~ubuntu-branches/ubuntu/trusty/manaplus/trusty-proposed

« back to all changes in this revision

Viewing changes to src/render/graphics.cpp

  • Committer: Package Import Robot
  • Author(s): Patrick Matthäi
  • Date: 2013-09-17 10:35:51 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20130917103551-az7p3nz9jgxwqjfn
Tags: 1.3.9.15-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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-2013  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
#include "render/graphics.h"
 
24
 
 
25
#include "main.h"
 
26
 
 
27
#include "configuration.h"
 
28
#include "graphicsmanager.h"
 
29
#include "graphicsvertexes.h"
 
30
#include "logger.h"
 
31
 
 
32
#include "resources/imagehelper.h"
 
33
#include "resources/openglimagehelper.h"
 
34
 
 
35
#include <guichan/sdl/sdlpixel.hpp>
 
36
 
 
37
#ifdef USE_OPENGL
 
38
#ifdef __APPLE__
 
39
#include <OpenGL/OpenGL.h>
 
40
#endif
 
41
#endif
 
42
 
 
43
#include "debug.h"
 
44
 
 
45
#ifdef USE_OPENGL
 
46
#ifndef GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX
 
47
#define GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049
 
48
#endif
 
49
#endif
 
50
 
 
51
Graphics::Graphics() :
 
52
    gcn::Graphics(),
 
53
    mWidth(0),
 
54
    mHeight(0),
 
55
    mWindow(nullptr),
 
56
#ifdef USE_SDL2
 
57
    mRenderer(nullptr),
 
58
#ifdef USE_OPENGL
 
59
    mGLContext(nullptr),
 
60
#endif
 
61
#endif
 
62
    mBpp(0),
 
63
    mAlpha(false),
 
64
    mFullscreen(false),
 
65
    mHWAccel(false),
 
66
    mRedraw(false),
 
67
    mDoubleBuffer(false),
 
68
    mRect(),
 
69
    mSecure(false),
 
70
    mOpenGL(RENDER_SOFTWARE),
 
71
    mEnableResize(false),
 
72
    mNoFrame(false),
 
73
    mName("Unknown"),
 
74
    mStartFreeMem(0),
 
75
    mSync(false),
 
76
    mColor(),
 
77
    mColor2()
 
78
{
 
79
    mRect.x = 0;
 
80
    mRect.y = 0;
 
81
    mRect.w = 0;
 
82
    mRect.h = 0;
 
83
}
 
84
 
 
85
Graphics::~Graphics()
 
86
{
 
87
    _endDraw();
 
88
#ifdef USE_SDL2
 
89
    if (mRenderer)
 
90
    {
 
91
        SDL_DestroyRenderer(mRenderer);
 
92
        mRenderer = nullptr;
 
93
    }
 
94
#ifdef USE_OPENGL
 
95
    if (mGLContext)
 
96
    {
 
97
        SDL_GL_DeleteContext(mGLContext);
 
98
        mGLContext = 0;
 
99
    }
 
100
#endif
 
101
#endif
 
102
}
 
103
 
 
104
void Graphics::setSync(const bool sync)
 
105
{
 
106
    mSync = sync;
 
107
}
 
108
 
 
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)
 
112
{
 
113
    logger->log("graphics backend: %s", getName().c_str());
 
114
    logger->log("Setting video mode %dx%d %s",
 
115
            w, h, fs ? "fullscreen" : "windowed");
 
116
 
 
117
    mWidth = w;
 
118
    mHeight = h;
 
119
    mBpp = bpp;
 
120
    mFullscreen = fs;
 
121
    mHWAccel = hwaccel;
 
122
    mEnableResize = resize;
 
123
    mNoFrame = noFrame;
 
124
}
 
125
 
 
126
int Graphics::getOpenGLFlags() const
 
127
{
 
128
#ifdef USE_OPENGL
 
129
 
 
130
#ifdef USE_SDL2
 
131
    int displayFlags = SDL_WINDOW_OPENGL;
 
132
    if (mFullscreen)
 
133
        displayFlags |= SDL_WINDOW_FULLSCREEN;
 
134
#else
 
135
    int displayFlags = SDL_ANYFORMAT | SDL_OPENGL;
 
136
#endif  // USE_SDL2
 
137
 
 
138
    if (mFullscreen)
 
139
    {
 
140
        displayFlags |= SDL_FULLSCREEN;
 
141
    }
 
142
    else
 
143
    {
 
144
        // Resizing currently not supported on Windows, where it would require
 
145
        // reuploading all textures.
 
146
#if !defined(_WIN32)
 
147
        if (mEnableResize)
 
148
            displayFlags |= SDL_RESIZABLE;
 
149
#endif
 
150
    }
 
151
 
 
152
    if (mNoFrame)
 
153
        displayFlags |= SDL_NOFRAME;
 
154
 
 
155
    return displayFlags;
 
156
#else
 
157
    return 0;
 
158
#endif  // USE_OPENGL
 
159
}
 
160
 
 
161
bool Graphics::setOpenGLMode()
 
162
{
 
163
#ifdef USE_OPENGL
 
164
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
 
165
    if (!(mWindow = graphicsManager.createWindow(mWidth, mHeight,
 
166
        mBpp, getOpenGLFlags())))
 
167
    {
 
168
        mRect.w = 0;
 
169
        mRect.h = 0;
 
170
        return false;
 
171
    }
 
172
 
 
173
#ifdef USE_SDL2
 
174
    int w1 = 0;
 
175
    int h1 = 0;
 
176
    SDL_GetWindowSize(mWindow, &w1, &h1);
 
177
    mRect.w = w1;
 
178
    mRect.h = h1;
 
179
 
 
180
    mGLContext = SDL_GL_CreateContext(mWindow);
 
181
 
 
182
#else  // USE_SDL2
 
183
 
 
184
    mRect.w = static_cast<uint16_t>(mWindow->w);
 
185
    mRect.h = static_cast<uint16_t>(mWindow->h);
 
186
#endif  // USE_SDL2
 
187
 
 
188
#ifdef __APPLE__
 
189
    if (mSync)
 
190
    {
 
191
        const GLint VBL = 1;
 
192
        CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &VBL);
 
193
    }
 
194
#endif
 
195
 
 
196
    graphicsManager.setGLVersion();
 
197
    graphicsManager.logVersion();
 
198
 
 
199
    // Setup OpenGL
 
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"));
 
206
 
 
207
    graphicsManager.initOpenGL();
 
208
    initArrays();
 
209
    graphicsManager.updateTextureFormat();
 
210
    updateMemoryInfo();
 
211
 
 
212
    GLint texSize;
 
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())
 
218
    {
 
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);
 
226
    }
 
227
    else
 
228
    {
 
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);
 
234
    }
 
235
    return videoInfo();
 
236
#else  // USE_OPENGL
 
237
 
 
238
    return false;
 
239
#endif  // USE_OPENGL
 
240
}
 
241
 
 
242
int Graphics::getSoftwareFlags() const
 
243
{
 
244
#ifdef USE_SDL2
 
245
    int displayFlags = SDL_WINDOW_SHOWN;
 
246
#else
 
247
    int displayFlags = SDL_ANYFORMAT;
 
248
 
 
249
    if (mHWAccel)
 
250
        displayFlags |= SDL_HWSURFACE | SDL_DOUBLEBUF;
 
251
    else
 
252
        displayFlags |= SDL_SWSURFACE;
 
253
#endif
 
254
 
 
255
    if (mFullscreen)
 
256
        displayFlags |= SDL_FULLSCREEN;
 
257
    else if (mEnableResize)
 
258
        displayFlags |= SDL_RESIZABLE;
 
259
 
 
260
    if (mNoFrame)
 
261
        displayFlags |= SDL_NOFRAME;
 
262
    return displayFlags;
 
263
}
 
264
 
 
265
 
 
266
void Graphics::updateMemoryInfo()
 
267
{
 
268
#ifdef USE_OPENGL
 
269
    if (mStartFreeMem)
 
270
        return;
 
271
 
 
272
    if (graphicsManager.supportExtension("GL_NVX_gpu_memory_info"))
 
273
    {
 
274
        glGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX,
 
275
            &mStartFreeMem);
 
276
        logger->log("free video memory: %d", mStartFreeMem);
 
277
    }
 
278
#endif
 
279
}
 
280
 
 
281
int Graphics::getMemoryUsage() const
 
282
{
 
283
#ifdef USE_OPENGL
 
284
    if (!mStartFreeMem)
 
285
        return 0;
 
286
 
 
287
    if (graphicsManager.supportExtension("GL_NVX_gpu_memory_info"))
 
288
    {
 
289
        GLint val;
 
290
        glGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX,
 
291
            &val);
 
292
        return mStartFreeMem - val;
 
293
    }
 
294
#endif
 
295
    return 0;
 
296
}
 
297
 
 
298
#ifdef USE_SDL2
 
299
void Graphics::dumpRendererInfo(const char *const str,
 
300
                                const SDL_RendererInfo &info)
 
301
{
 
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");
 
312
}
 
313
#endif
 
314
 
 
315
bool Graphics::videoInfo()
 
316
{
 
317
    logger->log("SDL video info");
 
318
#ifdef USE_SDL2
 
319
    logger->log("Using video driver: %s", SDL_GetCurrentVideoDriver());
 
320
 
 
321
    if (mRenderer)
 
322
    {
 
323
        SDL_RendererInfo info;
 
324
        SDL_GetRendererInfo(mRenderer, &info);
 
325
        dumpRendererInfo("Current SDL renderer name: %s", info);
 
326
 
 
327
        const int num = SDL_GetNumRenderDrivers();
 
328
        logger->log("Known renderers");
 
329
        for (int f = 0; f < num; f ++)
 
330
        {
 
331
            if (!SDL_GetRenderDriverInfo(f, &info))
 
332
                dumpRendererInfo("renderer name: %s", info);
 
333
        }
 
334
    }
 
335
#else
 
336
    char videoDriverName[65];
 
337
    if (SDL_VideoDriverName(videoDriverName, 64))
 
338
        logger->log("Using video driver: %s", videoDriverName);
 
339
    else
 
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");
 
343
 
 
344
    imageHelper->dumpSurfaceFormat(mWindow);
 
345
 
 
346
    const SDL_VideoInfo *const vi = SDL_GetVideoInfo();
 
347
    if (!vi)
 
348
        return false;
 
349
 
 
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"));
 
368
#endif
 
369
 
 
370
    return true;
 
371
}
 
372
 
 
373
bool Graphics::setFullscreen(const bool fs)
 
374
{
 
375
    if (mFullscreen == fs)
 
376
        return true;
 
377
 
 
378
    return setVideoMode(mWidth, mHeight, mBpp, fs, mHWAccel,
 
379
        mEnableResize, mNoFrame);
 
380
}
 
381
 
 
382
bool Graphics::resizeScreen(const int width, const int height)
 
383
{
 
384
    if (mWidth == width && mHeight == height)
 
385
        return true;
 
386
 
 
387
#ifdef USE_SDL2
 
388
    _endDraw();
 
389
 
 
390
    mRect.w = width;
 
391
    mRect.h = height;
 
392
    mWidth = width;
 
393
    mHeight = height;
 
394
 
 
395
#ifdef USE_OPENGL
 
396
    // +++ probably this way will not work in windows/mac
 
397
    // Setup OpenGL
 
398
    glViewport(0, 0, mWidth, mHeight);
 
399
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
 
400
#else
 
401
    // +++ need impliment resize in soft mode
 
402
#endif  // USE_OPENGL
 
403
 
 
404
    _beginDraw();
 
405
    return true;
 
406
 
 
407
#else
 
408
    const int prevWidth = mWidth;
 
409
    const int prevHeight = mHeight;
 
410
 
 
411
    _endDraw();
 
412
 
 
413
    const bool success = setVideoMode(width, height, mBpp,
 
414
        mFullscreen, mHWAccel, mEnableResize, mNoFrame);
 
415
 
 
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).
 
418
    if (!success)
 
419
    {
 
420
        if (!setVideoMode(prevWidth, prevHeight, mBpp,
 
421
            mFullscreen, mHWAccel, mEnableResize, mNoFrame))
 
422
        {
 
423
            return false;
 
424
        }
 
425
    }
 
426
 
 
427
    _beginDraw();
 
428
 
 
429
    return success;
 
430
#endif  // USE_SDL2
 
431
}
 
432
 
 
433
int Graphics::getWidth() const
 
434
{
 
435
    return mWidth;
 
436
}
 
437
 
 
438
int Graphics::getHeight() const
 
439
{
 
440
    return mHeight;
 
441
}
 
442
 
 
443
bool Graphics::drawImage(const Image *image, int x, int y)
 
444
{
 
445
    if (image)
 
446
    {
 
447
        return drawImage2(image, 0, 0, x, y,
 
448
            image->mBounds.w, image->mBounds.h, false);
 
449
    }
 
450
    else
 
451
    {
 
452
        return false;
 
453
    }
 
454
}
 
455
 
 
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)
 
467
{
 
468
    BLOCK_START("Graphics::drawImageRect")
 
469
    const bool drawMain = center && topLeft && topRight
 
470
        && bottomLeft && bottomRight;
 
471
 
 
472
    // Draw the center area
 
473
    if (center && drawMain)
 
474
    {
 
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());
 
480
    }
 
481
 
 
482
    // Draw the sides
 
483
    if (top && left && bottom && right)
 
484
    {
 
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);
 
493
    }
 
494
    // Draw the corners
 
495
    if (drawMain)
 
496
    {
 
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());
 
503
    }
 
504
    BLOCK_END("Graphics::drawImageRect")
 
505
}
 
506
 
 
507
void Graphics::drawImageRect(int x, int y, int w, int h,
 
508
                             const ImageRect &imgRect)
 
509
{
 
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],
 
513
            imgRect.grid[4]);
 
514
}
 
515
 
 
516
bool Graphics::drawNet(const int x1, const int y1, const int x2, const int y2,
 
517
                       const int width, const int height)
 
518
{
 
519
    for (int y = y1; y < y2; y += height)
 
520
        drawLine(x1, y, x2, y);
 
521
 
 
522
    for (int x = x1; x < x2; x += width)
 
523
        drawLine(x, y1, x, y2);
 
524
 
 
525
    return true;
 
526
}
 
527
 
 
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)
 
540
{
 
541
    if (!vert)
 
542
        return false;
 
543
 
 
544
    BLOCK_START("Graphics::calcImageRect")
 
545
    const bool drawMain = center && topLeft && topRight
 
546
        && bottomLeft && bottomRight;
 
547
 
 
548
//    pushClipArea(gcn::Rectangle(x, y, w, h));
 
549
 
 
550
    // Draw the center area
 
551
    if (center && drawMain)
 
552
    {
 
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());
 
558
    }
 
559
    // Draw the sides
 
560
    if (top && left && bottom && right)
 
561
    {
 
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);
 
570
    }
 
571
 
 
572
    calcTile(vert, topLeft, x, y);
 
573
    if (topRight)
 
574
        calcTile(vert, topRight, x + w - topRight->getWidth(), y);
 
575
    if (bottomLeft)
 
576
        calcTile(vert, bottomLeft, x, y + h - bottomLeft->getHeight());
 
577
    if (bottomRight)
 
578
    {
 
579
        calcTile(vert, bottomRight, x + w - bottomRight->getWidth(),
 
580
            y + h - bottomRight->getHeight());
 
581
    }
 
582
 
 
583
//    popClipArea();
 
584
    BLOCK_END("Graphics::calcImageRect")
 
585
    return 0;
 
586
}
 
587
 
 
588
void Graphics::setWindowSize(const int width A_UNUSED,
 
589
                             const int height A_UNUSED)
 
590
{
 
591
#ifdef USE_SDL2
 
592
    SDL_SetWindowSize(mWindow, width, height);
 
593
#endif
 
594
}