mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-05-09 11:51:09 +08:00
support for GLSL shader on both SDL1 and SDL2 builds
This commit is contained in:
parent
0df4c8dd39
commit
a01ac1c168
@ -1,4 +1,11 @@
|
|||||||
0.83.6
|
0.83.6
|
||||||
|
- Added GLSL shader support by porting the feature
|
||||||
|
from DOSBox SVN. Worked for SDL1 and SDL2 builds.
|
||||||
|
The config option "glshader" (in [render] section)
|
||||||
|
can be used to specify a GLSL shader file or a
|
||||||
|
built-in GLSL shader when the output is set to
|
||||||
|
"opengl" or "openglnb". For example, you can use
|
||||||
|
"glshader=sharp" for pixel-perfect mode. (Wengier)
|
||||||
- Support for FluidSynth MIDI Synthesizer is now
|
- Support for FluidSynth MIDI Synthesizer is now
|
||||||
activated by default for Windows Visual Studio
|
activated by default for Windows Visual Studio
|
||||||
x86/x64 builds. (Wengier)
|
x86/x64 builds. (Wengier)
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<category>Emulation</category>
|
<category>Emulation</category>
|
||||||
</categories>
|
</categories>
|
||||||
<releases>
|
<releases>
|
||||||
<release version="@PACKAGE_VERSION@" date="2020-9-19"/>
|
<release version="@PACKAGE_VERSION@" date="2020-9-20"/>
|
||||||
</releases>
|
</releases>
|
||||||
<screenshots>
|
<screenshots>
|
||||||
<screenshot/>
|
<screenshot/>
|
||||||
|
@ -737,6 +737,10 @@ pc-98 show graphics layer on initialize = true
|
|||||||
# To fit a scaler in the resolution used at full screen may require a border or side bars.
|
# To fit a scaler in the resolution used at full screen may require a border or side bars.
|
||||||
# To fill the screen entirely, depending on your hardware, a different scaler/fullresolution might work.
|
# To fill the screen entirely, depending on your hardware, a different scaler/fullresolution might work.
|
||||||
# Possible values: none, normal2x, normal3x, normal4x, normal5x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x, gray, gray2x, hardware_none, hardware2x, hardware3x, hardware4x, hardware5x, xbrz, xbrz_bilinear.
|
# Possible values: none, normal2x, normal3x, normal4x, normal5x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x, gray, gray2x, hardware_none, hardware2x, hardware3x, hardware4x, hardware5x, xbrz, xbrz_bilinear.
|
||||||
|
# glshader: Path to GLSL shader source to use with OpenGL output ("none" to disable).
|
||||||
|
# Can be either an absolute path, a file in the "glshaders" subdirectory of the DOSBox-X configuration directory,
|
||||||
|
# or one of the built-in shaders (use "sharp" for the pixel-perfect mode):
|
||||||
|
# advinterp2x, advinterp3x, advmame2x, advmame3x, rgb2x, rgb3x, scan2x, scan3x, tv2x, tv3x, sharp.
|
||||||
# xbrz slice: Number of screen lines to process in single xBRZ scaler taskset task, affects xBRZ performance, 16 is the default
|
# xbrz slice: Number of screen lines to process in single xBRZ scaler taskset task, affects xBRZ performance, 16 is the default
|
||||||
# xbrz fixed scale factor: To use fixed xBRZ scale factor (i.e. to attune performance), set it to 2-6, 0 - use automatic calculation (default)
|
# xbrz fixed scale factor: To use fixed xBRZ scale factor (i.e. to attune performance), set it to 2-6, 0 - use automatic calculation (default)
|
||||||
# xbrz max scale factor: To cap maximum xBRZ scale factor used (i.e. to attune performance), set it to 2-6, 0 - use scaler allowed maximum (default)
|
# xbrz max scale factor: To cap maximum xBRZ scale factor used (i.e. to attune performance), set it to 2-6, 0 - use scaler allowed maximum (default)
|
||||||
@ -753,6 +757,7 @@ char9 = true
|
|||||||
euro = -1
|
euro = -1
|
||||||
doublescan = true
|
doublescan = true
|
||||||
scaler = normal2x
|
scaler = normal2x
|
||||||
|
glshader = none
|
||||||
xbrz slice = 16
|
xbrz slice = 16
|
||||||
xbrz fixed scale factor = 0
|
xbrz fixed scale factor = 0
|
||||||
xbrz max scale factor = 0
|
xbrz max scale factor = 0
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*auto-generated*/
|
/*auto-generated*/
|
||||||
#define UPDATED_STR "Sep 19, 2020 6:54:21pm"
|
#define UPDATED_STR "Sep 20, 2020 7:16:36pm"
|
||||||
#define GIT_COMMIT_HASH "9ea356c"
|
#define GIT_COMMIT_HASH "8bcc19e"
|
||||||
#define COPYRIGHT_END_YEAR "2020"
|
#define COPYRIGHT_END_YEAR "2020"
|
||||||
|
@ -91,6 +91,9 @@ typedef struct {
|
|||||||
Bit8u *cacheRead;
|
Bit8u *cacheRead;
|
||||||
Bitu inHeight, inLine, outLine;
|
Bitu inHeight, inLine, outLine;
|
||||||
} scale;
|
} scale;
|
||||||
|
#if C_OPENGL
|
||||||
|
char* shader_src;
|
||||||
|
#endif
|
||||||
RenderPal_t pal;
|
RenderPal_t pal;
|
||||||
bool updating;
|
bool updating;
|
||||||
bool active;
|
bool active;
|
||||||
@ -108,6 +111,7 @@ void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,float fps,double scrn_ratio)
|
|||||||
bool RENDER_StartUpdate(void);
|
bool RENDER_StartUpdate(void);
|
||||||
void RENDER_EndUpdate(bool abort);
|
void RENDER_EndUpdate(bool abort);
|
||||||
void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue);
|
void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue);
|
||||||
|
bool RENDER_GetForceUpdate(void);
|
||||||
|
void RENDER_SetForceUpdate(bool);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -60,7 +60,7 @@ Bitu GFX_GetBestMode(Bitu flags);
|
|||||||
Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue);
|
Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue);
|
||||||
Bitu GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,GFX_CallBack_t callback);
|
Bitu GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,GFX_CallBack_t callback);
|
||||||
void GFX_TearDown(void);
|
void GFX_TearDown(void);
|
||||||
|
void GFX_SetShader(const char* src);
|
||||||
void GFX_ResetScreen(void);
|
void GFX_ResetScreen(void);
|
||||||
void GFX_RestoreMode(void);
|
void GFX_RestoreMode(void);
|
||||||
void GFX_Start(void);
|
void GFX_Start(void);
|
||||||
|
@ -2235,6 +2235,14 @@ void DOSBOX_SetupConfigSections(void) {
|
|||||||
Pstring = Pmulti->GetSection()->Add_string("force",Property::Changeable::Always,"");
|
Pstring = Pmulti->GetSection()->Add_string("force",Property::Changeable::Always,"");
|
||||||
Pstring->Set_values(force);
|
Pstring->Set_values(force);
|
||||||
|
|
||||||
|
#if C_OPENGL
|
||||||
|
Pstring = secprop->Add_path("glshader",Property::Changeable::Always,"none");
|
||||||
|
Pstring->Set_help("Path to GLSL shader source to use with OpenGL output (\"none\" to disable).\n"
|
||||||
|
"Can be either an absolute path, a file in the \"glshaders\" subdirectory of the DOSBox-X configuration directory,\n"
|
||||||
|
"or one of the built-in shaders (use \"sharp\" for the pixel-perfect mode):\n"
|
||||||
|
"advinterp2x, advinterp3x, advmame2x, advmame3x, rgb2x, rgb3x, scan2x, scan3x, tv2x, tv3x, sharp.");
|
||||||
|
#endif
|
||||||
|
|
||||||
#if C_XBRZ
|
#if C_XBRZ
|
||||||
Pint = secprop->Add_int("xbrz slice",Property::Changeable::OnlyAtStart,16);
|
Pint = secprop->Add_int("xbrz slice",Property::Changeable::OnlyAtStart,16);
|
||||||
Pint->SetMinMax(1,1024);
|
Pint->SetMinMax(1,1024);
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
#include "video.h"
|
#include "video.h"
|
||||||
@ -31,8 +33,10 @@
|
|||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "support.h"
|
#include "support.h"
|
||||||
#include "sdlmain.h"
|
#include "sdlmain.h"
|
||||||
|
#include "shell.h"
|
||||||
|
|
||||||
#include "render_scalers.h"
|
#include "render_scalers.h"
|
||||||
|
#include "render_glsl.h"
|
||||||
#if defined(__SSE__)
|
#if defined(__SSE__)
|
||||||
#include <xmmintrin.h>
|
#include <xmmintrin.h>
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
@ -366,7 +370,7 @@ void RENDER_EndUpdate( bool abort ) {
|
|||||||
#endif
|
#endif
|
||||||
// Force output to update the screen even if nothing changed...
|
// Force output to update the screen even if nothing changed...
|
||||||
// works only with Direct3D output (GFX_StartUpdate() was probably not even called)
|
// works only with Direct3D output (GFX_StartUpdate() was probably not even called)
|
||||||
if (render.forceUpdate) GFX_EndUpdate( 0 );
|
if (RENDER_GetForceUpdate()) GFX_EndUpdate( 0 );
|
||||||
}
|
}
|
||||||
render.frameskip.index = (render.frameskip.index + 1) & (RENDER_SKIP_CACHE - 1);
|
render.frameskip.index = (render.frameskip.index + 1) & (RENDER_SKIP_CACHE - 1);
|
||||||
render.updating=false;
|
render.updating=false;
|
||||||
@ -666,6 +670,9 @@ forcenormal:
|
|||||||
sdl.srcAspect.yToX = (double)sdl.srcAspect.y / sdl.srcAspect.x;
|
sdl.srcAspect.yToX = (double)sdl.srcAspect.y / sdl.srcAspect.x;
|
||||||
LOG_MSG("Aspect ratio: %u x %u xToY=%.3f yToX=%.3f",sdl.srcAspect.x,sdl.srcAspect.y,sdl.srcAspect.xToY,sdl.srcAspect.yToX);
|
LOG_MSG("Aspect ratio: %u x %u xToY=%.3f yToX=%.3f",sdl.srcAspect.x,sdl.srcAspect.y,sdl.srcAspect.xToY,sdl.srcAspect.yToX);
|
||||||
/* Setup the scaler variables */
|
/* Setup the scaler variables */
|
||||||
|
#if C_OPENGL
|
||||||
|
GFX_SetShader(render.shader_src);
|
||||||
|
#endif
|
||||||
gfx_flags=GFX_SetSize(width,height,gfx_flags,gfx_scalew,gfx_scaleh,&RENDER_CallBack);
|
gfx_flags=GFX_SetSize(width,height,gfx_flags,gfx_scalew,gfx_scaleh,&RENDER_CallBack);
|
||||||
if (gfx_flags & GFX_CAN_8)
|
if (gfx_flags & GFX_CAN_8)
|
||||||
render.scale.outMode = scalerMode8;
|
render.scale.outMode = scalerMode8;
|
||||||
@ -846,10 +853,72 @@ static void ChangeScaler(bool pressed) {
|
|||||||
|
|
||||||
void RENDER_UpdateFromScalerSetting(void);
|
void RENDER_UpdateFromScalerSetting(void);
|
||||||
|
|
||||||
|
bool RENDER_GetForceUpdate(void) {
|
||||||
|
return render.forceUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
void RENDER_SetForceUpdate(bool f) {
|
void RENDER_SetForceUpdate(bool f) {
|
||||||
render.forceUpdate = f;
|
render.forceUpdate = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if C_OPENGL
|
||||||
|
static bool RENDER_GetShader(std::string& shader_path, char *old_src) {
|
||||||
|
char* src;
|
||||||
|
std::stringstream buf;
|
||||||
|
std::ifstream fshader(shader_path.c_str(), std::ios_base::binary);
|
||||||
|
if (!fshader.is_open()) fshader.open((shader_path + ".glsl").c_str(), std::ios_base::binary);
|
||||||
|
if (fshader.is_open()) {
|
||||||
|
buf << fshader.rdbuf();
|
||||||
|
fshader.close();
|
||||||
|
}
|
||||||
|
else if (shader_path == "advinterp2x") buf << advinterp2x_glsl;
|
||||||
|
else if (shader_path == "advinterp3x") buf << advinterp3x_glsl;
|
||||||
|
else if (shader_path == "advmame2x") buf << advmame2x_glsl;
|
||||||
|
else if (shader_path == "advmame3x") buf << advmame3x_glsl;
|
||||||
|
else if (shader_path == "rgb2x") buf << rgb2x_glsl;
|
||||||
|
else if (shader_path == "rgb3x") buf << rgb3x_glsl;
|
||||||
|
else if (shader_path == "scan2x") buf << scan2x_glsl;
|
||||||
|
else if (shader_path == "scan3x") buf << scan3x_glsl;
|
||||||
|
else if (shader_path == "tv2x") buf << tv2x_glsl;
|
||||||
|
else if (shader_path == "tv3x") buf << tv3x_glsl;
|
||||||
|
else if (shader_path == "sharp") buf << sharp_glsl;
|
||||||
|
|
||||||
|
if (!buf.str().empty()) {
|
||||||
|
std::string s = buf.str();
|
||||||
|
if (first_shell) {
|
||||||
|
std::string pre_defs;
|
||||||
|
Bitu count = first_shell->GetEnvCount();
|
||||||
|
for (Bitu i=0; i < count; i++) {
|
||||||
|
std::string env;
|
||||||
|
if (!first_shell->GetEnvNum(i, env))
|
||||||
|
continue;
|
||||||
|
if (env.compare(0, 9, "GLSHADER_")==0) {
|
||||||
|
size_t brk = env.find('=');
|
||||||
|
if (brk == std::string::npos) continue;
|
||||||
|
env[brk] = ' ';
|
||||||
|
pre_defs += "#define " + env.substr(9) + '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pre_defs.empty()) {
|
||||||
|
// if "#version" occurs it must be before anything except comments and whitespace
|
||||||
|
size_t pos = buf.str().find("#version ");
|
||||||
|
if (pos != std::string::npos) pos = buf.str().find('\n', pos+9);
|
||||||
|
if (pos == std::string::npos) pos = 0;
|
||||||
|
else ++pos;
|
||||||
|
s = buf.str().insert(pos, pre_defs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// keep the same buffer if contents aren't different
|
||||||
|
if (old_src==NULL || s != old_src) {
|
||||||
|
src = strdup(s.c_str());
|
||||||
|
if (src==NULL) LOG_MSG("WARNING: Couldn't copy shader source");
|
||||||
|
} else src = old_src;
|
||||||
|
} else src = NULL;
|
||||||
|
render.shader_src = src;
|
||||||
|
return src != NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void RENDER_UpdateFrameskipMenu(void) {
|
void RENDER_UpdateFrameskipMenu(void) {
|
||||||
char tmp[64];
|
char tmp[64];
|
||||||
|
|
||||||
@ -1091,10 +1160,31 @@ void RENDER_Init() {
|
|||||||
|
|
||||||
render.autofit=section->Get_bool("autofit");
|
render.autofit=section->Get_bool("autofit");
|
||||||
|
|
||||||
|
#if C_OPENGL
|
||||||
|
char* shader_src = render.shader_src;
|
||||||
|
Prop_path *sh = section->Get_path("glshader");
|
||||||
|
std::string f = (std::string)sh->GetValue();
|
||||||
|
if (f.empty() || f=="none") render.shader_src = NULL;
|
||||||
|
else if (!RENDER_GetShader(sh->realpath,shader_src)) {
|
||||||
|
std::string path;
|
||||||
|
Cross::GetPlatformConfigDir(path);
|
||||||
|
path = path + "glshaders" + CROSS_FILESPLIT + f;
|
||||||
|
if (!RENDER_GetShader(path,shader_src) && (sh->realpath==f || !RENDER_GetShader(f,shader_src))) {
|
||||||
|
sh->SetValue("none");
|
||||||
|
LOG_MSG("Shader file \"%s\" not found", f.c_str());
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
LOG_MSG("Loaded GLSL shader: %s\n", f.c_str());
|
||||||
|
if (shader_src!=render.shader_src) free(shader_src);
|
||||||
|
#endif
|
||||||
|
|
||||||
//If something changed that needs a ReInit
|
//If something changed that needs a ReInit
|
||||||
// Only ReInit when there is a src.bpp (fixes crashes on startup and directly changing the scaler without a screen specified yet)
|
// Only ReInit when there is a src.bpp (fixes crashes on startup and directly changing the scaler without a screen specified yet)
|
||||||
if(running && render.src.bpp && ((render.aspect != aspect) || (render.scale.op != scaleOp) ||
|
if(running && render.src.bpp && ((render.aspect != aspect) || (render.scale.op != scaleOp) ||
|
||||||
(render.scale.size != scalersize) || (render.scale.forced != scalerforced) ||
|
(render.scale.size != scalersize) || (render.scale.forced != scalerforced) ||
|
||||||
|
#if C_OPENGL
|
||||||
|
(render.shader_src != shader_src) ||
|
||||||
|
#endif
|
||||||
render.scale.forced))
|
render.scale.forced))
|
||||||
RENDER_CallBack( GFX_CallBackReset );
|
RENDER_CallBack( GFX_CallBackReset );
|
||||||
|
|
||||||
|
576
src/gui/render_glsl.h
Normal file
576
src/gui/render_glsl.h
Normal file
@ -0,0 +1,576 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002-2020 The DOSBox Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if C_OPENGL
|
||||||
|
|
||||||
|
static const char advinterp2x_glsl[] =
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"uniform sampler2D rubyTexture;\n"
|
||||||
|
"uniform vec2 rubyInputSize;\n"
|
||||||
|
"uniform vec2 rubyOutputSize;\n"
|
||||||
|
"uniform vec2 rubyTextureSize;\n"
|
||||||
|
""
|
||||||
|
"#if defined(VERTEX)\n"
|
||||||
|
"attribute vec4 a_position;\n"
|
||||||
|
""
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = a_position;\n"
|
||||||
|
" v_texCoord = vec2(a_position.x+1.0,1.0-a_position.y)*rubyInputSize;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"#elif defined(FRAGMENT)\n"
|
||||||
|
""
|
||||||
|
"vec3 getadvinterp2xtexel(vec2 coord) {\n"
|
||||||
|
" vec2 base = floor(coord/vec2(2.0))+vec2(0.5);\n"
|
||||||
|
" vec3 c4 = texture2D(rubyTexture, base/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c1 = texture2D(rubyTexture, (base-vec2(0.0,1.0))/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c7 = texture2D(rubyTexture, (base+vec2(0.0,1.0))/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c3 = texture2D(rubyTexture, (base-vec2(1.0,0.0))/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c5 = texture2D(rubyTexture, (base+vec2(1.0,0.0))/rubyTextureSize).xyz;\n"
|
||||||
|
""
|
||||||
|
" bool outer = c1 != c7 && c3 != c5;\n"
|
||||||
|
" bool c3c1 = outer && c3==c1;\n"
|
||||||
|
" bool c1c5 = outer && c1==c5;\n"
|
||||||
|
" bool c3c7 = outer && c3==c7;\n"
|
||||||
|
" bool c7c5 = outer && c7==c5;\n"
|
||||||
|
""
|
||||||
|
" vec3 l00 = mix(c3,c4,c3c1?3.0/8.0:1.0);\n"
|
||||||
|
" vec3 l01 = mix(c5,c4,c1c5?3.0/8.0:1.0);\n"
|
||||||
|
" vec3 l10 = mix(c3,c4,c3c7?3.0/8.0:1.0);\n"
|
||||||
|
" vec3 l11 = mix(c5,c4,c7c5?3.0/8.0:1.0);\n"
|
||||||
|
""
|
||||||
|
" coord = max(floor(mod(coord, 2.0)), 0.0);\n"
|
||||||
|
" /* 2x2 output:\n"
|
||||||
|
" * |x=0|x=1\n"
|
||||||
|
" * y=0|l00|l01\n"
|
||||||
|
" * y=1|l10|l11\n"
|
||||||
|
" */\n"
|
||||||
|
""
|
||||||
|
" return mix(mix(l00,l01,coord.x), mix(l10,l11,coord.x), coord.y);\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" vec2 coord = v_texCoord;\n"
|
||||||
|
"#if defined(OPENGLNB)\n"
|
||||||
|
" gl_FragColor = getadvinterp2xtexel(coord);\n"
|
||||||
|
"#else\n"
|
||||||
|
" coord -= 0.5;\n"
|
||||||
|
" vec3 c0 = getadvinterp2xtexel(coord);\n"
|
||||||
|
" vec3 c1 = getadvinterp2xtexel(coord+vec2(1.0,0.0));\n"
|
||||||
|
" vec3 c2 = getadvinterp2xtexel(coord+vec2(0.0,1.0));\n"
|
||||||
|
" vec3 c3 = getadvinterp2xtexel(coord+vec2(1.0));\n"
|
||||||
|
""
|
||||||
|
" coord = fract(max(coord,0.0));\n"
|
||||||
|
" gl_FragColor = vec4(mix(mix(c0,c1,coord.x), mix(c2,c3,coord.x), coord.y), 1.0);\n"
|
||||||
|
"#endif\n"
|
||||||
|
"}\n"
|
||||||
|
"#endif";
|
||||||
|
|
||||||
|
static const char advinterp3x_glsl[] =
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"uniform sampler2D rubyTexture;\n"
|
||||||
|
"uniform vec2 rubyInputSize;\n"
|
||||||
|
"uniform vec2 rubyOutputSize;\n"
|
||||||
|
"uniform vec2 rubyTextureSize;\n"
|
||||||
|
""
|
||||||
|
"#if defined(VERTEX)\n"
|
||||||
|
"attribute vec4 a_position;\n"
|
||||||
|
""
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = a_position;\n"
|
||||||
|
" v_texCoord = vec2(a_position.x+1.0,1.0-a_position.y)/2.0*rubyInputSize*3.0;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"#elif defined(FRAGMENT)\n"
|
||||||
|
""
|
||||||
|
"vec3 getadvinterp3xtexel(vec2 coord) {\n"
|
||||||
|
" vec2 base = floor(coord/vec2(3.0))+vec2(0.5);\n"
|
||||||
|
" vec3 c0 = texture2D(rubyTexture, (base-vec2(1.0,1.0))/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c1 = texture2D(rubyTexture, (base-vec2(0.0,1.0))/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c2 = texture2D(rubyTexture, (base-vec2(-1.0,1.0))/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c3 = texture2D(rubyTexture, (base-vec2(1.0,0.0))/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c4 = texture2D(rubyTexture, base/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c5 = texture2D(rubyTexture, (base+vec2(1.0,0.0))/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c6 = texture2D(rubyTexture, (base+vec2(-1.0,1.0))/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c7 = texture2D(rubyTexture, (base+vec2(0.0,1.0))/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c8 = texture2D(rubyTexture, (base+vec2(1.0,1.0))/rubyTextureSize).xyz;\n"
|
||||||
|
""
|
||||||
|
" bool outer = c1 != c7 && c3 != c5;\n"
|
||||||
|
""
|
||||||
|
" vec3 l00 = mix(c3,c4,(outer && c3==c1) ? 3.0/8.0:1.0);\n"
|
||||||
|
" vec3 l01 = (outer && ((c3==c1&&c4!=c2)||(c5==c1&&c4!=c0))) ? c1 : c4;\n"
|
||||||
|
" vec3 l02 = mix(c5,c4,(outer && c5==c1) ? 3.0/8.0:1.0);\n"
|
||||||
|
" vec3 l10 = (outer && ((c3==c1&&c4!=c6)||(c3==c7&&c4!=c0))) ? c3 : c4;\n"
|
||||||
|
" vec3 l11 = c4;\n"
|
||||||
|
" vec3 l12 = (outer && ((c5==c1&&c4!=c8)||(c5==c7&&c4!=c2))) ? c5 : c4;\n"
|
||||||
|
" vec3 l20 = mix(c3,c4,(outer && c3==c7) ? 3.0/8.0:1.0);\n"
|
||||||
|
" vec3 l21 = (outer && ((c3==c7&&c4!=c8)||(c5==c7&&c4!=c6))) ? c7 : c4;\n"
|
||||||
|
" vec3 l22 = mix(c5,c4,(outer && c5==c7) ? 3.0/8.0:1.0);\n"
|
||||||
|
""
|
||||||
|
" coord = mod(coord, 3.0);\n"
|
||||||
|
" bvec2 l = lessThan(coord, vec2(1.0));\n"
|
||||||
|
" bvec2 h = greaterThanEqual(coord, vec2(2.0));\n"
|
||||||
|
""
|
||||||
|
" if (h.x) {\n"
|
||||||
|
" l01 = l02;\n"
|
||||||
|
" l11 = l12;\n"
|
||||||
|
" l21 = l22;\n"
|
||||||
|
" }\n"
|
||||||
|
" if (h.y) {\n"
|
||||||
|
" l10 = l20;\n"
|
||||||
|
" l11 = l21;\n"
|
||||||
|
" }\n"
|
||||||
|
" if (l.x) {\n"
|
||||||
|
" l01 = l00;\n"
|
||||||
|
" l11 = l10;\n"
|
||||||
|
" }\n"
|
||||||
|
" return l.y ? l01 : l11;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" vec2 coord = v_texCoord;\n"
|
||||||
|
"#if defined(OPENGLNB)\n"
|
||||||
|
" gl_FragColor = getadvinterp3xtexel(coord);\n"
|
||||||
|
"#else\n"
|
||||||
|
" coord -= 0.5;\n"
|
||||||
|
" vec3 c0 = getadvinterp3xtexel(coord);\n"
|
||||||
|
" vec3 c1 = getadvinterp3xtexel(coord+vec2(1.0,0.0));\n"
|
||||||
|
" vec3 c2 = getadvinterp3xtexel(coord+vec2(0.0,1.0));\n"
|
||||||
|
" vec3 c3 = getadvinterp3xtexel(coord+vec2(1.0));\n"
|
||||||
|
""
|
||||||
|
" coord = fract(max(coord,0.0));\n"
|
||||||
|
" gl_FragColor = vec4(mix(mix(c0,c1,coord.x), mix(c2,c3,coord.x), coord.y), 1.0);\n"
|
||||||
|
"#endif\n"
|
||||||
|
"}\n"
|
||||||
|
"#endif";
|
||||||
|
|
||||||
|
static const char advmame2x_glsl[] =
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"uniform sampler2D rubyTexture;\n"
|
||||||
|
"uniform vec2 rubyInputSize;\n"
|
||||||
|
"uniform vec2 rubyOutputSize;\n"
|
||||||
|
"uniform vec2 rubyTextureSize;\n"
|
||||||
|
""
|
||||||
|
"#if defined(VERTEX)\n"
|
||||||
|
"attribute vec4 a_position;\n"
|
||||||
|
""
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = a_position;\n"
|
||||||
|
" v_texCoord = vec2(a_position.x+1.0,1.0-a_position.y)*rubyInputSize;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"#elif defined(FRAGMENT)\n"
|
||||||
|
""
|
||||||
|
"vec3 getadvmame2xtexel(vec2 coord) {\n"
|
||||||
|
" vec2 base = floor(coord/vec2(2.0))+vec2(0.5);\n"
|
||||||
|
" vec3 c4 = texture2D(rubyTexture, base/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c1 = texture2D(rubyTexture, (base-vec2(0.0,1.0))/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c7 = texture2D(rubyTexture, (base+vec2(0.0,1.0))/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c3 = texture2D(rubyTexture, (base-vec2(1.0,0.0))/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c5 = texture2D(rubyTexture, (base+vec2(1.0,0.0))/rubyTextureSize).xyz;\n"
|
||||||
|
""
|
||||||
|
" bool outer = c1 != c7 && c3 != c5;\n"
|
||||||
|
" bool c3c1 = outer && c3==c1;\n"
|
||||||
|
" bool c1c5 = outer && c1==c5;\n"
|
||||||
|
" bool c3c7 = outer && c3==c7;\n"
|
||||||
|
" bool c7c5 = outer && c7==c5;\n"
|
||||||
|
""
|
||||||
|
" vec3 l00 = mix(c4,c3,c3c1?1.0:0.0);\n"
|
||||||
|
" vec3 l01 = mix(c4,c5,c1c5?1.0:0.0);\n"
|
||||||
|
" vec3 l10 = mix(c4,c3,c3c7?1.0:0.0);\n"
|
||||||
|
" vec3 l11 = mix(c4,c5,c7c5?1.0:0.0);\n"
|
||||||
|
""
|
||||||
|
" coord = max(floor(mod(coord, 2.0)), 0.0);\n"
|
||||||
|
" /* 2x2 output:\n"
|
||||||
|
" * |x=0|x=1\n"
|
||||||
|
" * y=0|l00|l01\n"
|
||||||
|
" * y=1|l10|l11\n"
|
||||||
|
" */\n"
|
||||||
|
""
|
||||||
|
" return mix(mix(l00,l01,coord.x), mix(l10,l11,coord.x), coord.y);\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" vec2 coord = v_texCoord;\n"
|
||||||
|
"#if defined(OPENGLNB)\n"
|
||||||
|
" gl_FragColor = getadvmame2xtexel(coord);\n"
|
||||||
|
"#else\n"
|
||||||
|
" coord -= 0.5;\n"
|
||||||
|
" vec3 c0 = getadvmame2xtexel(coord);\n"
|
||||||
|
" vec3 c1 = getadvmame2xtexel(coord+vec2(1.0,0.0));\n"
|
||||||
|
" vec3 c2 = getadvmame2xtexel(coord+vec2(0.0,1.0));\n"
|
||||||
|
" vec3 c3 = getadvmame2xtexel(coord+vec2(1.0));\n"
|
||||||
|
""
|
||||||
|
" coord = fract(max(coord,0.0));\n"
|
||||||
|
" gl_FragColor = vec4(mix(mix(c0,c1,coord.x), mix(c2,c3,coord.x), coord.y), 1.0);\n"
|
||||||
|
"#endif\n"
|
||||||
|
"}\n"
|
||||||
|
"#endif";
|
||||||
|
|
||||||
|
static const char advmame3x_glsl[] =
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"uniform sampler2D rubyTexture;\n"
|
||||||
|
"uniform vec2 rubyInputSize;\n"
|
||||||
|
"uniform vec2 rubyOutputSize;\n"
|
||||||
|
"uniform vec2 rubyTextureSize;\n"
|
||||||
|
""
|
||||||
|
"#if defined(VERTEX)\n"
|
||||||
|
"attribute vec4 a_position;\n"
|
||||||
|
""
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = a_position;\n"
|
||||||
|
" v_texCoord = vec2(a_position.x+1.0,1.0-a_position.y)/2.0*rubyInputSize*3.0;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"#elif defined(FRAGMENT)\n"
|
||||||
|
""
|
||||||
|
"vec3 getadvmame3xtexel(vec2 coord) {\n"
|
||||||
|
" vec2 base = floor(coord/vec2(3.0))+vec2(0.5);\n"
|
||||||
|
" coord = mod(coord, 3.0);\n"
|
||||||
|
" bvec2 l = lessThan(coord, vec2(1.0));\n"
|
||||||
|
" bvec2 h = greaterThanEqual(coord, vec2(2.0));\n"
|
||||||
|
" bvec2 m = equal(l,h);\n"
|
||||||
|
""
|
||||||
|
" vec2 left = vec2(h.x?1.0:-1.0, 0.0);\n"
|
||||||
|
" vec2 up = vec2(0.0, h.y?1.0:-1.0);\n"
|
||||||
|
" if (l==h) left.x = 0.0; // hack for center pixel, will ensure outer==false\n"
|
||||||
|
" if (m.y) {\n"
|
||||||
|
" // swap\n"
|
||||||
|
" left -= up;\n"
|
||||||
|
" up += left;\n"
|
||||||
|
" left = up - left;\n"
|
||||||
|
" }\n"
|
||||||
|
""
|
||||||
|
" vec3 c0 = texture2D(rubyTexture, (base+up+left)/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c1 = texture2D(rubyTexture, (base+up)/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c2 = texture2D(rubyTexture, (base+up-left)/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c3 = texture2D(rubyTexture, (base+left)/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c4 = texture2D(rubyTexture, base/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c5 = texture2D(rubyTexture, (base-left)/rubyTextureSize).xyz;\n"
|
||||||
|
" vec3 c7 = texture2D(rubyTexture, (base-up)/rubyTextureSize).xyz;\n"
|
||||||
|
""
|
||||||
|
" bool outer = c1 != c7 && c3 != c5;\n"
|
||||||
|
" bool check1 = c3==c1 && (!any(m) || c4!=c2);\n"
|
||||||
|
" bool check2 = any(m) && c5==c1 && c4!=c0;\n"
|
||||||
|
""
|
||||||
|
" return (outer && (check1 || check2)) ? c1 : c4;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" vec2 coord = v_texCoord;\n"
|
||||||
|
"#if defined(OPENGLNB)\n"
|
||||||
|
" gl_FragColor = getadvmame3xtexel(coord);\n"
|
||||||
|
"#else\n"
|
||||||
|
" coord -= 0.5;\n"
|
||||||
|
" vec3 c0 = getadvmame3xtexel(coord);\n"
|
||||||
|
" vec3 c1 = getadvmame3xtexel(coord+vec2(1.0,0.0));\n"
|
||||||
|
" vec3 c2 = getadvmame3xtexel(coord+vec2(0.0,1.0));\n"
|
||||||
|
" vec3 c3 = getadvmame3xtexel(coord+vec2(1.0));\n"
|
||||||
|
""
|
||||||
|
" coord = fract(max(coord,0.0));\n"
|
||||||
|
" gl_FragColor = vec4(mix(mix(c0,c1,coord.x), mix(c2,c3,coord.x), coord.y), 1.0);\n"
|
||||||
|
"#endif\n"
|
||||||
|
"}\n"
|
||||||
|
"#endif";
|
||||||
|
|
||||||
|
static const char rgb2x_glsl[] =
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"uniform sampler2D rubyTexture;\n"
|
||||||
|
"uniform vec2 rubyInputSize;\n"
|
||||||
|
"uniform vec2 rubyOutputSize;\n"
|
||||||
|
"uniform vec2 rubyTextureSize;\n"
|
||||||
|
""
|
||||||
|
"#if defined(VERTEX)\n"
|
||||||
|
"attribute vec4 a_position;\n"
|
||||||
|
""
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = a_position;\n"
|
||||||
|
" v_texCoord = vec2(a_position.x+1.0,1.0-a_position.y)/2.0*rubyInputSize * 2.0;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"#elif defined(FRAGMENT)\n"
|
||||||
|
""
|
||||||
|
"vec4 getRGB2xtexel(vec2 coord) {\n"
|
||||||
|
" vec2 mid = vec2(0.5);\n"
|
||||||
|
" vec4 s = texture2D(rubyTexture, (floor(coord/vec2(2.0))+mid)/rubyTextureSize);\n"
|
||||||
|
""
|
||||||
|
" coord = max(floor(mod(coord, 2.0)), 0.0);\n"
|
||||||
|
" /* 2x2 output:\n"
|
||||||
|
" * |x=0|x=1\n"
|
||||||
|
" * y=0| r | g\n"
|
||||||
|
" * y=1| b |rgb\n"
|
||||||
|
" */\n"
|
||||||
|
""
|
||||||
|
" s.r *= 1.0 - abs(coord.x - coord.y);\n"
|
||||||
|
" s.g *= coord.x;\n"
|
||||||
|
" s.b *= coord.y;\n"
|
||||||
|
" return s;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" vec2 coord = v_texCoord;\n"
|
||||||
|
"#if defined(OPENGLNB)\n"
|
||||||
|
" gl_FragColor = getRGB2xtexel(coord);\n"
|
||||||
|
"#else\n"
|
||||||
|
" coord -= 0.5;\n"
|
||||||
|
" vec4 c0 = getRGB2xtexel(coord);\n"
|
||||||
|
" vec4 c1 = getRGB2xtexel(coord+vec2(1.0,0.0));\n"
|
||||||
|
" vec4 c2 = getRGB2xtexel(coord+vec2(0.0,1.0));\n"
|
||||||
|
" vec4 c3 = getRGB2xtexel(coord+vec2(1.0));\n"
|
||||||
|
""
|
||||||
|
" coord = fract(max(coord,0.0));\n"
|
||||||
|
" gl_FragColor = mix(mix(c0,c1,coord.x), mix(c2,c3,coord.x), coord.y);\n"
|
||||||
|
"#endif\n"
|
||||||
|
"}\n"
|
||||||
|
"#endif";
|
||||||
|
|
||||||
|
static const char rgb3x_glsl[] =
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"uniform sampler2D rubyTexture;\n"
|
||||||
|
"uniform vec2 rubyInputSize;\n"
|
||||||
|
"uniform vec2 rubyOutputSize;\n"
|
||||||
|
"uniform vec2 rubyTextureSize;\n"
|
||||||
|
""
|
||||||
|
"#if defined(VERTEX)\n"
|
||||||
|
"attribute vec4 a_position;\n"
|
||||||
|
""
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = a_position;\n"
|
||||||
|
" v_texCoord = vec2(a_position.x+1.0,1.0-a_position.y)/2.0*rubyInputSize * 3.0;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"#elif defined(FRAGMENT)\n"
|
||||||
|
""
|
||||||
|
"vec4 getRGB3xtexel(vec2 coord) {\n"
|
||||||
|
" vec2 mid = vec2(0.5);\n"
|
||||||
|
" vec4 s = texture2D(rubyTexture, (floor(coord/vec2(3.0))+mid)/rubyTextureSize);\n"
|
||||||
|
""
|
||||||
|
" coord = max(floor(mod(coord, 3.0)), 0.0);\n"
|
||||||
|
" /* 3x3 output:\n"
|
||||||
|
" * | l | m | h\n"
|
||||||
|
" * l|rgb| g | b\n"
|
||||||
|
" * m| g | r |rgb\n"
|
||||||
|
" * h|rgb| b | r\n"
|
||||||
|
" */\n"
|
||||||
|
" vec2 l = step(0.0, -coord);\n"
|
||||||
|
" vec2 m = vec2(1.0) - abs(coord-1.0);\n"
|
||||||
|
" vec2 h = step(2.0, coord);\n"
|
||||||
|
""
|
||||||
|
" s.r *= l.x + m.y - 2.0*l.x*m.y + h.x*h.y;\n"
|
||||||
|
" s.g *= l.x + l.y*m.x + h.x*m.y;\n"
|
||||||
|
" s.b *= l.x*l.y + h.x + h.y - 2.0*h.x*h.y;\n"
|
||||||
|
" return s;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" vec2 coord = v_texCoord;\n"
|
||||||
|
"#if defined(OPENGLNB)\n"
|
||||||
|
" gl_FragColor = getRGB3xtexel(coord);\n"
|
||||||
|
"#else\n"
|
||||||
|
" coord -= 0.5;\n"
|
||||||
|
" vec4 c0 = getRGB3xtexel(coord);\n"
|
||||||
|
" vec4 c1 = getRGB3xtexel(coord+vec2(1.0,0.0));\n"
|
||||||
|
" vec4 c2 = getRGB3xtexel(coord+vec2(0.0,1.0));\n"
|
||||||
|
" vec4 c3 = getRGB3xtexel(coord+vec2(1.0));\n"
|
||||||
|
""
|
||||||
|
" coord = fract(max(coord,0.0));\n"
|
||||||
|
" gl_FragColor = mix(mix(c0,c1,coord.x), mix(c2,c3,coord.x), coord.y);\n"
|
||||||
|
"#endif\n"
|
||||||
|
"}\n"
|
||||||
|
"#endif";
|
||||||
|
|
||||||
|
static const char scan2x_glsl[] =
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"uniform vec2 rubyInputSize;\n"
|
||||||
|
"uniform vec2 rubyOutputSize;\n"
|
||||||
|
"uniform vec2 rubyTextureSize;\n"
|
||||||
|
""
|
||||||
|
"#if defined(VERTEX)\n"
|
||||||
|
"attribute vec4 a_position;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = a_position;\n"
|
||||||
|
" v_texCoord = vec2(a_position.x+1.0,1.0-a_position.y)/2.0*rubyInputSize;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"#elif defined(FRAGMENT)\n"
|
||||||
|
"uniform sampler2D rubyTexture;\n"
|
||||||
|
""
|
||||||
|
"void main() {\n"
|
||||||
|
" vec2 prescale = vec2(2.0);\n"
|
||||||
|
" vec2 texel = v_texCoord;\n"
|
||||||
|
" vec2 texel_floored = floor(texel);\n"
|
||||||
|
" vec2 s = fract(texel);\n"
|
||||||
|
" vec2 region_range = vec2(0.5) - vec2(0.5) / prescale;\n"
|
||||||
|
""
|
||||||
|
" vec2 center_dist = s - vec2(0.5);\n"
|
||||||
|
" vec2 f = (center_dist - clamp(center_dist, -region_range, region_range)) * prescale + vec2(0.5);\n"
|
||||||
|
""
|
||||||
|
" vec2 mod_texel = min(texel_floored + f, rubyInputSize-0.5);\n"
|
||||||
|
" vec4 p = texture2D(rubyTexture, mod_texel/rubyTextureSize);\n"
|
||||||
|
" float ss = abs(s.y*2.0-1.0);\n"
|
||||||
|
" p -= p*ss;\n"
|
||||||
|
""
|
||||||
|
" gl_FragColor = p;\n"
|
||||||
|
"}\n"
|
||||||
|
"#endif";
|
||||||
|
|
||||||
|
static const char scan3x_glsl[] =
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"uniform vec2 rubyInputSize;\n"
|
||||||
|
"uniform vec2 rubyOutputSize;\n"
|
||||||
|
"uniform vec2 rubyTextureSize;\n"
|
||||||
|
""
|
||||||
|
"#if defined(VERTEX)\n"
|
||||||
|
"attribute vec4 a_position;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = a_position;\n"
|
||||||
|
" v_texCoord = vec2(a_position.x+1.0,1.0-a_position.y)/2.0*rubyInputSize;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"#elif defined(FRAGMENT)\n"
|
||||||
|
"uniform sampler2D rubyTexture;\n"
|
||||||
|
""
|
||||||
|
"void main() {\n"
|
||||||
|
" vec2 prescale = vec2(3.0);\n"
|
||||||
|
" vec2 texel = v_texCoord;\n"
|
||||||
|
" vec2 texel_floored = floor(texel);\n"
|
||||||
|
" vec2 s = fract(texel);\n"
|
||||||
|
" vec2 region_range = vec2(0.5) - vec2(0.5) / prescale;\n"
|
||||||
|
""
|
||||||
|
" vec2 center_dist = s - 0.5;\n"
|
||||||
|
" vec2 f = (center_dist - clamp(center_dist, -region_range, region_range)) * prescale + vec2(0.5);\n"
|
||||||
|
""
|
||||||
|
" vec2 mod_texel = min(texel_floored + f, rubyInputSize-0.5);\n"
|
||||||
|
" vec4 p = texture2D(rubyTexture, mod_texel/rubyTextureSize);\n"
|
||||||
|
" float m = s.y*6.0;\n"
|
||||||
|
" m -= clamp(m, 2.0, 4.0);\n"
|
||||||
|
" m = abs(m/2.0);\n"
|
||||||
|
" gl_FragColor = p - p*m;\n"
|
||||||
|
"}\n"
|
||||||
|
"#endif";
|
||||||
|
|
||||||
|
static const char tv2x_glsl[] =
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"uniform vec2 rubyInputSize;\n"
|
||||||
|
"uniform vec2 rubyOutputSize;\n"
|
||||||
|
"uniform vec2 rubyTextureSize;\n"
|
||||||
|
""
|
||||||
|
"#if defined(VERTEX)\n"
|
||||||
|
"attribute vec4 a_position;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = a_position;\n"
|
||||||
|
" v_texCoord = vec2(a_position.x+1.0,1.0-a_position.y)/2.0*rubyInputSize;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"#elif defined(FRAGMENT)\n"
|
||||||
|
"uniform sampler2D rubyTexture;\n"
|
||||||
|
""
|
||||||
|
"void main() {\n"
|
||||||
|
" vec2 prescale = vec2(2.0);\n"
|
||||||
|
" vec2 texel = v_texCoord;\n"
|
||||||
|
" vec2 texel_floored = floor(texel);\n"
|
||||||
|
" vec2 s = fract(texel);\n"
|
||||||
|
" vec2 region_range = vec2(0.5) - vec2(0.5) / prescale;\n"
|
||||||
|
""
|
||||||
|
" vec2 center_dist = s - 0.5;\n"
|
||||||
|
" vec2 f = (center_dist - clamp(center_dist, -region_range, region_range)) * prescale + vec2(0.5);\n"
|
||||||
|
""
|
||||||
|
" vec2 mod_texel = min(texel_floored + f, rubyInputSize-0.5);\n"
|
||||||
|
" vec4 p = texture2D(rubyTexture, mod_texel/rubyTextureSize);\n"
|
||||||
|
" float ss = abs(s.y*2.0-1.0);\n"
|
||||||
|
" p -= p*ss*3.0/8.0;\n"
|
||||||
|
""
|
||||||
|
" gl_FragColor = p;\n"
|
||||||
|
"}\n"
|
||||||
|
"#endif";
|
||||||
|
|
||||||
|
static const char tv3x_glsl[] =
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"uniform vec2 rubyInputSize;\n"
|
||||||
|
"uniform vec2 rubyOutputSize;\n"
|
||||||
|
"uniform vec2 rubyTextureSize;\n"
|
||||||
|
""
|
||||||
|
"#if defined(VERTEX)\n"
|
||||||
|
"attribute vec4 a_position;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = a_position;\n"
|
||||||
|
" v_texCoord = vec2(a_position.x+1.0,1.0-a_position.y)/2.0*rubyInputSize;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"#elif defined(FRAGMENT)\n"
|
||||||
|
"uniform sampler2D rubyTexture;\n"
|
||||||
|
""
|
||||||
|
"void main() {\n"
|
||||||
|
" vec2 prescale = vec2(3.0);\n"
|
||||||
|
" vec2 texel = v_texCoord;\n"
|
||||||
|
" vec2 texel_floored = floor(texel);\n"
|
||||||
|
" vec2 s = fract(texel);\n"
|
||||||
|
" vec2 region_range = vec2(0.5) - vec2(0.5) / prescale;\n"
|
||||||
|
""
|
||||||
|
" vec2 center_dist = s - 0.5;\n"
|
||||||
|
" vec2 f = (center_dist - clamp(center_dist, -region_range, region_range)) * prescale + vec2(0.5);\n"
|
||||||
|
""
|
||||||
|
" vec2 mod_texel = min(texel_floored + f, rubyInputSize-0.5);\n"
|
||||||
|
" vec4 p = texture2D(rubyTexture, mod_texel/rubyTextureSize);\n"
|
||||||
|
" float ss = abs(s.y*2.0-1.0);\n"
|
||||||
|
" p -= p*ss*11.0/16.0;\n"
|
||||||
|
""
|
||||||
|
" gl_FragColor = p;\n"
|
||||||
|
"}\n"
|
||||||
|
"#endif";
|
||||||
|
|
||||||
|
static const char sharp_glsl[] =
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"uniform vec2 rubyInputSize;\n"
|
||||||
|
"uniform vec2 rubyOutputSize;\n"
|
||||||
|
"uniform vec2 rubyTextureSize;\n"
|
||||||
|
"varying vec2 prescale; // const set by vertex shader\n"
|
||||||
|
""
|
||||||
|
"#if defined(VERTEX)\n"
|
||||||
|
"attribute vec4 a_position;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = a_position;\n"
|
||||||
|
" v_texCoord = vec2(a_position.x+1.0,1.0-a_position.y)/2.0*rubyInputSize;\n"
|
||||||
|
" prescale = ceil(rubyOutputSize / rubyInputSize);\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"#elif defined(FRAGMENT)\n"
|
||||||
|
"uniform sampler2D rubyTexture;\n"
|
||||||
|
""
|
||||||
|
"void main() {\n"
|
||||||
|
" const vec2 halfp = vec2(0.5);\n"
|
||||||
|
" vec2 texel_floored = floor(v_texCoord);\n"
|
||||||
|
" vec2 s = fract(v_texCoord);\n"
|
||||||
|
" vec2 region_range = halfp - halfp / prescale;\n"
|
||||||
|
""
|
||||||
|
" vec2 center_dist = s - halfp;\n"
|
||||||
|
" vec2 f = (center_dist - clamp(center_dist, -region_range, region_range)) * prescale + halfp;\n"
|
||||||
|
""
|
||||||
|
" vec2 mod_texel = min(texel_floored + f, rubyInputSize-halfp);\n"
|
||||||
|
" gl_FragColor = texture2D(rubyTexture, mod_texel / rubyTextureSize);\n"
|
||||||
|
"}\n"
|
||||||
|
"#endif";
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -174,6 +174,48 @@ typedef enum PROCESS_DPI_AWARENESS {
|
|||||||
#include "sdlmain.h"
|
#include "sdlmain.h"
|
||||||
#include "build_timestamp.h"
|
#include "build_timestamp.h"
|
||||||
|
|
||||||
|
namespace gl2 {
|
||||||
|
extern PFNGLATTACHSHADERPROC glAttachShader;
|
||||||
|
extern PFNGLCOMPILESHADERPROC glCompileShader;
|
||||||
|
extern PFNGLCREATEPROGRAMPROC glCreateProgram;
|
||||||
|
extern PFNGLCREATESHADERPROC glCreateShader;
|
||||||
|
extern PFNGLDELETEPROGRAMPROC glDeleteProgram;
|
||||||
|
extern PFNGLDELETESHADERPROC glDeleteShader;
|
||||||
|
extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
|
||||||
|
extern PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
|
||||||
|
extern PFNGLGETPROGRAMIVPROC glGetProgramiv;
|
||||||
|
extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
|
||||||
|
extern PFNGLGETSHADERIVPROC glGetShaderiv;
|
||||||
|
extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
|
||||||
|
extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
|
||||||
|
extern PFNGLLINKPROGRAMPROC glLinkProgram;
|
||||||
|
extern PFNGLSHADERSOURCEPROC_NP glShaderSource;
|
||||||
|
extern PFNGLUNIFORM2FPROC glUniform2f;
|
||||||
|
extern PFNGLUNIFORM1IPROC glUniform1i;
|
||||||
|
extern PFNGLUSEPROGRAMPROC glUseProgram;
|
||||||
|
extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define glAttachShader gl2::glAttachShader
|
||||||
|
#define glCompileShader gl2::glCompileShader
|
||||||
|
#define glCreateProgram gl2::glCreateProgram
|
||||||
|
#define glCreateShader gl2::glCreateShader
|
||||||
|
#define glDeleteProgram gl2::glDeleteProgram
|
||||||
|
#define glDeleteShader gl2::glDeleteShader
|
||||||
|
#define glEnableVertexAttribArray gl2::glEnableVertexAttribArray
|
||||||
|
#define glGetAttribLocation gl2::glGetAttribLocation
|
||||||
|
#define glGetProgramiv gl2::glGetProgramiv
|
||||||
|
#define glGetProgramInfoLog gl2::glGetProgramInfoLog
|
||||||
|
#define glGetShaderiv gl2::glGetShaderiv
|
||||||
|
#define glGetShaderInfoLog gl2::glGetShaderInfoLog
|
||||||
|
#define glGetUniformLocation gl2::glGetUniformLocation
|
||||||
|
#define glLinkProgram gl2::glLinkProgram
|
||||||
|
#define glShaderSource gl2::glShaderSource
|
||||||
|
#define glUniform2f gl2::glUniform2f
|
||||||
|
#define glUniform1i gl2::glUniform1i
|
||||||
|
#define glUseProgram gl2::glUseProgram
|
||||||
|
#define glVertexAttribPointer gl2::glVertexAttribPointer
|
||||||
|
|
||||||
#ifdef MACOSX
|
#ifdef MACOSX
|
||||||
extern bool has_touch_bar_support;
|
extern bool has_touch_bar_support;
|
||||||
bool osx_detect_nstouchbar(void);
|
bool osx_detect_nstouchbar(void);
|
||||||
@ -2618,6 +2660,19 @@ void DoExtendedKeyboardHook(bool enable) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GFX_SetShader(const char* src) {
|
||||||
|
#if C_OPENGL
|
||||||
|
if (!sdl_opengl.use_shader || src == sdl_opengl.shader_src)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sdl_opengl.shader_src = src;
|
||||||
|
if (sdl_opengl.program_object) {
|
||||||
|
glDeleteProgram(sdl_opengl.program_object);
|
||||||
|
sdl_opengl.program_object = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void GFX_ReleaseMouse(void) {
|
void GFX_ReleaseMouse(void) {
|
||||||
if (sdl.mouse.locked)
|
if (sdl.mouse.locked)
|
||||||
GFX_CaptureMouse();
|
GFX_CaptureMouse();
|
||||||
@ -3262,9 +3317,9 @@ void GFX_EndUpdate(const Bit16u *changedLines) {
|
|||||||
if (d3d && d3d->getForceUpdate());
|
if (d3d && d3d->getForceUpdate());
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (!sdl.updating)
|
if (((sdl.desktop.type != SCREEN_OPENGL) || !RENDER_GetForceUpdate()) && !sdl.updating)
|
||||||
return;
|
return;
|
||||||
|
bool actually_updating = sdl.updating;
|
||||||
sdl.updating = false;
|
sdl.updating = false;
|
||||||
switch (sdl.desktop.type)
|
switch (sdl.desktop.type)
|
||||||
{
|
{
|
||||||
@ -3274,6 +3329,17 @@ void GFX_EndUpdate(const Bit16u *changedLines) {
|
|||||||
|
|
||||||
#if C_OPENGL
|
#if C_OPENGL
|
||||||
case SCREEN_OPENGL:
|
case SCREEN_OPENGL:
|
||||||
|
// Clear drawing area. Some drivers (on Linux) have more than 2 buffers and the screen might
|
||||||
|
// be dirty because of other programs.
|
||||||
|
if (!actually_updating) {
|
||||||
|
/* Don't really update; Just increase the frame counter.
|
||||||
|
* If we tried to update it may have not worked so well
|
||||||
|
* with VSync...
|
||||||
|
* (Think of 60Hz on the host with 70Hz on the client.)
|
||||||
|
*/
|
||||||
|
sdl_opengl.actual_frame_count++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
OUTPUT_OPENGL_EndUpdate(changedLines);
|
OUTPUT_OPENGL_EndUpdate(changedLines);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@ -3834,8 +3900,77 @@ static void GUI_StartUp() {
|
|||||||
sdl.overscan_width=(unsigned int)section->Get_int("overscan");
|
sdl.overscan_width=(unsigned int)section->Get_int("overscan");
|
||||||
// sdl.overscan_color=section->Get_int("overscancolor");
|
// sdl.overscan_color=section->Get_int("overscancolor");
|
||||||
|
|
||||||
|
#if C_OPENGL
|
||||||
|
if (sdl.desktop.want_type == SCREEN_OPENGL) { /* OPENGL is requested */
|
||||||
|
#if defined(C_SDL2)
|
||||||
|
GFX_SetResizeable(true);
|
||||||
|
if (!(sdl.window = GFX_SetSDLWindowMode(640,400, SCREEN_OPENGL)) || !(sdl_opengl.context = SDL_GL_CreateContext(sdl.window))) {
|
||||||
|
#else
|
||||||
|
sdl.surface = SDL_SetVideoMode(640,400,0,SDL_OPENGL);
|
||||||
|
if (sdl.surface == NULL) {
|
||||||
|
#endif
|
||||||
|
LOG_MSG("Could not initialize OpenGL, switching back to surface");
|
||||||
|
sdl.desktop.want_type = SCREEN_SURFACE;
|
||||||
|
} else {
|
||||||
|
sdl_opengl.program_object = 0;
|
||||||
|
glAttachShader = (PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader");
|
||||||
|
glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader");
|
||||||
|
glCreateProgram = (PFNGLCREATEPROGRAMPROC)SDL_GL_GetProcAddress("glCreateProgram");
|
||||||
|
glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader");
|
||||||
|
glDeleteProgram = (PFNGLDELETEPROGRAMPROC)SDL_GL_GetProcAddress("glDeleteProgram");
|
||||||
|
glDeleteShader = (PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader");
|
||||||
|
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)SDL_GL_GetProcAddress("glEnableVertexAttribArray");
|
||||||
|
glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)SDL_GL_GetProcAddress("glGetAttribLocation");
|
||||||
|
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)SDL_GL_GetProcAddress("glGetProgramiv");
|
||||||
|
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)SDL_GL_GetProcAddress("glGetProgramInfoLog");
|
||||||
|
glGetShaderiv = (PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv");
|
||||||
|
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog");
|
||||||
|
glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)SDL_GL_GetProcAddress("glGetUniformLocation");
|
||||||
|
glLinkProgram = (PFNGLLINKPROGRAMPROC)SDL_GL_GetProcAddress("glLinkProgram");
|
||||||
|
glShaderSource = (PFNGLSHADERSOURCEPROC_NP)SDL_GL_GetProcAddress("glShaderSource");
|
||||||
|
glUniform2f = (PFNGLUNIFORM2FPROC)SDL_GL_GetProcAddress("glUniform2f");
|
||||||
|
glUniform1i = (PFNGLUNIFORM1IPROC)SDL_GL_GetProcAddress("glUniform1i");
|
||||||
|
glUseProgram = (PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram");
|
||||||
|
glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)SDL_GL_GetProcAddress("glVertexAttribPointer");
|
||||||
|
sdl_opengl.use_shader = (glAttachShader && glCompileShader && glCreateProgram && glDeleteProgram && glDeleteShader && \
|
||||||
|
glEnableVertexAttribArray && glGetAttribLocation && glGetProgramiv && glGetProgramInfoLog && \
|
||||||
|
glGetShaderiv && glGetShaderInfoLog && glGetUniformLocation && glLinkProgram && glShaderSource && \
|
||||||
|
glUniform2f && glUniform1i && glUseProgram && glVertexAttribPointer);
|
||||||
|
|
||||||
|
sdl_opengl.buffer=0;
|
||||||
|
sdl_opengl.framebuf=0;
|
||||||
|
sdl_opengl.texture=0;
|
||||||
|
sdl_opengl.displaylist=0;
|
||||||
|
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &sdl_opengl.max_texsize);
|
||||||
|
glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)SDL_GL_GetProcAddress("glGenBuffersARB");
|
||||||
|
glBindBufferARB = (PFNGLBINDBUFFERARBPROC)SDL_GL_GetProcAddress("glBindBufferARB");
|
||||||
|
glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)SDL_GL_GetProcAddress("glDeleteBuffersARB");
|
||||||
|
glBufferDataARB = (PFNGLBUFFERDATAARBPROC)SDL_GL_GetProcAddress("glBufferDataARB");
|
||||||
|
glMapBufferARB = (PFNGLMAPBUFFERARBPROC)SDL_GL_GetProcAddress("glMapBufferARB");
|
||||||
|
glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)SDL_GL_GetProcAddress("glUnmapBufferARB");
|
||||||
|
const char * gl_ext = (const char *)glGetString (GL_EXTENSIONS);
|
||||||
|
if(gl_ext && *gl_ext){
|
||||||
|
sdl_opengl.packed_pixel=(strstr(gl_ext,"EXT_packed_pixels") != NULL);
|
||||||
|
sdl_opengl.paletted_texture=(strstr(gl_ext,"EXT_paletted_texture") != NULL);
|
||||||
|
sdl_opengl.pixel_buffer_object=(strstr(gl_ext,"GL_ARB_pixel_buffer_object") != NULL ) &&
|
||||||
|
glGenBuffersARB && glBindBufferARB && glDeleteBuffersARB && glBufferDataARB &&
|
||||||
|
glMapBufferARB && glUnmapBufferARB;
|
||||||
|
} else {
|
||||||
|
sdl_opengl.packed_pixel = false;
|
||||||
|
sdl_opengl.paletted_texture = false;
|
||||||
|
sdl_opengl.pixel_buffer_object = false;
|
||||||
|
}
|
||||||
|
#ifdef DB_DISABLE_DBO
|
||||||
|
sdl_opengl.pixel_buffer_object = false;
|
||||||
|
#endif
|
||||||
|
LOG_MSG("OpenGL extension: pixel_bufer_object %d",sdl_opengl.pixel_buffer_object);
|
||||||
|
}
|
||||||
|
} /* OPENGL is requested end */
|
||||||
|
|
||||||
|
#endif //OPENGL
|
||||||
|
|
||||||
|
/* Initialize screen for first time */
|
||||||
#if defined(C_SDL2)
|
#if defined(C_SDL2)
|
||||||
/* Initialize screen for first time */
|
|
||||||
GFX_SetResizeable(true);
|
GFX_SetResizeable(true);
|
||||||
if (!GFX_SetSDLSurfaceWindow(640,400))
|
if (!GFX_SetSDLSurfaceWindow(640,400))
|
||||||
E_Exit("Could not initialize video: %s",SDL_GetError());
|
E_Exit("Could not initialize video: %s",SDL_GetError());
|
||||||
@ -3847,7 +3982,6 @@ static void GUI_StartUp() {
|
|||||||
if (SDL_BITSPERPIXEL(sdl.desktop.pixelFormat) == 24)
|
if (SDL_BITSPERPIXEL(sdl.desktop.pixelFormat) == 24)
|
||||||
LOG_MSG("SDL: You are running in 24 bpp mode, this will slow down things!");
|
LOG_MSG("SDL: You are running in 24 bpp mode, this will slow down things!");
|
||||||
#else
|
#else
|
||||||
/* Initialize screen for first time */
|
|
||||||
sdl.surface=SDL_SetVideoMode(640,400,0,SDL_RESIZABLE);
|
sdl.surface=SDL_SetVideoMode(640,400,0,SDL_RESIZABLE);
|
||||||
if (sdl.surface == NULL) E_Exit("Could not initialize video: %s",SDL_GetError());
|
if (sdl.surface == NULL) E_Exit("Could not initialize video: %s",SDL_GetError());
|
||||||
sdl.deferred_resize = false;
|
sdl.deferred_resize = false;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "sdlmain.h"
|
#include "sdlmain.h"
|
||||||
|
#include "render.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -27,6 +28,56 @@ PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;
|
|||||||
PFNGLMAPBUFFERARBPROC glMapBufferARB = NULL;
|
PFNGLMAPBUFFERARBPROC glMapBufferARB = NULL;
|
||||||
PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
|
PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
|
||||||
|
|
||||||
|
/* Apple defines these functions in their GL header (as core functions)
|
||||||
|
* so we can't use their names as function pointers. We can't link
|
||||||
|
* directly as some platforms may not have them. So they get their own
|
||||||
|
* namespace here to keep the official names but avoid collisions.
|
||||||
|
*/
|
||||||
|
namespace gl2 {
|
||||||
|
PFNGLATTACHSHADERPROC glAttachShader = NULL;
|
||||||
|
PFNGLCOMPILESHADERPROC glCompileShader = NULL;
|
||||||
|
PFNGLCREATEPROGRAMPROC glCreateProgram = NULL;
|
||||||
|
PFNGLCREATESHADERPROC glCreateShader = NULL;
|
||||||
|
PFNGLDELETEPROGRAMPROC glDeleteProgram = NULL;
|
||||||
|
PFNGLDELETESHADERPROC glDeleteShader = NULL;
|
||||||
|
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = NULL;
|
||||||
|
PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation = NULL;
|
||||||
|
PFNGLGETPROGRAMIVPROC glGetProgramiv = NULL;
|
||||||
|
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = NULL;
|
||||||
|
PFNGLGETSHADERIVPROC glGetShaderiv = NULL;
|
||||||
|
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = NULL;
|
||||||
|
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = NULL;
|
||||||
|
PFNGLLINKPROGRAMPROC glLinkProgram = NULL;
|
||||||
|
PFNGLSHADERSOURCEPROC_NP glShaderSource = NULL;
|
||||||
|
PFNGLUNIFORM2FPROC glUniform2f = NULL;
|
||||||
|
PFNGLUNIFORM1IPROC glUniform1i = NULL;
|
||||||
|
PFNGLUSEPROGRAMPROC glUseProgram = NULL;
|
||||||
|
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "using" is meant to hide identical names declared in outer scope
|
||||||
|
* but is unreliable, so just redefine instead.
|
||||||
|
*/
|
||||||
|
#define glAttachShader gl2::glAttachShader
|
||||||
|
#define glCompileShader gl2::glCompileShader
|
||||||
|
#define glCreateProgram gl2::glCreateProgram
|
||||||
|
#define glCreateShader gl2::glCreateShader
|
||||||
|
#define glDeleteProgram gl2::glDeleteProgram
|
||||||
|
#define glDeleteShader gl2::glDeleteShader
|
||||||
|
#define glEnableVertexAttribArray gl2::glEnableVertexAttribArray
|
||||||
|
#define glGetAttribLocation gl2::glGetAttribLocation
|
||||||
|
#define glGetProgramiv gl2::glGetProgramiv
|
||||||
|
#define glGetProgramInfoLog gl2::glGetProgramInfoLog
|
||||||
|
#define glGetShaderiv gl2::glGetShaderiv
|
||||||
|
#define glGetShaderInfoLog gl2::glGetShaderInfoLog
|
||||||
|
#define glGetUniformLocation gl2::glGetUniformLocation
|
||||||
|
#define glLinkProgram gl2::glLinkProgram
|
||||||
|
#define glShaderSource gl2::glShaderSource
|
||||||
|
#define glUniform2f gl2::glUniform2f
|
||||||
|
#define glUniform1i gl2::glUniform1i
|
||||||
|
#define glUseProgram gl2::glUseProgram
|
||||||
|
#define glVertexAttribPointer gl2::glVertexAttribPointer
|
||||||
|
|
||||||
#if C_OPENGL && DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW
|
#if C_OPENGL && DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW
|
||||||
extern unsigned int SDLDrawGenFontTextureUnitPerRow;
|
extern unsigned int SDLDrawGenFontTextureUnitPerRow;
|
||||||
extern unsigned int SDLDrawGenFontTextureRows;
|
extern unsigned int SDLDrawGenFontTextureRows;
|
||||||
@ -221,6 +272,76 @@ Bitu OUTPUT_OPENGL_GetBestMode(Bitu flags)
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create a GLSL shader object, load the shader source, and compile the shader. */
|
||||||
|
static GLuint BuildShader ( GLenum type, const char *shaderSrc ) {
|
||||||
|
GLuint shader;
|
||||||
|
GLint compiled;
|
||||||
|
const char* src_strings[2];
|
||||||
|
std::string top;
|
||||||
|
|
||||||
|
// look for "#version" because it has to occur first
|
||||||
|
const char *ver = strstr(shaderSrc, "#version ");
|
||||||
|
if (ver) {
|
||||||
|
const char *endline = strchr(ver+9, '\n');
|
||||||
|
if (endline) {
|
||||||
|
top.assign(shaderSrc, endline-shaderSrc+1);
|
||||||
|
shaderSrc = endline+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
top += (type==GL_VERTEX_SHADER) ? "#define VERTEX 1\n":"#define FRAGMENT 1\n";
|
||||||
|
if (!sdl_opengl.bilinear)
|
||||||
|
top += "#define OPENGLNB 1\n";
|
||||||
|
|
||||||
|
src_strings[0] = top.c_str();
|
||||||
|
src_strings[1] = shaderSrc;
|
||||||
|
|
||||||
|
// Create the shader object
|
||||||
|
shader = glCreateShader(type);
|
||||||
|
if (shader == 0) return 0;
|
||||||
|
|
||||||
|
// Load the shader source
|
||||||
|
glShaderSource(shader, 2, src_strings, NULL);
|
||||||
|
|
||||||
|
// Compile the shader
|
||||||
|
glCompileShader(shader);
|
||||||
|
|
||||||
|
// Check the compile status
|
||||||
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
|
||||||
|
|
||||||
|
if (!compiled) {
|
||||||
|
char* infoLog = NULL;
|
||||||
|
GLint infoLen = 0;
|
||||||
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
|
||||||
|
|
||||||
|
if (infoLen>1) infoLog = (char*)malloc(infoLen);
|
||||||
|
if (infoLog) {
|
||||||
|
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
|
||||||
|
LOG_MSG("Error compiling shader: %s", infoLog);
|
||||||
|
free(infoLog);
|
||||||
|
} else LOG_MSG("Error getting shader compilation log");
|
||||||
|
|
||||||
|
glDeleteShader(shader);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool LoadGLShaders(const char *src, GLuint *vertex, GLuint *fragment) {
|
||||||
|
GLuint s = BuildShader(GL_VERTEX_SHADER, src);
|
||||||
|
if (s) {
|
||||||
|
*vertex = s;
|
||||||
|
s = BuildShader(GL_FRAGMENT_SHADER, src);
|
||||||
|
if (s) {
|
||||||
|
*fragment = s;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
glDeleteShader(*vertex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Bitu OUTPUT_OPENGL_SetSize()
|
Bitu OUTPUT_OPENGL_SetSize()
|
||||||
{
|
{
|
||||||
Bitu retFlags = 0;
|
Bitu retFlags = 0;
|
||||||
@ -256,10 +377,11 @@ Bitu OUTPUT_OPENGL_SetSize()
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// try 32 bits first then 16
|
||||||
#if defined(C_SDL2)
|
#if defined(C_SDL2)
|
||||||
SetupSurfaceScaledOpenGL(SDL_WINDOW_RESIZABLE, 0);
|
if (SetupSurfaceScaledOpenGL(SDL_WINDOW_RESIZABLE,32)==NULL) SetupSurfaceScaledOpenGL(SDL_WINDOW_RESIZABLE,16);
|
||||||
#else
|
#else
|
||||||
SetupSurfaceScaledOpenGL(SDL_RESIZABLE, 0);
|
if (SetupSurfaceScaledOpenGL(SDL_RESIZABLE,32)==NULL) SetupSurfaceScaledOpenGL(SDL_RESIZABLE,16);
|
||||||
#endif
|
#endif
|
||||||
if (!sdl.surface || sdl.surface->format->BitsPerPixel < 15)
|
if (!sdl.surface || sdl.surface->format->BitsPerPixel < 15)
|
||||||
{
|
{
|
||||||
@ -290,6 +412,100 @@ Bitu OUTPUT_OPENGL_SetSize()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sdl_opengl.use_shader) {
|
||||||
|
GLuint prog=0;
|
||||||
|
// reset error
|
||||||
|
glGetError();
|
||||||
|
glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&prog);
|
||||||
|
// if there was an error this context doesn't support shaders
|
||||||
|
if (glGetError()==GL_NO_ERROR && (sdl_opengl.program_object==0 || prog!=sdl_opengl.program_object)) {
|
||||||
|
// check if existing program is valid
|
||||||
|
if (sdl_opengl.program_object) {
|
||||||
|
glUseProgram(sdl_opengl.program_object);
|
||||||
|
if (glGetError() != GL_NO_ERROR) {
|
||||||
|
// program is not usable (probably new context), purge it
|
||||||
|
glDeleteProgram(sdl_opengl.program_object);
|
||||||
|
sdl_opengl.program_object = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// does program need to be rebuilt?
|
||||||
|
if (sdl_opengl.program_object == 0) {
|
||||||
|
GLuint vertexShader, fragmentShader;
|
||||||
|
const char *src = sdl_opengl.shader_src;
|
||||||
|
if (src && !LoadGLShaders(src, &vertexShader, &fragmentShader)) {
|
||||||
|
LOG_MSG("SDL:OPENGL:Failed to compile shader, falling back to default");
|
||||||
|
src = NULL;
|
||||||
|
}
|
||||||
|
if (src == NULL && !LoadGLShaders(shader_src_default, &vertexShader, &fragmentShader)) {
|
||||||
|
LOG_MSG("SDL:OPENGL:Failed to compile default shader!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdl_opengl.program_object = glCreateProgram();
|
||||||
|
if (!sdl_opengl.program_object) {
|
||||||
|
glDeleteShader(vertexShader);
|
||||||
|
glDeleteShader(fragmentShader);
|
||||||
|
LOG_MSG("SDL:OPENGL:Can't create program object, falling back to surface");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
glAttachShader(sdl_opengl.program_object, vertexShader);
|
||||||
|
glAttachShader(sdl_opengl.program_object, fragmentShader);
|
||||||
|
// Link the program
|
||||||
|
glLinkProgram(sdl_opengl.program_object);
|
||||||
|
// Even if we *are* successful, we may delete the shader objects
|
||||||
|
glDeleteShader(vertexShader);
|
||||||
|
glDeleteShader(fragmentShader);
|
||||||
|
|
||||||
|
// Check the link status
|
||||||
|
GLint isProgramLinked;
|
||||||
|
glGetProgramiv(sdl_opengl.program_object, GL_LINK_STATUS, &isProgramLinked);
|
||||||
|
if (!isProgramLinked) {
|
||||||
|
char * infoLog = NULL;
|
||||||
|
GLint infoLen = 0;
|
||||||
|
|
||||||
|
glGetProgramiv(sdl_opengl.program_object, GL_INFO_LOG_LENGTH, &infoLen);
|
||||||
|
if (infoLen>1) infoLog = (char*)malloc(infoLen);
|
||||||
|
if (infoLog) {
|
||||||
|
glGetProgramInfoLog(sdl_opengl.program_object, infoLen, NULL, infoLog);
|
||||||
|
LOG_MSG("SDL:OPENGL:Error linking program:\n %s", infoLog);
|
||||||
|
free(infoLog);
|
||||||
|
} else LOG_MSG("SDL:OPENGL:Failed to retrieve program link log");
|
||||||
|
|
||||||
|
glDeleteProgram(sdl_opengl.program_object);
|
||||||
|
sdl_opengl.program_object = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
glUseProgram(sdl_opengl.program_object);
|
||||||
|
|
||||||
|
GLint u = glGetAttribLocation(sdl_opengl.program_object, "a_position");
|
||||||
|
// upper left
|
||||||
|
sdl_opengl.vertex_data[0] = -1.0f;
|
||||||
|
sdl_opengl.vertex_data[1] = 1.0f;
|
||||||
|
// lower left
|
||||||
|
sdl_opengl.vertex_data[2] = -1.0f;
|
||||||
|
sdl_opengl.vertex_data[3] = -3.0f;
|
||||||
|
// upper right
|
||||||
|
sdl_opengl.vertex_data[4] = 3.0f;
|
||||||
|
sdl_opengl.vertex_data[5] = 1.0f;
|
||||||
|
// Load the vertex positions
|
||||||
|
glVertexAttribPointer(u, 2, GL_FLOAT, GL_FALSE, 0, sdl_opengl.vertex_data);
|
||||||
|
glEnableVertexAttribArray(u);
|
||||||
|
|
||||||
|
u = glGetUniformLocation(sdl_opengl.program_object, "rubyTexture");
|
||||||
|
glUniform1i(u, 0);
|
||||||
|
|
||||||
|
sdl_opengl.ruby.texture_size = glGetUniformLocation(sdl_opengl.program_object, "rubyTextureSize");
|
||||||
|
sdl_opengl.ruby.input_size = glGetUniformLocation(sdl_opengl.program_object, "rubyInputSize");
|
||||||
|
sdl_opengl.ruby.output_size = glGetUniformLocation(sdl_opengl.program_object, "rubyOutputSize");
|
||||||
|
sdl_opengl.ruby.frame_count = glGetUniformLocation(sdl_opengl.program_object, "rubyFrameCount");
|
||||||
|
// Don't force updating unless a shader depends on frame_count
|
||||||
|
RENDER_SetForceUpdate(sdl_opengl.ruby.frame_count != (GLint)-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Create the texture and display list */
|
/* Create the texture and display list */
|
||||||
if (sdl_opengl.pixel_buffer_object)
|
if (sdl_opengl.pixel_buffer_object)
|
||||||
{
|
{
|
||||||
@ -341,7 +557,7 @@ Bitu OUTPUT_OPENGL_SetSize()
|
|||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
// SDL_GL_SwapBuffers();
|
// SDL_GL_SwapBuffers();
|
||||||
// glClear(GL_COLOR_BUFFER_BIT);
|
// glClear(GL_COLOR_BUFFER_BIT);
|
||||||
glShadeModel(GL_FLAT);
|
//glShadeModel(GL_FLAT);
|
||||||
glBlendFunc(GL_ONE, GL_ZERO);
|
glBlendFunc(GL_ONE, GL_ZERO);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glDisable(GL_LIGHTING);
|
glDisable(GL_LIGHTING);
|
||||||
@ -353,36 +569,45 @@ Bitu OUTPUT_OPENGL_SetSize()
|
|||||||
glDisable(GL_STENCIL_TEST);
|
glDisable(GL_STENCIL_TEST);
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
if (sdl_opengl.program_object) {
|
||||||
glLoadIdentity();
|
// Set shader variables
|
||||||
|
glUniform2f(sdl_opengl.ruby.texture_size, (float)texsize, (float)texsize);
|
||||||
|
glUniform2f(sdl_opengl.ruby.input_size, (float)adjTexWidth, (float)adjTexHeight);
|
||||||
|
glUniform2f(sdl_opengl.ruby.output_size, sdl.clip.w, sdl.clip.h);
|
||||||
|
// The following uniform is *not* set right now
|
||||||
|
sdl_opengl.actual_frame_count = 0;
|
||||||
|
} else {
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glOrtho(0, sdl.surface->w, sdl.surface->h, 0, -1, 1);
|
glOrtho(0, sdl.surface->w, sdl.surface->h, 0, -1, 1);
|
||||||
|
|
||||||
glMatrixMode(GL_TEXTURE);
|
glMatrixMode(GL_TEXTURE);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glScaled(1.0 / texsize, 1.0 / texsize, 1.0);
|
glScaled(1.0 / texsize, 1.0 / texsize, 1.0);
|
||||||
|
|
||||||
// if (glIsList(sdl_opengl.displaylist))
|
// if (glIsList(sdl_opengl.displaylist))
|
||||||
// glDeleteLists(sdl_opengl.displaylist, 1);
|
// glDeleteLists(sdl_opengl.displaylist, 1);
|
||||||
// sdl_opengl.displaylist = glGenLists(1);
|
// sdl_opengl.displaylist = glGenLists(1);
|
||||||
sdl_opengl.displaylist = 1;
|
sdl_opengl.displaylist = 1;
|
||||||
|
|
||||||
glNewList(sdl_opengl.displaylist, GL_COMPILE);
|
glNewList(sdl_opengl.displaylist, GL_COMPILE);
|
||||||
glBindTexture(GL_TEXTURE_2D, sdl_opengl.texture);
|
glBindTexture(GL_TEXTURE_2D, sdl_opengl.texture);
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
|
|
||||||
glTexCoord2i(0, 0); glVertex2i((GLint)sdl.clip.x, (GLint)sdl.clip.y); // lower left
|
glTexCoord2i(0, 0); glVertex2i((GLint)sdl.clip.x, (GLint)sdl.clip.y); // lower left
|
||||||
glTexCoord2i((GLint)adjTexWidth, 0); glVertex2i((GLint)sdl.clip.x + (GLint)sdl.clip.w, (GLint)sdl.clip.y); // lower right
|
glTexCoord2i((GLint)adjTexWidth, 0); glVertex2i((GLint)sdl.clip.x + (GLint)sdl.clip.w, (GLint)sdl.clip.y); // lower right
|
||||||
glTexCoord2i((GLint)adjTexWidth, (GLint)adjTexHeight); glVertex2i((GLint)sdl.clip.x + (GLint)sdl.clip.w, (GLint)sdl.clip.y + (GLint)sdl.clip.h); // upper right
|
glTexCoord2i((GLint)adjTexWidth, (GLint)adjTexHeight); glVertex2i((GLint)sdl.clip.x + (GLint)sdl.clip.w, (GLint)sdl.clip.y + (GLint)sdl.clip.h); // upper right
|
||||||
glTexCoord2i(0, (GLint)adjTexHeight); glVertex2i((GLint)sdl.clip.x, (GLint)sdl.clip.y + (GLint)sdl.clip.h); // upper left
|
glTexCoord2i(0, (GLint)adjTexHeight); glVertex2i((GLint)sdl.clip.x, (GLint)sdl.clip.y + (GLint)sdl.clip.h); // upper left
|
||||||
|
|
||||||
glEnd();
|
glEnd();
|
||||||
glEndList();
|
glEndList();
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
#if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW
|
#if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW
|
||||||
void GFX_DrawSDLMenu(DOSBoxMenu &menu, DOSBoxMenu::displaylist &dl);
|
void GFX_DrawSDLMenu(DOSBoxMenu &menu, DOSBoxMenu::displaylist &dl);
|
||||||
@ -591,8 +816,8 @@ void OUTPUT_OPENGL_EndUpdate(const Bit16u *changedLines)
|
|||||||
#endif
|
#endif
|
||||||
(void*)0);
|
(void*)0);
|
||||||
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
|
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
|
||||||
glCallList(sdl_opengl.displaylist);
|
//glCallList(sdl_opengl.displaylist);
|
||||||
SDL_GL_SwapBuffers();
|
//SDL_GL_SwapBuffers();
|
||||||
}
|
}
|
||||||
else if (changedLines)
|
else if (changedLines)
|
||||||
{
|
{
|
||||||
@ -625,6 +850,12 @@ void OUTPUT_OPENGL_EndUpdate(const Bit16u *changedLines)
|
|||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
return;
|
||||||
|
if (sdl_opengl.program_object) {
|
||||||
|
glUniform1i(sdl_opengl.ruby.frame_count, sdl_opengl.actual_frame_count++);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
} else
|
||||||
glCallList(sdl_opengl.displaylist);
|
glCallList(sdl_opengl.displaylist);
|
||||||
|
|
||||||
#if 0 /* DEBUG Prove to me that you're drawing the damn texture */
|
#if 0 /* DEBUG Prove to me that you're drawing the damn texture */
|
||||||
@ -659,7 +890,6 @@ void OUTPUT_OPENGL_EndUpdate(const Bit16u *changedLines)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
SDL_GL_SwapBuffers();
|
SDL_GL_SwapBuffers();
|
||||||
}
|
|
||||||
|
|
||||||
if (!menu.hidecycles && !sdl.desktop.fullscreen) frames++;
|
if (!menu.hidecycles && !sdl.desktop.fullscreen) frames++;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,32 @@ extern PFNGLBUFFERDATAARBPROC glBufferDataARB;
|
|||||||
extern PFNGLMAPBUFFERARBPROC glMapBufferARB;
|
extern PFNGLMAPBUFFERARBPROC glMapBufferARB;
|
||||||
extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
|
extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
|
||||||
|
|
||||||
|
|
||||||
|
/* Don't guard these with GL_VERSION_2_0 - Apple defines it but not these typedefs.
|
||||||
|
* If they're already defined they should match these definitions, so no conflicts.
|
||||||
|
*/
|
||||||
|
typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
|
||||||
|
typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
|
||||||
|
typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
|
||||||
|
typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
|
||||||
|
typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
|
||||||
|
typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
|
||||||
|
typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||||
|
typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
|
||||||
|
typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
|
||||||
|
typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||||
|
typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
|
||||||
|
typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||||
|
typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
|
||||||
|
typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
|
||||||
|
//Change to NP, as Khronos changes include guard :(
|
||||||
|
typedef void (APIENTRYP PFNGLSHADERSOURCEPROC_NP) (GLuint shader, GLsizei count, const GLchar **string, const GLint *length);
|
||||||
|
typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
|
||||||
|
typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
|
||||||
|
typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
|
||||||
|
typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
|
||||||
|
|
||||||
|
|
||||||
#if defined(C_SDL2)
|
#if defined(C_SDL2)
|
||||||
# include <SDL_video.h>
|
# include <SDL_video.h>
|
||||||
#endif
|
#endif
|
||||||
@ -56,11 +82,39 @@ struct SDL_OpenGL {
|
|||||||
bool pixel_buffer_object;
|
bool pixel_buffer_object;
|
||||||
int menudraw_countdown;
|
int menudraw_countdown;
|
||||||
int clear_countdown;
|
int clear_countdown;
|
||||||
|
bool use_shader;
|
||||||
|
GLuint program_object;
|
||||||
|
const char *shader_src;
|
||||||
|
struct {
|
||||||
|
GLint texture_size;
|
||||||
|
GLint input_size;
|
||||||
|
GLint output_size;
|
||||||
|
GLint frame_count;
|
||||||
|
} ruby;
|
||||||
|
GLuint actual_frame_count;
|
||||||
|
GLfloat vertex_data[2*3];
|
||||||
#if defined(C_SDL2)
|
#if defined(C_SDL2)
|
||||||
SDL_GLContext context;
|
SDL_GLContext context;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static char const shader_src_default[] =
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"#if defined(VERTEX)\n"
|
||||||
|
"uniform vec2 rubyTextureSize;\n"
|
||||||
|
"uniform vec2 rubyInputSize;\n"
|
||||||
|
"attribute vec4 a_position;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = a_position;\n"
|
||||||
|
" v_texCoord = vec2(a_position.x+1.0,1.0-a_position.y)/2.0*rubyInputSize/rubyTextureSize;\n"
|
||||||
|
"}\n"
|
||||||
|
"#elif defined(FRAGMENT)\n"
|
||||||
|
"uniform sampler2D rubyTexture;\n\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_FragColor = texture2D(rubyTexture, v_texCoord);\n"
|
||||||
|
"}\n"
|
||||||
|
"#endif\n";
|
||||||
|
|
||||||
extern SDL_OpenGL sdl_opengl;
|
extern SDL_OpenGL sdl_opengl;
|
||||||
|
|
||||||
// output API
|
// output API
|
||||||
|
Loading…
x
Reference in New Issue
Block a user