TextureObjectManager.cpp revision 076b1cc3a9b90aa5b381a1ed268ca0b548444c9b
1/* 2 ** Copyright 2006, The Android Open Source Project 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 17#include <stdio.h> 18#include <stdlib.h> 19#include "context.h" 20#include "TextureObjectManager.h" 21 22namespace android { 23// ---------------------------------------------------------------------------- 24 25EGLTextureObject::EGLTextureObject() 26 : mCount(0), mSize(0) 27{ 28 init(); 29} 30 31EGLTextureObject::~EGLTextureObject() 32{ 33 if (!direct) { 34 if (mSize && surface.data) 35 free(surface.data); 36 if (mMipmaps) 37 freeMipmaps(); 38 } 39} 40 41void EGLTextureObject::init() 42{ 43 memset(&surface, 0, sizeof(surface)); 44 surface.version = sizeof(surface); 45 mMipmaps = 0; 46 mNumExtraLod = 0; 47 mIsComplete = false; 48 wraps = GL_REPEAT; 49 wrapt = GL_REPEAT; 50 min_filter = GL_LINEAR; 51 mag_filter = GL_LINEAR; 52 internalformat = 0; 53 memset(crop_rect, 0, sizeof(crop_rect)); 54 generate_mipmap = GL_FALSE; 55 direct = GL_FALSE; 56#ifdef LIBAGL_USE_GRALLOC_COPYBITS 57 copybits_fd = -1; 58#endif // LIBAGL_USE_GRALLOC_COPYBITS 59} 60 61void EGLTextureObject::copyParameters(const sp<EGLTextureObject>& old) 62{ 63 wraps = old->wraps; 64 wrapt = old->wrapt; 65 min_filter = old->min_filter; 66 mag_filter = old->mag_filter; 67 memcpy(crop_rect, old->crop_rect, sizeof(crop_rect)); 68 generate_mipmap = old->generate_mipmap; 69 direct = old->direct; 70} 71 72status_t EGLTextureObject::allocateMipmaps() 73{ 74 // here, by construction, mMipmaps=0 && mNumExtraLod=0 75 76 if (!surface.data) 77 return NO_INIT; 78 79 int w = surface.width; 80 int h = surface.height; 81 const int numLods = 31 - gglClz(max(w,h)); 82 if (numLods <= 0) 83 return NO_ERROR; 84 85 mMipmaps = (GGLSurface*)malloc(numLods * sizeof(GGLSurface)); 86 if (!mMipmaps) 87 return NO_MEMORY; 88 89 memset(mMipmaps, 0, numLods * sizeof(GGLSurface)); 90 mNumExtraLod = numLods; 91 return NO_ERROR; 92} 93 94void EGLTextureObject::freeMipmaps() 95{ 96 if (mMipmaps) { 97 for (int i=0 ; i<mNumExtraLod ; i++) { 98 if (mMipmaps[i].data) { 99 free(mMipmaps[i].data); 100 } 101 } 102 free(mMipmaps); 103 mMipmaps = 0; 104 mNumExtraLod = 0; 105 } 106} 107 108const GGLSurface& EGLTextureObject::mip(int lod) const 109{ 110 if (lod<=0 || !mMipmaps) 111 return surface; 112 lod = min(lod-1, mNumExtraLod-1); 113 return mMipmaps[lod]; 114} 115 116GGLSurface& EGLTextureObject::editMip(int lod) 117{ 118 return const_cast<GGLSurface&>(mip(lod)); 119} 120 121status_t EGLTextureObject::setSurface(GGLSurface const* s) 122{ 123 // XXX: glFlush() on 's' 124 if (mSize && surface.data) { 125 free(surface.data); 126 } 127 surface = *s; 128 internalformat = 0; 129 130 // we should keep the crop_rect, but it's delicate because 131 // the new size of the surface could make it invalid. 132 // so for now, we just loose it. 133 memset(crop_rect, 0, sizeof(crop_rect)); 134 135 // it would be nice if we could keep the generate_mipmap flag, 136 // we would have to generate them right now though. 137 generate_mipmap = GL_FALSE; 138 139 direct = GL_TRUE; 140 mSize = 0; // we don't own this surface 141 if (mMipmaps) 142 freeMipmaps(); 143 mIsComplete = true; 144 return NO_ERROR; 145} 146 147status_t EGLTextureObject::reallocate( 148 GLint level, int w, int h, int s, 149 int format, int compressedFormat, int bpr) 150{ 151 const size_t size = h * bpr; 152 if (level == 0) 153 { 154 if (size!=mSize || !surface.data) { 155 if (mSize && surface.data) { 156 free(surface.data); 157 } 158 surface.data = (GGLubyte*)malloc(size); 159 if (!surface.data) { 160 mSize = 0; 161 mIsComplete = false; 162 return NO_MEMORY; 163 } 164 mSize = size; 165 } 166 surface.version = sizeof(GGLSurface); 167 surface.width = w; 168 surface.height = h; 169 surface.stride = s; 170 surface.format = format; 171 surface.compressedFormat = compressedFormat; 172 if (mMipmaps) 173 freeMipmaps(); 174 mIsComplete = true; 175 } 176 else 177 { 178 if (!mMipmaps) { 179 if (allocateMipmaps() != NO_ERROR) 180 return NO_MEMORY; 181 } 182 183 LOGW_IF(level-1 >= mNumExtraLod, 184 "specifying mipmap level %d, but # of level is %d", 185 level, mNumExtraLod+1); 186 187 GGLSurface& mipmap = editMip(level); 188 if (mipmap.data) 189 free(mipmap.data); 190 191 mipmap.data = (GGLubyte*)malloc(size); 192 if (!mipmap.data) { 193 memset(&mipmap, 0, sizeof(GGLSurface)); 194 mIsComplete = false; 195 return NO_MEMORY; 196 } 197 198 mipmap.version = sizeof(GGLSurface); 199 mipmap.width = w; 200 mipmap.height = h; 201 mipmap.stride = s; 202 mipmap.format = format; 203 mipmap.compressedFormat = compressedFormat; 204 205 // check if the texture is complete 206 mIsComplete = true; 207 const GGLSurface* prev = &surface; 208 for (int i=0 ; i<mNumExtraLod ; i++) { 209 const GGLSurface* curr = mMipmaps + i; 210 if (curr->format != surface.format) { 211 mIsComplete = false; 212 break; 213 } 214 215 uint32_t w = (prev->width >> 1) ? : 1; 216 uint32_t h = (prev->height >> 1) ? : 1; 217 if (w != curr->width || h != curr->height) { 218 mIsComplete = false; 219 break; 220 } 221 prev = curr; 222 } 223 } 224 return NO_ERROR; 225} 226 227// ---------------------------------------------------------------------------- 228 229EGLSurfaceManager::EGLSurfaceManager() 230 : TokenManager(), mCount(0) 231{ 232} 233 234EGLSurfaceManager::~EGLSurfaceManager() 235{ 236 // everything gets freed automatically here... 237} 238 239sp<EGLTextureObject> EGLSurfaceManager::createTexture(GLuint name) 240{ 241 sp<EGLTextureObject> result; 242 243 Mutex::Autolock _l(mLock); 244 if (mTextures.indexOfKey(name) >= 0) 245 return result; // already exists! 246 247 result = new EGLTextureObject(); 248 249 status_t err = mTextures.add(name, result); 250 if (err < 0) 251 result.clear(); 252 253 return result; 254} 255 256sp<EGLTextureObject> EGLSurfaceManager::removeTexture(GLuint name) 257{ 258 Mutex::Autolock _l(mLock); 259 const ssize_t index = mTextures.indexOfKey(name); 260 if (index >= 0) { 261 sp<EGLTextureObject> result(mTextures.valueAt(index)); 262 mTextures.removeItemsAt(index); 263 return result; 264 } 265 return 0; 266} 267 268sp<EGLTextureObject> EGLSurfaceManager::replaceTexture(GLuint name) 269{ 270 sp<EGLTextureObject> tex; 271 Mutex::Autolock _l(mLock); 272 const ssize_t index = mTextures.indexOfKey(name); 273 if (index >= 0) { 274 const sp<EGLTextureObject>& old = mTextures.valueAt(index); 275 const uint32_t refs = old->getStrongCount(); 276 if (ggl_likely(refs == 1)) { 277 // we're the only owner 278 tex = old; 279 } else { 280 // keep the texture's parameters 281 tex = new EGLTextureObject(); 282 tex->copyParameters(old); 283 mTextures.removeItemsAt(index); 284 mTextures.add(name, tex); 285 } 286 } 287 return tex; 288} 289 290void EGLSurfaceManager::deleteTextures(GLsizei n, const GLuint *tokens) 291{ 292 // free all textures 293 Mutex::Autolock _l(mLock); 294 for (GLsizei i=0 ; i<n ; i++) { 295 const GLuint t(*tokens++); 296 if (t) { 297 mTextures.removeItem(t); 298 } 299 } 300} 301 302sp<EGLTextureObject> EGLSurfaceManager::texture(GLuint name) 303{ 304 Mutex::Autolock _l(mLock); 305 const ssize_t index = mTextures.indexOfKey(name); 306 if (index >= 0) 307 return mTextures.valueAt(index); 308 return 0; 309} 310 311// ---------------------------------------------------------------------------- 312}; // namespace android 313