TextureObjectManager.cpp revision dff8e58d47ede6e748c0b02e128ca33b42a4f362
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 : 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 buffer = 0; 60} 61 62void EGLTextureObject::copyParameters(const sp<EGLTextureObject>& old) 63{ 64 wraps = old->wraps; 65 wrapt = old->wrapt; 66 min_filter = old->min_filter; 67 mag_filter = old->mag_filter; 68 memcpy(crop_rect, old->crop_rect, sizeof(crop_rect)); 69 generate_mipmap = old->generate_mipmap; 70 direct = old->direct; 71} 72 73status_t EGLTextureObject::allocateMipmaps() 74{ 75 // here, by construction, mMipmaps=0 && mNumExtraLod=0 76 77 if (!surface.data) 78 return NO_INIT; 79 80 int w = surface.width; 81 int h = surface.height; 82 const int numLods = 31 - gglClz(max(w,h)); 83 if (numLods <= 0) 84 return NO_ERROR; 85 86 mMipmaps = (GGLSurface*)malloc(numLods * sizeof(GGLSurface)); 87 if (!mMipmaps) 88 return NO_MEMORY; 89 90 memset(mMipmaps, 0, numLods * sizeof(GGLSurface)); 91 mNumExtraLod = numLods; 92 return NO_ERROR; 93} 94 95void EGLTextureObject::freeMipmaps() 96{ 97 if (mMipmaps) { 98 for (int i=0 ; i<mNumExtraLod ; i++) { 99 if (mMipmaps[i].data) { 100 free(mMipmaps[i].data); 101 } 102 } 103 free(mMipmaps); 104 mMipmaps = 0; 105 mNumExtraLod = 0; 106 } 107} 108 109const GGLSurface& EGLTextureObject::mip(int lod) const 110{ 111 if (lod<=0 || !mMipmaps) 112 return surface; 113 lod = min(lod-1, mNumExtraLod-1); 114 return mMipmaps[lod]; 115} 116 117GGLSurface& EGLTextureObject::editMip(int lod) 118{ 119 return const_cast<GGLSurface&>(mip(lod)); 120} 121 122status_t EGLTextureObject::setSurface(GGLSurface const* s) 123{ 124 // XXX: glFlush() on 's' 125 if (mSize && surface.data) { 126 free(surface.data); 127 } 128 surface = *s; 129 internalformat = 0; 130 buffer = 0; 131 132 // we should keep the crop_rect, but it's delicate because 133 // the new size of the surface could make it invalid. 134 // so for now, we just loose it. 135 memset(crop_rect, 0, sizeof(crop_rect)); 136 137 // it would be nice if we could keep the generate_mipmap flag, 138 // we would have to generate them right now though. 139 generate_mipmap = GL_FALSE; 140 141 direct = GL_TRUE; 142 mSize = 0; // we don't own this surface 143 if (mMipmaps) 144 freeMipmaps(); 145 mIsComplete = true; 146 return NO_ERROR; 147} 148 149status_t EGLTextureObject::setImage(android_native_buffer_t* native_buffer) 150{ 151 GGLSurface sur; 152 sur.version = sizeof(GGLSurface); 153 sur.width = native_buffer->width; 154 sur.height= native_buffer->height; 155 sur.stride= native_buffer->stride; 156 sur.format= native_buffer->format; 157 sur.data = 0; 158 setSurface(&sur); 159 buffer = native_buffer; 160 return NO_ERROR; 161} 162 163status_t EGLTextureObject::reallocate( 164 GLint level, int w, int h, int s, 165 int format, int compressedFormat, int bpr) 166{ 167 const size_t size = h * bpr; 168 if (level == 0) 169 { 170 if (size!=mSize || !surface.data) { 171 if (mSize && surface.data) { 172 free(surface.data); 173 } 174 surface.data = (GGLubyte*)malloc(size); 175 if (!surface.data) { 176 mSize = 0; 177 mIsComplete = false; 178 return NO_MEMORY; 179 } 180 mSize = size; 181 } 182 surface.version = sizeof(GGLSurface); 183 surface.width = w; 184 surface.height = h; 185 surface.stride = s; 186 surface.format = format; 187 surface.compressedFormat = compressedFormat; 188 if (mMipmaps) 189 freeMipmaps(); 190 mIsComplete = true; 191 } 192 else 193 { 194 if (!mMipmaps) { 195 if (allocateMipmaps() != NO_ERROR) 196 return NO_MEMORY; 197 } 198 199 LOGW_IF(level-1 >= mNumExtraLod, 200 "specifying mipmap level %d, but # of level is %d", 201 level, mNumExtraLod+1); 202 203 GGLSurface& mipmap = editMip(level); 204 if (mipmap.data) 205 free(mipmap.data); 206 207 mipmap.data = (GGLubyte*)malloc(size); 208 if (!mipmap.data) { 209 memset(&mipmap, 0, sizeof(GGLSurface)); 210 mIsComplete = false; 211 return NO_MEMORY; 212 } 213 214 mipmap.version = sizeof(GGLSurface); 215 mipmap.width = w; 216 mipmap.height = h; 217 mipmap.stride = s; 218 mipmap.format = format; 219 mipmap.compressedFormat = compressedFormat; 220 221 // check if the texture is complete 222 mIsComplete = true; 223 const GGLSurface* prev = &surface; 224 for (int i=0 ; i<mNumExtraLod ; i++) { 225 const GGLSurface* curr = mMipmaps + i; 226 if (curr->format != surface.format) { 227 mIsComplete = false; 228 break; 229 } 230 231 uint32_t w = (prev->width >> 1) ? : 1; 232 uint32_t h = (prev->height >> 1) ? : 1; 233 if (w != curr->width || h != curr->height) { 234 mIsComplete = false; 235 break; 236 } 237 prev = curr; 238 } 239 } 240 return NO_ERROR; 241} 242 243// ---------------------------------------------------------------------------- 244 245EGLSurfaceManager::EGLSurfaceManager() 246 : TokenManager() 247{ 248} 249 250EGLSurfaceManager::~EGLSurfaceManager() 251{ 252 // everything gets freed automatically here... 253} 254 255sp<EGLTextureObject> EGLSurfaceManager::createTexture(GLuint name) 256{ 257 sp<EGLTextureObject> result; 258 259 Mutex::Autolock _l(mLock); 260 if (mTextures.indexOfKey(name) >= 0) 261 return result; // already exists! 262 263 result = new EGLTextureObject(); 264 265 status_t err = mTextures.add(name, result); 266 if (err < 0) 267 result.clear(); 268 269 return result; 270} 271 272sp<EGLTextureObject> EGLSurfaceManager::removeTexture(GLuint name) 273{ 274 Mutex::Autolock _l(mLock); 275 const ssize_t index = mTextures.indexOfKey(name); 276 if (index >= 0) { 277 sp<EGLTextureObject> result(mTextures.valueAt(index)); 278 mTextures.removeItemsAt(index); 279 return result; 280 } 281 return 0; 282} 283 284sp<EGLTextureObject> EGLSurfaceManager::replaceTexture(GLuint name) 285{ 286 sp<EGLTextureObject> tex; 287 Mutex::Autolock _l(mLock); 288 const ssize_t index = mTextures.indexOfKey(name); 289 if (index >= 0) { 290 const sp<EGLTextureObject>& old = mTextures.valueAt(index); 291 const uint32_t refs = old->getStrongCount(); 292 if (ggl_likely(refs == 1)) { 293 // we're the only owner 294 tex = old; 295 } else { 296 // keep the texture's parameters 297 tex = new EGLTextureObject(); 298 tex->copyParameters(old); 299 mTextures.removeItemsAt(index); 300 mTextures.add(name, tex); 301 } 302 } 303 return tex; 304} 305 306void EGLSurfaceManager::deleteTextures(GLsizei n, const GLuint *tokens) 307{ 308 // free all textures 309 Mutex::Autolock _l(mLock); 310 for (GLsizei i=0 ; i<n ; i++) { 311 const GLuint t(*tokens++); 312 if (t) { 313 mTextures.removeItem(t); 314 } 315 } 316} 317 318sp<EGLTextureObject> EGLSurfaceManager::texture(GLuint name) 319{ 320 Mutex::Autolock _l(mLock); 321 const ssize_t index = mTextures.indexOfKey(name); 322 if (index >= 0) 323 return mTextures.valueAt(index); 324 return 0; 325} 326 327// ---------------------------------------------------------------------------- 328}; // namespace android 329