• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ogles_init_vertex(ogles_context_t * c)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 
ogles_uninit_vertex(ogles_context_t *)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
perspective(ogles_context_t * c,vertex_t * v,uint32_t enables)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
clipFrustumPerspective(ogles_context_t * c,vertex_t * v,uint32_t enables)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
clipAllPerspective(ogles_context_t * c,vertex_t * v,uint32_t enables)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 
ogles_vertex_project(ogles_context_t * c,vertex_t * v)136 void ogles_vertex_project(ogles_context_t* c, vertex_t* v) {
137     perspective(c, v, c->rasterizer.state.enables);
138 }
139 
ogles_vertex_perspective2D(ogles_context_t * c,vertex_t * v)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 
ogles_vertex_perspective3DZ(ogles_context_t * c,vertex_t * v)151 void ogles_vertex_perspective3DZ(ogles_context_t* c, vertex_t* v) {
152     clipFrustumPerspective(c, v, GGL_ENABLE_DEPTH_TEST);
153 }
ogles_vertex_perspective3D(ogles_context_t * c,vertex_t * v)154 void ogles_vertex_perspective3D(ogles_context_t* c, vertex_t* v) {
155     clipFrustumPerspective(c, v, 0);
156 }
ogles_vertex_clipAllPerspective3DZ(ogles_context_t * c,vertex_t * v)157 void ogles_vertex_clipAllPerspective3DZ(ogles_context_t* c, vertex_t* v) {
158     clipAllPerspective(c, v, GGL_ENABLE_DEPTH_TEST);
159 }
ogles_vertex_clipAllPerspective3D(ogles_context_t * c,vertex_t * v)160 void ogles_vertex_clipAllPerspective3D(ogles_context_t* c, vertex_t* v) {
161     clipAllPerspective(c, v, 0);
162 }
163 
clipPlanex(GLenum plane,const GLfixed * equ,ogles_context_t * c)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 
glColor4f(GLfloat r,GLfloat g,GLfloat b,GLfloat a)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 
glColor4x(GLfixed r,GLfixed g,GLfixed b,GLfixed a)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 
glNormal3f(GLfloat x,GLfloat y,GLfloat z)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 
glNormal3x(GLfixed x,GLfixed y,GLfixed z)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 
glClipPlanef(GLenum plane,const GLfloat * equ)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 
glClipPlanex(GLenum plane,const GLfixed * equ)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