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:
Romain Guy
2013-06-06 14:02:54 -07:00
parent f69913056b
commit be1b127c7b
13 changed files with 53 additions and 11 deletions

View File

@@ -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));
}

View File

@@ -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.

View File

@@ -77,7 +77,7 @@ void Dither::bindDitherTexture() {
void Dither::clear() {
if (mInitialized) {
glDeleteTextures(1, &mDitherTexture);
mCaches->deleteTexture(mDitherTexture);
mInitialized = false;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -167,7 +167,7 @@ void Layer::generateTexture() {
void Layer::deleteTexture() {
if (texture.id) {
glDeleteTextures(1, &texture.id);
texture.deleteTexture();
texture.id = 0;
}
}

View File

@@ -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]);

View File

@@ -223,7 +223,7 @@ void PathCache::removeTexture(PathTexture* texture) {
}
if (texture->id) {
glDeleteTextures(1, &texture->id);
Caches::getInstance().deleteTexture(texture->id);
}
delete texture;
}

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -156,7 +156,7 @@ void CacheTexture::releaseTexture() {
mTexture = NULL;
}
if (mTextureId) {
glDeleteTextures(1, &mTextureId);
mCaches.deleteTexture(mTextureId);
mTextureId = 0;
}
mDirty = false;