state.cpp revision 7c1b96a165f970a09ed239bb4fb3f1b0d8f2a407
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_ELEMENTS_INDICES:
407        params[0] = 65536;
408        break;
409    case GL_MAX_ELEMENTS_VERTICES:
410        params[0] = 0x7FFFFFFF;
411        break;
412    case GL_MAX_LIGHTS:
413        params[0] = OGLES_MAX_LIGHTS;
414        break;
415    case GL_MAX_CLIP_PLANES:
416        params[0] = OGLES_MAX_CLIP_PLANES;
417        break;
418    case GL_MAX_MODELVIEW_STACK_DEPTH:
419        params[0] = OGLES_MODELVIEW_STACK_DEPTH;
420        break;
421    case GL_MAX_PROJECTION_STACK_DEPTH:
422        params[0] = OGLES_PROJECTION_STACK_DEPTH;
423        break;
424    case GL_MAX_TEXTURE_STACK_DEPTH:
425        params[0] = OGLES_TEXTURE_STACK_DEPTH;
426        break;
427    case GL_MAX_TEXTURE_SIZE:
428        params[0] = GGL_MAX_TEXTURE_SIZE;
429        break;
430    case GL_MAX_TEXTURE_UNITS:
431        params[0] = GGL_TEXTURE_UNIT_COUNT;
432        break;
433    case GL_MAX_VIEWPORT_DIMS:
434        params[0] = GGL_MAX_VIEWPORT_DIMS;
435        params[1] = GGL_MAX_VIEWPORT_DIMS;
436        break;
437    case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
438        params[0] = OGLES_NUM_COMPRESSED_TEXTURE_FORMATS;
439        break;
440    case GL_SMOOTH_LINE_WIDTH_RANGE:
441        params[0] = 0;
442        params[1] = GGL_MAX_SMOOTH_LINE_WIDTH;
443        break;
444    case GL_SMOOTH_POINT_SIZE_RANGE:
445        params[0] = 0;
446        params[1] = GGL_MAX_SMOOTH_POINT_SIZE;
447        break;
448    case GL_STENCIL_BITS:
449        params[0] = 0;
450        break;
451    case GL_SUBPIXEL_BITS:
452        params[0] = GGL_SUBPIXEL_BITS;
453        break;
454
455    case GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES:
456        memcpy( params,
457                c->transforms.modelview.top().elements(),
458                16*sizeof(GLint));
459        break;
460    case GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES:
461        memcpy( params,
462                c->transforms.projection.top().elements(),
463                16*sizeof(GLint));
464        break;
465    case GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES:
466        memcpy( params,
467                c->transforms.texture[c->textures.active].top().elements(),
468                16*sizeof(GLint));
469        break;
470
471    default:
472        ogles_error(c, GL_INVALID_ENUM);
473        break;
474    }
475}
476
477// ----------------------------------------------------------------------------
478
479void glPointSize(GLfloat size)
480{
481    ogles_context_t* c = ogles_context_t::get();
482    if (size <= 0) {
483        ogles_error(c, GL_INVALID_ENUM);
484        return;
485    }
486    c->point.size = TRI_FROM_FIXED(gglFloatToFixed(size));
487}
488
489void glPointSizex(GLfixed size)
490{
491    ogles_context_t* c = ogles_context_t::get();
492    if (size <= 0) {
493        ogles_error(c, GL_INVALID_ENUM);
494        return;
495    }
496    c->point.size = TRI_FROM_FIXED(size);
497}
498
499// ----------------------------------------------------------------------------
500
501void glLineWidth(GLfloat width)
502{
503    ogles_context_t* c = ogles_context_t::get();
504    if (width <= 0) {
505        ogles_error(c, GL_INVALID_ENUM);
506        return;
507    }
508    c->line.width = TRI_FROM_FIXED(gglFloatToFixed(width));
509}
510
511void glLineWidthx(GLfixed width)
512{
513    ogles_context_t* c = ogles_context_t::get();
514    if (width <= 0) {
515        ogles_error(c, GL_INVALID_ENUM);
516        return;
517    }
518    c->line.width = TRI_FROM_FIXED(width);
519}
520
521// ----------------------------------------------------------------------------
522
523void glColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
524    ogles_context_t* c = ogles_context_t::get();
525    c->rasterizer.procs.colorMask(c, r, g, b, a);
526}
527
528void glDepthMask(GLboolean flag) {
529    ogles_context_t* c = ogles_context_t::get();
530    c->rasterizer.procs.depthMask(c, flag);
531}
532
533void glStencilMask(GLuint mask) {
534    ogles_context_t* c = ogles_context_t::get();
535    c->rasterizer.procs.stencilMask(c, mask);
536}
537
538void glDepthFunc(GLenum func) {
539    ogles_context_t* c = ogles_context_t::get();
540    c->rasterizer.procs.depthFunc(c, func);
541}
542
543void glLogicOp(GLenum opcode) {
544    ogles_context_t* c = ogles_context_t::get();
545    c->rasterizer.procs.logicOp(c, opcode);
546}
547
548void glAlphaFuncx(GLenum func, GLclampx ref) {
549    ogles_context_t* c = ogles_context_t::get();
550    c->rasterizer.procs.alphaFuncx(c, func, ref);
551}
552
553void glBlendFunc(GLenum sfactor, GLenum dfactor) {
554    ogles_context_t* c = ogles_context_t::get();
555    c->rasterizer.procs.blendFunc(c, sfactor, dfactor);
556}
557
558void glClear(GLbitfield mask) {
559    ogles_context_t* c = ogles_context_t::get();
560    c->rasterizer.procs.clear(c, mask);
561}
562
563void glClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) {
564    ogles_context_t* c = ogles_context_t::get();
565    c->rasterizer.procs.clearColorx(c, red, green, blue, alpha);
566}
567
568void glClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a)
569{
570    ogles_context_t* c = ogles_context_t::get();
571    c->rasterizer.procs.clearColorx(c,
572                    gglFloatToFixed(r),
573                    gglFloatToFixed(g),
574                    gglFloatToFixed(b),
575                    gglFloatToFixed(a));
576}
577
578void glClearDepthx(GLclampx depth) {
579    ogles_context_t* c = ogles_context_t::get();
580    c->rasterizer.procs.clearDepthx(c, depth);
581}
582
583void glClearDepthf(GLclampf depth)
584{
585    ogles_context_t* c = ogles_context_t::get();
586    c->rasterizer.procs.clearDepthx(c, gglFloatToFixed(depth));
587}
588
589void glClearStencil(GLint s) {
590    ogles_context_t* c = ogles_context_t::get();
591    c->rasterizer.procs.clearStencil(c, s);
592}
593