diff options
Diffstat (limited to 'libvo')
-rw-r--r-- | libvo/eosd_packer.c | 254 | ||||
-rw-r--r-- | libvo/eosd_packer.h | 71 | ||||
-rw-r--r-- | libvo/gl_common.c | 159 | ||||
-rw-r--r-- | libvo/gl_common.h | 11 | ||||
-rw-r--r-- | libvo/mga_template.c | 2 | ||||
-rw-r--r-- | libvo/video_out.c | 4 | ||||
-rw-r--r-- | libvo/vo_directfb2.c | 14 | ||||
-rw-r--r-- | libvo/vo_directx.c | 4 | ||||
-rw-r--r-- | libvo/vo_gl.c | 326 | ||||
-rw-r--r-- | libvo/vo_kva.c | 2 | ||||
-rw-r--r-- | libvo/vo_svga.c | 4 | ||||
-rw-r--r-- | libvo/vo_vdpau.c | 255 | ||||
-rw-r--r-- | libvo/wskeys.h | 85 | ||||
-rw-r--r-- | libvo/x11_common.c | 164 | ||||
-rw-r--r-- | libvo/x11_common.h | 3 |
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 419c0f2b94..2036ac1803 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 e68465f009..1ad893cf52 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) |