1 import "OpenGLDisplayDriver"
13 #if defined(__EMSCRIPTEN__)
17 #include <GLES2/gl2.h>
20 #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
22 //# include "gl_core_3_3.h"
23 # include "gl_compat_4_4.h" // FIXME: no glPushAttrib() in core profile
25 # include "gl_compat_4_4.h"
31 #undef glEnableClientState
32 #undef glDisableClientState
33 #undef GL_VERTEX_ARRAY
34 #undef GL_NORMAL_ARRAY
35 #undef GL_TEXTURE_COORD_ARRAY
37 #undef glVertexPointer
38 #undef glTexCoordPointer
41 #define glEnableClientState glEnableVertexAttribArray
42 #define glDisableClientState glDisableVertexAttribArray
43 #define GL_VERTEX_ARRAY GLBufferContents::vertex
44 #define GL_NORMAL_ARRAY GLBufferContents::normal
45 #define GL_TEXTURE_COORD_ARRAY GLBufferContents::texCoord
46 #define GL_COLOR_ARRAY GLBufferContents::color
47 #define glVertexPointer(n, t, s, p) glVertexAttribPointer(GLBufferContents::vertex, n, t, GL_FALSE, s, p)
48 #define glTexCoordPointer(n, t, s, p) glVertexAttribPointer(GLBufferContents::texCoord, n, t, GL_FALSE, s, p)
49 #define glColorPointer(n, t, s, p) glVertexAttribPointer(GLBufferContents::color, n, t, GL_FALSE, s, p)
53 #if defined(ES1_1) || defined(ES2) || defined(SHADERS)
90 #undef glColorMaterial
93 #define glRecti glimtkRecti
94 #define glBegin glimtkBegin
95 #define glTexCoord2i glimtkTexCoord2i
96 #define glVertex2i glimtkVertex2i
97 #define glTexCoord2d glimtkTexCoord2d
98 #define glVertex2d glimtkVertex2d
99 #define glTexCoord2f glimtkTexCoord2f
100 #define glVertex2f glimtkVertex2f
101 #define glEnd glimtkEnd
102 #define glColor3f glimtkColor3f
103 #define glColor4ub glimtkColor4ub
104 #define glColor4fv glimtkColor4fv
105 #define glNormal3fv glimtkNormal3fv
106 #define glNormal3f glimtkNormal3f
107 #define glTexCoord2fv glimtkTexCoord2fv
108 #define glVertex3d glimtkVertex3d
109 #define glVertex3dv glimtkVertex3dv
110 #define glVertex3f glimtkVertex3f
111 #define glVertex3fv glimtkVertex3fv
113 #define glLoadMatrixd glmsLoadMatrixd
114 #define glLoadMatrixf glmsLoadMatrixf
115 #define glMultMatrixd glmsMultMatrixd
116 #define glFrustum glmsFrustum
117 #define glOrtho glmsOrtho
118 #define glScaled glmsScaled
119 #define glScalef glmsScaled
120 #define glTranslated glmsTranslated
121 #define glRotated glmsRotated
122 #define glMatrixMode glmsMatrixMode
123 #define glLoadIdentity glmsLoadIdentity
124 #define glPushMatrix glmsPushMatrix
125 #define glPopMatrix glmsPopMatrix
127 #define glLineStipple glesLineStipple
128 #define glColorMaterial glesColorMaterial
129 #define glLightModeli glesLightModeli
135 #define OFFSET(s, m) ((uint)(uintptr) (&((s *) 0)->m))
137 import "textureManager"
140 #define DM_ENABLE_IMAGE_ROTATION (1)
141 #define DM_ENABLE_EXT_COLOR (1)
145 static struct DMDrawVertexFlat
150 #if DM_ENABLE_EXT_COLOR
153 } __attribute__((aligned(16)));
155 static struct DMDrawVertex
160 #if DM_ENABLE_EXT_COLOR
163 } __attribute__((aligned(16)));
174 class DMProgramFlags : uint { bool valid:1; }
180 GLuint fragmentShader;
186 #if DM_ENABLE_EXT_COLOR
190 DMProgramFlags flags;
191 int64 lastUpdateCount;
194 class DMImageFlags : uint16
196 bool empty:1; // Image is empty, do not draw
197 bool blending:1; // Must draw image with blending
200 public struct DMImage
209 // Computed order for sorted rendering, in defineImage()
215 this = { flags = { empty = true } };
218 void defineImage( Texture texture, int offsetx, int offsety, int sizex, int sizey, bool blending, int programIndex, int layerindex )
220 int ordx = offsetx >> 6;
221 int ordy = offsety >> 6;
222 uint32 orderimage = ccMortonNumber32( ordx, ordy ) & ( ( 1 << DM_IMAGE_ORDER_BITS ) - 1 );
226 srcx = (short)offsetx;
227 srcy = (short)offsety;
228 sizex = (short)sizex;
229 sizey = (short)sizey;
230 programIndex = (short)programIndex;
231 flags = { blending = blending };
232 orderMask = (orderimage << DM_IMAGE_ORDER_SHIFT) |
233 (( blending == true ) << DM_BLEND_ORDER_SHIFT) |
234 (programIndex << DM_PROGRAM_ORDER_SHIFT) |
236 (layerindex << DM_LAYER_ORDER_SHIFT);
248 #if DM_ENABLE_IMAGE_ROTATION
252 #if DM_ENABLE_EXT_COLOR
263 define DM_IMAGE_ORDER_BITS = 8;
264 define DM_BLEND_ORDER_BITS = 1;
265 define DM_PROGRAM_ORDER_BITS = 4;
266 define DM_TEXTURE_ORDER_BITS = 10;
267 define DM_LAYER_ORDER_BITS = 4;
268 define DM_BARRIER_ORDER_BITS = 5;
270 define DM_IMAGE_ORDER_SHIFT = 0;
271 define DM_BLEND_ORDER_SHIFT = DM_IMAGE_ORDER_BITS;
272 define DM_PROGRAM_ORDER_SHIFT = DM_IMAGE_ORDER_BITS+DM_BLEND_ORDER_BITS;
273 define DM_TEXTURE_ORDER_SHIFT = DM_IMAGE_ORDER_BITS+DM_BLEND_ORDER_BITS+DM_PROGRAM_ORDER_BITS;
274 define DM_LAYER_ORDER_SHIFT = DM_IMAGE_ORDER_BITS+DM_BLEND_ORDER_BITS+DM_PROGRAM_ORDER_BITS+DM_TEXTURE_ORDER_BITS;
275 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;
277 define DM_LAYER_COUNT = 1<<DM_LAYER_ORDER_BITS;
278 define DM_PROGRAM_COUNT = 1<<DM_PROGRAM_ORDER_BITS;
280 define DM_CONTEXT_DRAW_BUFFER_COUNT = 64;
281 define DM_CONTEXT_DRAW_BUFFER_VERTEX_ALLOC = 1024;
284 /* Range is from zero to DM_LAYER_COUNT */
305 define DM_LAYER_BOTTOM = DMLayer::DM_LAYER_0_BOTTOM;
306 define DM_LAYER_BELOW = DMLayer::DM_LAYER_3_BELOW;
307 define DM_LAYER_NORMAL = DMLayer::DM_LAYER_6_NORMAL;
308 define DM_LAYER_ABOVE = DMLayer::DM_LAYER_9_ABOVE;
309 define DM_LAYER_TOP = DMLayer::DM_LAYER_15_TOP;
311 define DM_PROGRAM_NORMAL = 0;
312 define DM_PROGRAM_ALPHABLEND = 1;
313 define DM_PROGRAM_ALPHABLEND_INTENSITY = 2;
314 define DM_PROGRAM_ALPHABLEND_INTENSITY_EXTCOLOR = 3;
317 static inline void OpenGLErrorCheck( const char *file, int line )
319 int error = glGetError();
320 if( error != GL_NO_ERROR )
321 printf( "ERROR %d at %s:%d\n", error, file, line );
324 #define ERRORCHECK() OpenGLErrorCheck(__FILE__,__LINE__)
329 // Not using 32767.0 ; overflow when converting to int16 due to floating point crud causes problems
330 #define DM_IMAGE_ROTATION_NORMFACTOR (24576.0f)
332 #define DM_VERTEX_NORMSHIFT (2)
333 #define DM_VERTEX_NORMFACTOR (4.0f)
335 #define DM_TEXCOORD_NORMSHIFT (13)
336 #define DM_TEXCOORD_NORMFACTOR (8192.0 /*f*/)
338 static GLuint dmCreateShader( GLenum type, const char *shadersource, const char *optionstring )
344 const GLchar *sourcearray[2];
346 shader = glCreateShader( type );
350 if( !( optionstring ) )
352 sourcearray[0] = optionstring;
353 sourcearray[1] = shadersource;
354 glShaderSource( shader, 2, sourcearray, NULL );
355 glCompileShader( shader );
356 glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
357 if( status != GL_TRUE )
359 fprintf( stderr, "ERROR: Failed to compile shader\n" );
360 glGetShaderInfoLog( shader, 8192, &loglength,infolog );
361 fprintf( stderr, "ERROR: \n%s\n\n", infolog );
362 glDeleteShader( shader );
369 static bool dmCreateProgram( DMProgram program, const char *vertexsource, const char *fragmentsource, char *optionstring )
375 program.glProgram = 0;
376 program.vertexShader = 0;
377 program.fragmentShader = 0;
379 program.vertexShader = dmCreateShader( GL_VERTEX_SHADER, vertexsource, optionstring );
380 if( !( program.vertexShader ) )
382 fprintf(stderr, "ERROR: Unable to load vertex shader\n");
385 program.fragmentShader = dmCreateShader( GL_FRAGMENT_SHADER, fragmentsource, optionstring );
386 if( !( program.fragmentShader ) )
388 fprintf(stderr, "ERROR: Unable to load fragment shader\n");
391 program.glProgram = glCreateProgram();
392 if( !( program.glProgram ) )
394 fprintf(stderr, "ERROR: Unable to create program\n");
398 glAttachShader( program.glProgram, program.vertexShader );
399 glAttachShader( program.glProgram, program.fragmentShader );
401 glBindAttribLocation(program.glProgram, GLBufferContents::vertex, "vertex");
402 glBindAttribLocation(program.glProgram, GLBufferContents::texCoord, "texCoord");
403 glBindAttribLocation(program.glProgram, GLBufferContents::color, "color");
404 glBindAttribLocation(program.glProgram, GLBufferContents::normal, "normal");
406 glLinkProgram( program.glProgram );
407 glGetProgramiv( program.glProgram, GL_LINK_STATUS, &status );
408 if( status != GL_TRUE )
410 fprintf( stderr, "ERROR, failed to link shader program\n" );
411 glGetProgramInfoLog( program.glProgram, 8192, &loglength, infolog );
412 fprintf( stderr, "ERROR: \n%s\n\n", infolog );
416 // glUseProgram( program.glProgram );
418 program.matrixloc = glGetUniformLocation( program.glProgram, "uniMatrix" );
419 program.vertexloc = glGetAttribLocation( program.glProgram, "inVertex" );
420 program.texcoord0loc = glGetAttribLocation( program.glProgram, "inTexcoord0" );
421 program.texcoord1loc = glGetAttribLocation( program.glProgram, "inTexcoord1" );
422 program.colorloc = glGetAttribLocation( program.glProgram, "inColor" );
423 #if DM_ENABLE_EXT_COLOR
424 program.extcolorloc = glGetAttribLocation( program.glProgram, "inExtColor" );
426 program.texbaseloc = glGetUniformLocation( program.glProgram, "texBase" );
427 program.flags.valid = true;
432 if( program.fragmentShader )
433 glDeleteShader( program.fragmentShader );
434 if( program.vertexShader )
435 glDeleteShader( program.vertexShader );
436 if( program.glProgram )
437 glDeleteProgram( program.glProgram );
445 const char *dmVertexShaderNormal =
447 "uniform mat4 uniMatrix;\n"
448 "in vec2 inVertex;\n"
449 "in vec2 inTexcoord0;\n"
451 "out vec2 varTexcoord0;\n"
452 "out vec4 varColor;\n"
456 " varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
457 " varColor = inColor;\n"
458 " gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
464 const char *dmFragmentShaderNormal =
466 "uniform sampler2D texBase;\n"
467 "in vec2 varTexcoord0;\n"
468 "in vec4 varColor;\n"
471 " gl_FragColor = varColor * texture2D( texBase, varTexcoord0 );\n"
477 const char *dmVertexShaderAlpha =
479 "uniform mat4 uniMatrix;\n"
480 "in vec2 inVertex;\n"
481 "in vec2 inTexcoord0;\n"
483 "out vec2 varTexcoord0;\n"
484 "out vec4 varColor;\n"
488 " varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
489 " varColor = inColor;\n"
490 " gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
496 const char *dmFragmentShaderAlpha =
498 "uniform sampler2D texBase;\n"
499 "in vec2 varTexcoord0;\n"
500 "in vec4 varColor;\n"
503 " gl_FragColor = vec4( varColor.rgb, varColor.a * texture2D( texBase, varTexcoord0 ).r );\n"
508 const char *dmVertexShaderAlphaIntensity =
510 "uniform mat4 uniMatrix;\n"
511 "in vec2 inVertex;\n"
512 "in vec2 inTexcoord0;\n"
514 "out vec2 varTexcoord0;\n"
515 "out vec4 varColor;\n"
519 " varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
520 " varColor = inColor;\n"
521 " gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
527 const char *dmFragmentShaderAlphaIntensity =
529 "uniform sampler2D texBase;\n"
530 "in vec2 varTexcoord0;\n"
531 "in vec4 varColor;\n"
535 " tex = texture2D( texBase, varTexcoord0 ).rg;\n"
536 " gl_FragColor = vec4( varColor.rgb * tex.g, varColor.a * tex.r );\n"
541 const char *dmVertexShaderAlphaIntensityExtColor =
543 "uniform mat4 uniMatrix;\n"
544 "in vec2 inVertex;\n"
545 "in vec2 inTexcoord0;\n"
547 "in vec4 inExtColor;\n"
548 "out vec2 varTexcoord0;\n"
549 "out vec4 varColor;\n"
550 "out vec4 varExtColor;\n"
554 " varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
555 " varColor = inColor;\n"
556 " varExtColor = inExtColor;\n"
557 " gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
563 const char *dmFragmentShaderAlphaIntensityExtColor =
565 "uniform sampler2D texBase;\n"
566 "in vec2 varTexcoord0;\n"
567 "in vec4 varColor;\n"
568 "in vec4 varExtColor;\n"
572 " tex = texture2D( texBase, varTexcoord0 ).rg;\n"
573 " gl_FragColor = vec4( mix( varExtColor.rgb, varColor.rgb, tex.g ), mix( varExtColor.a, varColor.a, tex.g ) * tex.r );\n"
581 static void matrixOrtho( float *m, float left, float right, float bottom, float top, float nearval, float farval )
583 float x = 2.0f / ( right - left );
584 float y = 2.0f / ( top - bottom );
585 float z = -2.0f / ( farval - nearval );
586 float tx = -( right + left ) / ( right - left );
587 float ty = -( top + bottom ) / ( top - bottom );
588 float tz = -( farval + nearval ) / ( farval - nearval );
590 #define M(row,col) m[col*4+row]
591 M(0,0) = x; M(0,1) = 0.0; M(0,2) = 0.0; M(0,3) = tx;
592 M(1,0) = 0.0; M(1,1) = y; M(1,2) = 0.0; M(1,3) = ty;
593 M(2,0) = 0.0; M(2,1) = 0.0; M(2,2) = z; M(2,3) = tz;
594 M(3,0) = 0.0; M(3,1) = 0.0; M(3,2) = 0.0; M(3,3) = 1.0;
601 /* FIXME: Radix sort, not hybrid sort! */
603 static inline int dmSortImagesCmp( DMImageBuffer *draw0, DMImageBuffer *draw1 )
605 return ( ( draw0->orderindex < draw1->orderindex ) ? 0 : 1 );
608 #define HSORT_MAIN dmSortImages
609 #define HSORT_CMP dmSortImagesCmp
610 #define HSORT_TYPE DMImageBuffer
611 #include "cchybridsort.h"
619 // TOFIX: Make this private, have a property
620 public class DrawManagerFlags : uint32 { public: bool prehistoricOpenGL:1; }
622 public class DrawManager
624 DrawManagerFlags flags;
625 DMProgram shaderPrograms[DM_PROGRAM_COUNT];
630 int imageBufferCount;
632 DMImageBuffer *imageBuffer;
633 DMImageBuffer *imageBufferTmp;
635 // Buffers for drawimages() batching
636 DMDrawBuffer drawBuffer[DM_CONTEXT_DRAW_BUFFER_COUNT];
638 int drawBarrierIndex;
639 uint32 orderBarrierMask;
641 // Counter to track program uniforms and such
646 bool renderingFlipped;
648 static DMProgram *flushUseProgram( int programIndex )
650 DMProgram *program = &shaderPrograms[ programIndex ];
651 if( !program->flags.valid)
657 glUseProgram( program->glProgram );
658 if( program->lastUpdateCount != this.updateCount )
660 glUniformMatrix4fv( program->matrixloc, 1, GL_FALSE, this.matrix );
661 glUniform1i( program->texbaseloc, 0 );
662 program->lastUpdateCount = this.updateCount;
668 #if !defined(__EMSCRIPTEN__)
669 static void flushRenderDrawBufferArchaic( DMDrawBuffer drawBuffer, DMProgram program, int vertexCount )
671 glEnable( GL_TEXTURE_2D );
672 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer.vbo );
673 glColor3f( 1.0, 1.0, 1.0 );
675 glEnableClientState( GL_VERTEX_ARRAY );
676 glEnableClientState( GL_TEXTURE_COORD_ARRAY );
677 glEnableClientState( GL_COLOR_ARRAY );
679 glVertexPointer( 2, GL_FLOAT, sizeof(DMDrawVertexFlat), (void *)OFFSET(DMDrawVertexFlat,vertex) );
680 glTexCoordPointer( 2, GL_FLOAT, sizeof(DMDrawVertexFlat), (void *)OFFSET(DMDrawVertexFlat,texcoord0) );
681 glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(DMDrawVertexFlat), (void *)OFFSET(DMDrawVertexFlat,color) );
683 glDrawArrays( GL_TRIANGLES, 0, vertexCount );
685 glDisableClientState( GL_VERTEX_ARRAY );
686 glDisableClientState( GL_TEXTURE_COORD_ARRAY );
687 glDisableClientState( GL_COLOR_ARRAY );
688 glDisable( GL_TEXTURE_2D );
690 #if DM_FLUSH_EACH_RENDER_DRAW_BUFFER
695 void flushDrawImagesArchaic( )
697 bool flushflag, stateBlend;
698 int index, vertexCount, programIndex;
699 float vx0, vx1, vx2, vx3, vy0, vy1, vy2, vy3;
700 #if DM_ENABLE_IMAGE_ROTATION
701 float angsin, angcos, sizex, sizey;
703 float tx0, tx1, ty0, ty1;
704 DMImageBuffer *imageBuffer;
705 DMImage *image, *bindimage;
706 Texture texture, bindTexture;
707 DMDrawBuffer *drawBuffer;
708 DMDrawVertexFlat *vboVertex;
713 drawBarrierIndex = 0;
714 orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;
717 // Sort by image type and texture, minimize state changes
718 dmSortImages( this.imageBuffer, imageBufferTmp, imageBufferCount, (uint32)( (intptr_t)this.imageBuffer >> 4 ) );
720 // Fill a drawBuffer, write vertex and texcoords
721 drawBuffer = &this.drawBuffer[drawBufferIndex];
722 drawBufferIndex = ( drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
723 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
724 vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
727 glActiveTexture( GL_TEXTURE0 );
728 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
729 glDisable( GL_BLEND );
730 GLSetupLighting(false);
732 #if DM_RENDER_IMAGE_DEBUG
733 printf( " Flush %d images\n", (int)imageBufferCount );
741 imageBuffer = this.imageBuffer;
742 for( index = 0 ; index < imageBufferCount ; index++, imageBuffer++ )
744 image = imageBuffer->image;
745 texture = image->texture;
748 if( image != bindimage )
750 if( stateBlend != image->flags.blending )
752 if( texture != bindTexture )
755 if( vertexCount >= ( drawBuffer->vertexAlloc - 6 ) )
762 glUnmapBuffer( GL_ARRAY_BUFFER );
763 // Flush font manager texture updates
765 // Render buffered images
766 flushRenderDrawBufferArchaic( drawBuffer, program, vertexCount );
767 drawBuffer = &this.drawBuffer[drawBufferIndex];
768 drawBufferIndex = ( drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
769 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
770 vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
774 if( stateBlend != ( image->flags.blending ) )
776 stateBlend = image->flags.blending;
777 ( stateBlend ? glEnable : glDisable )( GL_BLEND );
778 #if DM_RENDER_IMAGE_DEBUG
779 printf( " Switch blending %d\n", stateBlend != false );
782 if( programIndex != image->programIndex )
784 programIndex = image->programIndex;
785 program = flushUseProgram( programIndex );
787 if( texture != bindTexture )
789 bindTexture = texture;
790 glBindTexture( GL_TEXTURE_2D, bindTexture.glTex );
791 #if DM_RENDER_IMAGE_DEBUG
792 printf( " Switch to texture 0x%x\n", (int)texture.orderMask );
798 #if DM_RENDER_IMAGE_DEBUG
799 printf( " Render image at %d %d, order 0x%x, texture %p\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex, texture );
802 #if DM_ENABLE_IMAGE_ROTATION
803 angsin = (float)imageBuffer->angsin * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
804 angcos = (float)imageBuffer->angcos * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
805 sizex = (float)imageBuffer->sizex;
806 sizey = (float)imageBuffer->sizey;
807 vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
808 vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
809 vx1 = vx0 + ( angcos * sizex );
810 vy1 = vy0 + ( angsin * sizex );
811 vx2 = vx0 - ( angsin * sizey );
812 vy2 = vy0 + ( angcos * sizey );
813 vx3 = vx0 + ( angcos * sizex ) - ( angsin * sizey );
814 vy3 = vy0 + ( angsin * sizex ) + ( angcos * sizey );
816 vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
817 vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
818 vx3 = vx0 + (float)( imageBuffer->sizex );
819 vy3 = vy0 + (float)( imageBuffer->sizey );
826 tx0 = (float)( image->srcx ) * texture.widthinv;
827 ty0 = (float)( image->srcy ) * texture.heightinv;
828 tx1 = (float)( image->srcx + image->sizex ) * texture.widthinv;
829 ty1 = (float)( image->srcy + image->sizey ) * texture.heightinv;
832 vboVertex[0].vertex[0] = vx3;
833 vboVertex[0].vertex[1] = vy3;
834 vboVertex[0].texcoord0[0] = tx1;
835 vboVertex[0].texcoord0[1] = ty1;
836 vboVertex[0].color = imageBuffer->color;
837 #if DM_ENABLE_EXT_COLOR
838 vboVertex[0].extcolor = imageBuffer->extcolor;
840 vboVertex[1].vertex[0] = vx1;
841 vboVertex[1].vertex[1] = vy1;
842 vboVertex[1].texcoord0[0] = tx1;
843 vboVertex[1].texcoord0[1] = ty0;
844 vboVertex[1].color = imageBuffer->color;
845 #if DM_ENABLE_EXT_COLOR
846 vboVertex[1].extcolor = imageBuffer->extcolor;
848 vboVertex[2].vertex[0] = vx2;
849 vboVertex[2].vertex[1] = vy2;
850 vboVertex[2].texcoord0[0] = tx0;
851 vboVertex[2].texcoord0[1] = ty1;
852 vboVertex[2].color = imageBuffer->color;
853 #if DM_ENABLE_EXT_COLOR
854 vboVertex[2].extcolor = imageBuffer->extcolor;
856 vboVertex[3].vertex[0] = vx0;
857 vboVertex[3].vertex[1] = vy0;
858 vboVertex[3].texcoord0[0] = tx0;
859 vboVertex[3].texcoord0[1] = ty0;
860 vboVertex[3].color = imageBuffer->color;
861 #if DM_ENABLE_EXT_COLOR
862 vboVertex[3].extcolor = imageBuffer->extcolor;
864 vboVertex[4].vertex[0] = vx2;
865 vboVertex[4].vertex[1] = vy2;
866 vboVertex[4].texcoord0[0] = tx0;
867 vboVertex[4].texcoord0[1] = ty1;
868 vboVertex[4].color = imageBuffer->color;
869 #if DM_ENABLE_EXT_COLOR
870 vboVertex[4].extcolor = imageBuffer->extcolor;
872 vboVertex[5].vertex[0] = vx1;
873 vboVertex[5].vertex[1] = vy1;
874 vboVertex[5].texcoord0[0] = tx1;
875 vboVertex[5].texcoord0[1] = ty0;
876 vboVertex[5].color = imageBuffer->color;
877 #if DM_ENABLE_EXT_COLOR
878 vboVertex[5].extcolor = imageBuffer->extcolor;
885 glUnmapBuffer( GL_ARRAY_BUFFER );
887 // Flush font manager texture updates
890 // Render buffered images
891 flushRenderDrawBufferArchaic( drawBuffer, program, vertexCount );
892 imageBufferCount = 0;
900 void flushRenderDrawBuffer( DMDrawBuffer drawBuffer, DMProgram program, int vertexCount )
902 glabCurArrayBuffer = 0;
904 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer.vbo );
905 if( program.vertexloc != -1 )
907 glEnableVertexAttribArray( program.vertexloc );
908 glVertexAttribPointer( program.vertexloc, 2, GL_SHORT, GL_FALSE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,vertex) );
910 if( program.texcoord0loc != -1 )
912 glEnableVertexAttribArray( program.texcoord0loc );
913 glVertexAttribPointer( program.texcoord0loc, 2, GL_SHORT, GL_FALSE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,texcoord0) );
915 if( program.colorloc != -1 )
917 glEnableVertexAttribArray( program.colorloc );
918 glVertexAttribPointer( program.colorloc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,color) );
921 #if DM_ENABLE_EXT_COLOR
922 if( program.extcolorloc != -1 )
924 glEnableVertexAttribArray( program.extcolorloc );
925 glVertexAttribPointer( program.extcolorloc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,extcolor) );
929 glDrawArrays( GL_TRIANGLES, 0, vertexCount );
931 if( program.vertexloc != -1 )
932 glDisableVertexAttribArray( program.vertexloc );
933 if( program.texcoord0loc != -1 )
934 glDisableVertexAttribArray( program.texcoord0loc );
935 if( program.colorloc != -1 )
936 glDisableVertexAttribArray( program.colorloc );
938 #if DM_FLUSH_EACH_RENDER_DRAW_BUFFER
943 void flushDrawImages( )
945 int index, stateblend, vertexcount, flushflag, programIndex;
946 float vx0, vx1, vx2, vx3, vy0, vy1, vy2, vy3;
947 #if DM_ENABLE_IMAGE_ROTATION
948 float angsin, angcos, sizex, sizey;
950 float tx0, tx1, ty0, ty1;
951 DMImageBuffer *imageBuffer;
952 DMImage *image, *bindimage;
953 Texture texture, bindtexture;
954 DMDrawBuffer *drawBuffer;
955 DMDrawVertex *vboVertex;
958 glabCurArrayBuffer = 0;
962 this.drawBarrierIndex = 0;
963 orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;
964 if( imageBufferCount )
966 /* Sort by image type and texture, minimize state changes */
967 dmSortImages( this.imageBuffer, this.imageBufferTmp, imageBufferCount, (uint32)( (uintptr)this.imageBuffer >> 4 ) );
969 /* Fill a drawBuffer, write vertex and texcoords */
970 drawBuffer = &this.drawBuffer[this.drawBufferIndex];
971 this.drawBufferIndex = ( this.drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
972 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
974 #if !defined(__EMSCRIPTEN__)
975 vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
979 glActiveTexture( GL_TEXTURE0 );
980 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
981 glDisable( GL_BLEND );
983 #if DM_RENDER_IMAGE_DEBUG
984 printf( " Flush %d images\n", (int)imageBufferCount );
992 imageBuffer = this.imageBuffer;
993 for( index = 0 ; index < imageBufferCount ; index++, imageBuffer++ )
995 image = imageBuffer->image;
996 texture = image->texture;
999 if( image != bindimage )
1001 if( stateblend != ( image->flags.blending ) )
1003 if( texture != bindtexture )
1006 if( vertexcount >= ( drawBuffer->vertexAlloc - 6 ) )
1013 #if !defined(__EMSCRIPTEN__)
1014 glUnmapBuffer( GL_ARRAY_BUFFER );
1016 // Flush font manager texture updates
1019 // Render buffered images
1020 flushRenderDrawBuffer( drawBuffer, program, vertexcount );
1021 drawBuffer = &this.drawBuffer[this.drawBufferIndex];
1022 this.drawBufferIndex = ( this.drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
1023 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
1024 #if !defined(__EMSCRIPTEN__)
1025 vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
1030 if( stateblend != ( image->flags.blending ) )
1032 stateblend = image->flags.blending;
1033 ( stateblend ? glEnable : glDisable )( GL_BLEND );
1034 #if DM_RENDER_IMAGE_DEBUG
1035 printf( " Switch blending %d\n", ( stateblend != 0 ) );
1038 if( programIndex != image->programIndex )
1040 programIndex = image->programIndex;
1041 program = flushUseProgram( programIndex );
1043 if( texture != bindtexture )
1045 bindtexture = texture;
1046 glBindTexture( GL_TEXTURE_2D, bindtexture.glTex );
1047 #if DM_RENDER_IMAGE_DEBUG
1048 printf( " Switch to texture 0x%x\n", (int)texture.orderMask );
1054 #if DM_RENDER_IMAGE_DEBUG
1055 printf( " Render image at %d %d, order 0x%x, texture %p\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex, texture );
1058 #if DM_ENABLE_IMAGE_ROTATION
1059 /* FIXME TODO: Don't go through float, compute texcoord integers directly */
1060 angsin = (float)imageBuffer->angsin * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
1061 angcos = (float)imageBuffer->angcos * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
1062 sizex = (float)imageBuffer->sizex;
1063 sizey = (float)imageBuffer->sizey;
1064 vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
1065 vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
1066 vx1 = vx0 + ( angcos * sizex );
1067 vy1 = vy0 + ( angsin * sizex );
1068 vx2 = vx0 - ( angsin * sizey );
1069 vy2 = vy0 + ( angcos * sizey );
1070 vx3 = vx0 + ( angcos * sizex ) - ( angsin * sizey );
1071 vy3 = vy0 + ( angsin * sizex ) + ( angcos * sizey );
1073 /* FIXME TODO: Don't go through float, compute texcoord integers directly */
1074 vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
1075 vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
1076 vx3 = vx0 + (float)( imageBuffer->sizex );
1077 vy3 = vy0 + (float)( imageBuffer->sizey );
1084 /* FIXME TODO: Don't go through float, compute texcoord integers directly */
1085 tx0 = (float)( image->srcx ) * texture.widthinv;
1086 ty0 = (float)( image->srcy ) * texture.heightinv;
1087 tx1 = (float)( image->srcx + image->sizex ) * texture.widthinv;
1088 ty1 = (float)( image->srcy + image->sizey ) * texture.heightinv;
1090 /* Write data to VBO */
1091 /* TODO: write vertex/texcoord all at once with SSE */
1092 vboVertex[0].vertex[0] = (short)( vx3 * DM_VERTEX_NORMFACTOR );
1093 vboVertex[0].vertex[1] = (short)( vy3 * DM_VERTEX_NORMFACTOR );
1094 vboVertex[0].texcoord0[0] = (short)( tx1 * DM_TEXCOORD_NORMFACTOR );
1095 vboVertex[0].texcoord0[1] = (short)( ty1 * DM_TEXCOORD_NORMFACTOR );
1096 vboVertex[0].color = imageBuffer->color;
1097 vboVertex[0].extcolor = imageBuffer->extcolor;
1098 vboVertex[1].vertex[0] = (short)( vx1 * DM_VERTEX_NORMFACTOR );
1099 vboVertex[1].vertex[1] = (short)( vy1 * DM_VERTEX_NORMFACTOR );
1100 vboVertex[1].texcoord0[0] = (short)( tx1 * DM_TEXCOORD_NORMFACTOR );
1101 vboVertex[1].texcoord0[1] = (short)( ty0 * DM_TEXCOORD_NORMFACTOR );
1102 vboVertex[1].color = imageBuffer->color;
1103 vboVertex[1].extcolor = imageBuffer->extcolor;
1104 vboVertex[2].vertex[0] = (short)( vx2 * DM_VERTEX_NORMFACTOR );
1105 vboVertex[2].vertex[1] = (short)( vy2 * DM_VERTEX_NORMFACTOR );
1106 vboVertex[2].texcoord0[0] = (short)( tx0 * DM_TEXCOORD_NORMFACTOR );
1107 vboVertex[2].texcoord0[1] = (short)( ty1 * DM_TEXCOORD_NORMFACTOR );
1108 vboVertex[2].color = imageBuffer->color;
1109 vboVertex[2].extcolor = imageBuffer->extcolor;
1110 vboVertex[3].vertex[0] = (short)( vx0 * DM_VERTEX_NORMFACTOR );
1111 vboVertex[3].vertex[1] = (short)( vy0 * DM_VERTEX_NORMFACTOR );
1112 vboVertex[3].texcoord0[0] = (short)( tx0 * DM_TEXCOORD_NORMFACTOR );
1113 vboVertex[3].texcoord0[1] = (short)( ty0 * DM_TEXCOORD_NORMFACTOR );
1114 vboVertex[3].color = imageBuffer->color;
1115 vboVertex[3].extcolor = imageBuffer->extcolor;
1116 vboVertex[4].vertex[0] = (short)( vx2 * DM_VERTEX_NORMFACTOR );
1117 vboVertex[4].vertex[1] = (short)( vy2 * DM_VERTEX_NORMFACTOR );
1118 vboVertex[4].texcoord0[0] = (short)( tx0 * DM_TEXCOORD_NORMFACTOR );
1119 vboVertex[4].texcoord0[1] = (short)( ty1 * DM_TEXCOORD_NORMFACTOR );
1120 vboVertex[4].color = imageBuffer->color;
1121 vboVertex[4].extcolor = imageBuffer->extcolor;
1122 vboVertex[5].vertex[0] = (short)( vx1 * DM_VERTEX_NORMFACTOR );
1123 vboVertex[5].vertex[1] = (short)( vy1 * DM_VERTEX_NORMFACTOR );
1124 vboVertex[5].texcoord0[0] = (short)( tx1 * DM_TEXCOORD_NORMFACTOR );
1125 vboVertex[5].texcoord0[1] = (short)( ty0 * DM_TEXCOORD_NORMFACTOR );
1126 vboVertex[5].color = imageBuffer->color;
1127 vboVertex[5].extcolor = imageBuffer->extcolor;
1133 #if !defined(__EMSCRIPTEN__)
1134 glUnmapBuffer( GL_ARRAY_BUFFER );
1136 // Flush font manager texture updates
1138 // Render buffered images
1139 flushRenderDrawBuffer( drawBuffer, program, vertexcount );
1140 imageBufferCount = 0;
1148 property bool renderingFlipped { set { renderingFlipped = value; } }
1150 virtual void flush();
1152 bool init( DrawManagerFlags flags )
1154 int drawBufferIndex, programIndex;
1155 DMDrawBuffer *drawBuffer;
1158 imageBufferCount = 0;
1159 imageBufferSize = 4096;
1160 imageBuffer = new DMImageBuffer[imageBufferSize];
1161 imageBufferTmp = new DMImageBuffer[imageBufferSize];
1165 if( flags.prehistoricOpenGL )
1166 vertexSize = sizeof(DMDrawVertexFlat);
1170 for( programIndex = 0 ; programIndex < DM_PROGRAM_COUNT ; programIndex++ )
1172 program = &shaderPrograms[ programIndex ];
1174 program->lastUpdateCount = -1;
1176 program = &shaderPrograms[ DM_PROGRAM_NORMAL ];
1177 if( !( dmCreateProgram( program, dmVertexShaderNormal, dmFragmentShaderNormal, 0 ) ) )
1179 program = &shaderPrograms[ DM_PROGRAM_ALPHABLEND ];
1180 if( !( dmCreateProgram( program, dmVertexShaderAlpha, dmFragmentShaderAlpha, 0 ) ) )
1182 program = &shaderPrograms[ DM_PROGRAM_ALPHABLEND_INTENSITY ];
1183 if( !( dmCreateProgram( program, dmVertexShaderAlphaIntensity, dmFragmentShaderAlphaIntensity, 0 ) ) )
1185 program = &shaderPrograms[ DM_PROGRAM_ALPHABLEND_INTENSITY_EXTCOLOR ];
1186 if( !( dmCreateProgram( program, dmVertexShaderAlphaIntensityExtColor, dmFragmentShaderAlphaIntensityExtColor, 0 ) ) )
1188 // glUseProgram( 0 );
1189 vertexSize = sizeof(DMDrawVertex);
1192 for( drawBufferIndex = 0 ; drawBufferIndex < DM_CONTEXT_DRAW_BUFFER_COUNT ; drawBufferIndex++ )
1194 drawBuffer = &this.drawBuffer[drawBufferIndex];
1195 drawBuffer->glType = GL_FLOAT;
1196 drawBuffer->vertexCount = 0;
1197 drawBuffer->vertexAlloc = DM_CONTEXT_DRAW_BUFFER_VERTEX_ALLOC;
1200 glGenBuffers( 1, &drawBuffer->vbo );
1201 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
1202 glBufferData( GL_ARRAY_BUFFER, drawBuffer->vertexAlloc * vertexSize, 0, GL_DYNAMIC_DRAW );
1204 drawBuffer->vertexBuffer = new byte[drawBuffer->vertexAlloc * vertexSize];
1209 glabCurArrayBuffer = 0;
1219 for( i = 0 ; i < DM_CONTEXT_DRAW_BUFFER_COUNT ; i++ )
1221 DMDrawBuffer *db = &drawBuffer[i];
1223 glDeleteBuffers( 1, &db->vbo );
1224 delete db->vertexBuffer;
1227 // TODO: Destroy the shaders!
1229 delete imageBufferTmp;
1232 void ready( int viewportwidth, int viewportheight )
1236 if(!flags.prehistoricOpenGL && !prevProgram)
1237 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *)&prevProgram);
1238 // while(glGetError());
1242 // Save OpenGL state
1243 // FIXME: no glPushAttrib() in core profile
1244 #if !defined(__EMSCRIPTEN__)
1245 glPushClientAttrib( GL_CLIENT_ALL_ATTRIB_BITS );
1246 glPushAttrib( GL_ALL_ATTRIB_BITS );
1249 // Prepare rendering pass
1250 if(renderingFlipped)
1251 matrixOrtho( matrix, 0.0, (float)viewportwidth, 0.0, (float)viewportheight, -1.0f, 1.0 );
1253 matrixOrtho( matrix, 0.0, (float)viewportwidth, (float)viewportheight, 0.0, -1.0f, 1.0 );
1254 norminv = 1.0f / DM_VERTEX_NORMFACTOR;
1255 for( mindex = 0 ; mindex < 12 ; mindex += 4 )
1257 matrix[mindex+0] *= norminv;
1258 matrix[mindex+1] *= norminv;
1259 matrix[mindex+2] *= norminv;
1261 drawBarrierIndex = 0;
1262 orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;
1263 orderBarrierMask = 0;
1267 if(flags.prehistoricOpenGL)
1269 glMatrixMode(MatrixMode::projection);
1270 glLoadMatrixf(matrix);
1272 glMatrixMode(MatrixMode::modelView);
1278 void drawImage( DMImage image, int offsetx, int offsety, int sizex, int sizey, uint32 color )
1280 DMImageBuffer *imageBuffer;
1282 if( image.flags.empty || ( sizex <= 0 ) || ( sizey <= 0 ) )
1285 if( imageBufferCount >= imageBufferSize )
1287 imageBufferSize <<= 1;
1288 this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
1289 imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
1292 imageBuffer = &this.imageBuffer[ imageBufferCount ];
1293 imageBuffer->image = image;
1294 imageBuffer->offsetx = (short)(offsetx << DM_VERTEX_NORMSHIFT);
1295 imageBuffer->offsety = (short)(offsety << DM_VERTEX_NORMSHIFT);
1296 imageBuffer->sizex = (short)sizex;
1297 imageBuffer->sizey = (short)sizey;
1298 #if DM_ENABLE_IMAGE_ROTATION
1299 imageBuffer->angsin = 0;
1300 imageBuffer->angcos = (short)DM_IMAGE_ROTATION_NORMFACTOR;
1302 imageBuffer->color = color;
1303 imageBuffer->orderindex = image.orderMask | orderBarrierMask;
1305 #if DM_RENDER_IMAGE_DEBUG
1306 printf( " Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
1312 void drawImageExtColor( DMImage image, int offsetx, int offsety, int sizex, int sizey, uint32 color, uint32 extcolor )
1314 DMImageBuffer *imageBuffer;
1316 if( ( image.flags.empty ) || ( sizex <= 0 ) || ( sizey <= 0 ) )
1319 if( imageBufferCount >= imageBufferSize )
1321 imageBufferSize <<= 1;
1322 this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
1323 imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
1326 imageBuffer = &this.imageBuffer[ imageBufferCount ];
1327 imageBuffer->image = image;
1328 imageBuffer->offsetx = (short)(offsetx << DM_VERTEX_NORMSHIFT);
1329 imageBuffer->offsety = (short)(offsety << DM_VERTEX_NORMSHIFT);
1330 imageBuffer->sizex = (short)sizex;
1331 imageBuffer->sizey = (short)sizey;
1332 #if DM_ENABLE_IMAGE_ROTATION
1333 imageBuffer->angsin = 0;
1334 imageBuffer->angcos = (short)DM_IMAGE_ROTATION_NORMFACTOR;
1336 imageBuffer->color = color;
1337 #if DM_ENABLE_EXT_COLOR
1338 imageBuffer->extcolor = extcolor;
1340 imageBuffer->orderindex = image.orderMask | orderBarrierMask;
1342 #if DM_RENDER_IMAGE_DEBUG
1343 printf( " Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
1346 this.imageBufferCount++;
1349 void drawImageFloat( DMImage image, float offsetx, float offsety, float sizex, float sizey, float angsin, float angcos, uint32 color )
1351 DMImageBuffer *imageBuffer;
1353 if( image.flags.empty || sizex <= 0 || sizey <= 0 )
1356 if( imageBufferCount >= imageBufferSize )
1358 imageBufferSize <<= 1;
1359 this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
1360 imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
1363 imageBuffer = &this.imageBuffer[ imageBufferCount ];
1364 imageBuffer->image = image;
1365 imageBuffer->offsetx = (short)roundf(offsetx * DM_VERTEX_NORMFACTOR);
1366 imageBuffer->offsety = (short)roundf(offsety * DM_VERTEX_NORMFACTOR);
1367 imageBuffer->sizex = (short)sizex;
1368 imageBuffer->sizey = (short)sizey;
1369 #if DM_ENABLE_IMAGE_ROTATION
1370 imageBuffer->angsin = (short)roundf( angsin * DM_IMAGE_ROTATION_NORMFACTOR );
1371 imageBuffer->angcos = (short)roundf( angcos * DM_IMAGE_ROTATION_NORMFACTOR );
1373 imageBuffer->color = color;
1374 imageBuffer->orderindex = image.orderMask | orderBarrierMask;
1376 #if DM_RENDER_IMAGE_DEBUG
1377 printf( " Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
1383 void drawImageFloatExtColor( DMImage image, float offsetx, float offsety, float sizex, float sizey, float angsin, float angcos, uint32 color, uint32 extcolor )
1385 DMImageBuffer *imageBuffer;
1387 if( ( image.flags.empty ) || ( sizex <= 0 ) || ( sizey <= 0 ) )
1390 if( this.imageBufferCount >= this.imageBufferSize )
1392 imageBufferSize <<= 1;
1393 this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
1394 imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
1397 imageBuffer = &this.imageBuffer[ imageBufferCount ];
1398 imageBuffer->image = image;
1399 imageBuffer->offsetx = (short)roundf( offsetx * DM_VERTEX_NORMFACTOR );
1400 imageBuffer->offsety = (short)roundf( offsety * DM_VERTEX_NORMFACTOR );
1401 imageBuffer->sizex = (short)sizex;
1402 imageBuffer->sizey = (short)sizey;
1403 #if DM_ENABLE_IMAGE_ROTATION
1404 imageBuffer->angsin = (short)roundf( angsin * DM_IMAGE_ROTATION_NORMFACTOR );
1405 imageBuffer->angcos = (short)roundf( angcos * DM_IMAGE_ROTATION_NORMFACTOR );
1407 imageBuffer->color = color;
1408 #if DM_ENABLE_EXT_COLOR
1409 imageBuffer->extcolor = extcolor;
1411 imageBuffer->orderindex = image.orderMask | orderBarrierMask;
1413 #if DM_RENDER_IMAGE_DEBUG
1414 printf( " Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
1417 this.imageBufferCount++;
1422 #if !defined(__EMSCRIPTEN__)
1423 if( flags.prehistoricOpenGL )
1424 flushDrawImagesArchaic( );
1430 glBindBuffer( GL_ARRAY_BUFFER, 0 );
1431 glabCurArrayBuffer = 0;
1432 if( !flags.prehistoricOpenGL )
1433 glUseProgram( prevProgram );
1434 // Restore OpenGL state
1435 // FIXME: no glPushAttrib() in core profile
1436 #if !defined(__EMSCRIPTEN__)
1438 glPopClientAttrib();
1445 if( drawBarrierIndex >= ( 1 << DM_BARRIER_ORDER_BITS ) )
1447 orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;