| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 |  | 
| Mark Salyzyn | 92dc3fc | 2014-03-12 13:12:44 -0700 | [diff] [blame] | 44 | void ogles_uninit_vertex(ogles_context_t* /*c*/) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 | } |