219 lines
6.6 KiB
C++
219 lines
6.6 KiB
C++
|
/*
|
||
|
* Overreact - Mr. 4th Dimention
|
||
|
* Allen Webster
|
||
|
* 03.21.2015 (mm.dd.yyyy)
|
||
|
*
|
||
|
* Win32 Rendering System Layer.
|
||
|
*/
|
||
|
|
||
|
#define SIG_STARTUP(name) void(name)(Win32RenderingVars *render_vars)
|
||
|
#define SIG_SHUTDOWN(name) void(name)(Win32RenderingVars *render_vars)
|
||
|
#define SIG_REDRAW(name) void(name)(Win32RenderingVars *render_vars)
|
||
|
#define SIG_SET_SIZE(name) void(name)(Win32RenderingVars *render_vars, i32 port_width, i32 port_height, i32 view_width, i32 view_height)
|
||
|
#define SIG_GET_RENDER_TARGET(name) Game_Render_Target(name)(Win32RenderingVars *render_vars)
|
||
|
|
||
|
#if RENDER_MODE == SOFTWARE
|
||
|
|
||
|
struct Win32RenderingVars{
|
||
|
HDC hdc;
|
||
|
BITMAPINFO bmp_info;
|
||
|
i32 width, height, pitch;
|
||
|
i32 pixel_data_size;
|
||
|
void *pixel_data;
|
||
|
};
|
||
|
|
||
|
internal
|
||
|
SIG_STARTUP(render_startup){}
|
||
|
|
||
|
internal
|
||
|
SIG_SHUTDOWN(render_shutdown){}
|
||
|
|
||
|
internal
|
||
|
SIG_REDRAW(render_redraw_screen){
|
||
|
render_vars->bmp_info.bmiHeader.biHeight =
|
||
|
-render_vars->bmp_info.bmiHeader.biHeight;
|
||
|
SetDIBitsToDevice(render_vars->hdc, 0, 0,
|
||
|
render_vars->width, render_vars->height,
|
||
|
0, 0,
|
||
|
0, render_vars->height,
|
||
|
render_vars->pixel_data,
|
||
|
&render_vars->bmp_info,
|
||
|
DIB_RGB_COLORS);
|
||
|
render_vars->bmp_info.bmiHeader.biHeight =
|
||
|
-render_vars->bmp_info.bmiHeader.biHeight;
|
||
|
}
|
||
|
|
||
|
// TODO(allen): This version ignores view / port ratio. It simply resize
|
||
|
// to the dimensions of the port and the game will render in the top
|
||
|
// left leaving the rest of the window ignored. Either implement
|
||
|
// software stretching, or at least center the view like the original Push.
|
||
|
internal
|
||
|
SIG_SET_SIZE(render_set_screen_size){
|
||
|
render_vars->width = port_width;
|
||
|
render_vars->height = port_height;
|
||
|
render_vars->pitch = port_width*4;
|
||
|
|
||
|
render_vars->bmp_info = {};
|
||
|
BITMAPINFOHEADER bmi_header = {};
|
||
|
bmi_header.biSize = sizeof(BITMAPINFOHEADER);
|
||
|
bmi_header.biWidth = render_vars->width;
|
||
|
bmi_header.biHeight = render_vars->height;
|
||
|
bmi_header.biPlanes = 1;
|
||
|
bmi_header.biBitCount = 32;
|
||
|
bmi_header.biCompression = BI_RGB;
|
||
|
render_vars->bmp_info.bmiHeader = bmi_header;
|
||
|
|
||
|
// TODO(allen): Bulletproof this.
|
||
|
|
||
|
i32 new_size = port_height*port_width*4;
|
||
|
if (new_size > render_vars->pixel_data_size){
|
||
|
if (render_vars->pixel_data){
|
||
|
VirtualFree(render_vars->pixel_data,
|
||
|
0, MEM_RELEASE);
|
||
|
}
|
||
|
|
||
|
render_vars->pixel_data_size = new_size;
|
||
|
render_vars->pixel_data =
|
||
|
VirtualAlloc(0, height*width*4,
|
||
|
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||
|
|
||
|
if (!render_vars->pixel_data){
|
||
|
WINERROR("Failed to setup window pixel memory");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SIG_GET_RENDER_TARGET(render_get_render_target){
|
||
|
Game_Render_Target render;
|
||
|
|
||
|
render.pixels = (u8*)render_vars->pixel_data;
|
||
|
render.width = render_vars->width;
|
||
|
render.height = render_vars->height;
|
||
|
render.pitch = render_vars->pitch;
|
||
|
|
||
|
return render;
|
||
|
}
|
||
|
|
||
|
#elif RENDER_MODE == OPENGL
|
||
|
|
||
|
struct Win32RenderingVars{
|
||
|
HDC hdc;
|
||
|
HGLRC context;
|
||
|
i32 width, height;
|
||
|
};
|
||
|
|
||
|
internal
|
||
|
SIG_STARTUP(render_startup){
|
||
|
int nPixelFormat;
|
||
|
|
||
|
static PIXELFORMATDESCRIPTOR pfd = {
|
||
|
sizeof(PIXELFORMATDESCRIPTOR), //size of structure
|
||
|
1, //default version
|
||
|
PFD_DRAW_TO_WINDOW | //window drawing support
|
||
|
PFD_SUPPORT_OPENGL | //opengl support
|
||
|
PFD_DOUBLEBUFFER, //double buffering support
|
||
|
PFD_TYPE_RGBA, //RGBA color mode
|
||
|
32, //32 bit color mode
|
||
|
0, 0, 0, 0, 0, 0, //ignore color bits
|
||
|
0, //no alpha buffer
|
||
|
0, //ignore shift bit
|
||
|
0, //no accumulation buffer
|
||
|
0, 0, 0, 0, //ignore accumulation bits
|
||
|
16, //16 bit z-buffer size
|
||
|
0, //no stencil buffer
|
||
|
0, //no aux buffer
|
||
|
PFD_MAIN_PLANE, //main drawing plane
|
||
|
0, //reserved
|
||
|
0, 0, 0 }; //layer masks ignored
|
||
|
|
||
|
nPixelFormat = ChoosePixelFormat(render_vars->hdc, &pfd);
|
||
|
SetPixelFormat(render_vars->hdc, nPixelFormat, &pfd);
|
||
|
|
||
|
render_vars->context = wglCreateContext(render_vars->hdc);
|
||
|
wglMakeCurrent(render_vars->hdc, render_vars->context);
|
||
|
|
||
|
glShadeModel(GL_SMOOTH);
|
||
|
glEnable(GL_TEXTURE_2D);
|
||
|
//glEnable(GL_DEPTH_TEST);
|
||
|
glDepthFunc(GL_LEQUAL);
|
||
|
glEnable(GL_CULL_FACE);
|
||
|
glFrontFace(GL_CCW);
|
||
|
glEnable(GL_BLEND);
|
||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||
|
|
||
|
GLenum error;
|
||
|
error = glGetError();
|
||
|
error = error;
|
||
|
}
|
||
|
|
||
|
internal
|
||
|
SIG_SHUTDOWN(render_shutdown){
|
||
|
wglMakeCurrent(render_vars->hdc, 0);
|
||
|
wglDeleteContext(render_vars->context);
|
||
|
}
|
||
|
|
||
|
internal
|
||
|
SIG_REDRAW(render_redraw_screen){
|
||
|
glFlush();
|
||
|
SwapBuffers(render_vars->hdc);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): This changes the aspect ratio of the view to perfectly
|
||
|
// fill the window. The height is untouched, the width is the only part
|
||
|
// of the view that is effected.
|
||
|
internal
|
||
|
SIG_SET_SIZE(render_set_screen_size){
|
||
|
render_vars->height = view_height;
|
||
|
render_vars->width = (i32)((port_width / ((real32)port_height)) * view_height);
|
||
|
|
||
|
glViewport(0, 0, port_width, port_height);
|
||
|
glMatrixMode(GL_PROJECTION);
|
||
|
glLoadIdentity();
|
||
|
gluOrtho2D(0.f, render_vars->width, view_height, 0.f);
|
||
|
glMatrixMode(GL_MODELVIEW);
|
||
|
glLoadIdentity();
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): This maintains a fixed aspect ratio and
|
||
|
// puts the game port in the center, expecting the game to
|
||
|
// add bars
|
||
|
#if 0
|
||
|
internal
|
||
|
SIG_SET_SIZE(render_set_screen_size){
|
||
|
render_vars->width = view_width;
|
||
|
render_vars->height = view_height;
|
||
|
|
||
|
real32 ratio_width, ratio_height;
|
||
|
ratio_width = (real32)(port_width) / view_width;
|
||
|
ratio_height = (real32)(port_height) / view_height;
|
||
|
|
||
|
i32 start_x, start_y;
|
||
|
if (ratio_width > ratio_height){
|
||
|
ratio_width = ratio_height;
|
||
|
start_y = 0;
|
||
|
start_x = (port_width - (ratio_width*view_width))/2;
|
||
|
}
|
||
|
else{
|
||
|
ratio_height = ratio_width;
|
||
|
start_x = 0;
|
||
|
start_y = (port_height - (ratio_height*view_height))/2;
|
||
|
}
|
||
|
|
||
|
glViewport(start_x, start_y, ratio_width*view_width, ratio_height*view_height);
|
||
|
glMatrixMode(GL_PROJECTION);
|
||
|
glLoadIdentity();
|
||
|
gluOrtho2D(0.f, view_width, view_height, 0.f);
|
||
|
glMatrixMode(GL_MODELVIEW);
|
||
|
glLoadIdentity();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
SIG_GET_RENDER_TARGET(render_get_render_target){
|
||
|
Game_Render_Target render = {};
|
||
|
render.width = render_vars->width;
|
||
|
render.height = render_vars->height;
|
||
|
return render;
|
||
|
}
|
||
|
|
||
|
#endif
|