raze-gles/source/build/src/glsurface.cpp
terminx ccdba037b5 Added Xfree() function to accompany the Xmalloc() family of functions and change all uses of Bfree() to Xfree()
This was necessary because everything is already allocated with the Xmalloc() functions, but a future commit will make blocks allocated with those functions no longer compatible with the system implementation of free(), which Bfree() wraps.

git-svn-id: https://svn.eduke32.com/eduke32@7705 1a8010ca-5511-0410-912e-c29ae57300e0

# Conflicts:
#	source/build/src/build.cpp
#	source/build/src/mdsprite.cpp
#	source/build/src/polymer.cpp
#	source/build/src/polymost.cpp
#	source/build/src/texcache.cpp
#	source/build/src/voxmodel.cpp
2019-09-20 12:07:10 +02:00

194 lines
5.2 KiB
C++

/*
* glsurface.cpp
* A 32-bit rendering surface that can quickly blit 8-bit paletted buffers implemented in OpenGL.
*
* Copyright © 2018, Alex Dawson. All rights reserved.
*/
#include "glsurface.h"
#include "glad/glad.h"
#include "baselayer.h"
#include "build.h"
#include "../../glbackend/glbackend.h"
static void* buffer;
static FHardwareTexture* bufferTexture;
static vec2_t bufferRes;
static FHardwareTexture* paletteTexture;
static GLuint shaderProgramID = 0;
static GLint texSamplerLoc = -1;
static GLint paletteSamplerLoc = -1;
static GLuint compileShader(GLenum shaderType, const char* const source)
{
GLuint shaderID = glCreateShader(shaderType);
if (shaderID == 0)
return 0;
const char* const sources[1] = {source};
glShaderSource(shaderID,
1,
sources,
NULL);
glCompileShader(shaderID);
GLint compileStatus;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compileStatus);
if (!compileStatus)
{
GLint logLength;
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLength);
OSD_Printf("Compile Status: %u\n", compileStatus);
if (logLength > 0)
{
char *infoLog = (char*) Xmalloc(logLength);
glGetShaderInfoLog(shaderID, logLength, &logLength, infoLog);
OSD_Printf("Log:\n%s\n", infoLog);
Xfree(infoLog);
}
}
return shaderID;
}
bool glsurface_initialize(vec2_t bufferResolution)
{
if (buffer)
glsurface_destroy();
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
bufferRes = bufferResolution;
buffer = Xaligned_alloc(16, bufferRes.x * bufferRes.y);
bufferTexture = GLInterface.NewTexture();
bufferTexture->CreateTexture(bufferRes.x, bufferRes.y, true, false);
GLInterface.Init();
glsurface_setPalette(curpalettefaded);
const char* const VERTEX_SHADER_CODE =
"#version 110\n\
\n\
attribute vec4 i_vertPos;\n\
attribute vec2 i_texCoord;\n\
\n\
varying vec2 v_texCoord;\n\
\n\
void main()\n\
{\n\
gl_Position = i_vertPos;\n\
v_texCoord = i_texCoord;\n\
}\n";
const char* const FRAGMENT_SHADER_CODE =
"#version 110\n\
\n\
//s_texture points to an indexed color texture\n\
uniform sampler2D s_texture;\n\
//s_palette is the palette texture\n\
uniform sampler2D s_palette;\n\
\n\
varying vec2 v_texCoord;\n\
\n\
const float c_paletteScale = 255.0/256.0;\n\
const float c_paletteOffset = 0.5/256.0;\n\
\n\
void main()\n\
{\n\
vec4 color = texture2D(s_texture, v_texCoord.xy);\n\
color.r = c_paletteOffset + c_paletteScale*color.r;\n\
color.rgb = texture2D(s_palette, color.rg).rgb;\n\
\n\
// DEBUG \n\
//color = texture2D(s_palette, v_texCoord.xy);\n\
//color = texture2D(s_texture, v_texCoord.xy);\n\
\n\
gl_FragColor = color;\n\
}\n";
shaderProgramID = glCreateProgram();
GLuint vertexShaderID = compileShader(GL_VERTEX_SHADER, VERTEX_SHADER_CODE);
GLuint fragmentShaderID = compileShader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER_CODE);
glAttachShader(shaderProgramID, vertexShaderID);
glAttachShader(shaderProgramID, fragmentShaderID);
glBindAttribLocation(shaderProgramID, 0, "i_vertPos");
glBindAttribLocation(shaderProgramID, 1, "i_texCoord");
glLinkProgram(shaderProgramID);
glDetachShader(shaderProgramID, vertexShaderID);
glDeleteShader(vertexShaderID);
glDetachShader(shaderProgramID, fragmentShaderID);
glDeleteShader(fragmentShaderID);
glUseProgram(shaderProgramID);
texSamplerLoc = glGetUniformLocation(shaderProgramID, "s_texture");
paletteSamplerLoc = glGetUniformLocation(shaderProgramID, "s_palette");
glUniform1i(texSamplerLoc, 0);
glUniform1i(paletteSamplerLoc, 1);
return true;
}
void glsurface_destroy()
{
if (!buffer)
return;
ALIGNED_FREE_AND_NULL(buffer);
delete bufferTexture;
bufferTexture = nullptr;
delete paletteTexture;
paletteTexture = nullptr;
glUseProgram(0);
glDeleteProgram(shaderProgramID);
shaderProgramID = 0;
}
void glsurface_setPalette(void* pPalette)
{
if (!buffer)
return;
if (!pPalette)
return;
if (!paletteTexture)
{
paletteTexture = GLInterface.NewTexture();
paletteTexture->CreateTexture(256, 1, false, false);
}
paletteTexture->LoadTexture(palette);
GLInterface.BindTexture(1, paletteTexture, Sampler2DNoFilter);
}
void* glsurface_getBuffer()
{
return buffer;
}
vec2_t glsurface_getBufferResolution()
{
return bufferRes;
}
void glsurface_blitBuffer()
{
if (!buffer)
return;
bufferTexture->LoadTexture((uint8_t*)buffer);
GLInterface.BindTexture(0, bufferTexture, Sampler2DNoFilter);
auto data = GLInterface.AllocVertices(4);
auto vt = data.second;
vt[0].Set(-1.0f, 1.0f, 0.0f, 0.0f, 0.0f); //top-left
vt[1].Set(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f); //bottom-left
vt[2].Set(1.0f, 1.0f, 0.0f, 1.0f, 0.0f); //top-right
vt[3].Set(1.0f, -1.0f, 0.0f, 1.0f, 1.0f); //bottom-right
GLInterface.Draw(DT_TRIANGLE_STRIP, data.first, 4);
}