comparison libvo/vo_gl.c @ 16099:629c54dc7e0d

support for rectangular and streaming textures.
author reimar
date Tue, 26 Jul 2005 10:16:18 +0000
parents 26f5936c3fa3
children 519a307e3ccf
comparison
equal deleted inserted replaced
16098:9277070add37 16099:629c54dc7e0d
53 static GLuint osdDispList[MAX_OSD_PARTS]; 53 static GLuint osdDispList[MAX_OSD_PARTS];
54 //! How many parts the OSD currently consists of 54 //! How many parts the OSD currently consists of
55 static int osdtexCnt = 0; 55 static int osdtexCnt = 0;
56 56
57 static int use_aspect; 57 static int use_aspect;
58 static int use_rectangle;
59 static int err_shown;
58 static uint32_t image_width; 60 static uint32_t image_width;
59 static uint32_t image_height; 61 static uint32_t image_height;
60 static uint32_t image_bytes; 62 static uint32_t image_bytes;
61 static int many_fmts; 63 static int many_fmts;
64 static GLenum gl_target;
62 static GLenum gl_texfmt; 65 static GLenum gl_texfmt;
63 static GLenum gl_format; 66 static GLenum gl_format;
64 static GLenum gl_type; 67 static GLenum gl_type;
68 static int gl_buffersize;
65 69
66 static int int_pause; 70 static int int_pause;
67 71
68 static uint32_t texture_width; 72 static uint32_t texture_width;
69 static uint32_t texture_height; 73 static uint32_t texture_height;
104 #endif 108 #endif
105 vo_osd_changed(OSDTYPE_OSD); 109 vo_osd_changed(OSDTYPE_OSD);
106 } 110 }
107 } 111 }
108 112
113 static void texSize(int w, int h, int *texw, int *texh) {
114 if (use_rectangle) {
115 *texw = w; *texh = h;
116 } else {
117 *texw = 32;
118 while (*texw < w)
119 *texw *= 2;
120 *texh = 32;
121 while (*texh < h)
122 *texh *= 2;
123 }
124 }
125
109 /** 126 /**
110 * \brief Initialize a (new or reused) OpenGL context. 127 * \brief Initialize a (new or reused) OpenGL context.
111 */ 128 */
112 static int initGl(uint32_t d_width, uint32_t d_height) { 129 static int initGl(uint32_t d_width, uint32_t d_height) {
113 unsigned char *ImageData = NULL; 130 unsigned char *ImageData = NULL;
114 texture_width = 32; 131 texSize(image_width, image_height, &texture_width, &texture_height);
115 while (texture_width < image_width ||
116 texture_width < image_height)
117 texture_width *= 2;
118 texture_height = texture_width;
119 132
120 glDisable(GL_BLEND); 133 glDisable(GL_BLEND);
121 glDisable(GL_DEPTH_TEST); 134 glDisable(GL_DEPTH_TEST);
122 glDepthMask(GL_FALSE); 135 glDepthMask(GL_FALSE);
123 glDisable(GL_CULL_FACE); 136 glDisable(GL_CULL_FACE);
124 glEnable(GL_TEXTURE_2D); 137 glEnable(gl_target);
125 138
126 mp_msg(MSGT_VO, MSGL_V, "[gl] Creating %dx%d texture...\n", 139 mp_msg(MSGT_VO, MSGL_V, "[gl] Creating %dx%d texture...\n",
127 texture_width, texture_height); 140 texture_width, texture_height);
128 141
129 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); 142 glTexParameterf(gl_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
130 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR); 143 glTexParameterf(gl_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
131 144
132 glAdjustAlignment(texture_width * image_bytes); 145 glAdjustAlignment(texture_width * image_bytes);
133 ImageData = malloc(texture_width * texture_height * image_bytes); 146 ImageData = malloc(texture_width * texture_height * image_bytes);
134 memset(ImageData, 0, texture_width * texture_height * image_bytes); 147 memset(ImageData, 0, texture_width * texture_height * image_bytes);
135 glTexImage2D(GL_TEXTURE_2D, 0, gl_texfmt, texture_width, texture_height, 0, 148 glTexImage2D(gl_target, 0, gl_texfmt, texture_width, texture_height, 0,
136 gl_format, gl_type, ImageData); 149 gl_format, gl_type, ImageData);
137 free (ImageData); 150 free (ImageData);
138 151
139 // set alignment as default is 4 which will break some files 152 // set alignment as default is 4 which will break some files
140 glAdjustAlignment(image_width * image_bytes); 153 glAdjustAlignment(image_width * image_bytes);
141 154
142 resize(d_width, d_height); 155 resize(d_width, d_height);
143 156
144 glClearColor( 0.0f,0.0f,0.0f,0.0f ); 157 glClearColor( 0.0f,0.0f,0.0f,0.0f );
145 glClear( GL_COLOR_BUFFER_BIT ); 158 glClear( GL_COLOR_BUFFER_BIT );
159 gl_buffersize = 0;
160 err_shown = 0;
146 return 1; 161 return 1;
147 } 162 }
148 163
149 /* connect to server, create and map window, 164 /* connect to server, create and map window,
150 * allocate colors and (shared) memory 165 * allocate colors and (shared) memory
283 // initialize to 8 to avoid special-casing on alignment 298 // initialize to 8 to avoid special-casing on alignment
284 int sx = 8, sy = 8; 299 int sx = 8, sy = 8;
285 GLfloat xcov, ycov; 300 GLfloat xcov, ycov;
286 GLint scale_type = (scaled_osd) ? GL_LINEAR : GL_NEAREST; 301 GLint scale_type = (scaled_osd) ? GL_LINEAR : GL_NEAREST;
287 char *clearTexture; 302 char *clearTexture;
288 while (sx < w) sx *= 2; 303 texSize(w, h, &sx, &sy);
289 while (sy < h) sy *= 2;
290 xcov = (GLfloat) w / (GLfloat) sx; 304 xcov = (GLfloat) w / (GLfloat) sx;
291 ycov = (GLfloat) h / (GLfloat) sy; 305 ycov = (GLfloat) h / (GLfloat) sy;
306 if (use_rectangle == 1) {
307 xcov = w;
308 ycov = h;
309 }
292 310
293 if (osdtexCnt >= MAX_OSD_PARTS) { 311 if (osdtexCnt >= MAX_OSD_PARTS) {
294 mp_msg(MSGT_VO, MSGL_ERR, "Too many OSD parts, contact the developers!\n"); 312 mp_msg(MSGT_VO, MSGL_ERR, "Too many OSD parts, contact the developers!\n");
295 return; 313 return;
296 } 314 }
299 317
300 // create Textures for OSD part 318 // create Textures for OSD part
301 glAdjustAlignment(stride); 319 glAdjustAlignment(stride);
302 glPixelStorei(GL_UNPACK_ROW_LENGTH, stride); 320 glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
303 glGenTextures(1, &osdtex[osdtexCnt]); 321 glGenTextures(1, &osdtex[osdtexCnt]);
304 glBindTexture(GL_TEXTURE_2D, osdtex[osdtexCnt]); 322 BindTexture(gl_target, osdtex[osdtexCnt]);
305 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, sx, sy, 0, 323 glTexImage2D(gl_target, 0, GL_LUMINANCE, sx, sy, 0,
306 GL_LUMINANCE, GL_UNSIGNED_BYTE, clearTexture); 324 GL_LUMINANCE, GL_UNSIGNED_BYTE, clearTexture);
307 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, scale_type); 325 glTexParameteri(gl_target, GL_TEXTURE_MIN_FILTER, scale_type);
308 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, scale_type); 326 glTexParameteri(gl_target, GL_TEXTURE_MAG_FILTER, scale_type);
309 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_LUMINANCE, 327 glTexSubImage2D(gl_target, 0, 0, 0, w, h, GL_LUMINANCE,
310 GL_UNSIGNED_BYTE, src); 328 GL_UNSIGNED_BYTE, src);
311 329
312 #ifndef FAST_OSD 330 #ifndef FAST_OSD
313 glGenTextures(1, &osdatex[osdtexCnt]); 331 glGenTextures(1, &osdatex[osdtexCnt]);
314 glBindTexture(GL_TEXTURE_2D, osdatex[osdtexCnt]); 332 BindTexture(gl_target, osdatex[osdtexCnt]);
315 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, sx, sy, 0, 333 glTexImage2D(gl_target, 0, GL_ALPHA, sx, sy, 0,
316 GL_LUMINANCE, GL_UNSIGNED_BYTE, clearTexture); 334 GL_LUMINANCE, GL_UNSIGNED_BYTE, clearTexture);
317 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, scale_type); 335 glTexParameteri(gl_target, GL_TEXTURE_MIN_FILTER, scale_type);
318 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, scale_type); 336 glTexParameteri(gl_target, GL_TEXTURE_MAG_FILTER, scale_type);
319 for (i = 0; i < h * stride; i++) 337 for (i = 0; i < h * stride; i++)
320 clearTexture[i] = ~(-srca[i]); 338 clearTexture[i] = ~(-srca[i]);
321 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_ALPHA, 339 glTexSubImage2D(gl_target, 0, 0, 0, w, h, GL_ALPHA,
322 GL_UNSIGNED_BYTE, clearTexture); 340 GL_UNSIGNED_BYTE, clearTexture);
323 #endif 341 #endif
324 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 342 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
325 glAdjustAlignment(image_width * image_bytes); 343 glAdjustAlignment(image_width * image_bytes);
326 344
327 glBindTexture(GL_TEXTURE_2D, 0); 345 BindTexture(gl_target, 0);
328 free(clearTexture); 346 free(clearTexture);
329 347
330 // Create a list for rendering this OSD part 348 // Create a list for rendering this OSD part
331 osdDispList[osdtexCnt] = glGenLists(1); 349 osdDispList[osdtexCnt] = glGenLists(1);
332 glNewList(osdDispList[osdtexCnt], GL_COMPILE); 350 glNewList(osdDispList[osdtexCnt], GL_COMPILE);
333 #ifndef FAST_OSD 351 #ifndef FAST_OSD
334 // render alpha 352 // render alpha
335 glBlendFunc(GL_ZERO, GL_SRC_ALPHA); 353 glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
336 glBindTexture(GL_TEXTURE_2D, osdatex[osdtexCnt]); 354 BindTexture(gl_target, osdatex[osdtexCnt]);
337 glBegin(GL_QUADS); 355 glBegin(GL_QUADS);
338 glTexCoord2f (0, 0); 356 glTexCoord2f (0, 0);
339 glVertex2f (x0, y0); 357 glVertex2f (x0, y0);
340 glTexCoord2f (0, ycov); 358 glTexCoord2f (0, ycov);
341 glVertex2f (x0, y0 + h); 359 glVertex2f (x0, y0 + h);
345 glVertex2f (x0 + w, y0); 363 glVertex2f (x0 + w, y0);
346 glEnd(); 364 glEnd();
347 #endif 365 #endif
348 // render OSD 366 // render OSD
349 glBlendFunc (GL_ONE, GL_ONE); 367 glBlendFunc (GL_ONE, GL_ONE);
350 glBindTexture(GL_TEXTURE_2D, osdtex[osdtexCnt]); 368 BindTexture(gl_target, osdtex[osdtexCnt]);
351 glBegin(GL_QUADS); 369 glBegin(GL_QUADS);
352 glTexCoord2f (0, 0); 370 glTexCoord2f (0, 0);
353 glVertex2f (x0, y0); 371 glVertex2f (x0, y0);
354 glTexCoord2f (0, ycov); 372 glTexCoord2f (0, ycov);
355 glVertex2f (x0, y0 + h); 373 glVertex2f (x0, y0 + h);
385 } 403 }
386 404
387 static void 405 static void
388 flip_page(void) 406 flip_page(void)
389 { 407 {
408 int tc_x = 1, tc_y = 1;
409 if (use_rectangle == 1) {
410 tc_x = texture_width;
411 tc_y = texture_height;
412 }
390 413
391 // glEnable(GL_TEXTURE_2D); 414 // glEnable(GL_TEXTURE_2D);
392 // glBindTexture(GL_TEXTURE_2D, texture_id); 415 // glBindTexture(GL_TEXTURE_2D, texture_id);
393 416
394 glColor3f(1,1,1); 417 glColor3f(1,1,1);
395 glBegin(GL_QUADS); 418 glBegin(GL_QUADS);
396 glTexCoord2f(0,0);glVertex2i(0,0); 419 glTexCoord2f(0,0);glVertex2i(0,0);
397 glTexCoord2f(0,1);glVertex2i(0,texture_height); 420 glTexCoord2f(0,tc_y);glVertex2i(0,texture_height);
398 glTexCoord2f(1,1);glVertex2i(texture_width,texture_height); 421 glTexCoord2f(tc_x,tc_y);glVertex2i(texture_width,texture_height);
399 glTexCoord2f(1,0);glVertex2i(texture_width,0); 422 glTexCoord2f(tc_x,0);glVertex2i(texture_width,0);
400 glEnd(); 423 glEnd();
401 424
402 if (osdtexCnt > 0) { 425 if (osdtexCnt > 0) {
403 // set special rendering parameters 426 // set special rendering parameters
404 if (!scaled_osd) { 427 if (!scaled_osd) {
412 glCallLists(osdtexCnt, GL_UNSIGNED_INT, osdDispList); 435 glCallLists(osdtexCnt, GL_UNSIGNED_INT, osdDispList);
413 // set rendering parameters back to defaults 436 // set rendering parameters back to defaults
414 glDisable (GL_BLEND); 437 glDisable (GL_BLEND);
415 if (!scaled_osd) 438 if (!scaled_osd)
416 glPopMatrix(); 439 glPopMatrix();
417 glBindTexture(GL_TEXTURE_2D, 0); 440 BindTexture(gl_target, 0);
418 } 441 }
419 442
420 // glFlush(); 443 // glFlush();
421 glFinish(); 444 glFinish();
422 glXSwapBuffers( mDisplay,vo_window ); 445 glXSwapBuffers( mDisplay,vo_window );
427 450
428 //static inline uint32_t draw_slice_x11(uint8_t *src[], uint32_t slice_num) 451 //static inline uint32_t draw_slice_x11(uint8_t *src[], uint32_t slice_num)
429 static uint32_t draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y) 452 static uint32_t draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y)
430 { 453 {
431 return 0; 454 return 0;
455 }
456
457 static uint32_t get_image(mp_image_t *mpi) {
458 if (!BindBuffer || !BufferData || !MapBuffer) {
459 if (!err_shown)
460 mp_msg(MSGT_VO, MSGL_ERR, "[gl] extensions missing for dr\n"
461 "Expect a _major_ speed penalty\n");
462 return VO_FALSE;
463 }
464 if (mpi->flags & MP_IMGFLAG_READABLE) return VO_FALSE;
465 if (mpi->type == MP_IMGTYPE_STATIC) return VO_FALSE;
466 BindBuffer(GL_PIXEL_UNPACK_BUFFER, 1);
467 mpi->stride[0] = mpi->width * mpi->bpp / 8;
468 if (mpi->stride[0] * mpi->h > gl_buffersize) {
469 BufferData(GL_PIXEL_UNPACK_BUFFER, mpi->stride[0] * mpi->h,
470 NULL, GL_STREAM_DRAW);
471 gl_buffersize = mpi->stride[0] * mpi->h;
472 }
473 mpi->planes[0] = MapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
474 BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
475 mpi->flags |= MP_IMGFLAG_DIRECT;
476 return VO_TRUE;
432 } 477 }
433 478
434 static uint32_t draw_image(mp_image_t *mpi) { 479 static uint32_t draw_image(mp_image_t *mpi) {
435 char *data = mpi->planes[0]; 480 char *data = mpi->planes[0];
436 int x = mpi->x; 481 int x = mpi->x;
437 int y = mpi->y; 482 int y = mpi->y;
438 int y_max = mpi->y + mpi->h; 483 int y_max = mpi->y + mpi->h;
439 int h = slice_height ? slice_height : mpi->h; 484 int h = slice_height ? slice_height : mpi->h;
440 if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK) 485 if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
441 return VO_TRUE; 486 return VO_TRUE;
487 if (mpi->flags & MP_IMGFLAG_DIRECT) {
488 data = NULL;
489 BindBuffer(GL_PIXEL_UNPACK_BUFFER, 1);
490 UnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
491 h = mpi->h; // always "upload" full texture
492 }
442 // this is not always correct, but should work for MPlayer 493 // this is not always correct, but should work for MPlayer
443 glAdjustAlignment(mpi->stride[0]); 494 glAdjustAlignment(mpi->stride[0]);
444 glPixelStorei(GL_UNPACK_ROW_LENGTH, mpi->stride[0] / (mpi->bpp / 8)); 495 glPixelStorei(GL_UNPACK_ROW_LENGTH, mpi->stride[0] / (mpi->bpp / 8));
445 for (y = mpi->y; y + h <= y_max; y += h) { 496 for (y = mpi->y; y + h <= y_max; y += h) {
446 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, 497 glTexSubImage2D(gl_target, 0, x, y,
447 mpi->w, h, 498 mpi->w, h,
448 gl_format, gl_type, 499 gl_format, gl_type,
449 data); 500 data);
450 data += mpi->stride[0] * h; 501 data += mpi->stride[0] * h;
451 } 502 }
452 if (y < y_max) 503 if (y < y_max)
453 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, mpi->w, y_max - y, 504 glTexSubImage2D(gl_target, 0, x, y, mpi->w, y_max - y,
454 gl_format, gl_type, data); 505 gl_format, gl_type, data);
506 if (mpi->flags & MP_IMGFLAG_DIRECT)
507 BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
455 return VO_TRUE; 508 return VO_TRUE;
456 } 509 }
457 510
458 static uint32_t 511 static uint32_t
459 draw_frame(uint8_t *src[]) 512 draw_frame(uint8_t *src[])
489 {"manyfmts", OPT_ARG_BOOL, &many_fmts, NULL}, 542 {"manyfmts", OPT_ARG_BOOL, &many_fmts, NULL},
490 {"osd", OPT_ARG_BOOL, &use_osd, NULL}, 543 {"osd", OPT_ARG_BOOL, &use_osd, NULL},
491 {"scaled-osd", OPT_ARG_BOOL, &scaled_osd, NULL}, 544 {"scaled-osd", OPT_ARG_BOOL, &scaled_osd, NULL},
492 {"aspect", OPT_ARG_BOOL, &use_aspect, NULL}, 545 {"aspect", OPT_ARG_BOOL, &use_aspect, NULL},
493 {"slice-height", OPT_ARG_INT, &slice_height, (opt_test_f)int_non_neg}, 546 {"slice-height", OPT_ARG_INT, &slice_height, (opt_test_f)int_non_neg},
547 {"rectangle", OPT_ARG_INT, &use_rectangle,(opt_test_f)int_non_neg},
494 {NULL} 548 {NULL}
495 }; 549 };
496 550
497 static uint32_t preinit(const char *arg) 551 static uint32_t preinit(const char *arg)
498 { 552 {
499 // set defaults 553 // set defaults
500 many_fmts = 1; 554 many_fmts = 1;
501 use_osd = 1; 555 use_osd = 1;
502 scaled_osd = 0; 556 scaled_osd = 0;
503 use_aspect = 1; 557 use_aspect = 1;
558 use_rectangle = 0;
504 slice_height = 4; 559 slice_height = 4;
505 if (subopt_parse(arg, subopts) != 0) { 560 if (subopt_parse(arg, subopts) != 0) {
506 mp_msg(MSGT_VO, MSGL_FATAL, 561 mp_msg(MSGT_VO, MSGL_FATAL,
507 "\n-vo gl command line help:\n" 562 "\n-vo gl command line help:\n"
508 "Example: mplayer -vo gl:slice-height=4\n" 563 "Example: mplayer -vo gl:slice-height=4\n"
513 " Slice size for texture transfer, 0 for whole image\n" 568 " Slice size for texture transfer, 0 for whole image\n"
514 " noosd\n" 569 " noosd\n"
515 " Do not use OpenGL OSD code\n" 570 " Do not use OpenGL OSD code\n"
516 " noaspect\n" 571 " noaspect\n"
517 " Do not do aspect scaling\n" 572 " Do not do aspect scaling\n"
573 " rectangle=<0,1,2>\n"
574 " 0: use power-of-two textures\n"
575 " 1: use texture_rectangle\n"
576 " 2: use texture_non_power_of_two\n"
518 "\n" ); 577 "\n" );
519 return -1; 578 return -1;
520 } 579 }
580 if (use_rectangle == 1)
581 gl_target = GL_TEXTURE_RECTANGLE;
582 else
583 gl_target = GL_TEXTURE_2D;
521 if (many_fmts) 584 if (many_fmts)
522 mp_msg (MSGT_VO, MSGL_WARN, "[gl] using extended formats.\n" 585 mp_msg (MSGT_VO, MSGL_WARN, "[gl] using extended formats.\n"
523 "Make sure you have OpenGL >= 1.2 and used corresponding " 586 "Make sure you have OpenGL >= 1.2 and used corresponding "
524 "headers for compiling!\n"); 587 "headers for compiling!\n");
525 mp_msg (MSGT_VO, MSGL_INFO, "[gl] Using %d as slice height " 588 mp_msg (MSGT_VO, MSGL_INFO, "[gl] Using %d as slice height "
534 switch (request) { 597 switch (request) {
535 case VOCTRL_PAUSE: return (int_pause=1); 598 case VOCTRL_PAUSE: return (int_pause=1);
536 case VOCTRL_RESUME: return (int_pause=0); 599 case VOCTRL_RESUME: return (int_pause=0);
537 case VOCTRL_QUERY_FORMAT: 600 case VOCTRL_QUERY_FORMAT:
538 return query_format(*((uint32_t*)data)); 601 return query_format(*((uint32_t*)data));
602 case VOCTRL_GET_IMAGE:
603 return get_image(data);
539 case VOCTRL_DRAW_IMAGE: 604 case VOCTRL_DRAW_IMAGE:
540 return draw_image(data); 605 return draw_image(data);
541 case VOCTRL_GUISUPPORT: 606 case VOCTRL_GUISUPPORT:
542 return VO_TRUE; 607 return VO_TRUE;
543 case VOCTRL_ONTOP: 608 case VOCTRL_ONTOP: