2009-02-08 04:27:30 +01:00
|
|
|
/*
|
|
|
|
* 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.
|
2010-06-13 12:42:32 +02:00
|
|
|
*
|
|
|
|
* 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.
|
2009-02-08 04:27:30 +01:00
|
|
|
*/
|
|
|
|
|
2001-02-24 21:28:24 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2005-09-15 00:08:04 +02:00
|
|
|
#include <math.h>
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
#include <stdbool.h>
|
2001-02-24 21:28:24 +01:00
|
|
|
|
|
|
|
#include "config.h"
|
2005-08-14 21:24:49 +02:00
|
|
|
#include "mp_msg.h"
|
2004-12-31 15:58:49 +01:00
|
|
|
#include "subopt-helper.h"
|
2001-02-24 21:28:24 +01:00
|
|
|
#include "video_out.h"
|
|
|
|
#include "video_out_internal.h"
|
2011-01-26 18:40:52 +01:00
|
|
|
#include "sub/font_load.h"
|
|
|
|
#include "sub/sub.h"
|
2001-02-24 21:28:24 +01:00
|
|
|
|
2004-10-17 15:28:22 +02:00
|
|
|
#include "gl_common.h"
|
2001-10-03 19:27:13 +02:00
|
|
|
#include "aspect.h"
|
2008-05-10 14:21:37 +02:00
|
|
|
#include "fastmemcpy.h"
|
2011-01-26 18:40:52 +01:00
|
|
|
#include "sub/ass_mp.h"
|
2001-03-03 22:46:39 +01:00
|
|
|
|
2010-04-24 18:52:06 +02:00
|
|
|
#ifdef CONFIG_GL_SDL
|
|
|
|
#ifdef CONFIG_SDL_SDL_H
|
|
|
|
#include <SDL/SDL.h>
|
|
|
|
#else
|
|
|
|
#include <SDL.h>
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2009-07-07 01:26:13 +02:00
|
|
|
static const vo_info_t info =
|
2001-02-24 21:28:24 +01:00
|
|
|
{
|
2010-02-27 19:20:22 +01:00
|
|
|
"OpenGL",
|
2006-08-28 22:38:31 +02:00
|
|
|
"gl",
|
2010-02-27 19:20:22 +01:00
|
|
|
"Reimar Doeffinger <Reimar.Doeffinger@gmx.de>",
|
2006-08-28 22:38:31 +02:00
|
|
|
""
|
2001-02-24 21:28:24 +01:00
|
|
|
};
|
|
|
|
|
2007-12-02 15:39:15 +01:00
|
|
|
const LIBVO_EXTERN(gl)
|
2002-11-11 16:22:10 +01:00
|
|
|
|
2010-02-27 19:16:41 +01:00
|
|
|
|
|
|
|
static const vo_info_t info_nosw =
|
|
|
|
{
|
2010-02-27 19:20:22 +01:00
|
|
|
"OpenGL no software rendering",
|
2010-02-27 19:16:41 +01:00
|
|
|
"gl_nosw",
|
2010-02-27 19:20:22 +01:00
|
|
|
"Reimar Doeffinger <Reimar.Doeffinger@gmx.de>",
|
2010-02-27 19:16:41 +01:00
|
|
|
""
|
|
|
|
};
|
|
|
|
static int preinit_nosw(const char *arg);
|
2010-03-10 01:14:30 +01:00
|
|
|
const struct vo_driver video_out_gl_nosw =
|
|
|
|
{
|
|
|
|
.is_new = 0,
|
|
|
|
.info = &info_nosw,
|
|
|
|
.preinit = old_vo_preinit,
|
|
|
|
.config = old_vo_config,
|
|
|
|
.control = old_vo_control,
|
|
|
|
.draw_slice = old_vo_draw_slice,
|
|
|
|
.draw_osd = old_vo_draw_osd,
|
|
|
|
.flip_page = old_vo_flip_page,
|
|
|
|
.check_events = old_vo_check_events,
|
|
|
|
.uninit = old_vo_uninit,
|
|
|
|
.old_functions = &(struct vo_old_functions){
|
|
|
|
preinit_nosw,
|
|
|
|
config,
|
|
|
|
control,
|
|
|
|
draw_frame,
|
|
|
|
draw_slice,
|
|
|
|
draw_osd,
|
|
|
|
flip_page,
|
|
|
|
check_events,
|
|
|
|
uninit,
|
|
|
|
}
|
|
|
|
};
|
2010-02-27 19:16:41 +01:00
|
|
|
|
2009-12-08 07:42:46 +01:00
|
|
|
static MPGLContext glctx;
|
2001-02-24 21:28:24 +01:00
|
|
|
|
2004-10-10 14:26:58 +02:00
|
|
|
static int use_osd;
|
2004-10-17 21:32:47 +02:00
|
|
|
static int scaled_osd;
|
2004-12-29 15:33:40 +01:00
|
|
|
//! How many parts the OSD may consist of at most
|
2004-10-08 21:53:11 +02:00
|
|
|
#define MAX_OSD_PARTS 20
|
2004-12-29 15:33:40 +01:00
|
|
|
//! Textures for OSD
|
2004-10-10 14:26:58 +02:00
|
|
|
static GLuint osdtex[MAX_OSD_PARTS];
|
2004-10-08 21:53:11 +02:00
|
|
|
#ifndef FAST_OSD
|
2004-12-29 15:33:40 +01:00
|
|
|
//! Alpha textures for OSD
|
2004-10-10 14:26:58 +02:00
|
|
|
static GLuint osdatex[MAX_OSD_PARTS];
|
2004-10-08 21:53:11 +02:00
|
|
|
#endif
|
2006-08-28 22:17:42 +02:00
|
|
|
static GLuint *eosdtex;
|
2009-03-06 13:56:13 +01:00
|
|
|
#define LARGE_EOSD_TEX_SIZE 512
|
|
|
|
#define TINYTEX_SIZE 16
|
|
|
|
#define TINYTEX_COLS (LARGE_EOSD_TEX_SIZE/TINYTEX_SIZE)
|
|
|
|
#define TINYTEX_MAX (TINYTEX_COLS*TINYTEX_COLS)
|
|
|
|
#define SMALLTEX_SIZE 32
|
|
|
|
#define SMALLTEX_COLS (LARGE_EOSD_TEX_SIZE/SMALLTEX_SIZE)
|
|
|
|
#define SMALLTEX_MAX (SMALLTEX_COLS*SMALLTEX_COLS)
|
2006-09-22 22:23:17 +02:00
|
|
|
static GLuint largeeosdtex[2];
|
2004-12-29 15:33:40 +01:00
|
|
|
//! Display lists that draw the OSD parts
|
2004-10-10 14:26:58 +02:00
|
|
|
static GLuint osdDispList[MAX_OSD_PARTS];
|
2006-06-15 10:43:41 +02:00
|
|
|
#ifndef FAST_OSD
|
|
|
|
static GLuint osdaDispList[MAX_OSD_PARTS];
|
|
|
|
#endif
|
2006-08-28 22:17:42 +02:00
|
|
|
static GLuint eosdDispList;
|
2004-12-29 15:33:40 +01:00
|
|
|
//! How many parts the OSD currently consists of
|
2005-09-09 16:47:54 +02:00
|
|
|
static int osdtexCnt;
|
2006-08-28 22:17:42 +02:00
|
|
|
static int eosdtexCnt;
|
2006-03-26 12:43:56 +02:00
|
|
|
static int osd_color;
|
2001-02-24 21:28:24 +01:00
|
|
|
|
2004-10-10 16:05:29 +02:00
|
|
|
static int use_aspect;
|
2008-12-05 16:36:54 +01:00
|
|
|
static int use_ycbcr;
|
2009-12-19 21:48:23 +01:00
|
|
|
#define MASK_ALL_YUV (~(1 << YUV_CONVERSION_NONE))
|
2010-05-09 23:25:38 +02:00
|
|
|
#define MASK_NOT_COMBINERS (~((1 << YUV_CONVERSION_NONE) | (1 << YUV_CONVERSION_COMBINERS)))
|
2009-12-19 21:48:23 +01:00
|
|
|
#define MASK_GAMMA_SUPPORT (MASK_NOT_COMBINERS & ~(1 << YUV_CONVERSION_FRAGMENT))
|
2005-09-15 00:08:04 +02:00
|
|
|
static int use_yuv;
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
static struct mp_csp_details colorspace = MP_CSP_DETAILS_DEFAULTS;
|
|
|
|
static int user_colorspace; //essentially unused; legacy warning
|
|
|
|
static int levelconv; //essentially unused; legacy warning
|
2009-12-30 12:32:24 +01:00
|
|
|
static int is_yuv;
|
2006-06-07 15:24:54 +02:00
|
|
|
static int lscale;
|
|
|
|
static int cscale;
|
2008-05-24 13:19:38 +02:00
|
|
|
static float filter_strength;
|
2006-06-07 15:24:54 +02:00
|
|
|
static int yuvconvtype;
|
2005-07-26 12:16:18 +02:00
|
|
|
static int use_rectangle;
|
|
|
|
static int err_shown;
|
2001-02-24 21:28:24 +01:00
|
|
|
static uint32_t image_width;
|
|
|
|
static uint32_t image_height;
|
2005-09-15 00:08:04 +02:00
|
|
|
static uint32_t image_format;
|
2004-04-08 23:50:29 +02:00
|
|
|
static int many_fmts;
|
2008-05-10 13:48:17 +02:00
|
|
|
static int ati_hack;
|
2008-05-10 14:21:37 +02:00
|
|
|
static int force_pbo;
|
2008-12-05 23:16:45 +01:00
|
|
|
static int mesa_buffer;
|
2005-08-16 20:27:12 +02:00
|
|
|
static int use_glFinish;
|
2005-08-19 11:31:02 +02:00
|
|
|
static int swap_interval;
|
2005-07-26 12:16:18 +02:00
|
|
|
static GLenum gl_target;
|
2005-08-25 14:45:57 +02:00
|
|
|
static GLint gl_texfmt;
|
2004-04-08 23:50:29 +02:00
|
|
|
static GLenum gl_format;
|
|
|
|
static GLenum gl_type;
|
2005-09-09 16:49:13 +02:00
|
|
|
static GLuint gl_buffer;
|
2008-11-24 12:04:50 +01:00
|
|
|
static GLuint gl_buffer_uv[2];
|
2005-07-26 12:16:18 +02:00
|
|
|
static int gl_buffersize;
|
2008-11-24 12:04:50 +01:00
|
|
|
static int gl_buffersize_uv;
|
2007-08-03 20:29:54 +02:00
|
|
|
static void *gl_bufferptr;
|
2008-11-24 12:04:50 +01:00
|
|
|
static void *gl_bufferptr_uv[2];
|
2008-12-05 23:16:45 +01:00
|
|
|
static int mesa_buffersize;
|
|
|
|
static void *mesa_bufferptr;
|
2005-09-15 00:08:04 +02:00
|
|
|
static GLuint fragprog;
|
2006-07-04 18:31:45 +02:00
|
|
|
static GLuint default_texs[22];
|
2005-09-15 00:08:04 +02:00
|
|
|
static char *custom_prog;
|
2005-09-25 18:31:58 +02:00
|
|
|
static char *custom_tex;
|
|
|
|
static int custom_tlin;
|
2006-07-08 21:29:04 +02:00
|
|
|
static int custom_trect;
|
2009-12-19 21:53:34 +01:00
|
|
|
static int mipmap_gen;
|
2010-07-05 21:19:56 +02:00
|
|
|
static int stereo_mode;
|
2001-02-24 21:28:24 +01:00
|
|
|
|
2003-09-01 00:27:10 +02:00
|
|
|
static int int_pause;
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
|
|
|
|
static struct mp_csp_equalizer video_eq;
|
2003-09-01 00:27:10 +02:00
|
|
|
|
2005-10-31 14:56:16 +01:00
|
|
|
static int texture_width;
|
|
|
|
static int texture_height;
|
2005-12-18 13:04:08 +01:00
|
|
|
static int mpi_flipped;
|
2006-07-10 20:36:50 +02:00
|
|
|
static int vo_flipped;
|
2007-02-06 20:26:58 +01:00
|
|
|
static int ass_border_x, ass_border_y;
|
2001-02-24 21:28:24 +01:00
|
|
|
|
2004-09-03 14:12:17 +02:00
|
|
|
static unsigned int slice_height = 1;
|
2002-12-30 02:34:20 +01:00
|
|
|
|
2008-05-25 13:26:09 +02:00
|
|
|
static void redraw(void);
|
|
|
|
|
2001-04-24 12:21:12 +02:00
|
|
|
static void resize(int x,int y){
|
2004-02-22 16:30:01 +01:00
|
|
|
mp_msg(MSGT_VO, MSGL_V, "[gl] Resize: %dx%d\n",x,y);
|
2005-06-18 20:32:29 +02:00
|
|
|
if (WinID >= 0) {
|
2010-07-01 21:43:38 +02:00
|
|
|
int left = 0, top = 0, w = x, h = y;
|
|
|
|
geometry(&left, &top, &w, &h, vo_dwidth, vo_dheight);
|
|
|
|
top = y - h - top;
|
|
|
|
mpglViewport(left, top, w, h);
|
2005-06-18 20:32:29 +02:00
|
|
|
} else
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglViewport( 0, 0, x, y );
|
2001-02-24 21:28:24 +01:00
|
|
|
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglMatrixMode(GL_PROJECTION);
|
|
|
|
mpglLoadIdentity();
|
2009-02-17 09:05:14 +01:00
|
|
|
ass_border_x = ass_border_y = 0;
|
2009-08-27 20:36:51 +02:00
|
|
|
if (aspect_scaling() && use_aspect) {
|
2004-10-10 16:05:29 +02:00
|
|
|
int new_w, new_h;
|
|
|
|
GLdouble scale_x, scale_y;
|
2009-08-27 20:36:51 +02:00
|
|
|
aspect(&new_w, &new_h, A_WINZOOM);
|
|
|
|
panscan_calc_windowed();
|
2004-10-10 16:05:29 +02:00
|
|
|
new_w += vo_panscan_x;
|
|
|
|
new_h += vo_panscan_y;
|
2008-12-03 10:27:19 +01:00
|
|
|
scale_x = (GLdouble)new_w / (GLdouble)x;
|
|
|
|
scale_y = (GLdouble)new_h / (GLdouble)y;
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglScaled(scale_x, scale_y, 1);
|
2009-08-27 15:54:53 +02:00
|
|
|
ass_border_x = (vo_dwidth - new_w) / 2;
|
|
|
|
ass_border_y = (vo_dheight - new_h) / 2;
|
2004-10-10 16:05:29 +02:00
|
|
|
}
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglOrtho(0, image_width, image_height, 0, -1,1);
|
2001-02-24 21:28:24 +01:00
|
|
|
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglMatrixMode(GL_MODELVIEW);
|
|
|
|
mpglLoadIdentity();
|
2004-10-08 21:53:11 +02:00
|
|
|
|
2004-10-17 21:32:47 +02:00
|
|
|
if (!scaled_osd) {
|
2008-08-07 12:36:07 +02:00
|
|
|
#ifdef CONFIG_FREETYPE
|
2010-07-05 21:45:14 +02:00
|
|
|
// adjust font size to display size
|
|
|
|
force_load_font = 1;
|
2005-04-10 15:12:55 +02:00
|
|
|
#endif
|
2010-07-05 21:45:14 +02:00
|
|
|
vo_osd_changed(OSDTYPE_OSD);
|
2004-10-17 21:32:47 +02:00
|
|
|
}
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglClear(GL_COLOR_BUFFER_BIT);
|
2008-05-25 13:26:09 +02:00
|
|
|
redraw();
|
2001-02-24 21:28:24 +01:00
|
|
|
}
|
|
|
|
|
2005-07-26 12:16:18 +02:00
|
|
|
static void texSize(int w, int h, int *texw, int *texh) {
|
|
|
|
if (use_rectangle) {
|
|
|
|
*texw = w; *texh = h;
|
|
|
|
} else {
|
|
|
|
*texw = 32;
|
|
|
|
while (*texw < w)
|
|
|
|
*texw *= 2;
|
|
|
|
*texh = 32;
|
|
|
|
while (*texh < h)
|
|
|
|
*texh *= 2;
|
|
|
|
}
|
2008-12-06 07:44:54 +01:00
|
|
|
if (mesa_buffer) *texw = (*texw + 63) & ~63;
|
2008-12-06 13:13:14 +01:00
|
|
|
else if (ati_hack) *texw = (*texw + 511) & ~511;
|
2005-07-26 12:16:18 +02:00
|
|
|
}
|
|
|
|
|
2005-09-25 18:41:28 +02:00
|
|
|
//! maximum size of custom fragment program
|
2005-09-15 00:08:04 +02:00
|
|
|
#define MAX_CUSTOM_PROG_SIZE (1024 * 1024)
|
2006-02-09 15:08:03 +01:00
|
|
|
static void update_yuvconv(void) {
|
2011-05-24 22:52:27 +02:00
|
|
|
int xs, ys, depth;
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
struct mp_csp_params cparams = { .colorspace = colorspace };
|
|
|
|
mp_csp_copy_equalizer_values(&cparams, &video_eq);
|
|
|
|
gl_conversion_params_t params = {gl_target, yuvconvtype, cparams,
|
2009-12-30 12:32:24 +01:00
|
|
|
texture_width, texture_height, 0, 0, filter_strength};
|
2011-05-24 22:52:27 +02:00
|
|
|
mp_get_chroma_shift(image_format, &xs, &ys, &depth);
|
2009-12-30 12:32:24 +01:00
|
|
|
params.chrom_texw = params.texw >> xs;
|
|
|
|
params.chrom_texh = params.texh >> ys;
|
2011-05-24 22:52:27 +02:00
|
|
|
params.csp_params.input_shift = -depth & 7;
|
2008-05-24 13:03:00 +02:00
|
|
|
glSetupYUVConversion(¶ms);
|
2005-09-15 00:08:04 +02:00
|
|
|
if (custom_prog) {
|
2010-04-13 07:54:44 +02:00
|
|
|
FILE *f = fopen(custom_prog, "rb");
|
2010-07-05 21:45:14 +02:00
|
|
|
if (!f) {
|
2005-09-15 00:08:04 +02:00
|
|
|
mp_msg(MSGT_VO, MSGL_WARN,
|
|
|
|
"[gl] Could not read customprog %s\n", custom_prog);
|
2010-07-05 21:45:14 +02:00
|
|
|
} else {
|
2005-09-15 00:08:04 +02:00
|
|
|
char *prog = calloc(1, MAX_CUSTOM_PROG_SIZE + 1);
|
|
|
|
fread(prog, 1, MAX_CUSTOM_PROG_SIZE, f);
|
|
|
|
fclose(f);
|
2006-06-08 20:50:11 +02:00
|
|
|
loadGPUProgram(GL_FRAGMENT_PROGRAM, prog);
|
2005-09-15 00:08:04 +02:00
|
|
|
free(prog);
|
|
|
|
}
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglProgramEnvParameter4f(GL_FRAGMENT_PROGRAM, 0,
|
2006-07-08 21:22:36 +02:00
|
|
|
1.0 / texture_width, 1.0 / texture_height,
|
|
|
|
texture_width, texture_height);
|
2005-09-15 00:08:04 +02:00
|
|
|
}
|
2005-09-25 18:31:58 +02:00
|
|
|
if (custom_tex) {
|
2010-04-30 19:12:52 +02:00
|
|
|
FILE *f = fopen(custom_tex, "rb");
|
2010-07-05 21:45:14 +02:00
|
|
|
if (!f) {
|
2005-09-25 18:31:58 +02:00
|
|
|
mp_msg(MSGT_VO, MSGL_WARN,
|
|
|
|
"[gl] Could not read customtex %s\n", custom_tex);
|
2010-07-05 21:45:14 +02:00
|
|
|
} else {
|
2005-09-25 18:31:58 +02:00
|
|
|
int width, height, maxval;
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglActiveTexture(GL_TEXTURE3);
|
2006-07-08 21:29:04 +02:00
|
|
|
if (glCreatePPMTex(custom_trect?GL_TEXTURE_RECTANGLE:GL_TEXTURE_2D, 0,
|
2010-07-05 21:45:14 +02:00
|
|
|
custom_tlin?GL_LINEAR:GL_NEAREST,
|
|
|
|
f, &width, &height, &maxval)) {
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglProgramEnvParameter4f(GL_FRAGMENT_PROGRAM, 1,
|
2006-07-08 21:22:36 +02:00
|
|
|
1.0 / width, 1.0 / height, width, height);
|
2010-07-05 21:45:14 +02:00
|
|
|
} else
|
2005-09-25 18:31:58 +02:00
|
|
|
mp_msg(MSGT_VO, MSGL_WARN,
|
|
|
|
"[gl] Error parsing customtex %s\n", custom_tex);
|
|
|
|
fclose(f);
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglActiveTexture(GL_TEXTURE0);
|
2005-09-25 18:31:58 +02:00
|
|
|
}
|
|
|
|
}
|
2005-09-15 00:08:04 +02:00
|
|
|
}
|
|
|
|
|
2005-09-09 18:43:18 +02:00
|
|
|
/**
|
|
|
|
* \brief remove all OSD textures and display-lists, thus clearing it.
|
|
|
|
*/
|
2006-02-09 15:08:03 +01:00
|
|
|
static void clearOSD(void) {
|
2005-09-09 16:47:54 +02:00
|
|
|
int i;
|
2006-03-15 13:15:35 +01:00
|
|
|
if (!osdtexCnt)
|
|
|
|
return;
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglDeleteTextures(osdtexCnt, osdtex);
|
2005-09-09 16:47:54 +02:00
|
|
|
#ifndef FAST_OSD
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglDeleteTextures(osdtexCnt, osdatex);
|
2006-06-15 10:43:41 +02:00
|
|
|
for (i = 0; i < osdtexCnt; i++)
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglDeleteLists(osdaDispList[i], 1);
|
2005-09-09 16:47:54 +02:00
|
|
|
#endif
|
|
|
|
for (i = 0; i < osdtexCnt; i++)
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglDeleteLists(osdDispList[i], 1);
|
2005-09-09 16:47:54 +02:00
|
|
|
osdtexCnt = 0;
|
|
|
|
}
|
|
|
|
|
2006-08-28 22:17:42 +02:00
|
|
|
/**
|
|
|
|
* \brief remove textures, display list and free memory used by EOSD
|
|
|
|
*/
|
|
|
|
static void clearEOSD(void) {
|
2006-09-22 21:58:43 +02:00
|
|
|
if (eosdDispList)
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglDeleteLists(eosdDispList, 1);
|
2006-09-22 21:58:43 +02:00
|
|
|
eosdDispList = 0;
|
|
|
|
if (eosdtexCnt)
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglDeleteTextures(eosdtexCnt, eosdtex);
|
2006-09-22 21:58:43 +02:00
|
|
|
eosdtexCnt = 0;
|
2006-08-28 22:17:42 +02:00
|
|
|
free(eosdtex);
|
|
|
|
eosdtex = NULL;
|
|
|
|
}
|
|
|
|
|
2009-08-06 22:58:31 +02:00
|
|
|
static inline int is_tinytex(ASS_Image *i, int tinytexcur) {
|
2009-03-06 13:56:13 +01:00
|
|
|
return i->w < TINYTEX_SIZE && i->h < TINYTEX_SIZE && tinytexcur < TINYTEX_MAX;
|
|
|
|
}
|
|
|
|
|
2009-08-06 22:58:31 +02:00
|
|
|
static inline int is_smalltex(ASS_Image *i, int smalltexcur) {
|
2009-03-06 13:56:13 +01:00
|
|
|
return i->w < SMALLTEX_SIZE && i->h < SMALLTEX_SIZE && smalltexcur < SMALLTEX_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void tinytex_pos(int tinytexcur, int *x, int *y) {
|
|
|
|
*x = (tinytexcur % TINYTEX_COLS) * TINYTEX_SIZE;
|
|
|
|
*y = (tinytexcur / TINYTEX_COLS) * TINYTEX_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void smalltex_pos(int smalltexcur, int *x, int *y) {
|
|
|
|
*x = (smalltexcur % SMALLTEX_COLS) * SMALLTEX_SIZE;
|
|
|
|
*y = (smalltexcur / SMALLTEX_COLS) * SMALLTEX_SIZE;
|
|
|
|
}
|
|
|
|
|
2006-08-28 22:17:42 +02:00
|
|
|
/**
|
|
|
|
* \brief construct display list from ass image list
|
|
|
|
* \param img image list to create OSD from.
|
|
|
|
* A value of NULL has the same effect as clearEOSD()
|
|
|
|
*/
|
2006-12-06 19:44:26 +01:00
|
|
|
static void genEOSD(mp_eosd_images_t *imgs) {
|
2006-08-28 22:17:42 +02:00
|
|
|
int sx, sy;
|
2006-09-22 22:23:17 +02:00
|
|
|
int tinytexcur = 0;
|
|
|
|
int smalltexcur = 0;
|
2006-08-28 22:17:42 +02:00
|
|
|
GLuint *curtex;
|
2008-12-03 10:27:19 +01:00
|
|
|
GLint scale_type = scaled_osd ? GL_LINEAR : GL_NEAREST;
|
2009-08-06 22:58:31 +02:00
|
|
|
ASS_Image *img = imgs->imgs;
|
|
|
|
ASS_Image *i;
|
2006-12-06 19:44:26 +01:00
|
|
|
|
|
|
|
if (imgs->changed == 0) // there are elements, but they are unchanged
|
|
|
|
return;
|
|
|
|
if (img && imgs->changed == 1) // there are elements, but they just moved
|
|
|
|
goto skip_upload;
|
|
|
|
|
2006-08-28 22:17:42 +02:00
|
|
|
clearEOSD();
|
2006-09-22 22:13:21 +02:00
|
|
|
if (!img)
|
|
|
|
return;
|
2006-09-22 22:23:17 +02:00
|
|
|
if (!largeeosdtex[0]) {
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglGenTextures(2, largeeosdtex);
|
|
|
|
mpglBindTexture(gl_target, largeeosdtex[0]);
|
2009-03-06 13:56:13 +01:00
|
|
|
glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, LARGE_EOSD_TEX_SIZE, LARGE_EOSD_TEX_SIZE, 0);
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindTexture(gl_target, largeeosdtex[1]);
|
2009-03-06 13:56:13 +01:00
|
|
|
glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, LARGE_EOSD_TEX_SIZE, LARGE_EOSD_TEX_SIZE, 0);
|
2006-09-22 22:23:17 +02:00
|
|
|
}
|
2006-08-28 22:17:42 +02:00
|
|
|
for (i = img; i; i = i->next)
|
2006-09-22 22:23:17 +02:00
|
|
|
{
|
|
|
|
if (i->w <= 0 || i->h <= 0 || i->stride < i->w)
|
|
|
|
continue;
|
2009-03-06 13:56:13 +01:00
|
|
|
if (is_tinytex(i, tinytexcur))
|
2006-09-22 22:23:17 +02:00
|
|
|
tinytexcur++;
|
2009-03-06 13:56:13 +01:00
|
|
|
else if (is_smalltex(i, smalltexcur))
|
2006-09-22 22:23:17 +02:00
|
|
|
smalltexcur++;
|
|
|
|
else
|
2006-09-22 22:26:12 +02:00
|
|
|
eosdtexCnt++;
|
2006-09-22 22:23:17 +02:00
|
|
|
}
|
2006-10-06 11:58:29 +02:00
|
|
|
mp_msg(MSGT_VO, MSGL_DBG2, "EOSD counts (tiny, small, all): %i, %i, %i\n",
|
|
|
|
tinytexcur, smalltexcur, eosdtexCnt);
|
2006-09-22 22:23:17 +02:00
|
|
|
if (eosdtexCnt) {
|
2006-09-22 22:26:12 +02:00
|
|
|
eosdtex = calloc(eosdtexCnt, sizeof(GLuint));
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglGenTextures(eosdtexCnt, eosdtex);
|
2006-09-22 22:23:17 +02:00
|
|
|
}
|
|
|
|
tinytexcur = smalltexcur = 0;
|
2006-09-22 22:19:51 +02:00
|
|
|
for (i = img, curtex = eosdtex; i; i = i->next) {
|
2006-09-22 22:23:17 +02:00
|
|
|
int x = 0, y = 0;
|
2006-08-28 22:17:42 +02:00
|
|
|
if (i->w <= 0 || i->h <= 0 || i->stride < i->w) {
|
|
|
|
mp_msg(MSGT_VO, MSGL_V, "Invalid dimensions OSD for part!\n");
|
|
|
|
continue;
|
|
|
|
}
|
2009-03-06 13:56:13 +01:00
|
|
|
if (is_tinytex(i, tinytexcur)) {
|
|
|
|
tinytex_pos(tinytexcur, &x, &y);
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindTexture(gl_target, largeeosdtex[0]);
|
2006-09-22 22:23:17 +02:00
|
|
|
tinytexcur++;
|
2009-03-06 13:56:13 +01:00
|
|
|
} else if (is_smalltex(i, smalltexcur)) {
|
|
|
|
smalltex_pos(smalltexcur, &x, &y);
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindTexture(gl_target, largeeosdtex[1]);
|
2006-09-22 22:23:17 +02:00
|
|
|
smalltexcur++;
|
|
|
|
} else {
|
2006-09-22 22:26:12 +02:00
|
|
|
texSize(i->w, i->h, &sx, &sy);
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindTexture(gl_target, *curtex++);
|
2008-09-20 19:48:01 +02:00
|
|
|
glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, sx, sy, 0);
|
2006-09-22 22:23:17 +02:00
|
|
|
}
|
2006-08-28 22:17:42 +02:00
|
|
|
glUploadTex(gl_target, GL_ALPHA, GL_UNSIGNED_BYTE, i->bitmap, i->stride,
|
2006-09-22 22:23:17 +02:00
|
|
|
x, y, i->w, i->h, 0);
|
2006-08-28 22:17:42 +02:00
|
|
|
}
|
2010-04-03 09:08:07 +02:00
|
|
|
eosdDispList = mpglGenLists(1);
|
2006-12-06 19:44:26 +01:00
|
|
|
skip_upload:
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglNewList(eosdDispList, GL_COMPILE);
|
2006-09-22 22:23:17 +02:00
|
|
|
tinytexcur = smalltexcur = 0;
|
2006-09-22 22:19:51 +02:00
|
|
|
for (i = img, curtex = eosdtex; i; i = i->next) {
|
2006-09-22 22:23:17 +02:00
|
|
|
int x = 0, y = 0;
|
2006-08-28 22:17:42 +02:00
|
|
|
if (i->w <= 0 || i->h <= 0 || i->stride < i->w)
|
|
|
|
continue;
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglColor4ub(i->color >> 24, (i->color >> 16) & 0xff, (i->color >> 8) & 0xff, 255 - (i->color & 0xff));
|
2009-03-06 13:56:13 +01:00
|
|
|
if (is_tinytex(i, tinytexcur)) {
|
|
|
|
tinytex_pos(tinytexcur, &x, &y);
|
|
|
|
sx = sy = LARGE_EOSD_TEX_SIZE;
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindTexture(gl_target, largeeosdtex[0]);
|
2006-09-22 22:23:17 +02:00
|
|
|
tinytexcur++;
|
2009-03-06 13:56:13 +01:00
|
|
|
} else if (is_smalltex(i, smalltexcur)) {
|
|
|
|
smalltex_pos(smalltexcur, &x, &y);
|
|
|
|
sx = sy = LARGE_EOSD_TEX_SIZE;
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindTexture(gl_target, largeeosdtex[1]);
|
2006-09-22 22:23:17 +02:00
|
|
|
smalltexcur++;
|
|
|
|
} else {
|
2006-09-22 22:26:12 +02:00
|
|
|
texSize(i->w, i->h, &sx, &sy);
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindTexture(gl_target, *curtex++);
|
2006-09-22 22:23:17 +02:00
|
|
|
}
|
|
|
|
glDrawTex(i->dst_x, i->dst_y, i->w, i->h, x, y, i->w, i->h, sx, sy, use_rectangle == 1, 0, 0);
|
2006-08-28 22:17:42 +02:00
|
|
|
}
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglEndList();
|
|
|
|
mpglBindTexture(gl_target, 0);
|
2006-08-28 22:17:42 +02:00
|
|
|
}
|
|
|
|
|
2005-09-09 16:47:54 +02:00
|
|
|
/**
|
|
|
|
* \brief uninitialize OpenGL context, freeing textures, buffers etc.
|
|
|
|
*/
|
2006-02-09 15:08:03 +01:00
|
|
|
static void uninitGl(void) {
|
2006-07-01 12:58:32 +02:00
|
|
|
int i = 0;
|
2010-04-03 09:08:07 +02:00
|
|
|
if (mpglDeletePrograms && fragprog)
|
|
|
|
mpglDeletePrograms(1, &fragprog);
|
2005-09-15 00:08:04 +02:00
|
|
|
fragprog = 0;
|
2006-07-01 12:58:32 +02:00
|
|
|
while (default_texs[i] != 0)
|
|
|
|
i++;
|
|
|
|
if (i)
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglDeleteTextures(i, default_texs);
|
2006-07-01 12:58:32 +02:00
|
|
|
default_texs[0] = 0;
|
2005-09-09 16:47:54 +02:00
|
|
|
clearOSD();
|
2006-08-28 22:17:42 +02:00
|
|
|
clearEOSD();
|
2006-09-22 22:23:17 +02:00
|
|
|
if (largeeosdtex[0])
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglDeleteTextures(2, largeeosdtex);
|
2006-09-22 22:23:17 +02:00
|
|
|
largeeosdtex[0] = 0;
|
2010-04-03 09:08:07 +02:00
|
|
|
if (mpglDeleteBuffers && gl_buffer)
|
|
|
|
mpglDeleteBuffers(1, &gl_buffer);
|
2005-09-09 16:47:54 +02:00
|
|
|
gl_buffer = 0; gl_buffersize = 0;
|
2007-08-03 20:29:54 +02:00
|
|
|
gl_bufferptr = NULL;
|
2010-04-03 09:08:07 +02:00
|
|
|
if (mpglDeleteBuffers && gl_buffer_uv[0])
|
|
|
|
mpglDeleteBuffers(2, gl_buffer_uv);
|
2008-11-24 12:04:50 +01:00
|
|
|
gl_buffer_uv[0] = gl_buffer_uv[1] = 0; gl_buffersize_uv = 0;
|
|
|
|
gl_bufferptr_uv[0] = gl_bufferptr_uv[1] = 0;
|
2009-12-19 14:49:44 +01:00
|
|
|
#ifdef CONFIG_GL_X11
|
2008-12-05 23:16:45 +01:00
|
|
|
if (mesa_bufferptr)
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglFreeMemoryMESA(mDisplay, mScreen, mesa_bufferptr);
|
2008-12-06 00:35:32 +01:00
|
|
|
#endif
|
2008-12-05 23:16:45 +01:00
|
|
|
mesa_bufferptr = NULL;
|
2005-09-09 16:47:54 +02:00
|
|
|
err_shown = 0;
|
|
|
|
}
|
|
|
|
|
2010-02-27 19:16:41 +01:00
|
|
|
static int isSoftwareGl(void)
|
|
|
|
{
|
2010-04-03 09:08:07 +02:00
|
|
|
const char *renderer = mpglGetString(GL_RENDERER);
|
2010-12-18 21:56:37 +01:00
|
|
|
return !renderer || strcmp(renderer, "Software Rasterizer") == 0 ||
|
|
|
|
strstr(renderer, "llvmpipe");
|
2010-02-27 19:16:41 +01:00
|
|
|
}
|
|
|
|
|
2008-12-10 17:39:45 +01:00
|
|
|
static void autodetectGlExtensions(void) {
|
2010-04-03 09:08:07 +02:00
|
|
|
const char *extensions = mpglGetString(GL_EXTENSIONS);
|
|
|
|
const char *vendor = mpglGetString(GL_VENDOR);
|
|
|
|
const char *version = mpglGetString(GL_VERSION);
|
2010-05-02 00:49:05 +02:00
|
|
|
const char *renderer = mpglGetString(GL_RENDERER);
|
2010-04-24 18:52:06 +02:00
|
|
|
int is_ati = vendor && strstr(vendor, "ATI") != NULL;
|
2009-02-03 12:46:31 +01:00
|
|
|
int ati_broken_pbo = 0;
|
2010-05-02 00:49:05 +02:00
|
|
|
mp_msg(MSGT_VO, MSGL_V, "[gl] Running on OpenGL '%s' by '%s', version '%s'\n", renderer, vendor, version);
|
2009-02-03 12:46:31 +01:00
|
|
|
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 (ati_hack == -1) ati_hack = ati_broken_pbo;
|
2010-05-24 19:36:23 +02:00
|
|
|
if (force_pbo == -1) {
|
|
|
|
force_pbo = 0;
|
|
|
|
if (extensions && strstr(extensions, "_pixel_buffer_object"))
|
|
|
|
force_pbo = is_ati;
|
|
|
|
}
|
|
|
|
if (use_rectangle == -1) {
|
2010-05-09 23:29:21 +02:00
|
|
|
use_rectangle = 0;
|
2010-05-24 19:36:23 +02:00
|
|
|
if (extensions) {
|
|
|
|
// if (strstr(extensions, "_texture_non_power_of_two"))
|
|
|
|
if (strstr(extensions, "_texture_rectangle"))
|
|
|
|
use_rectangle = renderer && strstr(renderer, "Mesa DRI R200") ? 1 : 0;
|
|
|
|
}
|
|
|
|
}
|
2010-04-24 18:58:24 +02:00
|
|
|
if (use_osd == -1)
|
|
|
|
use_osd = mpglBindTexture != NULL;
|
2010-04-04 18:56:30 +02:00
|
|
|
if (use_yuv == -1)
|
|
|
|
use_yuv = glAutodetectYUVConversion();
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
|
|
|
|
int eq_caps = 0;
|
|
|
|
int yuv_mask = (1 << 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;
|
|
|
|
}
|
|
|
|
video_eq.capabilities = eq_caps;
|
|
|
|
|
2008-12-23 21:56:45 +01:00
|
|
|
if (is_ati && (lscale == 1 || lscale == 2 || cscale == 1 || cscale == 2))
|
2009-02-03 12:47:07 +01:00
|
|
|
mp_msg(MSGT_VO, MSGL_WARN, "[gl] Selected scaling mode may be broken on ATI cards.\n"
|
2008-12-23 21:56:45 +01:00
|
|
|
"Tell _them_ to fix GL_REPEAT if you have issues.\n");
|
2010-02-02 21:37:48 +01:00
|
|
|
mp_msg(MSGT_VO, MSGL_V, "[gl] Settings after autodetection: ati-hack = %i, force-pbo = %i, rectangle = %i, yuv = %i\n",
|
|
|
|
ati_hack, force_pbo, use_rectangle, use_yuv);
|
2008-12-10 17:39:45 +01:00
|
|
|
}
|
|
|
|
|
2010-07-15 20:57:57 +02:00
|
|
|
static GLint get_scale_type(int chroma) {
|
|
|
|
int nearest = (chroma ? cscale : lscale) & 64;
|
|
|
|
if (nearest)
|
|
|
|
return mipmap_gen ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
|
|
|
|
return mipmap_gen ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
|
|
|
|
}
|
|
|
|
|
2004-11-01 21:24:37 +01:00
|
|
|
/**
|
|
|
|
* \brief Initialize a (new or reused) OpenGL context.
|
2005-09-09 16:47:54 +02:00
|
|
|
* set global gl-related variables to their default values
|
2004-11-01 21:24:37 +01:00
|
|
|
*/
|
|
|
|
static int initGl(uint32_t d_width, uint32_t d_height) {
|
2010-07-15 20:57:57 +02:00
|
|
|
GLint scale_type = get_scale_type(0);
|
2008-12-10 17:39:45 +01:00
|
|
|
autodetectGlExtensions();
|
2010-02-02 21:20:48 +01:00
|
|
|
gl_target = use_rectangle == 1 ? GL_TEXTURE_RECTANGLE : GL_TEXTURE_2D;
|
2010-07-15 20:50:57 +02:00
|
|
|
yuvconvtype = SET_YUV_CONVERSION(use_yuv) |
|
|
|
|
SET_YUV_LUM_SCALER(lscale) |
|
|
|
|
SET_YUV_CHROM_SCALER(cscale);
|
2010-02-02 21:20:48 +01:00
|
|
|
|
2005-07-26 12:16:18 +02:00
|
|
|
texSize(image_width, image_height, &texture_width, &texture_height);
|
2004-11-01 21:24:37 +01:00
|
|
|
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglDisable(GL_BLEND);
|
|
|
|
mpglDisable(GL_DEPTH_TEST);
|
|
|
|
mpglDepthMask(GL_FALSE);
|
|
|
|
mpglDisable(GL_CULL_FACE);
|
|
|
|
mpglEnable(gl_target);
|
|
|
|
mpglDrawBuffer(vo_doublebuffering?GL_BACK:GL_FRONT);
|
|
|
|
mpglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
2004-11-01 21:24:37 +01:00
|
|
|
|
|
|
|
mp_msg(MSGT_VO, MSGL_V, "[gl] Creating %dx%d texture...\n",
|
|
|
|
texture_width, texture_height);
|
|
|
|
|
2010-07-15 20:36:15 +02:00
|
|
|
glCreateClearTex(gl_target, gl_texfmt, gl_format, gl_type, scale_type,
|
|
|
|
texture_width, texture_height, 0);
|
|
|
|
if (mipmap_gen)
|
|
|
|
mpglTexParameteri(gl_target, GL_GENERATE_MIPMAP, GL_TRUE);
|
|
|
|
|
2009-12-30 12:32:24 +01:00
|
|
|
if (is_yuv) {
|
2006-07-01 12:58:32 +02:00
|
|
|
int i;
|
2011-05-24 22:52:27 +02:00
|
|
|
int xs, ys, depth;
|
|
|
|
int chroma_clear_val = 128;
|
2010-07-15 20:57:57 +02:00
|
|
|
scale_type = get_scale_type(1);
|
2011-05-24 22:52:27 +02:00
|
|
|
mp_get_chroma_shift(image_format, &xs, &ys, &depth);
|
|
|
|
chroma_clear_val >>= -depth & 7;
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglGenTextures(21, default_texs);
|
2006-07-04 18:31:45 +02:00
|
|
|
default_texs[21] = 0;
|
2006-07-01 12:58:32 +02:00
|
|
|
for (i = 0; i < 7; i++) {
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglActiveTexture(GL_TEXTURE1 + i);
|
|
|
|
mpglBindTexture(GL_TEXTURE_2D, default_texs[i]);
|
|
|
|
mpglBindTexture(GL_TEXTURE_RECTANGLE, default_texs[i + 7]);
|
|
|
|
mpglBindTexture(GL_TEXTURE_3D, default_texs[i + 14]);
|
2006-07-01 12:58:32 +02:00
|
|
|
}
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglActiveTexture(GL_TEXTURE1);
|
2009-12-19 21:53:34 +01:00
|
|
|
glCreateClearTex(gl_target, gl_texfmt, gl_format, gl_type, scale_type,
|
2011-05-24 22:52:27 +02:00
|
|
|
texture_width >> xs, texture_height >> ys,
|
|
|
|
chroma_clear_val);
|
2009-12-19 21:53:34 +01:00
|
|
|
if (mipmap_gen)
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglTexParameteri(gl_target, GL_GENERATE_MIPMAP, GL_TRUE);
|
|
|
|
mpglActiveTexture(GL_TEXTURE2);
|
2009-12-19 21:53:34 +01:00
|
|
|
glCreateClearTex(gl_target, gl_texfmt, gl_format, gl_type, scale_type,
|
2011-05-24 22:52:27 +02:00
|
|
|
texture_width >> xs, texture_height >> ys,
|
|
|
|
chroma_clear_val);
|
2009-12-19 21:53:34 +01:00
|
|
|
if (mipmap_gen)
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglTexParameteri(gl_target, GL_GENERATE_MIPMAP, GL_TRUE);
|
|
|
|
mpglActiveTexture(GL_TEXTURE0);
|
|
|
|
mpglBindTexture(gl_target, 0);
|
2009-12-19 21:48:23 +01:00
|
|
|
}
|
2009-12-30 12:32:24 +01:00
|
|
|
if (is_yuv || custom_prog)
|
2009-12-19 21:48:23 +01:00
|
|
|
{
|
|
|
|
if ((MASK_NOT_COMBINERS & (1 << use_yuv)) || custom_prog) {
|
2010-04-03 09:08:07 +02:00
|
|
|
if (!mpglGenPrograms || !mpglBindProgram) {
|
2009-12-19 21:48:23 +01:00
|
|
|
mp_msg(MSGT_VO, MSGL_ERR, "[gl] fragment program functions missing!\n");
|
|
|
|
} else {
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglGenPrograms(1, &fragprog);
|
|
|
|
mpglBindProgram(GL_FRAGMENT_PROGRAM, fragprog);
|
2009-12-19 21:48:23 +01:00
|
|
|
}
|
2005-09-15 00:08:04 +02:00
|
|
|
}
|
|
|
|
update_yuvconv();
|
|
|
|
}
|
2004-11-01 21:24:37 +01:00
|
|
|
|
|
|
|
resize(d_width, d_height);
|
|
|
|
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglClearColor( 0.0f,0.0f,0.0f,0.0f );
|
|
|
|
mpglClear( GL_COLOR_BUFFER_BIT );
|
|
|
|
if (mpglSwapInterval && swap_interval >= 0)
|
|
|
|
mpglSwapInterval(swap_interval);
|
2004-11-11 20:39:23 +01:00
|
|
|
return 1;
|
2004-11-01 21:24:37 +01:00
|
|
|
}
|
|
|
|
|
2010-02-02 21:37:48 +01:00
|
|
|
static int create_window(uint32_t d_width, uint32_t d_height, uint32_t flags, const char *title)
|
2001-02-24 21:28:24 +01:00
|
|
|
{
|
2010-11-10 23:48:41 +01:00
|
|
|
if (stereo_mode == GL_3D_QUADBUFFER)
|
|
|
|
flags |= VOFLAG_STEREO;
|
2009-12-19 14:49:44 +01:00
|
|
|
#ifdef CONFIG_GL_WIN32
|
2009-12-08 07:42:46 +01:00
|
|
|
if (glctx.type == GLTYPE_W32 && !vo_w32_config(d_width, d_height, flags))
|
2005-07-26 15:47:18 +02:00
|
|
|
return -1;
|
2009-12-08 07:42:46 +01:00
|
|
|
#endif
|
2009-12-19 14:49:44 +01:00
|
|
|
#ifdef CONFIG_GL_X11
|
2009-12-08 07:42:46 +01:00
|
|
|
if (glctx.type == GLTYPE_X11) {
|
2010-07-05 21:45:14 +02:00
|
|
|
static int default_glx_attribs[] = {
|
|
|
|
GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
|
|
|
|
GLX_DOUBLEBUFFER, None
|
|
|
|
};
|
2010-07-05 21:40:21 +02:00
|
|
|
static int stereo_glx_attribs[] = {
|
2010-07-05 21:45:14 +02:00
|
|
|
GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
|
2010-07-05 21:40:21 +02:00
|
|
|
GLX_DOUBLEBUFFER, GLX_STEREO, None
|
|
|
|
};
|
|
|
|
XVisualInfo *vinfo = NULL;
|
|
|
|
if (stereo_mode == GL_3D_QUADBUFFER) {
|
|
|
|
vinfo = glXChooseVisual(mDisplay, mScreen, stereo_glx_attribs);
|
|
|
|
if (!vinfo)
|
|
|
|
mp_msg(MSGT_VO, MSGL_ERR, "[gl] Could not find a stereo visual, "
|
|
|
|
"3D will probably not work!\n");
|
|
|
|
}
|
|
|
|
if (!vinfo)
|
|
|
|
vinfo = glXChooseVisual(mDisplay, mScreen, default_glx_attribs);
|
2010-07-05 21:45:14 +02:00
|
|
|
if (!vinfo) {
|
2006-08-28 22:38:31 +02:00
|
|
|
mp_msg(MSGT_VO, MSGL_ERR, "[gl] no GLX support present\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2009-11-21 23:32:53 +01:00
|
|
|
mp_msg(MSGT_VO, MSGL_V, "[gl] GLX chose visual with ID 0x%x\n", (int)vinfo->visualid);
|
2001-02-24 21:28:24 +01:00
|
|
|
|
2007-06-27 12:26:13 +02:00
|
|
|
vo_x11_create_vo_window(vinfo, vo_dx, vo_dy, d_width, d_height, flags,
|
|
|
|
XCreateColormap(mDisplay, mRootWin, vinfo->visual, AllocNone),
|
|
|
|
"gl", title);
|
2004-11-01 21:24:37 +01:00
|
|
|
}
|
2010-04-24 18:52:06 +02:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_GL_SDL
|
|
|
|
if (glctx.type == GLTYPE_SDL) {
|
2010-04-25 10:40:28 +02:00
|
|
|
SDL_WM_SetCaption(title, NULL);
|
2010-04-25 10:35:35 +02:00
|
|
|
vo_dwidth = d_width;
|
|
|
|
vo_dheight = d_height;
|
2010-04-24 18:52:06 +02:00
|
|
|
}
|
2005-07-26 15:47:18 +02:00
|
|
|
#endif
|
2010-02-02 21:37:48 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2001-02-24 21:28:24 +01:00
|
|
|
/* connect to server, create and map window,
|
|
|
|
* allocate colors and (shared) memory
|
|
|
|
*/
|
2009-05-13 04:58:57 +02:00
|
|
|
static int
|
2002-08-28 23:32:32 +02:00
|
|
|
config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format)
|
2001-02-24 21:28:24 +01:00
|
|
|
{
|
2009-12-30 12:32:24 +01:00
|
|
|
int xs, ys;
|
2006-08-28 22:38:31 +02:00
|
|
|
image_height = height;
|
|
|
|
image_width = width;
|
|
|
|
image_format = format;
|
2011-05-10 19:51:39 +02:00
|
|
|
is_yuv = mp_get_chroma_shift(image_format, &xs, &ys, NULL) > 0;
|
2009-12-30 12:32:24 +01:00
|
|
|
is_yuv |= (xs << 8) | (ys << 16);
|
2006-08-28 22:38:31 +02:00
|
|
|
glFindFormat(format, NULL, &gl_texfmt, &gl_format, &gl_type);
|
|
|
|
|
|
|
|
vo_flipped = !!(flags & VOFLAG_FLIPPING);
|
|
|
|
|
2010-02-02 21:37:48 +01:00
|
|
|
if (create_window(d_width, d_height, flags, title) < 0)
|
2005-07-26 15:47:18 +02:00
|
|
|
return -1;
|
2005-06-18 20:32:29 +02:00
|
|
|
|
2005-09-09 16:47:54 +02:00
|
|
|
if (vo_config_count)
|
|
|
|
uninitGl();
|
2009-12-08 07:42:46 +01:00
|
|
|
if (glctx.setGlWindow(&glctx) == SET_WINDOW_FAILED)
|
2009-09-01 17:20:05 +02:00
|
|
|
return -1;
|
2010-04-03 09:08:07 +02:00
|
|
|
if (mesa_buffer && !mpglAllocateMemoryMESA) {
|
2009-09-27 16:31:35 +02:00
|
|
|
mp_msg(MSGT_VO, MSGL_ERR, "Can not enable mesa-buffer because AllocateMemoryMESA was not found\n");
|
|
|
|
mesa_buffer = 0;
|
|
|
|
}
|
2004-11-01 21:24:37 +01:00
|
|
|
initGl(vo_dwidth, vo_dheight);
|
|
|
|
|
2006-08-28 22:38:31 +02:00
|
|
|
return 0;
|
2001-02-24 21:28:24 +01:00
|
|
|
}
|
|
|
|
|
2001-03-03 22:46:39 +01:00
|
|
|
static void check_events(void)
|
2001-02-24 21:28:24 +01:00
|
|
|
{
|
2009-12-08 07:42:46 +01:00
|
|
|
int e=glctx.check_events();
|
2010-04-25 12:44:53 +02:00
|
|
|
if(e&VO_EVENT_REINIT) {
|
|
|
|
uninitGl();
|
|
|
|
initGl(vo_dwidth, vo_dheight);
|
|
|
|
}
|
2001-03-03 22:46:39 +01:00
|
|
|
if(e&VO_EVENT_RESIZE) resize(vo_dwidth,vo_dheight);
|
2008-05-25 13:26:09 +02:00
|
|
|
if(e&VO_EVENT_EXPOSE && int_pause) redraw();
|
2001-03-03 22:46:39 +01:00
|
|
|
}
|
|
|
|
|
2004-10-08 21:53:11 +02:00
|
|
|
/**
|
|
|
|
* Creates the textures and the display list needed for displaying
|
|
|
|
* an OSD part.
|
|
|
|
* Callback function for vo_draw_text().
|
|
|
|
*/
|
|
|
|
static void create_osd_texture(int x0, int y0, int w, int h,
|
|
|
|
unsigned char *src, unsigned char *srca,
|
|
|
|
int stride)
|
|
|
|
{
|
2004-10-17 15:28:22 +02:00
|
|
|
// initialize to 8 to avoid special-casing on alignment
|
|
|
|
int sx = 8, sy = 8;
|
2008-12-03 10:27:19 +01:00
|
|
|
GLint scale_type = scaled_osd ? GL_LINEAR : GL_NEAREST;
|
2006-03-15 22:13:13 +01:00
|
|
|
|
|
|
|
if (w <= 0 || h <= 0 || stride < w) {
|
|
|
|
mp_msg(MSGT_VO, MSGL_V, "Invalid dimensions OSD for part!\n");
|
|
|
|
return;
|
|
|
|
}
|
2005-07-26 12:16:18 +02:00
|
|
|
texSize(w, h, &sx, &sy);
|
2004-10-08 21:53:11 +02:00
|
|
|
|
|
|
|
if (osdtexCnt >= MAX_OSD_PARTS) {
|
|
|
|
mp_msg(MSGT_VO, MSGL_ERR, "Too many OSD parts, contact the developers!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// create Textures for OSD part
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglGenTextures(1, &osdtex[osdtexCnt]);
|
|
|
|
mpglBindTexture(gl_target, osdtex[osdtexCnt]);
|
2008-09-20 19:48:01 +02:00
|
|
|
glCreateClearTex(gl_target, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, scale_type, sx, sy, 0);
|
2005-07-27 19:22:24 +02:00
|
|
|
glUploadTex(gl_target, GL_LUMINANCE, GL_UNSIGNED_BYTE, src, stride,
|
|
|
|
0, 0, w, h, 0);
|
2004-10-08 21:53:11 +02:00
|
|
|
|
|
|
|
#ifndef FAST_OSD
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglGenTextures(1, &osdatex[osdtexCnt]);
|
|
|
|
mpglBindTexture(gl_target, osdatex[osdtexCnt]);
|
2008-11-25 19:24:23 +01:00
|
|
|
glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, sx, sy, 0);
|
2005-07-27 19:22:24 +02:00
|
|
|
{
|
2005-08-14 21:24:49 +02:00
|
|
|
int i;
|
2006-07-02 05:59:36 +02:00
|
|
|
char *tmp = malloc(stride * h);
|
2005-08-19 14:23:34 +02:00
|
|
|
// convert alpha from weird MPlayer scale.
|
|
|
|
// in-place is not possible since it is reused for future OSDs
|
2006-10-24 20:51:38 +02:00
|
|
|
for (i = h * stride - 1; i >= 0; i--)
|
2008-02-11 20:00:01 +01:00
|
|
|
tmp[i] = -srca[i];
|
2005-07-27 19:22:24 +02:00
|
|
|
glUploadTex(gl_target, GL_ALPHA, GL_UNSIGNED_BYTE, tmp, stride,
|
|
|
|
0, 0, w, h, 0);
|
|
|
|
free(tmp);
|
|
|
|
}
|
2004-10-08 21:53:11 +02:00
|
|
|
#endif
|
|
|
|
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindTexture(gl_target, 0);
|
2004-10-08 21:53:11 +02:00
|
|
|
|
|
|
|
// Create a list for rendering this OSD part
|
|
|
|
#ifndef FAST_OSD
|
2010-04-03 09:08:07 +02:00
|
|
|
osdaDispList[osdtexCnt] = mpglGenLists(1);
|
|
|
|
mpglNewList(osdaDispList[osdtexCnt], GL_COMPILE);
|
2004-10-08 21:53:11 +02:00
|
|
|
// render alpha
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindTexture(gl_target, osdatex[osdtexCnt]);
|
2005-12-18 13:04:08 +01:00
|
|
|
glDrawTex(x0, y0, w, h, 0, 0, w, h, sx, sy, use_rectangle == 1, 0, 0);
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglEndList();
|
2004-10-08 21:53:11 +02:00
|
|
|
#endif
|
2010-04-03 09:08:07 +02:00
|
|
|
osdDispList[osdtexCnt] = mpglGenLists(1);
|
|
|
|
mpglNewList(osdDispList[osdtexCnt], GL_COMPILE);
|
2004-10-08 21:53:11 +02:00
|
|
|
// render OSD
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindTexture(gl_target, osdtex[osdtexCnt]);
|
2005-12-18 13:04:08 +01:00
|
|
|
glDrawTex(x0, y0, w, h, 0, 0, w, h, sx, sy, use_rectangle == 1, 0, 0);
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglEndList();
|
2004-10-08 21:53:11 +02:00
|
|
|
|
|
|
|
osdtexCnt++;
|
|
|
|
}
|
|
|
|
|
2010-08-01 19:36:15 +02:00
|
|
|
#define RENDER_OSD 1
|
|
|
|
#define RENDER_EOSD 2
|
|
|
|
|
2009-03-06 11:33:35 +01:00
|
|
|
/**
|
|
|
|
* \param type bit 0: render OSD, bit 1: render EOSD
|
|
|
|
*/
|
|
|
|
static void do_render_osd(int type) {
|
2010-08-01 19:36:15 +02:00
|
|
|
int draw_osd = (type & RENDER_OSD) && osdtexCnt > 0;
|
|
|
|
int draw_eosd = (type & RENDER_EOSD) && eosdDispList;
|
2010-08-01 19:37:38 +02:00
|
|
|
if (!draw_osd && !draw_eosd)
|
|
|
|
return;
|
|
|
|
// set special rendering parameters
|
|
|
|
if (!scaled_osd) {
|
|
|
|
mpglMatrixMode(GL_PROJECTION);
|
|
|
|
mpglPushMatrix();
|
|
|
|
mpglLoadIdentity();
|
|
|
|
mpglOrtho(0, vo_dwidth, vo_dheight, 0, -1, 1);
|
|
|
|
}
|
|
|
|
mpglEnable(GL_BLEND);
|
|
|
|
if (draw_eosd) {
|
|
|
|
mpglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
mpglCallList(eosdDispList);
|
|
|
|
}
|
|
|
|
if (draw_osd) {
|
|
|
|
mpglColor4ub((osd_color >> 16) & 0xff, (osd_color >> 8) & 0xff, osd_color & 0xff, 0xff - (osd_color >> 24));
|
|
|
|
// draw OSD
|
2006-06-15 10:43:41 +02:00
|
|
|
#ifndef FAST_OSD
|
2010-08-01 19:37:38 +02:00
|
|
|
mpglBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
mpglCallLists(osdtexCnt, GL_UNSIGNED_INT, osdaDispList);
|
2006-06-15 10:43:41 +02:00
|
|
|
#endif
|
2010-08-01 19:37:38 +02:00
|
|
|
mpglBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
|
|
mpglCallLists(osdtexCnt, GL_UNSIGNED_INT, osdDispList);
|
2004-10-08 21:53:11 +02:00
|
|
|
}
|
2010-08-01 19:37:38 +02:00
|
|
|
// set rendering parameters back to defaults
|
|
|
|
mpglDisable(GL_BLEND);
|
|
|
|
if (!scaled_osd)
|
|
|
|
mpglPopMatrix();
|
|
|
|
mpglBindTexture(gl_target, 0);
|
2008-05-25 13:06:51 +02:00
|
|
|
}
|
2004-10-08 21:53:11 +02:00
|
|
|
|
2009-12-27 15:31:13 +01:00
|
|
|
static void draw_osd(void)
|
|
|
|
{
|
|
|
|
if (!use_osd) return;
|
|
|
|
if (vo_osd_changed(0)) {
|
|
|
|
int osd_h, osd_w;
|
|
|
|
clearOSD();
|
|
|
|
osd_w = scaled_osd ? image_width : vo_dwidth;
|
|
|
|
osd_h = scaled_osd ? image_height : vo_dheight;
|
|
|
|
vo_draw_text_ext(osd_w, osd_h, ass_border_x, ass_border_y, ass_border_x, ass_border_y,
|
|
|
|
image_width, image_height, create_osd_texture);
|
|
|
|
}
|
2010-08-01 19:36:15 +02:00
|
|
|
if (vo_doublebuffering) do_render_osd(RENDER_OSD);
|
2009-12-27 15:31:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void do_render(void) {
|
|
|
|
// Enable(GL_TEXTURE_2D);
|
|
|
|
// BindTexture(GL_TEXTURE_2D, texture_id);
|
|
|
|
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglColor3f(1,1,1);
|
2009-12-30 12:32:24 +01:00
|
|
|
if (is_yuv || custom_prog)
|
2009-12-27 15:31:13 +01:00
|
|
|
glEnableYUVConversion(gl_target, yuvconvtype);
|
2010-07-05 21:19:56 +02:00
|
|
|
if (stereo_mode) {
|
|
|
|
glEnable3DLeft(stereo_mode);
|
|
|
|
glDrawTex(0, 0, image_width, image_height,
|
|
|
|
0, 0, image_width >> 1, image_height,
|
|
|
|
texture_width, texture_height,
|
|
|
|
use_rectangle == 1, is_yuv,
|
|
|
|
mpi_flipped ^ vo_flipped);
|
|
|
|
glEnable3DRight(stereo_mode);
|
|
|
|
glDrawTex(0, 0, image_width, image_height,
|
|
|
|
image_width >> 1, 0, image_width >> 1, image_height,
|
|
|
|
texture_width, texture_height,
|
|
|
|
use_rectangle == 1, is_yuv,
|
|
|
|
mpi_flipped ^ vo_flipped);
|
|
|
|
glDisable3D(stereo_mode);
|
|
|
|
} else {
|
2010-07-05 21:45:14 +02:00
|
|
|
glDrawTex(0, 0, image_width, image_height,
|
|
|
|
0, 0, image_width, image_height,
|
|
|
|
texture_width, texture_height,
|
|
|
|
use_rectangle == 1, is_yuv,
|
|
|
|
mpi_flipped ^ vo_flipped);
|
2010-07-05 21:19:56 +02:00
|
|
|
}
|
2009-12-30 12:32:24 +01:00
|
|
|
if (is_yuv || custom_prog)
|
2009-12-27 15:31:13 +01:00
|
|
|
glDisableYUVConversion(gl_target, yuvconvtype);
|
|
|
|
}
|
|
|
|
|
2008-05-25 13:06:51 +02:00
|
|
|
static void flip_page(void) {
|
2008-05-25 13:11:32 +02:00
|
|
|
if (vo_doublebuffering) {
|
2010-04-03 09:08:07 +02:00
|
|
|
if (use_glFinish) mpglFinish();
|
2009-12-08 07:42:46 +01:00
|
|
|
glctx.swapGlBuffers(&glctx);
|
2009-08-27 20:36:51 +02:00
|
|
|
if (aspect_scaling() && use_aspect)
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglClear(GL_COLOR_BUFFER_BIT);
|
2008-05-25 13:11:32 +02:00
|
|
|
} else {
|
2008-05-25 13:26:09 +02:00
|
|
|
do_render();
|
2010-08-01 19:36:15 +02:00
|
|
|
do_render_osd(RENDER_OSD | RENDER_EOSD);
|
2010-04-03 09:08:07 +02:00
|
|
|
if (use_glFinish) mpglFinish();
|
|
|
|
else mpglFlush();
|
2008-05-25 13:11:32 +02:00
|
|
|
}
|
2001-02-24 21:28:24 +01:00
|
|
|
}
|
|
|
|
|
2008-05-25 13:26:09 +02:00
|
|
|
static void redraw(void) {
|
2010-08-01 19:36:15 +02:00
|
|
|
if (vo_doublebuffering) { do_render(); do_render_osd(RENDER_OSD | RENDER_EOSD); }
|
2008-05-25 13:26:09 +02:00
|
|
|
flip_page();
|
2001-02-24 21:28:24 +01:00
|
|
|
}
|
|
|
|
|
2005-08-05 03:24:37 +02:00
|
|
|
static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y)
|
2001-02-24 21:28:24 +01:00
|
|
|
{
|
2008-12-03 10:27:19 +01:00
|
|
|
mpi_flipped = stride[0] < 0;
|
2005-09-15 00:08:04 +02:00
|
|
|
glUploadTex(gl_target, gl_format, gl_type, src[0], stride[0],
|
|
|
|
x, y, w, h, slice_height);
|
2009-12-30 12:32:24 +01:00
|
|
|
if (is_yuv) {
|
|
|
|
int xs, ys;
|
2011-05-10 19:51:39 +02:00
|
|
|
mp_get_chroma_shift(image_format, &xs, &ys, NULL);
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglActiveTexture(GL_TEXTURE1);
|
2005-09-15 00:08:04 +02:00
|
|
|
glUploadTex(gl_target, gl_format, gl_type, src[1], stride[1],
|
2009-12-30 12:32:24 +01:00
|
|
|
x >> xs, y >> ys, w >> xs, h >> ys, slice_height);
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglActiveTexture(GL_TEXTURE2);
|
2005-09-15 00:08:04 +02:00
|
|
|
glUploadTex(gl_target, gl_format, gl_type, src[2], stride[2],
|
2009-12-30 12:32:24 +01:00
|
|
|
x >> xs, y >> ys, w >> xs, h >> ys, slice_height);
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglActiveTexture(GL_TEXTURE0);
|
2005-09-15 00:08:04 +02:00
|
|
|
}
|
2006-08-28 22:38:31 +02:00
|
|
|
return 0;
|
2001-02-24 21:28:24 +01:00
|
|
|
}
|
|
|
|
|
2005-07-26 12:16:18 +02:00
|
|
|
static uint32_t get_image(mp_image_t *mpi) {
|
2008-12-05 21:56:49 +01:00
|
|
|
int needed_size;
|
2010-04-03 09:08:07 +02:00
|
|
|
if (!mpglGenBuffers || !mpglBindBuffer || !mpglBufferData || !mpglMapBuffer) {
|
2005-07-26 12:16:18 +02:00
|
|
|
if (!err_shown)
|
|
|
|
mp_msg(MSGT_VO, MSGL_ERR, "[gl] extensions missing for dr\n"
|
|
|
|
"Expect a _major_ speed penalty\n");
|
2005-07-26 22:36:34 +02:00
|
|
|
err_shown = 1;
|
2005-07-26 12:16:18 +02:00
|
|
|
return VO_FALSE;
|
|
|
|
}
|
|
|
|
if (mpi->flags & MP_IMGFLAG_READABLE) return VO_FALSE;
|
2009-03-16 15:25:03 +01:00
|
|
|
if (mpi->type != MP_IMGTYPE_STATIC && mpi->type != MP_IMGTYPE_TEMP &&
|
|
|
|
(mpi->type != MP_IMGTYPE_NUMBERED || mpi->number))
|
|
|
|
return VO_FALSE;
|
2008-12-06 13:13:14 +01:00
|
|
|
if (mesa_buffer) mpi->width = texture_width;
|
|
|
|
else if (ati_hack) {
|
2008-11-14 11:31:15 +01:00
|
|
|
mpi->width = texture_width;
|
|
|
|
mpi->height = texture_height;
|
2008-07-04 23:19:27 +02:00
|
|
|
}
|
2005-07-26 12:16:18 +02:00
|
|
|
mpi->stride[0] = mpi->width * mpi->bpp / 8;
|
2008-12-05 23:16:45 +01:00
|
|
|
needed_size = mpi->stride[0] * mpi->height;
|
|
|
|
if (mesa_buffer) {
|
2009-12-19 14:49:44 +01:00
|
|
|
#ifdef CONFIG_GL_X11
|
2008-12-05 23:16:45 +01:00
|
|
|
if (mesa_bufferptr && needed_size > mesa_buffersize) {
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglFreeMemoryMESA(mDisplay, mScreen, mesa_bufferptr);
|
2008-12-05 23:16:45 +01:00
|
|
|
mesa_bufferptr = NULL;
|
|
|
|
}
|
|
|
|
if (!mesa_bufferptr)
|
2010-04-03 09:08:07 +02:00
|
|
|
mesa_bufferptr = mpglAllocateMemoryMESA(mDisplay, mScreen, needed_size, 0, 1.0, 1.0);
|
2008-12-05 23:16:45 +01:00
|
|
|
mesa_buffersize = needed_size;
|
|
|
|
#endif
|
|
|
|
mpi->planes[0] = mesa_bufferptr;
|
|
|
|
} else {
|
2008-12-05 23:35:24 +01:00
|
|
|
if (!gl_buffer)
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglGenBuffers(1, &gl_buffer);
|
|
|
|
mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer);
|
2008-12-05 23:35:24 +01:00
|
|
|
if (needed_size > gl_buffersize) {
|
|
|
|
gl_buffersize = needed_size;
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBufferData(GL_PIXEL_UNPACK_BUFFER, gl_buffersize,
|
|
|
|
NULL, GL_DYNAMIC_DRAW);
|
2008-12-05 23:35:24 +01:00
|
|
|
}
|
|
|
|
if (!gl_bufferptr)
|
2010-04-03 09:08:07 +02:00
|
|
|
gl_bufferptr = mpglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
|
2008-12-05 23:35:24 +01:00
|
|
|
mpi->planes[0] = gl_bufferptr;
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
2005-07-26 12:16:18 +02:00
|
|
|
}
|
2008-12-03 10:27:19 +01:00
|
|
|
if (!mpi->planes[0]) {
|
2005-07-26 22:36:34 +02:00
|
|
|
if (!err_shown)
|
2008-01-18 19:16:32 +01:00
|
|
|
mp_msg(MSGT_VO, MSGL_ERR, "[gl] could not acquire buffer for dr\n"
|
2005-07-26 22:36:34 +02:00
|
|
|
"Expect a _major_ speed penalty\n");
|
|
|
|
err_shown = 1;
|
|
|
|
return VO_FALSE;
|
|
|
|
}
|
2009-12-30 12:32:24 +01:00
|
|
|
if (is_yuv) {
|
|
|
|
// planar YUV
|
2011-10-06 15:59:14 +02:00
|
|
|
int xs, ys, component_bits;
|
|
|
|
mp_get_chroma_shift(image_format, &xs, &ys, &component_bits);
|
|
|
|
int bp = (component_bits + 7) / 8;
|
2005-09-15 00:08:04 +02:00
|
|
|
mpi->flags |= MP_IMGFLAG_COMMON_STRIDE | MP_IMGFLAG_COMMON_PLANE;
|
2011-10-06 15:59:14 +02:00
|
|
|
mpi->stride[0] = mpi->width * bp;
|
2005-09-15 00:08:04 +02:00
|
|
|
mpi->planes[1] = mpi->planes[0] + mpi->stride[0] * mpi->height;
|
2011-10-06 15:59:14 +02:00
|
|
|
mpi->stride[1] = (mpi->width >> xs) * bp;
|
2009-12-30 12:32:24 +01:00
|
|
|
mpi->planes[2] = mpi->planes[1] + mpi->stride[1] * (mpi->height >> ys);
|
2011-10-06 15:59:14 +02:00
|
|
|
mpi->stride[2] = (mpi->width >> xs) * bp;
|
2008-12-06 13:13:14 +01:00
|
|
|
if (ati_hack && !mesa_buffer) {
|
2008-11-24 12:04:50 +01:00
|
|
|
mpi->flags &= ~MP_IMGFLAG_COMMON_PLANE;
|
2010-04-03 09:08:07 +02:00
|
|
|
if (!gl_buffer_uv[0]) mpglGenBuffers(2, gl_buffer_uv);
|
2008-11-24 12:04:50 +01:00
|
|
|
if (mpi->stride[1] * mpi->height > gl_buffersize_uv) {
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer_uv[0]);
|
|
|
|
mpglBufferData(GL_PIXEL_UNPACK_BUFFER, mpi->stride[1] * mpi->height,
|
|
|
|
NULL, GL_DYNAMIC_DRAW);
|
|
|
|
mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer_uv[1]);
|
|
|
|
mpglBufferData(GL_PIXEL_UNPACK_BUFFER, mpi->stride[1] * mpi->height,
|
|
|
|
NULL, GL_DYNAMIC_DRAW);
|
2008-11-24 12:04:50 +01:00
|
|
|
gl_buffersize_uv = mpi->stride[1] * mpi->height;
|
|
|
|
}
|
|
|
|
if (!gl_bufferptr_uv[0]) {
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer_uv[0]);
|
|
|
|
gl_bufferptr_uv[0] = mpglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
|
|
|
|
mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer_uv[1]);
|
|
|
|
gl_bufferptr_uv[1] = mpglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
|
2008-11-24 12:04:50 +01:00
|
|
|
}
|
|
|
|
mpi->planes[1] = gl_bufferptr_uv[0];
|
|
|
|
mpi->planes[2] = gl_bufferptr_uv[1];
|
|
|
|
}
|
2005-09-15 00:08:04 +02:00
|
|
|
}
|
2005-07-26 12:16:18 +02:00
|
|
|
mpi->flags |= MP_IMGFLAG_DIRECT;
|
|
|
|
return VO_TRUE;
|
|
|
|
}
|
|
|
|
|
2008-12-27 14:00:03 +01:00
|
|
|
static void clear_border(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) {
|
|
|
|
memset(dst + start, value, right_border);
|
|
|
|
dst += stride;
|
|
|
|
height--;
|
|
|
|
}
|
|
|
|
if (bottom_border > 0)
|
|
|
|
memset(dst, value, stride * bottom_border);
|
|
|
|
}
|
|
|
|
|
2005-07-25 21:11:14 +02:00
|
|
|
static uint32_t draw_image(mp_image_t *mpi) {
|
2005-07-27 19:22:24 +02:00
|
|
|
int slice = slice_height;
|
2008-05-10 14:21:37 +02:00
|
|
|
int stride[3];
|
|
|
|
unsigned char *planes[3];
|
|
|
|
mp_image_t mpi2 = *mpi;
|
2008-11-14 11:31:15 +01:00
|
|
|
int w = mpi->w, h = mpi->h;
|
2005-07-25 21:11:14 +02:00
|
|
|
if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
|
2008-05-25 13:26:09 +02:00
|
|
|
goto skip_upload;
|
2008-05-10 14:21:37 +02:00
|
|
|
mpi2.flags = 0; mpi2.type = MP_IMGTYPE_TEMP;
|
|
|
|
mpi2.width = mpi2.w; mpi2.height = mpi2.h;
|
|
|
|
if (force_pbo && !(mpi->flags & MP_IMGFLAG_DIRECT) && !gl_bufferptr && get_image(&mpi2) == VO_TRUE) {
|
2011-10-06 15:59:14 +02:00
|
|
|
int bpp = mpi->bpp;
|
|
|
|
int xs, ys, component_bits;
|
|
|
|
mp_get_chroma_shift(image_format, &xs, &ys, &component_bits);
|
|
|
|
if (is_yuv)
|
|
|
|
bpp = component_bits + 7;
|
2008-06-22 09:25:48 +02:00
|
|
|
memcpy_pic(mpi2.planes[0], mpi->planes[0], mpi->w * bpp / 8, mpi->h, mpi2.stride[0], mpi->stride[0]);
|
2009-12-30 12:32:24 +01:00
|
|
|
if (is_yuv) {
|
2011-10-06 15:59:14 +02:00
|
|
|
int bp = (component_bits + 7) / 8;
|
|
|
|
memcpy_pic(mpi2.planes[1], mpi->planes[1], (mpi->w >> xs) * bp, mpi->h >> ys, mpi2.stride[1], mpi->stride[1]);
|
|
|
|
memcpy_pic(mpi2.planes[2], mpi->planes[2], (mpi->w >> xs) * bp, mpi->h >> ys, mpi2.stride[2], mpi->stride[2]);
|
2008-05-10 14:21:37 +02:00
|
|
|
}
|
2008-12-27 14:00:03 +01:00
|
|
|
if (ati_hack) { // since we have to do a full upload we need to clear the borders
|
|
|
|
clear_border(mpi2.planes[0], mpi->w * bpp / 8, mpi2.stride[0], mpi->h, mpi2.height, 0);
|
2009-12-30 12:32:24 +01:00
|
|
|
if (is_yuv) {
|
|
|
|
clear_border(mpi2.planes[1], mpi->w >> xs, mpi2.stride[1], mpi->h >> ys, mpi2.height >> ys, 128);
|
|
|
|
clear_border(mpi2.planes[2], mpi->w >> xs, mpi2.stride[2], mpi->h >> ys, mpi2.height >> ys, 128);
|
2008-12-27 14:00:03 +01:00
|
|
|
}
|
|
|
|
}
|
2008-05-10 14:21:37 +02:00
|
|
|
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];
|
2008-12-03 10:27:19 +01:00
|
|
|
mpi_flipped = stride[0] < 0;
|
2008-12-06 07:18:57 +01:00
|
|
|
if (mpi->flags & MP_IMGFLAG_DIRECT) {
|
2008-12-06 07:44:54 +01:00
|
|
|
if (mesa_buffer) {
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, 1);
|
2008-12-06 07:44:54 +01:00
|
|
|
w = texture_width;
|
|
|
|
} else {
|
2008-12-06 07:40:47 +01:00
|
|
|
intptr_t base = (intptr_t)planes[0];
|
2008-12-06 07:41:36 +01:00
|
|
|
if (ati_hack) { w = texture_width; h = texture_height; }
|
2008-12-06 07:40:47 +01:00
|
|
|
if (mpi_flipped)
|
|
|
|
base += (mpi->h - 1) * stride[0];
|
|
|
|
planes[0] -= base;
|
|
|
|
planes[1] -= base;
|
|
|
|
planes[2] -= base;
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer);
|
|
|
|
mpglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
2008-12-06 07:40:47 +01:00
|
|
|
gl_bufferptr = NULL;
|
|
|
|
if (!(mpi->flags & MP_IMGFLAG_COMMON_PLANE))
|
|
|
|
planes[0] = planes[1] = planes[2] = NULL;
|
2008-12-06 07:18:57 +01:00
|
|
|
}
|
2008-12-05 23:16:45 +01:00
|
|
|
slice = 0; // always "upload" full texture
|
2008-12-06 07:18:57 +01:00
|
|
|
}
|
2006-07-10 20:35:29 +02:00
|
|
|
glUploadTex(gl_target, gl_format, gl_type, planes[0], stride[0],
|
2008-11-14 11:31:15 +01:00
|
|
|
mpi->x, mpi->y, w, h, slice);
|
2009-12-30 12:32:24 +01:00
|
|
|
if (is_yuv) {
|
|
|
|
int xs, ys;
|
2011-05-10 19:51:39 +02:00
|
|
|
mp_get_chroma_shift(image_format, &xs, &ys, NULL);
|
2008-11-24 12:04:50 +01:00
|
|
|
if ((mpi->flags & MP_IMGFLAG_DIRECT) && !(mpi->flags & MP_IMGFLAG_COMMON_PLANE)) {
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer_uv[0]);
|
|
|
|
mpglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
2008-11-24 12:04:50 +01:00
|
|
|
gl_bufferptr_uv[0] = NULL;
|
|
|
|
}
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglActiveTexture(GL_TEXTURE1);
|
2006-07-10 20:35:29 +02:00
|
|
|
glUploadTex(gl_target, gl_format, gl_type, planes[1], stride[1],
|
2009-12-30 12:32:24 +01:00
|
|
|
mpi->x >> xs, mpi->y >> ys, w >> xs, h >> ys, slice);
|
2008-11-24 12:04:50 +01:00
|
|
|
if ((mpi->flags & MP_IMGFLAG_DIRECT) && !(mpi->flags & MP_IMGFLAG_COMMON_PLANE)) {
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer_uv[1]);
|
|
|
|
mpglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
2008-11-24 12:04:50 +01:00
|
|
|
gl_bufferptr_uv[1] = NULL;
|
|
|
|
}
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglActiveTexture(GL_TEXTURE2);
|
2006-07-10 20:35:29 +02:00
|
|
|
glUploadTex(gl_target, gl_format, gl_type, planes[2], stride[2],
|
2009-12-30 12:32:24 +01:00
|
|
|
mpi->x >> xs, mpi->y >> ys, w >> xs, h >> ys, slice);
|
2010-04-03 09:08:07 +02:00
|
|
|
mpglActiveTexture(GL_TEXTURE0);
|
2005-09-15 00:08:04 +02:00
|
|
|
}
|
2008-12-06 07:18:57 +01:00
|
|
|
if (mpi->flags & MP_IMGFLAG_DIRECT) {
|
2010-04-03 09:08:07 +02:00
|
|
|
if (mesa_buffer) mpglPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, 0);
|
|
|
|
else mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
2008-12-06 07:18:57 +01:00
|
|
|
}
|
2008-05-25 13:26:09 +02:00
|
|
|
skip_upload:
|
|
|
|
if (vo_doublebuffering) do_render();
|
2005-07-25 21:11:14 +02:00
|
|
|
return VO_TRUE;
|
|
|
|
}
|
2001-02-24 21:28:24 +01:00
|
|
|
|
2005-08-05 03:24:37 +02:00
|
|
|
static int
|
2003-05-20 18:48:05 +02:00
|
|
|
draw_frame(uint8_t *src[])
|
2001-02-24 21:28:24 +01:00
|
|
|
{
|
2009-07-07 01:26:13 +02:00
|
|
|
return VO_ERROR;
|
2001-02-24 21:28:24 +01:00
|
|
|
}
|
|
|
|
|
2005-08-05 03:24:37 +02:00
|
|
|
static int
|
2001-02-24 21:28:24 +01:00
|
|
|
query_format(uint32_t format)
|
|
|
|
{
|
2011-05-10 19:51:39 +02:00
|
|
|
int depth;
|
2005-07-25 21:11:14 +02:00
|
|
|
int caps = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW |
|
2006-07-10 20:36:50 +02:00
|
|
|
VFCAP_FLIP |
|
2005-07-25 21:11:14 +02:00
|
|
|
VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE;
|
2004-10-08 21:53:11 +02:00
|
|
|
if (use_osd)
|
2007-04-27 18:10:45 +02:00
|
|
|
caps |= VFCAP_OSD | VFCAP_EOSD | (scaled_osd ? 0 : VFCAP_EOSD_UNSCALED);
|
2008-12-03 10:27:19 +01:00
|
|
|
if (format == IMGFMT_RGB24 || format == IMGFMT_RGBA)
|
2004-10-08 21:53:11 +02:00
|
|
|
return caps;
|
2011-05-10 19:51:39 +02:00
|
|
|
if (use_yuv && mp_get_chroma_shift(format, NULL, NULL, &depth) &&
|
2011-05-24 22:52:27 +02:00
|
|
|
(depth == 8 || depth == 16 || glYUVLargeRange(use_yuv)) &&
|
2009-12-31 23:53:25 +01:00
|
|
|
(IMGFMT_IS_YUVP16_NE(format) || !IMGFMT_IS_YUVP16(format)))
|
2005-09-15 00:08:04 +02:00
|
|
|
return caps;
|
2006-08-08 16:56:12 +02:00
|
|
|
// 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 (!use_yuv && (format == IMGFMT_Y8 || format == IMGFMT_Y800))
|
|
|
|
return 0;
|
2011-06-21 21:44:24 +02:00
|
|
|
if (!use_ycbcr && (format == IMGFMT_UYVY || format == IMGFMT_YVYU))
|
2008-12-05 16:36:54 +01:00
|
|
|
return 0;
|
2004-12-01 18:05:58 +01:00
|
|
|
if (many_fmts &&
|
|
|
|
glFindFormat(format, NULL, NULL, NULL, NULL))
|
2004-10-08 21:53:11 +02:00
|
|
|
return caps;
|
2001-02-24 21:28:24 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
uninit(void)
|
|
|
|
{
|
2005-09-09 16:47:54 +02:00
|
|
|
uninitGl();
|
2010-11-14 10:12:34 +01:00
|
|
|
free(custom_prog);
|
2005-09-15 00:08:04 +02:00
|
|
|
custom_prog = NULL;
|
2010-11-14 10:12:34 +01:00
|
|
|
free(custom_tex);
|
2005-09-25 18:31:58 +02:00
|
|
|
custom_tex = NULL;
|
2009-12-08 07:42:46 +01:00
|
|
|
uninit_mpglcontext(&glctx);
|
2001-02-24 21:28:24 +01:00
|
|
|
}
|
2002-01-26 17:01:26 +01:00
|
|
|
|
2009-03-07 09:51:40 +01:00
|
|
|
static const opt_t subopts[] = {
|
2004-12-31 15:58:49 +01:00
|
|
|
{"manyfmts", OPT_ARG_BOOL, &many_fmts, NULL},
|
|
|
|
{"osd", OPT_ARG_BOOL, &use_osd, NULL},
|
|
|
|
{"scaled-osd", OPT_ARG_BOOL, &scaled_osd, NULL},
|
|
|
|
{"aspect", OPT_ARG_BOOL, &use_aspect, NULL},
|
2008-12-05 16:36:54 +01:00
|
|
|
{"ycbcr", OPT_ARG_BOOL, &use_ycbcr, NULL},
|
2010-01-01 14:18:49 +01:00
|
|
|
{"slice-height", OPT_ARG_INT, &slice_height, int_non_neg},
|
|
|
|
{"rectangle", OPT_ARG_INT, &use_rectangle,int_non_neg},
|
|
|
|
{"yuv", OPT_ARG_INT, &use_yuv, int_non_neg},
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
{"colorspace", OPT_ARG_INT, &user_colorspace, NULL},
|
|
|
|
{"levelconv", OPT_ARG_INT, &levelconv, NULL},
|
2010-01-01 14:18:49 +01:00
|
|
|
{"lscale", OPT_ARG_INT, &lscale, int_non_neg},
|
|
|
|
{"cscale", OPT_ARG_INT, &cscale, int_non_neg},
|
2008-05-24 13:19:38 +02:00
|
|
|
{"filter-strength", OPT_ARG_FLOAT, &filter_strength, NULL},
|
2008-05-10 13:48:17 +02:00
|
|
|
{"ati-hack", OPT_ARG_BOOL, &ati_hack, NULL},
|
2008-05-10 14:21:37 +02:00
|
|
|
{"force-pbo", OPT_ARG_BOOL, &force_pbo, NULL},
|
2008-12-05 23:16:45 +01:00
|
|
|
{"mesa-buffer", OPT_ARG_BOOL, &mesa_buffer, NULL},
|
2005-08-16 20:27:12 +02:00
|
|
|
{"glfinish", OPT_ARG_BOOL, &use_glFinish, NULL},
|
2005-08-19 11:31:02 +02:00
|
|
|
{"swapinterval", OPT_ARG_INT, &swap_interval,NULL},
|
2005-09-15 00:08:04 +02:00
|
|
|
{"customprog", OPT_ARG_MSTRZ,&custom_prog, NULL},
|
2005-09-25 18:31:58 +02:00
|
|
|
{"customtex", OPT_ARG_MSTRZ,&custom_tex, NULL},
|
|
|
|
{"customtlin", OPT_ARG_BOOL, &custom_tlin, NULL},
|
2006-07-08 21:29:04 +02:00
|
|
|
{"customtrect", OPT_ARG_BOOL, &custom_trect, NULL},
|
2009-12-19 21:53:34 +01:00
|
|
|
{"mipmapgen", OPT_ARG_BOOL, &mipmap_gen, NULL},
|
2006-03-26 12:43:56 +02:00
|
|
|
{"osdcolor", OPT_ARG_INT, &osd_color, NULL},
|
2010-07-05 21:19:56 +02:00
|
|
|
{"stereo", OPT_ARG_INT, &stereo_mode, NULL},
|
2004-12-31 15:58:49 +01:00
|
|
|
{NULL}
|
|
|
|
};
|
|
|
|
|
2010-02-27 19:16:41 +01:00
|
|
|
static int preinit_internal(const char *arg, int allow_sw)
|
2002-01-26 17:01:26 +01:00
|
|
|
{
|
2004-12-31 15:58:49 +01:00
|
|
|
// set defaults
|
2010-04-25 12:53:01 +02:00
|
|
|
enum MPGLType gltype = GLTYPE_AUTO;
|
2005-07-19 10:42:55 +02:00
|
|
|
many_fmts = 1;
|
2010-04-24 18:58:24 +02:00
|
|
|
use_osd = -1;
|
2004-10-17 21:32:47 +02:00
|
|
|
scaled_osd = 0;
|
2004-10-10 16:05:29 +02:00
|
|
|
use_aspect = 1;
|
2008-12-05 16:36:54 +01:00
|
|
|
use_ycbcr = 0;
|
2010-02-02 21:37:48 +01:00
|
|
|
use_yuv = -1;
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
user_colorspace = 0;
|
2010-01-16 20:59:31 +01:00
|
|
|
levelconv = -1;
|
2006-06-07 15:24:54 +02:00
|
|
|
lscale = 0;
|
|
|
|
cscale = 0;
|
2008-05-24 13:19:38 +02:00
|
|
|
filter_strength = 0.5;
|
2008-12-10 17:39:45 +01:00
|
|
|
use_rectangle = -1;
|
2005-08-16 20:27:12 +02:00
|
|
|
use_glFinish = 0;
|
2008-12-10 17:39:45 +01:00
|
|
|
ati_hack = -1;
|
|
|
|
force_pbo = -1;
|
2008-12-05 23:16:45 +01:00
|
|
|
mesa_buffer = 0;
|
2005-08-19 11:31:02 +02:00
|
|
|
swap_interval = 1;
|
2007-07-29 00:54:08 +02:00
|
|
|
slice_height = 0;
|
2005-09-15 00:08:04 +02:00
|
|
|
custom_prog = NULL;
|
2005-09-25 18:31:58 +02:00
|
|
|
custom_tex = NULL;
|
|
|
|
custom_tlin = 1;
|
2006-07-08 21:29:04 +02:00
|
|
|
custom_trect = 0;
|
2009-12-19 21:53:34 +01:00
|
|
|
mipmap_gen = 0;
|
2006-03-26 12:43:56 +02:00
|
|
|
osd_color = 0xffffff;
|
2010-07-05 21:19:56 +02:00
|
|
|
stereo_mode = 0;
|
2004-12-31 15:58:49 +01:00
|
|
|
if (subopt_parse(arg, subopts) != 0) {
|
2004-09-03 14:12:17 +02:00
|
|
|
mp_msg(MSGT_VO, MSGL_FATAL,
|
2004-04-15 20:19:39 +02:00
|
|
|
"\n-vo gl command line help:\n"
|
|
|
|
"Example: mplayer -vo gl:slice-height=4\n"
|
|
|
|
"\nOptions:\n"
|
2007-02-03 12:31:09 +01:00
|
|
|
" nomanyfmts\n"
|
|
|
|
" Disable extended color formats for OpenGL 1.2 and later\n"
|
2004-04-15 20:19:39 +02:00
|
|
|
" slice-height=<0-...>\n"
|
|
|
|
" Slice size for texture transfer, 0 for whole image\n"
|
2004-10-08 21:53:11 +02:00
|
|
|
" noosd\n"
|
|
|
|
" Do not use OpenGL OSD code\n"
|
2008-12-05 16:50:24 +01:00
|
|
|
" scaled-osd\n"
|
|
|
|
" Render OSD at movie resolution and scale it\n"
|
2004-10-10 16:05:29 +02:00
|
|
|
" noaspect\n"
|
|
|
|
" Do not do aspect scaling\n"
|
2005-07-26 12:16:18 +02:00
|
|
|
" 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"
|
2008-05-10 13:48:17 +02:00
|
|
|
" ati-hack\n"
|
|
|
|
" Workaround ATI bug with PBOs\n"
|
2008-05-10 14:21:37 +02:00
|
|
|
" force-pbo\n"
|
|
|
|
" Force use of PBO even if this involves an extra memcpy\n"
|
2005-08-16 20:27:12 +02:00
|
|
|
" glfinish\n"
|
|
|
|
" Call glFinish() before swapping buffers\n"
|
2005-08-19 11:31:02 +02:00
|
|
|
" 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"
|
2009-12-19 22:08:14 +01:00
|
|
|
" ycbcr\n"
|
|
|
|
" also try to use the GL_MESA_ycbcr_texture extension\n"
|
2005-09-15 00:08:04 +02:00
|
|
|
" yuv=<n>\n"
|
|
|
|
" 0: use software YUV to RGB conversion.\n"
|
2005-10-01 14:53:49 +02:00
|
|
|
" 1: use register combiners (nVidia only, for older cards).\n"
|
2005-09-15 00:08:04 +02:00
|
|
|
" 2: use fragment program.\n"
|
|
|
|
" 3: use fragment program with gamma correction.\n"
|
|
|
|
" 4: use fragment program with gamma correction via lookup.\n"
|
2005-10-01 14:53:49 +02:00
|
|
|
" 5: use ATI-specific method (for older cards).\n"
|
2007-02-03 12:31:09 +01:00
|
|
|
" 6: use lookup via 3D texture.\n"
|
2006-06-13 22:30:16 +02:00
|
|
|
" lscale=<n>\n"
|
|
|
|
" 0: use standard bilinear scaling for luma.\n"
|
|
|
|
" 1: use improved bicubic scaling for luma.\n"
|
2007-03-11 15:59:08 +01:00
|
|
|
" 2: use cubic in X, linear in Y direction scaling for luma.\n"
|
2008-01-15 18:54:48 +01:00
|
|
|
" 3: as 1 but without using a lookup texture.\n"
|
2008-12-05 16:50:24 +01:00
|
|
|
" 4: experimental unsharp masking (sharpening).\n"
|
|
|
|
" 5: experimental unsharp masking (sharpening) with larger radius.\n"
|
2006-06-13 22:30:16 +02:00
|
|
|
" cscale=<n>\n"
|
|
|
|
" as lscale but for chroma (2x slower with little visible effect).\n"
|
2008-12-05 16:50:24 +01:00
|
|
|
" filter-strength=<value>\n"
|
|
|
|
" set the effect strength for some lscale/cscale filters\n"
|
2005-09-15 00:08:04 +02:00
|
|
|
" customprog=<filename>\n"
|
|
|
|
" use a custom YUV conversion program\n"
|
|
|
|
" customtex=<filename>\n"
|
|
|
|
" use a custom YUV conversion lookup texture\n"
|
2005-09-25 18:31:58 +02:00
|
|
|
" nocustomtlin\n"
|
|
|
|
" use GL_NEAREST scaling for customtex texture\n"
|
2006-07-08 21:29:04 +02:00
|
|
|
" customtrect\n"
|
|
|
|
" use texture_rectangle for customtex texture\n"
|
2009-12-19 21:53:34 +01:00
|
|
|
" mipmapgen\n"
|
|
|
|
" generate mipmaps for the video image (use with TXB in customprog)\n"
|
2008-02-11 20:01:34 +01:00
|
|
|
" osdcolor=<0xAARRGGBB>\n"
|
2006-03-26 12:43:56 +02:00
|
|
|
" use the given color for the OSD\n"
|
2010-07-05 21:19:56 +02:00
|
|
|
" 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"
|
2010-07-08 22:17:45 +02:00
|
|
|
" 3: side-by-side to quadbuffer stereo\n"
|
2004-04-15 20:19:39 +02:00
|
|
|
"\n" );
|
|
|
|
return -1;
|
|
|
|
}
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
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;
|
|
|
|
}
|
2010-02-02 21:37:48 +01:00
|
|
|
if (!init_mpglcontext(&glctx, gltype))
|
|
|
|
goto err_out;
|
2010-02-27 19:16:41 +01:00
|
|
|
if (use_yuv == -1 || !allow_sw) {
|
2010-02-04 23:08:23 +01:00
|
|
|
if (create_window(320, 200, VOFLAG_HIDDEN, NULL) < 0)
|
2010-02-02 21:37:48 +01:00
|
|
|
goto err_out;
|
|
|
|
if (glctx.setGlWindow(&glctx) == SET_WINDOW_FAILED)
|
|
|
|
goto err_out;
|
2010-02-27 19:16:41 +01:00
|
|
|
if (!allow_sw && isSoftwareGl())
|
|
|
|
goto err_out;
|
2010-02-02 21:37:48 +01:00
|
|
|
autodetectGlExtensions();
|
|
|
|
}
|
2010-02-05 08:12:05 +01:00
|
|
|
if (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", slice_height);
|
2002-10-17 11:49:25 +02:00
|
|
|
|
2002-02-17 09:24:43 +01:00
|
|
|
return 0;
|
2010-02-02 21:37:48 +01:00
|
|
|
|
|
|
|
err_out:
|
|
|
|
uninit();
|
|
|
|
return -1;
|
2002-01-26 17:01:26 +01:00
|
|
|
}
|
|
|
|
|
2010-02-27 19:16:41 +01:00
|
|
|
static int preinit(const char *arg)
|
|
|
|
{
|
|
|
|
return preinit_internal(arg, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int preinit_nosw(const char *arg)
|
|
|
|
{
|
|
|
|
return preinit_internal(arg, 0);
|
|
|
|
}
|
|
|
|
|
2008-04-02 18:38:34 +02:00
|
|
|
static int control(uint32_t request, void *data)
|
2002-01-26 17:01:26 +01:00
|
|
|
{
|
2002-02-09 01:47:26 +01:00
|
|
|
switch (request) {
|
2008-05-22 22:21:19 +02:00
|
|
|
case VOCTRL_PAUSE:
|
|
|
|
case VOCTRL_RESUME:
|
|
|
|
int_pause = (request == VOCTRL_PAUSE);
|
|
|
|
return VO_TRUE;
|
2002-02-09 01:47:26 +01:00
|
|
|
case VOCTRL_QUERY_FORMAT:
|
2008-12-03 10:27:19 +01:00
|
|
|
return query_format(*(uint32_t*)data);
|
2005-07-26 12:16:18 +02:00
|
|
|
case VOCTRL_GET_IMAGE:
|
|
|
|
return get_image(data);
|
2005-07-25 21:11:14 +02:00
|
|
|
case VOCTRL_DRAW_IMAGE:
|
|
|
|
return draw_image(data);
|
2006-08-28 22:17:42 +02:00
|
|
|
case VOCTRL_DRAW_EOSD:
|
2006-12-06 19:44:26 +01:00
|
|
|
if (!data)
|
|
|
|
return VO_FALSE;
|
2006-08-28 22:17:42 +02:00
|
|
|
genEOSD(data);
|
2010-08-01 19:36:15 +02:00
|
|
|
if (vo_doublebuffering) do_render_osd(RENDER_EOSD);
|
2006-08-28 22:17:42 +02:00
|
|
|
return VO_TRUE;
|
|
|
|
case VOCTRL_GET_EOSD_RES:
|
|
|
|
{
|
|
|
|
mp_eosd_res_t *r = data;
|
2009-08-27 16:07:15 +02:00
|
|
|
r->w = vo_dwidth; r->h = vo_dheight;
|
2006-08-28 22:17:42 +02:00
|
|
|
r->mt = r->mb = r->ml = r->mr = 0;
|
|
|
|
if (scaled_osd) {r->w = image_width; r->h = image_height;}
|
2009-08-27 20:36:51 +02:00
|
|
|
else if (aspect_scaling()) {
|
2007-10-19 20:16:23 +02:00
|
|
|
r->ml = r->mr = ass_border_x;
|
|
|
|
r->mt = r->mb = ass_border_y;
|
2006-08-28 22:17:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return VO_TRUE;
|
2003-11-30 17:36:10 +01:00
|
|
|
case VOCTRL_ONTOP:
|
2009-12-08 07:42:46 +01:00
|
|
|
glctx.ontop();
|
2003-11-30 17:36:10 +01:00
|
|
|
return VO_TRUE;
|
2002-05-15 01:44:35 +02:00
|
|
|
case VOCTRL_FULLSCREEN:
|
2009-12-08 07:42:46 +01:00
|
|
|
glctx.fullscreen();
|
2005-07-26 15:47:18 +02:00
|
|
|
resize(vo_dwidth, vo_dheight);
|
2002-05-15 01:44:35 +02:00
|
|
|
return VO_TRUE;
|
2005-11-17 21:49:46 +01:00
|
|
|
case VOCTRL_BORDER:
|
2009-12-08 07:42:46 +01:00
|
|
|
glctx.border();
|
2008-02-01 13:22:12 +01:00
|
|
|
resize(vo_dwidth, vo_dheight);
|
2005-11-17 21:49:46 +01:00
|
|
|
return VO_TRUE;
|
2004-10-10 16:05:29 +02:00
|
|
|
case VOCTRL_GET_PANSCAN:
|
|
|
|
if (!use_aspect) return VO_NOTIMPL;
|
|
|
|
return VO_TRUE;
|
|
|
|
case VOCTRL_SET_PANSCAN:
|
|
|
|
if (!use_aspect) return VO_NOTIMPL;
|
2008-12-03 10:27:19 +01:00
|
|
|
resize(vo_dwidth, vo_dheight);
|
2004-10-10 16:05:29 +02:00
|
|
|
return VO_TRUE;
|
2005-09-15 00:08:04 +02:00
|
|
|
case VOCTRL_GET_EQUALIZER:
|
2009-12-30 12:32:24 +01:00
|
|
|
if (is_yuv) {
|
2008-04-02 17:51:38 +02:00
|
|
|
struct voctrl_get_equalizer_args *args = data;
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
return mp_csp_equalizer_get(&video_eq, args->name, args->valueptr) >= 0 ?
|
|
|
|
VO_TRUE : VO_NOTIMPL;
|
2005-09-15 00:08:04 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case VOCTRL_SET_EQUALIZER:
|
2009-12-30 12:32:24 +01:00
|
|
|
if (is_yuv) {
|
2008-04-02 17:51:38 +02:00
|
|
|
struct voctrl_set_equalizer_args *args = data;
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
if (mp_csp_equalizer_set(&video_eq, args->name, args->value) < 0)
|
|
|
|
return VO_NOTIMPL;
|
2005-09-15 00:08:04 +02:00
|
|
|
update_yuvconv();
|
|
|
|
return VO_TRUE;
|
|
|
|
}
|
|
|
|
break;
|
video, options: implement better YUV->RGB conversion control
Rewrite control of the colorspace and input/output level parameters
used in YUV-RGB conversions, replacing VO-specific suboptions with new
common options and adding configuration support to more cases.
Add new option --colormatrix which selects the colorspace the original
video is assumed to have in YUV->RGB conversions. The default
behavior changes from assuming BT.601 to colorspace autoselection
between BT.601 and BT.709 using a simple heuristic based on video
size. Add new options --colormatrix-input-range and
--colormatrix-output-range which select input YUV and output RGB range.
Disable the previously existing VO-specific colorspace and level
conversion suboptions in vo_gl and vo_vdpau. Remove the
"yuv_colorspace" property and replace it with one named "colormatrix"
and semantics matching the new option. Add new properties matching the
options for level conversion.
Colorspace selection is currently supported by vo_gl, vo_vdpau, vo_xv
and vf_scale, and all can change it at runtime (previously only
vo_vdpau and vo_xv could). vo_vdpau now uses the same conversion
matrix generation as vo_gl instead of libvdpau functionality; the main
functional difference is that the "contrast" equalizer control behaves
somewhat differently (it scales the Y component around 1/2 instead of
around 0, so that contrast 0 makes the image gray rather than black).
vo_xv does not support level conversion. vf_scale supports range
setting for input, but always outputs full-range RGB.
The value of the slave properties is the policy setting used for
conversions. This means they can be set to any value regardless of
whether the current VO supports that value or whether there currently
even is any video. Possibly separate properties could be added to
query the conversion actually used at the moment, if any.
Because the colorspace and level settings are now set with a single
VF/VO control call, the return value of that is no longer used to
signal whether all the settings are actually supported. Instead code
should set all the details it can support, and ignore the rest. The
core will use GET_YUV_COLORSPACE to check which colorspace details
have been set and which not. In other words, the return value for
SET_YUV_COLORSPACE only signals whether any kind of YUV colorspace
conversion handling exists at all, and VOs have to take care to return
the actual state with GET_YUV_COLORSPACE instead.
To be changed in later commits: add missing option documentation.
2011-10-15 23:50:21 +02:00
|
|
|
case VOCTRL_SET_YUV_COLORSPACE: {
|
|
|
|
bool supports_csp = (1 << use_yuv) & MASK_NOT_COMBINERS;
|
|
|
|
if (vo_config_count && supports_csp) {
|
|
|
|
colorspace = *(struct mp_csp_details *)data;
|
|
|
|
update_yuvconv();
|
|
|
|
}
|
|
|
|
return VO_TRUE;
|
|
|
|
}
|
|
|
|
case VOCTRL_GET_YUV_COLORSPACE:
|
|
|
|
*(struct mp_csp_details *)data = colorspace;
|
|
|
|
return VO_TRUE;
|
2007-02-17 21:58:55 +01:00
|
|
|
case VOCTRL_UPDATE_SCREENINFO:
|
2009-12-08 07:42:46 +01:00
|
|
|
glctx.update_xinerama_info();
|
2007-02-17 21:58:55 +01:00
|
|
|
return VO_TRUE;
|
2008-12-09 16:31:01 +01:00
|
|
|
case VOCTRL_REDRAW_OSD:
|
|
|
|
if (vo_doublebuffering)
|
|
|
|
do_render();
|
|
|
|
draw_osd();
|
2009-03-22 03:26:59 +01:00
|
|
|
if (vo_doublebuffering)
|
|
|
|
do_render_osd(2);
|
2008-12-09 16:31:01 +01:00
|
|
|
flip_page();
|
|
|
|
return VO_TRUE;
|
2002-02-09 01:47:26 +01:00
|
|
|
}
|
|
|
|
return VO_NOTIMPL;
|
2002-01-26 17:01:26 +01:00
|
|
|
}
|