improved OpenGL support, almost no blitting anymore

This commit is contained in:
Albert Zeyer
2009-11-16 16:43:36 +01:00
parent 7e252b5586
commit b637f832d3
5 changed files with 200 additions and 65 deletions

View File

@@ -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)

View File

@@ -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();
}

View File

@@ -13,7 +13,14 @@
#define __CG_COPENGL_H__
#include <SDL.h>
#if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR)
#include <OpenGLES/ES1/gl.h>
#include <OpenGLES/ES1/glext.h>
#else
#include <SDL_opengl.h>
#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

View File

@@ -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!<br>");
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!<br>");
@@ -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<br>");
@@ -399,7 +424,14 @@ bool CVideoDriver::createSurfaces(void)
else
{
g_pLogFile->textOut("Blitsurface = creatergbsurfacefrom<br>");
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!<br>");
@@ -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
}

View File

@@ -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_ */