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