Commit ea24f446 by Jamie Madill

Release egl::Surface on Texture image changes.

We would get into a broken state if the user would bind a Texture to an egl::Surface, then change the Texture. This is valid in egl, and should release the Surface when it happens. BUG=485543 Change-Id: Idfaa305ac704f2bc579e79be816e88a23e69351b Reviewed-on: https://chromium-review.googlesource.com/271986Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/280906
parent 99f075da
...@@ -33,8 +33,7 @@ Surface::Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *c ...@@ -33,8 +33,7 @@ Surface::Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *c
// FIXME: Determine actual pixel aspect ratio // FIXME: Determine actual pixel aspect ratio
mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)), mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
mRenderBuffer(EGL_BACK_BUFFER), mRenderBuffer(EGL_BACK_BUFFER),
mSwapBehavior(EGL_BUFFER_PRESERVED), mSwapBehavior(EGL_BUFFER_PRESERVED)
mTexture(NULL)
{ {
addRef(); addRef();
...@@ -56,14 +55,14 @@ Surface::Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *c ...@@ -56,14 +55,14 @@ Surface::Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *c
Surface::~Surface() Surface::~Surface()
{ {
if (mTexture) if (mTexture.get())
{ {
if (mImplementation) if (mImplementation)
{ {
mImplementation->releaseTexImage(mTexture->id()); mImplementation->releaseTexImage(mTexture->id());
} }
mTexture->releaseTexImage(); mTexture->releaseTexImageFromSurface();
mTexture = NULL; mTexture.set(nullptr);
} }
SafeDelete(mImplementation); SafeDelete(mImplementation);
...@@ -146,21 +145,26 @@ EGLint Surface::getHeight() const ...@@ -146,21 +145,26 @@ EGLint Surface::getHeight() const
Error Surface::bindTexImage(gl::Texture *texture, EGLint buffer) Error Surface::bindTexImage(gl::Texture *texture, EGLint buffer)
{ {
ASSERT(!mTexture); ASSERT(!mTexture.get());
texture->bindTexImage(this); texture->bindTexImageFromSurface(this);
mTexture = texture; mTexture.set(texture);
return mImplementation->bindTexImage(buffer); return mImplementation->bindTexImage(buffer);
} }
Error Surface::releaseTexImage(EGLint buffer) Error Surface::releaseTexImage(EGLint buffer)
{ {
ASSERT(mTexture); ASSERT(mTexture.get());
gl::Texture *boundTexture = mTexture; mTexture->releaseTexImageFromSurface();
mTexture = NULL; mTexture.set(nullptr);
boundTexture->releaseTexImage();
return mImplementation->releaseTexImage(buffer); return mImplementation->releaseTexImage(buffer);
} }
void Surface::releaseTexImageFromTexture()
{
ASSERT(mTexture.get());
mTexture.set(nullptr);
}
} }
...@@ -64,13 +64,17 @@ class Surface final : public RefCountObject ...@@ -64,13 +64,17 @@ class Surface final : public RefCountObject
EGLenum getTextureFormat() const; EGLenum getTextureFormat() const;
EGLenum getTextureTarget() const; EGLenum getTextureTarget() const;
gl::Texture *getBoundTexture() const { return mTexture; } gl::Texture *getBoundTexture() const { return mTexture.get(); }
EGLint isFixedSize() const; EGLint isFixedSize() const;
private: private:
virtual ~Surface(); virtual ~Surface();
// ANGLE-only method, used internally
friend class gl::Texture;
void releaseTexImageFromTexture();
rx::SurfaceImpl *mImplementation; rx::SurfaceImpl *mImplementation;
EGLint mType; EGLint mType;
...@@ -90,7 +94,7 @@ class Surface final : public RefCountObject ...@@ -90,7 +94,7 @@ class Surface final : public RefCountObject
EGLenum mRenderBuffer; // Render buffer EGLenum mRenderBuffer; // Render buffer
EGLenum mSwapBehavior; // Buffer swap behavior EGLenum mSwapBehavior; // Buffer swap behavior
gl::Texture *mTexture; BindingPointer<gl::Texture> mTexture;
}; };
} }
......
...@@ -181,14 +181,15 @@ Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, cons ...@@ -181,14 +181,15 @@ Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, cons
{ {
ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal();
Error error = mTexture->setImage(target, level, internalFormat, size, format, type, unpack, pixels); Error error = mTexture->setImage(target, level, internalFormat, size, format, type, unpack, pixels);
if (error.isError()) if (error.isError())
{ {
return error; return error;
} }
releaseTexImage();
setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, type))); setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, type)));
return Error(GL_NO_ERROR); return Error(GL_NO_ERROR);
...@@ -207,14 +208,15 @@ Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFo ...@@ -207,14 +208,15 @@ Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFo
{ {
ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal();
Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpack, pixels); Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpack, pixels);
if (error.isError()) if (error.isError())
{ {
return error; return error;
} }
releaseTexImage();
setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE))); setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
return Error(GL_NO_ERROR); return Error(GL_NO_ERROR);
...@@ -233,14 +235,15 @@ Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceAre ...@@ -233,14 +235,15 @@ Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceAre
{ {
ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal();
Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source); Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source);
if (error.isError()) if (error.isError())
{ {
return error; return error;
} }
releaseTexImage();
setImageDesc(target, level, ImageDesc(Extents(sourceArea.width, sourceArea.height, 1), setImageDesc(target, level, ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE))); GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
...@@ -259,14 +262,15 @@ Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, c ...@@ -259,14 +262,15 @@ Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, c
{ {
ASSERT(target == mTarget); ASSERT(target == mTarget);
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal();
Error error = mTexture->setStorage(target, levels, internalFormat, size); Error error = mTexture->setStorage(target, levels, internalFormat, size);
if (error.isError()) if (error.isError())
{ {
return error; return error;
} }
releaseTexImage();
mImmutableLevelCount = levels; mImmutableLevelCount = levels;
clearImageDescs(); clearImageDescs();
setImageDescChain(levels, size, internalFormat); setImageDescChain(levels, size, internalFormat);
...@@ -277,14 +281,15 @@ Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, c ...@@ -277,14 +281,15 @@ Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, c
Error Texture::generateMipmaps() Error Texture::generateMipmaps()
{ {
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal();
Error error = mTexture->generateMipmaps(); Error error = mTexture->generateMipmaps();
if (error.isError()) if (error.isError())
{ {
return error; return error;
} }
releaseTexImage();
const ImageDesc &baseImageInfo = getImageDesc(getBaseImageTarget(), 0); const ImageDesc &baseImageInfo = getImageDesc(getBaseImageTarget(), 0);
size_t mipLevels = log2(std::max(std::max(baseImageInfo.size.width, baseImageInfo.size.height), baseImageInfo.size.depth)) + 1; size_t mipLevels = log2(std::max(std::max(baseImageInfo.size.width, baseImageInfo.size.height), baseImageInfo.size.depth)) + 1;
setImageDescChain(mipLevels, baseImageInfo.size, baseImageInfo.internalFormat); setImageDescChain(mipLevels, baseImageInfo.size, baseImageInfo.internalFormat);
...@@ -355,11 +360,15 @@ void Texture::clearImageDescs() ...@@ -355,11 +360,15 @@ void Texture::clearImageDescs()
mCompletenessCache.cacheValid = false; mCompletenessCache.cacheValid = false;
} }
void Texture::bindTexImage(egl::Surface *surface) void Texture::bindTexImageFromSurface(egl::Surface *surface)
{ {
ASSERT(surface); ASSERT(surface);
releaseTexImage(); if (mBoundSurface)
{
releaseTexImageFromSurface();
}
mTexture->bindTexImage(surface); mTexture->bindTexImage(surface);
mBoundSurface = surface; mBoundSurface = surface;
...@@ -370,16 +379,26 @@ void Texture::bindTexImage(egl::Surface *surface) ...@@ -370,16 +379,26 @@ void Texture::bindTexImage(egl::Surface *surface)
setImageDesc(mTarget, 0, desc); setImageDesc(mTarget, 0, desc);
} }
void Texture::releaseTexImage() void Texture::releaseTexImageFromSurface()
{
ASSERT(mBoundSurface);
mBoundSurface = nullptr;
mTexture->releaseTexImage();
// Erase the image info for level 0
ASSERT(mTarget == GL_TEXTURE_2D);
clearImageDesc(mTarget, 0);
}
void Texture::releaseTexImageInternal()
{ {
if (mBoundSurface) if (mBoundSurface)
{ {
mBoundSurface = NULL; // Notify the surface
mTexture->releaseTexImage(); mBoundSurface->releaseTexImageFromTexture();
// Erase the image info for level 0 // Then, call the same method as from the surface
ASSERT(mTarget == GL_TEXTURE_2D); releaseTexImageFromSurface();
clearImageDesc(mTarget, 0);
} }
} }
......
...@@ -82,9 +82,6 @@ class Texture final : public RefCountObject ...@@ -82,9 +82,6 @@ class Texture final : public RefCountObject
bool isImmutable() const; bool isImmutable() const;
GLsizei immutableLevelCount(); GLsizei immutableLevelCount();
void bindTexImage(egl::Surface *surface);
void releaseTexImage();
rx::TextureImpl *getImplementation() { return mTexture; } rx::TextureImpl *getImplementation() { return mTexture; }
const rx::TextureImpl *getImplementation() const { return mTexture; } const rx::TextureImpl *getImplementation() const { return mTexture; }
...@@ -93,6 +90,11 @@ class Texture final : public RefCountObject ...@@ -93,6 +90,11 @@ class Texture final : public RefCountObject
private: private:
static unsigned int issueTextureSerial(); static unsigned int issueTextureSerial();
// ANGLE-only method, used internally
friend class egl::Surface;
void bindTexImageFromSurface(egl::Surface *surface);
void releaseTexImageFromSurface();
rx::TextureImpl *mTexture; rx::TextureImpl *mTexture;
SamplerState mSamplerState; SamplerState mSamplerState;
...@@ -127,6 +129,7 @@ class Texture final : public RefCountObject ...@@ -127,6 +129,7 @@ class Texture final : public RefCountObject
void setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat); void setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat);
void clearImageDesc(GLenum target, size_t level); void clearImageDesc(GLenum target, size_t level);
void clearImageDescs(); void clearImageDescs();
void releaseTexImageInternal();
std::vector<ImageDesc> mImageDescs; std::vector<ImageDesc> mImageDescs;
......
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