blob: f211bcab3221a1834ff69ae23b926b6b39b25fc7 [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
108void ogles_uninit_light(ogles_context_t* c)
109{
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
220 const vec4_t eyeViewer = { 0, 0, 0x1000, 0 };
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800221 while (en) {
222 const int i = 31 - gglClz(en);
223 en &= ~(1<<i);
224 light_t& l = c->lighting.lights[i];
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);
227 vnorm3(l.normalizedObjPosition.v, l.objPosition.v);
Martin Storsjoe03eaa12009-08-11 18:01:14 +0200228 c->transforms.mvui.point4(&c->transforms.mvui,
229 &l.objViewer, &eyeViewer);
230 vnorm3(l.objViewer.v, l.objViewer.v);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800231 }
232}
233
234static inline void validate_light(ogles_context_t* c)
235{
236 // if colorMaterial is enabled, we get the color from the vertex
237 if (!c->lighting.colorMaterial.enable) {
238 material_t& material = c->lighting.front;
239 uint32_t en = c->lighting.enabledLights;
240 while (en) {
241 const int i = 31 - gglClz(en);
242 en &= ~(1<<i);
243 light_t& l = c->lighting.lights[i];
244 vmul3(l.implicitAmbient.v, material.ambient.v, l.ambient.v);
245 vmul3(l.implicitDiffuse.v, material.diffuse.v, l.diffuse.v);
246 vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v);
247
248 // this is just a flag to tell if we have a specular component
249 l.implicitSpecular.v[3] =
250 l.implicitSpecular.r |
251 l.implicitSpecular.g |
252 l.implicitSpecular.b;
253
254 l.rConstAttenuation = (l.attenuation[1] | l.attenuation[2])==0;
255 if (l.rConstAttenuation)
256 l.rConstAttenuation = gglRecipFast(l.attenuation[0]);
257 }
258 // emission and ambient for the whole scene
259 vmla3( c->lighting.implicitSceneEmissionAndAmbient.v,
260 c->lighting.lightModel.ambient.v,
261 material.ambient.v,
262 material.emission.v);
263 c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a;
264 }
265 validate_light_mvi(c);
266}
267
268void invalidate_lighting(ogles_context_t* c)
269{
270 // TODO: pick lightVertexValidate or lightVertexValidateMVI
271 // instead of systematically the heavier lightVertexValidate()
272 c->lighting.lightVertex = lightVertexValidate;
273}
274
275void ogles_invalidate_lighting_mvui(ogles_context_t* c)
276{
277 invalidate_lighting(c);
278}
279
280void lightVertexNop(ogles_context_t*, vertex_t* v)
281{
282 // we should never end-up here
283}
284
285void lightVertexValidateMVI(ogles_context_t* c, vertex_t* v)
286{
287 validate_light_mvi(c);
288 light_picker(c);
289 c->lighting.lightVertex(c, v);
290}
291
292void lightVertexValidate(ogles_context_t* c, vertex_t* v)
293{
294 validate_light(c);
295 light_picker(c);
296 c->lighting.lightVertex(c, v);
297}
298
299void lightVertexMaterial(ogles_context_t* c, vertex_t* v)
300{
301 // fetch the material color
302 const GLvoid* cp = c->arrays.color.element(
303 v->index & vertex_cache_t::INDEX_MASK);
304 c->arrays.color.fetch(c, v->color.v, cp);
305
306 // acquire the color-material from the vertex
307 material_t& material = c->lighting.front;
308 material.ambient =
309 material.diffuse = v->color;
310 // implicit arguments need to be computed per/vertex
311 uint32_t en = c->lighting.enabledLights;
312 while (en) {
313 const int i = 31 - gglClz(en);
314 en &= ~(1<<i);
315 light_t& l = c->lighting.lights[i];
316 vmul3(l.implicitAmbient.v, material.ambient.v, l.ambient.v);
317 vmul3(l.implicitDiffuse.v, material.diffuse.v, l.diffuse.v);
318 vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v);
Mathias Agopian50aba6d2009-06-02 22:51:09 -0700319 // this is just a flag to tell if we have a specular component
320 l.implicitSpecular.v[3] =
321 l.implicitSpecular.r |
322 l.implicitSpecular.g |
323 l.implicitSpecular.b;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800324 }
325 // emission and ambient for the whole scene
326 vmla3( c->lighting.implicitSceneEmissionAndAmbient.v,
327 c->lighting.lightModel.ambient.v,
328 material.ambient.v,
329 material.emission.v);
330 c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a;
331
332 // now we can light our vertex as usual
333 lightVertex(c, v);
334}
335
336void lightVertex(ogles_context_t* c, vertex_t* v)
337{
338 // emission and ambient for the whole scene
339 vec4_t r = c->lighting.implicitSceneEmissionAndAmbient;
340
341 uint32_t en = c->lighting.enabledLights;
342 if (ggl_likely(en)) {
343 // since we do the lighting in object-space, we don't need to
344 // transform each normal. However, we might still have to normalize
345 // it if GL_NORMALIZE is enabled.
346 vec4_t n;
347 c->arrays.normal.fetch(c, n.v,
348 c->arrays.normal.element(v->index & vertex_cache_t::INDEX_MASK));
Mathias Agopian69ca17a2009-06-02 22:05:04 -0700349
350 // TODO: right now we handle GL_RESCALE_NORMALS as if ti were
351 // GL_NORMALIZE. We could optimize this by scaling mvui
352 // appropriately instead.
353 if (c->transforms.rescaleNormals)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800354 vnorm3(n.v, n.v);
355
356 const material_t& material = c->lighting.front;
357 const int twoSide = c->lighting.lightModel.twoSide;
358
359 while (en) {
360 const int i = 31 - gglClz(en);
361 en &= ~(1<<i);
362 const light_t& l = c->lighting.lights[i];
363
364 vec4_t d, t;
365 GLfixed s;
366 GLfixed sqDist = 0x10000;
367
368 // compute vertex-to-light vector
369 if (ggl_unlikely(l.position.w)) {
Mathias Agopian69ca17a2009-06-02 22:05:04 -0700370 // lightPos/1.0 - vertex/vertex.w == lightPos*vertex.w - vertex
371 vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800372 sqDist = dot3(d.v, d.v);
373 vscale3(d.v, d.v, gglSqrtRecipx(sqDist));
374 } else {
375 // TODO: avoid copy here
376 d = l.normalizedObjPosition;
377 }
378
379 // ambient & diffuse
380 s = dot3(n.v, d.v);
381 s = (s<0) ? (twoSide?(-s):0) : s;
382 vsa3(t.v, l.implicitDiffuse.v, s, l.implicitAmbient.v);
383
384 // specular
385 if (ggl_unlikely(s && l.implicitSpecular.v[3])) {
386 vec4_t h;
Martin Storsjoe03eaa12009-08-11 18:01:14 +0200387 h.x = d.x + l.objViewer.x;
388 h.y = d.y + l.objViewer.y;
389 h.z = d.z + l.objViewer.z;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800390 vnorm3(h.v, h.v);
391 s = dot3(n.v, h.v);
392 s = (s<0) ? (twoSide?(-s):0) : s;
393 if (s > 0) {
394 s = gglPowx(s, material.shininess);
395 vsa3(t.v, l.implicitSpecular.v, s, t.v);
396 }
397 }
398
399 // spot
400 if (ggl_unlikely(l.spotCutoff != gglIntToFixed(180))) {
401 GLfixed spotAtt = -dot3(l.normalizedSpotDir.v, d.v);
402 if (spotAtt >= l.spotCutoffCosine) {
403 vscale3(t.v, t.v, gglPowx(spotAtt, l.spotExp));
404 }
405 }
406
407 // attenuation
408 if (ggl_unlikely(l.position.w)) {
409 if (l.rConstAttenuation) {
410 s = l.rConstAttenuation;
411 } else {
412 s = gglMulAddx(sqDist, l.attenuation[2], l.attenuation[0]);
413 if (l.attenuation[1])
414 s = gglMulAddx(gglSqrtx(sqDist), l.attenuation[1], s);
415 s = gglRecipFast(s);
416 }
417 vscale3(t.v, t.v, s);
418 }
419
420 r.r += t.r;
421 r.g += t.g;
422 r.b += t.b;
423 }
424 }
425 v->color.r = gglClampx(r.r);
426 v->color.g = gglClampx(r.g);
427 v->color.b = gglClampx(r.b);
428 v->color.a = gglClampx(r.a);
429 v->flags |= vertex_t::LIT;
430}
431
432static void lightModelx(GLenum pname, GLfixed param, ogles_context_t* c)
433{
434 if (ggl_unlikely(pname != GL_LIGHT_MODEL_TWO_SIDE)) {
435 ogles_error(c, GL_INVALID_ENUM);
436 return;
437 }
438 c->lighting.lightModel.twoSide = param ? GL_TRUE : GL_FALSE;
439 invalidate_lighting(c);
440}
441
442static void lightx(GLenum i, GLenum pname, GLfixed param, ogles_context_t* c)
443{
444 if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) {
445 ogles_error(c, GL_INVALID_ENUM);
446 return;
447 }
448
449 light_t& light = c->lighting.lights[i-GL_LIGHT0];
450 const GLfixed kDegToRad = GLfixed((M_PI * gglIntToFixed(1)) / 180.0f);
451 switch (pname) {
452 case GL_SPOT_EXPONENT:
453 if (GGLfixed(param) >= gglIntToFixed(128)) {
454 ogles_error(c, GL_INVALID_VALUE);
455 return;
456 }
457 light.spotExp = param;
458 break;
459 case GL_SPOT_CUTOFF:
460 if (param!=gglIntToFixed(180) && GGLfixed(param)>=gglIntToFixed(90)) {
461 ogles_error(c, GL_INVALID_VALUE);
462 return;
463 }
464 light.spotCutoff = param;
465 light.spotCutoffCosine =
466 gglFloatToFixed(cosinef((M_PI/(180.0f*65536.0f))*param));
467 break;
468 case GL_CONSTANT_ATTENUATION:
469 if (param < 0) {
470 ogles_error(c, GL_INVALID_VALUE);
471 return;
472 }
473 light.attenuation[0] = param;
474 break;
475 case GL_LINEAR_ATTENUATION:
476 if (param < 0) {
477 ogles_error(c, GL_INVALID_VALUE);
478 return;
479 }
480 light.attenuation[1] = param;
481 break;
482 case GL_QUADRATIC_ATTENUATION:
483 if (param < 0) {
484 ogles_error(c, GL_INVALID_VALUE);
485 return;
486 }
487 light.attenuation[2] = param;
488 break;
489 default:
490 ogles_error(c, GL_INVALID_ENUM);
491 return;
492 }
493 invalidate_lighting(c);
494}
495
496static void lightxv(GLenum i, GLenum pname, const GLfixed *params, ogles_context_t* c)
497{
498 if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) {
499 ogles_error(c, GL_INVALID_ENUM);
500 return;
501 }
502
503 GLfixed* what;
504 light_t& light = c->lighting.lights[i-GL_LIGHT0];
505 switch (pname) {
506 case GL_AMBIENT:
507 what = light.ambient.v;
508 break;
509 case GL_DIFFUSE:
510 what = light.diffuse.v;
511 break;
512 case GL_SPECULAR:
513 what = light.specular.v;
514 break;
515 case GL_POSITION: {
516 ogles_validate_transform(c, transform_state_t::MODELVIEW);
517 transform_t& mv = c->transforms.modelview.transform;
518 memcpy(light.position.v, params, sizeof(light.position.v));
519 mv.point4(&mv, &light.position, &light.position);
520 invalidate_lighting(c);
521 return;
522 }
523 case GL_SPOT_DIRECTION: {
524 ogles_validate_transform(c, transform_state_t::MVUI);
525 transform_t& mvui = c->transforms.mvui;
526 mvui.point3(&mvui, &light.spotDir, (vec4_t*)params);
527 vnorm3(light.normalizedSpotDir.v, light.spotDir.v);
528 invalidate_lighting(c);
529 return;
530 }
531 default:
532 lightx(i, pname, params[0], c);
533 return;
534 }
535 what[0] = params[0];
536 what[1] = params[1];
537 what[2] = params[2];
538 what[3] = params[3];
539 invalidate_lighting(c);
540}
541
542static void materialx(GLenum face, GLenum pname, GLfixed param, ogles_context_t* c)
543{
544 if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
545 ogles_error(c, GL_INVALID_ENUM);
546 return;
547 }
548 if (ggl_unlikely(pname != GL_SHININESS)) {
549 ogles_error(c, GL_INVALID_ENUM);
550 return;
551 }
552 c->lighting.front.shininess = param;
553 invalidate_lighting(c);
554}
555
556static void fogx(GLenum pname, GLfixed param, ogles_context_t* c)
557{
558 switch (pname) {
559 case GL_FOG_DENSITY:
560 if (param >= 0) {
561 c->fog.density = param;
562 break;
563 }
564 ogles_error(c, GL_INVALID_VALUE);
565 break;
566 case GL_FOG_START:
567 c->fog.start = param;
568 c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start);
569 break;
570 case GL_FOG_END:
571 c->fog.end = param;
572 c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start);
573 break;
574 case GL_FOG_MODE:
575 switch (param) {
576 case GL_LINEAR:
577 c->fog.mode = param;
578 c->fog.fog = fog_linear;
579 break;
580 case GL_EXP:
581 c->fog.mode = param;
582 c->fog.fog = fog_exp;
583 break;
584 case GL_EXP2:
585 c->fog.mode = param;
586 c->fog.fog = fog_exp2;
587 break;
588 default:
589 ogles_error(c, GL_INVALID_ENUM);
590 break;
591 }
592 break;
593 default:
594 ogles_error(c, GL_INVALID_ENUM);
595 break;
596 }
597}
598
599// ----------------------------------------------------------------------------
600}; // namespace android
601// ----------------------------------------------------------------------------
602
603using namespace android;
604
605#if 0
606#pragma mark -
607#pragma mark lighting APIs
608#endif
609
610void glShadeModel(GLenum mode)
611{
612 ogles_context_t* c = ogles_context_t::get();
613 if (ggl_unlikely(mode != GL_SMOOTH && mode != GL_FLAT)) {
614 ogles_error(c, GL_INVALID_ENUM);
615 return;
616 }
617 c->lighting.shadeModel = mode;
618}
619
620void glLightModelf(GLenum pname, GLfloat param)
621{
622 ogles_context_t* c = ogles_context_t::get();
623 lightModelx(pname, gglFloatToFixed(param), c);
624}
625
626void glLightModelx(GLenum pname, GLfixed param)
627{
628 ogles_context_t* c = ogles_context_t::get();
629 lightModelx(pname, param, c);
630}
631
632void glLightModelfv(GLenum pname, const GLfloat *params)
633{
634 ogles_context_t* c = ogles_context_t::get();
635 if (pname == GL_LIGHT_MODEL_TWO_SIDE) {
636 lightModelx(pname, gglFloatToFixed(params[0]), c);
637 return;
638 }
639
640 if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) {
641 ogles_error(c, GL_INVALID_ENUM);
642 return;
643 }
644
645 c->lighting.lightModel.ambient.r = gglFloatToFixed(params[0]);
646 c->lighting.lightModel.ambient.g = gglFloatToFixed(params[1]);
647 c->lighting.lightModel.ambient.b = gglFloatToFixed(params[2]);
648 c->lighting.lightModel.ambient.a = gglFloatToFixed(params[3]);
649 invalidate_lighting(c);
650}
651
652void glLightModelxv(GLenum pname, const GLfixed *params)
653{
654 ogles_context_t* c = ogles_context_t::get();
655 if (pname == GL_LIGHT_MODEL_TWO_SIDE) {
656 lightModelx(pname, params[0], c);
657 return;
658 }
659
660 if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) {
661 ogles_error(c, GL_INVALID_ENUM);
662 return;
663 }
664
665 c->lighting.lightModel.ambient.r = params[0];
666 c->lighting.lightModel.ambient.g = params[1];
667 c->lighting.lightModel.ambient.b = params[2];
668 c->lighting.lightModel.ambient.a = params[3];
669 invalidate_lighting(c);
670}
671
672// ----------------------------------------------------------------------------
673#if 0
674#pragma mark -
675#endif
676
677void glLightf(GLenum i, GLenum pname, GLfloat param)
678{
679 ogles_context_t* c = ogles_context_t::get();
680 lightx(i, pname, gglFloatToFixed(param), c);
681}
682
683void glLightx(GLenum i, GLenum pname, GLfixed param)
684{
685 ogles_context_t* c = ogles_context_t::get();
686 lightx(i, pname, param, c);
687}
688
689void glLightfv(GLenum i, GLenum pname, const GLfloat *params)
690{
691 ogles_context_t* c = ogles_context_t::get();
692 switch (pname) {
693 case GL_SPOT_EXPONENT:
694 case GL_SPOT_CUTOFF:
695 case GL_CONSTANT_ATTENUATION:
696 case GL_LINEAR_ATTENUATION:
697 case GL_QUADRATIC_ATTENUATION:
698 lightx(i, pname, gglFloatToFixed(params[0]), c);
699 return;
700 }
701
702 GLfixed paramsx[4];
703 paramsx[0] = gglFloatToFixed(params[0]);
704 paramsx[1] = gglFloatToFixed(params[1]);
705 paramsx[2] = gglFloatToFixed(params[2]);
706 if (pname != GL_SPOT_DIRECTION)
707 paramsx[3] = gglFloatToFixed(params[3]);
708
709 lightxv(i, pname, paramsx, c);
710}
711
712void glLightxv(GLenum i, GLenum pname, const GLfixed *params)
713{
714 ogles_context_t* c = ogles_context_t::get();
715 lightxv(i, pname, params, c);
716}
717
718// ----------------------------------------------------------------------------
719#if 0
720#pragma mark -
721#endif
722
723void glMaterialf(GLenum face, GLenum pname, GLfloat param)
724{
725 ogles_context_t* c = ogles_context_t::get();
726 materialx(face, pname, gglFloatToFixed(param), c);
727}
728
729void glMaterialx(GLenum face, GLenum pname, GLfixed param)
730{
731 ogles_context_t* c = ogles_context_t::get();
732 materialx(face, pname, param, c);
733}
734
735void glMaterialfv(
736 GLenum face, GLenum pname, const GLfloat *params)
737{
738 ogles_context_t* c = ogles_context_t::get();
739 if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
740 ogles_error(c, GL_INVALID_ENUM);
741 return;
742 }
743 GLfixed* what=0;
744 GLfixed* other=0;
745 switch (pname) {
746 case GL_AMBIENT: what = c->lighting.front.ambient.v; break;
747 case GL_DIFFUSE: what = c->lighting.front.diffuse.v; break;
748 case GL_SPECULAR: what = c->lighting.front.specular.v; break;
749 case GL_EMISSION: what = c->lighting.front.emission.v; break;
750 case GL_AMBIENT_AND_DIFFUSE:
751 what = c->lighting.front.ambient.v; break;
752 other = c->lighting.front.diffuse.v; break;
753 break;
754 case GL_SHININESS:
755 c->lighting.front.shininess = gglFloatToFixed(params[0]);
756 invalidate_lighting(c);
757 return;
758 default:
759 ogles_error(c, GL_INVALID_ENUM);
760 return;
761 }
762 what[0] = gglFloatToFixed(params[0]);
763 what[1] = gglFloatToFixed(params[1]);
764 what[2] = gglFloatToFixed(params[2]);
765 what[3] = gglFloatToFixed(params[3]);
766 if (other) {
767 other[0] = what[0];
768 other[1] = what[1];
769 other[2] = what[2];
770 other[3] = what[3];
771 }
772 invalidate_lighting(c);
773}
774
775void glMaterialxv(
776 GLenum face, GLenum pname, const GLfixed *params)
777{
778 ogles_context_t* c = ogles_context_t::get();
779 if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
780 ogles_error(c, GL_INVALID_ENUM);
781 return;
782 }
783 GLfixed* what=0;
784 GLfixed* other=0;
785 switch (pname) {
786 case GL_AMBIENT: what = c->lighting.front.ambient.v; break;
787 case GL_DIFFUSE: what = c->lighting.front.diffuse.v; break;
788 case GL_SPECULAR: what = c->lighting.front.specular.v; break;
789 case GL_EMISSION: what = c->lighting.front.emission.v; break;
790 case GL_AMBIENT_AND_DIFFUSE:
791 what = c->lighting.front.ambient.v; break;
792 other= c->lighting.front.diffuse.v; break;
793 break;
794 case GL_SHININESS:
795 c->lighting.front.shininess = gglFloatToFixed(params[0]);
796 invalidate_lighting(c);
797 return;
798 default:
799 ogles_error(c, GL_INVALID_ENUM);
800 return;
801 }
802 what[0] = params[0];
803 what[1] = params[1];
804 what[2] = params[2];
805 what[3] = params[3];
806 if (other) {
807 other[0] = what[0];
808 other[1] = what[1];
809 other[2] = what[2];
810 other[3] = what[3];
811 }
812 invalidate_lighting(c);
813}
814
815// ----------------------------------------------------------------------------
816#if 0
817#pragma mark -
818#pragma mark fog
819#endif
820
821void glFogf(GLenum pname, GLfloat param) {
822 ogles_context_t* c = ogles_context_t::get();
823 GLfixed paramx = (GLfixed)param;
824 if (pname != GL_FOG_MODE)
825 paramx = gglFloatToFixed(param);
826 fogx(pname, paramx, c);
827}
828
829void glFogx(GLenum pname, GLfixed param) {
830 ogles_context_t* c = ogles_context_t::get();
831 fogx(pname, param, c);
832}
833
834void glFogfv(GLenum pname, const GLfloat *params)
835{
836 ogles_context_t* c = ogles_context_t::get();
837 if (pname != GL_FOG_COLOR) {
838 GLfixed paramx = (GLfixed)params[0];
839 if (pname != GL_FOG_MODE)
840 paramx = gglFloatToFixed(params[0]);
841 fogx(pname, paramx, c);
842 return;
843 }
844 GLfixed paramsx[4];
845 paramsx[0] = gglFloatToFixed(params[0]);
846 paramsx[1] = gglFloatToFixed(params[1]);
847 paramsx[2] = gglFloatToFixed(params[2]);
848 paramsx[3] = gglFloatToFixed(params[3]);
849 c->rasterizer.procs.fogColor3xv(c, paramsx);
850}
851
852void glFogxv(GLenum pname, const GLfixed *params)
853{
854 ogles_context_t* c = ogles_context_t::get();
855 if (pname != GL_FOG_COLOR) {
856 fogx(pname, params[0], c);
857 return;
858 }
859 c->rasterizer.procs.fogColor3xv(c, params);
860}