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