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
// FIXME: Determine actual pixel aspect ratio
mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
mRenderBuffer(EGL_BACK_BUFFER),
mSwapBehavior(EGL_BUFFER_PRESERVED),
mTexture(NULL)
mSwapBehavior(EGL_BUFFER_PRESERVED)
{
addRef();
......@@ -56,14 +55,14 @@ Surface::Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *c
Surface::~Surface()
{
if (mTexture)
if (mTexture.get())
{
if (mImplementation)
{
mImplementation->releaseTexImage(mTexture->id());
}
mTexture->releaseTexImage();
mTexture = NULL;
mTexture->releaseTexImageFromSurface();
mTexture.set(nullptr);
}
SafeDelete(mImplementation);
......@@ -146,21 +145,26 @@ EGLint Surface::getHeight() const
Error Surface::bindTexImage(gl::Texture *texture, EGLint buffer)
{
ASSERT(!mTexture);
ASSERT(!mTexture.get());
texture->bindTexImage(this);
mTexture = texture;
texture->bindTexImageFromSurface(this);
mTexture.set(texture);
return mImplementation->bindTexImage(buffer);
}
Error Surface::releaseTexImage(EGLint buffer)
{
ASSERT(mTexture);
gl::Texture *boundTexture = mTexture;
mTexture = NULL;
ASSERT(mTexture.get());
mTexture->releaseTexImageFromSurface();
mTexture.set(nullptr);
boundTexture->releaseTexImage();
return mImplementation->releaseTexImage(buffer);
}
void Surface::releaseTexImageFromTexture()
{
ASSERT(mTexture.get());
mTexture.set(nullptr);
}
}
......@@ -64,13 +64,17 @@ class Surface final : public RefCountObject
EGLenum getTextureFormat() const;
EGLenum getTextureTarget() const;
gl::Texture *getBoundTexture() const { return mTexture; }
gl::Texture *getBoundTexture() const { return mTexture.get(); }
EGLint isFixedSize() const;
private:
virtual ~Surface();
// ANGLE-only method, used internally
friend class gl::Texture;
void releaseTexImageFromTexture();
rx::SurfaceImpl *mImplementation;
EGLint mType;
......@@ -90,7 +94,7 @@ class Surface final : public RefCountObject
EGLenum mRenderBuffer; // Render buffer
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
{
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);
if (error.isError())
{
return error;
}
releaseTexImage();
setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, type)));
return Error(GL_NO_ERROR);
......@@ -207,14 +208,15 @@ Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFo
{
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);
if (error.isError())
{
return error;
}
releaseTexImage();
setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
return Error(GL_NO_ERROR);
......@@ -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)));
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal();
Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source);
if (error.isError())
{
return error;
}
releaseTexImage();
setImageDesc(target, level, ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
......@@ -259,14 +262,15 @@ Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, c
{
ASSERT(target == mTarget);
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal();
Error error = mTexture->setStorage(target, levels, internalFormat, size);
if (error.isError())
{
return error;
}
releaseTexImage();
mImmutableLevelCount = levels;
clearImageDescs();
setImageDescChain(levels, size, internalFormat);
......@@ -277,14 +281,15 @@ Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, c
Error Texture::generateMipmaps()
{
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal();
Error error = mTexture->generateMipmaps();
if (error.isError())
{
return error;
}
releaseTexImage();
const ImageDesc &baseImageInfo = getImageDesc(getBaseImageTarget(), 0);
size_t mipLevels = log2(std::max(std::max(baseImageInfo.size.width, baseImageInfo.size.height), baseImageInfo.size.depth)) + 1;
setImageDescChain(mipLevels, baseImageInfo.size, baseImageInfo.internalFormat);
......@@ -355,11 +360,15 @@ void Texture::clearImageDescs()
mCompletenessCache.cacheValid = false;
}
void Texture::bindTexImage(egl::Surface *surface)
void Texture::bindTexImageFromSurface(egl::Surface *surface)
{
ASSERT(surface);
releaseTexImage();
if (mBoundSurface)
{
releaseTexImageFromSurface();
}
mTexture->bindTexImage(surface);
mBoundSurface = surface;
......@@ -370,16 +379,26 @@ void Texture::bindTexImage(egl::Surface *surface)
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)
{
mBoundSurface = NULL;
mTexture->releaseTexImage();
// Notify the surface
mBoundSurface->releaseTexImageFromTexture();
// Erase the image info for level 0
ASSERT(mTarget == GL_TEXTURE_2D);
clearImageDesc(mTarget, 0);
// Then, call the same method as from the surface
releaseTexImageFromSurface();
}
}
......
......@@ -82,9 +82,6 @@ class Texture final : public RefCountObject
bool isImmutable() const;
GLsizei immutableLevelCount();
void bindTexImage(egl::Surface *surface);
void releaseTexImage();
rx::TextureImpl *getImplementation() { return mTexture; }
const rx::TextureImpl *getImplementation() const { return mTexture; }
......@@ -93,6 +90,11 @@ class Texture final : public RefCountObject
private:
static unsigned int issueTextureSerial();
// ANGLE-only method, used internally
friend class egl::Surface;
void bindTexImageFromSurface(egl::Surface *surface);
void releaseTexImageFromSurface();
rx::TextureImpl *mTexture;
SamplerState mSamplerState;
......@@ -127,6 +129,7 @@ class Texture final : public RefCountObject
void setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat);
void clearImageDesc(GLenum target, size_t level);
void clearImageDescs();
void releaseTexImageInternal();
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