renderbackendopengl.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2005-2008 by the FIFE team                              *
00003  *   http://www.fifengine.de                                               *
00004  *   This file is part of FIFE.                                            *
00005  *                                                                         *
00006  *   FIFE is free software; you can redistribute it and/or                 *
00007  *   modify it under the terms of the GNU Lesser General Public            *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2.1 of the License, or (at your option) any later version.    *
00010  *                                                                         *
00011  *   This library is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00014  *   Lesser General Public License for more details.                       *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Lesser General Public      *
00017  *   License along with this library; if not, write to the                 *
00018  *   Free Software Foundation, Inc.,                                       *
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
00020  ***************************************************************************/
00021 
00022 // Standard C++ library includes
00023 
00024 // Platform specific includes
00025 
00026 // 3rd party library includes
00027 #include <SDL.h>
00028 
00029 // FIFE includes
00030 #include "util/base/exception.h"
00031 
00032 #include "fife_opengl.h"
00033 #include "glimage.h"
00034 #include "renderbackendopengl.h"
00035 #include "SDL_image.h"
00036 
00037 namespace FIFE {
00038 
00039     RenderBackendOpenGL::RenderBackendOpenGL(const SDL_Color& colorkey) : RenderBackend(colorkey) {
00040         // Get the pixelformat we want.
00041         SDL_Surface* testsurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, 1, 1, 32,
00042                 RMASK, GMASK, BMASK ,AMASK);
00043 
00044         m_rgba_format = *(testsurface->format);
00045         SDL_FreeSurface(testsurface);
00046     }
00047 
00048     const std::string& RenderBackendOpenGL::getName() const {
00049         static std::string backend_name = "OpenGL";
00050         return backend_name;
00051     }
00052 
00053     RenderBackendOpenGL::~RenderBackendOpenGL() {
00054     }
00055 
00056 
00057     void RenderBackendOpenGL::init() {
00058         Uint32 flags = SDL_INIT_VIDEO;
00059         if (SDL_InitSubSystem(flags) < 0)
00060             throw SDLException(SDL_GetError());
00061         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
00062 
00063         SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); // temporary hack
00064     }
00065 
00066     Image* RenderBackendOpenGL::createMainScreen(unsigned int width, unsigned int height, unsigned char bitsPerPixel, bool fs, const std::string& title, const std::string& icon) {
00067         delete m_screen;
00068         m_screen = 0;
00069 
00070         Uint32 flags = SDL_OPENGL | SDL_HWPALETTE | SDL_HWACCEL;
00071         if ( fs ) {
00072             flags |= SDL_FULLSCREEN;
00073         }
00074 
00075         if(icon != "") {
00076             SDL_Surface *img = IMG_Load(icon.c_str());
00077             if(img != NULL) {
00078                 SDL_WM_SetIcon(img, 0);
00079             }
00080         }
00081 
00082         SDL_Surface* screen = NULL;
00083 
00084         if( 0 == bitsPerPixel ) {
00086             unsigned char possibleBitsPerPixel[] = {32, 24, 16, 0};
00087             int i = 0;
00088             while( true ) {
00089                 bitsPerPixel = possibleBitsPerPixel[i];
00090                 if( !bitsPerPixel ) {
00091                     throw SDLException("Videomode not available");
00092                 }
00093 
00094                 if ( SDL_VideoModeOK(width, height, bitsPerPixel, flags) ) {
00095                     screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags);
00096                     if( screen ) {
00097                         break;
00098                     }
00099                 }
00100                 ++i;
00101             }
00102         } else {
00103             if ( !SDL_VideoModeOK(width, height, bitsPerPixel, flags) ) {
00104                 throw SDLException("Videomode not available");
00105             }
00106             screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags);
00107         }
00108 
00109         SDL_WM_SetCaption(title.c_str(), 0);
00110 
00111         if (!screen) {
00112             throw SDLException(SDL_GetError());
00113         }
00114 
00115         glViewport(0, 0, width, height);
00116         glMatrixMode(GL_PROJECTION);
00117         gluOrtho2D(0, width, height, 0);
00118         glMatrixMode(GL_MODELVIEW);
00119 
00120         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
00121         glEnable(GL_TEXTURE_2D);
00122         glEnable(GL_BLEND);
00123         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00124 
00125         glEnable(GL_SCISSOR_TEST);
00126 
00127         glPointSize(1.0);
00128         glLineWidth(1.0);
00129 
00130         m_screen = new GLImage(screen);
00131         return m_screen;
00132     }
00133 
00134     void RenderBackendOpenGL::startFrame() {
00135         glDisable(GL_SCISSOR_TEST);
00136         glClear(GL_COLOR_BUFFER_BIT);
00137         glEnable(GL_SCISSOR_TEST);
00138     }
00139 
00140     void RenderBackendOpenGL::endFrame() {
00141         SDL_GL_SwapBuffers();
00142     }
00143 
00144     Image* RenderBackendOpenGL::createImage(SDL_Surface* surface) {
00145         // Given an abritary surface, we must convert it to the format GLImage will understand.
00146         // It's easiest to let SDL do this for us.
00147 
00148         // Uh. Gotta love this :-)
00149         // Check for colorkey too?
00150         // Leave out the loss/shift checks?
00151         if(    m_rgba_format.BitsPerPixel == surface->format->BitsPerPixel
00152             && m_rgba_format.Rmask == surface->format->Rmask
00153             && m_rgba_format.Gmask == surface->format->Gmask
00154             && m_rgba_format.Bmask == surface->format->Bmask
00155             && m_rgba_format.Amask == surface->format->Amask
00156             && m_rgba_format.Rshift == surface->format->Rshift
00157             && m_rgba_format.Gshift == surface->format->Gshift
00158             && m_rgba_format.Bshift == surface->format->Bshift
00159             && m_rgba_format.Ashift == surface->format->Ashift
00160             && m_rgba_format.Rloss == surface->format->Rloss
00161             && m_rgba_format.Gloss == surface->format->Gloss
00162             && m_rgba_format.Bloss == surface->format->Bloss
00163             && m_rgba_format.Aloss == surface->format->Aloss
00164             && surface->flags & SDL_SRCALPHA   ) {
00165 
00166             return new GLImage(surface);
00167         }
00168 
00169         SDL_Surface* conv = SDL_ConvertSurface(surface, &m_rgba_format, SDL_SWSURFACE|SDL_SRCALPHA);
00170         GLImage* image = new GLImage(conv);
00171         SDL_FreeSurface( surface );
00172         return image;
00173     }
00174 
00175     Image* RenderBackendOpenGL::createImage(const uint8_t* data, unsigned int width, unsigned int height) {
00176         return new GLImage(data, width, height);
00177     }
00178 
00179     bool RenderBackendOpenGL::putPixel(int x, int y, int r, int g, int b) {
00180         if ((x < 0) || (x >= (int)getWidth()) || (y < 0) || (y >= (int)getHeight())) {
00181             return false;
00182         }
00183         glColor4ub(r, g, b, 255);
00184         glBegin(GL_POINTS);
00185         glVertex2i(x, y);
00186         glEnd();
00187         return true;
00188     }
00189 
00190     void RenderBackendOpenGL::drawLine(const Point& p1, const Point& p2, int r, int g, int b) {
00191         glColor4ub(r, g, b, 255);
00192         glBegin(GL_LINES);
00193         glVertex3f(p1.x+0.5f, p1.y+0.5f, 0);
00194         glVertex3f(p2.x+0.5f, p2.y+0.5f, 0);
00195         glEnd();
00196 
00197         glBegin(GL_POINTS);
00198         glVertex3f(p2.x+0.5f, p2.y+0.5f, 0);
00199         glEnd();
00200     }
00201 
00202     void RenderBackendOpenGL::drawQuad(const Point& p1, const Point& p2, const Point& p3, const Point& p4,  int r, int g, int b) {
00203         glColor4ub(r, g, b, 165);
00204         glBegin(GL_QUADS);
00205         glVertex3f(p1.x, p1.y, 0);
00206         glVertex3f(p2.x, p2.y, 0);
00207         glVertex3f(p3.x, p3.y, 0);
00208         glVertex3f(p4.x, p4.y, 0);
00209         glEnd();
00210     }
00211 
00212     void RenderBackendOpenGL::drawVertex(const Point& p, const uint8_t size, int r, int g, int b){
00213 
00214         GLfloat width;
00215 
00216         glGetFloatv(GL_LINE_WIDTH, &width);
00217         glLineWidth(1.0);
00218 
00219         glBegin(GL_LINE_LOOP);
00220         glColor4ub(r, g, b, 255);
00221 
00222         glVertex3f(p.x-size, p.y+size, 0);
00223         glVertex3f(p.x+size, p.y+size, 0);
00224         glVertex3f(p.x+size, p.y-size, 0);
00225         glVertex3f(p.x-size, p.y-size, 0);
00226 
00227         glEnd();
00228 
00229         glLineWidth(width);
00230     }
00231 }
Generated by  doxygen 1.6.2-20100208