Home | History | Annotate | Download | only in libagl
      1 /* libs/opengles/vertex.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 <stdio.h>
     19 #include <stdlib.h>
     20 #include "context.h"
     21 #include "fp.h"
     22 #include "vertex.h"
     23 #include "state.h"
     24 #include "matrix.h"
     25 
     26 namespace android {
     27 
     28 // ----------------------------------------------------------------------------
     29 
     30 void ogles_init_vertex(ogles_context_t* c)
     31 {
     32     c->cull.enable = GL_FALSE;
     33     c->cull.cullFace = GL_BACK;
     34     c->cull.frontFace = GL_CCW;
     35 
     36     c->current.color.r = 0x10000;
     37     c->current.color.g = 0x10000;
     38     c->current.color.b = 0x10000;
     39     c->current.color.a = 0x10000;
     40 
     41     c->currentNormal.z = 0x10000;
     42 }
     43 
     44 void ogles_uninit_vertex(ogles_context_t* /*c*/)
     45 {
     46 }
     47 
     48 // ----------------------------------------------------------------------------
     49 // vertex processing
     50 // ----------------------------------------------------------------------------
     51 
     52 // Divides a vertex clip coordinates by W
     53 static inline
     54 void perspective(ogles_context_t* c, vertex_t* v, uint32_t enables)
     55 {
     56     // [x,y,z]window = vpt * ([x,y,z]clip / clip.w)
     57     // [w]window = 1/w
     58 
     59     // With a regular projection generated by glFrustum(),
     60     // we have w=-z, therefore, w is in [zNear, zFar].
     61     // Also, zNear and zFar are stricly positive,
     62     // and 1/w (window.w) is in [1/zFar, 1/zNear], usually this
     63     // means ]0, +inf[ -- however, it is always recommended
     64     // to use as large values as possible for zNear.
     65     // All in all, w is usually smaller than 1.0 (assuming
     66     // zNear is at least 1.0); and even if zNear is smaller than 1.0
     67     // values of w won't be too big.
     68 
     69     const int32_t rw = gglRecip28(v->clip.w);
     70     const GLfixed* const m = c->transforms.vpt.transform.matrix.m;
     71     v->window.w = rw;
     72     v->window.x = gglMulAddx(gglMulx(v->clip.x, rw, 16), m[ 0], m[12], 28);
     73     v->window.y = gglMulAddx(gglMulx(v->clip.y, rw, 16), m[ 5], m[13], 28);
     74     v->window.x = TRI_FROM_FIXED(v->window.x);
     75     v->window.y = TRI_FROM_FIXED(v->window.y);
     76     if (enables & GGL_ENABLE_DEPTH_TEST) {
     77         v->window.z = gglMulAddx(gglMulx(v->clip.z, rw, 16), m[10], m[14], 28);
     78     }
     79 }
     80 
     81 // frustum clipping and W-divide
     82 static inline
     83 void clipFrustumPerspective(ogles_context_t* c, vertex_t* v, uint32_t enables)
     84 {
     85     // ndc = clip / W
     86     // window = ncd * viewport
     87 
     88     // clip to the view-volume
     89     uint32_t clip = v->flags & vertex_t::CLIP_ALL;
     90     const GLfixed w = v->clip.w;
     91     if (v->clip.x < -w)   clip |= vertex_t::CLIP_L;
     92     if (v->clip.x >  w)   clip |= vertex_t::CLIP_R;
     93     if (v->clip.y < -w)   clip |= vertex_t::CLIP_B;
     94     if (v->clip.y >  w)   clip |= vertex_t::CLIP_T;
     95     if (v->clip.z < -w)   clip |= vertex_t::CLIP_N;
     96     if (v->clip.z >  w)   clip |= vertex_t::CLIP_F;
     97 
     98     v->flags |= clip;
     99     c->arrays.cull &= clip;
    100 
    101     if (ggl_likely(!clip)) {
    102         // if the vertex is clipped, we don't do the perspective
    103         // divide, since we don't need its window coordinates.
    104         perspective(c, v, enables);
    105     }
    106 }
    107 
    108 // frustum clipping, user clipping and W-divide
    109 static inline
    110 void clipAllPerspective(ogles_context_t* c, vertex_t* v, uint32_t enables)
    111 {
    112     // compute eye coordinates
    113     c->arrays.mv_transform(
    114             &c->transforms.modelview.transform, &v->eye, &v->obj);
    115     v->flags |= vertex_t::EYE;
    116 
    117     // clip this vertex against each user clip plane
    118     uint32_t clip = 0;
    119     int planes = c->clipPlanes.enable;
    120     while (planes) {
    121         const int i = 31 - gglClz(planes);
    122         planes &= ~(1<<i);
    123         // XXX: we should have a special dot() for 2,3,4 coords vertices
    124         GLfixed d = dot4(c->clipPlanes.plane[i].equation.v, v->eye.v);
    125         if (d < 0) {
    126             clip |= 0x100<<i;
    127         }
    128     }
    129     v->flags |= clip;
    130 
    131     clipFrustumPerspective(c, v, enables);
    132 }
    133 
    134 // ----------------------------------------------------------------------------
    135 
    136 void ogles_vertex_project(ogles_context_t* c, vertex_t* v) {
    137     perspective(c, v, c->rasterizer.state.enables);
    138 }
    139 
    140 void ogles_vertex_perspective2D(ogles_context_t* c, vertex_t* v)
    141 {
    142     // here we assume w=1.0 and the viewport transformation
    143     // has been applied already.
    144     c->arrays.cull = 0;
    145     v->window.x = TRI_FROM_FIXED(v->clip.x);
    146     v->window.y = TRI_FROM_FIXED(v->clip.y);
    147     v->window.z = v->clip.z;
    148     v->window.w = v->clip.w << 12;
    149 }
    150 
    151 void ogles_vertex_perspective3DZ(ogles_context_t* c, vertex_t* v) {
    152     clipFrustumPerspective(c, v, GGL_ENABLE_DEPTH_TEST);
    153 }
    154 void ogles_vertex_perspective3D(ogles_context_t* c, vertex_t* v) {
    155     clipFrustumPerspective(c, v, 0);
    156 }
    157 void ogles_vertex_clipAllPerspective3DZ(ogles_context_t* c, vertex_t* v) {
    158     clipAllPerspective(c, v, GGL_ENABLE_DEPTH_TEST);
    159 }
    160 void ogles_vertex_clipAllPerspective3D(ogles_context_t* c, vertex_t* v) {
    161     clipAllPerspective(c, v, 0);
    162 }
    163 
    164 static void clipPlanex(GLenum plane, const GLfixed* equ, ogles_context_t* c)
    165 {
    166     const int p = plane - GL_CLIP_PLANE0;
    167     if (ggl_unlikely(uint32_t(p) > (GL_CLIP_PLANE5 - GL_CLIP_PLANE0))) {
    168         ogles_error(c, GL_INVALID_ENUM);
    169         return;
    170     }
    171 
    172     vec4_t& equation = c->clipPlanes.plane[p].equation;
    173     memcpy(equation.v, equ, sizeof(vec4_t));
    174 
    175     ogles_validate_transform(c, transform_state_t::MVIT);
    176     transform_t& mvit = c->transforms.mvit4;
    177     mvit.point4(&mvit, &equation, &equation);
    178 }
    179 
    180 // ----------------------------------------------------------------------------
    181 }; // namespace android
    182 // ----------------------------------------------------------------------------
    183 
    184 using namespace android;
    185 
    186 
    187 void glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
    188 {
    189     ogles_context_t* c = ogles_context_t::get();
    190     c->current.color.r       = gglFloatToFixed(r);
    191     c->currentColorClamped.r = gglClampx(c->current.color.r);
    192     c->current.color.g       = gglFloatToFixed(g);
    193     c->currentColorClamped.g = gglClampx(c->current.color.g);
    194     c->current.color.b       = gglFloatToFixed(b);
    195     c->currentColorClamped.b = gglClampx(c->current.color.b);
    196     c->current.color.a       = gglFloatToFixed(a);
    197     c->currentColorClamped.a = gglClampx(c->current.color.a);
    198 }
    199 
    200 void glColor4x(GLfixed r, GLfixed g, GLfixed b, GLfixed a)
    201 {
    202     ogles_context_t* c = ogles_context_t::get();
    203     c->current.color.r = r;
    204     c->current.color.g = g;
    205     c->current.color.b = b;
    206     c->current.color.a = a;
    207     c->currentColorClamped.r = gglClampx(r);
    208     c->currentColorClamped.g = gglClampx(g);
    209     c->currentColorClamped.b = gglClampx(b);
    210     c->currentColorClamped.a = gglClampx(a);
    211 }
    212 
    213 void glNormal3f(GLfloat x, GLfloat y, GLfloat z)
    214 {
    215     ogles_context_t* c = ogles_context_t::get();
    216     c->currentNormal.x = gglFloatToFixed(x);
    217     c->currentNormal.y = gglFloatToFixed(y);
    218     c->currentNormal.z = gglFloatToFixed(z);
    219 }
    220 
    221 void glNormal3x(GLfixed x, GLfixed y, GLfixed z)
    222 {
    223     ogles_context_t* c = ogles_context_t::get();
    224     c->currentNormal.x = x;
    225     c->currentNormal.y = y;
    226     c->currentNormal.z = z;
    227 }
    228 
    229 // ----------------------------------------------------------------------------
    230 
    231 void glClipPlanef(GLenum plane, const GLfloat* equ)
    232 {
    233     const GLfixed equx[4] = {
    234             gglFloatToFixed(equ[0]),
    235             gglFloatToFixed(equ[1]),
    236             gglFloatToFixed(equ[2]),
    237             gglFloatToFixed(equ[3])
    238     };
    239     ogles_context_t* c = ogles_context_t::get();
    240     clipPlanex(plane, equx, c);
    241 }
    242 
    243 void glClipPlanex(GLenum plane, const GLfixed* equ)
    244 {
    245     ogles_context_t* c = ogles_context_t::get();
    246     clipPlanex(plane, equ, c);
    247 }
    248