Otclient  14/8/2020
graphics.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2020 OTClient <https://github.com/edubart/otclient>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 #include "fontmanager.h"
24 
25 #if OPENGL_ES==2
26 #include "ogl/painterogl2.h"
27 #elif OPENGL_ES==1
28 #include "ogl/painterogl1.h"
29 #else
30 #include "ogl/painterogl1.h"
31 #include "ogl/painterogl2.h"
32 #endif
33 
34 #if defined(WIN32) && defined(DIRECTX)
35 #include "dx/painterdx9.h"
36 #endif
37 
40 #include "texturemanager.h"
41 #include "framebuffermanager.h"
43 
45 
47 {
48  m_maxTextureSize = -1;
49  m_selectedPainterEngine = Painter_Any;
50 }
51 
53 {
54  g_logger.info(stdext::format("GPU %s", glGetString(GL_RENDERER)));
55  g_logger.info(stdext::format("OpenGL %s", glGetString(GL_VERSION)));
56 
57 #if defined(WIN32) && defined(DIRECTX)
58  g_painterDX9 = new PainterDX9;
59 #endif
60 
61 #if OPENGL_ES==2
63 #elif OPENGL_ES==1
65 #else
66  // init GL extensions
67  GLenum err = glewInit();
68  if(err != GLEW_OK)
69  g_logger.fatal(stdext::format("Unable to init GLEW: %s", glewGetErrorString(err)));
70 
71  // overwrite framebuffer API if needed
72  if(GLEW_EXT_framebuffer_object && !GLEW_ARB_framebuffer_object) {
73  glGenFramebuffers = glGenFramebuffersEXT;
74  glDeleteFramebuffers = glDeleteFramebuffersEXT;
75  glBindFramebuffer = glBindFramebufferEXT;
76  glFramebufferTexture2D = glFramebufferTexture2DEXT;
77  glCheckFramebufferStatus = glCheckFramebufferStatusEXT;
78  glGenerateMipmap = glGenerateMipmapEXT;
79  }
80 
81  // opengl 1 is always supported
83 
84  // opengl 2 is only supported in newer hardware
85  if(GLEW_VERSION_2_0)
87 #endif
88 
89  // blending is always enabled
90  glEnable(GL_BLEND);
91 
92  // determine max texture size
93  int maxTextureSize = 0;
94  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
95  if(m_maxTextureSize == -1 || m_maxTextureSize > maxTextureSize)
96  m_maxTextureSize = maxTextureSize;
97 
98  if(Size(m_maxTextureSize,m_maxTextureSize) < g_window.getDisplaySize())
99  m_cacheBackbuffer = false;
100 
101  m_alphaBits = 0;
102  glGetIntegerv(GL_ALPHA_BITS, &m_alphaBits);
103 
104  m_ok = true;
105 
106  selectPainterEngine(m_prefferedPainterEngine);
107 
108  g_textures.init();
110 }
111 
113 {
114  g_fonts.terminate();
117 
118 #ifdef PAINTER_OGL2
119  if(g_painterOGL2) {
120  delete g_painterOGL2;
121  g_painterOGL2 = nullptr;
122  }
123 #endif
124 
125 #ifdef PAINTER_OGL1
126  if(g_painterOGL1) {
127  delete g_painterOGL1;
128  g_painterOGL1 = nullptr;
129  }
130 #endif
131 
132  g_painter = nullptr;
133 
134  m_ok = false;
135 }
136 
137 bool Graphics::parseOption(const std::string& option)
138 {
139  if(option == "-no-draw-arrays")
140  m_useDrawArrays = false;
141  else if(option == "-no-fbos")
142  m_useFBO = false;
143  else if(option == "-no-mipmaps")
144  m_useMipmaps = false;
145  else if(option == "-no-hardware-mipmaps")
146  m_useHardwareMipmaps = false;
147  else if(option == "-no-smooth")
148  m_useBilinearFiltering = false;
149  else if(option == "-hardware-buffers")
150  m_useHardwareBuffers = true;
151  else if(option == "-no-non-power-of-two-textures")
152  m_useNonPowerOfTwoTextures = false;
153  else if(option == "-no-clamp-to-edge")
154  m_useClampToEdge = false;
155  else if(option == "-no-backbuffer-cache")
156  m_cacheBackbuffer = false;
157  else if(option == "-opengl1")
158  m_prefferedPainterEngine = Painter_OpenGL1;
159  else if(option == "-opengl2")
160  m_prefferedPainterEngine = Painter_OpenGL2;
161  else
162  return false;
163  return true;
164 }
165 
167 {
168 #if defined(WIN32) && defined(DIRECTX)
169  if(g_painterDX9 && painterEngine == Painter_DirectX9)
170  return true;
171 #endif
172 
173 #ifdef PAINTER_OGL2
174  if(g_painterOGL2 && painterEngine == Painter_OpenGL2)
175  return true;
176 #endif
177 
178 #ifdef PAINTER_OGL1
179  if(g_painterOGL1 && painterEngine == Painter_OpenGL1)
180  return true;
181 #endif
182  return false;
183 }
184 
186 {
187  Painter *painter = nullptr;
188  Painter *fallbackPainter = nullptr;
189  PainterEngine fallbackPainterEngine = Painter_Any;
190 
191 #ifdef PAINTER_DX9
192  // use this to force directx if its enabled (avoid changes in options module, etc, will be removed)
193  painterEngine = Painter_DirectX9;
194 
195  // always prefer DirectX9 on Windows
196  if(g_painterDX9) {
197  if(!painter && (painterEngine == Painter_DirectX9 || painterEngine == Painter_Any)) {
198  m_selectedPainterEngine = Painter_DirectX9;
199  painter = g_painterDX9;
200  }
201  fallbackPainter = g_painterDX9;
202  fallbackPainterEngine = Painter_DirectX9;
203  }
204 #endif
205 
206 #ifdef PAINTER_OGL2
207  // always prefer OpenGL 2 over OpenGL 1
208  if(g_painterOGL2) {
209  if(!painter && (painterEngine == Painter_OpenGL2 || painterEngine == Painter_Any)) {
210  m_selectedPainterEngine = Painter_OpenGL2;
211  painter = g_painterOGL2;
212  }
213  fallbackPainter = g_painterOGL2;
214  fallbackPainterEngine = Painter_OpenGL2;
215  }
216 #endif
217 
218 #ifdef PAINTER_OGL1
219  // fallback to OpenGL 1 in older hardwares
220  if(g_painterOGL1) {
221  if(!painter && (painterEngine == Painter_OpenGL1 || painterEngine == Painter_Any)) {
222  m_selectedPainterEngine = Painter_OpenGL1;
223  painter = g_painterOGL1;
224  }
225  fallbackPainter = g_painterOGL1;
226  fallbackPainterEngine = Painter_OpenGL1;
227  }
228 #endif
229 
230  if(!painter) {
231  painter = fallbackPainter;
232  m_selectedPainterEngine = fallbackPainterEngine;
233  }
234 
235  // switch painters GL state
236  if(painter) {
237  if(painter != g_painter) {
238  if(g_painter)
239  g_painter->unbind();
240  painter->bind();
241  g_painter = painter;
242  }
243 
244  if(painterEngine == Painter_Any)
245  return true;
246  } else
247  g_logger.fatal("Neither OpenGL 1.0 nor OpenGL 2.0 painter engine is supported by your platform, "
248  "try updating your graphics drivers or your hardware and then run again.");
249 
250  return m_selectedPainterEngine == painterEngine;
251 }
252 
253 void Graphics::resize(const Size& size)
254 {
255  m_viewportSize = size;
256 #ifdef PAINTER_OGL1
257  if(g_painterOGL1)
259 #endif
260 
261 #ifdef PAINTER_OGL2
262  if(g_painterOGL2)
264 #endif
265 }
266 
268 {
269 #ifdef OPENGL_ES
270  return true;
271 #else
272  // glDrawArrays is supported by OpenGL 1.1
273  if(!GLEW_VERSION_1_1)
274  return false;
275  return m_useDrawArrays;
276 #endif
277 }
278 
280 {
281 #if OPENGL_ES==2
282  return true;
283 #elif OPENGL_ES==1
284  return false;
285 #else
286  // fragment and vertex programs are supported by OpenGL 2.0
287  if(GLEW_ARB_vertex_program && GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
288  return true;
289  return false;
290 #endif
291 }
292 
294 {
295 #if OPENGL_ES==2
296  return m_useFBO;
297 #elif OPENGL_ES==1
298  return false;
299 #else
300  // FBOs are supported by OpenGL 3.0
301  // or by OpenGL 2.0 with EXT_framebuffer_object (most of the OpenGL 2.0 implementations have this extension)
302  if(!GLEW_ARB_framebuffer_object || !GLEW_EXT_framebuffer_object)
303  return false;
304  return m_useFBO;
305 #endif
306 }
307 
309 {
310  // bilinear filtering is supported by any OpenGL implementation
311  return m_useBilinearFiltering;
312 }
313 
315 {
316 #if OPENGL_ES==2
317  return m_useHardwareBuffers;
318 #elif OPENGL_ES==1
319  // OpenGL ES 1.1 supports it but OpenGL ES 1.0 not
320  return false;
321 #else
322  // vertex buffer objects is supported by OpenGL 1.5
323  if(!GLEW_ARB_vertex_buffer_object)
324  return false;
325 #endif
326  return m_useHardwareBuffers;
327 }
328 
330 {
331 #if OPENGL_ES==2
332  return m_useNonPowerOfTwoTextures;
333 #elif OPENGL_ES==1
334  return false;
335 #else
336  // power of two textures is supported by OpenGL 2.0
337  if(!GLEW_ARB_texture_non_power_of_two)
338  return false;
339  return m_useNonPowerOfTwoTextures;
340 #endif
341 }
342 
344 {
345  // mipmaps is supported by any OpenGL implementation
346  return m_useMipmaps;
347 }
348 
350 {
351 #if OPENGL_ES==2
352  return m_useHardwareMipmaps;
353 #elif OPENGL_ES==1
354  return false;
355 #else
356  // glGenerateMipmap is supported when FBOs are
357  if(!GLEW_ARB_framebuffer_object || !GLEW_EXT_framebuffer_object)
358  return false;
359  return m_useHardwareMipmaps;
360 #endif
361 }
362 
364 {
365 #ifdef OPENGL_ES
366  return m_useClampToEdge;
367 #else
368  // GL_CLAMP_TO_EDGE is present in OpenGL 1.2
369  if(!GLEW_VERSION_1_2)
370  return false;
371  return m_useClampToEdge;
372 #endif
373 }
374 
376 {
377 #if OPENGL_ES==2
378  return true;
379 #elif OPENGL_ES==1
380  return false;
381 #else
382  if(!GLEW_VERSION_1_4)
383  return false;
384  return true;
385 #endif
386 }
387 
389 {
390 #if OPENGL_ES==2
391  return false;
392 #elif OPENGL_ES==1
393  return false;
394 #else
395  if(!GLEW_VERSION_1_4)
396  return false;
397  return true;
398 #endif
399 }
400 
402 {
403  if(!m_alphaBits)
404  return false;
405 #if OPENGL_ES==2
406  return m_cacheBackbuffer;
407 #elif OPENGL_ES==1
408  return false;
409 #else
410  if(!GLEW_VERSION_1_4)
411  return false;
412  return m_cacheBackbuffer;
413 #endif
414 }
415 
417 {
418 #if OPENGL_ES==2
419  return false;
420 #elif OPENGL_ES==1
421  return false;
422 #else
423  if(!GLEW_VERSION_1_2)
424  return true;
425  return false;
426 #endif
427 }
Graphics::selectPainterEngine
bool selectPainterEngine(PainterEngine painterEngine)
Definition: graphics.cpp:185
graphics.h
TextureManager::init
void init()
Definition: texturemanager.cpp:35
Painter::unbind
virtual void unbind()
Definition: painter.h:56
Painter::bind
virtual void bind()
Definition: painter.h:55
Graphics::canUseBlendFuncSeparate
bool canUseBlendFuncSeparate()
Definition: graphics.cpp:375
platformwindow.h
Graphics::Graphics
Graphics()
Definition: graphics.cpp:46
Graphics::Painter_DirectX9
@ Painter_DirectX9
Definition: graphics.h:39
Graphics::Painter_OpenGL1
@ Painter_OpenGL1
Definition: graphics.h:37
Graphics::canUseBilinearFiltering
bool canUseBilinearFiltering()
Definition: graphics.cpp:308
Graphics::isPainterEngineAvailable
bool isPainterEngineAvailable(PainterEngine painterEngine)
Definition: graphics.cpp:166
g_fonts
FontManager g_fonts
Definition: fontmanager.cpp:29
Graphics::canUseBlendEquation
bool canUseBlendEquation()
Definition: graphics.cpp:388
Graphics::canUseDrawArrays
bool canUseDrawArrays()
Definition: graphics.cpp:267
texturemanager.h
Graphics::hasScissorBug
bool hasScissorBug()
Definition: graphics.cpp:416
PainterOGL::setResolution
void setResolution(const Size &resolution)
Definition: painterogl.cpp:173
stdext::format
std::string format()
Definition: format.h:82
Graphics
Definition: graphics.h:30
Graphics::canCacheBackbuffer
bool canCacheBackbuffer()
Definition: graphics.cpp:401
Graphics::canUseClampToEdge
bool canUseClampToEdge()
Definition: graphics.cpp:363
g_painterOGL1
PainterOGL1 * g_painterOGL1
Definition: painterogl1.cpp:28
framebuffermanager.h
PainterOGL1
Definition: painterogl1.h:36
Logger::fatal
void fatal(const std::string &what)
Definition: logger.h:55
g_window
PlatformWindow & g_window
Definition: platformwindow.cpp:37
Graphics::PainterEngine
PainterEngine
Definition: graphics.h:35
Graphics::canUseHardwareMipmaps
bool canUseHardwareMipmaps()
Definition: graphics.cpp:349
g_logger
Logger g_logger
Definition: logger.cpp:35
Graphics::canUseFBO
bool canUseFBO()
Definition: graphics.cpp:293
FrameBufferManager::terminate
void terminate()
Definition: framebuffermanager.cpp:33
Graphics::resize
void resize(const Size &size)
Definition: graphics.cpp:253
Graphics::canUseShaders
bool canUseShaders()
Definition: graphics.cpp:279
Graphics::canUseHardwareBuffers
bool canUseHardwareBuffers()
Definition: graphics.cpp:314
Graphics::terminate
void terminate()
Definition: graphics.cpp:112
Painter
Definition: painter.h:31
g_painterOGL2
PainterOGL2 * g_painterOGL2
Definition: painterogl2.cpp:27
Size
TSize< int > Size
Definition: size.h:107
g_graphics
Graphics g_graphics
Definition: graphics.cpp:44
Graphics::canUseMipmaps
bool canUseMipmaps()
Definition: graphics.cpp:343
Graphics::parseOption
bool parseOption(const std::string &option)
Definition: graphics.cpp:137
PainterOGL2
Definition: painterogl2.h:35
FontManager::terminate
void terminate()
Definition: fontmanager.cpp:36
FrameBufferManager::init
void init()
Definition: framebuffermanager.cpp:28
fontmanager.h
Graphics::Painter_Any
@ Painter_Any
Definition: graphics.h:36
Graphics::canUseNonPowerOfTwoTextures
bool canUseNonPowerOfTwoTextures()
Definition: graphics.cpp:329
texture.h
Graphics::Painter_OpenGL2
@ Painter_OpenGL2
Definition: graphics.h:38
g_painter
Painter * g_painter
Definition: painter.cpp:28
PlatformWindow::getDisplaySize
virtual Size getDisplaySize()=0
painterogl1.h
g_textures
TextureManager g_textures
Definition: texturemanager.cpp:33
Graphics::init
void init()
Definition: graphics.cpp:52
g_framebuffers
FrameBufferManager g_framebuffers
Definition: framebuffermanager.cpp:26
TSize< int >
TextureManager::terminate
void terminate()
Definition: texturemanager.cpp:40
painterogl2.h
Logger::info
void info(const std::string &what)
Definition: logger.h:52