state.cpp revision 92dc3fc52cf097bd105460cf377779bdcf146d62
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
31namespace android {
32
33// ----------------------------------------------------------------------------
34
35static char const * const gVendorString     = "Android";
36static char const * const gRendererString   = "Android PixelFlinger 1.4";
37static char const * const gVersionString    = "OpenGL ES-CM 1.0";
38static 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
66ogles_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
104void 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
117void _ogles_error(ogles_context_t* c, GLenum error)
118{
119    if (c->error == GL_NO_ERROR)
120        c->error = error;
121}
122
123static 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
136static 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// ----------------------------------------------------------------------------
215using namespace android;
216
217#if 0
218#pragma mark -
219#endif
220
221// These ones are super-easy, we're not supporting those features!
222void glSampleCoverage(GLclampf /*value*/, GLboolean /*invert*/) {
223}
224void glSampleCoveragex(GLclampx /*value*/, GLboolean /*invert*/) {
225}
226void 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
237void 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
249void glAlphaFunc(GLenum func, GLclampf ref)
250{
251    glAlphaFuncx(func, gglFloatToFixed(ref));
252}
253
254void 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
268void 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
282void 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
302void glEnable(GLenum cap) {
303    ogles_context_t* c = ogles_context_t::get();
304    enable_disable(c, cap, 1);
305}
306void glDisable(GLenum cap) {
307    ogles_context_t* c = ogles_context_t::get();
308    enable_disable(c, cap, 0);
309}
310
311void glFinish()
312{ // nothing to do for our software implementation
313}
314
315void glFlush()
316{ // nothing to do for our software implementation
317}
318
319GLenum 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
343const 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
356void 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
485void 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
495void 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
507void 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
517void 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
529void 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
534void glDepthMask(GLboolean flag) {
535    ogles_context_t* c = ogles_context_t::get();
536    c->rasterizer.procs.depthMask(c, flag);
537}
538
539void glStencilMask(GLuint mask) {
540    ogles_context_t* c = ogles_context_t::get();
541    c->rasterizer.procs.stencilMask(c, mask);
542}
543
544void glDepthFunc(GLenum func) {
545    ogles_context_t* c = ogles_context_t::get();
546    c->rasterizer.procs.depthFunc(c, func);
547}
548
549void glLogicOp(GLenum opcode) {
550    ogles_context_t* c = ogles_context_t::get();
551    c->rasterizer.procs.logicOp(c, opcode);
552}
553
554void glAlphaFuncx(GLenum func, GLclampx ref) {
555    ogles_context_t* c = ogles_context_t::get();
556    c->rasterizer.procs.alphaFuncx(c, func, ref);
557}
558
559void glBlendFunc(GLenum sfactor, GLenum dfactor) {
560    ogles_context_t* c = ogles_context_t::get();
561    c->rasterizer.procs.blendFunc(c, sfactor, dfactor);
562}
563
564void glClear(GLbitfield mask) {
565    ogles_context_t* c = ogles_context_t::get();
566    c->rasterizer.procs.clear(c, mask);
567}
568
569void 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
574void 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
584void glClearDepthx(GLclampx depth) {
585    ogles_context_t* c = ogles_context_t::get();
586    c->rasterizer.procs.clearDepthx(c, depth);
587}
588
589void glClearDepthf(GLclampf depth)
590{
591    ogles_context_t* c = ogles_context_t::get();
592    c->rasterizer.procs.clearDepthx(c, gglFloatToFixed(depth));
593}
594
595void glClearStencil(GLint s) {
596    ogles_context_t* c = ogles_context_t::get();
597    c->rasterizer.procs.clearStencil(c, s);
598}
599