Commit ccab69d6 by Corentin Wallez Committed by Commit Bot

Implement GL_OES_surfaceless_context

BUG=angleproject:1651 Change-Id: I733ccedad7c7424cdb70e21ef8d48b2a15ccdfd7 Reviewed-on: https://chromium-review.googlesource.com/434762Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
parent 3f6d4dff
...@@ -211,7 +211,8 @@ Extensions::Extensions() ...@@ -211,7 +211,8 @@ Extensions::Extensions()
multisampleCompatibility(false), multisampleCompatibility(false),
framebufferMixedSamples(false), framebufferMixedSamples(false),
textureNorm16(false), textureNorm16(false),
pathRendering(false) pathRendering(false),
surfacelessContext(false)
{ {
} }
...@@ -643,6 +644,7 @@ const ExtensionInfoMap &GetExtensionInfoMap() ...@@ -643,6 +644,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples); map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples);
map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16); map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16);
map["GL_CHROMIUM_path_rendering"] = esOnlyExtension(&Extensions::pathRendering); map["GL_CHROMIUM_path_rendering"] = esOnlyExtension(&Extensions::pathRendering);
map["GL_OES_surfaceless_context"] = esOnlyExtension(&Extensions::surfacelessContext);
// clang-format on // clang-format on
return map; return map;
......
...@@ -348,6 +348,9 @@ struct Extensions ...@@ -348,6 +348,9 @@ struct Extensions
// GL_CHROMIUM_path_rendering // GL_CHROMIUM_path_rendering
bool pathRendering; bool pathRendering;
// GL_OES_surfaceless_context
bool surfacelessContext;
}; };
struct ExtensionInfo struct ExtensionInfo
......
...@@ -258,7 +258,8 @@ Context::Context(rx::EGLImplFactory *implFactory, ...@@ -258,7 +258,8 @@ Context::Context(rx::EGLImplFactory *implFactory,
mContextLostForced(false), mContextLostForced(false),
mResetStrategy(GetResetStrategy(attribs)), mResetStrategy(GetResetStrategy(attribs)),
mRobustAccess(GetRobustAccess(attribs)), mRobustAccess(GetRobustAccess(attribs)),
mCurrentSurface(nullptr) mCurrentSurface(nullptr),
mSurfacelessFramebuffer(nullptr)
{ {
if (mRobustAccess) if (mRobustAccess)
{ {
...@@ -426,6 +427,8 @@ Context::~Context() ...@@ -426,6 +427,8 @@ Context::~Context()
} }
mZeroTextures.clear(); mZeroTextures.clear();
SafeDelete(mSurfacelessFramebuffer);
if (mCurrentSurface != nullptr) if (mCurrentSurface != nullptr)
{ {
releaseSurface(); releaseSurface();
...@@ -436,8 +439,6 @@ Context::~Context() ...@@ -436,8 +439,6 @@ Context::~Context()
void Context::makeCurrent(egl::Surface *surface) void Context::makeCurrent(egl::Surface *surface)
{ {
ASSERT(surface != nullptr);
if (!mHasBeenCurrent) if (!mHasBeenCurrent)
{ {
initRendererString(); initRendererString();
...@@ -457,13 +458,27 @@ void Context::makeCurrent(egl::Surface *surface) ...@@ -457,13 +458,27 @@ void Context::makeCurrent(egl::Surface *surface)
{ {
releaseSurface(); releaseSurface();
} }
surface->setIsCurrent(true);
mCurrentSurface = surface; Framebuffer *newDefault = nullptr;
if (surface != nullptr)
{
surface->setIsCurrent(true);
mCurrentSurface = surface;
newDefault = surface->getDefaultFramebuffer();
}
else
{
if (mSurfacelessFramebuffer == nullptr)
{
mSurfacelessFramebuffer = new Framebuffer(mImplementation.get());
}
newDefault = mSurfacelessFramebuffer;
}
// Update default framebuffer, the binding of the previous default // Update default framebuffer, the binding of the previous default
// framebuffer (or lack of) will have a nullptr. // framebuffer (or lack of) will have a nullptr.
{ {
Framebuffer *newDefault = surface->getDefaultFramebuffer();
if (mGLState.getReadFramebuffer() == nullptr) if (mGLState.getReadFramebuffer() == nullptr)
{ {
mGLState.setReadFramebufferBinding(newDefault); mGLState.setReadFramebufferBinding(newDefault);
...@@ -2436,6 +2451,9 @@ void Context::initCaps(bool webGLContext) ...@@ -2436,6 +2451,9 @@ void Context::initCaps(bool webGLContext)
// Enable the no error extension if the context was created with the flag. // Enable the no error extension if the context was created with the flag.
mExtensions.noError = mSkipValidation; mExtensions.noError = mSkipValidation;
// Enable surfaceless to advertise we'll have the correct behavior when there is no default FBO
mExtensions.surfacelessContext = true;
// Explicitly enable GL_KHR_debug // Explicitly enable GL_KHR_debug
mExtensions.debug = true; mExtensions.debug = true;
mExtensions.maxDebugMessageLength = 1024; mExtensions.maxDebugMessageLength = 1024;
......
...@@ -702,6 +702,7 @@ class Context final : public ValidationContext ...@@ -702,6 +702,7 @@ class Context final : public ValidationContext
GLenum mResetStrategy; GLenum mResetStrategy;
bool mRobustAccess; bool mRobustAccess;
egl::Surface *mCurrentSurface; egl::Surface *mCurrentSurface;
Framebuffer *mSurfacelessFramebuffer;
State::DirtyBits mTexImageDirtyBits; State::DirtyBits mTexImageDirtyBits;
State::DirtyObjects mTexImageDirtyObjects; State::DirtyObjects mTexImageDirtyObjects;
......
...@@ -242,12 +242,6 @@ size_t FramebufferState::getDrawBufferCount() const ...@@ -242,12 +242,6 @@ size_t FramebufferState::getDrawBufferCount() const
return mDrawBufferStates.size(); return mDrawBufferStates.size();
} }
Error Framebuffer::getSamplePosition(size_t index, GLfloat *xy) const
{
ANGLE_TRY(mImpl->getSamplePosition(index, xy));
return gl::NoError();
}
bool FramebufferState::colorAttachmentsAreUniqueImages() const bool FramebufferState::colorAttachmentsAreUniqueImages() const
{ {
for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size(); for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
...@@ -311,6 +305,18 @@ Framebuffer::Framebuffer(rx::SurfaceImpl *surface) ...@@ -311,6 +305,18 @@ Framebuffer::Framebuffer(rx::SurfaceImpl *surface)
ChannelBinding(this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0))); ChannelBinding(this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0)));
} }
Framebuffer::Framebuffer(rx::GLImplFactory *factory)
: mState(),
mImpl(factory->createFramebuffer(mState)),
mId(0),
mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
{
mDirtyColorAttachmentBindings.push_back(
ChannelBinding(this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0)));
}
Framebuffer::~Framebuffer() Framebuffer::~Framebuffer()
{ {
SafeDelete(mImpl); SafeDelete(mImpl);
...@@ -511,11 +517,15 @@ bool Framebuffer::usingExtendedDrawBuffers() const ...@@ -511,11 +517,15 @@ bool Framebuffer::usingExtendedDrawBuffers() const
GLenum Framebuffer::checkStatus(const ContextState &state) GLenum Framebuffer::checkStatus(const ContextState &state)
{ {
// The default framebuffer *must* always be complete, though it may not be // The default framebuffer is always complete except when it is surfaceless in which
// subject to the same rules as application FBOs. ie, it could have 0x0 size. // case it is always unsupported. We return early because the default framebuffer may
// not be subject to the same rules as application FBOs. ie, it could have 0x0 size.
if (mId == 0) if (mId == 0)
{ {
return GL_FRAMEBUFFER_COMPLETE; ASSERT(mCachedStatus.valid());
ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
mCachedStatus.value() == GL_FRAMEBUFFER_UNDEFINED_OES);
return mCachedStatus.value();
} }
if (hasAnyDirtyBit() || !mCachedStatus.valid()) if (hasAnyDirtyBit() || !mCachedStatus.valid())
...@@ -911,6 +921,12 @@ int Framebuffer::getSamples(const ContextState &state) ...@@ -911,6 +921,12 @@ int Framebuffer::getSamples(const ContextState &state)
return 0; return 0;
} }
Error Framebuffer::getSamplePosition(size_t index, GLfloat *xy) const
{
ANGLE_TRY(mImpl->getSamplePosition(index, xy));
return gl::NoError();
}
bool Framebuffer::hasValidDepthStencil() const bool Framebuffer::hasValidDepthStencil() const
{ {
return mState.getDepthStencilAttachment() != nullptr; return mState.getDepthStencilAttachment() != nullptr;
...@@ -991,7 +1007,10 @@ void Framebuffer::syncState() ...@@ -991,7 +1007,10 @@ void Framebuffer::syncState()
{ {
mImpl->syncState(mDirtyBits); mImpl->syncState(mDirtyBits);
mDirtyBits.reset(); mDirtyBits.reset();
mCachedStatus.reset(); if (mId != 0)
{
mCachedStatus.reset();
}
} }
} }
......
...@@ -99,8 +99,13 @@ class FramebufferState final : angle::NonCopyable ...@@ -99,8 +99,13 @@ class FramebufferState final : angle::NonCopyable
class Framebuffer final : public LabeledObject, public angle::SignalReceiver class Framebuffer final : public LabeledObject, public angle::SignalReceiver
{ {
public: public:
// Constructor to build application-defined framebuffers
Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id); Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id);
// Constructor to build default framebuffers for a surface
Framebuffer(rx::SurfaceImpl *surface); Framebuffer(rx::SurfaceImpl *surface);
// Constructor to build a fake default framebuffer when surfaceless
Framebuffer(rx::GLImplFactory *factory);
virtual ~Framebuffer(); virtual ~Framebuffer();
void setLabel(const std::string &label) override; void setLabel(const std::string &label) override;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment