1 import "OpenGLDisplayDriver"
13 #if defined(__EMSCRIPTEN__)
17 #include <GLES2/gl2.h>
20 #if defined(__ANDROID__) || defined(__ODROID__)
27 #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
29 //# include "gl_core_3_3.h"
30 # include "gl_compat_4_4.h" // FIXME: no glPushAttrib() in core profile
32 # include "gl_compat_4_4.h"
38 #undef glEnableClientState
39 #undef glDisableClientState
40 #undef GL_VERTEX_ARRAY
41 #undef GL_NORMAL_ARRAY
42 #undef GL_TEXTURE_COORD_ARRAY
44 #undef glVertexPointer
45 #undef glTexCoordPointer
48 #define glEnableClientState glEnableVertexAttribArray
49 #define glDisableClientState glDisableVertexAttribArray
50 #define GL_VERTEX_ARRAY GLBufferContents::vertex
51 #define GL_NORMAL_ARRAY GLBufferContents::normal
52 #define GL_TEXTURE_COORD_ARRAY GLBufferContents::texCoord
53 #define GL_COLOR_ARRAY GLBufferContents::color
54 #define glVertexPointer(n, t, s, p) glVertexAttribPointer(GLBufferContents::vertex, n, t, GL_FALSE, s, p)
55 #define glTexCoordPointer(n, t, s, p) glVertexAttribPointer(GLBufferContents::texCoord, n, t, GL_FALSE, s, p)
56 #define glColorPointer(n, t, s, p) glVertexAttribPointer(GLBufferContents::color, n, t, GL_FALSE, s, p)
60 #if defined(_GLES) || defined(_GLES2) || defined(SHADERS)
97 #undef glColorMaterial
100 #define glRecti glimtkRecti
101 #define glBegin glimtkBegin
102 #define glTexCoord2i glimtkTexCoord2i
103 #define glVertex2i glimtkVertex2i
104 #define glTexCoord2d glimtkTexCoord2d
105 #define glVertex2d glimtkVertex2d
106 #define glTexCoord2f glimtkTexCoord2f
107 #define glVertex2f glimtkVertex2f
108 #define glEnd glimtkEnd
109 #define glColor3f glimtkColor3f
110 #define glColor4ub glimtkColor4ub
111 #define glColor4fv glimtkColor4fv
112 #define glNormal3fv glimtkNormal3fv
113 #define glNormal3f glimtkNormal3f
114 #define glTexCoord2fv glimtkTexCoord2fv
115 #define glVertex3d glimtkVertex3d
116 #define glVertex3dv glimtkVertex3dv
117 #define glVertex3f glimtkVertex3f
118 #define glVertex3fv glimtkVertex3fv
120 #define glLoadMatrixd glmsLoadMatrixd
121 #define glLoadMatrixf glmsLoadMatrixf
122 #define glMultMatrixd glmsMultMatrixd
123 #define glFrustum glmsFrustum
124 #define glOrtho glmsOrtho
125 #define glScaled glmsScaled
126 #define glScalef glmsScaled
127 #define glTranslated glmsTranslated
128 #define glRotated glmsRotated
129 #define glMatrixMode glmsMatrixMode
130 #define glLoadIdentity glmsLoadIdentity
131 #define glPushMatrix glmsPushMatrix
132 #define glPopMatrix glmsPopMatrix
134 #define glLineStipple glesLineStipple
135 #define glColorMaterial glesColorMaterial
136 #define glLightModeli glesLightModeli
142 #define OFFSET(s, m) ((uint)(uintptr) (&((s *) 0)->m))
144 import "textureManager"
147 #define DM_ENABLE_IMAGE_ROTATION (1)
148 #define DM_ENABLE_EXT_COLOR (1)
152 static struct DMDrawVertexFlat
157 #if DM_ENABLE_EXT_COLOR
160 } __attribute__((aligned(16)));
162 static struct DMDrawVertex
167 #if DM_ENABLE_EXT_COLOR
170 } __attribute__((aligned(16)));
181 class DMProgramFlags : uint { bool valid:1; }
187 GLuint fragmentShader;
193 #if DM_ENABLE_EXT_COLOR
197 DMProgramFlags flags;
198 int64 lastUpdateCount;
201 class DMImageFlags : uint16
203 bool empty:1; // Image is empty, do not draw
204 bool blending:1; // Must draw image with blending
207 public struct DMImage
216 // Computed order for sorted rendering, in defineImage()
222 this = { flags = { empty = true } };
225 void defineImage( Texture texture, int offsetx, int offsety, int sizex, int sizey, bool blending, int programIndex, int layerindex )
227 int ordx = offsetx >> 6;
228 int ordy = offsety >> 6;
229 uint32 orderimage = ccMortonNumber32( ordx, ordy ) & ( ( 1 << DM_IMAGE_ORDER_BITS ) - 1 );
233 srcx = (short)offsetx;
234 srcy = (short)offsety;
235 sizex = (short)sizex;
236 sizey = (short)sizey;
237 programIndex = (short)programIndex;
238 flags = { blending = blending };
239 orderMask = (orderimage << DM_IMAGE_ORDER_SHIFT) |
240 (( blending == true ) << DM_BLEND_ORDER_SHIFT) |
241 (programIndex << DM_PROGRAM_ORDER_SHIFT) |
243 (layerindex << DM_LAYER_ORDER_SHIFT);
255 #if DM_ENABLE_IMAGE_ROTATION
259 #if DM_ENABLE_EXT_COLOR
270 define DM_IMAGE_ORDER_BITS = 8;
271 define DM_BLEND_ORDER_BITS = 1;
272 define DM_PROGRAM_ORDER_BITS = 4;
273 define DM_TEXTURE_ORDER_BITS = 10;
274 define DM_LAYER_ORDER_BITS = 4;
275 define DM_BARRIER_ORDER_BITS = 5;
277 define DM_IMAGE_ORDER_SHIFT = 0;
278 define DM_BLEND_ORDER_SHIFT = DM_IMAGE_ORDER_BITS;
279 define DM_PROGRAM_ORDER_SHIFT = DM_IMAGE_ORDER_BITS+DM_BLEND_ORDER_BITS;
280 define DM_TEXTURE_ORDER_SHIFT = DM_IMAGE_ORDER_BITS+DM_BLEND_ORDER_BITS+DM_PROGRAM_ORDER_BITS;
281 define DM_LAYER_ORDER_SHIFT = DM_IMAGE_ORDER_BITS+DM_BLEND_ORDER_BITS+DM_PROGRAM_ORDER_BITS+DM_TEXTURE_ORDER_BITS;
282 define DM_BARRIER_ORDER_SHIFT = DM_IMAGE_ORDER_BITS+DM_BLEND_ORDER_BITS+DM_PROGRAM_ORDER_BITS+DM_TEXTURE_ORDER_BITS+DM_LAYER_ORDER_BITS;
284 define DM_LAYER_COUNT = 1<<DM_LAYER_ORDER_BITS;
285 define DM_PROGRAM_COUNT = 1<<DM_PROGRAM_ORDER_BITS;
287 define DM_CONTEXT_DRAW_BUFFER_COUNT = 64;
288 define DM_CONTEXT_DRAW_BUFFER_VERTEX_ALLOC = 1024;
291 /* Range is from zero to DM_LAYER_COUNT */
312 define DM_LAYER_BOTTOM = DMLayer::DM_LAYER_0_BOTTOM;
313 define DM_LAYER_BELOW = DMLayer::DM_LAYER_3_BELOW;
314 define DM_LAYER_NORMAL = DMLayer::DM_LAYER_6_NORMAL;
315 define DM_LAYER_ABOVE = DMLayer::DM_LAYER_9_ABOVE;
316 define DM_LAYER_TOP = DMLayer::DM_LAYER_15_TOP;
318 define DM_PROGRAM_NORMAL = 0;
319 define DM_PROGRAM_ALPHABLEND = 1;
320 define DM_PROGRAM_ALPHABLEND_INTENSITY = 2;
321 define DM_PROGRAM_ALPHABLEND_INTENSITY_EXTCOLOR = 3;
324 static inline void OpenGLErrorCheck( const char *file, int line )
326 int error = glGetError();
327 if( error != GL_NO_ERROR )
328 printf( "ERROR %d at %s:%d\n", error, file, line );
331 #define ERRORCHECK() OpenGLErrorCheck(__FILE__,__LINE__)
336 // Not using 32767.0 ; overflow when converting to int16 due to floating point crud causes problems
337 #define DM_IMAGE_ROTATION_NORMFACTOR (24576.0f)
339 #define DM_VERTEX_NORMSHIFT (2)
340 #define DM_VERTEX_NORMFACTOR (4.0f)
342 #define DM_TEXCOORD_NORMSHIFT (13)
343 #define DM_TEXCOORD_NORMFACTOR (8192.0 /*f*/)
346 static GLuint dmCreateShader( GLenum type, const char *shadersource, const char *optionstring )
352 const GLchar *sourcearray[2];
354 shader = glCreateShader( type );
358 if( !( optionstring ) )
360 sourcearray[0] = optionstring;
361 sourcearray[1] = shadersource;
362 glShaderSource( shader, 2, sourcearray, NULL );
363 glCompileShader( shader );
364 glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
365 if( status != GL_TRUE )
367 fprintf( stderr, "ERROR: Failed to compile shader\n" );
368 glGetShaderInfoLog( shader, 8192, &loglength,infolog );
369 fprintf( stderr, "ERROR: \n%s\n\n", infolog );
370 glDeleteShader( shader );
376 static bool dmCreateProgram( DMProgram program, const char *vertexsource, const char *fragmentsource, char *optionstring )
382 program.glProgram = 0;
383 program.vertexShader = 0;
384 program.fragmentShader = 0;
386 program.vertexShader = dmCreateShader( GL_VERTEX_SHADER, vertexsource, optionstring );
387 if( !( program.vertexShader ) )
389 fprintf(stderr, "ERROR: Unable to load vertex shader\n");
392 program.fragmentShader = dmCreateShader( GL_FRAGMENT_SHADER, fragmentsource, optionstring );
393 if( !( program.fragmentShader ) )
395 fprintf(stderr, "ERROR: Unable to load fragment shader\n");
398 program.glProgram = glCreateProgram();
399 if( !( program.glProgram ) )
401 fprintf(stderr, "ERROR: Unable to create program\n");
405 glAttachShader( program.glProgram, program.vertexShader );
406 glAttachShader( program.glProgram, program.fragmentShader );
408 glBindAttribLocation(program.glProgram, GLBufferContents::vertex, "vertex");
409 glBindAttribLocation(program.glProgram, GLBufferContents::texCoord, "texCoord");
410 glBindAttribLocation(program.glProgram, GLBufferContents::color, "color");
411 glBindAttribLocation(program.glProgram, GLBufferContents::normal, "normal");
413 glLinkProgram( program.glProgram );
414 glGetProgramiv( program.glProgram, GL_LINK_STATUS, &status );
415 if( status != GL_TRUE )
417 fprintf( stderr, "ERROR, failed to link shader program\n" );
418 glGetProgramInfoLog( program.glProgram, 8192, &loglength, infolog );
419 fprintf( stderr, "ERROR: \n%s\n\n", infolog );
423 // glUseProgram( program.glProgram );
425 program.matrixloc = glGetUniformLocation( program.glProgram, "uniMatrix" );
426 program.vertexloc = glGetAttribLocation( program.glProgram, "inVertex" );
427 program.texcoord0loc = glGetAttribLocation( program.glProgram, "inTexcoord0" );
428 program.texcoord1loc = glGetAttribLocation( program.glProgram, "inTexcoord1" );
429 program.colorloc = glGetAttribLocation( program.glProgram, "inColor" );
430 #if DM_ENABLE_EXT_COLOR
431 program.extcolorloc = glGetAttribLocation( program.glProgram, "inExtColor" );
433 program.texbaseloc = glGetUniformLocation( program.glProgram, "texBase" );
434 program.flags.valid = true;
439 if( program.fragmentShader )
440 glDeleteShader( program.fragmentShader );
441 if( program.vertexShader )
442 glDeleteShader( program.vertexShader );
443 if( program.glProgram )
444 glDeleteProgram( program.glProgram );
452 const char *dmVertexShaderNormal =
454 "uniform mat4 uniMatrix;\n"
455 "in vec2 inVertex;\n"
456 "in vec2 inTexcoord0;\n"
458 "out vec2 varTexcoord0;\n"
459 "out vec4 varColor;\n"
463 " varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
464 " varColor = inColor;\n"
465 " gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
471 const char *dmFragmentShaderNormal =
473 "uniform sampler2D texBase;\n"
474 "in vec2 varTexcoord0;\n"
475 "in vec4 varColor;\n"
478 " gl_FragColor = varColor * texture2D( texBase, varTexcoord0 );\n"
484 const char *dmVertexShaderAlpha =
486 "uniform mat4 uniMatrix;\n"
487 "in vec2 inVertex;\n"
488 "in vec2 inTexcoord0;\n"
490 "out vec2 varTexcoord0;\n"
491 "out vec4 varColor;\n"
495 " varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
496 " varColor = inColor;\n"
497 " gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
503 const char *dmFragmentShaderAlpha =
505 "uniform sampler2D texBase;\n"
506 "in vec2 varTexcoord0;\n"
507 "in vec4 varColor;\n"
510 " gl_FragColor = vec4( varColor.rgb, varColor.a * texture2D( texBase, varTexcoord0 ).r );\n"
515 const char *dmVertexShaderAlphaIntensity =
517 "uniform mat4 uniMatrix;\n"
518 "in vec2 inVertex;\n"
519 "in vec2 inTexcoord0;\n"
521 "out vec2 varTexcoord0;\n"
522 "out vec4 varColor;\n"
526 " varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
527 " varColor = inColor;\n"
528 " gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
534 const char *dmFragmentShaderAlphaIntensity =
536 "uniform sampler2D texBase;\n"
537 "in vec2 varTexcoord0;\n"
538 "in vec4 varColor;\n"
542 " tex = texture2D( texBase, varTexcoord0 ).rg;\n"
543 " gl_FragColor = vec4( varColor.rgb * tex.g, varColor.a * tex.r );\n"
548 const char *dmVertexShaderAlphaIntensityExtColor =
550 "uniform mat4 uniMatrix;\n"
551 "in vec2 inVertex;\n"
552 "in vec2 inTexcoord0;\n"
554 "in vec4 inExtColor;\n"
555 "out vec2 varTexcoord0;\n"
556 "out vec4 varColor;\n"
557 "out vec4 varExtColor;\n"
561 " varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
562 " varColor = inColor;\n"
563 " varExtColor = inExtColor;\n"
564 " gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
570 const char *dmFragmentShaderAlphaIntensityExtColor =
572 "uniform sampler2D texBase;\n"
573 "in vec2 varTexcoord0;\n"
574 "in vec4 varColor;\n"
575 "in vec4 varExtColor;\n"
579 " tex = texture2D( texBase, varTexcoord0 ).rg;\n"
580 " gl_FragColor = vec4( mix( varExtColor.rgb, varColor.rgb, tex.g ), mix( varExtColor.a, varColor.a, tex.g ) * tex.r );\n"
588 static void matrixOrtho( float *m, float left, float right, float bottom, float top, float nearval, float farval )
590 float x = 2.0f / ( right - left );
591 float y = 2.0f / ( top - bottom );
592 float z = -2.0f / ( farval - nearval );
593 float tx = -( right + left ) / ( right - left );
594 float ty = -( top + bottom ) / ( top - bottom );
595 float tz = -( farval + nearval ) / ( farval - nearval );
597 #define M(row,col) m[col*4+row]
598 M(0,0) = x; M(0,1) = 0.0; M(0,2) = 0.0; M(0,3) = tx;
599 M(1,0) = 0.0; M(1,1) = y; M(1,2) = 0.0; M(1,3) = ty;
600 M(2,0) = 0.0; M(2,1) = 0.0; M(2,2) = z; M(2,3) = tz;
601 M(3,0) = 0.0; M(3,1) = 0.0; M(3,2) = 0.0; M(3,3) = 1.0;
608 /* FIXME: Radix sort, not hybrid sort! */
610 static inline int dmSortImagesCmp( DMImageBuffer *draw0, DMImageBuffer *draw1 )
612 return ( ( draw0->orderindex < draw1->orderindex ) ? 0 : 1 );
615 #define HSORT_MAIN dmSortImages
616 #define HSORT_CMP dmSortImagesCmp
617 #define HSORT_TYPE DMImageBuffer
618 #include "cchybridsort.h"
626 // TOFIX: Make this private, have a property
627 public class DrawManagerFlags : uint32 { public: bool prehistoricOpenGL:1; }
629 public class DrawManager
631 DrawManagerFlags flags;
636 int imageBufferCount;
638 DMImageBuffer *imageBuffer;
639 DMImageBuffer *imageBufferTmp;
641 // Buffers for drawimages() batching
642 DMDrawBuffer drawBuffer[DM_CONTEXT_DRAW_BUFFER_COUNT];
644 int drawBarrierIndex;
645 uint32 orderBarrierMask;
647 // Counter to track program uniforms and such
650 DMProgram shaderPrograms[DM_PROGRAM_COUNT];
653 bool renderingFlipped;
655 static DMProgram *flushUseProgram( int programIndex )
657 DMProgram *program = &shaderPrograms[ programIndex ];
658 if( !program->flags.valid)
667 glUseProgram( program->glProgram );
669 if( program->lastUpdateCount != this.updateCount )
672 glUniformMatrix4fv( program->matrixloc, 1, GL_FALSE, this.matrix );
673 glUniform1i( program->texbaseloc, 0 );
675 program->lastUpdateCount = this.updateCount;
680 #if !defined(__EMSCRIPTEN__)
681 static void flushRenderDrawBufferArchaic( DMDrawBuffer drawBuffer, DMProgram program, int vertexCount )
683 glEnable( GL_TEXTURE_2D );
684 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer.vbo );
685 glColor3f( 1.0, 1.0, 1.0 );
687 glEnableClientState( GL_VERTEX_ARRAY );
688 glEnableClientState( GL_TEXTURE_COORD_ARRAY );
689 glEnableClientState( GL_COLOR_ARRAY );
691 glVertexPointer( 2, GL_FLOAT, sizeof(DMDrawVertexFlat), (void *)OFFSET(DMDrawVertexFlat,vertex) );
692 glTexCoordPointer( 2, GL_FLOAT, sizeof(DMDrawVertexFlat), (void *)OFFSET(DMDrawVertexFlat,texcoord0) );
693 glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(DMDrawVertexFlat), (void *)OFFSET(DMDrawVertexFlat,color) );
695 glDrawArrays( GL_TRIANGLES, 0, vertexCount );
697 glDisableClientState( GL_VERTEX_ARRAY );
698 glDisableClientState( GL_TEXTURE_COORD_ARRAY );
699 glDisableClientState( GL_COLOR_ARRAY );
700 glDisable( GL_TEXTURE_2D );
702 #if DM_FLUSH_EACH_RENDER_DRAW_BUFFER
707 void flushDrawImagesArchaic( )
709 bool flushflag, stateBlend;
710 int index, vertexCount, programIndex;
711 float vx0, vx1, vx2, vx3, vy0, vy1, vy2, vy3;
712 #if DM_ENABLE_IMAGE_ROTATION
713 float angsin, angcos, sizex, sizey;
715 float tx0, tx1, ty0, ty1;
716 DMImageBuffer *imageBuffer;
717 DMImage *image, *bindimage;
718 Texture texture, bindTexture;
719 DMDrawBuffer *drawBuffer;
720 DMDrawVertexFlat *vboVertex = null;
721 #if defined(_GLES) || defined(_GLES2)
722 DMDrawVertexFlat *vboStorage = null;
728 drawBarrierIndex = 0;
729 orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;
732 // Sort by image type and texture, minimize state changes
733 dmSortImages( this.imageBuffer, imageBufferTmp, imageBufferCount, (uint32)( (intptr_t)this.imageBuffer >> 4 ) );
735 // Fill a drawBuffer, write vertex and texcoords
736 drawBuffer = &this.drawBuffer[drawBufferIndex];
737 drawBufferIndex = ( drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
738 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
739 #if defined(_GLES) || defined(_GLES2)
740 vboVertex = vboStorage = new DMDrawVertexFlat[drawBuffer->vertexAlloc * 1];
742 vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
746 glActiveTexture( GL_TEXTURE0 );
747 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
748 glDisable( GL_BLEND );
749 GLSetupLighting(false);
751 #if DM_RENDER_IMAGE_DEBUG
752 printf( " Flush %d images\n", (int)imageBufferCount );
760 imageBuffer = this.imageBuffer;
761 for( index = 0 ; index < imageBufferCount ; index++, imageBuffer++ )
763 image = imageBuffer->image;
764 texture = image->texture;
767 if( image != bindimage )
769 if( stateBlend != image->flags.blending )
771 if( texture != bindTexture )
774 if( vertexCount >= ( drawBuffer->vertexAlloc - 6 ) )
781 #if defined(_GLES) || defined(_GLES2)
782 glBufferData( GL_ARRAY_BUFFER, drawBuffer->vertexAlloc * sizeof(DMDrawVertexFlat), vboStorage, GL_DYNAMIC_DRAW );
784 glUnmapBuffer( GL_ARRAY_BUFFER );
786 // Flush font manager texture updates
788 // Render buffered images
789 flushRenderDrawBufferArchaic( drawBuffer, program, vertexCount );
790 drawBuffer = &this.drawBuffer[drawBufferIndex];
791 drawBufferIndex = ( drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
792 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
793 #if defined(_GLES) || defined(_GLES2)
794 vboVertex = vboStorage;
796 vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
801 if( stateBlend != ( image->flags.blending ) )
803 stateBlend = image->flags.blending;
804 ( stateBlend ? glEnable : glDisable )( GL_BLEND );
805 #if DM_RENDER_IMAGE_DEBUG
806 printf( " Switch blending %d\n", stateBlend != false );
809 if( programIndex != image->programIndex )
811 programIndex = image->programIndex;
812 program = flushUseProgram( programIndex );
814 if( texture != bindTexture )
816 bindTexture = texture;
817 glBindTexture( GL_TEXTURE_2D, bindTexture.glTex );
818 #if DM_RENDER_IMAGE_DEBUG
819 printf( " Switch to texture 0x%x\n", (int)texture.orderMask );
825 #if DM_RENDER_IMAGE_DEBUG
826 printf( " Render image at %d %d, order 0x%x, texture %p\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex, texture );
829 #if DM_ENABLE_IMAGE_ROTATION
830 angsin = (float)imageBuffer->angsin * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
831 angcos = (float)imageBuffer->angcos * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
832 sizex = (float)imageBuffer->sizex;
833 sizey = (float)imageBuffer->sizey;
834 vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
835 vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
836 vx1 = vx0 + ( angcos * sizex );
837 vy1 = vy0 + ( angsin * sizex );
838 vx2 = vx0 - ( angsin * sizey );
839 vy2 = vy0 + ( angcos * sizey );
840 vx3 = vx0 + ( angcos * sizex ) - ( angsin * sizey );
841 vy3 = vy0 + ( angsin * sizex ) + ( angcos * sizey );
843 vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
844 vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
845 vx3 = vx0 + (float)( imageBuffer->sizex );
846 vy3 = vy0 + (float)( imageBuffer->sizey );
853 tx0 = (float)( image->srcx ) * texture.widthinv;
854 ty0 = (float)( image->srcy ) * texture.heightinv;
855 tx1 = (float)( image->srcx + image->sizex ) * texture.widthinv;
856 ty1 = (float)( image->srcy + image->sizey ) * texture.heightinv;
859 vboVertex[0].vertex[0] = vx3;
860 vboVertex[0].vertex[1] = vy3;
861 vboVertex[0].texcoord0[0] = tx1;
862 vboVertex[0].texcoord0[1] = ty1;
863 vboVertex[0].color = imageBuffer->color;
864 #if DM_ENABLE_EXT_COLOR
865 vboVertex[0].extcolor = imageBuffer->extcolor;
867 vboVertex[1].vertex[0] = vx1;
868 vboVertex[1].vertex[1] = vy1;
869 vboVertex[1].texcoord0[0] = tx1;
870 vboVertex[1].texcoord0[1] = ty0;
871 vboVertex[1].color = imageBuffer->color;
872 #if DM_ENABLE_EXT_COLOR
873 vboVertex[1].extcolor = imageBuffer->extcolor;
875 vboVertex[2].vertex[0] = vx2;
876 vboVertex[2].vertex[1] = vy2;
877 vboVertex[2].texcoord0[0] = tx0;
878 vboVertex[2].texcoord0[1] = ty1;
879 vboVertex[2].color = imageBuffer->color;
880 #if DM_ENABLE_EXT_COLOR
881 vboVertex[2].extcolor = imageBuffer->extcolor;
883 vboVertex[3].vertex[0] = vx0;
884 vboVertex[3].vertex[1] = vy0;
885 vboVertex[3].texcoord0[0] = tx0;
886 vboVertex[3].texcoord0[1] = ty0;
887 vboVertex[3].color = imageBuffer->color;
888 #if DM_ENABLE_EXT_COLOR
889 vboVertex[3].extcolor = imageBuffer->extcolor;
891 vboVertex[4].vertex[0] = vx2;
892 vboVertex[4].vertex[1] = vy2;
893 vboVertex[4].texcoord0[0] = tx0;
894 vboVertex[4].texcoord0[1] = ty1;
895 vboVertex[4].color = imageBuffer->color;
896 #if DM_ENABLE_EXT_COLOR
897 vboVertex[4].extcolor = imageBuffer->extcolor;
899 vboVertex[5].vertex[0] = vx1;
900 vboVertex[5].vertex[1] = vy1;
901 vboVertex[5].texcoord0[0] = tx1;
902 vboVertex[5].texcoord0[1] = ty0;
903 vboVertex[5].color = imageBuffer->color;
904 #if DM_ENABLE_EXT_COLOR
905 vboVertex[5].extcolor = imageBuffer->extcolor;
912 #if defined(_GLES) || defined(_GLES2) // TODO:
913 glBufferData( GL_ARRAY_BUFFER, drawBuffer->vertexAlloc * sizeof(DMDrawVertexFlat), vboStorage, GL_DYNAMIC_DRAW );
916 glUnmapBuffer( GL_ARRAY_BUFFER );
919 // Flush font manager texture updates
922 // Render buffered images
923 flushRenderDrawBufferArchaic( drawBuffer, program, vertexCount );
924 imageBufferCount = 0;
933 static void flushRenderDrawBuffer( DMDrawBuffer drawBuffer, DMProgram program, int vertexCount )
935 glabCurArrayBuffer = 0;
937 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer.vbo );
938 if( program.vertexloc != -1 )
940 glEnableVertexAttribArray( program.vertexloc );
941 glVertexAttribPointer( program.vertexloc, 2, GL_SHORT, GL_FALSE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,vertex) );
943 if( program.texcoord0loc != -1 )
945 glEnableVertexAttribArray( program.texcoord0loc );
946 glVertexAttribPointer( program.texcoord0loc, 2, GL_SHORT, GL_FALSE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,texcoord0) );
948 if( program.colorloc != -1 )
950 glEnableVertexAttribArray( program.colorloc );
951 glVertexAttribPointer( program.colorloc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,color) );
954 #if DM_ENABLE_EXT_COLOR
955 if( program.extcolorloc != -1 )
957 glEnableVertexAttribArray( program.extcolorloc );
958 glVertexAttribPointer( program.extcolorloc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,extcolor) );
962 glDrawArrays( GL_TRIANGLES, 0, vertexCount );
964 if( program.vertexloc != -1 )
965 glDisableVertexAttribArray( program.vertexloc );
966 if( program.texcoord0loc != -1 )
967 glDisableVertexAttribArray( program.texcoord0loc );
968 if( program.colorloc != -1 )
969 glDisableVertexAttribArray( program.colorloc );
971 #if DM_FLUSH_EACH_RENDER_DRAW_BUFFER
978 static void flushDrawImages( )
980 int index, stateblend, vertexcount, flushflag, programIndex;
981 float vx0, vx1, vx2, vx3, vy0, vy1, vy2, vy3;
982 #if DM_ENABLE_IMAGE_ROTATION
983 float angsin, angcos, sizex, sizey;
985 float tx0, tx1, ty0, ty1;
986 DMImageBuffer *imageBuffer;
987 DMImage *image, *bindimage;
988 Texture texture, bindtexture;
989 DMDrawBuffer *drawBuffer;
990 DMDrawVertex *vboVertex = null;
993 glabCurArrayBuffer = 0;
997 this.drawBarrierIndex = 0;
998 orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;
999 if( imageBufferCount )
1001 /* Sort by image type and texture, minimize state changes */
1002 dmSortImages( this.imageBuffer, this.imageBufferTmp, imageBufferCount, (uint32)( (uintptr)this.imageBuffer >> 4 ) );
1004 /* Fill a drawBuffer, write vertex and texcoords */
1005 drawBuffer = &this.drawBuffer[this.drawBufferIndex];
1006 this.drawBufferIndex = ( this.drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
1007 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
1009 #if !defined(_GLES) && !defined(_GLES2) // TODO:
1010 vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
1014 glActiveTexture( GL_TEXTURE0 );
1015 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1016 glDisable( GL_BLEND );
1018 #if DM_RENDER_IMAGE_DEBUG
1019 printf( " Flush %d images\n", (int)imageBufferCount );
1027 imageBuffer = this.imageBuffer;
1028 for( index = 0 ; index < imageBufferCount ; index++, imageBuffer++ )
1030 image = imageBuffer->image;
1031 texture = image->texture;
1034 if( image != bindimage )
1036 if( stateblend != ( image->flags.blending ) )
1038 if( texture != bindtexture )
1041 if( vertexcount >= ( drawBuffer->vertexAlloc - 6 ) )
1048 #if !defined(_GLES) && !defined(_GLES2) // TODO:
1049 glUnmapBuffer( GL_ARRAY_BUFFER );
1051 // Flush font manager texture updates
1054 // Render buffered images
1055 flushRenderDrawBuffer( drawBuffer, program, vertexcount );
1056 drawBuffer = &this.drawBuffer[this.drawBufferIndex];
1057 this.drawBufferIndex = ( this.drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
1058 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
1059 #if !defined(_GLES) && !defined(_GLES2) // TODO:
1060 vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
1065 if( stateblend != ( image->flags.blending ) )
1067 stateblend = image->flags.blending;
1068 ( stateblend ? glEnable : glDisable )( GL_BLEND );
1069 #if DM_RENDER_IMAGE_DEBUG
1070 printf( " Switch blending %d\n", ( stateblend != 0 ) );
1073 if( programIndex != image->programIndex )
1075 programIndex = image->programIndex;
1076 program = flushUseProgram( programIndex );
1078 if( texture != bindtexture )
1080 bindtexture = texture;
1081 glBindTexture( GL_TEXTURE_2D, bindtexture.glTex );
1082 #if DM_RENDER_IMAGE_DEBUG
1083 printf( " Switch to texture 0x%x\n", (int)texture.orderMask );
1089 #if DM_RENDER_IMAGE_DEBUG
1090 printf( " Render image at %d %d, order 0x%x, texture %p\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex, texture );
1093 #if DM_ENABLE_IMAGE_ROTATION
1094 /* FIXME TODO: Don't go through float, compute texcoord integers directly */
1095 angsin = (float)imageBuffer->angsin * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
1096 angcos = (float)imageBuffer->angcos * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
1097 sizex = (float)imageBuffer->sizex;
1098 sizey = (float)imageBuffer->sizey;
1099 vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
1100 vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
1101 vx1 = vx0 + ( angcos * sizex );
1102 vy1 = vy0 + ( angsin * sizex );
1103 vx2 = vx0 - ( angsin * sizey );
1104 vy2 = vy0 + ( angcos * sizey );
1105 vx3 = vx0 + ( angcos * sizex ) - ( angsin * sizey );
1106 vy3 = vy0 + ( angsin * sizex ) + ( angcos * sizey );
1108 /* FIXME TODO: Don't go through float, compute texcoord integers directly */
1109 vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
1110 vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
1111 vx3 = vx0 + (float)( imageBuffer->sizex );
1112 vy3 = vy0 + (float)( imageBuffer->sizey );
1119 /* FIXME TODO: Don't go through float, compute texcoord integers directly */
1120 tx0 = (float)( image->srcx ) * texture.widthinv;
1121 ty0 = (float)( image->srcy ) * texture.heightinv;
1122 tx1 = (float)( image->srcx + image->sizex ) * texture.widthinv;
1123 ty1 = (float)( image->srcy + image->sizey ) * texture.heightinv;
1125 /* Write data to VBO */
1126 /* TODO: write vertex/texcoord all at once with SSE */
1127 vboVertex[0].vertex[0] = (short)( vx3 * DM_VERTEX_NORMFACTOR );
1128 vboVertex[0].vertex[1] = (short)( vy3 * DM_VERTEX_NORMFACTOR );
1129 vboVertex[0].texcoord0[0] = (short)( tx1 * DM_TEXCOORD_NORMFACTOR );
1130 vboVertex[0].texcoord0[1] = (short)( ty1 * DM_TEXCOORD_NORMFACTOR );
1131 vboVertex[0].color = imageBuffer->color;
1132 vboVertex[0].extcolor = imageBuffer->extcolor;
1133 vboVertex[1].vertex[0] = (short)( vx1 * DM_VERTEX_NORMFACTOR );
1134 vboVertex[1].vertex[1] = (short)( vy1 * DM_VERTEX_NORMFACTOR );
1135 vboVertex[1].texcoord0[0] = (short)( tx1 * DM_TEXCOORD_NORMFACTOR );
1136 vboVertex[1].texcoord0[1] = (short)( ty0 * DM_TEXCOORD_NORMFACTOR );
1137 vboVertex[1].color = imageBuffer->color;
1138 vboVertex[1].extcolor = imageBuffer->extcolor;
1139 vboVertex[2].vertex[0] = (short)( vx2 * DM_VERTEX_NORMFACTOR );
1140 vboVertex[2].vertex[1] = (short)( vy2 * DM_VERTEX_NORMFACTOR );
1141 vboVertex[2].texcoord0[0] = (short)( tx0 * DM_TEXCOORD_NORMFACTOR );
1142 vboVertex[2].texcoord0[1] = (short)( ty1 * DM_TEXCOORD_NORMFACTOR );
1143 vboVertex[2].color = imageBuffer->color;
1144 vboVertex[2].extcolor = imageBuffer->extcolor;
1145 vboVertex[3].vertex[0] = (short)( vx0 * DM_VERTEX_NORMFACTOR );
1146 vboVertex[3].vertex[1] = (short)( vy0 * DM_VERTEX_NORMFACTOR );
1147 vboVertex[3].texcoord0[0] = (short)( tx0 * DM_TEXCOORD_NORMFACTOR );
1148 vboVertex[3].texcoord0[1] = (short)( ty0 * DM_TEXCOORD_NORMFACTOR );
1149 vboVertex[3].color = imageBuffer->color;
1150 vboVertex[3].extcolor = imageBuffer->extcolor;
1151 vboVertex[4].vertex[0] = (short)( vx2 * DM_VERTEX_NORMFACTOR );
1152 vboVertex[4].vertex[1] = (short)( vy2 * DM_VERTEX_NORMFACTOR );
1153 vboVertex[4].texcoord0[0] = (short)( tx0 * DM_TEXCOORD_NORMFACTOR );
1154 vboVertex[4].texcoord0[1] = (short)( ty1 * DM_TEXCOORD_NORMFACTOR );
1155 vboVertex[4].color = imageBuffer->color;
1156 vboVertex[4].extcolor = imageBuffer->extcolor;
1157 vboVertex[5].vertex[0] = (short)( vx1 * DM_VERTEX_NORMFACTOR );
1158 vboVertex[5].vertex[1] = (short)( vy1 * DM_VERTEX_NORMFACTOR );
1159 vboVertex[5].texcoord0[0] = (short)( tx1 * DM_TEXCOORD_NORMFACTOR );
1160 vboVertex[5].texcoord0[1] = (short)( ty0 * DM_TEXCOORD_NORMFACTOR );
1161 vboVertex[5].color = imageBuffer->color;
1162 vboVertex[5].extcolor = imageBuffer->extcolor;
1168 #if !defined(_GLES) && !defined(_GLES2) // TODO:
1169 glUnmapBuffer( GL_ARRAY_BUFFER );
1171 // Flush font manager texture updates
1173 // Render buffered images
1174 flushRenderDrawBuffer( drawBuffer, program, vertexcount );
1175 imageBufferCount = 0;
1184 property bool renderingFlipped { set { renderingFlipped = value; } }
1186 virtual void flush();
1188 bool init( DrawManagerFlags flags )
1190 int drawBufferIndex;
1191 DMDrawBuffer *drawBuffer;
1194 imageBufferCount = 0;
1195 imageBufferSize = 4096;
1196 imageBuffer = new DMImageBuffer[imageBufferSize];
1197 imageBufferTmp = new DMImageBuffer[imageBufferSize];
1201 if( flags.prehistoricOpenGL )
1202 vertexSize = sizeof(DMDrawVertexFlat);
1208 for( programIndex = 0 ; programIndex < DM_PROGRAM_COUNT ; programIndex++ )
1210 program = &shaderPrograms[ programIndex ];
1212 program->lastUpdateCount = -1;
1214 program = &shaderPrograms[ DM_PROGRAM_NORMAL ];
1215 if( !( dmCreateProgram( program, dmVertexShaderNormal, dmFragmentShaderNormal, 0 ) ) )
1217 program = &shaderPrograms[ DM_PROGRAM_ALPHABLEND ];
1218 if( !( dmCreateProgram( program, dmVertexShaderAlpha, dmFragmentShaderAlpha, 0 ) ) )
1220 program = &shaderPrograms[ DM_PROGRAM_ALPHABLEND_INTENSITY ];
1221 if( !( dmCreateProgram( program, dmVertexShaderAlphaIntensity, dmFragmentShaderAlphaIntensity, 0 ) ) )
1223 program = &shaderPrograms[ DM_PROGRAM_ALPHABLEND_INTENSITY_EXTCOLOR ];
1224 if( !( dmCreateProgram( program, dmVertexShaderAlphaIntensityExtColor, dmFragmentShaderAlphaIntensityExtColor, 0 ) ) )
1226 // glUseProgram( 0 );
1227 vertexSize = sizeof(DMDrawVertex);
1231 for( drawBufferIndex = 0 ; drawBufferIndex < DM_CONTEXT_DRAW_BUFFER_COUNT ; drawBufferIndex++ )
1233 drawBuffer = &this.drawBuffer[drawBufferIndex];
1234 drawBuffer->glType = GL_FLOAT;
1235 drawBuffer->vertexCount = 0;
1236 drawBuffer->vertexAlloc = DM_CONTEXT_DRAW_BUFFER_VERTEX_ALLOC;
1239 glGenBuffers( 1, &drawBuffer->vbo );
1240 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
1241 glBufferData( GL_ARRAY_BUFFER, drawBuffer->vertexAlloc * vertexSize, 0, GL_DYNAMIC_DRAW );
1243 drawBuffer->vertexBuffer = new byte[drawBuffer->vertexAlloc * vertexSize];
1248 glabCurArrayBuffer = 0;
1262 for( i = 0 ; i < DM_CONTEXT_DRAW_BUFFER_COUNT ; i++ )
1264 DMDrawBuffer *db = &drawBuffer[i];
1266 glDeleteBuffers( 1, &db->vbo );
1267 delete db->vertexBuffer;
1270 // TODO: Destroy the shaders!
1272 delete imageBufferTmp;
1275 void ready( int viewportwidth, int viewportheight )
1280 if(!flags.prehistoricOpenGL && !prevProgram)
1281 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *)&prevProgram);
1283 // while(glGetError());
1287 // Save OpenGL state
1288 // FIXME: no glPushAttrib() in core profile
1289 #if !defined(_GLES) && !defined(_GLES2) // TODO:
1290 glPushClientAttrib( GL_CLIENT_ALL_ATTRIB_BITS );
1291 glPushAttrib( GL_ALL_ATTRIB_BITS );
1294 // Prepare rendering pass
1295 if(renderingFlipped)
1296 matrixOrtho( matrix, 0.0, (float)viewportwidth, 0.0, (float)viewportheight, -1.0f, 1.0 );
1298 matrixOrtho( matrix, 0.0, (float)viewportwidth, (float)viewportheight, 0.0, -1.0f, 1.0 );
1299 norminv = 1.0f / DM_VERTEX_NORMFACTOR;
1300 for( mindex = 0 ; mindex < 12 ; mindex += 4 )
1302 matrix[mindex+0] *= norminv;
1303 matrix[mindex+1] *= norminv;
1304 matrix[mindex+2] *= norminv;
1306 drawBarrierIndex = 0;
1307 orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;
1308 orderBarrierMask = 0;
1312 if(flags.prehistoricOpenGL)
1314 glMatrixMode(MatrixMode::projection);
1315 glLoadMatrixf(matrix);
1317 glMatrixMode(MatrixMode::modelView);
1323 void drawImage( DMImage image, int offsetx, int offsety, int sizex, int sizey, uint32 color )
1325 DMImageBuffer *imageBuffer;
1327 if( image.flags.empty || ( sizex <= 0 ) || ( sizey <= 0 ) )
1330 if( imageBufferCount >= imageBufferSize )
1332 imageBufferSize <<= 1;
1333 this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
1334 imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
1337 imageBuffer = &this.imageBuffer[ imageBufferCount ];
1338 imageBuffer->image = image;
1339 imageBuffer->offsetx = (short)(offsetx << DM_VERTEX_NORMSHIFT);
1340 imageBuffer->offsety = (short)(offsety << DM_VERTEX_NORMSHIFT);
1341 imageBuffer->sizex = (short)sizex;
1342 imageBuffer->sizey = (short)sizey;
1343 #if DM_ENABLE_IMAGE_ROTATION
1344 imageBuffer->angsin = 0;
1345 imageBuffer->angcos = (short)DM_IMAGE_ROTATION_NORMFACTOR;
1347 imageBuffer->color = color;
1348 imageBuffer->orderindex = image.orderMask | orderBarrierMask;
1350 #if DM_RENDER_IMAGE_DEBUG
1351 printf( " Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
1357 void drawImageExtColor( DMImage image, int offsetx, int offsety, int sizex, int sizey, uint32 color, uint32 extcolor )
1359 DMImageBuffer *imageBuffer;
1361 if( ( image.flags.empty ) || ( sizex <= 0 ) || ( sizey <= 0 ) )
1364 if( imageBufferCount >= imageBufferSize )
1366 imageBufferSize <<= 1;
1367 this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
1368 imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
1371 imageBuffer = &this.imageBuffer[ imageBufferCount ];
1372 imageBuffer->image = image;
1373 imageBuffer->offsetx = (short)(offsetx << DM_VERTEX_NORMSHIFT);
1374 imageBuffer->offsety = (short)(offsety << DM_VERTEX_NORMSHIFT);
1375 imageBuffer->sizex = (short)sizex;
1376 imageBuffer->sizey = (short)sizey;
1377 #if DM_ENABLE_IMAGE_ROTATION
1378 imageBuffer->angsin = 0;
1379 imageBuffer->angcos = (short)DM_IMAGE_ROTATION_NORMFACTOR;
1381 imageBuffer->color = color;
1382 #if DM_ENABLE_EXT_COLOR
1383 imageBuffer->extcolor = extcolor;
1385 imageBuffer->orderindex = image.orderMask | orderBarrierMask;
1387 #if DM_RENDER_IMAGE_DEBUG
1388 printf( " Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
1391 this.imageBufferCount++;
1394 void drawImageFloat( DMImage image, float offsetx, float offsety, float sizex, float sizey, float angsin, float angcos, uint32 color )
1396 DMImageBuffer *imageBuffer;
1398 if( image.flags.empty || sizex <= 0 || sizey <= 0 )
1401 if( imageBufferCount >= imageBufferSize )
1403 imageBufferSize <<= 1;
1404 this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
1405 imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
1408 imageBuffer = &this.imageBuffer[ imageBufferCount ];
1409 imageBuffer->image = image;
1410 imageBuffer->offsetx = (short)roundf(offsetx * DM_VERTEX_NORMFACTOR);
1411 imageBuffer->offsety = (short)roundf(offsety * DM_VERTEX_NORMFACTOR);
1412 imageBuffer->sizex = (short)sizex;
1413 imageBuffer->sizey = (short)sizey;
1414 #if DM_ENABLE_IMAGE_ROTATION
1415 imageBuffer->angsin = (short)roundf( angsin * DM_IMAGE_ROTATION_NORMFACTOR );
1416 imageBuffer->angcos = (short)roundf( angcos * DM_IMAGE_ROTATION_NORMFACTOR );
1418 imageBuffer->color = color;
1419 imageBuffer->orderindex = image.orderMask | orderBarrierMask;
1421 #if DM_RENDER_IMAGE_DEBUG
1422 printf( " Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
1428 void drawImageFloatExtColor( DMImage image, float offsetx, float offsety, float sizex, float sizey, float angsin, float angcos, uint32 color, uint32 extcolor )
1430 DMImageBuffer *imageBuffer;
1432 if( ( image.flags.empty ) || ( sizex <= 0 ) || ( sizey <= 0 ) )
1435 if( this.imageBufferCount >= this.imageBufferSize )
1437 imageBufferSize <<= 1;
1438 this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
1439 imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
1442 imageBuffer = &this.imageBuffer[ imageBufferCount ];
1443 imageBuffer->image = image;
1444 imageBuffer->offsetx = (short)roundf( offsetx * DM_VERTEX_NORMFACTOR );
1445 imageBuffer->offsety = (short)roundf( offsety * DM_VERTEX_NORMFACTOR );
1446 imageBuffer->sizex = (short)sizex;
1447 imageBuffer->sizey = (short)sizey;
1448 #if DM_ENABLE_IMAGE_ROTATION
1449 imageBuffer->angsin = (short)roundf( angsin * DM_IMAGE_ROTATION_NORMFACTOR );
1450 imageBuffer->angcos = (short)roundf( angcos * DM_IMAGE_ROTATION_NORMFACTOR );
1452 imageBuffer->color = color;
1453 #if DM_ENABLE_EXT_COLOR
1454 imageBuffer->extcolor = extcolor;
1456 imageBuffer->orderindex = image.orderMask | orderBarrierMask;
1458 #if DM_RENDER_IMAGE_DEBUG
1459 printf( " Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
1462 this.imageBufferCount++;
1467 #if !defined(_GLES2)
1468 if(flags.prehistoricOpenGL)
1469 flushDrawImagesArchaic();
1472 #if defined(SHADERS)
1473 if(!flags.prehistoricOpenGL)
1483 glBindBuffer( GL_ARRAY_BUFFER, 0 );
1484 glabCurArrayBuffer = 0;
1486 if( !flags.prehistoricOpenGL )
1487 glUseProgram( prevProgram );
1489 // Restore OpenGL state
1490 // FIXME: no glPushAttrib() in core profile
1491 #if !defined(_GLES) && !defined(_GLES2) // TODO:
1493 glPopClientAttrib();
1500 if( drawBarrierIndex >= ( 1 << DM_BARRIER_ORDER_BITS ) )
1502 orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;
1507 imageBufferCount = 0;