• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
EGLTextureObject()27 EGLTextureObject::EGLTextureObject()
28     : mSize(0)
29 {
30     init();
31 }
32 
~EGLTextureObject()33 EGLTextureObject::~EGLTextureObject()
34 {
35     if (!direct) {
36         if (mSize && surface.data)
37             free(surface.data);
38         if (mMipmaps)
39             freeMipmaps();
40     }
41 }
42 
init()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 
copyParameters(const sp<EGLTextureObject> & old)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 
allocateMipmaps()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 
freeMipmaps()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 
mip(int lod) const108 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 
editMip(int lod)116 GGLSurface& EGLTextureObject::editMip(int lod)
117 {
118     return const_cast<GGLSurface&>(mip(lod));
119 }
120 
setSurface(GGLSurface const * s)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 
setImage(ANativeWindowBuffer * native_buffer)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 
reallocate(GLint level,int w,int h,int s,int format,int compressedFormat,int bpr)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 
EGLSurfaceManager()244 EGLSurfaceManager::EGLSurfaceManager()
245     : TokenManager()
246 {
247 }
248 
~EGLSurfaceManager()249 EGLSurfaceManager::~EGLSurfaceManager()
250 {
251     // everything gets freed automatically here...
252 }
253 
createTexture(GLuint name)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 
removeTexture(GLuint name)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 
replaceTexture(GLuint name)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 
deleteTextures(GLsizei n,const GLuint * tokens)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 
texture(GLuint name)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