blob: 5cbabea1f8a8e547fcd33272d02547c90c0ca840 [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**
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}