mirror of
https://github.com/mpv-player/mpv
synced 2025-01-02 04:42:10 +00:00
vo_gl3: make it work on OpenGL 2.1
Now vo_gl3 should work with standard OpenGL 2.1, as long as the GL_ARB_texture_rg extension is available. Optional features, which require features that are always in OpenGL 3.0, but are available as extensions only in OpenGL 2.1, are automatically disabled. The force-gl2 suboption, which was an unreliable hack to run vo_gl3 in an OpenGL 2.1 context, is removed. Significant changes are done to the extension loader to make it easier to identify optional OpenGL features. Context creation is a bit changed to simplify the code and to handle the fallback better if OpenGL 3 context creation fails, and creating an OpenGL legacy context is attempted. Based on the initial work by Rudolf Polzer <divverent@xonotic.org>, which included making the shader GLSL 1.20 compatible, and more.
This commit is contained in:
parent
db565ca4f8
commit
a0b43a11e4
@ -413,6 +413,9 @@ gl
|
||||
enabled). This option is for testing; to disable the OSD use
|
||||
``--osdlevel=0`` instead.
|
||||
|
||||
sw
|
||||
Continue even if a software renderer is detected.
|
||||
|
||||
backend=<sys>
|
||||
auto
|
||||
auto-select (default)
|
||||
@ -424,9 +427,7 @@ gl
|
||||
X11/GLX
|
||||
|
||||
gl3
|
||||
OpenGL video output driver, extended version. The requires an OpenGL 3
|
||||
capable graphics driver. (Note: this is only because of developer pedantry.
|
||||
The dependency on actual OpenGL 3 features is rather low.)
|
||||
OpenGL video output driver, extended version.
|
||||
|
||||
It supports extended scaling methods, dithering and color management.
|
||||
It tries to use sane defaults for good quality output.
|
||||
@ -434,6 +435,8 @@ gl3
|
||||
Note that some cheaper LCDs do dithering that gravely interferes with
|
||||
vo_gl3's dithering. Disabling dithering with ``dither-depth=-1`` helps.
|
||||
|
||||
Some features are available with OpenGL 3 capable graphics drivers only.
|
||||
|
||||
lscale=<filter>
|
||||
Set the scaling filter. Possible choices:
|
||||
bilinear
|
||||
@ -579,6 +582,9 @@ gl3
|
||||
glfinish
|
||||
Call glFinish() before swapping buffers
|
||||
|
||||
sw
|
||||
Continue even if a software renderer is detected.
|
||||
|
||||
backend=<sys>
|
||||
auto
|
||||
auto-select (default)
|
||||
@ -600,16 +606,12 @@ gl3
|
||||
|
||||
fbo-format=<fmt>
|
||||
Selects the internal format of any FBO textures used.
|
||||
fmt can be one of: rgb, rgba, rgb8, rgb16, rgb16f, rgb32f
|
||||
fmt can be one of: rgb, rgba, rgb8, rgb10, rgb16, rgb16f, rgb32f
|
||||
Default: rgb16.
|
||||
|
||||
gamma
|
||||
Always enable gamma control. (Disables delayed enabling.)
|
||||
|
||||
force-gl2
|
||||
Create a legacy GL context. This will randomly malfunction
|
||||
if the proper extensions are not supported.
|
||||
|
||||
icc-profile=<file>
|
||||
Load an ICC profile and use it to transform linear RGB to
|
||||
screen output. Needs LittleCMS2 support compiled in.
|
||||
|
1134
libvo/gl_common.c
1134
libvo/gl_common.c
File diff suppressed because it is too large
Load Diff
@ -153,16 +153,6 @@ void glEnable3DLeft(GL *gl, int type);
|
||||
void glEnable3DRight(GL *gl, int type);
|
||||
void glDisable3D(GL *gl, int type);
|
||||
|
||||
/** \addtogroup glcontext
|
||||
* \{ */
|
||||
//! could not set new window, will continue drawing into the old one.
|
||||
#define SET_WINDOW_FAILED -1
|
||||
//! new window is set, could even transfer the OpenGL context.
|
||||
#define SET_WINDOW_OK 0
|
||||
//! new window is set, but the OpenGL context needs to be reinitialized.
|
||||
#define SET_WINDOW_REINIT 1
|
||||
/** \} */
|
||||
|
||||
enum MPGLType {
|
||||
GLTYPE_AUTO,
|
||||
GLTYPE_COCOA,
|
||||
@ -171,49 +161,82 @@ enum MPGLType {
|
||||
};
|
||||
|
||||
enum {
|
||||
MPGLFLAG_DEBUG = 1,
|
||||
MPGL_CAP_GL = (1 << 0), // GL was successfully loaded
|
||||
MPGL_CAP_GL_LEGACY = (1 << 1), // GL 1.1 (but not 3.x)
|
||||
MPGL_CAP_GL2 = (1 << 2), // GL 2.0 (3.x core subset)
|
||||
MPGL_CAP_GL21 = (1 << 3), // GL 2.1 (3.x core subset)
|
||||
MPGL_CAP_GL3 = (1 << 4), // GL 3.x core
|
||||
MPGL_CAP_FB = (1 << 5),
|
||||
MPGL_CAP_VAO = (1 << 6),
|
||||
MPGL_CAP_SRGB_TEX = (1 << 7),
|
||||
MPGL_CAP_SRGB_FB = (1 << 8),
|
||||
MPGL_CAP_FLOAT_TEX = (1 << 9),
|
||||
MPGL_CAP_TEX_RG = (1 << 10), // GL_ARB_texture_rg / GL 3.x
|
||||
MPGL_CAP_NO_SW = (1 << 30), // used to block sw. renderers
|
||||
};
|
||||
|
||||
#define MPGL_VER(major, minor) (((major) << 16) | (minor))
|
||||
#define MPGL_VER_GET_MAJOR(ver) ((ver) >> 16)
|
||||
#define MPGL_VER_GET_MINOR(ver) ((ver) & ((1 << 16) - 1))
|
||||
|
||||
#define MPGL_VER_P(ver) MPGL_VER_GET_MAJOR(ver), MPGL_VER_GET_MINOR(ver)
|
||||
|
||||
typedef struct MPGLContext {
|
||||
GL *gl;
|
||||
enum MPGLType type;
|
||||
struct vo *vo;
|
||||
void *priv;
|
||||
|
||||
// Bit size of each component in the created framebuffer. 0 if unknown.
|
||||
int depth_r, depth_g, depth_b;
|
||||
int (*create_window)(struct MPGLContext *ctx, uint32_t d_width,
|
||||
uint32_t d_height, uint32_t flags);
|
||||
int (*setGlWindow)(struct MPGLContext *);
|
||||
void (*releaseGlContext)(struct MPGLContext *);
|
||||
|
||||
// GL version requested from create_window_gl3 backend.
|
||||
// (Might be different from the actual version in gl->version.)
|
||||
int requested_gl_version;
|
||||
|
||||
void (*swapGlBuffers)(struct MPGLContext *);
|
||||
int (*check_events)(struct vo *vo);
|
||||
void (*fullscreen)(struct vo *vo);
|
||||
int (*vo_init)(struct vo *vo);
|
||||
void (*vo_uninit)(struct vo *vo);
|
||||
// only available if GL3 context creation is supported
|
||||
// gl_flags: bitfield of MPGLFLAG_* constants
|
||||
// gl_version: requested OpenGL version number (use MPGL_VER())
|
||||
// return value is one of the SET_WINDOW_* constants
|
||||
int (*create_window_gl3)(struct MPGLContext *ctx, int gl_flags,
|
||||
int gl_version, uint32_t d_width,
|
||||
uint32_t d_height, uint32_t flags);
|
||||
void (*releaseGlContext)(struct MPGLContext *);
|
||||
|
||||
// Creates GL 1.x/2.x legacy context.
|
||||
bool (*create_window_old)(struct MPGLContext *ctx, uint32_t d_width,
|
||||
uint32_t d_height, uint32_t flags);
|
||||
|
||||
// Creates GL 3.x core context.
|
||||
bool (*create_window_gl3)(struct MPGLContext *ctx, uint32_t d_width,
|
||||
uint32_t d_height, uint32_t flags);
|
||||
|
||||
// optional
|
||||
void (*ontop)(struct vo *vo);
|
||||
void (*border)(struct vo *vo);
|
||||
void (*update_xinerama_info)(struct vo *vo);
|
||||
|
||||
// For free use by the backend.
|
||||
void *priv;
|
||||
// Internal to gl_common.c.
|
||||
bool (*selected_create_window)(struct MPGLContext *ctx, uint32_t d_width,
|
||||
uint32_t d_height, uint32_t flags);
|
||||
bool vo_init_ok;
|
||||
} MPGLContext;
|
||||
|
||||
int mpgl_find_backend(const char *name);
|
||||
|
||||
MPGLContext *init_mpglcontext(enum MPGLType type, struct vo *vo);
|
||||
void uninit_mpglcontext(MPGLContext *ctx);
|
||||
MPGLContext *mpgl_init(enum MPGLType type, struct vo *vo);
|
||||
void mpgl_uninit(MPGLContext *ctx);
|
||||
|
||||
// calls create_window_gl3 or create_window+setGlWindow
|
||||
int create_mpglcontext(struct MPGLContext *ctx, int gl_flags, int gl_version,
|
||||
uint32_t d_width, uint32_t d_height, uint32_t flags);
|
||||
// Create a VO window and create a GL context on it.
|
||||
// (Calls create_window_gl3 or create_window+setGlWindow.)
|
||||
// gl_caps: bitfield of MPGL_CAP_* (required GL version and feature set)
|
||||
// flags: passed to the backend's create window function
|
||||
// Returns success.
|
||||
bool mpgl_create_window(struct MPGLContext *ctx, int gl_caps, uint32_t d_width,
|
||||
uint32_t d_height, uint32_t flags);
|
||||
|
||||
// Destroy the window, without resetting GL3 vs. GL2 context choice.
|
||||
// If this fails (false), mpgl_uninit(ctx) must be called.
|
||||
bool mpgl_destroy_window(struct MPGLContext *ctx);
|
||||
|
||||
// print a multi line string with line numbers (e.g. for shader sources)
|
||||
// mod, lev: module and log level, as in mp_msg()
|
||||
@ -221,6 +244,11 @@ void mp_log_source(int mod, int lev, const char *src);
|
||||
|
||||
//function pointers loaded from the OpenGL library
|
||||
struct GL {
|
||||
int version; // MPGL_VER() mangled
|
||||
int glsl_version; // e.g. 130 for GLSL 1.30
|
||||
char *extensions; // Equivalent to GL_EXTENSIONS
|
||||
int mpgl_caps; // Bitfield of MPGL_CAP_* constants
|
||||
|
||||
void (GLAPIENTRY *Begin)(GLenum);
|
||||
void (GLAPIENTRY *End)(void);
|
||||
void (GLAPIENTRY *Viewport)(GLint, GLint, GLsizei, GLsizei);
|
||||
@ -281,8 +309,6 @@ struct GL {
|
||||
void (GLAPIENTRY *DisableClientState)(GLenum);
|
||||
GLenum (GLAPIENTRY *GetError)(void);
|
||||
|
||||
|
||||
// OpenGL extension functions
|
||||
void (GLAPIENTRY *GenBuffers)(GLsizei, GLuint *);
|
||||
void (GLAPIENTRY *DeleteBuffers)(GLsizei, const GLuint *);
|
||||
void (GLAPIENTRY *BindBuffer)(GLenum, GLuint);
|
||||
@ -304,7 +330,6 @@ struct GL {
|
||||
GLsizei, GLint, GLenum, GLenum,
|
||||
const GLvoid *);
|
||||
|
||||
// ancient ATI extensions
|
||||
void (GLAPIENTRY *BeginFragmentShader)(void);
|
||||
void (GLAPIENTRY *EndFragmentShader)(void);
|
||||
void (GLAPIENTRY *SampleMap)(GLuint, GLuint, GLenum);
|
||||
@ -315,8 +340,6 @@ struct GL {
|
||||
GLuint, GLuint, GLuint);
|
||||
void (GLAPIENTRY *SetFragmentShaderConstant)(GLuint, const GLfloat *);
|
||||
|
||||
|
||||
// GL 3, possibly in GL 2.x as well in form of extensions
|
||||
void (GLAPIENTRY *GenVertexArrays)(GLsizei, GLuint *);
|
||||
void (GLAPIENTRY *BindVertexArray)(GLuint);
|
||||
GLint (GLAPIENTRY *GetAttribLocation)(GLuint, const GLchar *);
|
||||
@ -350,6 +373,7 @@ struct GL {
|
||||
GLint);
|
||||
|
||||
void (GLAPIENTRY *Uniform1f)(GLint, GLfloat);
|
||||
void (GLAPIENTRY *Uniform2f)(GLint, GLfloat, GLfloat);
|
||||
void (GLAPIENTRY *Uniform3f)(GLint, GLfloat, GLfloat, GLfloat);
|
||||
void (GLAPIENTRY *Uniform1i)(GLint, GLint);
|
||||
void (GLAPIENTRY *UniformMatrix3fv)(GLint, GLsizei, GLboolean,
|
||||
|
@ -126,6 +126,7 @@ typedef struct {
|
||||
#define VOFLAG_FLIPPING 0x08
|
||||
#define VOFLAG_HIDDEN 0x10 //< Use to create a hidden window
|
||||
#define VOFLAG_STEREO 0x20 //< Use to create a stereo-capable window
|
||||
#define VOFLAG_GL_DEBUG 0x40 // Hint to request debug OpenGL context
|
||||
|
||||
typedef struct vo_info_s
|
||||
{
|
||||
|
@ -154,9 +154,8 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
|
||||
p->image_width = width;
|
||||
p->image_height = height;
|
||||
|
||||
if (p->mpglctx->create_window(p->mpglctx, d_width, d_height, flags) < 0)
|
||||
return -1;
|
||||
if (p->mpglctx->setGlWindow(p->mpglctx) == SET_WINDOW_FAILED)
|
||||
int mpgl_caps = MPGL_CAP_GL_LEGACY;
|
||||
if (!mpgl_create_window(p->mpglctx, mpgl_caps, d_width, d_height, flags))
|
||||
return -1;
|
||||
|
||||
init_gl(vo, vo->dwidth, vo->dheight);
|
||||
@ -367,7 +366,7 @@ static int query_format(struct vo *vo, uint32_t format)
|
||||
static void uninit(struct vo *vo)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
uninit_mpglcontext(p->mpglctx);
|
||||
mpgl_uninit(p->mpglctx);
|
||||
release_cv_entities(vo);
|
||||
}
|
||||
|
||||
@ -377,7 +376,7 @@ static int preinit(struct vo *vo, const char *arg)
|
||||
struct priv *p = vo->priv;
|
||||
|
||||
*p = (struct priv) {
|
||||
.mpglctx = init_mpglcontext(GLTYPE_COCOA, vo),
|
||||
.mpglctx = mpgl_init(GLTYPE_COCOA, vo),
|
||||
.colorspace = MP_CSP_DETAILS_DEFAULTS,
|
||||
.quad = talloc_ptrtype(p, p->quad),
|
||||
.osd = talloc_ptrtype(p, p->osd),
|
||||
|
@ -62,6 +62,8 @@ struct gl_priv {
|
||||
MPGLContext *glctx;
|
||||
GL *gl;
|
||||
|
||||
int allow_sw;
|
||||
|
||||
int use_osd;
|
||||
int scaled_osd;
|
||||
//! Textures for OSD
|
||||
@ -388,6 +390,9 @@ static void uninitGl(struct vo *vo)
|
||||
struct gl_priv *p = vo->priv;
|
||||
GL *gl = p->gl;
|
||||
|
||||
if (!gl)
|
||||
return;
|
||||
|
||||
int i = 0;
|
||||
if (gl->DeletePrograms && p->fragprog)
|
||||
gl->DeletePrograms(1, &p->fragprog);
|
||||
@ -415,16 +420,6 @@ static void uninitGl(struct vo *vo)
|
||||
p->err_shown = 0;
|
||||
}
|
||||
|
||||
static int isSoftwareGl(struct vo *vo)
|
||||
{
|
||||
struct gl_priv *p = vo->priv;
|
||||
const char *renderer = p->gl->GetString(GL_RENDERER);
|
||||
const char *vendor = p->gl->GetString(GL_VENDOR);
|
||||
return !renderer || strcmp(renderer, "Software Rasterizer") == 0 ||
|
||||
strstr(renderer, "llvmpipe") ||
|
||||
strcmp(vendor, "Microsoft Corporation") == 0;
|
||||
}
|
||||
|
||||
static void autodetectGlExtensions(struct vo *vo)
|
||||
{
|
||||
struct gl_priv *p = vo->priv;
|
||||
@ -596,15 +591,18 @@ static int initGl(struct vo *vo, uint32_t d_width, uint32_t d_height)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int create_window(struct vo *vo, uint32_t d_width, uint32_t d_height,
|
||||
uint32_t flags)
|
||||
static bool create_window(struct vo *vo, uint32_t d_width, uint32_t d_height,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct gl_priv *p = vo->priv;
|
||||
|
||||
if (p->stereo_mode == GL_3D_QUADBUFFER)
|
||||
flags |= VOFLAG_STEREO;
|
||||
|
||||
return p->glctx->create_window(p->glctx, d_width, d_height, flags);
|
||||
int mpgl_caps = MPGL_CAP_GL_LEGACY;
|
||||
if (!p->allow_sw)
|
||||
mpgl_caps |= MPGL_CAP_NO_SW;
|
||||
return mpgl_create_window(p->glctx, mpgl_caps, d_width, d_height, flags);
|
||||
}
|
||||
|
||||
static int config(struct vo *vo, uint32_t width, uint32_t height,
|
||||
@ -626,13 +624,12 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
|
||||
|
||||
p->vo_flipped = !!(flags & VOFLAG_FLIPPING);
|
||||
|
||||
if (create_window(vo, d_width, d_height, flags) < 0)
|
||||
return -1;
|
||||
|
||||
if (vo->config_count)
|
||||
uninitGl(vo);
|
||||
if (p->glctx->setGlWindow(p->glctx) == SET_WINDOW_FAILED)
|
||||
|
||||
if (!create_window(vo, d_width, d_height, flags))
|
||||
return -1;
|
||||
|
||||
initGl(vo, vo->dwidth, vo->dheight);
|
||||
|
||||
return 0;
|
||||
@ -1153,13 +1150,12 @@ static void uninit(struct vo *vo)
|
||||
{
|
||||
struct gl_priv *p = vo->priv;
|
||||
|
||||
if (p->glctx)
|
||||
uninitGl(vo);
|
||||
uninitGl(vo);
|
||||
free(p->custom_prog);
|
||||
p->custom_prog = NULL;
|
||||
free(p->custom_tex);
|
||||
p->custom_tex = NULL;
|
||||
uninit_mpglcontext(p->glctx);
|
||||
mpgl_uninit(p->glctx);
|
||||
p->glctx = NULL;
|
||||
p->gl = NULL;
|
||||
}
|
||||
@ -1192,7 +1188,6 @@ static int preinit(struct vo *vo, const char *arg)
|
||||
|
||||
p->eosd = eosd_packer_create(vo);
|
||||
|
||||
int allow_sw = 0;
|
||||
char *backend_arg = NULL;
|
||||
|
||||
//essentially unused; for legacy warnings only
|
||||
@ -1223,7 +1218,7 @@ static int preinit(struct vo *vo, const char *arg)
|
||||
{"mipmapgen", OPT_ARG_BOOL, &p->mipmap_gen, NULL},
|
||||
{"osdcolor", OPT_ARG_INT, &p->osd_color, NULL},
|
||||
{"stereo", OPT_ARG_INT, &p->stereo_mode, NULL},
|
||||
{"sw", OPT_ARG_BOOL, &allow_sw, NULL},
|
||||
{"sw", OPT_ARG_BOOL, &p->allow_sw, NULL},
|
||||
{"backend", OPT_ARG_MSTRZ,&backend_arg, backend_valid},
|
||||
// Removed options.
|
||||
// They are only parsed to notify the user about the replacements.
|
||||
@ -1330,27 +1325,21 @@ static int preinit(struct vo *vo, const char *arg)
|
||||
int backend = backend_arg ? mpgl_find_backend(backend_arg) : GLTYPE_AUTO;
|
||||
free(backend_arg);
|
||||
|
||||
p->glctx = init_mpglcontext(backend, vo);
|
||||
p->glctx = mpgl_init(backend, vo);
|
||||
if (!p->glctx)
|
||||
goto err_out;
|
||||
p->gl = p->glctx->gl;
|
||||
|
||||
if (p->use_yuv == -1 || !allow_sw) {
|
||||
if (create_window(vo, 320, 200, VOFLAG_HIDDEN) < 0)
|
||||
goto err_out;
|
||||
if (p->glctx->setGlWindow(p->glctx) == SET_WINDOW_FAILED)
|
||||
goto err_out;
|
||||
if (!allow_sw && isSoftwareGl(vo))
|
||||
if (p->use_yuv == -1) {
|
||||
if (!create_window(vo, 320, 200, VOFLAG_HIDDEN))
|
||||
goto err_out;
|
||||
autodetectGlExtensions(vo);
|
||||
// We created a window to test whether the GL context supports hardware
|
||||
// acceleration and so on. Destroy that window to make sure all state
|
||||
// associated with it is lost.
|
||||
uninit(vo);
|
||||
p->glctx = init_mpglcontext(backend, vo);
|
||||
if (!p->glctx)
|
||||
uninitGl(vo);
|
||||
if (!mpgl_destroy_window(p->glctx))
|
||||
goto err_out;
|
||||
p->gl = p->glctx->gl;
|
||||
}
|
||||
if (p->many_fmts)
|
||||
mp_msg(MSGT_VO, MSGL_INFO, "[gl] using extended formats. "
|
||||
|
221
libvo/vo_gl3.c
221
libvo/vo_gl3.c
@ -148,7 +148,6 @@ struct gl_priv {
|
||||
struct vo *vo;
|
||||
MPGLContext *glctx;
|
||||
GL *gl;
|
||||
const char *shader_version;
|
||||
|
||||
int use_indirect;
|
||||
int use_gamma;
|
||||
@ -160,7 +159,7 @@ struct gl_priv {
|
||||
int use_pbo;
|
||||
int use_glFinish;
|
||||
int use_gl_debug;
|
||||
int use_gl2;
|
||||
int allow_sw;
|
||||
|
||||
int dither_depth;
|
||||
int swap_interval;
|
||||
@ -194,6 +193,7 @@ struct gl_priv {
|
||||
GLuint dither_texture;
|
||||
float dither_quantization;
|
||||
float dither_multiply;
|
||||
int dither_size;
|
||||
|
||||
uint32_t image_width;
|
||||
uint32_t image_height;
|
||||
@ -305,9 +305,13 @@ static void draw_triangles(struct gl_priv *p, struct vertex *vb, int vert_count)
|
||||
GL_DYNAMIC_DRAW);
|
||||
gl->BindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
gl->BindVertexArray(p->vao);
|
||||
if (gl->BindVertexArray)
|
||||
gl->BindVertexArray(p->vao);
|
||||
|
||||
gl->DrawArrays(GL_TRIANGLES, 0, vert_count);
|
||||
gl->BindVertexArray(0);
|
||||
|
||||
if (gl->BindVertexArray)
|
||||
gl->BindVertexArray(0);
|
||||
|
||||
debug_check_gl(p, "after rendering");
|
||||
}
|
||||
@ -351,10 +355,12 @@ static void write_quad(struct vertex *va,
|
||||
#undef COLOR_INIT
|
||||
}
|
||||
|
||||
static void fbotex_init(struct gl_priv *p, struct fbotex *fbo, int w, int h)
|
||||
static bool fbotex_init(struct gl_priv *p, struct fbotex *fbo, int w, int h)
|
||||
{
|
||||
GL *gl = p->gl;
|
||||
bool res = true;
|
||||
|
||||
assert(gl->mpgl_caps & MPGL_CAP_FB);
|
||||
assert(!fbo->fbo);
|
||||
assert(!fbo->texture);
|
||||
|
||||
@ -375,25 +381,28 @@ static void fbotex_init(struct gl_priv *p, struct fbotex *fbo, int w, int h)
|
||||
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D, fbo->texture, 0);
|
||||
|
||||
if (gl->CheckFramebufferStatus(GL_FRAMEBUFFER)
|
||||
!= GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
if (gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
mp_msg(MSGT_VO, MSGL_ERR, "[gl] Error: framebuffer completeness "
|
||||
"check failed!\n");
|
||||
res = false;
|
||||
}
|
||||
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
debug_check_gl(p, "after creating framebuffer & associated texture");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void fbotex_uninit(struct gl_priv *p, struct fbotex *fbo)
|
||||
{
|
||||
GL *gl = p->gl;
|
||||
|
||||
gl->DeleteFramebuffers(1, &fbo->fbo);
|
||||
gl->DeleteTextures(1, &fbo->texture);
|
||||
*fbo = (struct fbotex) {0};
|
||||
if (gl->mpgl_caps & MPGL_CAP_FB) {
|
||||
gl->DeleteFramebuffers(1, &fbo->fbo);
|
||||
gl->DeleteTextures(1, &fbo->texture);
|
||||
*fbo = (struct fbotex) {0};
|
||||
}
|
||||
}
|
||||
|
||||
static void matrix_ortho2d(float m[3][3], float x0, float x1,
|
||||
@ -444,9 +453,20 @@ static void update_uniforms(struct gl_priv *p, GLuint program)
|
||||
1.0 / cparams.ggamma,
|
||||
1.0 / cparams.bgamma);
|
||||
|
||||
gl->Uniform1i(gl->GetUniformLocation(program, "texture1"), 0);
|
||||
gl->Uniform1i(gl->GetUniformLocation(program, "texture2"), 1);
|
||||
gl->Uniform1i(gl->GetUniformLocation(program, "texture3"), 2);
|
||||
for (int n = 0; n < p->plane_count; n++) {
|
||||
char textures_n[32];
|
||||
char textures_size_n[32];
|
||||
snprintf(textures_n, sizeof(textures_n), "textures[%d]", n);
|
||||
snprintf(textures_size_n, sizeof(textures_size_n), "textures_size[%d]", n);
|
||||
|
||||
gl->Uniform1i(gl->GetUniformLocation(program, textures_n), n);
|
||||
gl->Uniform2f(gl->GetUniformLocation(program, textures_size_n),
|
||||
p->texture_width >> p->planes[n].shift_x,
|
||||
p->texture_height >> p->planes[n].shift_y);
|
||||
}
|
||||
|
||||
gl->Uniform2f(gl->GetUniformLocation(program, "dither_size"),
|
||||
p->dither_size, p->dither_size);
|
||||
|
||||
gl->Uniform1i(gl->GetUniformLocation(program, "lut_3d"), TEXUNIT_3DLUT);
|
||||
|
||||
@ -607,12 +627,12 @@ static void shader_setup_scaler(char **shader, struct scaler *scaler, int pass)
|
||||
// The direction/pass assignment is rather arbitrary, but fixed in
|
||||
// other parts of the code (like FBO setup).
|
||||
const char *direction = pass == 0 ? "0, 1" : "1, 0";
|
||||
*shader = talloc_asprintf_append(*shader, "#define %s(p0, p1) "
|
||||
"sample_convolution_sep%d(vec2(%s), %s, p0, p1)\n",
|
||||
*shader = talloc_asprintf_append(*shader, "#define %s(p0, p1, p2) "
|
||||
"sample_convolution_sep%d(vec2(%s), %s, p0, p1, p2)\n",
|
||||
target, size, direction, scaler->lut_name);
|
||||
} else {
|
||||
*shader = talloc_asprintf_append(*shader, "#define %s(p0, p1) "
|
||||
"sample_convolution%d(%s, p0, p1)\n",
|
||||
*shader = talloc_asprintf_append(*shader, "#define %s(p0, p1, p2) "
|
||||
"sample_convolution%d(%s, p0, p1, p2)\n",
|
||||
target, size, scaler->lut_name);
|
||||
}
|
||||
}
|
||||
@ -642,7 +662,7 @@ static void compile_shaders(struct gl_priv *p)
|
||||
char *s_eosd = get_section(tmp, src, "frag_eosd");
|
||||
char *s_osd = get_section(tmp, src, "frag_osd");
|
||||
|
||||
char *header = talloc_asprintf(tmp, "#version %s\n%s", p->shader_version,
|
||||
char *header = talloc_asprintf(tmp, "#version %d\n%s", gl->glsl_version,
|
||||
shader_prelude);
|
||||
|
||||
char *header_eosd = talloc_strdup(tmp, header);
|
||||
@ -881,6 +901,8 @@ static void init_dither(struct gl_priv *p)
|
||||
unsigned char dither[256];
|
||||
make_dither_matrix(dither, size);
|
||||
|
||||
p->dither_size = size;
|
||||
|
||||
gl->ActiveTexture(GL_TEXTURE0 + TEXUNIT_DITHER);
|
||||
gl->GenTextures(1, &p->dither_texture);
|
||||
gl->BindTexture(GL_TEXTURE_2D, p->dither_texture);
|
||||
@ -1081,7 +1103,9 @@ static void do_render(struct gl_priv *p)
|
||||
float final_texw = p->image_width * source->tex_w / (float)source->vp_w;
|
||||
float final_texh = p->image_height * source->tex_h / (float)source->vp_h;
|
||||
|
||||
if (p->use_srgb && !p->use_lut_3d)
|
||||
bool use_srgb_fb = p->use_srgb && !p->use_lut_3d;
|
||||
|
||||
if (use_srgb_fb)
|
||||
gl->Enable(GL_FRAMEBUFFER_SRGB);
|
||||
|
||||
if (p->stereo_mode) {
|
||||
@ -1122,7 +1146,8 @@ static void do_render(struct gl_priv *p)
|
||||
draw_triangles(p, vb, VERTICES_PER_QUAD);
|
||||
}
|
||||
|
||||
gl->Disable(GL_FRAMEBUFFER_SRGB);
|
||||
if (use_srgb_fb)
|
||||
gl->Disable(GL_FRAMEBUFFER_SRGB);
|
||||
|
||||
gl->UseProgram(0);
|
||||
|
||||
@ -1583,6 +1608,70 @@ static void draw_eosd(struct gl_priv *p, mp_eosd_images_t *imgs)
|
||||
gl->Disable(GL_BLEND);
|
||||
}
|
||||
|
||||
// Disable features that are not supported with the current OpenGL version.
|
||||
static void check_gl_features(struct gl_priv *p)
|
||||
{
|
||||
GL *gl = p->gl;
|
||||
bool have_float_tex = gl->mpgl_caps & MPGL_CAP_FLOAT_TEX;
|
||||
bool have_fbo = gl->mpgl_caps & MPGL_CAP_FB;
|
||||
bool have_srgb = (gl->mpgl_caps & MPGL_CAP_SRGB_TEX) &&
|
||||
(gl->mpgl_caps & MPGL_CAP_SRGB_FB);
|
||||
|
||||
char *disabled[10];
|
||||
int n_disabled = 0;
|
||||
|
||||
if (have_fbo) {
|
||||
struct fbotex fbo = {0};
|
||||
have_fbo = fbotex_init(p, &fbo, 16, 16);
|
||||
fbotex_uninit(p, &fbo);
|
||||
}
|
||||
|
||||
// Disable these only if the user didn't disable scale-sep on the command
|
||||
// line, so convolution filter can still be forced to be run.
|
||||
// Normally, we want to disable them by default if FBOs are unavailable,
|
||||
// because they will be slow (not critically slow, but still slower).
|
||||
// Without FP textures, we must always disable them.
|
||||
if (!have_float_tex || (!have_fbo && p->use_scale_sep)) {
|
||||
for (int n = 0; n < 2; n++) {
|
||||
struct scaler *scaler = &p->scalers[n];
|
||||
if (mp_find_filter_kernel(scaler->name)) {
|
||||
scaler->name = "bilinear";
|
||||
disabled[n_disabled++]
|
||||
= have_float_tex ? "scaler (FBO)" : "scaler (float tex.)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!have_srgb && p->use_srgb) {
|
||||
p->use_srgb = false;
|
||||
disabled[n_disabled++] = "sRGB";
|
||||
}
|
||||
if (!have_fbo && p->use_lut_3d) {
|
||||
p->use_lut_3d = false;
|
||||
disabled[n_disabled++] = "color management (FBO)";
|
||||
}
|
||||
if (!have_srgb && p->use_lut_3d) {
|
||||
p->use_lut_3d = false;
|
||||
disabled[n_disabled++] = "color management (sRGB)";
|
||||
}
|
||||
|
||||
if (!have_fbo) {
|
||||
p->use_scale_sep = false;
|
||||
p->use_indirect = false;
|
||||
}
|
||||
|
||||
if (n_disabled) {
|
||||
mp_msg(MSGT_VO, MSGL_ERR, "[gl] Some OpenGL extensions not detected, "
|
||||
"disabling: ");
|
||||
for (int n = 0; n < n_disabled; n++) {
|
||||
if (n)
|
||||
mp_msg(MSGT_VO, MSGL_ERR, ", ");
|
||||
mp_msg(MSGT_VO, MSGL_ERR, "%s", disabled[n]);
|
||||
}
|
||||
mp_msg(MSGT_VO, MSGL_ERR, ".\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_vertex_array(GL *gl)
|
||||
{
|
||||
size_t stride = sizeof(struct vertex);
|
||||
@ -1616,15 +1705,7 @@ static int init_gl(struct gl_priv *p)
|
||||
mp_msg(MSGT_VO, MSGL_V, "[gl] Display depth: R=%d, G=%d, B=%d\n",
|
||||
p->glctx->depth_r, p->glctx->depth_g, p->glctx->depth_b);
|
||||
|
||||
GLint major, minor;
|
||||
gl->GetIntegerv(GL_MAJOR_VERSION, &major);
|
||||
gl->GetIntegerv(GL_MINOR_VERSION, &minor);
|
||||
|
||||
p->shader_version = "130";
|
||||
|
||||
// Hack for OSX: it only creates 3.2 contexts.
|
||||
if (MPGL_VER(major, minor) >= MPGL_VER(3, 2))
|
||||
p->shader_version = "150";
|
||||
check_gl_features(p);
|
||||
|
||||
gl->Disable(GL_DITHER);
|
||||
gl->Disable(GL_BLEND);
|
||||
@ -1634,13 +1715,18 @@ static int init_gl(struct gl_priv *p)
|
||||
gl->DrawBuffer(GL_BACK);
|
||||
|
||||
gl->GenBuffers(1, &p->vertex_buffer);
|
||||
gl->GenVertexArrays(1, &p->vao);
|
||||
|
||||
gl->BindBuffer(GL_ARRAY_BUFFER, p->vertex_buffer);
|
||||
gl->BindVertexArray(p->vao);
|
||||
setup_vertex_array(gl);
|
||||
|
||||
if (gl->BindVertexArray) {
|
||||
gl->GenVertexArrays(1, &p->vao);
|
||||
gl->BindVertexArray(p->vao);
|
||||
setup_vertex_array(gl);
|
||||
gl->BindVertexArray(0);
|
||||
} else {
|
||||
setup_vertex_array(gl);
|
||||
}
|
||||
|
||||
gl->BindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
gl->BindVertexArray(0);
|
||||
|
||||
GLint max_texture_size;
|
||||
gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
|
||||
@ -1664,7 +1750,8 @@ static void uninit_gl(struct gl_priv *p)
|
||||
|
||||
uninit_video(p);
|
||||
|
||||
gl->DeleteVertexArrays(1, &p->vao);
|
||||
if (gl->DeleteVertexArrays)
|
||||
gl->DeleteVertexArrays(1, &p->vao);
|
||||
p->vao = 0;
|
||||
gl->DeleteBuffers(1, &p->vertex_buffer);
|
||||
p->vertex_buffer = 0;
|
||||
@ -1762,26 +1849,19 @@ static int query_format(uint32_t format)
|
||||
return caps;
|
||||
}
|
||||
|
||||
static bool config_window(struct gl_priv *p, uint32_t d_width,
|
||||
static bool create_window(struct gl_priv *p, uint32_t d_width,
|
||||
uint32_t d_height, uint32_t flags)
|
||||
{
|
||||
if (p->stereo_mode == GL_3D_QUADBUFFER)
|
||||
flags |= VOFLAG_STEREO;
|
||||
|
||||
int mpgl_version = MPGL_VER(3, 0);
|
||||
int mpgl_flags = p->use_gl_debug ? MPGLFLAG_DEBUG : 0;
|
||||
if (p->use_gl_debug)
|
||||
flags |= VOFLAG_GL_DEBUG;
|
||||
|
||||
if (p->use_gl2)
|
||||
mpgl_version = MPGL_VER(2, 1);
|
||||
|
||||
if (create_mpglcontext(p->glctx, mpgl_flags, mpgl_version, d_width,
|
||||
d_height, flags) == SET_WINDOW_FAILED)
|
||||
return false;
|
||||
|
||||
if (!p->vertex_buffer)
|
||||
init_gl(p);
|
||||
|
||||
return true;
|
||||
int mpgl_caps = MPGL_CAP_GL21 | MPGL_CAP_TEX_RG;
|
||||
if (!p->allow_sw)
|
||||
mpgl_caps |= MPGL_CAP_NO_SW;
|
||||
return mpgl_create_window(p->glctx, mpgl_caps, d_width, d_height, flags);
|
||||
}
|
||||
|
||||
static int config(struct vo *vo, uint32_t width, uint32_t height,
|
||||
@ -1790,9 +1870,12 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
|
||||
{
|
||||
struct gl_priv *p = vo->priv;
|
||||
|
||||
if (!config_window(p, d_width, d_height, flags))
|
||||
if (!create_window(p, d_width, d_height, flags))
|
||||
return -1;
|
||||
|
||||
if (!p->vertex_buffer)
|
||||
init_gl(p);
|
||||
|
||||
p->vo_flipped = !!(flags & VOFLAG_FLIPPING);
|
||||
|
||||
if (p->image_format != format || p->image_width != width
|
||||
@ -1918,6 +2001,7 @@ static int control(struct vo *vo, uint32_t request, void *data)
|
||||
char *arg = data;
|
||||
if (!reparse_cmdline(p, arg))
|
||||
return false;
|
||||
check_gl_features(p);
|
||||
reinit_rendering(p);
|
||||
resize(p);
|
||||
vo->want_redraw = true;
|
||||
@ -1932,7 +2016,7 @@ static void uninit(struct vo *vo)
|
||||
struct gl_priv *p = vo->priv;
|
||||
|
||||
uninit_gl(p);
|
||||
uninit_mpglcontext(p->glctx);
|
||||
mpgl_uninit(p->glctx);
|
||||
p->glctx = NULL;
|
||||
p->gl = NULL;
|
||||
}
|
||||
@ -2105,6 +2189,7 @@ const struct fbo_format fbo_formats[] = {
|
||||
{"rgb", GL_RGB},
|
||||
{"rgba", GL_RGBA},
|
||||
{"rgb8", GL_RGB8},
|
||||
{"rgb10", GL_RGB10},
|
||||
{"rgb16", GL_RGB16},
|
||||
{"rgb16f", GL_RGB16F},
|
||||
{"rgb32f", GL_RGB32F},
|
||||
@ -2224,6 +2309,8 @@ static bool reparse_cmdline(struct gl_priv *p, char *arg)
|
||||
p->use_scale_sep = opt->use_scale_sep;
|
||||
p->dither_depth = opt->dither_depth;
|
||||
|
||||
check_gl_features(p);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2275,11 +2362,11 @@ static int preinit(struct vo *vo, const char *arg)
|
||||
{"lparam2", OPT_ARG_FLOAT, &p->scaler_params[1]},
|
||||
{"fancy-downscaling", OPT_ARG_BOOL, &p->use_fancy_downscaling},
|
||||
{"debug", OPT_ARG_BOOL, &p->use_gl_debug},
|
||||
{"force-gl2", OPT_ARG_BOOL, &p->use_gl2},
|
||||
{"indirect", OPT_ARG_BOOL, &p->use_indirect},
|
||||
{"scale-sep", OPT_ARG_BOOL, &p->use_scale_sep},
|
||||
{"fbo-format", OPT_ARG_MSTRZ, &fbo_format, fbo_format_valid},
|
||||
{"backend", OPT_ARG_MSTRZ, &backend_arg, backend_valid},
|
||||
{"sw", OPT_ARG_BOOL, &p->allow_sw},
|
||||
{"icc-profile", OPT_ARG_MSTRZ, &icc_profile},
|
||||
{"icc-cache", OPT_ARG_MSTRZ, &icc_cache},
|
||||
{"icc-intent", OPT_ARG_INT, &icc_intent},
|
||||
@ -2328,23 +2415,20 @@ static int preinit(struct vo *vo, const char *arg)
|
||||
|
||||
p->eosd = eosd_packer_create(vo);
|
||||
|
||||
p->glctx = init_mpglcontext(backend, vo);
|
||||
p->glctx = mpgl_init(backend, vo);
|
||||
if (!p->glctx)
|
||||
goto err_out;
|
||||
p->gl = p->glctx->gl;
|
||||
|
||||
if (true) {
|
||||
if (!config_window(p, 320, 200, VOFLAG_HIDDEN))
|
||||
goto err_out;
|
||||
// We created a window to test whether the GL context could be
|
||||
// created and so on. Destroy that window to make sure all state
|
||||
// associated with it is lost.
|
||||
uninit(vo);
|
||||
p->glctx = init_mpglcontext(backend, vo);
|
||||
if (!p->glctx)
|
||||
goto err_out;
|
||||
p->gl = p->glctx->gl;
|
||||
}
|
||||
if (!create_window(p, 320, 200, VOFLAG_HIDDEN))
|
||||
goto err_out;
|
||||
check_gl_features(p);
|
||||
// We created a window to test whether the GL context could be
|
||||
// created and so on. Destroy that window to make sure all state
|
||||
// associated with it is lost.
|
||||
uninit_gl(p);
|
||||
if (!mpgl_destroy_window(p->glctx))
|
||||
goto err_out;
|
||||
|
||||
return 0;
|
||||
|
||||
@ -2464,13 +2548,10 @@ static const char help_text[] =
|
||||
" This mechanism is disabled on RGB input.\n"
|
||||
" fbo-format=<fmt>\n"
|
||||
" Selects the internal format of any FBO textures used.\n"
|
||||
" fmt can be one of: rgb, rgba, rgb8, rgb16, rgb16f, rgb32f\n"
|
||||
" fmt can be one of: rgb, rgba, rgb8, rgb10, rgb16, rgb16f, rgb32f\n"
|
||||
" Default: rgb16.\n"
|
||||
" gamma\n"
|
||||
" Always enable gamma control. (Disables delayed enabling.)\n"
|
||||
" force-gl2\n"
|
||||
" Create a legacy GL context. This will randomly malfunction\n"
|
||||
" if the proper extensions are not supported.\n"
|
||||
"Color management:\n"
|
||||
" icc-profile=<file>\n"
|
||||
" Load an ICC profile and use it to transform linear RGB to\n"
|
||||
|
@ -22,7 +22,29 @@
|
||||
|
||||
// inserted at the beginning of all shaders
|
||||
#!section prelude
|
||||
|
||||
// GLSL 1.20 compatibility layer
|
||||
// texture() should be assumed to always map to texture2D()
|
||||
#if __VERSION__ >= 130
|
||||
# define texture1D texture
|
||||
# define texture3D texture
|
||||
# define DECLARE_FRAGPARMS \
|
||||
out vec4 out_color;
|
||||
#else
|
||||
# define texture texture2D
|
||||
# define DECLARE_FRAGPARMS
|
||||
# define out_color gl_FragColor
|
||||
# define in varying
|
||||
#endif
|
||||
|
||||
#!section vertex_all
|
||||
|
||||
#if __VERSION__ < 130
|
||||
# undef in
|
||||
# define in attribute
|
||||
# define out varying
|
||||
#endif
|
||||
|
||||
uniform mat3 transform;
|
||||
uniform sampler3D lut_3d;
|
||||
|
||||
@ -40,37 +62,36 @@ void main() {
|
||||
gl_Position = vec4(position, 1);
|
||||
color = vertex_color;
|
||||
#ifdef USE_3DLUT
|
||||
color = vec4(texture(lut_3d, color.rgb).rgb, color.a);
|
||||
color = vec4(texture3D(lut_3d, color.rgb).rgb, color.a);
|
||||
#endif
|
||||
texcoord = vertex_texcoord;
|
||||
}
|
||||
|
||||
#!section frag_eosd
|
||||
uniform sampler2D texture1;
|
||||
uniform sampler2D textures[3];
|
||||
|
||||
in vec2 texcoord;
|
||||
in vec4 color;
|
||||
out vec4 out_color;
|
||||
DECLARE_FRAGPARMS
|
||||
|
||||
void main() {
|
||||
out_color = vec4(color.rgb, color.a * texture(texture1, texcoord).r);
|
||||
out_color = vec4(color.rgb, color.a * texture(textures[0], texcoord).r);
|
||||
}
|
||||
|
||||
#!section frag_osd
|
||||
uniform sampler2D texture1;
|
||||
uniform sampler2D textures[3];
|
||||
|
||||
in vec2 texcoord;
|
||||
in vec4 color;
|
||||
out vec4 out_color;
|
||||
DECLARE_FRAGPARMS
|
||||
|
||||
void main() {
|
||||
out_color = texture(texture1, texcoord).rrrg * color;
|
||||
out_color = texture(textures[0], texcoord).rrrg * color;
|
||||
}
|
||||
|
||||
#!section frag_video
|
||||
uniform sampler2D texture1;
|
||||
uniform sampler2D texture2;
|
||||
uniform sampler2D texture3;
|
||||
uniform sampler2D textures[3];
|
||||
uniform vec2 textures_size[3];
|
||||
uniform sampler1D lut_c_1d;
|
||||
uniform sampler1D lut_l_1d;
|
||||
uniform sampler2D lut_c_2d;
|
||||
@ -83,11 +104,12 @@ uniform float conv_gamma;
|
||||
uniform float dither_quantization;
|
||||
uniform float dither_multiply;
|
||||
uniform float filter_param1;
|
||||
uniform vec2 dither_size;
|
||||
|
||||
in vec2 texcoord;
|
||||
out vec4 out_color;
|
||||
DECLARE_FRAGPARMS
|
||||
|
||||
vec4 sample_bilinear(sampler2D tex, vec2 texcoord) {
|
||||
vec4 sample_bilinear(sampler2D tex, vec2 texsize, vec2 texcoord) {
|
||||
return texture(tex, texcoord);
|
||||
}
|
||||
|
||||
@ -108,8 +130,7 @@ vec4 calcweights(float s) {
|
||||
return t;
|
||||
}
|
||||
|
||||
vec4 sample_bicubic_fast(sampler2D tex, vec2 texcoord) {
|
||||
vec2 texsize = textureSize(tex, 0);
|
||||
vec4 sample_bicubic_fast(sampler2D tex, vec2 texsize, vec2 texcoord) {
|
||||
vec2 pt = 1 / texsize;
|
||||
vec2 fcoord = fract(texcoord * texsize + vec2(0.5, 0.5));
|
||||
vec4 parmx = calcweights(fcoord.x);
|
||||
@ -130,12 +151,12 @@ vec4 sample_bicubic_fast(sampler2D tex, vec2 texcoord) {
|
||||
}
|
||||
|
||||
float[2] weights2(sampler1D lookup, float f) {
|
||||
vec4 c = texture(lookup, f);
|
||||
vec4 c = texture1D(lookup, f);
|
||||
return float[2](c.r, c.g);
|
||||
}
|
||||
|
||||
float[4] weights4(sampler1D lookup, float f) {
|
||||
vec4 c = texture(lookup, f);
|
||||
vec4 c = texture1D(lookup, f);
|
||||
return float[4](c.r, c.g, c.b, c.a);
|
||||
}
|
||||
|
||||
@ -169,13 +190,13 @@ float[16] weights16(sampler2D lookup, float f) {
|
||||
c3.r, c3.g, c3.b, c3.a, c4.r, c4.g, c4.b, c4.a);
|
||||
}
|
||||
|
||||
#define CONVOLUTION_SEP_N(NAME, N) \
|
||||
vec4 NAME(sampler2D tex, vec2 texcoord, vec2 pt, float weights[N]) { \
|
||||
vec4 res = vec4(0); \
|
||||
for (int n = 0; n < N; n++) { \
|
||||
res += weights[n] * texture(tex, texcoord + pt * n); \
|
||||
} \
|
||||
return res; \
|
||||
#define CONVOLUTION_SEP_N(NAME, N) \
|
||||
vec4 NAME(sampler2D tex, vec2 texcoord, vec2 pt, float weights[N]) { \
|
||||
vec4 res = vec4(0); \
|
||||
for (int n = 0; n < N; n++) { \
|
||||
res += weights[n] * texture(tex, texcoord + pt * n); \
|
||||
} \
|
||||
return res; \
|
||||
}
|
||||
|
||||
CONVOLUTION_SEP_N(convolution_sep2, 2)
|
||||
@ -188,8 +209,8 @@ CONVOLUTION_SEP_N(convolution_sep16, 16)
|
||||
// The dir parameter is (0, 1) or (1, 0), and we expect the shader compiler to
|
||||
// remove all the redundant multiplications and additions.
|
||||
#define SAMPLE_CONVOLUTION_SEP_N(NAME, N, SAMPLERT, CONV_FUNC, WEIGHTS_FUNC)\
|
||||
vec4 NAME(vec2 dir, SAMPLERT lookup, sampler2D tex, vec2 texcoord) { \
|
||||
vec2 texsize = textureSize(tex, 0); \
|
||||
vec4 NAME(vec2 dir, SAMPLERT lookup, sampler2D tex, vec2 texsize, \
|
||||
vec2 texcoord) { \
|
||||
vec2 pt = (1 / texsize) * dir; \
|
||||
float fcoord = dot(fract(texcoord * texsize - 0.5), dir); \
|
||||
vec2 base = texcoord - fcoord * pt; \
|
||||
@ -226,8 +247,7 @@ CONVOLUTION_N(convolution12, 12)
|
||||
CONVOLUTION_N(convolution16, 16)
|
||||
|
||||
#define SAMPLE_CONVOLUTION_N(NAME, N, SAMPLERT, CONV_FUNC, WEIGHTS_FUNC) \
|
||||
vec4 NAME(SAMPLERT lookup, sampler2D tex, vec2 texcoord) { \
|
||||
vec2 texsize = textureSize(tex, 0); \
|
||||
vec4 NAME(SAMPLERT lookup, sampler2D tex, vec2 texsize, vec2 texcoord) {\
|
||||
vec2 pt = 1 / texsize; \
|
||||
vec2 fcoord = fract(texcoord * texsize - 0.5); \
|
||||
vec2 base = texcoord - fcoord * pt; \
|
||||
@ -245,8 +265,7 @@ SAMPLE_CONVOLUTION_N(sample_convolution16, 16, sampler2D, convolution16, weights
|
||||
|
||||
|
||||
// Unsharp masking
|
||||
vec4 sample_sharpen3(sampler2D tex, vec2 texcoord) {
|
||||
vec2 texsize = textureSize(tex, 0);
|
||||
vec4 sample_sharpen3(sampler2D tex, vec2 texsize, vec2 texcoord) {
|
||||
vec2 pt = 1 / texsize;
|
||||
vec2 st = pt * 0.5;
|
||||
vec4 p = texture(tex, texcoord);
|
||||
@ -257,8 +276,7 @@ vec4 sample_sharpen3(sampler2D tex, vec2 texcoord) {
|
||||
return p + (p - 0.25 * sum) * filter_param1;
|
||||
}
|
||||
|
||||
vec4 sample_sharpen5(sampler2D tex, vec2 texcoord) {
|
||||
vec2 texsize = textureSize(tex, 0);
|
||||
vec4 sample_sharpen5(sampler2D tex, vec2 texsize, vec2 texcoord) {
|
||||
vec2 pt = 1 / texsize;
|
||||
vec2 st1 = pt * 1.2;
|
||||
vec4 p = texture(tex, texcoord);
|
||||
@ -277,11 +295,11 @@ vec4 sample_sharpen5(sampler2D tex, vec2 texcoord) {
|
||||
|
||||
void main() {
|
||||
#ifdef USE_PLANAR
|
||||
vec3 color = vec3(SAMPLE_L(texture1, texcoord).r,
|
||||
SAMPLE_C(texture2, texcoord).r,
|
||||
SAMPLE_C(texture3, texcoord).r);
|
||||
vec3 color = vec3(SAMPLE_L(textures[0], textures_size[0], texcoord).r,
|
||||
SAMPLE_C(textures[1], textures_size[1], texcoord).r,
|
||||
SAMPLE_C(textures[2], textures_size[2], texcoord).r);
|
||||
#else
|
||||
vec3 color = SAMPLE_L(texture1, texcoord).rgb;
|
||||
vec3 color = SAMPLE_L(textures[0], textures_size[0], texcoord).rgb;
|
||||
#endif
|
||||
#ifdef USE_GBRP
|
||||
color.gbr = color;
|
||||
@ -306,11 +324,11 @@ void main() {
|
||||
color = pow(color, inv_gamma);
|
||||
#endif
|
||||
#ifdef USE_3DLUT
|
||||
color = texture(lut_3d, color).rgb;
|
||||
color = texture3D(lut_3d, color).rgb;
|
||||
#endif
|
||||
#ifdef USE_DITHER
|
||||
float dither = texture(dither, gl_FragCoord.xy / textureSize(dither, 0)).r;
|
||||
color = floor(color * dither_multiply + dither ) / dither_quantization;
|
||||
float dither_value = texture(dither, gl_FragCoord.xy / dither_size).r;
|
||||
color = floor(color * dither_multiply + dither_value ) / dither_quantization;
|
||||
#endif
|
||||
out_color = vec4(color, 1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user