ManaPlus
graphicsmanager.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2012-2019 The ManaPlus Developers
4  * Copyright (C) 2019-2021 Andrei Karas
5  *
6  * This file is part of The ManaPlus Client.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "graphicsmanager.h"
23 
24 #ifdef USE_OPENGL
25 #ifndef WIN32
26 
27 #ifdef ANDROID
28 #include <GLES2/gl2.h>
29 #include <GLES/glext.h>
30 #include <EGL/egl.h>
31 
32 #ifndef USE_SDL2
33 PRAGMA48(GCC diagnostic push)
34 PRAGMA48(GCC diagnostic ignored "-Wshadow")
35 #include <SDL_android.h>
36 PRAGMA48(GCC diagnostic pop)
37 #endif // USE_SDL2
38 #elif defined(__native_client__)
39 #include <GL/Regal.h>
41 #else // ANDROID
42 #ifdef USE_X11
43 #include <GL/glx.h>
44 #endif // USE_X11
45 #endif // ANDROID
46 #endif // WIN32
47 #endif // USE_OPENGL
48 
49 #include "settings.h"
50 
51 #ifdef USE_OPENGL
57 
58 #include "render/opengl/mgl.h"
59 #include "render/opengl/mglcheck.h"
60 #include "render/opengl/mglemu.h"
61 #endif // USE_OPENGL
62 
63 #include "render/sdlgraphics.h"
64 
65 #ifdef USE_OPENGL
68 #ifndef ANDROID
71 #endif // ANDROID
73 #endif // USE_OPENGL
74 
77 
78 #ifdef USE_SDL2
80 
84 #endif // USE_SDL2
85 
86 #include "utils/delete2.h"
87 #include "utils/sdlhelper.h"
88 
89 #ifdef USE_OPENGL
90 #include "test/testmain.h"
91 #else // USE_OPENGL
92 #include "configuration.h"
93 
94 #include "render/renderers.h"
95 #endif // USE_OPENGL
96 
97 PRAGMA48(GCC diagnostic push)
98 PRAGMA48(GCC diagnostic ignored "-Wshadow")
99 #include <SDL_syswm.h>
100 PRAGMA48(GCC diagnostic pop)
101 
102 #include "debug.h"
103 
104 #ifdef USE_OPENGL
105 #ifndef GL_MAX_RENDERBUFFER_SIZE
106 #define GL_MAX_RENDERBUFFER_SIZE 0x84E8
107 #endif // GL_MAX_RENDERBUFFER_SIZE
108 #define useCompression(name) \
109  { \
110  OpenGLImageHelper::setInternalTextureType(name); \
111  logger->log("using " #name " texture compression"); \
112  }
113 #endif // USE_OPENGL
114 
116 
118 
120 
121 const int densitySize = 6;
122 
123 const std::string densityNames[] =
124 {
125  "low",
126  "medium",
127  "tv",
128  "high",
129  "xhigh",
130  "xxhigh"
131 };
132 
133 #ifdef USE_OPENGL
134 GLenum GraphicsManager::mLastError(GL_NO_ERROR);
135 #endif // USE_OPENGL
136 
138  mExtensions(),
139  mPlatformExtensions(),
140  mGlVersionString(),
141  mGlVendor(),
142  mGlRenderer(),
143  mGlShaderVersionString(),
144  mMinor(0),
145  mMajor(0),
146  mSLMinor(0),
147  mSLMajor(0),
148  mPlatformMinor(0),
149  mPlatformMajor(0),
150  mMaxVertices(500),
151  mMaxFboSize(0),
152  mMaxWidth(0),
153  mMaxHeight(0),
154  mWidthMM(0),
155  mHeightMM(0),
156  mDensity(-1),
157 #ifdef USE_OPENGL
158  mUseTextureSampler(true),
159  mTextureSampler(0),
160  mSupportDebug(0),
161  mSupportModernOpengl(false),
162  mGles(false),
163 #endif // USE_OPENGL
164  mUseAtlases(false)
165 {
166 }
167 
169 {
170 #ifdef USE_OPENGL
171  if (isGLNotNull(mglGenSamplers) && mTextureSampler)
172  mglDeleteSamplers(1, &mTextureSampler);
173 #endif // USE_OPENGL
174 }
175 
176 #ifdef USE_OPENGL
178 {
179  TestMain *const test = new TestMain;
180  test->exec(false);
181  return test;
182 }
183 
185 {
186  logger->log1("start detecting best mode...");
187  logger->log1("enable opengl mode");
188  int textureSampler = 0;
189  int compressTextures = 0;
190 #if !defined(ANDROID) && !defined(__native_client__) && !defined(__SWITCH__)
192 #endif // !defined(ANDROID) && !defined(__native_client__)
193 
194  SDL_Window *const window = createWindow(100, 100, 0,
195  SDL_ANYFORMAT | SDL_OPENGL);
196  mainGraphics->setWindow(window, 100, 100);
198 
199  initOpenGL();
200  logVersion();
201 
203 
204  // detecting features by known renderers or vendors
205  if (findI(mGlRenderer, "gdi generic") != std::string::npos)
206  {
207  // windows gdi OpenGL emulation
208  logger->log("detected gdi drawing");
209  logger->log("disable OpenGL");
210  mode = RENDER_SOFTWARE;
211  }
212  else if (findI(mGlRenderer, "Software Rasterizer") != std::string::npos)
213  {
214  // software OpenGL emulation
215  logger->log("detected software drawing");
216  logger->log("disable OpenGL");
217  mode = RENDER_SOFTWARE;
218  }
219  else if (findI(mGlRenderer, "Indirect") != std::string::npos)
220  {
221  // indirect OpenGL drawing
222  logger->log("detected indirect drawing");
223  logger->log("disable OpenGL");
224  mode = RENDER_SOFTWARE;
225  }
226  else if (findI(mGlVendor, "VMWARE") != std::string::npos)
227  {
228  // vmware emulation
229  logger->log("detected VMWARE driver");
230  logger->log("disable OpenGL");
231  mode = RENDER_SOFTWARE;
232  }
233  else if (findI(mGlVendor, "NVIDIA") != std::string::npos)
234  {
235  // hope it can work well
236  logger->log("detected NVIDIA driver");
237  config.setValue("useTextureSampler", true);
238  textureSampler = 1;
239  mode = RENDER_NORMAL_OPENGL;
240  }
241 
242  // detecting feature based on OpenGL version
243  if (!checkGLVersion(1, 1))
244  {
245  // very old OpenGL version
246  logger->log("OpenGL version too old");
247  mode = RENDER_SOFTWARE;
248  }
249 
250  if (mode != RENDER_SOFTWARE && findI(mGlVersionString, "Mesa")
251  != std::string::npos)
252  {
253  // Mesa detected. In latest Mesa look like compression broken.
254  config.setValue("compresstextures", false);
255  compressTextures = 0;
256  }
257 
258  config.setValue("opengl", CAST_S32(mode));
259  config.setValue("videoconfigured", true);
260  config.write();
261 
262  logger->log("detection complete");
263  return CAST_U32(mode)
264  | (1024 * textureSampler) | (2048 * compressTextures);
265 }
266 
267 #ifdef USE_SDL2
268 #define RENDER_SOFTWARE_INIT \
269  imageHelper = new SDL2SoftwareImageHelper; \
270  surfaceImageHelper = new SurfaceImageHelper; \
271  mainGraphics = new SDL2SoftwareGraphics; \
272  screenshortHelper = new Sdl2SoftwareScreenshotHelper;
273 #define RENDER_SDL2_DEFAULT_INIT \
274  imageHelper = new SDLImageHelper; \
275  surfaceImageHelper = new SurfaceImageHelper; \
276  mainGraphics = new SDLGraphics; \
277  screenshortHelper = new SdlScreenshotHelper; \
278  mainGraphics->setRendererFlags(SDL_RENDERER_ACCELERATED); \
279  mUseTextureSampler = false;
280 #else // USE_SDL2
281 #define RENDER_SOFTWARE_INIT \
282  imageHelper = new SDLImageHelper; \
283  surfaceImageHelper = imageHelper; \
284  mainGraphics = new SDLGraphics; \
285  screenshortHelper = new SdlScreenshotHelper;
286 #define RENDER_SDL2_DEFAULT_INIT
287 #endif // USE_SDL2
288 
289 #if defined(ANDROID) || defined(__native_client__) || defined(__SWITCH__)
290 #define RENDER_NORMAL_OPENGL_INIT
291 #define RENDER_MODERN_OPENGL_INIT
292 #else // defined(ANDROID) || defined(__native_client__)
293 #define RENDER_NORMAL_OPENGL_INIT \
294  imageHelper = new OpenGLImageHelper; \
295  surfaceImageHelper = new SurfaceImageHelper; \
296  mainGraphics = new NormalOpenGLGraphics; \
297  screenshortHelper = new OpenGLScreenshotHelper; \
298  mUseTextureSampler = true;
299 #define RENDER_MODERN_OPENGL_INIT \
300  imageHelper = new OpenGLImageHelper; \
301  surfaceImageHelper = new SurfaceImageHelper; \
302  mainGraphics = new ModernOpenGLGraphics; \
303  screenshortHelper = new OpenGLScreenshotHelper; \
304  mUseTextureSampler = true;
305 #endif // defined(ANDROID) || defined(__native_client__)
306 
307 #if defined(ANDROID)
308 #define RENDER_SAFE_OPENGL_INIT
309 #define RENDER_GLES2_OPENGL_INIT
310 #else // defined(ANDROID)
311 #ifdef __SWITCH__
312 #define RENDER_SAFE_OPENGL_INIT
313 #else
314 #define RENDER_SAFE_OPENGL_INIT \
315  imageHelper = new SafeOpenGLImageHelper; \
316  surfaceImageHelper = new SurfaceImageHelper; \
317  mainGraphics = new SafeOpenGLGraphics; \
318  screenshortHelper = new OpenGLScreenshotHelper; \
319  mUseTextureSampler = false;
320 #endif
321 #define RENDER_GLES2_OPENGL_INIT \
322  imageHelper = new OpenGLImageHelper; \
323  surfaceImageHelper = new SurfaceImageHelper; \
324  mainGraphics = new MobileOpenGL2Graphics; \
325  screenshortHelper = new MobileOpenGLScreenshotHelper; \
326  mUseTextureSampler = false;
327 #endif // defined(ANDROID)
328 
329 #if defined(__native_client__) || defined(__SWITCH__)
330 #define RENDER_GLES_OPENGL_INIT
331 #else // defined(__native_client__)
332 #define RENDER_GLES_OPENGL_INIT \
333  imageHelper = new OpenGLImageHelper; \
334  surfaceImageHelper = new SurfaceImageHelper; \
335  mainGraphics = new MobileOpenGLGraphics; \
336  screenshortHelper = new OpenGLScreenshotHelper; \
337  mUseTextureSampler = false;
338 #endif // defined(__native_client__)
339 
341 {
342  RenderType useOpenGL = RENDER_SOFTWARE;
344  {
345  if (settings.options.renderer < 0)
346  {
347  useOpenGL = intToRenderType(config.getIntValue("opengl"));
348  settings.options.renderer = CAST_S32(useOpenGL);
349  }
350  else
351  {
353  }
354  }
355 
356  // Setup image loading for the right image format
357  ImageHelper::setOpenGlMode(useOpenGL);
358 
359  // Create the graphics context
360  switch (useOpenGL)
361  {
362  case RENDER_SOFTWARE:
364  mUseTextureSampler = false;
365  break;
366  case RENDER_LAST:
367  case RENDER_NULL:
368  default:
369  break;
372  break;
373  case RENDER_SAFE_OPENGL:
375  break;
378  break;
379  case RENDER_GLES2_OPENGL:
381  break;
382  case RENDER_GLES_OPENGL:
384  break;
385  case RENDER_SDL2_DEFAULT:
387  break;
388  }
389  mUseAtlases = (useOpenGL == RENDER_NORMAL_OPENGL ||
390  useOpenGL == RENDER_SAFE_OPENGL ||
391  useOpenGL == RENDER_MODERN_OPENGL ||
392  useOpenGL == RENDER_GLES_OPENGL ||
393  useOpenGL == RENDER_GLES2_OPENGL) &&
394  config.getBoolValue("useAtlases");
395 
396 #else // USE_OPENGL
397 
399 {
400  RenderType useOpenGL = RENDER_SOFTWARE;
402  useOpenGL = intToRenderType(config.getIntValue("opengl"));
403 
404  // Setup image loading for the right image format
405  ImageHelper::setOpenGlMode(useOpenGL);
406 
407  // Create the graphics context
408  switch (useOpenGL)
409  {
410  case RENDER_SOFTWARE:
411  case RENDER_SAFE_OPENGL:
412  case RENDER_GLES_OPENGL:
413  case RENDER_GLES2_OPENGL:
416  case RENDER_NULL:
417  case RENDER_LAST:
418  default:
419 #ifndef USE_SDL2
420  case RENDER_SDL2_DEFAULT:
425 #else // USE_SDL2
426 
427  imageHelper = new SDL2SoftwareImageHelper;
429  mainGraphics = new SDL2SoftwareGraphics;
430  screenshortHelper = new Sdl2SoftwareScreenshotHelper;
431 
432 #endif // USE_SDL2
433 
434  break;
435 #ifdef USE_SDL2
436  case RENDER_SDL2_DEFAULT:
440  mainGraphics->setRendererFlags(SDL_RENDERER_ACCELERATED);
442  break;
443 #endif // USE_SDL2
444  };
445 #endif // USE_OPENGL
446 }
447 
449 {
452  delete surfaceImageHelper;
453  surfaceImageHelper = nullptr;
455 }
456 
458 {
459  const int bpp = 0;
460  const bool fullscreen = config.getBoolValue("screen");
461  const bool hwaccel = config.getBoolValue("hwaccel");
462  const bool enableResize = config.getBoolValue("enableresize");
463  const bool noFrame = config.getBoolValue("noframe");
464  const bool allowHighDPI = config.getBoolValue("allowHighDPI");
465 
466 #ifdef ANDROID
467 // int width = config.getValue("screenwidth", 0);
468 // int height = config.getValue("screenheight", 0);
469  StringVect videoModes;
470  SDL::getAllVideoModes(videoModes);
471  if (videoModes.empty())
472  logger->error("no video modes detected");
473  STD_VECTOR<int> res;
474  splitToIntVector(res, videoModes[0], 'x');
475  if (res.size() != 2)
476  logger->error("no video modes detected");
477 
478  int width = res[0];
479  int height = res[1];
480 #elif defined __native_client__
481 #ifdef USE_SDL2
482  // not implemented
483 #else // USE_SDL2
484 
485  const SDL_VideoInfo* info = SDL_GetVideoInfo();
486  int width = info->current_w;
487  int height = info->current_h;
488 #endif // USE_SDL2
489 #elif defined __SWITCH__
490  int width = 1280;
491  int height = 720;
492 #else // defined __native_client__
493 
494  int width = config.getIntValue("screenwidth");
495  int height = config.getIntValue("screenheight");
496 #endif // defined __native_client__
497 
498  const int scale = config.getIntValue("scale");
499 
500  // Try to set the desired video mode
501  if (!mainGraphics->setVideoMode(width, height, scale, bpp,
502  fullscreen, hwaccel, enableResize, noFrame, allowHighDPI))
503  {
504  logger->log(strprintf("Couldn't set %dx%dx%d video mode: %s",
505  width, height, bpp, SDL_GetError()));
506 
507  const int oldWidth = config.getValueInt("oldscreenwidth", -1);
508  const int oldHeight = config.getValueInt("oldscreenheight", -1);
509  const int oldFullscreen = config.getValueInt("oldscreen", -1);
510  if (oldWidth != -1 && oldHeight != -1 && oldFullscreen != -1)
511  {
512  config.deleteKey("oldscreenwidth");
513  config.deleteKey("oldscreenheight");
514  config.deleteKey("oldscreen");
515 
516  config.setValueInt("screenwidth", oldWidth);
517  config.setValueInt("screenheight", oldHeight);
518  config.setValue("screen", oldFullscreen == 1);
519  if (!mainGraphics->setVideoMode(oldWidth, oldHeight,
520  scale,
521  bpp,
522  oldFullscreen != 0,
523  hwaccel,
524  enableResize,
525  noFrame,
526  allowHighDPI))
527  {
528  logger->safeError(strprintf("Couldn't restore %dx%dx%d "
529  "video mode: %s", oldWidth, oldHeight, bpp,
530  SDL_GetError()));
531  }
532  }
533  }
534 }
535 
537 {
539 #ifdef USE_OPENGL
541 #if !defined(ANDROID) && !defined(__SWITCH__)
543 #endif // ANDROID
544  SurfaceImageHelper::SDLSetEnableAlphaCache(
545  config.getBoolValue("alphaCache") &&
547  ImageHelper::setEnableAlpha((config.getFloatValue("guialpha") != 1.0F ||
549  config.getBoolValue("enableGuiOpacity"));
550 #else // USE_OPENGL
551  SurfaceImageHelper::SDLSetEnableAlphaCache(
552  config.getBoolValue("alphaCache"));
553  ImageHelper::setEnableAlpha(config.getFloatValue("guialpha") != 1.0F &&
554  config.getBoolValue("enableGuiOpacity"));
555 #endif // USE_OPENGL
556  createRenderers();
557  setVideoMode();
558  detectPixelSize();
559 #ifdef USE_OPENGL
560  if (config.getBoolValue("checkOpenGLVersion") == true)
561  {
562  const RenderType oldOpenGLMode = openGLMode;
564  {
565  if (!mSupportModernOpengl || !checkGLVersion(3, 0))
566  {
567  logger->log("Fallback to normal OpenGL mode");
569  }
570  }
572  {
573  if (!checkGLVersion(2, 0))
574  {
575  logger->log("Fallback to safe OpenGL mode");
577  }
578  }
580  {
581  if (!checkGLVersion(2, 0) && !checkGLesVersion(1, 0))
582  {
583  logger->log("Fallback to safe OpenGL mode");
585  }
586  }
588  {
589  // +++ here need check also not implemented gles flag
590  if (!checkGLVersion(2, 0))
591  {
592  logger->log("Fallback to software mode");
594  }
595  }
596 
597  if (openGLMode != oldOpenGLMode)
598  {
599  deleteRenderers();
602  createRenderers();
603  setVideoMode();
604  detectPixelSize();
605  }
606  }
607 #if !defined(ANDROID) && !defined(__APPLE__)
608  const std::string str = config.getStringValue("textureSize");
609  STD_VECTOR<int> sizes;
610  splitToIntVector(sizes, str, ',');
611  const size_t pos = CAST_SIZE(openGLMode);
612  if (sizes.size() <= pos)
613  settings.textureSize = 1024;
614  else
615  settings.textureSize = sizes[pos];
616  logger->log("Detected max texture size: %u", settings.textureSize);
617 #endif // !defined(ANDROID) && !defined(__APPLE__)
618 #endif // USE_OPENGL
619 }
620 
621 #ifdef USE_SDL2
622 SDL_Window *GraphicsManager::createWindow(const int w, const int h,
623  const int bpp A_UNUSED,
624  const int flags)
625 {
626  return SDL_CreateWindow("ManaPlus", SDL_WINDOWPOS_UNDEFINED,
627  SDL_WINDOWPOS_UNDEFINED, w, h, flags);
628 }
629 
630 SDL_Renderer *GraphicsManager::createRenderer(SDL_Window *const window,
631  const int flags)
632 {
633  SDL::setRendererHint(config.getStringValue("sdlDriver"));
634  SDL_Renderer *const renderer = SDL_CreateRenderer(window, -1, flags);
635  SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
636  return renderer;
637 }
638 #else // USE_SDL2
639 
640 SDL_Window *GraphicsManager::createWindow(const int w, const int h,
641  const int bpp, const int flags)
642 {
643  return SDL_SetVideoMode(w, h, bpp, flags);
644 }
645 #endif // USE_SDL2
646 
647 #ifdef USE_OPENGL
649 {
650  mExtensions.clear();
651  logger->log1("opengl extensions: ");
652  if (checkGLVersion(3, 0))
653  { // get extensions in new way
654  assignFunction2(glGetStringi, "glGetStringi")
655  std::string extList;
656  int num = 0;
657  glGetIntegerv(GL_NUM_EXTENSIONS, &num);
658  for (int f = 0; f < num; f ++)
659  {
660  std::string str = reinterpret_cast<const char*>(
661  mglGetStringi(GL_EXTENSIONS, f));
662  mExtensions.insert(str);
663  extList.append(str).append(" ");
664  }
665  logger->log1(extList.c_str());
666  }
667  else
668  { // get extensions in old way
669  char const *extensions = reinterpret_cast<char const *>(
670  mglGetString(GL_EXTENSIONS));
671  if (extensions)
672  {
673  logger->log1(extensions);
674  splitToStringSet(mExtensions, extensions, ' ');
675  }
676  }
677 }
678 
680 {
681  SDL_SysWMinfo info;
682  SDL_VERSION(&info.version)
684  {
685 #ifdef WIN32
686  if (!mwglGetExtensionsString)
687  return;
688 
689  HDC hdc = GetDC(info.window);
690  if (hdc)
691  {
692  const char *const extensions = mwglGetExtensionsString(hdc);
693  if (extensions)
694  {
695  logger->log1("wGL extensions:");
696  logger->log1(extensions);
697  splitToStringSet(mPlatformExtensions, extensions, ' ');
698  }
699  }
700 #elif defined USE_X11
701  Display *const display = info.info.x11.display;
702  if (display)
703  {
704  Screen *const screen = XDefaultScreenOfDisplay(display);
705  if (!screen)
706  return;
707 
708  const int screenNum = XScreenNumberOfScreen(screen);
709  const char *const extensions = glXQueryExtensionsString(
710  display, screenNum);
711  if (extensions)
712  {
713  logger->log1("glx extensions:");
714  logger->log1(extensions);
715  splitToStringSet(mPlatformExtensions, extensions, ' ');
716  }
717  glXQueryVersion(display, &mPlatformMajor, &mPlatformMinor);
718  if (checkPlatformVersion(1, 1))
719  {
720  const char *const vendor1 = glXQueryServerString(
721  display, screenNum, GLX_VENDOR);
722  if (vendor1)
723  logger->log("glx server vendor: %s", vendor1);
724  const char *const version1 = glXQueryServerString(
725  display, screenNum, GLX_VERSION);
726  if (version1)
727  logger->log("glx server version: %s", version1);
728  const char *const extensions1 = glXQueryServerString(
729  display, screenNum, GLX_EXTENSIONS);
730  if (extensions1)
731  {
732  logger->log1("glx server extensions:");
733  logger->log1(extensions1);
734  }
735 
736  const char *const vendor2 = glXGetClientString(
737  display, GLX_VENDOR);
738  if (vendor2)
739  logger->log("glx client vendor: %s", vendor2);
740  const char *const version2 = glXGetClientString(
741  display, GLX_VERSION);
742  if (version2)
743  logger->log("glx client version: %s", version2);
744  const char *const extensions2 = glXGetClientString(
745  display, GLX_EXTENSIONS);
746  if (extensions2)
747  {
748  logger->log1("glx client extensions:");
749  logger->log1(extensions2);
750  }
751  }
752  logger->log("width=%d", DisplayWidth(display, screenNum));
753  }
754 #endif // WIN32
755  }
756 }
757 
758 bool GraphicsManager::supportExtension(const std::string &ext) const
759 {
760  return mExtensions.find(ext) != mExtensions.end();
761 }
762 
764 {
765  const int compressionFormat = config.getIntValue("compresstextures");
766  // using extensions if can
767  if (checkGLVersion(3, 1) ||
768  checkGLesVersion(2, 0) ||
769  supportExtension("GL_ARB_texture_compression"))
770  {
771  GLint num = 0;
772  mglGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num);
773  logger->log("support %d compressed formats", num);
774  GLint *const formats = new GLint[num > 10
775  ? CAST_SIZE(num) : 10];
776  mglGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats);
777  for (int f = 0; f < num; f ++)
778  logger->log(" 0x%x", CAST_U32(formats[f]));
779 
780  if (compressionFormat)
781  {
782  for (int f = 0; f < num; f ++)
783  {
784  switch (formats[f])
785  {
787  if (compressionFormat == 1)
788  {
789  delete []formats;
791  return;
792  }
793  break;
795  if (compressionFormat == 2)
796  {
797  delete []formats;
799  return;
800  }
801  break;
803  if (compressionFormat == 4)
804  {
805  delete []formats;
807  return;
808  }
809  break;
810  default:
811  break;
812  }
813  }
814  if (compressionFormat == 3)
815  {
816  delete []formats;
818  return;
819  }
820 
821  // workaround for MESA bptc compression detection
822  if (compressionFormat == 4
823  && supportExtension("GL_ARB_texture_compression_bptc"))
824  {
825  delete []formats;
827  return;
828  }
829  }
830  delete []formats;
831  if (compressionFormat)
832  logger->log1("no correct compression format found");
833  }
834  else
835  {
836  if (compressionFormat)
837  logger->log1("no correct compression format found");
838  }
839 }
840 
842 {
843  const int renderer = settings.options.renderer;
844 
845  // using default formats
846  if (renderer == RENDER_MODERN_OPENGL ||
847  renderer == RENDER_GLES_OPENGL ||
848  renderer == RENDER_GLES2_OPENGL ||
849  config.getBoolValue("newtextures"))
850  {
852 #if !defined(ANDROID) && !defined(__SWITCH__)
854 #endif // ANDROID
855 
856  logger->log1("using RGBA texture format");
857  }
858  else
859  {
861 #if !defined(ANDROID) && !defined(__SWITCH__)
863 #endif // ANDROID
864 
865  logger->log1("using 4 texture format");
866  }
867 }
868 
869 void GraphicsManager::logString(const char *const format, const int num)
870 {
871  const char *str = reinterpret_cast<const char*>(mglGetString(num));
872  if (!str)
873  logger->log(format, "?");
874  else
875  logger->log(format, str);
876 }
877 
878 std::string GraphicsManager::getGLString(const int num)
879 {
880  const char *str = reinterpret_cast<const char*>(mglGetString(num));
881  return str ? str : "";
882 }
883 
885 {
886  mGlVersionString = getGLString(GL_VERSION);
887  std::string version = mGlVersionString;
888  if (findCutFirst(version, "OpenGL ES "))
889  mGles = true;
890  sscanf(version.c_str(), "%5d.%5d", &mMajor, &mMinor);
891  logger->log("Detected gl version: %d.%d", mMajor, mMinor);
892  mGlVendor = getGLString(GL_VENDOR);
893  mGlRenderer = getGLString(GL_RENDERER);
894  mGlShaderVersionString = getGLString(GL_SHADING_LANGUAGE_VERSION);
895  version = mGlShaderVersionString;
896  cutFirst(version, "OpenGL ES GLSL ES ");
897  cutFirst(version, "OpenGL ES GLSL ");
898  cutFirst(version, "OpenGL ES ");
899  sscanf(version.c_str(), "%5d.%5d", &mSLMajor, &mSLMinor);
900  logger->log("Detected glsl version: %d.%d", mSLMajor, mSLMinor);
901 #ifdef ANDROID
902  if (!mMajor && !mMinor)
903  {
904  logger->log("Overriding detected OpenGL version on Android to 1.0");
905  mGles = true;
906  mMajor = 1;
907  mMinor = 0;
908  }
909 #endif // ANDROID
910 }
911 
913 {
914  logger->log("gl vendor: " + mGlVendor);
915  logger->log("gl renderer: " + mGlRenderer);
916  logger->log("gl version: " + mGlVersionString);
917  logger->log("glsl version: " + mGlShaderVersionString);
918 }
919 
920 bool GraphicsManager::checkGLVersion(const int major, const int minor) const
921 {
922  return mMajor > major || (mMajor == major && mMinor >= minor);
923 }
924 
925 bool GraphicsManager::checkSLVersion(const int major, const int minor) const
926 {
927  return mSLMajor > major || (mSLMajor == major && mSLMinor >= minor);
928 }
929 
930 bool GraphicsManager::checkGLesVersion(const int major, const int minor) const
931 {
932  return mGles && (mMajor > major || (mMajor == major && mMinor >= minor));
933 }
934 
936  const int minor) const
937 {
938  return mPlatformMajor > major || (mPlatformMajor == major
939  && mPlatformMinor >= minor);
940 }
941 
942 void GraphicsManager::createFBO(const int width, const int height,
943  FBOInfo *const fbo)
944 {
945  if (!fbo)
946  return;
947 
948  // create a texture object
949  glGenTextures(1, &fbo->textureId);
950  glBindTexture(OpenGLImageHelper::mTextureType, fbo->textureId);
951  glTexParameterf(OpenGLImageHelper::mTextureType,
952  GL_TEXTURE_MAG_FILTER, GL_LINEAR);
953  glTexParameterf(OpenGLImageHelper::mTextureType,
954  GL_TEXTURE_MIN_FILTER, GL_LINEAR);
955  glTexParameterf(OpenGLImageHelper::mTextureType,
956  GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
957  glTexParameterf(OpenGLImageHelper::mTextureType,
958  GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
959  glTexImage2D(OpenGLImageHelper::mTextureType, 0, GL_RGBA8, width, height,
960  0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
961  glBindTexture(OpenGLImageHelper::mTextureType, 0);
962 
963  // create a renderbuffer object to store depth info
964  mglGenRenderbuffers(1, &fbo->rboId);
965  mglBindRenderbuffer(GL_RENDERBUFFER, fbo->rboId);
966  mglRenderbufferStorage(GL_RENDERBUFFER,
967  GL_DEPTH_COMPONENT, width, height);
968  mglBindRenderbuffer(GL_RENDERBUFFER, 0);
969 
970  // create a framebuffer object
971  mglGenFramebuffers(1, &fbo->fboId);
972  mglBindFramebuffer(GL_FRAMEBUFFER, fbo->fboId);
973 
974  // attach the texture to FBO color attachment point
975  mglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
976  OpenGLImageHelper::mTextureType, fbo->textureId, 0);
977 
978  // attach the renderbuffer to depth attachment point
979  mglFramebufferRenderbuffer(GL_FRAMEBUFFER,
980  GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->rboId);
981 
982  mglBindFramebuffer(GL_FRAMEBUFFER, fbo->fboId);
983  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
984 }
985 
986 void GraphicsManager::deleteFBO(FBOInfo *const fbo)
987 {
988  if (!fbo)
989  return;
990 
991  mglBindFramebuffer(GL_FRAMEBUFFER, 0);
992  if (fbo->fboId)
993  {
994  mglDeleteFramebuffers(1, &fbo->fboId);
995  fbo->fboId = 0;
996  }
997  mglBindRenderbuffer(GL_RENDERBUFFER, 0);
998  if (fbo->rboId)
999  {
1000  mglDeleteRenderbuffers(1, &fbo->rboId);
1001  fbo->rboId = 0;
1002  }
1003  if (fbo->textureId)
1004  {
1005  glDeleteTextures(1, &fbo->textureId);
1006  fbo->textureId = 0;
1007  }
1008 }
1009 
1011 {
1012 #ifdef __native_client__
1013  emulateFunction(glTextureSubImage2DEXT);
1014 #else // __native_client__
1015 
1016  const bool is10 = checkGLVersion(1, 0);
1017  const bool is11 = checkGLVersion(1, 1);
1018  const bool is12 = checkGLVersion(1, 2);
1019  const bool is13 = checkGLVersion(1, 3);
1020  const bool is15 = checkGLVersion(1, 5);
1021  const bool is20 = checkGLVersion(2, 0);
1022  const bool is21 = checkGLVersion(2, 1);
1023  const bool is30 = checkGLVersion(3, 0);
1024  const bool is33 = checkGLVersion(3, 3);
1025  const bool is41 = checkGLVersion(4, 1);
1026  const bool is42 = checkGLVersion(4, 2);
1027  const bool is43 = checkGLVersion(4, 3);
1028  const bool is44 = checkGLVersion(4, 4);
1029  const bool is45 = checkGLVersion(4, 5);
1030  mSupportModernOpengl = true;
1031 
1032  // Texture sampler
1033  if (is10 && (is33 || supportExtension("GL_ARB_sampler_objects")))
1034  {
1035  logger->log1("found GL_ARB_sampler_objects");
1036  assignFunction(glGenSamplers)
1037  assignFunction(glDeleteSamplers)
1038  assignFunction(glBindSampler)
1039  assignFunction(glSamplerParameteri)
1040  if (isGLNotNull(mglGenSamplers)
1041  && config.getBoolValue("useTextureSampler"))
1042  {
1043  mUseTextureSampler &= true;
1044  }
1045  else
1046  {
1047  mUseTextureSampler = false;
1048  }
1049  }
1050  else
1051  {
1052  logger->log1("texture sampler not found");
1053  mUseTextureSampler = false;
1054  }
1055 
1056  if (!is11)
1057  {
1058  mSupportModernOpengl = false;
1059  emulateFunction(glTextureSubImage2DEXT);
1060  return;
1061  }
1062 
1063 /*
1064  if (findI(mGlVendor, "NVIDIA") != std::string::npos ||
1065  mGlVersionString.find("Mesa 10.6.") != std::string::npos ||
1066  mGlVersionString.find("Mesa 11.1.1") != std::string::npos ||
1067  mGlVersionString.find("Mesa 11.1.2") != std::string::npos ||
1068  mGlVersionString.find("Mesa 11.1.3") != std::string::npos ||
1069  mGlVersionString.find("Mesa 11.2") != std::string::npos ||
1070  (findI(mGlRenderer, "AMD Radeon HD") != std::string::npos &&
1071  (mGlVersionString.find(
1072  "Compatibility Profile Context 14.") != std::string::npos ||
1073  mGlVersionString.find(
1074  "Compatibility Profile Context 15.") != std::string::npos)))
1075  {
1076  logger->log1("Not checked for DSA because on "
1077  "NVIDIA or AMD or in Mesa it broken");
1078  emulateFunction(glTextureSubImage2DEXT);
1079  }
1080  else
1081 */
1082  { // not for NVIDIA. in NVIDIA atleast in windows drivers DSA is broken
1083  // Mesa 10.6.3 show support for DSA, but it broken. Works in 10.7 dev
1084  if (config.getBoolValue("enableDSA") == true)
1085  {
1086  if (is45)
1087  {
1088  logger->log1("found GL_EXT_direct_state_access");
1089  assignFunction(glTextureSubImage2D)
1090  }
1091  else if (supportExtension("GL_EXT_direct_state_access"))
1092  {
1093  logger->log1("found GL_EXT_direct_state_access");
1094  assignFunctionEmu2(glTextureSubImage2DEXT,
1095  "glTextureSubImage2DEXT")
1096  }
1097  else if (supportExtension("GL_ARB_direct_state_access"))
1098  {
1099  logger->log1("found GL_ARB_direct_state_access");
1100  logger->log1("GL_EXT_direct_state_access not found");
1101  assignFunction(glTextureSubImage2D)
1102  }
1103  else
1104  {
1105  logger->log1("GL_EXT_direct_state_access not found");
1106  logger->log1("GL_ARB_direct_state_access not found");
1107  emulateFunction(glTextureSubImage2DEXT);
1108  }
1109  }
1110  else
1111  {
1112  logger->log1("Direct state access disabled in settings");
1113  emulateFunction(glTextureSubImage2DEXT);
1114  }
1115  }
1116 
1117  if (is12 && (is42 || supportExtension("GL_ARB_texture_storage")))
1118  {
1119  logger->log1("found GL_ARB_texture_storage");
1120  assignFunction(glTexStorage2D)
1121  }
1122  else
1123  {
1124  logger->log1("GL_ARB_texture_storage not found");
1125  }
1126 
1127  if (is13 || supportExtension("GL_ARB_multitexture"))
1128  {
1129  logger->log1("found GL_ARB_multitexture or OpenGL 1.3");
1130  assignFunction(glActiveTexture)
1131  }
1132  else
1133  {
1134  emulateFunction(glActiveTexture);
1135  logger->log1("GL_ARB_multitexture not found");
1136  }
1137 
1138  if (is20 || supportExtension("GL_ARB_explicit_attrib_location"))
1139  {
1140  logger->log1("found GL_ARB_explicit_attrib_location or OpenGL 2.0");
1141  assignFunction(glBindAttribLocation)
1142  }
1143  else
1144  {
1145  logger->log1("GL_ARB_explicit_attrib_location not found");
1146  }
1147 
1148  if (is30 || supportExtension("GL_ARB_framebuffer_object"))
1149  { // frame buffer supported
1150  logger->log1("found GL_ARB_framebuffer_object");
1151  assignFunction(glGenRenderbuffers)
1152  assignFunction(glBindRenderbuffer)
1153  assignFunction(glRenderbufferStorage)
1154  assignFunction(glGenFramebuffers)
1155  assignFunction(glBindFramebuffer)
1156  assignFunction(glFramebufferTexture2D)
1157  assignFunction(glFramebufferRenderbuffer)
1158  assignFunction(glDeleteFramebuffers)
1159  assignFunction(glDeleteRenderbuffers)
1160  assignFunction(glCheckFramebufferStatus)
1161  }
1162  else if (supportExtension("GL_EXT_framebuffer_object"))
1163  { // old frame buffer extension
1164  logger->log1("found GL_EXT_framebuffer_object");
1165  assignFunctionEXT(glGenRenderbuffers)
1166  assignFunctionEXT(glBindRenderbuffer)
1167  assignFunctionEXT(glRenderbufferStorage)
1168  assignFunctionEXT(glGenFramebuffers)
1169  assignFunctionEXT(glBindFramebuffer)
1170  assignFunctionEXT(glFramebufferTexture2D)
1171  assignFunctionEXT(glFramebufferRenderbuffer)
1172  assignFunctionEXT(glDeleteFramebuffers)
1173  assignFunctionEXT(glDeleteRenderbuffers)
1174  }
1175  else
1176  { // no frame buffer support
1177  logger->log1("GL_ARB_framebuffer_object or "
1178  "GL_EXT_framebuffer_object not found");
1179  config.setValue("usefbo", false);
1180  }
1181 
1182  // debug extensions
1183  if (is43 || supportExtension("GL_KHR_debug"))
1184  {
1185  logger->log1("found GL_KHR_debug");
1186  assignFunction(glDebugMessageControl)
1187  assignFunction(glDebugMessageCallback)
1188  assignFunction(glPushDebugGroup)
1189  assignFunction(glPopDebugGroup)
1190  assignFunction(glObjectLabel)
1191  mSupportDebug = 2;
1192  }
1193  else if (supportExtension("GL_ARB_debug_output"))
1194  {
1195  logger->log1("found GL_ARB_debug_output");
1196  assignFunctionARB(glDebugMessageControl)
1197  assignFunctionARB(glDebugMessageCallback)
1198  mSupportDebug = 1;
1199  }
1200  else
1201  {
1202  logger->log1("debug extensions not found");
1203  mSupportDebug = 0;
1204  }
1205 
1206  if (supportExtension("GL_GREMEDY_frame_terminator"))
1207  {
1208  logger->log1("found GL_GREMEDY_frame_terminator");
1209  assignFunction2(glFrameTerminator, "glFrameTerminatorGREMEDY")
1210  }
1211  else
1212  {
1213  logger->log1("GL_GREMEDY_frame_terminator not found");
1214  }
1215  if (is44 || supportExtension("GL_EXT_debug_label"))
1216  {
1217  logger->log1("found GL_EXT_debug_label");
1218  assignFunction2(glLabelObject, "glObjectLabel")
1219  if (isGLNull(mglLabelObject))
1220  assignFunctionEXT(glLabelObject)
1221  assignFunctionEXT(glGetObjectLabel)
1222  }
1223  else
1224  {
1225  logger->log1("GL_EXT_debug_label not found");
1226  }
1227  if (supportExtension("GL_GREMEDY_string_marker"))
1228  {
1229  logger->log1("found GL_GREMEDY_string_marker");
1230  assignFunction2(glPushGroupMarker, "glStringMarkerGREMEDY")
1231  }
1232  else
1233  {
1234  logger->log1("GL_GREMEDY_string_marker not found");
1235  }
1236  if (supportExtension("GL_EXT_debug_marker"))
1237  {
1238  logger->log1("found GL_EXT_debug_marker");
1239  assignFunctionEXT(glInsertEventMarker)
1240  assignFunctionEXT(glPushGroupMarker)
1241  assignFunctionEXT(glPopGroupMarker)
1242  }
1243  else
1244  {
1245  logger->log1("GL_EXT_debug_marker not found");
1246  }
1247  if (is15 && (is30 || supportExtension("GL_EXT_timer_query")))
1248  {
1249  logger->log1("found GL_EXT_timer_query");
1250  assignFunction(glGenQueries)
1251  assignFunction(glBeginQuery)
1252  assignFunction(glEndQuery)
1253  assignFunction(glDeleteQueries)
1254  assignFunction(glGetQueryObjectiv)
1255  assignFunctionEXT(glGetQueryObjectui64v)
1256  }
1257  else
1258  {
1259  logger->log1("GL_EXT_timer_query not supported");
1260  }
1261  if (is20 && (is43 || supportExtension("GL_ARB_invalidate_subdata")))
1262  {
1263  logger->log1("found GL_ARB_invalidate_subdata");
1264  assignFunction(glInvalidateTexImage)
1265  }
1266  else
1267  {
1268  logger->log1("GL_ARB_invalidate_subdata not supported");
1269  }
1270  if (is21 && (is30 || supportExtension("GL_ARB_vertex_array_object")))
1271  {
1272  logger->log1("found GL_ARB_vertex_array_object");
1273  assignFunction(glGenVertexArrays)
1274  assignFunction(glBindVertexArray)
1275  assignFunction(glDeleteVertexArrays)
1276  assignFunction(glVertexAttribPointer)
1277  assignFunction(glEnableVertexAttribArray)
1278  assignFunction(glDisableVertexAttribArray)
1279  assignFunction(glVertexAttribIPointer)
1280  }
1281  else
1282  {
1283  mSupportModernOpengl = false;
1284  logger->log1("GL_ARB_vertex_array_object not found");
1285  }
1286  if (is20 || supportExtension("GL_ARB_vertex_buffer_object"))
1287  {
1288  assignFunction(glGenBuffers)
1289  assignFunction(glDeleteBuffers)
1290  assignFunction(glBindBuffer)
1291  assignFunction(glBufferData)
1292  assignFunction(glIsBuffer)
1293  }
1294  else
1295  {
1296  mSupportModernOpengl = false;
1297  logger->log1("buffers extension not found");
1298  }
1299  if (is43 || supportExtension("GL_ARB_copy_image"))
1300  {
1301  logger->log1("found GL_ARB_copy_image");
1302  assignFunction(glCopyImageSubData)
1303  }
1304  else
1305  {
1306  logger->log1("GL_ARB_copy_image not found");
1307  }
1308  if (is44 || supportExtension("GL_ARB_clear_texture"))
1309  {
1310  logger->log1("found GL_ARB_clear_texture");
1311  assignFunction(glClearTexImage)
1312  assignFunction(glClearTexSubImage)
1313  }
1314  else
1315  {
1316  logger->log1("GL_ARB_clear_texture not found");
1317  }
1318  if (is20 || supportExtension("GL_ARB_shader_objects"))
1319  {
1320  logger->log1("found GL_ARB_shader_objects");
1321  assignFunction(glCreateShader)
1322  assignFunction(glDeleteShader)
1323  assignFunction(glGetShaderiv)
1324  assignFunction(glGetShaderInfoLog)
1325  assignFunction(glGetShaderSource)
1326  assignFunction(glShaderSource)
1327  assignFunction(glCompileShader)
1328  assignFunction(glLinkProgram)
1329  assignFunction(glGetProgramInfoLog)
1330  assignFunction(glDeleteProgram)
1331  assignFunction(glCreateProgram)
1332  assignFunction(glAttachShader)
1333  assignFunction(glDetachShader)
1334  assignFunction(glGetAttachedShaders)
1335  assignFunction(glGetUniformLocation)
1336  assignFunction(glGetActiveUniform)
1337  assignFunction(glGetProgramiv)
1338  assignFunction(glUseProgram)
1339  assignFunction(glValidateProgram)
1340  assignFunction(glGetAttribLocation)
1341  assignFunction(glUniform1f)
1342  assignFunction(glUniform2f)
1343  assignFunction(glUniform3f)
1344  assignFunction(glUniform4f)
1345 
1346  if (is30 || supportExtension("GL_EXT_gpu_shader4"))
1347  {
1348  logger->log1("found GL_EXT_gpu_shader4");
1349  assignFunction(glBindFragDataLocation)
1350  }
1351  else
1352  {
1353  mSupportModernOpengl = false;
1354  logger->log1("GL_EXT_gpu_shader4 not supported");
1355  }
1356  if (is41 || supportExtension("GL_ARB_separate_shader_objects"))
1357  {
1358  logger->log1("found GL_ARB_separate_shader_objects");
1359  assignFunction(glProgramUniform1f)
1360  assignFunction(glProgramUniform2f)
1361  assignFunction(glProgramUniform3f)
1362  assignFunction(glProgramUniform4f)
1363  }
1364  else
1365  {
1366  logger->log1("GL_ARB_separate_shader_objects not supported");
1367  }
1368  if (is43 || supportExtension("GL_ARB_vertex_attrib_binding"))
1369  {
1370  logger->log1("found GL_ARB_vertex_attrib_binding");
1371  assignFunction(glBindVertexBuffer)
1372  assignFunction(glVertexAttribBinding)
1373  assignFunction(glVertexAttribFormat)
1374  assignFunction(glVertexAttribIFormat)
1375  }
1376  else
1377  {
1378  mSupportModernOpengl = false;
1379  logger->log1("GL_ARB_vertex_attrib_binding not supported");
1380  }
1381  if (is44 || supportExtension("GL_ARB_multi_bind"))
1382  {
1383  logger->log1("found GL_ARB_multi_bind");
1384  assignFunction(glBindVertexBuffers)
1385  }
1386  else
1387  {
1388  logger->log1("GL_ARB_multi_bind not supported");
1389  }
1390  }
1391  else
1392  {
1393  mSupportModernOpengl = false;
1394  logger->log1("shaders not supported");
1395  }
1396 
1397 #ifdef WIN32
1398  assignFunctionARB(wglGetExtensionsString)
1399 #endif // WIN32
1400 #endif // __native_client__
1401 }
1402 
1404 {
1405  GLint value = 0;
1406 #ifdef __native_client__
1407  mMaxVertices = 500;
1408 #else // __native_client__
1409 
1410  glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &value);
1411  logger->log("GL_MAX_ELEMENTS_VERTICES: %d", value);
1412 
1413  mMaxVertices = value;
1414 
1415  value = 0;
1416  glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &value);
1417  logger->log("GL_MAX_ELEMENTS_INDICES: %d", value);
1418  if (value < mMaxVertices)
1419  mMaxVertices = value;
1420  if (!mMaxVertices)
1421  {
1422  logger->log("Got 0 max amount of vertices or indicies. "
1423  "Overriding to 500");
1424  mMaxVertices = 500;
1425  }
1426 #endif // __native_client__
1427 
1428  value = 0;
1429  glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &value);
1430  logger->log("Max FBO size: %d", value);
1431  mMaxFboSize = value;
1432 }
1433 
1435 {
1436  setGLVersion();
1437  updateExtensions();
1440  updateDebugLog();
1442  updateLimits();
1443 }
1444 
1446 {
1447  GLenum err = getLastError();
1448  if (err)
1449  logger->log(errorToString(err));
1450  if (mUseTextureSampler)
1451  {
1452  logger->log1("using texture sampler");
1453  mglGenSamplers(1, &mTextureSampler);
1454  if (getLastError() != GL_NO_ERROR)
1455  {
1456  mUseTextureSampler = false;
1457  logger->log1("texture sampler error");
1459  return;
1460  }
1462  mglBindSampler(0, mTextureSampler);
1463  if (getLastError() != GL_NO_ERROR)
1464  {
1465  mUseTextureSampler = false;
1466  logger->log1("texture sampler error");
1467  }
1468  }
1470 #if !defined(ANDROID) && !defined(__SWITCH__)
1472 #endif // ANDROID
1473 }
1474 
1476 {
1477  GLenum tmp = glGetError();
1478  GLenum error = GL_NO_ERROR;
1479  while (tmp != GL_NO_ERROR)
1480  {
1481  error = tmp;
1482  mLastError = tmp;
1483  tmp = glGetError();
1484  }
1485  return error;
1486 }
1487 
1488 std::string GraphicsManager::errorToString(const GLenum error)
1489 {
1490  if (error)
1491  {
1492  std::string errmsg("Unknown error");
1493  switch (error)
1494  {
1495  case GL_INVALID_ENUM:
1496  errmsg = "GL_INVALID_ENUM";
1497  break;
1498  case GL_INVALID_VALUE:
1499  errmsg = "GL_INVALID_VALUE";
1500  break;
1501  case GL_INVALID_OPERATION:
1502  errmsg = "GL_INVALID_OPERATION";
1503  break;
1504  case GL_STACK_OVERFLOW:
1505  errmsg = "GL_STACK_OVERFLOW";
1506  break;
1507  case GL_STACK_UNDERFLOW:
1508  errmsg = "GL_STACK_UNDERFLOW";
1509  break;
1510  case GL_OUT_OF_MEMORY:
1511  errmsg = "GL_OUT_OF_MEMORY";
1512  break;
1513  default:
1514  break;
1515  }
1516  return "OpenGL error: " + errmsg;
1517  }
1518  return "";
1519 }
1520 
1522 {
1523  const GLenum error = GraphicsManager::getLastError();
1524  if (error != GL_NO_ERROR)
1526 }
1527 
1529 {
1530  config.setValue("videodetected", true);
1531  TestMain *const test = startDetection();
1532 
1533  if (test)
1534  {
1535  const Configuration &conf = test->getConfig();
1536  int val = conf.getValueInt("opengl", -1);
1537  if (val >= 0 && val < CAST_S32(RENDER_LAST))
1538  {
1539  config.setValue("opengl", val);
1540  val = conf.getValue("useTextureSampler", -1);
1541  if (val != -1)
1542  config.setValue("useTextureSampler", val);
1543  val = conf.getValue("compresstextures", -1);
1544  if (val != -1)
1545  config.setValue("compresstextures", val);
1546  }
1547  config.setValue("textureSize", conf.getValue("textureSize",
1548  "1024,1024,1024,1024,1024,1024"));
1549  config.setValue("testInfo", conf.getValue("testInfo", ""));
1550  config.setValue("sound", conf.getValue("sound", 0));
1551  delete test;
1552  }
1553 }
1554 
1555 static CALLBACK void debugCallback(GLenum source,
1556  GLenum type,
1557  GLuint id,
1558  GLenum severity,
1559  GLsizei length,
1560  const GLchar *text,
1561  GLvoid *userParam A_UNUSED)
1562 {
1563  std::string message("OPENGL:");
1564  switch (source)
1565  {
1566  case GL_DEBUG_SOURCE_API:
1567  message.append(" API");
1568  break;
1570  message.append(" WM");
1571  break;
1573  message.append(" SHADERS");
1574  break;
1576  message.append(" THIRD_PARTY");
1577  break;
1579  message.append(" APP");
1580  break;
1581  case GL_DEBUG_SOURCE_OTHER:
1582  message.append(" OTHER");
1583  break;
1584  default:
1585  message.append(" ?").append(toString(source));
1586  break;
1587  }
1588  switch (type)
1589  {
1590  case GL_DEBUG_TYPE_ERROR:
1591  message.append(" ERROR");
1592  break;
1594  message.append(" DEPRECATED");
1595  break;
1597  message.append(" UNDEFINED");
1598  break;
1600  message.append(" PORTABILITY");
1601  break;
1603  message.append(" PERFORMANCE");
1604  break;
1605  case GL_DEBUG_TYPE_OTHER:
1606  message.append(" OTHER");
1607  break;
1608  case GL_DEBUG_TYPE_MARKER:
1609  message.append(" MARKER");
1610  break;
1612  message.append(" PUSH GROUP");
1613  break;
1615  message.append(" POP GROUP");
1616  break;
1617  default:
1618  message.append(" ?").append(toString(type));
1619  break;
1620  }
1621  message.append(" ").append(toString(id));
1622  switch (severity)
1623  {
1625  message.append(" N");
1626  break;
1628  message.append(" H");
1629  break;
1631  message.append(" M");
1632  break;
1633  case GL_DEBUG_SEVERITY_LOW:
1634  message.append(" L");
1635  break;
1636  default:
1637  message.append(" ?").append(toString(type));
1638  break;
1639  }
1640  char *const buf = new char[CAST_SIZE(length + 1)];
1641  memcpy(buf, text, length);
1642  buf[length] = 0;
1643  message.append(" ").append(buf);
1644  delete [] buf;
1645  logger->log(message);
1646 }
1647 
1649 {
1650  if (mSupportDebug && config.getIntValue("debugOpenGL"))
1651  {
1652  logger->log1("Enable OpenGL debug log");
1653  glEnable(GL_DEBUG_OUTPUT);
1654  glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
1655 
1656  mglDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE,
1657  0, nullptr, GL_TRUE);
1658  mglDebugMessageCallback(&debugCallback, this);
1659  }
1660 }
1661 #endif // USE_OPENGL
1662 
1664 {
1665  SDL_SysWMinfo info;
1666  SDL_VERSION(&info.version)
1668  {
1669 #ifdef WIN32
1670  HDC hdc = GetDC(info.window);
1671  if (hdc)
1672  {
1673 // SetProcessDPIAware();
1674  mMaxWidth = GetDeviceCaps(hdc, HORZRES);
1675  mMaxHeight = GetDeviceCaps(hdc, VERTRES);
1676  mWidthMM = GetDeviceCaps(hdc, HORZSIZE);
1677  mHeightMM = GetDeviceCaps(hdc, VERTSIZE);
1678  }
1679 #elif defined USE_X11
1680  Display *const display = info.info.x11.display;
1681  if (display)
1682  {
1683  Screen *const screen = XDefaultScreenOfDisplay(display);
1684  if (!screen)
1685  return;
1686 
1687  const int screenNum = XScreenNumberOfScreen(screen);
1688  mMaxWidth = DisplayWidth(display, screenNum);
1689  mMaxHeight = DisplayHeight(display, screenNum);
1690  mWidthMM = DisplayWidthMM(display, screenNum);
1691  mHeightMM = DisplayHeightMM(display, screenNum);
1692  }
1693 #endif // WIN32
1694  }
1695 #if defined ANDROID
1696 #ifdef USE_SDL2
1697  const int dpi = atoi(getenv("DISPLAY_DPI"));
1698  if (dpi <= 120)
1699  mDensity = 0;
1700  else if (dpi <= 160)
1701  mDensity = 1;
1702  else if (dpi <= 213)
1703  mDensity = 2;
1704  else if (dpi <= 240)
1705  mDensity = 3;
1706  else if (dpi <= 320)
1707  mDensity = 4;
1708 // else if (dpi <= 480)
1709  else
1710  mDensity = 5;
1711  mMaxWidth = atoi(getenv("DISPLAY_RESOLUTION_WIDTH"));
1712  mMaxHeight = atoi(getenv("DISPLAY_RESOLUTION_HEIGHT"));
1713  mWidthMM = atoi(getenv("DISPLAY_WIDTH_MM"));
1714  mHeightMM = atoi(getenv("DISPLAY_HEIGHT_MM"));
1715 #else // USE_SDL2
1716 
1717  SDL_ANDROID_GetMetrics(&mMaxWidth, &mMaxHeight,
1718  &mWidthMM, &mHeightMM, &mDensity);
1719 #endif // USE_SDL2
1720 #endif // defined ANDROID
1721 
1722  logger->log("screen size in pixels: %ux%u", mMaxWidth, mMaxHeight);
1723  logger->log("screen size in millimeters: %ux%u", mWidthMM, mHeightMM);
1724  logger->log("actual screen density: " + getDensityString());
1725  const int density = config.getIntValue("screenDensity");
1726  if (density > 0 && density <= densitySize)
1727  {
1728  mDensity = density - 1;
1729  logger->log("selected screen density: " + getDensityString());
1730  }
1731 }
1732 
1734 {
1735  if (mDensity >= 0 && mDensity < densitySize)
1736  return densityNames[mDensity];
1737  return "";
1738 }
#define CAST_S32
Definition: cast.h:30
#define CAST_U32
Definition: cast.h:31
#define CAST_SIZE
Definition: cast.h:34
int getValueInt(const std::string &key, const int deflt) const
std::string getValue(const std::string &key, const std::string &deflt) const
void deleteKey(const std::string &key)
bool getBoolValue(const std::string &key) const
std::string getStringValue(const std::string &key) const
float getFloatValue(const std::string &key) const
void setValue(const std::string &key, const std::string &value)
void setValueInt(const std::string &key, const int value)
int getIntValue(const std::string &key) const
bool checkPlatformVersion(const int major, const int minor) const
static GLenum getLastError()
std::set< std::string > mPlatformExtensions
std::string getDensityString() const
static void deleteFBO(FBOInfo *const fbo)
static void updateTextureFormat()
static void deleteRenderers()
bool checkGLVersion(const int major, const int minor) const
static std::string getGLString(const int num)
static void createFBO(const int width, const int height, FBOInfo *const fbo)
static void logString(const char *const format, const int num)
bool supportExtension(const std::string &ext) const
std::string mGlVersionString
std::string mGlVendor
void updateTextureCompressionFormat() const
static SDL_Surface * createWindow(const int w, const int h, const int bpp, const int flags)
static GLenum mLastError
static void logError()
void updatePlanformExtensions()
void updateDebugLog() const
void logVersion() const
static void setVideoMode()
bool checkGLesVersion(const int major, const int minor) const
static std::string errorToString(const GLenum error)
std::string mGlRenderer
std::set< std::string > mExtensions
TestMain * startDetection()
bool checkSLVersion(const int major, const int minor) const
std::string mGlShaderVersionString
virtual bool setVideoMode(const int w, const int h, const int scale, const int bpp, const bool fs, const bool hwaccel, const bool resize, const bool noFrame, const bool allowHighDPI)=0
virtual void createGLContext(const bool custom)
Definition: graphics.cpp:418
void setWindow(SDL_Surface *const window, const int width, const int height)
Definition: graphics.h:136
SDL_Surface * getWindow() const
Definition: graphics.h:144
static void setEnableAlpha(const bool n)
Definition: imagehelper.h:98
static void setOpenGlMode(const RenderType useOpenGL)
Definition: imagehelper.h:103
void log(const char *const log_text,...)
Definition: logger.cpp:269
void log1(const char *const log_text)
Definition: logger.cpp:238
void safeError(const std::string &error_text) __attribute__((noreturn))
Definition: logger.cpp:435
void error(const std::string &error_text) __attribute__((noreturn))
Definition: logger.cpp:472
static void setInternalTextureType(const int n)
static void setBlur(const bool n)
static void initTextureSampler(const GLint id)
static void setUseTextureSampler(const bool b)
static void setBlur(const bool n)
static void setUseTextureSampler(const bool b)
static void setInternalTextureType(const int n)
Options options
Definition: settings.h:130
unsigned int textureSize
Definition: settings.h:132
int exec(const bool testAudio=true)
Definition: testmain.cpp:78
Configuration & getConfig()
Definition: testmain.h:46
Configuration config
#define delete2(var)
Definition: delete2.h:25
Graphics * mainGraphics
Definition: graphics.cpp:109
const std::string densityNames[]
RenderType openGLMode
#define RENDER_SOFTWARE_INIT
#define RENDER_GLES2_OPENGL_INIT
#define RENDER_GLES_OPENGL_INIT
#define RENDER_SAFE_OPENGL_INIT
GraphicsManager graphicsManager
#define RENDER_SDL2_DEFAULT_INIT
#define RENDER_MODERN_OPENGL_INIT
#define RENDER_NORMAL_OPENGL_INIT
ScreenshotHelper * screenshortHelper
#define useCompression(name)
const int densitySize
static void debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *text, GLvoid *userParam)
ImageHelper * imageHelper
Definition: imagehelper.cpp:44
ImageHelper * surfaceImageHelper
Definition: imagehelper.cpp:45
#define PRAGMA48(str)
Definition: localconsts.h:199
#define A_UNUSED
Definition: localconsts.h:160
Logger * logger
Definition: logger.cpp:89
#define mglGetString(...)
Definition: mgl.hpp:99
#define mglGetIntegerv(...)
Definition: mgl.hpp:95
#define isGLNotNull(func)
Definition: mglcheck.h:28
#define isGLNull(func)
Definition: mglcheck.h:27
#define GL_DEBUG_TYPE_MARKER
Definition: mgldefines.h:60
#define GL_DEBUG_SEVERITY_LOW
Definition: mgldefines.h:64
#define GL_DEBUG_SOURCE_THIRD_PARTY
Definition: mgldefines.h:51
#define GL_DEBUG_TYPE_PORTABILITY
Definition: mgldefines.h:57
#define GL_DEBUG_TYPE_OTHER
Definition: mgldefines.h:59
#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR
Definition: mgldefines.h:55
#define GL_DEBUG_TYPE_PUSH_GROUP
Definition: mgldefines.h:68
#define GL_COLOR_ATTACHMENT0
Definition: mgldefines.h:30
#define GL_DEBUG_SOURCE_APPLICATION
Definition: mgldefines.h:52
#define GL_DEBUG_SOURCE_OTHER
Definition: mgldefines.h:53
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
Definition: mgldefines.h:37
#define GL_DEBUG_SEVERITY_MEDIUM
Definition: mgldefines.h:63
#define GL_DEBUG_SOURCE_SHADER_COMPILER
Definition: mgldefines.h:50
#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR
Definition: mgldefines.h:56
#define GL_RENDERBUFFER
Definition: mgldefines.h:32
#define GL_DEBUG_SEVERITY_NOTIFICATION
Definition: mgldefines.h:61
#define GL_DEBUG_TYPE_POP_GROUP
Definition: mgldefines.h:71
#define GL_DEBUG_SOURCE_WINDOW_SYSTEM
Definition: mgldefines.h:49
#define GL_MAX_ELEMENTS_INDICES
Definition: mgldefines.h:42
#define GL_FRAMEBUFFER
Definition: mgldefines.h:31
#define GL_DEBUG_SOURCE_API
Definition: mgldefines.h:48
#define GL_COMPRESSED_RGBA_ARB
Definition: mgldefines.h:36
#define GL_DEBUG_TYPE_ERROR
Definition: mgldefines.h:54
#define GL_MAX_ELEMENTS_VERTICES
Definition: mgldefines.h:41
#define GL_DEBUG_SEVERITY_HIGH
Definition: mgldefines.h:62
#define GL_DEBUG_OUTPUT_SYNCHRONOUS
Definition: mgldefines.h:46
#define GL_DEPTH_ATTACHMENT
Definition: mgldefines.h:29
#define GL_COMPRESSED_RGBA_FXT1_3DFX
Definition: mgldefines.h:38
#define GL_DEBUG_TYPE_PERFORMANCE
Definition: mgldefines.h:58
#define GL_DEBUG_OUTPUT
Definition: mgldefines.h:47
#define GL_NUM_EXTENSIONS
Definition: mgldefines.h:28
#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB
Definition: mgldefines.h:132
#define assignFunction2(func, name)
Definition: mglfunctions.h:77
#define assignFunctionEmu2(func, name)
Definition: mglfunctions.h:86
#define assignFunctionARB(func)
Definition: mglfunctions.h:73
#define assignFunctionEXT(func)
Definition: mglfunctions.h:75
#define assignFunction(func)
Definition: mglfunctions.h:46
#define emulateFunction(func)
Definition: mglfunctions.h:100
#define CALLBACK
Definition: mgltypes.h:239
bool error(InputEvent &event) __attribute__((noreturn))
Definition: actions.cpp:82
bool info(InputEvent &event)
Definition: commands.cpp:57
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
bool getWindowWMInfo(const SDL_Surface *const window, SDL_SysWMinfo *const info)
Definition: sdlhelper.cpp:112
bool getAllVideoModes(StringVect &modeList)
Definition: sdlhelper.cpp:44
RenderType intToRenderType(const int mode)
Definition: renderers.cpp:43
RenderType
Definition: rendertype.h:26
@ RENDER_SAFE_OPENGL
Definition: rendertype.h:29
@ RENDER_GLES2_OPENGL
Definition: rendertype.h:33
@ RENDER_GLES_OPENGL
Definition: rendertype.h:30
@ RENDER_MODERN_OPENGL
Definition: rendertype.h:32
@ RENDER_LAST
Definition: rendertype.h:35
@ RENDER_NORMAL_OPENGL
Definition: rendertype.h:28
@ RENDER_SDL2_DEFAULT
Definition: rendertype.h:31
@ RENDER_NULL
Definition: rendertype.h:34
@ RENDER_SOFTWARE
Definition: rendertype.h:27
#define SDL_Window
Definition: sdlshared.h:60
#define SurfaceImageHelper
Definition: sdlshared.h:62
Settings settings
Definition: settings.cpp:32
void cutFirst(std::string &str1, const std::string &str2)
void splitToIntVector(std::vector< int > &tokens, const std::string &text, const char separator)
std::string strprintf(const char *const format,...)
bool findCutFirst(std::string &str1, const std::string &str2)
size_t findI(std::string str, std::string subStr)
void splitToStringSet(std::set< std::string > &tokens, const std::string &text, const char separator)
std::vector< std::string > StringVect
Definition: stringvector.h:29
bool noOpenGL
Definition: options.h:97
int renderer
Definition: options.h:91