• 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 #ifdef LIBAGL_USE_GRALLOC_COPYBITS
59     try_copybit = false;
60 #endif // LIBAGL_USE_GRALLOC_COPYBITS
61     buffer = 0;
62 }
63 
copyParameters(const sp<EGLTextureObject> & old)64 void 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 
allocateMipmaps()75 status_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 
freeMipmaps()97 void 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 
mip(int lod) const111 const 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 
editMip(int lod)119 GGLSurface& EGLTextureObject::editMip(int lod)
120 {
121     return const_cast<GGLSurface&>(mip(lod));
122 }
123 
setSurface(GGLSurface const * s)124 status_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 
setImage(android_native_buffer_t * native_buffer)151 status_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 
reallocate(GLint level,int w,int h,int s,int format,int compressedFormat,int bpr)165 status_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 
EGLSurfaceManager()247 EGLSurfaceManager::EGLSurfaceManager()
248     : TokenManager()
249 {
250 }
251 
~EGLSurfaceManager()252 EGLSurfaceManager::~EGLSurfaceManager()
253 {
254     // everything gets freed automatically here...
255 }
256 
createTexture(GLuint name)257 sp<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 
removeTexture(GLuint name)274 sp<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 
replaceTexture(GLuint name)286 sp<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 
deleteTextures(GLsizei n,const GLuint * tokens)308 void 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 
texture(GLuint name)320 sp<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