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 31 namespace android { 32 33 // ---------------------------------------------------------------------------- 34 35 static char const * const gVendorString = "Android"; 36 static char const * const gRendererString = "Android PixelFlinger 1.4"; 37 static char const * const gVersionString = "OpenGL ES-CM 1.0"; 38 static 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_OES_EGL_image " // OK 50 #ifdef GL_OES_compressed_ETC1_RGB8_texture 51 "GL_OES_compressed_ETC1_RGB8_texture " // OK 52 #endif 53 "GL_ARB_texture_compression " // OK 54 "GL_ARB_texture_non_power_of_two " // OK 55 "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 65 ogles_context_t *ogles_init(size_t extra) 66 { 67 void* const base = malloc(extra + sizeof(ogles_context_t) + 32); 68 if (!base) return 0; 69 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)); 74 75 // 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; 93 94 // in OpenGL, writing to the depth buffer is enabled by default. 95 c->rasterizer.procs.depthMask(c, 1); 96 97 // OpenGL enables dithering by default 98 c->rasterizer.procs.enable(c, GL_DITHER); 99 100 return c; 101 } 102 103 void 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)); 113 free(c->rasterizer.base); 114 } 115 116 void _ogles_error(ogles_context_t* c, GLenum error) 117 { 118 if (c->error == GL_NO_ERROR) 119 c->error = error; 120 } 121 122 static 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 135 static 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; 194 case GL_TEXTURE_EXTERNAL_OES: 195 c->rasterizer.procs.enableDisable(c, GL_TEXTURE_2D, enabled); 196 break; 197 198 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 // ---------------------------------------------------------------------------- 214 using namespace android; 215 216 #if 0 217 #pragma mark - 218 #endif 219 220 // These ones are super-easy, we're not supporting those features! 221 void glSampleCoverage(GLclampf value, GLboolean invert) { 222 } 223 void glSampleCoveragex(GLclampx value, GLboolean invert) { 224 } 225 void 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 236 void 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 248 void glAlphaFunc(GLenum func, GLclampf ref) 249 { 250 glAlphaFuncx(func, gglFloatToFixed(ref)); 251 } 252 253 void 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 267 void 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 281 void 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: 290 c->rasterizer.procs.enableDisable(c, 291 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 301 void glEnable(GLenum cap) { 302 ogles_context_t* c = ogles_context_t::get(); 303 enable_disable(c, cap, 1); 304 } 305 void glDisable(GLenum cap) { 306 ogles_context_t* c = ogles_context_t::get(); 307 enable_disable(c, cap, 0); 308 } 309 310 void glFinish() 311 { // nothing to do for our software implementation 312 } 313 314 void glFlush() 315 { // nothing to do for our software implementation 316 } 317 318 GLenum 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 } 332 333 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 342 const 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 355 void glGetIntegerv(GLenum pname, GLint *params) 356 { 357 int i; 358 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; 372 break; 373 } 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; 378 break; 379 } 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; 384 break; 385 } 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; 390 break; 391 } 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; 403 i = 10; 404 #ifdef GL_OES_compressed_ETC1_RGB8_texture 405 params[i++] = GL_ETC1_RGB8_OES; 406 #endif 407 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 484 void 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 494 void 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 506 void 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 516 void 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 528 void 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 533 void glDepthMask(GLboolean flag) { 534 ogles_context_t* c = ogles_context_t::get(); 535 c->rasterizer.procs.depthMask(c, flag); 536 } 537 538 void glStencilMask(GLuint mask) { 539 ogles_context_t* c = ogles_context_t::get(); 540 c->rasterizer.procs.stencilMask(c, mask); 541 } 542 543 void glDepthFunc(GLenum func) { 544 ogles_context_t* c = ogles_context_t::get(); 545 c->rasterizer.procs.depthFunc(c, func); 546 } 547 548 void glLogicOp(GLenum opcode) { 549 ogles_context_t* c = ogles_context_t::get(); 550 c->rasterizer.procs.logicOp(c, opcode); 551 } 552 553 void glAlphaFuncx(GLenum func, GLclampx ref) { 554 ogles_context_t* c = ogles_context_t::get(); 555 c->rasterizer.procs.alphaFuncx(c, func, ref); 556 } 557 558 void glBlendFunc(GLenum sfactor, GLenum dfactor) { 559 ogles_context_t* c = ogles_context_t::get(); 560 c->rasterizer.procs.blendFunc(c, sfactor, dfactor); 561 } 562 563 void glClear(GLbitfield mask) { 564 ogles_context_t* c = ogles_context_t::get(); 565 c->rasterizer.procs.clear(c, mask); 566 } 567 568 void 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 573 void 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 583 void glClearDepthx(GLclampx depth) { 584 ogles_context_t* c = ogles_context_t::get(); 585 c->rasterizer.procs.clearDepthx(c, depth); 586 } 587 588 void glClearDepthf(GLclampf depth) 589 { 590 ogles_context_t* c = ogles_context_t::get(); 591 c->rasterizer.procs.clearDepthx(c, gglFloatToFixed(depth)); 592 } 593 594 void glClearStencil(GLint s) { 595 ogles_context_t* c = ogles_context_t::get(); 596 c->rasterizer.procs.clearStencil(c, s); 597 } 598