1 /* libs/opengles/state.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 <stdlib.h>
19 
20 #include "context.h"
21 #include "fp.h"
22 #include "state.h"
23 #include "array.h"
24 #include "matrix.h"
25 #include "vertex.h"
26 #include "light.h"
27 #include "texture.h"
28 #include "BufferObjectManager.h"
29 #include "TextureObjectManager.h"
30 
31 namespace android {
32 
33 // ----------------------------------------------------------------------------
34 
35 static char const * const gVendorString     = "Android";
36 static char const * const gRendererString   = "Android PixelFlinger 1.4";
37 static char const * const gVersionString    = "OpenGL ES-CM 1.0";
38 static char const * const gExtensionsString =
39     "GL_OES_byte_coordinates "              // OK
40     "GL_OES_fixed_point "                   // OK
41     "GL_OES_single_precision "              // OK
42     "GL_OES_read_format "                   // OK
43     "GL_OES_compressed_paletted_texture "   // OK
44     "GL_OES_draw_texture "                  // OK
45     "GL_OES_matrix_get "                    // OK
46     "GL_OES_query_matrix "                  // OK
47     //        "GL_OES_point_size_array "              // TODO
48     //        "GL_OES_point_sprite "                  // TODO
49     "GL_OES_EGL_image "                     // OK
50     "GL_OES_EGL_sync "                      // OK
51 #ifdef GL_OES_compressed_ETC1_RGB8_texture
52     "GL_OES_compressed_ETC1_RGB8_texture "  // OK
53 #endif
54     "GL_ARB_texture_compression "           // OK
55     "GL_ARB_texture_non_power_of_two "      // OK
56     "GL_ANDROID_user_clip_plane "           // OK
57     "GL_ANDROID_vertex_buffer_object "      // OK
58     "GL_ANDROID_generate_mipmap "           // OK
59     ;
60 
61 // ----------------------------------------------------------------------------
62 #if 0
63 #pragma mark -
64 #endif
65 
ogles_init(size_t extra)66 ogles_context_t *ogles_init(size_t extra)
67 {
68     void* const base = malloc(extra + sizeof(ogles_context_t) + 32);
69     if (!base) return 0;
70 
71     ogles_context_t *c =
72             (ogles_context_t *)((ptrdiff_t(base) + extra + 31) & ~0x1FL);
73     memset(c, 0, sizeof(ogles_context_t));
74     ggl_init_context(&(c->rasterizer));
75 
76     // XXX: this should be passed as an argument
77     sp<EGLSurfaceManager> smgr(new EGLSurfaceManager());
78     c->surfaceManager = smgr.get();
79     c->surfaceManager->incStrong(c);
80 
81     sp<EGLBufferObjectManager> bomgr(new EGLBufferObjectManager());
82     c->bufferObjectManager = bomgr.get();
83     c->bufferObjectManager->incStrong(c);
84 
85     ogles_init_array(c);
86     ogles_init_matrix(c);
87     ogles_init_vertex(c);
88     ogles_init_light(c);
89     ogles_init_texture(c);
90 
91     c->rasterizer.base = base;
92     c->point.size = TRI_ONE;
93     c->line.width = TRI_ONE;
94 
95     // in OpenGL, writing to the depth buffer is enabled by default.
96     c->rasterizer.procs.depthMask(c, 1);
97 
98     // OpenGL enables dithering by default
99     c->rasterizer.procs.enable(c, GL_DITHER);
100 
101     return c;
102 }
103 
ogles_uninit(ogles_context_t * c)104 void ogles_uninit(ogles_context_t* c)
105 {
106     ogles_uninit_array(c);
107     ogles_uninit_matrix(c);
108     ogles_uninit_vertex(c);
109     ogles_uninit_light(c);
110     ogles_uninit_texture(c);
111     c->surfaceManager->decStrong(c);
112     c->bufferObjectManager->decStrong(c);
113     ggl_uninit_context(&(c->rasterizer));
114     free(c->rasterizer.base);
115 }
116 
_ogles_error(ogles_context_t * c,GLenum error)117 void _ogles_error(ogles_context_t* c, GLenum error)
118 {
119     if (c->error == GL_NO_ERROR)
120         c->error = error;
121 }
122 
stencilop_valid(GLenum op)123 static bool stencilop_valid(GLenum op) {
124     switch (op) {
125     case GL_KEEP:
126     case GL_ZERO:
127     case GL_REPLACE:
128     case GL_INCR:
129     case GL_DECR:
130     case GL_INVERT:
131         return true;
132     }
133     return false;
134 }
135 
enable_disable(ogles_context_t * c,GLenum cap,int enabled)136 static void enable_disable(ogles_context_t* c, GLenum cap, int enabled)
137 {
138     if ((cap >= GL_LIGHT0) && (cap<GL_LIGHT0+OGLES_MAX_LIGHTS)) {
139         c->lighting.lights[cap-GL_LIGHT0].enable = enabled;
140         c->lighting.enabledLights &= ~(1<<(cap-GL_LIGHT0));
141         c->lighting.enabledLights |= (enabled<<(cap-GL_LIGHT0));
142         return;
143     }
144 
145     switch (cap) {
146     case GL_POINT_SMOOTH:
147         c->point.smooth = enabled;
148         break;
149     case GL_LINE_SMOOTH:
150         c->line.smooth = enabled;
151         break;
152     case GL_POLYGON_OFFSET_FILL:
153         c->polygonOffset.enable = enabled;
154         break;
155     case GL_CULL_FACE:
156         c->cull.enable = enabled;
157         break;
158     case GL_LIGHTING:
159         c->lighting.enable = enabled;
160         break;
161     case GL_COLOR_MATERIAL:
162         c->lighting.colorMaterial.enable = enabled;
163         break;
164     case GL_NORMALIZE:
165     case GL_RESCALE_NORMAL:
166         c->transforms.rescaleNormals = enabled ? cap : 0;
167         // XXX: invalidate mvit
168         break;
169 
170     case GL_CLIP_PLANE0:
171     case GL_CLIP_PLANE1:
172     case GL_CLIP_PLANE2:
173     case GL_CLIP_PLANE3:
174     case GL_CLIP_PLANE4:
175     case GL_CLIP_PLANE5:
176         c->clipPlanes.enable &= ~(1<<(cap-GL_CLIP_PLANE0));
177         c->clipPlanes.enable |= (enabled<<(cap-GL_CLIP_PLANE0));
178         ogles_invalidate_perspective(c);
179         break;
180 
181     case GL_FOG:
182     case GL_DEPTH_TEST:
183         ogles_invalidate_perspective(c);
184         // fall-through...
185     case GL_BLEND:
186     case GL_SCISSOR_TEST:
187     case GL_ALPHA_TEST:
188     case GL_COLOR_LOGIC_OP:
189     case GL_DITHER:
190     case GL_STENCIL_TEST:
191     case GL_TEXTURE_2D:
192         // these need to fall through into the rasterizer
193         c->rasterizer.procs.enableDisable(c, cap, enabled);
194         break;
195     case GL_TEXTURE_EXTERNAL_OES:
196         c->rasterizer.procs.enableDisable(c, GL_TEXTURE_2D, enabled);
197         break;
198 
199     case GL_MULTISAMPLE:
200     case GL_SAMPLE_ALPHA_TO_COVERAGE:
201     case GL_SAMPLE_ALPHA_TO_ONE:
202     case GL_SAMPLE_COVERAGE:
203         // not supported in this implementation
204         break;
205 
206     default:
207         ogles_error(c, GL_INVALID_ENUM);
208         return;
209     }
210 }
211 
212 // ----------------------------------------------------------------------------
213 }; // namespace android
214 // ----------------------------------------------------------------------------
215 using namespace android;
216 
217 #if 0
218 #pragma mark -
219 #endif
220 
221 // These ones are super-easy, we're not supporting those features!
glSampleCoverage(GLclampf,GLboolean)222 void glSampleCoverage(GLclampf /*value*/, GLboolean /*invert*/) {
223 }
glSampleCoveragex(GLclampx,GLboolean)224 void glSampleCoveragex(GLclampx /*value*/, GLboolean /*invert*/) {
225 }
glStencilFunc(GLenum func,GLint,GLuint)226 void glStencilFunc(GLenum func, GLint /*ref*/, GLuint /*mask*/) {
227     ogles_context_t* c = ogles_context_t::get();
228     if (func < GL_NEVER || func > GL_ALWAYS) {
229         ogles_error(c, GL_INVALID_ENUM);
230         return;
231     }
232     // from OpenGL|ES 1.0 sepcification:
233     // If there is no stencil buffer, no stencil modification can occur
234     // and it is as if the stencil test always passes.
235 }
236 
glStencilOp(GLenum fail,GLenum zfail,GLenum zpass)237 void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
238     ogles_context_t* c = ogles_context_t::get();
239     if ((stencilop_valid(fail) &
240          stencilop_valid(zfail) &
241          stencilop_valid(zpass)) == 0) {
242         ogles_error(c, GL_INVALID_ENUM);
243         return;
244     }
245 }
246 
247 // ----------------------------------------------------------------------------
248 
glAlphaFunc(GLenum func,GLclampf ref)249 void glAlphaFunc(GLenum func, GLclampf ref)
250 {
251     glAlphaFuncx(func, gglFloatToFixed(ref));
252 }
253 
glCullFace(GLenum mode)254 void glCullFace(GLenum mode)
255 {
256     ogles_context_t* c = ogles_context_t::get();
257     switch (mode) {
258     case GL_FRONT:
259     case GL_BACK:
260     case GL_FRONT_AND_BACK:
261         break;
262     default:
263         ogles_error(c, GL_INVALID_ENUM);
264     }
265     c->cull.cullFace = mode;
266 }
267 
glFrontFace(GLenum mode)268 void glFrontFace(GLenum mode)
269 {
270     ogles_context_t* c = ogles_context_t::get();
271     switch (mode) {
272     case GL_CW:
273     case GL_CCW:
274         break;
275     default:
276         ogles_error(c, GL_INVALID_ENUM);
277         return;
278     }
279     c->cull.frontFace = mode;
280 }
281 
glHint(GLenum target,GLenum mode)282 void glHint(GLenum target, GLenum mode)
283 {
284     ogles_context_t* c = ogles_context_t::get();
285     switch (target) {
286     case GL_FOG_HINT:
287     case GL_GENERATE_MIPMAP_HINT:
288     case GL_LINE_SMOOTH_HINT:
289         break;
290     case GL_POINT_SMOOTH_HINT:
291         c->rasterizer.procs.enableDisable(c,
292                 GGL_POINT_SMOOTH_NICE, mode==GL_NICEST);
293         break;
294     case GL_PERSPECTIVE_CORRECTION_HINT:
295         c->perspective = (mode == GL_NICEST) ? 1 : 0;
296         break;
297     default:
298         ogles_error(c, GL_INVALID_ENUM);
299     }
300 }
301 
glEnable(GLenum cap)302 void glEnable(GLenum cap) {
303     ogles_context_t* c = ogles_context_t::get();
304     enable_disable(c, cap, 1);
305 }
glDisable(GLenum cap)306 void glDisable(GLenum cap) {
307     ogles_context_t* c = ogles_context_t::get();
308     enable_disable(c, cap, 0);
309 }
310 
glFinish()311 void glFinish()
312 { // nothing to do for our software implementation
313 }
314 
glFlush()315 void glFlush()
316 { // nothing to do for our software implementation
317 }
318 
glGetError()319 GLenum glGetError()
320 {
321     // From OpenGL|ES 1.0 specification:
322     // If more than one flag has recorded an error, glGetError returns
323     // and clears an arbitrary error flag value. Thus, glGetError should
324     // always be called in a loop, until it returns GL_NO_ERROR,
325     // if all error flags are to be reset.
326 
327     ogles_context_t* c = ogles_context_t::get();
328     if (c->error) {
329         const GLenum ret(c->error);
330         c->error = 0;
331         return ret;
332     }
333 
334     if (c->rasterizer.error) {
335         const GLenum ret(c->rasterizer.error);
336         c->rasterizer.error = 0;
337         return ret;
338     }
339 
340     return GL_NO_ERROR;
341 }
342 
glGetString(GLenum string)343 const GLubyte* glGetString(GLenum string)
344 {
345     switch (string) {
346     case GL_VENDOR:     return (const GLubyte*)gVendorString;
347     case GL_RENDERER:   return (const GLubyte*)gRendererString;
348     case GL_VERSION:    return (const GLubyte*)gVersionString;
349     case GL_EXTENSIONS: return (const GLubyte*)gExtensionsString;
350     }
351     ogles_context_t* c = ogles_context_t::get();
352     ogles_error(c, GL_INVALID_ENUM);
353     return 0;
354 }
355 
glGetIntegerv(GLenum pname,GLint * params)356 void glGetIntegerv(GLenum pname, GLint *params)
357 {
358     int i;
359     ogles_context_t* c = ogles_context_t::get();
360     switch (pname) {
361     case GL_ALIASED_POINT_SIZE_RANGE:
362         params[0] = 0;
363         params[1] = GGL_MAX_ALIASED_POINT_SIZE;
364         break;
365     case GL_ALIASED_LINE_WIDTH_RANGE:
366         params[0] = 0;
367         params[1] = GGL_MAX_ALIASED_POINT_SIZE;
368         break;
369     case GL_ALPHA_BITS: {
370         int index = c->rasterizer.state.buffers.color.format;
371         GGLFormat const * formats = gglGetPixelFormatTable();
372         params[0] = formats[index].ah - formats[index].al;
373         break;
374         }
375     case GL_RED_BITS: {
376         int index = c->rasterizer.state.buffers.color.format;
377         GGLFormat const * formats = gglGetPixelFormatTable();
378         params[0] = formats[index].rh - formats[index].rl;
379         break;
380         }
381     case GL_GREEN_BITS: {
382         int index = c->rasterizer.state.buffers.color.format;
383         GGLFormat const * formats = gglGetPixelFormatTable();
384         params[0] = formats[index].gh - formats[index].gl;
385         break;
386         }
387     case GL_BLUE_BITS: {
388         int index = c->rasterizer.state.buffers.color.format;
389         GGLFormat const * formats = gglGetPixelFormatTable();
390         params[0] = formats[index].bh - formats[index].bl;
391         break;
392         }
393     case GL_COMPRESSED_TEXTURE_FORMATS:
394         params[ 0] = GL_PALETTE4_RGB8_OES;
395         params[ 1] = GL_PALETTE4_RGBA8_OES;
396         params[ 2] = GL_PALETTE4_R5_G6_B5_OES;
397         params[ 3] = GL_PALETTE4_RGBA4_OES;
398         params[ 4] = GL_PALETTE4_RGB5_A1_OES;
399         params[ 5] = GL_PALETTE8_RGB8_OES;
400         params[ 6] = GL_PALETTE8_RGBA8_OES;
401         params[ 7] = GL_PALETTE8_R5_G6_B5_OES;
402         params[ 8] = GL_PALETTE8_RGBA4_OES;
403         params[ 9] = GL_PALETTE8_RGB5_A1_OES;
404         i = 10;
405 #ifdef GL_OES_compressed_ETC1_RGB8_texture
406         params[i++] = GL_ETC1_RGB8_OES;
407 #endif
408         break;
409     case GL_DEPTH_BITS:
410         params[0] = c->rasterizer.state.buffers.depth.format ? 0 : 16;
411         break;
412     case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
413         params[0] = GL_RGB;
414         break;
415     case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
416         params[0] = GL_UNSIGNED_SHORT_5_6_5;
417         break;
418     case GL_MAX_LIGHTS:
419         params[0] = OGLES_MAX_LIGHTS;
420         break;
421     case GL_MAX_CLIP_PLANES:
422         params[0] = OGLES_MAX_CLIP_PLANES;
423         break;
424     case GL_MAX_MODELVIEW_STACK_DEPTH:
425         params[0] = OGLES_MODELVIEW_STACK_DEPTH;
426         break;
427     case GL_MAX_PROJECTION_STACK_DEPTH:
428         params[0] = OGLES_PROJECTION_STACK_DEPTH;
429         break;
430     case GL_MAX_TEXTURE_STACK_DEPTH:
431         params[0] = OGLES_TEXTURE_STACK_DEPTH;
432         break;
433     case GL_MAX_TEXTURE_SIZE:
434         params[0] = GGL_MAX_TEXTURE_SIZE;
435         break;
436     case GL_MAX_TEXTURE_UNITS:
437         params[0] = GGL_TEXTURE_UNIT_COUNT;
438         break;
439     case GL_MAX_VIEWPORT_DIMS:
440         params[0] = GGL_MAX_VIEWPORT_DIMS;
441         params[1] = GGL_MAX_VIEWPORT_DIMS;
442         break;
443     case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
444         params[0] = OGLES_NUM_COMPRESSED_TEXTURE_FORMATS;
445         break;
446     case GL_SMOOTH_LINE_WIDTH_RANGE:
447         params[0] = 0;
448         params[1] = GGL_MAX_SMOOTH_LINE_WIDTH;
449         break;
450     case GL_SMOOTH_POINT_SIZE_RANGE:
451         params[0] = 0;
452         params[1] = GGL_MAX_SMOOTH_POINT_SIZE;
453         break;
454     case GL_STENCIL_BITS:
455         params[0] = 0;
456         break;
457     case GL_SUBPIXEL_BITS:
458         params[0] = GGL_SUBPIXEL_BITS;
459         break;
460 
461     case GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES:
462         memcpy( params,
463                 c->transforms.modelview.top().elements(),
464                 16*sizeof(GLint));
465         break;
466     case GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES:
467         memcpy( params,
468                 c->transforms.projection.top().elements(),
469                 16*sizeof(GLint));
470         break;
471     case GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES:
472         memcpy( params,
473                 c->transforms.texture[c->textures.active].top().elements(),
474                 16*sizeof(GLint));
475         break;
476 
477     default:
478         ogles_error(c, GL_INVALID_ENUM);
479         break;
480     }
481 }
482 
483 // ----------------------------------------------------------------------------
484 
glPointSize(GLfloat size)485 void glPointSize(GLfloat size)
486 {
487     ogles_context_t* c = ogles_context_t::get();
488     if (size <= 0) {
489         ogles_error(c, GL_INVALID_ENUM);
490         return;
491     }
492     c->point.size = TRI_FROM_FIXED(gglFloatToFixed(size));
493 }
494 
glPointSizex(GLfixed size)495 void glPointSizex(GLfixed size)
496 {
497     ogles_context_t* c = ogles_context_t::get();
498     if (size <= 0) {
499         ogles_error(c, GL_INVALID_ENUM);
500         return;
501     }
502     c->point.size = TRI_FROM_FIXED(size);
503 }
504 
505 // ----------------------------------------------------------------------------
506 
glLineWidth(GLfloat width)507 void glLineWidth(GLfloat width)
508 {
509     ogles_context_t* c = ogles_context_t::get();
510     if (width <= 0) {
511         ogles_error(c, GL_INVALID_ENUM);
512         return;
513     }
514     c->line.width = TRI_FROM_FIXED(gglFloatToFixed(width));
515 }
516 
glLineWidthx(GLfixed width)517 void glLineWidthx(GLfixed width)
518 {
519     ogles_context_t* c = ogles_context_t::get();
520     if (width <= 0) {
521         ogles_error(c, GL_INVALID_ENUM);
522         return;
523     }
524     c->line.width = TRI_FROM_FIXED(width);
525 }
526 
527 // ----------------------------------------------------------------------------
528 
glColorMask(GLboolean r,GLboolean g,GLboolean b,GLboolean a)529 void glColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
530     ogles_context_t* c = ogles_context_t::get();
531     c->rasterizer.procs.colorMask(c, r, g, b, a);
532 }
533 
glDepthMask(GLboolean flag)534 void glDepthMask(GLboolean flag) {
535     ogles_context_t* c = ogles_context_t::get();
536     c->rasterizer.procs.depthMask(c, flag);
537 }
538 
glStencilMask(GLuint mask)539 void glStencilMask(GLuint mask) {
540     ogles_context_t* c = ogles_context_t::get();
541     c->rasterizer.procs.stencilMask(c, mask);
542 }
543 
glDepthFunc(GLenum func)544 void glDepthFunc(GLenum func) {
545     ogles_context_t* c = ogles_context_t::get();
546     c->rasterizer.procs.depthFunc(c, func);
547 }
548 
glLogicOp(GLenum opcode)549 void glLogicOp(GLenum opcode) {
550     ogles_context_t* c = ogles_context_t::get();
551     c->rasterizer.procs.logicOp(c, opcode);
552 }
553 
glAlphaFuncx(GLenum func,GLclampx ref)554 void glAlphaFuncx(GLenum func, GLclampx ref) {
555     ogles_context_t* c = ogles_context_t::get();
556     c->rasterizer.procs.alphaFuncx(c, func, ref);
557 }
558 
glBlendFunc(GLenum sfactor,GLenum dfactor)559 void glBlendFunc(GLenum sfactor, GLenum dfactor) {
560     ogles_context_t* c = ogles_context_t::get();
561     c->rasterizer.procs.blendFunc(c, sfactor, dfactor);
562 }
563 
glClear(GLbitfield mask)564 void glClear(GLbitfield mask) {
565     ogles_context_t* c = ogles_context_t::get();
566     c->rasterizer.procs.clear(c, mask);
567 }
568 
glClearColorx(GLclampx red,GLclampx green,GLclampx blue,GLclampx alpha)569 void glClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) {
570     ogles_context_t* c = ogles_context_t::get();
571     c->rasterizer.procs.clearColorx(c, red, green, blue, alpha);
572 }
573 
glClearColor(GLclampf r,GLclampf g,GLclampf b,GLclampf a)574 void glClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a)
575 {
576     ogles_context_t* c = ogles_context_t::get();
577     c->rasterizer.procs.clearColorx(c,
578                     gglFloatToFixed(r),
579                     gglFloatToFixed(g),
580                     gglFloatToFixed(b),
581                     gglFloatToFixed(a));
582 }
583 
glClearDepthx(GLclampx depth)584 void glClearDepthx(GLclampx depth) {
585     ogles_context_t* c = ogles_context_t::get();
586     c->rasterizer.procs.clearDepthx(c, depth);
587 }
588 
glClearDepthf(GLclampf depth)589 void glClearDepthf(GLclampf depth)
590 {
591     ogles_context_t* c = ogles_context_t::get();
592     c->rasterizer.procs.clearDepthx(c, gglFloatToFixed(depth));
593 }
594 
glClearStencil(GLint s)595 void glClearStencil(GLint s) {
596     ogles_context_t* c = ogles_context_t::get();
597     c->rasterizer.procs.clearStencil(c, s);
598 }
599