blob: f927de95ecae155187750505565ae047a6ca0c31 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
2 ** Copyright 2006, The Android Open Source Project
3 **
Mathias Agopian076b1cc2009-04-10 14:24:30 -07004 ** 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
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08007 **
Mathias Agopian076b1cc2009-04-10 14:24:30 -07008 ** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08009 **
Mathias Agopian076b1cc2009-04-10 14:24:30 -070010 ** 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
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080014 ** limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include "context.h"
20#include "TextureObjectManager.h"
21
22namespace android {
23// ----------------------------------------------------------------------------
24
25EGLTextureObject::EGLTextureObject()
26 : mCount(0), mSize(0)
27{
28 init();
29}
30
31EGLTextureObject::~EGLTextureObject()
32{
33 if (!direct) {
34 if (mSize && surface.data)
35 free(surface.data);
36 if (mMipmaps)
37 freeMipmaps();
38 }
39}
40
41void EGLTextureObject::init()
42{
43 memset(&surface, 0, sizeof(surface));
44 surface.version = sizeof(surface);
45 mMipmaps = 0;
46 mNumExtraLod = 0;
47 mIsComplete = false;
48 wraps = GL_REPEAT;
49 wrapt = GL_REPEAT;
50 min_filter = GL_LINEAR;
51 mag_filter = GL_LINEAR;
52 internalformat = 0;
53 memset(crop_rect, 0, sizeof(crop_rect));
54 generate_mipmap = GL_FALSE;
55 direct = GL_FALSE;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070056#ifdef LIBAGL_USE_GRALLOC_COPYBITS
57 copybits_fd = -1;
58#endif // LIBAGL_USE_GRALLOC_COPYBITS
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080059}
60
61void 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
72status_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
94void 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
108const 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
116GGLSurface& EGLTextureObject::editMip(int lod)
117{
118 return const_cast<GGLSurface&>(mip(lod));
119}
120
121status_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
130 // we should keep the crop_rect, but it's delicate because
131 // the new size of the surface could make it invalid.
132 // so for now, we just loose it.
133 memset(crop_rect, 0, sizeof(crop_rect));
134
135 // it would be nice if we could keep the generate_mipmap flag,
136 // we would have to generate them right now though.
137 generate_mipmap = GL_FALSE;
138
139 direct = GL_TRUE;
140 mSize = 0; // we don't own this surface
141 if (mMipmaps)
142 freeMipmaps();
143 mIsComplete = true;
144 return NO_ERROR;
145}
146
147status_t EGLTextureObject::reallocate(
148 GLint level, int w, int h, int s,
149 int format, int compressedFormat, int bpr)
150{
151 const size_t size = h * bpr;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700152 if (level == 0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800153 {
154 if (size!=mSize || !surface.data) {
155 if (mSize && surface.data) {
156 free(surface.data);
157 }
158 surface.data = (GGLubyte*)malloc(size);
159 if (!surface.data) {
160 mSize = 0;
161 mIsComplete = false;
162 return NO_MEMORY;
163 }
164 mSize = size;
165 }
166 surface.version = sizeof(GGLSurface);
167 surface.width = w;
168 surface.height = h;
169 surface.stride = s;
170 surface.format = format;
171 surface.compressedFormat = compressedFormat;
172 if (mMipmaps)
173 freeMipmaps();
174 mIsComplete = true;
175 }
176 else
177 {
178 if (!mMipmaps) {
179 if (allocateMipmaps() != NO_ERROR)
180 return NO_MEMORY;
181 }
182
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700183 LOGW_IF(level-1 >= mNumExtraLod,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800184 "specifying mipmap level %d, but # of level is %d",
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700185 level, mNumExtraLod+1);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800186
187 GGLSurface& mipmap = editMip(level);
188 if (mipmap.data)
189 free(mipmap.data);
190
191 mipmap.data = (GGLubyte*)malloc(size);
192 if (!mipmap.data) {
193 memset(&mipmap, 0, sizeof(GGLSurface));
194 mIsComplete = false;
195 return NO_MEMORY;
196 }
197
198 mipmap.version = sizeof(GGLSurface);
199 mipmap.width = w;
200 mipmap.height = h;
201 mipmap.stride = s;
202 mipmap.format = format;
203 mipmap.compressedFormat = compressedFormat;
204
205 // check if the texture is complete
206 mIsComplete = true;
207 const GGLSurface* prev = &surface;
208 for (int i=0 ; i<mNumExtraLod ; i++) {
209 const GGLSurface* curr = mMipmaps + i;
210 if (curr->format != surface.format) {
211 mIsComplete = false;
212 break;
213 }
214
215 uint32_t w = (prev->width >> 1) ? : 1;
216 uint32_t h = (prev->height >> 1) ? : 1;
217 if (w != curr->width || h != curr->height) {
218 mIsComplete = false;
219 break;
220 }
221 prev = curr;
222 }
223 }
224 return NO_ERROR;
225}
226
227// ----------------------------------------------------------------------------
228
229EGLSurfaceManager::EGLSurfaceManager()
230 : TokenManager(), mCount(0)
231{
232}
233
234EGLSurfaceManager::~EGLSurfaceManager()
235{
236 // everything gets freed automatically here...
237}
238
239sp<EGLTextureObject> EGLSurfaceManager::createTexture(GLuint name)
240{
241 sp<EGLTextureObject> result;
242
243 Mutex::Autolock _l(mLock);
244 if (mTextures.indexOfKey(name) >= 0)
245 return result; // already exists!
246
247 result = new EGLTextureObject();
248
249 status_t err = mTextures.add(name, result);
250 if (err < 0)
251 result.clear();
252
253 return result;
254}
255
256sp<EGLTextureObject> EGLSurfaceManager::removeTexture(GLuint name)
257{
258 Mutex::Autolock _l(mLock);
259 const ssize_t index = mTextures.indexOfKey(name);
260 if (index >= 0) {
261 sp<EGLTextureObject> result(mTextures.valueAt(index));
262 mTextures.removeItemsAt(index);
263 return result;
264 }
265 return 0;
266}
267
268sp<EGLTextureObject> EGLSurfaceManager::replaceTexture(GLuint name)
269{
270 sp<EGLTextureObject> tex;
271 Mutex::Autolock _l(mLock);
272 const ssize_t index = mTextures.indexOfKey(name);
273 if (index >= 0) {
274 const sp<EGLTextureObject>& old = mTextures.valueAt(index);
275 const uint32_t refs = old->getStrongCount();
276 if (ggl_likely(refs == 1)) {
277 // we're the only owner
278 tex = old;
279 } else {
280 // keep the texture's parameters
281 tex = new EGLTextureObject();
282 tex->copyParameters(old);
283 mTextures.removeItemsAt(index);
284 mTextures.add(name, tex);
285 }
286 }
287 return tex;
288}
289
290void EGLSurfaceManager::deleteTextures(GLsizei n, const GLuint *tokens)
291{
292 // free all textures
293 Mutex::Autolock _l(mLock);
294 for (GLsizei i=0 ; i<n ; i++) {
295 const GLuint t(*tokens++);
296 if (t) {
297 mTextures.removeItem(t);
298 }
299 }
300}
301
302sp<EGLTextureObject> EGLSurfaceManager::texture(GLuint name)
303{
304 Mutex::Autolock _l(mLock);
305 const ssize_t index = mTextures.indexOfKey(name);
306 if (index >= 0)
307 return mTextures.valueAt(index);
308 return 0;
309}
310
311// ----------------------------------------------------------------------------
312}; // namespace android