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