typedef void (*GameCallback)(bool);
typedef void (*MouseCallback)(int, int, bool, bool, bool, bool); // X, Y, up/down, isLeft, isMiddle, isRight
+class VertexController;
+
+typedef enum {
+ Software = 0,
+ Accel2d = 1,
+ OpenGL = 2
+} DispMode_t;
+
class TextManager; // Forward decl
// Input Mode enum. This is the max events allowed in one go.
class ContextManager {
public:
ContextManager();
- ContextManager(int scr_width, int scr_height, bool fulls, bool accel);
+ ContextManager(int scr_width, int scr_height, bool fulls, DispMode_t disp);
// Initialization.
- void InitWindow(int width, int height, bool fulls, bool accel);
- void InitWindowLogical(int width, int height, int width_log, int height_log, bool fulls, bool accel);
+ void InitWindow(int width, int height, bool fulls, DispMode_t disp);
+ void InitWindowLogical(int width, int height, int width_log, int height_log, bool fulls, DispMode_t disp);
// Set window title
void SetTitle(char* title);
- // Display related.
+ // Render related.
void Clear();
void Flush();
-
void ClearOverlay();
+ void Blit(void* inp, SDL_Rect* src, SDL_Rect* dst, SDL_Rect* glrect);
+ void OverlayBlit(void* inp, SDL_Rect* src, SDL_Rect* dst, SDL_Rect* glrect);
+ // Accessors.
SDL_Surface* Surface();
SDL_Renderer* Renderer();
bool Accelerated();
- void Blit(void* inp, SDL_Rect* src, SDL_Rect* dst);
- void OverlayBlit(void* inp, SDL_Rect* src, SDL_Rect* dst);
-
- // Support funcs.
+ bool GLMode();
int GetWidth();
int GetHeight();
- // Get Input State and Modify input state.
+ // Run input callbacks and update states.
bool Input();
// Abstract remappable key functions.
void RemapKey(int index, SDL_Keycode to);
void InputMode(InMode mode);
- // Gets the AudioManager & TextManager
+ // Gets the AudioManager & TextManager for usage.
AudioManager* Audio();
TextManager* Text();
+ VertexController* Vertex();
// Exit methods.
void SetQuit();
bool GetQuit();
- // Logic sync limiter.
+ // Logic sync limiter @ 60fps
void StartSync();
void EndSync();
+ // Wrapper functions for tex load.
+ void* LoadImage(char* fname);
+ void* LoadImageMemory(void* mem, size_t len, char* type);
+ void* AccelImage(void* in);
+ void* GLTexImage(void* in);
+
~ContextManager();
private:
// Lower init.
- // DELETEME - Software rendering doesn't work now.
void _InitWindowSW(int width, int height, bool fulls);
void _InitWindowAC(int width, int height, bool fulls);
- // DELETEME - Software rendering doesn't work now.
+ void _InitWindowGL(int width, int height, bool fulls);
+
+ // Lower init, logical.
void _InitWindowLogicalSW(int width_win, int height_win, int width_log, int height_log, bool fulls);
void _InitWindowLogicalAC(int width_win, int height_win, int width_log, int height_log, bool fulls);
+ void _InitWindowLogicalGL(int width_win, int height_win, int width_log, int height_log, bool fulls);
+ // Used to load default values in abscense of GNU exts
void DefaultVariables();
InMode inputmode;
SDL_Surface* surface, *surface_o;
SDL_Texture* texture, *texture_o;
SDL_Renderer* renderer;
+ SDL_GLContext glctx;
+
// use logical size
bool logicalRender;
bool accelerate;
+ bool opengl_mode;
bool StartQuit;
AudioManager* audioMgr;
TextManager* txtMgr;
+ VertexController* vertCnt;
SDL_Keycode* inputMappings; // This can actually be used instead of InputList now. Weird.
bool* inputStates;
// use logical size
logicalRender = false;
accelerate = false;
+ opengl_mode = false;
StartQuit = false;
// Initializes SDL and saves stuff into the context.
- ContextManager::ContextManager(int scr_width, int scr_height, bool fulls, bool accel) {
+ ContextManager::ContextManager(int scr_width, int scr_height, bool fulls, DispMode_t disp) {
DefaultVariables();
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0) {
#endif
}
else {
- this->InitWindow(scr_width, scr_height, fulls, accel);
+ this->InitWindow(scr_width, scr_height, fulls, disp);
}
audioMgr = new AudioManager();
// Creates a window.
- void ContextManager::InitWindow(int width, int height, bool fulls, bool accel) {
+ void ContextManager::InitWindow(int width, int height, bool fulls, DispMode_t disp) {
this->WIN_width = width;
this->WIN_height = height;
this->LOG_width = width;
this->LOG_height = height;
#ifdef DEBUG_OVERKILL
- printf("[ContextManager::InitWindow] Params: w:%d h:%d f:%d a:%d\n", width, height, fulls, accel);
+ printf("[ContextManager::InitWindow] Params: w:%d h:%d f:%d a:%d\n", width, height, fulls, disp);
#endif
- if(accel) {
+ if (disp == Accel2d) {
_InitWindowAC(width, height, fulls);
this->texture_o = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
SDL_SetTextureBlendMode(this->texture_o, SDL_BLENDMODE_BLEND);
}
- else {
+ else if (disp == Software) {
_InitWindowSW(width, height, fulls);
this->surface_o = SDL_CreateRGBSurface(0, width, height, 32, RED_MASK, GREEN_MASK, BLUE_MASK, ALPHA_MASK);
SDL_SetSurfaceBlendMode(this->surface_o, SDL_BLENDMODE_BLEND);
}
+ else if (disp == OpenGL) {
+ _InitWindowGL(width, height, fulls);
+ }
txtMgr = new TextManager(this);
}
}
}
+ // OpenGL window. Note - a LOT functions different in this mode.
+ void ContextManager::_InitWindowGL(int width, int height, bool fulls) {
+
+ opengl_mode = true;
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+
+ // Request OpenGL 3.0 context. Yes, not 3.1, 3.2, 4.0. THREE POINT O'.
+ // Why? I use the fixed function pipeline which is gonzo in >3.1
+ // and I'm not about to learn a new api that consists of VBOs, FBOs,
+ // and shader code (which btw, is retarded.)
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+
+ if(!fulls)
+ this->window = SDL_CreateWindow("Zero", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN|SDL_WINDOW_OPENGL);
+ else
+ this->window = SDL_CreateWindow("Zero", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_FULLSCREEN|SDL_WINDOW_OPENGL);
+
+ glctx = SDL_GL_CreateContext(window);
+
+ glEnable( GL_TEXTURE_2D );
+
+ glViewport( 0, 0, width, height );
+
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+
+ glOrtho(0.0f, width, height, 0.0f, -1.0f, 1.0f);
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ vertCnt = new VertexController(this);
+ }
+
// Init window with a logical size and a real one. Determines which backend to use.
- void ContextManager::InitWindowLogical(int width_win, int height_win, int width_log, int height_log, bool fulls, bool accel) {
+ void ContextManager::InitWindowLogical(int width_win, int height_win, int width_log, int height_log, bool fulls, DispMode_t disp) {
this->LOG_width = width_log;
this->LOG_height = height_log;
this->WIN_width = width_win;
this->WIN_height = height_win;
#ifdef DEBUG_OVERKILL
- printf("[ContextManager::InitWindowLogical] phyw:%d phyh:%d logw:%d logh:%d f:%d a:%d\n", width_win, height_win, width_log, height_log, fulls, accel);
+ printf("[ContextManager::InitWindowLogical] phyw:%d phyh:%d logw:%d logh:%d f:%d a:%d\n", width_win, height_win, width_log, height_log, fulls, disp);
#endif
- if (accel) {
+ if (disp == Accel2d) {
_InitWindowLogicalAC(width_win, height_win, width_log, height_log, fulls);
this->texture_o = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width_win, height_win);
SDL_SetTextureBlendMode(this->texture_o, SDL_BLENDMODE_BLEND);
}
- else {
+ else if (disp == Software) {
_InitWindowLogicalSW(width_win, height_win, width_log, height_log, fulls);
this->surface_o = SDL_CreateRGBSurface(0, width_win, height_win, 32, RED_MASK, GREEN_MASK, BLUE_MASK, ALPHA_MASK);
SDL_SetSurfaceBlendMode(this->surface_o, SDL_BLENDMODE_BLEND);
SDL_RenderClear(renderer);
}
+ else if (opengl_mode) {
+ glClearColor(0,0,0,0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
else {
if (logicalRender)
SDL_FillRect(this->surface, NULL, SDL_MapRGB(this->surface->format, 0x0, 0x0, 0x0));
SDL_RenderClear(renderer);
SDL_SetRenderTarget(renderer, NULL);
}
+ else if (opengl_mode) {
+ glClearColor(0,0,0,0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
else {
SDL_FillRect(this->surface_o, NULL, SDL_MapRGBA(this->surface_o->format, 0, 0, 0, 0));
}
SDL_RenderPresent(renderer);
}
+ else if (opengl_mode) {
+ SDL_GL_SwapWindow(window);
+ }
else {
if(logicalRender)
SDL_BlitScaled(this->surface, NULL, SDL_GetWindowSurface(this->window), NULL);
return renderer;
}
- // return the renderer.
+ // return the mode.
bool ContextManager::Accelerated() {
return accelerate;
}
+ // return the mode.
+ bool ContextManager::GLMode() {
+ return opengl_mode;
+ }
+
// Blit data via cast. inp should be a SDL_Surface or SDL_Texture.
- void ContextManager::Blit(void* inp, SDL_Rect* src, SDL_Rect* dst) {
+ void ContextManager::Blit(void* inp, SDL_Rect* src, SDL_Rect* dst, SDL_Rect* glrect) {
if(accelerate) {
if (logicalRender) SDL_SetRenderTarget(renderer, texture);
if (logicalRender) SDL_SetRenderTarget(renderer, NULL);
}
+ else if(opengl_mode) {
+ GLuint in = ((GLuint*)inp)[0];
+
+ // printf("[GL] (blit) in: %d\n", in);
+
+ GLfloat x_tex, y_tex, x2_tex, y2_tex;
+ if(glrect == NULL) {
+ x_tex = 0.0f;
+ y_tex = 0.0f;
+ x2_tex = 1.0f;
+ y2_tex = 1.0f;
+ }
+ else {
+ GLfloat tex_width, tex_height;
+
+ tex_width = 1.0f / ((float)glrect->w);
+ tex_height = 1.0f / ((float)glrect->h);
+
+ x_tex = tex_width * ((float)(src->x));
+ y_tex = tex_height * ((float)(src->y));
+ x2_tex = tex_width * ((float)(src->x + src->w));
+ y2_tex = tex_height * ((float)(src->y + src->h));
+
+ // printf("Detail Calculation] tex_w:%f tex_h:%f x_t:%f y_t:%f x2_t:%f y2_t:%f\n", tex_width, tex_height, x_tex, y_tex, x2_tex, y2_tex);
+ }
+
+ GLfloat x_box, y_box, x2_box, y2_box;
+ x_box = dst->x;
+ y_box = dst->y + dst->h;
+ x2_box = dst->x + dst->w;
+ y2_box = dst->y;
+
+ //printf("[GL] Box: x.%f y.%f x2.%f y2.%f \n", x_box, y_box, x2_box, y2_box);
+
+ glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); //Don't use special coloring
+
+ // Bind the texture to which subsequent calls refer to
+ glBindTexture( GL_TEXTURE_2D, in );
+
+ glBegin( GL_QUADS );
+ //Bottom-left vertex (corner)
+ glTexCoord2f( x_tex, y_tex );
+ glVertex3f( x_box, y2_box, 0.0f );
+
+ //Bottom-right vertex (corner)
+ glTexCoord2f( x2_tex, y_tex );
+ glVertex3f( x2_box, y2_box, 0.0f );
+
+ //Top-right vertex (corner)
+ glTexCoord2f( x2_tex, y2_tex );
+ glVertex3f( x2_box, y_box, 0.0f );
+
+ //Top-left vertex (corner)
+ glTexCoord2f( x_tex, y2_tex );
+ glVertex3f( x_box, y_box, 0.0f );
+ glEnd();
+
+ glBindTexture( GL_TEXTURE_2D, 0 );
+ }
else {
SDL_BlitSurface((SDL_Surface*)inp, src, surface, dst);
}
}
// Blit data to overlay via cast. inp should be a SDL_Surface or SDL_Texture.
- void ContextManager::OverlayBlit(void* inp, SDL_Rect* src, SDL_Rect* dst) {
+ void ContextManager::OverlayBlit(void* inp, SDL_Rect* src, SDL_Rect* dst, SDL_Rect* glrect) {
// Recalculate src and dst based on upscale.
double OUTW_Ratio, OUTH_Ratio;
OUTW_Ratio = (double)WIN_width / (double)LOG_width;
dst->x = (int)(((double)dst->x) * OUTW_Ratio);
dst->y = (int)(((double)dst->y) * OUTH_Ratio);
- dst->w = (int)(((double)dst->w) * OUTW_Ratio);
- dst->h = (int)(((double)dst->h) * OUTH_Ratio);
+ if(OUTW_Ratio < 1) dst->w = (int)(((double)dst->w) * OUTW_Ratio);
+ if(OUTH_Ratio < 1) dst->h = (int)(((double)dst->h) * OUTH_Ratio);
if(accelerate) {
if (logicalRender) SDL_SetRenderTarget(renderer, texture_o);
if (logicalRender) SDL_SetRenderTarget(renderer, NULL);
}
+ else if(opengl_mode) {
+ GLuint in = ((GLuint*)inp)[0];
+
+ GLfloat x, y, x2, y2;
+ x = 1.0f / glrect->x;
+ y = 1.0f / glrect->y;
+ x2 = 1.0f / (glrect->w + glrect->x);
+ y2 = 1.0f / (glrect->h + glrect->y);
+
+ // Bind the texture to which subsequent calls refer to
+ glBindTexture( GL_TEXTURE_2D, in );
+
+ glBegin( GL_QUADS );
+ //Bottom-left vertex (corner)
+ glTexCoord2f( x, y );
+ glVertex3i( dst->x, dst->y + dst->h, 0.0f );
+
+ //Bottom-right vertex (corner)
+ glTexCoord2f( x2, y );
+ glVertex3i( dst->x + dst->w, dst->y + dst->h, 0.0f );
+
+ //Top-right vertex (corner)
+ glTexCoord2f( x2, y2 );
+ glVertex3i( dst->x + dst->w, dst->y, 0.0f );
+
+ //Top-left vertex (corner)
+ glTexCoord2f( x, y2 );
+ glVertex3i( dst->x, dst->y, 0.0f );
+ glEnd();
+ }
else {
SDL_BlitSurface((SDL_Surface*)inp, src, surface_o, dst);
}
void ContextManager::SetTitle(char* title) {
SDL_SetWindowTitle(window, title);
}
+
+ void* ContextManager::LoadImage(char* fname) {
+ return IMG_Load(fname);
+ }
+
+ void* ContextManager::LoadImageMemory(void* mem, size_t len, char* type) {
+ SDL_RWops* rwo = SDL_RWFromMem(mem, len);
+ SDL_Surface* bitmap_tmp = IMG_LoadTyped_RW(rwo, 0, type);
+
+ return bitmap_tmp;
+ }
+
+ void* ContextManager::AccelImage(void* in) {
+ if(accelerate) {
+ SDL_Texture* tex = SDL_CreateTextureFromSurface(renderer, (SDL_Surface*)in);
+ SDL_FreeSurface((SDL_Surface*)in);
+
+ return tex;
+ }
+ return in;
+ }
+
+ void* ContextManager::GLTexImage(void* in) {
+
+ if(!opengl_mode) return in;
+
+ GLuint *tex = (GLuint*)calloc(sizeof(GLuint), 1);
+ GLenum texture_format;
+ GLint nOfColors;
+ SDL_Surface* sfc = (SDL_Surface*)in;
+
+ if ( (sfc->w & (sfc->w - 1)) != 0 ) {
+ printf("[WARN] Image width not ^2.\n");
+ }
+
+ // Also check if the height is a power of 2
+ if ( (sfc->h & (sfc->h - 1)) != 0 ) {
+ printf("[WARN] Image height not ^2.\n");
+ }
+
+ // get the number of channels in the SDL surface
+ nOfColors = sfc->format->BytesPerPixel;
+ if (nOfColors == 4) // contains an alpha channel
+ {
+ if (sfc->format->Rmask == 0x000000ff)
+ texture_format = GL_RGBA;
+ else
+ texture_format = GL_BGRA;
+ }
+ else if (nOfColors == 3) // no alpha channel
+ {
+ if (sfc->format->Rmask == 0x000000ff)
+ texture_format = GL_RGB;
+ else
+ texture_format = GL_BGR;
+ }
+ else {
+ printf("[WARN] Image not truecolor (32bpp). Expect explosions.\n");
+ // this error should not go unhandled
+ }
+
+ // Have OpenGL generate a texture object handle for us
+ glGenTextures( 1, tex );
+
+ // Bind the texture object
+ glBindTexture( GL_TEXTURE_2D, tex[0] );
+
+ // Edit the texture object's image data using the information SDL_Surface gives us
+ glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, sfc->w, sfc->h, 0, texture_format, GL_UNSIGNED_BYTE, sfc->pixels );
+
+ // Set the texture's stretching properties
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ // printf("[GL] tex: %d\n", tex[0]);
+
+ return tex;
+ }
DefaultVars();
- SDL_Surface* bitmap_tmp = IMG_Load(fname);
+ SDL_Surface* bitmap_tmp = (SDL_Surface*)cx->LoadImage(fname);
if(!bitmap_tmp) {
printf("[UDisplayable::Ctor] File could not be loaded, this->Error set.\n");
// Determine if we're on an accelerated context. If so, we create a texture out of the bitmap.
// Then we store what we'll use to the void* bitmap, either Tex or Surf.
-
- if (cx->Accelerated()) {
- SDL_Texture* tex = SDL_CreateTextureFromSurface(ctx->Renderer(), bitmap_tmp);
- this->bitmap = (void*)tex;
- SDL_FreeSurface(bitmap_tmp);
+ if(cx->Accelerated()) {
+ this->bitmap = cx->AccelImage(bitmap_tmp);
}
else {
- this->bitmap = (void*)bitmap_tmp;
+ this->bitmap = cx->GLTexImage(bitmap_tmp);
}
}
#ifdef DEBUG_OVERKILL
DefaultVars();
- SDL_Surface* bitmap_tmp = IMG_Load(fname);
+ SDL_Surface* bitmap_tmp = (SDL_Surface*)cx->LoadImage(fname);
if(!bitmap_tmp) {
printf("[UDisplayable::Ctor] File could not be loaded, this->Error set.\n");
// Determine if we're on an accelerated context. If so, we create a texture out of the bitmap.
// Then we store what we'll use to the void* bitmap, either Tex or Surf.
- if (cx->Accelerated()) {
- SDL_Texture* tex = SDL_CreateTextureFromSurface(ctx->Renderer(), bitmap_tmp);
- this->bitmap = (void*)tex;
- SDL_FreeSurface(bitmap_tmp);
+ if(cx->Accelerated()) {
+ this->bitmap = cx->AccelImage(bitmap_tmp);
}
else {
- this->bitmap = (void*)bitmap_tmp;
+ this->bitmap = cx->GLTexImage(bitmap_tmp);
}
}
#ifdef DEBUG_OVERKILL
DefaultVars();
- SDL_RWops* rwo = SDL_RWFromMem(memory, mSize);
- SDL_Surface* bitmap_tmp = IMG_LoadTyped_RW(rwo, 0, "PNG");
- if(rwo == NULL || bitmap_tmp == NULL) {
- printf("Loading RWops failed. %s", SDL_GetError());
- while(1);
- //exit(-1);
- }
+ SDL_Surface* bitmap_tmp = (SDL_Surface*)cx->LoadImageMemory(memory, mSize, (char*)"PNG");
this->x = 0;
this->y = 0;
// Determine if we're on an accelerated context. If so, we create a texture out of the bitmap.
// Then we store what we'll use to the void* bitmap, either Tex or Surf.
- if (cx->Accelerated()) {
- SDL_Texture* tex = SDL_CreateTextureFromSurface(ctx->Renderer(), bitmap_tmp);
- this->bitmap = (void*)tex;
- SDL_FreeSurface(bitmap_tmp);
+ if(cx->Accelerated()) {
+ this->bitmap = cx->AccelImage(bitmap_tmp);
}
else {
- this->bitmap = (void*)bitmap_tmp;
+ this->bitmap = cx->GLTexImage(bitmap_tmp);
}
-
- this->dispMode = mode;
}
// Sets the position on screen.
src.h = bmp_h;
if (frameIndex == -1) {
- ctx->Blit(bitmap, &src, &loc_adj);
+ ctx->Blit(bitmap, &src, &loc_adj, NULL);
return;
}
frameClip.w = frameWidth;
frameClip.h = bmp_h;
- ctx->Blit(bitmap, &frameClip, &loc_adj);
+ if(ctx->GLMode()) {
+ SDL_Rect image_rect;
+
+ image_rect.x = 0;
+ image_rect.x = 0;
+ image_rect.w = bmp_w;
+ image_rect.h = bmp_h;
+
+ ctx->Blit(bitmap, &frameClip, &loc_adj, &image_rect); // GL needs data that isn't inside of bitmap.
+ }
+ else {
+ ctx->Blit(bitmap, &frameClip, &loc_adj, NULL);
+ }
}
// Get SDL_Rect for collision calculation. In a base Displayable, it returns the image width.