GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/render/normalopenglgraphics.cpp Lines: 0 677 0.0 %
Date: 2020-06-04 Branches: 0 924 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2004-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2019  The ManaPlus Developers
6
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#ifdef USE_OPENGL
24
#if !defined(ANDROID) && !defined(__native_client__) && !defined(__SWITCH__)
25
26
#include "render/normalopenglgraphics.h"
27
28
#ifdef OPENGLERRORS
29
#include "graphicsmanager.h"
30
#endif  // OPENGLERRORS
31
32
#ifdef DEBUG_OPENGL
33
#include "render/opengl/mgl.h"
34
#endif  // DEBUG_OPENGL
35
36
#include "render/vertexes/imagecollection.h"
37
38
#include "resources/imagerect.h"
39
#include "resources/openglimagehelper.h"
40
41
#include "resources/image/image.h"
42
43
#include "utils/sdlcheckutils.h"
44
45
#include "debug.h"
46
47
#define vertFill2D(tVar, vVar, x1, y1, x2, y2, dstX, dstY, w, h) \
48
    tVar[vp + 0] = x1; \
49
    tVar[vp + 1] = y1; \
50
    tVar[vp + 2] = x2; \
51
    tVar[vp + 3] = y1; \
52
    tVar[vp + 4] = x2; \
53
    tVar[vp + 5] = y2; \
54
    tVar[vp + 6] = x1; \
55
    tVar[vp + 7] = y2; \
56
    vVar[vp + 0] = dstX; \
57
    vVar[vp + 1] = dstY; \
58
    vVar[vp + 2] = dstX + w; \
59
    vVar[vp + 3] = dstY; \
60
    vVar[vp + 4] = dstX + w; \
61
    vVar[vp + 5] = dstY + h; \
62
    vVar[vp + 6] = dstX; \
63
    vVar[vp + 7] = dstY + h
64
65
66
#define vertFillNv(tVar, vVar, srcX, srcY, dstX, dstY, w, h) \
67
    tVar[vp + 0] = srcX; \
68
    tVar[vp + 1] = srcY; \
69
    tVar[vp + 2] = srcX + w; \
70
    tVar[vp + 3] = srcY; \
71
    tVar[vp + 4] = srcX + w; \
72
    tVar[vp + 5] = srcY + h; \
73
    tVar[vp + 6] = srcX; \
74
    tVar[vp + 7] = srcY + h; \
75
    vVar[vp + 0] = dstX; \
76
    vVar[vp + 1] = dstY; \
77
    vVar[vp + 2] = dstX + w; \
78
    vVar[vp + 3] = dstY; \
79
    vVar[vp + 4] = dstX + w; \
80
    vVar[vp + 5] = dstY + h; \
81
    vVar[vp + 6] = dstX; \
82
    vVar[vp + 7] = dstY + h
83
84
namespace
85
{
86
    const void *vertPtr = nullptr;
87
}  // namespace
88
89
GLuint NormalOpenGLGraphics::mTextureBinded = 0;
90
#ifdef DEBUG_DRAW_CALLS
91
unsigned int NormalOpenGLGraphics::mDrawCalls = 0;
92
unsigned int NormalOpenGLGraphics::mLastDrawCalls = 0;
93
#endif  // DEBUG_DRAW_CALLS
94
#ifdef DEBUG_BIND_TEXTURE
95
unsigned int NormalOpenGLGraphics::mBinds = 0;
96
unsigned int NormalOpenGLGraphics::mLastBinds = 0;
97
#endif  // DEBUG_BIND_TEXTURE
98
99
NormalOpenGLGraphics::NormalOpenGLGraphics() :
100
    mFloatTexArray(nullptr),
101
    mIntTexArray(nullptr),
102
    mIntVertArray(nullptr),
103
    mFloatTexArrayCached(nullptr),
104
    mIntTexArrayCached(nullptr),
105
    mIntVertArrayCached(nullptr),
106
    mAlphaCached(1.0F),
107
    mVpCached(0),
108
    mTexture(false),
109
    mIsByteColor(false),
110
    mByteColor(),
111
    mImageCached(0),
112
    mFloatColor(1.0F),
113
    mMaxVertices(500),
114
    mColorAlpha(false),
115
#ifdef DEBUG_BIND_TEXTURE
116
    mOldTexture(),
117
    mOldTextureId(0),
118
#endif  // DEBUG_BIND_TEXTURE
119
    mFbo()
120
{
121
    mOpenGL = RENDER_NORMAL_OPENGL;
122
    mName = "normal OpenGL";
123
}
124
125
NormalOpenGLGraphics::~NormalOpenGLGraphics()
126
{
127
    deleteArraysInternal();
128
}
129
130
void NormalOpenGLGraphics::initArrays(const int vertCount) restrict2
131
{
132
    mMaxVertices = vertCount;
133
    if (mMaxVertices < 500)
134
        mMaxVertices = 500;
135
    else if (mMaxVertices > 1024)
136
        mMaxVertices = 1024;
137
138
    // need alocate small size, after if limit reached reallocate to double size
139
    vertexBufSize = mMaxVertices;
140
    const size_t sz = mMaxVertices * 4 + 30;
141
    if (mFloatTexArray == nullptr)
142
        mFloatTexArray = new GLfloat[sz];
143
    if (mIntTexArray == nullptr)
144
        mIntTexArray = new GLint[sz];
145
    if (mIntVertArray == nullptr)
146
        mIntVertArray = new GLint[sz];
147
    if (mFloatTexArrayCached == nullptr)
148
        mFloatTexArrayCached = new GLfloat[sz];
149
    if (mIntTexArrayCached == nullptr)
150
        mIntTexArrayCached = new GLint[sz];
151
    if (mIntVertArrayCached == nullptr)
152
        mIntVertArrayCached = new GLint[sz];
153
}
154
155
void NormalOpenGLGraphics::deleteArrays() restrict2
156
{
157
    deleteArraysInternal();
158
}
159
160
void NormalOpenGLGraphics::deleteArraysInternal() restrict2
161
{
162
    delete [] mFloatTexArray;
163
    mFloatTexArray = nullptr;
164
    delete [] mIntTexArray;
165
    mIntTexArray = nullptr;
166
    delete [] mIntVertArray;
167
    mIntVertArray = nullptr;
168
    delete [] mFloatTexArrayCached;
169
    mFloatTexArrayCached = nullptr;
170
    delete [] mIntTexArrayCached;
171
    mIntTexArrayCached = nullptr;
172
    delete [] mIntVertArrayCached;
173
    mIntVertArrayCached = nullptr;
174
}
175
176
bool NormalOpenGLGraphics::setVideoMode(const int w, const int h,
177
                                        const int scale,
178
                                        const int bpp,
179
                                        const bool fs,
180
                                        const bool hwaccel,
181
                                        const bool resize,
182
                                        const bool noFrame,
183
                                        const bool allowHighDPI) restrict2
184
{
185
    setMainFlags(w, h,
186
        scale,
187
        bpp,
188
        fs,
189
        hwaccel,
190
        resize,
191
        noFrame,
192
        allowHighDPI);
193
194
    return setOpenGLMode();
195
}
196
197
static inline void bindPointerIntFloat(const GLint *restrict const vert,
198
                                       const GLfloat *restrict const tex)
199
                                       A_INLINE;
200
201
static inline void bindPointerIntFloat(const GLint *restrict const vert,
202
                                       const GLfloat *restrict const tex)
203
{
204
    if (vertPtr != vert)
205
    {
206
        vertPtr = vert;
207
        glVertexPointer(2, GL_INT, 0, vert);
208
        glTexCoordPointer(2, GL_FLOAT, 0, tex);
209
    }
210
}
211
212
static inline void bindPointerInt(const GLint *restrict const vert,
213
                                  const GLint *restrict const tex) A_INLINE;
214
215
static inline void bindPointerInt(const GLint *restrict const vert,
216
                                  const GLint *restrict const tex)
217
{
218
    if (vertPtr != vert)
219
    {
220
        vertPtr = vert;
221
        glVertexPointer(2, GL_INT, 0, vert);
222
        glTexCoordPointer(2, GL_INT, 0, tex);
223
    }
224
}
225
226
static inline void drawQuad(const Image *restrict const image,
227
                            const int srcX, const int srcY,
228
                            const int dstX, const int dstY,
229
                            const int width, const int height)
230
                            A_NONNULL(1) A_INLINE;
231
232
static inline void drawQuad(const Image *restrict const image,
233
                            const int srcX, const int srcY,
234
                            const int dstX, const int dstY,
235
                            const int width, const int height)
236
{
237
    if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
238
    {
239
        const float tw = static_cast<float>(image->mTexWidth);
240
        const float th = static_cast<float>(image->mTexHeight);
241
        // Find OpenGL normalized texture coordinates.
242
        const float texX1 = static_cast<float>(srcX) / tw;
243
        const float texY1 = static_cast<float>(srcY) / th;
244
        const float texX2 = static_cast<float>(srcX + width) / tw;
245
        const float texY2 = static_cast<float>(srcY + height) / th;
246
247
        GLfloat tex[] =
248
        {
249
            texX1, texY1,
250
            texX2, texY1,
251
            texX2, texY2,
252
            texX1, texY2
253
        };
254
255
        GLint vert[] =
256
        {
257
            dstX, dstY,
258
            dstX + width, dstY,
259
            dstX + width, dstY + height,
260
            dstX, dstY + height
261
        };
262
263
        bindPointerIntFloat(&vert[0], &tex[0]);
264
#ifdef DEBUG_DRAW_CALLS
265
        NormalOpenGLGraphics::mDrawCalls ++;
266
#endif  // DEBUG_DRAW_CALLS
267
268
        glDrawArrays(GL_QUADS, 0, 4);
269
#ifdef OPENGLERRORS
270
        graphicsManager.logError();
271
#endif  // OPENGLERRORS
272
    }
273
    else
274
    {
275
        GLint tex[] =
276
        {
277
            srcX, srcY,
278
            srcX + width, srcY,
279
            srcX + width, srcY + height,
280
            srcX, srcY + height
281
        };
282
        GLint vert[] =
283
        {
284
            dstX, dstY,
285
            dstX + width, dstY,
286
            dstX + width, dstY + height,
287
            dstX, dstY + height
288
        };
289
290
        bindPointerInt(&vert[0], &tex[0]);
291
#ifdef DEBUG_DRAW_CALLS
292
        NormalOpenGLGraphics::mDrawCalls ++;
293
#endif  // DEBUG_DRAW_CALLS
294
295
        glDrawArrays(GL_QUADS, 0, 4);
296
#ifdef OPENGLERRORS
297
        graphicsManager.logError();
298
#endif  // OPENGLERRORS
299
    }
300
}
301
302
static inline void drawRescaledQuad(const Image *restrict const image,
303
                                    const int srcX, const int srcY,
304
                                    const int dstX, const int dstY,
305
                                    const int width, const int height,
306
                                    const int desiredWidth,
307
                                    const int desiredHeight)
308
                                    A_NONNULL(1) A_INLINE;
309
310
static inline void drawRescaledQuad(const Image *restrict const image,
311
                                    const int srcX, const int srcY,
312
                                    const int dstX, const int dstY,
313
                                    const int width, const int height,
314
                                    const int desiredWidth,
315
                                    const int desiredHeight)
316
{
317
    if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
318
    {
319
        const float tw = static_cast<float>(image->mTexWidth);
320
        const float th = static_cast<float>(image->mTexHeight);
321
        // Find OpenGL normalized texture coordinates.
322
        const float texX1 = static_cast<float>(srcX) / tw;
323
        const float texY1 = static_cast<float>(srcY) / th;
324
        const float texX2 = static_cast<float>(srcX + width) / tw;
325
        const float texY2 = static_cast<float>(srcY + height) / th;
326
327
        GLfloat tex[] =
328
        {
329
            texX1, texY1,
330
            texX2, texY1,
331
            texX2, texY2,
332
            texX1, texY2
333
        };
334
335
        GLint vert[] =
336
        {
337
            dstX, dstY,
338
            dstX + desiredWidth, dstY,
339
            dstX + desiredWidth, dstY + desiredHeight,
340
            dstX, dstY + desiredHeight
341
        };
342
343
        bindPointerIntFloat(&vert[0], &tex[0]);
344
#ifdef DEBUG_DRAW_CALLS
345
        NormalOpenGLGraphics::mDrawCalls ++;
346
#endif  // DEBUG_DRAW_CALLS
347
348
        glDrawArrays(GL_QUADS, 0, 4);
349
#ifdef OPENGLERRORS
350
        graphicsManager.logError();
351
#endif  // OPENGLERRORS
352
    }
353
    else
354
    {
355
        GLint tex[] =
356
        {
357
            srcX, srcY,
358
            srcX + width, srcY,
359
            srcX + width, srcY + height,
360
            srcX, srcY + height
361
        };
362
        GLint vert[] =
363
        {
364
            dstX, dstY,
365
            dstX + desiredWidth, dstY,
366
            dstX + desiredWidth, dstY + desiredHeight,
367
            dstX, dstY + desiredHeight
368
        };
369
370
        bindPointerInt(&vert[0], &tex[0]);
371
#ifdef DEBUG_DRAW_CALLS
372
        NormalOpenGLGraphics::mDrawCalls ++;
373
#endif  // DEBUG_DRAW_CALLS
374
375
        glDrawArrays(GL_QUADS, 0, 4);
376
#ifdef OPENGLERRORS
377
        graphicsManager.logError();
378
#endif  // OPENGLERRORS
379
    }
380
}
381
382
void NormalOpenGLGraphics::drawImage(const Image *restrict const image,
383
                                     int dstX, int dstY) restrict2
384
{
385
    drawImageInline(image, dstX, dstY);
386
}
387
388
void NormalOpenGLGraphics::drawImageInline(const Image *restrict const image,
389
                                           int dstX, int dstY) restrict2
390
{
391
    FUNC_BLOCK("Graphics::drawImage", 1)
392
    if (image == nullptr)
393
        return;
394
395
    setColorAlpha(image->mAlpha);
396
#ifdef DEBUG_BIND_TEXTURE
397
    debugBindTexture(image);
398
#endif  // DEBUG_BIND_TEXTURE
399
400
    bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage);
401
    enableTexturingAndBlending();
402
403
    const SDL_Rect &imageRect = image->mBounds;
404
    drawQuad(image, imageRect.x, imageRect.y,
405
        dstX, dstY, imageRect.w, imageRect.h);
406
}
407
408
void NormalOpenGLGraphics::copyImage(const Image *restrict const image,
409
                                     int dstX, int dstY) restrict2
410
{
411
    drawImageInline(image, dstX, dstY);
412
}
413
414
void NormalOpenGLGraphics::testDraw() restrict2
415
{
416
    if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
417
    {
418
        GLfloat tex[] =
419
        {
420
            0.0F, 0.781250F,
421
            0.0F, 0.781250F,
422
            0.0F, 0.585938F,
423
            0.0F, 0.585938F
424
        };
425
426
        GLint vert[] =
427
        {
428
            0, 0,
429
            800, 0,
430
            800, 600,
431
            0, 600
432
        };
433
434
        bindPointerIntFloat(&vert[0], &tex[0]);
435
#ifdef DEBUG_DRAW_CALLS
436
        NormalOpenGLGraphics::mDrawCalls ++;
437
#endif  // DEBUG_DRAW_CALLS
438
439
        glDrawArrays(GL_QUADS, 0, 4);
440
#ifdef OPENGLERRORS
441
        graphicsManager.logError();
442
#endif  // OPENGLERRORS
443
    }
444
    else
445
    {
446
        GLint tex[] =
447
        {
448
            0, 0,
449
            800, 0,
450
            800, 600,
451
            0, 600
452
        };
453
454
        GLint vert[] =
455
        {
456
            0, 0,
457
            800, 0,
458
            800, 600,
459
            0, 600
460
        };
461
462
        bindPointerInt(&vert[0], &tex[0]);
463
#ifdef DEBUG_DRAW_CALLS
464
        NormalOpenGLGraphics::mDrawCalls ++;
465
#endif  // DEBUG_DRAW_CALLS
466
467
        glDrawArrays(GL_QUADS, 0, 4);
468
#ifdef OPENGLERRORS
469
        graphicsManager.logError();
470
#endif  // OPENGLERRORS
471
    }
472
}
473
474
void NormalOpenGLGraphics::drawImageCached(const Image *restrict const image,
475
                                           int x, int y) restrict2
476
{
477
    if (image == nullptr)
478
        return;
479
480
    if (image->mGLImage != mImageCached)
481
    {
482
        completeCache();
483
        mImageCached = image->mGLImage;
484
        mAlphaCached = image->mAlpha;
485
    }
486
487
    const SDL_Rect &imageRect = image->mBounds;
488
    const int w = imageRect.w;
489
    const int h = imageRect.h;
490
491
    if (w == 0 || h == 0)
492
        return;
493
494
    const int srcX = imageRect.x;
495
    const int srcY = imageRect.y;
496
497
    const unsigned int vLimit = mMaxVertices * 4;
498
499
    unsigned int vp = mVpCached;
500
501
    // Draw a set of textured rectangles
502
    if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
503
    {
504
        const float tw = static_cast<float>(image->mTexWidth);
505
        const float th = static_cast<float>(image->mTexHeight);
506
507
        const float texX1 = static_cast<float>(srcX) / tw;
508
        const float texY1 = static_cast<float>(srcY) / th;
509
510
        const float texX2 = static_cast<float>(srcX + w) / tw;
511
        const float texY2 = static_cast<float>(srcY + h) / th;
512
513
        vertFill2D(mFloatTexArrayCached, mIntVertArrayCached,
514
            texX1, texY1, texX2, texY2,
515
            x, y, w, h);
516
517
        vp += 8;
518
        if (vp >= vLimit)
519
        {
520
            completeCache();
521
            vp = 0;
522
        }
523
        else
524
        {
525
            mVpCached = vp;
526
        }
527
    }
528
    else
529
    {
530
        vertFillNv(mIntTexArrayCached, mIntVertArrayCached,
531
            srcX, srcY, x, y, w, h);
532
533
        vp += 8;
534
        if (vp >= vLimit)
535
        {
536
            completeCache();
537
            vp = 0;
538
        }
539
        else
540
        {
541
            mVpCached = vp;
542
        }
543
    }
544
}
545
546
void NormalOpenGLGraphics::drawPatternCached(const Image *restrict const image,
547
                                             const int x,
548
                                             const int y,
549
                                             const int w,
550
                                             const int h) restrict2
551
{
552
    FUNC_BLOCK("Graphics::drawPatternCached", 1)
553
    if (image == nullptr)
554
        return;
555
556
    if (image->mGLImage != mImageCached)
557
    {
558
        completeCache();
559
        mImageCached = image->mGLImage;
560
    }
561
562
    const SDL_Rect &imageRect = image->mBounds;
563
    const int srcX = imageRect.x;
564
    const int srcY = imageRect.y;
565
    const int iw = imageRect.w;
566
    const int ih = imageRect.h;
567
568
    if (iw == 0 || ih == 0)
569
        return;
570
571
    unsigned int vp = mVpCached;
572
    const unsigned int vLimit = mMaxVertices * 4;
573
    // Draw a set of textured rectangles
574
    if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
575
    {
576
        const float tw = static_cast<float>(image->mTexWidth);
577
        const float th = static_cast<float>(image->mTexHeight);
578
579
        const float texX1 = static_cast<float>(srcX) / tw;
580
        const float texY1 = static_cast<float>(srcY) / th;
581
582
        for (int py = 0; py < h; py += ih)
583
        {
584
            const int height = (py + ih >= h) ? h - py : ih;
585
            const int dstY = y + py;
586
            const float texY2 = static_cast<float>(srcY + height) / th;
587
            for (int px = 0; px < w; px += iw)
588
            {
589
                const int width = (px + iw >= w) ? w - px : iw;
590
                const int dstX = x + px;
591
592
                const float texX2 = static_cast<float>(srcX + width) / tw;
593
594
                vertFill2D(mFloatTexArrayCached, mIntVertArrayCached,
595
                    texX1, texY1, texX2, texY2,
596
                    dstX, dstY, width, height);
597
598
                vp += 8;
599
                if (vp >= vLimit)
600
                {
601
                    completeCache();
602
                    vp = 0;
603
                }
604
            }
605
        }
606
    }
607
    else
608
    {
609
        for (int py = 0; py < h; py += ih)
610
        {
611
            const int height = (py + ih >= h) ? h - py : ih;
612
            const int dstY = y + py;
613
            for (int px = 0; px < w; px += iw)
614
            {
615
                const int width = (px + iw >= w) ? w - px : iw;
616
                const int dstX = x + px;
617
618
                vertFillNv(mIntTexArrayCached, mIntVertArrayCached,
619
                    srcX, srcY, dstX, dstY, width, height);
620
621
                vp += 8;
622
                if (vp >= vLimit)
623
                {
624
                    completeCache();
625
                    vp = 0;
626
                }
627
            }
628
        }
629
    }
630
    mVpCached = vp;
631
}
632
633
void NormalOpenGLGraphics::completeCache() restrict2
634
{
635
    if (mImageCached == 0U)
636
        return;
637
638
    setColorAlpha(mAlphaCached);
639
#ifdef DEBUG_BIND_TEXTURE
640
    debugBindTexture(image);
641
#endif  // DEBUG_BIND_TEXTURE
642
643
    bindTexture(OpenGLImageHelper::mTextureType, mImageCached);
644
    enableTexturingAndBlending();
645
646
    if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
647
        drawQuadArrayfiCached(mVpCached);
648
    else
649
        drawQuadArrayiiCached(mVpCached);
650
651
    mImageCached = 0;
652
    mVpCached = 0;
653
}
654
655
void NormalOpenGLGraphics::drawRescaledImage(const Image *restrict const image,
656
                                             int dstX, int dstY,
657
                                             const int desiredWidth,
658
                                             const int desiredHeight) restrict2
659
{
660
    FUNC_BLOCK("Graphics::drawRescaledImage", 1)
661
    if (image == nullptr)
662
        return;
663
664
    const SDL_Rect &imageRect = image->mBounds;
665
666
    // Just draw the image normally when no resizing is necessary,
667
    if (imageRect.w == desiredWidth && imageRect.h == desiredHeight)
668
    {
669
        drawImageInline(image, dstX, dstY);
670
        return;
671
    }
672
673
    setColorAlpha(image->mAlpha);
674
#ifdef DEBUG_BIND_TEXTURE
675
    debugBindTexture(image);
676
#endif  // DEBUG_BIND_TEXTURE
677
678
    bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage);
679
    enableTexturingAndBlending();
680
681
    // Draw a textured quad.
682
    drawRescaledQuad(image, imageRect.x, imageRect.y, dstX, dstY,
683
        imageRect.w, imageRect.h, desiredWidth, desiredHeight);
684
}
685
686
void NormalOpenGLGraphics::drawPattern(const Image *restrict const image,
687
                                       const int x, const int y,
688
                                       const int w, const int h) restrict2
689
{
690
    drawPatternInline(image, x, y, w, h);
691
}
692
693
void NormalOpenGLGraphics::drawPatternInline(const Image *restrict const image,
694
                                             const int x,
695
                                             const int y,
696
                                             const int w,
697
                                             const int h) restrict2
698
{
699
    FUNC_BLOCK("Graphics::drawPattern", 1)
700
    if (image == nullptr)
701
        return;
702
703
    const SDL_Rect &imageRect = image->mBounds;
704
    const int srcX = imageRect.x;
705
    const int srcY = imageRect.y;
706
    const int iw = imageRect.w;
707
    const int ih = imageRect.h;
708
709
    if (iw == 0 || ih == 0)
710
        return;
711
712
    setColorAlpha(image->mAlpha);
713
714
#ifdef DEBUG_BIND_TEXTURE
715
    debugBindTexture(image);
716
#endif  // DEBUG_BIND_TEXTURE
717
718
    bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage);
719
720
    enableTexturingAndBlending();
721
722
    unsigned int vp = 0;
723
    const unsigned int vLimit = mMaxVertices * 4;
724
    // Draw a set of textured rectangles
725
    if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
726
    {
727
        const float tw = static_cast<float>(image->mTexWidth);
728
        const float th = static_cast<float>(image->mTexHeight);
729
730
        const float texX1 = static_cast<float>(srcX) / tw;
731
        const float texY1 = static_cast<float>(srcY) / th;
732
733
        for (int py = 0; py < h; py += ih)
734
        {
735
            const int height = (py + ih >= h) ? h - py : ih;
736
            const int dstY = y + py;
737
            const float texY2 = static_cast<float>(srcY + height) / th;
738
            for (int px = 0; px < w; px += iw)
739
            {
740
                const int width = (px + iw >= w) ? w - px : iw;
741
                const int dstX = x + px;
742
                const float texX2 = static_cast<float>(srcX + width) / tw;
743
744
                vertFill2D(mFloatTexArray, mIntVertArray,
745
                    texX1, texY1, texX2, texY2,
746
                    dstX, dstY, width, height);
747
748
                vp += 8;
749
                if (vp >= vLimit)
750
                {
751
                    drawQuadArrayfi(vp);
752
                    vp = 0;
753
                }
754
            }
755
        }
756
        if (vp > 0)
757
            drawQuadArrayfi(vp);
758
    }
759
    else
760
    {
761
        for (int py = 0; py < h; py += ih)
762
        {
763
            const int height = (py + ih >= h) ? h - py : ih;
764
            const int dstY = y + py;
765
            for (int px = 0; px < w; px += iw)
766
            {
767
                const int width = (px + iw >= w) ? w - px : iw;
768
                const int dstX = x + px;
769
770
                vertFillNv(mIntTexArray, mIntVertArray,
771
                    srcX, srcY, dstX, dstY, width, height);
772
773
                vp += 8;
774
                if (vp >= vLimit)
775
                {
776
                    drawQuadArrayii(vp);
777
                    vp = 0;
778
                }
779
            }
780
        }
781
        if (vp > 0)
782
            drawQuadArrayii(vp);
783
    }
784
}
785
786
void NormalOpenGLGraphics::drawRescaledPattern(const Image *
787
                                               restrict const image,
788
                                               const int x, const int y,
789
                                               const int w, const int h,
790
                                               const int scaledWidth,
791
                                               const int scaledHeight)
792
                                               restrict2
793
{
794
    if (image == nullptr)
795
        return;
796
797
    if (scaledWidth == 0 || scaledHeight == 0)
798
        return;
799
800
    const SDL_Rect &imageRect = image->mBounds;
801
    const int iw = imageRect.w;
802
    const int ih = imageRect.h;
803
    if (iw == 0 || ih == 0)
804
        return;
805
806
    const int srcX = imageRect.x;
807
    const int srcY = imageRect.y;
808
809
    setColorAlpha(image->mAlpha);
810
811
#ifdef DEBUG_BIND_TEXTURE
812
    debugBindTexture(image);
813
#endif  // DEBUG_BIND_TEXTURE
814
815
    bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage);
816
817
    enableTexturingAndBlending();
818
819
    unsigned int vp = 0;
820
    const unsigned int vLimit = mMaxVertices * 4;
821
822
    // Draw a set of textured rectangles
823
    if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
824
    {
825
        const float tw = static_cast<float>(image->mTexWidth);
826
        const float th = static_cast<float>(image->mTexHeight);
827
828
        const float texX1 = static_cast<float>(srcX) / tw;
829
        const float texY1 = static_cast<float>(srcY) / th;
830
831
        const float tFractionW = iw / tw;
832
        const float tFractionH = ih / th;
833
834
        for (int py = 0; py < h; py += scaledHeight)
835
        {
836
            const int height = (py + scaledHeight >= h)
837
                ? h - py : scaledHeight;
838
            const int dstY = y + py;
839
            const float visibleFractionH = static_cast<float>(height)
840
                / scaledHeight;
841
            const float texY2 = texY1 + tFractionH * visibleFractionH;
842
            for (int px = 0; px < w; px += scaledWidth)
843
            {
844
                const int width = (px + scaledWidth >= w)
845
                    ? w - px : scaledWidth;
846
                const int dstX = x + px;
847
                const float visibleFractionW = static_cast<float>(width)
848
                    / scaledWidth;
849
                const float texX2 = texX1 + tFractionW * visibleFractionW;
850
851
                vertFill2D(mFloatTexArray, mIntVertArray,
852
                    texX1, texY1, texX2, texY2,
853
                    dstX, dstY, width, height);
854
855
                vp += 8;
856
                if (vp >= vLimit)
857
                {
858
                    drawQuadArrayfi(vp);
859
                    vp = 0;
860
                }
861
            }
862
        }
863
        if (vp > 0)
864
            drawQuadArrayfi(vp);
865
    }
866
    else
867
    {
868
        const float scaleFactorW = static_cast<float>(scaledWidth) / iw;
869
        const float scaleFactorH = static_cast<float>(scaledHeight) / ih;
870
871
        for (int py = 0; py < h; py += scaledHeight)
872
        {
873
            const int height = (py + scaledHeight >= h)
874
                ? h - py : scaledHeight;
875
            const int dstY = y + py;
876
            const int scaledY = srcY + height / scaleFactorH;
877
            for (int px = 0; px < w; px += scaledWidth)
878
            {
879
                const int width = (px + scaledWidth >= w)
880
                    ? w - px : scaledWidth;
881
                const int dstX = x + px;
882
                const int scaledX = srcX + width / scaleFactorW;
883
884
                mIntTexArray[vp + 0] = srcX;
885
                mIntTexArray[vp + 1] = srcY;
886
887
                mIntTexArray[vp + 2] = scaledX;
888
                mIntTexArray[vp + 3] = srcY;
889
890
                mIntTexArray[vp + 4] = scaledX;
891
                mIntTexArray[vp + 5] = scaledY;
892
893
                mIntTexArray[vp + 6] = srcX;
894
                mIntTexArray[vp + 7] = scaledY;
895
896
                mIntVertArray[vp + 0] = dstX;
897
                mIntVertArray[vp + 1] = dstY;
898
899
                mIntVertArray[vp + 2] = dstX + width;
900
                mIntVertArray[vp + 3] = dstY;
901
902
                mIntVertArray[vp + 4] = dstX + width;
903
                mIntVertArray[vp + 5] = dstY + height;
904
905
                mIntVertArray[vp + 6] = dstX;
906
                mIntVertArray[vp + 7] = dstY + height;
907
908
                vp += 8;
909
                if (vp >= vLimit)
910
                {
911
                    drawQuadArrayii(vp);
912
                    vp = 0;
913
                }
914
            }
915
        }
916
        if (vp > 0)
917
            drawQuadArrayii(vp);
918
    }
919
}
920
921
inline void NormalOpenGLGraphics::drawVertexes(const
922
                                               OpenGLGraphicsVertexes
923
                                               &restrict ogl) restrict2
924
{
925
    const STD_VECTOR<GLint*> &intVertPool = ogl.mIntVertPool;
926
    STD_VECTOR<GLint*>::const_iterator iv;
927
    const STD_VECTOR<GLint*>::const_iterator iv_end = intVertPool.end();
928
    const STD_VECTOR<int> &vp = ogl.mVp;
929
    STD_VECTOR<int>::const_iterator ivp;
930
    const STD_VECTOR<int>::const_iterator ivp_end = vp.end();
931
932
    // Draw a set of textured rectangles
933
    if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
934
    {
935
        const STD_VECTOR<GLfloat*> &floatTexPool = ogl.mFloatTexPool;
936
        STD_VECTOR<GLfloat*>::const_iterator ft;
937
        const STD_VECTOR<GLfloat*>::const_iterator
938
            ft_end = floatTexPool.end();
939
940
        for (iv = intVertPool.begin(), ft = floatTexPool.begin(),
941
             ivp = vp.begin();
942
             iv != iv_end && ft != ft_end && ivp != ivp_end;
943
             ++ iv, ++ ft, ++ ivp)
944
        {
945
            drawQuadArrayfi(*iv, *ft, *ivp);
946
        }
947
    }
948
    else
949
    {
950
        const STD_VECTOR<GLint*> &intTexPool = ogl.mIntTexPool;
951
        STD_VECTOR<GLint*>::const_iterator it;
952
        const STD_VECTOR<GLint*>::const_iterator it_end = intTexPool.end();
953
954
        for (iv = intVertPool.begin(), it = intTexPool.begin(),
955
             ivp = vp.begin();
956
             iv != iv_end && it != it_end && ivp != ivp_end;
957
             ++ iv, ++ it, ++ ivp)
958
        {
959
            drawQuadArrayii(*iv, *it, *ivp);
960
        }
961
    }
962
}
963
964
void NormalOpenGLGraphics::calcPattern(ImageVertexes *restrict const vert,
965
                                       const Image *restrict const image,
966
                                       const int x,
967
                                       const int y,
968
                                       const int w,
969
                                       const int h) const restrict2
970
{
971
    calcPatternInline(vert, image, x, y, w, h);
972
}
973
974
void NormalOpenGLGraphics::calcPatternInline(ImageVertexes *
975
                                             restrict const vert,
976
                                             const Image *restrict const image,
977
                                             const int x,
978
                                             const int y,
979
                                             const int w,
980
                                             const int h) const restrict2
981
{
982
    if (image == nullptr || vert == nullptr)
983
        return;
984
985
    const SDL_Rect &imageRect = image->mBounds;
986
    const int iw = imageRect.w;
987
    const int ih = imageRect.h;
988
989
    if (iw == 0 || ih == 0)
990
        return;
991
992
    const int srcX = imageRect.x;
993
    const int srcY = imageRect.y;
994
995
    const unsigned int vLimit = mMaxVertices * 4;
996
997
    OpenGLGraphicsVertexes &ogl = vert->ogl;
998
    unsigned int vp = ogl.continueVp();
999
1000
    // Draw a set of textured rectangles
1001
    if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
1002
    {
1003
        const float tw = static_cast<float>(image->mTexWidth);
1004
        const float th = static_cast<float>(image->mTexHeight);
1005
        const float texX1 = static_cast<float>(srcX) / tw;
1006
        const float texY1 = static_cast<float>(srcY) / th;
1007
1008
        GLfloat *floatTexArray = ogl.continueFloatTexArray();
1009
        GLint *intVertArray = ogl.continueIntVertArray();
1010
1011
        for (int py = 0; py < h; py += ih)
1012
        {
1013
            const int height = (py + ih >= h) ? h - py : ih;
1014
            const int dstY = y + py;
1015
            const float texY2 = static_cast<float>(srcY + height) / th;
1016
            for (int px = 0; px < w; px += iw)
1017
            {
1018
                const int width = (px + iw >= w) ? w - px : iw;
1019
                const int dstX = x + px;
1020
                const float texX2 = static_cast<float>(srcX + width) / tw;
1021
1022
                vertFill2D(floatTexArray, intVertArray,
1023
                    texX1, texY1, texX2, texY2,
1024
                    dstX, dstY, width, height);
1025
1026
                vp += 8;
1027
                if (vp >= vLimit)
1028
                {
1029
                    floatTexArray = ogl.switchFloatTexArray();
1030
                    intVertArray = ogl.switchIntVertArray();
1031
                    ogl.switchVp(vp);
1032
                    vp = 0;
1033
                }
1034
            }
1035
        }
1036
    }
1037
    else
1038
    {
1039
        GLint *intTexArray = ogl.continueIntTexArray();
1040
        GLint *intVertArray = ogl.continueIntVertArray();
1041
1042
        for (int py = 0; py < h; py += ih)
1043
        {
1044
            const int height = (py + ih >= h) ? h - py : ih;
1045
            const int dstY = y + py;
1046
            for (int px = 0; px < w; px += iw)
1047
            {
1048
                const int width = (px + iw >= w) ? w - px : iw;
1049
                const int dstX = x + px;
1050
1051
                vertFillNv(intTexArray, intVertArray,
1052
                    srcX, srcY, dstX, dstY, width, height);
1053
1054
                vp += 8;
1055
                if (vp >= vLimit)
1056
                {
1057
                    intTexArray = ogl.switchIntTexArray();
1058
                    intVertArray = ogl.switchIntVertArray();
1059
                    ogl.switchVp(vp);
1060
                    vp = 0;
1061
                }
1062
            }
1063
        }
1064
    }
1065
    ogl.switchVp(vp);
1066
}
1067
1068
void NormalOpenGLGraphics::calcTileCollection(ImageCollection *
1069
                                              restrict const vertCol,
1070
                                              const Image *
1071
                                              restrict const image,
1072
                                              int x, int y) restrict2
1073
{
1074
    if (vertCol == nullptr || image == nullptr)
1075
        return;
1076
    if (vertCol->currentGLImage != image->mGLImage)
1077
    {
1078
        ImageVertexes *const vert = new ImageVertexes;
1079
        vertCol->currentGLImage = image->mGLImage;
1080
        vertCol->currentVert = vert;
1081
        vert->image = image;
1082
        vertCol->draws.push_back(vert);
1083
        calcTileVertexesInline(vert, image, x, y);
1084
    }
1085
    else
1086
    {
1087
        calcTileVertexesInline(vertCol->currentVert, image, x, y);
1088
    }
1089
}
1090
1091
void NormalOpenGLGraphics::drawTileCollection(const ImageCollection
1092
                                              *restrict const vertCol)
1093
                                              restrict2
1094
{
1095
    const ImageVertexesVector &draws = vertCol->draws;
1096
    const ImageCollectionCIter it_end = draws.end();
1097
    for (ImageCollectionCIter it = draws.begin(); it != it_end; ++ it)
1098
    {
1099
        const ImageVertexes *const vert = *it;
1100
        const Image *const image = vert->image;
1101
1102
        setColorAlpha(image->mAlpha);
1103
#ifdef DEBUG_BIND_TEXTURE
1104
        debugBindTexture(image);
1105
#endif  // DEBUG_BIND_TEXTURE
1106
1107
        bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage);
1108
        enableTexturingAndBlending();
1109
        drawVertexes(vert->ogl);
1110
    }
1111
}
1112
1113
void NormalOpenGLGraphics::calcPattern(ImageCollection *restrict const vertCol,
1114
                                       const Image *restrict const image,
1115
                                       const int x,
1116
                                       const int y,
1117
                                       const int w,
1118
                                       const int h) const restrict2
1119
{
1120
    if (vertCol == nullptr || image == nullptr)
1121
        return;
1122
    ImageVertexes *vert = nullptr;
1123
    if (vertCol->currentGLImage != image->mGLImage)
1124
    {
1125
        vert = new ImageVertexes;
1126
        vertCol->currentGLImage = image->mGLImage;
1127
        vertCol->currentVert = vert;
1128
        vert->image = image;
1129
        vertCol->draws.push_back(vert);
1130
    }
1131
    else
1132
    {
1133
        vert = vertCol->currentVert;
1134
    }
1135
1136
    calcPatternInline(vert, image, x, y, w, h);
1137
}
1138
1139
void NormalOpenGLGraphics::calcTileVertexes(ImageVertexes *restrict const vert,
1140
                                            const Image *restrict const image,
1141
                                            int dstX, int dstY) const restrict2
1142
{
1143
    calcTileVertexesInline(vert, image, dstX, dstY);
1144
}
1145
1146
void NormalOpenGLGraphics::calcTileVertexesInline(ImageVertexes *
1147
                                                  restrict const vert,
1148
                                                  const Image *
1149
                                                  restrict const image,
1150
                                                  int dstX,
1151
                                                  int dstY) const restrict2
1152
{
1153
    const SDL_Rect &imageRect = image->mBounds;
1154
    const int w = imageRect.w;
1155
    const int h = imageRect.h;
1156
1157
    if (w == 0 || h == 0)
1158
        return;
1159
1160
    const int srcX = imageRect.x;
1161
    const int srcY = imageRect.y;
1162
1163
    const unsigned int vLimit = mMaxVertices * 4;
1164
1165
    OpenGLGraphicsVertexes &ogl = vert->ogl;
1166
1167
//    STD_VECTOR<int> *vps = ogl.getVp();
1168
    unsigned int vp = ogl.continueVp();
1169
1170
    // Draw a set of textured rectangles
1171
    if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
1172
    {
1173
        const float tw = static_cast<float>(image->mTexWidth);
1174
        const float th = static_cast<float>(image->mTexHeight);
1175
1176
        const float texX1 = static_cast<float>(srcX) / tw;
1177
        const float texY1 = static_cast<float>(srcY) / th;
1178
1179
        const float texX2 = static_cast<float>(srcX + w) / tw;
1180
        const float texY2 = static_cast<float>(srcY + h) / th;
1181
1182
        GLfloat *const floatTexArray = ogl.continueFloatTexArray();
1183
        GLint *const intVertArray = ogl.continueIntVertArray();
1184
1185
        vertFill2D(floatTexArray, intVertArray,
1186
            texX1, texY1, texX2, texY2,
1187
            dstX, dstY, w, h);
1188
1189
        vp += 8;
1190
        if (vp >= vLimit)
1191
        {
1192
            ogl.switchFloatTexArray();
1193
            ogl.switchIntVertArray();
1194
            ogl.switchVp(vp);
1195
            vp = 0;
1196
        }
1197
    }
1198
    else
1199
    {
1200
        GLint *const intTexArray = ogl.continueIntTexArray();
1201
        GLint *const intVertArray = ogl.continueIntVertArray();
1202
1203
        vertFillNv(intTexArray, intVertArray,
1204
            srcX, srcY, dstX, dstY, w, h);
1205
1206
        vp += 8;
1207
        if (vp >= vLimit)
1208
        {
1209
            ogl.switchIntTexArray();
1210
            ogl.switchIntVertArray();
1211
            ogl.switchVp(vp);
1212
            vp = 0;
1213
        }
1214
    }
1215
    ogl.switchVp(vp);
1216
}
1217
1218
void NormalOpenGLGraphics::drawTileVertexes(const ImageVertexes *
1219
                                            restrict const vert) restrict2
1220
{
1221
    if (vert == nullptr)
1222
        return;
1223
    const Image *const image = vert->image;
1224
1225
    setColorAlpha(image->mAlpha);
1226
#ifdef DEBUG_BIND_TEXTURE
1227
    debugBindTexture(image);
1228
#endif  // DEBUG_BIND_TEXTURE
1229
1230
    bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage);
1231
    enableTexturingAndBlending();
1232
    drawVertexes(vert->ogl);
1233
}
1234
1235
void NormalOpenGLGraphics::calcWindow(ImageCollection *restrict const vertCol,
1236
                                      const int x, const int y,
1237
                                      const int w, const int h,
1238
                                      const ImageRect &restrict imgRect)
1239
                                      restrict2
1240
{
1241
    ImageVertexes *vert = nullptr;
1242
    Image *const image = imgRect.grid[4];
1243
    if (image == nullptr)
1244
        return;
1245
    if (vertCol->currentGLImage != image->mGLImage)
1246
    {
1247
        vert = new ImageVertexes;
1248
        vertCol->currentGLImage = image->mGLImage;
1249
        vertCol->currentVert = vert;
1250
        vert->image = image;
1251
        vertCol->draws.push_back(vert);
1252
    }
1253
    else
1254
    {
1255
        vert = vertCol->currentVert;
1256
    }
1257
    calcImageRect(vert, x, y, w, h, imgRect);
1258
}
1259
1260
void NormalOpenGLGraphics::updateScreen() restrict2
1261
{
1262
    BLOCK_START("Graphics::updateScreen")
1263
//    glFlush();
1264
//    glFinish();
1265
#ifdef DEBUG_DRAW_CALLS
1266
    mLastDrawCalls = mDrawCalls;
1267
    mDrawCalls = 0;
1268
#endif  // DEBUG_DRAW_CALLS
1269
#ifdef DEBUG_BIND_TEXTURE
1270
    mLastBinds = mBinds;
1271
    mBinds = 0;
1272
#endif  // DEBUG_BIND_TEXTURE
1273
#ifdef USE_SDL2
1274
    SDL_GL_SwapWindow(mWindow);
1275
#else  // USE_SDL2
1276
    SDL_GL_SwapBuffers();
1277
#endif  // USE_SDL2
1278
#ifdef DEBUG_OPENGL
1279
    if (isGLNotNull(mglFrameTerminator))
1280
        mglFrameTerminator();
1281
#endif  // DEBUG_OPENGL
1282
1283
// may be need clear?
1284
//  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1285
    BLOCK_END("Graphics::updateScreen")
1286
}
1287
1288
void NormalOpenGLGraphics::beginDraw() restrict2
1289
{
1290
    glMatrixMode(GL_TEXTURE);
1291
    glLoadIdentity();
1292
1293
    glMatrixMode(GL_PROJECTION);
1294
    glLoadIdentity();
1295
1296
    const int w = mRect.w;
1297
    const int h = mRect.h;
1298
1299
#ifdef ANDROID
1300
    glOrthof(0.0, static_cast<float>(w),
1301
        static_cast<float>(h),
1302
        0.0, -1.0, 1.0);
1303
#else  // ANDROID
1304
1305
    glOrtho(0.0, static_cast<double>(w),
1306
        static_cast<double>(h),
1307
        0.0, -1.0, 1.0);
1308
#endif  // ANDROID
1309
1310
    glMatrixMode(GL_MODELVIEW);
1311
    glLoadIdentity();
1312
1313
    setOpenGLFlags();
1314
    glDisable(GL_LIGHTING);
1315
    glDisable(GL_FOG);
1316
    glDisable(GL_COLOR_MATERIAL);
1317
1318
    glEnableClientState(GL_VERTEX_ARRAY);
1319
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1320
1321
    glShadeModel(GL_FLAT);
1322
    glDepthMask(GL_FALSE);
1323
1324
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1325
#ifndef ANDROID
1326
    glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
1327
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1328
    glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
1329
    glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
1330
#endif  // ANDROID
1331
1332
    pushClipArea(Rect(0, 0, w, h));
1333
}
1334
1335
void NormalOpenGLGraphics::endDraw() restrict2
1336
{
1337
    popClipArea();
1338
}
1339
1340
void NormalOpenGLGraphics::pushClipArea(const Rect &restrict area) restrict2
1341
{
1342
    int transX = 0;
1343
    int transY = 0;
1344
1345
    if (!mClipStack.empty())
1346
    {
1347
        const ClipRect &clipArea = mClipStack.top();
1348
        transX = -clipArea.xOffset;
1349
        transY = -clipArea.yOffset;
1350
    }
1351
1352
    Graphics::pushClipArea(area);
1353
1354
    const ClipRect &clipArea = mClipStack.top();
1355
    transX += clipArea.xOffset;
1356
    transY += clipArea.yOffset;
1357
1358
    if (transX != 0 || transY != 0)
1359
    {
1360
        glTranslatef(static_cast<GLfloat>(transX),
1361
                     static_cast<GLfloat>(transY), 0);
1362
    }
1363
    glScissor(clipArea.x * mScale,
1364
        (mRect.h - clipArea.y - clipArea.height) * mScale,
1365
        clipArea.width * mScale,
1366
        clipArea.height * mScale);
1367
}
1368
1369
void NormalOpenGLGraphics::popClipArea() restrict2
1370
{
1371
    if (mClipStack.empty())
1372
        return;
1373
1374
    const ClipRect &clipArea1 = mClipStack.top();
1375
    int transX = -clipArea1.xOffset;
1376
    int transY = -clipArea1.yOffset;
1377
1378
    Graphics::popClipArea();
1379
1380
    if (mClipStack.empty())
1381
        return;
1382
1383
    const ClipRect &clipArea = mClipStack.top();
1384
    transX += clipArea.xOffset;
1385
    transY += clipArea.yOffset;
1386
    if (transX != 0 || transY != 0)
1387
    {
1388
        glTranslatef(static_cast<GLfloat>(transX),
1389
                     static_cast<GLfloat>(transY), 0);
1390
    }
1391
    glScissor(clipArea.x * mScale,
1392
        (mRect.h - clipArea.y - clipArea.height) * mScale,
1393
        clipArea.width * mScale,
1394
        clipArea.height * mScale);
1395
}
1396
1397
void NormalOpenGLGraphics::drawPoint(int x, int y) restrict2
1398
{
1399
    disableTexturingAndBlending();
1400
    restoreColor();
1401
1402
#ifdef ANDROID
1403
    // TODO need fix
1404
#else  // ANDROID
1405
1406
    glBegin(GL_POINTS);
1407
    glVertex2i(x, y);
1408
    glEnd();
1409
#endif  // ANDROID
1410
}
1411
1412
void NormalOpenGLGraphics::drawLine(int x1, int y1,
1413
                                    int x2, int y2) restrict2
1414
{
1415
    disableTexturingAndBlending();
1416
    restoreColor();
1417
1418
    mFloatTexArray[0] = static_cast<float>(x1) + 0.5F;
1419
    mFloatTexArray[1] = static_cast<float>(y1) + 0.5F;
1420
    mFloatTexArray[2] = static_cast<float>(x2) + 0.5F;
1421
    mFloatTexArray[3] = static_cast<float>(y2) + 0.5F;
1422
1423
    drawLineArrayf(4);
1424
}
1425
1426
void NormalOpenGLGraphics::drawRectangle(const Rect &restrict rect) restrict2
1427
{
1428
    drawRectangle(rect, false);
1429
}
1430
1431
void NormalOpenGLGraphics::fillRectangle(const Rect &restrict rect) restrict2
1432
{
1433
    drawRectangle(rect, true);
1434
}
1435
1436
void NormalOpenGLGraphics::enableTexturingAndBlending() restrict2
1437
{
1438
    if (!mTexture)
1439
    {
1440
        glEnable(OpenGLImageHelper::mTextureType);
1441
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1442
        mTexture = true;
1443
    }
1444
1445
    if (!mAlpha)
1446
    {
1447
        glEnable(GL_BLEND);
1448
        mAlpha = true;
1449
    }
1450
}
1451
1452
void NormalOpenGLGraphics::disableTexturingAndBlending() restrict2
1453
{
1454
    mTextureBinded = 0;
1455
    if (mAlpha && !mColorAlpha)
1456
    {
1457
        glDisable(GL_BLEND);
1458
        mAlpha = false;
1459
    }
1460
    else if (!mAlpha && mColorAlpha)
1461
    {
1462
        glEnable(GL_BLEND);
1463
        mAlpha = true;
1464
    }
1465
1466
    if (mTexture)
1467
    {
1468
        glDisable(OpenGLImageHelper::mTextureType);
1469
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1470
        mTexture = false;
1471
    }
1472
}
1473
1474
void NormalOpenGLGraphics::drawRectangle(const Rect &restrict rect,
1475
                                         const bool filled) restrict2
1476
{
1477
    BLOCK_START("Graphics::drawRectangle")
1478
    const float offset = filled ? 0 : 0.5F;
1479
    const float x = static_cast<float>(rect.x);
1480
    const float y = static_cast<float>(rect.y);
1481
    const float width = static_cast<float>(rect.width);
1482
    const float height = static_cast<float>(rect.height);
1483
1484
    disableTexturingAndBlending();
1485
    restoreColor();
1486
1487
    GLfloat vert[] =
1488
    {
1489
        x + offset, y + offset,
1490
        x + width - offset, y + offset,
1491
        x + width - offset, y + height - offset,
1492
        x + offset, y + height - offset
1493
    };
1494
1495
    glVertexPointer(2, GL_FLOAT, 0, &vert);
1496
    vertPtr = nullptr;
1497
#ifdef DEBUG_DRAW_CALLS
1498
    mDrawCalls ++;
1499
#endif  // DEBUG_DRAW_CALLS
1500
1501
    glDrawArrays(filled ? GL_QUADS : GL_LINE_LOOP, 0, 4);
1502
#ifdef OPENGLERRORS
1503
    graphicsManager.logError();
1504
#endif  // OPENGLERRORS
1505
    BLOCK_END("Graphics::drawRectangle")
1506
}
1507
1508
void NormalOpenGLGraphics::drawNet(const int x1, const int y1,
1509
                                   const int x2, const int y2,
1510
                                   const int width, const int height) restrict2
1511
{
1512
    unsigned int vp = 0;
1513
    const unsigned int vLimit = mMaxVertices * 4;
1514
1515
    disableTexturingAndBlending();
1516
    restoreColor();
1517
1518
    const float xf1 = static_cast<float>(x1);
1519
    const float xf2 = static_cast<float>(x2);
1520
    const float yf1 = static_cast<float>(y1);
1521
    const float yf2 = static_cast<float>(y2);
1522
1523
    for (int y = y1; y < y2; y += height)
1524
    {
1525
        mFloatTexArray[vp + 0] = xf1;
1526
        mFloatTexArray[vp + 1] = static_cast<float>(y);
1527
1528
        mFloatTexArray[vp + 2] = xf2;
1529
        mFloatTexArray[vp + 3] = static_cast<float>(y);
1530
1531
        vp += 4;
1532
        if (vp >= vLimit)
1533
        {
1534
            drawLineArrayf(vp);
1535
            vp = 0;
1536
        }
1537
    }
1538
1539
    for (int x = x1; x < x2; x += width)
1540
    {
1541
        mFloatTexArray[vp + 0] = static_cast<float>(x);
1542
        mFloatTexArray[vp + 1] = yf1;
1543
1544
        mFloatTexArray[vp + 2] = static_cast<float>(x);
1545
        mFloatTexArray[vp + 3] = yf2;
1546
1547
        vp += 4;
1548
        if (vp >= vLimit)
1549
        {
1550
            drawLineArrayf(vp);
1551
            vp = 0;
1552
        }
1553
    }
1554
1555
    if (vp > 0)
1556
        drawLineArrayf(vp);
1557
}
1558
1559
void NormalOpenGLGraphics::bindTexture(const GLenum target,
1560
                                       const GLuint texture)
1561
{
1562
    if (mTextureBinded != texture)
1563
    {
1564
        mTextureBinded = texture;
1565
        glBindTexture(target, texture);
1566
#ifdef DEBUG_BIND_TEXTURE
1567
        mBinds ++;
1568
#endif  // DEBUG_BIND_TEXTURE
1569
    }
1570
}
1571
1572
inline void NormalOpenGLGraphics::drawQuadArrayfi(const int size) restrict2
1573
{
1574
    bindPointerIntFloat(&mIntVertArray[0], &mFloatTexArray[0]);
1575
#ifdef DEBUG_DRAW_CALLS
1576
    mDrawCalls ++;
1577
#endif  // DEBUG_DRAW_CALLS
1578
1579
    glDrawArrays(GL_QUADS, 0, size / 2);
1580
#ifdef OPENGLERRORS
1581
    graphicsManager.logError();
1582
#endif  // OPENGLERRORS
1583
}
1584
1585
inline void NormalOpenGLGraphics::drawQuadArrayfiCached(const int size)
1586
                                                        restrict2
1587
{
1588
    bindPointerIntFloat(&mIntVertArrayCached[0], &mFloatTexArrayCached[0]);
1589
#ifdef DEBUG_DRAW_CALLS
1590
    mDrawCalls ++;
1591
#endif  // DEBUG_DRAW_CALLS
1592
1593
    glDrawArrays(GL_QUADS, 0, size / 2);
1594
#ifdef OPENGLERRORS
1595
    graphicsManager.logError();
1596
#endif  // OPENGLERRORS
1597
}
1598
1599
inline void NormalOpenGLGraphics::drawQuadArrayfi(const GLint *restrict const
1600
                                                  intVertArray,
1601
                                                  const GLfloat *restrict const
1602
                                                  floatTexArray,
1603
                                                  const int size) restrict2
1604
{
1605
    vertPtr = intVertArray;
1606
    glVertexPointer(2, GL_INT, 0, intVertArray);
1607
    glTexCoordPointer(2, GL_FLOAT, 0, floatTexArray);
1608
#ifdef DEBUG_DRAW_CALLS
1609
    mDrawCalls ++;
1610
#endif  // DEBUG_DRAW_CALLS
1611
1612
    glDrawArrays(GL_QUADS, 0, size / 2);
1613
#ifdef OPENGLERRORS
1614
    graphicsManager.logError();
1615
#endif  // OPENGLERRORS
1616
}
1617
1618
inline void NormalOpenGLGraphics::drawQuadArrayii(const int size) restrict2
1619
{
1620
    bindPointerInt(&mIntVertArray[0], &mIntTexArray[0]);
1621
#ifdef DEBUG_DRAW_CALLS
1622
    mDrawCalls ++;
1623
#endif  // DEBUG_DRAW_CALLS
1624
1625
    glDrawArrays(GL_QUADS, 0, size / 2);
1626
#ifdef OPENGLERRORS
1627
    graphicsManager.logError();
1628
#endif  // OPENGLERRORS
1629
}
1630
1631
inline void NormalOpenGLGraphics::drawQuadArrayiiCached(const int size)
1632
                                                        restrict2
1633
{
1634
    bindPointerInt(&mIntVertArrayCached[0], &mIntTexArrayCached[0]);
1635
#ifdef DEBUG_DRAW_CALLS
1636
    mDrawCalls ++;
1637
#endif  // DEBUG_DRAW_CALLS
1638
1639
    glDrawArrays(GL_QUADS, 0, size / 2);
1640
#ifdef OPENGLERRORS
1641
    graphicsManager.logError();
1642
#endif  // OPENGLERRORS
1643
}
1644
1645
inline void NormalOpenGLGraphics::drawQuadArrayii(const GLint *restrict const
1646
                                                  intVertArray,
1647
                                                  const GLint *restrict const
1648
                                                  intTexArray,
1649
                                                  const int size) restrict2
1650
{
1651
    vertPtr = intVertArray;
1652
    glVertexPointer(2, GL_INT, 0, intVertArray);
1653
    glTexCoordPointer(2, GL_INT, 0, intTexArray);
1654
#ifdef DEBUG_DRAW_CALLS
1655
    mDrawCalls ++;
1656
#endif  // DEBUG_DRAW_CALLS
1657
1658
    glDrawArrays(GL_QUADS, 0, size / 2);
1659
#ifdef OPENGLERRORS
1660
    graphicsManager.logError();
1661
#endif  // OPENGLERRORS
1662
}
1663
1664
inline void NormalOpenGLGraphics::drawLineArrayi(const int size) restrict2
1665
{
1666
    glVertexPointer(2, GL_INT, 0, mIntVertArray);
1667
    vertPtr = nullptr;
1668
#ifdef DEBUG_DRAW_CALLS
1669
    mDrawCalls ++;
1670
#endif  // DEBUG_DRAW_CALLS
1671
1672
    glDrawArrays(GL_LINES, 0, size / 2);
1673
#ifdef OPENGLERRORS
1674
    graphicsManager.logError();
1675
#endif  // OPENGLERRORS
1676
}
1677
1678
inline void NormalOpenGLGraphics::drawLineArrayf(const int size) restrict2
1679
{
1680
    glVertexPointer(2, GL_FLOAT, 0, mFloatTexArray);
1681
    vertPtr = nullptr;
1682
#ifdef DEBUG_DRAW_CALLS
1683
    mDrawCalls ++;
1684
#endif  // DEBUG_DRAW_CALLS
1685
1686
    glDrawArrays(GL_LINES, 0, size / 2);
1687
#ifdef OPENGLERRORS
1688
    graphicsManager.logError();
1689
#endif  // OPENGLERRORS
1690
}
1691
1692
void NormalOpenGLGraphics::dumpSettings()
1693
{
1694
    GLint test[1000];
1695
    logger->log("\n\n");
1696
    logger->log("start opengl dump");
1697
    for (int f = 0; f < 65535; f ++)
1698
    {
1699
        test[0] = 0;
1700
        test[1] = 0;
1701
        test[2] = 0;
1702
        test[3] = 0;
1703
        glGetIntegerv(f, &test[0]);
1704
        if (test[0] != 0 || test[1] != 0 || test[2] != 0 || test[3] != 0)
1705
        {
1706
            logger->log("\n%d = %d, %d, %d, %d", f,
1707
                test[0], test[1], test[2], test[3]);
1708
        }
1709
    }
1710
}
1711
1712
void NormalOpenGLGraphics::setColorAlpha(const float alpha) restrict2
1713
{
1714
    if (!mIsByteColor && mFloatColor == alpha)
1715
        return;
1716
1717
    glColor4f(1.0F, 1.0F, 1.0F, alpha);
1718
    mIsByteColor = false;
1719
    mFloatColor = alpha;
1720
}
1721
1722
void NormalOpenGLGraphics::restoreColor() restrict2
1723
{
1724
    if (mIsByteColor && mByteColor == mColor)
1725
        return;
1726
1727
    glColor4ub(static_cast<GLubyte>(mColor.r),
1728
               static_cast<GLubyte>(mColor.g),
1729
               static_cast<GLubyte>(mColor.b),
1730
               static_cast<GLubyte>(mColor.a));
1731
    mIsByteColor = true;
1732
    mByteColor = mColor;
1733
}
1734
1735
void NormalOpenGLGraphics::drawImageRect(const int x, const int y,
1736
                                         const int w, const int h,
1737
                                         const ImageRect &restrict imgRect)
1738
                                         restrict2
1739
{
1740
    #include "render/graphics_drawImageRect.hpp"
1741
}
1742
1743
void NormalOpenGLGraphics::calcImageRect(ImageVertexes *restrict const vert,
1744
                                         const int x, const int y,
1745
                                         const int w, const int h,
1746
                                         const ImageRect &restrict imgRect)
1747
                                         restrict2
1748
{
1749
    #include "render/graphics_calcImageRect.hpp"
1750
}
1751
1752
void NormalOpenGLGraphics::clearScreen() const restrict2
1753
{
1754
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1755
}
1756
1757
#ifdef DEBUG_BIND_TEXTURE
1758
void NormalOpenGLGraphics::debugBindTexture(const Image *restrict const image)
1759
                                            restrict2
1760
{
1761
    const std::string texture = image->mIdPath;
1762
    if (mOldTexture != texture)
1763
    {
1764
        if ((!mOldTexture.empty() || !texture.empty())
1765
            && mOldTextureId != image->mGLImage)
1766
        {
1767
            logger->log("bind: %s (%d) to %s (%d)", mOldTexture.c_str(),
1768
                mOldTextureId, texture.c_str(), image->mGLImage);
1769
        }
1770
        mOldTextureId = image->mGLImage;
1771
        mOldTexture = texture;
1772
    }
1773
}
1774
#else  // DEBUG_BIND_TEXTURE
1775
1776
void NormalOpenGLGraphics::debugBindTexture(const Image *restrict const
1777
                                            image A_UNUSED) restrict2
1778
{
1779
}
1780
#endif  // DEBUG_BIND_TEXTURE
1781
1782
#endif  // !defined(ANDROID) && !defined(__native_client__) &&
1783
        // !defined(__SWITCH__)
1784
#endif  // USE_OPENGL