blob: a0f720a0d19b382159b6b6d490479dc2bfaf4553 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* libs/opengles/state.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
Mathias Agopian1473f462009-04-10 14:24:30 -07005** 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008**
Mathias Agopian1473f462009-04-10 14:24:30 -07009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010**
Mathias Agopian1473f462009-04-10 14:24:30 -070011** 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015** 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";
Mathias Agopian57e48652010-03-25 20:21:12 -070036static char const * const gRendererString = "Android PixelFlinger 1.3";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037static 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
Mathias Agopian1473f462009-04-10 14:24:30 -070049 "GL_OES_EGL_image " // OK
Mathias Agopiand1f73a22010-02-01 18:24:52 -080050#ifdef GL_OES_compressed_ETC1_RGB8_texture
51 "GL_OES_compressed_ETC1_RGB8_texture " // OK
52#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 "GL_ARB_texture_compression " // OK
54 "GL_ARB_texture_non_power_of_two " // OK
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055 "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);
Mathias Agopian1473f462009-04-10 14:24:30 -070068 if (!base) return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069
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));
Mathias Agopian1473f462009-04-10 14:24:30 -070074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 // 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;
Mathias Agopian1473f462009-04-10 14:24:30 -070093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094 // in OpenGL, writing to the depth buffer is enabled by default.
95 c->rasterizer.procs.depthMask(c, 1);
Mathias Agopian1473f462009-04-10 14:24:30 -070096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 // 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));
Mathias Agopian1473f462009-04-10 14:24:30 -0700113 free(c->rasterizer.base);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114}
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;
Mathias Agopian1473f462009-04-10 14:24:30 -0700194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 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:
Mathias Agopian1473f462009-04-10 14:24:30 -0700287 c->rasterizer.procs.enableDisable(c,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 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 }
Mathias Agopian1473f462009-04-10 14:24:30 -0700329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 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{
Mathias Agopiand1f73a22010-02-01 18:24:52 -0800354 int i;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 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;
Mathias Agopian1473f462009-04-10 14:24:30 -0700369 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 }
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;
Mathias Agopian1473f462009-04-10 14:24:30 -0700375 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 }
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;
Mathias Agopian1473f462009-04-10 14:24:30 -0700381 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382 }
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;
Mathias Agopian1473f462009-04-10 14:24:30 -0700387 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 }
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;
Mathias Agopiand1f73a22010-02-01 18:24:52 -0800400 i = 10;
401#ifdef GL_OES_compressed_ETC1_RGB8_texture
402 params[i++] = GL_ETC1_RGB8_OES;
403#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 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}