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 24 namespace android { 25 // ---------------------------------------------------------------------------- 26 27 EGLTextureObject::EGLTextureObject() 28 : mSize(0) 29 { 30 init(); 31 } 32 33 EGLTextureObject::~EGLTextureObject() 34 { 35 if (!direct) { 36 if (mSize && surface.data) 37 free(surface.data); 38 if (mMipmaps) 39 freeMipmaps(); 40 } 41 } 42 43 void 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 buffer = 0; 59 } 60 61 void 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 72 status_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 94 void 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 108 const 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 116 GGLSurface& EGLTextureObject::editMip(int lod) 117 { 118 return const_cast<GGLSurface&>(mip(lod)); 119 } 120 121 status_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 buffer = 0; 130 131 // we should keep the crop_rect, but it's delicate because 132 // the new size of the surface could make it invalid. 133 // so for now, we just loose it. 134 memset(crop_rect, 0, sizeof(crop_rect)); 135 136 // it would be nice if we could keep the generate_mipmap flag, 137 // we would have to generate them right now though. 138 generate_mipmap = GL_FALSE; 139 140 direct = GL_TRUE; 141 mSize = 0; // we don't own this surface 142 if (mMipmaps) 143 freeMipmaps(); 144 mIsComplete = true; 145 return NO_ERROR; 146 } 147 148 status_t EGLTextureObject::setImage(ANativeWindowBuffer* native_buffer) 149 { 150 GGLSurface sur; 151 sur.version = sizeof(GGLSurface); 152 sur.width = native_buffer->width; 153 sur.height= native_buffer->height; 154 sur.stride= native_buffer->stride; 155 sur.format= native_buffer->format; 156 sur.data = 0; 157 setSurface(&sur); 158 buffer = native_buffer; 159 return NO_ERROR; 160 } 161 162 status_t EGLTextureObject::reallocate( 163 GLint level, int w, int h, int s, 164 int format, int compressedFormat, int bpr) 165 { 166 const size_t size = h * bpr; 167 if (level == 0) 168 { 169 if (size!=mSize || !surface.data) { 170 if (mSize && surface.data) { 171 free(surface.data); 172 } 173 surface.data = (GGLubyte*)malloc(size); 174 if (!surface.data) { 175 mSize = 0; 176 mIsComplete = false; 177 return NO_MEMORY; 178 } 179 mSize = size; 180 } 181 surface.version = sizeof(GGLSurface); 182 surface.width = w; 183 surface.height = h; 184 surface.stride = s; 185 surface.format = format; 186 surface.compressedFormat = compressedFormat; 187 if (mMipmaps) 188 freeMipmaps(); 189 mIsComplete = true; 190 } 191 else 192 { 193 if (!mMipmaps) { 194 if (allocateMipmaps() != NO_ERROR) 195 return NO_MEMORY; 196 } 197 198 LOGW_IF(level-1 >= mNumExtraLod, 199 "specifying mipmap level %d, but # of level is %d", 200 level, mNumExtraLod+1); 201 202 GGLSurface& mipmap = editMip(level); 203 if (mipmap.data) 204 free(mipmap.data); 205 206 mipmap.data = (GGLubyte*)malloc(size); 207 if (!mipmap.data) { 208 memset(&mipmap, 0, sizeof(GGLSurface)); 209 mIsComplete = false; 210 return NO_MEMORY; 211 } 212 213 mipmap.version = sizeof(GGLSurface); 214 mipmap.width = w; 215 mipmap.height = h; 216 mipmap.stride = s; 217 mipmap.format = format; 218 mipmap.compressedFormat = compressedFormat; 219 220 // check if the texture is complete 221 mIsComplete = true; 222 const GGLSurface* prev = &surface; 223 for (int i=0 ; i<mNumExtraLod ; i++) { 224 const GGLSurface* curr = mMipmaps + i; 225 if (curr->format != surface.format) { 226 mIsComplete = false; 227 break; 228 } 229 230 uint32_t w = (prev->width >> 1) ? : 1; 231 uint32_t h = (prev->height >> 1) ? : 1; 232 if (w != curr->width || h != curr->height) { 233 mIsComplete = false; 234 break; 235 } 236 prev = curr; 237 } 238 } 239 return NO_ERROR; 240 } 241 242 // ---------------------------------------------------------------------------- 243 244 EGLSurfaceManager::EGLSurfaceManager() 245 : TokenManager() 246 { 247 } 248 249 EGLSurfaceManager::~EGLSurfaceManager() 250 { 251 // everything gets freed automatically here... 252 } 253 254 sp<EGLTextureObject> EGLSurfaceManager::createTexture(GLuint name) 255 { 256 sp<EGLTextureObject> result; 257 258 Mutex::Autolock _l(mLock); 259 if (mTextures.indexOfKey(name) >= 0) 260 return result; // already exists! 261 262 result = new EGLTextureObject(); 263 264 status_t err = mTextures.add(name, result); 265 if (err < 0) 266 result.clear(); 267 268 return result; 269 } 270 271 sp<EGLTextureObject> EGLSurfaceManager::removeTexture(GLuint name) 272 { 273 Mutex::Autolock _l(mLock); 274 const ssize_t index = mTextures.indexOfKey(name); 275 if (index >= 0) { 276 sp<EGLTextureObject> result(mTextures.valueAt(index)); 277 mTextures.removeItemsAt(index); 278 return result; 279 } 280 return 0; 281 } 282 283 sp<EGLTextureObject> EGLSurfaceManager::replaceTexture(GLuint name) 284 { 285 sp<EGLTextureObject> tex; 286 Mutex::Autolock _l(mLock); 287 const ssize_t index = mTextures.indexOfKey(name); 288 if (index >= 0) { 289 const sp<EGLTextureObject>& old = mTextures.valueAt(index); 290 const uint32_t refs = old->getStrongCount(); 291 if (ggl_likely(refs == 1)) { 292 // we're the only owner 293 tex = old; 294 } else { 295 // keep the texture's parameters 296 tex = new EGLTextureObject(); 297 tex->copyParameters(old); 298 mTextures.removeItemsAt(index); 299 mTextures.add(name, tex); 300 } 301 } 302 return tex; 303 } 304 305 void EGLSurfaceManager::deleteTextures(GLsizei n, const GLuint *tokens) 306 { 307 // free all textures 308 Mutex::Autolock _l(mLock); 309 for (GLsizei i=0 ; i<n ; i++) { 310 const GLuint t(*tokens++); 311 if (t) { 312 mTextures.removeItem(t); 313 } 314 } 315 } 316 317 sp<EGLTextureObject> EGLSurfaceManager::texture(GLuint name) 318 { 319 Mutex::Autolock _l(mLock); 320 const ssize_t index = mTextures.indexOfKey(name); 321 if (index >= 0) 322 return mTextures.valueAt(index); 323 return 0; 324 } 325 326 // ---------------------------------------------------------------------------- 327 }; // namespace android 328