3
* Copyright (C) 2004-2009 The Mana World Development Team
4
* Copyright (C) 2009-2010 The Mana Developers
5
* Copyright (C) 2011-2013 The ManaPlus Developers
7
* This file is part of The ManaPlus Client.
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
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.
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/>.
23
#include "render/graphics.h"
27
#include "configuration.h"
28
#include "graphicsmanager.h"
29
#include "graphicsvertexes.h"
32
#include "resources/imagehelper.h"
33
#include "resources/openglimagehelper.h"
35
#include <guichan/sdl/sdlpixel.hpp>
39
#include <OpenGL/OpenGL.h>
46
#ifndef GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX
47
#define GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049
51
Graphics::Graphics() :
70
mOpenGL(RENDER_SOFTWARE),
91
SDL_DestroyRenderer(mRenderer);
97
SDL_GL_DeleteContext(mGLContext);
104
void Graphics::setSync(const bool sync)
109
void Graphics::setMainFlags(const int w, const int h, const int bpp,
110
const bool fs, const bool hwaccel,
111
const bool resize, const bool noFrame)
113
logger->log("graphics backend: %s", getName().c_str());
114
logger->log("Setting video mode %dx%d %s",
115
w, h, fs ? "fullscreen" : "windowed");
122
mEnableResize = resize;
126
int Graphics::getOpenGLFlags() const
131
int displayFlags = SDL_WINDOW_OPENGL;
133
displayFlags |= SDL_WINDOW_FULLSCREEN;
135
int displayFlags = SDL_ANYFORMAT | SDL_OPENGL;
140
displayFlags |= SDL_FULLSCREEN;
144
// Resizing currently not supported on Windows, where it would require
145
// reuploading all textures.
148
displayFlags |= SDL_RESIZABLE;
153
displayFlags |= SDL_NOFRAME;
161
bool Graphics::setOpenGLMode()
164
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
165
if (!(mWindow = graphicsManager.createWindow(mWidth, mHeight,
166
mBpp, getOpenGLFlags())))
176
SDL_GetWindowSize(mWindow, &w1, &h1);
180
mGLContext = SDL_GL_CreateContext(mWindow);
184
mRect.w = static_cast<uint16_t>(mWindow->w);
185
mRect.h = static_cast<uint16_t>(mWindow->h);
192
CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &VBL);
196
graphicsManager.setGLVersion();
197
graphicsManager.logVersion();
200
glViewport(0, 0, mWidth, mHeight);
201
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
202
int gotDoubleBuffer = 0;
203
SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &gotDoubleBuffer);
204
logger->log("Using OpenGL %s double buffering.",
205
(gotDoubleBuffer ? "with" : "without"));
207
graphicsManager.initOpenGL();
209
graphicsManager.updateTextureFormat();
213
bool rectTex = graphicsManager.supportExtension(
214
"GL_ARB_texture_rectangle");
215
if (rectTex && OpenGLImageHelper::getInternalTextureType() == 4
216
&& getOpenGL() != 3 && config.getBoolValue("rectangulartextures")
217
&& !graphicsManager.isUseTextureSampler())
219
logger->log1("using GL_ARB_texture_rectangle");
220
OpenGLImageHelper::mTextureType = GL_TEXTURE_RECTANGLE_ARB;
221
glEnable(GL_TEXTURE_RECTANGLE_ARB);
222
glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &texSize);
223
OpenGLImageHelper::mTextureSize = texSize;
224
logger->log("OpenGL texture size: %d pixels (rectangle textures)",
225
OpenGLImageHelper::mTextureSize);
229
OpenGLImageHelper::mTextureType = GL_TEXTURE_2D;
230
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
231
OpenGLImageHelper::mTextureSize = texSize;
232
logger->log("OpenGL texture size: %d pixels",
233
OpenGLImageHelper::mTextureSize);
242
int Graphics::getSoftwareFlags() const
245
int displayFlags = SDL_WINDOW_SHOWN;
247
int displayFlags = SDL_ANYFORMAT;
250
displayFlags |= SDL_HWSURFACE | SDL_DOUBLEBUF;
252
displayFlags |= SDL_SWSURFACE;
256
displayFlags |= SDL_FULLSCREEN;
257
else if (mEnableResize)
258
displayFlags |= SDL_RESIZABLE;
261
displayFlags |= SDL_NOFRAME;
266
void Graphics::updateMemoryInfo()
272
if (graphicsManager.supportExtension("GL_NVX_gpu_memory_info"))
274
glGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX,
276
logger->log("free video memory: %d", mStartFreeMem);
281
int Graphics::getMemoryUsage() const
287
if (graphicsManager.supportExtension("GL_NVX_gpu_memory_info"))
290
glGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX,
292
return mStartFreeMem - val;
299
void Graphics::dumpRendererInfo(const char *const str,
300
const SDL_RendererInfo &info)
302
logger->log(str, info.name);
303
logger->log("flags:");
304
if (info.flags & SDL_RENDERER_SOFTWARE)
305
logger->log(" software");
306
if (info.flags & SDL_RENDERER_ACCELERATED)
307
logger->log(" accelerated");
308
if (info.flags & SDL_RENDERER_PRESENTVSYNC)
309
logger->log(" vsync");
310
if (info.flags & SDL_RENDERER_TARGETTEXTURE)
311
logger->log(" texture target");
315
bool Graphics::videoInfo()
317
logger->log("SDL video info");
319
logger->log("Using video driver: %s", SDL_GetCurrentVideoDriver());
323
SDL_RendererInfo info;
324
SDL_GetRendererInfo(mRenderer, &info);
325
dumpRendererInfo("Current SDL renderer name: %s", info);
327
const int num = SDL_GetNumRenderDrivers();
328
logger->log("Known renderers");
329
for (int f = 0; f < num; f ++)
331
if (!SDL_GetRenderDriverInfo(f, &info))
332
dumpRendererInfo("renderer name: %s", info);
336
char videoDriverName[65];
337
if (SDL_VideoDriverName(videoDriverName, 64))
338
logger->log("Using video driver: %s", videoDriverName);
340
logger->log1("Using video driver: unknown");
341
mDoubleBuffer = ((mWindow->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF);
342
logger->log("Double buffer mode: %s", mDoubleBuffer ? "yes" : "no");
344
imageHelper->dumpSurfaceFormat(mWindow);
346
const SDL_VideoInfo *const vi = SDL_GetVideoInfo();
350
logger->log("Possible to create hardware surfaces: %s",
351
((vi->hw_available) ? "yes" : "no"));
352
logger->log("Window manager available: %s",
353
((vi->wm_available) ? "yes" : "no"));
354
logger->log("Accelerated hardware to hardware blits: %s",
355
((vi->blit_hw) ? "yes" : "no"));
356
logger->log("Accelerated hardware to hardware colorkey blits: %s",
357
((vi->blit_hw_CC) ? "yes" : "no"));
358
logger->log("Accelerated hardware to hardware alpha blits: %s",
359
((vi->blit_hw_A) ? "yes" : "no"));
360
logger->log("Accelerated software to hardware blits: %s",
361
((vi->blit_sw) ? "yes" : "no"));
362
logger->log("Accelerated software to hardware colorkey blits: %s",
363
((vi->blit_sw_CC) ? "yes" : "no"));
364
logger->log("Accelerated software to hardware alpha blits: %s",
365
((vi->blit_sw_A) ? "yes" : "no"));
366
logger->log("Accelerated color fills: %s",
367
((vi->blit_fill) ? "yes" : "no"));
373
bool Graphics::setFullscreen(const bool fs)
375
if (mFullscreen == fs)
378
return setVideoMode(mWidth, mHeight, mBpp, fs, mHWAccel,
379
mEnableResize, mNoFrame);
382
bool Graphics::resizeScreen(const int width, const int height)
384
if (mWidth == width && mHeight == height)
396
// +++ probably this way will not work in windows/mac
398
glViewport(0, 0, mWidth, mHeight);
399
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
401
// +++ need impliment resize in soft mode
408
const int prevWidth = mWidth;
409
const int prevHeight = mHeight;
413
const bool success = setVideoMode(width, height, mBpp,
414
mFullscreen, mHWAccel, mEnableResize, mNoFrame);
416
// If it didn't work, try to restore the previous size. If that didn't
417
// work either, bail out (but then we're in deep trouble).
420
if (!setVideoMode(prevWidth, prevHeight, mBpp,
421
mFullscreen, mHWAccel, mEnableResize, mNoFrame))
433
int Graphics::getWidth() const
438
int Graphics::getHeight() const
443
bool Graphics::drawImage(const Image *image, int x, int y)
447
return drawImage2(image, 0, 0, x, y,
448
image->mBounds.w, image->mBounds.h, false);
456
void Graphics::drawImageRect(const int x, const int y,
457
const int w, const int h,
458
const Image *const topLeft,
459
const Image *const topRight,
460
const Image *const bottomLeft,
461
const Image *const bottomRight,
462
const Image *const top,
463
const Image *const right,
464
const Image *const bottom,
465
const Image *const left,
466
const Image *const center)
468
BLOCK_START("Graphics::drawImageRect")
469
const bool drawMain = center && topLeft && topRight
470
&& bottomLeft && bottomRight;
472
// Draw the center area
473
if (center && drawMain)
475
const int tlw = topLeft->getWidth();
476
const int tlh = topLeft->getHeight();
477
drawImagePattern(center, tlw + x, tlh + y,
478
w - tlw - topRight->getWidth(),
479
h - tlh - bottomLeft->getHeight());
483
if (top && left && bottom && right)
485
const int lw = left->getWidth();
486
const int rw = right->getWidth();
487
const int th = top->getHeight();
488
const int bh = bottom->getHeight();
489
drawImagePattern(top, x + lw, y, w - lw - rw, th);
490
drawImagePattern(bottom, x + lw, h - bh + y, w - lw - rw, bh);
491
drawImagePattern(left, x, y + th, lw, h - th - bh);
492
drawImagePattern(right, x + w - rw, th + y, rw, h - th - bh);
497
drawImage(topLeft, x, y);
498
drawImage(topRight, x + w - topRight->getWidth(), y);
499
drawImage(bottomLeft, x, h - bottomLeft->getHeight() + y);
500
drawImage(bottomRight,
501
x + w - bottomRight->getWidth(),
502
y + h - bottomRight->getHeight());
504
BLOCK_END("Graphics::drawImageRect")
507
void Graphics::drawImageRect(int x, int y, int w, int h,
508
const ImageRect &imgRect)
510
drawImageRect(x, y, w, h,
511
imgRect.grid[0], imgRect.grid[2], imgRect.grid[6], imgRect.grid[8],
512
imgRect.grid[1], imgRect.grid[5], imgRect.grid[7], imgRect.grid[3],
516
bool Graphics::drawNet(const int x1, const int y1, const int x2, const int y2,
517
const int width, const int height)
519
for (int y = y1; y < y2; y += height)
520
drawLine(x1, y, x2, y);
522
for (int x = x1; x < x2; x += width)
523
drawLine(x, y1, x, y2);
528
bool Graphics::calcImageRect(ImageVertexes *const vert,
529
const int x, const int y,
530
const int w, const int h,
531
const Image *const topLeft,
532
const Image *const topRight,
533
const Image *const bottomLeft,
534
const Image *const bottomRight,
535
const Image *const top,
536
const Image *const right,
537
const Image *const bottom,
538
const Image *const left,
539
const Image *const center)
544
BLOCK_START("Graphics::calcImageRect")
545
const bool drawMain = center && topLeft && topRight
546
&& bottomLeft && bottomRight;
548
// pushClipArea(gcn::Rectangle(x, y, w, h));
550
// Draw the center area
551
if (center && drawMain)
553
const int tlw = topLeft->getWidth();
554
const int tlh = topLeft->getHeight();
555
calcImagePattern(vert, center, tlw + x, tlh + y,
556
w - tlw - topRight->getWidth(),
557
h - tlh - bottomLeft->getHeight());
560
if (top && left && bottom && right)
562
const int lw = left->getWidth();
563
const int rw = right->getWidth();
564
const int th = top->getHeight();
565
const int bh = bottom->getHeight();
566
calcImagePattern(vert, top, x + lw, y, w - lw - rw, th);
567
calcImagePattern(vert, bottom, x + lw, y + h - bh, w - lw - rw, bh);
568
calcImagePattern(vert, left, x, y + th, lw, h - th - bh);
569
calcImagePattern(vert, right, x + w - rw, y + th, rw, h - th - bh);
572
calcTile(vert, topLeft, x, y);
574
calcTile(vert, topRight, x + w - topRight->getWidth(), y);
576
calcTile(vert, bottomLeft, x, y + h - bottomLeft->getHeight());
579
calcTile(vert, bottomRight, x + w - bottomRight->getWidth(),
580
y + h - bottomRight->getHeight());
584
BLOCK_END("Graphics::calcImageRect")
588
void Graphics::setWindowSize(const int width A_UNUSED,
589
const int height A_UNUSED)
592
SDL_SetWindowSize(mWindow, width, height);