tigr_gl.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. #ifndef TIGR_HEADLESS
  2. #include "tigr_internal.h"
  3. #include <assert.h>
  4. #ifdef TIGR_GAPI_GL
  5. #if __linux__
  6. #if __ANDROID__
  7. #include <GLES3/gl3.h>
  8. #else
  9. #define GLX_GLXEXT_PROTOTYPES
  10. #include <GL/glext.h>
  11. #endif
  12. #endif
  13. extern const char tigr_upscale_gl_vs[], tigr_upscale_gl_fs[], tigr_default_fx_gl_fs[];
  14. extern const int tigr_upscale_gl_vs_size, tigr_upscale_gl_fs_size, tigr_default_fx_gl_fs_size;
  15. #ifdef _WIN32
  16. #ifdef TIGR_GAPI_GL_WIN_USE_GLEXT
  17. #include <glext.h>
  18. #include <wglext.h>
  19. #else // short version of glext.h and wglext.h so we don't need to depend on them
  20. #ifndef APIENTRY
  21. #define APIENTRY
  22. #endif
  23. #ifndef APIENTRYP
  24. #define APIENTRYP APIENTRY*
  25. #endif
  26. typedef ptrdiff_t GLsizeiptr;
  27. #define GL_COMPILE_STATUS 0x8B81
  28. #define GL_LINK_STATUS 0x8B82
  29. #define GL_ARRAY_BUFFER 0x8892
  30. #define GL_STATIC_DRAW 0x88E4
  31. #define GL_VERTEX_SHADER 0x8B31
  32. #define GL_FRAGMENT_SHADER 0x8B30
  33. #define GL_BGRA 0x80E1
  34. #define GL_TEXTURE0 0x84C0
  35. typedef void(APIENTRYP PFNGLGENVERTEXARRAYSPROC)(GLsizei n, GLuint* arrays);
  36. typedef void(APIENTRYP PFNGLGENBUFFERSARBPROC)(GLsizei n, GLuint* buffers);
  37. typedef void(APIENTRYP PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer);
  38. typedef void(APIENTRYP PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
  39. typedef void(APIENTRYP PFNGLBINDVERTEXARRAYPROC)(GLuint array);
  40. typedef void(APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index);
  41. typedef void(APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index,
  42. GLint size,
  43. GLenum type,
  44. GLboolean normalized,
  45. GLsizei stride,
  46. const void* pointer);
  47. typedef GLuint(APIENTRYP PFNGLCREATESHADERPROC)(GLenum type);
  48. typedef char GLchar;
  49. typedef void(APIENTRYP PFNGLSHADERSOURCEPROC)(GLuint shader,
  50. GLsizei count,
  51. const GLchar* const* string,
  52. const GLint* length);
  53. typedef void(APIENTRYP PFNGLCOMPILESHADERPROC)(GLuint shader);
  54. typedef GLuint(APIENTRYP PFNGLCREATEPROGRAMPROC)(void);
  55. typedef void(APIENTRYP PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader);
  56. typedef void(APIENTRYP PFNGLLINKPROGRAMPROC)(GLuint program);
  57. typedef void(APIENTRYP PFNGLDELETESHADERPROC)(GLuint shader);
  58. typedef void(APIENTRYP PFNGLDELETEPROGRAMPROC)(GLuint program);
  59. typedef void(APIENTRYP PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint* params);
  60. typedef void(APIENTRYP PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
  61. typedef void(APIENTRYP PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint* params);
  62. typedef void(APIENTRYP PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
  63. typedef void(APIENTRYP PFNGLUSEPROGRAMPROC)(GLuint program);
  64. typedef GLint(APIENTRYP PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar* name);
  65. typedef void(APIENTRYP PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
  66. typedef void(APIENTRYP PFNGLUNIFORMMATRIX4FVPROC)(GLint location,
  67. GLsizei count,
  68. GLboolean transpose,
  69. const GLfloat* value);
  70. typedef void(APIENTRYP PFNGLACTIVETEXTUREPROC)(GLenum texture);
  71. #define WGL_DRAW_TO_WINDOW_ARB 0x2001
  72. #define WGL_SUPPORT_OPENGL_ARB 0x2010
  73. #define WGL_DOUBLE_BUFFER_ARB 0x2011
  74. #define WGL_PIXEL_TYPE_ARB 0x2013
  75. #define WGL_COLOR_BITS_ARB 0x2014
  76. #define WGL_DEPTH_BITS_ARB 0x2022
  77. #define WGL_STENCIL_BITS_ARB 0x2023
  78. #define WGL_TYPE_RGBA_ARB 0x202B
  79. #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
  80. #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
  81. typedef BOOL(WINAPI* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc,
  82. const int* piAttribIList,
  83. const FLOAT* pfAttribFList,
  84. UINT nMaxFormats,
  85. int* piFormats,
  86. UINT* nNumFormats);
  87. typedef HGLRC(WINAPI* PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hDC, HGLRC hShareContext, const int* attribList);
  88. #endif
  89. PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat;
  90. PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs;
  91. PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
  92. PFNGLGENBUFFERSARBPROC glGenBuffers;
  93. PFNGLBINDBUFFERPROC glBindBuffer;
  94. PFNGLBUFFERDATAPROC glBufferData;
  95. PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
  96. PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
  97. PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
  98. PFNGLCREATESHADERPROC glCreateShader;
  99. PFNGLSHADERSOURCEPROC glShaderSource;
  100. PFNGLCOMPILESHADERPROC glCompileShader;
  101. PFNGLCREATEPROGRAMPROC glCreateProgram;
  102. PFNGLATTACHSHADERPROC glAttachShader;
  103. PFNGLLINKPROGRAMPROC glLinkProgram;
  104. PFNGLDELETESHADERPROC glDeleteShader;
  105. PFNGLDELETEPROGRAMPROC glDeleteProgram;
  106. PFNGLGETSHADERIVPROC glGetShaderiv;
  107. PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
  108. PFNGLGETPROGRAMIVPROC glGetProgramiv;
  109. PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
  110. PFNGLUSEPROGRAMPROC glUseProgram;
  111. PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
  112. PFNGLUNIFORM4FPROC glUniform4f;
  113. PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
  114. PFNGLACTIVETEXTUREPROC glActiveTexture;
  115. int tigrGL11Init(Tigr* bmp) {
  116. int pixel_format;
  117. TigrInternal* win = tigrInternal(bmp);
  118. GLStuff* gl = &win->gl;
  119. PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR),
  120. 1,
  121. PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_SWAP_EXCHANGE,
  122. PFD_TYPE_RGBA,
  123. 32, // color bits
  124. 0,
  125. 0,
  126. 0,
  127. 0,
  128. 0,
  129. 0,
  130. 0,
  131. 0,
  132. 0,
  133. 0,
  134. 0,
  135. 0,
  136. 0,
  137. 24, // depth
  138. 8, // stencil
  139. 0,
  140. PFD_MAIN_PLANE, // is it ignored ?
  141. 0,
  142. 0,
  143. 0,
  144. 0 };
  145. if (!(gl->dc = GetDC((HWND)bmp->handle))) {
  146. tigrError(bmp, "Cannot create OpenGL device context.\n");
  147. return -1;
  148. }
  149. if (!(pixel_format = ChoosePixelFormat(gl->dc, &pfd))) {
  150. tigrError(bmp, "Cannot choose OpenGL pixel format.\n");
  151. return -1;
  152. }
  153. if (!SetPixelFormat(gl->dc, pixel_format, &pfd)) {
  154. tigrError(bmp, "Cannot set OpenGL pixel format.\n");
  155. return -1;
  156. }
  157. if (!(gl->hglrc = wglCreateContext(gl->dc))) {
  158. tigrError(bmp, "Cannot create OpenGL context.\n");
  159. return -1;
  160. }
  161. if (!wglMakeCurrent(gl->dc, gl->hglrc)) {
  162. tigrError(bmp, "Cannot activate OpenGL context.\n");
  163. return -1;
  164. }
  165. gl->gl_legacy = 1;
  166. return 0;
  167. }
  168. int tigrGL33Init(Tigr* bmp) {
  169. int pixel_format;
  170. UINT num_formats;
  171. TigrInternal* win = tigrInternal(bmp);
  172. GLStuff* gl = &win->gl;
  173. wglChoosePixelFormat = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
  174. wglCreateContextAttribs = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
  175. glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)wglGetProcAddress("glGenVertexArrays");
  176. glGenBuffers = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffers");
  177. glBindBuffer = (PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer");
  178. glBufferData = (PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData");
  179. glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)wglGetProcAddress("glBindVertexArray");
  180. glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress("glEnableVertexAttribArray");
  181. glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)wglGetProcAddress("glVertexAttribPointer");
  182. glCreateShader = (PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader");
  183. glShaderSource = (PFNGLSHADERSOURCEPROC)wglGetProcAddress("glShaderSource");
  184. glCompileShader = (PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader");
  185. glCreateProgram = (PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram");
  186. glAttachShader = (PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader");
  187. glLinkProgram = (PFNGLLINKPROGRAMPROC)wglGetProcAddress("glLinkProgram");
  188. glDeleteShader = (PFNGLDELETESHADERPROC)wglGetProcAddress("glDeleteShader");
  189. glDeleteProgram = (PFNGLDELETEPROGRAMPROC)wglGetProcAddress("glDeleteProgram");
  190. glGetShaderiv = (PFNGLGETSHADERIVPROC)wglGetProcAddress("glGetShaderiv");
  191. glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)wglGetProcAddress("glGetShaderInfoLog");
  192. glGetProgramiv = (PFNGLGETPROGRAMIVPROC)wglGetProcAddress("glGetProgramiv");
  193. glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)wglGetProcAddress("glGetProgramInfoLog");
  194. glUseProgram = (PFNGLUSEPROGRAMPROC)wglGetProcAddress("glUseProgram");
  195. glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)wglGetProcAddress("glGetUniformLocation");
  196. glUniform4f = (PFNGLUNIFORM4FPROC)wglGetProcAddress("glUniform4f");
  197. glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)wglGetProcAddress("glUniformMatrix4fv");
  198. glActiveTexture = (PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture");
  199. if (!wglChoosePixelFormat || !wglCreateContextAttribs) {
  200. tigrError(bmp, "Cannot create OpenGL context.\n");
  201. return -1;
  202. }
  203. const int attribList[] = { WGL_DRAW_TO_WINDOW_ARB,
  204. GL_TRUE,
  205. WGL_SUPPORT_OPENGL_ARB,
  206. GL_TRUE,
  207. WGL_DOUBLE_BUFFER_ARB,
  208. GL_TRUE,
  209. WGL_PIXEL_TYPE_ARB,
  210. WGL_TYPE_RGBA_ARB,
  211. WGL_COLOR_BITS_ARB,
  212. 32,
  213. WGL_DEPTH_BITS_ARB,
  214. 24,
  215. WGL_STENCIL_BITS_ARB,
  216. 8,
  217. 0 };
  218. int attribs[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 3, 0 };
  219. if (!wglChoosePixelFormat(gl->dc, attribList, NULL, 1, &pixel_format, &num_formats)) {
  220. tigrError(bmp, "Cannot choose OpenGL pixel format.\n");
  221. return -1;
  222. }
  223. if (!(gl->hglrc = wglCreateContextAttribs(gl->dc, gl->hglrc, attribs))) {
  224. tigrError(bmp, "Cannot create OpenGL context attribs.\n");
  225. return -1;
  226. }
  227. if (!wglMakeCurrent(gl->dc, gl->hglrc)) {
  228. tigrError(bmp, "Cannot activate OpenGL context.\n");
  229. return -1;
  230. }
  231. gl->gl_legacy = 0;
  232. return 0;
  233. }
  234. #endif
  235. void tigrCheckGLError(const char* state) {
  236. GLenum err = glGetError();
  237. if (err != GL_NO_ERROR) {
  238. tigrError(NULL, "got GL error %x when doing %s\n", err, state);
  239. }
  240. }
  241. void tigrCheckShaderErrors(GLuint object) {
  242. GLint success;
  243. GLchar info[2048];
  244. glGetShaderiv(object, GL_COMPILE_STATUS, &success);
  245. if (!success) {
  246. glGetShaderInfoLog(object, sizeof(info), NULL, info);
  247. tigrError(NULL, "shader compile error : %s\n", info);
  248. }
  249. }
  250. void tigrCheckProgramErrors(GLuint object) {
  251. GLint success;
  252. GLchar info[2048];
  253. glGetProgramiv(object, GL_LINK_STATUS, &success);
  254. if (!success) {
  255. glGetProgramInfoLog(object, sizeof(info), NULL, info);
  256. tigrError(NULL, "shader link error : %s\n", info);
  257. }
  258. }
  259. void tigrCreateShaderProgram(GLStuff* gl, const char* fxSource, int fxSize) {
  260. if (gl->program != 0) {
  261. glDeleteProgram(gl->program);
  262. gl->program = 0;
  263. }
  264. GLuint vs = glCreateShader(GL_VERTEX_SHADER);
  265. const char* vs_source = (const char*)&tigr_upscale_gl_vs;
  266. glShaderSource(vs, 1, &vs_source, &tigr_upscale_gl_vs_size);
  267. glCompileShader(vs);
  268. tigrCheckShaderErrors(vs);
  269. GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
  270. const char* fs_sources[] = {
  271. (const char*)tigr_upscale_gl_fs,
  272. fxSource,
  273. };
  274. const int fs_lengths[] = {
  275. tigr_upscale_gl_fs_size,
  276. fxSize,
  277. };
  278. glShaderSource(fs, 2, fs_sources, fs_lengths);
  279. glCompileShader(fs);
  280. tigrCheckShaderErrors(fs);
  281. gl->program = glCreateProgram();
  282. glAttachShader(gl->program, vs);
  283. glAttachShader(gl->program, fs);
  284. glLinkProgram(gl->program);
  285. tigrCheckProgramErrors(gl->program);
  286. glDeleteShader(vs);
  287. glDeleteShader(fs);
  288. gl->uniform_projection = glGetUniformLocation(gl->program, "projection");
  289. gl->uniform_model = glGetUniformLocation(gl->program, "model");
  290. gl->uniform_parameters = glGetUniformLocation(gl->program, "parameters");
  291. }
  292. void tigrGAPICreate(Tigr* bmp) {
  293. TigrInternal* win = tigrInternal(bmp);
  294. GLStuff* gl = &win->gl;
  295. GLuint VBO;
  296. GLfloat vertices[] = { // pos uv
  297. 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
  298. 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f
  299. };
  300. #ifdef _WIN32
  301. if (tigrGL11Init(bmp))
  302. return;
  303. tigrGL33Init(bmp);
  304. #endif
  305. if (!gl->gl_legacy) {
  306. // create vao
  307. glGenVertexArrays(1, &gl->vao);
  308. glGenBuffers(1, &VBO);
  309. glBindBuffer(GL_ARRAY_BUFFER, VBO);
  310. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  311. glBindVertexArray(gl->vao);
  312. glEnableVertexAttribArray(0);
  313. glEnableVertexAttribArray(1);
  314. glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), NULL);
  315. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), NULL);
  316. // create program
  317. tigrCreateShaderProgram(gl, tigr_default_fx_gl_fs, tigr_default_fx_gl_fs_size);
  318. }
  319. // create textures
  320. if (gl->gl_legacy) {
  321. glEnable(GL_TEXTURE_2D);
  322. }
  323. glGenTextures(2, gl->tex);
  324. for (int i = 0; i < 2; ++i) {
  325. glBindTexture(GL_TEXTURE_2D, gl->tex[i]);
  326. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl->gl_legacy ? GL_NEAREST : GL_LINEAR);
  327. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl->gl_legacy ? GL_NEAREST : GL_LINEAR);
  328. glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  329. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  330. }
  331. tigrCheckGLError("initialization");
  332. }
  333. void tigrGAPIDestroy(Tigr* bmp) {
  334. TigrInternal* win = tigrInternal(bmp);
  335. GLStuff* gl = &win->gl;
  336. if (tigrGAPIBegin(bmp) < 0) {
  337. tigrError(bmp, "Cannot activate OpenGL context.\n");
  338. return;
  339. }
  340. if (!gl->gl_legacy) {
  341. glDeleteTextures(2, gl->tex);
  342. glDeleteProgram(gl->program);
  343. }
  344. tigrCheckGLError("destroy");
  345. if (tigrGAPIEnd(bmp) < 0) {
  346. tigrError(bmp, "Cannot deactivate OpenGL context.\n");
  347. return;
  348. }
  349. }
  350. void tigrGAPIDraw(int legacy, GLuint uniform_model, GLuint tex, Tigr* bmp, int x1, int y1, int x2, int y2) {
  351. glBindTexture(GL_TEXTURE_2D, tex);
  352. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, bmp->w, bmp->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, bmp->pix);
  353. if (!legacy) {
  354. float sx = (float)(x2 - x1);
  355. float sy = (float)(y2 - y1);
  356. float tx = (float)x1;
  357. float ty = (float)y1;
  358. float model[16] = { sx, 0.0f, 0.0f, 0.0f, 0.0f, sy, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, tx, ty, 0.0f, 1.0f };
  359. glUniformMatrix4fv(uniform_model, 1, GL_FALSE, model);
  360. glDrawArrays(GL_TRIANGLES, 0, 6);
  361. } else {
  362. #if !(__APPLE__ || __ANDROID__)
  363. glBegin(GL_QUADS);
  364. glTexCoord2f(1.0f, 0.0f);
  365. glVertex2i(x2, y1);
  366. glTexCoord2f(0.0f, 0.0f);
  367. glVertex2i(x1, y1);
  368. glTexCoord2f(0.0f, 1.0f);
  369. glVertex2i(x1, y2);
  370. glTexCoord2f(1.0f, 1.0f);
  371. glVertex2i(x2, y2);
  372. glEnd();
  373. #else
  374. assert(0);
  375. #endif
  376. }
  377. }
  378. void tigrGAPIPresent(Tigr* bmp, int w, int h) {
  379. TigrInternal* win = tigrInternal(bmp);
  380. GLStuff* gl = &win->gl;
  381. glViewport(0, 0, w, h);
  382. if (!gl->gl_user_opengl_rendering) {
  383. glClearColor(0, 0, 0, 1);
  384. glClear(GL_COLOR_BUFFER_BIT);
  385. }
  386. if (!gl->gl_legacy) {
  387. float projection[16] = { 2.0f / w, 0.0f, 0.0f, 0.0f, 0.0f, -2.0f / h, 0.0f, 0.0f,
  388. 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f };
  389. glActiveTexture(GL_TEXTURE0);
  390. glBindVertexArray(gl->vao);
  391. glUseProgram(gl->program);
  392. glUniformMatrix4fv(gl->uniform_projection, 1, GL_FALSE, projection);
  393. glUniform4f(gl->uniform_parameters, win->p1, win->p2, win->p3, win->p4);
  394. } else {
  395. #if !(__APPLE__ || __ANDROID__)
  396. glMatrixMode(GL_PROJECTION);
  397. glLoadIdentity();
  398. glOrtho(0, w, h, 0, -1.0f, 1.0f);
  399. glEnable(GL_TEXTURE_2D);
  400. #else
  401. assert(0);
  402. #endif
  403. }
  404. if (gl->gl_user_opengl_rendering) {
  405. glEnable(GL_BLEND);
  406. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  407. } else {
  408. glDisable(GL_BLEND);
  409. }
  410. tigrGAPIDraw(gl->gl_legacy, gl->uniform_model, gl->tex[0], bmp, win->pos[0], win->pos[1], win->pos[2], win->pos[3]);
  411. if (win->widgetsScale > 0) {
  412. glEnable(GL_BLEND);
  413. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  414. tigrGAPIDraw(gl->gl_legacy, gl->uniform_model, gl->tex[1], win->widgets,
  415. (int)(w - win->widgets->w * win->widgetsScale), 0, w, (int)(win->widgets->h * win->widgetsScale));
  416. }
  417. tigrCheckGLError("present");
  418. gl->gl_user_opengl_rendering = 0;
  419. }
  420. #endif
  421. #endif // #ifndef TIGR_HEADLESS