1 // Written in the D programming language. 2 3 /** 4 DLANGUI library. 5 6 This module contains OpenGL access layer. 7 8 To enable OpenGL support, build with version(USE_OPENGL); 9 10 Synopsis: 11 12 ---- 13 import dlangui.graphics.glsupport; 14 15 ---- 16 17 Copyright: Vadim Lopatin, 2014 18 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 19 Authors: $(WEB coolreader.org, Vadim Lopatin) 20 */ 21 module dlangui.graphics.glsupport; 22 23 version(USE_OPENGL) { 24 25 import dlangui.core.logger; 26 private import derelict.opengl3.gl3; 27 //private import gl3n.linalg; 28 private import dlangui.core.types; 29 private import std.conv; 30 31 // utility function to fill 4-float array of vertex colors with converted CR 32bit color 32 private void LVGLFillColor(uint color, float * buf, int count) { 33 float r = ((color >> 16) & 255) / 255.0f; 34 float g = ((color >> 8) & 255) / 255.0f; 35 float b = ((color >> 0) & 255) / 255.0f; 36 float a = (((color >> 24) & 255) ^ 255) / 255.0f; 37 for (int i=0; i<count; i++) { 38 *buf++ = r; 39 *buf++ = g; 40 *buf++ = b; 41 *buf++ = a; 42 } 43 } 44 45 /// for OpenGL calls diagnostics. 46 private bool checkError(string context, string file = __FILE__, int line = __LINE__) { 47 int err = glGetError(); 48 if (err != GL_NO_ERROR) { 49 //string errorString = fromStringz(gluErrorString()); 50 Log.e("OpenGL error ", err, " at ", file, ":", line, " -- ", context); 51 return true; 52 } 53 return false; 54 } 55 56 immutable float Z_2D = -2.0f; 57 void drawSolidFillRect(Rect rc, uint color1, uint color2, uint color3, uint color4) { 58 float[6 * 4] colors; 59 LVGLFillColor(color1, colors.ptr + 4*0, 1); 60 LVGLFillColor(color4, colors.ptr + 4*1, 1); 61 LVGLFillColor(color3, colors.ptr + 4*2, 1); 62 LVGLFillColor(color1, colors.ptr + 4*3, 1); 63 LVGLFillColor(color3, colors.ptr + 4*4, 1); 64 LVGLFillColor(color2, colors.ptr + 4*5, 1); 65 float x0 = cast(float)(rc.left); 66 float y0 = cast(float)(bufferDy-rc.top); 67 float x1 = cast(float)(rc.right); 68 float y1 = cast(float)(bufferDy-rc.bottom); 69 70 // don't flip for framebuffer 71 if (currentFramebufferId) { 72 y0 = cast(float)(rc.top); 73 y1 = cast(float)(rc.bottom); 74 } 75 76 float[3 * 6] vertices = [ 77 x0,y0,Z_2D, 78 x0,y1,Z_2D, 79 x1,y1,Z_2D, 80 x0,y0,Z_2D, 81 x1,y1,Z_2D, 82 x1,y0,Z_2D]; 83 if (_solidFillProgram !is null) { 84 //Log.d("solid fill: vertices ", vertices, " colors ", colors); 85 _solidFillProgram.execute(vertices, colors); 86 } else 87 Log.e("No program"); 88 } 89 90 void drawColorAndTextureRect(uint textureId, int tdx, int tdy, Rect srcrc, Rect dstrc, uint color, bool linear) { 91 //Log.v("drawColorAndTextureRect tx=", textureId, " src=", srcrc, " dst=", dstrc); 92 drawColorAndTextureRect(textureId, tdx, tdy, srcrc.left, srcrc.top, srcrc.width(), srcrc.height(), dstrc.left, dstrc.top, dstrc.width(), dstrc.height(), color, linear); 93 } 94 95 void drawColorAndTextureRect(uint textureId, int tdx, int tdy, int srcx, int srcy, int srcdx, int srcdy, int xx, int yy, int dx, int dy, uint color, bool linear) { 96 float colors[6*4]; 97 LVGLFillColor(color, colors.ptr, 6); 98 float dstx0 = cast(float)xx; 99 float dsty0 = cast(float)(bufferDy - (yy)); 100 float dstx1 = cast(float)(xx + dx); 101 float dsty1 = cast(float)(bufferDy - (yy + dy)); 102 103 // don't flip for framebuffer 104 if (currentFramebufferId) { 105 dsty0 = cast(float)((yy)); 106 dsty1 = cast(float)((yy + dy)); 107 } 108 109 float srcx0 = srcx / cast(float)tdx; 110 float srcy0 = srcy / cast(float)tdy; 111 float srcx1 = (srcx + srcdx) / cast(float)tdx; 112 float srcy1 = (srcy + srcdy) / cast(float)tdy; 113 float[3 * 6] vertices = [dstx0,dsty0,Z_2D, 114 dstx0,dsty1,Z_2D, 115 dstx1,dsty1,Z_2D, 116 dstx0,dsty0,Z_2D, 117 dstx1,dsty1,Z_2D, 118 dstx1,dsty0,Z_2D]; 119 float[2 * 6] texcoords = [srcx0,srcy0, srcx0,srcy1, srcx1,srcy1, srcx0,srcy0, srcx1,srcy1, srcx1,srcy0]; 120 _textureProgram.execute(vertices, texcoords, colors, textureId, linear); 121 //drawColorAndTextureRect(vertices, texcoords, colors, textureId, linear); 122 } 123 124 /// generate new texture ID 125 uint genTexture() { 126 GLuint textureId = 0; 127 glGenTextures(1, &textureId); 128 return textureId; 129 } 130 131 /// delete OpenGL texture 132 void deleteTexture(ref uint textureId) { 133 if (!textureId) 134 return; 135 if (glIsTexture(textureId) != GL_TRUE) { 136 Log.e("Invalid texture ", textureId); 137 return; 138 } 139 GLuint id = textureId; 140 glDeleteTextures(1, &id); 141 checkError("glDeleteTextures"); 142 textureId = 0; 143 } 144 145 /// call glFlush 146 void flushGL() { 147 glFlush(); 148 checkError("glFlush"); 149 } 150 151 bool setTextureImage(uint textureId, int dx, int dy, ubyte * pixels) { 152 //checkError("before setTextureImage"); 153 glActiveTexture(GL_TEXTURE0); 154 checkError("updateTexture - glActiveTexture"); 155 glBindTexture(GL_TEXTURE_2D, 0); 156 checkError("updateTexture - glBindTexture(0)"); 157 glBindTexture(GL_TEXTURE_2D, textureId); 158 checkError("updateTexture - glBindTexture"); 159 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 160 checkError("updateTexture - glPixelStorei"); 161 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 162 checkError("updateTexture - glTexParameteri"); 163 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 164 checkError("updateTexture - glTexParameteri"); 165 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 166 checkError("updateTexture - glTexParameteri"); 167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 168 checkError("updateTexture - glTexParameteri"); 169 170 if (!glIsTexture(textureId)) 171 Log.e("second test - invalid texture passed to CRGLSupportImpl::setTextureImage"); 172 173 // ORIGINAL: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dx, dy, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 174 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dx, dy, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 175 checkError("updateTexture - glTexImage2D"); 176 if (glGetError() != GL_NO_ERROR) { 177 Log.e("Cannot set image for texture"); 178 return false; 179 } 180 checkError("after setTextureImage"); 181 return true; 182 } 183 184 bool setTextureImageAlpha(uint textureId, int dx, int dy, ubyte * pixels) { 185 checkError("before setTextureImageAlpha"); 186 glActiveTexture(GL_TEXTURE0); 187 checkError("updateTexture - glActiveTexture"); 188 glBindTexture(GL_TEXTURE_2D, 0); 189 checkError("updateTexture - glBindTexture(0)"); 190 glBindTexture(GL_TEXTURE_2D, textureId); 191 checkError("setTextureImageAlpha - glBindTexture"); 192 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 193 checkError("setTextureImageAlpha - glPixelStorei"); 194 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 195 checkError("setTextureImageAlpha - glTexParameteri"); 196 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 197 checkError("setTextureImageAlpha - glTexParameteri"); 198 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 199 checkError("setTextureImageAlpha - glTexParameteri"); 200 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 201 checkError("setTextureImageAlpha - glTexParameteri"); 202 203 if (!glIsTexture(textureId)) 204 Log.e("second test: invalid texture passed to CRGLSupportImpl::setTextureImageAlpha"); 205 206 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, dx, dy, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels); 207 checkError("setTextureImageAlpha - glTexImage2D"); 208 if (glGetError() != GL_NO_ERROR) { 209 Log.e("Cannot set image for texture"); 210 return false; 211 } 212 glBindTexture(GL_TEXTURE_2D, 0); 213 checkError("updateTexture - glBindTexture(0)"); 214 checkError("after setTextureImageAlpha"); 215 return true; 216 } 217 218 private uint currentFramebufferId; 219 220 /// returns texture ID for buffer, 0 if failed 221 bool createFramebuffer(ref uint textureId, ref uint framebufferId, int dx, int dy) { 222 checkError("before createFramebuffer"); 223 bool res = true; 224 textureId = framebufferId = 0; 225 textureId = genTexture(); 226 if (!textureId) 227 return false; 228 GLuint fid = 0; 229 glGenFramebuffers(1, &fid); 230 if (checkError("createFramebuffer glGenFramebuffersOES")) return false; 231 framebufferId = fid; 232 glBindFramebuffer(GL_FRAMEBUFFER, framebufferId); 233 if (checkError("createFramebuffer glBindFramebuffer")) return false; 234 235 glBindTexture(GL_TEXTURE_2D, textureId); 236 checkError("glBindTexture(GL_TEXTURE_2D, _textureId)"); 237 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, dx, dy, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, null); 238 checkError("glTexImage2D"); 239 240 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 241 checkError("texParameter"); 242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 243 checkError("texParameter"); 244 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 245 checkError("texParameter"); 246 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 247 checkError("texParameter"); 248 249 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0); 250 checkError("glFramebufferTexture2D"); 251 // Always check that our framebuffer is ok 252 if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 253 Log.e("glFramebufferTexture2D failed"); 254 res = false; 255 } 256 checkError("glCheckFramebufferStatus"); 257 //glClearColor(0.5f, 0, 0, 1); 258 glClearColor(0.5f, 0.5f, 0.5f, 1.0f); 259 checkError("glClearColor"); 260 glClear(GL_COLOR_BUFFER_BIT); 261 checkError("glClear"); 262 checkError("after createFramebuffer"); 263 //CRLog::trace("CRGLSupportImpl::createFramebuffer %d,%d texture=%d, buffer=%d", dx, dy, textureId, framebufferId); 264 currentFramebufferId = framebufferId; 265 266 glBindTexture(GL_TEXTURE_2D, 0); 267 checkError("createFramebuffer - glBindTexture(0)"); 268 glBindFramebuffer(GL_FRAMEBUFFER, 0); 269 checkError("createFramebuffer - glBindFramebuffer(0)"); 270 271 return res; 272 } 273 274 void deleteFramebuffer(ref uint framebufferId) { 275 //CRLog::debug("GLDrawBuf::deleteFramebuffer"); 276 if (framebufferId != 0) { 277 glBindFramebuffer(GL_FRAMEBUFFER, 0); 278 checkError("deleteFramebuffer - glBindFramebuffer"); 279 GLuint fid = framebufferId; 280 glDeleteFramebuffers(1, &fid); 281 checkError("deleteFramebuffer - glDeleteFramebuffer"); 282 } 283 //CRLog::trace("CRGLSupportImpl::deleteFramebuffer(%d)", framebufferId); 284 framebufferId = 0; 285 checkError("after deleteFramebuffer"); 286 currentFramebufferId = 0; 287 } 288 289 bool bindFramebuffer(uint framebufferId) { 290 //CRLog::trace("CRGLSupportImpl::bindFramebuffer(%d)", framebufferId); 291 glBindFramebuffer(GL_FRAMEBUFFER, framebufferId); 292 currentFramebufferId = framebufferId; 293 return !checkError("glBindFramebuffer"); 294 } 295 296 /// projection matrix 297 //private mat4 m; 298 /// current gl buffer width 299 private int bufferDx; 300 /// current gl buffer height 301 private int bufferDy; 302 303 //private float[16] matrix; 304 private float[16] qtmatrix; 305 306 void QMatrix4x4_ortho(float left, float right, float bottom, float top, float nearPlane, float farPlane) 307 { 308 // Bail out if the projection volume is zero-sized. 309 if (left == right || bottom == top || nearPlane == farPlane) 310 return; 311 312 // Construct the projection. 313 float width = right - left; 314 float invheight = top - bottom; 315 float clip = farPlane - nearPlane; 316 float[4][4] m; 317 m[0][0] = 2.0f / width; 318 m[1][0] = 0.0f; 319 m[2][0] = 0.0f; 320 m[3][0] = -(left + right) / width; 321 m[0][1] = 0.0f; 322 m[1][1] = 2.0f / invheight; 323 m[2][1] = 0.0f; 324 m[3][1] = -(top + bottom) / invheight; 325 m[0][2] = 0.0f; 326 m[1][2] = 0.0f; 327 m[2][2] = -2.0f / clip; 328 m[3][2] = -(nearPlane + farPlane) / clip; 329 m[0][3] = 0.0f; 330 m[1][3] = 0.0f; 331 m[2][3] = 0.0f; 332 m[3][3] = 1.0f; 333 for (int y = 0; y < 4; y++) 334 for (int x = 0; x < 4; x++) 335 qtmatrix[y * 4 + x] = m[y][x]; 336 } 337 338 void setOrthoProjection(int dx, int dy) { 339 bufferDx = dx; 340 bufferDy = dy; 341 QMatrix4x4_ortho(0, dx, 0, dy, 0.5f, 50.0f); 342 glViewport(0, 0, dx, dy); 343 checkError("glViewport"); 344 } 345 346 class GLProgram { 347 @property abstract string vertexSource(); 348 @property abstract string fragmentSource(); 349 protected GLuint vertexShader; 350 protected GLuint fragmentShader; 351 protected GLuint program; 352 protected bool initialized; 353 protected bool error; 354 protected string glslversion; 355 this() { 356 } 357 private GLuint compileShader(string src, GLuint type) { 358 import core.stdc.stdlib; 359 import std.string; 360 361 Log.d("compileShader glsl=", glslversion, " code: ", src); 362 363 GLuint shader = glCreateShader(type);//GL_VERTEX_SHADER 364 const char * psrc = src.toStringz; 365 GLuint len = cast(uint)src.length; 366 glShaderSource(shader, 1, &psrc, cast(const(int)*)&len); 367 glCompileShader(shader); 368 GLint compiled; 369 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 370 if (compiled) { 371 // compiled successfully 372 return shader; 373 } else { 374 GLint blen = 0; 375 GLsizei slen = 0; 376 glGetShaderiv(shader, GL_INFO_LOG_LENGTH , &blen); 377 if (blen > 1) 378 { 379 GLchar[] msg = new GLchar[blen + 1]; 380 GLchar * pmsg = &msg[0]; 381 glGetShaderInfoLog(shader, blen, &slen, pmsg); 382 Log.d("Shader compilation error: ", fromStringz(pmsg)); 383 } 384 return 0; 385 } 386 } 387 bool compile() { 388 glslversion = fromStringz(glGetString(GL_SHADING_LANGUAGE_VERSION)); 389 vertexShader = compileShader(vertexSource, GL_VERTEX_SHADER); 390 fragmentShader = compileShader(fragmentSource, GL_FRAGMENT_SHADER); 391 if (!vertexShader || !fragmentShader) { 392 error = true; 393 return false; 394 } 395 program = glCreateProgram(); 396 glAttachShader(program, vertexShader); 397 glAttachShader(program, fragmentShader); 398 glLinkProgram(program); 399 GLint isLinked = 0; 400 glGetProgramiv(program, GL_LINK_STATUS, &isLinked); 401 if (!isLinked) { 402 GLint maxLength = 0; 403 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength); 404 GLchar[] msg = new GLchar[maxLength + 1]; 405 GLchar * pmsg = &msg[0]; 406 glGetProgramInfoLog(program, maxLength, &maxLength, pmsg); 407 Log.e("Error while linking program: ", fromStringz(pmsg)); 408 error = true; 409 return false; 410 } 411 Log.d("Program compiled successfully"); 412 //glDetachShader(program, vertexShader); 413 //glDetachShader(program, fragmentShader); 414 glUseProgram(program); 415 checkError("glUseProgram " ~ to!string(program)); 416 if (!initLocations()) { 417 Log.e("some of locations were not found"); 418 error = true; 419 } 420 initialized = true; 421 return true; 422 } 423 bool initLocations() { 424 return true; 425 } 426 bool bind() { 427 if (!initialized) 428 return false; 429 if (!glIsProgram(program)) 430 Log.e("!glIsProgram(program)"); 431 glUseProgram(program); 432 checkError("glUseProgram " ~ to!string(program)); 433 return true; 434 } 435 void release() { 436 glUseProgram(0); 437 checkError("glUseProgram(0)"); 438 } 439 ~this() { 440 clear(); 441 } 442 void clear() { 443 // TODO: cleanup 444 if (program) 445 glDeleteProgram(program); 446 if (vertexShader) 447 glDeleteShader(vertexShader); 448 if (fragmentShader) 449 glDeleteShader(fragmentShader); 450 program = vertexShader = fragmentShader = 0; 451 initialized = false; 452 } 453 } 454 455 immutable string HIGHP = ""; 456 immutable string LOWP = ""; 457 immutable string MEDIUMP = ""; 458 459 class SolidFillProgram : GLProgram { 460 @property override string vertexSource() { 461 return 462 "attribute " ~ HIGHP ~ " vec4 vertex;\n" 463 "attribute " ~ LOWP ~ " vec4 colAttr;\n" 464 "varying " ~ LOWP ~ " vec4 col;\n" 465 "uniform " ~ MEDIUMP ~ " mat4 matrix;\n" 466 "void main(void)\n" 467 "{\n" 468 " gl_Position = matrix * vertex;\n" 469 " col = colAttr;\n" 470 "}\n"; 471 472 } 473 @property override string fragmentSource() { 474 return 475 "varying " ~ LOWP ~ " vec4 col;\n" 476 "void main(void)\n" 477 "{\n" 478 " gl_FragColor = col;\n" 479 "}\n"; 480 } 481 482 void beforeExecute() { 483 glEnable(GL_BLEND); 484 glDisable(GL_CULL_FACE); 485 checkError("glDisable(GL_CULL_FACE)"); 486 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 487 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 488 checkError("glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)"); 489 bind(); 490 //glUniformMatrix4fv(matrixLocation, 1, false, m.value_ptr); 491 //glUniformMatrix4fv(matrixLocation, 1, false, matrix.ptr); 492 glUniformMatrix4fv(matrixLocation, 1, false, qtmatrix.ptr); 493 checkError("glUniformMatrix4fv"); 494 } 495 496 void afterExecute() { 497 release(); 498 } 499 500 protected GLint matrixLocation; 501 protected GLint vertexLocation; 502 protected GLint colAttrLocation; 503 protected GLuint vertexBuffer; 504 protected GLuint colAttrBuffer; 505 override bool initLocations() { 506 bool res = super.initLocations(); 507 508 //glGenBuffers(1, &vertexBuffer); 509 //glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 510 //glBufferData(GL_ARRAY_BUFFER, float.sizeof * 3 * 6, null, GL_DYNAMIC_DRAW); 511 //glGenBuffers(1, &colAttrBuffer); 512 //glBindBuffer(GL_ARRAY_BUFFER, colAttrBuffer); 513 //glBufferData(GL_ARRAY_BUFFER, float.sizeof * 4 * 6, null, GL_DYNAMIC_DRAW); 514 515 matrixLocation = glGetUniformLocation(program, "matrix"); 516 checkError("glGetUniformLocation matrix"); 517 vertexLocation = glGetAttribLocation(program, "vertex"); 518 checkError("glGetAttribLocation vertex"); 519 colAttrLocation = glGetAttribLocation(program, "colAttr"); 520 checkError("glGetAttribLocation colAttr"); 521 return res && matrixLocation >= 0 && vertexLocation >= 0 && colAttrLocation >= 0; 522 } 523 524 bool execute(float[] vertices, float[] colors) { 525 if (error) 526 return false; 527 if (!initialized) 528 if (!compile()) 529 return false; 530 beforeExecute(); 531 532 glEnableVertexAttribArray(vertexLocation); 533 checkError("glEnableVertexAttribArray"); 534 glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, float.sizeof * 3, vertices.ptr); 535 checkError("glVertexAttribPointer"); 536 537 glEnableVertexAttribArray(colAttrLocation); 538 checkError("glEnableVertexAttribArray"); 539 glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, float.sizeof * 4, colors.ptr); 540 checkError("glVertexAttribPointer"); 541 542 glDrawArrays(GL_TRIANGLES, 0, 6); 543 checkError("glDrawArrays"); 544 545 glDisableVertexAttribArray(vertexLocation); 546 checkError("glDisableVertexAttribArray"); 547 glDisableVertexAttribArray(colAttrLocation); 548 checkError("glDisableVertexAttribArray"); 549 550 afterExecute(); 551 return true; 552 } 553 } 554 555 class TextureProgram : SolidFillProgram { 556 @property override string vertexSource() { 557 return 558 "attribute " ~ HIGHP ~ " vec4 vertex;\n" 559 "attribute " ~ LOWP ~ " vec4 colAttr;\n" 560 "attribute " ~ MEDIUMP ~ " vec4 texCoord;\n" 561 "varying " ~ LOWP ~ " vec4 col;\n" 562 "varying " ~ MEDIUMP ~ " vec4 texc;\n" 563 "uniform " ~ MEDIUMP ~ " mat4 matrix;\n" 564 "void main(void)\n" 565 "{\n" 566 " gl_Position = matrix * vertex;\n" 567 " col = colAttr;\n" 568 " texc = texCoord;\n" 569 "}\n"; 570 571 } 572 @property override string fragmentSource() { 573 return 574 "uniform sampler2D texture;\n" 575 "varying " ~ LOWP ~ " vec4 col;\n" 576 "varying " ~ MEDIUMP ~ " vec4 texc;\n" 577 "void main(void)\n" 578 "{\n" 579 " gl_FragColor = texture2D(texture, texc.st) * col;\n" 580 "}\n"; 581 } 582 583 GLint texCoordLocation; 584 override bool initLocations() { 585 bool res = super.initLocations(); 586 texCoordLocation = glGetAttribLocation(program, "texCoord"); 587 return res && texCoordLocation >= 0; 588 } 589 590 bool execute(float[] vertices, float[] texcoords, float[] colors, uint textureId, bool linear) { 591 if (error) 592 return false; 593 if (!initialized) 594 if (!compile()) 595 return false; 596 beforeExecute(); 597 glActiveTexture(GL_TEXTURE0); 598 checkError("glActiveTexture GL_TEXTURE0"); 599 glBindTexture(GL_TEXTURE_2D, textureId); 600 checkError("glBindTexture"); 601 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST); 602 checkError("drawColorAndTextureRect - glTexParameteri"); 603 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST); 604 checkError("drawColorAndTextureRect - glTexParameteri"); 605 606 glEnableVertexAttribArray(vertexLocation); 607 glEnableVertexAttribArray(colAttrLocation); 608 glEnableVertexAttribArray(texCoordLocation); 609 610 glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices.ptr); 611 glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, colors.ptr); 612 glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords.ptr); 613 614 glDrawArrays(GL_TRIANGLES, 0, 6); 615 checkError("glDrawArrays"); 616 617 glDisableVertexAttribArray(vertexLocation); 618 glDisableVertexAttribArray(colAttrLocation); 619 glDisableVertexAttribArray(texCoordLocation); 620 621 afterExecute(); 622 glBindTexture(GL_TEXTURE_2D, 0); 623 checkError("glBindTexture"); 624 return true; 625 } 626 } 627 628 __gshared TextureProgram _textureProgram; 629 __gshared SolidFillProgram _solidFillProgram; 630 631 bool initShaders() { 632 if (_textureProgram is null) { 633 _textureProgram = new TextureProgram(); 634 if (!_textureProgram.compile()) 635 return false; 636 } 637 if (_solidFillProgram is null) { 638 _solidFillProgram = new SolidFillProgram(); 639 if (!_solidFillProgram.compile()) 640 return false; 641 } 642 Log.d("Shaders compiled successfully"); 643 return true; 644 } 645 646 bool uninitShaders() { 647 Log.d("Uniniting shaders"); 648 if (_textureProgram !is null) { 649 destroy(_textureProgram); 650 _textureProgram = null; 651 } 652 if (_solidFillProgram !is null) { 653 destroy(_solidFillProgram); 654 _solidFillProgram = null; 655 } 656 return true; 657 } 658 659 bool isTexture(uint textureId) { 660 return glIsTexture(textureId) == GL_TRUE; 661 } 662 663 void setRotation(int x, int y, int rotationAngle) { 664 /* 665 this->rotationAngle = rotationAngle; 666 rotationX = x; 667 rotationY = y; 668 if (!currentFramebufferId) { 669 rotationY = bufferDy - rotationY; 670 } 671 672 QMatrix4x4 matrix2; 673 matrix2.ortho(0, bufferDx, 0, bufferDy, 0.5f, 5.0f); 674 if (rotationAngle) { 675 matrix2.translate(rotationX, rotationY, 0); 676 matrix2.rotate(rotationAngle, 0, 0, 1); 677 matrix2.translate(-rotationX, -rotationY, 0); 678 } 679 matrix2.copyDataTo(m); 680 */ 681 } 682 683 684 }