Assume a texture is unbound after deleting it
Bug #9316260 The GL specification indicates that deleting a bound texture has the side effect of binding the default texture (name=0). This change replaces all calls to glDeleteTextures() by Caches::deleteTexture() to properly keep track of texture bindings. Change-Id: Ifbc60ef433e0f9776a668dd5bd5f0adbc65a77a0
This commit is contained in:
@@ -508,6 +508,28 @@ void Caches::bindTexture(GLenum target, GLuint texture) {
|
||||
}
|
||||
}
|
||||
|
||||
void Caches::deleteTexture(GLuint texture) {
|
||||
// When glDeleteTextures() is called on a currently bound texture,
|
||||
// OpenGL ES specifies that the texture is then considered unbound
|
||||
// Consider the following series of calls:
|
||||
//
|
||||
// glGenTextures -> creates texture name 2
|
||||
// glBindTexture(2)
|
||||
// glDeleteTextures(2) -> 2 is now unbound
|
||||
// glGenTextures -> can return 2 again
|
||||
//
|
||||
// If we don't call glBindTexture(2) after the second glGenTextures
|
||||
// call, any texture operation will be performed on the default
|
||||
// texture (name=0)
|
||||
|
||||
for (int i = 0; i < REQUIRED_TEXTURE_UNITS_COUNT; i++) {
|
||||
if (mBoundTextures[i] == texture) {
|
||||
mBoundTextures[i] = 0;
|
||||
}
|
||||
}
|
||||
glDeleteTextures(1, &texture);
|
||||
}
|
||||
|
||||
void Caches::resetBoundTextures() {
|
||||
memset(mBoundTextures, 0, REQUIRED_TEXTURE_UNITS_COUNT * sizeof(GLuint));
|
||||
}
|
||||
|
||||
@@ -226,14 +226,25 @@ public:
|
||||
|
||||
/**
|
||||
* Binds the specified texture as a GL_TEXTURE_2D texture.
|
||||
* All texture bindings must be performed with this method or
|
||||
* bindTexture(GLenum, GLuint).
|
||||
*/
|
||||
void bindTexture(GLuint texture);
|
||||
|
||||
/**
|
||||
* Binds the specified texture..
|
||||
* Binds the specified texture with the specified render target.
|
||||
* All texture bindings must be performed with this method or
|
||||
* bindTexture(GLuint).
|
||||
*/
|
||||
void bindTexture(GLenum target, GLuint texture);
|
||||
|
||||
/**
|
||||
* Deletes the specified texture and clears it from the cache
|
||||
* of bound textures.
|
||||
* All textures must be deleted using this method.
|
||||
*/
|
||||
void deleteTexture(GLuint texture);
|
||||
|
||||
/**
|
||||
* Signals that the cache of bound textures should be cleared.
|
||||
* Other users of the context may have altered which textures are bound.
|
||||
|
||||
@@ -77,7 +77,7 @@ void Dither::bindDitherTexture() {
|
||||
|
||||
void Dither::clear() {
|
||||
if (mInitialized) {
|
||||
glDeleteTextures(1, &mDitherTexture);
|
||||
mCaches->deleteTexture(mDitherTexture);
|
||||
mInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ void GradientCache::operator()(GradientCacheEntry& shader, Texture*& texture) {
|
||||
const uint32_t size = texture->width * texture->height * bytesPerPixel();
|
||||
mSize -= size;
|
||||
|
||||
glDeleteTextures(1, &texture->id);
|
||||
texture->deleteTexture();
|
||||
delete texture;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ Image::~Image() {
|
||||
eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), mImage);
|
||||
mImage = EGL_NO_IMAGE_KHR;
|
||||
|
||||
glDeleteTextures(1, &mTexture);
|
||||
Caches::getInstance().deleteTexture(mTexture);
|
||||
mTexture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ void Layer::generateTexture() {
|
||||
|
||||
void Layer::deleteTexture() {
|
||||
if (texture.id) {
|
||||
glDeleteTextures(1, &texture.id);
|
||||
texture.deleteTexture();
|
||||
texture.id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -498,7 +498,7 @@ error:
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
|
||||
layer->setAlpha(alpha, mode);
|
||||
layer->setFbo(previousLayerFbo);
|
||||
glDeleteTextures(1, &texture);
|
||||
caches.deleteTexture(texture);
|
||||
caches.fboCache.put(fbo);
|
||||
glViewport(previousViewport[0], previousViewport[1],
|
||||
previousViewport[2], previousViewport[3]);
|
||||
|
||||
@@ -223,7 +223,7 @@ void PathCache::removeTexture(PathTexture* texture) {
|
||||
}
|
||||
|
||||
if (texture->id) {
|
||||
glDeleteTextures(1, &texture->id);
|
||||
Caches::getInstance().deleteTexture(texture->id);
|
||||
}
|
||||
delete texture;
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ void TextDropShadowCache::operator()(ShadowText& text, ShadowTexture*& texture)
|
||||
ALOGD("Shadow texture deleted, size = %d", texture->bitmapSize);
|
||||
}
|
||||
|
||||
glDeleteTextures(1, &texture->id);
|
||||
texture->deleteTexture();
|
||||
delete texture;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,5 +76,9 @@ void Texture::setFilterMinMag(GLenum min, GLenum mag, bool bindTexture, bool for
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::deleteTexture() const {
|
||||
mCaches.deleteTexture(id);
|
||||
}
|
||||
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
|
||||
@@ -51,6 +51,11 @@ public:
|
||||
virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false,
|
||||
bool force = false, GLenum renderTarget = GL_TEXTURE_2D);
|
||||
|
||||
/**
|
||||
* Convenience method to call glDeleteTextures() on this texture's id.
|
||||
*/
|
||||
void deleteTexture() const;
|
||||
|
||||
/**
|
||||
* Name of the texture.
|
||||
*/
|
||||
@@ -113,7 +118,7 @@ public:
|
||||
AutoTexture(const Texture* texture): mTexture(texture) { }
|
||||
~AutoTexture() {
|
||||
if (mTexture && mTexture->cleanup) {
|
||||
glDeleteTextures(1, &mTexture->id);
|
||||
mTexture->deleteTexture();
|
||||
delete mTexture;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ void TextureCache::operator()(SkBitmap*& bitmap, Texture*& texture) {
|
||||
if (mDebugEnabled) {
|
||||
ALOGD("Texture deleted, size = %d", texture->bitmapSize);
|
||||
}
|
||||
glDeleteTextures(1, &texture->id);
|
||||
texture->deleteTexture();
|
||||
delete texture;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ void CacheTexture::releaseTexture() {
|
||||
mTexture = NULL;
|
||||
}
|
||||
if (mTextureId) {
|
||||
glDeleteTextures(1, &mTextureId);
|
||||
mCaches.deleteTexture(mTextureId);
|
||||
mTextureId = 0;
|
||||
}
|
||||
mDirty = false;
|
||||
|
||||
Reference in New Issue
Block a user