Home | History | Annotate | Download | only in pixelflinger2
      1 /**
      2  **
      3  ** Copyright 2010, 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 #include <math.h>
     20 #include <string.h>
     21 #include <stdio.h>
     22 
     23 #include "pixelflinger2.h"
     24 #include "src/mesa/main/mtypes.h"
     25 #include "src/mesa/program/prog_parameter.h"
     26 #include "src/mesa/program/prog_uniform.h"
     27 #include "src/glsl/glsl_types.h"
     28 
     29 //#undef ALOGD
     30 //#define ALOGD(...)
     31 
     32 static inline void LerpVector4(const Vector4 * a, const Vector4 * b,
     33                                const VectorComp_t x, Vector4 * d) __attribute__((always_inline));
     34 static inline void LerpVector4(const Vector4 * a, const Vector4 * b,
     35                                const VectorComp_t x, Vector4 * d)
     36 {
     37    assert(a != d && b != d);
     38    //d = (b - a) * x + a;
     39    (*d) = (*b);
     40    (*d) -= (*a);
     41    (*d) *= x;
     42    (*d) += (*a);
     43 }
     44 
     45 static inline void InterpolateVertex(const VertexOutput * a, const VertexOutput * b, const VectorComp_t x,
     46                                      VertexOutput * v, const unsigned varyingCount)
     47 {
     48    LerpVector4(&a->position, &b->position, x, &v->position);
     49    for (unsigned i = 0; i < varyingCount; i++)
     50       LerpVector4(a->varyings + i, b->varyings + i, x, v->varyings + i);
     51    LerpVector4(&a->frontFacingPointCoord, &b->frontFacingPointCoord,
     52                x, &v->frontFacingPointCoord); // gl_PointCoord
     53    v->frontFacingPointCoord.y = a->frontFacingPointCoord.y; // gl_FrontFacing not interpolated
     54 
     55 }
     56 
     57 void GGLProcessVertex(const gl_shader_program * program, const VertexInput * input,
     58                       VertexOutput * output, const float (*constants)[4])
     59 {
     60    ShaderFunction_t function = (ShaderFunction_t)program->_LinkedShaders[MESA_SHADER_VERTEX]->function;
     61    function(input, output, constants);
     62 }
     63 
     64 static void ProcessVertex(const GGLInterface * iface, const VertexInput * input,
     65                           VertexOutput * output)
     66 {
     67    GGL_GET_CONST_CONTEXT(ctx, iface);
     68 
     69 //#if !USE_LLVM_TEXTURE_SAMPLER
     70 //    extern const GGLContext * textureGGLContext;
     71 //    textureGGLContext = ctx;
     72 //#endif
     73 //
     74 
     75 //   memcpy(ctx->glCtx->CurrentProgram->ValuesVertexInput, input, sizeof(*input));
     76 //   ctx->glCtx->CurrentProgram->_LinkedShaders[MESA_SHADER_VERTEX]->function();
     77 //   memcpy(output, ctx->glCtx->CurrentProgram->ValuesVertexOutput, sizeof(*output));
     78 
     79    GGLProcessVertex(ctx->CurrentProgram, input, output, ctx->CurrentProgram->ValuesUniform);
     80 //   const Vector4 * constants = (Vector4 *)
     81 //    ctx->glCtx->Shader.CurrentProgram->VertexProgram->Parameters->ParameterValues;
     82 //	ctx->glCtx->Shader.CurrentProgram->GLVMVP->function(input, output, constants);
     83 //
     84 //#if !USE_LLVM_TEXTURE_SAMPLER
     85 //    textureGGLContext = NULL;
     86 //#endif
     87 }
     88 
     89 #if USE_DUAL_THREAD
     90 static void * RasterTrapezoidWorker(void * threadArgs)
     91 {
     92    GGLContext::Worker * args = (GGLContext::Worker *)threadArgs;
     93    VertexOutput clip0, clip1, * left, * right;
     94 
     95    pthread_mutex_lock(&args->finishLock);
     96    pthread_mutex_lock(&args->assignLock);
     97    pthread_cond_signal(&args->finishCond);
     98    pthread_mutex_unlock(&args->finishLock);
     99 
    100    while (true) {
    101       pthread_cond_wait(&args->assignCond, &args->assignLock);
    102       if (args->quit)
    103       {
    104          pthread_mutex_unlock(&args->assignLock);
    105          break;
    106       }
    107       else
    108           assert(args->assignedWork);
    109 
    110       for (unsigned y = args->startY; y <= args->endY; y += 2) {
    111          do {
    112             if (args->bV.position.x < 0) {
    113                if (args->cV.position.x < 0)
    114                   break;
    115                InterpolateVertex(&args->bV, &args->cV, -args->bV.position.x /
    116                                  (args->cV.position.x - args->bV.position.x),
    117                                  &clip0, args->varyingCount);
    118                left = &clip0;
    119             } else
    120                left = &args->bV;
    121             if ((int)args->cV.position.x >= (int)args->width) {
    122                if (args->bV.position.x >= (int)args->width)
    123                   break;
    124                InterpolateVertex(&args->bV, &args->cV, (args->width - 1 - args->bV.position.x) /
    125                                  (args->cV.position.x - args->bV.position.x),
    126                                  &clip1, args->varyingCount);
    127                right = &clip1;
    128             } else
    129                right = &args->cV;
    130             args->iface->ScanLine(args->iface, left, right);
    131          } while (false);
    132          for (unsigned i = 0; i < args->varyingCount; i++) {
    133             args->bV.varyings[i] += args->bDx.varyings[i];
    134             args->cV.varyings[i] += args->cDx.varyings[i];
    135          }
    136          args->bV.position += args->bDx.position;
    137          args->cV.position += args->cDx.position;
    138          args->bV.frontFacingPointCoord += args->bDx.frontFacingPointCoord;
    139          args->cV.frontFacingPointCoord += args->cDx.frontFacingPointCoord;
    140       }
    141 
    142       pthread_mutex_lock(&args->finishLock);
    143       pthread_cond_signal(&args->finishCond);
    144       pthread_mutex_unlock(&args->finishLock);
    145    }
    146    pthread_exit(NULL);
    147    return NULL;
    148 }
    149 #endif
    150 
    151 static void RasterTrapezoid(const GGLInterface * iface, const VertexOutput * tl,
    152                             const VertexOutput * tr, const VertexOutput * bl,
    153                             const VertexOutput * br)
    154 {
    155    GGL_GET_CONST_CONTEXT(ctx, iface);
    156 
    157    assert(tl->position.x <= tr->position.x && bl->position.x <= br->position.x);
    158    assert(tl->position.y <= bl->position.y && tr->position.y <= br->position.y);
    159    assert(fabs(tl->position.y - tr->position.y) < 1 && fabs(bl->position.y - br->position.y) < 1);
    160 
    161    const unsigned width = ctx->frameSurface.width, height = ctx->frameSurface.height;
    162    const unsigned varyingCount = ctx->CurrentProgram->VaryingSlots;
    163 
    164 
    165    // tlv-trv and blv-brv are parallel and horizontal
    166    VertexOutput tlv(*tl), trv(*tr), blv(*bl), brv(*br);
    167    VertexOutput tmp;
    168 
    169    // vertically clip
    170 
    171    if ((int)tlv.position.y < 0) {
    172       InterpolateVertex(&tlv, &blv, (0 - tlv.position.y) / (blv.position.y - tlv.position.y),
    173                         &tmp, varyingCount);
    174       tlv = tmp;
    175    }
    176    if ((int)trv.position.y < 0) {
    177       InterpolateVertex(&trv, &brv, (0 - trv.position.y) / (brv.position.y - trv.position.y),
    178                         &tmp, varyingCount);
    179       trv = tmp;
    180    }
    181    if ((int)blv.position.y >= (int)height) {
    182       InterpolateVertex(&tlv, &blv, (height - 1 - tlv.position.y) / (blv.position.y - tlv.position.y),
    183                         &tmp, varyingCount);
    184       blv = tmp;
    185    }
    186    if ((int)brv.position.y >= (int)height) {
    187       InterpolateVertex(&trv, &brv, (height - 1 - trv.position.y) / (brv.position.y - trv.position.y),
    188                         &tmp, varyingCount);
    189       brv = tmp;
    190    }
    191 
    192 //   // horizontally clip
    193 //   if ((int)tlv.position.x < 0) {
    194 //      InterpolateVertex(&tlv, &trv, (0 - tlv.position.x) / (trv.position.x - tlv.position.x),
    195 //                        &tmp, varyingCount);
    196 //      tlv = tmp;
    197 //   }
    198 //   if ((int)blv.position.x < 0) {
    199 //      InterpolateVertex(&blv, &brv, (0 - blv.position.x) / (brv.position.x - blv.position.x),
    200 //                        &tmp, varyingCount);
    201 //      blv = tmp;
    202 //   }
    203 //   if ((int)trv.position.x >= (int)width) {
    204 //      InterpolateVertex(&tlv, &trv, (width - 1 - tlv.position.x) / (trv.position.x - tlv.position.x),
    205 //                        &tmp, varyingCount);
    206 //      trv = tmp;
    207 //   }
    208 //   if ((int)brv.position.x >= (int)width) {
    209 //      InterpolateVertex(&blv, &brv, (width - 1 - blv.position.x) / (brv.position.x - blv.position.x),
    210 //                        &tmp, varyingCount);
    211 //      brv = tmp;
    212 //   }
    213 
    214    const unsigned int startY = tlv.position.y;
    215    const unsigned int endY = blv.position.y;
    216 
    217    if (endY < startY)
    218       return;
    219 
    220    const VectorComp_t yDistInv = VectorComp_t_CTR(1.0f / (endY - startY));
    221 
    222    // bV and cV are left and right vertices on a horizontal line in quad
    223    // bDx and cDx are iterators from tlv to blv, trv to brv for bV and cV
    224 
    225    VertexOutput bV(tlv), cV(trv);
    226    VertexOutput bDx(blv), cDx(brv);
    227 
    228    for (unsigned i = 0; i < varyingCount; i++) {
    229       bDx.varyings[i] -= tlv.varyings[i];
    230       bDx.varyings[i] *= yDistInv;
    231 
    232       cDx.varyings[i] -= trv.varyings[i];
    233       cDx.varyings[i] *= yDistInv;
    234    }
    235 
    236    bDx.position -= tlv.position;
    237    bDx.position *= yDistInv;
    238 
    239    cDx.position -= trv.position;
    240    cDx.position *= yDistInv;
    241 
    242    bDx.frontFacingPointCoord -= tlv.frontFacingPointCoord; // gl_PointCoord
    243    bDx.frontFacingPointCoord *= yDistInv;
    244    bDx.frontFacingPointCoord.y = VectorComp_t_Zero; // gl_FrontFacing not interpolated
    245    cDx.frontFacingPointCoord -= trv.frontFacingPointCoord; // gl_PointCoord
    246    cDx.frontFacingPointCoord *= yDistInv;
    247    cDx.frontFacingPointCoord.y = VectorComp_t_Zero; // gl_FrontFacing not interpolated
    248 
    249 #if USE_DUAL_THREAD
    250    GGLContext::Worker & args = ctx->worker;
    251    if (!ctx->worker.thread) {
    252       pthread_attr_t attr;
    253       pthread_attr_init(&attr);
    254       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    255       int rc = pthread_create(&ctx->worker.thread, &attr, RasterTrapezoidWorker, &args);
    256       assert(!rc);
    257       // wait for worker to start
    258       pthread_cond_wait(&args.finishCond, &args.finishLock);
    259    }
    260    args.startY = startY + 1;
    261    args.endY = endY;
    262    if (args.startY <= args.endY) {
    263       pthread_mutex_lock(&args.assignLock);
    264 
    265       args.bV = bV;
    266       args.cV = cV;
    267       for (unsigned i = 0; i < varyingCount; i++) {
    268          args.bV.varyings[i] += bDx.varyings[i];
    269          bDx.varyings[i] += bDx.varyings[i];
    270          args.cV.varyings[i] += cDx.varyings[i];
    271          cDx.varyings[i] += cDx.varyings[i];
    272       }
    273       args.bV.position += bDx.position;
    274       bDx.position += bDx.position;
    275       args.cV.position += cDx.position;
    276       cDx.position += cDx.position;
    277       args.bV.frontFacingPointCoord += bDx.frontFacingPointCoord;
    278       bDx.frontFacingPointCoord += bDx.frontFacingPointCoord;
    279       args.cV.frontFacingPointCoord += cDx.frontFacingPointCoord;
    280       cDx.frontFacingPointCoord += cDx.frontFacingPointCoord;
    281       args.iface = iface;
    282       args.bDx = bDx;
    283       args.cDx = cDx;
    284       args.varyingCount = varyingCount;
    285       args.width = width;
    286       args.height = height;
    287       args.assignedWork = true;
    288 
    289       pthread_cond_signal(&args.assignCond);
    290       pthread_mutex_unlock(&args.assignLock);
    291    }
    292 #endif
    293 
    294    VertexOutput * left, * right;
    295    VertexOutput clip0, clip1;
    296 
    297    for (unsigned y = startY; y <= endY; y += 1 + USE_DUAL_THREAD) {
    298       do {
    299          if (bV.position.x < 0) {
    300             if (cV.position.x < 0)
    301                break;
    302             InterpolateVertex(&bV, &cV, -bV.position.x / (cV.position.x - bV.position.x),
    303                               &clip0, varyingCount);
    304             left = &clip0;
    305          } else
    306             left = &bV;
    307          if ((int)cV.position.x >= (int)width) {
    308             if (bV.position.x >= (int)width)
    309                break;
    310             InterpolateVertex(&bV, &cV, (width - 1 - bV.position.x) / (cV.position.x - bV.position.x),
    311                               &clip1, varyingCount);
    312             right = &clip1;
    313          } else
    314             right = &cV;
    315          iface->ScanLine(iface, left, right);
    316       } while (false);
    317       for (unsigned i = 0; i < varyingCount; i++) {
    318          bV.varyings[i] += bDx.varyings[i];
    319          cV.varyings[i] += cDx.varyings[i];
    320       }
    321       bV.position += bDx.position;
    322       cV.position += cDx.position;
    323       bV.frontFacingPointCoord += bDx.frontFacingPointCoord;
    324       cV.frontFacingPointCoord += cDx.frontFacingPointCoord;
    325    }
    326 
    327 #if USE_DUAL_THREAD
    328    if (args.assignedWork)
    329    {
    330       pthread_cond_wait(&args.finishCond, &args.finishLock);
    331       args.assignedWork = false;
    332    }
    333 #endif
    334 }
    335 
    336 static void RasterTriangle(const GGLInterface * iface, const VertexOutput * v1,
    337                            const VertexOutput * v2, const VertexOutput * v3)
    338 {
    339    GGL_GET_CONST_CONTEXT(ctx, iface);
    340    const unsigned varyingCount = ctx->CurrentProgram->VaryingSlots;
    341    const unsigned height = ctx->frameSurface.height;
    342    const VertexOutput * a = v1, * b = v2, * d = v3;
    343    //abc is a triangle, bcd is another triangle, they share bc as horizontal edge
    344    //c is between a and d, xy is screen coord
    345 
    346    //first sort 3 vertices by MIN y first
    347    if (v2->position.y < v1->position.y) {
    348       a = v2;
    349       b = v1;
    350    }
    351    if (v3->position.y < a->position.y) {
    352       d = b;
    353       b = a;
    354       a = v3;
    355    } else if (v3->position.y < b->position.y) {
    356       d = b;
    357       b = v3;
    358    }
    359 
    360    assert(a->position.y <= b->position.y && b->position.y <= d->position.y);
    361 
    362    VertexOutput cVertex;
    363    const VertexOutput* c = &cVertex;
    364 
    365    const VectorComp_t cLerp = (b->position.y - a->position.y) /
    366                               MAX2(VectorComp_t_One, (d->position.y - a->position.y));
    367    // create 4th vertex, same y as b to form two triangles/trapezoids sharing horizontal edge
    368    InterpolateVertex(a, d, cLerp, &cVertex, varyingCount);
    369 
    370    if (c->position.x < b->position.x) {
    371       const VertexOutput * tmp = c;
    372       c = b;
    373       b = tmp;
    374    }
    375 
    376    if ((int)a->position.y < (int)height && (int)b->position.y >= 0)
    377       RasterTrapezoid(iface, a, a, b, c);
    378    //b->position.y += VectorComp_t_One;
    379    //c->position.y += VectorComp_t_One;
    380    if ((int)b->position.y < (int)height && (int)d->position.y >= 0)
    381       RasterTrapezoid(iface, b, c, d, d);
    382 }
    383 
    384 static void DrawTriangle(const GGLInterface * iface, const VertexInput * vin1,
    385                          const VertexInput * vin2, const VertexInput * vin3)
    386 {
    387    GGL_GET_CONST_CONTEXT(ctx, iface);
    388 
    389    VertexOutput vouts[3];
    390    memset(vouts, 0, sizeof(vouts));
    391    VertexOutput * v1 = vouts + 0, * v2 = vouts + 1, * v3 = vouts + 2;
    392 
    393 //   ALOGD("pf2: DrawTriangle");
    394 
    395 //   if (!strstr(program->Shaders[MESA_SHADER_FRAGMENT]->Source,
    396 //               "gl_FragColor = color * texture2D(sampler, outTexCoords).a;"))
    397 //      return;
    398 
    399 //   for (unsigned i = 0; i < program->NumShaders; i++)
    400 //      if (program->Shaders[i]->Source)
    401 //         ALOGD("%s", program->Shaders[i]->Source);
    402 
    403 //   if (!strstr(program->Shaders[MESA_SHADER_FRAGMENT]->Source, ").a;"))
    404 //      return;
    405 
    406 //   ALOGD("%s", program->Shaders[MESA_SHADER_VERTEX]->Source);
    407 //   ALOGD("%s", program->Shaders[MESA_SHADER_FRAGMENT]->Source);
    408 
    409 //   for (unsigned i = 0; i < program->Attributes->NumParameters; i++) {
    410 //      const gl_program_parameter & attribute = program->Attributes->Parameters[i];
    411 //      ALOGD("attribute '%s': location=%d slots=%d \n", attribute.Name, attribute.Location, attribute.Slots);
    412 //   }
    413 //   for (unsigned i = 0; i < program->Varying->NumParameters; i++) {
    414 //      const gl_program_parameter & varying = program->Varying->Parameters[i];
    415 //      ALOGD("varying '%s': vs_location=%d fs_location=%d \n", varying.Name, varying.BindLocation, varying.Location);
    416 //   }
    417 //   for (unsigned i = 0; i < program->Uniforms->NumUniforms; i++) {
    418 //      const gl_uniform & uniform = program->Uniforms->Uniforms[i];
    419 //      ALOGD("uniform '%s': location=%d type=%s \n", uniform.Name, uniform.Pos, uniform.Type->name);
    420 //   }
    421 
    422 //   __attribute__ ((aligned (16)))
    423 //   static const float matrix[16] = {
    424 //      1,0,0,0,
    425 //      0,1,0,0,
    426 //      0,0,1,0,
    427 //      0,0,0,1
    428 //   };
    429 //
    430 //   iface->ShaderUniformMatrix((gl_shader_program *)program, 4, 4, 0, 1, GL_FALSE, matrix);
    431 
    432    iface->ProcessVertex(iface, vin1, v1);
    433    iface->ProcessVertex(iface, vin2, v2);
    434    iface->ProcessVertex(iface, vin3, v3);
    435 
    436 //   __attribute__ ((aligned (16)))
    437 //   static const float matrix[16] = {
    438 //      2,0,0,0,
    439 //      0,-2,0,0,
    440 //      0,0,-1,0,
    441 //      -1,1,0,1
    442 //   };
    443 
    444 
    445 //   float * matrix = program->ValuesUniform[0];
    446 //   for (unsigned i = 0; i < 4; i++)
    447 //      ALOGD("pf2: DrawTriangle %.2f \t %.2f \t %.2f \t %.2f \n", matrix[i * 4 + 0],
    448 //           matrix[i * 4 + 1], matrix[i * 4 + 2], matrix[i * 4 + 3]);
    449 ////   ALOGD("color %.02f %.02f %.02f %.02f", program->ValuesUniform[4][0], program->ValuesUniform[4][1],
    450 ////        program->ValuesUniform[4][2], program->ValuesUniform[4][3]);
    451 //   ALOGD("vin1 position %.02f %.02f %.02f %.02f", vin1->attributes[1].x, vin1->attributes[1].y,
    452 //        vin1->attributes[1].z, vin1->attributes[1].w);
    453 //   ALOGD("vin2 position %.02f %.02f %.02f %.02f", vin2->attributes[1].x, vin2->attributes[1].y,
    454 //        vin2->attributes[1].z, vin2->attributes[1].w);
    455 //   ALOGD("vin3 position %.02f %.02f %.02f %.02f", vin3->attributes[1].x, vin3->attributes[1].y,
    456 //        vin3->attributes[1].z, vin3->attributes[1].w);
    457 
    458 //   GGLProcessVertex(program, vin1, v1, (const float (*)[4])matrix);
    459 //   GGLProcessVertex(program, vin2, v2, (const float (*)[4])matrix);
    460 //   GGLProcessVertex(program, vin3, v3, (const float (*)[4])matrix);
    461 
    462 //   ALOGD("pf2: DrawTriangle processed %.02f %.02f %.2f %.2f \t %.02f %.02f %.2f %.2f \t %.02f %.02f %.2f %.2f",
    463 //        v1->position.x, v1->position.y, v1->position.z, v1->position.w,
    464 //        v2->position.x, v2->position.y, v2->position.z, v2->position.w,
    465 //        v3->position.x, v3->position.y, v3->position.z, v3->position.w);
    466 
    467    v1->position /= v1->position.w;
    468    v2->position /= v2->position.w;
    469    v3->position /= v3->position.w;
    470 
    471 //   ALOGD("pf2: DrawTriangle divided %.02f,%.02f \t %.02f,%.02f \t %.02f,%.02f", v1->position.x, v1->position.y,
    472 //      v2->position.x, v2->position.y, v3->position.x, v3->position.y);
    473 
    474    iface->ViewportTransform(iface, &v1->position);
    475    iface->ViewportTransform(iface, &v2->position);
    476    iface->ViewportTransform(iface, &v3->position);
    477 
    478 //   if (strstr(program->Shaders[MESA_SHADER_FRAGMENT]->Source,
    479 //              "gl_FragColor = color * texture2D(sampler, outTexCoords).a;")) {
    480 ////      ALOGD("%s", program->Shaders[MESA_SHADER_FRAGMENT]->Source);
    481 //      v1->position = vin1->attributes[0];
    482 //      v2->position = vin2->attributes[0];
    483 //      v3->position = vin3->attributes[0];
    484 //
    485 //      v1->varyings[0] = vin1->attributes[1];
    486 //      v2->varyings[0] = vin2->attributes[1];
    487 //      v3->varyings[0] = vin3->attributes[1];
    488 //   }
    489 
    490 //   ALOGD("pf2: DrawTriangle transformed %.0f,%.0f \t %.0f,%.0f \t %.0f,%.0f", v1->position.x, v1->position.y,
    491 //        v2->position.x, v2->position.y, v3->position.x, v3->position.y);
    492 
    493 //   ALOGD("pf2: DrawTriangle varying %.02f %.02f %.2f %.2f \t %.02f %.02f %.2f %.2f \t %.02f %.02f %.2f %.2f",
    494 //        v1->varyings[0].x, v1->varyings[0].y, v1->varyings[0].z, v1->varyings[0].w,
    495 //        v2->varyings[0].x, v2->varyings[0].y, v2->varyings[0].z, v2->varyings[0].w,
    496 //        v3->varyings[0].x, v3->varyings[0].y, v3->varyings[0].z, v3->varyings[0].w);
    497 
    498    VectorComp_t area;
    499    area = v1->position.x * v2->position.y - v2->position.x * v1->position.y;
    500    area += v2->position.x * v3->position.y - v3->position.x * v2->position.y;
    501    area += v3->position.x * v1->position.y - v1->position.x * v3->position.y;
    502    area *= 0.5f;
    503 
    504    if (GL_CCW == ctx->cullState.frontFace + GL_CW)
    505       (unsigned &)area ^= 0x80000000;
    506 
    507    if (false && ctx->cullState.enable) { // TODO: turn off for now
    508       switch (ctx->cullState.cullFace + GL_FRONT) {
    509       case GL_FRONT:
    510          if (!((unsigned &)area & 0x80000000)) // +ve, front facing
    511             return;
    512          break;
    513       case GL_BACK:
    514          if ((unsigned &)area & 0x80000000) // -ve, back facing
    515             return;
    516          break;
    517       case GL_FRONT_AND_BACK:
    518          return;
    519       default:
    520          assert(0);
    521       }
    522    }
    523 
    524    v1->frontFacingPointCoord.y = v2->frontFacingPointCoord.y =
    525                                     v3->frontFacingPointCoord.y = !((unsigned &)area & 0x80000000) ?
    526                                                                   VectorComp_t_One : VectorComp_t_Zero;
    527 
    528    iface->StencilSelect(iface, ((unsigned &)area & 0x80000000) ? GL_BACK : GL_FRONT);
    529 
    530 //    if (0)
    531 //    {
    532 //        GGLContext * ctx =(GGLContext *)iface;
    533 //        for (unsigned sampler = 0; sampler < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; sampler++)
    534 //        {
    535 //            if (!((1 << sampler) & ctx->glCtx->Shader.CurrentProgram->FragmentProgram->SamplersUsed))
    536 //                continue;
    537 //            const GGLTexture * texture = ctx->textureState.textures + sampler;
    538 //            int level = texture->width * texture->height / (area * 2) - 4;
    539 //            assert(texture->levels);
    540 //            ctx->textureState.textureData[sampler] = texture->levels[0];
    541 //            ctx->textureState.textureDimensions[sampler * 2] = texture->width;
    542 //            ctx->textureState.textureDimensions[sampler * 2 + 1] = texture->height;
    543 //            for (unsigned i = 1; i < texture->levelCount && i <= level; i++)
    544 //            {
    545 //                ctx->textureState.textureData[sampler] = texture->levels[i];
    546 //                ctx->textureState.textureDimensions[sampler * 2] += 1;
    547 //                ctx->textureState.textureDimensions[sampler * 2] /= 2;
    548 //                ctx->textureState.textureDimensions[sampler * 2 + 1] += 1;
    549 //                ctx->textureState.textureDimensions[sampler * 2 + 1] /= 2;
    550 //            }
    551 //        }
    552 //    }
    553 
    554    // TODO DXL view frustum clipping
    555    iface->RasterTriangle(iface, v1, v2, v3);
    556 
    557 //   ALOGD("pf2: DrawTriangle end");
    558 
    559 }
    560 
    561 static void PickRaster(GGLInterface * iface)
    562 {
    563    iface->ProcessVertex = ProcessVertex;
    564    iface->DrawTriangle = DrawTriangle;
    565    iface->RasterTriangle = RasterTriangle;
    566    iface->RasterTrapezoid = RasterTrapezoid;
    567 }
    568 
    569 static void ViewportTransform(const GGLInterface * iface, Vector4 * v)
    570 {
    571    GGL_GET_CONST_CONTEXT(ctx, iface);
    572    v->x = v->x * ctx->viewport.w + ctx->viewport.x;
    573    v->y *= -1;
    574    v->y = v->y * ctx->viewport.h + ctx->viewport.y;
    575    v->z = v->z * ctx->viewport.f + ctx->viewport.n;
    576 }
    577 
    578 
    579 void InitializeRasterFunctions(GGLInterface * iface)
    580 {
    581    GGL_GET_CONTEXT(ctx, iface);
    582    ctx->PickRaster = PickRaster;
    583    iface->ViewportTransform = ViewportTransform;
    584 }
    585