state.cpp revision 3a0cae8e5f3881cb1bcb02ab7fa4cbacf5b55525
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    case GL_TEXTURE_EXTERNAL_OES:
195        c->rasterizer.procs.enableDisable(c, GL_TEXTURE_2D, enabled);
196        break;
197
198    case GL_MULTISAMPLE:
199    case GL_SAMPLE_ALPHA_TO_COVERAGE:
200    case GL_SAMPLE_ALPHA_TO_ONE:
201    case GL_SAMPLE_COVERAGE:
202        // not supported in this implementation
203        break;
204
205    default:
206        ogles_error(c, GL_INVALID_ENUM);
207        return;
208    }
209}
210
211// ----------------------------------------------------------------------------
212}; // namespace android
213// ----------------------------------------------------------------------------
214using namespace android;
215
216#if 0
217#pragma mark -
218#endif
219
220// These ones are super-easy, we're not supporting those features!
221void glSampleCoverage(GLclampf value, GLboolean invert) {
222}
223void glSampleCoveragex(GLclampx value, GLboolean invert) {
224}
225void glStencilFunc(GLenum func, GLint ref, GLuint mask) {
226    ogles_context_t* c = ogles_context_t::get();
227    if (func < GL_NEVER || func > GL_ALWAYS) {
228        ogles_error(c, GL_INVALID_ENUM);
229        return;
230    }
231    // from OpenGL|ES 1.0 sepcification:
232    // If there is no stencil buffer, no stencil modification can occur
233    // and it is as if the stencil test always passes.
234}
235
236void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
237    ogles_context_t* c = ogles_context_t::get();
238    if ((stencilop_valid(fail) &
239         stencilop_valid(zfail) &
240         stencilop_valid(zpass)) == 0) {
241        ogles_error(c, GL_INVALID_ENUM);
242        return;
243    }
244}
245
246// ----------------------------------------------------------------------------
247
248void glAlphaFunc(GLenum func, GLclampf ref)
249{
250    glAlphaFuncx(func, gglFloatToFixed(ref));
251}
252
253void glCullFace(GLenum mode)
254{
255    ogles_context_t* c = ogles_context_t::get();
256    switch (mode) {
257    case GL_FRONT:
258    case GL_BACK:
259    case GL_FRONT_AND_BACK:
260        break;
261    default:
262        ogles_error(c, GL_INVALID_ENUM);
263    }
264    c->cull.cullFace = mode;
265}
266
267void glFrontFace(GLenum mode)
268{
269    ogles_context_t* c = ogles_context_t::get();
270    switch (mode) {
271    case GL_CW:
272    case GL_CCW:
273        break;
274    default:
275        ogles_error(c, GL_INVALID_ENUM);
276        return;
277    }
278    c->cull.frontFace = mode;
279}
280
281void glHint(GLenum target, GLenum mode)
282{
283    ogles_context_t* c = ogles_context_t::get();
284    switch (target) {
285    case GL_FOG_HINT:
286    case GL_GENERATE_MIPMAP_HINT:
287    case GL_LINE_SMOOTH_HINT:
288        break;
289    case GL_POINT_SMOOTH_HINT:
290        c->rasterizer.procs.enableDisable(c,
291                GGL_POINT_SMOOTH_NICE, mode==GL_NICEST);
292        break;
293    case GL_PERSPECTIVE_CORRECTION_HINT:
294        c->perspective = (mode == GL_NICEST) ? 1 : 0;
295        break;
296    default:
297        ogles_error(c, GL_INVALID_ENUM);
298    }
299}
300
301void glEnable(GLenum cap) {
302    ogles_context_t* c = ogles_context_t::get();
303    enable_disable(c, cap, 1);
304}
305void glDisable(GLenum cap) {
306    ogles_context_t* c = ogles_context_t::get();
307    enable_disable(c, cap, 0);
308}
309
310void glFinish()
311{ // nothing to do for our software implementation
312}
313
314void glFlush()
315{ // nothing to do for our software implementation
316}
317
318GLenum glGetError()
319{
320    // From OpenGL|ES 1.0 specification:
321    // If more than one flag has recorded an error, glGetError returns
322    // and clears an arbitrary error flag value. Thus, glGetError should
323    // always be called in a loop, until it returns GL_NO_ERROR,
324    // if all error flags are to be reset.
325
326    ogles_context_t* c = ogles_context_t::get();
327    if (c->error) {
328        const GLenum ret(c->error);
329        c->error = 0;
330        return ret;
331    }
332
333    if (c->rasterizer.error) {
334        const GLenum ret(c->rasterizer.error);
335        c->rasterizer.error = 0;
336        return ret;
337    }
338
339    return GL_NO_ERROR;
340}
341
342const GLubyte* glGetString(GLenum string)
343{
344    switch (string) {
345    case GL_VENDOR:     return (const GLubyte*)gVendorString;
346    case GL_RENDERER:   return (const GLubyte*)gRendererString;
347    case GL_VERSION:    return (const GLubyte*)gVersionString;
348    case GL_EXTENSIONS: return (const GLubyte*)gExtensionsString;
349    }
350    ogles_context_t* c = ogles_context_t::get();
351    ogles_error(c, GL_INVALID_ENUM);
352    return 0;
353}
354
355void glGetIntegerv(GLenum pname, GLint *params)
356{
357    int i;
358    ogles_context_t* c = ogles_context_t::get();
359    switch (pname) {
360    case GL_ALIASED_POINT_SIZE_RANGE:
361        params[0] = 0;
362        params[1] = GGL_MAX_ALIASED_POINT_SIZE;
363        break;
364    case GL_ALIASED_LINE_WIDTH_RANGE:
365        params[0] = 0;
366        params[1] = GGL_MAX_ALIASED_POINT_SIZE;
367        break;
368    case GL_ALPHA_BITS: {
369        int index = c->rasterizer.state.buffers.color.format;
370        GGLFormat const * formats = gglGetPixelFormatTable();
371        params[0] = formats[index].ah - formats[index].al;
372        break;
373        }
374    case GL_RED_BITS: {
375        int index = c->rasterizer.state.buffers.color.format;
376        GGLFormat const * formats = gglGetPixelFormatTable();
377        params[0] = formats[index].rh - formats[index].rl;
378        break;
379        }
380    case GL_GREEN_BITS: {
381        int index = c->rasterizer.state.buffers.color.format;
382        GGLFormat const * formats = gglGetPixelFormatTable();
383        params[0] = formats[index].gh - formats[index].gl;
384        break;
385        }
386    case GL_BLUE_BITS: {
387        int index = c->rasterizer.state.buffers.color.format;
388        GGLFormat const * formats = gglGetPixelFormatTable();
389        params[0] = formats[index].bh - formats[index].bl;
390        break;
391        }
392    case GL_COMPRESSED_TEXTURE_FORMATS:
393        params[ 0] = GL_PALETTE4_RGB8_OES;
394        params[ 1] = GL_PALETTE4_RGBA8_OES;
395        params[ 2] = GL_PALETTE4_R5_G6_B5_OES;
396        params[ 3] = GL_PALETTE4_RGBA4_OES;
397        params[ 4] = GL_PALETTE4_RGB5_A1_OES;
398        params[ 5] = GL_PALETTE8_RGB8_OES;
399        params[ 6] = GL_PALETTE8_RGBA8_OES;
400        params[ 7] = GL_PALETTE8_R5_G6_B5_OES;
401        params[ 8] = GL_PALETTE8_RGBA4_OES;
402        params[ 9] = GL_PALETTE8_RGB5_A1_OES;
403        i = 10;
404#ifdef GL_OES_compressed_ETC1_RGB8_texture
405        params[i++] = GL_ETC1_RGB8_OES;
406#endif
407        break;
408    case GL_DEPTH_BITS:
409        params[0] = c->rasterizer.state.buffers.depth.format ? 0 : 16;
410        break;
411    case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
412        params[0] = GL_RGB;
413        break;
414    case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
415        params[0] = GL_UNSIGNED_SHORT_5_6_5;
416        break;
417    case GL_MAX_LIGHTS:
418        params[0] = OGLES_MAX_LIGHTS;
419        break;
420    case GL_MAX_CLIP_PLANES:
421        params[0] = OGLES_MAX_CLIP_PLANES;
422        break;
423    case GL_MAX_MODELVIEW_STACK_DEPTH:
424        params[0] = OGLES_MODELVIEW_STACK_DEPTH;
425        break;
426    case GL_MAX_PROJECTION_STACK_DEPTH:
427        params[0] = OGLES_PROJECTION_STACK_DEPTH;
428        break;
429    case GL_MAX_TEXTURE_STACK_DEPTH:
430        params[0] = OGLES_TEXTURE_STACK_DEPTH;
431        break;
432    case GL_MAX_TEXTURE_SIZE:
433        params[0] = GGL_MAX_TEXTURE_SIZE;
434        break;
435    case GL_MAX_TEXTURE_UNITS:
436        params[0] = GGL_TEXTURE_UNIT_COUNT;
437        break;
438    case GL_MAX_VIEWPORT_DIMS:
439        params[0] = GGL_MAX_VIEWPORT_DIMS;
440        params[1] = GGL_MAX_VIEWPORT_DIMS;
441        break;
442    case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
443        params[0] = OGLES_NUM_COMPRESSED_TEXTURE_FORMATS;
444        break;
445    case GL_SMOOTH_LINE_WIDTH_RANGE:
446        params[0] = 0;
447        params[1] = GGL_MAX_SMOOTH_LINE_WIDTH;
448        break;
449    case GL_SMOOTH_POINT_SIZE_RANGE:
450        params[0] = 0;
451        params[1] = GGL_MAX_SMOOTH_POINT_SIZE;
452        break;
453    case GL_STENCIL_BITS:
454        params[0] = 0;
455        break;
456    case GL_SUBPIXEL_BITS:
457        params[0] = GGL_SUBPIXEL_BITS;
458        break;
459
460    case GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES:
461        memcpy( params,
462                c->transforms.modelview.top().elements(),
463                16*sizeof(GLint));
464        break;
465    case GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES:
466        memcpy( params,
467                c->transforms.projection.top().elements(),
468                16*sizeof(GLint));
469        break;
470    case GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES:
471        memcpy( params,
472                c->transforms.texture[c->textures.active].top().elements(),
473                16*sizeof(GLint));
474        break;
475
476    default:
477        ogles_error(c, GL_INVALID_ENUM);
478        break;
479    }
480}
481
482// ----------------------------------------------------------------------------
483
484void glPointSize(GLfloat size)
485{
486    ogles_context_t* c = ogles_context_t::get();
487    if (size <= 0) {
488        ogles_error(c, GL_INVALID_ENUM);
489        return;
490    }
491    c->point.size = TRI_FROM_FIXED(gglFloatToFixed(size));
492}
493
494void glPointSizex(GLfixed size)
495{
496    ogles_context_t* c = ogles_context_t::get();
497    if (size <= 0) {
498        ogles_error(c, GL_INVALID_ENUM);
499        return;
500    }
501    c->point.size = TRI_FROM_FIXED(size);
502}
503
504// ----------------------------------------------------------------------------
505
506void glLineWidth(GLfloat width)
507{
508    ogles_context_t* c = ogles_context_t::get();
509    if (width <= 0) {
510        ogles_error(c, GL_INVALID_ENUM);
511        return;
512    }
513    c->line.width = TRI_FROM_FIXED(gglFloatToFixed(width));
514}
515
516void glLineWidthx(GLfixed width)
517{
518    ogles_context_t* c = ogles_context_t::get();
519    if (width <= 0) {
520        ogles_error(c, GL_INVALID_ENUM);
521        return;
522    }
523    c->line.width = TRI_FROM_FIXED(width);
524}
525
526// ----------------------------------------------------------------------------
527
528void glColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
529    ogles_context_t* c = ogles_context_t::get();
530    c->rasterizer.procs.colorMask(c, r, g, b, a);
531}
532
533void glDepthMask(GLboolean flag) {
534    ogles_context_t* c = ogles_context_t::get();
535    c->rasterizer.procs.depthMask(c, flag);
536}
537
538void glStencilMask(GLuint mask) {
539    ogles_context_t* c = ogles_context_t::get();
540    c->rasterizer.procs.stencilMask(c, mask);
541}
542
543void glDepthFunc(GLenum func) {
544    ogles_context_t* c = ogles_context_t::get();
545    c->rasterizer.procs.depthFunc(c, func);
546}
547
548void glLogicOp(GLenum opcode) {
549    ogles_context_t* c = ogles_context_t::get();
550    c->rasterizer.procs.logicOp(c, opcode);
551}
552
553void glAlphaFuncx(GLenum func, GLclampx ref) {
554    ogles_context_t* c = ogles_context_t::get();
555    c->rasterizer.procs.alphaFuncx(c, func, ref);
556}
557
558void glBlendFunc(GLenum sfactor, GLenum dfactor) {
559    ogles_context_t* c = ogles_context_t::get();
560    c->rasterizer.procs.blendFunc(c, sfactor, dfactor);
561}
562
563void glClear(GLbitfield mask) {
564    ogles_context_t* c = ogles_context_t::get();
565    c->rasterizer.procs.clear(c, mask);
566}
567
568void glClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) {
569    ogles_context_t* c = ogles_context_t::get();
570    c->rasterizer.procs.clearColorx(c, red, green, blue, alpha);
571}
572
573void glClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a)
574{
575    ogles_context_t* c = ogles_context_t::get();
576    c->rasterizer.procs.clearColorx(c,
577                    gglFloatToFixed(r),
578                    gglFloatToFixed(g),
579                    gglFloatToFixed(b),
580                    gglFloatToFixed(a));
581}
582
583void glClearDepthx(GLclampx depth) {
584    ogles_context_t* c = ogles_context_t::get();
585    c->rasterizer.procs.clearDepthx(c, depth);
586}
587
588void glClearDepthf(GLclampf depth)
589{
590    ogles_context_t* c = ogles_context_t::get();
591    c->rasterizer.procs.clearDepthx(c, gglFloatToFixed(depth));
592}
593
594void glClearStencil(GLint s) {
595    ogles_context_t* c = ogles_context_t::get();
596    c->rasterizer.procs.clearStencil(c, s);
597}
598