gl_common.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,599 行 · 第 1/4 页
C
1,599 行
/** * \file gl_common.c * \brief OpenGL helper functions used by vo_gl.c and vo_gl2.c * * Common OpenGL routines. * Copyleft (C) Reimar Döffinger <Reimar.Doeffinger@stud.uni-karlsruhe.de>, 2005 * Licensend under the GNU GPL v2 or later. * Special thanks go to the xine team and Matthias Hopf, whose video_out_opengl.c * gave me lots of good ideas. */#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <ctype.h>#include <math.h>#include "gl_common.h"#undef memcpy#define memcpy uc_memcpy/** * \defgroup glextfunctions OpenGL extension functions * * the pointers to these functions are acquired when the OpenGL * context is created * \{ */void (APIENTRY *GenBuffers)(GLsizei, GLuint *);void (APIENTRY *DeleteBuffers)(GLsizei, const GLuint *);void (APIENTRY *BindBuffer)(GLenum, GLuint);GLvoid* (APIENTRY *MapBuffer)(GLenum, GLenum); GLboolean (APIENTRY *UnmapBuffer)(GLenum);void (APIENTRY *BufferData)(GLenum, intptr_t, const GLvoid *, GLenum);void (APIENTRY *CombinerParameterfv)(GLenum, const GLfloat *);void (APIENTRY *CombinerParameteri)(GLenum, GLint);void (APIENTRY *CombinerInput)(GLenum, GLenum, GLenum, GLenum, GLenum, GLenum);void (APIENTRY *CombinerOutput)(GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean);void (APIENTRY *BeginFragmentShader)(void);void (APIENTRY *EndFragmentShader)(void);void (APIENTRY *SampleMap)(GLuint, GLuint, GLenum);void (APIENTRY *ColorFragmentOp2)(GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);void (APIENTRY *ColorFragmentOp3)(GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);void (APIENTRY *SetFragmentShaderConstant)(GLuint, const GLfloat *);void (APIENTRY *ActiveTexture)(GLenum);void (APIENTRY *BindTexture)(GLenum, GLuint);void (APIENTRY *MultiTexCoord2f)(GLenum, GLfloat, GLfloat);void (APIENTRY *GenPrograms)(GLsizei, GLuint *);void (APIENTRY *DeletePrograms)(GLsizei, const GLuint *);void (APIENTRY *BindProgram)(GLenum, GLuint);void (APIENTRY *ProgramString)(GLenum, GLenum, GLsizei, const GLvoid *);void (APIENTRY *GetProgramiv)(GLenum, GLenum, GLint *);void (APIENTRY *ProgramEnvParameter4f)(GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);int (APIENTRY *SwapInterval)(int);void (APIENTRY *TexImage3D)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);/** \} */ // end of glextfunctions group//! \defgroup glgeneral OpenGL general helper functions//! \defgroup glcontext OpenGL context management helper functions//! \defgroup gltexture OpenGL texture handling helper functions//! \defgroup glconversion OpenGL conversion helper functionsstatic 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; glPixelStorei (GL_UNPACK_ALIGNMENT, gl_alignment);}struct gl_name_map_struct { GLint value; const char *name;};#undef MAP#define MAP(a) {a, #a}//! mapping table for the glValName functionstatic 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), // 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/** * \brief return the name of an OpenGL constant * \param value the constant * \return name of the constant or "Unknown format!" * \ingroup glgeneral */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!";}//! always return this format as internal texture format in glFindFormat#define TEXTUREFORMAT_ALWAYS GL_RGB8#undef TEXTUREFORMAT_ALWAYS/** * \brief find the OpenGL settings coresponding to format. * * All parameters may be NULL. * \param fmt MPlayer format to analyze. * \param bpp [OUT] bits per pixel of that format. * \param gl_texfmt [OUT] internal texture format that fits the * image format, not necessarily the best for performance. * \param gl_format [OUT] OpenGL format for this image format. * \param gl_type [OUT] OpenGL type for this image format. * \return 1 if format is supported by OpenGL, 0 if not. * \ingroup gltexture */int glFindFormat(uint32_t fmt, int *bpp, GLint *gl_texfmt, GLenum *gl_format, GLenum *gl_type){ int supported = 1; int dummy1; GLenum dummy2; GLint dummy3; if (bpp == NULL) bpp = &dummy1; if (gl_texfmt == NULL) gl_texfmt = &dummy3; if (gl_format == NULL) gl_format = &dummy2; if (gl_type == NULL) gl_type = &dummy2; *bpp = IMGFMT_IS_BGR(fmt)?IMGFMT_BGR_DEPTH(fmt):IMGFMT_RGB_DEPTH(fmt); *gl_texfmt = 3; switch (fmt) { case IMGFMT_RGB24: *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; case IMGFMT_YV12: 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;#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;#endif case IMGFMT_RGB15: *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;#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;#endif case IMGFMT_BGR15: *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; case IMGFMT_BGR24: *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; default: *gl_texfmt = 4; *gl_format = GL_RGBA; *gl_type = GL_UNSIGNED_BYTE; supported = 0; }#ifdef TEXTUREFORMAT_ALWAYS *gl_texfmt = TEXTUREFORMAT_ALWAYS;#endif return supported;}static void *setNull(const GLubyte *s) { return NULL;}typedef struct { void **funcptr; const char *extstr; const char *funcnames[7];} extfunc_desc_t;static const extfunc_desc_t extfuncs[] = { {(void **)&GenBuffers, NULL, {"glGenBuffers", "glGenBuffersARB", NULL}}, {(void **)&DeleteBuffers, NULL, {"glDeleteBuffers", "glDeleteBuffersARB", NULL}}, {(void **)&BindBuffer, NULL, {"glBindBuffer", "glBindBufferARB", NULL}}, {(void **)&MapBuffer, NULL, {"glMapBuffer", "glMapBufferARB", NULL}}, {(void **)&UnmapBuffer, NULL, {"glUnmapBuffer", "glUnmapBufferARB", NULL}}, {(void **)&BufferData, NULL, {"glBufferData", "glBufferDataARB", NULL}}, {(void **)&CombinerParameterfv, "NV_register_combiners", {"glCombinerParameterfv", "glCombinerParameterfvNV", NULL}}, {(void **)&CombinerParameteri, "NV_register_combiners", {"glCombinerParameteri", "glCombinerParameteriNV", NULL}}, {(void **)&CombinerInput, "NV_register_combiners", {"glCombinerInput", "glCombinerInputNV", NULL}}, {(void **)&CombinerOutput, "NV_register_combiners", {"glCombinerOutput", "glCombinerOutputNV", NULL}}, {(void **)&BeginFragmentShader, "ATI_fragment_shader", {"glBeginFragmentShaderATI", NULL}}, {(void **)&EndFragmentShader, "ATI_fragment_shader", {"glEndFragmentShaderATI", NULL}}, {(void **)&SampleMap, "ATI_fragment_shader", {"glSampleMapATI", NULL}}, {(void **)&ColorFragmentOp2, "ATI_fragment_shader", {"glColorFragmentOp2ATI", NULL}}, {(void **)&ColorFragmentOp3, "ATI_fragment_shader", {"glColorFragmentOp3ATI", NULL}}, {(void **)&SetFragmentShaderConstant, "ATI_fragment_shader", {"glSetFragmentShaderConstantATI", NULL}}, {(void **)&ActiveTexture, NULL, {"glActiveTexture", "glActiveTextureARB", NULL}}, {(void **)&BindTexture, NULL, {"glBindTexture", "glBindTextureARB", "glBindTextureEXT", NULL}}, {(void **)&MultiTexCoord2f, NULL, {"glMultiTexCoord2f", "glMultiTexCoord2fARB", NULL}}, {(void **)&GenPrograms, "_program", {"glGenProgramsARB", NULL}}, {(void **)&DeletePrograms, "_program", {"glDeleteProgramsARB", NULL}}, {(void **)&BindProgram, "_program", {"glBindProgramARB", NULL}}, {(void **)&ProgramString, "_program", {"glProgramStringARB", NULL}}, {(void **)&GetProgramiv, "_program", {"glGetProgramivARB", NULL}}, {(void **)&ProgramEnvParameter4f, "_program", {"glProgramEnvParameter4fARB", NULL}}, {(void **)&SwapInterval, "_swap_control", {"glXSwapInterval", "glXSwapIntervalEXT", "glXSwapIntervalSGI", "wglSwapInterval", "wglSwapIntervalEXT", "wglSwapIntervalSGI", NULL}}, {(void **)&TexImage3D, NULL, {"glTexImage3D", NULL}}, {NULL}};/** * \brief find the function pointers of some useful OpenGL extensions * \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 = (const char *)glGetString(GL_EXTENSIONS); char *allexts; 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_V, "OpenGL extensions string:\n%s\n", allexts); if (!getProcAddress) getProcAddress = setNull; 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]); } *(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);}/** * \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 * \ingroup gltexture */void glCreateClearTex(GLenum target, GLenum fmt, GLint filter, int w, int h, unsigned char val) { GLfloat fval = (GLfloat)val / 255.0; GLfloat border[4] = {fval, fval, fval, fval}; GLenum clrfmt = (fmt == GL_ALPHA) ? GL_ALPHA : GL_LUMINANCE; char *init = 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_TO_EDGE); glTexParameteri(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. glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, border); free(init);}/** * \brief skips whitespace and comments * \param f file to read from */static void ppm_skip(FILE *f) { int c, comment = 0; do { c = fgetc(f); if (c == '#') comment = 1; if (c == '\n') comment = 0; } while (c != EOF && (isspace(c) || comment)); if (c != EOF) ungetc(c, f);}#define MAXDIM (16 * 1024)/** * \brief creates a texture from a PPM file * \param target texture taget, usually GL_TEXTURE_2D * \param fmt internal texture format, 0 for default * \param filter filter used for scaling, e.g. GL_LINEAR * \param f file to read PPM from * \param width [out] width of texture * \param height [out] height of texture * \param maxval [out] maxval value from PPM file * \return 0 on error, 1 otherwise * \ingroup gltexture */int glCreatePPMTex(GLenum target, GLenum fmt, GLint filter, FILE *f, int *width, int *height, int *maxval) { unsigned w, h, m, val, bpp; char *data; ppm_skip(f); if (fgetc(f) != 'P' || fgetc(f) != '6') return 0; ppm_skip(f); if (fscanf(f, "%u", &w) != 1) return 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?