Home | History | Annotate | Download | only in libagl
      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