OpenTTD Source  1.11.2
opengl.cpp
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #include "../stdafx.h"
13 
14 /* Define to disable buffer syncing. Will increase max fast forward FPS but produces artifacts. Mainly useful for performance testing. */
15 // #define NO_GL_BUFFER_SYNC
16 /* Define to allow software rendering backends. */
17 // #define GL_ALLOW_SOFTWARE_RENDERER
18 
19 #if defined(_WIN32)
20 # include <windows.h>
21 #endif
22 
23 #define GL_GLEXT_PROTOTYPES
24 #if defined(__APPLE__)
25 # include <OpenGL/gl3.h>
26 #else
27 # include <GL/gl.h>
28 #endif
29 #include "../3rdparty/opengl/glext.h"
30 
31 #include "opengl.h"
32 #include "../core/geometry_func.hpp"
33 #include "../core/mem_func.hpp"
34 #include "../core/math_func.hpp"
35 #include "../core/mem_func.hpp"
36 #include "../gfx_func.h"
37 #include "../debug.h"
38 #include "../blitter/factory.hpp"
39 #include "../zoom_func.h"
40 #include <array>
41 #include <numeric>
42 
43 #include "../table/opengl_shader.h"
44 #include "../table/sprites.h"
45 
46 
47 #include "../safeguards.h"
48 
49 
50 /* Define function pointers of all OpenGL functions that we load dynamically. */
51 
52 #define GL(function) static decltype(&function) _ ## function
53 
54 GL(glGetString);
55 GL(glGetIntegerv);
56 GL(glGetError);
57 GL(glDebugMessageControl);
58 GL(glDebugMessageCallback);
59 
60 GL(glDisable);
61 GL(glEnable);
62 GL(glViewport);
63 GL(glClear);
64 GL(glClearColor);
65 GL(glBlendFunc);
66 GL(glDrawArrays);
67 
68 GL(glTexImage1D);
69 GL(glTexImage2D);
70 GL(glTexParameteri);
71 GL(glTexSubImage1D);
72 GL(glTexSubImage2D);
73 GL(glBindTexture);
74 GL(glDeleteTextures);
75 GL(glGenTextures);
76 GL(glPixelStorei);
77 
78 GL(glActiveTexture);
79 
80 GL(glGenBuffers);
81 GL(glDeleteBuffers);
82 GL(glBindBuffer);
83 GL(glBufferData);
84 GL(glBufferSubData);
85 GL(glMapBuffer);
86 GL(glUnmapBuffer);
87 GL(glClearBufferSubData);
88 
89 GL(glBufferStorage);
90 GL(glMapBufferRange);
91 GL(glClientWaitSync);
92 GL(glFenceSync);
93 GL(glDeleteSync);
94 
95 GL(glGenVertexArrays);
96 GL(glDeleteVertexArrays);
97 GL(glBindVertexArray);
98 
99 GL(glCreateProgram);
100 GL(glDeleteProgram);
101 GL(glLinkProgram);
102 GL(glUseProgram);
103 GL(glGetProgramiv);
104 GL(glGetProgramInfoLog);
105 GL(glCreateShader);
106 GL(glDeleteShader);
107 GL(glShaderSource);
108 GL(glCompileShader);
109 GL(glAttachShader);
110 GL(glGetShaderiv);
111 GL(glGetShaderInfoLog);
112 GL(glGetUniformLocation);
113 GL(glUniform1i);
114 GL(glUniform1f);
115 GL(glUniform2f);
116 GL(glUniform4f);
117 
118 GL(glGetAttribLocation);
119 GL(glEnableVertexAttribArray);
120 GL(glDisableVertexAttribArray);
121 GL(glVertexAttribPointer);
122 GL(glBindFragDataLocation);
123 
124 #undef GL
125 
126 
129  float x, y;
130  float u, v;
131 };
132 
134 static const int MAX_CACHED_CURSORS = 48;
135 
136 /* static */ OpenGLBackend *OpenGLBackend::instance = nullptr;
137 
138 GetOGLProcAddressProc GetOGLProcAddress;
139 
147 const char *FindStringInExtensionList(const char *string, const char *substring)
148 {
149  while (1) {
150  /* Is the extension string present at all? */
151  const char *pos = strstr(string, substring);
152  if (pos == nullptr) break;
153 
154  /* Is this a real match, i.e. are the chars before and after the matched string
155  * indeed spaces (or the start or end of the string, respectively)? */
156  const char *end = pos + strlen(substring);
157  if ((pos == string || pos[-1] == ' ') && (*end == ' ' || *end == '\0')) return pos;
158 
159  /* False hit, try again for the remaining string. */
160  string = end;
161  }
162 
163  return nullptr;
164 }
165 
171 static bool IsOpenGLExtensionSupported(const char *extension)
172 {
173  static PFNGLGETSTRINGIPROC glGetStringi = nullptr;
174  static bool glGetStringi_loaded = false;
175 
176  /* Starting with OpenGL 3.0 the preferred API to get the extensions
177  * has changed. Try to load the required function once. */
178  if (!glGetStringi_loaded) {
179  if (IsOpenGLVersionAtLeast(3, 0)) glGetStringi = (PFNGLGETSTRINGIPROC)GetOGLProcAddress("glGetStringi");
180  glGetStringi_loaded = true;
181  }
182 
183  if (glGetStringi != nullptr) {
184  /* New style: Each supported extension can be queried and compared independently. */
185  GLint num_exts;
186  _glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts);
187 
188  for (GLint i = 0; i < num_exts; i++) {
189  const char *entry = (const char *)glGetStringi(GL_EXTENSIONS, i);
190  if (strcmp(entry, extension) == 0) return true;
191  }
192  } else {
193  /* Old style: A single, space-delimited string for all extensions. */
194  return FindStringInExtensionList((const char *)_glGetString(GL_EXTENSIONS), extension) != nullptr;
195  }
196 
197  return false;
198 }
199 
200 static byte _gl_major_ver = 0;
201 static byte _gl_minor_ver = 0;
202 
210 bool IsOpenGLVersionAtLeast(byte major, byte minor)
211 {
212  return (_gl_major_ver > major) || (_gl_major_ver == major && _gl_minor_ver >= minor);
213 }
214 
222 template <typename F>
223 static bool BindGLProc(F &f, const char *name)
224 {
225  f = reinterpret_cast<F>(GetOGLProcAddress(name));
226  return f != nullptr;
227 }
228 
230 static bool BindBasicInfoProcs()
231 {
232  if (!BindGLProc(_glGetString, "glGetString")) return false;
233  if (!BindGLProc(_glGetIntegerv, "glGetIntegerv")) return false;
234  if (!BindGLProc(_glGetError, "glGetError")) return false;
235 
236  return true;
237 }
238 
240 static bool BindBasicOpenGLProcs()
241 {
242  if (!BindGLProc(_glDisable, "glDisable")) return false;
243  if (!BindGLProc(_glEnable, "glEnable")) return false;
244  if (!BindGLProc(_glViewport, "glViewport")) return false;
245  if (!BindGLProc(_glTexImage1D, "glTexImage1D")) return false;
246  if (!BindGLProc(_glTexImage2D, "glTexImage2D")) return false;
247  if (!BindGLProc(_glTexParameteri, "glTexParameteri")) return false;
248  if (!BindGLProc(_glTexSubImage1D, "glTexSubImage1D")) return false;
249  if (!BindGLProc(_glTexSubImage2D, "glTexSubImage2D")) return false;
250  if (!BindGLProc(_glBindTexture, "glBindTexture")) return false;
251  if (!BindGLProc(_glDeleteTextures, "glDeleteTextures")) return false;
252  if (!BindGLProc(_glGenTextures, "glGenTextures")) return false;
253  if (!BindGLProc(_glPixelStorei, "glPixelStorei")) return false;
254  if (!BindGLProc(_glClear, "glClear")) return false;
255  if (!BindGLProc(_glClearColor, "glClearColor")) return false;
256  if (!BindGLProc(_glBlendFunc, "glBlendFunc")) return false;
257  if (!BindGLProc(_glDrawArrays, "glDrawArrays")) return false;
258 
259  return true;
260 }
261 
263 static bool BindTextureExtensions()
264 {
265  if (IsOpenGLVersionAtLeast(1, 3)) {
266  if (!BindGLProc(_glActiveTexture, "glActiveTexture")) return false;
267  } else {
268  if (!BindGLProc(_glActiveTexture, "glActiveTextureARB")) return false;
269  }
270 
271  return true;
272 }
273 
275 static bool BindVBOExtension()
276 {
277  if (IsOpenGLVersionAtLeast(1, 5)) {
278  if (!BindGLProc(_glGenBuffers, "glGenBuffers")) return false;
279  if (!BindGLProc(_glDeleteBuffers, "glDeleteBuffers")) return false;
280  if (!BindGLProc(_glBindBuffer, "glBindBuffer")) return false;
281  if (!BindGLProc(_glBufferData, "glBufferData")) return false;
282  if (!BindGLProc(_glBufferSubData, "glBufferSubData")) return false;
283  if (!BindGLProc(_glMapBuffer, "glMapBuffer")) return false;
284  if (!BindGLProc(_glUnmapBuffer, "glUnmapBuffer")) return false;
285  } else {
286  if (!BindGLProc(_glGenBuffers, "glGenBuffersARB")) return false;
287  if (!BindGLProc(_glDeleteBuffers, "glDeleteBuffersARB")) return false;
288  if (!BindGLProc(_glBindBuffer, "glBindBufferARB")) return false;
289  if (!BindGLProc(_glBufferData, "glBufferDataARB")) return false;
290  if (!BindGLProc(_glBufferSubData, "glBufferSubDataARB")) return false;
291  if (!BindGLProc(_glMapBuffer, "glMapBufferARB")) return false;
292  if (!BindGLProc(_glUnmapBuffer, "glUnmapBufferARB")) return false;
293  }
294 
295  if (IsOpenGLVersionAtLeast(4, 3) || IsOpenGLExtensionSupported("GL_ARB_clear_buffer_object")) {
296  BindGLProc(_glClearBufferSubData, "glClearBufferSubData");
297  } else {
298  _glClearBufferSubData = nullptr;
299  }
300 
301  return true;
302 }
303 
305 static bool BindVBAExtension()
306 {
307  /* The APPLE and ARB variants have different semantics (that don't matter for us).
308  * Successfully getting pointers to one variant doesn't mean it is supported for
309  * the current context. Always check the extension strings as well. */
310  if (IsOpenGLVersionAtLeast(3, 0) || IsOpenGLExtensionSupported("GL_ARB_vertex_array_object")) {
311  if (!BindGLProc(_glGenVertexArrays, "glGenVertexArrays")) return false;
312  if (!BindGLProc(_glDeleteVertexArrays, "glDeleteVertexArrays")) return false;
313  if (!BindGLProc(_glBindVertexArray, "glBindVertexArray")) return false;
314  } else if (IsOpenGLExtensionSupported("GL_APPLE_vertex_array_object")) {
315  if (!BindGLProc(_glGenVertexArrays, "glGenVertexArraysAPPLE")) return false;
316  if (!BindGLProc(_glDeleteVertexArrays, "glDeleteVertexArraysAPPLE")) return false;
317  if (!BindGLProc(_glBindVertexArray, "glBindVertexArrayAPPLE")) return false;
318  }
319 
320  return true;
321 }
322 
324 static bool BindShaderExtensions()
325 {
326  if (IsOpenGLVersionAtLeast(2, 0)) {
327  if (!BindGLProc(_glCreateProgram, "glCreateProgram")) return false;
328  if (!BindGLProc(_glDeleteProgram, "glDeleteProgram")) return false;
329  if (!BindGLProc(_glLinkProgram, "glLinkProgram")) return false;
330  if (!BindGLProc(_glUseProgram, "glUseProgram")) return false;
331  if (!BindGLProc(_glGetProgramiv, "glGetProgramiv")) return false;
332  if (!BindGLProc(_glGetProgramInfoLog, "glGetProgramInfoLog")) return false;
333  if (!BindGLProc(_glCreateShader, "glCreateShader")) return false;
334  if (!BindGLProc(_glDeleteShader, "glDeleteShader")) return false;
335  if (!BindGLProc(_glShaderSource, "glShaderSource")) return false;
336  if (!BindGLProc(_glCompileShader, "glCompileShader")) return false;
337  if (!BindGLProc(_glAttachShader, "glAttachShader")) return false;
338  if (!BindGLProc(_glGetShaderiv, "glGetShaderiv")) return false;
339  if (!BindGLProc(_glGetShaderInfoLog, "glGetShaderInfoLog")) return false;
340  if (!BindGLProc(_glGetUniformLocation, "glGetUniformLocation")) return false;
341  if (!BindGLProc(_glUniform1i, "glUniform1i")) return false;
342  if (!BindGLProc(_glUniform1f, "glUniform1f")) return false;
343  if (!BindGLProc(_glUniform2f, "glUniform2f")) return false;
344  if (!BindGLProc(_glUniform4f, "glUniform4f")) return false;
345 
346  if (!BindGLProc(_glGetAttribLocation, "glGetAttribLocation")) return false;
347  if (!BindGLProc(_glEnableVertexAttribArray, "glEnableVertexAttribArray")) return false;
348  if (!BindGLProc(_glDisableVertexAttribArray, "glDisableVertexAttribArray")) return false;
349  if (!BindGLProc(_glVertexAttribPointer, "glVertexAttribPointer")) return false;
350  } else {
351  /* In the ARB extension programs and shaders are in the same object space. */
352  if (!BindGLProc(_glCreateProgram, "glCreateProgramObjectARB")) return false;
353  if (!BindGLProc(_glDeleteProgram, "glDeleteObjectARB")) return false;
354  if (!BindGLProc(_glLinkProgram, "glLinkProgramARB")) return false;
355  if (!BindGLProc(_glUseProgram, "glUseProgramObjectARB")) return false;
356  if (!BindGLProc(_glGetProgramiv, "glGetObjectParameterivARB")) return false;
357  if (!BindGLProc(_glGetProgramInfoLog, "glGetInfoLogARB")) return false;
358  if (!BindGLProc(_glCreateShader, "glCreateShaderObjectARB")) return false;
359  if (!BindGLProc(_glDeleteShader, "glDeleteObjectARB")) return false;
360  if (!BindGLProc(_glShaderSource, "glShaderSourceARB")) return false;
361  if (!BindGLProc(_glCompileShader, "glCompileShaderARB")) return false;
362  if (!BindGLProc(_glAttachShader, "glAttachObjectARB")) return false;
363  if (!BindGLProc(_glGetShaderiv, "glGetObjectParameterivARB")) return false;
364  if (!BindGLProc(_glGetShaderInfoLog, "glGetInfoLogARB")) return false;
365  if (!BindGLProc(_glGetUniformLocation, "glGetUniformLocationARB")) return false;
366  if (!BindGLProc(_glUniform1i, "glUniform1iARB")) return false;
367  if (!BindGLProc(_glUniform1f, "glUniform1fARB")) return false;
368  if (!BindGLProc(_glUniform2f, "glUniform2fARB")) return false;
369  if (!BindGLProc(_glUniform4f, "glUniform4fARB")) return false;
370 
371  if (!BindGLProc(_glGetAttribLocation, "glGetAttribLocationARB")) return false;
372  if (!BindGLProc(_glEnableVertexAttribArray, "glEnableVertexAttribArrayARB")) return false;
373  if (!BindGLProc(_glDisableVertexAttribArray, "glDisableVertexAttribArrayARB")) return false;
374  if (!BindGLProc(_glVertexAttribPointer, "glVertexAttribPointerARB")) return false;
375  }
376 
377  /* Bind functions only needed when using GLSL 1.50 shaders. */
378  if (IsOpenGLVersionAtLeast(3, 0)) {
379  BindGLProc(_glBindFragDataLocation, "glBindFragDataLocation");
380  } else if (IsOpenGLExtensionSupported("GL_EXT_gpu_shader4")) {
381  BindGLProc(_glBindFragDataLocation, "glBindFragDataLocationEXT");
382  } else {
383  _glBindFragDataLocation = nullptr;
384  }
385 
386  return true;
387 }
388 
390 static bool BindPersistentBufferExtensions()
391 {
392  /* Optional functions for persistent buffer mapping. */
393  if (IsOpenGLVersionAtLeast(3, 0)) {
394  if (!BindGLProc(_glMapBufferRange, "glMapBufferRange")) return false;
395  }
396  if (IsOpenGLVersionAtLeast(4, 4) || IsOpenGLExtensionSupported("GL_ARB_buffer_storage")) {
397  if (!BindGLProc(_glBufferStorage, "glBufferStorage")) return false;
398  }
399 #ifndef NO_GL_BUFFER_SYNC
400  if (IsOpenGLVersionAtLeast(3, 2) || IsOpenGLExtensionSupported("GL_ARB_sync")) {
401  if (!BindGLProc(_glClientWaitSync, "glClientWaitSync")) return false;
402  if (!BindGLProc(_glFenceSync, "glFenceSync")) return false;
403  if (!BindGLProc(_glDeleteSync, "glDeleteSync")) return false;
404  }
405 #endif
406 
407  return true;
408 }
409 
411 void APIENTRY DebugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)
412 {
413  /* Make severity human readable. */
414  const char *severity_str = "";
415  switch (severity) {
416  case GL_DEBUG_SEVERITY_HIGH: severity_str = "high"; break;
417  case GL_DEBUG_SEVERITY_MEDIUM: severity_str = "medium"; break;
418  case GL_DEBUG_SEVERITY_LOW: severity_str = "low"; break;
419  }
420 
421  /* Make type human readable.*/
422  const char *type_str = "Other";
423  switch (type) {
424  case GL_DEBUG_TYPE_ERROR: type_str = "Error"; break;
425  case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: type_str = "Deprecated"; break;
426  case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: type_str = "Undefined behaviour"; break;
427  case GL_DEBUG_TYPE_PERFORMANCE: type_str = "Performance"; break;
428  case GL_DEBUG_TYPE_PORTABILITY: type_str = "Portability"; break;
429  }
430 
431  DEBUG(driver, 6, "OpenGL: %s (%s) - %s", type_str, severity_str, message);
432 }
433 
435 void SetupDebugOutput()
436 {
437 #ifndef NO_DEBUG_MESSAGES
438  if (_debug_driver_level < 6) return;
439 
440  if (IsOpenGLVersionAtLeast(4, 3)) {
441  BindGLProc(_glDebugMessageControl, "glDebugMessageControl");
442  BindGLProc(_glDebugMessageCallback, "glDebugMessageCallback");
443  } else if (IsOpenGLExtensionSupported("GL_ARB_debug_output")) {
444  BindGLProc(_glDebugMessageControl, "glDebugMessageControlARB");
445  BindGLProc(_glDebugMessageCallback, "glDebugMessageCallbackARB");
446  }
447 
448  if (_glDebugMessageControl != nullptr && _glDebugMessageCallback != nullptr) {
449  /* Enable debug output. As synchronous debug output costs performance, we only enable it with a high debug level. */
450  _glEnable(GL_DEBUG_OUTPUT);
451  if (_debug_driver_level >= 8) _glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
452 
453  _glDebugMessageCallback(&DebugOutputCallback, nullptr);
454  /* Enable all messages on highest debug level.*/
455  _glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, _debug_driver_level >= 9 ? GL_TRUE : GL_FALSE);
456  /* Get debug messages for errors and undefined/deprecated behaviour. */
457  _glDebugMessageControl(GL_DONT_CARE, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, nullptr, GL_TRUE);
458  _glDebugMessageControl(GL_DONT_CARE, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, GL_DONT_CARE, 0, nullptr, GL_TRUE);
459  _glDebugMessageControl(GL_DONT_CARE, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, GL_DONT_CARE, 0, nullptr, GL_TRUE);
460  }
461 #endif
462 }
463 
470 /* static */ const char *OpenGLBackend::Create(GetOGLProcAddressProc get_proc, const Dimension &screen_res)
471 {
473 
474  GetOGLProcAddress = get_proc;
475 
477  return OpenGLBackend::instance->Init(screen_res);
478 }
479 
483 /* static */ void OpenGLBackend::Destroy()
484 {
486  OpenGLBackend::instance = nullptr;
487 }
488 
492 OpenGLBackend::OpenGLBackend() : cursor_cache(MAX_CACHED_CURSORS)
493 {
494 }
495 
500 {
501  if (_glDeleteProgram != nullptr) {
502  _glDeleteProgram(this->remap_program);
503  _glDeleteProgram(this->vid_program);
504  _glDeleteProgram(this->pal_program);
505  _glDeleteProgram(this->sprite_program);
506  }
507  if (_glDeleteVertexArrays != nullptr) _glDeleteVertexArrays(1, &this->vao_quad);
508  if (_glDeleteBuffers != nullptr) {
509  _glDeleteBuffers(1, &this->vbo_quad);
510  _glDeleteBuffers(1, &this->vid_pbo);
511  _glDeleteBuffers(1, &this->anim_pbo);
512  }
513  if (_glDeleteTextures != nullptr) {
514  this->InternalClearCursorCache();
516 
517  _glDeleteTextures(1, &this->vid_texture);
518  _glDeleteTextures(1, &this->anim_texture);
519  _glDeleteTextures(1, &this->pal_texture);
520  }
521 }
522 
528 const char *OpenGLBackend::Init(const Dimension &screen_res)
529 {
530  if (!BindBasicInfoProcs()) return "OpenGL not supported";
531 
532  /* Always query the supported OpenGL version as the current context might have changed. */
533  const char *ver = (const char *)_glGetString(GL_VERSION);
534  const char *vend = (const char *)_glGetString(GL_VENDOR);
535  const char *renderer = (const char *)_glGetString(GL_RENDERER);
536 
537  if (ver == nullptr || vend == nullptr || renderer == nullptr) return "OpenGL not supported";
538 
539  DEBUG(driver, 1, "OpenGL driver: %s - %s (%s)", vend, renderer, ver);
540 
541 #ifndef GL_ALLOW_SOFTWARE_RENDERER
542  /* Don't use MESA software rendering backends as they are slower than
543  * just using a non-OpenGL video driver. */
544  if (strncmp(renderer, "llvmpipe", 8) == 0 || strncmp(renderer, "softpipe", 8) == 0) return "Software renderer detected, not using OpenGL";
545 #endif
546 
547  const char *minor = strchr(ver, '.');
548  _gl_major_ver = atoi(ver);
549  _gl_minor_ver = minor != nullptr ? atoi(minor + 1) : 0;
550 
551 #ifdef _WIN32
552  /* Old drivers on Windows (especially if made by Intel) seem to be
553  * unstable, so cull the oldest stuff here. */
554  if (!IsOpenGLVersionAtLeast(3, 2)) return "Need at least OpenGL version 3.2 on Windows";
555 #endif
556 
557  if (!BindBasicOpenGLProcs()) return "Failed to bind basic OpenGL functions.";
558 
559  SetupDebugOutput();
560 
561  /* OpenGL 1.3 is the absolute minimum. */
562  if (!IsOpenGLVersionAtLeast(1, 3)) return "OpenGL version >= 1.3 required";
563  /* Check for non-power-of-two texture support. */
564  if (!IsOpenGLVersionAtLeast(2, 0) && !IsOpenGLExtensionSupported("GL_ARB_texture_non_power_of_two")) return "Non-power-of-two textures not supported";
565  /* Check for single element texture formats. */
566  if (!IsOpenGLVersionAtLeast(3, 0) && !IsOpenGLExtensionSupported("GL_ARB_texture_rg")) return "Single element texture formats not supported";
567  if (!BindTextureExtensions()) return "Failed to bind texture extension functions";
568  /* Check for vertex buffer objects. */
569  if (!IsOpenGLVersionAtLeast(1, 5) && !IsOpenGLExtensionSupported("ARB_vertex_buffer_object")) return "Vertex buffer objects not supported";
570  if (!BindVBOExtension()) return "Failed to bind VBO extension functions";
571  /* Check for pixel buffer objects. */
572  if (!IsOpenGLVersionAtLeast(2, 1) && !IsOpenGLExtensionSupported("GL_ARB_pixel_buffer_object")) return "Pixel buffer objects not supported";
573  /* Check for vertex array objects. */
574  if (!IsOpenGLVersionAtLeast(3, 0) && (!IsOpenGLExtensionSupported("GL_ARB_vertex_array_object") || !IsOpenGLExtensionSupported("GL_APPLE_vertex_array_object"))) return "Vertex array objects not supported";
575  if (!BindVBAExtension()) return "Failed to bind VBA extension functions";
576  /* Check for shader objects. */
577  if (!IsOpenGLVersionAtLeast(2, 0) && (!IsOpenGLExtensionSupported("GL_ARB_shader_objects") || !IsOpenGLExtensionSupported("GL_ARB_fragment_shader") || !IsOpenGLExtensionSupported("GL_ARB_vertex_shader"))) return "No shader support";
578  if (!BindShaderExtensions()) return "Failed to bind shader extension functions";
579  if (IsOpenGLVersionAtLeast(3, 2) && _glBindFragDataLocation == nullptr) return "OpenGL claims to support version 3.2 but doesn't have glBindFragDataLocation";
580 
581  this->persistent_mapping_supported = IsOpenGLVersionAtLeast(3, 0) && (IsOpenGLVersionAtLeast(4, 4) || IsOpenGLExtensionSupported("GL_ARB_buffer_storage"));
582 #ifndef NO_GL_BUFFER_SYNC
583  this->persistent_mapping_supported = this->persistent_mapping_supported && (IsOpenGLVersionAtLeast(3, 2) || IsOpenGLExtensionSupported("GL_ARB_sync"));
584 #endif
585 
586  if (this->persistent_mapping_supported && !BindPersistentBufferExtensions()) {
587  DEBUG(driver, 1, "OpenGL claims to support persistent buffer mapping but doesn't export all functions, not using persistent mapping.");
588  this->persistent_mapping_supported = false;
589  }
590  if (this->persistent_mapping_supported) DEBUG(driver, 3, "OpenGL: Using persistent buffer mapping");
591 
592  /* Check maximum texture size against screen resolution. */
593  GLint max_tex_size = 0;
594  _glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
595  if (std::max(screen_res.width, screen_res.height) > (uint)max_tex_size) return "Max supported texture size is too small";
596 
597  /* Check available texture units. */
598  GLint max_tex_units = 0;
599  _glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_tex_units);
600  if (max_tex_units < 4) return "Not enough simultaneous textures supported";
601 
602  DEBUG(driver, 2, "OpenGL shading language version: %s, texture units = %d", (const char *)_glGetString(GL_SHADING_LANGUAGE_VERSION), (int)max_tex_units);
603 
604  if (!this->InitShaders()) return "Failed to initialize shaders";
605 
606  /* Setup video buffer texture. */
607  _glGenTextures(1, &this->vid_texture);
608  _glBindTexture(GL_TEXTURE_2D, this->vid_texture);
609  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
610  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
611  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
612  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
613  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
614  _glBindTexture(GL_TEXTURE_2D, 0);
615  if (_glGetError() != GL_NO_ERROR) return "Can't generate video buffer texture";
616 
617  /* Setup video buffer texture. */
618  _glGenTextures(1, &this->anim_texture);
619  _glBindTexture(GL_TEXTURE_2D, this->anim_texture);
620  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
621  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
622  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
623  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
624  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
625  _glBindTexture(GL_TEXTURE_2D, 0);
626  if (_glGetError() != GL_NO_ERROR) return "Can't generate animation buffer texture";
627 
628  /* Setup palette texture. */
629  _glGenTextures(1, &this->pal_texture);
630  _glBindTexture(GL_TEXTURE_1D, this->pal_texture);
631  _glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
632  _glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
633  _glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAX_LEVEL, 0);
634  _glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
635  _glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
636  _glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA8, 256, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr);
637  _glBindTexture(GL_TEXTURE_1D, 0);
638  if (_glGetError() != GL_NO_ERROR) return "Can't generate palette lookup texture";
639 
640  /* Bind uniforms in rendering shader program. */
641  GLint tex_location = _glGetUniformLocation(this->vid_program, "colour_tex");
642  GLint palette_location = _glGetUniformLocation(this->vid_program, "palette");
643  GLint sprite_location = _glGetUniformLocation(this->vid_program, "sprite");
644  GLint screen_location = _glGetUniformLocation(this->vid_program, "screen");
645  _glUseProgram(this->vid_program);
646  _glUniform1i(tex_location, 0); // Texture unit 0.
647  _glUniform1i(palette_location, 1); // Texture unit 1.
648  /* Values that result in no transform. */
649  _glUniform4f(sprite_location, 0.0f, 0.0f, 1.0f, 1.0f);
650  _glUniform2f(screen_location, 1.0f, 1.0f);
651 
652  /* Bind uniforms in palette rendering shader program. */
653  tex_location = _glGetUniformLocation(this->pal_program, "colour_tex");
654  palette_location = _glGetUniformLocation(this->pal_program, "palette");
655  sprite_location = _glGetUniformLocation(this->pal_program, "sprite");
656  screen_location = _glGetUniformLocation(this->pal_program, "screen");
657  _glUseProgram(this->pal_program);
658  _glUniform1i(tex_location, 0); // Texture unit 0.
659  _glUniform1i(palette_location, 1); // Texture unit 1.
660  _glUniform4f(sprite_location, 0.0f, 0.0f, 1.0f, 1.0f);
661  _glUniform2f(screen_location, 1.0f, 1.0f);
662 
663  /* Bind uniforms in remap shader program. */
664  tex_location = _glGetUniformLocation(this->remap_program, "colour_tex");
665  palette_location = _glGetUniformLocation(this->remap_program, "palette");
666  GLint remap_location = _glGetUniformLocation(this->remap_program, "remap_tex");
667  this->remap_sprite_loc = _glGetUniformLocation(this->remap_program, "sprite");
668  this->remap_screen_loc = _glGetUniformLocation(this->remap_program, "screen");
669  this->remap_zoom_loc = _glGetUniformLocation(this->remap_program, "zoom");
670  this->remap_rgb_loc = _glGetUniformLocation(this->remap_program, "rgb");
671  _glUseProgram(this->remap_program);
672  _glUniform1i(tex_location, 0); // Texture unit 0.
673  _glUniform1i(palette_location, 1); // Texture unit 1.
674  _glUniform1i(remap_location, 2); // Texture unit 2.
675 
676  /* Bind uniforms in sprite shader program. */
677  tex_location = _glGetUniformLocation(this->sprite_program, "colour_tex");
678  palette_location = _glGetUniformLocation(this->sprite_program, "palette");
679  remap_location = _glGetUniformLocation(this->sprite_program, "remap_tex");
680  GLint pal_location = _glGetUniformLocation(this->sprite_program, "pal");
681  this->sprite_sprite_loc = _glGetUniformLocation(this->sprite_program, "sprite");
682  this->sprite_screen_loc = _glGetUniformLocation(this->sprite_program, "screen");
683  this->sprite_zoom_loc = _glGetUniformLocation(this->sprite_program, "zoom");
684  this->sprite_rgb_loc = _glGetUniformLocation(this->sprite_program, "rgb");
685  this->sprite_crash_loc = _glGetUniformLocation(this->sprite_program, "crash");
686  _glUseProgram(this->sprite_program);
687  _glUniform1i(tex_location, 0); // Texture unit 0.
688  _glUniform1i(palette_location, 1); // Texture unit 1.
689  _glUniform1i(remap_location, 2); // Texture unit 2.
690  _glUniform1i(pal_location, 3); // Texture unit 3.
691  (void)_glGetError(); // Clear errors.
692 
693  /* Create pixel buffer object as video buffer storage. */
694  _glGenBuffers(1, &this->vid_pbo);
695  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vid_pbo);
696  _glGenBuffers(1, &this->anim_pbo);
697  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->anim_pbo);
698  if (_glGetError() != GL_NO_ERROR) return "Can't allocate pixel buffer for video buffer";
699 
700  /* Prime vertex buffer with a full-screen quad and store
701  * the corresponding state in a vertex array object. */
702  static const Simple2DVertex vert_array[] = {
703  // x y u v
704  { 1.f, -1.f, 1.f, 1.f },
705  { 1.f, 1.f, 1.f, 0.f },
706  { -1.f, -1.f, 0.f, 1.f },
707  { -1.f, 1.f, 0.f, 0.f },
708  };
709 
710  /* Create VAO. */
711  _glGenVertexArrays(1, &this->vao_quad);
712  _glBindVertexArray(this->vao_quad);
713 
714  /* Create and fill VBO. */
715  _glGenBuffers(1, &this->vbo_quad);
716  _glBindBuffer(GL_ARRAY_BUFFER, this->vbo_quad);
717  _glBufferData(GL_ARRAY_BUFFER, sizeof(vert_array), vert_array, GL_STATIC_DRAW);
718  if (_glGetError() != GL_NO_ERROR) return "Can't generate VBO for fullscreen quad";
719 
720  /* Set vertex state. */
721  GLint loc_position = _glGetAttribLocation(this->vid_program, "position");
722  GLint colour_position = _glGetAttribLocation(this->vid_program, "colour_uv");
723  _glEnableVertexAttribArray(loc_position);
724  _glEnableVertexAttribArray(colour_position);
725  _glVertexAttribPointer(loc_position, 2, GL_FLOAT, GL_FALSE, sizeof(Simple2DVertex), (GLvoid *)offsetof(Simple2DVertex, x));
726  _glVertexAttribPointer(colour_position, 2, GL_FLOAT, GL_FALSE, sizeof(Simple2DVertex), (GLvoid *)offsetof(Simple2DVertex, u));
727  _glBindVertexArray(0);
728 
729  /* Create resources for sprite rendering. */
730  if (!OpenGLSprite::Create()) return "Failed to create sprite rendering resources";
731 
732  this->PrepareContext();
733  (void)_glGetError(); // Clear errors.
734 
735  return nullptr;
736 }
737 
738 void OpenGLBackend::PrepareContext()
739 {
740  _glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
741  _glDisable(GL_DEPTH_TEST);
742  /* Enable alpha blending using the src alpha factor. */
743  _glEnable(GL_BLEND);
744  _glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
745 }
746 
752 static bool VerifyShader(GLuint shader)
753 {
754  static ReusableBuffer<char> log_buf;
755 
756  GLint result = GL_FALSE;
757  _glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
758 
759  /* Output log if there is one. */
760  GLint log_len = 0;
761  _glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_len);
762  if (log_len > 0) {
763  _glGetShaderInfoLog(shader, log_len, nullptr, log_buf.Allocate(log_len));
764  DEBUG(driver, result != GL_TRUE ? 0 : 2, "%s", log_buf.GetBuffer()); // Always print on failure.
765  }
766 
767  return result == GL_TRUE;
768 }
769 
775 static bool VerifyProgram(GLuint program)
776 {
777  static ReusableBuffer<char> log_buf;
778 
779  GLint result = GL_FALSE;
780  _glGetProgramiv(program, GL_LINK_STATUS, &result);
781 
782  /* Output log if there is one. */
783  GLint log_len = 0;
784  _glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_len);
785  if (log_len > 0) {
786  _glGetProgramInfoLog(program, log_len, nullptr, log_buf.Allocate(log_len));
787  DEBUG(driver, result != GL_TRUE ? 0 : 2, "%s", log_buf.GetBuffer()); // Always print on failure.
788  }
789 
790  return result == GL_TRUE;
791 }
792 
798 {
799  const char *ver = (const char *)_glGetString(GL_SHADING_LANGUAGE_VERSION);
800  if (ver == nullptr) return false;
801 
802  int glsl_major = ver[0] - '0';
803  int glsl_minor = ver[2] - '0';
804 
805  bool glsl_150 = (IsOpenGLVersionAtLeast(3, 2) || glsl_major > 1 || (glsl_major == 1 && glsl_minor >= 5)) && _glBindFragDataLocation != nullptr;
806 
807  /* Create vertex shader. */
808  GLuint vert_shader = _glCreateShader(GL_VERTEX_SHADER);
809  _glShaderSource(vert_shader, glsl_150 ? lengthof(_vertex_shader_sprite_150) : lengthof(_vertex_shader_sprite), glsl_150 ? _vertex_shader_sprite_150 : _vertex_shader_sprite, nullptr);
810  _glCompileShader(vert_shader);
811  if (!VerifyShader(vert_shader)) return false;
812 
813  /* Create fragment shader for plain RGBA. */
814  GLuint frag_shader_rgb = _glCreateShader(GL_FRAGMENT_SHADER);
815  _glShaderSource(frag_shader_rgb, glsl_150 ? lengthof(_frag_shader_direct_150) : lengthof(_frag_shader_direct), glsl_150 ? _frag_shader_direct_150 : _frag_shader_direct, nullptr);
816  _glCompileShader(frag_shader_rgb);
817  if (!VerifyShader(frag_shader_rgb)) return false;
818 
819  /* Create fragment shader for paletted only. */
820  GLuint frag_shader_pal = _glCreateShader(GL_FRAGMENT_SHADER);
821  _glShaderSource(frag_shader_pal, glsl_150 ? lengthof(_frag_shader_palette_150) : lengthof(_frag_shader_palette), glsl_150 ? _frag_shader_palette_150 : _frag_shader_palette, nullptr);
822  _glCompileShader(frag_shader_pal);
823  if (!VerifyShader(frag_shader_pal)) return false;
824 
825  /* Sprite remap fragment shader. */
826  GLuint remap_shader = _glCreateShader(GL_FRAGMENT_SHADER);
828  _glCompileShader(remap_shader);
829  if (!VerifyShader(remap_shader)) return false;
830 
831  /* Sprite fragment shader. */
832  GLuint sprite_shader = _glCreateShader(GL_FRAGMENT_SHADER);
833  _glShaderSource(sprite_shader, glsl_150 ? lengthof(_frag_shader_sprite_blend_150) : lengthof(_frag_shader_sprite_blend), glsl_150 ? _frag_shader_sprite_blend_150 : _frag_shader_sprite_blend, nullptr);
834  _glCompileShader(sprite_shader);
835  if (!VerifyShader(sprite_shader)) return false;
836 
837  /* Link shaders to program. */
838  this->vid_program = _glCreateProgram();
839  _glAttachShader(this->vid_program, vert_shader);
840  _glAttachShader(this->vid_program, frag_shader_rgb);
841 
842  this->pal_program = _glCreateProgram();
843  _glAttachShader(this->pal_program, vert_shader);
844  _glAttachShader(this->pal_program, frag_shader_pal);
845 
846  this->remap_program = _glCreateProgram();
847  _glAttachShader(this->remap_program, vert_shader);
848  _glAttachShader(this->remap_program, remap_shader);
849 
850  this->sprite_program = _glCreateProgram();
851  _glAttachShader(this->sprite_program, vert_shader);
852  _glAttachShader(this->sprite_program, sprite_shader);
853 
854  if (glsl_150) {
855  /* Bind fragment shader outputs. */
856  _glBindFragDataLocation(this->vid_program, 0, "colour");
857  _glBindFragDataLocation(this->pal_program, 0, "colour");
858  _glBindFragDataLocation(this->remap_program, 0, "colour");
859  _glBindFragDataLocation(this->sprite_program, 0, "colour");
860  }
861 
862  _glLinkProgram(this->vid_program);
863  if (!VerifyProgram(this->vid_program)) return false;
864 
865  _glLinkProgram(this->pal_program);
866  if (!VerifyProgram(this->pal_program)) return false;
867 
868  _glLinkProgram(this->remap_program);
869  if (!VerifyProgram(this->remap_program)) return false;
870 
871  _glLinkProgram(this->sprite_program);
872  if (!VerifyProgram(this->sprite_program)) return false;
873 
874  _glDeleteShader(vert_shader);
875  _glDeleteShader(frag_shader_rgb);
876  _glDeleteShader(frag_shader_pal);
877  _glDeleteShader(remap_shader);
878  _glDeleteShader(sprite_shader);
879 
880  return true;
881 }
882 
889 template <class T>
890 static void ClearPixelBuffer(size_t len, T data)
891 {
892  T *buf = reinterpret_cast<T *>(_glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE));
893  for (size_t i = 0; i < len; i++) {
894  *buf++ = data;
895  }
896  _glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
897 }
898 
906 bool OpenGLBackend::Resize(int w, int h, bool force)
907 {
908  if (!force && _screen.width == w && _screen.height == h) return false;
909 
911  int pitch = Align(w, 4);
912 
913  _glViewport(0, 0, w, h);
914 
915  _glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch);
916 
917  this->vid_buffer = nullptr;
918  if (this->persistent_mapping_supported) {
919  _glDeleteBuffers(1, &this->vid_pbo);
920  _glGenBuffers(1, &this->vid_pbo);
921  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vid_pbo);
922  _glBufferStorage(GL_PIXEL_UNPACK_BUFFER, pitch * h * bpp / 8, nullptr, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_CLIENT_STORAGE_BIT);
923  } else {
924  /* Re-allocate video buffer texture and backing store. */
925  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vid_pbo);
926  _glBufferData(GL_PIXEL_UNPACK_BUFFER, pitch * h * bpp / 8, nullptr, GL_DYNAMIC_DRAW);
927  }
928 
929  if (bpp == 32) {
930  /* Initialize backing store alpha to opaque for 32bpp modes. */
931  Colour black(0, 0, 0);
932  if (_glClearBufferSubData != nullptr) {
933  _glClearBufferSubData(GL_PIXEL_UNPACK_BUFFER, GL_RGBA8, 0, pitch * h * bpp / 8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &black.data);
934  } else {
935  ClearPixelBuffer<uint32>(pitch * h, black.data);
936  }
937  } else if (bpp == 8) {
938  if (_glClearBufferSubData != nullptr) {
939  byte b = 0;
940  _glClearBufferSubData(GL_PIXEL_UNPACK_BUFFER, GL_R8, 0, pitch * h, GL_RED, GL_UNSIGNED_BYTE, &b);
941  } else {
942  ClearPixelBuffer<byte>(pitch * h, 0);
943  }
944  }
945 
946  _glActiveTexture(GL_TEXTURE0);
947  _glBindTexture(GL_TEXTURE_2D, this->vid_texture);
948  switch (bpp) {
949  case 8:
950  _glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
951  break;
952 
953  default:
954  _glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr);
955  break;
956  }
957  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
958 
959  /* Does this blitter need a separate animation buffer? */
960  if (BlitterFactory::GetCurrentBlitter()->NeedsAnimationBuffer()) {
961  this->anim_buffer = nullptr;
962  if (this->persistent_mapping_supported) {
963  _glDeleteBuffers(1, &this->anim_pbo);
964  _glGenBuffers(1, &this->anim_pbo);
965  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->anim_pbo);
966  _glBufferStorage(GL_PIXEL_UNPACK_BUFFER, pitch * h, nullptr, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_CLIENT_STORAGE_BIT);
967  } else {
968  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->anim_pbo);
969  _glBufferData(GL_PIXEL_UNPACK_BUFFER, pitch * h, nullptr, GL_DYNAMIC_DRAW);
970  }
971 
972  /* Initialize buffer as 0 == no remap. */
973  if (_glClearBufferSubData != nullptr) {
974  byte b = 0;
975  _glClearBufferSubData(GL_PIXEL_UNPACK_BUFFER, GL_R8, 0, pitch * h, GL_RED, GL_UNSIGNED_BYTE, &b);
976  } else {
977  ClearPixelBuffer<byte>(pitch * h, 0);
978  }
979 
980  _glBindTexture(GL_TEXTURE_2D, this->anim_texture);
981  _glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
982  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
983  } else {
984  if (this->anim_buffer != nullptr) {
985  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->anim_pbo);
986  _glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
987  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
988  this->anim_buffer = nullptr;
989  }
990 
991  /* Allocate dummy texture that always reads as 0 == no remap. */
992  uint dummy = 0;
993  _glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
994  _glBindTexture(GL_TEXTURE_2D, this->anim_texture);
995  _glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &dummy);
996  }
997 
998  _glBindTexture(GL_TEXTURE_2D, 0);
999 
1000  /* Set new viewport. */
1001  _screen.height = h;
1002  _screen.width = w;
1003  _screen.pitch = pitch;
1004  _screen.dst_ptr = nullptr;
1005 
1006  /* Update screen size in remap shader program. */
1007  _glUseProgram(this->remap_program);
1008  _glUniform2f(this->remap_screen_loc, (float)_screen.width, (float)_screen.height);
1009 
1010  _glClear(GL_COLOR_BUFFER_BIT);
1011 
1012  return true;
1013 }
1014 
1021 void OpenGLBackend::UpdatePalette(const Colour *pal, uint first, uint length)
1022 {
1023  assert(first + length <= 256);
1024 
1025  _glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1026  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
1027  _glActiveTexture(GL_TEXTURE1);
1028  _glBindTexture(GL_TEXTURE_1D, this->pal_texture);
1029  _glTexSubImage1D(GL_TEXTURE_1D, 0, first, length, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pal + first);
1030 }
1031 
1036 {
1037  _glClear(GL_COLOR_BUFFER_BIT);
1038 
1039  _glDisable(GL_BLEND);
1040 
1041  /* Blit video buffer to screen. */
1042  _glActiveTexture(GL_TEXTURE0);
1043  _glBindTexture(GL_TEXTURE_2D, this->vid_texture);
1044  _glActiveTexture(GL_TEXTURE1);
1045  _glBindTexture(GL_TEXTURE_1D, this->pal_texture);
1046  /* Is the blitter relying on a separate animation buffer? */
1047  if (BlitterFactory::GetCurrentBlitter()->NeedsAnimationBuffer()) {
1048  _glActiveTexture(GL_TEXTURE2);
1049  _glBindTexture(GL_TEXTURE_2D, this->anim_texture);
1050  _glUseProgram(this->remap_program);
1051  _glUniform4f(this->remap_sprite_loc, 0.0f, 0.0f, 1.0f, 1.0f);
1052  _glUniform2f(this->remap_screen_loc, 1.0f, 1.0f);
1053  _glUniform1f(this->remap_zoom_loc, 0);
1054  _glUniform1i(this->remap_rgb_loc, 1);
1055  } else {
1056  _glUseProgram(BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 8 ? this->pal_program : this->vid_program);
1057  }
1058  _glBindVertexArray(this->vao_quad);
1059  _glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1060 
1061  _glEnable(GL_BLEND);
1062 }
1063 
1068 {
1069  if (!this->cursor_in_window) return;
1070 
1071  /* Draw cursor on screen */
1072  _cur_dpi = &_screen;
1073  for (uint i = 0; i < this->cursor_sprite_count; ++i) {
1074  SpriteID sprite = this->cursor_sprite_seq[i].sprite;
1075 
1076  /* Sprites are cached by PopulateCursorCache(). */
1077  if (this->cursor_cache.Contains(sprite)) {
1078  Sprite *spr = this->cursor_cache.Get(sprite);
1079 
1080  this->RenderOglSprite((OpenGLSprite *)spr->data, this->cursor_sprite_seq[i].pal,
1081  this->cursor_pos.x + this->cursor_sprite_pos[i].x + UnScaleByZoom(spr->x_offs, ZOOM_LVL_GUI),
1082  this->cursor_pos.y + this->cursor_sprite_pos[i].y + UnScaleByZoom(spr->y_offs, ZOOM_LVL_GUI),
1083  ZOOM_LVL_GUI);
1084  }
1085  }
1086 }
1087 
1088 void OpenGLBackend::PopulateCursorCache()
1089 {
1090  static_assert(lengthof(_cursor.sprite_seq) == lengthof(this->cursor_sprite_seq));
1091  static_assert(lengthof(_cursor.sprite_pos) == lengthof(this->cursor_sprite_pos));
1092 
1093  if (this->clear_cursor_cache) {
1094  /* We have a pending cursor cache clear to do first. */
1095  this->clear_cursor_cache = false;
1096  this->last_sprite_pal = (PaletteID)-1;
1097 
1098  this->InternalClearCursorCache();
1099  }
1100 
1101  this->cursor_pos = _cursor.pos;
1102  this->cursor_sprite_count = _cursor.sprite_count;
1103  this->cursor_in_window = _cursor.in_window;
1104 
1105  for (uint i = 0; i < _cursor.sprite_count; ++i) {
1106  this->cursor_sprite_seq[i] = _cursor.sprite_seq[i];
1107  this->cursor_sprite_pos[i] = _cursor.sprite_pos[i];
1108  SpriteID sprite = _cursor.sprite_seq[i].sprite;
1109 
1110  if (!this->cursor_cache.Contains(sprite)) {
1111  Sprite *old = this->cursor_cache.Insert(sprite, (Sprite *)GetRawSprite(sprite, ST_NORMAL, &SimpleSpriteAlloc, this));
1112  if (old != nullptr) {
1113  OpenGLSprite *sprite = (OpenGLSprite *)old->data;
1114  sprite->~OpenGLSprite();
1115  free(old);
1116  }
1117  }
1118  }
1119 }
1120 
1125 {
1126  Sprite *sp;
1127  while ((sp = this->cursor_cache.Pop()) != nullptr) {
1128  OpenGLSprite *sprite = (OpenGLSprite *)sp->data;
1129  sprite->~OpenGLSprite();
1130  free(sp);
1131  }
1132 }
1133 
1138 {
1139  /* If the game loop is threaded, this function might be called
1140  * from the game thread. As we can call OpenGL functions only
1141  * on the main thread, just set a flag that is handled the next
1142  * time we prepare the cursor cache for drawing. */
1143  this->clear_cursor_cache = true;
1144 }
1145 
1151 {
1152 #ifndef NO_GL_BUFFER_SYNC
1153  if (this->sync_vid_mapping != nullptr) _glClientWaitSync(this->sync_vid_mapping, GL_SYNC_FLUSH_COMMANDS_BIT, 10000000);
1154 #endif
1155 
1156  if (!this->persistent_mapping_supported) {
1157  assert(this->vid_buffer == nullptr);
1158  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vid_pbo);
1159  this->vid_buffer = _glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE);
1160  } else if (this->vid_buffer == nullptr) {
1161  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vid_pbo);
1162  this->vid_buffer = _glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, _screen.pitch * _screen.height * BlitterFactory::GetCurrentBlitter()->GetScreenDepth() / 8, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
1163  }
1164 
1165  return this->vid_buffer;
1166 }
1167 
1173 {
1174  if (this->anim_pbo == 0) return nullptr;
1175 
1176 #ifndef NO_GL_BUFFER_SYNC
1177  if (this->sync_anim_mapping != nullptr) _glClientWaitSync(this->sync_anim_mapping, GL_SYNC_FLUSH_COMMANDS_BIT, 10000000);
1178 #endif
1179 
1180  if (!this->persistent_mapping_supported) {
1181  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->anim_pbo);
1182  this->anim_buffer = _glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE);
1183  } else if (this->anim_buffer == nullptr) {
1184  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->anim_pbo);
1185  this->anim_buffer = _glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, _screen.pitch * _screen.height, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
1186  }
1187 
1188  return (uint8 *)this->anim_buffer;
1189 }
1190 
1195 void OpenGLBackend::ReleaseVideoBuffer(const Rect &update_rect)
1196 {
1197  assert(this->vid_pbo != 0);
1198 
1199  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vid_pbo);
1200  if (!this->persistent_mapping_supported) {
1201  _glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
1202  this->vid_buffer = nullptr;
1203  }
1204 
1205 #ifndef NO_GL_BUFFER_SYNC
1206  if (this->persistent_mapping_supported) {
1207  _glDeleteSync(this->sync_vid_mapping);
1208  this->sync_vid_mapping = nullptr;
1209  }
1210 #endif
1211 
1212  /* Update changed rect of the video buffer texture. */
1213  if (!IsEmptyRect(update_rect)) {
1214  _glActiveTexture(GL_TEXTURE0);
1215  _glBindTexture(GL_TEXTURE_2D, this->vid_texture);
1216  _glPixelStorei(GL_UNPACK_ROW_LENGTH, _screen.pitch);
1217  switch (BlitterFactory::GetCurrentBlitter()->GetScreenDepth()) {
1218  case 8:
1219  _glTexSubImage2D(GL_TEXTURE_2D, 0, update_rect.left, update_rect.top, update_rect.right - update_rect.left, update_rect.bottom - update_rect.top, GL_RED, GL_UNSIGNED_BYTE, (GLvoid *)(size_t)(update_rect.top * _screen.pitch + update_rect.left));
1220  break;
1221 
1222  default:
1223  _glTexSubImage2D(GL_TEXTURE_2D, 0, update_rect.left, update_rect.top, update_rect.right - update_rect.left, update_rect.bottom - update_rect.top, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, (GLvoid *)(size_t)(update_rect.top * _screen.pitch * 4 + update_rect.left * 4));
1224  break;
1225  }
1226 
1227 #ifndef NO_GL_BUFFER_SYNC
1228  if (this->persistent_mapping_supported) this->sync_vid_mapping = _glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1229 #endif
1230  }
1231 }
1232 
1237 void OpenGLBackend::ReleaseAnimBuffer(const Rect &update_rect)
1238 {
1239  if (this->anim_pbo == 0) return;
1240 
1241  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->anim_pbo);
1242  if (!this->persistent_mapping_supported) {
1243  _glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
1244  this->anim_buffer = nullptr;
1245  }
1246 
1247 #ifndef NO_GL_BUFFER_SYNC
1248  if (this->persistent_mapping_supported) {
1249  _glDeleteSync(this->sync_anim_mapping);
1250  this->sync_anim_mapping = nullptr;
1251  }
1252 #endif
1253 
1254  /* Update changed rect of the video buffer texture. */
1255  if (update_rect.left != update_rect.right) {
1256  _glActiveTexture(GL_TEXTURE0);
1257  _glBindTexture(GL_TEXTURE_2D, this->anim_texture);
1258  _glPixelStorei(GL_UNPACK_ROW_LENGTH, _screen.pitch);
1259  _glTexSubImage2D(GL_TEXTURE_2D, 0, update_rect.left, update_rect.top, update_rect.right - update_rect.left, update_rect.bottom - update_rect.top, GL_RED, GL_UNSIGNED_BYTE, (GLvoid *)(size_t)(update_rect.top * _screen.pitch + update_rect.left));
1260 
1261 #ifndef NO_GL_BUFFER_SYNC
1262  if (this->persistent_mapping_supported) this->sync_anim_mapping = _glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1263 #endif
1264  }
1265 }
1266 
1267 /* virtual */ Sprite *OpenGLBackend::Encode(const SpriteLoader::Sprite *sprite, AllocatorProc *allocator)
1268 {
1269  /* Allocate and construct sprite data. */
1270  Sprite *dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + sizeof(OpenGLSprite));
1271 
1272  OpenGLSprite *gl_sprite = (OpenGLSprite *)dest_sprite->data;
1273  new (gl_sprite) OpenGLSprite(sprite->width, sprite->height, sprite->type == ST_FONT ? 1 : ZOOM_LVL_COUNT, sprite->colours);
1274 
1275  /* Upload texture data. */
1276  for (int i = 0; i < (sprite->type == ST_FONT ? 1 : ZOOM_LVL_COUNT); i++) {
1277  gl_sprite->Update(sprite[i].width, sprite[i].height, i, sprite[i].data);
1278  }
1279 
1280  dest_sprite->height = sprite->height;
1281  dest_sprite->width = sprite->width;
1282  dest_sprite->x_offs = sprite->x_offs;
1283  dest_sprite->y_offs = sprite->y_offs;
1284 
1285  return dest_sprite;
1286 }
1287 
1295 void OpenGLBackend::RenderOglSprite(OpenGLSprite *gl_sprite, PaletteID pal, int x, int y, ZoomLevel zoom)
1296 {
1297  /* Set textures. */
1298  bool rgb = gl_sprite->BindTextures();
1299  _glActiveTexture(GL_TEXTURE0 + 1);
1300  _glBindTexture(GL_TEXTURE_1D, this->pal_texture);
1301 
1302  /* Set palette remap. */
1303  _glActiveTexture(GL_TEXTURE0 + 3);
1304  if (pal != PAL_NONE) {
1305  _glBindTexture(GL_TEXTURE_1D, OpenGLSprite::pal_tex);
1306  if (pal != this->last_sprite_pal) {
1307  /* Different remap palette in use, update texture. */
1308  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, OpenGLSprite::pal_pbo);
1309  _glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1310 
1311  _glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, 256, GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1);
1312  _glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 256, GL_RED, GL_UNSIGNED_BYTE, 0);
1313 
1314  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
1315 
1316  this->last_sprite_pal = pal;
1317  }
1318  } else {
1319  _glBindTexture(GL_TEXTURE_1D, OpenGLSprite::pal_identity);
1320  }
1321 
1322  /* Set up shader program. */
1323  Dimension dim = gl_sprite->GetSize(zoom);
1324  _glUseProgram(this->sprite_program);
1325  _glUniform4f(this->sprite_sprite_loc, (float)x, (float)y, (float)dim.width, (float)dim.height);
1326  _glUniform1f(this->sprite_zoom_loc, (float)(zoom - ZOOM_LVL_BEGIN));
1327  _glUniform2f(this->sprite_screen_loc, (float)_screen.width, (float)_screen.height);
1328  _glUniform1i(this->sprite_rgb_loc, rgb ? 1 : 0);
1329  _glUniform1i(this->sprite_crash_loc, pal == PALETTE_CRASH ? 1 : 0);
1330 
1331  _glBindVertexArray(this->vao_quad);
1332  _glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1333 }
1334 
1335 
1336 /* static */ GLuint OpenGLSprite::dummy_tex[] = { 0, 0 };
1337 /* static */ GLuint OpenGLSprite::pal_identity = 0;
1338 /* static */ GLuint OpenGLSprite::pal_tex = 0;
1339 /* static */ GLuint OpenGLSprite::pal_pbo = 0;
1340 
1345 /* static */ bool OpenGLSprite::Create()
1346 {
1347  _glGenTextures(NUM_TEX, OpenGLSprite::dummy_tex);
1348 
1349  for (int t = TEX_RGBA; t < NUM_TEX; t++) {
1350  _glBindTexture(GL_TEXTURE_2D, OpenGLSprite::dummy_tex[t]);
1351 
1352  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1353  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1354  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
1355  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1356  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1357  }
1358 
1359  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
1360  _glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1361 
1362  /* Load dummy RGBA texture. */
1363  const Colour rgb_pixel(0, 0, 0);
1364  _glBindTexture(GL_TEXTURE_2D, OpenGLSprite::dummy_tex[TEX_RGBA]);
1365  _glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &rgb_pixel);
1366 
1367  /* Load dummy remap texture. */
1368  const uint pal = 0;
1369  _glBindTexture(GL_TEXTURE_2D, OpenGLSprite::dummy_tex[TEX_REMAP]);
1370  _glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &pal);
1371 
1372  /* Create palette remap textures. */
1373  std::array<uint8, 256> identity_pal;
1374  std::iota(std::begin(identity_pal), std::end(identity_pal), 0);
1375 
1376  /* Permanent texture for identity remap. */
1377  _glGenTextures(1, &OpenGLSprite::pal_identity);
1378  _glBindTexture(GL_TEXTURE_1D, OpenGLSprite::pal_identity);
1379  _glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1380  _glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1381  _glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAX_LEVEL, 0);
1382  _glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1383  _glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1384  _glTexImage1D(GL_TEXTURE_1D, 0, GL_R8, 256, 0, GL_RED, GL_UNSIGNED_BYTE, identity_pal.data());
1385 
1386  /* Dynamically updated texture for remaps. */
1387  _glGenTextures(1, &OpenGLSprite::pal_tex);
1388  _glBindTexture(GL_TEXTURE_1D, OpenGLSprite::pal_tex);
1389  _glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1390  _glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1391  _glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAX_LEVEL, 0);
1392  _glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1393  _glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1394  _glTexImage1D(GL_TEXTURE_1D, 0, GL_R8, 256, 0, GL_RED, GL_UNSIGNED_BYTE, identity_pal.data());
1395 
1396  /* Pixel buffer for remap updates. */
1397  _glGenBuffers(1, &OpenGLSprite::pal_pbo);
1398  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, OpenGLSprite::pal_pbo);
1399  _glBufferData(GL_PIXEL_UNPACK_BUFFER, 256, identity_pal.data(), GL_DYNAMIC_DRAW);
1400  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
1401 
1402  return _glGetError() == GL_NO_ERROR;
1403 }
1404 
1406 /* static */ void OpenGLSprite::Destroy()
1407 {
1408  _glDeleteTextures(NUM_TEX, OpenGLSprite::dummy_tex);
1409  _glDeleteTextures(1, &OpenGLSprite::pal_identity);
1410  _glDeleteTextures(1, &OpenGLSprite::pal_tex);
1411  if (_glDeleteBuffers != nullptr) _glDeleteBuffers(1, &OpenGLSprite::pal_pbo);
1412 }
1413 
1421 OpenGLSprite::OpenGLSprite(uint width, uint height, uint levels, SpriteColourComponent components)
1422 {
1423  assert(levels > 0);
1424  (void)_glGetError();
1425 
1426  this->dim.width = width;
1427  this->dim.height = height;
1428 
1429  MemSetT(this->tex, 0, NUM_TEX);
1430  _glActiveTexture(GL_TEXTURE0);
1431  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
1432 
1433  for (int t = TEX_RGBA; t < NUM_TEX; t++) {
1434  /* Sprite component present? */
1435  if (t == TEX_RGBA && components == SCC_PAL) continue;
1436  if (t == TEX_REMAP && (components & SCC_PAL) != SCC_PAL) continue;
1437 
1438  /* Allocate texture. */
1439  _glGenTextures(1, &this->tex[t]);
1440  _glBindTexture(GL_TEXTURE_2D, this->tex[t]);
1441 
1442  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1443  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1444  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels - 1);
1445  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1446  _glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1447 
1448  /* Set size. */
1449  for (uint i = 0, w = width, h = height; i < levels; i++, w /= 2, h /= 2) {
1450  assert(w * h != 0);
1451  if (t == TEX_REMAP) {
1452  _glTexImage2D(GL_TEXTURE_2D, i, GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
1453  } else {
1454  _glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA8, w, h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr);
1455  }
1456  }
1457  }
1458 
1459  assert(_glGetError() == GL_NO_ERROR);
1460 }
1461 
1462 OpenGLSprite::~OpenGLSprite()
1463 {
1464  _glDeleteTextures(NUM_TEX, this->tex);
1465 }
1466 
1474 void OpenGLSprite::Update(uint width, uint height, uint level, const SpriteLoader::CommonPixel * data)
1475 {
1476  static ReusableBuffer<Colour> buf_rgba;
1477  static ReusableBuffer<uint8> buf_pal;
1478 
1479  _glActiveTexture(GL_TEXTURE0);
1480  _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
1481  _glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1482 
1483  if (this->tex[TEX_RGBA] != 0) {
1484  /* Unpack pixel data */
1485  Colour *rgba = buf_rgba.Allocate(width * height);
1486  for (size_t i = 0; i < width * height; i++) {
1487  rgba[i].r = data[i].r;
1488  rgba[i].g = data[i].g;
1489  rgba[i].b = data[i].b;
1490  rgba[i].a = data[i].a;
1491  }
1492 
1493  _glBindTexture(GL_TEXTURE_2D, this->tex[TEX_RGBA]);
1494  _glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, rgba);
1495  }
1496 
1497  if (this->tex[TEX_REMAP] != 0) {
1498  /* Unpack and align pixel data. */
1499  int pitch = Align(width, 4);
1500 
1501  uint8 *pal = buf_pal.Allocate(pitch * height);
1502  const SpriteLoader::CommonPixel *row = data;
1503  for (uint y = 0; y < height; y++, pal += pitch, row += width) {
1504  for (uint x = 0; x < width; x++) {
1505  pal[x] = row[x].m;
1506  }
1507  }
1508 
1509  _glBindTexture(GL_TEXTURE_2D, this->tex[TEX_REMAP]);
1510  _glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, buf_pal.GetBuffer());
1511  }
1512 
1513  assert(_glGetError() == GL_NO_ERROR);
1514 }
1515 
1522 {
1523  Dimension sd = { (uint)UnScaleByZoomLower(this->dim.width, level), (uint)UnScaleByZoomLower(this->dim.height, level) };
1524  return sd;
1525 }
1526 
1532 {
1533  _glActiveTexture(GL_TEXTURE0);
1534  _glBindTexture(GL_TEXTURE_2D, this->tex[TEX_RGBA] != 0 ? this->tex[TEX_RGBA] : OpenGLSprite::dummy_tex[TEX_RGBA]);
1535  _glActiveTexture(GL_TEXTURE0 + 2);
1536  _glBindTexture(GL_TEXTURE_2D, this->tex[TEX_REMAP] != 0 ? this->tex[TEX_REMAP] : OpenGLSprite::dummy_tex[TEX_REMAP]);
1537 
1538  return this->tex[TEX_RGBA] != 0;
1539 }
SpriteLoader::CommonPixel::m
uint8 m
Remap-channel.
Definition: spriteloader.hpp:38
OpenGLBackend::cursor_pos
Point cursor_pos
Cursor position.
Definition: opengl.h:68
SCC_PAL
@ SCC_PAL
Sprite has palette data.
Definition: spriteloader.hpp:24
OpenGLBackend::sync_vid_mapping
GLsync sync_vid_mapping
Sync object for the persistently mapped video buffer.
Definition: opengl.h:35
_frag_shader_palette
static const char * _frag_shader_palette[]
Fragment shader that performs a palette lookup to read the colour from an 8bpp texture.
Definition: opengl_shader.h:64
SpriteLoader::CommonPixel::r
uint8 r
Red-channel.
Definition: spriteloader.hpp:34
LRUCache::Get
Tdata * Get(const Tkey key)
Get an item from the cache.
Definition: lrucache.hpp:106
OpenGLBackend::RenderOglSprite
void RenderOglSprite(OpenGLSprite *gl_sprite, PaletteID pal, int x, int y, ZoomLevel zoom)
Render a sprite to the back buffer.
Definition: opengl.cpp:1295
OpenGLSprite::pal_tex
static GLuint pal_tex
Texture for palette remap.
Definition: opengl.h:132
Colour::data
uint32 data
Conversion of the channel information to a 32 bit number.
Definition: gfx_type.h:164
OpenGLBackend::pal_program
GLuint pal_program
Shader program for rendering a paletted video buffer.
Definition: opengl.h:42
OpenGLSprite::TEX_RGBA
@ TEX_RGBA
RGBA texture part.
Definition: opengl.h:121
UnScaleByZoomLower
static int UnScaleByZoomLower(int value, ZoomLevel zoom)
Scale by zoom level, usually shift right (when zoom > ZOOM_LVL_NORMAL)
Definition: zoom_func.h:56
GB
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
Definition: bitmath_func.hpp:32
ST_FONT
@ ST_FONT
A sprite used for fonts.
Definition: gfx_type.h:304
ReusableBuffer
A reusable buffer that can be used for places that temporary allocate a bit of memory and do that ver...
Definition: alloc_type.hpp:24
Dimension
Dimensions (a width and height) of a rectangle in 2D.
Definition: geometry_type.hpp:27
_frag_shader_sprite_blend_150
static const char * _frag_shader_sprite_blend_150[]
GLSL 1.50 fragment shader that performs a palette lookup to read the colour from a sprite texture.
Definition: opengl_shader.h:179
OpenGLSprite::GetSize
Dimension GetSize(ZoomLevel level) const
Query the sprite size at a certain zoom level.
Definition: opengl.cpp:1521
CursorVars::sprite_count
uint sprite_count
number of sprites to draw
Definition: gfx_type.h:130
LRUCache::Pop
Tdata * Pop()
Pop the least recently used item.
Definition: lrucache.hpp:90
OpenGLSprite::pal_identity
static GLuint pal_identity
Identity texture mapping.
Definition: opengl.h:131
_frag_shader_direct_150
static const char * _frag_shader_direct_150[]
GLSL 1.50 fragment shader that reads the fragment colour from a 32bpp texture.
Definition: opengl_shader.h:53
_vertex_shader_sprite
static const char * _vertex_shader_sprite[]
Vertex shader that positions a sprite on screen.
Definition: opengl_shader.h:13
OpenGLSprite::Destroy
static void Destroy()
Free all common resources for sprite rendering.
Definition: opengl.cpp:1406
Sprite::data
byte data[]
Sprite data.
Definition: spritecache.h:22
OpenGLSprite::tex
GLuint tex[NUM_TEX]
The texture objects.
Definition: opengl.h:127
OpenGLSprite::OpenGLSprite
OpenGLSprite(uint width, uint height, uint levels, SpriteColourComponent components)
Create an OpenGL sprite with a palette remap part.
Definition: opengl.cpp:1421
OpenGLSprite::TEX_REMAP
@ TEX_REMAP
Remap texture part.
Definition: opengl.h:122
Blitter::GetScreenDepth
virtual uint8 GetScreenDepth()=0
Get the screen depth this blitter works for.
PalSpriteID::sprite
SpriteID sprite
The 'real' sprite.
Definition: gfx_type.h:23
ZOOM_LVL_COUNT
@ ZOOM_LVL_COUNT
Number of zoom levels.
Definition: zoom_type.h:32
Sprite::height
uint16 height
Height of the sprite.
Definition: spritecache.h:18
Sprite::x_offs
int16 x_offs
Number of pixels to shift the sprite to the right.
Definition: spritecache.h:20
OpenGLBackend::vid_buffer
void * vid_buffer
Pointer to the mapped video buffer.
Definition: opengl.h:38
ZoomLevel
ZoomLevel
All zoom levels we know.
Definition: zoom_type.h:21
ReusableBuffer::Allocate
T * Allocate(size_t count)
Get buffer of at least count times T.
Definition: alloc_type.hpp:42
ST_NORMAL
@ ST_NORMAL
The most basic (normal) sprite.
Definition: gfx_type.h:302
OpenGLSprite::pal_pbo
static GLuint pal_pbo
Pixel buffer object for remap upload.
Definition: opengl.h:133
OpenGLBackend::~OpenGLBackend
~OpenGLBackend()
Free allocated resources.
Definition: opengl.cpp:499
OpenGLBackend::sprite_zoom_loc
GLint sprite_zoom_loc
Uniform location for sprite zoom;.
Definition: opengl.h:60
CursorVars::sprite_pos
Point sprite_pos[16]
relative position of individual sprites
Definition: gfx_type.h:129
ZOOM_LVL_BEGIN
@ ZOOM_LVL_BEGIN
Begin for iteration.
Definition: zoom_type.h:23
OpenGLBackend::anim_pbo
GLuint anim_pbo
Pixel buffer object storing the memory used for the animation buffer.
Definition: opengl.h:48
SpriteID
uint32 SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:17
OpenGLBackend
Platform-independent back-end class for OpenGL video drivers.
Definition: opengl.h:30
OpenGLBackend::vid_texture
GLuint vid_texture
Texture handle for the video buffer texture.
Definition: opengl.h:40
OpenGLBackend::remap_rgb_loc
GLint remap_rgb_loc
Uniform location for RGB mode flag;.
Definition: opengl.h:55
_frag_shader_palette_150
static const char * _frag_shader_palette_150[]
GLSL 1.50 fragment shader that performs a palette lookup to read the colour from an 8bpp texture.
Definition: opengl_shader.h:76
OpenGLBackend::DrawMouseCursor
void DrawMouseCursor()
Draw mouse cursor on screen.
Definition: opengl.cpp:1067
OpenGLBackend::last_sprite_pal
PaletteID last_sprite_pal
Last uploaded remap palette.
Definition: opengl.h:65
Align
static T Align(const T x, uint n)
Return the smallest multiple of n equal or greater than x.
Definition: math_func.hpp:35
Simple2DVertex
A simple 2D vertex with just position and texture.
Definition: opengl.cpp:128
PALETTE_WIDTH
@ PALETTE_WIDTH
number of bits of the sprite containing the recolour palette
Definition: sprites.h:1518
SpriteLoader::Sprite::type
SpriteType type
The sprite type.
Definition: spriteloader.hpp:52
DEBUG
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:35
OpenGLBackend::anim_buffer
void * anim_buffer
Pointer to the mapped animation buffer.
Definition: opengl.h:47
OpenGLBackend::ReleaseVideoBuffer
void ReleaseVideoBuffer(const Rect &update_rect)
Update video buffer texture after the video buffer was filled.
Definition: opengl.cpp:1195
OpenGLBackend::vbo_quad
GLuint vbo_quad
Vertex buffer with a fullscreen quad.
Definition: opengl.h:44
OpenGLSprite::Create
static bool Create()
Create all common resources for sprite rendering.
Definition: opengl.cpp:1345
SpriteLoader::CommonPixel
Definition of a common pixel in OpenTTD's realm.
Definition: spriteloader.hpp:33
LRUCache::Contains
bool Contains(const Tkey key)
Test if a key is already contained in the cache.
Definition: lrucache.hpp:49
BlitterFactory::GetCurrentBlitter
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
Definition: factory.hpp:141
OpenGLBackend::GetVideoBuffer
void * GetVideoBuffer()
Get a pointer to the memory for the video driver to draw to.
Definition: opengl.cpp:1150
OpenGLBackend::instance
static OpenGLBackend * instance
Singleton instance pointer.
Definition: opengl.h:32
Sprite::width
uint16 width
Width of the sprite.
Definition: spritecache.h:19
SpriteLoader::Sprite::x_offs
int16 x_offs
The x-offset of where the sprite will be drawn.
Definition: spriteloader.hpp:50
OpenGLBackend::cursor_in_window
bool cursor_in_window
Cursor inside this window.
Definition: opengl.h:69
OpenGLBackend::anim_texture
GLuint anim_texture
Texture handle for the animation buffer texture.
Definition: opengl.h:49
OpenGLBackend::sprite_screen_loc
GLint sprite_screen_loc
Uniform location for screen size;.
Definition: opengl.h:59
OpenGLBackend::Create
static const char * Create(GetOGLProcAddressProc get_proc, const Dimension &screen_res)
Create and initialize the singleton back-end class.
Definition: opengl.cpp:470
_vertex_shader_sprite_150
static const char * _vertex_shader_sprite_150[]
GLSL 1.50 vertex shader that positions a sprite on screen.
Definition: opengl_shader.h:28
OpenGLBackend::sync_anim_mapping
GLsync sync_anim_mapping
Sync object for the persistently mapped animation buffer.
Definition: opengl.h:36
OpenGLBackend::Destroy
static void Destroy()
Free resources and destroy singleton back-end class.
Definition: opengl.cpp:483
UnScaleByZoom
static int UnScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift right (when zoom > ZOOM_LVL_NORMAL) When shifting right,...
Definition: zoom_func.h:34
OpenGLBackend::persistent_mapping_supported
bool persistent_mapping_supported
Persistent pixel buffer mapping supported.
Definition: opengl.h:34
OpenGLBackend::cursor_cache
LRUCache< SpriteID, Sprite > cursor_cache
Cache of encoded cursor sprites.
Definition: opengl.h:64
LRUCache::Insert
Tdata * Insert(const Tkey key, Tdata *item)
Insert a new data item with a specified key.
Definition: lrucache.hpp:60
SpriteLoader::Sprite::colours
SpriteColourComponent colours
The colour components of the sprite with useful information.
Definition: spriteloader.hpp:53
OpenGLBackend::cursor_sprite_seq
PalSpriteID cursor_sprite_seq[16]
Current image of cursor.
Definition: opengl.h:70
_frag_shader_rgb_mask_blend_150
static const char * _frag_shader_rgb_mask_blend_150[]
GLSL 1.50 fragment shader that performs a palette lookup to read the colour from an 8bpp texture.
Definition: opengl_shader.h:128
Colour
Structure to access the alpha, red, green, and blue channels from a 32 bit number.
Definition: gfx_type.h:163
OpenGLBackend::vao_quad
GLuint vao_quad
Vertex array object storing the rendering state for the fullscreen quad.
Definition: opengl.h:43
OpenGLSprite::dummy_tex
static GLuint dummy_tex[NUM_TEX]
1x1 dummy textures to substitute for unused sprite components.
Definition: opengl.h:129
OpenGLBackend::ClearCursorCache
void ClearCursorCache()
Queue a request for cursor cache clear.
Definition: opengl.cpp:1137
SpriteLoader::CommonPixel::b
uint8 b
Blue-channel.
Definition: spriteloader.hpp:36
SpriteLoader::Sprite::width
uint16 width
Width of the sprite.
Definition: spriteloader.hpp:49
PALETTE_CRASH
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition: sprites.h:1594
OpenGLSprite::Update
void Update(uint width, uint height, uint level, const SpriteLoader::CommonPixel *data)
Update a single mip-map level with new pixel data.
Definition: opengl.cpp:1474
IsEmptyRect
static bool IsEmptyRect(const Rect &r)
Check if a rectangle is empty.
Definition: geometry_func.hpp:22
_frag_shader_sprite_blend
static const char * _frag_shader_sprite_blend[]
Fragment shader that performs a palette lookup to read the colour from a sprite texture.
Definition: opengl_shader.h:151
OpenGLBackend::pal_texture
GLuint pal_texture
Palette lookup texture.
Definition: opengl.h:45
Colour::a
uint8 a
colour channels in LE order
Definition: gfx_type.h:171
FindStringInExtensionList
const char * FindStringInExtensionList(const char *string, const char *substring)
Find a substring in a string made of space delimited elements.
Definition: opengl.cpp:147
GetRawSprite
void * GetRawSprite(SpriteID sprite, SpriteType type, AllocatorProc *allocator, SpriteEncoder *encoder)
Reads a sprite (from disk or sprite cache).
Definition: spritecache.cpp:876
ReusableBuffer::GetBuffer
const T * GetBuffer() const
Get the currently allocated buffer.
Definition: alloc_type.hpp:75
OpenGLBackend::cursor_sprite_count
uint cursor_sprite_count
Number of cursor sprites to draw.
Definition: opengl.h:72
PaletteID
uint32 PaletteID
The number of the palette.
Definition: gfx_type.h:18
OpenGLBackend::InternalClearCursorCache
void InternalClearCursorCache()
Clear all cached cursor sprites.
Definition: opengl.cpp:1124
OpenGLBackend::sprite_sprite_loc
GLint sprite_sprite_loc
Uniform location for sprite parameters.
Definition: opengl.h:58
Sprite::y_offs
int16 y_offs
Number of pixels to shift the sprite downwards.
Definition: spritecache.h:21
opengl.h
SpriteLoader::Sprite
Structure for passing information from the sprite loader to the blitter.
Definition: spriteloader.hpp:47
OpenGLSprite::BindTextures
bool BindTextures()
Bind textures for rendering this sprite.
Definition: opengl.cpp:1531
OpenGLBackend::Paint
void Paint()
Render video buffer to the screen.
Definition: opengl.cpp:1035
OpenGLBackend::remap_sprite_loc
GLint remap_sprite_loc
Uniform location for sprite parameters.
Definition: opengl.h:52
CursorVars::sprite_seq
PalSpriteID sprite_seq[16]
current image of cursor
Definition: gfx_type.h:128
lengthof
#define lengthof(x)
Return the length of an fixed size array.
Definition: stdafx.h:369
OpenGLBackend::UpdatePalette
void UpdatePalette(const Colour *pal, uint first, uint length)
Update the stored palette.
Definition: opengl.cpp:1021
OpenGLBackend::sprite_program
GLuint sprite_program
Shader program for blending and rendering a sprite to the video buffer.
Definition: opengl.h:57
OpenGLBackend::sprite_crash_loc
GLint sprite_crash_loc
Uniform location for crash remap mode flag;.
Definition: opengl.h:62
MemSetT
static void MemSetT(T *ptr, byte value, size_t num=1)
Type-safe version of memset().
Definition: mem_func.hpp:49
OpenGLSprite
Class that encapsulates a RGBA texture together with a paletted remap texture.
Definition: opengl.h:117
SpriteLoader::CommonPixel::g
uint8 g
Green-channel.
Definition: spriteloader.hpp:35
SpriteLoader::CommonPixel::a
uint8 a
Alpha-channel.
Definition: spriteloader.hpp:37
OpenGLBackend::clear_cursor_cache
bool clear_cursor_cache
A clear of the cursor cache is pending.
Definition: opengl.h:66
OpenGLBackend::OpenGLBackend
OpenGLBackend()
Construct OpenGL back-end class.
Definition: opengl.cpp:492
_frag_shader_rgb_mask_blend
static const char * _frag_shader_rgb_mask_blend[]
Fragment shader that performs a palette lookup to read the colour from an 8bpp texture.
Definition: opengl_shader.h:104
ST_RECOLOUR
@ ST_RECOLOUR
Recolour sprite.
Definition: gfx_type.h:305
SpriteLoader::Sprite::y_offs
int16 y_offs
The y-offset of where the sprite will be drawn.
Definition: spriteloader.hpp:51
SpriteLoader::Sprite::height
uint16 height
Height of the sprite.
Definition: spriteloader.hpp:48
OpenGLBackend::sprite_rgb_loc
GLint sprite_rgb_loc
Uniform location for RGB mode flag;.
Definition: opengl.h:61
free
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: stdafx.h:456
_frag_shader_direct
static const char * _frag_shader_direct[]
Fragment shader that reads the fragment colour from a 32bpp texture.
Definition: opengl_shader.h:43
SimpleSpriteAlloc
void * SimpleSpriteAlloc(size_t size)
Sprite allocator simply using malloc.
Definition: spritecache.cpp:817
OpenGLBackend::remap_zoom_loc
GLint remap_zoom_loc
Uniform location for sprite zoom;.
Definition: opengl.h:54
OpenGLBackend::remap_screen_loc
GLint remap_screen_loc
Uniform location for screen size;.
Definition: opengl.h:53
Rect
Specification of a rectangle with absolute coordinates of all edges.
Definition: geometry_type.hpp:47
CursorVars::pos
Point pos
logical mouse position
Definition: gfx_type.h:117
OpenGLBackend::vid_pbo
GLuint vid_pbo
Pixel buffer object storing the memory used for the video driver to draw to.
Definition: opengl.h:39
Sprite
Data structure describing a sprite.
Definition: spritecache.h:17
CursorVars::in_window
bool in_window
mouse inside this window, determines drawing logic
Definition: gfx_type.h:141
OpenGLBackend::ReleaseAnimBuffer
void ReleaseAnimBuffer(const Rect &update_rect)
Update animation buffer texture after the animation buffer was filled.
Definition: opengl.cpp:1237
OpenGLBackend::remap_program
GLuint remap_program
Shader program for blending and rendering a RGBA + remap texture.
Definition: opengl.h:51
OpenGLBackend::Init
const char * Init(const Dimension &screen_res)
Check for the needed OpenGL functionality and allocate all resources.
Definition: opengl.cpp:528
OpenGLBackend::vid_program
GLuint vid_program
Shader program for rendering a RGBA video buffer.
Definition: opengl.h:41
OpenGLBackend::Resize
bool Resize(int w, int h, bool force=false)
Change the size of the drawing window and allocate matching resources.
Definition: opengl.cpp:906
OpenGLBackend::GetAnimBuffer
uint8 * GetAnimBuffer()
Get a pointer to the memory for the separate animation buffer.
Definition: opengl.cpp:1172
OpenGLBackend::Encode
Sprite * Encode(const SpriteLoader::Sprite *sprite, AllocatorProc *allocator) override
Convert a sprite from the loader to our own format.
Definition: opengl.cpp:1267
IsOpenGLVersionAtLeast
bool IsOpenGLVersionAtLeast(byte major, byte minor)
Check if the current OpenGL version is equal or higher than a given one.
Definition: opengl.cpp:210
OpenGLBackend::cursor_sprite_pos
Point cursor_sprite_pos[16]
Relative position of individual cursor sprites.
Definition: opengl.h:71
OpenGLBackend::InitShaders
bool InitShaders()
Create all needed shader programs.
Definition: opengl.cpp:797
SpriteColourComponent
SpriteColourComponent
The different colour components a sprite can have.
Definition: spriteloader.hpp:21