osd: Fixed various OpenGL issues - fixes -nowaitvsync not working on Windows with -video opengl.

Turned shader tool/shader manager into a class so multiple
screens/windows don't nuke each other.

Don't try to get supported extensions without a valid GL context with
Windows OSD.

Use per-context GL function pointers for shader manager and for all
functions when using GL dispatch.  Windows doesn't guarantee extension
functions from one context are valid for another.
This commit is contained in:
Vas Crabb 2023-02-25 08:32:03 +11:00
parent 247e1e1fbb
commit 3e27dd60a2
8 changed files with 1111 additions and 944 deletions

View File

@ -1,13 +1,17 @@
// license:BSD-3-Clause
// copyright-holders:Sven Gothel
#include <cstdio> /* snprintf */
#include <cstdlib> /* malloc */
#include "osdcomm.h"
#include "osd_opengl.h"
#include "gl_shader_mgr.h"
#include "gl_shader_tool.h"
#include "osdcomm.h"
#include "util/strformat.h"
#include <algorithm>
#include <iterator>
namespace {
#define GLSL_VERTEX_SHADER_INT_NUMBER 1 // general
#define GLSL_VERTEX_SHADER_MAX_NUMBER 2 // general + custom
@ -15,16 +19,16 @@
#ifdef GLSL_SOURCE_ON_DISK
static char const *const glsl_mamebm_vsh_files [GLSL_VERTEX_SHADER_INT_NUMBER] =
static char const *const glsl_mamebm_vsh_files[GLSL_VERTEX_SHADER_INT_NUMBER] =
{
"/tmp/glsl_general.vsh" // general
"/tmp/glsl_general.vsh" // general
};
static char const *const glsl_mamebm_fsh_files [GLSL_SHADER_FEAT_INT_NUMBER] =
static char const *const glsl_mamebm_fsh_files[glsl_shader_info::FEAT_INT_NUMBER] =
{
"/tmp/glsl_plain_rgb32_dir.fsh", // rgb32 dir plain
"/tmp/glsl_bilinear_rgb32_dir.fsh", // rgb32 dir bilinear
"/tmp/glsl_bicubic_rgb32_dir.fsh", // rgb32 dir bicubic
"/tmp/glsl_plain_rgb32_dir.fsh", // rgb32 dir plain
"/tmp/glsl_bilinear_rgb32_dir.fsh", // rgb32 dir bilinear
"/tmp/glsl_bicubic_rgb32_dir.fsh", // rgb32 dir bicubic
};
#else // GLSL_SOURCE_ON_DISK
@ -35,207 +39,239 @@ static char const *const glsl_mamebm_fsh_files [GLSL_SHADER_FEAT_INT_NUMBER] =
#include "shader/glsl_bilinear_rgb32_dir.fsh.c"
#include "shader/glsl_bicubic_rgb32_dir.fsh.c"
static char const *const glsl_mamebm_vsh_sources [GLSL_VERTEX_SHADER_INT_NUMBER] =
static char const *const glsl_mamebm_vsh_sources[GLSL_VERTEX_SHADER_INT_NUMBER] =
{
glsl_general_vsh_src // general
glsl_general_vsh_src // general
};
static char const *const glsl_mamebm_fsh_sources [GLSL_SHADER_FEAT_INT_NUMBER] =
static char const *const glsl_mamebm_fsh_sources[glsl_shader_info::FEAT_INT_NUMBER] =
{
glsl_plain_rgb32_dir_fsh_src, // rgb32 dir plain
glsl_bilinear_rgb32_dir_fsh_src, // rgb32 dir bilinear
glsl_bicubic_rgb32_dir_fsh_src, // rgb32 dir bicubic
glsl_plain_rgb32_dir_fsh_src, // rgb32 dir plain
glsl_bilinear_rgb32_dir_fsh_src, // rgb32 dir bilinear
glsl_bicubic_rgb32_dir_fsh_src, // rgb32 dir bicubic
};
#endif // GLSL_SOURCE_ON_DISK
static char const *const glsl_mamebm_filter_names [GLSL_SHADER_FEAT_MAX_NUMBER] =
{
"plain",
"bilinear",
"bicubic",
"custom"
};
static GLhandleARB glsl_mamebm_programs [GLSL_SHADER_FEAT_MAX_NUMBER+9] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* rgb32 dir: plain, bilinear, bicubic, custom0-9, .. */
};
static char const *const glsl_mamebm_filter_names[glsl_shader_info::FEAT_MAX_NUMBER]{
"plain",
"bilinear",
"bicubic",
"custom" };
/**
* fragment shader -> vertex shader mapping
*/
static int glsl_mamebm_fsh2vsh[GLSL_SHADER_FEAT_MAX_NUMBER] =
static const int glsl_mamebm_fsh2vsh[glsl_shader_info::FEAT_MAX_NUMBER] =
{
0, // plain -> general
0, // bilinear -> general
0, // bicubic -> general
1, // custom -> custom
1, // custom -> custom
};
static GLhandleARB glsl_mamebm_vsh_shader[GLSL_VERTEX_SHADER_MAX_NUMBER+9] =
class glsl_shader_impl : public glsl_shader_info
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}; /* general, custom0-9 */
static GLhandleARB glsl_mamebm_fsh_shader [GLSL_SHADER_FEAT_MAX_NUMBER+9] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* rgb32 dir: plain, bilinear, bicubic, custom0-9 */
};
static GLhandleARB glsl_scrn_programs [10] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* rgb32: custom0-9, .. */
};
static GLhandleARB glsl_scrn_vsh_shader[10] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}; /* custom0-9 */
static GLhandleARB glsl_scrn_fsh_shader [10] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}; /* rgb32: custom0-9 */
const char * glsl_shader_get_filter_name_mamebm(int glslShaderFeature)
{
if ( !(0 <= glslShaderFeature && glslShaderFeature < GLSL_SHADER_FEAT_MAX_NUMBER) )
return "illegal shader feature";
return glsl_mamebm_filter_names[glslShaderFeature];
}
GLhandleARB glsl_shader_get_program_mamebm(int glslShaderFeature, int idx)
{
if ( !(0 <= glslShaderFeature && glslShaderFeature < GLSL_SHADER_FEAT_MAX_NUMBER) )
return 0;
return glsl_mamebm_programs[glslShaderFeature+idx];
}
GLhandleARB glsl_shader_get_program_scrn(int idx)
{
if ( !(0 <= idx && idx < 10) )
return 0;
return glsl_scrn_programs[idx];
}
glsl_shader_info *glsl_shader_init(osd_gl_context *gl_ctx)
{
int i,j, err;
err = gl_shader_loadExtention(gl_ctx);
if(err) return nullptr;
for (i=0; !err && i<GLSL_VERTEX_SHADER_INT_NUMBER; i++)
public:
glsl_shader_impl(
#if defined(USE_DISPATCH_GL)
osd_gl_dispatch *gld
#endif
)
#if defined(USE_DISPATCH_GL)
: glsl_shader_info(gld)
#endif
{
#ifdef GLSL_SOURCE_ON_DISK
if(glsl_mamebm_vsh_files[i])
err = gl_compile_shader_file ( &glsl_mamebm_vsh_shader[i], GL_VERTEX_SHADER_ARB,
glsl_mamebm_vsh_files[i], 0);
#else
if(glsl_mamebm_vsh_sources[i])
err = gl_compile_shader_source( &glsl_mamebm_vsh_shader[i], GL_VERTEX_SHADER_ARB,
glsl_mamebm_vsh_sources[i], 0);
#endif
std::fill(std::begin(mamebm_programs), std::end(mamebm_programs), 0);
std::fill(std::begin(mamebm_vsh_shader), std::end(mamebm_vsh_shader), 0);
std::fill(std::begin(mamebm_fsh_shader), std::end(mamebm_fsh_shader), 0);
std::fill(std::begin(scrn_programs), std::end(scrn_programs), 0);
std::fill(std::begin(scrn_vsh_shader), std::end(scrn_vsh_shader), 0);
std::fill(std::begin(scrn_fsh_shader), std::end(scrn_fsh_shader), 0);
}
if(err) return nullptr;
for (j=0; !err && j<GLSL_SHADER_FEAT_INT_NUMBER; j++)
bool initalize(osd_gl_context &gl_ctx)
{
#ifdef GLSL_SOURCE_ON_DISK
if(glsl_mamebm_fsh_files[j])
err = gl_compile_shader_files (&glsl_mamebm_programs[j],
&glsl_mamebm_vsh_shader[glsl_mamebm_fsh2vsh[j]],
&glsl_mamebm_fsh_shader[j],
nullptr /*precompiled*/, glsl_mamebm_fsh_files[j], 0);
#else
if(glsl_mamebm_fsh_sources[j])
err = gl_compile_shader_sources(&glsl_mamebm_programs[j],
&glsl_mamebm_vsh_shader[glsl_mamebm_fsh2vsh[j]],
&glsl_mamebm_fsh_shader[j],
nullptr /*precompiled*/, glsl_mamebm_fsh_sources[j]);
#endif
}
if (err) return nullptr;
return new glsl_shader_info{ 0 };
}
if (!load_extension(gl_ctx))
return false;
int glsl_shader_free(glsl_shader_info *shinfo)
{
pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
int err = 0;
for (int i = 0; !err && (i < GLSL_VERTEX_SHADER_INT_NUMBER); i++)
{
#ifdef GLSL_SOURCE_ON_DISK
if (glsl_mamebm_vsh_files[i])
err = compile_file(
&mamebm_vsh_shader[i],
GL_VERTEX_SHADER_ARB,
glsl_mamebm_vsh_files[i],
false);
#else
if (glsl_mamebm_vsh_sources[i])
err = compile_source(
&mamebm_vsh_shader[i],
GL_VERTEX_SHADER_ARB,
glsl_mamebm_vsh_sources[i],
false);
#endif
}
if (err)
return false;
for (int j = 0; !err && (j < FEAT_INT_NUMBER); j++)
{
#ifdef GLSL_SOURCE_ON_DISK
if (glsl_mamebm_fsh_files[j])
err = compile_files(
&mamebm_programs[j],
&mamebm_vsh_shader[glsl_mamebm_fsh2vsh[j]],
&mamebm_fsh_shader[j],
nullptr, // precompiled
glsl_mamebm_fsh_files[j],
false);
#else
if (glsl_mamebm_fsh_sources[j])
err = compile_sources(
&mamebm_programs[j],
&mamebm_vsh_shader[glsl_mamebm_fsh2vsh[j]],
&mamebm_fsh_shader[j],
nullptr, // precompiled
glsl_mamebm_fsh_sources[j]);
#endif
}
if (err)
return false;
return true;
}
virtual ~glsl_shader_impl()
{
pfn_glUseProgramObjectARB(0);
glFinish();
for (int i=0; i<GLSL_VERTEX_SHADER_MAX_NUMBER+9; i++)
{
if ( glsl_mamebm_vsh_shader[i] )
(void) gl_delete_shader(nullptr, &glsl_mamebm_vsh_shader[i], nullptr);
for (int i = 0; i < GLSL_VERTEX_SHADER_MAX_NUMBER + 9; i++)
{
if (mamebm_vsh_shader[i])
delete_shader(nullptr, &mamebm_vsh_shader[i], nullptr);
}
for (int j = 0; j < FEAT_MAX_NUMBER + 9; j++)
{
if (mamebm_fsh_shader[j])
delete_shader(nullptr, nullptr, &mamebm_fsh_shader[j]);
}
for (int j = 0; j < FEAT_MAX_NUMBER + 9; j++)
{
if (mamebm_programs[j])
delete_shader(&mamebm_programs[j], nullptr, nullptr);
}
for (int i = 0; i < 10; i++)
{
if (scrn_vsh_shader[i])
delete_shader(nullptr, &scrn_vsh_shader[i], nullptr);
if (scrn_fsh_shader[i])
delete_shader(nullptr, nullptr, &scrn_fsh_shader[i]);
if (scrn_programs[i])
delete_shader(&scrn_programs[i], nullptr, nullptr);
}
}
for (int j=0; j<GLSL_SHADER_FEAT_MAX_NUMBER+9; j++)
virtual const char *get_filter_name_mamebm(int glslShaderFeature) override
{
if ( glsl_mamebm_fsh_shader[j] )
(void) gl_delete_shader(nullptr, nullptr, &glsl_mamebm_fsh_shader[j]);
if ((0 > glslShaderFeature) || (glslShaderFeature >= FEAT_MAX_NUMBER))
return "illegal shader feature";
return glsl_mamebm_filter_names[glslShaderFeature];
}
for (int j=0; j<GLSL_SHADER_FEAT_MAX_NUMBER+9; j++)
virtual GLhandleARB get_program_mamebm(int glslShaderFeature, int idx) override
{
if ( glsl_mamebm_programs[j] )
(void) gl_delete_shader( &glsl_mamebm_programs[j], nullptr, nullptr);
if ((0 > glslShaderFeature) || (glslShaderFeature >= FEAT_MAX_NUMBER))
return 0;
return mamebm_programs[glslShaderFeature + idx];
}
for (int i=0; i<10; i++)
virtual GLhandleARB get_program_scrn(int idx) override
{
if ( glsl_scrn_vsh_shader[i] )
(void) gl_delete_shader(nullptr, &glsl_scrn_vsh_shader[i], nullptr);
if ( glsl_scrn_fsh_shader[i] )
(void) gl_delete_shader(nullptr, nullptr, &glsl_scrn_fsh_shader[i]);
if ( glsl_scrn_programs[i] )
(void) gl_delete_shader( &glsl_scrn_programs[i], nullptr, nullptr);
if ((0 > idx) || (idx >= 10))
return 0;
return scrn_programs[idx];
}
delete shinfo;
return 0;
}
virtual int add_mamebm(const char *custShaderPrefix, int idx) override
{
int err;
int glsl_shader_add_mamebm(glsl_shader_info *shinfo, const char * custShaderPrefix, int idx)
err = compile_file(
&mamebm_vsh_shader[GLSL_VERTEX_SHADER_CUSTOM + idx],
GL_VERTEX_SHADER_ARB,
util::string_format("%s.vsh", custShaderPrefix).c_str(),
false);
if (err)
return err;
err = compile_files(
&mamebm_programs[FEAT_CUSTOM + idx],
&mamebm_vsh_shader[GLSL_VERTEX_SHADER_CUSTOM + idx],
&mamebm_fsh_shader[FEAT_CUSTOM + idx],
nullptr, // precompiled
util::string_format("%s_rgb32_dir.fsh", custShaderPrefix).c_str(),
false);
return err;
}
virtual int add_scrn(const char *custShaderPrefix, int idx) override
{
int err;
err = compile_file(
&scrn_vsh_shader[idx],
GL_VERTEX_SHADER_ARB,
util::string_format("%s.vsh", custShaderPrefix).c_str(),
false);
if (err)
return err;
err = compile_files(
&scrn_programs[idx],
&scrn_vsh_shader[idx],
&scrn_fsh_shader[idx],
nullptr, // precompiled
util::string_format("%s.fsh", custShaderPrefix).c_str(),
false);
return err;
}
private:
GLhandleARB mamebm_programs[FEAT_MAX_NUMBER + 9]; // rgb32 dir: plain, bilinear, bicubic, custom0-9, ..
GLhandleARB mamebm_vsh_shader[GLSL_VERTEX_SHADER_MAX_NUMBER + 9]; // general, custom0-9
GLhandleARB mamebm_fsh_shader[FEAT_MAX_NUMBER+9]; // rgb32 dir: plain, bilinear, bicubic, custom0-9
GLhandleARB scrn_programs[10]; // rgb32: custom0-9, ..
GLhandleARB scrn_vsh_shader[10]; // custom0-9
GLhandleARB scrn_fsh_shader[10]; // rgb32: custom0-9
};
} // anonymous namespace
std::unique_ptr<glsl_shader_info> glsl_shader_info::init(
osd_gl_context &gl_ctx
#if defined(USE_DISPATCH_GL)
, osd_gl_dispatch *gld
#endif
)
{
int err;
static char fname[8192];
snprintf(fname, 8192, "%s.vsh", custShaderPrefix); fname[8191]=0;
err = gl_compile_shader_file ( &glsl_mamebm_vsh_shader[GLSL_VERTEX_SHADER_CUSTOM+idx], GL_VERTEX_SHADER_ARB, fname, 0);
if(err) return err;
snprintf(fname, 8192, "%s_rgb32_dir.fsh", custShaderPrefix); fname[8191]=0;
err = gl_compile_shader_files (&glsl_mamebm_programs[GLSL_SHADER_FEAT_CUSTOM+idx],
&glsl_mamebm_vsh_shader[GLSL_VERTEX_SHADER_CUSTOM+idx],
&glsl_mamebm_fsh_shader[GLSL_SHADER_FEAT_CUSTOM+idx],
nullptr /*precompiled*/, fname, 0);
return err;
}
int glsl_shader_add_scrn(glsl_shader_info *shinfo, const char * custShaderPrefix, int idx)
{
int err;
static char fname[8192];
snprintf(fname, 8192, "%s.vsh", custShaderPrefix); fname[8191]=0;
err = gl_compile_shader_file ( &glsl_scrn_vsh_shader[idx], GL_VERTEX_SHADER_ARB, fname, 0);
if(err) return err;
snprintf(fname, 8192, "%s.fsh", custShaderPrefix); fname[8191]=0;
err = gl_compile_shader_files (&glsl_scrn_programs[idx],
&glsl_scrn_vsh_shader[idx],
&glsl_scrn_fsh_shader[idx],
nullptr /*precompiled*/, fname, 0);
return err;
auto result = std::make_unique<glsl_shader_impl>(
#if defined(USE_DISPATCH_GL)
gld
#endif
);
if (!result->initalize(gl_ctx))
result.reset();
return result;
}

View File

@ -1,51 +1,57 @@
// license:BSD-3-Clause
// copyright-holders:Sven Gothel
#ifndef MAME_OSD_OPENGL_GL_SHADER_MGR_H
#define MAME_OSD_OPENGL_GL_SHADER_MGR_H
#ifndef GL_SHADER_MGR_H
#define GL_SHADER_MGR_H
#pragma once
#include "gl_shader_tool.h"
#include "osd_opengl.h"
#include <memory>
// #define GLSL_SOURCE_ON_DISK 1
enum GLSL_SHADER_FEATURE {
GLSL_SHADER_FEAT_PLAIN,
GLSL_SHADER_FEAT_BILINEAR,
GLSL_SHADER_FEAT_BICUBIC,
GLSL_SHADER_FEAT_INT_NUMBER,
GLSL_SHADER_FEAT_CUSTOM = GLSL_SHADER_FEAT_INT_NUMBER,
GLSL_SHADER_FEAT_MAX_NUMBER
};
// old code passed sdl_info * to functions here
// however the parameter was not used
// changed interface to more generic one.
struct glsl_shader_info
class glsl_shader_info : public gl_shader_tool
{
int dummy; // avoid compiler breakage
public:
enum FEATURE
{
FEAT_PLAIN,
FEAT_BILINEAR,
FEAT_BICUBIC,
FEAT_INT_NUMBER,
FEAT_CUSTOM = FEAT_INT_NUMBER,
FEAT_MAX_NUMBER
};
using gl_shader_tool::gl_shader_tool;
virtual ~glsl_shader_info() = default;
/**
* returns the GLSL program if ok/available, otherwise 0
*/
virtual GLhandleARB get_program_mamebm(int glslShaderFeature, int idx) = 0;
virtual const char *get_filter_name_mamebm(int glslShaderFeature) = 0;
virtual int add_mamebm(const char *custShaderPrefix, int idx) = 0;
virtual GLhandleARB get_program_scrn(int idx) = 0;
virtual int add_scrn(const char *custShaderPrefix, int idx) = 0;
/**
* returns pointer if OK, otherwise nullptr
*/
static std::unique_ptr<glsl_shader_info> init(
osd_gl_context &gl_ctx
#if defined(USE_DISPATCH_GL)
, osd_gl_dispatch *gld
#endif
);
};
/**
* returns pointer if ok, otherwise nullptr
*/
glsl_shader_info *glsl_shader_init(osd_gl_context *gl_ctx);
/**
* returns 0 if ok, otherwise an error value
*/
int glsl_shader_free(glsl_shader_info *shinfo);
/**
* returns the GLSL program if ok/available, otherwise 0
*/
GLhandleARB glsl_shader_get_program_mamebm(int glslShaderFeature, int idx);
const char * glsl_shader_get_filter_name_mamebm(int glslShaderFeature);
int glsl_shader_add_mamebm(glsl_shader_info *shinfo, const char * custShaderPrefix, int idx);
GLhandleARB glsl_shader_get_program_scrn(int idx);
int glsl_shader_add_scrn(glsl_shader_info *shinfo, const char * custShaderPrefix, int idx);
#endif // GL_SHADER_MGR_H
#endif // MAME_OSD_OPENGL_GL_SHADER_MGR_H

View File

@ -15,59 +15,90 @@
*
*/
#include "emu.h"
#include "gl_shader_tool.h"
PFNGLGETOBJECTPARAMETERIVARBPROC pfn_glGetObjectParameterivARB= nullptr;
PFNGLGETINFOLOGARBPROC pfn_glGetInfoLogARB= nullptr;
PFNGLDELETEOBJECTARBPROC pfn_glDeleteObjectARB= nullptr;
PFNGLCREATESHADEROBJECTARBPROC pfn_glCreateShaderObjectARB= nullptr;
PFNGLSHADERSOURCEARBPROC pfn_glShaderSourceARB= nullptr;
PFNGLCOMPILESHADERARBPROC pfn_glCompileShaderARB= nullptr;
PFNGLCREATEPROGRAMOBJECTARBPROC pfn_glCreateProgramObjectARB= nullptr;
PFNGLATTACHOBJECTARBPROC pfn_glAttachObjectARB= nullptr;
PFNGLLINKPROGRAMARBPROC pfn_glLinkProgramARB= nullptr;
PFNGLVALIDATEPROGRAMARBPROC pfn_glValidateProgramARB= nullptr;
PFNGLUSEPROGRAMOBJECTARBPROC pfn_glUseProgramObjectARB= nullptr;
PFNGLGETUNIFORMLOCATIONARBPROC pfn_glGetUniformLocationARB= nullptr;
PFNGLUNIFORM1FARBPROC pfn_glUniform1fARB= nullptr;
PFNGLUNIFORM1IARBPROC pfn_glUniform1iARB= nullptr;
PFNGLUNIFORM1FVARBPROC pfn_glUniform1fvARB= nullptr;
PFNGLUNIFORM2FVARBPROC pfn_glUniform2fvARB= nullptr;
PFNGLUNIFORM3FVARBPROC pfn_glUniform3fvARB= nullptr;
PFNGLUNIFORM4FVARBPROC pfn_glUniform4fvARB= nullptr;
PFNGLUNIFORM1IVARBPROC pfn_glUniform1ivARB= nullptr;
PFNGLUNIFORM2IVARBPROC pfn_glUniform2ivARB= nullptr;
PFNGLUNIFORM3IVARBPROC pfn_glUniform3ivARB= nullptr;
PFNGLUNIFORM4IVARBPROC pfn_glUniform4ivARB= nullptr;
#include "osdcore.h"
int gl_shader_loadExtention(osd_gl_context *gl_ctx)
#define GL_CHECK_ERROR_VERBOSE() check_error(CHECK_ALWAYS_VERBOSE, __FILE__, __LINE__)
#define GL_CHECK_ERROR_NORMAL() check_error(CHECK_VERBOSE, __FILE__, __LINE__)
#define GL_CHECK_ERROR_QUIET() check_error(CHECK_QUIET, __FILE__, __LINE__)
#define GL_CHECK_ERROR(m) check_error(m, __FILE__, __LINE__)
#define GL_SHADER_CHECK_ERROR_VERBOSE(o,q) check_error(o, q, CHECK_ALWAYS_VERBOSE, __FILE__, __LINE__)
#define GL_SHADER_CHECK_ERROR_NORMAL(o,q) check_error(o, q, CHECK_VERBOSE, __FILE__, __LINE__)
#define GL_SHADER_CHECK_ERROR_QUIET(o,q) check_error(o, q, CHECK_QUIET, __FILE__, __LINE__)
#define GL_SHADER_CHECK_ERROR(o,q,m) check_error(o, q, m, __FILE__, __LINE__)
#ifdef GL_SHADER_TOOL_DEBUG
#define GL_SHADER_CHECK(o, q) GL_SHADER_CHECK_ERROR_VERBOSE(o, q)
#define GL_CHECK() GL_CHECK_ERROR_VERBOSE()
#else
#define GL_SHADER_CHECK(o, q) GL_SHADER_CHECK_ERROR_NORMAL(o, q)
#define GL_CHECK() GL_CHECK_ERROR_NORMAL()
#endif
gl_shader_tool::gl_shader_tool(
#if defined(USE_DISPATCH_GL)
osd_gl_dispatch *gld
#endif
)
: pfn_glGetObjectParameterivARB(nullptr)
, pfn_glGetInfoLogARB(nullptr)
, pfn_glDeleteObjectARB(nullptr)
, pfn_glCreateShaderObjectARB(nullptr)
, pfn_glShaderSourceARB(nullptr)
, pfn_glCompileShaderARB(nullptr)
, pfn_glCreateProgramObjectARB(nullptr)
, pfn_glAttachObjectARB(nullptr)
, pfn_glLinkProgramARB(nullptr)
, pfn_glValidateProgramARB(nullptr)
, pfn_glUseProgramObjectARB(nullptr)
, pfn_glGetUniformLocationARB(nullptr)
, pfn_glUniform1fARB(nullptr)
, pfn_glUniform1iARB(nullptr)
, pfn_glUniform1fvARB(nullptr)
, pfn_glUniform2fvARB(nullptr)
, pfn_glUniform3fvARB(nullptr)
, pfn_glUniform4fvARB(nullptr)
, pfn_glUniform1ivARB(nullptr)
, pfn_glUniform2ivARB(nullptr)
, pfn_glUniform3ivARB(nullptr)
, pfn_glUniform4ivARB(nullptr)
#if defined(USE_DISPATCH_GL)
, gl_dispatch(gld)
#endif
{
pfn_glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) gl_ctx->getProcAddress("glGetObjectParameterivARB");
pfn_glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) gl_ctx->getProcAddress ("glGetInfoLogARB");
pfn_glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) gl_ctx->getProcAddress ("glDeleteObjectARB");
pfn_glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) gl_ctx->getProcAddress ("glCreateShaderObjectARB");
pfn_glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) gl_ctx->getProcAddress ("glShaderSourceARB");
pfn_glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) gl_ctx->getProcAddress ("glCompileShaderARB");
pfn_glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) gl_ctx->getProcAddress ("glCreateProgramObjectARB");
pfn_glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) gl_ctx->getProcAddress ("glAttachObjectARB");
pfn_glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) gl_ctx->getProcAddress ("glLinkProgramARB");
pfn_glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) gl_ctx->getProcAddress ("glValidateProgramARB");
pfn_glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) gl_ctx->getProcAddress ("glUseProgramObjectARB");
pfn_glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) gl_ctx->getProcAddress ("glGetUniformLocationARB");
pfn_glUniform1fARB = (PFNGLUNIFORM1FARBPROC) gl_ctx->getProcAddress ("glUniform1fARB");
pfn_glUniform1iARB = (PFNGLUNIFORM1IARBPROC) gl_ctx->getProcAddress ("glUniform1iARB");
pfn_glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) gl_ctx->getProcAddress ("glUniform1fvARB");
pfn_glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) gl_ctx->getProcAddress ("glUniform2fvARB");
pfn_glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) gl_ctx->getProcAddress ("glUniform3fvARB");
pfn_glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) gl_ctx->getProcAddress ("glUniform4fvARB");
pfn_glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC) gl_ctx->getProcAddress ("glUniform1ivARB");
pfn_glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) gl_ctx->getProcAddress ("glUniform2ivARB");
pfn_glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) gl_ctx->getProcAddress ("glUniform3ivARB");
pfn_glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) gl_ctx->getProcAddress ("glUniform4ivARB");
}
if ( pfn_glGetObjectParameterivARB && pfn_glGetInfoLogARB && pfn_glDeleteObjectARB && pfn_glCreateShaderObjectARB &&
bool gl_shader_tool::load_extension(osd_gl_context &gl_ctx)
{
gl_ctx.get_proc_address(pfn_glGetObjectParameterivARB, "glGetObjectParameterivARB");
gl_ctx.get_proc_address(pfn_glGetInfoLogARB, "glGetInfoLogARB");
gl_ctx.get_proc_address(pfn_glDeleteObjectARB, "glDeleteObjectARB");
gl_ctx.get_proc_address(pfn_glCreateShaderObjectARB, "glCreateShaderObjectARB");
gl_ctx.get_proc_address(pfn_glShaderSourceARB, "glShaderSourceARB");
gl_ctx.get_proc_address(pfn_glCompileShaderARB, "glCompileShaderARB");
gl_ctx.get_proc_address(pfn_glCreateProgramObjectARB, "glCreateProgramObjectARB");
gl_ctx.get_proc_address(pfn_glAttachObjectARB, "glAttachObjectARB");
gl_ctx.get_proc_address(pfn_glLinkProgramARB, "glLinkProgramARB");
gl_ctx.get_proc_address(pfn_glValidateProgramARB, "glValidateProgramARB");
gl_ctx.get_proc_address(pfn_glUseProgramObjectARB, "glUseProgramObjectARB");
gl_ctx.get_proc_address(pfn_glGetUniformLocationARB, "glGetUniformLocationARB");
gl_ctx.get_proc_address(pfn_glUniform1fARB, "glUniform1fARB");
gl_ctx.get_proc_address(pfn_glUniform1iARB, "glUniform1iARB");
gl_ctx.get_proc_address(pfn_glUniform1fvARB, "glUniform1fvARB");
gl_ctx.get_proc_address(pfn_glUniform2fvARB, "glUniform2fvARB");
gl_ctx.get_proc_address(pfn_glUniform3fvARB, "glUniform3fvARB");
gl_ctx.get_proc_address(pfn_glUniform4fvARB, "glUniform4fvARB");
gl_ctx.get_proc_address(pfn_glUniform1ivARB, "glUniform1ivARB");
gl_ctx.get_proc_address(pfn_glUniform2ivARB, "glUniform2ivARB");
gl_ctx.get_proc_address(pfn_glUniform3ivARB, "glUniform3ivARB");
gl_ctx.get_proc_address(pfn_glUniform4ivARB, "glUniform4ivARB");
if (pfn_glGetObjectParameterivARB && pfn_glGetInfoLogARB && pfn_glDeleteObjectARB && pfn_glCreateShaderObjectARB &&
pfn_glShaderSourceARB && pfn_glCompileShaderARB && pfn_glCreateProgramObjectARB && pfn_glAttachObjectARB &&
pfn_glLinkProgramARB && pfn_glValidateProgramARB && pfn_glUseProgramObjectARB &&
pfn_glGetUniformLocationARB && pfn_glUniform1fARB && pfn_glUniform1iARB &&
@ -75,62 +106,52 @@ int gl_shader_loadExtention(osd_gl_context *gl_ctx)
pfn_glUniform1ivARB && pfn_glUniform2ivARB && pfn_glUniform3ivARB && pfn_glUniform4ivARB
)
{
return 0;
return true;
}
osd_printf_error("OpenGL: missing ARB shader function: ");
if (!pfn_glGetObjectParameterivARB) osd_printf_error("glGetObjectParameterivARB, ");
if (!pfn_glGetInfoLogARB) osd_printf_error("glGetInfoLogARB, ");
if (!pfn_glDeleteObjectARB) osd_printf_error("glDeleteObjectARB, ");
if (!pfn_glCreateShaderObjectARB) osd_printf_error("glCreateShaderObjectARB, ");
if (!pfn_glShaderSourceARB) osd_printf_error("glShaderSourceARB, ");
if (!pfn_glCompileShaderARB) osd_printf_error("glCompileShaderARB, ");
if (!pfn_glCreateProgramObjectARB) osd_printf_error("glCreateProgramObjectARB, ");
if (!pfn_glAttachObjectARB) osd_printf_error("glAttachObjectARB, ");
if (!pfn_glLinkProgramARB) osd_printf_error("glLinkProgramARB, ");
if (!pfn_glValidateProgramARB) osd_printf_error("glValidateProgramARB, ");
if (!pfn_glUseProgramObjectARB) osd_printf_error("glUseProgramObjectARB, ");
if (!pfn_glGetUniformLocationARB) osd_printf_error("glGetUniformLocationARB, ");
if (!pfn_glUniform1fARB) osd_printf_error("glUniform1fARB, ");
if (!pfn_glUniform1iARB) osd_printf_error("glUniform1iARB");
if (!pfn_glUniform1fvARB) osd_printf_error("glUniform1fvARB, ");
if (!pfn_glUniform2fvARB) osd_printf_error("glUniform2fvARB, ");
if (!pfn_glUniform3fvARB) osd_printf_error("glUniform3fvARB, ");
if (!pfn_glUniform4fvARB) osd_printf_error("glUniform4fvARB, ");
if (!pfn_glUniform1ivARB) osd_printf_error("glUniform1ivARB");
if (!pfn_glUniform2ivARB) osd_printf_error("glUniform2ivARB");
if (!pfn_glUniform3ivARB) osd_printf_error("glUniform3ivARB");
if (!pfn_glUniform4ivARB) osd_printf_error("glUniform4ivARB");
if (!pfn_glGetObjectParameterivARB) osd_printf_error(" glGetObjectParameterivARB");
if (!pfn_glGetInfoLogARB) osd_printf_error(" glGetInfoLogARB");
if (!pfn_glDeleteObjectARB) osd_printf_error(" glDeleteObjectARB");
if (!pfn_glCreateShaderObjectARB) osd_printf_error(" glCreateShaderObjectARB");
if (!pfn_glShaderSourceARB) osd_printf_error(" glShaderSourceARB");
if (!pfn_glCompileShaderARB) osd_printf_error(" glCompileShaderARB");
if (!pfn_glCreateProgramObjectARB) osd_printf_error(" glCreateProgramObjectARB");
if (!pfn_glAttachObjectARB) osd_printf_error(" glAttachObjectARB");
if (!pfn_glLinkProgramARB) osd_printf_error(" glLinkProgramARB");
if (!pfn_glValidateProgramARB) osd_printf_error(" glValidateProgramARB");
if (!pfn_glUseProgramObjectARB) osd_printf_error(" glUseProgramObjectARB");
if (!pfn_glGetUniformLocationARB) osd_printf_error(" glGetUniformLocationARB");
if (!pfn_glUniform1fARB) osd_printf_error(" glUniform1fARB");
if (!pfn_glUniform1iARB) osd_printf_error(" glUniform1iARB");
if (!pfn_glUniform1fvARB) osd_printf_error(" glUniform1fvARB");
if (!pfn_glUniform2fvARB) osd_printf_error(" glUniform2fvARB");
if (!pfn_glUniform3fvARB) osd_printf_error(" glUniform3fvARB");
if (!pfn_glUniform4fvARB) osd_printf_error(" glUniform4fvARB");
if (!pfn_glUniform1ivARB) osd_printf_error(" glUniform1ivARB");
if (!pfn_glUniform2ivARB) osd_printf_error(" glUniform2ivARB");
if (!pfn_glUniform3ivARB) osd_printf_error(" glUniform3ivARB");
if (!pfn_glUniform4ivARB) osd_printf_error(" glUniform4ivARB");
osd_printf_error("\n");
return -1;
return false;
}
int gl_check_error(GLSLCheckMode m, const char *file, const int line)
int gl_shader_tool::check_error(GLSLCheckMode m, const char *file, const int line)
{
GLenum glerr = glGetError();
if (GL_NO_ERROR != glerr)
{
if ( CHECK_VERBOSE <= m )
{
osd_printf_warning( "%s:%d: GL Error: %d 0x%X\n", file, line, (int)glerr, (unsigned int)glerr);
}
}
return (GL_NO_ERROR != glerr)? glerr : 0;
GLenum const glerr = glGetError();
if (GL_NO_ERROR != glerr)
{
if (CHECK_VERBOSE <= m)
osd_printf_warning("%s:%d: GL Error: %d 0x%X\n", file, line, int(glerr), unsigned(glerr));
}
return (GL_NO_ERROR != glerr) ? glerr : 0;
}
int gl_shader_check_error(GLhandleARB obj, GLenum obj_query, GLSLCheckMode m, const char *file, const int line)
int gl_shader_tool::check_error(GLhandleARB obj, GLenum obj_query, GLSLCheckMode m, const char *file, const int line)
{
GLsizei length;
GLcharARB buffer[255];
GLenum glerr;
GLint param;
int res=0;
glerr = gl_check_error(m, file, line);
if(!obj)
GLenum const glerr = check_error(m, file, line);
if (!obj)
return glerr;
if(obj_query != GL_OBJECT_TYPE_ARB &&
@ -144,79 +165,88 @@ int gl_shader_check_error(GLhandleARB obj, GLenum obj_query, GLSLCheckMode m, co
return -1;
}
GLint param;
pfn_glGetObjectParameterivARB(obj, obj_query, &param);
int res = 0;
switch(obj_query)
{
case GL_OBJECT_TYPE_ARB:
if( param!=GL_PROGRAM_OBJECT_ARB && param!=GL_SHADER_OBJECT_ARB )
case GL_OBJECT_TYPE_ARB:
if (param != GL_PROGRAM_OBJECT_ARB && param != GL_SHADER_OBJECT_ARB)
{
if ( CHECK_VERBOSE <= m )
osd_printf_warning("%s:%d: GL Error: object type 0x%X generation failed\n", file, line, (unsigned int)(uintptr_t)obj);
res=-1;
} else if ( CHECK_ALWAYS_VERBOSE <= m )
}
else if (CHECK_ALWAYS_VERBOSE <= m)
{
if(param==GL_PROGRAM_OBJECT_ARB)
if (param==GL_PROGRAM_OBJECT_ARB)
osd_printf_warning("%s:%d: GL Error: object type 0x%X is PROGRAM, successful\n", file, line, (unsigned int)(uintptr_t)obj);
else
osd_printf_warning("%s:%d: GL Info: object type 0x%X is SHADER, successful\n", file, line, (unsigned int)(uintptr_t)obj);
}
break;
case GL_OBJECT_DELETE_STATUS_ARB:
if(param!=1)
case GL_OBJECT_DELETE_STATUS_ARB:
if (param != 1)
{
if ( CHECK_ALWAYS_VERBOSE <= m )
if (CHECK_ALWAYS_VERBOSE <= m)
osd_printf_warning("%s:%d: GL Info: object 0x%X not yet marked for deletion\n", file, line, (unsigned int)(uintptr_t)obj);
} else if ( CHECK_ALWAYS_VERBOSE <= m )
}
else if (CHECK_ALWAYS_VERBOSE <= m)
{
osd_printf_warning("%s:%d: GL Info: object 0x%X deletion successful\n", file, line, (unsigned int)(uintptr_t)obj);
}
break;
case GL_OBJECT_COMPILE_STATUS_ARB:
if(param!=1)
case GL_OBJECT_COMPILE_STATUS_ARB:
if (param != 1)
{
if ( CHECK_VERBOSE <= m )
if (CHECK_VERBOSE <= m)
osd_printf_warning("%s:%d: GL Error: object 0x%X compilation failed\n", file, line, (unsigned int)(uintptr_t)obj);
res=-1;
} else if ( CHECK_ALWAYS_VERBOSE <= m )
res = -1;
}
else if (CHECK_ALWAYS_VERBOSE <= m)
{
osd_printf_warning("%s:%d: GL Info: object 0x%X compiled successful\n", file, line, (unsigned int)(uintptr_t)obj);
}
break;
case GL_OBJECT_LINK_STATUS_ARB:
if(param!=1)
case GL_OBJECT_LINK_STATUS_ARB:
if (param != 1)
{
if ( CHECK_VERBOSE <= m )
if (CHECK_VERBOSE <= m)
osd_printf_warning("%s:%d: GL Error: object 0x%X linking failed\n", file, line, (unsigned int)(uintptr_t)obj);
res=-1;
} else if ( CHECK_ALWAYS_VERBOSE <= m )
res = -1;
}
else if (CHECK_ALWAYS_VERBOSE <= m)
{
osd_printf_warning("%s:%d: GL Info: object 0x%X linked successful\n", file, line, (unsigned int)(uintptr_t)obj);
}
break;
case GL_OBJECT_VALIDATE_STATUS_ARB:
if(param!=1)
case GL_OBJECT_VALIDATE_STATUS_ARB:
if (param != 1)
{
if ( CHECK_VERBOSE <= m )
if (CHECK_VERBOSE <= m)
osd_printf_warning("%s:%d: GL Error: object 0x%X validation failed\n", file, line, (unsigned int)(uintptr_t)obj);
res=-1;
} else if ( CHECK_ALWAYS_VERBOSE <= m )
res = -1;
}
else if (CHECK_ALWAYS_VERBOSE <= m
)
{
osd_printf_warning("%s:%d: GL Info: object 0x%X validation successful\n", file, line, (unsigned int)(uintptr_t)obj);
}
break;
}
}
if ( res<0 || CHECK_ALWAYS_VERBOSE <= m )
if (res < 0 || CHECK_ALWAYS_VERBOSE <= m)
{
GLsizei length;
GLcharARB buffer[255];
length=0;
pfn_glGetInfoLogARB(obj, sizeof(buffer), &length, buffer);
if(length>0)
if (length>0)
osd_printf_warning("%s:%d glInfoLog: %s\n", file, line, buffer);
}
(void) glGetError(); // ;-)
(void)glGetError(); // ;-)
return res;
}
@ -234,157 +264,175 @@ int gl_round_to_pow2(int v)
return v;
}
int gl_texture_check_size(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height,
GLint border, GLenum format, GLenum type,
GLint *avail_width, GLint *avail_height,
int verbose)
int gl_shader_tool::texture_check_size(
GLenum target,
GLint level,
GLint internalFormat,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
GLint *avail_width,
GLint *avail_height,
bool verbose)
{
int err=1;
GLenum texTargetProxy = (target==GL_TEXTURE_RECTANGLE_ARB)?GL_PROXY_TEXTURE_RECTANGLE_ARB:GL_PROXY_TEXTURE_2D;
if ( !avail_width || !avail_height)
return -1;
if (!avail_width || !avail_height)
return -1;
*avail_width = 0;
*avail_height = 0;
GL_CHECK_ERROR_QUIET();
/* Test the max texture size */
while(err && width>=1 && height>=1 /* && width>=64 && height>=64 */)
// Test the max texture size
int err = 1;
GLenum const texTargetProxy = (target == GL_TEXTURE_RECTANGLE_ARB) ? GL_PROXY_TEXTURE_RECTANGLE_ARB : GL_PROXY_TEXTURE_2D;
while (err && width>=1 && height>=1 /* && width>=64 && height>=64 */)
{
glTexImage2D (texTargetProxy, level,
internalFormat,
width, height,
border, format, type, nullptr);
if ( 0!=(err=GL_CHECK_ERROR_NORMAL() )) return err;
glTexImage2D(texTargetProxy, level,
internalFormat,
width, height,
border, format, type, nullptr);
if (0 != (err=GL_CHECK_ERROR_NORMAL()))
return err;
glGetTexLevelParameteriv( texTargetProxy, level, GL_TEXTURE_WIDTH, avail_width);
glGetTexLevelParameteriv( texTargetProxy, level, GL_TEXTURE_HEIGHT, avail_height);
if ( 0!=(err=GL_CHECK_ERROR_NORMAL() )) return err;
glGetTexLevelParameteriv(texTargetProxy, level, GL_TEXTURE_WIDTH, avail_width);
glGetTexLevelParameteriv(texTargetProxy, level, GL_TEXTURE_HEIGHT, avail_height);
if (0 != (err=GL_CHECK_ERROR_NORMAL()))
return err;
if ( (*avail_width) != width || (*avail_height) != height )
{
err=1;
if(verbose)
if ((*avail_width != width) || (*avail_height != height))
{
osd_printf_warning("gl_texture_size_check: "
"TexImage2D(0x%X, %d, 0x%X, %d, %d, %d, 0x%X, 0x%X): returned size does not match: %dx%d\n",
(unsigned int)target, (int)level, (int)internalFormat,
(int)width, (int)height, (int)border, (unsigned int)format, (unsigned int)type,
(int)*avail_width, (int)*avail_height);
}
err = 1;
if ( (*avail_width) == width )
height /= 2;
else if ( (*avail_height) == height )
width /= 2;
else if (width > height)
width /= 2;
else
if (verbose)
{
osd_printf_warning("gl_texture_size_check: "
"TexImage2D(0x%X, %d, 0x%X, %d, %d, %d, 0x%X, 0x%X): returned size does not match: %dx%d\n",
(unsigned int)target, (int)level, (int)internalFormat,
width, height, border, (unsigned int)format, (unsigned int)type,
*avail_width, *avail_height);
}
if (*avail_width == width)
height /= 2;
if(verbose)
{
fprintf (stderr, "gl_texture_size_check: trying [%dx%d] !\n", (int)height, (int)width);
else if (*avail_height == height)
width /= 2;
else if (width > height)
width /= 2;
else
height /= 2;
if (verbose)
{
osd_printf_verbose("gl_texture_size_check: trying [%dx%d] !\n", height, width);
}
}
else
{
err = 0;
}
} else {
err=0;
}
}
if(!err)
if (!err)
{
*avail_width = width;
*avail_width = width;
*avail_height = height;
}
return err;
}
static int delete_shader_tool( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader, int externalcall)
int gl_shader_tool::delete_shader_tool(
GLhandleARB *program,
GLhandleARB *vertex_shader,
GLhandleARB *fragment_shader,
bool externalcall)
{
int res=0;
int res = 0;
GL_CHECK_ERROR_QUIET();
if(program!= nullptr && *program!=0)
if (program && *program!=0)
{
pfn_glDeleteObjectARB(*program);
if(externalcall)
{
if (externalcall)
res |= GL_SHADER_CHECK(*program, GL_OBJECT_DELETE_STATUS_ARB);
}
*program=0;
*program = 0;
}
if(vertex_shader!= nullptr && *vertex_shader!=0)
if (vertex_shader && *vertex_shader!=0)
{
pfn_glDeleteObjectARB(*vertex_shader);
if(externalcall)
{
if (externalcall)
res |= GL_SHADER_CHECK(*vertex_shader, GL_OBJECT_DELETE_STATUS_ARB);
}
*vertex_shader=0;
}
if(fragment_shader!= nullptr && *fragment_shader!=0)
if (fragment_shader && *fragment_shader!=0)
{
pfn_glDeleteObjectARB(*fragment_shader);
if(externalcall)
{
if (externalcall)
res |= GL_SHADER_CHECK(*fragment_shader, GL_OBJECT_DELETE_STATUS_ARB);
}
*fragment_shader=0;
}
return res;
return res;
}
int gl_compile_shader_source( GLhandleARB *shader, GLenum type, const char * shader_source, int verbose )
int gl_shader_tool::compile_source(
GLhandleARB *shader,
GLenum type,
const char *shader_source,
bool verbose)
{
int err = 0;
int err = 0;
if(shader== nullptr || shader_source== nullptr)
if (!shader || !shader_source)
{
if(shader== nullptr)
if (!shader)
osd_printf_warning("error: gl_compile_shader_source: nullptr shader passed\n");
if(shader_source== nullptr)
if (!shader_source)
osd_printf_warning("error: gl_compile_shader_source: nullptr shader source passed\n");
return -1;
}
*shader = pfn_glCreateShaderObjectARB(type);
err=GL_SHADER_CHECK(*shader, GL_OBJECT_TYPE_ARB);
if(err) goto errout;
*shader = pfn_glCreateShaderObjectARB(type);
err = GL_SHADER_CHECK(*shader, GL_OBJECT_TYPE_ARB);
if (err)
goto errout;
pfn_glShaderSourceARB(*shader, 1, (const GLcharARB **)&shader_source, nullptr);
pfn_glShaderSourceARB(*shader, 1, (const GLcharARB **)&shader_source, nullptr);
pfn_glCompileShaderARB(*shader);
err=GL_SHADER_CHECK(*shader, GL_OBJECT_COMPILE_STATUS_ARB);
if(err) goto errout;
pfn_glCompileShaderARB(*shader);
err = GL_SHADER_CHECK(*shader, GL_OBJECT_COMPILE_STATUS_ARB);
if (err)
goto errout;
if(verbose)
if (verbose)
osd_printf_warning( "<%s>\n", shader_source);
return 0;
errout:
if(*shader!=0)
{
if (*shader != 0)
pfn_glDeleteObjectARB(*shader);
}
osd_printf_warning("failed to process shader: <%s>\n", shader_source);
return err;
return err;
}
int gl_compile_shader_file( GLhandleARB *shader, GLenum type, const char * shader_file, int verbose )
int gl_shader_tool::compile_file(
GLhandleARB *shader,
GLenum type,
const char *shader_file,
bool verbose)
{
if(shader== nullptr || shader_file== nullptr)
if (!shader || !shader_file)
{
if(shader== nullptr)
if (!shader)
osd_printf_warning("error: gl_compile_shader_source: nullptr shader passed\n");
if(shader_file== nullptr)
if (!shader_file)
osd_printf_warning("error: gl_compile_shader_source: nullptr shader file passed\n");
return -1;
}
FILE *const file = fopen(shader_file, "r");
if(!file)
if (!file)
{
osd_printf_warning("cannot open shader_file: %s\n", shader_file);
return -1;
@ -399,15 +447,16 @@ int gl_compile_shader_file( GLhandleARB *shader, GLenum type, const char * shade
memset(buffer, 0, buffer_len + 1);
/* Load Shader Sources */
for( int i = 0, c = 0; i<buffer_len && EOF!=(c=fgetc(file)); i++ )
buffer[i]=(char)c;
for (int i = 0, c = 0; i<buffer_len && EOF!=(c=fgetc(file)); i++)
buffer[i] = char(c);
fclose(file);
int const err=gl_compile_shader_source(shader, type, buffer, verbose);
int const err = compile_source(shader, type, buffer, verbose);
free(buffer);
if(err) goto errout;
if (err)
goto errout;
if(verbose)
if (verbose)
osd_printf_warning("shader file: %s\n", shader_file);
return 0;
@ -418,180 +467,204 @@ errout:
}
int gl_compile_shader_files( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader,
const char * vertex_shader_file,
const char * fragment_shader_file,
int verbose
)
int gl_shader_tool::compile_files(
GLhandleARB *program,
GLhandleARB *vertex_shader,
GLhandleARB *fragment_shader,
const char * vertex_shader_file,
const char * fragment_shader_file,
bool verbose)
{
int err;
if (!program)
{
err=-1;
err = -1;
osd_printf_warning("no program ptr passed\n");
goto errout;
}
if (!vertex_shader)
{
err=-1;
err = -1;
osd_printf_warning("no vertex_shader ptr passed\n");
goto errout;
}
if (!fragment_shader)
{
err=-1;
err = -1;
osd_printf_warning("no fragment_shader ptr passed\n");
goto errout;
}
*program = pfn_glCreateProgramObjectARB();
err=GL_SHADER_CHECK(*program, GL_OBJECT_TYPE_ARB);
if(err) goto errout;
*program = pfn_glCreateProgramObjectARB();
err=GL_SHADER_CHECK(*program, GL_OBJECT_TYPE_ARB);
if (err)
goto errout;
if(!vertex_shader_file)
if (!vertex_shader_file)
{
if (!(*vertex_shader))
{
err=-1;
err = -1;
osd_printf_warning("no vertex_shader_file, nor vertex_shader id passed\n");
goto errout;
}
err=GL_SHADER_CHECK(*vertex_shader, GL_OBJECT_TYPE_ARB);
if(err) goto errout;
} else {
err = gl_compile_shader_file(vertex_shader, GL_VERTEX_SHADER_ARB, vertex_shader_file, verbose);
if(err) return err;
err = GL_SHADER_CHECK(*vertex_shader, GL_OBJECT_TYPE_ARB);
if (err)
goto errout;
}
pfn_glAttachObjectARB(*program, *vertex_shader);
else
{
err = compile_file(vertex_shader, GL_VERTEX_SHADER_ARB, vertex_shader_file, verbose);
if (err)
return err;
}
pfn_glAttachObjectARB(*program, *vertex_shader);
if(!fragment_shader_file)
if (!fragment_shader_file)
{
if (!(*fragment_shader))
{
err=-1;
err = -1;
osd_printf_warning("no fragment_shader_file, nor fragment_shader id passed\n");
goto errout;
}
err=GL_SHADER_CHECK(*fragment_shader, GL_OBJECT_TYPE_ARB);
if(err) goto errout;
} else {
err = gl_compile_shader_file(fragment_shader, GL_FRAGMENT_SHADER_ARB, fragment_shader_file, verbose);
if(err) return err;
err = GL_SHADER_CHECK(*fragment_shader, GL_OBJECT_TYPE_ARB);
if (err)
goto errout;
}
pfn_glAttachObjectARB(*program, *fragment_shader);
else
{
err = compile_file(fragment_shader, GL_FRAGMENT_SHADER_ARB, fragment_shader_file, verbose);
if (err)
return err;
}
pfn_glAttachObjectARB(*program, *fragment_shader);
pfn_glLinkProgramARB(*program);
err=GL_SHADER_CHECK(*program, GL_OBJECT_LINK_STATUS_ARB);
if(err) goto errout;
pfn_glLinkProgramARB(*program);
err = GL_SHADER_CHECK(*program, GL_OBJECT_LINK_STATUS_ARB);
if (err)
goto errout;
pfn_glValidateProgramARB(*program);
err=GL_SHADER_CHECK(*program, GL_OBJECT_VALIDATE_STATUS_ARB);
if(err) goto errout;
pfn_glValidateProgramARB(*program);
err = GL_SHADER_CHECK(*program, GL_OBJECT_VALIDATE_STATUS_ARB);
if (err)
goto errout;
return 0;
return 0;
errout:
delete_shader_tool(program, vertex_shader, fragment_shader, 0);
return err;
delete_shader_tool(program, vertex_shader, fragment_shader, false);
return err;
}
int gl_compile_shader_sources( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader,
const GLcharARB * vertex_shader_source,
const GLcharARB * fragment_shader_source
)
int gl_shader_tool::compile_sources(
GLhandleARB *program,
GLhandleARB *vertex_shader,
GLhandleARB *fragment_shader,
const GLcharARB * vertex_shader_source,
const GLcharARB * fragment_shader_source)
{
int err = 0;
int err = 0;
if (!program)
{
err=-1;
err = -1;
osd_printf_warning("no program ptr passed\n");
goto errout;
}
if (!vertex_shader)
{
err=-1;
err = -1;
osd_printf_warning("no vertex_shader ptr passed\n");
goto errout;
}
if (!fragment_shader)
{
err=-1;
err = -1;
osd_printf_warning("no fragment_shader ptr passed\n");
goto errout;
}
*program = pfn_glCreateProgramObjectARB();
err=GL_SHADER_CHECK(*program, GL_OBJECT_TYPE_ARB);
if(err) goto errout;
*program = pfn_glCreateProgramObjectARB();
err = GL_SHADER_CHECK(*program, GL_OBJECT_TYPE_ARB);
if (err)
goto errout;
if(!vertex_shader_source)
if (!vertex_shader_source)
{
if (!(*vertex_shader))
{
err=-1;
err = -1;
osd_printf_warning("no vertex_shader_source nor a vertex_shader id passed\n");
goto errout;
}
err=GL_SHADER_CHECK(*vertex_shader, GL_OBJECT_TYPE_ARB);
if(err) goto errout;
err = GL_SHADER_CHECK(*vertex_shader, GL_OBJECT_TYPE_ARB);
if (err)
goto errout;
}
if(!fragment_shader_source)
if (!fragment_shader_source)
{
if (!(*fragment_shader))
{
err=-1;
err = -1;
osd_printf_warning("no fragment_shader_source nor a fragment_shader id passed\n");
goto errout;
}
err=GL_SHADER_CHECK(*fragment_shader, GL_OBJECT_TYPE_ARB);
if(err) goto errout;
err = GL_SHADER_CHECK(*fragment_shader, GL_OBJECT_TYPE_ARB);
if (err)
goto errout;
}
if(vertex_shader_source)
if (vertex_shader_source)
{
err=gl_compile_shader_source(vertex_shader, GL_VERTEX_SHADER_ARB, vertex_shader_source, 0);
if(err) goto errout;
err = compile_source(vertex_shader, GL_VERTEX_SHADER_ARB, vertex_shader_source, false);
if (err)
goto errout;
}
pfn_glAttachObjectARB(*program, *vertex_shader);
pfn_glAttachObjectARB(*program, *vertex_shader);
if(fragment_shader_source)
if (fragment_shader_source)
{
err=gl_compile_shader_source(fragment_shader, GL_FRAGMENT_SHADER_ARB, fragment_shader_source, 0);
if(err) goto errout;
err = compile_source(fragment_shader, GL_FRAGMENT_SHADER_ARB, fragment_shader_source, false);
if (err)
goto errout;
}
pfn_glAttachObjectARB(*program, *fragment_shader);
pfn_glAttachObjectARB(*program, *fragment_shader);
pfn_glLinkProgramARB(*program);
err=GL_SHADER_CHECK(*program, GL_OBJECT_LINK_STATUS_ARB);
if(err) {
pfn_glLinkProgramARB(*program);
err = GL_SHADER_CHECK(*program, GL_OBJECT_LINK_STATUS_ARB);
if (err)
{
osd_printf_warning("failed to link program\n");
osd_printf_warning("vertex shader: <%s>\n", vertex_shader_source);
osd_printf_warning("fragment shader: <%s>\n", fragment_shader_source);
goto errout;
}
pfn_glValidateProgramARB(*program);
err=GL_SHADER_CHECK(*program, GL_OBJECT_VALIDATE_STATUS_ARB);
if(err) {
pfn_glValidateProgramARB(*program);
err = GL_SHADER_CHECK(*program, GL_OBJECT_VALIDATE_STATUS_ARB);
if (err)
{
osd_printf_warning("failed to validate program\n");
osd_printf_warning("vertex shader: <%s>\n", vertex_shader_source);
osd_printf_warning("fragment shader: <%s>\n", fragment_shader_source);
goto errout;
}
return 0;
return 0;
errout:
delete_shader_tool(program, vertex_shader, fragment_shader, 0);
return err;
delete_shader_tool(program, vertex_shader, fragment_shader, false);
return err;
}
int gl_delete_shader( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader )
int gl_shader_tool::delete_shader(
GLhandleARB *program,
GLhandleARB *vertex_shader,
GLhandleARB *fragment_shader)
{
return delete_shader_tool(program, vertex_shader, fragment_shader, 1);
return delete_shader_tool(program, vertex_shader, fragment_shader, true);
}

View File

@ -17,10 +17,14 @@
* GL_ARB_fragment_shader
*
*/
#ifndef MAME_OSD_OPENGL_GL_SHADER_TOOL_H
#define MAME_OSD_OPENGL_GL_SHADER_TOOL_H
#pragma once
#ifndef _GL_SHADER_TOOL_
#define _GL_SHADER_TOOL_
#include "osd_opengl.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
@ -36,14 +40,10 @@ extern "C" {
*
*/
#include <stdint.h>
#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES 1
#endif
#include "osd_opengl.h"
#if defined(SDLMAME_MACOSX)
#ifndef APIENTRY
@ -55,80 +55,6 @@ extern "C" {
#endif
typedef void * (APIENTRYP PFNGLGETPROCADDRESSOS)(const char *procName);
/**
* YOU HAVE TO CALL THIS FUNCTION ONCE !
* @return 0 - ok .. all shader ARB functions loaded
* otherwise !=0
*/
int gl_shader_loadExtention(osd_gl_context *gl_ctx);
enum GLSLCheckMode {
CHECK_QUIET, /* just return 0, if no error, otherwise the GL error code, no stderr output */
CHECK_VERBOSE, /* same as CHECK_QUIET, but in the case of an error, use stderr to be verbose */
CHECK_ALWAYS_VERBOSE /* always print out all information available */
};
#define GL_CHECK_ERROR_VERBOSE() gl_check_error(CHECK_ALWAYS_VERBOSE,__FILE__,__LINE__)
#define GL_CHECK_ERROR_NORMAL() gl_check_error(CHECK_VERBOSE,__FILE__,__LINE__)
#define GL_CHECK_ERROR_QUIET() gl_check_error(CHECK_QUIET,__FILE__,__LINE__)
#define GL_CHECK_ERROR(m) gl_check_error(m,__FILE__,__LINE__)
#define GL_SHADER_CHECK_ERROR_VERBOSE(o,q) gl_shader_check_error(o,q,CHECK_ALWAYS_VERBOSE,__FILE__,__LINE__)
#define GL_SHADER_CHECK_ERROR_NORMAL(o,q) gl_shader_check_error(o,q,CHECK_VERBOSE,__FILE__,__LINE__)
#define GL_SHADER_CHECK_ERROR_QUIET(o,q) gl_shader_check_error(o,q,CHECK_QUIET,__FILE__,__LINE__)
#define GL_SHADER_CHECK_ERROR(o,q,m) gl_shader_check_error(o,q,m,__FILE__,__LINE__)
#ifdef GL_SHADER_TOOL_DEBUG
#define GL_SHADER_CHECK(o,q) GL_SHADER_CHECK_ERROR_VERBOSE(o,q)
#define GL_CHECK() GL_CHECK_ERROR_VERBOSE()
#else
#define GL_SHADER_CHECK(o,q) GL_SHADER_CHECK_ERROR_NORMAL(o,q)
#define GL_CHECK() GL_CHECK_ERROR_NORMAL()
#endif
int gl_check_error(GLSLCheckMode m, const char *file, const int line);
int gl_texture_check_size(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height,
GLint border, GLenum format, GLenum type,
GLsizei *avail_width, GLsizei *avail_height,
int verbose);
int gl_round_to_pow2(int v);
/**
* @param obj_query Can be either GL_OBJECT_TYPE_ARB, GL_OBJECT_DELETE_STATUS_ARB, GL_OBJECT_COMPILE_STATUS_ARB,
* GL_OBJECT_LINK_STATUS_ARB, GL_OBJECT_VALIDATE_STATUS_ARB
* Should be used after the referring action, i.e. GL_OBJECT_DELETE_STATUS_ARB after a
* glDeleteObjectARB call, etc.
*/
int gl_shader_check_error(GLhandleARB obj, GLenum obj_query, GLSLCheckMode m, const char *file, const int line);
int gl_compile_shader_file ( GLhandleARB *shader, GLenum type, const char * shader_file, int verbose );
int gl_compile_shader_source( GLhandleARB *shader, GLenum type, const char * shader_source, int verbose );
/**
* you can pass either a valid shader_file, or a precompiled vertex_shader,
* this is true for both, vertex and fragment shaders.
*/
int gl_compile_shader_files( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader,
const char * vertex_shader_file,
const char * fragment_shader_file,
int verbose
);
/**
* you can pass either a valid shader_file, or a precompiled vertex_shader,
* this is true for both, vertex and fragment shaders.
*/
int gl_compile_shader_sources( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader,
const GLcharARB * vertex_shader_source,
const GLcharARB * fragment_shader_source
);
int gl_delete_shader( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader );
#if defined(SDLMAME_MACOSX)
#ifndef GL_ARB_shader_objects
typedef char GLcharARB;
@ -158,32 +84,118 @@ typedef void (APIENTRYP PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count,
typedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value);
#endif
extern PFNGLGETOBJECTPARAMETERIVARBPROC pfn_glGetObjectParameterivARB;
extern PFNGLGETINFOLOGARBPROC pfn_glGetInfoLogARB;
extern PFNGLDELETEOBJECTARBPROC pfn_glDeleteObjectARB;
extern PFNGLCREATESHADEROBJECTARBPROC pfn_glCreateShaderObjectARB;
extern PFNGLSHADERSOURCEARBPROC pfn_glShaderSourceARB;
extern PFNGLCOMPILESHADERARBPROC pfn_glCompileShaderARB;
extern PFNGLCREATEPROGRAMOBJECTARBPROC pfn_glCreateProgramObjectARB;
extern PFNGLATTACHOBJECTARBPROC pfn_glAttachObjectARB;
extern PFNGLLINKPROGRAMARBPROC pfn_glLinkProgramARB;
extern PFNGLVALIDATEPROGRAMARBPROC pfn_glValidateProgramARB;
extern PFNGLUSEPROGRAMOBJECTARBPROC pfn_glUseProgramObjectARB;
extern PFNGLGETUNIFORMLOCATIONARBPROC pfn_glGetUniformLocationARB;
extern PFNGLUNIFORM1FARBPROC pfn_glUniform1fARB;
extern PFNGLUNIFORM1IARBPROC pfn_glUniform1iARB;
extern PFNGLUNIFORM1FVARBPROC pfn_glUniform1fvARB;
extern PFNGLUNIFORM2FVARBPROC pfn_glUniform2fvARB;
extern PFNGLUNIFORM3FVARBPROC pfn_glUniform3fvARB;
extern PFNGLUNIFORM4FVARBPROC pfn_glUniform4fvARB;
extern PFNGLUNIFORM1IVARBPROC pfn_glUniform1ivARB;
extern PFNGLUNIFORM2IVARBPROC pfn_glUniform2ivARB;
extern PFNGLUNIFORM3IVARBPROC pfn_glUniform3ivARB;
extern PFNGLUNIFORM4IVARBPROC pfn_glUniform4ivARB;
typedef void * (APIENTRYP PFNGLGETPROCADDRESSOS)(const char *procName);
#ifdef __cplusplus
}
#endif
class gl_shader_tool
{
public:
gl_shader_tool(
#if defined(USE_DISPATCH_GL)
osd_gl_dispatch *gld
#endif
);
PFNGLGETOBJECTPARAMETERIVARBPROC pfn_glGetObjectParameterivARB;
PFNGLGETINFOLOGARBPROC pfn_glGetInfoLogARB;
PFNGLDELETEOBJECTARBPROC pfn_glDeleteObjectARB;
PFNGLCREATESHADEROBJECTARBPROC pfn_glCreateShaderObjectARB;
PFNGLSHADERSOURCEARBPROC pfn_glShaderSourceARB;
PFNGLCOMPILESHADERARBPROC pfn_glCompileShaderARB;
PFNGLCREATEPROGRAMOBJECTARBPROC pfn_glCreateProgramObjectARB;
PFNGLATTACHOBJECTARBPROC pfn_glAttachObjectARB;
PFNGLLINKPROGRAMARBPROC pfn_glLinkProgramARB;
PFNGLVALIDATEPROGRAMARBPROC pfn_glValidateProgramARB;
PFNGLUSEPROGRAMOBJECTARBPROC pfn_glUseProgramObjectARB;
PFNGLGETUNIFORMLOCATIONARBPROC pfn_glGetUniformLocationARB;
PFNGLUNIFORM1FARBPROC pfn_glUniform1fARB;
PFNGLUNIFORM1IARBPROC pfn_glUniform1iARB;
PFNGLUNIFORM1FVARBPROC pfn_glUniform1fvARB;
PFNGLUNIFORM2FVARBPROC pfn_glUniform2fvARB;
PFNGLUNIFORM3FVARBPROC pfn_glUniform3fvARB;
PFNGLUNIFORM4FVARBPROC pfn_glUniform4fvARB;
PFNGLUNIFORM1IVARBPROC pfn_glUniform1ivARB;
PFNGLUNIFORM2IVARBPROC pfn_glUniform2ivARB;
PFNGLUNIFORM3IVARBPROC pfn_glUniform3ivARB;
PFNGLUNIFORM4IVARBPROC pfn_glUniform4ivARB;
/**
* YOU HAVE TO CALL THIS FUNCTION ONCE !
* @return true - ok .. all shader ARB functions loaded
* otherwise false
*/
bool load_extension(osd_gl_context &gl_ctx);
int texture_check_size(
GLenum target,
GLint level,
GLint internalFormat,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
GLsizei *avail_width,
GLsizei *avail_height,
bool verbose);
protected:
int compile_file(GLhandleARB *shader, GLenum type, const char *shader_file, bool verbose);
int compile_source(GLhandleARB *shader, GLenum type, const char *shader_source, bool verbose);
/**
* you can pass either a valid shader_file, or a precompiled vertex_shader,
* this is true for both, vertex and fragment shaders.
*/
int compile_files(
GLhandleARB *program,
GLhandleARB *vertex_shader,
GLhandleARB *fragment_shader,
const char *vertex_shader_file,
const char *fragment_shader_file,
bool verbose);
/**
* you can pass either a valid shader_file, or a precompiled vertex_shader,
* this is true for both, vertex and fragment shaders.
*/
int compile_sources(
GLhandleARB *program,
GLhandleARB *vertex_shader,
GLhandleARB *fragment_shader,
const GLcharARB *vertex_shader_source,
const GLcharARB *fragment_shader_source);
int delete_shader(GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader);
#if defined(USE_DISPATCH_GL)
osd_gl_dispatch *const gl_dispatch; // name is magic, can't be changed
#endif
private:
enum GLSLCheckMode
{
CHECK_QUIET, // just return 0, if no error, otherwise the GL error code, no stderr output
CHECK_VERBOSE, // same as CHECK_QUIET, but in the case of an error, use stderr to be verbose
CHECK_ALWAYS_VERBOSE // always print out all information available
};
int check_error(GLSLCheckMode m, const char *file, const int line);
/**
* @param obj_query Can be either GL_OBJECT_TYPE_ARB, GL_OBJECT_DELETE_STATUS_ARB, GL_OBJECT_COMPILE_STATUS_ARB,
* GL_OBJECT_LINK_STATUS_ARB, GL_OBJECT_VALIDATE_STATUS_ARB
* Should be used after the referring action, i.e. GL_OBJECT_DELETE_STATUS_ARB after a
* glDeleteObjectARB call, etc.
*/
int check_error(GLhandleARB obj, GLenum obj_query, GLSLCheckMode m, const char *file, const int line);
int delete_shader_tool(GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader, bool externalcall);
};
int gl_round_to_pow2(int v);
#endif // MAME_OSD_OPENGL_GL_SHADER_TOOL_H

View File

@ -43,21 +43,31 @@
class osd_gl_context
{
public:
osd_gl_context() { }
virtual ~osd_gl_context() { }
virtual void MakeCurrent() = 0;
virtual const char *LastErrorMsg() = 0;
virtual void *getProcAddress(const char *proc) = 0;
virtual ~osd_gl_context() = default;
virtual explicit operator bool() const = 0;
virtual void make_current() = 0;
virtual const char *last_error_message() = 0;
virtual void *get_proc_address(const char *proc) = 0;
/*
* 0 for immediate updates,
* 1 for updates synchronized with the vertical retrace,
* -1 for late swap tearing
*
* returns -1 if swap interval is not supported
*
* returns false if swap interval is not supported
*/
virtual int SetSwapInterval(const int swap) = 0;
virtual void SwapBuffer() = 0;
virtual bool set_swap_interval(const int swap) = 0;
virtual void swap_buffer() = 0;
template <typename T>
bool get_proc_address(T &ptr, const char *name)
{
ptr = T(uintptr_t(get_proc_address(name)));
return bool(ptr);
}
};
@ -93,11 +103,6 @@
#undef OSD_GL
#undef OSD_GL_UNUSED
#ifdef _MSC_VER
extern "C" osd_gl_dispatch *gl_dispatch;
#endif
extern osd_gl_dispatch *gl_dispatch;
/*
* Use gl_mangle to map function names
*/
@ -120,67 +125,67 @@
*
***************************************************************/
#define glAccum MANGLE(Accum)
#define glActiveStencilFaceEXT MANGLE(ActiveStencilFaceEXT)
#define glActiveTextureARB MANGLE(ActiveTextureARB)
#define glActiveTexture MANGLE(ActiveTexture)
#define glAlphaFragmentOp1ATI MANGLE(AlphaFragmentOp1ATI)
#define glAlphaFragmentOp2ATI MANGLE(AlphaFragmentOp2ATI)
#define glAlphaFragmentOp3ATI MANGLE(AlphaFragmentOp3ATI)
#define glAlphaFunc MANGLE(AlphaFunc)
#define glApplyTextureEXT MANGLE(ApplyTextureEXT)
#define glAreProgramsResidentNV MANGLE(AreProgramsResidentNV)
#define glAccum MANGLE(Accum)
#define glActiveStencilFaceEXT MANGLE(ActiveStencilFaceEXT)
#define glActiveTextureARB MANGLE(ActiveTextureARB)
#define glActiveTexture MANGLE(ActiveTexture)
#define glAlphaFragmentOp1ATI MANGLE(AlphaFragmentOp1ATI)
#define glAlphaFragmentOp2ATI MANGLE(AlphaFragmentOp2ATI)
#define glAlphaFragmentOp3ATI MANGLE(AlphaFragmentOp3ATI)
#define glAlphaFunc MANGLE(AlphaFunc)
#define glApplyTextureEXT MANGLE(ApplyTextureEXT)
#define glAreProgramsResidentNV MANGLE(AreProgramsResidentNV)
#define glAreTexturesResidentEXT MANGLE(AreTexturesResidentEXT)
#define glAreTexturesResident MANGLE(AreTexturesResident)
#define glArrayElementEXT MANGLE(ArrayElementEXT)
#define glArrayElement MANGLE(ArrayElement)
#define glArrayObjectATI MANGLE(ArrayObjectATI)
#define glAsyncMarkerSGIX MANGLE(AsyncMarkerSGIX)
#define glAttachObjectARB MANGLE(AttachObjectARB)
#define glAttachShader MANGLE(AttachShader)
#define glAreTexturesResident MANGLE(AreTexturesResident)
#define glArrayElementEXT MANGLE(ArrayElementEXT)
#define glArrayElement MANGLE(ArrayElement)
#define glArrayObjectATI MANGLE(ArrayObjectATI)
#define glAsyncMarkerSGIX MANGLE(AsyncMarkerSGIX)
#define glAttachObjectARB MANGLE(AttachObjectARB)
#define glAttachShader MANGLE(AttachShader)
#define glBeginFragmentShaderATI MANGLE(BeginFragmentShaderATI)
#define glBegin MANGLE(Begin)
#define glBeginOcclusionQueryNV MANGLE(BeginOcclusionQueryNV)
#define glBeginQueryARB MANGLE(BeginQueryARB)
#define glBeginQuery MANGLE(BeginQuery)
#define glBeginVertexShaderEXT MANGLE(BeginVertexShaderEXT)
#define glBindAttribLocationARB MANGLE(BindAttribLocationARB)
#define glBindAttribLocation MANGLE(BindAttribLocation)
#define glBindBufferARB MANGLE(BindBufferARB)
#define glBindBuffer MANGLE(BindBuffer)
#define glBindFragmentShaderATI MANGLE(BindFragmentShaderATI)
#define glBindFramebufferEXT MANGLE(BindFramebufferEXT)
#define glBindLightParameterEXT MANGLE(BindLightParameterEXT)
#define glBegin MANGLE(Begin)
#define glBeginOcclusionQueryNV MANGLE(BeginOcclusionQueryNV)
#define glBeginQueryARB MANGLE(BeginQueryARB)
#define glBeginQuery MANGLE(BeginQuery)
#define glBeginVertexShaderEXT MANGLE(BeginVertexShaderEXT)
#define glBindAttribLocationARB MANGLE(BindAttribLocationARB)
#define glBindAttribLocation MANGLE(BindAttribLocation)
#define glBindBufferARB MANGLE(BindBufferARB)
#define glBindBuffer MANGLE(BindBuffer)
#define glBindFragmentShaderATI MANGLE(BindFragmentShaderATI)
#define glBindFramebufferEXT MANGLE(BindFramebufferEXT)
#define glBindLightParameterEXT MANGLE(BindLightParameterEXT)
#define glBindMaterialParameterEXT MANGLE(BindMaterialParameterEXT)
#define glBindParameterEXT MANGLE(BindParameterEXT)
#define glBindProgramARB MANGLE(BindProgramARB)
#define glBindProgramNV MANGLE(BindProgramNV)
#define glBindRenderbufferEXT MANGLE(BindRenderbufferEXT)
#define glBindParameterEXT MANGLE(BindParameterEXT)
#define glBindProgramARB MANGLE(BindProgramARB)
#define glBindProgramNV MANGLE(BindProgramNV)
#define glBindRenderbufferEXT MANGLE(BindRenderbufferEXT)
#define glBindTexGenParameterEXT MANGLE(BindTexGenParameterEXT)
#define glBindTextureEXT MANGLE(BindTextureEXT)
#define glBindTexture MANGLE(BindTexture)
#define glBindTextureUnitParameterEXT MANGLE(BindTextureUnitParameterEXT)
#define glBindVertexArrayAPPLE MANGLE(BindVertexArrayAPPLE)
#define glBindVertexShaderEXT MANGLE(BindVertexShaderEXT)
#define glBinormal3bEXT MANGLE(Binormal3bEXT)
#define glBinormal3bvEXT MANGLE(Binormal3bvEXT)
#define glBinormal3dEXT MANGLE(Binormal3dEXT)
#define glBinormal3dvEXT MANGLE(Binormal3dvEXT)
#define glBinormal3fEXT MANGLE(Binormal3fEXT)
#define glBinormal3fvEXT MANGLE(Binormal3fvEXT)
#define glBinormal3iEXT MANGLE(Binormal3iEXT)
#define glBinormal3ivEXT MANGLE(Binormal3ivEXT)
#define glBinormal3sEXT MANGLE(Binormal3sEXT)
#define glBinormal3svEXT MANGLE(Binormal3svEXT)
#define glBinormalPointerEXT MANGLE(BinormalPointerEXT)
#define glBitmap MANGLE(Bitmap)
#define glBlendColorEXT MANGLE(BlendColorEXT)
#define glBlendColor MANGLE(BlendColor)
#define glBlendEquationEXT MANGLE(BlendEquationEXT)
#define glBlendEquation MANGLE(BlendEquation)
#define glBindTextureEXT MANGLE(BindTextureEXT)
#define glBindTexture MANGLE(BindTexture)
#define glBindTextureUnitParameterEXT MANGLE(BindTextureUnitParameterEXT)
#define glBindVertexArrayAPPLE MANGLE(BindVertexArrayAPPLE)
#define glBindVertexShaderEXT MANGLE(BindVertexShaderEXT)
#define glBinormal3bEXT MANGLE(Binormal3bEXT)
#define glBinormal3bvEXT MANGLE(Binormal3bvEXT)
#define glBinormal3dEXT MANGLE(Binormal3dEXT)
#define glBinormal3dvEXT MANGLE(Binormal3dvEXT)
#define glBinormal3fEXT MANGLE(Binormal3fEXT)
#define glBinormal3fvEXT MANGLE(Binormal3fvEXT)
#define glBinormal3iEXT MANGLE(Binormal3iEXT)
#define glBinormal3ivEXT MANGLE(Binormal3ivEXT)
#define glBinormal3sEXT MANGLE(Binormal3sEXT)
#define glBinormal3svEXT MANGLE(Binormal3svEXT)
#define glBinormalPointerEXT MANGLE(BinormalPointerEXT)
#define glBitmap MANGLE(Bitmap)
#define glBlendColorEXT MANGLE(BlendColorEXT)
#define glBlendColor MANGLE(BlendColor)
#define glBlendEquationEXT MANGLE(BlendEquationEXT)
#define glBlendEquation MANGLE(BlendEquation)
#define glBlendEquationSeparateATI MANGLE(BlendEquationSeparateATI)
#define glBlendEquationSeparateEXT MANGLE(BlendEquationSeparateEXT)
#define glBlendEquationSeparate MANGLE(BlendEquationSeparate)
#define glBlendEquationSeparate MANGLE(BlendEquationSeparate)
#define glBlendFunc MANGLE(BlendFunc)
#define glBlendFuncSeparateEXT MANGLE(BlendFuncSeparateEXT)
#define glBlendFuncSeparateINGR MANGLE(BlendFuncSeparateINGR)

View File

@ -25,7 +25,6 @@
#include "modules/lib/osdlib.h"
#include "modules/lib/osdobj_common.h"
#include "modules/opengl/gl_shader_mgr.h"
#include "modules/opengl/gl_shader_tool.h"
#include "osdcomm.h"
// OSD headers
@ -190,7 +189,14 @@ struct ogl_video_config
class ogl_texture_info
{
public:
ogl_texture_info()
ogl_texture_info(
#if defined(USE_DISPATCH_GL)
osd_gl_dispatch *gld
#endif
)
#if defined(USE_DISPATCH_GL)
: gl_dispatch(gld)
#endif
{
for (int i=0; i<2; i++)
{
@ -204,6 +210,9 @@ public:
texCoord[i] = 0.0f;
}
#if defined(USE_DISPATCH_GL)
osd_gl_dispatch *const gl_dispatch; // name is magic, can't be changed
#endif
HashT hash = 0; // hash value for the texture (must be >= pointer size)
uint32_t flags = 0; // rendering flags
render_texinfo texinfo; // copy of the texture info
@ -258,7 +267,6 @@ public:
, m_usepbo(0)
, m_usefbo(0)
, m_useglsl(0)
, m_glsl(nullptr)
, m_glsl_program_num(0)
, m_glsl_program_mb2sc(0)
, m_usetexturerect(0)
@ -314,6 +322,7 @@ private:
void destroy_all_textures();
void loadGLExtensions();
void loadgl_functions();
void initialize_gl();
void set_blendmode(int blendmode);
HashT texture_compute_hash(const render_texinfo *texture, uint32_t flags);
@ -336,6 +345,20 @@ private:
int texture_fbo_create(uint32_t text_unit, uint32_t text_name, uint32_t fbo_name, int width, int height) const;
void texture_set_data(ogl_texture_info *texture, const render_texinfo *texsource, uint32_t flags) const;
int gl_check_error(bool log, const char *file, int line) const
{
GLenum const glerr = glGetError();
if (GL_NO_ERROR != glerr)
{
if (log)
osd_printf_warning("%s:%d: GL Error: %d 0x%X\n", file, line, int(glerr), unsigned(glerr));
}
return (GL_NO_ERROR != glerr) ? glerr : 0;
}
#define GL_CHECK_ERROR_QUIET() gl_check_error(false, __FILE__, __LINE__)
#define GL_CHECK_ERROR_NORMAL() gl_check_error(true, __FILE__, __LINE__)
ogl_video_config const &m_ogl_config;
int32_t m_blittimer;
@ -344,6 +367,7 @@ private:
osd_dim m_blit_dim;
std::unique_ptr<osd_gl_context> m_gl_context;
std::unique_ptr<glsl_shader_info> m_shader_tool;
int m_initialized; // is everything well initialized, i.e. all GL stuff etc.
// 3D info (GL mode only)
@ -357,8 +381,6 @@ private:
int m_usefbo; // runtime check if FBO is available
int m_useglsl; // runtime check if GLSL is available
glsl_shader_info *m_glsl; // glsl_shader_info
GLhandleARB m_glsl_program[2*GLSL_SHADER_MAX]; // GLSL programs, or 0
int m_glsl_program_num; // number of GLSL programs
int m_glsl_program_mb2sc; // GLSL program idx, which transforms
@ -379,6 +401,10 @@ private:
int32_t m_surf_h;
GLfloat m_texVerticex[8];
#if defined(USE_DISPATCH_GL)
std::unique_ptr<osd_gl_dispatch> gl_dispatch; // name is magic, can't be changed
#endif
// OGL 1.3
#if defined(GL_ARB_multitexture) && !defined(OSD_MAC)
PFNGLACTIVETEXTUREARBPROC m_glActiveTexture = nullptr;
@ -520,7 +546,7 @@ void renderer_ogl::set_blendmode(int blendmode)
}
}
static int glsl_shader_feature = GLSL_SHADER_FEAT_PLAIN;
static int glsl_shader_feature = glsl_shader_info::FEAT_PLAIN; // FIXME: why is this static?
//============================================================
// Static Variables
@ -532,9 +558,10 @@ bool renderer_ogl::s_shown_video_info = false;
// Load the OGL function addresses
//============================================================
static void loadgl_functions(osd_gl_context &context)
void renderer_ogl::loadgl_functions()
{
#ifdef USE_DISPATCH_GL
#if defined(USE_DISPATCH_GL)
gl_dispatch = std::make_unique<osd_gl_dispatch>();
int err_count = 0;
@ -542,11 +569,11 @@ static void loadgl_functions(osd_gl_context &context)
* while func will be expanded to disp_p->glBegin
*/
#define OSD_GL(ret,func,params) \
if (!( func = (ret (APIENTRY *)params) context.getProcAddress( #func ) )) \
{ err_count++; osd_printf_error("GL function %s not found!\n", #func ); }
#define OSD_GL(ret, func, params) \
if (!m_gl_context->get_proc_address(func, #func)) \
{ err_count++; osd_printf_error("GL function %s not found!\n", #func); }
#define OSD_GL_UNUSED(ret,func,params)
#define OSD_GL_UNUSED(ret, func, params)
#define GET_GLFUNC 1
#include "modules/opengl/osd_opengl.h"
@ -729,12 +756,13 @@ int renderer_ogl::create()
#else
m_gl_context.reset(new sdl_gl_context(dynamic_cast<sdl_window_info &>(window()).platform_window()));
#endif
if (m_gl_context->LastErrorMsg() != nullptr)
if (!*m_gl_context)
{
osd_printf_error("%s\n", m_gl_context->LastErrorMsg());
char const *const msg = m_gl_context->last_error_message();
osd_printf_error("Creating OpenGL context failed: %s\n", msg ? msg : "unknown error");
return 1;
}
m_gl_context->SetSwapInterval(video_config.waitvsync ? 1 : 0);
m_gl_context->set_swap_interval(video_config.waitvsync ? 1 : 0);
m_blittimer = 0;
m_surf_w = 0;
@ -750,7 +778,7 @@ int renderer_ogl::create()
/* load any GL function addresses
* this must be done here because we need a context
*/
loadgl_functions(*m_gl_context);
loadgl_functions();
initialize_gl();
m_init_context = 0;
@ -786,7 +814,7 @@ void renderer_ogl::destroy_all_textures()
if (!m_initialized)
return;
m_gl_context->MakeCurrent();
m_gl_context->make_current();
bool const lock = bool(window().m_primlist);
if (lock)
@ -840,11 +868,7 @@ void renderer_ogl::destroy_all_textures()
}
}
if (m_useglsl)
{
glsl_shader_free(m_glsl);
m_glsl = nullptr;
}
m_shader_tool.reset();
m_initialized = 0;
@ -885,86 +909,67 @@ void renderer_ogl::loadGLExtensions()
// Get Pointers To The GL Functions
// VBO:
if( m_usevbo )
if (m_usevbo)
{
m_glGenBuffers = (PFNGLGENBUFFERSPROC) m_gl_context->getProcAddress("glGenBuffers");
m_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) m_gl_context->getProcAddress("glDeleteBuffers");
m_glBindBuffer = (PFNGLBINDBUFFERPROC) m_gl_context->getProcAddress("glBindBuffer");
m_glBufferData = (PFNGLBUFFERDATAPROC) m_gl_context->getProcAddress("glBufferData");
m_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) m_gl_context->getProcAddress("glBufferSubData");
m_gl_context->get_proc_address(m_glGenBuffers, "glGenBuffers");
m_gl_context->get_proc_address(m_glDeleteBuffers, "glDeleteBuffers");
m_gl_context->get_proc_address(m_glBindBuffer, "glBindBuffer");
m_gl_context->get_proc_address(m_glBufferData, "glBufferData");
m_gl_context->get_proc_address(m_glBufferSubData, "glBufferSubData");
}
// PBO:
if ( m_usepbo )
if (m_usepbo)
{
m_glMapBuffer = (PFNGLMAPBUFFERPROC) m_gl_context->getProcAddress("glMapBuffer");
m_glUnmapBuffer= (PFNGLUNMAPBUFFERPROC) m_gl_context->getProcAddress("glUnmapBuffer");
m_gl_context->get_proc_address(m_glMapBuffer, "glMapBuffer");
m_gl_context->get_proc_address(m_glUnmapBuffer, "glUnmapBuffer");
}
// FBO:
if ( m_usefbo )
if (m_usefbo)
{
m_glIsFramebuffer = (PFNGLISFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glIsFramebufferEXT");
m_glBindFramebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glBindFramebufferEXT");
m_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glDeleteFramebuffersEXT");
m_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glGenFramebuffersEXT");
m_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) m_gl_context->getProcAddress("glCheckFramebufferStatusEXT");
m_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) m_gl_context->getProcAddress("glFramebufferTexture2DEXT");
m_gl_context->get_proc_address(m_glIsFramebuffer, "glIsFramebufferEXT");
m_gl_context->get_proc_address(m_glBindFramebuffer, "glBindFramebufferEXT");
m_gl_context->get_proc_address(m_glDeleteFramebuffers, "glDeleteFramebuffersEXT");
m_gl_context->get_proc_address(m_glGenFramebuffers, "glGenFramebuffersEXT");
m_gl_context->get_proc_address(m_glCheckFramebufferStatus, "glCheckFramebufferStatusEXT");
m_gl_context->get_proc_address(m_glFramebufferTexture2D, "glFramebufferTexture2DEXT");
}
if ( m_usevbo &&
( !m_glGenBuffers || !m_glDeleteBuffers ||
!m_glBindBuffer || !m_glBufferData || !m_glBufferSubData
) )
if (m_usevbo && (!m_glGenBuffers || !m_glDeleteBuffers || !m_glBindBuffer || !m_glBufferData || !m_glBufferSubData))
{
m_usepbo=false;
m_usepbo = false;
if (_once)
{
osd_printf_warning("OpenGL: VBO not supported, missing: ");
osd_printf_warning("OpenGL: VBO not supported, missing:");
if (!m_glGenBuffers)
{
osd_printf_warning("glGenBuffers, ");
}
osd_printf_warning(" glGenBuffers");
if (!m_glDeleteBuffers)
{
osd_printf_warning("glDeleteBuffers");
}
osd_printf_warning(" glDeleteBuffers");
if (!m_glBindBuffer)
{
osd_printf_warning("glBindBuffer, ");
}
osd_printf_warning(" glBindBuffer");
if (!m_glBufferData)
{
osd_printf_warning("glBufferData, ");
}
osd_printf_warning(" glBufferData");
if (!m_glBufferSubData)
{
osd_printf_warning("glBufferSubData, ");
}
osd_printf_warning(" glBufferSubData");
osd_printf_warning("\n");
}
if ( m_usevbo )
if (m_usevbo)
{
if (_once)
{
osd_printf_warning("OpenGL: PBO not supported, no VBO support.\n");
}
m_usepbo=false;
m_usepbo = false;
}
}
if ( m_usepbo && ( !m_glMapBuffer || !m_glUnmapBuffer ) )
if (m_usepbo && (!m_glMapBuffer || !m_glUnmapBuffer))
{
m_usepbo=false;
m_usepbo = false;
if (_once)
{
osd_printf_warning("OpenGL: PBO not supported, missing: ");
osd_printf_warning("OpenGL: PBO not supported, missing:");
if (!m_glMapBuffer)
{
osd_printf_warning("glMapBuffer, ");
}
osd_printf_warning(" glMapBuffer");
if (!m_glUnmapBuffer)
{
osd_printf_warning("glUnmapBuffer, ");
}
osd_printf_warning(" glUnmapBuffer");
osd_printf_warning("\n");
}
}
@ -974,89 +979,68 @@ void renderer_ogl::loadGLExtensions()
!m_glGenFramebuffers || !m_glCheckFramebufferStatus || !m_glFramebufferTexture2D
))
{
m_usefbo=false;
m_usefbo = false;
if (_once)
{
osd_printf_warning("OpenGL: FBO not supported, missing: ");
osd_printf_warning("OpenGL: FBO not supported, missing:");
if (!m_glIsFramebuffer)
{
osd_printf_warning("m_glIsFramebuffer, ");
}
osd_printf_warning(" m_glIsFramebuffer");
if (!m_glBindFramebuffer)
{
osd_printf_warning("m_glBindFramebuffer, ");
}
osd_printf_warning(" m_glBindFramebuffer");
if (!m_glDeleteFramebuffers)
{
osd_printf_warning("m_glDeleteFramebuffers, ");
}
osd_printf_warning(" m_glDeleteFramebuffers");
if (!m_glGenFramebuffers)
{
osd_printf_warning("m_glGenFramebuffers, ");
}
osd_printf_warning(" m_glGenFramebuffers");
if (!m_glCheckFramebufferStatus)
{
osd_printf_warning("m_glCheckFramebufferStatus, ");
}
osd_printf_warning(" m_glCheckFramebufferStatus");
if (!m_glFramebufferTexture2D)
{
osd_printf_warning("m_glFramebufferTexture2D, ");
}
osd_printf_warning(" m_glFramebufferTexture2D");
osd_printf_warning("\n");
}
}
if (_once)
{
if ( m_usevbo )
{
if (m_usevbo)
osd_printf_verbose("OpenGL: VBO supported\n");
}
else
{
osd_printf_warning("OpenGL: VBO not supported\n");
}
if ( m_usepbo )
{
if (m_usepbo)
osd_printf_verbose("OpenGL: PBO supported\n");
}
else
{
osd_printf_warning("OpenGL: PBO not supported\n");
}
if ( m_usefbo )
{
if (m_usefbo)
osd_printf_verbose("OpenGL: FBO supported\n");
}
else
{
osd_printf_warning("OpenGL: FBO not supported\n");
}
}
if ( m_useglsl )
if (m_useglsl)
{
#if defined(GL_ARB_multitexture) && !defined(OSD_MAC)
m_glActiveTexture = (PFNGLACTIVETEXTUREARBPROC) m_gl_context->getProcAddress("glActiveTextureARB");
m_gl_context->get_proc_address(m_glActiveTexture, "glActiveTextureARB");
#else
m_glActiveTexture = (PFNGLACTIVETEXTUREPROC) m_gl_context->getProcAddress("glActiveTexture");
m_gl_context->get_proc_address(m_glActiveTexture, "glActiveTexture");
#endif
if (!m_glActiveTexture)
{
if (_once)
{
osd_printf_warning("OpenGL: GLSL disabled, glActiveTexture(ARB) not supported\n");
}
m_useglsl = 0;
}
}
if ( m_useglsl )
if (m_useglsl)
{
m_glsl = glsl_shader_init(m_gl_context.get());
m_useglsl = (m_glsl != nullptr ? 1 : 0);
m_shader_tool = glsl_shader_info::init(
*m_gl_context
#if defined(USE_DISPATCH_GL)
, gl_dispatch.get()
#endif
);
m_useglsl = (m_shader_tool ? 1 : 0);
if ( ! m_useglsl )
{
@ -1081,13 +1065,12 @@ void renderer_ogl::loadGLExtensions()
if (m_useglsl)
{
int i;
video_config.filter = false;
glsl_shader_feature = GLSL_SHADER_FEAT_PLAIN;
glsl_shader_feature = glsl_shader_info::FEAT_PLAIN;
m_glsl_program_num = 0;
m_glsl_program_mb2sc = 0;
for(i=0; i<m_ogl_config.glsl_shader_mamebm_num; i++)
for (int i=0; i<m_ogl_config.glsl_shader_mamebm_num; i++)
{
if ( !m_usefbo && m_glsl_program_num==1 )
{
@ -1098,12 +1081,14 @@ void renderer_ogl::loadGLExtensions()
break;
}
if ( glsl_shader_add_mamebm(m_glsl, m_ogl_config.glsl_shader_mamebm[i].c_str(), m_glsl_program_num) )
if ( m_shader_tool->add_mamebm(m_ogl_config.glsl_shader_mamebm[i].c_str(), m_glsl_program_num) )
{
osd_printf_error("OpenGL: GLSL loading mame bitmap shader %d failed (%s)\n",
i, m_ogl_config.glsl_shader_mamebm[i]);
} else {
glsl_shader_feature = GLSL_SHADER_FEAT_CUSTOM;
}
else
{
glsl_shader_feature = glsl_shader_info::FEAT_CUSTOM;
if (_once)
{
osd_printf_verbose("OpenGL: GLSL using mame bitmap shader filter %d: '%s'\n",
@ -1119,14 +1104,15 @@ void renderer_ogl::loadGLExtensions()
osd_printf_verbose("OpenGL: GLSL cannot use screen bitmap shader without bitmap shader\n");
}
for(i=0; m_usefbo && m_glsl_program_num>0 && i<m_ogl_config.glsl_shader_scrn_num; i++)
for(int i=0; m_usefbo && m_glsl_program_num>0 && i<m_ogl_config.glsl_shader_scrn_num; i++)
{
if ( glsl_shader_add_scrn(m_glsl, m_ogl_config.glsl_shader_scrn[i].c_str(),
m_glsl_program_num-1-m_glsl_program_mb2sc) )
if ( m_shader_tool->add_scrn(m_ogl_config.glsl_shader_scrn[i].c_str(), m_glsl_program_num-1-m_glsl_program_mb2sc) )
{
osd_printf_error("OpenGL: GLSL loading screen bitmap shader %d failed (%s)\n",
i, m_ogl_config.glsl_shader_scrn[i]);
} else {
}
else
{
if (_once)
{
osd_printf_verbose("OpenGL: GLSL using screen bitmap shader filter %d: '%s'\n",
@ -1137,7 +1123,7 @@ void renderer_ogl::loadGLExtensions()
}
if ( 0==m_glsl_program_num &&
0 <= m_ogl_config.glsl_filter && m_ogl_config.glsl_filter < GLSL_SHADER_FEAT_INT_NUMBER )
0 <= m_ogl_config.glsl_filter && m_ogl_config.glsl_filter < glsl_shader_info::FEAT_INT_NUMBER )
{
m_glsl_program_mb2sc = m_glsl_program_num; // the last mame_bitmap (mb) shader does it.
m_glsl_program_num++;
@ -1146,12 +1132,14 @@ void renderer_ogl::loadGLExtensions()
if (_once)
{
osd_printf_verbose("OpenGL: GLSL using shader filter '%s', idx: %d, num %d (vid filter: %d)\n",
glsl_shader_get_filter_name_mamebm(glsl_shader_feature),
m_shader_tool->get_filter_name_mamebm(glsl_shader_feature),
glsl_shader_feature, m_glsl_program_num, video_config.filter);
}
}
} else {
}
else
{
if (_once)
{
osd_printf_verbose("OpenGL: using vid filter: %d\n", video_config.filter);
@ -1183,7 +1171,7 @@ int renderer_ogl::draw(const int update)
clear_flags(FI_CHANGED);
}
m_gl_context->MakeCurrent();
m_gl_context->make_current();
if (m_init_context)
{
@ -1540,7 +1528,7 @@ int renderer_ogl::draw(const int update)
window().m_primlist->release_lock();
m_init_context = 0;
m_gl_context->SwapBuffer();
m_gl_context->swap_buffer();
return 0;
}
@ -1818,7 +1806,7 @@ int renderer_ogl::texture_fbo_create(uint32_t text_unit, uint32_t text_name, uin
glBindTexture(GL_TEXTURE_2D, text_name);
{
GLint _width, _height;
if ( gl_texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
if ( m_shader_tool->texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &_width, &_height, 1) )
{
osd_printf_error("cannot create fbo texture, req: %dx%d, avail: %dx%d - bail out\n",
@ -1873,45 +1861,43 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex
for(i=0; i<m_glsl_program_num; i++)
{
if ( i<=m_glsl_program_mb2sc )
{
m_glsl_program[i] = glsl_shader_get_program_mamebm(glsl_shader_feature, i);
} else {
m_glsl_program[i] = glsl_shader_get_program_scrn(i-1-m_glsl_program_mb2sc);
}
pfn_glUseProgramObjectARB(m_glsl_program[i]);
m_glsl_program[i] = m_shader_tool->get_program_mamebm(glsl_shader_feature, i);
else
m_glsl_program[i] = m_shader_tool->get_program_scrn(i-1-m_glsl_program_mb2sc);
m_shader_tool->pfn_glUseProgramObjectARB(m_glsl_program[i]);
if ( i<=m_glsl_program_mb2sc )
{
// GL_TEXTURE0 GLSL Uniforms
uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture");
pfn_glUniform1iARB(uniform_location, 0);
uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture");
m_shader_tool->pfn_glUniform1iARB(uniform_location, 0);
GL_CHECK_ERROR_NORMAL();
}
{
GLfloat color_texture_sz[2] = { (GLfloat)texture->rawwidth, (GLfloat)texture->rawheight };
uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_sz");
pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_sz[0]));
uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_sz");
m_shader_tool->pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_sz[0]));
GL_CHECK_ERROR_NORMAL();
}
GLfloat color_texture_pow2_sz[2] = { (GLfloat)texture->rawwidth_create, (GLfloat)texture->rawheight_create };
uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_pow2_sz");
pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_pow2_sz[0]));
uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_pow2_sz");
m_shader_tool->pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_pow2_sz[0]));
GL_CHECK_ERROR_NORMAL();
GLfloat screen_texture_sz[2] = { (GLfloat) m_blit_dim.width(), (GLfloat) m_blit_dim.height() };
uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_sz");
pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_sz[0]));
uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_sz");
m_shader_tool->pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_sz[0]));
GL_CHECK_ERROR_NORMAL();
GLfloat screen_texture_pow2_sz[2] = { (GLfloat)surf_w_pow2, (GLfloat)surf_h_pow2 };
uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_pow2_sz");
pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_pow2_sz[0]));
uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_pow2_sz");
m_shader_tool->pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_pow2_sz[0]));
GL_CHECK_ERROR_NORMAL();
}
pfn_glUseProgramObjectARB(m_glsl_program[0]); // start with 1st shader
m_shader_tool->pfn_glUseProgramObjectARB(m_glsl_program[0]); // start with 1st shader
if( m_glsl_program_num > 1 )
{
@ -1969,7 +1955,7 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex
uint32_t * dummy = nullptr;
GLint _width, _height;
if ( gl_texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8,
if ( m_shader_tool->texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8,
texture->rawwidth_create, texture->rawheight_create,
0,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
@ -1991,7 +1977,7 @@ int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_tex
if ((PRIMFLAG_GET_SCREENTEX(flags)) && video_config.filter)
{
assert( glsl_shader_feature == GLSL_SHADER_FEAT_PLAIN );
assert( glsl_shader_feature == glsl_shader_info::FEAT_PLAIN );
// screen textures get the user's choice of filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@ -2026,7 +2012,11 @@ ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource,
ogl_texture_info *texture;
// allocate a new texture
texture = new ogl_texture_info;
texture = new ogl_texture_info(
#if defined(USE_DISPATCH_GL)
gl_dispatch.get()
#endif
);
// fill in the core data
texture->hash = texture_compute_hash(texsource, flags);
@ -2090,7 +2080,7 @@ ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource,
if ( texture->type != TEXTURE_TYPE_SHADER && m_useglsl)
{
pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
m_shader_tool->pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
}
if ( texture->type==TEXTURE_TYPE_SHADER )
@ -2697,8 +2687,8 @@ void renderer_ogl::texture_mpass_flip(ogl_texture_info *texture, int shaderIdx)
if ( shaderIdx>0 )
{
int uniform_location;
uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "mpass_texture");
pfn_glUniform1iARB(uniform_location, texture->mpass_textureunit[mpass_src_idx]-GL_TEXTURE0);
uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "mpass_texture");
m_shader_tool->pfn_glUniform1iARB(uniform_location, texture->mpass_textureunit[mpass_src_idx]-GL_TEXTURE0);
GL_CHECK_ERROR_NORMAL();
}
@ -2776,8 +2766,8 @@ void renderer_ogl::texture_shader_update(ogl_texture_info *texture, render_conta
vid_attributes[1] = settings.m_contrast;
vid_attributes[2] = settings.m_brightness;
vid_attributes[3] = 0.0f;
uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "vid_attributes");
pfn_glUniform4fvARB(uniform_location, 1, &(vid_attributes[shaderIdx]));
uniform_location = m_shader_tool->pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "vid_attributes");
m_shader_tool->pfn_glUniform4fvARB(uniform_location, 1, &(vid_attributes[shaderIdx]));
if ( GL_CHECK_ERROR_QUIET() ) {
osd_printf_verbose("GLSL: could not set 'vid_attributes' for shader prog idx %d\n", shaderIdx);
}
@ -2798,7 +2788,7 @@ ogl_texture_info * renderer_ogl::texture_update(const render_primitive *prim, in
{
if ( texture->type == TEXTURE_TYPE_SHADER )
{
pfn_glUseProgramObjectARB(m_glsl_program[shaderIdx]); // back to our shader
m_shader_tool->pfn_glUseProgramObjectARB(m_glsl_program[shaderIdx]); // back to our shader
}
else if ( texture->type == TEXTURE_TYPE_DYNAMIC )
{
@ -2862,7 +2852,7 @@ void renderer_ogl::texture_disable(ogl_texture_info * texture)
if ( texture->type == TEXTURE_TYPE_SHADER )
{
assert ( m_useglsl );
pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
m_shader_tool->pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
}
else if ( texture->type == TEXTURE_TYPE_DYNAMIC )
{
@ -2877,22 +2867,26 @@ void renderer_ogl::texture_disable(ogl_texture_info * texture)
void renderer_ogl::texture_all_disable()
{
if ( m_useglsl )
if (m_useglsl)
{
pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
m_shader_tool->pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
m_glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, 0);
if ( m_usefbo ) m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
if (m_usefbo)
m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
m_glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, 0);
if ( m_usefbo ) m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
if (m_usefbo)
m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
m_glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
if ( m_usefbo ) m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
if (m_usefbo)
m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
m_glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
if ( m_usefbo ) m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
if (m_usefbo)
m_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
@ -2919,7 +2913,7 @@ class video_opengl : public osd_module, public render_module
public:
video_opengl()
: osd_module(OSD_RENDERER_PROVIDER, "opengl")
#ifdef USE_DISPATCH_GL
#if defined(USE_DISPATCH_GL)
, m_dll_loaded(false)
#endif
{
@ -2936,8 +2930,7 @@ protected:
private:
ogl_video_config m_ogl_config;
#ifdef USE_DISPATCH_GL
std::unique_ptr<osd_gl_dispatch> m_gl_dispatch;
#if defined(USE_DISPATCH_GL)
bool m_dll_loaded;
#endif
};
@ -3001,7 +2994,6 @@ int video_opengl::init(osd_interface &osd, osd_options const &options)
}
#endif // defined(OSD_SDL)
m_dll_loaded = true;
m_gl_dispatch = std::make_unique<osd_gl_dispatch>();
#endif // defined(USE_DISPATCH_GL)
#if defined(OSD_WINDOWS)
@ -3020,7 +3012,6 @@ void video_opengl::exit()
if (m_dll_loaded)
SDL_GL_UnloadLibrary();
#endif // defined(OSD_SDL)
m_gl_dispatch.reset();
m_dll_loaded = false;
#endif // defined(USE_DISPATCH_GL)

View File

@ -8,61 +8,76 @@
//
//============================================================
#ifndef MAME_RENDER_SDLGLCONTEXT_H
#define MAME_RENDER_SDLGLCONTEXT_H
#pragma once
#ifndef __SDL_GL_CONTEXT__
#define __SDL_GL_CONTEXT__
#include "modules/opengl/osd_opengl.h"
#include "strformat.h"
#include <SDL2/SDL.h>
#include "modules/opengl/osd_opengl.h"
#include <string>
class sdl_gl_context : public osd_gl_context
{
public:
sdl_gl_context(SDL_Window *window) : osd_gl_context(), m_context(0), m_window(window)
sdl_gl_context(SDL_Window *window) : m_context(0), m_window(window)
{
m_error[0] = 0;
m_context = SDL_GL_CreateContext(window);
if (!m_context)
if (!m_context)
{
snprintf(m_error,255, "OpenGL not supported on this driver: %s", SDL_GetError());
try { m_error = util::string_format("OpenGL not supported on this driver: %s", SDL_GetError()); }
catch (...) { m_error.clear(); }
}
}
virtual ~sdl_gl_context()
{
SDL_GL_DeleteContext(m_context);
if (m_context)
SDL_GL_DeleteContext(m_context);
}
virtual void MakeCurrent() override
virtual explicit operator bool() const
{
return bool(m_context);
}
virtual void make_current() override
{
SDL_GL_MakeCurrent(m_window, m_context);
}
virtual int SetSwapInterval(const int swap) override
virtual bool set_swap_interval(const int swap) override
{
return SDL_GL_SetSwapInterval(swap);
return 0 == SDL_GL_SetSwapInterval(swap);
}
virtual const char *LastErrorMsg() override
virtual const char *last_error_message() override
{
if (m_error[0] == 0)
return nullptr;
if (!m_error.empty())
return m_error.c_str();
else
return m_error;
return nullptr;
}
virtual void *getProcAddress(const char *proc) override
virtual void *get_proc_address(const char *proc) override
{
return SDL_GL_GetProcAddress(proc);
}
virtual void SwapBuffer() override
virtual void swap_buffer() override
{
SDL_GL_SwapWindow(m_window);
}
private:
SDL_GLContext m_context;
SDL_Window *m_window;
char m_error[256];
SDL_Window *const m_window;
std::string m_error;
};
#endif // __SDL_GL_CONTEXT__
#endif // MAME_RENDER_SDLGLCONTEXT_H

View File

@ -7,168 +7,197 @@
// SDLMAME by Olivier Galibert and R. Belmont
//
//============================================================
#ifndef MAME_RENDER_WINGLCONTEXT_H
#define MAME_RENDER_WINGLCONTEXT_H
#pragma once
#ifndef __WIN_GL_CONTEXT__
#define __WIN_GL_CONTEXT__
#include "modules/opengl/osd_opengl.h"
#include "modules/lib/osdlib.h"
// Typedefs for dynamically loaded functions
typedef PROC (WINAPI *wglGetProcAddress_fn)(LPCSTR);
typedef HGLRC (WINAPI *wglCreateContext_fn)(HDC);
typedef BOOL (WINAPI *wglDeleteContext_fn)(HGLRC);
typedef BOOL (WINAPI *wglMakeCurrent_fn)(HDC, HGLRC);
#include "strconv.h"
#include <cstring>
#include <string>
typedef const char * (WINAPI *wglGetExtensionsStringEXT_fn)(void);
typedef BOOL (WINAPI *wglSwapIntervalEXT_fn)(int);
typedef int (WINAPI *wglGetSwapIntervalEXT_fn)(void);
class win_gl_context : public osd_gl_context
{
public:
win_gl_context(HWND window) : osd_gl_context(), m_context(0), m_window(nullptr), m_hdc(0)
using osd_gl_context::get_proc_address;
win_gl_context(HWND window) : m_context(nullptr), m_window(window), m_hdc(nullptr)
{
m_error[0] = 0;
// open DLL and bind required functions
opengl32_dll = osd::dynamic_module::open({ "opengl32.dll" });
pfn_wglGetProcAddress = opengl32_dll->bind<wglGetProcAddress_fn>("wglGetProcAddress");
pfn_wglCreateContext = opengl32_dll->bind<wglCreateContext_fn>("wglCreateContext");
pfn_wglDeleteContext = opengl32_dll->bind<wglDeleteContext_fn>("wglDeleteContext");
pfn_wglMakeCurrent = opengl32_dll->bind<wglMakeCurrent_fn>("wglMakeCurrent");
if (!pfn_wglGetProcAddress || !pfn_wglCreateContext || !pfn_wglDeleteContext || !pfn_wglMakeCurrent)
return;
if (pfn_wglGetProcAddress == nullptr || pfn_wglCreateContext == nullptr ||
pfn_wglDeleteContext == nullptr || pfn_wglMakeCurrent == nullptr)
m_hdc = GetDC(window);
if (!m_hdc)
{
get_last_error_string();
return;
}
pfn_wglGetExtensionsStringEXT = (wglGetExtensionsStringEXT_fn)(*pfn_wglGetProcAddress)("wglGetExtensionsStringEXT");
if (setupPixelFormat())
{
m_context = (*pfn_wglCreateContext)(m_hdc);
if (!m_context)
get_last_error_string();
}
if (!m_context)
return;
(*pfn_wglMakeCurrent)(m_hdc, m_context);
get_proc_address(pfn_wglGetExtensionsStringEXT, "wglGetExtensionsStringEXT");
if (WGLExtensionSupported("WGL_EXT_swap_control"))
{
pfn_wglSwapIntervalEXT = (BOOL (WINAPI *) (int)) getProcAddress("wglSwapIntervalEXT");
pfn_wglGetSwapIntervalEXT = (int (WINAPI *) (void)) getProcAddress("wglGetSwapIntervalEXT");
get_proc_address(pfn_wglSwapIntervalEXT, "wglSwapIntervalEXT");
get_proc_address(pfn_wglGetSwapIntervalEXT, "wglGetSwapIntervalEXT");
}
else
{
pfn_wglSwapIntervalEXT = nullptr;
pfn_wglGetSwapIntervalEXT = nullptr;
}
m_hdc = GetDC(window);
if (!setupPixelFormat(m_hdc))
{
m_context = (*pfn_wglCreateContext)(m_hdc);
if (!m_context)
{
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, GetLastError(), 0, m_error, 255, nullptr);
return;
}
(*pfn_wglMakeCurrent)(m_hdc, m_context);
}
}
virtual ~win_gl_context()
{
(*pfn_wglDeleteContext)(m_context);
ReleaseDC(m_window, m_hdc);
if (m_context)
(*pfn_wglDeleteContext)(m_context);
if (m_hdc)
ReleaseDC(m_window, m_hdc);
}
virtual void MakeCurrent() override
virtual explicit operator bool() const override
{
return bool(m_context);
}
virtual void make_current() override
{
(*pfn_wglMakeCurrent)(m_hdc, m_context);
}
virtual const char *LastErrorMsg() override
virtual const char *last_error_message() override
{
if (m_error[0] == 0)
return nullptr;
if (!m_error.empty())
return m_error.c_str();
else
return m_error;
return nullptr;
}
virtual void *getProcAddress(const char *proc) override
virtual void *get_proc_address(const char *proc) override
{
return (void *)(*pfn_wglGetProcAddress)(proc);
return reinterpret_cast<void *>(uintptr_t((*pfn_wglGetProcAddress)(proc)));
}
virtual int SetSwapInterval(const int swap) override
virtual bool set_swap_interval(const int swap) override
{
if (pfn_wglSwapIntervalEXT != nullptr)
{
pfn_wglSwapIntervalEXT(swap ? 1 : 0);
}
return 0;
if (!pfn_wglSwapIntervalEXT)
return false;
pfn_wglSwapIntervalEXT(swap ? 1 : 0);
return true;
}
virtual void SwapBuffer() override
virtual void swap_buffer() override
{
SwapBuffers(m_hdc);
//wglSwapLayerBuffers(GetDC(window().m_hwnd), WGL_SWAP_MAIN_PLANE);
}
private:
// Typedefs for dynamically loaded functions
typedef PROC (WINAPI *wglGetProcAddress_fn)(LPCSTR);
typedef HGLRC (WINAPI *wglCreateContext_fn)(HDC);
typedef BOOL (WINAPI *wglDeleteContext_fn)(HGLRC);
typedef BOOL (WINAPI *wglMakeCurrent_fn)(HDC, HGLRC);
int setupPixelFormat(HDC hDC)
typedef const char * (WINAPI *wglGetExtensionsStringEXT_fn)();
typedef BOOL (WINAPI *wglSwapIntervalEXT_fn)(int);
typedef int (WINAPI *wglGetSwapIntervalEXT_fn)();
bool setupPixelFormat()
{
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), /* size */
1, /* version */
PFD_SUPPORT_OPENGL |
PFD_DRAW_TO_WINDOW |
PFD_DOUBLEBUFFER, /* support double-buffering */
PFD_TYPE_RGBA, /* color type */
32, /* prefered color depth */
0, 0, 0, 0, 0, 0, /* color bits (ignored) */
0, /* no alpha buffer */
0, /* alpha bits (ignored) */
0, /* no accumulation buffer */
0, 0, 0, 0, /* accum bits (ignored) */
16, /* depth buffer */
0, /* no stencil buffer */
0, /* no auxiliary buffers */
PFD_MAIN_PLANE, /* main layer */
0, /* reserved */
0, 0, 0, /* no layer, visible, damage masks */
};
int pixelFormat = ChoosePixelFormat(hDC, &pfd);
sizeof(PIXELFORMATDESCRIPTOR), // size
1, // version
PFD_SUPPORT_OPENGL |
PFD_DRAW_TO_WINDOW |
PFD_DOUBLEBUFFER, // support double-buffering
PFD_TYPE_RGBA, // color type
32, // prefered color depth
0, 0, 0, 0, 0, 0, // color bits (ignored)
0, // no alpha buffer
0, // alpha bits (ignored)
0, // no accumulation buffer
0, 0, 0, 0, // accum bits (ignored)
16, // depth buffer
0, // no stencil buffer
0, // no auxiliary buffers
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0, // no layer, visible, damage masks
};
const int pixelFormat = ChoosePixelFormat(m_hdc, &pfd);
if (pixelFormat == 0)
{
strcpy(m_error, "ChoosePixelFormat failed.");
return 1;
get_last_error_string();
return false;
}
if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE)
if (SetPixelFormat(m_hdc, pixelFormat, &pfd) != TRUE)
{
strcpy(m_error, "SetPixelFormat failed.");
return 1;
get_last_error_string();
return false;
}
return 0;
return true;
}
bool WGLExtensionSupported(const char *extension_name)
{
if (pfn_wglGetExtensionsStringEXT == nullptr)
if (!pfn_wglGetExtensionsStringEXT)
return false;
// printf("%s\n", pfn_wglGetExtensionsStringEXT());
return strstr(pfn_wglGetExtensionsStringEXT(), extension_name) != nullptr;
}
if (strstr(pfn_wglGetExtensionsStringEXT(), extension_name) != nullptr)
return true;
else
return false;
void get_last_error_string()
{
LPTSTR buffer = nullptr;
const auto result = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
nullptr,
GetLastError(),
0,
LPTSTR(&buffer),
0,
nullptr);
if (!result || !buffer)
{
m_error.clear();
return;
}
try { m_error = osd::text::from_tstring(buffer); }
catch (...) { m_error.clear(); }
LocalFree(buffer);
}
HGLRC m_context;
HWND m_window;
HWND const m_window;
HDC m_hdc;
char m_error[256];
std::string m_error;
osd::dynamic_module::ptr opengl32_dll;
wglGetProcAddress_fn pfn_wglGetProcAddress;
@ -181,4 +210,4 @@ private:
wglGetSwapIntervalEXT_fn pfn_wglGetSwapIntervalEXT;
};
#endif // __WIN_GL_CONTEXT__
#endif // MAME_RENDER_WINGLCONTEXT_H