ManaPlus
mobileopenglgraphics.cpp
Go to the documentation of this file.
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-2018 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(__native_client__)
24 
26 
27 #ifdef OPENGLERRORS
28 #include "graphicsmanager.h"
29 #endif // OPENGLERRORS
30 
31 #include "render/opengl/mgl.h"
32 #ifdef __native_client__
34 #endif // __native_client__
35 
37 
38 #include "resources/imagerect.h"
40 
41 #include "resources/image/image.h"
42 
43 #include "utils/sdlcheckutils.h"
44 
45 #include "debug.h"
46 
47 #define vertFill2D(tVar, vVar, x1, y1, x2, y2, dstX, dstY, w, h) \
48  tVar[vp + 0] = x1; \
49  tVar[vp + 1] = y1; \
50  tVar[vp + 2] = x2; \
51  tVar[vp + 3] = y1; \
52  tVar[vp + 4] = x2; \
53  tVar[vp + 5] = y2; \
54  tVar[vp + 6] = x1; \
55  tVar[vp + 7] = y1; \
56  tVar[vp + 8] = x1; \
57  tVar[vp + 9] = y2; \
58  tVar[vp + 10] = x2; \
59  tVar[vp + 11] = y2; \
60  vVar[vp + 0] = static_cast<GLshort>(dstX); \
61  vVar[vp + 1] = static_cast<GLshort>(dstY); \
62  vVar[vp + 2] = static_cast<GLshort>(dstX + w); \
63  vVar[vp + 3] = static_cast<GLshort>(dstY); \
64  vVar[vp + 4] = static_cast<GLshort>(dstX + w); \
65  vVar[vp + 5] = static_cast<GLshort>(dstY + h); \
66  vVar[vp + 6] = static_cast<GLshort>(dstX); \
67  vVar[vp + 7] = static_cast<GLshort>(dstY); \
68  vVar[vp + 8] = static_cast<GLshort>(dstX); \
69  vVar[vp + 9] = static_cast<GLshort>(dstY + h); \
70  vVar[vp + 10] = static_cast<GLshort>(dstX + w); \
71  vVar[vp + 11] = static_cast<GLshort>(dstY + h);
72 
74 #ifdef DEBUG_DRAW_CALLS
75 unsigned int MobileOpenGLGraphics::mDrawCalls = 0;
76 unsigned int MobileOpenGLGraphics::mLastDrawCalls = 0;
77 #endif // DEBUG_DRAW_CALLS
78 
80  mFloatTexArray(nullptr),
81  mShortVertArray(nullptr),
82  mFloatTexArrayCached(nullptr),
83  mShortVertArrayCached(nullptr),
84  mAlphaCached(1.0F),
85  mVpCached(0),
86  mTexture(false),
87  mIsByteColor(false),
88  mByteColor(),
89  mImageCached(0),
90  mFloatColor(1.0F),
91  mMaxVertices(500),
92  mColorAlpha(false),
93 #ifdef DEBUG_BIND_TEXTURE
94  mOldTexture(),
95  mOldTextureId(0),
96 #endif // DEBUG_BIND_TEXTURE
97  mFbo()
98 {
100  mName = "mobile OpenGL ES";
101 }
102 
104 {
106 }
107 
109 {
110 // glesTest();
111 }
112 
114 {
115  mMaxVertices = vertCount;
116  if (mMaxVertices < 500)
117  mMaxVertices = 500;
118  else if (mMaxVertices > 1024)
119  mMaxVertices = 1024;
120 
121  // need alocate small size, after if limit reached reallocate to double size
122  const size_t sz = mMaxVertices * 4 + 30;
124  if (mFloatTexArray == nullptr)
125  mFloatTexArray = new GLfloat[sz];
126  if (mShortVertArray == nullptr)
127  mShortVertArray = new GLshort[sz];
128  if (mFloatTexArrayCached == nullptr)
129  mFloatTexArrayCached = new GLfloat[sz];
130  if (mShortVertArrayCached == nullptr)
131  mShortVertArrayCached = new GLshort[sz];
132 }
133 
135 {
137 }
138 
140 {
141  delete [] mFloatTexArray;
142  mFloatTexArray = nullptr;
143  delete [] mShortVertArray;
144  mShortVertArray = nullptr;
145  delete [] mFloatTexArrayCached;
146  mFloatTexArrayCached = nullptr;
147  delete [] mShortVertArrayCached;
148  mShortVertArrayCached = nullptr;
149 }
150 
151 bool MobileOpenGLGraphics::setVideoMode(const int w, const int h,
152  const int scale,
153  const int bpp,
154  const bool fs,
155  const bool hwaccel,
156  const bool resize,
157  const bool noFrame,
158  const bool allowHighDPI) restrict2
159 {
160  setMainFlags(w, h,
161  scale,
162  bpp,
163  fs,
164  hwaccel,
165  resize,
166  noFrame,
167  allowHighDPI);
168 
169  return setOpenGLMode();
170 }
171 
172 static inline void drawQuad(const Image *restrict const image,
173  const int srcX,
174  const int srcY,
175  const int dstX,
176  const int dstY,
177  const int width,
178  const int height) A_NONNULL(1) A_INLINE;
179 
180 static inline void drawQuad(const Image *restrict const image,
181  const int srcX,
182  const int srcY,
183  const int dstX,
184  const int dstY,
185  const int width,
186  const int height)
187 {
188 // if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
189  {
190  const float tw = static_cast<float>(image->mTexWidth);
191  const float th = static_cast<float>(image->mTexHeight);
192  // Find OpenGL normalized texture coordinates.
193  const float texX1 = static_cast<float>(srcX) / tw;
194  const float texY1 = static_cast<float>(srcY) / th;
195  const float texX2 = static_cast<float>(srcX + width) / tw;
196  const float texY2 = static_cast<float>(srcY + height) / th;
197 
198  GLfloat tex[] =
199  {
200  texX1, texY1,
201  texX2, texY1,
202  texX1, texY2,
203  texX2, texY2
204  };
205 
206  GLshort vert[] =
207  {
208  static_cast<GLshort>(dstX), static_cast<GLshort>(dstY),
209  static_cast<GLshort>(dstX + width), static_cast<GLshort>(dstY),
210  static_cast<GLshort>(dstX), static_cast<GLshort>(dstY + height),
211  static_cast<GLshort>(dstX + width),
212  static_cast<GLshort>(dstY + height)
213  };
214 
215  glVertexPointer(2, GL_SHORT, 0, &vert);
216  glTexCoordPointer(2, GL_FLOAT, 0, &tex);
217 
218 #ifdef DEBUG_DRAW_CALLS
219  MobileOpenGLGraphics::mDrawCalls ++;
220 #endif // DEBUG_DRAW_CALLS
221  mglDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
222 #ifdef OPENGLERRORS
224 #endif // OPENGLERRORS
225  }
226 }
227 
228 static inline void drawRescaledQuad(const Image *restrict const image,
229  const int srcX, const int srcY,
230  const int dstX, const int dstY,
231  const int width, const int height,
232  const int desiredWidth,
233  const int desiredHeight)
234  A_NONNULL(1) A_INLINE;
235 
236 static inline void drawRescaledQuad(const Image *restrict const image,
237  const int srcX, const int srcY,
238  const int dstX, const int dstY,
239  const int width, const int height,
240  const int desiredWidth,
241  const int desiredHeight)
242 {
243 // if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
244  {
245  const float tw = static_cast<float>(image->mTexWidth);
246  const float th = static_cast<float>(image->mTexHeight);
247  // Find OpenGL normalized texture coordinates.
248  const float texX1 = static_cast<float>(srcX) / tw;
249  const float texY1 = static_cast<float>(srcY) / th;
250  const float texX2 = static_cast<float>(srcX + width) / tw;
251  const float texY2 = static_cast<float>(srcY + height) / th;
252 
253  GLfloat tex[] =
254  {
255  texX1, texY1,
256  texX2, texY1,
257  texX1, texY2,
258  texX2, texY2
259  };
260 
261  GLshort vert[] =
262  {
263  static_cast<GLshort>(dstX), static_cast<GLshort>(dstY),
264  static_cast<GLshort>(dstX + desiredWidth),
265  static_cast<GLshort>(dstY),
266  static_cast<GLshort>(dstX), static_cast<GLshort>(
267  dstY + desiredHeight),
268  static_cast<GLshort>(dstX + desiredWidth),
269  static_cast<GLshort>(dstY + desiredHeight)
270  };
271  glVertexPointer(2, GL_SHORT, 0, &vert);
272  glTexCoordPointer(2, GL_FLOAT, 0, &tex);
273 
274 #ifdef DEBUG_DRAW_CALLS
275  MobileOpenGLGraphics::mDrawCalls ++;
276 #endif // DEBUG_DRAW_CALLS
277  mglDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
278 #ifdef OPENGLERRORS
280 #endif // OPENGLERRORS
281  }
282 }
283 
285  int dstX, int dstY) restrict2
286 {
287  drawImageInline(image, dstX, dstY);
288 }
289 
291  int dstX, int dstY) restrict2
292 {
293  FUNC_BLOCK("Graphics::drawImage", 1)
294  if (image == nullptr)
295  return;
296 
297  setColorAlpha(image->mAlpha);
298 #ifdef DEBUG_BIND_TEXTURE
299  debugBindTexture(image);
300 #endif // DEBUG_BIND_TEXTURE
303 
304  const SDL_Rect &imageRect = image->mBounds;
305  drawQuad(image, imageRect.x, imageRect.y,
306  dstX, dstY, imageRect.w, imageRect.h);
307 }
308 
310  int dstX, int dstY) restrict2
311 {
312  drawImageInline(image, dstX, dstY);
313 }
314 
316  int x, int y) restrict2
317 {
318  if (image == nullptr)
319  return;
320 
321  if (image->mGLImage != mImageCached)
322  {
323  completeCache();
324  mImageCached = image->mGLImage;
325  mAlphaCached = image->mAlpha;
326  }
327 
328  const SDL_Rect &imageRect = image->mBounds;
329  const int srcX = imageRect.x;
330  const int srcY = imageRect.y;
331  const int w = imageRect.w;
332  const int h = imageRect.h;
333 
334  if (w == 0 || h == 0)
335  return;
336 
337  const float tw = static_cast<float>(image->mTexWidth);
338  const float th = static_cast<float>(image->mTexHeight);
339 
340  const unsigned int vLimit = mMaxVertices * 4;
341 
342  unsigned int vp = mVpCached;
343 
344  // Draw a set of textured rectangles
345 // if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
346  {
347  float texX1 = static_cast<float>(srcX) / tw;
348  float texY1 = static_cast<float>(srcY) / th;
349  float texX2 = static_cast<float>(srcX + w) / tw;
350  float texY2 = static_cast<float>(srcY + h) / th;
351 
353  texX1, texY1, texX2, texY2,
354  x, y, w, h);
355 
356  vp += 12;
357  if (vp >= vLimit)
358  {
359  completeCache();
360  vp = 0;
361  }
362  else
363  {
364  mVpCached = vp;
365  }
366  }
367 }
368 
370  const int x,
371  const int y,
372  const int w,
373  const int h) restrict2
374 {
375  if (image == nullptr)
376  return;
377 
378  if (image->mGLImage != mImageCached)
379  {
380  completeCache();
381  mImageCached = image->mGLImage;
382  }
383 
384  const SDL_Rect &imageRect = image->mBounds;
385  const int srcX = imageRect.x;
386  const int srcY = imageRect.y;
387  const int iw = imageRect.w;
388  const int ih = imageRect.h;
389 
390  if (iw == 0 || ih == 0)
391  return;
392 
393  const float tw = static_cast<float>(image->mTexWidth);
394  const float th = static_cast<float>(image->mTexHeight);
395 
396  unsigned int vp = mVpCached;
397  const unsigned int vLimit = mMaxVertices * 4;
398  const float texX1 = static_cast<float>(srcX) / tw;
399  const float texY1 = static_cast<float>(srcY) / th;
400 
401  for (int py = 0; py < h; py += ih)
402  {
403  const int height = (py + ih >= h) ? h - py : ih;
404  const float texY2 = static_cast<float>(srcY + height) / th;
405  const int dstY = y + py;
406  for (int px = 0; px < w; px += iw)
407  {
408  const int width = (px + iw >= w) ? w - px : iw;
409  const int dstX = x + px;
410 
411  const float texX2 = static_cast<float>(srcX + width) / tw;
412 
414  texX1, texY1, texX2, texY2,
415  dstX, dstY, width, height);
416 
417  vp += 12;
418  if (vp >= vLimit)
419  {
420  completeCache();
421  vp = 0;
422  }
423  }
424  }
425  mVpCached = vp;
426 }
427 
429 {
430  if (mImageCached == 0u)
431  return;
432 
434 #ifdef DEBUG_BIND_TEXTURE
435 // debugBindTexture(image);
436 #endif // DEBUG_BIND_TEXTURE
439 
441  mImageCached = 0;
442  mVpCached = 0;
443 }
444 
446  int dstX, int dstY,
447  const int desiredWidth,
448  const int desiredHeight) restrict2
449 {
450  FUNC_BLOCK("Graphics::drawRescaledImage", 1)
451  if (image == nullptr)
452  return;
453 
454  const SDL_Rect &imageRect = image->mBounds;
455 
456  // Just draw the image normally when no resizing is necessary,
457  if (imageRect.w == desiredWidth && imageRect.h == desiredHeight)
458  {
459  drawImageInline(image, dstX, dstY);
460  return;
461  }
462 
463  setColorAlpha(image->mAlpha);
464 #ifdef DEBUG_BIND_TEXTURE
465  debugBindTexture(image);
466 #endif // DEBUG_BIND_TEXTURE
469 
470  // Draw a textured quad.
471  drawRescaledQuad(image, imageRect.x, imageRect.y, dstX, dstY,
472  imageRect.w, imageRect.h, desiredWidth, desiredHeight);
473 }
474 
476  const int x, const int y,
477  const int w, const int h) restrict2
478 {
479  drawPatternInline(image, x, y, w, h);
480 }
481 
483  const int x,
484  const int y,
485  const int w,
486  const int h) restrict2
487 {
488  FUNC_BLOCK("Graphics::drawPattern", 1)
489  if (image == nullptr)
490  return;
491 
492  const SDL_Rect &imageRect = image->mBounds;
493  const int srcX = imageRect.x;
494  const int srcY = imageRect.y;
495  const int iw = imageRect.w;
496  const int ih = imageRect.h;
497 
498  if (iw == 0 || ih == 0)
499  return;
500 
501  const float tw = static_cast<float>(image->mTexWidth);
502  const float th = static_cast<float>(image->mTexHeight);
503 
504  setColorAlpha(image->mAlpha);
505 
506 #ifdef DEBUG_BIND_TEXTURE
507  debugBindTexture(image);
508 #endif // DEBUG_BIND_TEXTURE
510 
512 
513  unsigned int vp = 0;
514  const unsigned int vLimit = mMaxVertices * 4;
515  // Draw a set of textured rectangles
516  const float texX1 = static_cast<float>(srcX) / tw;
517  const float texY1 = static_cast<float>(srcY) / th;
518 
519  for (int py = 0; py < h; py += ih)
520  {
521  const int height = (py + ih >= h) ? h - py : ih;
522  const float texY2 = static_cast<float>(srcY + height) / th;
523  const int dstY = y + py;
524  for (int px = 0; px < w; px += iw)
525  {
526  const int width = (px + iw >= w) ? w - px : iw;
527  const int dstX = x + px;
528 
529  const float texX2 = static_cast<float>(srcX + width) / tw;
530 
532  texX1, texY1, texX2, texY2,
533  dstX, dstY, width, height);
534 
535  vp += 12;
536  if (vp >= vLimit)
537  {
539  vp = 0;
540  }
541  }
542  }
543  if (vp > 0)
545 }
546 
548  restrict const image,
549  const int x, const int y,
550  const int w, const int h,
551  const int scaledWidth,
552  const int scaledHeight)
553  restrict2
554 {
555  if (image == nullptr)
556  return;
557 
558  if (scaledWidth == 0 || scaledHeight == 0)
559  return;
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  if (iw == 0 || ih == 0)
567  return;
568 
569  setColorAlpha(image->mAlpha);
570 
571 #ifdef DEBUG_BIND_TEXTURE
572  debugBindTexture(image);
573 #endif // DEBUG_BIND_TEXTURE
575 
577 
578  unsigned int vp = 0;
579  const unsigned int vLimit = mMaxVertices * 4;
580 
581  // Draw a set of textured rectangles
582  const float tw = static_cast<float>(image->mTexWidth);
583  const float th = static_cast<float>(image->mTexHeight);
584 
585  const float texX1 = static_cast<float>(srcX) / tw;
586  const float texY1 = static_cast<float>(srcY) / th;
587 
588  const float tFractionW = iw / tw;
589  const float tFractionH = ih / th;
590 
591  for (int py = 0; py < h; py += scaledHeight)
592  {
593  const int height = (py + scaledHeight >= h)
594  ? h - py : scaledHeight;
595  const int dstY = y + py;
596  const float visibleFractionH = static_cast<float>(height)
597  / scaledHeight;
598  const float texY2 = texY1 + tFractionH * visibleFractionH;
599  for (int px = 0; px < w; px += scaledWidth)
600  {
601  const int width = (px + scaledWidth >= w)
602  ? w - px : scaledWidth;
603  const int dstX = x + px;
604  const float visibleFractionW = static_cast<float>(width)
605  / scaledWidth;
606  const float texX2 = texX1 + tFractionW * visibleFractionW;
607 
609  texX1, texY1, texX2, texY2,
610  dstX, dstY, width, height);
611 
612  vp += 12;
613  if (vp >= vLimit)
614  {
616  vp = 0;
617  }
618  }
619  }
620  if (vp > 0)
622 }
623 
626  &restrict ogl) restrict2
627 {
628  const STD_VECTOR<GLshort*> &shortVertPool = ogl.mShortVertPool;
629  STD_VECTOR<GLshort*>::const_iterator iv;
630  const STD_VECTOR<GLshort*>::const_iterator iv_end = shortVertPool.end();
631  const STD_VECTOR<int> &vp = ogl.mVp;
632  STD_VECTOR<int>::const_iterator ivp;
633  const STD_VECTOR<int>::const_iterator ivp_end = vp.end();
634 
635  // Draw a set of textured rectangles
636 // if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
637  {
638  const STD_VECTOR<GLfloat*> &floatTexPool = ogl.mFloatTexPool;
639  STD_VECTOR<GLfloat*>::const_iterator ft;
640  const STD_VECTOR<GLfloat*>::const_iterator
641  ft_end = floatTexPool.end();
642 
643  for (iv = shortVertPool.begin(), ft = floatTexPool.begin(),
644  ivp = vp.begin();
645  iv != iv_end && ft != ft_end && ivp != ivp_end;
646  ++ iv, ++ ft, ++ ivp)
647  {
648  drawTriangleArrayfs(*iv, *ft, *ivp);
649  }
650  }
651 }
652 
654  const Image *restrict const image,
655  const int x,
656  const int y,
657  const int w,
658  const int h) const restrict2
659 {
660  calcPatternInline(vert, image, x, y, w, h);
661 }
662 
664  restrict const vert,
665  const Image *restrict const image,
666  const int x,
667  const int y,
668  const int w,
669  const int h) const restrict2
670 {
671  if (image == nullptr || vert == nullptr)
672  return;
673 
674  const SDL_Rect &imageRect = image->mBounds;
675  const int srcX = imageRect.x;
676  const int srcY = imageRect.y;
677  const int iw = imageRect.w;
678  const int ih = imageRect.h;
679 
680  if (iw == 0 || ih == 0)
681  return;
682 
683  const float tw = static_cast<float>(image->mTexWidth);
684  const float th = static_cast<float>(image->mTexHeight);
685 
686  const unsigned int vLimit = mMaxVertices * 4;
687 
688  OpenGLGraphicsVertexes &ogl = vert->ogl;
689  unsigned int vp = ogl.continueVp();
690 
691  // Draw a set of textured rectangles
692 // if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
693  {
694  const float texX1 = static_cast<float>(srcX) / tw;
695  const float texY1 = static_cast<float>(srcY) / th;
696 
697  GLfloat *floatTexArray = ogl.continueFloatTexArray();
698  GLshort *shortVertArray = ogl.continueShortVertArray();
699 
700  for (int py = 0; py < h; py += ih)
701  {
702  const int height = (py + ih >= h) ? h - py : ih;
703  const int dstY = y + py;
704  const float texY2 = static_cast<float>(srcY + height) / th;
705  for (int px = 0; px < w; px += iw)
706  {
707  const int width = (px + iw >= w) ? w - px : iw;
708  const int dstX = x + px;
709  const float texX2 = static_cast<float>(srcX + width) / tw;
710 
711  vertFill2D(floatTexArray, shortVertArray,
712  texX1, texY1, texX2, texY2,
713  dstX, dstY, width, height);
714 
715  vp += 12;
716  if (vp >= vLimit)
717  {
718  floatTexArray = ogl.switchFloatTexArray();
719  shortVertArray = ogl.switchShortVertArray();
720  ogl.switchVp(vp);
721  vp = 0;
722  }
723  }
724  }
725  }
726  ogl.switchVp(vp);
727 }
728 
730  restrict const vertCol,
731  const Image *
732  restrict const image,
733  int x, int y) restrict2
734 {
735  if (vertCol == nullptr || image == nullptr)
736  return;
737  if (vertCol->currentGLImage != image->mGLImage)
738  {
739  ImageVertexes *const vert = new ImageVertexes;
740  vertCol->currentGLImage = image->mGLImage;
741  vertCol->currentVert = vert;
742  vert->image = image;
743  vertCol->draws.push_back(vert);
744  calcTileVertexesInline(vert, image, x, y);
745  }
746  else
747  {
748  calcTileVertexesInline(vertCol->currentVert, image, x, y);
749  }
750 }
751 
753  restrict const vertCol)
754  restrict2
755 {
756  const ImageVertexesVector &draws = vertCol->draws;
757  const ImageCollectionCIter it_end = draws.end();
758  for (ImageCollectionCIter it = draws.begin(); it != it_end; ++ it)
759  {
760  const ImageVertexes *const vert = *it;
761  const Image *const image = vert->image;
762 
763  setColorAlpha(image->mAlpha);
764 #ifdef DEBUG_BIND_TEXTURE
765  debugBindTexture(image);
766 #endif // DEBUG_BIND_TEXTURE
769  drawVertexes(vert->ogl);
770  }
771 }
772 
774  const Image *restrict const image,
775  const int x,
776  const int y,
777  const int w,
778  const int h) const restrict2
779 {
780  if (vertCol == nullptr || image == nullptr)
781  return;
782  ImageVertexes *vert = nullptr;
783  if (vertCol->currentGLImage != image->mGLImage)
784  {
785  vert = new ImageVertexes;
786  vertCol->currentGLImage = image->mGLImage;
787  vertCol->currentVert = vert;
788  vert->image = image;
789  vertCol->draws.push_back(vert);
790  }
791  else
792  {
793  vert = vertCol->currentVert;
794  }
795 
796  calcPatternInline(vert, image, x, y, w, h);
797 }
798 
800  const Image *restrict const image,
801  int dstX, int dstY) const restrict2
802 {
803  calcTileVertexesInline(vert, image, dstX, dstY);
804 }
805 
807  restrict const vert,
808  const Image *
809  restrict const image,
810  int dstX,
811  int dstY) const restrict2
812 {
813  const SDL_Rect &imageRect = image->mBounds;
814  const int srcX = imageRect.x;
815  const int srcY = imageRect.y;
816  const int w = imageRect.w;
817  const int h = imageRect.h;
818 
819  if (w == 0 || h == 0)
820  return;
821 
822  const float tw = static_cast<float>(image->mTexWidth);
823  const float th = static_cast<float>(image->mTexHeight);
824 
825  const unsigned int vLimit = mMaxVertices * 4;
826 
827  OpenGLGraphicsVertexes &ogl = vert->ogl;
828 
829 // STD_VECTOR<int> *vps = ogl.getVp();
830  unsigned int vp = ogl.continueVp();
831 
832  // Draw a set of textured rectangles
833 // if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D)
834  {
835  float texX1 = static_cast<float>(srcX) / tw;
836  float texY1 = static_cast<float>(srcY) / th;
837  float texX2 = static_cast<float>(srcX + w) / tw;
838  float texY2 = static_cast<float>(srcY + h) / th;
839 
840  GLfloat *const floatTexArray = ogl.continueFloatTexArray();
841  GLshort *const shortVertArray = ogl.continueShortVertArray();
842 
843  vertFill2D(floatTexArray, shortVertArray,
844  texX1, texY1, texX2, texY2,
845  dstX, dstY, w, h);
846 
847  vp += 12;
848  if (vp >= vLimit)
849  {
850  ogl.switchFloatTexArray();
851  ogl.switchShortVertArray();
852  ogl.switchVp(vp);
853  vp = 0;
854  }
855  }
856  ogl.switchVp(vp);
857 }
858 
860  restrict const vert) restrict2
861 {
862  if (vert == nullptr)
863  return;
864  const Image *const image = vert->image;
865 
866  setColorAlpha(image->mAlpha);
867 #ifdef DEBUG_BIND_TEXTURE
868  debugBindTexture(image);
869 #endif // DEBUG_BIND_TEXTURE
872  drawVertexes(vert->ogl);
873 }
874 
876  const int x, const int y,
877  const int w, const int h,
878  const ImageRect &restrict imgRect)
879  restrict2
880 {
881  ImageVertexes *vert = nullptr;
882  const Image *const image = imgRect.grid[4];
883  if (image == nullptr)
884  return;
885  if (vertCol->currentGLImage != image->mGLImage)
886  {
887  vert = new ImageVertexes;
888  vertCol->currentGLImage = image->mGLImage;
889  vertCol->currentVert = vert;
890  vert->image = image;
891  vertCol->draws.push_back(vert);
892  }
893  else
894  {
895  vert = vertCol->currentVert;
896  }
897  calcImageRect(vert, x, y, w, h, imgRect);
898 }
899 
900 
902 {
903  BLOCK_START("Graphics::updateScreen")
904 // glFlush();
905 // glFinish();
906 #ifdef DEBUG_DRAW_CALLS
907  mLastDrawCalls = mDrawCalls;
908  mDrawCalls = 0;
909 #endif // DEBUG_DRAW_CALLS
910 #ifdef USE_SDL2
911  SDL_GL_SwapWindow(mWindow);
912 #else // USE_SDL2
913 
914  SDL_GL_SwapBuffers();
915 #endif // USE_SDL2
916 #ifdef DEBUG_OPENGL
917  if (isGLNotNull(mglFrameTerminator))
918  mglFrameTerminator();
919 #endif // DEBUG_OPENGL
920 
921  BLOCK_END("Graphics::updateScreen")
922 }
923 
925 {
926  glMatrixMode(GL_TEXTURE);
927  glLoadIdentity();
928 
929  glMatrixMode(GL_PROJECTION);
930  glLoadIdentity();
931 
932 #ifdef ANDROID
933  glOrthof(0.0, static_cast<float>(mRect.w),
934  static_cast<float>(mRect.h),
935  0.0, -1.0, 1.0);
936 #else // ANDROID
937 
938  glOrtho(0.0, static_cast<double>(mRect.w),
939  static_cast<double>(mRect.h),
940  0.0, -1.0, 1.0);
941 #endif // ANDROID
942 
943  glMatrixMode(GL_MODELVIEW);
944  glLoadIdentity();
945 
946  setOpenGLFlags();
947  mglDisable(GL_LIGHTING);
948  mglDisable(GL_FOG);
949  mglDisable(GL_COLOR_MATERIAL);
950 
951  glShadeModel(GL_FLAT);
952 
953  glEnableClientState(GL_VERTEX_ARRAY);
954  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
955 
956 #ifndef ANDROID
957  mglHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
958  mglHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
959  mglHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
960  mglHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
961 #endif // ANDROID
962 
963  pushClipArea(Rect(0, 0, mRect.w, mRect.h));
964 }
965 
967 {
968  popClipArea();
969 }
970 
972 {
973  int transX = 0;
974  int transY = 0;
975 
976  if (!mClipStack.empty())
977  {
978  const ClipRect &clipArea = mClipStack.top();
979  transX = -clipArea.xOffset;
980  transY = -clipArea.yOffset;
981  }
982 
984 
985  const ClipRect &clipArea = mClipStack.top();
986  transX += clipArea.xOffset;
987  transY += clipArea.yOffset;
988 
989  if (transX != 0 || transY != 0)
990  {
991  glTranslatef(static_cast<GLfloat>(transX),
992  static_cast<GLfloat>(transY), 0);
993  }
994  mglScissor(clipArea.x * mScale,
995  (mRect.h - clipArea.y - clipArea.height) * mScale,
996  clipArea.width * mScale,
997  clipArea.height * mScale);
998 }
999 
1001 {
1002  if (mClipStack.empty())
1003  return;
1004 
1005  const ClipRect &clipArea1 = mClipStack.top();
1006  int transX = -clipArea1.xOffset;
1007  int transY = -clipArea1.yOffset;
1008 
1010 
1011  if (mClipStack.empty())
1012  return;
1013 
1014  const ClipRect &clipArea = mClipStack.top();
1015  transX += clipArea.xOffset;
1016  transY += clipArea.yOffset;
1017  if (transX != 0 || transY != 0)
1018  {
1019  glTranslatef(static_cast<GLfloat>(transX),
1020  static_cast<GLfloat>(transY), 0);
1021  }
1022  mglScissor(clipArea.x * mScale,
1023  (mRect.h - clipArea.y - clipArea.height) * mScale,
1024  clipArea.width * mScale,
1025  clipArea.height * mScale);
1026 }
1027 
1028 #ifdef ANDROID
1030 #else // ANDROID
1032 #endif // ANDROID
1033 {
1035  restoreColor();
1036 
1037 #ifdef ANDROID
1038  // TODO need fix
1039 #else // ANDROID
1040 
1041  glBegin(GL_POINTS);
1042  glVertex2i(x, y);
1043  glEnd();
1044 #endif // ANDROID
1045 }
1046 
1048  int x2, int y2) restrict2
1049 {
1051  restoreColor();
1052 
1053  mShortVertArray[0] = static_cast<GLshort>(x1);
1054  mShortVertArray[1] = static_cast<GLshort>(y1);
1055  mShortVertArray[2] = static_cast<GLshort>(x2);
1056  mShortVertArray[3] = static_cast<GLshort>(y2);
1057 
1058  drawLineArrays(4);
1059 }
1060 
1062 {
1063  drawRectangle(rect, false);
1064 }
1065 
1067 {
1068  drawRectangle(rect, true);
1069 }
1070 
1072 {
1073  if (!mTexture)
1074  {
1076  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1077  mTexture = true;
1078  }
1079 
1080  if (!mAlpha)
1081  {
1082  mglEnable(GL_BLEND);
1083  mAlpha = true;
1084  }
1085 }
1086 
1088 {
1089  mTextureBinded = 0;
1090  if (mAlpha && !mColorAlpha)
1091  {
1092  mglDisable(GL_BLEND);
1093  mAlpha = false;
1094  }
1095  else if (!mAlpha && mColorAlpha)
1096  {
1097  mglEnable(GL_BLEND);
1098  mAlpha = true;
1099  }
1100 
1101  if (mTexture)
1102  {
1104  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1105  mTexture = false;
1106  }
1107 }
1108 
1110  const bool filled) restrict2
1111 {
1112  BLOCK_START("Graphics::drawRectangle")
1114  restoreColor();
1115 
1116  const GLshort x = static_cast<GLshort>(rect.x);
1117  const GLshort y = static_cast<GLshort>(rect.y);
1118  const GLshort width = static_cast<GLshort>(rect.width);
1119  const GLshort height = static_cast<GLshort>(rect.height);
1120  const GLshort xw = static_cast<GLshort>(rect.x + width);
1121  const GLshort yh = static_cast<GLshort>(rect.y + height);
1122 
1123  if (filled)
1124  {
1125  GLshort vert[] =
1126  {
1127  x, y,
1128  xw, y,
1129  x, yh,
1130  xw, yh
1131  };
1132 
1133  glVertexPointer(2, GL_SHORT, 0, &vert);
1134 #ifdef DEBUG_DRAW_CALLS
1135  mDrawCalls ++;
1136 #endif // DEBUG_DRAW_CALLS
1137 
1138  mglDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1139 #ifdef OPENGLERRORS
1141 #endif // OPENGLERRORS
1142  }
1143  else
1144  {
1145  GLshort vert[] =
1146  {
1147  x, y,
1148  xw, y,
1149  xw, yh,
1150  x, yh
1151  };
1152 
1153  glVertexPointer(2, GL_SHORT, 0, &vert);
1154 #ifdef DEBUG_DRAW_CALLS
1155  mDrawCalls ++;
1156 #endif // DEBUG_DRAW_CALLS
1157 
1158  mglDrawArrays(GL_LINE_LOOP, 0, 4);
1159 #ifdef OPENGLERRORS
1161 #endif // OPENGLERRORS
1162  }
1163  BLOCK_END("Graphics::drawRectangle")
1164 }
1165 
1166 void MobileOpenGLGraphics::drawNet(const int x1, const int y1,
1167  const int x2, const int y2,
1168  const int width, const int height) restrict2
1169 {
1170  unsigned int vp = 0;
1171  const unsigned int vLimit = mMaxVertices * 4;
1172 
1174  restoreColor();
1175 
1176  const GLshort xs1 = static_cast<GLshort>(x1);
1177  const GLshort xs2 = static_cast<GLshort>(x2);
1178  const GLshort ys1 = static_cast<GLshort>(y1);
1179  const GLshort ys2 = static_cast<GLshort>(y2);
1180  const int16_t width1 = CAST_S16(width);
1181  const int16_t height1 = CAST_S16(height);
1182 
1183  for (int16_t y = CAST_S16(y1); y < y2; y += height1)
1184  {
1185  mShortVertArray[vp + 0] = xs1;
1186  mShortVertArray[vp + 1] = y;
1187 
1188  mShortVertArray[vp + 2] = xs2;
1189  mShortVertArray[vp + 3] = y;
1190 
1191  vp += 4;
1192  if (vp >= vLimit)
1193  {
1194  drawLineArrays(vp);
1195  vp = 0;
1196  }
1197  }
1198 
1199  for (int16_t x = CAST_S16(x1); x < x2; x += width1)
1200  {
1201  mShortVertArray[vp + 0] = x;
1202  mShortVertArray[vp + 1] = ys1;
1203 
1204  mShortVertArray[vp + 2] = x;
1205  mShortVertArray[vp + 3] = ys2;
1206 
1207  vp += 4;
1208  if (vp >= vLimit)
1209  {
1210  drawLineArrays(vp);
1211  vp = 0;
1212  }
1213  }
1214 
1215  if (vp > 0)
1216  drawLineArrays(vp);
1217 }
1218 
1219 void MobileOpenGLGraphics::bindTexture(const GLenum target,
1220  const GLuint texture)
1221 {
1222  if (mTextureBinded != texture)
1223  {
1224  mTextureBinded = texture;
1225  mglBindTexture(target, texture);
1226  }
1227 }
1228 
1230 {
1231  glVertexPointer(2, GL_SHORT, 0, mShortVertArray);
1232  glTexCoordPointer(2, GL_FLOAT, 0, mFloatTexArray);
1233 
1234 #ifdef DEBUG_DRAW_CALLS
1235  mDrawCalls ++;
1236 #endif // DEBUG_DRAW_CALLS
1237 
1238  mglDrawArrays(GL_TRIANGLES, 0, size / 2);
1239 #ifdef OPENGLERRORS
1241 #endif // OPENGLERRORS
1242 }
1243 
1245  restrict2
1246 {
1247  glVertexPointer(2, GL_SHORT, 0, mShortVertArrayCached);
1248  glTexCoordPointer(2, GL_FLOAT, 0, mFloatTexArrayCached);
1249 
1250 #ifdef DEBUG_DRAW_CALLS
1251  mDrawCalls ++;
1252 #endif // DEBUG_DRAW_CALLS
1253 
1254  mglDrawArrays(GL_TRIANGLES, 0, size / 2);
1255 #ifdef OPENGLERRORS
1257 #endif // OPENGLERRORS
1258 }
1259 
1261  const shortVertArray,
1262  const GLfloat *restrict
1263  const floatTexArray,
1264  const int size) restrict2
1265 {
1266  glVertexPointer(2, GL_SHORT, 0, shortVertArray);
1267  glTexCoordPointer(2, GL_FLOAT, 0, floatTexArray);
1268 
1269 #ifdef DEBUG_DRAW_CALLS
1270  mDrawCalls ++;
1271 #endif // DEBUG_DRAW_CALLS
1272 
1273  mglDrawArrays(GL_TRIANGLES, 0, size / 2);
1274 #ifdef OPENGLERRORS
1276 #endif // OPENGLERRORS
1277 }
1278 
1280 {
1281  glVertexPointer(2, GL_SHORT, 0, mShortVertArray);
1282 
1283 #ifdef DEBUG_DRAW_CALLS
1284  mDrawCalls ++;
1285 #endif // DEBUG_DRAW_CALLS
1286 
1287  mglDrawArrays(GL_LINES, 0, size / 2);
1288 #ifdef OPENGLERRORS
1290 #endif // OPENGLERRORS
1291 }
1292 
1294 {
1295  GLint test[1000];
1296  logger->log("\n\n");
1297  logger->log("start opengl dump");
1298  for (int f = 0; f < 65535; f ++)
1299  {
1300  test[0] = 0;
1301  test[1] = 0;
1302  test[2] = 0;
1303  test[3] = 0;
1304  mglGetIntegerv(f, &test[0]);
1305  if (test[0] != 0 || test[1] != 0 || test[2] != 0 || test[3] != 0)
1306  {
1307  logger->log("\n%d = %d, %d, %d, %d", f,
1308  test[0], test[1], test[2], test[3]);
1309  }
1310  }
1311 }
1312 
1314 {
1315  if (!mIsByteColor && mFloatColor == alpha)
1316  return;
1317 
1318  glColor4f(1.0F, 1.0F, 1.0F, alpha);
1319  mIsByteColor = false;
1320  mFloatColor = alpha;
1321 }
1322 
1324 {
1325  if (mIsByteColor && mByteColor == mColor)
1326  return;
1327 
1328  glColor4ub(static_cast<GLubyte>(mColor.r),
1329  static_cast<GLubyte>(mColor.g),
1330  static_cast<GLubyte>(mColor.b),
1331  static_cast<GLubyte>(mColor.a));
1332  mIsByteColor = true;
1333  mByteColor = mColor;
1334 }
1335 
1336 void MobileOpenGLGraphics::drawImageRect(const int x, const int y,
1337  const int w, const int h,
1338  const ImageRect &restrict imgRect)
1339  restrict2
1340 {
1342 }
1343 
1345  const int x, const int y,
1346  const int w, const int h,
1347  const ImageRect &restrict imgRect)
1348  restrict2
1349 {
1351 }
1352 
1354 {
1355  mglClear(GL_COLOR_BUFFER_BIT |
1356  GL_DEPTH_BUFFER_BIT |
1357  GL_STENCIL_BUFFER_BIT);
1358 }
1359 
1360 #ifdef DEBUG_BIND_TEXTURE
1361 void MobileOpenGLGraphics::debugBindTexture(const Image *restrict const image)
1362  restrict2
1363 {
1364  const std::string texture = image->mIdPath;
1365  if (mOldTexture != texture)
1366  {
1367  if ((!mOldTexture.empty() || !texture.empty())
1368  && mOldTextureId != image->mGLImage)
1369  {
1370  logger->log("bind: %s (%d) to %s (%d)", mOldTexture.c_str(),
1371  mOldTextureId, texture.c_str(), image->mGLImage);
1372  }
1373  mOldTextureId = image->mGLImage;
1374  mOldTexture = texture;
1375  }
1376 }
1377 #else // DEBUG_BIND_TEXTURE
1378 
1380  image A_UNUSED) restrict2
1381 {
1382 }
1383 #endif // DEBUG_BIND_TEXTURE
1384 
1385 #endif // defined(USE_OPENGL) && !defined(__native_client__)
void drawVertexes(const OpenGLGraphicsVertexes &ogl) A_INLINE
void setMainFlags(const int w, const int h, const int scale, const int bpp, const bool fs, const bool hwaccel, const bool resize, const bool noFrame, const bool allowHighDPI)
Definition: graphics.cpp:181
int width
Definition: rect.h:218
#define mglHint(...)
Definition: mgl.hpp:86
void pushClipArea(const Rect &area)
std::string mName
Definition: graphics.h:548
SDL_Surface * mWindow
Definition: graphics.h:522
void calcImageRect(ImageVertexes *const vert, int x, int y, int w, int h, const ImageRect &imgRect) A_INLINE
RenderType mOpenGL
Definition: graphics.h:544
void drawPattern(const Image *const image, const int x, const int y, const int w, const int h)
unsigned int a
Definition: color.h:250
void calcPatternInline(ImageVertexes *const vert, const Image *const image, const int x, const int y, const int w, const int h) const A_INLINE
#define isGLNotNull(func)
Definition: mglcheck.h:27
std::vector< ImageVertexes * > ImageVertexesVector
Definition: imagevertexes.h:55
void drawRescaledPattern(const Image *const image, const int x, const int y, const int w, const int h, const int scaledWidth, const int scaledHeight)
unsigned int g
Definition: color.h:239
Definition: rect.h:72
void drawPatternInline(const Image *const image, const int x, const int y, const int w, const int h) A_INLINE
#define BLOCK_START(name)
Definition: perfomance.h:78
void calcPattern(ImageVertexes *const vert, const Image *const image, const int x, const int y, const int w, const int h) const
const Image * image
Definition: imagevertexes.h:47
#define mglBindTexture(...)
Definition: mgl.hpp:92
unsigned int vertexBufSize
static void bindTexture(const GLenum target, const GLuint texture)
void drawNet(const int x1, const int y1, const int x2, const int y2, const int width, const int height)
void calcTileCollection(ImageCollection *const vertCol, const Image *const image, int x, int y)
#define BLOCK_END(name)
Definition: perfomance.h:79
void drawRescaledImage(const Image *const image, int dstX, int dstY, const int desiredWidth, const int desiredHeight)
int yOffset
Definition: cliprect.h:126
virtual void popClipArea()
Definition: graphics.cpp:738
#define mglScissor(...)
Definition: mgl.hpp:88
static void drawRescaledQuad(const Image *const image, const int srcX, const int srcY, const int dstX, const int dstY, const int width, const int height, const int desiredWidth, const int desiredHeight) A_INLINE
void copyImage(const Image *const image, int dstX, int dstY)
#define A_NONNULL(...)
Definition: localconsts.h:179
ImageVertexesVector::const_iterator ImageCollectionCIter
Definition: imagevertexes.h:57
void drawImage(const Image *const image, int dstX, int dstY)
Logger * logger
Definition: logger.cpp:88
Color mColor
Definition: graphics.h:552
#define mglClear(...)
Definition: mgl.hpp:96
int x
Definition: rect.h:208
void drawRectangle(const Rect &rect)
void drawLine(int x1, int y1, int x2, int y2)
unsigned int b
Definition: color.h:244
void initArrays(const int vertCount)
void calcTileVertexesInline(ImageVertexes *const vert, const Image *const image, int x, int y) const A_INLINE
bool setVideoMode(const int w, const int h, const int scalle, const int bpp, const bool fs, const bool hwaccel, const bool resize, const bool noFrame, const bool allowHighDPI)
static void drawQuad(const Image *const image, const int srcX, const int srcY, const int dstX, const int dstY, const int width, const int height) A_INLINE
int xOffset
Definition: cliprect.h:121
int y
Definition: rect.h:213
bool mAlpha
Definition: graphics.h:537
#define nullptr
Definition: localconsts.h:44
#define mglDrawArrays(...)
Definition: mgl.hpp:82
float mAlpha
Definition: image.h:212
int height
Definition: rect.h:223
void debugBindTexture(const Image *const image)
void drawTriangleArrayfsCached(const int size) A_INLINE
#define FUNC_BLOCK(name, id)
Definition: perfomance.h:80
SDL_Rect mRect
Definition: graphics.h:542
void setOpenGLFlags()
Definition: graphics.cpp:747
#define vertFill2D(tVar, vVar, x1, y1, x2, y2, dstX, dstY, w, h)
GLuint mGLImage
Definition: image.h:182
void setColorAlpha(const float alpha) A_INLINE
#define A_UNUSED
Definition: localconsts.h:171
static void logError()
void drawImageInline(const Image *const image, int dstX, int dstY) A_INLINE
void drawPatternCached(const Image *const image, const int x, const int y, const int w, const int h)
#define mglGetIntegerv(...)
Definition: mgl.hpp:94
int mScale
Definition: graphics.h:551
void drawPoint(int x, int y)
MStack< ClipRect > mClipStack
Definition: graphics.h:520
void calcTileVertexes(ImageVertexes *const vert, const Image *const image, int x, int y) const
Definition: image.h:61
void drawLineArrays(const int size) A_INLINE
virtual void pushClipArea(const Rect &area)
Definition: graphics.cpp:676
#define restrict
Definition: localconsts.h:176
void calcWindow(ImageCollection *const vertCol, const int x, const int y, const int w, const int h, const ImageRect &imgRect)
#define CAST_S16
Definition: cast.h:27
void drawTileVertexes(const ImageVertexes *const vert)
#define mglDisable(...)
Definition: mgl.hpp:84
T & top() const
Definition: mstack.h:72
void log(const char *const log_text,...)
Definition: logger.cpp:264
OpenGLGraphicsVertexes ogl
Definition: imagevertexes.h:49
void fillRectangle(const Rect &rect)
bool empty() const
Definition: mstack.h:87
void drawImageCached(const Image *const image, int x, int y)
GraphicsManager graphicsManager
#define restrict2
Definition: localconsts.h:177
bool setOpenGLMode()
Definition: graphics.cpp:282
#define mglEnable(...)
Definition: mgl.hpp:90
void drawTriangleArrayfs(const GLshort *const shortVertArray, const GLfloat *const floatTexArray, const int size) A_INLINE
void drawTileCollection(const ImageCollection *const vertCol)
unsigned int r
Definition: color.h:234
void drawImageRect(int x, int y, int w, int h, const ImageRect &imgRect)