#ifdef TCOD_SDL2
#include <sys.h>
#include "libtcod_int.h"
#include "console.h"
#ifndef NO_OPENGL
#include <stdio.h>
#include <SDL.h>
#include <SDL_opengl.h>
#define CHECKGL( GLcall ) \
GLcall; \
if(!_CheckGL_Error( #GLcall, __FILE__, __LINE__)) \
return false;
#ifdef NDEBUG
#define DBGCHECKGL(GLcall) GLcall
#else
#define DBGCHECKGL CHECKGL
#endif
typedef enum
{
Character,
ForeCol,
BackCol,
ConsoleDataEnumSize
} ConsoleDataEnum;
const int ConsoleDataAlignment[3] = {4, 3, 3 };
static const char *TCOD_con_vertex_shader =
#ifndef NDEBUG
"#version 110\n"
#endif
"uniform vec2 termsize; "
"void main(void) "
"{ "
" gl_Position = gl_Vertex; "
" gl_TexCoord[0] = gl_MultiTexCoord0; "
" gl_TexCoord[0].x = gl_TexCoord[0].x*termsize.x; "
" gl_TexCoord[0].y = gl_TexCoord[0].y*termsize.y; "
"} "
;
static const char *TCOD_con_pixel_shader =
#ifndef NDEBUG
"#version 110\n"
#endif
"uniform sampler2D font; "
"uniform sampler2D term; "
"uniform sampler2D termfcol; "
"uniform sampler2D termbcol; "
"uniform float fontw; "
"uniform vec2 fontcoef; "
"uniform vec2 termsize; "
"uniform vec2 termcoef; "
"void main(void) "
"{ "
" vec2 rawCoord = gl_TexCoord[0].xy; "
" vec2 conPos = floor(rawCoord); "
" vec2 pixPos = fract(rawCoord); "
" pixPos = vec2(pixPos.x*fontcoef.x,pixPos.y*fontcoef.y); "
" vec2 address = vec2(conPos.x*termcoef.x,conPos.y*termcoef.y); "
" address=address+vec2(0.001, 0.001); "
" vec4 charvec = texture2D(term,address);"
" float inchar = (charvec.r * 256.0) + (charvec.g * 256.0 * 256.0);"
" vec4 tcharfcol = texture2D(termfcol, address); "
" vec4 tcharbcol = texture2D(termbcol, address); "
" vec4 tchar = vec4(mod(floor(inchar),floor(fontw)),floor(inchar/fontw), 0.0, 0.0); "
" gl_FragColor = texture2D(font, vec2((tchar.x*fontcoef.x),(tchar.y*fontcoef.y))+pixPos.xy); "
" gl_FragColor=gl_FragColor.a*tcharfcol+(1.0-gl_FragColor.a)*tcharbcol; "
"} "
;
bool _CheckGL_Error(const char* GLcall, const char* file, const int line)
{
GLenum errCode;
if((errCode = glGetError())!=GL_NO_ERROR)
{
printf("OPENGL ERROR #%i: in file %s on line %i\n",errCode,file, line);
printf("OPENGL Call: %s\n",GLcall);
return false;
}
return true;
}
void TCOD_opengl_init_attributes(void) {
static bool first=true;
if ( first ) {
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32 );
first=false;
}
}
static int POTconwidth, POTconheight, conwidth, conheight;
static GLhandleARB conProgram, conVertShader, conFragShader;
static GLuint font_tex;
static int POTfontwidth,POTfontheight, fontwidth,fontheight;
static GLuint Tex[ConsoleDataEnumSize];
static unsigned char *data[ConsoleDataEnumSize];
static bool dirty[ConsoleDataEnumSize];
static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB=0;
static PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB=0;
static PFNGLSHADERSOURCEARBPROC glShaderSourceARB=0;
static PFNGLCOMPILESHADERARBPROC glCompileShaderARB=0;
static PFNGLGETINFOLOGARBPROC glGetInfoLogARB=0;
static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB=0;
static PFNGLATTACHOBJECTARBPROC glAttachObjectARB=0;
static PFNGLLINKPROGRAMARBPROC glLinkProgramARB=0;
static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB=0;
static PFNGLUNIFORM2FARBPROC glUniform2fARB=0;
static PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB=0;
static PFNGLUNIFORM1FARBPROC glUniform1fARB=0;
static PFNGLUNIFORM1IARBPROC glUniform1iARB=0;
static PFNGLACTIVETEXTUREPROC glActiveTextureF=0;
static SDL_GLContext glcontext;
void TCOD_opengl_uninit_state() {
SDL_GL_DeleteContext(glcontext);
}
bool TCOD_opengl_init_state(int conw, int conh, void *font) {
SDL_Surface *font_surf=(SDL_Surface *)font;
SDL_PixelFormat *my_format=SDL_AllocFormat(SDL_GetWindowPixelFormat(window));
uint32_t rmask, gmask, bmask, amask;
SDL_Surface *temp;
SDL_Surface *temp_alpha;
glcontext = SDL_GL_CreateContext(window);
if ( TCOD_ctx.renderer == TCOD_RENDERER_GLSL ) {
bool hasShader = false;
const char *glexts=(const char *)glGetString(GL_EXTENSIONS);
if (glexts ) {
hasShader = (strstr(glexts,"GL_ARB_shader_objects") != NULL);
}
if (! hasShader ) {
TCOD_LOG(("Missing GL_ARB_shader_objects extension. Falling back to fixed pipeline...\n"));
TCOD_ctx.renderer = TCOD_RENDERER_OPENGL;
}
}
glCreateShaderObjectARB=(PFNGLCREATESHADEROBJECTARBPROC)SDL_GL_GetProcAddress("glCreateShaderObjectARB");
glGetObjectParameterivARB=(PFNGLGETOBJECTPARAMETERIVARBPROC)SDL_GL_GetProcAddress("glGetObjectParameterivARB");
glShaderSourceARB=(PFNGLSHADERSOURCEARBPROC)SDL_GL_GetProcAddress("glShaderSourceARB");
glCompileShaderARB=(PFNGLCOMPILESHADERARBPROC)SDL_GL_GetProcAddress("glCompileShaderARB");
glGetInfoLogARB=(PFNGLGETINFOLOGARBPROC)SDL_GL_GetProcAddress("glGetInfoLogARB");
glCreateProgramObjectARB=(PFNGLCREATEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glCreateProgramObjectARB");
glAttachObjectARB=(PFNGLATTACHOBJECTARBPROC)SDL_GL_GetProcAddress("glAttachObjectARB");
glLinkProgramARB=(PFNGLLINKPROGRAMARBPROC)SDL_GL_GetProcAddress("glLinkProgramARB");
glUseProgramObjectARB=(PFNGLUSEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glUseProgramObjectARB");
glUniform2fARB=(PFNGLUNIFORM2FARBPROC)SDL_GL_GetProcAddress("glUniform2fARB");
glGetUniformLocationARB=(PFNGLGETUNIFORMLOCATIONARBPROC)SDL_GL_GetProcAddress("glGetUniformLocationARB");
glUniform1fARB=(PFNGLUNIFORM1FARBPROC)SDL_GL_GetProcAddress("glUniform1fARB");
glUniform1iARB=(PFNGLUNIFORM1IARBPROC)SDL_GL_GetProcAddress("glUniform1iARB");
glActiveTextureF=(PFNGLACTIVETEXTUREPROC)SDL_GL_GetProcAddress("glActiveTexture");
glEnable(GL_TEXTURE_2D);
glClearColor(1.0f, 1.0f, 0.0f, 0.0f);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
if ( TCOD_ctx.renderer == TCOD_RENDERER_GLSL ) {
glOrtho(0, conw, 0, conh, -1.0f, 1.0f);
glDisable (GL_BLEND);
} else {
glOrtho(0, conw, conh, 0.0f, -1.0f, 1.0f);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
if ( ! TCOD_ctx.fullscreen ) {
typedef bool (APIENTRY *PFNWGLSWAPINTERVALFARPROC)(int);
PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = 0;
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)SDL_GL_GetProcAddress("wglSwapIntervalEXT");
if (wglSwapIntervalEXT) wglSwapIntervalEXT(0);
}
conwidth=conw;
conheight=conh;
POTconwidth=POTconheight=1;
while ( POTconwidth < conw ) POTconwidth *= 2;
while ( POTconheight < conh ) POTconheight *= 2;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
fontwidth=font_surf->w;
fontheight=font_surf->h;
POTfontwidth=POTfontheight=1;
while ( POTfontwidth < fontwidth ) POTfontwidth *= 2;
while ( POTfontheight < fontheight ) POTfontheight *= 2;
SDL_SetColorKey(font_surf, 1, SDL_MapRGB(font_surf->format, 0, 0, 0));
my_format->Amask = amask;
temp_alpha = SDL_ConvertSurface(font_surf, my_format, 0);
SDL_FreeFormat(my_format);
temp = SDL_CreateRGBSurface(SDL_SWSURFACE, POTfontwidth, POTfontheight, 32, bmask, gmask, rmask, amask);
SDL_BlitSurface(temp_alpha, NULL, temp, NULL);
SDL_FreeSurface(temp_alpha);
CHECKGL(glGenTextures(1, &font_tex));
CHECKGL(glBindTexture(GL_TEXTURE_2D, font_tex));
SDL_LockSurface(temp);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
CHECKGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, temp->w, temp->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp->pixels));
SDL_UnlockSurface(temp);
SDL_FreeSurface(temp);
return true;
}
static GLhandleARB loadShader(const char *txt, GLuint type) {
int success;
int infologLength = 0;
int charsWritten = 0;
char *infoLog;
GLhandleARB v = glCreateShaderObjectARB(type);
glShaderSourceARB(v, 1, &txt, 0);
glCompileShaderARB(v);
glGetObjectParameterivARB(v, GL_COMPILE_STATUS, &success);
if(success!=GL_TRUE)
{
glGetObjectParameterivARB(v, GL_INFO_LOG_LENGTH,&infologLength);
if(infologLength>0)
{
infoLog = (char *)malloc(infologLength);
glGetInfoLogARB(v, infologLength, &charsWritten, infoLog);
printf("GLSL ERROR : %s\n",infoLog);
free(infoLog);
}
return 0;
}
return v;
}
static bool loadProgram(const char *vertShaderCode, const char *fragShaderCode,
GLhandleARB *vertShader, GLhandleARB *fragShader, GLhandleARB *prog) {
int success;
*prog = DBGCHECKGL(glCreateProgramObjectARB());
*vertShader = loadShader(vertShaderCode, GL_VERTEX_SHADER);
if ( *vertShader == 0 ) return false;
glAttachObjectARB(*prog, *vertShader);
*fragShader = loadShader(fragShaderCode, GL_FRAGMENT_SHADER);
if ( *fragShader == 0 ) return false;
glAttachObjectARB(*prog, *fragShader);
glLinkProgramARB(*prog);
glGetObjectParameterivARB(*prog, GL_LINK_STATUS, &success);
if(success!=GL_TRUE)
{
int infologLength = 0;
int charsWritten = 0;
char *infoLog;
glGetObjectParameterivARB(*prog, GL_INFO_LOG_LENGTH,&infologLength);
if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetInfoLogARB(*prog, infologLength, &charsWritten, infoLog);
printf("OPENGL ERROR: Program link Error");
printf("%s\n",infoLog);
free(infoLog);
}
return false;
}
return true;
}
bool TCOD_opengl_init_shaders(void) {
int i;
TCOD_color_t *fCol;
if ( TCOD_ctx.renderer == TCOD_RENDERER_GLSL ) {
if (! loadProgram(TCOD_con_vertex_shader, TCOD_con_pixel_shader, &conVertShader, &conFragShader, &conProgram ) ) return false;
}
for(i = 0; i< ConsoleDataEnumSize; i++)
{
data[i] = (unsigned char *)calloc(conwidth*conheight,ConsoleDataAlignment[i]);
dirty[i]=true;
}
fCol = (TCOD_color_t *)data[ForeCol];
for( i = 0; i < conwidth*conheight; i++)
{
fCol[i].r=255;
fCol[i].g=255;
fCol[i].b=255;
}
glGenTextures(3, Tex);
CHECKGL(glBindTexture(GL_TEXTURE_2D, Tex[Character]));
CHECKGL(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ));
CHECKGL(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ));
CHECKGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, POTconwidth, POTconheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0));
CHECKGL(glBindTexture(GL_TEXTURE_2D, Tex[ForeCol]));
CHECKGL(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ));
CHECKGL(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ));
CHECKGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, POTconwidth, POTconheight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0));
CHECKGL(glBindTexture(GL_TEXTURE_2D, Tex[BackCol]));
CHECKGL(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ));
CHECKGL(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ));
CHECKGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, POTconwidth, POTconheight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0));
CHECKGL(glBindTexture(GL_TEXTURE_2D, 0));
return true;
}
static bool updateTex(ConsoleDataEnum dataType) {
GLenum Type=0;
DBGCHECKGL(glBindTexture(GL_TEXTURE_2D, Tex[dataType]));
switch(ConsoleDataAlignment[dataType])
{
case 1:
Type = GL_RED;
break;
case 3:
Type = GL_RGB;
break;
case 4:
Type = GL_RGBA;
break;
}
DBGCHECKGL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, conwidth, conheight, Type, GL_UNSIGNED_BYTE, data[dataType]));
DBGCHECKGL(glBindTexture(GL_TEXTURE_2D,0));
return true;
}
static void updateChar(ConsoleDataEnum dataType, int BufferPos, unsigned char *c, int length, int offset) {
int i;
dirty[dataType] = true;
for(i = 0; i<length; i++) {
data[dataType][BufferPos*ConsoleDataAlignment[dataType] + i + offset] = c[i];
}
}
void TCOD_opengl_putchar_ex(int x, int y, int c, TCOD_color_t fore, TCOD_color_t back) {
int loc = x+y*conwidth;
if ( TCOD_ctx.renderer == TCOD_RENDERER_GLSL ) {
updateChar(Character, loc, (unsigned char *)&c, ConsoleDataAlignment[Character], 0);
updateChar(ForeCol, loc, &fore.r, ConsoleDataAlignment[ForeCol], 0);
}
updateChar(BackCol, loc, &back.r, ConsoleDataAlignment[BackCol], 0);
}
bool TCOD_opengl_render( int oldFade, bool *ascii_updated, TCOD_console_data_t *console, TCOD_console_data_t *cache) {
int x,y,i;
int fade = (int)TCOD_console_get_fade();
bool track_changes = (cache && oldFade == fade);
TCOD_color_t *ofg, *obg, *nfg, *nbg;
int *c = console->ch_array;
int *oc;
nfg = TCOD_image_get_colors(console->fg_colors);
nbg = TCOD_image_get_colors(console->bg_colors);
if (track_changes) {
oc = cache->ch_array;
ofg = TCOD_image_get_colors(cache->fg_colors);
obg = TCOD_image_get_colors(cache->bg_colors);
}
for (y=0;y<conheight;y++) {
for (x=0; x<conwidth; x++) {
bool changed=true;
if ( track_changes ) {
changed=false;
if (
nbg->r != obg->r || nbg->g != obg->g || nbg->b != obg->b ||
nfg->r != ofg->r || nfg->g != ofg->g || nfg->b != ofg->b ||
*c != *oc) {
changed=true;
}
}
if ( changed ) {
TCOD_opengl_putchar_ex(x, y, TCOD_ctx.ascii_to_tcod[*c], *nfg, *nbg);
}
c++;
nfg++;
nbg++;
if (track_changes) {
oc++;
ofg++;
obg++;
}
}
}
for( i = 0; i< ConsoleDataEnumSize; i++)
{
if(dirty[i])
{
updateTex((ConsoleDataEnum)i);
dirty[i] = false;
}
}
if ( TCOD_ctx.renderer == TCOD_RENDERER_OPENGL ) {
float texw=(float)conwidth/POTconwidth;
float texh=(float)conheight/POTconheight;
float fonw=(float)fontwidth/(TCOD_ctx.fontNbCharHoriz*POTfontwidth);
float fonh=(float)fontheight/(TCOD_ctx.fontNbCharVertic*POTfontheight);
DBGCHECKGL(glBindTexture(GL_TEXTURE_2D, Tex[BackCol]));
DBGCHECKGL(glBegin(GL_QUADS);
glColor3f(1.0,1.0,1.0);
glTexCoord2f( 0.0, 0.0 );
glVertex2i( 0, 0);
glTexCoord2f( 0.0, texh);
glVertex2i( 0, conheight );
glTexCoord2f( texw, texh );
glVertex2i( conwidth, conheight);
glTexCoord2f( texw, 0.0 );
glVertex2i( conwidth, 0 );
glEnd());
DBGCHECKGL(glBindTexture(GL_TEXTURE_2D, font_tex));
c = console->ch_array;
nfg = TCOD_image_get_colors(console->fg_colors);
nbg = TCOD_image_get_colors(console->bg_colors);
for (y=0;y<conheight;y++) {
for (x=0; x<conwidth; x++) {
if ( *c != ' ' ) {
TCOD_color_t f=*nfg;
TCOD_color_t b=*nbg;
if ( f.r != b.r || f.g != b.g || f.b != b.b ) {
int srcx,srcy,destx,desty;
int ascii;
destx=x;
desty=y;
if ( TCOD_ctx.fullscreen ) {
destx+=TCOD_ctx.fullscreen_offsetx/TCOD_ctx.font_width;
desty+=TCOD_ctx.fullscreen_offsety/TCOD_ctx.font_height;
}
ascii = TCOD_ctx.ascii_to_tcod[*c];
srcx = (ascii%TCOD_ctx.fontNbCharHoriz);
srcy = (ascii/TCOD_ctx.fontNbCharHoriz);
glBegin( GL_QUADS );
glColor3f((GLfloat)(f.r/255.0), (GLfloat)(f.g/255.0), (GLfloat)(f.b/255.0));
glTexCoord2f( srcx*fonw, srcy*fonh );
glVertex2i( destx, desty);
glTexCoord2f( srcx*fonw, (srcy+1)*fonh );
glVertex2i( destx, desty+1 );
glTexCoord2f( (srcx+1)*fonw, (srcy+1)*fonh );
glVertex2i( destx+1, desty+1 );
glTexCoord2f( (srcx+1)*fonw, srcy*fonh );
glVertex2i( destx+1, desty );
glEnd();
}
}
c++;
nfg++;
nbg++;
}
}
DBGCHECKGL(glBindTexture(GL_TEXTURE_2D, 0));
} else {
DBGCHECKGL(glUseProgramObjectARB(conProgram));
DBGCHECKGL(glUniform2fARB(glGetUniformLocationARB(conProgram,"termsize"), (float) conwidth, (float) conheight));
DBGCHECKGL(glUniform2fARB(glGetUniformLocationARB(conProgram,"termcoef"), 1.0f/POTconwidth, 1.0f/POTconheight));
DBGCHECKGL(glUniform1fARB(glGetUniformLocationARB(conProgram,"fontw"), (float)TCOD_ctx.fontNbCharHoriz));
DBGCHECKGL(glUniform2fARB(glGetUniformLocationARB(conProgram,"fontcoef"), (float)(fontwidth)/(POTfontwidth*TCOD_ctx.fontNbCharHoriz), (float)(fontheight)/(POTfontheight*TCOD_ctx.fontNbCharVertic)));
DBGCHECKGL(glActiveTextureF(GL_TEXTURE0));
DBGCHECKGL(glBindTexture(GL_TEXTURE_2D, font_tex));
DBGCHECKGL(glUniform1iARB(glGetUniformLocationARB(conProgram,"font"),0));
DBGCHECKGL(glActiveTextureF(GL_TEXTURE1));
DBGCHECKGL(glBindTexture(GL_TEXTURE_2D, Tex[Character]));
DBGCHECKGL(glUniform1iARB(glGetUniformLocationARB(conProgram,"term"),1));
DBGCHECKGL(glActiveTextureF(GL_TEXTURE2));
DBGCHECKGL(glBindTexture(GL_TEXTURE_2D, Tex[ForeCol]));
DBGCHECKGL(glUniform1iARB(glGetUniformLocationARB(conProgram,"termfcol"),2));
DBGCHECKGL(glActiveTextureF(GL_TEXTURE3));
DBGCHECKGL(glBindTexture(GL_TEXTURE_2D, Tex[BackCol]));
DBGCHECKGL(glUniform1iARB(glGetUniformLocationARB(conProgram,"termbcol"),3));
DBGCHECKGL(glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f,-1.0f,0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f,1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f,1.0f,0.0f);
glEnd());
DBGCHECKGL(glBindTexture(GL_TEXTURE_2D, 0));
DBGCHECKGL(glUseProgramObjectARB(0));
}
if ( fade != 255 ) {
int x=0,y=0;
if ( TCOD_ctx.fullscreen ) {
x=TCOD_ctx.fullscreen_offsetx/TCOD_ctx.font_width;
y=TCOD_ctx.fullscreen_offsety/TCOD_ctx.font_height;
}
glBegin( GL_QUADS );
glColor4f(TCOD_ctx.fading_color.r/255.0f,TCOD_ctx.fading_color.g/255.0f,TCOD_ctx.fading_color.b/255.0f,1.0f-fade/255.0f);
glVertex2i( x, y);
glVertex2i( x, y+conheight );
glVertex2i( x+conwidth, y+conheight );
glVertex2i( x+conwidth, y);
glEnd();
}
return true;
}
void TCOD_opengl_swap(void) {
SDL_GL_SwapWindow(window);
}
void * TCOD_opengl_get_screen(void) {
SDL_Surface *surf;
int pixw,pixh,offx=0,offy=0,x,y;
uint32_t mask,nmask;
pixw=TCOD_ctx.root->w * TCOD_ctx.font_width;
pixh=TCOD_ctx.root->h * TCOD_ctx.font_height;
surf=TCOD_sys_get_surface(pixw,pixh,false);
if ( TCOD_ctx.fullscreen ) {
offx=TCOD_ctx.fullscreen_offsetx;
offy=TCOD_ctx.fullscreen_offsety;
}
glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(offx,offy,pixw,pixh, GL_RGB, GL_UNSIGNED_BYTE, surf->pixels);
glPopClientAttrib();
mask=surf->format->Rmask|surf->format->Gmask|surf->format->Bmask;
nmask=~mask;
for (x=0; x < surf->w; x++) {
for (y=0; y < surf->h/2; y++) {
int offsrc=x*3+y*surf->pitch;
int offdst=x*3+(surf->h-1-y)*surf->pitch;
uint32_t *pixsrc = (uint32_t *)(((uint8_t*)surf->pixels)+offsrc);
uint32_t *pixdst = (uint32_t *)(((uint8_t*)surf->pixels)+offdst);
uint32_t tmp = *pixsrc;
*pixsrc = ((*pixsrc) & nmask) | ((*pixdst) & mask);
*pixdst = ((*pixdst) & nmask) | (tmp & mask);
}
}
return (void *)surf;
}
#endif
#endif