• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libs/opengles/texture.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include "context.h"
21 #include "fp.h"
22 #include "state.h"
23 #include "texture.h"
24 #include "TextureObjectManager.h"
25 
26 #include <private/ui/android_natives_priv.h>
27 
28 #ifdef LIBAGL_USE_GRALLOC_COPYBITS
29 #include "copybit.h"
30 #endif // LIBAGL_USE_GRALLOC_COPYBITS
31 
32 namespace android {
33 
34 // ----------------------------------------------------------------------------
35 
36 static void bindTextureTmu(
37     ogles_context_t* c, int tmu, GLuint texture, const sp<EGLTextureObject>& tex);
38 
39 static __attribute__((noinline))
40 void generateMipmap(ogles_context_t* c, GLint level);
41 
42 // ----------------------------------------------------------------------------
43 
44 #if 0
45 #pragma mark -
46 #pragma mark Init
47 #endif
48 
ogles_init_texture(ogles_context_t * c)49 void ogles_init_texture(ogles_context_t* c)
50 {
51     c->textures.packAlignment   = 4;
52     c->textures.unpackAlignment = 4;
53 
54     // each context has a default named (0) texture (not shared)
55     c->textures.defaultTexture = new EGLTextureObject();
56     c->textures.defaultTexture->incStrong(c);
57 
58     // bind the default texture to each texture unit
59     for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
60         bindTextureTmu(c, i, 0, c->textures.defaultTexture);
61         memset(c->current.texture[i].v, 0, sizeof(vec4_t));
62         c->current.texture[i].Q = 0x10000;
63     }
64 }
65 
ogles_uninit_texture(ogles_context_t * c)66 void ogles_uninit_texture(ogles_context_t* c)
67 {
68     if (c->textures.ggl)
69         gglUninit(c->textures.ggl);
70     c->textures.defaultTexture->decStrong(c);
71     for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
72         if (c->textures.tmu[i].texture)
73             c->textures.tmu[i].texture->decStrong(c);
74     }
75 }
76 
77 static __attribute__((noinline))
validate_tmu(ogles_context_t * c,int i)78 void validate_tmu(ogles_context_t* c, int i)
79 {
80     texture_unit_t& u(c->textures.tmu[i]);
81     if (u.dirty) {
82         u.dirty = 0;
83         c->rasterizer.procs.activeTexture(c, i);
84         c->rasterizer.procs.bindTexture(c, &(u.texture->surface));
85         c->rasterizer.procs.texGeni(c, GGL_S,
86                 GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC);
87         c->rasterizer.procs.texGeni(c, GGL_T,
88                 GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC);
89         c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D,
90                 GGL_TEXTURE_WRAP_S, u.texture->wraps);
91         c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D,
92                 GGL_TEXTURE_WRAP_T, u.texture->wrapt);
93         c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D,
94                 GGL_TEXTURE_MIN_FILTER, u.texture->min_filter);
95         c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D,
96                 GGL_TEXTURE_MAG_FILTER, u.texture->mag_filter);
97 
98         // disable this texture unit if it's not complete
99         if (!u.texture->isComplete()) {
100             c->rasterizer.procs.disable(c, GGL_TEXTURE_2D);
101         }
102     }
103 }
104 
ogles_validate_texture(ogles_context_t * c)105 void ogles_validate_texture(ogles_context_t* c)
106 {
107     for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
108         if (c->rasterizer.state.texture[i].enable)
109             validate_tmu(c, i);
110     }
111     c->rasterizer.procs.activeTexture(c, c->textures.active);
112 }
113 
114 static
invalidate_texture(ogles_context_t * c,int tmu,uint8_t flags=0xFF)115 void invalidate_texture(ogles_context_t* c, int tmu, uint8_t flags = 0xFF) {
116     c->textures.tmu[tmu].dirty = flags;
117 }
118 
119 /*
120  * If the active textures are EGLImage, they need to be locked before
121  * they can be used.
122  *
123  * FIXME: code below is far from being optimal
124  *
125  */
126 
ogles_lock_textures(ogles_context_t * c)127 void ogles_lock_textures(ogles_context_t* c)
128 {
129     for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
130         if (c->rasterizer.state.texture[i].enable) {
131             texture_unit_t& u(c->textures.tmu[i]);
132             android_native_buffer_t* native_buffer = u.texture->buffer;
133             if (native_buffer) {
134                 c->rasterizer.procs.activeTexture(c, i);
135                 hw_module_t const* pModule;
136                 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule))
137                     continue;
138 
139                 gralloc_module_t const* module =
140                     reinterpret_cast<gralloc_module_t const*>(pModule);
141 
142                 void* vaddr;
143                 int err = module->lock(module, native_buffer->handle,
144                         GRALLOC_USAGE_SW_READ_OFTEN,
145                         0, 0, native_buffer->width, native_buffer->height,
146                         &vaddr);
147 
148                 u.texture->setImageBits(vaddr);
149                 c->rasterizer.procs.bindTexture(c, &(u.texture->surface));
150             }
151         }
152     }
153 }
154 
ogles_unlock_textures(ogles_context_t * c)155 void ogles_unlock_textures(ogles_context_t* c)
156 {
157     for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
158         if (c->rasterizer.state.texture[i].enable) {
159             texture_unit_t& u(c->textures.tmu[i]);
160             android_native_buffer_t* native_buffer = u.texture->buffer;
161             if (native_buffer) {
162                 c->rasterizer.procs.activeTexture(c, i);
163                 hw_module_t const* pModule;
164                 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule))
165                     continue;
166 
167                 gralloc_module_t const* module =
168                     reinterpret_cast<gralloc_module_t const*>(pModule);
169 
170                 module->unlock(module, native_buffer->handle);
171                 u.texture->setImageBits(NULL);
172                 c->rasterizer.procs.bindTexture(c, &(u.texture->surface));
173             }
174         }
175     }
176     c->rasterizer.procs.activeTexture(c, c->textures.active);
177 }
178 
179 // ----------------------------------------------------------------------------
180 #if 0
181 #pragma mark -
182 #pragma mark Format conversion
183 #endif
184 
185 static uint32_t gl2format_table[6][4] = {
186     // BYTE, 565, 4444, 5551
187     { GGL_PIXEL_FORMAT_A_8,
188       0, 0, 0 },                        // GL_ALPHA
189     { GGL_PIXEL_FORMAT_RGB_888,
190       GGL_PIXEL_FORMAT_RGB_565,
191       0, 0 },                           // GL_RGB
192     { GGL_PIXEL_FORMAT_RGBA_8888,
193       0,
194       GGL_PIXEL_FORMAT_RGBA_4444,
195       GGL_PIXEL_FORMAT_RGBA_5551 },     // GL_RGBA
196     { GGL_PIXEL_FORMAT_L_8,
197       0, 0, 0 },                        // GL_LUMINANCE
198     { GGL_PIXEL_FORMAT_LA_88,
199       0, 0, 0 },                        // GL_LUMINANCE_ALPHA
200 };
201 
convertGLPixelFormat(GLint format,GLenum type)202 static int32_t convertGLPixelFormat(GLint format, GLenum type)
203 {
204     int32_t fi = -1;
205     int32_t ti = -1;
206     switch (format) {
207     case GL_ALPHA:              fi = 0;     break;
208     case GL_RGB:                fi = 1;     break;
209     case GL_RGBA:               fi = 2;     break;
210     case GL_LUMINANCE:          fi = 3;     break;
211     case GL_LUMINANCE_ALPHA:    fi = 4;     break;
212     }
213     switch (type) {
214     case GL_UNSIGNED_BYTE:          ti = 0; break;
215     case GL_UNSIGNED_SHORT_5_6_5:   ti = 1; break;
216     case GL_UNSIGNED_SHORT_4_4_4_4: ti = 2; break;
217     case GL_UNSIGNED_SHORT_5_5_5_1: ti = 3; break;
218     }
219     if (fi==-1 || ti==-1)
220         return 0;
221     return gl2format_table[fi][ti];
222 }
223 
224 // ----------------------------------------------------------------------------
225 
validFormatType(ogles_context_t * c,GLenum format,GLenum type)226 static GLenum validFormatType(ogles_context_t* c, GLenum format, GLenum type)
227 {
228     GLenum error = 0;
229     if (format<GL_ALPHA || format>GL_LUMINANCE_ALPHA) {
230         error = GL_INVALID_ENUM;
231     }
232     if (type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT_4_4_4_4 &&
233         type != GL_UNSIGNED_SHORT_5_5_5_1 && type != GL_UNSIGNED_SHORT_5_6_5) {
234         error = GL_INVALID_ENUM;
235     }
236     if (type == GL_UNSIGNED_SHORT_5_6_5 && format != GL_RGB) {
237         error = GL_INVALID_OPERATION;
238     }
239     if ((type == GL_UNSIGNED_SHORT_4_4_4_4 ||
240          type == GL_UNSIGNED_SHORT_5_5_5_1)  && format != GL_RGBA) {
241         error = GL_INVALID_OPERATION;
242     }
243     if (error) {
244         ogles_error(c, error);
245     }
246     return error;
247 }
248 
249 // ----------------------------------------------------------------------------
250 
getRasterizer(ogles_context_t * c)251 GGLContext* getRasterizer(ogles_context_t* c)
252 {
253     GGLContext* ggl = c->textures.ggl;
254     if (ggl_unlikely(!ggl)) {
255         // this is quite heavy the first time...
256         gglInit(&ggl);
257         if (!ggl) {
258             return 0;
259         }
260         GGLfixed colors[4] = { 0, 0, 0, 0x10000 };
261         c->textures.ggl = ggl;
262         ggl->activeTexture(ggl, 0);
263         ggl->enable(ggl, GGL_TEXTURE_2D);
264         ggl->texEnvi(ggl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE);
265         ggl->disable(ggl, GGL_DITHER);
266         ggl->shadeModel(ggl, GGL_FLAT);
267         ggl->color4xv(ggl, colors);
268     }
269     return ggl;
270 }
271 
272 static __attribute__((noinline))
copyPixels(ogles_context_t * c,const GGLSurface & dst,GLint xoffset,GLint yoffset,const GGLSurface & src,GLint x,GLint y,GLsizei w,GLsizei h)273 int copyPixels(
274         ogles_context_t* c,
275         const GGLSurface& dst,
276         GLint xoffset, GLint yoffset,
277         const GGLSurface& src,
278         GLint x, GLint y, GLsizei w, GLsizei h)
279 {
280     if ((dst.format == src.format) &&
281         (dst.stride == src.stride) &&
282         (dst.width == src.width) &&
283         (dst.height == src.height) &&
284         (dst.stride > 0) &&
285         ((x|y) == 0) &&
286         ((xoffset|yoffset) == 0))
287     {
288         // this is a common case...
289         const GGLFormat& pixelFormat(c->rasterizer.formats[src.format]);
290         const size_t size = src.height * src.stride * pixelFormat.size;
291         memcpy(dst.data, src.data, size);
292         return 0;
293     }
294 
295     // use pixel-flinger to handle all the conversions
296     GGLContext* ggl = getRasterizer(c);
297     if (!ggl) {
298         // the only reason this would fail is because we ran out of memory
299         return GL_OUT_OF_MEMORY;
300     }
301 
302     ggl->colorBuffer(ggl, &dst);
303     ggl->bindTexture(ggl, &src);
304     ggl->texCoord2i(ggl, x-xoffset, y-yoffset);
305     ggl->recti(ggl, xoffset, yoffset, xoffset+w, yoffset+h);
306     return 0;
307 }
308 
309 // ----------------------------------------------------------------------------
310 
311 static __attribute__((noinline))
getAndBindActiveTextureObject(ogles_context_t * c)312 sp<EGLTextureObject> getAndBindActiveTextureObject(ogles_context_t* c)
313 {
314     sp<EGLTextureObject> tex;
315     const int active = c->textures.active;
316     const GLuint name = c->textures.tmu[active].name;
317 
318     // free the reference to the previously bound object
319     texture_unit_t& u(c->textures.tmu[active]);
320     if (u.texture)
321         u.texture->decStrong(c);
322 
323     if (name == 0) {
324         // 0 is our local texture object, not shared with anyone.
325         // But it affects all bound TMUs immediately.
326         // (we need to invalidate all units bound to this texture object)
327         tex = c->textures.defaultTexture;
328         for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
329             if (c->textures.tmu[i].texture == tex.get())
330                 invalidate_texture(c, i);
331         }
332     } else {
333         // get a new texture object for that name
334         tex = c->surfaceManager->replaceTexture(name);
335     }
336 
337     // bind this texture to the current active texture unit
338     // and add a reference to this texture object
339     u.texture = tex.get();
340     u.texture->incStrong(c);
341     u.name = name;
342     invalidate_texture(c, active);
343     return tex;
344 }
345 
bindTextureTmu(ogles_context_t * c,int tmu,GLuint texture,const sp<EGLTextureObject> & tex)346 void bindTextureTmu(
347     ogles_context_t* c, int tmu, GLuint texture, const sp<EGLTextureObject>& tex)
348 {
349     if (tex.get() == c->textures.tmu[tmu].texture)
350         return;
351 
352     // free the reference to the previously bound object
353     texture_unit_t& u(c->textures.tmu[tmu]);
354     if (u.texture)
355         u.texture->decStrong(c);
356 
357     // bind this texture to the current active texture unit
358     // and add a reference to this texture object
359     u.texture = tex.get();
360     u.texture->incStrong(c);
361     u.name = texture;
362     invalidate_texture(c, tmu);
363 }
364 
createTextureSurface(ogles_context_t * c,GGLSurface ** outSurface,int32_t * outSize,GLint level,GLenum format,GLenum type,GLsizei width,GLsizei height,GLenum compressedFormat=0)365 int createTextureSurface(ogles_context_t* c,
366         GGLSurface** outSurface, int32_t* outSize, GLint level,
367         GLenum format, GLenum type, GLsizei width, GLsizei height,
368         GLenum compressedFormat = 0)
369 {
370     // find out which texture is bound to the current unit
371     const int active = c->textures.active;
372     const GLuint name = c->textures.tmu[active].name;
373 
374     // convert the pixelformat to one we can handle
375     const int32_t formatIdx = convertGLPixelFormat(format, type);
376     if (formatIdx == 0) { // we don't know what to do with this
377         return GL_INVALID_OPERATION;
378     }
379 
380     // figure out the size we need as well as the stride
381     const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]);
382     const int32_t align = c->textures.unpackAlignment-1;
383     const int32_t bpr = ((width * pixelFormat.size) + align) & ~align;
384     const size_t size = bpr * height;
385     const int32_t stride = bpr / pixelFormat.size;
386 
387     if (level > 0) {
388         const int active = c->textures.active;
389         EGLTextureObject* tex = c->textures.tmu[active].texture;
390         status_t err = tex->reallocate(level,
391                 width, height, stride, formatIdx, compressedFormat, bpr);
392         if (err != NO_ERROR)
393             return GL_OUT_OF_MEMORY;
394         GGLSurface& surface = tex->editMip(level);
395         *outSurface = &surface;
396         *outSize = size;
397         return 0;
398     }
399 
400     sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c);
401     status_t err = tex->reallocate(level,
402             width, height, stride, formatIdx, compressedFormat, bpr);
403     if (err != NO_ERROR)
404         return GL_OUT_OF_MEMORY;
405 
406     tex->internalformat = format;
407     *outSurface = &tex->surface;
408     *outSize = size;
409     return 0;
410 }
411 
dataSizePalette4(int numLevels,int width,int height,int format)412 static size_t dataSizePalette4(int numLevels, int width, int height, int format)
413 {
414     int indexBits = 8;
415     int entrySize = 0;
416     switch (format) {
417     case GL_PALETTE4_RGB8_OES:
418         indexBits = 4;
419         /* FALLTHROUGH */
420     case GL_PALETTE8_RGB8_OES:
421         entrySize = 3;
422         break;
423 
424     case GL_PALETTE4_RGBA8_OES:
425         indexBits = 4;
426         /* FALLTHROUGH */
427     case GL_PALETTE8_RGBA8_OES:
428         entrySize = 4;
429         break;
430 
431     case GL_PALETTE4_R5_G6_B5_OES:
432     case GL_PALETTE4_RGBA4_OES:
433     case GL_PALETTE4_RGB5_A1_OES:
434         indexBits = 4;
435         /* FALLTHROUGH */
436     case GL_PALETTE8_R5_G6_B5_OES:
437     case GL_PALETTE8_RGBA4_OES:
438     case GL_PALETTE8_RGB5_A1_OES:
439         entrySize = 2;
440         break;
441     }
442 
443     size_t size = (1 << indexBits) * entrySize; // palette size
444 
445     for (int i=0 ; i< numLevels ; i++) {
446         int w = (width  >> i) ? : 1;
447         int h = (height >> i) ? : 1;
448         int levelSize = h * ((w * indexBits) / 8) ? : 1;
449         size += levelSize;
450     }
451 
452     return size;
453 }
454 
decodePalette4(const GLvoid * data,int level,int width,int height,void * surface,int stride,int format)455 static void decodePalette4(const GLvoid *data, int level, int width, int height,
456                            void *surface, int stride, int format)
457 
458 {
459     int indexBits = 8;
460     int entrySize = 0;
461     switch (format) {
462     case GL_PALETTE4_RGB8_OES:
463         indexBits = 4;
464         /* FALLTHROUGH */
465     case GL_PALETTE8_RGB8_OES:
466         entrySize = 3;
467         break;
468 
469     case GL_PALETTE4_RGBA8_OES:
470         indexBits = 4;
471         /* FALLTHROUGH */
472     case GL_PALETTE8_RGBA8_OES:
473         entrySize = 4;
474         break;
475 
476     case GL_PALETTE4_R5_G6_B5_OES:
477     case GL_PALETTE4_RGBA4_OES:
478     case GL_PALETTE4_RGB5_A1_OES:
479         indexBits = 4;
480         /* FALLTHROUGH */
481     case GL_PALETTE8_R5_G6_B5_OES:
482     case GL_PALETTE8_RGBA4_OES:
483     case GL_PALETTE8_RGB5_A1_OES:
484         entrySize = 2;
485         break;
486     }
487 
488     const int paletteSize = (1 << indexBits) * entrySize;
489 
490     uint8_t const* pixels = (uint8_t *)data + paletteSize;
491     for (int i=0 ; i<level ; i++) {
492         int w = (width  >> i) ? : 1;
493         int h = (height >> i) ? : 1;
494         pixels += h * ((w * indexBits) / 8);
495     }
496     width  = (width  >> level) ? : 1;
497     height = (height >> level) ? : 1;
498 
499     if (entrySize == 2) {
500         uint8_t const* const palette = (uint8_t*)data;
501         for (int y=0 ; y<height ; y++) {
502             uint8_t* p = (uint8_t*)surface + y*stride*2;
503             if (indexBits == 8) {
504                 for (int x=0 ; x<width ; x++) {
505                     int index = 2 * (*pixels++);
506                     *p++ = palette[index + 0];
507                     *p++ = palette[index + 1];
508                 }
509             } else {
510                 for (int x=0 ; x<width ; x+=2) {
511                     int v = *pixels++;
512                     int index = 2 * (v >> 4);
513                     *p++ = palette[index + 0];
514                     *p++ = palette[index + 1];
515                     if (x+1 < width) {
516                         index = 2 * (v & 0xF);
517                         *p++ = palette[index + 0];
518                         *p++ = palette[index + 1];
519                     }
520                 }
521             }
522         }
523     } else if (entrySize == 3) {
524         uint8_t const* const palette = (uint8_t*)data;
525         for (int y=0 ; y<height ; y++) {
526             uint8_t* p = (uint8_t*)surface + y*stride*3;
527             if (indexBits == 8) {
528                 for (int x=0 ; x<width ; x++) {
529                     int index = 3 * (*pixels++);
530                     *p++ = palette[index + 0];
531                     *p++ = palette[index + 1];
532                     *p++ = palette[index + 2];
533                 }
534             } else {
535                 for (int x=0 ; x<width ; x+=2) {
536                     int v = *pixels++;
537                     int index = 3 * (v >> 4);
538                     *p++ = palette[index + 0];
539                     *p++ = palette[index + 1];
540                     *p++ = palette[index + 2];
541                     if (x+1 < width) {
542                         index = 3 * (v & 0xF);
543                         *p++ = palette[index + 0];
544                         *p++ = palette[index + 1];
545                         *p++ = palette[index + 2];
546                     }
547                 }
548             }
549         }
550     } else if (entrySize == 4) {
551         uint8_t const* const palette = (uint8_t*)data;
552         for (int y=0 ; y<height ; y++) {
553             uint8_t* p = (uint8_t*)surface + y*stride*4;
554             if (indexBits == 8) {
555                 for (int x=0 ; x<width ; x++) {
556                     int index = 4 * (*pixels++);
557                     *p++ = palette[index + 0];
558                     *p++ = palette[index + 1];
559                     *p++ = palette[index + 2];
560                     *p++ = palette[index + 3];
561                 }
562             } else {
563                 for (int x=0 ; x<width ; x+=2) {
564                     int v = *pixels++;
565                     int index = 4 * (v >> 4);
566                     *p++ = palette[index + 0];
567                     *p++ = palette[index + 1];
568                     *p++ = palette[index + 2];
569                     *p++ = palette[index + 3];
570                     if (x+1 < width) {
571                         index = 4 * (v & 0xF);
572                         *p++ = palette[index + 0];
573                         *p++ = palette[index + 1];
574                         *p++ = palette[index + 2];
575                         *p++ = palette[index + 3];
576                     }
577                 }
578             }
579         }
580     }
581 }
582 
583 
584 
585 static __attribute__((noinline))
set_depth_and_fog(ogles_context_t * c,GLint z)586 void set_depth_and_fog(ogles_context_t* c, GLint z)
587 {
588     const uint32_t enables = c->rasterizer.state.enables;
589     // we need to compute Zw
590     int32_t iterators[3];
591     iterators[1] = iterators[2] = 0;
592     GGLfixed Zw;
593     GGLfixed n = gglFloatToFixed(c->transforms.vpt.zNear);
594     GGLfixed f = gglFloatToFixed(c->transforms.vpt.zFar);
595     if (z<=0)       Zw = n;
596     else if (z>=1)  Zw = f;
597     else            Zw = gglMulAddx(z, (f-n), n);
598     if (enables & GGL_ENABLE_FOG) {
599         // set up fog if needed...
600         iterators[0] = c->fog.fog(c, Zw);
601         c->rasterizer.procs.fogGrad3xv(c, iterators);
602     }
603     if (enables & GGL_ENABLE_DEPTH_TEST) {
604         // set up z-test if needed...
605         int32_t z = (Zw & ~(Zw>>31));
606         if (z >= 0x10000)
607             z = 0xFFFF;
608         iterators[0] = (z << 16) | z;
609         c->rasterizer.procs.zGrad3xv(c, iterators);
610     }
611 }
612 
613 // ----------------------------------------------------------------------------
614 #if 0
615 #pragma mark -
616 #pragma mark Generate mimaps
617 #endif
618 
619 extern status_t buildAPyramid(ogles_context_t* c, EGLTextureObject* tex);
620 
generateMipmap(ogles_context_t * c,GLint level)621 void generateMipmap(ogles_context_t* c, GLint level)
622 {
623     if (level == 0) {
624         const int active = c->textures.active;
625         EGLTextureObject* tex = c->textures.tmu[active].texture;
626         if (tex->generate_mipmap) {
627             if (buildAPyramid(c, tex) != NO_ERROR) {
628                 ogles_error(c, GL_OUT_OF_MEMORY);
629                 return;
630             }
631         }
632     }
633 }
634 
635 
texParameterx(GLenum target,GLenum pname,GLfixed param,ogles_context_t * c)636 static void texParameterx(
637         GLenum target, GLenum pname, GLfixed param, ogles_context_t* c)
638 {
639     if (target != GL_TEXTURE_2D) {
640         ogles_error(c, GL_INVALID_ENUM);
641         return;
642     }
643 
644     EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture;
645     switch (pname) {
646     case GL_TEXTURE_WRAP_S:
647         if ((param == GL_REPEAT) ||
648             (param == GL_CLAMP_TO_EDGE)) {
649             textureObject->wraps = param;
650         } else {
651             goto invalid_enum;
652         }
653         break;
654     case GL_TEXTURE_WRAP_T:
655         if ((param == GL_REPEAT) ||
656             (param == GL_CLAMP_TO_EDGE)) {
657             textureObject->wrapt = param;
658         } else {
659             goto invalid_enum;
660         }
661         break;
662     case GL_TEXTURE_MIN_FILTER:
663         if ((param == GL_NEAREST) ||
664             (param == GL_LINEAR) ||
665             (param == GL_NEAREST_MIPMAP_NEAREST) ||
666             (param == GL_LINEAR_MIPMAP_NEAREST) ||
667             (param == GL_NEAREST_MIPMAP_LINEAR) ||
668             (param == GL_LINEAR_MIPMAP_LINEAR)) {
669             textureObject->min_filter = param;
670         } else {
671             goto invalid_enum;
672         }
673         break;
674     case GL_TEXTURE_MAG_FILTER:
675         if ((param == GL_NEAREST) ||
676             (param == GL_LINEAR)) {
677             textureObject->mag_filter = param;
678         } else {
679             goto invalid_enum;
680         }
681         break;
682     case GL_GENERATE_MIPMAP:
683         textureObject->generate_mipmap = param;
684         break;
685     default:
686 invalid_enum:
687         ogles_error(c, GL_INVALID_ENUM);
688         return;
689     }
690     invalidate_texture(c, c->textures.active);
691 }
692 
693 
694 
drawTexxOESImp(GLfixed x,GLfixed y,GLfixed z,GLfixed w,GLfixed h,ogles_context_t * c)695 static void drawTexxOESImp(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
696         ogles_context_t* c)
697 {
698     ogles_lock_textures(c);
699 
700     const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
701     y = gglIntToFixed(cbSurface.height) - (y + h);
702     w >>= FIXED_BITS;
703     h >>= FIXED_BITS;
704 
705     // set up all texture units
706     for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
707         if (!c->rasterizer.state.texture[i].enable)
708             continue;
709 
710         int32_t texcoords[8];
711         texture_unit_t& u(c->textures.tmu[i]);
712 
713         // validate this tmu (bind, wrap, filter)
714         validate_tmu(c, i);
715         // we CLAMP here, which works with premultiplied (s,t)
716         c->rasterizer.procs.texParameteri(c,
717                 GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_S, GGL_CLAMP);
718         c->rasterizer.procs.texParameteri(c,
719                 GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_T, GGL_CLAMP);
720         u.dirty = 0xFF; // XXX: should be more subtle
721 
722         EGLTextureObject* textureObject = u.texture;
723         const GLint Ucr = textureObject->crop_rect[0] << 16;
724         const GLint Vcr = textureObject->crop_rect[1] << 16;
725         const GLint Wcr = textureObject->crop_rect[2] << 16;
726         const GLint Hcr = textureObject->crop_rect[3] << 16;
727 
728         // computes texture coordinates (pre-multiplied)
729         int32_t dsdx = Wcr / w;   // dsdx =  ((Wcr/w)/Wt)*Wt
730         int32_t dtdy =-Hcr / h;   // dtdy = -((Hcr/h)/Ht)*Ht
731         int32_t s0   = Ucr       - gglMulx(dsdx, x); // s0 = Ucr - x * dsdx
732         int32_t t0   = (Vcr+Hcr) - gglMulx(dtdy, y); // t0 = (Vcr+Hcr) - y*dtdy
733         texcoords[0] = s0;
734         texcoords[1] = dsdx;
735         texcoords[2] = 0;
736         texcoords[3] = t0;
737         texcoords[4] = 0;
738         texcoords[5] = dtdy;
739         texcoords[6] = 0;
740         texcoords[7] = 0;
741         c->rasterizer.procs.texCoordGradScale8xv(c, i, texcoords);
742     }
743 
744     const uint32_t enables = c->rasterizer.state.enables;
745     if (ggl_unlikely(enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)))
746         set_depth_and_fog(c, z);
747 
748     c->rasterizer.procs.activeTexture(c, c->textures.active);
749     c->rasterizer.procs.color4xv(c, c->currentColorClamped.v);
750     c->rasterizer.procs.disable(c, GGL_W_LERP);
751     c->rasterizer.procs.disable(c, GGL_AA);
752     c->rasterizer.procs.shadeModel(c, GL_FLAT);
753     c->rasterizer.procs.recti(c,
754             gglFixedToIntRound(x),
755             gglFixedToIntRound(y),
756             gglFixedToIntRound(x)+w,
757             gglFixedToIntRound(y)+h);
758 
759     ogles_unlock_textures(c);
760 }
761 
drawTexxOES(GLfixed x,GLfixed y,GLfixed z,GLfixed w,GLfixed h,ogles_context_t * c)762 static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
763         ogles_context_t* c)
764 {
765 #ifdef LIBAGL_USE_GRALLOC_COPYBITS
766     if (drawTexiOESWithCopybit(gglFixedToIntRound(x),
767             gglFixedToIntRound(y), gglFixedToIntRound(z),
768             gglFixedToIntRound(w), gglFixedToIntRound(h), c)) {
769         return;
770     }
771 #else
772     // quickly reject empty rects
773     if ((w|h) <= 0)
774         return;
775 #endif
776     drawTexxOESImp(x, y, z, w, h, c);
777 }
778 
drawTexiOES(GLint x,GLint y,GLint z,GLint w,GLint h,ogles_context_t * c)779 static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_context_t* c)
780 {
781     // All coordinates are integer, so if we have only one
782     // texture unit active and no scaling is required
783     // THEN, we can use our special 1:1 mapping
784     // which is a lot faster.
785 
786     if (ggl_likely(c->rasterizer.state.enabled_tmu == 1)) {
787 #ifdef LIBAGL_USE_GRALLOC_COPYBITS
788         if (drawTexiOESWithCopybit(x, y, z, w, h, c)) {
789             return;
790         }
791 #endif
792         const int tmu = 0;
793         texture_unit_t& u(c->textures.tmu[tmu]);
794         EGLTextureObject* textureObject = u.texture;
795         const GLint Wcr = textureObject->crop_rect[2];
796         const GLint Hcr = textureObject->crop_rect[3];
797 
798         if ((w == Wcr) && (h == -Hcr)) {
799 #ifndef LIBAGL_USE_GRALLOC_COPYBITS
800             if ((w|h) <= 0) return; // quickly reject empty rects
801 #endif
802 
803             if (u.dirty) {
804                 c->rasterizer.procs.activeTexture(c, tmu);
805                 c->rasterizer.procs.bindTexture(c, &(u.texture->surface));
806                 c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D,
807                         GGL_TEXTURE_MIN_FILTER, u.texture->min_filter);
808                 c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D,
809                         GGL_TEXTURE_MAG_FILTER, u.texture->mag_filter);
810             }
811             c->rasterizer.procs.texGeni(c, GGL_S,
812                     GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
813             c->rasterizer.procs.texGeni(c, GGL_T,
814                     GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
815             u.dirty = 0xFF; // XXX: should be more subtle
816             c->rasterizer.procs.activeTexture(c, c->textures.active);
817 
818             const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
819             y = cbSurface.height - (y + h);
820             const GLint Ucr = textureObject->crop_rect[0];
821             const GLint Vcr = textureObject->crop_rect[1];
822             const GLint s0  = Ucr - x;
823             const GLint t0  = (Vcr + Hcr) - y;
824 
825             const GLuint tw = textureObject->surface.width;
826             const GLuint th = textureObject->surface.height;
827             if ((uint32_t(s0+x+w) > tw) || (uint32_t(t0+y+h) > th)) {
828                 // The GL spec is unclear about what should happen
829                 // in this case, so we just use the slow case, which
830                 // at least won't crash
831                 goto slow_case;
832             }
833 
834             ogles_lock_textures(c);
835 
836             c->rasterizer.procs.texCoord2i(c, s0, t0);
837             const uint32_t enables = c->rasterizer.state.enables;
838             if (ggl_unlikely(enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)))
839                 set_depth_and_fog(c, z);
840 
841             c->rasterizer.procs.color4xv(c, c->currentColorClamped.v);
842             c->rasterizer.procs.disable(c, GGL_W_LERP);
843             c->rasterizer.procs.disable(c, GGL_AA);
844             c->rasterizer.procs.shadeModel(c, GL_FLAT);
845             c->rasterizer.procs.recti(c, x, y, x+w, y+h);
846 
847             ogles_unlock_textures(c);
848 
849             return;
850         }
851     }
852 
853 slow_case:
854     drawTexxOESImp(
855             gglIntToFixed(x), gglIntToFixed(y), gglIntToFixed(z),
856             gglIntToFixed(w), gglIntToFixed(h),
857             c);
858 }
859 
860 
861 }; // namespace android
862 // ----------------------------------------------------------------------------
863 
864 using namespace android;
865 
866 
867 #if 0
868 #pragma mark -
869 #pragma mark Texture API
870 #endif
871 
glActiveTexture(GLenum texture)872 void glActiveTexture(GLenum texture)
873 {
874     ogles_context_t* c = ogles_context_t::get();
875     if (uint32_t(texture-GL_TEXTURE0) > uint32_t(GGL_TEXTURE_UNIT_COUNT)) {
876         ogles_error(c, GL_INVALID_ENUM);
877         return;
878     }
879     c->textures.active = texture - GL_TEXTURE0;
880     c->rasterizer.procs.activeTexture(c, c->textures.active);
881 }
882 
glBindTexture(GLenum target,GLuint texture)883 void glBindTexture(GLenum target, GLuint texture)
884 {
885     ogles_context_t* c = ogles_context_t::get();
886     if (target != GL_TEXTURE_2D) {
887         ogles_error(c, GL_INVALID_ENUM);
888         return;
889     }
890 
891     // Bind or create a texture
892     sp<EGLTextureObject> tex;
893     if (texture == 0) {
894         // 0 is our local texture object
895         tex = c->textures.defaultTexture;
896     } else {
897         tex = c->surfaceManager->texture(texture);
898         if (ggl_unlikely(tex == 0)) {
899             tex = c->surfaceManager->createTexture(texture);
900             if (tex == 0) {
901                 ogles_error(c, GL_OUT_OF_MEMORY);
902                 return;
903             }
904         }
905     }
906     bindTextureTmu(c, c->textures.active, texture, tex);
907 }
908 
glGenTextures(GLsizei n,GLuint * textures)909 void glGenTextures(GLsizei n, GLuint *textures)
910 {
911     ogles_context_t* c = ogles_context_t::get();
912     if (n<0) {
913         ogles_error(c, GL_INVALID_VALUE);
914         return;
915     }
916     // generate unique (shared) texture names
917     c->surfaceManager->getToken(n, textures);
918 }
919 
glDeleteTextures(GLsizei n,const GLuint * textures)920 void glDeleteTextures(GLsizei n, const GLuint *textures)
921 {
922     ogles_context_t* c = ogles_context_t::get();
923     if (n<0) {
924         ogles_error(c, GL_INVALID_VALUE);
925         return;
926     }
927 
928     // If deleting a bound texture, bind this unit to 0
929     for (int t=0 ; t<GGL_TEXTURE_UNIT_COUNT ; t++) {
930         if (c->textures.tmu[t].name == 0)
931             continue;
932         for (int i=0 ; i<n ; i++) {
933             if (textures[i] && (textures[i] == c->textures.tmu[t].name)) {
934                 // bind this tmu to texture 0
935                 sp<EGLTextureObject> tex(c->textures.defaultTexture);
936                 bindTextureTmu(c, t, 0, tex);
937             }
938         }
939     }
940     c->surfaceManager->deleteTextures(n, textures);
941     c->surfaceManager->recycleTokens(n, textures);
942 }
943 
glMultiTexCoord4f(GLenum target,GLfloat s,GLfloat t,GLfloat r,GLfloat q)944 void glMultiTexCoord4f(
945         GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
946 {
947     ogles_context_t* c = ogles_context_t::get();
948     if (uint32_t(target-GL_TEXTURE0) > uint32_t(GGL_TEXTURE_UNIT_COUNT)) {
949         ogles_error(c, GL_INVALID_ENUM);
950         return;
951     }
952     const int tmu = target-GL_TEXTURE0;
953     c->current.texture[tmu].S = gglFloatToFixed(s);
954     c->current.texture[tmu].T = gglFloatToFixed(t);
955     c->current.texture[tmu].R = gglFloatToFixed(r);
956     c->current.texture[tmu].Q = gglFloatToFixed(q);
957 }
958 
glMultiTexCoord4x(GLenum target,GLfixed s,GLfixed t,GLfixed r,GLfixed q)959 void glMultiTexCoord4x(
960         GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
961 {
962     ogles_context_t* c = ogles_context_t::get();
963     if (uint32_t(target-GL_TEXTURE0) > uint32_t(GGL_TEXTURE_UNIT_COUNT)) {
964         ogles_error(c, GL_INVALID_ENUM);
965         return;
966     }
967     const int tmu = target-GL_TEXTURE0;
968     c->current.texture[tmu].S = s;
969     c->current.texture[tmu].T = t;
970     c->current.texture[tmu].R = r;
971     c->current.texture[tmu].Q = q;
972 }
973 
glPixelStorei(GLenum pname,GLint param)974 void glPixelStorei(GLenum pname, GLint param)
975 {
976     ogles_context_t* c = ogles_context_t::get();
977     if ((pname != GL_PACK_ALIGNMENT) && (pname != GL_UNPACK_ALIGNMENT)) {
978         ogles_error(c, GL_INVALID_ENUM);
979         return;
980     }
981     if ((param<=0 || param>8) || (param & (param-1))) {
982         ogles_error(c, GL_INVALID_VALUE);
983         return;
984     }
985     if (pname == GL_PACK_ALIGNMENT)
986         c->textures.packAlignment = param;
987     if (pname == GL_UNPACK_ALIGNMENT)
988         c->textures.unpackAlignment = param;
989 }
990 
glTexEnvf(GLenum target,GLenum pname,GLfloat param)991 void glTexEnvf(GLenum target, GLenum pname, GLfloat param)
992 {
993     ogles_context_t* c = ogles_context_t::get();
994     c->rasterizer.procs.texEnvi(c, target, pname, GLint(param));
995 }
996 
glTexEnvfv(GLenum target,GLenum pname,const GLfloat * params)997 void glTexEnvfv(
998         GLenum target, GLenum pname, const GLfloat *params)
999 {
1000     ogles_context_t* c = ogles_context_t::get();
1001     if (pname == GL_TEXTURE_ENV_MODE) {
1002         c->rasterizer.procs.texEnvi(c, target, pname, GLint(*params));
1003         return;
1004     }
1005     if (pname == GL_TEXTURE_ENV_COLOR) {
1006         GGLfixed fixed[4];
1007         for (int i=0 ; i<4 ; i++)
1008             fixed[i] = gglFloatToFixed(params[i]);
1009         c->rasterizer.procs.texEnvxv(c, target, pname, fixed);
1010         return;
1011     }
1012     ogles_error(c, GL_INVALID_ENUM);
1013 }
1014 
glTexEnvx(GLenum target,GLenum pname,GLfixed param)1015 void glTexEnvx(GLenum target, GLenum pname, GLfixed param)
1016 {
1017     ogles_context_t* c = ogles_context_t::get();
1018     c->rasterizer.procs.texEnvi(c, target, pname, param);
1019 }
1020 
glTexEnvxv(GLenum target,GLenum pname,const GLfixed * params)1021 void glTexEnvxv(
1022         GLenum target, GLenum pname, const GLfixed *params)
1023 {
1024     ogles_context_t* c = ogles_context_t::get();
1025     c->rasterizer.procs.texEnvxv(c, target, pname, params);
1026 }
1027 
glTexParameteriv(GLenum target,GLenum pname,const GLint * params)1028 void glTexParameteriv(
1029         GLenum target, GLenum pname, const GLint* params)
1030 {
1031     ogles_context_t* c = ogles_context_t::get();
1032     if (target != GGL_TEXTURE_2D) {
1033         ogles_error(c, GL_INVALID_ENUM);
1034         return;
1035     }
1036 
1037     EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture;
1038     switch (pname) {
1039     case GL_TEXTURE_CROP_RECT_OES:
1040         memcpy(textureObject->crop_rect, params, 4*sizeof(GLint));
1041         break;
1042     default:
1043         texParameterx(target, pname, GLfixed(params[0]), c);
1044         return;
1045     }
1046 }
1047 
glTexParameterf(GLenum target,GLenum pname,GLfloat param)1048 void glTexParameterf(
1049         GLenum target, GLenum pname, GLfloat param)
1050 {
1051     ogles_context_t* c = ogles_context_t::get();
1052     texParameterx(target, pname, GLfixed(param), c);
1053 }
1054 
glTexParameterx(GLenum target,GLenum pname,GLfixed param)1055 void glTexParameterx(
1056         GLenum target, GLenum pname, GLfixed param)
1057 {
1058     ogles_context_t* c = ogles_context_t::get();
1059     texParameterx(target, pname, param, c);
1060 }
1061 
glTexParameteri(GLenum target,GLenum pname,GLint param)1062 void glTexParameteri(
1063         GLenum target, GLenum pname, GLint param)
1064 {
1065     ogles_context_t* c = ogles_context_t::get();
1066     texParameterx(target, pname, GLfixed(param), c);
1067 }
1068 
1069 // ----------------------------------------------------------------------------
1070 #if 0
1071 #pragma mark -
1072 #endif
1073 
glCompressedTexImage2D(GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,const GLvoid * data)1074 void glCompressedTexImage2D(
1075         GLenum target, GLint level, GLenum internalformat,
1076         GLsizei width, GLsizei height, GLint border,
1077         GLsizei imageSize, const GLvoid *data)
1078 {
1079     ogles_context_t* c = ogles_context_t::get();
1080     if (target != GL_TEXTURE_2D) {
1081         ogles_error(c, GL_INVALID_ENUM);
1082         return;
1083     }
1084     if ((internalformat < GL_PALETTE4_RGB8_OES ||
1085          internalformat > GL_PALETTE8_RGB5_A1_OES)) {
1086         ogles_error(c, GL_INVALID_ENUM);
1087         return;
1088     }
1089     if (width<0 || height<0 || border!=0) {
1090         ogles_error(c, GL_INVALID_VALUE);
1091         return;
1092     }
1093 
1094     // "uncompress" the texture since pixelflinger doesn't support
1095     // any compressed texture format natively.
1096     GLenum format;
1097     GLenum type;
1098     switch (internalformat) {
1099     case GL_PALETTE8_RGB8_OES:
1100     case GL_PALETTE4_RGB8_OES:
1101         format      = GL_RGB;
1102         type        = GL_UNSIGNED_BYTE;
1103         break;
1104     case GL_PALETTE8_RGBA8_OES:
1105     case GL_PALETTE4_RGBA8_OES:
1106         format      = GL_RGBA;
1107         type        = GL_UNSIGNED_BYTE;
1108         break;
1109     case GL_PALETTE8_R5_G6_B5_OES:
1110     case GL_PALETTE4_R5_G6_B5_OES:
1111         format      = GL_RGB;
1112         type        = GL_UNSIGNED_SHORT_5_6_5;
1113         break;
1114     case GL_PALETTE8_RGBA4_OES:
1115     case GL_PALETTE4_RGBA4_OES:
1116         format      = GL_RGBA;
1117         type        = GL_UNSIGNED_SHORT_4_4_4_4;
1118         break;
1119     case GL_PALETTE8_RGB5_A1_OES:
1120     case GL_PALETTE4_RGB5_A1_OES:
1121         format      = GL_RGBA;
1122         type        = GL_UNSIGNED_SHORT_5_5_5_1;
1123         break;
1124     default:
1125         ogles_error(c, GL_INVALID_ENUM);
1126         return;
1127     }
1128 
1129     if (!data || !width || !height) {
1130         // unclear if this is an error or not...
1131         return;
1132     }
1133 
1134     int32_t size;
1135     GGLSurface* surface;
1136     // all mipmap levels are specified at once.
1137     const int numLevels = level<0 ? -level : 1;
1138 
1139     if (dataSizePalette4(numLevels, width, height, format) > imageSize) {
1140         ogles_error(c, GL_INVALID_VALUE);
1141         return;
1142     }
1143 
1144     for (int i=0 ; i<numLevels ; i++) {
1145         int lod_w = (width  >> i) ? : 1;
1146         int lod_h = (height >> i) ? : 1;
1147         int error = createTextureSurface(c, &surface, &size,
1148                 i, format, type, lod_w, lod_h);
1149         if (error) {
1150             ogles_error(c, error);
1151             return;
1152         }
1153         decodePalette4(data, i, width, height,
1154                 surface->data, surface->stride, internalformat);
1155     }
1156 }
1157 
1158 
glTexImage2D(GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const GLvoid * pixels)1159 void glTexImage2D(
1160         GLenum target, GLint level, GLint internalformat,
1161         GLsizei width, GLsizei height, GLint border,
1162         GLenum format, GLenum type, const GLvoid *pixels)
1163 {
1164     ogles_context_t* c = ogles_context_t::get();
1165     if (target != GL_TEXTURE_2D) {
1166         ogles_error(c, GL_INVALID_ENUM);
1167         return;
1168     }
1169     if (width<0 || height<0 || border!=0 || level < 0) {
1170         ogles_error(c, GL_INVALID_VALUE);
1171         return;
1172     }
1173     if (format != (GLenum)internalformat) {
1174         ogles_error(c, GL_INVALID_OPERATION);
1175         return;
1176     }
1177     if (validFormatType(c, format, type)) {
1178         return;
1179     }
1180 
1181     int32_t size = 0;
1182     GGLSurface* surface = 0;
1183     int error = createTextureSurface(c, &surface, &size,
1184             level, format, type, width, height);
1185     if (error) {
1186         ogles_error(c, error);
1187         return;
1188     }
1189 
1190     if (pixels) {
1191         const int32_t formatIdx = convertGLPixelFormat(format, type);
1192         const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]);
1193         const int32_t align = c->textures.unpackAlignment-1;
1194         const int32_t bpr = ((width * pixelFormat.size) + align) & ~align;
1195         const size_t size = bpr * height;
1196         const int32_t stride = bpr / pixelFormat.size;
1197 
1198         GGLSurface userSurface;
1199         userSurface.version = sizeof(userSurface);
1200         userSurface.width  = width;
1201         userSurface.height = height;
1202         userSurface.stride = stride;
1203         userSurface.format = formatIdx;
1204         userSurface.compressedFormat = 0;
1205         userSurface.data = (GLubyte*)pixels;
1206 
1207         int err = copyPixels(c, *surface, 0, 0, userSurface, 0, 0, width, height);
1208         if (err) {
1209             ogles_error(c, err);
1210             return;
1211         }
1212         generateMipmap(c, level);
1213     }
1214 }
1215 
1216 // ----------------------------------------------------------------------------
1217 
glCompressedTexSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,const GLvoid * data)1218 void glCompressedTexSubImage2D(
1219         GLenum target, GLint level, GLint xoffset,
1220         GLint yoffset, GLsizei width, GLsizei height,
1221         GLenum format, GLsizei imageSize,
1222         const GLvoid *data)
1223 {
1224     ogles_context_t* c = ogles_context_t::get();
1225     ogles_error(c, GL_INVALID_ENUM);
1226 }
1227 
glTexSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,const GLvoid * pixels)1228 void glTexSubImage2D(
1229         GLenum target, GLint level, GLint xoffset,
1230         GLint yoffset, GLsizei width, GLsizei height,
1231         GLenum format, GLenum type, const GLvoid *pixels)
1232 {
1233     ogles_context_t* c = ogles_context_t::get();
1234     if (target != GL_TEXTURE_2D) {
1235         ogles_error(c, GL_INVALID_ENUM);
1236         return;
1237     }
1238     if (xoffset<0 || yoffset<0 || width<0 || height<0 || level<0) {
1239         ogles_error(c, GL_INVALID_VALUE);
1240         return;
1241     }
1242     if (validFormatType(c, format, type)) {
1243         return;
1244     }
1245 
1246     // find out which texture is bound to the current unit
1247     const int active = c->textures.active;
1248     EGLTextureObject* tex = c->textures.tmu[active].texture;
1249     const GGLSurface& surface(tex->mip(level));
1250 
1251     if (!tex->internalformat || tex->direct) {
1252         ogles_error(c, GL_INVALID_OPERATION);
1253         return;
1254     }
1255 
1256     if (format != tex->internalformat) {
1257         ogles_error(c, GL_INVALID_OPERATION);
1258         return;
1259     }
1260     if ((xoffset + width  > GLsizei(surface.width)) ||
1261         (yoffset + height > GLsizei(surface.height))) {
1262         ogles_error(c, GL_INVALID_VALUE);
1263         return;
1264     }
1265     if (!width || !height) {
1266         return; // okay, but no-op.
1267     }
1268 
1269     // figure out the size we need as well as the stride
1270     const int32_t formatIdx = convertGLPixelFormat(format, type);
1271     if (formatIdx == 0) { // we don't know what to do with this
1272         ogles_error(c, GL_INVALID_OPERATION);
1273         return;
1274     }
1275 
1276     const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]);
1277     const int32_t align = c->textures.unpackAlignment-1;
1278     const int32_t bpr = ((width * pixelFormat.size) + align) & ~align;
1279     const size_t size = bpr * height;
1280     const int32_t stride = bpr / pixelFormat.size;
1281     GGLSurface userSurface;
1282     userSurface.version = sizeof(userSurface);
1283     userSurface.width  = width;
1284     userSurface.height = height;
1285     userSurface.stride = stride;
1286     userSurface.format = formatIdx;
1287     userSurface.compressedFormat = 0;
1288     userSurface.data = (GLubyte*)pixels;
1289 
1290     int err = copyPixels(c,
1291             surface, xoffset, yoffset,
1292             userSurface, 0, 0, width, height);
1293     if (err) {
1294         ogles_error(c, err);
1295         return;
1296     }
1297 
1298     generateMipmap(c, level);
1299 
1300     // since we only changed the content of the texture, we don't need
1301     // to call bindTexture on the main rasterizer.
1302 }
1303 
1304 // ----------------------------------------------------------------------------
1305 
glCopyTexImage2D(GLenum target,GLint level,GLenum internalformat,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)1306 void glCopyTexImage2D(
1307         GLenum target, GLint level, GLenum internalformat,
1308         GLint x, GLint y, GLsizei width, GLsizei height,
1309         GLint border)
1310 {
1311     ogles_context_t* c = ogles_context_t::get();
1312     if (target != GL_TEXTURE_2D) {
1313         ogles_error(c, GL_INVALID_ENUM);
1314         return;
1315     }
1316     if (internalformat<GL_ALPHA || internalformat>GL_LUMINANCE_ALPHA) {
1317         ogles_error(c, GL_INVALID_ENUM);
1318         return;
1319     }
1320     if (width<0 || height<0 || border!=0 || level<0) {
1321         ogles_error(c, GL_INVALID_VALUE);
1322         return;
1323     }
1324 
1325     GLenum format = 0;
1326     GLenum type = GL_UNSIGNED_BYTE;
1327     const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
1328     const int cbFormatIdx = cbSurface.format;
1329     switch (cbFormatIdx) {
1330     case GGL_PIXEL_FORMAT_RGB_565:
1331         type = GL_UNSIGNED_SHORT_5_6_5;
1332         break;
1333     case GGL_PIXEL_FORMAT_RGBA_5551:
1334         type = GL_UNSIGNED_SHORT_5_5_5_1;
1335         break;
1336     case GGL_PIXEL_FORMAT_RGBA_4444:
1337         type = GL_UNSIGNED_SHORT_4_4_4_4;
1338         break;
1339     }
1340     switch (internalformat) {
1341     case GL_ALPHA:
1342     case GL_LUMINANCE_ALPHA:
1343     case GL_LUMINANCE:
1344         type = GL_UNSIGNED_BYTE;
1345         break;
1346     }
1347 
1348     // figure out the format to use for the new texture
1349     switch (cbFormatIdx) {
1350     case GGL_PIXEL_FORMAT_RGBA_8888:
1351     case GGL_PIXEL_FORMAT_A_8:
1352     case GGL_PIXEL_FORMAT_RGBA_5551:
1353     case GGL_PIXEL_FORMAT_RGBA_4444:
1354         format = internalformat;
1355         break;
1356     case GGL_PIXEL_FORMAT_RGBX_8888:
1357     case GGL_PIXEL_FORMAT_RGB_888:
1358     case GGL_PIXEL_FORMAT_RGB_565:
1359     case GGL_PIXEL_FORMAT_L_8:
1360         switch (internalformat) {
1361         case GL_LUMINANCE:
1362         case GL_RGB:
1363             format = internalformat;
1364             break;
1365         }
1366         break;
1367     }
1368 
1369     if (format == 0) {
1370         // invalid combination
1371         ogles_error(c, GL_INVALID_ENUM);
1372         return;
1373     }
1374 
1375     // create the new texture...
1376     int32_t size;
1377     GGLSurface* surface;
1378     int error = createTextureSurface(c, &surface, &size,
1379             level, format, type, width, height);
1380     if (error) {
1381         ogles_error(c, error);
1382         return;
1383     }
1384 
1385     // The bottom row is stored first in textures
1386     GGLSurface txSurface(*surface);
1387     txSurface.stride = -txSurface.stride;
1388 
1389     // (x,y) is the lower-left corner of colorBuffer
1390     y = cbSurface.height - (y + height);
1391 
1392     int err = copyPixels(c,
1393             txSurface, 0, 0,
1394             cbSurface, x, y, cbSurface.width, cbSurface.height);
1395     if (err) {
1396         ogles_error(c, err);
1397     }
1398 
1399     generateMipmap(c, level);
1400 }
1401 
glCopyTexSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height)1402 void glCopyTexSubImage2D(
1403         GLenum target, GLint level, GLint xoffset, GLint yoffset,
1404         GLint x, GLint y, GLsizei width, GLsizei height)
1405 {
1406     ogles_context_t* c = ogles_context_t::get();
1407     if (target != GL_TEXTURE_2D) {
1408         ogles_error(c, GL_INVALID_ENUM);
1409         return;
1410     }
1411     if (xoffset<0 || yoffset<0 || width<0 || height<0 || level<0) {
1412         ogles_error(c, GL_INVALID_VALUE);
1413         return;
1414     }
1415     if (!width || !height) {
1416         return; // okay, but no-op.
1417     }
1418 
1419     // find out which texture is bound to the current unit
1420     const int active = c->textures.active;
1421     EGLTextureObject* tex = c->textures.tmu[active].texture;
1422     const GGLSurface& surface(tex->mip(level));
1423 
1424     if (!tex->internalformat) {
1425         ogles_error(c, GL_INVALID_OPERATION);
1426         return;
1427     }
1428     if ((xoffset + width  > GLsizei(surface.width)) ||
1429         (yoffset + height > GLsizei(surface.height))) {
1430         ogles_error(c, GL_INVALID_VALUE);
1431         return;
1432     }
1433 
1434     // The bottom row is stored first in textures
1435     GGLSurface txSurface(surface);
1436     txSurface.stride = -txSurface.stride;
1437 
1438     // (x,y) is the lower-left corner of colorBuffer
1439     const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
1440     y = cbSurface.height - (y + height);
1441 
1442     int err = copyPixels(c,
1443             surface, xoffset, yoffset,
1444             cbSurface, x, y, width, height);
1445     if (err) {
1446         ogles_error(c, err);
1447         return;
1448     }
1449 
1450     generateMipmap(c, level);
1451 }
1452 
glReadPixels(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels)1453 void glReadPixels(
1454         GLint x, GLint y, GLsizei width, GLsizei height,
1455         GLenum format, GLenum type, GLvoid *pixels)
1456 {
1457     ogles_context_t* c = ogles_context_t::get();
1458     if ((format != GL_RGBA) && (format != GL_RGB)) {
1459         ogles_error(c, GL_INVALID_ENUM);
1460         return;
1461     }
1462     if ((type != GL_UNSIGNED_BYTE) && (type != GL_UNSIGNED_SHORT_5_6_5)) {
1463         ogles_error(c, GL_INVALID_ENUM);
1464         return;
1465     }
1466     if (width<0 || height<0) {
1467         ogles_error(c, GL_INVALID_VALUE);
1468         return;
1469     }
1470     if (x<0 || x<0) {
1471         ogles_error(c, GL_INVALID_VALUE);
1472         return;
1473     }
1474 
1475     int32_t formatIdx = GGL_PIXEL_FORMAT_NONE;
1476     if ((format == GL_RGBA) && (type == GL_UNSIGNED_BYTE)) {
1477         formatIdx = GGL_PIXEL_FORMAT_RGBA_8888;
1478     } else if ((format == GL_RGB) && (type == GL_UNSIGNED_SHORT_5_6_5)) {
1479         formatIdx = GGL_PIXEL_FORMAT_RGB_565;
1480     } else {
1481         ogles_error(c, GL_INVALID_OPERATION);
1482         return;
1483     }
1484 
1485     const GGLSurface& readSurface = c->rasterizer.state.buffers.read.s;
1486     if ((x+width > GLint(readSurface.width)) ||
1487             (y+height > GLint(readSurface.height))) {
1488         ogles_error(c, GL_INVALID_VALUE);
1489         return;
1490     }
1491 
1492     const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]);
1493     const int32_t align = c->textures.packAlignment-1;
1494     const int32_t bpr = ((width * pixelFormat.size) + align) & ~align;
1495     const int32_t stride = bpr / pixelFormat.size;
1496 
1497     GGLSurface userSurface;
1498     userSurface.version = sizeof(userSurface);
1499     userSurface.width  = width;
1500     userSurface.height = height;
1501     userSurface.stride = -stride; // bottom row is transfered first
1502     userSurface.format = formatIdx;
1503     userSurface.compressedFormat = 0;
1504     userSurface.data = (GLubyte*)pixels;
1505 
1506     // use pixel-flinger to handle all the conversions
1507     GGLContext* ggl = getRasterizer(c);
1508     if (!ggl) {
1509         // the only reason this would fail is because we ran out of memory
1510         ogles_error(c, GL_OUT_OF_MEMORY);
1511         return;
1512     }
1513 
1514     ggl->colorBuffer(ggl, &userSurface);  // destination is user buffer
1515     ggl->bindTexture(ggl, &readSurface);  // source is read-buffer
1516     ggl->texCoord2i(ggl, x, readSurface.height - (y + height));
1517     ggl->recti(ggl, 0, 0, width, height);
1518 }
1519 
1520 // ----------------------------------------------------------------------------
1521 #if 0
1522 #pragma mark -
1523 #pragma mark DrawTexture Extension
1524 #endif
1525 
glDrawTexsvOES(const GLshort * coords)1526 void glDrawTexsvOES(const GLshort* coords) {
1527     ogles_context_t* c = ogles_context_t::get();
1528     drawTexiOES(coords[0], coords[1], coords[2], coords[3], coords[4], c);
1529 }
glDrawTexivOES(const GLint * coords)1530 void glDrawTexivOES(const GLint* coords) {
1531     ogles_context_t* c = ogles_context_t::get();
1532     drawTexiOES(coords[0], coords[1], coords[2], coords[3], coords[4], c);
1533 }
glDrawTexsOES(GLshort x,GLshort y,GLshort z,GLshort w,GLshort h)1534 void glDrawTexsOES(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h) {
1535     ogles_context_t* c = ogles_context_t::get();
1536     drawTexiOES(x, y, z, w, h, c);
1537 }
glDrawTexiOES(GLint x,GLint y,GLint z,GLint w,GLint h)1538 void glDrawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h) {
1539     ogles_context_t* c = ogles_context_t::get();
1540     drawTexiOES(x, y, z, w, h, c);
1541 }
1542 
glDrawTexfvOES(const GLfloat * coords)1543 void glDrawTexfvOES(const GLfloat* coords) {
1544     ogles_context_t* c = ogles_context_t::get();
1545     drawTexxOES(
1546             gglFloatToFixed(coords[0]),
1547             gglFloatToFixed(coords[1]),
1548             gglFloatToFixed(coords[2]),
1549             gglFloatToFixed(coords[3]),
1550             gglFloatToFixed(coords[4]),
1551             c);
1552 }
glDrawTexxvOES(const GLfixed * coords)1553 void glDrawTexxvOES(const GLfixed* coords) {
1554     ogles_context_t* c = ogles_context_t::get();
1555     drawTexxOES(coords[0], coords[1], coords[2], coords[3], coords[4], c);
1556 }
glDrawTexfOES(GLfloat x,GLfloat y,GLfloat z,GLfloat w,GLfloat h)1557 void glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h){
1558     ogles_context_t* c = ogles_context_t::get();
1559     drawTexxOES(
1560             gglFloatToFixed(x), gglFloatToFixed(y), gglFloatToFixed(z),
1561             gglFloatToFixed(w), gglFloatToFixed(h),
1562             c);
1563 }
glDrawTexxOES(GLfixed x,GLfixed y,GLfixed z,GLfixed w,GLfixed h)1564 void glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) {
1565     ogles_context_t* c = ogles_context_t::get();
1566     drawTexxOES(x, y, z, w, h, c);
1567 }
1568 
1569 // ----------------------------------------------------------------------------
1570 #if 0
1571 #pragma mark -
1572 #pragma mark EGL Image Extension
1573 #endif
1574 
glEGLImageTargetTexture2DOES(GLenum target,GLeglImageOES image)1575 void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
1576 {
1577     ogles_context_t* c = ogles_context_t::get();
1578     if (target != GL_TEXTURE_2D) {
1579         ogles_error(c, GL_INVALID_ENUM);
1580         return;
1581     }
1582 
1583     android_native_buffer_t* native_buffer = (android_native_buffer_t*)image;
1584     if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) {
1585         ogles_error(c, GL_INVALID_VALUE);
1586         return;
1587     }
1588     if (native_buffer->common.version != sizeof(android_native_buffer_t)) {
1589         ogles_error(c, GL_INVALID_VALUE);
1590         return;
1591     }
1592 
1593     // bind it to the texture unit
1594     sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c);
1595     tex->setImage(native_buffer);
1596 
1597 #ifdef LIBAGL_USE_GRALLOC_COPYBITS
1598     tex->try_copybit = false;
1599     if (c->copybits.blitEngine != NULL) {
1600         tex->try_copybit = true;
1601     }
1602 #endif // LIBAGL_USE_GRALLOC_COPYBITS
1603 }
1604 
glEGLImageTargetRenderbufferStorageOES(GLenum target,GLeglImageOES image)1605 void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
1606 {
1607 }
1608