blob: 216c7251285f26ad92b19dc940ac86ea0f677bf0 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/* libs/opengles/light.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 "context.h"
20#include "fp.h"
21#include "light.h"
22#include "state.h"
23#include "matrix.h"
24
25
26#if defined(__arm__) && defined(__thumb__)
27#warning "light.cpp should not be compiled in thumb on ARM."
28#endif
29
30namespace android {
31
32// ----------------------------------------------------------------------------
33
34static void invalidate_lighting(ogles_context_t* c);
35static void lightVertexValidate(ogles_context_t* c, vertex_t* v);
36static void lightVertexNop(ogles_context_t* c, vertex_t* v);
37static void lightVertex(ogles_context_t* c, vertex_t* v);
38static void lightVertexMaterial(ogles_context_t* c, vertex_t* v);
39
40static inline void vscale3(GLfixed* d, const GLfixed* m, GLfixed s);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080041
42static __attribute__((noinline))
43void vnorm3(GLfixed* d, const GLfixed* a);
44
45static inline void vsa3(GLfixed* d,
46 const GLfixed* m, GLfixed s, const GLfixed* a);
Mathias Agopian69ca17a2009-06-02 22:05:04 -070047static inline void vss3(GLfixed* d,
48 const GLfixed* m, GLfixed s, const GLfixed* a);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080049static inline void vmla3(GLfixed* d,
50 const GLfixed* m0, const GLfixed* m1, const GLfixed* a);
51static inline void vmul3(GLfixed* d,
52 const GLfixed* m0, const GLfixed* m1);
53
54static GLfixed fog_linear(ogles_context_t* c, GLfixed z);
55static GLfixed fog_exp(ogles_context_t* c, GLfixed z);
56static GLfixed fog_exp2(ogles_context_t* c, GLfixed z);
57
58
59// ----------------------------------------------------------------------------
60
61static void init_white(vec4_t& c) {
62 c.r = c.g = c.b = c.a = 0x10000;
63}
64
65void ogles_init_light(ogles_context_t* c)
66{
67 for (unsigned int i=0 ; i<OGLES_MAX_LIGHTS ; i++) {
68 c->lighting.lights[i].ambient.a = 0x10000;
69 c->lighting.lights[i].position.z = 0x10000;
70 c->lighting.lights[i].spotDir.z = -0x10000;
71 c->lighting.lights[i].spotCutoff = gglIntToFixed(180);
72 c->lighting.lights[i].attenuation[0] = 0x10000;
73 }
74 init_white(c->lighting.lights[0].diffuse);
75 init_white(c->lighting.lights[0].specular);
76
77 c->lighting.front.ambient.r =
78 c->lighting.front.ambient.g =
79 c->lighting.front.ambient.b = gglFloatToFixed(0.2f);
80 c->lighting.front.ambient.a = 0x10000;
81 c->lighting.front.diffuse.r =
82 c->lighting.front.diffuse.g =
83 c->lighting.front.diffuse.b = gglFloatToFixed(0.8f);
84 c->lighting.front.diffuse.a = 0x10000;
85 c->lighting.front.specular.a = 0x10000;
86 c->lighting.front.emission.a = 0x10000;
87
88 c->lighting.lightModel.ambient.r =
89 c->lighting.lightModel.ambient.g =
90 c->lighting.lightModel.ambient.b = gglFloatToFixed(0.2f);
91 c->lighting.lightModel.ambient.a = 0x10000;
92
93 c->lighting.colorMaterial.face = GL_FRONT_AND_BACK;
94 c->lighting.colorMaterial.mode = GL_AMBIENT_AND_DIFFUSE;
95
96 c->fog.mode = GL_EXP;
97 c->fog.fog = fog_exp;
98 c->fog.density = 0x10000;
99 c->fog.end = 0x10000;
100 c->fog.invEndMinusStart = 0x10000;
101
102 invalidate_lighting(c);
103
104 c->rasterizer.procs.shadeModel(c, GL_SMOOTH);
105 c->lighting.shadeModel = GL_SMOOTH;
106}
107
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -0700108void ogles_uninit_light(ogles_context_t* /*c*/)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800109{
110}
111
112static inline int32_t clampF(GLfixed f) CONST;
113int32_t clampF(GLfixed f) {
114 f = (f & ~(f>>31));
115 if (f >= 0x10000)
116 f = 0x10000;
117 return f;
118}
119
120static GLfixed fog_linear(ogles_context_t* c, GLfixed z) {
121 return clampF(gglMulx((c->fog.end - ((z<0)?-z:z)), c->fog.invEndMinusStart));
122}
123
124static GLfixed fog_exp(ogles_context_t* c, GLfixed z) {
125 const float e = fixedToFloat(gglMulx(c->fog.density, ((z<0)?-z:z)));
126 return clampF(gglFloatToFixed(fastexpf(-e)));
127}
128
129static GLfixed fog_exp2(ogles_context_t* c, GLfixed z) {
130 const float e = fixedToFloat(gglMulx(c->fog.density, z));
131 return clampF(gglFloatToFixed(fastexpf(-e*e)));
132}
133
134// ----------------------------------------------------------------------------
135#if 0
136#pragma mark -
137#pragma mark math helpers
138#endif
139
140static inline
141void vscale3(GLfixed* d, const GLfixed* m, GLfixed s) {
142 d[0] = gglMulx(m[0], s);
143 d[1] = gglMulx(m[1], s);
144 d[2] = gglMulx(m[2], s);
145}
146
147static inline
148void vsa3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a) {
149 d[0] = gglMulAddx(m[0], s, a[0]);
150 d[1] = gglMulAddx(m[1], s, a[1]);
151 d[2] = gglMulAddx(m[2], s, a[2]);
152}
153
154static inline
Mathias Agopian69ca17a2009-06-02 22:05:04 -0700155void vss3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a) {
156 d[0] = gglMulSubx(m[0], s, a[0]);
157 d[1] = gglMulSubx(m[1], s, a[1]);
158 d[2] = gglMulSubx(m[2], s, a[2]);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800159}
160
161static inline
162void vmla3(GLfixed* d,
163 const GLfixed* m0, const GLfixed* m1, const GLfixed* a)
164{
165 d[0] = gglMulAddx(m0[0], m1[0], a[0]);
166 d[1] = gglMulAddx(m0[1], m1[1], a[1]);
167 d[2] = gglMulAddx(m0[2], m1[2], a[2]);
168}
169
170static inline
171void vmul3(GLfixed* d, const GLfixed* m0, const GLfixed* m1) {
172 d[0] = gglMulx(m0[0], m1[0]);
173 d[1] = gglMulx(m0[1], m1[1]);
174 d[2] = gglMulx(m0[2], m1[2]);
175}
176
177void vnorm3(GLfixed* d, const GLfixed* a)
178{
179 // we must take care of overflows when normalizing a vector
180 GLfixed n;
181 int32_t x = a[0]; x = x>=0 ? x : -x;
182 int32_t y = a[1]; y = y>=0 ? y : -y;
183 int32_t z = a[2]; z = z>=0 ? z : -z;
184 if (ggl_likely(x<=0x6800 && y<=0x6800 && z<= 0x6800)) {
185 // in this case this will all fit on 32 bits
186 n = x*x + y*y + z*z;
187 n = gglSqrtRecipx(n);
188 n <<= 8;
189 } else {
190 // here norm^2 is at least 0x7EC00000 (>>32 == 0.495117)
191 n = vsquare3(x, y, z);
192 n = gglSqrtRecipx(n);
193 }
194 vscale3(d, a, n);
195}
196
197// ----------------------------------------------------------------------------
198#if 0
199#pragma mark -
200#pragma mark lighting equations
201#endif
202
203static inline void light_picker(ogles_context_t* c)
204{
205 if (ggl_likely(!c->lighting.enable)) {
206 c->lighting.lightVertex = lightVertexNop;
207 return;
208 }
209 if (c->lighting.colorMaterial.enable) {
210 c->lighting.lightVertex = lightVertexMaterial;
211 } else {
212 c->lighting.lightVertex = lightVertex;
213 }
214}
215
216static inline void validate_light_mvi(ogles_context_t* c)
217{
218 uint32_t en = c->lighting.enabledLights;
Martin Storsjoe03eaa12009-08-11 18:01:14 +0200219 // Vector from object to viewer, in eye coordinates
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800220 while (en) {
221 const int i = 31 - gglClz(en);
222 en &= ~(1<<i);
223 light_t& l = c->lighting.lights[i];
Mathias Agopian04a3f572010-02-02 18:48:15 -0800224#if OBJECT_SPACE_LIGHTING
Mathias Agopian69ca17a2009-06-02 22:05:04 -0700225 c->transforms.mvui.point4(&c->transforms.mvui,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800226 &l.objPosition, &l.position);
Mathias Agopian04a3f572010-02-02 18:48:15 -0800227#else
228 l.objPosition = l.position;
229#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800230 vnorm3(l.normalizedObjPosition.v, l.objPosition.v);
231 }
Dan Stozac044ae52016-01-08 10:52:16 -0800232 const vec4_t eyeViewer = {{{ 0, 0, 0x10000, 0 }}};
Mathias Agopian04a3f572010-02-02 18:48:15 -0800233#if OBJECT_SPACE_LIGHTING
234 c->transforms.mvui.point3(&c->transforms.mvui,
235 &c->lighting.objViewer, &eyeViewer);
236 vnorm3(c->lighting.objViewer.v, c->lighting.objViewer.v);
237#else
238 c->lighting.objViewer = eyeViewer;
239#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800240}
241
242static inline void validate_light(ogles_context_t* c)
243{
244 // if colorMaterial is enabled, we get the color from the vertex
245 if (!c->lighting.colorMaterial.enable) {
246 material_t& material = c->lighting.front;
247 uint32_t en = c->lighting.enabledLights;
248 while (en) {
249 const int i = 31 - gglClz(en);
250 en &= ~(1<<i);
251 light_t& l = c->lighting.lights[i];
252 vmul3(l.implicitAmbient.v, material.ambient.v, l.ambient.v);
253 vmul3(l.implicitDiffuse.v, material.diffuse.v, l.diffuse.v);
254 vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v);
255
256 // this is just a flag to tell if we have a specular component
257 l.implicitSpecular.v[3] =
258 l.implicitSpecular.r |
259 l.implicitSpecular.g |
260 l.implicitSpecular.b;
261
262 l.rConstAttenuation = (l.attenuation[1] | l.attenuation[2])==0;
263 if (l.rConstAttenuation)
264 l.rConstAttenuation = gglRecipFast(l.attenuation[0]);
265 }
266 // emission and ambient for the whole scene
267 vmla3( c->lighting.implicitSceneEmissionAndAmbient.v,
268 c->lighting.lightModel.ambient.v,
269 material.ambient.v,
270 material.emission.v);
271 c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a;
272 }
273 validate_light_mvi(c);
274}
275
276void invalidate_lighting(ogles_context_t* c)
277{
278 // TODO: pick lightVertexValidate or lightVertexValidateMVI
279 // instead of systematically the heavier lightVertexValidate()
280 c->lighting.lightVertex = lightVertexValidate;
281}
282
283void ogles_invalidate_lighting_mvui(ogles_context_t* c)
284{
285 invalidate_lighting(c);
286}
287
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -0700288void lightVertexNop(ogles_context_t*, vertex_t* /*v*/)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800289{
290 // we should never end-up here
291}
292
293void lightVertexValidateMVI(ogles_context_t* c, vertex_t* v)
294{
295 validate_light_mvi(c);
296 light_picker(c);
297 c->lighting.lightVertex(c, v);
298}
299
300void lightVertexValidate(ogles_context_t* c, vertex_t* v)
301{
302 validate_light(c);
303 light_picker(c);
304 c->lighting.lightVertex(c, v);
305}
306
307void lightVertexMaterial(ogles_context_t* c, vertex_t* v)
308{
309 // fetch the material color
310 const GLvoid* cp = c->arrays.color.element(
311 v->index & vertex_cache_t::INDEX_MASK);
312 c->arrays.color.fetch(c, v->color.v, cp);
313
314 // acquire the color-material from the vertex
315 material_t& material = c->lighting.front;
316 material.ambient =
317 material.diffuse = v->color;
318 // implicit arguments need to be computed per/vertex
319 uint32_t en = c->lighting.enabledLights;
320 while (en) {
321 const int i = 31 - gglClz(en);
322 en &= ~(1<<i);
323 light_t& l = c->lighting.lights[i];
324 vmul3(l.implicitAmbient.v, material.ambient.v, l.ambient.v);
325 vmul3(l.implicitDiffuse.v, material.diffuse.v, l.diffuse.v);
326 vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v);
Mathias Agopian50aba6d2009-06-02 22:51:09 -0700327 // this is just a flag to tell if we have a specular component
328 l.implicitSpecular.v[3] =
329 l.implicitSpecular.r |
330 l.implicitSpecular.g |
331 l.implicitSpecular.b;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800332 }
333 // emission and ambient for the whole scene
334 vmla3( c->lighting.implicitSceneEmissionAndAmbient.v,
335 c->lighting.lightModel.ambient.v,
336 material.ambient.v,
337 material.emission.v);
338 c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a;
339
340 // now we can light our vertex as usual
341 lightVertex(c, v);
342}
343
344void lightVertex(ogles_context_t* c, vertex_t* v)
345{
346 // emission and ambient for the whole scene
347 vec4_t r = c->lighting.implicitSceneEmissionAndAmbient;
Mathias Agopian04a3f572010-02-02 18:48:15 -0800348 const vec4_t objViewer = c->lighting.objViewer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800349
350 uint32_t en = c->lighting.enabledLights;
351 if (ggl_likely(en)) {
352 // since we do the lighting in object-space, we don't need to
353 // transform each normal. However, we might still have to normalize
354 // it if GL_NORMALIZE is enabled.
355 vec4_t n;
356 c->arrays.normal.fetch(c, n.v,
357 c->arrays.normal.element(v->index & vertex_cache_t::INDEX_MASK));
Mathias Agopian69ca17a2009-06-02 22:05:04 -0700358
Mathias Agopian04a3f572010-02-02 18:48:15 -0800359#if !OBJECT_SPACE_LIGHTING
360 c->transforms.mvui.point3(&c->transforms.mvui, &n, &n);
361#endif
362
363 // TODO: right now we handle GL_RESCALE_NORMALS as if it were
Mathias Agopian69ca17a2009-06-02 22:05:04 -0700364 // GL_NORMALIZE. We could optimize this by scaling mvui
365 // appropriately instead.
366 if (c->transforms.rescaleNormals)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800367 vnorm3(n.v, n.v);
368
369 const material_t& material = c->lighting.front;
370 const int twoSide = c->lighting.lightModel.twoSide;
371
372 while (en) {
373 const int i = 31 - gglClz(en);
374 en &= ~(1<<i);
375 const light_t& l = c->lighting.lights[i];
376
377 vec4_t d, t;
378 GLfixed s;
379 GLfixed sqDist = 0x10000;
380
381 // compute vertex-to-light vector
382 if (ggl_unlikely(l.position.w)) {
Mathias Agopian69ca17a2009-06-02 22:05:04 -0700383 // lightPos/1.0 - vertex/vertex.w == lightPos*vertex.w - vertex
Martin Storsjod5b1cda2012-04-24 00:50:56 +0300384#if !OBJECT_SPACE_LIGHTING
385 vec4_t o;
386 const transform_t& mv = c->transforms.modelview.transform;
387 mv.point4(&mv, &o, &v->obj);
388 vss3(d.v, l.objPosition.v, o.w, o.v);
389#else
Mathias Agopian69ca17a2009-06-02 22:05:04 -0700390 vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v);
Martin Storsjod5b1cda2012-04-24 00:50:56 +0300391#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800392 sqDist = dot3(d.v, d.v);
393 vscale3(d.v, d.v, gglSqrtRecipx(sqDist));
394 } else {
395 // TODO: avoid copy here
396 d = l.normalizedObjPosition;
397 }
398
399 // ambient & diffuse
400 s = dot3(n.v, d.v);
401 s = (s<0) ? (twoSide?(-s):0) : s;
402 vsa3(t.v, l.implicitDiffuse.v, s, l.implicitAmbient.v);
Mathias Agopian04a3f572010-02-02 18:48:15 -0800403
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800404 // specular
405 if (ggl_unlikely(s && l.implicitSpecular.v[3])) {
406 vec4_t h;
Mathias Agopian04a3f572010-02-02 18:48:15 -0800407 h.x = d.x + objViewer.x;
408 h.y = d.y + objViewer.y;
409 h.z = d.z + objViewer.z;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800410 vnorm3(h.v, h.v);
411 s = dot3(n.v, h.v);
412 s = (s<0) ? (twoSide?(-s):0) : s;
413 if (s > 0) {
414 s = gglPowx(s, material.shininess);
415 vsa3(t.v, l.implicitSpecular.v, s, t.v);
416 }
417 }
418
419 // spot
420 if (ggl_unlikely(l.spotCutoff != gglIntToFixed(180))) {
421 GLfixed spotAtt = -dot3(l.normalizedSpotDir.v, d.v);
422 if (spotAtt >= l.spotCutoffCosine) {
423 vscale3(t.v, t.v, gglPowx(spotAtt, l.spotExp));
424 }
425 }
426
427 // attenuation
428 if (ggl_unlikely(l.position.w)) {
429 if (l.rConstAttenuation) {
430 s = l.rConstAttenuation;
431 } else {
432 s = gglMulAddx(sqDist, l.attenuation[2], l.attenuation[0]);
433 if (l.attenuation[1])
434 s = gglMulAddx(gglSqrtx(sqDist), l.attenuation[1], s);
435 s = gglRecipFast(s);
436 }
437 vscale3(t.v, t.v, s);
438 }
439
440 r.r += t.r;
441 r.g += t.g;
442 r.b += t.b;
443 }
444 }
445 v->color.r = gglClampx(r.r);
446 v->color.g = gglClampx(r.g);
447 v->color.b = gglClampx(r.b);
448 v->color.a = gglClampx(r.a);
449 v->flags |= vertex_t::LIT;
450}
451
452static void lightModelx(GLenum pname, GLfixed param, ogles_context_t* c)
453{
454 if (ggl_unlikely(pname != GL_LIGHT_MODEL_TWO_SIDE)) {
455 ogles_error(c, GL_INVALID_ENUM);
456 return;
457 }
458 c->lighting.lightModel.twoSide = param ? GL_TRUE : GL_FALSE;
459 invalidate_lighting(c);
460}
461
462static void lightx(GLenum i, GLenum pname, GLfixed param, ogles_context_t* c)
463{
464 if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) {
465 ogles_error(c, GL_INVALID_ENUM);
466 return;
467 }
468
469 light_t& light = c->lighting.lights[i-GL_LIGHT0];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800470 switch (pname) {
471 case GL_SPOT_EXPONENT:
472 if (GGLfixed(param) >= gglIntToFixed(128)) {
473 ogles_error(c, GL_INVALID_VALUE);
474 return;
475 }
476 light.spotExp = param;
477 break;
478 case GL_SPOT_CUTOFF:
479 if (param!=gglIntToFixed(180) && GGLfixed(param)>=gglIntToFixed(90)) {
480 ogles_error(c, GL_INVALID_VALUE);
481 return;
482 }
483 light.spotCutoff = param;
484 light.spotCutoffCosine =
485 gglFloatToFixed(cosinef((M_PI/(180.0f*65536.0f))*param));
486 break;
487 case GL_CONSTANT_ATTENUATION:
488 if (param < 0) {
489 ogles_error(c, GL_INVALID_VALUE);
490 return;
491 }
492 light.attenuation[0] = param;
493 break;
494 case GL_LINEAR_ATTENUATION:
495 if (param < 0) {
496 ogles_error(c, GL_INVALID_VALUE);
497 return;
498 }
499 light.attenuation[1] = param;
500 break;
501 case GL_QUADRATIC_ATTENUATION:
502 if (param < 0) {
503 ogles_error(c, GL_INVALID_VALUE);
504 return;
505 }
506 light.attenuation[2] = param;
507 break;
508 default:
509 ogles_error(c, GL_INVALID_ENUM);
510 return;
511 }
512 invalidate_lighting(c);
513}
514
515static void lightxv(GLenum i, GLenum pname, const GLfixed *params, ogles_context_t* c)
516{
517 if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) {
518 ogles_error(c, GL_INVALID_ENUM);
519 return;
520 }
521
522 GLfixed* what;
523 light_t& light = c->lighting.lights[i-GL_LIGHT0];
524 switch (pname) {
525 case GL_AMBIENT:
526 what = light.ambient.v;
527 break;
528 case GL_DIFFUSE:
529 what = light.diffuse.v;
530 break;
531 case GL_SPECULAR:
532 what = light.specular.v;
533 break;
534 case GL_POSITION: {
535 ogles_validate_transform(c, transform_state_t::MODELVIEW);
536 transform_t& mv = c->transforms.modelview.transform;
Mathias Agopian04a3f572010-02-02 18:48:15 -0800537 mv.point4(&mv, &light.position, reinterpret_cast<vec4_t const*>(params));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800538 invalidate_lighting(c);
539 return;
540 }
541 case GL_SPOT_DIRECTION: {
Mathias Agopian04a3f572010-02-02 18:48:15 -0800542#if OBJECT_SPACE_LIGHTING
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800543 ogles_validate_transform(c, transform_state_t::MVUI);
544 transform_t& mvui = c->transforms.mvui;
Mathias Agopian04a3f572010-02-02 18:48:15 -0800545 mvui.point3(&mvui, &light.spotDir, reinterpret_cast<vec4_t const*>(params));
546#else
547 light.spotDir = *reinterpret_cast<vec4_t const*>(params);
548#endif
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800549 vnorm3(light.normalizedSpotDir.v, light.spotDir.v);
550 invalidate_lighting(c);
551 return;
552 }
553 default:
554 lightx(i, pname, params[0], c);
555 return;
556 }
557 what[0] = params[0];
558 what[1] = params[1];
559 what[2] = params[2];
560 what[3] = params[3];
561 invalidate_lighting(c);
562}
563
564static void materialx(GLenum face, GLenum pname, GLfixed param, ogles_context_t* c)
565{
566 if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
567 ogles_error(c, GL_INVALID_ENUM);
568 return;
569 }
570 if (ggl_unlikely(pname != GL_SHININESS)) {
571 ogles_error(c, GL_INVALID_ENUM);
572 return;
573 }
574 c->lighting.front.shininess = param;
575 invalidate_lighting(c);
576}
577
578static void fogx(GLenum pname, GLfixed param, ogles_context_t* c)
579{
580 switch (pname) {
581 case GL_FOG_DENSITY:
582 if (param >= 0) {
583 c->fog.density = param;
584 break;
585 }
586 ogles_error(c, GL_INVALID_VALUE);
587 break;
588 case GL_FOG_START:
589 c->fog.start = param;
590 c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start);
591 break;
592 case GL_FOG_END:
593 c->fog.end = param;
594 c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start);
595 break;
596 case GL_FOG_MODE:
597 switch (param) {
598 case GL_LINEAR:
599 c->fog.mode = param;
600 c->fog.fog = fog_linear;
601 break;
602 case GL_EXP:
603 c->fog.mode = param;
604 c->fog.fog = fog_exp;
605 break;
606 case GL_EXP2:
607 c->fog.mode = param;
608 c->fog.fog = fog_exp2;
609 break;
610 default:
611 ogles_error(c, GL_INVALID_ENUM);
612 break;
613 }
614 break;
615 default:
616 ogles_error(c, GL_INVALID_ENUM);
617 break;
618 }
619}
620
621// ----------------------------------------------------------------------------
622}; // namespace android
623// ----------------------------------------------------------------------------
624
625using namespace android;
626
627#if 0
628#pragma mark -
629#pragma mark lighting APIs
630#endif
631
632void glShadeModel(GLenum mode)
633{
634 ogles_context_t* c = ogles_context_t::get();
635 if (ggl_unlikely(mode != GL_SMOOTH && mode != GL_FLAT)) {
636 ogles_error(c, GL_INVALID_ENUM);
637 return;
638 }
639 c->lighting.shadeModel = mode;
640}
641
642void glLightModelf(GLenum pname, GLfloat param)
643{
644 ogles_context_t* c = ogles_context_t::get();
645 lightModelx(pname, gglFloatToFixed(param), c);
646}
647
648void glLightModelx(GLenum pname, GLfixed param)
649{
650 ogles_context_t* c = ogles_context_t::get();
651 lightModelx(pname, param, c);
652}
653
654void glLightModelfv(GLenum pname, const GLfloat *params)
655{
656 ogles_context_t* c = ogles_context_t::get();
657 if (pname == GL_LIGHT_MODEL_TWO_SIDE) {
658 lightModelx(pname, gglFloatToFixed(params[0]), c);
659 return;
660 }
661
662 if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) {
663 ogles_error(c, GL_INVALID_ENUM);
664 return;
665 }
666
667 c->lighting.lightModel.ambient.r = gglFloatToFixed(params[0]);
668 c->lighting.lightModel.ambient.g = gglFloatToFixed(params[1]);
669 c->lighting.lightModel.ambient.b = gglFloatToFixed(params[2]);
670 c->lighting.lightModel.ambient.a = gglFloatToFixed(params[3]);
671 invalidate_lighting(c);
672}
673
674void glLightModelxv(GLenum pname, const GLfixed *params)
675{
676 ogles_context_t* c = ogles_context_t::get();
677 if (pname == GL_LIGHT_MODEL_TWO_SIDE) {
678 lightModelx(pname, params[0], c);
679 return;
680 }
681
682 if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) {
683 ogles_error(c, GL_INVALID_ENUM);
684 return;
685 }
686
687 c->lighting.lightModel.ambient.r = params[0];
688 c->lighting.lightModel.ambient.g = params[1];
689 c->lighting.lightModel.ambient.b = params[2];
690 c->lighting.lightModel.ambient.a = params[3];
691 invalidate_lighting(c);
692}
693
694// ----------------------------------------------------------------------------
695#if 0
696#pragma mark -
697#endif
698
699void glLightf(GLenum i, GLenum pname, GLfloat param)
700{
701 ogles_context_t* c = ogles_context_t::get();
702 lightx(i, pname, gglFloatToFixed(param), c);
703}
704
705void glLightx(GLenum i, GLenum pname, GLfixed param)
706{
707 ogles_context_t* c = ogles_context_t::get();
708 lightx(i, pname, param, c);
709}
710
711void glLightfv(GLenum i, GLenum pname, const GLfloat *params)
712{
713 ogles_context_t* c = ogles_context_t::get();
714 switch (pname) {
715 case GL_SPOT_EXPONENT:
716 case GL_SPOT_CUTOFF:
717 case GL_CONSTANT_ATTENUATION:
718 case GL_LINEAR_ATTENUATION:
719 case GL_QUADRATIC_ATTENUATION:
720 lightx(i, pname, gglFloatToFixed(params[0]), c);
721 return;
722 }
723
724 GLfixed paramsx[4];
725 paramsx[0] = gglFloatToFixed(params[0]);
726 paramsx[1] = gglFloatToFixed(params[1]);
727 paramsx[2] = gglFloatToFixed(params[2]);
728 if (pname != GL_SPOT_DIRECTION)
729 paramsx[3] = gglFloatToFixed(params[3]);
730
731 lightxv(i, pname, paramsx, c);
732}
733
734void glLightxv(GLenum i, GLenum pname, const GLfixed *params)
735{
736 ogles_context_t* c = ogles_context_t::get();
737 lightxv(i, pname, params, c);
738}
739
740// ----------------------------------------------------------------------------
741#if 0
742#pragma mark -
743#endif
744
745void glMaterialf(GLenum face, GLenum pname, GLfloat param)
746{
747 ogles_context_t* c = ogles_context_t::get();
748 materialx(face, pname, gglFloatToFixed(param), c);
749}
750
751void glMaterialx(GLenum face, GLenum pname, GLfixed param)
752{
753 ogles_context_t* c = ogles_context_t::get();
754 materialx(face, pname, param, c);
755}
756
757void glMaterialfv(
758 GLenum face, GLenum pname, const GLfloat *params)
759{
760 ogles_context_t* c = ogles_context_t::get();
761 if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
762 ogles_error(c, GL_INVALID_ENUM);
763 return;
764 }
765 GLfixed* what=0;
766 GLfixed* other=0;
767 switch (pname) {
768 case GL_AMBIENT: what = c->lighting.front.ambient.v; break;
769 case GL_DIFFUSE: what = c->lighting.front.diffuse.v; break;
770 case GL_SPECULAR: what = c->lighting.front.specular.v; break;
771 case GL_EMISSION: what = c->lighting.front.emission.v; break;
772 case GL_AMBIENT_AND_DIFFUSE:
Mathias Agopian04a3f572010-02-02 18:48:15 -0800773 what = c->lighting.front.ambient.v;
774 other = c->lighting.front.diffuse.v;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800775 break;
776 case GL_SHININESS:
777 c->lighting.front.shininess = gglFloatToFixed(params[0]);
778 invalidate_lighting(c);
779 return;
780 default:
781 ogles_error(c, GL_INVALID_ENUM);
782 return;
783 }
784 what[0] = gglFloatToFixed(params[0]);
785 what[1] = gglFloatToFixed(params[1]);
786 what[2] = gglFloatToFixed(params[2]);
787 what[3] = gglFloatToFixed(params[3]);
788 if (other) {
789 other[0] = what[0];
790 other[1] = what[1];
791 other[2] = what[2];
792 other[3] = what[3];
793 }
794 invalidate_lighting(c);
795}
796
797void glMaterialxv(
798 GLenum face, GLenum pname, const GLfixed *params)
799{
800 ogles_context_t* c = ogles_context_t::get();
801 if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
802 ogles_error(c, GL_INVALID_ENUM);
803 return;
804 }
805 GLfixed* what=0;
806 GLfixed* other=0;
807 switch (pname) {
808 case GL_AMBIENT: what = c->lighting.front.ambient.v; break;
809 case GL_DIFFUSE: what = c->lighting.front.diffuse.v; break;
810 case GL_SPECULAR: what = c->lighting.front.specular.v; break;
811 case GL_EMISSION: what = c->lighting.front.emission.v; break;
812 case GL_AMBIENT_AND_DIFFUSE:
Mathias Agopian04a3f572010-02-02 18:48:15 -0800813 what = c->lighting.front.ambient.v;
814 other = c->lighting.front.diffuse.v;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800815 break;
816 case GL_SHININESS:
817 c->lighting.front.shininess = gglFloatToFixed(params[0]);
818 invalidate_lighting(c);
819 return;
820 default:
821 ogles_error(c, GL_INVALID_ENUM);
822 return;
823 }
824 what[0] = params[0];
825 what[1] = params[1];
826 what[2] = params[2];
827 what[3] = params[3];
828 if (other) {
829 other[0] = what[0];
830 other[1] = what[1];
831 other[2] = what[2];
832 other[3] = what[3];
833 }
834 invalidate_lighting(c);
835}
836
837// ----------------------------------------------------------------------------
838#if 0
839#pragma mark -
840#pragma mark fog
841#endif
842
843void glFogf(GLenum pname, GLfloat param) {
844 ogles_context_t* c = ogles_context_t::get();
845 GLfixed paramx = (GLfixed)param;
846 if (pname != GL_FOG_MODE)
847 paramx = gglFloatToFixed(param);
848 fogx(pname, paramx, c);
849}
850
851void glFogx(GLenum pname, GLfixed param) {
852 ogles_context_t* c = ogles_context_t::get();
853 fogx(pname, param, c);
854}
855
856void glFogfv(GLenum pname, const GLfloat *params)
857{
858 ogles_context_t* c = ogles_context_t::get();
859 if (pname != GL_FOG_COLOR) {
860 GLfixed paramx = (GLfixed)params[0];
861 if (pname != GL_FOG_MODE)
862 paramx = gglFloatToFixed(params[0]);
863 fogx(pname, paramx, c);
864 return;
865 }
866 GLfixed paramsx[4];
867 paramsx[0] = gglFloatToFixed(params[0]);
868 paramsx[1] = gglFloatToFixed(params[1]);
869 paramsx[2] = gglFloatToFixed(params[2]);
870 paramsx[3] = gglFloatToFixed(params[3]);
871 c->rasterizer.procs.fogColor3xv(c, paramsx);
872}
873
874void glFogxv(GLenum pname, const GLfixed *params)
875{
876 ogles_context_t* c = ogles_context_t::get();
877 if (pname != GL_FOG_COLOR) {
878 fogx(pname, params[0], c);
879 return;
880 }
881 c->rasterizer.procs.fogColor3xv(c, params);
882}