More helper functions/defines and bugfixes

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@16118 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
reimar 2005-07-27 17:22:24 +00:00
parent 14e64d20c2
commit f467c97576
3 changed files with 153 additions and 65 deletions

View File

@ -1,3 +1,5 @@
#include <stdlib.h>
#include <string.h>
#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 <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 @@ 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
}
/**

View File

@ -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

View File

@ -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
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;