mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-11-10 23:02:03 +00:00
When OpenGL is available, prefer using the new glsurface to blit the classic renderer's 8-bit buffer to the screen.
git-svn-id: https://svn.eduke32.com/eduke32@6919 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
38de24d7eb
commit
9d243606d0
6 changed files with 334 additions and 11 deletions
|
@ -228,7 +228,7 @@ else
|
|||
endif
|
||||
endif
|
||||
ifeq (1,$(USE_OPENGL))
|
||||
engine_objs += voxmodel.cpp mdsprite.cpp tilepacker.cpp
|
||||
engine_objs += glsurface.cpp voxmodel.cpp mdsprite.cpp tilepacker.cpp
|
||||
engine_deps += glad
|
||||
ifeq (1,$(POLYMER))
|
||||
engine_objs += glbuild.cpp polymer.cpp
|
||||
|
|
41
source/build/include/glsurface.h
Normal file
41
source/build/include/glsurface.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef GLSURFACE_H_
|
||||
#define GLSURFACE_H_
|
||||
|
||||
#include "compat.h"
|
||||
#include "palette.h"
|
||||
|
||||
// Initialize the glsurface with the Software renderer's buffer resolution.
|
||||
// If the Software renderer's resolution and the actual resolution don't match,
|
||||
// glsurface will still render at the full size of the screen.
|
||||
// If a surface already exists, glsurface_destroy() will be automatically called before re-initializing.
|
||||
// Returns whether or not the glsurface could be successfully initialized.
|
||||
bool glsurface_initialize(vec2_t inputBufferResolution);
|
||||
|
||||
// Destroy an existing surface.
|
||||
void glsurface_destroy();
|
||||
|
||||
// Sets the palette at paletteID to contain the byte buffer pointed to by pPalette.
|
||||
// If the surface is not initialized, the function returns immediately.
|
||||
void glsurface_setPalette(int32_t paletteID, void* pPalette);
|
||||
|
||||
// Returns a pointer to the start of the surface's pixel buffer
|
||||
// Returns NULL if the surface is not initialized.
|
||||
void* glsurface_getBuffer();
|
||||
|
||||
// Returns the resolution of the surface's buffer
|
||||
vec2_t glsurface_getBufferResolution();
|
||||
|
||||
// Blit the surface's pixel buffer to the screen.
|
||||
// paletteID is the id of a palette previously set with glsurface_setPalette().
|
||||
// Renders as soon as the data has been uploaded.
|
||||
// If the surface is not initialized, the function returns immediately.
|
||||
void glsurface_blitBuffer(int32_t paletteID);
|
||||
|
||||
#endif /* GLSURFACE_H_ */
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#ifdef USE_OPENGL
|
||||
# include "glad/glad.h"
|
||||
# include "glsurface.h"
|
||||
# include "mdsprite.h"
|
||||
# ifdef POLYMER
|
||||
# include "polymer.h"
|
||||
|
@ -9898,6 +9899,11 @@ int32_t videoSetGameMode(char davidoption, int32_t daxdim, int32_t daydim, int32
|
|||
#ifdef USE_OPENGL
|
||||
fxdim = (float) daxdim;
|
||||
fydim = (float) daydim;
|
||||
|
||||
if (videoGetRenderMode() == REND_CLASSIC && !nogl)
|
||||
{
|
||||
glsurface_initialize({xdim, ydim});
|
||||
}
|
||||
#endif
|
||||
|
||||
videoAllocateBuffers();
|
||||
|
|
238
source/build/src/glsurface.cpp
Normal file
238
source/build/src/glsurface.cpp
Normal file
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* 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"
|
||||
|
||||
static void* buffer;
|
||||
static GLuint bufferTexID;
|
||||
static vec2_t bufferRes;
|
||||
|
||||
static GLuint paletteTexIDs[MAXBASEPALS];
|
||||
|
||||
static GLuint quadVertsID = 0;
|
||||
|
||||
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);
|
||||
OSD_Printf("Compile Status: %u\n", compileStatus);
|
||||
|
||||
if (!compileStatus)
|
||||
{
|
||||
GLint logLength;
|
||||
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0)
|
||||
{
|
||||
char *infoLog = (char*) malloc(logLength);
|
||||
glGetShaderInfoLog(shaderID, logLength, &logLength, infoLog);
|
||||
OSD_Printf("Log:\n%s\n", infoLog);
|
||||
free(infoLog);
|
||||
}
|
||||
}
|
||||
|
||||
return shaderID;
|
||||
}
|
||||
|
||||
bool glsurface_initialize(vec2_t inputBufferResolution)
|
||||
{
|
||||
if (buffer)
|
||||
glsurface_destroy();
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
bufferRes = inputBufferResolution;
|
||||
buffer = malloc(bufferRes.x*bufferRes.y);
|
||||
|
||||
glGenBuffers(1, &quadVertsID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quadVertsID);
|
||||
const float quadVerts[] =
|
||||
{
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, //top-left
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, //bottom-left
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 0.0f, //top-right
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 1.0f //bottom-right
|
||||
};
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVerts), quadVerts, GL_STATIC_DRAW);
|
||||
|
||||
//specify format/arrangement for vertex positions:
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(float) * 5, 0);
|
||||
//specify format/arrangement for vertex texture coords:
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, false, sizeof(float) * 5, (const void*) (sizeof(float) * 3));
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glGenTextures(1, &bufferTexID);
|
||||
glBindTexture(GL_TEXTURE_2D, bufferTexID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, bufferRes.x, bufferRes.y, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
|
||||
|
||||
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 = texture2D(s_palette, color.rg);\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);
|
||||
|
||||
for (int basepalnum = 0; basepalnum < MAXBASEPALS; ++basepalnum)
|
||||
{
|
||||
glsurface_setPalette(basepalnum, basepaltable[basepalnum]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void glsurface_destroy()
|
||||
{
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
free(buffer);
|
||||
buffer = 0;
|
||||
|
||||
glDeleteBuffers(1, &quadVertsID);
|
||||
quadVertsID = 0;
|
||||
|
||||
glDeleteTextures(1, &bufferTexID);
|
||||
bufferTexID = 0;
|
||||
glDeleteTextures(MAXBASEPALS, paletteTexIDs);
|
||||
memset(paletteTexIDs, 0, sizeof(paletteTexIDs));
|
||||
|
||||
glDeleteProgram(shaderProgramID);
|
||||
shaderProgramID = 0;
|
||||
}
|
||||
|
||||
void glsurface_setPalette(int32_t paletteID, void* pPalette)
|
||||
{
|
||||
if (!buffer)
|
||||
return;
|
||||
if (!pPalette)
|
||||
return;
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
if (paletteTexIDs[paletteID])
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, paletteTexIDs[paletteID]);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 1, GL_RGB, GL_UNSIGNED_BYTE, (void*) buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
glGenTextures(1, paletteTexIDs+paletteID);
|
||||
glBindTexture(GL_TEXTURE_2D, paletteTexIDs[paletteID]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 256, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, pPalette);
|
||||
}
|
||||
}
|
||||
|
||||
void* glsurface_getBuffer()
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
||||
vec2_t glsurface_getBufferResolution()
|
||||
{
|
||||
return bufferRes;
|
||||
}
|
||||
|
||||
void glsurface_blitBuffer(int32_t paletteID)
|
||||
{
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, paletteTexIDs[paletteID]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bufferRes.x, bufferRes.y, GL_RED, GL_UNSIGNED_BYTE, (void*) buffer);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP,
|
||||
0,
|
||||
4);
|
||||
}
|
|
@ -8,6 +8,10 @@
|
|||
#include "a.h"
|
||||
#include "xxhash.h"
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
# include "glsurface.h"
|
||||
#endif
|
||||
|
||||
uint8_t *basepaltable[MAXBASEPALS] = { palette };
|
||||
uint8_t basepalreset=1;
|
||||
uint8_t curbasepal;
|
||||
|
@ -656,7 +660,14 @@ void paletteSetColorTable(int32_t id, uint8_t const * const table)
|
|||
Bmemcpy(basepaltable[id], table, 768);
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
uploadbasepalette(id);
|
||||
if (videoGetRenderMode() == REND_CLASSIC)
|
||||
{
|
||||
glsurface_setPalette(id, basepaltable[id]);
|
||||
}
|
||||
else if (videoGetRenderMode() >= REND_POLYMOST)
|
||||
{
|
||||
uploadbasepalette(id);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#ifdef USE_OPENGL
|
||||
# include "glad/glad.h"
|
||||
# include "glbuild.h"
|
||||
# include "glsurface.h"
|
||||
#endif
|
||||
|
||||
#if defined _WIN32
|
||||
|
@ -1300,6 +1301,7 @@ static void destroy_window_resources()
|
|||
#ifdef USE_OPENGL
|
||||
void sdlayer_setvideomode_opengl(void)
|
||||
{
|
||||
glsurface_destroy();
|
||||
polymost_glreset();
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
@ -1447,8 +1449,13 @@ int32_t setvideomode_sdlcommon(int32_t *x, int32_t *y, int32_t c, int32_t fs, in
|
|||
while (lockcount) videoEndDrawing();
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
if (bpp > 8 && sdl_surface)
|
||||
polymost_glreset();
|
||||
if (sdl_surface)
|
||||
{
|
||||
if (bpp > 8)
|
||||
polymost_glreset();
|
||||
else if (!nogl)
|
||||
glsurface_destroy();
|
||||
}
|
||||
#endif
|
||||
|
||||
// clear last gamma/contrast/brightness so that it will be set anew
|
||||
|
@ -1462,7 +1469,7 @@ void setvideomode_sdlcommonpost(int32_t x, int32_t y, int32_t c, int32_t fs, int
|
|||
wm_setapptitle(apptitle);
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
if (c > 8)
|
||||
if (!nogl)
|
||||
sdlayer_setvideomode_opengl();
|
||||
#endif
|
||||
|
||||
|
@ -1587,7 +1594,7 @@ int32_t videoSetMode(int32_t x, int32_t y, int32_t c, int32_t fs)
|
|||
initprintf("Setting video mode %dx%d (%d-bpp %s)\n", x, y, c, ((fs & 1) ? "fullscreen" : "windowed"));
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
if (c > 8)
|
||||
if (c > 8 || !nogl)
|
||||
{
|
||||
int32_t i, j;
|
||||
#ifdef USE_GLEXT
|
||||
|
@ -1722,6 +1729,19 @@ void videoBeginDrawing(void)
|
|||
modechange = 0;
|
||||
return;
|
||||
}
|
||||
else if (!nogl)
|
||||
{
|
||||
if (offscreenrendering) return;
|
||||
|
||||
frameplace = (intptr_t)glsurface_getBuffer();
|
||||
if (modechange)
|
||||
{
|
||||
bytesperline = xdim;
|
||||
calc_ylookup(bytesperline, ydim);
|
||||
modechange=0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// lock the frame
|
||||
if (lockcount++ > 0)
|
||||
|
@ -1748,7 +1768,7 @@ void videoBeginDrawing(void)
|
|||
//
|
||||
void videoEndDrawing(void)
|
||||
{
|
||||
if (bpp > 8)
|
||||
if (bpp > 8 || !nogl)
|
||||
{
|
||||
if (!offscreenrendering) frameplace = 0;
|
||||
return;
|
||||
|
@ -1783,14 +1803,21 @@ void videoShowFrame(int32_t w)
|
|||
#endif
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
if (bpp > 8)
|
||||
if (!nogl)
|
||||
{
|
||||
if (palfadedelta)
|
||||
fullscreen_tint_gl(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
|
||||
if (bpp > 8)
|
||||
{
|
||||
if (palfadedelta)
|
||||
fullscreen_tint_gl(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
AndroidDrawControls();
|
||||
AndroidDrawControls();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
glsurface_blitBuffer(curbasepal);
|
||||
}
|
||||
|
||||
static uint32_t lastSwapTime = 0;
|
||||
SDL_GL_SwapWindow(sdl_window);
|
||||
|
|
Loading…
Reference in a new issue