1 /* libs/opengles/vertex.cpp
3 ** Copyright 2006, The Android Open Source Project
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
9 ** http://www.apache.org/licenses/LICENSE-2.0
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.
28 // ----------------------------------------------------------------------------
30 void ogles_init_vertex(ogles_context_t* c)
32 c->cull.enable = GL_FALSE;
33 c->cull.cullFace = GL_BACK;
34 c->cull.frontFace = GL_CCW;
36 c->current.color.r = 0x10000;
37 c->current.color.g = 0x10000;
38 c->current.color.b = 0x10000;
39 c->current.color.a = 0x10000;
41 c->currentNormal.z = 0x10000;
44 void ogles_uninit_vertex(ogles_context_t* c)
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 // Divides a vertex clip coordinates by W
54 void perspective(ogles_context_t* c, vertex_t* v, uint32_t enables)
56 // [x,y,z]window = vpt * ([x,y,z]clip / clip.w)
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.
69 const int32_t rw = gglRecip28(v->clip.w);
70 const GLfixed* const m = c->transforms.vpt.transform.matrix.m;
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);
81 // frustum clipping and W-divide
83 void clipFrustumPerspective(ogles_context_t* c, vertex_t* v, uint32_t enables)
86 // window = ncd * viewport
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;
99 c->arrays.cull &= clip;
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);
108 // frustum clipping, user clipping and W-divide
110 void clipAllPerspective(ogles_context_t* c, vertex_t* v, uint32_t enables)
112 // compute eye coordinates
113 c->arrays.mv_transform(
114 &c->transforms.modelview.transform, &v->eye, &v->obj);
115 v->flags |= vertex_t::EYE;
117 // clip this vertex against each user clip plane
119 int planes = c->clipPlanes.enable;
121 const int i = 31 - gglClz(planes);
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);
131 clipFrustumPerspective(c, v, enables);
134 // ----------------------------------------------------------------------------
136 void ogles_vertex_project(ogles_context_t* c, vertex_t* v) {
137 perspective(c, v, c->rasterizer.state.enables);
140 void ogles_vertex_perspective2D(ogles_context_t* c, vertex_t* v)
142 // here we assume w=1.0 and the viewport transformation
143 // has been applied already.
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;
151 void ogles_vertex_perspective3DZ(ogles_context_t* c, vertex_t* v) {
152 clipFrustumPerspective(c, v, GGL_ENABLE_DEPTH_TEST);
154 void ogles_vertex_perspective3D(ogles_context_t* c, vertex_t* v) {
155 clipFrustumPerspective(c, v, 0);
157 void ogles_vertex_clipAllPerspective3DZ(ogles_context_t* c, vertex_t* v) {
158 clipAllPerspective(c, v, GGL_ENABLE_DEPTH_TEST);
160 void ogles_vertex_clipAllPerspective3D(ogles_context_t* c, vertex_t* v) {
161 clipAllPerspective(c, v, 0);
164 static void clipPlanex(GLenum plane, const GLfixed* equ, ogles_context_t* c)
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);
172 vec4_t& equation = c->clipPlanes.plane[p].equation;
173 memcpy(equation.v, equ, sizeof(vec4_t));
175 ogles_validate_transform(c, transform_state_t::MVIT);
176 transform_t& mvit = c->transforms.mvit4;
177 mvit.point4(&mvit, &equation, &equation);
180 // ----------------------------------------------------------------------------
181 }; // namespace android
182 // ----------------------------------------------------------------------------
184 using namespace android;
187 void glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
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);
200 void glColor4x(GLfixed r, GLfixed g, GLfixed b, GLfixed a)
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);
213 void glNormal3f(GLfloat x, GLfloat y, GLfloat z)
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);
221 void glNormal3x(GLfixed x, GLfixed y, GLfixed z)
223 ogles_context_t* c = ogles_context_t::get();
224 c->currentNormal.x = x;
225 c->currentNormal.y = y;
226 c->currentNormal.z = z;
229 // ----------------------------------------------------------------------------
231 void glClipPlanef(GLenum plane, const GLfloat* equ)
233 const GLfixed equx[4] = {
234 gglFloatToFixed(equ[0]),
235 gglFloatToFixed(equ[1]),
236 gglFloatToFixed(equ[2]),
237 gglFloatToFixed(equ[3])
239 ogles_context_t* c = ogles_context_t::get();
240 clipPlanex(plane, equx, c);
243 void glClipPlanex(GLenum plane, const GLfixed* equ)
245 ogles_context_t* c = ogles_context_t::get();
246 clipPlanex(plane, equ, c);