From c852246cdf3e2604d1a3bff1fccd981d7b3b58c9 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 25 Sep 2011 11:18:07 +0200 Subject: vo_gl: convert to new API, clean up code Reformat vo_gl.c, gl_common.c, gl_common.h. Remove all global variables and move them into a context struct (the Windows and SDL backends still refer to global_vo though). Change vo_gl.c to use the "new" VO API. --- libvo/gl_common.c | 2928 +++++++++++++++++++++++++++-------------------------- libvo/gl_common.h | 312 +++--- libvo/vo_gl.c | 2485 ++++++++++++++++++++++++--------------------- 3 files changed, 2980 insertions(+), 2745 deletions(-) diff --git a/libvo/gl_common.c b/libvo/gl_common.c index eb12d79a74..16e05fb688 100644 --- a/libvo/gl_common.c +++ b/libvo/gl_common.c @@ -32,115 +32,19 @@ * \brief OpenGL helper functions used by vo_gl.c and vo_gl2.c */ +#include #include #include #include #include #include -#include "old_vo_defines.h" +#include "talloc.h" #include "gl_common.h" +#include "old_vo_wrapper.h" #include "csputils.h" #include "aspect.h" #include "pnm_loader.h" - -void (GLAPIENTRY *mpglBegin)(GLenum); -void (GLAPIENTRY *mpglEnd)(void); -void (GLAPIENTRY *mpglViewport)(GLint, GLint, GLsizei, GLsizei); -void (GLAPIENTRY *mpglMatrixMode)(GLenum); -void (GLAPIENTRY *mpglLoadIdentity)(void); -void (GLAPIENTRY *mpglTranslated)(double, double, double); -void (GLAPIENTRY *mpglScaled)(double, double, double); -void (GLAPIENTRY *mpglOrtho)(double, double, double, double, double, double); -void (GLAPIENTRY *mpglFrustum)(double, double, double, double, double, double); -void (GLAPIENTRY *mpglPushMatrix)(void); -void (GLAPIENTRY *mpglPopMatrix)(void); -void (GLAPIENTRY *mpglClear)(GLbitfield); -GLuint (GLAPIENTRY *mpglGenLists)(GLsizei); -void (GLAPIENTRY *mpglDeleteLists)(GLuint, GLsizei); -void (GLAPIENTRY *mpglNewList)(GLuint, GLenum); -void (GLAPIENTRY *mpglEndList)(void); -void (GLAPIENTRY *mpglCallList)(GLuint); -void (GLAPIENTRY *mpglCallLists)(GLsizei, GLenum, const GLvoid *); -void (GLAPIENTRY *mpglGenTextures)(GLsizei, GLuint *); -void (GLAPIENTRY *mpglDeleteTextures)(GLsizei, const GLuint *); -void (GLAPIENTRY *mpglTexEnvf)(GLenum, GLenum, GLfloat); -void (GLAPIENTRY *mpglTexEnvi)(GLenum, GLenum, GLint); -void (GLAPIENTRY *mpglColor4ub)(GLubyte, GLubyte, GLubyte, GLubyte); -void (GLAPIENTRY *mpglColor3f)(GLfloat, GLfloat, GLfloat); -void (GLAPIENTRY *mpglColor4f)(GLfloat, GLfloat, GLfloat, GLfloat); -void (GLAPIENTRY *mpglClearColor)(GLclampf, GLclampf, GLclampf, GLclampf); -void (GLAPIENTRY *mpglClearDepth)(GLclampd); -void (GLAPIENTRY *mpglDepthFunc)(GLenum); -void (GLAPIENTRY *mpglEnable)(GLenum); -void (GLAPIENTRY *mpglDisable)(GLenum); -const GLubyte *(GLAPIENTRY *mpglGetString)(GLenum); -void (GLAPIENTRY *mpglDrawBuffer)(GLenum); -void (GLAPIENTRY *mpglDepthMask)(GLboolean); -void (GLAPIENTRY *mpglBlendFunc)(GLenum, GLenum); -void (GLAPIENTRY *mpglFlush)(void); -void (GLAPIENTRY *mpglFinish)(void); -void (GLAPIENTRY *mpglPixelStorei)(GLenum, GLint); -void (GLAPIENTRY *mpglTexImage1D)(GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, const GLvoid *); -void (GLAPIENTRY *mpglTexImage2D)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); -void (GLAPIENTRY *mpglTexSubImage2D)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); -void (GLAPIENTRY *mpglTexParameteri)(GLenum, GLenum, GLint); -void (GLAPIENTRY *mpglTexParameterf)(GLenum, GLenum, GLfloat); -void (GLAPIENTRY *mpglTexParameterfv)(GLenum, GLenum, const GLfloat *); -void (GLAPIENTRY *mpglTexCoord2f)(GLfloat, GLfloat); -void (GLAPIENTRY *mpglVertex2f)(GLfloat, GLfloat); -void (GLAPIENTRY *mpglVertex3f)(GLfloat, GLfloat, GLfloat); -void (GLAPIENTRY *mpglNormal3f)(GLfloat, GLfloat, GLfloat); -void (GLAPIENTRY *mpglLightfv)(GLenum, GLenum, const GLfloat *); -void (GLAPIENTRY *mpglColorMaterial)(GLenum, GLenum); -void (GLAPIENTRY *mpglShadeModel)(GLenum); -void (GLAPIENTRY *mpglGetIntegerv)(GLenum, GLint *); -void (GLAPIENTRY *mpglColorMask)(GLboolean, GLboolean, GLboolean, GLboolean); - -/** - * \defgroup glextfunctions OpenGL extension functions - * - * the pointers to these functions are acquired when the OpenGL - * context is created - * \{ - */ -void (GLAPIENTRY *mpglGenBuffers)(GLsizei, GLuint *); -void (GLAPIENTRY *mpglDeleteBuffers)(GLsizei, const GLuint *); -void (GLAPIENTRY *mpglBindBuffer)(GLenum, GLuint); -GLvoid* (GLAPIENTRY *mpglMapBuffer)(GLenum, GLenum); -GLboolean (GLAPIENTRY *mpglUnmapBuffer)(GLenum); -void (GLAPIENTRY *mpglBufferData)(GLenum, intptr_t, const GLvoid *, GLenum); -void (GLAPIENTRY *mpglCombinerParameterfv)(GLenum, const GLfloat *); -void (GLAPIENTRY *mpglCombinerParameteri)(GLenum, GLint); -void (GLAPIENTRY *mpglCombinerInput)(GLenum, GLenum, GLenum, GLenum, GLenum, - GLenum); -void (GLAPIENTRY *mpglCombinerOutput)(GLenum, GLenum, GLenum, GLenum, GLenum, - GLenum, GLenum, GLboolean, GLboolean, - GLboolean); -void (GLAPIENTRY *mpglBeginFragmentShader)(void); -void (GLAPIENTRY *mpglEndFragmentShader)(void); -void (GLAPIENTRY *mpglSampleMap)(GLuint, GLuint, GLenum); -void (GLAPIENTRY *mpglColorFragmentOp2)(GLenum, GLuint, GLuint, GLuint, GLuint, - GLuint, GLuint, GLuint, GLuint, GLuint); -void (GLAPIENTRY *mpglColorFragmentOp3)(GLenum, GLuint, GLuint, GLuint, GLuint, - GLuint, GLuint, GLuint, GLuint, GLuint, - GLuint, GLuint, GLuint); -void (GLAPIENTRY *mpglSetFragmentShaderConstant)(GLuint, const GLfloat *); -void (GLAPIENTRY *mpglActiveTexture)(GLenum); -void (GLAPIENTRY *mpglBindTexture)(GLenum, GLuint); -void (GLAPIENTRY *mpglMultiTexCoord2f)(GLenum, GLfloat, GLfloat); -void (GLAPIENTRY *mpglGenPrograms)(GLsizei, GLuint *); -void (GLAPIENTRY *mpglDeletePrograms)(GLsizei, const GLuint *); -void (GLAPIENTRY *mpglBindProgram)(GLenum, GLuint); -void (GLAPIENTRY *mpglProgramString)(GLenum, GLenum, GLsizei, const GLvoid *); -void (GLAPIENTRY *mpglGetProgramiv)(GLenum, GLenum, GLint *); -void (GLAPIENTRY *mpglProgramEnvParameter4f)(GLenum, GLuint, GLfloat, GLfloat, - GLfloat, GLfloat); -int (GLAPIENTRY *mpglSwapInterval)(int); -void (GLAPIENTRY *mpglTexImage3D)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, - GLint, GLenum, GLenum, const GLvoid *); -void* (GLAPIENTRY *mpglAllocateMemoryMESA)(void *, int, size_t, float, float, float); -void (GLAPIENTRY *mpglFreeMemoryMESA)(void *, int, void *); -/** \} */ // end of glextfunctions group +#include "options.h" //! \defgroup glgeneral OpenGL general helper functions @@ -150,60 +54,59 @@ void (GLAPIENTRY *mpglFreeMemoryMESA)(void *, int, void *); //! \defgroup glconversion OpenGL conversion helper functions -static GLint hqtexfmt; - /** * \brief adjusts the GL_UNPACK_ALIGNMENT to fit the stride. * \param stride number of bytes per line for which alignment should fit. * \ingroup glgeneral */ -void glAdjustAlignment(int stride) { - GLint gl_alignment; - if (stride % 8 == 0) - gl_alignment=8; - else if (stride % 4 == 0) - gl_alignment=4; - else if (stride % 2 == 0) - gl_alignment=2; - else - gl_alignment=1; - mpglPixelStorei(GL_UNPACK_ALIGNMENT, gl_alignment); +void glAdjustAlignment(GL *gl, int stride) +{ + GLint gl_alignment; + if (stride % 8 == 0) + gl_alignment = 8; + else if (stride % 4 == 0) + gl_alignment = 4; + else if (stride % 2 == 0) + gl_alignment = 2; + else + gl_alignment = 1; + gl->PixelStorei(GL_UNPACK_ALIGNMENT, gl_alignment); } struct gl_name_map_struct { - GLint value; - const char *name; + GLint value; + const char *name; }; #undef MAP -#define MAP(a) {a, #a} +#define MAP(a) {a, # a} //! mapping table for the glValName function static const struct gl_name_map_struct gl_name_map[] = { - // internal format - MAP(GL_R3_G3_B2), MAP(GL_RGB4), MAP(GL_RGB5), MAP(GL_RGB8), - MAP(GL_RGB10), MAP(GL_RGB12), MAP(GL_RGB16), MAP(GL_RGBA2), - MAP(GL_RGBA4), MAP(GL_RGB5_A1), MAP(GL_RGBA8), MAP(GL_RGB10_A2), - MAP(GL_RGBA12), MAP(GL_RGBA16), MAP(GL_LUMINANCE8), MAP(GL_LUMINANCE16), - - // format - MAP(GL_RGB), MAP(GL_RGBA), MAP(GL_RED), MAP(GL_GREEN), MAP(GL_BLUE), - MAP(GL_ALPHA), MAP(GL_LUMINANCE), MAP(GL_LUMINANCE_ALPHA), - MAP(GL_COLOR_INDEX), - // rest 1.2 only - MAP(GL_BGR), MAP(GL_BGRA), - - //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 - 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), - {0, 0} + // internal format + MAP(GL_R3_G3_B2), MAP(GL_RGB4), MAP(GL_RGB5), MAP(GL_RGB8), + MAP(GL_RGB10), MAP(GL_RGB12), MAP(GL_RGB16), MAP(GL_RGBA2), + MAP(GL_RGBA4), MAP(GL_RGB5_A1), MAP(GL_RGBA8), MAP(GL_RGB10_A2), + MAP(GL_RGBA12), MAP(GL_RGBA16), MAP(GL_LUMINANCE8), MAP(GL_LUMINANCE16), + + // format + MAP(GL_RGB), MAP(GL_RGBA), MAP(GL_RED), MAP(GL_GREEN), MAP(GL_BLUE), + MAP(GL_ALPHA), MAP(GL_LUMINANCE), MAP(GL_LUMINANCE_ALPHA), + MAP(GL_COLOR_INDEX), + // rest 1.2 only + MAP(GL_BGR), MAP(GL_BGRA), + + //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 + 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), + {0, 0} }; #undef MAP @@ -215,14 +118,14 @@ static const struct gl_name_map_struct gl_name_map[] = { */ const char *glValName(GLint value) { - int i = 0; - - while (gl_name_map[i].name) { - if (gl_name_map[i].value == value) - return gl_name_map[i].name; - i++; - } - return "Unknown format!"; + int i = 0; + + while (gl_name_map[i].name) { + if (gl_name_map[i].value == value) + return gl_name_map[i].name; + i++; + } + return "Unknown format!"; } //! always return this format as internal texture format in glFindFormat @@ -243,121 +146,125 @@ const char *glValName(GLint value) * \ingroup gltexture */ int glFindFormat(uint32_t fmt, int *bpp, GLint *gl_texfmt, - GLenum *gl_format, GLenum *gl_type) + GLenum *gl_format, GLenum *gl_type) { - int supported = 1; - int dummy1; - GLenum dummy2; - GLint dummy3; - if (!bpp) bpp = &dummy1; - if (!gl_texfmt) gl_texfmt = &dummy3; - if (!gl_format) gl_format = &dummy2; - if (!gl_type) gl_type = &dummy2; - - if (mp_get_chroma_shift(fmt, NULL, NULL, NULL)) { - // reduce the possible cases a bit - if (IMGFMT_IS_YUVP16_LE(fmt)) - fmt = IMGFMT_420P16_LE; - else if (IMGFMT_IS_YUVP16_BE(fmt)) - fmt = IMGFMT_420P16_BE; - else - fmt = IMGFMT_YV12; - } + int supported = 1; + int dummy1; + GLenum dummy2; + GLint dummy3; + if (!bpp) + bpp = &dummy1; + if (!gl_texfmt) + gl_texfmt = &dummy3; + if (!gl_format) + gl_format = &dummy2; + if (!gl_type) + gl_type = &dummy2; + + if (mp_get_chroma_shift(fmt, NULL, NULL, NULL)) { + // reduce the possible cases a bit + if (IMGFMT_IS_YUVP16_LE(fmt)) + fmt = IMGFMT_420P16_LE; + else if (IMGFMT_IS_YUVP16_BE(fmt)) + fmt = IMGFMT_420P16_BE; + else + fmt = IMGFMT_YV12; + } - *bpp = IMGFMT_IS_BGR(fmt)?IMGFMT_BGR_DEPTH(fmt):IMGFMT_RGB_DEPTH(fmt); - *gl_texfmt = 3; - switch (fmt) { + *bpp = IMGFMT_IS_BGR(fmt) ? IMGFMT_BGR_DEPTH(fmt) : IMGFMT_RGB_DEPTH(fmt); + *gl_texfmt = 3; + switch (fmt) { case IMGFMT_RGB48NE: - *gl_format = GL_RGB; - *gl_type = GL_UNSIGNED_SHORT; - break; + *gl_format = GL_RGB; + *gl_type = GL_UNSIGNED_SHORT; + break; case IMGFMT_RGB24: - *gl_format = GL_RGB; - *gl_type = GL_UNSIGNED_BYTE; - break; + *gl_format = GL_RGB; + *gl_type = GL_UNSIGNED_BYTE; + break; case IMGFMT_RGBA: - *gl_texfmt = 4; - *gl_format = GL_RGBA; - *gl_type = GL_UNSIGNED_BYTE; - break; + *gl_texfmt = 4; + *gl_format = GL_RGBA; + *gl_type = GL_UNSIGNED_BYTE; + break; case IMGFMT_420P16: - supported = 0; // no native YUV support - *gl_texfmt = GL_LUMINANCE16; - *bpp = 16; - *gl_format = GL_LUMINANCE; - *gl_type = GL_UNSIGNED_SHORT; - break; + supported = 0; // no native YUV support + *gl_texfmt = GL_LUMINANCE16; + *bpp = 16; + *gl_format = GL_LUMINANCE; + *gl_type = GL_UNSIGNED_SHORT; + break; case IMGFMT_YV12: - supported = 0; // no native YV12 support + supported = 0; // no native YV12 support case IMGFMT_Y800: case IMGFMT_Y8: - *gl_texfmt = 1; - *bpp = 8; - *gl_format = GL_LUMINANCE; - *gl_type = GL_UNSIGNED_BYTE; - break; + *gl_texfmt = 1; + *bpp = 8; + *gl_format = GL_LUMINANCE; + *gl_type = GL_UNSIGNED_BYTE; + break; case IMGFMT_UYVY: // IMGFMT_YUY2 would be more logical for the _REV format, // but gives clearly swapped colors. case IMGFMT_YVYU: - *gl_texfmt = GL_YCBCR_MESA; - *bpp = 16; - *gl_format = GL_YCBCR_MESA; - *gl_type = fmt == IMGFMT_UYVY ? GL_UNSIGNED_SHORT_8_8 : GL_UNSIGNED_SHORT_8_8_REV; - break; + *gl_texfmt = GL_YCBCR_MESA; + *bpp = 16; + *gl_format = GL_YCBCR_MESA; + *gl_type = fmt == IMGFMT_UYVY ? GL_UNSIGNED_SHORT_8_8 : GL_UNSIGNED_SHORT_8_8_REV; + break; #if 0 // we do not support palettized formats, although the format the // swscale produces works case IMGFMT_RGB8: - gl_format = GL_RGB; - gl_type = GL_UNSIGNED_BYTE_2_3_3_REV; - break; + gl_format = GL_RGB; + gl_type = GL_UNSIGNED_BYTE_2_3_3_REV; + break; #endif case IMGFMT_RGB15: - *gl_format = GL_RGBA; - *gl_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - break; + *gl_format = GL_RGBA; + *gl_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + break; case IMGFMT_RGB16: - *gl_format = GL_RGB; - *gl_type = GL_UNSIGNED_SHORT_5_6_5_REV; - break; + *gl_format = GL_RGB; + *gl_type = GL_UNSIGNED_SHORT_5_6_5_REV; + break; #if 0 case IMGFMT_BGR8: - // special case as red and blue have a differen number of bits. - // GL_BGR and GL_UNSIGNED_BYTE_3_3_2 isn't supported at least - // by nVidia drivers, and in addition would give more bits to - // blue than to red, which isn't wanted - gl_format = GL_RGB; - gl_type = GL_UNSIGNED_BYTE_3_3_2; - break; + // special case as red and blue have a differen number of bits. + // GL_BGR and GL_UNSIGNED_BYTE_3_3_2 isn't supported at least + // by nVidia drivers, and in addition would give more bits to + // blue than to red, which isn't wanted + gl_format = GL_RGB; + gl_type = GL_UNSIGNED_BYTE_3_3_2; + break; #endif case IMGFMT_BGR15: - *gl_format = GL_BGRA; - *gl_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - break; + *gl_format = GL_BGRA; + *gl_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + break; case IMGFMT_BGR16: - *gl_format = GL_RGB; - *gl_type = GL_UNSIGNED_SHORT_5_6_5; - break; + *gl_format = GL_RGB; + *gl_type = GL_UNSIGNED_SHORT_5_6_5; + break; case IMGFMT_BGR24: - *gl_format = GL_BGR; - *gl_type = GL_UNSIGNED_BYTE; - break; + *gl_format = GL_BGR; + *gl_type = GL_UNSIGNED_BYTE; + break; case IMGFMT_BGRA: - *gl_texfmt = 4; - *gl_format = GL_BGRA; - *gl_type = GL_UNSIGNED_BYTE; - break; + *gl_texfmt = 4; + *gl_format = GL_BGRA; + *gl_type = GL_UNSIGNED_BYTE; + break; default: - *gl_texfmt = 4; - *gl_format = GL_RGBA; - *gl_type = GL_UNSIGNED_BYTE; - supported = 0; - } + *gl_texfmt = 4; + *gl_format = GL_RGBA; + *gl_type = GL_UNSIGNED_BYTE; + supported = 0; + } #ifdef TEXTUREFORMAT_ALWAYS - *gl_texfmt = TEXTUREFORMAT_ALWAYS; + *gl_texfmt = TEXTUREFORMAT_ALWAYS; #endif - return supported; + return supported; } #ifdef HAVE_LIBDL @@ -368,112 +275,150 @@ int glFindFormat(uint32_t fmt, int *bpp, GLint *gl_texfmt, * \param s name of function to find * \return address of function or NULL if not found */ -static void *getdladdr(const char *s) { - void *ret = NULL; +static void *getdladdr(const char *s) +{ + void *ret = NULL; #ifdef HAVE_LIBDL - void *handle = dlopen(NULL, RTLD_LAZY); - if (!handle) - return NULL; - ret = dlsym(handle, s); - dlclose(handle); + void *handle = dlopen(NULL, RTLD_LAZY); + if (!handle) + return NULL; + ret = dlsym(handle, s); + dlclose(handle); #endif - return ret; + return ret; } typedef struct { - void *funcptr; - const char *extstr; - const char *funcnames[7]; - void *fallback; + ptrdiff_t offset; // offset to the function pointer in struct GL + const char *extstr; + const char *funcnames[7]; + void *fallback; } extfunc_desc_t; -#define DEF_FUNC_DESC(name) {&mpgl##name, NULL, {"gl"#name, NULL}, gl ##name} +#define DEF_FUNC_DESC(name) \ + {offsetof(GL, name), NULL, {"gl" # name, NULL}, gl ## name} +#define DEF_EXT_FUNCS(...) __VA_ARGS__ +#define DEF_EXT_DESC(name, ext, funcnames) \ + {offsetof(GL, name), ext, {DEF_EXT_FUNCS funcnames}} + static const extfunc_desc_t extfuncs[] = { - // these aren't extension functions but we query them anyway to allow - // different "backends" with one binary - DEF_FUNC_DESC(Begin), - DEF_FUNC_DESC(End), - DEF_FUNC_DESC(Viewport), - DEF_FUNC_DESC(MatrixMode), - DEF_FUNC_DESC(LoadIdentity), - DEF_FUNC_DESC(Translated), - DEF_FUNC_DESC(Scaled), - DEF_FUNC_DESC(Ortho), - DEF_FUNC_DESC(Frustum), - DEF_FUNC_DESC(PushMatrix), - DEF_FUNC_DESC(PopMatrix), - DEF_FUNC_DESC(Clear), - DEF_FUNC_DESC(GenLists), - DEF_FUNC_DESC(DeleteLists), - DEF_FUNC_DESC(NewList), - DEF_FUNC_DESC(EndList), - DEF_FUNC_DESC(CallList), - DEF_FUNC_DESC(CallLists), - DEF_FUNC_DESC(GenTextures), - DEF_FUNC_DESC(DeleteTextures), - DEF_FUNC_DESC(TexEnvf), - DEF_FUNC_DESC(TexEnvi), - DEF_FUNC_DESC(Color4ub), - DEF_FUNC_DESC(Color3f), - DEF_FUNC_DESC(Color4f), - DEF_FUNC_DESC(ClearColor), - DEF_FUNC_DESC(ClearDepth), - DEF_FUNC_DESC(DepthFunc), - DEF_FUNC_DESC(Enable), - DEF_FUNC_DESC(Disable), - DEF_FUNC_DESC(DrawBuffer), - DEF_FUNC_DESC(DepthMask), - DEF_FUNC_DESC(BlendFunc), - DEF_FUNC_DESC(Flush), - DEF_FUNC_DESC(Finish), - DEF_FUNC_DESC(PixelStorei), - DEF_FUNC_DESC(TexImage1D), - DEF_FUNC_DESC(TexImage2D), - DEF_FUNC_DESC(TexSubImage2D), - DEF_FUNC_DESC(TexParameteri), - DEF_FUNC_DESC(TexParameterf), - DEF_FUNC_DESC(TexParameterfv), - DEF_FUNC_DESC(TexCoord2f), - DEF_FUNC_DESC(Vertex2f), - DEF_FUNC_DESC(Vertex3f), - DEF_FUNC_DESC(Normal3f), - DEF_FUNC_DESC(Lightfv), - DEF_FUNC_DESC(ColorMaterial), - DEF_FUNC_DESC(ShadeModel), - DEF_FUNC_DESC(GetIntegerv), - DEF_FUNC_DESC(ColorMask), - - // here start the real extensions - {&mpglGenBuffers, NULL, {"glGenBuffers", "glGenBuffersARB", NULL}}, - {&mpglDeleteBuffers, NULL, {"glDeleteBuffers", "glDeleteBuffersARB", NULL}}, - {&mpglBindBuffer, NULL, {"glBindBuffer", "glBindBufferARB", NULL}}, - {&mpglMapBuffer, NULL, {"glMapBuffer", "glMapBufferARB", NULL}}, - {&mpglUnmapBuffer, NULL, {"glUnmapBuffer", "glUnmapBufferARB", NULL}}, - {&mpglBufferData, NULL, {"glBufferData", "glBufferDataARB", NULL}}, - {&mpglCombinerParameterfv, "NV_register_combiners", {"glCombinerParameterfv", "glCombinerParameterfvNV", NULL}}, - {&mpglCombinerParameteri, "NV_register_combiners", {"glCombinerParameteri", "glCombinerParameteriNV", NULL}}, - {&mpglCombinerInput, "NV_register_combiners", {"glCombinerInput", "glCombinerInputNV", NULL}}, - {&mpglCombinerOutput, "NV_register_combiners", {"glCombinerOutput", "glCombinerOutputNV", NULL}}, - {&mpglBeginFragmentShader, "ATI_fragment_shader", {"glBeginFragmentShaderATI", NULL}}, - {&mpglEndFragmentShader, "ATI_fragment_shader", {"glEndFragmentShaderATI", NULL}}, - {&mpglSampleMap, "ATI_fragment_shader", {"glSampleMapATI", NULL}}, - {&mpglColorFragmentOp2, "ATI_fragment_shader", {"glColorFragmentOp2ATI", NULL}}, - {&mpglColorFragmentOp3, "ATI_fragment_shader", {"glColorFragmentOp3ATI", NULL}}, - {&mpglSetFragmentShaderConstant, "ATI_fragment_shader", {"glSetFragmentShaderConstantATI", NULL}}, - {&mpglActiveTexture, NULL, {"glActiveTexture", "glActiveTextureARB", NULL}}, - {&mpglBindTexture, NULL, {"glBindTexture", "glBindTextureARB", "glBindTextureEXT", NULL}}, - {&mpglMultiTexCoord2f, NULL, {"glMultiTexCoord2f", "glMultiTexCoord2fARB", NULL}}, - {&mpglGenPrograms, "_program", {"glGenProgramsARB", NULL}}, - {&mpglDeletePrograms, "_program", {"glDeleteProgramsARB", NULL}}, - {&mpglBindProgram, "_program", {"glBindProgramARB", NULL}}, - {&mpglProgramString, "_program", {"glProgramStringARB", NULL}}, - {&mpglGetProgramiv, "_program", {"glGetProgramivARB", NULL}}, - {&mpglProgramEnvParameter4f, "_program", {"glProgramEnvParameter4fARB", NULL}}, - {&mpglSwapInterval, "_swap_control", {"glXSwapIntervalSGI", "glXSwapInterval", "wglSwapIntervalSGI", "wglSwapInterval", "wglSwapIntervalEXT", NULL}}, - {&mpglTexImage3D, NULL, {"glTexImage3D", NULL}}, - {&mpglAllocateMemoryMESA, "GLX_MESA_allocate_memory", {"glXAllocateMemoryMESA", NULL}}, - {&mpglFreeMemoryMESA, "GLX_MESA_allocate_memory", {"glXFreeMemoryMESA", NULL}}, - {NULL} + // these aren't extension functions but we query them anyway to allow + // different "backends" with one binary + DEF_FUNC_DESC(Begin), + DEF_FUNC_DESC(End), + DEF_FUNC_DESC(Viewport), + DEF_FUNC_DESC(MatrixMode), + DEF_FUNC_DESC(LoadIdentity), + DEF_FUNC_DESC(Translated), + DEF_FUNC_DESC(Scaled), + DEF_FUNC_DESC(Ortho), + DEF_FUNC_DESC(Frustum), + DEF_FUNC_DESC(PushMatrix), + DEF_FUNC_DESC(PopMatrix), + DEF_FUNC_DESC(Clear), + DEF_FUNC_DESC(GenLists), + DEF_FUNC_DESC(DeleteLists), + DEF_FUNC_DESC(NewList), + DEF_FUNC_DESC(EndList), + DEF_FUNC_DESC(CallList), + DEF_FUNC_DESC(CallLists), + DEF_FUNC_DESC(GenTextures), + DEF_FUNC_DESC(DeleteTextures), + DEF_FUNC_DESC(TexEnvf), + DEF_FUNC_DESC(TexEnvi), + DEF_FUNC_DESC(Color4ub), + DEF_FUNC_DESC(Color3f), + DEF_FUNC_DESC(Color4f), + DEF_FUNC_DESC(ClearColor), + DEF_FUNC_DESC(ClearDepth), + DEF_FUNC_DESC(DepthFunc), + DEF_FUNC_DESC(Enable), + DEF_FUNC_DESC(Disable), + DEF_FUNC_DESC(DrawBuffer), + DEF_FUNC_DESC(DepthMask), + DEF_FUNC_DESC(BlendFunc), + DEF_FUNC_DESC(Flush), + DEF_FUNC_DESC(Finish), + DEF_FUNC_DESC(PixelStorei), + DEF_FUNC_DESC(TexImage1D), + DEF_FUNC_DESC(TexImage2D), + DEF_FUNC_DESC(TexSubImage2D), + DEF_FUNC_DESC(GetTexImage), + DEF_FUNC_DESC(TexParameteri), + DEF_FUNC_DESC(TexParameterf), + DEF_FUNC_DESC(TexParameterfv), + DEF_FUNC_DESC(TexCoord2f), + DEF_FUNC_DESC(Vertex2f), + DEF_FUNC_DESC(Vertex3f), + DEF_FUNC_DESC(Normal3f), + DEF_FUNC_DESC(Lightfv), + DEF_FUNC_DESC(ColorMaterial), + DEF_FUNC_DESC(ShadeModel), + DEF_FUNC_DESC(GetIntegerv), + DEF_FUNC_DESC(ColorMask), + DEF_FUNC_DESC(ReadPixels), + DEF_FUNC_DESC(ReadBuffer), + + DEF_EXT_DESC(GenBuffers, NULL, + ("glGenBuffers", "glGenBuffersARB")), + DEF_EXT_DESC(DeleteBuffers, NULL, + ("glDeleteBuffers", "glDeleteBuffersARB")), + DEF_EXT_DESC(BindBuffer, NULL, + ("glBindBuffer", "glBindBufferARB")), + DEF_EXT_DESC(MapBuffer, NULL, + ("glMapBuffer", "glMapBufferARB")), + DEF_EXT_DESC(UnmapBuffer, NULL, + ("glUnmapBuffer", "glUnmapBufferARB")), + DEF_EXT_DESC(BufferData, NULL, + ("glBufferData", "glBufferDataARB")), + DEF_EXT_DESC(CombinerParameterfv, "NV_register_combiners", + ("glCombinerParameterfv", "glCombinerParameterfvNV")), + DEF_EXT_DESC(CombinerParameteri, "NV_register_combiners", + ("glCombinerParameteri", "glCombinerParameteriNV")), + DEF_EXT_DESC(CombinerInput, "NV_register_combiners", + ("glCombinerInput", "glCombinerInputNV")), + DEF_EXT_DESC(CombinerOutput, "NV_register_combiners", + ("glCombinerOutput", "glCombinerOutputNV")), + DEF_EXT_DESC(BeginFragmentShader, "ATI_fragment_shader", + ("glBeginFragmentShaderATI")), + DEF_EXT_DESC(EndFragmentShader, "ATI_fragment_shader", + ("glEndFragmentShaderATI")), + DEF_EXT_DESC(SampleMap, "ATI_fragment_shader", + ("glSampleMapATI")), + DEF_EXT_DESC(ColorFragmentOp2, "ATI_fragment_shader", + ("glColorFragmentOp2ATI")), + DEF_EXT_DESC(ColorFragmentOp3, "ATI_fragment_shader", + ("glColorFragmentOp3ATI")), + DEF_EXT_DESC(SetFragmentShaderConstant, "ATI_fragment_shader", + ("glSetFragmentShaderConstantATI")), + DEF_EXT_DESC(ActiveTexture, NULL, + ("glActiveTexture", "glActiveTextureARB")), + DEF_EXT_DESC(BindTexture, NULL, + ("glBindTexture", "glBindTextureARB", "glBindTextureEXT")), + DEF_EXT_DESC(MultiTexCoord2f, NULL, + ("glMultiTexCoord2f", "glMultiTexCoord2fARB")), + DEF_EXT_DESC(GenPrograms, "_program", + ("glGenProgramsARB")), + DEF_EXT_DESC(DeletePrograms, "_program", + ("glDeleteProgramsARB")), + DEF_EXT_DESC(BindProgram, "_program", + ("glBindProgramARB")), + DEF_EXT_DESC(ProgramString, "_program", + ("glProgramStringARB")), + DEF_EXT_DESC(GetProgramiv, "_program", + ("glGetProgramivARB")), + DEF_EXT_DESC(ProgramEnvParameter4f, "_program", + ("glProgramEnvParameter4fARB")), + DEF_EXT_DESC(SwapInterval, "_swap_control", + ("glXSwapIntervalSGI", "glXSwapInterval", "wglSwapIntervalSGI", + "wglSwapInterval", "wglSwapIntervalEXT")), + DEF_EXT_DESC(TexImage3D, NULL, + ("glTexImage3D")), + DEF_EXT_DESC(AllocateMemoryMESA, "GLX_MESA_allocate_memory", + ("glXAllocateMemoryMESA")), + DEF_EXT_DESC(FreeMemoryMESA, "GLX_MESA_allocate_memory", + ("glXFreeMemoryMESA")), + {-1} }; /** @@ -481,46 +426,44 @@ static const extfunc_desc_t extfuncs[] = { * \param getProcAddress function to resolve function names, may be NULL * \param ext2 an extra extension string */ -static void getFunctions(void *(*getProcAddress)(const GLubyte *), - const char *ext2) { - const extfunc_desc_t *dsc; - const char *extensions; - char *allexts; - - if (!getProcAddress) - getProcAddress = (void *)getdladdr; - - // special case, we need glGetString before starting to find the other functions - mpglGetString = getProcAddress("glGetString"); - if (!mpglGetString) - mpglGetString = glGetString; - - extensions = (const char *)mpglGetString(GL_EXTENSIONS); - if (!extensions) extensions = ""; - if (!ext2) ext2 = ""; - allexts = malloc(strlen(extensions) + strlen(ext2) + 2); - strcpy(allexts, extensions); - strcat(allexts, " "); - strcat(allexts, ext2); - mp_msg(MSGT_VO, MSGL_DBG2, "OpenGL extensions string:\n%s\n", allexts); - for (dsc = extfuncs; dsc->funcptr; dsc++) { - void *ptr = NULL; - int i; - if (!dsc->extstr || strstr(allexts, dsc->extstr)) { - for (i = 0; !ptr && dsc->funcnames[i]; i++) - ptr = getProcAddress((const GLubyte *)dsc->funcnames[i]); +static void getFunctions(GL *gl, void *(*getProcAddress)(const GLubyte *), + const char *ext2) +{ + const extfunc_desc_t *dsc; + const char *extensions; + char *allexts; + + if (!getProcAddress) + getProcAddress = (void *)getdladdr; + + // special case, we need glGetString before starting to find the other functions + gl->GetString = getProcAddress("glGetString"); + if (!gl->GetString) + gl->GetString = glGetString; + + extensions = (const char *)gl->GetString(GL_EXTENSIONS); + if (!extensions) + extensions = ""; + if (!ext2) + ext2 = ""; + allexts = malloc(strlen(extensions) + strlen(ext2) + 2); + strcpy(allexts, extensions); + strcat(allexts, " "); + strcat(allexts, ext2); + mp_msg(MSGT_VO, MSGL_DBG2, "OpenGL extensions string:\n%s\n", allexts); + for (dsc = extfuncs; dsc->offset >= 0; dsc++) { + void *ptr = NULL; + int i; + if (!dsc->extstr || strstr(allexts, dsc->extstr)) { + for (i = 0; !ptr && dsc->funcnames[i]; i++) + ptr = getProcAddress((const GLubyte *)dsc->funcnames[i]); + } + if (!ptr) + ptr = dsc->fallback; + void **funcptr = (void**)(((char*)gl) + dsc->offset); + *funcptr = ptr; } - if (!ptr) - ptr = dsc->fallback; - *(void **)dsc->funcptr = ptr; - } - if (strstr(allexts, "_texture_float")) - hqtexfmt = GL_RGB32F; - else if (strstr(allexts, "NV_float_buffer")) - hqtexfmt = GL_FLOAT_RGB32_NV; - else - hqtexfmt = GL_RGB16; - free(allexts); + free(allexts); } /** @@ -535,30 +478,47 @@ static void getFunctions(void *(*getProcAddress)(const GLubyte *), * \param val luminance value to fill texture with * \ingroup gltexture */ -void glCreateClearTex(GLenum target, GLenum fmt, GLenum format, GLenum type, GLint filter, - int w, int h, unsigned char val) { - GLfloat fval = (GLfloat)val / 255.0; - GLfloat border[4] = {fval, fval, fval, fval}; - int stride; - char *init; - if (w == 0) w = 1; - if (h == 0) h = 1; - stride = w * glFmt2bpp(format, type); - if (!stride) return; - init = malloc(stride * h); - memset(init, val, stride * h); - glAdjustAlignment(stride); - mpglPixelStorei(GL_UNPACK_ROW_LENGTH, w); - mpglTexImage2D(target, 0, fmt, w, h, 0, format, type, init); - mpglTexParameterf(target, GL_TEXTURE_PRIORITY, 1.0); - mpglTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter); - mpglTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter); - mpglTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - mpglTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // Border texels should not be used with CLAMP_TO_EDGE - // We set a sane default anyway. - mpglTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, border); - free(init); +void glCreateClearTex(GL *gl, GLenum target, GLenum fmt, GLenum format, + GLenum type, GLint filter, int w, int h, + unsigned char val) +{ + GLfloat fval = (GLfloat)val / 255.0; + GLfloat border[4] = { + fval, fval, fval, fval + }; + int stride; + char *init; + if (w == 0) + w = 1; + if (h == 0) + h = 1; + stride = w * glFmt2bpp(format, type); + if (!stride) + return; + init = malloc(stride * h); + memset(init, val, stride * h); + glAdjustAlignment(gl, stride); + gl->PixelStorei(GL_UNPACK_ROW_LENGTH, w); + gl->TexImage2D(target, 0, fmt, w, h, 0, format, type, init); + gl->TexParameterf(target, GL_TEXTURE_PRIORITY, 1.0); + gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter); + gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter); + gl->TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl->TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + // Border texels should not be used with CLAMP_TO_EDGE + // We set a sane default anyway. + gl->TexParameterfv(target, GL_TEXTURE_BORDER_COLOR, border); + free(init); +} + +static GLint detect_hqtexfmt(GL *gl) +{ + const char *extensions = (const char *)gl->GetString(GL_EXTENSIONS); + if (strstr(extensions, "_texture_float")) + return GL_RGB32F; + else if (strstr(extensions, "NV_float_buffer")) + return GL_FLOAT_RGB32_NV; + return GL_RGB16; } /** @@ -573,29 +533,34 @@ void glCreateClearTex(GLenum target, GLenum fmt, GLenum format, GLenum type, GLi * \return 0 on error, 1 otherwise * \ingroup gltexture */ -int glCreatePPMTex(GLenum target, GLenum fmt, GLint filter, - FILE *f, int *width, int *height, int *maxval) { - int w, h, m, bpp; - GLenum type; - uint8_t *data = read_pnm(f, &w, &h, &bpp, &m); - if (!data || (bpp != 3 && bpp != 6)) { +int glCreatePPMTex(GL *gl, GLenum target, GLenum fmt, GLint filter, + FILE *f, int *width, int *height, int *maxval) +{ + int w, h, m, bpp; + GLenum type; + uint8_t *data = read_pnm(f, &w, &h, &bpp, &m); + GLint hqtexfmt = detect_hqtexfmt(gl); + if (!data || (bpp != 3 && bpp != 6)) { + free(data); + return 0; + } + if (!fmt) { + fmt = bpp == 6 ? hqtexfmt : 3; + if (fmt == GL_FLOAT_RGB32_NV && target != GL_TEXTURE_RECTANGLE) + fmt = GL_RGB16; + } + type = bpp == 6 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE; + glCreateClearTex(gl, target, fmt, GL_RGB, type, filter, w, h, 0); + glUploadTex(gl, target, GL_RGB, type, + data, w * bpp, 0, 0, w, h, 0); free(data); - return 0; - } - if (!fmt) { - fmt = bpp == 6 ? hqtexfmt : 3; - if (fmt == GL_FLOAT_RGB32_NV && target != GL_TEXTURE_RECTANGLE) - fmt = GL_RGB16; - } - type = bpp == 6 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE; - glCreateClearTex(target, fmt, GL_RGB, type, filter, w, h, 0); - glUploadTex(target, GL_RGB, type, - data, w * bpp, 0, 0, w, h, 0); - free(data); - if (width) *width = w; - if (height) *height = h; - if (maxval) *maxval = m; - return 1; + if (width) + *width = w; + if (height) + *height = h; + if (maxval) + *maxval = m; + return 1; } /** @@ -607,38 +572,39 @@ int glCreatePPMTex(GLenum target, GLenum fmt, GLint filter, * * Does not handle all possible variants, just those used by MPlayer */ -int glFmt2bpp(GLenum format, GLenum type) { - int component_size = 0; - switch (type) { +int glFmt2bpp(GLenum format, GLenum type) +{ + int component_size = 0; + switch (type) { case GL_UNSIGNED_BYTE_3_3_2: case GL_UNSIGNED_BYTE_2_3_3_REV: - return 1; + 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; + return 2; case GL_UNSIGNED_BYTE: - component_size = 1; - break; + component_size = 1; + break; case GL_UNSIGNED_SHORT: - component_size = 2; - break; - } - switch (format) { + component_size = 2; + break; + } + switch (format) { case GL_LUMINANCE: case GL_ALPHA: - return component_size; + return component_size; case GL_YCBCR_MESA: - return 2; + return 2; case GL_RGB: case GL_BGR: - return 3 * component_size; + return 3 * component_size; case GL_RGBA: case GL_BGRA: - return 4 * component_size; - } - return 0; // unknown + return 4 * component_size; + } + return 0; // unknown } /** @@ -655,49 +621,52 @@ int glFmt2bpp(GLenum format, GLenum type) { * \param slice height of an upload slice, 0 for all at once * \ingroup gltexture */ -void glUploadTex(GLenum target, GLenum format, GLenum type, +void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type, const void *dataptr, int stride, - int x, int y, int w, int h, int slice) { - const uint8_t *data = dataptr; - int y_max = y + h; - if (w <= 0 || h <= 0) return; - if (slice <= 0) - slice = h; - if (stride < 0) { - data += (h - 1) * stride; - stride = -stride; - } - // this is not always correct, but should work for MPlayer - glAdjustAlignment(stride); - mpglPixelStorei(GL_UNPACK_ROW_LENGTH, stride / glFmt2bpp(format, type)); - for (; y + slice <= y_max; y += slice) { - mpglTexSubImage2D(target, 0, x, y, w, slice, format, type, data); - data += stride * slice; - } - if (y < y_max) - mpglTexSubImage2D(target, 0, x, y, w, y_max - y, format, type, data); + int x, int y, int w, int h, int slice) +{ + const uint8_t *data = dataptr; + int y_max = y + h; + if (w <= 0 || h <= 0) + return; + if (slice <= 0) + slice = h; + if (stride < 0) { + data += (h - 1) * stride; + stride = -stride; + } + // this is not always correct, but should work for MPlayer + glAdjustAlignment(gl, stride); + gl->PixelStorei(GL_UNPACK_ROW_LENGTH, stride / glFmt2bpp(format, type)); + for (; y + slice <= y_max; y += slice) { + gl->TexSubImage2D(target, 0, x, y, w, slice, format, type, data); + data += stride * slice; + } + if (y < y_max) + gl->TexSubImage2D(target, 0, x, y, w, y_max - y, format, type, data); } static void fillUVcoeff(GLfloat *ucoef, GLfloat *vcoef, - float uvcos, float uvsin) { - int i; - ucoef[0] = 0 * uvcos + 1.403 * uvsin; - vcoef[0] = 0 * uvsin + 1.403 * uvcos; - ucoef[1] = -0.344 * uvcos + -0.714 * uvsin; - vcoef[1] = -0.344 * uvsin + -0.714 * uvcos; - ucoef[2] = 1.770 * uvcos + 0 * uvsin; - vcoef[2] = 1.770 * uvsin + 0 * uvcos; - ucoef[3] = 0; - vcoef[3] = 0; - // Coefficients (probably) must be in [0, 1] range, whereas they originally - // are in [-2, 2] range, so here comes the trick: - // First put them in the [-0.5, 0.5] range, then add 0.5. - // This can be undone with the HALF_BIAS and SCALE_BY_FOUR arguments - // for CombinerInput and CombinerOutput (or the respective ATI variants) - for (i = 0; i < 4; i++) { - ucoef[i] = ucoef[i] * 0.25 + 0.5; - vcoef[i] = vcoef[i] * 0.25 + 0.5; - } + float uvcos, float uvsin) +{ + int i; + ucoef[0] = 0 * uvcos + 1.403 * uvsin; + vcoef[0] = 0 * uvsin + 1.403 * uvcos; + ucoef[1] = -0.344 * uvcos + -0.714 * uvsin; + vcoef[1] = -0.344 * uvsin + -0.714 * uvcos; + ucoef[2] = 1.770 * uvcos + 0 * uvsin; + vcoef[2] = 1.770 * uvsin + 0 * uvcos; + ucoef[3] = 0; + vcoef[3] = 0; + // Coefficients (probably) must be in [0, 1] range, whereas they originally + // are in [-2, 2] range, so here comes the trick: + // First put them in the [-0.5, 0.5] range, then add 0.5. + // This can be undone with the HALF_BIAS and SCALE_BY_FOUR arguments + // for CombinerInput and CombinerOutput (or the respective ATI variants) + for (i = 0; i < 4; i++) { + ucoef[i] = ucoef[i] * 0.25 + 0.5; + vcoef[i] = vcoef[i] * 0.25 + 0.5; + } } /** @@ -705,55 +674,56 @@ static void fillUVcoeff(GLfloat *ucoef, GLfloat *vcoef, * \param uvcos used for saturation and hue adjustment * \param uvsin used for saturation and hue adjustment */ -static void glSetupYUVCombiners(float uvcos, float uvsin) { - GLfloat ucoef[4]; - GLfloat vcoef[4]; - GLint i; - if (!mpglCombinerInput || !mpglCombinerOutput || - !mpglCombinerParameterfv || !mpglCombinerParameteri) { - mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Combiner functions missing!\n"); - return; - } - mpglGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &i); - if (i < 2) - mp_msg(MSGT_VO, MSGL_ERR, - "[gl] 2 general combiners needed for YUV combiner support (found %i)\n", i); - mpglGetIntegerv(GL_MAX_TEXTURE_UNITS, &i); - if (i < 3) - mp_msg(MSGT_VO, MSGL_ERR, - "[gl] 3 texture units needed for YUV combiner support (found %i)\n", i); - fillUVcoeff(ucoef, vcoef, uvcos, uvsin); - mpglCombinerParameterfv(GL_CONSTANT_COLOR0_NV, ucoef); - mpglCombinerParameterfv(GL_CONSTANT_COLOR1_NV, vcoef); - - // UV first, like this green component cannot overflow - mpglCombinerInput(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, - GL_TEXTURE1, GL_HALF_BIAS_NORMAL_NV, GL_RGB); - mpglCombinerInput(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, - GL_CONSTANT_COLOR0_NV, GL_HALF_BIAS_NORMAL_NV, GL_RGB); - mpglCombinerInput(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, - GL_TEXTURE2, GL_HALF_BIAS_NORMAL_NV, GL_RGB); - mpglCombinerInput(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, - GL_CONSTANT_COLOR1_NV, GL_HALF_BIAS_NORMAL_NV, GL_RGB); - mpglCombinerOutput(GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, - GL_SPARE0_NV, GL_SCALE_BY_FOUR_NV, GL_NONE, GL_FALSE, - GL_FALSE, GL_FALSE); - - // stage 2 - mpglCombinerInput(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV, GL_SPARE0_NV, - GL_SIGNED_IDENTITY_NV, GL_RGB); - mpglCombinerInput(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV, GL_ZERO, - GL_UNSIGNED_INVERT_NV, GL_RGB); - mpglCombinerInput(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_C_NV, - GL_TEXTURE0, GL_SIGNED_IDENTITY_NV, GL_RGB); - mpglCombinerInput(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_D_NV, GL_ZERO, - GL_UNSIGNED_INVERT_NV, GL_RGB); - mpglCombinerOutput(GL_COMBINER1_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, - GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, - GL_FALSE, GL_FALSE); - - // leave final combiner stage in default mode - mpglCombinerParameteri(GL_NUM_GENERAL_COMBINERS_NV, 2); +static void glSetupYUVCombiners(GL *gl, float uvcos, float uvsin) +{ + GLfloat ucoef[4]; + GLfloat vcoef[4]; + GLint i; + if (!gl->CombinerInput || !gl->CombinerOutput || + !gl->CombinerParameterfv || !gl->CombinerParameteri) { + mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Combiner functions missing!\n"); + return; + } + gl->GetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &i); + if (i < 2) + mp_msg(MSGT_VO, MSGL_ERR, + "[gl] 2 general combiners needed for YUV combiner support (found %i)\n", i); + gl->GetIntegerv(GL_MAX_TEXTURE_UNITS, &i); + if (i < 3) + mp_msg(MSGT_VO, MSGL_ERR, + "[gl] 3 texture units needed for YUV combiner support (found %i)\n", i); + fillUVcoeff(ucoef, vcoef, uvcos, uvsin); + gl->CombinerParameterfv(GL_CONSTANT_COLOR0_NV, ucoef); + gl->CombinerParameterfv(GL_CONSTANT_COLOR1_NV, vcoef); + + // UV first, like this green component cannot overflow + gl->CombinerInput(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, + GL_TEXTURE1, GL_HALF_BIAS_NORMAL_NV, GL_RGB); + gl->CombinerInput(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, + GL_CONSTANT_COLOR0_NV, GL_HALF_BIAS_NORMAL_NV, GL_RGB); + gl->CombinerInput(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, + GL_TEXTURE2, GL_HALF_BIAS_NORMAL_NV, GL_RGB); + gl->CombinerInput(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, + GL_CONSTANT_COLOR1_NV, GL_HALF_BIAS_NORMAL_NV, GL_RGB); + gl->CombinerOutput(GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, + GL_SPARE0_NV, GL_SCALE_BY_FOUR_NV, GL_NONE, GL_FALSE, + GL_FALSE, GL_FALSE); + + // stage 2 + gl->CombinerInput(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV, GL_SPARE0_NV, + GL_SIGNED_IDENTITY_NV, GL_RGB); + gl->CombinerInput(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV, GL_ZERO, + GL_UNSIGNED_INVERT_NV, GL_RGB); + gl->CombinerInput(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_C_NV, + GL_TEXTURE0, GL_SIGNED_IDENTITY_NV, GL_RGB); + gl->CombinerInput(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_D_NV, GL_ZERO, + GL_UNSIGNED_INVERT_NV, GL_RGB); + gl->CombinerOutput(GL_COMBINER1_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, + GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, + GL_FALSE, GL_FALSE); + + // leave final combiner stage in default mode + gl->CombinerParameteri(GL_NUM_GENERAL_COMBINERS_NV, 2); } /** @@ -762,94 +732,96 @@ static void glSetupYUVCombiners(float uvcos, float uvsin) { * \param text if set use the GL_ATI_text_fragment_shader API as * used on OS X. */ -static void glSetupYUVFragmentATI(struct mp_csp_params *csp_params, - int text) { - GLint i; - float yuv2rgb[3][4]; - - mpglGetIntegerv (GL_MAX_TEXTURE_UNITS, &i); - if (i < 3) - mp_msg(MSGT_VO, MSGL_ERR, - "[gl] 3 texture units needed for YUV combiner (ATI) support (found %i)\n", i); - - mp_get_yuv2rgb_coeffs(csp_params, yuv2rgb); - for (i = 0; i < 3; i++) { - int j; - yuv2rgb[i][3] -= -0.5 * (yuv2rgb[i][1] + yuv2rgb[i][2]); - for (j = 0; j < 4; j++) { - yuv2rgb[i][j] *= 0.125; - yuv2rgb[i][j] += 0.5; - if (yuv2rgb[i][j] > 1) - yuv2rgb[i][j] = 1; - if (yuv2rgb[i][j] < 0) - yuv2rgb[i][j] = 0; +static void glSetupYUVFragmentATI(GL *gl, struct mp_csp_params *csp_params, + int text) +{ + GLint i; + float yuv2rgb[3][4]; + + gl->GetIntegerv(GL_MAX_TEXTURE_UNITS, &i); + if (i < 3) + mp_msg(MSGT_VO, MSGL_ERR, + "[gl] 3 texture units needed for YUV combiner (ATI) support (found %i)\n", i); + + mp_get_yuv2rgb_coeffs(csp_params, yuv2rgb); + for (i = 0; i < 3; i++) { + int j; + yuv2rgb[i][3] -= -0.5 * (yuv2rgb[i][1] + yuv2rgb[i][2]); + for (j = 0; j < 4; j++) { + yuv2rgb[i][j] *= 0.125; + yuv2rgb[i][j] += 0.5; + if (yuv2rgb[i][j] > 1) + yuv2rgb[i][j] = 1; + if (yuv2rgb[i][j] < 0) + yuv2rgb[i][j] = 0; + } } - } - if (text == 0) { - GLfloat c0[4] = {yuv2rgb[0][0], yuv2rgb[1][0], yuv2rgb[2][0]}; - GLfloat c1[4] = {yuv2rgb[0][1], yuv2rgb[1][1], yuv2rgb[2][1]}; - GLfloat c2[4] = {yuv2rgb[0][2], yuv2rgb[1][2], yuv2rgb[2][2]}; - GLfloat c3[4] = {yuv2rgb[0][3], yuv2rgb[1][3], yuv2rgb[2][3]}; - if (!mpglBeginFragmentShader || !mpglEndFragmentShader || - !mpglSetFragmentShaderConstant || !mpglSampleMap || - !mpglColorFragmentOp2 || !mpglColorFragmentOp3) { - mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Combiner (ATI) functions missing!\n"); - return; + if (text == 0) { + GLfloat c0[4] = { yuv2rgb[0][0], yuv2rgb[1][0], yuv2rgb[2][0] }; + GLfloat c1[4] = { yuv2rgb[0][1], yuv2rgb[1][1], yuv2rgb[2][1] }; + GLfloat c2[4] = { yuv2rgb[0][2], yuv2rgb[1][2], yuv2rgb[2][2] }; + GLfloat c3[4] = { yuv2rgb[0][3], yuv2rgb[1][3], yuv2rgb[2][3] }; + if (!gl->BeginFragmentShader || !gl->EndFragmentShader || + !gl->SetFragmentShaderConstant || !gl->SampleMap || + !gl->ColorFragmentOp2 || !gl->ColorFragmentOp3) { + mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Combiner (ATI) functions missing!\n"); + return; + } + gl->GetIntegerv(GL_NUM_FRAGMENT_REGISTERS_ATI, &i); + if (i < 3) + mp_msg(MSGT_VO, MSGL_ERR, + "[gl] 3 registers needed for YUV combiner (ATI) support (found %i)\n", i); + gl->BeginFragmentShader(); + gl->SetFragmentShaderConstant(GL_CON_0_ATI, c0); + gl->SetFragmentShaderConstant(GL_CON_1_ATI, c1); + gl->SetFragmentShaderConstant(GL_CON_2_ATI, c2); + gl->SetFragmentShaderConstant(GL_CON_3_ATI, c3); + gl->SampleMap(GL_REG_0_ATI, GL_TEXTURE0, GL_SWIZZLE_STR_ATI); + gl->SampleMap(GL_REG_1_ATI, GL_TEXTURE1, GL_SWIZZLE_STR_ATI); + gl->SampleMap(GL_REG_2_ATI, GL_TEXTURE2, GL_SWIZZLE_STR_ATI); + gl->ColorFragmentOp2(GL_MUL_ATI, GL_REG_1_ATI, GL_NONE, GL_NONE, + GL_REG_1_ATI, GL_NONE, GL_BIAS_BIT_ATI, + GL_CON_1_ATI, GL_NONE, GL_BIAS_BIT_ATI); + gl->ColorFragmentOp3(GL_MAD_ATI, GL_REG_2_ATI, GL_NONE, GL_NONE, + GL_REG_2_ATI, GL_NONE, GL_BIAS_BIT_ATI, + GL_CON_2_ATI, GL_NONE, GL_BIAS_BIT_ATI, + GL_REG_1_ATI, GL_NONE, GL_NONE); + gl->ColorFragmentOp3(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, + GL_REG_0_ATI, GL_NONE, GL_NONE, + GL_CON_0_ATI, GL_NONE, GL_BIAS_BIT_ATI, + GL_REG_2_ATI, GL_NONE, GL_NONE); + gl->ColorFragmentOp2(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, GL_8X_BIT_ATI, + GL_REG_0_ATI, GL_NONE, GL_NONE, + GL_CON_3_ATI, GL_NONE, GL_BIAS_BIT_ATI); + gl->EndFragmentShader(); + } else { + static const char template[] = + "!!ATIfs1.0\n" + "StartConstants;\n" + " CONSTANT c0 = {%e, %e, %e};\n" + " CONSTANT c1 = {%e, %e, %e};\n" + " CONSTANT c2 = {%e, %e, %e};\n" + " CONSTANT c3 = {%e, %e, %e};\n" + "EndConstants;\n" + "StartOutputPass;\n" + " SampleMap r0, t0.str;\n" + " SampleMap r1, t1.str;\n" + " SampleMap r2, t2.str;\n" + " MUL r1.rgb, r1.bias, c1.bias;\n" + " MAD r2.rgb, r2.bias, c2.bias, r1;\n" + " MAD r0.rgb, r0, c0.bias, r2;\n" + " ADD r0.rgb.8x, r0, c3.bias;\n" + "EndPass;\n"; + char buffer[512]; + snprintf(buffer, sizeof(buffer), template, + yuv2rgb[0][0], yuv2rgb[1][0], yuv2rgb[2][0], + yuv2rgb[0][1], yuv2rgb[1][1], yuv2rgb[2][1], + yuv2rgb[0][2], yuv2rgb[1][2], yuv2rgb[2][2], + yuv2rgb[0][3], yuv2rgb[1][3], yuv2rgb[2][3]); + mp_msg(MSGT_VO, MSGL_DBG2, "[gl] generated fragment program:\n%s\n", + buffer); + loadGPUProgram(gl, GL_TEXT_FRAGMENT_SHADER_ATI, buffer); } - mpglGetIntegerv(GL_NUM_FRAGMENT_REGISTERS_ATI, &i); - if (i < 3) - mp_msg(MSGT_VO, MSGL_ERR, - "[gl] 3 registers needed for YUV combiner (ATI) support (found %i)\n", i); - mpglBeginFragmentShader(); - mpglSetFragmentShaderConstant(GL_CON_0_ATI, c0); - mpglSetFragmentShaderConstant(GL_CON_1_ATI, c1); - mpglSetFragmentShaderConstant(GL_CON_2_ATI, c2); - mpglSetFragmentShaderConstant(GL_CON_3_ATI, c3); - mpglSampleMap(GL_REG_0_ATI, GL_TEXTURE0, GL_SWIZZLE_STR_ATI); - mpglSampleMap(GL_REG_1_ATI, GL_TEXTURE1, GL_SWIZZLE_STR_ATI); - mpglSampleMap(GL_REG_2_ATI, GL_TEXTURE2, GL_SWIZZLE_STR_ATI); - mpglColorFragmentOp2(GL_MUL_ATI, GL_REG_1_ATI, GL_NONE, GL_NONE, - GL_REG_1_ATI, GL_NONE, GL_BIAS_BIT_ATI, - GL_CON_1_ATI, GL_NONE, GL_BIAS_BIT_ATI); - mpglColorFragmentOp3(GL_MAD_ATI, GL_REG_2_ATI, GL_NONE, GL_NONE, - GL_REG_2_ATI, GL_NONE, GL_BIAS_BIT_ATI, - GL_CON_2_ATI, GL_NONE, GL_BIAS_BIT_ATI, - GL_REG_1_ATI, GL_NONE, GL_NONE); - mpglColorFragmentOp3(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, - GL_REG_0_ATI, GL_NONE, GL_NONE, - GL_CON_0_ATI, GL_NONE, GL_BIAS_BIT_ATI, - GL_REG_2_ATI, GL_NONE, GL_NONE); - mpglColorFragmentOp2(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, GL_8X_BIT_ATI, - GL_REG_0_ATI, GL_NONE, GL_NONE, - GL_CON_3_ATI, GL_NONE, GL_BIAS_BIT_ATI); - mpglEndFragmentShader(); - } else { - static const char template[] = - "!!ATIfs1.0\n" - "StartConstants;\n" - " CONSTANT c0 = {%e, %e, %e};\n" - " CONSTANT c1 = {%e, %e, %e};\n" - " CONSTANT c2 = {%e, %e, %e};\n" - " CONSTANT c3 = {%e, %e, %e};\n" - "EndConstants;\n" - "StartOutputPass;\n" - " SampleMap r0, t0.str;\n" - " SampleMap r1, t1.str;\n" - " SampleMap r2, t2.str;\n" - " MUL r1.rgb, r1.bias, c1.bias;\n" - " MAD r2.rgb, r2.bias, c2.bias, r1;\n" - " MAD r0.rgb, r0, c0.bias, r2;\n" - " ADD r0.rgb.8x, r0, c3.bias;\n" - "EndPass;\n"; - char buffer[512]; - snprintf(buffer, sizeof(buffer), template, - yuv2rgb[0][0], yuv2rgb[1][0], yuv2rgb[2][0], - yuv2rgb[0][1], yuv2rgb[1][1], yuv2rgb[2][1], - yuv2rgb[0][2], yuv2rgb[1][2], yuv2rgb[2][2], - yuv2rgb[0][3], yuv2rgb[1][3], yuv2rgb[2][3]); - mp_msg(MSGT_VO, MSGL_DBG2, "[gl] generated fragment program:\n%s\n", buffer); - loadGPUProgram(GL_TEXT_FRAGMENT_SHADER_ATI, buffer); - } } /** @@ -860,15 +832,16 @@ static void glSetupYUVFragmentATI(struct mp_csp_params *csp_params, * calculates the weights and stores them after appropriate transformation * for the scaler fragment program. */ -static void store_weights(float x, GLfloat *dst) { - float w0 = (((-1 * x + 3) * x - 3) * x + 1) / 6; - float w1 = ((( 3 * x - 6) * x + 0) * x + 4) / 6; - float w2 = (((-3 * x + 3) * x + 3) * x + 1) / 6; - float w3 = ((( 1 * x + 0) * x + 0) * x + 0) / 6; - *dst++ = 1 + x - w1 / (w0 + w1); - *dst++ = 1 - x + w3 / (w2 + w3); - *dst++ = w0 + w1; - *dst++ = 0; +static void store_weights(float x, GLfloat *dst) +{ + float w0 = (((-1 * x + 3) * x - 3) * x + 1) / 6; + float w1 = (((3 * x - 6) * x + 0) * x + 4) / 6; + float w2 = (((-3 * x + 3) * x + 3) * x + 1) / 6; + float w3 = (((1 * x + 0) * x + 0) * x + 0) / 6; + *dst++ = 1 + x - w1 / (w0 + w1); + *dst++ = 1 - x + w3 / (w2 + w3); + *dst++ = w0 + w1; + *dst++ = 0; } //! to avoid artefacts this should be rather large @@ -877,191 +850,193 @@ static void store_weights(float x, GLfloat *dst) { * \brief creates the 1D lookup texture needed for fast higher-order filtering * \param unit texture unit to attach texture to */ -static void gen_spline_lookup_tex(GLenum unit) { - GLfloat *tex = calloc(4 * LOOKUP_BSPLINE_RES, sizeof(*tex)); - GLfloat *tp = tex; - int i; - for (i = 0; i < LOOKUP_BSPLINE_RES; i++) { - float x = (float)(i + 0.5) / LOOKUP_BSPLINE_RES; - store_weights(x, tp); - tp += 4; - } - store_weights(0, tex); - store_weights(1, &tex[4 * (LOOKUP_BSPLINE_RES - 1)]); - mpglActiveTexture(unit); - mpglTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16, LOOKUP_BSPLINE_RES, 0, GL_RGBA, GL_FLOAT, tex); - mpglTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_PRIORITY, 1.0); - mpglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - mpglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - mpglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); - mpglActiveTexture(GL_TEXTURE0); - free(tex); +static void gen_spline_lookup_tex(GL *gl, GLenum unit) +{ + GLfloat *tex = calloc(4 * LOOKUP_BSPLINE_RES, sizeof(*tex)); + GLfloat *tp = tex; + int i; + for (i = 0; i < LOOKUP_BSPLINE_RES; i++) { + float x = (float)(i + 0.5) / LOOKUP_BSPLINE_RES; + store_weights(x, tp); + tp += 4; + } + store_weights(0, tex); + store_weights(1, &tex[4 * (LOOKUP_BSPLINE_RES - 1)]); + gl->ActiveTexture(unit); + gl->TexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16, LOOKUP_BSPLINE_RES, 0, GL_RGBA, + GL_FLOAT, tex); + gl->TexParameterf(GL_TEXTURE_1D, GL_TEXTURE_PRIORITY, 1.0); + gl->TexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gl->TexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gl->TexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); + gl->ActiveTexture(GL_TEXTURE0); + free(tex); } static const char *bilin_filt_template = - "TEX yuv.%c, fragment.texcoord[%c], texture[%c], %s;\n"; + "TEX yuv.%c, fragment.texcoord[%c], texture[%c], %s;\n"; #define BICUB_FILT_MAIN(textype) \ - /* first y-interpolation */ \ - "ADD coord, fragment.texcoord[%c].xyxy, cdelta.xyxw;\n" \ - "ADD coord2, fragment.texcoord[%c].xyxy, cdelta.zyzw;\n" \ - "TEX a.r, coord.xyxy, texture[%c], "textype";\n" \ - "TEX a.g, coord.zwzw, texture[%c], "textype";\n" \ - /* second y-interpolation */ \ - "TEX b.r, coord2.xyxy, texture[%c], "textype";\n" \ - "TEX b.g, coord2.zwzw, texture[%c], "textype";\n" \ - "LRP a.b, parmy.b, a.rrrr, a.gggg;\n" \ - "LRP a.a, parmy.b, b.rrrr, b.gggg;\n" \ - /* x-interpolation */ \ - "LRP yuv.%c, parmx.b, a.bbbb, a.aaaa;\n" + /* first y-interpolation */ \ + "ADD coord, fragment.texcoord[%c].xyxy, cdelta.xyxw;\n" \ + "ADD coord2, fragment.texcoord[%c].xyxy, cdelta.zyzw;\n" \ + "TEX a.r, coord.xyxy, texture[%c], "textype ";\n" \ + "TEX a.g, coord.zwzw, texture[%c], "textype ";\n" \ + /* second y-interpolation */ \ + "TEX b.r, coord2.xyxy, texture[%c], "textype ";\n" \ + "TEX b.g, coord2.zwzw, texture[%c], "textype ";\n" \ + "LRP a.b, parmy.b, a.rrrr, a.gggg;\n" \ + "LRP a.a, parmy.b, b.rrrr, b.gggg;\n" \ + /* x-interpolation */ \ + "LRP yuv.%c, parmx.b, a.bbbb, a.aaaa;\n" static const char *bicub_filt_template_2D = - "MAD coord.xy, fragment.texcoord[%c], {%e, %e}, {0.5, 0.5};\n" - "TEX parmx, coord.x, texture[%c], 1D;\n" - "MUL cdelta.xz, parmx.rrgg, {-%e, 0, %e, 0};\n" - "TEX parmy, coord.y, texture[%c], 1D;\n" - "MUL cdelta.yw, parmy.rrgg, {0, -%e, 0, %e};\n" - BICUB_FILT_MAIN("2D"); + "MAD coord.xy, fragment.texcoord[%c], {%e, %e}, {0.5, 0.5};\n" + "TEX parmx, coord.x, texture[%c], 1D;\n" + "MUL cdelta.xz, parmx.rrgg, {-%e, 0, %e, 0};\n" + "TEX parmy, coord.y, texture[%c], 1D;\n" + "MUL cdelta.yw, parmy.rrgg, {0, -%e, 0, %e};\n" + BICUB_FILT_MAIN("2D"); static const char *bicub_filt_template_RECT = - "ADD coord, fragment.texcoord[%c], {0.5, 0.5};\n" - "TEX parmx, coord.x, texture[%c], 1D;\n" - "MUL cdelta.xz, parmx.rrgg, {-1, 0, 1, 0};\n" - "TEX parmy, coord.y, texture[%c], 1D;\n" - "MUL cdelta.yw, parmy.rrgg, {0, -1, 0, 1};\n" - BICUB_FILT_MAIN("RECT"); + "ADD coord, fragment.texcoord[%c], {0.5, 0.5};\n" + "TEX parmx, coord.x, texture[%c], 1D;\n" + "MUL cdelta.xz, parmx.rrgg, {-1, 0, 1, 0};\n" + "TEX parmy, coord.y, texture[%c], 1D;\n" + "MUL cdelta.yw, parmy.rrgg, {0, -1, 0, 1};\n" + BICUB_FILT_MAIN("RECT"); #define CALCWEIGHTS(t, s) \ - "MAD "t", {-0.5, 0.1666, 0.3333, -0.3333}, "s", {1, 0, -0.5, 0.5};\n" \ - "MAD "t", "t", "s", {0, 0, -0.5, 0.5};\n" \ - "MAD "t", "t", "s", {-0.6666, 0, 0.8333, 0.1666};\n" \ - "RCP a.x, "t".z;\n" \ - "RCP a.y, "t".w;\n" \ - "MAD "t".xy, "t".xyxy, a.xyxy, {1, 1, 0, 0};\n" \ - "ADD "t".x, "t".xxxx, "s";\n" \ - "SUB "t".y, "t".yyyy, "s";\n" + "MAD "t ", {-0.5, 0.1666, 0.3333, -0.3333}, "s ", {1, 0, -0.5, 0.5};\n" \ + "MAD "t ", "t ", "s ", {0, 0, -0.5, 0.5};\n" \ + "MAD "t ", "t ", "s ", {-0.6666, 0, 0.8333, 0.1666};\n" \ + "RCP a.x, "t ".z;\n" \ + "RCP a.y, "t ".w;\n" \ + "MAD "t ".xy, "t ".xyxy, a.xyxy, {1, 1, 0, 0};\n" \ + "ADD "t ".x, "t ".xxxx, "s ";\n" \ + "SUB "t ".y, "t ".yyyy, "s ";\n" static const char *bicub_notex_filt_template_2D = - "MAD coord.xy, fragment.texcoord[%c], {%e, %e}, {0.5, 0.5};\n" - "FRC coord.xy, coord.xyxy;\n" - CALCWEIGHTS("parmx", "coord.xxxx") - "MUL cdelta.xz, parmx.rrgg, {-%e, 0, %e, 0};\n" - CALCWEIGHTS("parmy", "coord.yyyy") - "MUL cdelta.yw, parmy.rrgg, {0, -%e, 0, %e};\n" - BICUB_FILT_MAIN("2D"); + "MAD coord.xy, fragment.texcoord[%c], {%e, %e}, {0.5, 0.5};\n" + "FRC coord.xy, coord.xyxy;\n" + CALCWEIGHTS("parmx", "coord.xxxx") + "MUL cdelta.xz, parmx.rrgg, {-%e, 0, %e, 0};\n" + CALCWEIGHTS("parmy", "coord.yyyy") + "MUL cdelta.yw, parmy.rrgg, {0, -%e, 0, %e};\n" + BICUB_FILT_MAIN("2D"); static const char *bicub_notex_filt_template_RECT = - "ADD coord, fragment.texcoord[%c], {0.5, 0.5};\n" - "FRC coord.xy, coord.xyxy;\n" - CALCWEIGHTS("parmx", "coord.xxxx") - "MUL cdelta.xz, parmx.rrgg, {-1, 0, 1, 0};\n" - CALCWEIGHTS("parmy", "coord.yyyy") - "MUL cdelta.yw, parmy.rrgg, {0, -1, 0, 1};\n" - BICUB_FILT_MAIN("RECT"); + "ADD coord, fragment.texcoord[%c], {0.5, 0.5};\n" + "FRC coord.xy, coord.xyxy;\n" + CALCWEIGHTS("parmx", "coord.xxxx") + "MUL cdelta.xz, parmx.rrgg, {-1, 0, 1, 0};\n" + CALCWEIGHTS("parmy", "coord.yyyy") + "MUL cdelta.yw, parmy.rrgg, {0, -1, 0, 1};\n" + BICUB_FILT_MAIN("RECT"); #define BICUB_X_FILT_MAIN(textype) \ - "ADD coord.xy, fragment.texcoord[%c].xyxy, cdelta.xyxy;\n" \ - "ADD coord2.xy, fragment.texcoord[%c].xyxy, cdelta.zyzy;\n" \ - "TEX a.r, coord, texture[%c], "textype";\n" \ - "TEX b.r, coord2, texture[%c], "textype";\n" \ - /* x-interpolation */ \ - "LRP yuv.%c, parmx.b, a.rrrr, b.rrrr;\n" + "ADD coord.xy, fragment.texcoord[%c].xyxy, cdelta.xyxy;\n" \ + "ADD coord2.xy, fragment.texcoord[%c].xyxy, cdelta.zyzy;\n" \ + "TEX a.r, coord, texture[%c], "textype ";\n" \ + "TEX b.r, coord2, texture[%c], "textype ";\n" \ + /* x-interpolation */ \ + "LRP yuv.%c, parmx.b, a.rrrr, b.rrrr;\n" static const char *bicub_x_filt_template_2D = - "MAD coord.x, fragment.texcoord[%c], {%e}, {0.5};\n" - "TEX parmx, coord, texture[%c], 1D;\n" - "MUL cdelta.xyz, parmx.rrgg, {-%e, 0, %e};\n" - BICUB_X_FILT_MAIN("2D"); + "MAD coord.x, fragment.texcoord[%c], {%e}, {0.5};\n" + "TEX parmx, coord, texture[%c], 1D;\n" + "MUL cdelta.xyz, parmx.rrgg, {-%e, 0, %e};\n" + BICUB_X_FILT_MAIN("2D"); static const char *bicub_x_filt_template_RECT = - "ADD coord.x, fragment.texcoord[%c], {0.5};\n" - "TEX parmx, coord, texture[%c], 1D;\n" - "MUL cdelta.xyz, parmx.rrgg, {-1, 0, 1};\n" - BICUB_X_FILT_MAIN("RECT"); + "ADD coord.x, fragment.texcoord[%c], {0.5};\n" + "TEX parmx, coord, texture[%c], 1D;\n" + "MUL cdelta.xyz, parmx.rrgg, {-1, 0, 1};\n" + BICUB_X_FILT_MAIN("RECT"); static const char *unsharp_filt_template = - "PARAM dcoord%c = {%e, %e, %e, %e};\n" - "ADD coord, fragment.texcoord[%c].xyxy, dcoord%c;\n" - "SUB coord2, fragment.texcoord[%c].xyxy, dcoord%c;\n" - "TEX a.r, fragment.texcoord[%c], texture[%c], %s;\n" - "TEX b.r, coord.xyxy, texture[%c], %s;\n" - "TEX b.g, coord.zwzw, texture[%c], %s;\n" - "ADD b.r, b.r, b.g;\n" - "TEX b.b, coord2.xyxy, texture[%c], %s;\n" - "TEX b.g, coord2.zwzw, texture[%c], %s;\n" - "DP3 b, b, {0.25, 0.25, 0.25};\n" - "SUB b.r, a.r, b.r;\n" - "MAD yuv.%c, b.r, {%e}, a.r;\n"; + "PARAM dcoord%c = {%e, %e, %e, %e};\n" + "ADD coord, fragment.texcoord[%c].xyxy, dcoord%c;\n" + "SUB coord2, fragment.texcoord[%c].xyxy, dcoord%c;\n" + "TEX a.r, fragment.texcoord[%c], texture[%c], %s;\n" + "TEX b.r, coord.xyxy, texture[%c], %s;\n" + "TEX b.g, coord.zwzw, texture[%c], %s;\n" + "ADD b.r, b.r, b.g;\n" + "TEX b.b, coord2.xyxy, texture[%c], %s;\n" + "TEX b.g, coord2.zwzw, texture[%c], %s;\n" + "DP3 b, b, {0.25, 0.25, 0.25};\n" + "SUB b.r, a.r, b.r;\n" + "MAD yuv.%c, b.r, {%e}, a.r;\n"; static const char *unsharp_filt_template2 = - "PARAM dcoord%c = {%e, %e, %e, %e};\n" - "PARAM dcoord2%c = {%e, 0, 0, %e};\n" - "ADD coord, fragment.texcoord[%c].xyxy, dcoord%c;\n" - "SUB coord2, fragment.texcoord[%c].xyxy, dcoord%c;\n" - "TEX a.r, fragment.texcoord[%c], texture[%c], %s;\n" - "TEX b.r, coord.xyxy, texture[%c], %s;\n" - "TEX b.g, coord.zwzw, texture[%c], %s;\n" - "ADD b.r, b.r, b.g;\n" - "TEX b.b, coord2.xyxy, texture[%c], %s;\n" - "TEX b.g, coord2.zwzw, texture[%c], %s;\n" - "ADD b.r, b.r, b.b;\n" - "ADD b.a, b.r, b.g;\n" - "ADD coord, fragment.texcoord[%c].xyxy, dcoord2%c;\n" - "SUB coord2, fragment.texcoord[%c].xyxy, dcoord2%c;\n" - "TEX b.r, coord.xyxy, texture[%c], %s;\n" - "TEX b.g, coord.zwzw, texture[%c], %s;\n" - "ADD b.r, b.r, b.g;\n" - "TEX b.b, coord2.xyxy, texture[%c], %s;\n" - "TEX b.g, coord2.zwzw, texture[%c], %s;\n" - "DP4 b.r, b, {-0.1171875, -0.1171875, -0.1171875, -0.09765625};\n" - "MAD b.r, a.r, {0.859375}, b.r;\n" - "MAD yuv.%c, b.r, {%e}, a.r;\n"; + "PARAM dcoord%c = {%e, %e, %e, %e};\n" + "PARAM dcoord2%c = {%e, 0, 0, %e};\n" + "ADD coord, fragment.texcoord[%c].xyxy, dcoord%c;\n" + "SUB coord2, fragment.texcoord[%c].xyxy, dcoord%c;\n" + "TEX a.r, fragment.texcoord[%c], texture[%c], %s;\n" + "TEX b.r, coord.xyxy, texture[%c], %s;\n" + "TEX b.g, coord.zwzw, texture[%c], %s;\n" + "ADD b.r, b.r, b.g;\n" + "TEX b.b, coord2.xyxy, texture[%c], %s;\n" + "TEX b.g, coord2.zwzw, texture[%c], %s;\n" + "ADD