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