aboutsummaryrefslogtreecommitdiffhomepage
path: root/libvo
diff options
context:
space:
mode:
Diffstat (limited to 'libvo')
-rw-r--r--libvo/aspect.c148
-rw-r--r--libvo/aspect.h37
-rw-r--r--libvo/bitmap_packer.c227
-rw-r--r--libvo/bitmap_packer.h68
-rw-r--r--libvo/cocoa_common.h55
-rw-r--r--libvo/cocoa_common.m865
-rw-r--r--libvo/csputils.c391
-rw-r--r--libvo/csputils.h151
-rw-r--r--libvo/d3d_shader_yuv.h142
-rw-r--r--libvo/d3d_shader_yuv.hlsl44
-rw-r--r--libvo/d3d_shader_yuv_2ch.h170
-rw-r--r--libvo/fastmemcpy.h77
-rw-r--r--libvo/filter_kernels.c279
-rw-r--r--libvo/filter_kernels.h45
-rw-r--r--libvo/geometry.c112
-rw-r--r--libvo/geometry.h29
-rw-r--r--libvo/gl_common.c2654
-rw-r--r--libvo/gl_common.h396
-rw-r--r--libvo/gl_header_fixes.h257
-rw-r--r--libvo/gl_osd.c324
-rw-r--r--libvo/gl_osd.h43
-rw-r--r--libvo/osx_common.c145
-rw-r--r--libvo/osx_common.h27
-rw-r--r--libvo/video_out.c530
-rw-r--r--libvo/video_out.h352
-rw-r--r--libvo/vo_caca.c395
-rw-r--r--libvo/vo_corevideo.h28
-rw-r--r--libvo/vo_corevideo.m457
-rw-r--r--libvo/vo_direct3d.c2101
-rw-r--r--libvo/vo_image.c198
-rw-r--r--libvo/vo_lavc.c553
-rw-r--r--libvo/vo_null.c103
-rw-r--r--libvo/vo_opengl.c2419
-rw-r--r--libvo/vo_opengl_old.c1166
-rw-r--r--libvo/vo_opengl_shaders.glsl355
-rw-r--r--libvo/vo_vdpau.c1718
-rw-r--r--libvo/vo_x11.c620
-rw-r--r--libvo/vo_xv.c716
-rw-r--r--libvo/w32_common.c757
-rw-r--r--libvo/w32_common.h66
-rw-r--r--libvo/x11_common.c2404
-rw-r--r--libvo/x11_common.h184
42 files changed, 0 insertions, 21808 deletions
diff --git a/libvo/aspect.c b/libvo/aspect.c
deleted file mode 100644
index f3cd00a5e5..0000000000
--- a/libvo/aspect.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/* Stuff for correct aspect scaling. */
-#include "aspect.h"
-#include "geometry.h"
-#include "video_out.h"
-#include "mp_msg.h"
-#include "options.h"
-
-#include "video_out.h"
-
-void aspect_save_videores(struct vo *vo, int w, int h, int d_w, int d_h)
-{
- vo->aspdat.orgw = w;
- vo->aspdat.orgh = h;
- vo->aspdat.prew = d_w;
- vo->aspdat.preh = d_h;
- vo->aspdat.par = (double)d_w / d_h * h / w;
-}
-
-void aspect_save_screenres(struct vo *vo, int scrw, int scrh)
-{
- mp_msg(MSGT_VO, MSGL_DBG2, "aspect_save_screenres %dx%d\n", scrw, scrh);
- struct MPOpts *opts = vo->opts;
- if (scrw <= 0 && scrh <= 0)
- scrw = 1024;
- if (scrh <= 0)
- scrh = (scrw * 3 + 3) / 4;
- if (scrw <= 0)
- scrw = (scrh * 4 + 2) / 3;
- vo->aspdat.scrw = scrw;
- vo->aspdat.scrh = scrh;
- if (opts->force_monitor_aspect)
- vo->monitor_par = opts->force_monitor_aspect * scrh / scrw;
- else
- vo->monitor_par = 1.0 / opts->monitor_pixel_aspect;
-}
-
-/* aspect is called with the source resolution and the
- * resolution, that the scaled image should fit into
- */
-
-void aspect_fit(struct vo *vo, int *srcw, int *srch, int fitw, int fith)
-{
- struct aspect_data *aspdat = &vo->aspdat;
- float pixelaspect = vo->monitor_par;
-
- mp_msg(MSGT_VO, MSGL_DBG2, "aspect(0) fitin: %dx%d monitor_par: %.2f\n",
- fitw, fith, vo->monitor_par);
- *srcw = fitw;
- *srch = (float)fitw / aspdat->prew * aspdat->preh / pixelaspect;
- *srch += *srch % 2; // round
- mp_msg(MSGT_VO, MSGL_DBG2, "aspect(1) wh: %dx%d (org: %dx%d)\n",
- *srcw, *srch, aspdat->prew, aspdat->preh);
- if (*srch > fith || *srch < aspdat->orgh) {
- int tmpw = (float)fith / aspdat->preh * aspdat->prew * pixelaspect;
- tmpw += tmpw % 2; // round
- if (tmpw <= fitw) {
- *srch = fith;
- *srcw = tmpw;
- } else if (*srch > fith) {
- mp_tmsg(MSGT_VO, MSGL_WARN,
- "[ASPECT] Warning: No suitable new res found!\n");
- }
- }
- aspdat->asp = *srcw / (float)*srch;
- mp_msg(MSGT_VO, MSGL_DBG2, "aspect(2) wh: %dx%d (org: %dx%d)\n",
- *srcw, *srch, aspdat->prew, aspdat->preh);
-}
-
-static void get_max_dims(struct vo *vo, int *w, int *h, int zoom)
-{
- struct aspect_data *aspdat = &vo->aspdat;
- *w = zoom ? aspdat->scrw : aspdat->prew;
- *h = zoom ? aspdat->scrh : aspdat->preh;
- if (zoom && WinID >= 0)
- zoom = A_WINZOOM;
- if (zoom == A_WINZOOM) {
- *w = vo->dwidth;
- *h = vo->dheight;
- }
-}
-
-void aspect(struct vo *vo, int *srcw, int *srch, int zoom)
-{
- int fitw;
- int fith;
- get_max_dims(vo, &fitw, &fith, zoom);
- if (!zoom && geometry_wh_changed) {
- mp_msg(MSGT_VO, MSGL_DBG2, "aspect(0) no aspect forced!\n");
- return; // the user doesn't want to fix aspect
- }
- aspect_fit(vo, srcw, srch, fitw, fith);
-}
-
-void panscan_init(struct vo *vo)
-{
- vo->panscan_x = 0;
- vo->panscan_y = 0;
- vo->panscan_amount = 0.0f;
-}
-
-static void panscan_calc_internal(struct vo *vo, int zoom)
-{
- int fwidth, fheight;
- int vo_panscan_area;
- int max_w, max_h;
- get_max_dims(vo, &max_w, &max_h, zoom);
- struct MPOpts *opts = vo->opts;
-
- if (opts->vo_panscanrange > 0) {
- aspect(vo, &fwidth, &fheight, zoom);
- vo_panscan_area = max_h - fheight;
- if (!vo_panscan_area)
- vo_panscan_area = max_w - fwidth;
- vo_panscan_area *= opts->vo_panscanrange;
- } else
- vo_panscan_area = -opts->vo_panscanrange * max_h;
-
- vo->panscan_amount = vo_fs || zoom == A_WINZOOM ? vo_panscan : 0;
- vo->panscan_x = vo_panscan_area * vo->panscan_amount * vo->aspdat.asp;
- vo->panscan_y = vo_panscan_area * vo->panscan_amount;
-}
-
-/**
- * vos that set vo_dwidth and v_dheight correctly should call this to update
- * vo_panscan_x and vo_panscan_y
- */
-void panscan_calc_windowed(struct vo *vo)
-{
- panscan_calc_internal(vo, A_WINZOOM);
-}
diff --git a/libvo/aspect.h b/libvo/aspect.h
deleted file mode 100644
index c5247421d2..0000000000
--- a/libvo/aspect.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_ASPECT_H
-#define MPLAYER_ASPECT_H
-/* Stuff for correct aspect scaling. */
-
-struct vo;
-void panscan_init(struct vo *vo);
-void panscan_calc_windowed(struct vo *vo);
-
-void aspect_save_videores(struct vo *vo, int w, int h, int d_w, int d_h);
-void aspect_save_screenres(struct vo *vo, int scrw, int scrh);
-
-#define A_WINZOOM 2 ///< zoom to fill window size
-#define A_ZOOM 1
-#define A_NOZOOM 0
-
-void aspect(struct vo *vo, int *srcw, int *srch, int zoom);
-void aspect_fit(struct vo *vo, int *srcw, int *srch, int fitw, int fith);
-
-#endif /* MPLAYER_ASPECT_H */
diff --git a/libvo/bitmap_packer.c b/libvo/bitmap_packer.c
deleted file mode 100644
index 603a6ce410..0000000000
--- a/libvo/bitmap_packer.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Calculate how to pack bitmap rectangles into a larger surface
- *
- * Copyright 2009, 2012 Uoti Urpala
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdlib.h>
-#include <assert.h>
-
-#include <libavutil/common.h>
-
-#include "talloc.h"
-#include "bitmap_packer.h"
-#include "mp_msg.h"
-#include "mpcommon.h"
-#include "sub/dec_sub.h"
-#include "fastmemcpy.h"
-
-#define IS_POWER_OF_2(x) (((x) > 0) && !(((x) - 1) & (x)))
-
-void packer_reset(struct bitmap_packer *packer)
-{
- struct bitmap_packer old = *packer;
- *packer = (struct bitmap_packer) {
- .w_max = old.w_max,
- .h_max = old.h_max,
- };
- talloc_free_children(packer);
-}
-
-void packer_get_bb(struct bitmap_packer *packer, struct pos out_bb[2])
-{
- out_bb[0] = (struct pos) {0};
- out_bb[1] = (struct pos) {
- FFMIN(packer->used_width + packer->padding, packer->w),
- FFMIN(packer->used_height + packer->padding, packer->h),
- };
-}
-
-#define HEIGHT_SORT_BITS 4
-static int size_index(int s)
-{
- int n = av_log2_16bit(s);
- return (n << HEIGHT_SORT_BITS)
- + (- 1 - (s << 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 in[i].x / in[i].y.
- * The height of each rectangle must be less than 65536.
- * 'scratch' must point to work memory for num_rects+16 ints.
- * The packed position for rectangle number i is set in out[i].
- * 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 pos *in, struct pos *out, int num_rects,
- int w, int h, int *scratch, int *used_width)
-{
- int bins[16 << HEIGHT_SORT_BITS];
- int sizes[16 << HEIGHT_SORT_BITS] = { 0 };
- for (int i = 0; i < num_rects; i++)
- sizes[size_index(in[i].y)]++;
- 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(in[i].y)]++] = 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 + in[obj].y;
- if (bottom > s.bottom)
- break;
- int right = s.x + in[obj].x;
- if (right > w)
- break;
- bins[s.size]++;
- out[obj] = (struct pos){s.x, y};
- num_rects--;
- if (maxy < 0)
- stack[stackpos++] = s;
- s.x = right;
- maxy = FFMAX(maxy, bottom);
- }
- *used_width = FFMAX(*used_width, s.x);
- if (maxy > 0)
- s.bottom = maxy;
- }
- }
- return num_rects ? -1 : y;
-}
-
-int packer_pack(struct bitmap_packer *packer)
-{
- if (packer->count == 0)
- return 0;
- int w_orig = packer->w, h_orig = packer->h;
- struct pos *in = packer->in;
- int xmax = 0, ymax = 0;
- for (int i = 0; i < packer->count; i++) {
- if (in[i].x <= packer->padding || in[i].y <= packer->padding)
- in[i] = (struct pos){0, 0};
- if (in[i].x < 0 || in [i].x > 65535 || in[i].y < 0 || in[i].y > 65535) {
- mp_msg(MSGT_VO, MSGL_FATAL, "Invalid OSD / subtitle bitmap size\n");
- abort();
- }
- xmax = FFMAX(xmax, in[i].x);
- ymax = FFMAX(ymax, in[i].y);
- }
- xmax = FFMAX(0, xmax - packer->padding);
- ymax = FFMAX(0, ymax - packer->padding);
- if (xmax > packer->w)
- packer->w = 1 << av_log2(xmax - 1) + 1;
- if (ymax > packer->h)
- packer->h = 1 << av_log2(ymax - 1) + 1;
- while (1) {
- int used_width = 0;
- int y = pack_rectangles(in, packer->result, packer->count,
- packer->w + packer->padding,
- packer->h + packer->padding,
- packer->scratch, &used_width);
- if (y >= 0) {
- // No padding at edges
- packer->used_width = FFMIN(used_width, packer->w);
- packer->used_height = FFMIN(y, packer->h);
- assert(packer->w == 0 || IS_POWER_OF_2(packer->w));
- assert(packer->h == 0 || IS_POWER_OF_2(packer->h));
- return packer->w != w_orig || packer->h != h_orig;
- }
- if (packer->w <= packer->h && packer->w != packer->w_max)
- packer->w = FFMIN(packer->w * 2, packer->w_max);
- else if (packer->h != packer->h_max)
- packer->h = FFMIN(packer->h * 2, packer->h_max);
- else {
- packer->w = w_orig;
- packer->h = h_orig;
- return -1;
- }
- }
-}
-
-void packer_set_size(struct bitmap_packer *packer, int size)
-{
- packer->count = size;
- if (size <= packer->asize)
- return;
- packer->asize = FFMAX(packer->asize * 2, size);
- talloc_free(packer->result);
- talloc_free(packer->scratch);
- packer->in = talloc_realloc(packer, packer->in, struct pos, packer->asize);
- packer->result = talloc_array_ptrtype(packer, packer->result,
- packer->asize);
- packer->scratch = talloc_array_ptrtype(packer, packer->scratch,
- packer->asize + 16);
-}
-
-int packer_pack_from_subbitmaps(struct bitmap_packer *packer,
- struct sub_bitmaps *b)
-{
- packer->count = 0;
- if (b->format == SUBBITMAP_EMPTY)
- return 0;
- packer_set_size(packer, b->num_parts);
- int a = packer->padding;
- for (int i = 0; i < b->num_parts; i++)
- packer->in[i] = (struct pos){b->parts[i].w + a, b->parts[i].h + a};
- return packer_pack(packer);
-}
-
-void packer_copy_subbitmaps(struct bitmap_packer *packer, struct sub_bitmaps *b,
- void *data, int pixel_stride, int stride)
-{
- assert(packer->count == b->num_parts);
- if (packer->padding) {
- struct pos bb[2];
- packer_get_bb(packer, bb);
- memset_pic(data, 0, bb[1].x * pixel_stride, bb[1].y, stride);
- }
- for (int n = 0; n < packer->count; n++) {
- struct sub_bitmap *s = &b->parts[n];
- struct pos p = packer->result[n];
-
- void *pdata = (uint8_t *)data + p.y * stride + p.x * pixel_stride;
- memcpy_pic(pdata, s->bitmap, s->w * pixel_stride, s->h,
- stride, s->stride);
- }
-}
diff --git a/libvo/bitmap_packer.h b/libvo/bitmap_packer.h
deleted file mode 100644
index b86c3ec4f9..0000000000
--- a/libvo/bitmap_packer.h
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef MPLAYER_PACK_RECTANGLES_H
-#define MPLAYER_PACK_RECTANGLES_H
-
-struct pos {
- int x;
- int y;
-};
-
-struct bitmap_packer {
- int w;
- int h;
- int w_max;
- int h_max;
- int padding;
- int count;
- struct pos *in;
- struct pos *result;
- int used_width;
- int used_height;
-
- // internal
- int *scratch;
- int asize;
-};
-
-struct ass_image;
-struct sub_bitmaps;
-
-// Clear all internal state. Leave the following fields: w_max, h_max
-void packer_reset(struct bitmap_packer *packer);
-
-// Get the bounding box used for bitmap data (including padding).
-// The bounding box doesn't exceed (0,0)-(packer->w,packer->h).
-void packer_get_bb(struct bitmap_packer *packer, struct pos out_bb[2]);
-
-/* Reallocate packer->in for at least to desired number of items.
- * Also sets packer->count to the same value.
- */
-void packer_set_size(struct bitmap_packer *packer, int size);
-
-/* To use this, set packer->count to number of rectangles, w_max and h_max
- * to maximum output rectangle size, and w and h to start size (may be 0).
- * Write input sizes in packer->in.
- * Resulting packing will be written in packer->result.
- * w and h will be increased if necessary for successful packing.
- * There is a strong guarantee that w and h will be powers of 2 (or set to 0).
- * Return value is -1 if packing failed because w and h were set to max
- * values but that wasn't enough, 1 if w or h was increased, and 0 otherwise.
- */
-int packer_pack(struct bitmap_packer *packer);
-
-/* Like above, but packer->count will be automatically set and
- * packer->in will be reallocated if needed and filled from the
- * given image list.
- */
-int packer_pack_from_subbitmaps(struct bitmap_packer *packer,
- struct sub_bitmaps *b);
-
-// Copy the (already packed) sub-bitmaps from b to the image in data.
-// data must point to an image that is at least (packer->w, packer->h) big.
-// The image has the given stride (bytes between (x, y) to (x, y + 1)), and the
-// pixel format used by both the sub-bitmaps and the image uses pixel_stride
-// bytes per pixel (bytes between (x, y) to (x + 1, y)).
-// If packer->padding is set, the padding borders are cleared with 0.
-void packer_copy_subbitmaps(struct bitmap_packer *packer, struct sub_bitmaps *b,
- void *data, int pixel_stride, int stride);
-
-#endif
diff --git a/libvo/cocoa_common.h b/libvo/cocoa_common.h
deleted file mode 100644
index 079e497441..0000000000
--- a/libvo/cocoa_common.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Cocoa OpenGL Backend
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef MPLAYER_COCOA_COMMON_H
-#define MPLAYER_COCOA_COMMON_H
-
-#include "video_out.h"
-
-struct vo_cocoa_state;
-
-bool vo_cocoa_gui_running(void);
-void *vo_cocoa_glgetaddr(const char *s);
-
-int vo_cocoa_init(struct vo *vo);
-void vo_cocoa_uninit(struct vo *vo);
-
-void vo_cocoa_update_xinerama_info(struct vo *vo);
-
-int vo_cocoa_change_attributes(struct vo *vo);
-int vo_cocoa_create_window(struct vo *vo, uint32_t d_width,
- uint32_t d_height, uint32_t flags,
- int gl3profile);
-
-void vo_cocoa_swap_buffers(struct vo *vo);
-int vo_cocoa_check_events(struct vo *vo);
-void vo_cocoa_fullscreen(struct vo *vo);
-void vo_cocoa_ontop(struct vo *vo);
-void vo_cocoa_pause(struct vo *vo);
-void vo_cocoa_resume(struct vo *vo);
-
-// returns an int to conform to the gl extensions from other platforms
-int vo_cocoa_swap_interval(int enabled);
-
-void *vo_cocoa_cgl_context(struct vo *vo);
-void *vo_cocoa_cgl_pixel_format(struct vo *vo);
-
-int vo_cocoa_cgl_color_size(struct vo *vo);
-
-#endif /* MPLAYER_COCOA_COMMON_H */
diff --git a/libvo/cocoa_common.m b/libvo/cocoa_common.m
deleted file mode 100644
index 337e0a32be..0000000000
--- a/libvo/cocoa_common.m
+++ /dev/null
@@ -1,865 +0,0 @@
-/*
- * Cocoa OpenGL Backend
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#import <Cocoa/Cocoa.h>
-#import <CoreServices/CoreServices.h> // for CGDisplayHideCursor
-#import <IOKit/pwr_mgt/IOPMLib.h>
-#include <dlfcn.h>
-
-#include "cocoa_common.h"
-
-#include "config.h"
-
-#include "options.h"
-#include "video_out.h"
-#include "aspect.h"
-
-#include "mp_fifo.h"
-#include "talloc.h"
-
-#include "input/input.h"
-#include "input/keycodes.h"
-#include "osx_common.h"
-#include "mp_msg.h"
-
-#ifndef NSOpenGLPFAOpenGLProfile
-#define NSOpenGLPFAOpenGLProfile 99
-#endif
-
-#ifndef NSOpenGLProfileVersionLegacy
-#define NSOpenGLProfileVersionLegacy 0x1000
-#endif
-
-#ifndef NSOpenGLProfileVersion3_2Core
-#define NSOpenGLProfileVersion3_2Core 0x3200
-#endif
-
-#define NSLeftAlternateKeyMask (0x000020 | NSAlternateKeyMask)
-#define NSRightAlternateKeyMask (0x000040 | NSAlternateKeyMask)
-
-// add methods not available on OSX versions prior to 10.7
-#ifndef MAC_OS_X_VERSION_10_7
-@interface NSView (IntroducedInLion)
-- (NSRect)convertRectToBacking:(NSRect)aRect;
-- (void)setWantsBestResolutionOpenGLSurface:(BOOL)aBool;
-@end
-#endif
-
-// add power management assertion not available on OSX versions prior to 10.7
-#ifndef kIOPMAssertionTypePreventUserIdleDisplaySleep
-#define kIOPMAssertionTypePreventUserIdleDisplaySleep \
- CFSTR("PreventUserIdleDisplaySleep")
-#endif
-
-@interface GLMPlayerWindow : NSWindow <NSWindowDelegate> {
- struct vo *_vo;
-}
-- (void)setVideoOutput:(struct vo *)vo;
-- (BOOL)canBecomeKeyWindow;
-- (BOOL)canBecomeMainWindow;
-- (void)fullscreen;
-- (void)mouseEvent:(NSEvent *)theEvent;
-- (void)mulSize:(float)multiplier;
-- (void)setContentSize:(NSSize)newSize keepCentered:(BOOL)keepCentered;
-@end
-
-@interface GLMPlayerOpenGLView : NSView
-@end
-
-struct vo_cocoa_state {
- NSAutoreleasePool *pool;
- GLMPlayerWindow *window;
- NSOpenGLContext *glContext;
- NSOpenGLPixelFormat *pixelFormat;
-
- NSSize current_video_size;
- NSSize previous_video_size;
-
- NSRect screen_frame;
- NSScreen *screen_handle;
- NSArray *screen_array;
-
- NSInteger windowed_mask;
- NSInteger fullscreen_mask;
-
- NSRect windowed_frame;
-
- NSString *window_title;
-
- NSInteger window_level;
- NSInteger fullscreen_window_level;
-
- int display_cursor;
- int cursor_timer;
- int cursor_autohide_delay;
-
- bool did_resize;
- bool out_fs_resize;
-
- IOPMAssertionID power_mgmt_assertion;
-};
-
-static int _instances = 0;
-
-static void create_menu(void);
-
-static struct vo_cocoa_state *vo_cocoa_init_state(struct vo *vo)
-{
- struct vo_cocoa_state *s = talloc_ptrtype(vo, s);
- *s = (struct vo_cocoa_state){
- .pool = [[NSAutoreleasePool alloc] init],
- .did_resize = NO,
- .current_video_size = {0,0},
- .previous_video_size = {0,0},
- .windowed_mask = NSTitledWindowMask|NSClosableWindowMask|
- NSMiniaturizableWindowMask|NSResizableWindowMask,
- .fullscreen_mask = NSBorderlessWindowMask,
- .windowed_frame = {{0,0},{0,0}},
- .out_fs_resize = NO,
- .display_cursor = 1,
- .cursor_autohide_delay = vo->opts->cursor_autohide_delay,
- .power_mgmt_assertion = kIOPMNullAssertionID,
- };
- return s;
-}
-
-static bool supports_hidpi(NSView *view)
-{
- SEL hdpi_selector = @selector(setWantsBestResolutionOpenGLSurface:);
- return is_osx_version_at_least(10, 7, 0) && view &&
- [view respondsToSelector:hdpi_selector];
-}
-
-bool vo_cocoa_gui_running(void)
-{
- return _instances > 0;
-}
-
-void *vo_cocoa_glgetaddr(const char *s)
-{
- void *ret = NULL;
- void *handle = dlopen(
- "/System/Library/Frameworks/OpenGL.framework/OpenGL",
- RTLD_LAZY | RTLD_LOCAL);
- if (!handle)
- return NULL;
- ret = dlsym(handle, s);
- dlclose(handle);
- return ret;
-}
-
-static void enable_power_management(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- if (!s->power_mgmt_assertion) return;
- IOPMAssertionRelease(s->power_mgmt_assertion);
- s->power_mgmt_assertion = kIOPMNullAssertionID;
-}
-
-static void disable_power_management(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- if (s->power_mgmt_assertion) return;
-
- CFStringRef assertion_type = kIOPMAssertionTypeNoDisplaySleep;
- if (is_osx_version_at_least(10, 7, 0))
- assertion_type = kIOPMAssertionTypePreventUserIdleDisplaySleep;
-
- IOPMAssertionCreateWithName(assertion_type, kIOPMAssertionLevelOn,
- CFSTR("org.mplayer2.power_mgmt"), &s->power_mgmt_assertion);
-}
-
-int vo_cocoa_init(struct vo *vo)
-{
- vo->cocoa = vo_cocoa_init_state(vo);
- _instances++;
-
- NSApplicationLoad();
- NSApp = [NSApplication sharedApplication];
- [NSApp setActivationPolicy: NSApplicationActivationPolicyRegular];
- disable_power_management(vo);
-
- return 1;
-}
-
-void vo_cocoa_uninit(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- CGDisplayShowCursor(kCGDirectMainDisplay);
- enable_power_management(vo);
- [NSApp setPresentationOptions:NSApplicationPresentationDefault];
-
- [s->window release];
- s->window = nil;
- [s->glContext release];
- s->glContext = nil;
- [s->pool release];
- s->pool = nil;
-
- _instances--;
-}
-
-void vo_cocoa_pause(struct vo *vo)
-{
- enable_power_management(vo);
-}
-
-void vo_cocoa_resume(struct vo *vo)
-{
- disable_power_management(vo);
-}
-
-static int current_screen_has_dock_or_menubar(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- NSRect f = s->screen_frame;
- NSRect vf = [s->screen_handle visibleFrame];
- return f.size.height > vf.size.height || f.size.width > vf.size.width;
-}
-
-static void update_screen_info(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- s->screen_array = [NSScreen screens];
- if (xinerama_screen >= (int)[s->screen_array count]) {
- mp_msg(MSGT_VO, MSGL_INFO, "[cocoa] Device ID %d does not exist, "
- "falling back to main device\n", xinerama_screen);
- xinerama_screen = -1;
- }
-
- if (xinerama_screen < 0) { // default behaviour
- if (! (s->screen_handle = [s->window screen]) )
- s->screen_handle = [s->screen_array objectAtIndex:0];
- } else {
- s->screen_handle = [s->screen_array objectAtIndex:(xinerama_screen)];
- }
-
- s->screen_frame = [s->screen_handle frame];
-}
-
-void vo_cocoa_update_xinerama_info(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- struct MPOpts *opts = vo->opts;
-
- update_screen_info(vo);
- aspect_save_screenres(vo, s->screen_frame.size.width,
- s->screen_frame.size.height);
- opts->vo_screenwidth = s->screen_frame.size.width;
- opts->vo_screenheight = s->screen_frame.size.height;
- xinerama_x = s->screen_frame.origin.x;
- xinerama_y = s->screen_frame.origin.y;
-}
-
-int vo_cocoa_change_attributes(struct vo *vo)
-{
- return 0;
-}
-
-static void resize_window(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- NSView *view = [s->window contentView];
- NSRect frame;
-
- if (supports_hidpi(view)) {
- frame = [view convertRectToBacking: [view frame]];
- } else {
- frame = [view frame];
- }
-
- vo->dwidth = frame.size.width;
- vo->dheight = frame.size.height;
- [s->glContext update];
-}
-
-static void vo_set_level(struct vo *vo, int ontop)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- if (ontop) {
- s->window_level = NSNormalWindowLevel + 1;
- } else {
- s->window_level = NSNormalWindowLevel;
- }
-
- if (!vo_fs)
- [s->window setLevel:s->window_level];
-}
-
-void vo_cocoa_ontop(struct vo *vo)
-{
- struct MPOpts *opts = vo->opts;
- opts->vo_ontop = !opts->vo_ontop;
- vo_set_level(vo, opts->vo_ontop);
-}
-
-static void update_state_sizes(struct vo_cocoa_state *s,
- uint32_t d_width, uint32_t d_height)
-{
- if (s->current_video_size.width > 0 || s->current_video_size.height > 0)
- s->previous_video_size = s->current_video_size;
- s->current_video_size = NSMakeSize(d_width, d_height);
-}
-
-static int create_window(struct vo *vo, uint32_t d_width, uint32_t d_height,
- uint32_t flags, int gl3profile)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- struct MPOpts *opts = vo->opts;
-
- const NSRect window_rect = NSMakeRect(0, 0, d_width, d_height);
- const NSRect glview_rect = NSMakeRect(0, 0, 100, 100);
-
- s->window =
- [[GLMPlayerWindow alloc] initWithContentRect:window_rect
- styleMask:s->windowed_mask
- backing:NSBackingStoreBuffered
- defer:NO];
-
- GLMPlayerOpenGLView *glView =
- [[GLMPlayerOpenGLView alloc] initWithFrame:glview_rect];
-
- // check for HiDPI support and enable it (available on 10.7 +)
- if (supports_hidpi(glView))
- [glView setWantsBestResolutionOpenGLSurface:YES];
-
- int i = 0;
- NSOpenGLPixelFormatAttribute attr[32];
- if (is_osx_version_at_least(10, 7, 0)) {
- attr[i++] = NSOpenGLPFAOpenGLProfile;
- if (gl3profile) {
- attr[i++] = NSOpenGLProfileVersion3_2Core;
- } else {
- attr[i++] = NSOpenGLProfileVersionLegacy;
- }
- } else if(gl3profile) {
- mp_msg(MSGT_VO, MSGL_ERR,
- "[cocoa] Invalid pixel format attribute "
- "(GL3 is not supported on OSX versions prior to 10.7)\n");
- return -1;
- }
- attr[i++] = NSOpenGLPFADoubleBuffer; // double buffered
- attr[i] = (NSOpenGLPixelFormatAttribute)0;
-
- s->pixelFormat =
- [[[NSOpenGLPixelFormat alloc] initWithAttributes:attr] autorelease];
- if (!s->pixelFormat) {
- mp_msg(MSGT_VO, MSGL_ERR,
- "[cocoa] Invalid pixel format attribute "
- "(GL3 not supported?)\n");
- return -1;
- }
- s->glContext =
- [[NSOpenGLContext alloc] initWithFormat:s->pixelFormat
- shareContext:nil];
-
- create_menu();
-
- [s->window setContentView:glView];
- [glView release];
- [s->window setAcceptsMouseMovedEvents:YES];
- [s->glContext setView:glView];
- [s->glContext makeCurrentContext];
- [s->window setVideoOutput:vo];
-
- [NSApp setDelegate:s->window];
- [s->window setDelegate:s->window];
- [s->window setContentSize:s->current_video_size];
- [s->window setContentAspectRatio:s->current_video_size];
- [s->window setFrameOrigin:NSMakePoint(vo->dx, vo->dy)];
-
- if (flags & VOFLAG_HIDDEN) {
- [s->window orderOut:nil];
- } else {
- [s->window makeKeyAndOrderFront:nil];
- [NSApp activateIgnoringOtherApps:YES];
- }
-
- if (flags & VOFLAG_FULLSCREEN)
- vo_cocoa_fullscreen(vo);
-
- vo_set_level(vo, opts->vo_ontop);
-
- return 0;
-}
-
-static void update_window(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
-
- if (s->current_video_size.width != s->previous_video_size.width ||
- s->current_video_size.height != s->previous_video_size.height) {
- if (vo_fs) {
- // we will resize as soon as we get out of fullscreen
- s->out_fs_resize = YES;
- } else {
- // only if we are not in fullscreen and the video size did
- // change we resize the window and set a new aspect ratio
- [s->window setContentSize:s->current_video_size
- keepCentered:YES];
- [s->window setContentAspectRatio:s->current_video_size];
- }
- }
-}
-
-int vo_cocoa_create_window(struct vo *vo, uint32_t d_width,
- uint32_t d_height, uint32_t flags,
- int gl3profile)
-{
- struct vo_cocoa_state *s = vo->cocoa;
-
- update_state_sizes(s, d_width, d_height);
-
- if (!(s->window || s->glContext)) {
- if (create_window(vo, d_width, d_height, flags, gl3profile) < 0)
- return -1;
- } else {
- update_window(vo);
- }
-
- resize_window(vo);
-
- if (s->window_title)
- [s->window_title release];
-
- s->window_title =
- [[NSString alloc] initWithUTF8String:vo_get_window_title(vo)];
- [s->window setTitle: s->window_title];
-
- return 0;
-}
-
-void vo_cocoa_swap_buffers(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- [s->glContext flushBuffer];
-}
-
-static void vo_cocoa_display_cursor(struct vo *vo, int requested_state)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- if (requested_state) {
- if (!vo_fs || s->cursor_autohide_delay > -2) {
- s->display_cursor = requested_state;
- CGDisplayShowCursor(kCGDirectMainDisplay);
- }
- } else {
- if (s->cursor_autohide_delay != -1) {
- s->display_cursor = requested_state;
- CGDisplayHideCursor(kCGDirectMainDisplay);
- }
- }
-}
-
-int vo_cocoa_check_events(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- NSEvent *event;
- int ms_time = (int) ([[NSProcessInfo processInfo] systemUptime] * 1000);
-
- // automatically hide mouse cursor
- if (vo_fs && s->display_cursor &&
- (ms_time - s->cursor_timer >= s->cursor_autohide_delay)) {
- vo_cocoa_display_cursor(vo, 0);
- s->cursor_timer = ms_time;
- }
-
- event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil
- inMode:NSEventTrackingRunLoopMode dequeue:YES];
- if (event == nil)
- return 0;
- [NSApp sendEvent:event];
-
- if (s->did_resize) {
- s->did_resize = NO;
- resize_window(vo);
- return VO_EVENT_RESIZE;
- }
- // Without SDL's bootstrap code (include SDL.h in mplayer.c),
- // on Leopard, we have trouble to get the play window automatically focused
- // when the app is actived. The Following code fix this problem.
- if ([event type] == NSAppKitDefined
- && [event subtype] == NSApplicationActivatedEventType) {
- [s->window makeMainWindow];
- [s->window makeKeyAndOrderFront:nil];
- }
- return 0;
-}
-
-void vo_cocoa_fullscreen(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- [s->window fullscreen];
- resize_window(vo);
-}
-
-int vo_cocoa_swap_interval(int enabled)
-{
- [[NSOpenGLContext currentContext] setValues:&enabled
- forParameter:NSOpenGLCPSwapInterval];
- return 0;
-}
-
-void *vo_cocoa_cgl_context(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- return [s->glContext CGLContextObj];
-}
-
-void *vo_cocoa_cgl_pixel_format(struct vo *vo)
-{
- return CGLGetPixelFormat(vo_cocoa_cgl_context(vo));
-}
-
-int vo_cocoa_cgl_color_size(struct vo *vo)
-{
- GLint value;
- CGLDescribePixelFormat(vo_cocoa_cgl_pixel_format(vo), 0,
- kCGLPFAColorSize, &value);
- switch (value) {
- case 32:
- case 24:
- return 8;
- case 16:
- return 5;
- }
-
- return 8;
-}
-
-static NSMenuItem *new_menu_item(NSMenu *parent_menu, NSString *title,
- SEL action, NSString *key_equivalent)
-{
- NSMenuItem *new_item =
- [[NSMenuItem alloc] initWithTitle:title action:action
- keyEquivalent:key_equivalent];
- [parent_menu addItem:new_item];
- return [new_item autorelease];
-}
-
-static NSMenuItem *new_main_menu_item(NSMenu *parent_menu, NSMenu *child_menu,
- NSString *title)
-{
- NSMenuItem *new_item =
- [[NSMenuItem alloc] initWithTitle:title action:nil
- keyEquivalent:@""];
- [new_item setSubmenu:child_menu];
- [parent_menu addItem:new_item];
- return [new_item autorelease];
-}
-
-void create_menu()
-{
- NSAutoreleasePool *pool = [NSAutoreleasePool new];
- NSMenu *main_menu, *m_menu, *w_menu;
- NSMenuItem *app_menu_item;
-
- main_menu = [[NSMenu new] autorelease];
- app_menu_item = [[NSMenuItem new] autorelease];
- [main_menu addItem:app_menu_item];
- [NSApp setMainMenu: main_menu];
-
- m_menu = [[[NSMenu alloc] initWithTitle:@"Movie"] autorelease];
- new_menu_item(m_menu, @"Half Size", @selector(halfSize), @"0");
- new_menu_item(m_menu, @"Normal Size", @selector(normalSize), @"1");
- new_menu_item(m_menu, @"Double Size", @selector(doubleSize), @"2");
-
- new_main_menu_item(main_menu, m_menu, @"Movie");
-
- w_menu = [[[NSMenu alloc] initWithTitle:@"Window"] autorelease];
- new_menu_item(w_menu, @"Minimize", @selector(performMiniaturize:), @"m");
- new_menu_item(w_menu, @"Zoom", @selector(performZoom:), @"z");
-
- new_main_menu_item(main_menu, w_menu, @"Window");
- [pool release];
-}
-
-@implementation GLMPlayerWindow
-- (void)setVideoOutput:(struct vo *)vo
-{
- _vo = vo;
-}
-
-- (void)windowDidResize:(NSNotification *) notification
-{
- if (_vo) {
- struct vo_cocoa_state *s = _vo->cocoa;
- s->did_resize = YES;
- }
-}
-
-- (void)fullscreen
-{
- struct vo_cocoa_state *s = _vo->cocoa;
- if (!vo_fs) {
- update_screen_info(_vo);
- if (current_screen_has_dock_or_menubar(_vo))
- [NSApp setPresentationOptions:NSApplicationPresentationHideDock|
- NSApplicationPresentationHideMenuBar];
- s->windowed_frame = [self frame];
- [self setHasShadow:NO];
- [self setStyleMask:s->fullscreen_mask];
- [self setFrame:s->screen_frame display:YES animate:NO];
- vo_fs = VO_TRUE;
- vo_cocoa_display_cursor(_vo, 0);
- [self setMovableByWindowBackground: NO];
- } else {
- [NSApp setPresentationOptions:NSApplicationPresentationDefault];
- [self setHasShadow:YES];
- [self setStyleMask:s->windowed_mask];
- [self setTitle:s->window_title];
- [self setFrame:s->windowed_frame display:YES animate:NO];
- if (s->out_fs_resize) {
- [self setContentSize:s->current_video_size keepCentered:YES];
- s->out_fs_resize = NO;
- }
- [self setContentAspectRatio:s->current_video_size];
- vo_fs = VO_FALSE;
- vo_cocoa_display_cursor(_vo, 1);
- [self setMovableByWindowBackground: YES];
- }
-}
-
-- (BOOL)canBecomeMainWindow { return YES; }
-- (BOOL)canBecomeKeyWindow { return YES; }
-- (BOOL)acceptsFirstResponder { return YES; }
-- (BOOL)becomeFirstResponder { return YES; }
-- (BOOL)resignFirstResponder { return YES; }
-- (BOOL)windowShouldClose:(id)sender
-{
- mplayer_put_key(_vo->key_fifo, KEY_CLOSE_WIN);
- // We have to wait for MPlayer to handle this,
- // otherwise we are in trouble if the
- // KEY_CLOSE_WIN handler is disabled
- return NO;
-}
-
-- (BOOL)isMovableByWindowBackground
-{
- // this is only valid as a starting value. it will be rewritten in the
- // -fullscreen method.
- return !vo_fs;
-}
-
-- (void)handleQuitEvent:(NSAppleEventDescriptor*)e
- withReplyEvent:(NSAppleEventDescriptor*)r
-{
- mplayer_put_key(_vo->key_fifo, KEY_CLOSE_WIN);
-}
-
-- (void)keyDown:(NSEvent *)theEvent
-{
- unsigned char charcode;
- if (([theEvent modifierFlags] & NSRightAlternateKeyMask) ==
- NSRightAlternateKeyMask)
- charcode = *[[theEvent characters] UTF8String];
- else
- charcode = [[theEvent charactersIgnoringModifiers] characterAtIndex:0];
-
- int key = convert_key([theEvent keyCode], charcode);
-
- if (key > -1) {
- if ([theEvent modifierFlags] & NSShiftKeyMask)
- key |= KEY_MODIFIER_SHIFT;
- if ([theEvent modifierFlags] & NSControlKeyMask)
- key |= KEY_MODIFIER_CTRL;
- if (([theEvent modifierFlags] & NSLeftAlternateKeyMask) ==
- NSLeftAlternateKeyMask)
- key |= KEY_MODIFIER_ALT;
- if ([theEvent modifierFlags] & NSCommandKeyMask)
- key |= KEY_MODIFIER_META;
- mplayer_put_key(_vo->key_fifo, key);
- }
-}
-
-- (void)mouseMoved: (NSEvent *) theEvent
-{
- if (vo_fs)
- vo_cocoa_display_cursor(_vo, 1);
-}
-
-- (void)mouseDragged:(NSEvent *)theEvent
-{
- [self mouseEvent: theEvent];
-}
-
-- (void)mouseDown:(NSEvent *)theEvent
-{
- [self mouseEvent: theEvent];
-}
-
-- (void)mouseUp:(NSEvent *)theEvent
-{
- [self mouseEvent: theEvent];
-}
-
-- (void)rightMouseDown:(NSEvent *)theEvent
-{
- [self mouseEvent: theEvent];
-}
-
-- (void)rightMouseUp:(NSEvent *)theEvent
-{
- [self mouseEvent: theEvent];
-}
-
-- (void)otherMouseDown:(NSEvent *)theEvent
-{
- [self mouseEvent: theEvent];
-}
-
-- (void)otherMouseUp:(NSEvent *)theEvent
-{
- [self mouseEvent: theEvent];
-}
-
-- (void)scrollWheel:(NSEvent *)theEvent
-{
- if ([theEvent deltaY] > 0)
- mplayer_put_key(_vo->key_fifo, MOUSE_BTN3);
- else
- mplayer_put_key(_vo->key_fifo, MOUSE_BTN4);
-}
-
-- (void)mouseEvent:(NSEvent *)theEvent
-{
- if ([theEvent buttonNumber] >= 0 && [theEvent buttonNumber] <= 9) {
- int buttonNumber = [theEvent buttonNumber];
- // Fix to mplayer defined button order: left, middle, right
- if (buttonNumber == 1) buttonNumber = 2;
- else if (buttonNumber == 2) buttonNumber = 1;
- switch ([theEvent type]) {
- case NSLeftMouseDown:
- case NSRightMouseDown:
- case NSOtherMouseDown:
- mplayer_put_key(_vo->key_fifo,
- (MOUSE_BTN0 + buttonNumber) | MP_KEY_DOWN);
- // Looks like Cocoa doesn't create MouseUp events when we are
- // doing the second click in a double click. Put in the key_fifo
- // the key that would be put from the MouseUp handling code.
- if([theEvent clickCount] == 2)
- mplayer_put_key(_vo->key_fifo, MOUSE_BTN0 + buttonNumber);
- break;
- case NSLeftMouseUp:
- case NSRightMouseUp:
- case NSOtherMouseUp:
- mplayer_put_key(_vo->key_fifo, MOUSE_BTN0 + buttonNumber);
- break;
- }
- }
-}
-
-- (void)applicationWillBecomeActive:(NSNotification *)aNotification
-{
- if (vo_fs && current_screen_has_dock_or_menubar(_vo)) {
- [NSApp setPresentationOptions:NSApplicationPresentationHideDock|
- NSApplicationPresentationHideMenuBar];
- }
-}
-
-- (void)applicationWillResignActive:(NSNotification *)aNotification
-{
- if (vo_fs) {
- [NSApp setPresentationOptions:NSApplicationPresentationDefault];
- }
-}
-
-- (void)applicationDidFinishLaunching:(NSNotification*)notification
-{
- // Install an event handler so the Quit menu entry works
- // The proper way using NSApp setDelegate: and
- // applicationShouldTerminate: does not work,
- // probably NSApplication never installs its handler.
- [[NSAppleEventManager sharedAppleEventManager]
- setEventHandler:self
- andSelector:@selector(handleQuitEvent:withReplyEvent:)
- forEventClass:kCoreEventClass
- andEventID:kAEQuitApplication];
-}
-
-- (void)normalSize
-{
- struct vo_cocoa_state *s = _vo->cocoa;
- if (!vo_fs)
- [self setContentSize:s->current_video_size keepCentered:YES];
-}
-
-- (void)halfSize { [self mulSize:0.5f];}
-
-- (void)doubleSize { [self mulSize:2.0f];}
-
-- (void)mulSize:(float)multiplier
-{
- if (!vo_fs) {
- struct vo_cocoa_state *s = _vo->cocoa;
- NSSize size = [[self contentView] frame].size;
- size.width = s->current_video_size.width * (multiplier);
- size.height = s->current_video_size.height * (multiplier);
- [self setContentSize:size keepCentered:YES];
- }
-}
-
-- (void)setCenteredContentSize:(NSSize)ns
-{
- NSRect nf = [self frame];
- NSRect vf = [[self screen] visibleFrame];
- NSRect cb = [[self contentView] bounds];
- int title_height = nf.size.height - cb.size.height;
- double ratio = (double)ns.width / (double)ns.height;
-
- // clip the new size to the visibleFrame's size if needed
- if (ns.width > vf.size.width || ns.height + title_height > vf.size.height) {
- ns = vf.size;
- ns.height -= title_height; // make space for the title bar
-
- if (ns.width > ns.height) {
- ns.height = ((double)ns.width * 1/ratio + 0.5);
- } else {
- ns.width = ((double)ns.height * ratio + 0.5);
- }
- }
-
- int dw = nf.size.width - ns.width;
- int dh = nf.size.height - ns.height - title_height;
-
- nf.origin.x += dw / 2;
- nf.origin.y += dh / 2;
-
- NSRect new_frame =
- NSMakeRect(nf.origin.x, nf.origin.y, ns.width, ns.height + title_height);
- [self setFrame:new_frame display:YES animate:NO];
-}
-
-- (void)setContentSize:(NSSize)ns keepCentered:(BOOL)keepCentered
-{
- if (keepCentered) {
- [self setCenteredContentSize:ns];
- } else {
- [self setContentSize:ns];
- }
-}
-@end
-
-@implementation GLMPlayerOpenGLView
-- (void)drawRect: (NSRect)rect
-{
- [[NSColor clearColor] set];
- NSRectFill([self bounds]);
-}
-@end
diff --git a/libvo/csputils.c b/libvo/csputils.c
deleted file mode 100644
index 23eb099f69..0000000000
--- a/libvo/csputils.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * Common code related to colorspaces and conversion
- *
- * Copyleft (C) 2009 Reimar Döffinger <Reimar.Doeffinger@gmx.de>
- *
- * mp_invert_yuv2rgb based on DarkPlaces engine, original code (GPL2 or later)
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * You can alternatively redistribute this file and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- */
-
-#include <stdint.h>
-#include <math.h>
-#include <assert.h>
-#include <libavutil/common.h>
-
-#include "csputils.h"
-
-char * const mp_csp_names[MP_CSP_COUNT] = {
- "Autoselect",
- "BT.601 (SD)",
- "BT.709 (HD)",
- "SMPTE-240M",
- "RGB",
-};
-
-char * const mp_csp_equalizer_names[MP_CSP_EQ_COUNT] = {
- "brightness",
- "contrast",
- "hue",
- "saturation",
- "gamma",
-};
-
-enum mp_csp avcol_spc_to_mp_csp(enum AVColorSpace colorspace)
-{
- switch (colorspace) {
- case AVCOL_SPC_BT709: return MP_CSP_BT_709;
- case AVCOL_SPC_BT470BG: return MP_CSP_BT_601;
- case AVCOL_SPC_SMPTE170M: return MP_CSP_BT_601;
- case AVCOL_SPC_SMPTE240M: return MP_CSP_SMPTE_240M;
- case AVCOL_SPC_RGB: return MP_CSP_RGB;
- default: return MP_CSP_AUTO;
- }
-}
-
-enum mp_csp_levels avcol_range_to_mp_csp_levels(enum AVColorRange range)
-{
- switch (range) {
- case AVCOL_RANGE_MPEG: return MP_CSP_LEVELS_TV;
- case AVCOL_RANGE_JPEG: return MP_CSP_LEVELS_PC;
- default: return MP_CSP_LEVELS_AUTO;
- }
-}
-
-enum AVColorSpace mp_csp_to_avcol_spc(enum mp_csp colorspace)
-{
- switch (colorspace) {
- case MP_CSP_BT_709: return AVCOL_SPC_BT709;
- case MP_CSP_BT_601: return AVCOL_SPC_BT470BG;
- case MP_CSP_SMPTE_240M: return AVCOL_SPC_SMPTE240M;
- case MP_CSP_RGB: return AVCOL_SPC_RGB;
- default: return AVCOL_SPC_UNSPECIFIED;
- }
-}
-
-enum AVColorRange mp_csp_levels_to_avcol_range(enum mp_csp_levels range)
-{
- switch (range) {
- case MP_CSP_LEVELS_TV: return AVCOL_RANGE_MPEG;
- case MP_CSP_LEVELS_PC: return AVCOL_RANGE_JPEG;
- default: return AVCOL_RANGE_UNSPECIFIED;
- }
-}
-
-enum mp_csp mp_csp_guess_colorspace(int width, int height)
-{
- return width >= 1280 || height > 576 ? MP_CSP_BT_709 : MP_CSP_BT_601;
-}
-
-/**
- * \brief little helper function to create a lookup table for gamma
- * \param map buffer to create map into
- * \param size size of buffer
- * \param gamma gamma value
- */
-void mp_gen_gamma_map(uint8_t *map, int size, float gamma)
-{
- if (gamma == 1.0) {
- for (int i = 0; i < size; i++)
- map[i] = 255 * i / (size - 1);
- return;
- }
- gamma = 1.0 / gamma;
- for (int i = 0; i < size; i++) {
- float tmp = (float)i / (size - 1.0);
- tmp = pow(tmp, gamma);
- if (tmp > 1.0)
- tmp = 1.0;
- if (tmp < 0.0)
- tmp = 0.0;
- map[i] = 255 * tmp;
- }
-}
-
-/* Fill in the Y, U, V vectors of a yuv2rgb conversion matrix
- * based on the given luma weights of the R, G and B components (lr, lg, lb).
- * lr+lg+lb is assumed to equal 1.
- * This function is meant for colorspaces satisfying the following
- * conditions (which are true for common YUV colorspaces):
- * - The mapping from input [Y, U, V] to output [R, G, B] is linear.
- * - Y is the vector [1, 1, 1]. (meaning input Y component maps to 1R+1G+1B)
- * - U maps to a value with zero R and positive B ([0, x, y], y > 0;
- * i.e. blue and green only).
- * - V maps to a value with zero B and positive R ([x, y, 0], x > 0;
- * i.e. red and green only).
- * - U and V are orthogonal to the luma vector [lr, lg, lb].
- * - The magnitudes of the vectors U and V are the minimal ones for which
- * the image of the set Y=[0...1],U=[-0.5...0.5],V=[-0.5...0.5] under the
- * conversion function will cover the set R=[0...1],G=[0...1],B=[0...1]
- * (the resulting matrix can be converted for other input/output ranges
- * outside this function).
- * Under these conditions the given parameters lr, lg, lb uniquely
- * determine the mapping of Y, U, V to R, G, B.
- */
-static void luma_coeffs(float m[3][4], float lr, float lg, float lb)
-{
- assert(fabs(lr+lg+lb - 1) < 1e-6);
- m[0][0] = m[1][0] = m[2][0] = 1;
- m[0][1] = 0;
- m[1][1] = -2 * (1-lb) * lb/lg;
- m[2][1] = 2 * (1-lb);
- m[0][2] = 2 * (1-lr);
- m[1][2] = -2 * (1-lr) * lr/lg;
- m[2][2] = 0;
- // Constant coefficients (m[x][3]) not set here
-}
-
-/**
- * \brief get the coefficients of the yuv -> rgb conversion matrix
- * \param params struct specifying the properties of the conversion like
- * brightness, ...
- * \param m array to store coefficients into
- */
-void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4])
-{
- int format = params->colorspace.format;
- if (format <= MP_CSP_AUTO || format >= MP_CSP_COUNT)
- format = MP_CSP_BT_601;
- switch (format) {
- case MP_CSP_BT_601: luma_coeffs(m, 0.299, 0.587, 0.114 ); break;
- case MP_CSP_BT_709: luma_coeffs(m, 0.2126, 0.7152, 0.0722); break;
- case MP_CSP_SMPTE_240M: luma_coeffs(m, 0.2122, 0.7013, 0.0865); break;
- default:
- abort();
- };
-
- // Hue is equivalent to rotating input [U, V] subvector around the origin.
- // Saturation scales [U, V].
- float huecos = params->saturation * cos(params->hue);
- float huesin = params->saturation * sin(params->hue);
- for (int i = 0; i < 3; i++) {
- float u = m[i][COL_U];
- m[i][COL_U] = huecos * u - huesin * m[i][COL_V];
- m[i][COL_V] = huesin * u + huecos * m[i][COL_V];
- }
-
- int levels_in = params->colorspace.levels_in;
- if (levels_in <= MP_CSP_LEVELS_AUTO || levels_in >= MP_CSP_LEVELS_COUNT)
- levels_in = MP_CSP_LEVELS_TV;
- assert(params->input_bits >= 8);
- assert(params->texture_bits >= params->input_bits);
- double s = (1 << params->input_bits-8) / ((1<<params->texture_bits)-1.);
- // The values below are written in 0-255 scale
- struct yuvlevels { double ymin, ymax, cmin, cmid; }
- yuvlim = { 16*s, 235*s, 16*s, 128*s },
- yuvfull = { 0*s, 255*s, 1*s, 128*s }, // '1' for symmetry around 128
- yuvlev;
- switch (levels_in) {
- case MP_CSP_LEVELS_TV: yuvlev = yuvlim; break;
- case MP_CSP_LEVELS_PC: yuvlev = yuvfull; break;
- default:
- abort();
- }
-
- int levels_out = params->colorspace.levels_out;
- if (levels_out <= MP_CSP_LEVELS_AUTO || levels_out >= MP_CSP_LEVELS_COUNT)
- levels_out = MP_CSP_LEVELS_PC;
- struct rgblevels { double min, max; }
- rgblim = { 16/255., 235/255. },
- rgbfull = { 0, 1 },
- rgblev;
- switch (levels_out) {
- case MP_CSP_LEVELS_TV: rgblev = rgblim; break;
- case MP_CSP_LEVELS_PC: rgblev = rgbfull; break;
- default:
- abort();
- }
-
- double ymul = (rgblev.max - rgblev.min) / (yuvlev.ymax - yuvlev.ymin);
- double cmul = (rgblev.max - rgblev.min) / (yuvlev.cmid - yuvlev.cmin) / 2;
- for (int i = 0; i < 3; i++) {
- m[i][COL_Y] *= ymul;
- m[i][COL_U] *= cmul;
- m[i][COL_V] *= cmul;
- // Set COL_C so that Y=umin,UV=cmid maps to RGB=min (black to black)
- m[i][COL_C] = rgblev.min - m[i][COL_Y] * yuvlev.ymin
- -(m[i][COL_U] + m[i][COL_V]) * yuvlev.cmid;
- }
-
- // Brightness adds a constant to output R,G,B.
- // Contrast scales Y around 1/2 (not 0 in this implementation).
- for (int i = 0; i < 3; i++) {
- m[i][COL_C] += params->brightness;
- m[i][COL_Y] *= params->contrast;
- m[i][COL_C] += (rgblev.max-rgblev.min) * (1 - params->contrast)/2;
- }
-
- int in_bits = FFMAX(params->int_bits_in, 1);
- int out_bits = FFMAX(params->int_bits_out, 1);
- double in_scale = (1 << in_bits) - 1.0;
- double out_scale = (1 << out_bits) - 1.0;
- for (int i = 0; i < 3; i++) {
- m[i][COL_C] *= out_scale; // constant is 1.0
- for (int x = 0; x < 3; x++)
- m[i][x] *= out_scale / in_scale;
- }
-}
-
-//! size of gamma map use to avoid slow exp function in gen_yuv2rgb_map
-#define GMAP_SIZE (1024)
-/**
- * \brief generate a 3D YUV -> RGB map
- * \param params struct containing parameters like brightness, gamma, ...
- * \param map where to store map. Must provide space for (size + 2)^3 elements
- * \param size size of the map, excluding border
- */
-void mp_gen_yuv2rgb_map(struct mp_csp_params *params, unsigned char *map, int size)
-{
- int i, j, k, l;
- float step = 1.0 / size;
- float y, u, v;
- float yuv2rgb[3][4];
- unsigned char gmaps[3][GMAP_SIZE];
- mp_gen_gamma_map(gmaps[0], GMAP_SIZE, params->rgamma);
- mp_gen_gamma_map(gmaps[1], GMAP_SIZE, params->ggamma);
- mp_gen_gamma_map(gmaps[2], GMAP_SIZE, params->bgamma);
- mp_get_yuv2rgb_coeffs(params, yuv2rgb);
- for (i = 0; i < 3; i++)
- for (j = 0; j < 4; j++)
- yuv2rgb[i][j] *= GMAP_SIZE - 1;
- v = 0;
- for (i = -1; i <= size; i++) {
- u = 0;
- for (j = -1; j <= size; j++) {
- y = 0;
- for (k = -1; k <= size; k++) {
- for (l = 0; l < 3; l++) {
- float rgb = yuv2rgb[l][COL_Y] * y + yuv2rgb[l][COL_U] * u +
- yuv2rgb[l][COL_V] * v + yuv2rgb[l][COL_C];
- *map++ = gmaps[l][av_clip(rgb, 0, GMAP_SIZE - 1)];
- }
- y += (k == -1 || k == size - 1) ? step / 2 : step;
- }
- u += (j == -1 || j == size - 1) ? step / 2 : step;
- }
- v += (i == -1 || i == size - 1) ? step / 2 : step;
- }
-}
-
-// Copy settings from eq into params.
-void mp_csp_copy_equalizer_values(struct mp_csp_params *params,
- const struct mp_csp_equalizer *eq)
-{
- params->brightness = eq->values[MP_CSP_EQ_BRIGHTNESS] / 100.0;
- params->contrast = (eq->values[MP_CSP_EQ_CONTRAST] + 100) / 100.0;
- params->hue = eq->values[MP_CSP_EQ_HUE] / 100.0 * 3.1415927;
- params->saturation = (eq->values[MP_CSP_EQ_SATURATION] + 100) / 100.0;
- float gamma = exp(log(8.0) * eq->values[MP_CSP_EQ_GAMMA] / 100.0);
- params->rgamma = gamma;
- params->ggamma = gamma;
- params->bgamma = gamma;
-}
-
-static int find_eq(int capabilities, const char *name)
-{
- for (int i = 0; i < MP_CSP_EQ_COUNT; i++) {
- if (strcmp(name, mp_csp_equalizer_names[i]) == 0)
- return ((1 << i) & capabilities) ? i : -1;
- }
- return -1;
-}
-
-int mp_csp_equalizer_get(struct mp_csp_equalizer *eq, const char *property,
- int *out_value)
-{
- int index = find_eq(eq->capabilities, property);
- if (index < 0)
- return -1;
-
- *out_value = eq->values[index];
-
- return 0;
-}
-
-int mp_csp_equalizer_set(struct mp_csp_equalizer *eq, const char *property,
- int value)
-{
- int index = find_eq(eq->capabilities, property);
- if (index < 0)
- return 0;
-
- eq->values[index] = value;
-
- return 1;
-}
-
-void mp_invert_yuv2rgb(float out[3][4], float in[3][4])
-{
- float m00 = in[0][0], m01 = in[0][1], m02 = in[0][2], m03 = in[0][3],
- m10 = in[1][0], m11 = in[1][1], m12 = in[1][2], m13 = in[1][3],
- m20 = in[2][0], m21 = in[2][1], m22 = in[2][2], m23 = in[2][3];
-
- // calculate the adjoint
- out[0][0] = (m11 * m22 - m21 * m12);
- out[0][1] = -(m01 * m22 - m21 * m02);
- out[0][2] = (m01 * m12 - m11 * m02);
- out[1][0] = -(m10 * m22 - m20 * m12);
- out[1][1] = (m00 * m22 - m20 * m02);
- out[1][2] = -(m00 * m12 - m10 * m02);
- out[2][0] = (m10 * m21 - m20 * m11);
- out[2][1] = -(m00 * m21 - m20 * m01);
- out[2][2] = (m00 * m11 - m10 * m01);
-
- // calculate the determinant (as inverse == 1/det * adjoint,
- // adjoint * m == identity * det, so this calculates the det)
- float det = m00 * out[0][0] + m10 * out[0][1] + m20 * out[0][2];
- det = 1.0f / det;
-
- out[0][0] *= det;
- out[0][1] *= det;
- out[0][2] *= det;
- out[1][0] *= det;
- out[1][1] *= det;
- out[1][2] *= det;
- out[2][0] *= det;
- out[2][1] *= det;
- out[2][2] *= det;
-
- // fix the constant coefficient
- // rgb = M * yuv + C
- // M^-1 * rgb = yuv + M^-1 * C
- // yuv = M^-1 * rgb - M^-1 * C
- // ^^^^^^^^^^
- out[0][3] = -(out[0][0] * m03 + out[0][1] * m13 + out[0][2] * m23);
- out[1][3] = -(out[1][0] * m03 + out[1][1] * m13 + out[1][2] * m23);
- out[2][3] = -(out[2][0] * m03 + out[2][1] * m13 + out[2][2] * m23);
-}
-
-// Multiply the color in c with the given matrix.
-// c is {R, G, B} or {Y, U, V} (depending on input/output and matrix).
-// Output is clipped to the given number of bits.
-void mp_map_int_color(float matrix[3][4], int clip_bits, int c[3])
-{
- int in[3] = {c[0], c[1], c[2]};
- for (int i = 0; i < 3; i++) {
- double val = matrix[i][3];
- for (int x = 0; x < 3; x++)
- val += matrix[i][x] * in[x];
- int ival = lrint(val);
- c[i] = av_clip(ival, 0, (1 << clip_bits) - 1);
- }
-}
diff --git a/libvo/csputils.h b/libvo/csputils.h
deleted file mode 100644
index d66bb86fa3..0000000000
--- a/libvo/csputils.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * You can alternatively redistribute this file and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- */
-
-#ifndef MPLAYER_CSPUTILS_H
-#define MPLAYER_CSPUTILS_H
-
-#include <stdbool.h>
-#include <stdint.h>
-
-#include "libavcodec/avcodec.h"
-
-/* NOTE: the csp and levels AUTO values are converted to specific ones
- * above vf/vo level. At least vf_scale relies on all valid settings being
- * nonzero at vf/vo level.
- */
-
-enum mp_csp {
- MP_CSP_AUTO,
- MP_CSP_BT_601,
- MP_CSP_BT_709,
- MP_CSP_SMPTE_240M,
- MP_CSP_RGB,
- MP_CSP_COUNT
-};
-
-// Any enum mp_csp value is a valid index (except MP_CSP_COUNT)
-extern char * const mp_csp_names[MP_CSP_COUNT];
-
-enum mp_csp_levels {
- MP_CSP_LEVELS_AUTO,
- MP_CSP_LEVELS_TV,
- MP_CSP_LEVELS_PC,
- MP_CSP_LEVELS_COUNT,
-};
-
-struct mp_csp_details {
- enum mp_csp format;
- enum mp_csp_levels levels_in; // encoded video
- enum mp_csp_levels levels_out; // output device
-};
-
-// initializer for struct mp_csp_details that contains reasonable defaults
-#define MP_CSP_DETAILS_DEFAULTS {MP_CSP_BT_601, MP_CSP_LEVELS_TV, MP_CSP_LEVELS_PC}
-
-struct mp_csp_params {
- struct mp_csp_details colorspace;
- float brightness;
- float contrast;
- float hue;
- float saturation;
- float rgamma;
- float ggamma;
- float bgamma;
- // texture_bits/input_bits is for rescaling fixed point input to range [0,1]
- int texture_bits;
- int input_bits;
- // for scaling integer input and output (if 0, assume range [0,1])
- int int_bits_in;
- int int_bits_out;
-};
-
-#define MP_CSP_PARAMS_DEFAULTS { \
- .colorspace = MP_CSP_DETAILS_DEFAULTS, \
- .brightness = 0, .contrast = 1, .hue = 0, .saturation = 1, \
- .rgamma = 1, .ggamma = 1, .bgamma = 1, \
- .texture_bits = 8, .input_bits = 8}
-
-enum mp_csp_equalizer_param {
- MP_CSP_EQ_BRIGHTNESS,
- MP_CSP_EQ_CONTRAST,
- MP_CSP_EQ_HUE,
- MP_CSP_EQ_SATURATION,
- MP_CSP_EQ_GAMMA,
- MP_CSP_EQ_COUNT,
-};
-
-#define MP_CSP_EQ_CAPS_COLORMATRIX \
- ( (1 << MP_CSP_EQ_BRIGHTNESS) \
- | (1 << MP_CSP_EQ_CONTRAST) \
- | (1 << MP_CSP_EQ_HUE) \
- | (1 << MP_CSP_EQ_SATURATION) )
-
-#define MP_CSP_EQ_CAPS_GAMMA (1 << MP_CSP_EQ_GAMMA)
-
-extern char * const mp_csp_equalizer_names[MP_CSP_EQ_COUNT];
-
-// Default initialization with 0 is enough, except for the capabilities field
-struct mp_csp_equalizer {
- // Bit field of capabilities. For example (1 << MP_CSP_EQ_HUE) means hue
- // support is available.
- int capabilities;
- // Value for each property is in the range [-100, 100].
- // 0 is default, meaning neutral or no change.
- int values[MP_CSP_EQ_COUNT];
-};
-
-
-void mp_csp_copy_equalizer_values(struct mp_csp_params *params,
- const struct mp_csp_equalizer *eq);
-
-int mp_csp_equalizer_set(struct mp_csp_equalizer *eq, const char *property,
- int value);
-
-int mp_csp_equalizer_get(struct mp_csp_equalizer *eq, const char *property,
- int *out_value);
-
-enum mp_csp avcol_spc_to_mp_csp(enum AVColorSpace colorspace);
-
-enum mp_csp_levels avcol_range_to_mp_csp_levels(enum AVColorRange range);
-
-enum AVColorSpace mp_csp_to_avcol_spc(enum mp_csp colorspace);
-
-enum AVColorRange mp_csp_levels_to_avcol_range(enum mp_csp_levels range);
-
-enum mp_csp mp_csp_guess_colorspace(int width, int height);
-
-void mp_gen_gamma_map(unsigned char *map, int size, float gamma);
-#define ROW_R 0
-#define ROW_G 1
-#define ROW_B 2
-#define COL_Y 0
-#define COL_U 1
-#define COL_V 2
-#define COL_C 3
-void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float yuv2rgb[3][4]);
-void mp_gen_yuv2rgb_map(struct mp_csp_params *params, uint8_t *map, int size);
-
-void mp_invert_yuv2rgb(float out[3][4], float in[3][4]);
-void mp_map_int_color(float matrix[3][4], int clip_bits, int c[3]);
-
-#endif /* MPLAYER_CSPUTILS_H */
diff --git a/libvo/d3d_shader_yuv.h b/libvo/d3d_shader_yuv.h
deleted file mode 100644
index 49ef753b4c..0000000000
--- a/libvo/d3d_shader_yuv.h
+++ /dev/null
@@ -1,142 +0,0 @@
-#if 0
-//
-// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
-//
-// fxc /Tps_2_0 /Fhz:\tmp\mplayer\libvo\d3d_shader_yuv.h
-// z:\tmp\mplayer\libvo\d3d_shader_yuv.hlsl /Vnd3d_shader_yuv
-//
-//
-// Parameters:
-//
-// float4x4 colormatrix;
-// sampler2D tex0;
-// sampler2D tex1;
-// sampler2D tex2;
-//
-//
-// Registers:
-//
-// Name Reg Size
-// ------------ ----- ----
-// colormatrix c0 4
-// tex0 s0 1
-// tex1 s1 1
-// tex2 s2 1
-//
-
- ps_2_0
- def c4, 1, 0, 0, 0
- dcl t0.xy
- dcl t1.xy
- dcl t2.xy
- dcl_2d s0
- dcl_2d s1
- dcl_2d s2
- texld r0, t0, s0
- texld r1, t1, s1
- texld r2, t2, s2
- mov r0.y, r1.x
- mov r0.z, r2.x
- mov r0.w, c4.x
- dp4 r1.x, r0, c0
- dp4 r1.y, r0, c1
- dp4 r1.z, r0, c2
- dp4 r1.w, r0, c3
- mov oC0, r1
-
-// approximately 11 instruction slots used (3 texture, 8 arithmetic)
-#endif
-
-const BYTE d3d_shader_yuv[] =
-{
- 0, 2, 255, 255, 254, 255,
- 67, 0, 67, 84, 65, 66,
- 28, 0, 0, 0, 215, 0,
- 0, 0, 0, 2, 255, 255,
- 4, 0, 0, 0, 28, 0,
- 0, 0, 0, 1, 0, 0,
- 208, 0, 0, 0, 108, 0,
- 0, 0, 2, 0, 0, 0,
- 4, 0, 2, 0, 120, 0,
- 0, 0, 0, 0, 0, 0,
- 136, 0, 0, 0, 3, 0,
- 0, 0, 1, 0, 2, 0,
- 144, 0, 0, 0, 0, 0,
- 0, 0, 160, 0, 0, 0,
- 3, 0, 1, 0, 1, 0,
- 6, 0, 168, 0, 0, 0,
- 0, 0, 0, 0, 184, 0,
- 0, 0, 3, 0, 2, 0,
- 1, 0, 10, 0, 192, 0,
- 0, 0, 0, 0, 0, 0,
- 99, 111, 108, 111, 114, 109,
- 97, 116, 114, 105, 120, 0,
- 3, 0, 3, 0, 4, 0,
- 4, 0, 1, 0, 0, 0,
- 0, 0, 0, 0, 116, 101,
- 120, 48, 0, 171, 171, 171,
- 4, 0, 12, 0, 1, 0,
- 1, 0, 1, 0, 0, 0,
- 0, 0, 0, 0, 116, 101,
- 120, 49, 0, 171, 171, 171,
- 4, 0, 12, 0, 1, 0,
- 1, 0, 1, 0, 0, 0,
- 0, 0, 0, 0, 116, 101,
- 120, 50, 0, 171, 171, 171,
- 4, 0, 12, 0, 1, 0,
- 1, 0, 1, 0, 0, 0,
- 0, 0, 0, 0, 112, 115,
- 95, 50, 95, 48, 0, 77,
- 105, 99, 114, 111, 115, 111,
- 102, 116, 32, 40, 82, 41,
- 32, 72, 76, 83, 76, 32,
- 83, 104, 97, 100, 101, 114,
- 32, 67, 111, 109, 112, 105,
- 108, 101, 114, 32, 57, 46,
- 50, 55, 46, 57, 53, 50,
- 46, 51, 48, 50, 50, 0,
- 81, 0, 0, 5, 4, 0,
- 15, 160, 0, 0, 128, 63,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 31, 0, 0, 2, 0, 0,
- 0, 128, 0, 0, 3, 176,
- 31, 0, 0, 2, 0, 0,
- 0, 128, 1, 0, 3, 176,
- 31, 0, 0, 2, 0, 0,
- 0, 128, 2, 0, 3, 176,
- 31, 0, 0, 2, 0, 0,
- 0, 144, 0, 8, 15, 160,
- 31, 0, 0, 2, 0, 0,
- 0, 144, 1, 8, 15, 160,
- 31, 0, 0, 2, 0, 0,
- 0, 144, 2, 8, 15, 160,
- 66, 0, 0, 3, 0, 0,
- 15, 128, 0, 0, 228, 176,
- 0, 8, 228, 160, 66, 0,
- 0, 3, 1, 0, 15, 128,
- 1, 0, 228, 176, 1, 8,
- 228, 160, 66, 0, 0, 3,
- 2, 0, 15, 128, 2, 0,
- 228, 176, 2, 8, 228, 160,
- 1, 0, 0, 2, 0, 0,
- 2, 128, 1, 0, 0, 128,
- 1, 0, 0, 2, 0, 0,
- 4, 128, 2, 0, 0, 128,
- 1, 0, 0, 2, 0, 0,
- 8, 128, 4, 0, 0, 160,
- 9, 0, 0, 3, 1, 0,
- 1, 128, 0, 0, 228, 128,
- 0, 0, 228, 160, 9, 0,
- 0, 3, 1, 0, 2, 128,
- 0, 0, 228, 128, 1, 0,
- 228, 160, 9, 0, 0, 3,
- 1, 0, 4, 128, 0, 0,
- 228, 128, 2, 0, 228, 160,
- 9, 0, 0, 3, 1, 0,
- 8, 128, 0, 0, 228, 128,
- 3, 0, 228, 160, 1, 0,
- 0, 2, 0, 8, 15, 128,
- 1, 0, 228, 128, 255, 255,
- 0, 0
-};
diff --git a/libvo/d3d_shader_yuv.hlsl b/libvo/d3d_shader_yuv.hlsl
deleted file mode 100644
index b17e257210..0000000000
--- a/libvo/d3d_shader_yuv.hlsl
+++ /dev/null
@@ -1,44 +0,0 @@
-// Compile with:
-// fxc.exe /Tps_2_0 /Fhd3d_shader_yuv.h d3d_shader_yuv.hlsl /Vnd3d_shader_yuv
-// fxc.exe /Tps_2_0 /Fhd3d_shader_yuv_2ch.h d3d_shader_yuv.hlsl /Vnd3d_shader_yuv_2ch /DUSE_2CH=1
-
-// Be careful with this shader. You can't use constant slots, since we don't
-// load the shader with D3DX. All uniform variables are mapped to hardcoded
-// constant slots.
-
-sampler2D tex0 : register(s0);
-sampler2D tex1 : register(s1);
-sampler2D tex2 : register(s2);
-
-uniform float4x4 colormatrix : register(c0);
-uniform float2 depth : register(c5);
-
-#ifdef USE_2CH
-
-float1 sample(sampler2D tex, float2 t)
-{
- // Sample from A8L8 format as if we sampled a single value from L16.
- // We compute the 2 channel values back into one.
- return dot(tex2D(tex, t).xw, depth);
-}
-
-#else
-
-float1 sample(sampler2D tex, float2 t)
-{
- return tex2D(tex, t).x;
-}
-
-#endif
-
-float4 main(float2 t0 : TEXCOORD0,
- float2 t1 : TEXCOORD1,
- float2 t2 : TEXCOORD2)
- : COLOR
-{
- float4 c = float4(sample(tex0, t0),
- sample(tex1, t1),
- sample(tex2, t2),
- 1);
- return mul(c, colormatrix);
-}
diff --git a/libvo/d3d_shader_yuv_2ch.h b/libvo/d3d_shader_yuv_2ch.h
deleted file mode 100644
index 45dcc73992..0000000000
--- a/libvo/d3d_shader_yuv_2ch.h
+++ /dev/null
@@ -1,170 +0,0 @@
-#if 0
-//
-// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
-//
-// fxc /Tps_2_0 /Fhz:\tmp\mplayer\libvo\d3d_shader_yuv_2ch.h
-// z:\tmp\mplayer\libvo\d3d_shader_yuv.hlsl /Vnd3d_shader_yuv_2ch
-// /DUSE_2CH=1
-//
-//
-// Parameters:
-//
-// float4x4 colormatrix;
-// float2 depth;
-// sampler2D tex0;
-// sampler2D tex1;
-// sampler2D tex2;
-//
-//
-// Registers:
-//
-// Name Reg Size
-// ------------ ----- ----
-// colormatrix c0 4
-// depth c5 1
-// tex0 s0 1
-// tex1 s1 1
-// tex2 s2 1
-//
-
- ps_2_0
- def c4, 1, 0, 0, 0
- dcl t0.xy
- dcl t1.xy
- dcl t2.xy
- dcl_2d s0
- dcl_2d s1
- dcl_2d s2
- texld r0, t0, s0
- texld r1, t1, s1
- texld r2, t2, s2
- mul r0.x, r0.x, c5.x
- mad r0.x, r0.w, c5.y, r0.x
- mul r1.x, r1.x, c5.x
- mad r0.y, r1.w, c5.y, r1.x
- mul r1.x, r2.x, c5.x
- mad r0.z, r2.w, c5.y, r1.x
- mov r0.w, c4.x
- dp4 r1.x, r0, c0
- dp4 r1.y, r0, c1
- dp4 r1.z, r0, c2
- dp4 r1.w, r0, c3
- mov oC0, r1
-
-// approximately 15 instruction slots used (3 texture, 12 arithmetic)
-#endif
-
-const BYTE d3d_shader_yuv_2ch[] =
-{
- 0, 2, 255, 255, 254, 255,
- 78, 0, 67, 84, 65, 66,
- 28, 0, 0, 0, 3, 1,
- 0, 0, 0, 2, 255, 255,
- 5, 0, 0, 0, 28, 0,
- 0, 0, 0, 1, 0, 0,
- 252, 0, 0, 0, 128, 0,
- 0, 0, 2, 0, 0, 0,
- 4, 0, 2, 0, 140, 0,
- 0, 0, 0, 0, 0, 0,
- 156, 0, 0, 0, 2, 0,
- 5, 0, 1, 0, 22, 0,
- 164, 0, 0, 0, 0, 0,
- 0, 0, 180, 0, 0, 0,
- 3, 0, 0, 0, 1, 0,
- 2, 0, 188, 0, 0, 0,
- 0, 0, 0, 0, 204, 0,
- 0, 0, 3, 0, 1, 0,
- 1, 0, 6, 0, 212, 0,
- 0, 0, 0, 0, 0, 0,
- 228, 0, 0, 0, 3, 0,
- 2, 0, 1, 0, 10, 0,
- 236, 0, 0, 0, 0, 0,
- 0, 0, 99, 111, 108, 111,
- 114, 109, 97, 116, 114, 105,
- 120, 0, 3, 0, 3, 0,
- 4, 0, 4, 0, 1, 0,
- 0, 0, 0, 0, 0, 0,
- 100, 101, 112, 116, 104, 0,
- 171, 171, 1, 0, 3, 0,
- 1, 0, 2, 0, 1, 0,
- 0, 0, 0, 0, 0, 0,
- 116, 101, 120, 48, 0, 171,
- 171, 171, 4, 0, 12, 0,
- 1, 0, 1, 0, 1, 0,
- 0, 0, 0, 0, 0, 0,
- 116, 101, 120, 49, 0, 171,
- 171, 171, 4, 0, 12, 0,
- 1, 0, 1, 0, 1, 0,
- 0, 0, 0, 0, 0, 0,
- 116, 101, 120, 50, 0, 171,
- 171, 171, 4, 0, 12, 0,
- 1, 0, 1, 0, 1, 0,
- 0, 0, 0, 0, 0, 0,
- 112, 115, 95, 50, 95, 48,
- 0, 77, 105, 99, 114, 111,
- 115, 111, 102, 116, 32, 40,
- 82, 41, 32, 72, 76, 83,
- 76, 32, 83, 104, 97, 100,
- 101, 114, 32, 67, 111, 109,
- 112, 105, 108, 101, 114, 32,
- 57, 46, 50, 55, 46, 57,
- 53, 50, 46, 51, 48, 50,
- 50, 0, 81, 0, 0, 5,
- 4, 0, 15, 160, 0, 0,
- 128, 63, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 31, 0, 0, 2,
- 0, 0, 0, 128, 0, 0,
- 3, 176, 31, 0, 0, 2,
- 0, 0, 0, 128, 1, 0,
- 3, 176, 31, 0, 0, 2,
- 0, 0, 0, 128, 2, 0,
- 3, 176, 31, 0, 0, 2,
- 0, 0, 0, 144, 0, 8,
- 15, 160, 31, 0, 0, 2,
- 0, 0, 0, 144, 1, 8,
- 15, 160, 31, 0, 0, 2,
- 0, 0, 0, 144, 2, 8,
- 15, 160, 66, 0, 0, 3,
- 0, 0, 15, 128, 0, 0,
- 228, 176, 0, 8, 228, 160,
- 66, 0, 0, 3, 1, 0,
- 15, 128, 1, 0, 228, 176,
- 1, 8, 228, 160, 66, 0,
- 0, 3, 2, 0, 15, 128,
- 2, 0, 228, 176, 2, 8,
- 228, 160, 5, 0, 0, 3,
- 0, 0, 1, 128, 0, 0,
- 0, 128, 5, 0, 0, 160,
- 4, 0, 0, 4, 0, 0,
- 1, 128, 0, 0, 255, 128,
- 5, 0, 85, 160, 0, 0,
- 0, 128, 5, 0, 0, 3,
- 1, 0, 1, 128, 1, 0,
- 0, 128, 5, 0, 0, 160,
- 4, 0, 0, 4, 0, 0,
- 2, 128, 1, 0, 255, 128,
- 5, 0, 85, 160, 1, 0,
- 0, 128, 5, 0, 0, 3,
- 1, 0, 1, 128, 2, 0,
- 0, 128, 5, 0, 0, 160,
- 4, 0, 0, 4, 0, 0,
- 4, 128, 2, 0, 255, 128,
- 5, 0, 85, 160, 1, 0,
- 0, 128, 1, 0, 0, 2,
- 0, 0, 8, 128, 4, 0,
- 0, 160, 9, 0, 0, 3,
- 1, 0, 1, 128, 0, 0,
- 228, 128, 0, 0, 228, 160,
- 9, 0, 0, 3, 1, 0,
- 2, 128, 0, 0, 228, 128,
- 1, 0, 228, 160, 9, 0,
- 0, 3, 1, 0, 4, 128,
- 0, 0, 228, 128, 2, 0,
- 228, 160, 9, 0, 0, 3,
- 1, 0, 8, 128, 0, 0,
- 228, 128, 3, 0, 228, 160,
- 1, 0, 0, 2, 0, 8,
- 15, 128, 1, 0, 228, 128,
- 255, 255, 0, 0
-};
diff --git a/libvo/fastmemcpy.h b/libvo/fastmemcpy.h
deleted file mode 100644
index c2cd79314f..0000000000
--- a/libvo/fastmemcpy.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * MPlayer 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with MPlayer; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef MPLAYER_FASTMEMCPY_H
-#define MPLAYER_FASTMEMCPY_H
-
-#include "config.h"
-#include <inttypes.h>
-#include <string.h>
-#include <stddef.h>
-
-#define memcpy_pic(d, s, b, h, ds, ss) memcpy_pic2(d, s, b, h, ds, ss, 0)
-#define my_memcpy_pic(d, s, b, h, ds, ss) memcpy_pic2(d, s, b, h, ds, ss, 1)
-
-/**
- * \param limit2width always skip data between end of line and start of next
- * instead of copying the full block when strides are the same
- */
-static inline void * memcpy_pic2(void * dst, const void * src,
- int bytesPerLine, int height,
- int dstStride, int srcStride, int limit2width)
-{
- int i;
- void *retval=dst;
-
- if(!limit2width && dstStride == srcStride)
- {
- if (srcStride < 0) {
- src = (uint8_t*)src + (height-1)*srcStride;
- dst = (uint8_t*)dst + (height-1)*dstStride;
- srcStride = -srcStride;
- }
-
- memcpy(dst, src, srcStride*height);
- }
- else
- {
- for(i=0; i<height; i++)
- {
- memcpy(dst, src, bytesPerLine);
- src = (uint8_t*)src + srcStride;
- dst = (uint8_t*)dst + dstStride;
- }
- }
-
- return retval;
-}
-
-static inline void memset_pic(void *dst, int fill, int bytesPerLine, int height,
- int stride)
-{
- if (bytesPerLine == stride) {
- memset(dst, fill, stride * height);
- } else {
- for (int i = 0; i < height; i++) {
- memset(dst, fill, bytesPerLine);
- dst = (uint8_t *)dst + stride;
- }
- }
-}
-
-#endif /* MPLAYER_FASTMEMCPY_H */
diff --git a/libvo/filter_kernels.c b/libvo/filter_kernels.c
deleted file mode 100644
index 2c2f56ee51..0000000000
--- a/libvo/filter_kernels.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * This file is part of mplayer2.
- *
- * Most code for computing the weights is taken from Anti-Grain Geometry (AGG)
- * (licensed under GPL 2 or later), with modifications.
- * Copyright (C) 2002-2006 Maxim Shemanarev
- * http://vector-agg.cvs.sourceforge.net/viewvc/vector-agg/agg-2.5/include/agg_image_filters.h?view=markup
- *
- * Also see glumpy (BSD licensed), contains the same code in Python:
- * http://code.google.com/p/glumpy/source/browse/glumpy/image/filter.py
- *
- * Also see: Paul Heckbert's "zoom"
- *
- * Also see XBMC: ConvolutionKernels.cpp etc.
- *
- * 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 <stddef.h>
-#include <string.h>
-#include <math.h>
-#include <assert.h>
-
-#include "filter_kernels.h"
-
-// NOTE: all filters are separable, symmetric, and are intended for use with
-// a lookup table/texture.
-
-const struct filter_kernel *mp_find_filter_kernel(const char *name)
-{
- for (const struct filter_kernel *k = mp_filter_kernels; k->name; k++) {
- if (strcmp(k->name, name) == 0)
- return k;
- }
- return NULL;
-}
-
-// sizes = sorted list of available filter sizes, terminated with size 0
-// inv_scale = source_size / dest_size
-bool mp_init_filter(struct filter_kernel *filter, const int *sizes,
- double inv_scale)
-{
- // only downscaling requires widening the filter
- filter->inv_scale = inv_scale >= 1.0 ? inv_scale : 1.0;
- double support = filter->radius * filter->inv_scale;
- int size = ceil(2.0 * support);
- // round up to smallest available size that's still large enough
- if (size < sizes[0])
- size = sizes[0];
- const int *cursize = sizes;
- while (size > *cursize && *cursize)
- cursize++;
- if (*cursize) {
- filter->size = *cursize;
- return true;
- } else {
- // The filter doesn't fit - instead of failing completely, use the
- // largest filter available. This is incorrect, but better than refusing
- // to do anything.
- filter->size = cursize[-1];
- filter->inv_scale = filter->size / 2.0 / filter->radius;
- return false;
- }
-}
-
-// Calculate the 1D filtering kernel for N sample points.
-// N = number of samples, which is filter->size
-// The weights will be stored in out_w[0] to out_w[N - 1]
-// f = x0 - abs(x0), subpixel position in the range [0,1) or [0,1].
-void mp_compute_weights(struct filter_kernel *filter, double f, float *out_w)
-{
- assert(filter->size > 0);
- double sum = 0;
- for (int n = 0; n < filter->size; n++) {
- double x = f - (n - filter->size / 2 + 1);
- double w = filter->weight(filter, fabs(x) / filter->inv_scale);
- out_w[n] = w;
- sum += w;
- }
- //normalize
- for (int n = 0; n < filter->size; n++)
- out_w[n] /= sum;
-}
-
-// Fill the given array with weights for the range [0.0, 1.0]. The array is
-// interpreted as rectangular array of count * filter->size items.
-void mp_compute_lut(struct filter_kernel *filter, int count, float *out_array)
-{
- for (int n = 0; n < count; n++) {
- mp_compute_weights(filter, n / (double)(count - 1),
- out_array + filter->size * n);
- }
-}
-
-typedef struct filter_kernel kernel;
-
-static double bilinear(kernel *k, double x)
-{
- return 1.0 - x;
-}
-
-static double hanning(kernel *k, double x)
-{
- return 0.5 + 0.5 * cos(M_PI * x);
-}
-
-static double hamming(kernel *k, double x)
-{
- return 0.54 + 0.46 * cos(M_PI * x);
-}
-
-static double hermite(kernel *k, double x)
-{
- return (2.0 * x - 3.0) * x * x + 1.0;
-}
-
-static double quadric(kernel *k, double x)
-{
- // NOTE: glumpy uses 0.75, AGG uses 0.5
- if (x < 0.5)
- return 0.75 - x * x;
- if (x < 1.5)
- return 0.5 * (x - 1.5) * (x - 1.5);
- return 0;
-}
-
-static double bc_pow3(double x)
-{
- return (x <= 0) ? 0 : x * x * x;
-}
-
-static double bicubic(kernel *k, double x)
-{
- return (1.0/6.0) * ( bc_pow3(x + 2)
- - 4 * bc_pow3(x + 1)
- + 6 * bc_pow3(x)
- - 4 * bc_pow3(x - 1));
-}
-
-static double bessel_i0(double epsilon, double x)
-{
- double sum = 1;
- double y = x * x / 4;
- double t = y;
- for (int i = 2; t > epsilon; i++) {
- sum += t;
- t *= y / (i * i);
- }
- return sum;
-}
-
-static double kaiser(kernel *k, double x)
-{
- double a = k->params[0];
- double b = k->params[1];
- double epsilon = 1e-12;
- double i0a = 1 / bessel_i0(epsilon, b);
- return bessel_i0(epsilon, a * sqrt(1 - x * x)) * i0a;
-}
-
-static double catmull_rom(kernel *k, double x)
-{
- if (x < 1.0)
- return 0.5 * (2.0 + x * x * (-5.0 + x * 3.0));
- if (x < 2.0)
- return 0.5 * (4.0 + x * (-8.0 + x * (5.0 - x)));
- return 0;
-}
-
-// Mitchell-Netravali
-static double mitchell(kernel *k, double x)
-{
- double b = k->params[0];
- double c = k->params[1];
- double
- p0 = (6.0 - 2.0 * b) / 6.0,
- p2 = (-18.0 + 12.0 * b + 6.0 * c) / 6.0,
- p3 = (12.0 - 9.0 * b - 6.0 * c) / 6.0,
- q0 = (8.0 * b + 24.0 * c) / 6.0,
- q1 = (-12.0 * b - 48.0 * c) / 6.0,
- q2 = (6.0 * b + 30.0 * c) / 6.0,
- q3 = (-b - 6.0 * c) / 6.0;
- if (x < 1.0)
- return p0 + x * x * (p2 + x * p3);
- if (x < 2.0)
- return q0 + x * (q1 + x * (q2 + x * q3));
- return 0;
-}
-
-static double spline16(kernel *k, double x)
-{
- if (x < 1.0)
- return ((x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0;
- return ((-1.0/3.0 * (x-1) + 4.0/5.0) * (x-1) - 7.0/15.0 ) * (x-1);
-}
-
-static double spline36(kernel *k, double x)
-{
- if(x < 1.0)
- return ((13.0/11.0 * x - 453.0/209.0) * x - 3.0/209.0) * x + 1.0;
- if(x < 2.0)
- return ((-6.0/11.0 * (x - 1) + 270.0/209.0) * (x - 1) - 156.0/209.0)
- * (x - 1);
- return ((1.0/11.0 * (x - 2) - 45.0/209.0) * (x - 2) + 26.0/209.0)
- * (x - 2);
-}
-
-static double gaussian(kernel *k, double x)
-{
- return exp(-2.0 * x * x) * sqrt(2.0 / M_PI);
-}
-
-static double sinc(kernel *k, double x)
-{
- if (x == 0.0)
- return 1.0;
- double pix = M_PI * x;
- return sin(pix) / pix;
-}
-
-static double lanczos(kernel *k, double x)
-{
- double radius = k->size / 2;
- if (x < -radius || x > radius)
- return 0;
- if (x == 0)
- return 1;
- double pix = M_PI * x;
- return radius * sin(pix) * sin(pix / radius) / (pix * pix);
-}
-
-static double blackman(kernel *k, double x)
-{
- double radius = k->size / 2;
- if (x == 0.0)
- return 1.0;
- if (x > radius)
- return 0.0;
- x *= M_PI;
- double xr = x / radius;
- return (sin(x) / x) * (0.42 + 0.5 * cos(xr) + 0.08 * cos(2 * xr));
-}
-
-const struct filter_kernel mp_filter_kernels[] = {
- {"bilinear_slow", 1, bilinear},
- {"hanning", 1, hanning},
- {"hamming", 1, hamming},
- {"hermite", 1, hermite},
- {"quadric", 1.5, quadric},
- {"bicubic", 2, bicubic},
- {"kaiser", 1, kaiser, .params = {6.33, 6.33} },
- {"catmull_rom", 2, catmull_rom},
- {"mitchell", 2, mitchell, .params = {1.0/3.0, 1.0/3.0} },
- {"spline16", 2, spline16},
- {"spline36", 3, spline36},
- {"gaussian", 2, gaussian},
- {"sinc2", 2, sinc},
- {"sinc3", 3, sinc},
- {"sinc4", 4, sinc},
- {"lanczos2", 2, lanczos},
- {"lanczos3", 3, lanczos},
- {"lanczos4", 4, lanczos},
- {"blackman2", 2, blackman},
- {"blackman3", 3, blackman},
- {"blackman4", 4, blackman},
- {0}
-};
diff --git a/libvo/filter_kernels.h b/libvo/filter_kernels.h
deleted file mode 100644
index 46a392c40a..0000000000
--- a/libvo/filter_kernels.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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_FILTER_KERNELS_H
-#define MPLAYER_FILTER_KERNELS_H
-
-#include <stdbool.h>
-
-struct filter_kernel {
- const char *name;
- double radius;
- double (*weight)(struct filter_kernel *kernel, double x);
-
- // The filter params can be changed at runtime. Only used by some filters.
- float params[2];
- // The following values are set by mp_init_filter() at runtime.
- // Number of coefficients; equals the rounded up radius multiplied with 2.
- int size;
- double inv_scale;
-};
-
-extern const struct filter_kernel mp_filter_kernels[];
-
-const struct filter_kernel *mp_find_filter_kernel(const char *name);
-bool mp_init_filter(struct filter_kernel *filter, const int *sizes,
- double scale);
-void mp_compute_weights(struct filter_kernel *filter, double f, float *out_w);
-void mp_compute_lut(struct filter_kernel *filter, int count, float *out_array);
-
-#endif /* MPLAYER_FILTER_KERNELS_H */
diff --git a/libvo/geometry.c b/libvo/geometry.c
deleted file mode 100644
index 941528aea9..0000000000
--- a/libvo/geometry.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * copyright (C) 2002 Mark Zealey <mark@zealos.org>
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <limits.h>
-#include "geometry.h"
-#include "mp_msg.h"
-
-/* A string of the form [WxH][+X+Y] or xpos[%]:ypos[%] */
-char *vo_geometry;
-// set when either width or height is changed
-int geometry_wh_changed;
-int geometry_xy_changed;
-
-// xpos,ypos: position of the left upper corner
-// widw,widh: width and height of the window
-// scrw,scrh: width and height of the current screen
-int geometry(int *xpos, int *ypos, int *widw, int *widh, int scrw, int scrh)
-{
- if(vo_geometry != NULL) {
- char xsign[2], ysign[2], dummy[2];
- int width, height, xoff, yoff, xper, yper;
- int i;
- int ok = 0;
- for (i = 0; !ok && i < 9; i++) {
- width = height = xoff = yoff = xper = yper = INT_MIN;
- strcpy(xsign, "+");
- strcpy(ysign, "+");
- switch (i) {
- case 0:
- ok = sscanf(vo_geometry, "%ix%i%1[+-]%i%1[+-]%i%c",
- &width, &height, xsign, &xoff, ysign,
- &yoff, dummy) == 6;
- break;
- case 1:
- ok = sscanf(vo_geometry, "%ix%i%c", &width, &height, dummy) == 2;
- break;
- case 2:
- ok = sscanf(vo_geometry, "%1[+-]%i%1[+-]%i%c",
- xsign, &xoff, ysign, &yoff, dummy) == 4;
- break;
- case 3:
- ok = sscanf(vo_geometry, "%i%%:%i%1[%]%c", &xper, &yper, dummy, dummy) == 3;
- break;
- case 4:
- ok = sscanf(vo_geometry, "%i:%i%1[%]%c", &xoff, &yper, dummy, dummy) == 3;
- break;
- case 5:
- ok = sscanf(vo_geometry, "%i%%:%i%c", &xper, &yoff, dummy) == 2;
- break;
- case 6:
- ok = sscanf(vo_geometry, "%i:%i%c", &xoff, &yoff, dummy) == 2;
- break;
- case 7:
- ok = sscanf(vo_geometry, "%i%1[%]%c", &xper, dummy, dummy) == 2;
- break;
- case 8:
- ok = sscanf(vo_geometry, "%i%c", &xoff, dummy) == 1;
- break;
- }
- }
- if (!ok) {
- mp_msg(MSGT_VO, MSGL_ERR,
- "-geometry must be in [WxH][[+-]X[+-]Y] | [X[%%]:[Y[%%]]] format, incorrect (%s)\n", vo_geometry);
- return 0;
- }
-
- mp_msg(MSGT_VO, MSGL_V,"geometry window parameter: widw: %i,"
- " widh: %i, scrw: %i, scrh: %i\n",*widw, *widh, scrw, scrh);
-
- mp_msg(MSGT_VO, MSGL_V,"geometry set to width: %i,"
- "height: %i, xoff: %s%i, yoff: %s%i, xper: %i, yper: %i\n",
- width, height, xsign, xoff, ysign, yoff, xper, yper);
-
- if (width > 0) *widw = width;
- if (height > 0) *widh = height;
-
- if(xoff != INT_MIN && xsign[0] == '-') xoff = scrw - *widw - xoff;
- if(yoff != INT_MIN && ysign[0] == '-') yoff = scrh - *widh - yoff;
- if(xper >= 0 && xper <= 100) xoff = (scrw - *widw) * ((float)xper / 100.0);
- if(yper >= 0 && yper <= 100) yoff = (scrh - *widh) * ((float)yper / 100.0);
-
- mp_msg(MSGT_VO, MSGL_V,"geometry set to width: %i,"
- "height: %i, xoff: %i, yoff: %i, xper: %i, yper: %i\n",
- width, height, xoff, yoff, xper, yper);
-
- if (xoff != INT_MIN && xpos) *xpos = xoff;
- if (yoff != INT_MIN && ypos) *ypos = yoff;
-
- geometry_wh_changed = width > 0 || height > 0;
- geometry_xy_changed = xoff != INT_MIN || yoff != INT_MIN;
- }
- return 1;
-}
diff --git a/libvo/geometry.h b/libvo/geometry.h
deleted file mode 100644
index 77868a5aad..0000000000
--- a/libvo/geometry.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * copyright (C) 2002 Mark Zealey <mark@zealos.org>
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_GEOMETRY_H
-#define MPLAYER_GEOMETRY_H
-
-extern char *vo_geometry;
-extern int geometry_wh_changed;
-extern int geometry_xy_changed;
-int geometry(int *xpos, int *ypos, int *widw, int *widh, int scrw, int scrh);
-
-#endif /* MPLAYER_GEOMETRY_H */
diff --git a/libvo/gl_common.c b/libvo/gl_common.c
deleted file mode 100644
index 80db2eacc4..0000000000
--- a/libvo/gl_common.c
+++ /dev/null
@@ -1,2654 +0,0 @@
-/*
- * common OpenGL routines
- *
- * copyleft (C) 2005-2010 Reimar Döffinger <Reimar.Doeffinger@gmx.de>
- * Special thanks go to the xine team and Matthias Hopf, whose video_out_opengl.c
- * gave me lots of good ideas.
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * You can alternatively redistribute this file and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- */
-
-/**
- * \file gl_common.c
- * \brief OpenGL helper functions used by vo_gl.c and vo_gl2.c
- */
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdbool.h>
-#include <math.h>
-#include <assert.h>
-#include "talloc.h"
-#include "gl_common.h"
-#include "csputils.h"
-#include "aspect.h"
-#include "pnm_loader.h"
-#include "options.h"
-#include "sub/sub.h"
-#include "bitmap_packer.h"
-
-//! \defgroup glgeneral OpenGL general helper functions
-
-// GLU has this as gluErrorString (we don't use GLU, as it is legacy-OpenGL)
-static const char *gl_error_to_string(GLenum error)
-{
- switch (error) {
- case GL_INVALID_ENUM: return "INVALID_ENUM";
- case GL_INVALID_VALUE: return "INVALID_VALUE";
- case GL_INVALID_OPERATION: return "INVALID_OPERATION";
- case GL_INVALID_FRAMEBUFFER_OPERATION:
- return "INVALID_FRAMEBUFFER_OPERATION";
- case GL_OUT_OF_MEMORY: return "OUT_OF_MEMORY";
- default: return "unknown";
- }
-}
-
-void glCheckError(GL *gl, const char *info)
-{
- for (;;) {
- GLenum error = gl->GetError();
- if (error == GL_NO_ERROR)
- break;
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] %s: OpenGL error %s.\n", info,
- gl_error_to_string(error));
- }
-}
-
-//! \defgroup glcontext OpenGL context management helper functions
-
-//! \defgroup gltexture OpenGL texture handling helper functions
-
-//! \defgroup glconversion OpenGL conversion helper functions
-
-/**
- * \brief adjusts the GL_UNPACK_ALIGNMENT to fit the stride.
- * \param stride number of bytes per line for which alignment should fit.
- * \ingroup glgeneral
- */
-void glAdjustAlignment(GL *gl, int stride)
-{
- GLint gl_alignment;
- if (stride % 8 == 0)
- gl_alignment = 8;
- else if (stride % 4 == 0)
- gl_alignment = 4;
- else if (stride % 2 == 0)
- gl_alignment = 2;
- else
- gl_alignment = 1;
- gl->PixelStorei(GL_UNPACK_ALIGNMENT, gl_alignment);
- gl->PixelStorei(GL_PACK_ALIGNMENT, gl_alignment);
-}
-
-//! always return this format as internal texture format in glFindFormat
-#define TEXTUREFORMAT_ALWAYS GL_RGB8
-#undef TEXTUREFORMAT_ALWAYS
-
-/**
- * \brief find the OpenGL settings coresponding to format.
- *
- * All parameters may be NULL.
- * \param fmt MPlayer format to analyze.
- * \param bpp [OUT] bits per pixel of that format.
- * \param gl_texfmt [OUT] internal texture format that fits the
- * image format, not necessarily the best for performance.
- * \param gl_format [OUT] OpenGL format for this image format.
- * \param gl_type [OUT] OpenGL type for this image format.
- * \return 1 if format is supported by OpenGL, 0 if not.
- * \ingroup gltexture
- */
-int glFindFormat(uint32_t fmt, int have_texture_rg, int *bpp, GLint *gl_texfmt,
- GLenum *gl_format, GLenum *gl_type)
-{
- int supported = 1;
- int dummy1;
- GLenum dummy2;
- GLint dummy3;
- if (!bpp)
- bpp = &dummy1;
- if (!gl_texfmt)
- gl_texfmt = &dummy3;
- if (!gl_format)
- gl_format = &dummy2;
- if (!gl_type)
- gl_type = &dummy2;
-
- if (mp_get_chroma_shift(fmt, NULL, NULL, NULL)) {
- // reduce the possible cases a bit
- if (IMGFMT_IS_YUVP16_LE(fmt))
- fmt = IMGFMT_420P16_LE;
- else if (IMGFMT_IS_YUVP16_BE(fmt))
- fmt = IMGFMT_420P16_BE;
- else
- fmt = IMGFMT_YV12;
- }
-
- *bpp = IMGFMT_IS_BGR(fmt) ? IMGFMT_BGR_DEPTH(fmt) : IMGFMT_RGB_DEPTH(fmt);
- *gl_texfmt = 3;
- switch (fmt) {
- case IMGFMT_RGB48NE:
- *gl_format = GL_RGB;
- *gl_type = GL_UNSIGNED_SHORT;
- break;
- case IMGFMT_RGB24:
- *gl_format = GL_RGB;
- *gl_type = GL_UNSIGNED_BYTE;
- break;
- case IMGFMT_RGBA:
- *gl_texfmt = 4;
- *gl_format = GL_RGBA;
- *gl_type = GL_UNSIGNED_BYTE;
- break;
- case IMGFMT_420P16:
- supported = 0; // no native YUV support
- *gl_texfmt = have_texture_rg ? GL_R16 : GL_LUMINANCE16;
- *bpp = 16;
- *gl_format = have_texture_rg ? GL_RED : GL_LUMINANCE;
- *gl_type = GL_UNSIGNED_SHORT;
- break;
- case IMGFMT_YV12:
- supported = 0; // no native YV12 support
- case IMGFMT_Y800:
- case IMGFMT_Y8:
- *gl_texfmt = 1;
- *bpp = 8;
- *gl_format = GL_LUMINANCE;
- *gl_type = GL_UNSIGNED_BYTE;
- break;
- case IMGFMT_UYVY:
- // IMGFMT_YUY2 would be more logical for the _REV format,
- // but gives clearly swapped colors.
- case IMGFMT_YVYU:
- *gl_texfmt = GL_YCBCR_MESA;
- *bpp = 16;
- *gl_format = GL_YCBCR_MESA;
- *gl_type = fmt == IMGFMT_UYVY ? GL_UNSIGNED_SHORT_8_8 : GL_UNSIGNED_SHORT_8_8_REV;
- break;
-#if 0
- // 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;
- break;
-#endif
- case IMGFMT_RGB15:
- *gl_format = GL_RGBA;
- *gl_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
- break;
- case IMGFMT_RGB16:
- *gl_format = GL_RGB;
- *gl_type = GL_UNSIGNED_SHORT_5_6_5_REV;
- break;
-#if 0
- case IMGFMT_BGR8:
- // 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;
- break;
-#endif
- case IMGFMT_BGR15:
- *gl_format = GL_BGRA;
- *gl_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
- break;
- case IMGFMT_BGR16:
- *gl_format = GL_RGB;
- *gl_type = GL_UNSIGNED_SHORT_5_6_5;
- break;
- case IMGFMT_BGR24:
- *gl_format = GL_BGR;
- *gl_type = GL_UNSIGNED_BYTE;
- break;
- case IMGFMT_BGRA:
- *gl_texfmt = 4;
- *gl_format = GL_BGRA;
- *gl_type = GL_UNSIGNED_BYTE;
- break;
- default:
- *gl_texfmt = 4;
- *gl_format = GL_RGBA;
- *gl_type = GL_UNSIGNED_BYTE;
- supported = 0;
- }
-#ifdef TEXTUREFORMAT_ALWAYS
- *gl_texfmt = TEXTUREFORMAT_ALWAYS;
-#endif
- return supported;
-}
-
-struct feature {
- int id;
- const char *name;
-};
-
-static const struct feature features[] = {
- {MPGL_CAP_GL, "Basic OpenGL"},
- {MPGL_CAP_GL_LEGACY, "Legacy OpenGL"},
- {MPGL_CAP_GL2, "OpenGL 2.0"},
- {MPGL_CAP_GL21, "OpenGL 2.1"},
- {MPGL_CAP_GL3, "OpenGL 3.0"},
- {MPGL_CAP_FB, "Framebuffers"},
- {MPGL_CAP_VAO, "VAOs"},
- {MPGL_CAP_SRGB_TEX, "sRGB textures"},
- {MPGL_CAP_SRGB_FB, "sRGB framebuffers"},
- {MPGL_CAP_FLOAT_TEX, "Float textures"},
- {MPGL_CAP_TEX_RG, "RG textures"},
- {MPGL_CAP_NO_SW, "NO_SW"},
- {0},
-};
-
-static void list_features(int set, int msgl, bool invert)
-{
- for (const struct feature *f = &features[0]; f->id; f++) {
- if (invert == !(f->id & set))
- mp_msg(MSGT_VO, msgl, " [%s]", f->name);
- }
- mp_msg(MSGT_VO, msgl, "\n");
-}
-
-// This guesses if the current GL context is a suspected software renderer.
-static bool is_software_gl(GL *gl)
-{
- const char *renderer = gl->GetString(GL_RENDERER);
- const char *vendor = gl->GetString(GL_VENDOR);
- return !(renderer && vendor) ||
- strcmp(renderer, "Software Rasterizer") == 0 ||
- strstr(renderer, "llvmpipe") ||
- strcmp(vendor, "Microsoft Corporation") == 0 ||
- strcmp(renderer, "Mesa X11") == 0;
-}
-
-#ifdef HAVE_LIBDL
-#include <dlfcn.h>
-#endif
-/**
- * \brief find address of a linked function
- * \param s name of function to find
- * \return address of function or NULL if not found
- */
-static void *getdladdr(const char *s)
-{
- void *ret = NULL;
-#ifdef HAVE_LIBDL
- void *handle = dlopen(NULL, RTLD_LAZY);
- if (!handle)
- return NULL;
- ret = dlsym(handle, s);
- dlclose(handle);
-#endif
- return ret;
-}
-
-#define FN_OFFS(name) offsetof(GL, name)
-
-// Define the function with a "hard" reference to the function as fallback.
-// (This requires linking with a compatible OpenGL library.)
-#define DEF_FN_HARD(name) {FN_OFFS(name), {"gl" # name}, gl ## name}
-
-#define DEF_FN(name) {FN_OFFS(name), {"gl" # name}}
-#define DEF_FN_NAMES(name, ...) {FN_OFFS(name), {__VA_ARGS__}}
-
-struct gl_function {
- ptrdiff_t offset;
- char *funcnames[7];
- void *fallback;
-};
-
-struct gl_functions {
- const char *extension; // introduced with this extension in any version
- int provides; // bitfield of MPGL_CAP_* constants
- int ver_core; // introduced as required function
- int ver_removed; // removed as required function (no replacement)
- bool partial_ok; // loading only some functions is ok
- struct gl_function *functions;
-};
-
-#define MAX_FN_COUNT 50 // max functions per gl_functions section
-
-struct gl_functions gl_functions[] = {
- // GL functions which are always available anywhere at least since 1.1
- {
- .ver_core = MPGL_VER(1, 1),
- .provides = MPGL_CAP_GL,
- .functions = (struct gl_function[]) {
- DEF_FN_HARD(Viewport),
- DEF_FN_HARD(Clear),
- DEF_FN_HARD(GenTextures),
- DEF_FN_HARD(DeleteTextures),
- DEF_FN_HARD(TexEnvi),
- DEF_FN_HARD(ClearColor),
- DEF_FN_HARD(Enable),
- DEF_FN_HARD(Disable),
- DEF_FN_HARD(DrawBuffer),
- DEF_FN_HARD(DepthMask),
- DEF_FN_HARD(BlendFunc),
- DEF_FN_HARD(Flush),
- DEF_FN_HARD(Finish),
- DEF_FN_HARD(PixelStorei),
- DEF_FN_HARD(TexImage1D),
- DEF_FN_HARD(TexImage2D),
- DEF_FN_HARD(TexSubImage2D),
- DEF_FN_HARD(GetTexImage),
- DEF_FN_HARD(TexParameteri),
- DEF_FN_HARD(TexParameterf),
- DEF_FN_HARD(TexParameterfv),
- DEF_FN_HARD(GetIntegerv),
- DEF_FN_HARD(GetBooleanv),
- DEF_FN_HARD(ColorMask),
- DEF_FN_HARD(ReadPixels),
- DEF_FN_HARD(ReadBuffer),
- DEF_FN_HARD(DrawArrays),
- DEF_FN_HARD(GetString),
- DEF_FN_HARD(GetError),
- {0}
- },
- },
- // GL 2.0-3.x functions
- {
- .ver_core = MPGL_VER(2, 0),
- .provides = MPGL_CAP_GL2,
- .functions = (struct gl_function[]) {
- DEF_FN(GenBuffers),
- DEF_FN(DeleteBuffers),
- DEF_FN(BindBuffer),
- DEF_FN(MapBuffer),
- DEF_FN(UnmapBuffer),
- DEF_FN(BufferData),
- DEF_FN(ActiveTexture),
- DEF_FN(BindTexture),
- DEF_FN(GetAttribLocation),
- DEF_FN(EnableVertexAttribArray),
- DEF_FN(DisableVertexAttribArray),
- DEF_FN(VertexAttribPointer),
- DEF_FN(UseProgram),
- DEF_FN(GetUniformLocation),
- DEF_FN(CompileShader),
- DEF_FN(CreateProgram),
- DEF_FN(CreateShader),
- DEF_FN(ShaderSource),
- DEF_FN(LinkProgram),
- DEF_FN(AttachShader),
- DEF_FN(DeleteShader),
- DEF_FN(DeleteProgram),
- DEF_FN(GetShaderInfoLog),
- DEF_FN(GetShaderiv),
- DEF_FN(GetProgramInfoLog),
- DEF_FN(GetProgramiv),
- DEF_FN(BindAttribLocation),
- DEF_FN(Uniform1f),
- DEF_FN(Uniform2f),
- DEF_FN(Uniform3f),
- DEF_FN(Uniform1i),
- DEF_FN(UniformMatrix3fv),
- DEF_FN(TexImage3D),
- {0},
- },
- },
- // GL 2.1-3.x functions (also: GLSL 120 shaders)
- {
- .ver_core = MPGL_VER(2, 1),
- .provides = MPGL_CAP_GL21,
- .functions = (struct gl_function[]) {
- DEF_FN(UniformMatrix4x3fv),
- {0}
- },
- },
- // GL 3.x core only functions.
- {
- .ver_core = MPGL_VER(3, 0),
- .provides = MPGL_CAP_GL3 | MPGL_CAP_SRGB_TEX | MPGL_CAP_SRGB_FB,
- .functions = (struct gl_function[]) {
- DEF_FN(GetStringi),
- {0}
- },
- },
- // Framebuffers, extension in GL 2.x, core in GL 3.x core.
- {
- .ver_core = MPGL_VER(3, 0),
- .extension = "GL_ARB_framebuffer_object",
- .provides = MPGL_CAP_FB,
- .functions = (struct gl_function[]) {
- DEF_FN(BindFramebuffer),
- DEF_FN(GenFramebuffers),
- DEF_FN(DeleteFramebuffers),
- DEF_FN(CheckFramebufferStatus),
- DEF_FN(FramebufferTexture2D),
- {0}
- },
- },
- // Framebuffers, alternative extension name.
- {
- .ver_removed = MPGL_VER(3, 0), // don't touch these fn names in 3.x
- .extension = "GL_EXT_framebuffer_object",
- .provides = MPGL_CAP_FB,
- .functions = (struct gl_function[]) {
- DEF_FN_NAMES(BindFramebuffer, "glBindFramebufferEXT"),
- DEF_FN_NAMES(GenFramebuffers, "glGenFramebuffersEXT"),
- DEF_FN_NAMES(DeleteFramebuffers, "glDeleteFramebuffersEXT"),
- DEF_FN_NAMES(CheckFramebufferStatus, "glCheckFramebufferStatusEXT"),
- DEF_FN_NAMES(FramebufferTexture2D, "glFramebufferTexture2DEXT"),
- {0}
- },
- },
- // VAOs, extension in GL 2.x, core in GL 3.x core.
- {
- .ver_core = MPGL_VER(3, 0),
- .extension = "GL_ARB_vertex_array_object",
- .provides = MPGL_CAP_VAO,
- .functions = (struct gl_function[]) {
- DEF_FN(GenVertexArrays),
- DEF_FN(BindVertexArray),
- DEF_FN(DeleteVertexArrays),
- {0}
- }
- },
- // sRGB textures, extension in GL 2.x, core in GL 3.x core.
- {
- .ver_core = MPGL_VER(3, 0),
- .extension = "GL_EXT_texture_sRGB",
- .provides = MPGL_CAP_SRGB_TEX,
- .functions = (struct gl_function[]) {{0}},
- },
- // sRGB framebuffers, extension in GL 2.x, core in GL 3.x core.
- {
- .ver_core = MPGL_VER(3, 0),
- .extension = "GL_EXT_framebuffer_sRGB",
- .provides = MPGL_CAP_SRGB_FB,
- .functions = (struct gl_function[]) {{0}},
- },
- // Float textures, extension in GL 2.x, core in GL 3.x core.
- {
- .ver_core = MPGL_VER(3, 0),
- .extension = "GL_ARB_texture_float",
- .provides = MPGL_CAP_FLOAT_TEX,
- .functions = (struct gl_function[]) {{0}},
- },
- // GL_RED / GL_RG textures, extension in GL 2.x, core in GL 3.x core.
- {
- .ver_core = MPGL_VER(3, 0),
- .extension = "GL_ARB_texture_rg",
- .provides = MPGL_CAP_TEX_RG,
- .functions = (struct gl_function[]) {{0}},
- },
- // Swap control, always an OS specific extension
- {
- .extension = "_swap_control",
- .functions = (struct gl_function[]) {
- DEF_FN_NAMES(SwapInterval, "glXSwapIntervalSGI", "glXSwapInterval",
- "wglSwapIntervalSGI", "wglSwapInterval",
- "wglSwapIntervalEXT"),
- {0}
- },
- },
- // GL legacy functions in GL 1.x - 2.x, removed from GL 3.x
- {
- .ver_core = MPGL_VER(1, 1),
- .ver_removed = MPGL_VER(3, 0),
- .provides = MPGL_CAP_GL_LEGACY,
- .functions = (struct gl_function[]) {
- DEF_FN_HARD(Begin),
- DEF_FN_HARD(End),
- DEF_FN_HARD(MatrixMode),
- DEF_FN_HARD(LoadIdentity),
- DEF_FN_HARD(Translated),
- DEF_FN_HARD(Scaled),
- DEF_FN_HARD(Ortho),
- DEF_FN_HARD(PushMatrix),
- DEF_FN_HARD(PopMatrix),
- DEF_FN_HARD(GenLists),
- DEF_FN_HARD(DeleteLists),
- DEF_FN_HARD(NewList),
- DEF_FN_HARD(EndList),
- DEF_FN_HARD(CallList),
- DEF_FN_HARD(CallLists),
- DEF_FN_HARD(Color4ub),
- DEF_FN_HARD(Color4f),
- DEF_FN_HARD(TexCoord2f),
- DEF_FN_HARD(TexCoord2fv),
- DEF_FN_HARD(Vertex2f),
- DEF_FN_HARD(VertexPointer),
- DEF_FN_HARD(ColorPointer),
- DEF_FN_HARD(TexCoordPointer),
- DEF_FN_HARD(EnableClientState),
- DEF_FN_HARD(DisableClientState),
- {0}
- },
- },
- // Loading of old extensions, which are later added to GL 2.0.
- // NOTE: actually we should be checking the extension strings: the OpenGL
- // library could provide an entry point, but not implement it.
- // But the previous code didn't do that, and nobody ever complained.
- {
- .ver_removed = MPGL_VER(2, 1),
- .partial_ok = true,
- .functions = (struct gl_function[]) {
- DEF_FN_NAMES(GenBuffers, "glGenBuffers", "glGenBuffersARB"),
- DEF_FN_NAMES(DeleteBuffers, "glDeleteBuffers", "glDeleteBuffersARB"),
- DEF_FN_NAMES(BindBuffer, "glBindBuffer", "glBindBufferARB"),
- DEF_FN_NAMES(MapBuffer, "glMapBuffer", "glMapBufferARB"),
- DEF_FN_NAMES(UnmapBuffer, "glUnmapBuffer", "glUnmapBufferARB"),
- DEF_FN_NAMES(BufferData, "glBufferData", "glBufferDataARB"),
- DEF_FN_NAMES(ActiveTexture, "glActiveTexture", "glActiveTextureARB"),
- DEF_FN_NAMES(BindTexture, "glBindTexture", "glBindTextureARB", "glBindTextureEXT"),
- DEF_FN_NAMES(MultiTexCoord2f, "glMultiTexCoord2f", "glMultiTexCoord2fARB"),
- DEF_FN_NAMES(TexImage3D, "glTexImage3D"),
- {0}
- },
- },
- // Ancient ARB shaders.
- {
- .extension = "_program",
- .ver_removed = MPGL_VER(3, 0),
- .functions = (struct gl_function[]) {
- DEF_FN_NAMES(GenPrograms, "glGenProgramsARB"),
- DEF_FN_NAMES(DeletePrograms, "glDeleteProgramsARB"),
- DEF_FN_NAMES(BindProgram, "glBindProgramARB"),
- DEF_FN_NAMES(ProgramString, "glProgramStringARB"),
- DEF_FN_NAMES(GetProgramivARB, "glGetProgramivARB"),
- DEF_FN_NAMES(ProgramEnvParameter4f, "glProgramEnvParameter4fARB"),
- {0}
- },
- },
- // Ancient ATI extensions.
- {
- .extension = "ATI_fragment_shader",
- .ver_removed = MPGL_VER(3, 0),
- .functions = (struct gl_function[]) {
- DEF_FN_NAMES(BeginFragmentShader, "glBeginFragmentShaderATI"),
- DEF_FN_NAMES(EndFragmentShader, "glEndFragmentShaderATI"),
- DEF_FN_NAMES(SampleMap, "glSampleMapATI"),
- DEF_FN_NAMES(ColorFragmentOp2, "glColorFragmentOp2ATI"),
- DEF_FN_NAMES(ColorFragmentOp3, "glColorFragmentOp3ATI"),
- DEF_FN_NAMES(SetFragmentShaderConstant, "glSetFragmentShaderConstantATI"),
- {0}
- },
- },
-};
-
-#undef FN_OFFS
-#undef DEF_FN_HARD
-#undef DEF_FN
-#undef DEF_FN_NAMES
-
-
-/**
- * \brief find the function pointers of some useful OpenGL extensions
- * \param getProcAddress function to resolve function names, may be NULL
- * \param ext2 an extra extension string
- */
-static void getFunctions(GL *gl, void *(*getProcAddress)(const GLubyte *),
- const char *ext2, bool gl3)
-{
- talloc_free_children(gl);
- *gl = (GL) {
- .extensions = talloc_strdup(gl, ext2 ? ext2 : ""),
- };
-
- if (!getProcAddress)
- getProcAddress = (void *)getdladdr;
-
- GLint major = 0, minor = 0;
- if (gl3) {
- gl->GetStringi = getProcAddress("glGetStringi");
- gl->GetIntegerv = getProcAddress("glGetIntegerv");
-
- if (!(gl->GetStringi && gl->GetIntegerv))
- return;
-
- gl->GetIntegerv(GL_MAJOR_VERSION, &major);
- gl->GetIntegerv(GL_MINOR_VERSION, &minor);
-
- GLint exts;
- gl->GetIntegerv(GL_NUM_EXTENSIONS, &exts);
- for (int n = 0; n < exts; n++) {
- gl->extensions
- = talloc_asprintf_append(gl->extensions, " %s",
- gl->GetStringi(GL_EXTENSIONS, n));
- }
- } else {
- gl->GetString = getProcAddress("glGetString");
- if (!gl->GetString)
- gl->GetString = glGetString;
-
- const char *ext = (char*)gl->GetString(GL_EXTENSIONS);
- gl->extensions = talloc_asprintf_append(gl->extensions, " %s", ext);
-
- const char *version = gl->GetString(GL_VERSION);
- sscanf(version, "%d.%d", &major, &minor);
- }
- gl->version = MPGL_VER(major, minor);
-
- mp_msg(MSGT_VO, MSGL_V, "[gl] Detected OpenGL %d.%d.\n", major, minor);
- mp_msg(MSGT_VO, MSGL_DBG2, "[gl] Combined OpenGL extensions string:\n%s\n",
- gl->extensions);
-
- for (int n = 0; n < sizeof(gl_functions) / sizeof(gl_functions[0]); n++) {
- struct gl_functions *section = &gl_functions[n];
-
- // With gl3=false, we could have a legacy context, where functionality
- // is never removed. (E.g. the context could be at version >= 3.0, but
- // legacy functions like glBegin still exist and work.)
- if (gl3 && section->ver_removed && gl->version >= section->ver_removed)
- continue;
-
- bool must_exist = section->ver_core && gl->version >= section->ver_core
- && !section->partial_ok;
-
- if (!must_exist && section->extension &&
- !strstr(gl->extensions, section->extension))
- continue;
-
- void *loaded[MAX_FN_COUNT] = {0};
- bool all_loaded = true;
-
- for (int i = 0; section->functions[i].funcnames[0]; i++) {
- struct gl_function *fn = &section->functions[i];
- void *ptr = NULL;
- for (int x = 0; fn->funcnames[x]; x++) {
- ptr = getProcAddress((const GLubyte *)fn->funcnames[x]);
- if (ptr)
- break;
- }
- if (!ptr)
- ptr = fn->fallback;
- if (!ptr) {
- all_loaded = false;
- if (must_exist) {
- // Either we or the driver are not conforming to OpenGL.
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] Required function '%s' not "
- "found.\n", fn->funcnames[0]);
- talloc_free_children(gl);
- *gl = (GL) {0};
- return;
- }
- }
- assert(i < MAX_FN_COUNT);
- loaded[i] = ptr;
- }
-
- if (all_loaded || section->partial_ok) {
- gl->mpgl_caps |= section->provides;
- for (int i = 0; section->functions[i].funcnames[0]; i++) {
- struct gl_function *fn = &section->functions[i];
- void **funcptr = (void**)(((char*)gl) + fn->offset);
- if (loaded[i])
- *funcptr = loaded[i];
- }
- }
- }
-
- gl->glsl_version = 0;
- if (gl->version >= MPGL_VER(2, 0))
- gl->glsl_version = 110;
- if (gl->version >= MPGL_VER(2, 1))
- gl->glsl_version = 120;
- if (gl->version >= MPGL_VER(3, 0))
- gl->glsl_version = 130;
- // Specifically needed for OSX (normally we request 3.0 contexts only, but
- // OSX always creates 3.2 contexts when requesting a core context).
- if (gl->version >= MPGL_VER(3, 2))
- gl->glsl_version = 150;
-
- if (!is_software_gl(gl))
- gl->mpgl_caps |= MPGL_CAP_NO_SW;
-
- mp_msg(MSGT_VO, MSGL_V, "[gl] Detected OpenGL features:");
- list_features(gl->mpgl_caps, MSGL_V, false);
-}
-
-/**
- * \brief create a texture and set some defaults
- * \param target texture taget, usually GL_TEXTURE_2D
- * \param fmt internal texture format
- * \param format texture host data format
- * \param type texture host data type
- * \param filter filter used for scaling, e.g. GL_LINEAR
- * \param w texture width
- * \param h texture height
- * \param val luminance value to fill texture with
- * \ingroup gltexture
- */
-void glCreateClearTex(GL *gl, GLenum target, GLenum fmt, GLenum format,
- GLenum type, GLint filter, int w, int h,
- unsigned char val)
-{
- GLfloat fval = (GLfloat)val / 255.0;
- GLfloat border[4] = {
- fval, fval, fval, fval
- };
- int stride;
- char *init;
- if (w == 0)
- w = 1;
- if (h == 0)
- h = 1;
- stride = w * glFmt2bpp(format, type);
- if (!stride)
- return;
- init = malloc(stride * h);
- memset(init, val, stride * h);
- glAdjustAlignment(gl, stride);
- gl->PixelStorei(GL_UNPACK_ROW_LENGTH, w);
- gl->TexImage2D(target, 0, fmt, w, h, 0, format, type, init);
- gl->TexParameterf(target, GL_TEXTURE_PRIORITY, 1.0);
- gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
- gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
- gl->TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gl->TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- // Border texels should not be used with CLAMP_TO_EDGE
- // We set a sane default anyway.
- gl->TexParameterfv(target, GL_TEXTURE_BORDER_COLOR, border);
- free(init);
-}
-
-static GLint detect_hqtexfmt(GL *gl)
-{
- const char *extensions = (const char *)gl->GetString(GL_EXTENSIONS);
- if (strstr(extensions, "_texture_float"))
- return GL_RGB32F;
- else if (strstr(extensions, "NV_float_buffer"))
- return GL_FLOAT_RGB32_NV;
- return GL_RGB16;
-}
-
-/**
- * \brief creates a texture from a PPM file
- * \param target texture taget, usually GL_TEXTURE_2D
- * \param fmt internal texture format, 0 for default
- * \param filter filter used for scaling, e.g. GL_LINEAR
- * \param f file to read PPM from
- * \param width [out] width of texture
- * \param height [out] height of texture
- * \param maxval [out] maxval value from PPM file
- * \return 0 on error, 1 otherwise
- * \ingroup gltexture
- */
-int glCreatePPMTex(GL *gl, GLenum target, GLenum fmt, GLint filter,
- FILE *f, int *width, int *height, int *maxval)
-{
- int w, h, m, bpp;
- GLenum type;
- uint8_t *data = read_pnm(f, &w, &h, &bpp, &m);
- GLint hqtexfmt = detect_hqtexfmt(gl);
- if (!data || (bpp != 3 && bpp != 6)) {
- free(data);
- return 0;
- }
- if (!fmt) {
- fmt = bpp == 6 ? hqtexfmt : 3;
- if (fmt == GL_FLOAT_RGB32_NV && target != GL_TEXTURE_RECTANGLE)
- fmt = GL_RGB16;
- }
- type = bpp == 6 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE;
- glCreateClearTex(gl, target, fmt, GL_RGB, type, filter, w, h, 0);
- glUploadTex(gl, target, GL_RGB, type,
- data, w * bpp, 0, 0, w, h, 0);
- free(data);
- if (width)
- *width = w;
- if (height)
- *height = h;
- if (maxval)
- *maxval = m;
- return 1;
-}
-
-/**
- * \brief return the number of bytes per pixel for the given format
- * \param format OpenGL format
- * \param type OpenGL type
- * \return bytes per pixel
- * \ingroup glgeneral
- *
- * Does not handle all possible variants, just those used by MPlayer
- */
-int glFmt2bpp(GLenum format, GLenum type)
-{
- int component_size = 0;
- switch (type) {
- case GL_UNSIGNED_BYTE_3_3_2:
- case GL_UNSIGNED_BYTE_2_3_3_REV:
- return 1;
- case GL_UNSIGNED_SHORT_5_5_5_1:
- case GL_UNSIGNED_SHORT_1_5_5_5_REV:
- case GL_UNSIGNED_SHORT_5_6_5:
- case GL_UNSIGNED_SHORT_5_6_5_REV:
- return 2;
- case GL_UNSIGNED_BYTE:
- component_size = 1;
- break;
- case GL_UNSIGNED_SHORT:
- component_size = 2;
- break;
- }
- switch (format) {
- case GL_LUMINANCE:
- case GL_ALPHA:
- return component_size;
- case GL_YCBCR_MESA:
- return 2;
- case GL_RGB:
- case GL_BGR:
- return 3 * component_size;
- case GL_RGBA:
- case GL_BGRA:
- return 4 * component_size;
- case GL_RED:
- return component_size;
- case GL_RG:
- case GL_LUMINANCE_ALPHA:
- return 2 * component_size;
- }
- abort(); // unknown
-}
-
-/**
- * \brief upload a texture, handling things like stride and slices
- * \param target texture target, usually GL_TEXTURE_2D
- * \param format OpenGL format of data
- * \param type OpenGL type of data
- * \param dataptr data to upload
- * \param stride data stride
- * \param x x offset in texture
- * \param y y offset in texture
- * \param w width of the texture part to upload
- * \param h height of the texture part to upload
- * \param slice height of an upload slice, 0 for all at once
- * \ingroup gltexture
- */
-void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type,
- const void *dataptr, int stride,
- int x, int y, int w, int h, int slice)
-{
- const uint8_t *data = dataptr;
- int y_max = y + h;
- if (w <= 0 || h <= 0)
- return;
- if (slice <= 0)
- slice = h;
- if (stride < 0) {
- data += (h - 1) * stride;
- stride = -stride;
- }
- // this is not always correct, but should work for MPlayer
- glAdjustAlignment(gl, stride);
- gl->PixelStorei(GL_UNPACK_ROW_LENGTH, stride / glFmt2bpp(format, type));
- for (; y + slice <= y_max; y += slice) {
- gl->TexSubImage2D(target, 0, x, y, w, slice, format, type, data);
- data += stride * slice;
- }
- if (y < y_max)
- gl->TexSubImage2D(target, 0, x, y, w, y_max - y, format, type, data);
-}
-
-// Like glUploadTex, but upload a byte array with all elements set to val.
-// If scratch is not NULL, points to a resizeable talloc memory block than can
-// be freely used by the function (for avoiding temporary memory allocations).
-void glClearTex(GL *gl, GLenum target, GLenum format, GLenum type,
- int x, int y, int w, int h, uint8_t val, void **scratch)
-{
- int bpp = glFmt2bpp(format, type);
- int stride = w * bpp;
- int size = h * stride;
- if (size < 1)
- return;
- void *data = scratch ? *scratch : NULL;
- if (talloc_get_size(data) < size)
- data = talloc_realloc(NULL, data, char *, size);
- memset(data, val, size);
- glAdjustAlignment(gl, stride);
- gl->PixelStorei(GL_UNPACK_ROW_LENGTH, w);
- gl->TexSubImage2D(target, 0, x, y, w, h, format, type, data);
- if (scratch) {
- *scratch = data;
- } else {
- talloc_free(data);
- }
-}
-
-/**
- * \brief download a texture, handling things like stride and slices
- * \param target texture target, usually GL_TEXTURE_2D
- * \param format OpenGL format of data
- * \param type OpenGL type of data
- * \param dataptr destination memory for download
- * \param stride data stride (must be positive)
- * \ingroup gltexture
- */
-void glDownloadTex(GL *gl, GLenum target, GLenum format, GLenum type,
- void *dataptr, int stride)
-{
- // this is not always correct, but should work for MPlayer
- glAdjustAlignment(gl, stride);
- gl->PixelStorei(GL_PACK_ROW_LENGTH, stride / glFmt2bpp(format, type));
- gl->GetTexImage(target, 0, format, type, dataptr);
-}
-
-/**
- * \brief Setup ATI version of register combiners for YUV to RGB conversion.
- * \param csp_params parameters used for colorspace conversion
- * \param text if set use the GL_ATI_text_fragment_shader API as
- * used on OS X.
- */
-static void glSetupYUVFragmentATI(GL *gl, struct mp_csp_params *csp_params,
- int text)
-{
- GLint i;
- float yuv2rgb[3][4];
-
- gl->GetIntegerv(GL_MAX_TEXTURE_UNITS, &i);
- if (i < 3)
- mp_msg(MSGT_VO, MSGL_ERR,
- "[gl] 3 texture units needed for YUV combiner (ATI) support (found %i)\n", i);
-
- mp_get_yuv2rgb_coeffs(csp_params, yuv2rgb);
- for (i = 0; i < 3; i++) {
- int j;
- yuv2rgb[i][3] -= -0.5 * (yuv2rgb[i][1] + yuv2rgb[i][2]);
- for (j = 0; j < 4; j++) {
- yuv2rgb[i][j] *= 0.125;
- yuv2rgb[i][j] += 0.5;
- if (yuv2rgb[i][j] > 1)
- yuv2rgb[i][j] = 1;
- if (yuv2rgb[i][j] < 0)
- yuv2rgb[i][j] = 0;
- }
- }
- if (text == 0) {
- GLfloat c0[4] = { yuv2rgb[0][0], yuv2rgb[1][0], yuv2rgb[2][0] };
- GLfloat c1[4] = { yuv2rgb[0][1], yuv2rgb[1][1], yuv2rgb[2][1] };
- GLfloat c2[4] = { yuv2rgb[0][2], yuv2rgb[1][2], yuv2rgb[2][2] };
- GLfloat c3[4] = { yuv2rgb[0][3], yuv2rgb[1][3], yuv2rgb[2][3] };
- if (!gl->BeginFragmentShader || !gl->EndFragmentShader ||
- !gl->SetFragmentShaderConstant || !gl->SampleMap ||
- !gl->ColorFragmentOp2 || !gl->ColorFragmentOp3) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Combiner (ATI) functions missing!\n");
- return;
- }
- gl->GetIntegerv(GL_NUM_FRAGMENT_REGISTERS_ATI, &i);
- if (i < 3)
- mp_msg(MSGT_VO, MSGL_ERR,
- "[gl] 3 registers needed for YUV combiner (ATI) support (found %i)\n", i);
- gl->BeginFragmentShader();
- gl->SetFragmentShaderConstant(GL_CON_0_ATI, c0);
- gl->SetFragmentShaderConstant(GL_CON_1_ATI, c1);
- gl->SetFragmentShaderConstant(GL_CON_2_ATI, c2);
- gl->SetFragmentShaderConstant(GL_CON_3_ATI, c3);
- gl->SampleMap(GL_REG_0_ATI, GL_TEXTURE0, GL_SWIZZLE_STR_ATI);
- gl->SampleMap(GL_REG_1_ATI, GL_TEXTURE1, GL_SWIZZLE_STR_ATI);
- gl->SampleMap(GL_REG_2_ATI, GL_TEXTURE2, GL_SWIZZLE_STR_ATI);
- gl->ColorFragmentOp2(GL_MUL_ATI, GL_REG_1_ATI, GL_NONE, GL_NONE,
- GL_REG_1_ATI, GL_NONE, GL_BIAS_BIT_ATI,
- GL_CON_1_ATI, GL_NONE, GL_BIAS_BIT_ATI);
- gl->ColorFragmentOp3(GL_MAD_ATI, GL_REG_2_ATI, GL_NONE, GL_NONE,
- GL_REG_2_ATI, GL_NONE, GL_BIAS_BIT_ATI,
- GL_CON_2_ATI, GL_NONE, GL_BIAS_BIT_ATI,
- GL_REG_1_ATI, GL_NONE, GL_NONE);
- gl->ColorFragmentOp3(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
- GL_REG_0_ATI, GL_NONE, GL_NONE,
- GL_CON_0_ATI, GL_NONE, GL_BIAS_BIT_ATI,
- GL_REG_2_ATI, GL_NONE, GL_NONE);
- gl->ColorFragmentOp2(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, GL_8X_BIT_ATI,
- GL_REG_0_ATI, GL_NONE, GL_NONE,
- GL_CON_3_ATI, GL_NONE, GL_BIAS_BIT_ATI);
- gl->EndFragmentShader();
- } else {
- static const char template[] =
- "!!ATIfs1.0\n"
- "StartConstants;\n"
- " CONSTANT c0 = {%e, %e, %e};\n"
- " CONSTANT c1 = {%e, %e, %e};\n"
- " CONSTANT c2 = {%e, %e, %e};\n"
- " CONSTANT c3 = {%e, %e, %e};\n"
- "EndConstants;\n"
- "StartOutputPass;\n"
- " SampleMap r0, t0.str;\n"
- " SampleMap r1, t1.str;\n"
- " SampleMap r2, t2.str;\n"
- " MUL r1.rgb, r1.bias, c1.bias;\n"
- " MAD r2.rgb, r2.bias, c2.bias, r1;\n"
- " MAD r0.rgb, r0, c0.bias, r2;\n"
- " ADD r0.rgb.8x, r0, c3.bias;\n"
- "EndPass;\n";
- char buffer[512];
- snprintf(buffer, sizeof(buffer), template,
- yuv2rgb[0][0], yuv2rgb[1][0], yuv2rgb[2][0],
- yuv2rgb[0][1], yuv2rgb[1][1], yuv2rgb[2][1],
- yuv2rgb[0][2], yuv2rgb[1][2], yuv2rgb[2][2],
- yuv2rgb[0][3], yuv2rgb[1][3], yuv2rgb[2][3]);
- mp_msg(MSGT_VO, MSGL_DBG2, "[gl] generated fragment program:\n%s\n",
- buffer);
- loadGPUProgram(gl, GL_TEXT_FRAGMENT_SHADER_ATI, buffer);
- }
-}
-
-// Replace all occurances of variables named "$"+name (e.g. $foo) in *text with
-// replace, and return the result. *text must have been allocated with talloc.
-static void replace_var_str(char **text, const char *name, const char *replace)
-{
- size_t namelen = strlen(name);
- char *nextvar = *text;
- void *parent = talloc_parent(*text);
- for (;;) {
- nextvar = strchr(nextvar, '$');
- if (!nextvar)
- break;
- char *until = nextvar;
- nextvar++;
- if (strncmp(nextvar, name, namelen) != 0)
- continue;
- nextvar += namelen;
- // try not to replace prefixes of other vars (e.g. $foo vs. $foo_bar)
- char term = nextvar[0];
- if (isalnum(term) || term == '_')
- continue;
- int prelength = until - *text;
- int postlength = nextvar - *text;
- char *n = talloc_asprintf(parent, "%.*s%s%s", prelength, *text, replace,
- nextvar);
- talloc_free(*text);
- *text = n;
- nextvar = *text + postlength;
- }
-}
-
-static void replace_var_float(char **text, const char *name, float replace)
-{
- char *s = talloc_asprintf(NULL, "%e", replace);
- replace_var_str(text, name, s);
- talloc_free(s);
-}
-
-static void replace_var_char(char **text, const char *name, char replace)
-{
- char s[2] = { replace, '\0' };
- replace_var_str(text, name, s);
-}
-
-// Append template to *text. Possibly initialize *text if it's NULL.
-static void append_template(char **text, const char* template)
-{
- if (!text)
- *text = talloc_strdup(NULL, template);
- else
- *text = talloc_strdup_append(*text, template);
-}
-
-/**
- * \brief helper function for gen_spline_lookup_tex
- * \param x subpixel-position ((0,1) range) to calculate weights for
- * \param dst where to store transformed weights, must provide space for 4 GLfloats
- *
- * calculates the weights and stores them after appropriate transformation
- * for the scaler fragment program.
- */
-static void store_weights(float x, GLfloat *dst)
-{
- float w0 = (((-1 * x + 3) * x - 3) * x + 1) / 6;
- float w1 = (((3 * x - 6) * x + 0) * x + 4) / 6;
- float w2 = (((-3 * x + 3) * x + 3) * x + 1) / 6;
- float w3 = (((1 * x + 0) * x + 0) * x + 0) / 6;
- *dst++ = 1 + x - w1 / (w0 + w1);
- *dst++ = 1 - x + w3 / (w2 + w3);
- *dst++ = w0 + w1;
- *dst++ = 0;
-}
-
-//! to avoid artefacts this should be rather large
-#define LOOKUP_BSPLINE_RES (2 * 1024)
-/**
- * \brief creates the 1D lookup texture needed for fast higher-order filtering
- * \param unit texture unit to attach texture to
- */
-static void gen_spline_lookup_tex(GL *gl, GLenum unit)
-{
- GLfloat *tex = calloc(4 * LOOKUP_BSPLINE_RES, sizeof(*tex));
- GLfloat *tp = tex;
- int i;
- for (i = 0; i < LOOKUP_BSPLINE_RES; i++) {
- float x = (float)(i + 0.5) / LOOKUP_BSPLINE_RES;
- store_weights(x, tp);
- tp += 4;
- }
- store_weights(0, tex);
- store_weights(1, &tex[4 * (LOOKUP_BSPLINE_RES - 1)]);
- gl->ActiveTexture(unit);
- gl->TexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16, LOOKUP_BSPLINE_RES, 0, GL_RGBA,
- 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 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[] =
- SAMPLE("yuv.$out_comp","fragment.texcoord[$in_tex]","texture[$in_tex]");
-
-#define BICUB_FILT_MAIN \
- /* first y-interpolation */ \
- "ADD coord, fragment.texcoord[$in_tex].xyxy, cdelta.xyxw;\n" \
- "ADD coord2, fragment.texcoord[$in_tex].xyxy, cdelta.zyzw;\n" \
- SAMPLE("a.r","coord.xyxy","texture[$in_tex]") \
- SAMPLE("a.g","coord.zwzw","texture[$in_tex]") \
- /* second y-interpolation */ \
- SAMPLE("b.r","coord2.xyxy","texture[$in_tex]") \
- SAMPLE("b.g","coord2.zwzw","texture[$in_tex]") \
- "LRP a.b, parmy.b, a.rrrr, a.gggg;\n" \
- "LRP a.a, parmy.b, b.rrrr, b.gggg;\n" \
- /* x-interpolation */ \
- "LRP yuv.$out_comp, parmx.b, a.bbbb, a.aaaa;\n"
-
-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"
- "TEX parmy, coord.y, texture[$texs], 1D;\n"
- "MUL cdelta.yw, parmy.rrgg, {0, -$pth, 0, $pth};\n"
- BICUB_FILT_MAIN;
-
-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"
- "TEX parmy, coord.y, texture[$texs], 1D;\n"
- "MUL cdelta.yw, parmy.rrgg, {0, -1, 0, 1};\n"
- BICUB_FILT_MAIN;
-
-#define CALCWEIGHTS(t, s) \
- "MAD "t ", {-0.5, 0.1666, 0.3333, -0.3333}, "s ", {1, 0, -0.5, 0.5};\n" \
- "MAD "t ", "t ", "s ", {0, 0, -0.5, 0.5};\n" \
- "MAD "t ", "t ", "s ", {-0.6666, 0, 0.8333, 0.1666};\n" \
- "RCP a.x, "t ".z;\n" \
- "RCP a.y, "t ".w;\n" \
- "MAD "t ".xy, "t ".xyxy, a.xyxy, {1, 1, 0, 0};\n" \
- "ADD "t ".x, "t ".xxxx, "s ";\n" \
- "SUB "t ".y, "t ".yyyy, "s ";\n"
-
-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")
- "MUL cdelta.xz, parmx.rrgg, {-$ptw, 0, $ptw, 0};\n"
- CALCWEIGHTS("parmy", "coord.yyyy")
- "MUL cdelta.yw, parmy.rrgg, {0, -$pth, 0, $pth};\n"
- BICUB_FILT_MAIN;
-
-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")
- "MUL cdelta.xz, parmx.rrgg, {-1, 0, 1, 0};\n"
- CALCWEIGHTS("parmy", "coord.yyyy")
- "MUL cdelta.yw, parmy.rrgg, {0, -1, 0, 1};\n"
- BICUB_FILT_MAIN;
-
-#define BICUB_X_FILT_MAIN \
- "ADD coord.xy, fragment.texcoord[$in_tex].xyxy, cdelta.xyxy;\n" \
- "ADD coord2.xy, fragment.texcoord[$in_tex].xyxy, cdelta.zyzy;\n" \
- SAMPLE("a.r","coord","texture[$in_tex]") \
- SAMPLE("b.r","coord2","texture[$in_tex]") \
- /* x-interpolation */ \
- "LRP yuv.$out_comp, parmx.b, a.rrrr, b.rrrr;\n"
-
-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[] =
- "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[] =
- "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"
- SAMPLE("a.r","fragment.texcoord[$in_tex]","texture[$in_tex]")
- SAMPLE("b.r","coord.xyxy","texture[$in_tex]")
- SAMPLE("b.g","coord.zwzw","texture[$in_tex]")
- "ADD b.r, b.r, b.g;\n"
- SAMPLE("b.b","coord2.xyxy","texture[$in_tex]")
- SAMPLE("b.g","coord2.zwzw","texture[$in_tex]")
- "DP3 b, b, {0.25, 0.25, 0.25};\n"
- "SUB b.r, a.r, b.r;\n"
- "MAD textemp.r, b.r, {$strength}, a.r;\n"
- "MOV yuv.$out_comp, textemp.r;\n";
-
-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"
- "SUB coord2, fragment.texcoord[$in_tex].xyxy, dcoord$out_comp;\n"
- SAMPLE("a.r","fragment.texcoord[$in_tex]","texture[$in_tex]")
- SAMPLE("b.r","coord.xyxy","texture[$in_tex]")
- SAMPLE("b.g","coord.zwzw","texture[$in_tex]")
- "ADD b.r, b.r, b.g;\n"
- SAMPLE("b.b","coord2.xyxy","texture[$in_tex]")
- SAMPLE("b.g","coord2.zwzw","texture[$in_tex]")
- "ADD b.r, b.r, b.b;\n"
- "ADD b.a, b.r, b.g;\n"
- "ADD coord, fragment.texcoord[$in_tex].xyxy, dcoord2$out_comp;\n"
- "SUB coord2, fragment.texcoord[$in_tex].xyxy, dcoord2$out_comp;\n"
- SAMPLE("b.r","coord.xyxy","texture[$in_tex]")
- SAMPLE("b.g","coord.zwzw","texture[$in_tex]")
- "ADD b.r, b.r, b.g;\n"
- SAMPLE("b.b","coord2.xyxy","texture[$in_tex]")
- SAMPLE("b.g","coord2.zwzw","texture[$in_tex]")
- "DP4 b.r, b, {-0.1171875, -0.1171875, -0.1171875, -0.09765625};\n"
- "MAD b.r, a.r, {0.859375}, b.r;\n"
- "MAD textemp.r, b.r, {$strength}, a.r;\n"
- "MOV yuv.$out_comp, textemp.r;\n";
-
-static const char yuv_prog_template[] =
- "PARAM ycoef = {$cm11, $cm21, $cm31};\n"
- "PARAM ucoef = {$cm12, $cm22, $cm32};\n"
- "PARAM vcoef = {$cm13, $cm23, $cm33};\n"
- "PARAM offsets = {$cm14, $cm24, $cm34};\n"
- "TEMP res;\n"
- "MAD res.rgb, yuv.rrrr, ycoef, offsets;\n"
- "MAD res.rgb, yuv.gggg, ucoef, res;\n"
- "MAD res.rgb, yuv.bbbb, vcoef, res;\n";
-
-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"
- "PARAM offsets = {$cm14, $cm24, $cm34};\n"
- "PARAM gamma = {$gamma_r, $gamma_g, $gamma_b};\n"
- "TEMP res;\n"
- "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 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[] =
- "PARAM ycoef = {$cm11, $cm21, $cm31, 0};\n"
- "PARAM ucoef = {$cm12, $cm22, $cm32, 0};\n"
- "PARAM vcoef = {$cm13, $cm23, $cm33, 0};\n"
- "PARAM offsets = {$cm14, $cm24, $cm34, 0.125};\n"
- "TEMP res;\n"
- "MAD res, yuv.rrrr, ycoef, offsets;\n"
- "MAD res.rgb, yuv.gggg, ucoef, res;\n"
- "MAD res.rgb, yuv.bbbb, vcoef, res;\n"
- "TEX res.r, res.raaa, texture[$conv_tex0], 2D;\n"
- "ADD res.a, res.a, 0.25;\n"
- "TEX res.g, res.gaaa, texture[$conv_tex0], 2D;\n"
- "ADD res.a, res.a, 0.25;\n"
- "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 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
- * \param scaler scaler type to create texture for
- * \param texu contains next free texture unit number
- * \param texs texture unit ids for the scaler are stored in this array
- */
-static void create_scaler_textures(GL *gl, int scaler, int *texu, char *texs)
-{
- switch (scaler) {
- case YUV_SCALER_BILIN:
- case YUV_SCALER_BICUB_NOTEX:
- case YUV_SCALER_UNSHARP:
- case YUV_SCALER_UNSHARP2:
- break;
- case YUV_SCALER_BICUB:
- case YUV_SCALER_BICUB_X:
- texs[0] = (*texu)++;
- gen_spline_lookup_tex(gl, GL_TEXTURE0 + texs[0]);
- texs[0] += '0';
- break;
- default:
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] unknown scaler type %i\n", scaler);
- }
-}
-
-//! resolution of texture for gamma lookup table
-#define LOOKUP_RES 512
-//! resolution for 3D yuv->rgb conversion lookup table
-#define LOOKUP_3DRES 32
-/**
- * \brief creates and initializes helper textures needed for yuv conversion
- * \param params struct containing parameters like brightness, gamma, ...
- * \param texu contains next free texture unit number
- * \param texs texture unit ids for the conversion are stored in this array
- */
-static void create_conv_textures(GL *gl, gl_conversion_params_t *params,
- int *texu, char *texs)
-{
- unsigned char *lookup_data = NULL;
- int conv = YUV_CONVERSION(params->type);
- switch (conv) {
- case YUV_CONVERSION_FRAGMENT:
- case YUV_CONVERSION_FRAGMENT_POW:
- break;
- case YUV_CONVERSION_FRAGMENT_LOOKUP:
- texs[0] = (*texu)++;
- gl->ActiveTexture(GL_TEXTURE0 + texs[0]);
- lookup_data = malloc(4 * LOOKUP_RES);
- mp_gen_gamma_map(lookup_data, LOOKUP_RES, params->csp_params.rgamma);
- mp_gen_gamma_map(&lookup_data[LOOKUP_RES], LOOKUP_RES,
- params->csp_params.ggamma);
- mp_gen_gamma_map(&lookup_data[2 * LOOKUP_RES], LOOKUP_RES,
- params->csp_params.bgamma);
- glCreateClearTex(gl, GL_TEXTURE_2D, GL_LUMINANCE8, GL_LUMINANCE,
- GL_UNSIGNED_BYTE, GL_LINEAR, LOOKUP_RES, 4, 0);
- glUploadTex(gl, GL_TEXTURE_2D, GL_LUMINANCE, GL_UNSIGNED_BYTE,
- lookup_data, LOOKUP_RES, 0, 0, LOOKUP_RES, 4, 0);
- gl->ActiveTexture(GL_TEXTURE0);
- texs[0] += '0';
- break;
- case YUV_CONVERSION_FRAGMENT_LOOKUP3D:
- {
- int sz = LOOKUP_3DRES + 2; // texture size including borders
- if (!gl->TexImage3D) {
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] Missing 3D texture function!\n");
- break;
- }
- texs[0] = (*texu)++;
- gl->ActiveTexture(GL_TEXTURE0 + texs[0]);
- lookup_data = malloc(3 * sz * sz * sz);
- mp_gen_yuv2rgb_map(&params->csp_params, lookup_data, LOOKUP_3DRES);
- glAdjustAlignment(gl, sz);
- gl->PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- gl->TexImage3D(GL_TEXTURE_3D, 0, 3, sz, sz, sz, 1,
- GL_RGB, GL_UNSIGNED_BYTE, lookup_data);
- gl->TexParameterf(GL_TEXTURE_3D, GL_TEXTURE_PRIORITY, 1.0);
- gl->TexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- gl->TexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- gl->TexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);
- gl->ActiveTexture(GL_TEXTURE0);
- texs[0] += '0';
- }
- break;
- default:
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] unknown conversion type %i\n", conv);
- }
- free(lookup_data);
-}
-
-/**
- * \brief adds a scaling texture read at the current fragment program position
- * \param scaler type of scaler to insert
- * \param prog pointer to fragment program so far
- * \param texs array containing the texture unit identifiers for this scaler
- * \param in_tex texture unit the scaler should read from
- * \param out_comp component of the yuv variable the scaler stores the result in
- * \param rect if rectangular (pixel) adressing should be used for in_tex
- * \param texw width of the in_tex texture
- * \param texh height of the in_tex texture
- * \param strength strength of filter effect if the scaler does some kind of filtering
- */
-static void add_scaler(int scaler, char **prog, char *texs,
- char in_tex, char out_comp, int rect, int texw, int texh,
- double strength)
-{
- const char *ttype = rect ? "RECT" : "2D";
- const float ptw = rect ? 1.0 : 1.0 / texw;
- const float pth = rect ? 1.0 : 1.0 / texh;
- switch (scaler) {
- case YUV_SCALER_BILIN:
- append_template(prog, bilin_filt_template);
- break;
- case YUV_SCALER_BICUB:
- if (rect)
- append_template(prog, bicub_filt_template_RECT);
- else
- append_template(prog, bicub_filt_template_2D);
- break;
- case YUV_SCALER_BICUB_X:
- if (rect)
- append_template(prog, bicub_x_filt_template_RECT);
- else
- append_template(prog, bicub_x_filt_template_2D);
- break;
- case YUV_SCALER_BICUB_NOTEX:
- if (rect)
- append_template(prog, bicub_notex_filt_template_RECT);
- else
- append_template(prog, bicub_notex_filt_template_2D);
- break;
- case YUV_SCALER_UNSHARP:
- append_template(prog, unsharp_filt_template);
- break;
- case YUV_SCALER_UNSHARP2:
- append_template(prog, unsharp_filt_template2);
- break;
- }
-
- replace_var_char(prog, "texs", texs[0]);
- replace_var_char(prog, "in_tex", in_tex);
- replace_var_char(prog, "out_comp", out_comp);
- replace_var_str(prog, "tex_type", ttype);
- replace_var_float(prog, "texw", texw);
- replace_var_float(prog, "texh", texh);
- replace_var_float(prog, "ptw", ptw);
- replace_var_float(prog, "pth", pth);
-
- // this is silly, not sure if that couldn't be in the shader source instead
- replace_var_float(prog, "ptw_05", ptw * 0.5);
- replace_var_float(prog, "pth_05", pth * 0.5);
- replace_var_float(prog, "ptw_15", ptw * 1.5);
- replace_var_float(prog, "pth_15", pth * 1.5);
- replace_var_float(prog, "ptw_12", ptw * 1.2);
- replace_var_float(prog, "pth_12", pth * 1.2);
-
- replace_var_float(prog, "strength", strength);
-}
-
-static const struct {
- const char *name;
- GLenum cur;
- GLenum max;
-} progstats[] = {
- {"instructions", 0x88A0, 0x88A1},
- {"native instructions", 0x88A2, 0x88A3},
- {"temporaries", 0x88A4, 0x88A5},
- {"native temporaries", 0x88A6, 0x88A7},
- {"parameters", 0x88A8, 0x88A9},
- {"native parameters", 0x88AA, 0x88AB},
- {"attribs", 0x88AC, 0x88AD},
- {"native attribs", 0x88AE, 0x88AF},
- {"ALU instructions", 0x8805, 0x880B},
- {"TEX instructions", 0x8806, 0x880C},
- {"TEX indirections", 0x8807, 0x880D},
- {"native ALU instructions", 0x8808, 0x880E},
- {"native TEX instructions", 0x8809, 0x880F},
- {"native TEX indirections", 0x880A, 0x8810},
- {NULL, 0, 0}
-};
-
-/**
- * \brief load the specified GPU Program
- * \param target program target to load into, only GL_FRAGMENT_PROGRAM is tested
- * \param prog program string
- * \return 1 on success, 0 otherwise
- */
-int loadGPUProgram(GL *gl, GLenum target, char *prog)
-{
- int i;
- GLint cur = 0, max = 0, err = 0;
- if (!gl->ProgramString) {
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] Missing GPU program function\n");
- return 0;
- }
- gl->ProgramString(target, GL_PROGRAM_FORMAT_ASCII, strlen(prog), prog);
- gl->GetIntegerv(GL_PROGRAM_ERROR_POSITION, &err);
- if (err != -1) {
- mp_msg(MSGT_VO, MSGL_ERR,
- "[gl] Error compiling fragment program, make sure your card supports\n"
- "[gl] GL_ARB_fragment_program (use glxinfo to check).\n"
- "[gl] Error message:\n %s at %.10s\n",
- gl->GetString(GL_PROGRAM_ERROR_STRING), &prog[err]);
- return 0;
- }
- if (!gl->GetProgramivARB || !mp_msg_test(MSGT_VO, MSGL_DBG2))
- return 1;
- mp_msg(MSGT_VO, MSGL_V, "[gl] Program statistics:\n");
- for (i = 0; progstats[i].name; i++) {
- gl->GetProgramivARB(target, progstats[i].cur, &cur);
- gl->GetProgramivARB(target, progstats[i].max, &max);
- mp_msg(MSGT_VO, MSGL_V, "[gl] %s: %i/%i\n", progstats[i].name, cur,
- max);
- }
- return 1;
-}
-
-#define MAX_PROGSZ (1024 * 1024)
-
-/**
- * \brief setup a fragment program that will do YUV->RGB conversion
- * \param parms struct containing parameters like conversion and scaler type,
- * brightness, ...
- */
-static void glSetupYUVFragprog(GL *gl, gl_conversion_params_t *params)
-{
- int type = params->type;
- int texw = params->texw;
- int texh = params->texh;
- int rect = params->target == GL_TEXTURE_RECTANGLE;
- static const char prog_hdr[] =
- "!!ARBfp1.0\n"
- "OPTION ARB_precision_hint_fastest;\n"
- // all scaler variables must go here so they aren't defined
- // multiple times when the same scaler is used more than once
- "TEMP coord, coord2, cdelta, parmx, parmy, a, b, yuv, textemp;\n";
- char *yuv_prog = NULL;
- char **prog = &yuv_prog;
- int cur_texu = 3;
- char lum_scale_texs[1] = {0};
- char chrom_scale_texs[1] = {0};
- 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))
- memcpy(chrom_scale_texs, lum_scale_texs, sizeof(chrom_scale_texs));
- 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,
- "[gl] %i texture units needed for this type of YUV fragment support (found %i)\n",
- cur_texu, i);
- if (!gl->ProgramString) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] ProgramString function missing!\n");
- return;
- }
- append_template(prog, prog_hdr);
- add_scaler(YUV_LUM_SCALER(type), prog, lum_scale_texs,
- '0', 'r', rect, texw, texh, params->filter_strength);
- add_scaler(YUV_CHROM_SCALER(type), prog,
- chrom_scale_texs, '1', 'g', rect, params->chrom_texw,
- params->chrom_texh, params->filter_strength);
- add_scaler(YUV_CHROM_SCALER(type), prog,
- chrom_scale_texs, '2', 'b', rect, params->chrom_texw,
- params->chrom_texh, params->filter_strength);
- mp_get_yuv2rgb_coeffs(&params->csp_params, yuv2rgb);
- switch (YUV_CONVERSION(type)) {
- case YUV_CONVERSION_FRAGMENT:
- append_template(prog, yuv_prog_template);
- break;
- case YUV_CONVERSION_FRAGMENT_POW:
- append_template(prog, yuv_pow_prog_template);
- break;
- case YUV_CONVERSION_FRAGMENT_LOOKUP:
- append_template(prog, yuv_lookup_prog_template);
- break;
- case YUV_CONVERSION_FRAGMENT_LOOKUP3D:
- append_template(prog, yuv_lookup3d_prog_template);
- break;
- default:
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] unknown conversion type %i\n",
- YUV_CONVERSION(type));
- break;
- }
- for (int r = 0; r < 3; r++) {
- for (int c = 0; c < 4; c++) {
- // "cmRC"
- char var[] = { 'c', 'm', '1' + r, '1' + c, '\0' };
- replace_var_float(prog, var, yuv2rgb[r][c]);
- }
- }
- replace_var_float(prog, "gamma_r", (float)1.0 / params->csp_params.rgamma);
- 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);
- talloc_free(yuv_prog);
-}
-
-/**
- * \brief detect the best YUV->RGB conversion method available
- */
-int glAutodetectYUVConversion(GL *gl)
-{
- const char *extensions = gl->GetString(GL_EXTENSIONS);
- if (!extensions || !gl->MultiTexCoord2f)
- return YUV_CONVERSION_NONE;
- if (strstr(extensions, "GL_ARB_fragment_program"))
- return YUV_CONVERSION_FRAGMENT;
- if (strstr(extensions, "GL_ATI_text_fragment_shader"))
- return YUV_CONVERSION_TEXT_FRAGMENT;
- if (strstr(extensions, "GL_ATI_fragment_shader"))
- return YUV_CONVERSION_COMBINERS_ATI;
- return YUV_CONVERSION_NONE;
-}
-
-/**
- * \brief setup YUV->RGB conversion
- * \param parms struct containing parameters like conversion and scaler type,
- * brightness, ...
- * \ingroup glconversion
- */
-void glSetupYUVConversion(GL *gl, gl_conversion_params_t *params)
-{
- if (params->chrom_texw == 0)
- params->chrom_texw = 1;
- if (params->chrom_texh == 0)
- params->chrom_texh = 1;
- switch (YUV_CONVERSION(params->type)) {
- case YUV_CONVERSION_COMBINERS_ATI:
- glSetupYUVFragmentATI(gl, &params->csp_params, 0);
- break;
- case YUV_CONVERSION_TEXT_FRAGMENT:
- glSetupYUVFragmentATI(gl, &params->csp_params, 1);
- break;
- case YUV_CONVERSION_FRAGMENT_LOOKUP:
- case YUV_CONVERSION_FRAGMENT_LOOKUP3D:
- case YUV_CONVERSION_FRAGMENT:
- case YUV_CONVERSION_FRAGMENT_POW:
- glSetupYUVFragprog(gl, params);
- break;
- case YUV_CONVERSION_NONE:
- break;
- default:
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] unknown conversion type %i\n",
- YUV_CONVERSION(params->type));
- }
-}
-
-/**
- * \brief enable the specified YUV conversion
- * \param target texture target for Y, U and V textures (e.g. GL_TEXTURE_2D)
- * \param type type of YUV conversion
- * \ingroup glconversion
- */
-void glEnableYUVConversion(GL *gl, GLenum target, int type)
-{
- switch (YUV_CONVERSION(type)) {
- case YUV_CONVERSION_COMBINERS_ATI:
- gl->ActiveTexture(GL_TEXTURE1);
- gl->Enable(target);
- gl->ActiveTexture(GL_TEXTURE2);
- gl->Enable(target);
- gl->ActiveTexture(GL_TEXTURE0);
- gl->Enable(GL_FRAGMENT_SHADER_ATI);
- break;
- case YUV_CONVERSION_TEXT_FRAGMENT:
- gl->ActiveTexture(GL_TEXTURE1);
- gl->Enable(target);
- gl->ActiveTexture(GL_TEXTURE2);
- gl->Enable(target);
- gl->ActiveTexture(GL_TEXTURE0);
- gl->Enable(GL_TEXT_FRAGMENT_SHADER_ATI);
- break;
- case YUV_CONVERSION_FRAGMENT_LOOKUP3D:
- case YUV_CONVERSION_FRAGMENT_LOOKUP:
- case YUV_CONVERSION_FRAGMENT_POW:
- case YUV_CONVERSION_FRAGMENT:
- case YUV_CONVERSION_NONE:
- gl->Enable(GL_FRAGMENT_PROGRAM);
- break;
- }
-}
-
-/**
- * \brief disable the specified YUV conversion
- * \param target texture target for Y, U and V textures (e.g. GL_TEXTURE_2D)
- * \param type type of YUV conversion
- * \ingroup glconversion
- */
-void glDisableYUVConversion(GL *gl, GLenum target, int type)
-{
- switch (YUV_CONVERSION(type)) {
- case YUV_CONVERSION_COMBINERS_ATI:
- gl->ActiveTexture(GL_TEXTURE1);
- gl->Disable(target);
- gl->ActiveTexture(GL_TEXTURE2);
- gl->Disable(target);
- gl->ActiveTexture(GL_TEXTURE0);
- gl->Disable(GL_FRAGMENT_SHADER_ATI);
- break;
- case YUV_CONVERSION_TEXT_FRAGMENT:
- gl->Disable(GL_TEXT_FRAGMENT_SHADER_ATI);
- // HACK: at least the Mac OS X 10.5 PPC Radeon drivers are broken and
- // without this disable the texture units while the program is still
- // running (10.4 PPC seems to work without this though).
- gl->Flush();
- gl->ActiveTexture(GL_TEXTURE1);
- gl->Disable(target);
- gl->ActiveTexture(GL_TEXTURE2);
- gl->Disable(target);
- gl->ActiveTexture(GL_TEXTURE0);
- break;
- case YUV_CONVERSION_FRAGMENT_LOOKUP3D:
- case YUV_CONVERSION_FRAGMENT_LOOKUP:
- case YUV_CONVERSION_FRAGMENT_POW:
- case YUV_CONVERSION_FRAGMENT:
- case YUV_CONVERSION_NONE:
- gl->Disable(GL_FRAGMENT_PROGRAM);
- break;
- }
-}
-
-void glEnable3DLeft(GL *gl, int type)
-{
- GLint buffer;
- switch (type) {
- case GL_3D_RED_CYAN:
- gl->ColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
- break;
- case GL_3D_GREEN_MAGENTA:
- gl->ColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
- break;
- case GL_3D_QUADBUFFER:
- gl->GetIntegerv(GL_DRAW_BUFFER, &buffer);
- switch (buffer) {
- case GL_FRONT:
- case GL_FRONT_LEFT:
- case GL_FRONT_RIGHT:
- buffer = GL_FRONT_LEFT;
- break;
- case GL_BACK:
- case GL_BACK_LEFT:
- case GL_BACK_RIGHT:
- buffer = GL_BACK_LEFT;
- break;
- }
- gl->DrawBuffer(buffer);
- break;
- }
-}
-
-void glEnable3DRight(GL *gl, int type)
-{
- GLint buffer;
- switch (type) {
- case GL_3D_RED_CYAN:
- gl->ColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE);
- break;
- case GL_3D_GREEN_MAGENTA:
- gl->ColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_FALSE);
- break;
- case GL_3D_QUADBUFFER:
- gl->GetIntegerv(GL_DRAW_BUFFER, &buffer);
- switch (buffer) {
- case GL_FRONT:
- case GL_FRONT_LEFT:
- case GL_FRONT_RIGHT:
- buffer = GL_FRONT_RIGHT;
- break;
- case GL_BACK:
- case GL_BACK_LEFT:
- case GL_BACK_RIGHT:
- buffer = GL_BACK_RIGHT;
- break;
- }
- gl->DrawBuffer(buffer);
- break;
- }
-}
-
-void glDisable3D(GL *gl, int type)
-{
- GLint buffer;
- switch (type) {
- case GL_3D_RED_CYAN:
- case GL_3D_GREEN_MAGENTA:
- gl->ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- break;
- case GL_3D_QUADBUFFER:
- gl->DrawBuffer(GL_BACK);
- gl->GetIntegerv(GL_DRAW_BUFFER, &buffer);
- switch (buffer) {
- case GL_FRONT:
- case GL_FRONT_LEFT:
- case GL_FRONT_RIGHT:
- buffer = GL_FRONT;
- break;
- case GL_BACK:
- case GL_BACK_LEFT:
- case GL_BACK_RIGHT:
- buffer = GL_BACK;
- break;
- }
- gl->DrawBuffer(buffer);
- break;
- }
-}
-
-/**
- * \brief draw a texture part at given 2D coordinates
- * \param x screen top coordinate
- * \param y screen left coordinate
- * \param w screen width coordinate
- * \param h screen height coordinate
- * \param tx texture top coordinate in pixels
- * \param ty texture left coordinate in pixels
- * \param tw texture part width in pixels
- * \param th texture part height in pixels
- * \param sx width of texture in pixels
- * \param sy height of texture in pixels
- * \param rect_tex whether this texture uses texture_rectangle extension
- * \param is_yv12 if != 0, also draw the textures from units 1 and 2,
- * bits 8 - 15 and 16 - 23 specify the x and y scaling of those textures
- * \param flip flip the texture upside down
- * \ingroup gltexture
- */
-void glDrawTex(GL *gl, GLfloat x, GLfloat y, GLfloat w, GLfloat h,
- GLfloat tx, GLfloat ty, GLfloat tw, GLfloat th,
- int sx, int sy, int rect_tex, int is_yv12, int flip)
-{
- int chroma_x_shift = (is_yv12 >> 8) & 31;
- int chroma_y_shift = (is_yv12 >> 16) & 31;
- GLfloat xscale = 1 << chroma_x_shift;
- GLfloat yscale = 1 << chroma_y_shift;
- GLfloat tx2 = tx / xscale, ty2 = ty / yscale, tw2 = tw / xscale, th2 = th / yscale;
- if (!rect_tex) {
- tx /= sx;
- ty /= sy;
- tw /= sx;
- th /= sy;
- tx2 = tx, ty2 = ty, tw2 = tw, th2 = th;
- }
- if (flip) {
- y += h;
- h = -h;
- }
- gl->Begin(GL_QUADS);
- gl->TexCoord2f(tx, ty);
- if (is_yv12) {
- gl->MultiTexCoord2f(GL_TEXTURE1, tx2, ty2);
- gl->MultiTexCoord2f(GL_TEXTURE2, tx2, ty2);
- }
- gl->Vertex2f(x, y);
- gl->TexCoord2f(tx, ty + th);
- if (is_yv12) {
- gl->MultiTexCoord2f(GL_TEXTURE1, tx2, ty2 + th2);
- gl->MultiTexCoord2f(GL_TEXTURE2, tx2, ty2 + th2);
- }
- gl->Vertex2f(x, y + h);
- gl->TexCoord2f(tx + tw, ty + th);
- if (is_yv12) {
- gl->MultiTexCoord2f(GL_TEXTURE1, tx2 + tw2, ty2 + th2);
- gl->MultiTexCoord2f(GL_TEXTURE2, tx2 + tw2, ty2 + th2);
- }
- gl->Vertex2f(x + w, y + h);
- gl->TexCoord2f(tx + tw, ty);
- if (is_yv12) {
- gl->MultiTexCoord2f(GL_TEXTURE1, tx2 + tw2, ty2);
- gl->MultiTexCoord2f(GL_TEXTURE2, tx2 + tw2, ty2);
- }
- gl->Vertex2f(x + w, y);
- gl->End();
-}
-
-mp_image_t *glGetWindowScreenshot(GL *gl)
-{
- GLint vp[4]; //x, y, w, h
- gl->GetIntegerv(GL_VIEWPORT, vp);
- mp_image_t *image = alloc_mpi(vp[2], vp[3], IMGFMT_RGB24);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- gl->PixelStorei(GL_PACK_ALIGNMENT, 0);
- gl->PixelStorei(GL_PACK_ROW_LENGTH, 0);
- gl->ReadBuffer(GL_FRONT);
- //flip image while reading
- for (int y = 0; y < vp[3]; y++) {
- gl->ReadPixels(vp[0], vp[1] + vp[3] - y - 1, vp[2], 1,
- GL_RGB, GL_UNSIGNED_BYTE,
- image->planes[0] + y * image->stride[0]);
- }
- return image;
-}
-
-#ifdef CONFIG_GL_COCOA
-#include "cocoa_common.h"
-
-static bool create_window_cocoa(struct MPGLContext *ctx, uint32_t d_width,
- uint32_t d_height, uint32_t flags, bool gl3)
-{
- int rv = vo_cocoa_create_window(ctx->vo, d_width, d_height, flags, gl3);
- if (rv != 0)
- return false;
-
- getFunctions(ctx->gl, (void *)vo_cocoa_glgetaddr, NULL, gl3);
-
- if (gl3) {
- ctx->depth_r = vo_cocoa_cgl_color_size(ctx->vo);
- ctx->depth_g = vo_cocoa_cgl_color_size(ctx->vo);
- ctx->depth_b = vo_cocoa_cgl_color_size(ctx->vo);
- }
-
- if (!ctx->gl->SwapInterval)
- ctx->gl->SwapInterval = vo_cocoa_swap_interval;
-
- return true;
-}
-
-static bool create_window_cocoa_old(struct MPGLContext *ctx, uint32_t d_width,
- uint32_t d_height, uint32_t flags)
-{
- return create_window_cocoa(ctx, d_width, d_height, flags, false);
-}
-
-static bool create_window_cocoa_gl3(struct MPGLContext *ctx, uint32_t d_width,
- uint32_t d_height, uint32_t flags)
-{
- return create_window_cocoa(ctx, d_width, d_height, flags, true);
-}
-
-static void releaseGlContext_cocoa(MPGLContext *ctx)
-{
-}
-
-static void swapGlBuffers_cocoa(MPGLContext *ctx)
-{
- vo_cocoa_swap_buffers(ctx->vo);
-}
-#endif
-
-#ifdef CONFIG_GL_WIN32
-#include <windows.h>
-#include "w32_common.h"
-
-struct w32_context {
- HGLRC context;
-};
-
-static void *w32gpa(const GLubyte *procName)
-{
- HMODULE oglmod;
- void *res = wglGetProcAddress(procName);
- if (res)
- return res;
- oglmod = GetModuleHandle("opengl32.dll");
- return GetProcAddress(oglmod, procName);
-}
-
-static bool create_window_w32_old(struct MPGLContext *ctx, uint32_t d_width,
- uint32_t d_height, uint32_t flags)
-{
- GL *gl = ctx->gl;
-
- if (!vo_w32_config(ctx->vo, d_width, d_height, flags))
- return false;
-
- struct w32_context *w32_ctx = ctx->priv;
- HGLRC *context = &w32_ctx->context;
-
- if (*context) {
- gl->Finish(); // supposedly to prevent flickering
- return true;
- }
-
- HWND win = ctx->vo->w32->window;
- HDC windc = vo_w32_get_dc(ctx->vo, win);
- bool res = false;
-
- HGLRC new_context = wglCreateContext(windc);
- if (!new_context) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not create GL context!\n");
- goto out;
- }
-
- if (!wglMakeCurrent(windc, new_context)) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not set GL context!\n");
- wglDeleteContext(new_context);
- goto out;
- }
-
- *context = new_context;
-
- getFunctions(ctx->gl, w32gpa, NULL, false);
- res = true;
-
-out:
- vo_w32_release_dc(ctx->vo, win, windc);
- return res;
-}
-
-static bool create_window_w32_gl3(struct MPGLContext *ctx, uint32_t d_width,
- uint32_t d_height, uint32_t flags)
-{
- if (!vo_w32_config(ctx->vo, d_width, d_height, flags))
- return false;
-
- struct w32_context *w32_ctx = ctx->priv;
- HGLRC *context = &w32_ctx->context;
-
- if (*context) // reuse existing context
- return true; // not reusing it breaks gl3!
-
- HWND win = ctx->vo->w32->window;
- HDC windc = vo_w32_get_dc(ctx->vo, win);
- HGLRC new_context = 0;
-
- new_context = wglCreateContext(windc);
- if (!new_context) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not create GL context!\n");
- return false;
- }
-
- // set context
- if (!wglMakeCurrent(windc, new_context)) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not set GL context!\n");
- goto out;
- }
-
- const char *(GLAPIENTRY *wglGetExtensionsStringARB)(HDC hdc)
- = w32gpa((const GLubyte*)"wglGetExtensionsStringARB");
-
- if (!wglGetExtensionsStringARB)
- goto unsupported;
-
- const char *wgl_exts = wglGetExtensionsStringARB(windc);
- if (!strstr(wgl_exts, "WGL_ARB_create_context"))
- goto unsupported;
-
- HGLRC (GLAPIENTRY *wglCreateContextAttribsARB)(HDC hDC, HGLRC hShareContext,
- const int *attribList)
- = w32gpa((const GLubyte*)"wglCreateContextAttribsARB");
-
- if (!wglCreateContextAttribsARB)
- goto unsupported;
-
- int gl_version = ctx->requested_gl_version;
- int attribs[] = {
- WGL_CONTEXT_MAJOR_VERSION_ARB, MPGL_VER_GET_MAJOR(gl_version),
- WGL_CONTEXT_MINOR_VERSION_ARB, MPGL_VER_GET_MINOR(gl_version),
- WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
- WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
- 0
- };
-
- *context = wglCreateContextAttribsARB(windc, 0, attribs);
- if (! *context) {
- // NVidia, instead of ignoring WGL_CONTEXT_FLAGS_ARB, will error out if
- // it's present on pre-3.2 contexts.
- // Remove it from attribs and retry the context creation.
- attribs[6] = attribs[7] = 0;
- *context = wglCreateContextAttribsARB(windc, 0, attribs);
- }
- if (! *context) {
- int err = GetLastError();
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not create an OpenGL 3.x"
- " context: error 0x%x\n", err);
- goto out;
- }
-
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(new_context);
-
- if (!wglMakeCurrent(windc, *context)) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not set GL3 context!\n");
- wglDeleteContext(*context);
- return false;
- }
-
- /* update function pointers */
- getFunctions(ctx->gl, w32gpa, NULL, true);
-
- int pfmt = GetPixelFormat(windc);
- PIXELFORMATDESCRIPTOR pfd;
- if (DescribePixelFormat(windc, pfmt, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) {
- ctx->depth_r = pfd.cRedBits;
- ctx->depth_g = pfd.cGreenBits;
- ctx->depth_b = pfd.cBlueBits;
- }
-
- return true;
-
-unsupported:
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] The current OpenGL implementation does"
- " not support OpenGL 3.x \n");
-out:
- wglDeleteContext(new_context);
- return false;
-}
-
-static void releaseGlContext_w32(MPGLContext *ctx)
-{
- struct w32_context *w32_ctx = ctx->priv;
- HGLRC *context = &w32_ctx->context;
- if (*context) {
- wglMakeCurrent(0, 0);
- wglDeleteContext(*context);
- }
- *context = 0;
-}
-
-static void swapGlBuffers_w32(MPGLContext *ctx)
-{
- HDC vo_hdc = vo_w32_get_dc(ctx->vo, ctx->vo->w32->window);
- SwapBuffers(vo_hdc);
- vo_w32_release_dc(ctx->vo, ctx->vo->w32->window, vo_hdc);
-}
-#endif
-
-#ifdef CONFIG_GL_X11
-#include <X11/Xlib.h>
-#include <GL/glx.h>
-#include "x11_common.h"
-
-struct glx_context {
- XVisualInfo *vinfo;
- GLXContext context;
- GLXFBConfig fbc;
-};
-
-// The GL3/FBC initialization code roughly follows/copies from:
-// http://www.opengl.org/wiki/Tutorial:_OpenGL_3.0_Context_Creation_(GLX)
-// but also uses some of the old code.
-
-static GLXFBConfig select_fb_config(struct vo *vo, const int *attribs)
-{
- int fbcount;
- GLXFBConfig *fbc = glXChooseFBConfig(vo->x11->display, vo->x11->screen,
- attribs, &fbcount);
- if (!fbc)
- return NULL;
-
- // The list in fbc is sorted (so that the first element is the best).
- GLXFBConfig fbconfig = fbc[0];
-
- XFree(fbc);
-
- return fbconfig;
-}
-
-static bool create_glx_window(struct MPGLContext *ctx, uint32_t d_width,
- uint32_t d_height, uint32_t flags)
-{
- struct vo *vo = ctx->vo;
- struct glx_context *glx_ctx = ctx->priv;
-
- if (glx_ctx->context) {
- // GL context and window already exist.
- // Only update window geometry etc.
- Colormap colormap = XCreateColormap(vo->x11->display, vo->x11->rootwin,
- glx_ctx->vinfo->visual, AllocNone);
- vo_x11_create_vo_window(vo, glx_ctx->vinfo, vo->dx, vo->dy, d_width,
- d_height, flags, colormap, "gl");
- XFreeColormap(vo->x11->display, colormap);
- return true;
- }
-
- int glx_major, glx_minor;
-
- // FBConfigs were added in GLX version 1.3.
- if (!glXQueryVersion(vo->x11->display, &glx_major, &glx_minor) ||
- (MPGL_VER(glx_major, glx_minor) < MPGL_VER(1, 3)))
- {
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] GLX version older than 1.3.\n");
- return false;
- }
-
- const int glx_attribs_stereo_value_idx = 1; // index of GLX_STEREO + 1
- int glx_attribs[] = {
- GLX_STEREO, False,
- GLX_X_RENDERABLE, True,
- GLX_RED_SIZE, 1,
- GLX_GREEN_SIZE, 1,
- GLX_BLUE_SIZE, 1,
- GLX_DOUBLEBUFFER, True,
- None
- };
- GLXFBConfig fbc = NULL;
- if (flags & VOFLAG_STEREO) {
- glx_attribs[glx_attribs_stereo_value_idx] = True;
- fbc = select_fb_config(vo, glx_attribs);
- if (!fbc) {
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] Could not find a stereo visual,"
- " 3D will probably not work!\n");
- glx_attribs[glx_attribs_stereo_value_idx] = False;
- }
- }
- if (!fbc)
- fbc = select_fb_config(vo, glx_attribs);
- if (!fbc) {
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] no GLX support present\n");
- return false;
- }
-
- glx_ctx->fbc = fbc;
- glx_ctx->vinfo = glXGetVisualFromFBConfig(vo->x11->display, fbc);
-
- mp_msg(MSGT_VO, MSGL_V, "[gl] GLX chose visual with ID 0x%x\n",
- (int)glx_ctx->vinfo->visualid);
-
- glXGetFBConfigAttrib(vo->x11->display, fbc, GLX_RED_SIZE, &ctx->depth_r);
- glXGetFBConfigAttrib(vo->x11->display, fbc, GLX_GREEN_SIZE, &ctx->depth_g);
- glXGetFBConfigAttrib(vo->x11->display, fbc, GLX_BLUE_SIZE, &ctx->depth_b);
-
- Colormap colormap = XCreateColormap(vo->x11->display, vo->x11->rootwin,
- glx_ctx->vinfo->visual, AllocNone);
- vo_x11_create_vo_window(vo, glx_ctx->vinfo, vo->dx, vo->dy, d_width,
- d_height, flags, colormap, "gl");
- XFreeColormap(vo->x11->display, colormap);
-
- return true;
-}
-
-static bool create_window_x11_old(struct MPGLContext *ctx, uint32_t d_width,
- uint32_t d_height, uint32_t flags)
-{
- struct glx_context *glx_ctx = ctx->priv;
- Display *display = ctx->vo->x11->display;
- struct vo *vo = ctx->vo;
- GL *gl = ctx->gl;
-
- if (!create_glx_window(ctx, d_width, d_height, flags))
- return false;
-
- if (glx_ctx->context)
- return true;
-
- GLXContext new_context = glXCreateContext(display, glx_ctx->vinfo, NULL,
- True);
- if (!new_context) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not create GLX context!\n");
- return false;
- }
-
- if (!glXMakeCurrent(display, ctx->vo->x11->window, new_context)) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not set GLX context!\n");
- glXDestroyContext(display, new_context);
- return false;
- }
-
- void *(*getProcAddress)(const GLubyte *);
- getProcAddress = getdladdr("glXGetProcAddress");
- if (!getProcAddress)
- getProcAddress = getdladdr("glXGetProcAddressARB");
-
- const char *glxstr = "";
- const char *(*glXExtStr)(Display *, int)
- = getdladdr("glXQueryExtensionsString");
- if (glXExtStr)
- glxstr = glXExtStr(display, ctx->vo->x11->screen);
-
- getFunctions(gl, getProcAddress, glxstr, false);
- if (!gl->GenPrograms && gl->GetString &&
- gl->version < MPGL_VER(3, 0) &&
- getProcAddress &&
- strstr(gl->GetString(GL_EXTENSIONS), "GL_ARB_vertex_program"))
- {
- mp_msg(MSGT_VO, MSGL_WARN,
- "Broken glXGetProcAddress detected, trying workaround\n");
- getFunctions(gl, NULL, glxstr, false);
- }
-
- glx_ctx->context = new_context;
-
- if (!glXIsDirect(vo->x11->display, new_context))
- ctx->gl->mpgl_caps &= ~MPGL_CAP_NO_SW;
-
- return true;
-}
-
-typedef GLXContext (*glXCreateContextAttribsARBProc)
- (Display*, GLXFBConfig, GLXContext, Bool, const int*);
-
-static bool create_window_x11_gl3(struct MPGLContext *ctx, uint32_t d_width,
- uint32_t d_height, uint32_t flags)
-{
- struct glx_context *glx_ctx = ctx->priv;
- struct vo *vo = ctx->vo;
-
- if (!create_glx_window(ctx, d_width, d_height, flags))
- return false;
-
- if (glx_ctx->context)
- return true;
-
- glXCreateContextAttribsARBProc glXCreateContextAttribsARB =
- (glXCreateContextAttribsARBProc)
- glXGetProcAddressARB((const GLubyte *)"glXCreateContextAttribsARB");
-
- const char *glxstr = "";
- const char *(*glXExtStr)(Display *, int)
- = getdladdr("glXQueryExtensionsString");
- if (glXExtStr)
- glxstr = glXExtStr(vo->x11->display, vo->x11->screen);
- bool have_ctx_ext = glxstr && !!strstr(glxstr, "GLX_ARB_create_context");
-
- if (!(have_ctx_ext && glXCreateContextAttribsARB)) {
- return false;
- }
-
- int gl_version = ctx->requested_gl_version;
- int context_attribs[] = {
- GLX_CONTEXT_MAJOR_VERSION_ARB, MPGL_VER_GET_MAJOR(gl_version),
- GLX_CONTEXT_MINOR_VERSION_ARB, MPGL_VER_GET_MINOR(gl_version),
- GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
- GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
- | (flags & VOFLAG_GL_DEBUG ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
- None
- };
- GLXContext context = glXCreateContextAttribsARB(vo->x11->display,
- glx_ctx->fbc, 0, True,
- context_attribs);
- if (!context) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not create GLX context!\n");
- return false;
- }
-
- // set context
- if (!glXMakeCurrent(vo->x11->display, vo->x11->window, context)) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not set GLX context!\n");
- glXDestroyContext(vo->x11->display, context);
- return false;
- }
-
- glx_ctx->context = context;
-
- getFunctions(ctx->gl, (void *)glXGetProcAddress, glxstr, true);
-
- if (!glXIsDirect(vo->x11->display, context))
- ctx->gl->mpgl_caps &= ~MPGL_CAP_NO_SW;
-
- return true;
-}
-
-/**
- * \brief free the VisualInfo and GLXContext of an OpenGL context.
- * \ingroup glcontext
- */
-static void releaseGlContext_x11(MPGLContext *ctx)
-{
- struct glx_context *glx_ctx = ctx->priv;
- XVisualInfo **vinfo = &glx_ctx->vinfo;
- GLXContext *context = &glx_ctx->context;
- Display *display = ctx->vo->x11->display;
- GL *gl = ctx->gl;
- if (*vinfo)
- XFree(*vinfo);
- *vinfo = NULL;
- if (*context) {
- if (gl->Finish)
- gl->Finish();
- glXMakeCurrent(display, None, NULL);
- glXDestroyContext(display, *context);
- }
- *context = 0;
-}
-
-static void swapGlBuffers_x11(MPGLContext *ctx)
-{
- glXSwapBuffers(ctx->vo->x11->display, ctx->vo->x11->window);
-}
-#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},
- // 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},
-
- {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 *mpgl_init(enum MPGLType type, struct vo *vo)
-{
- MPGLContext *ctx;
- if (type == GLTYPE_AUTO) {
- ctx = mpgl_init(GLTYPE_COCOA, vo);
- if (ctx)
- return ctx;
- ctx = mpgl_init(GLTYPE_W32, vo);
- if (ctx)
- return ctx;
- return mpgl_init(GLTYPE_X11, vo);
- }
- ctx = talloc_zero(NULL, MPGLContext);
- *ctx = (MPGLContext) {
- .gl = talloc_zero(ctx, GL),
- .type = type,
- .vo = vo,
- .requested_gl_version = MPGL_VER(3, 0),
- .vo_init_ok = true,
- };
- switch (ctx->type) {
-#ifdef CONFIG_GL_COCOA
- case GLTYPE_COCOA:
- ctx->create_window_old = create_window_cocoa_old;
- ctx->create_window_gl3 = create_window_cocoa_gl3;
- ctx->releaseGlContext = releaseGlContext_cocoa;
- ctx->swapGlBuffers = swapGlBuffers_cocoa;
- ctx->check_events = vo_cocoa_check_events;
- ctx->update_xinerama_info = vo_cocoa_update_xinerama_info;
- ctx->fullscreen = vo_cocoa_fullscreen;
- ctx->ontop = vo_cocoa_ontop;
- ctx->vo_init = vo_cocoa_init;
- ctx->pause = vo_cocoa_pause;
- ctx->resume = vo_cocoa_resume;
- ctx->vo_uninit = vo_cocoa_uninit;
- break;
-#endif
-#ifdef CONFIG_GL_WIN32
- case GLTYPE_W32:
- ctx->priv = talloc_zero(ctx, struct w32_context);
- ctx->create_window_old = create_window_w32_old;
- ctx->create_window_gl3 = create_window_w32_gl3;
- ctx->releaseGlContext = releaseGlContext_w32;
- ctx->swapGlBuffers = swapGlBuffers_w32;
- ctx->update_xinerama_info = w32_update_xinerama_info;
- ctx->border = vo_w32_border;
- ctx->check_events = vo_w32_check_events;
- ctx->fullscreen = vo_w32_fullscreen;
- ctx->ontop = vo_w32_ontop;
- ctx->vo_init = vo_w32_init;
- ctx->vo_uninit = vo_w32_uninit;
- break;
-#endif
-#ifdef CONFIG_GL_X11
- case GLTYPE_X11:
- ctx->priv = talloc_zero(ctx, struct glx_context);
- ctx->create_window_old = create_window_x11_old;
- ctx->create_window_gl3 = create_window_x11_gl3;
- ctx->releaseGlContext = releaseGlContext_x11;
- ctx->swapGlBuffers = swapGlBuffers_x11;
- ctx->update_xinerama_info = update_xinerama_info;
- ctx->border = vo_x11_border;
- ctx->check_events = vo_x11_check_events;
- ctx->fullscreen = vo_x11_fullscreen;
- ctx->ontop = vo_x11_ontop;
- ctx->vo_init = vo_init;
- ctx->vo_uninit = vo_x11_uninit;
- break;
-#endif
- }
- if (ctx->vo_init && ctx->vo_init(vo))
- return ctx;
- talloc_free(ctx);
- return NULL;
-}
-
-bool mpgl_destroy_window(struct MPGLContext *ctx)
-{
- ctx->releaseGlContext(ctx);
- *ctx->gl = (GL) {0};
- // This is a caveat. At least on X11, this will recreate the X display
- // connection. Also, if vo_init() fails, unspecified things will happen.
- ctx->vo_uninit(ctx->vo);
- ctx->vo_init_ok = ctx->vo_init(ctx->vo);
- return ctx->vo_init_ok;
-}
-
-static bool create_window(struct MPGLContext *ctx, int gl_caps,
- bool (*create)(struct MPGLContext *, uint32_t,
- uint32_t, uint32_t),
- uint32_t d_width, uint32_t d_height, uint32_t flags)
-{
- if (!create || !ctx->vo_init_ok)
- return false;
- if (create(ctx, d_width, d_height, flags)) {
- int missing = (ctx->gl->mpgl_caps & gl_caps) ^ gl_caps;
- if (!missing) {
- ctx->selected_create_window = create;
- return true;
- }
- mp_msg(MSGT_VO, MSGL_WARN, "[gl] Missing OpenGL features:");
- list_features(missing, MSGL_WARN, false);
- if (missing & MPGL_CAP_NO_SW) {
- mp_msg(MSGT_VO, MSGL_WARN, "[gl] Rejecting suspected software "
- "OpenGL renderer.\n");
- }
- }
- // If we tried to create a GL 3 context, and we're going to create a legacy
- // context after this, the window should be recreated at least on X11.
- mpgl_destroy_window(ctx);
- return false;
-}
-
-bool mpgl_create_window(struct MPGLContext *ctx, int gl_caps, uint32_t d_width,
- uint32_t d_height, uint32_t flags)
-{
- assert(ctx->vo_init_ok);
- if (ctx->selected_create_window)
- return ctx->selected_create_window(ctx, d_width, d_height, flags);
-
- bool allow_gl3 = !(gl_caps & MPGL_CAP_GL_LEGACY);
- bool allow_legacy = !(gl_caps & MPGL_CAP_GL3);
- gl_caps |= MPGL_CAP_GL;
-
- if (allow_gl3 && create_window(ctx, gl_caps, ctx->create_window_gl3,
- d_width, d_height, flags))
- return true;
-
- if (allow_legacy && create_window(ctx, gl_caps, ctx->create_window_old,
- d_width, d_height, flags))
- return true;
-
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] OpenGL context creation failed!\n");
- return false;
-}
-
-void mpgl_uninit(MPGLContext *ctx)
-{
- if (!ctx)
- return;
- if (ctx->vo_init_ok) {
- ctx->releaseGlContext(ctx);
- ctx->vo_uninit(ctx->vo);
- }
- talloc_free(ctx);
-}
-
-void mp_log_source(int mod, int lev, const char *src)
-{
- int line = 1;
- if (!src)
- return;
- while (*src) {
- const char *end = strchr(src, '\n');
- const char *next = end + 1;
- if (!end)
- next = end = src + strlen(src);
- mp_msg(mod, lev, "[%3d] %.*s\n", line, (int)(end - src), src);
- line++;
- src = next;
- }
-}
diff --git a/libvo/gl_common.h b/libvo/gl_common.h
deleted file mode 100644
index 9816566097..0000000000
--- a/libvo/gl_common.h
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * You can alternatively redistribute this file and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- */
-
-#ifndef MPLAYER_GL_COMMON_H
-#define MPLAYER_GL_COMMON_H
-
-#include <stdio.h>
-#include <stdint.h>
-
-#include "config.h"
-#include "mp_msg.h"
-
-#include "video_out.h"
-#include "csputils.h"
-
-#include "libmpcodecs/mp_image.h"
-
-#if defined(CONFIG_GL_COCOA) && !defined(CONFIG_GL_X11)
-#ifdef GL_VERSION_3_0
-#include <OpenGL/gl3.h>
-#else
-#include <OpenGL/gl.h>
-#endif
-#include <OpenGL/glext.h>
-#else
-#include <GL/gl.h>
-#include <GL/glext.h>
-#endif
-
-#include "libvo/gl_header_fixes.h"
-
-struct GL;
-typedef struct GL GL;
-
-void glAdjustAlignment(GL *gl, int stride);
-
-int glFindFormat(uint32_t format, int have_texture_rg, int *bpp,
- GLint *gl_texfmt, GLenum *gl_format, GLenum *gl_type);
-int glFmt2bpp(GLenum format, GLenum type);
-void glCreateClearTex(GL *gl, GLenum target, GLenum fmt, GLenum format,
- GLenum type, GLint filter, int w, int h,
- unsigned char val);
-int glCreatePPMTex(GL *gl, GLenum target, GLenum fmt, GLint filter,
- FILE *f, int *width, int *height, int *maxval);
-void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type,
- const void *dataptr, int stride,
- int x, int y, int w, int h, int slice);
-void glClearTex(GL *gl, GLenum target, GLenum format, GLenum type,
- int x, int y, int w, int h, uint8_t val, void **scratch);
-void glDownloadTex(GL *gl, GLenum target, GLenum format, GLenum type,
- void *dataptr, int stride);
-void glDrawTex(GL *gl, GLfloat x, GLfloat y, GLfloat w, GLfloat h,
- GLfloat tx, GLfloat ty, GLfloat tw, GLfloat th,
- int sx, int sy, int rect_tex, int is_yv12, int flip);
-int loadGPUProgram(GL *gl, GLenum target, char *prog);
-void glCheckError(GL *gl, const char *info);
-mp_image_t *glGetWindowScreenshot(GL *gl);
-
-/** \addtogroup glconversion
- * \{ */
-//! do not use YUV conversion, this should always stay 0
-#define YUV_CONVERSION_NONE 0
-//! use nVidia specific register combiners for YUV conversion
-//! implementation has been removed
-#define YUV_CONVERSION_COMBINERS 1
-//! use a fragment program for YUV conversion
-#define YUV_CONVERSION_FRAGMENT 2
-//! use a fragment program for YUV conversion with gamma using POW
-#define YUV_CONVERSION_FRAGMENT_POW 3
-//! use a fragment program with additional table lookup for YUV conversion
-#define YUV_CONVERSION_FRAGMENT_LOOKUP 4
-//! use ATI specific register combiners ("fragment program")
-#define YUV_CONVERSION_COMBINERS_ATI 5
-//! use a fragment program with 3D table lookup for YUV conversion
-#define YUV_CONVERSION_FRAGMENT_LOOKUP3D 6
-//! use ATI specific "text" register combiners ("fragment program")
-#define YUV_CONVERSION_TEXT_FRAGMENT 7
-//! use normal bilinear scaling for textures
-#define YUV_SCALER_BILIN 0
-//! use higher quality bicubic scaling for textures
-#define YUV_SCALER_BICUB 1
-//! use cubic scaling in X and normal linear scaling in Y direction
-#define YUV_SCALER_BICUB_X 2
-//! use cubic scaling without additional lookup texture
-#define YUV_SCALER_BICUB_NOTEX 3
-#define YUV_SCALER_UNSHARP 4
-#define YUV_SCALER_UNSHARP2 5
-//! mask for conversion type
-#define YUV_CONVERSION_MASK 0xF
-//! mask for scaler type
-#define YUV_SCALER_MASK 0xF
-//! shift value for luminance scaler type
-#define YUV_LUM_SCALER_SHIFT 8
-//! shift value for chrominance scaler type
-#define YUV_CHROM_SCALER_SHIFT 12
-//! extract conversion out of type
-#define YUV_CONVERSION(t) ((t) & YUV_CONVERSION_MASK)
-//! extract luminance scaler out of type
-#define YUV_LUM_SCALER(t) (((t) >> YUV_LUM_SCALER_SHIFT) & YUV_SCALER_MASK)
-//! extract chrominance scaler out of type
-#define YUV_CHROM_SCALER(t) (((t) >> YUV_CHROM_SCALER_SHIFT) & YUV_SCALER_MASK)
-#define SET_YUV_CONVERSION(c) ((c) & YUV_CONVERSION_MASK)
-#define SET_YUV_LUM_SCALER(s) (((s) & YUV_SCALER_MASK) << YUV_LUM_SCALER_SHIFT)
-#define SET_YUV_CHROM_SCALER(s) (((s) & YUV_SCALER_MASK) << YUV_CHROM_SCALER_SHIFT)
-//! returns whether the yuv conversion supports large brightness range etc.
-static inline int glYUVLargeRange(int conv)
-{
- switch (conv) {
- case YUV_CONVERSION_NONE:
- case YUV_CONVERSION_COMBINERS_ATI:
- case YUV_CONVERSION_FRAGMENT_LOOKUP3D:
- case YUV_CONVERSION_TEXT_FRAGMENT:
- return 0;
- }
- return 1;
-}
-/** \} */
-
-typedef struct {
- GLenum target;
- int type;
- struct mp_csp_params csp_params;
- int texw;
- int texh;
- int chrom_texw;
- int chrom_texh;
- float filter_strength;
- float noise_strength;
-} gl_conversion_params_t;
-
-int glAutodetectYUVConversion(GL *gl);
-void glSetupYUVConversion(GL *gl, gl_conversion_params_t *params);
-void glEnableYUVConversion(GL *gl, GLenum target, int type);
-void glDisableYUVConversion(GL *gl, GLenum target, int type);
-
-#define GL_3D_RED_CYAN 1
-#define GL_3D_GREEN_MAGENTA 2
-#define GL_3D_QUADBUFFER 3
-
-void glEnable3DLeft(GL *gl, int type);
-void glEnable3DRight(GL *gl, int type);
-void glDisable3D(GL *gl, int type);
-
-enum MPGLType {
- GLTYPE_AUTO,
- GLTYPE_COCOA,
- GLTYPE_W32,
- GLTYPE_X11,
-};
-
-enum {
- 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;
-
- // Bit size of each component in the created framebuffer. 0 if unknown.
- int depth_r, depth_g, depth_b;
-
- // 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);
- 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 (*pause)(struct vo *vo);
- void (*resume)(struct vo *vo);
- 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 *mpgl_init(enum MPGLType type, struct vo *vo);
-void mpgl_uninit(MPGLContext *ctx);
-
-// 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()
-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);
- void (GLAPIENTRY *MatrixMode)(GLenum);
- void (GLAPIENTRY *LoadIdentity)(void);
- void (GLAPIENTRY *Translated)(double, double, double);
- void (GLAPIENTRY *Scaled)(double, double, double);
- void (GLAPIENTRY *Ortho)(double, double, double, double, double,double);
- void (GLAPIENTRY *PushMatrix)(void);
- void (GLAPIENTRY *PopMatrix)(void);
- void (GLAPIENTRY *Clear)(GLbitfield);
- GLuint (GLAPIENTRY *GenLists)(GLsizei);
- void (GLAPIENTRY *DeleteLists)(GLuint, GLsizei);
- void (GLAPIENTRY *NewList)(GLuint, GLenum);
- void (GLAPIENTRY *EndList)(void);
- void (GLAPIENTRY *CallList)(GLuint);
- void (GLAPIENTRY *CallLists)(GLsizei, GLenum, const GLvoid *);
- void (GLAPIENTRY *GenTextures)(GLsizei, GLuint *);
- void (GLAPIENTRY *DeleteTextures)(GLsizei, const GLuint *);
- void (GLAPIENTRY *TexEnvi)(GLenum, GLenum, GLint);
- void (GLAPIENTRY *Color4ub)(GLubyte, GLubyte, GLubyte, GLubyte);
- void (GLAPIENTRY *Color4f)(GLfloat, GLfloat, GLfloat, GLfloat);
- void (GLAPIENTRY *ClearColor)(GLclampf, GLclampf, GLclampf, GLclampf);
- void (GLAPIENTRY *Enable)(GLenum);
- void (GLAPIENTRY *Disable)(GLenum);
- const GLubyte *(GLAPIENTRY * GetString)(GLenum);
- void (GLAPIENTRY *DrawBuffer)(GLenum);
- void (GLAPIENTRY *DepthMask)(GLboolean);
- void (GLAPIENTRY *BlendFunc)(GLenum, GLenum);
- void (GLAPIENTRY *Flush)(void);
- void (GLAPIENTRY *Finish)(void);
- void (GLAPIENTRY *PixelStorei)(GLenum, GLint);
- void (GLAPIENTRY *TexImage1D)(GLenum, GLint, GLint, GLsizei, GLint,
- GLenum, GLenum, const GLvoid *);
- void (GLAPIENTRY *TexImage2D)(GLenum, GLint, GLint, GLsizei, GLsizei,
- GLint, GLenum, GLenum, const GLvoid *);
- void (GLAPIENTRY *TexSubImage2D)(GLenum, GLint, GLint, GLint,
- GLsizei, GLsizei, GLenum, GLenum,
- const GLvoid *);
- void (GLAPIENTRY *GetTexImage)(GLenum, GLint, GLenum, GLenum, GLvoid *);
- void (GLAPIENTRY *TexParameteri)(GLenum, GLenum, GLint);
- void (GLAPIENTRY *TexParameterf)(GLenum, GLenum, GLfloat);
- void (GLAPIENTRY *TexParameterfv)(GLenum, GLenum, const GLfloat *);
- void (GLAPIENTRY *TexCoord2f)(GLfloat, GLfloat);
- void (GLAPIENTRY *TexCoord2fv)(const GLfloat *);
- void (GLAPIENTRY *Vertex2f)(GLfloat, GLfloat);
- void (GLAPIENTRY *GetIntegerv)(GLenum, GLint *);
- void (GLAPIENTRY *GetBooleanv)(GLenum, GLboolean *);
- void (GLAPIENTRY *ColorMask)(GLboolean, GLboolean, GLboolean, GLboolean);
- 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);
- GLenum (GLAPIENTRY *GetError)(void);
-
- void (GLAPIENTRY *GenBuffers)(GLsizei, GLuint *);
- void (GLAPIENTRY *DeleteBuffers)(GLsizei, const GLuint *);
- void (GLAPIENTRY *BindBuffer)(GLenum, GLuint);
- GLvoid * (GLAPIENTRY * MapBuffer)(GLenum, GLenum);
- GLboolean (GLAPIENTRY *UnmapBuffer)(GLenum);
- void (GLAPIENTRY *BufferData)(GLenum, intptr_t, const GLvoid *, GLenum);
- void (GLAPIENTRY *ActiveTexture)(GLenum);
- void (GLAPIENTRY *BindTexture)(GLenum, GLuint);
- void (GLAPIENTRY *MultiTexCoord2f)(GLenum, GLfloat, GLfloat);
- void (GLAPIENTRY *GenPrograms)(GLsizei, GLuint *);
- void (GLAPIENTRY *DeletePrograms)(GLsizei, const GLuint *);
- void (GLAPIENTRY *BindProgram)(GLenum, GLuint);
- void (GLAPIENTRY *ProgramString)(GLenum, GLenum, GLsizei, const GLvoid *);
- void (GLAPIENTRY *GetProgramivARB)(GLenum, GLenum, GLint *);
- void (GLAPIENTRY *ProgramEnvParameter4f)(GLenum, GLuint, GLfloat, GLfloat,
- GLfloat, GLfloat);
- int (GLAPIENTRY *SwapInterval)(int);
- void (GLAPIENTRY *TexImage3D)(GLenum, GLint, GLenum, GLsizei, GLsizei,
- GLsizei, GLint, GLenum, GLenum,
- const GLvoid *);
-
- void (GLAPIENTRY *BeginFragmentShader)(void);
- void (GLAPIENTRY *EndFragmentShader)(void);
- void (GLAPIENTRY *SampleMap)(GLuint, GLuint, GLenum);
- void (GLAPIENTRY *ColorFragmentOp2)(GLenum, GLuint, GLuint, GLuint, GLuint,
- GLuint, GLuint, GLuint, GLuint, GLuint);
- void (GLAPIENTRY *ColorFragmentOp3)(GLenum, GLuint, GLuint, GLuint, GLuint,
- GLuint, GLuint, GLuint, GLuint, GLuint,
- GLuint, GLuint, GLuint);
- void (GLAPIENTRY *SetFragmentShaderConstant)(GLuint, const GLfloat *);
-
- void (GLAPIENTRY *GenVertexArrays)(GLsizei, GLuint *);
- void (GLAPIENTRY *BindVertexArray)(GLuint);
- GLint (GLAPIENTRY *GetAttribLocation)(GLuint, const GLchar *);
- void (GLAPIENTRY *EnableVertexAttribArray)(GLuint);
- void (GLAPIENTRY *DisableVertexAttribArray)(GLuint);
- void (GLAPIENTRY *VertexAttribPointer)(GLuint, GLint, GLenum, GLboolean,
- GLsizei, const GLvoid *);
- void (GLAPIENTRY *DeleteVertexArrays)(GLsizei, const GLuint *);
- void (GLAPIENTRY *UseProgram)(GLuint);
- GLint (GLAPIENTRY *GetUniformLocation)(GLuint, const GLchar *);
- void (GLAPIENTRY *CompileShader)(GLuint);
- GLuint (GLAPIENTRY *CreateProgram)(void);
- GLuint (GLAPIENTRY *CreateShader)(GLenum);
- void (GLAPIENTRY *ShaderSource)(GLuint, GLsizei, const GLchar **,
- const GLint *);
- void (GLAPIENTRY *LinkProgram)(GLuint);
- void (GLAPIENTRY *AttachShader)(GLuint, GLuint);
- void (GLAPIENTRY *DeleteShader)(GLuint);
- void (GLAPIENTRY *DeleteProgram)(GLuint);
- void (GLAPIENTRY *GetShaderInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *);
- void (GLAPIENTRY *GetShaderiv)(GLuint, GLenum, GLint *);
- void (GLAPIENTRY *GetProgramInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *);
- void (GLAPIENTRY *GetProgramiv)(GLenum, GLenum, GLint *);
- const GLubyte* (GLAPIENTRY *GetStringi)(GLenum, GLuint);
- void (GLAPIENTRY *BindAttribLocation)(GLuint, GLuint, const GLchar *);
- void (GLAPIENTRY *BindFramebuffer)(GLenum, GLuint);
- void (GLAPIENTRY *GenFramebuffers)(GLsizei, GLuint *);
- void (GLAPIENTRY *DeleteFramebuffers)(GLsizei, const GLuint *);
- GLenum (GLAPIENTRY *CheckFramebufferStatus)(GLenum);
- void (GLAPIENTRY *FramebufferTexture2D)(GLenum, GLenum, GLenum, GLuint,
- GLint);
-
- void (GLAPIENTRY *Uniform1f)(GLint, GLfloat);
- void (GLAPIENTRY *Uniform2f)(GLint, GLfloat, GLfloat);
- void (GLAPIENTRY *Uniform3f)(GLint, GLfloat, GLfloat, GLfloat);
- void (GLAPIENTRY *Uniform4f)(GLint, GLfloat, GLfloat, GLfloat, GLfloat);
- void (GLAPIENTRY *Uniform1i)(GLint, GLint);
- void (GLAPIENTRY *UniformMatrix3fv)(GLint, GLsizei, GLboolean,
- const GLfloat *);
- void (GLAPIENTRY *UniformMatrix4x3fv)(GLint, GLsizei, GLboolean,
- const GLfloat *);
-};
-
-#endif /* MPLAYER_GL_COMMON_H */
diff --git a/libvo/gl_header_fixes.h b/libvo/gl_header_fixes.h
deleted file mode 100644
index d149a9970a..0000000000
--- a/libvo/gl_header_fixes.h
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * You can alternatively redistribute this file and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- */
-
-// workaround for some gl.h headers
-#ifndef GLAPIENTRY
-#ifdef APIENTRY
-#define GLAPIENTRY APIENTRY
-#elif defined(CONFIG_GL_WIN32)
-#define GLAPIENTRY __stdcall
-#else
-#define GLAPIENTRY
-#endif
-#endif
-
-/**
- * \defgroup glextdefines OpenGL extension defines
- *
- * conditionally define all extension defines used.
- * vendor specific extensions should be marked as such
- * (e.g. _NV), _ARB is not used to ease readability.
- * \{
- */
-#ifndef GL_TEXTURE_3D
-#define GL_TEXTURE_3D 0x806F
-#endif
-#ifndef GL_TEXTURE_WRAP_R
-#define GL_TEXTURE_WRAP_R 0x8072
-#endif
-#ifndef GL_CLAMP_TO_EDGE
-#define GL_CLAMP_TO_EDGE 0x812F
-#endif
-#ifndef GL_GENERATE_MIPMAP
-#define GL_GENERATE_MIPMAP 0x8191
-#endif
-#ifndef GL_TEXT_FRAGMENT_SHADER_ATI
-#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200
-#endif
-#ifndef GL_FRAGMENT_SHADER_ATI
-#define GL_FRAGMENT_SHADER_ATI 0x8920
-#endif
-#ifndef GL_NUM_FRAGMENT_REGISTERS_ATI
-#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E
-#endif
-#ifndef GL_REG_0_ATI
-#define GL_REG_0_ATI 0x8921
-#endif
-#ifndef GL_REG_1_ATI
-#define GL_REG_1_ATI 0x8922
-#endif
-#ifndef GL_REG_2_ATI
-#define GL_REG_2_ATI 0x8923
-#endif
-#ifndef GL_CON_0_ATI
-#define GL_CON_0_ATI 0x8941
-#endif
-#ifndef GL_CON_1_ATI
-#define GL_CON_1_ATI 0x8942
-#endif
-#ifndef GL_CON_2_ATI
-#define GL_CON_2_ATI 0x8943
-#endif
-#ifndef GL_CON_3_ATI
-#define GL_CON_3_ATI 0x8944
-#endif
-#ifndef GL_ADD_ATI
-#define GL_ADD_ATI 0x8963
-#endif
-#ifndef GL_MUL_ATI
-#define GL_MUL_ATI 0x8964
-#endif
-#ifndef GL_MAD_ATI
-#define GL_MAD_ATI 0x8968
-#endif
-#ifndef GL_SWIZZLE_STR_ATI
-#define GL_SWIZZLE_STR_ATI 0x8976
-#endif
-#ifndef GL_4X_BIT_ATI
-#define GL_4X_BIT_ATI 2
-#endif
-#ifndef GL_8X_BIT_ATI
-#define GL_8X_BIT_ATI 4
-#endif
-#ifndef GL_BIAS_BIT_ATI
-#define GL_BIAS_BIT_ATI 8
-#endif
-#ifndef GL_MAX_TEXTURE_UNITS
-#define GL_MAX_TEXTURE_UNITS 0x84E2
-#endif
-#ifndef GL_TEXTURE0
-#define GL_TEXTURE0 0x84C0
-#endif
-#ifndef GL_TEXTURE1
-#define GL_TEXTURE1 0x84C1
-#endif
-#ifndef GL_TEXTURE2
-#define GL_TEXTURE2 0x84C2
-#endif
-#ifndef GL_TEXTURE3
-#define GL_TEXTURE3 0x84C3
-#endif
-#ifndef GL_TEXTURE_RECTANGLE
-#define GL_TEXTURE_RECTANGLE 0x84F5
-#endif
-#ifndef GL_PIXEL_UNPACK_BUFFER
-#define GL_PIXEL_UNPACK_BUFFER 0x88EC
-#endif
-#ifndef GL_STREAM_DRAW
-#define GL_STREAM_DRAW 0x88E0
-#endif
-#ifndef GL_DYNAMIC_DRAW
-#define GL_DYNAMIC_DRAW 0x88E8
-#endif
-#ifndef GL_WRITE_ONLY
-#define GL_WRITE_ONLY 0x88B9
-#endif
-#ifndef GL_BGR
-#define GL_BGR 0x80E0
-#endif
-#ifndef GL_BGRA
-#define GL_BGRA 0x80E1
-#endif
-#ifndef GL_UNSIGNED_BYTE_3_3_2
-#define GL_UNSIGNED_BYTE_3_3_2 0x8032
-#endif
-#ifndef GL_UNSIGNED_BYTE_2_3_3_REV
-#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
-#endif
-#ifndef GL_UNSIGNED_SHORT_4_4_4_4
-#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
-#endif
-#ifndef GL_UNSIGNED_SHORT_4_4_4_4_REV
-#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
-#endif
-#ifndef GL_UNSIGNED_SHORT_5_6_5
-#define GL_UNSIGNED_SHORT_5_6_5 0x8363
-#endif
-#ifndef GL_UNSIGNED_INT_8_8_8_8
-#define GL_UNSIGNED_INT_8_8_8_8 0x8035
-#endif
-#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
-#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
-#endif
-#ifndef GL_UNSIGNED_SHORT_5_6_5_REV
-#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
-#endif
-#ifndef GL_UNSIGNED_INT_10_10_10_2
-#define GL_UNSIGNED_INT_10_10_10_2 0x8036
-#endif
-#ifndef GL_UNSIGNED_INT_2_10_10_10_REV
-#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
-#endif
-#ifndef GL_UNSIGNED_SHORT_5_5_5_1
-#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
-#endif
-#ifndef GL_UNSIGNED_SHORT_1_5_5_5_REV
-#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
-#endif
-#ifndef GL_UNSIGNED_SHORT_8_8
-#define GL_UNSIGNED_SHORT_8_8 0x85BA
-#endif
-#ifndef GL_UNSIGNED_SHORT_8_8_REV
-#define GL_UNSIGNED_SHORT_8_8_REV 0x85BB
-#endif
-#ifndef GL_YCBCR_MESA
-#define GL_YCBCR_MESA 0x8757
-#endif
-#ifndef GL_RGB32F
-#define GL_RGB32F 0x8815
-#endif
-#ifndef GL_FLOAT_RGB32_NV
-#define GL_FLOAT_RGB32_NV 0x8889
-#endif
-#ifndef GL_LUMINANCE16
-#define GL_LUMINANCE16 0x8042
-#endif
-#ifndef GL_R16
-#define GL_R16 0x822A
-#endif
-#ifndef GL_UNPACK_CLIENT_STORAGE_APPLE
-#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2
-#endif
-#ifndef GL_FRAGMENT_PROGRAM
-#define GL_FRAGMENT_PROGRAM 0x8804
-#endif
-#ifndef GL_PROGRAM_FORMAT_ASCII
-#define GL_PROGRAM_FORMAT_ASCII 0x8875
-#endif
-#ifndef GL_PROGRAM_ERROR_POSITION
-#define GL_PROGRAM_ERROR_POSITION 0x864B
-#endif
-#ifndef GL_MAX_TEXTURE_IMAGE_UNITS
-#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
-#endif
-#ifndef GL_PROGRAM_ERROR_STRING
-#define GL_PROGRAM_ERROR_STRING 0x8874
-#endif
-/** \} */ // end of glextdefines group
-
-
-#if defined(CONFIG_GL_WIN32) && !defined(WGL_CONTEXT_MAJOR_VERSION_ARB)
-/* these are supposed to be defined in wingdi.h but mingw's is too old */
-/* only the bits actually used by mplayer are defined */
-/* reference: http://www.opengl.org/registry/specs/ARB/wgl_create_context.txt */
-
-#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
-#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
-#define WGL_CONTEXT_FLAGS_ARB 0x2094
-#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
-#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
-#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
-#endif
-
-// Define just enough constants to make the OpenGL 3 code compile against
-// older SDKs. Values are taken straight from OpenGL/gl3.h
-#if defined __APPLE__ && !(defined GL_VERSION_3_0)
-#define GL_RGBA16F 0x881A
-#define GL_RGB16F 0x881B
-#define GL_MAJOR_VERSION 0x821B
-#define GL_MINOR_VERSION 0x821C
-#define GL_NUM_EXTENSIONS 0x821D
-
-#ifndef GL_ARB_framebuffer_sRGB
-#define GL_FRAMEBUFFER_SRGB 0x8DB9
-#endif
-#endif
-
-// FreeBSD 10.0-CURRENT lacks the GLX_ARB_create_context extension completely
-#ifndef GLX_CONTEXT_MAJOR_VERSION_ARB
-#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
-#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
-#define GLX_CONTEXT_FLAGS_ARB 0x2094
-#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
-#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
-#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
-#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
-#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
-#endif
diff --git a/libvo/gl_osd.c b/libvo/gl_osd.c
deleted file mode 100644
index 81485cabe9..0000000000
--- a/libvo/gl_osd.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * This file is part of mplayer.
- *
- * mplayer 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.
- *
- * mplayer 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 mplayer. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdlib.h>
-#include <assert.h>
-#include <libavutil/common.h>
-
-#include "bitmap_packer.h"
-
-#include "gl_osd.h"
-
-struct osd_fmt_entry {
- GLint internal_format;
- GLint format;
- GLenum type;
-};
-
-// glBlendFunc() arguments
-static const int blend_factors[SUBBITMAP_COUNT][2] = {
- [SUBBITMAP_LIBASS] = {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA},
- [SUBBITMAP_RGBA] = {GL_ONE, GL_ONE_MINUS_SRC_ALPHA},
-};
-
-static const struct osd_fmt_entry osd_to_gl3_formats[SUBBITMAP_COUNT] = {
- [SUBBITMAP_LIBASS] = {GL_RED, GL_RED, GL_UNSIGNED_BYTE},
- [SUBBITMAP_RGBA] = {GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE},
-};
-
-static const struct osd_fmt_entry osd_to_gl_legacy_formats[SUBBITMAP_COUNT] = {
- [SUBBITMAP_LIBASS] = {GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE},
- [SUBBITMAP_RGBA] = {GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE},
-};
-
-struct mpgl_osd *mpgl_osd_init(GL *gl, bool legacy)
-{
- GLint max_texture_size;
- gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
-
- struct mpgl_osd *ctx = talloc_ptrtype(NULL, ctx);
- *ctx = (struct mpgl_osd) {
- .gl = gl,
- .fmt_table = legacy ? osd_to_gl_legacy_formats : osd_to_gl3_formats,
- .scratch = talloc_zero_size(ctx, 1),
- };
-
- for (int n = 0; n < MAX_OSD_PARTS; n++) {
- struct mpgl_osd_part *p = talloc_ptrtype(ctx, p);
- *p = (struct mpgl_osd_part) {
- .packer = talloc_struct(p, struct bitmap_packer, {
- .w_max = max_texture_size,
- .h_max = max_texture_size,
- }),
- };
- ctx->parts[n] = p;
- }
-
- for (int n = 0; n < SUBBITMAP_COUNT; n++)
- ctx->formats[n] = ctx->fmt_table[n].type != 0;
-
- return ctx;
-}
-
-void mpgl_osd_destroy(struct mpgl_osd *ctx)
-{
- GL *gl = ctx->gl;
-
- for (int n = 0; n < MAX_OSD_PARTS; n++) {
- struct mpgl_osd_part *p = ctx->parts[n];
- gl->DeleteTextures(1, &p->texture);
- if (gl->DeleteBuffers)
- gl->DeleteBuffers(1, &p->buffer);
- }
- talloc_free(ctx);
-}
-
-static bool upload_pbo(struct mpgl_osd *ctx, struct mpgl_osd_part *osd,
- struct sub_bitmaps *imgs)
-{
- GL *gl = ctx->gl;
- bool success = true;
- struct osd_fmt_entry fmt = ctx->fmt_table[imgs->format];
- int pix_stride = glFmt2bpp(fmt.format, fmt.type);
-
- if (!osd->buffer) {
- gl->GenBuffers(1, &osd->buffer);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, osd->buffer);
- gl->BufferData(GL_PIXEL_UNPACK_BUFFER, osd->w * osd->h * pix_stride,
- NULL, GL_DYNAMIC_COPY);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- }
-
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, osd->buffer);
- char *data = gl->MapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
- if (!data) {
- success = false;
- } else {
- struct pos bb[2];
- packer_get_bb(osd->packer, bb);
- size_t stride = osd->w * pix_stride;
- packer_copy_subbitmaps(osd->packer, imgs, data, pix_stride, stride);
- if (!gl->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER))
- success = false;
- glUploadTex(gl, GL_TEXTURE_2D, fmt.format, fmt.type, NULL, stride,
- bb[0].x, bb[0].y, bb[1].x - bb[0].x, bb[1].y - bb[0].y,
- 0);
- }
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-
- if (!success) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Error: can't upload subtitles! "
- "Remove the 'pbo' suboption.\n");
- }
-
- return success;
-}
-
-static void upload_tex(struct mpgl_osd *ctx, struct mpgl_osd_part *osd,
- struct sub_bitmaps *imgs)
-{
- struct osd_fmt_entry fmt = ctx->fmt_table[imgs->format];
- if (osd->packer->padding) {
- struct pos bb[2];
- packer_get_bb(osd->packer, bb);
- glClearTex(ctx->gl, GL_TEXTURE_2D, fmt.format, fmt.type,
- bb[0].x, bb[0].y, bb[1].x - bb[0].y, bb[1].y - bb[0].y,
- 0, &ctx->scratch);
- }
- for (int n = 0; n < osd->packer->count; n++) {
- struct sub_bitmap *s = &imgs->parts[n];
- struct pos p = osd->packer->result[n];
-
- glUploadTex(ctx->gl, GL_TEXTURE_2D, fmt.format, fmt.type,
- s->bitmap, s->stride, p.x, p.y, s->w, s->h, 0);
- }
-}
-
-static bool upload_osd(struct mpgl_osd *ctx, struct mpgl_osd_part *osd,
- struct sub_bitmaps *imgs)
-{
- GL *gl = ctx->gl;
-
- // assume 2x2 filter on scaling
- osd->packer->padding = ctx->scaled || imgs->scaled;
- int r = packer_pack_from_subbitmaps(osd->packer, imgs);
- if (r < 0) {
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] OSD bitmaps do not fit on "
- "a surface with the maximum supported size %dx%d.\n",
- osd->packer->w_max, osd->packer->h_max);
- return false;
- }
-
- struct osd_fmt_entry fmt = ctx->fmt_table[imgs->format];
- assert(fmt.type != 0);
-
- if (!osd->texture)
- gl->GenTextures(1, &osd->texture);
-
- gl->BindTexture(GL_TEXTURE_2D, osd->texture);
-
- if (osd->packer->w > osd->w || osd->packer->h > osd->h
- || osd->format != imgs->format)
- {
- osd->format = imgs->format;
- osd->w = FFMAX(32, osd->packer->w);
- osd->h = FFMAX(32, osd->packer->h);
-
- gl->TexImage2D(GL_TEXTURE_2D, 0, fmt.internal_format, osd->w, osd->h,
- 0, fmt.format, fmt.type, NULL);
-
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- if (gl->DeleteBuffers)
- gl->DeleteBuffers(1, &osd->buffer);
- osd->buffer = 0;
- }
-
- bool uploaded = false;
- if (ctx->use_pbo)
- uploaded = upload_pbo(ctx, osd, imgs);
- if (!uploaded)
- upload_tex(ctx, osd, imgs);
-
- gl->BindTexture(GL_TEXTURE_2D, 0);
-
- return true;
-}
-
-struct mpgl_osd_part *mpgl_osd_generate(struct mpgl_osd *ctx,
- struct sub_bitmaps *imgs)
-{
- if (imgs->num_parts == 0 || !ctx->formats[imgs->format])
- return NULL;
-
- struct mpgl_osd_part *osd = ctx->parts[imgs->render_index];
-
- if (imgs->bitmap_pos_id != osd->bitmap_pos_id) {
- if (imgs->bitmap_id != osd->bitmap_id) {
- if (!upload_osd(ctx, osd, imgs))
- osd->packer->count = 0;
- }
-
- osd->bitmap_id = imgs->bitmap_id;
- osd->bitmap_pos_id = imgs->bitmap_pos_id;
- osd->num_vertices = 0;
- }
-
- return osd->packer->count ? osd : NULL;
-}
-
-void mpgl_osd_set_gl_state(struct mpgl_osd *ctx, struct mpgl_osd_part *p)
-{
- GL *gl = ctx->gl;
-
- gl->BindTexture(GL_TEXTURE_2D, p->texture);
- gl->Enable(GL_BLEND);
- gl->BlendFunc(blend_factors[p->format][0], blend_factors[p->format][1]);
-}
-
-void mpgl_osd_unset_gl_state(struct mpgl_osd *ctx, struct mpgl_osd_part *p)
-{
- GL *gl = ctx->gl;
-
- gl->Disable(GL_BLEND);
- gl->BindTexture(GL_TEXTURE_2D, 0);
-}
-
-struct vertex {
- float position[2];
- uint8_t color[4];
- float texcoord[2];
-};
-
-static void draw_legacy_cb(void *pctx, struct sub_bitmaps *imgs)
-{
- struct mpgl_osd *ctx = pctx;
- struct mpgl_osd_part *osd = mpgl_osd_generate(ctx, imgs);
- if (!osd)
- return;
-
- if (!osd->num_vertices) {
- // 2 triangles primitives per quad = 6 vertices per quad
- // not using GL_QUADS, as it is deprecated in OpenGL 3.x and later
- osd->vertices = talloc_realloc(osd, osd->vertices, struct vertex,
- osd->packer->count * 6);
-
- struct vertex *va = osd->vertices;
- float tex_w = osd->w;
- float tex_h = osd->h;
-
- for (int n = 0; n < osd->packer->count; n++) {
- struct sub_bitmap *b = &imgs->parts[n];
- struct pos p = osd->packer->result[n];
-
- uint32_t c = imgs->format == SUBBITMAP_LIBASS
- ? b->libass.color : 0xFFFFFF00;
- uint8_t color[4] = { c >> 24, (c >> 16) & 0xff,
- (c >> 8) & 0xff, 255 - (c & 0xff) };
-
- float x0 = b->x;
- float y0 = b->y;
- float x1 = b->x + b->dw;
- float y1 = b->y + b->dh;
- float tx0 = p.x / tex_w;
- float ty0 = p.y / tex_h;
- float tx1 = (p.x + b->w) / tex_w;
- float ty1 = (p.y + b->h) / tex_h;
-
-#define COLOR_INIT {color[0], color[1], color[2], color[3]}
- struct vertex *v = &va[osd->num_vertices];
- v[0] = (struct vertex) { {x0, y0}, COLOR_INIT, {tx0, ty0} };
- v[1] = (struct vertex) { {x0, y1}, COLOR_INIT, {tx0, ty1} };
- v[2] = (struct vertex) { {x1, y0}, COLOR_INIT, {tx1, ty0} };
- v[3] = (struct vertex) { {x1, y1}, COLOR_INIT, {tx1, ty1} };
- v[4] = v[2];
- v[5] = v[1];
-#undef COLOR_INIT
- osd->num_vertices += 6;
- }
- }
-
- GL *gl = ctx->gl;
-
- struct vertex *va = osd->vertices;
- size_t stride = sizeof(va[0]);
-
- gl->VertexPointer(2, GL_FLOAT, stride, &va[0].position[0]);
- gl->ColorPointer(4, GL_UNSIGNED_BYTE, stride, &va[0].color[0]);
- gl->TexCoordPointer(2, GL_FLOAT, stride, &va[0].texcoord[0]);
-
- gl->EnableClientState(GL_VERTEX_ARRAY);
- gl->EnableClientState(GL_TEXTURE_COORD_ARRAY);
- gl->EnableClientState(GL_COLOR_ARRAY);
-
- mpgl_osd_set_gl_state(ctx, osd);
- gl->DrawArrays(GL_TRIANGLES, 0, osd->num_vertices);
- mpgl_osd_unset_gl_state(ctx, osd);
-
- gl->DisableClientState(GL_VERTEX_ARRAY);
- gl->DisableClientState(GL_TEXTURE_COORD_ARRAY);
- gl->DisableClientState(GL_COLOR_ARRAY);
-}
-
-void mpgl_osd_draw_legacy(struct mpgl_osd *ctx, struct osd_state *osd,
- struct mp_osd_res res)
-{
- osd_draw(osd, res, osd->vo_pts, 0, ctx->formats, draw_legacy_cb, ctx);
-}
diff --git a/libvo/gl_osd.h b/libvo/gl_osd.h
deleted file mode 100644
index cf3182ffb2..0000000000
--- a/libvo/gl_osd.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef MPLAYER_GL_OSD_H
-#define MPLAYER_GL_OSD_H
-
-#include <stdbool.h>
-#include <inttypes.h>
-
-#include "gl_common.h"
-#include "sub/sub.h"
-
-struct mpgl_osd_part {
- enum sub_bitmap_format format;
- int bitmap_id, bitmap_pos_id;
- GLuint texture;
- int w, h;
- GLuint buffer;
- int num_vertices;
- void *vertices;
- struct bitmap_packer *packer;
-};
-
-struct mpgl_osd {
- GL *gl;
- bool use_pbo;
- bool scaled;
- struct mpgl_osd_part *parts[MAX_OSD_PARTS];
- const struct osd_fmt_entry *fmt_table;
- bool formats[SUBBITMAP_COUNT];
- void *scratch;
-};
-
-struct mpgl_osd *mpgl_osd_init(GL *gl, bool legacy);
-void mpgl_osd_destroy(struct mpgl_osd *ctx);
-
-struct mpgl_osd_part *mpgl_osd_generate(struct mpgl_osd *ctx,
- struct sub_bitmaps *b);
-
-void mpgl_osd_set_gl_state(struct mpgl_osd *ctx, struct mpgl_osd_part *p);
-void mpgl_osd_unset_gl_state(struct mpgl_osd *ctx, struct mpgl_osd_part *p);
-
-void mpgl_osd_draw_legacy(struct mpgl_osd *ctx, struct osd_state *osd,
- struct mp_osd_res res);
-
-#endif
diff --git a/libvo/osx_common.c b/libvo/osx_common.c
deleted file mode 100644
index 2aa0a28126..0000000000
--- a/libvo/osx_common.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#include "config.h"
-
-// only to get keycode definitions from HIToolbox/Events.h
-#include <Carbon/Carbon.h>
-#include <CoreServices/CoreServices.h>
-#include "config.h"
-#include "osx_common.h"
-#include "video_out.h"
-#include "input/keycodes.h"
-#include "input/input.h"
-#include "mp_msg.h"
-
-/*
- * Define keycodes only found in OSX >= 10.5 for older versions
- */
-#if MAC_OS_X_VERSION_MAX_ALLOWED <= 1040
-#define kVK_ANSI_Keypad0 0x52
-#define kVK_ANSI_Keypad1 0x53
-#define kVK_ANSI_Keypad2 0x54
-#define kVK_ANSI_Keypad3 0x55
-#define kVK_ANSI_Keypad4 0x56
-#define kVK_ANSI_Keypad5 0x57
-#define kVK_ANSI_Keypad6 0x58
-#define kVK_ANSI_Keypad7 0x59
-#define kVK_ANSI_Keypad8 0x5b
-#define kVK_ANSI_Keypad9 0x5c
-#define kVK_ANSI_KeypadDecimal 0x41
-#define kVK_ANSI_KeypadDivide 0x4b
-#define kVK_ANSI_KeypadEnter 0x4c
-#define kVK_ANSI_KeypadMinus 0x4e
-#define kVK_ANSI_KeypadMultiply 0x43
-#define kVK_ANSI_KeypadPlus 0x45
-#define kVK_Control 0x3b
-#define kVK_Delete 0x33
-#define kVK_DownArrow 0x7d
-#define kVK_End 0x77
-#define kVK_Escape 0x35
-#define kVK_F1 0x7a
-#define kVK_F10 0x6d
-#define kVK_F11 0x67
-#define kVK_F12 0x6f
-#define kVK_F2 0x78
-#define kVK_F3 0x63
-#define kVK_F4 0x76
-#define kVK_F5 0x60
-#define kVK_F6 0x61
-#define kVK_F7 0x62
-#define kVK_F8 0x64
-#define kVK_F9 0x65
-#define kVK_ForwardDelete 0x75
-#define kVK_Help 0x72
-#define kVK_Home 0x73
-#define kVK_LeftArrow 0x7b
-#define kVK_Option 0x3a
-#define kVK_PageDown 0x79
-#define kVK_PageUp 0x74
-#define kVK_Return 0x24
-#define kVK_RightArrow 0x7c
-#define kVK_Shift 0x38
-#define kVK_Tab 0x30
-#define kVK_UpArrow 0x7e
-#endif /* MAC_OS_X_VERSION_MAX_ALLOWED <= 1040 */
-
-static const struct mp_keymap keymap[] = {
- // special keys
- {0x34, KEY_ENTER}, // Enter key on some iBooks?
- {kVK_Return, KEY_ENTER},
- {kVK_Escape, KEY_ESC},
- {kVK_Delete, KEY_BACKSPACE}, {kVK_Option, KEY_BACKSPACE}, {kVK_Control, KEY_BACKSPACE}, {kVK_Shift, KEY_BACKSPACE},
- {kVK_Tab, KEY_TAB},
-
- // cursor keys
- {kVK_UpArrow, KEY_UP}, {kVK_DownArrow, KEY_DOWN}, {kVK_LeftArrow, KEY_LEFT}, {kVK_RightArrow, KEY_RIGHT},
-
- // navigation block
- {kVK_Help, KEY_INSERT}, {kVK_ForwardDelete, KEY_DELETE}, {kVK_Home, KEY_HOME},
- {kVK_End, KEY_END}, {kVK_PageUp, KEY_PAGE_UP}, {kVK_PageDown, KEY_PAGE_DOWN},
-
- // F-keys
- {kVK_F1, KEY_F + 1}, {kVK_F2, KEY_F + 2}, {kVK_F3, KEY_F + 3}, {kVK_F4, KEY_F + 4},
- {kVK_F5, KEY_F + 5}, {kVK_F6, KEY_F + 6}, {kVK_F7, KEY_F + 7}, {kVK_F8, KEY_F + 8},
- {kVK_F9, KEY_F + 9}, {kVK_F10, KEY_F + 10}, {kVK_F11, KEY_F + 11}, {kVK_F12, KEY_F + 12},
-
- // numpad
- {kVK_ANSI_KeypadPlus, '+'}, {kVK_ANSI_KeypadMinus, '-'}, {kVK_ANSI_KeypadMultiply, '*'},
- {kVK_ANSI_KeypadDivide, '/'}, {kVK_ANSI_KeypadEnter, KEY_KPENTER}, {kVK_ANSI_KeypadDecimal, KEY_KPDEC},
- {kVK_ANSI_Keypad0, KEY_KP0}, {kVK_ANSI_Keypad1, KEY_KP1}, {kVK_ANSI_Keypad2, KEY_KP2}, {kVK_ANSI_Keypad3, KEY_KP3},
- {kVK_ANSI_Keypad4, KEY_KP4}, {kVK_ANSI_Keypad5, KEY_KP5}, {kVK_ANSI_Keypad6, KEY_KP6}, {kVK_ANSI_Keypad7, KEY_KP7},
- {kVK_ANSI_Keypad8, KEY_KP8}, {kVK_ANSI_Keypad9, KEY_KP9},
-
- {0, 0}
-};
-
-int convert_key(unsigned key, unsigned charcode)
-{
- int mpkey = lookup_keymap_table(keymap, key);
- if (mpkey)
- return mpkey;
- return charcode;
-}
-
-/**
- * Checks at runtime that OSX version is the same or newer than the one
- * provided as input.
- */
-int is_osx_version_at_least(int majorv, int minorv, int bugfixv)
-{
- OSErr err;
- SInt32 major, minor, bugfix;
- if ((err = Gestalt(gestaltSystemVersionMajor, &major)) != noErr)
- goto fail;
- if ((err = Gestalt(gestaltSystemVersionMinor, &minor)) != noErr)
- goto fail;
- if ((err = Gestalt(gestaltSystemVersionBugFix, &bugfix)) != noErr)
- goto fail;
-
- if(major > majorv ||
- (major == majorv && (minor > minorv ||
- (minor == minorv && bugfix >= bugfixv))))
- return 1;
- else
- return 0;
-fail:
- // There's no reason the Gestalt system call should fail on OSX.
- mp_msg(MSGT_VO, MSGL_FATAL, "[osx] Failed to get system version number. "
- "Please contact the developers. Error code: %ld\n", (long)err);
- return 0;
-}
diff --git a/libvo/osx_common.h b/libvo/osx_common.h
deleted file mode 100644
index ae31a6353d..0000000000
--- a/libvo/osx_common.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_OSX_COMMON_H
-#define MPLAYER_OSX_COMMON_H
-
-struct vo;
-
-int convert_key(unsigned key, unsigned charcode);
-int is_osx_version_at_least(int majorv, int minorv, int bugfixv);
-
-#endif /* MPLAYER_OSX_COMMON_H */
diff --git a/libvo/video_out.c b/libvo/video_out.c
deleted file mode 100644
index 571f00da4d..0000000000
--- a/libvo/video_out.c
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
- * libvo common functions, variables used by many/all drivers.
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stdbool.h>
-
-#include <unistd.h>
-//#include <sys/mman.h>
-
-#include "config.h"
-#include "options.h"
-#include "talloc.h"
-#include "bstr.h"
-#include "video_out.h"
-#include "aspect.h"
-#include "geometry.h"
-#include "input/input.h"
-#include "mp_fifo.h"
-#include "m_config.h"
-#include "mp_msg.h"
-#include "libmpcodecs/vfcap.h"
-#include "sub/sub.h"
-
-#include "osdep/shmem.h"
-#ifdef CONFIG_X11
-#include "x11_common.h"
-#endif
-
-int xinerama_screen = -1;
-int xinerama_x;
-int xinerama_y;
-
-int vo_nomouse_input = 0;
-int vo_grabpointer = 1;
-int vo_vsync = 1;
-int vo_fs = 0;
-int vo_fsmode = 0;
-float vo_panscan = 0.0f;
-int vo_refresh_rate=0;
-int vo_keepaspect=1;
-int vo_rootwin=0;
-int vo_border=1;
-int64_t WinID = -1;
-
-int vo_pts=0; // for hw decoding
-float vo_fps=0;
-
-int vo_colorkey = 0x0000ff00; // default colorkey is green
- // (0xff000000 means that colorkey has been disabled)
-
-//
-// Externally visible list of all vo drivers
-//
-extern struct vo_driver video_out_x11;
-extern struct vo_driver video_out_vdpau;
-extern struct vo_driver video_out_xv;
-extern struct vo_driver video_out_opengl;
-extern struct vo_driver video_out_opengl_hq;
-extern struct vo_driver video_out_opengl_old;
-extern struct vo_driver video_out_null;
-extern struct vo_driver video_out_image;
-extern struct vo_driver video_out_lavc;
-extern struct vo_driver video_out_caca;
-extern struct vo_driver video_out_direct3d;
-extern struct vo_driver video_out_direct3d_shaders;
-extern struct vo_driver video_out_corevideo;
-
-const struct vo_driver *video_out_drivers[] =
-{
-#ifdef CONFIG_DIRECT3D
- &video_out_direct3d_shaders,
- &video_out_direct3d,
-#endif
-#ifdef CONFIG_GL_COCOA
- &video_out_opengl,
- &video_out_opengl_old,
-#endif
-#ifdef CONFIG_COREVIDEO
- &video_out_corevideo,
-#endif
-#if CONFIG_VDPAU
- &video_out_vdpau,
-#endif
-#ifdef CONFIG_XV
- &video_out_xv,
-#endif
-#ifdef CONFIG_GL
-#if !defined CONFIG_GL_COCOA
- &video_out_opengl,
- &video_out_opengl_old,
-#endif
-#endif
-#ifdef CONFIG_X11
- &video_out_x11,
-#endif
-#ifdef CONFIG_CACA
- &video_out_caca,
-#endif
- &video_out_null,
- // should not be auto-selected
- &video_out_image,
-#ifdef CONFIG_ENCODING
- &video_out_lavc,
-#endif
-#ifdef CONFIG_GL
- &video_out_opengl_hq,
-#endif
- NULL
-};
-
-
-static int vo_preinit(struct vo *vo, char *arg)
-{
- if (vo->driver->priv_size) {
- vo->priv = talloc_zero_size(vo, vo->driver->priv_size);
- if (vo->driver->priv_defaults)
- memcpy(vo->priv, vo->driver->priv_defaults, vo->driver->priv_size);
- }
- if (vo->driver->options) {
- struct m_config *cfg = m_config_simple(vo->priv);
- talloc_steal(vo->priv, cfg);
- m_config_register_options(cfg, vo->driver->options);
- char n[50];
- int l = snprintf(n, sizeof(n), "vo/%s", vo->driver->info->short_name);
- assert(l < sizeof(n));
- int r = m_config_parse_suboptions(cfg, n, arg);
- if (r < 0)
- return r;
- }
- return vo->driver->preinit(vo, arg);
-}
-
-int vo_control(struct vo *vo, uint32_t request, void *data)
-{
- return vo->driver->control(vo, request, data);
-}
-
-// Return -1 if driver appears not to support a draw_image interface,
-// 0 otherwise (whether the driver actually drew something or not).
-int vo_draw_image(struct vo *vo, struct mp_image *mpi, double pts)
-{
- if (!vo->config_ok)
- return 0;
- if (vo->driver->buffer_frames) {
- vo->driver->draw_image(vo, mpi, pts);
- return 0;
- }
- vo->frame_loaded = true;
- vo->next_pts = pts;
- // Guaranteed to support at least DRAW_IMAGE later
- if (vo->driver->is_new) {
- vo->waiting_mpi = mpi;
- return 0;
- }
- if (vo_control(vo, VOCTRL_DRAW_IMAGE, mpi) == VO_NOTIMPL)
- return -1;
- return 0;
-}
-
-int vo_redraw_frame(struct vo *vo)
-{
- if (!vo->config_ok || !vo->hasframe)
- return -1;
- if (vo_control(vo, VOCTRL_REDRAW_FRAME, NULL) == true) {
- vo->redrawing = true;
- return 0;
- }
- return -1;
-}
-
-int vo_get_buffered_frame(struct vo *vo, bool eof)
-{
- if (!vo->config_ok)
- return -1;
- if (vo->frame_loaded)
- return 0;
- if (!vo->driver->buffer_frames)
- return -1;
- vo->driver->get_buffered_frame(vo, eof);
- return vo->frame_loaded ? 0 : -1;
-}
-
-void vo_skip_frame(struct vo *vo)
-{
- vo_control(vo, VOCTRL_SKIPFRAME, NULL);
- vo->frame_loaded = false;
-}
-
-int vo_draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h, int x, int y)
-{
- return vo->driver->draw_slice(vo, src, stride, w, h, x, y);
-}
-
-void vo_new_frame_imminent(struct vo *vo)
-{
- if (!vo->driver->is_new)
- return;
- if (vo->driver->buffer_frames)
- vo_control(vo, VOCTRL_NEWFRAME, NULL);
- else {
- vo_control(vo, VOCTRL_DRAW_IMAGE, vo->waiting_mpi);
- vo->waiting_mpi = NULL;
- }
-}
-
-void vo_draw_osd(struct vo *vo, struct osd_state *osd)
-{
- if (vo->config_ok && (vo->default_caps & VFCAP_OSD))
- vo->driver->draw_osd(vo, osd);
-}
-
-void vo_flip_page(struct vo *vo, unsigned int pts_us, int duration)
-{
- if (!vo->config_ok)
- return;
- if (!vo->redrawing) {
- vo->frame_loaded = false;
- vo->next_pts = MP_NOPTS_VALUE;
- }
- vo->want_redraw = false;
- vo->redrawing = false;
- if (vo->driver->flip_page_timed)
- vo->driver->flip_page_timed(vo, pts_us, duration);
- else
- vo->driver->flip_page(vo);
- vo->hasframe = true;
-}
-
-void vo_check_events(struct vo *vo)
-{
- if (!vo->config_ok) {
- if (vo->registered_fd != -1)
- mp_input_rm_key_fd(vo->input_ctx, vo->registered_fd);
- vo->registered_fd = -1;
- return;
- }
- vo->driver->check_events(vo);
-}
-
-void vo_seek_reset(struct vo *vo)
-{
- vo_control(vo, VOCTRL_RESET, NULL);
- vo->frame_loaded = false;
- vo->hasframe = false;
-}
-
-void vo_destroy(struct vo *vo)
-{
- if (vo->registered_fd != -1)
- mp_input_rm_key_fd(vo->input_ctx, vo->registered_fd);
- vo->driver->uninit(vo);
- talloc_free(vo);
-}
-
-void list_video_out(void)
-{
- int i = 0;
- mp_tmsg(MSGT_CPLAYER, MSGL_INFO, "Available video output drivers:\n");
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_OUTPUTS\n");
- while (video_out_drivers[i]) {
- const vo_info_t *info = video_out_drivers[i++]->info;
- mp_msg(MSGT_GLOBAL, MSGL_INFO,"\t%s\t%s\n", info->short_name, info->name);
- }
- mp_msg(MSGT_GLOBAL, MSGL_INFO,"\n");
-}
-
-static void replace_legacy_vo_name(bstr *name)
-{
- bstr new = *name;
- if (bstr_equals0(*name, "gl"))
- new = bstr0("opengl");
- if (bstr_equals0(*name, "gl3"))
- new = bstr0("opengl-hq");
- if (!bstr_equals(*name, new)) {
- mp_tmsg(MSGT_CPLAYER, MSGL_ERR, "VO driver '%.*s' has been replaced "
- "with '%.*s'!\n", BSTR_P(*name), BSTR_P(new));
- }
- *name = new;
-}
-
-struct vo *init_best_video_out(struct MPOpts *opts,
- struct mp_fifo *key_fifo,
- struct input_ctx *input_ctx,
- struct encode_lavc_context *encode_lavc_ctx)
-{
- char **vo_list = opts->video_driver_list;
- int i;
- struct vo *vo = talloc_ptrtype(NULL, vo);
- struct vo initial_values = {
- .opts = opts,
- .key_fifo = key_fifo,
- .encode_lavc_ctx = encode_lavc_ctx,
- .input_ctx = input_ctx,
- .event_fd = -1,
- .registered_fd = -1,
- };
- // first try the preferred drivers, with their optional subdevice param:
- if (vo_list && vo_list[0])
- while (vo_list[0][0]) {
- char *arg = vo_list[0];
- bstr name = bstr0(arg);
- char *params = strchr(arg, ':');
- if (params) {
- name = bstr_splice(name, 0, params - arg);
- params++;
- }
- replace_legacy_vo_name(&name);
- for (i = 0; video_out_drivers[i]; i++) {
- const struct vo_driver *video_driver = video_out_drivers[i];
- const vo_info_t *info = video_driver->info;
- if (bstr_equals0(name, info->short_name)) {
- // name matches, try it
- *vo = initial_values;
- vo->driver = video_driver;
- if (!vo_preinit(vo, params))
- return vo; // success!
- talloc_free_children(vo);
- }
- }
- // continue...
- ++vo_list;
- if (!(vo_list[0])) {
- talloc_free(vo);
- return NULL; // do NOT fallback to others
- }
- }
- // now try the rest...
- for (i = 0; video_out_drivers[i]; i++) {
- const struct vo_driver *video_driver = video_out_drivers[i];
- *vo = initial_values;
- vo->driver = video_driver;
- if (!vo_preinit(vo, NULL))
- return vo; // success!
- talloc_free_children(vo);
- }
- talloc_free(vo);
- return NULL;
-}
-
-static int event_fd_callback(void *ctx, int fd)
-{
- struct vo *vo = ctx;
- vo_check_events(vo);
- return MP_INPUT_NOTHING;
-}
-
-int vo_config(struct vo *vo, uint32_t width, uint32_t height,
- uint32_t d_width, uint32_t d_height, uint32_t flags,
- uint32_t format)
-{
- struct MPOpts *opts = vo->opts;
- panscan_init(vo);
- aspect_save_videores(vo, width, height, d_width, d_height);
-
- if (vo_control(vo, VOCTRL_UPDATE_SCREENINFO, NULL) == VO_TRUE) {
- aspect(vo, &d_width, &d_height, A_NOZOOM);
- vo->dx = (int)(opts->vo_screenwidth - d_width) / 2;
- vo->dy = (int)(opts->vo_screenheight - d_height) / 2;
- geometry(&vo->dx, &vo->dy, &d_width, &d_height,
- opts->vo_screenwidth, opts->vo_screenheight);
- geometry_xy_changed |= xinerama_screen >= 0;
- vo->dx += xinerama_x;
- vo->dy += xinerama_y;
- vo->dwidth = d_width;
- vo->dheight = d_height;
- }
-
- vo->default_caps = vo_control(vo, VOCTRL_QUERY_FORMAT, &format);
-
- int ret = vo->driver->config(vo, width, height, d_width, d_height, flags,
- format);
- vo->config_ok = (ret == 0);
- vo->config_count += vo->config_ok;
- if (!vo->config_ok)
- vo->default_caps = 0;
- if (vo->registered_fd == -1 && vo->event_fd != -1 && vo->config_ok) {
- mp_input_add_key_fd(vo->input_ctx, vo->event_fd, 1, event_fd_callback,
- NULL, vo);
- vo->registered_fd = vo->event_fd;
- }
- vo->frame_loaded = false;
- vo->waiting_mpi = NULL;
- vo->redrawing = false;
- vo->hasframe = false;
- return ret;
-}
-
-/**
- * \brief lookup an integer in a table, table must have 0 as the last key
- * \param key key to search for
- * \result translation corresponding to key or "to" value of last mapping
- * if not found.
- */
-int lookup_keymap_table(const struct mp_keymap *map, int key) {
- while (map->from && map->from != key) map++;
- return map->to;
-}
-
-static void print_video_rect(struct vo *vo, struct mp_rect src,
- struct mp_rect dst, struct mp_osd_res osd)
-{
- int lv = MSGL_V;
-
- int sw = src.x1 - src.x0, sh = src.y1 - src.y0;
- int dw = dst.x1 - dst.x0, dh = dst.y1 - dst.y0;
-
- mp_msg(MSGT_VO, lv, "[vo] Window size: %dx%d\n",
- vo->dwidth, vo->dheight);
- mp_msg(MSGT_VO, lv, "[vo] Video source: %dx%d (%dx%d)\n",
- vo->aspdat.orgw, vo->aspdat.orgh,
- vo->aspdat.prew, vo->aspdat.preh);
- mp_msg(MSGT_VO, lv, "[vo] Video display: (%d, %d) %dx%d -> (%d, %d) %dx%d\n",
- src.x0, src.y0, sw, sh, dst.x0, dst.y0, dw, dh);
- mp_msg(MSGT_VO, lv, "[vo] Video scale: %f/%f\n",
- (double)dw / sw, (double)dh / sh);
- mp_msg(MSGT_VO, lv, "[vo] OSD borders: l=%d t=%d r=%d b=%d\n",
- osd.ml, osd.mt, osd.mr, osd.mb);
- mp_msg(MSGT_VO, lv, "[vo] Video borders: l=%d t=%d r=%d b=%d\n",
- dst.x0, dst.y0, vo->dwidth - dst.x1, vo->dheight - dst.y1);
-}
-
-static void src_dst_split_scaling(int src_size, int dst_size,
- int scaled_src_size, int *src_start,
- int *src_end, int *dst_start, int *dst_end)
-{
- if (scaled_src_size > dst_size) {
- int border = src_size * (scaled_src_size - dst_size) / scaled_src_size;
- // round to a multiple of 2, this is at least needed for vo_direct3d
- // and ATI cards
- border = (border / 2 + 1) & ~1;
- *src_start = border;
- *src_end = src_size - border;
- *dst_start = 0;
- *dst_end = dst_size;
- } else {
- *src_start = 0;
- *src_end = src_size;
- *dst_start = (dst_size - scaled_src_size) / 2;
- *dst_end = *dst_start + scaled_src_size;
- }
-}
-
-// Calculate the appropriate source and destination rectangle to
-// get a correctly scaled picture, including pan-scan.
-// out_src: visible part of the video
-// out_dst: area of screen covered by the video source rectangle
-// out_osd: OSD size, OSD margins, etc.
-void vo_get_src_dst_rects(struct vo *vo, struct mp_rect *out_src,
- struct mp_rect *out_dst, struct mp_osd_res *out_osd)
-{
- int src_w = vo->aspdat.orgw;
- int src_h = vo->aspdat.orgh;
- struct mp_rect dst = {0, 0, vo->dwidth, vo->dheight};
- struct mp_rect src = {0, 0, src_w, src_h};
- struct mp_osd_res osd = {
- .w = vo->dwidth,
- .h = vo->dheight,
- .display_par = vo->monitor_par,
- .video_par = vo->aspdat.par,
- };
- if (aspect_scaling()) {
- int scaled_width = 0, scaled_height = 0;
- aspect(vo, &scaled_width, &scaled_height, A_WINZOOM);
- panscan_calc_windowed(vo);
- scaled_width += vo->panscan_x;
- scaled_height += vo->panscan_y;
- int border_w = vo->dwidth - scaled_width;
- int border_h = vo->dheight - scaled_height;
- osd.ml = border_w / 2;
- osd.mt = border_h / 2;
- osd.mr = border_w - osd.ml;
- osd.mb = border_h - osd.mt;
- src_dst_split_scaling(src_w, vo->dwidth, scaled_width,
- &src.x0, &src.x1, &dst.x0, &dst.x1);
- src_dst_split_scaling(src_h, vo->dheight, scaled_height,
- &src.y0, &src.y1, &dst.y0, &dst.y1);
- }
-
- *out_src = src;
- *out_dst = dst;
- *out_osd = osd;
-
- print_video_rect(vo, src, dst, osd);
-}
-
-// Return the window title the VO should set. Always returns a null terminated
-// string. The string is valid until frontend code is invoked again. Copy it if
-// you need to keep the string for an extended period of time.
-const char *vo_get_window_title(struct vo *vo)
-{
- if (!vo->window_title)
- vo->window_title = talloc_strdup(vo, "");
- return vo->window_title;
-}
-
-/**
- * Generates a mouse movement message if those are enable and sends it
- * to the "main" MPlayer.
- *
- * \param posx new x position of mouse
- * \param posy new y position of mouse
- */
-void vo_mouse_movement(struct vo *vo, int posx, int posy)
-{
- char cmd_str[40];
- if (!enable_mouse_movements)
- return;
- snprintf(cmd_str, sizeof(cmd_str), "set_mouse_pos %i %i", posx, posy);
- mp_input_queue_cmd(vo->input_ctx, mp_input_parse_cmd(bstr0(cmd_str), ""));
-}
diff --git a/libvo/video_out.h b/libvo/video_out.h
deleted file mode 100644
index ac2ded9b3c..0000000000
--- a/libvo/video_out.h
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) Aaron Holtzman - Aug 1999
- * Strongly modified, most parts rewritten: A'rpi/ESP-team - 2000-2001
- * (C) MPlayer developers
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_VIDEO_OUT_H
-#define MPLAYER_VIDEO_OUT_H
-
-#include <inttypes.h>
-#include <stdbool.h>
-
-#include "libmpcodecs/img_format.h"
-#include "mpcommon.h"
-
-#define VO_EVENT_EXPOSE 1
-#define VO_EVENT_RESIZE 2
-#define VO_EVENT_KEYPRESS 4
-#define VO_EVENT_REINIT 8
-#define VO_EVENT_MOVE 16
-
-enum mp_voctrl {
- /* does the device support the required format */
- VOCTRL_QUERY_FORMAT = 1,
- /* signal a device reset seek */
- VOCTRL_RESET,
- /* used to switch to fullscreen */
- VOCTRL_FULLSCREEN,
- /* signal a device pause */
- VOCTRL_PAUSE,
- /* start/resume playback */
- VOCTRL_RESUME,
- /* libmpcodecs direct rendering */
- VOCTRL_GET_IMAGE,
- VOCTRL_DRAW_IMAGE,
- VOCTRL_GET_PANSCAN,
- VOCTRL_SET_PANSCAN,
- VOCTRL_SET_EQUALIZER, // struct voctrl_set_equalizer_args
- VOCTRL_GET_EQUALIZER, // struct voctrl_get_equalizer_args
- VOCTRL_DUPLICATE_FRAME,
-
- VOCTRL_START_SLICE,
-
- VOCTRL_NEWFRAME,
- VOCTRL_SKIPFRAME,
- VOCTRL_REDRAW_FRAME,
-
- VOCTRL_ONTOP,
- VOCTRL_ROOTWIN,
- VOCTRL_BORDER,
-
- VOCTRL_SET_DEINTERLACE,
- VOCTRL_GET_DEINTERLACE,
-
- VOCTRL_UPDATE_SCREENINFO,
-
- VOCTRL_SET_YUV_COLORSPACE, // struct mp_csp_details
- VOCTRL_GET_YUV_COLORSPACE, // struct mp_csp_details
-
- VOCTRL_SCREENSHOT, // struct voctrl_screenshot_args
-
- VOCTRL_SET_COMMAND_LINE, // char*
-};
-
-// VOCTRL_SET_EQUALIZER
-struct voctrl_set_equalizer_args {
- const char *name;
- int value;
-};
-
-// VOCTRL_GET_EQUALIZER
-struct voctrl_get_equalizer_args {
- const char *name;
- int *valueptr;
-};
-
-// VOCTRL_SCREENSHOT
-struct voctrl_screenshot_args {
- // 0: Save image of the currently displayed video frame, in original
- // resolution.
- // 1: Save full screenshot of the window. Should contain OSD, EOSD, and the
- // scaled video.
- // The value of this variable can be ignored if only a single method is
- // implemented.
- int full_window;
- // Will be set to a newly allocated image, that contains the screenshot.
- // The caller has to free the pointer with free_mp_image().
- // It is not specified whether the image data is a copy or references the
- // image data directly.
- // Is never NULL. (Failure has to be indicated by returning VO_FALSE.)
- struct mp_image *out_image;
- // Whether the VO rendered OSD/subtitles into out_image
- bool has_osd;
-};
-
-typedef struct {
- int x,y;
- int w,h;
-} mp_win_t;
-
-#define VO_TRUE 1
-#define VO_FALSE 0
-#define VO_ERROR -1
-#define VO_NOTAVAIL -2
-#define VO_NOTIMPL -3
-
-#define VOFLAG_FULLSCREEN 0x01
-#define VOFLAG_MODESWITCHING 0x02
-#define VOFLAG_SWSCALE 0x04
-#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
-{
- /* driver name ("Matrox Millennium G200/G400" */
- const char *name;
- /* short name (for config strings) ("vdpau") */
- const char *short_name;
- /* author ("Aaron Holtzman <aholtzma@ess.engr.uvic.ca>") */
- const char *author;
- /* any additional comments */
- const char *comment;
-} vo_info_t;
-
-struct vo;
-struct osd_state;
-struct mp_image;
-
-struct vo_driver {
- // Driver uses new API
- bool is_new;
- // Driver buffers or adds (deinterlace) frames and will keep track
- // of pts values itself
- bool buffer_frames;
-
- const vo_info_t *info;
- /*
- * Preinitializes driver (real INITIALIZATION)
- * arg - currently it's vo_subdevice
- * returns: zero on successful initialization, non-zero on error.
- */
- int (*preinit)(struct vo *vo, const char *arg);
- /*
- * Initialize (means CONFIGURE) the display driver.
- * params:
- * width,height: image source size
- * d_width,d_height: size of the requested window size, just a hint
- * fullscreen: flag, 0=windowd 1=fullscreen, just a hint
- * title: window title, if available
- * format: fourcc of pixel format
- * returns : zero on successful initialization, non-zero on error.
- */
- int (*config)(struct vo *vo, uint32_t width, uint32_t height,
- uint32_t d_width, uint32_t d_height, uint32_t fullscreen,
- uint32_t format);
-
- /*
- * Control interface
- */
- int (*control)(struct vo *vo, uint32_t request, void *data);
-
- void (*draw_image)(struct vo *vo, struct mp_image *mpi, double pts);
-
- /*
- * Get extra frames from the VO, such as those added by VDPAU
- * deinterlace. Preparing the next such frame if any could be done
- * automatically by the VO after a previous flip_page(), but having
- * it as a separate step seems to allow making code more robust.
- */
- void (*get_buffered_frame)(struct vo *vo, bool eof);
-
- /*
- * Draw a planar YUV slice to the buffer:
- * params:
- * src[3] = source image planes (Y,U,V)
- * stride[3] = source image planes line widths (in bytes)
- * w,h = width*height of area to be copied (in Y pixels)
- * x,y = position at the destination image (in Y pixels)
- */
- int (*draw_slice)(struct vo *vo, uint8_t *src[], int stride[], int w,
- int h, int x, int y);
-
- /*
- * Draws OSD to the screen buffer
- */
- void (*draw_osd)(struct vo *vo, struct osd_state *osd);
-
- /*
- * Blit/Flip buffer to the screen. Must be called after each frame!
- */
- void (*flip_page)(struct vo *vo);
- void (*flip_page_timed)(struct vo *vo, unsigned int pts_us, int duration);
-
- /*
- * This func is called after every frames to handle keyboard and
- * other events. It's called in PAUSE mode too!
- */
- void (*check_events)(struct vo *vo);
-
- /*
- * Closes driver. Should restore the original state of the system.
- */
- void (*uninit)(struct vo *vo);
-
- // Size of private struct for automatic allocation (0 doesn't allocate)
- int priv_size;
-
- // If not NULL, it's copied into the newly allocated private struct.
- const void *priv_defaults;
-
- // List of options to parse into priv struct (requires privsize to be set)
- const struct m_option *options;
-};
-
-struct vo {
- int config_ok; // Last config call was successful?
- int config_count; // Total number of successful config calls
- int default_caps; // query_format() result for configured video format
-
- bool frame_loaded; // Is there a next frame the VO could flip to?
- struct mp_image *waiting_mpi;
- double next_pts; // pts value of the next frame if any
- double next_pts2; // optional pts of frame after that
- bool want_redraw; // visible frame wrong (window resize), needs refresh
- bool redrawing; // between redrawing frame and flipping it
- bool hasframe; // >= 1 frame has been drawn, so redraw is possible
-
- double flip_queue_offset; // queue flip events at most this much in advance
-
- const struct vo_driver *driver;
- void *priv;
- struct MPOpts *opts;
- struct vo_x11_state *x11;
- struct vo_w32_state *w32;
- struct vo_cocoa_state *cocoa;
- struct mp_fifo *key_fifo;
- struct encode_lavc_context *encode_lavc_ctx;
- struct input_ctx *input_ctx;
- int event_fd; // check_events() should be called when this has input
- int registered_fd; // set to event_fd when registered in input system
-
- // requested position/resolution (usually window position/window size)
- int dx;
- int dy;
- int dwidth;
- int dheight;
-
- int panscan_x;
- int panscan_y;
- float panscan_amount;
- float monitor_par;
- struct aspect_data {
- int orgw; // real width
- int orgh; // real height
- int prew; // prescaled width
- int preh; // prescaled height
- float par; // pixel aspect ratio out of orgw/orgh and prew/preh
- int scrw; // horizontal resolution
- int scrh; // vertical resolution
- float asp;
- } aspdat;
-
- char *window_title;
-};
-
-struct vo *init_best_video_out(struct MPOpts *opts,
- struct mp_fifo *key_fifo,
- struct input_ctx *input_ctx,
- struct encode_lavc_context *encode_lavc_ctx);
-int vo_config(struct vo *vo, uint32_t width, uint32_t height,
- uint32_t d_width, uint32_t d_height, uint32_t flags,
- uint32_t format);
-void list_video_out(void);
-
-int vo_control(struct vo *vo, uint32_t request, void *data);
-int vo_draw_image(struct vo *vo, struct mp_image *mpi, double pts);
-int vo_redraw_frame(struct vo *vo);
-int vo_get_buffered_frame(struct vo *vo, bool eof);
-void vo_skip_frame(struct vo *vo);
-int vo_draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h, int x, int y);
-void vo_new_frame_imminent(struct vo *vo);
-void vo_draw_osd(struct vo *vo, struct osd_state *osd);
-void vo_flip_page(struct vo *vo, unsigned int pts_us, int duration);
-void vo_check_events(struct vo *vo);
-void vo_seek_reset(struct vo *vo);
-void vo_destroy(struct vo *vo);
-
-const char *vo_get_window_title(struct vo *vo);
-
-// NULL terminated array of all drivers
-extern const struct vo_driver *video_out_drivers[];
-
-extern int xinerama_screen;
-extern int xinerama_x;
-extern int xinerama_y;
-
-extern int vo_grabpointer;
-extern int vo_vsync;
-extern int vo_fs;
-extern int vo_fsmode;
-extern float vo_panscan;
-extern int vo_refresh_rate;
-extern int vo_keepaspect;
-extern int vo_rootwin;
-extern int vo_border;
-
-extern int vo_nomouse_input;
-extern int enable_mouse_movements;
-
-extern int vo_pts;
-extern float vo_fps;
-
-extern int vo_colorkey;
-
-extern int64_t WinID;
-
-struct mp_keymap {
- int from;
- int to;
-};
-int lookup_keymap_table(const struct mp_keymap *map, int key);
-
-void vo_mouse_movement(struct vo *vo, int posx, int posy);
-
-struct mp_osd_res;
-void vo_get_src_dst_rects(struct vo *vo, struct mp_rect *out_src,
- struct mp_rect *out_dst, struct mp_osd_res *out_osd);
-
-static inline int aspect_scaling(void)
-{
- return vo_keepaspect || vo_fs;
-}
-
-#endif /* MPLAYER_VIDEO_OUT_H */
diff --git a/libvo/vo_caca.c b/libvo/vo_caca.c
deleted file mode 100644
index 2d998bf91d..0000000000
--- a/libvo/vo_caca.c
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * video output driver for libcaca
- *
- * by Pigeon <pigeon@pigeond.net>
- *
- * Some functions/codes/ideas are from x11 and aalib vo
- *
- * TODO: support draw_alpha?
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <string.h>
-#include <time.h>
-#include <errno.h>
-#include <assert.h>
-#include <caca.h>
-
-#include "config.h"
-#include "video_out.h"
-#include "sub/sub.h"
-#include "libmpcodecs/mp_image.h"
-#include "libmpcodecs/vfcap.h"
-
-#include "input/keycodes.h"
-#include "input/input.h"
-#include "mp_msg.h"
-#include "mp_fifo.h"
-
-/* caca stuff */
-static caca_canvas_t *canvas;
-static caca_display_t *display;
-static caca_dither_t *dither = NULL;
-static const char *dither_antialias = "default";
-static const char *dither_charset = "default";
-static const char *dither_color = "default";
-static const char *dither_algo = "none";
-
-/* image infos */
-static int image_format;
-static int image_width;
-static int image_height;
-
-static int screen_w, screen_h;
-
-/* We want 24bpp always for now */
-static unsigned int bpp = 24;
-static unsigned int depth = 3;
-static unsigned int rmask = 0xff0000;
-static unsigned int gmask = 0x00ff00;
-static unsigned int bmask = 0x0000ff;
-static unsigned int amask = 0;
-
-#define MESSAGE_SIZE 512
-#define MESSAGE_DURATION 5
-
-static time_t stoposd = 0;
-static int showosdmessage = 0;
-static char osdmessagetext[MESSAGE_SIZE];
-static char posbar[MESSAGE_SIZE];
-
-static int osdx = 0, osdy = 0;
-static int posbary = 2;
-
-static void osdmessage(int duration, const char *fmt, ...)
-{
- /* for outputting a centered string at the window bottom for a while */
- va_list ar;
- char m[MESSAGE_SIZE];
-
- va_start(ar, fmt);
- vsprintf(m, fmt, ar);
- va_end(ar);
- strcpy(osdmessagetext, m);
-
- showosdmessage = 1;
- stoposd = time(NULL) + duration;
- osdx = (screen_w - strlen(osdmessagetext)) / 2;
- posbar[0] = '\0';
-}
-
-static void osdpercent(int duration, int min, int max, int val,
- const char *desc, const char *unit)
-{
- /* prints a bar for setting values */
- float step;
- int where, i;
-
- step = (float)screen_w / (float)(max - min);
- where = (val - min) * step;
- osdmessage(duration, "%s: %i%s", desc, val, unit);
- posbar[0] = '|';
- posbar[screen_w - 1] = '|';
-
- for (i = 0; i < screen_w; i++) {
- if (i == where)
- posbar[i] = '#';
- else
- posbar[i] = '-';
- }
-
- if (where != 0)
- posbar[0] = '|';
-
- if (where != (screen_w - 1))
- posbar[screen_w - 1] = '|';
-
- posbar[screen_w] = '\0';
-}
-
-static int resize(void)
-{
- screen_w = caca_get_canvas_width(canvas);
- screen_h = caca_get_canvas_height(canvas);
-
- caca_free_dither(dither);
-
- dither = caca_create_dither(bpp, image_width, image_height,
- depth * image_width,
- rmask, gmask, bmask, amask);
- if (dither == NULL) {
- mp_msg(MSGT_VO, MSGL_FATAL, "vo_caca: caca_create_dither failed!\n");
- return ENOSYS;
- }
-
- /* Default libcaca features */
- caca_set_dither_antialias(dither, dither_antialias);
- caca_set_dither_charset(dither, dither_charset);
- caca_set_dither_color(dither, dither_color);
- caca_set_dither_algorithm(dither, dither_algo);
-
- return 0;
-}
-
-static int config(struct vo *vo, uint32_t width, uint32_t height,
- uint32_t d_width, uint32_t d_height, uint32_t flags,
- uint32_t format)
-{
- image_height = height;
- image_width = width;
- image_format = format;
-
- showosdmessage = 0;
- posbar[0] = '\0';
-
- return resize();
-}
-
-static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
-{
- assert(mpi->stride[0] == image_width * 3);
- caca_dither_bitmap(canvas, 0, 0, screen_w, screen_h, dither,
- mpi->planes[0]);
- return true;
-}
-
-static int draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h,
- int x, int y)
-{
- return 0;
-}
-
-static void flip_page(struct vo *vo)
-{
- if (showosdmessage) {
- if (time(NULL) >= stoposd) {
- showosdmessage = 0;
- if (*posbar)
- posbar[0] = '\0';
- } else {
- caca_put_str(canvas, osdx, osdy, osdmessagetext);
- if (*posbar)
- caca_put_str(canvas, 0, posbary, posbar);
- }
- }
-
- caca_refresh_display(display);
-}
-
-static void set_next_str(const char * const *list, const char **str,
- const char **msg)
-{
- int ind;
- for (ind = 0; list[ind]; ind += 2) {
- if (strcmp(list[ind], *str) == 0) {
- if (list[ind + 2] == NULL)
- ind = -2;
- *str = list[ind + 2];
- *msg = list[ind + 3];
- return;
- }
- }
-
- *str = list[0];
- *msg = list[1];
-}
-
-static const struct mp_keymap keysym_map[] = {
- {CACA_KEY_RETURN, KEY_ENTER}, {CACA_KEY_ESCAPE, KEY_ESC},
- {CACA_KEY_UP, KEY_DOWN}, {CACA_KEY_DOWN, KEY_DOWN},
- {CACA_KEY_LEFT, KEY_LEFT}, {CACA_KEY_RIGHT, KEY_RIGHT},
- {CACA_KEY_PAGEUP, KEY_PAGE_UP}, {CACA_KEY_PAGEDOWN, KEY_PAGE_DOWN},
- {CACA_KEY_HOME, KEY_HOME}, {CACA_KEY_END, KEY_END},
- {CACA_KEY_INSERT, KEY_INSERT}, {CACA_KEY_DELETE, KEY_DELETE},
- {CACA_KEY_BACKSPACE, KEY_BACKSPACE}, {CACA_KEY_TAB, KEY_TAB},
- {CACA_KEY_PAUSE, KEY_PAUSE},
- {CACA_KEY_F1, KEY_F+1}, {CACA_KEY_F2, KEY_F+2},
- {CACA_KEY_F3, KEY_F+3}, {CACA_KEY_F4, KEY_F+4},
- {CACA_KEY_F5, KEY_F+5}, {CACA_KEY_F6, KEY_F+6},
- {CACA_KEY_F7, KEY_F+7}, {CACA_KEY_F8, KEY_F+8},
- {CACA_KEY_F9, KEY_F+9}, {CACA_KEY_F10, KEY_F+10},
- {CACA_KEY_F11, KEY_F+11}, {CACA_KEY_F12, KEY_F+12},
- {CACA_KEY_F13, KEY_F+13}, {CACA_KEY_F14, KEY_F+14},
- {CACA_KEY_F15, KEY_F+15},
- {0, 0}
-};
-
-static void check_events(struct vo *vo)
-{
- caca_event_t cev;
- while (caca_get_event(display, CACA_EVENT_ANY, &cev, 0)) {
-
- switch (cev.type) {
- case CACA_EVENT_RESIZE:
- caca_refresh_display(display);
- resize();
- break;
- case CACA_EVENT_QUIT:
- mplayer_put_key(vo->key_fifo, KEY_CLOSE_WIN);
- break;
- case CACA_EVENT_MOUSE_MOTION:
- vo_mouse_movement(vo, cev.data.mouse.x, cev.data.mouse.y);
- break;
- case CACA_EVENT_MOUSE_PRESS:
- if (!vo_nomouse_input)
- mplayer_put_key(vo->key_fifo,
- (MOUSE_BTN0 + cev.data.mouse.button - 1) | MP_KEY_DOWN);
- break;
- case CACA_EVENT_MOUSE_RELEASE:
- if (!vo_nomouse_input)
- mplayer_put_key(vo->key_fifo,
- MOUSE_BTN0 + cev.data.mouse.button - 1);
- break;
- case CACA_EVENT_KEY_PRESS:
- {
- int key = cev.data.key.ch;
- int mpkey = lookup_keymap_table(keysym_map, key);
- const char *msg_name;
-
- if (mpkey)
- mplayer_put_key(vo->key_fifo, mpkey);
- else
- switch (key) {
- case 'd':
- case 'D':
- /* Toggle dithering algorithm */
- set_next_str(caca_get_dither_algorithm_list(dither),
- &dither_algo, &msg_name);
- caca_set_dither_algorithm(dither, dither_algo);
- osdmessage(MESSAGE_DURATION, "Using %s", msg_name);
- break;
-
- case 'a':
- case 'A':
- /* Toggle antialiasing method */
- set_next_str(caca_get_dither_antialias_list(dither),
- &dither_antialias, &msg_name);
- caca_set_dither_antialias(dither, dither_antialias);
- osdmessage(MESSAGE_DURATION, "Using %s", msg_name);
- break;
-
- case 'h':
- case 'H':
- /* Toggle charset method */
- set_next_str(caca_get_dither_charset_list(dither),
- &dither_charset, &msg_name);
- caca_set_dither_charset(dither, dither_charset);
- osdmessage(MESSAGE_DURATION, "Using %s", msg_name);
- break;
-
- case 'c':
- case 'C':
- /* Toggle color method */
- set_next_str(caca_get_dither_color_list(dither),
- &dither_color, &msg_name);
- caca_set_dither_color(dither, dither_color);
- osdmessage(MESSAGE_DURATION, "Using %s", msg_name);
- break;
-
- default:
- if (key <= 255)
- mplayer_put_key(vo->key_fifo, key);
- break;
- }
- }
- }
- }
-}
-
-static void uninit(struct vo *vo)
-{
- caca_free_dither(dither);
- dither = NULL;
- caca_free_display(display);
- caca_free_canvas(canvas);
-}
-
-static void draw_osd(struct vo *vo, struct osd_state *osd)
-{
- if (osd->progbar_type != -1)
- osdpercent(MESSAGE_DURATION, 0, 255, osd->progbar_value,
- sub_osd_names[osd->progbar_type], "");
-}
-
-static int preinit(struct vo *vo, const char *arg)
-{
- if (arg) {
- mp_msg(MSGT_VO, MSGL_ERR, "vo_caca: Unknown subdevice: %s\n", arg);
- return ENOSYS;
- }
-
- canvas = caca_create_canvas(0, 0);
- if (canvas == NULL) {
- mp_msg(MSGT_VO, MSGL_ERR, "vo_caca: failed to create canvas\n");
- return ENOSYS;
- }
-
- display = caca_create_display(canvas);
-
- if (display == NULL) {
- mp_msg(MSGT_VO, MSGL_ERR, "vo_caca: failed to create display\n");
- caca_free_canvas(canvas);
- return ENOSYS;
- }
-
- caca_set_display_title(display, "mpv");
-
- return 0;
-}
-
-static int query_format(uint32_t format)
-{
- if (format == IMGFMT_BGR24)
- return VFCAP_OSD | VFCAP_CSP_SUPPORTED;
-
- return 0;
-}
-
-static int control(struct vo *vo, uint32_t request, void *data)
-{
- switch (request) {
- case VOCTRL_QUERY_FORMAT:
- return query_format(*((uint32_t *)data));
- case VOCTRL_DRAW_IMAGE:
- return draw_image(vo, data);
- default:
- return VO_NOTIMPL;
- }
-}
-
-const struct vo_driver video_out_caca = {
- .is_new = false,
- .info = &(const vo_info_t) {
- "libcaca",
- "caca",
- "Pigeon <pigeon@pigeond.net>",
- ""
- },
- .preinit = preinit,
- .config = config,
- .control = control,
- .draw_slice = draw_slice,
- .draw_osd = draw_osd,
- .flip_page = flip_page,
- .check_events = check_events,
- .uninit = uninit,
-};
diff --git a/libvo/vo_corevideo.h b/libvo/vo_corevideo.h
deleted file mode 100644
index cfb86621bc..0000000000
--- a/libvo/vo_corevideo.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * CoreVideo video output driver
- *
- * Copyright (c) 2005 Nicolas Plourde <nicolasplourde@gmail.com>
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_VO_COREVIDEO_H
-#define MPLAYER_VO_COREVIDEO_H
-
-#import <QuartzCore/QuartzCore.h>
-
-#endif /* MPLAYER_VO_COREVIDEO_H */
diff --git a/libvo/vo_corevideo.m b/libvo/vo_corevideo.m
deleted file mode 100644
index 5116ab653c..0000000000
--- a/libvo/vo_corevideo.m
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * CoreVideo video output driver
- * Copyright (c) 2005 Nicolas Plourde <nicolasplourde@gmail.com>
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <assert.h>
-
-#import "vo_corevideo.h"
-
-// mplayer includes
-#import "fastmemcpy.h"
-#import "talloc.h"
-#import "video_out.h"
-#import "aspect.h"
-#import "sub/sub.h"
-#import "subopt-helper.h"
-
-#import "csputils.h"
-#import "libmpcodecs/vfcap.h"
-#import "libmpcodecs/mp_image.h"
-
-#import "gl_common.h"
-#import "gl_osd.h"
-#import "cocoa_common.h"
-
-struct quad {
- GLfloat lowerLeft[2];
- GLfloat lowerRight[2];
- GLfloat upperRight[2];
- GLfloat upperLeft[2];
-};
-
-struct priv {
- MPGLContext *mpglctx;
- OSType pixelFormat;
- unsigned int image_width;
- unsigned int image_height;
- struct mp_csp_details colorspace;
- int ass_border_x, ass_border_y;
-
- CVPixelBufferRef pixelBuffer;
- CVOpenGLTextureCacheRef textureCache;
- CVOpenGLTextureRef texture;
- struct quad *quad;
-
- struct mpgl_osd *osd;
-};
-
-static void resize(struct vo *vo, int width, int height)
-{
- struct priv *p = vo->priv;
- GL *gl = p->mpglctx->gl;
-
- gl->Viewport(0, 0, width, height);
- gl->MatrixMode(GL_PROJECTION);
- gl->LoadIdentity();
- p->ass_border_x = p->ass_border_y = 0;
- if (aspect_scaling()) {
- int new_w, new_h;
- GLdouble scale_x, scale_y;
-
- aspect(vo, &new_w, &new_h, A_WINZOOM);
- panscan_calc_windowed(vo);
- new_w += vo->panscan_x;
- new_h += vo->panscan_y;
- scale_x = (GLdouble)new_w / (GLdouble)width;
- scale_y = (GLdouble)new_h / (GLdouble)height;
- gl->Scaled(scale_x, scale_y, 1);
- p->ass_border_x = (vo->dwidth - new_w) / 2;
- p->ass_border_y = (vo->dheight - new_h) / 2;
- }
-
- gl->Ortho(0, p->image_width, p->image_height, 0, -1.0, 1.0);
- gl->MatrixMode(GL_MODELVIEW);
- gl->LoadIdentity();
-
- gl->Clear(GL_COLOR_BUFFER_BIT);
- vo->want_redraw = true;
-}
-
-static int init_gl(struct vo *vo, uint32_t d_width, uint32_t d_height)
-{
- struct priv *p = vo->priv;
- GL *gl = p->mpglctx->gl;
-
- const char *vendor = gl->GetString(GL_VENDOR);
- const char *version = gl->GetString(GL_VERSION);
- const char *renderer = gl->GetString(GL_RENDERER);
-
- mp_msg(MSGT_VO, MSGL_V, "[vo_corevideo] Running on OpenGL '%s' by '%s',"
- " version '%s'\n", renderer, vendor, version);
-
- gl->Disable(GL_BLEND);
- gl->Disable(GL_DEPTH_TEST);
- gl->DepthMask(GL_FALSE);
- gl->Disable(GL_CULL_FACE);
- gl->Enable(GL_TEXTURE_2D);
- gl->DrawBuffer(GL_BACK);
- gl->TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- if (!p->osd)
- p->osd = mpgl_osd_init(gl, true);
-
- resize(vo, d_width, d_height);
-
- gl->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- if (gl->SwapInterval)
- gl->SwapInterval(1);
- return 1;
-}
-
-static void release_cv_entities(struct vo *vo) {
- struct priv *p = vo->priv;
- CVPixelBufferRelease(p->pixelBuffer);
- p->pixelBuffer = NULL;
- CVOpenGLTextureRelease(p->texture);
- p->texture = NULL;
- CVOpenGLTextureCacheRelease(p->textureCache);
- p->textureCache = NULL;
-}
-
-static int config(struct vo *vo, uint32_t width, uint32_t height,
- uint32_t d_width, uint32_t d_height, uint32_t flags,
- uint32_t format)
-{
- struct priv *p = vo->priv;
- release_cv_entities(vo);
- p->image_width = width;
- p->image_height = height;
-
- 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);
-
- return 0;
-}
-
-static void check_events(struct vo *vo)
-{
- struct priv *p = vo->priv;
- int e = p->mpglctx->check_events(vo);
- if (e & VO_EVENT_RESIZE)
- resize(vo, vo->dwidth, vo->dheight);
-}
-
-static void prepare_texture(struct vo *vo)
-{
- struct priv *p = vo->priv;
- struct quad *q = p->quad;
- CVReturn error;
-
- CVOpenGLTextureRelease(p->texture);
- error = CVOpenGLTextureCacheCreateTextureFromImage(NULL,
- p->textureCache, p->pixelBuffer, 0, &p->texture);
- if(error != kCVReturnSuccess)
- mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL"
- " texture(%d)\n", error);
-
- CVOpenGLTextureGetCleanTexCoords(p->texture, q->lowerLeft, q->lowerRight,
- q->upperRight, q->upperLeft);
-}
-
-static void do_render(struct vo *vo)
-{
- struct priv *p = vo->priv;
- struct quad *q = p->quad;
- GL *gl = p->mpglctx->gl;
- prepare_texture(vo);
-
- float x0 = 0;
- float y0 = 0;
- float w = p->image_width;
- float h = p->image_height;
-
- // vertically flips the image
- y0 += h;
- h = -h;
-
- float xm = x0 + w;
- float ym = y0 + h;
-
- gl->Enable(CVOpenGLTextureGetTarget(p->texture));
- gl->BindTexture(
- CVOpenGLTextureGetTarget(p->texture),
- CVOpenGLTextureGetName(p->texture));
-
- gl->Begin(GL_QUADS);
- gl->TexCoord2fv(q->lowerLeft); gl->Vertex2f(x0, y0);
- gl->TexCoord2fv(q->upperLeft); gl->Vertex2f(x0, ym);
- gl->TexCoord2fv(q->upperRight); gl->Vertex2f(xm, ym);
- gl->TexCoord2fv(q->lowerRight); gl->Vertex2f(xm, y0);
- gl->End();
-
- gl->Disable(CVOpenGLTextureGetTarget(p->texture));
-}
-
-static void flip_page(struct vo *vo)
-{
- struct priv *p = vo->priv;
- p->mpglctx->swapGlBuffers(p->mpglctx);
- p->mpglctx->gl->Clear(GL_COLOR_BUFFER_BIT);
-}
-
-static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
-{
- struct priv *p = vo->priv;
- CVReturn error;
-
- if (!p->textureCache || !p->pixelBuffer) {
- error = CVOpenGLTextureCacheCreate(NULL, 0, vo_cocoa_cgl_context(vo),
- vo_cocoa_cgl_pixel_format(vo), 0, &p->textureCache);
- if(error != kCVReturnSuccess)
- mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL"
- " texture Cache(%d)\n", error);
-
- error = CVPixelBufferCreateWithBytes(NULL, mpi->width, mpi->height,
- p->pixelFormat, mpi->planes[0], mpi->width * mpi->bpp / 8,
- NULL, NULL, NULL, &p->pixelBuffer);
- if(error != kCVReturnSuccess)
- mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create Pixel"
- "Buffer(%d)\n", error);
- }
-
- do_render(vo);
- return VO_TRUE;
-}
-
-static int query_format(struct vo *vo, uint32_t format)
-{
- struct priv *p = vo->priv;
- const int flags = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW |
- VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN |
- VOCAP_NOSLICES;
- switch (format) {
- case IMGFMT_YUY2:
- p->pixelFormat = kYUVSPixelFormat;
- return flags;
-
- case IMGFMT_RGB24:
- p->pixelFormat = k24RGBPixelFormat;
- return flags;
-
- case IMGFMT_ARGB:
- p->pixelFormat = k32ARGBPixelFormat;
- return flags;
-
- case IMGFMT_BGRA:
- p->pixelFormat = k32BGRAPixelFormat;
- return flags;
- }
- return 0;
-}
-
-static void uninit(struct vo *vo)
-{
- struct priv *p = vo->priv;
- if (p->osd)
- mpgl_osd_destroy(p->osd);
- release_cv_entities(vo);
- mpgl_uninit(p->mpglctx);
-}
-
-
-static int preinit(struct vo *vo, const char *arg)
-{
- struct priv *p = vo->priv;
-
- *p = (struct priv) {
- .mpglctx = mpgl_init(GLTYPE_COCOA, vo),
- .colorspace = MP_CSP_DETAILS_DEFAULTS,
- .quad = talloc_ptrtype(p, p->quad),
- };
-
- return 0;
-}
-
-static void draw_osd(struct vo *vo, struct osd_state *osd)
-{
- struct priv *p = vo->priv;
- GL *gl = p->mpglctx->gl;
- assert(p->osd);
-
- gl->MatrixMode(GL_PROJECTION);
- gl->PushMatrix();
- gl->LoadIdentity();
- gl->Ortho(0, vo->dwidth, vo->dheight, 0, -1, 1);
-
- struct mp_osd_res res = {
- .w = vo->dwidth,
- .h = vo->dheight,
- .display_par = vo->monitor_par,
- .video_par = vo->aspdat.par,
- };
-
- if (aspect_scaling()) {
- res.ml = res.mr = p->ass_border_x;
- res.mt = res.mb = p->ass_border_y;
- }
-
- mpgl_osd_draw_legacy(p->osd, osd, res);
-
- gl->PopMatrix();
-}
-
-static CFStringRef get_cv_csp_matrix(struct vo *vo)
-{
- struct priv *p = vo->priv;
- switch (p->colorspace.format) {
- case MP_CSP_BT_601:
- return kCVImageBufferYCbCrMatrix_ITU_R_601_4;
- case MP_CSP_BT_709:
- return kCVImageBufferYCbCrMatrix_ITU_R_709_2;
- case MP_CSP_SMPTE_240M:
- return kCVImageBufferYCbCrMatrix_SMPTE_240M_1995;
- }
- return kCVImageBufferYCbCrMatrix_ITU_R_601_4;
-}
-
-static void set_yuv_colorspace(struct vo *vo)
-{
- struct priv *p = vo->priv;
- CVBufferSetAttachment(p->pixelBuffer,
- kCVImageBufferYCbCrMatrixKey, get_cv_csp_matrix(vo),
- kCVAttachmentMode_ShouldPropagate);
- vo->want_redraw = true;
-}
-
-static int get_image_fmt(struct vo *vo)
-{
- struct priv *p = vo->priv;
- switch (p->pixelFormat) {
- case kYUVSPixelFormat: return IMGFMT_YUY2;
- case k24RGBPixelFormat: return IMGFMT_RGB24;
- case k32ARGBPixelFormat: return IMGFMT_ARGB;
- case k32BGRAPixelFormat: return IMGFMT_BGRA;
- }
- mp_msg(MSGT_VO, MSGL_ERR, "[vo_corevideo] Failed to convert pixel format. "
- "Please contact the developers. PixelFormat: %d\n", p->pixelFormat);
- return -1;
-}
-
-static mp_image_t *get_screenshot(struct vo *vo)
-{
- int img_fmt = get_image_fmt(vo);
- if (img_fmt < 0) return NULL;
-
- struct priv *p = vo->priv;
- void *base = CVPixelBufferGetBaseAddress(p->pixelBuffer);
-
- size_t width = CVPixelBufferGetWidth(p->pixelBuffer);
- size_t height = CVPixelBufferGetHeight(p->pixelBuffer);
- size_t stride = CVPixelBufferGetBytesPerRow(p->pixelBuffer);
- size_t image_size = stride * height;
-
- mp_image_t *image = alloc_mpi(width, height, img_fmt);
- memcpy(image->planes[0], base, image_size);
- image->stride[0] = stride;
-
- image->display_w = vo->aspdat.prew;
- image->display_h = vo->aspdat.preh;
-
- mp_image_set_colorspace_details(image, &p->colorspace);
-
- return image;
-}
-
-static int control(struct vo *vo, uint32_t request, void *data)
-{
- struct priv *p = vo->priv;
- switch (request) {
- case VOCTRL_DRAW_IMAGE:
- return draw_image(vo, data);
- case VOCTRL_QUERY_FORMAT:
- return query_format(vo, *(uint32_t*)data);
- case VOCTRL_ONTOP:
- p->mpglctx->ontop(vo);
- return VO_TRUE;
- case VOCTRL_PAUSE:
- if (!p->mpglctx->pause)
- break;
- p->mpglctx->pause(vo);
- return VO_TRUE;
- case VOCTRL_RESUME:
- if (!p->mpglctx->resume)
- break;
- p->mpglctx->resume(vo);
- return VO_TRUE;
- case VOCTRL_FULLSCREEN:
- p->mpglctx->fullscreen(vo);
- resize(vo, vo->dwidth, vo->dheight);
- return VO_TRUE;
- case VOCTRL_GET_PANSCAN:
- return VO_TRUE;
- case VOCTRL_SET_PANSCAN:
- resize(vo, vo->dwidth, vo->dheight);
- return VO_TRUE;
- case VOCTRL_UPDATE_SCREENINFO:
- p->mpglctx->update_xinerama_info(vo);
- return VO_TRUE;
- case VOCTRL_REDRAW_FRAME:
- do_render(vo);
- return VO_TRUE;
- case VOCTRL_SET_YUV_COLORSPACE:
- p->colorspace.format = ((struct mp_csp_details *)data)->format;
- set_yuv_colorspace(vo);
- return VO_TRUE;
- case VOCTRL_GET_YUV_COLORSPACE:
- *(struct mp_csp_details *)data = p->colorspace;
- return VO_TRUE;
- case VOCTRL_SCREENSHOT: {
- struct voctrl_screenshot_args *args = data;
- if (args->full_window)
- args->out_image = glGetWindowScreenshot(p->mpglctx->gl);
- else
- args->out_image = get_screenshot(vo);
- return VO_TRUE;
- }
- }
- return VO_NOTIMPL;
-}
-
-const struct vo_driver video_out_corevideo = {
- .is_new = true,
- .info = &(const vo_info_t) {
- "Mac OS X Core Video",
- "corevideo",
- "Nicolas Plourde <nicolas.plourde@gmail.com> and others",
- ""
- },
- .preinit = preinit,
- .config = config,
- .control = control,
- .draw_osd = draw_osd,
- .flip_page = flip_page,
- .check_events = check_events,
- .uninit = uninit,
- .priv_size = sizeof(struct priv),
-};
diff --git a/libvo/vo_direct3d.c b/libvo/vo_direct3d.c
deleted file mode 100644
index 294a101ffe..0000000000
--- a/libvo/vo_direct3d.c
+++ /dev/null
@@ -1,2101 +0,0 @@
-/*
- * Copyright (c) 2008 Georgi Petrov (gogothebee) <gogothebee@gmail.com>
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <windows.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <stdbool.h>
-#include <assert.h>
-#include <d3d9.h>
-#include "config.h"
-#include "options.h"
-#include "subopt-helper.h"
-#include "talloc.h"
-#include "video_out.h"
-#include "libmpcodecs/vfcap.h"
-#include "csputils.h"
-#include "libmpcodecs/mp_image.h"
-#include "libmpcodecs/img_format.h"
-#include "fastmemcpy.h"
-#include "mp_msg.h"
-#include "aspect.h"
-#include "w32_common.h"
-#include "libavutil/common.h"
-#include "sub/sub.h"
-#include "bitmap_packer.h"
-
-// shaders generated by fxc.exe from d3d_shader_yuv.hlsl
-#include "d3d_shader_yuv.h"
-#include "d3d_shader_yuv_2ch.h"
-
-
-// TODO: beg someone to add this (there is already IMGFMT_Y8)
-// equals MAKEFOURCC('Y', '1', '6', ' ')
-#define IMGFMT_Y16 0x20363159
-#define IMGFMT_A8Y8 MAKEFOURCC('A', '8', 'Y', '8')
-
-#define IMGFMT_IS_Y(x) ((x) == IMGFMT_Y8 || (x) == IMGFMT_Y16 || (x) == IMGFMT_A8Y8)
-#define IMGFMT_Y_DEPTH(x) ((x) == IMGFMT_Y8 ? 8 : 16)
-
-#define DEVTYPE D3DDEVTYPE_HAL
-//#define DEVTYPE D3DDEVTYPE_REF
-
-#define D3DFVF_OSD_VERTEX (D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_DIFFUSE)
-
-typedef struct {
- float x, y, z;
- D3DCOLOR color;
- float tu, tv;
-} vertex_osd;
-
-#define D3DFVF_VIDEO_VERTEX (D3DFVF_XYZ | D3DFVF_TEX3)
-
-typedef struct {
- float x, y, z;
- // pairs of texture coordinates for up to 3 planes
- float t[3][2];
-} vertex_video;
-
-
-struct d3dtex {
- // user-requested size
- int w, h;
- // allocated texture size
- int tex_w, tex_h;
- // D3DPOOL_SYSTEMMEM (or others) texture:
- // - can be locked in order to write (and even read) data
- // - can _not_ (probably) be used as texture for rendering
- // This is always non-NULL if d3dtex_allocate succeeds.
- IDirect3DTexture9 *system;
- // D3DPOOL_DEFAULT texture:
- // - can't be locked (Probably.)
- // - must be used for rendering
- // This will be NULL on systems with device_texture_sys != 0.
- IDirect3DTexture9 *device;
-};
-
-struct texplane {
- int bytes_per_pixel;
- int bits_per_pixel;
- // chroma shifts
- // e.g. get the plane's width in pixels with (priv->src_width >> shift_x)
- int shift_x, shift_y;
- D3DFORMAT d3d_format;
- struct d3dtex texture;
- // temporary locking during uploading the frame (e.g. for draw_slice)
- D3DLOCKED_RECT locked_rect;
- // value used to clear the image with memset (YUV chroma planes do not use
- // the value 0 for this)
- uint8_t clearval;
-};
-
-struct osdpart {
- enum sub_bitmap_format format;
- int bitmap_id, bitmap_pos_id;
- struct d3dtex texture;
- int num_vertices;
- vertex_osd *vertices;
- struct bitmap_packer *packer;
-};
-
-/* Global variables "priv" structure. I try to keep their count low.
- */
-typedef struct d3d_priv {
- int opt_prefer_stretchrect;
- int opt_disable_textures;
- int opt_disable_stretchrect;
- int opt_disable_shaders;
- int opt_only_8bit;
- int opt_disable_osd;
- int opt_disable_texture_align;
- // debugging
- int opt_force_power_of_2;
- int opt_texture_memory;
- int opt_swap_discard;
- int opt_exact_backbuffer;
- int opt_16bit_textures;
-
- struct vo *vo;
-
- int is_clear_needed; /**< 1 = Clear the backbuffer before StretchRect
- 0 = (default) Don't clear it */
- D3DLOCKED_RECT locked_rect; /**< The locked offscreen surface */
- RECT fs_movie_rect; /**< Rect (upscaled) of the movie when displayed
- in fullscreen */
- RECT fs_panscan_rect; /**< PanScan source surface cropping in
- fullscreen */
- int src_width; /**< Source (movie) width */
- int src_height; /**< Source (movie) heigth */
- struct mp_osd_res osd_res;
- int image_format; /**< mplayer image format */
- bool use_textures; /**< use 3D texture rendering, instead of
- StretchRect */
- bool use_shaders; /**< use shader for YUV color conversion
- (or possibly for RGB video equalizers) */
- bool use_2ch_hack; /**< 2 byte YUV formats use 2 channel hack */
-
- int plane_count;
- struct texplane planes[3];
-
- IDirect3DPixelShader9 *pixel_shader;
- const BYTE *pixel_shader_data;
-
- D3DFORMAT movie_src_fmt; /**< Movie colorspace format (depends on
- the movie's codec) */
- D3DFORMAT desktop_fmt; /**< Desktop (screen) colorspace format.
- Usually XRGB */
-
- HANDLE d3d9_dll; /**< d3d9 Library HANDLE */
- IDirect3D9 * (WINAPI *pDirect3DCreate9)(UINT); /**< pointer to Direct3DCreate9 function */
-
- LPDIRECT3D9 d3d_handle; /**< Direct3D Handle */
- LPDIRECT3DDEVICE9 d3d_device; /**< The Direct3D Adapter */
- bool d3d_in_scene; /**< BeginScene was called, EndScene not */
- IDirect3DSurface9 *d3d_surface; /**< Offscreen Direct3D Surface. MPlayer
- renders inside it. Uses colorspace
- priv->movie_src_fmt */
- IDirect3DSurface9 *d3d_backbuf; /**< Video card's back buffer (used to
- display next frame) */
- int cur_backbuf_width; /**< Current backbuffer width */
- int cur_backbuf_height; /**< Current backbuffer height */
- int device_caps_power2_only; /**< 1 = texture sizes have to be power 2
- 0 = texture sizes can be anything */
- int device_caps_square_only; /**< 1 = textures have to be square
- 0 = textures do not have to be square */
- int device_texture_sys; /**< 1 = device can texture from system memory
- 0 = device requires shadow */
- int max_texture_width; /**< from the device capabilities */
- int max_texture_height; /**< from the device capabilities */
-
- D3DMATRIX d3d_colormatrix;
- float d3d_depth_vector[4];
- struct mp_csp_details colorspace;
- struct mp_csp_equalizer video_eq;
-
- struct osdpart *osd[MAX_OSD_PARTS];
-} d3d_priv;
-
-struct fmt_entry {
- const unsigned int mplayer_fmt; /**< Given by MPlayer */
- const D3DFORMAT fourcc; /**< Required by D3D's test function */
-};
-
-/* Map table from reported MPlayer format to the required
- fourcc. This is needed to perform the format query. */
-
-static const struct fmt_entry fmt_table[] = {
- // planar YUV
- {IMGFMT_YV12, MAKEFOURCC('Y','V','1','2')},
- {IMGFMT_I420, MAKEFOURCC('I','4','2','0')},
- {IMGFMT_IYUV, MAKEFOURCC('I','Y','U','V')},
- {IMGFMT_YVU9, MAKEFOURCC('Y','V','U','9')},
- // packed YUV
- {IMGFMT_YUY2, D3DFMT_YUY2},
- {IMGFMT_UYVY, D3DFMT_UYVY},
- // packed RGB
- {IMGFMT_BGR32, D3DFMT_X8R8G8B8},
- {IMGFMT_RGB32, D3DFMT_X8B8G8R8},
- {IMGFMT_BGR24, D3DFMT_R8G8B8}, //untested
- {IMGFMT_BGR16, D3DFMT_R5G6B5},
- {IMGFMT_BGR15, D3DFMT_X1R5G5B5},
- {IMGFMT_BGR8 , D3DFMT_R3G3B2}, //untested
- // grayscale (can be considered both packed and planar)
- {IMGFMT_Y8, D3DFMT_L8},
- {IMGFMT_Y16, D3DFMT_L16},
- {IMGFMT_A8Y8, D3DFMT_A8L8},
- {0},
-};
-
-static const D3DFORMAT osd_fmt_table[SUBBITMAP_COUNT] = {
- [SUBBITMAP_LIBASS] = D3DFMT_A8,
- [SUBBITMAP_RGBA] = D3DFMT_A8R8G8B8,
-};
-static const bool osd_fmt_supported[SUBBITMAP_COUNT] = {
- [SUBBITMAP_LIBASS] = true,
- [SUBBITMAP_RGBA] = true,
-};
-
-
-static void update_colorspace(d3d_priv *priv);
-static void d3d_clear_video_textures(d3d_priv *priv);
-static bool resize_d3d(d3d_priv *priv);
-static uint32_t d3d_draw_frame(d3d_priv *priv);
-static int draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h,
- int x, int y);
-static void uninit(struct vo *vo);
-static void flip_page(struct vo *vo);
-static mp_image_t *get_screenshot(d3d_priv *priv);
-static mp_image_t *get_window_screenshot(d3d_priv *priv);
-
-
-static void d3d_matrix_identity(D3DMATRIX *m)
-{
- memset(m, 0, sizeof(D3DMATRIX));
- m->_11 = m->_22 = m->_33 = m->_44 = 1.0f;
-}
-
-static void d3d_matrix_ortho(D3DMATRIX *m, float left, float right,
- float bottom, float top)
-{
- d3d_matrix_identity(m);
- m->_11 = 2.0f / (right - left);
- m->_22 = 2.0f / (top - bottom);
- m->_33 = 1.0f;
- m->_41 = -(right + left) / (right - left);
- m->_42 = -(top + bottom) / (top - bottom);
- m->_43 = 0;
- m->_44 = 1.0f;
-}
-
-/****************************************************************************
- * *
- * *
- * *
- * Direct3D specific implementation functions *
- * *
- * *
- * *
- ****************************************************************************/
-
-static bool d3d_begin_scene(d3d_priv *priv)
-{
- if (!priv->d3d_in_scene) {
- if (FAILED(IDirect3DDevice9_BeginScene(priv->d3d_device))) {
- mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>BeginScene failed.\n");
- return false;
- }
- priv->d3d_in_scene = true;
- }
- return true;
-}
-
-/** @brief Calculate scaled fullscreen movie rectangle with
- * preserved aspect ratio.
- */
-static void calc_fs_rect(d3d_priv *priv)
-{
- struct mp_rect src_rect;
- struct mp_rect dst_rect;
- vo_get_src_dst_rects(priv->vo, &src_rect, &dst_rect, &priv->osd_res);
-
- priv->fs_movie_rect.left = dst_rect.x0;
- priv->fs_movie_rect.right = dst_rect.x1;
- priv->fs_movie_rect.top = dst_rect.y0;
- priv->fs_movie_rect.bottom = dst_rect.y1;
- priv->fs_panscan_rect.left = src_rect.x0;
- priv->fs_panscan_rect.right = src_rect.x1;
- priv->fs_panscan_rect.top = src_rect.y0;
- priv->fs_panscan_rect.bottom = src_rect.y1;
-
- mp_msg(MSGT_VO, MSGL_V,
- "<vo_direct3d>Video rectangle: t: %ld, l: %ld, r: %ld, b:%ld\n",
- priv->fs_movie_rect.top, priv->fs_movie_rect.left,
- priv->fs_movie_rect.right, priv->fs_movie_rect.bottom);
-
- /* The backbuffer should be cleared before next StretchRect. This is
- * necessary because our new draw area could be smaller than the
- * previous one used by StretchRect and without it, leftovers from the
- * previous frame will be left. */
- priv->is_clear_needed = 1;
-}
-
-// Adjust the texture size *width/*height to fit the requirements of the D3D
-// device. The texture size is only increased.
-static void d3d_fix_texture_size(d3d_priv *priv, int *width, int *height)
-{
- int tex_width = *width;
- int tex_height = *height;
-
- // avoid nasty special cases with 0-sized textures and texture sizes
- tex_width = FFMAX(tex_width, 1);
- tex_height = FFMAX(tex_height, 1);
-
- if (priv->device_caps_power2_only) {
- tex_width = 1;
- tex_height = 1;
- while (tex_width < *width) tex_width <<= 1;
- while (tex_height < *height) tex_height <<= 1;
- }
- if (priv->device_caps_square_only)
- /* device only supports square textures */
- tex_width = tex_height = FFMAX(tex_width, tex_height);
- // better round up to a multiple of 16
- if (!priv->opt_disable_texture_align) {
- tex_width = (tex_width + 15) & ~15;
- tex_height = (tex_height + 15) & ~15;
- }
-
- *width = tex_width;
- *height = tex_height;
-}
-
-static void d3dtex_release(d3d_priv *priv, struct d3dtex *tex)
-{
- if (tex->system)
- IDirect3DTexture9_Release(tex->system);
- tex->system = NULL;
-
- if (tex->device)
- IDirect3DTexture9_Release(tex->device);
- tex->device = NULL;
-
- tex->tex_w = tex->tex_h = 0;
-}
-
-static bool d3dtex_allocate(d3d_priv *priv, struct d3dtex *tex, D3DFORMAT fmt,
- int w, int h)
-{
- d3dtex_release(priv, tex);
-
- tex->w = w;
- tex->h = h;
-
- int tw = w, th = h;
- d3d_fix_texture_size(priv, &tw, &th);
-
- int memtype = D3DPOOL_SYSTEMMEM;
- switch (priv->opt_texture_memory) {
- case 1: memtype = D3DPOOL_MANAGED; break;
- case 2: memtype = D3DPOOL_DEFAULT; break;
- }
-
- if (FAILED(IDirect3DDevice9_CreateTexture(priv->d3d_device, tw, th, 1,
- D3DUSAGE_DYNAMIC, fmt, memtype, &tex->system, NULL)))
- {
- mp_msg(MSGT_VO, MSGL_ERR,
- "<vo_direct3d>Allocating %dx%d texture in system RAM failed.\n",
- w, h);
- goto error_exit;
- }
-
- if (!priv->device_texture_sys && !priv->opt_texture_memory) {
- if (FAILED(IDirect3DDevice9_CreateTexture(priv->d3d_device, tw, th, 1,
- D3DUSAGE_DYNAMIC, fmt, D3DPOOL_DEFAULT, &tex->device, NULL)))
- {
- mp_msg(MSGT_VO, MSGL_ERR,
- "<vo_direct3d>Allocating %dx%d texture in video RAM failed.\n",
- w, h);
- goto error_exit;
- }
- }
-
- tex->tex_w = tw;
- tex->tex_h = th;
-
- return true;
-
-error_exit:
- d3dtex_release(priv, tex);
- return false;
-}
-
-static IDirect3DBaseTexture9 *d3dtex_get_render_texture(d3d_priv *priv,
- struct d3dtex *tex)
-{
- return (IDirect3DBaseTexture9 *)(tex->device ? tex->device : tex->system);
-}
-
-// Copy system texture contents to device texture.
-static bool d3dtex_update(d3d_priv *priv, struct d3dtex *tex)
-{
- if (!tex->device)
- return true;
- return !FAILED(IDirect3DDevice9_UpdateTexture(priv->d3d_device,
- (IDirect3DBaseTexture9 *)tex->system,
- (IDirect3DBaseTexture9 *)tex->device));
-}
-
-static void d3d_unlock_video_objects(d3d_priv *priv)
-{
- bool any_failed = false;
-
- if (priv->locked_rect.pBits) {
- if (FAILED(IDirect3DSurface9_UnlockRect(priv->d3d_surface)))
- any_failed = true;
- }
- priv->locked_rect.pBits = NULL;
-
- for (int n = 0; n < priv->plane_count; n++) {
- struct texplane *plane = &priv->planes[n];
- if (plane->locked_rect.pBits) {
- if (FAILED(IDirect3DTexture9_UnlockRect(plane->texture.system, 0)))
- any_failed = true;
- }
- plane->locked_rect.pBits = NULL;
- }
-
- if (any_failed) {
- mp_msg(MSGT_VO, MSGL_V,
- "<vo_direct3d>Unlocking video objects failed.\n");
- }
-}
-
-// Free video surface/textures, shaders, etc.
-static void d3d_destroy_video_objects(d3d_priv *priv)
-{
- d3d_unlock_video_objects(priv);
-
- if (priv->d3d_surface)
- IDirect3DSurface9_Release(priv->d3d_surface);
- priv->d3d_surface = NULL;
-
- for (int n = 0; n < priv->plane_count; n++) {
- d3dtex_release(priv, &priv->planes[n].texture);
- }
-
- if (priv->pixel_shader)
- IDirect3DPixelShader9_Release(priv->pixel_shader);
- priv->pixel_shader = NULL;
-}
-
-/** @brief Destroy D3D Offscreen and Backbuffer surfaces.
- */
-static void destroy_d3d_surfaces(d3d_priv *priv)
-{
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>destroy_d3d_surfaces called.\n");
-
- d3d_destroy_video_objects(priv);
-
- for (int n = 0; n < MAX_OSD_PARTS; n++) {
- struct osdpart *osd = priv->osd[n];
- d3dtex_release(priv, &osd->texture);
- osd->bitmap_id = osd->bitmap_pos_id = -1;
- }
-
- if (priv->d3d_backbuf)
- IDirect3DSurface9_Release(priv->d3d_backbuf);
- priv->d3d_backbuf = NULL;
-
- priv->d3d_in_scene = false;
-}
-
-// Allocate video surface or textures, and create shaders if needed.
-static bool d3d_configure_video_objects(d3d_priv *priv)
-{
- int n;
- bool need_clear = false;
-
- assert(priv->image_format != 0);
-
- if (priv->use_textures) {
- for (n = 0; n < priv->plane_count; n++) {
- struct texplane *plane = &priv->planes[n];
-
- if (!plane->texture.system) {
- if (!d3dtex_allocate(priv,
- &plane->texture,
- plane->d3d_format,
- priv->src_width >> plane->shift_x,
- priv->src_height >> plane->shift_y))
- {
- mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Allocating plane %d"
- " failed.\n", n);
- return false;
- }
-
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Allocated plane %d:"
- " %d bit, shift=%d/%d size=%d/%d (%d/%d).\n", n,
- plane->bits_per_pixel,
- plane->shift_x, plane->shift_y,
- plane->texture.w, plane->texture.h,
- plane->texture.tex_w, plane->texture.tex_h);
-
- need_clear = true;
- }
- }
-
- if (need_clear)
- d3d_clear_video_textures(priv);
-
- if (priv->pixel_shader_data) {
- if (!priv->pixel_shader &&
- FAILED(IDirect3DDevice9_CreatePixelShader(priv->d3d_device,
- (DWORD *)priv->pixel_shader_data, &priv->pixel_shader)))
- {
- mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Failed to create "
- "YUV conversion pixel shader.\n");
- return false;
- }
- }
-
- } else {
-
- if (!priv->d3d_surface &&
- FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(
- priv->d3d_device, priv->src_width, priv->src_height,
- priv->movie_src_fmt, D3DPOOL_DEFAULT, &priv->d3d_surface, NULL)))
- {
- mp_msg(MSGT_VO, MSGL_ERR,
- "<vo_direct3d>Allocating offscreen surface failed.\n");
- return false;
- }
- }
-
- return true;
-}
-
-static bool d3d_lock_video_textures(d3d_priv *priv)
-{
- for (int n = 0; n < priv->plane_count; n++) {
- struct texplane *plane = &priv->planes[n];
-
- if (!plane->locked_rect.pBits) {
- if (FAILED(IDirect3DTexture9_LockRect(plane->texture.system, 0,
- &plane->locked_rect, NULL, 0)))
- {
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Texture lock failure.\n");
- d3d_unlock_video_objects(priv);
- return false;
- }
- }
- }
-
- return true;
-}
-
-static void d3d_clear_video_textures(d3d_priv *priv)
-{
- if (!d3d_lock_video_textures(priv))
- return;
-
- for (int n = 0; n < priv->plane_count; n++) {
- struct texplane *plane = &priv->planes[n];
- memset(plane->locked_rect.pBits, plane->clearval,
- plane->locked_rect.Pitch * plane->texture.tex_h);
- }
-
- d3d_unlock_video_objects(priv);
-}
-
-// Recreate and initialize D3D objects if necessary. The amount of work that
-// needs to be done can be quite different: it could be that full initialization
-// is required, or that some objects need to be created, or that nothing is
-// done.
-static bool create_d3d_surfaces(d3d_priv *priv)
-{
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>create_d3d_surfaces called.\n");
-
- if (!priv->d3d_backbuf &&
- FAILED(IDirect3DDevice9_GetBackBuffer(priv->d3d_device, 0, 0,
- D3DBACKBUFFER_TYPE_MONO,
- &priv->d3d_backbuf))) {
- mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Allocating backbuffer failed.\n");
- return 0;
- }
-
- if (!d3d_configure_video_objects(priv))
- return 0;
-
- /* setup default renderstate */
- IDirect3DDevice9_SetRenderState(priv->d3d_device,
- D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
- IDirect3DDevice9_SetRenderState(priv->d3d_device,
- D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
- IDirect3DDevice9_SetRenderState(priv->d3d_device,
- D3DRS_ALPHAFUNC, D3DCMP_GREATER);
- IDirect3DDevice9_SetRenderState(priv->d3d_device,
- D3DRS_ALPHAREF, (DWORD)0x0);
- IDirect3DDevice9_SetRenderState(priv->d3d_device,
- D3DRS_LIGHTING, FALSE);
-
- // we use up to 3 samplers for up to 3 YUV planes
- for (int n = 0; n < 3; n++) {
- IDirect3DDevice9_SetSamplerState(priv->d3d_device, n, D3DSAMP_MINFILTER,
- D3DTEXF_LINEAR);
- IDirect3DDevice9_SetSamplerState(priv->d3d_device, n, D3DSAMP_MAGFILTER,
- D3DTEXF_LINEAR);
- IDirect3DDevice9_SetSamplerState(priv->d3d_device, n, D3DSAMP_ADDRESSU,
- D3DTADDRESS_CLAMP);
- IDirect3DDevice9_SetSamplerState(priv->d3d_device, n, D3DSAMP_ADDRESSV,
- D3DTADDRESS_CLAMP);
- }
-
- return 1;
-}
-
-static bool init_d3d(d3d_priv *priv)
-{
- D3DDISPLAYMODE disp_mode;
- D3DCAPS9 disp_caps;
- DWORD texture_caps;
- DWORD dev_caps;
-
- priv->d3d_handle = priv->pDirect3DCreate9(D3D_SDK_VERSION);
- if (!priv->d3d_handle) {
- mp_msg(MSGT_VO, MSGL_ERR,
- "<vo_direct3d>Initializing Direct3D failed.\n");
- return false;
- }
-
- if (FAILED(IDirect3D9_GetAdapterDisplayMode(priv->d3d_handle,
- D3DADAPTER_DEFAULT,
- &disp_mode))) {
- mp_msg(MSGT_VO, MSGL_ERR,
- "<vo_direct3d>Reading display mode failed.\n");
- return false;
- }
-
- priv->desktop_fmt = disp_mode.Format;
- priv->cur_backbuf_width = disp_mode.Width;
- priv->cur_backbuf_height = disp_mode.Height;
-
- mp_msg(MSGT_VO, MSGL_V,
- "<vo_direct3d>Setting backbuffer dimensions to (%dx%d).\n",
- disp_mode.Width, disp_mode.Height);
-
- if (FAILED(IDirect3D9_GetDeviceCaps(priv->d3d_handle,
- D3DADAPTER_DEFAULT,
- DEVTYPE,
- &disp_caps)))
- {
- mp_msg(MSGT_VO, MSGL_ERR,
- "<vo_direct3d>Reading display capabilities failed.\n");
- return false;
- }
-
- /* Store relevant information reguarding caps of device */
- texture_caps = disp_caps.TextureCaps;
- dev_caps = disp_caps.DevCaps;
- priv->device_caps_power2_only = (texture_caps & D3DPTEXTURECAPS_POW2) &&
- !(texture_caps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
- priv->device_caps_square_only = texture_caps & D3DPTEXTURECAPS_SQUAREONLY;
- priv->device_texture_sys = dev_caps & D3DDEVCAPS_TEXTURESYSTEMMEMORY;
- priv->max_texture_width = disp_caps.MaxTextureWidth;
- priv->max_texture_height = disp_caps.MaxTextureHeight;
-
- if (priv->opt_force_power_of_2)
- priv->device_caps_power2_only = 1;
-
- mp_msg(MSGT_VO, MSGL_V,
- "<vo_direct3d>device_caps_power2_only %d, device_caps_square_only %d\n"
- "<vo_direct3d>device_texture_sys %d\n"
- "<vo_direct3d>max_texture_width %d, max_texture_height %d\n",
- priv->device_caps_power2_only, priv->device_caps_square_only,
- priv->device_texture_sys, priv->max_texture_width,
- priv->max_texture_height);
-
- return true;
-}
-
-/** @brief Fill D3D Presentation parameters
- */
-static void fill_d3d_presentparams(d3d_priv *priv,
- D3DPRESENT_PARAMETERS *present_params)
-{
- /* Prepare Direct3D initialization parameters. */
- memset(present_params, 0, sizeof(D3DPRESENT_PARAMETERS));
- present_params->Windowed = TRUE;
- present_params->SwapEffect =
- priv->opt_swap_discard ? D3DSWAPEFFECT_DISCARD : D3DSWAPEFFECT_COPY;
- present_params->Flags = D3DPRESENTFLAG_VIDEO;
- present_params->hDeviceWindow = priv->vo->w32->window;
- present_params->BackBufferWidth = priv->cur_backbuf_width;
- present_params->BackBufferHeight = priv->cur_backbuf_height;
- present_params->MultiSampleType = D3DMULTISAMPLE_NONE;
- present_params->PresentationInterval = D3DPRESENT_INTERVAL_ONE;
- present_params->BackBufferFormat = priv->desktop_fmt;
- present_params->BackBufferCount = 1;
- present_params->EnableAutoDepthStencil = FALSE;
-}
-
-
-// Create a new backbuffer. Create or Reset the D3D device.
-static bool change_d3d_backbuffer(d3d_priv *priv)
-{
- D3DPRESENT_PARAMETERS present_params;
-
- int window_w = priv->vo->dwidth;
- int window_h = priv->vo->dheight;
-
- /* Grow the backbuffer in the required dimension. */
- if (window_w > priv->cur_backbuf_width)
- priv->cur_backbuf_width = window_w;
-
- if (window_h > priv->cur_backbuf_height)
- priv->cur_backbuf_height = window_h;
-
- if (priv->opt_exact_backbuffer) {
- priv->cur_backbuf_width = window_w;
- priv->cur_backbuf_height = window_h;
- }
-
- /* The grown backbuffer dimensions are ready and fill_d3d_presentparams
- * will use them, so we can reset the device.
- */
- fill_d3d_presentparams(priv, &present_params);
-
- if (!priv->d3d_device) {
- if (FAILED(IDirect3D9_CreateDevice(priv->d3d_handle,
- D3DADAPTER_DEFAULT,
- DEVTYPE, priv->vo->w32->window,
- D3DCREATE_SOFTWARE_VERTEXPROCESSING
- | D3DCREATE_FPU_PRESERVE,
- &present_params, &priv->d3d_device)))
- {
- mp_msg(MSGT_VO, MSGL_V,
- "<vo_direct3d>Creating Direct3D device failed.\n");
- return 0;
- }
- } else {
- if (FAILED(IDirect3DDevice9_Reset(priv->d3d_device, &present_params))) {
- mp_msg(MSGT_VO, MSGL_ERR,
- "<vo_direct3d>Reseting Direct3D device failed.\n");
- return 0;
- }
- }
-
- mp_msg(MSGT_VO, MSGL_V,
- "<vo_direct3d>New backbuffer (%dx%d), VO (%dx%d)\n",
- present_params.BackBufferWidth, present_params.BackBufferHeight,
- window_w, window_h);
-
- return 1;
-}
-
-/** @brief Reconfigure the whole Direct3D. Called only
- * when the video adapter becomes uncooperative. ("Lost" devices)
- * @return 1 on success, 0 on failure
- */
-static int reconfigure_d3d(d3d_priv *priv)
-{
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>reconfigure_d3d called.\n");
-
- destroy_d3d_surfaces(priv);
-
- if (priv->d3d_device)
- IDirect3DDevice9_Release(priv->d3d_device);
- priv->d3d_device = NULL;
-
- // Force complete destruction of the D3D state.
- // Note: this step could be omitted. The resize_d3d call below would detect
- // that d3d_device is NULL, and would properly recreate it. I'm not sure why
- // the following code to release and recreate the d3d_handle exists.
- if (priv->d3d_handle)
- IDirect3D9_Release(priv->d3d_handle);
- priv->d3d_handle = NULL;
- if (!init_d3d(priv))
- return 0;
-
- // Proper re-initialization.
- if (!resize_d3d(priv))
- return 0;
-
- return 1;
-}
-
-// Resize Direct3D context on window resize.
-// This function also is called when major initializations need to be done.
-static bool resize_d3d(d3d_priv *priv)
-{
- D3DVIEWPORT9 vp = {0, 0, priv->vo->dwidth, priv->vo->dheight, 0, 1};
-
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>resize_d3d called.\n");
-
- /* Make sure that backbuffer is large enough to accomodate the new
- viewport dimensions. Grow it if necessary. */
-
- bool backbuf_resize = priv->vo->dwidth > priv->cur_backbuf_width ||
- priv->vo->dheight > priv->cur_backbuf_height;
-
- if (priv->opt_exact_backbuffer) {
- backbuf_resize = priv->vo->dwidth != priv->cur_backbuf_width ||
- priv->vo->dheight != priv->cur_backbuf_height;
- }
-
- if (backbuf_resize || !priv->d3d_device)
- {
- destroy_d3d_surfaces(priv);
- if (!change_d3d_backbuffer(priv))
- return 0;
- }
-
- if (!priv->d3d_device)
- return 1;
-
- if (!create_d3d_surfaces(priv))
- return 0;
-
- if (FAILED(IDirect3DDevice9_SetViewport(priv->d3d_device, &vp))) {
- mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Setting viewport failed.\n");
- return 0;
- }
-
- // so that screen coordinates map to D3D ones
- D3DMATRIX view;
- d3d_matrix_ortho(&view, 0.5f, vp.Width + 0.5f, vp.Height + 0.5f, 0.5f);
- IDirect3DDevice9_SetTransform(priv->d3d_device, D3DTS_VIEW, &view);
-
- calc_fs_rect(priv);
-
- priv->vo->want_redraw = true;
-
- return 1;
-}
-
-/** @brief Uninitialize Direct3D and close the window.
- */
-static void uninit_d3d(d3d_priv *priv)
-{
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>uninit_d3d called.\n");
-
- destroy_d3d_surfaces(priv);
-
- if (priv->d3d_device)
- IDirect3DDevice9_Release(priv->d3d_device);
- priv->d3d_device = NULL;
-
- if (priv->d3d_handle) {
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Stopping Direct3D.\n");
- IDirect3D9_Release(priv->d3d_handle);
- }
- priv->d3d_handle = NULL;
-}
-
-static uint32_t d3d_upload_and_render_frame_texture(d3d_priv *priv,
- mp_image_t *mpi)
-{
- if (!(mpi->flags & MP_IMGFLAG_DRAW_CALLBACK))
- draw_slice(priv->vo, mpi->planes, mpi->stride, mpi->w, mpi->h, 0, 0);
-
- d3d_unlock_video_objects(priv);
-
- for (int n = 0; n < priv->plane_count; n++) {
- d3dtex_update(priv, &priv->planes[n].texture);
- }
-
- return d3d_draw_frame(priv);
-}
-
-/** @brief Render a frame on the screen.
- * @param mpi mpi structure with the decoded frame inside
- * @return VO_TRUE on success, VO_ERROR on failure
- */
-static uint32_t d3d_upload_and_render_frame(d3d_priv *priv, mp_image_t *mpi)
-{
- if (!priv->d3d_device)
- return VO_TRUE;
-
- if (priv->use_textures)
- return d3d_upload_and_render_frame_texture(priv, mpi);
-
- if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
- goto skip_upload;
-
- if (mpi->flags & MP_IMGFLAG_PLANAR) { /* Copy a planar frame. */
- draw_slice(priv->vo, mpi->planes, mpi->stride, mpi->w, mpi->h, 0, 0);
- goto skip_upload;
- }
-
- /* If we're here, then we should lock the rect and copy a packed frame */
- if (!priv->locked_rect.pBits) {
- if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface,
- &priv->locked_rect, NULL, 0))) {
- mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Surface lock failed.\n");
- return VO_ERROR;
- }
- }
-
- memcpy_pic(priv->locked_rect.pBits, mpi->planes[0], mpi->stride[0],
- mpi->height, priv->locked_rect.Pitch, mpi->stride[0]);
-
-skip_upload:
- d3d_unlock_video_objects(priv);
-
- return d3d_draw_frame(priv);
-}
-
-static uint32_t d3d_draw_frame(d3d_priv *priv)
-{
- int n;
-
- if (!priv->d3d_device)
- return VO_TRUE;
-
- if (!d3d_begin_scene(priv))
- return VO_ERROR;
-
- if (priv->is_clear_needed || priv->opt_swap_discard) {
- IDirect3DDevice9_Clear(priv->d3d_device, 0, NULL,
- D3DCLEAR_TARGET, 0, 0, 0);
- priv->is_clear_needed = 0;
- }
-
- if (priv->use_textures) {
-
- for (n = 0; n < priv->plane_count; n++) {
- IDirect3DDevice9_SetTexture(priv->d3d_device, n,
- d3dtex_get_render_texture(priv, &priv->planes[n].texture));
- }
-
- RECT rm = priv->fs_movie_rect;
- RECT rs = priv->fs_panscan_rect;
-
- vertex_video vb[] = {
- { rm.left, rm.top, 0.0f},
- { rm.right, rm.top, 0.0f},
- { rm.left, rm.bottom, 0.0f},
- { rm.right, rm.bottom, 0.0f}
- };
-
- float texc[4][2] = {
- { rs.left, rs.top},
- { rs.right, rs.top},
- { rs.left, rs.bottom},
- { rs.right, rs.bottom}
- };
-
- for (n = 0; n < priv->plane_count; n++) {
- float s_x = (1.0f / (1 << priv->planes[n].shift_x))
- / priv->planes[n].texture.tex_w;
- float s_y = (1.0f / (1 << priv->planes[n].shift_y))
- / priv->planes[n].texture.tex_h;
- for (int i = 0; i < 4; i++) {
- vb[i].t[n][0] = texc[i][0] * s_x;
- vb[i].t[n][1] = texc[i][1] * s_y;
- }
- }
-
- if (priv->pixel_shader) {
- IDirect3DDevice9_SetPixelShader(priv->d3d_device, priv->pixel_shader);
- IDirect3DDevice9_SetPixelShaderConstantF(priv->d3d_device, 0,
- &priv->d3d_colormatrix._11,
- 4);
- IDirect3DDevice9_SetPixelShaderConstantF(priv->d3d_device, 5,
- priv->d3d_depth_vector,
- 1);
- }
-
- IDirect3DDevice9_SetFVF(priv->d3d_device, D3DFVF_VIDEO_VERTEX);
- IDirect3DDevice9_DrawPrimitiveUP(priv->d3d_device, D3DPT_TRIANGLESTRIP,
- 2, &vb[0], sizeof(vertex_video));
-
- IDirect3DDevice9_SetPixelShader(priv->d3d_device, NULL);
-
- for (n = 0; n < priv->plane_count; n++) {
- IDirect3DDevice9_SetTexture(priv->d3d_device, n, NULL);
- }
-
- } else {
- if (FAILED(IDirect3DDevice9_StretchRect(priv->d3d_device,
- priv->d3d_surface,
- &priv->fs_panscan_rect,
- priv->d3d_backbuf,
- &priv->fs_movie_rect,
- D3DTEXF_LINEAR))) {
- mp_msg(MSGT_VO, MSGL_ERR,
- "<vo_direct3d>Copying frame to the backbuffer failed.\n");
- return VO_ERROR;
- }
- }
-
- return VO_TRUE;
-}
-
-// Return the high byte of the value that represents white in chroma (U/V)
-static int get_chroma_clear_val(int bit_depth)
-{
- return 1 << (bit_depth - 1 & 7);
-}
-
-// this macro is supposed to work on all formats supported by 3D rendering, and
-// that produce "reasonable" output (i.e. no mixed up colors)
-#define IMGFMT_IS_ANY_RND(x) \
- (IMGFMT_IS_BGR(x) || IMGFMT_IS_RGB(x) || IMGFMT_IS_Y(x))
-
-// pixel size in bit for any IMGFMT_IS_ANY_RND(x)==true
-// we assume that the actual pixel strides are always aligned on bytes
-static int imgfmt_any_rnd_depth(int fmt)
-{
- if (IMGFMT_IS_BGR(fmt))
- return IMGFMT_BGR_DEPTH(fmt);
- if (IMGFMT_IS_RGB(fmt))
- return IMGFMT_RGB_DEPTH(fmt);
- if (IMGFMT_IS_Y(fmt))
- return IMGFMT_Y_DEPTH(fmt);
- assert(false);
- return 0;
-}
-
-static D3DFORMAT check_format(d3d_priv *priv, uint32_t movie_fmt,
- bool as_texture)
-{
- const char *type = as_texture ? "texture rendering" : "StretchRect";
- const struct fmt_entry *cur = &fmt_table[0];
-
- // Don't try to handle weird packed texture formats (although I don't know
- // if D3D9 would even accept any such format for 3D rendering; and we
- // certainly don't try any tricks like matching it to RGB formats and
- // applying a YUV conversion matrix)
- if (as_texture && !IMGFMT_IS_ANY_RND(movie_fmt))
- return 0;
-
- while (cur->mplayer_fmt) {
- if (cur->mplayer_fmt == movie_fmt) {
- HRESULT res;
- if (as_texture) {
- res = IDirect3D9_CheckDeviceFormat(priv->d3d_handle,
- D3DADAPTER_DEFAULT,
- DEVTYPE,
- priv->desktop_fmt,
- D3DUSAGE_DYNAMIC | D3DUSAGE_QUERY_FILTER,
- D3DRTYPE_TEXTURE,
- cur->fourcc);
- } else {
- /* Test conversion from Movie colorspace to
- * display's target colorspace. */
- res = IDirect3D9_CheckDeviceFormatConversion(priv->d3d_handle,
- D3DADAPTER_DEFAULT,
- DEVTYPE,
- cur->fourcc,
- priv->desktop_fmt);
- }
- if (FAILED(res)) {
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Rejected image format "
- "(%s): %s\n", type, vo_format_name(cur->mplayer_fmt));
- return 0;
- }
-
- mp_msg(MSGT_VO, MSGL_DBG2, "<vo_direct3d>Accepted image format "
- "(%s): %s\n", type, vo_format_name(cur->mplayer_fmt));
-
- return cur->fourcc;
- }
- cur++;
- }
-
- return 0;
-}
-
-// Check whether YUV conversion with shaders can be done.
-// Returns the format the individual planes should use (or 0 on failure)
-static D3DFORMAT check_shader_conversion(d3d_priv *priv, uint32_t fmt)
-{
- if (priv->opt_disable_shaders)
- return 0;
- int component_bits;
- if (!mp_get_chroma_shift(fmt, NULL, NULL, &component_bits))
- return 0;
- if (component_bits < 8 || component_bits > 16)
- return 0;
- bool is_8bit = component_bits == 8;
- if (!is_8bit && priv->opt_only_8bit)
- return 0;
- int texfmt = IMGFMT_Y8;
- if (!is_8bit) {
- if (priv->opt_16bit_textures)
- texfmt = IMGFMT_Y16;
- else
- texfmt = IMGFMT_A8Y8;
- }
- return check_format(priv, texfmt, true);
-}
-
-// Return if the image format can be used. If it can, decide which rendering
-// and conversion mode to use.
-// If initialize is true, actually setup all variables to use the picked
-// rendering mode.
-static bool init_rendering_mode(d3d_priv *priv, uint32_t fmt, bool initialize)
-{
- int n;
- int blit_d3dfmt = check_format(priv, fmt, false);
- int texture_d3dfmt = check_format(priv, fmt, true);
- int shader_d3dfmt = check_shader_conversion(priv, fmt);
-
- if (priv->opt_disable_textures)
- texture_d3dfmt = 0;
- if (priv->opt_disable_shaders)
- shader_d3dfmt = 0;
- if (priv->opt_disable_stretchrect)
- blit_d3dfmt = 0;
-
- if (!(blit_d3dfmt || shader_d3dfmt || texture_d3dfmt))
- return false;
-
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Accepted rendering methods for "
- "format='%s': StretchRect=%#x, Texture=%#x, Texture+Shader=%#x.\n",
- vo_format_name(fmt), blit_d3dfmt, texture_d3dfmt, shader_d3dfmt);
-
- if (!initialize)
- return true;
-
- // initialization doesn't fail beyond this point
-
- priv->use_shaders = false;
- priv->use_textures = false;
- priv->use_2ch_hack = false;
- priv->movie_src_fmt = 0;
- priv->pixel_shader_data = NULL;
- priv->plane_count = 0;
- priv->image_format = fmt;
-
- if (blit_d3dfmt && priv->opt_prefer_stretchrect)
- texture_d3dfmt = shader_d3dfmt = 0;
-
- if (texture_d3dfmt) {
- priv->use_textures = true;
- } else if (shader_d3dfmt) {
- priv->use_textures = true;
- priv->use_shaders = true;
- } else {
- assert(!!blit_d3dfmt);
- }
-
- if (priv->use_textures) {
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Using 3D rendering.\n");
-
- struct texplane *planes = &priv->planes[0];
- planes[0].shift_x = planes[0].shift_y = 0;
- planes[0].clearval = 0;
-
- if (!priv->use_shaders) {
- assert(IMGFMT_IS_ANY_RND(priv->image_format));
- priv->plane_count = 1;
- planes[0].bits_per_pixel = imgfmt_any_rnd_depth(priv->image_format);
- planes[0].d3d_format = texture_d3dfmt;
- } else {
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Using YUV shaders.\n");
-
- int sx, sy, component_bits;
- mp_get_chroma_shift(priv->image_format, &sx, &sy, &component_bits);
- priv->plane_count = 3;
- for (n = 0; n < 3; n++) {
- planes[n].d3d_format = shader_d3dfmt;
- planes[n].bits_per_pixel = component_bits;
- if (n > 0) {
- planes[n].shift_x = sx;
- planes[n].shift_y = sy;
- planes[n].clearval = get_chroma_clear_val(component_bits);
- }
- }
- if (shader_d3dfmt != D3DFMT_A8L8) {
- priv->pixel_shader_data = d3d_shader_yuv;
- } else {
- mp_msg(MSGT_VO, MSGL_WARN, "<vo_direct3d>Using YUV 2ch hack.\n");
-
- priv->pixel_shader_data = d3d_shader_yuv_2ch;
- priv->use_2ch_hack = true;
- }
- }
-
- for (n = 0; n < priv->plane_count; n++) {
- planes[n].bytes_per_pixel = (planes[n].bits_per_pixel + 7) / 8;
- }
-
- } else {
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Using StretchRect.\n");
-
- priv->movie_src_fmt = blit_d3dfmt;
- }
-
- update_colorspace(priv);
-
- return true;
-}
-
-/** @brief Query if movie colorspace is supported by the HW.
- * @return 0 on failure, device capabilities (not probed
- * currently) on success.
- */
-static int query_format(d3d_priv *priv, uint32_t movie_fmt)
-{
- if (!init_rendering_mode(priv, movie_fmt, false))
- return 0;
-
- int osd_caps = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW
- | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN;
- if (!priv->opt_disable_osd)
- osd_caps |= VFCAP_OSD;
- return osd_caps;
-}
-
-/****************************************************************************
- * *
- * *
- * *
- * libvo Control / Callback functions *
- * *
- * *
- * *
- ****************************************************************************/
-
-static void get_2ch_depth_multiplier(int depth, float *out_f1, float *out_f2) {
- // How to get these values:
- // The suffix i8 and i16 is for values with 8/16 bit fixed point numbers.
- // The suffix f is for float, ideally in the range 0.0-1.0.
- // c_i8 is a two component vector, sampled from a two channel texture.
- // (c_i8.x is the low byte, c_i8.y is the high byte)
- // r_f is the resulting color scalar value.
- //
- // c_i8 = c_f * (2^8-1)
- // r_i16 = c_i8.x + c_i8.y * 2^8
- // r_f = r_i16 / (2^16-1)
- // = c_f.x * (2^8-1) / (2^16-1) + c_f.y * (2^8-1) * 2^8 / (2^16-1)
- // = c_f.x * ((2^8-1) / (2^16-1)) + c_f.y * (2^8 * ((2^8-1) / (2^16-1)))
- // out = ((2^8-1) / (2^16-1), 2^8 * ((2^8-1) / (2^16-1)))
- // The result color is r_f = dot(c_f, out).
- // Same goes for other bit depth, such as 10 bit. Assuming (2^depth-1) is
- // the maximum possible value at that depth, you have to scale the value
- // r_i16 with it, the factor (2^16-1) in the formula above has to be
- // replaced with (2^depth-1).
- float factor = (float)((1 << 8) - 1) / (float)((1 << depth) - 1);
- *out_f1 = factor;
- *out_f2 = 256.0 * factor;
-}
-
-static void update_colorspace(d3d_priv *priv)
-{
- float coeff[3][4];
- struct mp_csp_params csp = { .colorspace = priv->colorspace };
- mp_csp_copy_equalizer_values(&csp, &priv->video_eq);
-
- if (priv->use_shaders) {
- if (!priv->use_2ch_hack) {
- csp.input_bits = priv->planes[0].bits_per_pixel;
- csp.texture_bits = (csp.input_bits + 7) & ~7;
- } else {
- float f1, f2;
- get_2ch_depth_multiplier(priv->planes[0].bits_per_pixel, &f1, &f2);
- priv->d3d_depth_vector[0] = f1;
- priv->d3d_depth_vector[1] = f2;
- priv->d3d_depth_vector[2] = priv->d3d_depth_vector[3] = 0;
- // no change
- csp.input_bits = 8;
- csp.texture_bits = 8;
- }
-
- mp_get_yuv2rgb_coeffs(&csp, coeff);
- for (int row = 0; row < 3; row++) {
- for (int col = 0; col < 4; col++) {
- priv->d3d_colormatrix.m[row][col] = coeff[row][col];
- }
- }
- }
-}
-
-const char *options_help_text = "-vo direct3d command line help:\n"
-"Example: -vo direct3d:disable-osd:disable-textures\n"
-"Options:\n"
-" prefer-stretchrect\n"
-" Use IDirect3DDevice9::StretchRect over other methods if possible.\n"
-" disable-stretchrect\n"
-" Never render the video using IDirect3DDevice9::StretchRect.\n"
-" disable-textures\n"
-" Never render the video using D3D texture rendering. (Rendering with\n"
-" textures + shader will still be allowed. Add disable-shaders to\n"
-" completely disable video rendering with textures.)\n"
-" disable-shaders\n"
-" Never use shaders when rendering video.\n"
-" only-8bit\n"
-" Never render YUV video with more than 8 bits per component.\n"
-" (Using this flag will force software conversion to 8 bit.)\n"
-" disable-osd\n"
-" Disable OSD rendering.\n"
-" (Using this flag might force the insertion of the 'ass' video filter,\n"
-" which will render the subtitles in software.)\n"
-" disable-texture-align\n"
-" Normally texture sizes are always aligned to 16. With this option\n"
-" enabled, the video texture will always have exactly the same size as\n"
-" the video itself.\n"
-"Debug options. These might be incorrect, might be removed in the future, might\n"
-"crash, might cause slow downs, etc. Contact the developers if you actually need\n"
-"any of these for performance or proper operation.\n"
-" force-power-of-2\n"
-" Always force textures to power of 2, even if the device reports\n"
-" non-power-of-2 texture sizes as supported.\n"
-" texture-memory=N\n"
-" Only affects operation with shaders/texturing enabled, and (E)OSD.\n"
-" Values for N:\n"
-" 0 default, will often use an additional shadow texture + copy\n"
-" 1 use D3DPOOL_MANAGED\n"
-" 2 use D3DPOOL_DEFAULT\n"
-" 3 use D3DPOOL_SYSTEMMEM, but without shadow texture\n"
-" swap-discard\n"
-" Use D3DSWAPEFFECT_DISCARD, which might be faster.\n"
-" Might be slower too, as it must (?) clear every frame.\n"
-" exact-backbuffer\n"
-" Always resize the backbuffer to window size.\n"
-" no16bit-textures\n"
-" Don't use textures with a 16 bit color channel for YUV formats that\n"
-" use more than 8 bits per component. Instead, use D3DFMT_A8L8 textures\n"
-" and compute the values sampled from the 2 channels back into one.\n"
-" Might be slower, since the shader becomes slightly more complicated.\n"
-" Might work better, if your drivers either don't support D3DFMT_L16,\n"
-" or if either the texture unit or the shaders don't operate in at least\n"
-" 16 bit precision.\n"
-"";
-
-/** @brief libvo Callback: Preinitialize the video card.
- * Preinit the hardware just enough to be queried about
- * supported formats.
- *
- * @return 0 on success, -1 on failure
- */
-
-static int preinit_internal(struct vo *vo, const char *arg, bool allow_shaders)
-{
- d3d_priv *priv = talloc_zero(vo, d3d_priv);
- vo->priv = priv;
-
- *priv = (d3d_priv) {
- .vo = vo,
-
- .opt_16bit_textures = true,
-
- .colorspace = MP_CSP_DETAILS_DEFAULTS,
- .video_eq = { MP_CSP_EQ_CAPS_COLORMATRIX },
- };
-
- for (int n = 0; n < MAX_OSD_PARTS; n++) {
- struct osdpart *osd = talloc_ptrtype(priv, osd);
- *osd = (struct osdpart) {
- .packer = talloc_zero(osd, struct bitmap_packer),
- };
- priv->osd[n] = osd;
- }
-
- if (!allow_shaders) {
- priv->opt_disable_shaders = priv->opt_disable_textures = true;
- }
-
- const opt_t subopts[] = {
- {"prefer-stretchrect", OPT_ARG_BOOL, &priv->opt_prefer_stretchrect},
- {"disable-textures", OPT_ARG_BOOL, &priv->opt_disable_textures},
- {"disable-stretchrect", OPT_ARG_BOOL, &priv->opt_disable_stretchrect},
- {"disable-shaders", OPT_ARG_BOOL, &priv->opt_disable_shaders},
- {"only-8bit", OPT_ARG_BOOL, &priv->opt_only_8bit},
- {"disable-osd", OPT_ARG_BOOL, &priv->opt_disable_osd},
- {"force-power-of-2", OPT_ARG_BOOL, &priv->opt_force_power_of_2},
- {"disable-texture-align", OPT_ARG_BOOL, &priv->opt_disable_texture_align},
- {"texture-memory", OPT_ARG_INT, &priv->opt_texture_memory},
- {"swap-discard", OPT_ARG_BOOL, &priv->opt_swap_discard},
- {"exact-backbuffer", OPT_ARG_BOOL, &priv->opt_exact_backbuffer},
- {"16bit-textures", OPT_ARG_BOOL, &priv->opt_16bit_textures},
- {NULL}
- };
- if (subopt_parse(arg, subopts) != 0) {
- mp_msg(MSGT_VO, MSGL_FATAL, options_help_text);
- return -1;
- }
-
- priv->d3d9_dll = LoadLibraryA("d3d9.dll");
- if (!priv->d3d9_dll) {
- mp_msg(MSGT_VO, MSGL_ERR,
- "<vo_direct3d>Unable to dynamically load d3d9.dll\n");
- goto err_out;
- }
-
- priv->pDirect3DCreate9 = (void *)GetProcAddress(priv->d3d9_dll,
- "Direct3DCreate9");
- if (!priv->pDirect3DCreate9) {
- mp_msg(MSGT_VO, MSGL_ERR,
- "<vo_direct3d>Unable to find entry point of Direct3DCreate9\n");
- goto err_out;
- }
-
- if (!init_d3d(priv))
- goto err_out;
-
- /* w32_common framework call. Configures window on the screen, gets
- * fullscreen dimensions and does other useful stuff.
- */
- if (!vo_w32_init(vo)) {
- mp_msg(MSGT_VO, MSGL_V,
- "<vo_direct3d>Configuring onscreen window failed.\n");
- goto err_out;
- }
-
- return 0;
-
-err_out:
- uninit(vo);
- return -1;
-}
-
-static int preinit_standard(struct vo *vo, const char *arg)
-{
- return preinit_internal(vo, arg, false);
-}
-
-static int preinit_shaders(struct vo *vo, const char *arg)
-{
- return preinit_internal(vo, arg, true);
-}
-
-/** @brief libvo Callback: Handle control requests.
- * @return VO_TRUE on success, VO_NOTIMPL when not implemented
- */
-static int control(struct vo *vo, uint32_t request, void *data)
-{
- d3d_priv *priv = vo->priv;
-
- switch (request) {
- case VOCTRL_QUERY_FORMAT:
- return query_format(priv, *(uint32_t*) data);
- case VOCTRL_DRAW_IMAGE:
- return d3d_upload_and_render_frame(priv, data);
- case VOCTRL_FULLSCREEN:
- vo_w32_fullscreen(vo);
- resize_d3d(priv);
- return VO_TRUE;
- case VOCTRL_RESET:
- return VO_NOTIMPL;
- case VOCTRL_REDRAW_FRAME:
- priv->is_clear_needed = 1;
- d3d_draw_frame(priv);
- return VO_TRUE;
- case VOCTRL_SET_YUV_COLORSPACE:
- priv->colorspace = *(struct mp_csp_details *)data;
- update_colorspace(priv);
- vo->want_redraw = true;
- return VO_TRUE;
- case VOCTRL_GET_YUV_COLORSPACE:
- if (!priv->use_shaders)
- break; // no idea what the heck D3D YUV uses
- *(struct mp_csp_details *)data = priv->colorspace;
- return VO_TRUE;
- case VOCTRL_SET_EQUALIZER: {
- if (!priv->use_shaders)
- break;
- struct voctrl_set_equalizer_args *args = data;
- if (mp_csp_equalizer_set(&priv->video_eq, args->name, args->value) < 0)
- return VO_NOTIMPL;
- update_colorspace(priv);
- vo->want_redraw = true;
- return VO_TRUE;
- }
- case VOCTRL_GET_EQUALIZER: {
- if (!priv->use_shaders)
- break;
- struct voctrl_get_equalizer_args *args = data;
- return mp_csp_equalizer_get(&priv->video_eq, args->name, args->valueptr)
- >= 0 ? VO_TRUE : VO_NOTIMPL;
- }
- case VOCTRL_ONTOP:
- vo_w32_ontop(vo);
- return VO_TRUE;
- case VOCTRL_BORDER:
- vo_w32_border(vo);
- return VO_TRUE;
- case VOCTRL_UPDATE_SCREENINFO:
- w32_update_xinerama_info(vo);
- return VO_TRUE;
- case VOCTRL_SET_PANSCAN:
- calc_fs_rect(priv);
- return VO_TRUE;
- case VOCTRL_GET_PANSCAN:
- return VO_TRUE;
- case VOCTRL_SCREENSHOT: {
- struct voctrl_screenshot_args *args = data;
- if (args->full_window)
- args->out_image = get_window_screenshot(priv);
- else
- args->out_image = get_screenshot(priv);
- return !!args->out_image;
- }
- }
- return VO_NOTIMPL;
-}
-
-/** @brief libvo Callback: Configre the Direct3D adapter.
- * @param width Movie source width
- * @param height Movie source height
- * @param d_width Screen (destination) width
- * @param d_height Screen (destination) height
- * @param options Options bitmap
- * @param format Movie colorspace format (using MPlayer's
- * defines, e.g. IMGFMT_YUY2)
- * @return 0 on success, VO_ERROR on failure
- */
-static int config(struct vo *vo, uint32_t width, uint32_t height,
- uint32_t d_width, uint32_t d_height, uint32_t options,
- uint32_t format)
-{
- d3d_priv *priv = vo->priv;
-
- /* w32_common framework call. Creates window on the screen with
- * the given coordinates.
- */
- if (!vo_w32_config(vo, d_width, d_height, options)) {
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Creating window failed.\n");
- return VO_ERROR;
- }
-
- if ((priv->image_format != format)
- || (priv->src_width != width)
- || (priv->src_height != height))
- {
- d3d_destroy_video_objects(priv);
-
- priv->src_width = width;
- priv->src_height = height;
- init_rendering_mode(priv, format, true);
- }
-
- if (!resize_d3d(priv))
- return VO_ERROR;
-
- return 0; /* Success */
-}
-
-/** @brief libvo Callback: Flip next already drawn frame on the
- * screen.
- */
-static void flip_page(struct vo *vo)
-{
- d3d_priv *priv = vo->priv;
-
- if (priv->d3d_device && priv->d3d_in_scene) {
- if (FAILED(IDirect3DDevice9_EndScene(priv->d3d_device))) {
- mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>EndScene failed.\n");
- }
- }
- priv->d3d_in_scene = false;
-
- RECT rect = {0, 0, vo->dwidth, vo->dheight};
- if (!priv->d3d_device ||
- FAILED(IDirect3DDevice9_Present(priv->d3d_device, &rect, 0, 0, 0))) {
- mp_msg(MSGT_VO, MSGL_V,
- "<vo_direct3d>Trying to reinitialize uncooperative video adapter.\n");
- if (!reconfigure_d3d(priv)) {
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Reinitialization failed.\n");
- return;
- } else {
- mp_msg(MSGT_VO, MSGL_V,
- "<vo_direct3d>Video adapter reinitialized.\n");
- }
- }
-}
-
-/** @brief libvo Callback: Uninitializes all pointers and closes
- * all D3D related stuff,
- */
-static void uninit(struct vo *vo)
-{
- d3d_priv *priv = vo->priv;
-
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>uninit called.\n");
-
- uninit_d3d(priv);
- vo_w32_uninit(vo);
- if (priv->d3d9_dll)
- FreeLibrary(priv->d3d9_dll);
- priv->d3d9_dll = NULL;
-}
-
-/** @brief libvo Callback: Handles video window events.
- */
-static void check_events(struct vo *vo)
-{
- d3d_priv *priv = vo->priv;
-
- int flags = vo_w32_check_events(vo);
- if (flags & VO_EVENT_RESIZE)
- resize_d3d(priv);
-
- if (flags & VO_EVENT_EXPOSE)
- vo->want_redraw = true;
-}
-
-static int draw_slice_textures(d3d_priv *priv, uint8_t *src[], int stride[],
- int w, int h, int x, int y)
-{
- if (!d3d_lock_video_textures(priv))
- return VO_FALSE;
-
- for (int n = 0; n < priv->plane_count; n++) {
- struct texplane *plane = &priv->planes[n];
-
- int dst_stride = plane->locked_rect.Pitch;
- uint8_t *pdst = (uint8_t*)plane->locked_rect.pBits
- + (y >> plane->shift_y) * dst_stride
- + (x >> plane->shift_x) * plane->bytes_per_pixel;
-
- memcpy_pic(pdst, src[n], (w >> plane->shift_x) * plane->bytes_per_pixel,
- h >> plane->shift_y, dst_stride, stride[n]);
- }
-
- return 0;
-}
-
-/** @brief libvo Callback: Draw slice
- * @return 0 on success
- */
-static int draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h,
- int x, int y)
-{
- d3d_priv *priv = vo->priv;
-
- if (!priv->d3d_device)
- return 0;
-
- char *my_src; /**< Pointer to the source image */
- char *dst; /**< Pointer to the destination image */
- int uv_stride; /**< Stride of the U/V planes */
-
- if (priv->use_textures)
- return draw_slice_textures(priv, src, stride, w, h, x, y);
-
- /* Lock the offscreen surface if it's not already locked. */
- if (!priv->locked_rect.pBits) {
- if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface,
- &priv->locked_rect, NULL, 0))) {
- mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Surface lock failure.\n");
- return VO_FALSE;
- }
- }
-
- uv_stride = priv->locked_rect.Pitch / 2;
-
- /* Copy Y */
- dst = priv->locked_rect.pBits;
- dst = dst + priv->locked_rect.Pitch * y + x;
- my_src = src[0];
- memcpy_pic(dst, my_src, w, h, priv->locked_rect.Pitch, stride[0]);
-
- w /= 2;
- h /= 2;
- x /= 2;
- y /= 2;
-
- /* Copy U */
- dst = priv->locked_rect.pBits;
- dst = dst + priv->locked_rect.Pitch * priv->src_height
- + uv_stride * y + x;
- if (priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2'))
- my_src = src[2];
- else
- my_src = src[1];
-
- memcpy_pic(dst, my_src, w, h, uv_stride, stride[1]);
-
- /* Copy V */
- dst = priv->locked_rect.pBits;
- dst = dst + priv->locked_rect.Pitch * priv->src_height
- + uv_stride * (priv->src_height / 2) + uv_stride * y + x;
- if (priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2'))
- my_src=src[1];
- else
- my_src=src[2];
-
- memcpy_pic(dst, my_src, w, h, uv_stride, stride[2]);
-
- return 0; /* Success */
-}
-
-static bool get_screenshot_from_surface(d3d_priv *priv, mp_image_t *image)
-{
- if (!priv->locked_rect.pBits) {
- if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface,
- &priv->locked_rect, NULL, 0))) {
- mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Surface lock failed.\n");
- return false;
- }
- }
-
- if (image->flags & MP_IMGFLAG_PLANAR) {
- char *src;
- int w = priv->src_width;
- int h = priv->src_height;
- int swapped = priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2');
- int plane1 = swapped ? 2 : 1;
- int plane2 = swapped ? 1 : 2;
-
- int uv_stride = priv->locked_rect.Pitch / 2;
-
- /* Copy Y */
- src = priv->locked_rect.pBits;
- memcpy_pic(image->planes[0], src, w, h, priv->locked_rect.Pitch,
- image->stride[0]);
-
- w /= 2;
- h /= 2;
-
- /* Copy U */
- src = priv->locked_rect.pBits;
- src = src + priv->locked_rect.Pitch * priv->src_height;
-
- memcpy_pic(image->planes[plane1], src, w, h, uv_stride,
- image->stride[1]);
-
- /* Copy V */
- src = priv->locked_rect.pBits;
- src = src + priv->locked_rect.Pitch * priv->src_height
- + uv_stride * (priv->src_height / 2);
-
- memcpy_pic(image->planes[plane2], src, w, h, uv_stride,
- image->stride[2]);
- } else {
- // packed YUV or RGB
- memcpy_pic(image->planes[0], priv->locked_rect.pBits, image->stride[0],
- image->height, priv->locked_rect.Pitch, image->stride[0]);
- }
-
- d3d_unlock_video_objects(priv);
- return true;
-}
-
-static bool get_screenshot_from_texture(d3d_priv *priv, mp_image_t *image)
-{
- if (!d3d_lock_video_textures(priv)) {
- d3d_unlock_video_objects(priv);
- return false;
- }
-
- assert(image->num_planes == priv->plane_count);
-
- for (int n = 0; n < priv->plane_count; n++) {
- struct texplane *plane = &priv->planes[n];
-
- int width = priv->src_width >> plane->shift_x;
- int height = priv->src_height >> plane->shift_y;
-
- memcpy_pic(image->planes[n], plane->locked_rect.pBits,
- width * plane->bytes_per_pixel, height,
- image->stride[n], plane->locked_rect.Pitch);
- }
-
- return true;
-}
-
-static mp_image_t *get_screenshot(d3d_priv *priv)
-{
- if (!priv->d3d_device)
- return NULL;
-
- mp_image_t *image = alloc_mpi(priv->src_width, priv->src_height,
- priv->image_format);
-
- bool res;
-
- if (priv->use_textures)
- res = get_screenshot_from_texture(priv, image);
- else
- res = get_screenshot_from_surface(priv, image);
-
- if (!res) {
- free_mp_image(image);
- return NULL;
- }
-
- image->display_w = priv->vo->aspdat.prew;
- image->display_h = priv->vo->aspdat.preh;
-
- mp_image_set_colorspace_details(image, &priv->colorspace);
-
- return image;
-}
-
-static mp_image_t *get_window_screenshot(d3d_priv *priv)
-{
- D3DDISPLAYMODE mode;
- mp_image_t *image = NULL;
- RECT window_rc;
- RECT screen_rc;
- RECT visible;
- POINT pt;
- D3DLOCKED_RECT locked_rect;
- int width, height;
-
- if (FAILED(IDirect3DDevice9_GetDisplayMode(priv->d3d_device, 0, &mode))) {
- mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>GetDisplayMode failed.\n");
- goto error_exit;
- }
-
- IDirect3DSurface9 *surface = NULL;
- if (FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(priv->d3d_device,
- mode.Width, mode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface,
- NULL)))
- {
- mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>Couldn't create surface.\n");
- goto error_exit;
- }
-
- if (FAILED(IDirect3DDevice9_GetFrontBufferData(priv->d3d_device, 0,
- surface)))
- {
- mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>Couldn't copy frontbuffer.\n");
- goto error_exit;
- }
-
- GetClientRect(priv->vo->w32->window, &window_rc);
- pt = (POINT) { 0, 0 };
- ClientToScreen(priv->vo->w32->window, &pt);
- window_rc.left = pt.x;
- window_rc.top = pt.y;
- window_rc.right += window_rc.left;
- window_rc.bottom += window_rc.top;
-
- screen_rc = (RECT) { 0, 0, mode.Width, mode.Height };
-
- if (!IntersectRect(&visible, &screen_rc, &window_rc))
- goto error_exit;
- width = visible.right - visible.left;
- height = visible.bottom - visible.top;
- if (width < 1 || height < 1)
- goto error_exit;
-
- image = alloc_mpi(width, height, IMGFMT_BGR32);
-
- IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
-
- memcpy_pic(image->planes[0], (char*)locked_rect.pBits + visible.top *
- locked_rect.Pitch + visible.left * 4, width * 4, height,
- image->stride[0], locked_rect.Pitch);
-
- IDirect3DSurface9_UnlockRect(surface);
- IDirect3DSurface9_Release(surface);
-
- return image;
-
-error_exit:
- if (image)
- free_mp_image(image);
- if (surface)
- IDirect3DSurface9_Release(surface);
- return NULL;
-}
-
-static bool upload_osd(d3d_priv *priv, struct osdpart *osd,
- struct sub_bitmaps *imgs)
-{
- D3DFORMAT fmt = osd_fmt_table[imgs->format];
-
- osd->packer->w_max = priv->max_texture_width;
- osd->packer->h_max = priv->max_texture_height;
-
- osd->packer->padding = imgs->scaled; // assume 2x2 filter on scaling
- int r = packer_pack_from_subbitmaps(osd->packer, imgs);
- if (r < 0) {
- mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>OSD bitmaps do not fit on "
- "a surface with the maximum supported size %dx%d.\n",
- osd->packer->w_max, osd->packer->h_max);
- return false;
- }
-
- if (osd->packer->w > osd->texture.tex_w
- || osd->packer->h > osd->texture.tex_h
- || osd->format != imgs->format)
- {
- osd->format = imgs->format;
-
- int new_w = osd->packer->w;
- int new_h = osd->packer->h;
- d3d_fix_texture_size(priv, &new_w, &new_h);
-
- mp_msg(MSGT_VO, MSGL_DBG2, "<vo_direct3d>reallocate OSD surface.\n");
-
- d3dtex_release(priv, &osd->texture);
- d3dtex_allocate(priv, &osd->texture, fmt, new_w, new_h);
-
- if (!osd->texture.system)
- return false; // failed to allocate
- }
-
- struct pos bb[2];
- packer_get_bb(osd->packer, bb);
- RECT dirty_rc = { bb[0].x, bb[0].y, bb[1].x, bb[1].y };
-
- D3DLOCKED_RECT locked_rect;
-
- if (FAILED(IDirect3DTexture9_LockRect(osd->texture.system, 0, &locked_rect,
- &dirty_rc, 0)))
- {
- mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>OSD texture lock failed.\n");
- return false;
- }
-
- int ps = fmt == D3DFMT_A8 ? 1 : 4;
- packer_copy_subbitmaps(osd->packer, imgs, locked_rect.pBits, ps,
- locked_rect.Pitch);
-
- if (FAILED(IDirect3DTexture9_UnlockRect(osd->texture.system, 0))) {
- mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>OSD texture unlock failed.\n");
- return false;
- }
-
- return d3dtex_update(priv, &osd->texture);
-}
-
-static struct osdpart *generate_osd(d3d_priv *priv, struct sub_bitmaps *imgs)
-{
- if (imgs->num_parts == 0 || !osd_fmt_table[imgs->format])
- return NULL;
-
- struct osdpart *osd = priv->osd[imgs->render_index];
-
- if (imgs->bitmap_pos_id != osd->bitmap_pos_id) {
- if (imgs->bitmap_id != osd->bitmap_id) {
- if (!upload_osd(priv, osd, imgs))
- osd->packer->count = 0;
- }
-
- osd->bitmap_id = imgs->bitmap_id;
- osd->bitmap_pos_id = imgs->bitmap_pos_id;
- osd->num_vertices = 0;
- }
-
- return osd->packer->count ? osd : NULL;
-}
-
-static D3DCOLOR ass_to_d3d_color(uint32_t color)
-{
- uint32_t r = (color >> 24) & 0xff;
- uint32_t g = (color >> 16) & 0xff;
- uint32_t b = (color >> 8) & 0xff;
- uint32_t a = 0xff - (color & 0xff);
- return D3DCOLOR_ARGB(a, r, g, b);
-}
-
-static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs)
-{
- d3d_priv *priv = ctx;
-
- struct osdpart *osd = generate_osd(priv, imgs);
- if (!osd)
- return;
-
- if (osd->packer->count && !osd->num_vertices) {
- // We need 2 primitives per quad which makes 6 vertices (we could reduce
- // the number of vertices by using an indexed vertex array, but it's
- // probably not worth doing)
- osd->num_vertices = osd->packer->count * 6;
- osd->vertices = talloc_realloc(osd, osd->vertices, vertex_osd,
- osd->num_vertices);
-
- float tex_w = osd->texture.tex_w;
- float tex_h = osd->texture.tex_h;
-
- for (int n = 0; n < osd->packer->count; n++) {
- struct sub_bitmap *b = &imgs->parts[n];
- struct pos p = osd->packer->result[n];
-
- D3DCOLOR color = imgs->format == SUBBITMAP_LIBASS
- ? ass_to_d3d_color(b->libass.color)
- : D3DCOLOR_ARGB(255, 255, 255, 255);
-
- float x0 = b->x;
- float y0 = b->y;
- float x1 = b->x + b->dw;
- float y1 = b->y + b->dh;
- float tx0 = p.x / tex_w;
- float ty0 = p.y / tex_h;
- float tx1 = (p.x + b->w) / tex_w;
- float ty1 = (p.y + b->h) / tex_h;
-
- vertex_osd *v = &osd->vertices[n * 6];
- v[0] = (vertex_osd) { x0, y0, 0, color, tx0, ty0 };
- v[1] = (vertex_osd) { x1, y0, 0, color, tx1, ty0 };
- v[2] = (vertex_osd) { x0, y1, 0, color, tx0, ty1 };
- v[3] = (vertex_osd) { x1, y1, 0, color, tx1, ty1 };
- v[4] = v[2];
- v[5] = v[1];
- }
- }
-
- d3d_begin_scene(priv);
-
- IDirect3DDevice9_SetRenderState(priv->d3d_device,
- D3DRS_ALPHABLENDENABLE, TRUE);
-
- IDirect3DDevice9_SetTexture(priv->d3d_device, 0,
- d3dtex_get_render_texture(priv, &osd->texture));
-
- if (imgs->format == SUBBITMAP_LIBASS) {
- // do not use the color value from the A8 texture, because that is black
- IDirect3DDevice9_SetRenderState(priv->d3d_device,D3DRS_TEXTUREFACTOR,
- 0xFFFFFFFF);
- IDirect3DDevice9_SetTextureStageState(priv->d3d_device,0,
- D3DTSS_COLORARG1, D3DTA_TFACTOR);
-
- IDirect3DDevice9_SetTextureStageState(priv->d3d_device, 0,
- D3DTSS_ALPHAOP, D3DTOP_MODULATE);
- } else {
- IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_SRCBLEND,
- D3DBLEND_ONE);
- }
-
- IDirect3DDevice9_SetFVF(priv->d3d_device, D3DFVF_OSD_VERTEX);
- IDirect3DDevice9_DrawPrimitiveUP(priv->d3d_device, D3DPT_TRIANGLELIST,
- osd->num_vertices / 3,
- osd->vertices, sizeof(vertex_osd));
-
- IDirect3DDevice9_SetTextureStageState(priv->d3d_device,0,
- D3DTSS_COLORARG1, D3DTA_TEXTURE);
- IDirect3DDevice9_SetTextureStageState(priv->d3d_device, 0,
- D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
- IDirect3DDevice9_SetRenderState(priv->d3d_device,
- D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
-
- IDirect3DDevice9_SetTexture(priv->d3d_device, 0, NULL);
-
- IDirect3DDevice9_SetRenderState(priv->d3d_device,
- D3DRS_ALPHABLENDENABLE, FALSE);
-}
-
-
-static void draw_osd(struct vo *vo, struct osd_state *osd)
-{
- d3d_priv *priv = vo->priv;
- if (!priv->d3d_device)
- return;
-
- osd_draw(osd, priv->osd_res, osd->vo_pts, 0, osd_fmt_supported,
- draw_osd_cb, priv);
-}
-
-#define AUTHOR "Georgi Petrov (gogothebee) <gogothebee@gmail.com> and others"
-
-const struct vo_driver video_out_direct3d = {
- .is_new = true,
- .info = &(const vo_info_t) {
- "Direct3D 9 Renderer",
- "direct3d",
- AUTHOR,
- ""
- },
- .preinit = preinit_standard,
- .config = config,
- .control = control,
- .draw_slice = draw_slice,
- .draw_osd = draw_osd,
- .flip_page = flip_page,
- .check_events = check_events,
- .uninit = uninit,
-};
-
-const struct vo_driver video_out_direct3d_shaders = {
- .is_new = true,
- .info = &(const vo_info_t) {
- "Direct3D 9 Renderer (using shaders for YUV conversion)",
- "direct3d_shaders",
- AUTHOR,
- ""
- },
- .preinit = preinit_shaders,
- .config = config,
- .control = control,
- .draw_slice = draw_slice,
- .draw_osd = draw_osd,
- .flip_page = flip_page,
- .check_events = check_events,
- .uninit = uninit,
-};
diff --git a/libvo/vo_image.c b/libvo/vo_image.c
deleted file mode 100644
index 7f80a16f35..0000000000
--- a/libvo/vo_image.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * This file is part of mplayer.
- *
- * mplayer 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.
- *
- * mplayer 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 mplayer. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <stdbool.h>
-#include <sys/stat.h>
-
-#include <libswscale/swscale.h>
-
-#include "config.h"
-#include "bstr.h"
-#include "osdep/io.h"
-#include "path.h"
-#include "talloc.h"
-#include "mp_msg.h"
-#include "libvo/video_out.h"
-#include "libvo/csputils.h"
-#include "libmpcodecs/vfcap.h"
-#include "libmpcodecs/mp_image.h"
-#include "fmt-conversion.h"
-#include "image_writer.h"
-#include "m_config.h"
-#include "m_option.h"
-
-struct priv {
- struct image_writer_opts *opts;
- char *outdir;
-
- int frame;
-
- uint32_t d_width;
- uint32_t d_height;
-
- struct mp_csp_details colorspace;
-};
-
-static bool checked_mkdir(const char *buf)
-{
- mp_msg(MSGT_VO, MSGL_INFO, "[vo_image] Creating output directory '%s'...\n",
- buf);
- if (mkdir(buf, 0755) < 0) {
- char *errstr = strerror(errno);
- if (errno == EEXIST) {
- struct stat stat_p;
- if (mp_stat(buf, &stat_p ) == 0 && S_ISDIR(stat_p.st_mode))
- return true;
- }
- mp_msg(MSGT_VO, MSGL_ERR, "[vo_image] Error creating output directory"
- ": %s\n", errstr);
- return false;
- }
- return true;
-}
-
-static int config(struct vo *vo, uint32_t width, uint32_t height,
- uint32_t d_width, uint32_t d_height, uint32_t flags,
- uint32_t format)
-{
- struct priv *p = vo->priv;
-
- p->d_width = d_width;
- p->d_height = d_height;
-
- if (p->outdir && vo->config_count < 1)
- if (!checked_mkdir(p->outdir))
- return -1;
-
- return 0;
-}
-
-static void check_events(struct vo *vo)
-{
-}
-
-static void draw_osd(struct vo *vo, struct osd_state *osd)
-{
-}
-
-static void flip_page(struct vo *vo)
-{
-}
-
-static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
-{
- struct priv *p = vo->priv;
-
- mp_image_t img = *mpi;
- img.width = p->d_width;
- img.height = p->d_height;
- mp_image_set_colorspace_details(&img, &p->colorspace);
-
- void *t = talloc_new(NULL);
- char *filename = talloc_asprintf(t, "%08d.%s", p->frame,
- image_writer_file_ext(p->opts));
-
- if (p->outdir && strlen(p->outdir))
- filename = mp_path_join(t, bstr0(p->outdir), bstr0(filename));
-
- mp_msg(MSGT_VO, MSGL_STATUS, "\nSaving %s\n", filename);
- write_image(&img, p->opts, filename);
-
- talloc_free(t);
-
- (p->frame)++;
-
- return VO_TRUE;
-}
-
-static int query_format(struct vo *vo, uint32_t fmt)
-{
- enum PixelFormat av_format = imgfmt2pixfmt(fmt);
-
- // NOTE: accept everything that can be converted by swscale. screenshot.c
- // always wants RGB (at least for now), but it probably doesn't matter
- // whether we or screenshot.c do the conversion.
- if (av_format != PIX_FMT_NONE && sws_isSupportedInput(av_format))
- return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW |
- VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN;
- return 0;
-}
-
-static void uninit(struct vo *vo)
-{
-}
-
-static int preinit(struct vo *vo, const char *arg)
-{
- return 0;
-}
-
-static int control(struct vo *vo, uint32_t request, void *data)
-{
- struct priv *p = vo->priv;
-
- switch (request) {
- case VOCTRL_QUERY_FORMAT:
- return query_format(vo, *(uint32_t *)data);
- case VOCTRL_DRAW_IMAGE:
- return draw_image(vo, data);
- case VOCTRL_SET_YUV_COLORSPACE:
- p->colorspace = *(struct mp_csp_details *)data;
- return true;
- case VOCTRL_GET_YUV_COLORSPACE:
- *(struct mp_csp_details *)data = p->colorspace;
- return true;
- // prevent random frame stepping by frontend
- case VOCTRL_REDRAW_FRAME:
- return true;
- }
- return VO_NOTIMPL;
-}
-
-#undef OPT_BASE_STRUCT
-#define OPT_BASE_STRUCT struct priv
-
-const struct vo_driver video_out_image =
-{
- .is_new = true,
- .info = &(const vo_info_t) {
- "Write video frames to image files",
- "image",
- "wm4",
- ""
- },
- .priv_size = sizeof(struct priv),
- .priv_defaults = &(const struct priv) {
- .colorspace = MP_CSP_DETAILS_DEFAULTS,
- },
- .options = (const struct m_option[]) {
- OPT_SUBSTRUCT(opts, image_writer_conf, M_OPT_MERGE),
- OPT_STRING("outdir", outdir, 0),
- {0},
- },
- .preinit = preinit,
- .config = config,
- .control = control,
- .draw_osd = draw_osd,
- .flip_page = flip_page,
- .check_events = check_events,
- .uninit = uninit,
-};
diff --git a/libvo/vo_lavc.c b/libvo/vo_lavc.c
deleted file mode 100644
index b86cd76509..0000000000
--- a/libvo/vo_lavc.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * video encoding using libavformat
- * Copyright (C) 2010 Nicolas George <george@nsup.org>
- * Copyright (C) 2011 Rudolf Polzer <divVerent@xonotic.org>
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "mpcommon.h"
-#include "options.h"
-#include "fmt-conversion.h"
-#include "libmpcodecs/mp_image.h"
-#include "libmpcodecs/vfcap.h"
-#include "subopt-helper.h"
-#include "talloc.h"
-#include "video_out.h"
-
-#include "encode_lavc.h"
-
-#include "sub/sub.h"
-#include "sub/dec_sub.h"
-
-struct priv {
- uint8_t *buffer;
- size_t buffer_size;
- AVStream *stream;
- int have_first_packet;
-
- int harddup;
-
- double lastpts;
- int64_t lastipts;
- int64_t lastframeipts;
- double expected_next_pts;
- mp_image_t *lastimg;
- int lastimg_wants_osd;
- int lastdisplaycount;
-
- AVRational worst_time_base;
- int worst_time_base_is_stream;
-
- struct mp_csp_details colorspace;
-};
-
-static int preinit(struct vo *vo, const char *arg)
-{
- struct priv *vc;
- if (!encode_lavc_available(vo->encode_lavc_ctx)) {
- mp_msg(MSGT_ENCODE, MSGL_ERR,
- "vo-lavc: the option -o (output file) must be specified\n");
- return -1;
- }
- vo->priv = talloc_zero(vo, struct priv);
- vc = vo->priv;
- vc->harddup = vo->encode_lavc_ctx->options->harddup;
- vc->colorspace = (struct mp_csp_details) MP_CSP_DETAILS_DEFAULTS;
- return 0;
-}
-
-static void draw_image(struct vo *vo, mp_image_t *mpi, double pts);
-static void uninit(struct vo *vo)
-{
- struct priv *vc = vo->priv;
- if (!vc)
- return;
-
- if (vc->lastipts >= 0 && vc->stream)
- draw_image(vo, NULL, MP_NOPTS_VALUE);
-
- if (vc->lastimg) {
- // palette hack
- if (vc->lastimg->imgfmt == IMGFMT_RGB8
- || vc->lastimg->imgfmt == IMGFMT_BGR8)
- vc->lastimg->planes[1] = NULL;
- free_mp_image(vc->lastimg);
- vc->lastimg = NULL;
- }
-
- vo->priv = NULL;
-}
-
-static int config(struct vo *vo, uint32_t width, uint32_t height,
- uint32_t d_width, uint32_t d_height, uint32_t flags,
- uint32_t format)
-{
- struct priv *vc = vo->priv;
- enum PixelFormat pix_fmt = imgfmt2pixfmt(format);
- AVRational display_aspect_ratio, image_aspect_ratio;
- AVRational aspect;
-
- if (!vc)
- return -1;
-
- display_aspect_ratio.num = d_width;
- display_aspect_ratio.den = d_height;
- image_aspect_ratio.num = width;
- image_aspect_ratio.den = height;
- aspect = av_div_q(display_aspect_ratio, image_aspect_ratio);
-
- if (vc->stream) {
- /* NOTE:
- * in debug builds we get a "comparison between signed and unsigned"
- * warning here. We choose to ignore that; just because ffmpeg currently
- * uses a plain 'int' for these struct fields, it doesn't mean it always
- * will */
- if (width == vc->stream->codec->width &&
- height == vc->stream->codec->height) {
- if (aspect.num != vc->stream->codec->sample_aspect_ratio.num ||
- aspect.den != vc->stream->codec->sample_aspect_ratio.den) {
- /* aspect-only changes are not critical */
- mp_msg(MSGT_ENCODE, MSGL_WARN, "vo-lavc: unsupported pixel aspect "
- "ratio change from %d:%d to %d:%d\n",
- vc->stream->codec->sample_aspect_ratio.num,
- vc->stream->codec->sample_aspect_ratio.den,
- aspect.num, aspect.den);
- }
- return 0;
- }
-
- /* FIXME Is it possible with raw video? */
- mp_msg(MSGT_ENCODE, MSGL_ERR,
- "vo-lavc: resolution changes not supported.\n");
- goto error;
- }
-
- vc->lastipts = MP_NOPTS_VALUE;
- vc->lastframeipts = MP_NOPTS_VALUE;
-
- if (pix_fmt == PIX_FMT_NONE)
- goto error; /* imgfmt2pixfmt already prints something */
-
- vc->stream = encode_lavc_alloc_stream(vo->encode_lavc_ctx,
- AVMEDIA_TYPE_VIDEO);
- vc->stream->sample_aspect_ratio = vc->stream->codec->sample_aspect_ratio =
- aspect;
- vc->stream->codec->width = width;
- vc->stream->codec->height = height;
- vc->stream->codec->pix_fmt = pix_fmt;
-
- encode_lavc_set_csp(vo->encode_lavc_ctx, vc->stream, vc->colorspace.format);
- encode_lavc_set_csp_levels(vo->encode_lavc_ctx, vc->stream, vc->colorspace.levels_out);
-
- if (encode_lavc_open_codec(vo->encode_lavc_ctx, vc->stream) < 0)
- goto error;
-
- vc->colorspace.format = encode_lavc_get_csp(vo->encode_lavc_ctx, vc->stream);
- vc->colorspace.levels_out = encode_lavc_get_csp_levels(vo->encode_lavc_ctx, vc->stream);
-
- vc->buffer_size = 6 * width * height + 200;
- if (vc->buffer_size < FF_MIN_BUFFER_SIZE)
- vc->buffer_size = FF_MIN_BUFFER_SIZE;
- if (vc->buffer_size < sizeof(AVPicture))
- vc->buffer_size = sizeof(AVPicture);
-
- vc->buffer = talloc_size(vc, vc->buffer_size);
-
- vc->lastimg = alloc_mpi(width, height, format);
-
- // palette hack
- if (vc->lastimg->imgfmt == IMGFMT_RGB8 ||
- vc->lastimg->imgfmt == IMGFMT_BGR8)
- vc->lastimg->planes[1] = talloc_zero_size(vc, 1024);
-
- return 0;
-
-error:
- uninit(vo);
- return -1;
-}
-
-static int query_format(struct vo *vo, uint32_t format)
-{
- enum PixelFormat pix_fmt = imgfmt2pixfmt(format);
-
- if (!vo->encode_lavc_ctx)
- return 0;
-
- if (!encode_lavc_supports_pixfmt(vo->encode_lavc_ctx, pix_fmt))
- return 0;
-
- return
- VFCAP_CSP_SUPPORTED |
- // we can do it
- VFCAP_CSP_SUPPORTED_BY_HW |
- // we don't convert colorspaces here
- VFCAP_OSD |
- // we have OSD
- VOCAP_NOSLICES;
- // we don't use slices
-}
-
-static void write_packet(struct vo *vo, int size, AVPacket *packet)
-{
- struct priv *vc = vo->priv;
-
- if (size < 0) {
- mp_msg(MSGT_ENCODE, MSGL_ERR, "vo-lavc: error encoding\n");
- return;
- }
-
- if (size > 0) {
- packet->stream_index = vc->stream->index;
- if (packet->pts != AV_NOPTS_VALUE) {
- packet->pts = av_rescale_q(packet->pts,
- vc->stream->codec->time_base,
- vc->stream->time_base);
- } else {
- mp_msg(MSGT_ENCODE, MSGL_WARN, "vo-lavc: codec did not provide pts\n");
- packet->pts = av_rescale_q(vc->lastipts, vc->worst_time_base,
- vc->stream->time_base);
- }
- if (packet->dts != AV_NOPTS_VALUE) {
- packet->dts = av_rescale_q(packet->dts,
- vc->stream->codec->time_base,
- vc->stream->time_base);
- }
- if (packet->duration > 0) {
- packet->duration = av_rescale_q(packet->duration,
- vc->stream->codec->time_base,
- vc->stream->time_base);
- } else {
- // HACK: libavformat calculates dts wrong if the initial packet
- // duration is not set, but ONLY if the time base is "high" and if we
- // have b-frames!
- if (!packet->duration)
- if (!vc->have_first_packet)
- if (vc->stream->codec->has_b_frames
- || vc->stream->codec->max_b_frames)
- if (vc->stream->time_base.num * 1000LL <=
- vc->stream->time_base.den)
- packet->duration = FFMAX(1, av_rescale_q(1,
- vc->stream->codec->time_base, vc->stream->time_base));
- }
-
- if (encode_lavc_write_frame(vo->encode_lavc_ctx, packet) < 0) {
- mp_msg(MSGT_ENCODE, MSGL_ERR, "vo-lavc: error writing\n");
- return;
- }
-
- vc->have_first_packet = 1;
- }
-}
-
-static int encode_video(struct vo *vo, AVFrame *frame, AVPacket *packet)
-{
- struct priv *vc = vo->priv;
- if (encode_lavc_oformat_flags(vo->encode_lavc_ctx) & AVFMT_RAWPICTURE) {
- if (!frame)
- return 0;
- memcpy(vc->buffer, frame, sizeof(AVPicture));
- mp_msg(MSGT_ENCODE, MSGL_DBG2, "vo-lavc: got pts %f\n",
- frame->pts * (double) vc->stream->codec->time_base.num /
- (double) vc->stream->codec->time_base.den);
- packet->size = sizeof(AVPicture);
- return packet->size;
- } else {
- int got_packet = 0;
- int status = avcodec_encode_video2(vc->stream->codec, packet,
- frame, &got_packet);
- int size = (status < 0) ? status : got_packet ? packet->size : 0;
-
- if (frame)
- mp_msg(MSGT_ENCODE, MSGL_DBG2, "vo-lavc: got pts %f; out size: %d\n",
- frame->pts * (double) vc->stream->codec->time_base.num /
- (double) vc->stream->codec->time_base.den, size);
-
- encode_lavc_write_stats(vo->encode_lavc_ctx, vc->stream);
- return size;
- }
-}
-
-static void draw_image(struct vo *vo, mp_image_t *mpi, double pts)
-{
- struct priv *vc = vo->priv;
- struct encode_lavc_context *ectx = vo->encode_lavc_ctx;
- int i, size;
- AVFrame *frame;
- AVCodecContext *avc;
- int64_t frameipts;
- double nextpts;
-
- if (!vc)
- return;
- if (!encode_lavc_start(ectx)) {
- mp_msg(MSGT_ENCODE, MSGL_WARN, "vo-lavc: NOTE: skipped initial video frame (probably because audio is not there yet)\n");
- return;
- }
- if (pts == MP_NOPTS_VALUE) {
- if (mpi)
- mp_msg(MSGT_ENCODE, MSGL_WARN, "vo-lavc: frame without pts, please report; synthesizing pts instead\n");
- pts = vc->expected_next_pts;
- }
-
- avc = vc->stream->codec;
-
- if (vc->worst_time_base.den == 0) {
- //if (avc->time_base.num / avc->time_base.den >= vc->stream->time_base.num / vc->stream->time_base.den)
- if (avc->time_base.num * (double) vc->stream->time_base.den >=
- vc->stream->time_base.num * (double) avc->time_base.den) {
- mp_msg(MSGT_ENCODE, MSGL_V, "vo-lavc: NOTE: using codec time base "
- "(%d/%d) for frame dropping; the stream base (%d/%d) is "
- "not worse.\n", (int)avc->time_base.num,
- (int)avc->time_base.den, (int)vc->stream->time_base.num,
- (int)vc->stream->time_base.den);
- vc->worst_time_base = avc->time_base;
- vc->worst_time_base_is_stream = 0;
- } else {
- mp_msg(MSGT_ENCODE, MSGL_WARN, "vo-lavc: NOTE: not using codec time "
- "base (%d/%d) for frame dropping; the stream base (%d/%d) "
- "is worse.\n", (int)avc->time_base.num,
- (int)avc->time_base.den, (int)vc->stream->time_base.num,
- (int)vc->stream->time_base.den);
- vc->worst_time_base = vc->stream->time_base;
- vc->worst_time_base_is_stream = 1;
- }
-
- // NOTE: we use the following "axiom" of av_rescale_q:
- // if time base A is worse than time base B, then
- // av_rescale_q(av_rescale_q(x, A, B), B, A) == x
- // this can be proven as long as av_rescale_q rounds to nearest, which
- // it currently does
-
- // av_rescale_q(x, A, B) * B = "round x*A to nearest multiple of B"
- // and:
- // av_rescale_q(av_rescale_q(x, A, B), B, A) * A
- // == "round av_rescale_q(x, A, B)*B to nearest multiple of A"
- // == "round 'round x*A to nearest multiple of B' to nearest multiple of A"
- //
- // assume this fails. Then there is a value of x*A, for which the
- // nearest multiple of B is outside the range [(x-0.5)*A, (x+0.5)*A[.
- // Absurd, as this range MUST contain at least one multiple of B.
- }
-
- double timeunit = (double)vc->worst_time_base.num / vc->worst_time_base.den;
-
- double outpts;
- if (ectx->options->rawts)
- outpts = pts;
- else if (ectx->options->copyts) {
- // fix the discontinuity pts offset
- nextpts = pts;
- if (ectx->discontinuity_pts_offset == MP_NOPTS_VALUE) {
- ectx->discontinuity_pts_offset = ectx->next_in_pts - nextpts;
- }
- else if (fabs(nextpts + ectx->discontinuity_pts_offset - ectx->next_in_pts) > 30) {
- mp_msg(MSGT_ENCODE, MSGL_WARN,
- "vo-lavc: detected an unexpected discontinuity (pts jumped by "
- "%f seconds)\n",
- nextpts + ectx->discontinuity_pts_offset - ectx->next_in_pts);
- ectx->discontinuity_pts_offset = ectx->next_in_pts - nextpts;
- }
-
- outpts = pts + ectx->discontinuity_pts_offset;
- }
- else {
- // adjust pts by knowledge of audio pts vs audio playback time
- double duration = 0;
- if (ectx->last_video_in_pts != MP_NOPTS_VALUE)
- duration = pts - ectx->last_video_in_pts;
- if (duration < 0)
- duration = timeunit; // XXX warn about discontinuity?
- outpts = vc->lastpts + duration;
- if (ectx->audio_pts_offset != MP_NOPTS_VALUE) {
- double adj = outpts - pts - ectx->audio_pts_offset;
- adj = FFMIN(adj, duration * 0.1);
- adj = FFMAX(adj, -duration * 0.1);
- outpts -= adj;
- }
- }
- vc->lastpts = outpts;
- ectx->last_video_in_pts = pts;
- frameipts = floor((outpts + encode_lavc_getoffset(ectx, vc->stream))
- / timeunit + 0.5);
-
- // calculate expected pts of next video frame
- vc->expected_next_pts = pts + timeunit;
-
- if (!ectx->options->rawts && ectx->options->copyts) {
- // set next allowed output pts value
- nextpts = vc->expected_next_pts + ectx->discontinuity_pts_offset;
- if (nextpts > ectx->next_in_pts)
- ectx->next_in_pts = nextpts;
- }
-
- // never-drop mode
- if (ectx->options->neverdrop && frameipts <= vc->lastipts) {
- mp_msg(MSGT_ENCODE, MSGL_INFO, "vo-lavc: -oneverdrop increased pts by %d\n",
- (int) (vc->lastipts - frameipts + 1));
- frameipts = vc->lastipts + 1;
- vc->lastpts = frameipts * timeunit - encode_lavc_getoffset(ectx, vc->stream);
- }
-
- if (vc->lastipts != MP_NOPTS_VALUE) {
- frame = avcodec_alloc_frame();
-
- // we have a valid image in lastimg
- while (vc->lastipts < frameipts) {
- int64_t thisduration = vc->harddup ? 1 : (frameipts - vc->lastipts);
- AVPacket packet;
-
- avcodec_get_frame_defaults(frame);
-
- // this is a nop, unless the worst time base is the STREAM time base
- frame->pts = av_rescale_q(vc->lastipts, vc->worst_time_base,
- avc->time_base);
-
- for (i = 0; i < 4; i++) {
- frame->data[i] = vc->lastimg->planes[i];
- frame->linesize[i] = vc->lastimg->stride[i];
- }
- frame->quality = avc->global_quality;
-
- av_init_packet(&packet);
- packet.data = vc->buffer;
- packet.size = vc->buffer_size;
- size = encode_video(vo, frame, &packet);
- write_packet(vo, size, &packet);
-
- vc->lastipts += thisduration;
- ++vc->lastdisplaycount;
- }
-
- avcodec_free_frame(&frame);
- }
-
- if (!mpi) {
- // finish encoding
- do {
- AVPacket packet;
- av_init_packet(&packet);
- packet.data = vc->buffer;
- packet.size = vc->buffer_size;
- size = encode_video(vo, NULL, &packet);
- write_packet(vo, size, &packet);
- } while (size > 0);
- } else {
- if (frameipts >= vc->lastframeipts) {
- if (vc->lastframeipts != MP_NOPTS_VALUE && vc->lastdisplaycount != 1)
- mp_msg(MSGT_ENCODE, MSGL_INFO,
- "vo-lavc: Frame at pts %d got displayed %d times\n",
- (int) vc->lastframeipts, vc->lastdisplaycount);
- copy_mpi(vc->lastimg, mpi);
- vc->lastimg_wants_osd = true;
-
- // palette hack
- if (vc->lastimg->imgfmt == IMGFMT_RGB8 ||
- vc->lastimg->imgfmt == IMGFMT_BGR8)
- memcpy(vc->lastimg->planes[1], mpi->planes[1], 1024);
-
- vc->lastframeipts = vc->lastipts = frameipts;
- if (ectx->options->rawts && vc->lastipts < 0) {
- mp_msg(MSGT_ENCODE, MSGL_ERR, "vo-lavc: why does this happen? DEBUG THIS! vc->lastipts = %lld\n", (long long) vc->lastipts);
- vc->lastipts = -1;
- }
- vc->lastdisplaycount = 0;
- } else {
- mp_msg(MSGT_ENCODE, MSGL_INFO, "vo-lavc: Frame at pts %d got dropped "
- "entirely because pts went backwards\n", (int) frameipts);
- vc->lastimg_wants_osd = false;
- }
- }
-}
-
-static void flip_page_timed(struct vo *vo, unsigned int pts_us, int duration)
-{
-}
-
-static void check_events(struct vo *vo)
-{
-}
-
-static void draw_osd(struct vo *vo, struct osd_state *osd)
-{
- struct priv *vc = vo->priv;
-
- if (vc->lastimg && vc->lastimg_wants_osd) {
- struct aspect_data asp = vo->aspdat;
- double sar = (double)asp.orgw / asp.orgh;
- double dar = (double)asp.prew / asp.preh;
-
- struct mp_osd_res dim = {
- .w = asp.orgw,
- .h = asp.orgh,
- .display_par = sar / dar,
- .video_par = dar / sar,
- };
-
- mp_image_set_colorspace_details(vc->lastimg, &vc->colorspace);
-
- osd_draw_on_image(osd, dim, osd->vo_pts, OSD_DRAW_SUB_ONLY, vc->lastimg);
- }
-}
-
-static int control(struct vo *vo, uint32_t request, void *data)
-{
- struct priv *vc = vo->priv;
- switch (request) {
- case VOCTRL_QUERY_FORMAT:
- return query_format(vo, *((uint32_t *)data));
- case VOCTRL_DRAW_IMAGE:
- draw_image(vo, (mp_image_t *)data, vo->next_pts);
- return 0;
- case VOCTRL_SET_YUV_COLORSPACE:
- vc->colorspace = *(struct mp_csp_details *)data;
- if (vc->stream) {
- encode_lavc_set_csp(vo->encode_lavc_ctx, vc->stream, vc->colorspace.format);
- encode_lavc_set_csp_levels(vo->encode_lavc_ctx, vc->stream, vc->colorspace.levels_out);
- vc->colorspace.format = encode_lavc_get_csp(vo->encode_lavc_ctx, vc->stream);
- vc->colorspace.levels_out = encode_lavc_get_csp_levels(vo->encode_lavc_ctx, vc->stream);
- }
- return 1;
- case VOCTRL_GET_YUV_COLORSPACE:
- *(struct mp_csp_details *)data = vc->colorspace;
- return 1;
- }
- return VO_NOTIMPL;
-}
-
-const struct vo_driver video_out_lavc = {
- .is_new = true,
- .buffer_frames = false,
- .info = &(const struct vo_info_s){
- "video encoding using libavcodec",
- "lavc",
- "Nicolas George <george@nsup.org>, Rudolf Polzer <divVerent@xonotic.org>",
- ""
- },
- .preinit = preinit,
- .config = config,
- .control = control,
- .uninit = uninit,
- .check_events = check_events,
- .draw_osd = draw_osd,
- .flip_page_timed = flip_page_timed,
-};
-
-// vim: sw=4 ts=4 et tw=80
diff --git a/libvo/vo_null.c b/libvo/vo_null.c
deleted file mode 100644
index 1f307f7f5b..0000000000
--- a/libvo/vo_null.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * based on video_out_null.c from mpeg2dec
- *
- * Copyright (C) Aaron Holtzman - June 2000
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include "config.h"
-#include "mp_msg.h"
-#include "video_out.h"
-#include "libmpcodecs/vfcap.h"
-#include "libmpcodecs/mp_image.h"
-
-static int draw_slice(struct vo *vo, uint8_t *image[], int stride[],
- int w, int h, int x, int y)
-{
- return 0;
-}
-
-static void draw_osd(struct vo *vo, struct osd_state *osd)
-{
-}
-
-static void flip_page(struct vo *vo)
-{
-}
-
-static int query_format(struct vo *vo, uint32_t format)
-{
- if (IMGFMT_IS_HWACCEL(format))
- return 0;
- return VFCAP_CSP_SUPPORTED;
-}
-
-static int config(struct vo *vo, uint32_t width, uint32_t height,
- uint32_t d_width, uint32_t d_height, uint32_t flags,
- uint32_t format)
-{
- return 0;
-}
-
-static void uninit(struct vo *vo)
-{
-}
-
-static void check_events(struct vo *vo)
-{
-}
-
-static int preinit(struct vo *vo, const char *arg)
-{
- if (arg) {
- mp_tmsg(MSGT_VO, MSGL_WARN, "[VO_NULL] Unknown subdevice: %s.\n", arg);
- return ENOSYS;
- }
- return 0;
-}
-
-static int control(struct vo *vo, uint32_t request, void *data)
-{
- switch (request) {
- case VOCTRL_QUERY_FORMAT:
- return query_format(vo, *((uint32_t *)data));
- }
- return VO_NOTIMPL;
-}
-
-const struct vo_driver video_out_null = {
- .is_new = false,
- .info = &(const vo_info_t) {
- "Null video output",
- "null",
- "Aaron Holtzman <aholtzma@ess.engr.uvic.ca>",
- ""
- },
- .preinit = preinit,
- .config = config,
- .control = control,
- .draw_slice = draw_slice,
- .draw_osd = draw_osd,
- .flip_page = flip_page,
- .check_events = check_events,
- .uninit = uninit,
-};
diff --git a/libvo/vo_opengl.c b/libvo/vo_opengl.c
deleted file mode 100644
index 7b5289838f..0000000000
--- a/libvo/vo_opengl.c
+++ /dev/null
@@ -1,2419 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * You can alternatively redistribute this file and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <stdbool.h>
-#include <assert.h>
-#include "config.h"
-
-#include <libavutil/common.h>
-
-#ifdef CONFIG_LCMS2
-#include <lcms2.h>
-#include "stream/stream.h"
-#endif
-
-#include "talloc.h"
-#include "mpcommon.h"
-#include "bstr.h"
-#include "mp_msg.h"
-#include "subopt-helper.h"
-#include "video_out.h"
-#include "libmpcodecs/vfcap.h"
-#include "libmpcodecs/mp_image.h"
-#include "geometry.h"
-#include "sub/sub.h"
-#include "bitmap_packer.h"
-
-#include "gl_common.h"
-#include "gl_osd.h"
-#include "filter_kernels.h"
-#include "aspect.h"
-#include "fastmemcpy.h"
-
-static const char vo_opengl_shaders[] =
-// Generated from libvo/vo_opengl_shaders.glsl
-#include "libvo/vo_opengl_shaders.h"
-;
-
-// Pixel width of 1D lookup textures.
-#define LOOKUP_TEXTURE_SIZE 256
-
-// Texture units 0-2 are used by the video, with unit 0 for free use.
-// Units 3-4 are used for scaler LUTs.
-#define TEXUNIT_SCALERS 3
-#define TEXUNIT_3DLUT 5
-#define TEXUNIT_DITHER 6
-
-// lscale/cscale arguments that map directly to shader filter routines.
-// Note that the convolution filters are not included in this list.
-static const char *fixed_scale_filters[] = {
- "bilinear",
- "bicubic_fast",
- "sharpen3",
- "sharpen5",
- NULL
-};
-
-struct lut_tex_format {
- int pixels;
- GLint internal_format;
- GLenum format;
-};
-
-// Indexed with filter_kernel->size.
-// This must match the weightsN functions in the shader.
-// Each entry uses (size+3)/4 pixels per LUT entry, and size/pixels components
-// per pixel.
-struct lut_tex_format lut_tex_formats[] = {
- [2] = {1, GL_RG16F, GL_RG},
- [4] = {1, GL_RGBA16F, GL_RGBA},
- [6] = {2, GL_RGB16F, GL_RGB},
- [8] = {2, GL_RGBA16F, GL_RGBA},
- [12] = {3, GL_RGBA16F, GL_RGBA},
- [16] = {4, GL_RGBA16F, GL_RGBA},
-};
-
-// must be sorted, and terminated with 0
-static const int filter_sizes[] = {2, 4, 6, 8, 12, 16, 0};
-
-struct vertex {
- float position[2];
- uint8_t color[4];
- float texcoord[2];
-};
-
-#define VERTEX_ATTRIB_POSITION 0
-#define VERTEX_ATTRIB_COLOR 1
-#define VERTEX_ATTRIB_TEXCOORD 2
-
-// 2 triangles primitives per quad = 6 vertices per quad
-// (GL_QUAD is deprecated, strips can't be used with OSD image lists)
-#define VERTICES_PER_QUAD 6
-
-struct texplane {
- int shift_x, shift_y;
- GLuint gl_texture;
- int gl_buffer;
- int buffer_size;
- void *buffer_ptr;
-};
-
-struct scaler {
- int index;
- const char *name;
- float params[2];
- struct filter_kernel *kernel;
- GLuint gl_lut;
- const char *lut_name;
-
- // kernel points here
- struct filter_kernel kernel_storage;
-};
-
-struct fbotex {
- GLuint fbo;
- GLuint texture;
- int tex_w, tex_h; // size of .texture
- int vp_w, vp_h; // viewport of fbo / used part of the texture
-};
-
-struct gl_priv {
- struct vo *vo;
- MPGLContext *glctx;
- GL *gl;
-
- int use_indirect;
- int use_gamma;
- int use_srgb;
- int use_scale_sep;
- int use_fancy_downscaling;
- int use_lut_3d;
- int use_npot;
- int use_pbo;
- int use_glFinish;
- int use_gl_debug;
- int allow_sw;
-
- int dither_depth;
- int swap_interval;
- GLint fbo_format;
- int stereo_mode;
- int osd_color;
-
- struct gl_priv *defaults;
- struct gl_priv *orig_cmdline;
-
- GLuint vertex_buffer;
- GLuint vao;
-
- GLuint osd_programs[SUBBITMAP_COUNT];
- GLuint indirect_program, scale_sep_program, final_program;
-
- struct mpgl_osd *osd;
-
- GLuint lut_3d_texture;
- int lut_3d_w, lut_3d_h, lut_3d_d;
- void *lut_3d_data;
-
- GLuint dither_texture;
- float dither_quantization;
- float dither_multiply;
- int dither_size;
-
- uint32_t image_width;
- uint32_t image_height;
- uint32_t image_format;
- int texture_width;
- int texture_height;
-
- bool is_yuv;
- bool is_linear_rgb;
-
- // per pixel (full pixel when packed, each component when planar)
- int plane_bytes;
- int plane_bits;
- int component_bits;
-
- GLint gl_internal_format;
- GLenum gl_format;
- GLenum gl_type;
-
- int plane_count;
- struct texplane planes[3];
-
- struct fbotex indirect_fbo; // RGB target
- struct fbotex scale_sep_fbo; // first pass when doing 2 pass scaling
-
- // state for luma (0) and chroma (1) scalers
- struct scaler scalers[2];
- // luma scaler parameters (the same are used for chroma)
- float scaler_params[2];
-
- struct mp_csp_details colorspace;
- struct mp_csp_equalizer video_eq;
-
- int mpi_flipped;
- int vo_flipped;
-
- struct mp_rect src_rect; // displayed part of the source video
- struct mp_rect dst_rect; // video rectangle on output window
- struct mp_osd_res osd_rect; // OSD size/margins
- int vp_x, vp_y, vp_w, vp_h; // GL viewport
-
- int frames_rendered;
-
- void *scratch;
-};
-
-struct fmt_entry {
- int mp_format;
- GLint internal_format;
- GLenum format;
- int component_bits;
- GLenum type;
-};
-
-static const struct fmt_entry mp_to_gl_formats[] = {
- {IMGFMT_RGB48NE, GL_RGB16, GL_RGB, 16, GL_UNSIGNED_SHORT},
- {IMGFMT_RGB24, GL_RGB, GL_RGB, 8, GL_UNSIGNED_BYTE},
- {IMGFMT_RGBA, GL_RGBA, GL_RGBA, 8, GL_UNSIGNED_BYTE},
- {IMGFMT_RGB15, GL_RGBA, GL_RGBA, 5, GL_UNSIGNED_SHORT_1_5_5_5_REV},
- {IMGFMT_RGB16, GL_RGB, GL_RGB, 6, GL_UNSIGNED_SHORT_5_6_5_REV},
- {IMGFMT_BGR15, GL_RGBA, GL_BGRA, 5, GL_UNSIGNED_SHORT_1_5_5_5_REV},
- {IMGFMT_BGR16, GL_RGB, GL_RGB, 6, GL_UNSIGNED_SHORT_5_6_5},
- {IMGFMT_BGR24, GL_RGB, GL_BGR, 8, GL_UNSIGNED_BYTE},
- {IMGFMT_BGRA, GL_RGBA, GL_BGRA, 8, GL_UNSIGNED_BYTE},
- {0},
-};
-
-static const char *osd_shaders[SUBBITMAP_COUNT] = {
- [SUBBITMAP_LIBASS] = "frag_osd_libass",
- [SUBBITMAP_RGBA] = "frag_osd_rgba",
-};
-
-
-static const char help_text[];
-
-static void uninit_rendering(struct gl_priv *p);
-static void delete_shaders(struct gl_priv *p);
-static bool reparse_cmdline(struct gl_priv *p, char *arg);
-
-
-static void default_tex_params(struct GL *gl, GLenum target, GLint filter)
-{
- gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
- gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
- gl->TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gl->TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-}
-
-static void debug_check_gl(struct gl_priv *p, const char *msg)
-{
- if (p->use_gl_debug || p->frames_rendered < 5)
- glCheckError(p->gl, msg);
-}
-
-static void tex_size(struct gl_priv *p, int w, int h, int *texw, int *texh)
-{
- if (p->use_npot) {
- *texw = w;
- *texh = h;
- } else {
- *texw = 32;
- while (*texw < w)
- *texw *= 2;
- *texh = 32;
- while (*texh < h)
- *texh *= 2;
- }
-}
-
-static void draw_triangles(struct gl_priv *p, struct vertex *vb, int vert_count)
-{
- GL *gl = p->gl;
-
- assert(vert_count % 3 == 0);
-
- gl->BindBuffer(GL_ARRAY_BUFFER, p->vertex_buffer);
- gl->BufferData(GL_ARRAY_BUFFER, vert_count * sizeof(struct vertex), vb,
- GL_DYNAMIC_DRAW);
- gl->BindBuffer(GL_ARRAY_BUFFER, 0);
-
- if (gl->BindVertexArray)
- gl->BindVertexArray(p->vao);
-
- gl->DrawArrays(GL_TRIANGLES, 0, vert_count);
-
- if (gl->BindVertexArray)
- gl->BindVertexArray(0);
-
- debug_check_gl(p, "after rendering");
-}
-
-// Write a textured quad to a vertex array.
-// va = destination vertex array, VERTICES_PER_QUAD entries will be overwritten
-// x0, y0, x1, y1 = destination coordinates of the quad
-// tx0, ty0, tx1, ty1 = source texture coordinates (usually in pixels)
-// texture_w, texture_h = size of the texture, or an inverse factor
-// color = optional color for all vertices, NULL for opaque white
-// flip = flip vertically
-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)
-{
- 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 (flip) {
- float tmp = ty0;
- ty0 = ty1;
- ty1 = tmp;
- }
-
-#define COLOR_INIT {color[0], color[1], color[2], color[3]}
- va[0] = (struct vertex) { {x0, y0}, COLOR_INIT, {tx0, ty0} };
- va[1] = (struct vertex) { {x0, y1}, COLOR_INIT, {tx0, ty1} };
- va[2] = (struct vertex) { {x1, y0}, COLOR_INIT, {tx1, ty0} };
- va[3] = (struct vertex) { {x1, y1}, COLOR_INIT, {tx1, ty1} };
- va[4] = va[2];
- va[5] = va[1];
-#undef COLOR_INIT
-}
-
-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);
-
- tex_size(p, w, h, &fbo->tex_w, &fbo->tex_h);
-
- fbo->vp_w = w;
- fbo->vp_h = h;
-
- mp_msg(MSGT_VO, MSGL_V, "[gl] Create FBO: %dx%d\n", fbo->tex_w, fbo->tex_h);
-
- gl->GenFramebuffers(1, &fbo->fbo);
- gl->GenTextures(1, &fbo->texture);
- gl->BindTexture(GL_TEXTURE_2D, fbo->texture);
- gl->TexImage2D(GL_TEXTURE_2D, 0, p->fbo_format, fbo->tex_w, fbo->tex_h, 0,
- GL_RGB, GL_UNSIGNED_BYTE, NULL);
- default_tex_params(gl, GL_TEXTURE_2D, GL_LINEAR);
- gl->BindFramebuffer(GL_FRAMEBUFFER, fbo->fbo);
- gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, fbo->texture, 0);
-
- 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;
-
- 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,
- float y0, float y1)
-{
- memset(m, 0, 9 * sizeof(float));
- m[0][0] = 2.0f / (x1 - x0);
- m[1][1] = 2.0f / (y1 - y0);
- m[2][0] = -(x1 + x0) / (x1 - x0);
- m[2][1] = -(y1 + y0) / (y1 - y0);
- m[2][2] = 1.0f;
-}
-
-static void update_uniforms(struct gl_priv *p, GLuint program)
-{
- GL *gl = p->gl;
- GLint loc;
-
- if (program == 0)
- return;
-
- gl->UseProgram(program);
-
- struct mp_csp_params cparams = {
- .colorspace = p->colorspace,
- .input_bits = p->plane_bits,
- .texture_bits = (p->plane_bits + 7) & ~7,
- };
- mp_csp_copy_equalizer_values(&cparams, &p->video_eq);
-
- loc = gl->GetUniformLocation(program, "transform");
- if (loc >= 0) {
- float matrix[3][3];
- matrix_ortho2d(matrix, 0, p->vp_w, p->vp_h, 0);
- gl->UniformMatrix3fv(loc, 1, GL_FALSE, &matrix[0][0]);
- }
-
- loc = gl->GetUniformLocation(program, "colormatrix");
- if (loc >= 0) {
- float yuv2rgb[3][4] = {{0}};
- if (p->is_yuv)
- mp_get_yuv2rgb_coeffs(&cparams, yuv2rgb);
- gl->UniformMatrix4x3fv(loc, 1, GL_TRUE, &yuv2rgb[0][0]);
- }
-
- gl->Uniform3f(gl->GetUniformLocation(program, "inv_gamma"),
- 1.0 / cparams.rgamma,
- 1.0 / cparams.ggamma,
- 1.0 / cparams.bgamma);
-
- 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);
-
- for (int n = 0; n < 2; n++) {
- const char *lut = p->scalers[n].lut_name;
- if (lut)
- gl->Uniform1i(gl->GetUniformLocation(program, lut),
- TEXUNIT_SCALERS + n);
- }
-
- gl->Uniform1i(gl->GetUniformLocation(program, "dither"), TEXUNIT_DITHER);
- gl->Uniform1f(gl->GetUniformLocation(program, "dither_quantization"),
- p->dither_quantization);
- gl->Uniform1f(gl->GetUniformLocation(program, "dither_multiply"),
- p->dither_multiply);
-
- float sparam1 = p->scaler_params[0];
- gl->Uniform1f(gl->GetUniformLocation(program, "filter_param1"),
- isnan(sparam1) ? 0.5f : sparam1);
-
- loc = gl->GetUniformLocation(program, "osd_color");
- if (loc >= 0) {
- int r = (p->osd_color >> 16) & 0xff;
- int g = (p->osd_color >> 8) & 0xff;
- int b = p->osd_color & 0xff;
- int a = 0xff - (p->osd_color >> 24);
- gl->Uniform4f(loc, r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
- }
-
- gl->UseProgram(0);
-
- debug_check_gl(p, "update_uniforms()");
-}
-
-static void update_all_uniforms(struct gl_priv *p)
-{
- for (int n = 0; n < SUBBITMAP_COUNT; n++)
- update_uniforms(p, p->osd_programs[n]);
- update_uniforms(p, p->indirect_program);
- update_uniforms(p, p->scale_sep_program);
- update_uniforms(p, p->final_program);
-}
-
-#define SECTION_HEADER "#!section "
-
-static char *get_section(void *talloc_ctx, struct bstr source,
- const char *section)
-{
- char *res = talloc_strdup(talloc_ctx, "");
- bool copy = false;
- while (source.len) {
- struct bstr line = bstr_strip_linebreaks(bstr_getline(source, &source));
- if (bstr_eatstart(&line, bstr0(SECTION_HEADER))) {
- copy = bstrcmp0(line, section) == 0;
- } else if (copy) {
- res = talloc_asprintf_append_buffer(res, "%.*s\n", BSTR_P(line));
- }
- }
- return res;
-}
-
-static char *t_concat(void *talloc_ctx, const char *s1, const char *s2)
-{
- return talloc_asprintf(talloc_ctx, "%s%s", s1, s2);
-}
-
-static GLuint create_shader(GL *gl, GLenum type, const char *header,
- const char *source)
-{
- void *tmp = talloc_new(NULL);
- const char *full_source = t_concat(tmp, header, source);
-
- GLuint shader = gl->CreateShader(type);
- gl->ShaderSource(shader, 1, &full_source, NULL);
- gl->CompileShader(shader);
- GLint status;
- gl->GetShaderiv(shader, GL_COMPILE_STATUS, &status);
- GLint log_length;
- gl->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
-
- int pri = status ? (log_length > 1 ? MSGL_V : MSGL_DBG2) : MSGL_ERR;
- const char *typestr = type == GL_VERTEX_SHADER ? "vertex" : "fragment";
- if (mp_msg_test(MSGT_VO, pri)) {
- mp_msg(MSGT_VO, pri, "[gl] %s shader source:\n", typestr);
- mp_log_source(MSGT_VO, pri, full_source);
- }
- if (log_length > 1) {
- GLchar *log = talloc_zero_size(tmp, log_length + 1);
- gl->GetShaderInfoLog(shader, log_length, NULL, log);
- mp_msg(MSGT_VO, pri, "[gl] %s shader compile log (status=%d):\n%s\n",
- typestr, status, log);
- }
-
- talloc_free(tmp);
-
- return shader;
-}
-
-static void prog_create_shader(GL *gl, GLuint program, GLenum type,
- const char *header, const char *source)
-{
- GLuint shader = create_shader(gl, type, header, source);
- gl->AttachShader(program, shader);
- gl->DeleteShader(shader);
-}
-
-static void link_shader(GL *gl, GLuint program)
-{
- gl->LinkProgram(program);
- GLint status;
- gl->GetProgramiv(program, GL_LINK_STATUS, &status);
- GLint log_length;
- gl->GetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
-
- int pri = status ? (log_length > 1 ? MSGL_V : MSGL_DBG2) : MSGL_ERR;
- if (mp_msg_test(MSGT_VO, pri)) {
- GLchar *log = talloc_zero_size(NULL, log_length + 1);
- gl->GetProgramInfoLog(program, log_length, NULL, log);
- mp_msg(MSGT_VO, pri, "[gl] shader link log (status=%d): %s\n",
- status, log);
- talloc_free(log);
- }
-}
-
-static void bind_attrib_locs(GL *gl, GLuint program)
-{
- gl->BindAttribLocation(program, VERTEX_ATTRIB_POSITION, "vertex_position");
- gl->BindAttribLocation(program, VERTEX_ATTRIB_COLOR, "vertex_color");
- gl->BindAttribLocation(program, VERTEX_ATTRIB_TEXCOORD, "vertex_texcoord");
-}
-
-static GLuint create_program(GL *gl, const char *name, const char *header,
- const char *vertex, const char *frag)
-{
- mp_msg(MSGT_VO, MSGL_V, "[gl] compiling shader program '%s'\n", name);
- mp_msg(MSGT_VO, MSGL_V, "[gl] header:\n");
- mp_log_source(MSGT_VO, MSGL_V, header);
- GLuint prog = gl->CreateProgram();
- prog_create_shader(gl, prog, GL_VERTEX_SHADER, header, vertex);
- prog_create_shader(gl, prog, GL_FRAGMENT_SHADER, header, frag);
- bind_attrib_locs(gl, prog);
- link_shader(gl, prog);
- return prog;
-}
-
-static void shader_def(char **shader, const char *name,
- const char *value)
-{
- *shader = talloc_asprintf_append(*shader, "#define %s %s\n", name, value);
-}
-
-static void shader_def_opt(char **shader, const char *name, bool b)
-{
- if (b)
- shader_def(shader, name, "1");
-}
-
-static void shader_setup_scaler(char **shader, struct scaler *scaler, int pass)
-{
- const char *target = scaler->index == 0 ? "SAMPLE_L" : "SAMPLE_C";
- if (!scaler->kernel) {
- *shader = talloc_asprintf_append(*shader, "#define %s sample_%s\n",
- target, scaler->name);
- } else {
- int size = scaler->kernel->size;
- if (pass != -1) {
- // 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, 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, p2) "
- "sample_convolution%d(%s, p0, p1, p2)\n",
- target, size, scaler->lut_name);
- }
- }
-}
-
-// return false if RGB or 4:4:4 YUV
-static bool input_is_subsampled(struct gl_priv *p)
-{
- for (int i = 0; i < p->plane_count; i++)
- if (p->planes[i].shift_x || p->planes[i].shift_y)
- return true;
- return false;
-}
-
-static void compile_shaders(struct gl_priv *p)
-{
- GL *gl = p->gl;
-
- delete_shaders(p);
-
- void *tmp = talloc_new(NULL);
-
- struct bstr src = bstr0(vo_opengl_shaders);
- char *vertex_shader = get_section(tmp, src, "vertex_all");
- char *shader_prelude = get_section(tmp, src, "prelude");
- char *s_video = get_section(tmp, src, "frag_video");
-
- char *header = talloc_asprintf(tmp, "#version %d\n%s", gl->glsl_version,
- shader_prelude);
-
- char *header_osd = talloc_strdup(tmp, header);
- shader_def_opt(&header_osd, "USE_OSD_LINEAR_CONV", p->use_srgb &&
- !p->use_lut_3d);
- shader_def_opt(&header_osd, "USE_OSD_3DLUT", p->use_lut_3d);
- shader_def_opt(&header_osd, "USE_OSD_SRGB", p->use_srgb);
-
- for (int n = 0; n < SUBBITMAP_COUNT; n++) {
- const char *name = osd_shaders[n];
- if (name) {
- char *s_osd = get_section(tmp, src, name);
- p->osd_programs[n] =
- create_program(gl, name, header_osd, vertex_shader, s_osd);
- }
- }
-
- char *header_conv = talloc_strdup(tmp, "");
- char *header_final = talloc_strdup(tmp, "");
- char *header_sep = NULL;
-
- bool convert_input_to_linear = !p->is_linear_rgb
- && (p->use_srgb || p->use_lut_3d);
-
- shader_def_opt(&header_conv, "USE_PLANAR", p->plane_count > 1);
- shader_def_opt(&header_conv, "USE_GBRP", p->image_format == IMGFMT_GBRP);
- shader_def_opt(&header_conv, "USE_YGRAY", p->is_yuv && p->plane_count == 1);
- shader_def_opt(&header_conv, "USE_COLORMATRIX", p->is_yuv);
- shader_def_opt(&header_conv, "USE_LINEAR_CONV", convert_input_to_linear);
-
- shader_def_opt(&header_final, "USE_LINEAR_CONV_INV", p->use_lut_3d);
- shader_def_opt(&header_final, "USE_GAMMA_POW", p->use_gamma);
- shader_def_opt(&header_final, "USE_3DLUT", p->use_lut_3d);
- shader_def_opt(&header_final, "USE_SRGB", p->use_srgb);
- shader_def_opt(&header_final, "USE_DITHER", p->dither_texture != 0);
-
- if (p->use_scale_sep && p->scalers[0].kernel) {
- header_sep = talloc_strdup(tmp, "");
- shader_def_opt(&header_sep, "FIXED_SCALE", true);
- shader_setup_scaler(&header_sep, &p->scalers[0], 0);
- shader_setup_scaler(&header_final, &p->scalers[0], 1);
- } else {
- shader_setup_scaler(&header_final, &p->scalers[0], -1);
- }
-
- // We want to do scaling in linear light. Scaling is closely connected to
- // texture sampling due to how the shader is structured (or if GL bilinear
- // scaling is used). The purpose of the "indirect" pass is to convert the
- // input video to linear RGB.
- // Another purpose is reducing input to a single texture for scaling.
- bool use_indirect = p->use_indirect;
-
- // Don't sample from input video textures before converting the input to
- // linear light. (Unneeded when sRGB textures are used.)
- if (convert_input_to_linear)
- use_indirect = true;
-
- // It doesn't make sense to scale the chroma with cscale in the 1. scale
- // step and with lscale in the 2. step. If the chroma is subsampled, a
- // convolution filter wouldn't even work entirely correctly, because the
- // luma scaler would sample two texels instead of one per tap for chroma.
- // Also, even with 4:4:4 YUV or planar RGB, the indirection might be faster,
- // because the shader can't use one scaler for sampling from 3 textures. It
- // has to fetch the coefficients for each texture separately, even though
- // they're the same (this is not an inherent restriction, but would require
- // to restructure the shader).
- if (header_sep && p->plane_count > 1)
- use_indirect = true;
-
- if (input_is_subsampled(p)) {
- shader_setup_scaler(&header_conv, &p->scalers[1], -1);
- } else {
- // Force using the luma scaler on chroma. If the "indirect" stage is
- // used, the actual scaling will happen in the next stage.
- shader_def(&header_conv, "SAMPLE_C",
- use_indirect ? "sample_bilinear" : "SAMPLE_L");
- }
-
- if (use_indirect) {
- // We don't use filtering for the Y-plane (luma), because it's never
- // scaled in this scenario.
- shader_def(&header_conv, "SAMPLE_L", "sample_bilinear");
- shader_def_opt(&header_conv, "FIXED_SCALE", true);
- header_conv = t_concat(tmp, header, header_conv);
- p->indirect_program =
- create_program(gl, "indirect", header_conv, vertex_shader, s_video);
- } else if (header_sep) {
- header_sep = t_concat(tmp, header_sep, header_conv);
- } else {
- header_final = t_concat(tmp, header_final, header_conv);
- }
-
- if (header_sep) {
- header_sep = t_concat(tmp, header, header_sep);
- p->scale_sep_program =
- create_program(gl, "scale_sep", header_sep, vertex_shader, s_video);
- }
-
- header_final = t_concat(tmp, header, header_final);
- p->final_program =
- create_program(gl, "final", header_final, vertex_shader, s_video);
-
- debug_check_gl(p, "shader compilation");
-
- talloc_free(tmp);
-}
-
-static void delete_program(GL *gl, GLuint *prog)
-{
- gl->DeleteProgram(*prog);
- *prog = 0;
-}
-
-static void delete_shaders(struct gl_priv *p)
-{
- GL *gl = p->gl;
-
- for (int n = 0; n < SUBBITMAP_COUNT; n++)
- delete_program(gl, &p->osd_programs[n]);
- delete_program(gl, &p->indirect_program);
- delete_program(gl, &p->scale_sep_program);
- delete_program(gl, &p->final_program);
-}
-
-static double get_scale_factor(struct gl_priv *p)
-{
- double sx = (p->dst_rect.x1 - p->dst_rect.x0) /
- (double)(p->src_rect.x1 - p->src_rect.x0);
- double sy = (p->dst_rect.y1 - p->dst_rect.y0) /
- (double)(p->src_rect.y1 - p->src_rect.y0);
- // xxx: actually we should use different scalers in X/Y directions if the
- // scale factors are different due to anamorphic content
- return FFMIN(sx, sy);
-}
-
-static bool update_scale_factor(struct gl_priv *p, struct filter_kernel *kernel)
-{
- double scale = get_scale_factor(p);
- if (!p->use_fancy_downscaling && scale < 1.0)
- scale = 1.0;
- return mp_init_filter(kernel, filter_sizes, FFMAX(1.0, 1.0 / scale));
-}
-
-static void init_scaler(struct gl_priv *p, struct scaler *scaler)
-{
- GL *gl = p->gl;
-
- assert(scaler->name);
-
- scaler->kernel = NULL;
-
- const struct filter_kernel *t_kernel = mp_find_filter_kernel(scaler->name);
- if (!t_kernel)
- return;
-
- scaler->kernel_storage = *t_kernel;
- scaler->kernel = &scaler->kernel_storage;
-
- for (int n = 0; n < 2; n++) {
- if (!isnan(p->scaler_params[n]))
- scaler->kernel->params[n] = p->scaler_params[n];
- }
-
- update_scale_factor(p, scaler->kernel);
-
- int size = scaler->kernel->size;
- assert(size < FF_ARRAY_ELEMS(lut_tex_formats));
- struct lut_tex_format *fmt = &lut_tex_formats[size];
- bool use_2d = fmt->pixels > 1;
- bool is_luma = scaler->index == 0;
- scaler->lut_name = use_2d
- ? (is_luma ? "lut_l_2d" : "lut_c_2d")
- : (is_luma ? "lut_l_1d" : "lut_c_1d");
-
- gl->ActiveTexture(GL_TEXTURE0 + TEXUNIT_SCALERS + scaler->index);
- GLenum target = use_2d ? GL_TEXTURE_2D : GL_TEXTURE_1D;
-
- if (!scaler->gl_lut)
- gl->GenTextures(1, &scaler->gl_lut);
-
- gl->BindTexture(target, scaler->gl_lut);
- gl->PixelStorei(GL_UNPACK_ALIGNMENT, 4);
- gl->PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-
- float *weights = talloc_array(NULL, float, LOOKUP_TEXTURE_SIZE * size);
- mp_compute_lut(scaler->kernel, LOOKUP_TEXTURE_SIZE, weights);
- if (use_2d) {
- gl->TexImage2D(GL_TEXTURE_2D, 0, fmt->internal_format, fmt->pixels,
- LOOKUP_TEXTURE_SIZE, 0, fmt->format, GL_FLOAT,
- weights);
- } else {
- gl->TexImage1D(GL_TEXTURE_1D, 0, fmt->internal_format,
- LOOKUP_TEXTURE_SIZE, 0, fmt->format, GL_FLOAT,
- weights);
- }
- talloc_free(weights);
-
- gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gl->TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gl->TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- gl->ActiveTexture(GL_TEXTURE0);
-
- debug_check_gl(p, "after initializing scaler");
-}
-
-static void make_dither_matrix(unsigned char *m, int size)
-{
- m[0] = 0;
- for (int sz = 1; sz < size; sz *= 2) {
- int offset[] = {sz*size, sz, sz * (size+1), 0};
- for (int i = 0; i < 4; i++)
- for (int y = 0; y < sz * size; y += size)
- for (int x = 0; x < sz; x++)
- m[x+y+offset[i]] = m[x+y] * 4 + (3-i) * 256/size/size;
- }
-}
-
-static void init_dither(struct gl_priv *p)
-{
- GL *gl = p->gl;
-
- // Assume 8 bits per component if unknown.
- int dst_depth = p->glctx->depth_g ? p->glctx->depth_g : 8;
- if (p->dither_depth > 0)
- dst_depth = p->dither_depth;
-
- int src_depth = p->component_bits;
- if (p->use_lut_3d)
- src_depth = 16;
-
- if (dst_depth >= src_depth || p->dither_depth < 0 || src_depth < 0)
- return;
-
- mp_msg(MSGT_VO, MSGL_V, "[gl] Dither %d->%d.\n", src_depth, dst_depth);
-
- // This defines how many bits are considered significant for output on
- // screen. The superfluous bits will be used for rounded according to the
- // dither matrix. The precision of the source implicitly decides how many
- // dither patterns can be visible.
- p->dither_quantization = (1 << dst_depth) - 1;
- int size = 8;
- p->dither_multiply = p->dither_quantization + 1.0 / (size*size);
- 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);
- gl->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
- gl->PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RED, size, size, 0, GL_RED,
- GL_UNSIGNED_BYTE, dither);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- gl->ActiveTexture(GL_TEXTURE0);
-}
-
-static void reinit_rendering(struct gl_priv *p)
-{
- mp_msg(MSGT_VO, MSGL_V, "[gl] Reinit rendering.\n");
-
- if (p->gl->SwapInterval && p->swap_interval >= 0)
- p->gl->SwapInterval(p->swap_interval);
-
- debug_check_gl(p, "before scaler initialization");
-
- uninit_rendering(p);
-
- init_dither(p);
-
- init_scaler(p, &p->scalers[0]);
- init_scaler(p, &p->scalers[1]);
-
- compile_shaders(p);
-
- if (p->indirect_program && !p->indirect_fbo.fbo)
- fbotex_init(p, &p->indirect_fbo, p->texture_width, p->texture_height);
-
- if (!p->osd) {
- p->osd = mpgl_osd_init(p->gl, false);
- p->osd->use_pbo = p->use_pbo;
- }
-}
-
-static void uninit_rendering(struct gl_priv *p)
-{
- GL *gl = p->gl;
-
- delete_shaders(p);
-
- for (int n = 0; n < 2; n++) {
- gl->DeleteTextures(1, &p->scalers[n].gl_lut);
- p->scalers[n].gl_lut = 0;
- p->scalers[n].lut_name = NULL;
- p->scalers[n].kernel = NULL;
- }
-
- gl->DeleteTextures(1, &p->dither_texture);
- p->dither_texture = 0;
-
- if (p->osd)
- mpgl_osd_destroy(p->osd);
- p->osd = NULL;
-}
-
-static void init_lut_3d(struct gl_priv *p)
-{
- GL *gl = p->gl;
-
- gl->GenTextures(1, &p->lut_3d_texture);
- gl->ActiveTexture(GL_TEXTURE0 + TEXUNIT_3DLUT);
- gl->BindTexture(GL_TEXTURE_3D, p->lut_3d_texture);
- gl->PixelStorei(GL_UNPACK_ALIGNMENT, 4);
- gl->PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- gl->TexImage3D(GL_TEXTURE_3D, 0, GL_RGB16, p->lut_3d_w, p->lut_3d_h,
- p->lut_3d_d, 0, GL_RGB, GL_UNSIGNED_SHORT, p->lut_3d_data);
- gl->TexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gl->TexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- gl->TexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
- gl->ActiveTexture(GL_TEXTURE0);
-
- debug_check_gl(p, "after 3d lut creation");
-}
-
-static void init_video(struct gl_priv *p)
-{
- GL *gl = p->gl;
-
- if (p->use_lut_3d && !p->lut_3d_texture)
- init_lut_3d(p);
-
- if (!p->is_yuv && (p->use_srgb || p->use_lut_3d)) {
- p->is_linear_rgb = true;
- p->gl_internal_format = GL_SRGB;
- }
-
- int eq_caps = MP_CSP_EQ_CAPS_GAMMA;
- if (p->is_yuv)
- eq_caps |= MP_CSP_EQ_CAPS_COLORMATRIX;
- p->video_eq.capabilities = eq_caps;
-
- debug_check_gl(p, "before video texture creation");
-
- tex_size(p, p->image_width, p->image_height,
- &p->texture_width, &p->texture_height);
-
- for (int n = 0; n < p->plane_count; n++) {
- struct texplane *plane = &p->planes[n];
-
- int w = p->texture_width >> plane->shift_x;
- int h = p->texture_height >> plane->shift_y;
-
- mp_msg(MSGT_VO, MSGL_V, "[gl] Texture for plane %d: %dx%d\n", n, w, h);
-
- gl->ActiveTexture(GL_TEXTURE0 + n);
- gl->GenTextures(1, &plane->gl_texture);
- gl->BindTexture(GL_TEXTURE_2D, plane->gl_texture);
-
- gl->TexImage2D(GL_TEXTURE_2D, 0, p->gl_internal_format, w, h, 0,
- p->gl_format, p->gl_type, NULL);
- default_tex_params(gl, GL_TEXTURE_2D, GL_LINEAR);
- }
- gl->ActiveTexture(GL_TEXTURE0);
-
- debug_check_gl(p, "after video texture creation");
-
- reinit_rendering(p);
-}
-
-static void uninit_video(struct gl_priv *p)
-{
- GL *gl = p->gl;
-
- uninit_rendering(p);
-
- for (int n = 0; n < 3; n++) {
- struct texplane *plane = &p->planes[n];
-
- gl->DeleteTextures(1, &plane->gl_texture);
- plane->gl_texture = 0;
- gl->DeleteBuffers(1, &plane->gl_buffer);
- plane->gl_buffer = 0;
- plane->buffer_ptr = NULL;
- plane->buffer_size = 0;
- }
-
- fbotex_uninit(p, &p->indirect_fbo);
- fbotex_uninit(p, &p->scale_sep_fbo);
-}
-
-static void render_to_fbo(struct gl_priv *p, struct fbotex *fbo, int w, int h,
- int tex_w, int tex_h)
-{
- GL *gl = p->gl;
-
- gl->Viewport(0, 0, fbo->vp_w, fbo->vp_h);
- gl->BindFramebuffer(GL_FRAMEBUFFER, fbo->fbo);
-
- struct vertex vb[VERTICES_PER_QUAD];
- write_quad(vb, -1, -1, 1, 1,
- 0, 0, w, h,
- tex_w, tex_h,
- NULL, false);
- draw_triangles(p, vb, VERTICES_PER_QUAD);
-
- gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
- gl->Viewport(p->vp_x, p->vp_y, p->vp_w, p->vp_h);
-
-}
-
-static void handle_pass(struct gl_priv *p, struct fbotex **source,
- struct fbotex *fbo, GLuint program)
-{
- GL *gl = p->gl;
-
- if (!program)
- return;
-
- gl->BindTexture(GL_TEXTURE_2D, (*source)->texture);
- gl->UseProgram(program);
- render_to_fbo(p, fbo, (*source)->vp_w, (*source)->vp_h,
- (*source)->tex_w, (*source)->tex_h);
- *source = fbo;
-}
-
-static void do_render(struct gl_priv *p)
-{
- GL *gl = p->gl;
- struct vertex vb[VERTICES_PER_QUAD];
- bool is_flipped = p->mpi_flipped ^ p->vo_flipped;
-
- // Order of processing:
- // [indirect -> [scale_sep ->]] final
-
- struct fbotex dummy = {
- .vp_w = p->image_width, .vp_h = p->image_height,
- .tex_w = p->texture_width, .tex_h = p->texture_height,
- .texture = p->planes[0].gl_texture,
- };
- struct fbotex *source = &dummy;
-
- handle_pass(p, &source, &p->indirect_fbo, p->indirect_program);
- handle_pass(p, &source, &p->scale_sep_fbo, p->scale_sep_program);
-
- gl->BindTexture(GL_TEXTURE_2D, source->texture);
- gl->UseProgram(p->final_program);
-
- 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->stereo_mode) {
- int w = p->src_rect.x1 - p->src_rect.x0;
- int imgw = p->image_width;
-
- glEnable3DLeft(gl, p->stereo_mode);
-
- write_quad(vb,
- p->dst_rect.x0, p->dst_rect.y0,
- p->dst_rect.x1, p->dst_rect.y1,
- p->src_rect.x0 / 2, p->src_rect.y0,
- p->src_rect.x0 / 2 + w / 2, p->src_rect.y1,
- final_texw, final_texh,
- NULL, is_flipped);
- draw_triangles(p, vb, VERTICES_PER_QUAD);
-
- glEnable3DRight(gl, p->stereo_mode);
-
- write_quad(vb,
- p->dst_rect.x0, p->dst_rect.y0,
- p->dst_rect.x1, p->dst_rect.y1,
- p->src_rect.x0 / 2 + imgw / 2, p->src_rect.y0,
- p->src_rect.x0 / 2 + imgw / 2 + w / 2, p->src_rect.y1,
- final_texw, final_texh,
- NULL, is_flipped);
- draw_triangles(p, vb, VERTICES_PER_QUAD);
-
- glDisable3D(gl, p->stereo_mode);
- } else {
- write_quad(vb,
- p->dst_rect.x0, p->dst_rect.y0,
- p->dst_rect.x1, p->dst_rect.y1,
- p->src_rect.x0, p->src_rect.y0,
- p->src_rect.x1, p->src_rect.y1,
- final_texw, final_texh,
- NULL, is_flipped);
- draw_triangles(p, vb, VERTICES_PER_QUAD);
- }
-
- gl->UseProgram(0);
-
- debug_check_gl(p, "after video rendering");
-}
-
-static void update_window_sized_objects(struct gl_priv *p)
-{
- if (p->scale_sep_program) {
- int h = p->dst_rect.y1 - p->dst_rect.y0;
- if (h > p->scale_sep_fbo.tex_h) {
- fbotex_uninit(p, &p->scale_sep_fbo);
- // Round up to an arbitrary alignment to make window resizing or
- // panscan controls smoother (less texture reallocations).
- int height = FFALIGN(h, 256);
- fbotex_init(p, &p->scale_sep_fbo, p->image_width, height);
- }
- p->scale_sep_fbo.vp_w = p->image_width;
- p->scale_sep_fbo.vp_h = h;
- }
-}
-
-static void resize(struct gl_priv *p)
-{
- GL *gl = p->gl;
- struct vo *vo = p->vo;
-
- mp_msg(MSGT_VO, MSGL_V, "[gl] Resize: %dx%d\n", vo->dwidth, vo->dheight);
- p->vp_x = 0, p->vp_y = 0;
- p->vp_w = vo->dwidth, p->vp_h = vo->dheight;
- gl->Viewport(p->vp_x, p->vp_y, p->vp_w, p->vp_h);
-
- vo_get_src_dst_rects(vo, &p->src_rect, &p->dst_rect, &p->osd_rect);
-
- bool need_scaler_reinit = false; // filter size change needed
- bool need_scaler_update = false; // filter LUT change needed
- bool too_small = false;
- for (int n = 0; n < 2; n++) {
- if (p->scalers[n].kernel) {
- struct filter_kernel tkernel = *p->scalers[n].kernel;
- struct filter_kernel old = tkernel;
- bool ok = update_scale_factor(p, &tkernel);
- too_small |= !ok;
- need_scaler_reinit |= (tkernel.size != old.size);
- need_scaler_update |= (tkernel.inv_scale != old.inv_scale);
- }
- }
- if (need_scaler_reinit) {
- reinit_rendering(p);
- } else if (need_scaler_update) {
- init_scaler(p, &p->scalers[0]);
- init_scaler(p, &p->scalers[1]);
- }
- if (too_small)
- mp_msg(MSGT_VO, MSGL_WARN, "[gl] Can't downscale that much, window "
- "output may look suboptimal.\n");
-
- update_window_sized_objects(p);
- update_all_uniforms(p);
-
- gl->Clear(GL_COLOR_BUFFER_BIT);
- vo->want_redraw = true;
-}
-
-static void flip_page(struct vo *vo)
-{
- struct gl_priv *p = vo->priv;
- GL *gl = p->gl;
-
- if (p->use_glFinish)
- gl->Finish();
-
- p->glctx->swapGlBuffers(p->glctx);
-
- if (p->dst_rect.x0 > p->vp_x || p->dst_rect.y0 > p->vp_y
- || p->dst_rect.x1 < p->vp_x + p->vp_w
- || p->dst_rect.y1 < p->vp_y + p->vp_h)
- {
- gl->Clear(GL_COLOR_BUFFER_BIT);
- }
-
- p->frames_rendered++;
-}
-
-static int draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h,
- int x, int y)
-{
- struct gl_priv *p = vo->priv;
- GL *gl = p->gl;
-
- p->mpi_flipped = stride[0] < 0;
-
- for (int n = 0; n < p->plane_count; n++) {
- gl->ActiveTexture(GL_TEXTURE0 + n);
- gl->BindTexture(GL_TEXTURE_2D, p->planes[n].gl_texture);
- int xs = p->planes[n].shift_x, ys = p->planes[n].shift_y;
- glUploadTex(gl, GL_TEXTURE_2D, p->gl_format, p->gl_type, src[n],
- stride[n], x >> xs, y >> ys, w >> xs, h >> ys, 0);
- }
- gl->ActiveTexture(GL_TEXTURE0);
-
- return 0;
-}
-
-static uint32_t get_image(struct vo *vo, mp_image_t *mpi)
-{
- struct gl_priv *p = vo->priv;
- GL *gl = p->gl;
-
- if (!p->use_pbo)
- return VO_FALSE;
-
- // We don't support alpha planes. (Disabling PBOs with normal draw calls is
- // an undesired, but harmless side-effect.)
- if (mpi->num_planes != p->plane_count)
- return VO_FALSE;
-
- if (mpi->flags & MP_IMGFLAG_READABLE)
- return VO_FALSE;
- if (mpi->type != MP_IMGTYPE_STATIC && mpi->type != MP_IMGTYPE_TEMP &&
- (mpi->type != MP_IMGTYPE_NUMBERED || mpi->number))
- return VO_FALSE;
- mpi->flags &= ~MP_IMGFLAG_COMMON_PLANE;
- for (int n = 0; n < p->plane_count; n++) {
- struct texplane *plane = &p->planes[n];
- mpi->stride[n] = (mpi->width >> plane->shift_x) * p->plane_bytes;
- int needed_size = (mpi->height >> plane->shift_y) * mpi->stride[n];
- if (!plane->gl_buffer)
- gl->GenBuffers(1, &plane->gl_buffer);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, plane->gl_buffer);
- if (needed_size > plane->buffer_size) {
- plane->buffer_size = needed_size;
- gl->BufferData(GL_PIXEL_UNPACK_BUFFER, plane->buffer_size,
- NULL, GL_DYNAMIC_DRAW);
- }
- if (!plane->buffer_ptr)
- plane->buffer_ptr = gl->MapBuffer(GL_PIXEL_UNPACK_BUFFER,
- GL_WRITE_ONLY);
- mpi->planes[n] = plane->buffer_ptr;
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- }
- mpi->flags |= MP_IMGFLAG_DIRECT;
- return VO_TRUE;
-}
-
-static uint32_t draw_image(struct gl_priv *p, mp_image_t *mpi)
-{
- GL *gl = p->gl;
- int n;
-
- assert(mpi->num_planes >= p->plane_count);
-
- mp_image_t mpi2 = *mpi;
- int w = mpi->w, h = mpi->h;
- if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
- goto skip_upload;
- mpi2.flags = 0;
- mpi2.type = MP_IMGTYPE_TEMP;
- mpi2.width = mpi2.w;
- mpi2.height = mpi2.h;
- if (!(mpi->flags & MP_IMGFLAG_DIRECT)
- && !p->planes[0].buffer_ptr
- && get_image(p->vo, &mpi2) == VO_TRUE)
- {
- for (n = 0; n < p->plane_count; n++) {
- struct texplane *plane = &p->planes[n];
- int xs = plane->shift_x, ys = plane->shift_y;
- int line_bytes = (mpi->w >> xs) * p->plane_bytes;
- memcpy_pic(mpi2.planes[n], mpi->planes[n], line_bytes, mpi->h >> ys,
- mpi2.stride[n], mpi->stride[n]);
- }
- mpi = &mpi2;
- }
- p->mpi_flipped = mpi->stride[0] < 0;
- for (n = 0; n < p->plane_count; n++) {
- struct texplane *plane = &p->planes[n];
- int xs = plane->shift_x, ys = plane->shift_y;
- void *plane_ptr = mpi->planes[n];
- if (mpi->flags & MP_IMGFLAG_DIRECT) {
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, plane->gl_buffer);
- if (!gl->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER))
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Video PBO upload failed. "
- "Remove the 'pbo' suboption.\n");
- plane->buffer_ptr = NULL;
- plane_ptr = NULL; // PBO offset 0
- }
- gl->ActiveTexture(GL_TEXTURE0 + n);
- gl->BindTexture(GL_TEXTURE_2D, plane->gl_texture);
- glUploadTex(gl, GL_TEXTURE_2D, p->gl_format, p->gl_type, plane_ptr,
- mpi->stride[n], 0, 0, w >> xs, h >> ys, 0);
- }
- gl->ActiveTexture(GL_TEXTURE0);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-skip_upload:
- do_render(p);
- return VO_TRUE;
-}
-
-static mp_image_t *get_screenshot(struct gl_priv *p)
-{
- GL *gl = p->gl;
-
- mp_image_t *image = alloc_mpi(p->texture_width, p->texture_height,
- p->image_format);
-
- // NOTE about image formats with alpha plane: we don't even have the alpha
- // anymore. We never upload it to any texture, as it would be a waste of
- // time. On the other hand, we can't find a "similar", non-alpha image
- // format easily. So we just leave the alpha plane of the newly allocated
- // image as-is, and hope that the alpha is ignored by the receiver of the
- // screenshot. (If not, code should be added to make it fully opaque.)
-
- for (int n = 0; n < p->plane_count; n++) {
- gl->ActiveTexture(GL_TEXTURE0 + n);
- gl->BindTexture(GL_TEXTURE_2D, p->planes[n].gl_texture);
- glDownloadTex(gl, GL_TEXTURE_2D, p->gl_format, p->gl_type,
- image->planes[n], image->stride[n]);
- }
- gl->ActiveTexture(GL_TEXTURE0);
-
- image->w = p->image_width;
- image->h = p->image_height;
- image->display_w = p->vo->aspdat.prew;
- image->display_h = p->vo->aspdat.preh;
-
- mp_image_set_colorspace_details(image, &p->colorspace);
-
- return image;
-}
-
-static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs)
-{
- struct gl_priv *p = ctx;
- GL *gl = p->gl;
-
- struct mpgl_osd_part *osd = mpgl_osd_generate(p->osd, imgs);
- if (!osd)
- return;
-
- assert(osd->format != SUBBITMAP_EMPTY);
-
- if (!osd->num_vertices) {
- osd->vertices = talloc_realloc(osd, osd->vertices, struct vertex,
- osd->packer->count * VERTICES_PER_QUAD);
-
- struct vertex *va = osd->vertices;
-
- for (int n = 0; n < osd->packer->count; n++) {
- struct sub_bitmap *b = &imgs->parts[n];
- struct pos p = osd->packer->result[n];
-
- // NOTE: the blend color is used with SUBBITMAP_LIBASS only, so it
- // doesn't matter that we upload garbage for the other formats
- uint32_t c = b->libass.color;
- uint8_t color[4] = { c >> 24, (c >> 16) & 0xff,
- (c >> 8) & 0xff, 255 - (c & 0xff) };
-
- write_quad(&va[osd->num_vertices],
- b->x, b->y, b->x + b->dw, b->y + b->dh,
- p.x, p.y, p.x + b->w, p.y + b->h,
- osd->w, osd->h, color, false);
- osd->num_vertices += VERTICES_PER_QUAD;
- }
- }
-
- debug_check_gl(p, "before drawing osd");
-
- gl->UseProgram(p->osd_programs[osd->format]);
- mpgl_osd_set_gl_state(p->osd, osd);
- draw_triangles(p, osd->vertices, osd->num_vertices);
- mpgl_osd_unset_gl_state(p->osd, osd);
- gl->UseProgram(0);
-
- debug_check_gl(p, "after drawing osd");
-}
-
-static void draw_osd(struct vo *vo, struct osd_state *osd)
-{
- struct gl_priv *p = vo->priv;
- assert(p->osd);
-
- osd_draw(osd, p->osd_rect, osd->vo_pts, 0, p->osd->formats, draw_osd_cb, p);
-}
-
-// 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;
-
- // srgb_compand() not available
- if (gl->glsl_version < 130)
- have_srgb = false;
-
- 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);
-
- gl->EnableVertexAttribArray(VERTEX_ATTRIB_POSITION);
- gl->VertexAttribPointer(VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE,
- stride, (void*)offsetof(struct vertex, position));
-
- gl->EnableVertexAttribArray(VERTEX_ATTRIB_COLOR);
- gl->VertexAttribPointer(VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE,
- stride, (void*)offsetof(struct vertex, color));
-
- gl->EnableVertexAttribArray(VERTEX_ATTRIB_TEXCOORD);
- gl->VertexAttribPointer(VERTEX_ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE,
- stride, (void*)offsetof(struct vertex, texcoord));
-}
-
-static int init_gl(struct gl_priv *p)
-{
- GL *gl = p->gl;
-
- debug_check_gl(p, "before init_gl");
-
- const char *vendor = gl->GetString(GL_VENDOR);
- const char *version = gl->GetString(GL_VERSION);
- const char *renderer = gl->GetString(GL_RENDERER);
- const char *glsl = gl->GetString(GL_SHADING_LANGUAGE_VERSION);
- mp_msg(MSGT_VO, MSGL_V, "[gl] GL_RENDERER='%s', GL_VENDOR='%s', "
- "GL_VERSION='%s', GL_SHADING_LANGUAGE_VERSION='%s'"
- "\n", renderer, vendor, version, glsl);
- 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);
-
- check_gl_features(p);
-
- gl->Disable(GL_DITHER);
- gl->Disable(GL_BLEND);
- gl->Disable(GL_DEPTH_TEST);
- gl->DepthMask(GL_FALSE);
- gl->Disable(GL_CULL_FACE);
- gl->DrawBuffer(GL_BACK);
-
- gl->GenBuffers(1, &p->vertex_buffer);
- gl->BindBuffer(GL_ARRAY_BUFFER, p->vertex_buffer);
-
- 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->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- gl->Clear(GL_COLOR_BUFFER_BIT);
-
- debug_check_gl(p, "after init_gl");
-
- return 1;
-}
-
-static void uninit_gl(struct gl_priv *p)
-{
- GL *gl = p->gl;
-
- // NOTE: GL functions might not be loaded yet
- if (!(p->glctx && p->gl->DeleteTextures))
- return;
-
- uninit_video(p);
-
- if (gl->DeleteVertexArrays)
- gl->DeleteVertexArrays(1, &p->vao);
- p->vao = 0;
- gl->DeleteBuffers(1, &p->vertex_buffer);
- p->vertex_buffer = 0;
-
- gl->DeleteTextures(1, &p->lut_3d_texture);
- p->lut_3d_texture = 0;
-}
-
-static bool init_format(int fmt, struct gl_priv *init)
-{
- bool supported = false;
- struct gl_priv dummy;
- if (!init)
- init = &dummy;
-
- mp_image_t dummy_img = {0};
- mp_image_setfmt(&dummy_img, fmt);
-
- init->image_format = fmt;
- init->component_bits = -1;
-
- // RGB/packed formats
- for (const struct fmt_entry *e = mp_to_gl_formats; e->mp_format; e++) {
- if (e->mp_format == fmt) {
- supported = true;
- init->plane_bits = dummy_img.bpp;
- init->gl_format = e->format;
- init->gl_internal_format = e->internal_format;
- init->component_bits = e->component_bits;
- init->gl_type = e->type;
- break;
- }
- }
-
- // YUV/planar formats
- if (!supported && mp_get_chroma_shift(fmt, NULL, NULL, &init->plane_bits)) {
- init->gl_format = GL_RED;
- init->component_bits = init->plane_bits;
- if (init->plane_bits == 8) {
- supported = true;
- init->gl_internal_format = GL_RED;
- init->gl_type = GL_UNSIGNED_BYTE;
- } else if (IMGFMT_IS_YUVP16_NE(fmt)) {
- supported = true;
- init->gl_internal_format = GL_R16;
- init->gl_type = GL_UNSIGNED_SHORT;
- }
- }
-
- // RGB/planar
- if (!supported && fmt == IMGFMT_GBRP) {
- supported = true;
- init->plane_bits = init->component_bits = 8;
- init->gl_format = GL_RED;
- init->gl_internal_format = GL_RED;
- init->gl_type = GL_UNSIGNED_BYTE;
- }
-
- if (!supported)
- return false;
-
- init->plane_bytes = (init->plane_bits + 7) / 8;
- init->is_yuv = dummy_img.flags & MP_IMGFLAG_YUV;
- init->is_linear_rgb = false;
-
- // NOTE: we throw away the additional alpha plane, if one exists.
- init->plane_count = dummy_img.num_planes > 2 ? 3 : 1;
- assert(dummy_img.num_planes >= init->plane_count);
- assert(dummy_img.num_planes <= init->plane_count + 1);
-
- for (int n = 0; n < init->plane_count; n++) {
- struct texplane *plane = &init->planes[n];
-
- plane->shift_x = n > 0 ? dummy_img.chroma_x_shift : 0;
- plane->shift_y = n > 0 ? dummy_img.chroma_y_shift : 0;
- }
-
- return true;
-}
-
-static int query_format(uint32_t format)
-{
- int caps = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_FLIP |
- VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE |
- VFCAP_OSD;
- if (!init_format(format, NULL))
- return 0;
- return caps;
-}
-
-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;
-
- if (p->use_gl_debug)
- flags |= VOFLAG_GL_DEBUG;
-
- 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,
- uint32_t d_width, uint32_t d_height, uint32_t flags,
- uint32_t format)
-{
- struct gl_priv *p = vo->priv;
-
- 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
- || p->image_height != height)
- {
- uninit_video(p);
- p->image_height = height;
- p->image_width = width;
- init_format(format, p);
- init_video(p);
- }
-
- resize(p);
-
- return 0;
-}
-
-static void check_events(struct vo *vo)
-{
- struct gl_priv *p = vo->priv;
-
- int e = p->glctx->check_events(vo);
- if (e & VO_EVENT_REINIT) {
- uninit_gl(p);
- init_gl(p);
- init_video(p);
- resize(p);
- }
- if (e & VO_EVENT_RESIZE)
- resize(p);
- if (e & VO_EVENT_EXPOSE)
- vo->want_redraw = true;
-}
-
-static int control(struct vo *vo, uint32_t request, void *data)
-{
- struct gl_priv *p = vo->priv;
-
- switch (request) {
- case VOCTRL_QUERY_FORMAT:
- return query_format(*(uint32_t *)data);
- case VOCTRL_DRAW_IMAGE:
- return draw_image(p, data);
- case VOCTRL_ONTOP:
- if (!p->glctx->ontop)
- break;
- p->glctx->ontop(vo);
- return VO_TRUE;
- case VOCTRL_PAUSE:
- if (!p->glctx->pause)
- break;
- p->glctx->pause(vo);
- return VO_TRUE;
- case VOCTRL_RESUME:
- if (!p->glctx->resume)
- break;
- p->glctx->resume(vo);
- return VO_TRUE;
- case VOCTRL_FULLSCREEN:
- p->glctx->fullscreen(vo);
- resize(p);
- return VO_TRUE;
- case VOCTRL_BORDER:
- if (!p->glctx->border)
- break;
- p->glctx->border(vo);
- resize(p);
- return VO_TRUE;
- case VOCTRL_GET_PANSCAN:
- return VO_TRUE;
- case VOCTRL_SET_PANSCAN:
- resize(p);
- return VO_TRUE;
- case VOCTRL_GET_EQUALIZER: {
- struct voctrl_get_equalizer_args *args = data;
- return mp_csp_equalizer_get(&p->video_eq, args->name, args->valueptr)
- >= 0 ? VO_TRUE : VO_NOTIMPL;
- }
- case VOCTRL_SET_EQUALIZER: {
- struct voctrl_set_equalizer_args *args = data;
- if (mp_csp_equalizer_set(&p->video_eq, args->name, args->value) < 0)
- return VO_NOTIMPL;
- if (!p->use_gamma && p->video_eq.values[MP_CSP_EQ_GAMMA] != 0) {
- mp_msg(MSGT_VO, MSGL_V, "[gl] Auto-enabling gamma.\n");
- p->use_gamma = true;
- compile_shaders(p);
- }
- update_all_uniforms(p);
- vo->want_redraw = true;
- return VO_TRUE;
- }
- case VOCTRL_SET_YUV_COLORSPACE: {
- if (p->is_yuv) {
- p->colorspace = *(struct mp_csp_details *)data;
- update_all_uniforms(p);
- vo->want_redraw = true;
- }
- return VO_TRUE;
- }
- case VOCTRL_GET_YUV_COLORSPACE:
- *(struct mp_csp_details *)data = p->colorspace;
- return VO_TRUE;
- case VOCTRL_UPDATE_SCREENINFO:
- if (!p->glctx->update_xinerama_info)
- break;
- p->glctx->update_xinerama_info(vo);
- return VO_TRUE;
- case VOCTRL_SCREENSHOT: {
- struct voctrl_screenshot_args *args = data;
- if (args->full_window)
- args->out_image = glGetWindowScreenshot(p->gl);
- else
- args->out_image = get_screenshot(p);
- return true;
- }
- case VOCTRL_REDRAW_FRAME:
- do_render(p);
- return true;
- case VOCTRL_SET_COMMAND_LINE: {
- char *arg = data;
- if (!reparse_cmdline(p, arg))
- return false;
- check_gl_features(p);
- reinit_rendering(p);
- resize(p);
- vo->want_redraw = true;
- return true;
- }
- }
- return VO_NOTIMPL;
-}
-
-static void uninit(struct vo *vo)
-{
- struct gl_priv *p = vo->priv;
-
- uninit_gl(p);
- mpgl_uninit(p->glctx);
- p->glctx = NULL;
- p->gl = NULL;
-}
-
-#ifdef CONFIG_LCMS2
-
-static void lcms2_error_handler(cmsContext ctx, cmsUInt32Number code,
- const char *msg)
-{
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] lcms2: %s\n", msg);
-}
-
-static struct bstr load_file(struct gl_priv *p, void *talloc_ctx,
- const char *filename)
-{
- struct bstr res = {0};
- stream_t *s = open_stream(filename, p->vo->opts, NULL);
- if (s) {
- res = stream_read_complete(s, talloc_ctx, 1000000000, 0);
- free_stream(s);
- }
- return res;
-}
-
-#define LUT3D_CACHE_HEADER "mpv 3dlut cache 1.0\n"
-
-static bool load_icc(struct gl_priv *p, const char *icc_file,
- const char *icc_cache, int icc_intent,
- int s_r, int s_g, int s_b)
-{
- void *tmp = talloc_new(p);
- uint16_t *output = talloc_array(tmp, uint16_t, s_r * s_g * s_b * 3);
-
- if (icc_intent == -1)
- icc_intent = INTENT_ABSOLUTE_COLORIMETRIC;
-
- mp_msg(MSGT_VO, MSGL_INFO, "[gl] Opening ICC profile '%s'\n", icc_file);
- struct bstr iccdata = load_file(p, tmp, icc_file);
- if (!iccdata.len)
- goto error_exit;
-
- char *cache_info = talloc_asprintf(tmp, "intent=%d, size=%dx%dx%d\n",
- icc_intent, s_r, s_g, s_b);
-
- // check cache
- if (icc_cache) {
- mp_msg(MSGT_VO, MSGL_INFO, "[gl] Opening 3D LUT cache in file '%s'.\n",
- icc_cache);
- struct bstr cachedata = load_file(p, tmp, icc_cache);
- if (bstr_eatstart(&cachedata, bstr0(LUT3D_CACHE_HEADER))
- && bstr_eatstart(&cachedata, bstr0(cache_info))
- && bstr_eatstart(&cachedata, iccdata)
- && cachedata.len == talloc_get_size(output))
- {
- memcpy(output, cachedata.start, cachedata.len);
- goto done;
- } else {
- mp_msg(MSGT_VO, MSGL_WARN, "[gl] 3D LUT cache invalid!\n");
- }
- }
-
- cmsSetLogErrorHandler(lcms2_error_handler);
-
- cmsHPROFILE profile = cmsOpenProfileFromMem(iccdata.start, iccdata.len);
- if (!profile)
- goto error_exit;
-
- cmsCIExyY d65;
- cmsWhitePointFromTemp(&d65, 6504);
- static const cmsCIExyYTRIPLE bt709prim = {
- .Red = {0.64, 0.33, 1.0},
- .Green = {0.30, 0.60, 1.0},
- .Blue = {0.15, 0.06, 1.0},
- };
- cmsToneCurve *tonecurve = cmsBuildGamma(NULL, 2.2);
- cmsHPROFILE vid_profile = cmsCreateRGBProfile(&d65, &bt709prim,
- (cmsToneCurve*[3]){tonecurve, tonecurve, tonecurve});
- cmsFreeToneCurve(tonecurve);
- cmsHTRANSFORM trafo = cmsCreateTransform(vid_profile, TYPE_RGB_16,
- profile, TYPE_RGB_16,
- icc_intent,
- cmsFLAGS_HIGHRESPRECALC);
- cmsCloseProfile(profile);
- cmsCloseProfile(vid_profile);
-
- if (!trafo)
- goto error_exit;
-
- // transform a (s_r)x(s_g)x(s_b) cube, with 3 components per channel
- uint16_t *input = talloc_array(tmp, uint16_t, s_r * 3);
- for (int b = 0; b < s_b; b++) {
- for (int g = 0; g < s_g; g++) {
- for (int r = 0; r < s_r; r++) {
- input[r * 3 + 0] = r * 65535 / (s_r - 1);
- input[r * 3 + 1] = g * 65535 / (s_g - 1);
- input[r * 3 + 2] = b * 65535 / (s_b - 1);
- }
- size_t base = (b * s_r * s_g + g * s_r) * 3;
- cmsDoTransform(trafo, input, output + base, s_r);
- }
- }
-
- cmsDeleteTransform(trafo);
-
- if (icc_cache) {
- FILE *out = fopen(icc_cache, "wb");
- if (out) {
- fprintf(out, "%s%s", LUT3D_CACHE_HEADER, cache_info);
- fwrite(iccdata.start, iccdata.len, 1, out);
- fwrite(output, talloc_get_size(output), 1, out);
- fclose(out);
- }
- }
-
-done:
-
- p->lut_3d_data = talloc_steal(p, output);
- p->lut_3d_w = s_r, p->lut_3d_h = s_g, p->lut_3d_d = s_b;
- p->use_lut_3d = true;
-
- talloc_free(tmp);
- return true;
-
-error_exit:
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Error loading ICC profile.\n");
- talloc_free(tmp);
- return false;
-}
-
-#else /* CONFIG_LCMS2 */
-
-static bool load_icc(struct gl_priv *p, ...)
-{
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] LCMS2 support not compiled.\n");
- return false;
-}
-
-#endif /* CONFIG_LCMS2 */
-
-static bool parse_3dlut_size(const char *s, int *p1, int *p2, int *p3)
-{
- if (sscanf(s, "%dx%dx%d", p1, p2, p3) != 3)
- return false;
- for (int n = 0; n < 3; n++) {
- int s = ((int[]) { *p1, *p2, *p3 })[n];
- if (s < 2 || s > 256 || ((s - 1) & s))
- return false;
- }
- return true;
-}
-
-static int lut3d_size_valid(void *arg)
-{
- char *s = *(char **)arg;
- int p1, p2, p3;
- return parse_3dlut_size(s, &p1, &p2, &p3);
-}
-
-static int backend_valid(void *arg)
-{
- return mpgl_find_backend(*(const char **)arg) >= 0;
-}
-
-struct fbo_format {
- const char *name;
- GLint format;
-};
-
-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},
- {0}
-};
-
-static GLint find_fbo_format(const char *name)
-{
- for (const struct fbo_format *fmt = fbo_formats; fmt->name; fmt++) {
- if (strcmp(fmt->name, name) == 0)
- return fmt->format;
- }
- return -1;
-}
-
-static int fbo_format_valid(void *arg)
-{
- return find_fbo_format(*(const char **)arg) >= 0;
-}
-
-static bool can_use_filter_kernel(const struct filter_kernel *kernel)
-{
- if (!kernel)
- return false;
- struct filter_kernel k = *kernel;
- return mp_init_filter(&k, filter_sizes, 1);
-}
-
-static const char* handle_scaler_opt(const char *name)
-{
- const struct filter_kernel *kernel = mp_find_filter_kernel(name);
- if (can_use_filter_kernel(kernel))
- return kernel->name;
-
- for (const char **filter = fixed_scale_filters; *filter; filter++) {
- if (strcmp(*filter, name) == 0)
- return *filter;
- }
-
- return NULL;
-}
-
-static int scaler_valid(void *arg)
-{
- return handle_scaler_opt(*(const char **)arg) != NULL;
-}
-
-#if 0
-static void print_scalers(void)
-{
- mp_msg(MSGT_VO, MSGL_INFO, "Available scalers:\n");
- for (const char **e = fixed_scale_filters; *e; e++) {
- mp_msg(MSGT_VO, MSGL_INFO, " %s\n", *e);
- }
- for (const struct filter_kernel *e = mp_filter_kernels; e->name; e++) {
- if (can_use_filter_kernel(e))
- mp_msg(MSGT_VO, MSGL_INFO, " %s\n", e->name);
- }
-}
-#endif
-
-static bool reparse_cmdline(struct gl_priv *p, char *arg)
-{
- struct gl_priv tmp = *p->defaults;
- struct gl_priv *opt = &tmp;
-
- if (strcmp(arg, "-") == 0) {
- tmp = *p->orig_cmdline;
- arg = "";
- }
-
- char *scalers[2] = {0};
- char *fbo_format = NULL;
-
- const opt_t subopts[] = {
- {"srgb", OPT_ARG_BOOL, &opt->use_srgb},
- {"pbo", OPT_ARG_BOOL, &opt->use_pbo},
- {"glfinish", OPT_ARG_BOOL, &opt->use_glFinish},
- {"swapinterval", OPT_ARG_INT, &opt->swap_interval},
- {"osdcolor", OPT_ARG_INT, &opt->osd_color},
- {"lscale", OPT_ARG_MSTRZ, &scalers[0], scaler_valid},
- {"cscale", OPT_ARG_MSTRZ, &scalers[1], scaler_valid},
- {"lparam1", OPT_ARG_FLOAT, &opt->scaler_params[0]},
- {"lparam2", OPT_ARG_FLOAT, &opt->scaler_params[1]},
- {"fancy-downscaling", OPT_ARG_BOOL, &opt->use_fancy_downscaling},
- {"indirect", OPT_ARG_BOOL, &opt->use_indirect},
- {"scale-sep", OPT_ARG_BOOL, &opt->use_scale_sep},
- {"fbo-format", OPT_ARG_MSTRZ, &fbo_format, fbo_format_valid},
- {"dither-depth", OPT_ARG_INT, &opt->dither_depth},
- {NULL}
- };
-
- if (subopt_parse(arg, subopts) != 0)
- return false;
-
- p->fbo_format = opt->fbo_format;
- if (fbo_format)
- p->fbo_format = find_fbo_format(fbo_format);
- free(fbo_format);
-
- for (int n = 0; n < 2; n++) {
- p->scalers[n].name = opt->scalers[n].name;
- if (scalers[n])
- p->scalers[n].name = handle_scaler_opt(scalers[n]);
- free(scalers[n]);
- }
-
- // xxx ideally we'd put all options into an option struct, and just copy
- p->use_srgb = opt->use_srgb; //xxx changing srgb will be wrong on RGB input!
- p->use_pbo = opt->use_pbo;
- p->use_glFinish = opt->use_glFinish;
- p->swap_interval = opt->swap_interval;
- p->osd_color = opt->osd_color;
- memcpy(p->scaler_params, opt->scaler_params, sizeof(p->scaler_params));
- p->use_fancy_downscaling = opt->use_fancy_downscaling;
- p->use_indirect = opt->use_indirect;
- p->use_scale_sep = opt->use_scale_sep;
- p->dither_depth = opt->dither_depth;
-
- check_gl_features(p);
-
- return true;
-}
-
-static int preinit(struct vo *vo, const char *arg)
-{
- struct gl_priv *p = talloc_zero(vo, struct gl_priv);
- vo->priv = p;
-
- bool hq = strcmp(vo->driver->info->short_name, "opengl-hq") == 0;
-
- *p = (struct gl_priv) {
- .vo = vo,
- .colorspace = MP_CSP_DETAILS_DEFAULTS,
- .use_npot = 1,
- .use_pbo = hq,
- .swap_interval = vo_vsync,
- .osd_color = 0xffffff,
- .dither_depth = hq ? 0 : -1,
- .fbo_format = hq ? GL_RGB16 : GL_RGB,
- .use_scale_sep = 1,
- .scalers = {
- { .index = 0, .name = hq ? "lanczos2" : "bilinear" },
- { .index = 1, .name = "bilinear" },
- },
- .scaler_params = {NAN, NAN},
- .scratch = talloc_zero_array(p, char *, 1),
- };
-
- p->defaults = talloc(p, struct gl_priv);
- *p->defaults = *p;
-
- char *scalers[2] = {0};
- char *backend_arg = NULL;
- char *fbo_format = NULL;
- char *icc_profile = NULL;
- char *icc_cache = NULL;
- int icc_intent = -1;
- char *icc_size_str = NULL;
-
- const opt_t subopts[] = {
- {"gamma", OPT_ARG_BOOL, &p->use_gamma},
- {"srgb", OPT_ARG_BOOL, &p->use_srgb},
- {"npot", OPT_ARG_BOOL, &p->use_npot},
- {"pbo", OPT_ARG_BOOL, &p->use_pbo},
- {"glfinish", OPT_ARG_BOOL, &p->use_glFinish},
- {"swapinterval", OPT_ARG_INT, &p->swap_interval},
- {"osdcolor", OPT_ARG_INT, &p->osd_color},
- {"stereo", OPT_ARG_INT, &p->stereo_mode},
- {"lscale", OPT_ARG_MSTRZ, &scalers[0], scaler_valid},
- {"cscale", OPT_ARG_MSTRZ, &scalers[1], scaler_valid},
- {"lparam1", OPT_ARG_FLOAT, &p->scaler_params[0]},
- {"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},
- {"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},
- {"3dlut-size", OPT_ARG_MSTRZ, &icc_size_str,
- lut3d_size_valid},
- {"dither-depth", OPT_ARG_INT, &p->dither_depth},
- {NULL}
- };
-
- if (subopt_parse(arg, subopts) != 0) {
- mp_msg(MSGT_VO, MSGL_FATAL, help_text);
- goto err_out;
- }
-
- int backend = backend_arg ? mpgl_find_backend(backend_arg) : GLTYPE_AUTO;
- free(backend_arg);
-
- if (fbo_format)
- p->fbo_format = find_fbo_format(fbo_format);
- free(fbo_format);
-
- for (int n = 0; n < 2; n++) {
- if (scalers[n])
- p->scalers[n].name = handle_scaler_opt(scalers[n]);
- free(scalers[n]);
- }
-
- int s_r = 128, s_g = 256, s_b = 64;
- if (icc_size_str)
- parse_3dlut_size(icc_size_str, &s_r, &s_g, &s_b);
- free(icc_size_str);
-
- bool success = true;
- if (icc_profile) {
- success = load_icc(p, icc_profile, icc_cache, icc_intent,
- s_r, s_g, s_b);
- }
- free(icc_profile);
- free(icc_cache);
-
- if (!success)
- goto err_out;
-
- p->orig_cmdline = talloc(p, struct gl_priv);
- *p->orig_cmdline = *p;
-
- p->glctx = mpgl_init(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;
-
-err_out:
- uninit(vo);
- return -1;
-}
-
-const struct vo_driver video_out_opengl = {
- .is_new = true,
- .info = &(const vo_info_t) {
- "Extended OpenGL Renderer",
- "opengl",
- "Based on vo_gl.c by Reimar Doeffinger",
- ""
- },
- .preinit = preinit,
- .config = config,
- .control = control,
- .draw_slice = draw_slice,
- .draw_osd = draw_osd,
- .flip_page = flip_page,
- .check_events = check_events,
- .uninit = uninit,
-};
-
-const struct vo_driver video_out_opengl_hq = {
- .is_new = true,
- .info = &(const vo_info_t) {
- "Extended OpenGL Renderer (high quality rendering preset)",
- "opengl-hq",
- "Based on vo_gl.c by Reimar Doeffinger",
- ""
- },
- .preinit = preinit,
- .config = config,
- .control = control,
- .draw_slice = draw_slice,
- .draw_osd = draw_osd,
- .flip_page = flip_page,
- .check_events = check_events,
- .uninit = uninit,
-};
-
-static const char help_text[] =
-"\n--vo=opengl command line help:\n"
-"Example: mpv --vo=opengl:scale-sep:lscale=lanczos2\n"
-"\nOptions:\n"
-" lscale=<filter>\n"
-" Set the scaling filter. Possible choices:\n"
-" bilinear: bilinear texture filtering (fastest).\n"
-" bicubic_fast: bicubic filter (without lookup texture).\n"
-" sharpen3: unsharp masking (sharpening) with radius=3.\n"
-" sharpen5: unsharp masking (sharpening) with radius=5.\n"
-" lanczos2: Lanczos with radius=2 (recommended).\n"
-" lanczos3: Lanczos with radius=3 (not recommended).\n"
-" mitchell: Mitchell-Netravali.\n"
-" Default: bilinear\n"
-" lparam1=<value> / lparam2=<value>\n"
-" Set parameters for configurable filters. Affects chroma scaler\n"
-" as well.\n"
-" Filters which use this:\n"
-" mitchell: b and c params (defaults: b=1/3 c=1/3)\n"
-" kaiser: (defaults: 6.33 6.33)\n"
-" sharpen3: lparam1 sets sharpening strength (default: 0.5)\n"
-" sharpen5: as with sharpen3\n"
-" osdcolor=<0xAARRGGBB>\n"
-" Use the given color for the OSD.\n"
-" stereo=<n>\n"
-" 0: normal display\n"
-" 1: side-by-side to red-cyan stereo\n"
-" 2: side-by-side to green-magenta stereo\n"
-" 3: side-by-side to quadbuffer stereo\n"
-" srgb\n"
-" Enable gamma-correct scaling by working in linear light. This\n"
-" makes use of sRGB textures and framebuffers.\n"
-" This option forces the options 'indirect' and 'gamma'.\n"
-" NOTE: For YUV colorspaces, gamma 2.2 is assumed. RGB input is always\n"
-" assumed to be in sRGB.\n"
-" pbo\n"
-" Enable use of PBOs. This is faster, but can sometimes lead to\n"
-" sporadic and temporary image corruption.\n"
-" dither-depth=<n>\n"
-" Positive non-zero values select the target bit depth.\n"
-" -1: Disable any dithering done by mpv.\n"
-" 0: Automatic selection. If output bit depth can't be detected,\n"
-" 8 bits per component are assumed.\n"
-" 8: Dither to 8 bit output.\n"
-" Default: -1.\n"
-" Note that dithering will always be disabled if the bit depth\n"
-" of the video is lower or qual to the detected dither-depth.\n"
-" If color management is enabled, input depth is assumed to be\n"
-" 16 bits, because the 3D LUT output is 16 bit wide.\n"
-" debug\n"
-" Check for OpenGL errors, i.e. call glGetError(). Also request a\n"
-" debug OpenGL context.\n"
-"Less useful options:\n"
-" swapinterval=<n>\n"
-" Interval in displayed frames between to buffer swaps.\n"
-" 1 is equivalent to enable VSYNC, 0 to disable VSYNC.\n"
-" no-scale-sep\n"
-" When using a separable scale filter for luma, usually two filter\n"
-" passes are done. This is often faster. However, it forces\n"
-" conversion to RGB in an extra pass, so it can actually be slower\n"
-" if used with fast filters on small screen resolutions. Using\n"
-" this options will make rendering a single operation.\n"
-" Note that chroma scalers are always done as 1-pass filters.\n"
-" cscale=<n>\n"
-" As lscale but for chroma (2x slower with little visible effect).\n"
-" Note that with some scaling filters, upscaling is always done in\n"
-" RGB. If chroma is not subsampled, this option is ignored, and the\n"
-" luma scaler is used instead. Setting this option is often useless.\n"
-" fancy-downscaling\n"
-" When using convolution based filters, extend the filter size\n"
-" when downscaling. Trades quality for reduced downscaling performance.\n"
-" no-npot\n"
-" Force use of power-of-2 texture sizes. For debugging only.\n"
-" Borders will look discolored due to filtering.\n"
-" glfinish\n"
-" Call glFinish() before swapping buffers\n"
-" backend=<sys>\n"
-" auto: auto-select (default)\n"
-" cocoa: Cocoa/OSX\n"
-" win: Win32/WGL\n"
-" x11: X11/GLX\n"
-" indirect\n"
-" Do YUV conversion and scaling as separate passes. This will\n"
-" first render the video into a video-sized RGB texture, and\n"
-" draw the result on screen. The luma scaler is used to scale\n"
-" the RGB image when rendering to screen. The chroma scaler\n"
-" is used only on YUV conversion, and only if the video uses\n"
-" chroma-subsampling.\n"
-" 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, rgb10, rgb16, rgb16f, rgb32f\n"
-" Default: rgb.\n"
-" gamma\n"
-" Always enable gamma control. (Disables delayed enabling.)\n"
-"Color management:\n"
-" icc-profile=<file>\n"
-" Load an ICC profile and use it to transform linear RGB to\n"
-" screen output. Needs LittleCMS2 support compiled in.\n"
-" icc-cache=<file>\n"
-" Store and load the 3D LUT created from the ICC profile in\n"
-" this file. This can be used to speed up loading, since\n"
-" LittleCMS2 can take a while to create the 3D LUT.\n"
-" Note that this file will be up to ~100 MB big.\n"
-" icc-intent=<value>\n"
-" 0: perceptual\n"
-" 1: relative colorimetric\n"
-" 2: saturation\n"
-" 3: absolute colorimetric (default)\n"
-" 3dlut-size=<r>x<g>x<b>\n"
-" Size of the 3D LUT generated from the ICC profile in each\n"
-" dimension. Default is 128x256x64.\n"
-" Sizes must be a power of two, and 256 at most.\n"
-"Note: all defaults mentioned are for 'opengl', not 'opengl-hq'.\n"
-"\n";
diff --git a/libvo/vo_opengl_old.c b/libvo/vo_opengl_old.c
deleted file mode 100644
index b8b1fd4813..0000000000
--- a/libvo/vo_opengl_old.c
+++ /dev/null
@@ -1,1166 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * You can alternatively redistribute this file and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <stdbool.h>
-#include <assert.h>
-
-#include "config.h"
-#include "talloc.h"
-#include "mp_msg.h"
-#include "subopt-helper.h"
-#include "video_out.h"
-#include "libmpcodecs/vfcap.h"
-#include "libmpcodecs/mp_image.h"
-#include "geometry.h"
-#include "sub/sub.h"
-
-#include "gl_common.h"
-#include "gl_osd.h"
-#include "aspect.h"
-#include "fastmemcpy.h"
-
-//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 gl_priv {
- MPGLContext *glctx;
- GL *gl;
-
- int allow_sw;
-
- int use_osd;
- int scaled_osd;
- struct mpgl_osd *osd;
- int osd_color;
-
- int use_ycbcr;
- int use_yuv;
- struct mp_csp_details colorspace;
- int is_yuv;
- int lscale;
- int cscale;
- float filter_strength;
- float noise_strength;
- int yuvconvtype;
- int use_rectangle;
- int err_shown;
- uint32_t image_width;
- uint32_t image_height;
- uint32_t image_format;
- int many_fmts;
- int have_texture_rg;
- int ati_hack;
- int force_pbo;
- int use_glFinish;
- int swap_interval;
- GLenum target;
- GLint texfmt;
- GLenum gl_format;
- GLenum gl_type;
- GLuint buffer;
- GLuint buffer_uv[2];
- int buffersize;
- int buffersize_uv;
- void *bufferptr;
- void *bufferptr_uv[2];
- GLuint fragprog;
- GLuint default_texs[22];
- char *custom_prog;
- char *custom_tex;
- int custom_tlin;
- int custom_trect;
- int mipmap_gen;
- int stereo_mode;
-
- struct mp_csp_equalizer video_eq;
-
- int texture_width;
- int texture_height;
- int mpi_flipped;
- int vo_flipped;
- int ass_border_x, ass_border_y;
-
- unsigned int slice_height;
-};
-
-static void resize(struct vo *vo, int x, int y)
-{
- struct gl_priv *p = vo->priv;
- GL *gl = p->gl;
-
- mp_msg(MSGT_VO, MSGL_V, "[gl] Resize: %dx%d\n", x, y);
- gl->Viewport(0, 0, x, y);
-
- gl->MatrixMode(GL_PROJECTION);
- gl->LoadIdentity();
- p->ass_border_x = p->ass_border_y = 0;
- if (aspect_scaling()) {
- int new_w, new_h;
- GLdouble scale_x, scale_y;
- aspect(vo, &new_w, &new_h, A_WINZOOM);
- panscan_calc_windowed(vo);
- new_w += vo->panscan_x;
- new_h += vo->panscan_y;
- scale_x = (GLdouble)new_w / (GLdouble)x;
- scale_y = (GLdouble)new_h / (GLdouble)y;
- gl->Scaled(scale_x, scale_y, 1);
- p->ass_border_x = (vo->dwidth - new_w) / 2;
- p->ass_border_y = (vo->dheight - new_h) / 2;
- }
- gl->Ortho(0, p->image_width, p->image_height, 0, -1, 1);
-
- gl->MatrixMode(GL_MODELVIEW);
- gl->LoadIdentity();
-
- gl->Clear(GL_COLOR_BUFFER_BIT);
- vo->want_redraw = true;
-}
-
-static void texSize(struct vo *vo, int w, int h, int *texw, int *texh)
-{
- struct gl_priv *p = vo->priv;
-
- if (p->use_rectangle) {
- *texw = w;
- *texh = h;
- } else {
- *texw = 32;
- while (*texw < w)
- *texw *= 2;
- *texh = 32;
- while (*texh < h)
- *texh *= 2;
- }
- if (p->ati_hack)
- *texw = (*texw + 511) & ~511;
-}
-
-//! maximum size of custom fragment program
-#define MAX_CUSTOM_PROG_SIZE (1024 * 1024)
-static void update_yuvconv(struct vo *vo)
-{
- struct gl_priv *p = vo->priv;
- GL *gl = p->gl;
-
- int xs, ys, depth;
- struct mp_csp_params cparams = { .colorspace = p->colorspace };
- mp_csp_copy_equalizer_values(&cparams, &p->video_eq);
- gl_conversion_params_t params = {
- p->target, p->yuvconvtype, cparams,
- p->texture_width, p->texture_height, 0, 0, p->filter_strength,
- p->noise_strength
- };
- mp_get_chroma_shift(p->image_format, &xs, &ys, &depth);
- params.chrom_texw = params.texw >> xs;
- params.chrom_texh = params.texh >> ys;
- params.csp_params.input_bits = depth;
- params.csp_params.texture_bits = depth+7 & ~7;
- glSetupYUVConversion(gl, &params);
- if (p->custom_prog) {
- FILE *f = fopen(p->custom_prog, "rb");
- if (!f) {
- mp_msg(MSGT_VO, MSGL_WARN,
- "[gl] Could not read customprog %s\n", p->custom_prog);
- } else {
- char *prog = calloc(1, MAX_CUSTOM_PROG_SIZE + 1);
- fread(prog, 1, MAX_CUSTOM_PROG_SIZE, f);
- fclose(f);
- loadGPUProgram(gl, GL_FRAGMENT_PROGRAM, prog);
- free(prog);
- }
- gl->ProgramEnvParameter4f(GL_FRAGMENT_PROGRAM, 0,
- 1.0 / p->texture_width,
- 1.0 / p->texture_height,
- p->texture_width, p->texture_height);
- }
- if (p->custom_tex) {
- FILE *f = fopen(p->custom_tex, "rb");
- if (!f) {
- mp_msg(MSGT_VO, MSGL_WARN,
- "[gl] Could not read customtex %s\n", p->custom_tex);
- } else {
- int width, height, maxval;
- gl->ActiveTexture(GL_TEXTURE3);
- if (glCreatePPMTex(gl, p->custom_trect ? GL_TEXTURE_RECTANGLE : GL_TEXTURE_2D,
- 0, p->custom_tlin ? GL_LINEAR : GL_NEAREST,
- f, &width, &height, &maxval)) {
- gl->ProgramEnvParameter4f(GL_FRAGMENT_PROGRAM, 1,
- 1.0 / width, 1.0 / height,
- width, height);
- } else
- mp_msg(MSGT_VO, MSGL_WARN,
- "[gl] Error parsing customtex %s\n", p->custom_tex);
- fclose(f);
- gl->ActiveTexture(GL_TEXTURE0);
- }
- }
-}
-
-static void draw_osd(struct vo *vo, struct osd_state *osd)
-{
- struct gl_priv *p = vo->priv;
- GL *gl = p->gl;
- assert(p->osd);
-
- if (!p->use_osd)
- return;
-
- if (!p->scaled_osd) {
- gl->MatrixMode(GL_PROJECTION);
- gl->PushMatrix();
- gl->LoadIdentity();
- gl->Ortho(0, vo->dwidth, vo->dheight, 0, -1, 1);
- }
-
- gl->Color4ub((p->osd_color >> 16) & 0xff, (p->osd_color >> 8) & 0xff,
- p->osd_color & 0xff, 0xff - (p->osd_color >> 24));
-
- struct mp_osd_res res = {
- .w = vo->dwidth,
- .h = vo->dheight,
- .display_par = vo->monitor_par,
- .video_par = vo->aspdat.par,
- };
- if (p->scaled_osd) {
- res.w = p->image_width;
- res.h = p->image_height;
- } else if (aspect_scaling()) {
- res.ml = res.mr = p->ass_border_x;
- res.mt = res.mb = p->ass_border_y;
- }
-
- mpgl_osd_draw_legacy(p->osd, osd, res);
-
- if (!p->scaled_osd)
- gl->PopMatrix();
-}
-
-/**
- * \brief uninitialize OpenGL context, freeing textures, buffers etc.
- */
-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);
- p->fragprog = 0;
- while (p->default_texs[i] != 0)
- i++;
- if (i)
- gl->DeleteTextures(i, p->default_texs);
- p->default_texs[0] = 0;
- if (p->osd)
- mpgl_osd_destroy(p->osd);
- p->osd = NULL;
- p->buffer = 0;
- p->buffersize = 0;
- p->bufferptr = NULL;
- if (gl->DeleteBuffers && p->buffer_uv[0])
- gl->DeleteBuffers(2, p->buffer_uv);
- p->buffer_uv[0] = p->buffer_uv[1] = 0;
- p->buffersize_uv = 0;
- p->bufferptr_uv[0] = p->bufferptr_uv[1] = 0;
- p->err_shown = 0;
-}
-
-static void autodetectGlExtensions(struct vo *vo)
-{
- struct gl_priv *p = vo->priv;
- GL *gl = p->gl;
-
- const char *extensions = gl->GetString(GL_EXTENSIONS);
- const char *vendor = gl->GetString(GL_VENDOR);
- const char *version = gl->GetString(GL_VERSION);
- const char *renderer = gl->GetString(GL_RENDERER);
- int is_ati = vendor && strstr(vendor, "ATI") != NULL;
- int ati_broken_pbo = 0;
- mp_msg(MSGT_VO, MSGL_V, "[gl] Running on OpenGL '%s' by '%s', version '%s'\n",
- renderer, vendor, version);
- if (is_ati && strncmp(version, "2.1.", 4) == 0) {
- int ver = atoi(version + 4);
- mp_msg(MSGT_VO, MSGL_V, "[gl] Detected ATI driver version: %i\n", ver);
- ati_broken_pbo = ver && ver < 8395;
- }
- if (p->ati_hack == -1)
- p->ati_hack = ati_broken_pbo;
- if (p->force_pbo == -1) {
- p->force_pbo = 0;
- if (extensions && strstr(extensions, "_pixel_buffer_object"))
- p->force_pbo = is_ati;
- }
- p->have_texture_rg = extensions && strstr(extensions, "GL_ARB_texture_rg");
- if (p->use_rectangle == -1) {
- p->use_rectangle = 0;
- if (extensions) {
-// if (strstr(extensions, "_texture_non_power_of_two"))
- if (strstr(extensions, "_texture_rectangle"))
- p->use_rectangle = renderer
- && strstr(renderer, "Mesa DRI R200") ? 1 : 0;
- }
- }
- if (p->use_osd == -1)
- p->use_osd = gl->BindTexture != NULL;
- if (p->use_yuv == -1)
- p->use_yuv = glAutodetectYUVConversion(gl);
-
- int eq_caps = 0;
- int yuv_mask = (1 << p->use_yuv);
- if (!(yuv_mask & MASK_NOT_COMBINERS)) {
- // combiners
- eq_caps = (1 << MP_CSP_EQ_HUE) | (1 << MP_CSP_EQ_SATURATION);
- } else if (yuv_mask & MASK_ALL_YUV) {
- eq_caps = MP_CSP_EQ_CAPS_COLORMATRIX;
- if (yuv_mask & MASK_GAMMA_SUPPORT)
- eq_caps |= MP_CSP_EQ_CAPS_GAMMA;
- }
- p->video_eq.capabilities = eq_caps;
-
- if (is_ati && (p->lscale == 1 || p->lscale == 2 || p->cscale == 1 || p->cscale == 2))
- mp_msg(MSGT_VO, MSGL_WARN, "[gl] Selected scaling mode may be broken on"
- " ATI cards.\n"
- "Tell _them_ to fix GL_REPEAT if you have issues.\n");
- mp_msg(MSGT_VO, MSGL_V, "[gl] Settings after autodetection: ati-hack = %i, "
- "force-pbo = %i, rectangle = %i, yuv = %i\n",
- p->ati_hack, p->force_pbo, p->use_rectangle, p->use_yuv);
-}
-
-static GLint get_scale_type(struct vo *vo, int chroma)
-{
- struct gl_priv *p = vo->priv;
-
- int nearest = (chroma ? p->cscale : p->lscale) & 64;
- if (nearest)
- return p->mipmap_gen ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
- return p->mipmap_gen ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
-}
-
-// Return the high byte of the value that represents white in chroma (U/V)
-static int get_chroma_clear_val(int bit_depth)
-{
- return 1 << (bit_depth - 1 & 7);
-}
-
-/**
- * \brief Initialize a (new or reused) OpenGL context.
- * set global gl-related variables to their default values
- */
-static int initGl(struct vo *vo, uint32_t d_width, uint32_t d_height)
-{
- struct gl_priv *p = vo->priv;
- GL *gl = p->gl;
-
- GLint scale_type = get_scale_type(vo, 0);
- autodetectGlExtensions(vo);
- p->target = p->use_rectangle == 1 ? GL_TEXTURE_RECTANGLE : GL_TEXTURE_2D;
- p->yuvconvtype = SET_YUV_CONVERSION(p->use_yuv) |
- SET_YUV_LUM_SCALER(p->lscale) |
- SET_YUV_CHROM_SCALER(p->cscale);
-
- texSize(vo, p->image_width, p->image_height,
- &p->texture_width, &p->texture_height);
-
- gl->Disable(GL_BLEND);
- gl->Disable(GL_DEPTH_TEST);
- gl->DepthMask(GL_FALSE);
- gl->Disable(GL_CULL_FACE);
- gl->Enable(p->target);
- gl->DrawBuffer(GL_BACK);
- gl->TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- mp_msg(MSGT_VO, MSGL_V, "[gl] Creating %dx%d texture...\n",
- p->texture_width, p->texture_height);
-
- glCreateClearTex(gl, p->target, p->texfmt, p->gl_format,
- p->gl_type, scale_type,
- p->texture_width, p->texture_height, 0);
-
- if (p->mipmap_gen)
- gl->TexParameteri(p->target, GL_GENERATE_MIPMAP, GL_TRUE);
-
- if (p->is_yuv) {
- int i;
- int xs, ys, depth;
- scale_type = get_scale_type(vo, 1);
- mp_get_chroma_shift(p->image_format, &xs, &ys, &depth);
- int clear = get_chroma_clear_val(depth);
- gl->GenTextures(21, p->default_texs);
- p->default_texs[21] = 0;
- for (i = 0; i < 7; i++) {
- gl->ActiveTexture(GL_TEXTURE1 + i);
- gl->BindTexture(GL_TEXTURE_2D, p->default_texs[i]);
- gl->BindTexture(GL_TEXTURE_RECTANGLE, p->default_texs[i + 7]);
- gl->BindTexture(GL_TEXTURE_3D, p->default_texs[i + 14]);
- }
- gl->ActiveTexture(GL_TEXTURE1);
- glCreateClearTex(gl, p->target, p->texfmt, p->gl_format,
- p->gl_type, scale_type,
- p->texture_width >> xs, p->texture_height >> ys,
- clear);
- if (p->mipmap_gen)
- gl->TexParameteri(p->target, GL_GENERATE_MIPMAP, GL_TRUE);
- gl->ActiveTexture(GL_TEXTURE2);
- glCreateClearTex(gl, p->target, p->texfmt, p->gl_format,
- p->gl_type, scale_type,
- p->texture_width >> xs, p->texture_height >> ys,
- clear);
- if (p->mipmap_gen)
- gl->TexParameteri(p->target, GL_GENERATE_MIPMAP, GL_TRUE);
- gl->ActiveTexture(GL_TEXTURE0);
- gl->BindTexture(p->target, 0);
- }
- if (p->is_yuv || p->custom_prog) {
- if ((MASK_NOT_COMBINERS & (1 << p->use_yuv)) || p->custom_prog) {
- if (!gl->GenPrograms || !gl->BindProgram)
- mp_msg(MSGT_VO, MSGL_ERR,
- "[gl] fragment program functions missing!\n");
- else {
- gl->GenPrograms(1, &p->fragprog);
- gl->BindProgram(GL_FRAGMENT_PROGRAM, p->fragprog);
- }
- }
- update_yuvconv(vo);
- }
-
- p->osd = mpgl_osd_init(gl, true);
- p->osd->scaled = p->scaled_osd;
-
- resize(vo, d_width, d_height);
-
- gl->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- gl->Clear(GL_COLOR_BUFFER_BIT);
- if (gl->SwapInterval && p->swap_interval >= 0)
- gl->SwapInterval(p->swap_interval);
- return 1;
-}
-
-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;
-
- 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,
- uint32_t d_width, uint32_t d_height, uint32_t flags,
- uint32_t format)
-{
- struct gl_priv *p = vo->priv;
-
- int xs, ys;
- p->image_height = height;
- p->image_width = width;
- p->image_format = format;
- p->is_yuv = mp_get_chroma_shift(p->image_format, &xs, &ys, NULL) > 0;
- p->is_yuv |= (xs << 8) | (ys << 16);
- glFindFormat(format, p->have_texture_rg, NULL, &p->texfmt, &p->gl_format,
- &p->gl_type);
-
- p->vo_flipped = !!(flags & VOFLAG_FLIPPING);
-
- if (vo->config_count)
- uninitGl(vo);
-
- if (!create_window(vo, d_width, d_height, flags))
- return -1;
-
- initGl(vo, vo->dwidth, vo->dheight);
-
- return 0;
-}
-
-static void check_events(struct vo *vo)
-{
- struct gl_priv *p = vo->priv;
-
- int e = p->glctx->check_events(vo);
- if (e & VO_EVENT_REINIT) {
- uninitGl(vo);
- initGl(vo, vo->dwidth, vo->dheight);
- }
- if (e & VO_EVENT_RESIZE)
- resize(vo, vo->dwidth, vo->dheight);
- if (e & VO_EVENT_EXPOSE)
- vo->want_redraw = true;
-}
-
-static void do_render(struct vo *vo)
-{
- struct gl_priv *p = vo->priv;
- GL *gl = p->gl;
-
-// Enable(GL_TEXTURE_2D);
-// BindTexture(GL_TEXTURE_2D, texture_id);
-
- gl->Color4f(1, 1, 1, 1);
- if (p->is_yuv || p->custom_prog)
- glEnableYUVConversion(gl, p->target, p->yuvconvtype);
- if (p->stereo_mode) {
- glEnable3DLeft(gl, p->stereo_mode);
- glDrawTex(gl, 0, 0, p->image_width, p->image_height,
- 0, 0, p->image_width >> 1, p->image_height,
- p->texture_width, p->texture_height,
- p->use_rectangle == 1, p->is_yuv,
- p->mpi_flipped ^ p->vo_flipped);
- glEnable3DRight(gl, p->stereo_mode);
- glDrawTex(gl, 0, 0, p->image_width, p->image_height,
- p->image_width >> 1, 0, p->image_width >> 1,
- p->image_height, p->texture_width, p->texture_height,
- p->use_rectangle == 1, p->is_yuv,
- p->mpi_flipped ^ p->vo_flipped);
- glDisable3D(gl, p->stereo_mode);
- } else {
- glDrawTex(gl, 0, 0, p->image_width, p->image_height,
- 0, 0, p->image_width, p->image_height,
- p->texture_width, p->texture_height,
- p->use_rectangle == 1, p->is_yuv,
- p->mpi_flipped ^ p->vo_flipped);
- }
- if (p->is_yuv || p->custom_prog)
- glDisableYUVConversion(gl, p->target, p->yuvconvtype);
-}
-
-static void flip_page(struct vo *vo)
-{
- struct gl_priv *p = vo->priv;
- GL *gl = p->gl;
-
- if (p->use_glFinish)
- gl->Finish();
- p->glctx->swapGlBuffers(p->glctx);
- if (aspect_scaling())
- gl->Clear(GL_COLOR_BUFFER_BIT);
-}
-
-static int draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h,
- int x, int y)
-{
- struct gl_priv *p = vo->priv;
- GL *gl = p->gl;
-
- p->mpi_flipped = stride[0] < 0;
- glUploadTex(gl, p->target, p->gl_format, p->gl_type, src[0], stride[0],
- x, y, w, h, p->slice_height);
- if (p->is_yuv) {
- int xs, ys;
- mp_get_chroma_shift(p->image_format, &xs, &ys, NULL);
- gl->ActiveTexture(GL_TEXTURE1);
- glUploadTex(gl, p->target, p->gl_format, p->gl_type, src[1], stride[1],
- x >> xs, y >> ys, w >> xs, h >> ys, p->slice_height);
- gl->ActiveTexture(GL_TEXTURE2);
- glUploadTex(gl, p->target, p->gl_format, p->gl_type, src[2], stride[2],
- x >> xs, y >> ys, w >> xs, h >> ys, p->slice_height);
- gl->ActiveTexture(GL_TEXTURE0);
- }
- return 0;
-}
-
-static uint32_t get_image(struct vo *vo, mp_image_t *mpi)
-{
- struct gl_priv *p = vo->priv;
- GL *gl = p->gl;
-
- int needed_size;
- if (!gl->GenBuffers || !gl->BindBuffer || !gl->BufferData || !gl->MapBuffer) {
- if (!p->err_shown)
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] extensions missing for dr\n"
- "Expect a _major_ speed penalty\n");
- p->err_shown = 1;
- return VO_FALSE;
- }
- if (mpi->flags & MP_IMGFLAG_READABLE)
- return VO_FALSE;
- if (mpi->type != MP_IMGTYPE_STATIC && mpi->type != MP_IMGTYPE_TEMP &&
- (mpi->type != MP_IMGTYPE_NUMBERED || mpi->number))
- return VO_FALSE;
- if (p->ati_hack) {
- mpi->width = p->texture_width;
- mpi->height = p->texture_height;
- }
- mpi->stride[0] = mpi->width * mpi->bpp / 8;
- needed_size = mpi->stride[0] * mpi->height;
- if (!p->buffer)
- gl->GenBuffers(1, &p->buffer);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer);
- if (needed_size > p->buffersize) {
- p->buffersize = needed_size;
- gl->BufferData(GL_PIXEL_UNPACK_BUFFER, p->buffersize,
- NULL, GL_DYNAMIC_DRAW);
- }
- if (!p->bufferptr)
- p->bufferptr = gl->MapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
- mpi->planes[0] = p->bufferptr;
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- if (!mpi->planes[0]) {
- if (!p->err_shown)
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] could not acquire buffer for dr\n"
- "Expect a _major_ speed penalty\n");
- p->err_shown = 1;
- return VO_FALSE;
- }
- if (p->is_yuv) {
- // planar YUV
- int xs, ys, component_bits;
- mp_get_chroma_shift(p->image_format, &xs, &ys, &component_bits);
- int bp = (component_bits + 7) / 8;
- mpi->flags |= MP_IMGFLAG_COMMON_STRIDE | MP_IMGFLAG_COMMON_PLANE;
- mpi->stride[0] = mpi->width * bp;
- mpi->planes[1] = mpi->planes[0] + mpi->stride[0] * mpi->height;
- mpi->stride[1] = (mpi->width >> xs) * bp;
- mpi->planes[2] = mpi->planes[1] + mpi->stride[1] * (mpi->height >> ys);
- mpi->stride[2] = (mpi->width >> xs) * bp;
- if (p->ati_hack) {
- mpi->flags &= ~MP_IMGFLAG_COMMON_PLANE;
- if (!p->buffer_uv[0])
- gl->GenBuffers(2, p->buffer_uv);
- int buffer_size = mpi->stride[1] * mpi->height;
- if (buffer_size > p->buffersize_uv) {
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer_uv[0]);
- gl->BufferData(GL_PIXEL_UNPACK_BUFFER, buffer_size, NULL,
- GL_DYNAMIC_DRAW);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer_uv[1]);
- gl->BufferData(GL_PIXEL_UNPACK_BUFFER, buffer_size, NULL,
- GL_DYNAMIC_DRAW);
- p->buffersize_uv = buffer_size;
- }
- if (!p->bufferptr_uv[0]) {
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer_uv[0]);
- p->bufferptr_uv[0] = gl->MapBuffer(GL_PIXEL_UNPACK_BUFFER,
- GL_WRITE_ONLY);
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer_uv[1]);
- p->bufferptr_uv[1] = gl->MapBuffer(GL_PIXEL_UNPACK_BUFFER,
- GL_WRITE_ONLY);
- }
- mpi->planes[1] = p->bufferptr_uv[0];
- mpi->planes[2] = p->bufferptr_uv[1];
- }
- }
- mpi->flags |= MP_IMGFLAG_DIRECT;
- return VO_TRUE;
-}
-
-static void clear_border(struct vo *vo, uint8_t *dst, int start, int stride,
- int height, int full_height, int value)
-{
- int right_border = stride - start;
- int bottom_border = full_height - height;
- while (height > 0) {
- if (right_border > 0)
- memset(dst + start, value, right_border);
- dst += stride;
- height--;
- }
- if (bottom_border > 0)
- memset(dst, value, stride * bottom_border);
-}
-
-static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
-{
- struct gl_priv *p = vo->priv;
- GL *gl = p->gl;
-
- int slice = p->slice_height;
- int stride[3];
- unsigned char *planes[3];
- mp_image_t mpi2 = *mpi;
- int w = mpi->w, h = mpi->h;
- if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
- goto skip_upload;
- mpi2.flags = 0;
- mpi2.type = MP_IMGTYPE_TEMP;
- mpi2.width = mpi2.w;
- mpi2.height = mpi2.h;
- if (p->force_pbo && !(mpi->flags & MP_IMGFLAG_DIRECT) && !p->bufferptr
- && get_image(vo, &mpi2) == VO_TRUE)
- {
- int bp = mpi->bpp / 8;
- int xs, ys, component_bits;
- mp_get_chroma_shift(p->image_format, &xs, &ys, &component_bits);
- if (p->is_yuv)
- bp = (component_bits + 7) / 8;
- memcpy_pic(mpi2.planes[0], mpi->planes[0], mpi->w * bp, mpi->h,
- mpi2.stride[0], mpi->stride[0]);
- int uv_bytes = (mpi->w >> xs) * bp;
- if (p->is_yuv) {
- memcpy_pic(mpi2.planes[1], mpi->planes[1], uv_bytes, mpi->h >> ys,
- mpi2.stride[1], mpi->stride[1]);
- memcpy_pic(mpi2.planes[2], mpi->planes[2], uv_bytes, mpi->h >> ys,
- mpi2.stride[2], mpi->stride[2]);
- }
- if (p->ati_hack) {
- // since we have to do a full upload we need to clear the borders
- clear_border(vo, mpi2.planes[0], mpi->w * bp, mpi2.stride[0],
- mpi->h, mpi2.height, 0);
- if (p->is_yuv) {
- int clear = get_chroma_clear_val(component_bits);
- clear_border(vo, mpi2.planes[1], uv_bytes, mpi2.stride[1],
- mpi->h >> ys, mpi2.height >> ys, clear);
- clear_border(vo, mpi2.planes[2], uv_bytes, mpi2.stride[2],
- mpi->h >> ys, mpi2.height >> ys, clear);
- }
- }
- mpi = &mpi2;
- }
- stride[0] = mpi->stride[0];
- stride[1] = mpi->stride[1];
- stride[2] = mpi->stride[2];
- planes[0] = mpi->planes[0];
- planes[1] = mpi->planes[1];
- planes[2] = mpi->planes[2];
- p->mpi_flipped = stride[0] < 0;
- if (mpi->flags & MP_IMGFLAG_DIRECT) {
- intptr_t base = (intptr_t)planes[0];
- if (p->ati_hack) {
- w = p->texture_width;
- h = p->texture_height;
- }
- if (p->mpi_flipped)
- base += (mpi->h - 1) * stride[0];
- planes[0] -= base;
- planes[1] -= base;
- planes[2] -= base;
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer);
- gl->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
- p->bufferptr = NULL;
- if (!(mpi->flags & MP_IMGFLAG_COMMON_PLANE))
- planes[0] = planes[1] = planes[2] = NULL;
- slice = 0; // always "upload" full texture
- }
- glUploadTex(gl, p->target, p->gl_format, p->gl_type, planes[0],
- stride[0], 0, 0, w, h, slice);
- if (p->is_yuv) {
- int xs, ys;
- mp_get_chroma_shift(p->image_format, &xs, &ys, NULL);
- if ((mpi->flags & MP_IMGFLAG_DIRECT) && !(mpi->flags & MP_IMGFLAG_COMMON_PLANE)) {
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer_uv[0]);
- gl->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
- p->bufferptr_uv[0] = NULL;
- }
- gl->ActiveTexture(GL_TEXTURE1);
- glUploadTex(gl, p->target, p->gl_format, p->gl_type, planes[1],
- stride[1], 0, 0, w >> xs, h >> ys, slice);
- if ((mpi->flags & MP_IMGFLAG_DIRECT) && !(mpi->flags & MP_IMGFLAG_COMMON_PLANE)) {
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer_uv[1]);
- gl->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
- p->bufferptr_uv[1] = NULL;
- }
- gl->ActiveTexture(GL_TEXTURE2);
- glUploadTex(gl, p->target, p->gl_format, p->gl_type, planes[2],
- stride[2], 0, 0, w >> xs, h >> ys, slice);
- gl->ActiveTexture(GL_TEXTURE0);
- }
- if (mpi->flags & MP_IMGFLAG_DIRECT) {
- gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- }
-skip_upload:
- do_render(vo);
- return VO_TRUE;
-}
-
-static mp_image_t *get_screenshot(struct vo *vo)
-{
- struct gl_priv *p = vo->priv;
- GL *gl = p->gl;
-
- mp_image_t *image = alloc_mpi(p->texture_width, p->texture_height,
- p->image_format);
-
- glDownloadTex(gl, p->target, p->gl_format, p->gl_type, image->planes[0],
- image->stride[0]);
-
- if (p->is_yuv) {
- gl->ActiveTexture(GL_TEXTURE1);
- glDownloadTex(gl, p->target, p->gl_format, p->gl_type, image->planes[1],
- image->stride[1]);
- gl->ActiveTexture(GL_TEXTURE2);
- glDownloadTex(gl, p->target, p->gl_format, p->gl_type, image->planes[2],
- image->stride[2]);
- gl->ActiveTexture(GL_TEXTURE0);
- }
-
- image->w = p->image_width;
- image->h = p->image_height;
- image->display_w = vo->aspdat.prew;
- image->display_h = vo->aspdat.preh;
-
- mp_image_set_colorspace_details(image, &p->colorspace);
-
- return image;
-}
-
-static int query_format(struct vo *vo, uint32_t format)
-{
- struct gl_priv *p = vo->priv;
-
- int depth;
- int caps = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_FLIP |
- VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE;
- if (p->use_osd)
- caps |= VFCAP_OSD;
- if (format == IMGFMT_RGB24 || format == IMGFMT_RGBA)
- return caps;
- if (p->use_yuv && mp_get_chroma_shift(format, NULL, NULL, &depth) &&
- (depth == 8 || depth == 16 || glYUVLargeRange(p->use_yuv)) &&
- (IMGFMT_IS_YUVP16_NE(format) || !IMGFMT_IS_YUVP16(format)))
- return caps;
- // HACK, otherwise we get only b&w with some filters (e.g. -vf eq)
- // ideally MPlayer should be fixed instead not to use Y800 when it has the choice
- if (!p->use_yuv && (format == IMGFMT_Y8 || format == IMGFMT_Y800))
- return 0;
- if (!p->use_ycbcr && (format == IMGFMT_UYVY || format == IMGFMT_YVYU))
- return 0;
- if (p->many_fmts &&
- glFindFormat(format, p->have_texture_rg, NULL, NULL, NULL, NULL))
- return caps;
- return 0;
-}
-
-static void uninit(struct vo *vo)
-{
- struct gl_priv *p = vo->priv;
-
- uninitGl(vo);
- free(p->custom_prog);
- p->custom_prog = NULL;
- free(p->custom_tex);
- p->custom_tex = NULL;
- mpgl_uninit(p->glctx);
- p->glctx = NULL;
- p->gl = NULL;
-}
-
-static int backend_valid(void *arg)
-{
- return mpgl_find_backend(*(const char **)arg) >= 0;
-}
-
-static int preinit(struct vo *vo, const char *arg)
-{
- struct gl_priv *p = talloc_zero(vo, struct gl_priv);
- vo->priv = p;
-
- *p = (struct gl_priv) {
- .many_fmts = 1,
- .use_osd = -1,
- .use_yuv = -1,
- .colorspace = MP_CSP_DETAILS_DEFAULTS,
- .filter_strength = 0.5,
- .use_rectangle = -1,
- .ati_hack = -1,
- .force_pbo = -1,
- .swap_interval = vo_vsync,
- .custom_prog = NULL,
- .custom_tex = NULL,
- .custom_tlin = 1,
- .osd_color = 0xffffff,
- };
-
- char *backend_arg = NULL;
-
- //essentially unused; for legacy warnings only
- int user_colorspace = 0;
- int levelconv = -1;
- int aspect = -1;
-
- const opt_t subopts[] = {
- {"manyfmts", OPT_ARG_BOOL, &p->many_fmts, NULL},
- {"osd", OPT_ARG_BOOL, &p->use_osd, NULL},
- {"scaled-osd", OPT_ARG_BOOL, &p->scaled_osd, NULL},
- {"ycbcr", OPT_ARG_BOOL, &p->use_ycbcr, NULL},
- {"slice-height", OPT_ARG_INT, &p->slice_height, int_non_neg},
- {"rectangle", OPT_ARG_INT, &p->use_rectangle,int_non_neg},
- {"yuv", OPT_ARG_INT, &p->use_yuv, int_non_neg},
- {"lscale", OPT_ARG_INT, &p->lscale, int_non_neg},
- {"cscale", OPT_ARG_INT, &p->cscale, int_non_neg},
- {"filter-strength", OPT_ARG_FLOAT, &p->filter_strength, NULL},
- {"noise-strength", OPT_ARG_FLOAT, &p->noise_strength, NULL},
- {"ati-hack", OPT_ARG_BOOL, &p->ati_hack, NULL},
- {"force-pbo", OPT_ARG_BOOL, &p->force_pbo, NULL},
- {"glfinish", OPT_ARG_BOOL, &p->use_glFinish, NULL},
- {"swapinterval", OPT_ARG_INT, &p->swap_interval,NULL},
- {"customprog", OPT_ARG_MSTRZ,&p->custom_prog, NULL},
- {"customtex", OPT_ARG_MSTRZ,&p->custom_tex, NULL},
- {"customtlin", OPT_ARG_BOOL, &p->custom_tlin, NULL},
- {"customtrect", OPT_ARG_BOOL, &p->custom_trect, NULL},
- {"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, &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.
- {"aspect", OPT_ARG_BOOL, &aspect, NULL},
- {"colorspace", OPT_ARG_INT, &user_colorspace, NULL},
- {"levelconv", OPT_ARG_INT, &levelconv, NULL},
- {NULL}
- };
-
- if (subopt_parse(arg, subopts) != 0) {
- mp_msg(MSGT_VO, MSGL_FATAL,
- "\n-vo opengl_old command line help:\n"
- "Example: mpv -vo opengl_old:slice-height=4\n"
- "\nOptions:\n"
- " nomanyfmts\n"
- " Disable extended color formats for OpenGL 1.2 and later\n"
- " slice-height=<0-...>\n"
- " Slice size for texture transfer, 0 for whole image\n"
- " noosd\n"
- " Do not use OpenGL OSD code\n"
- " scaled-osd\n"
- " Render OSD at movie resolution and scale it\n"
- " rectangle=<0,1,2>\n"
- " 0: use power-of-two textures\n"
- " 1: use texture_rectangle\n"
- " 2: use texture_non_power_of_two\n"
- " ati-hack\n"
- " Workaround ATI bug with PBOs\n"
- " force-pbo\n"
- " Force use of PBO even if this involves an extra memcpy\n"
- " glfinish\n"
- " Call glFinish() before swapping buffers\n"
- " swapinterval=<n>\n"
- " Interval in displayed frames between to buffer swaps.\n"
- " 1 is equivalent to enable VSYNC, 0 to disable VSYNC.\n"
- " Requires GLX_SGI_swap_control support to work.\n"
- " ycbcr\n"
- " also try to use the GL_MESA_ycbcr_texture extension\n"
- " yuv=<n>\n"
- " 0: use software YUV to RGB conversion.\n"
- " 1: deprecated, will use yuv=2 (used to be nVidia register combiners).\n"
- " 2: use fragment program.\n"
- " 3: use fragment program with gamma correction.\n"
- " 4: use fragment program with gamma correction via lookup.\n"
- " 5: use ATI-specific method (for older cards).\n"
- " 6: use lookup via 3D texture.\n"
- " lscale=<n>\n"
- " 0: use standard bilinear scaling for luma.\n"
- " 1: use improved bicubic scaling for luma.\n"
- " 2: use cubic in X, linear in Y direction scaling for luma.\n"
- " 3: as 1 but without using a lookup texture.\n"
- " 4: experimental unsharp masking (sharpening).\n"
- " 5: experimental unsharp masking (sharpening) with larger radius.\n"
- " cscale=<n>\n"
- " as lscale but for chroma (2x slower with little visible effect).\n"
- " filter-strength=<value>\n"
- " set the effect strength for some lscale/cscale filters\n"
- " noise-strength=<value>\n"
- " set how much noise to add. 1.0 is suitable for dithering to 6 bit.\n"
- " customprog=<filename>\n"
- " use a custom YUV conversion program\n"
- " customtex=<filename>\n"
- " use a custom YUV conversion lookup texture\n"
- " nocustomtlin\n"
- " use GL_NEAREST scaling for customtex texture\n"
- " customtrect\n"
- " use texture_rectangle for customtex texture\n"
- " mipmapgen\n"
- " generate mipmaps for the video image (use with TXB in customprog)\n"
- " osdcolor=<0xAARRGGBB>\n"
- " use the given color for the OSD\n"
- " stereo=<n>\n"
- " 0: normal display\n"
- " 1: side-by-side to red-cyan stereo\n"
- " 2: side-by-side to green-magenta stereo\n"
- " 3: side-by-side to quadbuffer stereo\n"
- " sw\n"
- " allow using a software renderer, if such is detected\n"
- " backend=<sys>\n"
- " auto: auto-select (default)\n"
- " cocoa: Cocoa/OSX\n"
- " win: Win32/WGL\n"
- " x11: X11/GLX\n"
- "\n");
- return -1;
- }
- if (user_colorspace != 0 || levelconv != -1) {
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] \"colorspace\" and \"levelconv\" "
- "suboptions have been removed. Use options --colormatrix and"
- " --colormatrix-input-range/--colormatrix-output-range instead.\n");
- return -1;
- }
- if (aspect != -1) {
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] \"noaspect\" suboption has been "
- "removed. Use --noaspect instead.\n");
- return -1;
- }
- if (p->use_yuv == 1) {
- mp_msg(MSGT_VO, MSGL_WARN, "[gl] yuv=1 (nVidia register combiners) have"
- " been removed, using yuv=2 instead.\n");
- p->use_yuv = 2;
- }
-
- int backend = backend_arg ? mpgl_find_backend(backend_arg) : GLTYPE_AUTO;
- free(backend_arg);
-
- p->glctx = mpgl_init(backend, vo);
- if (!p->glctx)
- goto err_out;
- p->gl = p->glctx->gl;
-
- 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.
- uninitGl(vo);
- if (!mpgl_destroy_window(p->glctx))
- goto err_out;
- }
- if (p->many_fmts)
- mp_msg(MSGT_VO, MSGL_INFO, "[gl] using extended formats. "
- "Use -vo gl:nomanyfmts if playback fails.\n");
- mp_msg(MSGT_VO, MSGL_V, "[gl] Using %d as slice height "
- "(0 means image height).\n", p->slice_height);
-
- return 0;
-
-err_out:
- uninit(vo);
- return -1;
-}
-
-static int control(struct vo *vo, uint32_t request, void *data)
-{
- struct gl_priv *p = vo->priv;
-
- switch (request) {
- case VOCTRL_QUERY_FORMAT:
- return query_format(vo, *(uint32_t *)data);
- case VOCTRL_DRAW_IMAGE:
- return draw_image(vo, data);
- case VOCTRL_ONTOP:
- if (!p->glctx->ontop)
- break;
- p->glctx->ontop(vo);
- return VO_TRUE;
- case VOCTRL_FULLSCREEN:
- p->glctx->fullscreen(vo);
- resize(vo, vo->dwidth, vo->dheight);
- return VO_TRUE;
- case VOCTRL_BORDER:
- if (!p->glctx->border)
- break;
- p->glctx->border(vo);
- resize(vo, vo->dwidth, vo->dheight);
- return VO_TRUE;
- case VOCTRL_GET_PANSCAN:
- return VO_TRUE;
- case VOCTRL_SET_PANSCAN:
- resize(vo, vo->dwidth, vo->dheight);
- return VO_TRUE;
- case VOCTRL_GET_EQUALIZER:
- if (p->is_yuv) {
- struct voctrl_get_equalizer_args *args = data;
- return mp_csp_equalizer_get(&p->video_eq, args->name, args->valueptr)
- >= 0 ? VO_TRUE : VO_NOTIMPL;
- }
- break;
- case VOCTRL_SET_EQUALIZER:
- if (p->is_yuv) {
- struct voctrl_set_equalizer_args *args = data;
- if (mp_csp_equalizer_set(&p->video_eq, args->name, args->value) < 0)
- return VO_NOTIMPL;
- update_yuvconv(vo);
- vo->want_redraw = true;
- return VO_TRUE;
- }
- break;
- case VOCTRL_SET_YUV_COLORSPACE: {
- bool supports_csp = (1 << p->use_yuv) & MASK_NOT_COMBINERS;
- if (vo->config_count && supports_csp) {
- p->colorspace = *(struct mp_csp_details *)data;
- update_yuvconv(vo);
- vo->want_redraw = true;
- }
- return VO_TRUE;
- }
- case VOCTRL_GET_YUV_COLORSPACE:
- *(struct mp_csp_details *)data = p->colorspace;
- return VO_TRUE;
- case VOCTRL_UPDATE_SCREENINFO:
- if (!p->glctx->update_xinerama_info)
- break;
- p->glctx->update_xinerama_info(vo);
- return VO_TRUE;
- case VOCTRL_REDRAW_FRAME:
- do_render(vo);
- return true;
- case VOCTRL_PAUSE:
- if (!p->glctx->pause)
- break;
- p->glctx->pause(vo);
- return VO_TRUE;
- case VOCTRL_RESUME:
- if (!p->glctx->resume)
- break;
- p->glctx->resume(vo);
- return VO_TRUE;
- case VOCTRL_SCREENSHOT: {
- struct voctrl_screenshot_args *args = data;
- if (args->full_window)
- args->out_image = glGetWindowScreenshot(p->gl);
- else
- args->out_image = get_screenshot(vo);
- return true;
- }
- }
- return VO_NOTIMPL;
-}
-
-const struct vo_driver video_out_opengl_old = {
- .is_new = true,
- .info = &(const vo_info_t) {
- "OpenGL",
- "opengl-old",
- "Reimar Doeffinger <Reimar.Doeffinger@gmx.de>",
- ""
- },
- .preinit = preinit,
- .config = config,
- .control = control,
- .draw_slice = draw_slice,
- .draw_osd = draw_osd,
- .flip_page = flip_page,
- .check_events = check_events,
- .uninit = uninit,
-};
diff --git a/libvo/vo_opengl_shaders.glsl b/libvo/vo_opengl_shaders.glsl
deleted file mode 100644
index 1f302889e4..0000000000
--- a/libvo/vo_opengl_shaders.glsl
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * 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.
- */
-
-// Note that this file is not directly passed as shader, but run through some
-// text processing functions, and in fact contains multiple vertex and fragment
-// shaders.
-
-// 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
-
-// Earlier GLSL doesn't support mix() with bvec
-#if __VERSION__ >= 130
-vec3 srgb_compand(vec3 v)
-{
- return mix(1.055 * pow(v, vec3(1.0/2.4)) - vec3(0.055), v * 12.92,
- lessThanEqual(v, vec3(0.0031308)));
-}
-#endif
-
-#!section vertex_all
-
-#if __VERSION__ < 130
-# undef in
-# define in attribute
-# define out varying
-#endif
-
-uniform mat3 transform;
-uniform sampler3D lut_3d;
-
-in vec2 vertex_position;
-in vec4 vertex_color;
-out vec4 color;
-in vec2 vertex_texcoord;
-out vec2 texcoord;
-
-void main() {
- vec3 position = vec3(vertex_position, 1);
-#ifndef FIXED_SCALE
- position = transform * position;
-#endif
- gl_Position = vec4(position, 1);
- color = vertex_color;
-
-#ifdef USE_OSD_LINEAR_CONV
- // If no 3dlut is being used, we need to pull up to linear light for
- // the sRGB function. *IF* 3dlut is used, we do not.
- color.rgb = pow(color.rgb, vec3(2.2));
-#endif
-#ifdef USE_OSD_3DLUT
- color = vec4(texture3D(lut_3d, color.rgb).rgb, color.a);
-#endif
-#ifdef USE_OSD_SRGB
- color.rgb = srgb_compand(color.rgb);
-#endif
-
- texcoord = vertex_texcoord;
-}
-
-#!section frag_osd_libass
-uniform sampler2D textures[3];
-
-in vec2 texcoord;
-in vec4 color;
-DECLARE_FRAGPARMS
-
-void main() {
- out_color = vec4(color.rgb, color.a * texture(textures[0], texcoord).r);
-}
-
-#!section frag_osd_rgba
-uniform sampler2D textures[3];
-
-in vec2 texcoord;
-DECLARE_FRAGPARMS
-
-void main() {
- out_color = texture(textures[0], texcoord);
-}
-
-#!section frag_video
-uniform sampler2D textures[3];
-uniform vec2 textures_size[3];
-uniform sampler1D lut_c_1d;
-uniform sampler1D lut_l_1d;
-uniform sampler2D lut_c_2d;
-uniform sampler2D lut_l_2d;
-uniform sampler3D lut_3d;
-uniform sampler2D dither;
-uniform mat4x3 colormatrix;
-uniform vec3 inv_gamma;
-uniform float conv_gamma;
-uniform float dither_quantization;
-uniform float dither_multiply;
-uniform float filter_param1;
-uniform vec2 dither_size;
-
-in vec2 texcoord;
-DECLARE_FRAGPARMS
-
-vec4 sample_bilinear(sampler2D tex, vec2 texsize, vec2 texcoord) {
- return texture(tex, texcoord);
-}
-
-// Explanation how bicubic scaling with only 4 texel fetches is done:
-// http://www.mate.tue.nl/mate/pdfs/10318.pdf
-// 'Efficient GPU-Based Texture Interpolation using Uniform B-Splines'
-// Explanation why this algorithm normally always blurs, even with unit scaling:
-// http://bigwww.epfl.ch/preprints/ruijters1001p.pdf
-// 'GPU Prefilter for Accurate Cubic B-spline Interpolation'
-vec4 calcweights(float s) {
- vec4 t = vec4(-0.5, 0.1666, 0.3333, -0.3333) * s + vec4(1, 0, -0.5, 0.5);
- t = t * s + vec4(0, 0, -0.5, 0.5);
- t = t * s + vec4(-0.6666, 0, 0.8333, 0.1666);
- vec2 a = vec2(1 / t.z, 1 / t.w);
- t.xy = t.xy * a + vec2(1, 1);
- t.x = t.x + s;
- t.y = t.y - s;
- return t;
-}
-
-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);
- vec4 parmy = calcweights(fcoord.y);
- vec4 cdelta;
- cdelta.xz = parmx.rg * vec2(-pt.x, pt.x);
- cdelta.yw = parmy.rg * vec2(-pt.y, pt.y);
- // first y-interpolation
- vec4 ar = texture(tex, texcoord + cdelta.xy);
- vec4 ag = texture(tex, texcoord + cdelta.xw);
- vec4 ab = mix(ag, ar, parmy.b);
- // second y-interpolation
- vec4 br = texture(tex, texcoord + cdelta.zy);
- vec4 bg = texture(tex, texcoord + cdelta.zw);
- vec4 aa = mix(bg, br, parmy.b);
- // x-interpolation
- return mix(aa, ab, parmx.b);
-}
-
-float[2] weights2(sampler1D lookup, float f) {
- vec4 c = texture1D(lookup, f);
- return float[2](c.r, c.g);
-}
-
-float[4] weights4(sampler1D lookup, float f) {
- vec4 c = texture1D(lookup, f);
- return float[4](c.r, c.g, c.b, c.a);
-}
-
-float[6] weights6(sampler2D lookup, float f) {
- vec4 c1 = texture(lookup, vec2(0.25, f));
- vec4 c2 = texture(lookup, vec2(0.75, f));
- return float[6](c1.r, c1.g, c1.b, c2.r, c2.g, c2.b);
-}
-
-float[8] weights8(sampler2D lookup, float f) {
- vec4 c1 = texture(lookup, vec2(0.25, f));
- vec4 c2 = texture(lookup, vec2(0.75, f));
- return float[8](c1.r, c1.g, c1.b, c1.a, c2.r, c2.g, c2.b, c2.a);
-}
-
-float[12] weights12(sampler2D lookup, float f) {
- vec4 c1 = texture(lookup, vec2(1.0/6.0, f));
- vec4 c2 = texture(lookup, vec2(0.5, f));
- vec4 c3 = texture(lookup, vec2(5.0/6.0, f));
- return float[12](c1.r, c1.g, c1.b, c1.a,
- c2.r, c2.g, c2.b, c2.a,
- c3.r, c3.g, c3.b, c3.a);
-}
-
-float[16] weights16(sampler2D lookup, float f) {
- vec4 c1 = texture(lookup, vec2(0.125, f));
- vec4 c2 = texture(lookup, vec2(0.375, f));
- vec4 c3 = texture(lookup, vec2(0.625, f));
- vec4 c4 = texture(lookup, vec2(0.875, f));
- return float[16](c1.r, c1.g, c1.b, c1.a, c2.r, c2.g, c2.b, c2.a,
- 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; \
- }
-
-CONVOLUTION_SEP_N(convolution_sep2, 2)
-CONVOLUTION_SEP_N(convolution_sep4, 4)
-CONVOLUTION_SEP_N(convolution_sep6, 6)
-CONVOLUTION_SEP_N(convolution_sep8, 8)
-CONVOLUTION_SEP_N(convolution_sep12, 12)
-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, \
- vec2 texcoord) { \
- vec2 pt = (1 / texsize) * dir; \
- float fcoord = dot(fract(texcoord * texsize - 0.5), dir); \
- vec2 base = texcoord - fcoord * pt; \
- return CONV_FUNC(tex, base - pt * (N / 2 - 1), pt, \
- WEIGHTS_FUNC(lookup, fcoord)); \
- }
-
-SAMPLE_CONVOLUTION_SEP_N(sample_convolution_sep2, 2, sampler1D, convolution_sep2, weights2)
-SAMPLE_CONVOLUTION_SEP_N(sample_convolution_sep4, 4, sampler1D, convolution_sep4, weights4)
-SAMPLE_CONVOLUTION_SEP_N(sample_convolution_sep6, 6, sampler2D, convolution_sep6, weights6)
-SAMPLE_CONVOLUTION_SEP_N(sample_convolution_sep8, 8, sampler2D, convolution_sep8, weights8)
-SAMPLE_CONVOLUTION_SEP_N(sample_convolution_sep12, 12, sampler2D, convolution_sep12, weights12)
-SAMPLE_CONVOLUTION_SEP_N(sample_convolution_sep16, 16, sampler2D, convolution_sep16, weights16)
-
-
-#define CONVOLUTION_N(NAME, N) \
- vec4 NAME(sampler2D tex, vec2 texcoord, vec2 pt, float taps_x[N], \
- float taps_y[N]) { \
- vec4 res = vec4(0); \
- for (int y = 0; y < N; y++) { \
- vec4 line = vec4(0); \
- for (int x = 0; x < N; x++) \
- line += taps_x[x] * texture(tex, texcoord + pt * vec2(x, y));\
- res += taps_y[y] * line; \
- } \
- return res; \
- }
-
-CONVOLUTION_N(convolution2, 2)
-CONVOLUTION_N(convolution4, 4)
-CONVOLUTION_N(convolution6, 6)
-CONVOLUTION_N(convolution8, 8)
-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) {\
- vec2 pt = 1 / texsize; \
- vec2 fcoord = fract(texcoord * texsize - 0.5); \
- vec2 base = texcoord - fcoord * pt; \
- return CONV_FUNC(tex, base - pt * (N / 2 - 1), pt, \
- WEIGHTS_FUNC(lookup, fcoord.x), \
- WEIGHTS_FUNC(lookup, fcoord.y)); \
- }
-
-SAMPLE_CONVOLUTION_N(sample_convolution2, 2, sampler1D, convolution2, weights2)
-SAMPLE_CONVOLUTION_N(sample_convolution4, 4, sampler1D, convolution4, weights4)
-SAMPLE_CONVOLUTION_N(sample_convolution6, 6, sampler2D, convolution6, weights6)
-SAMPLE_CONVOLUTION_N(sample_convolution8, 8, sampler2D, convolution8, weights8)
-SAMPLE_CONVOLUTION_N(sample_convolution12, 12, sampler2D, convolution12, weights12)
-SAMPLE_CONVOLUTION_N(sample_convolution16, 16, sampler2D, convolution16, weights16)
-
-
-// Unsharp masking
-vec4 sample_sharpen3(sampler2D tex, vec2 texsize, vec2 texcoord) {
- vec2 pt = 1 / texsize;
- vec2 st = pt * 0.5;
- vec4 p = texture(tex, texcoord);
- vec4 sum = texture(tex, texcoord + st * vec2(+1, +1))
- + texture(tex, texcoord + st * vec2(+1, -1))
- + texture(tex, texcoord + st * vec2(-1, +1))
- + texture(tex, texcoord + st * vec2(-1, -1));
- return p + (p - 0.25 * sum) * filter_param1;
-}
-
-vec4 sample_sharpen5(sampler2D tex, vec2 texsize, vec2 texcoord) {
- vec2 pt = 1 / texsize;
- vec2 st1 = pt * 1.2;
- vec4 p = texture(tex, texcoord);
- vec4 sum1 = texture(tex, texcoord + st1 * vec2(+1, +1))
- + texture(tex, texcoord + st1 * vec2(+1, -1))
- + texture(tex, texcoord + st1 * vec2(-1, +1))
- + texture(tex, texcoord + st1 * vec2(-1, -1));
- vec2 st2 = pt * 1.5;
- vec4 sum2 = texture(tex, texcoord + st2 * vec2(+1, 0))
- + texture(tex, texcoord + st2 * vec2( 0, +1))
- + texture(tex, texcoord + st2 * vec2(-1, 0))
- + texture(tex, texcoord + st2 * vec2( 0, -1));
- vec4 t = p * 0.859375 + sum2 * -0.1171875 + sum1 * -0.09765625;
- return p + t * filter_param1;
-}
-
-void main() {
-#ifdef USE_PLANAR
- 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(textures[0], textures_size[0], texcoord).rgb;
-#endif
-#ifdef USE_GBRP
- color.gbr = color;
-#endif
-#ifdef USE_YGRAY
- // NOTE: actually slightly wrong for 16 bit input video, and completely
- // wrong for 9/10 bit input
- color.gb = vec2(128.0/255.0);
-#endif
-#ifdef USE_COLORMATRIX
- color = mat3(colormatrix) * color + colormatrix[3];
-#endif
-#ifdef USE_LINEAR_CONV
- color = pow(color, vec3(2.2));
-#endif
-#ifdef USE_LINEAR_CONV_INV
- // Convert from linear RGB to gamma RGB before putting it through the 3D-LUT
- // in the final stage.
- color = pow(color, vec3(1.0/2.2));
-#endif
-#ifdef USE_GAMMA_POW
- color = pow(color, inv_gamma);
-#endif
-#ifdef USE_3DLUT
- color = texture3D(lut_3d, color).rgb;
-#endif
-#ifdef USE_SRGB
- color.rgb = srgb_compand(color.rgb);
-#endif
-#ifdef USE_DITHER
- 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);
-}
diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c
deleted file mode 100644
index a523ea5815..0000000000
--- a/libvo/vo_vdpau.c
+++ /dev/null
@@ -1,1718 +0,0 @@
-/*
- * VDPAU video output driver
- *
- * Copyright (C) 2008 NVIDIA
- * Copyright (C) 2009 Uoti Urpala
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/*
- * Actual decoding and presentation are implemented here.
- * All necessary frame information is collected through
- * the "vdpau_render_state" structure after parsing all headers
- * etc. in libavcodec for different codecs.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <limits.h>
-#include <assert.h>
-
-#include <libavutil/common.h>
-#include <libavcodec/vdpau.h>
-
-#include "config.h"
-#include "mp_msg.h"
-#include "options.h"
-#include "talloc.h"
-#include "video_out.h"
-#include "x11_common.h"
-#include "aspect.h"
-#include "csputils.h"
-#include "sub/sub.h"
-#include "m_option.h"
-#include "libmpcodecs/vfcap.h"
-#include "libmpcodecs/mp_image.h"
-#include "osdep/timer.h"
-#include "bitmap_packer.h"
-
-#define WRAP_ADD(x, a, m) ((a) < 0 \
- ? ((x)+(a)+(m) < (m) ? (x)+(a)+(m) : (x)+(a)) \
- : ((x)+(a) < (m) ? (x)+(a) : (x)+(a)-(m)))
-
-#define CHECK_ST_ERROR(message) \
- do { \
- if (vdp_st != VDP_STATUS_OK) { \
- mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] %s: %s\n", \
- message, vdp->get_error_string(vdp_st)); \
- return -1; \
- } \
- } while (0)
-
-#define CHECK_ST_WARNING(message) \
- do { \
- if (vdp_st != VDP_STATUS_OK) \
- mp_msg(MSGT_VO, MSGL_WARN, "[ vdpau] %s: %s\n", \
- message, vdp->get_error_string(vdp_st)); \
- } while (0)
-
-/* number of video and output surfaces */
-#define MAX_OUTPUT_SURFACES 15
-#define MAX_VIDEO_SURFACES 50
-#define NUM_BUFFERED_VIDEO 5
-
-/* Pixelformat used for output surfaces */
-#define OUTPUT_RGBA_FORMAT VDP_RGBA_FORMAT_B8G8R8A8
-
-/*
- * Global variable declaration - VDPAU specific
- */
-
-struct vdp_functions {
-#define VDP_FUNCTION(vdp_type, _, mp_name) vdp_type *mp_name;
-#include "vdpau_template.c"
-#undef VDP_FUNCTION
-};
-
-struct vdpctx {
- struct vdp_functions *vdp;
-
- VdpDevice vdp_device;
- bool is_preempted;
- bool preemption_acked;
- bool preemption_user_notified;
- unsigned int last_preemption_retry_fail;
- VdpGetProcAddress *vdp_get_proc_address;
-
- VdpPresentationQueueTarget flip_target;
- VdpPresentationQueue flip_queue;
- uint64_t last_vdp_time;
- unsigned int last_sync_update;
-
- VdpOutputSurface output_surfaces[MAX_OUTPUT_SURFACES];
- VdpOutputSurface screenshot_surface;
- int num_output_surfaces;
- struct buffered_video_surface {
- VdpVideoSurface surface;
- double pts;
- mp_image_t *mpi;
- } buffered_video[NUM_BUFFERED_VIDEO];
- int deint_queue_pos;
- int output_surface_width, output_surface_height;
-
- VdpVideoMixer video_mixer;
- struct mp_csp_details colorspace;
- int deint;
- int deint_type;
- int deint_counter;
- int pullup;
- float denoise;
- float sharpen;
- int hqscaling;
- int chroma_deint;
- int flip_offset_window;
- int flip_offset_fs;
- int top_field_first;
- bool flip;
-
- VdpDecoder decoder;
- int decoder_max_refs;
-
- VdpRect src_rect_vid;
- VdpRect out_rect_vid;
- struct mp_osd_res osd_rect;
-
- struct vdpau_render_state surface_render[MAX_VIDEO_SURFACES];
- int surface_num;
- int query_surface_num;
- VdpTime recent_vsync_time;
- float user_fps;
- int composite_detect;
- unsigned int vsync_interval;
- uint64_t last_queue_time;
- uint64_t queue_time[MAX_OUTPUT_SURFACES];
- uint64_t last_ideal_time;
- bool dropped_frame;
- uint64_t dropped_time;
- uint32_t vid_width, vid_height;
- uint32_t image_format;
- VdpChromaType vdp_chroma_type;
- VdpYCbCrFormat vdp_pixel_format;
-
- // OSD
- struct osd_bitmap_surface {
- VdpRGBAFormat format;
- VdpBitmapSurface surface;
- uint32_t max_width;
- uint32_t max_height;
- struct bitmap_packer *packer;
- // List of surfaces to be rendered
- struct osd_target {
- VdpRect source;
- VdpRect dest;
- VdpColor color;
- } *targets;
- int targets_size;
- int render_count;
- int bitmap_id;
- int bitmap_pos_id;
- } osd_surfaces[MAX_OSD_PARTS];
-
- // Video equalizer
- struct mp_csp_equalizer video_eq;
-
- // These tell what's been initialized and uninit() should free/uninitialize
- bool mode_switched;
-};
-
-static bool status_ok(struct vo *vo);
-
-static int change_vdptime_sync(struct vdpctx *vc, unsigned int *t)
-{
- struct vdp_functions *vdp = vc->vdp;
- VdpStatus vdp_st;
- VdpTime vdp_time;
- vdp_st = vdp->presentation_queue_get_time(vc->flip_queue, &vdp_time);
- CHECK_ST_ERROR("Error when calling vdp_presentation_queue_get_time");
- unsigned int t1 = *t;
- unsigned int t2 = GetTimer();
- uint64_t old = vc->last_vdp_time + (t1 - vc->last_sync_update) * 1000ULL;
- if (vdp_time > old)
- if (vdp_time > old + (t2 - t1) * 1000ULL)
- vdp_time -= (t2 - t1) * 1000ULL;
- else
- vdp_time = old;
- mp_msg(MSGT_VO, MSGL_DBG2, "[vdpau] adjusting VdpTime offset by %f µs\n",
- (int64_t)(vdp_time - old) / 1000.);
- vc->last_vdp_time = vdp_time;
- vc->last_sync_update = t1;
- *t = t2;
- return 0;
-}
-
-static uint64_t sync_vdptime(struct vo *vo)
-{
- struct vdpctx *vc = vo->priv;
-
- unsigned int t = GetTimer();
- if (t - vc->last_sync_update > 5000000)
- change_vdptime_sync(vc, &t);
- uint64_t now = (t - vc->last_sync_update) * 1000ULL + vc->last_vdp_time;
- // Make sure nanosecond inaccuracies don't make things inconsistent
- now = FFMAX(now, vc->recent_vsync_time);
- return now;
-}
-
-static uint64_t convert_to_vdptime(struct vo *vo, unsigned int t)
-{
- struct vdpctx *vc = vo->priv;
- return (int)(t - vc->last_sync_update) * 1000LL + vc->last_vdp_time;
-}
-
-static int render_video_to_output_surface(struct vo *vo,
- VdpOutputSurface output_surface,
- VdpRect *output_rect)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
- VdpTime dummy;
- VdpStatus vdp_st;
- if (vc->deint_queue_pos < 0)
- return -1;
-
- struct buffered_video_surface *bv = vc->buffered_video;
- int field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
- unsigned int dp = vc->deint_queue_pos;
- // dp==0 means last field of latest frame, 1 earlier field of latest frame,
- // 2 last field of previous frame and so on
- if (vc->deint) {
- field = vc->top_field_first ^ (dp & 1) ?
- VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD:
- VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
- }
- const VdpVideoSurface *past_fields = (const VdpVideoSurface []){
- bv[(dp+1)/2].surface, bv[(dp+2)/2].surface};
- const VdpVideoSurface *future_fields = (const VdpVideoSurface []){
- dp >= 1 ? bv[(dp-1)/2].surface : VDP_INVALID_HANDLE};
- vdp_st = vdp->presentation_queue_block_until_surface_idle(vc->flip_queue,
- output_surface,
- &dummy);
- CHECK_ST_WARNING("Error when calling "
- "vdp_presentation_queue_block_until_surface_idle");
-
- vdp_st = vdp->video_mixer_render(vc->video_mixer, VDP_INVALID_HANDLE,
- 0, field, 2, past_fields,
- bv[dp/2].surface, 1, future_fields,
- &vc->src_rect_vid, output_surface,
- NULL, output_rect, 0, NULL);
- CHECK_ST_WARNING("Error when calling vdp_video_mixer_render");
- return 0;
-}
-
-static int video_to_output_surface(struct vo *vo)
-{
- struct vdpctx *vc = vo->priv;
-
- return render_video_to_output_surface(vo,
- vc->output_surfaces[vc->surface_num],
- &vc->out_rect_vid);
-}
-
-static int next_deint_queue_pos(struct vo *vo, bool eof)
-{
- struct vdpctx *vc = vo->priv;
-
- int dqp = vc->deint_queue_pos;
- if (dqp < 0)
- dqp += 1000;
- else
- dqp = vc->deint >= 2 ? dqp - 1 : dqp - 2 | 1;
- if (dqp < (eof ? 0 : 3))
- return -1;
- return dqp;
-}
-
-static void set_next_frame_info(struct vo *vo, bool eof)
-{
- struct vdpctx *vc = vo->priv;
-
- vo->frame_loaded = false;
- int dqp = next_deint_queue_pos(vo, eof);
- if (dqp < 0)
- return;
- vo->frame_loaded = true;
-
- // Set pts values
- struct buffered_video_surface *bv = vc->buffered_video;
- int idx = dqp >> 1;
- if (idx == 0) { // no future frame/pts available
- vo->next_pts = bv[0].pts;
- vo->next_pts2 = MP_NOPTS_VALUE;
- } else if (!(vc->deint >= 2)) { // no field-splitting deinterlace
- vo->next_pts = bv[idx].pts;
- vo->next_pts2 = bv[idx - 1].pts;
- } else { // deinterlace with separate fields
- double intermediate_pts;
- double diff = bv[idx - 1].pts - bv[idx].pts;
- if (diff > 0 && diff < 0.5)
- intermediate_pts = (bv[idx].pts + bv[idx - 1].pts) / 2;
- else
- intermediate_pts = bv[idx].pts;
- if (dqp & 1) { // first field
- vo->next_pts = bv[idx].pts;
- vo->next_pts2 = intermediate_pts;
- } else {
- vo->next_pts = intermediate_pts;
- vo->next_pts2 = bv[idx - 1].pts;
- }
- }
-}
-
-static void add_new_video_surface(struct vo *vo, VdpVideoSurface surface,
- struct mp_image *reserved_mpi, double pts)
-{
- struct vdpctx *vc = vo->priv;
- struct buffered_video_surface *bv = vc->buffered_video;
-
- if (reserved_mpi)
- reserved_mpi->usage_count++;
- if (bv[NUM_BUFFERED_VIDEO - 1].mpi)
- bv[NUM_BUFFERED_VIDEO - 1].mpi->usage_count--;
-
- for (int i = NUM_BUFFERED_VIDEO - 1; i > 0; i--)
- bv[i] = bv[i - 1];
- bv[0] = (struct buffered_video_surface){
- .mpi = reserved_mpi,
- .surface = surface,
- .pts = pts,
- };
-
- vc->deint_queue_pos = FFMIN(vc->deint_queue_pos + 2,
- NUM_BUFFERED_VIDEO * 2 - 3);
- set_next_frame_info(vo, false);
-}
-
-static void forget_frames(struct vo *vo)
-{
- struct vdpctx *vc = vo->priv;
-
- vc->deint_queue_pos = -1001;
- vc->dropped_frame = false;
- for (int i = 0; i < NUM_BUFFERED_VIDEO; i++) {
- struct buffered_video_surface *p = vc->buffered_video + i;
- if (p->mpi)
- p->mpi->usage_count--;
- *p = (struct buffered_video_surface){
- .surface = VDP_INVALID_HANDLE,
- };
- }
-}
-
-static void resize(struct vo *vo)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
- VdpStatus vdp_st;
- struct mp_rect src_rect;
- struct mp_rect dst_rect;
- vo_get_src_dst_rects(vo, &src_rect, &dst_rect, &vc->osd_rect);
- vc->out_rect_vid.x0 = dst_rect.x0;
- vc->out_rect_vid.x1 = dst_rect.x1;
- vc->out_rect_vid.y0 = dst_rect.y0;
- vc->out_rect_vid.y1 = dst_rect.y1;
- vc->src_rect_vid.x0 = src_rect.x0;
- vc->src_rect_vid.x1 = src_rect.x1;
- vc->src_rect_vid.y0 = vc->flip ? src_rect.y1 : src_rect.y0;
- vc->src_rect_vid.y1 = vc->flip ? src_rect.y0 : src_rect.y1;
-
- int flip_offset_ms = vo_fs ? vc->flip_offset_fs : vc->flip_offset_window;
- vo->flip_queue_offset = flip_offset_ms / 1000.;
-
- if (vc->output_surface_width < vo->dwidth
- || vc->output_surface_height < vo->dheight) {
- if (vc->output_surface_width < vo->dwidth) {
- vc->output_surface_width += vc->output_surface_width >> 1;
- vc->output_surface_width = FFMAX(vc->output_surface_width,
- vo->dwidth);
- }
- if (vc->output_surface_height < vo->dheight) {
- vc->output_surface_height += vc->output_surface_height >> 1;
- vc->output_surface_height = FFMAX(vc->output_surface_height,
- vo->dheight);
- }
- // Creation of output_surfaces
- for (int i = 0; i < vc->num_output_surfaces; i++)
- if (vc->output_surfaces[i] != VDP_INVALID_HANDLE) {
- vdp_st = vdp->output_surface_destroy(vc->output_surfaces[i]);
- CHECK_ST_WARNING("Error when calling "
- "vdp_output_surface_destroy");
- }
- for (int i = 0; i < vc->num_output_surfaces; i++) {
- vdp_st = vdp->output_surface_create(vc->vdp_device,
- OUTPUT_RGBA_FORMAT,
- vc->output_surface_width,
- vc->output_surface_height,
- &vc->output_surfaces[i]);
- CHECK_ST_WARNING("Error when calling vdp_output_surface_create");
- mp_msg(MSGT_VO, MSGL_DBG2, "vdpau out create: %u\n",
- vc->output_surfaces[i]);
- }
- }
- vo->want_redraw = true;
-}
-
-static void preemption_callback(VdpDevice device, void *context)
-{
- struct vdpctx *vc = context;
- vc->is_preempted = true;
- vc->preemption_acked = false;
-}
-
-/* Initialize vdp_get_proc_address, called from preinit() */
-static int win_x11_init_vdpau_procs(struct vo *vo)
-{
- struct vo_x11_state *x11 = vo->x11;
- struct vdpctx *vc = vo->priv;
- if (vc->vdp) // reinitialization after preemption
- memset(vc->vdp, 0, sizeof(*vc->vdp));
- else
- vc->vdp = talloc_zero(vc, struct vdp_functions);
- struct vdp_functions *vdp = vc->vdp;
- VdpStatus vdp_st;
-
- struct vdp_function {
- const int id;
- int offset;
- };
-
- const struct vdp_function *dsc;
-
- static const struct vdp_function vdp_func[] = {
-#define VDP_FUNCTION(_, macro_name, mp_name) {macro_name, offsetof(struct vdp_functions, mp_name)},
-#include "vdpau_template.c"
-#undef VDP_FUNCTION
- {0, -1}
- };
-
- vdp_st = vdp_device_create_x11(x11->display, x11->screen, &vc->vdp_device,
- &vc->vdp_get_proc_address);
- if (vdp_st != VDP_STATUS_OK) {
- if (vc->is_preempted)
- mp_msg(MSGT_VO, MSGL_DBG2, "[vdpau] Error calling "
- "vdp_device_create_x11 while preempted: %d\n", vdp_st);
- else
- mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] Error when calling "
- "vdp_device_create_x11: %d\n", vdp_st);
- return -1;
- }
-
- vdp->get_error_string = NULL;
- for (dsc = vdp_func; dsc->offset >= 0; dsc++) {
- vdp_st = vc->vdp_get_proc_address(vc->vdp_device, dsc->id,
- (void **)((char *)vdp + dsc->offset));
- if (vdp_st != VDP_STATUS_OK) {
- mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] Error when calling "
- "vdp_get_proc_address(function id %d): %s\n", dsc->id,
- vdp->get_error_string ? vdp->get_error_string(vdp_st) : "?");
- return -1;
- }
- }
- vdp_st = vdp->preemption_callback_register(vc->vdp_device,
- preemption_callback, vc);
- return 0;
-}
-
-static int win_x11_init_vdpau_flip_queue(struct vo *vo)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
- struct vo_x11_state *x11 = vo->x11;
- VdpStatus vdp_st;
-
- if (vc->flip_target == VDP_INVALID_HANDLE) {
- vdp_st = vdp->presentation_queue_target_create_x11(vc->vdp_device,
- x11->window,
- &vc->flip_target);
- CHECK_ST_ERROR("Error when calling "
- "vdp_presentation_queue_target_create_x11");
- }
-
- /* Emperically this seems to be the first call which fails when we
- * try to reinit after preemption while the user is still switched
- * from X to a virtual terminal (creating the vdp_device initially
- * succeeds, as does creating the flip_target above). This is
- * probably not guaranteed behavior, but we'll assume it as a simple
- * way to reduce warnings while trying to recover from preemption.
- */
- if (vc->flip_queue == VDP_INVALID_HANDLE) {
- vdp_st = vdp->presentation_queue_create(vc->vdp_device, vc->flip_target,
- &vc->flip_queue);
- if (vc->is_preempted && vdp_st != VDP_STATUS_OK) {
- mp_msg(MSGT_VO, MSGL_DBG2, "[vdpau] Failed to create flip queue "
- "while preempted: %s\n", vdp->get_error_string(vdp_st));
- return -1;
- } else
- CHECK_ST_ERROR("Error when calling vdp_presentation_queue_create");
- }
-
- VdpTime vdp_time;
- vdp_st = vdp->presentation_queue_get_time(vc->flip_queue, &vdp_time);
- CHECK_ST_ERROR("Error when calling vdp_presentation_queue_get_time");
- vc->last_vdp_time = vdp_time;
- vc->last_sync_update = GetTimer();
-
- vc->vsync_interval = 1;
- if (vc->composite_detect && vo_x11_screen_is_composited(vo)) {
- mp_msg(MSGT_VO, MSGL_INFO, "[vdpau] Compositing window manager "
- "detected. Assuming timing info is inaccurate.\n");
- } else if (vc->user_fps > 0) {
- vc->vsync_interval = 1e9 / vc->user_fps;
- mp_msg(MSGT_VO, MSGL_INFO, "[vdpau] Assuming user-specified display "
- "refresh rate of %.3f Hz.\n", vc->user_fps);
- } else if (vc->user_fps == 0) {
-#ifdef CONFIG_XF86VM
- double fps = vo_vm_get_fps(vo);
- if (!fps)
- mp_msg(MSGT_VO, MSGL_WARN, "[vdpau] Failed to get display FPS\n");
- else {
- vc->vsync_interval = 1e9 / fps;
- // This is verbose, but I'm not yet sure how common wrong values are
- mp_msg(MSGT_VO, MSGL_INFO,
- "[vdpau] Got display refresh rate %.3f Hz.\n"
- "[vdpau] If that value looks wrong give the "
- "-vo vdpau:fps=X suboption manually.\n", fps);
- }
-#else
- mp_msg(MSGT_VO, MSGL_INFO, "[vdpau] This binary has been compiled "
- "without XF86VidMode support.\n");
- mp_msg(MSGT_VO, MSGL_INFO, "[vdpau] Can't use vsync-aware timing "
- "without manually provided -vo vdpau:fps=X suboption.\n");
-#endif
- } else
- mp_msg(MSGT_VO, MSGL_V, "[vdpau] framedrop/timing logic disabled by "
- "user.\n");
-
- return 0;
-}
-
-static int set_video_attribute(struct vdpctx *vc, VdpVideoMixerAttribute attr,
- const void *value, char *attr_name)
-{
- struct vdp_functions *vdp = vc->vdp;
- VdpStatus vdp_st;
-
- vdp_st = vdp->video_mixer_set_attribute_values(vc->video_mixer, 1, &attr,
- &value);
- if (vdp_st != VDP_STATUS_OK) {
- mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] Error setting video mixer "
- "attribute %s: %s\n", attr_name, vdp->get_error_string(vdp_st));
- return -1;
- }
- return 0;
-}
-
-static void update_csc_matrix(struct vo *vo)
-{
- struct vdpctx *vc = vo->priv;
-
- mp_msg(MSGT_VO, MSGL_V, "[vdpau] Updating CSC matrix\n");
-
- // VdpCSCMatrix happens to be compatible with mplayer's CSC matrix type
- // both are float[3][4]
- VdpCSCMatrix matrix;
-
- struct mp_csp_params cparams = {
- .colorspace = vc->colorspace, .input_bits = 8, .texture_bits = 8 };
- mp_csp_copy_equalizer_values(&cparams, &vc->video_eq);
- mp_get_yuv2rgb_coeffs(&cparams, matrix);
-
- set_video_attribute(vc, VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX,
- &matrix, "CSC matrix");
-}
-
-#define SET_VIDEO_ATTR(attr_name, attr_type, value) set_video_attribute(vc, \
- VDP_VIDEO_MIXER_ATTRIBUTE_ ## attr_name, &(attr_type){value},\
- # attr_name)
-static int create_vdp_mixer(struct vo *vo, VdpChromaType vdp_chroma_type)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
-#define VDP_NUM_MIXER_PARAMETER 3
-#define MAX_NUM_FEATURES 6
- int i;
- VdpStatus vdp_st;
-
- if (vc->video_mixer != VDP_INVALID_HANDLE)
- return 0;
-
- int feature_count = 0;
- VdpVideoMixerFeature features[MAX_NUM_FEATURES];
- VdpBool feature_enables[MAX_NUM_FEATURES];
- static const VdpVideoMixerParameter parameters[VDP_NUM_MIXER_PARAMETER] = {
- VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH,
- VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT,
- VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE,
- };
- const void *const parameter_values[VDP_NUM_MIXER_PARAMETER] = {
- &vc->vid_width,
- &vc->vid_height,
- &vdp_chroma_type,
- };
- features[feature_count++] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL;
- if (vc->deint_type == 4)
- features[feature_count++] =
- VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL;
- if (vc->pullup)
- features[feature_count++] = VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE;
- if (vc->denoise)
- features[feature_count++] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION;
- if (vc->sharpen)
- features[feature_count++] = VDP_VIDEO_MIXER_FEATURE_SHARPNESS;
- if (vc->hqscaling) {
- VdpVideoMixerFeature hqscaling_feature =
- VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + vc->hqscaling-1;
- VdpBool hqscaling_available;
- vdp_st = vdp->video_mixer_query_feature_support(vc->vdp_device,
- hqscaling_feature,
- &hqscaling_available);
- CHECK_ST_ERROR("Error when calling video_mixer_query_feature_support");
- if (hqscaling_available)
- features[feature_count++] = hqscaling_feature;
- else
- mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] Your hardware or VDPAU "
- "library does not support requested hqscaling.\n");
- }
-
- vdp_st = vdp->video_mixer_create(vc->vdp_device, feature_count, features,
- VDP_NUM_MIXER_PARAMETER,
- parameters, parameter_values,
- &vc->video_mixer);
- CHECK_ST_ERROR("Error when calling vdp_video_mixer_create");
-
- for (i = 0; i < feature_count; i++)
- feature_enables[i] = VDP_TRUE;
- if (vc->deint < 3)
- feature_enables[0] = VDP_FALSE;
- if (vc->deint_type == 4 && vc->deint < 4)
- feature_enables[1] = VDP_FALSE;
- if (feature_count) {
- vdp_st = vdp->video_mixer_set_feature_enables(vc->video_mixer,
- feature_count, features,
- feature_enables);
- CHECK_ST_WARNING("Error calling vdp_video_mixer_set_feature_enables");
- }
- if (vc->denoise)
- SET_VIDEO_ATTR(NOISE_REDUCTION_LEVEL, float, vc->denoise);
- if (vc->sharpen)
- SET_VIDEO_ATTR(SHARPNESS_LEVEL, float, vc->sharpen);
- if (!vc->chroma_deint)
- SET_VIDEO_ATTR(SKIP_CHROMA_DEINTERLACE, uint8_t, 1);
-
- update_csc_matrix(vo);
- return 0;
-}
-
-// Free everything specific to a certain video file
-static void free_video_specific(struct vo *vo)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
- int i;
- VdpStatus vdp_st;
-
- if (vc->decoder != VDP_INVALID_HANDLE)
- vdp->decoder_destroy(vc->decoder);
- vc->decoder = VDP_INVALID_HANDLE;
- vc->decoder_max_refs = -1;
-
- forget_frames(vo);
-
- for (i = 0; i < MAX_VIDEO_SURFACES; i++) {
- if (vc->surface_render[i].surface != VDP_INVALID_HANDLE) {
- vdp_st = vdp->video_surface_destroy(vc->surface_render[i].surface);
- CHECK_ST_WARNING("Error when calling vdp_video_surface_destroy");
- }
- vc->surface_render[i].surface = VDP_INVALID_HANDLE;
- }
-
- if (vc->video_mixer != VDP_INVALID_HANDLE) {
- vdp_st = vdp->video_mixer_destroy(vc->video_mixer);
- CHECK_ST_WARNING("Error when calling vdp_video_mixer_destroy");
- }
- vc->video_mixer = VDP_INVALID_HANDLE;
-
- if (vc->screenshot_surface != VDP_INVALID_HANDLE) {
- vdp_st = vdp->output_surface_destroy(vc->screenshot_surface);
- CHECK_ST_WARNING("Error when calling vdp_output_surface_destroy");
- }
- vc->screenshot_surface = VDP_INVALID_HANDLE;
-}
-
-static int create_vdp_decoder(struct vo *vo, int max_refs)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
- VdpStatus vdp_st;
- VdpDecoderProfile vdp_decoder_profile;
- if (vc->decoder != VDP_INVALID_HANDLE)
- vdp->decoder_destroy(vc->decoder);
- switch (vc->image_format) {
- case IMGFMT_VDPAU_MPEG1:
- vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG1;
- break;
- case IMGFMT_VDPAU_MPEG2:
- vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG2_MAIN;
- break;
- case IMGFMT_VDPAU_H264:
- vdp_decoder_profile = VDP_DECODER_PROFILE_H264_HIGH;
- mp_msg(MSGT_VO, MSGL_V, "[vdpau] Creating H264 hardware decoder "
- "for %d reference frames.\n", max_refs);
- break;
- case IMGFMT_VDPAU_WMV3:
- vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_MAIN;
- break;
- case IMGFMT_VDPAU_VC1:
- vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_ADVANCED;
- break;
- case IMGFMT_VDPAU_MPEG4:
- vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP;
- break;
- default:
- mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] Unknown image format!\n");
- goto fail;
- }
- vdp_st = vdp->decoder_create(vc->vdp_device, vdp_decoder_profile,
- vc->vid_width, vc->vid_height, max_refs,
- &vc->decoder);
- CHECK_ST_WARNING("Failed creating VDPAU decoder");
- if (vdp_st != VDP_STATUS_OK) {
- fail:
- vc->decoder = VDP_INVALID_HANDLE;
- vc->decoder_max_refs = 0;
- return 0;
- }
- vc->decoder_max_refs = max_refs;
- return 1;
-}
-
-static int initialize_vdpau_objects(struct vo *vo)
-{
- struct vdpctx *vc = vo->priv;
-
- vc->vdp_chroma_type = VDP_CHROMA_TYPE_420;
- switch (vc->image_format) {
- case IMGFMT_YV12:
- case IMGFMT_I420:
- case IMGFMT_IYUV:
- vc->vdp_pixel_format = VDP_YCBCR_FORMAT_YV12;
- break;
- case IMGFMT_NV12:
- vc->vdp_pixel_format = VDP_YCBCR_FORMAT_NV12;
- break;
- case IMGFMT_YUY2:
- vc->vdp_pixel_format = VDP_YCBCR_FORMAT_YUYV;
- vc->vdp_chroma_type = VDP_CHROMA_TYPE_422;
- break;
- case IMGFMT_UYVY:
- vc->vdp_pixel_format = VDP_YCBCR_FORMAT_UYVY;
- vc->vdp_chroma_type = VDP_CHROMA_TYPE_422;
- }
- if (win_x11_init_vdpau_flip_queue(vo) < 0)
- return -1;
-
- if (create_vdp_mixer(vo, vc->vdp_chroma_type) < 0)
- return -1;
-
- forget_frames(vo);
- resize(vo);
- return 0;
-}
-
-static void mark_vdpau_objects_uninitialized(struct vo *vo)
-{
- struct vdpctx *vc = vo->priv;
-
- vc->decoder = VDP_INVALID_HANDLE;
- for (int i = 0; i < MAX_VIDEO_SURFACES; i++)
- vc->surface_render[i].surface = VDP_INVALID_HANDLE;
- forget_frames(vo);
- vc->video_mixer = VDP_INVALID_HANDLE;
- vc->flip_queue = VDP_INVALID_HANDLE;
- vc->flip_target = VDP_INVALID_HANDLE;
- for (int i = 0; i < MAX_OUTPUT_SURFACES; i++)
- vc->output_surfaces[i] = VDP_INVALID_HANDLE;
- vc->screenshot_surface = VDP_INVALID_HANDLE;
- vc->vdp_device = VDP_INVALID_HANDLE;
- for (int i = 0; i < MAX_OSD_PARTS; i++) {
- struct osd_bitmap_surface *sfc = &vc->osd_surfaces[i];
- talloc_free(sfc->packer);
- sfc->bitmap_id = sfc->bitmap_pos_id = 0;
- *sfc = (struct osd_bitmap_surface){
- .surface = VDP_INVALID_HANDLE,
- };
- }
- vc->output_surface_width = vc->output_surface_height = -1;
-}
-
-static int handle_preemption(struct vo *vo)
-{
- struct vdpctx *vc = vo->priv;
-
- if (!vc->is_preempted)
- return 0;
- if (!vc->preemption_acked)
- mark_vdpau_objects_uninitialized(vo);
- vc->preemption_acked = true;
- if (!vc->preemption_user_notified) {
- mp_tmsg(MSGT_VO, MSGL_ERR, "[vdpau] Got display preemption notice! "
- "Will attempt to recover.\n");
- vc->preemption_user_notified = true;
- }
- /* Trying to initialize seems to be quite slow, so only try once a
- * second to avoid using 100% CPU. */
- if (vc->last_preemption_retry_fail
- && GetTimerMS() - vc->last_preemption_retry_fail < 1000)
- return -1;
- if (win_x11_init_vdpau_procs(vo) < 0 || initialize_vdpau_objects(vo) < 0) {
- vc->last_preemption_retry_fail = GetTimerMS() | 1;
- return -1;
- }
- vc->last_preemption_retry_fail = 0;
- vc->is_preempted = false;
- vc->preemption_user_notified = false;
- mp_tmsg(MSGT_VO, MSGL_INFO, "[vdpau] Recovered from display preemption.\n");
- return 1;
-}
-
-/*
- * connect to X server, create and map window, initialize all
- * VDPAU objects, create different surfaces etc.
- */
-static int config(struct vo *vo, uint32_t width, uint32_t height,
- uint32_t d_width, uint32_t d_height, uint32_t flags,
- uint32_t format)
-{
- struct vdpctx *vc = vo->priv;
- struct vo_x11_state *x11 = vo->x11;
- XVisualInfo vinfo;
- XSetWindowAttributes xswa;
- XWindowAttributes attribs;
- unsigned long xswamask;
- int depth;
-
-#ifdef CONFIG_XF86VM
- int vm = flags & VOFLAG_MODESWITCHING;
-#endif
-
- if (handle_preemption(vo) < 0)
- return -1;
-
- vc->flip = flags & VOFLAG_FLIPPING;
- vc->image_format = format;
- vc->vid_width = width;
- vc->vid_height = height;
-
- free_video_specific(vo);
- if (IMGFMT_IS_VDPAU(vc->image_format) && !create_vdp_decoder(vo, 2))
- return -1;
-
-#ifdef CONFIG_XF86VM
- if (vm) {
- vo_vm_switch(vo);
- vc->mode_switched = true;
- }
-#endif
- XGetWindowAttributes(x11->display, DefaultRootWindow(x11->display),
- &attribs);
- depth = attribs.depth;
- if (depth != 15 && depth != 16 && depth != 24 && depth != 32)
- depth = 24;
- XMatchVisualInfo(x11->display, x11->screen, depth, TrueColor, &vinfo);
-
- xswa.background_pixel = 0;
- xswa.border_pixel = 0;
- /* Do not use CWBackPixel: It leads to VDPAU errors after
- * aspect ratio changes. */
- xswamask = CWBorderPixel;
-
- vo_x11_create_vo_window(vo, &vinfo, vo->dx, vo->dy, d_width, d_height,
- flags, CopyFromParent, "vdpau");
- XChangeWindowAttributes(x11->display, x11->window, xswamask, &xswa);
-
-#ifdef CONFIG_XF86VM
- if (vm) {
- /* Grab the mouse pointer in our window */
- if (vo_grabpointer)
- XGrabPointer(x11->display, x11->window, True, 0,
- GrabModeAsync, GrabModeAsync,
- x11->window, None, CurrentTime);
- XSetInputFocus(x11->display, x11->window, RevertToNone, CurrentTime);
- }
-#endif
-
- if (initialize_vdpau_objects(vo) < 0)
- return -1;
-
- return 0;
-}
-
-static void check_events(struct vo *vo)
-{
- if (handle_preemption(vo) < 0)
- return;
-
- int e = vo_x11_check_events(vo);
-
- if (e & VO_EVENT_RESIZE)
- resize(vo);
- else if (e & VO_EVENT_EXPOSE) {
- vo->want_redraw = true;
- }
-}
-
-static struct bitmap_packer *make_packer(struct vo *vo, VdpRGBAFormat format)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
-
- struct bitmap_packer *packer = talloc_zero(vo, struct bitmap_packer);
- uint32_t w_max = 0, h_max = 0;
- VdpStatus vdp_st = vdp->
- bitmap_surface_query_capabilities(vc->vdp_device, format,
- &(VdpBool){0}, &w_max, &h_max);
- CHECK_ST_WARNING("Query to get max OSD surface size failed");
- packer->w_max = w_max;
- packer->h_max = h_max;
- return packer;
-}
-
-static void draw_osd_part(struct vo *vo, int index)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
- VdpStatus vdp_st;
- struct osd_bitmap_surface *sfc = &vc->osd_surfaces[index];
- VdpOutputSurface output_surface = vc->output_surfaces[vc->surface_num];
- int i;
-
- VdpOutputSurfaceRenderBlendState blend_state = {
- .struct_version = VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION,
- .blend_factor_source_color =
- VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA,
- .blend_factor_source_alpha =
- VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE,
- .blend_factor_destination_color =
- VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
- .blend_factor_destination_alpha =
- VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA,
- .blend_equation_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD,
- .blend_equation_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD,
- };
-
- VdpOutputSurfaceRenderBlendState blend_state_premultiplied = blend_state;
- blend_state_premultiplied.blend_factor_source_color =
- VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE;
-
- for (i = 0; i < sfc->render_count; i++) {
- VdpOutputSurfaceRenderBlendState *blend = &blend_state;
- if (sfc->format == VDP_RGBA_FORMAT_B8G8R8A8)
- blend = &blend_state_premultiplied;
- vdp_st = vdp->
- output_surface_render_bitmap_surface(output_surface,
- &sfc->targets[i].dest,
- sfc->surface,
- &sfc->targets[i].source,
- &sfc->targets[i].color,
- blend,
- VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
- CHECK_ST_WARNING("OSD: Error when rendering");
- }
-}
-
-static void generate_osd_part(struct vo *vo, struct sub_bitmaps *imgs)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
- VdpStatus vdp_st;
- struct osd_bitmap_surface *sfc = &vc->osd_surfaces[imgs->render_index];
- bool need_upload = false;
-
- if (imgs->bitmap_pos_id == sfc->bitmap_pos_id)
- return; // Nothing changed and we still have the old data
-
- sfc->render_count = 0;
-
- if (imgs->format == SUBBITMAP_EMPTY || imgs->num_parts == 0)
- return;
-
- if (imgs->bitmap_id == sfc->bitmap_id)
- goto osd_skip_upload;
-
- need_upload = true;
- VdpRGBAFormat format;
- int format_size;
- switch (imgs->format) {
- case SUBBITMAP_LIBASS:
- format = VDP_RGBA_FORMAT_A8;
- format_size = 1;
- break;
- case SUBBITMAP_RGBA:
- format = VDP_RGBA_FORMAT_B8G8R8A8;
- format_size = 4;
- break;
- default:
- abort();
- };
- if (sfc->format != format) {
- talloc_free(sfc->packer);
- sfc->packer = NULL;
- };
- sfc->format = format;
- if (!sfc->packer)
- sfc->packer = make_packer(vo, format);
- sfc->packer->padding = imgs->scaled; // assume 2x2 filter on scaling
- int r = packer_pack_from_subbitmaps(sfc->packer, imgs);
- if (r < 0) {
- mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] OSD bitmaps do not fit on "
- "a surface with the maximum supported size\n");
- return;
- } else if (r == 1) {
- if (sfc->surface != VDP_INVALID_HANDLE) {
- vdp_st = vdp->bitmap_surface_destroy(sfc->surface);
- CHECK_ST_WARNING("Error when calling vdp_bitmap_surface_destroy");
- }
- mp_msg(MSGT_VO, MSGL_V, "[vdpau] Allocating a %dx%d surface for "
- "OSD bitmaps.\n", sfc->packer->w, sfc->packer->h);
- vdp_st = vdp->bitmap_surface_create(vc->vdp_device, format,
- sfc->packer->w, sfc->packer->h,
- true, &sfc->surface);
- if (vdp_st != VDP_STATUS_OK)
- sfc->surface = VDP_INVALID_HANDLE;
- CHECK_ST_WARNING("OSD: error when creating surface");
- }
- if (imgs->scaled) {
- char zeros[sfc->packer->used_width * format_size];
- memset(zeros, 0, sizeof(zeros));
- vdp_st = vdp->bitmap_surface_put_bits_native(sfc->surface,
- &(const void *){zeros}, &(uint32_t){0},
- &(VdpRect){0, 0, sfc->packer->used_width,
- sfc->packer->used_height});
- }
-
-osd_skip_upload:
- if (sfc->surface == VDP_INVALID_HANDLE)
- return;
- if (sfc->packer->count > sfc->targets_size) {
- talloc_free(sfc->targets);
- sfc->targets_size = sfc->packer->count;
- sfc->targets = talloc_size(vc, sfc->targets_size
- * sizeof(*sfc->targets));
- }
-
- for (int i = 0 ;i < sfc->packer->count; i++) {
- struct sub_bitmap *b = &imgs->parts[i];
- struct osd_target *target = sfc->targets + sfc->render_count;
- int x = sfc->packer->result[i].x;
- int y = sfc->packer->result[i].y;
- target->source = (VdpRect){x, y, x + b->w, y + b->h};
- target->dest = (VdpRect){b->x, b->y, b->x + b->dw, b->y + b->dh};
- target->color = (VdpColor){1, 1, 1, 1};
- if (imgs->format == SUBBITMAP_LIBASS) {
- uint32_t color = b->libass.color;
- target->color.alpha = 1.0 - ((color >> 0) & 0xff) / 255.0;
- target->color.blue = ((color >> 8) & 0xff) / 255.0;
- target->color.green = ((color >> 16) & 0xff) / 255.0;
- target->color.red = ((color >> 24) & 0xff) / 255.0;
- }
- if (need_upload) {
- vdp_st = vdp->
- bitmap_surface_put_bits_native(sfc->surface,
- &(const void *){b->bitmap},
- &(uint32_t){b->stride},
- &target->source);
- CHECK_ST_WARNING("OSD: putbits failed");
- }
- sfc->render_count++;
- }
-
- sfc->bitmap_id = imgs->bitmap_id;
- sfc->bitmap_pos_id = imgs->bitmap_pos_id;
-}
-
-static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs)
-{
- struct vo *vo = ctx;
- generate_osd_part(vo, imgs);
- draw_osd_part(vo, imgs->render_index);
-}
-
-static void draw_osd(struct vo *vo, struct osd_state *osd)
-{
- struct vdpctx *vc = vo->priv;
-
- if (!status_ok(vo))
- return;
-
- static const bool formats[SUBBITMAP_COUNT] = {
- [SUBBITMAP_LIBASS] = true,
- [SUBBITMAP_RGBA] = true,
- };
-
- osd_draw(osd, vc->osd_rect, osd->vo_pts, 0, formats, draw_osd_cb, vo);
-}
-
-static int update_presentation_queue_status(struct vo *vo)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
- VdpStatus vdp_st;
-
- while (vc->query_surface_num != vc->surface_num) {
- VdpTime vtime;
- VdpPresentationQueueStatus status;
- VdpOutputSurface surface = vc->output_surfaces[vc->query_surface_num];
- vdp_st = vdp->presentation_queue_query_surface_status(vc->flip_queue,
- surface,
- &status, &vtime);
- CHECK_ST_WARNING("Error calling "
- "presentation_queue_query_surface_status");
- if (status == VDP_PRESENTATION_QUEUE_STATUS_QUEUED)
- break;
- if (vc->vsync_interval > 1) {
- uint64_t qtime = vc->queue_time[vc->query_surface_num];
- if (vtime < qtime + vc->vsync_interval / 2)
- mp_msg(MSGT_VO, MSGL_V, "[vdpau] Frame shown too early\n");
- if (vtime > qtime + vc->vsync_interval)
- mp_msg(MSGT_VO, MSGL_V, "[vdpau] Frame shown late\n");
- }
- vc->query_surface_num = WRAP_ADD(vc->query_surface_num, 1,
- vc->num_output_surfaces);
- vc->recent_vsync_time = vtime;
- }
- int num_queued = WRAP_ADD(vc->surface_num, -vc->query_surface_num,
- vc->num_output_surfaces);
- mp_msg(MSGT_VO, MSGL_DBG3, "[vdpau] Queued surface count (before add): "
- "%d\n", num_queued);
- return num_queued;
-}
-
-static inline uint64_t prev_vs2(struct vdpctx *vc, uint64_t ts, int shift)
-{
- uint64_t offset = ts - vc->recent_vsync_time;
- // Fix negative values for 1<<shift vsyncs before vc->recent_vsync_time
- offset += (uint64_t)vc->vsync_interval << shift;
- offset %= vc->vsync_interval;
- return ts - offset;
-}
-
-static void flip_page_timed(struct vo *vo, unsigned int pts_us, int duration)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
- VdpStatus vdp_st;
- uint32_t vsync_interval = vc->vsync_interval;
-
- if (handle_preemption(vo) < 0)
- return;
-
- if (duration > INT_MAX / 1000)
- duration = -1;
- else
- duration *= 1000;
-
- if (vc->vsync_interval == 1)
- duration = -1; // Make sure drop logic is disabled
-
- uint64_t now = sync_vdptime(vo);
- uint64_t pts = pts_us ? convert_to_vdptime(vo, pts_us) : now;
- uint64_t ideal_pts = pts;
- uint64_t npts = duration >= 0 ? pts + duration : UINT64_MAX;
-
-#define PREV_VS2(ts, shift) prev_vs2(vc, ts, shift)
- // Only gives accurate results for ts >= vc->recent_vsync_time
-#define PREV_VSYNC(ts) PREV_VS2(ts, 0)
-
- /* We hope to be here at least one vsync before the frame should be shown.
- * If we are running late then don't drop the frame unless there is
- * already one queued for the next vsync; even if we _hope_ to show the
- * next frame soon enough to mean this one should be dropped we might
- * not make the target time in reality. Without this check we could drop
- * every frame, freezing the display completely if video lags behind.
- */
- if (now > PREV_VSYNC(FFMAX(pts, vc->last_queue_time + vsync_interval)))
- npts = UINT64_MAX;
-
- /* Allow flipping a frame at a vsync if its presentation time is a
- * bit after that vsync and the change makes the flip time delta
- * from previous frame better match the target timestamp delta.
- * This avoids instability with frame timestamps falling near vsyncs.
- * For example if the frame timestamps were (with vsyncs at
- * integer values) 0.01, 1.99, 4.01, 5.99, 8.01, ... then
- * straightforward timing at next vsync would flip the frames at
- * 1, 2, 5, 6, 9; this changes it to 1, 2, 4, 6, 8 and so on with
- * regular 2-vsync intervals.
- *
- * Also allow moving the frame forward if it looks like we dropped
- * the previous frame incorrectly (now that we know better after
- * having final exact timestamp information for this frame) and
- * there would unnecessarily be a vsync without a frame change.
- */
- uint64_t vsync = PREV_VSYNC(pts);
- if (pts < vsync + vsync_interval / 4
- && (vsync - PREV_VS2(vc->last_queue_time, 16)
- > pts - vc->last_ideal_time + vsync_interval / 2
- || vc->dropped_frame && vsync > vc->dropped_time))
- pts -= vsync_interval / 2;
-
- vc->dropped_frame = true; // changed at end if false
- vc->dropped_time = ideal_pts;
-
- pts = FFMAX(pts, vc->last_queue_time + vsync_interval);
- pts = FFMAX(pts, now);
- if (npts < PREV_VSYNC(pts) + vsync_interval)
- return;
-
- int num_flips = update_presentation_queue_status(vo);
- vsync = vc->recent_vsync_time + num_flips * vc->vsync_interval;
- now = sync_vdptime(vo);
- pts = FFMAX(pts, now);
- pts = FFMAX(pts, vsync + (vsync_interval >> 2));
- vsync = PREV_VSYNC(pts);
- if (npts < vsync + vsync_interval)
- return;
- pts = vsync + (vsync_interval >> 2);
- vdp_st =
- vdp->presentation_queue_display(vc->flip_queue,
- vc->output_surfaces[vc->surface_num],
- vo->dwidth, vo->dheight, pts);
- CHECK_ST_WARNING("Error when calling vdp_presentation_queue_display");
-
- vc->last_queue_time = pts;
- vc->queue_time[vc->surface_num] = pts;
- vc->last_ideal_time = ideal_pts;
- vc->dropped_frame = false;
- vc->surface_num = WRAP_ADD(vc->surface_num, 1, vc->num_output_surfaces);
-}
-
-static int draw_slice(struct vo *vo, uint8_t *image[], int stride[], int w,
- int h, int x, int y)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
- VdpStatus vdp_st;
-
- if (handle_preemption(vo) < 0)
- return VO_TRUE;
-
- struct vdpau_render_state *rndr = (struct vdpau_render_state *)image[0];
- int max_refs = vc->image_format == IMGFMT_VDPAU_H264 ?
- rndr->info.h264.num_ref_frames : 2;
- if (!IMGFMT_IS_VDPAU(vc->image_format))
- return VO_FALSE;
- if ((vc->decoder == VDP_INVALID_HANDLE || vc->decoder_max_refs < max_refs)
- && !create_vdp_decoder(vo, max_refs))
- return VO_FALSE;
-
- vdp_st = vdp->decoder_render(vc->decoder, rndr->surface,
- (void *)&rndr->info,
- rndr->bitstream_buffers_used,
- rndr->bitstream_buffers);
- CHECK_ST_WARNING("Failed VDPAU decoder rendering");
- return VO_TRUE;
-}
-
-
-static struct vdpau_render_state *get_surface(struct vo *vo, int number)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
-
- if (number >= MAX_VIDEO_SURFACES)
- return NULL;
- if (vc->surface_render[number].surface == VDP_INVALID_HANDLE
- && !vc->is_preempted) {
- VdpStatus vdp_st;
- vdp_st = vdp->video_surface_create(vc->vdp_device, vc->vdp_chroma_type,
- vc->vid_width, vc->vid_height,
- &vc->surface_render[number].surface);
- CHECK_ST_WARNING("Error when calling vdp_video_surface_create");
- }
- mp_msg(MSGT_VO, MSGL_DBG3, "vdpau vid create: %u\n",
- vc->surface_render[number].surface);
- return &vc->surface_render[number];
-}
-
-static void draw_image(struct vo *vo, mp_image_t *mpi, double pts)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
- struct mp_image *reserved_mpi = NULL;
- struct vdpau_render_state *rndr;
-
- if (IMGFMT_IS_VDPAU(vc->image_format)) {
- rndr = mpi->priv;
- reserved_mpi = mpi;
- } else if (!(mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)) {
- rndr = get_surface(vo, vc->deint_counter);
- vc->deint_counter = WRAP_ADD(vc->deint_counter, 1, NUM_BUFFERED_VIDEO);
- if (handle_preemption(vo) >= 0) {
- VdpStatus vdp_st;
- const void *destdata[3] = {mpi->planes[0], mpi->planes[2],
- mpi->planes[1]};
- if (vc->image_format == IMGFMT_NV12)
- destdata[1] = destdata[2];
- vdp_st = vdp->video_surface_put_bits_y_cb_cr(rndr->surface,
- vc->vdp_pixel_format, destdata, mpi->stride);
- CHECK_ST_WARNING("Error when calling "
- "vdp_video_surface_put_bits_y_cb_cr");
- }
- } else
- // We don't support slice callbacks so this shouldn't occur -
- // I think the flags test above in pointless, but I'm adding
- // this instead of removing it just in case.
- abort();
- if (mpi->fields & MP_IMGFIELD_ORDERED)
- vc->top_field_first = !!(mpi->fields & MP_IMGFIELD_TOP_FIRST);
- else
- vc->top_field_first = 1;
-
- add_new_video_surface(vo, rndr->surface, reserved_mpi, pts);
-
- return;
-}
-
-// warning: the size and pixel format of surface must match that of the
-// surfaces in vc->output_surfaces
-static struct mp_image *read_output_surface(struct vdpctx *vc,
- VdpOutputSurface surface,
- int width, int height)
-{
- VdpStatus vdp_st;
- struct vdp_functions *vdp = vc->vdp;
- struct mp_image *image = alloc_mpi(width, height, IMGFMT_BGR32);
- image->colorspace = MP_CSP_RGB;
- image->levels = vc->colorspace.levels_out; // hardcoded with conv. matrix
-
- void *dst_planes[] = { image->planes[0] };
- uint32_t dst_pitches[] = { image->stride[0] };
- vdp_st = vdp->output_surface_get_bits_native(surface, NULL, dst_planes,
- dst_pitches);
- CHECK_ST_WARNING("Error when calling vdp_output_surface_get_bits_native");
-
- return image;
-}
-
-static struct mp_image *get_screenshot(struct vo *vo)
-{
- struct vdpctx *vc = vo->priv;
- VdpStatus vdp_st;
- struct vdp_functions *vdp = vc->vdp;
-
- if (vc->screenshot_surface == VDP_INVALID_HANDLE) {
- vdp_st = vdp->output_surface_create(vc->vdp_device,
- OUTPUT_RGBA_FORMAT,
- vc->vid_width, vc->vid_height,
- &vc->screenshot_surface);
- CHECK_ST_WARNING("Error when calling vdp_output_surface_create");
- }
-
- VdpRect rc = { .x1 = vc->vid_width, .y1 = vc->vid_height };
- render_video_to_output_surface(vo, vc->screenshot_surface, &rc);
-
- struct mp_image *image = read_output_surface(vc, vc->screenshot_surface,
- vc->vid_width, vc->vid_height);
-
- image->display_w = vo->aspdat.prew;
- image->display_h = vo->aspdat.preh;
-
- return image;
-}
-
-static struct mp_image *get_window_screenshot(struct vo *vo)
-{
- struct vdpctx *vc = vo->priv;
- int last_surface = WRAP_ADD(vc->surface_num, -1, vc->num_output_surfaces);
- VdpOutputSurface screen = vc->output_surfaces[last_surface];
- struct mp_image *image = read_output_surface(vo->priv, screen,
- vc->output_surface_width,
- vc->output_surface_height);
- image->width = image->w = vo->dwidth;
- image->height = image->h = vo->dheight;
- return image;
-}
-
-static uint32_t get_image(struct vo *vo, mp_image_t *mpi)
-{
- struct vdpctx *vc = vo->priv;
- struct vdpau_render_state *rndr;
-
- // no dr for non-decoding for now
- if (!IMGFMT_IS_VDPAU(vc->image_format))
- return VO_FALSE;
- if (mpi->type != MP_IMGTYPE_NUMBERED)
- return VO_FALSE;
-
- rndr = get_surface(vo, mpi->number);
- if (!rndr) {
- mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] no surfaces available in "
- "get_image\n");
- // TODO: this probably breaks things forever, provide a dummy buffer?
- return VO_FALSE;
- }
- mpi->flags |= MP_IMGFLAG_DIRECT;
- mpi->stride[0] = mpi->stride[1] = mpi->stride[2] = 0;
- mpi->planes[0] = mpi->planes[1] = mpi->planes[2] = NULL;
- // hack to get around a check and to avoid a special-case in vd_ffmpeg.c
- mpi->planes[0] = (void *)rndr;
- mpi->num_planes = 1;
- mpi->priv = rndr;
- return VO_TRUE;
-}
-
-static int query_format(uint32_t format)
-{
- int default_flags = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW
- | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_OSD
- | VFCAP_FLIP;
- switch (format) {
- case IMGFMT_YV12:
- case IMGFMT_I420:
- case IMGFMT_IYUV:
- case IMGFMT_NV12:
- case IMGFMT_YUY2:
- case IMGFMT_UYVY:
- return default_flags | VOCAP_NOSLICES;
- case IMGFMT_VDPAU_MPEG1:
- case IMGFMT_VDPAU_MPEG2:
- case IMGFMT_VDPAU_H264:
- case IMGFMT_VDPAU_WMV3:
- case IMGFMT_VDPAU_VC1:
- case IMGFMT_VDPAU_MPEG4:
- return default_flags;
- }
- return 0;
-}
-
-static void destroy_vdpau_objects(struct vo *vo)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
-
- int i;
- VdpStatus vdp_st;
-
- free_video_specific(vo);
-
- if (vc->flip_queue != VDP_INVALID_HANDLE) {
- vdp_st = vdp->presentation_queue_destroy(vc->flip_queue);
- CHECK_ST_WARNING("Error when calling vdp_presentation_queue_destroy");
- }
-
- if (vc->flip_target != VDP_INVALID_HANDLE) {
- vdp_st = vdp->presentation_queue_target_destroy(vc->flip_target);
- CHECK_ST_WARNING("Error when calling "
- "vdp_presentation_queue_target_destroy");
- }
-
- for (i = 0; i < vc->num_output_surfaces; i++) {
- if (vc->output_surfaces[i] == VDP_INVALID_HANDLE)
- continue;
- vdp_st = vdp->output_surface_destroy(vc->output_surfaces[i]);
- CHECK_ST_WARNING("Error when calling vdp_output_surface_destroy");
- }
-
- for (int i = 0; i < MAX_OSD_PARTS; i++) {
- struct osd_bitmap_surface *sfc = &vc->osd_surfaces[i];
- if (sfc->surface != VDP_INVALID_HANDLE) {
- vdp_st = vdp->bitmap_surface_destroy(sfc->surface);
- CHECK_ST_WARNING("Error when calling vdp_bitmap_surface_destroy");
- }
- }
-
- vdp_st = vdp->device_destroy(vc->vdp_device);
- CHECK_ST_WARNING("Error when calling vdp_device_destroy");
-}
-
-static void uninit(struct vo *vo)
-{
- struct vdpctx *vc = vo->priv;
-
- /* Destroy all vdpau objects */
- destroy_vdpau_objects(vo);
-
-#ifdef CONFIG_XF86VM
- if (vc->mode_switched)
- vo_vm_close(vo);
-#endif
- vo_x11_uninit(vo);
-
- // Free bitstream buffers allocated by FFmpeg
- for (int i = 0; i < MAX_VIDEO_SURFACES; i++)
- av_freep(&vc->surface_render[i].bitstream_buffers);
-}
-
-static int preinit(struct vo *vo, const char *arg)
-{
- struct vdpctx *vc = vo->priv;
-
- // Mark everything as invalid first so uninit() can tell what has been
- // allocated
- mark_vdpau_objects_uninitialized(vo);
-
- vc->colorspace = (struct mp_csp_details) MP_CSP_DETAILS_DEFAULTS;
- vc->video_eq.capabilities = MP_CSP_EQ_CAPS_COLORMATRIX;
-
- vc->deint_type = vc->deint ? FFABS(vc->deint) : 3;
- if (vc->deint < 0)
- vc->deint = 0;
-
- if (!vo_init(vo))
- return -1;
-
- // After this calling uninit() should work to free resources
-
- if (win_x11_init_vdpau_procs(vo) < 0) {
- if (vc->vdp && vc->vdp->device_destroy)
- vc->vdp->device_destroy(vc->vdp_device);
- vo_x11_uninit(vo);
- return -1;
- }
-
- return 0;
-}
-
-static int get_equalizer(struct vo *vo, const char *name, int *value)
-{
- struct vdpctx *vc = vo->priv;
- return mp_csp_equalizer_get(&vc->video_eq, name, value) >= 0 ?
- VO_TRUE : VO_NOTIMPL;
-}
-
-static bool status_ok(struct vo *vo)
-{
- if (!vo->config_ok || handle_preemption(vo) < 0)
- return false;
- return true;
-}
-
-static int set_equalizer(struct vo *vo, const char *name, int value)
-{
- struct vdpctx *vc = vo->priv;
-
- if (mp_csp_equalizer_set(&vc->video_eq, name, value) < 0)
- return VO_NOTIMPL;
-
- if (status_ok(vo))
- update_csc_matrix(vo);
- return true;
-}
-
-static void checked_resize(struct vo *vo)
-{
- if (!status_ok(vo))
- return;
- resize(vo);
-}
-
-static int control(struct vo *vo, uint32_t request, void *data)
-{
- struct vdpctx *vc = vo->priv;
- struct vdp_functions *vdp = vc->vdp;
-
- handle_preemption(vo);
-
- switch (request) {
- case VOCTRL_GET_DEINTERLACE:
- *(int *)data = vc->deint;
- return VO_TRUE;
- case VOCTRL_SET_DEINTERLACE:
- vc->deint = *(int *)data;
- if (vc->deint)
- vc->deint = vc->deint_type;
- if (vc->deint_type > 2 && status_ok(vo)) {
- VdpStatus vdp_st;
- VdpVideoMixerFeature features[1] =
- {vc->deint_type == 3 ?
- VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL :
- VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL};
- VdpBool feature_enables[1] = {vc->deint ? VDP_TRUE : VDP_FALSE};
- vdp_st = vdp->video_mixer_set_feature_enables(vc->video_mixer,
- 1, features,
- feature_enables);
- CHECK_ST_WARNING("Error changing deinterlacing settings");
- }
- vo->want_redraw = true;
- return VO_TRUE;
- case VOCTRL_PAUSE:
- if (vc->dropped_frame)
- vo->want_redraw = true;
- return true;
- case VOCTRL_QUERY_FORMAT:
- return query_format(*(uint32_t *)data);
- case VOCTRL_GET_IMAGE:
- return get_image(vo, data);
- case VOCTRL_DRAW_IMAGE:
- abort(); // draw_image() should get called directly
- case VOCTRL_BORDER:
- vo_x11_border(vo);
- checked_resize(vo);
- return VO_TRUE;
- case VOCTRL_FULLSCREEN:
- vo_x11_fullscreen(vo);
- checked_resize(vo);
- return VO_TRUE;
- case VOCTRL_GET_PANSCAN:
- return VO_TRUE;
- case VOCTRL_SET_PANSCAN:
- checked_resize(vo);
- return VO_TRUE;
- case VOCTRL_SET_EQUALIZER: {
- vo->want_redraw = true;
- struct voctrl_set_equalizer_args *args = data;
- return set_equalizer(vo, args->name, args->value);
- }
- case VOCTRL_GET_EQUALIZER: {
- struct voctrl_get_equalizer_args *args = data;
- return get_equalizer(vo, args->name, args->valueptr);
- }
- case VOCTRL_SET_YUV_COLORSPACE:
- vc->colorspace = *(struct mp_csp_details *)data;
- if (status_ok(vo))
- update_csc_matrix(vo);
- vo->want_redraw = true;
- return true;
- case VOCTRL_GET_YUV_COLORSPACE:
- *(struct mp_csp_details *)data = vc->colorspace;
- return true;
- case VOCTRL_ONTOP:
- vo_x11_ontop(vo);
- return VO_TRUE;
- case VOCTRL_UPDATE_SCREENINFO:
- update_xinerama_info(vo);
- return VO_TRUE;
- case VOCTRL_NEWFRAME:
- vc->deint_queue_pos = next_deint_queue_pos(vo, true);
- if (status_ok(vo))
- video_to_output_surface(vo);
- return true;
- case VOCTRL_SKIPFRAME:
- vc->deint_queue_pos = next_deint_queue_pos(vo, true);
- return true;
- case VOCTRL_REDRAW_FRAME:
- if (status_ok(vo))
- video_to_output_surface(vo);
- return true;
- case VOCTRL_RESET:
- forget_frames(vo);
- return true;
- case VOCTRL_SCREENSHOT: {
- if (!status_ok(vo))
- return false;
- struct voctrl_screenshot_args *args = data;
- if (args->full_window)
- args->out_image = get_window_screenshot(vo);
- else
- args->out_image = get_screenshot(vo);
- return true;
- }
- }
- return VO_NOTIMPL;
-}
-
-#undef OPT_BASE_STRUCT
-#define OPT_BASE_STRUCT struct vdpctx
-
-const struct vo_driver video_out_vdpau = {
- .is_new = true,
- .buffer_frames = true,
- .info = &(const struct vo_info_s){
- "VDPAU with X11",
- "vdpau",
- "Rajib Mahapatra <rmahapatra@nvidia.com> and others",
- ""
- },
- .preinit = preinit,
- .config = config,
- .control = control,
- .draw_image = draw_image,
- .get_buffered_frame = set_next_frame_info,
- .draw_slice = draw_slice,
- .draw_osd = draw_osd,
- .flip_page_timed = flip_page_timed,
- .check_events = check_events,
- .uninit = uninit,
- .priv_size = sizeof(struct vdpctx),
- .options = (const struct m_option []){
- OPT_INTRANGE("deint", deint, 0, -4, 4),
- OPT_FLAG_ON("chroma-deint", chroma_deint, 0, OPTDEF_INT(1)),
- OPT_FLAG_OFF("nochroma-deint", chroma_deint, 0),
- OPT_MAKE_FLAGS("pullup", pullup, 0),
- OPT_FLOATRANGE("denoise", denoise, 0, 0, 1),
- OPT_FLOATRANGE("sharpen", sharpen, 0, -1, 1),
- OPT_INTRANGE("hqscaling", hqscaling, 0, 0, 9),
- OPT_FLOAT("fps", user_fps, 0),
- OPT_FLAG_ON("composite-detect", composite_detect, 0, OPTDEF_INT(1)),
- OPT_INT("queuetime_windowed", flip_offset_window, 0, OPTDEF_INT(50)),
- OPT_INT("queuetime_fs", flip_offset_fs, 0, OPTDEF_INT(50)),
- OPT_INTRANGE("output_surfaces", num_output_surfaces, 0,
- 2, MAX_OUTPUT_SURFACES, OPTDEF_INT(3)),
- {NULL},
- }
-};
diff --git a/libvo/vo_x11.c b/libvo/vo_x11.c
deleted file mode 100644
index 2358b0a295..0000000000
--- a/libvo/vo_x11.c
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include "config.h"
-#include "video_out.h"
-#include "aspect.h"
-#include "csputils.h"
-#include "libmpcodecs/mp_image.h"
-#include "libmpcodecs/vfcap.h"
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-#include <errno.h>
-
-#include "x11_common.h"
-
-#ifdef HAVE_SHM
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <X11/extensions/XShm.h>
-#endif
-
-#include "sub/sub.h"
-
-#include "libmpcodecs/sws_utils.h"
-#define MODE_RGB 0x1
-#define MODE_BGR 0x2
-
-#include "mp_msg.h"
-
-extern int sws_flags;
-
-struct priv {
- struct vo *vo;
-
- /* local data */
- unsigned char *ImageData;
- //! original unaligned pointer for free
- unsigned char *ImageDataOrig;
-
- /* X11 related variables */
- XImage *myximage;
- int depth, bpp;
- XWindowAttributes attribs;
-
- int int_pause;
-
- int Flip_Flag;
- int zoomFlag;
-
- uint32_t image_width;
- uint32_t image_height;
- uint32_t in_format;
- uint32_t out_format;
- int out_offset;
- int srcW;
- int srcH;
-
- int old_vo_dwidth;
- int old_vo_dheight;
-
- struct SwsContext *swsContext;
- int dst_width;
-
- XVisualInfo vinfo;
-
- int firstTime;
-
-#ifdef HAVE_SHM
- int Shmem_Flag;
-
- XShmSegmentInfo Shminfo[1];
- int gXErrorFlag;
- int CompletionType;
-#endif
-};
-
-static void flip_page(struct vo *vo);
-
-static void check_events(struct vo *vo)
-{
- struct priv *p = vo->priv;
-
- int ret = vo_x11_check_events(vo);
-
- if (ret & VO_EVENT_RESIZE)
- vo_x11_clearwindow(vo, vo->x11->window);
- else if (ret & VO_EVENT_EXPOSE)
- vo_x11_clearwindow_part(vo, vo->x11->window, p->myximage->width,
- p->myximage->height);
- if (ret & VO_EVENT_EXPOSE && p->int_pause)
- flip_page(vo);
-}
-
-static void getMyXImage(struct priv *p)
-{
- struct vo *vo = p->vo;
-#ifdef HAVE_SHM
- if (vo->x11->display_is_local && XShmQueryExtension(vo->x11->display))
- p->Shmem_Flag = 1;
- else {
- p->Shmem_Flag = 0;
- mp_msg(MSGT_VO, MSGL_WARN,
- "Shared memory not supported\nReverting to normal Xlib\n");
- }
- if (p->Shmem_Flag)
- p->CompletionType = XShmGetEventBase(vo->x11->display) + ShmCompletion;
-
- if (p->Shmem_Flag) {
- p->myximage =
- XShmCreateImage(vo->x11->display, p->vinfo.visual, p->depth,
- ZPixmap, NULL, &p->Shminfo[0], p->image_width,
- p->image_height);
- if (p->myximage == NULL) {
- mp_msg(MSGT_VO, MSGL_WARN,
- "Shared memory error,disabling ( Ximage error )\n");
- goto shmemerror;
- }
- p->Shminfo[0].shmid = shmget(IPC_PRIVATE,
- p->myximage->bytes_per_line *
- p->myximage->height,
- IPC_CREAT | 0777);
- if (p->Shminfo[0].shmid < 0) {
- XDestroyImage(p->myximage);
- mp_msg(MSGT_VO, MSGL_V, "%s\n", strerror(errno));
- //perror( strerror( errno ) );
- mp_msg(MSGT_VO, MSGL_WARN,
- "Shared memory error,disabling ( seg id error )\n");
- goto shmemerror;
- }
- p->Shminfo[0].shmaddr = (char *) shmat(p->Shminfo[0].shmid, 0, 0);
-
- if (p->Shminfo[0].shmaddr == ((char *) -1)) {
- XDestroyImage(p->myximage);
- if (p->Shminfo[0].shmaddr != ((char *) -1))
- shmdt(p->Shminfo[0].shmaddr);
- mp_msg(MSGT_VO, MSGL_WARN,
- "Shared memory error,disabling ( address error )\n");
- goto shmemerror;
- }
- p->myximage->data = p->Shminfo[0].shmaddr;
- p->ImageData = (unsigned char *) p->myximage->data;
- p->Shminfo[0].readOnly = False;
- XShmAttach(vo->x11->display, &p->Shminfo[0]);
-
- XSync(vo->x11->display, False);
-
- if (p->gXErrorFlag) {
- XDestroyImage(p->myximage);
- shmdt(p->Shminfo[0].shmaddr);
- mp_msg(MSGT_VO, MSGL_WARN, "Shared memory error,disabling.\n");
- p->gXErrorFlag = 0;
- goto shmemerror;
- } else
- shmctl(p->Shminfo[0].shmid, IPC_RMID, 0);
-
- if (!p->firstTime) {
- mp_msg(MSGT_VO, MSGL_V, "Sharing memory.\n");
- p->firstTime = 1;
- }
- } else {
-shmemerror:
- p->Shmem_Flag = 0;
-#endif
- p->myximage =
- XCreateImage(vo->x11->display, p->vinfo.visual, p->depth, ZPixmap,
- 0, NULL, p->image_width, p->image_height, 8, 0);
- p->ImageDataOrig =
- malloc(p->myximage->bytes_per_line * p->image_height + 32);
- p->myximage->data = p->ImageDataOrig + 16 - ((long)p->ImageDataOrig & 15);
- memset(p->myximage->data, 0, p->myximage->bytes_per_line * p->image_height);
- p->ImageData = p->myximage->data;
-#ifdef HAVE_SHM
-}
-#endif
-}
-
-static void freeMyXImage(struct priv *p)
-{
- struct vo *vo = p->vo;
-#ifdef HAVE_SHM
- if (p->Shmem_Flag) {
- XShmDetach(vo->x11->display, &p->Shminfo[0]);
- XDestroyImage(p->myximage);
- shmdt(p->Shminfo[0].shmaddr);
- } else
-#endif
- {
- p->myximage->data = p->ImageDataOrig;
- XDestroyImage(p->myximage);
- p->ImageDataOrig = NULL;
- }
- p->myximage = NULL;
- p->ImageData = NULL;
-}
-
-#if BYTE_ORDER == BIG_ENDIAN
-#define BO_NATIVE MSBFirst
-#define BO_NONNATIVE LSBFirst
-#else
-#define BO_NATIVE LSBFirst
-#define BO_NONNATIVE MSBFirst
-#endif
-const struct fmt2Xfmtentry_s {
- uint32_t mpfmt;
- int byte_order;
- unsigned red_mask;
- unsigned green_mask;
- unsigned blue_mask;
-} fmt2Xfmt[] = {
- {IMGFMT_RGB8, BO_NATIVE, 0x00000007, 0x00000038, 0x000000C0},
- {IMGFMT_RGB8, BO_NONNATIVE, 0x00000007, 0x00000038, 0x000000C0},
- {IMGFMT_BGR8, BO_NATIVE, 0x000000E0, 0x0000001C, 0x00000003},
- {IMGFMT_BGR8, BO_NONNATIVE, 0x000000E0, 0x0000001C, 0x00000003},
- {IMGFMT_RGB15, BO_NATIVE, 0x0000001F, 0x000003E0, 0x00007C00},
- {IMGFMT_BGR15, BO_NATIVE, 0x00007C00, 0x000003E0, 0x0000001F},
- {IMGFMT_RGB16, BO_NATIVE, 0x0000001F, 0x000007E0, 0x0000F800},
- {IMGFMT_BGR16, BO_NATIVE, 0x0000F800, 0x000007E0, 0x0000001F},
- {IMGFMT_RGB24, MSBFirst, 0x00FF0000, 0x0000FF00, 0x000000FF},
- {IMGFMT_RGB24, LSBFirst, 0x000000FF, 0x0000FF00, 0x00FF0000},
- {IMGFMT_BGR24, MSBFirst, 0x000000FF, 0x0000FF00, 0x00FF0000},
- {IMGFMT_BGR24, LSBFirst, 0x00FF0000, 0x0000FF00, 0x000000FF},
- {IMGFMT_RGB32, BO_NATIVE, 0x000000FF, 0x0000FF00, 0x00FF0000},
- {IMGFMT_RGB32, BO_NONNATIVE, 0xFF000000, 0x00FF0000, 0x0000FF00},
- {IMGFMT_BGR32, BO_NATIVE, 0x00FF0000, 0x0000FF00, 0x000000FF},
- {IMGFMT_BGR32, BO_NONNATIVE, 0x0000FF00, 0x00FF0000, 0xFF000000},
- {IMGFMT_ARGB, MSBFirst, 0x00FF0000, 0x0000FF00, 0x000000FF},
- {IMGFMT_ARGB, LSBFirst, 0x0000FF00, 0x00FF0000, 0xFF000000},
- {IMGFMT_ABGR, MSBFirst, 0x000000FF, 0x0000FF00, 0x00FF0000},
- {IMGFMT_ABGR, LSBFirst, 0xFF000000, 0x00FF0000, 0x0000FF00},
- {IMGFMT_RGBA, MSBFirst, 0xFF000000, 0x00FF0000, 0x0000FF00},
- {IMGFMT_RGBA, LSBFirst, 0x000000FF, 0x0000FF00, 0x00FF0000},
- {IMGFMT_BGRA, MSBFirst, 0x0000FF00, 0x00FF0000, 0xFF000000},
- {IMGFMT_BGRA, LSBFirst, 0x00FF0000, 0x0000FF00, 0x000000FF},
- {0}
-};
-
-static int config(struct vo *vo, uint32_t width, uint32_t height,
- uint32_t d_width, uint32_t d_height, uint32_t flags,
- uint32_t format)
-{
- struct priv *p = vo->priv;
-
- Colormap theCmap;
- const struct fmt2Xfmtentry_s *fmte = fmt2Xfmt;
-
-#ifdef CONFIG_XF86VM
- int vm = flags & VOFLAG_MODESWITCHING;
-#endif
- p->Flip_Flag = flags & VOFLAG_FLIPPING;
- p->zoomFlag = flags & VOFLAG_SWSCALE;
-
- p->old_vo_dwidth = -1;
- p->old_vo_dheight = -1;
-
- p->in_format = format;
- p->srcW = width;
- p->srcH = height;
-
- XGetWindowAttributes(vo->x11->display, vo->x11->rootwin, &p->attribs);
- p->depth = p->attribs.depth;
-
- if (p->depth != 15 && p->depth != 16 && p->depth != 24 && p->depth != 32) {
- Visual *visual;
-
- p->depth = vo_find_depth_from_visuals(vo->x11->display, vo->x11->screen,
- &visual);
- }
- if (!XMatchVisualInfo(vo->x11->display, vo->x11->screen, p->depth,
- DirectColor, &p->vinfo)
- || (WinID > 0
- && p->vinfo.visualid != XVisualIDFromVisual(p->attribs.visual)))
- {
- XMatchVisualInfo(vo->x11->display, vo->x11->screen, p->depth, TrueColor,
- &p->vinfo);
- }
-
- /* set image size (which is indeed neither the input nor output size),
- if zoom is on it will be changed during draw_slice anyway so we don't
- duplicate the aspect code here
- */
- p->image_width = (width + 7) & (~7);
- p->image_height = height;
-
- {
-#ifdef CONFIG_XF86VM
- if (vm)
- vo_vm_switch(vo);
-
-#endif
- theCmap = vo_x11_create_colormap(vo, &p->vinfo);
-
- vo_x11_create_vo_window(vo, &p->vinfo, vo->dx, vo->dy, vo->dwidth,
- vo->dheight, flags, theCmap, "x11");
- if (WinID > 0)
- p->depth = vo_x11_update_geometry(vo, true);
-
-#ifdef CONFIG_XF86VM
- if (vm) {
- /* Grab the mouse pointer in our window */
- if (vo_grabpointer)
- XGrabPointer(vo->x11->display, vo->x11->window, True, 0,
- GrabModeAsync, GrabModeAsync,
- vo->x11->window, None, CurrentTime);
- XSetInputFocus(vo->x11->display, vo->x11->window, RevertToNone,
- CurrentTime);
- }
-#endif
- }
-
- if (p->myximage) {
- freeMyXImage(p);
- sws_freeContext(p->swsContext);
- }
- getMyXImage(p);
-
- while (fmte->mpfmt) {
- int depth = IMGFMT_RGB_DEPTH(fmte->mpfmt);
- /* bits_per_pixel in X seems to be set to 16 for 15 bit formats
- => force depth to 16 so that only the color masks are used for the format check */
- if (depth == 15)
- depth = 16;
-
- if (depth == p->myximage->bits_per_pixel &&
- fmte->byte_order == p->myximage->byte_order &&
- fmte->red_mask == p->myximage->red_mask &&
- fmte->green_mask == p->myximage->green_mask &&
- fmte->blue_mask == p->myximage->blue_mask)
- break;
- fmte++;
- }
- if (!fmte->mpfmt) {
- mp_msg(
- MSGT_VO, MSGL_ERR,
- "X server image format not supported, please contact the developers\n");
- return -1;
- }
- p->out_format = fmte->mpfmt;
- p->bpp = p->myximage->bits_per_pixel;
- p->out_offset = 0;
- // We can easily "emulate" non-native RGB32 and BGR32
- if (p->out_format == (IMGFMT_BGR32 | 128)
- || p->out_format == (IMGFMT_RGB32 | 128))
- {
- p->out_format &= ~128;
-#if BYTE_ORDER == BIG_ENDIAN
- p->out_offset = 1;
-#else
- p->out_offset = -1;
-#endif
- }
-
- /* always allocate swsContext as size could change between frames */
- p->swsContext = sws_getContextFromCmdLine(width, height, p->in_format,
- width, height, p->out_format);
- if (!p->swsContext)
- return -1;
-
- p->dst_width = width;
-
- return 0;
-}
-
-static void Display_Image(struct priv *p, XImage *myximage, uint8_t *ImageData)
-{
- struct vo *vo = p->vo;
-
- int x = (vo->dwidth - p->dst_width) / 2;
- int y = (vo->dheight - p->myximage->height) / 2;
-
- // do not draw if the image needs rescaling
- if ((p->old_vo_dwidth != vo->dwidth ||
- p->old_vo_dheight != vo->dheight) && p->zoomFlag)
- return;
-
- if (WinID == 0) {
- x = vo->dx;
- y = vo->dy;
- }
- p->myximage->data += p->out_offset;
-#ifdef HAVE_SHM
- if (p->Shmem_Flag) {
- XShmPutImage(vo->x11->display, vo->x11->window, vo->x11->vo_gc,
- p->myximage, 0, 0, x, y, p->dst_width, p->myximage->height,
- True);
- } else
-#endif
- {
- XPutImage(vo->x11->display, vo->x11->window, vo->x11->vo_gc,
- p->myximage, 0, 0, x, y, p->dst_width, p->myximage->height);
- }
- p->myximage->data -= p->out_offset;
-}
-
-static struct mp_image get_x_buffer(struct priv *p)
-{
- struct mp_image img = {0};
- img.w = img.width = p->image_width;
- img.h = img.height = p->image_height;
- mp_image_setfmt(&img, p->out_format);
-
- img.planes[0] = p->ImageData;
- img.stride[0] = p->image_width * ((p->bpp + 7) / 8);
-
- return img;
-}
-
-static void draw_osd(struct vo *vo, struct osd_state *osd)
-{
- struct priv *p = vo->priv;
-
- struct mp_image img = get_x_buffer(p);
-
- struct mp_osd_res res = {
- .w = img.w,
- .h = img.h,
- .display_par = vo->monitor_par,
- .video_par = vo->aspdat.par,
- };
-
- osd_draw_on_image(osd, res, osd->vo_pts, 0, &img);
-}
-
-static void flip_page(struct vo *vo)
-{
- struct priv *p = vo->priv;
- Display_Image(p, p->myximage, p->ImageData);
- XSync(vo->x11->display, False);
-}
-
-static int draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h,
- int x, int y)
-{
- struct priv *p = vo->priv;
- uint8_t *dst[MP_MAX_PLANES] = {NULL};
- int dstStride[MP_MAX_PLANES] = {0};
-
- if ((p->old_vo_dwidth != vo->dwidth || p->old_vo_dheight != vo->dheight)
- /*&& y==0 */ && p->zoomFlag)
- {
- int newW = vo->dwidth;
- int newH = vo->dheight;
- struct SwsContext *oldContext = p->swsContext;
-
- p->old_vo_dwidth = vo->dwidth;
- p->old_vo_dheight = vo->dheight;
-
- if (vo_fs)
- aspect(vo, &newW, &newH, A_ZOOM);
- if (sws_flags == 0)
- newW &= (~31); // not needed but, if the user wants the FAST_BILINEAR SCALER, then its needed
-
- p->swsContext
- = sws_getContextFromCmdLine(p->srcW, p->srcH, p->in_format, newW,
- newH, p->out_format);
- if (p->swsContext) {
- p->image_width = (newW + 7) & (~7);
- p->image_height = newH;
-
- freeMyXImage(p);
- getMyXImage(p);
- sws_freeContext(oldContext);
- } else
- p->swsContext = oldContext;
- p->dst_width = newW;
- }
-
- dstStride[0] = p->image_width * ((p->bpp + 7) / 8);
- dst[0] = p->ImageData;
- if (p->Flip_Flag) {
- dst[0] += dstStride[0] * (p->image_height - 1);
- dstStride[0] = -dstStride[0];
- }
- sws_scale(p->swsContext, (const uint8_t **)src, stride, y, h, dst,
- dstStride);
- return 0;
-}
-
-static int query_format(struct vo *vo, uint32_t format)
-{
- mp_msg(MSGT_VO, MSGL_DBG2,
- "vo_x11: query_format was called: %x (%s)\n", format,
- vo_format_name(format));
- if (IMGFMT_IS_BGR(format)) {
- if (IMGFMT_BGR_DEPTH(format) <= 8)
- return 0; // TODO 8bpp not yet fully implemented
- if (IMGFMT_BGR_DEPTH(format) == vo->x11->depthonscreen)
- return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW |
- VFCAP_OSD | VFCAP_SWSCALE | VFCAP_FLIP |
- VFCAP_ACCEPT_STRIDE;
- else
- return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_SWSCALE |
- VFCAP_FLIP |
- VFCAP_ACCEPT_STRIDE;
- }
-
- switch (format) {
- case IMGFMT_I420:
- case IMGFMT_IYUV:
- case IMGFMT_YV12:
- return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_SWSCALE |
- VFCAP_ACCEPT_STRIDE;
- }
- return 0;
-}
-
-
-static void uninit(struct vo *vo)
-{
- struct priv *p = vo->priv;
- if (p->myximage)
- freeMyXImage(p);
-
-#ifdef CONFIG_XF86VM
- vo_vm_close(vo);
-#endif
-
- p->zoomFlag = 0;
- vo_x11_uninit(vo);
-
- sws_freeContext(p->swsContext);
-}
-
-static int preinit(struct vo *vo, const char *arg)
-{
- struct priv *p = vo->priv;
- p->vo = vo;
-
- if (arg) {
- mp_msg(MSGT_VO, MSGL_ERR, "vo_x11: Unknown subdevice: %s\n", arg);
- return ENOSYS;
- }
-
- if (!vo_init(vo))
- return -1; // Can't open X11
- return 0;
-}
-
-static int control(struct vo *vo, uint32_t request, void *data)
-{
- struct priv *p = vo->priv;
- switch (request) {
- case VOCTRL_PAUSE:
- return p->int_pause = 1;
- case VOCTRL_RESUME:
- return p->int_pause = 0;
- case VOCTRL_QUERY_FORMAT:
- return query_format(vo, *((uint32_t *) data));
- case VOCTRL_FULLSCREEN:
- vo_x11_fullscreen(vo);
- vo_x11_clearwindow(vo, vo->x11->window);
- return VO_TRUE;
- case VOCTRL_SET_EQUALIZER:
- {
- struct voctrl_set_equalizer_args *args = data;
- return vo_x11_set_equalizer(vo, args->name, args->value);
- }
- case VOCTRL_GET_EQUALIZER:
- {
- struct voctrl_get_equalizer_args *args = data;
- return vo_x11_get_equalizer(args->name, args->valueptr);
- }
- case VOCTRL_ONTOP:
- vo_x11_ontop(vo);
- return VO_TRUE;
- case VOCTRL_UPDATE_SCREENINFO:
- update_xinerama_info(vo);
- return VO_TRUE;
- }
- return VO_NOTIMPL;
-}
-
-const struct vo_driver video_out_x11 = {
- .is_new = false,
- .info = &(const vo_info_t) {
- "X11 ( XImage/Shm )",
- "x11",
- "Aaron Holtzman <aholtzma@ess.engr.uvic.ca>",
- ""
- },
- .priv_size = sizeof(struct priv),
- .priv_defaults = &(const struct priv) {
- .srcW = -1,
- .srcH = -1,
- .old_vo_dwidth = -1,
- .old_vo_dheight = -1,
-#ifdef HAVE_SHM
- .CompletionType = -1,
-#endif
- },
- .preinit = preinit,
- .config = config,
- .control = control,
- .draw_slice = draw_slice,
- .draw_osd = draw_osd,
- .flip_page = flip_page,
- .check_events = check_events,
- .uninit = uninit,
-};
diff --git a/libvo/vo_xv.c b/libvo/vo_xv.c
deleted file mode 100644
index 3673764ed4..0000000000
--- a/libvo/vo_xv.c
+++ /dev/null
@@ -1,716 +0,0 @@
-/*
- * X11 Xv interface
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <errno.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-#include <libavutil/common.h>
-
-#include "config.h"
-
-#ifdef HAVE_SHM
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <X11/extensions/XShm.h>
-#endif
-
-// Note: depends on the inclusion of X11/extensions/XShm.h
-#include <X11/extensions/Xv.h>
-#include <X11/extensions/Xvlib.h>
-
-#include "options.h"
-#include "talloc.h"
-#include "mp_msg.h"
-#include "video_out.h"
-#include "libmpcodecs/vfcap.h"
-#include "libmpcodecs/mp_image.h"
-#include "x11_common.h"
-#include "fastmemcpy.h"
-#include "sub/sub.h"
-#include "aspect.h"
-#include "csputils.h"
-#include "subopt-helper.h"
-
-static const vo_info_t info = {
- "X11/Xv",
- "xv",
- "Gerd Knorr <kraxel@goldbach.in-berlin.de> and others",
- ""
-};
-
-struct xvctx {
- XvAdaptorInfo *ai;
- XvImageFormatValues *fo;
- unsigned int formats, adaptors, xv_format;
- int current_buf;
- int current_ip_buf;
- int num_buffers;
- int total_buffers;
- bool have_image_copy;
- bool unchanged_image;
- int visible_buf;
- XvImage *xvimage[2 + 1];
- uint32_t image_width;
- uint32_t image_height;
- uint32_t image_format;
- struct mp_csp_details cached_csp;
- int is_paused;
- struct mp_rect src_rect;
- struct mp_rect dst_rect;
- uint32_t max_width, max_height; // zero means: not set
- int mode_switched;
-#ifdef HAVE_SHM
- XShmSegmentInfo Shminfo[2 + 1];
- int Shmem_Flag;
-#endif
-};
-
-static void allocate_xvimage(struct vo *, int);
-static void deallocate_xvimage(struct vo *vo, int foo);
-
-static void read_xv_csp(struct vo *vo)
-{
- struct xvctx *ctx = vo->priv;
- struct vo_x11_state *x11 = vo->x11;
- struct mp_csp_details *cspc = &ctx->cached_csp;
- *cspc = (struct mp_csp_details) MP_CSP_DETAILS_DEFAULTS;
- int bt709_enabled;
- if (vo_xv_get_eq(vo, x11->xv_port, "bt_709", &bt709_enabled))
- cspc->format = bt709_enabled == 100 ? MP_CSP_BT_709 : MP_CSP_BT_601;
-}
-
-static void resize(struct vo *vo)
-{
- struct xvctx *ctx = vo->priv;
-
- // Can't be used, because the function calculates screen-space coordinates,
- // while we need video-space.
- struct mp_osd_res unused;
-
- vo_get_src_dst_rects(vo, &ctx->src_rect, &ctx->dst_rect, &unused);
-
- struct mp_rect *dst = &ctx->dst_rect;
- int dw = dst->x1 - dst->x0, dh = dst->y1 - dst->y0;
- vo_x11_clearwindow_part(vo, vo->x11->window, dw, dh);
- vo_xv_draw_colorkey(vo, dst->x0, dst->y0, dw, dh);
- read_xv_csp(vo);
-}
-
-/*
- * connect to server, create and map window,
- * allocate colors and (shared) memory
- */
-static int config(struct vo *vo, uint32_t width, uint32_t height,
- uint32_t d_width, uint32_t d_height, uint32_t flags,
- uint32_t format)
-{
- struct vo_x11_state *x11 = vo->x11;
- XVisualInfo vinfo;
- XSetWindowAttributes xswa;
- XWindowAttributes attribs;
- unsigned long xswamask;
- int depth;
- struct xvctx *ctx = vo->priv;
- int i;
-
- ctx->image_height = height;
- ctx->image_width = width;
- ctx->image_format = format;
-
- if ((ctx->max_width != 0 && ctx->max_height != 0)
- && (ctx->image_width > ctx->max_width
- || ctx->image_height > ctx->max_height)) {
- mp_tmsg(MSGT_VO, MSGL_ERR, "Source image dimensions are too high: %ux%u (maximum is %ux%u)\n",
- ctx->image_width, ctx->image_height, ctx->max_width,
- ctx->max_height);
- return -1;
- }
-
- ctx->visible_buf = -1;
- ctx->have_image_copy = false;
-
- /* check image formats */
- ctx->xv_format = 0;
- for (i = 0; i < ctx->formats; i++) {
- mp_msg(MSGT_VO, MSGL_V, "Xvideo image format: 0x%x (%4.4s) %s\n",
- ctx->fo[i].id, (char *) &ctx->fo[i].id,
- (ctx->fo[i].format == XvPacked) ? "packed" : "planar");
- if (ctx->fo[i].id == format)
- ctx->xv_format = ctx->fo[i].id;
- }
- if (!ctx->xv_format)
- return -1;
-
- {
-#ifdef CONFIG_XF86VM
- int vm = flags & VOFLAG_MODESWITCHING;
- if (vm) {
- vo_vm_switch(vo);
- ctx->mode_switched = 1;
- }
-#endif
- XGetWindowAttributes(x11->display, DefaultRootWindow(x11->display),
- &attribs);
- depth = attribs.depth;
- if (depth != 15 && depth != 16 && depth != 24 && depth != 32)
- depth = 24;
- XMatchVisualInfo(x11->display, x11->screen, depth, TrueColor, &vinfo);
-
- xswa.border_pixel = 0;
- xswamask = CWBorderPixel;
- if (x11->xv_ck_info.method == CK_METHOD_BACKGROUND) {
- xswa.background_pixel = x11->xv_colorkey;
- xswamask |= CWBackPixel;
- }
-
- vo_x11_create_vo_window(vo, &vinfo, vo->dx, vo->dy, vo->dwidth,
- vo->dheight, flags, CopyFromParent, "xv");
- XChangeWindowAttributes(x11->display, x11->window, xswamask, &xswa);
-
-#ifdef CONFIG_XF86VM
- if (vm) {
- /* Grab the mouse pointer in our window */
- if (vo_grabpointer)
- XGrabPointer(x11->display, x11->window, True, 0, GrabModeAsync,
- GrabModeAsync, x11->window, None, CurrentTime);
- XSetInputFocus(x11->display, x11->window, RevertToNone,
- CurrentTime);
- }
-#endif
- }
-
- mp_msg(MSGT_VO, MSGL_V, "using Xvideo port %d for hw scaling\n",
- x11->xv_port);
-
- // In case config has been called before
- for (i = 0; i < ctx->total_buffers; i++)
- deallocate_xvimage(vo, i);
-
- ctx->num_buffers = 2;
- ctx->total_buffers = ctx->num_buffers + 1;
-
- for (i = 0; i < ctx->total_buffers; i++)
- allocate_xvimage(vo, i);
-
- ctx->current_buf = 0;
- ctx->current_ip_buf = 0;
-
-
- resize(vo);
-
- return 0;
-}
-
-static void allocate_xvimage(struct vo *vo, int foo)
-{
- struct xvctx *ctx = vo->priv;
- struct vo_x11_state *x11 = vo->x11;
- /*
- * allocate XvImages. FIXME: no error checking, without
- * mit-shm this will bomb... trzing to fix ::atmos
- */
-#ifdef HAVE_SHM
- if (x11->display_is_local && XShmQueryExtension(x11->display))
- ctx->Shmem_Flag = 1;
- else {
- ctx->Shmem_Flag = 0;
- mp_tmsg(MSGT_VO, MSGL_INFO, "[VO_XV] Shared memory not supported\nReverting to normal Xv.\n");
- }
- if (ctx->Shmem_Flag) {
- ctx->xvimage[foo] =
- (XvImage *) XvShmCreateImage(x11->display, x11->xv_port,
- ctx->xv_format, NULL,
- ctx->image_width, ctx->image_height,
- &ctx->Shminfo[foo]);
-
- ctx->Shminfo[foo].shmid = shmget(IPC_PRIVATE,
- ctx->xvimage[foo]->data_size,
- IPC_CREAT | 0777);
- ctx->Shminfo[foo].shmaddr = (char *) shmat(ctx->Shminfo[foo].shmid, 0,
- 0);
- ctx->Shminfo[foo].readOnly = False;
-
- ctx->xvimage[foo]->data = ctx->Shminfo[foo].shmaddr;
- XShmAttach(x11->display, &ctx->Shminfo[foo]);
- XSync(x11->display, False);
- shmctl(ctx->Shminfo[foo].shmid, IPC_RMID, 0);
- } else
-#endif
- {
- ctx->xvimage[foo] =
- (XvImage *) XvCreateImage(x11->display, x11->xv_port,
- ctx->xv_format, NULL, ctx->image_width,
- ctx->image_height);
- ctx->xvimage[foo]->data = malloc(ctx->xvimage[foo]->data_size);
- XSync(x11->display, False);
- }
- memset(ctx->xvimage[foo]->data, 128, ctx->xvimage[foo]->data_size);
- return;
-}
-
-static void deallocate_xvimage(struct vo *vo, int foo)
-{
- struct xvctx *ctx = vo->priv;
-#ifdef HAVE_SHM
- if (ctx->Shmem_Flag) {
- XShmDetach(vo->x11->display, &ctx->Shminfo[foo]);
- shmdt(ctx->Shminfo[foo].shmaddr);
- } else
-#endif
- {
- free(ctx->xvimage[foo]->data);
- }
- XFree(ctx->xvimage[foo]);
-
- XSync(vo->x11->display, False);
- return;
-}
-
-static inline void put_xvimage(struct vo *vo, XvImage *xvi)
-{
- struct xvctx *ctx = vo->priv;
- struct vo_x11_state *x11 = vo->x11;
- struct mp_rect *src = &ctx->src_rect;
- struct mp_rect *dst = &ctx->dst_rect;
- int dw = dst->x1 - dst->x0, dh = dst->y1 - dst->y0;
- int sw = src->x1 - src->x0, sh = src->y1 - src->y0;
-#ifdef HAVE_SHM
- if (ctx->Shmem_Flag) {
- XvShmPutImage(x11->display, x11->xv_port, x11->window, x11->vo_gc, xvi,
- src->x0, src->y0, sw, sh,
- dst->x0, dst->y0, dw, dh,
- False);
- } else
-#endif
- {
- XvPutImage(x11->display, x11->xv_port, x11->window, x11->vo_gc, xvi,
- src->x0, src->y0, sw, sh,
- dst->x0, dst->y0, dw, dh);
- }
-}
-
-static struct mp_image get_xv_buffer(struct vo *vo, int buf_index)
-{
- struct xvctx *ctx = vo->priv;
- XvImage *xv_image = ctx->xvimage[buf_index];
-
- struct mp_image img = {0};
- img.w = img.width = xv_image->width;
- img.h = img.height = xv_image->height;
- mp_image_setfmt(&img, ctx->image_format);
-
- bool swapuv = ctx->image_format == IMGFMT_YV12;
- for (int n = 0; n < img.num_planes; n++) {
- int sn = n > 0 && swapuv ? (n == 1 ? 2 : 1) : n;
- img.planes[n] = xv_image->data + xv_image->offsets[sn];
- img.stride[n] = xv_image->pitches[sn];
- }
-
- mp_image_set_colorspace_details(&img, &ctx->cached_csp);
-
- return img;
-}
-
-static void copy_backup_image(struct vo *vo, int dest, int src)
-{
- struct mp_image img_dest = get_xv_buffer(vo, dest);
- struct mp_image img_src = get_xv_buffer(vo, src);
-
- copy_mpi(&img_dest, &img_src);
-}
-
-static void check_events(struct vo *vo)
-{
- int e = vo_x11_check_events(vo);
-
- if (e & VO_EVENT_EXPOSE || e & VO_EVENT_RESIZE) {
- resize(vo);
- vo->want_redraw = true;
- }
-}
-
-static void draw_osd(struct vo *vo, struct osd_state *osd)
-{
- struct xvctx *ctx = vo->priv;
-
- struct mp_image img = get_xv_buffer(vo, ctx->current_buf);
-
- struct mp_rect *src = &ctx->src_rect;
- struct mp_rect *dst = &ctx->dst_rect;
- int dw = dst->x1 - dst->x0, dh = dst->y1 - dst->y0;
- int sw = src->x1 - src->x0, sh = src->y1 - src->y0;
- double xvpar = (double)dw / dh * sh / sw;
-
- struct mp_osd_res res = {
- .w = ctx->image_width,
- .h = ctx->image_height,
- .display_par = vo->monitor_par / xvpar,
- .video_par = vo->aspdat.par,
- };
-
- if (osd_draw_on_image(osd, res, osd->vo_pts, 0, &img))
- ctx->unchanged_image = false;
-}
-
-static int redraw_frame(struct vo *vo)
-{
- struct xvctx *ctx = vo->priv;
-
- if (ctx->have_image_copy)
- copy_backup_image(vo, ctx->visible_buf, ctx->num_buffers);
- else if (ctx->unchanged_image) {
- copy_backup_image(vo, ctx->num_buffers, ctx->visible_buf);
- ctx->have_image_copy = true;
- } else
- return false;
- ctx->current_buf = ctx->visible_buf;
- return true;
-}
-
-static void flip_page(struct vo *vo)
-{
- struct xvctx *ctx = vo->priv;
- put_xvimage(vo, ctx->xvimage[ctx->current_buf]);
-
- /* remember the currently visible buffer */
- ctx->visible_buf = ctx->current_buf;
-
- ctx->current_buf = (ctx->current_buf + 1) % ctx->num_buffers;
- XFlush(vo->x11->display);
- return;
-}
-
-static int draw_slice(struct vo *vo, uint8_t *image[], int stride[], int w,
- int h, int x, int y)
-{
- struct xvctx *ctx = vo->priv;
- uint8_t *dst;
- XvImage *current_image = ctx->xvimage[ctx->current_buf];
-
- dst = current_image->data + current_image->offsets[0]
- + current_image->pitches[0] * y + x;
- memcpy_pic(dst, image[0], w, h, current_image->pitches[0], stride[0]);
-
- x /= 2;
- y /= 2;
- w /= 2;
- h /= 2;
-
- dst = current_image->data + current_image->offsets[1]
- + current_image->pitches[1] * y + x;
- if (ctx->image_format != IMGFMT_YV12)
- memcpy_pic(dst, image[1], w, h, current_image->pitches[1], stride[1]);
- else
- memcpy_pic(dst, image[2], w, h, current_image->pitches[1], stride[2]);
-
- dst = current_image->data + current_image->offsets[2]
- + current_image->pitches[2] * y + x;
- if (ctx->image_format == IMGFMT_YV12)
- memcpy_pic(dst, image[1], w, h, current_image->pitches[1], stride[1]);
- else
- memcpy_pic(dst, image[2], w, h, current_image->pitches[1], stride[2]);
-
- return 0;
-}
-
-static mp_image_t *get_screenshot(struct vo *vo)
-{
- struct xvctx *ctx = vo->priv;
-
- // try to get an image without OSD
- int id = ctx->have_image_copy ? ctx->num_buffers : ctx->visible_buf;
- struct mp_image img = get_xv_buffer(vo, id);
- img.display_w = vo->aspdat.prew;
- img.display_h = vo->aspdat.preh;
-
- return talloc_memdup(NULL, &img, sizeof(img));
-}
-
-static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
-{
- struct xvctx *ctx = vo->priv;
-
- ctx->have_image_copy = false;
-
- if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
- ; // done
- else if (mpi->flags & MP_IMGFLAG_PLANAR)
- draw_slice(vo, mpi->planes, mpi->stride, mpi->w, mpi->h, 0, 0);
- else if (mpi->flags & MP_IMGFLAG_YUV)
- // packed YUV:
- memcpy_pic(ctx->xvimage[ctx->current_buf]->data +
- ctx->xvimage[ctx->current_buf]->offsets[0], mpi->planes[0],
- mpi->w * (mpi->bpp / 8), mpi->h,
- ctx->xvimage[ctx->current_buf]->pitches[0], mpi->stride[0]);
- else
- return false;
-
- if (ctx->is_paused) {
- copy_backup_image(vo, ctx->num_buffers, ctx->current_buf);
- ctx->have_image_copy = true;
- }
- ctx->unchanged_image = true;
- return true;
-}
-
-static int query_format(struct xvctx *ctx, uint32_t format)
-{
- uint32_t i;
- int flag = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_OSD | VFCAP_ACCEPT_STRIDE; // FIXME! check for DOWN
-
- /* check image formats */
- for (i = 0; i < ctx->formats; i++) {
- if (ctx->fo[i].id == format)
- return flag; //xv_format = fo[i].id;
- }
- return 0;
-}
-
-static void uninit(struct vo *vo)
-{
- struct xvctx *ctx = vo->priv;
- int i;
-
- ctx->visible_buf = -1;
- if (ctx->ai)
- XvFreeAdaptorInfo(ctx->ai);
- ctx->ai = NULL;
- if (ctx->fo) {
- XFree(ctx->fo);
- ctx->fo = NULL;
- }
- for (i = 0; i < ctx->total_buffers; i++)
- deallocate_xvimage(vo, i);
-#ifdef CONFIG_XF86VM
- if (ctx->mode_switched)
- vo_vm_close(vo);
-#endif
- // uninit() shouldn't get called unless initialization went past vo_init()
- vo_x11_uninit(vo);
-}
-
-static int preinit(struct vo *vo, const char *arg)
-{
- XvPortID xv_p;
- int busy_ports = 0;
- unsigned int i;
- strarg_t ck_src_arg = { 0, NULL };
- strarg_t ck_method_arg = { 0, NULL };
- struct xvctx *ctx = talloc_zero(vo, struct xvctx);
- vo->priv = ctx;
- int xv_adaptor = -1;
-
- if (!vo_init(vo))
- return -1;
-
- struct vo_x11_state *x11 = vo->x11;
-
- const opt_t subopts[] =
- {
- /* name arg type arg var test */
- { "port", OPT_ARG_INT, &x11->xv_port, int_pos },
- { "adaptor", OPT_ARG_INT, &xv_adaptor, int_non_neg },
- { "ck", OPT_ARG_STR, &ck_src_arg, xv_test_ck },
- { "ck-method", OPT_ARG_STR, &ck_method_arg, xv_test_ckm },
- { NULL }
- };
-
- x11->xv_port = 0;
-
- /* parse suboptions */
- if (subopt_parse(arg, subopts) != 0) {
- return -1;
- }
-
- /* modify colorkey settings according to the given options */
- xv_setup_colorkeyhandling(vo, ck_method_arg.str, ck_src_arg.str);
-
- /* check for Xvideo extension */
- unsigned int ver, rel, req, ev, err;
- if (Success != XvQueryExtension(x11->display, &ver, &rel, &req, &ev, &err)) {
- mp_tmsg(MSGT_VO, MSGL_ERR, "[VO_XV] Sorry, Xv not supported by this X11 version/driver\n[VO_XV] ******** Try with -vo x11 *********\n");
- goto error;
- }
-
- /* check for Xvideo support */
- if (Success !=
- XvQueryAdaptors(x11->display, DefaultRootWindow(x11->display),
- &ctx->adaptors, &ctx->ai)) {
- mp_tmsg(MSGT_VO, MSGL_ERR, "[VO_XV] XvQueryAdaptors failed.\n");
- goto error;
- }
-
- /* check adaptors */
- if (x11->xv_port) {
- int port_found;
-
- for (port_found = 0, i = 0; !port_found && i < ctx->adaptors; i++) {
- if ((ctx->ai[i].type & XvInputMask)
- && (ctx->ai[i].type & XvImageMask)) {
- for (xv_p = ctx->ai[i].base_id;
- xv_p < ctx->ai[i].base_id + ctx->ai[i].num_ports;
- ++xv_p) {
- if (xv_p == x11->xv_port) {
- port_found = 1;
- break;
- }
- }
- }
- }
- if (port_found) {
- if (XvGrabPort(x11->display, x11->xv_port, CurrentTime))
- x11->xv_port = 0;
- } else {
- mp_tmsg(MSGT_VO, MSGL_WARN, "[VO_XV] Invalid port parameter, overriding with port 0.\n");
- x11->xv_port = 0;
- }
- }
-
- for (i = 0; i < ctx->adaptors && x11->xv_port == 0; i++) {
- /* check if adaptor number has been specified */
- if (xv_adaptor != -1 && xv_adaptor != i)
- continue;
-
- if ((ctx->ai[i].type & XvInputMask) && (ctx->ai[i].type & XvImageMask)) {
- for (xv_p = ctx->ai[i].base_id;
- xv_p < ctx->ai[i].base_id + ctx->ai[i].num_ports; ++xv_p)
- if (!XvGrabPort(x11->display, xv_p, CurrentTime)) {
- x11->xv_port = xv_p;
- mp_msg(MSGT_VO, MSGL_V,
- "[VO_XV] Using Xv Adapter #%d (%s)\n",
- i, ctx->ai[i].name);
- break;
- } else {
- mp_tmsg(MSGT_VO, MSGL_WARN, "[VO_XV] Could not grab port %i.\n",
- (int) xv_p);
- ++busy_ports;
- }
- }
- }
- if (!x11->xv_port) {
- if (busy_ports)
- mp_tmsg(MSGT_VO, MSGL_ERR,
- "[VO_XV] Could not find free Xvideo port - maybe another process is already\n"\
- "[VO_XV] using it. Close all video applications, and try again. If that does\n"\
- "[VO_XV] not help, see 'mpv -vo help' for other (non-xv) video out drivers.\n");
- else
- mp_tmsg(MSGT_VO, MSGL_ERR,
- "[VO_XV] It seems there is no Xvideo support for your video card available.\n"\
- "[VO_XV] Run 'xvinfo' to verify its Xv support and read\n"\
- "[VO_XV] DOCS/HTML/en/video.html#xv!\n"\
- "[VO_XV] See 'mpv -vo help' for other (non-xv) video out drivers.\n"\
- "[VO_XV] Try -vo x11.\n");
- goto error;
- }
-
- if (!vo_xv_init_colorkey(vo)) {
- goto error; // bail out, colorkey setup failed
- }
- vo_xv_enable_vsync(vo);
- vo_xv_get_max_img_dim(vo, &ctx->max_width, &ctx->max_height);
-
- ctx->fo = XvListImageFormats(x11->display, x11->xv_port,
- (int *) &ctx->formats);
-
- return 0;
-
- error:
- uninit(vo); // free resources
- return -1;
-}
-
-static int control(struct vo *vo, uint32_t request, void *data)
-{
- struct xvctx *ctx = vo->priv;
- struct vo_x11_state *x11 = vo->x11;
- switch (request) {
- case VOCTRL_PAUSE:
- return (ctx->is_paused = 1);
- case VOCTRL_RESUME:
- return (ctx->is_paused = 0);
- case VOCTRL_QUERY_FORMAT:
- return query_format(ctx, *((uint32_t *) data));
- case VOCTRL_DRAW_IMAGE:
- return draw_image(vo, data);
- case VOCTRL_GET_PANSCAN:
- return VO_TRUE;
- case VOCTRL_FULLSCREEN:
- vo_x11_fullscreen(vo);
- /* indended, fallthrough to update panscan on fullscreen/windowed switch */
- case VOCTRL_SET_PANSCAN:
- resize(vo);
- return VO_TRUE;
- case VOCTRL_SET_EQUALIZER: {
- vo->want_redraw = true;
- struct voctrl_set_equalizer_args *args = data;
- return vo_xv_set_eq(vo, x11->xv_port, args->name, args->value);
- }
- case VOCTRL_GET_EQUALIZER: {
- struct voctrl_get_equalizer_args *args = data;
- return vo_xv_get_eq(vo, x11->xv_port, args->name, args->valueptr);
- }
- case VOCTRL_SET_YUV_COLORSPACE:;
- struct mp_csp_details* given_cspc = data;
- int is_709 = given_cspc->format == MP_CSP_BT_709;
- vo_xv_set_eq(vo, x11->xv_port, "bt_709", is_709 * 200 - 100);
- read_xv_csp(vo);
- vo->want_redraw = true;
- return true;
- case VOCTRL_GET_YUV_COLORSPACE:;
- struct mp_csp_details* cspc = data;
- read_xv_csp(vo);
- *cspc = ctx->cached_csp;
- return true;
- case VOCTRL_ONTOP:
- vo_x11_ontop(vo);
- return VO_TRUE;
- case VOCTRL_UPDATE_SCREENINFO:
- update_xinerama_info(vo);
- return VO_TRUE;
- case VOCTRL_REDRAW_FRAME:
- return redraw_frame(vo);
- case VOCTRL_SCREENSHOT: {
- struct voctrl_screenshot_args *args = data;
- args->out_image = get_screenshot(vo);
- args->has_osd = !ctx->have_image_copy;
- return true;
- }
- }
- return VO_NOTIMPL;
-}
-
-const struct vo_driver video_out_xv = {
- .is_new = 1,
- .info = &info,
- .preinit = preinit,
- .config = config,
- .control = control,
- .draw_slice = draw_slice,
- .draw_osd = draw_osd,
- .flip_page = flip_page,
- .check_events = check_events,
- .uninit = uninit
-};
diff --git a/libvo/w32_common.c b/libvo/w32_common.c
deleted file mode 100644
index f60f5328de..0000000000
--- a/libvo/w32_common.c
+++ /dev/null
@@ -1,757 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <limits.h>
-#include <assert.h>
-#include <windows.h>
-#include <windowsx.h>
-
-#include "options.h"
-#include "input/keycodes.h"
-#include "input/input.h"
-#include "mp_msg.h"
-#include "video_out.h"
-#include "aspect.h"
-#include "w32_common.h"
-#include "mp_fifo.h"
-#include "osdep/io.h"
-#include "talloc.h"
-
-#define WIN_ID_TO_HWND(x) ((HWND)(uint32_t)(x))
-
-static const wchar_t classname[] = L"mpv";
-
-static const struct mp_keymap vk_map[] = {
- // special keys
- {VK_ESCAPE, KEY_ESC}, {VK_BACK, KEY_BS}, {VK_TAB, KEY_TAB},
- {VK_RETURN, KEY_ENTER}, {VK_PAUSE, KEY_PAUSE}, {VK_SNAPSHOT, KEY_PRINT},
-
- // cursor keys
- {VK_LEFT, KEY_LEFT}, {VK_UP, KEY_UP}, {VK_RIGHT, KEY_RIGHT}, {VK_DOWN, KEY_DOWN},
-
- // navigation block
- {VK_INSERT, KEY_INSERT}, {VK_DELETE, KEY_DELETE}, {VK_HOME, KEY_HOME}, {VK_END, KEY_END},
- {VK_PRIOR, KEY_PAGE_UP}, {VK_NEXT, KEY_PAGE_DOWN},
-
- // F-keys
- {VK_F1, KEY_F+1}, {VK_F2, KEY_F+2}, {VK_F3, KEY_F+3}, {VK_F4, KEY_F+4},
- {VK_F5, KEY_F+5}, {VK_F6, KEY_F+6}, {VK_F7, KEY_F+7}, {VK_F8, KEY_F+8},
- {VK_F9, KEY_F+9}, {VK_F10, KEY_F+10}, {VK_F11, KEY_F+11}, {VK_F12, KEY_F+12},
- // numpad
- {VK_NUMPAD0, KEY_KP0}, {VK_NUMPAD1, KEY_KP1}, {VK_NUMPAD2, KEY_KP2},
- {VK_NUMPAD3, KEY_KP3}, {VK_NUMPAD4, KEY_KP4}, {VK_NUMPAD5, KEY_KP5},
- {VK_NUMPAD6, KEY_KP6}, {VK_NUMPAD7, KEY_KP7}, {VK_NUMPAD8, KEY_KP8},
- {VK_NUMPAD9, KEY_KP9}, {VK_DECIMAL, KEY_KPDEC},
-
- {0, 0}
-};
-
-static void add_window_borders(HWND hwnd, RECT *rc)
-{
- AdjustWindowRect(rc, GetWindowLong(hwnd, GWL_STYLE), 0);
-}
-
-// basically a reverse AdjustWindowRect (win32 doesn't appear to have this)
-static void subtract_window_borders(HWND hwnd, RECT *rc)
-{
- RECT b = { 0, 0, 0, 0 };
- add_window_borders(hwnd, &b);
- rc->left -= b.left;
- rc->top -= b.top;
- rc->right -= b.right;
- rc->bottom -= b.bottom;
-}
-
-// turn a WMSZ_* input value in v into the border that should be resized
-// returns: 0=left, 1=top, 2=right, 3=bottom, -1=undefined
-static int get_resize_border(int v) {
- switch (v) {
- case WMSZ_LEFT: return 3;
- case WMSZ_TOP: return 2;
- case WMSZ_RIGHT: return 3;
- case WMSZ_BOTTOM: return 2;
- case WMSZ_TOPLEFT: return 1;
- case WMSZ_TOPRIGHT: return 1;
- case WMSZ_BOTTOMLEFT: return 3;
- case WMSZ_BOTTOMRIGHT: return 3;
- default: return -1;
- }
-}
-
-static bool key_state(struct vo *vo, int vk)
-{
- return GetKeyState(vk) & 0x8000;
-}
-
-static int mod_state(struct vo *vo)
-{
- int res = 0;
- if (key_state(vo, VK_CONTROL))
- res |= KEY_MODIFIER_CTRL;
- if (key_state(vo, VK_SHIFT))
- res |= KEY_MODIFIER_SHIFT;
- if (key_state(vo, VK_MENU))
- res |= KEY_MODIFIER_ALT;
- return res;
-}
-
-static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
- LPARAM lParam)
-{
- if (message == WM_NCCREATE) {
- CREATESTRUCT *cs = (void*)lParam;
- SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)cs->lpCreateParams);
- }
- struct vo *vo = (void*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
- // message before WM_NCCREATE, pray to Raymond Chen that it's not important
- if (!vo)
- return DefWindowProcW(hWnd, message, wParam, lParam);
- struct vo_w32_state *w32 = vo->w32;
-
- switch (message) {
- case WM_ERASEBKGND: // no need to erase background seperately
- return 1;
- case WM_PAINT:
- w32->event_flags |= VO_EVENT_EXPOSE;
- break;
- case WM_MOVE: {
- w32->event_flags |= VO_EVENT_MOVE;
- POINT p = {0};
- ClientToScreen(w32->window, &p);
- w32->window_x = p.x;
- w32->window_y = p.y;
- mp_msg(MSGT_VO, MSGL_V, "[vo] move window: %d:%d\n",
- w32->window_x, w32->window_y);
- break;
- }
- case WM_SIZE: {
- w32->event_flags |= VO_EVENT_RESIZE;
- RECT r;
- GetClientRect(w32->window, &r);
- vo->dwidth = r.right;
- vo->dheight = r.bottom;
- mp_msg(MSGT_VO, MSGL_V, "[vo] resize window: %d:%d\n",
- vo->dwidth, vo->dheight);
- break;
- }
- case WM_SIZING:
- if (vo_keepaspect && !vo_fs && WinID < 0) {
- RECT *rc = (RECT*)lParam;
- // get client area of the windows if it had the rect rc
- // (subtracting the window borders)
- RECT r = *rc;
- subtract_window_borders(w32->window, &r);
- int c_w = r.right - r.left, c_h = r.bottom - r.top;
- float aspect = vo->aspdat.asp;
- int d_w = c_h * aspect - c_w;
- int d_h = c_w / aspect - c_h;
- int d_corners[4] = { d_w, d_h, -d_w, -d_h };
- int corners[4] = { rc->left, rc->top, rc->right, rc->bottom };
- int corner = get_resize_border(wParam);
- if (corner >= 0)
- corners[corner] -= d_corners[corner];
- *rc = (RECT) { corners[0], corners[1], corners[2], corners[3] };
- return TRUE;
- }
- break;
- case WM_CLOSE:
- mplayer_put_key(vo->key_fifo, KEY_CLOSE_WIN);
- break;
- case WM_SYSCOMMAND:
- switch (wParam) {
- case SC_SCREENSAVE:
- case SC_MONITORPOWER:
- mp_msg(MSGT_VO, MSGL_V, "vo: win32: killing screensaver\n");
- return 0;
- }
- break;
- case WM_KEYDOWN:
- case WM_SYSKEYDOWN: {
- int mpkey = lookup_keymap_table(vk_map, wParam);
- if (mpkey)
- mplayer_put_key(vo->key_fifo, mpkey | mod_state(vo));
- if (wParam == VK_F10)
- return 0;
- break;
- }
- case WM_CHAR:
- case WM_SYSCHAR: {
- int mods = mod_state(vo);
- int code = wParam;
- // Windows enables Ctrl+Alt when AltGr (VK_RMENU) is pressed.
- // E.g. AltGr+9 on a German keyboard would yield Ctrl+Alt+[
- // Warning: wine handles this differently. Don't test this on wine!
- if (key_state(vo, VK_RMENU))
- mods &= ~(KEY_MODIFIER_CTRL | KEY_MODIFIER_ALT);
- // Apparently Ctrl+A to Ctrl+Z is special cased, and produces
- // character codes from 1-26. Work it around.
- // Also, enter/return (including the keypad variant) and CTRL+J both
- // map to wParam==10. As a workaround, check VK_RETURN to
- // distinguish these two key combinations.
- if ((mods & KEY_MODIFIER_CTRL) && code >= 1 && code <= 26
- && !key_state(vo, VK_RETURN))
- code = code - 1 + (mods & KEY_MODIFIER_SHIFT ? 'A' : 'a');
- if (code >= 32 && code < (1<<21)) {
- mplayer_put_key(vo->key_fifo, code | mods);
- // At least with Alt+char, not calling DefWindowProcW stops
- // Windows from emitting a beep.
- return 0;
- }
- break;
- }
- case WM_LBUTTONDOWN:
- if (!vo_nomouse_input && (vo_fs || (wParam & MK_CONTROL))) {
- mplayer_put_key(vo->key_fifo, MOUSE_BTN0 | mod_state(vo));
- break;
- }
- if (!vo_fs) {
- ReleaseCapture();
- SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
- return 0;
- }
- break;
- case WM_MBUTTONDOWN:
- if (!vo_nomouse_input)
- mplayer_put_key(vo->key_fifo, MOUSE_BTN1 | mod_state(vo));
- break;
- case WM_RBUTTONDOWN:
- if (!vo_nomouse_input)
- mplayer_put_key(vo->key_fifo, MOUSE_BTN2 | mod_state(vo));
- break;
- case WM_MOUSEMOVE:
- vo_mouse_movement(vo, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- break;
- case WM_MOUSEWHEEL:
- if (!vo_nomouse_input) {
- int x = GET_WHEEL_DELTA_WPARAM(wParam);
- if (x > 0)
- mplayer_put_key(vo->key_fifo, MOUSE_BTN3 | mod_state(vo));
- else
- mplayer_put_key(vo->key_fifo, MOUSE_BTN4 | mod_state(vo));
- }
- break;
- case WM_XBUTTONDOWN:
- if (!vo_nomouse_input) {
- int x = HIWORD(wParam);
- if (x == 1)
- mplayer_put_key(vo->key_fifo, MOUSE_BTN5 | mod_state(vo));
- else // if (x == 2)
- mplayer_put_key(vo->key_fifo, MOUSE_BTN6 | mod_state(vo));
- }
- break;
- }
-
- return DefWindowProcW(hWnd, message, wParam, lParam);
-}
-
-/**
- * \brief Dispatch incoming window events and handle them.
- *
- * This function should be placed inside libvo's function "check_events".
- *
- * \return int with these flags possibly set, take care to handle in the right order
- * if it matters in your driver:
- *
- * VO_EVENT_RESIZE = The window was resized. If necessary reinit your
- * driver render context accordingly.
- * VO_EVENT_EXPOSE = The window was exposed. Call e.g. flip_frame() to redraw
- * the window if the movie is paused.
- */
-int vo_w32_check_events(struct vo *vo)
-{
- struct vo_w32_state *w32 = vo->w32;
- MSG msg;
- w32->event_flags = 0;
- while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) {
- TranslateMessage(&msg);
- DispatchMessageW(&msg);
- }
- if (WinID >= 0) {
- BOOL res;
- RECT r;
- POINT p;
- res = GetClientRect(w32->window, &r);
- if (res && (r.right != vo->dwidth || r.bottom != vo->dheight)) {
- vo->dwidth = r.right; vo->dheight = r.bottom;
- w32->event_flags |= VO_EVENT_RESIZE;
- }
- p.x = 0; p.y = 0;
- ClientToScreen(w32->window, &p);
- if (p.x != w32->window_x || p.y != w32->window_y) {
- w32->window_x = p.x; w32->window_y = p.y;
- w32->event_flags |= VO_EVENT_MOVE;
- }
- res = GetClientRect(WIN_ID_TO_HWND(WinID), &r);
- if (res && (r.right != vo->dwidth || r.bottom != vo->dheight))
- MoveWindow(w32->window, 0, 0, r.right, r.bottom, FALSE);
- if (!IsWindow(WIN_ID_TO_HWND(WinID)))
- // Window has probably been closed, e.g. due to program crash
- mplayer_put_key(vo->key_fifo, KEY_CLOSE_WIN);
- }
-
- return w32->event_flags;
-}
-
-static BOOL CALLBACK mon_enum(HMONITOR hmon, HDC hdc, LPRECT r, LPARAM p)
-{
- struct vo *vo = (void*)p;
- struct vo_w32_state *w32 = vo->w32;
- // this defaults to the last screen if specified number does not exist
- xinerama_x = r->left;
- xinerama_y = r->top;
- vo->opts->vo_screenwidth = r->right - r->left;
- vo->opts->vo_screenheight = r->bottom - r->top;
- if (w32->mon_cnt == xinerama_screen)
- return FALSE;
- w32->mon_cnt++;
- return TRUE;
-}
-
-/**
- * \brief Update screen information.
- *
- * This function should be called in libvo's "control" callback
- * with parameter VOCTRL_UPDATE_SCREENINFO.
- * Note that this also enables the new API where geometry and aspect
- * calculations are done in video_out.c:config_video_out
- *
- * Global libvo variables changed:
- * xinerama_x
- * xinerama_y
- * vo_screenwidth
- * vo_screenheight
- */
-void w32_update_xinerama_info(struct vo *vo)
-{
- struct vo_w32_state *w32 = vo->w32;
- xinerama_x = xinerama_y = 0;
- if (xinerama_screen < -1) {
- int tmp;
- xinerama_x = GetSystemMetrics(SM_XVIRTUALSCREEN);
- xinerama_y = GetSystemMetrics(SM_YVIRTUALSCREEN);
- tmp = GetSystemMetrics(SM_CXVIRTUALSCREEN);
- if (tmp) vo->opts->vo_screenwidth = tmp;
- tmp = GetSystemMetrics(SM_CYVIRTUALSCREEN);
- if (tmp) vo->opts->vo_screenheight = tmp;
- } else if (xinerama_screen == -1) {
- MONITORINFO mi;
- HMONITOR m = MonitorFromWindow(w32->window, MONITOR_DEFAULTTOPRIMARY);
- mi.cbSize = sizeof(mi);
- GetMonitorInfoW(m, &mi);
- xinerama_x = mi.rcMonitor.left;
- xinerama_y = mi.rcMonitor.top;
- vo->opts->vo_screenwidth = mi.rcMonitor.right - mi.rcMonitor.left;
- vo->opts->vo_screenheight = mi.rcMonitor.bottom - mi.rcMonitor.top;
- } else if (xinerama_screen > 0) {
- w32->mon_cnt = 0;
- EnumDisplayMonitors(NULL, NULL, mon_enum, (LONG_PTR)vo);
- }
- aspect_save_screenres(vo, vo->opts->vo_screenwidth,
- vo->opts->vo_screenheight);
-}
-
-static void updateScreenProperties(struct vo *vo)
-{
- struct vo_w32_state *w32 = vo->w32;
- DEVMODE dm;
- dm.dmSize = sizeof dm;
- dm.dmDriverExtra = 0;
- dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
- if (!EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &dm)) {
- mp_msg(MSGT_VO, MSGL_ERR,
- "vo: win32: unable to enumerate display settings!\n");
- return;
- }
-
- vo->opts->vo_screenwidth = dm.dmPelsWidth;
- vo->opts->vo_screenheight = dm.dmPelsHeight;
- w32->depthonscreen = dm.dmBitsPerPel;
- w32_update_xinerama_info(vo);
-}
-
-static void changeMode(struct vo *vo)
-{
- struct vo_w32_state *w32 = vo->w32;
- DEVMODE dm;
- dm.dmSize = sizeof dm;
- dm.dmDriverExtra = 0;
-
- dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
- dm.dmBitsPerPel = w32->depthonscreen;
- dm.dmPelsWidth = vo->opts->vo_screenwidth;
- dm.dmPelsHeight = vo->opts->vo_screenheight;
-
- if (w32->vm) {
- int bestMode = -1;
- int bestScore = INT_MAX;
- int i;
- for (i = 0; EnumDisplaySettings(0, i, &dm); ++i) {
- int score = (dm.dmPelsWidth - w32->o_dwidth)
- * (dm.dmPelsHeight - w32->o_dheight);
- if (dm.dmBitsPerPel != w32->depthonscreen
- || dm.dmPelsWidth < w32->o_dwidth
- || dm.dmPelsHeight < w32->o_dheight)
- continue;
-
- if (score < bestScore) {
- bestScore = score;
- bestMode = i;
- }
- }
-
- if (bestMode != -1)
- EnumDisplaySettings(0, bestMode, &dm);
-
- ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
- }
-}
-
-static void resetMode(struct vo *vo)
-{
- struct vo_w32_state *w32 = vo->w32;
- if (w32->vm)
- ChangeDisplaySettings(0, 0);
-}
-
-static DWORD update_style(struct vo *vo, DWORD style)
-{
- const DWORD NO_FRAME = WS_POPUP;
- const DWORD FRAME = WS_OVERLAPPEDWINDOW | WS_SIZEBOX;
- style &= ~(NO_FRAME | FRAME);
- style |= (vo_border && !vo_fs) ? FRAME : NO_FRAME;
- return style;
-}
-
-// Update the window title, position, size, and border style from vo_* values.
-static int reinit_window_state(struct vo *vo)
-{
- struct vo_w32_state *w32 = vo->w32;
- HWND layer = HWND_NOTOPMOST;
- RECT r;
-
- if (WinID >= 0)
- return 1;
-
- wchar_t *title = mp_from_utf8(NULL, vo_get_window_title(vo));
- SetWindowTextW(w32->window, title);
- talloc_free(title);
-
- bool toggle_fs = w32->current_fs != vo_fs;
- w32->current_fs = vo_fs;
-
- DWORD style = update_style(vo, GetWindowLong(w32->window, GWL_STYLE));
-
- if (vo_fs || vo->opts->vo_ontop)
- layer = HWND_TOPMOST;
-
- // xxx not sure if this can trigger any unwanted messages (WM_MOVE/WM_SIZE)
- if (vo_fs) {
- changeMode(vo);
- while (ShowCursor(0) >= 0) /**/ ;
- } else {
- resetMode(vo);
- while (ShowCursor(1) < 0) /**/ ;
- }
- updateScreenProperties(vo);
-
- if (vo_fs) {
- // Save window position and size when switching to fullscreen.
- if (toggle_fs) {
- w32->prev_width = vo->dwidth;
- w32->prev_height = vo->dheight;
- w32->prev_x = w32->window_x;
- w32->prev_y = w32->window_y;
- mp_msg(MSGT_VO, MSGL_V, "[vo] save window bounds: %d:%d:%d:%d\n",
- w32->prev_x, w32->prev_y, w32->prev_width, w32->prev_height);
- }
- vo->dwidth = vo->opts->vo_screenwidth;
- vo->dheight = vo->opts->vo_screenheight;
- w32->window_x = xinerama_x;
- w32->window_y = xinerama_y;
- } else {
- if (toggle_fs) {
- // Restore window position and size when switching from fullscreen.
- mp_msg(MSGT_VO, MSGL_V, "[vo] restore window bounds: %d:%d:%d:%d\n",
- w32->prev_x, w32->prev_y, w32->prev_width, w32->prev_height);
- vo->dwidth = w32->prev_width;
- vo->dheight = w32->prev_height;
- w32->window_x = w32->prev_x;
- w32->window_y = w32->prev_y;
- }
- }
-
- r.left = w32->window_x;
- r.right = r.left + vo->dwidth;
- r.top = w32->window_y;
- r.bottom = r.top + vo->dheight;
-
- SetWindowLong(w32->window, GWL_STYLE, style);
- add_window_borders(w32->window, &r);
-
- mp_msg(MSGT_VO, MSGL_V, "[vo] reset window bounds: %ld:%ld:%ld:%ld\n",
- r.left, r.top, r.right - r.left, r.bottom - r.top);
-
- SetWindowPos(w32->window, layer, r.left, r.top, r.right - r.left,
- r.bottom - r.top, SWP_FRAMECHANGED);
- // For some reason, moving SWP_SHOWWINDOW to a second call works better
- // with wine: returning from fullscreen doesn't cause a bogus resize to
- // screen size.
- // It's not needed on Windows XP or wine with a virtual desktop.
- // It doesn't seem to have any negative effects.
- SetWindowPos(w32->window, NULL, 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
-
- return 1;
-}
-
-/**
- * \brief Configure and show window on the screen.
- *
- * This function should be called in libvo's "config" callback.
- * It configures a window and shows it on the screen.
- *
- * \return 1 - Success, 0 - Failure
- */
-int vo_w32_config(struct vo *vo, uint32_t width, uint32_t height,
- uint32_t flags)
-{
- struct vo_w32_state *w32 = vo->w32;
- PIXELFORMATDESCRIPTOR pfd;
- int pf;
- HDC vo_hdc = vo_w32_get_dc(vo, w32->window);
-
- memset(&pfd, 0, sizeof pfd);
- pfd.nSize = sizeof pfd;
- pfd.nVersion = 1;
- pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
- if (flags & VOFLAG_STEREO)
- pfd.dwFlags |= PFD_STEREO;
- pfd.iPixelType = PFD_TYPE_RGBA;
- pfd.cColorBits = 24;
- pfd.iLayerType = PFD_MAIN_PLANE;
- pf = ChoosePixelFormat(vo_hdc, &pfd);
- if (!pf) {
- mp_msg(MSGT_VO, MSGL_ERR, "vo: win32: unable to select a valid pixel format!\n");
- vo_w32_release_dc(vo, w32->window, vo_hdc);
- return 0;
- }
-
- SetPixelFormat(vo_hdc, pf, &pfd);
- vo_w32_release_dc(vo, w32->window, vo_hdc);
-
- // we already have a fully initialized window, so nothing needs to be done
- if (flags & VOFLAG_HIDDEN)
- return 1;
-
- bool reset_size = !(w32->o_dwidth == width && w32->o_dheight == height);
-
- w32->o_dwidth = width;
- w32->o_dheight = height;
-
- // the desired size is ignored in wid mode, it always matches the window size.
- if (WinID < 0) {
- if (w32->window_bounds_initialized) {
- // restore vo_dwidth/vo_dheight, which are reset against our will
- // in vo_config()
- RECT r;
- GetClientRect(w32->window, &r);
- vo->dwidth = r.right;
- vo->dheight = r.bottom;
- } else {
- // first vo_config call; vo_config() will always set vo_dx/dy so
- // that the window is centered on the screen, and this is the only
- // time we actually want to use vo_dy/dy (this is not sane, and
- // video_out.h should provide a function to query the initial
- // window position instead)
- w32->window_bounds_initialized = true;
- reset_size = true;
- w32->window_x = w32->prev_x = vo->dx;
- w32->window_y = w32->prev_y = vo->dy;
- }
- if (reset_size) {
- w32->prev_width = vo->dwidth = width;
- w32->prev_height = vo->dheight = height;
- }
- }
-
- vo_fs = flags & VOFLAG_FULLSCREEN;
- w32->vm = flags & VOFLAG_MODESWITCHING;
- return reinit_window_state(vo);
-}
-
-/**
- * \brief Initialize w32_common framework.
- *
- * The first function that should be called from the w32_common framework.
- * It handles window creation on the screen with proper title and attributes.
- * It also initializes the framework's internal variables. The function should
- * be called after your own preinit initialization and you shouldn't do any
- * window management on your own.
- *
- * Global libvo variables changed:
- * vo_w32_window
- * vo_screenwidth
- * vo_screenheight
- *
- * \return 1 = Success, 0 = Failure
- */
-int vo_w32_init(struct vo *vo)
-{
- struct vo_w32_state *w32 = vo->w32;
- if (w32 && w32->window)
- return 1;
-
- if (!w32)
- w32 = vo->w32 = talloc_zero(vo, struct vo_w32_state);
-
- HINSTANCE hInstance = GetModuleHandleW(NULL);
-
- HICON mplayerIcon = LoadIconW(hInstance, L"IDI_ICON1");
-
- WNDCLASSEXW wcex = {
- .cbSize = sizeof wcex,
- .style = CS_OWNDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW,
- .lpfnWndProc = WndProc,
- .hInstance = hInstance,
- .hIcon = mplayerIcon,
- .hCursor = LoadCursor(0, IDC_ARROW),
- .lpszClassName = classname,
- .hIconSm = mplayerIcon,
- };
-
- if (!RegisterClassExW(&wcex)) {
- mp_msg(MSGT_VO, MSGL_ERR,
- "vo: win32: unable to register window class!\n");
- return 0;
- }
-
- if (WinID >= 0) {
- RECT r;
- GetClientRect(WIN_ID_TO_HWND(WinID), &r);
- vo->dwidth = r.right; vo->dheight = r.bottom;
- w32->window = CreateWindowExW(WS_EX_NOPARENTNOTIFY, classname,
- classname,
- WS_CHILD | WS_VISIBLE,
- 0, 0, vo->dwidth, vo->dheight,
- WIN_ID_TO_HWND(WinID), 0, hInstance, vo);
- } else {
- w32->window = CreateWindowExW(0, classname,
- classname,
- update_style(vo, 0),
- CW_USEDEFAULT, 0, 100, 100,
- 0, 0, hInstance, vo);
- }
-
- if (!w32->window) {
- mp_msg(MSGT_VO, MSGL_ERR, "vo: win32: unable to create window!\n");
- return 0;
- }
-
- if (WinID >= 0)
- EnableWindow(w32->window, 0);
-
- updateScreenProperties(vo);
-
- mp_msg(MSGT_VO, MSGL_V, "vo: win32: running at %dx%d with depth %d\n",
- vo->opts->vo_screenwidth, vo->opts->vo_screenheight,
- w32->depthonscreen);
-
- return 1;
-}
-
-/**
- * \brief Toogle fullscreen / windowed mode.
- *
- * Should be called on VOCTRL_FULLSCREEN event. The window is
- * always resized during this call, so the rendering context
- * should be reinitialized with the new dimensions.
- * It is unspecified if vo_check_events will create a resize
- * event in addition or not.
- */
-
-void vo_w32_fullscreen(struct vo *vo)
-{
- vo_fs = !vo_fs;
- reinit_window_state(vo);
-}
-
-/**
- * \brief Toogle window border attribute.
- *
- * Should be called on VOCTRL_BORDER event.
- */
-void vo_w32_border(struct vo *vo)
-{
- vo_border = !vo_border;
- reinit_window_state(vo);
-}
-
-/**
- * \brief Toogle window ontop attribute.
- *
- * Should be called on VOCTRL_ONTOP event.
- */
-void vo_w32_ontop(struct vo *vo)
-{
- vo->opts->vo_ontop = !vo->opts->vo_ontop;
- reinit_window_state(vo);
-}
-
-/**
- * \brief Uninitialize w32_common framework.
- *
- * Should be called last in video driver's uninit function. First release
- * anything built on top of the created window e.g. rendering context inside
- * and call vo_w32_uninit at the end.
- */
-void vo_w32_uninit(struct vo *vo)
-{
- struct vo_w32_state *w32 = vo->w32;
- mp_msg(MSGT_VO, MSGL_V, "vo: win32: uninit\n");
- if (!w32)
- return;
- resetMode(vo);
- ShowCursor(1);
- DestroyWindow(w32->window);
- UnregisterClassW(classname, 0);
- talloc_free(w32);
- vo->w32 = NULL;
-}
-
-/**
- * \brief get a device context to draw in
- *
- * \param wnd window the DC should belong to if it makes sense
- */
-HDC vo_w32_get_dc(struct vo *vo, HWND wnd)
-{
- struct vo_w32_state *w32 = vo->w32;
- return GetDC(wnd);
-}
-
-/**
- * \brief release a device context
- *
- * \param wnd window the DC probably belongs to
- */
-void vo_w32_release_dc(struct vo *vo, HWND wnd, HDC dc)
-{
- struct vo_w32_state *w32 = vo->w32;
- ReleaseDC(wnd, dc);
-}
diff --git a/libvo/w32_common.h b/libvo/w32_common.h
deleted file mode 100644
index c6d9fc7653..0000000000
--- a/libvo/w32_common.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_W32_COMMON_H
-#define MPLAYER_W32_COMMON_H
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <windows.h>
-
-struct vo_w32_state {
- HWND window;
-
- bool vm;
-
- int depthonscreen;
-
- // last non-fullscreen extends (updated only on fullscreen or on initialization)
- int prev_width;
- int prev_height;
- int prev_x;
- int prev_y;
-
- // whether the window position and size were intialized
- bool window_bounds_initialized;
-
- bool current_fs;
-
- int window_x;
- int window_y;
-
- // video size
- uint32_t o_dwidth;
- uint32_t o_dheight;
-
- int event_flags;
- int mon_cnt;
-};
-
-int vo_w32_init(struct vo *vo);
-void vo_w32_uninit(struct vo *vo);
-void vo_w32_ontop(struct vo *vo);
-void vo_w32_border(struct vo *vo);
-void vo_w32_fullscreen(struct vo *vo);
-int vo_w32_check_events(struct vo *vo);
-int vo_w32_config(struct vo *vo, uint32_t, uint32_t, uint32_t);
-void w32_update_xinerama_info(struct vo *vo);
-HDC vo_w32_get_dc(struct vo *vo, HWND wnd);
-void vo_w32_release_dc(struct vo *vo, HWND wnd, HDC dc);
-
-#endif /* MPLAYER_W32_COMMON_H */
diff --git a/libvo/x11_common.c b/libvo/x11_common.c
deleted file mode 100644
index 04d5c6880b..0000000000
--- a/libvo/x11_common.c
+++ /dev/null
@@ -1,2404 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <inttypes.h>
-#include <limits.h>
-
-#include "config.h"
-#include "bstr.h"
-#include "options.h"
-#include "mp_msg.h"
-#include "mp_fifo.h"
-#include "libavutil/common.h"
-#include "x11_common.h"
-#include "talloc.h"
-
-#include <string.h>
-#include <unistd.h>
-#include <assert.h>
-
-#include "video_out.h"
-#include "aspect.h"
-#include "geometry.h"
-#include "osdep/timer.h"
-
-#include <X11/Xmd.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-
-#ifdef CONFIG_XSS
-#include <X11/extensions/scrnsaver.h>
-#endif
-
-#ifdef CONFIG_XDPMS
-#include <X11/extensions/dpms.h>
-#endif
-
-#ifdef CONFIG_XINERAMA
-#include <X11/extensions/Xinerama.h>
-#endif
-
-#ifdef CONFIG_XF86VM
-#include <X11/extensions/xf86vmode.h>
-#endif
-
-#ifdef CONFIG_XF86XK
-#include <X11/XF86keysym.h>
-#endif
-
-#ifdef CONFIG_XV
-#include <X11/extensions/Xv.h>
-#include <X11/extensions/Xvlib.h>
-
-#include "subopt-helper.h"
-#endif
-
-#include "input/input.h"
-#include "input/keycodes.h"
-
-#define WIN_LAYER_ONBOTTOM 2
-#define WIN_LAYER_NORMAL 4
-#define WIN_LAYER_ONTOP 6
-#define WIN_LAYER_ABOVE_DOCK 10
-
-int fs_layer = WIN_LAYER_ABOVE_DOCK;
-
-int stop_xscreensaver = 1;
-
-static int dpms_disabled = 0;
-
-char *mDisplayName = NULL;
-
-char **vo_fstype_list;
-
-/* 1 means that the WM is metacity (broken as hell) */
-int metacity_hack = 0;
-
-#ifdef CONFIG_XF86VM
-static int modecount;
-static XF86VidModeModeInfo **vidmodes;
-static XF86VidModeModeLine modeline;
-#endif
-
-static int vo_x11_get_fs_type(int supported);
-static void saver_off(Display *);
-static void saver_on(Display *);
-
-/*
- * Sends the EWMH fullscreen state event.
- *
- * action: could be one of _NET_WM_STATE_REMOVE -- remove state
- * _NET_WM_STATE_ADD -- add state
- * _NET_WM_STATE_TOGGLE -- toggle
- */
-void vo_x11_ewmh_fullscreen(struct vo_x11_state *x11, int action)
-{
- assert(action == _NET_WM_STATE_REMOVE ||
- action == _NET_WM_STATE_ADD || action == _NET_WM_STATE_TOGGLE);
-
- if (x11->fs_type & vo_wm_FULLSCREEN)
- {
- XEvent xev;
-
- /* init X event structure for _NET_WM_FULLSCREEN client message */
- xev.xclient.type = ClientMessage;
- xev.xclient.serial = 0;
- xev.xclient.send_event = True;
- xev.xclient.message_type = x11->XA_NET_WM_STATE;
- xev.xclient.window = x11->window;
- xev.xclient.format = 32;
- xev.xclient.data.l[0] = action;
- xev.xclient.data.l[1] = x11->XA_NET_WM_STATE_FULLSCREEN;
- xev.xclient.data.l[2] = 0;
- xev.xclient.data.l[3] = 0;
- xev.xclient.data.l[4] = 0;
-
- /* finally send that damn thing */
- if (!XSendEvent(x11->display, DefaultRootWindow(x11->display), False,
- SubstructureRedirectMask | SubstructureNotifyMask,
- &xev))
- {
- mp_tmsg(MSGT_VO, MSGL_ERR, "\nX11: Couldn't send EWMH fullscreen event!\n");
- }
- }
-}
-
-static void vo_hidecursor(Display * disp, Window win)
-{
- Cursor no_ptr;
- Pixmap bm_no;
- XColor black, dummy;
- Colormap colormap;
- const char bm_no_data[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
- if (WinID == 0)
- return; // do not hide if playing on the root window
-
- colormap = DefaultColormap(disp, DefaultScreen(disp));
- if ( !XAllocNamedColor(disp, colormap, "black", &black, &dummy) )
- {
- return; // color alloc failed, give up
- }
- bm_no = XCreateBitmapFromData(disp, win, bm_no_data, 8, 8);
- no_ptr = XCreatePixmapCursor(disp, bm_no, bm_no, &black, &black, 0, 0);
- XDefineCursor(disp, win, no_ptr);
- XFreeCursor(disp, no_ptr);
- if (bm_no != None)
- XFreePixmap(disp, bm_no);
- XFreeColors(disp,colormap,&black.pixel,1,0);
-}
-
-static void vo_showcursor(Display * disp, Window win)
-{
- if (WinID == 0)
- return;
- XDefineCursor(disp, win, 0);
-}
-
-static int x11_errorhandler(Display * display, XErrorEvent * event)
-{
-#define MSGLEN 60
- char msg[MSGLEN];
-
- XGetErrorText(display, event->error_code, (char *) &msg, MSGLEN);
-
- mp_msg(MSGT_VO, MSGL_ERR, "X11 error: %s\n", msg);
-
- mp_msg(MSGT_VO, MSGL_V,
- "Type: %x, display: %p, resourceid: %lx, serial: %lx\n",
- event->type, event->display, event->resourceid, event->serial);
- mp_msg(MSGT_VO, MSGL_V,
- "Error code: %x, request code: %x, minor code: %x\n",
- event->error_code, event->request_code, event->minor_code);
-
-// abort();
- return 0;
-#undef MSGLEN
-}
-
-void fstype_help(void)
-{
- mp_tmsg(MSGT_VO, MSGL_INFO, "Available fullscreen layer change modes:\n");
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FULL_SCREEN_TYPES\n");
-
- mp_msg(MSGT_VO, MSGL_INFO, " %-15s %s\n", "none",
- "don't set fullscreen window layer");
- mp_msg(MSGT_VO, MSGL_INFO, " %-15s %s\n", "layer",
- "use _WIN_LAYER hint with default layer");
- mp_msg(MSGT_VO, MSGL_INFO, " %-15s %s\n", "layer=<0..15>",
- "use _WIN_LAYER hint with a given layer number");
- mp_msg(MSGT_VO, MSGL_INFO, " %-15s %s\n", "netwm",
- "force NETWM style");
- mp_msg(MSGT_VO, MSGL_INFO, " %-15s %s\n", "above",
- "use _NETWM_STATE_ABOVE hint if available");
- mp_msg(MSGT_VO, MSGL_INFO, " %-15s %s\n", "below",
- "use _NETWM_STATE_BELOW hint if available");
- mp_msg(MSGT_VO, MSGL_INFO, " %-15s %s\n", "fullscreen",
- "use _NETWM_STATE_FULLSCREEN hint if available");
- mp_msg(MSGT_VO, MSGL_INFO, " %-15s %s\n", "stays_on_top",
- "use _NETWM_STATE_STAYS_ON_TOP hint if available");
- mp_msg(MSGT_VO, MSGL_INFO,
- "You can also negate the settings with simply putting '-' in the beginning");
- mp_msg(MSGT_VO, MSGL_INFO, "\n");
-}
-
-static void fstype_dump(int fstype)
-{
- if (fstype)
- {
- mp_msg(MSGT_VO, MSGL_V, "[x11] Current fstype setting honours");
- if (fstype & vo_wm_LAYER)
- mp_msg(MSGT_VO, MSGL_V, " LAYER");
- if (fstype & vo_wm_FULLSCREEN)
- mp_msg(MSGT_VO, MSGL_V, " FULLSCREEN");
- if (fstype & vo_wm_STAYS_ON_TOP)
- mp_msg(MSGT_VO, MSGL_V, " STAYS_ON_TOP");
- if (fstype & vo_wm_ABOVE)
- mp_msg(MSGT_VO, MSGL_V, " ABOVE");
- if (fstype & vo_wm_BELOW)
- mp_msg(MSGT_VO, MSGL_V, " BELOW");
- mp_msg(MSGT_VO, MSGL_V, " X atoms\n");
- } else
- mp_msg(MSGT_VO, MSGL_V,
- "[x11] Current fstype setting doesn't honour any X atoms\n");
-}
-
-static int net_wm_support_state_test(struct vo_x11_state *x11, Atom atom)
-{
-#define NET_WM_STATE_TEST(x) { if (atom == x11->XA_NET_WM_STATE_##x) { mp_msg( MSGT_VO,MSGL_V, "[x11] Detected wm supports " #x " state.\n" ); return vo_wm_##x; } }
-
- NET_WM_STATE_TEST(FULLSCREEN);
- NET_WM_STATE_TEST(ABOVE);
- NET_WM_STATE_TEST(STAYS_ON_TOP);
- NET_WM_STATE_TEST(BELOW);
- return 0;
-}
-
-static int x11_get_property(struct vo_x11_state *x11, Atom type, Atom ** args,
- unsigned long *nitems)
-{
- int format;
- unsigned long bytesafter;
-
- return Success ==
- XGetWindowProperty(x11->display, x11->rootwin, type, 0, 16384, False,
- AnyPropertyType, &type, &format, nitems,
- &bytesafter, (unsigned char **) args)
- && *nitems > 0;
-}
-
-static int vo_wm_detect(struct vo *vo)
-{
- struct vo_x11_state *x11 = vo->x11;
- int i;
- int wm = 0;
- unsigned long nitems;
- Atom *args = NULL;
-
- if (WinID >= 0)
- return 0;
-
-// -- supports layers
- if (x11_get_property(x11, x11->XA_WIN_PROTOCOLS, &args, &nitems))
- {
- mp_msg(MSGT_VO, MSGL_V, "[x11] Detected wm supports layers.\n");
- for (i = 0; i < nitems; i++)
- {
- if (args[i] == x11->XA_WIN_LAYER)
- {
- wm |= vo_wm_LAYER;
- metacity_hack |= 1;
- } else
- /* metacity is the only window manager I know which reports
- * supporting only the _WIN_LAYER hint in _WIN_PROTOCOLS.
- * (what's more support for it is broken) */
- metacity_hack |= 2;
- }
- XFree(args);
- if (wm && (metacity_hack == 1))
- {
- // metacity claims to support layers, but it is not the truth :-)
- wm ^= vo_wm_LAYER;
- mp_msg(MSGT_VO, MSGL_V,
- "[x11] Using workaround for Metacity bugs.\n");
- }
- }
-// --- netwm
- if (x11_get_property(x11, x11->XA_NET_SUPPORTED, &args, &nitems))
- {
- mp_msg(MSGT_VO, MSGL_V, "[x11] Detected wm supports NetWM.\n");
- for (i = 0; i < nitems; i++)
- wm |= net_wm_support_state_test(vo->x11, args[i]);
- XFree(args);
- }
-
- if (wm == 0)
- mp_msg(MSGT_VO, MSGL_V, "[x11] Unknown wm type...\n");
- return wm;
-}
-
-#define XA_INIT(x) x11->XA##x = XInternAtom(x11->display, #x, False)
-static void init_atoms(struct vo_x11_state *x11)
-{
- XA_INIT(_NET_SUPPORTED);
- XA_INIT(_NET_WM_STATE);
- XA_INIT(_NET_WM_STATE_FULLSCREEN);
- XA_INIT(_NET_WM_STATE_ABOVE);
- XA_INIT(_NET_WM_STATE_STAYS_ON_TOP);
- XA_INIT(_NET_WM_STATE_BELOW);
- XA_INIT(_NET_WM_PID);
- XA_INIT(_NET_WM_NAME);
- XA_INIT(_NET_WM_ICON_NAME);
- XA_INIT(_WIN_PROTOCOLS);
- XA_INIT(_WIN_LAYER);
- XA_INIT(_WIN_HINTS);
- XA_INIT(WM_PROTOCOLS);
- XA_INIT(WM_DELETE_WINDOW);
- XA_INIT(UTF8_STRING);
- char buf[50];
- sprintf(buf, "_NET_WM_CM_S%d", x11->screen);
- x11->XA_NET_WM_CM = XInternAtom(x11->display, buf, False);
-}
-
-void update_xinerama_info(struct vo *vo) {
- struct MPOpts *opts = vo->opts;
- xinerama_x = xinerama_y = 0;
-#ifdef CONFIG_XINERAMA
- if (xinerama_screen >= -1 && XineramaIsActive(vo->x11->display))
- {
- int screen = xinerama_screen;
- XineramaScreenInfo *screens;
- int num_screens;
-
- screens = XineramaQueryScreens(vo->x11->display, &num_screens);
- if (screen >= num_screens)
- screen = num_screens - 1;
- if (screen == -1) {
- int x = vo->dx + vo->dwidth / 2;
- int y = vo->dy + vo->dheight / 2;
- for (screen = num_screens - 1; screen > 0; screen--) {
- int left = screens[screen].x_org;
- int right = left + screens[screen].width;
- int top = screens[screen].y_org;
- int bottom = top + screens[screen].height;
- if (left <= x && x <= right && top <= y && y <= bottom)
- break;
- }
- }
- if (screen < 0)
- screen = 0;
- opts->vo_screenwidth = screens[screen].width;
- opts->vo_screenheight = screens[screen].height;
- xinerama_x = screens[screen].x_org;
- xinerama_y = screens[screen].y_org;
-
- XFree(screens);
- }
-#endif
- aspect_save_screenres(vo, opts->vo_screenwidth, opts->vo_screenheight);
-}
-
-int vo_init(struct vo *vo)
-{
- struct MPOpts *opts = vo->opts;
-// int mScreen;
- int depth, bpp;
- unsigned int mask;
-
-// char * DisplayName = ":0.0";
-// Display * mDisplay;
- XImage *mXImage = NULL;
-
-// Window mRootWin;
- XWindowAttributes attribs;
- char *dispName;
-
- if (vo->x11)
- return 1;
-
- vo->x11 = vo_x11_init_state();
- struct vo_x11_state *x11 = vo->x11;
-
- if (vo_rootwin)
- WinID = 0; // use root window
-
- if (x11->depthonscreen)
- {
- saver_off(x11->display);
- return 1; // already called
- }
-
- XSetErrorHandler(x11_errorhandler);
-
-#if 0
- if (!mDisplayName)
- if (!(mDisplayName = getenv("DISPLAY")))
- mDisplayName = strdup(":0.0");
-#else
- dispName = XDisplayName(mDisplayName);
-#endif
-
- mp_msg(MSGT_VO, MSGL_V, "X11 opening display: %s\n", dispName);
-
- x11->display = XOpenDisplay(dispName);
- if (!x11->display)
- {
- mp_msg(MSGT_VO, MSGL_ERR,
- "vo: couldn't open the X11 display (%s)!\n", dispName);
- talloc_free(x11);
- vo->x11 = NULL;
- return 0;
- }
- x11->screen = DefaultScreen(x11->display); // screen ID
- x11->rootwin = RootWindow(x11->display, x11->screen); // root window ID
-
- x11->xim = XOpenIM(x11->display, NULL, NULL, NULL);
-
- init_atoms(vo->x11);
-
-#ifdef CONFIG_XF86VM
- {
- int clock;
-
- XF86VidModeGetModeLine(x11->display, x11->screen, &clock, &modeline);
- if (!opts->vo_screenwidth)
- opts->vo_screenwidth = modeline.hdisplay;
- if (!opts->vo_screenheight)
- opts->vo_screenheight = modeline.vdisplay;
- }
-#endif
- {
- if (!opts->vo_screenwidth)
- opts->vo_screenwidth = DisplayWidth(x11->display, x11->screen);
- if (!opts->vo_screenheight)
- opts->vo_screenheight = DisplayHeight(x11->display, x11->screen);
- }
- // get color depth (from root window, or the best visual):
- XGetWindowAttributes(x11->display, x11->rootwin, &attribs);
- depth = attribs.depth;
-
- if (depth != 15 && depth != 16 && depth != 24 && depth != 32)
- {
- Visual *visual;
-
- depth = vo_find_depth_from_visuals(x11->display, x11->screen, &visual);
- if (depth != -1)
- mXImage = XCreateImage(x11->display, visual, depth, ZPixmap,
- 0, NULL, 1, 1, 8, 1);
- } else
- mXImage =
- XGetImage(x11->display, x11->rootwin, 0, 0, 1, 1, AllPlanes, ZPixmap);
-
- x11->depthonscreen = depth; // display depth on screen
-
- // get bits/pixel from XImage structure:
- if (mXImage == NULL)
- {
- mask = 0;
- } else
- {
- /*
- * for the depth==24 case, the XImage structures might use
- * 24 or 32 bits of data per pixel. The x11->depthonscreen
- * field stores the amount of data per pixel in the
- * XImage structure!
- *
- * Maybe we should rename vo_depthonscreen to (or add) vo_bpp?
- */
- bpp = mXImage->bits_per_pixel;
- if ((x11->depthonscreen + 7) / 8 != (bpp + 7) / 8)
- x11->depthonscreen = bpp; // by A'rpi
- mask =
- mXImage->red_mask | mXImage->green_mask | mXImage->blue_mask;
- mp_msg(MSGT_VO, MSGL_V,
- "vo: X11 color mask: %X (R:%lX G:%lX B:%lX)\n", mask,
- mXImage->red_mask, mXImage->green_mask, mXImage->blue_mask);
- XDestroyImage(mXImage);
- }
- if (((x11->depthonscreen + 7) / 8) == 2)
- {
- if (mask == 0x7FFF)
- x11->depthonscreen = 15;
- else if (mask == 0xFFFF)
- x11->depthonscreen = 16;
- }
-// XCloseDisplay( mDisplay );
-/* slightly improved local display detection AST */
- if (strncmp(dispName, "unix:", 5) == 0)
- dispName += 4;
- else if (strncmp(dispName, "localhost:", 10) == 0)
- dispName += 9;
- if (*dispName == ':' && atoi(dispName + 1) < 10)
- x11->display_is_local = 1;
- else
- x11->display_is_local = 0;
- mp_msg(MSGT_VO, MSGL_V,
- "vo: X11 running at %dx%d with depth %d and %d bpp (\"%s\" => %s display)\n",
- opts->vo_screenwidth, opts->vo_screenheight, depth, x11->depthonscreen,
- dispName, x11->display_is_local ? "local" : "remote");
-
- x11->wm_type = vo_wm_detect(vo);
-
- x11->fs_type = vo_x11_get_fs_type(x11->wm_type);
-
- fstype_dump(x11->fs_type);
-
- saver_off(x11->display);
- return 1;
-}
-
-void vo_uninit(struct vo_x11_state *x11)
-{
- if (!x11)
- return;
- if (!x11->display)
- {
- mp_msg(MSGT_VO, MSGL_V,
- "vo: x11 uninit called but X11 not initialized..\n");
- } else {
- mp_msg(MSGT_VO, MSGL_V, "vo: uninit ...\n");
- if (x11->xim)
- XCloseIM(x11->xim);
- XSetErrorHandler(NULL);
- XCloseDisplay(x11->display);
- x11->depthonscreen = 0;
- x11->display = NULL;
- }
- talloc_free(x11);
-}
-
-static const struct mp_keymap keymap[] = {
- // special keys
- {XK_Pause, KEY_PAUSE}, {XK_Escape, KEY_ESC}, {XK_BackSpace, KEY_BS},
- {XK_Tab, KEY_TAB}, {XK_Return, KEY_ENTER},
- {XK_Menu, KEY_MENU}, {XK_Print, KEY_PRINT},
-
- // cursor keys
- {XK_Left, KEY_LEFT}, {XK_Right, KEY_RIGHT}, {XK_Up, KEY_UP}, {XK_Down, KEY_DOWN},
-
- // navigation block
- {XK_Insert, KEY_INSERT}, {XK_Delete, KEY_DELETE}, {XK_Home, KEY_HOME}, {XK_End, KEY_END},
- {XK_Page_Up, KEY_PAGE_UP}, {XK_Page_Down, KEY_PAGE_DOWN},
-
- // F-keys
- {XK_F1, KEY_F+1}, {XK_F2, KEY_F+2}, {XK_F3, KEY_F+3}, {XK_F4, KEY_F+4},
- {XK_F5, KEY_F+5}, {XK_F6, KEY_F+6}, {XK_F7, KEY_F+7}, {XK_F8, KEY_F+8},
- {XK_F9, KEY_F+9}, {XK_F10, KEY_F+10}, {XK_F11, KEY_F+11}, {XK_F12, KEY_F+12},
-
- // numpad independent of numlock
- {XK_KP_Subtract, '-'}, {XK_KP_Add, '+'}, {XK_KP_Multiply, '*'}, {XK_KP_Divide, '/'},
- {XK_KP_Enter, KEY_KPENTER},
-
- // numpad with numlock
- {XK_KP_0, KEY_KP0}, {XK_KP_1, KEY_KP1}, {XK_KP_2, KEY_KP2},
- {XK_KP_3, KEY_KP3}, {XK_KP_4, KEY_KP4}, {XK_KP_5, KEY_KP5},
- {XK_KP_6, KEY_KP6}, {XK_KP_7, KEY_KP7}, {XK_KP_8, KEY_KP8},
- {XK_KP_9, KEY_KP9}, {XK_KP_Decimal, KEY_KPDEC},
- {XK_KP_Separator, KEY_KPDEC},
-
- // numpad without numlock
- {XK_KP_Insert, KEY_KPINS}, {XK_KP_End, KEY_KP1}, {XK_KP_Down, KEY_KP2},
- {XK_KP_Page_Down, KEY_KP3}, {XK_KP_Left, KEY_KP4}, {XK_KP_Begin, KEY_KP5},
- {XK_KP_Right, KEY_KP6}, {XK_KP_Home, KEY_KP7}, {XK_KP_Up, KEY_KP8},
- {XK_KP_Page_Up, KEY_KP9}, {XK_KP_Delete, KEY_KPDEL},
-
-#ifdef XF86XK_AudioPause
- {XF86XK_MenuKB, KEY_MENU},
- {XF86XK_AudioPlay, KEY_PLAY}, {XF86XK_AudioPause, KEY_PAUSE}, {XF86XK_AudioStop, KEY_STOP},
- {XF86XK_AudioPrev, KEY_PREV}, {XF86XK_AudioNext, KEY_NEXT},
- {XF86XK_AudioMute, KEY_MUTE}, {XF86XK_AudioLowerVolume, KEY_VOLUME_DOWN}, {XF86XK_AudioRaiseVolume, KEY_VOLUME_UP},
-#endif
-
- {0, 0}
-};
-
-static int vo_x11_lookupkey(int key)
-{
- static const char *passthrough_keys = " -+*/<>`~!@#$%^&()_{}:;\"\',.?\\|=[]";
- int mpkey = 0;
- if ((key >= 'a' && key <= 'z') ||
- (key >= 'A' && key <= 'Z') ||
- (key >= '0' && key <= '9') ||
- (key > 0 && key < 256 && strchr(passthrough_keys, key)))
- mpkey = key;
-
- if (!mpkey)
- mpkey = lookup_keymap_table(keymap, key);
-
- return mpkey;
-}
-
-
-// ----- Motif header: -------
-
-#define MWM_HINTS_FUNCTIONS (1L << 0)
-#define MWM_HINTS_DECORATIONS (1L << 1)
-#define MWM_HINTS_INPUT_MODE (1L << 2)
-#define MWM_HINTS_STATUS (1L << 3)
-
-#define MWM_FUNC_ALL (1L << 0)
-#define MWM_FUNC_RESIZE (1L << 1)
-#define MWM_FUNC_MOVE (1L << 2)
-#define MWM_FUNC_MINIMIZE (1L << 3)
-#define MWM_FUNC_MAXIMIZE (1L << 4)
-#define MWM_FUNC_CLOSE (1L << 5)
-
-#define MWM_DECOR_ALL (1L << 0)
-#define MWM_DECOR_BORDER (1L << 1)
-#define MWM_DECOR_RESIZEH (1L << 2)
-#define MWM_DECOR_TITLE (1L << 3)
-#define MWM_DECOR_MENU (1L << 4)
-#define MWM_DECOR_MINIMIZE (1L << 5)
-#define MWM_DECOR_MAXIMIZE (1L << 6)
-
-#define MWM_INPUT_MODELESS 0
-#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1
-#define MWM_INPUT_SYSTEM_MODAL 2
-#define MWM_INPUT_FULL_APPLICATION_MODAL 3
-#define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL
-
-#define MWM_TEAROFF_WINDOW (1L<<0)
-
-typedef struct
-{
- long flags;
- long functions;
- long decorations;
- long input_mode;
- long state;
-} MotifWmHints;
-
-static MotifWmHints vo_MotifWmHints;
-static Atom vo_MotifHints = None;
-
-void vo_x11_decoration(struct vo *vo, int d)
-{
- struct vo_x11_state *x11 = vo->x11;
- Atom mtype;
- int mformat;
- unsigned long mn, mb;
-
- if (!WinID)
- return;
-
- if (vo_fsmode & 8)
- {
- XSetTransientForHint(x11->display, x11->window,
- RootWindow(x11->display, x11->screen));
- }
-
- vo_MotifHints = XInternAtom(x11->display, "_MOTIF_WM_HINTS", 0);
- if (vo_MotifHints != None)
- {
- if (!d)
- {
- MotifWmHints *mhints = NULL;
-
- XGetWindowProperty(x11->display, x11->window,
- vo_MotifHints, 0, 20, False,
- vo_MotifHints, &mtype, &mformat, &mn,
- &mb, (unsigned char **) &mhints);
- if (mhints)
- {
- if (mhints->flags & MWM_HINTS_DECORATIONS)
- x11->olddecor = mhints->decorations;
- if (mhints->flags & MWM_HINTS_FUNCTIONS)
- x11->oldfuncs = mhints->functions;
- XFree(mhints);
- }
- }
-
- memset(&vo_MotifWmHints, 0, sizeof(MotifWmHints));
- vo_MotifWmHints.flags =
- MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS;
- if (d)
- {
- vo_MotifWmHints.functions = x11->oldfuncs;
- d = x11->olddecor;
- }
-#if 0
- vo_MotifWmHints.decorations =
- d | ((vo_fsmode & 2) ? 0 : MWM_DECOR_MENU);
-#else
- vo_MotifWmHints.decorations =
- d | ((vo_fsmode & 2) ? MWM_DECOR_MENU : 0);
-#endif
- XChangeProperty(x11->display, x11->window, vo_MotifHints,
- vo_MotifHints, 32,
- PropModeReplace,
- (unsigned char *) &vo_MotifWmHints,
- (vo_fsmode & 4) ? 4 : 5);
- }
-}
-
-void vo_x11_classhint(struct vo *vo, Window window, const char *name)
-{
- struct MPOpts *opts = vo->opts;
- struct vo_x11_state *x11 = vo->x11;
- XClassHint wmClass;
- pid_t pid = getpid();
-
- wmClass.res_name = opts->vo_winname ? opts->vo_winname : (char *)name;
- wmClass.res_class = "mpv";
- XSetClassHint(x11->display, window, &wmClass);
- XChangeProperty(x11->display, window, x11->XA_NET_WM_PID, XA_CARDINAL,
- 32, PropModeReplace, (unsigned char *) &pid, 1);
-}
-
-void vo_x11_uninit(struct vo *vo)
-{
- struct vo_x11_state *x11 = vo->x11;
- saver_on(x11->display);
- if (x11->window != None)
- vo_showcursor(x11->display, x11->window);
-
- if (x11->f_gc != None)
- {
- XFreeGC(vo->x11->display, x11->f_gc);
- x11->f_gc = None;
- }
- {
- if (x11->vo_gc != None)
- {
- XFreeGC(vo->x11->display, x11->vo_gc);
- x11->vo_gc = None;
- }
- if (x11->window != None)
- {
- XClearWindow(x11->display, x11->window);
- if (WinID < 0)
- {
- XEvent xev;
-
- if (x11->xic)
- XDestroyIC(x11->xic);
- x11->xic = NULL;
-
- XUnmapWindow(x11->display, x11->window);
- XSelectInput(x11->display, x11->window, StructureNotifyMask);
- XDestroyWindow(x11->display, x11->window);
- do
- {
- XNextEvent(x11->display, &xev);
- }
- while (xev.type != DestroyNotify
- || xev.xdestroywindow.event != x11->window);
- }
- x11->window = None;
- }
- vo_fs = 0;
- x11->vo_old_width = x11->vo_old_height = 0;
- x11->last_video_width = 0;
- x11->last_video_height = 0;
- x11->size_changed_during_fs = false;
- }
- vo_uninit(x11);
- vo->x11 = NULL;
-}
-
-static int check_resize(struct vo *vo)
-{
- int old_w = vo->dwidth, old_h = vo->dheight;
- int old_x = vo->dx, old_y = vo->dy;
- int rc = 0;
- vo_x11_update_geometry(vo, true);
- if (vo->dwidth != old_w || vo->dheight != old_h)
- rc |= VO_EVENT_RESIZE;
- if (vo->dx != old_x || vo->dy != old_y)
- rc |= VO_EVENT_MOVE;
- return rc;
-}
-
-int vo_x11_check_events(struct vo *vo)
-{
- struct vo_x11_state *x11 = vo->x11;
- struct MPOpts *opts = vo->opts;
- Display *display = vo->x11->display;
- int ret = 0;
- XEvent Event;
-
- if (x11->mouse_waiting_hide && opts->cursor_autohide_delay != -1 &&
- (GetTimerMS() - x11->mouse_timer >= opts->cursor_autohide_delay)) {
- vo_hidecursor(display, x11->window);
- x11->mouse_waiting_hide = 0;
- }
-
- if (WinID > 0)
- ret |= check_resize(vo);
- while (XPending(display))
- {
- XNextEvent(display, &Event);
-// printf("\rEvent.type=%X \n",Event.type);
- switch (Event.type)
- {
- case Expose:
- ret |= VO_EVENT_EXPOSE;
- break;
- case ConfigureNotify:
- if (x11->window == None)
- break;
- ret |= check_resize(vo);
- break;
- case KeyPress:
- {
- char buf[100];
- KeySym keySym = 0;
- int modifiers = 0;
- if (Event.xkey.state & ShiftMask)
- modifiers |= KEY_MODIFIER_SHIFT;
- if (Event.xkey.state & ControlMask)
- modifiers |= KEY_MODIFIER_CTRL;
- if (Event.xkey.state & Mod1Mask)
- modifiers |= KEY_MODIFIER_ALT;
- if (Event.xkey.state & Mod4Mask)
- modifiers |= KEY_MODIFIER_META;
- if (x11->xic) {
- Status status;
- int len = Xutf8LookupString(x11->xic, &Event.xkey, buf,
- sizeof(buf), &keySym,
- &status);
- int mpkey = vo_x11_lookupkey(keySym);
- if (mpkey) {
- mplayer_put_key(vo->key_fifo, mpkey | modifiers);
- } else if (status == XLookupChars
- || status == XLookupBoth)
- {
- struct bstr t = { buf, len };
- mplayer_put_key_utf8(vo->key_fifo, modifiers, t);
- }
- } else {
- XLookupString(&Event.xkey, buf, sizeof(buf), &keySym,
- &x11->compose_status);
- int mpkey = vo_x11_lookupkey(keySym);
- if (mpkey)
- mplayer_put_key(vo->key_fifo, mpkey | modifiers);
- }
- ret |= VO_EVENT_KEYPRESS;
- }
- break;
- case MotionNotify:
- vo_mouse_movement(vo, Event.xmotion.x, Event.xmotion.y);
-
- if (opts->cursor_autohide_delay > -2) {
- vo_showcursor(display, x11->window);
- x11->mouse_waiting_hide = 1;
- x11->mouse_timer = GetTimerMS();
- }
- break;
- case ButtonPress:
- if (opts->cursor_autohide_delay > -2) {
- vo_showcursor(display, x11->window);
- x11->mouse_waiting_hide = 1;
- x11->mouse_timer = GetTimerMS();
- }
- mplayer_put_key(vo->key_fifo,
- (MOUSE_BTN0 + Event.xbutton.button - 1)
- | MP_KEY_DOWN);
- break;
- case ButtonRelease:
- if (opts->cursor_autohide_delay > -2) {
- vo_showcursor(display, x11->window);
- x11->mouse_waiting_hide = 1;
- x11->mouse_timer = GetTimerMS();
- }
- mplayer_put_key(vo->key_fifo,
- MOUSE_BTN0 + Event.xbutton.button - 1);
- break;
- case PropertyNotify:
- {
- char *name =
- XGetAtomName(display, Event.xproperty.atom);
-
- if (!name)
- break;
-
-// fprintf(stderr,"[ws] PropertyNotify ( 0x%x ) %s ( 0x%x )\n",vo_window,name,Event.xproperty.atom );
-
- XFree(name);
- }
- break;
- case MapNotify:
- x11->vo_hint.win_gravity = x11->old_gravity;
- XSetWMNormalHints(display, x11->window, &x11->vo_hint);
- x11->fs_flip = 0;
- break;
- case DestroyNotify:
- mp_msg(MSGT_VO, MSGL_WARN, "Our window was destroyed, exiting\n");
- mplayer_put_key(vo->key_fifo, KEY_CLOSE_WIN);
- break;
- case ClientMessage:
- if (Event.xclient.message_type == x11->XAWM_PROTOCOLS &&
- Event.xclient.data.l[0] == x11->XAWM_DELETE_WINDOW)
- mplayer_put_key(vo->key_fifo, KEY_CLOSE_WIN);
- break;
- }
- }
- return ret;
-}
-
-/**
- * \brief sets the size and position of the non-fullscreen window.
- */
-static void vo_x11_nofs_sizepos(struct vo *vo, int x, int y,
- int width, int height)
-{
- struct vo_x11_state *x11 = vo->x11;
- if (width == x11->last_video_width && height == x11->last_video_height) {
- if (!vo->opts->force_window_position && !x11->size_changed_during_fs)
- return;
- } else if (vo_fs)
- x11->size_changed_during_fs = true;
- x11->last_video_height = height;
- x11->last_video_width = width;
- vo_x11_sizehint(vo, x, y, width, height, 0);
- if (vo_fs) {
- x11->vo_old_x = x;
- x11->vo_old_y = y;
- x11->vo_old_width = width;
- x11->vo_old_height = height;
- }
- else
- {
- vo->dwidth = width;
- vo->dheight = height;
- if (vo->opts->force_window_position)
- XMoveResizeWindow(vo->x11->display, vo->x11->window, x, y, width,
- height);
- else
- XResizeWindow(vo->x11->display, vo->x11->window, width, height);
- }
-}
-
-void vo_x11_sizehint(struct vo *vo, int x, int y, int width, int height, int max)
-{
- struct vo_x11_state *x11 = vo->x11;
- x11->vo_hint.flags = 0;
- if (vo_keepaspect)
- {
- x11->vo_hint.flags |= PAspect;
- x11->vo_hint.min_aspect.x = width;
- x11->vo_hint.min_aspect.y = height;
- x11->vo_hint.max_aspect.x = width;
- x11->vo_hint.max_aspect.y = height;
- }
-
- x11->vo_hint.flags |= PPosition | PSize;
- x11->vo_hint.x = x;
- x11->vo_hint.y = y;
- x11->vo_hint.width = width;
- x11->vo_hint.height = height;
- if (max)
- {
- x11->vo_hint.flags |= PMaxSize;
- x11->vo_hint.max_width = width;
- x11->vo_hint.max_height = height;
- } else
- {
- x11->vo_hint.max_width = 0;
- x11->vo_hint.max_height = 0;
- }
-
- // Set minimum height/width to 4 to avoid off-by-one errors.
- x11->vo_hint.flags |= PMinSize;
- x11->vo_hint.min_width = x11->vo_hint.min_height = 4;
-
- // Set the base size. A window manager might display the window
- // size to the user relative to this.
- // Setting these to width/height might be nice, but e.g. fluxbox can't handle it.
- x11->vo_hint.flags |= PBaseSize;
- x11->vo_hint.base_width = 0 /*width*/;
- x11->vo_hint.base_height = 0 /*height*/;
-
- x11->vo_hint.flags |= PWinGravity;
- x11->vo_hint.win_gravity = StaticGravity;
- XSetWMNormalHints(x11->display, x11->window, &x11->vo_hint);
-}
-
-static int vo_x11_get_gnome_layer(struct vo_x11_state *x11, Window win)
-{
- Atom type;
- int format;
- unsigned long nitems;
- unsigned long bytesafter;
- unsigned short *args = NULL;
-
- if (XGetWindowProperty(x11->display, win, x11->XA_WIN_LAYER, 0, 16384,
- False, AnyPropertyType, &type, &format, &nitems,
- &bytesafter,
- (unsigned char **) &args) == Success
- && nitems > 0 && args)
- {
- mp_msg(MSGT_VO, MSGL_V, "[x11] original window layer is %d.\n",
- *args);
- return *args;
- }
- return WIN_LAYER_NORMAL;
-}
-
-// set a X text property that expects a UTF8_STRING type
-static void vo_x11_set_property_utf8(struct vo *vo, Atom name, const char *t)
-{
- struct vo_x11_state *x11 = vo->x11;
-
- XChangeProperty(x11->display, x11->window, name, x11->XAUTF8_STRING, 8,
- PropModeReplace, t, strlen(t));
-}
-
-// set a X text property that expects a STRING or COMPOUND_TEXT type
-static void vo_x11_set_property_string(struct vo *vo, Atom name, const char *t)
-{
- struct vo_x11_state *x11 = vo->x11;
- XTextProperty prop = {0};
-
- if (Xutf8TextListToTextProperty(x11->display, (char **)&t, 1,
- XStdICCTextStyle, &prop) == Success)
- {
- XSetTextProperty(x11->display, x11->window, &prop, name);
- } else {
- // Strictly speaking this violates the ICCCM, but there's no way we
- // can do this correctly.
- vo_x11_set_property_utf8(vo, name, t);
- }
-
- if (prop.value)
- XFree(prop.value);
-}
-
-static void vo_x11_update_window_title(struct vo *vo)
-{
- struct vo_x11_state *x11 = vo->x11;
-
- const char *title = vo_get_window_title(vo);
- vo_x11_set_property_string(vo, XA_WM_NAME, title);
- vo_x11_set_property_string(vo, XA_WM_ICON_NAME, title);
- vo_x11_set_property_utf8(vo, x11->XA_NET_WM_NAME, title);
- vo_x11_set_property_utf8(vo, x11->XA_NET_WM_ICON_NAME, title);
-}
-
-//
-static Window vo_x11_create_smooth_window(struct vo_x11_state *x11, Window mRoot,
- Visual * vis, int x, int y,
- unsigned int width, unsigned int height,
- int depth, Colormap col_map)
-{
- unsigned long xswamask = CWBorderPixel;
- XSetWindowAttributes xswa;
- Window ret_win;
-
- if (col_map != CopyFromParent)
- {
- xswa.colormap = col_map;
- xswamask |= CWColormap;
- }
- xswa.background_pixel = 0;
- xswa.border_pixel = 0;
- xswa.backing_store = NotUseful;
- xswa.bit_gravity = StaticGravity;
-
- ret_win =
- XCreateWindow(x11->display, x11->rootwin, x, y, width, height, 0, depth,
- CopyFromParent, vis, xswamask, &xswa);
- XSetWMProtocols(x11->display, ret_win, &x11->XAWM_DELETE_WINDOW, 1);
- if (x11->f_gc == None)
- x11->f_gc = XCreateGC(x11->display, ret_win, 0, 0);
- XSetForeground(x11->display, x11->f_gc, 0);
-
- return ret_win;
-}
-
-/**
- * \brief create and setup a window suitable for display
- * \param vis Visual to use for creating the window
- * \param x x position of window
- * \param y y position of window
- * \param width width of window
- * \param height height of window
- * \param flags flags for window creation.
- * Only VOFLAG_FULLSCREEN is supported so far.
- * \param col_map Colourmap for window or CopyFromParent if a specific colormap isn't needed
- * \param classname name to use for the classhint
- *
- * This also does the grunt-work like setting Window Manager hints etc.
- * If vo_window is already set it just moves and resizes it.
- */
-void vo_x11_create_vo_window(struct vo *vo, XVisualInfo *vis, int x, int y,
- unsigned int width, unsigned int height, int flags,
- Colormap col_map, const char *classname)
-{
- struct MPOpts *opts = vo->opts;
- struct vo_x11_state *x11 = vo->x11;
- Display *mDisplay = vo->x11->display;
- if (WinID >= 0) {
- vo_fs = flags & VOFLAG_FULLSCREEN;
- x11->window = WinID ? (Window)WinID : x11->rootwin;
- if (col_map != CopyFromParent) {
- unsigned long xswamask = CWColormap;
- XSetWindowAttributes xswa;
- xswa.colormap = col_map;
- XChangeWindowAttributes(mDisplay, x11->window, xswamask, &xswa);
- XInstallColormap(mDisplay, col_map);
- }
- if (WinID) {
- // Expose events can only really be handled by us, so request them.
- vo_x11_selectinput_witherr(mDisplay, x11->window, ExposureMask);
- } else
- // Do not capture events since it might break the parent application
- // if it relies on events being forwarded to the parent of WinID.
- // It also is consistent with the w32_common.c code.
- vo_x11_selectinput_witherr(mDisplay, x11->window,
- StructureNotifyMask | KeyPressMask | PointerMotionMask |
- ButtonPressMask | ButtonReleaseMask | ExposureMask);
-
- vo_x11_update_geometry(vo, true);
- goto final;
- }
- if (x11->window == None) {
- vo_fs = 0;
- vo->dwidth = width;
- vo->dheight = height;
- x11->window = vo_x11_create_smooth_window(x11, x11->rootwin, vis->visual,
- x, y, width, height, vis->depth, col_map);
- x11->window_state = VOFLAG_HIDDEN;
- }
- if (flags & VOFLAG_HIDDEN)
- goto final;
- if (x11->window_state & VOFLAG_HIDDEN) {
- XSizeHints hint;
- x11->window_state &= ~VOFLAG_HIDDEN;
- vo_x11_classhint(vo, x11->window, classname);
- vo_hidecursor(mDisplay, x11->window);
- XSelectInput(mDisplay, x11->window, StructureNotifyMask);
- hint.x = x; hint.y = y;
- hint.width = width; hint.height = height;
- hint.flags = PSize;
- if (geometry_xy_changed)
- hint.flags |= PPosition;
- XSetWMNormalHints(mDisplay, x11->window, &hint);
- if (!vo_border) vo_x11_decoration(vo, 0);
- // map window
- x11->xic = XCreateIC(x11->xim,
- XNInputStyle, XIMPreeditNone | XIMStatusNone,
- XNClientWindow, x11->window,
- XNFocusWindow, x11->window,
- NULL);
- XSelectInput(mDisplay, x11->window, NoEventMask);
- vo_x11_selectinput_witherr(mDisplay, x11->window,
- StructureNotifyMask | KeyPressMask | PointerMotionMask |
- ButtonPressMask | ButtonReleaseMask | ExposureMask);
- XMapWindow(mDisplay, x11->window);
- vo_x11_clearwindow(vo, x11->window);
- }
- vo_x11_update_window_title(vo);
- if (opts->vo_ontop) vo_x11_setlayer(vo, x11->window, opts->vo_ontop);
- vo_x11_update_geometry(vo, !geometry_xy_changed);
- vo_x11_nofs_sizepos(vo, vo->dx, vo->dy, width, height);
- if (!!vo_fs != !!(flags & VOFLAG_FULLSCREEN))
- vo_x11_fullscreen(vo);
- else if (vo_fs) {
- // if we are already in fullscreen do not switch back and forth, just
- // set the size values right.
- vo->dwidth = vo->opts->vo_screenwidth;
- vo->dheight = vo->opts->vo_screenheight;
- }
-final:
- if (x11->vo_gc != None)
- XFreeGC(mDisplay, x11->vo_gc);
- x11->vo_gc = XCreateGC(mDisplay, x11->window, 0, NULL);
-
- XSync(mDisplay, False);
- vo->event_fd = ConnectionNumber(x11->display);
-}
-
-void vo_x11_clearwindow_part(struct vo *vo, Window vo_window,
- int img_width, int img_height)
-{
- struct vo_x11_state *x11 = vo->x11;
- Display *mDisplay = vo->x11->display;
- int u_dheight, u_dwidth, left_ov, left_ov2;
-
- if (x11->f_gc == None)
- return;
-
- u_dheight = vo->dheight;
- u_dwidth = vo->dwidth;
- if ((u_dheight <= img_height) && (u_dwidth <= img_width))
- return;
-
- left_ov = (u_dheight - img_height) / 2;
- left_ov2 = (u_dwidth - img_width) / 2;
-
- XFillRectangle(mDisplay, vo_window, x11->f_gc, 0, 0, u_dwidth, left_ov);
- XFillRectangle(mDisplay, vo_window, x11->f_gc, 0, u_dheight - left_ov - 1,
- u_dwidth, left_ov + 1);
-
- if (u_dwidth > img_width)
- {
- XFillRectangle(mDisplay, vo_window, x11->f_gc, 0, left_ov, left_ov2,
- img_height);
- XFillRectangle(mDisplay, vo_window, x11->f_gc, u_dwidth - left_ov2 - 1,
- left_ov, left_ov2 + 1, img_height);
- }
-
- XFlush(mDisplay);
-}
-
-void vo_x11_clearwindow(struct vo *vo, Window vo_window)
-{
- struct vo_x11_state *x11 = vo->x11;
- struct MPOpts *opts = vo->opts;
- if (x11->f_gc == None)
- return;
- XFillRectangle(x11->display, vo_window, x11->f_gc, 0, 0,
- opts->vo_screenwidth, opts->vo_screenheight);
- //
- XFlush(x11->display);
-}
-
-
-void vo_x11_setlayer(struct vo *vo, Window vo_window, int layer)
-{
- struct vo_x11_state *x11 = vo->x11;
- if (WinID >= 0)
- return;
-
- if (x11->fs_type & vo_wm_LAYER)
- {
- XClientMessageEvent xev;
-
- if (!x11->orig_layer)
- x11->orig_layer = vo_x11_get_gnome_layer(x11, vo_window);
-
- memset(&xev, 0, sizeof(xev));
- xev.type = ClientMessage;
- xev.display = x11->display;
- xev.window = vo_window;
- xev.message_type = x11->XA_WIN_LAYER;
- xev.format = 32;
- xev.data.l[0] = layer ? fs_layer : x11->orig_layer; // if not fullscreen, stay on default layer
- xev.data.l[1] = CurrentTime;
- mp_msg(MSGT_VO, MSGL_V,
- "[x11] Layered style stay on top (layer %ld).\n",
- xev.data.l[0]);
- XSendEvent(x11->display, x11->rootwin, False, SubstructureNotifyMask,
- (XEvent *) & xev);
- } else if (x11->fs_type & vo_wm_NETWM)
- {
- XClientMessageEvent xev;
- char *state;
-
- memset(&xev, 0, sizeof(xev));
- xev.type = ClientMessage;
- xev.message_type = x11->XA_NET_WM_STATE;
- xev.display = x11->display;
- xev.window = vo_window;
- xev.format = 32;
- xev.data.l[0] = layer;
-
- if (x11->fs_type & vo_wm_STAYS_ON_TOP)
- xev.data.l[1] = x11->XA_NET_WM_STATE_STAYS_ON_TOP;
- else if (x11->fs_type & vo_wm_ABOVE)
- xev.data.l[1] = x11->XA_NET_WM_STATE_ABOVE;
- else if (x11->fs_type & vo_wm_FULLSCREEN)
- xev.data.l[1] = x11->XA_NET_WM_STATE_FULLSCREEN;
- else if (x11->fs_type & vo_wm_BELOW)
- // This is not fallback. We can safely assume that the situation
- // where only NETWM_STATE_BELOW is supported doesn't exist.
- xev.data.l[1] = x11->XA_NET_WM_STATE_BELOW;
-
- XSendEvent(x11->display, x11->rootwin, False, SubstructureRedirectMask,
- (XEvent *) & xev);
- state = XGetAtomName(x11->display, xev.data.l[1]);
- mp_msg(MSGT_VO, MSGL_V,
- "[x11] NET style stay on top (layer %d). Using state %s.\n",
- layer, state);
- XFree(state);
- }
-}
-
-static int vo_x11_get_fs_type(int supported)
-{
- int i;
- int type = supported;
-
- if (vo_fstype_list)
- {
- for (i = 0; vo_fstype_list[i]; i++)
- {
- int neg = 0;
- char *arg = vo_fstype_list[i];
-
- if (vo_fstype_list[i][0] == '-')
- {
- neg = 1;
- arg = vo_fstype_list[i] + 1;
- }
-
- if (!strncmp(arg, "layer", 5))
- {
- if (!neg && (arg[5] == '='))
- {
- char *endptr = NULL;
- int layer = strtol(vo_fstype_list[i] + 6, &endptr, 10);
-
- if (endptr && *endptr == '\0' && layer >= 0
- && layer <= 15)
- fs_layer = layer;
- }
- if (neg)
- type &= ~vo_wm_LAYER;
- else
- type |= vo_wm_LAYER;
- } else if (!strcmp(arg, "above"))
- {
- if (neg)
- type &= ~vo_wm_ABOVE;
- else
- type |= vo_wm_ABOVE;
- } else if (!strcmp(arg, "fullscreen"))
- {
- if (neg)
- type &= ~vo_wm_FULLSCREEN;
- else
- type |= vo_wm_FULLSCREEN;
- } else if (!strcmp(arg, "stays_on_top"))
- {
- if (neg)
- type &= ~vo_wm_STAYS_ON_TOP;
- else
- type |= vo_wm_STAYS_ON_TOP;
- } else if (!strcmp(arg, "below"))
- {
- if (neg)
- type &= ~vo_wm_BELOW;
- else
- type |= vo_wm_BELOW;
- } else if (!strcmp(arg, "netwm"))
- {
- if (neg)
- type &= ~vo_wm_NETWM;
- else
- type |= vo_wm_NETWM;
- } else if (!strcmp(arg, "none"))
- type = 0; // clear; keep parsing
- }
- }
-
- return type;
-}
-
-/**
- * \brief update vo->dx, vo->dy, vo->dwidth and vo->dheight with current values of vo->x11->window
- * \return returns current color depth of vo->x11->window
- */
-int vo_x11_update_geometry(struct vo *vo, bool update_pos)
-{
- struct vo_x11_state *x11 = vo->x11;
- unsigned depth, w, h;
- int dummy_int;
- Window dummy_win;
- XGetGeometry(x11->display, x11->window, &dummy_win, &dummy_int, &dummy_int,
- &w, &h, &dummy_int, &depth);
- if (w <= INT_MAX && h <= INT_MAX) {
- vo->dwidth = w;
- vo->dheight = h;
- }
- if (update_pos)
- XTranslateCoordinates(x11->display, x11->window, x11->rootwin, 0, 0,
- &vo->dx, &vo->dy, &dummy_win);
-
- return depth <= INT_MAX ? depth : 0;
-}
-
-void vo_x11_fullscreen(struct vo *vo)
-{
- struct MPOpts *opts = vo->opts;
- struct vo_x11_state *x11 = vo->x11;
- int x, y, w, h;
- x = x11->vo_old_x;
- y = x11->vo_old_y;
- w = x11->vo_old_width;
- h = x11->vo_old_height;
-
- if (WinID >= 0) {
- vo_fs = !vo_fs;
- return;
- }
- if (x11->fs_flip)
- return;
-
- if (vo_fs)
- {
- vo_x11_ewmh_fullscreen(x11, _NET_WM_STATE_REMOVE); // removes fullscreen state if wm supports EWMH
- vo_fs = VO_FALSE;
- if (x11->size_changed_during_fs && (x11->fs_type & vo_wm_FULLSCREEN))
- vo_x11_nofs_sizepos(vo, vo->dx, vo->dy, x11->last_video_width,
- x11->last_video_height);
- x11->size_changed_during_fs = false;
- } else
- {
- // win->fs
- vo_x11_ewmh_fullscreen(x11, _NET_WM_STATE_ADD); // sends fullscreen state to be added if wm supports EWMH
-
- vo_fs = VO_TRUE;
- if ( ! (x11->fs_type & vo_wm_FULLSCREEN) ) // not needed with EWMH fs
- {
- x11->vo_old_x = vo->dx;
- x11->vo_old_y = vo->dy;
- x11->vo_old_width = vo->dwidth;
- x11->vo_old_height = vo->dheight;
- }
- update_xinerama_info(vo);
- x = xinerama_x;
- y = xinerama_y;
- w = opts->vo_screenwidth;
- h = opts->vo_screenheight;
- }
- {
- long dummy;
-
- XGetWMNormalHints(x11->display, x11->window, &x11->vo_hint, &dummy);
- if (!(x11->vo_hint.flags & PWinGravity))
- x11->old_gravity = NorthWestGravity;
- else
- x11->old_gravity = x11->vo_hint.win_gravity;
- }
- if (x11->wm_type == 0 && !(vo_fsmode & 16))
- {
- XUnmapWindow(x11->display, x11->window); // required for MWM
- XWithdrawWindow(x11->display, x11->window, x11->screen);
- x11->fs_flip = 1;
- }
-
- if ( ! (x11->fs_type & vo_wm_FULLSCREEN) ) // not needed with EWMH fs
- {
- vo_x11_decoration(vo, vo_border && !vo_fs);
- vo_x11_sizehint(vo, x, y, w, h, 0);
- vo_x11_setlayer(vo, x11->window, vo_fs);
-
-
- XMoveResizeWindow(x11->display, x11->window, x, y, w, h);
- }
- /* some WMs lose ontop after fullscreen */
- if ((!(vo_fs)) & opts->vo_ontop)
- vo_x11_setlayer(vo, x11->window, opts->vo_ontop);
-
- XMapRaised(x11->display, x11->window);
- if ( ! (x11->fs_type & vo_wm_FULLSCREEN) ) // some WMs change window pos on map
- XMoveResizeWindow(x11->display, x11->window, x, y, w, h);
- XRaiseWindow(x11->display, x11->window);
- XFlush(x11->display);
-}
-
-void vo_x11_ontop(struct vo *vo)
-{
- struct MPOpts *opts = vo->opts;
- opts->vo_ontop = !opts->vo_ontop;
-
- vo_x11_setlayer(vo, vo->x11->window, opts->vo_ontop);
-}
-
-void vo_x11_border(struct vo *vo)
-{
- vo_border = !vo_border;
- vo_x11_decoration(vo, vo_border && !vo_fs);
-}
-
-/*
- * XScreensaver stuff
- */
-
-static int screensaver_off;
-static unsigned int time_last;
-
-void xscreensaver_heartbeat(struct vo_x11_state *x11)
-{
- unsigned int time = GetTimerMS();
-
- if (x11->display && screensaver_off && (time - time_last) > 30000)
- {
- time_last = time;
-
- XResetScreenSaver(x11->display);
- }
-}
-
-static int xss_suspend(Display *mDisplay, Bool suspend)
-{
-#ifndef CONFIG_XSS
- return 0;
-#else
- int event, error, major, minor;
- if (XScreenSaverQueryExtension(mDisplay, &event, &error) != True ||
- XScreenSaverQueryVersion(mDisplay, &major, &minor) != True)
- return 0;
- if (major < 1 || (major == 1 && minor < 1))
- return 0;
- XScreenSaverSuspend(mDisplay, suspend);
- return 1;
-#endif
-}
-
-/*
- * End of XScreensaver stuff
- */
-
-static void saver_on(Display * mDisplay)
-{
-
- if (!screensaver_off)
- return;
- screensaver_off = 0;
- if (xss_suspend(mDisplay, False))
- return;
-#ifdef CONFIG_XDPMS
- if (dpms_disabled)
- {
- int nothing;
- if (DPMSQueryExtension(mDisplay, &nothing, &nothing))
- {
- if (!DPMSEnable(mDisplay))
- { // restoring power saving settings
- mp_msg(MSGT_VO, MSGL_WARN, "DPMS not available?\n");
- } else
- {
- // DPMS does not seem to be enabled unless we call DPMSInfo
- BOOL onoff;
- CARD16 state;
-
- DPMSForceLevel(mDisplay, DPMSModeOn);
- DPMSInfo(mDisplay, &state, &onoff);
- if (onoff)
- {
- mp_msg(MSGT_VO, MSGL_V,
- "Successfully enabled DPMS\n");
- } else
- {
- mp_msg(MSGT_VO, MSGL_WARN, "Could not enable DPMS\n");
- }
- }
- }
- dpms_disabled = 0;
- }
-#endif
-}
-
-static void saver_off(Display * mDisplay)
-{
- int nothing;
-
- if (!stop_xscreensaver || screensaver_off)
- return;
- screensaver_off = 1;
- if (xss_suspend(mDisplay, True))
- return;
-#ifdef CONFIG_XDPMS
- if (DPMSQueryExtension(mDisplay, &nothing, &nothing))
- {
- BOOL onoff;
- CARD16 state;
-
- DPMSInfo(mDisplay, &state, &onoff);
- if (onoff)
- {
- Status stat;
-
- mp_msg(MSGT_VO, MSGL_V, "Disabling DPMS\n");
- dpms_disabled = 1;
- stat = DPMSDisable(mDisplay); // monitor powersave off
- mp_msg(MSGT_VO, MSGL_V, "DPMSDisable stat: %d\n", stat);
- }
- }
-#endif
-}
-
-static XErrorHandler old_handler = NULL;
-static int selectinput_err = 0;
-static int x11_selectinput_errorhandler(Display * display,
- XErrorEvent * event)
-{
- if (event->error_code == BadAccess)
- {
- selectinput_err = 1;
- mp_msg(MSGT_VO, MSGL_ERR,
- "X11 error: BadAccess during XSelectInput Call\n");
- mp_msg(MSGT_VO, MSGL_ERR,
- "X11 error: The 'ButtonPressMask' mask of specified window has probably already used by another appication (see man XSelectInput)\n");
- /* If you think MPlayer should shutdown with this error,
- * comment out the following line */
- return 0;
- }
- if (old_handler != NULL)
- old_handler(display, event);
- else
- x11_errorhandler(display, event);
- return 0;
-}
-
-void vo_x11_selectinput_witherr(Display * display, Window w,
- long event_mask)
-{
- XSync(display, False);
- old_handler = XSetErrorHandler(x11_selectinput_errorhandler);
- selectinput_err = 0;
- if (vo_nomouse_input)
- {
- XSelectInput(display, w,
- event_mask &
- (~(ButtonPressMask | ButtonReleaseMask)));
- } else
- {
- XSelectInput(display, w, event_mask);
- }
- XSync(display, False);
- XSetErrorHandler(old_handler);
- if (selectinput_err)
- {
- mp_msg(MSGT_VO, MSGL_ERR,
- "X11 error: mpv discards mouse control (reconfiguring)\n");
- XSelectInput(display, w,
- event_mask &
- (~
- (ButtonPressMask | ButtonReleaseMask |
- PointerMotionMask)));
- }
-}
-
-#ifdef CONFIG_XF86VM
-void vo_vm_switch(struct vo *vo)
-{
- struct vo_x11_state *x11 = vo->x11;
- struct MPOpts *opts = vo->opts;
- Display *mDisplay = x11->display;
- int vm_event, vm_error;
- int vm_ver, vm_rev;
- int i, j, have_vm = 0;
- int X = vo->dwidth, Y = vo->dheight;
- int modeline_width, modeline_height;
-
- if (XF86VidModeQueryExtension(mDisplay, &vm_event, &vm_error))
- {
- XF86VidModeQueryVersion(mDisplay, &vm_ver, &vm_rev);
- mp_msg(MSGT_VO, MSGL_V, "XF86VidMode extension v%i.%i\n", vm_ver,
- vm_rev);
- have_vm = 1;
- } else {
- mp_msg(MSGT_VO, MSGL_WARN,
- "XF86VidMode extension not available.\n");
- }
-
- if (have_vm)
- {
- if (vidmodes == NULL)
- XF86VidModeGetAllModeLines(mDisplay, x11->screen, &modecount,
- &vidmodes);
- j = 0;
- modeline_width = vidmodes[0]->hdisplay;
- modeline_height = vidmodes[0]->vdisplay;
-
- for (i = 1; i < modecount; i++)
- if ((vidmodes[i]->hdisplay >= X)
- && (vidmodes[i]->vdisplay >= Y))
- if ((vidmodes[i]->hdisplay <= modeline_width)
- && (vidmodes[i]->vdisplay <= modeline_height))
- {
- modeline_width = vidmodes[i]->hdisplay;
- modeline_height = vidmodes[i]->vdisplay;
- j = i;
- }
-
- mp_tmsg(MSGT_VO, MSGL_INFO, "XF86VM: Selected video mode %dx%d for image size %dx%d.\n",
- modeline_width, modeline_height, X, Y);
- XF86VidModeLockModeSwitch(mDisplay, x11->screen, 0);
- XF86VidModeSwitchToMode(mDisplay, x11->screen, vidmodes[j]);
- XF86VidModeSwitchToMode(mDisplay, x11->screen, vidmodes[j]);
-
- // FIXME: all this is more of a hack than proper solution
- X = (opts->vo_screenwidth - modeline_width) / 2;
- Y = (opts->vo_screenheight - modeline_height) / 2;
- XF86VidModeSetViewPort(mDisplay, x11->screen, X, Y);
- vo->dx = X;
- vo->dy = Y;
- vo->dwidth = modeline_width;
- vo->dheight = modeline_height;
- aspect_save_screenres(vo, modeline_width, modeline_height);
- }
-}
-
-void vo_vm_close(struct vo *vo)
-{
- Display *dpy = vo->x11->display;
- struct MPOpts *opts = vo->opts;
- if (vidmodes != NULL)
- {
- int i;
-
- free(vidmodes);
- vidmodes = NULL;
- XF86VidModeGetAllModeLines(dpy, vo->x11->screen, &modecount,
- &vidmodes);
- for (i = 0; i < modecount; i++)
- if ((vidmodes[i]->hdisplay == opts->vo_screenwidth)
- && (vidmodes[i]->vdisplay == opts->vo_screenheight))
- {
- mp_msg(MSGT_VO, MSGL_INFO,
- "Returning to original mode %dx%d\n",
- opts->vo_screenwidth, opts->vo_screenheight);
- break;
- }
-
- XF86VidModeSwitchToMode(dpy, vo->x11->screen, vidmodes[i]);
- XF86VidModeSwitchToMode(dpy, vo->x11->screen, vidmodes[i]);
- free(vidmodes);
- vidmodes = NULL;
- modecount = 0;
- }
-}
-
-double vo_vm_get_fps(struct vo *vo)
-{
- struct vo_x11_state *x11 = vo->x11;
- int clock;
- XF86VidModeModeLine modeline;
- if (!XF86VidModeGetModeLine(x11->display, x11->screen, &clock, &modeline))
- return 0;
- if (modeline.privsize)
- XFree(modeline.private);
- return 1e3 * clock / modeline.htotal / modeline.vtotal;
-}
-#endif
-
-
-/*
- * Scan the available visuals on this Display/Screen. Try to find
- * the 'best' available TrueColor visual that has a decent color
- * depth (at least 15bit). If there are multiple visuals with depth
- * >= 15bit, we prefer visuals with a smaller color depth.
- */
-int vo_find_depth_from_visuals(Display * dpy, int screen,
- Visual ** visual_return)
-{
- XVisualInfo visual_tmpl;
- XVisualInfo *visuals;
- int nvisuals, i;
- int bestvisual = -1;
- int bestvisual_depth = -1;
-
- visual_tmpl.screen = screen;
- visual_tmpl.class = TrueColor;
- visuals = XGetVisualInfo(dpy,
- VisualScreenMask | VisualClassMask,
- &visual_tmpl, &nvisuals);
- if (visuals != NULL)
- {
- for (i = 0; i < nvisuals; i++)
- {
- mp_msg(MSGT_VO, MSGL_V,
- "vo: X11 truecolor visual %#lx, depth %d, R:%lX G:%lX B:%lX\n",
- visuals[i].visualid, visuals[i].depth,
- visuals[i].red_mask, visuals[i].green_mask,
- visuals[i].blue_mask);
- /*
- * Save the visual index and its depth, if this is the first
- * truecolor visul, or a visual that is 'preferred' over the
- * previous 'best' visual.
- */
- if (bestvisual_depth == -1
- || (visuals[i].depth >= 15
- && (visuals[i].depth < bestvisual_depth
- || bestvisual_depth < 15)))
- {
- bestvisual = i;
- bestvisual_depth = visuals[i].depth;
- }
- }
-
- if (bestvisual != -1 && visual_return != NULL)
- *visual_return = visuals[bestvisual].visual;
-
- XFree(visuals);
- }
- return bestvisual_depth;
-}
-
-
-static Colormap cmap = None;
-static XColor cols[256];
-static int cm_size, red_mask, green_mask, blue_mask;
-
-
-Colormap vo_x11_create_colormap(struct vo *vo, XVisualInfo *vinfo)
-{
- struct vo_x11_state *x11 = vo->x11;
- unsigned k, r, g, b, ru, gu, bu, m, rv, gv, bv, rvu, gvu, bvu;
-
- if (vinfo->class != DirectColor)
- return XCreateColormap(x11->display, x11->rootwin, vinfo->visual,
- AllocNone);
-
- /* can this function get called twice or more? */
- if (cmap)
- return cmap;
- cm_size = vinfo->colormap_size;
- red_mask = vinfo->red_mask;
- green_mask = vinfo->green_mask;
- blue_mask = vinfo->blue_mask;
- ru = (red_mask & (red_mask - 1)) ^ red_mask;
- gu = (green_mask & (green_mask - 1)) ^ green_mask;
- bu = (blue_mask & (blue_mask - 1)) ^ blue_mask;
- rvu = 65536ull * ru / (red_mask + ru);
- gvu = 65536ull * gu / (green_mask + gu);
- bvu = 65536ull * bu / (blue_mask + bu);
- r = g = b = 0;
- rv = gv = bv = 0;
- m = DoRed | DoGreen | DoBlue;
- for (k = 0; k < cm_size; k++)
- {
- int t;
-
- cols[k].pixel = r | g | b;
- cols[k].red = rv;
- cols[k].green = gv;
- cols[k].blue = bv;
- cols[k].flags = m;
- t = (r + ru) & red_mask;
- if (t < r)
- m &= ~DoRed;
- r = t;
- t = (g + gu) & green_mask;
- if (t < g)
- m &= ~DoGreen;
- g = t;
- t = (b + bu) & blue_mask;
- if (t < b)
- m &= ~DoBlue;
- b = t;
- rv += rvu;
- gv += gvu;
- bv += bvu;
- }
- cmap = XCreateColormap(x11->display, x11->rootwin, vinfo->visual, AllocAll);
- XStoreColors(x11->display, cmap, cols, cm_size);
- return cmap;
-}
-
-/*
- * Via colormaps/gamma ramps we can do gamma, brightness, contrast,
- * hue and red/green/blue intensity, but we cannot do saturation.
- * Currently only gamma, brightness and contrast are implemented.
- * Is there sufficient interest for hue and/or red/green/blue intensity?
- */
-/* these values have range [-100,100] and are initially 0 */
-static int vo_gamma = 0;
-static int vo_brightness = 0;
-static int vo_contrast = 0;
-
-static int transform_color(float val,
- float brightness, float contrast, float gamma) {
- float s = pow(val, gamma);
- s = (s - 0.5) * contrast + 0.5;
- s += brightness;
- if (s < 0)
- s = 0;
- if (s > 1)
- s = 1;
- return (unsigned short) (s * 65535);
-}
-
-uint32_t vo_x11_set_equalizer(struct vo *vo, const char *name, int value)
-{
- float gamma, brightness, contrast;
- float rf, gf, bf;
- int k;
-
- /*
- * IMPLEMENTME: consider using XF86VidModeSetGammaRamp in the case
- * of TrueColor-ed window but be careful:
- * Unlike the colormaps, which are private for the X client
- * who created them and thus automatically destroyed on client
- * disconnect, this gamma ramp is a system-wide (X-server-wide)
- * setting and _must_ be restored before the process exits.
- * Unforunately when the process crashes (or gets killed
- * for some reason) it is impossible to restore the setting,
- * and such behaviour could be rather annoying for the users.
- */
- if (cmap == None)
- return VO_NOTAVAIL;
-
- if (!strcasecmp(name, "brightness"))
- vo_brightness = value;
- else if (!strcasecmp(name, "contrast"))
- vo_contrast = value;
- else if (!strcasecmp(name, "gamma"))
- vo_gamma = value;
- else
- return VO_NOTIMPL;
-
- brightness = 0.01 * vo_brightness;
- contrast = tan(0.0095 * (vo_contrast + 100) * M_PI / 4);
- gamma = pow(2, -0.02 * vo_gamma);
-
- rf = (float) ((red_mask & (red_mask - 1)) ^ red_mask) / red_mask;
- gf = (float) ((green_mask & (green_mask - 1)) ^ green_mask) /
- green_mask;
- bf = (float) ((blue_mask & (blue_mask - 1)) ^ blue_mask) / blue_mask;
-
- /* now recalculate the colormap using the newly set value */
- for (k = 0; k < cm_size; k++)
- {
- cols[k].red = transform_color(rf * k, brightness, contrast, gamma);
- cols[k].green = transform_color(gf * k, brightness, contrast, gamma);
- cols[k].blue = transform_color(bf * k, brightness, contrast, gamma);
- }
-
- XStoreColors(vo->x11->display, cmap, cols, cm_size);
- XFlush(vo->x11->display);
- return VO_TRUE;
-}
-
-uint32_t vo_x11_get_equalizer(const char *name, int *value)
-{
- if (cmap == None)
- return VO_NOTAVAIL;
- if (!strcasecmp(name, "brightness"))
- *value = vo_brightness;
- else if (!strcasecmp(name, "contrast"))
- *value = vo_contrast;
- else if (!strcasecmp(name, "gamma"))
- *value = vo_gamma;
- else
- return VO_NOTIMPL;
- return VO_TRUE;
-}
-
-bool vo_x11_screen_is_composited(struct vo *vo)
-{
- struct vo_x11_state *x11 = vo->x11;
- return XGetSelectionOwner(x11->display, x11->XA_NET_WM_CM) != None;
-}
-
-#ifdef CONFIG_XV
-
-static int xv_find_atom(struct vo *vo, uint32_t xv_port, const char *name,
- bool get, int *min, int *max)
-{
- Atom atom = None;
- int howmany = 0;
- XvAttribute *attributes = XvQueryPortAttributes(vo->x11->display, xv_port,
- &howmany);
- for (int i = 0; i < howmany && attributes; i++) {
- int flag = get ? XvGettable : XvSettable;
- if (attributes[i].flags & flag) {
- atom = XInternAtom(vo->x11->display, attributes[i].name, True);
- *min = attributes[i].min_value;
- *max = attributes[i].max_value;
-/* since we have SET_DEFAULTS first in our list, we can check if it's available
- then trigger it if it's ok so that the other values are at default upon query */
- if (atom != None) {
- if (!strcmp(attributes[i].name, "XV_BRIGHTNESS") &&
- (!strcasecmp(name, "brightness")))
- break;
- else if (!strcmp(attributes[i].name, "XV_CONTRAST") &&
- (!strcasecmp(name, "contrast")))
- break;
- else if (!strcmp(attributes[i].name, "XV_SATURATION") &&
- (!strcasecmp(name, "saturation")))
- break;
- else if (!strcmp(attributes[i].name, "XV_HUE") &&
- (!strcasecmp(name, "hue")))
- break;
- if (!strcmp(attributes[i].name, "XV_RED_INTENSITY") &&
- (!strcasecmp(name, "red_intensity")))
- break;
- else if (!strcmp(attributes[i].name, "XV_GREEN_INTENSITY")
- && (!strcasecmp(name, "green_intensity")))
- break;
- else if (!strcmp(attributes[i].name, "XV_BLUE_INTENSITY")
- && (!strcasecmp(name, "blue_intensity")))
- break;
- else if ((!strcmp(attributes[i].name, "XV_ITURBT_709") //NVIDIA
- || !strcmp(attributes[i].name, "XV_COLORSPACE"))//ATI
- && (!strcasecmp(name, "bt_709")))
- break;
- atom = None;
- continue;
- }
- }
- }
- XFree(attributes);
- return atom;
-}
-
-int vo_xv_set_eq(struct vo *vo, uint32_t xv_port, const char *name, int value)
-{
- mp_dbg(MSGT_VO, MSGL_V, "xv_set_eq called! (%s, %d)\n", name, value);
-
- int min, max;
- int atom = xv_find_atom(vo, xv_port, name, false, &min, &max);
- if (atom != None) {
- // -100 -> min
- // 0 -> (max+min)/2
- // +100 -> max
- int port_value = (value + 100) * (max - min) / 200 + min;
- XvSetPortAttribute(vo->x11->display, xv_port, atom, port_value);
- return VO_TRUE;
- }
- return VO_FALSE;
-}
-
-int vo_xv_get_eq(struct vo *vo, uint32_t xv_port, const char *name, int *value)
-{
- int min, max;
- int atom = xv_find_atom(vo, xv_port, name, true, &min, &max);
- if (atom != None) {
- int port_value = 0;
- XvGetPortAttribute(vo->x11->display, xv_port, atom, &port_value);
-
- *value = (port_value - min) * 200 / (max - min) - 100;
- mp_dbg(MSGT_VO, MSGL_V, "xv_get_eq called! (%s, %d)\n",
- name, *value);
- return VO_TRUE;
- }
- return VO_FALSE;
-}
-
-/**
- * \brief Interns the requested atom if it is available.
- *
- * \param atom_name String containing the name of the requested atom.
- *
- * \return Returns the atom if available, else None is returned.
- *
- */
-static Atom xv_intern_atom_if_exists(struct vo_x11_state *x11,
- char const *atom_name)
-{
- XvAttribute * attributes;
- int attrib_count,i;
- Atom xv_atom = None;
-
- attributes = XvQueryPortAttributes(x11->display, x11->xv_port, &attrib_count );
- if( attributes!=NULL )
- {
- for ( i = 0; i < attrib_count; ++i )
- {
- if ( strcmp(attributes[i].name, atom_name ) == 0 )
- {
- xv_atom = XInternAtom(x11->display, atom_name, False );
- break; // found what we want, break out
- }
- }
- XFree( attributes );
- }
-
- return xv_atom;
-}
-
-/**
- * \brief Try to enable vsync for xv.
- * \return Returns -1 if not available, 0 on failure and 1 on success.
- */
-int vo_xv_enable_vsync(struct vo *vo)
-{
- struct vo_x11_state *x11 = vo->x11;
- Atom xv_atom = xv_intern_atom_if_exists(x11, "XV_SYNC_TO_VBLANK");
- if (xv_atom == None)
- return -1;
- return XvSetPortAttribute(x11->display, x11->xv_port, xv_atom, 1) == Success;
-}
-
-/**
- * \brief Get maximum supported source image dimensions.
- *
- * This function does not set the variables pointed to by
- * width and height if the information could not be retrieved,
- * so the caller is reponsible for properly initializing them.
- *
- * \param width [out] The maximum width gets stored here.
- * \param height [out] The maximum height gets stored here.
- *
- */
-void vo_xv_get_max_img_dim(struct vo *vo, uint32_t * width, uint32_t * height)
-{
- struct vo_x11_state *x11 = vo->x11;
- XvEncodingInfo * encodings;
- //unsigned long num_encodings, idx; to int or too long?!
- unsigned int num_encodings, idx;
-
- XvQueryEncodings(x11->display, x11->xv_port, &num_encodings, &encodings);
-
- if ( encodings )
- {
- for ( idx = 0; idx < num_encodings; ++idx )
- {
- if ( strcmp( encodings[idx].name, "XV_IMAGE" ) == 0 )
- {
- *width = encodings[idx].width;
- *height = encodings[idx].height;
- break;
- }
- }
- }
-
- mp_msg( MSGT_VO, MSGL_V,
- "[xv common] Maximum source image dimensions: %ux%u\n",
- *width, *height );
-
- XvFreeEncodingInfo( encodings );
-}
-
-/**
- * \brief Print information about the colorkey method and source.
- *
- * \param ck_handling Integer value containing the information about
- * colorkey handling (see x11_common.h).
- *
- * Outputs the content of |ck_handling| as a readable message.
- *
- */
-static void vo_xv_print_ck_info(struct vo_x11_state *x11)
-{
- mp_msg( MSGT_VO, MSGL_V, "[xv common] " );
-
- switch ( x11->xv_ck_info.method )
- {
- case CK_METHOD_NONE:
- mp_msg( MSGT_VO, MSGL_V, "Drawing no colorkey.\n" ); return;
- case CK_METHOD_AUTOPAINT:
- mp_msg( MSGT_VO, MSGL_V, "Colorkey is drawn by Xv." ); break;
- case CK_METHOD_MANUALFILL:
- mp_msg( MSGT_VO, MSGL_V, "Drawing colorkey manually." ); break;
- case CK_METHOD_BACKGROUND:
- mp_msg( MSGT_VO, MSGL_V, "Colorkey is drawn as window background." ); break;
- }
-
- mp_msg( MSGT_VO, MSGL_V, "\n[xv common] " );
-
- switch ( x11->xv_ck_info.source )
- {
- case CK_SRC_CUR:
- mp_msg( MSGT_VO, MSGL_V, "Using colorkey from Xv (0x%06lx).\n",
- x11->xv_colorkey );
- break;
- case CK_SRC_USE:
- if ( x11->xv_ck_info.method == CK_METHOD_AUTOPAINT )
- {
- mp_msg( MSGT_VO, MSGL_V,
- "Ignoring colorkey from mpv (0x%06lx).\n",
- x11->xv_colorkey );
- }
- else
- {
- mp_msg( MSGT_VO, MSGL_V,
- "Using colorkey from mpv (0x%06lx)."
- " Use -colorkey to change.\n",
- x11->xv_colorkey );
- }
- break;
- case CK_SRC_SET:
- mp_msg( MSGT_VO, MSGL_V,
- "Setting and using colorkey from mpv (0x%06lx)."
- " Use -colorkey to change.\n",
- x11->xv_colorkey );
- break;
- }
-}
-/**
- * \brief Init colorkey depending on the settings in xv_ck_info.
- *
- * \return Returns 0 on failure and 1 on success.
- *
- * Sets the colorkey variable according to the CK_SRC_* and CK_METHOD_*
- * flags in xv_ck_info.
- *
- * Possiblilities:
- * * Methods
- * - manual colorkey drawing ( CK_METHOD_MANUALFILL )
- * - set colorkey as window background ( CK_METHOD_BACKGROUND )
- * - let Xv paint the colorkey ( CK_METHOD_AUTOPAINT )
- * * Sources
- * - use currently set colorkey ( CK_SRC_CUR )
- * - use colorkey in vo_colorkey ( CK_SRC_USE )
- * - use and set colorkey in vo_colorkey ( CK_SRC_SET )
- *
- * NOTE: If vo_colorkey has bits set after the first 3 low order bytes
- * we don't draw anything as this means it was forced to off.
- */
-int vo_xv_init_colorkey(struct vo *vo)
-{
- struct vo_x11_state *x11 = vo->x11;
- Atom xv_atom;
- int rez;
-
- /* check if colorkeying is needed */
- xv_atom = xv_intern_atom_if_exists(vo->x11, "XV_COLORKEY");
-
- /* if we have to deal with colorkeying ... */
- if( xv_atom != None && !(vo_colorkey & 0xFF000000) )
- {
- /* check if we should use the colorkey specified in vo_colorkey */
- if ( x11->xv_ck_info.source != CK_SRC_CUR )
- {
- x11->xv_colorkey = vo_colorkey;
-
- /* check if we have to set the colorkey too */
- if ( x11->xv_ck_info.source == CK_SRC_SET )
- {
- xv_atom = XInternAtom(x11->display, "XV_COLORKEY",False);
-
- rez = XvSetPortAttribute(x11->display, x11->xv_port, xv_atom, vo_colorkey);
- if ( rez != Success )
- {
- mp_msg( MSGT_VO, MSGL_FATAL,
- "[xv common] Couldn't set colorkey!\n" );
- return 0; // error setting colorkey
- }
- }
- }
- else
- {
- int colorkey_ret;
-
- rez=XvGetPortAttribute(x11->display,x11->xv_port, xv_atom, &colorkey_ret);
- if ( rez == Success )
- {
- x11->xv_colorkey = colorkey_ret;
- }
- else
- {
- mp_msg( MSGT_VO, MSGL_FATAL,
- "[xv common] Couldn't get colorkey!"
- "Maybe the selected Xv port has no overlay.\n" );
- return 0; // error getting colorkey
- }
- }
-
- xv_atom = xv_intern_atom_if_exists(vo->x11, "XV_AUTOPAINT_COLORKEY");
-
- /* should we draw the colorkey ourselves or activate autopainting? */
- if ( x11->xv_ck_info.method == CK_METHOD_AUTOPAINT )
- {
- rez = !Success; // reset rez to something different than Success
-
- if ( xv_atom != None ) // autopaint is supported
- {
- rez = XvSetPortAttribute(x11->display, x11->xv_port, xv_atom, 1);
- }
-
- if ( rez != Success )
- {
- // fallback to manual colorkey drawing
- x11->xv_ck_info.method = CK_METHOD_MANUALFILL;
- }
- }
- else // disable colorkey autopainting if supported
- {
- if ( xv_atom != None ) // we have autopaint attribute
- {
- XvSetPortAttribute(x11->display, x11->xv_port, xv_atom, 0);
- }
- }
- }
- else // do no colorkey drawing at all
- {
- x11->xv_ck_info.method = CK_METHOD_NONE;
- } /* end: should we draw colorkey */
-
- /* output information about the current colorkey settings */
- vo_xv_print_ck_info(x11);
-
- return 1; // success
-}
-
-/**
- * \brief Draw the colorkey on the video window.
- *
- * Draws the colorkey depending on the set method ( colorkey_handling ).
- *
- * Also draws the black bars ( when the video doesn't fit the display in
- * fullscreen ) separately, so they don't overlap with the video area.
- * It doesn't call XFlush.
- *
- */
-void vo_xv_draw_colorkey(struct vo *vo, int32_t x, int32_t y,
- int32_t w, int32_t h)
-{
- struct vo_x11_state *x11 = vo->x11;
- if( x11->xv_ck_info.method == CK_METHOD_MANUALFILL ||
- x11->xv_ck_info.method == CK_METHOD_BACKGROUND )//less tearing than XClearWindow()
- {
- XSetForeground(x11->display, x11->vo_gc, x11->xv_colorkey );
- XFillRectangle(x11->display, x11->window, x11->vo_gc,
- x, y,
- w, h );
- }
-}
-
-/** \brief Tests if a valid argument for the ck suboption was given. */
-int xv_test_ck( void * arg )
-{
- strarg_t * strarg = (strarg_t *)arg;
-
- if ( strargcmp( strarg, "use" ) == 0 ||
- strargcmp( strarg, "set" ) == 0 ||
- strargcmp( strarg, "cur" ) == 0 )
- {
- return 1;
- }
-
- return 0;
-}
-/** \brief Tests if a valid arguments for the ck-method suboption was given. */
-int xv_test_ckm( void * arg )
-{
- strarg_t * strarg = (strarg_t *)arg;
-
- if ( strargcmp( strarg, "bg" ) == 0 ||
- strargcmp( strarg, "man" ) == 0 ||
- strargcmp( strarg, "auto" ) == 0 )
- {
- return 1;
- }
-
- return 0;
-}
-
-/**
- * \brief Modify the colorkey_handling var according to str
- *
- * Checks if a valid pointer ( not NULL ) to the string
- * was given. And in that case modifies the colorkey_handling
- * var to reflect the requested behaviour.
- * If nothing happens the content of colorkey_handling stays
- * the same.
- *
- * \param str Pointer to the string or NULL
- *
- */
-void xv_setup_colorkeyhandling(struct vo *vo, const char *ck_method_str,
- const char *ck_str)
-{
- struct vo_x11_state *x11 = vo->x11;
- /* check if a valid pointer to the string was passed */
- if ( ck_str )
- {
- if ( strncmp( ck_str, "use", 3 ) == 0 )
- {
- x11->xv_ck_info.source = CK_SRC_USE;
- }
- else if ( strncmp( ck_str, "set", 3 ) == 0 )
- {
- x11->xv_ck_info.source = CK_SRC_SET;
- }
- }
- /* check if a valid pointer to the string was passed */
- if ( ck_method_str )
- {
- if ( strncmp( ck_method_str, "bg", 2 ) == 0 )
- {
- x11->xv_ck_info.method = CK_METHOD_BACKGROUND;
- }
- else if ( strncmp( ck_method_str, "man", 3 ) == 0 )
- {
- x11->xv_ck_info.method = CK_METHOD_MANUALFILL;
- }
- else if ( strncmp( ck_method_str, "auto", 4 ) == 0 )
- {
- x11->xv_ck_info.method = CK_METHOD_AUTOPAINT;
- }
- }
-}
-
-#endif
-
-struct vo_x11_state *vo_x11_init_state(void)
-{
- struct vo_x11_state *s = talloc_ptrtype(NULL, s);
- *s = (struct vo_x11_state){
- .xv_ck_info = { CK_METHOD_MANUALFILL, CK_SRC_CUR },
- .olddecor = MWM_DECOR_ALL,
- .oldfuncs = MWM_FUNC_MOVE | MWM_FUNC_CLOSE | MWM_FUNC_MINIMIZE |
- MWM_FUNC_MAXIMIZE | MWM_FUNC_RESIZE,
- .old_gravity = NorthWestGravity,
- };
- return s;
-}
diff --git a/libvo/x11_common.h b/libvo/x11_common.h
deleted file mode 100644
index cb8b39a3b1..0000000000
--- a/libvo/x11_common.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_X11_COMMON_H
-#define MPLAYER_X11_COMMON_H
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-#include "config.h"
-
-struct vo;
-
-struct vo_x11_state {
- Display *display;
- Window window;
- Window rootwin;
- int screen;
- int display_is_local;
- int depthonscreen;
-
- XIM xim;
- XIC xic;
-
- GC vo_gc;
-
- struct xv_ck_info_s {
- int method; ///< CK_METHOD_* constants
- int source; ///< CK_SRC_* constants
- } xv_ck_info;
- unsigned long xv_colorkey;
- unsigned int xv_port;
-
- int wm_type;
- int fs_type;
- int window_state;
- int fs_flip;
-
- GC f_gc;
- XSizeHints vo_hint;
- unsigned int mouse_timer;
- int mouse_waiting_hide;
- int orig_layer;
- int old_gravity;
- int vo_old_x;
- int vo_old_y;
- int vo_old_width;
- int vo_old_height;
-
- /* Keep track of original video width/height to determine when to
- * resize window when reconfiguring. Resize window when video size
- * changes, but don't force window size changes as long as video size
- * stays the same (even if that size is different from the current
- * window size after the user modified the latter). */
- int last_video_width;
- int last_video_height;
- /* Video size changed during fullscreen when we couldn't tell the new
- * size to the window manager. Must set window size when turning
- * fullscreen off. */
- bool size_changed_during_fs;
-
- unsigned int olddecor;
- unsigned int oldfuncs;
- XComposeStatus compose_status;
-
- Atom XA_NET_SUPPORTED;
- Atom XA_NET_WM_STATE;
- Atom XA_NET_WM_STATE_FULLSCREEN;
- Atom XA_NET_WM_STATE_ABOVE;
- Atom XA_NET_WM_STATE_STAYS_ON_TOP;
- Atom XA_NET_WM_STATE_BELOW;
- Atom XA_NET_WM_PID;
- Atom XA_NET_WM_NAME;
- Atom XA_NET_WM_ICON_NAME;
- Atom XA_WIN_PROTOCOLS;
- Atom XA_WIN_LAYER;
- Atom XA_WIN_HINTS;
- Atom XAWM_PROTOCOLS;
- Atom XAWM_DELETE_WINDOW;
- Atom XAUTF8_STRING;
- Atom XA_NET_WM_CM;
-};
-
-#define vo_wm_LAYER 1
-#define vo_wm_FULLSCREEN 2
-#define vo_wm_STAYS_ON_TOP 4
-#define vo_wm_ABOVE 8
-#define vo_wm_BELOW 16
-#define vo_wm_NETWM (vo_wm_FULLSCREEN | vo_wm_STAYS_ON_TOP | vo_wm_ABOVE | vo_wm_BELOW)
-
-/* EWMH state actions, see
- http://freedesktop.org/Standards/wm-spec/index.html#id2768769 */
-#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
-#define _NET_WM_STATE_ADD 1 /* add/set property */
-#define _NET_WM_STATE_TOGGLE 2 /* toggle property */
-
-extern int metacity_hack;
-
-extern char** vo_fstype_list;
-
-extern char *mDisplayName;
-
-struct vo_x11_state *vo_x11_init_state(void);
-int vo_init(struct vo *vo);
-void vo_uninit(struct vo_x11_state *x11);
-void vo_x11_decoration(struct vo *vo, int d );
-void vo_x11_classhint(struct vo *vo, Window window, const char *name);
-void vo_x11_sizehint(struct vo *vo, int x, int y, int width, int height, int max);
-int vo_x11_check_events(struct vo *vo);
-void vo_x11_selectinput_witherr(Display *display, Window w, long event_mask);
-void vo_x11_fullscreen(struct vo *vo);
-int vo_x11_update_geometry(struct vo *vo, bool update_pos);
-void vo_x11_setlayer(struct vo *vo, Window vo_window, int layer);
-void vo_x11_uninit(struct vo *vo);
-Colormap vo_x11_create_colormap(struct vo *vo, XVisualInfo *vinfo);
-uint32_t vo_x11_set_equalizer(struct vo *vo, const char *name, int value);
-uint32_t vo_x11_get_equalizer(const char *name, int *value);
-bool vo_x11_screen_is_composited(struct vo *vo);
-void fstype_help(void);
-void vo_x11_create_vo_window(struct vo *vo, XVisualInfo *vis,
- int x, int y, unsigned int width, unsigned int height, int flags,
- Colormap col_map, const char *classname);
-void vo_x11_clearwindow_part(struct vo *vo, Window vo_window,
- int img_width, int img_height);
-void vo_x11_clearwindow(struct vo *vo, Window vo_window);
-void vo_x11_ontop(struct vo *vo);
-void vo_x11_border(struct vo *vo);
-void vo_x11_ewmh_fullscreen(struct vo_x11_state *x11, int action);
-
-
-int vo_xv_set_eq(struct vo *vo, uint32_t xv_port, const char *name, int value);
-int vo_xv_get_eq(struct vo *vo, uint32_t xv_port, const char *name, int *value);
-
-int vo_xv_enable_vsync(struct vo *vo);
-
-void vo_xv_get_max_img_dim(struct vo *vo, uint32_t * width, uint32_t * height);
-
-/*** colorkey handling ***/
-
-#define CK_METHOD_NONE 0 ///< no colorkey drawing
-#define CK_METHOD_BACKGROUND 1 ///< set colorkey as window background
-#define CK_METHOD_AUTOPAINT 2 ///< let xv draw the colorkey
-#define CK_METHOD_MANUALFILL 3 ///< manually draw the colorkey
-#define CK_SRC_USE 0 ///< use specified / default colorkey
-#define CK_SRC_SET 1 ///< use and set specified / default colorkey
-#define CK_SRC_CUR 2 ///< use current colorkey ( get it from xv )
-
-int vo_xv_init_colorkey(struct vo *vo);
-void vo_xv_draw_colorkey(struct vo *vo, int32_t x, int32_t y, int32_t w, int32_t h);
-void xv_setup_colorkeyhandling(struct vo *vo, const char *ck_method_str, const char *ck_str);
-
-/*** test functions for common suboptions ***/
-int xv_test_ck( void * arg );
-int xv_test_ckm( void * arg );
-
-#ifdef CONFIG_XF86VM
-void vo_vm_switch(struct vo *vo);
-void vo_vm_close(struct vo *vo);
-double vo_vm_get_fps(struct vo *vo);
-#endif
-
-void update_xinerama_info(struct vo *vo);
-
-int vo_find_depth_from_visuals(Display *dpy, int screen, Visual **visual_return);
-void xscreensaver_heartbeat(struct vo_x11_state *x11);
-
-#endif /* MPLAYER_X11_COMMON_H */