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