00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <vlc_common.h>
00030 #include <vlc_picture_pool.h>
00031 #include <vlc_vout_opengl.h>
00032
00033 #ifdef __APPLE__
00034 # include <OpenGL/gl.h>
00035 # include <OpenGL/glext.h>
00036 #else
00037 # include <GL/gl.h>
00038 #endif
00039
00040 #ifndef YCBCR_MESA
00041 # define YCBCR_MESA 0x8757
00042 #endif
00043 #ifndef UNSIGNED_SHORT_8_8_MESA
00044 # define UNSIGNED_SHORT_8_8_MESA 0x85BA
00045 #endif
00046
00047 #ifndef GL_UNSIGNED_SHORT_5_6_5
00048 # define GL_UNSIGNED_SHORT_5_6_5 0x8363
00049 #endif
00050 #ifndef GL_CLAMP_TO_EDGE
00051 # define GL_CLAMP_TO_EDGE 0x812F
00052 #endif
00053
00054 #ifdef __APPLE__
00055
00056
00057 # define VLCGL_TARGET GL_TEXTURE_RECTANGLE_EXT
00058
00059
00060 # define VLCGL_FORMAT GL_YCBCR_422_APPLE
00061 # define VLCGL_TYPE GL_UNSIGNED_SHORT_8_8_APPLE
00062
00063 # define VLCGL_TEXTURE_COUNT (2)
00064 #else
00065
00066 # define VLCGL_TARGET GL_TEXTURE_2D
00067
00068
00069 # define VLCGL_RGB_FORMAT GL_RGBA
00070 # define VLCGL_RGB_TYPE GL_UNSIGNED_BYTE
00071
00072
00073 # define VLCGL_YUV_FORMAT YCBCR_MESA
00074 # define VLCGL_YUV_TYPE UNSIGNED_SHORT_8_8_MESA
00075
00076
00077 # define VLCGL_FORMAT VLCGL_RGB_FORMAT
00078 # define VLCGL_TYPE VLCGL_RGB_TYPE
00079
00080 # define VLCGL_TEXTURE_COUNT (1)
00081 #endif
00082
00083 static inline int GetAlignedSize(int i_size)
00084 {
00085
00086 int i_result = 1;
00087 while(i_result < i_size)
00088 i_result *= 2;
00089
00090 return i_result;
00091 }
00092
00093 typedef struct {
00094 vout_opengl_t *gl;
00095
00096 video_format_t fmt;
00097
00098 int tex_pixel_size;
00099 int tex_width;
00100 int tex_height;
00101
00102 GLuint texture[VLCGL_TEXTURE_COUNT];
00103 uint8_t *buffer[VLCGL_TEXTURE_COUNT];
00104
00105 picture_pool_t *pool;
00106 } vout_display_opengl_t;
00107
00108 static int vout_display_opengl_Init(vout_display_opengl_t *vgl,
00109 video_format_t *fmt,
00110 vout_opengl_t *gl)
00111 {
00112 vgl->gl = gl;
00113
00114
00115
00116 #if (defined(WORDS_BIGENDIAN) && VLCGL_FORMAT == GL_YCBCR_422_APPLE) || (VLCGL_FORMAT == YCBCR_MESA)
00117 fmt->i_chroma = VLC_CODEC_YUYV;
00118 vgl->tex_pixel_size = 2;
00119 #elif defined(GL_YCBCR_422_APPLE) && (VLCGL_FORMAT == GL_YCBCR_422_APPLE)
00120 fmt->i_chroma = VLC_CODEC_UYVY;
00121 vgl->tex_pixel_size = 2;
00122 #elif VLCGL_FORMAT == GL_RGB
00123 # if VLCGL_TYPE == GL_UNSIGNED_BYTE
00124 fmt->i_chroma = VLC_CODEC_RGB24;
00125 # if defined(WORDS_BIGENDIAN)
00126 fmt->i_rmask = 0x00ff0000;
00127 fmt->i_gmask = 0x0000ff00;
00128 fmt->i_bmask = 0x000000ff;
00129 # else
00130 fmt->i_rmask = 0x000000ff;
00131 fmt->i_gmask = 0x0000ff00;
00132 fmt->i_bmask = 0x00ff0000;
00133 # endif
00134 vgl->tex_pixel_size = 3;
00135 # else
00136 fmt->i_chroma = VLC_CODEC_RGB16;
00137 # if defined(WORDS_BIGENDIAN)
00138 fmt->i_rmask = 0x001f;
00139 fmt->i_gmask = 0x07e0;
00140 fmt->i_bmask = 0xf800;
00141 # else
00142 fmt->i_rmask = 0xf800;
00143 fmt->i_gmask = 0x07e0;
00144 fmt->i_bmask = 0x001f;
00145 # endif
00146 vgl->tex_pixel_size = 2;
00147 # endif
00148 #else
00149 fmt->i_chroma = VLC_CODEC_RGB32;
00150 # if defined(WORDS_BIGENDIAN)
00151 fmt->i_rmask = 0xff000000;
00152 fmt->i_gmask = 0x00ff0000;
00153 fmt->i_bmask = 0x0000ff00;
00154 # else
00155 fmt->i_rmask = 0x000000ff;
00156 fmt->i_gmask = 0x0000ff00;
00157 fmt->i_bmask = 0x00ff0000;
00158 # endif
00159 vgl->tex_pixel_size = 4;
00160 #endif
00161
00162 vgl->fmt = *fmt;
00163
00164
00165 #ifdef __APPLE__
00166 vgl->tex_width = fmt->i_width;
00167 vgl->tex_height = fmt->i_height;
00168 #else
00169
00170 vgl->tex_width = GetAlignedSize(fmt->i_width);
00171 vgl->tex_height = GetAlignedSize(fmt->i_height);
00172 #endif
00173
00174
00175 for (int i = 0; i < VLCGL_TEXTURE_COUNT; i++) {
00176 vgl->texture[i] = 0;
00177 vgl->buffer[i] = NULL;
00178 }
00179 vgl->pool = NULL;
00180
00181
00182 if (!vout_opengl_Lock(vgl->gl)) {
00183
00184 glDisable(GL_BLEND);
00185 glDisable(GL_DEPTH_TEST);
00186 glDepthMask(GL_FALSE);
00187 glDisable(GL_CULL_FACE);
00188 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
00189 glClear(GL_COLOR_BUFFER_BIT);
00190
00191 vout_opengl_Unlock(vgl->gl);
00192 }
00193 return VLC_SUCCESS;
00194 }
00195 static void vout_display_opengl_Clean(vout_display_opengl_t *vgl)
00196 {
00197
00198 if (!vout_opengl_Lock(vgl->gl)) {
00199
00200 glFinish();
00201 glFlush();
00202 glDeleteTextures(VLCGL_TEXTURE_COUNT, vgl->texture);
00203
00204 vout_opengl_Unlock(vgl->gl);
00205 }
00206 if (vgl->pool) {
00207 picture_pool_Delete(vgl->pool);
00208 for (int i = 0; i < VLCGL_TEXTURE_COUNT; i++)
00209 free(vgl->buffer[i]);
00210 }
00211 }
00212
00213 static int vout_display_opengl_ResetTextures(vout_display_opengl_t *vgl)
00214 {
00215 if (vout_opengl_Lock(vgl->gl))
00216 return VLC_EGENERIC;
00217
00218 glDeleteTextures(VLCGL_TEXTURE_COUNT, vgl->texture);
00219
00220 glGenTextures(VLCGL_TEXTURE_COUNT, vgl->texture);
00221 for (int i = 0; i < VLCGL_TEXTURE_COUNT; i++) {
00222 glBindTexture(VLCGL_TARGET, vgl->texture[i]);
00223
00224
00225 glTexParameterf(VLCGL_TARGET, GL_TEXTURE_PRIORITY, 1.0);
00226
00227 glTexParameteri(VLCGL_TARGET, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00228 glTexParameteri(VLCGL_TARGET, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00229
00230 glTexParameteri(VLCGL_TARGET, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00231 glTexParameteri(VLCGL_TARGET, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00232
00233 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00234
00235 #ifdef __APPLE__
00236
00237
00238 glEnable(GL_UNPACK_CLIENT_STORAGE_APPLE);
00239 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
00240
00241 #if 0
00242
00243 glTexParameteri(VLCGL_TARGET, GL_TEXTURE_STORAGE_HINT_APPLE,
00244 GL_STORAGE_CACHED_APPLE);
00245 #else
00246
00247 glTexParameteri(VLCGL_TARGET, GL_TEXTURE_STORAGE_HINT_APPLE,
00248 GL_STORAGE_SHARED_APPLE);
00249 #endif
00250 #endif
00251
00252
00253 if (vgl->buffer[i])
00254 glTexImage2D(VLCGL_TARGET, 0, 3, vgl->tex_width, vgl->tex_height,
00255 0, VLCGL_FORMAT, VLCGL_TYPE, vgl->buffer[i]);
00256 }
00257
00258 vout_opengl_Unlock(vgl->gl);
00259 return VLC_SUCCESS;
00260 }
00261
00262 #ifdef __APPLE__
00263
00264 struct picture_sys_t {
00265 vout_display_opengl_t *vgl;
00266 GLuint *texture;
00267 };
00268
00269
00270 static inline GLuint get_texture(picture_t *picture)
00271 {
00272 return *picture->p_sys->texture;
00273 }
00274
00275 static int PictureLock(picture_t *picture)
00276 {
00277 if (!picture->p_sys)
00278 return VLC_SUCCESS;
00279
00280 vout_display_opengl_t *vgl = picture->p_sys->vgl;
00281 if (!vout_opengl_Lock(vgl->gl)) {
00282
00283 glBindTexture(VLCGL_TARGET, get_texture(picture));
00284 glTexSubImage2D(VLCGL_TARGET, 0, 0, 0,
00285 vgl->fmt.i_width, vgl->fmt.i_height,
00286 VLCGL_FORMAT, VLCGL_TYPE, picture->p[0].p_pixels);
00287
00288 vout_opengl_Unlock(vgl->gl);
00289 }
00290 return VLC_SUCCESS;
00291 }
00292 static void PictureUnlock(picture_t *picture)
00293 {
00294 VLC_UNUSED(picture);
00295 }
00296 #endif
00297
00298 static picture_pool_t *vout_display_opengl_GetPool(vout_display_opengl_t *vgl)
00299 {
00300 picture_t *picture[VLCGL_TEXTURE_COUNT];
00301
00302 int i;
00303 for (i = 0; i < VLCGL_TEXTURE_COUNT; i++) {
00304
00305
00306 vgl->buffer[i] = malloc(vgl->tex_width * vgl->tex_height * vgl->tex_pixel_size);
00307 if (!vgl->buffer[i])
00308 break;
00309
00310 picture_resource_t rsc;
00311 memset(&rsc, 0, sizeof(rsc));
00312 #ifdef __APPLE__
00313 rsc.p_sys = malloc(sizeof(*rsc.p_sys));
00314 if (rsc.p_sys)
00315 {
00316 rsc.p_sys->vgl = vgl;
00317 rsc.p_sys->texture = &vgl->texture[i];
00318 }
00319 #endif
00320 rsc.p[0].p_pixels = vgl->buffer[i];
00321 rsc.p[0].i_pitch = vgl->fmt.i_width * vgl->tex_pixel_size;
00322 rsc.p[0].i_lines = vgl->fmt.i_height;
00323
00324 picture[i] = picture_NewFromResource(&vgl->fmt, &rsc);
00325 if (!picture[i]) {
00326 free(vgl->buffer[i]);
00327 vgl->buffer[i] = NULL;
00328 break;
00329 }
00330 }
00331 if (i < VLCGL_TEXTURE_COUNT)
00332 goto error;
00333
00334
00335 picture_pool_configuration_t cfg;
00336 memset(&cfg, 0, sizeof(cfg));
00337 cfg.picture_count = i;
00338 cfg.picture = picture;
00339 #ifdef __APPLE__
00340 cfg.lock = PictureLock;
00341 cfg.unlock = PictureUnlock;
00342 #endif
00343 vgl->pool = picture_pool_NewExtended(&cfg);
00344 if (!vgl->pool)
00345 goto error;
00346
00347 vout_display_opengl_ResetTextures(vgl);
00348
00349 return vgl->pool;
00350
00351 error:
00352 for (int j = 0; j < i; j++) {
00353 picture_Delete(picture[j]);
00354 vgl->buffer[j] = NULL;
00355 }
00356 return NULL;
00357 }
00358
00359 static int vout_display_opengl_Prepare(vout_display_opengl_t *vgl,
00360 picture_t *picture)
00361 {
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378 if (vout_opengl_Lock(vgl->gl))
00379 return VLC_EGENERIC;
00380
00381 #ifdef __APPLE__
00382
00383 glBindTexture(VLCGL_TARGET, get_texture(picture));
00384 #else
00385
00386 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
00387 vgl->fmt.i_width, vgl->fmt.i_height,
00388 VLCGL_FORMAT, VLCGL_TYPE, picture->p[0].p_pixels);
00389 #endif
00390
00391 vout_opengl_Unlock(vgl->gl);
00392 return VLC_SUCCESS;
00393 }
00394
00395 static int vout_display_opengl_Display(vout_display_opengl_t *vgl,
00396 const video_format_t *source)
00397 {
00398 if (vout_opengl_Lock(vgl->gl))
00399 return VLC_EGENERIC;
00400
00401
00402
00403 #if VLCGL_TARGET == GL_TEXTURE_2D
00404 const float f_normw = vgl->tex_width;
00405 const float f_normh = vgl->tex_height;
00406 #else
00407 assert(VLCGL_TARGET == GL_TEXTURE_RECTANGLE_EXT);
00408 const float f_normw = 1.0;
00409 const float f_normh = 1.0;
00410 #endif
00411
00412 float f_x = (source->i_x_offset + 0 ) / f_normw;
00413 float f_y = (source->i_y_offset + 0 ) / f_normh;
00414 float f_width = (source->i_x_offset + source->i_visible_width ) / f_normw;
00415 float f_height = (source->i_y_offset + source->i_visible_height) / f_normh;
00416
00417
00418
00419
00420
00421 glClear(GL_COLOR_BUFFER_BIT);
00422
00423 glEnable(VLCGL_TARGET);
00424
00425 glBegin(GL_POLYGON);
00426 glTexCoord2f(f_x, f_y); glVertex2f(-1.0, 1.0);
00427 glTexCoord2f(f_width, f_y); glVertex2f( 1.0, 1.0);
00428 glTexCoord2f(f_width, f_height); glVertex2f( 1.0, -1.0);
00429 glTexCoord2f(f_x, f_height); glVertex2f(-1.0, -1.0);
00430 glEnd();
00431
00432 glDisable(VLCGL_TARGET);
00433
00434 vout_opengl_Swap(vgl->gl);
00435
00436 vout_opengl_Unlock(vgl->gl);
00437 return VLC_SUCCESS;
00438 }
00439