vo_gl2.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 925 行 · 第 1/2 页

C
925
字号
/* * video_out_gl.c, X11/OpenGL interface * based on video_out_x11 by Aaron Holtzman, * and WS opengl window manager by Pontscho/Fresh! */#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include "config.h"#include "mp_msg.h"#include "subopt-helper.h"#include "video_out.h"#include "video_out_internal.h"#include "sub.h"#include "gl_common.h"#include "aspect.h"#ifdef HAVE_NEW_GUI#include "gui/interface.h"#endif#undef TEXTUREFORMAT_ALWAYS#ifdef SYS_DARWIN#define TEXTUREFORMAT_ALWAYS GL_RGBA8#endif//! force texture height, useful for debugging#define TEXTURE_HEIGHT 128#undef TEXTURE_HEIGHT//! force texture width, useful for debugging#define TEXTURE_WIDTH 128#undef TEXTURE_WIDTHstatic vo_info_t info ={  "X11 (OpenGL) - multiple textures version",  "gl2",  "Arpad Gereoffy & Sven Goethel",  ""};LIBVO_EXTERN(gl2)/* local data */static unsigned char *ImageData=NULL;#ifdef GL_WIN32    static int gl_vinfo = 0;    static HGLRC gl_context = 0;#define update_xinerama_info w32_update_xinerama_info#define vo_init vo_w32_init#define vo_window vo_w32_window#else    static XVisualInfo *gl_vinfo = NULL;    static GLXContext gl_context = 0;#endifstatic uint32_t image_width;static uint32_t image_height;static uint32_t image_format;static uint32_t image_bpp;static uint32_t image_bytes;static int int_pause;static uint32_t texture_width;static uint32_t texture_height;static int texnumx, texnumy, raw_line_len;static int texdirty;static struct TexSquare * texgrid = NULL;static GLuint   fragprog;static GLuint   lookupTex;static GLint    gl_internal_format;static int      rgb_sz, r_sz, g_sz, b_sz, a_sz;static GLenum   gl_bitmap_format;static GLenum   gl_bitmap_type;static int      isGL12 = GL_FALSE;static int      gl_bilinear=1;static int      gl_antialias=0;static int      use_yuv;static int      use_glFinish;static void (*draw_alpha_fnc)                 (int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);/* The squares that are tiled to make up the game screen polygon */struct TexSquare{  GLubyte *texture;  GLuint texobj;  GLuint uvtexobjs[2];  GLfloat fx, fy, fw, fh;};static GLint getInternalFormat(void){#ifdef GL_WIN32  PIXELFORMATDESCRIPTOR pfd;  HDC vo_hdc = GetDC(vo_window);  int pf = GetPixelFormat(vo_hdc);  if (!DescribePixelFormat(vo_hdc, pf, sizeof pfd, &pfd)) {    r_sz = g_sz = b_sz = a_sz = 0;  } else {    r_sz = pfd.cRedBits;    g_sz = pfd.cGreenBits;    b_sz = pfd.cBlueBits;    a_sz = pfd.cAlphaBits;  }  ReleaseDC(vo_window, vo_hdc);#else  if (glXGetConfig(mDisplay, gl_vinfo, GLX_RED_SIZE, &r_sz) != 0) r_sz = 0;  if (glXGetConfig(mDisplay, gl_vinfo, GLX_GREEN_SIZE, &g_sz) != 0) g_sz = 0;  if (glXGetConfig(mDisplay, gl_vinfo, GLX_BLUE_SIZE, &b_sz) != 0) b_sz = 0;  if (glXGetConfig(mDisplay, gl_vinfo, GLX_ALPHA_SIZE, &a_sz) != 0) a_sz = 0;#endif  rgb_sz=r_sz+g_sz+b_sz;  if(rgb_sz<=0) rgb_sz=24;#ifdef TEXTUREFORMAT_ALWAYS  return TEXTUREFORMAT_ALWAYS;#else  if(r_sz==3 && g_sz==3 && b_sz==2 && a_sz==0)    return GL_R3_G3_B2;  if(r_sz==4 && g_sz==4 && b_sz==4 && a_sz==0)    return GL_RGB4;  if(r_sz==5 && g_sz==5 && b_sz==5 && a_sz==0)    return GL_RGB5;  if(r_sz==8 && g_sz==8 && b_sz==8 && a_sz==0)    return GL_RGB8;  if(r_sz==10 && g_sz==10 && b_sz==10 && a_sz==0)    return GL_RGB10;  if(r_sz==2 && g_sz==2 && b_sz==2 && a_sz==2)    return GL_RGBA2;  if(r_sz==4 && g_sz==4 && b_sz==4 && a_sz==4)    return GL_RGBA4;  if(r_sz==5 && g_sz==5 && b_sz==5 && a_sz==1)    return GL_RGB5_A1;  if(r_sz==8 && g_sz==8 && b_sz==8 && a_sz==8)    return GL_RGBA8;  if(r_sz==10 && g_sz==10 && b_sz==10 && a_sz==2)    return GL_RGB10_A2;#endif  return GL_RGB;}static int initTextures(void){  struct TexSquare *tsq=0;  GLfloat texpercx, texpercy;  int s;  int x=0, y=0;  GLint format=0;  // textures smaller than 64x64 might not be supported  s=64;  while (s<image_width)    s*=2;  texture_width=s;  s=64;  while (s<image_height)    s*=2;  texture_height=s;  if (image_format != IMGFMT_YV12)  gl_internal_format = getInternalFormat();  /* Test the max texture size */  do {    glTexImage2D (GL_PROXY_TEXTURE_2D, 0,                  gl_internal_format,                  texture_width, texture_height,                  0, gl_bitmap_format, gl_bitmap_type, NULL);    glGetTexLevelParameteriv      (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);    if (format != gl_internal_format)    {      mp_msg (MSGT_VO, MSGL_V, "[gl2] Needed texture [%dx%d] too big, trying ",              texture_height, texture_width);      if (texture_width > texture_height)        texture_width /= 2;      else        texture_height /= 2;      mp_msg (MSGT_VO, MSGL_V, "[%dx%d] !\n", texture_height, texture_width);      if(texture_width < 64 || texture_height < 64) {        mp_msg (MSGT_VO, MSGL_FATAL, "[gl2] Give up .. usable texture size not avaiable, or texture config error !\n");        return -1;      }    }  }  while (format != gl_internal_format && texture_width > 1 && texture_height > 1);#ifdef TEXTURE_WIDTH  texture_width = TEXTURE_WIDTH;#endif#ifdef TEXTURE_HEIGHT  texture_height = TEXTURE_HEIGHT;#endif  texnumx = image_width / texture_width;  if ((image_width % texture_width) > 0)    texnumx++;  texnumy = image_height / texture_height;  if ((image_height % texture_height) > 0)    texnumy++;  mp_msg(MSGT_VO, MSGL_V, "[gl2] Creating %dx%d textures of size %dx%d ...\n",         texnumx, texnumy, texture_width,texture_height);  /* Allocate the texture memory */  texpercx = (GLfloat) texture_width / (GLfloat) image_width;  texpercy = (GLfloat) texture_height / (GLfloat) image_height;  if (texgrid)    free(texgrid);  texgrid = calloc (texnumx * texnumy, sizeof (struct TexSquare));  raw_line_len = image_width * image_bytes;  mp_msg (MSGT_VO, MSGL_DBG2, "[gl2] texture-usage %d*width=%d, %d*height=%d\n",          (int) texnumx, (int) texture_width, (int) texnumy,          (int) texture_height);  tsq = texgrid;  for (y = 0; y < texnumy; y++) {    for (x = 0; x < texnumx; x++) {      tsq->fx = x * texpercx;      tsq->fy = y * texpercy;      tsq->fw = texpercx;      tsq->fh = texpercy;      tsq->texobj=0;      tsq->uvtexobjs[0] = tsq->uvtexobjs[1] = 0;      glGenTextures (1, &(tsq->texobj));      glBindTexture (GL_TEXTURE_2D, tsq->texobj);      if (image_format == IMGFMT_YV12) {        glGenTextures(2, tsq->uvtexobjs);        ActiveTexture(GL_TEXTURE1);        glBindTexture (GL_TEXTURE_2D, tsq->uvtexobjs[0]);        ActiveTexture(GL_TEXTURE2);        glBindTexture (GL_TEXTURE_2D, tsq->uvtexobjs[1]);        ActiveTexture(GL_TEXTURE0);      }      glCreateClearTex(GL_TEXTURE_2D, gl_internal_format, GL_LINEAR,                       texture_width, texture_height, 0);      glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);      if (image_format == IMGFMT_YV12) {        ActiveTexture(GL_TEXTURE1);        glCreateClearTex(GL_TEXTURE_2D, gl_internal_format, GL_LINEAR,                         texture_width / 2, texture_height / 2, 128);        ActiveTexture(GL_TEXTURE2);        glCreateClearTex(GL_TEXTURE_2D, gl_internal_format, GL_LINEAR,                         texture_width / 2, texture_height / 2, 128);        ActiveTexture(GL_TEXTURE0);      }      tsq++;    }  /* for all texnumx */  }  /* for all texnumy */  return 0;}static void resetTexturePointers(unsigned char *imageSource){  unsigned char *texdata_start, *line_start;  struct TexSquare *tsq = texgrid;  int x=0, y=0;  line_start = (unsigned char *) imageSource;  for (y = 0; y < texnumy; y++) {    texdata_start = line_start;    for (x = 0; x < texnumx; x++) {      tsq->texture = texdata_start;      texdata_start += texture_width * image_bytes;      tsq++;    }  /* for all texnumx */    line_start += texture_height * raw_line_len;  }  /* for all texnumy */}static void gl_set_bilinear (int val){  int x, y;  if(val>=0)    gl_bilinear = val;  else    gl_bilinear++;  gl_bilinear=gl_bilinear%2;  /* no mipmap yet .. */  for (y = 0; y < texnumy; y++) {    for (x = 0; x < texnumx; x++) {      glBindTexture (GL_TEXTURE_2D, texgrid[y * texnumx + x].texobj);      switch (gl_bilinear) {        case 0:          glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);          glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);          mp_msg(MSGT_VO, MSGL_INFO, "[gl2] bilinear off\n");          break;        case 1:          glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);          glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);          mp_msg(MSGT_VO, MSGL_INFO, "[gl2] bilinear linear\n");          break;        case 2:          glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);          glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);          mp_msg(MSGT_VO, MSGL_INFO, "[gl2] bilinear mipmap nearest\n");          break;        case 3:          glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);          glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);          mp_msg(MSGT_VO, MSGL_INFO, "[gl2] bilinear mipmap linear\n");          break;      }    }  }}static void gl_set_antialias (int val){  gl_antialias=val;  if (gl_antialias) {    glShadeModel (GL_SMOOTH);    glEnable (GL_POLYGON_SMOOTH);    glEnable (GL_LINE_SMOOTH);    glEnable (GL_POINT_SMOOTH);    mp_msg(MSGT_VO, MSGL_INFO, "[gl2] antialiasing on\n");  } else {    glShadeModel (GL_FLAT);    glDisable (GL_POLYGON_SMOOTH);    glDisable (GL_LINE_SMOOTH);    glDisable (GL_POINT_SMOOTH);    mp_msg(MSGT_VO, MSGL_INFO, "[gl2] antialiasing off\n");  }}static void drawTextureDisplay (void){  struct TexSquare *square = texgrid;  int x, y;  glColor3f(1.0,1.0,1.0);  if (image_format == IMGFMT_YV12)    glEnableYUVConversion(GL_TEXTURE_2D, use_yuv);  for (y = 0; y < texnumy; y++) {    int thish = texture_height;    if (y == texnumy - 1 && image_height % texture_height)      thish = image_height % texture_height;    for (x = 0; x < texnumx; x++) {      int thisw = texture_width;      if (x == texnumx - 1 && image_width % texture_width)        thisw = image_width % texture_width;      glBindTexture (GL_TEXTURE_2D, square->texobj);      if (image_format == IMGFMT_YV12) {        ActiveTexture(GL_TEXTURE1);        glBindTexture (GL_TEXTURE_2D, square->uvtexobjs[0]);        ActiveTexture(GL_TEXTURE2);        glBindTexture (GL_TEXTURE_2D, square->uvtexobjs[1]);        ActiveTexture(GL_TEXTURE0);      }      if (texdirty) {        glUploadTex(GL_TEXTURE_2D, gl_bitmap_format,  gl_bitmap_type,                    square->texture, image_width * image_bytes,                    0, 0, thisw, thish, 0);      }      glDrawTex(square->fx, square->fy, square->fw, square->fh,                0, 0, texture_width, texture_height,                texture_width, texture_height,                0, image_format == IMGFMT_YV12, 0);      square++;    } /* for all texnumx */  } /* for all texnumy */  if (image_format == IMGFMT_YV12)    glDisableYUVConversion(GL_TEXTURE_2D, use_yuv);  texdirty = 0;}static void resize(int *x,int *y){  mp_msg(MSGT_VO,MSGL_V,"[gl2] Resize: %dx%d\n",*x,*y);  if( vo_fs ) {    glClear(GL_COLOR_BUFFER_BIT);    aspect(x, y, A_ZOOM);    panscan_calc();    *x += vo_panscan_x;    *y += vo_panscan_y;    glViewport( (vo_screenwidth-*x)/2, (vo_screenheight-*y)/2, *x, *y);  } else {    //aspect(x, y, A_NOZOOM);    if (WinID >= 0) {      int top = 0, left = 0, w = *x, h = *y;      geometry(&top, &left, &w, &h, vo_screenwidth, vo_screenheight);      glViewport(top, left, w, h);    } else      glViewport( 0, 0, *x, *y );  }  glMatrixMode(GL_PROJECTION);  glLoadIdentity();  glOrtho (0, 1, 1, 0, -1.0, 1.0);  glMatrixMode(GL_MODELVIEW);  glLoadIdentity();}static void draw_alpha_32(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){   vo_draw_alpha_rgb32(w,h,src,srca,stride,ImageData+4*(y0*image_width+x0),4*image_width);}static void draw_alpha_24(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){   vo_draw_alpha_rgb24(w,h,src,srca,stride,ImageData+3*(y0*image_width+x0),3*image_width);}static void draw_alpha_16(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){   vo_draw_alpha_rgb16(w,h,src,srca,stride,ImageData+2*(y0*image_width+x0),2*image_width);}static void draw_alpha_15(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){   vo_draw_alpha_rgb15(w,h,src,srca,stride,ImageData+2*(y0*image_width+x0),2*image_width);}static void draw_alpha_null(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){}#ifdef GL_WIN32static int config_w32(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format) {  if (!vo_w32_config(d_width, d_height, flags))    return -1;  if (vo_fs)    aspect(&d_width, &d_height, A_ZOOM);  return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?