Home | History | Annotate | Download | only in libpixelflinger
      1 /* libs/pixelflinger/pixelflinger.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 
     19 #include <stdlib.h>
     20 #include <string.h>
     21 #include <assert.h>
     22 
     23 #include <sys/time.h>
     24 
     25 #include <pixelflinger/pixelflinger.h>
     26 #include <private/pixelflinger/ggl_context.h>
     27 
     28 #include "buffer.h"
     29 #include "clear.h"
     30 #include "picker.h"
     31 #include "raster.h"
     32 #include "scanline.h"
     33 #include "trap.h"
     34 
     35 #include "codeflinger/GGLAssembler.h"
     36 #include "codeflinger/CodeCache.h"
     37 
     38 #include <stdio.h>
     39 
     40 
     41 namespace android {
     42 
     43 // ----------------------------------------------------------------------------
     44 
     45 // 8x8 Bayer dither matrix
     46 static const uint8_t gDitherMatrix[GGL_DITHER_SIZE] = {
     47      0, 32,  8, 40,  2, 34, 10, 42,
     48     48, 16, 56, 24, 50, 18, 58, 26,
     49     12, 44,  4, 36, 14, 46,  6, 38,
     50     60, 28, 52, 20, 62, 30, 54, 22,
     51      3, 35, 11, 43,  1, 33,  9, 41,
     52     51, 19, 59, 27, 49, 17, 57, 25,
     53     15, 47,  7, 39, 13, 45,  5, 37,
     54     63, 31, 55, 23, 61, 29, 53, 21
     55 };
     56 
     57 static void ggl_init_procs(context_t* c);
     58 static void ggl_set_scissor(context_t* c);
     59 
     60 static void ggl_enable_blending(context_t* c, int enable);
     61 static void ggl_enable_scissor_test(context_t* c, int enable);
     62 static void ggl_enable_alpha_test(context_t* c, int enable);
     63 static void ggl_enable_logic_op(context_t* c, int enable);
     64 static void ggl_enable_dither(context_t* c, int enable);
     65 static void ggl_enable_stencil_test(context_t* c, int enable);
     66 static void ggl_enable_depth_test(context_t* c, int enable);
     67 static void ggl_enable_aa(context_t* c, int enable);
     68 static void ggl_enable_point_aa_nice(context_t* c, int enable);
     69 static void ggl_enable_texture2d(context_t* c, int enable);
     70 static void ggl_enable_w_lerp(context_t* c, int enable);
     71 static void ggl_enable_fog(context_t* c, int enable);
     72 
     73 static inline int min(int a, int b) CONST;
     74 static inline int min(int a, int b) {
     75     return a < b ? a : b;
     76 }
     77 
     78 static inline int max(int a, int b) CONST;
     79 static inline int max(int a, int b) {
     80     return a < b ? b : a;
     81 }
     82 
     83 // ----------------------------------------------------------------------------
     84 
     85 void ggl_error(context_t* c, GGLenum error)
     86 {
     87     if (c->error == GGL_NO_ERROR)
     88         c->error = error;
     89 }
     90 
     91 // ----------------------------------------------------------------------------
     92 
     93 static void ggl_bindTexture(void* con, const GGLSurface* surface)
     94 {
     95     GGL_CONTEXT(c, con);
     96     if (surface->format != c->activeTMU->surface.format)
     97         ggl_state_changed(c, GGL_TMU_STATE);
     98     ggl_set_surface(c, &(c->activeTMU->surface), surface);
     99 }
    100 
    101 
    102 static void ggl_bindTextureLod(void* con, GGLuint tmu,const GGLSurface* surface)
    103 {
    104     GGL_CONTEXT(c, con);
    105     // All LODs must have the same format
    106     ggl_set_surface(c, &c->state.texture[tmu].surface, surface);
    107 }
    108 
    109 static void ggl_colorBuffer(void* con, const GGLSurface* surface)
    110 {
    111     GGL_CONTEXT(c, con);
    112     if (surface->format != c->state.buffers.color.format)
    113         ggl_state_changed(c, GGL_CB_STATE);
    114 
    115     if (surface->width > c->state.buffers.coverageBufferSize) {
    116         // allocate the coverage factor buffer
    117         free(c->state.buffers.coverage);
    118         c->state.buffers.coverage = (int16_t*)malloc(surface->width * 2);
    119         c->state.buffers.coverageBufferSize =
    120                 c->state.buffers.coverage ? surface->width : 0;
    121     }
    122     ggl_set_surface(c, &(c->state.buffers.color), surface);
    123     if (c->state.buffers.read.format == 0) {
    124         ggl_set_surface(c, &(c->state.buffers.read), surface);
    125     }
    126     ggl_set_scissor(c);
    127 }
    128 
    129 static void ggl_readBuffer(void* con, const GGLSurface* surface)
    130 {
    131     GGL_CONTEXT(c, con);
    132     ggl_set_surface(c, &(c->state.buffers.read), surface);
    133 }
    134 
    135 static void ggl_depthBuffer(void* con, const GGLSurface* surface)
    136 {
    137     GGL_CONTEXT(c, con);
    138     if (surface->format == GGL_PIXEL_FORMAT_Z_16) {
    139         ggl_set_surface(c, &(c->state.buffers.depth), surface);
    140     } else {
    141         c->state.buffers.depth.format = GGL_PIXEL_FORMAT_NONE;
    142         ggl_enable_depth_test(c, 0);
    143     }
    144 }
    145 
    146 static void ggl_scissor(void* con, GGLint x, GGLint y,
    147         GGLsizei width, GGLsizei height)
    148 {
    149     GGL_CONTEXT(c, con);
    150     c->state.scissor.user_left = x;
    151     c->state.scissor.user_top = y;
    152     c->state.scissor.user_right = x + width;
    153     c->state.scissor.user_bottom = y + height;
    154     ggl_set_scissor(c);
    155 }
    156 
    157 // ----------------------------------------------------------------------------
    158 
    159 static void enable_disable(context_t* c, GGLenum name, int en)
    160 {
    161     switch (name) {
    162     case GGL_BLEND:             ggl_enable_blending(c, en);      break;
    163     case GGL_SCISSOR_TEST:      ggl_enable_scissor_test(c, en);  break;
    164     case GGL_ALPHA_TEST:        ggl_enable_alpha_test(c, en);    break;
    165     case GGL_COLOR_LOGIC_OP:    ggl_enable_logic_op(c, en);      break;
    166     case GGL_DITHER:            ggl_enable_dither(c, en);        break;
    167     case GGL_STENCIL_TEST:      ggl_enable_stencil_test(c, en);  break;
    168     case GGL_DEPTH_TEST:        ggl_enable_depth_test(c, en);    break;
    169     case GGL_AA:                ggl_enable_aa(c, en);            break;
    170     case GGL_TEXTURE_2D:        ggl_enable_texture2d(c, en);     break;
    171     case GGL_W_LERP:            ggl_enable_w_lerp(c, en);        break;
    172     case GGL_FOG:               ggl_enable_fog(c, en);           break;
    173     case GGL_POINT_SMOOTH_NICE: ggl_enable_point_aa_nice(c, en); break;
    174     }
    175 }
    176 
    177 static void ggl_enable(void* con, GGLenum name)
    178 {
    179     GGL_CONTEXT(c, con);
    180     enable_disable(c, name, 1);
    181 }
    182 
    183 static void ggl_disable(void* con, GGLenum name)
    184 {
    185     GGL_CONTEXT(c, con);
    186     enable_disable(c, name, 0);
    187 }
    188 
    189 static void ggl_enableDisable(void* con, GGLenum name, GGLboolean en)
    190 {
    191     GGL_CONTEXT(c, con);
    192     enable_disable(c, name, en ? 1 : 0);
    193 }
    194 
    195 // ----------------------------------------------------------------------------
    196 
    197 static void ggl_shadeModel(void* con, GGLenum mode)
    198 {
    199     GGL_CONTEXT(c, con);
    200     switch (mode) {
    201     case GGL_FLAT:
    202         if (c->state.enables & GGL_ENABLE_SMOOTH) {
    203             c->state.enables &= ~GGL_ENABLE_SMOOTH;
    204             ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    205         }
    206         break;
    207     case GGL_SMOOTH:
    208         if (!(c->state.enables & GGL_ENABLE_SMOOTH)) {
    209             c->state.enables |= GGL_ENABLE_SMOOTH;
    210             ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    211         }
    212         break;
    213     default:
    214         ggl_error(c, GGL_INVALID_ENUM);
    215     }
    216 }
    217 
    218 static void ggl_color4xv(void* con, const GGLclampx* color)
    219 {
    220     GGL_CONTEXT(c, con);
    221 	c->shade.r0 = gglFixedToIteratedColor(color[0]);
    222 	c->shade.g0 = gglFixedToIteratedColor(color[1]);
    223 	c->shade.b0 = gglFixedToIteratedColor(color[2]);
    224 	c->shade.a0 = gglFixedToIteratedColor(color[3]);
    225 }
    226 
    227 static void ggl_colorGrad12xv(void* con, const GGLcolor* grad)
    228 {
    229     GGL_CONTEXT(c, con);
    230     // it is very important to round the iterated value here because
    231     // the rasterizer doesn't clamp them, therefore the iterated value
    232     //must absolutely be correct.
    233     // GGLColor is encoded as 8.16 value
    234     const int32_t round = 0x8000;
    235 	c->shade.r0   = grad[ 0] + round;
    236 	c->shade.drdx = grad[ 1];
    237 	c->shade.drdy = grad[ 2];
    238 	c->shade.g0   = grad[ 3] + round;
    239 	c->shade.dgdx = grad[ 4];
    240 	c->shade.dgdy = grad[ 5];
    241 	c->shade.b0   = grad[ 6] + round;
    242 	c->shade.dbdx = grad[ 7];
    243 	c->shade.dbdy = grad[ 8];
    244 	c->shade.a0   = grad[ 9] + round;
    245 	c->shade.dadx = grad[10];
    246 	c->shade.dady = grad[11];
    247 }
    248 
    249 static void ggl_zGrad3xv(void* con, const GGLfixed32* grad)
    250 {
    251     GGL_CONTEXT(c, con);
    252     // z iterators are encoded as 0.32 fixed point and the z-buffer
    253     // holds 16 bits, the rounding value is 0x8000.
    254     const uint32_t round = 0x8000;
    255 	c->shade.z0   = grad[0] + round;
    256 	c->shade.dzdx = grad[1];
    257 	c->shade.dzdy = grad[2];
    258 }
    259 
    260 static void ggl_wGrad3xv(void* con, const GGLfixed* grad)
    261 {
    262     GGL_CONTEXT(c, con);
    263 	c->shade.w0   = grad[0];
    264 	c->shade.dwdx = grad[1];
    265 	c->shade.dwdy = grad[2];
    266 }
    267 
    268 // ----------------------------------------------------------------------------
    269 
    270 static void ggl_fogGrad3xv(void* con, const GGLfixed* grad)
    271 {
    272     GGL_CONTEXT(c, con);
    273 	c->shade.f0     = grad[0];
    274 	c->shade.dfdx   = grad[1];
    275 	c->shade.dfdy   = grad[2];
    276 }
    277 
    278 static void ggl_fogColor3xv(void* con, const GGLclampx* color)
    279 {
    280     GGL_CONTEXT(c, con);
    281     const int32_t r = gglClampx(color[0]);
    282     const int32_t g = gglClampx(color[1]);
    283     const int32_t b = gglClampx(color[2]);
    284     c->state.fog.color[GGLFormat::ALPHA]= 0xFF; // unused
    285 	c->state.fog.color[GGLFormat::RED]  = (r - (r>>8))>>8;
    286 	c->state.fog.color[GGLFormat::GREEN]= (g - (g>>8))>>8;
    287 	c->state.fog.color[GGLFormat::BLUE] = (b - (b>>8))>>8;
    288 }
    289 
    290 static void ggl_enable_fog(context_t* c, int enable)
    291 {
    292     const int e = (c->state.enables & GGL_ENABLE_FOG)?1:0;
    293     if (e != enable) {
    294         if (enable) c->state.enables |= GGL_ENABLE_FOG;
    295         else        c->state.enables &= ~GGL_ENABLE_FOG;
    296         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    297     }
    298 }
    299 
    300 // ----------------------------------------------------------------------------
    301 
    302 static void ggl_blendFunc(void* con, GGLenum src, GGLenum dst)
    303 {
    304     GGL_CONTEXT(c, con);
    305     c->state.blend.src = src;
    306     c->state.blend.src_alpha = src;
    307     c->state.blend.dst = dst;
    308     c->state.blend.dst_alpha = dst;
    309     c->state.blend.alpha_separate = 0;
    310     if (c->state.enables & GGL_ENABLE_BLENDING) {
    311         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    312     }
    313 }
    314 
    315 static void ggl_blendFuncSeparate(void* con,
    316         GGLenum src, GGLenum dst,
    317         GGLenum srcAlpha, GGLenum dstAplha)
    318 {
    319     GGL_CONTEXT(c, con);
    320     c->state.blend.src = src;
    321     c->state.blend.src_alpha = srcAlpha;
    322     c->state.blend.dst = dst;
    323     c->state.blend.dst_alpha = dstAplha;
    324     c->state.blend.alpha_separate = 1;
    325     if (c->state.enables & GGL_ENABLE_BLENDING) {
    326         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    327     }
    328 }
    329 
    330 // ----------------------------------------------------------------------------
    331 
    332 static void ggl_texEnvi(void* con,	GGLenum target,
    333 							GGLenum pname,
    334 							GGLint param)
    335 {
    336     GGL_CONTEXT(c, con);
    337     if (target != GGL_TEXTURE_ENV || pname != GGL_TEXTURE_ENV_MODE) {
    338         ggl_error(c, GGL_INVALID_ENUM);
    339         return;
    340     }
    341     switch (param) {
    342     case GGL_REPLACE:
    343     case GGL_MODULATE:
    344     case GGL_DECAL:
    345     case GGL_BLEND:
    346     case GGL_ADD:
    347         if (c->activeTMU->env != param) {
    348             c->activeTMU->env = param;
    349             ggl_state_changed(c, GGL_TMU_STATE);
    350         }
    351         break;
    352     default:
    353         ggl_error(c, GGL_INVALID_ENUM);
    354     }
    355 }
    356 
    357 static void ggl_texEnvxv(void* con, GGLenum target,
    358         GGLenum pname, const GGLfixed* params)
    359 {
    360     GGL_CONTEXT(c, con);
    361     if (target != GGL_TEXTURE_ENV) {
    362         ggl_error(c, GGL_INVALID_ENUM);
    363         return;
    364     }
    365     switch (pname) {
    366     case GGL_TEXTURE_ENV_MODE:
    367         ggl_texEnvi(con, target, pname, params[0]);
    368         break;
    369     case GGL_TEXTURE_ENV_COLOR: {
    370         uint8_t* const color = c->activeTMU->env_color;
    371         const GGLclampx r = gglClampx(params[0]);
    372         const GGLclampx g = gglClampx(params[1]);
    373         const GGLclampx b = gglClampx(params[2]);
    374         const GGLclampx a = gglClampx(params[3]);
    375         color[0] = (a-(a>>8))>>8;
    376         color[1] = (r-(r>>8))>>8;
    377         color[2] = (g-(g>>8))>>8;
    378         color[3] = (b-(b>>8))>>8;
    379         break;
    380     }
    381     default:
    382         ggl_error(c, GGL_INVALID_ENUM);
    383         return;
    384     }
    385 }
    386 
    387 
    388 static void ggl_texParameteri(void* con,
    389         GGLenum target,
    390         GGLenum pname,
    391         GGLint param)
    392 {
    393     GGL_CONTEXT(c, con);
    394     if (target != GGL_TEXTURE_2D) {
    395         ggl_error(c, GGL_INVALID_ENUM);
    396         return;
    397     }
    398 
    399     if (param == GGL_CLAMP_TO_EDGE)
    400         param = GGL_CLAMP;
    401 
    402     uint16_t* what = 0;
    403     switch (pname) {
    404     case GGL_TEXTURE_WRAP_S:
    405         if ((param == GGL_CLAMP) ||
    406             (param == GGL_REPEAT)) {
    407             what = &c->activeTMU->s_wrap;
    408         }
    409         break;
    410     case GGL_TEXTURE_WRAP_T:
    411         if ((param == GGL_CLAMP) ||
    412             (param == GGL_REPEAT)) {
    413             what = &c->activeTMU->t_wrap;
    414         }
    415         break;
    416     case GGL_TEXTURE_MIN_FILTER:
    417         if ((param == GGL_NEAREST) ||
    418             (param == GGL_NEAREST_MIPMAP_NEAREST) ||
    419             (param == GGL_NEAREST_MIPMAP_LINEAR)) {
    420             what = &c->activeTMU->min_filter;
    421             param = GGL_NEAREST;
    422         }
    423         if ((param == GGL_LINEAR) ||
    424             (param == GGL_LINEAR_MIPMAP_NEAREST) ||
    425             (param == GGL_LINEAR_MIPMAP_LINEAR)) {
    426             what = &c->activeTMU->min_filter;
    427             param = GGL_LINEAR;
    428         }
    429         break;
    430     case GGL_TEXTURE_MAG_FILTER:
    431         if ((param == GGL_NEAREST) ||
    432             (param == GGL_LINEAR)) {
    433             what = &c->activeTMU->mag_filter;
    434         }
    435         break;
    436     }
    437 
    438     if (!what) {
    439         ggl_error(c, GGL_INVALID_ENUM);
    440         return;
    441     }
    442 
    443     if (*what != param) {
    444         *what = param;
    445         ggl_state_changed(c, GGL_TMU_STATE);
    446     }
    447 }
    448 
    449 static void ggl_texCoordGradScale8xv(void* con, GGLint tmu, const int32_t* grad)
    450 {
    451     GGL_CONTEXT(c, con);
    452     texture_t& u = c->state.texture[tmu];
    453 	u.shade.is0   = grad[0];
    454 	u.shade.idsdx = grad[1];
    455 	u.shade.idsdy = grad[2];
    456 	u.shade.it0   = grad[3];
    457 	u.shade.idtdx = grad[4];
    458 	u.shade.idtdy = grad[5];
    459     u.shade.sscale= grad[6];
    460     u.shade.tscale= grad[7];
    461 }
    462 
    463 static void ggl_texCoord2x(void* con, GGLfixed s, GGLfixed t)
    464 {
    465     GGL_CONTEXT(c, con);
    466 	c->activeTMU->shade.is0 = s;
    467 	c->activeTMU->shade.it0 = t;
    468     c->activeTMU->shade.sscale= 0;
    469     c->activeTMU->shade.tscale= 0;
    470 }
    471 
    472 static void ggl_texCoord2i(void* con, GGLint s, GGLint t)
    473 {
    474     ggl_texCoord2x(con, s<<16, t<<16);
    475 }
    476 
    477 static void ggl_texGeni(void* con, GGLenum coord, GGLenum pname, GGLint param)
    478 {
    479     GGL_CONTEXT(c, con);
    480     if (pname != GGL_TEXTURE_GEN_MODE) {
    481         ggl_error(c, GGL_INVALID_ENUM);
    482         return;
    483     }
    484 
    485     uint32_t* coord_ptr = 0;
    486     if (coord == GGL_S)         coord_ptr = &(c->activeTMU->s_coord);
    487     else if (coord == GGL_T)    coord_ptr = &(c->activeTMU->t_coord);
    488 
    489     if (coord_ptr) {
    490         if (*coord_ptr != uint32_t(param)) {
    491             *coord_ptr = uint32_t(param);
    492             ggl_state_changed(c, GGL_TMU_STATE);
    493         }
    494     } else {
    495         ggl_error(c, GGL_INVALID_ENUM);
    496     }
    497 }
    498 
    499 static void ggl_activeTexture(void* con, GGLuint tmu)
    500 {
    501     GGL_CONTEXT(c, con);
    502     if (tmu >= GGLuint(GGL_TEXTURE_UNIT_COUNT)) {
    503         ggl_error(c, GGL_INVALID_ENUM);
    504         return;
    505     }
    506     c->activeTMUIndex = tmu;
    507     c->activeTMU = &(c->state.texture[tmu]);
    508 }
    509 
    510 // ----------------------------------------------------------------------------
    511 
    512 static void ggl_colorMask(void* con, GGLboolean r,
    513                                      GGLboolean g,
    514                                      GGLboolean b,
    515                                      GGLboolean a)
    516 {
    517     GGL_CONTEXT(c, con);
    518     int mask = 0;
    519     if (a)  mask |= 1 << GGLFormat::ALPHA;
    520     if (r)  mask |= 1 << GGLFormat::RED;
    521     if (g)  mask |= 1 << GGLFormat::GREEN;
    522     if (b)  mask |= 1 << GGLFormat::BLUE;
    523     if (c->state.mask.color != mask) {
    524         c->state.mask.color = mask;
    525         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    526     }
    527 }
    528 
    529 static void ggl_depthMask(void* con, GGLboolean flag)
    530 {
    531     GGL_CONTEXT(c, con);
    532     if (c->state.mask.depth != flag?1:0) {
    533         c->state.mask.depth = flag?1:0;
    534         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    535     }
    536 }
    537 
    538 static void ggl_stencilMask(void* con, GGLuint mask)
    539 {
    540     GGL_CONTEXT(c, con);
    541     if (c->state.mask.stencil != mask) {
    542         c->state.mask.stencil = mask;
    543         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    544     }
    545 }
    546 
    547 // ----------------------------------------------------------------------------
    548 
    549 static void ggl_alphaFuncx(void* con, GGLenum func, GGLclampx ref)
    550 {
    551     GGL_CONTEXT(c, con);
    552     if ((func < GGL_NEVER) || (func > GGL_ALWAYS)) {
    553         ggl_error(c, GGL_INVALID_ENUM);
    554         return;
    555     }
    556     c->state.alpha_test.ref = gglFixedToIteratedColor(gglClampx(ref));
    557     if (c->state.alpha_test.func != func) {
    558         c->state.alpha_test.func = func;
    559         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    560     }
    561 }
    562 
    563 // ----------------------------------------------------------------------------
    564 
    565 static void ggl_depthFunc(void* con, GGLenum func)
    566 {
    567     GGL_CONTEXT(c, con);
    568     if ((func < GGL_NEVER) || (func > GGL_ALWAYS)) {
    569         ggl_error(c, GGL_INVALID_ENUM);
    570         return;
    571     }
    572     if (c->state.depth_test.func != func) {
    573         c->state.depth_test.func = func;
    574         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    575     }
    576 }
    577 
    578 // ----------------------------------------------------------------------------
    579 
    580 static void ggl_logicOp(void* con, GGLenum opcode)
    581 {
    582     GGL_CONTEXT(c, con);
    583     if ((opcode < GGL_CLEAR) || (opcode > GGL_SET)) {
    584         ggl_error(c, GGL_INVALID_ENUM);
    585         return;
    586     }
    587     if (c->state.logic_op.opcode != opcode) {
    588         c->state.logic_op.opcode = opcode;
    589         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    590     }
    591 }
    592 
    593 
    594 // ----------------------------------------------------------------------------
    595 
    596 void ggl_set_scissor(context_t* c)
    597 {
    598     if (c->state.enables & GGL_ENABLE_SCISSOR_TEST) {
    599         const int32_t l = c->state.scissor.user_left;
    600         const int32_t t = c->state.scissor.user_top;
    601         const int32_t r = c->state.scissor.user_right;
    602         const int32_t b = c->state.scissor.user_bottom;
    603         c->state.scissor.left   = max(0, l);
    604         c->state.scissor.right  = min(c->state.buffers.color.width, r);
    605         c->state.scissor.top    = max(0, t);
    606         c->state.scissor.bottom = min(c->state.buffers.color.height, b);
    607     } else {
    608         c->state.scissor.left   = 0;
    609         c->state.scissor.top    = 0;
    610         c->state.scissor.right  = c->state.buffers.color.width;
    611         c->state.scissor.bottom = c->state.buffers.color.height;
    612     }
    613 }
    614 
    615 void ggl_enable_blending(context_t* c, int enable)
    616 {
    617     const int e = (c->state.enables & GGL_ENABLE_BLENDING)?1:0;
    618     if (e != enable) {
    619         if (enable) c->state.enables |= GGL_ENABLE_BLENDING;
    620         else        c->state.enables &= ~GGL_ENABLE_BLENDING;
    621         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    622     }
    623 }
    624 
    625 void ggl_enable_scissor_test(context_t* c, int enable)
    626 {
    627     const int e = (c->state.enables & GGL_ENABLE_SCISSOR_TEST)?1:0;
    628     if (e != enable) {
    629         if (enable) c->state.enables |= GGL_ENABLE_SCISSOR_TEST;
    630         else        c->state.enables &= ~GGL_ENABLE_SCISSOR_TEST;
    631         ggl_set_scissor(c);
    632     }
    633 }
    634 
    635 void ggl_enable_alpha_test(context_t* c, int enable)
    636 {
    637     const int e = (c->state.enables & GGL_ENABLE_ALPHA_TEST)?1:0;
    638     if (e != enable) {
    639         if (enable) c->state.enables |= GGL_ENABLE_ALPHA_TEST;
    640         else        c->state.enables &= ~GGL_ENABLE_ALPHA_TEST;
    641         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    642     }
    643 }
    644 
    645 void ggl_enable_logic_op(context_t* c, int enable)
    646 {
    647     const int e = (c->state.enables & GGL_ENABLE_LOGIC_OP)?1:0;
    648     if (e != enable) {
    649         if (enable) c->state.enables |= GGL_ENABLE_LOGIC_OP;
    650         else        c->state.enables &= ~GGL_ENABLE_LOGIC_OP;
    651         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    652     }
    653 }
    654 
    655 void ggl_enable_dither(context_t* c, int enable)
    656 {
    657     const int e = (c->state.enables & GGL_ENABLE_DITHER)?1:0;
    658     if (e != enable) {
    659         if (enable) c->state.enables |= GGL_ENABLE_DITHER;
    660         else        c->state.enables &= ~GGL_ENABLE_DITHER;
    661         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    662     }
    663 }
    664 
    665 void ggl_enable_stencil_test(context_t* /*c*/, int /*enable*/)
    666 {
    667 }
    668 
    669 void ggl_enable_depth_test(context_t* c, int enable)
    670 {
    671     if (c->state.buffers.depth.format == 0)
    672         enable = 0;
    673     const int e = (c->state.enables & GGL_ENABLE_DEPTH_TEST)?1:0;
    674     if (e != enable) {
    675         if (enable) c->state.enables |= GGL_ENABLE_DEPTH_TEST;
    676         else        c->state.enables &= ~GGL_ENABLE_DEPTH_TEST;
    677         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    678     }
    679 }
    680 
    681 void ggl_enable_aa(context_t* c, int enable)
    682 {
    683     const int e = (c->state.enables & GGL_ENABLE_AA)?1:0;
    684     if (e != enable) {
    685         if (enable) c->state.enables |= GGL_ENABLE_AA;
    686         else        c->state.enables &= ~GGL_ENABLE_AA;
    687         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    688     }
    689 }
    690 
    691 void ggl_enable_point_aa_nice(context_t* c, int enable)
    692 {
    693     const int e = (c->state.enables & GGL_ENABLE_POINT_AA_NICE)?1:0;
    694     if (e != enable) {
    695         if (enable) c->state.enables |= GGL_ENABLE_POINT_AA_NICE;
    696         else        c->state.enables &= ~GGL_ENABLE_POINT_AA_NICE;
    697         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    698     }
    699 }
    700 
    701 void ggl_enable_w_lerp(context_t* c, int enable)
    702 {
    703     const int e = (c->state.enables & GGL_ENABLE_W)?1:0;
    704     if (e != enable) {
    705         if (enable) c->state.enables |= GGL_ENABLE_W;
    706         else        c->state.enables &= ~GGL_ENABLE_W;
    707         ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
    708     }
    709 }
    710 
    711 void ggl_enable_texture2d(context_t* c, int enable)
    712 {
    713     if (c->activeTMU->enable != enable) {
    714         const uint32_t tmu = c->activeTMUIndex;
    715         c->activeTMU->enable = enable;
    716         const uint32_t mask = 1UL << tmu;
    717         if (enable)                 c->state.enabled_tmu |= mask;
    718         else                        c->state.enabled_tmu &= ~mask;
    719         if (c->state.enabled_tmu)   c->state.enables |= GGL_ENABLE_TMUS;
    720         else                        c->state.enables &= ~GGL_ENABLE_TMUS;
    721         ggl_state_changed(c, GGL_TMU_STATE);
    722     }
    723 }
    724 
    725 
    726 // ----------------------------------------------------------------------------
    727 
    728 int64_t ggl_system_time()
    729 {
    730     struct timespec t;
    731     t.tv_sec = t.tv_nsec = 0;
    732     clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t);
    733     return int64_t(t.tv_sec)*1000000000LL + t.tv_nsec;
    734 }
    735 
    736 // ----------------------------------------------------------------------------
    737 
    738 void ggl_init_procs(context_t* c)
    739 {
    740     GGLContext& procs = *(GGLContext*)c;
    741     GGL_INIT_PROC(procs, scissor);
    742     GGL_INIT_PROC(procs, activeTexture);
    743     GGL_INIT_PROC(procs, bindTexture);
    744     GGL_INIT_PROC(procs, bindTextureLod);
    745     GGL_INIT_PROC(procs, colorBuffer);
    746     GGL_INIT_PROC(procs, readBuffer);
    747     GGL_INIT_PROC(procs, depthBuffer);
    748     GGL_INIT_PROC(procs, enable);
    749     GGL_INIT_PROC(procs, disable);
    750     GGL_INIT_PROC(procs, enableDisable);
    751     GGL_INIT_PROC(procs, shadeModel);
    752     GGL_INIT_PROC(procs, color4xv);
    753     GGL_INIT_PROC(procs, colorGrad12xv);
    754     GGL_INIT_PROC(procs, zGrad3xv);
    755     GGL_INIT_PROC(procs, wGrad3xv);
    756     GGL_INIT_PROC(procs, fogGrad3xv);
    757     GGL_INIT_PROC(procs, fogColor3xv);
    758     GGL_INIT_PROC(procs, blendFunc);
    759     GGL_INIT_PROC(procs, blendFuncSeparate);
    760     GGL_INIT_PROC(procs, texEnvi);
    761     GGL_INIT_PROC(procs, texEnvxv);
    762     GGL_INIT_PROC(procs, texParameteri);
    763     GGL_INIT_PROC(procs, texCoord2i);
    764     GGL_INIT_PROC(procs, texCoord2x);
    765     GGL_INIT_PROC(procs, texCoordGradScale8xv);
    766     GGL_INIT_PROC(procs, texGeni);
    767     GGL_INIT_PROC(procs, colorMask);
    768     GGL_INIT_PROC(procs, depthMask);
    769     GGL_INIT_PROC(procs, stencilMask);
    770     GGL_INIT_PROC(procs, alphaFuncx);
    771     GGL_INIT_PROC(procs, depthFunc);
    772     GGL_INIT_PROC(procs, logicOp);
    773     ggl_init_clear(c);
    774 }
    775 
    776 void ggl_init_context(context_t* c)
    777 {
    778     memset(c, 0, sizeof(context_t));
    779     ggl_init_procs(c);
    780     ggl_init_trap(c);
    781     ggl_init_scanline(c);
    782     ggl_init_texture(c);
    783     ggl_init_picker(c);
    784     ggl_init_raster(c);
    785     c->formats = gglGetPixelFormatTable();
    786     c->state.blend.src = GGL_ONE;
    787     c->state.blend.dst = GGL_ZERO;
    788     c->state.blend.src_alpha = GGL_ONE;
    789     c->state.blend.dst_alpha = GGL_ZERO;
    790     c->state.mask.color = 0xF;
    791     c->state.mask.depth = 0;
    792     c->state.mask.stencil = 0xFFFFFFFF;
    793     c->state.logic_op.opcode = GGL_COPY;
    794     c->state.alpha_test.func = GGL_ALWAYS;
    795     c->state.depth_test.func = GGL_LESS;
    796     c->state.depth_test.clearValue = FIXED_ONE;
    797     c->shade.w0 = FIXED_ONE;
    798     memcpy(c->ditherMatrix, gDitherMatrix, sizeof(gDitherMatrix));
    799 }
    800 
    801 void ggl_uninit_context(context_t* c)
    802 {
    803     ggl_uninit_scanline(c);
    804 }
    805 
    806 // ----------------------------------------------------------------------------
    807 }; // namespace android
    808 // ----------------------------------------------------------------------------
    809 
    810 
    811 
    812 using namespace android;
    813 
    814 ssize_t gglInit(GGLContext** context)
    815 {
    816     void* const base = malloc(sizeof(context_t) + 32);
    817 	if (base) {
    818         // always align the context on cache lines
    819         context_t *c = (context_t *)((ptrdiff_t(base)+31) & ~0x1FL);
    820         ggl_init_context(c);
    821         c->base = base;
    822 		*context = (GGLContext*)c;
    823 	} else {
    824 		return -1;
    825 	}
    826 	return 0;
    827 }
    828 
    829 ssize_t gglUninit(GGLContext* con)
    830 {
    831     GGL_CONTEXT(c, (void*)con);
    832     ggl_uninit_context(c);
    833 	free(c->base);
    834 	return 0;
    835 }
    836 
    837