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 + -
显示快捷键?