426 lines
13 KiB
C++
426 lines
13 KiB
C++
/*
|
|
* General render target operations.
|
|
*/
|
|
|
|
// TOP
|
|
|
|
Bank_Begin_Setup_Sig(begin_setup){
|
|
Asset_Bank_Setup setup = {0};
|
|
setup.bank = bank;
|
|
setup.trans_part = trans_part;
|
|
setup.system = system;
|
|
return(setup);
|
|
}
|
|
|
|
Bank_End_Setup_Sig(end_setup){}
|
|
|
|
Bank_Bind_Font_Sig(bind_font){
|
|
System_API *system = setup->system;
|
|
Asset_Bank *bank = setup->bank;
|
|
Partition *part = setup->trans_part;
|
|
Font *font = 0;
|
|
i32 i = 0;
|
|
|
|
font = get_font(bank, font_id);
|
|
if (font){
|
|
// TODO(tyler): Implementation of distance field text rendering for size-agnostic fonts
|
|
// TODO(allen): Pick a good size for the texture based
|
|
// on the size we want the font to be.
|
|
// TODO(allen): Background asset streaming.
|
|
Temp_Memory temp = begin_temp(part);
|
|
u8 *temp_bitmap = push_array(part, u8, 512*512);
|
|
File_Dump dump = system->DBG_dump_begin(file_name);
|
|
u8 *ttf_buffer = push_array(part, u8, dump.size);
|
|
|
|
if (system->DBG_dump_end(dump, ttf_buffer)){
|
|
stbtt_fontinfo fontinfo;
|
|
i32 ascent;
|
|
f32 scale;
|
|
f32 pixel_height = 16.f;
|
|
|
|
stbtt_InitFont(&fontinfo, ttf_buffer, 0);
|
|
scale = stbtt_ScaleForPixelHeight(&fontinfo, pixel_height);
|
|
stbtt_GetFontVMetrics(&fontinfo, &ascent, 0, 0);
|
|
|
|
font->texture_w = 512;
|
|
font->texture_h = 512;
|
|
font->pull_up = ascent*scale;
|
|
font->id = font_id;
|
|
|
|
stbtt_BakeFontBitmap(ttf_buffer, 0, pixel_height,
|
|
temp_bitmap, font->texture_w, font->texture_h,
|
|
0, 128, font->chardata, part);
|
|
|
|
for (i = 0; i < 128; ++i){
|
|
font->advance[i] = font->chardata[i].xadvance;
|
|
}
|
|
|
|
glGenTextures(1, &font->texture_id);
|
|
glBindTexture(GL_TEXTURE_2D, font->texture_id);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512, 512,
|
|
0, GL_ALPHA, GL_UNSIGNED_BYTE,
|
|
temp_bitmap);
|
|
|
|
#ifdef DEVELOPER
|
|
{
|
|
GLenum error = glGetError();
|
|
GLenum copy = error;
|
|
AllowLocal(copy);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
end_temp(temp);
|
|
}
|
|
}
|
|
|
|
struct Bmp_Data{
|
|
i32 w, h, byte_pitch;
|
|
u16 bpp;
|
|
u8 *data;
|
|
};
|
|
|
|
struct Bmp_File_Info{
|
|
u16 type;
|
|
u32 file_size;
|
|
u16 res1, res2;
|
|
u32 off_bits;
|
|
|
|
u32 struct_size;
|
|
i32 w, h;
|
|
u16 planes;
|
|
u16 bpp;
|
|
u32 compression;
|
|
u32 image_size;
|
|
i32 xppm;
|
|
i32 yppm;
|
|
u32 colors_used;
|
|
u32 colors_important;
|
|
};
|
|
|
|
b32
|
|
bmp_read(u8 *src_buffer, i32 size, Bmp_Data *bmp, Bmp_File_Info *bmp_info){
|
|
u8 *ptr = src_buffer;
|
|
b32 result = 0;
|
|
|
|
bmp_info->type = PtrRead(ptr, u16);
|
|
bmp_info->file_size = PtrRead(ptr, u32);
|
|
bmp_info->res1 = PtrRead(ptr, u16);
|
|
bmp_info->res2 = PtrRead(ptr, u16);
|
|
bmp_info->off_bits = PtrRead(ptr, u32);
|
|
|
|
if (bmp_info->type == 0x4D42){
|
|
bmp_info->struct_size = PtrRead(ptr, u32);
|
|
bmp_info->w = PtrRead(ptr, i32);
|
|
bmp_info->h = PtrRead(ptr, i32);
|
|
bmp_info->planes = PtrRead(ptr, u16);
|
|
bmp_info->bpp = PtrRead(ptr, u16);
|
|
bmp_info->compression = PtrRead(ptr, u32);
|
|
bmp_info->image_size = PtrRead(ptr, u32);
|
|
bmp_info->xppm = PtrRead(ptr, i32);
|
|
bmp_info->yppm = PtrRead(ptr, i32);
|
|
bmp_info->colors_used = PtrRead(ptr, u32);
|
|
bmp_info->colors_important = PtrRead(ptr, u32);
|
|
|
|
bmp->w = bmp_info->w;
|
|
bmp->h = bmp_info->h;
|
|
bmp->byte_pitch = bmp_info->image_size / bmp->h;
|
|
bmp->bpp = bmp_info->bpp;
|
|
|
|
if (bmp->byte_pitch == bmp->w*4){
|
|
bmp->data = src_buffer + bmp_info->off_bits;
|
|
result = 1;
|
|
}
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
struct POT_Texture{
|
|
void *data;
|
|
u32 w, h;
|
|
};
|
|
|
|
u32
|
|
round_up_pot(u32 x){
|
|
--x;
|
|
x |= (x >> 1);
|
|
x |= (x >> 2);
|
|
x |= (x >> 4);
|
|
x |= (x >> 8);
|
|
x |= (x >> 16);
|
|
++x;
|
|
return(x);
|
|
}
|
|
|
|
POT_Texture
|
|
pot_bmp_texture(Partition *part, void *data, i32 w, i32 h, i32 pitch){
|
|
POT_Texture result = {0};
|
|
char *src_line = 0;
|
|
char *dst_line = 0;
|
|
char *pixel = 0;
|
|
char r,g,b,a;
|
|
i32 dst_pitch = 0;
|
|
i32 y = 0, x = 0;
|
|
|
|
result.w = round_up_pot((u32)w);
|
|
result.h = round_up_pot((u32)h);
|
|
dst_pitch = result.w*4;
|
|
align_partition(part, 4);
|
|
result.data = push_array(part, char, result.h*dst_pitch);
|
|
memset(result.data, 0, result.h*dst_pitch);
|
|
|
|
src_line = (char*)data;
|
|
dst_line = (char*)result.data;
|
|
|
|
for (y = 0; y < h; ++y){
|
|
memcpy(dst_line, src_line, pitch);
|
|
|
|
pixel = dst_line;
|
|
for (x = 0; x < w; ++x){
|
|
b = pixel[0];
|
|
g = pixel[1];
|
|
r = pixel[2];
|
|
a = pixel[3];
|
|
|
|
pixel[0] = r;
|
|
pixel[1] = g;
|
|
pixel[2] = b;
|
|
pixel[3] = a;
|
|
|
|
pixel += 4;
|
|
}
|
|
|
|
src_line += pitch;
|
|
dst_line += dst_pitch;
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
u32
|
|
load_bmp(System_API *system, Partition *part, Image *image, i32 image_id, char *file_name){
|
|
u32 prev_tex_id = 0;
|
|
if (image){
|
|
// TODO(allen): Background asset streaming.
|
|
Bmp_Data bmp;
|
|
Bmp_File_Info bmp_info;
|
|
|
|
Temp_Memory temp = begin_temp(part);
|
|
File_Dump dump = system->DBG_dump_begin(file_name);
|
|
u8 *bmp_buffer = push_array(part, u8, dump.size);
|
|
if (system->DBG_dump_end(dump, bmp_buffer)){
|
|
if (bmp_read(bmp_buffer, dump.size, &bmp, &bmp_info)){
|
|
POT_Texture texture =
|
|
pot_bmp_texture(part, bmp.data, bmp.w, bmp.h, bmp.byte_pitch);
|
|
|
|
image->tex_x = (f32)bmp.w/(f32)texture.w;
|
|
image->tex_y = (f32)bmp.h/(f32)texture.h;
|
|
image->width = (f32)bmp.w;
|
|
image->height = (f32)bmp.h;
|
|
image->id = image_id;
|
|
|
|
prev_tex_id = image->texture_id;
|
|
|
|
glGenTextures(1, &image->texture_id);
|
|
glBindTexture(GL_TEXTURE_2D, image->texture_id);
|
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
|
|
texture.w, texture.h,
|
|
0, GL_RGBA, GL_UNSIGNED_BYTE,
|
|
texture.data);
|
|
}
|
|
}
|
|
end_temp(temp);
|
|
}
|
|
return(prev_tex_id);
|
|
}
|
|
|
|
Bank_Bind_BMP_Sig(bind_bmp){
|
|
Asset_Bank *bank = setup->bank;
|
|
Partition *part = setup->trans_part;
|
|
Image *image = get_image(bank, image_id);
|
|
load_bmp(setup->system, part, image, image_id, file_name);
|
|
}
|
|
|
|
Bank_Replace_BMP_Sig(replace_bmp){
|
|
u32 prev_tex_id = 0;
|
|
Image *image = get_image(bank, image_id);
|
|
prev_tex_id = load_bmp(system, part, image, image_id, file_name);
|
|
if (prev_tex_id){
|
|
glDeleteTextures(1, &prev_tex_id);
|
|
}
|
|
}
|
|
|
|
#include <windows.h>
|
|
#include "cd_windows_render_vars.h"
|
|
|
|
#include "cd_gl_defines.h"
|
|
|
|
static void*
|
|
win32_load_gl_always(char *name, HMODULE module){
|
|
void *p = (void *)wglGetProcAddress(name), *r = 0;
|
|
if(p == 0 ||
|
|
(p == (void*)0x1) || (p == (void*)0x2) || (p == (void*)0x3) ||
|
|
(p == (void*)-1) ){
|
|
r = (void *)GetProcAddress(module, name);
|
|
}
|
|
else{
|
|
r = p;
|
|
}
|
|
return(r);
|
|
}
|
|
|
|
// TODO(allen): Need to move anything that couples
|
|
// rendering to platform into a separate layer.
|
|
Init_Sig(init){
|
|
Win32_Render_Vars *vars = (Win32_Render_Vars*)render_vars;
|
|
|
|
// GL context initialization
|
|
{
|
|
PIXELFORMATDESCRIPTOR format;
|
|
int format_id;
|
|
BOOL success;
|
|
HDC dc;
|
|
|
|
format.nSize = sizeof(format);
|
|
format.nVersion = 1;
|
|
format.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
|
|
format.iPixelType = PFD_TYPE_RGBA;
|
|
format.cColorBits = 32;
|
|
format.cRedBits = 0;
|
|
format.cRedShift = 0;
|
|
format.cGreenBits = 0;
|
|
format.cGreenShift = 0;
|
|
format.cBlueBits = 0;
|
|
format.cBlueShift = 0;
|
|
format.cAlphaBits = 0;
|
|
format.cAlphaShift = 0;
|
|
format.cAccumBits = 0;
|
|
format.cAccumRedBits = 0;
|
|
format.cAccumGreenBits = 0;
|
|
format.cAccumBlueBits = 0;
|
|
format.cAccumAlphaBits = 0;
|
|
format.cDepthBits = 24;
|
|
format.cStencilBits = 8;
|
|
format.cAuxBuffers = 0;
|
|
format.iLayerType = PFD_MAIN_PLANE;
|
|
format.bReserved = 0;
|
|
format.dwLayerMask = 0;
|
|
format.dwVisibleMask = 0;
|
|
format.dwDamageMask = 0;
|
|
|
|
dc = GetDC(vars->hwnd);
|
|
Assert(dc);
|
|
format_id = ChoosePixelFormat(dc, &format);
|
|
Assert(format_id != 0);
|
|
success = SetPixelFormat(dc, format_id, &format);
|
|
Assert(success == TRUE);
|
|
|
|
HGLRC glcontext = wglCreateContext(dc);
|
|
wglMakeCurrent(dc, glcontext);
|
|
|
|
{
|
|
HMODULE module = LoadLibraryA("opengl32.dll");
|
|
|
|
wglCreateContextAttribsARB_Function *wglCreateContextAttribsARB = 0;
|
|
wglCreateContextAttribsARB = (wglCreateContextAttribsARB_Function*)
|
|
win32_load_gl_always("wglCreateContextAttribsARB", module);
|
|
|
|
wglChoosePixelFormatARB_Function *wglChoosePixelFormatARB = 0;
|
|
wglChoosePixelFormatARB = (wglChoosePixelFormatARB_Function*)
|
|
win32_load_gl_always("wglChoosePixelFormatARB", module);
|
|
|
|
if (wglCreateContextAttribsARB != 0 && wglChoosePixelFormatARB != 0){
|
|
const int choosePixel_attribList[] =
|
|
{
|
|
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
|
|
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
|
|
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
|
|
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
|
|
WGL_COLOR_BITS_ARB, 32,
|
|
WGL_DEPTH_BITS_ARB, 24,
|
|
WGL_STENCIL_BITS_ARB, 8,
|
|
0,
|
|
};
|
|
|
|
int extended_format_id;
|
|
UINT num_formats = 0;
|
|
BOOL result = 0;
|
|
|
|
result = wglChoosePixelFormatARB(dc,
|
|
choosePixel_attribList,
|
|
0,
|
|
1,
|
|
&extended_format_id,
|
|
&num_formats);
|
|
|
|
if (result != 0 && num_formats > 0){
|
|
const int createContext_attribList[] = {
|
|
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
|
|
WGL_CONTEXT_MINOR_VERSION_ARB, 2,
|
|
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
|
0
|
|
};
|
|
|
|
if (extended_format_id == format_id){
|
|
HGLRC extended_context =
|
|
wglCreateContextAttribsARB(dc,
|
|
0,
|
|
createContext_attribList);
|
|
if (extended_context){
|
|
wglMakeCurrent(dc, extended_context);
|
|
wglDeleteContext(glcontext);
|
|
glcontext = extended_context;
|
|
|
|
MessageBoxA(0,(char*)glGetString(GL_VERSION), "OPENGL VERSION",0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ReleaseDC(vars->hwnd, dc);
|
|
}
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
glEnable(GL_SCISSOR_TEST);
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glClearColor(0,0,0,0);
|
|
}
|
|
|
|
Display_Sig(display){
|
|
Win32_Render_Vars *vars = (Win32_Render_Vars*)render_vars;
|
|
glFlush();
|
|
HDC dc = GetDC(vars->hwnd);
|
|
SwapBuffers(dc);
|
|
ReleaseDC(vars->hwnd, dc);
|
|
}
|
|
|
|
Set_Screen_Sig(set_screen){
|
|
if (w > 0 && h > 0){
|
|
glViewport(0, h - out_h, out_w, out_h);
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
glOrtho(0, out_w, 0, out_h, -1, 1);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
glScissor(0, h - out_h, out_w, out_h);
|
|
}
|
|
}
|
|
|
|
// BOTTOM
|
|
|