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