changeset 16117:d280ec2b9e63

More helper functions/defines and bugfixes
author reimar
date Wed, 27 Jul 2005 17:22:24 +0000
parents 86ae36aac3ba
children 322e569c47bd
files libvo/gl_common.c libvo/gl_common.h libvo/vo_gl.c
diffstat 3 files changed, 153 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/libvo/gl_common.c	Wed Jul 27 15:38:52 2005 +0000
+++ b/libvo/gl_common.c	Wed Jul 27 17:22:24 2005 +0000
@@ -1,3 +1,5 @@
+#include <stdlib.h>
+#include <string.h>
 #include "gl_common.h"
 
 void (APIENTRY *BindBuffer)(GLenum, GLuint);
@@ -57,23 +59,19 @@
   MAP(GL_ALPHA), MAP(GL_LUMINANCE), MAP(GL_LUMINANCE_ALPHA),
   MAP(GL_COLOR_INDEX),
   // rest 1.2 only
-#ifdef GL_VERSION_1_2
   MAP(GL_BGR), MAP(GL_BGRA),
-#endif
 
   //type
   MAP(GL_BYTE), MAP(GL_UNSIGNED_BYTE), MAP(GL_SHORT), MAP(GL_UNSIGNED_SHORT),
   MAP(GL_INT), MAP(GL_UNSIGNED_INT), MAP(GL_FLOAT), MAP(GL_DOUBLE),
   MAP(GL_2_BYTES), MAP(GL_3_BYTES), MAP(GL_4_BYTES),
   // rest 1.2 only
-#ifdef GL_VERSION_1_2
   MAP(GL_UNSIGNED_BYTE_3_3_2), MAP(GL_UNSIGNED_BYTE_2_3_3_REV),
   MAP(GL_UNSIGNED_SHORT_5_6_5), MAP(GL_UNSIGNED_SHORT_5_6_5_REV),
   MAP(GL_UNSIGNED_SHORT_4_4_4_4), MAP(GL_UNSIGNED_SHORT_4_4_4_4_REV),
   MAP(GL_UNSIGNED_SHORT_5_5_5_1), MAP(GL_UNSIGNED_SHORT_1_5_5_5_REV),
   MAP(GL_UNSIGNED_INT_8_8_8_8), MAP(GL_UNSIGNED_INT_8_8_8_8_REV),
   MAP(GL_UNSIGNED_INT_10_10_10_2), MAP(GL_UNSIGNED_INT_2_10_10_10_REV),
-#endif
   {0, 0}
 };
 #undef MAP
@@ -140,7 +138,6 @@
       *gl_format = GL_LUMINANCE;
       *gl_type = GL_UNSIGNED_BYTE;
       break;
-#ifdef GL_VERSION_1_2
 #if 0
     // we do not support palettized formats, although the format the
     // swscale produces works
@@ -184,7 +181,6 @@
       *gl_format = GL_BGRA;
       *gl_type = GL_UNSIGNED_BYTE;
       break;
-#endif
     default:
       *gl_texfmt = 4;
       *gl_format = GL_RGBA;
@@ -203,6 +199,9 @@
 
 static void *(*getProcAddress)(const GLubyte *procName) = NULL;
 
+/**
+ * \brief find the function pointers of some useful OpenGL extensions
+ */
 static void getFunctions() {
   if (!getProcAddress)
     getProcAddress = setNull;
@@ -256,6 +255,96 @@
     ProgramEnvParameter4f = getProcAddress("glProgramEnvParameter4fNV");
 }
 
+/**
+ * \brief create a texture and set some defaults
+ * \param target texture taget, usually GL_TEXTURE_2D
+ * \param fmt internal texture format
+ * \param filter filter used for scaling, e.g. GL_LINEAR
+ * \param w texture width
+ * \param h texture height
+ * \param val luminance value to fill texture with
+ */
+void glCreateClearTex(GLenum target, GLenum fmt, GLint filter,
+                      int w, int h, char val) {
+  GLenum clrfmt = (fmt == GL_ALPHA) ? GL_ALPHA : GL_LUMINANCE;
+  char *init = (char *)malloc(w * h);
+  memset(init, val, w * h);
+  glAdjustAlignment(w);
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, w);
+  glTexImage2D(target, 0, fmt, w, h, 0, clrfmt, GL_UNSIGNED_BYTE, init);
+  glTexParameterf(target, GL_TEXTURE_PRIORITY, 1.0);
+  glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
+  glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
+  glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP);
+  glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP);
+  free(init);
+}
+
+/**
+ * \brief return the number of bytes oer pixel for the given format
+ * \param format OpenGL format
+ * \param type OpenGL type
+ * \return bytes per pixel
+ *
+ * Does not handle all possible variants, just those use by MPlayer
+ */
+int glFmt2bpp(GLenum format, GLenum type) {
+  switch (type) {
+    case GL_UNSIGNED_BYTE_3_3_2:
+    case GL_UNSIGNED_BYTE_2_3_3_REV:
+      return 1;
+    case GL_UNSIGNED_SHORT_5_5_5_1:
+    case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+    case GL_UNSIGNED_SHORT_5_6_5:
+    case GL_UNSIGNED_SHORT_5_6_5_REV:
+      return 2;
+  }
+  if (type != GL_UNSIGNED_BYTE)
+    return 0; //not implemented
+  switch (format) {
+    case GL_LUMINANCE:
+    case GL_ALPHA:
+      return 1;
+    case GL_RGB:
+    case GL_BGR:
+      return 3;
+    case GL_RGBA:
+    case GL_BGRA:
+      return 4;
+  }
+  return 0; // unkown
+}
+
+/**
+ * \brief upload a texture, handling things like stride and slices
+ * \param target texture target, usually GL_TEXTURE_2D
+ * \param format OpenGL format of data
+ * \param type OpenGL type of data
+ * \param data data to upload
+ * \param stride data stride
+ * \param x x offset in texture
+ * \param y y offset in texture
+ * \param w width of the texture part to upload
+ * \param h height of the texture part to upload
+ * \param slice height of an upload slice, 0 for all at once
+ */
+void glUploadTex(GLenum target, GLenum format, GLenum type,
+                 const char *data, int stride,
+                 int x, int y, int w, int h, int slice) {
+  int y_max = y + h;
+  if (slice <= 0)
+    slice = h;
+  // this is not always correct, but should work for MPlayer
+  glAdjustAlignment(stride);
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / glFmt2bpp(format, type));
+  for (; y + slice <= y_max; y += slice) {
+    glTexSubImage2D(target, 0, x, y, w, slice, format, type, data);
+    data += stride * slice;
+  }
+  if (y < y_max)
+    glTexSubImage2D(target, 0, x, y, w, y_max - y, format, type, data);
+}
+
 #ifdef GL_WIN32
 static void *w32gpa(const GLubyte *procName) {
   return wglGetProcAddress(procName);
@@ -326,10 +415,9 @@
   *context = 0;
 }
 #else
-#if defined(__sun) || defined(__sgi)
-extern void *dlopen(const char *, int);
+#ifdef HAVE_LIBDL
+#include <dlfcn.h>
 #endif
-extern void *dlsym(void *, const char *);
 /**
  * \brief find address of a linked function
  * \param s name of function to find
@@ -338,12 +426,16 @@
  * Copied from xine
  */
 static void *getdladdr(const GLubyte *s) {
+#ifdef HAVE_LIBDL
 #if defined(__sun) || defined(__sgi)
   static void *handle = dlopen(NULL, RTLD_LAZY);
   return dlsym(handle, s);
 #else
   return dlsym(0, s);
 #endif
+#else
+  return NULL;
+#endif
 }
 
 /**
--- a/libvo/gl_common.h	Wed Jul 27 15:38:52 2005 +0000
+++ b/libvo/gl_common.h	Wed Jul 27 17:22:24 2005 +0000
@@ -29,6 +29,30 @@
 #ifndef GL_WRITE_ONLY
 #define GL_WRITE_ONLY 0x88B9
 #endif
+#ifndef GL_BGR
+#define GL_BGR 0x80E0
+#endif
+#ifndef GL_BGRA
+#define GL_BGRA 0x80E1
+#endif
+#ifndef GL_UNSIGNED_BYTE_3_3_2
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#endif
+#ifndef GL_UNSIGNED_BYTE_2_3_3_REV
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#endif
+#ifndef GL_UNSIGNED_SHORT_5_6_5
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#endif
+#ifndef GL_UNSIGNED_SHORT_5_6_5_REV
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#endif
+#ifndef GL_UNSIGNED_SHORT_5_5_5_1
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#endif
+#ifndef GL_UNSIGNED_SHORT_1_5_5_5_REV
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#endif
 
 void glAdjustAlignment(int stride);
 
@@ -36,6 +60,12 @@
 
 int glFindFormat(uint32_t format, uint32_t *bpp, GLenum *gl_texfmt,
                   GLenum *gl_format, GLenum *gl_type);
+int glFmt2bpp(GLenum format, GLenum type);
+void glCreateClearTex(GLenum target, GLenum fmt, GLint filter,
+                      int w, int h, char val);
+void glUploadTex(GLenum target, GLenum format, GLenum type,
+                 const char *data, int stride,
+                 int x, int y, int w, int h, int slice);
 
 //! could not set new window, will continue drawing into the old one.
 #define SET_WINDOW_FAILED -1
--- a/libvo/vo_gl.c	Wed Jul 27 15:38:52 2005 +0000
+++ b/libvo/vo_gl.c	Wed Jul 27 17:22:24 2005 +0000
@@ -64,7 +64,6 @@
 static int err_shown;
 static uint32_t image_width;
 static uint32_t image_height;
-static uint32_t image_bytes;
 static int many_fmts;
 static GLenum gl_target;
 static GLenum gl_texfmt;
@@ -134,7 +133,6 @@
  * \brief Initialize a (new or reused) OpenGL context.
  */
 static int initGl(uint32_t d_width, uint32_t d_height) {
-  unsigned char *ImageData = NULL;
   texSize(image_width, image_height, &texture_width, &texture_height);
 
   glDisable(GL_BLEND); 
@@ -146,18 +144,8 @@
   mp_msg(MSGT_VO, MSGL_V, "[gl] Creating %dx%d texture...\n",
           texture_width, texture_height);
 
-  glTexParameterf(gl_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  glTexParameterf(gl_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-
-  glAdjustAlignment(texture_width * image_bytes);
-  ImageData = malloc(texture_width * texture_height * image_bytes);
-  memset(ImageData, 0, texture_width * texture_height * image_bytes);
-  glTexImage2D(gl_target, 0, gl_texfmt, texture_width, texture_height, 0,
-       gl_format, gl_type, ImageData);
-  free (ImageData);
-
-  // set alignment as default is 4 which will break some files
-  glAdjustAlignment(image_width * image_bytes);
+  glCreateClearTex(gl_target, gl_texfmt, GL_LINEAR,
+                   texture_width, texture_height, 0);
 
   resize(d_width, d_height);
 
@@ -174,10 +162,10 @@
 static uint32_t 
 config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format)
 {
+	int tmp;
 	image_height = height;
 	image_width = width;
-	glFindFormat(format, &image_bytes, &gl_texfmt, &gl_format, &gl_type);
-	image_bytes = (image_bytes + 7) / 8;
+	glFindFormat(format, &tmp, &gl_texfmt, &gl_format, &gl_type);
 
 	int_pause = 0;
 
@@ -321,7 +309,6 @@
   int sx = 8, sy = 8;
   GLfloat xcov, ycov;
   GLint scale_type = (scaled_osd) ? GL_LINEAR : GL_NEAREST;
-  char *clearTexture;
   texSize(w, h, &sx, &sy);
   xcov = (GLfloat) w / (GLfloat) sx;
   ycov = (GLfloat) h / (GLfloat) sy;
@@ -334,38 +321,29 @@
     mp_msg(MSGT_VO, MSGL_ERR, "Too many OSD parts, contact the developers!\n");
     return;
   }
-  clearTexture = malloc(sx * sy);
-  memset(clearTexture, 0, sx * sy);
 
   // create Textures for OSD part
-  glAdjustAlignment(stride);
-  glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
   glGenTextures(1, &osdtex[osdtexCnt]);
   BindTexture(gl_target, osdtex[osdtexCnt]);
-  glTexImage2D(gl_target, 0, GL_LUMINANCE, sx, sy, 0,
-                 GL_LUMINANCE, GL_UNSIGNED_BYTE, clearTexture);
-  glTexParameteri(gl_target, GL_TEXTURE_MIN_FILTER, scale_type);
-  glTexParameteri(gl_target, GL_TEXTURE_MAG_FILTER, scale_type);
-  glTexSubImage2D(gl_target, 0, 0, 0, w, h, GL_LUMINANCE,
-                    GL_UNSIGNED_BYTE, src);
+  glCreateClearTex(gl_target, GL_LUMINANCE, scale_type, sx, sy, 0);
+  glUploadTex(gl_target, GL_LUMINANCE, GL_UNSIGNED_BYTE, src, stride,
+              0, 0, w, h, 0);
 
 #ifndef FAST_OSD
   glGenTextures(1, &osdatex[osdtexCnt]);
   BindTexture(gl_target, osdatex[osdtexCnt]);
-  glTexImage2D(gl_target, 0, GL_ALPHA, sx, sy, 0,
-                 GL_LUMINANCE, GL_UNSIGNED_BYTE, clearTexture);
-  glTexParameteri(gl_target, GL_TEXTURE_MIN_FILTER, scale_type);
-  glTexParameteri(gl_target, GL_TEXTURE_MAG_FILTER, scale_type);
+  glCreateClearTex(gl_target, GL_ALPHA, scale_type, sx, sy, 0);
+  {
+  char *tmp = (char *)malloc(stride * h);
   for (i = 0; i < h * stride; i++)
-    clearTexture[i] = ~(-srca[i]);
-  glTexSubImage2D(gl_target, 0, 0, 0, w, h, GL_ALPHA,
-                    GL_UNSIGNED_BYTE, clearTexture);
+    tmp[i] = ~(-srca[i]);
+  glUploadTex(gl_target, GL_ALPHA, GL_UNSIGNED_BYTE, tmp, stride,
+              0, 0, w, h, 0);
+  free(tmp);
+  }
 #endif
-  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-  glAdjustAlignment(image_width * image_bytes);
 
   BindTexture(gl_target, 0);
-  free(clearTexture);
 
   // Create a list for rendering this OSD part
   osdDispList[osdtexCnt] = glGenLists(1);
@@ -489,7 +467,8 @@
     return VO_FALSE;
   }
   if (mpi->flags & MP_IMGFLAG_READABLE) return VO_FALSE;
-  if (mpi->type == MP_IMGTYPE_STATIC) return VO_FALSE;
+  if (mpi->type == MP_IMGTYPE_IP || mpi->type == MP_IMGTYPE_IPB)
+    return VO_FALSE; // we can not provide readable buffers
   BindBuffer(GL_PIXEL_UNPACK_BUFFER, 1);
   mpi->stride[0] = mpi->width * mpi->bpp / 8;
   if (mpi->stride[0] * mpi->h > gl_buffersize) {
@@ -497,6 +476,7 @@
                NULL, GL_STREAM_DRAW);
     gl_buffersize = mpi->stride[0] * mpi->h;
   }
+  UnmapBuffer(GL_PIXEL_UNPACK_BUFFER); // HACK, needed for some MPEG4 files??
   mpi->planes[0] = MapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
   BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
   if (mpi->planes[0] == NULL) {
@@ -512,31 +492,17 @@
 
 static uint32_t draw_image(mp_image_t *mpi) {
   char *data = mpi->planes[0];
-  int x = mpi->x;
-  int y = mpi->y;
-  int y_max = mpi->y + mpi->h;
-  int h = slice_height ? slice_height : mpi->h;
+  int slice = slice_height;
   if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
     return VO_TRUE;
   if (mpi->flags & MP_IMGFLAG_DIRECT) {
     data = NULL;
     BindBuffer(GL_PIXEL_UNPACK_BUFFER, 1);
     UnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
-    h = mpi->h; // always "upload" full texture
+    slice = 0; // always "upload" full texture
   }
-  // this is not always correct, but should work for MPlayer
-  glAdjustAlignment(mpi->stride[0]);
-  glPixelStorei(GL_UNPACK_ROW_LENGTH, mpi->stride[0] / (mpi->bpp / 8));
-  for (y = mpi->y; y + h <= y_max; y += h) {
-    glTexSubImage2D(gl_target, 0, x, y,
-                    mpi->w, h,
-                    gl_format, gl_type,
-                    data);
-    data += mpi->stride[0] * h;
-  }
-  if (y < y_max)
-    glTexSubImage2D(gl_target, 0, x, y, mpi->w, y_max - y,
-                    gl_format, gl_type, data);
+  glUploadTex(gl_target, gl_format, gl_type, data, mpi->stride[0],
+              mpi->x, mpi->y, mpi->w, mpi->h, slice);
   if (mpi->flags & MP_IMGFLAG_DIRECT)
     BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
   return VO_TRUE;