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