From f467c975765552fd92aa06cffb26a1311d05cf98 Mon Sep 17 00:00:00 2001 From: reimar Date: Wed, 27 Jul 2005 17:22:24 +0000 Subject: More helper functions/defines and bugfixes git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@16118 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libvo/gl_common.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++----- libvo/gl_common.h | 30 +++++++++++++++ libvo/vo_gl.c | 78 +++++++++++--------------------------- 3 files changed, 153 insertions(+), 65 deletions(-) (limited to 'libvo') diff --git a/libvo/gl_common.c b/libvo/gl_common.c index 20e39b9af1..e68bc75d69 100644 --- a/libvo/gl_common.c +++ b/libvo/gl_common.c @@ -1,3 +1,5 @@ +#include +#include #include "gl_common.h" void (APIENTRY *BindBuffer)(GLenum, GLuint); @@ -57,23 +59,19 @@ static const struct gl_name_map_struct gl_name_map[] = { 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 @@ int glFindFormat(uint32_t fmt, uint32_t *bpp, GLenum *gl_texfmt, *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 @@ int glFindFormat(uint32_t fmt, uint32_t *bpp, GLenum *gl_texfmt, *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 *setNull(const GLubyte *s) { 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 @@ static void getFunctions() { 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 @@ void releaseGlContext(int *vinfo, HGLRC *context) { *context = 0; } #else -#if defined(__sun) || defined(__sgi) -extern void *dlopen(const char *, int); +#ifdef HAVE_LIBDL +#include #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 @@ extern void *dlsym(void *, const char *); * 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 } /** diff --git a/libvo/gl_common.h b/libvo/gl_common.h index 62d34ef5fd..e4e442b3c6 100644 --- a/libvo/gl_common.h +++ b/libvo/gl_common.h @@ -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 @@ const char *glValName(GLint value); 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 diff --git a/libvo/vo_gl.c b/libvo/vo_gl.c index b7933a6dde..e3a513e60a 100644 --- a/libvo/vo_gl.c +++ b/libvo/vo_gl.c @@ -64,7 +64,6 @@ static int use_rectangle; 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 @@ static void texSize(int w, int h, int *texw, int *texh) { * \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 @@ static int initGl(uint32_t d_width, uint32_t d_height) { 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 int initGl(uint32_t d_width, uint32_t d_height) { 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 @@ static void create_osd_texture(int x0, int y0, int w, int h, 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 @@ static void create_osd_texture(int x0, int y0, int w, int h, 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 @@ static uint32_t get_image(mp_image_t *mpi) { 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 @@ static uint32_t get_image(mp_image_t *mpi) { 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 get_image(mp_image_t *mpi) { 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 - } - // 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; + slice = 0; // always "upload" full texture } - 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; -- cgit v1.2.3