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 
    195     case GL_MULTISAMPLE:
    196     case GL_SAMPLE_ALPHA_TO_COVERAGE:
    197     case GL_SAMPLE_ALPHA_TO_ONE:
    198     case GL_SAMPLE_COVERAGE:
    199         // not supported in this implementation
    200         break;
    201 
    202     default:
    203         ogles_error(c, GL_INVALID_ENUM);
    204         return;
    205     }
    206 }
    207 
    208 // ----------------------------------------------------------------------------
    209 }; // namespace android
    210 // ----------------------------------------------------------------------------
    211 using namespace android;
    212 
    213 #if 0
    214 #pragma mark -
    215 #endif
    216 
    217 // These ones are super-easy, we're not supporting those features!
    218 void glSampleCoverage(GLclampf value, GLboolean invert) {
    219 }
    220 void glSampleCoveragex(GLclampx value, GLboolean invert) {
    221 }
    222 void glStencilFunc(GLenum func, GLint ref, GLuint mask) {
    223     ogles_context_t* c = ogles_context_t::get();
    224     if (func < GL_NEVER || func > GL_ALWAYS) {
    225         ogles_error(c, GL_INVALID_ENUM);
    226         return;
    227     }
    228     // from OpenGL|ES 1.0 sepcification:
    229     // If there is no stencil buffer, no stencil modification can occur
    230     // and it is as if the stencil test always passes.
    231 }
    232 
    233 void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
    234     ogles_context_t* c = ogles_context_t::get();
    235     if ((stencilop_valid(fail) &
    236          stencilop_valid(zfail) &
    237          stencilop_valid(zpass)) == 0) {
    238         ogles_error(c, GL_INVALID_ENUM);
    239         return;
    240     }
    241 }
    242 
    243 // ----------------------------------------------------------------------------
    244 
    245 void glAlphaFunc(GLenum func, GLclampf ref)
    246 {
    247     glAlphaFuncx(func, gglFloatToFixed(ref));
    248 }
    249 
    250 void glCullFace(GLenum mode)
    251 {
    252     ogles_context_t* c = ogles_context_t::get();
    253     switch (mode) {
    254     case GL_FRONT:
    255     case GL_BACK:
    256     case GL_FRONT_AND_BACK:
    257         break;
    258     default:
    259         ogles_error(c, GL_INVALID_ENUM);
    260     }
    261     c->cull.cullFace = mode;
    262 }
    263 
    264 void glFrontFace(GLenum mode)
    265 {
    266     ogles_context_t* c = ogles_context_t::get();
    267     switch (mode) {
    268     case GL_CW:
    269     case GL_CCW:
    270         break;
    271     default:
    272         ogles_error(c, GL_INVALID_ENUM);
    273         return;
    274     }
    275     c->cull.frontFace = mode;
    276 }
    277 
    278 void glHint(GLenum target, GLenum mode)
    279 {
    280     ogles_context_t* c = ogles_context_t::get();
    281     switch (target) {
    282     case GL_FOG_HINT:
    283     case GL_GENERATE_MIPMAP_HINT:
    284     case GL_LINE_SMOOTH_HINT:
    285         break;
    286     case GL_POINT_SMOOTH_HINT:
    287         c->rasterizer.procs.enableDisable(c,
    288                 GGL_POINT_SMOOTH_NICE, mode==GL_NICEST);
    289         break;
    290     case GL_PERSPECTIVE_CORRECTION_HINT:
    291         c->perspective = (mode == GL_NICEST) ? 1 : 0;
    292         break;
    293     default:
    294         ogles_error(c, GL_INVALID_ENUM);
    295     }
    296 }
    297 
    298 void glEnable(GLenum cap) {
    299     ogles_context_t* c = ogles_context_t::get();
    300     enable_disable(c, cap, 1);
    301 }
    302 void glDisable(GLenum cap) {
    303     ogles_context_t* c = ogles_context_t::get();
    304     enable_disable(c, cap, 0);
    305 }
    306 
    307 void glFinish()
    308 { // nothing to do for our software implementation
    309 }
    310 
    311 void glFlush()
    312 { // nothing to do for our software implementation
    313 }
    314 
    315 GLenum glGetError()
    316 {
    317     // From OpenGL|ES 1.0 specification:
    318     // If more than one flag has recorded an error, glGetError returns
    319     // and clears an arbitrary error flag value. Thus, glGetError should
    320     // always be called in a loop, until it returns GL_NO_ERROR,
    321     // if all error flags are to be reset.
    322 
    323     ogles_context_t* c = ogles_context_t::get();
    324     if (c->error) {
    325         const GLenum ret(c->error);
    326         c->error = 0;
    327         return ret;
    328     }
    329 
    330     if (c->rasterizer.error) {
    331         const GLenum ret(c->rasterizer.error);
    332         c->rasterizer.error = 0;
    333         return ret;
    334     }
    335 
    336     return GL_NO_ERROR;
    337 }
    338 
    339 const GLubyte* glGetString(GLenum string)
    340 {
    341     switch (string) {
    342     case GL_VENDOR:     return (const GLubyte*)gVendorString;
    343     case GL_RENDERER:   return (const GLubyte*)gRendererString;
    344     case GL_VERSION:    return (const GLubyte*)gVersionString;
    345     case GL_EXTENSIONS: return (const GLubyte*)gExtensionsString;
    346     }
    347     ogles_context_t* c = ogles_context_t::get();
    348     ogles_error(c, GL_INVALID_ENUM);
    349     return 0;
    350 }
    351 
    352 void glGetIntegerv(GLenum pname, GLint *params)
    353 {
    354     int i;
    355     ogles_context_t* c = ogles_context_t::get();
    356     switch (pname) {
    357     case GL_ALIASED_POINT_SIZE_RANGE:
    358         params[0] = 0;
    359         params[1] = GGL_MAX_ALIASED_POINT_SIZE;
    360         break;
    361     case GL_ALIASED_LINE_WIDTH_RANGE:
    362         params[0] = 0;
    363         params[1] = GGL_MAX_ALIASED_POINT_SIZE;
    364         break;
    365     case GL_ALPHA_BITS: {
    366         int index = c->rasterizer.state.buffers.color.format;
    367         GGLFormat const * formats = gglGetPixelFormatTable();
    368         params[0] = formats[index].ah - formats[index].al;
    369         break;
    370         }
    371     case GL_RED_BITS: {
    372         int index = c->rasterizer.state.buffers.color.format;
    373         GGLFormat const * formats = gglGetPixelFormatTable();
    374         params[0] = formats[index].rh - formats[index].rl;
    375         break;
    376         }
    377     case GL_GREEN_BITS: {
    378         int index = c->rasterizer.state.buffers.color.format;
    379         GGLFormat const * formats = gglGetPixelFormatTable();
    380         params[0] = formats[index].gh - formats[index].gl;
    381         break;
    382         }
    383     case GL_BLUE_BITS: {
    384         int index = c->rasterizer.state.buffers.color.format;
    385         GGLFormat const * formats = gglGetPixelFormatTable();
    386         params[0] = formats[index].bh - formats[index].bl;
    387         break;
    388         }
    389     case GL_COMPRESSED_TEXTURE_FORMATS:
    390         params[ 0] = GL_PALETTE4_RGB8_OES;
    391         params[ 1] = GL_PALETTE4_RGBA8_OES;
    392         params[ 2] = GL_PALETTE4_R5_G6_B5_OES;
    393         params[ 3] = GL_PALETTE4_RGBA4_OES;
    394         params[ 4] = GL_PALETTE4_RGB5_A1_OES;
    395         params[ 5] = GL_PALETTE8_RGB8_OES;
    396         params[ 6] = GL_PALETTE8_RGBA8_OES;
    397         params[ 7] = GL_PALETTE8_R5_G6_B5_OES;
    398         params[ 8] = GL_PALETTE8_RGBA4_OES;
    399         params[ 9] = GL_PALETTE8_RGB5_A1_OES;
    400         i = 10;
    401 #ifdef GL_OES_compressed_ETC1_RGB8_texture
    402         params[i++] = GL_ETC1_RGB8_OES;
    403 #endif
    404         break;
    405     case GL_DEPTH_BITS:
    406         params[0] = c->rasterizer.state.buffers.depth.format ? 0 : 16;
    407         break;
    408     case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
    409         params[0] = GL_RGB;
    410         break;
    411     case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
    412         params[0] = GL_UNSIGNED_SHORT_5_6_5;
    413         break;
    414     case GL_MAX_LIGHTS:
    415         params[0] = OGLES_MAX_LIGHTS;
    416         break;
    417     case GL_MAX_CLIP_PLANES:
    418         params[0] = OGLES_MAX_CLIP_PLANES;
    419         break;
    420     case GL_MAX_MODELVIEW_STACK_DEPTH:
    421         params[0] = OGLES_MODELVIEW_STACK_DEPTH;
    422         break;
    423     case GL_MAX_PROJECTION_STACK_DEPTH:
    424         params[0] = OGLES_PROJECTION_STACK_DEPTH;
    425         break;
    426     case GL_MAX_TEXTURE_STACK_DEPTH:
    427         params[0] = OGLES_TEXTURE_STACK_DEPTH;
    428         break;
    429     case GL_MAX_TEXTURE_SIZE:
    430         params[0] = GGL_MAX_TEXTURE_SIZE;
    431         break;
    432     case GL_MAX_TEXTURE_UNITS:
    433         params[0] = GGL_TEXTURE_UNIT_COUNT;
    434         break;
    435     case GL_MAX_VIEWPORT_DIMS:
    436         params[0] = GGL_MAX_VIEWPORT_DIMS;
    437         params[1] = GGL_MAX_VIEWPORT_DIMS;
    438         break;
    439     case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
    440         params[0] = OGLES_NUM_COMPRESSED_TEXTURE_FORMATS;
    441         break;
    442     case GL_SMOOTH_LINE_WIDTH_RANGE:
    443         params[0] = 0;
    444         params[1] = GGL_MAX_SMOOTH_LINE_WIDTH;
    445         break;
    446     case GL_SMOOTH_POINT_SIZE_RANGE:
    447         params[0] = 0;
    448         params[1] = GGL_MAX_SMOOTH_POINT_SIZE;
    449         break;
    450     case GL_STENCIL_BITS:
    451         params[0] = 0;
    452         break;
    453     case GL_SUBPIXEL_BITS:
    454         params[0] = GGL_SUBPIXEL_BITS;
    455         break;
    456 
    457     case GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES:
    458         memcpy( params,
    459                 c->transforms.modelview.top().elements(),
    460                 16*sizeof(GLint));
    461         break;
    462     case GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES:
    463         memcpy( params,
    464                 c->transforms.projection.top().elements(),
    465                 16*sizeof(GLint));
    466         break;
    467     case GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES:
    468         memcpy( params,
    469                 c->transforms.texture[c->textures.active].top().elements(),
    470                 16*sizeof(GLint));
    471         break;
    472 
    473     default:
    474         ogles_error(c, GL_INVALID_ENUM);
    475         break;
    476     }
    477 }
    478 
    479 // ----------------------------------------------------------------------------
    480 
    481 void glPointSize(GLfloat size)
    482 {
    483     ogles_context_t* c = ogles_context_t::get();
    484     if (size <= 0) {
    485         ogles_error(c, GL_INVALID_ENUM);
    486         return;
    487     }
    488     c->point.size = TRI_FROM_FIXED(gglFloatToFixed(size));
    489 }
    490 
    491 void glPointSizex(GLfixed size)
    492 {
    493     ogles_context_t* c = ogles_context_t::get();
    494     if (size <= 0) {
    495         ogles_error(c, GL_INVALID_ENUM);
    496         return;
    497     }
    498     c->point.size = TRI_FROM_FIXED(size);
    499 }
    500 
    501 // ----------------------------------------------------------------------------
    502 
    503 void glLineWidth(GLfloat width)
    504 {
    505     ogles_context_t* c = ogles_context_t::get();
    506     if (width <= 0) {
    507         ogles_error(c, GL_INVALID_ENUM);
    508         return;
    509     }
    510     c->line.width = TRI_FROM_FIXED(gglFloatToFixed(width));
    511 }
    512 
    513 void glLineWidthx(GLfixed width)
    514 {
    515     ogles_context_t* c = ogles_context_t::get();
    516     if (width <= 0) {
    517         ogles_error(c, GL_INVALID_ENUM);
    518         return;
    519     }
    520     c->line.width = TRI_FROM_FIXED(width);
    521 }
    522 
    523 // ----------------------------------------------------------------------------
    524 
    525 void glColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
    526     ogles_context_t* c = ogles_context_t::get();
    527     c->rasterizer.procs.colorMask(c, r, g, b, a);
    528 }
    529 
    530 void glDepthMask(GLboolean flag) {
    531     ogles_context_t* c = ogles_context_t::get();
    532     c->rasterizer.procs.depthMask(c, flag);
    533 }
    534 
    535 void glStencilMask(GLuint mask) {
    536     ogles_context_t* c = ogles_context_t::get();
    537     c->rasterizer.procs.stencilMask(c, mask);
    538 }
    539 
    540 void glDepthFunc(GLenum func) {
    541     ogles_context_t* c = ogles_context_t::get();
    542     c->rasterizer.procs.depthFunc(c, func);
    543 }
    544 
    545 void glLogicOp(GLenum opcode) {
    546     ogles_context_t* c = ogles_context_t::get();
    547     c->rasterizer.procs.logicOp(c, opcode);
    548 }
    549 
    550 void glAlphaFuncx(GLenum func, GLclampx ref) {
    551     ogles_context_t* c = ogles_context_t::get();
    552     c->rasterizer.procs.alphaFuncx(c, func, ref);
    553 }
    554 
    555 void glBlendFunc(GLenum sfactor, GLenum dfactor) {
    556     ogles_context_t* c = ogles_context_t::get();
    557     c->rasterizer.procs.blendFunc(c, sfactor, dfactor);
    558 }
    559 
    560 void glClear(GLbitfield mask) {
    561     ogles_context_t* c = ogles_context_t::get();
    562     c->rasterizer.procs.clear(c, mask);
    563 }
    564 
    565 void glClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) {
    566     ogles_context_t* c = ogles_context_t::get();
    567     c->rasterizer.procs.clearColorx(c, red, green, blue, alpha);
    568 }
    569 
    570 void glClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a)
    571 {
    572     ogles_context_t* c = ogles_context_t::get();
    573     c->rasterizer.procs.clearColorx(c,
    574                     gglFloatToFixed(r),
    575                     gglFloatToFixed(g),
    576                     gglFloatToFixed(b),
    577                     gglFloatToFixed(a));
    578 }
    579 
    580 void glClearDepthx(GLclampx depth) {
    581     ogles_context_t* c = ogles_context_t::get();
    582     c->rasterizer.procs.clearDepthx(c, depth);
    583 }
    584 
    585 void glClearDepthf(GLclampf depth)
    586 {
    587     ogles_context_t* c = ogles_context_t::get();
    588     c->rasterizer.procs.clearDepthx(c, gglFloatToFixed(depth));
    589 }
    590 
    591 void glClearStencil(GLint s) {
    592     ogles_context_t* c = ogles_context_t::get();
    593     c->rasterizer.procs.clearStencil(c, s);
    594 }
    595