From 4503b047574e1374d16d2bec7e10285f59cc6d51 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Thu, 19 Jul 2012 21:15:55 +0300 Subject: Rename opengl1graphics to safeopenglgraphics. --- src/CMakeLists.txt | 4 +- src/Makefile.am | 4 +- src/compoundsprite.cpp | 2 +- src/graphicsmanager.cpp | 2 +- src/graphicsvertexes.h | 6 +- src/opengl1graphics.cpp | 691 ------------------------------------ src/opengl1graphics.h | 141 -------- src/resources/image.cpp | 2 +- src/resources/image.h | 2 +- src/resources/openglimagehelper.cpp | 4 +- src/resources/subimage.cpp | 2 +- src/safeopenglgraphics.cpp | 691 ++++++++++++++++++++++++++++++++++++ src/safeopenglgraphics.h | 141 ++++++++ 13 files changed, 846 insertions(+), 846 deletions(-) delete mode 100644 src/opengl1graphics.cpp delete mode 100644 src/opengl1graphics.h create mode 100644 src/safeopenglgraphics.cpp create mode 100644 src/safeopenglgraphics.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7fe4630b3..94d39ed4a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -586,8 +586,6 @@ SET(SRCS map.h maplayer.cpp maplayer.h - opengl1graphics.cpp - opengl1graphics.h openglgraphics.cpp openglgraphics.h particle.cpp @@ -608,6 +606,8 @@ SET(SRCS properties.h rotationalparticle.cpp rotationalparticle.h + safeopenglgraphics.cpp + safeopenglgraphics.h shopitem.cpp shopitem.h simpleanimation.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 00a136b4a..b69cce69b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -599,8 +599,6 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ map.h \ maplayer.cpp \ maplayer.h \ - opengl1graphics.cpp\ - opengl1graphics.h \ openglgraphics.cpp\ openglgraphics.h \ particle.cpp \ @@ -621,6 +619,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ properties.h \ rotationalparticle.cpp \ rotationalparticle.h \ + safeopenglgraphics.cpp\ + safeopenglgraphics.h \ shopitem.cpp \ shopitem.h \ simpleanimation.cpp \ diff --git a/src/compoundsprite.cpp b/src/compoundsprite.cpp index 98ee8c6df..f3ccac072 100644 --- a/src/compoundsprite.cpp +++ b/src/compoundsprite.cpp @@ -27,7 +27,7 @@ #ifdef USE_OPENGL #include "openglgraphics.h" -#include "opengl1graphics.h" +#include "safeopenglgraphics.h" #endif #include "client.h" diff --git a/src/graphicsmanager.cpp b/src/graphicsmanager.cpp index e32cf24ef..f18f8c03d 100644 --- a/src/graphicsmanager.cpp +++ b/src/graphicsmanager.cpp @@ -172,7 +172,7 @@ void GraphicsManager::initGraphics(bool noOpenGL) break; case 2: imageHelper = new OpenGLImageHelper; - mainGraphics = new OpenGL1Graphics; + mainGraphics = new SafeOpenGLGraphics; break; }; diff --git a/src/graphicsvertexes.h b/src/graphicsvertexes.h index a4ce65013..70ba4847b 100644 --- a/src/graphicsvertexes.h +++ b/src/graphicsvertexes.h @@ -33,7 +33,7 @@ #include -#include "opengl1graphics.h" +#include "safeopenglgraphics.h" #include "openglgraphics.h" #endif @@ -61,7 +61,7 @@ class SDLGraphicsVertexes }; #ifdef USE_OPENGL -class OpenGL1GraphicsVertexes +class SafeOpenGLGraphicsVertexes { }; @@ -147,7 +147,7 @@ class GraphicsVertexes SDLGraphicsVertexes sdl[5]; #ifdef USE_OPENGL -// OpenGL1GraphicsVertexes ogl1[5]; +// SafeOpenGLGraphicsVertexes ogl1[5]; OpenGLGraphicsVertexes ogl[5]; #endif diff --git a/src/opengl1graphics.cpp b/src/opengl1graphics.cpp deleted file mode 100644 index 88079c2bd..000000000 --- a/src/opengl1graphics.cpp +++ /dev/null @@ -1,691 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2004-2009 The Mana World Development Team - * Copyright (C) 2009-2010 The Mana Developers - * Copyright (C) 2011-2012 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "main.h" - -#ifdef USE_OPENGL -#include "opengl1graphics.h" - -#include "configuration.h" -#include "graphicsvertexes.h" -#include "logger.h" - -#include "resources/image.h" -#include "resources/openglimagehelper.h" - -#include - -#include "debug.h" - -#ifndef GL_TEXTURE_RECTANGLE_ARB -#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 -#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 -#endif - -GLuint OpenGL1Graphics::mLastImage = 0; - -OpenGL1Graphics::OpenGL1Graphics(): - mAlpha(false), mTexture(false), mColorAlpha(false), - mFboId(0), mTextureId(0), mRboId(0) -{ - mOpenGL = 2; - mName = "safe OpenGL"; -} - -OpenGL1Graphics::~OpenGL1Graphics() -{ -} - -bool OpenGL1Graphics::setVideoMode(int w, int h, int bpp, bool fs, - bool hwaccel, bool resize, bool noFrame) -{ - setMainFlags(w, h, bpp, fs, hwaccel, resize, noFrame); - - return setOpenGLMode(); -} - -static inline void drawQuad(const Image *image, - int srcX, int srcY, int dstX, int dstY, - int width, int height) -{ - if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) - { - // Find OpenGL normalized texture coordinates. - float texX1 = static_cast(srcX) - / static_cast(image->getTextureWidth()); - float texY1 = static_cast(srcY) - / static_cast(image->getTextureHeight()); - float texX2 = static_cast(srcX + width) / static_cast( - image->getTextureWidth()); - float texY2 = static_cast(srcY + height) / static_cast( - image->getTextureHeight()); - - glTexCoord2f(texX1, texY1); - glVertex2i(dstX, dstY); - glTexCoord2f(texX2, texY1); - glVertex2i(dstX + width, dstY); - glTexCoord2f(texX2, texY2); - glVertex2i(dstX + width, dstY + height); - glTexCoord2f(texX1, texY2); - glVertex2i(dstX, dstY + height); - } - else - { - glTexCoord2i(srcX, srcY); - glVertex2i(dstX, dstY); - glTexCoord2i(srcX + width, srcY); - glVertex2i(dstX + width, dstY); - glTexCoord2i(srcX + width, srcY + height); - glVertex2i(dstX + width, dstY + height); - glTexCoord2i(srcX, srcY + height); - glVertex2i(dstX, dstY + height); - } -} - -static inline void drawRescaledQuad(Image *image, int srcX, int srcY, - int dstX, int dstY, int width, int height, - int desiredWidth, int desiredHeight) -{ - if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) - { - // Find OpenGL normalized texture coordinates. - float texX1 = static_cast(srcX) - / static_cast(image->getTextureWidth()); - float texY1 = static_cast(srcY) - / static_cast(image->getTextureHeight()); - float texX2 = static_cast(srcX + width) / static_cast( - image->getTextureWidth()); - float texY2 = static_cast(srcY + height) / static_cast( - image->getTextureHeight()); - - glTexCoord2f(texX1, texY1); - glVertex2i(dstX, dstY); - glTexCoord2f(texX2, texY1); - glVertex2i(dstX + desiredWidth, dstY); - glTexCoord2f(texX2, texY2); - glVertex2i(dstX + desiredWidth, dstY + desiredHeight); - glTexCoord2f(texX1, texY2); - glVertex2i(dstX, dstY + desiredHeight); - } - else - { - glTexCoord2i(srcX, srcY); - glVertex2i(dstX, dstY); - glTexCoord2i(srcX + width, srcY); - glVertex2i(dstX + desiredWidth, dstY); - glTexCoord2i(srcX + width, srcY + height); - glVertex2i(dstX + desiredWidth, dstY + desiredHeight); - glTexCoord2i(srcX, srcY + height); - glVertex2i(dstX, dstY + desiredHeight); - } -} - - -bool OpenGL1Graphics::drawImage2(const Image *image, int srcX, int srcY, - int dstX, int dstY, - int width, int height, bool useColor) -{ - if (!image) - return false; - - srcX += image->mBounds.x; - srcY += image->mBounds.y; - - if (!useColor) - glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - - bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); - - setTexturingAndBlending(true); - - // Draw a textured quad. - glBegin(GL_QUADS); - drawQuad(image, srcX, srcY, dstX, dstY, width, height); - glEnd(); - - if (!useColor) - { - glColor4ub(static_cast(mColor.r), - static_cast(mColor.g), - static_cast(mColor.b), - static_cast(mColor.a)); - } - - return true; -} - -bool OpenGL1Graphics::drawRescaledImage(Image *image, int srcX, int srcY, - int dstX, int dstY, - int width, int height, - int desiredWidth, int desiredHeight, - bool useColor) -{ - return drawRescaledImage(image, srcX, srcY, - dstX, dstY, - width, height, - desiredWidth, desiredHeight, - useColor, true); -} - -bool OpenGL1Graphics::drawRescaledImage(Image *image, int srcX, int srcY, - int dstX, int dstY, - int width, int height, - int desiredWidth, int desiredHeight, - bool useColor, bool smooth) -{ - if (!image) - return false; - - // Just draw the image normally when no resizing is necessary, - if (width == desiredWidth && height == desiredHeight) - { - return drawImage2(image, srcX, srcY, dstX, dstY, - width, height, useColor); - } - - // When the desired image is smaller than the current one, - // disable smooth effect. - if (width > desiredWidth && height > desiredHeight) - smooth = false; - - srcX += image->mBounds.x; - srcY += image->mBounds.y; - - if (!useColor) - glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - - bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); - - setTexturingAndBlending(true); - - // Draw a textured quad. - glBegin(GL_QUADS); - drawRescaledQuad(image, srcX, srcY, dstX, dstY, width, height, - desiredWidth, desiredHeight); - - if (smooth) // A basic smooth effect... - { - glColor4f(1.0f, 1.0f, 1.0f, 0.2f); - drawRescaledQuad(image, srcX, srcY, dstX - 1, dstY - 1, width, height, - desiredWidth + 1, desiredHeight + 1); - drawRescaledQuad(image, srcX, srcY, dstX + 1, dstY + 1, width, height, - desiredWidth - 1, desiredHeight - 1); - - drawRescaledQuad(image, srcX, srcY, dstX + 1, dstY, width, height, - desiredWidth - 1, desiredHeight); - drawRescaledQuad(image, srcX, srcY, dstX, dstY + 1, width, height, - desiredWidth, desiredHeight - 1); - } - - glEnd(); - - if (!useColor) - { - glColor4ub(static_cast(mColor.r), - static_cast(mColor.g), - static_cast(mColor.b), - static_cast(mColor.a)); - } - - return true; -} - -/* Optimising the functions that Graphics::drawImagePattern would call, - * so that glBegin...glEnd are outside the main loop. */ -void OpenGL1Graphics::drawImagePattern(const Image *image, int x, int y, - int w, int h) -{ - if (!image) - return; - - const int srcX = image->mBounds.x; - const int srcY = image->mBounds.y; - - const int iw = image->mBounds.w; - const int ih = image->mBounds.h; - if (iw == 0 || ih == 0) - return; - - glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - - bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); - - setTexturingAndBlending(true); - - // Draw a set of textured rectangles - glBegin(GL_QUADS); - - for (int py = 0; py < h; py += ih) - { - const int height = (py + ih >= h) ? h - py : ih; - const int dstY = y + py; - for (int px = 0; px < w; px += iw) - { - int width = (px + iw >= w) ? w - px : iw; - int dstX = x + px; - - drawQuad(image, srcX, srcY, dstX, dstY, width, height); - } - } - - glEnd(); - - glColor4ub(static_cast(mColor.r), - static_cast(mColor.g), - static_cast(mColor.b), - static_cast(mColor.a)); -} - -void OpenGL1Graphics::drawRescaledImagePattern(Image *image, int x, int y, - int w, int h, - int scaledWidth, - int scaledHeight) -{ - if (!image) - return; - - const int srcX = image->mBounds.x; - const int srcY = image->mBounds.y; - - const int iw = scaledWidth; - const int ih = scaledHeight; - if (iw == 0 || ih == 0) - return; - - glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - - bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); - - setTexturingAndBlending(true); - - // Draw a set of textured rectangles - glBegin(GL_QUADS); - - const float scaleFactorW = static_cast(scaledWidth) - / image->getWidth(); - const float scaleFactorH = static_cast(scaledHeight) - / image->getHeight(); - - for (int py = 0; py < h; py += ih) - { - const int height = (py + ih >= h) ? h - py : ih; - const int dstY = y + py; - for (int px = 0; px < w; px += iw) - { - int width = (px + iw >= w) ? w - px : iw; - int dstX = x + px; - - drawRescaledQuad(image, srcX, srcY, dstX, dstY, - width / scaleFactorW, height / scaleFactorH, - scaledWidth, scaledHeight); - } - } - - glEnd(); - - glColor4ub(static_cast(mColor.r), static_cast(mColor.g), - static_cast(mColor.b), static_cast(mColor.a)); -} - -bool OpenGL1Graphics::calcImageRect(GraphicsVertexes* vert, - int x, int y, int w, int h, - Image *topLeft A_UNUSED, - Image *topRight A_UNUSED, - Image *bottomLeft A_UNUSED, - Image *bottomRight A_UNUSED, - Image *top A_UNUSED, Image *right A_UNUSED, - Image *bottom A_UNUSED, - Image *left A_UNUSED, - Image *center A_UNUSED) -{ - if (!vert) - return false; - - vert->init(x, y, w, h); - return true; -} - -void OpenGL1Graphics::calcTile(ImageVertexes *vert A_UNUSED, - int x A_UNUSED, int y A_UNUSED) -{ - -} - -void OpenGL1Graphics::drawTile(ImageVertexes *vert A_UNUSED) -{ - -} - -void OpenGL1Graphics::drawImageRect2(GraphicsVertexes* vert, - const ImageRect &imgRect) -{ - if (!vert) - return; - - drawImageRect(vert->getX(), vert->getY(), vert->getW(), vert->getH(), - imgRect.grid[0], imgRect.grid[2], imgRect.grid[6], imgRect.grid[8], - imgRect.grid[1], imgRect.grid[5], imgRect.grid[7], imgRect.grid[3], - imgRect.grid[4]); -} - -void OpenGL1Graphics::updateScreen() -{ - glFlush(); - glFinish(); - SDL_GL_SwapBuffers(); -} - -void OpenGL1Graphics::_beginDraw() -{ - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - - glOrtho(0.0, static_cast(mTarget->w), - static_cast(mTarget->h), 0.0, -1.0, 1.0); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glEnable(GL_SCISSOR_TEST); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - pushClipArea(gcn::Rectangle(0, 0, mTarget->w, mTarget->h)); -} - -void OpenGL1Graphics::_endDraw() -{ - popClipArea(); -} - -void OpenGL1Graphics::prepareScreenshot() -{ -#if !defined(_WIN32) - if (config.getBoolValue("usefbo")) - { - int h = mTarget->h; - int w = mTarget->w; - - // create a texture object - glGenTextures(1, &mTextureId); - glBindTexture(GL_TEXTURE_2D, mTextureId); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, - GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glBindTexture(GL_TEXTURE_2D, 0); - - // create a renderbuffer object to store depth info - glGenRenderbuffersEXT(1, &mRboId); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mRboId); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, - GL_DEPTH_COMPONENT, w, h); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); - - // create a framebuffer object - glGenFramebuffersEXT(1, &mFboId); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFboId); - - // attach the texture to FBO color attachment point - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - GL_TEXTURE_2D, mTextureId, 0); - - // attach the renderbuffer to depth attachment point - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, - GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mRboId); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFboId); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } -#endif -} - -SDL_Surface* OpenGL1Graphics::getScreenshot() -{ - const int h = mTarget->h; - const int w = mTarget->w - (mTarget->w % 4); - GLint pack = 1; - - SDL_Surface *screenshot = SDL_CreateRGBSurface( - SDL_SWSURFACE, - w, h, 24, - 0xff0000, 0x00ff00, 0x0000ff, 0x000000); - - if (!screenshot) - return nullptr; - - if (SDL_MUSTLOCK(screenshot)) - SDL_LockSurface(screenshot); - - // Grap the pixel buffer and write it to the SDL surface - glGetIntegerv(GL_PACK_ALIGNMENT, &pack); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, screenshot->pixels); - - // Flip the screenshot, as OpenGL has 0,0 in bottom left - unsigned int lineSize = 3 * w; - GLubyte* buf = static_cast(malloc(lineSize)); - - for (int i = 0; i < (h / 2); i++) - { - GLubyte *top = static_cast( - screenshot->pixels) + lineSize * i; - GLubyte *bot = static_cast( - screenshot->pixels) + lineSize * (h - 1 - i); - - memcpy(buf, top, lineSize); - memcpy(top, bot, lineSize); - memcpy(bot, buf, lineSize); - } - - free(buf); - -#if !defined(_WIN32) - if (config.getBoolValue("usefbo")) - { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - if (mFboId) - { - glDeleteFramebuffersEXT(1, &mFboId); - mFboId = 0; - } - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); - if (mRboId) - { - glDeleteRenderbuffersEXT(1, &mRboId); - mRboId = 0; - } - if (mTextureId) - { - glDeleteTextures(1, &mTextureId); - mTextureId = 0; - } - } -#endif - - glPixelStorei(GL_PACK_ALIGNMENT, pack); - - if (SDL_MUSTLOCK(screenshot)) - SDL_UnlockSurface(screenshot); - - return screenshot; -} - -bool OpenGL1Graphics::pushClipArea(gcn::Rectangle area) -{ - int transX = 0; - int transY = 0; - - if (!mClipStack.empty()) - { - const gcn::ClipRectangle &clipArea = mClipStack.top(); - transX = -clipArea.xOffset; - transY = -clipArea.yOffset; - } - - bool result = gcn::Graphics::pushClipArea(area); - - const gcn::ClipRectangle &clipArea = mClipStack.top(); - transX += clipArea.xOffset; - transY += clipArea.yOffset; - - glPushMatrix(); - glTranslatef(static_cast(transX), - static_cast(transY), 0); - glScissor(clipArea.x, mTarget->h - clipArea.y - clipArea.height, - clipArea.width, clipArea.height); - - return result; -} - -void OpenGL1Graphics::popClipArea() -{ - gcn::Graphics::popClipArea(); - - if (mClipStack.empty()) - return; - - glPopMatrix(); - const gcn::ClipRectangle &clipArea = mClipStack.top(); - glScissor(clipArea.x, mTarget->h - clipArea.y - clipArea.height, - clipArea.width, clipArea.height); -} - -void OpenGL1Graphics::setColor(const gcn::Color& color) -{ - mColor = color; - glColor4ub(static_cast(color.r), - static_cast(color.g), - static_cast(color.b), - static_cast(color.a)); - - mColorAlpha = (color.a != 255); -} - -void OpenGL1Graphics::drawPoint(int x, int y) -{ - setTexturingAndBlending(false); - - glBegin(GL_POINTS); - glVertex2i(x, y); - glEnd(); -} - -void OpenGL1Graphics::drawLine(int x1, int y1, int x2, int y2) -{ - setTexturingAndBlending(false); - - glBegin(GL_LINES); - glVertex2f(static_cast(x1) + 0.5f, static_cast(y1) + 0.5f); - glVertex2f(static_cast(x2) + 0.5f, static_cast(y2) + 0.5f); - glEnd(); - - glBegin(GL_POINTS); - glVertex2f(static_cast(x2) + 0.5f, static_cast(y2) + 0.5f); - glEnd(); -} - -void OpenGL1Graphics::drawRectangle(const gcn::Rectangle& rect) -{ - drawRectangle(rect, false); -} - -void OpenGL1Graphics::fillRectangle(const gcn::Rectangle& rect) -{ - drawRectangle(rect, true); -} - -void OpenGL1Graphics::setTargetPlane(int width A_UNUSED, int height A_UNUSED) -{ -} - -void OpenGL1Graphics::setTexturingAndBlending(bool enable) -{ - if (enable) - { - if (!mTexture) - { - glEnable(OpenGLImageHelper::mTextureType); - mTexture = true; - } - - if (!mAlpha) - { - glEnable(GL_BLEND); - mAlpha = true; - } - } - else - { - mLastImage = 0; - if (mAlpha && !mColorAlpha) - { - glDisable(GL_BLEND); - mAlpha = false; - } - else if (!mAlpha && mColorAlpha) - { - glEnable(GL_BLEND); - mAlpha = true; - } - - if (mTexture) - { - glDisable(OpenGLImageHelper::mTextureType); - mTexture = false; - } - } -} - -void OpenGL1Graphics::drawRectangle(const gcn::Rectangle& rect, bool filled) -{ - const float offset = filled ? 0 : 0.5f; - - setTexturingAndBlending(false); - - glBegin(filled ? GL_QUADS : GL_LINE_LOOP); - glVertex2f(static_cast(rect.x) + offset, - static_cast(rect.y) + offset); - glVertex2f(static_cast(rect.x + rect.width) - offset, - static_cast(rect.y) + offset); - glVertex2f(static_cast(rect.x + rect.width) - offset, - static_cast(rect.y + rect.height) - offset); - glVertex2f(static_cast(rect.x) + offset, - static_cast(rect.y + rect.height) - offset); - glEnd(); -} - -void OpenGL1Graphics::bindTexture(GLenum target, GLuint texture) -{ - if (mLastImage != texture) - { - mLastImage = texture; - glBindTexture(target, texture); - } -} - -#endif // USE_OPENGL diff --git a/src/opengl1graphics.h b/src/opengl1graphics.h deleted file mode 100644 index 5c4d7ffb7..000000000 --- a/src/opengl1graphics.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2004-2009 The Mana World Development Team - * Copyright (C) 2009-2010 The Mana Developers - * Copyright (C) 2011-2012 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef OPENGL1GRAPHICS_H -#define OPENGL1GRAPHICS_H - -#ifdef USE_OPENGL -#include "main.h" - -#include "graphics.h" - -//#define NO_SDL_GLEXT -#define GL_GLEXT_PROTOTYPES 1 - -#include -#include - -class OpenGL1Graphics : public Graphics -{ - public: - OpenGL1Graphics(); - - ~OpenGL1Graphics(); - - bool setVideoMode(int w, int h, int bpp, bool fs, - bool hwaccel, bool resize, bool noFrame); - - /** - * Draws a resclaled version of the image - */ - bool drawRescaledImage(Image *image, int srcX, int srcY, - int dstX, int dstY, - int width, int height, - int desiredWidth, int desiredHeight, - bool useColor); - - /** - * Used to get the smooth rescale option over the standard function. - */ - bool drawRescaledImage(Image *image, int srcX, int srcY, - int dstX, int dstY, - int width, int height, - int desiredWidth, int desiredHeight, - bool useColor, bool smooth); - - void drawImagePattern(const Image *image, - int x, int y, - int w, int h); - - /** - * Draw a pattern based on a rescaled version of the given image... - */ - void drawRescaledImagePattern(Image *image, - int x, int y, int w, int h, - int scaledWidth, int scaledHeight); - - bool calcImageRect(GraphicsVertexes* vert, - int x, int y, int w, int h, - Image *topLeft, Image *topRight, - Image *bottomLeft, Image *bottomRight, - Image *top, Image *right, - Image *bottom, Image *left, - Image *center); - - void drawImageRect2(GraphicsVertexes* vert, const ImageRect &imgRect); - - void calcTile(ImageVertexes *vert, int x, int y); - - void drawTile(ImageVertexes *vert); - - void updateScreen(); - - void _beginDraw(); - void _endDraw(); - - bool pushClipArea(gcn::Rectangle area); - void popClipArea(); - - void setColor(const gcn::Color &color); - - void drawPoint(int x, int y); - - void drawLine(int x1, int y1, int x2, int y2); - - void drawRectangle(const gcn::Rectangle &rect, bool filled); - - void drawRectangle(const gcn::Rectangle &rect); - - void fillRectangle(const gcn::Rectangle &rect); - - void setTargetPlane(int width, int height); - - /** - * Takes a screenshot and returns it as SDL surface. - */ - SDL_Surface *getScreenshot(); - - void prepareScreenshot(); - - static void bindTexture(GLenum target, GLuint texture); - - static GLuint mLastImage; - - protected: - bool drawImage2(const Image *image, - int srcX, int srcY, - int dstX, int dstY, - int width, int height, - bool useColor); - - void setTexturingAndBlending(bool enable); - - private: - bool mAlpha, mTexture; - bool mColorAlpha; - GLuint mFboId; - GLuint mTextureId; - GLuint mRboId; -}; -#endif - -#endif diff --git a/src/resources/image.cpp b/src/resources/image.cpp index c642980af..342bca1b5 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -27,7 +27,7 @@ #ifdef USE_OPENGL #include "openglgraphics.h" -#include "opengl1graphics.h" +#include "safeopenglgraphics.h" #endif #include "client.h" diff --git a/src/resources/image.h b/src/resources/image.h index 59178cca6..756c9e23d 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -60,7 +60,7 @@ class Image : public Resource friend class SDLImageHelper; #ifdef USE_OPENGL friend class OpenGLGraphics; - friend class OpenGL1Graphics; + friend class SafeOpenGLGraphics; #endif public: diff --git a/src/resources/openglimagehelper.cpp b/src/resources/openglimagehelper.cpp index ae3b55741..120288b3f 100644 --- a/src/resources/openglimagehelper.cpp +++ b/src/resources/openglimagehelper.cpp @@ -28,7 +28,7 @@ #include "resources/resourcemanager.h" #include "openglgraphics.h" -#include "opengl1graphics.h" +#include "safeopenglgraphics.h" #include "client.h" #include "logger.h" @@ -215,7 +215,7 @@ Image *OpenGLImageHelper::glLoad(SDL_Surface *tmpImage) if (mUseOpenGL == 1) OpenGLGraphics::bindTexture(mTextureType, texture); else if (mUseOpenGL == 2) - OpenGL1Graphics::bindTexture(mTextureType, texture); + SafeOpenGLGraphics::bindTexture(mTextureType, texture); if (SDL_MUSTLOCK(tmpImage)) SDL_LockSurface(tmpImage); diff --git a/src/resources/subimage.cpp b/src/resources/subimage.cpp index 294a966c4..1b9f745d3 100644 --- a/src/resources/subimage.cpp +++ b/src/resources/subimage.cpp @@ -24,7 +24,7 @@ #ifdef USE_OPENGL #include "openglgraphics.h" -#include "opengl1graphics.h" +#include "safeopenglgraphics.h" #endif #include "client.h" diff --git a/src/safeopenglgraphics.cpp b/src/safeopenglgraphics.cpp new file mode 100644 index 000000000..cc8bcc95b --- /dev/null +++ b/src/safeopenglgraphics.cpp @@ -0,0 +1,691 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "main.h" + +#ifdef USE_OPENGL +#include "safeopenglgraphics.h" + +#include "configuration.h" +#include "graphicsvertexes.h" +#include "logger.h" + +#include "resources/image.h" +#include "resources/openglimagehelper.h" + +#include + +#include "debug.h" + +#ifndef GL_TEXTURE_RECTANGLE_ARB +#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 +#endif + +GLuint SafeOpenGLGraphics::mLastImage = 0; + +SafeOpenGLGraphics::SafeOpenGLGraphics(): + mAlpha(false), mTexture(false), mColorAlpha(false), + mFboId(0), mTextureId(0), mRboId(0) +{ + mOpenGL = 2; + mName = "safe OpenGL"; +} + +SafeOpenGLGraphics::~SafeOpenGLGraphics() +{ +} + +bool SafeOpenGLGraphics::setVideoMode(int w, int h, int bpp, bool fs, + bool hwaccel, bool resize, bool noFrame) +{ + setMainFlags(w, h, bpp, fs, hwaccel, resize, noFrame); + + return setOpenGLMode(); +} + +static inline void drawQuad(const Image *image, + int srcX, int srcY, int dstX, int dstY, + int width, int height) +{ + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) + { + // Find OpenGL normalized texture coordinates. + float texX1 = static_cast(srcX) + / static_cast(image->getTextureWidth()); + float texY1 = static_cast(srcY) + / static_cast(image->getTextureHeight()); + float texX2 = static_cast(srcX + width) / static_cast( + image->getTextureWidth()); + float texY2 = static_cast(srcY + height) / static_cast( + image->getTextureHeight()); + + glTexCoord2f(texX1, texY1); + glVertex2i(dstX, dstY); + glTexCoord2f(texX2, texY1); + glVertex2i(dstX + width, dstY); + glTexCoord2f(texX2, texY2); + glVertex2i(dstX + width, dstY + height); + glTexCoord2f(texX1, texY2); + glVertex2i(dstX, dstY + height); + } + else + { + glTexCoord2i(srcX, srcY); + glVertex2i(dstX, dstY); + glTexCoord2i(srcX + width, srcY); + glVertex2i(dstX + width, dstY); + glTexCoord2i(srcX + width, srcY + height); + glVertex2i(dstX + width, dstY + height); + glTexCoord2i(srcX, srcY + height); + glVertex2i(dstX, dstY + height); + } +} + +static inline void drawRescaledQuad(Image *image, int srcX, int srcY, + int dstX, int dstY, int width, int height, + int desiredWidth, int desiredHeight) +{ + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) + { + // Find OpenGL normalized texture coordinates. + float texX1 = static_cast(srcX) + / static_cast(image->getTextureWidth()); + float texY1 = static_cast(srcY) + / static_cast(image->getTextureHeight()); + float texX2 = static_cast(srcX + width) / static_cast( + image->getTextureWidth()); + float texY2 = static_cast(srcY + height) / static_cast( + image->getTextureHeight()); + + glTexCoord2f(texX1, texY1); + glVertex2i(dstX, dstY); + glTexCoord2f(texX2, texY1); + glVertex2i(dstX + desiredWidth, dstY); + glTexCoord2f(texX2, texY2); + glVertex2i(dstX + desiredWidth, dstY + desiredHeight); + glTexCoord2f(texX1, texY2); + glVertex2i(dstX, dstY + desiredHeight); + } + else + { + glTexCoord2i(srcX, srcY); + glVertex2i(dstX, dstY); + glTexCoord2i(srcX + width, srcY); + glVertex2i(dstX + desiredWidth, dstY); + glTexCoord2i(srcX + width, srcY + height); + glVertex2i(dstX + desiredWidth, dstY + desiredHeight); + glTexCoord2i(srcX, srcY + height); + glVertex2i(dstX, dstY + desiredHeight); + } +} + + +bool SafeOpenGLGraphics::drawImage2(const Image *image, int srcX, int srcY, + int dstX, int dstY, + int width, int height, bool useColor) +{ + if (!image) + return false; + + srcX += image->mBounds.x; + srcY += image->mBounds.y; + + if (!useColor) + glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); + + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); + + setTexturingAndBlending(true); + + // Draw a textured quad. + glBegin(GL_QUADS); + drawQuad(image, srcX, srcY, dstX, dstY, width, height); + glEnd(); + + if (!useColor) + { + glColor4ub(static_cast(mColor.r), + static_cast(mColor.g), + static_cast(mColor.b), + static_cast(mColor.a)); + } + + return true; +} + +bool SafeOpenGLGraphics::drawRescaledImage(Image *image, int srcX, int srcY, + int dstX, int dstY, + int width, int height, + int desiredWidth, int desiredHeight, + bool useColor) +{ + return drawRescaledImage(image, srcX, srcY, + dstX, dstY, + width, height, + desiredWidth, desiredHeight, + useColor, true); +} + +bool SafeOpenGLGraphics::drawRescaledImage(Image *image, int srcX, int srcY, + int dstX, int dstY, + int width, int height, + int desiredWidth, int desiredHeight, + bool useColor, bool smooth) +{ + if (!image) + return false; + + // Just draw the image normally when no resizing is necessary, + if (width == desiredWidth && height == desiredHeight) + { + return drawImage2(image, srcX, srcY, dstX, dstY, + width, height, useColor); + } + + // When the desired image is smaller than the current one, + // disable smooth effect. + if (width > desiredWidth && height > desiredHeight) + smooth = false; + + srcX += image->mBounds.x; + srcY += image->mBounds.y; + + if (!useColor) + glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); + + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); + + setTexturingAndBlending(true); + + // Draw a textured quad. + glBegin(GL_QUADS); + drawRescaledQuad(image, srcX, srcY, dstX, dstY, width, height, + desiredWidth, desiredHeight); + + if (smooth) // A basic smooth effect... + { + glColor4f(1.0f, 1.0f, 1.0f, 0.2f); + drawRescaledQuad(image, srcX, srcY, dstX - 1, dstY - 1, width, height, + desiredWidth + 1, desiredHeight + 1); + drawRescaledQuad(image, srcX, srcY, dstX + 1, dstY + 1, width, height, + desiredWidth - 1, desiredHeight - 1); + + drawRescaledQuad(image, srcX, srcY, dstX + 1, dstY, width, height, + desiredWidth - 1, desiredHeight); + drawRescaledQuad(image, srcX, srcY, dstX, dstY + 1, width, height, + desiredWidth, desiredHeight - 1); + } + + glEnd(); + + if (!useColor) + { + glColor4ub(static_cast(mColor.r), + static_cast(mColor.g), + static_cast(mColor.b), + static_cast(mColor.a)); + } + + return true; +} + +/* Optimising the functions that Graphics::drawImagePattern would call, + * so that glBegin...glEnd are outside the main loop. */ +void SafeOpenGLGraphics::drawImagePattern(const Image *image, int x, int y, + int w, int h) +{ + if (!image) + return; + + const int srcX = image->mBounds.x; + const int srcY = image->mBounds.y; + + const int iw = image->mBounds.w; + const int ih = image->mBounds.h; + if (iw == 0 || ih == 0) + return; + + glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); + + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); + + setTexturingAndBlending(true); + + // Draw a set of textured rectangles + glBegin(GL_QUADS); + + for (int py = 0; py < h; py += ih) + { + const int height = (py + ih >= h) ? h - py : ih; + const int dstY = y + py; + for (int px = 0; px < w; px += iw) + { + int width = (px + iw >= w) ? w - px : iw; + int dstX = x + px; + + drawQuad(image, srcX, srcY, dstX, dstY, width, height); + } + } + + glEnd(); + + glColor4ub(static_cast(mColor.r), + static_cast(mColor.g), + static_cast(mColor.b), + static_cast(mColor.a)); +} + +void SafeOpenGLGraphics::drawRescaledImagePattern(Image *image, int x, int y, + int w, int h, + int scaledWidth, + int scaledHeight) +{ + if (!image) + return; + + const int srcX = image->mBounds.x; + const int srcY = image->mBounds.y; + + const int iw = scaledWidth; + const int ih = scaledHeight; + if (iw == 0 || ih == 0) + return; + + glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); + + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); + + setTexturingAndBlending(true); + + // Draw a set of textured rectangles + glBegin(GL_QUADS); + + const float scaleFactorW = static_cast(scaledWidth) + / image->getWidth(); + const float scaleFactorH = static_cast(scaledHeight) + / image->getHeight(); + + for (int py = 0; py < h; py += ih) + { + const int height = (py + ih >= h) ? h - py : ih; + const int dstY = y + py; + for (int px = 0; px < w; px += iw) + { + int width = (px + iw >= w) ? w - px : iw; + int dstX = x + px; + + drawRescaledQuad(image, srcX, srcY, dstX, dstY, + width / scaleFactorW, height / scaleFactorH, + scaledWidth, scaledHeight); + } + } + + glEnd(); + + glColor4ub(static_cast(mColor.r), static_cast(mColor.g), + static_cast(mColor.b), static_cast(mColor.a)); +} + +bool SafeOpenGLGraphics::calcImageRect(GraphicsVertexes* vert, + int x, int y, int w, int h, + Image *topLeft A_UNUSED, + Image *topRight A_UNUSED, + Image *bottomLeft A_UNUSED, + Image *bottomRight A_UNUSED, + Image *top A_UNUSED, Image *right A_UNUSED, + Image *bottom A_UNUSED, + Image *left A_UNUSED, + Image *center A_UNUSED) +{ + if (!vert) + return false; + + vert->init(x, y, w, h); + return true; +} + +void SafeOpenGLGraphics::calcTile(ImageVertexes *vert A_UNUSED, + int x A_UNUSED, int y A_UNUSED) +{ + +} + +void SafeOpenGLGraphics::drawTile(ImageVertexes *vert A_UNUSED) +{ + +} + +void SafeOpenGLGraphics::drawImageRect2(GraphicsVertexes* vert, + const ImageRect &imgRect) +{ + if (!vert) + return; + + drawImageRect(vert->getX(), vert->getY(), vert->getW(), vert->getH(), + imgRect.grid[0], imgRect.grid[2], imgRect.grid[6], imgRect.grid[8], + imgRect.grid[1], imgRect.grid[5], imgRect.grid[7], imgRect.grid[3], + imgRect.grid[4]); +} + +void SafeOpenGLGraphics::updateScreen() +{ + glFlush(); + glFinish(); + SDL_GL_SwapBuffers(); +} + +void SafeOpenGLGraphics::_beginDraw() +{ + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glOrtho(0.0, static_cast(mTarget->w), + static_cast(mTarget->h), 0.0, -1.0, 1.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glEnable(GL_SCISSOR_TEST); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + pushClipArea(gcn::Rectangle(0, 0, mTarget->w, mTarget->h)); +} + +void SafeOpenGLGraphics::_endDraw() +{ + popClipArea(); +} + +void SafeOpenGLGraphics::prepareScreenshot() +{ +#if !defined(_WIN32) + if (config.getBoolValue("usefbo")) + { + int h = mTarget->h; + int w = mTarget->w; + + // create a texture object + glGenTextures(1, &mTextureId); + glBindTexture(GL_TEXTURE_2D, mTextureId); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, + GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glBindTexture(GL_TEXTURE_2D, 0); + + // create a renderbuffer object to store depth info + glGenRenderbuffersEXT(1, &mRboId); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mRboId); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, + GL_DEPTH_COMPONENT, w, h); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + + // create a framebuffer object + glGenFramebuffersEXT(1, &mFboId); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFboId); + + // attach the texture to FBO color attachment point + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, mTextureId, 0); + + // attach the renderbuffer to depth attachment point + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, + GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mRboId); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFboId); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } +#endif +} + +SDL_Surface* SafeOpenGLGraphics::getScreenshot() +{ + const int h = mTarget->h; + const int w = mTarget->w - (mTarget->w % 4); + GLint pack = 1; + + SDL_Surface *screenshot = SDL_CreateRGBSurface( + SDL_SWSURFACE, + w, h, 24, + 0xff0000, 0x00ff00, 0x0000ff, 0x000000); + + if (!screenshot) + return nullptr; + + if (SDL_MUSTLOCK(screenshot)) + SDL_LockSurface(screenshot); + + // Grap the pixel buffer and write it to the SDL surface + glGetIntegerv(GL_PACK_ALIGNMENT, &pack); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, screenshot->pixels); + + // Flip the screenshot, as OpenGL has 0,0 in bottom left + unsigned int lineSize = 3 * w; + GLubyte* buf = static_cast(malloc(lineSize)); + + for (int i = 0; i < (h / 2); i++) + { + GLubyte *top = static_cast( + screenshot->pixels) + lineSize * i; + GLubyte *bot = static_cast( + screenshot->pixels) + lineSize * (h - 1 - i); + + memcpy(buf, top, lineSize); + memcpy(top, bot, lineSize); + memcpy(bot, buf, lineSize); + } + + free(buf); + +#if !defined(_WIN32) + if (config.getBoolValue("usefbo")) + { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + if (mFboId) + { + glDeleteFramebuffersEXT(1, &mFboId); + mFboId = 0; + } + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + if (mRboId) + { + glDeleteRenderbuffersEXT(1, &mRboId); + mRboId = 0; + } + if (mTextureId) + { + glDeleteTextures(1, &mTextureId); + mTextureId = 0; + } + } +#endif + + glPixelStorei(GL_PACK_ALIGNMENT, pack); + + if (SDL_MUSTLOCK(screenshot)) + SDL_UnlockSurface(screenshot); + + return screenshot; +} + +bool SafeOpenGLGraphics::pushClipArea(gcn::Rectangle area) +{ + int transX = 0; + int transY = 0; + + if (!mClipStack.empty()) + { + const gcn::ClipRectangle &clipArea = mClipStack.top(); + transX = -clipArea.xOffset; + transY = -clipArea.yOffset; + } + + bool result = gcn::Graphics::pushClipArea(area); + + const gcn::ClipRectangle &clipArea = mClipStack.top(); + transX += clipArea.xOffset; + transY += clipArea.yOffset; + + glPushMatrix(); + glTranslatef(static_cast(transX), + static_cast(transY), 0); + glScissor(clipArea.x, mTarget->h - clipArea.y - clipArea.height, + clipArea.width, clipArea.height); + + return result; +} + +void SafeOpenGLGraphics::popClipArea() +{ + gcn::Graphics::popClipArea(); + + if (mClipStack.empty()) + return; + + glPopMatrix(); + const gcn::ClipRectangle &clipArea = mClipStack.top(); + glScissor(clipArea.x, mTarget->h - clipArea.y - clipArea.height, + clipArea.width, clipArea.height); +} + +void SafeOpenGLGraphics::setColor(const gcn::Color& color) +{ + mColor = color; + glColor4ub(static_cast(color.r), + static_cast(color.g), + static_cast(color.b), + static_cast(color.a)); + + mColorAlpha = (color.a != 255); +} + +void SafeOpenGLGraphics::drawPoint(int x, int y) +{ + setTexturingAndBlending(false); + + glBegin(GL_POINTS); + glVertex2i(x, y); + glEnd(); +} + +void SafeOpenGLGraphics::drawLine(int x1, int y1, int x2, int y2) +{ + setTexturingAndBlending(false); + + glBegin(GL_LINES); + glVertex2f(static_cast(x1) + 0.5f, static_cast(y1) + 0.5f); + glVertex2f(static_cast(x2) + 0.5f, static_cast(y2) + 0.5f); + glEnd(); + + glBegin(GL_POINTS); + glVertex2f(static_cast(x2) + 0.5f, static_cast(y2) + 0.5f); + glEnd(); +} + +void SafeOpenGLGraphics::drawRectangle(const gcn::Rectangle& rect) +{ + drawRectangle(rect, false); +} + +void SafeOpenGLGraphics::fillRectangle(const gcn::Rectangle& rect) +{ + drawRectangle(rect, true); +} + +void SafeOpenGLGraphics::setTargetPlane(int width A_UNUSED, int height A_UNUSED) +{ +} + +void SafeOpenGLGraphics::setTexturingAndBlending(bool enable) +{ + if (enable) + { + if (!mTexture) + { + glEnable(OpenGLImageHelper::mTextureType); + mTexture = true; + } + + if (!mAlpha) + { + glEnable(GL_BLEND); + mAlpha = true; + } + } + else + { + mLastImage = 0; + if (mAlpha && !mColorAlpha) + { + glDisable(GL_BLEND); + mAlpha = false; + } + else if (!mAlpha && mColorAlpha) + { + glEnable(GL_BLEND); + mAlpha = true; + } + + if (mTexture) + { + glDisable(OpenGLImageHelper::mTextureType); + mTexture = false; + } + } +} + +void SafeOpenGLGraphics::drawRectangle(const gcn::Rectangle& rect, bool filled) +{ + const float offset = filled ? 0 : 0.5f; + + setTexturingAndBlending(false); + + glBegin(filled ? GL_QUADS : GL_LINE_LOOP); + glVertex2f(static_cast(rect.x) + offset, + static_cast(rect.y) + offset); + glVertex2f(static_cast(rect.x + rect.width) - offset, + static_cast(rect.y) + offset); + glVertex2f(static_cast(rect.x + rect.width) - offset, + static_cast(rect.y + rect.height) - offset); + glVertex2f(static_cast(rect.x) + offset, + static_cast(rect.y + rect.height) - offset); + glEnd(); +} + +void SafeOpenGLGraphics::bindTexture(GLenum target, GLuint texture) +{ + if (mLastImage != texture) + { + mLastImage = texture; + glBindTexture(target, texture); + } +} + +#endif // USE_OPENGL diff --git a/src/safeopenglgraphics.h b/src/safeopenglgraphics.h new file mode 100644 index 000000000..304c62d85 --- /dev/null +++ b/src/safeopenglgraphics.h @@ -0,0 +1,141 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef OPENGL1GRAPHICS_H +#define OPENGL1GRAPHICS_H + +#ifdef USE_OPENGL +#include "main.h" + +#include "graphics.h" + +//#define NO_SDL_GLEXT +#define GL_GLEXT_PROTOTYPES 1 + +#include +#include + +class SafeOpenGLGraphics : public Graphics +{ + public: + SafeOpenGLGraphics(); + + ~SafeOpenGLGraphics(); + + bool setVideoMode(int w, int h, int bpp, bool fs, + bool hwaccel, bool resize, bool noFrame); + + /** + * Draws a resclaled version of the image + */ + bool drawRescaledImage(Image *image, int srcX, int srcY, + int dstX, int dstY, + int width, int height, + int desiredWidth, int desiredHeight, + bool useColor); + + /** + * Used to get the smooth rescale option over the standard function. + */ + bool drawRescaledImage(Image *image, int srcX, int srcY, + int dstX, int dstY, + int width, int height, + int desiredWidth, int desiredHeight, + bool useColor, bool smooth); + + void drawImagePattern(const Image *image, + int x, int y, + int w, int h); + + /** + * Draw a pattern based on a rescaled version of the given image... + */ + void drawRescaledImagePattern(Image *image, + int x, int y, int w, int h, + int scaledWidth, int scaledHeight); + + bool calcImageRect(GraphicsVertexes* vert, + int x, int y, int w, int h, + Image *topLeft, Image *topRight, + Image *bottomLeft, Image *bottomRight, + Image *top, Image *right, + Image *bottom, Image *left, + Image *center); + + void drawImageRect2(GraphicsVertexes* vert, const ImageRect &imgRect); + + void calcTile(ImageVertexes *vert, int x, int y); + + void drawTile(ImageVertexes *vert); + + void updateScreen(); + + void _beginDraw(); + void _endDraw(); + + bool pushClipArea(gcn::Rectangle area); + void popClipArea(); + + void setColor(const gcn::Color &color); + + void drawPoint(int x, int y); + + void drawLine(int x1, int y1, int x2, int y2); + + void drawRectangle(const gcn::Rectangle &rect, bool filled); + + void drawRectangle(const gcn::Rectangle &rect); + + void fillRectangle(const gcn::Rectangle &rect); + + void setTargetPlane(int width, int height); + + /** + * Takes a screenshot and returns it as SDL surface. + */ + SDL_Surface *getScreenshot(); + + void prepareScreenshot(); + + static void bindTexture(GLenum target, GLuint texture); + + static GLuint mLastImage; + + protected: + bool drawImage2(const Image *image, + int srcX, int srcY, + int dstX, int dstY, + int width, int height, + bool useColor); + + void setTexturingAndBlending(bool enable); + + private: + bool mAlpha, mTexture; + bool mColorAlpha; + GLuint mFboId; + GLuint mTextureId; + GLuint mRboId; +}; +#endif + +#endif -- cgit v1.2.3-60-g2f50