diff --git a/src/CGraphics.cpp b/src/CGraphics.cpp index 5a0593b4a..736a89b29 100644 --- a/src/CGraphics.cpp +++ b/src/CGraphics.cpp @@ -733,6 +733,7 @@ Uint8 *CGraphics::getScrollbuffer(void) void CGraphics::renderHQBitmap() { +#ifndef USE_OPENGL if(HQBitmap) { SDL_Rect srcrect; @@ -745,6 +746,7 @@ void CGraphics::renderHQBitmap() HQBitmap->updateHQBitmap(g_pVideoDriver->getBGLayerSurface(), &srcrect, NULL); } +#endif } void CGraphics::loadHQGraphics(unsigned char episode, unsigned char level, const std::string& datadir) diff --git a/src/sdl/COpenGL.cpp b/src/sdl/COpenGL.cpp index 8ff654a05..5d6207b86 100644 --- a/src/sdl/COpenGL.cpp +++ b/src/sdl/COpenGL.cpp @@ -20,6 +20,25 @@ COpenGL::~COpenGL() { if(m_opengl_buffer){ delete[] m_opengl_buffer; m_opengl_buffer = NULL; } } +static void createTexture(GLuint& tex, int oglfilter, bool withAlpha = false) { + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, oglfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, oglfilter); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + if(withAlpha) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + else + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); +} + bool COpenGL::initGL(unsigned Width, unsigned Height, unsigned char Depth, GLint oglfilter, unsigned char scalex, bool aspect) { @@ -32,7 +51,7 @@ bool COpenGL::initGL(unsigned Width, unsigned Height, unsigned char Depth, if(aspect) glViewport(0,(Height-(Height*200)/240)/2,Width, (Height*200)/240); else - glViewport(0,0,Width, Height); + glViewport(0,0,Height, Width); // Set clear colour glClearColor(0,0,0,0); @@ -40,7 +59,7 @@ bool COpenGL::initGL(unsigned Width, unsigned Height, unsigned char Depth, // Set projection glMatrixMode( GL_PROJECTION ); glLoadIdentity(); - glOrtho( 0 , 1, 1, 0 , -1 , 1 ); + glOrthof( 0.0f , 1.0f, 1.0f, 0.0f , -1.0f , 1.0f ); // Now Initialize modelview matrix glMatrixMode( GL_MODELVIEW ); @@ -72,20 +91,11 @@ bool COpenGL::initGL(unsigned Width, unsigned Height, unsigned char Depth, glGetTexLevelParameterfv.*/ - glEnable (m_texparam); - glBindTexture(m_texparam, 1); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - glTexParameteri(m_texparam, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri (m_texparam, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - - glTexParameteri (m_texparam, GL_TEXTURE_MAG_FILTER, oglfilter); - glTexParameteri (m_texparam, GL_TEXTURE_MIN_FILTER, oglfilter); - - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - + glEnable(GL_TEXTURE_2D); + createTexture(m_texture, oglfilter); + createTexture(m_texBG, oglfilter); + createTexture(m_texFG, oglfilter, true); + if(scalex > 1) m_opengl_buffer = new char[GAME_STD_HEIGHT*GAME_STD_WIDTH*scalex*Depth]; else @@ -110,13 +120,88 @@ bool COpenGL::initGL(unsigned Width, unsigned Height, unsigned char Depth, void COpenGL::setSurface(SDL_Surface *blitsurface) { m_blitsurface = blitsurface; } -void COpenGL::render(void) -{ - //Clear the screen - glClear(GL_COLOR_BUFFER_BIT); // Clear The Screen +static void loadSurface(GLuint texture, SDL_Surface* surface) { + glBindTexture(GL_TEXTURE_2D, texture); + LockSurface(surface); + if(surface->format->BitsPerPixel == 24) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels); + else { + // we assume RGBA + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels); + } + UnlockSurface(surface); +} +void COpenGL::reloadBG(SDL_Surface* surf) { + loadSurface(m_texBG, surf); +} + +void COpenGL::reloadFG(SDL_Surface* surf) { + loadSurface(m_texFG, surf); +} + +static void renderTexture(GLuint texture, bool withAlpha = false) { + glViewport(0,200,512, 256); + glLoadIdentity(); + //glOrthof(0, 1, 0, 1, 0, 1); + //glOrthof(0, 1, 0, 1, 0, 1); + + + // Set up an array of values to use as the sprite vertices. + GLfloat vertices[] = + { + 0, 0, + 1, 0, + 1, 1, + 0, 1, + }; + + // Set up an array of values for the texture coordinates. + GLfloat texcoords[] = + { + 0, 0, + 1, 0, + 1, 1, + 0, 1, + }; + + //Render the vertices by pointing to the arrays. + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glVertexPointer(2, GL_FLOAT, 0, vertices); + glTexCoordPointer(2, GL_FLOAT, 0, texcoords); + + glEnable(GL_BLEND); + if(withAlpha) + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + else + glBlendFunc(GL_ONE, GL_ZERO /*GL_SRC_COLOR*/); + + glBindTexture (GL_TEXTURE_2D, texture); + + // Set the texture parameters to use a linear filter when minifying. + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + //Finally draw the arrays. + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + glDisable(GL_BLEND); + +} + +void COpenGL::render(bool withFG) +{ + //glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + renderTexture(m_texBG); + LockSurface(m_blitsurface); + glBindTexture (GL_TEXTURE_2D, m_texture); + if(m_ScaleX == 2) //Scale 2x { scale(2, m_opengl_buffer, (GAME_STD_WIDTH<<1)*(m_Depth>>3), m_blitsurface->pixels, @@ -141,26 +226,14 @@ void COpenGL::render(void) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GAME_STD_WIDTH<<2, GAME_STD_HEIGHT<<2, 0, GL_BGRA, GL_UNSIGNED_BYTE, m_opengl_buffer); } else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GAME_STD_WIDTH, GAME_STD_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_BYTE, m_blitsurface->pixels); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, m_blitsurface->pixels); + UnlockSurface(m_blitsurface); - glBindTexture (GL_TEXTURE_2D, 1); + renderTexture(m_texture); - glBegin (GL_QUADS); - glTexCoord2f (0.0, 0.0); - glVertex3f (0.0, 0.0, 0.0); - glTexCoord2f (1.0, 0.0); - glVertex3f (1.0, 0.0, 0.0); - glTexCoord2f (1.0, 1.0); - glVertex3f (1.0, 1.0, 0.0); - glTexCoord2f (0.0, 1.0); - glVertex3f (0.0, 1.0, 0.0); - glEnd(); - - UnlockSurface(m_blitsurface); - - // Reset (Position?) - glLoadIdentity(); - - SDL_GL_SwapBuffers(); + if(withFG) + renderTexture(m_texFG, true); + + SDL_GL_SwapBuffers(); } diff --git a/src/sdl/COpenGL.h b/src/sdl/COpenGL.h index 5d9ccea88..d1da8d8d2 100644 --- a/src/sdl/COpenGL.h +++ b/src/sdl/COpenGL.h @@ -13,7 +13,14 @@ #define __CG_COPENGL_H__ #include + +#if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR) +#include +#include +#else #include +#endif + #include "../scale2x/scalebit.h" class COpenGL { @@ -21,11 +28,13 @@ public: COpenGL(); virtual ~COpenGL(); - void render(void); + void render(bool withFG); bool initGL(unsigned Width, unsigned Height, unsigned char Depth, GLint oglfilter, unsigned char scalex, bool aspect); void setSurface(SDL_Surface *blitsurface); + void reloadBG(SDL_Surface* surf); + void reloadFG(SDL_Surface* surf); private: SDL_Surface *m_blitsurface; @@ -33,6 +42,10 @@ private: unsigned char m_Depth; unsigned char m_ScaleX; unsigned int m_texparam; + GLuint m_texture; + + GLuint m_texBG, m_texFG; + }; #endif diff --git a/src/sdl/CVideoDriver.cpp b/src/sdl/CVideoDriver.cpp index 7325f4880..bb86751b1 100644 --- a/src/sdl/CVideoDriver.cpp +++ b/src/sdl/CVideoDriver.cpp @@ -50,6 +50,8 @@ int ConsoleExpireTimer = 0; CVideoDriver::CVideoDriver() { // Default values + m_updateFG = false; + showfps=true; #ifdef WIZ m_Resolution.width=320; @@ -91,14 +93,17 @@ CVideoDriver::CVideoDriver() { BlitSurface=NULL; #if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR) - st_resolution resolution = {320, 480, 32}; - m_Resolutionlist.push_back(resolution); + m_Resolution.width = 320; // 320; + m_Resolution.height = 200; // 480; + m_Resolution.depth = 32; + m_Resolutionlist.push_back(m_Resolution); m_Resolution_pos = m_Resolutionlist.begin(); Zoom = 1; Filtermode = 0; FrameSkip=1; m_targetfps = 40; + m_aspect_correction = false; #else m_Resolution_pos = m_Resolutionlist.begin(); @@ -221,7 +226,7 @@ extern "C" void iPhoneRotateScreen(); #endif bool CVideoDriver::start(void) -{ +{ bool retval = false; if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO) < 0) @@ -296,7 +301,8 @@ bool CVideoDriver::applyMode(void) if(m_opengl) { SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); - SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); + // TODO: unknown in SDL 1.3. important? +// SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); Mode |= SDL_OPENGL; } #endif @@ -354,6 +360,20 @@ void CVideoDriver::setZoom(short value) bool CVideoDriver::createSurfaces(void) { + static const Uint32 RGBA[] = { +#if SDL_BYTEORDER == SDL_LIL_ENDIAN // OpenGL RGBA masks + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000 +#else + 0xFF000000, + 0x00FF0000, + 0x0000FF00, + 0x000000FF +#endif + }; + // This function creates the surfaces which are needed for the game. unsigned stretch_blit_yoff; @@ -367,15 +387,16 @@ bool CVideoDriver::createSurfaces(void) return false; } - BGLayerSurface = SDL_CreateRGBSurface(Mode,320, 200, m_Resolution.depth, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask); + BGLayerSurface = SDL_CreateRGBSurface(SDL_SWSURFACE/*Mode*/,512, 256, 24, 0x0000ff, 0x00ff00, 0xff0000, 0x0); + //BGLayerSurface = SDL_CreateRGBSurface(SDL_SWSURFACE/*Mode*/,320, 200, m_Resolution.depth, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask); if (!BGLayerSurface) { g_pLogFile->textOut(RED,"VideoDriver: Couldn't create BGLayerSurface!
"); return false; } - - FGLayerSurface = SDL_CreateRGBSurface(Mode,320, 200, m_Resolution.depth, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask); + FGLayerSurface = SDL_CreateRGBSurface(SDL_SWSURFACE/*Mode*/,512, 256, 32, RGBA[0], RGBA[1], RGBA[2], RGBA[3]); + //FGLayerSurface = SDL_CreateRGBSurface(SDL_SWSURFACE/*Mode*/,320, 200, m_Resolution.depth, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask); if (!FGLayerSurface) { g_pLogFile->textOut(RED,"VideoDriver: Couldn't create FGLayerSurface!
"); @@ -387,6 +408,10 @@ bool CVideoDriver::createSurfaces(void) //Set surface alpha SDL_SetAlpha( FGLayerSurface, SDL_SRCALPHA, 225 ); + SDL_Rect r = {0, 0, 512, 256}; + SDL_FillRect(FGLayerSurface, &r, SDL_MapRGBA(FGLayerSurface->format, 0, 0, 0, 0)); + + if(m_Resolution.width == 320 && !m_opengl) { g_pLogFile->textOut("Blitsurface = Screen
"); @@ -399,7 +424,14 @@ bool CVideoDriver::createSurfaces(void) else { g_pLogFile->textOut("Blitsurface = creatergbsurfacefrom
"); - BlitSurface = SDL_CreateRGBSurface(Mode,GAME_STD_WIDTH, GAME_STD_HEIGHT, m_Resolution.depth, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask); +#ifdef USE_OPENGL + // We must create a surface with the size being a power of two. + // Also, we will use a handy format. + BlitSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 512, 256, 24, 0x0000ff, 0x00ff00, 0xff0000, 0x0); +#else + BlitSurface = SDL_CreateRGBSurface(SDL_SWSURFACE /*Mode & ~SDL_DOUBLEBUF & ~SDL_HWPALETTE & ~SDL_HWSURFACE*/,GAME_STD_WIDTH, GAME_STD_HEIGHT, m_Resolution.depth, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask); +#endif + if (!BlitSurface) { g_pLogFile->textOut(RED,"VidDrv_Start(): Couldn't create BlitSurface!
"); @@ -437,7 +469,7 @@ void CVideoDriver::pal_apply(void) } static void sb_lowblit(SDL_Surface* src, SDL_Rect* srcrect, SDL_Surface* dst, SDL_Rect* dstrect) { -#if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR) +#if !defined(USE_OPENGL) && (defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR)) // SDL_BlitSurface doesn't work for some reason int _xend = srcrect->x + dstrect->w; int _yend = srcrect->y + dstrect->h; @@ -551,7 +583,9 @@ char tempbuf[80]; } void CVideoDriver::blitBGLayer(void) { +#ifndef USE_OPENGL SDL_BlitSurface(BGLayerSurface, NULL, BlitSurface, NULL); +#endif } void CVideoDriver::update_screen(void) @@ -559,15 +593,18 @@ void CVideoDriver::update_screen(void) #ifdef USE_OPENGL if(m_opengl) { - SDL_BlitSurface(FGLayerSurface, NULL, BlitSurface, NULL); + if(m_updateFG) + mp_OpenGL->reloadFG(FGLayerSurface); + + mp_OpenGL->render(m_updateFG); - mp_OpenGL->render(); + if(m_updateFG) { + // Flush the layers + SDL_Rect r = {0, 0, 512, 256}; + SDL_FillRect(FGLayerSurface, &r, SDL_MapRGBA(FGLayerSurface->format, 0, 0, 0, 0)); - LockSurface(FGLayerSurface); - // Flush the layers - memset(FGLayerSurface->pixels,SDL_MapRGB(FGLayerSurface->format, 0, 0, 0), - GAME_STD_WIDTH*GAME_STD_HEIGHT*FGLayerSurface->format->BytesPerPixel); - UnlockSurface(FGLayerSurface); + m_updateFG = false; + } } else // No OpenGL but Software Rendering #endif @@ -780,27 +817,29 @@ void CVideoDriver::setpixel(unsigned int x, unsigned int y, unsigned char c) if( x >= GAME_STD_WIDTH || y >= GAME_STD_HEIGHT ) // out of Bonds!!! return; - if(BlitSurface->format->BitsPerPixel == 16) + if(FGLayerSurface->format->BitsPerPixel == 16) { Uint16 *ubuff16; ubuff16 = (Uint16*) FGLayerSurface->pixels; - ubuff16 += (y * 320) + x; - *ubuff16 = convert4to16BPPcolor(c, BlitSurface); + ubuff16 += (y * FGLayerSurface->pitch/FGLayerSurface->format->BytesPerPixel) + x; + *ubuff16 = convert4to16BPPcolor(c, FGLayerSurface); } - else if(BlitSurface->format->BitsPerPixel == 32) + else if(FGLayerSurface->format->BitsPerPixel == 32) { Uint32 *ubuff32; ubuff32 = (Uint32*) FGLayerSurface->pixels; - ubuff32 += (y * 320) + x; - *ubuff32 = convert4to32BPPcolor(c, BlitSurface); + ubuff32 += (y * FGLayerSurface->pitch/FGLayerSurface->format->BytesPerPixel) + x; + *ubuff32 = convert4to32BPPcolor(c, FGLayerSurface); } else - { + { // 8bit surface assumed Uint8 *ubuff8; ubuff8 = (Uint8*) FGLayerSurface->pixels; - ubuff8 += (y * 320) + x; + ubuff8 += (y * FGLayerSurface->pitch) + x; *ubuff8 = (Uint8) c; } + + m_updateFG = true; } unsigned char CVideoDriver::getpixel(int x, int y) { @@ -889,4 +928,10 @@ SDL_Surface *CVideoDriver::getScrollSurface(void) SDL_Surface *CVideoDriver::getBGLayerSurface(void) { return BGLayerSurface; } +void CVideoDriver::updateBG() { +#ifdef USE_OPENGL + if(m_opengl) + mp_OpenGL->reloadBG(BGLayerSurface); +#endif +} diff --git a/src/sdl/CVideoDriver.h b/src/sdl/CVideoDriver.h index 0dace2d9b..13c782833 100644 --- a/src/sdl/CVideoDriver.h +++ b/src/sdl/CVideoDriver.h @@ -80,7 +80,8 @@ public: #endif SDL_Surface *getScrollSurface(void); SDL_Surface *getBGLayerSurface(void); - + void updateBG(); + void setMode(int width, int height,int depth); void setFrameskip(unsigned short value); void setFilter(short value); @@ -139,5 +140,6 @@ private: // buffer of 320x200. SDL_Surface *BlitSurface; + bool m_updateFG; }; #endif /* CVIDEODRIVER_H_ */