diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:31:44 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:31:44 -0800 |
commit | 9066cfe9886ac131c34d59ed0e2d287b0e3c0087 (patch) | |
tree | d88beb88001f2482911e3d28e43833b50e4b4e97 /opengl/libagl/TextureObjectManager.cpp | |
parent | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (diff) | |
download | frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.tar.gz frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.tar.bz2 frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.zip |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'opengl/libagl/TextureObjectManager.cpp')
-rw-r--r-- | opengl/libagl/TextureObjectManager.cpp | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/opengl/libagl/TextureObjectManager.cpp b/opengl/libagl/TextureObjectManager.cpp new file mode 100644 index 00000000000..ce31854172d --- /dev/null +++ b/opengl/libagl/TextureObjectManager.cpp @@ -0,0 +1,309 @@ +/* + ** Copyright 2006, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include "context.h" +#include "TextureObjectManager.h" + +namespace android { +// ---------------------------------------------------------------------------- + +EGLTextureObject::EGLTextureObject() + : mCount(0), mSize(0) +{ + init(); +} + +EGLTextureObject::~EGLTextureObject() +{ + if (!direct) { + if (mSize && surface.data) + free(surface.data); + if (mMipmaps) + freeMipmaps(); + } +} + +void EGLTextureObject::init() +{ + memset(&surface, 0, sizeof(surface)); + surface.version = sizeof(surface); + mMipmaps = 0; + mNumExtraLod = 0; + mIsComplete = false; + wraps = GL_REPEAT; + wrapt = GL_REPEAT; + min_filter = GL_LINEAR; + mag_filter = GL_LINEAR; + internalformat = 0; + memset(crop_rect, 0, sizeof(crop_rect)); + generate_mipmap = GL_FALSE; + direct = GL_FALSE; +} + +void EGLTextureObject::copyParameters(const sp<EGLTextureObject>& old) +{ + wraps = old->wraps; + wrapt = old->wrapt; + min_filter = old->min_filter; + mag_filter = old->mag_filter; + memcpy(crop_rect, old->crop_rect, sizeof(crop_rect)); + generate_mipmap = old->generate_mipmap; + direct = old->direct; +} + +status_t EGLTextureObject::allocateMipmaps() +{ + // here, by construction, mMipmaps=0 && mNumExtraLod=0 + + if (!surface.data) + return NO_INIT; + + int w = surface.width; + int h = surface.height; + const int numLods = 31 - gglClz(max(w,h)); + if (numLods <= 0) + return NO_ERROR; + + mMipmaps = (GGLSurface*)malloc(numLods * sizeof(GGLSurface)); + if (!mMipmaps) + return NO_MEMORY; + + memset(mMipmaps, 0, numLods * sizeof(GGLSurface)); + mNumExtraLod = numLods; + return NO_ERROR; +} + +void EGLTextureObject::freeMipmaps() +{ + if (mMipmaps) { + for (int i=0 ; i<mNumExtraLod ; i++) { + if (mMipmaps[i].data) { + free(mMipmaps[i].data); + } + } + free(mMipmaps); + mMipmaps = 0; + mNumExtraLod = 0; + } +} + +const GGLSurface& EGLTextureObject::mip(int lod) const +{ + if (lod<=0 || !mMipmaps) + return surface; + lod = min(lod-1, mNumExtraLod-1); + return mMipmaps[lod]; +} + +GGLSurface& EGLTextureObject::editMip(int lod) +{ + return const_cast<GGLSurface&>(mip(lod)); +} + +status_t EGLTextureObject::setSurface(GGLSurface const* s) +{ + // XXX: glFlush() on 's' + if (mSize && surface.data) { + free(surface.data); + } + surface = *s; + internalformat = 0; + + // we should keep the crop_rect, but it's delicate because + // the new size of the surface could make it invalid. + // so for now, we just loose it. + memset(crop_rect, 0, sizeof(crop_rect)); + + // it would be nice if we could keep the generate_mipmap flag, + // we would have to generate them right now though. + generate_mipmap = GL_FALSE; + + direct = GL_TRUE; + mSize = 0; // we don't own this surface + if (mMipmaps) + freeMipmaps(); + mIsComplete = true; + return NO_ERROR; +} + +status_t EGLTextureObject::reallocate( + GLint level, int w, int h, int s, + int format, int compressedFormat, int bpr) +{ + const size_t size = h * bpr; + if (level == 0) + { + if (size!=mSize || !surface.data) { + if (mSize && surface.data) { + free(surface.data); + } + surface.data = (GGLubyte*)malloc(size); + if (!surface.data) { + mSize = 0; + mIsComplete = false; + return NO_MEMORY; + } + mSize = size; + } + surface.version = sizeof(GGLSurface); + surface.width = w; + surface.height = h; + surface.stride = s; + surface.format = format; + surface.compressedFormat = compressedFormat; + if (mMipmaps) + freeMipmaps(); + mIsComplete = true; + } + else + { + if (!mMipmaps) { + if (allocateMipmaps() != NO_ERROR) + return NO_MEMORY; + } + + LOGW_IF(level-1 >= mNumExtraLod, + "specifying mipmap level %d, but # of level is %d", + level, mNumExtraLod+1); + + GGLSurface& mipmap = editMip(level); + if (mipmap.data) + free(mipmap.data); + + mipmap.data = (GGLubyte*)malloc(size); + if (!mipmap.data) { + memset(&mipmap, 0, sizeof(GGLSurface)); + mIsComplete = false; + return NO_MEMORY; + } + + mipmap.version = sizeof(GGLSurface); + mipmap.width = w; + mipmap.height = h; + mipmap.stride = s; + mipmap.format = format; + mipmap.compressedFormat = compressedFormat; + + // check if the texture is complete + mIsComplete = true; + const GGLSurface* prev = &surface; + for (int i=0 ; i<mNumExtraLod ; i++) { + const GGLSurface* curr = mMipmaps + i; + if (curr->format != surface.format) { + mIsComplete = false; + break; + } + + uint32_t w = (prev->width >> 1) ? : 1; + uint32_t h = (prev->height >> 1) ? : 1; + if (w != curr->width || h != curr->height) { + mIsComplete = false; + break; + } + prev = curr; + } + } + return NO_ERROR; +} + +// ---------------------------------------------------------------------------- + +EGLSurfaceManager::EGLSurfaceManager() + : TokenManager(), mCount(0) +{ +} + +EGLSurfaceManager::~EGLSurfaceManager() +{ + // everything gets freed automatically here... +} + +sp<EGLTextureObject> EGLSurfaceManager::createTexture(GLuint name) +{ + sp<EGLTextureObject> result; + + Mutex::Autolock _l(mLock); + if (mTextures.indexOfKey(name) >= 0) + return result; // already exists! + + result = new EGLTextureObject(); + + status_t err = mTextures.add(name, result); + if (err < 0) + result.clear(); + + return result; +} + +sp<EGLTextureObject> EGLSurfaceManager::removeTexture(GLuint name) +{ + Mutex::Autolock _l(mLock); + const ssize_t index = mTextures.indexOfKey(name); + if (index >= 0) { + sp<EGLTextureObject> result(mTextures.valueAt(index)); + mTextures.removeItemsAt(index); + return result; + } + return 0; +} + +sp<EGLTextureObject> EGLSurfaceManager::replaceTexture(GLuint name) +{ + sp<EGLTextureObject> tex; + Mutex::Autolock _l(mLock); + const ssize_t index = mTextures.indexOfKey(name); + if (index >= 0) { + const sp<EGLTextureObject>& old = mTextures.valueAt(index); + const uint32_t refs = old->getStrongCount(); + if (ggl_likely(refs == 1)) { + // we're the only owner + tex = old; + } else { + // keep the texture's parameters + tex = new EGLTextureObject(); + tex->copyParameters(old); + mTextures.removeItemsAt(index); + mTextures.add(name, tex); + } + } + return tex; +} + +void EGLSurfaceManager::deleteTextures(GLsizei n, const GLuint *tokens) +{ + // free all textures + Mutex::Autolock _l(mLock); + for (GLsizei i=0 ; i<n ; i++) { + const GLuint t(*tokens++); + if (t) { + mTextures.removeItem(t); + } + } +} + +sp<EGLTextureObject> EGLSurfaceManager::texture(GLuint name) +{ + Mutex::Autolock _l(mLock); + const ssize_t index = mTextures.indexOfKey(name); + if (index >= 0) + return mTextures.valueAt(index); + return 0; +} + +// ---------------------------------------------------------------------------- +}; // namespace android |