DEADSOFTWARE

Workaround Stupid GLES blending bug
[nanogl.git] / nanoWrap.cpp
1 /*
2 Copyright (C) 2007-2009 Olli Hinkka
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20 /*
21 #include <e32def.h>
22 #include <e32std.h>
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "gl.h"
30 #include "glesinterface.h"
31 #include "nanogl.h"
32
33 #define GL_TEXTURE0_ARB 0x84C0
34 #define GL_TEXTURE1_ARB 0x84C1
35
36 struct nanoState
37 {
38 GLboolean alpha_test;
39 GLboolean blend;
40 GLboolean clip_planei;
41 GLboolean color_logic_op;
42 GLboolean color_material;
43 GLboolean cull_face;
44 GLboolean depth_test;
45 GLboolean dither;
46 GLboolean fog;
47 GLboolean lighti;
48 GLboolean lighting;
49 GLboolean line_smooth;
50 GLboolean matrix_palette_oes;
51 GLboolean multisample;
52 GLboolean normalize;
53 GLboolean point_smooth;
54 GLboolean point_sprite_oes;
55 GLboolean polygon_offset_fill;
56 GLboolean rescale_normal;
57 GLboolean sample_alpha_to_coverage;
58 GLboolean sample_alpha_to_one;
59 GLboolean sample_coverage;
60 GLboolean scissor_test;
61 GLboolean stencil_test;
62 GLboolean depthmask;
63 GLboolean stupidglesbug;
64 GLclampf depth_range_near;
65 GLclampf depth_range_far;
66 GLenum depth_func;
67 GLenum cullface;
68 GLenum shademodel;
69 GLenum sfactor;
70 GLenum dfactor;
71 GLenum matrixmode;
72 };
73
74 static struct nanoState nanoglState;
75
76 static struct nanoState nanoglInitState =
77 {
78 GL_FALSE,
79 GL_FALSE,
80 GL_FALSE,
81 GL_FALSE,
82 GL_FALSE,
83 GL_FALSE,
84 GL_FALSE,
85 GL_TRUE,
86 GL_FALSE,
87 GL_FALSE,
88 GL_FALSE,
89 GL_FALSE,
90 GL_FALSE,
91 GL_TRUE,
92 GL_FALSE,
93 GL_FALSE,
94 GL_FALSE,
95 GL_FALSE,
96 GL_FALSE,
97 GL_FALSE,
98 GL_FALSE,
99 GL_FALSE,
100 GL_FALSE,
101 GL_FALSE,
102 GL_TRUE,
103 GL_FALSE,
104 0.0f,
105 1.0f,
106 GL_LESS,
107 GL_BACK,
108 GL_SMOOTH,
109 GL_ONE,
110 GL_ZERO,
111 GL_MODELVIEW,
112 };
113
114 struct booleanstate
115 {
116 GLboolean value;
117 GLboolean changed;
118 };
119
120 struct floatstate
121 {
122 GLfloat value;
123 GLboolean changed;
124 };
125
126 struct uintstate
127 {
128 GLuint value;
129 GLboolean changed;
130 };
131
132 struct ptrstate
133 {
134 GLint size;
135 GLenum type;
136 GLsizei stride;
137 GLvoid *ptr;
138 GLboolean changed;
139 GLboolean enabled;
140 };
141
142 struct nanotmuState
143 {
144 struct booleanstate texture_2d;
145 struct floatstate texture_env_mode;
146 struct uintstate boundtexture;
147 struct ptrstate vertex_array;
148 struct ptrstate color_array;
149 struct ptrstate texture_coord_array;
150 struct ptrstate normal_array;
151 };
152
153 static struct nanotmuState tmuState0;
154 static struct nanotmuState tmuState1;
155
156 static struct nanotmuState tmuInitState =
157 {
158 {GL_FALSE, GL_FALSE},
159 {GL_MODULATE, GL_FALSE},
160 {0x7fffffff, GL_FALSE},
161 {4, GL_FLOAT, 0, NULL, GL_FALSE, GL_FALSE},
162 {4, GL_FLOAT, 0, NULL, GL_FALSE, GL_FALSE},
163 {4, GL_FLOAT, 0, NULL, GL_FALSE, GL_FALSE},
164 {3, GL_FLOAT, 0, NULL, GL_FALSE, GL_FALSE},
165 };
166
167 static struct nanotmuState *activetmuState = &tmuState0;
168
169 extern "C++" GlESInterface *glEsImpl;
170
171 static GLenum wrapperPrimitiveMode = GL_QUADS;
172 GLboolean useTexCoordArray = GL_FALSE;
173 static GLenum activetmu = GL_TEXTURE0;
174 static GLenum clientactivetmu = GL_TEXTURE0;
175
176 #if defined( __MULTITEXTURE_SUPPORT__ )
177 GLboolean useMultiTexCoordArray = GL_FALSE;
178 #endif
179
180 #if !defined( __WINS__ )
181 //#define __FORCEINLINE __forceinline
182 #define __FORCEINLINE inline
183 #else
184 #define __FORCEINLINE
185 #endif
186
187 static GLboolean delayedttmuchange = GL_FALSE;
188 static GLenum delayedtmutarget = GL_TEXTURE0;
189
190 struct VertexAttrib
191 {
192 float x;
193 float y;
194 float z;
195 #if !defined( __MULTITEXTURE_SUPPORT__ )
196 float padding;
197 #endif
198 unsigned char red;
199 unsigned char green;
200 unsigned char blue;
201 unsigned char alpha;
202
203 float s;
204 float t;
205 #if defined( __MULTITEXTURE_SUPPORT__ )
206 float s_multi;
207 float t_multi;
208 #endif
209 };
210
211 static VertexAttrib vertexattribs[60000];
212
213 static GLushort indexArray[50000];
214
215 static GLuint vertexCount = 0;
216 static GLuint indexCount = 0;
217 static GLuint vertexMark = 0;
218 static int indexbase = 0;
219
220 static VertexAttrib *ptrVertexAttribArray = NULL;
221 static VertexAttrib *ptrVertexAttribArrayMark = NULL;
222
223 static VertexAttrib currentVertexAttrib;
224 #if defined( __MULTITEXTURE_SUPPORT__ )
225 static VertexAttrib currentVertexAttribInit = {0.0f, 0.0f, 0.0f, 255, 255, 255, 255, 0.0f, 0.0f, 0.0f, 0.0f};
226 #else
227 static VertexAttrib currentVertexAttribInit = {
228 0.0f, 0.0f, 0.0f, 0.0f, 255, 255, 255, 255, 0.0f, 0.0f,
229 };
230 #endif
231 static GLushort *ptrIndexArray = NULL;
232
233 static GLboolean arraysValid = GL_FALSE;
234
235 void InitGLStructs( )
236 {
237 ptrVertexAttribArray = vertexattribs;
238 ptrVertexAttribArrayMark = ptrVertexAttribArray;
239 ptrIndexArray = indexArray;
240
241 memcpy( &nanoglState, &nanoglInitState, sizeof( struct nanoState ) );
242 memcpy( &tmuState0, &tmuInitState, sizeof( struct nanotmuState ) );
243 memcpy( &tmuState1, &tmuInitState, sizeof( struct nanotmuState ) );
244 memcpy( &currentVertexAttrib, &currentVertexAttribInit, sizeof( struct VertexAttrib ) );
245
246 activetmuState = &tmuState0;
247 wrapperPrimitiveMode = GL_QUADS;
248 useTexCoordArray = GL_FALSE;
249 activetmu = GL_TEXTURE0;
250 clientactivetmu = GL_TEXTURE0;
251 delayedttmuchange = GL_FALSE;
252 delayedtmutarget = GL_TEXTURE0;
253 vertexCount = 0;
254 indexCount = 0;
255 vertexMark = 0;
256 indexbase = 0;
257 arraysValid = GL_FALSE;
258 }
259
260 void ResetNanoState( )
261 {
262
263 if ( tmuState0.color_array.enabled )
264 {
265 glEsImpl->glEnableClientState( GL_COLOR_ARRAY );
266 }
267 else
268 {
269 glEsImpl->glDisableClientState( GL_COLOR_ARRAY );
270 }
271
272 if ( tmuState0.vertex_array.enabled )
273 {
274 glEsImpl->glEnableClientState( GL_VERTEX_ARRAY );
275 }
276 else
277 {
278 glEsImpl->glDisableClientState( GL_VERTEX_ARRAY );
279 }
280
281 if ( tmuState0.texture_coord_array.enabled )
282 {
283 glEsImpl->glEnableClientState( GL_TEXTURE_COORD_ARRAY );
284 }
285 else
286 {
287 glEsImpl->glDisableClientState( GL_TEXTURE_COORD_ARRAY );
288 }
289
290 if ( tmuState0.normal_array.enabled )
291 {
292 glEsImpl->glEnableClientState( GL_NORMAL_ARRAY );
293 }
294 else
295 {
296 glEsImpl->glDisableClientState( GL_NORMAL_ARRAY );
297 }
298 glEsImpl->glVertexPointer( tmuState0.vertex_array.size,
299 tmuState0.vertex_array.type,
300 tmuState0.vertex_array.stride,
301 tmuState0.vertex_array.ptr );
302
303 glEsImpl->glTexCoordPointer( tmuState0.texture_coord_array.size,
304 tmuState0.texture_coord_array.type,
305 tmuState0.texture_coord_array.stride,
306 tmuState0.texture_coord_array.ptr );
307
308 glEsImpl->glColorPointer( tmuState0.color_array.size,
309 tmuState0.color_array.type,
310 tmuState0.color_array.stride,
311 tmuState0.color_array.ptr );
312
313 glEsImpl->glNormalPointer(
314 tmuState0.normal_array.type,
315 tmuState0.normal_array.stride,
316 tmuState0.normal_array.ptr );
317
318 glEsImpl->glMatrixMode( nanoglState.matrixmode );
319
320 glEsImpl->glColor4f( currentVertexAttrib.red, currentVertexAttrib.green, currentVertexAttrib.blue, currentVertexAttrib.alpha );
321
322 glEsImpl->glBlendFunc( nanoglState.sfactor, nanoglState.dfactor );
323
324 //glEsImpl->glBindTexture(GL_TEXTURE_2D, stackTextureState);
325
326 glEsImpl->glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, activetmuState->texture_env_mode.value );
327
328 arraysValid = GL_FALSE;
329 }
330
331 void FlushOnStateChange( )
332 {
333 if ( delayedttmuchange )
334 {
335 delayedttmuchange = GL_FALSE;
336 #ifndef USE_CORE_PROFILE
337 glEsImpl->glActiveTexture( delayedtmutarget );
338 #endif
339 }
340
341 if ( !vertexCount )
342 return;
343
344 if ( !arraysValid )
345 {
346 glEsImpl->glClientActiveTexture( GL_TEXTURE0 );
347 glEsImpl->glVertexPointer( 3, GL_FLOAT, sizeof( VertexAttrib ), &vertexattribs[0].x );
348 glEsImpl->glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( VertexAttrib ), &vertexattribs[0].red );
349 glEsImpl->glTexCoordPointer( 2, GL_FLOAT, sizeof( VertexAttrib ), &vertexattribs[0].s );
350 glEsImpl->glEnableClientState( GL_VERTEX_ARRAY );
351 glEsImpl->glEnableClientState( GL_TEXTURE_COORD_ARRAY );
352 glEsImpl->glEnableClientState( GL_COLOR_ARRAY );
353 #if defined( __MULTITEXTURE_SUPPORT__ )
354 glEsImpl->glClientActiveTexture( GL_TEXTURE1 );
355 glEsImpl->glTexCoordPointer( 2, GL_FLOAT, sizeof( VertexAttrib ), &vertexattribs[0].s_multi );
356 glEsImpl->glEnableClientState( GL_TEXTURE_COORD_ARRAY );
357 glEsImpl->glClientActiveTexture( GL_TEXTURE0 );
358 #endif
359 arraysValid = GL_TRUE;
360 }
361
362 glEsImpl->glDrawElements( GL_TRIANGLES, vertexCount, GL_UNSIGNED_SHORT, indexArray );
363
364 #if defined( __MULTITEXTURE_SUPPORT__ )
365 useMultiTexCoordArray = GL_FALSE;
366 #endif
367 vertexCount = 0;
368 indexCount = 0;
369 ptrVertexAttribArray = vertexattribs;
370 ptrVertexAttribArrayMark = ptrVertexAttribArray;
371 ptrIndexArray = indexArray;
372 useTexCoordArray = GL_FALSE;
373 }
374 void nanoGL_Flush( )
375 {
376 FlushOnStateChange( );
377 }
378 void nanoGL_Reset( )
379 {
380 ResetNanoState( );
381 }
382 void glBegin( GLenum mode )
383 {
384 wrapperPrimitiveMode = mode;
385 vertexMark = vertexCount;
386 ptrVertexAttribArrayMark = ptrVertexAttribArray;
387 indexbase = indexCount;
388 }
389
390 void glEnd( void )
391 {
392 vertexCount += ( (unsigned char *)ptrVertexAttribArray - (unsigned char *)ptrVertexAttribArrayMark ) / sizeof( VertexAttrib );
393 if ( vertexCount < 3 )
394 {
395 return;
396 }
397 switch ( wrapperPrimitiveMode )
398 {
399 case GL_QUADS:
400 {
401 *ptrIndexArray++ = indexCount;
402 *ptrIndexArray++ = indexCount + 1;
403 *ptrIndexArray++ = indexCount + 2;
404 *ptrIndexArray++ = indexCount;
405 *ptrIndexArray++ = indexCount + 2;
406 *ptrIndexArray++ = indexCount + 3;
407 indexCount += 4;
408 vertexCount += 2;
409 }
410 break;
411 case GL_TRIANGLES:
412 {
413 int vcount = ( vertexCount - vertexMark ) / 3;
414 for ( int count = 0; count < vcount; count++ )
415 {
416 *ptrIndexArray++ = indexCount;
417 *ptrIndexArray++ = indexCount + 1;
418 *ptrIndexArray++ = indexCount + 2;
419 indexCount += 3;
420 }
421 }
422 break;
423 case GL_TRIANGLE_STRIP:
424 {
425 *ptrIndexArray++ = indexCount;
426 *ptrIndexArray++ = indexCount + 1;
427 *ptrIndexArray++ = indexCount + 2;
428 indexCount += 3;
429 int vcount = ( ( vertexCount - vertexMark ) - 3 );
430 if ( vcount && ( (long)ptrIndexArray & 0x02 ) )
431 {
432 *ptrIndexArray++ = indexCount - 1; // 2
433 *ptrIndexArray++ = indexCount - 2; // 1
434 *ptrIndexArray++ = indexCount; // 3
435 indexCount++;
436 vcount -= 1;
437 int odd = vcount & 1;
438 vcount /= 2;
439 unsigned int *longptr = (unsigned int *)ptrIndexArray;
440
441 for ( int count = 0; count < vcount; count++ )
442 {
443 *( longptr++ ) = ( indexCount - 2 ) | ( ( indexCount - 1 ) << 16 );
444 *( longptr++ ) = ( indexCount ) | ( ( indexCount ) << 16 );
445 *( longptr++ ) = ( indexCount - 1 ) | ( ( indexCount + 1 ) << 16 );
446 indexCount += 2;
447 }
448 ptrIndexArray = (unsigned short *)( longptr );
449 if ( odd )
450 {
451 *ptrIndexArray++ = indexCount - 2; // 2
452 *ptrIndexArray++ = indexCount - 1; // 1
453 *ptrIndexArray++ = indexCount; // 3
454 indexCount++;
455 }
456 }
457 else
458 {
459 //already aligned
460 int odd = vcount & 1;
461 vcount /= 2;
462 unsigned int *longptr = (unsigned int *)ptrIndexArray;
463
464 for ( int count = 0; count < vcount; count++ )
465 {
466 *( longptr++ ) = ( indexCount - 1 ) | ( ( indexCount - 2 ) << 16 );
467 *( longptr++ ) = ( indexCount ) | ( ( indexCount - 1 ) << 16 );
468 *( longptr++ ) = ( indexCount ) | ( ( indexCount + 1 ) << 16 );
469 indexCount += 2;
470 }
471 ptrIndexArray = (unsigned short *)( longptr );
472 if ( odd )
473 {
474
475 *ptrIndexArray++ = indexCount - 1; // 2
476 *ptrIndexArray++ = indexCount - 2; // 1
477 *ptrIndexArray++ = indexCount; // 3
478 indexCount++;
479 }
480 }
481 vertexCount += ( vertexCount - vertexMark - 3 ) * 2;
482 }
483 break;
484 case GL_POLYGON:
485 case GL_TRIANGLE_FAN:
486 {
487 *ptrIndexArray++ = indexCount++;
488 *ptrIndexArray++ = indexCount++;
489 *ptrIndexArray++ = indexCount++;
490 int vcount = ( ( vertexCount - vertexMark ) - 3 );
491 for ( int count = 0; count < vcount; count++ )
492 {
493 *ptrIndexArray++ = indexbase;
494 *ptrIndexArray++ = indexCount - 1;
495 *ptrIndexArray++ = indexCount++;
496 vertexCount += 2;
497 }
498 }
499 break;
500
501 default:
502 break;
503 }
504 if ( ptrVertexAttribArray - vertexattribs > 20000 * sizeof( VertexAttrib ) ||
505 ptrIndexArray - indexArray > 15000 * sizeof( GLushort ) )
506 FlushOnStateChange( );
507 }
508
509 void glEnable( GLenum cap )
510 {
511 GLboolean statechanged = GL_FALSE;
512 switch ( cap )
513 {
514 case GL_ALPHA_TEST:
515 {
516 if ( !nanoglState.alpha_test )
517 {
518 nanoglState.alpha_test = GL_TRUE;
519 statechanged = GL_TRUE;
520 }
521 break;
522 }
523 case GL_BLEND:
524 {
525 if ( !nanoglState.blend )
526 {
527 nanoglState.blend = GL_TRUE;
528 statechanged = GL_TRUE;
529 }
530 break;
531 }
532 //case GL_CLIP_PLANEi
533 case GL_COLOR_LOGIC_OP:
534 {
535 if ( !nanoglState.color_logic_op )
536 {
537 nanoglState.color_logic_op = GL_TRUE;
538 statechanged = GL_TRUE;
539 }
540 break;
541 }
542 case GL_COLOR_MATERIAL:
543 {
544 if ( !nanoglState.color_material )
545 {
546 nanoglState.color_material = GL_TRUE;
547 statechanged = GL_TRUE;
548 }
549 break;
550 }
551 case GL_CULL_FACE:
552 {
553 if ( !nanoglState.cull_face )
554 {
555 nanoglState.cull_face = GL_TRUE;
556 statechanged = GL_TRUE;
557 }
558 break;
559 }
560 case GL_DEPTH_TEST:
561 {
562 if ( !nanoglState.depth_test )
563 {
564 nanoglState.depth_test = GL_TRUE;
565 statechanged = GL_TRUE;
566 }
567 break;
568 }
569 case GL_DITHER:
570 {
571 if ( !nanoglState.dither )
572 {
573 nanoglState.dither = GL_TRUE;
574 statechanged = GL_TRUE;
575 }
576 break;
577 }
578 case GL_FOG:
579 //case GL_LIGHTi
580 {
581 if ( !nanoglState.fog )
582 {
583 nanoglState.fog = GL_TRUE;
584 statechanged = GL_TRUE;
585 }
586 break;
587 }
588 case GL_LIGHTING:
589 {
590 if ( !nanoglState.lighting )
591 {
592 nanoglState.lighting = GL_TRUE;
593 statechanged = GL_TRUE;
594 }
595 break;
596 }
597 case GL_LINE_SMOOTH:
598 {
599 if ( !nanoglState.line_smooth )
600 {
601 nanoglState.line_smooth = GL_TRUE;
602 statechanged = GL_TRUE;
603 }
604 break;
605 }
606 /* case GL_MATRIX_PALETTE_OES:
607 {
608 if (!nanoglState.matrix_palette_oes)
609 {
610 nanoglState.matrix_palette_oes = GL_TRUE;
611 statechanged = GL_TRUE;
612 }
613 break;
614 }*/
615 case GL_MULTISAMPLE:
616 {
617 if ( !nanoglState.multisample )
618 {
619 nanoglState.multisample = GL_TRUE;
620 statechanged = GL_TRUE;
621 }
622 break;
623 }
624 case GL_NORMALIZE:
625 {
626 if ( !nanoglState.normalize )
627 {
628 nanoglState.normalize = GL_TRUE;
629 statechanged = GL_TRUE;
630 }
631 break;
632 }
633 /* case GL_POINT_SPRITE_OES:
634 {
635 if (!nanoglState.point_sprite_oes)
636 {
637 nanoglState.point_sprite_oes = GL_TRUE;
638 statechanged = GL_TRUE;
639 }
640 break;
641 }*/
642 case GL_POLYGON_OFFSET_FILL:
643 {
644 if ( !nanoglState.polygon_offset_fill )
645 {
646 nanoglState.polygon_offset_fill = GL_TRUE;
647 statechanged = GL_TRUE;
648 }
649 break;
650 }
651 case GL_RESCALE_NORMAL:
652 {
653 if ( !nanoglState.rescale_normal )
654 {
655 nanoglState.rescale_normal = GL_TRUE;
656 statechanged = GL_TRUE;
657 }
658 break;
659 }
660 case GL_SAMPLE_ALPHA_TO_COVERAGE:
661 {
662 if ( !nanoglState.sample_alpha_to_coverage )
663 {
664 nanoglState.sample_alpha_to_coverage = GL_TRUE;
665 statechanged = GL_TRUE;
666 }
667 break;
668 }
669 case GL_SAMPLE_ALPHA_TO_ONE:
670 {
671 if ( !nanoglState.sample_alpha_to_one )
672 {
673 nanoglState.sample_alpha_to_one = GL_TRUE;
674 statechanged = GL_TRUE;
675 }
676 break;
677 }
678 case GL_SAMPLE_COVERAGE:
679 {
680 if ( !nanoglState.sample_coverage )
681 {
682 nanoglState.sample_coverage = GL_TRUE;
683 statechanged = GL_TRUE;
684 }
685 break;
686 }
687 case GL_SCISSOR_TEST:
688 {
689 if ( !nanoglState.scissor_test )
690 {
691 nanoglState.scissor_test = GL_TRUE;
692 statechanged = GL_TRUE;
693 }
694 break;
695 }
696 case GL_STENCIL_TEST:
697 {
698 return;
699 /* if (!nanoglState.stencil_test)
700 {
701 nanoglState.stencil_test = GL_TRUE;
702 statechanged = GL_TRUE;
703 }*/
704 break;
705 }
706 case GL_TEXTURE_2D:
707 {
708 if ( !activetmuState->texture_2d.value )
709 {
710 FlushOnStateChange( );
711 glEsImpl->glEnable( cap );
712 activetmuState->texture_2d.value = GL_TRUE;
713 return;
714 }
715 break;
716 }
717 default:
718 break;
719 }
720
721 if ( statechanged )
722 {
723 FlushOnStateChange( );
724 glEsImpl->glEnable( cap );
725 }
726 }
727
728 void glDisable( GLenum cap )
729 {
730 GLboolean statechanged = GL_FALSE;
731 switch ( cap )
732 {
733 case GL_ALPHA_TEST:
734 {
735 if ( nanoglState.alpha_test )
736 {
737 nanoglState.alpha_test = GL_FALSE;
738 statechanged = GL_TRUE;
739 }
740 break;
741 }
742 case GL_BLEND:
743 {
744 if ( nanoglState.blend )
745 {
746 nanoglState.blend = GL_FALSE;
747 statechanged = GL_TRUE;
748 }
749 break;
750 }
751 //case GL_CLIP_PLANEi
752 case GL_COLOR_LOGIC_OP:
753 {
754 if ( nanoglState.color_logic_op )
755 {
756 nanoglState.color_logic_op = GL_FALSE;
757 statechanged = GL_TRUE;
758 }
759 break;
760 }
761 case GL_COLOR_MATERIAL:
762 {
763 if ( nanoglState.color_material )
764 {
765 nanoglState.color_material = GL_FALSE;
766 statechanged = GL_TRUE;
767 }
768 break;
769 }
770 case GL_CULL_FACE:
771 {
772 if ( nanoglState.cull_face )
773 {
774 nanoglState.cull_face = GL_FALSE;
775 statechanged = GL_TRUE;
776 }
777 break;
778 }
779 case GL_DEPTH_TEST:
780 {
781 if ( nanoglState.depth_test )
782 {
783 nanoglState.depth_test = GL_FALSE;
784 statechanged = GL_TRUE;
785 }
786 break;
787 }
788 case GL_DITHER:
789 {
790 if ( nanoglState.dither )
791 {
792 nanoglState.dither = GL_FALSE;
793 statechanged = GL_TRUE;
794 }
795 break;
796 }
797 case GL_FOG:
798 //case GL_LIGHTi
799 {
800 if ( nanoglState.fog )
801 {
802 nanoglState.fog = GL_FALSE;
803 statechanged = GL_TRUE;
804 }
805 break;
806 }
807 case GL_LIGHTING:
808 {
809 if ( nanoglState.lighting )
810 {
811 nanoglState.lighting = GL_FALSE;
812 statechanged = GL_TRUE;
813 }
814 break;
815 }
816 case GL_LINE_SMOOTH:
817 {
818 if ( nanoglState.line_smooth )
819 {
820 nanoglState.line_smooth = GL_FALSE;
821 statechanged = GL_TRUE;
822 }
823 break;
824 }
825 /* case GL_MATRIX_PALETTE_OES:
826 {
827 if (nanoglState.matrix_palette_oes)
828 {
829 nanoglState.matrix_palette_oes = GL_FALSE;
830 statechanged = GL_TRUE;
831 }
832 break;
833 }*/
834 case GL_MULTISAMPLE:
835 {
836 if ( nanoglState.multisample )
837 {
838 nanoglState.multisample = GL_FALSE;
839 statechanged = GL_TRUE;
840 }
841 break;
842 }
843 case GL_NORMALIZE:
844 {
845 if ( nanoglState.normalize )
846 {
847 nanoglState.normalize = GL_FALSE;
848 statechanged = GL_TRUE;
849 }
850 break;
851 }
852 /* case GL_POINT_SPRITE_OES:
853 {
854 if (nanoglState.point_sprite_oes)
855 {
856 nanoglState.point_sprite_oes = GL_FALSE;
857 statechanged = GL_TRUE;
858 }
859 break;
860 }*/
861 case GL_POLYGON_OFFSET_FILL:
862 {
863 if ( nanoglState.polygon_offset_fill )
864 {
865 nanoglState.polygon_offset_fill = GL_FALSE;
866 statechanged = GL_TRUE;
867 }
868 break;
869 }
870 case GL_RESCALE_NORMAL:
871 {
872 if ( nanoglState.rescale_normal )
873 {
874 nanoglState.rescale_normal = GL_FALSE;
875 statechanged = GL_TRUE;
876 }
877 break;
878 }
879 case GL_SAMPLE_ALPHA_TO_COVERAGE:
880 {
881 if ( nanoglState.sample_alpha_to_coverage )
882 {
883 nanoglState.sample_alpha_to_coverage = GL_FALSE;
884 statechanged = GL_TRUE;
885 }
886 break;
887 }
888 case GL_SAMPLE_ALPHA_TO_ONE:
889 {
890 if ( nanoglState.sample_alpha_to_one )
891 {
892 nanoglState.sample_alpha_to_one = GL_FALSE;
893 statechanged = GL_TRUE;
894 }
895 break;
896 }
897 case GL_SAMPLE_COVERAGE:
898 {
899 if ( nanoglState.sample_coverage )
900 {
901 nanoglState.sample_coverage = GL_FALSE;
902 statechanged = GL_TRUE;
903 }
904 break;
905 }
906 case GL_SCISSOR_TEST:
907 {
908 if ( nanoglState.scissor_test )
909 {
910 nanoglState.scissor_test = GL_FALSE;
911 statechanged = GL_TRUE;
912 }
913 break;
914 }
915 case GL_STENCIL_TEST:
916 {
917 return;
918 /* if (nanoglState.stencil_test)
919 {
920 nanoglState.stencil_test = GL_FALSE;
921 statechanged = GL_TRUE;
922 }*/
923 break;
924 }
925 case GL_TEXTURE_2D:
926 {
927 if ( activetmuState->texture_2d.value )
928 {
929 FlushOnStateChange( );
930 glEsImpl->glDisable( cap );
931 activetmuState->texture_2d.value = GL_FALSE;
932 return;
933 }
934 break;
935 }
936 default:
937 break;
938 }
939
940 if ( statechanged )
941 {
942 FlushOnStateChange( );
943 glEsImpl->glDisable( cap );
944 }
945 }
946
947 void glVertex2f( GLfloat x, GLfloat y )
948 {
949 glVertex3f( x, y, 0.0f );
950 }
951
952 __FORCEINLINE unsigned int ClampTo255( float value )
953 {
954 unsigned int retval = (unsigned int)( value );
955 if ( retval > 255 )
956 {
957 retval = 255;
958 }
959 return retval;
960 }
961
962 void glColor3f( GLfloat red, GLfloat green, GLfloat blue )
963 {
964 currentVertexAttrib.red = (unsigned char)ClampTo255( red * 255.0f );
965 currentVertexAttrib.green = (unsigned char)ClampTo255( green * 255.0f );
966 currentVertexAttrib.blue = (unsigned char)ClampTo255( blue * 255.0f );
967 currentVertexAttrib.alpha = 255;
968 }
969
970 void glTexCoord2fv( const GLfloat *v )
971 {
972 memcpy( &currentVertexAttrib.s, v, 2 * sizeof( float ) );
973 }
974
975 void glTexCoord2f( GLfloat s, GLfloat t )
976 {
977 currentVertexAttrib.s = s;
978 currentVertexAttrib.t = t;
979 }
980
981 void glViewport( GLint x, GLint y, GLsizei width, GLsizei height )
982 {
983 FlushOnStateChange( );
984 glEsImpl->glViewport( x, y, width, height );
985 }
986
987 void glLoadIdentity( void )
988 {
989 FlushOnStateChange( );
990 glEsImpl->glLoadIdentity( );
991 }
992
993 void glColor4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
994 {
995 if( nanoglState.stupidglesbug )
996 {
997 currentVertexAttrib.red = (unsigned char)ClampTo255( ( red * alpha ) * 255.0f );
998 currentVertexAttrib.green = (unsigned char)ClampTo255( ( green * alpha ) * 255.0f );
999 currentVertexAttrib.blue = (unsigned char)ClampTo255( ( blue * alpha ) * 255.0f );
1000 }
1001 else
1002 {
1003 currentVertexAttrib.red = (unsigned char)ClampTo255( red * 255.0f );
1004 currentVertexAttrib.green = (unsigned char)ClampTo255( green * 255.0f );
1005 currentVertexAttrib.blue = (unsigned char)ClampTo255( blue * 255.0f );
1006 }
1007 currentVertexAttrib.alpha = (unsigned char)ClampTo255( alpha * 255.0f );
1008 }
1009
1010 void glOrtho( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar )
1011 {
1012 FlushOnStateChange( );
1013 #ifdef USE_CORE_PROFILE
1014 glEsImpl->glOrtho( left, right, bottom, top, zNear, zFar );
1015 #else
1016 glEsImpl->glOrthof( left, right, bottom, top, zNear, zFar );
1017 #endif
1018 }
1019
1020 void glMatrixMode( GLenum mode )
1021 {
1022 if ( nanoglState.matrixmode == mode )
1023 {
1024 return;
1025 }
1026 nanoglState.matrixmode = mode;
1027 FlushOnStateChange( );
1028 glEsImpl->glMatrixMode( mode );
1029 }
1030
1031 void glTexParameterf( GLenum target, GLenum pname, GLfloat param )
1032 {
1033 if ( pname == GL_TEXTURE_BORDER_COLOR )
1034 {
1035 return; // not supported by opengl es
1036 }
1037 if ( ( pname == GL_TEXTURE_WRAP_S ||
1038 pname == GL_TEXTURE_WRAP_T ) &&
1039 param == GL_CLAMP )
1040 {
1041 param = 0x812F;
1042 }
1043
1044 FlushOnStateChange( );
1045 glEsImpl->glTexParameterf( target, pname, param );
1046 }
1047
1048 void glTexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
1049 {
1050 glTexParameterf( target, pname, params[0] );
1051 }
1052
1053 void glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels )
1054 {
1055 FlushOnStateChange( );
1056 internalformat = format;
1057 glEsImpl->glTexImage2D( target, level, internalformat, width, height, border, format, type, pixels );
1058 }
1059
1060 void glDrawBuffer( GLenum /*mode*/ )
1061 {
1062 }
1063
1064 void glTranslatef( GLfloat x, GLfloat y, GLfloat z )
1065 {
1066 FlushOnStateChange( );
1067 glEsImpl->glTranslatef( x, y, z );
1068 }
1069
1070 void glRotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
1071 {
1072 FlushOnStateChange( );
1073 glEsImpl->glRotatef( angle, x, y, z );
1074 }
1075
1076 void glScalef( GLfloat x, GLfloat y, GLfloat z )
1077 {
1078 FlushOnStateChange( );
1079 glEsImpl->glScalef( x, y, z );
1080 }
1081
1082 void glDepthRange( GLclampf zNear, GLclampf zFar )
1083 {
1084 if ( ( nanoglState.depth_range_near == zNear ) && ( nanoglState.depth_range_far == zFar ) )
1085 {
1086 return;
1087 }
1088 else
1089 {
1090 nanoglState.depth_range_near = zNear;
1091 nanoglState.depth_range_far = zFar;
1092 }
1093 FlushOnStateChange( );
1094 #ifdef USE_CORE_PROFILE
1095 glEsImpl->glDepthRange( zNear, zFar );
1096 #else
1097 glEsImpl->glDepthRangef( zNear, zFar );
1098 #endif
1099 }
1100
1101 void glDepthFunc( GLenum func )
1102 {
1103 if ( nanoglState.depth_func == func )
1104 {
1105 return;
1106 }
1107 else
1108 {
1109 nanoglState.depth_func = func;
1110 }
1111 FlushOnStateChange( );
1112 glEsImpl->glDepthFunc( func );
1113 }
1114
1115 void glFinish( void )
1116 {
1117 FlushOnStateChange( );
1118 glEsImpl->glFinish( );
1119 }
1120
1121 void glGetFloatv( GLenum pname, GLfloat *params )
1122 {
1123 FlushOnStateChange( );
1124 glEsImpl->glGetFloatv( pname, params );
1125 }
1126
1127 void glCullFace( GLenum mode )
1128 {
1129 if ( nanoglState.cullface == mode )
1130 {
1131 return;
1132 }
1133 else
1134 {
1135 nanoglState.cullface = mode;
1136 }
1137 FlushOnStateChange( );
1138 glEsImpl->glCullFace( mode );
1139 }
1140
1141 void glFrustum( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar )
1142 {
1143 FlushOnStateChange( );
1144 glEsImpl->glFrustumf( left, right, bottom, top, zNear, zFar );
1145 }
1146
1147 void glClear( GLbitfield mask )
1148 {
1149 FlushOnStateChange( );
1150 glEsImpl->glClear( mask );
1151 }
1152
1153 void glVertex3f( GLfloat x, GLfloat y, GLfloat z )
1154 {
1155 GLfloat *vert = (GLfloat *)ptrVertexAttribArray++;
1156 *vert++ = x;
1157 *vert++ = y;
1158 *vert++ = z;
1159 #if defined( __MULTITEXTURE_SUPPORT__ )
1160 memcpy( vert, &currentVertexAttrib.red, 5 * sizeof( GLfloat ) );
1161 #else
1162 memcpy( vert + 1, &currentVertexAttrib.red, 3 * sizeof( GLfloat ) );
1163 #endif
1164 }
1165
1166 void glColor4fv( const GLfloat *v )
1167 {
1168 if( nanoglState.stupidglesbug )
1169 {
1170 currentVertexAttrib.red = (unsigned char)ClampTo255( ( v[0] * v[3] ) * 255.0f );
1171 currentVertexAttrib.green = (unsigned char)ClampTo255( ( v[1] * v[3] ) * 255.0f );
1172 currentVertexAttrib.blue = (unsigned char)ClampTo255( ( v[2] * v[3] ) * 255.0f );
1173 }
1174 else
1175 {
1176 currentVertexAttrib.red = (unsigned char)ClampTo255( v[0] * 255.0f );
1177 currentVertexAttrib.green = (unsigned char)ClampTo255( v[1] * 255.0f );
1178 currentVertexAttrib.blue = (unsigned char)ClampTo255( v[2] * 255.0f );
1179 }
1180 currentVertexAttrib.alpha = (unsigned char)ClampTo255( v[3] * 255.0f );
1181 }
1182
1183 void glColor3ubv( const GLubyte *v )
1184 {
1185 currentVertexAttrib.red = v[0];
1186 currentVertexAttrib.green = v[1];
1187 currentVertexAttrib.blue = v[2];
1188 currentVertexAttrib.alpha = 255;
1189 }
1190
1191 void glColor4ubv( const GLubyte *v )
1192 {
1193 //*((unsigned int*)(&currentVertexAttrib.red)) = *((unsigned int*)(v));
1194 if( nanoglState.stupidglesbug )
1195 {
1196 currentVertexAttrib.red = (unsigned char)ClampTo255( v[0] * v[3] / 255.0f );
1197 currentVertexAttrib.green = (unsigned char)ClampTo255( v[1] * v[3] / 255.0f );
1198 currentVertexAttrib.blue = (unsigned char)ClampTo255( v[2] * v[3] / 255.0f );
1199 }
1200 else
1201 {
1202 currentVertexAttrib.red = v[0];
1203 currentVertexAttrib.green = v[1];
1204 currentVertexAttrib.blue = v[2];
1205 }
1206 currentVertexAttrib.alpha = v[3];
1207 }
1208
1209 void glColor3fv( const GLfloat *v )
1210 {
1211 currentVertexAttrib.red = (unsigned char)ClampTo255( v[0] * 255.0f );
1212 currentVertexAttrib.green = (unsigned char)ClampTo255( v[1] * 255.0f );
1213 currentVertexAttrib.blue = (unsigned char)ClampTo255( v[2] * 255.0f );
1214 currentVertexAttrib.alpha = 255;
1215 }
1216
1217 //-- nicknekit: xash3d funcs --
1218
1219 void glColor4ub( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha )
1220 {
1221 if( nanoglState.stupidglesbug )
1222 {
1223 currentVertexAttrib.red = (unsigned char)ClampTo255( red * alpha / 255.0f );
1224 currentVertexAttrib.green = (unsigned char)ClampTo255( green * alpha / 255.0f );
1225 currentVertexAttrib.blue = (unsigned char)ClampTo255( blue * alpha / 255.0f );
1226 }
1227 else
1228 {
1229 currentVertexAttrib.red = red;
1230 currentVertexAttrib.green = green;
1231 currentVertexAttrib.blue = blue;
1232 }
1233 currentVertexAttrib.alpha = alpha;
1234 }
1235
1236 void glColor3ub( GLubyte red, GLubyte green, GLubyte blue )
1237 {
1238 currentVertexAttrib.red = red;
1239 currentVertexAttrib.green = green;
1240 currentVertexAttrib.blue = blue;
1241 currentVertexAttrib.alpha = 255;
1242 }
1243
1244 void glNormal3fv( const GLfloat *v )
1245 {
1246 FlushOnStateChange( );
1247 glEsImpl->glNormal3f( v[0], v[1], v[2] );
1248 }
1249
1250 void glCopyTexImage2D( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border )
1251 {
1252 FlushOnStateChange( );
1253 glEsImpl->glCopyTexImage2D( target, level, internalformat, x, y, width, height, border );
1254 }
1255
1256 void glTexImage1D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels )
1257 {
1258 glTexImage2D( GL_TEXTURE_2D, level, internalformat, width, 1, border, format, type, pixels );
1259 }
1260
1261 void glTexImage3D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels )
1262 {
1263 glTexImage2D( GL_TEXTURE_2D, level, internalformat, width, height, border, format, type, pixels );
1264 }
1265
1266 void glTexSubImage1D( GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels )
1267 {
1268 glTexSubImage2D( target, level, xoffset, 0, width, 1, format, type, pixels );
1269 }
1270
1271 void glTexSubImage3D( GLenum target, GLint level,
1272 GLint xoffset, GLint yoffset,
1273 GLint zoffset, GLsizei width,
1274 GLsizei height, GLsizei depth,
1275 GLenum format,
1276 GLenum type, const GLvoid *pixels )
1277 {
1278 glTexSubImage2D( target, level, xoffset, yoffset, width, height, format, type, pixels );
1279 }
1280
1281 GLboolean glIsTexture( GLuint texture )
1282 {
1283 FlushOnStateChange( );
1284 return glEsImpl->glIsTexture( texture );
1285 }
1286
1287 void glTexGeni( GLenum coord, GLenum pname, GLint param )
1288 {
1289 //for mirrors? not needed for original hl?
1290 }
1291
1292 void glTexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
1293 {
1294 //for mirrors? not needed for original hl?
1295 }
1296
1297 //-- --//
1298
1299 void glHint( GLenum target, GLenum mode )
1300 {
1301 FlushOnStateChange( );
1302 glEsImpl->glHint( target, mode );
1303 }
1304
1305 void glBlendFunc( GLenum sfactor, GLenum dfactor )
1306 {
1307 if ( ( nanoglState.sfactor == sfactor ) && ( nanoglState.dfactor == dfactor ) )
1308 {
1309 return;
1310 }
1311
1312 if( sfactor == GL_SRC_ALPHA && dfactor == GL_ONE )
1313 {
1314 sfactor = GL_ONE; // workaround gles bug
1315 nanoglState.stupidglesbug = GL_TRUE;
1316 }
1317 else
1318 nanoglState.stupidglesbug = GL_FALSE;
1319
1320 nanoglState.sfactor = sfactor;
1321 nanoglState.dfactor = dfactor;
1322 FlushOnStateChange( );
1323 glEsImpl->glBlendFunc( sfactor, dfactor );
1324 }
1325
1326 void glPopMatrix( void )
1327 {
1328 FlushOnStateChange( );
1329 glEsImpl->glPopMatrix( );
1330 }
1331
1332 void glShadeModel( GLenum mode )
1333 {
1334 if ( nanoglState.shademodel == mode )
1335 {
1336 return;
1337 }
1338 nanoglState.shademodel = mode;
1339 FlushOnStateChange( );
1340 glEsImpl->glShadeModel( mode );
1341 }
1342
1343 void glPushMatrix( void )
1344 {
1345 FlushOnStateChange( );
1346 glEsImpl->glPushMatrix( );
1347 }
1348
1349 void glTexEnvf( GLenum target, GLenum pname, GLfloat param )
1350 {
1351 if ( target == GL_TEXTURE_ENV )
1352 {
1353 if ( pname == GL_TEXTURE_ENV_MODE )
1354 {
1355 if ( param == activetmuState->texture_env_mode.value )
1356 {
1357 return;
1358 }
1359 else
1360 {
1361 FlushOnStateChange( );
1362 glEsImpl->glTexEnvf( target, pname, param );
1363 activetmuState->texture_env_mode.value = param;
1364 return;
1365 }
1366 }
1367 }
1368 FlushOnStateChange( );
1369 glEsImpl->glTexEnvf( target, pname, param );
1370 }
1371
1372 void glVertex3fv( const GLfloat *v )
1373 {
1374 GLfloat *vert = (GLfloat *)ptrVertexAttribArray++;
1375 memcpy( vert, v, 3 * sizeof( GLfloat ) );
1376 #if defined( __MULTITEXTURE_SUPPORT__ )
1377 memcpy( vert + 3, &currentVertexAttrib.red, 5 * sizeof( GLfloat ) );
1378 #else
1379 memcpy( vert + 4, &currentVertexAttrib.red, 3 * sizeof( GLfloat ) );
1380 #endif
1381 }
1382
1383 void glDepthMask( GLboolean flag )
1384 {
1385 if ( nanoglState.depthmask == flag )
1386 {
1387 return;
1388 }
1389 nanoglState.depthmask = flag;
1390 FlushOnStateChange( );
1391 glEsImpl->glDepthMask( flag );
1392 }
1393
1394 void glBindTexture( GLenum target, GLuint texture )
1395 {
1396 if ( activetmuState->boundtexture.value == texture )
1397 {
1398 return;
1399 }
1400 FlushOnStateChange( );
1401 activetmuState->boundtexture.value = texture;
1402 glEsImpl->glBindTexture( target, texture );
1403 }
1404
1405 void glGetIntegerv( GLenum pname, GLint *params )
1406 {
1407 FlushOnStateChange( );
1408 glEsImpl->glGetIntegerv( pname, params );
1409 }
1410
1411 GLubyte nano_extensions_string[4096];
1412 const GLubyte *glGetString( GLenum name )
1413 {
1414
1415 if ( name == GL_EXTENSIONS )
1416 {
1417 #if defined( __MULTITEXTURE_SUPPORT__ )
1418 sprintf( (char *)nano_extensions_string, "%s %s", glEsImpl->glGetString( name ), "GL_ARB_multitexture EXT_texture_env_add" );
1419 #else
1420 sprintf( (char *)nano_extensions_string, "%s %s", glEsImpl->glGetString( name ), "EXT_texture_env_add" );
1421 #endif
1422 return nano_extensions_string;
1423 }
1424 return glEsImpl->glGetString( name );
1425 }
1426
1427 void glAlphaFunc( GLenum func, GLclampf ref )
1428 {
1429 FlushOnStateChange( );
1430 glEsImpl->glAlphaFunc( func, ref );
1431 }
1432
1433 void glFlush( void )
1434 {
1435 FlushOnStateChange( );
1436 glEsImpl->glFlush( );
1437 }
1438
1439 void glReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels )
1440 {
1441 if ( format == GL_DEPTH_COMPONENT )
1442 {
1443 // OpenglEs 1.1 does not support reading depth buffer without an extension
1444 memset( pixels, 0xff, 4 );
1445 return;
1446 }
1447 FlushOnStateChange( );
1448 glEsImpl->glReadPixels( x, y, width, height, format, type, pixels );
1449 }
1450
1451 void glReadBuffer( GLenum /*mode*/ )
1452 {
1453 }
1454
1455 void glLoadMatrixf( const GLfloat *m )
1456 {
1457 FlushOnStateChange( );
1458 glEsImpl->glLoadMatrixf( m );
1459 }
1460
1461 void glTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels )
1462 {
1463 FlushOnStateChange( );
1464 glEsImpl->glTexSubImage2D( target, level, xoffset, yoffset, width, height, format, type, pixels );
1465 }
1466
1467 void glClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
1468 {
1469 FlushOnStateChange( );
1470 glEsImpl->glClearColor( red, green, blue, alpha );
1471 }
1472
1473 GLenum glGetError( void )
1474 {
1475 //FlushOnStateChange();
1476 return GL_NO_ERROR; //glEsImpl->glGetError();
1477 }
1478
1479 void glActiveTexture( GLenum texture )
1480 {
1481 if ( activetmu == texture )
1482 {
1483 return;
1484 }
1485 if ( delayedttmuchange )
1486 {
1487 delayedttmuchange = GL_FALSE;
1488 }
1489 else
1490 {
1491 delayedttmuchange = GL_TRUE;
1492 delayedtmutarget = texture;
1493 }
1494 if ( texture == GL_TEXTURE0 )
1495 {
1496 activetmuState = &tmuState0;
1497 }
1498 else
1499 {
1500 activetmuState = &tmuState1;
1501 }
1502 activetmu = texture;
1503 }
1504
1505 void glClientActiveTexture( GLenum texture )
1506 {
1507 clientactivetmu = texture;
1508 }
1509
1510 void glPolygonMode( GLenum face, GLenum mode )
1511 {
1512 }
1513
1514 void glDeleteTextures( GLsizei n, const GLuint *textures )
1515 {
1516 FlushOnStateChange( );
1517 glEsImpl->glDeleteTextures( n, textures );
1518 }
1519
1520 void glClearDepth( GLclampf depth )
1521 {
1522 FlushOnStateChange( );
1523 glEsImpl->glClearDepthf( depth );
1524 }
1525
1526 void glClipPlane( GLenum plane, const GLdouble *equation )
1527 {
1528 FlushOnStateChange( );
1529 float array[4];
1530 array[0] = ( GLfloat )( equation[0] );
1531 array[1] = ( GLfloat )( equation[1] );
1532 array[2] = ( GLfloat )( equation[2] );
1533 array[3] = ( GLfloat )( equation[3] );
1534 glEsImpl->glClipPlanef( plane, array );
1535 }
1536
1537 void glScissor( GLint x, GLint y, GLsizei width, GLsizei height )
1538 {
1539 FlushOnStateChange( );
1540 glEsImpl->glScissor( x, y, width, height );
1541 }
1542
1543 void glPointSize( GLfloat size )
1544 {
1545 FlushOnStateChange( );
1546 glEsImpl->glPointSize( size );
1547 }
1548
1549 void glArrayElement( GLint i )
1550 {
1551 }
1552 void glLineWidth( GLfloat width )
1553 {
1554 }
1555 void glCallList( GLuint list )
1556 {
1557 }
1558 void glColorMask( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha )
1559 {
1560 }
1561 void glStencilFunc( GLenum func, GLint ref, GLuint mask )
1562 {
1563 }
1564 void glStencilOp( GLenum fail, GLenum zfail, GLenum zpass )
1565 {
1566 }
1567
1568 struct ptrstate vertex_array;
1569 struct ptrstate color_array;
1570 struct ptrstate texture_coord_array;
1571
1572 void glDrawElements( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices )
1573 {
1574 // ensure that all primitives specified between glBegin/glEnd pairs
1575 // are rendered first, and that we have correct tmu in use..
1576 FlushOnStateChange( );
1577 // setup correct vertex/color/texcoord pointers
1578 if ( arraysValid ||
1579 tmuState0.vertex_array.changed ||
1580 tmuState0.color_array.changed ||
1581 tmuState0.texture_coord_array.changed || tmuState0.normal_array.changed )
1582 {
1583 glEsImpl->glClientActiveTexture( GL_TEXTURE0 );
1584 }
1585 if ( arraysValid || tmuState0.vertex_array.changed )
1586 {
1587 if ( tmuState0.vertex_array.enabled )
1588 {
1589 glEsImpl->glEnableClientState( GL_VERTEX_ARRAY );
1590 }
1591 else
1592 {
1593 glEsImpl->glDisableClientState( GL_VERTEX_ARRAY );
1594 }
1595 glEsImpl->glVertexPointer( tmuState0.vertex_array.size,
1596 tmuState0.vertex_array.type,
1597 tmuState0.vertex_array.stride,
1598 tmuState0.vertex_array.ptr );
1599 tmuState0.vertex_array.changed = GL_FALSE;
1600 }
1601 if ( arraysValid || tmuState0.color_array.changed )
1602 {
1603 if ( tmuState0.color_array.enabled )
1604 {
1605 glEsImpl->glEnableClientState( GL_COLOR_ARRAY );
1606 }
1607 else
1608 {
1609 glEsImpl->glDisableClientState( GL_COLOR_ARRAY );
1610 }
1611 glEsImpl->glColorPointer( tmuState0.color_array.size,
1612 tmuState0.color_array.type,
1613 tmuState0.color_array.stride,
1614 tmuState0.color_array.ptr );
1615 tmuState0.color_array.changed = GL_FALSE;
1616 }
1617 if ( arraysValid || tmuState0.normal_array.changed )
1618 {
1619 if ( tmuState0.normal_array.enabled )
1620 {
1621 glEsImpl->glEnableClientState( GL_NORMAL_ARRAY );
1622 }
1623 else
1624 {
1625 glEsImpl->glDisableClientState( GL_NORMAL_ARRAY );
1626 }
1627 glEsImpl->glNormalPointer( tmuState0.normal_array.type,
1628 tmuState0.normal_array.stride,
1629 tmuState0.normal_array.ptr );
1630 tmuState0.normal_array.changed = GL_FALSE;
1631 }
1632 if ( arraysValid || tmuState0.texture_coord_array.changed )
1633 {
1634 tmuState0.texture_coord_array.changed = GL_FALSE;
1635 if ( tmuState0.texture_coord_array.enabled )
1636 {
1637 glEsImpl->glEnableClientState( GL_TEXTURE_COORD_ARRAY );
1638 }
1639 else
1640 {
1641 glEsImpl->glDisableClientState( GL_TEXTURE_COORD_ARRAY );
1642 }
1643 glEsImpl->glTexCoordPointer( tmuState0.texture_coord_array.size,
1644 tmuState0.texture_coord_array.type,
1645 tmuState0.texture_coord_array.stride,
1646 tmuState0.texture_coord_array.ptr );
1647 }
1648
1649 if ( arraysValid || tmuState1.texture_coord_array.changed )
1650 {
1651 tmuState1.texture_coord_array.changed = GL_FALSE;
1652 glEsImpl->glClientActiveTexture( GL_TEXTURE1 );
1653 if ( tmuState1.texture_coord_array.enabled )
1654 {
1655 glEsImpl->glEnableClientState( GL_TEXTURE_COORD_ARRAY );
1656 }
1657 else
1658 {
1659 glEsImpl->glDisableClientState( GL_TEXTURE_COORD_ARRAY );
1660 }
1661 glEsImpl->glTexCoordPointer( tmuState1.texture_coord_array.size,
1662 tmuState1.texture_coord_array.type,
1663 tmuState1.texture_coord_array.stride,
1664 tmuState1.texture_coord_array.ptr );
1665 }
1666
1667 arraysValid = GL_FALSE;
1668 glEsImpl->glDrawElements( mode, count, type, indices );
1669 }
1670
1671 void glEnableClientState( GLenum array )
1672 {
1673 struct nanotmuState *clientstate = NULL;
1674 if ( clientactivetmu == GL_TEXTURE0 )
1675 {
1676 clientstate = &tmuState0;
1677 }
1678 else if ( clientactivetmu == GL_TEXTURE1 )
1679 {
1680 clientstate = &tmuState1;
1681 }
1682 else
1683 {
1684 return;
1685 }
1686 switch ( array )
1687 {
1688 case GL_VERTEX_ARRAY:
1689 if ( clientstate->vertex_array.enabled )
1690 {
1691 return;
1692 }
1693 clientstate->vertex_array.enabled = GL_TRUE;
1694 clientstate->vertex_array.changed = GL_TRUE;
1695 break;
1696 case GL_COLOR_ARRAY:
1697 if ( clientstate->color_array.enabled )
1698 {
1699 return;
1700 }
1701 clientstate->color_array.enabled = GL_TRUE;
1702 clientstate->color_array.changed = GL_TRUE;
1703
1704 break;
1705 case GL_NORMAL_ARRAY:
1706 if ( clientstate->normal_array.enabled )
1707 {
1708 return;
1709 }
1710 clientstate->normal_array.enabled = GL_TRUE;
1711 clientstate->normal_array.changed = GL_TRUE;
1712
1713 break;
1714 case GL_TEXTURE_COORD_ARRAY:
1715 if ( clientstate->texture_coord_array.enabled )
1716 {
1717 return;
1718 }
1719 clientstate->texture_coord_array.enabled = GL_TRUE;
1720 clientstate->texture_coord_array.changed = GL_TRUE;
1721 break;
1722 default:
1723 break;
1724 }
1725 }
1726 void glDisableClientState( GLenum array )
1727 {
1728 struct nanotmuState *clientstate = NULL;
1729 if ( clientactivetmu == GL_TEXTURE0 )
1730 {
1731 clientstate = &tmuState0;
1732 }
1733 else if ( clientactivetmu == GL_TEXTURE1 )
1734 {
1735 clientstate = &tmuState1;
1736 }
1737 else
1738 {
1739 return;
1740 }
1741 switch ( array )
1742 {
1743 case GL_VERTEX_ARRAY:
1744 if ( !clientstate->vertex_array.enabled )
1745 {
1746 return;
1747 }
1748 clientstate->vertex_array.enabled = GL_FALSE;
1749 clientstate->vertex_array.changed = GL_TRUE;
1750 break;
1751 case GL_COLOR_ARRAY:
1752 if ( !clientstate->color_array.enabled )
1753 {
1754 return;
1755 }
1756 clientstate->color_array.enabled = GL_FALSE;
1757 clientstate->color_array.changed = GL_TRUE;
1758
1759 break;
1760 case GL_NORMAL_ARRAY:
1761 if ( !clientstate->normal_array.enabled )
1762 {
1763 return;
1764 }
1765 clientstate->normal_array.enabled = GL_FALSE;
1766 clientstate->normal_array.changed = GL_TRUE;
1767
1768 break;
1769 case GL_TEXTURE_COORD_ARRAY:
1770 if ( !clientstate->texture_coord_array.enabled )
1771 {
1772 return;
1773 }
1774 clientstate->texture_coord_array.enabled = GL_FALSE;
1775 clientstate->texture_coord_array.changed = GL_TRUE;
1776 break;
1777 default:
1778 break;
1779 }
1780 }
1781 void glVertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
1782 {
1783 if ( tmuState0.vertex_array.size == size &&
1784 tmuState0.vertex_array.stride == stride &&
1785 tmuState0.vertex_array.type == type &&
1786 tmuState0.vertex_array.ptr == pointer )
1787 {
1788 return;
1789 }
1790 tmuState0.vertex_array.size = size;
1791 tmuState0.vertex_array.stride = stride;
1792 tmuState0.vertex_array.type = type;
1793 tmuState0.vertex_array.ptr = (GLvoid *)pointer;
1794 tmuState0.vertex_array.changed = GL_TRUE;
1795 }
1796 void glTexCoordPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
1797 {
1798 struct nanotmuState *clientstate = NULL;
1799 if ( clientactivetmu == GL_TEXTURE0 )
1800 {
1801 clientstate = &tmuState0;
1802 }
1803 else if ( clientactivetmu == GL_TEXTURE1 )
1804 {
1805 clientstate = &tmuState1;
1806 }
1807 if ( clientstate->texture_coord_array.size == size &&
1808 clientstate->texture_coord_array.stride == stride &&
1809 clientstate->texture_coord_array.type == type &&
1810 clientstate->texture_coord_array.ptr == pointer )
1811 {
1812 return;
1813 }
1814 clientstate->texture_coord_array.size = size;
1815 clientstate->texture_coord_array.stride = stride;
1816 clientstate->texture_coord_array.type = type;
1817 clientstate->texture_coord_array.ptr = (GLvoid *)pointer;
1818 clientstate->texture_coord_array.changed = GL_TRUE;
1819 }
1820 void glColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
1821 {
1822 if ( tmuState0.color_array.size == size &&
1823 tmuState0.color_array.stride == stride &&
1824 tmuState0.color_array.type == type &&
1825 tmuState0.color_array.ptr == pointer )
1826 {
1827 return;
1828 }
1829 tmuState0.color_array.size = size;
1830 tmuState0.color_array.stride = stride;
1831 tmuState0.color_array.type = type;
1832 tmuState0.color_array.ptr = (GLvoid *)pointer;
1833 tmuState0.color_array.changed = GL_TRUE;
1834 }
1835
1836 void glNormalPointer( GLenum type, GLsizei stride, const GLvoid *pointer )
1837 {
1838 int size = 0;
1839 if ( tmuState0.normal_array.size == size &&
1840 tmuState0.normal_array.stride == stride &&
1841 tmuState0.normal_array.type == type &&
1842 tmuState0.normal_array.ptr == pointer )
1843 {
1844 return;
1845 }
1846 tmuState0.normal_array.size = size;
1847 tmuState0.normal_array.stride = stride;
1848 tmuState0.normal_array.type = type;
1849 tmuState0.normal_array.ptr = (GLvoid *)pointer;
1850 tmuState0.normal_array.changed = GL_TRUE;
1851 }
1852 void glPolygonOffset( GLfloat factor, GLfloat units )
1853 {
1854 FlushOnStateChange( );
1855 glEsImpl->glPolygonOffset( factor, units );
1856 }
1857 void glStencilMask( GLuint mask )
1858 {
1859 }
1860 void glClearStencil( GLint s )
1861 {
1862 }
1863
1864 #if defined( __MULTITEXTURE_SUPPORT__ )
1865
1866 extern "C" void glMultiTexCoord2fARB( GLenum target, GLfloat s, GLfloat t );
1867
1868 void glMultiTexCoord2fARB( GLenum target, GLfloat s, GLfloat t )
1869 {
1870 if ( target == GL_TEXTURE0 )
1871 {
1872 glTexCoord2f( s, t );
1873 }
1874 else
1875 {
1876 currentVertexAttrib.s_multi = s;
1877 currentVertexAttrib.t_multi = t;
1878 }
1879 }
1880 #endif
1881
1882 /* Vladimir */
1883 /*void glDrawArrays( GLenum mode, int first, int count)
1884 {
1885 FlushOnStateChange();
1886 glEsImpl->glDrawArrays(mode, first , count);
1887 }*/
1888 void glMultMatrixf( const GLfloat *m )
1889 {
1890 FlushOnStateChange( );
1891 glEsImpl->glMultMatrixf( m );
1892 }
1893
1894 void glPixelStorei( GLenum pname, GLint param )
1895 {
1896 FlushOnStateChange( );
1897 glEsImpl->glPixelStorei( pname, param );
1898 }
1899
1900 void glFogf( GLenum pname, GLfloat param )
1901 {
1902 FlushOnStateChange( );
1903 glEsImpl->glFogf( pname, param );
1904 }
1905
1906 void glFogfv( GLenum pname, const GLfloat *params )
1907 {
1908 FlushOnStateChange( );
1909 glEsImpl->glFogfv( pname, params );
1910 }
1911
1912 void glGetTexParameteriv( GLenum target, GLenum pname, GLint *params )
1913 {
1914 FlushOnStateChange( );
1915 glEsImpl->glGetTexParameteriv( target, pname, params );
1916 }
1917
1918 // This gives: called unimplemented OpenGL ES API (Android)
1919 void glTexParameteri( GLenum target, GLenum pname, GLint param )
1920 {
1921 if ( pname == GL_TEXTURE_BORDER_COLOR )
1922 {
1923 return; // not supported by opengl es
1924 }
1925 if ( ( pname == GL_TEXTURE_WRAP_S ||
1926 pname == GL_TEXTURE_WRAP_T ) &&
1927 param == GL_CLAMP )
1928 {
1929 param = 0x812F;
1930 }
1931
1932 FlushOnStateChange( );
1933 glEsImpl->glTexParameteri( target, pname, param );
1934 }
1935
1936 void glTexParameterx( GLenum target, GLenum pname, GLfixed param )
1937 {
1938 if ( pname == GL_TEXTURE_BORDER_COLOR )
1939 {
1940 return; // not supported by opengl es
1941 }
1942 if ( ( pname == GL_TEXTURE_WRAP_S ||
1943 pname == GL_TEXTURE_WRAP_T ) &&
1944 param == GL_CLAMP )
1945 {
1946 param = 0x812F;
1947 }
1948 FlushOnStateChange( );
1949 glEsImpl->glTexParameterx( target, pname, param );
1950 }
1951
1952 void glGenTextures( GLsizei n, GLuint *textures )
1953 {
1954 FlushOnStateChange( );
1955 glEsImpl->glGenTextures( n, textures );
1956 }
1957
1958 void glFrontFace( GLenum mode )
1959 {
1960 FlushOnStateChange( );
1961 glEsImpl->glFrontFace( mode );
1962 }
1963 // End Vladimir
1964
1965 void glTexEnvi( GLenum target, GLenum pname, GLint param )
1966 {
1967 if ( target == GL_TEXTURE_ENV )
1968 {
1969 if ( pname == GL_TEXTURE_ENV_MODE )
1970 {
1971 if ( param == activetmuState->texture_env_mode.value )
1972 {
1973 return;
1974 }
1975 else
1976 {
1977 FlushOnStateChange( );
1978 glEsImpl->glTexEnvi( target, pname, param );
1979 activetmuState->texture_env_mode.value = param;
1980 return;
1981 }
1982 }
1983 }
1984 FlushOnStateChange( );
1985 glEsImpl->glTexEnvi( target, pname, param );
1986 }
1987
1988 #ifdef __MULTITEXTURE_SUPPORT__
1989 void glMultiTexCoord3fARB( GLenum a, GLfloat b, GLfloat c, GLfloat )
1990 {
1991 return glMultiTexCoord2fARB( a, b, c );
1992 }
1993
1994 void glMultiTexCoord2f( GLenum, GLfloat, GLfloat )
1995 {
1996 }
1997 #endif
1998 void glDrawArrays( GLenum mode, GLint first, GLsizei count )
1999 {
2000 // ensure that all primitives specified between glBegin/glEnd pairs
2001 // are rendered first, and that we have correct tmu in use..
2002 if ( mode == GL_QUADS )
2003 mode = GL_TRIANGLE_FAN;
2004 FlushOnStateChange( );
2005 // setup correct vertex/color/texcoord pointers
2006 if ( arraysValid ||
2007 tmuState0.vertex_array.changed ||
2008 tmuState0.color_array.changed ||
2009 tmuState0.texture_coord_array.changed || tmuState0.normal_array.changed )
2010 {
2011 glEsImpl->glClientActiveTexture( GL_TEXTURE0 );
2012 }
2013 if ( arraysValid || tmuState0.vertex_array.changed )
2014 {
2015 if ( tmuState0.vertex_array.enabled )
2016 {
2017 glEsImpl->glEnableClientState( GL_VERTEX_ARRAY );
2018 }
2019 else
2020 {
2021 glEsImpl->glDisableClientState( GL_VERTEX_ARRAY );
2022 }
2023 glEsImpl->glVertexPointer( tmuState0.vertex_array.size,
2024 tmuState0.vertex_array.type,
2025 tmuState0.vertex_array.stride,
2026 tmuState0.vertex_array.ptr );
2027 tmuState0.vertex_array.changed = GL_FALSE;
2028 }
2029 if ( arraysValid || tmuState0.color_array.changed )
2030 {
2031 if ( tmuState0.color_array.enabled )
2032 {
2033 glEsImpl->glEnableClientState( GL_COLOR_ARRAY );
2034 }
2035 else
2036 {
2037 glEsImpl->glDisableClientState( GL_COLOR_ARRAY );
2038 }
2039 glEsImpl->glColorPointer( tmuState0.color_array.size,
2040 tmuState0.color_array.type,
2041 tmuState0.color_array.stride,
2042 tmuState0.color_array.ptr );
2043 tmuState0.color_array.changed = GL_FALSE;
2044 }
2045 if ( arraysValid || tmuState0.normal_array.changed )
2046 {
2047 if ( tmuState0.normal_array.enabled )
2048 {
2049 glEsImpl->glEnableClientState( GL_NORMAL_ARRAY );
2050 }
2051 else
2052 {
2053 glEsImpl->glDisableClientState( GL_NORMAL_ARRAY );
2054 }
2055 glEsImpl->glNormalPointer( tmuState0.normal_array.type,
2056 tmuState0.normal_array.stride,
2057 tmuState0.normal_array.ptr );
2058 tmuState0.normal_array.changed = GL_FALSE;
2059 }
2060 if ( arraysValid || tmuState0.texture_coord_array.changed )
2061 {
2062 tmuState0.texture_coord_array.changed = GL_FALSE;
2063 if ( tmuState0.texture_coord_array.enabled )
2064 {
2065 glEsImpl->glEnableClientState( GL_TEXTURE_COORD_ARRAY );
2066 }
2067 else
2068 {
2069 glEsImpl->glDisableClientState( GL_TEXTURE_COORD_ARRAY );
2070 }
2071 glEsImpl->glTexCoordPointer( tmuState0.texture_coord_array.size,
2072 tmuState0.texture_coord_array.type,
2073 tmuState0.texture_coord_array.stride,
2074 tmuState0.texture_coord_array.ptr );
2075 }
2076
2077 if ( arraysValid || tmuState1.texture_coord_array.changed )
2078 {
2079 tmuState1.texture_coord_array.changed = GL_FALSE;
2080 glEsImpl->glClientActiveTexture( GL_TEXTURE1 );
2081 if ( tmuState1.texture_coord_array.enabled )
2082 {
2083 glEsImpl->glEnableClientState( GL_TEXTURE_COORD_ARRAY );
2084 }
2085 else
2086 {
2087 glEsImpl->glDisableClientState( GL_TEXTURE_COORD_ARRAY );
2088 }
2089 glEsImpl->glTexCoordPointer( tmuState1.texture_coord_array.size,
2090 tmuState1.texture_coord_array.type,
2091 tmuState1.texture_coord_array.stride,
2092 tmuState1.texture_coord_array.ptr );
2093 }
2094
2095 arraysValid = GL_FALSE;
2096 glEsImpl->glDrawArrays( mode, first, count );
2097 }
2098 /*void glNormalPointer(GLenum type, GLsizei stride, const void *ptr)
2099 {
2100 glEsImpl->glNormalPointer( type, stride, ptr );
2101 }*/
2102
2103 void glCopyTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height )
2104 {
2105 FlushOnStateChange( );
2106 glEsImpl->glCopyTexSubImage2D( target, level, xoffset, yoffset, x, y, width, height );
2107 }
2108
2109 void glGenFramebuffers( GLsizei n, GLuint *framebuffers )
2110 {
2111 FlushOnStateChange( );
2112 glEsImpl->glGenFramebuffers( n, framebuffers );
2113 }
2114
2115 void glGenRenderbuffers( GLsizei n, GLuint *renderbuffers )
2116 {
2117 FlushOnStateChange( );
2118 glEsImpl->glGenRenderbuffers( n, renderbuffers );
2119 }
2120
2121 void glBindRenderbuffer( GLenum target, GLuint renderbuffer )
2122 {
2123 FlushOnStateChange( );
2124 glEsImpl->glBindRenderbuffer( target, renderbuffer );
2125 }
2126
2127 void glBindFramebuffer( GLenum target, GLuint framebuffer )
2128 {
2129 FlushOnStateChange( );
2130 glEsImpl->glBindFramebuffer( target, framebuffer );
2131 }
2132
2133 void glFramebufferRenderbuffer( GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer )
2134 {
2135 FlushOnStateChange( );
2136 glEsImpl->glFramebufferRenderbuffer( target, attachment, renderbuffertarget, renderbuffer );
2137 }
2138
2139 void glDeleteFramebuffers( GLsizei n, const GLuint *framebuffers )
2140 {
2141 FlushOnStateChange( );
2142 glEsImpl->glDeleteFramebuffers( n, framebuffers );
2143 }
2144
2145 void glDeleteRenderbuffers( GLsizei n, const GLuint *renderbuffers )
2146 {
2147 FlushOnStateChange( );
2148 glEsImpl->glDeleteRenderbuffers( n, renderbuffers );
2149 }
2150 void glFramebufferTexture2D( GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level )
2151 {
2152 FlushOnStateChange( );
2153 glEsImpl->glFramebufferTexture2D( target, attachment, textarget, texture, level );
2154 }
2155
2156 void glRenderbufferStorage( GLenum target, GLenum internalformat, GLsizei width, GLsizei height )
2157 {
2158 FlushOnStateChange( );
2159 glEsImpl->glRenderbufferStorage( target, internalformat, width, height );
2160 }