2 ** Copyright 2006, The Android Open Source Project
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
8 ** http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include "TextureObjectManager.h"
23 // ----------------------------------------------------------------------------
25 EGLTextureObject::EGLTextureObject()
31 EGLTextureObject::~EGLTextureObject()
34 if (mSize && surface.data)
41 void EGLTextureObject::init()
43 memset(&surface, 0, sizeof(surface));
44 surface.version = sizeof(surface);
50 min_filter = GL_LINEAR;
51 mag_filter = GL_LINEAR;
53 memset(crop_rect, 0, sizeof(crop_rect));
54 generate_mipmap = GL_FALSE;
59 void EGLTextureObject::copyParameters(const sp<EGLTextureObject>& old)
63 min_filter = old->min_filter;
64 mag_filter = old->mag_filter;
65 memcpy(crop_rect, old->crop_rect, sizeof(crop_rect));
66 generate_mipmap = old->generate_mipmap;
70 status_t EGLTextureObject::allocateMipmaps()
72 // here, by construction, mMipmaps=0 && mNumExtraLod=0
77 int w = surface.width;
78 int h = surface.height;
79 const int numLods = 31 - gglClz(max(w,h));
83 mMipmaps = (GGLSurface*)malloc(numLods * sizeof(GGLSurface));
87 memset(mMipmaps, 0, numLods * sizeof(GGLSurface));
88 mNumExtraLod = numLods;
92 void EGLTextureObject::freeMipmaps()
95 for (int i=0 ; i<mNumExtraLod ; i++) {
96 if (mMipmaps[i].data) {
97 free(mMipmaps[i].data);
106 const GGLSurface& EGLTextureObject::mip(int lod) const
108 if (lod<=0 || !mMipmaps)
110 lod = min(lod-1, mNumExtraLod-1);
111 return mMipmaps[lod];
114 GGLSurface& EGLTextureObject::editMip(int lod)
116 return const_cast<GGLSurface&>(mip(lod));
119 status_t EGLTextureObject::setSurface(GGLSurface const* s)
121 // XXX: glFlush() on 's'
122 if (mSize && surface.data) {
129 // we should keep the crop_rect, but it's delicate because
130 // the new size of the surface could make it invalid.
131 // so for now, we just loose it.
132 memset(crop_rect, 0, sizeof(crop_rect));
134 // it would be nice if we could keep the generate_mipmap flag,
135 // we would have to generate them right now though.
136 generate_mipmap = GL_FALSE;
139 mSize = 0; // we don't own this surface
146 status_t EGLTextureObject::setImage(ANativeWindowBuffer* native_buffer)
149 sur.version = sizeof(GGLSurface);
150 sur.width = native_buffer->width;
151 sur.height= native_buffer->height;
152 sur.stride= native_buffer->stride;
153 sur.format= native_buffer->format;
156 buffer = native_buffer;
160 status_t EGLTextureObject::reallocate(
161 GLint level, int w, int h, int s,
162 int format, int compressedFormat, int bpr)
164 const size_t size = h * bpr;
167 if (size!=mSize || !surface.data) {
168 if (mSize && surface.data) {
171 surface.data = (GGLubyte*)malloc(size);
179 surface.version = sizeof(GGLSurface);
183 surface.format = format;
184 surface.compressedFormat = compressedFormat;
192 if (allocateMipmaps() != NO_ERROR)
196 ALOGW_IF(level-1 >= mNumExtraLod,
197 "specifying mipmap level %d, but # of level is %d",
198 level, mNumExtraLod+1);
200 GGLSurface& mipmap = editMip(level);
204 mipmap.data = (GGLubyte*)malloc(size);
206 memset(&mipmap, 0, sizeof(GGLSurface));
211 mipmap.version = sizeof(GGLSurface);
215 mipmap.format = format;
216 mipmap.compressedFormat = compressedFormat;
218 // check if the texture is complete
220 const GGLSurface* prev = &surface;
221 for (int i=0 ; i<mNumExtraLod ; i++) {
222 const GGLSurface* curr = mMipmaps + i;
223 if (curr->format != surface.format) {
228 uint32_t w = (prev->width >> 1) ? : 1;
229 uint32_t h = (prev->height >> 1) ? : 1;
230 if (w != curr->width || h != curr->height) {
240 // ----------------------------------------------------------------------------
242 EGLSurfaceManager::EGLSurfaceManager()
247 EGLSurfaceManager::~EGLSurfaceManager()
249 // everything gets freed automatically here...
252 sp<EGLTextureObject> EGLSurfaceManager::createTexture(GLuint name)
254 sp<EGLTextureObject> result;
256 Mutex::Autolock _l(mLock);
257 if (mTextures.indexOfKey(name) >= 0)
258 return result; // already exists!
260 result = new EGLTextureObject();
262 status_t err = mTextures.add(name, result);
269 sp<EGLTextureObject> EGLSurfaceManager::removeTexture(GLuint name)
271 Mutex::Autolock _l(mLock);
272 const ssize_t index = mTextures.indexOfKey(name);
274 sp<EGLTextureObject> result(mTextures.valueAt(index));
275 mTextures.removeItemsAt(index);
281 sp<EGLTextureObject> EGLSurfaceManager::replaceTexture(GLuint name)
283 sp<EGLTextureObject> tex;
284 Mutex::Autolock _l(mLock);
285 const ssize_t index = mTextures.indexOfKey(name);
287 const sp<EGLTextureObject>& old = mTextures.valueAt(index);
288 const uint32_t refs = old->getStrongCount();
289 if (ggl_likely(refs == 1)) {
290 // we're the only owner
293 // keep the texture's parameters
294 tex = new EGLTextureObject();
295 tex->copyParameters(old);
296 mTextures.removeItemsAt(index);
297 mTextures.add(name, tex);
303 void EGLSurfaceManager::deleteTextures(GLsizei n, const GLuint *tokens)
306 Mutex::Autolock _l(mLock);
307 for (GLsizei i=0 ; i<n ; i++) {
308 const GLuint t(*tokens++);
310 mTextures.removeItem(t);
315 sp<EGLTextureObject> EGLSurfaceManager::texture(GLuint name)
317 Mutex::Autolock _l(mLock);
318 const ssize_t index = mTextures.indexOfKey(name);
320 return mTextures.valueAt(index);
324 // ----------------------------------------------------------------------------
325 }; // namespace android