Experimental vo_gl with (limited) support for hardware YUV.

Reimar Döffinger <[email protected]> Fri, 23 Apr 2004 23:39:14 +0200
Newsgroups gmane.comp.video.mplayer.g2.devel
Message-ID <[email protected]>
This is a multi-part message in MIME format.
--------------010405090309040607050200
Content-Type: text/plain; charset=ISO-8859-15; format=flowed
Content-Transfer-Encoding: quoted-printable

Hi,
just thought I let everyone have a look at what I'm currently working=20
on. It can play YUV directly on nVidia GPUs better than GeForce3, but=20
probably won't work at all with older cards :( - it's still a long way=20
till it's finished, but I hope the concept will be extensible enough.
On my PC it uses slightly less CPU even than xv (even with=20
sync-to-vblank enabled).
As always comments or test results are welcome.

Greetings,
Reimar D=F6ffinger

--------------010405090309040607050200
Content-Type: text/plain;
 name="vo_gl.c"
Content-Disposition: inline;
 filename="vo_gl.c"
Content-Transfer-Encoding: quoted-printable


#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#include "config.h"
#include "mp_msg.h"

#include "video_out.h"
#include "video/vfcap.h"
#include "video/img_format.h"

#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glx.h>

#define DEFAULT_INTERNAL_FORMAT GL_RGB

typedef enum {
  VO_GL_NO_CONV, VO_GL_REG_COMB_CONV, VO_GL_FRAG_PROG_CONV
} glConvType;

struct vo_buffer_priv_s {
  GLuint planeTexture[4];
  GLuint glDisplayList;
};

struct vo_priv_s {
  Window window;
  Display *display;
  int img_width;
  int img_height;
  int d_width;
  int d_height;
  char numPlanes;
  GLint planeInternalFormat[4];
  GLsizei planeTextureWidth[4];
  GLsizei planeTextureHeight[4];
  int planeWidth[4];
  int planeHeight[4];
  char planeBytesPerPixel[4];
  GLenum planeFormat[4];
  GLenum planeType[4];
  glConvType conversion;
  char supportYUV;
  char useGL12;
  XVisualInfo vinfo;
  GLXContext context;
  glConvType bestYUVConversion;
  void (APIENTRY * glCombinerParameterfv) (GLenum, const GLfloat *);
  void (APIENTRY * glCombinerParameteri) (GLenum, GLint);
  void (APIENTRY * glCombinerInput) (GLenum, GLenum, GLenum, GLenum, GLen=
um,
                                     GLenum);
  void (APIENTRY * glCombinerOutput) (GLenum, GLenum, GLenum, GLenum, GLe=
num,
                                      GLenum, GLenum, GLboolean, GLboolea=
n,
                                      GLboolean);
  void (APIENTRY * glActiveTexture) (GLenum);
  void (APIENTRY * glMultiTexCoord2f) (GLenum, GLfloat, GLfloat);
};

static void resize (vo_instance_t * vo, int src[4])
{
  mp_msg (MSGT_VO, MSGL_V, "[gl] resize ");
  mp_msg (MSGT_VO, MSGL_V, "(%i, %i, %i, %i),", vo->x, vo->y, vo->w, vo->=
h);
  if (src)
    mp_msg (MSGT_VO, MSGL_V, "(%i, %i, %i, %i)\n", src[0], src[1], src[2]=
,
            src[3]);
  else
    mp_msg (MSGT_VO, MSGL_V, "NULL\n");
  glViewport (vo->x, vo->y, vo->w, vo->h);
  if (src) {
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    // FIXME: how do we find out when we should flip ??
    glTranslatef (-src[0], -src[1], 0);
    glOrtho (0, src[2], src[3], 0, -1, 1);

    glMatrixMode (GL_MODELVIEW);
    glLoadIdentity ();
  }
}

static void getGLFunctions (vo_instance_t * vo)
{
  GLint maxGeneralCombiners;
  GLint maxTextureUnits;
  vo->priv->glCombinerParameterfv =3D
    glXGetProcAddressARB ("glCombinerParameterfvNV");
  vo->priv->glCombinerParameteri =3D
    glXGetProcAddressARB ("glCombinerParameteriNV");
  vo->priv->glCombinerInput =3D glXGetProcAddressARB ("glCombinerInputNV"=
);
  vo->priv->glCombinerOutput =3D glXGetProcAddressARB ("glCombinerOutputN=
V");
  vo->priv->glActiveTexture =3D glXGetProcAddressARB ("glActiveTextureARB=
");
  vo->priv->glMultiTexCoord2f =3D glXGetProcAddressARB ("glMultiTexCoord2=
fARB");
  glGetIntegerv (GL_MAX_GENERAL_COMBINERS_NV, &maxGeneralCombiners);
  glGetIntegerv (GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
  if (maxTextureUnits >=3D 3 && maxGeneralCombiners >=3D 2)
    vo->priv->bestYUVConversion =3D VO_GL_REG_COMB_CONV;
  else
    vo->priv->bestYUVConversion =3D VO_GL_NO_CONV;
}

static int control (vo_instance_t * vo, int request, void *data, ...)
{
  switch (request) {
    case VOCTRL_SET_WINDOW:
      vo->priv->window =3D *((Window *) data);
      if (!vo->priv->context) {
        vo->priv->context =3D
          glXCreateContext (vo->priv->display, &vo->priv->vinfo, NULL, Tr=
ue);
      } else
        glFinish ();
      glXMakeCurrent (vo->priv->display, vo->priv->window, vo->priv->cont=
ext);
      return VO_TRUE;
    case VOCTRL_MOVE_DEST:
      vo->x =3D ((int *) data)[0];
      vo->y =3D ((int *) data)[1];
      resize (vo, NULL);
      return VO_TRUE;
    case VOCTRL_RESIZE_DEST:
      vo->w =3D ((int *) data)[0];
      vo->h =3D ((int *) data)[1];
      resize (vo, NULL);
      return VO_TRUE;
    case VOCTRL_RESIZE_SRC:
      resize (vo, data);
      return VO_TRUE;
  }
  return VO_NOTIMPL;
}

static unsigned int query_format (vo_instance_t * vo,
                                  unsigned int format, int width, int hei=
ght)
{
  const int supported =3D
    VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_HWSCALE_UP |
    VFCAP_HWSCALE_DOWN | VFCAP_FLIP;
  switch (format) {
    case IMGFMT_RGB8:
    case IMGFMT_RGB15:
    case IMGFMT_RGB16:
    case IMGFMT_RGB24:
    case IMGFMT_RGB32:
    case IMGFMT_BGR8:
    case IMGFMT_BGR15:
    case IMGFMT_BGR16:
    case IMGFMT_BGR24:
    case IMGFMT_BGR32:
    case IMGFMT_Y800:
    case IMGFMT_YV12:
      return supported;
  }
  return 0;
}

static void uninit (vo_instance_t * vo)
{
  if (vo->priv->context)
    glXDestroyContext (vo->priv->display, vo->priv->context);
  free (vo->priv);
  free (vo);
}

typedef struct {
  int pixelBytes;
  GLint internalFormat;
  GLenum format;
  GLenum type;
  int width_div;
  int height_div;
} PlaneInfo;

typedef struct {
  unsigned int format;
  char numPlanes;
  PlaneInfo plane[4];
} FormatInfo;

FormatInfo formatInfos[] =3D {
{
  IMGFMT_RGB8, 1, {
    {1, 0, GL_RGB, GL_UNSIGNED_BYTE_2_3_3_REV, 1, 1},
  }
}, {
  IMGFMT_RGB15, 1, {
    {2, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 1, 1},
  }
}, {
  IMGFMT_RGB16, 1, {
    {2, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, 1, 1},
  }
}, {
  IMGFMT_RGB24, 1, {
    {3, 0, GL_RGB, GL_UNSIGNED_BYTE, 1, 1},
  }
}, {
  IMGFMT_RGB32, 1, {
    {4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 1, 1},
  }
}, {
  IMGFMT_BGR8, 1, {
    {1, 0, GL_RGB, GL_UNSIGNED_BYTE_3_3_2, 1, 1},
  }
}, {
  IMGFMT_BGR15, 1, {
    {2, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 1, 1},
  }
}, {
  IMGFMT_BGR16, 1, {
    {2, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 1, 1},
  }
}, {
  IMGFMT_BGR24, 1, {
    {3, 0, GL_BGR, GL_UNSIGNED_BYTE, 1, 1},
  }
}, {
  IMGFMT_BGR32, 1, {
    {4, 0, GL_BGRA, GL_UNSIGNED_BYTE, 1, 1},
  }
}, {
  IMGFMT_Y800, 1, {
    {1, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1, 1},
  }
}, {
  IMGFMT_YV12, 3, {
    {1, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1, 1},
    {1, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 2, 2},
    {1, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 2, 2},
  }
}, {
  IMGFMT_444P, 3, {
    {1, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1, 1},
    {1, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1, 1},
    {1, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1, 1},
  }
}, {
  0, 0, {
    {0, 0, 0, 0, 0, 0},
  }
}
};

static void analyzeFormat (vo_instance_t * vo, unsigned int format)
{
  int i =3D 0;
  FormatInfo *fi;
  while (formatInfos[i].format !=3D 0 && formatInfos[i].format !=3D forma=
t)
    i++;
  if (formatInfos[i].format !=3D format) {
    mp_msg (MSGT_VO, MSGL_ERR,
            "[gl] Unknown image format. This shouldn't happen!\n");
  };
  fi =3D &formatInfos[i];
  vo->priv->numPlanes =3D fi->numPlanes;
  for (i =3D 0; i < fi->numPlanes; i++) {
    vo->priv->planeWidth[i] =3D vo->priv->img_width / fi->plane[i].width_=
div;
    vo->priv->planeHeight[i] =3D vo->priv->img_height / fi->plane[i].heig=
ht_div;
    vo->priv->planeBytesPerPixel[i] =3D fi->plane[i].pixelBytes;
    if (fi->plane[i].internalFormat !=3D 0)
      vo->priv->planeInternalFormat[i] =3D fi->plane[i].internalFormat;
    else
      vo->priv->planeInternalFormat[i] =3D DEFAULT_INTERNAL_FORMAT;
    vo->priv->planeFormat[i] =3D fi->plane[i].format;
    vo->priv->planeType[i] =3D fi->plane[i].type;
  }
}

static void findTextureSizes (vo_instance_t * vo)
{
  int i, tmp;
  for (i =3D 0; i < vo->priv->numPlanes; i++) {
    tmp =3D 1;
    while (tmp < vo->priv->planeWidth[i])
      tmp *=3D 2;
    vo->priv->planeTextureWidth[i] =3D tmp;
    tmp =3D 1;
    while (tmp < vo->priv->planeHeight[i])
      tmp *=3D 2;
    vo->priv->planeTextureHeight[i] =3D tmp;
  }
}

static void createTextures (vo_instance_t * vo, vo_buffer_t * buf)
{
  int i;
  char *texInitData =3D NULL;
  char initVal =3D 0;
  GLfloat borderColor[4];
  int size;

  glGenTextures (vo->priv->numPlanes, buf->priv->planeTexture);
  for (i =3D 0; i < vo->priv->numPlanes; i++) {
    glActiveTexture (GL_TEXTURE0 + i);
    glEnable (GL_TEXTURE_2D);
    glBindTexture (GL_TEXTURE_2D, buf->priv->planeTexture[i]);
    glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    mp_msg (MSGT_VO, MSGL_V,
            "[gl] Allocating texture of size %dx%d ...\n",
            vo->priv->planeTextureWidth[i], vo->priv->planeTextureHeight[=
i]);
    size =3D vo->priv->planeTextureWidth[i] * vo->priv->planeTextureHeigh=
t[i];
    texInitData =3D malloc (size);
    if (i =3D=3D 0) {
      borderColor[0] =3D 0.0;
      borderColor[1] =3D 0.0;
      borderColor[2] =3D 0.0;
      borderColor[3] =3D 0.0;
      initVal =3D 0;
    } else {                    // no green borders in YUV
      borderColor[0] =3D 0.5;
      borderColor[1] =3D 0.5;
      borderColor[2] =3D 0.5;
      borderColor[3] =3D 0.0;
      initVal =3D 128;
    }
    memset (texInitData, initVal, size);
    glTexImage2D (GL_TEXTURE_2D, 0, vo->priv->planeInternalFormat[i],
                  vo->priv->planeTextureWidth[i],
                  vo->priv->planeTextureHeight[i], 0, GL_LUMINANCE,
                  GL_UNSIGNED_BYTE, texInitData);
    mp_msg (MSGT_VO, MSGL_V, "[gl] glTexImage2D finished with %d\n",
            glGetError ());
    free (texInitData);
    glTexParameterfv (GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor=
);
  }
}

static void setupConversion (vo_instance_t * vo)
{
  int i;
  GLfloat ucoef[] =3D { 0, -0.344, 1.770, 0 };
  GLfloat vcoef[] =3D { 1.403, -0.714, 0, 0 };

  switch (vo->priv->conversion) {
    case VO_GL_NO_CONV:
      break;
    case VO_GL_REG_COMB_CONV:
      // It seems that coefficient must be in [0,1] range, so here comes
      // the trick:
      // first put them in [-0.5, 0.5] range, then add 0.5;
      // can be undone with the HALF_BIAS and SCALE_BY_FOUR arguments
      // for CombinerInput and CombinerOutput
      for (i =3D 0; i < 4; i++) {
        ucoef[i] =3D ucoef[i] * 0.25 + 0.5;
        vcoef[i] =3D vcoef[i] * 0.25 + 0.5;
      }

      vo->priv->glCombinerParameterfv (GL_CONSTANT_COLOR0_NV, ucoef);
      vo->priv->glCombinerParameterfv (GL_CONSTANT_COLOR1_NV, vcoef);

      // UV first, like this green component can't overflow
      vo->priv->glCombinerInput (GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_N=
V,
                                 GL_TEXTURE1, GL_HALF_BIAS_NORMAL_NV, GL_=
RGB);
      vo->priv->glCombinerInput (GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_N=
V,
                                 GL_CONSTANT_COLOR0_NV,
                                 GL_HALF_BIAS_NORMAL_NV, GL_RGB);
      vo->priv->glCombinerInput (GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_N=
V,
                                 GL_TEXTURE2, GL_HALF_BIAS_NORMAL_NV, GL_=
RGB);
      vo->priv->glCombinerInput (GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_N=
V,
                                 GL_CONSTANT_COLOR1_NV,
                                 GL_HALF_BIAS_NORMAL_NV, GL_RGB);
      vo->priv->glCombinerOutput (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);

      vo->priv->glCombinerInput (GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_N=
V,
                                 GL_SPARE0_NV, GL_SIGNED_IDENTITY_NV, GL_=
RGB);
      vo->priv->glCombinerInput (GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_N=
V,
                                 GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB);
      vo->priv->glCombinerInput (GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_C_N=
V,
                                 GL_TEXTURE0, GL_SIGNED_IDENTITY_NV, GL_R=
GB);
      vo->priv->glCombinerInput (GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_D_N=
V,
                                 GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB);
      vo->priv->glCombinerOutput (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
      vo->priv->glCombinerParameteri (GL_NUM_GENERAL_COMBINERS_NV, 2);
      break;
    case VO_GL_FRAG_PROG_CONV:
      break;
    default:
      mp_msg (MSGT_VO, MSGL_ERR, "[gl] unknown conversion type!");
      break;
  }
}

static void activateConversion (vo_instance_t * vo, vo_buffer_t * buf)
{
  glActiveTexture (GL_TEXTURE0);
  glBindTexture (GL_TEXTURE_2D, buf->priv->planeTexture[0]);
  switch (vo->priv->conversion) {
    case VO_GL_NO_CONV:
      break;
    case VO_GL_REG_COMB_CONV:
      vo->priv->glActiveTexture (GL_TEXTURE0);
      glBindTexture (GL_TEXTURE_2D, buf->priv->planeTexture[0]);
      vo->priv->glActiveTexture (GL_TEXTURE1);
      glBindTexture (GL_TEXTURE_2D, buf->priv->planeTexture[2]);
      vo->priv->glActiveTexture (GL_TEXTURE2);
      glBindTexture (GL_TEXTURE_2D, buf->priv->planeTexture[1]);
      glEnable (GL_REGISTER_COMBINERS_NV);
      break;
    case VO_GL_FRAG_PROG_CONV:
      break;
    default:
      mp_msg (MSGT_VO, MSGL_ERR, "[gl] unknown conversion type!");
      break;
  }
}

static void deactivateConversion (vo_instance_t * vo, vo_buffer_t * buf)
{
  switch (vo->priv->conversion) {
    case VO_GL_NO_CONV:
      break;
    case VO_GL_REG_COMB_CONV:
      glDisable (GL_REGISTER_COMBINERS_NV);
      break;
    case VO_GL_FRAG_PROG_CONV:
      break;
    default:
      mp_msg (MSGT_VO, MSGL_ERR, "[gl] unknown conversion type!");
      break;
  }
}

static void createDisplayList (vo_instance_t * vo, vo_buffer_t * buf)
{
  int i;
  GLfloat xcov[4], ycov[4];
  buf->priv->glDisplayList =3D glGenLists (1);
  for (i =3D 0; i < vo->priv->numPlanes; i++) {
    xcov[i] =3D
      (GLfloat) vo->priv->planeWidth[i] /
      (GLfloat) vo->priv->planeTextureWidth[i];
    ycov[i] =3D
      (GLfloat) vo->priv->planeHeight[i] /
      (GLfloat) vo->priv->planeTextureHeight[i];
  }
  // TODO: set this at an appropriate place to a useable default
  if (vo->priv->numPlanes =3D=3D 3)
    vo->priv->conversion =3D vo->priv->bestYUVConversion;

  setupConversion (vo);

  glNewList (buf->priv->glDisplayList, GL_COMPILE);
  activateConversion (vo, buf);
  glBegin (GL_QUADS);
  for (i =3D 0; i < vo->priv->numPlanes; i++)
    glMultiTexCoord2f (GL_TEXTURE0 + i, 0, 0);
  glVertex2i (0, 0);
  for (i =3D 0; i < vo->priv->numPlanes; i++)
    glMultiTexCoord2f (GL_TEXTURE0 + i, xcov[i], 0);
  glVertex2i (vo->priv->img_width, 0);
  for (i =3D 0; i < vo->priv->numPlanes; i++)
    glMultiTexCoord2f (GL_TEXTURE0 + i, xcov[i], ycov[i]);
  glVertex2i (vo->priv->img_width, vo->priv->img_height);
  for (i =3D 0; i < vo->priv->numPlanes; i++)
    glMultiTexCoord2f (GL_TEXTURE0 + i, 0, ycov[i]);
  glVertex2i (0, vo->priv->img_height);
  glEnd ();
  deactivateConversion (vo, buf);

  glEndList ();
}

static int config (vo_instance_t * vo, int width, int height,
                   int d_width, int d_height, unsigned int format)
{
  int dest_coords[] =3D { 0, 0, width, height };
  vo->priv->img_width =3D width;
  vo->priv->img_height =3D height;
  vo->priv->d_width =3D d_width;
  vo->priv->d_height =3D d_height;
  vo->buffer_w =3D width;
  vo->buffer_h =3D height;
  vo->w =3D d_width;
  vo->h =3D d_height;
  getGLFunctions (vo);
  analyzeFormat (vo, format);
  findTextureSizes (vo);
  glDisable (GL_BLEND);
  glDisable (GL_DEPTH_TEST);
  glDepthMask (GL_FALSE);
  glDisable (GL_CULL_FACE);
  glClearColor (0, 0, 0, 0);
  resize (vo, dest_coords);
  return VO_TRUE;
}

static void updateTexture (vo_instance_t * vo, vo_buffer_t * buf, int pla=
neNr,
                           int x, int y, int w, int h, unsigned char *dat=
a)
{
  mp_msg (MSGT_VO, MSGL_DBG1, "[gl] updateTexture (%i, %i, %i, %i, %i, %x=
)\n",
          planeNr, x, y, w, h, data);
  glBindTexture (GL_TEXTURE_2D, buf->priv->planeTexture[planeNr]);
  glTexSubImage2D (GL_TEXTURE_2D, 0, x, y, w, h,
                   vo->priv->planeFormat[planeNr],
                   vo->priv->planeType[planeNr], data);
  mp_msg (MSGT_VO, MSGL_DBG1, "[gl] glTexSubImage2D finished with %d\n",
          glGetError ());
}

static void draw_slice (vo_instance_t * vo, vo_buffer_t * buf,
                        unsigned char *src[], int stride[], int w, int h,
                        int x, int y)
{
  mp_msg (MSGT_VO, MSGL_DBG1, "[gl] draw_slice\n");
}

static int frame_done (vo_instance_t * vo, vo_buffer_t * buf)
{
  int i;
  mp_msg (MSGT_VO, MSGL_DBG1, "[gl] frame_done\n");
  for (i =3D 0; i < vo->priv->numPlanes; i++)
    updateTexture (vo, buf, i, 0, 0, vo->priv->planeWidth[i],
                   vo->priv->planeHeight[i], buf->planes[i]);
  glFlush ();
  return 0;
}

static void show_frame (vo_instance_t * vo, vo_buffer_t * buf,
                        unsigned int time_pos)
{
  mp_msg (MSGT_VO, MSGL_DBG1, "[gl] show_frame\n");
  glCallList (buf->priv->glDisplayList);
  glXSwapBuffers (vo->priv->display, vo->priv->window);
  glClear (GL_COLOR_BUFFER_BIT);
}

static vo_buffer_t *get_buffer (vo_instance_t * vo)
{
  int i;
  vo_buffer_t *buffer =3D calloc (sizeof (vo_buffer_t), 1);
  buffer->priv =3D calloc (sizeof (struct vo_buffer_priv_s), 1);
  createTextures (vo, buffer);
  createDisplayList (vo, buffer);

  buffer->status =3D 0;
  for (i =3D 0; i < vo->priv->numPlanes; i++) {
    buffer->planes[i] =3D
      calloc (vo->priv->planeWidth[i] * vo->priv->planeHeight[i] *
              vo->priv->planeBytesPerPixel[i], 1);
    buffer->stride[i] =3D
      vo->priv->planeWidth[i] * vo->priv->planeBytesPerPixel[i];
  }
  return buffer;
}

static void release_buffer (vo_instance_t * vo, vo_buffer_t * buf)
{
  int i;
  for (i =3D 0; i < vo->priv->numPlanes; i++)
    free (buf->planes[i]);
  glDeleteLists (buf->priv->glDisplayList, 1);
  glDeleteTextures (vo->priv->numPlanes, buf->priv->planeTexture);
  free (buf->priv);
  free (buf);
}

static vo_instance_t *preinit (char *args, void *x11_display)
{
  vo_instance_t *vo;
  if (!x11_display)
    return NULL;                // X11 not available
  vo =3D calloc (sizeof (vo_instance_t), 1);
  vo->priv =3D calloc (sizeof (struct vo_priv_s), 1);
  memset (vo->priv, 0, sizeof (struct vo_priv_s));
  vo->priv->useGL12 =3D 1;
  vo->priv->supportYUV =3D 0;
  vo->priv->display =3D x11_display;
  XMatchVisualInfo (vo->priv->display, DefaultScreen (vo->priv->display),=
 24,
                    TrueColor, &vo->priv->vinfo);

#if 0
  if (arg) {
    if (strcmp (arg, "gl11") =3D=3D 0) {
      useGL12 =3D 0;
    } else if (strcmp (arg, "glyuv") =3D=3D 0) {
      supportYUV =3D 1;
    } else {
      printf ("[gl] Unknown subdevice: %s\n", arg);
      return ENOSYS;
    }
  }
#endif

  vo->buffer_flags =3D 0;
  vo->num_buffers =3D 0;
  // functions:
  vo->query_format =3D query_format;
  vo->control =3D control;
  vo->config =3D config;
  vo->draw_slice =3D draw_slice;
  vo->frame_done =3D frame_done;
  vo->show_frame =3D show_frame;
  vo->uninit =3D uninit;
  vo->get_buffer =3D get_buffer;
  vo->release_buffer =3D release_buffer;
  return vo;
}

vo_info_t vo_driver_gl =3D {
  MODULE_TYPE_VO, MODULE_VERSION, preinit, "gl", "OpenGL driver",
  "Reimar D=F6ffinger", "Reimar D=F6ffinger", NULL,
  VO_MODULE_CAPS_X11 | VO_MODULE_CAPS_WINDOW | VO_MODULE_CAPS_GUI, NULL,
  NULL, 0
};

--------------010405090309040607050200
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
MPlayer-G2-dev mailing list
[email protected]
http://mplayerhq.hu/mailman/listinfo/mplayer-g2-dev

--------------010405090309040607050200--