summaryrefslogtreecommitdiffstats
path: root/libvo
diff options
context:
space:
mode:
Diffstat (limited to 'libvo')
-rw-r--r--libvo/eosd_packer.c254
-rw-r--r--libvo/eosd_packer.h71
-rw-r--r--libvo/gl_common.c159
-rw-r--r--libvo/gl_common.h11
-rw-r--r--libvo/mga_template.c2
-rw-r--r--libvo/video_out.c4
-rw-r--r--libvo/vo_directfb2.c14
-rw-r--r--libvo/vo_directx.c4
-rw-r--r--libvo/vo_gl.c326
-rw-r--r--libvo/vo_kva.c2
-rw-r--r--libvo/vo_svga.c4
-rw-r--r--libvo/vo_vdpau.c255
-rw-r--r--libvo/wskeys.h85
-rw-r--r--libvo/x11_common.c164
-rw-r--r--libvo/x11_common.h3
15 files changed, 762 insertions, 596 deletions
diff --git a/libvo/eosd_packer.c b/libvo/eosd_packer.c
new file mode 100644
index 0000000000..103648b7c4
--- /dev/null
+++ b/libvo/eosd_packer.c
@@ -0,0 +1,254 @@
+/*
+ * Common code for packing EOSD images into larger surfaces.
+ *
+ * This file is part of mplayer2.
+ *
+ * mplayer2 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mplayer2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with mplayer2; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <libavutil/common.h>
+#include "talloc.h"
+#include "mp_msg.h"
+#include "eosd_packer.h"
+
+// Initial size of EOSD surface in pixels (x*x)
+#define EOSD_SURFACE_INITIAL_SIZE 256
+
+// Allocate an eosd_packer, which can be used to layout and cache the list of
+// EOSD images contained in a mp_eosd_images_t into a flat surface.
+// It can be free'd with talloc_free().
+// Don't forget to call eosd_init() before using it.
+struct eosd_packer *eosd_packer_create(void *talloc_ctx) {
+ return talloc_zero(talloc_ctx, struct eosd_packer);
+}
+
+// Call this when you need to completely reinitialize the EOSD state, e.g. when
+// when your EOSD surface was deleted.
+// max_width and max_height are the maximum surface sizes that should be
+// allowed.
+void eosd_packer_reinit(struct eosd_packer *state, uint32_t max_width,
+ uint32_t max_height)
+{
+ state->max_surface_width = max_width;
+ state->max_surface_height = max_height;
+ state->surface.w = 0;
+ state->surface.h = 0;
+ state->targets_count = 0;
+}
+
+#define HEIGHT_SORT_BITS 4
+static int size_index(struct eosd_target *r)
+{
+ unsigned int h = r->source.y1;
+ int n = av_log2_16bit(h);
+ return (n << HEIGHT_SORT_BITS)
+ + (- 1 - (h << HEIGHT_SORT_BITS >> n) & (1 << HEIGHT_SORT_BITS) - 1);
+}
+
+/* Pack the given rectangles into an area of size w * h.
+ * The size of each rectangle is read from .source.x1/.source.y1.
+ * The height of each rectangle must be at least 1 and less than 65536.
+ * The .source rectangle is then set corresponding to the packed position.
+ * 'scratch' must point to work memory for num_rects+16 ints.
+ * Return 0 on success, -1 if the rectangles did not fit in w*h.
+ *
+ * The rectangles are placed in rows in order approximately sorted by
+ * height (the approximate sorting is simpler than a full one would be,
+ * and allows the algorithm to work in linear time). Additionally, to
+ * reduce wasted space when there are a few tall rectangles, empty
+ * lower-right parts of rows are filled recursively when the size of
+ * rectangles in the row drops past a power-of-two threshold. So if a
+ * row starts with rectangles of size 3x50, 10x40 and 5x20 then the
+ * free rectangle with corners (13, 20)-(w, 50) is filled recursively.
+ */
+static int pack_rectangles(struct eosd_target *rects, int num_rects,
+ int w, int h, int *scratch)
+{
+ int bins[16 << HEIGHT_SORT_BITS];
+ int sizes[16 << HEIGHT_SORT_BITS] = {};
+ for (int i = 0; i < num_rects; i++)
+ sizes[size_index(rects + i)]++;
+ int idx = 0;
+ for (int i = 0; i < 16 << HEIGHT_SORT_BITS; i += 1 << HEIGHT_SORT_BITS) {
+ for (int j = 0; j < 1 << HEIGHT_SORT_BITS; j++) {
+ bins[i + j] = idx;
+ idx += sizes[i + j];
+ }
+ scratch[idx++] = -1;
+ }
+ for (int i = 0; i < num_rects; i++)
+ scratch[bins[size_index(rects + i)]++] = i;
+ for (int i = 0; i < 16; i++)
+ bins[i] = bins[i << HEIGHT_SORT_BITS] - sizes[i << HEIGHT_SORT_BITS];
+ struct {
+ int size, x, bottom;
+ } stack[16] = {{15, 0, h}}, s = {};
+ int stackpos = 1;
+ int y;
+ while (stackpos) {
+ y = s.bottom;
+ s = stack[--stackpos];
+ s.size++;
+ while (s.size--) {
+ int maxy = -1;
+ int obj;
+ while ((obj = scratch[bins[s.size]]) >= 0) {
+ int bottom = y + rects[obj].source.y1;
+ if (bottom > s.bottom)
+ break;
+ int right = s.x + rects[obj].source.x1;
+ if (right > w)
+ break;
+ bins[s.size]++;
+ rects[obj].source.x0 = s.x;
+ rects[obj].source.x1 += s.x;
+ rects[obj].source.y0 = y;
+ rects[obj].source.y1 += y;
+ num_rects--;
+ if (maxy <= 0)
+ stack[stackpos++] = s;
+ s.x = right;
+ maxy = FFMAX(maxy, bottom);
+ }
+ if (maxy > 0)
+ s.bottom = maxy;
+ }
+ }
+ return num_rects ? -1 : 0;
+}
+
+// padding to reduce interpolation artifacts when doing scaling & filtering
+#define EOSD_PADDING 0
+
+// Release all previous images, and packs the images in imgs into state. The
+// caller must check the change variables:
+// *out_need_reposition == true: sub-image positions changed
+// *out_need_upload == true: upload all sub-images again
+// *out_need_reallocate == true: resize the EOSD texture to state->surface.w/h
+// Logical implications: need_reallocate => need_upload => need_reposition
+void eosd_packer_generate(struct eosd_packer *state, mp_eosd_images_t *imgs,
+ bool *out_need_reposition, bool *out_need_upload,
+ bool *out_need_reallocate)
+{
+ int i;
+ ASS_Image *img = imgs->imgs;
+ ASS_Image *p;
+ struct eosd_surface *sfc = &state->surface;
+
+ *out_need_reposition = false;
+ *out_need_upload = false;
+ *out_need_reallocate = false;
+
+ int change_state = imgs->changed;
+
+ // eosd_reinit() was probably called, force full reupload.
+ if (state->targets_count == 0 && img)
+ change_state = 2;
+
+ if (change_state == 0)
+ return; // Nothing changed, no need to redraw
+
+ state->targets_count = 0;
+
+ *out_need_reposition = true;
+
+ if (!img)
+ return; // There's nothing to render!
+
+ if (change_state == 1)
+ goto eosd_skip_upload;
+
+ *out_need_upload = true;
+ while (1) {
+ for (p = img, i = 0; p; p = p->next) {
+ if (p->w <= 0 || p->h <= 0)
+ continue;
+ // Allocate new space for surface/target arrays
+ if (i >= state->targets_size) {
+ state->targets_size = FFMAX(state->targets_size * 2, 512);
+ state->targets =
+ talloc_realloc_size(state, state->targets,
+ state->targets_size
+ * sizeof(*state->targets));
+ state->scratch =
+ talloc_realloc_size(state, state->scratch,
+ (state->targets_size + 16)
+ * sizeof(*state->scratch));
+ }
+ state->targets[i].source.x1 = p->w + EOSD_PADDING;
+ state->targets[i].source.y1 = p->h + EOSD_PADDING;
+ i++;
+ }
+ if (pack_rectangles(state->targets, i, sfc->w, sfc->h,
+ state->scratch) >= 0)
+ break;
+ int w = FFMIN(FFMAX(sfc->w * 2, EOSD_SURFACE_INITIAL_SIZE),
+ state->max_surface_width);
+ int h = FFMIN(FFMAX(sfc->h * 2, EOSD_SURFACE_INITIAL_SIZE),
+ state->max_surface_height);
+ if (w == sfc->w && h == sfc->h) {
+ mp_msg(MSGT_VO, MSGL_ERR, "[eosd] EOSD bitmaps do not fit on "
+ "a surface with the maximum supported size\n");
+ return;
+ }
+ sfc->w = w;
+ sfc->h = h;
+ *out_need_reallocate = true;
+ }
+ if (*out_need_reallocate) {
+ mp_msg(MSGT_VO, MSGL_V, "[eosd] Allocate a %dx%d surface for "
+ "EOSD bitmaps.\n", sfc->w, sfc->h);
+ }
+
+eosd_skip_upload:
+ for (p = img; p; p = p->next) {
+ if (p->w <= 0 || p->h <= 0)
+ continue;
+ struct eosd_target *target = &state->targets[state->targets_count];
+ target->source.x1 -= EOSD_PADDING;
+ target->source.y1 -= EOSD_PADDING;
+ target->dest.x0 = p->dst_x;
+ target->dest.y0 = p->dst_y;
+ target->dest.x1 = p->w + p->dst_x;
+ target->dest.y1 = p->h + p->dst_y;
+ target->color = p->color;
+ target->ass_img = p;
+ state->targets_count++;
+ }
+}
+
+// Calculate the bounding box of all sub-rectangles in the EOSD surface that
+// will be used for EOSD rendering.
+// If the bounding box is empty, return false.
+bool eosd_packer_calculate_source_bb(struct eosd_packer *state,
+ struct eosd_rect *out_bb)
+{
+ struct eosd_rect bb = { state->surface.w, state->surface.h, 0, 0 };
+
+ for (int n = 0; n < state->targets_count; n++) {
+ struct eosd_rect s = state->targets[n].source;
+ bb.x0 = FFMIN(bb.x0, s.x0);
+ bb.y0 = FFMIN(bb.y0, s.y0);
+ bb.x1 = FFMAX(bb.x1, s.x1);
+ bb.y1 = FFMAX(bb.y1, s.y1);
+ }
+
+ // avoid degenerate bounding box if empty
+ bb.x0 = FFMIN(bb.x0, bb.x1);
+ bb.y0 = FFMIN(bb.y0, bb.y1);
+
+ *out_bb = bb;
+ return state->targets_count > 0;
+}
diff --git a/libvo/eosd_packer.h b/libvo/eosd_packer.h
new file mode 100644
index 0000000000..e207a4a2dd
--- /dev/null
+++ b/libvo/eosd_packer.h
@@ -0,0 +1,71 @@
+/*
+ * This file is part of mplayer2.
+ *
+ * mplayer2 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mplayer2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with mplayer2; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPLAYER_EOSD_PACKER_H
+#define MPLAYER_EOSD_PACKER_H
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include "sub/ass_mp.h"
+
+// Pool of surfaces
+struct eosd_surface {
+ //void *native_surface;
+ int w;
+ int h;
+};
+
+struct eosd_rect {
+ int x0, y0, x1, y1;
+};
+
+// List of surfaces to be rendered
+struct eosd_target {
+ struct eosd_rect source; // position in EOSD surface
+ struct eosd_rect dest; // position on screen
+ uint32_t color; // libass-style color of the image
+ // NOTE: This must not be accessed after you return from your VO's
+ // VOCTRL_DRAW_EOSD call - libass will free or reuse the associated
+ // memory. Feel free to set this to NULL to make erroneous accesses to
+ // this member fail early.
+ ASS_Image *ass_img;
+};
+
+struct eosd_packer {
+ struct eosd_surface surface;
+ struct eosd_target *targets;
+ int targets_count; // number of valid elements in targets
+ int targets_size; // number of allocated elements in targets
+
+ uint32_t max_surface_width;
+ uint32_t max_surface_height;
+
+ int *scratch;
+};
+
+struct eosd_packer *eosd_packer_create(void *talloc_ctx);
+void eosd_packer_reinit(struct eosd_packer *state, uint32_t max_width,
+ uint32_t max_height);
+void eosd_packer_generate(struct eosd_packer *state, mp_eosd_images_t *imgs,
+ bool *out_need_reposition, bool *out_need_upload,
+ bool *out_need_reallocate);
+bool eosd_packer_calculate_source_bb(struct eosd_packer *state,
+ struct eosd_rect *out_bb);
+
+#endif /* MPLAYER_EOSD_PACKER_H */
diff --git a/libvo/gl_common.c b/libvo/gl_common.c
index 7cca800d40..481d21e2fe 100644
--- a/libvo/gl_common.c
+++ b/libvo/gl_common.c
@@ -218,8 +218,8 @@ int glFindFormat(uint32_t fmt, int have_texture_rg, int *bpp, GLint *gl_texfmt,
// we do not support palettized formats, although the format the
// swscale produces works
case IMGFMT_RGB8:
- gl_format = GL_RGB;
- gl_type = GL_UNSIGNED_BYTE_2_3_3_REV;
+ *gl_format = GL_RGB;
+ *gl_type = GL_UNSIGNED_BYTE_2_3_3_REV;
break;
#endif
case IMGFMT_RGB15:
@@ -232,12 +232,12 @@ int glFindFormat(uint32_t fmt, int have_texture_rg, int *bpp, GLint *gl_texfmt,
break;
#if 0
case IMGFMT_BGR8:
- // special case as red and blue have a differen number of bits.
+ // special case as red and blue have a different number of bits.
// GL_BGR and GL_UNSIGNED_BYTE_3_3_2 isn't supported at least
// by nVidia drivers, and in addition would give more bits to
// blue than to red, which isn't wanted
- gl_format = GL_RGB;
- gl_type = GL_UNSIGNED_BYTE_3_3_2;
+ *gl_format = GL_RGB;
+ *gl_type = GL_UNSIGNED_BYTE_3_3_2;
break;
#endif
case IMGFMT_BGR15:
@@ -329,7 +329,6 @@ static const extfunc_desc_t extfuncs[] = {
DEF_FUNC_DESC(TexEnvf),
DEF_FUNC_DESC(TexEnvi),
DEF_FUNC_DESC(Color4ub),
- DEF_FUNC_DESC(Color3f),
DEF_FUNC_DESC(Color4f),
DEF_FUNC_DESC(ClearColor),
DEF_FUNC_DESC(ClearDepth),
@@ -360,6 +359,12 @@ static const extfunc_desc_t extfuncs[] = {
DEF_FUNC_DESC(ColorMask),
DEF_FUNC_DESC(ReadPixels),
DEF_FUNC_DESC(ReadBuffer),
+ DEF_FUNC_DESC(VertexPointer),
+ DEF_FUNC_DESC(ColorPointer),
+ DEF_FUNC_DESC(TexCoordPointer),
+ DEF_FUNC_DESC(DrawArrays),
+ DEF_FUNC_DESC(EnableClientState),
+ DEF_FUNC_DESC(DisableClientState),
DEF_EXT_DESC(GenBuffers, NULL,
("glGenBuffers", "glGenBuffersARB")),
@@ -855,11 +860,41 @@ static void gen_spline_lookup_tex(GL *gl, GLenum unit)
free(tex);
}
+#define NOISE_RES 2048
+
+/**
+ * \brief creates the 1D lookup texture needed to generate pseudo-random numbers.
+ * \param unit texture unit to attach texture to
+ */
+static void gen_noise_lookup_tex(GL *gl, GLenum unit) {
+ GLfloat *tex = calloc(NOISE_RES, sizeof(*tex));
+ uint32_t lcg = 0x79381c11;
+ int i;
+ for (i = 0; i < NOISE_RES; i++)
+ tex[i] = (double)i / (NOISE_RES - 1);
+ for (i = 0; i < NOISE_RES - 1; i++) {
+ int remain = NOISE_RES - i;
+ int idx = i + (lcg >> 16) % remain;
+ GLfloat tmp = tex[i];
+ tex[i] = tex[idx];
+ tex[idx] = tmp;
+ lcg = lcg * 1664525 + 1013904223;
+ }
+ gl->ActiveTexture(unit);
+ gl->TexImage1D(GL_TEXTURE_1D, 0, 1, NOISE_RES, 0, GL_RED, GL_FLOAT, tex);
+ gl->TexParameterf(GL_TEXTURE_1D, GL_TEXTURE_PRIORITY, 1.0);
+ gl->TexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ gl->TexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ gl->TexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ gl->ActiveTexture(GL_TEXTURE0);
+ free(tex);
+}
+
#define SAMPLE(dest, coord, texture) \
"TEX textemp, " coord ", " texture ", $tex_type;\n" \
"MOV " dest ", textemp.r;\n"
-static const char *bilin_filt_template =
+static const char bilin_filt_template[] =
SAMPLE("yuv.$out_comp","fragment.texcoord[$in_tex]","texture[$in_tex]");
#define BICUB_FILT_MAIN \
@@ -876,7 +911,7 @@ static const char *bilin_filt_template =
/* x-interpolation */ \
"LRP yuv.$out_comp, parmx.b, a.bbbb, a.aaaa;\n"
-static const char *bicub_filt_template_2D =
+static const char bicub_filt_template_2D[] =
"MAD coord.xy, fragment.texcoord[$in_tex], {$texw, $texh}, {0.5, 0.5};\n"
"TEX parmx, coord.x, texture[$texs], 1D;\n"
"MUL cdelta.xz, parmx.rrgg, {-$ptw, 0, $ptw, 0};\n"
@@ -884,7 +919,7 @@ static const char *bicub_filt_template_2D =
"MUL cdelta.yw, parmy.rrgg, {0, -$pth, 0, $pth};\n"
BICUB_FILT_MAIN;
-static const char *bicub_filt_template_RECT =
+static const char bicub_filt_template_RECT[] =
"ADD coord, fragment.texcoord[$in_tex], {0.5, 0.5};\n"
"TEX parmx, coord.x, texture[$texs], 1D;\n"
"MUL cdelta.xz, parmx.rrgg, {-1, 0, 1, 0};\n"
@@ -902,7 +937,7 @@ static const char *bicub_filt_template_RECT =
"ADD "t ".x, "t ".xxxx, "s ";\n" \
"SUB "t ".y, "t ".yyyy, "s ";\n"
-static const char *bicub_notex_filt_template_2D =
+static const char bicub_notex_filt_template_2D[] =
"MAD coord.xy, fragment.texcoord[$in_tex], {$texw, $texh}, {0.5, 0.5};\n"
"FRC coord.xy, coord.xyxy;\n"
CALCWEIGHTS("parmx", "coord.xxxx")
@@ -911,7 +946,7 @@ static const char *bicub_notex_filt_template_2D =
"MUL cdelta.yw, parmy.rrgg, {0, -$pth, 0, $pth};\n"
BICUB_FILT_MAIN;
-static const char *bicub_notex_filt_template_RECT =
+static const char bicub_notex_filt_template_RECT[] =
"ADD coord, fragment.texcoord[$in_tex], {0.5, 0.5};\n"
"FRC coord.xy, coord.xyxy;\n"
CALCWEIGHTS("parmx", "coord.xxxx")
@@ -928,19 +963,19 @@ static const char *bicub_notex_filt_template_RECT =
/* x-interpolation */ \
"LRP yuv.$out_comp, parmx.b, a.rrrr, b.rrrr;\n"
-static const char *bicub_x_filt_template_2D =
+static const char bicub_x_filt_template_2D[] =
"MAD coord.x, fragment.texcoord[$in_tex], {$texw}, {0.5};\n"
"TEX parmx, coord, texture[$texs], 1D;\n"
"MUL cdelta.xyz, parmx.rrgg, {-$ptw, 0, $ptw};\n"
BICUB_X_FILT_MAIN;
-static const char *bicub_x_filt_template_RECT =
+static const char bicub_x_filt_template_RECT[] =
"ADD coord.x, fragment.texcoord[$in_tex], {0.5};\n"
"TEX parmx, coord, texture[$texs], 1D;\n"
"MUL cdelta.xyz, parmx.rrgg, {-1, 0, 1};\n"
BICUB_X_FILT_MAIN;
-static const char *unsharp_filt_template =
+static const char unsharp_filt_template[] =
"PARAM dcoord$out_comp = {$ptw_05, $pth_05, $ptw_05, -$pth_05};\n"
"ADD coord, fragment.texcoord[$in_tex].xyxy, dcoord$out_comp;\n"
"SUB coord2, fragment.texcoord[$in_tex].xyxy, dcoord$out_comp;\n"
@@ -955,7 +990,7 @@ static const char *unsharp_filt_template =
"MAD textemp.r, b.r, {$strength}, a.r;\n"
"MOV yuv.$out_comp, textemp.r;\n";
-static const char *unsharp_filt_template2 =
+static const char unsharp_filt_template2[] =
"PARAM dcoord$out_comp = {$ptw_12, $pth_12, $ptw_12, -$pth_12};\n"
"PARAM dcoord2$out_comp = {$ptw_15, 0, 0, $pth_15};\n"
"ADD coord, fragment.texcoord[$in_tex].xyxy, dcoord$out_comp;\n"
@@ -980,7 +1015,7 @@ static const char *unsharp_filt_template2 =
"MAD textemp.r, b.r, {$strength}, a.r;\n"
"MOV yuv.$out_comp, textemp.r;\n";
-static const char *yuv_prog_template =
+static const char yuv_prog_template[] =
"PARAM ycoef = {$cm11, $cm21, $cm31};\n"
"PARAM ucoef = {$cm12, $cm22, $cm32};\n"
"PARAM vcoef = {$cm13, $cm23, $cm33};\n"
@@ -988,10 +1023,9 @@ static const char *yuv_prog_template =
"TEMP res;\n"
"MAD res.rgb, yuv.rrrr, ycoef, offsets;\n"
"MAD res.rgb, yuv.gggg, ucoef, res;\n"
- "MAD result.color.rgb, yuv.bbbb, vcoef, res;\n"
- "END";
+ "MAD res.rgb, yuv.bbbb, vcoef, res;\n";
-static const char *yuv_pow_prog_template =
+static const char yuv_pow_prog_template[] =
"PARAM ycoef = {$cm11, $cm21, $cm31};\n"
"PARAM ucoef = {$cm12, $cm22, $cm32};\n"
"PARAM vcoef = {$cm13, $cm23, $cm33};\n"
@@ -1001,12 +1035,11 @@ static const char *yuv_pow_prog_template =
"MAD res.rgb, yuv.rrrr, ycoef, offsets;\n"
"MAD res.rgb, yuv.gggg, ucoef, res;\n"
"MAD_SAT res.rgb, yuv.bbbb, vcoef, res;\n"
- "POW result.color.r, res.r, gamma.r;\n"
- "POW result.color.g, res.g, gamma.g;\n"
- "POW result.color.b, res.b, gamma.b;\n"
- "END";
+ "POW res.r, res.r, gamma.r;\n"
+ "POW res.g, res.g, gamma.g;\n"
+ "POW res.b, res.b, gamma.b;\n";
-static const char *yuv_lookup_prog_template =
+static const char yuv_lookup_prog_template[] =
"PARAM ycoef = {$cm11, $cm21, $cm31, 0};\n"
"PARAM ucoef = {$cm12, $cm22, $cm32, 0};\n"
"PARAM vcoef = {$cm13, $cm23, $cm33, 0};\n"
@@ -1015,16 +1048,23 @@ static const char *yuv_lookup_prog_template =
"MAD res, yuv.rrrr, ycoef, offsets;\n"
"MAD res.rgb, yuv.gggg, ucoef, res;\n"
"MAD res.rgb, yuv.bbbb, vcoef, res;\n"
- "TEX result.color.r, res.raaa, texture[$conv_tex0], 2D;\n"
+ "TEX res.r, res.raaa, texture[$conv_tex0], 2D;\n"
"ADD res.a, res.a, 0.25;\n"
- "TEX result.color.g, res.gaaa, texture[$conv_tex0], 2D;\n"
+ "TEX res.g, res.gaaa, texture[$conv_tex0], 2D;\n"
"ADD res.a, res.a, 0.25;\n"
- "TEX result.color.b, res.baaa, texture[$conv_tex0], 2D;\n"
- "END";
+ "TEX res.b, res.baaa, texture[$conv_tex0], 2D;\n";
+
+static const char yuv_lookup3d_prog_template[] =
+ "TEMP res;\n"
+ "TEX res, yuv, texture[$conv_tex0], 3D;\n";
-static const char *yuv_lookup3d_prog_template =
- "TEX result.color, yuv, texture[$conv_tex0], 3D;\n"
- "END";
+static const char noise_filt_template[] =
+ "MUL coord.xy, fragment.texcoord[0], {$noise_sx, $noise_sy};\n"
+ "TEMP rand;\n"
+ "TEX rand.r, coord.x, texture[$noise_filt_tex], 1D;\n"
+ "ADD rand.r, rand.r, coord.y;\n"
+ "TEX rand.r, rand.r, texture[$noise_filt_tex], 1D;\n"
+ "MAD res.rgb, rand.rrrr, {$noise_str, $noise_str, $noise_str}, res;\n";
/**
* \brief creates and initializes helper textures needed for scaling texture read
@@ -1269,10 +1309,12 @@ static void glSetupYUVFragprog(GL *gl, gl_conversion_params_t *params)
char lum_scale_texs[1];
char chrom_scale_texs[1];
char conv_texs[1];
+ char filt_texs[1] = {0};
GLint i;
// this is the conversion matrix, with y, u, v factors
// for red, green, blue and the constant offsets
float yuv2rgb[3][4];
+ int noise = params->noise_strength != 0;
create_conv_textures(gl, params, &cur_texu, conv_texs);
create_scaler_textures(gl, YUV_LUM_SCALER(type), &cur_texu, lum_scale_texs);
if (YUV_CHROM_SCALER(type) == YUV_LUM_SCALER(type))
@@ -1280,6 +1322,12 @@ static void glSetupYUVFragprog(GL *gl, gl_conversion_params_t *params)
else
create_scaler_textures(gl, YUV_CHROM_SCALER(type), &cur_texu,
chrom_scale_texs);
+
+ if (noise) {
+ gen_noise_lookup_tex(gl, cur_texu);
+ filt_texs[0] = '0' + cur_texu++;
+ }
+
gl->GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &i);
if (i < cur_texu)
mp_msg(MSGT_VO, MSGL_ERR,
@@ -1328,6 +1376,25 @@ static void glSetupYUVFragprog(GL *gl, gl_conversion_params_t *params)
replace_var_float(prog, "gamma_g", (float)1.0 / params->csp_params.ggamma);
replace_var_float(prog, "gamma_b", (float)1.0 / params->csp_params.bgamma);
replace_var_char(prog, "conv_tex0", conv_texs[0]);
+
+ if (noise) {
+ // 1.0 strength is suitable for dithering 8 to 6 bit
+ double str = params->noise_strength * (1.0 / 64);
+ double scale_x = (double)NOISE_RES / texw;
+ double scale_y = (double)NOISE_RES / texh;
+ if (rect) {
+ scale_x /= texw;
+ scale_y /= texh;
+ }
+ append_template(prog, noise_filt_template);
+ replace_var_float(prog, "noise_sx", scale_x);
+ replace_var_float(prog, "noise_sy", scale_y);
+ replace_var_char(prog, "noise_filt_tex", filt_texs[0]);
+ replace_var_float(prog, "noise_str", str);
+ }
+
+ append_template(prog, "MOV result.color.rgb, res;\nEND");
+
mp_msg(MSGT_VO, MSGL_DBG2, "[gl] generated fragment program:\n%s\n",
yuv_prog);
loadGPUProgram(gl, GL_FRAGMENT_PROGRAM, yuv_prog);
@@ -2020,6 +2087,36 @@ static void new_vo_sdl_fullscreen(struct vo *vo) { vo_sdl_fullscreen(); }
#endif
+struct backend {
+ const char *name;
+ enum MPGLType type;
+};
+
+static struct backend backends[] = {
+ {"auto", GLTYPE_AUTO},
+ {"cocoa", GLTYPE_COCOA},
+ {"win", GLTYPE_W32},
+ {"x11", GLTYPE_X11},
+ {"sdl", GLTYPE_SDL},
+ // mplayer-svn aliases (note that mplayer-svn couples these with the numeric
+ // values of the internal GLTYPE_* constants)
+ {"-1", GLTYPE_AUTO},
+ { "0", GLTYPE_W32},
+ { "1", GLTYPE_X11},
+ { "2", GLTYPE_SDL},
+
+ {0}
+};
+
+int mpgl_find_backend(const char *name)
+{
+ for (const struct backend *entry = backends; entry->name; entry++) {
+ if (strcmp(entry->name, name) == 0)
+ return entry->type;
+ }
+ return -1;
+}
+
MPGLContext *init_mpglcontext(enum MPGLType type, struct vo *vo)
{
MPGLContext *ctx;
diff --git a/libvo/gl_common.h b/libvo/gl_common.h
index 8e3294f441..d0b447fab7 100644
--- a/libvo/gl_common.h
+++ b/libvo/gl_common.h
@@ -335,6 +335,7 @@ typedef struct {
int chrom_texw;
int chrom_texh;
float filter_strength;
+ float noise_strength;
} gl_conversion_params_t;
int glAutodetectYUVConversion(GL *gl);
@@ -398,6 +399,8 @@ typedef struct MPGLContext {
void (*ontop)(struct vo *vo);
} MPGLContext;
+int mpgl_find_backend(const char *name);
+
MPGLContext *init_mpglcontext(enum MPGLType type, struct vo *vo);
void uninit_mpglcontext(MPGLContext *ctx);
@@ -426,7 +429,6 @@ struct GL {
void (GLAPIENTRY *TexEnvf)(GLenum, GLenum, GLfloat);
void (GLAPIENTRY *TexEnvi)(GLenum, GLenum, GLint);
void (GLAPIENTRY *Color4ub)(GLubyte, GLubyte, GLubyte, GLubyte);
- void (GLAPIENTRY *Color3f)(GLfloat, GLfloat, GLfloat);
void (GLAPIENTRY *Color4f)(GLfloat, GLfloat, GLfloat, GLfloat);
void (GLAPIENTRY *ClearColor)(GLclampf, GLclampf, GLclampf, GLclampf);
void (GLAPIENTRY *ClearDepth)(GLclampd);
@@ -463,6 +465,13 @@ struct GL {
void (GLAPIENTRY *ReadPixels)(GLint, GLint, GLsizei, GLsizei, GLenum,
GLenum, GLvoid *);
void (GLAPIENTRY *ReadBuffer)(GLenum);
+ void (GLAPIENTRY *VertexPointer)(GLint, GLenum, GLsizei, const GLvoid *);
+ void (GLAPIENTRY *ColorPointer)(GLint, GLenum, GLsizei, const GLvoid *);
+ void (GLAPIENTRY *TexCoordPointer)(GLint, GLenum, GLsizei, const GLvoid *);
+ void (GLAPIENTRY *DrawArrays)(GLenum, GLint, GLsizei);
+ void (GLAPIENTRY *EnableClientState)(GLenum);
+ void (GLAPIENTRY *DisableClientState)(GLenum);
+
// OpenGL extension functions
void (GLAPIENTRY *GenBuffers)(GLsizei, GLuint *);
diff --git a/libvo/mga_template.c b/libvo/mga_template.c
index 6886ecd8f7..274be76098 100644
--- a/libvo/mga_template.c
+++ b/libvo/mga_template.c
@@ -189,7 +189,7 @@ draw_image(mp_image_t *mpi){
if(mpi->flags&MP_IMGFLAG_PLANAR){
// copy planar:
- draw_slice(mpi->planes,mpi->stride,mpi->w,mpi->h,mpi->x,mpi->y);
+ draw_slice(mpi->planes,mpi->stride,mpi->w,mpi->h,0,0);
} else {
// copy packed:
mem2agpcpy_pic(vid_data, mpi->planes[0], // dst,src
diff --git a/libvo/video_out.c b/libvo/video_out.c
index 9573439882..1d81000795 100644
--- a/libvo/video_out.c
+++ b/libvo/video_out.c
@@ -84,7 +84,6 @@ extern struct vo_driver video_out_vdpau;
extern struct vo_driver video_out_xv;
extern struct vo_driver video_out_gl_nosw;
extern struct vo_driver video_out_gl;
-extern struct vo_driver video_out_gl_sdl;
extern struct vo_driver video_out_dga;
extern struct vo_driver video_out_sdl;
extern struct vo_driver video_out_3dfx;
@@ -181,9 +180,6 @@ const struct vo_driver *video_out_drivers[] =
#ifdef CONFIG_GL
&video_out_gl,
#endif
-#ifdef CONFIG_GL_SDL
- &video_out_gl_sdl,
-#endif
#ifdef CONFIG_DGA
&video_out_dga,
#endif
diff --git a/libvo/vo_directfb2.c b/libvo/vo_directfb2.c
index d21c9e37c6..b50adba614 100644
--- a/libvo/vo_directfb2.c
+++ b/libvo/vo_directfb2.c
@@ -1279,7 +1279,7 @@ static uint32_t put_image(mp_image_t *mpi){
p = FFMIN(mpi->w, pitch);
- src = mpi->planes[0]+mpi->y*mpi->stride[0]+mpi->x;
+ src = mpi->planes[0];
for (i=0;i<mpi->h;i++) {
fast_memcpy(dst+i*pitch,src+i*mpi->stride[0],p);
@@ -1290,14 +1290,14 @@ static uint32_t put_image(mp_image_t *mpi){
dst += pitch*height;
p = p/2;
- src = mpi->planes[2]+mpi->y*mpi->stride[2]+mpi->x/2;
+ src = mpi->planes[2];
for (i=0;i<mpi->h/2;i++) {
fast_memcpy(dst+i*pitch/2,src+i*mpi->stride[2],p);
}
dst += pitch*height/4;
- src = mpi->planes[1]+mpi->y*mpi->stride[1]+mpi->x/2;
+ src = mpi->planes[1];
for (i=0;i<mpi->h/2;i++) {
fast_memcpy(dst+i*pitch/2,src+i*mpi->stride[1],p);
@@ -1307,14 +1307,14 @@ static uint32_t put_image(mp_image_t *mpi){
dst += pitch*height;
p = p/2;
- src = mpi->planes[1]+mpi->y*mpi->stride[1]+mpi->x/2;
+ src = mpi->planes[1];
for (i=0;i<mpi->h/2;i++) {
fast_memcpy(dst+i*pitch/2,src+i*mpi->stride[1],p);
}
dst += pitch*height/4;
- src = mpi->planes[2]+mpi->y*mpi->stride[2]+mpi->x/2;
+ src = mpi->planes[2];
for (i=0;i<mpi->h/2;i++) {
fast_memcpy(dst+i*pitch/2,src+i*mpi->stride[2],p);
@@ -1356,11 +1356,11 @@ static uint32_t put_image(mp_image_t *mpi){
if (frame) {
DFBCHECK (frame->Lock(frame,DSLF_WRITE,(void *)&dst,&pitch));
framelocked = 1;
- mem2agpcpy_pic(dst,mpi->planes[0] + mpi->y * mpi->stride[0] + mpi->x * (mpi->bpp >> 3) ,mpi->w * (mpi->bpp >> 3),mpi->h,pitch,mpi->stride[0]);
+ mem2agpcpy_pic(dst,mpi->planes[0] ,mpi->w * (mpi->bpp >> 3),mpi->h,pitch,mpi->stride[0]);
} else {
DFBCHECK (primary->Lock(primary,DSLF_WRITE,(void *)&dst,&pitch));
primarylocked = 1;
- mem2agpcpy_pic(dst + yoffset * pitch + xoffset * (mpi->bpp >> 3),mpi->planes[0] + mpi->y * mpi->stride[0] + mpi->x * (mpi->bpp >> 3) ,mpi->w * (mpi->bpp >> 3),mpi->h,pitch,mpi->stride[0]);
+ mem2agpcpy_pic(dst + yoffset * pitch + xoffset * (mpi->bpp >> 3),mpi->planes[0] ,mpi->w * (mpi->bpp >> 3),mpi->h,pitch,mpi->stride[0]);
};
unlock();
diff --git a/libvo/vo_directx.c b/libvo/vo_directx.c
index d504e23567..c937e13618 100644
--- a/libvo/vo_directx.c
+++ b/libvo/vo_directx.c
@@ -930,8 +930,8 @@ static uint32_t put_image(mp_image_t *mpi){
uint8_t *d;
uint8_t *s;
- uint32_t x = mpi->x;
- uint32_t y = mpi->y;
+ uint32_t x = 0;
+ uint32_t y = 0;
uint32_t w = mpi->w;
uint32_t h = mpi->h;
diff --git a/libvo/vo_gl.c b/libvo/vo_gl.c
index 12749426ab..adb5c55a74 100644
--- a/libvo/vo_gl.c
+++ b/libvo/vo_gl.c
@@ -38,6 +38,7 @@
#include "osd.h"
#include "sub/font_load.h"
#include "sub/sub.h"
+#include "eosd_packer.h"
#include "gl_common.h"
#include "aspect.h"
@@ -49,19 +50,17 @@ static int preinit_nosw(struct vo *vo, const char *arg);
//! How many parts the OSD may consist of at most
#define MAX_OSD_PARTS 20
-#define LARGE_EOSD_TEX_SIZE 512
-#define TINYTEX_SIZE 16
-#define TINYTEX_COLS (LARGE_EOSD_TEX_SIZE / TINYTEX_SIZE)
-#define TINYTEX_MAX (TINYTEX_COLS * TINYTEX_COLS)
-#define SMALLTEX_SIZE 32
-#define SMALLTEX_COLS (LARGE_EOSD_TEX_SIZE / SMALLTEX_SIZE)
-#define SMALLTEX_MAX (SMALLTEX_COLS * SMALLTEX_COLS)
-
//for gl_priv.use_yuv
#define MASK_ALL_YUV (~(1 << YUV_CONVERSION_NONE))
#define MASK_NOT_COMBINERS (~((1 << YUV_CONVERSION_NONE) | (1 << YUV_CONVERSION_COMBINERS)))
#define MASK_GAMMA_SUPPORT (MASK_NOT_COMBINERS & ~(1 << YUV_CONVERSION_FRAGMENT))
+struct vertex_eosd {
+ float x, y;
+ uint8_t color[4];
+ float u, v;
+};