GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/graphicsmanager.cpp Lines: 22 715 3.1 %
Date: 2020-06-04 Branches: 17 1260 1.3 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2012-2019  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>
39
#include "render/opengl/naclglfunctions.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
51
#include "render/mobileopengl2graphics.h"
52
#include "render/mobileopenglgraphics.h"
53
#include "render/modernopenglgraphics.h"
54
#include "render/normalopenglgraphics.h"
55
#include "render/safeopenglgraphics.h"
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
65
#include "resources/openglimagehelper.h"
66
#include "resources/openglscreenshothelper.h"
67
#ifndef ANDROID
68
#include "resources/mobileopenglscreenshothelper.h"
69
#include "resources/safeopenglimagehelper.h"
70
#endif  // ANDROID
71
#include "render/opengl/mglfunctions.h"
72
#endif  // USE_OPENGL
73
74
#include "resources/sdlimagehelper.h"
75
#include "resources/sdlscreenshothelper.h"
76
77
#ifdef USE_SDL2
78
#include "render/sdl2softwaregraphics.h"
79
80
#include "resources/sdl2softwareimagehelper.h"
81
#include "resources/sdl2softwarescreenshothelper.h"
82
#include "resources/surfaceimagehelper.h"
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
114
1
GraphicsManager graphicsManager;
115
116
RenderType openGLMode = RENDER_SOFTWARE;
117
118
ScreenshotHelper *screenshortHelper = nullptr;
119
120
const int densitySize = 6;
121
122
3
const std::string densityNames[] =
123
{
124
    "low",
125
    "medium",
126
    "tv",
127
    "high",
128
    "xhigh",
129
    "xxhigh"
130



13
};
131
132
#ifdef USE_OPENGL
133
GLenum GraphicsManager::mLastError(GL_NO_ERROR);
134
#endif  // USE_OPENGL
135
136
1
GraphicsManager::GraphicsManager() :
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
7
    mUseAtlases(false)
164
{
165
1
}
166
167
8
GraphicsManager::~GraphicsManager()
168
{
169
#ifdef USE_OPENGL
170

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

3
}