~ubuntu-branches/ubuntu/precise/mplayer2/precise-proposed

« back to all changes in this revision

Viewing changes to libvo/vo_gl.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2012-01-12 22:59:30 UTC
  • mfrom: (5.1.8 sid)
  • Revision ID: package-import@ubuntu.com-20120112225930-jsg10o7na7nk73w5
Tags: 2.0-426-gc32b3ed-2
* Upload to unstable
* don't build-depend on libcdparanoia-dev on the hurd

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#include <stdlib.h>
26
26
#include <string.h>
27
27
#include <math.h>
 
28
#include <stdbool.h>
28
29
 
29
30
#include "config.h"
 
31
#include "talloc.h"
30
32
#include "mp_msg.h"
31
33
#include "subopt-helper.h"
32
34
#include "video_out.h"
33
 
#include "video_out_internal.h"
 
35
#include "libmpcodecs/vfcap.h"
 
36
#include "libmpcodecs/mp_image.h"
 
37
#include "geometry.h"
 
38
#include "osd.h"
34
39
#include "sub/font_load.h"
35
40
#include "sub/sub.h"
36
41
 
39
44
#include "fastmemcpy.h"
40
45
#include "sub/ass_mp.h"
41
46
 
42
 
#ifdef CONFIG_GL_SDL
43
 
#ifdef CONFIG_SDL_SDL_H
44
 
#include <SDL/SDL.h>
45
 
#else
46
 
#include <SDL.h>
47
 
#endif
48
 
#endif
49
 
 
50
 
static const vo_info_t info =
51
 
{
52
 
  "OpenGL",
53
 
  "gl",
54
 
  "Reimar Doeffinger <Reimar.Doeffinger@gmx.de>",
55
 
  ""
56
 
};
57
 
 
58
 
const LIBVO_EXTERN(gl)
59
 
 
60
 
 
61
 
static const vo_info_t info_nosw =
62
 
{
63
 
  "OpenGL no software rendering",
64
 
  "gl_nosw",
65
 
  "Reimar Doeffinger <Reimar.Doeffinger@gmx.de>",
66
 
  ""
67
 
};
68
 
static int preinit_nosw(const char *arg);
69
 
const struct vo_driver video_out_gl_nosw =
70
 
{
71
 
    .is_new = 0,
72
 
    .info = &info_nosw,
73
 
    .preinit = old_vo_preinit,
74
 
    .config = old_vo_config,
75
 
    .control = old_vo_control,
76
 
    .draw_slice = old_vo_draw_slice,
77
 
    .draw_osd = old_vo_draw_osd,
78
 
    .flip_page = old_vo_flip_page,
79
 
    .check_events = old_vo_check_events,
80
 
    .uninit = old_vo_uninit,
81
 
    .old_functions = &(struct vo_old_functions){
82
 
        preinit_nosw,
83
 
        config,
84
 
        control,
85
 
        draw_frame,
86
 
        draw_slice,
87
 
        draw_osd,
88
 
        flip_page,
89
 
        check_events,
90
 
        uninit,
91
 
    }
92
 
};
93
 
 
94
 
static MPGLContext glctx;
95
 
 
96
 
static int use_osd;
97
 
static int scaled_osd;
 
47
static int preinit_nosw(struct vo *vo, const char *arg);
 
48
 
98
49
//! How many parts the OSD may consist of at most
99
50
#define MAX_OSD_PARTS 20
100
 
//! Textures for OSD
101
 
static GLuint osdtex[MAX_OSD_PARTS];
102
 
#ifndef FAST_OSD
103
 
//! Alpha textures for OSD
104
 
static GLuint osdatex[MAX_OSD_PARTS];
105
 
#endif
106
 
static GLuint *eosdtex;
 
51
 
107
52
#define LARGE_EOSD_TEX_SIZE 512
108
53
#define TINYTEX_SIZE 16
109
 
#define TINYTEX_COLS (LARGE_EOSD_TEX_SIZE/TINYTEX_SIZE)
110
 
#define TINYTEX_MAX (TINYTEX_COLS*TINYTEX_COLS)
 
54
#define TINYTEX_COLS (LARGE_EOSD_TEX_SIZE / TINYTEX_SIZE)
 
55
#define TINYTEX_MAX (TINYTEX_COLS * TINYTEX_COLS)
111
56
#define SMALLTEX_SIZE 32
112
 
#define SMALLTEX_COLS (LARGE_EOSD_TEX_SIZE/SMALLTEX_SIZE)
113
 
#define SMALLTEX_MAX (SMALLTEX_COLS*SMALLTEX_COLS)
114
 
static GLuint largeeosdtex[2];
115
 
//! Display lists that draw the OSD parts
116
 
static GLuint osdDispList[MAX_OSD_PARTS];
117
 
#ifndef FAST_OSD
118
 
static GLuint osdaDispList[MAX_OSD_PARTS];
119
 
#endif
120
 
static GLuint eosdDispList;
121
 
//! How many parts the OSD currently consists of
122
 
static int osdtexCnt;
123
 
static int eosdtexCnt;
124
 
static int osd_color;
 
57
#define SMALLTEX_COLS (LARGE_EOSD_TEX_SIZE / SMALLTEX_SIZE)
 
58
#define SMALLTEX_MAX (SMALLTEX_COLS * SMALLTEX_COLS)
125
59
 
126
 
static int use_aspect;
127
 
static int use_ycbcr;
 
60
//for gl_priv.use_yuv
128
61
#define MASK_ALL_YUV (~(1 << YUV_CONVERSION_NONE))
129
62
#define MASK_NOT_COMBINERS (~((1 << YUV_CONVERSION_NONE) | (1 << YUV_CONVERSION_COMBINERS)))
130
63
#define MASK_GAMMA_SUPPORT (MASK_NOT_COMBINERS & ~(1 << YUV_CONVERSION_FRAGMENT))
131
 
static int use_yuv;
132
 
static int colorspace;
133
 
static int levelconv;
134
 
static int is_yuv;
135
 
static int lscale;
136
 
static int cscale;
137
 
static float filter_strength;
138
 
static int yuvconvtype;
139
 
static int use_rectangle;
140
 
static int err_shown;
141
 
static uint32_t image_width;
142
 
static uint32_t image_height;
143
 
static uint32_t image_format;
144
 
static int many_fmts;
145
 
static int ati_hack;
146
 
static int force_pbo;
147
 
static int mesa_buffer;
148
 
static int use_glFinish;
149
 
static int swap_interval;
150
 
static GLenum gl_target;
151
 
static GLint gl_texfmt;
152
 
static GLenum gl_format;
153
 
static GLenum gl_type;
154
 
static GLuint gl_buffer;
155
 
static GLuint gl_buffer_uv[2];
156
 
static int gl_buffersize;
157
 
static int gl_buffersize_uv;
158
 
static void *gl_bufferptr;
159
 
static void *gl_bufferptr_uv[2];
160
 
static int mesa_buffersize;
161
 
static void *mesa_bufferptr;
162
 
static GLuint fragprog;
163
 
static GLuint default_texs[22];
164
 
static char *custom_prog;
165
 
static char *custom_tex;
166
 
static int custom_tlin;
167
 
static int custom_trect;
168
 
static int mipmap_gen;
169
 
static int stereo_mode;
170
 
 
171
 
static int int_pause;
172
 
static int eq_bri = 0;
173
 
static int eq_cont = 0;
174
 
static int eq_sat = 0;
175
 
static int eq_hue = 0;
176
 
static int eq_rgamma = 0;
177
 
static int eq_ggamma = 0;
178
 
static int eq_bgamma = 0;
179
 
 
180
 
static int texture_width;
181
 
static int texture_height;
182
 
static int mpi_flipped;
183
 
static int vo_flipped;
184
 
static int ass_border_x, ass_border_y;
185
 
 
186
 
static unsigned int slice_height = 1;
187
 
 
188
 
static void redraw(void);
189
 
 
190
 
static void resize(int x,int y){
191
 
  mp_msg(MSGT_VO, MSGL_V, "[gl] Resize: %dx%d\n",x,y);
192
 
  if (WinID >= 0) {
193
 
    int left = 0, top = 0, w = x, h = y;
194
 
    geometry(&left, &top, &w, &h, vo_dwidth, vo_dheight);
195
 
    top = y - h - top;
196
 
    mpglViewport(left, top, w, h);
197
 
  } else
198
 
    mpglViewport( 0, 0, x, y );
199
 
 
200
 
  mpglMatrixMode(GL_PROJECTION);
201
 
  mpglLoadIdentity();
202
 
  ass_border_x = ass_border_y = 0;
203
 
  if (aspect_scaling() && use_aspect) {
204
 
    int new_w, new_h;
205
 
    GLdouble scale_x, scale_y;
206
 
    aspect(&new_w, &new_h, A_WINZOOM);
207
 
    panscan_calc_windowed();
208
 
    new_w += vo_panscan_x;
209
 
    new_h += vo_panscan_y;
210
 
    scale_x = (GLdouble)new_w / (GLdouble)x;
211
 
    scale_y = (GLdouble)new_h / (GLdouble)y;
212
 
    mpglScaled(scale_x, scale_y, 1);
213
 
    ass_border_x = (vo_dwidth - new_w) / 2;
214
 
    ass_border_y = (vo_dheight - new_h) / 2;
215
 
  }
216
 
  mpglOrtho(0, image_width, image_height, 0, -1,1);
217
 
 
218
 
  mpglMatrixMode(GL_MODELVIEW);
219
 
  mpglLoadIdentity();
220
 
 
221
 
  if (!scaled_osd) {
 
64
 
 
65
struct gl_priv {
 
66
    MPGLContext *glctx;
 
67
    GL *gl;
 
68
 
 
69
    int use_osd;
 
70
    int scaled_osd;
 
71
    //! Textures for OSD
 
72
    GLuint osdtex[MAX_OSD_PARTS];
 
73
#ifndef FAST_OSD
 
74
    //! Alpha textures for OSD
 
75
    GLuint osdatex[MAX_OSD_PARTS];
 
76
#endif
 
77
    GLuint *eosdtex;
 
78
    GLuint largeeosdtex[2];
 
79
    //! Display lists that draw the OSD parts
 
80
    GLuint osdDispList[MAX_OSD_PARTS];
 
81
#ifndef FAST_OSD
 
82
    GLuint osdaDispList[MAX_OSD_PARTS];
 
83
#endif
 
84
    GLuint eosdDispList;
 
85
    //! How many parts the OSD currently consists of
 
86
    int osdtexCnt;
 
87
    int eosdtexCnt;
 
88
    int osd_color;
 
89
 
 
90
    int use_ycbcr;
 
91
    int use_yuv;
 
92
    struct mp_csp_details colorspace;
 
93
    int is_yuv;
 
94
    int lscale;
 
95
    int cscale;
 
96
    float filter_strength;
 
97
    int yuvconvtype;
 
98
    int use_rectangle;
 
99
    int err_shown;
 
100
    uint32_t image_width;
 
101
    uint32_t image_height;
 
102
    uint32_t image_format;
 
103
    uint32_t image_d_width;
 
104
    uint32_t image_d_height;
 
105
    int many_fmts;
 
106
    int have_texture_rg;
 
107
    int ati_hack;
 
108
    int force_pbo;
 
109
    int use_glFinish;
 
110
    int swap_interval;
 
111
    GLenum target;
 
112
    GLint texfmt;
 
113
    GLenum gl_format;
 
114
    GLenum gl_type;
 
115
    GLuint buffer;
 
116
    GLuint buffer_uv[2];
 
117
    int buffersize;
 
118
    int buffersize_uv;
 
119
    void *bufferptr;
 
120
    void *bufferptr_uv[2];
 
121
    GLuint fragprog;
 
122
    GLuint default_texs[22];
 
123
    char *custom_prog;
 
124
    char *custom_tex;
 
125
    int custom_tlin;
 
126
    int custom_trect;
 
127
    int mipmap_gen;
 
128
    int stereo_mode;
 
129
 
 
130
    struct mp_csp_equalizer video_eq;
 
131
 
 
132
    int texture_width;
 
133
    int texture_height;
 
134
    int mpi_flipped;
 
135
    int vo_flipped;
 
136
    int ass_border_x, ass_border_y;
 
137
 
 
138
    unsigned int slice_height;
 
139
};
 
140
 
 
141
static void resize(struct vo *vo, int x, int y)
 
142
{
 
143
    struct gl_priv *p = vo->priv;
 
144
    GL *gl = p->gl;
 
145
 
 
146
    mp_msg(MSGT_VO, MSGL_V, "[gl] Resize: %dx%d\n", x, y);
 
147
    if (WinID >= 0) {
 
148
        int left = 0, top = 0, w = x, h = y;
 
149
        geometry(&left, &top, &w, &h, vo->dwidth, vo->dheight);
 
150
        top = y - h - top;
 
151
        gl->Viewport(left, top, w, h);
 
152
    } else
 
153
        gl->Viewport(0, 0, x, y);
 
154
 
 
155
    gl->MatrixMode(GL_PROJECTION);
 
156
    gl->LoadIdentity();
 
157
    p->ass_border_x = p->ass_border_y = 0;
 
158
    if (aspect_scaling()) {
 
159
        int new_w, new_h;
 
160
        GLdouble scale_x, scale_y;
 
161
        aspect(vo, &new_w, &new_h, A_WINZOOM);
 
162
        panscan_calc_windowed(vo);
 
163
        new_w += vo->panscan_x;
 
164
        new_h += vo->panscan_y;
 
165
        scale_x = (GLdouble)new_w / (GLdouble)x;
 
166
        scale_y = (GLdouble)new_h / (GLdouble)y;
 
167
        gl->Scaled(scale_x, scale_y, 1);
 
168
        p->ass_border_x = (vo->dwidth - new_w) / 2;
 
169
        p->ass_border_y = (vo->dheight - new_h) / 2;
 
170
    }
 
171
    gl->Ortho(0, p->image_width, p->image_height, 0, -1, 1);
 
172
 
 
173
    gl->MatrixMode(GL_MODELVIEW);
 
174
    gl->LoadIdentity();
 
175
 
 
176
    if (!p->scaled_osd) {
222
177
#ifdef CONFIG_FREETYPE
223
 
    // adjust font size to display size
224
 
    force_load_font = 1;
 
178
        // adjust font size to display size
 
179
        force_load_font = 1;
225
180
#endif
226
 
    vo_osd_changed(OSDTYPE_OSD);
227
 
  }
228
 
  mpglClear(GL_COLOR_BUFFER_BIT);
229
 
  redraw();
 
181
        vo_osd_changed(OSDTYPE_OSD);
 
182
    }
 
183
    gl->Clear(GL_COLOR_BUFFER_BIT);
 
184
    vo->want_redraw = true;
230
185
}
231
186
 
232
 
static void texSize(int w, int h, int *texw, int *texh) {
233
 
  if (use_rectangle) {
234
 
    *texw = w; *texh = h;
235
 
  } else {
236
 
    *texw = 32;
237
 
    while (*texw < w)
238
 
      *texw *= 2;
239
 
    *texh = 32;
240
 
    while (*texh < h)
241
 
      *texh *= 2;
242
 
  }
243
 
  if (mesa_buffer) *texw = (*texw + 63) & ~63;
244
 
  else if (ati_hack) *texw = (*texw + 511) & ~511;
 
187
static void texSize(struct vo *vo, int w, int h, int *texw, int *texh)
 
188
{
 
189
    struct gl_priv *p = vo->priv;
 
190
 
 
191
    if (p->use_rectangle) {
 
192
        *texw = w;
 
193
        *texh = h;
 
194
    } else {
 
195
        *texw = 32;
 
196
        while (*texw < w)
 
197
            *texw *= 2;
 
198
        *texh = 32;
 
199
        while (*texh < h)
 
200
            *texh *= 2;
 
201
    }
 
202
    if (p->ati_hack)
 
203
        *texw = (*texw + 511) & ~511;
245
204
}
246
205
 
247
206
//! maximum size of custom fragment program
248
207
#define MAX_CUSTOM_PROG_SIZE (1024 * 1024)
249
 
static void update_yuvconv(void) {
250
 
  int xs, ys;
251
 
  float bri = eq_bri / 100.0;
252
 
  float cont = (eq_cont + 100) / 100.0;
253
 
  float hue = eq_hue / 100.0 * 3.1415927;
254
 
  float sat = (eq_sat + 100) / 100.0;
255
 
  float rgamma = exp(log(8.0) * eq_rgamma / 100.0);
256
 
  float ggamma = exp(log(8.0) * eq_ggamma / 100.0);
257
 
  float bgamma = exp(log(8.0) * eq_bgamma / 100.0);
258
 
  gl_conversion_params_t params = {gl_target, yuvconvtype,
259
 
      {colorspace, levelconv, bri, cont, hue, sat, rgamma, ggamma, bgamma},
260
 
      texture_width, texture_height, 0, 0, filter_strength};
261
 
  mp_get_chroma_shift(image_format, &xs, &ys);
262
 
  params.chrom_texw = params.texw >> xs;
263
 
  params.chrom_texh = params.texh >> ys;
264
 
  glSetupYUVConversion(&params);
265
 
  if (custom_prog) {
266
 
    FILE *f = fopen(custom_prog, "rb");
267
 
    if (!f) {
268
 
      mp_msg(MSGT_VO, MSGL_WARN,
269
 
             "[gl] Could not read customprog %s\n", custom_prog);
270
 
    } else {
271
 
      char *prog = calloc(1, MAX_CUSTOM_PROG_SIZE + 1);
272
 
      fread(prog, 1, MAX_CUSTOM_PROG_SIZE, f);
273
 
      fclose(f);
274
 
      loadGPUProgram(GL_FRAGMENT_PROGRAM, prog);
275
 
      free(prog);
276
 
    }
277
 
    mpglProgramEnvParameter4f(GL_FRAGMENT_PROGRAM, 0,
278
 
               1.0 / texture_width, 1.0 / texture_height,
279
 
               texture_width, texture_height);
280
 
  }
281
 
  if (custom_tex) {
282
 
    FILE *f = fopen(custom_tex, "rb");
283
 
    if (!f) {
284
 
      mp_msg(MSGT_VO, MSGL_WARN,
285
 
             "[gl] Could not read customtex %s\n", custom_tex);
286
 
    } else {
287
 
      int width, height, maxval;
288
 
      mpglActiveTexture(GL_TEXTURE3);
289
 
      if (glCreatePPMTex(custom_trect?GL_TEXTURE_RECTANGLE:GL_TEXTURE_2D, 0,
290
 
                         custom_tlin?GL_LINEAR:GL_NEAREST,
291
 
                         f, &width, &height, &maxval)) {
292
 
        mpglProgramEnvParameter4f(GL_FRAGMENT_PROGRAM, 1,
293
 
                   1.0 / width, 1.0 / height, width, height);
294
 
      } else
295
 
        mp_msg(MSGT_VO, MSGL_WARN,
296
 
               "[gl] Error parsing customtex %s\n", custom_tex);
297
 
      fclose(f);
298
 
      mpglActiveTexture(GL_TEXTURE0);
299
 
    }
300
 
  }
 
208
static void update_yuvconv(struct vo *vo)
 
209
{
 
210
    struct gl_priv *p = vo->priv;
 
211
    GL *gl = p->gl;
 
212
 
 
213
    int xs, ys, depth;
 
214
    struct mp_csp_params cparams = { .colorspace = p->colorspace };
 
215
    mp_csp_copy_equalizer_values(&cparams, &p->video_eq);
 
216
    gl_conversion_params_t params = {
 
217
        p->target, p->yuvconvtype, cparams,
 
218
        p->texture_width, p->texture_height, 0, 0, p->filter_strength
 
219
    };
 
220
    mp_get_chroma_shift(p->image_format, &xs, &ys, &depth);
 
221
    params.chrom_texw = params.texw >> xs;
 
222
    params.chrom_texh = params.texh >> ys;
 
223
    params.csp_params.input_shift = -depth & 7;
 
224
    glSetupYUVConversion(gl, &params);
 
225
    if (p->custom_prog) {
 
226
        FILE *f = fopen(p->custom_prog, "rb");
 
227
        if (!f) {
 
228
            mp_msg(MSGT_VO, MSGL_WARN,
 
229
                   "[gl] Could not read customprog %s\n", p->custom_prog);
 
230
        } else {
 
231
            char *prog = calloc(1, MAX_CUSTOM_PROG_SIZE + 1);
 
232
            fread(prog, 1, MAX_CUSTOM_PROG_SIZE, f);
 
233
            fclose(f);
 
234
            loadGPUProgram(gl, GL_FRAGMENT_PROGRAM, prog);
 
235
            free(prog);
 
236
        }
 
237
        gl->ProgramEnvParameter4f(GL_FRAGMENT_PROGRAM, 0,
 
238
                                  1.0 / p->texture_width,
 
239
                                  1.0 / p->texture_height,
 
240
                                  p->texture_width, p->texture_height);
 
241
    }
 
242
    if (p->custom_tex) {
 
243
        FILE *f = fopen(p->custom_tex, "rb");
 
244
        if (!f) {
 
245
            mp_msg(MSGT_VO, MSGL_WARN,
 
246
                   "[gl] Could not read customtex %s\n", p->custom_tex);
 
247
        } else {
 
248
            int width, height, maxval;
 
249
            gl->ActiveTexture(GL_TEXTURE3);
 
250
            if (glCreatePPMTex(gl, p->custom_trect ? GL_TEXTURE_RECTANGLE : GL_TEXTURE_2D,
 
251
                               0, p->custom_tlin ? GL_LINEAR : GL_NEAREST,
 
252
                               f, &width, &height, &maxval)) {
 
253
                gl->ProgramEnvParameter4f(GL_FRAGMENT_PROGRAM, 1,
 
254
                                          1.0 / width, 1.0 / height,
 
255
                                          width, height);
 
256
            } else
 
257
                mp_msg(MSGT_VO, MSGL_WARN,
 
258
                       "[gl] Error parsing customtex %s\n", p->custom_tex);
 
259
            fclose(f);
 
260
            gl->ActiveTexture(GL_TEXTURE0);
 
261
        }
 
262
    }
301
263
}
302
264
 
303
265
/**
304
266
 * \brief remove all OSD textures and display-lists, thus clearing it.
305
267
 */
306
 
static void clearOSD(void) {
307
 
  int i;
308
 
  if (!osdtexCnt)
309
 
    return;
310
 
  mpglDeleteTextures(osdtexCnt, osdtex);
 
268
static void clearOSD(struct vo *vo)
 
269
{
 
270
    struct gl_priv *p = vo->priv;
 
271
    GL *gl = p->gl;
 
272
 
 
273
    int i;
 
274
    if (!p->osdtexCnt)
 
275
        return;
 
276
    gl->DeleteTextures(p->osdtexCnt, p->osdtex);
311
277
#ifndef FAST_OSD
312
 
  mpglDeleteTextures(osdtexCnt, osdatex);
313
 
  for (i = 0; i < osdtexCnt; i++)
314
 
    mpglDeleteLists(osdaDispList[i], 1);
 
278
    gl->DeleteTextures(p->osdtexCnt, p->osdatex);
 
279
    for (i = 0; i < p->osdtexCnt; i++)
 
280
        gl->DeleteLists(p->osdaDispList[i], 1);
315
281
#endif
316
 
  for (i = 0; i < osdtexCnt; i++)
317
 
    mpglDeleteLists(osdDispList[i], 1);
318
 
  osdtexCnt = 0;
 
282
    for (i = 0; i < p->osdtexCnt; i++)
 
283
        gl->DeleteLists(p->osdDispList[i], 1);
 
284
    p->osdtexCnt = 0;
319
285
}
320
286
 
321
287
/**
322
288
 * \brief remove textures, display list and free memory used by EOSD
323
289
 */
324
 
static void clearEOSD(void) {
325
 
  if (eosdDispList)
326
 
    mpglDeleteLists(eosdDispList, 1);
327
 
  eosdDispList = 0;
328
 
  if (eosdtexCnt)
329
 
    mpglDeleteTextures(eosdtexCnt, eosdtex);
330
 
  eosdtexCnt = 0;
331
 
  free(eosdtex);
332
 
  eosdtex = NULL;
333
 
}
334
 
 
335
 
static inline int is_tinytex(ASS_Image *i, int tinytexcur) {
336
 
  return i->w < TINYTEX_SIZE && i->h < TINYTEX_SIZE && tinytexcur < TINYTEX_MAX;
337
 
}
338
 
 
339
 
static inline int is_smalltex(ASS_Image *i, int smalltexcur) {
340
 
  return i->w < SMALLTEX_SIZE && i->h < SMALLTEX_SIZE && smalltexcur < SMALLTEX_MAX;
341
 
}
342
 
 
343
 
static inline void tinytex_pos(int tinytexcur, int *x, int *y) {
344
 
  *x = (tinytexcur % TINYTEX_COLS) * TINYTEX_SIZE;
345
 
  *y = (tinytexcur / TINYTEX_COLS) * TINYTEX_SIZE;
346
 
}
347
 
 
348
 
static inline void smalltex_pos(int smalltexcur, int *x, int *y) {
349
 
  *x = (smalltexcur % SMALLTEX_COLS) * SMALLTEX_SIZE;
350
 
  *y = (smalltexcur / SMALLTEX_COLS) * SMALLTEX_SIZE;
 
290
static void clearEOSD(struct vo *vo)
 
291
{
 
292
    struct gl_priv *p = vo->priv;
 
293
    GL *gl = p->gl;
 
294
 
 
295
    if (p->eosdDispList)
 
296
        gl->DeleteLists(p->eosdDispList, 1);
 
297
    p->eosdDispList = 0;
 
298
    if (p->eosdtexCnt)
 
299
        gl->DeleteTextures(p->eosdtexCnt, p->eosdtex);
 
300
    p->eosdtexCnt = 0;
 
301
    free(p->eosdtex);
 
302
    p->eosdtex = NULL;
 
303
}
 
304
 
 
305
static inline int is_tinytex(ASS_Image *i, int tinytexcur)
 
306
{
 
307
    return i->w < TINYTEX_SIZE && i->h < TINYTEX_SIZE
 
308
           && tinytexcur < TINYTEX_MAX;
 
309
}
 
310
 
 
311
static inline int is_smalltex(ASS_Image *i, int smalltexcur)
 
312
{
 
313
    return i->w < SMALLTEX_SIZE && i->h < SMALLTEX_SIZE
 
314
           && smalltexcur < SMALLTEX_MAX;
 
315
}
 
316
 
 
317
static inline void tinytex_pos(int tinytexcur, int *x, int *y)
 
318
{
 
319
    *x = (tinytexcur % TINYTEX_COLS) * TINYTEX_SIZE;
 
320
    *y = (tinytexcur / TINYTEX_COLS) * TINYTEX_SIZE;
 
321
}
 
322
 
 
323
static inline void smalltex_pos(int smalltexcur, int *x, int *y)
 
324
{
 
325
    *x = (smalltexcur % SMALLTEX_COLS) * SMALLTEX_SIZE;
 
326
    *y = (smalltexcur / SMALLTEX_COLS) * SMALLTEX_SIZE;
351
327
}
352
328
 
353
329
/**
355
331
 * \param img image list to create OSD from.
356
332
 *            A value of NULL has the same effect as clearEOSD()
357
333
 */
358
 
static void genEOSD(mp_eosd_images_t *imgs) {
359
 
  int sx, sy;
360
 
  int tinytexcur = 0;
361
 
  int smalltexcur = 0;
362
 
  GLuint *curtex;
363
 
  GLint scale_type = scaled_osd ? GL_LINEAR : GL_NEAREST;
364
 
  ASS_Image *img = imgs->imgs;
365
 
  ASS_Image *i;
366
 
 
367
 
  if (imgs->changed == 0) // there are elements, but they are unchanged
368
 
      return;
369
 
  if (img && imgs->changed == 1) // there are elements, but they just moved
370
 
      goto skip_upload;
371
 
 
372
 
  clearEOSD();
373
 
  if (!img)
374
 
    return;
375
 
  if (!largeeosdtex[0]) {
376
 
    mpglGenTextures(2, largeeosdtex);
377
 
    mpglBindTexture(gl_target, largeeosdtex[0]);
378
 
    glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, LARGE_EOSD_TEX_SIZE, LARGE_EOSD_TEX_SIZE, 0);
379
 
    mpglBindTexture(gl_target, largeeosdtex[1]);
380
 
    glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, LARGE_EOSD_TEX_SIZE, LARGE_EOSD_TEX_SIZE, 0);
381
 
  }
382
 
  for (i = img; i; i = i->next)
383
 
  {
384
 
    if (i->w <= 0 || i->h <= 0 || i->stride < i->w)
385
 
      continue;
386
 
    if (is_tinytex(i, tinytexcur))
387
 
      tinytexcur++;
388
 
    else if (is_smalltex(i, smalltexcur))
389
 
      smalltexcur++;
390
 
    else
391
 
      eosdtexCnt++;
392
 
  }
393
 
  mp_msg(MSGT_VO, MSGL_DBG2, "EOSD counts (tiny, small, all): %i, %i, %i\n",
394
 
         tinytexcur, smalltexcur, eosdtexCnt);
395
 
  if (eosdtexCnt) {
396
 
    eosdtex = calloc(eosdtexCnt, sizeof(GLuint));
397
 
    mpglGenTextures(eosdtexCnt, eosdtex);
398
 
  }
399
 
  tinytexcur = smalltexcur = 0;
400
 
  for (i = img, curtex = eosdtex; i; i = i->next) {
401
 
    int x = 0, y = 0;
402
 
    if (i->w <= 0 || i->h <= 0 || i->stride < i->w) {
403
 
      mp_msg(MSGT_VO, MSGL_V, "Invalid dimensions OSD for part!\n");
404
 
      continue;
405
 
    }
406
 
    if (is_tinytex(i, tinytexcur)) {
407
 
      tinytex_pos(tinytexcur, &x, &y);
408
 
      mpglBindTexture(gl_target, largeeosdtex[0]);
409
 
      tinytexcur++;
410
 
    } else if (is_smalltex(i, smalltexcur)) {
411
 
      smalltex_pos(smalltexcur, &x, &y);
412
 
      mpglBindTexture(gl_target, largeeosdtex[1]);
413
 
      smalltexcur++;
414
 
    } else {
415
 
      texSize(i->w, i->h, &sx, &sy);
416
 
      mpglBindTexture(gl_target, *curtex++);
417
 
      glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, sx, sy, 0);
418
 
    }
419
 
    glUploadTex(gl_target, GL_ALPHA, GL_UNSIGNED_BYTE, i->bitmap, i->stride,
420
 
                x, y, i->w, i->h, 0);
421
 
  }
422
 
  eosdDispList = mpglGenLists(1);
 
334
static void genEOSD(struct vo *vo, mp_eosd_images_t *imgs)
 
335
{
 
336
    struct gl_priv *p = vo->priv;
 
337
    GL *gl = p->gl;
 
338
 
 
339
    int sx, sy;
 
340
    int tinytexcur = 0;
 
341
    int smalltexcur = 0;
 
342
    GLuint *curtex;
 
343
    GLint scale_type = p->scaled_osd ? GL_LINEAR : GL_NEAREST;
 
344
    ASS_Image *img = imgs->imgs;
 
345
    ASS_Image *i;
 
346
 
 
347
    if (imgs->changed == 0) // there are elements, but they are unchanged
 
348
        return;
 
349
    if (img && imgs->changed == 1) // there are elements, but they just moved
 
350
        goto skip_upload;
 
351
 
 
352
    clearEOSD(vo);
 
353
    if (!img)
 
354
        return;
 
355
    if (!p->largeeosdtex[0]) {
 
356
        gl->GenTextures(2, p->largeeosdtex);
 
357
        for (int n = 0; n < 2; n++) {
 
358
            gl->BindTexture(p->target, p->largeeosdtex[n]);
 
359
            glCreateClearTex(gl, p->target, GL_ALPHA, GL_ALPHA,
 
360
                             GL_UNSIGNED_BYTE, scale_type,
 
361
                             LARGE_EOSD_TEX_SIZE, LARGE_EOSD_TEX_SIZE, 0);
 
362
        }
 
363
    }
 
364
    for (i = img; i; i = i->next) {
 
365
        if (i->w <= 0 || i->h <= 0 || i->stride < i->w)
 
366
            continue;
 
367
        if (is_tinytex(i, tinytexcur))
 
368
            tinytexcur++;
 
369
        else if (is_smalltex(i, smalltexcur))
 
370
            smalltexcur++;
 
371
        else
 
372
            p->eosdtexCnt++;
 
373
    }
 
374
    mp_msg(MSGT_VO, MSGL_DBG2, "EOSD counts (tiny, small, all): %i, %i, %i\n",
 
375
           tinytexcur, smalltexcur, p->eosdtexCnt);
 
376
    if (p->eosdtexCnt) {
 
377
        p->eosdtex = calloc(p->eosdtexCnt, sizeof(GLuint));
 
378
        gl->GenTextures(p->eosdtexCnt, p->eosdtex);
 
379
    }
 
380
    tinytexcur = smalltexcur = 0;
 
381
    for (i = img, curtex = p->eosdtex; i; i = i->next) {
 
382
        int x = 0, y = 0;
 
383
        if (i->w <= 0 || i->h <= 0 || i->stride < i->w) {
 
384
            mp_msg(MSGT_VO, MSGL_V, "Invalid dimensions OSD for part!\n");
 
385
            continue;
 
386
        }
 
387
        if (is_tinytex(i, tinytexcur)) {
 
388
            tinytex_pos(tinytexcur, &x, &y);
 
389
            gl->BindTexture(p->target, p->largeeosdtex[0]);
 
390
            tinytexcur++;
 
391
        } else if (is_smalltex(i, smalltexcur)) {
 
392
            smalltex_pos(smalltexcur, &x, &y);
 
393
            gl->BindTexture(p->target, p->largeeosdtex[1]);
 
394
            smalltexcur++;
 
395
        } else {
 
396
            texSize(vo, i->w, i->h, &sx, &sy);
 
397
            gl->BindTexture(p->target, *curtex++);
 
398
            glCreateClearTex(gl, p->target, GL_ALPHA, GL_ALPHA,
 
399
                             GL_UNSIGNED_BYTE, scale_type, sx, sy, 0);
 
400
        }
 
401
        glUploadTex(gl, p->target, GL_ALPHA, GL_UNSIGNED_BYTE, i->bitmap,
 
402
                    i->stride, x, y, i->w, i->h, 0);
 
403
    }
 
404
    p->eosdDispList = gl->GenLists(1);
423
405
skip_upload:
424
 
  mpglNewList(eosdDispList, GL_COMPILE);
425
 
  tinytexcur = smalltexcur = 0;
426
 
  for (i = img, curtex = eosdtex; i; i = i->next) {
427
 
    int x = 0, y = 0;
428
 
    if (i->w <= 0 || i->h <= 0 || i->stride < i->w)
429
 
      continue;
430
 
    mpglColor4ub(i->color >> 24, (i->color >> 16) & 0xff, (i->color >> 8) & 0xff, 255 - (i->color & 0xff));
431
 
    if (is_tinytex(i, tinytexcur)) {
432
 
      tinytex_pos(tinytexcur, &x, &y);
433
 
      sx = sy = LARGE_EOSD_TEX_SIZE;
434
 
      mpglBindTexture(gl_target, largeeosdtex[0]);
435
 
      tinytexcur++;
436
 
    } else if (is_smalltex(i, smalltexcur)) {
437
 
      smalltex_pos(smalltexcur, &x, &y);
438
 
      sx = sy = LARGE_EOSD_TEX_SIZE;
439
 
      mpglBindTexture(gl_target, largeeosdtex[1]);
440
 
      smalltexcur++;
441
 
    } else {
442
 
      texSize(i->w, i->h, &sx, &sy);
443
 
      mpglBindTexture(gl_target, *curtex++);
 
406
    gl->NewList(p->eosdDispList, GL_COMPILE);
 
407
    tinytexcur = smalltexcur = 0;
 
408
    for (i = img, curtex = p->eosdtex; i; i = i->next) {
 
409
        int x = 0, y = 0;
 
410
        if (i->w <= 0 || i->h <= 0 || i->stride < i->w)
 
411
            continue;
 
412
        gl->Color4ub(i->color >> 24, (i->color >> 16) & 0xff,
 
413
                     (i->color >> 8) & 0xff, 255 - (i->color & 0xff));
 
414
        if (is_tinytex(i, tinytexcur)) {
 
415
            tinytex_pos(tinytexcur, &x, &y);
 
416
            sx = sy = LARGE_EOSD_TEX_SIZE;
 
417
            gl->BindTexture(p->target, p->largeeosdtex[0]);
 
418
            tinytexcur++;
 
419
        } else if (is_smalltex(i, smalltexcur)) {
 
420
            smalltex_pos(smalltexcur, &x, &y);
 
421
            sx = sy = LARGE_EOSD_TEX_SIZE;
 
422
            gl->BindTexture(p->target, p->largeeosdtex[1]);
 
423
            smalltexcur++;
 
424
        } else {
 
425
            texSize(vo, i->w, i->h, &sx, &sy);
 
426
            gl->BindTexture(p->target, *curtex++);
 
427
        }
 
428
        glDrawTex(gl, i->dst_x, i->dst_y, i->w, i->h, x, y, i->w, i->h, sx, sy,
 
429
                  p->use_rectangle == 1, 0, 0);
444
430
    }
445
 
    glDrawTex(i->dst_x, i->dst_y, i->w, i->h, x, y, i->w, i->h, sx, sy, use_rectangle == 1, 0, 0);
446
 
  }
447
 
  mpglEndList();
448
 
  mpglBindTexture(gl_target, 0);
 
431
    gl->EndList();
 
432
    gl->BindTexture(p->target, 0);
449
433
}
450
434
 
451
435
/**
452
436
 * \brief uninitialize OpenGL context, freeing textures, buffers etc.
453
437
 */
454
 
static void uninitGl(void) {
455
 
  int i = 0;
456
 
  if (mpglDeletePrograms && fragprog)
457
 
    mpglDeletePrograms(1, &fragprog);
458
 
  fragprog = 0;
459
 
  while (default_texs[i] != 0)
460
 
    i++;
461
 
  if (i)
462
 
    mpglDeleteTextures(i, default_texs);
463
 
  default_texs[0] = 0;
464
 
  clearOSD();
465
 
  clearEOSD();
466
 
  if (largeeosdtex[0])
467
 
    mpglDeleteTextures(2, largeeosdtex);
468
 
  largeeosdtex[0] = 0;
469
 
  if (mpglDeleteBuffers && gl_buffer)
470
 
    mpglDeleteBuffers(1, &gl_buffer);
471
 
  gl_buffer = 0; gl_buffersize = 0;
472
 
  gl_bufferptr = NULL;
473
 
  if (mpglDeleteBuffers && gl_buffer_uv[0])
474
 
    mpglDeleteBuffers(2, gl_buffer_uv);
475
 
  gl_buffer_uv[0] = gl_buffer_uv[1] = 0; gl_buffersize_uv = 0;
476
 
  gl_bufferptr_uv[0] = gl_bufferptr_uv[1] = 0;
477
 
#ifdef CONFIG_GL_X11
478
 
  if (mesa_bufferptr)
479
 
    mpglFreeMemoryMESA(mDisplay, mScreen, mesa_bufferptr);
480
 
#endif
481
 
  mesa_bufferptr = NULL;
482
 
  err_shown = 0;
483
 
}
484
 
 
485
 
static int isSoftwareGl(void)
486
 
{
487
 
  const char *renderer = mpglGetString(GL_RENDERER);
488
 
  return !renderer || strcmp(renderer, "Software Rasterizer") == 0 ||
489
 
         strstr(renderer, "llvmpipe");
490
 
}
491
 
 
492
 
static void autodetectGlExtensions(void) {
493
 
  const char *extensions = mpglGetString(GL_EXTENSIONS);
494
 
  const char *vendor     = mpglGetString(GL_VENDOR);
495
 
  const char *version    = mpglGetString(GL_VERSION);
496
 
  const char *renderer   = mpglGetString(GL_RENDERER);
497
 
  int is_ati = vendor && strstr(vendor, "ATI") != NULL;
498
 
  int ati_broken_pbo = 0;
499
 
  mp_msg(MSGT_VO, MSGL_V, "[gl] Running on OpenGL '%s' by '%s', version '%s'\n", renderer, vendor, version);
500
 
  if (is_ati && strncmp(version, "2.1.", 4) == 0) {
501
 
    int ver = atoi(version + 4);
502
 
    mp_msg(MSGT_VO, MSGL_V, "[gl] Detected ATI driver version: %i\n", ver);
503
 
    ati_broken_pbo = ver && ver < 8395;
504
 
  }
505
 
  if (ati_hack      == -1) ati_hack      = ati_broken_pbo;
506
 
  if (force_pbo     == -1) {
507
 
    force_pbo = 0;
508
 
    if (extensions && strstr(extensions, "_pixel_buffer_object"))
509
 
      force_pbo = is_ati;
510
 
  }
511
 
  if (use_rectangle == -1) {
512
 
    use_rectangle = 0;
513
 
    if (extensions) {
 
438
static void uninitGl(struct vo *vo)
 
439
{
 
440
    struct gl_priv *p = vo->priv;
 
441
    GL *gl = p->gl;
 
442
 
 
443
    int i = 0;
 
444
    if (gl->DeletePrograms && p->fragprog)
 
445
        gl->DeletePrograms(1, &p->fragprog);
 
446
    p->fragprog = 0;
 
447
    while (p->default_texs[i] != 0)
 
448
        i++;
 
449
    if (i)
 
450
        gl->DeleteTextures(i, p->default_texs);
 
451
    p->default_texs[0] = 0;
 
452
    clearOSD(vo);
 
453
    clearEOSD(vo);
 
454
    if (p->largeeosdtex[0])
 
455
        gl->DeleteTextures(2, p->largeeosdtex);
 
456
    p->largeeosdtex[0] = 0;
 
457
    if (gl->DeleteBuffers && p->buffer)
 
458
        gl->DeleteBuffers(1, &p->buffer);
 
459
    p->buffer = 0;
 
460
    p->buffersize = 0;
 
461
    p->bufferptr = NULL;
 
462
    if (gl->DeleteBuffers && p->buffer_uv[0])
 
463
        gl->DeleteBuffers(2, p->buffer_uv);
 
464
    p->buffer_uv[0] = p->buffer_uv[1] = 0;
 
465
    p->buffersize_uv = 0;
 
466
    p->bufferptr_uv[0] = p->bufferptr_uv[1] = 0;
 
467
    p->err_shown = 0;
 
468
}
 
469
 
 
470
static int isSoftwareGl(struct vo *vo)
 
471
{
 
472
    struct gl_priv *p = vo->priv;
 
473
    const char *renderer = p->gl->GetString(GL_RENDERER);
 
474
    return !renderer || strcmp(renderer, "Software Rasterizer") == 0 ||
 
475
           strstr(renderer, "llvmpipe");
 
476
}
 
477
 
 
478
static void autodetectGlExtensions(struct vo *vo)
 
479
{
 
480
    struct gl_priv *p = vo->priv;
 
481
    GL *gl = p->gl;
 
482
 
 
483
    const char *extensions = gl->GetString(GL_EXTENSIONS);
 
484
    const char *vendor     = gl->GetString(GL_VENDOR);
 
485
    const char *version    = gl->GetString(GL_VERSION);
 
486
    const char *renderer   = gl->GetString(GL_RENDERER);
 
487
    int is_ati = vendor && strstr(vendor, "ATI") != NULL;
 
488
    int ati_broken_pbo = 0;
 
489
    mp_msg(MSGT_VO, MSGL_V, "[gl] Running on OpenGL '%s' by '%s', version '%s'\n",
 
490
           renderer, vendor, version);
 
491
    if (is_ati && strncmp(version, "2.1.", 4) == 0) {
 
492
        int ver = atoi(version + 4);
 
493
        mp_msg(MSGT_VO, MSGL_V, "[gl] Detected ATI driver version: %i\n", ver);
 
494
        ati_broken_pbo = ver && ver < 8395;
 
495
    }
 
496
    if (p->ati_hack == -1)
 
497
        p->ati_hack = ati_broken_pbo;
 
498
    if (p->force_pbo == -1) {
 
499
        p->force_pbo = 0;
 
500
        if (extensions && strstr(extensions, "_pixel_buffer_object"))
 
501
            p->force_pbo = is_ati;
 
502
    }
 
503
    p->have_texture_rg = extensions && strstr(extensions, "GL_ARB_texture_rg");
 
504
    if (p->use_rectangle == -1) {
 
505
        p->use_rectangle = 0;
 
506
        if (extensions) {
514
507
//      if (strstr(extensions, "_texture_non_power_of_two"))
515
 
      if (strstr(extensions, "_texture_rectangle"))
516
 
        use_rectangle = renderer && strstr(renderer, "Mesa DRI R200") ? 1 : 0;
517
 
    }
518
 
  }
519
 
  if (use_osd == -1)
520
 
    use_osd = mpglBindTexture != NULL;
521
 
  if (use_yuv == -1)
522
 
    use_yuv = glAutodetectYUVConversion();
523
 
  if (is_ati && (lscale == 1 || lscale == 2 || cscale == 1 || cscale == 2))
524
 
    mp_msg(MSGT_VO, MSGL_WARN, "[gl] Selected scaling mode may be broken on ATI cards.\n"
525
 
             "Tell _them_ to fix GL_REPEAT if you have issues.\n");
526
 
  mp_msg(MSGT_VO, MSGL_V, "[gl] Settings after autodetection: ati-hack = %i, force-pbo = %i, rectangle = %i, yuv = %i\n",
527
 
         ati_hack, force_pbo, use_rectangle, use_yuv);
528
 
}
529
 
 
530
 
static GLint get_scale_type(int chroma) {
531
 
  int nearest = (chroma ? cscale : lscale) & 64;
532
 
  if (nearest)
533
 
    return mipmap_gen ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
534
 
  return mipmap_gen ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
 
508
            if (strstr(extensions, "_texture_rectangle"))
 
509
                p->use_rectangle = renderer
 
510
                    && strstr(renderer, "Mesa DRI R200") ? 1 : 0;
 
511
        }
 
512
    }
 
513
    if (p->use_osd == -1)
 
514
        p->use_osd = gl->BindTexture != NULL;
 
515
    if (p->use_yuv == -1)
 
516
        p->use_yuv = glAutodetectYUVConversion(gl);
 
517
 
 
518
    int eq_caps = 0;
 
519
    int yuv_mask = (1 << p->use_yuv);
 
520
    if (!(yuv_mask & MASK_NOT_COMBINERS)) {
 
521
        // combiners
 
522
        eq_caps = (1 << MP_CSP_EQ_HUE) | (1 << MP_CSP_EQ_SATURATION);
 
523
    } else if (yuv_mask & MASK_ALL_YUV) {
 
524
        eq_caps = MP_CSP_EQ_CAPS_COLORMATRIX;
 
525
        if (yuv_mask & MASK_GAMMA_SUPPORT)
 
526
            eq_caps |= MP_CSP_EQ_CAPS_GAMMA;
 
527
    }
 
528
    p->video_eq.capabilities = eq_caps;
 
529
 
 
530
    if (is_ati && (p->lscale == 1 || p->lscale == 2 || p->cscale == 1 || p->cscale == 2))
 
531
        mp_msg(MSGT_VO, MSGL_WARN, "[gl] Selected scaling mode may be broken on"
 
532
               " ATI cards.\n"
 
533
               "Tell _them_ to fix GL_REPEAT if you have issues.\n");
 
534
    mp_msg(MSGT_VO, MSGL_V, "[gl] Settings after autodetection: ati-hack = %i, "
 
535
           "force-pbo = %i, rectangle = %i, yuv = %i\n",
 
536
           p->ati_hack, p->force_pbo, p->use_rectangle, p->use_yuv);
 
537
}
 
538
 
 
539
static GLint get_scale_type(struct vo *vo, int chroma)
 
540
{
 
541
    struct gl_priv *p = vo->priv;
 
542
 
 
543
    int nearest = (chroma ? p->cscale : p->lscale) & 64;
 
544
    if (nearest)
 
545
        return p->mipmap_gen ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
 
546
    return p->mipmap_gen ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
 
547
}
 
548
 
 
549
// Return the high byte of the value that represents white in chroma (U/V)
 
550
static int get_chroma_clear_val(int bit_depth)
 
551
{
 
552
    return 1 << (bit_depth - 1 & 7);
535
553
}
536
554
 
537
555
/**
538
556
 * \brief Initialize a (new or reused) OpenGL context.
539
557
 * set global gl-related variables to their default values
540
558
 */
541
 
static int initGl(uint32_t d_width, uint32_t d_height) {
542
 
  GLint scale_type = get_scale_type(0);
543
 
  autodetectGlExtensions();
544
 
  gl_target = use_rectangle == 1 ? GL_TEXTURE_RECTANGLE : GL_TEXTURE_2D;
545
 
  yuvconvtype = SET_YUV_CONVERSION(use_yuv) |
546
 
                SET_YUV_LUM_SCALER(lscale) |
547
 
                SET_YUV_CHROM_SCALER(cscale);
548
 
 
549
 
  texSize(image_width, image_height, &texture_width, &texture_height);
550
 
 
551
 
  mpglDisable(GL_BLEND);
552
 
  mpglDisable(GL_DEPTH_TEST);
553
 
  mpglDepthMask(GL_FALSE);
554
 
  mpglDisable(GL_CULL_FACE);
555
 
  mpglEnable(gl_target);
556
 
  mpglDrawBuffer(vo_doublebuffering?GL_BACK:GL_FRONT);
557
 
  mpglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
558
 
 
559
 
  mp_msg(MSGT_VO, MSGL_V, "[gl] Creating %dx%d texture...\n",
560
 
          texture_width, texture_height);
561
 
 
562
 
  glCreateClearTex(gl_target, gl_texfmt, gl_format, gl_type, scale_type,
563
 
                   texture_width, texture_height, 0);
564
 
  if (mipmap_gen)
565
 
    mpglTexParameteri(gl_target, GL_GENERATE_MIPMAP, GL_TRUE);
566
 
 
567
 
  if (is_yuv) {
568
 
    int i;
 
559
static int initGl(struct vo *vo, uint32_t d_width, uint32_t d_height)
 
560
{
 
561
    struct gl_priv *p = vo->priv;
 
562
    GL *gl = p->gl;
 
563
 
 
564
    GLint scale_type = get_scale_type(vo, 0);
 
565
    autodetectGlExtensions(vo);
 
566
    p->target = p->use_rectangle == 1 ? GL_TEXTURE_RECTANGLE : GL_TEXTURE_2D;
 
567
    p->yuvconvtype = SET_YUV_CONVERSION(p->use_yuv) |
 
568
                     SET_YUV_LUM_SCALER(p->lscale) |
 
569
                     SET_YUV_CHROM_SCALER(p->cscale);
 
570
 
 
571
    texSize(vo, p->image_width, p->image_height,
 
572
            &p->texture_width, &p->texture_height);
 
573
 
 
574
    gl->Disable(GL_BLEND);
 
575
    gl->Disable(GL_DEPTH_TEST);
 
576
    gl->DepthMask(GL_FALSE);
 
577
    gl->Disable(GL_CULL_FACE);
 
578
    gl->Enable(p->target);
 
579
    gl->DrawBuffer(vo_doublebuffering ? GL_BACK : GL_FRONT);
 
580
    gl->TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 
581
 
 
582
    mp_msg(MSGT_VO, MSGL_V, "[gl] Creating %dx%d texture...\n",
 
583
           p->texture_width, p->texture_height);
 
584
 
 
585
    glCreateClearTex(gl, p->target, p->texfmt, p->gl_format,
 
586
                     p->gl_type, scale_type,
 
587
                     p->texture_width, p->texture_height, 0);
 
588
 
 
589
    if (p->mipmap_gen)
 
590
        gl->TexParameteri(p->target, GL_GENERATE_MIPMAP, GL_TRUE);
 
591
 
 
592
    if (p->is_yuv) {
 
593
        int i;
 
594
        int xs, ys, depth;
 
595
        scale_type = get_scale_type(vo, 1);
 
596
        mp_get_chroma_shift(p->image_format, &xs, &ys, &depth);
 
597
        int clear = get_chroma_clear_val(depth);
 
598
        gl->GenTextures(21, p->default_texs);
 
599
        p->default_texs[21] = 0;
 
600
        for (i = 0; i < 7; i++) {
 
601
            gl->ActiveTexture(GL_TEXTURE1 + i);
 
602
            gl->BindTexture(GL_TEXTURE_2D, p->default_texs[i]);
 
603
            gl->BindTexture(GL_TEXTURE_RECTANGLE, p->default_texs[i + 7]);
 
604
            gl->BindTexture(GL_TEXTURE_3D, p->default_texs[i + 14]);
 
605
        }
 
606
        gl->ActiveTexture(GL_TEXTURE1);
 
607
        glCreateClearTex(gl, p->target, p->texfmt, p->gl_format,
 
608
                         p->gl_type, scale_type,
 
609
                         p->texture_width >> xs, p->texture_height >> ys,
 
610
                         clear);
 
611
        if (p->mipmap_gen)
 
612
            gl->TexParameteri(p->target, GL_GENERATE_MIPMAP, GL_TRUE);
 
613
        gl->ActiveTexture(GL_TEXTURE2);
 
614
        glCreateClearTex(gl, p->target, p->texfmt, p->gl_format,
 
615
                         p->gl_type, scale_type,
 
616
                         p->texture_width >> xs, p->texture_height >> ys,
 
617
                         clear);
 
618
        if (p->mipmap_gen)
 
619
            gl->TexParameteri(p->target, GL_GENERATE_MIPMAP, GL_TRUE);
 
620
        gl->ActiveTexture(GL_TEXTURE0);
 
621
        gl->BindTexture(p->target, 0);
 
622
    }
 
623
    if (p->is_yuv || p->custom_prog) {
 
624
        if ((MASK_NOT_COMBINERS & (1 << p->use_yuv)) || p->custom_prog) {
 
625
            if (!gl->GenPrograms || !gl->BindProgram)
 
626
                mp_msg(MSGT_VO, MSGL_ERR,
 
627
                       "[gl] fragment program functions missing!\n");
 
628
            else {
 
629
                gl->GenPrograms(1, &p->fragprog);
 
630
                gl->BindProgram(GL_FRAGMENT_PROGRAM, p->fragprog);
 
631
            }
 
632
        }
 
633
        update_yuvconv(vo);
 
634
    }
 
635
 
 
636
    resize(vo, d_width, d_height);
 
637
 
 
638
    gl->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
639
    gl->Clear(GL_COLOR_BUFFER_BIT);
 
640
    if (gl->SwapInterval && p->swap_interval >= 0)
 
641
        gl->SwapInterval(p->swap_interval);
 
642
    return 1;
 
643
}
 
644
 
 
645
static int create_window(struct vo *vo, uint32_t d_width, uint32_t d_height,
 
646
                         uint32_t flags)
 
647
{
 
648
    struct gl_priv *p = vo->priv;
 
649
 
 
650
    if (p->stereo_mode == GL_3D_QUADBUFFER)
 
651
        flags |= VOFLAG_STEREO;
 
652
 
 
653
    return p->glctx->create_window(p->glctx, d_width, d_height, flags);
 
654
}
 
655
 
 
656
static int config(struct vo *vo, uint32_t width, uint32_t height,
 
657
                  uint32_t d_width, uint32_t d_height, uint32_t flags,
 
658
                  uint32_t format)
 
659
{
 
660
    struct gl_priv *p = vo->priv;
 
661
 
569
662
    int xs, ys;
570
 
    scale_type = get_scale_type(1);
571
 
    mp_get_chroma_shift(image_format, &xs, &ys);
572
 
    mpglGenTextures(21, default_texs);
573
 
    default_texs[21] = 0;
574
 
    for (i = 0; i < 7; i++) {
575
 
      mpglActiveTexture(GL_TEXTURE1 + i);
576
 
      mpglBindTexture(GL_TEXTURE_2D, default_texs[i]);
577
 
      mpglBindTexture(GL_TEXTURE_RECTANGLE, default_texs[i + 7]);
578
 
      mpglBindTexture(GL_TEXTURE_3D, default_texs[i + 14]);
579
 
    }
580
 
    mpglActiveTexture(GL_TEXTURE1);
581
 
    glCreateClearTex(gl_target, gl_texfmt, gl_format, gl_type, scale_type,
582
 
                     texture_width >> xs, texture_height >> ys, 128);
583
 
    if (mipmap_gen)
584
 
      mpglTexParameteri(gl_target, GL_GENERATE_MIPMAP, GL_TRUE);
585
 
    mpglActiveTexture(GL_TEXTURE2);
586
 
    glCreateClearTex(gl_target, gl_texfmt, gl_format, gl_type, scale_type,
587
 
                     texture_width >> xs, texture_height >> ys, 128);
588
 
    if (mipmap_gen)
589
 
      mpglTexParameteri(gl_target, GL_GENERATE_MIPMAP, GL_TRUE);
590
 
    mpglActiveTexture(GL_TEXTURE0);
591
 
    mpglBindTexture(gl_target, 0);
592
 
  }
593
 
  if (is_yuv || custom_prog)
594
 
  {
595
 
    if ((MASK_NOT_COMBINERS & (1 << use_yuv)) || custom_prog) {
596
 
      if (!mpglGenPrograms || !mpglBindProgram) {
597
 
        mp_msg(MSGT_VO, MSGL_ERR, "[gl] fragment program functions missing!\n");
598
 
      } else {
599
 
        mpglGenPrograms(1, &fragprog);
600
 
        mpglBindProgram(GL_FRAGMENT_PROGRAM, fragprog);
601
 
      }
602
 
    }
603
 
    update_yuvconv();
604
 
  }
605
 
 
606
 
  resize(d_width, d_height);
607
 
 
608
 
  mpglClearColor( 0.0f,0.0f,0.0f,0.0f );
609
 
  mpglClear( GL_COLOR_BUFFER_BIT );
610
 
  if (mpglSwapInterval && swap_interval >= 0)
611
 
    mpglSwapInterval(swap_interval);
612
 
  return 1;
613
 
}
614
 
 
615
 
static int create_window(uint32_t d_width, uint32_t d_height, uint32_t flags, const char *title)
616
 
{
617
 
  if (stereo_mode == GL_3D_QUADBUFFER)
618
 
    flags |= VOFLAG_STEREO;
619
 
#ifdef CONFIG_GL_WIN32
620
 
  if (glctx.type == GLTYPE_W32 && !vo_w32_config(d_width, d_height, flags))
621
 
    return -1;
622
 
#endif
623
 
#ifdef CONFIG_GL_X11
624
 
  if (glctx.type == GLTYPE_X11) {
625
 
    static int default_glx_attribs[] = {
626
 
      GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
627
 
      GLX_DOUBLEBUFFER, None
628
 
    };
629
 
    static int stereo_glx_attribs[]  = {
630
 
      GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
631
 
      GLX_DOUBLEBUFFER, GLX_STEREO, None
632
 
    };
633
 
    XVisualInfo *vinfo = NULL;
634
 
    if (stereo_mode == GL_3D_QUADBUFFER) {
635
 
      vinfo = glXChooseVisual(mDisplay, mScreen, stereo_glx_attribs);
636
 
      if (!vinfo)
637
 
        mp_msg(MSGT_VO, MSGL_ERR, "[gl] Could not find a stereo visual, "
638
 
                                  "3D will probably not work!\n");
639
 
    }
640
 
    if (!vinfo)
641
 
      vinfo = glXChooseVisual(mDisplay, mScreen, default_glx_attribs);
642
 
    if (!vinfo) {
643
 
      mp_msg(MSGT_VO, MSGL_ERR, "[gl] no GLX support present\n");
644
 
      return -1;
645
 
    }
646
 
    mp_msg(MSGT_VO, MSGL_V, "[gl] GLX chose visual with ID 0x%x\n", (int)vinfo->visualid);
647
 
 
648
 
    vo_x11_create_vo_window(vinfo, vo_dx, vo_dy, d_width, d_height, flags,
649
 
            XCreateColormap(mDisplay, mRootWin, vinfo->visual, AllocNone),
650
 
            "gl", title);
651
 
  }
652
 
#endif
653
 
#ifdef CONFIG_GL_SDL
654
 
  if (glctx.type == GLTYPE_SDL) {
655
 
    SDL_WM_SetCaption(title, NULL);
656
 
    vo_dwidth  = d_width;
657
 
    vo_dheight = d_height;
658
 
  }
659
 
#endif
660
 
  return 0;
661
 
}
662
 
 
663
 
/* connect to server, create and map window,
664
 
 * allocate colors and (shared) memory
665
 
 */
666
 
static int
667
 
config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format)
668
 
{
669
 
  int xs, ys;
670
 
  image_height = height;
671
 
  image_width = width;
672
 
  image_format = format;
673
 
  is_yuv = mp_get_chroma_shift(image_format, &xs, &ys) > 0;
674
 
  is_yuv |= (xs << 8) | (ys << 16);
675
 
  glFindFormat(format, NULL, &gl_texfmt, &gl_format, &gl_type);
676
 
 
677
 
  vo_flipped = !!(flags & VOFLAG_FLIPPING);
678
 
 
679
 
  if (create_window(d_width, d_height, flags, title) < 0)
680
 
    return -1;
681
 
 
682
 
  if (vo_config_count)
683
 
    uninitGl();
684
 
  if (glctx.setGlWindow(&glctx) == SET_WINDOW_FAILED)
685
 
    return -1;
686
 
  if (mesa_buffer && !mpglAllocateMemoryMESA) {
687
 
    mp_msg(MSGT_VO, MSGL_ERR, "Can not enable mesa-buffer because AllocateMemoryMESA was not found\n");
688
 
    mesa_buffer = 0;
689
 
  }
690
 
  initGl(vo_dwidth, vo_dheight);
691
 
 
692
 
  return 0;
693
 
}
694
 
 
695
 
static void check_events(void)
696
 
{
697
 
    int e=glctx.check_events();
698
 
    if(e&VO_EVENT_REINIT) {
699
 
        uninitGl();
700
 
        initGl(vo_dwidth, vo_dheight);
701
 
    }
702
 
    if(e&VO_EVENT_RESIZE) resize(vo_dwidth,vo_dheight);
703
 
    if(e&VO_EVENT_EXPOSE && int_pause) redraw();
 
663
    p->image_height = height;
 
664
    p->image_width = width;
 
665
    p->image_format = format;
 
666
    p->image_d_width = d_width;
 
667
    p->image_d_height = d_height;
 
668
    p->is_yuv = mp_get_chroma_shift(p->image_format, &xs, &ys, NULL) > 0;
 
669
    p->is_yuv |= (xs << 8) | (ys << 16);
 
670
    glFindFormat(format, p->have_texture_rg, NULL, &p->texfmt, &p->gl_format,
 
671
                 &p->gl_type);
 
672
 
 
673
    p->vo_flipped = !!(flags & VOFLAG_FLIPPING);
 
674
 
 
675
    if (create_window(vo, d_width, d_height, flags) < 0)
 
676
        return -1;
 
677
 
 
678
    if (vo->config_count)
 
679
        uninitGl(vo);
 
680
    if (p->glctx->setGlWindow(p->glctx) == SET_WINDOW_FAILED)
 
681
        return -1;
 
682
    initGl(vo, vo->dwidth, vo->dheight);
 
683
 
 
684
    return 0;
 
685
}
 
686
 
 
687
static void check_events(struct vo *vo)
 
688
{
 
689
    struct gl_priv *p = vo->priv;
 
690
 
 
691
    int e = p->glctx->check_events(vo);
 
692
    if (e & VO_EVENT_REINIT) {
 
693
        uninitGl(vo);
 
694
        initGl(vo, vo->dwidth, vo->dheight);
 
695
    }
 
696
    if (e & VO_EVENT_RESIZE)
 
697
        resize(vo, vo->dwidth, vo->dheight);
 
698
    if (e & VO_EVENT_EXPOSE)
 
699
        vo->want_redraw = true;
704
700
}
705
701
 
706
702
/**
707
703
 * Creates the textures and the display list needed for displaying
708
704
 * an OSD part.
709
 
 * Callback function for vo_draw_text().
 
705
 * Callback function for osd_draw_text_ext().
710
706
 */
711
 
static void create_osd_texture(int x0, int y0, int w, int h,
712
 
                                 unsigned char *src, unsigned char *srca,
713
 
                                 int stride)
 
707
static void create_osd_texture(void *ctx, int x0, int y0, int w, int h,
 
708
                               unsigned char *src, unsigned char *srca,
 
709
                               int stride)
714
710
{
715
 
  // initialize to 8 to avoid special-casing on alignment
716
 
  int sx = 8, sy = 8;
717
 
  GLint scale_type = scaled_osd ? GL_LINEAR : GL_NEAREST;
718
 
 
719
 
  if (w <= 0 || h <= 0 || stride < w) {
720
 
    mp_msg(MSGT_VO, MSGL_V, "Invalid dimensions OSD for part!\n");
721
 
    return;
722
 
  }
723
 
  texSize(w, h, &sx, &sy);
724
 
 
725
 
  if (osdtexCnt >= MAX_OSD_PARTS) {
726
 
    mp_msg(MSGT_VO, MSGL_ERR, "Too many OSD parts, contact the developers!\n");
727
 
    return;
728
 
  }
729
 
 
730
 
  // create Textures for OSD part
731
 
  mpglGenTextures(1, &osdtex[osdtexCnt]);
732
 
  mpglBindTexture(gl_target, osdtex[osdtexCnt]);
733
 
  glCreateClearTex(gl_target, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, scale_type, sx, sy, 0);
734
 
  glUploadTex(gl_target, GL_LUMINANCE, GL_UNSIGNED_BYTE, src, stride,
735
 
              0, 0, w, h, 0);
736
 
 
737
 
#ifndef FAST_OSD
738
 
  mpglGenTextures(1, &osdatex[osdtexCnt]);
739
 
  mpglBindTexture(gl_target, osdatex[osdtexCnt]);
740
 
  glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, sx, sy, 0);
741
 
  {
742
 
  int i;
743
 
  char *tmp = malloc(stride * h);
744
 
  // convert alpha from weird MPlayer scale.
745
 
  // in-place is not possible since it is reused for future OSDs
746
 
  for (i = h * stride - 1; i >= 0; i--)
747
 
    tmp[i] = -srca[i];
748
 
  glUploadTex(gl_target, GL_ALPHA, GL_UNSIGNED_BYTE, tmp, stride,
749
 
              0, 0, w, h, 0);
750
 
  free(tmp);
751
 
  }
752
 
#endif
753
 
 
754
 
  mpglBindTexture(gl_target, 0);
755
 
 
756
 
  // Create a list for rendering this OSD part
757
 
#ifndef FAST_OSD
758
 
  osdaDispList[osdtexCnt] = mpglGenLists(1);
759
 
  mpglNewList(osdaDispList[osdtexCnt], GL_COMPILE);
760
 
  // render alpha
761
 
  mpglBindTexture(gl_target, osdatex[osdtexCnt]);
762
 
  glDrawTex(x0, y0, w, h, 0, 0, w, h, sx, sy, use_rectangle == 1, 0, 0);
763
 
  mpglEndList();
764
 
#endif
765
 
  osdDispList[osdtexCnt] = mpglGenLists(1);
766
 
  mpglNewList(osdDispList[osdtexCnt], GL_COMPILE);
767
 
  // render OSD
768
 
  mpglBindTexture(gl_target, osdtex[osdtexCnt]);
769
 
  glDrawTex(x0, y0, w, h, 0, 0, w, h, sx, sy, use_rectangle == 1, 0, 0);
770
 
  mpglEndList();
771
 
 
772
 
  osdtexCnt++;
 
711
    struct vo *vo = ctx;
 
712
    struct gl_priv *p = vo->priv;
 
713
    GL *gl = p->gl;
 
714
 
 
715
    // initialize to 8 to avoid special-casing on alignment
 
716
    int sx = 8, sy = 8;
 
717
    GLint scale_type = p->scaled_osd ? GL_LINEAR : GL_NEAREST;
 
718
 
 
719
    if (w <= 0 || h <= 0 || stride < w) {
 
720
        mp_msg(MSGT_VO, MSGL_V, "Invalid dimensions OSD for part!\n");
 
721
        return;
 
722
    }
 
723
    texSize(vo, w, h, &sx, &sy);
 
724
 
 
725
    if (p->osdtexCnt >= MAX_OSD_PARTS) {
 
726
        mp_msg(MSGT_VO, MSGL_ERR, "Too many OSD parts, contact the developers!\n");
 
727
        return;
 
728
    }
 
729
 
 
730
    // create Textures for OSD part
 
731
    gl->GenTextures(1, &p->osdtex[p->osdtexCnt]);
 
732
    gl->BindTexture(p->target, p->osdtex[p->osdtexCnt]);
 
733
    glCreateClearTex(gl, p->target, GL_LUMINANCE, GL_LUMINANCE,
 
734
                     GL_UNSIGNED_BYTE, scale_type, sx, sy, 0);
 
735
    glUploadTex(gl, p->target, GL_LUMINANCE, GL_UNSIGNED_BYTE, src, stride,
 
736
                0, 0, w, h, 0);
 
737
 
 
738
#ifndef FAST_OSD
 
739
    gl->GenTextures(1, &p->osdatex[p->osdtexCnt]);
 
740
    gl->BindTexture(p->target, p->osdatex[p->osdtexCnt]);
 
741
    glCreateClearTex(gl, p->target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE,
 
742
                     scale_type, sx, sy, 0);
 
743
    {
 
744
        int i;
 
745
        char *tmp = malloc(stride * h);
 
746
        // convert alpha from weird MPlayer scale.
 
747
        // in-place is not possible since it is reused for future OSDs
 
748
        for (i = h * stride - 1; i >= 0; i--)
 
749
            tmp[i] = -srca[i];
 
750
        glUploadTex(gl, p->target, GL_ALPHA, GL_UNSIGNED_BYTE, tmp, stride,
 
751
                    0, 0, w, h, 0);
 
752
        free(tmp);
 
753
    }
 
754
#endif
 
755
 
 
756
    gl->BindTexture(p->target, 0);
 
757
 
 
758
    // Create a list for rendering this OSD part
 
759
#ifndef FAST_OSD
 
760
    p->osdaDispList[p->osdtexCnt] = gl->GenLists(1);
 
761
    gl->NewList(p->osdaDispList[p->osdtexCnt], GL_COMPILE);
 
762
    // render alpha
 
763
    gl->BindTexture(p->target, p->osdatex[p->osdtexCnt]);
 
764
    glDrawTex(gl, x0, y0, w, h, 0, 0, w, h, sx, sy, p->use_rectangle == 1, 0, 0);
 
765
    gl->EndList();
 
766
#endif
 
767
    p->osdDispList[p->osdtexCnt] = gl->GenLists(1);
 
768
    gl->NewList(p->osdDispList[p->osdtexCnt], GL_COMPILE);
 
769
    // render OSD
 
770
    gl->BindTexture(p->target, p->osdtex[p->osdtexCnt]);
 
771
    glDrawTex(gl, x0, y0, w, h, 0, 0, w, h, sx, sy, p->use_rectangle == 1, 0, 0);
 
772
    gl->EndList();
 
773
 
 
774
    p->osdtexCnt++;
773
775
}
774
776
 
775
777
#define RENDER_OSD  1
778
780
/**
779
781
 * \param type bit 0: render OSD, bit 1: render EOSD
780
782
 */
781
 
static void do_render_osd(int type) {
782
 
  int draw_osd  = (type & RENDER_OSD)  && osdtexCnt > 0;
783
 
  int draw_eosd = (type & RENDER_EOSD) && eosdDispList;
784
 
  if (!draw_osd && !draw_eosd)
785
 
    return;
786
 
  // set special rendering parameters
787
 
  if (!scaled_osd) {
788
 
    mpglMatrixMode(GL_PROJECTION);
789
 
    mpglPushMatrix();
790
 
    mpglLoadIdentity();
791
 
    mpglOrtho(0, vo_dwidth, vo_dheight, 0, -1, 1);
792
 
  }
793
 
  mpglEnable(GL_BLEND);
794
 
  if (draw_eosd) {
795
 
    mpglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
796
 
    mpglCallList(eosdDispList);
797
 
  }
798
 
  if (draw_osd) {
799
 
    mpglColor4ub((osd_color >> 16) & 0xff, (osd_color >> 8) & 0xff, osd_color & 0xff, 0xff - (osd_color >> 24));
800
 
    // draw OSD
 
783
static void do_render_osd(struct vo *vo, int type)
 
784
{
 
785
    struct gl_priv *p = vo->priv;
 
786
    GL *gl = p->gl;
 
787
 
 
788
    int draw_osd  = (type & RENDER_OSD) && p->osdtexCnt > 0;
 
789
    int draw_eosd = (type & RENDER_EOSD) && p->eosdDispList;
 
790
    if (!draw_osd && !draw_eosd)
 
791
        return;
 
792
    // set special rendering parameters
 
793
    if (!p->scaled_osd) {
 
794
        gl->MatrixMode(GL_PROJECTION);
 
795
        gl->PushMatrix();
 
796
        gl->LoadIdentity();
 
797
        gl->Ortho(0, vo->dwidth, vo->dheight, 0, -1, 1);
 
798
    }
 
799
    gl->Enable(GL_BLEND);
 
800
    if (draw_eosd) {
 
801
        gl->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
802
        gl->CallList(p->eosdDispList);
 
803
    }
 
804
    if (draw_osd) {
 
805
        gl->Color4ub((p->osd_color >> 16) & 0xff, (p->osd_color >> 8) & 0xff,
 
806
                     p->osd_color & 0xff, 0xff - (p->osd_color >> 24));
 
807
        // draw OSD
801
808
#ifndef FAST_OSD
802
 
    mpglBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
803
 
    mpglCallLists(osdtexCnt, GL_UNSIGNED_INT, osdaDispList);
 
809
        gl->BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
 
810
        gl->CallLists(p->osdtexCnt, GL_UNSIGNED_INT, p->osdaDispList);
804
811
#endif
805
 
    mpglBlendFunc(GL_SRC_ALPHA, GL_ONE);
806
 
    mpglCallLists(osdtexCnt, GL_UNSIGNED_INT, osdDispList);
807
 
  }
808
 
  // set rendering parameters back to defaults
809
 
  mpglDisable(GL_BLEND);
810
 
  if (!scaled_osd)
811
 
    mpglPopMatrix();
812
 
  mpglBindTexture(gl_target, 0);
813
 
}
814
 
 
815
 
static void draw_osd(void)
816
 
{
817
 
  if (!use_osd) return;
818
 
  if (vo_osd_changed(0)) {
819
 
    int osd_h, osd_w;
820
 
    clearOSD();
821
 
    osd_w = scaled_osd ? image_width : vo_dwidth;
822
 
    osd_h = scaled_osd ? image_height : vo_dheight;
823
 
    vo_draw_text_ext(osd_w, osd_h, ass_border_x, ass_border_y, ass_border_x, ass_border_y,
824
 
                     image_width, image_height, create_osd_texture);
825
 
  }
826
 
  if (vo_doublebuffering) do_render_osd(RENDER_OSD);
827
 
}
828
 
 
829
 
static void do_render(void) {
 
812
        gl->BlendFunc(GL_SRC_ALPHA, GL_ONE);
 
813
        gl->CallLists(p->osdtexCnt, GL_UNSIGNED_INT, p->osdDispList);
 
814
    }
 
815
    // set rendering parameters back to defaults
 
816
    gl->Disable(GL_BLEND);
 
817
    if (!p->scaled_osd)
 
818
        gl->PopMatrix();
 
819
    gl->BindTexture(p->target, 0);
 
820
}
 
821
 
 
822
static void draw_osd(struct vo *vo, struct osd_state *osd)
 
823
{
 
824
    struct gl_priv *p = vo->priv;
 
825
 
 
826
    if (!p->use_osd)
 
827
        return;
 
828
    if (vo_osd_changed(0)) {
 
829
        int osd_h, osd_w;
 
830
        clearOSD(vo);
 
831
        osd_w = p->scaled_osd ? p->image_width : vo->dwidth;
 
832
        osd_h = p->scaled_osd ? p->image_height : vo->dheight;
 
833
        osd_draw_text_ext(osd, osd_w, osd_h, p->ass_border_x,
 
834
                          p->ass_border_y, p->ass_border_x,
 
835
                          p->ass_border_y, p->image_width,
 
836
                          p->image_height, create_osd_texture, vo);
 
837
    }
 
838
    if (vo_doublebuffering)
 
839
        do_render_osd(vo, RENDER_OSD);
 
840
}
 
841
 
 
842
static void do_render(struct vo *vo)
 
843
{
 
844
    struct gl_priv *p = vo->priv;
 
845
    GL *gl = p->gl;
 
846
 
830
847
//  Enable(GL_TEXTURE_2D);
831
848
//  BindTexture(GL_TEXTURE_2D, texture_id);
832
849
 
833
 
  mpglColor3f(1,1,1);
834
 
  if (is_yuv || custom_prog)
835
 
    glEnableYUVConversion(gl_target, yuvconvtype);
836
 
  if (stereo_mode) {
837
 
    glEnable3DLeft(stereo_mode);
838
 
    glDrawTex(0, 0, image_width, image_height,
839
 
              0, 0, image_width >> 1, image_height,
840
 
              texture_width, texture_height,
841
 
              use_rectangle == 1, is_yuv,
842
 
              mpi_flipped ^ vo_flipped);
843
 
    glEnable3DRight(stereo_mode);
844
 
    glDrawTex(0, 0, image_width, image_height,
845
 
              image_width >> 1, 0, image_width >> 1, image_height,
846
 
              texture_width, texture_height,
847
 
              use_rectangle == 1, is_yuv,
848
 
              mpi_flipped ^ vo_flipped);
849
 
    glDisable3D(stereo_mode);
850
 
  } else {
851
 
    glDrawTex(0, 0, image_width, image_height,
852
 
              0, 0, image_width, image_height,
853
 
              texture_width, texture_height,
854
 
              use_rectangle == 1, is_yuv,
855
 
              mpi_flipped ^ vo_flipped);
856
 
  }
857
 
  if (is_yuv || custom_prog)
858
 
    glDisableYUVConversion(gl_target, yuvconvtype);
859
 
}
860
 
 
861
 
static void flip_page(void) {
862
 
  if (vo_doublebuffering) {
863
 
    if (use_glFinish) mpglFinish();
864
 
    glctx.swapGlBuffers(&glctx);
865
 
    if (aspect_scaling() && use_aspect)
866
 
      mpglClear(GL_COLOR_BUFFER_BIT);
867
 
  } else {
868
 
    do_render();
869
 
    do_render_osd(RENDER_OSD | RENDER_EOSD);
870
 
    if (use_glFinish) mpglFinish();
871
 
    else mpglFlush();
872
 
  }
873
 
}
874
 
 
875
 
static void redraw(void) {
876
 
  if (vo_doublebuffering) { do_render(); do_render_osd(RENDER_OSD | RENDER_EOSD); }
877
 
  flip_page();
878
 
}
879
 
 
880
 
static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y)
881
 
{
882
 
  mpi_flipped = stride[0] < 0;
883
 
  glUploadTex(gl_target, gl_format, gl_type, src[0], stride[0],
884
 
              x, y, w, h, slice_height);
885
 
  if (is_yuv) {
886
 
    int xs, ys;
887
 
    mp_get_chroma_shift(image_format, &xs, &ys);
888
 
    mpglActiveTexture(GL_TEXTURE1);
889
 
    glUploadTex(gl_target, gl_format, gl_type, src[1], stride[1],
890
 
                x >> xs, y >> ys, w >> xs, h >> ys, slice_height);
891
 
    mpglActiveTexture(GL_TEXTURE2);
892
 
    glUploadTex(gl_target, gl_format, gl_type, src[2], stride[2],
893
 
                x >> xs, y >> ys, w >> xs, h >> ys, slice_height);
894
 
    mpglActiveTexture(GL_TEXTURE0);
895
 
  }
896
 
  return 0;
897
 
}
898
 
 
899
 
static uint32_t get_image(mp_image_t *mpi) {
900
 
  int needed_size;
901
 
  if (!mpglGenBuffers || !mpglBindBuffer || !mpglBufferData || !mpglMapBuffer) {
902
 
    if (!err_shown)
903
 
      mp_msg(MSGT_VO, MSGL_ERR, "[gl] extensions missing for dr\n"
904
 
                                "Expect a _major_ speed penalty\n");
905
 
    err_shown = 1;
906
 
    return VO_FALSE;
907
 
  }
908
 
  if (mpi->flags & MP_IMGFLAG_READABLE) return VO_FALSE;
909
 
  if (mpi->type != MP_IMGTYPE_STATIC && mpi->type != MP_IMGTYPE_TEMP &&
910
 
      (mpi->type != MP_IMGTYPE_NUMBERED || mpi->number))
911
 
    return VO_FALSE;
912
 
  if (mesa_buffer) mpi->width = texture_width;
913
 
  else if (ati_hack) {
914
 
    mpi->width = texture_width;
915
 
    mpi->height = texture_height;
916
 
  }
917
 
  mpi->stride[0] = mpi->width * mpi->bpp / 8;
918
 
  needed_size = mpi->stride[0] * mpi->height;
919
 
  if (mesa_buffer) {
920
 
#ifdef CONFIG_GL_X11
921
 
    if (mesa_bufferptr && needed_size > mesa_buffersize) {
922
 
      mpglFreeMemoryMESA(mDisplay, mScreen, mesa_bufferptr);
923
 
      mesa_bufferptr = NULL;
924
 
    }
925
 
    if (!mesa_bufferptr)
926
 
      mesa_bufferptr = mpglAllocateMemoryMESA(mDisplay, mScreen, needed_size, 0, 1.0, 1.0);
927
 
    mesa_buffersize = needed_size;
928
 
#endif
929
 
    mpi->planes[0] = mesa_bufferptr;
930
 
  } else {
931
 
    if (!gl_buffer)
932
 
      mpglGenBuffers(1, &gl_buffer);
933
 
    mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer);
934
 
    if (needed_size > gl_buffersize) {
935
 
      gl_buffersize = needed_size;
936
 
      mpglBufferData(GL_PIXEL_UNPACK_BUFFER, gl_buffersize,
937
 
                     NULL, GL_DYNAMIC_DRAW);
938
 
    }
939
 
    if (!gl_bufferptr)
940
 
      gl_bufferptr = mpglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
941
 
    mpi->planes[0] = gl_bufferptr;
942
 
    mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
943
 
  }
944
 
  if (!mpi->planes[0]) {
945
 
    if (!err_shown)
946
 
      mp_msg(MSGT_VO, MSGL_ERR, "[gl] could not acquire buffer for dr\n"
947
 
                                "Expect a _major_ speed penalty\n");
948
 
    err_shown = 1;
949
 
    return VO_FALSE;
950
 
  }
951
 
  if (is_yuv) {
952
 
    // planar YUV
953
 
    int xs, ys;
954
 
    mp_get_chroma_shift(image_format, &xs, &ys);
955
 
    mpi->flags |= MP_IMGFLAG_COMMON_STRIDE | MP_IMGFLAG_COMMON_PLANE;
956
 
    mpi->stride[0] = mpi->width;
957
 
    mpi->planes[1] = mpi->planes[0] + mpi->stride[0] * mpi->height;
958
 
    mpi->stride[1] = mpi->width >> xs;
959
 
    mpi->planes[2] = mpi->planes[1] + mpi->stride[1] * (mpi->height >> ys);
960
 
    mpi->stride[2] = mpi->width >> xs;
961
 
    if (ati_hack && !mesa_buffer) {
962
 
      mpi->flags &= ~MP_IMGFLAG_COMMON_PLANE;
963
 
      if (!gl_buffer_uv[0]) mpglGenBuffers(2, gl_buffer_uv);
964
 
      if (mpi->stride[1] * mpi->height > gl_buffersize_uv) {
965
 
        mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer_uv[0]);
966
 
        mpglBufferData(GL_PIXEL_UNPACK_BUFFER, mpi->stride[1] * mpi->height,
967
 
                       NULL, GL_DYNAMIC_DRAW);
968
 
        mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer_uv[1]);
969
 
        mpglBufferData(GL_PIXEL_UNPACK_BUFFER, mpi->stride[1] * mpi->height,
970
 
                       NULL, GL_DYNAMIC_DRAW);
971
 
        gl_buffersize_uv = mpi->stride[1] * mpi->height;
972
 
      }
973
 
      if (!gl_bufferptr_uv[0]) {
974
 
        mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer_uv[0]);
975
 
        gl_bufferptr_uv[0] = mpglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
976
 
        mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer_uv[1]);
977
 
        gl_bufferptr_uv[1] = mpglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
978
 
      }
979
 
      mpi->planes[1] = gl_bufferptr_uv[0];
980
 
      mpi->planes[2] = gl_bufferptr_uv[1];
981
 
    }
982
 
  }
983
 
  mpi->flags |= MP_IMGFLAG_DIRECT;
984
 
  return VO_TRUE;
985
 
}
986
 
 
987
 
static void clear_border(uint8_t *dst, int start, int stride, int height, int full_height, int value) {
988
 
  int right_border = stride - start;
989
 
  int bottom_border = full_height - height;
990
 
  while (height > 0) {
991
 
    memset(dst + start, value, right_border);
992
 
    dst += stride;
993
 
    height--;
994
 
  }
995
 
  if (bottom_border > 0)
996
 
    memset(dst, value, stride * bottom_border);
997
 
}
998
 
 
999
 
static uint32_t draw_image(mp_image_t *mpi) {
1000
 
  int slice = slice_height;
1001
 
  int stride[3];
1002
 
  unsigned char *planes[3];
1003
 
  mp_image_t mpi2 = *mpi;
1004
 
  int w = mpi->w, h = mpi->h;
1005
 
  if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
1006
 
    goto skip_upload;
1007
 
  mpi2.flags = 0; mpi2.type = MP_IMGTYPE_TEMP;
1008
 
  mpi2.width = mpi2.w; mpi2.height = mpi2.h;
1009
 
  if (force_pbo && !(mpi->flags & MP_IMGFLAG_DIRECT) && !gl_bufferptr && get_image(&mpi2) == VO_TRUE) {
1010
 
    int bpp = is_yuv ? 8 : mpi->bpp;
1011
 
    int xs, ys;
1012
 
    mp_get_chroma_shift(image_format, &xs, &ys);
1013
 
    memcpy_pic(mpi2.planes[0], mpi->planes[0], mpi->w * bpp / 8, mpi->h, mpi2.stride[0], mpi->stride[0]);
1014
 
    if (is_yuv) {
1015
 
      memcpy_pic(mpi2.planes[1], mpi->planes[1], mpi->w >> xs, mpi->h >> ys, mpi2.stride[1], mpi->stride[1]);
1016
 
      memcpy_pic(mpi2.planes[2], mpi->planes[2], mpi->w >> xs, mpi->h >> ys, mpi2.stride[2], mpi->stride[2]);
1017
 
    }
1018
 
    if (ati_hack) { // since we have to do a full upload we need to clear the borders
1019
 
      clear_border(mpi2.planes[0], mpi->w * bpp / 8, mpi2.stride[0], mpi->h, mpi2.height, 0);
1020
 
      if (is_yuv) {
1021
 
        clear_border(mpi2.planes[1], mpi->w >> xs, mpi2.stride[1], mpi->h >> ys, mpi2.height >> ys, 128);
1022
 
        clear_border(mpi2.planes[2], mpi->w >> xs, mpi2.stride[2], mpi->h >> ys, mpi2.height >> ys, 128);
1023
 
      }
1024
 
    }
1025
 
    mpi = &mpi2;
1026
 
  }
1027
 
  stride[0] = mpi->stride[0]; stride[1] = mpi->stride[1]; stride[2] = mpi->stride[2];
1028
 
  planes[0] = mpi->planes[0]; planes[1] = mpi->planes[1]; planes[2] = mpi->planes[2];
1029
 
  mpi_flipped = stride[0] < 0;
1030
 
  if (mpi->flags & MP_IMGFLAG_DIRECT) {
1031
 
    if (mesa_buffer) {
1032
 
      mpglPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, 1);
1033
 
      w = texture_width;
1034
 
    } else {
1035
 
      intptr_t base = (intptr_t)planes[0];
1036
 
      if (ati_hack) { w = texture_width; h = texture_height; }
1037
 
      if (mpi_flipped)
1038
 
        base += (mpi->h - 1) * stride[0];
1039
 
      planes[0] -= base;
1040
 
      planes[1] -= base;
1041
 
      planes[2] -= base;
1042
 
      mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer);
1043
 
      mpglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
1044
 
      gl_bufferptr = NULL;
1045
 
      if (!(mpi->flags & MP_IMGFLAG_COMMON_PLANE))
1046
 
        planes[0] = planes[1] = planes[2] = NULL;
1047
 
    }
1048
 
    slice = 0; // always "upload" full texture
1049
 
  }
1050
 
  glUploadTex(gl_target, gl_format, gl_type, planes[0], stride[0],
1051
 
              mpi->x, mpi->y, w, h, slice);
1052
 
  if (is_yuv) {
1053
 
    int xs, ys;
1054
 
    mp_get_chroma_shift(image_format, &xs, &ys);
1055
 
    if ((mpi->flags & MP_IMGFLAG_DIRECT) && !(mpi->flags & MP_IMGFLAG_COMMON_PLANE)) {
1056
 
      mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer_uv[0]);
1057
 
      mpglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
1058
 
      gl_bufferptr_uv[0] = NULL;
1059
 
    }
1060
 
    mpglActiveTexture(GL_TEXTURE1);
1061
 
    glUploadTex(gl_target, gl_format, gl_type, planes[1], stride[1],
1062
 
                mpi->x >> xs, mpi->y >> ys, w >> xs, h >> ys, slice);
1063
 
    if ((mpi->flags & MP_IMGFLAG_DIRECT) && !(mpi->flags & MP_IMGFLAG_COMMON_PLANE)) {
1064
 
      mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_buffer_uv[1]);
1065
 
      mpglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
1066
 
      gl_bufferptr_uv[1] = NULL;
1067
 
    }
1068
 
    mpglActiveTexture(GL_TEXTURE2);
1069
 
    glUploadTex(gl_target, gl_format, gl_type, planes[2], stride[2],
1070
 
                mpi->x >> xs, mpi->y >> ys, w >> xs, h >> ys, slice);
1071
 
    mpglActiveTexture(GL_TEXTURE0);
1072
 
  }
1073
 
  if (mpi->flags & MP_IMGFLAG_DIRECT) {
1074
 
    if (mesa_buffer) mpglPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, 0);
1075
 
    else mpglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
1076
 
  }
 
850
    gl->Color3f(1, 1, 1);
 
851
    if (p->is_yuv || p->custom_prog)
 
852
        glEnableYUVConversion(gl, p->target, p->yuvconvtype);
 
853
    if (p->stereo_mode) {
 
854
        glEnable3DLeft(gl, p->stereo_mode);
 
855
        glDrawTex(gl, 0, 0, p->image_width, p->image_height,
 
856
                  0, 0, p->image_width >> 1, p->image_height,
 
857
                  p->texture_width, p->texture_height,
 
858
                  p->use_rectangle == 1, p->is_yuv,
 
859
                  p->mpi_flipped ^ p->vo_flipped);
 
860
        glEnable3DRight(gl, p->stereo_mode);
 
861
        glDrawTex(gl, 0, 0, p->image_width, p->image_height,
 
862
                  p->image_width >> 1, 0, p->image_width >> 1,
 
863
                  p->image_height, p->texture_width, p->texture_height,
 
864
                  p->use_rectangle == 1, p->is_yuv,
 
865
                  p->mpi_flipped ^ p->vo_flipped);
 
866
        glDisable3D(gl, p->stereo_mode);
 
867
    } else {
 
868
        glDrawTex(gl, 0, 0, p->image_width, p->image_height,
 
869
                  0, 0, p->image_width, p->image_height,
 
870
                  p->texture_width, p->texture_height,
 
871
                  p->use_rectangle == 1, p->is_yuv,
 
872
                  p->mpi_flipped ^ p->vo_flipped);
 
873
    }
 
874
    if (p->is_yuv || p->custom_prog)
 
875
        glDisableYUVConversion(gl, p->target, p->yuvconvtype);
 
876
}
 
877
 
 
878
static void flip_page(struct vo *vo)
 
879
{
 
880
    struct gl_priv *p = vo->priv;
 
881
    GL *gl = p->gl;
 
882
 
 
883
    if (vo_doublebuffering) {
 
884
        if (p->use_glFinish)
 
885
            gl->Finish();
 
886
        p->glctx->swapGlBuffers(p->glctx);
 
887
        if (aspect_scaling())
 
888
            gl->Clear(GL_COLOR_BUFFER_BIT);
 
889
    } else {
 
890
        do_render(vo);
 
891
        do_render_osd(vo, RENDER_OSD | RENDER_EOSD);
 
892
        if (p->use_glFinish)
 
893
            gl->Finish();
 
894
        else
 
895
            gl->Flush();
 
896
    }
 
897
}
 
898
 
 
899
static int draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h,
 
900
                      int x, int y)
 
901
{
 
902
    struct gl_priv *p = vo->priv;
 
903
    GL *gl = p->gl;
 
904
 
 
905
    p->mpi_flipped = stride[0] < 0;
 
906
    glUploadTex(gl, p->target, p->gl_format, p->gl_type, src[0], stride[0],
 
907
                x, y, w, h, p->slice_height);
 
908
    if (p->is_yuv) {
 
909
        int xs, ys;
 
910
        mp_get_chroma_shift(p->image_format, &xs, &ys, NULL);
 
911
        gl->ActiveTexture(GL_TEXTURE1);
 
912
        glUploadTex(gl, p->target, p->gl_format, p->gl_type, src[1], stride[1],
 
913
                    x >> xs, y >> ys, w >> xs, h >> ys, p->slice_height);
 
914
        gl->ActiveTexture(GL_TEXTURE2);
 
915
        glUploadTex(gl, p->target, p->gl_format, p->gl_type, src[2], stride[2],
 
916
                    x >> xs, y >> ys, w >> xs, h >> ys, p->slice_height);
 
917
        gl->ActiveTexture(GL_TEXTURE0);
 
918
    }
 
919
    return 0;
 
920
}
 
921
 
 
922
static uint32_t get_image(struct vo *vo, mp_image_t *mpi)
 
923
{
 
924
    struct gl_priv *p = vo->priv;
 
925
    GL *gl = p->gl;
 
926
 
 
927
    int needed_size;
 
928
    if (!gl->GenBuffers || !gl->BindBuffer || !gl->BufferData || !gl->MapBuffer) {
 
929
        if (!p->err_shown)
 
930
            mp_msg(MSGT_VO, MSGL_ERR, "[gl] extensions missing for dr\n"
 
931
                   "Expect a _major_ speed penalty\n");
 
932
        p->err_shown = 1;
 
933
        return VO_FALSE;
 
934
    }
 
935
    if (mpi->flags & MP_IMGFLAG_READABLE)
 
936
        return VO_FALSE;
 
937
    if (mpi->type != MP_IMGTYPE_STATIC && mpi->type != MP_IMGTYPE_TEMP &&
 
938
        (mpi->type != MP_IMGTYPE_NUMBERED || mpi->number))
 
939
        return VO_FALSE;
 
940
    if (p->ati_hack) {
 
941
        mpi->width = p->texture_width;
 
942
        mpi->height = p->texture_height;
 
943
    }
 
944
    mpi->stride[0] = mpi->width * mpi->bpp / 8;
 
945
    needed_size = mpi->stride[0] * mpi->height;
 
946
    if (!p->buffer)
 
947
        gl->GenBuffers(1, &p->buffer);
 
948
    gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer);
 
949
    if (needed_size > p->buffersize) {
 
950
        p->buffersize = needed_size;
 
951
        gl->BufferData(GL_PIXEL_UNPACK_BUFFER, p->buffersize,
 
952
                        NULL, GL_DYNAMIC_DRAW);
 
953
    }
 
954
    if (!p->bufferptr)
 
955
        p->bufferptr = gl->MapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
 
956
    mpi->planes[0] = p->bufferptr;
 
957
    gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
 
958
    if (!mpi->planes[0]) {
 
959
        if (!p->err_shown)
 
960
            mp_msg(MSGT_VO, MSGL_ERR, "[gl] could not acquire buffer for dr\n"
 
961
                   "Expect a _major_ speed penalty\n");
 
962
        p->err_shown = 1;
 
963
        return VO_FALSE;
 
964
    }
 
965
    if (p->is_yuv) {
 
966
        // planar YUV
 
967
        int xs, ys, component_bits;
 
968
        mp_get_chroma_shift(p->image_format, &xs, &ys, &component_bits);
 
969
        int bp = (component_bits + 7) / 8;
 
970
        mpi->flags |= MP_IMGFLAG_COMMON_STRIDE | MP_IMGFLAG_COMMON_PLANE;
 
971
        mpi->stride[0] = mpi->width * bp;
 
972
        mpi->planes[1] = mpi->planes[0] + mpi->stride[0] * mpi->height;
 
973
        mpi->stride[1] = (mpi->width >> xs) * bp;
 
974
        mpi->planes[2] = mpi->planes[1] + mpi->stride[1] * (mpi->height >> ys);
 
975
        mpi->stride[2] = (mpi->width >> xs) * bp;
 
976
        if (p->ati_hack) {
 
977
            mpi->flags &= ~MP_IMGFLAG_COMMON_PLANE;
 
978
            if (!p->buffer_uv[0])
 
979
                gl->GenBuffers(2, p->buffer_uv);
 
980
            int buffer_size = mpi->stride[1] * mpi->height;
 
981
            if (buffer_size > p->buffersize_uv) {
 
982
                gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer_uv[0]);
 
983
                gl->BufferData(GL_PIXEL_UNPACK_BUFFER, buffer_size, NULL,
 
984
                               GL_DYNAMIC_DRAW);
 
985
                gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer_uv[1]);
 
986
                gl->BufferData(GL_PIXEL_UNPACK_BUFFER, buffer_size, NULL,
 
987
                               GL_DYNAMIC_DRAW);
 
988
                p->buffersize_uv = buffer_size;
 
989
            }
 
990
            if (!p->bufferptr_uv[0]) {
 
991
                gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer_uv[0]);
 
992
                p->bufferptr_uv[0] = gl->MapBuffer(GL_PIXEL_UNPACK_BUFFER,
 
993
                                                   GL_WRITE_ONLY);
 
994
                gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer_uv[1]);
 
995
                p->bufferptr_uv[1] = gl->MapBuffer(GL_PIXEL_UNPACK_BUFFER,
 
996
                                                   GL_WRITE_ONLY);
 
997
            }
 
998
            mpi->planes[1] = p->bufferptr_uv[0];
 
999
            mpi->planes[2] = p->bufferptr_uv[1];
 
1000
        }
 
1001
    }
 
1002
    mpi->flags |= MP_IMGFLAG_DIRECT;
 
1003
    return VO_TRUE;
 
1004
}
 
1005
 
 
1006
static void clear_border(struct vo *vo, uint8_t *dst, int start, int stride,
 
1007
                         int height, int full_height, int value)
 
1008
{
 
1009
    int right_border = stride - start;
 
1010
    int bottom_border = full_height - height;
 
1011
    while (height > 0) {
 
1012
        if (right_border > 0)
 
1013
            memset(dst + start, value, right_border);
 
1014
        dst += stride;
 
1015
        height--;
 
1016
    }
 
1017
    if (bottom_border > 0)
 
1018
        memset(dst, value, stride * bottom_border);
 
1019
}
 
1020
 
 
1021
static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
 
1022
{
 
1023
    struct gl_priv *p = vo->priv;
 
1024
    GL *gl = p->gl;
 
1025
 
 
1026
    int slice = p->slice_height;
 
1027
    int stride[3];
 
1028
    unsigned char *planes[3];
 
1029
    mp_image_t mpi2 = *mpi;
 
1030
    int w = mpi->w, h = mpi->h;
 
1031
    if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
 
1032
        goto skip_upload;
 
1033
    mpi2.flags = 0;
 
1034
    mpi2.type = MP_IMGTYPE_TEMP;
 
1035
    mpi2.width = mpi2.w;
 
1036
    mpi2.height = mpi2.h;
 
1037
    if (p->force_pbo && !(mpi->flags & MP_IMGFLAG_DIRECT) && !p->bufferptr
 
1038
        && get_image(vo, &mpi2) == VO_TRUE)
 
1039
    {
 
1040
        int bp = mpi->bpp / 8;
 
1041
        int xs, ys, component_bits;
 
1042
        mp_get_chroma_shift(p->image_format, &xs, &ys, &component_bits);
 
1043
        if (p->is_yuv)
 
1044
            bp = (component_bits + 7) / 8;
 
1045
        memcpy_pic(mpi2.planes[0], mpi->planes[0], mpi->w * bp, mpi->h,
 
1046
                   mpi2.stride[0], mpi->stride[0]);
 
1047
        int uv_bytes = (mpi->w >> xs) * bp;
 
1048
        if (p->is_yuv) {
 
1049
            memcpy_pic(mpi2.planes[1], mpi->planes[1], uv_bytes, mpi->h >> ys,
 
1050
                       mpi2.stride[1], mpi->stride[1]);
 
1051
            memcpy_pic(mpi2.planes[2], mpi->planes[2], uv_bytes, mpi->h >> ys,
 
1052
                       mpi2.stride[2], mpi->stride[2]);
 
1053
        }
 
1054
        if (p->ati_hack) {
 
1055
            // since we have to do a full upload we need to clear the borders
 
1056
            clear_border(vo, mpi2.planes[0], mpi->w * bp, mpi2.stride[0],
 
1057
                         mpi->h, mpi2.height, 0);
 
1058
            if (p->is_yuv) {
 
1059
                int clear = get_chroma_clear_val(component_bits);
 
1060
                clear_border(vo, mpi2.planes[1], uv_bytes, mpi2.stride[1],
 
1061
                             mpi->h >> ys, mpi2.height >> ys, clear);
 
1062
                clear_border(vo, mpi2.planes[2], uv_bytes, mpi2.stride[2],
 
1063
                             mpi->h >> ys, mpi2.height >> ys, clear);
 
1064
            }
 
1065
        }
 
1066
        mpi = &mpi2;
 
1067
    }
 
1068
    stride[0] = mpi->stride[0];
 
1069
    stride[1] = mpi->stride[1];
 
1070
    stride[2] = mpi->stride[2];
 
1071
    planes[0] = mpi->planes[0];
 
1072
    planes[1] = mpi->planes[1];
 
1073
    planes[2] = mpi->planes[2];
 
1074
    p->mpi_flipped = stride[0] < 0;
 
1075
    if (mpi->flags & MP_IMGFLAG_DIRECT) {
 
1076
        intptr_t base = (intptr_t)planes[0];
 
1077
        if (p->ati_hack) {
 
1078
            w = p->texture_width;
 
1079
            h = p->texture_height;
 
1080
        }
 
1081
        if (p->mpi_flipped)
 
1082
            base += (mpi->h - 1) * stride[0];
 
1083
        planes[0] -= base;
 
1084
        planes[1] -= base;
 
1085
        planes[2] -= base;
 
1086
        gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer);
 
1087
        gl->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
 
1088
        p->bufferptr = NULL;
 
1089
        if (!(mpi->flags & MP_IMGFLAG_COMMON_PLANE))
 
1090
            planes[0] = planes[1] = planes[2] = NULL;
 
1091
        slice = 0; // always "upload" full texture
 
1092
    }
 
1093
    glUploadTex(gl, p->target, p->gl_format, p->gl_type, planes[0],
 
1094
                stride[0], mpi->x, mpi->y, w, h, slice);
 
1095
    if (p->is_yuv) {
 
1096
        int xs, ys;
 
1097
        mp_get_chroma_shift(p->image_format, &xs, &ys, NULL);
 
1098
        if ((mpi->flags & MP_IMGFLAG_DIRECT) && !(mpi->flags & MP_IMGFLAG_COMMON_PLANE)) {
 
1099
            gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer_uv[0]);
 
1100
            gl->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
 
1101
            p->bufferptr_uv[0] = NULL;
 
1102
        }
 
1103
        gl->ActiveTexture(GL_TEXTURE1);
 
1104
        glUploadTex(gl, p->target, p->gl_format, p->gl_type, planes[1],
 
1105
                    stride[1], mpi->x >> xs, mpi->y >> ys, w >> xs, h >> ys,
 
1106
                    slice);
 
1107
        if ((mpi->flags & MP_IMGFLAG_DIRECT) && !(mpi->flags & MP_IMGFLAG_COMMON_PLANE)) {
 
1108
            gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->buffer_uv[1]);
 
1109
            gl->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
 
1110
            p->bufferptr_uv[1] = NULL;
 
1111
        }
 
1112
        gl->ActiveTexture(GL_TEXTURE2);
 
1113
        glUploadTex(gl, p->target, p->gl_format, p->gl_type, planes[2],
 
1114
                    stride[2], mpi->x >> xs, mpi->y >> ys, w >> xs, h >> ys,
 
1115
                    slice);
 
1116
        gl->ActiveTexture(GL_TEXTURE0);
 
1117
    }
 
1118
    if (mpi->flags & MP_IMGFLAG_DIRECT) {
 
1119
        gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
 
1120
    }
1077
1121
skip_upload:
1078
 
  if (vo_doublebuffering) do_render();
1079
 
  return VO_TRUE;
1080
 
}
1081
 
 
1082
 
static int
1083
 
draw_frame(uint8_t *src[])
1084
 
{
1085
 
  return VO_ERROR;
1086
 
}
1087
 
 
1088
 
static int
1089
 
query_format(uint32_t format)
1090
 
{
1091
 
    int caps = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW |
1092
 
               VFCAP_FLIP |
 
1122
    if (vo_doublebuffering)
 
1123
        do_render(vo);
 
1124
    return VO_TRUE;
 
1125
}
 
1126
 
 
1127
static mp_image_t *get_screenshot(struct vo *vo)
 
1128
{
 
1129
    struct gl_priv *p = vo->priv;
 
1130
    GL *gl = p->gl;
 
1131
 
 
1132
    mp_image_t *image = alloc_mpi(p->texture_width, p->texture_height,
 
1133
                                  p->image_format);
 
1134
 
 
1135
    glDownloadTex(gl, p->target, p->gl_format, p->gl_type, image->planes[0],
 
1136
                  image->stride[0]);
 
1137
 
 
1138
    if (p->is_yuv) {
 
1139
        gl->ActiveTexture(GL_TEXTURE1);
 
1140
        glDownloadTex(gl, p->target, p->gl_format, p->gl_type, image->planes[1],
 
1141
                      image->stride[1]);
 
1142
        gl->ActiveTexture(GL_TEXTURE2);
 
1143
        glDownloadTex(gl, p->target, p->gl_format, p->gl_type, image->planes[2],
 
1144
                      image->stride[2]);
 
1145
        gl->ActiveTexture(GL_TEXTURE0);
 
1146
    }
 
1147
 
 
1148
    image->width = p->image_width;
 
1149
    image->height = p->image_height;
 
1150
 
 
1151
    image->w = p->image_d_width;
 
1152
    image->h = p->image_d_height;
 
1153
 
 
1154
    return image;
 
1155
}
 
1156
 
 
1157
static mp_image_t *get_window_screenshot(struct vo *vo)
 
1158
{
 
1159
    struct gl_priv *p = vo->priv;
 
1160
    GL *gl = p->gl;
 
1161
 
 
1162
    GLint vp[4]; //x, y, w, h
 
1163
    gl->GetIntegerv(GL_VIEWPORT, vp);
 
1164
    mp_image_t *image = alloc_mpi(vp[2], vp[3], IMGFMT_RGB24);
 
1165
    gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
 
1166
    gl->PixelStorei(GL_PACK_ALIGNMENT, 0);
 
1167
    gl->PixelStorei(GL_PACK_ROW_LENGTH, 0);
 
1168
    gl->ReadBuffer(GL_FRONT);
 
1169
    //flip image while reading
 
1170
    for (int y = 0; y < vp[3]; y++) {
 
1171
        gl->ReadPixels(vp[0], vp[1] + vp[3] - y - 1, vp[2], 1,
 
1172
                       GL_RGB, GL_UNSIGNED_BYTE,
 
1173
                       image->planes[0] + y * image->stride[0]);
 
1174
    }
 
1175
    return image;
 
1176
}
 
1177
 
 
1178
static int query_format(struct vo *vo, uint32_t format)
 
1179
{
 
1180
    struct gl_priv *p = vo->priv;
 
1181
 
 
1182
    int depth;
 
1183
    int caps = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_FLIP |
1093
1184
               VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE;
1094
 
    if (use_osd)
1095
 
      caps |= VFCAP_OSD | VFCAP_EOSD | (scaled_osd ? 0 : VFCAP_EOSD_UNSCALED);
 
1185
    if (p->use_osd)
 
1186
        caps |= VFCAP_OSD | VFCAP_EOSD | (p->scaled_osd ? 0 : VFCAP_EOSD_UNSCALED);
1096
1187
    if (format == IMGFMT_RGB24 || format == IMGFMT_RGBA)
1097
1188
        return caps;
1098
 
    if (use_yuv && mp_get_chroma_shift(format, NULL, NULL) &&
 
1189
    if (p->use_yuv && mp_get_chroma_shift(format, NULL, NULL, &depth) &&
 
1190
        (depth == 8 || depth == 16 || glYUVLargeRange(p->use_yuv)) &&
1099
1191
        (IMGFMT_IS_YUVP16_NE(format) || !IMGFMT_IS_YUVP16(format)))
1100
1192
        return caps;
1101
1193
    // HACK, otherwise we get only b&w with some filters (e.g. -vf eq)
1102
1194
    // ideally MPlayer should be fixed instead not to use Y800 when it has the choice
1103
 
    if (!use_yuv && (format == IMGFMT_Y8 || format == IMGFMT_Y800))
1104
 
        return 0;
1105
 
    if (!use_ycbcr && (format == IMGFMT_UYVY || format == IMGFMT_YUY2))
1106
 
        return 0;
1107
 
    if (many_fmts &&
1108
 
         glFindFormat(format, NULL, NULL, NULL, NULL))
 
1195
    if (!p->use_yuv && (format == IMGFMT_Y8 || format == IMGFMT_Y800))
 
1196
        return 0;
 
1197
    if (!p->use_ycbcr && (format == IMGFMT_UYVY || format == IMGFMT_YVYU))
 
1198
        return 0;
 
1199
    if (p->many_fmts &&
 
1200
        glFindFormat(format, p->have_texture_rg, NULL, NULL, NULL, NULL))
1109
1201
        return caps;
1110
1202
    return 0;
1111
1203
}
1112
1204
 
1113
 
 
1114
 
static void
1115
 
uninit(void)
1116
 
{
1117
 
  uninitGl();
1118
 
  free(custom_prog);
1119
 
  custom_prog = NULL;
1120
 
  free(custom_tex);
1121
 
  custom_tex = NULL;
1122
 
  uninit_mpglcontext(&glctx);
1123
 
}
1124
 
 
1125
 
static int valid_csp(void *p)
1126
 
{
1127
 
  int *csp = p;
1128
 
  return *csp >= -1 && *csp < MP_CSP_COUNT;
1129
 
}
1130
 
 
1131
 
static int valid_csp_lvl(void *p)
1132
 
{
1133
 
  int *lvl = p;
1134
 
  return *lvl >= -1 && *lvl < MP_CSP_LEVELCONV_COUNT;
1135
 
}
1136
 
 
1137
 
static const opt_t subopts[] = {
1138
 
  {"manyfmts",     OPT_ARG_BOOL, &many_fmts,    NULL},
1139
 
  {"osd",          OPT_ARG_BOOL, &use_osd,      NULL},
1140
 
  {"scaled-osd",   OPT_ARG_BOOL, &scaled_osd,   NULL},
1141
 
  {"aspect",       OPT_ARG_BOOL, &use_aspect,   NULL},
1142
 
  {"ycbcr",        OPT_ARG_BOOL, &use_ycbcr,    NULL},
1143
 
  {"slice-height", OPT_ARG_INT,  &slice_height, int_non_neg},
1144
 
  {"rectangle",    OPT_ARG_INT,  &use_rectangle,int_non_neg},
1145
 
  {"yuv",          OPT_ARG_INT,  &use_yuv,      int_non_neg},
1146
 
  {"colorspace",   OPT_ARG_INT,  &colorspace,   valid_csp},
1147
 
  {"levelconv",    OPT_ARG_INT,  &levelconv,    valid_csp_lvl},
1148
 
  {"lscale",       OPT_ARG_INT,  &lscale,       int_non_neg},
1149
 
  {"cscale",       OPT_ARG_INT,  &cscale,       int_non_neg},
1150
 
  {"filter-strength", OPT_ARG_FLOAT, &filter_strength, NULL},
1151
 
  {"ati-hack",     OPT_ARG_BOOL, &ati_hack,     NULL},
1152
 
  {"force-pbo",    OPT_ARG_BOOL, &force_pbo,    NULL},
1153
 
  {"mesa-buffer",  OPT_ARG_BOOL, &mesa_buffer,  NULL},
1154
 
  {"glfinish",     OPT_ARG_BOOL, &use_glFinish, NULL},
1155
 
  {"swapinterval", OPT_ARG_INT,  &swap_interval,NULL},
1156
 
  {"customprog",   OPT_ARG_MSTRZ,&custom_prog,  NULL},
1157
 
  {"customtex",    OPT_ARG_MSTRZ,&custom_tex,   NULL},
1158
 
  {"customtlin",   OPT_ARG_BOOL, &custom_tlin,  NULL},
1159
 
  {"customtrect",  OPT_ARG_BOOL, &custom_trect, NULL},
1160
 
  {"mipmapgen",    OPT_ARG_BOOL, &mipmap_gen,   NULL},
1161
 
  {"osdcolor",     OPT_ARG_INT,  &osd_color,    NULL},
1162
 
  {"stereo",       OPT_ARG_INT,  &stereo_mode,  NULL},
1163
 
  {NULL}
1164
 
};
1165
 
 
1166
 
static int preinit_internal(const char *arg, int allow_sw)
1167
 
{
1168
 
    // set defaults
1169
 
    enum MPGLType gltype = GLTYPE_AUTO;
1170
 
    many_fmts = 1;
1171
 
    use_osd = -1;
1172
 
    scaled_osd = 0;
1173
 
    use_aspect = 1;
1174
 
    use_ycbcr = 0;
1175
 
    use_yuv = -1;
1176
 
    colorspace = -1;
1177
 
    levelconv = -1;
1178
 
    lscale = 0;
1179
 
    cscale = 0;
1180
 
    filter_strength = 0.5;
1181
 
    use_rectangle = -1;
1182
 
    use_glFinish = 0;
1183
 
    ati_hack = -1;
1184
 
    force_pbo = -1;
1185
 
    mesa_buffer = 0;
1186
 
    swap_interval = 1;
1187
 
    slice_height = 0;
1188
 
    custom_prog = NULL;
1189
 
    custom_tex = NULL;
1190
 
    custom_tlin = 1;
1191
 
    custom_trect = 0;
1192
 
    mipmap_gen = 0;
1193
 
    osd_color = 0xffffff;
1194
 
    stereo_mode = 0;
 
1205
static void uninit(struct vo *vo)
 
1206
{
 
1207
    struct gl_priv *p = vo->priv;
 
1208
 
 
1209
    if (p->glctx)
 
1210
        uninitGl(vo);
 
1211
    free(p->custom_prog);
 
1212
    p->custom_prog = NULL;
 
1213
    free(p->custom_tex);
 
1214
    p->custom_tex = NULL;
 
1215
    uninit_mpglcontext(p->glctx);
 
1216
    p->glctx = NULL;
 
1217
    p->gl = NULL;
 
1218
}
 
1219
 
 
1220
static int preinit_internal(struct vo *vo, const char *arg, int allow_sw,
 
1221
                            enum MPGLType gltype)
 
1222
{
 
1223
    struct gl_priv *p = talloc_zero(vo, struct gl_priv);
 
1224
    vo->priv = p;
 
1225
 
 
1226
    *p = (struct gl_priv) {
 
1227
        .many_fmts = 1,
 
1228
        .use_osd = -1,
 
1229
        .use_yuv = -1,
 
1230
        .colorspace = MP_CSP_DETAILS_DEFAULTS,
 
1231
        .filter_strength = 0.5,
 
1232
        .use_rectangle = -1,
 
1233
        .ati_hack = -1,
 
1234
        .force_pbo = -1,
 
1235
        .swap_interval = 1,
 
1236
        .custom_prog = NULL,
 
1237
        .custom_tex = NULL,
 
1238
        .custom_tlin = 1,
 
1239
        .osd_color = 0xffffff,
 
1240
    };
 
1241
 
 
1242
    //essentially unused; for legacy warnings only
 
1243
    int user_colorspace = 0;
 
1244
    int levelconv = -1;
 
1245
    int aspect = -1;
 
1246
 
 
1247
    const opt_t subopts[] = {
 
1248
        {"manyfmts",     OPT_ARG_BOOL, &p->many_fmts,    NULL},
 
1249
        {"osd",          OPT_ARG_BOOL, &p->use_osd,      NULL},
 
1250
        {"scaled-osd",   OPT_ARG_BOOL, &p->scaled_osd,   NULL},
 
1251
        {"ycbcr",        OPT_ARG_BOOL, &p->use_ycbcr,    NULL},
 
1252
        {"slice-height", OPT_ARG_INT,  &p->slice_height, int_non_neg},
 
1253
        {"rectangle",    OPT_ARG_INT,  &p->use_rectangle,int_non_neg},
 
1254
        {"yuv",          OPT_ARG_INT,  &p->use_yuv,      int_non_neg},
 
1255
        {"lscale",       OPT_ARG_INT,  &p->lscale,       int_non_neg},
 
1256
        {"cscale",       OPT_ARG_INT,  &p->cscale,       int_non_neg},
 
1257
        {"filter-strength", OPT_ARG_FLOAT, &p->filter_strength, NULL},
 
1258
        {"ati-hack",     OPT_ARG_BOOL, &p->ati_hack,     NULL},
 
1259
        {"force-pbo",    OPT_ARG_BOOL, &p->force_pbo,    NULL},
 
1260
        {"glfinish",     OPT_ARG_BOOL, &p->use_glFinish, NULL},
 
1261
        {"swapinterval", OPT_ARG_INT,  &p->swap_interval,NULL},
 
1262
        {"customprog",   OPT_ARG_MSTRZ,&p->custom_prog,  NULL},
 
1263
        {"customtex",    OPT_ARG_MSTRZ,&p->custom_tex,   NULL},
 
1264
        {"customtlin",   OPT_ARG_BOOL, &p->custom_tlin,  NULL},
 
1265
        {"customtrect",  OPT_ARG_BOOL, &p->custom_trect, NULL},
 
1266
        {"mipmapgen",    OPT_ARG_BOOL, &p->mipmap_gen,   NULL},
 
1267
        {"osdcolor",     OPT_ARG_INT,  &p->osd_color,    NULL},
 
1268
        {"stereo",       OPT_ARG_INT,  &p->stereo_mode,  NULL},
 
1269
        // Removed options.
 
1270
        // They are only parsed to notify the user about the replacements.
 
1271
        {"aspect",       OPT_ARG_BOOL, &aspect,          NULL},
 
1272
        {"colorspace",   OPT_ARG_INT,  &user_colorspace, NULL},
 
1273
        {"levelconv",    OPT_ARG_INT,  &levelconv,       NULL},
 
1274
        {NULL}
 
1275
    };
 
1276
 
1195
1277
    if (subopt_parse(arg, subopts) != 0) {
1196
 
      mp_msg(MSGT_VO, MSGL_FATAL,
1197
 
              "\n-vo gl command line help:\n"
1198
 
              "Example: mplayer -vo gl:slice-height=4\n"
1199
 
              "\nOptions:\n"
1200
 
              "  nomanyfmts\n"
1201
 
              "    Disable extended color formats for OpenGL 1.2 and later\n"
1202
 
              "  slice-height=<0-...>\n"
1203
 
              "    Slice size for texture transfer, 0 for whole image\n"
1204
 
              "  noosd\n"
1205
 
              "    Do not use OpenGL OSD code\n"
1206
 
              "  scaled-osd\n"
1207
 
              "    Render OSD at movie resolution and scale it\n"
1208
 
              "  noaspect\n"
1209
 
              "    Do not do aspect scaling\n"
1210
 
              "  rectangle=<0,1,2>\n"
1211
 
              "    0: use power-of-two textures\n"
1212
 
              "    1: use texture_rectangle\n"
1213
 
              "    2: use texture_non_power_of_two\n"
1214
 
              "  ati-hack\n"
1215
 
              "    Workaround ATI bug with PBOs\n"
1216
 
              "  force-pbo\n"
1217
 
              "    Force use of PBO even if this involves an extra memcpy\n"
1218
 
              "  glfinish\n"
1219
 
              "    Call glFinish() before swapping buffers\n"
1220
 
              "  swapinterval=<n>\n"
1221
 
              "    Interval in displayed frames between to buffer swaps.\n"
1222
 
              "    1 is equivalent to enable VSYNC, 0 to disable VSYNC.\n"
1223
 
              "    Requires GLX_SGI_swap_control support to work.\n"
1224
 
              "  ycbcr\n"
1225
 
              "    also try to use the GL_MESA_ycbcr_texture extension\n"
1226
 
              "  yuv=<n>\n"
1227
 
              "    0: use software YUV to RGB conversion.\n"
1228
 
              "    1: use register combiners (nVidia only, for older cards).\n"
1229
 
              "    2: use fragment program.\n"
1230
 
              "    3: use fragment program with gamma correction.\n"
1231
 
              "    4: use fragment program with gamma correction via lookup.\n"
1232
 
              "    5: use ATI-specific method (for older cards).\n"
1233
 
              "    6: use lookup via 3D texture.\n"
1234
 
              "  colorspace=<n>\n"
1235
 
              "    0: MPlayer's default YUV to RGB conversion\n"
1236
 
              "    1: YUV to RGB according to BT.601\n"
1237
 
              "    2: YUV to RGB according to BT.709\n"
1238
 
              "    3: YUV to RGB according to SMPT-240M\n"
1239
 
              "    4: YUV to RGB according to EBU\n"
1240
 
              "    5: XYZ to RGB\n"
1241
 
              "  levelconv=<n>\n"
1242
 
              "    0: YUV to RGB converting TV to PC levels\n"
1243
 
              "    1: YUV to RGB converting PC to TV levels\n"
1244
 
              "    2: YUV to RGB without converting levels\n"
1245
 
              "  lscale=<n>\n"
1246
 
              "    0: use standard bilinear scaling for luma.\n"
1247
 
              "    1: use improved bicubic scaling for luma.\n"
1248
 
              "    2: use cubic in X, linear in Y direction scaling for luma.\n"
1249
 
              "    3: as 1 but without using a lookup texture.\n"
1250
 
              "    4: experimental unsharp masking (sharpening).\n"
1251
 
              "    5: experimental unsharp masking (sharpening) with larger radius.\n"
1252
 
              "  cscale=<n>\n"
1253
 
              "    as lscale but for chroma (2x slower with little visible effect).\n"
1254
 
              "  filter-strength=<value>\n"
1255
 
              "    set the effect strength for some lscale/cscale filters\n"
1256
 
              "  customprog=<filename>\n"
1257
 
              "    use a custom YUV conversion program\n"
1258
 
              "  customtex=<filename>\n"
1259
 
              "    use a custom YUV conversion lookup texture\n"
1260
 
              "  nocustomtlin\n"
1261
 
              "    use GL_NEAREST scaling for customtex texture\n"
1262
 
              "  customtrect\n"
1263
 
              "    use texture_rectangle for customtex texture\n"
1264
 
              "  mipmapgen\n"
1265
 
              "    generate mipmaps for the video image (use with TXB in customprog)\n"
1266
 
              "  osdcolor=<0xAARRGGBB>\n"
1267
 
              "    use the given color for the OSD\n"
1268
 
              "  stereo=<n>\n"
1269
 
              "    0: normal display\n"
1270
 
              "    1: side-by-side to red-cyan stereo\n"
1271
 
              "    2: side-by-side to green-magenta stereo\n"
1272
 
              "    3: side-by-side to quadbuffer stereo\n"
1273
 
              "\n" );
1274
 
      return -1;
1275
 
    }
1276
 
    if (!init_mpglcontext(&glctx, gltype))
1277
 
      goto err_out;
1278
 
    if (use_yuv == -1 || !allow_sw) {
1279
 
      if (create_window(320, 200, VOFLAG_HIDDEN, NULL) < 0)
1280
 
        goto err_out;
1281
 
      if (glctx.setGlWindow(&glctx) == SET_WINDOW_FAILED)
1282
 
        goto err_out;
1283
 
      if (!allow_sw && isSoftwareGl())
1284
 
        goto err_out;
1285
 
      autodetectGlExtensions();
1286
 
    }
1287
 
    if (many_fmts)
1288
 
      mp_msg(MSGT_VO, MSGL_INFO, "[gl] using extended formats. "
 
1278
        mp_msg(MSGT_VO, MSGL_FATAL,
 
1279
               "\n-vo gl command line help:\n"
 
1280
               "Example: mplayer -vo gl:slice-height=4\n"
 
1281
               "\nOptions:\n"
 
1282
               "  nomanyfmts\n"
 
1283
               "    Disable extended color formats for OpenGL 1.2 and later\n"
 
1284
               "  slice-height=<0-...>\n"
 
1285
               "    Slice size for texture transfer, 0 for whole image\n"
 
1286
               "  noosd\n"
 
1287
               "    Do not use OpenGL OSD code\n"
 
1288
               "  scaled-osd\n"
 
1289
               "    Render OSD at movie resolution and scale it\n"
 
1290
               "  rectangle=<0,1,2>\n"
 
1291
               "    0: use power-of-two textures\n"
 
1292
               "    1: use texture_rectangle\n"
 
1293
               "    2: use texture_non_power_of_two\n"
 
1294
               "  ati-hack\n"
 
1295
               "    Workaround ATI bug with PBOs\n"
 
1296
               "  force-pbo\n"
 
1297
               "    Force use of PBO even if this involves an extra memcpy\n"
 
1298
               "  glfinish\n"
 
1299
               "    Call glFinish() before swapping buffers\n"
 
1300
               "  swapinterval=<n>\n"
 
1301
               "    Interval in displayed frames between to buffer swaps.\n"
 
1302
               "    1 is equivalent to enable VSYNC, 0 to disable VSYNC.\n"
 
1303
               "    Requires GLX_SGI_swap_control support to work.\n"
 
1304
               "  ycbcr\n"
 
1305
               "    also try to use the GL_MESA_ycbcr_texture extension\n"
 
1306
               "  yuv=<n>\n"
 
1307
               "    0: use software YUV to RGB conversion.\n"
 
1308
               "    1: deprecated, will use yuv=2 (used to be nVidia register combiners).\n"
 
1309
               "    2: use fragment program.\n"
 
1310
               "    3: use fragment program with gamma correction.\n"
 
1311
               "    4: use fragment program with gamma correction via lookup.\n"
 
1312
               "    5: use ATI-specific method (for older cards).\n"
 
1313
               "    6: use lookup via 3D texture.\n"
 
1314
               "  lscale=<n>\n"
 
1315
               "    0: use standard bilinear scaling for luma.\n"
 
1316
               "    1: use improved bicubic scaling for luma.\n"
 
1317
               "    2: use cubic in X, linear in Y direction scaling for luma.\n"
 
1318
               "    3: as 1 but without using a lookup texture.\n"
 
1319
               "    4: experimental unsharp masking (sharpening).\n"
 
1320
               "    5: experimental unsharp masking (sharpening) with larger radius.\n"
 
1321
               "  cscale=<n>\n"
 
1322
               "    as lscale but for chroma (2x slower with little visible effect).\n"
 
1323
               "  filter-strength=<value>\n"
 
1324
               "    set the effect strength for some lscale/cscale filters\n"
 
1325
               "  customprog=<filename>\n"
 
1326
               "    use a custom YUV conversion program\n"
 
1327
               "  customtex=<filename>\n"
 
1328
               "    use a custom YUV conversion lookup texture\n"
 
1329
               "  nocustomtlin\n"
 
1330
               "    use GL_NEAREST scaling for customtex texture\n"
 
1331
               "  customtrect\n"
 
1332
               "    use texture_rectangle for customtex texture\n"
 
1333
               "  mipmapgen\n"
 
1334
               "    generate mipmaps for the video image (use with TXB in customprog)\n"
 
1335
               "  osdcolor=<0xAARRGGBB>\n"
 
1336
               "    use the given color for the OSD\n"
 
1337
               "  stereo=<n>\n"
 
1338
               "    0: normal display\n"
 
1339
               "    1: side-by-side to red-cyan stereo\n"
 
1340
               "    2: side-by-side to green-magenta stereo\n"
 
1341
               "    3: side-by-side to quadbuffer stereo\n"
 
1342
               "\n");
 
1343
        return -1;
 
1344
    }
 
1345
    if (user_colorspace != 0 || levelconv != -1) {
 
1346
        mp_msg(MSGT_VO, MSGL_ERR, "[gl] \"colorspace\" and \"levelconv\" "
 
1347
               "suboptions have been removed. Use options --colormatrix and"
 
1348
               " --colormatrix-input-range/--colormatrix-output-range instead.\n");
 
1349
        return -1;
 
1350
    }
 
1351
    if (aspect != -1) {
 
1352
        mp_msg(MSGT_VO, MSGL_ERR, "[gl] \"noaspect\" suboption has been "
 
1353
               "removed. Use --noaspect instead.\n");
 
1354
        return -1;
 
1355
    }
 
1356
    if (p->use_yuv == 1) {
 
1357
        mp_msg(MSGT_VO, MSGL_WARN, "[gl] yuv=1 (nVidia register combiners) have"
 
1358
               " been removed, using yuv=2 instead.\n");
 
1359
        p->use_yuv = 2;
 
1360
    }
 
1361
    p->glctx = init_mpglcontext(gltype, vo);
 
1362
    if (!p->glctx)
 
1363
        goto err_out;
 
1364
    p->gl = p->glctx->gl;
 
1365
 
 
1366
    if (p->glctx->type == GLTYPE_SDL && p->use_yuv == -1) {
 
1367
        // Apparently it's not possible to implement VOFLAG_HIDDEN on SDL 1.2,
 
1368
        // so don't do autodetection. Use a sufficiently useful and safe YUV
 
1369
        // conversion mode.
 
1370
        p->use_yuv = YUV_CONVERSION_FRAGMENT;
 
1371
    }
 
1372
 
 
1373
    if (p->use_yuv == -1 || !allow_sw) {
 
1374
        if (create_window(vo, 320, 200, VOFLAG_HIDDEN) < 0)
 
1375
            goto err_out;
 
1376
        if (p->glctx->setGlWindow(p->glctx) == SET_WINDOW_FAILED)
 
1377
            goto err_out;
 
1378
        if (!allow_sw && isSoftwareGl(vo))
 
1379
            goto err_out;
 
1380
        autodetectGlExtensions(vo);
 
1381
        // We created a window to test whether the GL context supports hardware
 
1382
        // acceleration and so on. Destroy that window to make sure all state
 
1383
        // associated with it is lost.
 
1384
        uninit(vo);
 
1385
        p->glctx = init_mpglcontext(gltype, vo);
 
1386
        if (!p->glctx)
 
1387
            goto err_out;
 
1388
        p->gl = p->glctx->gl;
 
1389
    }
 
1390
    if (p->many_fmts)
 
1391
        mp_msg(MSGT_VO, MSGL_INFO, "[gl] using extended formats. "
1289
1392
               "Use -vo gl:nomanyfmts if playback fails.\n");
1290
1393
    mp_msg(MSGT_VO, MSGL_V, "[gl] Using %d as slice height "
1291
 
             "(0 means image height).\n", slice_height);
 
1394
           "(0 means image height).\n", p->slice_height);
1292
1395
 
1293
1396
    return 0;
1294
1397
 
1295
1398
err_out:
1296
 
    uninit();
 
1399
    uninit(vo);
1297
1400
    return -1;
1298
1401
}
1299
1402
 
1300
 
static int preinit(const char *arg)
1301
 
{
1302
 
    return preinit_internal(arg, 1);
1303
 
}
1304
 
 
1305
 
static int preinit_nosw(const char *arg)
1306
 
{
1307
 
    return preinit_internal(arg, 0);
1308
 
}
1309
 
 
1310
 
static const struct {
1311
 
  const char *name;
1312
 
  int *value;
1313
 
  int supportmask;
1314
 
} eq_map[] = {
1315
 
  {"brightness",  &eq_bri,    MASK_NOT_COMBINERS},
1316
 
  {"contrast",    &eq_cont,   MASK_NOT_COMBINERS},
1317
 
  {"saturation",  &eq_sat,    MASK_ALL_YUV      },
1318
 
  {"hue",         &eq_hue,    MASK_ALL_YUV      },
1319
 
  {"gamma",       &eq_rgamma, MASK_GAMMA_SUPPORT},
1320
 
  {"red_gamma",   &eq_rgamma, MASK_GAMMA_SUPPORT},
1321
 
  {"green_gamma", &eq_ggamma, MASK_GAMMA_SUPPORT},
1322
 
  {"blue_gamma",  &eq_bgamma, MASK_GAMMA_SUPPORT},
1323
 
  {NULL,          NULL,       0                 }
1324
 
};
1325
 
 
1326
 
static int control(uint32_t request, void *data)
1327
 
{
1328
 
  switch (request) {
1329
 
  case VOCTRL_PAUSE:
1330
 
  case VOCTRL_RESUME:
1331
 
    int_pause = (request == VOCTRL_PAUSE);
1332
 
    return VO_TRUE;
1333
 
  case VOCTRL_QUERY_FORMAT:
1334
 
    return query_format(*(uint32_t*)data);
1335
 
  case VOCTRL_GET_IMAGE:
1336
 
    return get_image(data);
1337
 
  case VOCTRL_DRAW_IMAGE:
1338
 
    return draw_image(data);
1339
 
  case VOCTRL_DRAW_EOSD:
1340
 
    if (!data)
1341
 
      return VO_FALSE;
1342
 
    genEOSD(data);
1343
 
    if (vo_doublebuffering) do_render_osd(RENDER_EOSD);
1344
 
    return VO_TRUE;
1345
 
  case VOCTRL_GET_EOSD_RES:
1346
 
    {
1347
 
      mp_eosd_res_t *r = data;
1348
 
      r->w = vo_dwidth; r->h = vo_dheight;
1349
 
      r->mt = r->mb = r->ml = r->mr = 0;
1350
 
      if (scaled_osd) {r->w = image_width; r->h = image_height;}
1351
 
      else if (aspect_scaling()) {
1352
 
        r->ml = r->mr = ass_border_x;
1353
 
        r->mt = r->mb = ass_border_y;
1354
 
      }
1355
 
    }
1356
 
    return VO_TRUE;
1357
 
  case VOCTRL_ONTOP:
1358
 
    glctx.ontop();
1359
 
    return VO_TRUE;
1360
 
  case VOCTRL_FULLSCREEN:
1361
 
    glctx.fullscreen();
1362
 
    resize(vo_dwidth, vo_dheight);
1363
 
    return VO_TRUE;
1364
 
  case VOCTRL_BORDER:
1365
 
    glctx.border();
1366
 
    resize(vo_dwidth, vo_dheight);
1367
 
    return VO_TRUE;
1368
 
  case VOCTRL_GET_PANSCAN:
1369
 
    if (!use_aspect) return VO_NOTIMPL;
1370
 
    return VO_TRUE;
1371
 
  case VOCTRL_SET_PANSCAN:
1372
 
    if (!use_aspect) return VO_NOTIMPL;
1373
 
    resize(vo_dwidth, vo_dheight);
1374
 
    return VO_TRUE;
1375
 
  case VOCTRL_GET_EQUALIZER:
1376
 
    if (is_yuv) {
1377
 
      struct voctrl_get_equalizer_args *args = data;
1378
 
      int i;
1379
 
      for (i = 0; eq_map[i].name; i++)
1380
 
        if (strcmp(args->name, eq_map[i].name) == 0) break;
1381
 
      if (!(eq_map[i].supportmask & (1 << use_yuv)))
1382
 
        break;
1383
 
      *args->valueptr = *eq_map[i].value;
1384
 
      return VO_TRUE;
1385
 
    }
1386
 
    break;
1387
 
  case VOCTRL_SET_EQUALIZER:
1388
 
    if (is_yuv) {
1389
 
      struct voctrl_set_equalizer_args *args = data;
1390
 
      int i;
1391
 
      for (i = 0; eq_map[i].name; i++)
1392
 
        if (strcmp(args->name, eq_map[i].name) == 0) break;
1393
 
      if (!(eq_map[i].supportmask & (1 << use_yuv)))
1394
 
        break;
1395
 
      *eq_map[i].value = args->value;
1396
 
      if (strcmp(args->name, "gamma") == 0)
1397
 
        eq_rgamma = eq_ggamma = eq_bgamma = args->value;
1398
 
      update_yuvconv();
1399
 
      return VO_TRUE;
1400
 
    }
1401
 
    break;
1402
 
  case VOCTRL_UPDATE_SCREENINFO:
1403
 
    glctx.update_xinerama_info();
1404
 
    return VO_TRUE;
1405
 
  case VOCTRL_REDRAW_OSD:
1406
 
    if (vo_doublebuffering)
1407
 
      do_render();
1408
 
    draw_osd();
1409
 
    if (vo_doublebuffering)
1410
 
      do_render_osd(2);
1411
 
    flip_page();
1412
 
    return VO_TRUE;
1413
 
  }
1414
 
  return VO_NOTIMPL;
1415
 
}
 
1403
static int preinit(struct vo *vo, const char *arg)
 
1404
{
 
1405
    return preinit_internal(vo, arg, 1, GLTYPE_AUTO);
 
1406
}
 
1407
 
 
1408
static int control(struct vo *vo, uint32_t request, void *data)
 
1409
{
 
1410
    struct gl_priv *p = vo->priv;
 
1411
 
 
1412
    switch (request) {
 
1413
    case VOCTRL_QUERY_FORMAT:
 
1414
        return query_format(vo, *(uint32_t *)data);
 
1415
    case VOCTRL_GET_IMAGE:
 
1416
        return get_image(vo, data);
 
1417
    case VOCTRL_DRAW_IMAGE:
 
1418
        return draw_image(vo, data);
 
1419
    case VOCTRL_DRAW_EOSD:
 
1420
        if (!data)
 
1421
            return VO_FALSE;
 
1422
        genEOSD(vo, data);
 
1423
        if (vo_doublebuffering)
 
1424
            do_render_osd(vo, RENDER_EOSD);
 
1425
        return VO_TRUE;
 
1426
    case VOCTRL_GET_EOSD_RES: {
 
1427
        mp_eosd_res_t *r = data;
 
1428
        r->w = vo->dwidth;
 
1429
        r->h = vo->dheight;
 
1430
        r->mt = r->mb = r->ml = r->mr = 0;
 
1431
        if (p->scaled_osd) {
 
1432
            r->w = p->image_width;
 
1433
            r->h = p->image_height;
 
1434
        } else if (aspect_scaling()) {
 
1435
            r->ml = r->mr = p->ass_border_x;
 
1436
            r->mt = r->mb = p->ass_border_y;
 
1437
        }
 
1438
        return VO_TRUE;
 
1439
    }
 
1440
    case VOCTRL_ONTOP:
 
1441
        if (!p->glctx->ontop)
 
1442
            break;
 
1443
        p->glctx->ontop(vo);
 
1444
        return VO_TRUE;
 
1445
    case VOCTRL_FULLSCREEN:
 
1446
        p->glctx->fullscreen(vo);
 
1447
        resize(vo, vo->dwidth, vo->dheight);
 
1448
        return VO_TRUE;
 
1449
    case VOCTRL_BORDER:
 
1450
        if (!p->glctx->border)
 
1451
            break;
 
1452
        p->glctx->border(vo);
 
1453
        resize(vo, vo->dwidth, vo->dheight);
 
1454
        return VO_TRUE;
 
1455
    case VOCTRL_GET_PANSCAN:
 
1456
        return VO_TRUE;
 
1457
    case VOCTRL_SET_PANSCAN:
 
1458
        resize(vo, vo->dwidth, vo->dheight);
 
1459
        return VO_TRUE;
 
1460
    case VOCTRL_GET_EQUALIZER:
 
1461
        if (p->is_yuv) {
 
1462
            struct voctrl_get_equalizer_args *args = data;
 
1463
            return mp_csp_equalizer_get(&p->video_eq, args->name, args->valueptr)
 
1464
                   >= 0 ? VO_TRUE : VO_NOTIMPL;
 
1465
        }
 
1466
        break;
 
1467
    case VOCTRL_SET_EQUALIZER:
 
1468
        if (p->is_yuv) {
 
1469
            struct voctrl_set_equalizer_args *args = data;
 
1470
            if (mp_csp_equalizer_set(&p->video_eq, args->name, args->value) < 0)
 
1471
                return VO_NOTIMPL;
 
1472
            update_yuvconv(vo);
 
1473
            vo->want_redraw = true;
 
1474
            return VO_TRUE;
 
1475
        }
 
1476
        break;
 
1477
    case VOCTRL_SET_YUV_COLORSPACE: {
 
1478
        bool supports_csp = (1 << p->use_yuv) & MASK_NOT_COMBINERS;
 
1479
        if (vo->config_count && supports_csp) {
 
1480
            p->colorspace = *(struct mp_csp_details *)data;
 
1481
            update_yuvconv(vo);
 
1482
            vo->want_redraw = true;
 
1483
        }
 
1484
        return VO_TRUE;
 
1485
    }
 
1486
    case VOCTRL_GET_YUV_COLORSPACE:
 
1487
        *(struct mp_csp_details *)data = p->colorspace;
 
1488
        return VO_TRUE;
 
1489
    case VOCTRL_UPDATE_SCREENINFO:
 
1490
        if (!p->glctx->update_xinerama_info)
 
1491
            break;
 
1492
        p->glctx->update_xinerama_info(vo);
 
1493
        return VO_TRUE;
 
1494
    case VOCTRL_REDRAW_FRAME:
 
1495
        if (vo_doublebuffering)
 
1496
            do_render(vo);
 
1497
        return true;
 
1498
    case VOCTRL_SCREENSHOT: {
 
1499
        struct voctrl_screenshot_args *args = data;
 
1500
        if (args->full_window)
 
1501
            args->out_image = get_window_screenshot(vo);
 
1502
        else
 
1503
            args->out_image = get_screenshot(vo);
 
1504
        return true;
 
1505
    }
 
1506
    }
 
1507
    return VO_NOTIMPL;
 
1508
}
 
1509
 
 
1510
const struct vo_driver video_out_gl = {
 
1511
    .is_new = true,
 
1512
    .info = &(const vo_info_t) {
 
1513
        "OpenGL",
 
1514
        "gl",
 
1515
        "Reimar Doeffinger <Reimar.Doeffinger@gmx.de>",
 
1516
        ""
 
1517
    },
 
1518
    .preinit = preinit,
 
1519
    .config = config,
 
1520
    .control = control,
 
1521
    .draw_slice = draw_slice,
 
1522
    .draw_osd = draw_osd,
 
1523
    .flip_page = flip_page,
 
1524
    .check_events = check_events,
 
1525
    .uninit = uninit,
 
1526
};
 
1527
 
 
1528
static int preinit_nosw(struct vo *vo, const char *arg)
 
1529
{
 
1530
    return preinit_internal(vo, arg, 0, GLTYPE_AUTO);
 
1531
}
 
1532
 
 
1533
const struct vo_driver video_out_gl_nosw =
 
1534
{
 
1535
    .is_new = true,
 
1536
    .info = &(const vo_info_t) {
 
1537
        "OpenGL no software rendering",
 
1538
        "gl_nosw",
 
1539
        "Reimar Doeffinger <Reimar.Doeffinger@gmx.de>",
 
1540
        ""
 
1541
    },
 
1542
    .preinit = preinit_nosw,
 
1543
    .config = config,
 
1544
    .control = control,
 
1545
    .draw_slice = draw_slice,
 
1546
    .draw_osd = draw_osd,
 
1547
    .flip_page = flip_page,
 
1548
    .check_events = check_events,
 
1549
    .uninit = uninit,
 
1550
};
 
1551
 
 
1552
#ifdef CONFIG_GL_SDL
 
1553
static int preinit_sdl(struct vo *vo, const char *arg)
 
1554
{
 
1555
    return preinit_internal(vo, arg, 1, GLTYPE_SDL);
 
1556
}
 
1557
 
 
1558
const struct vo_driver video_out_gl_sdl = {
 
1559
    .is_new = true,
 
1560
    .info = &(const vo_info_t) {
 
1561
        "OpenGL with SDL",
 
1562
        "gl_sdl",
 
1563
        "Reimar Doeffinger <Reimar.Doeffinger@gmx.de>",
 
1564
        ""
 
1565
    },
 
1566
    .preinit = preinit_sdl,
 
1567
    .config = config,
 
1568
    .control = control,
 
1569
    .draw_slice = draw_slice,
 
1570
    .draw_osd = draw_osd,
 
1571
    .flip_page = flip_page,
 
1572
    .check_events = check_events,
 
1573
    .uninit = uninit,
 
1574
};
 
1575
#endif