blob: 90e9612b83869be845d6c8a26aacf482e16177e0 [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 Agopianf91bff92010-10-19 14:47:08 -070036static char const * const gRendererString = "Android PixelFlinger 1.4";
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 Agopianf319e2f2011-08-18 16:26:21 -0700194 case GL_TEXTURE_EXTERNAL_OES:
195 c->rasterizer.procs.enableDisable(c, GL_TEXTURE_2D, enabled);
196 break;
Mathias Agopian1473f462009-04-10 14:24:30 -0700197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 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:
Mathias Agopian1473f462009-04-10 14:24:30 -0700290 c->rasterizer.procs.enableDisable(c,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 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 }
Mathias Agopian1473f462009-04-10 14:24:30 -0700332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 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{
Mathias Agopiand1f73a22010-02-01 18:24:52 -0800357 int i;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 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;
Mathias Agopian1473f462009-04-10 14:24:30 -0700372 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373 }
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;
Mathias Agopian1473f462009-04-10 14:24:30 -0700378 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 }
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;
Mathias Agopian1473f462009-04-10 14:24:30 -0700384 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 }
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;
Mathias Agopian1473f462009-04-10 14:24:30 -0700390 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 }
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;
Mathias Agopiand1f73a22010-02-01 18:24:52 -0800403 i = 10;
404#ifdef GL_OES_compressed_ETC1_RGB8_texture
405 params[i++] = GL_ETC1_RGB8_OES;
406#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 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}