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     "GL_OES_EGL_sync "                      // OK
     51 #ifdef GL_OES_compressed_ETC1_RGB8_texture
     52     "GL_OES_compressed_ETC1_RGB8_texture "  // OK
     53 #endif
     54     "GL_ARB_texture_compression "           // OK
     55     "GL_ARB_texture_non_power_of_two "      // OK
     56     "GL_ANDROID_user_clip_plane "           // OK
     57     "GL_ANDROID_vertex_buffer_object "      // OK
     58     "GL_ANDROID_generate_mipmap "           // OK
     59     ;
     60 
     61 // ----------------------------------------------------------------------------
     62 #if 0
     63 #pragma mark -
     64 #endif
     65 
     66 ogles_context_t *ogles_init(size_t extra)
     67 {
     68     void* const base = malloc(extra + sizeof(ogles_context_t) + 32);
     69     if (!base) return 0;
     70 
     71     ogles_context_t *c =
     72             (ogles_context_t *)((ptrdiff_t(base) + extra + 31) & ~0x1FL);
     73     memset(c, 0, sizeof(ogles_context_t));
     74     ggl_init_context(&(c->rasterizer));
     75 
     76     // XXX: this should be passed as an argument
     77     sp<EGLSurfaceManager> smgr(new EGLSurfaceManager());
     78     c->surfaceManager = smgr.get();
     79     c->surfaceManager->incStrong(c);
     80 
     81     sp<EGLBufferObjectManager> bomgr(new EGLBufferObjectManager());
     82     c->bufferObjectManager = bomgr.get();
     83     c->bufferObjectManager->incStrong(c);
     84 
     85     ogles_init_array(c);
     86     ogles_init_matrix(c);
     87     ogles_init_vertex(c);
     88     ogles_init_light(c);
     89     ogles_init_texture(c);
     90 
     91     c->rasterizer.base = base;
     92     c->point.size = TRI_ONE;
     93     c->line.width = TRI_ONE;
     94 
     95     // in OpenGL, writing to the depth buffer is enabled by default.
     96     c->rasterizer.procs.depthMask(c, 1);
     97 
     98     // OpenGL enables dithering by default
     99     c->rasterizer.procs.enable(c, GL_DITHER);
    100 
    101     return c;
    102 }
    103 
    104 void ogles_uninit(ogles_context_t* c)
    105 {
    106     ogles_uninit_array(c);
    107     ogles_uninit_matrix(c);
    108     ogles_uninit_vertex(c);
    109     ogles_uninit_light(c);
    110     ogles_uninit_texture(c);
    111     c->surfaceManager->decStrong(c);
    112     c->bufferObjectManager->decStrong(c);
    113     ggl_uninit_context(&(c->rasterizer));
    114     free(c->rasterizer.base);
    115 }
    116 
    117 void _ogles_error(ogles_context_t* c, GLenum error)
    118 {
    119     if (c->error == GL_NO_ERROR)
    120         c->error = error;
    121 }
    122 
    123 static bool stencilop_valid(GLenum op) {
    124     switch (op) {
    125     case GL_KEEP:
    126     case GL_ZERO:
    127     case GL_REPLACE:
    128     case GL_INCR:
    129     case GL_DECR:
    130     case GL_INVERT:
    131         return true;
    132     }
    133     return false;
    134 }
    135 
    136 static void enable_disable(ogles_context_t* c, GLenum cap, int enabled)
    137 {
    138     if ((cap >= GL_LIGHT0) && (cap<GL_LIGHT0+OGLES_MAX_LIGHTS)) {
    139         c->lighting.lights[cap-GL_LIGHT0].enable = enabled;
    140         c->lighting.enabledLights &= ~(1<<(cap-GL_LIGHT0));
    141         c->lighting.enabledLights |= (enabled<<(cap-GL_LIGHT0));
    142         return;
    143     }
    144 
    145     switch (cap) {
    146     case GL_POINT_SMOOTH:
    147         c->point.smooth = enabled;
    148         break;
    149     case GL_LINE_SMOOTH:
    150         c->line.smooth = enabled;
    151         break;
    152     case GL_POLYGON_OFFSET_FILL:
    153         c->polygonOffset.enable = enabled;
    154         break;
    155     case GL_CULL_FACE:
    156         c->cull.enable = enabled;
    157         break;
    158     case GL_LIGHTING:
    159         c->lighting.enable = enabled;
    160         break;
    161     case GL_COLOR_MATERIAL:
    162         c->lighting.colorMaterial.enable = enabled;
    163         break;
    164     case GL_NORMALIZE:
    165     case GL_RESCALE_NORMAL:
    166         c->transforms.rescaleNormals = enabled ? cap : 0;
    167         // XXX: invalidate mvit
    168         break;
    169 
    170     case GL_CLIP_PLANE0:
    171     case GL_CLIP_PLANE1:
    172     case GL_CLIP_PLANE2:
    173     case GL_CLIP_PLANE3:
    174     case GL_CLIP_PLANE4:
    175     case GL_CLIP_PLANE5:
    176         c->clipPlanes.enable &= ~(1<<(cap-GL_CLIP_PLANE0));
    177         c->clipPlanes.enable |= (enabled<<(cap-GL_CLIP_PLANE0));
    178         ogles_invalidate_perspective(c);
    179         break;
    180 
    181     case GL_FOG:
    182     case GL_DEPTH_TEST:
    183         ogles_invalidate_perspective(c);
    184         // fall-through...
    185     case GL_BLEND:
    186     case GL_SCISSOR_TEST:
    187     case GL_ALPHA_TEST:
    188     case GL_COLOR_LOGIC_OP:
    189     case GL_DITHER:
    190     case GL_STENCIL_TEST:
    191     case GL_TEXTURE_2D:
    192         // these need to fall through into the rasterizer
    193         c->rasterizer.procs.enableDisable(c, cap, enabled);
    194         break;
    195     case GL_TEXTURE_EXTERNAL_OES:
    196         c->rasterizer.procs.enableDisable(c, GL_TEXTURE_2D, enabled);
    197         break;
    198 
    199     case GL_MULTISAMPLE:
    200     case GL_SAMPLE_ALPHA_TO_COVERAGE:
    201     case GL_SAMPLE_ALPHA_TO_ONE:
    202     case GL_SAMPLE_COVERAGE:
    203         // not supported in this implementation
    204         break;
    205 
    206     default:
    207         ogles_error(c, GL_INVALID_ENUM);
    208         return;
    209     }
    210 }
    211 
    212 // ----------------------------------------------------------------------------
    213 }; // namespace android
    214 // ----------------------------------------------------------------------------
    215 using namespace android;
    216 
    217 #if 0
    218 #pragma mark -
    219 #endif
    220 
    221 // These ones are super-easy, we're not supporting those features!
    222 void glSampleCoverage(GLclampf value, GLboolean invert) {
    223 }
    224 void glSampleCoveragex(GLclampx value, GLboolean invert) {
    225 }
    226 void glStencilFunc(GLenum func, GLint ref, GLuint mask) {
    227     ogles_context_t* c = ogles_context_t::get();
    228     if (func < GL_NEVER || func > GL_ALWAYS) {
    229         ogles_error(c, GL_INVALID_ENUM);
    230         return;
    231     }
    232     // from OpenGL|ES 1.0 sepcification:
    233     // If there is no stencil buffer, no stencil modification can occur
    234     // and it is as if the stencil test always passes.
    235 }
    236 
    237 void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
    238     ogles_context_t* c = ogles_context_t::get();
    239     if ((stencilop_valid(fail) &
    240          stencilop_valid(zfail) &
    241          stencilop_valid(zpass)) == 0) {
    242         ogles_error(c, GL_INVALID_ENUM);
    243         return;
    244     }
    245 }
    246 
    247 // ----------------------------------------------------------------------------
    248 
    249 void glAlphaFunc(GLenum func, GLclampf ref)
    250 {
    251     glAlphaFuncx(func, gglFloatToFixed(ref));
    252 }
    253 
    254 void glCullFace(GLenum mode)
    255 {
    256     ogles_context_t* c = ogles_context_t::get();
    257     switch (mode) {
    258     case GL_FRONT:
    259     case GL_BACK:
    260     case GL_FRONT_AND_BACK:
    261         break;
    262     default:
    263         ogles_error(c, GL_INVALID_ENUM);
    264     }
    265     c->cull.cullFace = mode;
    266 }
    267 
    268 void glFrontFace(GLenum mode)
    269 {
    270     ogles_context_t* c = ogles_context_t::get();
    271     switch (mode) {
    272     case GL_CW:
    273     case GL_CCW:
    274         break;
    275     default:
    276         ogles_error(c, GL_INVALID_ENUM);
    277         return;
    278     }
    279     c->cull.frontFace = mode;
    280 }
    281 
    282 void glHint(GLenum target, GLenum mode)
    283 {
    284     ogles_context_t* c = ogles_context_t::get();
    285     switch (target) {
    286     case GL_FOG_HINT:
    287     case GL_GENERATE_MIPMAP_HINT:
    288     case GL_LINE_SMOOTH_HINT:
    289         break;
    290     case GL_POINT_SMOOTH_HINT:
    291         c->rasterizer.procs.enableDisable(c,
    292                 GGL_POINT_SMOOTH_NICE, mode==GL_NICEST);
    293         break;
    294     case GL_PERSPECTIVE_CORRECTION_HINT:
    295         c->perspective = (mode == GL_NICEST) ? 1 : 0;
    296         break;
    297     default:
    298         ogles_error(c, GL_INVALID_ENUM);
    299     }
    300 }
    301 
    302 void glEnable(GLenum cap) {
    303     ogles_context_t* c = ogles_context_t::get();
    304     enable_disable(c, cap, 1);
    305 }
    306 void glDisable(GLenum cap) {
    307     ogles_context_t* c = ogles_context_t::get();
    308     enable_disable(c, cap, 0);
    309 }
    310 
    311 void glFinish()
    312 { // nothing to do for our software implementation
    313 }
    314 
    315 void glFlush()
    316 { // nothing to do for our software implementation
    317 }
    318 
    319 GLenum glGetError()
    320 {
    321     // From OpenGL|ES 1.0 specification:
    322     // If more than one flag has recorded an error, glGetError returns
    323     // and clears an arbitrary error flag value. Thus, glGetError should
    324     // always be called in a loop, until it returns GL_NO_ERROR,
    325     // if all error flags are to be reset.
    326 
    327     ogles_context_t* c = ogles_context_t::get();
    328     if (c->error) {
    329         const GLenum ret(c->error);
    330         c->error = 0;
    331         return ret;
    332     }
    333 
    334     if (c->rasterizer.error) {
    335         const GLenum ret(c->rasterizer.error);
    336         c->rasterizer.error = 0;
    337         return ret;
    338     }
    339 
    340     return GL_NO_ERROR;
    341 }
    342 
    343 const GLubyte* glGetString(GLenum string)
    344 {
    345     switch (string) {
    346     case GL_VENDOR:     return (const GLubyte*)gVendorString;
    347     case GL_RENDERER:   return (const GLubyte*)gRendererString;
    348     case GL_VERSION:    return (const GLubyte*)gVersionString;
    349     case GL_EXTENSIONS: return (const GLubyte*)gExtensionsString;
    350     }
    351     ogles_context_t* c = ogles_context_t::get();
    352     ogles_error(c, GL_INVALID_ENUM);
    353     return 0;
    354 }
    355 
    356 void glGetIntegerv(GLenum pname, GLint *params)
    357 {
    358     int i;
    359     ogles_context_t* c = ogles_context_t::get();
    360     switch (pname) {
    361     case GL_ALIASED_POINT_SIZE_RANGE:
    362         params[0] = 0;
    363         params[1] = GGL_MAX_ALIASED_POINT_SIZE;
    364         break;
    365     case GL_ALIASED_LINE_WIDTH_RANGE:
    366         params[0] = 0;
    367         params[1] = GGL_MAX_ALIASED_POINT_SIZE;
    368         break;
    369     case GL_ALPHA_BITS: {
    370         int index = c->rasterizer.state.buffers.color.format;
    371         GGLFormat const * formats = gglGetPixelFormatTable();
    372         params[0] = formats[index].ah - formats[index].al;
    373         break;
    374         }
    375     case GL_RED_BITS: {
    376         int index = c->rasterizer.state.buffers.color.format;
    377         GGLFormat const * formats = gglGetPixelFormatTable();
    378         params[0] = formats[index].rh - formats[index].rl;
    379         break;
    380         }
    381     case GL_GREEN_BITS: {
    382         int index = c->rasterizer.state.buffers.color.format;
    383         GGLFormat const * formats = gglGetPixelFormatTable();
    384         params[0] = formats[index].gh - formats[index].gl;
    385         break;
    386         }
    387     case GL_BLUE_BITS: {
    388         int index = c->rasterizer.state.buffers.color.format;
    389         GGLFormat const * formats = gglGetPixelFormatTable();
    390         params[0] = formats[index].bh - formats[index].bl;
    391         break;
    392         }
    393     case GL_COMPRESSED_TEXTURE_FORMATS:
    394         params[ 0] = GL_PALETTE4_RGB8_OES;
    395         params[ 1] = GL_PALETTE4_RGBA8_OES;
    396         params[ 2] = GL_PALETTE4_R5_G6_B5_OES;
    397         params[ 3] = GL_PALETTE4_RGBA4_OES;
    398         params[ 4] = GL_PALETTE4_RGB5_A1_OES;
    399         params[ 5] = GL_PALETTE8_RGB8_OES;
    400         params[ 6] = GL_PALETTE8_RGBA8_OES;
    401         params[ 7] = GL_PALETTE8_R5_G6_B5_OES;
    402         params[ 8] = GL_PALETTE8_RGBA4_OES;
    403         params[ 9] = GL_PALETTE8_RGB5_A1_OES;
    404         i = 10;
    405 #ifdef GL_OES_compressed_ETC1_RGB8_texture
    406         params[i++] = GL_ETC1_RGB8_OES;
    407 #endif
    408         break;
    409     case GL_DEPTH_BITS:
    410         params[0] = c->rasterizer.state.buffers.depth.format ? 0 : 16;
    411         break;
    412     case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
    413         params[0] = GL_RGB;
    414         break;
    415     case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
    416         params[0] = GL_UNSIGNED_SHORT_5_6_5;
    417         break;
    418     case GL_MAX_LIGHTS:
    419         params[0] = OGLES_MAX_LIGHTS;
    420         break;
    421     case GL_MAX_CLIP_PLANES:
    422         params[0] = OGLES_MAX_CLIP_PLANES;
    423         break;
    424     case GL_MAX_MODELVIEW_STACK_DEPTH:
    425         params[0] = OGLES_MODELVIEW_STACK_DEPTH;
    426         break;
    427     case GL_MAX_PROJECTION_STACK_DEPTH:
    428         params[0] = OGLES_PROJECTION_STACK_DEPTH;
    429         break;
    430     case GL_MAX_TEXTURE_STACK_DEPTH:
    431         params[0] = OGLES_TEXTURE_STACK_DEPTH;
    432         break;
    433     case GL_MAX_TEXTURE_SIZE:
    434         params[0] = GGL_MAX_TEXTURE_SIZE;
    435         break;
    436     case GL_MAX_TEXTURE_UNITS:
    437         params[0] = GGL_TEXTURE_UNIT_COUNT;
    438         break;
    439     case GL_MAX_VIEWPORT_DIMS:
    440         params[0] = GGL_MAX_VIEWPORT_DIMS;
    441         params[1] = GGL_MAX_VIEWPORT_DIMS;
    442         break;
    443     case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
    444         params[0] = OGLES_NUM_COMPRESSED_TEXTURE_FORMATS;
    445         break;
    446     case GL_SMOOTH_LINE_WIDTH_RANGE:
    447         params[0] = 0;
    448         params[1] = GGL_MAX_SMOOTH_LINE_WIDTH;
    449         break;
    450     case GL_SMOOTH_POINT_SIZE_RANGE:
    451         params[0] = 0;
    452         params[1] = GGL_MAX_SMOOTH_POINT_SIZE;
    453         break;
    454     case GL_STENCIL_BITS:
    455         params[0] = 0;
    456         break;
    457     case GL_SUBPIXEL_BITS:
    458         params[0] = GGL_SUBPIXEL_BITS;
    459         break;
    460 
    461     case GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES:
    462         memcpy( params,
    463                 c->transforms.modelview.top().elements(),
    464                 16*sizeof(GLint));
    465         break;
    466     case GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES:
    467         memcpy( params,
    468                 c->transforms.projection.top().elements(),
    469                 16*sizeof(GLint));
    470         break;
    471     case GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES:
    472         memcpy( params,
    473                 c->transforms.texture[c->textures.active].top().elements(),
    474                 16*sizeof(GLint));
    475         break;
    476 
    477     default:
    478         ogles_error(c, GL_INVALID_ENUM);
    479         break;
    480     }
    481 }
    482 
    483 // ----------------------------------------------------------------------------
    484 
    485 void glPointSize(GLfloat size)
    486 {
    487     ogles_context_t* c = ogles_context_t::get();
    488     if (size <= 0) {
    489         ogles_error(c, GL_INVALID_ENUM);
    490         return;
    491     }
    492     c->point.size = TRI_FROM_FIXED(gglFloatToFixed(size));
    493 }
    494 
    495 void glPointSizex(GLfixed size)
    496 {
    497     ogles_context_t* c = ogles_context_t::get();
    498     if (size <= 0) {
    499         ogles_error(c, GL_INVALID_ENUM);
    500         return;
    501     }
    502     c->point.size = TRI_FROM_FIXED(size);
    503 }
    504 
    505 // ----------------------------------------------------------------------------
    506 
    507 void glLineWidth(GLfloat width)
    508 {
    509     ogles_context_t* c = ogles_context_t::get();
    510     if (width <= 0) {
    511         ogles_error(c, GL_INVALID_ENUM);
    512         return;
    513     }
    514     c->line.width = TRI_FROM_FIXED(gglFloatToFixed(width));
    515 }
    516 
    517 void glLineWidthx(GLfixed width)
    518 {
    519     ogles_context_t* c = ogles_context_t::get();
    520     if (width <= 0) {
    521         ogles_error(c, GL_INVALID_ENUM);
    522         return;
    523     }
    524     c->line.width = TRI_FROM_FIXED(width);
    525 }
    526 
    527 // ----------------------------------------------------------------------------
    528 
    529 void glColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
    530     ogles_context_t* c = ogles_context_t::get();
    531     c->rasterizer.procs.colorMask(c, r, g, b, a);
    532 }
    533 
    534 void glDepthMask(GLboolean flag) {
    535     ogles_context_t* c = ogles_context_t::get();
    536     c->rasterizer.procs.depthMask(c, flag);
    537 }
    538 
    539 void glStencilMask(GLuint mask) {
    540     ogles_context_t* c = ogles_context_t::get();
    541     c->rasterizer.procs.stencilMask(c, mask);
    542 }
    543 
    544 void glDepthFunc(GLenum func) {
    545     ogles_context_t* c = ogles_context_t::get();
    546     c->rasterizer.procs.depthFunc(c, func);
    547 }
    548 
    549 void glLogicOp(GLenum opcode) {
    550     ogles_context_t* c = ogles_context_t::get();
    551     c->rasterizer.procs.logicOp(c, opcode);
    552 }
    553 
    554 void glAlphaFuncx(GLenum func, GLclampx ref) {
    555     ogles_context_t* c = ogles_context_t::get();
    556     c->rasterizer.procs.alphaFuncx(c, func, ref);
    557 }
    558 
    559 void glBlendFunc(GLenum sfactor, GLenum dfactor) {
    560     ogles_context_t* c = ogles_context_t::get();
    561     c->rasterizer.procs.blendFunc(c, sfactor, dfactor);
    562 }
    563 
    564 void glClear(GLbitfield mask) {
    565     ogles_context_t* c = ogles_context_t::get();
    566     c->rasterizer.procs.clear(c, mask);
    567 }
    568 
    569 void glClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) {
    570     ogles_context_t* c = ogles_context_t::get();
    571     c->rasterizer.procs.clearColorx(c, red, green, blue, alpha);
    572 }
    573 
    574 void glClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a)
    575 {
    576     ogles_context_t* c = ogles_context_t::get();
    577     c->rasterizer.procs.clearColorx(c,
    578                     gglFloatToFixed(r),
    579                     gglFloatToFixed(g),
    580                     gglFloatToFixed(b),
    581                     gglFloatToFixed(a));
    582 }
    583 
    584 void glClearDepthx(GLclampx depth) {
    585     ogles_context_t* c = ogles_context_t::get();
    586     c->rasterizer.procs.clearDepthx(c, depth);
    587 }
    588 
    589 void glClearDepthf(GLclampf depth)
    590 {
    591     ogles_context_t* c = ogles_context_t::get();
    592     c->rasterizer.procs.clearDepthx(c, gglFloatToFixed(depth));
    593 }
    594 
    595 void glClearStencil(GLint s) {
    596     ogles_context_t* c = ogles_context_t::get();
    597     c->rasterizer.procs.clearStencil(c, s);
    598 }
    599