[MPlayer-dev-eng] Video output for RV280+Mesa3D

malc av1474 at comtv.ru
Sat Dec 6 14:32:06 CET 2008


On Sat, 6 Dec 2008, Diego Biurrun wrote:

> On Fri, Dec 05, 2008 at 01:44:51PM +0300, malc wrote:
>>
>> The patch implements the most performant(at least on this mac mini) way to
>> put YV12/I420/YUY2/UYVY data on screen. Constraints include:
>> a) PPC
>> b) Altivec presence
>> c) Mesa3D + GLX_MESA_allocate_memory
>> d) Horizontal resolution being multiple of 16
>>
>> The code also relies on SDL for operation.
>>
>> --- libvo/vo_rv280.c	(revision 0)
>> +++ libvo/vo_rv280.c	(revision 0)
>> @@ -0,0 +1,732 @@
>> +#define GL_GLEXT_PROTOTYPES
>> +#define GLX_GLXEXT_PROTOTYPES
>
> This is missing a license header
>
>> +void mplayer_put_key(int code);
>
> Please #include mp_fifo.h instead.
>
>> +/*
>> + * AltiVec-enhanced yuv2yuvX
>> + *
>> + * Copyright (C) 2004 Romain Dolbeau <romain at dolbeau.org>
>> + * based on the equivalent C code in "postproc/swscale.c"
>
> You mean libswscale/swscale.c?

No, i took it from postproc/swscale, it has been moved since then.

>> +/*
>> + * AltiVec-enhanced yuv2yuvX
>> + *
>> + * Copyright (C) 2004 Romain Dolbeau <romain at dolbeau.org>
>> + * based on the equivalent C code in "postproc/swscale.c"
>
> ditto

Ditto what?

> I think this code should be added to libswscale if it is really faster.

As i explained elsewhere it uses transient stores and as such is not really
a candidate for general purpose scaling mechanism.

>> +static void flip_page (void)
>
> Sometimes you put a space before the opening parenthesis, sometimes you
> don't.  Leave it out.

Save for one instance i always add space before parenthesis, in all other
instance the code without spaces was just copy&pasted from swscale/vo_sdl

>> --- configure	(revision 28089)
>> +++ configure	(working copy)
>> @@ -4891,6 +4891,10 @@
>>      _vomodules="sdl $_vomodules"
>>      _aomodules="sdl $_aomodules"
>>      _res_comment="using $_sdlconfig"
>> +  if test "$_gl" = yes && linux && ppc ; then
>> +    _def_rv280="#define HAVE_RV280 1"
>> +    _rv280="yes"
>> +  fi
>>    else
>>      _def_sdl='#undef CONFIG_SDL'
>>      _novomodules="sdl $_novomodules"
>
> I think it should be possible to enable this separately.

Most definitely, i have no idea of the most idiomatic way to do that and
hence it was left out.

Index: Makefile
===================================================================
--- Makefile	(revision 28107)
+++ Makefile	(working copy)
@@ -544,6 +544,7 @@
  SRCS_MPLAYER-$(GGI)          += libvo/vo_ggi.c
  SRCS_MPLAYER-$(GIF)          += libvo/vo_gif89a.c
  SRCS_MPLAYER-$(GL)           += libvo/gl_common.c libvo/vo_gl.c libvo/vo_gl2.c
+SRCS_MPLAYER-$(RV280)        += libvo/vo_rv280.c
  SRCS_MPLAYER-$(GL_WIN32)     += libvo/w32_common.c
  SRCS_MPLAYER-$(GUI)          += gui/bitmap.c
  SRCS_MPLAYER-$(GUI_GTK)      += gui/app.c \
Index: libvo/video_out.c
===================================================================
--- libvo/video_out.c	(revision 28107)
+++ libvo/video_out.c	(working copy)
@@ -114,6 +114,7 @@
  extern vo_functions_t video_out_quartz;
  extern vo_functions_t video_out_pnm;
  extern vo_functions_t video_out_md5sum;
+extern vo_functions_t video_out_rv280;

  const vo_functions_t* const video_out_drivers[] =
  {
@@ -250,6 +251,9 @@
  #ifdef CONFIG_MD5SUM
      &video_out_md5sum,
  #endif
+#ifdef HAVE_RV280
+    &video_out_rv280,
+#endif
          NULL
  };

Index: libvo/vo_rv280.c
===================================================================
--- libvo/vo_rv280.c	(revision 0)
+++ libvo/vo_rv280.c	(revision 0)
@@ -0,0 +1,743 @@
+/* This code unless otherwise noted is in public domain */
+#define GL_GLEXT_PROTOTYPES
+#define GLX_GLXEXT_PROTOTYPES
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "aspect.h"
+#include "video_out.h"
+#include "video_out_internal.h"
+#include "sub.h"
+#include "subopt-helper.h"
+#include "mp_msg.h"
+#include "osdep/keycodes.h"
+#include "x11_common.h"
+
+#include <SDL.h>
+#include <SDL_syswm.h>
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <GL/glu.h>
+
+#include <altivec.h>
+
+#define fail(...) mp_msg(MSGT_VO, MSGL_FATAL, "[rv280]: " __VA_ARGS__)
+#define sdl_fail(fmt, ...) fail(fmt ": %s\n", SDL_GetError())
+
+void mplayer_put_ke(int code);
+
+extern int vd_use_slices;
+
+static vo_info_t info = {
+    "rv280",
+    "rv280",
+    "",
+    ""
+};
+
+LIBVO_EXTERN(rv280);
+
+typedef struct {
+    uint32_t format;
+    int w, h, dw, dh, vx, vy, vw, vh;
+    SDL_Surface *screen;
+    Uint32 sdl_flags;
+    Display *dpy;
+    Window win;
+    void *memory;
+    GLuint texid[2];
+    GLint coords[4][2];
+    int gl_initialized;
+    int cursor_visible;
+    int bytes_per_line;
+    void *memory_osd;
+    int bytes_per_line_osd;
+    uint32_t hint_chroma;
+    uint32_t hint_luma;
+    uint32_t hint_dst;
+} State;
+
+static State glob_state;
+
+static void rv280_clear_osd(State *s)
+{
+    size_t i;
+    vector float *dst = s->memory_osd;
+    vector float zero = {0};
+
+    for (i = 0; i < s->bytes_per_line_osd * s->h;) {
+        vec_st(zero, i, dst); i += 16;
+        vec_st(zero, i, dst); i += 16;
+    }
+}
+
+static void *rv280_gart_alloc(State *s)
+{
+    void *memory;
+
+    s->bytes_per_line =((s->w * 2 + 63) & ~63);
+    memory = glXAllocateMemoryMESA(s->dpy, DefaultScreen(s->dpy),
+                                    s->bytes_per_line * s->h,
+                                    0.0, 0.0, 0.0);
+    if (!memory)
+        fail("glXAllocateMemoryMESA failed\n");
+
+    if (1) {
+        s->bytes_per_line_osd =((s->w * 4 + 63) & ~63);
+        s->memory_osd = glXAllocateMemoryMESA(s->dpy, DefaultScreen(s->dpy),
+                                               s->bytes_per_line_osd * s->h,
+                                               0.0, 0.0, 0.0);
+    }
+    return memory;
+}
+
+static void rv280_gart_free(State *s)
+{
+    if (s->memory)
+        glXFreeMemoryMESA(s->dpy, DefaultScreen(s->dpy), s->memory);
+    s->memory = NULL;
+    if (s->memory_osd)
+        glXFreeMemoryMESA(s->dpy, DefaultScreen(s->dpy), s->memory_osd);
+    s->memory_osd = NULL;
+}
+
+static int rv280_sdl_set_mode(State *s, int w, int h, int dw, int dh)
+{
+    int retcode;
+    SDL_SysWMinfo info;
+
+    retcode = SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+    if (retcode) {
+        sdl_fail("SDL_GL_SetAttribute failed");
+        goto err0;
+    }
+
+    s->screen = SDL_SetVideoMode(dw, dh, 0, s->sdl_flags);
+    if (!s->screen) {
+        sdl_fail("SDL_SetVideoMode failed");
+        goto err0;
+    }
+
+    SDL_VERSION(&info.version);
+    retcode = SDL_GetWMInfo(&info);
+    if (!retcode) {
+        sdl_fail("SDL_GetWMInfo failed");
+        goto err0;
+    }
+
+    s->dpy = info.info.x11.display;
+    s->win = info.info.x11.wmwindow;
+
+    s->w = w;
+    s->h = h;
+    s->memory = rv280_gart_alloc(s);
+    if (!s->memory) goto err0;
+    s->cursor_visible = 0;
+    SDL_ShowCursor(0);
+    return 0;
+
+ err0:
+    return -1;
+}
+
+static void rv280_sdl_fini(State *s)
+{
+    rv280_gart_free(s);
+    s->screen = NULL;
+}
+
+static int rv280_gl_init(State *s)
+{
+    glGenTextures(s->memory_osd ? 2 : 1, s->texid);
+
+    memset(s->coords, 0, sizeof(s->coords));
+    s->coords[1][0] = s->w;
+    s->coords[2][0] = s->w;
+    s->coords[2][1] = s->h;
+    s->coords[3][1] = s->h;
+    s->gl_initialized = 1;
+    return 0;
+}
+
+static void rv280_gl_fini(State *s)
+{
+    if (s->gl_initialized) {
+        s->gl_initialized = 0;
+        glDeleteTextures(s->memory_osd ? 2 : 1, s->texid);
+    }
+}
+
+static void rv280_draw(State *s)
+{
+    int i;
+    const GLint quad[] = {-1, 1, 1, 1, 1, -1, -1, -1};
+
+    glBegin(GL_QUADS);
+    {
+        for (i = 0; i < 4; ++i) {
+            if (!s->memory_osd) {
+                glTexCoord2iv(&s->coords[i][0]);
+            }
+            else {
+                glMultiTexCoord2iv(GL_TEXTURE0_ARB, &s->coords[i][0]);
+                glMultiTexCoord2iv(GL_TEXTURE1_ARB, &s->coords[i][0]);
+            }
+            glVertex2iv(quad + i * 2);
+        }
+    }
+    glEnd();
+}
+
+
+static void rv280_resize_gl(State *s, int w, int h)
+{
+    glViewport(0, 0, w, h);
+
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+
+    glMatrixMod(GL_MODELVIEW);
+    glLoadIdentity();
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    vo_osd_changed(1);
+}
+
+static int rv280_sdl_resize(State *s, int x, int y)
+{
+    int retcode;
+    SDL_SysWMinfo info;
+    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+    s->screen = SDL_SetVideoMode(x, y, 0, s->sdl_flags);
+    if (!s->screen) {
+        sdl_fail("SDL_SetVideoMode failed");
+        return -1;
+    }
+
+    rv280_resize_gl(s, x, y);
+
+    SDL_VERSION(&info.version);
+    retcode = SDL_GetWMInfo(&info);
+    if (!retcode) {
+        sdl_fail("SDL_GetWMInfo failed");
+        return -1;
+    }
+
+    s->dpy = info.info.x11.display;
+    s->win = info.info.x11.wmwindow;
+
+    s->dw = x;
+    s->dh = y;
+
+    s->vw = x;
+    s->vh = y;
+    s->vx = 0;
+    s->vy = 0;
+
+    if (vo_fs) {
+        aspect(&s->vw, &s->vh, A_ZOOM);
+        s->vx =(x - s->vw) / 2;
+        s->vy =(y - s->vh) / 2;
+    }
+
+    glViewport(s->vx, s->vy, s->vw, s->vh);
+
+    if (s->memory_osd) {
+        glActiveTexture(GL_TEXTURE1_ARB);
+        glEnable(GL_TEXTURE_RECTANGLE_ARB);
+        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s->texid[1]);
+
+        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+
+        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+        glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
+
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS);
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
+
+        glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+        glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
+        glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
+
+        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+        glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, s->bytes_per_line_osd >> 2);
+    }
+
+    glActiveTexture(GL_TEXTURE0_ARB);
+    glEnable(GL_TEXTURE_RECTANGLE_ARB);
+    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s->texid[0]);
+
+    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+    glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
+    glPixelStorei(GL_UNPACK_ROW_LENGTH, s->bytes_per_line >> 1);
+    return 0;
+}
+
+static uint32_t rv280_compute_hint(int w)
+{
+    union {
+        struct {
+            int stride : 16;
+            int count : 8;
+            int size : 5;
+            int pad : 3;
+        } hint;
+        uint32_t val;
+    } u;
+
+    u.hint.stride = 16;
+    u.hint.count = 1;
+    u.hint.size = w >> 4;
+    u.hint.pad = 0;
+    return u.val;
+    /* return(u.hint.stride << 16) |(u.hint.count << 8) |(u.hint.size << 3); */
+}
+
+/*
+ * Following function is based on:
+ *
+ * AltiVec-enhanced yuv2yuvX
+ *
+ * Copyright (C) 2004 Romain Dolbeau <romain at dolbeau.org>
+ * based on the equivalent C code in libswscale/swscale.c
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+static void rv280_yv12toyuy2_unscaled_altivec(
+    State *s,
+    uint8_t* src[],
+    int srcStride[],
+    uint8_t* dst,
+    int dstStride
+    )
+{
+    uint8_t *ysrc = src[0];
+    uint8_t *usrc = src[1];
+    uint8_t *vsrc = src[2];
+    const int width = s->w;
+    const int height = s->h;
+    const int lumStride = srcStride[0];
+    const int chromStride = srcStride[1];
+    const vector unsigned char yperm = vec_lvs(0, ysrc);
+    register int y;
+
+    /* this code assume:
+
+    1) dst is 16 bytes-aligned
+    2) dstStride is a multiple of 16
+    3) width is a multiple of 16
+    4) lum&chrom stride are multiple of 8
+    */
+
+    for (y=0; y<height; y++) {
+        int i;
+
+        vec_dstt(ysrc, s->hint_luma, 0);
+        /* vec_dststt(dst, s->hint_dst, 3); */
+        if (!(y & 1)) {
+            vec_dstt(usrc, s->hint_chroma, 1);
+            vec_dstt(vsrc, s->hint_chroma, 2);
+        }
+
+        for (i = 0; i < width - 31; i+= 32) {
+            const unsigned int j = i >> 1;
+            vector unsigned char v_yA = vec_ld(i, ysrc);
+            vector unsigned char v_yB = vec_ld(i + 16, ysrc);
+            vector unsigned char v_yC = vec_ld(i + 32, ysrc);
+            vector unsigned char v_y1 = vec_perm(v_yA, v_yB, yperm);
+            vector unsigned char v_y2 = vec_perm(v_yB, v_yC, yperm);
+            vector unsigned char v_uA = vec_ld(j, usrc);
+            vector unsigned char v_uB = vec_ld(j + 16, usrc);
+            vector unsigned char v_u = vec_perm(v_uA, v_uB, vec_lvsl(j, usrc));
+            vector unsigned char v_vA = vec_ld(j, vsrc);
+            vector unsigned char v_vB = vec_ld(j + 16, vsrc);
+            vector unsigned char v_v = vec_perm(v_vA, v_vB, vec_lvsl(j, vsrc));
+            vector unsigned char v_uv_a = vec_mergeh(v_u, v_v);
+            vector unsigned char v_uv_b = vec_mergel(v_u, v_v);
+            vector unsigned char v_yuy2_0 = vec_mergeh(v_y1, v_uv_a);
+            vector unsigned char v_yuy2_1 = vec_mergel(v_y1, v_uv_a);
+            vector unsigned char v_yuy2_2 = vec_mergeh(v_y2, v_uv_b);
+            vector unsigned char v_yuy2_3 = vec_mergel(v_y2, v_uv_b);
+            vec_st(v_yuy2_0,(i << 1), dst);
+            vec_st(v_yuy2_1,(i << 1) + 16, dst);
+            vec_st(v_yuy2_2,(i << 1) + 32, dst);
+            vec_st(v_yuy2_3,(i << 1) + 48, dst);
+        }
+        if (i < width) {
+            const unsigned int j = i >> 1;
+            vector unsigned char v_y1 = vec_ld(i, ysrc);
+            vector unsigned char v_u = vec_ld(j, usrc);
+            vector unsigned char v_v = vec_ld(j, vsrc);
+            vector unsigned char v_uv_a = vec_mergeh(v_u, v_v);
+            vector unsigned char v_yuy2_0 = vec_mergeh(v_y1, v_uv_a);
+            vector unsigned char v_yuy2_1 = vec_mergel(v_y1, v_uv_a);
+            vec_st(v_yuy2_0,(i << 1), dst);
+            vec_st(v_yuy2_1,(i << 1) + 16, dst);
+        }
+        if (y & 1) {
+            usrc += chromStride;
+            vsrc += chromStride;
+        }
+        ysrc += lumStride;
+        dst += dstStride;
+    }
+}
+
+static int preinit(const char *arg)
+{
+    int retcode;
+    State *s = &glob_state;
+
+    if (!vo_init()) {
+        fail("vo_init failed\n");
+        return -1;
+    }
+
+    retcode = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE);
+    if (retcode) {
+        sdl_fail("SDL_Init failed");
+        return -1;
+    }
+
+    s->sdl_flags = SDL_OPENGL | SDL_RESIZABLE;
+    vd_use_slices = 0;
+
+    return 0;
+}
+
+static int query_format(uint32_t format)
+{
+    int flags = 0;
+
+    if (format == IMGFMT_I420 || format == IMGFMT_YV12 || format == IMGFMT_IYUV
+        || format == IMGFMT_YUY2 || format == IMGFMT_YVYU || format == IMGFMT_UYVY) {
+        flags = VFCAP_CSP_SUPPORTED
+            | VFCAP_CSP_SUPPORTED_BY_HW
+            | VFCAP_HWSCALE_UP
+            | VFCAP_HWSCALE_DOWN
+            ;
+    }
+    return flags;
+}
+
+static int control(uint32_t request, void *data, ...)
+{
+    switch(request) {
+        case VOCTRL_QUERY_FORMAT:
+            return query_format(*(uint32_t *)data);
+
+        case VOCTRL_FULLSCREEN:
+            return VO_TRUE;
+
+        case VOCTRL_UPDATE_SCREENINFO:
+            update_xinerama_info();
+            return VO_TRUE;
+
+        default:
+            return VO_NOTIMPL;
+    }
+}
+
+static int draw_slice(uint8_t *src[], int stride[], int w, int h, int x, int y)
+{
+    State *s = &glob_state;
+    GLenum type = GL_UNSIGNED_SHORT_8_8_REV_MESA;
+
+    switch(s->format) {
+        case IMGFMT_YV12:
+        case IMGFMT_I420:
+            rv280_yv12toyuy2_unscaled_altivec(s, src, stride, s->memory, s->bytes_per_line);
+            break;
+
+        case IMGFMT_UYVY:
+            type = GL_UNSIGNED_SHORT_8_8_MESA;
+        case IMGFMT_YUY2:
+        {
+            char *sp = src[0];
+            char *dp = s->memory;
+            int count = s->w * 2;
+
+            for (y = 0; y < s->h; ++y) {
+                memcpy(dp, sp, count);
+                sp += stride[0];
+                dp += s->bytes_per_line;
+            }
+        }
+        break;
+
+        default:
+            fail("draw_slice unknown format %x %*s\n", s->format, 4,(char *) &s->format);
+            return -1;
+    }
+    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA,
+                  s->w, s->h, 0, GL_YCBCR_MESA, type, s->memory);
+    return 0;
+}
+
+static int draw_frame(uint8_t *src[])
+{
+    State *s = &glob_state;
+
+    switch(s->format) {
+        case IMGFMT_UYVY:
+        case IMGFMT_YUY2:
+        {
+            int stride = s->w * 2;
+            return draw_slice(src, &stride, 0, 0, s->w, s->h);
+        }
+
+        default:
+            fail("draw_frame unknown format %x %*s\n", s->format, 4,(char *) &s->format);
+            return -1;
+    }
+}
+
+static void draw_alpha_yuy2(int x0, int y0, int w, int h,
+                            unsigned char *src, unsigned char *srca,
+                            int stride)
+{
+    State *s = &glob_state;
+    x0 += s->w *(vo_panscan_x >> 1) /(s->dw + vo_panscan_x);
+    vo_draw_alpha_yuy2(w, h, src, srca, stride,
+                      (char *) s->memory + s->bytes_per_line * y0 + 2 * x0,
+                       s->bytes_per_line);
+}
+
+static void rv280_load_osd(State *s)
+{
+    glActiveTexture(GL_TEXTURE1_ARB);
+    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s->texid[1]);
+    glPixelStorei(GL_UNPACK_ROW_LENGTH, s->bytes_per_line_osd >> 2);
+    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
+                  s->w, s->h, 0, GL_BGRA,
+                  GL_UNSIGNED_INT_8_8_8_8_REV, s->memory_osd);
+    glActiveTexture(GL_TEXTURE0_ARB);
+    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s->texid[0]);
+    glPixelStorei(GL_UNPACK_ROW_LENGTH, s->bytes_per_line >> 1);
+}
+
+static void draw_alpha_rgba(int x0, int y0, int w, int h,
+                             unsigned char *src, unsigned char *srca,
+                             int stride)
+{
+    State *s = &glob_state;
+    char *p;
+    int y, x;
+
+    p = s->memory_osd;
+    p += s->bytes_per_line_osd * y0 + 4 * x0;
+
+    for (y = 0; y < h; ++y) {
+        for (x = 0; x < w; ++x) {
+            p[x*4 + 0] = src[x];
+            p[x*4 + 1] = src[x];
+            p[x*4 + 2] = src[x];
+            p[x*4 + 3] = -srca[x];
+        }
+        p += s->bytes_per_line_osd;
+        src += stride;
+        srca += stride;
+    }
+}
+
+static void draw_osd(void)
+{
+    State *s = &glob_state;
+
+    if (!s->memory_osd) {
+        vo_draw_text(s->w, s->h, draw_alpha_yuy2);
+    }
+    else {
+        if (vo_osd_changed(0)) {
+            rv280_clear_osd(s);
+            vo_draw_text(s->w, s->h, draw_alpha_rgba);
+            rv280_load_osd(s);
+        }
+    }
+}
+
+static void flip_page(void)
+{
+    State *s = &glob_state;
+    rv280_draw(s);
+    SDL_GL_SwapBuffers();
+}
+
+#define shift_key(event->key.keysym.mod==(KMOD_LSHIFT||KMOD_RSHIFT))
+static void rv280_process_keydown(State *s, SDL_Event *event)
+{
+    int key = event->key.keysym.sym;
+
+    switch(key) {
+        case SDLK_RETURN: mplayer_put_key(KEY_ENTER);break;
+        case SDLK_ESCAPE: mplayer_put_key(KEY_ESC);break;
+        case SDLK_q: mplayer_put_key('q');break;
+
+        case SDLK_F1: mplayer_put_key(KEY_F+1);break;
+        case SDLK_F2: mplayer_put_key(KEY_F+2);break;
+        case SDLK_F3: mplayer_put_key(KEY_F+3);break;
+        case SDLK_F4: mplayer_put_key(KEY_F+4);break;
+        case SDLK_F5: mplayer_put_key(KEY_F+5);break;
+        case SDLK_F6: mplayer_put_key(KEY_F+6);break;
+        case SDLK_F7: mplayer_put_key(KEY_F+7);break;
+        case SDLK_F8: mplayer_put_key(KEY_F+8);break;
+        case SDLK_F9: mplayer_put_key(KEY_F+9);break;
+        case SDLK_F10: mplayer_put_key(KEY_F+10);break;
+        case SDLK_F11: mplayer_put_key(KEY_F+11);break;
+        case SDLK_F12: mplayer_put_key(KEY_F+12);break;
+
+        case SDLK_h: mplayer_put_key('h');break;
+        case SDLK_k: mplayer_put_key('k');break;
+        case SDLK_j: mplayer_put_key('j');break;
+        case SDLK_v: mplayer_put_key('v');break;
+        case SDLK_o: mplayer_put_key('o');break;
+        case SDLK_l: mplayer_put_key('l');break;
+        case SDLK_f:
+            vo_fs ^= 1;
+            vo_fs_type = vo_wm_FULLSCREEN;
+            vo_window = s->win;
+            mDisplay = s->dpy;
+            vo_x11_ewmh_fullscreen(_NET_WM_STATE_TOGGLE);
+            break;
+        case SDLK_SPACE: mplayer_put_key(' ');break;
+        case SDLK_p: mplayer_put_key('p');break;
+        case SDLK_7: mplayer_put_key(shift_key?'/':'7'); break;
+        case SDLK_PLUS: mplayer_put_key(shift_key?'*':'+'); break;
+        case SDLK_KP_PLUS: mplayer_put_key('+');break;
+        case SDLK_MINUS:
+        case SDLK_KP_MINUS: mplayer_put_key('-');break;
+        case SDLK_TAB: mplayer_put_key('\t');break;
+        case SDLK_PAGEUP: mplayer_put_key(KEY_PAGE_UP);break;
+        case SDLK_PAGEDOWN: mplayer_put_key(KEY_PAGE_DOWN);break;
+        case SDLK_UP: mplayer_put_key(KEY_UP);break;
+        case SDLK_DOWN: mplayer_put_key(KEY_DOWN);break;
+        case SDLK_LEFT: mplayer_put_key(KEY_LEFT);break;
+        case SDLK_RIGHT: mplayer_put_key(KEY_RIGHT);break;
+        case SDLK_LESS: mplayer_put_key(shift_key?'>':'<'); break;
+        case SDLK_GREATER: mplayer_put_key('>'); break;
+        case SDLK_ASTERISK:
+        case SDLK_KP_MULTIPLY: mplayer_put_key('*'); break;
+        case SDLK_SLASH:
+        case SDLK_KP_DIVIDE: mplayer_put_key('/'); break;
+        case SDLK_KP0: mplayer_put_key(KEY_KP0); break;
+        case SDLK_KP1: mplayer_put_key(KEY_KP1); break;
+        case SDLK_KP2: mplayer_put_key(KEY_KP2); break;
+        case SDLK_KP3: mplayer_put_key(KEY_KP3); break;
+        case SDLK_KP4: mplayer_put_key(KEY_KP4); break;
+        case SDLK_KP5: mplayer_put_key(KEY_KP5); break;
+        case SDLK_KP6: mplayer_put_key(KEY_KP6); break;
+        case SDLK_KP7: mplayer_put_key(KEY_KP7); break;
+        case SDLK_KP8: mplayer_put_key(KEY_KP8); break;
+        case SDLK_KP9: mplayer_put_key(KEY_KP9); break;
+        case SDLK_KP_PERIOD: mplayer_put_key(KEY_KPDEC); break;
+        case SDLK_KP_ENTER: mplayer_put_key(KEY_KPENTER); break;
+        case SDLK_c: SDL_ShowCursor(s->cursor_visible = !s->cursor_visible); break;
+
+        default: break;
+    }
+}
+
+static void check_events(void)
+{
+    State *s = &glob_state;
+
+    for (;;) {
+        int retcode;
+        SDL_Event ev;
+
+        retcode = SDL_PollEvent(&ev);
+        if (!retcode) return;
+
+        switch(ev.type) {
+            case SDL_QUIT:
+                mplayer_put_key('q');
+                break;
+
+            case SDL_VIDEORESIZE:
+                rv280_sdl_resize(s, ev.resize.w, ev.resize.h);
+                break;
+
+            case SDL_KEYDOWN:
+                rv280_process_keydown(s, &ev);
+                break;
+
+            default:
+                break;
+        }
+    }
+}
+
+static int config(uint32_t width, uint32_t height, uint32_t d_width,
+                   uint32_t d_height, uint32_t flags, char *title,
+                   uint32_t format)
+{
+    State *s = &glob_state;
+
+    rv280_gl_fini(s);
+    rv280_sdl_fini(s);
+
+    if (width & 15) {
+        fail("can't handle width that is not multiple of sixteen\n");
+        return -1;
+    }
+
+    if (rv280_sdl_set_mode(s, width, height, d_width, d_height))
+        return -1;
+
+    if (rv280_gl_init(s)) {
+        rv280_sdl_fini(s);
+        return -1;
+    }
+
+    rv280_sdl_resize(s, d_width, d_height);
+
+    s->w = width;
+    s->h = height;
+    s->dw = d_width;
+    s->dh = d_height;
+    s->vw = d_width;
+    s->vh = d_height;
+    s->format = format;
+
+    s->hint_luma = rv280_compute_hint(s->w);
+    s->hint_chroma = rv280_compute_hint(s->w >> 1);
+    s->hint_dst = rv280_compute_hint(s->w << 1);
+
+    aspect_save_orig(width, height);
+    aspect_save_prescale(d_width, d_height);
+    SDL_WM_SetCaption(title, NULL);
+    return 0;
+}
+
+static void uninit(void)
+{
+    State *s = &glob_state;
+    rv280_gl_fini(s);
+    rv280_sdl_fini(s);
+}
Index: configure
===================================================================
--- configure	(revision 28107)
+++ configure	(working copy)
@@ -4891,6 +4891,10 @@
    _vomodules="sdl $_vomodules"
    _aomodules="sdl $_aomodules"
    _res_comment="using $_sdlconfig"
+  if test "$_gl" = yes && linux && ppc ; then
+    _def_rv280="#define HAVE_RV280 1"
+    _rv280="yes"
+  fi
  else
    _def_sdl='#undef CONFIG_SDL'
    _novomodules="sdl $_novomodules"
@@ -8072,6 +8076,7 @@
  XVMC = $_xvmc
  YUV4MPEG = $_yuv4mpeg
  ZR = $_zr
+RV280 = $_rv280

  # FFmpeg
  LIBAVUTIL = $_libavutil
@@ -8501,6 +8506,7 @@
  $_def_xvr100
  $_def_yuv4mpeg
  $_def_zr
+$_def_rv280


  /* FFmpeg */
-- 
mailto:av1474 at comtv.ru



More information about the MPlayer-dev-eng mailing list