summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-12-01 23:39:13 +0100
committerwm4 <wm4@nowhere>2013-12-01 23:39:13 +0100
commitdc582f2505d7583f414dcfa777371f986de381d3 (patch)
tree20fdff93deb3b96a10f0022db8c04244677a56a6 /video
parentf30c2c99d16527c045caee90c9f7b2a7a7c85c00 (diff)
downloadmpv-dc582f2505d7583f414dcfa777371f986de381d3.tar.bz2
mpv-dc582f2505d7583f414dcfa777371f986de381d3.tar.xz
vo_opengl: add support for rectangle textures
This allows vo_opengl to use GL_TEXTURE_RECTANGLE textures, either by enabling it with the 'rectangle-textures' sub-option, or by having a hwdec backend force it. By default it's off. The _only_ reason we're adding this is because VDA can export rectangle textures only.
Diffstat (limited to 'video')
-rw-r--r--video/out/gl_common.h3
-rw-r--r--video/out/gl_video.c91
-rw-r--r--video/out/gl_video.h1
-rw-r--r--video/out/gl_video_shaders.glsl34
-rw-r--r--video/out/vo_opengl.c1
5 files changed, 86 insertions, 44 deletions
diff --git a/video/out/gl_common.h b/video/out/gl_common.h
index 8b5ac63d9a..c19ec7f73d 100644
--- a/video/out/gl_common.h
+++ b/video/out/gl_common.h
@@ -177,6 +177,9 @@ struct gl_hwdec {
// internal representation in gl_video.c as the hardware texture.
// It's used to build the rendering chain, and also as screenshot format.
int converted_imgfmt;
+ // Normally this is GL_TEXTURE_2D, but the hwdec driver can set it to
+ // GL_TEXTURE_RECTANGLE.
+ GLenum gl_texture_target;
};
struct gl_hwdec_driver {
diff --git a/video/out/gl_video.c b/video/out/gl_video.c
index 881f649a34..4c901965fa 100644
--- a/video/out/gl_video.c
+++ b/video/out/gl_video.c
@@ -145,6 +145,8 @@ struct gl_video {
int depth_g;
+ GLenum gl_target; // texture target (GL_TEXTURE_2D, ...) for video and FBOs
+
GLuint vertex_buffer;
GLuint vao;
@@ -340,6 +342,7 @@ const struct m_sub_options gl_video_conf = {
({"no", 0},
{"yes", 1}, {"", 1},
{"blend", 2})),
+ OPT_FLAG("rectangle-textures", use_rectangle, 0),
{0}
},
.size = sizeof(struct gl_video_opts),
@@ -419,17 +422,19 @@ static void write_quad(struct vertex *va,
float x0, float y0, float x1, float y1,
float tx0, float ty0, float tx1, float ty1,
float texture_w, float texture_h,
- const uint8_t color[4], bool flip)
+ const uint8_t color[4], GLenum target, bool flip)
{
static const uint8_t white[4] = { 255, 255, 255, 255 };
if (!color)
color = white;
- tx0 /= texture_w;
- ty0 /= texture_h;
- tx1 /= texture_w;
- ty1 /= texture_h;
+ if (target == GL_TEXTURE_2D) {
+ tx0 /= texture_w;
+ ty0 /= texture_h;
+ tx1 /= texture_w;
+ ty1 /= texture_h;
+ }
if (flip) {
float tmp = ty0;
@@ -470,14 +475,14 @@ static bool fbotex_init(struct gl_video *p, struct fbotex *fbo, int w, int h,
gl->GenFramebuffers(1, &fbo->fbo);
gl->GenTextures(1, &fbo->texture);
- gl->BindTexture(GL_TEXTURE_2D, fbo->texture);
- gl->TexImage2D(GL_TEXTURE_2D, 0, iformat,
+ gl->BindTexture(p->gl_target, fbo->texture);
+ gl->TexImage2D(p->gl_target, 0, iformat,
fbo->tex_w, fbo->tex_h, 0,
GL_RGB, GL_UNSIGNED_BYTE, NULL);
- default_tex_params(gl, GL_TEXTURE_2D, GL_LINEAR);
+ default_tex_params(gl, p->gl_target, GL_LINEAR);
gl->BindFramebuffer(GL_FRAMEBUFFER, fbo->fbo);
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, fbo->texture, 0);
+ p->gl_target, fbo->texture, 0);
if (gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
MP_ERR(p, "Error: framebuffer completeness check failed!\n");
@@ -567,8 +572,20 @@ static void update_uniforms(struct gl_video *p, GLuint program)
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->image.planes[n].tex_w, p->image.planes[n].tex_h);
+ if (p->gl_target == GL_TEXTURE_2D) {
+ gl->Uniform2f(gl->GetUniformLocation(program, textures_size_n),
+ p->image.planes[n].tex_w, p->image.planes[n].tex_h);
+ } else {
+ // Makes the pixel size calculation code think they are 1x1
+ gl->Uniform2f(gl->GetUniformLocation(program, textures_size_n), 1, 1);
+ }
+ }
+
+ loc = gl->GetUniformLocation(program, "chroma_div");
+ if (loc >= 0) {
+ int xs = p->image_desc.chroma_xs;
+ int ys = p->image_desc.chroma_ys;
+ gl->Uniform2f(loc, 1.0 / (1 << xs), 1.0 / (1 << ys));
}
loc = gl->GetUniformLocation(program, "chroma_center_offset");
@@ -588,8 +605,9 @@ static void update_uniforms(struct gl_video *p, GLuint program)
// move chroma center to luma center (in chroma coord. space)
float o_x = ls_w < 1 ? ls_w * -cx / 2 : 0;
float o_y = ls_h < 1 ? ls_h * -cy / 2 : 0;
- gl->Uniform2f(loc, o_x / FFMAX(p->image.planes[1].w, 1),
- o_y / FFMAX(p->image.planes[1].h, 1));
+ int c = p->gl_target == GL_TEXTURE_2D ? 1 : 0;
+ gl->Uniform2f(loc, o_x / FFMAX(p->image.planes[1].w * c, 1),
+ o_y / FFMAX(p->image.planes[1].h * c, 1));
}
gl->Uniform2f(gl->GetUniformLocation(program, "dither_size"),
@@ -798,6 +816,13 @@ static void compile_shaders(struct gl_video *p)
char *header = talloc_asprintf(tmp, "#version %d\n%s%s", gl->glsl_version,
shader_prelude, PRELUDE_END);
+ if (p->gl_target == GL_TEXTURE_RECTANGLE) {
+ shader_def(&header, "VIDEO_SAMPLER", "sampler2DRect");
+ shader_def_opt(&header, "USE_RECTANGLE", true);
+ } else {
+ shader_def(&header, "VIDEO_SAMPLER", "sampler2D");
+ }
+
// Need to pass alpha through the whole chain. (Not needed for OSD shaders.)
if (p->opts.alpha_mode == 1)
shader_def_opt(&header, "USE_ALPHA", p->has_alpha);
@@ -1218,7 +1243,7 @@ static void set_image_textures(struct gl_video *p, struct video_image *vimg,
for (int n = 0; n < 4; n++) {
gl->ActiveTexture(GL_TEXTURE0 + n);
- gl->BindTexture(GL_TEXTURE_2D, imgtex[n]);
+ gl->BindTexture(p->gl_target, imgtex[n]);
}
gl->ActiveTexture(GL_TEXTURE0);
}
@@ -1229,7 +1254,7 @@ static void unset_image_textures(struct gl_video *p)
for (int n = 0; n < 4; n++) {
gl->ActiveTexture(GL_TEXTURE0 + n);
- gl->BindTexture(GL_TEXTURE_2D, 0);
+ gl->BindTexture(p->gl_target, 0);
}
gl->ActiveTexture(GL_TEXTURE0);
@@ -1241,10 +1266,14 @@ static void init_video(struct gl_video *p, const struct mp_image_params *params)
{
GL *gl = p->gl;
- check_gl_features(p);
-
init_format(params->imgfmt, p);
+ p->gl_target = p->opts.use_rectangle ? GL_TEXTURE_RECTANGLE : GL_TEXTURE_2D;
+ if (p->hwdec_active)
+ p->gl_target = p->hwdec->gl_texture_target;
+
+ check_gl_features(p);
+
p->image_w = params->w;
p->image_h = params->h;
p->image_dw = params->d_w;
@@ -1295,13 +1324,13 @@ static void init_video(struct gl_video *p, const struct mp_image_params *params)
gl->ActiveTexture(GL_TEXTURE0 + n);
gl->GenTextures(1, &plane->gl_texture);
- gl->BindTexture(GL_TEXTURE_2D, plane->gl_texture);
+ gl->BindTexture(p->gl_target, plane->gl_texture);
- gl->TexImage2D(GL_TEXTURE_2D, 0, plane->gl_internal_format,
+ gl->TexImage2D(p->gl_target, 0, plane->gl_internal_format,
plane->tex_w, plane->tex_h, 0,
plane->gl_format, plane->gl_type, NULL);
- default_tex_params(gl, GL_TEXTURE_2D, GL_LINEAR);
+ default_tex_params(gl, p->gl_target, GL_LINEAR);
}
MP_VERBOSE(p, "Texture for plane %d: %dx%d\n",
@@ -1377,7 +1406,7 @@ static void render_to_fbo(struct gl_video *p, struct fbotex *fbo,
write_quad(vb, -1, -1, 1, 1,
x, y, x + w, y + h,
tex_w, tex_h,
- NULL, false);
+ NULL, p->gl_target, false);
draw_triangles(p, vb, VERTICES_PER_QUAD);
gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -1394,7 +1423,7 @@ static void handle_pass(struct gl_video *p, struct fbotex *chain,
if (!program)
return;
- gl->BindTexture(GL_TEXTURE_2D, chain->texture);
+ gl->BindTexture(p->gl_target, chain->texture);
gl->UseProgram(program);
render_to_fbo(p, fbo, chain->vp_x, chain->vp_y,
chain->vp_w, chain->vp_h,
@@ -1448,7 +1477,7 @@ void gl_video_render_frame(struct gl_video *p)
handle_pass(p, &chain, &p->scale_sep_fbo, p->scale_sep_program);
- gl->BindTexture(GL_TEXTURE_2D, chain.texture);
+ gl->BindTexture(p->gl_target, chain.texture);
gl->UseProgram(p->final_program);
struct mp_rect src = {p->src_rect.x0, chain.vp_y,
@@ -1468,7 +1497,7 @@ void gl_video_render_frame(struct gl_video *p)
src.x0 / 2, src.y0,
src.x0 / 2 + w / 2, src.y1,
src_texw, src_texh,
- NULL, is_flipped);
+ NULL, p->gl_target, is_flipped);
draw_triangles(p, vb, VERTICES_PER_QUAD);
glEnable3DRight(gl, p->opts.stereo_mode);
@@ -1479,7 +1508,7 @@ void gl_video_render_frame(struct gl_video *p)
src.x0 / 2 + imgw / 2, src.y0,
src.x0 / 2 + imgw / 2 + w / 2, src.y1,
src_texw, src_texh,
- NULL, is_flipped);
+ NULL, p->gl_target, is_flipped);
draw_triangles(p, vb, VERTICES_PER_QUAD);
glDisable3D(gl, p->opts.stereo_mode);
@@ -1490,7 +1519,7 @@ void gl_video_render_frame(struct gl_video *p)
src.x0, src.y0,
src.x1, src.y1,
src_texw, src_texh,
- NULL, is_flipped);
+ NULL, p->gl_target, is_flipped);
draw_triangles(p, vb, VERTICES_PER_QUAD);
}
@@ -1644,8 +1673,8 @@ void gl_video_upload_image(struct gl_video *p, struct mp_image *mpi)
plane_ptr = NULL; // PBO offset 0
}
gl->ActiveTexture(GL_TEXTURE0 + n);
- gl->BindTexture(GL_TEXTURE_2D, plane->gl_texture);
- glUploadTex(gl, GL_TEXTURE_2D, plane->gl_format, plane->gl_type,
+ gl->BindTexture(p->gl_target, plane->gl_texture);
+ glUploadTex(gl, p->gl_target, plane->gl_format, plane->gl_type,
plane_ptr, mpi->stride[n], 0, 0, plane->w, plane->h, 0);
}
gl->ActiveTexture(GL_TEXTURE0);
@@ -1674,7 +1703,7 @@ struct mp_image *gl_video_download_image(struct gl_video *p)
for (int n = 0; n < p->plane_count; n++) {
struct texplane *plane = &vimg->planes[n];
gl->ActiveTexture(GL_TEXTURE0 + n);
- glDownloadTex(gl, GL_TEXTURE_2D, plane->gl_format, plane->gl_type,
+ glDownloadTex(gl, p->gl_target, plane->gl_format, plane->gl_type,
image->planes[n], image->stride[n]);
}
mp_image_set_attributes(image, &p->image_params);
@@ -1711,7 +1740,7 @@ static void draw_osd_cb(void *ctx, struct mpgl_osd_part *osd,
write_quad(&va[osd->num_vertices],
b->x, b->y, b->x + b->dw, b->y + b->dh,
pos.x, pos.y, pos.x + b->w, pos.y + b->h,
- osd->w, osd->h, color, false);
+ osd->w, osd->h, color, GL_TEXTURE_2D, false);
osd->num_vertices += VERTICES_PER_QUAD;
}
}
@@ -2084,8 +2113,8 @@ struct gl_video *gl_video_init(GL *gl, struct mp_log *log)
.gl = gl,
.log = log,
.opts = gl_video_opts_def,
+ .gl_target = GL_TEXTURE_2D,
.gl_debug = true,
- .colorspace = MP_CSP_DETAILS_DEFAULTS,
.scalers = {
{ .index = 0, .name = "bilinear" },
{ .index = 1, .name = "bilinear" },
diff --git a/video/out/gl_video.h b/video/out/gl_video.h
index 27da29461c..a4f864a9dd 100644
--- a/video/out/gl_video.h
+++ b/video/out/gl_video.h
@@ -46,6 +46,7 @@ struct gl_video_opts {
int stereo_mode;
int alpha_mode;
int chroma_location;
+ int use_rectangle;
};
extern const struct m_sub_options gl_video_conf;
diff --git a/video/out/gl_video_shaders.glsl b/video/out/gl_video_shaders.glsl
index b0df20b544..af966905a0 100644
--- a/video/out/gl_video_shaders.glsl
+++ b/video/out/gl_video_shaders.glsl
@@ -112,12 +112,13 @@ void main() {
}
#!section frag_video
-uniform sampler2D texture0;
-uniform sampler2D texture1;
-uniform sampler2D texture2;
-uniform sampler2D texture3;
+uniform VIDEO_SAMPLER texture0;
+uniform VIDEO_SAMPLER texture1;
+uniform VIDEO_SAMPLER texture2;
+uniform VIDEO_SAMPLER texture3;
uniform vec2 textures_size[4];
uniform vec2 chroma_center_offset;
+uniform vec2 chroma_div;
uniform sampler1D lut_c_1d;
uniform sampler1D lut_l_1d;
uniform sampler2D lut_c_2d;
@@ -140,7 +141,7 @@ DECLARE_FRAGPARMS
#define CONV_NV12 1
#define CONV_PLANAR 2
-vec4 sample_bilinear(sampler2D tex, vec2 texsize, vec2 texcoord) {
+vec4 sample_bilinear(VIDEO_SAMPLER tex, vec2 texsize, vec2 texcoord) {
return texture(tex, texcoord);
}
@@ -161,7 +162,7 @@ vec4 calcweights(float s) {
return t;
}
-vec4 sample_bicubic_fast(sampler2D tex, vec2 texsize, vec2 texcoord) {
+vec4 sample_bicubic_fast(VIDEO_SAMPLER tex, vec2 texsize, vec2 texcoord) {
vec2 pt = 1 / texsize;
vec2 fcoord = fract(texcoord * texsize + vec2(0.5, 0.5));
vec4 parmx = calcweights(fcoord.x);
@@ -222,7 +223,7 @@ float[16] weights16(sampler2D lookup, float f) {
}
#define CONVOLUTION_SEP_N(NAME, N) \
- vec4 NAME(sampler2D tex, vec2 texcoord, vec2 pt, float weights[N]) { \
+ vec4 NAME(VIDEO_SAMPLER 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); \
@@ -240,7 +241,7 @@ 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 texsize, \
+ vec4 NAME(vec2 dir, SAMPLERT lookup, VIDEO_SAMPLER tex, vec2 texsize, \
vec2 texcoord) { \
vec2 pt = (1 / texsize) * dir; \
float fcoord = dot(fract(texcoord * texsize - 0.5), dir); \
@@ -258,7 +259,7 @@ SAMPLE_CONVOLUTION_SEP_N(sample_convolution_sep16, 16, sampler2D, convolution_se
#define CONVOLUTION_N(NAME, N) \
- vec4 NAME(sampler2D tex, vec2 texcoord, vec2 pt, float taps_x[N], \
+ vec4 NAME(VIDEO_SAMPLER tex, vec2 texcoord, vec2 pt, float taps_x[N], \
float taps_y[N]) { \
vec4 res = vec4(0); \
for (int y = 0; y < N; y++) { \
@@ -278,7 +279,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 texsize, vec2 texcoord) {\
+ vec4 NAME(SAMPLERT lookup, VIDEO_SAMPLER tex, vec2 texsize, vec2 texcoord) {\
vec2 pt = 1 / texsize; \
vec2 fcoord = fract(texcoord * texsize - 0.5); \
vec2 base = texcoord - fcoord * pt; \
@@ -296,7 +297,7 @@ SAMPLE_CONVOLUTION_N(sample_convolution16, 16, sampler2D, convolution16, weights
// Unsharp masking
-vec4 sample_sharpen3(sampler2D tex, vec2 texsize, vec2 texcoord) {
+vec4 sample_sharpen3(VIDEO_SAMPLER tex, vec2 texsize, vec2 texcoord) {
vec2 pt = 1 / texsize;
vec2 st = pt * 0.5;
vec4 p = texture(tex, texcoord);
@@ -307,7 +308,7 @@ vec4 sample_sharpen3(sampler2D tex, vec2 texsize, vec2 texcoord) {
return p + (p - 0.25 * sum) * filter_param1;
}
-vec4 sample_sharpen5(sampler2D tex, vec2 texsize, vec2 texcoord) {
+vec4 sample_sharpen5(VIDEO_SAMPLER tex, vec2 texsize, vec2 texcoord) {
vec2 pt = 1 / texsize;
vec2 st1 = pt * 1.2;
vec4 p = texture(tex, texcoord);
@@ -325,7 +326,14 @@ vec4 sample_sharpen5(sampler2D tex, vec2 texsize, vec2 texcoord) {
}
void main() {
- vec2 chr_texcoord = texcoord + chroma_center_offset;
+ vec2 chr_texcoord = texcoord;
+#ifdef USE_RECTANGLE
+ chr_texcoord = chr_texcoord * chroma_div;
+#else
+ // Texture coordinates are [0,1], and chroma plane coordinates are
+ // magically rescaled.
+#endif
+ chr_texcoord = chr_texcoord + chroma_center_offset;
#ifndef USE_CONV
#define USE_CONV 0
#endif
diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c
index e086e36e7d..774d87ed05 100644
--- a/video/out/vo_opengl.c
+++ b/video/out/vo_opengl.c
@@ -206,6 +206,7 @@ static void load_hwdec_driver(struct gl_priv *p,
.log = mp_log_new(hwdec, p->vo->log, drv->api_name),
.mpgl = p->glctx,
.info = talloc_zero(hwdec, struct mp_hwdec_info),
+ .gl_texture_target = GL_TEXTURE_2D,
};
mpgl_lock(p->glctx);
if (hwdec->driver->create(hwdec) < 0) {