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