Create a default framebuffer per surface/context pair on MakeCurrent.

Sharing a gl::Framebuffer object between multiple contexts causes problems if
contexts are not virtualized because the native framebuffer objects are not
shared between these contexts.  The FramebufferImpl created should be the glue
that binds a specific context to a specific surface.

Update the SurfaceImpl implementations to re-create the framebuffer
object before passing it to FramebufferGL.  No backing resources will be
re-created.

BUG=angleproject:2464

Change-Id: Id0b13a221c22b71517b25cb5b1ef2392ad2ecdd6
Reviewed-on: https://chromium-review.googlesource.com/1039985
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Frank Henigman <fjhenigman@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Geoff Lang 2018-05-01 16:48:21 -04:00 коммит произвёл Commit Bot
Родитель cbab27508e
Коммит bf7b95db6b
29 изменённых файлов: 246 добавлений и 242 удалений

Просмотреть файл

@ -291,7 +291,6 @@ Context::Context(rx::EGLImplFactory *implFactory,
mRobustAccess(GetRobustAccess(attribs)),
mCurrentSurface(static_cast<egl::Surface *>(EGL_NO_SURFACE)),
mCurrentDisplay(static_cast<egl::Display *>(EGL_NO_DISPLAY)),
mSurfacelessFramebuffer(nullptr),
mWebGLContext(GetWebGLContext(attribs)),
mExtensionsEnabled(GetExtensionsEnabled(attribs, mWebGLContext)),
mMemoryProgramCache(memoryProgramCache),
@ -445,12 +444,6 @@ egl::Error Context::onDestroy(const egl::Display *display)
}
// Delete the Surface first to trigger a finish() in Vulkan.
if (mSurfacelessFramebuffer)
{
mSurfacelessFramebuffer->onDestroy(this);
SafeDelete(mSurfacelessFramebuffer);
}
ANGLE_TRY(releaseSurface(display));
for (auto fence : mFenceNVMap)
@ -553,16 +546,11 @@ egl::Error Context::makeCurrent(egl::Display *display, egl::Surface *surface)
{
ANGLE_TRY(surface->setIsCurrent(this, true));
mCurrentSurface = surface;
newDefault = surface->getDefaultFramebuffer();
newDefault = surface->createDefaultFramebuffer(this);
}
else
{
if (mSurfacelessFramebuffer == nullptr)
{
mSurfacelessFramebuffer = new Framebuffer(mImplementation.get());
}
newDefault = mSurfacelessFramebuffer;
newDefault = new Framebuffer(mImplementation.get());
}
// Update default framebuffer, the binding of the previous default
@ -586,25 +574,25 @@ egl::Error Context::makeCurrent(egl::Display *display, egl::Surface *surface)
egl::Error Context::releaseSurface(const egl::Display *display)
{
// Remove the default framebuffer
Framebuffer *currentDefault = nullptr;
if (mCurrentSurface != nullptr)
{
currentDefault = mCurrentSurface->getDefaultFramebuffer();
}
else if (mSurfacelessFramebuffer != nullptr)
{
currentDefault = mSurfacelessFramebuffer;
}
gl::Framebuffer *defaultFramebuffer = mState.mFramebuffers->getFramebuffer(0);
if (mGLState.getReadFramebuffer() == currentDefault)
// Remove the default framebuffer
if (mGLState.getReadFramebuffer() == defaultFramebuffer)
{
mGLState.setReadFramebufferBinding(nullptr);
}
if (mGLState.getDrawFramebuffer() == currentDefault)
if (mGLState.getDrawFramebuffer() == defaultFramebuffer)
{
mGLState.setDrawFramebufferBinding(nullptr);
}
if (defaultFramebuffer)
{
defaultFramebuffer->onDestroy(this);
delete defaultFramebuffer;
}
mState.mFramebuffers->setDefaultFramebuffer(nullptr);
if (mCurrentSurface)

Просмотреть файл

@ -1577,7 +1577,6 @@ class Context final : angle::NonCopyable
bool mRobustAccess;
egl::Surface *mCurrentSurface;
egl::Display *mCurrentDisplay;
Framebuffer *mSurfacelessFramebuffer;
bool mWebGLContext;
bool mExtensionsEnabled;
MemoryProgramCache *mMemoryProgramCache;

Просмотреть файл

@ -632,9 +632,9 @@ Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id
}
}
Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface)
Framebuffer::Framebuffer(const Context *context, egl::Surface *surface)
: mState(),
mImpl(surface->getImplementation()->createDefaultFramebuffer(mState)),
mImpl(surface->getImplementation()->createDefaultFramebuffer(context, mState)),
mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
@ -642,9 +642,7 @@ Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface)
ASSERT(mImpl != nullptr);
mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
const Context *proxyContext = display->getProxyContext();
setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), surface,
setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), surface,
FramebufferAttachment::kDefaultNumViews,
FramebufferAttachment::kDefaultBaseViewIndex,
FramebufferAttachment::kDefaultMultiviewLayout,
@ -652,7 +650,7 @@ Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface)
if (surface->getConfig()->depthSize > 0)
{
setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex(), surface,
setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex(), surface,
FramebufferAttachment::kDefaultNumViews,
FramebufferAttachment::kDefaultBaseViewIndex,
FramebufferAttachment::kDefaultMultiviewLayout,
@ -661,7 +659,7 @@ Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface)
if (surface->getConfig()->stencilSize > 0)
{
setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex(), surface,
setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex(), surface,
FramebufferAttachment::kDefaultNumViews,
FramebufferAttachment::kDefaultBaseViewIndex,
FramebufferAttachment::kDefaultMultiviewLayout,

Просмотреть файл

@ -142,8 +142,8 @@ class Framebuffer final : public angle::ObserverInterface, public LabeledObject
public:
// Constructor to build application-defined framebuffers
Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id);
// Constructor to build default framebuffers for a surface
Framebuffer(const egl::Display *display, egl::Surface *surface);
// Constructor to build default framebuffers for a surface and context pair
Framebuffer(const Context *context, egl::Surface *surface);
// Constructor to build a fake default framebuffer when surfaceless
Framebuffer(rx::GLImplFactory *factory);

Просмотреть файл

@ -423,14 +423,10 @@ Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
// static
void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer)
{
// Default framebuffer are owned by their respective Surface
if (framebuffer->id() != 0)
{
framebuffer->onDestroy(context);
delete framebuffer;
}
}
GLuint FramebufferManager::createFramebuffer()
{

Просмотреть файл

@ -25,7 +25,7 @@ namespace egl
{
SurfaceState::SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn)
: defaultFramebuffer(nullptr), config(configIn), attributes(attributesIn)
: config(configIn), attributes(attributesIn)
{
}
@ -117,10 +117,6 @@ rx::FramebufferAttachmentObjectImpl *Surface::getAttachmentImpl() const
Error Surface::destroyImpl(const Display *display)
{
if (mState.defaultFramebuffer)
{
mState.defaultFramebuffer->onDestroy(display->getProxyContext());
}
if (mImplementation)
{
mImplementation->destroy(display);
@ -128,24 +124,19 @@ Error Surface::destroyImpl(const Display *display)
if (mTexture.get())
{
gl::Context *context = display->getProxyContext();
if (mImplementation)
{
ANGLE_TRY(
mImplementation->releaseTexImage(display->getProxyContext(), EGL_BACK_BUFFER));
ANGLE_TRY(mImplementation->releaseTexImage(context, EGL_BACK_BUFFER));
}
auto glErr = mTexture->releaseTexImageFromSurface(display->getProxyContext());
auto glErr = mTexture->releaseTexImageFromSurface(context);
if (glErr.isError())
{
return Error(EGL_BAD_SURFACE);
}
mTexture.set(display->getProxyContext(), nullptr);
mTexture.set(context, nullptr);
}
if (mState.defaultFramebuffer)
{
mState.defaultFramebuffer->onDestroy(display->getProxyContext());
}
SafeDelete(mState.defaultFramebuffer);
SafeDelete(mImplementation);
delete this;
@ -169,10 +160,6 @@ Error Surface::initialize(const Display *display)
// Must happen after implementation initialize for Android.
mSwapBehavior = mImplementation->getSwapBehavior();
// Must happen after implementation initialize for OSX.
mState.defaultFramebuffer = createDefaultFramebuffer(display);
ASSERT(mState.defaultFramebuffer != nullptr);
if (mBuftype == EGL_IOSURFACE_ANGLE)
{
GLenum internalFormat =
@ -452,9 +439,9 @@ GLuint Surface::getId() const
return 0;
}
gl::Framebuffer *Surface::createDefaultFramebuffer(const Display *display)
gl::Framebuffer *Surface::createDefaultFramebuffer(const gl::Context *context)
{
return new gl::Framebuffer(display, this);
return new gl::Framebuffer(context, this);
}
gl::InitState Surface::initState(const gl::ImageIndex & /*imageIndex*/) const

Просмотреть файл

@ -24,6 +24,7 @@
namespace gl
{
class Context;
class Framebuffer;
class Texture;
}
@ -42,7 +43,6 @@ struct SurfaceState final : private angle::NonCopyable
{
SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn);
gl::Framebuffer *defaultFramebuffer;
const egl::Config *config;
AttributeMap attributes;
};
@ -79,6 +79,8 @@ class Surface : public gl::FramebufferAttachmentObject
void setMultisampleResolve(EGLenum resolve);
void setSwapBehavior(EGLenum behavior);
gl::Framebuffer *createDefaultFramebuffer(const gl::Context *context);
const Config *getConfig() const;
// width and height can change with client window resizing
@ -100,7 +102,6 @@ class Surface : public gl::FramebufferAttachmentObject
EGLenum getMultisampleResolve() const;
gl::Texture *getBoundTexture() const { return mTexture.get(); }
gl::Framebuffer *getDefaultFramebuffer() { return mState.defaultFramebuffer; }
EGLint isFixedSize() const;

Просмотреть файл

@ -30,7 +30,8 @@ class MockSurfaceImpl : public rx::SurfaceImpl
MOCK_METHOD1(destroy, void(const egl::Display *));
MOCK_METHOD1(initialize, egl::Error(const egl::Display *));
MOCK_METHOD1(createDefaultFramebuffer, rx::FramebufferImpl *(const gl::FramebufferState &data));
MOCK_METHOD2(createDefaultFramebuffer,
rx::FramebufferImpl *(const gl::Context *, const gl::FramebufferState &data));
MOCK_METHOD1(swap, egl::Error(const gl::Context *));
MOCK_METHOD3(swapWithDamage, egl::Error(const gl::Context *, EGLint *, EGLint));
MOCK_METHOD5(postSubBuffer, egl::Error(const gl::Context *, EGLint, EGLint, EGLint, EGLint));

Просмотреть файл

@ -24,6 +24,7 @@ struct Format;
namespace gl
{
class Context;
class FramebufferState;
}
@ -47,7 +48,8 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl
virtual void destroy(const egl::Display *display) {}
virtual egl::Error initialize(const egl::Display *display) = 0;
virtual FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) = 0;
virtual FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state) = 0;
virtual egl::Error swap(const gl::Context *context) = 0;
virtual egl::Error swapWithDamage(const gl::Context *context, EGLint *rects, EGLint n_rects);
virtual egl::Error postSubBuffer(const gl::Context *context,

Просмотреть файл

@ -132,7 +132,8 @@ egl::Error SurfaceD3D::initialize(const egl::Display *display)
return egl::NoError();
}
FramebufferImpl *SurfaceD3D::createDefaultFramebuffer(const gl::FramebufferState &data)
FramebufferImpl *SurfaceD3D::createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &data)
{
return mRenderer->createDefaultFramebuffer(data);
}

Просмотреть файл

@ -29,7 +29,8 @@ class SurfaceD3D : public SurfaceImpl
void releaseSwapChain();
egl::Error initialize(const egl::Display *display) override;
FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state) override;
egl::Error swap(const gl::Context *context) override;
egl::Error postSubBuffer(const gl::Context *context,

Просмотреть файл

@ -26,7 +26,8 @@ SurfaceGL::~SurfaceGL()
{
}
FramebufferImpl *SurfaceGL::createDefaultFramebuffer(const gl::FramebufferState &data)
FramebufferImpl *SurfaceGL::createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &data)
{
return new FramebufferGL(data, 0, true);
}

Просмотреть файл

@ -20,7 +20,8 @@ class SurfaceGL : public SurfaceImpl
SurfaceGL(const egl::SurfaceState &state);
~SurfaceGL() override;
FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override;
FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &data) override;
egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
gl::Error initializeContents(const gl::Context *context,

Просмотреть файл

@ -52,7 +52,8 @@ class PbufferSurfaceCGL : public SurfaceGL
EGLint isPostSubBufferSupported() const override;
EGLint getSwapBehavior() const override;
FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state) override;
private:
unsigned mWidth;
@ -63,7 +64,6 @@ class PbufferSurfaceCGL : public SurfaceGL
const FunctionsGL *mFunctions;
StateManagerGL *mStateManager;
GLuint mFramebuffer;
GLuint mColorRenderbuffer;
GLuint mDSRenderbuffer;
};

Просмотреть файл

@ -28,7 +28,6 @@ PbufferSurfaceCGL::PbufferSurfaceCGL(const egl::SurfaceState &state,
mHeight(height),
mFunctions(functions),
mStateManager(renderer->getStateManager()),
mFramebuffer(0),
mColorRenderbuffer(0),
mDSRenderbuffer(0)
{
@ -36,12 +35,6 @@ PbufferSurfaceCGL::PbufferSurfaceCGL(const egl::SurfaceState &state,
PbufferSurfaceCGL::~PbufferSurfaceCGL()
{
if (mFramebuffer != 0)
{
mFunctions->deleteFramebuffers(1, &mFramebuffer);
mFramebuffer = 0;
}
if (mColorRenderbuffer != 0)
{
mFunctions->deleteRenderbuffers(1, &mColorRenderbuffer);
@ -64,13 +57,6 @@ egl::Error PbufferSurfaceCGL::initialize(const egl::Display *display)
mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer);
mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mWidth, mHeight);
mFunctions->genFramebuffers(1, &mFramebuffer);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
mColorRenderbuffer);
mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, mDSRenderbuffer);
return egl::NoError();
}
@ -138,10 +124,21 @@ EGLint PbufferSurfaceCGL::getSwapBehavior() const
return EGL_BUFFER_PRESERVED;
}
FramebufferImpl *PbufferSurfaceCGL::createDefaultFramebuffer(const gl::FramebufferState &state)
FramebufferImpl *PbufferSurfaceCGL::createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state)
{
// TODO(cwallez) assert it happens only once?
return new FramebufferGL(state, mFramebuffer, true);
const FunctionsGL *functions = GetFunctionsGL(context);
StateManagerGL *stateManager = GetStateManagerGL(context);
GLuint framebuffer = 0;
functions->genFramebuffers(1, &framebuffer);
stateManager->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
mColorRenderbuffer);
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
mDSRenderbuffer);
return new FramebufferGL(state, framebuffer, true);
}
} // namespace rx

Просмотреть файл

@ -84,7 +84,8 @@ class WindowSurfaceCGL : public SurfaceGL
EGLint isPostSubBufferSupported() const override;
EGLint getSwapBehavior() const override;
FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state) override;
private:
SwapLayer *mSwapLayer;
@ -96,7 +97,6 @@ class WindowSurfaceCGL : public SurfaceGL
const FunctionsGL *mFunctions;
StateManagerGL *mStateManager;
GLuint mFramebuffer;
GLuint mDSRenderbuffer;
};

Просмотреть файл

@ -13,10 +13,11 @@
#import <QuartzCore/QuartzCore.h>
#include "common/debug.h"
#include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/gl/FramebufferGL.h"
#include "libANGLE/renderer/gl/RendererGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
@interface SwapLayer : CAOpenGLLayer
{
@ -154,7 +155,6 @@
mContext(context),
mFunctions(functions),
mStateManager(renderer->getStateManager()),
mFramebuffer(0),
mDSRenderbuffer(0)
{
pthread_mutex_init(&mSwapState.mutex, nullptr);
@ -163,11 +163,6 @@
WindowSurfaceCGL::~WindowSurfaceCGL()
{
pthread_mutex_destroy(&mSwapState.mutex);
if (mFramebuffer != 0)
{
mFunctions->deleteFramebuffers(1, &mFramebuffer);
mFramebuffer = 0;
}
if (mDSRenderbuffer != 0)
{
@ -220,13 +215,6 @@ egl::Error WindowSurfaceCGL::initialize(const egl::Display *display)
mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer);
mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
mFunctions->genFramebuffers(1, &mFramebuffer);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
mSwapState.beingRendered->texture, 0);
mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
mDSRenderbuffer);
return egl::Error(EGL_SUCCESS);
}
@ -237,7 +225,10 @@ egl::Error WindowSurfaceCGL::makeCurrent()
egl::Error WindowSurfaceCGL::swap(const gl::Context *context)
{
mFunctions->flush();
const FunctionsGL *functions = GetFunctionsGL(context);
StateManagerGL *stateManager = GetStateManagerGL(context);
functions->flush();
mSwapState.beingRendered->swapId = ++mCurrentSwapId;
pthread_mutex_lock(&mSwapState.mutex);
@ -252,19 +243,20 @@ egl::Error WindowSurfaceCGL::swap(const gl::Context *context)
if (texture.width != width || texture.height != height)
{
mStateManager->bindTexture(gl::TextureType::_2D, texture.texture);
mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
stateManager->bindTexture(gl::TextureType::_2D, texture.texture);
functions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, nullptr);
mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer);
mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
stateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer);
functions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
texture.width = width;
texture.height = height;
}
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(context->getFramebuffer(0));
stateManager->bindFramebuffer(GL_FRAMEBUFFER, framebufferGL->getFramebufferID());
functions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
mSwapState.beingRendered->texture, 0);
return egl::Error(EGL_SUCCESS);
@ -326,10 +318,21 @@ EGLint WindowSurfaceCGL::getSwapBehavior() const
return EGL_BUFFER_DESTROYED;
}
FramebufferImpl *WindowSurfaceCGL::createDefaultFramebuffer(const gl::FramebufferState &state)
FramebufferImpl *WindowSurfaceCGL::createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state)
{
// TODO(cwallez) assert it happens only once?
return new FramebufferGL(state, mFramebuffer, true);
const FunctionsGL *functions = GetFunctionsGL(context);
StateManagerGL *stateManager = GetStateManagerGL(context);
GLuint framebuffer = 0;
functions->genFramebuffers(1, &framebuffer);
stateManager->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
functions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
mSwapState.beingRendered->texture, 0);
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
mDSRenderbuffer);
return new FramebufferGL(state, framebuffer, true);
}
} // namespace rx

Просмотреть файл

@ -113,15 +113,19 @@ DisplayOzone::Buffer::Buffer(DisplayOzone *display,
mImage(EGL_NO_IMAGE_KHR),
mColorBuffer(0),
mDSBuffer(0),
mGLFB(0),
mTexture(0)
{
}
DisplayOzone::Buffer::~Buffer()
{
mDisplay->mFunctionsGL->deleteFramebuffers(1, &mGLFB);
reset();
FunctionsGL *gl = mDisplay->mFunctionsGL;
gl->deleteRenderbuffers(1, &mColorBuffer);
mColorBuffer = 0;
gl->deleteRenderbuffers(1, &mDSBuffer);
mDSBuffer = 0;
}
void DisplayOzone::Buffer::reset()
@ -133,15 +137,8 @@ void DisplayOzone::Buffer::reset()
mHasDRMFB = false;
}
FunctionsGL *gl = mDisplay->mFunctionsGL;
gl->deleteRenderbuffers(1, &mColorBuffer);
mColorBuffer = 0;
gl->deleteRenderbuffers(1, &mDSBuffer);
mDSBuffer = 0;
// Here we might destroy the GL framebuffer (mGLFB) but unlike every other resource in Buffer,
// it does not get destroyed (and recreated) because when it is the default framebuffer for
// an ANGLE surface then ANGLE expects it to have the same lifetime as that surface.
// Make sure to keep the color and depth stencil buffers alive so they maintain the same GL IDs
// if they are bound to any emulated default framebuffer.
if (mImage != EGL_NO_IMAGE_KHR)
{
@ -151,6 +148,7 @@ void DisplayOzone::Buffer::reset()
if (mTexture)
{
FunctionsGL *gl = mDisplay->mFunctionsGL;
gl->deleteTextures(1, &mTexture);
mTexture = 0;
}
@ -216,33 +214,17 @@ bool DisplayOzone::Buffer::resize(int32_t width, int32_t height)
FunctionsGL *gl = mDisplay->mFunctionsGL;
StateManagerGL *sm = mDisplay->getRenderer()->getStateManager();
gl->genRenderbuffers(1, &mColorBuffer);
// Update the storage of the renderbuffers but don't generate new IDs. This will update all
// framebuffers they are bound to.
sm->bindRenderbuffer(GL_RENDERBUFFER, mColorBuffer);
gl->eGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mImage);
sm->bindFramebuffer(GL_FRAMEBUFFER, mGLFB);
gl->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER,
mColorBuffer);
if (mDepthBits || mStencilBits)
{
gl->genRenderbuffers(1, &mDSBuffer);
sm->bindRenderbuffer(GL_RENDERBUFFER, mDSBuffer);
gl->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height);
}
if (mDepthBits)
{
gl->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
mDSBuffer);
}
if (mStencilBits)
{
gl->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
mDSBuffer);
}
mWidth = width;
mHeight = height;
return true;
@ -251,14 +233,12 @@ bool DisplayOzone::Buffer::resize(int32_t width, int32_t height)
bool DisplayOzone::Buffer::initialize(const NativeWindow *native)
{
mNative = native;
mDisplay->mFunctionsGL->genFramebuffers(1, &mGLFB);
return resize(native->width, native->height);
return createRenderbuffers() && resize(native->width, native->height);
}
bool DisplayOzone::Buffer::initialize(int width, int height)
{
mDisplay->mFunctionsGL->genFramebuffers(1, &mGLFB);
return resize(width, height);
return createRenderbuffers() && resize(width, height);
}
void DisplayOzone::Buffer::bindTexImage()
@ -305,29 +285,70 @@ uint32_t DisplayOzone::Buffer::getDRMFB()
return mDRMFB;
}
FramebufferGL *DisplayOzone::Buffer::framebufferGL(const gl::FramebufferState &state)
GLuint DisplayOzone::Buffer::createGLFB(const gl::Context *context)
{
return new FramebufferGL(state, mGLFB, true);
const FunctionsGL *functions = GetFunctionsGL(context);
StateManagerGL *stateManager = GetStateManagerGL(context);
GLuint framebuffer = 0;
functions->genFramebuffers(1, &framebuffer);
stateManager->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER,
mColorBuffer);
if (mDepthBits)
{
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
mDSBuffer);
}
void DisplayOzone::Buffer::present()
if (mStencilBits)
{
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
mDSBuffer);
}
return framebuffer;
}
FramebufferGL *DisplayOzone::Buffer::framebufferGL(const gl::Context *context,
const gl::FramebufferState &state)
{
return new FramebufferGL(state, createGLFB(context), true);
}
void DisplayOzone::Buffer::present(const gl::Context *context)
{
if (mNative)
{
if (mNative->visible)
{
mDisplay->drawBuffer(this);
mDisplay->drawBuffer(context, this);
}
resize(mNative->width, mNative->height);
}
}
bool DisplayOzone::Buffer::createRenderbuffers()
{
FunctionsGL *gl = mDisplay->mFunctionsGL;
StateManagerGL *sm = mDisplay->getRenderer()->getStateManager();
gl->genRenderbuffers(1, &mColorBuffer);
sm->bindRenderbuffer(GL_RENDERBUFFER, mColorBuffer);
if (mDepthBits || mStencilBits)
{
gl->genRenderbuffers(1, &mDSBuffer);
sm->bindRenderbuffer(GL_RENDERBUFFER, mDSBuffer);
}
return true;
}
DisplayOzone::DisplayOzone(const egl::DisplayState &state)
: DisplayEGL(state),
mSwapControl(SwapControl::ABSENT),
mMinSwapInterval(0),
mMaxSwapInterval(0),
mCurrentSwapInterval(-1),
mGBM(nullptr),
mConnector(nullptr),
mMode(nullptr),
@ -603,7 +624,7 @@ GLuint DisplayOzone::makeShader(GLuint type, const char *src)
return shader;
}
void DisplayOzone::drawWithTexture(Buffer *buffer)
void DisplayOzone::drawWithTexture(const gl::Context *context, Buffer *buffer)
{
FunctionsGL *gl = mFunctionsGL;
StateManagerGL *sm = getRenderer()->getStateManager();
@ -727,13 +748,15 @@ void DisplayOzone::drawWithTexture(Buffer *buffer)
sm->bindTexture(gl::TextureType::_2D, tex);
gl->vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
gl->enableVertexAttribArray(0);
sm->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawing->getGLFB());
GLuint fbo = mDrawing->createGLFB(context);
sm->bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
gl->drawArrays(GL_TRIANGLE_STRIP, 0, 4);
gl->drawElements(GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, 0);
sm->deleteTexture(tex);
sm->deleteFramebuffer(fbo);
}
void DisplayOzone::drawBuffer(Buffer *buffer)
void DisplayOzone::drawBuffer(const gl::Context *context, Buffer *buffer)
{
if (!mDrawing)
{
@ -755,16 +778,19 @@ void DisplayOzone::drawBuffer(Buffer *buffer)
}
StateManagerGL *sm = getRenderer()->getStateManager();
sm->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawing->getGLFB());
GLuint fbo = mDrawing->createGLFB(context);
sm->bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
sm->setClearColor(gl::ColorF(0, 0, 0, 1));
sm->setClearDepth(1);
sm->setScissorTestEnabled(false);
sm->setColorMask(true, true, true, true);
sm->setDepthMask(true);
mFunctionsGL->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
sm->deleteFramebuffer(fbo);
}
drawWithTexture(buffer);
drawWithTexture(context, buffer);
presentScreen();
}

Просмотреть файл

@ -75,17 +75,19 @@ class DisplayOzone final : public DisplayEGL
bool initialize(int32_t width, int32_t height);
void reset();
bool resize(int32_t width, int32_t height);
FramebufferGL *framebufferGL(const gl::FramebufferState &state);
void present();
GLuint createGLFB(const gl::Context *context);
FramebufferGL *framebufferGL(const gl::Context *context, const gl::FramebufferState &state);
void present(const gl::Context *context);
uint32_t getDRMFB();
void bindTexImage();
GLuint getTexture();
int32_t getWidth() const { return mWidth; }
int32_t getHeight() const { return mHeight; }
GLuint getGLFB() const { return mGLFB; }
const NativeWindow *getNative() const { return mNative; }
private:
bool createRenderbuffers();
DisplayOzone *mDisplay;
const NativeWindow *mNative;
int mWidth;
@ -103,7 +105,6 @@ class DisplayOzone final : public DisplayEGL
EGLImageKHR mImage;
GLuint mColorBuffer;
GLuint mDSBuffer;
GLuint mGLFB;
GLuint mTexture;
};
@ -148,9 +149,8 @@ class DisplayOzone final : public DisplayEGL
egl::Error makeCurrentSurfaceless(gl::Context *context) override;
GLuint makeShader(GLuint type, const char *src);
void drawBuffer(Buffer *buffer);
void drawWithBlit(Buffer *buffer);
void drawWithTexture(Buffer *buffer);
void drawBuffer(const gl::Context *context, Buffer *buffer);
void drawWithTexture(const gl::Context *context, Buffer *buffer);
void flushGL();
bool hasUsableScreen(int fd);
void presentScreen();
@ -161,19 +161,6 @@ class DisplayOzone final : public DisplayEGL
void *data);
void pageFlipHandler(unsigned int sequence, uint64_t tv);
// TODO(fjhenigman) Implement swap control. The following stuff will be used for that.
enum class SwapControl
{
ABSENT,
EXT,
MESA,
SGI,
};
SwapControl mSwapControl;
int mMinSwapInterval;
int mMaxSwapInterval;
int mCurrentSwapInterval;
gbm_device *mGBM;
drmModeConnectorPtr mConnector;
drmModeModeInfoPtr mMode;

Просмотреть файл

@ -29,9 +29,10 @@ egl::Error SurfaceOzone::initialize(const egl::Display *display)
return egl::NoError();
}
FramebufferImpl *SurfaceOzone::createDefaultFramebuffer(const gl::FramebufferState &state)
FramebufferImpl *SurfaceOzone::createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state)
{
return mBuffer->framebufferGL(state);
return mBuffer->framebufferGL(context, state);
}
egl::Error SurfaceOzone::makeCurrent()
@ -41,7 +42,7 @@ egl::Error SurfaceOzone::makeCurrent()
egl::Error SurfaceOzone::swap(const gl::Context *context)
{
mBuffer->present();
mBuffer->present(context);
return egl::NoError();
}

Просмотреть файл

@ -22,7 +22,8 @@ class SurfaceOzone : public SurfaceGL
DisplayOzone::Buffer *buffer);
~SurfaceOzone() override;
FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state) override;
egl::Error initialize(const egl::Display *display) override;
egl::Error makeCurrent() override;

Просмотреть файл

@ -256,8 +256,7 @@ D3DTextureSurfaceWGL::D3DTextureSurfaceWGL(const egl::SurfaceState &state,
mBoundObjectTextureHandle(nullptr),
mBoundObjectRenderbufferHandle(nullptr),
mColorRenderbufferID(0),
mDepthStencilRenderbufferID(0),
mFramebufferID(0)
mDepthStencilRenderbufferID(0)
{
}
@ -284,9 +283,6 @@ D3DTextureSurfaceWGL::~D3DTextureSurfaceWGL()
mBoundObjectTextureHandle = nullptr;
}
// GL framebuffer is deleted by the default framebuffer object
mFramebufferID = 0;
mDisplay->releaseD3DDevice(mDeviceHandle);
mDeviceHandle = nullptr;
}
@ -350,21 +346,6 @@ egl::Error D3DTextureSurfaceWGL::initialize(const egl::Display *display)
static_cast<GLsizei>(mHeight));
}
mFunctionsGL->genFramebuffers(1, &mFramebufferID);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
mColorRenderbufferID);
if (config->depthSize > 0)
{
mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
mDepthStencilRenderbufferID);
}
if (config->stencilSize > 0)
{
mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, mDepthStencilRenderbufferID);
}
return egl::NoError();
}
@ -496,9 +477,29 @@ EGLint D3DTextureSurfaceWGL::getSwapBehavior() const
return EGL_BUFFER_PRESERVED;
}
FramebufferImpl *D3DTextureSurfaceWGL::createDefaultFramebuffer(const gl::FramebufferState &data)
FramebufferImpl *D3DTextureSurfaceWGL::createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &data)
{
return new FramebufferGL(data, mFramebufferID, true);
const FunctionsGL *functions = GetFunctionsGL(context);
StateManagerGL *stateManager = GetStateManagerGL(context);
GLuint framebufferID = 0;
functions->genFramebuffers(1, &framebufferID);
stateManager->bindFramebuffer(GL_FRAMEBUFFER, framebufferID);
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
mColorRenderbufferID);
if (mState.config->depthSize > 0)
{
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
mDepthStencilRenderbufferID);
}
if (mState.config->stencilSize > 0)
{
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
mDepthStencilRenderbufferID);
}
return new FramebufferGL(data, framebufferID, true);
}
HDC D3DTextureSurfaceWGL::getDC() const

Просмотреть файл

@ -63,7 +63,8 @@ class D3DTextureSurfaceWGL : public SurfaceWGL
EGLint isPostSubBufferSupported() const override;
EGLint getSwapBehavior() const override;
FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override;
FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &data) override;
HDC getDC() const override;
@ -95,7 +96,6 @@ class D3DTextureSurfaceWGL : public SurfaceWGL
GLuint mColorRenderbufferID;
GLuint mDepthStencilRenderbufferID;
GLuint mFramebufferID;
};
} // namespace rx

Просмотреть файл

@ -48,7 +48,6 @@ DXGISwapChainWindowSurfaceWGL::DXGISwapChainWindowSurfaceWGL(const egl::SurfaceS
mColorRenderbufferID(0),
mRenderbufferBufferHandle(nullptr),
mDepthRenderbufferID(0),
mFramebufferID(0),
mTextureID(0),
mTextureHandle(nullptr),
mWidth(0),
@ -105,9 +104,11 @@ egl::Error DXGISwapChainWindowSurfaceWGL::initialize(const egl::Display *display
mSwapChainFlags = 0;
mDepthBufferFormat = GL_DEPTH24_STENCIL8;
mFunctionsGL->genFramebuffers(1, &mFramebufferID);
mFunctionsGL->genRenderbuffers(1, &mColorRenderbufferID);
mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mColorRenderbufferID);
mFunctionsGL->genRenderbuffers(1, &mDepthRenderbufferID);
mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbufferID);
return createSwapChain();
}
@ -268,9 +269,34 @@ EGLint DXGISwapChainWindowSurfaceWGL::getSwapBehavior() const
}
FramebufferImpl *DXGISwapChainWindowSurfaceWGL::createDefaultFramebuffer(
const gl::Context *context,
const gl::FramebufferState &data)
{
return new FramebufferGL(data, mFramebufferID, true);
const FunctionsGL *functions = GetFunctionsGL(context);
StateManagerGL *stateManager = GetStateManagerGL(context);
GLuint framebufferID = 0;
stateManager->bindFramebuffer(GL_FRAMEBUFFER, framebufferID);
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
mColorRenderbufferID);
if (mDepthBufferFormat != GL_NONE)
{
const gl::InternalFormat &depthStencilFormatInfo =
gl::GetSizedInternalFormatInfo(mDepthBufferFormat);
if (depthStencilFormatInfo.depthBits > 0)
{
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
mDepthRenderbufferID);
}
if (depthStencilFormatInfo.stencilBits > 0)
{
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, mDepthRenderbufferID);
}
}
return new FramebufferGL(data, framebufferID, true);
}
HDC DXGISwapChainWindowSurfaceWGL::getDC() const
@ -470,7 +496,6 @@ egl::Error DXGISwapChainWindowSurfaceWGL::createSwapChain()
<< gl::FmtHR(result);
}
mFunctionsGL->genRenderbuffers(1, &mColorRenderbufferID);
mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mColorRenderbufferID);
mRenderbufferBufferHandle =
mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, mColorRenderbufferID,
@ -500,11 +525,6 @@ egl::Error DXGISwapChainWindowSurfaceWGL::createSwapChain()
return error;
}
ASSERT(mFramebufferID != 0);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
mColorRenderbufferID);
if (mDepthBufferFormat != GL_NONE)
{
ASSERT(mDepthRenderbufferID != 0);
@ -512,19 +532,6 @@ egl::Error DXGISwapChainWindowSurfaceWGL::createSwapChain()
mFunctionsGL->renderbufferStorage(GL_RENDERBUFFER, mDepthBufferFormat,
static_cast<GLsizei>(mWidth),
static_cast<GLsizei>(mHeight));
const gl::InternalFormat &depthStencilFormatInfo =
gl::GetSizedInternalFormatInfo(mDepthBufferFormat);
if (depthStencilFormatInfo.depthBits > 0)
{
mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, mDepthRenderbufferID);
}
if (depthStencilFormatInfo.stencilBits > 0)
{
mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, mDepthRenderbufferID);
}
}
mFirstSwap = true;

Просмотреть файл

@ -59,7 +59,8 @@ class DXGISwapChainWindowSurfaceWGL : public SurfaceWGL
EGLint isPostSubBufferSupported() const override;
EGLint getSwapBehavior() const override;
FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override;
FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &data) override;
HDC getDC() const override;
@ -93,8 +94,6 @@ class DXGISwapChainWindowSurfaceWGL : public SurfaceWGL
GLuint mDepthRenderbufferID;
GLuint mFramebufferID;
GLuint mTextureID;
HANDLE mTextureHandle;

Просмотреть файл

@ -29,7 +29,8 @@ egl::Error SurfaceNULL::initialize(const egl::Display *display)
return egl::NoError();
}
FramebufferImpl *SurfaceNULL::createDefaultFramebuffer(const gl::FramebufferState &state)
FramebufferImpl *SurfaceNULL::createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state)
{
return new FramebufferNULL(state);
}

Просмотреть файл

@ -22,7 +22,8 @@ class SurfaceNULL : public SurfaceImpl
~SurfaceNULL() override;
egl::Error initialize(const egl::Display *display) override;
FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state) override;
egl::Error swap(const gl::Context *context) override;
egl::Error postSubBuffer(const gl::Context *context,
EGLint x,

Просмотреть файл

@ -66,7 +66,8 @@ egl::Error OffscreenSurfaceVk::initialize(const egl::Display *display)
return egl::NoError();
}
FramebufferImpl *OffscreenSurfaceVk::createDefaultFramebuffer(const gl::FramebufferState &state)
FramebufferImpl *OffscreenSurfaceVk::createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state)
{
// Use a user FBO for an offscreen RT.
return FramebufferVk::CreateUserFBO(state);
@ -442,7 +443,8 @@ vk::Error WindowSurfaceVk::initializeImpl(RendererVk *renderer)
return vk::NoError();
}
FramebufferImpl *WindowSurfaceVk::createDefaultFramebuffer(const gl::FramebufferState &state)
FramebufferImpl *WindowSurfaceVk::createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state)
{
return FramebufferVk::CreateDefaultFBO(state, this);
}

Просмотреть файл

@ -27,7 +27,8 @@ class OffscreenSurfaceVk : public SurfaceImpl
~OffscreenSurfaceVk() override;
egl::Error initialize(const egl::Display *display) override;
FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state) override;
egl::Error swap(const gl::Context *context) override;
egl::Error postSubBuffer(const gl::Context *context,
EGLint x,
@ -74,7 +75,8 @@ class WindowSurfaceVk : public SurfaceImpl, public vk::CommandGraphResource
void destroy(const egl::Display *display) override;
egl::Error initialize(const egl::Display *display) override;
FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state) override;
egl::Error swap(const gl::Context *context) override;
egl::Error postSubBuffer(const gl::Context *context,
EGLint x,