1 import "OpenGLDisplayDriver"
13 #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
15 //# include "gl_core_3_3.h"
16 # include "gl_compat_4_4.h" // FIXME: no glPushAttrib() in core profile
18 # include "gl_compat_4_4.h"
24 #undef glEnableClientState
25 #undef glDisableClientState
26 #undef GL_VERTEX_ARRAY
27 #undef GL_NORMAL_ARRAY
28 #undef GL_TEXTURE_COORD_ARRAY
30 #undef glVertexPointer
31 #undef glTexCoordPointer
34 #define glEnableClientState glEnableVertexAttribArray
35 #define glDisableClientState glDisableVertexAttribArray
36 #define GL_VERTEX_ARRAY GLBufferContents::vertex
37 #define GL_NORMAL_ARRAY GLBufferContents::normal
38 #define GL_TEXTURE_COORD_ARRAY GLBufferContents::texCoord
39 #define GL_COLOR_ARRAY GLBufferContents::color
40 #define glVertexPointer(n, t, s, p) glVertexAttribPointer(GLBufferContents::vertex, n, t, GL_FALSE, s, p)
41 #define glTexCoordPointer(n, t, s, p) glVertexAttribPointer(GLBufferContents::texCoord, n, t, GL_FALSE, s, p)
42 #define glColorPointer(n, t, s, p) glVertexAttribPointer(GLBufferContents::color, n, t, GL_FALSE, s, p)
46 #if defined(ES1_1) || defined(ES2) || defined(SHADERS)
82 #undef glColorMaterial
85 #define glRecti glimtkRecti
86 #define glBegin glimtkBegin
87 #define glTexCoord2i glimtkTexCoord2i
88 #define glVertex2i glimtkVertex2i
89 #define glTexCoord2d glimtkTexCoord2d
90 #define glVertex2d glimtkVertex2d
91 #define glTexCoord2f glimtkTexCoord2f
92 #define glVertex2f glimtkVertex2f
93 #define glEnd glimtkEnd
94 #define glColor3f glimtkColor3f
95 #define glColor4ub glimtkColor4ub
96 #define glColor4fv glimtkColor4fv
97 #define glNormal3fv glimtkNormal3fv
98 #define glNormal3f glimtkNormal3f
99 #define glTexCoord2fv glimtkTexCoord2fv
100 #define glVertex3d glimtkVertex3d
101 #define glVertex3dv glimtkVertex3dv
102 #define glVertex3f glimtkVertex3f
103 #define glVertex3fv glimtkVertex3fv
105 #define glLoadMatrixd glmsLoadMatrixd
106 #define glMultMatrixd glmsMultMatrixd
107 #define glFrustum glmsFrustum
108 #define glOrtho glmsOrtho
109 #define glScaled glmsScaled
110 #define glScalef glmsScaled
111 #define glTranslated glmsTranslated
112 #define glRotated glmsRotated
113 #define glMatrixMode glmsMatrixMode
114 #define glLoadIdentity glmsLoadIdentity
115 #define glPushMatrix glmsPushMatrix
116 #define glPopMatrix glmsPopMatrix
118 #define glLineStipple glesLineStipple
119 #define glColorMaterial glesColorMaterial
120 #define glLightModeli glesLightModeli
126 #define OFFSET(s, m) ((uint)(uintptr) (&((s *) 0)->m))
128 import "textureManager"
131 #define DM_ENABLE_IMAGE_ROTATION (1)
132 #define DM_ENABLE_EXT_COLOR (1)
136 static struct DMDrawVertexFlat
141 #if DM_ENABLE_EXT_COLOR
144 } __attribute__((aligned(16)));
146 static struct DMDrawVertex
151 #if DM_ENABLE_EXT_COLOR
154 } __attribute__((aligned(16)));
165 class DMProgramFlags : uint { bool valid:1; }
171 GLuint fragmentShader;
177 #if DM_ENABLE_EXT_COLOR
181 DMProgramFlags flags;
182 int64 lastUpdateCount;
185 class DMImageFlags : uint16
187 bool empty:1; // Image is empty, do not draw
188 bool blending:1; // Must draw image with blending
191 public struct DMImage
200 // Computed order for sorted rendering, in defineImage()
206 this = { flags = { empty = true } };
209 void defineImage( Texture texture, int offsetx, int offsety, int sizex, int sizey, bool blending, int programIndex, int layerindex )
211 int ordx = offsetx >> 6;
212 int ordy = offsety >> 6;
213 uint32 orderimage = ccMortonNumber32( ordx, ordy ) & ( ( 1 << DM_IMAGE_ORDER_BITS ) - 1 );
217 srcx = (short)offsetx;
218 srcy = (short)offsety;
219 sizex = (short)sizex;
220 sizey = (short)sizey;
221 programIndex = (short)programIndex;
222 flags = { blending = blending };
223 orderMask = (orderimage << DM_IMAGE_ORDER_SHIFT) |
224 (( blending == true ) << DM_BLEND_ORDER_SHIFT) |
225 (programIndex << DM_PROGRAM_ORDER_SHIFT) |
227 (layerindex << DM_LAYER_ORDER_SHIFT);
239 #if DM_ENABLE_IMAGE_ROTATION
243 #if DM_ENABLE_EXT_COLOR
254 define DM_IMAGE_ORDER_BITS = 8;
255 define DM_BLEND_ORDER_BITS = 1;
256 define DM_PROGRAM_ORDER_BITS = 4;
257 define DM_TEXTURE_ORDER_BITS = 10;
258 define DM_LAYER_ORDER_BITS = 4;
259 define DM_BARRIER_ORDER_BITS = 5;
261 define DM_IMAGE_ORDER_SHIFT = 0;
262 define DM_BLEND_ORDER_SHIFT = DM_IMAGE_ORDER_BITS;
263 define DM_PROGRAM_ORDER_SHIFT = DM_IMAGE_ORDER_BITS+DM_BLEND_ORDER_BITS;
264 define DM_TEXTURE_ORDER_SHIFT = DM_IMAGE_ORDER_BITS+DM_BLEND_ORDER_BITS+DM_PROGRAM_ORDER_BITS;
265 define DM_LAYER_ORDER_SHIFT = DM_IMAGE_ORDER_BITS+DM_BLEND_ORDER_BITS+DM_PROGRAM_ORDER_BITS+DM_TEXTURE_ORDER_BITS;
266 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;
268 define DM_LAYER_COUNT = 1<<DM_LAYER_ORDER_BITS;
269 define DM_PROGRAM_COUNT = 1<<DM_PROGRAM_ORDER_BITS;
271 define DM_CONTEXT_DRAW_BUFFER_COUNT = 64;
272 define DM_CONTEXT_DRAW_BUFFER_VERTEX_ALLOC = 1024;
275 /* Range is from zero to DM_LAYER_COUNT */
296 define DM_LAYER_BOTTOM = DMLayer::DM_LAYER_0_BOTTOM;
297 define DM_LAYER_BELOW = DMLayer::DM_LAYER_3_BELOW;
298 define DM_LAYER_NORMAL = DMLayer::DM_LAYER_6_NORMAL;
299 define DM_LAYER_ABOVE = DMLayer::DM_LAYER_9_ABOVE;
300 define DM_LAYER_TOP = DMLayer::DM_LAYER_15_TOP;
302 define DM_PROGRAM_NORMAL = 0;
303 define DM_PROGRAM_ALPHABLEND = 1;
304 define DM_PROGRAM_ALPHABLEND_INTENSITY = 2;
305 define DM_PROGRAM_ALPHABLEND_INTENSITY_EXTCOLOR = 3;
308 static inline void OpenGLErrorCheck( const char *file, int line )
310 int error = glGetError();
311 if( error != GL_NO_ERROR )
312 printf( "ERROR %d at %s:%d\n", error, file, line );
315 #define ERRORCHECK() OpenGLErrorCheck(__FILE__,__LINE__)
320 #define DM_IMAGE_ROTATION_NORMFACTOR (32767.0f)
322 #define DM_VERTEX_NORMSHIFT (2)
323 #define DM_VERTEX_NORMFACTOR (4.0f)
325 #define DM_TEXCOORD_NORMSHIFT (13)
326 #define DM_TEXCOORD_NORMFACTOR (8192.0f)
328 static GLuint dmCreateShader( GLenum type, const char *shadersource, const char *optionstring )
334 const GLchar *sourcearray[2];
336 shader = glCreateShader( type );
340 if( !( optionstring ) )
342 sourcearray[0] = optionstring;
343 sourcearray[1] = shadersource;
344 glShaderSource( shader, 2, sourcearray, NULL );
345 glCompileShader( shader );
346 glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
347 if( status != GL_TRUE )
349 fprintf( stderr, "ERROR: Failed to compile shader\n" );
350 glGetShaderInfoLog( shader, 8192, &loglength,infolog );
351 fprintf( stderr, "ERROR: \n%s\n\n", infolog );
352 glDeleteShader( shader );
359 static bool dmCreateProgram( DMProgram program, const char *vertexsource, const char *fragmentsource, char *optionstring )
365 program.glProgram = 0;
366 program.vertexShader = 0;
367 program.fragmentShader = 0;
369 program.vertexShader = dmCreateShader( GL_VERTEX_SHADER, vertexsource, optionstring );
370 if( !( program.vertexShader ) )
372 fprintf(stderr, "ERROR: Unable to load vertex shader\n");
375 program.fragmentShader = dmCreateShader( GL_FRAGMENT_SHADER, fragmentsource, optionstring );
376 if( !( program.fragmentShader ) )
378 fprintf(stderr, "ERROR: Unable to load fragment shader\n");
381 program.glProgram = glCreateProgram();
382 if( !( program.glProgram ) )
384 fprintf(stderr, "ERROR: Unable to create program\n");
388 glAttachShader( program.glProgram, program.vertexShader );
389 glAttachShader( program.glProgram, program.fragmentShader );
391 glBindAttribLocation(program.glProgram, GLBufferContents::vertex, "vertex");
392 glBindAttribLocation(program.glProgram, GLBufferContents::texCoord, "texCoord");
393 glBindAttribLocation(program.glProgram, GLBufferContents::color, "color");
394 glBindAttribLocation(program.glProgram, GLBufferContents::normal, "normal");
396 glLinkProgram( program.glProgram );
397 glGetProgramiv( program.glProgram, GL_LINK_STATUS, &status );
398 if( status != GL_TRUE )
400 fprintf( stderr, "ERROR, failed to link shader program\n" );
401 glGetProgramInfoLog( program.glProgram, 8192, &loglength, infolog );
402 fprintf( stderr, "ERROR: \n%s\n\n", infolog );
406 // glUseProgram( program.glProgram );
408 program.matrixloc = glGetUniformLocation( program.glProgram, "uniMatrix" );
409 program.vertexloc = glGetAttribLocation( program.glProgram, "inVertex" );
410 program.texcoord0loc = glGetAttribLocation( program.glProgram, "inTexcoord0" );
411 program.texcoord1loc = glGetAttribLocation( program.glProgram, "inTexcoord1" );
412 program.colorloc = glGetAttribLocation( program.glProgram, "inColor" );
413 #if DM_ENABLE_EXT_COLOR
414 program.extcolorloc = glGetAttribLocation( program.glProgram, "inExtColor" );
416 program.texbaseloc = glGetUniformLocation( program.glProgram, "texBase" );
417 program.flags.valid = true;
422 if( program.fragmentShader )
423 glDeleteShader( program.fragmentShader );
424 if( program.vertexShader )
425 glDeleteShader( program.vertexShader );
426 if( program.glProgram )
427 glDeleteProgram( program.glProgram );
435 const char *dmVertexShaderNormal =
437 "uniform mat4 uniMatrix;\n"
438 "in vec2 inVertex;\n"
439 "in vec2 inTexcoord0;\n"
441 "out vec2 varTexcoord0;\n"
442 "out vec4 varColor;\n"
446 " varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
447 " varColor = inColor;\n"
448 " gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
454 const char *dmFragmentShaderNormal =
456 "uniform sampler2D texBase;\n"
457 "in vec2 varTexcoord0;\n"
458 "in vec4 varColor;\n"
459 "out vec4 gl_FragColor;\n"
462 " gl_FragColor = varColor * texture2D( texBase, varTexcoord0 );\n"
468 const char *dmVertexShaderAlpha =
470 "uniform mat4 uniMatrix;\n"
471 "in vec2 inVertex;\n"
472 "in vec2 inTexcoord0;\n"
474 "out vec2 varTexcoord0;\n"
475 "out vec4 varColor;\n"
479 " varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
480 " varColor = inColor;\n"
481 " gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
487 const char *dmFragmentShaderAlpha =
489 "uniform sampler2D texBase;\n"
490 "in vec2 varTexcoord0;\n"
491 "in vec4 varColor;\n"
492 "out vec4 gl_FragColor;\n"
495 " gl_FragColor = vec4( varColor.rgb, varColor.a * texture2D( texBase, varTexcoord0 ).r );\n"
500 const char *dmVertexShaderAlphaIntensity =
502 "uniform mat4 uniMatrix;\n"
503 "in vec2 inVertex;\n"
504 "in vec2 inTexcoord0;\n"
506 "out vec2 varTexcoord0;\n"
507 "out vec4 varColor;\n"
511 " varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
512 " varColor = inColor;\n"
513 " gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
519 const char *dmFragmentShaderAlphaIntensity =
521 "uniform sampler2D texBase;\n"
522 "in vec2 varTexcoord0;\n"
523 "in vec4 varColor;\n"
524 "out vec4 gl_FragColor;\n"
528 " tex = texture2D( texBase, varTexcoord0 ).rg;\n"
529 " gl_FragColor = vec4( varColor.rgb * tex.g, varColor.a * tex.r );\n"
534 const char *dmVertexShaderAlphaIntensityExtColor =
536 "uniform mat4 uniMatrix;\n"
537 "in vec2 inVertex;\n"
538 "in vec2 inTexcoord0;\n"
540 "in vec4 inExtColor;\n"
541 "out vec2 varTexcoord0;\n"
542 "out vec4 varColor;\n"
543 "out vec4 varExtColor;\n"
547 " varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
548 " varColor = inColor;\n"
549 " varExtColor = inExtColor;\n"
550 " gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
556 const char *dmFragmentShaderAlphaIntensityExtColor =
558 "uniform sampler2D texBase;\n"
559 "in vec2 varTexcoord0;\n"
560 "in vec4 varColor;\n"
561 "in vec4 varExtColor;\n"
562 "out vec4 gl_FragColor;\n"
566 " tex = texture2D( texBase, varTexcoord0 ).rg;\n"
567 " gl_FragColor = vec4( mix( varExtColor.rgb, varColor.rgb, tex.g ), mix( varExtColor.a, varColor.a, tex.g ) * tex.r );\n"
575 static void matrixOrtho( float *m, float left, float right, float bottom, float top, float nearval, float farval )
577 float x = 2.0f / ( right - left );
578 float y = 2.0f / ( top - bottom );
579 float z = -2.0f / ( farval - nearval );
580 float tx = -( right + left ) / ( right - left );
581 float ty = -( top + bottom ) / ( top - bottom );
582 float tz = -( farval + nearval ) / ( farval - nearval );
584 #define M(row,col) m[col*4+row]
585 M(0,0) = x; M(0,1) = 0.0; M(0,2) = 0.0; M(0,3) = tx;
586 M(1,0) = 0.0; M(1,1) = y; M(1,2) = 0.0; M(1,3) = ty;
587 M(2,0) = 0.0; M(2,1) = 0.0; M(2,2) = z; M(2,3) = tz;
588 M(3,0) = 0.0; M(3,1) = 0.0; M(3,2) = 0.0; M(3,3) = 1.0;
595 /* FIXME: Radix sort, not hybrid sort! */
597 static inline int dmSortImagesCmp( DMImageBuffer *draw0, DMImageBuffer *draw1 )
599 return ( ( draw0->orderindex < draw1->orderindex ) ? 0 : 1 );
602 #define HSORT_MAIN dmSortImages
603 #define HSORT_CMP dmSortImagesCmp
604 #define HSORT_TYPE DMImageBuffer
605 #include "cchybridsort.h"
613 // TOFIX: Make this private, have a property
614 public class DrawManagerFlags : uint32 { public: bool prehistoricOpenGL:1; }
616 public class DrawManager
618 DrawManagerFlags flags;
619 DMProgram shaderPrograms[DM_PROGRAM_COUNT];
624 int imageBufferCount;
626 DMImageBuffer *imageBuffer;
627 DMImageBuffer *imageBufferTmp;
629 // Buffers for drawimages() batching
630 DMDrawBuffer drawBuffer[DM_CONTEXT_DRAW_BUFFER_COUNT];
632 int drawBarrierIndex;
633 uint32 orderBarrierMask;
635 // Counter to track program uniforms and such
640 static DMProgram *flushUseProgram( int programIndex )
642 DMProgram *program = &shaderPrograms[ programIndex ];
643 if( !program->flags.valid)
649 glUseProgram( program->glProgram );
650 if( program->lastUpdateCount != this.updateCount )
652 glUniformMatrix4fv( program->matrixloc, 1, GL_FALSE, this.matrix );
653 glUniform1i( program->texbaseloc, 0 );
654 program->lastUpdateCount = this.updateCount;
660 static void flushRenderDrawBufferArchaic( DMDrawBuffer drawBuffer, DMProgram program, int vertexCount )
662 glEnable( GL_TEXTURE_2D );
663 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer.vbo );
664 glColor3f( 1.0, 1.0, 1.0 );
666 glEnableClientState( GL_VERTEX_ARRAY );
667 glEnableClientState( GL_TEXTURE_COORD_ARRAY );
668 glEnableClientState( GL_COLOR_ARRAY );
670 glVertexPointer( 2, GL_FLOAT, sizeof(DMDrawVertexFlat), (void *)OFFSET(DMDrawVertexFlat,vertex) );
671 glTexCoordPointer( 2, GL_FLOAT, sizeof(DMDrawVertexFlat), (void *)OFFSET(DMDrawVertexFlat,texcoord0) );
672 glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(DMDrawVertexFlat), (void *)OFFSET(DMDrawVertexFlat,color) );
674 glDrawArrays( GL_TRIANGLES, 0, vertexCount );
676 glDisableClientState( GL_VERTEX_ARRAY );
677 glDisableClientState( GL_TEXTURE_COORD_ARRAY );
678 glDisableClientState( GL_COLOR_ARRAY );
679 glDisable( GL_TEXTURE_2D );
681 #if DM_FLUSH_EACH_RENDER_DRAW_BUFFER
686 void flushDrawImagesArchaic( )
688 bool flushflag, stateBlend;
689 int index, vertexCount, programIndex;
690 float vx0, vx1, vx2, vx3, vy0, vy1, vy2, vy3;
691 #if DM_ENABLE_IMAGE_ROTATION
692 float angsin, angcos, sizex, sizey;
694 float tx0, tx1, ty0, ty1;
695 DMImageBuffer *imageBuffer;
696 DMImage *image, *bindimage;
697 Texture texture, bindTexture;
698 DMDrawBuffer *drawBuffer;
699 DMDrawVertexFlat *vboVertex;
704 drawBarrierIndex = 0;
705 orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;
708 // Sort by image type and texture, minimize state changes
709 dmSortImages( this.imageBuffer, imageBufferTmp, imageBufferCount, (uint32)( (intptr_t)this.imageBuffer >> 4 ) );
711 // Fill a drawBuffer, write vertex and texcoords
712 drawBuffer = &this.drawBuffer[drawBufferIndex];
713 drawBufferIndex = ( drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
714 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
715 vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
718 glActiveTexture( GL_TEXTURE0 );
719 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
720 glDisable( GL_BLEND );
722 #if DM_RENDER_IMAGE_DEBUG
723 printf( " Flush %d images\n", (int)imageBufferCount );
731 imageBuffer = this.imageBuffer;
732 for( index = 0 ; index < imageBufferCount ; index++, imageBuffer++ )
734 image = imageBuffer->image;
735 texture = image->texture;
738 if( image != bindimage )
740 if( stateBlend != image->flags.blending )
742 if( texture != bindTexture )
745 if( vertexCount >= ( drawBuffer->vertexAlloc - 6 ) )
752 glUnmapBuffer( GL_ARRAY_BUFFER );
753 // Flush font manager texture updates
755 // Render buffered images
756 flushRenderDrawBufferArchaic( drawBuffer, program, vertexCount );
757 drawBuffer = &this.drawBuffer[drawBufferIndex];
758 drawBufferIndex = ( drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
759 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
760 vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
764 if( stateBlend != ( image->flags.blending ) )
766 stateBlend = image->flags.blending;
767 ( stateBlend ? glEnable : glDisable )( GL_BLEND );
768 #if DM_RENDER_IMAGE_DEBUG
769 printf( " Switch blending %d\n", stateBlend != false );
772 if( programIndex != image->programIndex )
774 programIndex = image->programIndex;
775 program = flushUseProgram( programIndex );
777 if( texture != bindTexture )
779 bindTexture = texture;
780 glBindTexture( GL_TEXTURE_2D, bindTexture.glTex );
781 #if DM_RENDER_IMAGE_DEBUG
782 printf( " Switch to texture 0x%x\n", (int)texture.orderMask );
788 #if DM_RENDER_IMAGE_DEBUG
789 printf( " Render image at %d %d, order 0x%x, texture %p\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex, texture );
792 #if DM_ENABLE_IMAGE_ROTATION
793 angsin = (float)imageBuffer->angsin * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
794 angcos = (float)imageBuffer->angcos * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
795 sizex = (float)imageBuffer->sizex;
796 sizey = (float)imageBuffer->sizey;
797 vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
798 vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
799 vx1 = vx0 + ( angcos * sizex );
800 vy1 = vy0 + ( angsin * sizex );
801 vx2 = vx0 - ( angsin * sizey );
802 vy2 = vy0 + ( angcos * sizey );
803 vx3 = vx0 + ( angcos * sizex ) - ( angsin * sizey );
804 vy3 = vy0 + ( angsin * sizex ) + ( angcos * sizey );
806 vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
807 vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
808 vx3 = vx0 + (float)( imageBuffer->sizex );
809 vy3 = vy0 + (float)( imageBuffer->sizey );
816 tx0 = (float)( image->srcx ) * texture.widthinv;
817 ty0 = (float)( image->srcy ) * texture.heightinv;
818 tx1 = (float)( image->srcx + image->sizex ) * texture.widthinv;
819 ty1 = (float)( image->srcy + image->sizey ) * texture.heightinv;
822 vboVertex[0].vertex[0] = vx3;
823 vboVertex[0].vertex[1] = vy3;
824 vboVertex[0].texcoord0[0] = tx1;
825 vboVertex[0].texcoord0[1] = ty1;
826 vboVertex[0].color = imageBuffer->color;
827 #if DM_ENABLE_EXT_COLOR
828 vboVertex[0].extcolor = imageBuffer->extcolor;
830 vboVertex[1].vertex[0] = vx1;
831 vboVertex[1].vertex[1] = vy1;
832 vboVertex[1].texcoord0[0] = tx1;
833 vboVertex[1].texcoord0[1] = ty0;
834 vboVertex[1].color = imageBuffer->color;
835 #if DM_ENABLE_EXT_COLOR
836 vboVertex[1].extcolor = imageBuffer->extcolor;
838 vboVertex[2].vertex[0] = vx2;
839 vboVertex[2].vertex[1] = vy2;
840 vboVertex[2].texcoord0[0] = tx0;
841 vboVertex[2].texcoord0[1] = ty1;
842 vboVertex[2].color = imageBuffer->color;
843 #if DM_ENABLE_EXT_COLOR
844 vboVertex[2].extcolor = imageBuffer->extcolor;
846 vboVertex[3].vertex[0] = vx0;
847 vboVertex[3].vertex[1] = vy0;
848 vboVertex[3].texcoord0[0] = tx0;
849 vboVertex[3].texcoord0[1] = ty0;
850 vboVertex[3].color = imageBuffer->color;
851 #if DM_ENABLE_EXT_COLOR
852 vboVertex[3].extcolor = imageBuffer->extcolor;
854 vboVertex[4].vertex[0] = vx2;
855 vboVertex[4].vertex[1] = vy2;
856 vboVertex[4].texcoord0[0] = tx0;
857 vboVertex[4].texcoord0[1] = ty1;
858 vboVertex[4].color = imageBuffer->color;
859 #if DM_ENABLE_EXT_COLOR
860 vboVertex[4].extcolor = imageBuffer->extcolor;
862 vboVertex[5].vertex[0] = vx1;
863 vboVertex[5].vertex[1] = vy1;
864 vboVertex[5].texcoord0[0] = tx1;
865 vboVertex[5].texcoord0[1] = ty0;
866 vboVertex[5].color = imageBuffer->color;
867 #if DM_ENABLE_EXT_COLOR
868 vboVertex[5].extcolor = imageBuffer->extcolor;
875 glUnmapBuffer( GL_ARRAY_BUFFER );
877 // Flush font manager texture updates
880 // Render buffered images
881 flushRenderDrawBufferArchaic( drawBuffer, program, vertexCount );
882 imageBufferCount = 0;
889 void flushRenderDrawBuffer( DMDrawBuffer drawBuffer, DMProgram program, int vertexCount )
891 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer.vbo );
892 if( program.vertexloc != -1 )
894 glEnableVertexAttribArray( program.vertexloc );
895 glVertexAttribPointer( program.vertexloc, 2, GL_SHORT, GL_FALSE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,vertex) );
897 if( program.texcoord0loc != -1 )
899 glEnableVertexAttribArray( program.texcoord0loc );
900 glVertexAttribPointer( program.texcoord0loc, 2, GL_SHORT, GL_FALSE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,texcoord0) );
902 if( program.colorloc != -1 )
904 glEnableVertexAttribArray( program.colorloc );
905 glVertexAttribPointer( program.colorloc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,color) );
908 #if DM_ENABLE_EXT_COLOR
909 if( program.extcolorloc != -1 )
911 glEnableVertexAttribArray( program.extcolorloc );
912 glVertexAttribPointer( program.extcolorloc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,extcolor) );
916 glDrawArrays( GL_TRIANGLES, 0, vertexCount );
918 if( program.vertexloc != -1 )
919 glDisableVertexAttribArray( program.vertexloc );
920 if( program.texcoord0loc != -1 )
921 glDisableVertexAttribArray( program.texcoord0loc );
922 if( program.colorloc != -1 )
923 glDisableVertexAttribArray( program.colorloc );
925 #if DM_FLUSH_EACH_RENDER_DRAW_BUFFER
930 void flushDrawImages( )
932 int index, stateblend, vertexcount, flushflag, programIndex;
933 float vx0, vx1, vx2, vx3, vy0, vy1, vy2, vy3;
934 #if DM_ENABLE_IMAGE_ROTATION
935 float angsin, angcos, sizex, sizey;
937 float tx0, tx1, ty0, ty1;
938 DMImageBuffer *imageBuffer;
939 DMImage *image, *bindimage;
940 Texture texture, bindtexture;
941 DMDrawBuffer *drawBuffer;
942 DMDrawVertex *vboVertex;
947 this.drawBarrierIndex = 0;
948 orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;
949 if( imageBufferCount )
951 /* Sort by image type and texture, minimize state changes */
952 dmSortImages( this.imageBuffer, this.imageBufferTmp, imageBufferCount, (uint32)( (uintptr)this.imageBuffer >> 4 ) );
954 /* Fill a drawBuffer, write vertex and texcoords */
955 drawBuffer = &this.drawBuffer[this.drawBufferIndex];
956 this.drawBufferIndex = ( this.drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
957 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
958 vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
961 glActiveTexture( GL_TEXTURE0 );
962 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
963 glDisable( GL_BLEND );
965 #if DM_RENDER_IMAGE_DEBUG
966 printf( " Flush %d images\n", (int)imageBufferCount );
974 imageBuffer = this.imageBuffer;
975 for( index = 0 ; index < imageBufferCount ; index++, imageBuffer++ )
977 image = imageBuffer->image;
978 texture = image->texture;
981 if( image != bindimage )
983 if( stateblend != ( image->flags.blending ) )
985 if( texture != bindtexture )
988 if( vertexcount >= ( drawBuffer->vertexAlloc - 6 ) )
995 glUnmapBuffer( GL_ARRAY_BUFFER );
996 // Flush font manager texture updates
999 // Render buffered images
1000 flushRenderDrawBuffer( drawBuffer, program, vertexcount );
1001 drawBuffer = &this.drawBuffer[this.drawBufferIndex];
1002 this.drawBufferIndex = ( this.drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
1003 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
1004 vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
1008 if( stateblend != ( image->flags.blending ) )
1010 stateblend = image->flags.blending;
1011 ( stateblend ? glEnable : glDisable )( GL_BLEND );
1012 #if DM_RENDER_IMAGE_DEBUG
1013 printf( " Switch blending %d\n", ( stateblend != 0 ) );
1016 if( programIndex != image->programIndex )
1018 programIndex = image->programIndex;
1019 program = flushUseProgram( programIndex );
1021 if( texture != bindtexture )
1023 bindtexture = texture;
1024 glBindTexture( GL_TEXTURE_2D, bindtexture.glTex );
1025 #if DM_RENDER_IMAGE_DEBUG
1026 printf( " Switch to texture 0x%x\n", (int)texture.orderMask );
1032 #if DM_RENDER_IMAGE_DEBUG
1033 printf( " Render image at %d %d, order 0x%x, texture %p\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex, texture );
1036 #if DM_ENABLE_IMAGE_ROTATION
1037 /* FIXME TODO: Don't go through float, compute texcoord integers directly */
1038 angsin = (float)imageBuffer->angsin * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
1039 angcos = (float)imageBuffer->angcos * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
1040 sizex = (float)imageBuffer->sizex;
1041 sizey = (float)imageBuffer->sizey;
1042 vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
1043 vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
1044 vx1 = vx0 + ( angcos * sizex );
1045 vy1 = vy0 + ( angsin * sizex );
1046 vx2 = vx0 - ( angsin * sizey );
1047 vy2 = vy0 + ( angcos * sizey );
1048 vx3 = vx0 + ( angcos * sizex ) - ( angsin * sizey );
1049 vy3 = vy0 + ( angsin * sizex ) + ( angcos * sizey );
1051 /* FIXME TODO: Don't go through float, compute texcoord integers directly */
1052 vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
1053 vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
1054 vx3 = vx0 + (float)( imageBuffer->sizex );
1055 vy3 = vy0 + (float)( imageBuffer->sizey );
1062 /* FIXME TODO: Don't go through float, compute texcoord integers directly */
1063 tx0 = (float)( image->srcx ) * texture.widthinv;
1064 ty0 = (float)( image->srcy ) * texture.heightinv;
1065 tx1 = (float)( image->srcx + image->sizex ) * texture.widthinv;
1066 ty1 = (float)( image->srcy + image->sizey ) * texture.heightinv;
1068 /* Write data to VBO */
1069 /* TODO: write vertex/texcoord all at once with SSE */
1070 vboVertex[0].vertex[0] = (short)( vx3 * DM_VERTEX_NORMFACTOR );
1071 vboVertex[0].vertex[1] = (short)( vy3 * DM_VERTEX_NORMFACTOR );
1072 vboVertex[0].texcoord0[0] = (short)( tx1 * DM_TEXCOORD_NORMFACTOR );
1073 vboVertex[0].texcoord0[1] = (short)( ty1 * DM_TEXCOORD_NORMFACTOR );
1074 vboVertex[0].color = imageBuffer->color;
1075 vboVertex[0].extcolor = imageBuffer->extcolor;
1076 vboVertex[1].vertex[0] = (short)( vx1 * DM_VERTEX_NORMFACTOR );
1077 vboVertex[1].vertex[1] = (short)( vy1 * DM_VERTEX_NORMFACTOR );
1078 vboVertex[1].texcoord0[0] = (short)( tx1 * DM_TEXCOORD_NORMFACTOR );
1079 vboVertex[1].texcoord0[1] = (short)( ty0 * DM_TEXCOORD_NORMFACTOR );
1080 vboVertex[1].color = imageBuffer->color;
1081 vboVertex[1].extcolor = imageBuffer->extcolor;
1082 vboVertex[2].vertex[0] = (short)( vx2 * DM_VERTEX_NORMFACTOR );
1083 vboVertex[2].vertex[1] = (short)( vy2 * DM_VERTEX_NORMFACTOR );
1084 vboVertex[2].texcoord0[0] = (short)( tx0 * DM_TEXCOORD_NORMFACTOR );
1085 vboVertex[2].texcoord0[1] = (short)( ty1 * DM_TEXCOORD_NORMFACTOR );
1086 vboVertex[2].color = imageBuffer->color;
1087 vboVertex[2].extcolor = imageBuffer->extcolor;
1088 vboVertex[3].vertex[0] = (short)( vx0 * DM_VERTEX_NORMFACTOR );
1089 vboVertex[3].vertex[1] = (short)( vy0 * DM_VERTEX_NORMFACTOR );
1090 vboVertex[3].texcoord0[0] = (short)( tx0 * DM_TEXCOORD_NORMFACTOR );
1091 vboVertex[3].texcoord0[1] = (short)( ty0 * DM_TEXCOORD_NORMFACTOR );
1092 vboVertex[3].color = imageBuffer->color;
1093 vboVertex[3].extcolor = imageBuffer->extcolor;
1094 vboVertex[4].vertex[0] = (short)( vx2 * DM_VERTEX_NORMFACTOR );
1095 vboVertex[4].vertex[1] = (short)( vy2 * DM_VERTEX_NORMFACTOR );
1096 vboVertex[4].texcoord0[0] = (short)( tx0 * DM_TEXCOORD_NORMFACTOR );
1097 vboVertex[4].texcoord0[1] = (short)( ty1 * DM_TEXCOORD_NORMFACTOR );
1098 vboVertex[4].color = imageBuffer->color;
1099 vboVertex[4].extcolor = imageBuffer->extcolor;
1100 vboVertex[5].vertex[0] = (short)( vx1 * DM_VERTEX_NORMFACTOR );
1101 vboVertex[5].vertex[1] = (short)( vy1 * DM_VERTEX_NORMFACTOR );
1102 vboVertex[5].texcoord0[0] = (short)( tx1 * DM_TEXCOORD_NORMFACTOR );
1103 vboVertex[5].texcoord0[1] = (short)( ty0 * DM_TEXCOORD_NORMFACTOR );
1104 vboVertex[5].color = imageBuffer->color;
1105 vboVertex[5].extcolor = imageBuffer->extcolor;
1111 glUnmapBuffer( GL_ARRAY_BUFFER );
1112 // Flush font manager texture updates
1114 // Render buffered images
1115 flushRenderDrawBuffer( drawBuffer, program, vertexcount );
1116 imageBufferCount = 0;
1124 virtual void flush();
1126 bool init( DrawManagerFlags flags )
1128 int drawBufferIndex, programIndex;
1129 DMDrawBuffer *drawBuffer;
1132 imageBufferCount = 0;
1133 imageBufferSize = 4096;
1134 imageBuffer = new DMImageBuffer[imageBufferSize];
1135 imageBufferTmp = new DMImageBuffer[imageBufferSize];
1139 if( flags.prehistoricOpenGL )
1140 vertexSize = sizeof(DMDrawVertexFlat);
1144 for( programIndex = 0 ; programIndex < DM_PROGRAM_COUNT ; programIndex++ )
1146 program = &shaderPrograms[ programIndex ];
1148 program->lastUpdateCount = -1;
1150 program = &shaderPrograms[ DM_PROGRAM_NORMAL ];
1151 if( !( dmCreateProgram( program, dmVertexShaderNormal, dmFragmentShaderNormal, 0 ) ) )
1153 program = &shaderPrograms[ DM_PROGRAM_ALPHABLEND ];
1154 if( !( dmCreateProgram( program, dmVertexShaderAlpha, dmFragmentShaderAlpha, 0 ) ) )
1156 program = &shaderPrograms[ DM_PROGRAM_ALPHABLEND_INTENSITY ];
1157 if( !( dmCreateProgram( program, dmVertexShaderAlphaIntensity, dmFragmentShaderAlphaIntensity, 0 ) ) )
1159 program = &shaderPrograms[ DM_PROGRAM_ALPHABLEND_INTENSITY_EXTCOLOR ];
1160 if( !( dmCreateProgram( program, dmVertexShaderAlphaIntensityExtColor, dmFragmentShaderAlphaIntensityExtColor, 0 ) ) )
1162 // glUseProgram( 0 );
1163 vertexSize = sizeof(DMDrawVertex);
1166 for( drawBufferIndex = 0 ; drawBufferIndex < DM_CONTEXT_DRAW_BUFFER_COUNT ; drawBufferIndex++ )
1168 drawBuffer = &this.drawBuffer[drawBufferIndex];
1169 drawBuffer->glType = GL_FLOAT;
1170 drawBuffer->vertexCount = 0;
1171 drawBuffer->vertexAlloc = DM_CONTEXT_DRAW_BUFFER_VERTEX_ALLOC;
1174 glGenBuffers( 1, &drawBuffer->vbo );
1175 glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
1176 glBufferData( GL_ARRAY_BUFFER, drawBuffer->vertexAlloc * vertexSize, 0, GL_DYNAMIC_DRAW );
1178 drawBuffer->vertexBuffer = new byte[drawBuffer->vertexAlloc * vertexSize];
1191 for( i = 0 ; i < DM_CONTEXT_DRAW_BUFFER_COUNT ; i++ )
1193 DMDrawBuffer *db = &drawBuffer[i];
1195 glDeleteBuffers( 1, &db->vbo );
1196 delete db->vertexBuffer;
1199 // TODO: Destroy the shaders!
1201 delete imageBufferTmp;
1204 void ready( int viewportwidth, int viewportheight )
1208 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *)&prevProgram);
1209 // while(glGetError());
1213 // Save OpenGL state
1214 // FIXME: no glPushAttrib() in core profile
1216 glPushClientAttrib( GL_CLIENT_ALL_ATTRIB_BITS );
1217 glPushAttrib( GL_ALL_ATTRIB_BITS );
1220 // Prepare rendering pass
1221 matrixOrtho( matrix, 0.0, (float)viewportwidth, (float)viewportheight, 0.0, -1.0f, 1.0 );
1222 norminv = 1.0f / DM_VERTEX_NORMFACTOR;
1223 for( mindex = 0 ; mindex < 12 ; mindex += 4 )
1225 matrix[mindex+0] *= norminv;
1226 matrix[mindex+1] *= norminv;
1227 matrix[mindex+2] *= norminv;
1229 drawBarrierIndex = 0;
1230 orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;
1231 orderBarrierMask = 0;
1236 void drawImage( DMImage image, int offsetx, int offsety, int sizex, int sizey, uint32 color )
1238 DMImageBuffer *imageBuffer;
1240 if( image.flags.empty || ( sizex <= 0 ) || ( sizey <= 0 ) )
1243 if( imageBufferCount >= imageBufferSize )
1245 imageBufferSize <<= 1;
1246 this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
1247 imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
1250 imageBuffer = &this.imageBuffer[ imageBufferCount ];
1251 imageBuffer->image = image;
1252 imageBuffer->offsetx = (short)(offsetx << DM_VERTEX_NORMSHIFT);
1253 imageBuffer->offsety = (short)(offsety << DM_VERTEX_NORMSHIFT);
1254 imageBuffer->sizex = (short)sizex;
1255 imageBuffer->sizey = (short)sizey;
1256 #if DM_ENABLE_IMAGE_ROTATION
1257 imageBuffer->angsin = 0;
1258 imageBuffer->angcos = (short)DM_IMAGE_ROTATION_NORMFACTOR;
1260 imageBuffer->color = color;
1261 imageBuffer->orderindex = image.orderMask | orderBarrierMask;
1263 #if DM_RENDER_IMAGE_DEBUG
1264 printf( " Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
1270 void drawImageExtColor( DMImage image, int offsetx, int offsety, int sizex, int sizey, uint32 color, uint32 extcolor )
1272 DMImageBuffer *imageBuffer;
1274 if( ( image.flags.empty ) || ( sizex <= 0 ) || ( sizey <= 0 ) )
1277 if( imageBufferCount >= imageBufferSize )
1279 imageBufferSize <<= 1;
1280 this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
1281 imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
1284 imageBuffer = &this.imageBuffer[ imageBufferCount ];
1285 imageBuffer->image = image;
1286 imageBuffer->offsetx = (short)(offsetx << DM_VERTEX_NORMSHIFT);
1287 imageBuffer->offsety = (short)(offsety << DM_VERTEX_NORMSHIFT);
1288 imageBuffer->sizex = (short)sizex;
1289 imageBuffer->sizey = (short)sizey;
1290 #if DM_ENABLE_IMAGE_ROTATION
1291 imageBuffer->angsin = 0;
1292 imageBuffer->angcos = (short)DM_IMAGE_ROTATION_NORMFACTOR;
1294 imageBuffer->color = color;
1295 #if DM_ENABLE_EXT_COLOR
1296 imageBuffer->extcolor = extcolor;
1298 imageBuffer->orderindex = image.orderMask | orderBarrierMask;
1300 #if DM_RENDER_IMAGE_DEBUG
1301 printf( " Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
1304 this.imageBufferCount++;
1307 void drawImageFloat( DMImage image, float offsetx, float offsety, float sizex, float sizey, float angsin, float angcos, uint32 color )
1309 DMImageBuffer *imageBuffer;
1311 if( image.flags.empty || sizex <= 0 || sizey <= 0 )
1314 if( imageBufferCount >= imageBufferSize )
1316 imageBufferSize <<= 1;
1317 this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
1318 imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
1321 imageBuffer = &this.imageBuffer[ imageBufferCount ];
1322 imageBuffer->image = image;
1323 imageBuffer->offsetx = (short)roundf(offsetx * DM_VERTEX_NORMFACTOR);
1324 imageBuffer->offsety = (short)roundf(offsety * DM_VERTEX_NORMFACTOR);
1325 imageBuffer->sizex = (short)sizex;
1326 imageBuffer->sizey = (short)sizey;
1327 #if DM_ENABLE_IMAGE_ROTATION
1328 imageBuffer->angsin = (short)roundf( angsin * DM_IMAGE_ROTATION_NORMFACTOR );
1329 imageBuffer->angcos = (short)roundf( angcos * DM_IMAGE_ROTATION_NORMFACTOR );
1331 imageBuffer->color = color;
1332 imageBuffer->orderindex = image.orderMask | orderBarrierMask;
1334 #if DM_RENDER_IMAGE_DEBUG
1335 printf( " Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
1341 void drawImageFloatExtColor( DMImage image, float offsetx, float offsety, float sizex, float sizey, float angsin, float angcos, uint32 color, uint32 extcolor )
1343 DMImageBuffer *imageBuffer;
1345 if( ( image.flags.empty ) || ( sizex <= 0 ) || ( sizey <= 0 ) )
1348 if( this.imageBufferCount >= this.imageBufferSize )
1350 imageBufferSize <<= 1;
1351 this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
1352 imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
1355 imageBuffer = &this.imageBuffer[ imageBufferCount ];
1356 imageBuffer->image = image;
1357 imageBuffer->offsetx = (short)roundf( offsetx * DM_VERTEX_NORMFACTOR );
1358 imageBuffer->offsety = (short)roundf( offsety * DM_VERTEX_NORMFACTOR );
1359 imageBuffer->sizex = (short)sizex;
1360 imageBuffer->sizey = (short)sizey;
1361 #if DM_ENABLE_IMAGE_ROTATION
1362 imageBuffer->angsin = (short)roundf( angsin * DM_IMAGE_ROTATION_NORMFACTOR );
1363 imageBuffer->angcos = (short)roundf( angcos * DM_IMAGE_ROTATION_NORMFACTOR );
1365 imageBuffer->color = color;
1366 #if DM_ENABLE_EXT_COLOR
1367 imageBuffer->extcolor = extcolor;
1369 imageBuffer->orderindex = image.orderMask | orderBarrierMask;
1371 #if DM_RENDER_IMAGE_DEBUG
1372 printf( " Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
1375 this.imageBufferCount++;
1380 if( flags.prehistoricOpenGL )
1381 flushDrawImagesArchaic( );
1386 glBindBuffer( GL_ARRAY_BUFFER, 0 );
1387 glabCurArrayBuffer = 0;
1388 if( !flags.prehistoricOpenGL )
1389 glUseProgram( prevProgram );
1390 // Restore OpenGL state
1391 // FIXME: no glPushAttrib() in core profile
1394 glPopClientAttrib();
1401 if( drawBarrierIndex >= ( 1 << DM_BARRIER_ORDER_BITS ) )
1403 orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;