Merge branch 'master' of ssh://git.freedesktop.org/git/mesa/mesa into pipe-video
authorChristian König <deathsimple@vodafone.de>
Tue, 12 Oct 2010 21:05:25 +0000 (23:05 +0200)
committerChristian König <deathsimple@vodafone.de>
Tue, 12 Oct 2010 21:07:29 +0000 (23:07 +0200)
Conflicts:
configure.ac
src/gallium/drivers/nvfx/Makefile
src/gallium/include/pipe/p_defines.h
src/gallium/include/pipe/p_screen.h
src/gallium/include/state_tracker/dri1_api.h
src/gallium/include/state_tracker/drm_api.h
src/gallium/winsys/nouveau/drm/nouveau_drm_api.c

87 files changed:
configure.ac
src/driclient/include/driclient.h [deleted file]
src/driclient/include/xf86dri.h [deleted file]
src/driclient/src/Makefile [deleted file]
src/driclient/src/XF86dri.c [deleted file]
src/driclient/src/driclient.c [deleted file]
src/driclient/src/xf86dristr.h [deleted file]
src/gallium/auxiliary/Makefile
src/gallium/auxiliary/SConscript
src/gallium/auxiliary/util/u_format.csv
src/gallium/auxiliary/util/u_format_yuv.c
src/gallium/auxiliary/util/u_format_yuv.h
src/gallium/auxiliary/util/u_video.h [new file with mode: 0644]
src/gallium/auxiliary/vl/vl_bitstream_parser.c [new file with mode: 0644]
src/gallium/auxiliary/vl/vl_bitstream_parser.h [new file with mode: 0644]
src/gallium/auxiliary/vl/vl_compositor.c [new file with mode: 0644]
src/gallium/auxiliary/vl/vl_compositor.h [new file with mode: 0644]
src/gallium/auxiliary/vl/vl_csc.c [new file with mode: 0644]
src/gallium/auxiliary/vl/vl_csc.h [new file with mode: 0644]
src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c [new file with mode: 0644]
src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h [new file with mode: 0644]
src/gallium/auxiliary/vl/vl_types.h [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_video_context.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_video_context.h [new file with mode: 0644]
src/gallium/drivers/nvfx/Makefile
src/gallium/drivers/nvfx/nvfx_screen.c
src/gallium/drivers/nvfx/nvfx_state.h
src/gallium/drivers/nvfx/nvfx_video_context.c [new file with mode: 0644]
src/gallium/drivers/nvfx/nvfx_video_context.h [new file with mode: 0644]
src/gallium/drivers/r300/r300_video_context.c [new file with mode: 0644]
src/gallium/drivers/r300/r300_video_context.h [new file with mode: 0644]
src/gallium/drivers/softpipe/Makefile
src/gallium/drivers/softpipe/SConscript
src/gallium/drivers/softpipe/sp_screen.c
src/gallium/drivers/softpipe/sp_texture.h
src/gallium/drivers/softpipe/sp_video_context.c [new file with mode: 0644]
src/gallium/drivers/softpipe/sp_video_context.h [new file with mode: 0644]
src/gallium/include/pipe/p_defines.h
src/gallium/include/pipe/p_format.h
src/gallium/include/pipe/p_screen.h
src/gallium/include/pipe/p_video_context.h [new file with mode: 0644]
src/gallium/include/pipe/p_video_state.h [new file with mode: 0644]
src/gallium/state_trackers/vdpau/Makefile [new file with mode: 0644]
src/gallium/state_trackers/vdpau/device.c [new file with mode: 0644]
src/gallium/state_trackers/vdpau/ftab.c [new file with mode: 0644]
src/gallium/state_trackers/vdpau/htab.c [new file with mode: 0644]
src/gallium/state_trackers/vdpau/query.c [new file with mode: 0644]
src/gallium/state_trackers/vdpau/vdpau_private.h [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/Makefile [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/attributes.c [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/block.c [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/context.c [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/subpicture.c [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/surface.c [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/tests/.gitignore [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/tests/Makefile [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/tests/test_context.c [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/tests/test_subpicture.c [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/tests/testlib.c [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/tests/testlib.h [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c [new file with mode: 0644]
src/gallium/state_trackers/xorg/xvmc/xvmc_private.h [new file with mode: 0644]
src/gallium/targets/Makefile.vdpau [new file with mode: 0644]
src/gallium/targets/Makefile.xvmc [new file with mode: 0644]
src/gallium/targets/dri-nouveau/Makefile
src/gallium/targets/vdpau-softpipe/Makefile [new file with mode: 0644]
src/gallium/targets/xvmc-nouveau/Makefile [new file with mode: 0644]
src/gallium/targets/xvmc-softpipe/Makefile [new file with mode: 0644]
src/gallium/winsys/g3dvl/Makefile [new file with mode: 0644]
src/gallium/winsys/g3dvl/dri/Makefile [new file with mode: 0644]
src/gallium/winsys/g3dvl/dri/XF86dri.c [new file with mode: 0644]
src/gallium/winsys/g3dvl/dri/dri2.c [new file with mode: 0644]
src/gallium/winsys/g3dvl/dri/dri2.h [new file with mode: 0644]
src/gallium/winsys/g3dvl/dri/dri_winsys.c [new file with mode: 0644]
src/gallium/winsys/g3dvl/dri/driclient.c [new file with mode: 0644]
src/gallium/winsys/g3dvl/dri/driclient.h [new file with mode: 0644]
src/gallium/winsys/g3dvl/dri/xf86dri.h [new file with mode: 0644]
src/gallium/winsys/g3dvl/dri/xf86dristr.h [new file with mode: 0644]
src/gallium/winsys/g3dvl/drm/Makefile [new file with mode: 0644]
src/gallium/winsys/g3dvl/drm/Makefile.template [new file with mode: 0644]
src/gallium/winsys/g3dvl/drm/nouveau/Makefile [new file with mode: 0644]
src/gallium/winsys/g3dvl/drm/radeon/Makefile [new file with mode: 0644]
src/gallium/winsys/g3dvl/vl_winsys.h [new file with mode: 0644]
src/gallium/winsys/g3dvl/xlib/xsp_winsys.c [new file with mode: 0644]

index 364ee0394703c38d5ef951f1915449a250a0340f..dec8a2674b93fd1b9a350896a4f5807d269d7f03 100644 (file)
@@ -1331,6 +1331,13 @@ yes)
             VG_LIB_DEPS="$VG_LIB_DEPS -lpthread"
             EGL_CLIENT_APIS="$EGL_CLIENT_APIS "'$(VG_LIB)'
             ;;
+        xorg/xvmc)
+            # Check for libXvMC?
+            if test "x$enable_gallium_g3dvl" != xyes; then
+                AC_MSG_ERROR([cannot build XvMC state tracker without --enable-gallium-g3dvl])
+            fi
+            HAVE_ST_XVMC="yes"
+            ;;
         esac
 
        if test -n "$tracker"; then
@@ -1465,7 +1472,7 @@ dnl
 dnl Gallium helper functions
 dnl
 gallium_check_st() {
-    if test "x$HAVE_ST_DRI" = xyes || test "x$HAVE_ST_XORG" = xyes; then
+    if test "x$HAVE_ST_DRI" = xyes || test "x$HAVE_ST_XORG" = xyes || test "x$HAVE_ST_XVMC" = xyes; then
          GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS $1"
     fi
     if test "x$HAVE_ST_DRI" = xyes && test "x$2" != x; then
@@ -1474,6 +1481,9 @@ gallium_check_st() {
     if test "x$HAVE_ST_XORG" = xyes && test "x$3" != x; then
          GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS $3"
     fi
+    if test "x$HAVE_ST_XVMC" = xyes && test "x$5" != x; then
+         GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS $5"
+    fi
 }
 
 
@@ -1576,7 +1586,26 @@ AC_ARG_ENABLE([gallium-nouveau],
     [enable_gallium_nouveau=no])
 if test "x$enable_gallium_nouveau" = xyes; then
     GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS nouveau nvfx nv50"
-    gallium_check_st "nouveau/drm" "dri-nouveau" "xorg-nouveau"
+    gallium_check_st "nouveau/drm" "dri-nouveau" "xorg-nouveau" "xvmc-nouveau"
+fi
+
+dnl
+dnl Gallium G3DVL configuration
+dnl
+AC_ARG_ENABLE([gallium-g3dvl],
+    [AS_HELP_STRING([--enable-gallium-g3dvl],
+        [build gallium g3dvl @<:@default=disabled@:>@])],
+    [enable_gallium_g3dvl="$enableval"],
+    [enable_gallium_g3dvl=no])
+if test "x$enable_gallium_g3dvl" = xyes; then
+    case "$mesa_driver" in
+    xlib)
+        GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS xvmc-softpipe"
+        ;;
+    dri)
+        GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS g3dvl/dri"
+        ;;
+    esac
 fi
 
 dnl
diff --git a/src/driclient/include/driclient.h b/src/driclient/include/driclient.h
deleted file mode 100644 (file)
index d391525..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#ifndef driclient_h
-#define driclient_h
-
-#include <stdint.h>
-#include <X11/Xlib.h>
-#include <drm_sarea.h>
-#include "xf86dri.h"
-
-/* TODO: Bring in DRI XML options */
-
-typedef struct dri_version
-{
-       int major;
-       int minor;
-       int patch;
-} dri_version_t;
-
-typedef struct dri_screen
-{
-       Display                 *display;
-       unsigned int            num;
-       dri_version_t           ddx, dri, drm;
-       int                     draw_lock_id;
-       int                     fd;
-       drm_sarea_t             *sarea;
-       void                    *drawable_hash;
-       void                    *private;
-} dri_screen_t;
-
-struct dri_context;
-
-typedef struct dri_drawable
-{
-       drm_drawable_t          drm_drawable;
-       Drawable                x_drawable;
-       unsigned int            sarea_index;
-       unsigned int            *sarea_stamp;
-       unsigned int            last_sarea_stamp;
-       int                     x, y, w, h;
-       int                     back_x, back_y;
-       int                     num_cliprects, num_back_cliprects;
-       drm_clip_rect_t         *cliprects, *back_cliprects;
-       dri_screen_t            *dri_screen;
-       unsigned int            refcount;
-       void                    *private;
-} dri_drawable_t;
-
-typedef struct dri_context
-{
-       XID                     id;
-       drm_context_t           drm_context;
-       dri_screen_t            *dri_screen;
-       void                    *private;
-} dri_context_t;
-
-typedef struct dri_framebuffer
-{
-       drm_handle_t            drm_handle;
-       int                     base, size, stride;
-       int                     private_size;
-       void                    *private;
-} dri_framebuffer_t;
-
-int driCreateScreen(Display *display, int screen, dri_screen_t **dri_screen, dri_framebuffer_t *dri_framebuf);
-int driDestroyScreen(dri_screen_t *dri_screen);
-int driCreateDrawable(dri_screen_t *dri_screen, Drawable drawable, dri_drawable_t **dri_drawable);
-int driUpdateDrawableInfo(dri_drawable_t *dri_drawable);
-int driDestroyDrawable(dri_drawable_t *dri_drawable);
-int driCreateContext(dri_screen_t *dri_screen, Visual *visual, dri_context_t **dri_context);
-int driDestroyContext(dri_context_t *dri_context);
-
-#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(dri_drawable)                                  \
-do                                                                                     \
-{                                                                                      \
-       if (*(dri_drawable->sarea_stamp) != dri_drawable->last_sarea_stamp)             \
-               driUpdateDrawableInfo(dri_drawable);                                    \
-} while (0)
-
-#define DRI_VALIDATE_DRAWABLE_INFO(dri_screen, dri_drawable)                                   \
-do                                                                                             \
-{                                                                                              \
-       while (*(dri_drawable->sarea_stamp) != dri_drawable->last_sarea_stamp)                  \
-       {                                                                                       \
-               register unsigned int hwContext = dri_screen->sarea->lock.lock &                \
-               ~(DRM_LOCK_HELD | DRM_LOCK_CONT);                                               \
-               DRM_UNLOCK(dri_screen->fd, &dri_screen->sarea->lock, hwContext);                \
-                                                                                               \
-               DRM_SPINLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);      \
-               DRI_VALIDATE_DRAWABLE_INFO_ONCE(dri_drawable);                                  \
-               DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);    \
-                                                                                               \
-               DRM_LIGHT_LOCK(dri_screen->fd, &dri_screen->sarea->lock, hwContext);            \
-       }                                                                                       \
-} while (0)
-
-#endif
-
diff --git a/src/driclient/include/xf86dri.h b/src/driclient/include/xf86dri.h
deleted file mode 100644 (file)
index baf80a7..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/**************************************************************************
-
-Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
-Copyright 2000 VA Linux Systems, Inc.
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sub license, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
-ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/**
- * \file xf86dri.h
- * Protocol numbers and function prototypes for DRI X protocol.
- *
- * \author Kevin E. Martin <martin@valinux.com>
- * \author Jens Owen <jens@tungstengraphics.com>
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- */
-
-#ifndef _XF86DRI_H_
-#define _XF86DRI_H_
-
-#include <X11/Xfuncproto.h>
-#include <xf86drm.h>
-
-#define X_XF86DRIQueryVersion                  0
-#define X_XF86DRIQueryDirectRenderingCapable   1
-#define X_XF86DRIOpenConnection                        2
-#define X_XF86DRICloseConnection               3
-#define X_XF86DRIGetClientDriverName           4
-#define X_XF86DRICreateContext                 5
-#define X_XF86DRIDestroyContext                        6
-#define X_XF86DRICreateDrawable                        7
-#define X_XF86DRIDestroyDrawable               8
-#define X_XF86DRIGetDrawableInfo               9
-#define X_XF86DRIGetDeviceInfo                 10
-#define X_XF86DRIAuthConnection                 11
-#define X_XF86DRIOpenFullScreen                 12   /* Deprecated */
-#define X_XF86DRICloseFullScreen                13   /* Deprecated */
-
-#define XF86DRINumberEvents            0
-
-#define XF86DRIClientNotLocal          0
-#define XF86DRIOperationNotSupported   1
-#define XF86DRINumberErrors            (XF86DRIOperationNotSupported + 1)
-
-#ifndef _XF86DRI_SERVER_
-
-_XFUNCPROTOBEGIN
-
-Bool XF86DRIQueryExtension( Display *dpy, int *event_base, int *error_base );
-
-Bool XF86DRIQueryVersion( Display *dpy, int *majorVersion, int *minorVersion,
-    int *patchVersion );
-
-Bool XF86DRIQueryDirectRenderingCapable( Display *dpy, int screen,
-    Bool *isCapable );
-
-Bool XF86DRIOpenConnection( Display *dpy, int screen, drm_handle_t *hSAREA,
-    char **busIDString );
-
-Bool XF86DRIAuthConnection( Display *dpy, int screen, drm_magic_t magic );
-
-Bool XF86DRICloseConnection( Display *dpy, int screen );
-
-Bool XF86DRIGetClientDriverName( Display *dpy, int screen,
-    int *ddxDriverMajorVersion, int *ddxDriverMinorVersion,
-    int *ddxDriverPatchVersion, char **clientDriverName );
-
-Bool XF86DRICreateContext( Display *dpy, int screen, Visual *visual,
-    XID *ptr_to_returned_context_id, drm_context_t *hHWContext );
-
-Bool XF86DRICreateContextWithConfig( Display *dpy, int screen, int configID,
-    XID *ptr_to_returned_context_id, drm_context_t *hHWContext );
-
-Bool XF86DRIDestroyContext( Display *dpy, int screen,
-    XID context_id );
-
-Bool XF86DRICreateDrawable( Display *dpy, int screen,
-    Drawable drawable, drm_drawable_t *hHWDrawable );
-
-Bool XF86DRIDestroyDrawable( Display *dpy, int screen, 
-    Drawable drawable);
-
-Bool XF86DRIGetDrawableInfo( Display *dpy, int screen, Drawable drawable,
-    unsigned int *index, unsigned int *stamp, 
-    int *X, int *Y, int *W, int *H,
-    int *numClipRects, drm_clip_rect_t ** pClipRects,
-    int *backX, int *backY,
-    int *numBackClipRects, drm_clip_rect_t **pBackClipRects );
-
-Bool XF86DRIGetDeviceInfo( Display *dpy, int screen,
-    drm_handle_t *hFrameBuffer, int *fbOrigin, int *fbSize,
-    int *fbStride, int *devPrivateSize, void **pDevPrivate );
-
-_XFUNCPROTOEND
-
-#endif /* _XF86DRI_SERVER_ */
-
-#endif /* _XF86DRI_H_ */
-
diff --git a/src/driclient/src/Makefile b/src/driclient/src/Makefile
deleted file mode 100644 (file)
index 34435a2..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-TARGET         = libdriclient.a
-OBJECTS                = driclient.o XF86dri.o
-DRMDIR         ?= /usr
-
-CFLAGS         += -g -Wall -fPIC -I../include -I${DRMDIR}/include -I${DRMDIR}/include/drm
-
-#############################################
-
-.PHONY = all clean
-
-all: ${TARGET}
-
-${TARGET}: ${OBJECTS}
-       ar rcs $@ $^
-       if ! test -d ../lib; then mkdir ../lib; fi
-       cp ${TARGET} ../lib
-
-clean:
-       rm -rf ${OBJECTS} ${TARGET} ../lib/${TARGET}
diff --git a/src/driclient/src/XF86dri.c b/src/driclient/src/XF86dri.c
deleted file mode 100644 (file)
index 831a760..0000000
+++ /dev/null
@@ -1,618 +0,0 @@
-/**************************************************************************
-
-Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
-Copyright 2000 VA Linux Systems, Inc.
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sub license, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
-ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- *   Kevin E. Martin <martin@valinux.com>
- *   Jens Owen <jens@tungstengraphics.com>
- *   Rickard E. (Rik) Faith <faith@valinux.com>
- *
- */
-
-/* THIS IS NOT AN X CONSORTIUM STANDARD */
-
-#include <X11/Xlibint.h>
-#include <X11/extensions/Xext.h>
-#include <X11/extensions/extutil.h>
-#include "xf86dristr.h"
-
-static XExtensionInfo _xf86dri_info_data;
-static XExtensionInfo *xf86dri_info = &_xf86dri_info_data;
-static char xf86dri_extension_name[] = XF86DRINAME;
-
-#define XF86DRICheckExtension(dpy,i,val) \
-  XextCheckExtension (dpy, i, xf86dri_extension_name, val)
-
-/*****************************************************************************
- *                                                                           *
- *                        private utility routines                          *
- *                                                                           *
- *****************************************************************************/
-
-static int close_display(Display *dpy, XExtCodes *extCodes);
-static /* const */ XExtensionHooks xf86dri_extension_hooks = {
-    NULL,                              /* create_gc */
-    NULL,                              /* copy_gc */
-    NULL,                              /* flush_gc */
-    NULL,                              /* free_gc */
-    NULL,                              /* create_font */
-    NULL,                              /* free_font */
-    close_display,                     /* close_display */
-    NULL,                              /* wire_to_event */
-    NULL,                              /* event_to_wire */
-    NULL,                              /* error */
-    NULL,                              /* error_string */
-};
-
-static XEXT_GENERATE_FIND_DISPLAY (find_display, xf86dri_info, 
-                                  xf86dri_extension_name, 
-                                  &xf86dri_extension_hooks, 
-                                  0, NULL)
-
-static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86dri_info)
-
-
-/*****************************************************************************
- *                                                                           *
- *                 public XFree86-DRI Extension routines                    *
- *                                                                           *
- *****************************************************************************/
-
-#if 0
-#include <stdio.h>
-#define TRACE(msg)  fprintf(stderr,"XF86DRI%s\n", msg);
-#else
-#define TRACE(msg)
-#endif
-
-#define PUBLIC
-
-PUBLIC Bool XF86DRIQueryExtension (dpy, event_basep, error_basep)
-    Display *dpy;
-    int *event_basep, *error_basep;
-{
-    XExtDisplayInfo *info = find_display (dpy);
-
-    TRACE("QueryExtension...");
-    if (XextHasExtension(info)) {
-       *event_basep = info->codes->first_event;
-       *error_basep = info->codes->first_error;
-        TRACE("QueryExtension... return True");
-       return True;
-    } else {
-        TRACE("QueryExtension... return False");
-       return False;
-    }
-}
-
-PUBLIC Bool XF86DRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion)
-    Display* dpy;
-    int* majorVersion; 
-    int* minorVersion;
-    int* patchVersion;
-{
-    XExtDisplayInfo *info = find_display (dpy);
-    xXF86DRIQueryVersionReply rep;
-    xXF86DRIQueryVersionReq *req;
-
-    TRACE("QueryVersion...");
-    XF86DRICheckExtension (dpy, info, False);
-
-    LockDisplay(dpy);
-    GetReq(XF86DRIQueryVersion, req);
-    req->reqType = info->codes->major_opcode;
-    req->driReqType = X_XF86DRIQueryVersion;
-    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
-       UnlockDisplay(dpy);
-       SyncHandle();
-        TRACE("QueryVersion... return False");
-       return False;
-    }
-    *majorVersion = rep.majorVersion;
-    *minorVersion = rep.minorVersion;
-    *patchVersion = rep.patchVersion;
-    UnlockDisplay(dpy);
-    SyncHandle();
-    TRACE("QueryVersion... return True");
-    return True;
-}
-
-PUBLIC Bool XF86DRIQueryDirectRenderingCapable(dpy, screen, isCapable)
-    Display* dpy;
-    int screen;
-    Bool* isCapable;
-{
-    XExtDisplayInfo *info = find_display (dpy);
-    xXF86DRIQueryDirectRenderingCapableReply rep;
-    xXF86DRIQueryDirectRenderingCapableReq *req;
-
-    TRACE("QueryDirectRenderingCapable...");
-    XF86DRICheckExtension (dpy, info, False);
-
-    LockDisplay(dpy);
-    GetReq(XF86DRIQueryDirectRenderingCapable, req);
-    req->reqType = info->codes->major_opcode;
-    req->driReqType = X_XF86DRIQueryDirectRenderingCapable;
-    req->screen = screen;
-    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
-       UnlockDisplay(dpy);
-       SyncHandle();
-        TRACE("QueryDirectRenderingCapable... return False");
-       return False;
-    }
-    *isCapable = rep.isCapable;
-    UnlockDisplay(dpy);
-    SyncHandle();
-    TRACE("QueryDirectRenderingCapable... return True");
-    return True;
-}
-
-PUBLIC Bool XF86DRIOpenConnection(dpy, screen, hSAREA, busIdString)
-    Display* dpy;
-    int screen;
-    drm_handle_t * hSAREA;
-    char **busIdString;
-{
-    XExtDisplayInfo *info = find_display (dpy);
-    xXF86DRIOpenConnectionReply rep;
-    xXF86DRIOpenConnectionReq *req;
-
-    TRACE("OpenConnection...");
-    XF86DRICheckExtension (dpy, info, False);
-
-    LockDisplay(dpy);
-    GetReq(XF86DRIOpenConnection, req);
-    req->reqType = info->codes->major_opcode;
-    req->driReqType = X_XF86DRIOpenConnection;
-    req->screen = screen;
-    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
-       UnlockDisplay(dpy);
-       SyncHandle();
-        TRACE("OpenConnection... return False");
-       return False;
-    }
-
-    *hSAREA = rep.hSAREALow;
-    if (sizeof(drm_handle_t) == 8) {
-       int shift = 32; /* var to prevent warning on next line */
-       *hSAREA |= ((drm_handle_t) rep.hSAREAHigh) << shift;
-    }
-
-    if (rep.length) {
-        if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) {
-            _XEatData(dpy, ((rep.busIdStringLength+3) & ~3));
-            UnlockDisplay(dpy);
-            SyncHandle();
-            TRACE("OpenConnection... return False");
-            return False;
-        }
-       _XReadPad(dpy, *busIdString, rep.busIdStringLength);
-    } else {
-        *busIdString = NULL;
-    }
-    UnlockDisplay(dpy);
-    SyncHandle();
-    TRACE("OpenConnection... return True");
-    return True;
-}
-
-PUBLIC Bool XF86DRIAuthConnection(dpy, screen, magic)
-    Display* dpy;
-    int screen;
-    drm_magic_t magic;
-{
-    XExtDisplayInfo *info = find_display (dpy);
-    xXF86DRIAuthConnectionReq *req;
-    xXF86DRIAuthConnectionReply rep;
-
-    TRACE("AuthConnection...");
-    XF86DRICheckExtension (dpy, info, False);
-
-    LockDisplay(dpy);
-    GetReq(XF86DRIAuthConnection, req);
-    req->reqType = info->codes->major_opcode;
-    req->driReqType = X_XF86DRIAuthConnection;
-    req->screen = screen;
-    req->magic = magic;
-    rep.authenticated = 0;
-    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.authenticated) {
-       UnlockDisplay(dpy);
-       SyncHandle();
-        TRACE("AuthConnection... return False");
-       return False;
-    }
-    UnlockDisplay(dpy);
-    SyncHandle();
-    TRACE("AuthConnection... return True");
-    return True;
-}
-
-PUBLIC Bool XF86DRICloseConnection(dpy, screen)
-    Display* dpy;
-    int screen;
-{
-    XExtDisplayInfo *info = find_display (dpy);
-    xXF86DRICloseConnectionReq *req;
-
-    TRACE("CloseConnection...");
-
-    XF86DRICheckExtension (dpy, info, False);
-
-    LockDisplay(dpy);
-    GetReq(XF86DRICloseConnection, req);
-    req->reqType = info->codes->major_opcode;
-    req->driReqType = X_XF86DRICloseConnection;
-    req->screen = screen;
-    UnlockDisplay(dpy);
-    SyncHandle();
-    TRACE("CloseConnection... return True");
-    return True;
-}
-
-PUBLIC Bool XF86DRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion, 
-       ddxDriverMinorVersion, ddxDriverPatchVersion, clientDriverName)
-    Display* dpy;
-    int screen;
-    int* ddxDriverMajorVersion;
-    int* ddxDriverMinorVersion;
-    int* ddxDriverPatchVersion;
-    char** clientDriverName;
-{
-    XExtDisplayInfo *info = find_display (dpy);
-    xXF86DRIGetClientDriverNameReply rep;
-    xXF86DRIGetClientDriverNameReq *req;
-
-    TRACE("GetClientDriverName...");
-    XF86DRICheckExtension (dpy, info, False);
-
-    LockDisplay(dpy);
-    GetReq(XF86DRIGetClientDriverName, req);
-    req->reqType = info->codes->major_opcode;
-    req->driReqType = X_XF86DRIGetClientDriverName;
-    req->screen = screen;
-    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
-       UnlockDisplay(dpy);
-       SyncHandle();
-        TRACE("GetClientDriverName... return False");
-       return False;
-    }
-
-    *ddxDriverMajorVersion = rep.ddxDriverMajorVersion;
-    *ddxDriverMinorVersion = rep.ddxDriverMinorVersion;
-    *ddxDriverPatchVersion = rep.ddxDriverPatchVersion;
-
-    if (rep.length) {
-        if (!(*clientDriverName = (char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) {
-            _XEatData(dpy, ((rep.clientDriverNameLength+3) & ~3));
-            UnlockDisplay(dpy);
-            SyncHandle();
-            TRACE("GetClientDriverName... return False");
-            return False;
-        }
-       _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength);
-    } else {
-        *clientDriverName = NULL;
-    }
-    UnlockDisplay(dpy);
-    SyncHandle();
-    TRACE("GetClientDriverName... return True");
-    return True;
-}
-
-PUBLIC Bool XF86DRICreateContextWithConfig(dpy, screen, configID, context,
-       hHWContext)
-    Display* dpy;
-    int screen;
-    int configID;
-    XID* context;
-    drm_context_t * hHWContext;
-{
-    XExtDisplayInfo *info = find_display (dpy);
-    xXF86DRICreateContextReply rep;
-    xXF86DRICreateContextReq *req;
-
-    TRACE("CreateContext...");
-    XF86DRICheckExtension (dpy, info, False);
-
-    LockDisplay(dpy);
-    GetReq(XF86DRICreateContext, req);
-    req->reqType = info->codes->major_opcode;
-    req->driReqType = X_XF86DRICreateContext;
-    req->visual = configID;
-    req->screen = screen;
-    *context = XAllocID(dpy);
-    req->context = *context;
-    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
-       UnlockDisplay(dpy);
-       SyncHandle();
-        TRACE("CreateContext... return False");
-       return False;
-    }
-    *hHWContext = rep.hHWContext;
-    UnlockDisplay(dpy);
-    SyncHandle();
-    TRACE("CreateContext... return True");
-    return True;
-}
-
-PUBLIC Bool XF86DRICreateContext(dpy, screen, visual, context, hHWContext)
-    Display* dpy;
-    int screen;
-    Visual* visual;
-    XID* context;
-    drm_context_t * hHWContext;
-{
-    return XF86DRICreateContextWithConfig( dpy, screen, visual->visualid,
-                                          context, hHWContext );
-}
-
-PUBLIC Bool XF86DRIDestroyContext( Display * ndpy, int screen, 
-    XID context )
-{
-    Display * const dpy = (Display *) ndpy;
-    XExtDisplayInfo *info = find_display (dpy);
-    xXF86DRIDestroyContextReq *req;
-
-    TRACE("DestroyContext...");
-    XF86DRICheckExtension (dpy, info, False);
-
-    LockDisplay(dpy);
-    GetReq(XF86DRIDestroyContext, req);
-    req->reqType = info->codes->major_opcode;
-    req->driReqType = X_XF86DRIDestroyContext;
-    req->screen = screen;
-    req->context = context;
-    UnlockDisplay(dpy);
-    SyncHandle();
-    TRACE("DestroyContext... return True");
-    return True;
-}
-
-PUBLIC Bool XF86DRICreateDrawable( Display * ndpy, int screen, 
-    Drawable drawable, drm_drawable_t * hHWDrawable )
-{
-    Display * const dpy = (Display *) ndpy;
-    XExtDisplayInfo *info = find_display (dpy);
-    xXF86DRICreateDrawableReply rep;
-    xXF86DRICreateDrawableReq *req;
-
-    TRACE("CreateDrawable...");
-    XF86DRICheckExtension (dpy, info, False);
-
-    LockDisplay(dpy);
-    GetReq(XF86DRICreateDrawable, req);
-    req->reqType = info->codes->major_opcode;
-    req->driReqType = X_XF86DRICreateDrawable;
-    req->screen = screen;
-    req->drawable = drawable;
-    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
-       UnlockDisplay(dpy);
-       SyncHandle();
-        TRACE("CreateDrawable... return False");
-       return False;
-    }
-    *hHWDrawable = rep.hHWDrawable;
-    UnlockDisplay(dpy);
-    SyncHandle();
-    TRACE("CreateDrawable... return True");
-    return True;
-}
-
-PUBLIC Bool XF86DRIDestroyDrawable( Display * ndpy, int screen,
-    Drawable drawable )
-{
-    Display * const dpy = (Display *) ndpy;
-    XExtDisplayInfo *info = find_display (dpy);
-    xXF86DRIDestroyDrawableReq *req;
-
-    TRACE("DestroyDrawable...");
-    XF86DRICheckExtension (dpy, info, False);
-
-    LockDisplay(dpy);
-    GetReq(XF86DRIDestroyDrawable, req);
-    req->reqType = info->codes->major_opcode;
-    req->driReqType = X_XF86DRIDestroyDrawable;
-    req->screen = screen;
-    req->drawable = drawable;
-    UnlockDisplay(dpy);
-    SyncHandle();
-    TRACE("DestroyDrawable... return True");
-    return True;
-}
-
-PUBLIC Bool XF86DRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable,
-    unsigned int* index, unsigned int* stamp,
-    int* X, int* Y, int* W, int* H,
-    int* numClipRects, drm_clip_rect_t ** pClipRects,
-    int* backX, int* backY,
-    int* numBackClipRects, drm_clip_rect_t ** pBackClipRects )
-{
-    XExtDisplayInfo *info = find_display (dpy);
-    xXF86DRIGetDrawableInfoReply rep;
-    xXF86DRIGetDrawableInfoReq *req;
-    int total_rects;
-
-    TRACE("GetDrawableInfo...");
-    XF86DRICheckExtension (dpy, info, False);
-
-    LockDisplay(dpy);
-    GetReq(XF86DRIGetDrawableInfo, req);
-    req->reqType = info->codes->major_opcode;
-    req->driReqType = X_XF86DRIGetDrawableInfo;
-    req->screen = screen;
-    req->drawable = drawable;
-
-    if (!_XReply(dpy, (xReply *)&rep, 1, xFalse)) 
-    {
-       UnlockDisplay(dpy);
-       SyncHandle();
-        TRACE("GetDrawableInfo... return False");
-       return False;
-    }
-    *index = rep.drawableTableIndex;
-    *stamp = rep.drawableTableStamp;
-    *X = (int)rep.drawableX;
-    *Y = (int)rep.drawableY;
-    *W = (int)rep.drawableWidth;
-    *H = (int)rep.drawableHeight;
-    *numClipRects = rep.numClipRects;
-    total_rects = *numClipRects;
-
-    *backX = rep.backX;
-    *backY = rep.backY;
-    *numBackClipRects = rep.numBackClipRects;
-    total_rects += *numBackClipRects;
-
-#if 0
-    /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
-     * backwards compatibility (Because of the >> 2 shift) but the fix
-     * enables multi-threaded apps to work.
-     */
-    if (rep.length !=  ((((SIZEOF(xXF86DRIGetDrawableInfoReply) - 
-                      SIZEOF(xGenericReply) + 
-                      total_rects * sizeof(drm_clip_rect_t)) + 3) & ~3) >> 2)) {
-        _XEatData(dpy, rep.length);
-       UnlockDisplay(dpy);
-       SyncHandle();
-        TRACE("GetDrawableInfo... return False");
-        return False;
-    }
-#endif
-
-    if (*numClipRects) {
-       int len = sizeof(drm_clip_rect_t) * (*numClipRects);
-
-       *pClipRects = (drm_clip_rect_t *)Xcalloc(len, 1);
-       if (*pClipRects) 
-         _XRead(dpy, (char*)*pClipRects, len);
-    } else {
-        *pClipRects = NULL;
-    }
-
-    if (*numBackClipRects) {
-       int len = sizeof(drm_clip_rect_t) * (*numBackClipRects);
-
-       *pBackClipRects = (drm_clip_rect_t *)Xcalloc(len, 1);
-       if (*pBackClipRects) 
-         _XRead(dpy, (char*)*pBackClipRects, len);
-    } else {
-        *pBackClipRects = NULL;
-    }
-
-    UnlockDisplay(dpy);
-    SyncHandle();
-    TRACE("GetDrawableInfo... return True");
-    return True;
-}
-
-PUBLIC Bool XF86DRIGetDeviceInfo(dpy, screen, hFrameBuffer, 
-       fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate)
-    Display* dpy;
-    int screen;
-    drm_handle_t * hFrameBuffer;
-    int* fbOrigin;
-    int* fbSize;
-    int* fbStride;
-    int* devPrivateSize;
-    void** pDevPrivate;
-{
-    XExtDisplayInfo *info = find_display (dpy);
-    xXF86DRIGetDeviceInfoReply rep;
-    xXF86DRIGetDeviceInfoReq *req;
-
-    TRACE("GetDeviceInfo...");
-    XF86DRICheckExtension (dpy, info, False);
-
-    LockDisplay(dpy);
-    GetReq(XF86DRIGetDeviceInfo, req);
-    req->reqType = info->codes->major_opcode;
-    req->driReqType = X_XF86DRIGetDeviceInfo;
-    req->screen = screen;
-    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
-       UnlockDisplay(dpy);
-       SyncHandle();
-        TRACE("GetDeviceInfo... return False");
-       return False;
-    }
-
-    *hFrameBuffer = rep.hFrameBufferLow;
-    if (sizeof(drm_handle_t) == 8) {
-       int shift = 32; /* var to prevent warning on next line */
-       *hFrameBuffer |= ((drm_handle_t) rep.hFrameBufferHigh) << shift;
-    }
-
-    *fbOrigin = rep.framebufferOrigin;
-    *fbSize = rep.framebufferSize;
-    *fbStride = rep.framebufferStride;
-    *devPrivateSize = rep.devPrivateSize;
-
-    if (rep.length) {
-        if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) {
-            _XEatData(dpy, ((rep.devPrivateSize+3) & ~3));
-            UnlockDisplay(dpy);
-            SyncHandle();
-            TRACE("GetDeviceInfo... return False");
-            return False;
-        }
-       _XRead(dpy, (char*)*pDevPrivate, rep.devPrivateSize);
-    } else {
-        *pDevPrivate = NULL;
-    }
-
-    UnlockDisplay(dpy);
-    SyncHandle();
-    TRACE("GetDeviceInfo... return True");
-    return True;
-}
-
-PUBLIC Bool XF86DRIOpenFullScreen(dpy, screen, drawable)
-    Display* dpy;
-    int screen;
-    Drawable drawable;
-{
-    /* This function and the underlying X protocol are deprecated.
-     */
-    (void) dpy;
-    (void) screen;
-    (void) drawable;
-    return False;
-}
-
-PUBLIC Bool XF86DRICloseFullScreen(dpy, screen, drawable)
-    Display* dpy;
-    int screen;
-    Drawable drawable;
-{
-    /* This function and the underlying X protocol are deprecated.
-     */
-    (void) dpy;
-    (void) screen;
-    (void) drawable;
-    return True;
-}
-
diff --git a/src/driclient/src/driclient.c b/src/driclient/src/driclient.c
deleted file mode 100644 (file)
index dc2189a..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-#include "driclient.h"
-#include <assert.h>
-#include <stdlib.h>
-
-int driCreateScreen(Display *display, int screen, dri_screen_t **dri_screen, dri_framebuffer_t *dri_framebuf)
-{
-       int             evbase, errbase;
-       char            *driver_name;
-       int             newly_opened;
-       drm_magic_t     magic;
-       drmVersionPtr   drm_version;
-       drm_handle_t    sarea_handle;
-       char            *bus_id;
-       dri_screen_t    *dri_scrn;
-
-       assert(display);
-       assert(dri_screen);
-
-       if (!XF86DRIQueryExtension(display, &evbase, &errbase))
-               return 1;
-
-       dri_scrn = calloc(1, sizeof(dri_screen_t));
-
-       if (!dri_scrn)
-               return 1;
-
-       if (!XF86DRIQueryVersion(display, &dri_scrn->dri.major, &dri_scrn->dri.minor, &dri_scrn->dri.patch))
-               goto free_screen;
-
-       dri_scrn->display = display;
-       dri_scrn->num = screen;
-       dri_scrn->draw_lock_id = 1;
-
-       if (!XF86DRIOpenConnection(display, screen, &sarea_handle, &bus_id))
-               goto free_screen;
-
-       dri_scrn->fd = -1;
-       dri_scrn->fd = drmOpenOnce(NULL, bus_id, &newly_opened);
-       XFree(bus_id);
-
-       if (dri_scrn->fd < 0)
-               goto close_connection;
-
-       if (drmGetMagic(dri_scrn->fd, &magic))
-               goto close_drm;
-
-       drm_version = drmGetVersion(dri_scrn->fd);
-
-       if (!drm_version)
-               goto close_drm;
-
-       dri_scrn->drm.major = drm_version->version_major;
-       dri_scrn->drm.minor = drm_version->version_minor;
-       dri_scrn->drm.patch = drm_version->version_patchlevel;
-       drmFreeVersion(drm_version);
-
-       if (!XF86DRIAuthConnection(display, screen, magic))
-               goto close_drm;
-
-       if (!XF86DRIGetClientDriverName
-       (
-               display,
-               screen,
-               &dri_scrn->ddx.major,
-               &dri_scrn->ddx.minor,
-               &dri_scrn->ddx.patch,
-               &driver_name
-       ))
-               goto close_drm;
-
-       if (drmMap(dri_scrn->fd, sarea_handle, SAREA_MAX, (drmAddress)&dri_scrn->sarea))
-               goto close_drm;
-
-       dri_scrn->drawable_hash = drmHashCreate();
-
-       if (!dri_scrn->drawable_hash)
-               goto unmap_sarea;
-
-       if (dri_framebuf)
-       {
-               if (!XF86DRIGetDeviceInfo
-               (
-                       display,
-                       screen, &dri_framebuf->drm_handle,
-                       &dri_framebuf->base,
-                       &dri_framebuf->size,
-                       &dri_framebuf->stride,
-                       &dri_framebuf->private_size,
-                       &dri_framebuf->private
-               ))
-                       goto destroy_hash;
-       }
-
-       *dri_screen = dri_scrn;
-
-       return 0;
-
-destroy_hash:
-       drmHashDestroy(dri_scrn->drawable_hash);
-unmap_sarea:
-       drmUnmap(dri_scrn->sarea, SAREA_MAX);
-close_drm:
-       drmCloseOnce(dri_scrn->fd);
-close_connection:
-       XF86DRICloseConnection(display, screen);
-free_screen:
-       free(dri_scrn);
-
-       return 1;
-}
-
-int driDestroyScreen(dri_screen_t *dri_screen)
-{
-       Drawable        draw;
-       dri_drawable_t  *dri_draw;
-
-       assert(dri_screen);
-
-       if (drmHashFirst(dri_screen->drawable_hash, &draw, (void**)&dri_draw))
-       {
-               dri_draw->refcount = 1;
-               driDestroyDrawable(dri_draw);
-
-               while (drmHashNext(dri_screen->drawable_hash, &draw, (void**)&dri_draw))
-               {
-                       dri_draw->refcount = 1;
-                       driDestroyDrawable(dri_draw);
-               }
-       }
-
-       drmHashDestroy(dri_screen->drawable_hash);
-       drmUnmap(dri_screen->sarea, SAREA_MAX);
-       drmCloseOnce(dri_screen->fd);
-       XF86DRICloseConnection(dri_screen->display, dri_screen->num);
-       free(dri_screen);
-
-       return 0;
-}
-
-int driCreateDrawable(dri_screen_t *dri_screen, Drawable drawable, dri_drawable_t **dri_drawable)
-{
-       int             evbase, errbase;
-       dri_drawable_t  *dri_draw;
-
-       assert(dri_screen);
-       assert(dri_drawable);
-
-       if (!XF86DRIQueryExtension(dri_screen->display, &evbase, &errbase))
-               return 1;
-
-       if (!drmHashLookup(dri_screen->drawable_hash, drawable, (void**)dri_drawable))
-       {
-               /* Found */
-               (*dri_drawable)->refcount++;
-               return 0;
-       }
-
-       dri_draw = calloc(1, sizeof(dri_drawable_t));
-
-       if (!dri_draw)
-               return 1;
-
-       if (!XF86DRICreateDrawable(dri_screen->display, 0, drawable, &dri_draw->drm_drawable))
-       {
-               free(dri_draw);
-               return 1;
-       }
-
-       dri_draw->x_drawable = drawable;
-       dri_draw->sarea_index = 0;
-       dri_draw->sarea_stamp = NULL;
-       dri_draw->last_sarea_stamp = 0;
-       dri_draw->dri_screen = dri_screen;
-       dri_draw->refcount = 1;
-
-       if (drmHashInsert(dri_screen->drawable_hash, drawable, dri_draw))
-       {
-               XF86DRIDestroyDrawable(dri_screen->display, dri_screen->num, drawable);
-               free(dri_draw);
-               return 1;
-       }
-
-       if (!dri_draw->sarea_stamp || *dri_draw->sarea_stamp != dri_draw->last_sarea_stamp)
-       {
-               DRM_SPINLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
-
-               if (driUpdateDrawableInfo(dri_draw))
-               {
-                       XF86DRIDestroyDrawable(dri_screen->display, dri_screen->num, drawable);
-                       free(dri_draw);
-                       DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
-                       return 1;
-               }
-
-               DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
-       }
-
-       *dri_drawable = dri_draw;
-
-       return 0;
-}
-
-int driUpdateDrawableInfo(dri_drawable_t *dri_drawable)
-{
-       assert(dri_drawable);
-
-       if (dri_drawable->cliprects)
-       {
-               XFree(dri_drawable->cliprects);
-               dri_drawable->cliprects = NULL;
-       }
-       if (dri_drawable->back_cliprects)
-       {
-               XFree(dri_drawable->back_cliprects);
-               dri_drawable->back_cliprects = NULL;
-       }
-
-       DRM_SPINUNLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id);
-
-       if (!XF86DRIGetDrawableInfo
-       (
-               dri_drawable->dri_screen->display,
-               dri_drawable->dri_screen->num,
-               dri_drawable->x_drawable,
-               &dri_drawable->sarea_index,
-               &dri_drawable->last_sarea_stamp,
-               &dri_drawable->x,
-               &dri_drawable->y,
-               &dri_drawable->w,
-               &dri_drawable->h,
-               &dri_drawable->num_cliprects,
-               &dri_drawable->cliprects,
-               &dri_drawable->back_x,
-               &dri_drawable->back_y,
-               &dri_drawable->num_back_cliprects,
-               &dri_drawable->back_cliprects
-       ))
-       {
-               dri_drawable->sarea_stamp = &dri_drawable->last_sarea_stamp;
-               dri_drawable->num_cliprects = 0;
-               dri_drawable->cliprects = NULL;
-               dri_drawable->num_back_cliprects = 0;
-               dri_drawable->back_cliprects = 0;
-
-               return 1;
-       }
-       else
-               dri_drawable->sarea_stamp = &dri_drawable->dri_screen->sarea->drawableTable[dri_drawable->sarea_index].stamp;
-
-       DRM_SPINLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id);
-
-       return 0;
-}
-
-int driDestroyDrawable(dri_drawable_t *dri_drawable)
-{
-       assert(dri_drawable);
-
-       if (--dri_drawable->refcount == 0)
-       {
-               if (dri_drawable->cliprects)
-                       XFree(dri_drawable->cliprects);
-               if (dri_drawable->back_cliprects)
-                       XFree(dri_drawable->back_cliprects);
-               drmHashDelete(dri_drawable->dri_screen->drawable_hash, dri_drawable->x_drawable);
-               XF86DRIDestroyDrawable(dri_drawable->dri_screen->display, dri_drawable->dri_screen->num, dri_drawable->x_drawable);
-               free(dri_drawable);
-       }
-
-       return 0;
-}
-
-int driCreateContext(dri_screen_t *dri_screen, Visual *visual, dri_context_t **dri_context)
-{
-       int             evbase, errbase;
-       dri_context_t   *dri_ctx;
-
-       assert(dri_screen);
-       assert(visual);
-       assert(dri_context);
-
-       if (!XF86DRIQueryExtension(dri_screen->display, &evbase, &errbase))
-               return 1;
-
-       dri_ctx = calloc(1, sizeof(dri_context_t));
-
-       if (!dri_ctx)
-               return 1;
-
-       if (!XF86DRICreateContext(dri_screen->display, dri_screen->num, visual, &dri_ctx->id, &dri_ctx->drm_context))
-       {
-               free(dri_ctx);
-               return 1;
-       }
-
-       dri_ctx->dri_screen = dri_screen;
-       *dri_context = dri_ctx;
-
-       return 0;
-}
-
-int driDestroyContext(dri_context_t *dri_context)
-{
-       assert(dri_context);
-
-       XF86DRIDestroyContext(dri_context->dri_screen->display, dri_context->dri_screen->num, dri_context->id);
-       free(dri_context);
-
-       return 0;
-}
diff --git a/src/driclient/src/xf86dristr.h b/src/driclient/src/xf86dristr.h
deleted file mode 100644 (file)
index b834bd1..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-/**************************************************************************
-
-Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
-Copyright 2000 VA Linux Systems, Inc.
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sub license, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
-ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- *   Kevin E. Martin <martin@valinux.com>
- *   Jens Owen <jens@tungstengraphics.com>
- *   Rickard E. (Rik) Fiath <faith@valinux.com>
- *
- */
-
-#ifndef _XF86DRISTR_H_
-#define _XF86DRISTR_H_
-
-#include "xf86dri.h"
-
-#define XF86DRINAME "XFree86-DRI"
-
-/* The DRI version number.  This was originally set to be the same of the
- * XFree86 version number.  However, this version is really indepedent of
- * the XFree86 version.
- *
- * Version History:
- *    4.0.0: Original
- *    4.0.1: Patch to bump clipstamp when windows are destroyed, 28 May 02
- *    4.1.0: Add transition from single to multi in DRMInfo rec, 24 Jun 02
- */
-#define XF86DRI_MAJOR_VERSION  4
-#define XF86DRI_MINOR_VERSION  1
-#define XF86DRI_PATCH_VERSION  0
-
-typedef struct _XF86DRIQueryVersion {
-    CARD8      reqType;                /* always DRIReqCode */
-    CARD8      driReqType;             /* always X_DRIQueryVersion */
-    CARD16     length B16;
-} xXF86DRIQueryVersionReq;
-#define sz_xXF86DRIQueryVersionReq     4
-
-typedef struct {
-    BYTE       type;                   /* X_Reply */
-    BOOL       pad1;
-    CARD16     sequenceNumber B16;
-    CARD32     length B32;
-    CARD16     majorVersion B16;       /* major version of DRI protocol */
-    CARD16     minorVersion B16;       /* minor version of DRI protocol */
-    CARD32     patchVersion B32;       /* patch version of DRI protocol */
-    CARD32     pad3 B32;
-    CARD32     pad4 B32;
-    CARD32     pad5 B32;
-    CARD32     pad6 B32;
-} xXF86DRIQueryVersionReply;
-#define sz_xXF86DRIQueryVersionReply   32
-
-typedef struct _XF86DRIQueryDirectRenderingCapable {
-    CARD8      reqType;                /* always DRIReqCode */
-    CARD8      driReqType;             /* X_DRIQueryDirectRenderingCapable */
-    CARD16     length B16;
-    CARD32     screen B32;
-} xXF86DRIQueryDirectRenderingCapableReq;
-#define sz_xXF86DRIQueryDirectRenderingCapableReq      8
-
-typedef struct {
-    BYTE       type;                   /* X_Reply */
-    BOOL       pad1;
-    CARD16     sequenceNumber B16;
-    CARD32     length B32;
-    BOOL       isCapable;
-    BOOL       pad2;
-    BOOL       pad3;
-    BOOL       pad4;
-    CARD32     pad5 B32;
-    CARD32     pad6 B32;
-    CARD32     pad7 B32;
-    CARD32     pad8 B32;
-    CARD32     pad9 B32;
-} xXF86DRIQueryDirectRenderingCapableReply;
-#define sz_xXF86DRIQueryDirectRenderingCapableReply    32
-
-typedef struct _XF86DRIOpenConnection {
-    CARD8      reqType;                /* always DRIReqCode */
-    CARD8      driReqType;             /* always X_DRIOpenConnection */
-    CARD16     length B16;
-    CARD32     screen B32;
-} xXF86DRIOpenConnectionReq;
-#define sz_xXF86DRIOpenConnectionReq   8
-
-typedef struct {
-    BYTE       type;                   /* X_Reply */
-    BOOL       pad1;
-    CARD16     sequenceNumber B16;
-    CARD32     length B32;
-    CARD32     hSAREALow B32;
-    CARD32     hSAREAHigh B32;
-    CARD32     busIdStringLength B32;
-    CARD32     pad6 B32;
-    CARD32     pad7 B32;
-    CARD32     pad8 B32;
-} xXF86DRIOpenConnectionReply;
-#define sz_xXF86DRIOpenConnectionReply 32
-
-typedef struct _XF86DRIAuthConnection {
-    CARD8      reqType;                /* always DRIReqCode */
-    CARD8      driReqType;             /* always X_DRICloseConnection */
-    CARD16     length B16;
-    CARD32     screen B32;
-    CARD32      magic B32;
-} xXF86DRIAuthConnectionReq;
-#define sz_xXF86DRIAuthConnectionReq   12
-
-typedef struct {
-    BYTE        type;
-    BOOL        pad1;
-    CARD16      sequenceNumber B16;
-    CARD32      length B32;
-    CARD32      authenticated B32;
-    CARD32      pad2 B32;
-    CARD32      pad3 B32;
-    CARD32      pad4 B32;
-    CARD32      pad5 B32;
-    CARD32      pad6 B32;
-} xXF86DRIAuthConnectionReply;
-#define zx_xXF86DRIAuthConnectionReply  32
-
-typedef struct _XF86DRICloseConnection {
-    CARD8      reqType;                /* always DRIReqCode */
-    CARD8      driReqType;             /* always X_DRICloseConnection */
-    CARD16     length B16;
-    CARD32     screen B32;
-} xXF86DRICloseConnectionReq;
-#define sz_xXF86DRICloseConnectionReq  8
-
-typedef struct _XF86DRIGetClientDriverName {
-    CARD8      reqType;                /* always DRIReqCode */
-    CARD8      driReqType;             /* always X_DRIGetClientDriverName */
-    CARD16     length B16;
-    CARD32     screen B32;
-} xXF86DRIGetClientDriverNameReq;
-#define sz_xXF86DRIGetClientDriverNameReq      8
-
-typedef struct {
-    BYTE       type;                   /* X_Reply */
-    BOOL       pad1;
-    CARD16     sequenceNumber B16;
-    CARD32     length B32;
-    CARD32     ddxDriverMajorVersion B32;
-    CARD32     ddxDriverMinorVersion B32;
-    CARD32     ddxDriverPatchVersion B32;
-    CARD32     clientDriverNameLength B32;
-    CARD32     pad5 B32;
-    CARD32     pad6 B32;
-} xXF86DRIGetClientDriverNameReply;
-#define sz_xXF86DRIGetClientDriverNameReply    32
-
-typedef struct _XF86DRICreateContext {
-    CARD8      reqType;                /* always DRIReqCode */
-    CARD8      driReqType;             /* always X_DRICreateContext */
-    CARD16     length B16;
-    CARD32     screen B32;
-    CARD32     visual B32;
-    CARD32     context B32;
-} xXF86DRICreateContextReq;
-#define sz_xXF86DRICreateContextReq    16
-
-typedef struct {
-    BYTE       type;                   /* X_Reply */
-    BOOL       pad1;
-    CARD16     sequenceNumber B16;
-    CARD32     length B32;
-    CARD32     hHWContext B32;
-    CARD32     pad2 B32;
-    CARD32     pad3 B32;
-    CARD32     pad4 B32;
-    CARD32     pad5 B32;
-    CARD32     pad6 B32;
-} xXF86DRICreateContextReply;
-#define sz_xXF86DRICreateContextReply  32
-
-typedef struct _XF86DRIDestroyContext {
-    CARD8      reqType;                /* always DRIReqCode */
-    CARD8      driReqType;             /* always X_DRIDestroyContext */
-    CARD16     length B16;
-    CARD32     screen B32;
-    CARD32     context B32;
-} xXF86DRIDestroyContextReq;
-#define sz_xXF86DRIDestroyContextReq   12
-
-typedef struct _XF86DRICreateDrawable {
-    CARD8      reqType;                /* always DRIReqCode */
-    CARD8      driReqType;             /* always X_DRICreateDrawable */
-    CARD16     length B16;
-    CARD32     screen B32;
-    CARD32     drawable B32;
-} xXF86DRICreateDrawableReq;
-#define sz_xXF86DRICreateDrawableReq   12
-
-typedef struct {
-    BYTE       type;                   /* X_Reply */
-    BOOL       pad1;
-    CARD16     sequenceNumber B16;
-    CARD32     length B32;
-    CARD32     hHWDrawable B32;
-    CARD32     pad2 B32;
-    CARD32     pad3 B32;
-    CARD32     pad4 B32;
-    CARD32     pad5 B32;
-    CARD32     pad6 B32;
-} xXF86DRICreateDrawableReply;
-#define sz_xXF86DRICreateDrawableReply 32
-
-typedef struct _XF86DRIDestroyDrawable {
-    CARD8      reqType;                /* always DRIReqCode */
-    CARD8      driReqType;             /* always X_DRIDestroyDrawable */
-    CARD16     length B16;
-    CARD32     screen B32;
-    CARD32     drawable B32;
-} xXF86DRIDestroyDrawableReq;
-#define sz_xXF86DRIDestroyDrawableReq  12
-
-typedef struct _XF86DRIGetDrawableInfo {
-    CARD8      reqType;                /* always DRIReqCode */
-    CARD8      driReqType;             /* always X_DRIGetDrawableInfo */
-    CARD16     length B16;
-    CARD32     screen B32;
-    CARD32     drawable B32;
-} xXF86DRIGetDrawableInfoReq;
-#define sz_xXF86DRIGetDrawableInfoReq  12
-
-typedef struct {
-    BYTE       type;                   /* X_Reply */
-    BOOL       pad1;
-    CARD16     sequenceNumber B16;
-    CARD32     length B32;
-    CARD32     drawableTableIndex B32;
-    CARD32     drawableTableStamp B32;
-    INT16      drawableX B16;
-    INT16      drawableY B16;
-    INT16      drawableWidth B16;
-    INT16      drawableHeight B16;
-    CARD32     numClipRects B32;
-    INT16       backX B16;
-    INT16       backY B16;
-    CARD32      numBackClipRects B32;
-} xXF86DRIGetDrawableInfoReply;
-
-#define sz_xXF86DRIGetDrawableInfoReply        36
-
-
-typedef struct _XF86DRIGetDeviceInfo {
-    CARD8      reqType;                /* always DRIReqCode */
-    CARD8      driReqType;             /* always X_DRIGetDeviceInfo */
-    CARD16     length B16;
-    CARD32     screen B32;
-} xXF86DRIGetDeviceInfoReq;
-#define sz_xXF86DRIGetDeviceInfoReq    8
-
-typedef struct {
-    BYTE       type;                   /* X_Reply */
-    BOOL       pad1;
-    CARD16     sequenceNumber B16;
-    CARD32     length B32;
-    CARD32     hFrameBufferLow B32;
-    CARD32     hFrameBufferHigh B32;
-    CARD32     framebufferOrigin B32;
-    CARD32     framebufferSize B32;
-    CARD32     framebufferStride B32;
-    CARD32     devPrivateSize B32;
-} xXF86DRIGetDeviceInfoReply;
-#define sz_xXF86DRIGetDeviceInfoReply  32
-
-typedef struct _XF86DRIOpenFullScreen {
-    CARD8       reqType;       /* always DRIReqCode */
-    CARD8       driReqType;    /* always X_DRIOpenFullScreen */
-    CARD16      length B16;
-    CARD32      screen B32;
-    CARD32      drawable B32;
-} xXF86DRIOpenFullScreenReq;
-#define sz_xXF86DRIOpenFullScreenReq    12
-
-typedef struct {
-    BYTE        type;
-    BOOL        pad1;
-    CARD16      sequenceNumber B16;
-    CARD32      length B32;
-    CARD32      isFullScreen B32;
-    CARD32      pad2 B32;
-    CARD32      pad3 B32;
-    CARD32      pad4 B32;
-    CARD32      pad5 B32;
-    CARD32      pad6 B32;
-} xXF86DRIOpenFullScreenReply;
-#define sz_xXF86DRIOpenFullScreenReply  32
-
-typedef struct _XF86DRICloseFullScreen {
-    CARD8       reqType;       /* always DRIReqCode */
-    CARD8       driReqType;    /* always X_DRICloseFullScreen */
-    CARD16      length B16;
-    CARD32      screen B32;
-    CARD32      drawable B32;
-} xXF86DRICloseFullScreenReq;
-#define sz_xXF86DRICloseFullScreenReq   12
-
-typedef struct {
-    BYTE        type;
-    BOOL        pad1;
-    CARD16      sequenceNumber B16;
-    CARD32      length B32;
-    CARD32      pad2 B32;
-    CARD32      pad3 B32;
-    CARD32      pad4 B32;
-    CARD32      pad5 B32;
-    CARD32      pad6 B32;
-    CARD32      pad7 B32;
-} xXF86DRICloseFullScreenReply;
-#define sz_xXF86DRICloseFullScreenReply  32
-
-
-#endif /* _XF86DRISTR_H_ */
index 02af4d9280a69835bef04611eccc30da3a1d6e9f..05096b12a86f984c55e1f4abb6f20bf732910d3a 100644 (file)
@@ -143,14 +143,11 @@ C_SOURCES = \
        util/u_transfer.c \
        util/u_resource.c \
        util/u_upload_mgr.c \
-       target-helpers/wrap_screen.c
-
-       # Disabling until pipe-video branch gets merged in
-       #vl/vl_bitstream_parser.c \
-       #vl/vl_mpeg12_mc_renderer.c \
-       #vl/vl_compositor.c \
-       #vl/vl_csc.c \
-       #vl/vl_shader_build.c \
+       target-helpers/wrap_screen.c \
+       vl/vl_bitstream_parser.c \
+       vl/vl_mpeg12_mc_renderer.c \
+       vl/vl_compositor.c \
+       vl/vl_csc.c
 
 GALLIVM_SOURCES = \
         gallivm/lp_bld_arit.c \
index 48547c4b2c6fce65fda01f00e121fe9e5050afe0..a18f7c0b2a386a4febd9ef6247e13f660ea321a4 100644 (file)
@@ -192,12 +192,10 @@ source = [
     'util/u_tile.c',
     'util/u_transfer.c',
     'util/u_upload_mgr.c',
-    # Disabling until pipe-video branch gets merged in
-    #'vl/vl_bitstream_parser.c',
-    #'vl/vl_mpeg12_mc_renderer.c',
-    #'vl/vl_compositor.c',
-    #'vl/vl_csc.c',
-    #'vl/vl_shader_build.c',
+    'vl/vl_bitstream_parser.c',
+    'vl/vl_mpeg12_mc_renderer.c',
+    'vl/vl_compositor.c',
+    'vl/vl_csc.c',
     'target-helpers/wrap_screen.c',
 ]
 
index 016e73c4a1dee08b41840bfe4f14fdab39e7e968..0811280b97bedfbeab8c66be54b3d8e2261edfb3 100644 (file)
@@ -230,3 +230,11 @@ PIPE_FORMAT_R32G32B32A32_FIXED    , plain, 1, 1, h32 , h32 , h32 , h32 , xyzw, r
 PIPE_FORMAT_R10G10B10X2_USCALED   , plain, 1, 1, u10 , u10 , u10  , x2 , xyz1, rgb
 # A.k.a. D3DDECLTYPE_DEC3N
 PIPE_FORMAT_R10G10B10X2_SNORM     , plain, 1, 1, sn10, sn10, sn10 , x2 , xyz1, rgb
+
+PIPE_FORMAT_YV12                  , subsampled, 1, 1, x8  , x8  , x8  , x8  , xyzw, yuv
+PIPE_FORMAT_YV16                  , subsampled, 1, 1, x8  , x8  , x8  , x8  , xyzw, yuv
+PIPE_FORMAT_IYUV                  , subsampled, 1, 1, x8  , x8  , x8  , x8  , xyzw, yuv
+PIPE_FORMAT_NV12                  , subsampled, 1, 1, x8  , x8  , x8  , x8  , xyzw, yuv
+PIPE_FORMAT_NV21                  , subsampled, 1, 1, x8  , x8  , x8  , x8  , xyzw, yuv
+PIPE_FORMAT_IA44                  , subsampled, 1, 1, x8  , x8  , x8  , x8  , xyzw, yuv
+PIPE_FORMAT_AI44                  , subsampled, 1, 1, x8  , x8  , x8  , x8  , xyzw, yuv
index ab8bf29c97b9eb665688fc4833cf64594f8c86e6..64ea0b35347b81f51d7dc273220ad3a34c9f1f49 100644 (file)
@@ -1045,3 +1045,138 @@ util_format_yuyv_fetch_rgba_float(float *dst, const uint8_t *src,
 
    dst[3] = 1.0f;
 }
+
+/* XXX: Stubbed for now */
+void
+util_format_yv12_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_yv12_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_yv12_unpack_rgba_float(float *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_yv12_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
+                             const float *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_yv12_fetch_rgba_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j) {}
+void
+util_format_yv16_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_yv16_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_yv16_unpack_rgba_float(float *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_yv16_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
+                             const float *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_yv16_fetch_rgba_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j) {}
+void
+util_format_iyuv_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_iyuv_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_iyuv_unpack_rgba_float(float *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_iyuv_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
+                             const float *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_iyuv_fetch_rgba_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j) {}
+void
+util_format_nv12_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_nv12_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_nv12_unpack_rgba_float(float *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_nv12_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
+                             const float *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_nv12_fetch_rgba_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j) {}
+void
+util_format_nv21_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_nv21_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_nv21_unpack_rgba_float(float *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_nv21_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
+                             const float *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_nv21_fetch_rgba_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j) {}
+void
+util_format_ia44_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_ia44_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_ia44_unpack_rgba_float(float *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_ia44_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
+                             const float *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_ia44_fetch_rgba_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j) {}
+void
+util_format_ai44_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_ai44_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_ai44_unpack_rgba_float(float *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_ai44_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
+                             const float *src_row, unsigned src_stride,
+                             unsigned width, unsigned height) {}
+void
+util_format_ai44_fetch_rgba_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j) {}
index dc9632346d15839178274277e57fbe138c654b79..9f2365a52662e3da093152bdd6916a07c8049328 100644 (file)
@@ -169,6 +169,141 @@ void
 util_format_yuyv_fetch_rgba_float(float *dst, const uint8_t *src,
                              unsigned i, unsigned j);
 
+/* XXX: Stubbed for now */
+void
+util_format_yv12_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_yv12_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_yv12_unpack_rgba_float(float *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_yv12_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
+                             const float *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_yv12_fetch_rgba_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j);
+void
+util_format_yv16_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_yv16_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_yv16_unpack_rgba_float(float *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_yv16_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
+                             const float *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_yv16_fetch_rgba_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j);
+void
+util_format_iyuv_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_iyuv_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_iyuv_unpack_rgba_float(float *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_iyuv_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
+                             const float *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_iyuv_fetch_rgba_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j);
+void
+util_format_nv12_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_nv12_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_nv12_unpack_rgba_float(float *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_nv12_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
+                             const float *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_nv12_fetch_rgba_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j);
+void
+util_format_nv21_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_nv21_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_nv21_unpack_rgba_float(float *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_nv21_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
+                             const float *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_nv21_fetch_rgba_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j);
+void
+util_format_ia44_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_ia44_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_ia44_unpack_rgba_float(float *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_ia44_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
+                             const float *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_ia44_fetch_rgba_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j);
+void
+util_format_ai44_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_ai44_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_ai44_unpack_rgba_float(float *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_ai44_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
+                             const float *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+void
+util_format_ai44_fetch_rgba_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j);
+
 
 void
 util_format_r8g8_b8g8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
diff --git a/src/gallium/auxiliary/util/u_video.h b/src/gallium/auxiliary/util/u_video.h
new file mode 100644 (file)
index 0000000..78cceb6
--- /dev/null
@@ -0,0 +1,71 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef U_VIDEO_H
+#define U_VIDEO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <pipe/p_defines.h>
+
+/* u_reduce_video_profile() needs these */
+#include <pipe/p_compiler.h>
+#include <util/u_debug.h>
+
+static INLINE enum pipe_video_codec
+u_reduce_video_profile(enum pipe_video_profile profile)
+{
+   switch (profile)
+   {
+      case PIPE_VIDEO_PROFILE_MPEG1:
+      case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE:
+      case PIPE_VIDEO_PROFILE_MPEG2_MAIN:
+         return PIPE_VIDEO_CODEC_MPEG12;
+
+      case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE:
+      case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE:
+         return PIPE_VIDEO_CODEC_MPEG4;
+
+      case PIPE_VIDEO_PROFILE_VC1_SIMPLE:
+      case PIPE_VIDEO_PROFILE_VC1_MAIN:
+      case PIPE_VIDEO_PROFILE_VC1_ADVANCED:
+         return PIPE_VIDEO_CODEC_VC1;
+
+      case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE:
+      case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
+      case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
+         return PIPE_VIDEO_CODEC_MPEG4_AVC;
+
+      default:
+         assert(0);
+         return PIPE_VIDEO_CODEC_UNKNOWN;
+   }
+}
+
+#endif /* U_VIDEO_H */
diff --git a/src/gallium/auxiliary/vl/vl_bitstream_parser.c b/src/gallium/auxiliary/vl/vl_bitstream_parser.c
new file mode 100644 (file)
index 0000000..3193ea5
--- /dev/null
@@ -0,0 +1,167 @@
+/**************************************************************************
+ * 
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "vl_bitstream_parser.h"
+#include <assert.h>
+#include <limits.h>
+#include <util/u_memory.h>
+
+static unsigned
+grab_bits(unsigned cursor, unsigned how_many_bits, unsigned bitstream_elt)
+{
+   unsigned excess_bits = sizeof(unsigned) * CHAR_BIT - how_many_bits - cursor;
+       
+   assert(cursor < sizeof(unsigned) * CHAR_BIT);
+   assert(how_many_bits > 0 && how_many_bits <= sizeof(unsigned) * CHAR_BIT);
+   assert(cursor + how_many_bits <= sizeof(unsigned) * CHAR_BIT);
+
+   return (bitstream_elt << excess_bits) >> (excess_bits + cursor);
+}
+
+static unsigned
+show_bits(unsigned cursor, unsigned how_many_bits, const unsigned *bitstream)
+{      
+   unsigned cur_int = cursor / (sizeof(unsigned) * CHAR_BIT);
+   unsigned cur_bit = cursor % (sizeof(unsigned) * CHAR_BIT);
+       
+   assert(bitstream);
+       
+   if (cur_bit + how_many_bits > sizeof(unsigned) * CHAR_BIT) {
+      unsigned lower = grab_bits(cur_bit, sizeof(unsigned) * CHAR_BIT - cur_bit,
+                                 bitstream[cur_int]);
+      unsigned upper = grab_bits(0, cur_bit + how_many_bits - sizeof(unsigned) * CHAR_BIT,
+                                 bitstream[cur_int + 1]);
+      return lower | upper << (sizeof(unsigned) * CHAR_BIT - cur_bit);
+   }
+   else
+      return grab_bits(cur_bit, how_many_bits, bitstream[cur_int]);
+}
+
+bool vl_bitstream_parser_init(struct vl_bitstream_parser *parser,
+                              unsigned num_bitstreams,
+                              const void **bitstreams,
+                              const unsigned *sizes)
+{
+   assert(parser);
+   assert(num_bitstreams);
+   assert(bitstreams);
+   assert(sizes);
+
+   parser->num_bitstreams = num_bitstreams;
+   parser->bitstreams = (const unsigned**)bitstreams;
+   parser->sizes = sizes;
+   parser->cur_bitstream = 0;
+   parser->cursor = 0;
+
+   return true;
+}
+
+void vl_bitstream_parser_cleanup(struct vl_bitstream_parser *parser)
+{
+   assert(parser);
+}
+
+unsigned
+vl_bitstream_parser_get_bits(struct vl_bitstream_parser *parser,
+                             unsigned how_many_bits)
+{
+   unsigned bits;
+
+   assert(parser);
+
+   bits = vl_bitstream_parser_show_bits(parser, how_many_bits);
+
+   vl_bitstream_parser_forward(parser, how_many_bits);
+
+   return bits;
+}
+
+unsigned
+vl_bitstream_parser_show_bits(struct vl_bitstream_parser *parser,
+                              unsigned how_many_bits)
+{      
+   unsigned bits = 0;
+   unsigned shift = 0;
+   unsigned cursor;
+   unsigned cur_bitstream;
+
+   assert(parser);
+
+   cursor = parser->cursor;
+   cur_bitstream = parser->cur_bitstream;
+
+   while (1) {
+      unsigned bits_left = parser->sizes[cur_bitstream] * CHAR_BIT - cursor;
+      unsigned bits_to_show = how_many_bits > bits_left ? bits_left : how_many_bits;
+
+      bits |= show_bits(cursor, bits_to_show,
+                        parser->bitstreams[cur_bitstream]) << shift;
+               
+      if (how_many_bits > bits_to_show) {
+         how_many_bits -= bits_to_show;
+         cursor = 0;
+         ++cur_bitstream;
+         shift += bits_to_show;
+      }
+      else
+         break;
+   }
+
+   return bits;
+}
+
+void vl_bitstream_parser_forward(struct vl_bitstream_parser *parser,
+                                 unsigned how_many_bits)
+{
+   assert(parser);
+   assert(how_many_bits);
+
+   parser->cursor += how_many_bits;
+
+   while (parser->cursor > parser->sizes[parser->cur_bitstream] * CHAR_BIT) {
+      parser->cursor -= parser->sizes[parser->cur_bitstream++] * CHAR_BIT;
+      assert(parser->cur_bitstream < parser->num_bitstreams);
+   }
+}
+
+void vl_bitstream_parser_rewind(struct vl_bitstream_parser *parser,
+                                unsigned how_many_bits)
+{
+   signed c;
+       
+   assert(parser);
+   assert(how_many_bits);
+       
+   c = parser->cursor - how_many_bits;
+
+   while (c < 0) {
+      c += parser->sizes[parser->cur_bitstream--] * CHAR_BIT;
+      assert(parser->cur_bitstream < parser->num_bitstreams);
+   }
+
+   parser->cursor = (unsigned)c;
+}
diff --git a/src/gallium/auxiliary/vl/vl_bitstream_parser.h b/src/gallium/auxiliary/vl/vl_bitstream_parser.h
new file mode 100644 (file)
index 0000000..30ec743
--- /dev/null
@@ -0,0 +1,63 @@
+/**************************************************************************
+ * 
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef vl_bitstream_parser_h
+#define vl_bitstream_parser_h
+
+#include "pipe/p_compiler.h"
+
+struct vl_bitstream_parser
+{
+   unsigned num_bitstreams;
+   const unsigned **bitstreams;
+   const unsigned *sizes;
+   unsigned cur_bitstream;
+   unsigned cursor;
+};
+
+bool vl_bitstream_parser_init(struct vl_bitstream_parser *parser,
+                              unsigned num_bitstreams,
+                              const void **bitstreams,
+                              const unsigned *sizes);
+
+void vl_bitstream_parser_cleanup(struct vl_bitstream_parser *parser);
+
+unsigned
+vl_bitstream_parser_get_bits(struct vl_bitstream_parser *parser,
+                             unsigned how_many_bits);
+
+unsigned
+vl_bitstream_parser_show_bits(struct vl_bitstream_parser *parser,
+                              unsigned how_many_bits);
+
+void vl_bitstream_parser_forward(struct vl_bitstream_parser *parser,
+                                 unsigned how_many_bits);
+
+void vl_bitstream_parser_rewind(struct vl_bitstream_parser *parser,
+                                unsigned how_many_bits);
+
+#endif /* vl_bitstream_parser_h */
diff --git a/src/gallium/auxiliary/vl/vl_compositor.c b/src/gallium/auxiliary/vl/vl_compositor.c
new file mode 100644 (file)
index 0000000..0640b1a
--- /dev/null
@@ -0,0 +1,636 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vl_compositor.h"
+#include <assert.h>
+#include <pipe/p_context.h>
+#include <util/u_inlines.h>
+#include <util/u_memory.h>
+#include <util/u_keymap.h>
+#include <util/u_sampler.h>
+#include <tgsi/tgsi_ureg.h>
+#include "vl_csc.h"
+
+struct vertex_shader_consts
+{
+   struct vertex4f dst_scale;
+   struct vertex4f dst_trans;
+   struct vertex4f src_scale;
+   struct vertex4f src_trans;
+};
+
+struct fragment_shader_consts
+{
+   float matrix[16];
+};
+
+static bool
+u_video_rects_equal(struct pipe_video_rect *a, struct pipe_video_rect *b)
+{
+   assert(a && b);
+
+   if (a->x != b->x)
+      return false;
+   if (a->y != b->y)
+      return false;
+   if (a->w != b->w)
+      return false;
+   if (a->h != b->h)
+      return false;
+
+   return true;
+}
+
+static bool
+create_vert_shader(struct vl_compositor *c)
+{
+   struct ureg_program *shader;
+   struct ureg_src vpos, vtex;
+   struct ureg_dst o_vpos, o_vtex;
+
+   shader = ureg_create(TGSI_PROCESSOR_VERTEX);
+   if (!shader)
+      return false;
+
+   vpos = ureg_DECL_vs_input(shader, 0);
+   vtex = ureg_DECL_vs_input(shader, 1);
+   o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, 0);
+   o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, 1);
+
+   /*
+    * o_vpos = vpos
+    * o_vtex = vtex
+    */
+   ureg_MOV(shader, o_vpos, vpos);
+   ureg_MOV(shader, o_vtex, vtex);
+
+   ureg_END(shader);
+
+   c->vertex_shader = ureg_create_shader_and_destroy(shader, c->pipe);
+   if (!c->vertex_shader)
+      return false;
+
+   return true;
+}
+
+static bool
+create_frag_shader_ycbcr_2_rgb(struct vl_compositor *c)
+{
+   struct ureg_program *shader;
+   struct ureg_src tc;
+   struct ureg_src csc[4];
+   struct ureg_src sampler;
+   struct ureg_dst texel;
+   struct ureg_dst fragment;
+   unsigned i;
+
+   shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+   if (!shader)
+      return false;
+
+   tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, 1, TGSI_INTERPOLATE_LINEAR);
+   for (i = 0; i < 4; ++i)
+      csc[i] = ureg_DECL_constant(shader, i);
+   sampler = ureg_DECL_sampler(shader, 0);
+   texel = ureg_DECL_temporary(shader);
+   fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
+
+   /*
+    * texel = tex(tc, sampler)
+    * fragment = csc * texel
+    */
+   ureg_TEX(shader, texel, TGSI_TEXTURE_2D, tc, sampler);
+   for (i = 0; i < 4; ++i)
+      ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(texel));
+
+   ureg_release_temporary(shader, texel);
+   ureg_END(shader);
+
+   c->fragment_shader.ycbcr_2_rgb = ureg_create_shader_and_destroy(shader, c->pipe);
+   if (!c->fragment_shader.ycbcr_2_rgb)
+      return false;
+
+   return true;
+}
+
+static bool
+create_frag_shader_rgb_2_rgb(struct vl_compositor *c)
+{
+   struct ureg_program *shader;
+   struct ureg_src tc;
+   struct ureg_src sampler;
+   struct ureg_dst fragment;
+
+   shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+   if (!shader)
+      return false;
+
+   tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, 1, TGSI_INTERPOLATE_LINEAR);
+   sampler = ureg_DECL_sampler(shader, 0);
+   fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
+
+   /*
+    * fragment = tex(tc, sampler)
+    */
+   ureg_TEX(shader, fragment, TGSI_TEXTURE_2D, tc, sampler);
+   ureg_END(shader);
+
+   c->fragment_shader.rgb_2_rgb = ureg_create_shader_and_destroy(shader, c->pipe);
+   if (!c->fragment_shader.rgb_2_rgb)
+      return false;
+
+   return true;
+}
+
+static bool
+init_pipe_state(struct vl_compositor *c)
+{
+   struct pipe_sampler_state sampler;
+
+   assert(c);
+
+   c->fb_state.nr_cbufs = 1;
+   c->fb_state.zsbuf = NULL;
+
+   sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+   sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+   sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+   sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
+   sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+   sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
+   sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
+   sampler.compare_func = PIPE_FUNC_ALWAYS;
+   sampler.normalized_coords = 1;
+   /*sampler.lod_bias = ;*/
+   /*sampler.min_lod = ;*/
+   /*sampler.max_lod = ;*/
+   /*sampler.border_color[i] = ;*/
+   /*sampler.max_anisotropy = ;*/
+   c->sampler = c->pipe->create_sampler_state(c->pipe, &sampler);
+
+   return true;
+}
+
+static void cleanup_pipe_state(struct vl_compositor *c)
+{
+   assert(c);
+
+   c->pipe->delete_sampler_state(c->pipe, c->sampler);
+}
+
+static bool
+init_shaders(struct vl_compositor *c)
+{
+   assert(c);
+
+   if (!create_vert_shader(c)) {
+      debug_printf("Unable to create vertex shader.\n");
+      return false;
+   }
+   if (!create_frag_shader_ycbcr_2_rgb(c)) {
+      debug_printf("Unable to create YCbCr-to-RGB fragment shader.\n");
+      return false;
+   }
+   if (!create_frag_shader_rgb_2_rgb(c)) {
+      debug_printf("Unable to create RGB-to-RGB fragment shader.\n");
+      return false;
+   }
+
+   return true;
+}
+
+static void cleanup_shaders(struct vl_compositor *c)
+{
+   assert(c);
+
+   c->pipe->delete_vs_state(c->pipe, c->vertex_shader);
+   c->pipe->delete_fs_state(c->pipe, c->fragment_shader.ycbcr_2_rgb);
+   c->pipe->delete_fs_state(c->pipe, c->fragment_shader.rgb_2_rgb);
+}
+
+static bool
+init_buffers(struct vl_compositor *c)
+{
+   struct fragment_shader_consts fsc;
+   struct pipe_vertex_element vertex_elems[2];
+
+   assert(c);
+
+   /*
+    * Create our vertex buffer and vertex buffer elements
+    */
+   c->vertex_buf.stride = sizeof(struct vertex4f);
+   c->vertex_buf.max_index = (VL_COMPOSITOR_MAX_LAYERS + 2) * 6 - 1;
+   c->vertex_buf.buffer_offset = 0;
+   /* XXX: Create with DYNAMIC or STREAM */
+   c->vertex_buf.buffer = pipe_buffer_create
+   (
+      c->pipe->screen,
+      PIPE_BIND_VERTEX_BUFFER,
+      sizeof(struct vertex4f) * (VL_COMPOSITOR_MAX_LAYERS + 2) * 6
+   );
+
+   vertex_elems[0].src_offset = 0;
+   vertex_elems[0].instance_divisor = 0;
+   vertex_elems[0].vertex_buffer_index = 0;
+   vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
+   vertex_elems[1].src_offset = sizeof(struct vertex2f);
+   vertex_elems[1].instance_divisor = 0;
+   vertex_elems[1].vertex_buffer_index = 0;
+   vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
+   c->vertex_elems_state = c->pipe->create_vertex_elements_state(c->pipe, 2, vertex_elems);
+
+   /*
+    * Create our fragment shader's constant buffer
+    * Const buffer contains the color conversion matrix and bias vectors
+    */
+   /* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */
+   c->fs_const_buf = pipe_buffer_create
+   (
+      c->pipe->screen,
+      PIPE_BIND_CONSTANT_BUFFER,
+      sizeof(struct fragment_shader_consts)
+   );
+
+   vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, fsc.matrix);
+
+   vl_compositor_set_csc_matrix(c, fsc.matrix);
+
+   return true;
+}
+
+static void
+cleanup_buffers(struct vl_compositor *c)
+{
+   assert(c);
+
+   c->pipe->delete_vertex_elements_state(c->pipe, c->vertex_elems_state);
+   pipe_resource_reference(&c->vertex_buf.buffer, NULL);
+   pipe_resource_reference(&c->fs_const_buf, NULL);
+}
+
+static void
+texview_map_delete(const struct keymap *map,
+                   const void *key, void *data,
+                   void *user)
+{
+   struct pipe_sampler_view *sv = (struct pipe_sampler_view*)data;
+
+   assert(map);
+   assert(key);
+   assert(data);
+   assert(user);
+
+   pipe_sampler_view_reference(&sv, NULL);
+}
+
+bool vl_compositor_init(struct vl_compositor *compositor, struct pipe_context *pipe)
+{
+   unsigned i;
+
+   assert(compositor);
+
+   memset(compositor, 0, sizeof(struct vl_compositor));
+
+   compositor->pipe = pipe;
+
+   compositor->texview_map = util_new_keymap(sizeof(struct pipe_surface*), -1,
+                                             texview_map_delete);
+   if (!compositor->texview_map)
+      return false;
+
+   if (!init_pipe_state(compositor)) {
+      util_delete_keymap(compositor->texview_map, compositor->pipe);
+      return false;
+   }
+   if (!init_shaders(compositor)) {
+      util_delete_keymap(compositor->texview_map, compositor->pipe);
+      cleanup_pipe_state(compositor);
+      return false;
+   }
+   if (!init_buffers(compositor)) {
+      util_delete_keymap(compositor->texview_map, compositor->pipe);
+      cleanup_shaders(compositor);
+      cleanup_pipe_state(compositor);
+      return false;
+   }
+
+   compositor->fb_state.width = 0;
+   compositor->fb_state.height = 0;
+   compositor->bg = NULL;
+   compositor->dirty_bg = false;
+   for (i = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i)
+      compositor->layers[i] = NULL;
+   compositor->dirty_layers = 0;
+
+   return true;
+}
+
+void vl_compositor_cleanup(struct vl_compositor *compositor)
+{
+   assert(compositor);
+
+   util_delete_keymap(compositor->texview_map, compositor->pipe);
+   cleanup_buffers(compositor);
+   cleanup_shaders(compositor);
+   cleanup_pipe_state(compositor);
+}
+
+void vl_compositor_set_background(struct vl_compositor *compositor,
+                                 struct pipe_surface *bg, struct pipe_video_rect *bg_src_rect)
+{
+   assert(compositor);
+   assert((bg && bg_src_rect) || (!bg && !bg_src_rect));
+
+   if (compositor->bg != bg ||
+       !u_video_rects_equal(&compositor->bg_src_rect, bg_src_rect)) {
+      pipe_surface_reference(&compositor->bg, bg);
+      /*if (!u_video_rects_equal(&compositor->bg_src_rect, bg_src_rect))*/
+         compositor->bg_src_rect = *bg_src_rect;
+      compositor->dirty_bg = true;
+   }
+}
+
+void vl_compositor_set_layers(struct vl_compositor *compositor,
+                              struct pipe_surface *layers[],
+                              struct pipe_video_rect *src_rects[],
+                              struct pipe_video_rect *dst_rects[],
+                              unsigned num_layers)
+{
+   unsigned i;
+
+   assert(compositor);
+   assert(num_layers <= VL_COMPOSITOR_MAX_LAYERS);
+
+   for (i = 0; i < num_layers; ++i)
+   {
+      assert((layers[i] && src_rects[i] && dst_rects[i]) ||
+             (!layers[i] && !src_rects[i] && !dst_rects[i]));
+
+      if (compositor->layers[i] != layers[i] ||
+          !u_video_rects_equal(&compositor->layer_src_rects[i], src_rects[i]) ||
+          !u_video_rects_equal(&compositor->layer_dst_rects[i], dst_rects[i]))
+      {
+         pipe_surface_reference(&compositor->layers[i], layers[i]);
+         /*if (!u_video_rects_equal(&compositor->layer_src_rects[i], src_rects[i]))*/
+            compositor->layer_src_rects[i] = *src_rects[i];
+         /*if (!u_video_rects_equal(&compositor->layer_dst_rects[i], dst_rects[i]))*/
+            compositor->layer_dst_rects[i] = *dst_rects[i];
+         compositor->dirty_layers |= 1 << i;
+      }
+
+      if (layers[i])
+         compositor->dirty_layers |= 1 << i;
+   }
+
+   for (; i < VL_COMPOSITOR_MAX_LAYERS; ++i)
+      pipe_surface_reference(&compositor->layers[i], NULL);
+}
+
+static void gen_rect_verts(unsigned pos,
+                           struct pipe_video_rect *src_rect,
+                           struct vertex2f *src_inv_size,
+                           struct pipe_video_rect *dst_rect,
+                           struct vertex2f *dst_inv_size,
+                           struct vertex4f *vb)
+{
+   assert(pos < VL_COMPOSITOR_MAX_LAYERS + 2);
+   assert(src_rect);
+   assert(src_inv_size);
+   assert((dst_rect && dst_inv_size) /*|| (!dst_rect && !dst_inv_size)*/);
+   assert(vb);
+
+   vb[pos * 6 + 0].x = dst_rect->x * dst_inv_size->x;
+   vb[pos * 6 + 0].y = dst_rect->y * dst_inv_size->y;
+   vb[pos * 6 + 0].z = src_rect->x * src_inv_size->x;
+   vb[pos * 6 + 0].w = src_rect->y * src_inv_size->y;
+
+   vb[pos * 6 + 1].x = dst_rect->x * dst_inv_size->x;
+   vb[pos * 6 + 1].y = (dst_rect->y + dst_rect->h) * dst_inv_size->y;
+   vb[pos * 6 + 1].z = src_rect->x * src_inv_size->x;
+   vb[pos * 6 + 1].w = (src_rect->y + src_rect->h) * src_inv_size->y;
+
+   vb[pos * 6 + 2].x = (dst_rect->x + dst_rect->w) * dst_inv_size->x;
+   vb[pos * 6 + 2].y = dst_rect->y * dst_inv_size->y;
+   vb[pos * 6 + 2].z = (src_rect->x + src_rect->w) * src_inv_size->x;
+   vb[pos * 6 + 2].w = src_rect->y * src_inv_size->y;
+
+   vb[pos * 6 + 3].x = (dst_rect->x + dst_rect->w) * dst_inv_size->x;
+   vb[pos * 6 + 3].y = dst_rect->y * dst_inv_size->y;
+   vb[pos * 6 + 3].z = (src_rect->x + src_rect->w) * src_inv_size->x;
+   vb[pos * 6 + 3].w = src_rect->y * src_inv_size->y;
+
+   vb[pos * 6 + 4].x = dst_rect->x * dst_inv_size->x;
+   vb[pos * 6 + 4].y = (dst_rect->y + dst_rect->h) * dst_inv_size->y;
+   vb[pos * 6 + 4].z = src_rect->x * src_inv_size->x;
+   vb[pos * 6 + 4].w = (src_rect->y + src_rect->h) * src_inv_size->y;
+
+   vb[pos * 6 + 5].x = (dst_rect->x + dst_rect->w) * dst_inv_size->x;
+   vb[pos * 6 + 5].y = (dst_rect->y + dst_rect->h) * dst_inv_size->y;
+   vb[pos * 6 + 5].z = (src_rect->x + src_rect->w) * src_inv_size->x;
+   vb[pos * 6 + 5].w = (src_rect->y + src_rect->h) * src_inv_size->y;
+}
+
+static unsigned gen_data(struct vl_compositor *c,
+                         struct pipe_surface *src_surface,
+                         struct pipe_video_rect *src_rect,
+                         struct pipe_video_rect *dst_rect,
+                         struct pipe_surface **textures,
+                         void **frag_shaders)
+{
+   void *vb;
+   struct pipe_transfer *buf_transfer;
+   unsigned num_rects = 0;
+   unsigned i;
+
+   assert(c);
+   assert(src_surface);
+   assert(src_rect);
+   assert(dst_rect);
+   assert(textures);
+
+   vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer,
+                        PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
+                        &buf_transfer);
+
+   if (!vb)
+      return 0;
+
+   if (c->dirty_bg) {
+      struct vertex2f bg_inv_size = {1.0f / c->bg->width, 1.0f / c->bg->height};
+      gen_rect_verts(num_rects, &c->bg_src_rect, &bg_inv_size, NULL, NULL, vb);
+      textures[num_rects] = c->bg;
+      /* XXX: Hack */
+      frag_shaders[num_rects] = c->fragment_shader.rgb_2_rgb;
+      ++num_rects;
+      c->dirty_bg = false;
+   }
+
+   {
+      struct vertex2f src_inv_size = { 1.0f / src_surface->width, 1.0f / src_surface->height};
+      gen_rect_verts(num_rects, src_rect, &src_inv_size, dst_rect, &c->fb_inv_size, vb);
+      textures[num_rects] = src_surface;
+      /* XXX: Hack, sort of */
+      frag_shaders[num_rects] = c->fragment_shader.ycbcr_2_rgb;
+      ++num_rects;
+   }
+
+   for (i = 0; c->dirty_layers > 0; i++) {
+      assert(i < VL_COMPOSITOR_MAX_LAYERS);
+
+      if (c->dirty_layers & (1 << i)) {
+         struct vertex2f layer_inv_size = {1.0f / c->layers[i]->width, 1.0f / c->layers[i]->height};
+         gen_rect_verts(num_rects, &c->layer_src_rects[i], &layer_inv_size,
+                        &c->layer_dst_rects[i], &c->fb_inv_size, vb);
+         textures[num_rects] = c->layers[i];
+         /* XXX: Hack */
+         frag_shaders[num_rects] = c->fragment_shader.rgb_2_rgb;
+         ++num_rects;
+         c->dirty_layers &= ~(1 << i);
+      }
+   }
+
+   pipe_buffer_unmap(c->pipe, c->vertex_buf.buffer, buf_transfer);
+
+   return num_rects;
+}
+
+static void draw_layers(struct vl_compositor *c,
+                        struct pipe_surface *src_surface,
+                        struct pipe_video_rect *src_rect,
+                        struct pipe_video_rect *dst_rect)
+{
+   unsigned num_rects;
+   struct pipe_surface *src_surfaces[VL_COMPOSITOR_MAX_LAYERS + 2];
+   void *frag_shaders[VL_COMPOSITOR_MAX_LAYERS + 2];
+   unsigned i;
+
+   assert(c);
+   assert(src_surface);
+   assert(src_rect);
+   assert(dst_rect);
+
+   num_rects = gen_data(c, src_surface, src_rect, dst_rect, src_surfaces, frag_shaders);
+
+   for (i = 0; i < num_rects; ++i) {
+      boolean delete_view = FALSE;
+      struct pipe_sampler_view *surface_view = (struct pipe_sampler_view*)util_keymap_lookup(c->texview_map,
+                                                                                             &src_surfaces[i]);
+      if (!surface_view) {
+         struct pipe_sampler_view templat;
+         u_sampler_view_default_template(&templat, src_surfaces[i]->texture,
+                                         src_surfaces[i]->texture->format);
+         surface_view = c->pipe->create_sampler_view(c->pipe, src_surfaces[i]->texture,
+                                                     &templat);
+         if (!surface_view)
+            return;
+
+         delete_view = !util_keymap_insert(c->texview_map, &src_surfaces[i],
+                                           surface_view, c->pipe);
+      }
+
+      c->pipe->bind_fs_state(c->pipe, frag_shaders[i]);
+      c->pipe->set_fragment_sampler_views(c->pipe, 1, &surface_view);
+      c->pipe->draw_arrays(c->pipe, PIPE_PRIM_TRIANGLES, i * 6, 6);
+
+      if (delete_view) {
+         pipe_sampler_view_reference(&surface_view, NULL);
+      }
+   }
+}
+
+void vl_compositor_render(struct vl_compositor          *compositor,
+                          struct pipe_surface           *src_surface,
+                          enum pipe_mpeg12_picture_type picture_type,
+                          /*unsigned                    num_past_surfaces,
+                          struct pipe_surface           *past_surfaces,
+                          unsigned                      num_future_surfaces,
+                          struct pipe_surface           *future_surfaces,*/
+                          struct pipe_video_rect        *src_area,
+                          struct pipe_surface           *dst_surface,
+                          struct pipe_video_rect        *dst_area,
+                          struct pipe_fence_handle      **fence)
+{
+   assert(compositor);
+   assert(src_surface);
+   assert(src_area);
+   assert(dst_surface);
+   assert(dst_area);
+   assert(picture_type == PIPE_MPEG12_PICTURE_TYPE_FRAME);
+
+   if (compositor->fb_state.width != dst_surface->width) {
+      compositor->fb_inv_size.x = 1.0f / dst_surface->width;
+      compositor->fb_state.width = dst_surface->width;
+   }
+   if (compositor->fb_state.height != dst_surface->height) {
+      compositor->fb_inv_size.y = 1.0f / dst_surface->height;
+      compositor->fb_state.height = dst_surface->height;
+   }
+
+   compositor->fb_state.cbufs[0] = dst_surface;
+
+   compositor->viewport.scale[0] = compositor->fb_state.width;
+   compositor->viewport.scale[1] = compositor->fb_state.height;
+   compositor->viewport.scale[2] = 1;
+   compositor->viewport.scale[3] = 1;
+   compositor->viewport.translate[0] = 0;
+   compositor->viewport.translate[1] = 0;
+   compositor->viewport.translate[2] = 0;
+   compositor->viewport.translate[3] = 0;
+
+   compositor->pipe->set_framebuffer_state(compositor->pipe, &compositor->fb_state);
+   compositor->pipe->set_viewport_state(compositor->pipe, &compositor->viewport);
+   compositor->pipe->bind_fragment_sampler_states(compositor->pipe, 1, &compositor->sampler);
+   compositor->pipe->bind_vs_state(compositor->pipe, compositor->vertex_shader);
+   compositor->pipe->set_vertex_buffers(compositor->pipe, 1, &compositor->vertex_buf);
+   compositor->pipe->bind_vertex_elements_state(compositor->pipe, compositor->vertex_elems_state);
+   compositor->pipe->set_constant_buffer(compositor->pipe, PIPE_SHADER_FRAGMENT, 0, compositor->fs_const_buf);
+
+   draw_layers(compositor, src_surface, src_area, dst_area);
+
+   assert(!compositor->dirty_bg && !compositor->dirty_layers);
+   compositor->pipe->flush(compositor->pipe, PIPE_FLUSH_RENDER_CACHE, fence);
+}
+
+void vl_compositor_set_csc_matrix(struct vl_compositor *compositor, const float *mat)
+{
+   struct pipe_transfer *buf_transfer;
+
+   assert(compositor);
+
+   memcpy
+   (
+      pipe_buffer_map(compositor->pipe, compositor->fs_const_buf,
+                      PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
+                      &buf_transfer),
+      mat,
+      sizeof(struct fragment_shader_consts)
+   );
+
+   pipe_buffer_unmap(compositor->pipe, compositor->fs_const_buf,
+                     buf_transfer);
+}
diff --git a/src/gallium/auxiliary/vl/vl_compositor.h b/src/gallium/auxiliary/vl/vl_compositor.h
new file mode 100644 (file)
index 0000000..820c9ef
--- /dev/null
@@ -0,0 +1,98 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef vl_compositor_h
+#define vl_compositor_h
+
+#include <pipe/p_compiler.h>
+#include <pipe/p_state.h>
+#include <pipe/p_video_state.h>
+#include "vl_types.h"
+
+struct pipe_context;
+struct keymap;
+
+#define VL_COMPOSITOR_MAX_LAYERS 16
+
+struct vl_compositor
+{
+   struct pipe_context *pipe;
+
+   struct pipe_framebuffer_state fb_state;
+   struct vertex2f fb_inv_size;
+   void *sampler;
+   struct pipe_sampler_view *sampler_view;
+   void *vertex_shader;
+   struct
+   {
+      void *ycbcr_2_rgb;
+      void *rgb_2_rgb;
+   } fragment_shader;
+   struct pipe_viewport_state viewport;
+   struct pipe_vertex_buffer vertex_buf;
+   void *vertex_elems_state;
+   struct pipe_resource *fs_const_buf;
+
+   struct pipe_surface *bg;
+   struct pipe_video_rect bg_src_rect;
+   bool dirty_bg;
+   struct pipe_surface *layers[VL_COMPOSITOR_MAX_LAYERS];
+   struct pipe_video_rect layer_src_rects[VL_COMPOSITOR_MAX_LAYERS];
+   struct pipe_video_rect layer_dst_rects[VL_COMPOSITOR_MAX_LAYERS];
+   unsigned dirty_layers;
+
+   struct keymap *texview_map;
+};
+
+bool vl_compositor_init(struct vl_compositor *compositor, struct pipe_context *pipe);
+
+void vl_compositor_cleanup(struct vl_compositor *compositor);
+
+void vl_compositor_set_background(struct vl_compositor *compositor,
+                                  struct pipe_surface *bg, struct pipe_video_rect *bg_src_rect);
+
+void vl_compositor_set_layers(struct vl_compositor *compositor,
+                              struct pipe_surface *layers[],
+                              struct pipe_video_rect *src_rects[],
+                              struct pipe_video_rect *dst_rects[],
+                              unsigned num_layers);
+
+void vl_compositor_render(struct vl_compositor          *compositor,
+                          struct pipe_surface           *src_surface,
+                          enum pipe_mpeg12_picture_type picture_type,
+                          /*unsigned                    num_past_surfaces,
+                          struct pipe_surface           *past_surfaces,
+                          unsigned                      num_future_surfaces,
+                          struct pipe_surface           *future_surfaces,*/
+                          struct pipe_video_rect        *src_area,
+                          struct pipe_surface           *dst_surface,
+                          struct pipe_video_rect        *dst_area,
+                          struct pipe_fence_handle      **fence);
+
+void vl_compositor_set_csc_matrix(struct vl_compositor *compositor, const float *mat);
+
+#endif /* vl_compositor_h */
diff --git a/src/gallium/auxiliary/vl/vl_csc.c b/src/gallium/auxiliary/vl/vl_csc.c
new file mode 100644 (file)
index 0000000..5ecc43a
--- /dev/null
@@ -0,0 +1,206 @@
+/**************************************************************************
+ * 
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "vl_csc.h"
+#include <util/u_math.h>
+#include <util/u_debug.h>
+
+/*
+ * Color space conversion formulas
+ *
+ * To convert YCbCr to RGB,
+ *    vec4  ycbcr, rgb
+ *    mat44 csc
+ *    rgb = csc * ycbcr
+ *
+ * To calculate the color space conversion matrix csc with ProcAmp adjustments,
+ *    mat44 csc, cstd, procamp, bias
+ *    csc = cstd * (procamp * bias)
+ *
+ * Where cstd is a matrix corresponding to one of the color standards (BT.601, BT.709, etc)
+ * adjusted for the kind of YCbCr -> RGB mapping wanted (1:1, full),
+ * bias is a matrix corresponding to the kind of YCbCr -> RGB mapping wanted (1:1, full)
+ *
+ * To calculate procamp,
+ *    mat44 procamp, hue, saturation, brightness, contrast
+ *    procamp = brightness * (saturation * (contrast * hue))
+ * Alternatively,
+ *    procamp = saturation * (brightness * (contrast * hue))
+ *
+ * contrast
+ * [ c, 0, 0, 0]
+ * [ 0, c, 0, 0]
+ * [ 0, 0, c, 0]
+ * [ 0, 0, 0, 1]
+ *
+ * brightness
+ * [ 1, 0, 0, b]
+ * [ 0, 1, 0, 0]
+ * [ 0, 0, 1, 0]
+ * [ 0, 0, 0, 1]
+ *
+ * saturation
+ * [ 1, 0, 0, 0]
+ * [ 0, s, 0, 0]
+ * [ 0, 0, s, 0]
+ * [ 0, 0, 0, 1]
+ *
+ * hue
+ * [ 1,       0,      0, 0]
+ * [ 0,  cos(h), sin(h), 0]
+ * [ 0, -sin(h), cos(h), 0]
+ * [ 0,       0,      0, 1]
+ *
+ * procamp
+ * [ c,           0,          0, b]
+ * [ 0,  c*s*cos(h), c*s*sin(h), 0]
+ * [ 0, -c*s*sin(h), c*s*cos(h), 0]
+ * [ 0,           0,          0, 1]
+ *
+ * bias
+ * [ 1, 0, 0,  ybias]
+ * [ 0, 1, 0, cbbias]
+ * [ 0, 0, 1, crbias]
+ * [ 0, 0, 0,      1]
+ *
+ * csc
+ * [ c*cstd[ 0], c*cstd[ 1]*s*cos(h) - c*cstd[ 2]*s*sin(h), c*cstd[ 2]*s*cos(h) + c*cstd[ 1]*s*sin(h), cstd[ 3] + cstd[ 0]*(b + c*ybias) + cstd[ 1]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[ 2]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]
+ * [ c*cstd[ 4], c*cstd[ 5]*s*cos(h) - c*cstd[ 6]*s*sin(h), c*cstd[ 6]*s*cos(h) + c*cstd[ 5]*s*sin(h), cstd[ 7] + cstd[ 4]*(b + c*ybias) + cstd[ 5]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[ 6]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]
+ * [ c*cstd[ 8], c*cstd[ 9]*s*cos(h) - c*cstd[10]*s*sin(h), c*cstd[10]*s*cos(h) + c*cstd[ 9]*s*sin(h), cstd[11] + cstd[ 8]*(b + c*ybias) + cstd[ 9]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[10]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]
+ * [ c*cstd[12], c*cstd[13]*s*cos(h) - c*cstd[14]*s*sin(h), c*cstd[14]*s*cos(h) + c*cstd[13]*s*sin(h), cstd[15] + cstd[12]*(b + c*ybias) + cstd[13]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[14]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]
+ */
+
+/*
+ * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [16,235]
+ */
+static const float bt_601[16] =
+{
+   1.0f,  0.0f,    1.371f, 0.0f,
+   1.0f, -0.336f, -0.698f, 0.0f,
+   1.0f,  1.732f,  0.0f,   0.0f,
+   0.0f,  0.0f,    0.0f,   1.0f
+};
+
+/*
+ * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [0,255]
+ */
+static const float bt_601_full[16] =
+{
+   1.164f,  0.0f,    1.596f, 0.0f,
+   1.164f, -0.391f, -0.813f, 0.0f,
+   1.164f,  2.018f,  0.0f,   0.0f,
+   0.0f,    0.0f,    0.0f,   1.0f
+};
+
+/*
+ * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [16,235]
+ */
+static const float bt_709[16] =
+{
+   1.0f,  0.0f,    1.540f, 0.0f,
+   1.0f, -0.183f, -0.459f, 0.0f,
+   1.0f,  1.816f,  0.0f,   0.0f,
+   0.0f,  0.0f,    0.0f,   1.0f
+};
+
+/*
+ * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [0,255]
+ */
+static const float bt_709_full[16] =
+{
+   1.164f,  0.0f,    1.793f, 0.0f,
+   1.164f, -0.213f, -0.534f, 0.0f,
+   1.164f,  2.115f,  0.0f,   0.0f,
+   0.0f,    0.0f,    0.0f,   1.0f
+};
+
+static const float identity[16] =
+{
+   1.0f, 0.0f, 0.0f, 0.0f,
+   0.0f, 1.0f, 0.0f, 0.0f,
+   0.0f, 0.0f, 1.0f, 0.0f,
+   0.0f, 0.0f, 0.0f, 1.0f
+};
+
+void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs,
+                       struct vl_procamp *procamp,
+                       bool full_range,
+                       float *matrix)
+{
+   float ybias = full_range ? -16.0f/255.0f : 0.0f;
+   float cbbias = -128.0f/255.0f;
+   float crbias = -128.0f/255.0f;
+   float c = procamp ? procamp->contrast : 1.0f;
+   float s = procamp ? procamp->saturation : 1.0f;
+   float b = procamp ? procamp->brightness : 0.0f;
+   float h = procamp ? procamp->hue : 0.0f;
+   const float *cstd;
+
+   assert(matrix);
+
+   switch (cs) {
+      case VL_CSC_COLOR_STANDARD_BT_601:
+         cstd = full_range ? &bt_601_full[0] : &bt_601[0];
+         break;
+      case VL_CSC_COLOR_STANDARD_BT_709:
+         cstd = full_range ? &bt_709_full[0] : &bt_709[0];
+         break;
+      case VL_CSC_COLOR_STANDARD_IDENTITY:
+      default:
+         assert(cs == VL_CSC_COLOR_STANDARD_IDENTITY);
+         memcpy(matrix, &identity[0], sizeof(float) * 16);
+         return;
+   }
+
+   matrix[ 0] = c*cstd[ 0];
+   matrix[ 1] = c*cstd[ 1]*s*cosf(h) - c*cstd[ 2]*s*sinf(h);
+   matrix[ 2] = c*cstd[ 2]*s*cosf(h) + c*cstd[ 1]*s*sinf(h);
+   matrix[ 3] = cstd[ 3] + cstd[ 0]*(b + c*ybias) + cstd[ 1]*(c*cbbias*s*cosf(h) + c*crbias*s*sinf(h)) + cstd[ 2]*(c*crbias*s*cosf(h) - c*cbbias*s*sinf(h));
+
+   matrix[ 4] = c*cstd[ 4];
+   matrix[ 5] = c*cstd[ 5]*s*cosf(h) - c*cstd[ 6]*s*sinf(h);
+   matrix[ 6] = c*cstd[ 6]*s*cosf(h) + c*cstd[ 5]*s*sinf(h);
+   matrix[ 7] = cstd[ 7] + cstd[ 4]*(b + c*ybias) + cstd[ 5]*(c*cbbias*s*cosf(h) + c*crbias*s*sinf(h)) + cstd[ 6]*(c*crbias*s*cosf(h) - c*cbbias*s*sinf(h));
+
+   matrix[ 8] = c*cstd[ 8];
+   matrix[ 9] = c*cstd[ 9]*s*cosf(h) - c*cstd[10]*s*sinf(h);
+   matrix[10] = c*cstd[10]*s*cosf(h) + c*cstd[ 9]*s*sinf(h);
+   matrix[11] = cstd[11] + cstd[ 8]*(b + c*ybias) + cstd[ 9]*(c*cbbias*s*cosf(h) + c*crbias*s*sinf(h)) + cstd[10]*(c*crbias*s*cosf(h) - c*cbbias*s*sinf(h));
+
+   matrix[12] = c*cstd[12];
+   matrix[13] = c*cstd[13]*s*cos(h) - c*cstd[14]*s*sin(h);
+   matrix[14] = c*cstd[14]*s*cos(h) + c*cstd[13]*s*sin(h);
+   matrix[15] = cstd[15] + cstd[12]*(b + c*ybias) + cstd[13]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[14]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h));
+}
diff --git a/src/gallium/auxiliary/vl/vl_csc.h b/src/gallium/auxiliary/vl/vl_csc.h
new file mode 100644 (file)
index 0000000..722ca35
--- /dev/null
@@ -0,0 +1,53 @@
+/**************************************************************************
+ * 
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef vl_csc_h
+#define vl_csc_h
+
+#include <pipe/p_compiler.h>
+
+struct vl_procamp
+{
+   float brightness;
+   float contrast;
+   float saturation;
+   float hue;
+};
+
+enum VL_CSC_COLOR_STANDARD
+{
+   VL_CSC_COLOR_STANDARD_IDENTITY,
+   VL_CSC_COLOR_STANDARD_BT_601,
+   VL_CSC_COLOR_STANDARD_BT_709
+};
+
+void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs,
+                       struct vl_procamp *procamp,
+                       bool full_range,
+                       float *matrix);
+
+#endif /* vl_csc_h */
diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c
new file mode 100644 (file)
index 0000000..e9024e4
--- /dev/null
@@ -0,0 +1,1472 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vl_mpeg12_mc_renderer.h"
+#include <assert.h>
+#include <pipe/p_context.h>
+#include <util/u_inlines.h>
+#include <util/u_format.h>
+#include <util/u_math.h>
+#include <util/u_memory.h>
+#include <util/u_keymap.h>
+#include <util/u_sampler.h>
+#include <tgsi/tgsi_ureg.h>
+
+#define DEFAULT_BUF_ALIGNMENT 1
+#define MACROBLOCK_WIDTH 16
+#define MACROBLOCK_HEIGHT 16
+#define BLOCK_WIDTH 8
+#define BLOCK_HEIGHT 8
+#define ZERO_BLOCK_NIL -1.0f
+#define ZERO_BLOCK_IS_NIL(zb) ((zb).x < 0.0f)
+#define SCALE_FACTOR_16_TO_9 (32767.0f / 255.0f)
+
+struct vertex_shader_consts
+{
+   struct vertex4f denorm;
+};
+
+struct fragment_shader_consts
+{
+   struct vertex4f multiplier;
+   struct vertex4f div;
+};
+
+struct vert_stream_0
+{
+   struct vertex2f pos;
+   struct vertex2f luma_tc;
+   struct vertex2f cb_tc;
+   struct vertex2f cr_tc;
+};
+
+enum MACROBLOCK_TYPE
+{
+   MACROBLOCK_TYPE_INTRA,
+   MACROBLOCK_TYPE_FWD_FRAME_PRED,
+   MACROBLOCK_TYPE_FWD_FIELD_PRED,
+   MACROBLOCK_TYPE_BKWD_FRAME_PRED,
+   MACROBLOCK_TYPE_BKWD_FIELD_PRED,
+   MACROBLOCK_TYPE_BI_FRAME_PRED,
+   MACROBLOCK_TYPE_BI_FIELD_PRED,
+
+   NUM_MACROBLOCK_TYPES
+};
+
+static bool
+create_intra_vert_shader(struct vl_mpeg12_mc_renderer *r)
+{
+   struct ureg_program *shader;
+   struct ureg_src vpos, vtex[3];
+   struct ureg_dst o_vpos, o_vtex[3];
+   unsigned i;
+
+   shader = ureg_create(TGSI_PROCESSOR_VERTEX);
+   if (!shader)
+      return false;
+
+   vpos = ureg_DECL_vs_input(shader, 0);
+   for (i = 0; i < 3; ++i)
+      vtex[i] = ureg_DECL_vs_input(shader, i + 1);
+   o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, 0);
+   for (i = 0; i < 3; ++i)
+      o_vtex[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, i + 1);
+
+   /*
+    * o_vpos = vpos
+    * o_vtex[0..2] = vtex[0..2]
+    */
+   ureg_MOV(shader, o_vpos, vpos);
+   for (i = 0; i < 3; ++i)
+      ureg_MOV(shader, o_vtex[i], vtex[i]);
+
+   ureg_END(shader);
+
+   r->i_vs = ureg_create_shader_and_destroy(shader, r->pipe);
+   if (!r->i_vs)
+      return false;
+
+   return true;
+}
+
+static bool
+create_intra_frag_shader(struct vl_mpeg12_mc_renderer *r)
+{
+   struct ureg_program *shader;
+   struct ureg_src tc[3];
+   struct ureg_src sampler[3];
+   struct ureg_dst texel, temp;
+   struct ureg_dst fragment;
+   unsigned i;
+
+   shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+   if (!shader)
+      return false;
+
+   for (i = 0; i < 3; ++i)  {
+      tc[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, i + 1, TGSI_INTERPOLATE_LINEAR);
+      sampler[i] = ureg_DECL_sampler(shader, i);
+   }
+   texel = ureg_DECL_temporary(shader);
+   temp = ureg_DECL_temporary(shader);
+   fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
+
+   /*
+    * texel.r = tex(tc[0], sampler[0])
+    * texel.g = tex(tc[1], sampler[1])
+    * texel.b = tex(tc[2], sampler[2])
+    * fragment = texel * scale
+    */
+   for (i = 0; i < 3; ++i) {
+      /* Nouveau can't writemask tex dst regs (yet?), do in two steps */
+      ureg_TEX(shader, temp, TGSI_TEXTURE_2D, tc[i], sampler[i]);
+      ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), ureg_scalar(ureg_src(temp), TGSI_SWIZZLE_X));
+   }
+   ureg_MUL(shader, fragment, ureg_src(texel), ureg_scalar(ureg_imm1f(shader, SCALE_FACTOR_16_TO_9), TGSI_SWIZZLE_X));
+
+   ureg_release_temporary(shader, texel);
+   ureg_release_temporary(shader, temp);
+   ureg_END(shader);
+
+   r->i_fs = ureg_create_shader_and_destroy(shader, r->pipe);
+   if (!r->i_fs)
+      return false;
+
+   return true;
+}
+
+static bool
+create_frame_pred_vert_shader(struct vl_mpeg12_mc_renderer *r)
+{
+   struct ureg_program *shader;
+   struct ureg_src vpos, vtex[4];
+   struct ureg_dst o_vpos, o_vtex[4];
+   unsigned i;
+
+   shader = ureg_create(TGSI_PROCESSOR_VERTEX);
+   if (!shader)
+      return false;
+
+   vpos = ureg_DECL_vs_input(shader, 0);
+   for (i = 0; i < 4; ++i)
+      vtex[i] = ureg_DECL_vs_input(shader, i + 1);
+   o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, 0);
+   for (i = 0; i < 4; ++i)
+      o_vtex[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, i + 1);
+
+   /*
+    * o_vpos = vpos
+    * o_vtex[0..2] = vtex[0..2]
+    * o_vtex[3] = vpos + vtex[3] // Apply motion vector
+    */
+   ureg_MOV(shader, o_vpos, vpos);
+   for (i = 0; i < 3; ++i)
+      ureg_MOV(shader, o_vtex[i], vtex[i]);
+   ureg_ADD(shader, o_vtex[3], vpos, vtex[3]);
+
+   ureg_END(shader);
+
+   r->p_vs[0] = ureg_create_shader_and_destroy(shader, r->pipe);
+   if (!r->p_vs[0])
+      return false;
+
+   return true;
+}
+
+#if 0
+static void
+create_field_pred_vert_shader(struct vl_mpeg12_mc_renderer *r)
+{
+   assert(false);
+}
+#endif
+
+static bool
+create_frame_pred_frag_shader(struct vl_mpeg12_mc_renderer *r)
+{
+   struct ureg_program *shader;
+   struct ureg_src tc[4];
+   struct ureg_src sampler[4];
+   struct ureg_dst texel, ref;
+   struct ureg_dst fragment;
+   unsigned i;
+
+   shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+   if (!shader)
+      return false;
+
+   for (i = 0; i < 4; ++i)  {
+      tc[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, i + 1, TGSI_INTERPOLATE_LINEAR);
+      sampler[i] = ureg_DECL_sampler(shader, i);
+   }
+   texel = ureg_DECL_temporary(shader);
+   ref = ureg_DECL_temporary(shader);
+   fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
+
+   /*
+    * texel.r = tex(tc[0], sampler[0])
+    * texel.g = tex(tc[1], sampler[1])
+    * texel.b = tex(tc[2], sampler[2])
+    * ref = tex(tc[3], sampler[3])
+    * fragment = texel * scale + ref
+    */
+   for (i = 0; i < 3; ++i) {
+      /* Nouveau can't writemask tex dst regs (yet?), do in two steps */
+      ureg_TEX(shader, ref, TGSI_TEXTURE_2D, tc[i], sampler[i]);
+      ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), ureg_scalar(ureg_src(ref), TGSI_SWIZZLE_X));
+   }
+   ureg_TEX(shader, ref, TGSI_TEXTURE_2D, tc[3], sampler[3]);
+   ureg_MAD(shader, fragment, ureg_src(texel), ureg_scalar(ureg_imm1f(shader, SCALE_FACTOR_16_TO_9), TGSI_SWIZZLE_X), ureg_src(ref));
+
+   ureg_release_temporary(shader, texel);
+   ureg_release_temporary(shader, ref);
+   ureg_END(shader);
+
+   r->p_fs[0] = ureg_create_shader_and_destroy(shader, r->pipe);
+   if (!r->p_fs[0])
+      return false;
+
+   return true;
+}
+
+#if 0
+static void
+create_field_pred_frag_shader(struct vl_mpeg12_mc_renderer *r)
+{
+   assert(false);
+}
+#endif
+
+static bool
+create_frame_bi_pred_vert_shader(struct vl_mpeg12_mc_renderer *r)
+{
+   struct ureg_program *shader;
+   struct ureg_src vpos, vtex[5];
+   struct ureg_dst o_vpos, o_vtex[5];
+   unsigned i;
+
+   shader = ureg_create(TGSI_PROCESSOR_VERTEX);
+   if (!shader)
+      return false;
+
+   vpos = ureg_DECL_vs_input(shader, 0);
+   for (i = 0; i < 4; ++i)
+      vtex[i] = ureg_DECL_vs_input(shader, i + 1);
+   /* Skip input 5 */
+   vtex[4] = ureg_DECL_vs_input(shader, 6);
+   o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, 0);
+   for (i = 0; i < 5; ++i)
+      o_vtex[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, i + 1);
+
+   /*
+    * o_vpos = vpos
+    * o_vtex[0..2] = vtex[0..2]
+    * o_vtex[3..4] = vpos + vtex[3..4] // Apply motion vector
+    */
+   ureg_MOV(shader, o_vpos, vpos);
+   for (i = 0; i < 3; ++i)
+      ureg_MOV(shader, o_vtex[i], vtex[i]);
+   for (i = 3; i < 5; ++i)
+      ureg_ADD(shader, o_vtex[i], vpos, vtex[i]);
+
+   ureg_END(shader);
+
+   r->b_vs[0] = ureg_create_shader_and_destroy(shader, r->pipe);
+   if (!r->b_vs[0])
+      return false;
+
+   return true;
+}
+
+#if 0
+static void
+create_field_bi_pred_vert_shader(struct vl_mpeg12_mc_renderer *r)
+{
+   assert(false);
+}
+#endif
+
+static bool
+create_frame_bi_pred_frag_shader(struct vl_mpeg12_mc_renderer *r)
+{
+   struct ureg_program *shader;
+   struct ureg_src tc[5];
+   struct ureg_src sampler[5];
+   struct ureg_dst texel, ref[2];
+   struct ureg_dst fragment;
+   unsigned i;
+
+   shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+   if (!shader)
+      return false;
+
+   for (i = 0; i < 5; ++i)  {
+      tc[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, i + 1, TGSI_INTERPOLATE_LINEAR);
+      sampler[i] = ureg_DECL_sampler(shader, i);
+   }
+   texel = ureg_DECL_temporary(shader);
+   ref[0] = ureg_DECL_temporary(shader);
+   ref[1] = ureg_DECL_temporary(shader);
+   fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
+
+   /*
+    * texel.r = tex(tc[0], sampler[0])
+    * texel.g = tex(tc[1], sampler[1])
+    * texel.b = tex(tc[2], sampler[2])
+    * ref[0..1 = tex(tc[3..4], sampler[3..4])
+    * ref[0] = lerp(ref[0], ref[1], 0.5)
+    * fragment = texel * scale + ref[0]
+    */
+   for (i = 0; i < 3; ++i) {
+      /* Nouveau can't writemask tex dst regs (yet?), do in two steps */
+      ureg_TEX(shader, ref[0], TGSI_TEXTURE_2D, tc[i], sampler[i]);
+      ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), ureg_scalar(ureg_src(ref[0]), TGSI_SWIZZLE_X));
+   }
+   ureg_TEX(shader, ref[0], TGSI_TEXTURE_2D, tc[3], sampler[3]);
+   ureg_TEX(shader, ref[1], TGSI_TEXTURE_2D, tc[4], sampler[4]);
+   ureg_LRP(shader, ref[0], ureg_scalar(ureg_imm1f(shader, 0.5f), TGSI_SWIZZLE_X), ureg_src(ref[0]), ureg_src(ref[1]));
+
+   ureg_MAD(shader, fragment, ureg_src(texel), ureg_scalar(ureg_imm1f(shader, SCALE_FACTOR_16_TO_9), TGSI_SWIZZLE_X), ureg_src(ref[0]));
+
+   ureg_release_temporary(shader, texel);
+   ureg_release_temporary(shader, ref[0]);
+   ureg_release_temporary(shader, ref[1]);
+   ureg_END(shader);
+
+   r->b_fs[0] = ureg_create_shader_and_destroy(shader, r->pipe);
+   if (!r->b_fs[0])
+      return false;
+
+   return true;
+}
+
+#if 0
+static void
+create_field_bi_pred_frag_shader(struct vl_mpeg12_mc_renderer *r)
+{
+   assert(false);
+}
+#endif
+
+static void
+xfer_buffers_map(struct vl_mpeg12_mc_renderer *r)
+{
+   unsigned i;
+
+   assert(r);
+
+   for (i = 0; i < 3; ++i) {
+      struct pipe_box rect =
+      {
+         0, 0, 0,
+         r->textures.all[i]->width0,
+         r->textures.all[i]->height0,
+         1
+      };
+
+      r->tex_transfer[i] = r->pipe->get_transfer
+      (
+         r->pipe, r->textures.all[i],
+         u_subresource(0, 0),
+         PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
+         &rect
+      );
+
+      r->texels[i] = r->pipe->transfer_map(r->pipe, r->tex_transfer[i]);
+   }
+}
+
+static void
+xfer_buffers_unmap(struct vl_mpeg12_mc_renderer *r)
+{
+   unsigned i;
+
+   assert(r);
+
+   for (i = 0; i < 3; ++i) {
+      r->pipe->transfer_unmap(r->pipe, r->tex_transfer[i]);
+      r->pipe->transfer_destroy(r->pipe, r->tex_transfer[i]);
+   }
+}
+
+static bool
+init_pipe_state(struct vl_mpeg12_mc_renderer *r)
+{
+   struct pipe_sampler_state sampler;
+   unsigned filters[5];
+   unsigned i;
+
+   assert(r);
+
+   r->viewport.scale[0] = r->pot_buffers ?
+      util_next_power_of_two(r->picture_width) : r->picture_width;
+   r->viewport.scale[1] = r->pot_buffers ?
+      util_next_power_of_two(r->picture_height) : r->picture_height;
+   r->viewport.scale[2] = 1;
+   r->viewport.scale[3] = 1;
+   r->viewport.translate[0] = 0;
+   r->viewport.translate[1] = 0;
+   r->viewport.translate[2] = 0;
+   r->viewport.translate[3] = 0;
+
+   r->fb_state.width = r->pot_buffers ?
+      util_next_power_of_two(r->picture_width) : r->picture_width;
+   r->fb_state.height = r->pot_buffers ?
+      util_next_power_of_two(r->picture_height) : r->picture_height;
+   r->fb_state.nr_cbufs = 1;
+   r->fb_state.zsbuf = NULL;
+
+   /* Luma filter */
+   filters[0] = PIPE_TEX_FILTER_NEAREST;
+   /* Chroma filters */
+   if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_444 ||
+       r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE) {
+      filters[1] = PIPE_TEX_FILTER_NEAREST;
+      filters[2] = PIPE_TEX_FILTER_NEAREST;
+   }
+   else {
+      filters[1] = PIPE_TEX_FILTER_LINEAR;
+      filters[2] = PIPE_TEX_FILTER_LINEAR;
+   }
+   /* Fwd, bkwd ref filters */
+   filters[3] = PIPE_TEX_FILTER_LINEAR;
+   filters[4] = PIPE_TEX_FILTER_LINEAR;
+
+   for (i = 0; i < 5; ++i) {
+      sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+      sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+      sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+      sampler.min_img_filter = filters[i];
+      sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+      sampler.mag_img_filter = filters[i];
+      sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
+      sampler.compare_func = PIPE_FUNC_ALWAYS;
+      sampler.normalized_coords = 1;
+      /*sampler.shadow_ambient = ; */
+      /*sampler.lod_bias = ; */
+      sampler.min_lod = 0;
+      /*sampler.max_lod = ; */
+      /*sampler.border_color[i] = ; */
+      /*sampler.max_anisotropy = ; */
+      r->samplers.all[i] = r->pipe->create_sampler_state(r->pipe, &sampler);
+   }
+
+   return true;
+}
+
+static void
+cleanup_pipe_state(struct vl_mpeg12_mc_renderer *r)
+{
+   unsigned i;
+
+   assert(r);
+
+   for (i = 0; i < 5; ++i)
+      r->pipe->delete_sampler_state(r->pipe, r->samplers.all[i]);
+}
+
+static bool
+init_shaders(struct vl_mpeg12_mc_renderer *r)
+{
+   assert(r);
+
+   create_intra_vert_shader(r);
+   create_intra_frag_shader(r);
+   create_frame_pred_vert_shader(r);
+   create_frame_pred_frag_shader(r);
+   create_frame_bi_pred_vert_shader(r);
+   create_frame_bi_pred_frag_shader(r);
+
+   return true;
+}
+
+static void
+cleanup_shaders(struct vl_mpeg12_mc_renderer *r)
+{
+   assert(r);
+
+   r->pipe->delete_vs_state(r->pipe, r->i_vs);
+   r->pipe->delete_fs_state(r->pipe, r->i_fs);
+   r->pipe->delete_vs_state(r->pipe, r->p_vs[0]);
+   r->pipe->delete_fs_state(r->pipe, r->p_fs[0]);
+   r->pipe->delete_vs_state(r->pipe, r->b_vs[0]);
+   r->pipe->delete_fs_state(r->pipe, r->b_fs[0]);
+}
+
+static bool
+init_buffers(struct vl_mpeg12_mc_renderer *r)
+{
+   struct pipe_resource template;
+   struct pipe_vertex_element vertex_elems[8];
+   struct pipe_sampler_view sampler_view;
+
+   const unsigned mbw =
+      align(r->picture_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH;
+   const unsigned mbh =
+      align(r->picture_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT;
+
+   unsigned i;
+
+   assert(r);
+
+   r->macroblocks_per_batch =
+      mbw * (r->bufmode == VL_MPEG12_MC_RENDERER_BUFFER_PICTURE ? mbh : 1);
+   r->num_macroblocks = 0;
+   r->macroblock_buf = MALLOC(r->macroblocks_per_batch * sizeof(struct pipe_mpeg12_macroblock));
+
+   memset(&template, 0, sizeof(struct pipe_resource));
+   template.target = PIPE_TEXTURE_2D;
+   /* TODO: Accomodate HW that can't do this and also for cases when this isn't precise enough */
+   template.format = PIPE_FORMAT_R16_SNORM;
+   template.last_level = 0;
+   template.width0 = r->pot_buffers ?
+      util_next_power_of_two(r->picture_width) : r->picture_width;
+   template.height0 = r->pot_buffers ?
+      util_next_power_of_two(r->picture_height) : r->picture_height;
+   template.depth0 = 1;
+   template.usage = PIPE_USAGE_DYNAMIC;
+   template.bind = PIPE_BIND_SAMPLER_VIEW;
+   template.flags = 0;
+
+   r->textures.individual.y = r->pipe->screen->resource_create(r->pipe->screen, &template);
+
+   if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) {
+      template.width0 = r->pot_buffers ?
+         util_next_power_of_two(r->picture_width / 2) :
+         r->picture_width / 2;
+      template.height0 = r->pot_buffers ?
+         util_next_power_of_two(r->picture_height / 2) :
+         r->picture_height / 2;
+   }
+   else if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422)
+      template.height0 = r->pot_buffers ?
+         util_next_power_of_two(r->picture_height / 2) :
+         r->picture_height / 2;
+
+   r->textures.individual.cb =
+      r->pipe->screen->resource_create(r->pipe->screen, &template);
+   r->textures.individual.cr =
+      r->pipe->screen->resource_create(r->pipe->screen, &template);
+
+   for (i = 0; i < 3; ++i) {
+      u_sampler_view_default_template(&sampler_view,
+                                      r->textures.all[i],
+                                      r->textures.all[i]->format);
+      r->sampler_views.all[i] = r->pipe->create_sampler_view(r->pipe, r->textures.all[i], &sampler_view);
+   }
+
+   r->vertex_bufs.individual.ycbcr.stride = sizeof(struct vertex2f) * 4;
+   r->vertex_bufs.individual.ycbcr.max_index = 24 * r->macroblocks_per_batch - 1;
+   r->vertex_bufs.individual.ycbcr.buffer_offset = 0;
+   /* XXX: Create with usage DYNAMIC or STREAM */
+   r->vertex_bufs.individual.ycbcr.buffer = pipe_buffer_create
+   (
+      r->pipe->screen,
+      PIPE_BIND_VERTEX_BUFFER,
+      sizeof(struct vertex2f) * 4 * 24 * r->macroblocks_per_batch
+   );
+
+   for (i = 1; i < 3; ++i) {
+      r->vertex_bufs.all[i].stride = sizeof(struct vertex2f) * 2;
+      r->vertex_bufs.all[i].max_index = 24 * r->macroblocks_per_batch - 1;
+      r->vertex_bufs.all[i].buffer_offset = 0;
+      /* XXX: Create with usage DYNAMIC or STREAM */
+      r->vertex_bufs.all[i].buffer = pipe_buffer_create
+      (
+         r->pipe->screen,
+         PIPE_BIND_VERTEX_BUFFER,
+         sizeof(struct vertex2f) * 2 * 24 * r->macroblocks_per_batch
+      );
+   }
+
+   /* Position element */
+   vertex_elems[0].src_offset = 0;
+   vertex_elems[0].instance_divisor = 0;
+   vertex_elems[0].vertex_buffer_index = 0;
+   vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+   /* Luma, texcoord element */
+   vertex_elems[1].src_offset = sizeof(struct vertex2f);
+   vertex_elems[1].instance_divisor = 0;
+   vertex_elems[1].vertex_buffer_index = 0;
+   vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+   /* Chroma Cr texcoord element */
+   vertex_elems[2].src_offset = sizeof(struct vertex2f) * 2;
+   vertex_elems[2].instance_divisor = 0;
+   vertex_elems[2].vertex_buffer_index = 0;
+   vertex_elems[2].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+   /* Chroma Cb texcoord element */
+   vertex_elems[3].src_offset = sizeof(struct vertex2f) * 3;
+   vertex_elems[3].instance_divisor = 0;
+   vertex_elems[3].vertex_buffer_index = 0;
+   vertex_elems[3].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+   /* First ref surface top field texcoord element */
+   vertex_elems[4].src_offset = 0;
+   vertex_elems[4].instance_divisor = 0;
+   vertex_elems[4].vertex_buffer_index = 1;
+   vertex_elems[4].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+   /* First ref surface bottom field texcoord element */
+   vertex_elems[5].src_offset = sizeof(struct vertex2f);
+   vertex_elems[5].instance_divisor = 0;
+   vertex_elems[5].vertex_buffer_index = 1;
+   vertex_elems[5].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+   /* Second ref surface top field texcoord element */
+   vertex_elems[6].src_offset = 0;
+   vertex_elems[6].instance_divisor = 0;
+   vertex_elems[6].vertex_buffer_index = 2;
+   vertex_elems[6].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+   /* Second ref surface bottom field texcoord element */
+   vertex_elems[7].src_offset = sizeof(struct vertex2f);
+   vertex_elems[7].instance_divisor = 0;
+   vertex_elems[7].vertex_buffer_index = 2;
+   vertex_elems[7].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+   r->vertex_elems_state.individual.i = r->pipe->create_vertex_elements_state(r->pipe, 4, vertex_elems);
+   r->vertex_elems_state.individual.p = r->pipe->create_vertex_elements_state(r->pipe, 6, vertex_elems);
+   r->vertex_elems_state.individual.b = r->pipe->create_vertex_elements_state(r->pipe, 8, vertex_elems);
+
+   r->vs_const_buf = pipe_buffer_create
+   (
+      r->pipe->screen,
+      PIPE_BIND_CONSTANT_BUFFER,
+      sizeof(struct vertex_shader_consts)
+   );
+
+   return true;
+}
+
+static void
+cleanup_buffers(struct vl_mpeg12_mc_renderer *r)
+{
+   unsigned i;
+
+   assert(r);
+
+   pipe_resource_reference(&r->vs_const_buf, NULL);
+
+   for (i = 0; i < 3; ++i) {
+      pipe_sampler_view_reference(&r->sampler_views.all[i], NULL);
+      r->pipe->delete_vertex_elements_state(r->pipe, r->vertex_elems_state.all[i]);
+      pipe_resource_reference(&r->vertex_bufs.all[i].buffer, NULL);
+      pipe_resource_reference(&r->textures.all[i], NULL);
+   }
+
+   FREE(r->macroblock_buf);
+}
+
+static enum MACROBLOCK_TYPE
+get_macroblock_type(struct pipe_mpeg12_macroblock *mb)
+{
+   assert(mb);
+
+   switch (mb->mb_type) {
+      case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA:
+         return MACROBLOCK_TYPE_INTRA;
+      case PIPE_MPEG12_MACROBLOCK_TYPE_FWD:
+         return mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME ?
+            MACROBLOCK_TYPE_FWD_FRAME_PRED : MACROBLOCK_TYPE_FWD_FIELD_PRED;
+      case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD:
+         return mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME ?
+            MACROBLOCK_TYPE_BKWD_FRAME_PRED : MACROBLOCK_TYPE_BKWD_FIELD_PRED;
+      case PIPE_MPEG12_MACROBLOCK_TYPE_BI:
+         return mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME ?
+            MACROBLOCK_TYPE_BI_FRAME_PRED : MACROBLOCK_TYPE_BI_FIELD_PRED;
+      default:
+         assert(0);
+   }
+
+   /* Unreachable */
+   return -1;
+}
+
+static void
+gen_block_verts(struct vert_stream_0 *vb, unsigned cbp, unsigned mbx, unsigned mby,
+                const struct vertex2f *unit, const struct vertex2f *half, const struct vertex2f *offset,
+                unsigned luma_mask, unsigned cb_mask, unsigned cr_mask,
+                bool use_zeroblocks, struct vertex2f *zero_blocks)
+{
+   struct vertex2f v;
+
+   assert(vb);
+   assert(unit && half && offset);
+   assert(zero_blocks || !use_zeroblocks);
+
+   /* Generate vertices for two triangles covering a block */
+   v.x = mbx * unit->x + offset->x;
+   v.y = mby * unit->y + offset->y;
+
+   vb[0].pos.x = v.x;
+   vb[0].pos.y = v.y;
+   vb[1].pos.x = v.x;
+   vb[1].pos.y = v.y + half->y;
+   vb[2].pos.x = v.x + half->x;
+   vb[2].pos.y = v.y;
+   vb[3].pos.x = v.x + half->x;
+   vb[3].pos.y = v.y;
+   vb[4].pos.x = v.x;
+   vb[4].pos.y = v.y + half->y;
+   vb[5].pos.x = v.x + half->x;
+   vb[5].pos.y = v.y + half->y;
+
+   /* Generate texcoords for the triangles, either pointing to the correct area on the luma/chroma texture
+      or if zero blocks are being used, to the zero block if the appropriate CBP bits aren't set (i.e. no data
+      for this channel is defined for this block) */
+
+   if (!use_zeroblocks || cbp & luma_mask) {
+      v.x = mbx * unit->x + offset->x;
+      v.y = mby * unit->y + offset->y;
+   }
+   else {
+      v.x = zero_blocks[0].x;
+      v.y = zero_blocks[0].y;
+   }
+
+   vb[0].luma_tc.x = v.x;
+   vb[0].luma_tc.y = v.y;
+   vb[1].luma_tc.x = v.x;
+   vb[1].luma_tc.y = v.y + half->y;
+   vb[2].luma_tc.x = v.x + half->x;
+   vb[2].luma_tc.y = v.y;
+   vb[3].luma_tc.x = v.x + half->x;
+   vb[3].luma_tc.y = v.y;
+   vb[4].luma_tc.x = v.x;
+   vb[4].luma_tc.y = v.y + half->y;
+   vb[5].luma_tc.x = v.x + half->x;
+   vb[5].luma_tc.y = v.y + half->y;
+
+   if (!use_zeroblocks || cbp & cb_mask) {
+      v.x = mbx * unit->x + offset->x;
+      v.y = mby * unit->y + offset->y;
+   }
+   else {
+      v.x = zero_blocks[1].x;
+      v.y = zero_blocks[1].y;
+   }
+
+   vb[0].cb_tc.x = v.x;
+   vb[0].cb_tc.y = v.y;
+   vb[1].cb_tc.x = v.x;
+   vb[1].cb_tc.y = v.y + half->y;
+   vb[2].cb_tc.x = v.x + half->x;
+   vb[2].cb_tc.y = v.y;
+   vb[3].cb_tc.x = v.x + half->x;
+   vb[3].cb_tc.y = v.y;
+   vb[4].cb_tc.x = v.x;
+   vb[4].cb_tc.y = v.y + half->y;
+   vb[5].cb_tc.x = v.x + half->x;
+   vb[5].cb_tc.y = v.y + half->y;
+
+   if (!use_zeroblocks || cbp & cr_mask) {
+      v.x = mbx * unit->x + offset->x;
+      v.y = mby * unit->y + offset->y;
+   }
+   else {
+      v.x = zero_blocks[2].x;
+      v.y = zero_blocks[2].y;
+   }
+
+   vb[0].cr_tc.x = v.x;
+   vb[0].cr_tc.y = v.y;
+   vb[1].cr_tc.x = v.x;
+   vb[1].cr_tc.y = v.y + half->y;
+   vb[2].cr_tc.x = v.x + half->x;
+   vb[2].cr_tc.y = v.y;
+   vb[3].cr_tc.x = v.x + half->x;
+   vb[3].cr_tc.y = v.y;
+   vb[4].cr_tc.x = v.x;
+   vb[4].cr_tc.y = v.y + half->y;
+   vb[5].cr_tc.x = v.x + half->x;
+   vb[5].cr_tc.y = v.y + half->y;
+}
+
+static void
+gen_macroblock_verts(struct vl_mpeg12_mc_renderer *r,
+                     struct pipe_mpeg12_macroblock *mb, unsigned pos,
+                     struct vert_stream_0 *ycbcr_vb, struct vertex2f **ref_vb)
+{
+   struct vertex2f mo_vec[2];
+
+   unsigned i;
+
+   assert(r);
+   assert(mb);
+   assert(ycbcr_vb);
+   assert(pos < r->macroblocks_per_batch);
+
+   mo_vec[1].x = 0;
+   mo_vec[1].y = 0;
+
+   switch (mb->mb_type) {
+      case PIPE_MPEG12_MACROBLOCK_TYPE_BI:
+      {
+         struct vertex2f *vb;
+
+         assert(ref_vb && ref_vb[1]);
+
+         vb = ref_vb[1] + pos * 2 * 24;
+
+         mo_vec[0].x = mb->pmv[0][1][0] * 0.5f * r->surface_tex_inv_size.x;
+         mo_vec[0].y = mb->pmv[0][1][1] * 0.5f * r->surface_tex_inv_size.y;
+
+         if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) {
+            for (i = 0; i < 24 * 2; i += 2) {
+               vb[i].x = mo_vec[0].x;
+               vb[i].y = mo_vec[0].y;
+            }
+         }
+         else {
+            mo_vec[1].x = mb->pmv[1][1][0] * 0.5f * r->surface_tex_inv_size.x;
+            mo_vec[1].y = mb->pmv[1][1][1] * 0.5f * r->surface_tex_inv_size.y;
+
+            for (i = 0; i < 24 * 2; i += 2) {
+               vb[i].x = mo_vec[0].x;
+               vb[i].y = mo_vec[0].y;
+               vb[i + 1].x = mo_vec[1].x;
+               vb[i + 1].y = mo_vec[1].y;
+            }
+         }
+
+         /* fall-through */
+      }
+      case PIPE_MPEG12_MACROBLOCK_TYPE_FWD:
+      case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD:
+      {
+         struct vertex2f *vb;
+
+         assert(ref_vb && ref_vb[0]);
+
+         vb = ref_vb[0] + pos * 2 * 24;
+
+         if (mb->mb_type == PIPE_MPEG12_MACROBLOCK_TYPE_BKWD) {
+             mo_vec[0].x = mb->pmv[0][1][0] * 0.5f * r->surface_tex_inv_size.x;
+             mo_vec[0].y = mb->pmv[0][1][1] * 0.5f * r->surface_tex_inv_size.y;
+
+             if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FIELD) {
+                mo_vec[1].x = mb->pmv[1][1][0] * 0.5f * r->surface_tex_inv_size.x;
+                mo_vec[1].y = mb->pmv[1][1][1] * 0.5f * r->surface_tex_inv_size.y;
+             }
+         }
+         else {
+            mo_vec[0].x = mb->pmv[0][0][0] * 0.5f * r->surface_tex_inv_size.x;
+            mo_vec[0].y = mb->pmv[0][0][1] * 0.5f * r->surface_tex_inv_size.y;
+
+            if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FIELD) {
+               mo_vec[1].x = mb->pmv[1][0][0] * 0.5f * r->surface_tex_inv_size.x;
+               mo_vec[1].y = mb->pmv[1][0][1] * 0.5f * r->surface_tex_inv_size.y;
+            }
+         }
+
+         if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) {
+            for (i = 0; i < 24 * 2; i += 2) {
+               vb[i].x = mo_vec[0].x;
+               vb[i].y = mo_vec[0].y;
+            }
+         }
+         else {
+            for (i = 0; i < 24 * 2; i += 2) {
+               vb[i].x = mo_vec[0].x;
+               vb[i].y = mo_vec[0].y;
+               vb[i + 1].x = mo_vec[1].x;
+               vb[i + 1].y = mo_vec[1].y;
+            }
+         }
+
+         /* fall-through */
+      }
+      case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA:
+      {
+         const struct vertex2f unit =
+         {
+            r->surface_tex_inv_size.x * MACROBLOCK_WIDTH,
+            r->surface_tex_inv_size.y * MACROBLOCK_HEIGHT
+         };
+         const struct vertex2f half =
+         {
+            r->surface_tex_inv_size.x * (MACROBLOCK_WIDTH / 2),
+            r->surface_tex_inv_size.y * (MACROBLOCK_HEIGHT / 2)
+         };
+         const struct vertex2f offsets[2][2] =
+         {
+            {
+               {0, 0}, {0, half.y}
+            },
+            {
+               {half.x, 0}, {half.x, half.y}
+            }
+         };
+         const bool use_zb = r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE;
+
+         struct vert_stream_0 *vb = ycbcr_vb + pos * 24;
+
+         gen_block_verts(vb, mb->cbp, mb->mbx, mb->mby,
+                         &unit, &half, &offsets[0][0],
+                         32, 2, 1, use_zb, r->zero_block);
+
+         gen_block_verts(vb + 6, mb->cbp, mb->mbx, mb->mby,
+                         &unit, &half, &offsets[1][0],
+                         16, 2, 1, use_zb, r->zero_block);
+
+         gen_block_verts(vb + 12, mb->cbp, mb->mbx, mb->mby,
+                         &unit, &half, &offsets[0][1],
+                         8, 2, 1, use_zb, r->zero_block);
+
+         gen_block_verts(vb + 18, mb->cbp, mb->mbx, mb->mby,
+                         &unit, &half, &offsets[1][1],
+                         4, 2, 1, use_zb, r->zero_block);
+
+         break;
+      }
+      default:
+         assert(0);
+   }
+}
+
+static void
+gen_macroblock_stream(struct vl_mpeg12_mc_renderer *r,
+                      unsigned *num_macroblocks)
+{
+   unsigned offset[NUM_MACROBLOCK_TYPES];
+   struct vert_stream_0 *ycbcr_vb;
+   struct vertex2f *ref_vb[2];
+   struct pipe_transfer *buf_transfer[3];
+   unsigned i;
+
+   assert(r);
+   assert(num_macroblocks);
+
+   for (i = 0; i < r->num_macroblocks; ++i) {
+      enum MACROBLOCK_TYPE mb_type = get_macroblock_type(&r->macroblock_buf[i]);
+      ++num_macroblocks[mb_type];
+   }
+
+   offset[0] = 0;
+
+   for (i = 1; i < NUM_MACROBLOCK_TYPES; ++i)
+      offset[i] = offset[i - 1] + num_macroblocks[i - 1];
+
+   ycbcr_vb = (struct vert_stream_0 *)pipe_buffer_map
+   (
+      r->pipe,
+      r->vertex_bufs.individual.ycbcr.buffer,
+      PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
+      &buf_transfer[0]
+   );
+
+   for (i = 0; i < 2; ++i)
+      ref_vb[i] = (struct vertex2f *)pipe_buffer_map
+      (
+         r->pipe,
+         r->vertex_bufs.individual.ref[i].buffer,
+         PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
+         &buf_transfer[i + 1]
+      );
+
+   for (i = 0; i < r->num_macroblocks; ++i) {
+      enum MACROBLOCK_TYPE mb_type = get_macroblock_type(&r->macroblock_buf[i]);
+
+      gen_macroblock_verts(r, &r->macroblock_buf[i], offset[mb_type],
+                           ycbcr_vb, ref_vb);
+
+      ++offset[mb_type];
+   }
+
+   pipe_buffer_unmap(r->pipe, r->vertex_bufs.individual.ycbcr.buffer, buf_transfer[0]);
+   for (i = 0; i < 2; ++i)
+      pipe_buffer_unmap(r->pipe, r->vertex_bufs.individual.ref[i].buffer, buf_transfer[i + 1]);
+}
+
+static struct pipe_sampler_view
+*find_or_create_sampler_view(struct vl_mpeg12_mc_renderer *r, struct pipe_surface *surface)
+{
+   struct pipe_sampler_view *sampler_view;
+   assert(r);
+   assert(surface);
+
+   sampler_view = (struct pipe_sampler_view*)util_keymap_lookup(r->texview_map, &surface);
+   if (!sampler_view) {
+      struct pipe_sampler_view templat;
+      boolean added_to_map;
+
+      u_sampler_view_default_template(&templat, surface->texture,
+                                      surface->texture->format);
+      sampler_view = r->pipe->create_sampler_view(r->pipe, surface->texture,
+                                                  &templat);
+      if (!sampler_view)
+         return NULL;
+
+      added_to_map = util_keymap_insert(r->texview_map, &surface,
+                                        sampler_view, r->pipe);
+      assert(added_to_map);
+   }
+
+   return sampler_view;
+}
+
+static void
+flush(struct vl_mpeg12_mc_renderer *r)
+{
+   unsigned num_macroblocks[NUM_MACROBLOCK_TYPES] = { 0 };
+   unsigned vb_start = 0;
+   struct vertex_shader_consts *vs_consts;
+   struct pipe_transfer *buf_transfer;
+   unsigned i;
+
+   assert(r);
+   assert(r->num_macroblocks == r->macroblocks_per_batch);
+
+   gen_macroblock_stream(r, num_macroblocks);
+
+   r->fb_state.cbufs[0] = r->surface;
+
+   r->pipe->set_framebuffer_state(r->pipe, &r->fb_state);
+   r->pipe->set_viewport_state(r->pipe, &r->viewport);
+
+   vs_consts = pipe_buffer_map
+   (
+      r->pipe, r->vs_const_buf,
+      PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
+      &buf_transfer
+   );
+
+   vs_consts->denorm.x = r->surface->width;
+   vs_consts->denorm.y = r->surface->height;
+
+   pipe_buffer_unmap(r->pipe, r->vs_const_buf, buf_transfer);
+
+   r->pipe->set_constant_buffer(r->pipe, PIPE_SHADER_VERTEX, 0,
+                                r->vs_const_buf);
+
+   if (num_macroblocks[MACROBLOCK_TYPE_INTRA] > 0) {
+      r->pipe->set_vertex_buffers(r->pipe, 1, r->vertex_bufs.all);
+      r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.i);
+      r->pipe->set_fragment_sampler_views(r->pipe, 3, r->sampler_views.all);
+      r->pipe->bind_fragment_sampler_states(r->pipe, 3, r->samplers.all);
+      r->pipe->bind_vs_state(r->pipe, r->i_vs);
+      r->pipe->bind_fs_state(r->pipe, r->i_fs);
+
+      r->pipe->draw_arrays(r->pipe, PIPE_PRIM_TRIANGLES, vb_start,
+                           num_macroblocks[MACROBLOCK_TYPE_INTRA] * 24);
+      vb_start += num_macroblocks[MACROBLOCK_TYPE_INTRA] * 24;
+   }
+
+   if (num_macroblocks[MACROBLOCK_TYPE_FWD_FRAME_PRED] > 0) {
+      r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all);
+      r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.p);
+      r->textures.individual.ref[0] = r->past->texture;
+      r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->past);
+      r->pipe->set_fragment_sampler_views(r->pipe, 4, r->sampler_views.all);
+      r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all);
+      r->pipe->bind_vs_state(r->pipe, r->p_vs[0]);
+      r->pipe->bind_fs_state(r->pipe, r->p_fs[0]);
+
+      r->pipe->draw_arrays(r->pipe, PIPE_PRIM_TRIANGLES, vb_start,
+                           num_macroblocks[MACROBLOCK_TYPE_FWD_FRAME_PRED] * 24);
+      vb_start += num_macroblocks[MACROBLOCK_TYPE_FWD_FRAME_PRED] * 24;
+   }
+
+   if (false /*num_macroblocks[MACROBLOCK_TYPE_FWD_FIELD_PRED] > 0 */ ) {
+      r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all);
+      r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.p);
+      r->textures.individual.ref[0] = r->past->texture;
+      r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->past);
+      r->pipe->set_fragment_sampler_views(r->pipe, 4, r->sampler_views.all);
+      r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all);
+      r->pipe->bind_vs_state(r->pipe, r->p_vs[1]);
+      r->pipe->bind_fs_state(r->pipe, r->p_fs[1]);
+
+      r->pipe->draw_arrays(r->pipe, PIPE_PRIM_TRIANGLES, vb_start,
+                           num_macroblocks[MACROBLOCK_TYPE_FWD_FIELD_PRED] * 24);
+      vb_start += num_macroblocks[MACROBLOCK_TYPE_FWD_FIELD_PRED] * 24;
+   }
+
+   if (num_macroblocks[MACROBLOCK_TYPE_BKWD_FRAME_PRED] > 0) {
+      r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all);
+      r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.p);
+      r->textures.individual.ref[0] = r->future->texture;
+      r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->future);
+      r->pipe->set_fragment_sampler_views(r->pipe, 4, r->sampler_views.all);
+      r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all);
+      r->pipe->bind_vs_state(r->pipe, r->p_vs[0]);
+      r->pipe->bind_fs_state(r->pipe, r->p_fs[0]);
+
+      r->pipe->draw_arrays(r->pipe, PIPE_PRIM_TRIANGLES, vb_start,
+                           num_macroblocks[MACROBLOCK_TYPE_BKWD_FRAME_PRED] * 24);
+      vb_start += num_macroblocks[MACROBLOCK_TYPE_BKWD_FRAME_PRED] * 24;
+   }
+
+   if (false /*num_macroblocks[MACROBLOCK_TYPE_BKWD_FIELD_PRED] > 0*/ ) {
+      r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all);
+      r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.p);
+      r->textures.individual.ref[0] = r->future->texture;
+      r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->future);
+      r->pipe->set_fragment_sampler_views(r->pipe, 4, r->sampler_views.all);
+      r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all);
+      r->pipe->bind_vs_state(r->pipe, r->p_vs[1]);
+      r->pipe->bind_fs_state(r->pipe, r->p_fs[1]);
+
+      r->pipe->draw_arrays(r->pipe, PIPE_PRIM_TRIANGLES, vb_start,
+                           num_macroblocks[MACROBLOCK_TYPE_BKWD_FIELD_PRED] * 24);
+      vb_start += num_macroblocks[MACROBLOCK_TYPE_BKWD_FIELD_PRED] * 24;
+   }
+
+   if (num_macroblocks[MACROBLOCK_TYPE_BI_FRAME_PRED] > 0) {
+      r->pipe->set_vertex_buffers(r->pipe, 3, r->vertex_bufs.all);
+      r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.b);
+      r->textures.individual.ref[0] = r->past->texture;
+      r->textures.individual.ref[1] = r->future->texture;
+      r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->past);
+      r->sampler_views.individual.ref[1] = find_or_create_sampler_view(r, r->future);
+      r->pipe->set_fragment_sampler_views(r->pipe, 5, r->sampler_views.all);
+      r->pipe->bind_fragment_sampler_states(r->pipe, 5, r->samplers.all);
+      r->pipe->bind_vs_state(r->pipe, r->b_vs[0]);
+      r->pipe->bind_fs_state(r->pipe, r->b_fs[0]);
+
+      r->pipe->draw_arrays(r->pipe, PIPE_PRIM_TRIANGLES, vb_start,
+                           num_macroblocks[MACROBLOCK_TYPE_BI_FRAME_PRED] * 24);
+      vb_start += num_macroblocks[MACROBLOCK_TYPE_BI_FRAME_PRED] * 24;
+   }
+
+   if (false /*num_macroblocks[MACROBLOCK_TYPE_BI_FIELD_PRED] > 0 */ ) {
+      r->pipe->set_vertex_buffers(r->pipe, 3, r->vertex_bufs.all);
+      r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.b);
+      r->textures.individual.ref[0] = r->past->texture;
+      r->textures.individual.ref[1] = r->future->texture;
+      r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->past);
+      r->sampler_views.individual.ref[1] = find_or_create_sampler_view(r, r->future);
+      r->pipe->set_fragment_sampler_views(r->pipe, 5, r->sampler_views.all);
+      r->pipe->bind_fragment_sampler_states(r->pipe, 5, r->samplers.all);
+      r->pipe->bind_vs_state(r->pipe, r->b_vs[1]);
+      r->pipe->bind_fs_state(r->pipe, r->b_fs[1]);
+
+      r->pipe->draw_arrays(r->pipe, PIPE_PRIM_TRIANGLES, vb_start,
+                           num_macroblocks[MACROBLOCK_TYPE_BI_FIELD_PRED] * 24);
+      vb_start += num_macroblocks[MACROBLOCK_TYPE_BI_FIELD_PRED] * 24;
+   }
+
+   r->pipe->flush(r->pipe, PIPE_FLUSH_RENDER_CACHE, r->fence);
+
+   if (r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE)
+      for (i = 0; i < 3; ++i)
+         r->zero_block[i].x = ZERO_BLOCK_NIL;
+
+   r->num_macroblocks = 0;
+}
+
+static void
+grab_frame_coded_block(short *src, short *dst, unsigned dst_pitch)
+{
+   unsigned y;
+
+   assert(src);
+   assert(dst);
+
+   for (y = 0; y < BLOCK_HEIGHT; ++y)
+      memcpy(dst + y * dst_pitch, src + y * BLOCK_WIDTH, BLOCK_WIDTH * 2);
+}
+
+static void
+grab_field_coded_block(short *src, short *dst, unsigned dst_pitch)
+{
+   unsigned y;
+
+   assert(src);
+   assert(dst);
+
+   for (y = 0; y < BLOCK_HEIGHT; ++y)
+      memcpy(dst + y * dst_pitch * 2, src + y * BLOCK_WIDTH, BLOCK_WIDTH * 2);
+}
+
+static void
+fill_zero_block(short *dst, unsigned dst_pitch)
+{
+   unsigned y;
+
+   assert(dst);
+
+   for (y = 0; y < BLOCK_HEIGHT; ++y)
+      memset(dst + y * dst_pitch, 0, BLOCK_WIDTH * 2);
+}
+
+static void
+grab_blocks(struct vl_mpeg12_mc_renderer *r, unsigned mbx, unsigned mby,
+            enum pipe_mpeg12_dct_type dct_type, unsigned cbp, short *blocks)
+{
+   unsigned tex_pitch;
+   short *texels;
+   unsigned tb = 0, sb = 0;
+   unsigned mbpx = mbx * MACROBLOCK_WIDTH, mbpy = mby * MACROBLOCK_HEIGHT;
+   unsigned x, y;
+
+   assert(r);
+   assert(blocks);
+
+   tex_pitch = r->tex_transfer[0]->stride / util_format_get_blocksize(r->tex_transfer[0]->resource->format);
+   texels = r->texels[0] + mbpy * tex_pitch + mbpx;
+
+   for (y = 0; y < 2; ++y) {
+      for (x = 0; x < 2; ++x, ++tb) {
+         if ((cbp >> (5 - tb)) & 1) {
+            if (dct_type == PIPE_MPEG12_DCT_TYPE_FRAME) {
+               grab_frame_coded_block(blocks + sb * BLOCK_WIDTH * BLOCK_HEIGHT,
+                                      texels + y * tex_pitch * BLOCK_WIDTH +
+                                      x * BLOCK_WIDTH, tex_pitch);
+            }
+            else {
+               grab_field_coded_block(blocks + sb * BLOCK_WIDTH * BLOCK_HEIGHT,
+                                      texels + y * tex_pitch + x * BLOCK_WIDTH,
+                                      tex_pitch);
+            }
+
+            ++sb;
+         }
+         else if (r->eb_handling != VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_NONE) {
+            if (r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ALL ||
+                ZERO_BLOCK_IS_NIL(r->zero_block[0])) {
+               fill_zero_block(texels + y * tex_pitch * BLOCK_WIDTH + x * BLOCK_WIDTH, tex_pitch);
+               if (r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE) {
+                  r->zero_block[0].x = (mbpx + x * 8) * r->surface_tex_inv_size.x;
+                  r->zero_block[0].y = (mbpy + y * 8) * r->surface_tex_inv_size.y;
+               }
+            }
+         }
+      }
+   }
+
+   /* TODO: Implement 422, 444 */
+   assert(r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
+
+   mbpx /= 2;
+   mbpy /= 2;
+
+   for (tb = 0; tb < 2; ++tb) {
+      tex_pitch = r->tex_transfer[tb + 1]->stride / util_format_get_blocksize(r->tex_transfer[tb + 1]->resource->format);
+      texels = r->texels[tb + 1] + mbpy * tex_pitch + mbpx;
+
+      if ((cbp >> (1 - tb)) & 1) {
+         grab_frame_coded_block(blocks + sb * BLOCK_WIDTH * BLOCK_HEIGHT, texels, tex_pitch);
+         ++sb;
+      }
+      else if (r->eb_handling != VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_NONE) {
+         if (r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ALL ||
+             ZERO_BLOCK_IS_NIL(r->zero_block[tb + 1])) {
+            fill_zero_block(texels, tex_pitch);
+            if (r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE) {
+               r->zero_block[tb + 1].x = (mbpx << 1) * r->surface_tex_inv_size.x;
+               r->zero_block[tb + 1].y = (mbpy << 1) * r->surface_tex_inv_size.y;
+            }
+         }
+      }
+   }
+}
+
+static void
+grab_macroblock(struct vl_mpeg12_mc_renderer *r,
+                struct pipe_mpeg12_macroblock *mb)
+{
+   assert(r);
+   assert(mb);
+   assert(mb->blocks);
+   assert(r->num_macroblocks < r->macroblocks_per_batch);
+
+   memcpy(&r->macroblock_buf[r->num_macroblocks], mb,
+          sizeof(struct pipe_mpeg12_macroblock));
+
+   grab_blocks(r, mb->mbx, mb->mby, mb->dct_type, mb->cbp, mb->blocks);
+
+   ++r->num_macroblocks;
+}
+
+static void
+texview_map_delete(const struct keymap *map,
+                   const void *key, void *data,
+                   void *user)
+{
+   struct pipe_sampler_view *sv = (struct pipe_sampler_view*)data;
+
+   assert(map);
+   assert(key);
+   assert(data);
+   assert(user);
+
+   pipe_sampler_view_reference(&sv, NULL);
+}
+
+bool
+vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer *renderer,
+                           struct pipe_context *pipe,
+                           unsigned picture_width,
+                           unsigned picture_height,
+                           enum pipe_video_chroma_format chroma_format,
+                           enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode,
+                           enum VL_MPEG12_MC_RENDERER_EMPTY_BLOCK eb_handling,
+                           bool pot_buffers)
+{
+   unsigned i;
+
+   assert(renderer);
+   assert(pipe);
+   /* TODO: Implement other policies */
+   assert(bufmode == VL_MPEG12_MC_RENDERER_BUFFER_PICTURE);
+   /* TODO: Implement this */
+   /* XXX: XFER_ALL sampling issue at block edges when using bilinear filtering */
+   assert(eb_handling != VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_NONE);
+   /* TODO: Non-pot buffers untested, probably doesn't work without changes to texcoord generation, vert shader, etc */
+   assert(pot_buffers);
+
+   memset(renderer, 0, sizeof(struct vl_mpeg12_mc_renderer));
+
+   renderer->pipe = pipe;
+   renderer->picture_width = picture_width;
+   renderer->picture_height = picture_height;
+   renderer->chroma_format = chroma_format;
+   renderer->bufmode = bufmode;
+   renderer->eb_handling = eb_handling;
+   renderer->pot_buffers = pot_buffers;
+
+   renderer->texview_map = util_new_keymap(sizeof(struct pipe_surface*), -1,
+                                           texview_map_delete);
+   if (!renderer->texview_map)
+      return false;
+
+   if (!init_pipe_state(renderer)) {
+      util_delete_keymap(renderer->texview_map, renderer->pipe);
+      return false;
+   }
+   if (!init_shaders(renderer)) {
+      util_delete_keymap(renderer->texview_map, renderer->pipe);
+      cleanup_pipe_state(renderer);
+      return false;
+   }
+   if (!init_buffers(renderer)) {
+      util_delete_keymap(renderer->texview_map, renderer->pipe);
+      cleanup_shaders(renderer);
+      cleanup_pipe_state(renderer);
+      return false;
+   }
+
+   renderer->surface = NULL;
+   renderer->past = NULL;
+   renderer->future = NULL;
+   for (i = 0; i < 3; ++i)
+      renderer->zero_block[i].x = ZERO_BLOCK_NIL;
+   renderer->num_macroblocks = 0;
+
+   xfer_buffers_map(renderer);
+
+   return true;
+}
+
+void
+vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer *renderer)
+{
+   assert(renderer);
+
+   xfer_buffers_unmap(renderer);
+
+   util_delete_keymap(renderer->texview_map, renderer->pipe);
+   cleanup_pipe_state(renderer);
+   cleanup_shaders(renderer);
+   cleanup_buffers(renderer);
+
+   pipe_surface_reference(&renderer->surface, NULL);
+   pipe_surface_reference(&renderer->past, NULL);
+   pipe_surface_reference(&renderer->future, NULL);
+}
+
+void
+vl_mpeg12_mc_renderer_render_macroblocks(struct vl_mpeg12_mc_renderer
+                                         *renderer,
+                                         struct pipe_surface *surface,
+                                         struct pipe_surface *past,
+                                         struct pipe_surface *future,
+                                         unsigned num_macroblocks,
+                                         struct pipe_mpeg12_macroblock
+                                         *mpeg12_macroblocks,
+                                         struct pipe_fence_handle **fence)
+{
+   bool new_surface = false;
+
+   assert(renderer);
+   assert(surface);
+   assert(num_macroblocks);
+   assert(mpeg12_macroblocks);
+
+   if (renderer->surface) {
+      if (surface != renderer->surface) {
+         if (renderer->num_macroblocks > 0) {
+            xfer_buffers_unmap(renderer);
+            flush(renderer);
+         }
+
+         new_surface = true;
+      }
+
+      /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */
+      assert(surface != renderer->surface || renderer->past == past);
+      assert(surface != renderer->surface || renderer->future == future);
+   }
+   else
+      new_surface = true;
+
+   if (new_surface) {
+      pipe_surface_reference(&renderer->surface, surface);
+      pipe_surface_reference(&renderer->past, past);
+      pipe_surface_reference(&renderer->future, future);
+      renderer->fence = fence;
+      renderer->surface_tex_inv_size.x = 1.0f / surface->width;
+      renderer->surface_tex_inv_size.y = 1.0f / surface->height;
+   }
+
+   while (num_macroblocks) {
+      unsigned left_in_batch = renderer->macroblocks_per_batch - renderer->num_macroblocks;
+      unsigned num_to_submit = MIN2(num_macroblocks, left_in_batch);
+      unsigned i;
+
+      for (i = 0; i < num_to_submit; ++i) {
+         assert(mpeg12_macroblocks[i].base.codec == PIPE_VIDEO_CODEC_MPEG12);
+         grab_macroblock(renderer, &mpeg12_macroblocks[i]);
+      }
+
+      num_macroblocks -= num_to_submit;
+
+      if (renderer->num_macroblocks == renderer->macroblocks_per_batch) {
+         xfer_buffers_unmap(renderer);
+         flush(renderer);
+         xfer_buffers_map(renderer);
+         /* Next time we get this surface it may have new ref frames */
+         pipe_surface_reference(&renderer->surface, NULL);
+         pipe_surface_reference(&renderer->past, NULL);
+         pipe_surface_reference(&renderer->future, NULL);
+      }
+   }
+}
diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h
new file mode 100644 (file)
index 0000000..85191cf
--- /dev/null
@@ -0,0 +1,132 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef vl_mpeg12_mc_renderer_h
+#define vl_mpeg12_mc_renderer_h
+
+#include <pipe/p_compiler.h>
+#include <pipe/p_state.h>
+#include <pipe/p_video_state.h>
+#include "vl_types.h"
+
+struct pipe_context;
+struct pipe_macroblock;
+struct keymap;
+
+/* A slice is video-width (rounded up to a multiple of macroblock width) x macroblock height */
+enum VL_MPEG12_MC_RENDERER_BUFFER_MODE
+{
+   VL_MPEG12_MC_RENDERER_BUFFER_SLICE,  /* Saves memory at the cost of smaller batches */
+   VL_MPEG12_MC_RENDERER_BUFFER_PICTURE /* Larger batches, more memory */
+};
+
+enum VL_MPEG12_MC_RENDERER_EMPTY_BLOCK
+{
+   VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ALL, /* Waste of memory bandwidth */
+   VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE, /* Can only do point-filtering when interpolating subsampled chroma channels */
+   VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_NONE /* Needs conditional texel fetch! */
+};
+
+struct vl_mpeg12_mc_renderer
+{
+   struct pipe_context *pipe;
+   unsigned picture_width;
+   unsigned picture_height;
+   enum pipe_video_chroma_format chroma_format;
+   enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode;
+   enum VL_MPEG12_MC_RENDERER_EMPTY_BLOCK eb_handling;
+   bool pot_buffers;
+   unsigned macroblocks_per_batch;
+
+   struct pipe_viewport_state viewport;
+   struct pipe_resource *vs_const_buf;
+   struct pipe_framebuffer_state fb_state;
+   union
+   {
+      void *all[3];
+      struct { void *i, *p, *b; } individual;
+   } vertex_elems_state;
+
+   union
+   {
+      void *all[5];
+      struct { void *y, *cb, *cr, *ref[2]; } individual;
+   } samplers;
+
+   union
+   {
+      struct pipe_sampler_view *all[5];
+      struct { struct pipe_sampler_view *y, *cb, *cr, *ref[2]; } individual;
+   } sampler_views;
+
+   void *i_vs, *p_vs[2], *b_vs[2];
+   void *i_fs, *p_fs[2], *b_fs[2];
+
+   union
+   {
+      struct pipe_resource *all[5];
+      struct { struct pipe_resource *y, *cb, *cr, *ref[2]; } individual;
+   } textures;
+
+   union
+   {
+      struct pipe_vertex_buffer all[3];
+      struct { struct pipe_vertex_buffer ycbcr, ref[2]; } individual;
+   } vertex_bufs;
+
+   struct pipe_surface *surface, *past, *future;
+   struct pipe_fence_handle **fence;
+   unsigned num_macroblocks;
+   struct pipe_mpeg12_macroblock *macroblock_buf;
+   struct pipe_transfer *tex_transfer[3];
+   short *texels[3];
+   struct vertex2f surface_tex_inv_size;
+   struct vertex2f zero_block[3];
+
+   struct keymap *texview_map;
+};
+
+bool vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer *renderer,
+                                struct pipe_context *pipe,
+                                unsigned picture_width,
+                                unsigned picture_height,
+                                enum pipe_video_chroma_format chroma_format,
+                                enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode,
+                                enum VL_MPEG12_MC_RENDERER_EMPTY_BLOCK eb_handling,
+                                bool pot_buffers);
+
+void vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer *renderer);
+
+void vl_mpeg12_mc_renderer_render_macroblocks(struct vl_mpeg12_mc_renderer *renderer,
+                                              struct pipe_surface *surface,
+                                              struct pipe_surface *past,
+                                              struct pipe_surface *future,
+                                              unsigned num_macroblocks,
+                                              struct pipe_mpeg12_macroblock *mpeg12_macroblocks,
+                                              struct pipe_fence_handle **fence);
+
+#endif /* vl_mpeg12_mc_renderer_h */
diff --git a/src/gallium/auxiliary/vl/vl_types.h b/src/gallium/auxiliary/vl/vl_types.h
new file mode 100644 (file)
index 0000000..ce17554
--- /dev/null
@@ -0,0 +1,41 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef vl_types_h
+#define vl_types_h
+
+struct vertex2f
+{
+   float x, y;
+};
+
+struct vertex4f
+{
+   float x, y, z, w;
+};
+
+#endif /* vl_types_h */
diff --git a/src/gallium/drivers/nv40/nv40_video_context.c b/src/gallium/drivers/nv40/nv40_video_context.c
new file mode 100644 (file)
index 0000000..15a26ea
--- /dev/null
@@ -0,0 +1,48 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "nv40_video_context.h"
+#include <softpipe/sp_video_context.h>
+
+struct pipe_video_context *
+nv40_video_create(struct pipe_screen *screen, enum pipe_video_profile profile,
+                  enum pipe_video_chroma_format chroma_format,
+                  unsigned width, unsigned height, void *priv)
+{
+   struct pipe_context *pipe;
+
+   assert(screen);
+
+   pipe = screen->context_create(screen, priv);
+   if (!pipe)
+      return NULL;
+
+   return sp_video_create_ex(pipe, profile, chroma_format, width, height,
+                             VL_MPEG12_MC_RENDERER_BUFFER_PICTURE,
+                             VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE,
+                             true);
+}
diff --git a/src/gallium/drivers/nv40/nv40_video_context.h b/src/gallium/drivers/nv40/nv40_video_context.h
new file mode 100644 (file)
index 0000000..64196ca
--- /dev/null
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef __NV40_VIDEO_CONTEXT_H__
+#define __NV40_VIDEO_CONTEXT_H__
+
+#include <pipe/p_video_context.h>
+
+struct pipe_video_context *
+nv40_video_create(struct pipe_screen *screen, enum pipe_video_profile profile,
+                  enum pipe_video_chroma_format chroma_format,
+                  unsigned width, unsigned height, void *priv);
+
+#endif
index 46bb082388116d98c17ee3b8e0086f4753511e4e..95da778225616b0fce542d8839f6be890c39c433 100644 (file)
@@ -24,7 +24,8 @@ C_SOURCES = \
        nvfx_surface.c \
        nvfx_transfer.c \
        nvfx_vbo.c \
-       nvfx_vertprog.c
+       nvfx_vertprog.c \
+       nvfx_video_context.c
 
 LIBRARY_INCLUDES = \
        -I$(TOP)/src/gallium/drivers/nouveau/include
index 8024800bd09dc29d8ca464856d7e323e8876aeeb..875b3a96ca693847db87a1ca8cbb51beec3256f7 100644 (file)
@@ -6,6 +6,7 @@
 #include "nouveau/nouveau_screen.h"
 #include "nouveau/nv_object.xml.h"
 #include "nvfx_context.h"
+#include "nvfx_video_context.h"
 #include "nvfx_screen.h"
 #include "nvfx_resource.h"
 #include "nvfx_tex.h"
@@ -434,6 +435,7 @@ nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
        pscreen->get_paramf = nvfx_screen_get_paramf;
        pscreen->is_format_supported = nvfx_screen_is_format_supported;
        pscreen->context_create = nvfx_create;
+       pscreen->video_context_create = nvfx_video_create;
 
        switch (dev->chipset & 0xf0) {
        case 0x30:
index 8fafca1950ccb5bc4116373dd881ef18899b7a87..15e1cbb1986703cf6202f5ca6ef76fe47b14191a 100644 (file)
@@ -2,6 +2,7 @@
 #define __NVFX_STATE_H__
 
 #include "pipe/p_state.h"
+#include "pipe/p_video_state.h"
 #include "tgsi/tgsi_scan.h"
 #include "nouveau/nouveau_statebuf.h"
 #include "util/u_dynarray.h"
diff --git a/src/gallium/drivers/nvfx/nvfx_video_context.c b/src/gallium/drivers/nvfx/nvfx_video_context.c
new file mode 100644 (file)
index 0000000..9212ae5
--- /dev/null
@@ -0,0 +1,49 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "nvfx_video_context.h"
+#include <softpipe/sp_video_context.h>
+
+struct pipe_video_context *
+nvfx_video_create(struct pipe_screen *screen, enum pipe_video_profile profile,
+                  enum pipe_video_chroma_format chroma_format,
+                  unsigned width, unsigned height, void *priv)
+{
+   struct pipe_context *pipe;
+
+   assert(screen);
+
+   pipe = screen->context_create(screen, priv);
+   if (!pipe)
+      return NULL;
+
+   return sp_video_create_ex(pipe, profile, chroma_format, width, height,
+                             VL_MPEG12_MC_RENDERER_BUFFER_PICTURE,
+                             VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE,
+                             true,
+                             PIPE_FORMAT_VUYX);
+}
diff --git a/src/gallium/drivers/nvfx/nvfx_video_context.h b/src/gallium/drivers/nvfx/nvfx_video_context.h
new file mode 100644 (file)
index 0000000..6619427
--- /dev/null
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef __NVFX_VIDEO_CONTEXT_H__
+#define __NVFX_VIDEO_CONTEXT_H__
+
+#include <pipe/p_video_context.h>
+
+struct pipe_video_context *
+nvfx_video_create(struct pipe_screen *screen, enum pipe_video_profile profile,
+                  enum pipe_video_chroma_format chroma_format,
+                  unsigned width, unsigned height, void *priv);
+
+#endif
diff --git a/src/gallium/drivers/r300/r300_video_context.c b/src/gallium/drivers/r300/r300_video_context.c
new file mode 100644 (file)
index 0000000..622f1b8
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2009-2010  Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ *   CooperYuan <cooper.yuan@amd.com>, <cooperyuan@gmail.com>
+ */
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <pipe/p_defines.h>
+#include <pipe/p_context.h>
+#include <pipe/p_screen.h>
+#include <pipe/p_inlines.h>
+#include <util/u_memory.h>
+#include <X11/Xlib.h>
+
+#include <fcntl.h>
+
+#include "radeon_buffer.h"
+#include "radeon_r300.h"
+#include "r300_screen.h"
+#include "r300_texture.h"
+#include "p_video_context.h"
+#include "radeon_vl.h"
+#include "softpipe/sp_winsys.h"
+#include "softpipe/sp_texture.h"
+
+#include "r300_video_context.h"
+#include <softpipe/sp_video_context.h>
+
+static void r300_mpeg12_destroy(struct pipe_video_context *vpipe)
+{
+    struct radeon_mpeg12_context *ctx = (struct radeon_mpeg12_context*)vpipe;
+
+    assert(vpipe);
+
+    ctx->pipe->bind_vs_state(ctx->pipe, NULL);
+    ctx->pipe->bind_fs_state(ctx->pipe, NULL);
+
+    ctx->pipe->delete_blend_state(ctx->pipe, ctx->blend);
+    ctx->pipe->delete_rasterizer_state(ctx->pipe, ctx->rast);
+    ctx->pipe->delete_depth_stencil_alpha_state(ctx->pipe, ctx->dsa);
+
+    pipe_video_surface_reference(&ctx->decode_target, NULL);
+    vl_compositor_cleanup(&ctx->compositor);
+    vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
+    ctx->pipe->destroy(ctx->pipe);
+
+    FREE(ctx);
+}
+
+static void
+r300_mpeg12_decode_macroblocks(struct pipe_video_context *vpipe,
+                               struct pipe_video_surface *past,
+                               struct pipe_video_surface *future,
+                               unsigned num_macroblocks,
+                               struct pipe_macroblock *macroblocks,
+                               struct pipe_fence_handle **fence)
+{
+    struct radeon_mpeg12_context *ctx = (struct radeon_mpeg12_context*)vpipe;
+    struct pipe_mpeg12_macroblock *mpeg12_macroblocks =
+                         (struct pipe_mpeg12_macroblock*)macroblocks;
+
+    assert(vpipe);
+    assert(num_macroblocks);
+    assert(macroblocks);
+    assert(macroblocks->codec == PIPE_VIDEO_CODEC_MPEG12);
+    assert(ctx->decode_target);
+
+    vl_mpeg12_mc_renderer_render_macroblocks(
+                            &ctx->mc_renderer,
+                            r300_video_surface(ctx->decode_target)->tex,
+                            past ? r300_video_surface(past)->tex : NULL,
+                            future ? r300_video_surface(future)->tex : NULL,
+                            num_macroblocks, mpeg12_macroblocks, fence);
+}
+
+static void r300_mpeg12_clear_surface(struct pipe_video_context *vpipe,
+                                      unsigned x, unsigned y,
+                                      unsigned width, unsigned height,
+                                      unsigned value,
+                                      struct pipe_surface *surface)
+{
+    struct radeon_mpeg12_context *ctx = (struct radeon_mpeg12_context*)vpipe;
+
+    assert(vpipe);
+    assert(surface);
+
+    if (ctx->pipe->surface_fill)
+        ctx->pipe->surface_fill(ctx->pipe, surface, x, y, width, height, value);
+    else
+        util_surface_fill(ctx->pipe, surface, x, y, width, height, value);
+}
+
+static void
+r300_mpeg12_render_picture(struct pipe_video_context     *vpipe,
+                           struct pipe_video_surface     *src_surface,
+                           enum pipe_mpeg12_picture_type picture_type,
+                           struct pipe_video_rect        *src_area,
+                           struct pipe_surface           *dst_surface,
+                           struct pipe_video_rect        *dst_area,
+                           struct pipe_fence_handle      **fence)
+{
+    struct radeon_mpeg12_context *ctx = (struct radeon_mpeg12_context*)vpipe;
+
+    assert(vpipe);
+    assert(src_surface);
+    assert(src_area);
+    assert(dst_surface);
+    assert(dst_area);
+
+    vl_compositor_render(&ctx->compositor,
+                         r300_video_surface(src_surface)->tex,
+                         picture_type, src_area, dst_surface->texture,
+                         dst_area, fence);
+}
+
+static void r300_mpeg12_set_decode_target(struct pipe_video_context *vpipe,
+                                          struct pipe_video_surface *dt)
+{
+    struct radeon_mpeg12_context *ctx = (struct radeon_mpeg12_context*)vpipe;
+
+    assert(vpipe);
+    assert(dt);
+
+    pipe_video_surface_reference(&ctx->decode_target, dt);
+}
+
+static void r300_mpeg12_set_csc_matrix(struct pipe_video_context *vpipe,
+                                       const float *mat)
+{
+    struct radeon_mpeg12_context *ctx = (struct radeon_mpeg12_context*)vpipe;
+
+    assert(vpipe);
+
+    vl_compositor_set_csc_matrix(&ctx->compositor, mat);
+}
+
+static bool r300_mpeg12_init_pipe_state(struct radeon_mpeg12_context *ctx)
+{
+    struct pipe_rasterizer_state rast;
+    struct pipe_blend_state blend;
+    struct pipe_depth_stencil_alpha_state dsa;
+    unsigned i;
+
+    assert(ctx);
+
+    rast.flatshade = 1;
+    rast.flatshade_first = 0;
+    rast.light_twoside = 0;
+    rast.front_winding = PIPE_WINDING_CCW;
+    rast.cull_mode = PIPE_WINDING_CW;
+    rast.fill_cw = PIPE_POLYGON_MODE_FILL;
+    rast.fill_ccw = PIPE_POLYGON_MODE_FILL;
+    rast.offset_cw = 0;
+    rast.offset_ccw = 0;
+    rast.scissor = 0;
+    rast.poly_smooth = 0;
+    rast.poly_stipple_enable = 0;
+    rast.point_sprite = 0;
+    rast.point_size_per_vertex = 0;
+    rast.multisample = 0;
+    rast.line_smooth = 0;
+    rast.line_stipple_enable = 0;
+    rast.line_stipple_factor = 0;
+    rast.line_stipple_pattern = 0;
+    rast.line_last_pixel = 0;
+    rast.bypass_vs_clip_and_viewport = 0;
+    rast.line_width = 1;
+    rast.point_smooth = 0;
+    rast.point_size = 1;
+    rast.offset_units = 1;
+    rast.offset_scale = 1;
+    /*rast.sprite_coord_mode[i] = ;*/
+    ctx->rast = ctx->pipe->create_rasterizer_state(ctx->pipe, &rast);
+    ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rast);
+
+    blend.blend_enable = 0;
+    blend.rgb_func = PIPE_BLEND_ADD;
+    blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+    blend.rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
+    blend.alpha_func = PIPE_BLEND_ADD;
+    blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+    blend.alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
+    blend.logicop_enable = 0;
+    blend.logicop_func = PIPE_LOGICOP_CLEAR;
+    /* Needed to allow color writes to FB, even if blending disabled */
+    blend.colormask = PIPE_MASK_RGBA;
+    blend.dither = 0;
+    ctx->blend = ctx->pipe->create_blend_state(ctx->pipe, &blend);
+    ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend);
+
+    dsa.depth.enabled = 0;
+    dsa.depth.writemask = 0;
+    dsa.depth.func = PIPE_FUNC_ALWAYS;
+    for (i = 0; i < 2; ++i)
+    {
+        dsa.stencil[i].enabled = 0;
+        dsa.stencil[i].func = PIPE_FUNC_ALWAYS;
+        dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP;
+        dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP;
+        dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP;
+        dsa.stencil[i].ref_value = 0;
+        dsa.stencil[i].valuemask = 0;
+        dsa.stencil[i].writemask = 0;
+    }
+    dsa.alpha.enabled = 0;
+    dsa.alpha.func = PIPE_FUNC_ALWAYS;
+    dsa.alpha.ref_value = 0;
+    ctx->dsa = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &dsa);
+    ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->dsa);
+
+    return true;
+}
+
+static struct pipe_video_context *
+r300_mpeg12_context_create(struct pipe_screen *screen,
+                           enum pipe_video_profile profile,
+                           enum pipe_video_chroma_format chroma_format,
+                           unsigned int width,
+                           unsigned int height)
+{
+    struct radeon_mpeg12_context *ctx;
+    ctx = CALLOC_STRUCT(radeon_mpeg12_context);
+    if (!ctx)
+        return NULL;
+
+    ctx->base.profile       = profile;
+    ctx->base.chroma_format = chroma_format;
+    ctx->base.width         = width;
+    ctx->base.height        = height;
+    ctx->base.screen        = screen;
+
+    ctx->base.destroy               = radeon_mpeg12_destroy;
+    ctx->base.decode_macroblocks    = radeon_mpeg12_decode_macroblocks;
+    ctx->base.clear_surface         = radeon_mpeg12_clear_surface;
+    ctx->base.render_picture        = radeon_mpeg12_render_picture;
+    ctx->base.set_decode_target     = radeon_mpeg12_set_decode_target;
+    ctx->base.set_csc_matrix        = radeon_mpeg12_set_csc_matrix;
+
+    ctx->pipe = r300_create_context(screen,(struct r300_winsys*)screen->winsys);
+    if (!ctx->pipe)
+    {
+        FREE(ctx);
+        return NULL;
+    }
+
+    if (!vl_mpeg12_mc_renderer_init(&ctx->mc_renderer, ctx->pipe,
+                                   width, height, chroma_format,
+                                   VL_MPEG12_MC_RENDERER_BUFFER_PICTURE,
+                                   VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE,
+                                   true))
+    {
+        ctx->pipe->destroy(ctx->pipe);
+        FREE(ctx);
+        return NULL;
+    }
+
+    if (!vl_compositor_init(&ctx->compositor, ctx->pipe))
+    {
+        vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
+        ctx->pipe->destroy(ctx->pipe);
+        FREE(ctx);
+        return NULL;
+    }
+
+    if (!radeon_mpeg12_init_pipe_state(ctx))
+    {
+        vl_compositor_cleanup(&ctx->compositor);
+        vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
+        ctx->pipe->destroy(ctx->pipe);
+        FREE(ctx);
+        return NULL;
+    }
+
+    return &ctx->base;
+}
+
+struct pipe_video_context *
+r300_video_create(struct pipe_context *pipe, enum pipe_video_profile profile,
+                  enum pipe_video_chroma_format chroma_format,
+                  unsigned width, unsigned height,
+                  unsigned pvctx_id)
+{
+    struct pipe_video_context *vpipe;
+    struct radeon_vl_context *rvl_ctx;
+
+    assert(p_screen);
+    assert(width && height);
+
+    /* create radeon pipe_context */
+    switch(u_reduce_video_profile(profile))
+    {
+        case PIPE_VIDEO_CODEC_MPEG12:
+            vpipe = radeon_mpeg12_context_create(p_screen, profile, chr_f,
+                                                 width, height);
+            break;
+        default:
+            return NULL;
+    }
+
+    /* create radeon_vl_context */
+    rvl_ctx = calloc(1, sizeof(struct radeon_vl_context));
+    rvl_ctx->display = display;
+    rvl_ctx->screen = screen;
+
+    vpipe->priv = rvl_ctx;
+
+    return vpipe;
+}
diff --git a/src/gallium/drivers/r300/r300_video_context.h b/src/gallium/drivers/r300/r300_video_context.h
new file mode 100644 (file)
index 0000000..a8210ba
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009-2010  Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ *   CooperYuan <cooper.yuan@amd.com>, <cooperyuan@gmail.com>
+ */
+
+#ifndef __R300_VIDEO_CONTEXT_H__
+#define __R300_VIDEO_CONTEXT_H__
+
+#include <pipe/p_video_context.h>
+
+struct pipe_context;
+
+struct pipe_video_context*
+r300_video_create(struct pipe_context *pipe, enum pipe_video_profile profile,
+                  enum pipe_video_chroma_format chroma_format,
+                  unsigned width, unsigned height,
+                  unsigned pvctx_id);
+
+#endif
index 28953582f0a4bf36dfd72b3e1df64ce0daded59a..8876bd163986febd5106778725061da337207d0f 100644 (file)
@@ -19,7 +19,7 @@ C_SOURCES = \
        sp_quad_fs.c \
        sp_quad_blend.c \
        sp_screen.c \
-        sp_setup.c \
+       sp_setup.c \
        sp_state_blend.c \
        sp_state_clip.c \
        sp_state_derived.c \
@@ -33,6 +33,7 @@ C_SOURCES = \
        sp_tex_sample.c \
        sp_tex_tile_cache.c \
        sp_tile_cache.c \
-       sp_surface.c
+       sp_surface.c \
+       sp_video_context.c
 
 include ../../Makefile.template
index d5f4d28aeffe499928981c4d19d5b28413ca17b7..dea7f885e0def451cbab52bfe416559df94660e1 100644 (file)
@@ -35,6 +35,7 @@ softpipe = env.ConvenienceLibrary(
                'sp_tex_tile_cache.c',
                'sp_texture.c',
                'sp_tile_cache.c',
+               'sp_video_context.c',
        ])
 
 Export('softpipe')
index 2053d02f6289fcb4d726e975c71abe9342b658c2..25a0a6221798c762a6be5c25da7c75839bb219a6 100644 (file)
@@ -39,6 +39,7 @@
 #include "sp_texture.h"
 #include "sp_screen.h"
 #include "sp_context.h"
+#include "sp_video_context.h"
 #include "sp_fence.h"
 #include "sp_public.h"
 
@@ -301,6 +302,7 @@ softpipe_create_screen(struct sw_winsys *winsys)
    screen->base.is_format_supported = softpipe_is_format_supported;
    screen->base.context_create = softpipe_create_context;
    screen->base.flush_frontbuffer = softpipe_flush_frontbuffer;
+   screen->base.video_context_create = sp_video_create;
 
    util_format_s3tc_init();
 
index 6b205dc53290cca4b6747aa1d5fbd6ad21cf985f..7e3249b46f01bdf83e5f139e0fd1ae19f13923b3 100644 (file)
@@ -82,7 +82,6 @@ struct softpipe_transfer
 };
 
 
-
 /** cast wrappers */
 static INLINE struct softpipe_resource *
 softpipe_resource(struct pipe_resource *pt)
diff --git a/src/gallium/drivers/softpipe/sp_video_context.c b/src/gallium/drivers/softpipe/sp_video_context.c
new file mode 100644 (file)
index 0000000..44df00e
--- /dev/null
@@ -0,0 +1,526 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
+
+#include "sp_video_context.h"
+#include <util/u_inlines.h>
+#include <util/u_memory.h>
+#include <util/u_rect.h>
+#include <util/u_video.h>
+#include "sp_public.h"
+#include "sp_texture.h"
+
+static void
+sp_mpeg12_destroy(struct pipe_video_context *vpipe)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+
+   /* Asserted in softpipe_delete_fs_state() for some reason */
+   ctx->pipe->bind_vs_state(ctx->pipe, NULL);
+   ctx->pipe->bind_fs_state(ctx->pipe, NULL);
+
+   ctx->pipe->delete_blend_state(ctx->pipe, ctx->blend);
+   ctx->pipe->delete_rasterizer_state(ctx->pipe, ctx->rast);
+   ctx->pipe->delete_depth_stencil_alpha_state(ctx->pipe, ctx->dsa);
+
+   pipe_surface_reference(&ctx->decode_target, NULL);
+   vl_compositor_cleanup(&ctx->compositor);
+   vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
+   ctx->pipe->destroy(ctx->pipe);
+
+   FREE(ctx);
+}
+
+static int
+sp_mpeg12_get_param(struct pipe_video_context *vpipe, int param)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+
+   switch (param) {
+      case PIPE_CAP_NPOT_TEXTURES:
+         /* XXX: Temporary; not all paths are NPOT-tested */
+#if 0
+         return ctx->pipe->screen->get_param(ctx->pipe->screen, param);
+#endif
+         return FALSE;
+      case PIPE_CAP_DECODE_TARGET_PREFERRED_FORMAT:
+         return ctx->decode_format;
+      default:
+      {
+         debug_printf("Softpipe: Unknown PIPE_CAP %d\n", param);
+         return 0;
+      }
+   }
+}
+
+static boolean
+sp_mpeg12_is_format_supported(struct pipe_video_context *vpipe,
+                              enum pipe_format format,
+                              unsigned usage,
+                              unsigned geom)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+
+   /* XXX: Temporary; not all paths are NPOT-tested */
+   if (geom & PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO)
+      return FALSE;
+
+   return ctx->pipe->screen->is_format_supported(ctx->pipe->screen, PIPE_TEXTURE_2D,
+                                                 format, usage, geom);
+}
+
+static void
+sp_mpeg12_decode_macroblocks(struct pipe_video_context *vpipe,
+                             struct pipe_surface *past,
+                             struct pipe_surface *future,
+                             unsigned num_macroblocks,
+                             struct pipe_macroblock *macroblocks,
+                             struct pipe_fence_handle **fence)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+   struct pipe_mpeg12_macroblock *mpeg12_macroblocks = (struct pipe_mpeg12_macroblock*)macroblocks;
+
+   assert(vpipe);
+   assert(num_macroblocks);
+   assert(macroblocks);
+   assert(macroblocks->codec == PIPE_VIDEO_CODEC_MPEG12);
+   assert(ctx->decode_target);
+
+   vl_mpeg12_mc_renderer_render_macroblocks(&ctx->mc_renderer,
+                                            ctx->decode_target,
+                                            past, future, num_macroblocks,
+                                            mpeg12_macroblocks, fence);
+}
+
+static void
+sp_mpeg12_surface_fill(struct pipe_video_context *vpipe,
+                       struct pipe_surface *dst,
+                       unsigned dstx, unsigned dsty,
+                       unsigned width, unsigned height,
+                       unsigned value)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+   assert(dst);
+
+   if (ctx->pipe->surface_fill)
+      ctx->pipe->surface_fill(ctx->pipe, dst, dstx, dsty, width, height, value);
+   else
+      util_surface_fill(ctx->pipe, dst, dstx, dsty, width, height, value);
+}
+
+static void
+sp_mpeg12_surface_copy(struct pipe_video_context *vpipe,
+                       struct pipe_surface *dst,
+                       unsigned dstx, unsigned dsty,
+                       struct pipe_surface *src,
+                       unsigned srcx, unsigned srcy,
+                       unsigned width, unsigned height)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+   assert(dst);
+
+   if (ctx->pipe->surface_copy)
+      ctx->pipe->surface_copy(ctx->pipe, dst, dstx, dsty, src, srcx, srcy, width, height);
+   else
+      util_surface_copy(ctx->pipe, FALSE, dst, dstx, dsty, src, srcx, srcy, width, height);
+}
+
+static struct pipe_transfer*
+sp_mpeg12_get_transfer(struct pipe_video_context *vpipe,
+                       struct pipe_resource *resource,
+                       struct pipe_subresource subresource,
+                       unsigned usage,  /* a combination of PIPE_TRANSFER_x */
+                       const struct pipe_box *box)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+   assert(resource);
+   assert(box);
+
+   return ctx->pipe->get_transfer(ctx->pipe, resource, subresource, usage, box);
+}
+
+static void
+sp_mpeg12_transfer_destroy(struct pipe_video_context *vpipe,
+                           struct pipe_transfer *transfer)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+   assert(transfer);
+
+   ctx->pipe->transfer_destroy(ctx->pipe, transfer);
+}
+
+static void*
+sp_mpeg12_transfer_map(struct pipe_video_context *vpipe,
+                       struct pipe_transfer *transfer)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+   assert(transfer);
+
+   return ctx->pipe->transfer_map(ctx->pipe, transfer);
+}
+
+static void
+sp_mpeg12_transfer_flush_region(struct pipe_video_context *vpipe,
+                                struct pipe_transfer *transfer,
+                                const struct pipe_box *box)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+   assert(transfer);
+   assert(box);
+
+   ctx->pipe->transfer_flush_region(ctx->pipe, transfer, box);
+}
+
+static void
+sp_mpeg12_transfer_unmap(struct pipe_video_context *vpipe,
+                         struct pipe_transfer *transfer)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+   assert(transfer);
+
+   ctx->pipe->transfer_unmap(ctx->pipe, transfer);
+}
+
+static void
+sp_mpeg12_transfer_inline_write(struct pipe_video_context *vpipe,
+                                struct pipe_resource *resource,
+                                struct pipe_subresource subresource,
+                                unsigned usage, /* a combination of PIPE_TRANSFER_x */
+                                const struct pipe_box *box,
+                                const void *data,
+                                unsigned stride,
+                                unsigned slice_stride)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+   assert(resource);
+   assert(box);
+   assert(data);
+   assert(ctx->pipe->transfer_inline_write);
+
+   ctx->pipe->transfer_inline_write(ctx->pipe, resource, subresource, usage,
+                                    box, data, stride, slice_stride);
+}
+
+static void
+sp_mpeg12_render_picture(struct pipe_video_context     *vpipe,
+                         struct pipe_surface           *src_surface,
+                         enum pipe_mpeg12_picture_type picture_type,
+                         /*unsigned                    num_past_surfaces,
+                         struct pipe_surface           *past_surfaces,
+                         unsigned                      num_future_surfaces,
+                         struct pipe_surface           *future_surfaces,*/
+                         struct pipe_video_rect        *src_area,
+                         struct pipe_surface           *dst_surface,
+                         struct pipe_video_rect        *dst_area,
+                         struct pipe_fence_handle      **fence)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+   assert(src_surface);
+   assert(src_area);
+   assert(dst_surface);
+   assert(dst_area);
+
+   vl_compositor_render(&ctx->compositor, src_surface,
+                        picture_type, src_area, dst_surface, dst_area, fence);
+}
+
+static void
+sp_mpeg12_set_picture_background(struct pipe_video_context *vpipe,
+                                  struct pipe_surface *bg,
+                                  struct pipe_video_rect *bg_src_rect)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+   assert(bg);
+   assert(bg_src_rect);
+
+   vl_compositor_set_background(&ctx->compositor, bg, bg_src_rect);
+}
+
+static void
+sp_mpeg12_set_picture_layers(struct pipe_video_context *vpipe,
+                             struct pipe_surface *layers[],
+                             struct pipe_video_rect *src_rects[],
+                             struct pipe_video_rect *dst_rects[],
+                             unsigned num_layers)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+   assert((layers && src_rects && dst_rects) ||
+          (!layers && !src_rects && !dst_rects));
+
+   vl_compositor_set_layers(&ctx->compositor, layers, src_rects, dst_rects, num_layers);
+}
+
+static void
+sp_mpeg12_set_decode_target(struct pipe_video_context *vpipe,
+                            struct pipe_surface *dt)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+   assert(dt);
+
+   pipe_surface_reference(&ctx->decode_target, dt);
+}
+
+static void
+sp_mpeg12_set_csc_matrix(struct pipe_video_context *vpipe, const float *mat)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+
+   vl_compositor_set_csc_matrix(&ctx->compositor, mat);
+}
+
+static bool
+init_pipe_state(struct sp_mpeg12_context *ctx)
+{
+   struct pipe_rasterizer_state rast;
+   struct pipe_blend_state blend;
+   struct pipe_depth_stencil_alpha_state dsa;
+   unsigned i;
+
+   assert(ctx);
+
+   rast.flatshade = 1;
+   rast.flatshade_first = 0;
+   rast.light_twoside = 0;
+   rast.front_winding = PIPE_WINDING_CCW;
+   rast.cull_mode = PIPE_WINDING_CW;
+   rast.fill_cw = PIPE_POLYGON_MODE_FILL;
+   rast.fill_ccw = PIPE_POLYGON_MODE_FILL;
+   rast.offset_cw = 0;
+   rast.offset_ccw = 0;
+   rast.scissor = 0;
+   rast.poly_smooth = 0;
+   rast.poly_stipple_enable = 0;
+   rast.sprite_coord_enable = 0;
+   rast.point_size_per_vertex = 0;
+   rast.multisample = 0;
+   rast.line_smooth = 0;
+   rast.line_stipple_enable = 0;
+   rast.line_stipple_factor = 0;
+   rast.line_stipple_pattern = 0;
+   rast.line_last_pixel = 0;
+   rast.line_width = 1;
+   rast.point_smooth = 0;
+   rast.point_quad_rasterization = 0;
+   rast.point_size = 1;
+   rast.offset_units = 1;
+   rast.offset_scale = 1;
+   rast.gl_rasterization_rules = 1;
+   ctx->rast = ctx->pipe->create_rasterizer_state(ctx->pipe, &rast);
+   ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rast);
+
+   blend.independent_blend_enable = 0;
+   blend.rt[0].blend_enable = 0;
+   blend.rt[0].rgb_func = PIPE_BLEND_ADD;
+   blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+   blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
+   blend.rt[0].alpha_func = PIPE_BLEND_ADD;
+   blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+   blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
+   blend.logicop_enable = 0;
+   blend.logicop_func = PIPE_LOGICOP_CLEAR;
+   /* Needed to allow color writes to FB, even if blending disabled */
+   blend.rt[0].colormask = PIPE_MASK_RGBA;
+   blend.dither = 0;
+   ctx->blend = ctx->pipe->create_blend_state(ctx->pipe, &blend);
+   ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend);
+
+   dsa.depth.enabled = 0;
+   dsa.depth.writemask = 0;
+   dsa.depth.func = PIPE_FUNC_ALWAYS;
+   for (i = 0; i < 2; ++i) {
+      dsa.stencil[i].enabled = 0;
+      dsa.stencil[i].func = PIPE_FUNC_ALWAYS;
+      dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP;
+      dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP;
+      dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP;
+      dsa.stencil[i].valuemask = 0;
+      dsa.stencil[i].writemask = 0;
+   }
+   dsa.alpha.enabled = 0;
+   dsa.alpha.func = PIPE_FUNC_ALWAYS;
+   dsa.alpha.ref_value = 0;
+   ctx->dsa = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &dsa);
+   ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->dsa);
+
+   return true;
+}
+
+static struct pipe_video_context *
+sp_mpeg12_create(struct pipe_context *pipe, enum pipe_video_profile profile,
+                 enum pipe_video_chroma_format chroma_format,
+                 unsigned width, unsigned height,
+                 enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode,
+                 enum VL_MPEG12_MC_RENDERER_EMPTY_BLOCK eb_handling,
+                 bool pot_buffers,
+                 enum pipe_format decode_format)
+{
+   struct sp_mpeg12_context *ctx;
+
+   assert(u_reduce_video_profile(profile) == PIPE_VIDEO_CODEC_MPEG12);
+
+   ctx = CALLOC_STRUCT(sp_mpeg12_context);
+
+   if (!ctx)
+      return NULL;
+
+   ctx->base.profile = profile;
+   ctx->base.chroma_format = chroma_format;
+   ctx->base.width = width;
+   ctx->base.height = height;
+
+   ctx->base.screen = pipe->screen;
+   ctx->base.destroy = sp_mpeg12_destroy;
+   ctx->base.get_param = sp_mpeg12_get_param;
+   ctx->base.is_format_supported = sp_mpeg12_is_format_supported;
+   ctx->base.decode_macroblocks = sp_mpeg12_decode_macroblocks;
+   ctx->base.render_picture = sp_mpeg12_render_picture;
+   ctx->base.surface_fill = sp_mpeg12_surface_fill;
+   ctx->base.surface_copy = sp_mpeg12_surface_copy;
+   ctx->base.get_transfer = sp_mpeg12_get_transfer;
+   ctx->base.transfer_destroy = sp_mpeg12_transfer_destroy;
+   ctx->base.transfer_map = sp_mpeg12_transfer_map;
+   ctx->base.transfer_flush_region = sp_mpeg12_transfer_flush_region;
+   ctx->base.transfer_unmap = sp_mpeg12_transfer_unmap;
+   if (pipe->transfer_inline_write)
+      ctx->base.transfer_inline_write = sp_mpeg12_transfer_inline_write;
+   ctx->base.set_picture_background = sp_mpeg12_set_picture_background;
+   ctx->base.set_picture_layers = sp_mpeg12_set_picture_layers;
+   ctx->base.set_decode_target = sp_mpeg12_set_decode_target;
+   ctx->base.set_csc_matrix = sp_mpeg12_set_csc_matrix;
+
+   ctx->pipe = pipe;
+   ctx->decode_format = decode_format;
+
+   if (!vl_mpeg12_mc_renderer_init(&ctx->mc_renderer, ctx->pipe,
+                                   width, height, chroma_format,
+                                   bufmode, eb_handling, pot_buffers)) {
+      ctx->pipe->destroy(ctx->pipe);
+      FREE(ctx);
+      return NULL;
+   }
+
+   if (!vl_compositor_init(&ctx->compositor, ctx->pipe)) {
+      vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
+      ctx->pipe->destroy(ctx->pipe);
+      FREE(ctx);
+      return NULL;
+   }
+
+   if (!init_pipe_state(ctx)) {
+      vl_compositor_cleanup(&ctx->compositor);
+      vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
+      ctx->pipe->destroy(ctx->pipe);
+      FREE(ctx);
+      return NULL;
+   }
+
+   return &ctx->base;
+}
+
+struct pipe_video_context *
+sp_video_create(struct pipe_screen *screen, enum pipe_video_profile profile,
+                enum pipe_video_chroma_format chroma_format,
+                unsigned width, unsigned height, void *priv)
+{
+   struct pipe_context *pipe;
+
+   assert(screen);
+   assert(width && height);
+
+   pipe = screen->context_create(screen, NULL);
+   if (!pipe)
+      return NULL;
+
+   /* TODO: Use slice buffering for softpipe when implemented, no advantage to buffering an entire picture with softpipe */
+   /* TODO: Use XFER_NONE when implemented */
+   return sp_video_create_ex(pipe, profile,
+                             chroma_format,
+                             width, height,
+                             VL_MPEG12_MC_RENDERER_BUFFER_PICTURE,
+                             VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE,
+                             true,
+                             PIPE_FORMAT_XYUV);
+}
+
+struct pipe_video_context *
+sp_video_create_ex(struct pipe_context *pipe, enum pipe_video_profile profile,
+                   enum pipe_video_chroma_format chroma_format,
+                   unsigned width, unsigned height,
+                   enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode,
+                   enum VL_MPEG12_MC_RENDERER_EMPTY_BLOCK eb_handling,
+                   bool pot_buffers,
+                   enum pipe_format decode_format)
+{
+   assert(pipe);
+   assert(width && height);
+
+   switch (u_reduce_video_profile(profile)) {
+      case PIPE_VIDEO_CODEC_MPEG12:
+         return sp_mpeg12_create(pipe, profile,
+                                 chroma_format,
+                                 width, height,
+                                 bufmode, eb_handling,
+                                 pot_buffers,
+                                 decode_format);
+      default:
+         return NULL;
+   }
+}
diff --git a/src/gallium/drivers/softpipe/sp_video_context.h b/src/gallium/drivers/softpipe/sp_video_context.h
new file mode 100644 (file)
index 0000000..0fe48d7
--- /dev/null
@@ -0,0 +1,69 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef SP_VIDEO_CONTEXT_H
+#define SP_VIDEO_CONTEXT_H
+
+#include <pipe/p_video_context.h>
+#include <vl/vl_mpeg12_mc_renderer.h>
+#include <vl/vl_compositor.h>
+
+struct pipe_screen;
+struct pipe_context;
+
+struct sp_mpeg12_context
+{
+   struct pipe_video_context base;
+   struct pipe_context *pipe;
+   struct pipe_surface *decode_target;
+   struct vl_mpeg12_mc_renderer mc_renderer;
+   struct vl_compositor compositor;
+
+   void *rast;
+   void *dsa;
+   void *blend;
+
+   enum pipe_format decode_format;
+};
+
+struct pipe_video_context *
+sp_video_create(struct pipe_screen *screen, enum pipe_video_profile profile,
+                enum pipe_video_chroma_format chroma_format,
+                unsigned width, unsigned height, void *priv);
+
+/* Other drivers can call this function in their pipe_video_context constructors and pass it
+   an accelerated pipe_context along with suitable buffering modes, etc */
+struct pipe_video_context *
+sp_video_create_ex(struct pipe_context *pipe, enum pipe_video_profile profile,
+                   enum pipe_video_chroma_format chroma_format,
+                   unsigned width, unsigned height,
+                   enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode,
+                   enum VL_MPEG12_MC_RENDERER_EMPTY_BLOCK eb_handling,
+                   bool pot_buffers,
+                   enum pipe_format decode_format);
+
+#endif /* SP_VIDEO_CONTEXT_H */
index 8b4663742fa5bd4fcfee53b4143c197095dd6907..9d5700ef439a2cb0c76d94babdccc714407595cc 100644 (file)
@@ -492,6 +492,30 @@ enum pipe_shader_cap
 #define PIPE_REFERENCED_FOR_READ  (1 << 0)
 #define PIPE_REFERENCED_FOR_WRITE (1 << 1)
 
+enum pipe_video_codec
+{
+   PIPE_VIDEO_CODEC_UNKNOWN = 0,
+   PIPE_VIDEO_CODEC_MPEG12,   /**< MPEG1, MPEG2 */
+   PIPE_VIDEO_CODEC_MPEG4,    /**< DIVX, XVID */
+   PIPE_VIDEO_CODEC_VC1,      /**< WMV */
+   PIPE_VIDEO_CODEC_MPEG4_AVC /**< H.264 */
+};
+
+enum pipe_video_profile
+{
+   PIPE_VIDEO_PROFILE_MPEG1,
+   PIPE_VIDEO_PROFILE_MPEG2_SIMPLE,
+   PIPE_VIDEO_PROFILE_MPEG2_MAIN,
+   PIPE_VIDEO_PROFILE_MPEG4_SIMPLE,
+   PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE,
+   PIPE_VIDEO_PROFILE_VC1_SIMPLE,
+   PIPE_VIDEO_PROFILE_VC1_MAIN,
+   PIPE_VIDEO_PROFILE_VC1_ADVANCED,
+   PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE,
+   PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN,
+   PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH
+};
+
 /**
  * Composite query types
  */
index 06412f4894c8ffcadde6b7b7eb9f71ea5388549b..240e349ba7e599e283e7311812196fd395a7548d 100644 (file)
@@ -186,9 +186,27 @@ enum pipe_format {
    PIPE_FORMAT_R8G8B8X8_UNORM          = 134,
    PIPE_FORMAT_B4G4R4X4_UNORM          = 135,
 
+   PIPE_FORMAT_YV12                  = 136,
+   PIPE_FORMAT_YV16                  = 137,
+   PIPE_FORMAT_IYUV                  = 138,  /**< aka I420 */
+   PIPE_FORMAT_NV12                  = 139,
+   PIPE_FORMAT_NV21                  = 140,
+   PIPE_FORMAT_AYUV                  = PIPE_FORMAT_A8R8G8B8_UNORM,
+   PIPE_FORMAT_VUYA                  = PIPE_FORMAT_B8G8R8A8_UNORM,
+   PIPE_FORMAT_XYUV                  = PIPE_FORMAT_X8R8G8B8_UNORM,
+   PIPE_FORMAT_VUYX                  = PIPE_FORMAT_B8G8R8X8_UNORM,
+   PIPE_FORMAT_IA44                  = 141,
+   PIPE_FORMAT_AI44                  = 142,
+
    PIPE_FORMAT_COUNT
 };
 
+enum pipe_video_chroma_format
+{
+   PIPE_VIDEO_CHROMA_FORMAT_420,
+   PIPE_VIDEO_CHROMA_FORMAT_422,
+   PIPE_VIDEO_CHROMA_FORMAT_444
+};
 
 #ifdef __cplusplus
 }
index 912631242f51ba52734ee5e06b8d646838374b76..2f22ac22bbf7ca1fd9eee4cadd0d1abf3f022058 100644 (file)
@@ -93,7 +93,12 @@ struct pipe_screen {
    int (*get_shader_param)( struct pipe_screen *, unsigned shader, enum pipe_shader_cap param );
 
    struct pipe_context * (*context_create)( struct pipe_screen *,
-                                           void *priv );
+                                            void *priv );
+
+   struct pipe_video_context * (*video_context_create)( struct pipe_screen *screen,
+                                                        enum pipe_video_profile profile,
+                                                        enum pipe_video_chroma_format chroma_format,
+                                                        unsigned width, unsigned height, void *priv );
 
    /**
     * Check if the given pipe_format is supported as a texture or
diff --git a/src/gallium/include/pipe/p_video_context.h b/src/gallium/include/pipe/p_video_context.h
new file mode 100644 (file)
index 0000000..294dc46
--- /dev/null
@@ -0,0 +1,178 @@
+/**************************************************************************
+ * 
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef PIPE_VIDEO_CONTEXT_H
+#define PIPE_VIDEO_CONTEXT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <pipe/p_video_state.h>
+
+/* XXX: Move to an appropriate place */
+#define PIPE_CAP_DECODE_TARGET_PREFERRED_FORMAT 256
+
+struct pipe_screen;
+struct pipe_buffer;
+struct pipe_surface;
+struct pipe_macroblock;
+struct pipe_picture_desc;
+struct pipe_fence_handle;
+
+/**
+ * Gallium video rendering context
+ */
+struct pipe_video_context
+{
+   struct pipe_screen *screen;
+   enum pipe_video_profile profile;
+   enum pipe_video_chroma_format chroma_format;
+   unsigned width;
+   unsigned height;
+
+   void *priv; /**< context private data (for DRI for example) */
+
+   /**
+    * Query an integer-valued capability/parameter/limit
+    * \param param  one of PIPE_CAP_x
+    */
+   int (*get_param)(struct pipe_video_context *vpipe, int param);
+
+   /**
+    * Check if the given pipe_format is supported as a texture or
+    * drawing surface.
+    */
+   boolean (*is_format_supported)(struct pipe_video_context *vpipe,
+                                  enum pipe_format format,
+                                  unsigned usage,
+                                  unsigned geom);
+
+   void (*destroy)(struct pipe_video_context *vpipe);
+
+   /**
+    * Picture decoding and displaying
+    */
+   /*@{*/
+   void (*decode_bitstream)(struct pipe_video_context *vpipe,
+                            unsigned num_bufs,
+                            struct pipe_buffer **bitstream_buf);
+
+   void (*decode_macroblocks)(struct pipe_video_context *vpipe,
+                              struct pipe_surface *past,
+                              struct pipe_surface *future,
+                              unsigned num_macroblocks,
+                              struct pipe_macroblock *macroblocks,
+                              struct pipe_fence_handle **fence);
+
+   void (*render_picture)(struct pipe_video_context     *vpipe,
+                          struct pipe_surface           *src_surface,
+                          enum pipe_mpeg12_picture_type picture_type,
+                          /*unsigned                    num_past_surfaces,
+                          struct pipe_surface           *past_surfaces,
+                          unsigned                      num_future_surfaces,
+                          struct pipe_surface           *future_surfaces,*/
+                          struct pipe_video_rect        *src_area,
+                          struct pipe_surface           *dst_surface,
+                          struct pipe_video_rect        *dst_area,
+                          struct pipe_fence_handle      **fence);
+
+   void (*surface_fill)(struct pipe_video_context *vpipe,
+                        struct pipe_surface *dst,
+                        unsigned dstx, unsigned dsty,
+                        unsigned width, unsigned height,
+                        unsigned value);
+
+   void (*surface_copy)(struct pipe_video_context *vpipe,
+                        struct pipe_surface *dst,
+                        unsigned dstx, unsigned dsty,
+                        struct pipe_surface *src,
+                        unsigned srcx, unsigned srcy,
+                        unsigned width, unsigned height);
+
+   struct pipe_transfer *(*get_transfer)(struct pipe_video_context *vpipe,
+                                         struct pipe_resource *resource,
+                                         struct pipe_subresource subresource,
+                                         unsigned usage,  /* a combination of PIPE_TRANSFER_x */
+                                         const struct pipe_box *box);
+
+   void (*transfer_destroy)(struct pipe_video_context *vpipe,
+                            struct pipe_transfer *transfer);
+
+   void* (*transfer_map)(struct pipe_video_context *vpipe,
+                         struct pipe_transfer *transfer);
+
+   void (*transfer_flush_region)(struct pipe_video_context *vpipe,
+                                 struct pipe_transfer *transfer,
+                                 const struct pipe_box *box);
+
+   void (*transfer_unmap)(struct pipe_video_context *vpipe,
+                          struct pipe_transfer *transfer);
+
+   void (*transfer_inline_write)(struct pipe_video_context *vpipe,
+                                 struct pipe_resource *resource,
+                                 struct pipe_subresource subresource,
+                                 unsigned usage, /* a combination of PIPE_TRANSFER_x */
+                                 const struct pipe_box *box,
+                                 const void *data,
+                                 unsigned stride,
+                                 unsigned slice_stride);
+
+   /*@}*/
+
+   /**
+    * Parameter-like states (or properties)
+    */
+   /*@{*/
+   void (*set_picture_background)(struct pipe_video_context *vpipe,
+                                  struct pipe_surface *bg,
+                                  struct pipe_video_rect *bg_src_rect);
+
+   void (*set_picture_layers)(struct pipe_video_context *vpipe,
+                              struct pipe_surface *layers[],
+                              struct pipe_video_rect *src_rects[],
+                              struct pipe_video_rect *dst_rects[],
+                              unsigned num_layers);
+
+   void (*set_picture_desc)(struct pipe_video_context *vpipe,
+                            const struct pipe_picture_desc *desc);
+
+   void (*set_decode_target)(struct pipe_video_context *vpipe,
+                             struct pipe_surface *dt);
+
+   void (*set_csc_matrix)(struct pipe_video_context *vpipe, const float *mat);
+
+   /* TODO: Interface for scaling modes, post-processing, etc. */
+   /*@}*/
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PIPE_VIDEO_CONTEXT_H */
diff --git a/src/gallium/include/pipe/p_video_state.h b/src/gallium/include/pipe/p_video_state.h
new file mode 100644 (file)
index 0000000..5eb9635
--- /dev/null
@@ -0,0 +1,132 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef PIPE_VIDEO_STATE_H
+#define PIPE_VIDEO_STATE_H
+
+#include <pipe/p_defines.h>
+#include <pipe/p_format.h>
+#include <pipe/p_state.h>
+#include <pipe/p_screen.h>
+#include <util/u_inlines.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct pipe_video_rect
+{
+   unsigned x, y, w, h;
+};
+
+enum pipe_mpeg12_picture_type
+{
+   PIPE_MPEG12_PICTURE_TYPE_FIELD_TOP,
+   PIPE_MPEG12_PICTURE_TYPE_FIELD_BOTTOM,
+   PIPE_MPEG12_PICTURE_TYPE_FRAME
+};
+
+enum pipe_mpeg12_macroblock_type
+{
+   PIPE_MPEG12_MACROBLOCK_TYPE_INTRA,
+   PIPE_MPEG12_MACROBLOCK_TYPE_FWD,
+   PIPE_MPEG12_MACROBLOCK_TYPE_BKWD,
+   PIPE_MPEG12_MACROBLOCK_TYPE_BI,
+
+   PIPE_MPEG12_MACROBLOCK_NUM_TYPES
+};
+
+enum pipe_mpeg12_motion_type
+{
+   PIPE_MPEG12_MOTION_TYPE_FIELD,
+   PIPE_MPEG12_MOTION_TYPE_FRAME,
+   PIPE_MPEG12_MOTION_TYPE_DUALPRIME,
+   PIPE_MPEG12_MOTION_TYPE_16x8
+};
+
+enum pipe_mpeg12_dct_type
+{
+   PIPE_MPEG12_DCT_TYPE_FIELD,
+   PIPE_MPEG12_DCT_TYPE_FRAME
+};
+
+struct pipe_macroblock
+{
+   enum pipe_video_codec codec;
+};
+
+struct pipe_mpeg12_macroblock
+{
+   struct pipe_macroblock base;
+
+   unsigned mbx;
+   unsigned mby;
+   enum pipe_mpeg12_macroblock_type mb_type;
+   enum pipe_mpeg12_motion_type mo_type;
+   enum pipe_mpeg12_dct_type dct_type;
+   signed pmv[2][2][2];
+   unsigned cbp;
+   short *blocks;
+};
+
+#if 0
+struct pipe_picture_desc
+{
+   enum pipe_video_format format;
+};
+
+struct pipe_mpeg12_picture_desc
+{
+   struct pipe_picture_desc base;
+
+   /* TODO: Use bitfields where possible? */
+   struct pipe_surface *forward_reference;
+   struct pipe_surface *backward_reference;
+   unsigned picture_coding_type;
+   unsigned fcode;
+   unsigned intra_dc_precision;
+   unsigned picture_structure;
+   unsigned top_field_first;
+   unsigned frame_pred_frame_dct;
+   unsigned concealment_motion_vectors;
+   unsigned q_scale_type;
+   unsigned intra_vlc_format;
+   unsigned alternate_scan;
+   unsigned full_pel_forward_vector;
+   unsigned full_pel_backward_vector;
+   struct pipe_buffer *intra_quantizer_matrix;
+   struct pipe_buffer *non_intra_quantizer_matrix;
+   struct pipe_buffer *chroma_intra_quantizer_matrix;
+   struct pipe_buffer *chroma_non_intra_quantizer_matrix;
+};
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PIPE_VIDEO_STATE_H */
diff --git a/src/gallium/state_trackers/vdpau/Makefile b/src/gallium/state_trackers/vdpau/Makefile
new file mode 100644 (file)
index 0000000..346cce9
--- /dev/null
@@ -0,0 +1,15 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = vdpautracker
+
+LIBRARY_INCLUDES = \
+       $(shell pkg-config --cflags-only-I vdpau) \
+       -I$(TOP)/src/gallium/winsys/g3dvl
+
+C_SOURCES = htab.c \
+           ftab.c \
+           device.c \
+           query.c
+
+include ../../Makefile.template
diff --git a/src/gallium/state_trackers/vdpau/device.c b/src/gallium/state_trackers/vdpau/device.c
new file mode 100644 (file)
index 0000000..83fcaff
--- /dev/null
@@ -0,0 +1,98 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <vdpau/vdpau_x11.h>
+#include <pipe/p_compiler.h>
+#include <vl_winsys.h>
+#include <util/u_memory.h>
+#include "vdpau_private.h"
+
+VdpDeviceCreateX11 vdp_imp_device_create_x11;
+
+PUBLIC VdpStatus
+vdp_imp_device_create_x11(Display *display, int screen, VdpDevice *device, VdpGetProcAddress **get_proc_address)
+{
+   VdpStatus    ret;
+   vlVdpDevice *dev;
+
+   if (!(display && device && get_proc_address))
+      return VDP_STATUS_INVALID_POINTER;
+
+   if (!vlCreateHTAB()) {
+      ret = VDP_STATUS_RESOURCES;
+      goto no_htab;
+   }
+
+   dev = CALLOC(1, sizeof(vlVdpDevice));
+   if (!dev) {
+      ret = VDP_STATUS_RESOURCES;
+      goto no_dev;
+   }
+
+   *device = vlAddDataHTAB(dev);
+   if (*device == 0) {
+      ret = VDP_STATUS_ERROR;
+      goto no_handle;
+   }
+
+   *get_proc_address = &vlVdpGetProcAddress;
+
+   return VDP_STATUS_OK;
+
+no_handle:
+   FREE(dev);
+no_dev:
+   vlDestroyHTAB();
+no_htab:
+   return ret;
+}
+
+VdpStatus vlVdpDeviceDestroy(VdpDevice device)
+{
+   vlVdpDevice *dev = vlGetDataHTAB(device);
+   if (!dev)
+      return VDP_STATUS_INVALID_HANDLE;
+   FREE(dev);
+   vlDestroyHTAB();
+
+   return VDP_STATUS_OK;
+}
+
+VdpStatus vlVdpGetProcAddress(VdpDevice device, VdpFuncId function_id, void **function_pointer)
+{
+   vlVdpDevice *dev = vlGetDataHTAB(device);
+   if (!dev)
+      return VDP_STATUS_INVALID_HANDLE;
+
+   if (!function_pointer)
+      return VDP_STATUS_INVALID_POINTER;
+
+   if (!vlGetFuncFTAB(function_id, function_pointer))
+      return VDP_STATUS_INVALID_FUNC_ID;
+
+   return VDP_STATUS_OK;
+}
diff --git a/src/gallium/state_trackers/vdpau/ftab.c b/src/gallium/state_trackers/vdpau/ftab.c
new file mode 100644 (file)
index 0000000..a8a2985
--- /dev/null
@@ -0,0 +1,122 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include "vdpau_private.h"
+
+static void* ftab[67] =
+{
+   0, /* VDP_FUNC_ID_GET_ERROR_STRING */
+   0, /* VDP_FUNC_ID_GET_PROC_ADDRESS */
+   &vlVdpGetApiVersion, /* VDP_FUNC_ID_GET_API_VERSION */
+   0,
+   &vlVdpGetInformationString, /* VDP_FUNC_ID_GET_INFORMATION_STRING */
+   &vlVdpDeviceDestroy, /* VDP_FUNC_ID_DEVICE_DESTROY */
+   0, /* VDP_FUNC_ID_GENERATE_CSC_MATRIX */
+   &vlVdpVideoSurfaceQueryCapabilities, /* VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES */
+   &vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities, /* VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES */
+   0, /* VDP_FUNC_ID_VIDEO_SURFACE_CREATE */
+   0, /* VDP_FUNC_ID_VIDEO_SURFACE_DESTROY */
+   0, /* VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS */
+   0, /* VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR */
+   0, /* VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR */
+   &vlVdpOutputSurfaceQueryCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES */
+   &vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_GET_PUT_BITS_NATIVE_CAPABILITIES */
+   0, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_INDEXED_CAPABILITIES */
+   &vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_Y_CB_CR_CAPABILITIES */
+   0, /* VDP_FUNC_ID_OUTPUT_SURFACE_CREATE */
+   0, /* VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY */
+   0, /* VDP_FUNC_ID_OUTPUT_SURFACE_GET_PARAMETERS */
+   0, /* VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE */
+   0, /* VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE */
+   0, /* VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED */
+   0, /* VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR */
+   &vlVdpBitmapSurfaceQueryCapabilities, /* VDP_FUNC_ID_BITMAP_SURFACE_QUERY_CAPABILITIES */
+   0, /* VDP_FUNC_ID_BITMAP_SURFACE_CREATE */
+   0, /* VDP_FUNC_ID_BITMAP_SURFACE_DESTROY */
+   0, /* VDP_FUNC_ID_BITMAP_SURFACE_GET_PARAMETERS */
+   0, /* VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE */
+   0,
+   0,
+   0,
+   0, /* VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE */
+   0, /* VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE */
+   0, /* VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_VIDEO_SURFACE_LUMA */
+   &vlVdpDecoderQueryCapabilities, /* VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES */
+   0, /* VDP_FUNC_ID_DECODER_CREATE */
+   0, /* VDP_FUNC_ID_DECODER_DESTROY */
+   0, /* VDP_FUNC_ID_DECODER_GET_PARAMETERS */
+   0, /* VDP_FUNC_ID_DECODER_RENDER */
+   &vlVdpVideoMixerQueryFeatureSupport, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT */
+   &vlVdpVideoMixerQueryParameterSupport, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT */
+   &vlVdpVideoMixerQueryAttributeSupport, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT */
+   &vlVdpVideoMixerQueryParameterValueRange, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE */
+   &vlVdpVideoMixerQueryAttributeValueRange, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE */
+   0, /* VDP_FUNC_ID_VIDEO_MIXER_CREATE */
+   0, /* VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES */
+   0, /* VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES */
+   0, /* VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_SUPPORT */
+   0, /* VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_ENABLES */
+   0, /* VDP_FUNC_ID_VIDEO_MIXER_GET_PARAMETER_VALUES */
+   0, /* VDP_FUNC_ID_VIDEO_MIXER_GET_ATTRIBUTE_VALUES */
+   0, /* VDP_FUNC_ID_VIDEO_MIXER_DESTROY */
+   0, /* VDP_FUNC_ID_VIDEO_MIXER_RENDER */
+   0, /* VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY */
+   0, /* VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE */
+   0, /* VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY */
+   0, /* VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR */
+   0, /* VDP_FUNC_ID_PRESENTATION_QUEUE_GET_BACKGROUND_COLOR */
+   0,
+   0,
+   0, /* VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME */
+   0, /* VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY */
+   0, /* VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE */
+   0, /* VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS */
+   0  /* VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER */
+};
+
+static void* ftab_winsys[1] =
+{
+   0  /* VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 */
+};
+
+boolean vlGetFuncFTAB(VdpFuncId function_id, void **func)
+{
+   assert(func);
+   if (function_id < VDP_FUNC_ID_BASE_WINSYS) {
+      if (function_id > 66)
+         return FALSE;
+      *func = ftab[function_id];
+   }
+   else {
+      function_id -= VDP_FUNC_ID_BASE_WINSYS;
+      if (function_id > 0)
+        return FALSE;
+      *func = ftab_winsys[function_id];
+   }
+   return TRUE;
+}
diff --git a/src/gallium/state_trackers/vdpau/htab.c b/src/gallium/state_trackers/vdpau/htab.c
new file mode 100644 (file)
index 0000000..0c95805
--- /dev/null
@@ -0,0 +1,94 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <util/u_handle_table.h>
+#include <os/os_thread.h>
+#include "vdpau_private.h"
+
+#ifdef VL_HANDLES
+static struct handle_table *htab = NULL;
+pipe_static_mutex(htab_lock);
+#endif
+
+boolean vlCreateHTAB(void)
+{
+#ifdef VL_HANDLES
+   boolean ret;
+   /* Make sure handle table handles match VDPAU handles. */
+   assert(sizeof(unsigned) <= sizeof(vlHandle));
+   pipe_mutex_lock(htab_lock);
+   if (!htab)
+      htab = handle_table_create();
+   ret = htab != NULL;
+   pipe_mutex_unlock(htab_lock);
+   return ret;
+#else
+   return TRUE;
+#endif
+}
+
+void vlDestroyHTAB(void)
+{
+#ifdef VL_HANDLES
+   pipe_mutex_lock(htab_lock);
+   if (htab) {
+      handle_table_destroy(htab);
+      htab = NULL;
+   }
+   pipe_mutex_unlock(htab_lock);
+#endif
+}
+
+vlHandle vlAddDataHTAB(void *data)
+{
+   assert(data);
+#ifdef VL_HANDLES
+   vlHandle handle = 0;
+   pipe_mutex_lock(htab_lock);
+   if (htab)
+      handle = handle_table_add(htab, data);
+   pipe_mutex_unlock(htab_lock);
+   return handle;
+#else
+   return (vlHandle)data;
+#endif
+}
+
+void* vlGetDataHTAB(vlHandle handle)
+{
+   assert(handle);
+#ifdef VL_HANDLES
+   void *data = NULL;
+   pipe_mutex_lock(htab_lock);
+   if (htab)
+      data = handle_table_get(htab, handle);
+   pipe_mutex_unlock(htab_lock);
+   return data;
+#else
+   return (void*)handle;
+#endif
+}
diff --git a/src/gallium/state_trackers/vdpau/query.c b/src/gallium/state_trackers/vdpau/query.c
new file mode 100644 (file)
index 0000000..57bd7fb
--- /dev/null
@@ -0,0 +1,171 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vdpau_private.h"
+
+VdpStatus
+vlVdpGetApiVersion(uint32_t *api_version)
+{
+   if (!api_version)
+      return VDP_STATUS_INVALID_POINTER;
+
+   *api_version = 1;
+   return VDP_STATUS_OK;
+}
+
+VdpStatus
+vlVdpGetInformationString(char const **information_string)
+{
+   if (!information_string)
+      return VDP_STATUS_INVALID_POINTER;
+
+   *information_string = "VDPAU-G3DVL";
+   return VDP_STATUS_OK;
+}
+
+VdpStatus
+vlVdpVideoSurfaceQueryCapabilities(VdpDevice device, VdpChromaType surface_chroma_type,
+                                   VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height)
+{
+   if (!(is_supported && max_width && max_height))
+      return VDP_STATUS_INVALID_POINTER;
+
+   return VDP_STATUS_NO_IMPLEMENTATION;
+}
+
+VdpStatus
+vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities(VdpDevice device, VdpChromaType surface_chroma_type,
+                                                  VdpYCbCrFormat bits_ycbcr_format,
+                                                  VdpBool *is_supported)
+{
+   if (!is_supported)
+      return VDP_STATUS_INVALID_POINTER;
+
+   return VDP_STATUS_NO_IMPLEMENTATION;
+}
+
+VdpStatus
+vlVdpDecoderQueryCapabilities(VdpDevice device, VdpDecoderProfile profile,
+                              VdpBool *is_supported, uint32_t *max_level, uint32_t *max_macroblocks,
+                              uint32_t *max_width, uint32_t *max_height)
+{
+   if (!(is_supported && max_level && max_macroblocks && max_width && max_height))
+      return VDP_STATUS_INVALID_POINTER;
+
+   return VDP_STATUS_NO_IMPLEMENTATION;
+}
+
+VdpStatus
+vlVdpOutputSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
+                                    VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height)
+{
+   if (!(is_supported && max_width && max_height))
+      return VDP_STATUS_INVALID_POINTER;
+
+   return VDP_STATUS_NO_IMPLEMENTATION;
+}
+
+VdpStatus
+vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
+                                                    VdpBool *is_supported)
+{
+   if (!is_supported)
+      return VDP_STATUS_INVALID_POINTER;
+
+   return VDP_STATUS_NO_IMPLEMENTATION;
+}
+
+VdpStatus
+vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
+                                                VdpYCbCrFormat bits_ycbcr_format,
+                                                VdpBool *is_supported)
+{
+   if (!is_supported)
+      return VDP_STATUS_INVALID_POINTER;
+
+   return VDP_STATUS_NO_IMPLEMENTATION;
+}
+
+VdpStatus
+vlVdpBitmapSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
+                                    VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height)
+{
+   if (!(is_supported && max_width && max_height))
+      return VDP_STATUS_INVALID_POINTER;
+
+   return VDP_STATUS_NO_IMPLEMENTATION;
+}
+
+VdpStatus
+vlVdpVideoMixerQueryFeatureSupport(VdpDevice device, VdpVideoMixerFeature feature,
+                                   VdpBool *is_supported)
+{
+   if (!is_supported)
+      return VDP_STATUS_INVALID_POINTER;
+
+   return VDP_STATUS_NO_IMPLEMENTATION;
+}
+
+VdpStatus
+vlVdpVideoMixerQueryParameterSupport(VdpDevice device, VdpVideoMixerParameter parameter,
+                                     VdpBool *is_supported)
+{
+   if (!is_supported)
+      return VDP_STATUS_INVALID_POINTER;
+
+   return VDP_STATUS_NO_IMPLEMENTATION;
+}
+
+VdpStatus
+vlVdpVideoMixerQueryParameterValueRange(VdpDevice device, VdpVideoMixerParameter parameter,
+                                        void *min_value, void *max_value)
+{
+   if (!(min_value && max_value))
+      return VDP_STATUS_INVALID_POINTER;
+
+   return VDP_STATUS_NO_IMPLEMENTATION;
+}
+
+VdpStatus
+vlVdpVideoMixerQueryAttributeSupport(VdpDevice device, VdpVideoMixerAttribute attribute,
+                                     VdpBool *is_supported)
+{
+   if (!is_supported)
+      return VDP_STATUS_INVALID_POINTER;
+
+   return VDP_STATUS_NO_IMPLEMENTATION;
+}
+
+VdpStatus
+vlVdpVideoMixerQueryAttributeValueRange(VdpDevice device, VdpVideoMixerAttribute attribute,
+                                        void *min_value, void *max_value)
+{
+   if (!(min_value && max_value))
+      return VDP_STATUS_INVALID_POINTER;
+
+   return VDP_STATUS_NO_IMPLEMENTATION;
+}
diff --git a/src/gallium/state_trackers/vdpau/vdpau_private.h b/src/gallium/state_trackers/vdpau/vdpau_private.h
new file mode 100644 (file)
index 0000000..8f54ae6
--- /dev/null
@@ -0,0 +1,59 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <vdpau/vdpau.h>
+#include <pipe/p_compiler.h>
+
+typedef struct
+{
+   int dummy;
+} vlVdpDevice;
+
+typedef uint32_t vlHandle;
+
+boolean vlCreateHTAB(void);
+void vlDestroyHTAB(void);
+vlHandle vlAddDataHTAB(void *data);
+void* vlGetDataHTAB(vlHandle handle);
+boolean vlGetFuncFTAB(VdpFuncId function_id, void **func);
+
+VdpDeviceDestroy vlVdpDeviceDestroy;
+VdpGetProcAddress vlVdpGetProcAddress;
+VdpGetApiVersion vlVdpGetApiVersion;
+VdpGetInformationString vlVdpGetInformationString;
+VdpVideoSurfaceQueryCapabilities vlVdpVideoSurfaceQueryCapabilities;
+VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities;
+VdpDecoderQueryCapabilities vlVdpDecoderQueryCapabilities;
+VdpOutputSurfaceQueryCapabilities vlVdpOutputSurfaceQueryCapabilities;
+VdpOutputSurfaceQueryGetPutBitsNativeCapabilities vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities;
+VdpOutputSurfaceQueryPutBitsYCbCrCapabilities vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities;
+VdpBitmapSurfaceQueryCapabilities vlVdpBitmapSurfaceQueryCapabilities;
+VdpVideoMixerQueryFeatureSupport vlVdpVideoMixerQueryFeatureSupport;
+VdpVideoMixerQueryParameterSupport vlVdpVideoMixerQueryParameterSupport;
+VdpVideoMixerQueryParameterValueRange vlVdpVideoMixerQueryParameterValueRange;
+VdpVideoMixerQueryAttributeSupport vlVdpVideoMixerQueryAttributeSupport;
+VdpVideoMixerQueryAttributeValueRange vlVdpVideoMixerQueryAttributeValueRange;
diff --git a/src/gallium/state_trackers/xorg/xvmc/Makefile b/src/gallium/state_trackers/xorg/xvmc/Makefile
new file mode 100644 (file)
index 0000000..126dc6d
--- /dev/null
@@ -0,0 +1,16 @@
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = xvmctracker
+
+LIBRARY_INCLUDES = \
+       $(shell pkg-config --cflags-only-I xvmc) \
+       -I$(TOP)/src/gallium/winsys/g3dvl
+
+C_SOURCES = block.c \
+            surface.c \
+            context.c \
+            subpicture.c \
+            attributes.c
+
+include ../../../Makefile.template
diff --git a/src/gallium/state_trackers/xorg/xvmc/attributes.c b/src/gallium/state_trackers/xorg/xvmc/attributes.c
new file mode 100644 (file)
index 0000000..d23d863
--- /dev/null
@@ -0,0 +1,50 @@
+/**************************************************************************
+ * 
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XvMClib.h>
+#include <pipe/p_compiler.h>
+
+PUBLIC
+XvAttribute* XvMCQueryAttributes(Display *dpy, XvMCContext *context, int *number)
+{
+   return NULL;
+}
+
+PUBLIC
+Status XvMCSetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int value)
+{
+   return BadImplementation;
+}
+
+PUBLIC
+Status XvMCGetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int *value)
+{
+   return BadImplementation;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/block.c b/src/gallium/state_trackers/xorg/xvmc/block.c
new file mode 100644 (file)
index 0000000..c7da7a8
--- /dev/null
@@ -0,0 +1,92 @@
+/**************************************************************************
+ * 
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMClib.h>
+#include <util/u_memory.h>
+#include "xvmc_private.h"
+
+PUBLIC
+Status XvMCCreateBlocks(Display *dpy, XvMCContext *context, unsigned int num_blocks, XvMCBlockArray *blocks)
+{
+   assert(dpy);
+
+   if (!context)
+      return XvMCBadContext;
+   if (num_blocks == 0)
+      return BadValue;
+
+   assert(blocks);
+
+   blocks->context_id = context->context_id;
+   blocks->num_blocks = num_blocks;
+   blocks->blocks = MALLOC(BLOCK_SIZE_BYTES * num_blocks);
+   blocks->privData = NULL;
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCDestroyBlocks(Display *dpy, XvMCBlockArray *blocks)
+{
+   assert(dpy);
+   assert(blocks);
+   FREE(blocks->blocks);
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCCreateMacroBlocks(Display *dpy, XvMCContext *context, unsigned int num_blocks, XvMCMacroBlockArray *blocks)
+{
+   assert(dpy);
+
+   if (!context)
+      return XvMCBadContext;
+   if (num_blocks == 0)
+      return BadValue;
+
+   assert(blocks);
+
+   blocks->context_id = context->context_id;
+   blocks->num_blocks = num_blocks;
+   blocks->macro_blocks = MALLOC(sizeof(XvMCMacroBlock) * num_blocks);
+   blocks->privData = NULL;
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCDestroyMacroBlocks(Display *dpy, XvMCMacroBlockArray *blocks)
+{
+   assert(dpy);
+   assert(blocks);
+   FREE(blocks->macro_blocks);
+
+   return Success;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/context.c b/src/gallium/state_trackers/xorg/xvmc/context.c
new file mode 100644 (file)
index 0000000..5e4af9e
--- /dev/null
@@ -0,0 +1,298 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <X11/Xlibint.h>
+#include <X11/extensions/XvMClib.h>
+#include <pipe/p_screen.h>
+#include <pipe/p_video_context.h>
+#include <pipe/p_video_state.h>
+#include <pipe/p_state.h>
+#include <vl_winsys.h>
+#include <util/u_memory.h>
+#include <vl/vl_csc.h>
+#include "xvmc_private.h"
+
+static Status Validate(Display *dpy, XvPortID port, int surface_type_id,
+                       unsigned int width, unsigned int height, int flags,
+                       bool *found_port, int *screen, int *chroma_format,
+                       int *mc_type, int *surface_flags,
+                       unsigned short *subpic_max_w,
+                       unsigned short *subpic_max_h)
+{
+   bool found_surface = false;
+   XvAdaptorInfo *adaptor_info;
+   unsigned int num_adaptors;
+   int num_types;
+   unsigned int max_width, max_height;
+   Status ret;
+
+   assert(dpy);
+   assert(found_port);
+   assert(screen);
+   assert(chroma_format);
+   assert(mc_type);
+   assert(surface_flags);
+   assert(subpic_max_w);
+   assert(subpic_max_h);
+
+   *found_port = false;
+
+   for (unsigned int i = 0; i < XScreenCount(dpy); ++i) {
+      ret = XvQueryAdaptors(dpy, XRootWindow(dpy, i), &num_adaptors, &adaptor_info);
+      if (ret != Success)
+         return ret;
+
+      for (unsigned int j = 0; j < num_adaptors && !*found_port; ++j) {
+         for (unsigned int k = 0; k < adaptor_info[j].num_ports && !*found_port; ++k) {
+            XvMCSurfaceInfo *surface_info;
+
+            if (adaptor_info[j].base_id + k != port)
+               continue;
+
+            *found_port = true;
+
+            surface_info = XvMCListSurfaceTypes(dpy, adaptor_info[j].base_id, &num_types);
+            if (!surface_info) {
+               XvFreeAdaptorInfo(adaptor_info);
+               return BadAlloc;
+            }
+
+            for (unsigned int l = 0; l < num_types && !found_surface; ++l) {
+               if (surface_info[l].surface_type_id != surface_type_id)
+                  continue;
+
+               found_surface = true;
+               max_width = surface_info[l].max_width;
+               max_height = surface_info[l].max_height;
+               *chroma_format = surface_info[l].chroma_format;
+               *mc_type = surface_info[l].mc_type;
+               *surface_flags = surface_info[l].flags;
+               *subpic_max_w = surface_info[l].subpicture_max_width;
+               *subpic_max_h = surface_info[l].subpicture_max_height;
+               *screen = i;
+
+               XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested context surface format.\n" \
+                                    "[XvMC]   screen=%u, port=%u\n" \
+                                    "[XvMC]   id=0x%08X\n" \
+                                    "[XvMC]   max width=%u, max height=%u\n" \
+                                    "[XvMC]   chroma format=0x%08X\n" \
+                                    "[XvMC]   acceleration level=0x%08X\n" \
+                                    "[XvMC]   flags=0x%08X\n" \
+                                    "[XvMC]   subpicture max width=%u, max height=%u\n",
+                                    i, port, surface_type_id, max_width, max_height, *chroma_format,
+                                    *mc_type, *surface_flags, *subpic_max_w, *subpic_max_h);
+            }
+
+            XFree(surface_info);
+         }
+      }
+
+      XvFreeAdaptorInfo(adaptor_info);
+   }
+
+   if (!*found_port) {
+      XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable port.\n");
+      return XvBadPort;
+   }
+   if (!found_surface) {
+      XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable surface.\n");
+      return BadMatch;
+   }
+   if (width > max_width || height > max_height) {
+      XVMC_MSG(XVMC_ERR, "[XvMC] Requested context dimensions (w=%u,h=%u) too large (max w=%u,h=%u).\n",
+               width, height, max_width, max_height);
+      return BadValue;
+   }
+   if (flags != XVMC_DIRECT && flags != 0) {
+      XVMC_MSG(XVMC_ERR, "[XvMC] Invalid context flags 0x%08X.\n", flags);
+      return BadValue;
+   }
+
+   return Success;
+}
+
+static enum pipe_video_profile ProfileToPipe(int xvmc_profile)
+{
+   if (xvmc_profile & XVMC_MPEG_1)
+      assert(0);
+   if (xvmc_profile & XVMC_MPEG_2)
+      return PIPE_VIDEO_PROFILE_MPEG2_MAIN;
+   if (xvmc_profile & XVMC_H263)
+      assert(0);
+   if (xvmc_profile & XVMC_MPEG_4)
+      assert(0);
+
+   assert(0);
+
+   XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized profile 0x%08X.\n", xvmc_profile);
+
+   return -1;
+}
+
+static enum pipe_video_chroma_format FormatToPipe(int xvmc_format)
+{
+   switch (xvmc_format) {
+      case XVMC_CHROMA_FORMAT_420:
+         return PIPE_VIDEO_CHROMA_FORMAT_420;
+      case XVMC_CHROMA_FORMAT_422:
+         return PIPE_VIDEO_CHROMA_FORMAT_422;
+      case XVMC_CHROMA_FORMAT_444:
+         return PIPE_VIDEO_CHROMA_FORMAT_444;
+      default:
+         assert(0);
+   }
+
+   XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized format 0x%08X.\n", xvmc_format);
+
+   return -1;
+}
+
+PUBLIC
+Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id,
+                         int width, int height, int flags, XvMCContext *context)
+{
+   bool found_port;
+   int scrn;
+   int chroma_format;
+   int mc_type;
+   int surface_flags;
+   unsigned short subpic_max_w;
+   unsigned short subpic_max_h;
+   Status ret;
+   struct vl_screen *vscreen;
+   struct vl_context *vctx;
+   XvMCContextPrivate *context_priv;
+   float csc[16];
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Creating context %p.\n", context);
+
+   assert(dpy);
+
+   if (!context)
+      return XvMCBadContext;
+
+   ret = Validate(dpy, port, surface_type_id, width, height, flags,
+                  &found_port, &scrn, &chroma_format, &mc_type, &surface_flags,
+                  &subpic_max_w, &subpic_max_h);
+
+   /* Success and XvBadPort have the same value */
+   if (ret != Success || !found_port)
+      return ret;
+
+   /* XXX: Current limits */
+   if (chroma_format != XVMC_CHROMA_FORMAT_420) {
+      XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsupported chroma format.\n");
+      return BadImplementation;
+   }
+   if (mc_type != (XVMC_MOCOMP | XVMC_MPEG_2)) {
+      XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Non-MPEG2/Mocomp acceleration unsupported.\n");
+      return BadImplementation;
+   }
+   if (!(surface_flags & XVMC_INTRA_UNSIGNED)) {
+      XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Signed intra unsupported.\n");
+      return BadImplementation;
+   }
+
+   context_priv = CALLOC(1, sizeof(XvMCContextPrivate));
+   if (!context_priv)
+      return BadAlloc;
+
+   /* TODO: Reuse screen if process creates another context */
+   vscreen = vl_screen_create(dpy, scrn);
+
+   if (!vscreen) {
+      XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL screen.\n");
+      FREE(context_priv);
+      return BadAlloc;
+   }
+
+   vctx = vl_video_create(vscreen, ProfileToPipe(mc_type),
+                          FormatToPipe(chroma_format), width, height);
+
+   if (!vctx) {
+      XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL context.\n");
+      vl_screen_destroy(vscreen);
+      FREE(context_priv);
+      return BadAlloc;
+   }
+
+   /* TODO: Define some Xv attribs to allow users to specify color standard, procamp */
+   vl_csc_get_matrix
+   (
+      debug_get_bool_option("G3DVL_NO_CSC", FALSE) ?
+      VL_CSC_COLOR_STANDARD_IDENTITY : VL_CSC_COLOR_STANDARD_BT_601,
+      NULL, true, csc
+   );
+   vctx->vpipe->set_csc_matrix(vctx->vpipe, csc);
+
+   context_priv->vctx = vctx;
+   context_priv->subpicture_max_width = subpic_max_w;
+   context_priv->subpicture_max_height = subpic_max_h;
+
+   context->context_id = XAllocID(dpy);
+   context->surface_type_id = surface_type_id;
+   context->width = width;
+   context->height = height;
+   context->flags = flags;
+   context->port = port;
+   context->privData = context_priv;
+
+   SyncHandle();
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p created.\n", context);
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCDestroyContext(Display *dpy, XvMCContext *context)
+{
+   struct vl_screen *vscreen;
+   struct vl_context *vctx;
+   XvMCContextPrivate *context_priv;
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying context %p.\n", context);
+
+   assert(dpy);
+
+   if (!context || !context->privData)
+      return XvMCBadContext;
+
+   context_priv = context->privData;
+   vctx = context_priv->vctx;
+   pipe_surface_reference(&context_priv->backbuffer, NULL);
+   vscreen = vctx->vscreen;
+   vl_video_destroy(vctx);
+   vl_screen_destroy(vscreen);
+   FREE(context_priv);
+   context->privData = NULL;
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p destroyed.\n", context);
+
+   return Success;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/subpicture.c b/src/gallium/state_trackers/xorg/xvmc/subpicture.c
new file mode 100644 (file)
index 0000000..e0c9e30
--- /dev/null
@@ -0,0 +1,440 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <X11/Xlibint.h>
+#include <X11/extensions/XvMClib.h>
+#include <xorg/fourcc.h>
+#include <vl_winsys.h>
+#include <pipe/p_screen.h>
+#include <pipe/p_video_context.h>
+#include <pipe/p_state.h>
+#include <util/u_memory.h>
+#include <util/u_math.h>
+#include "xvmc_private.h"
+
+#define FOURCC_RGB 0x0000003
+
+static enum pipe_format XvIDToPipe(int xvimage_id)
+{
+   switch (xvimage_id) {
+      case FOURCC_RGB:
+         return PIPE_FORMAT_B8G8R8X8_UNORM;
+      default:
+         XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id);
+         return PIPE_FORMAT_NONE;
+   }
+}
+
+static int PipeToComponentOrder(enum pipe_format format, char *component_order)
+{
+   assert(component_order);
+
+   switch (format) {
+      case PIPE_FORMAT_B8G8R8X8_UNORM:
+         return 0;
+      default:
+         XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized PIPE_FORMAT 0x%08X.\n", format);
+         component_order[0] = 0;
+         component_order[1] = 0;
+         component_order[2] = 0;
+         component_order[3] = 0;
+   }
+
+      return 0;
+}
+
+static Status Validate(Display *dpy, XvPortID port, int surface_type_id, int xvimage_id)
+{
+   XvImageFormatValues *subpictures;
+   int num_subpics;
+   unsigned int i;
+
+   subpictures = XvMCListSubpictureTypes(dpy, port, surface_type_id, &num_subpics);
+   if (num_subpics < 1) {
+      if (subpictures)
+         XFree(subpictures);
+      return BadMatch;
+   }
+   if (!subpictures)
+      return BadAlloc;
+
+   for (i = 0; i < num_subpics; ++i) {
+      if (subpictures[i].id == xvimage_id) {
+         XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested subpicture format.\n" \
+                              "[XvMC]   port=%u\n" \
+                              "[XvMC]   surface id=0x%08X\n" \
+                              "[XvMC]   image id=0x%08X\n" \
+                              "[XvMC]   type=%08X\n" \
+                              "[XvMC]   byte order=%08X\n" \
+                              "[XvMC]   bits per pixel=%u\n" \
+                              "[XvMC]   format=%08X\n" \
+                              "[XvMC]   num planes=%d\n",
+                              port, surface_type_id, xvimage_id, subpictures[i].type, subpictures[i].byte_order,
+                              subpictures[i].bits_per_pixel, subpictures[i].format, subpictures[i].num_planes);
+         if (subpictures[i].type == XvRGB) {
+            XVMC_MSG(XVMC_TRACE, "[XvMC]   depth=%d\n" \
+                                 "[XvMC]   red mask=0x%08X\n" \
+                                 "[XvMC]   green mask=0x%08X\n" \
+                                 "[XvMC]   blue mask=0x%08X\n",
+                                 subpictures[i].depth, subpictures[i].red_mask, subpictures[i].green_mask, subpictures[i].blue_mask);
+         }
+         else if (subpictures[i].type == XvYUV) {
+            XVMC_MSG(XVMC_TRACE, "[XvMC]   y sample bits=0x%08X\n" \
+                                 "[XvMC]   u sample bits=0x%08X\n" \
+                                 "[XvMC]   v sample bits=0x%08X\n" \
+                                 "[XvMC]   horz y period=%u\n" \
+                                 "[XvMC]   horz u period=%u\n" \
+                                 "[XvMC]   horz v period=%u\n" \
+                                 "[XvMC]   vert y period=%u\n" \
+                                 "[XvMC]   vert u period=%u\n" \
+                                 "[XvMC]   vert v period=%u\n",
+                                 subpictures[i].y_sample_bits, subpictures[i].u_sample_bits, subpictures[i].v_sample_bits,
+                                 subpictures[i].horz_y_period, subpictures[i].horz_u_period, subpictures[i].horz_v_period,
+                                 subpictures[i].vert_y_period, subpictures[i].vert_u_period, subpictures[i].vert_v_period);
+         }
+         break;
+      }
+   }
+
+   XFree(subpictures);
+
+   return i < num_subpics ? Success : BadMatch;
+}
+
+PUBLIC
+Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *subpicture,
+                            unsigned short width, unsigned short height, int xvimage_id)
+{
+   XvMCContextPrivate *context_priv;
+   XvMCSubpicturePrivate *subpicture_priv;
+   struct pipe_video_context *vpipe;
+   struct pipe_resource template;
+   struct pipe_resource *tex;
+   Status ret;
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Creating subpicture %p.\n", subpicture);
+
+   assert(dpy);
+
+   if (!context)
+      return XvMCBadContext;
+
+   context_priv = context->privData;
+   vpipe = context_priv->vctx->vpipe;
+
+   if (!subpicture)
+      return XvMCBadSubpicture;
+
+   if (width > context_priv->subpicture_max_width ||
+       height > context_priv->subpicture_max_height)
+      return BadValue;
+
+   ret = Validate(dpy, context->port, context->surface_type_id, xvimage_id);
+   if (ret != Success)
+      return ret;
+
+   subpicture_priv = CALLOC(1, sizeof(XvMCSubpicturePrivate));
+   if (!subpicture_priv)
+      return BadAlloc;
+
+   memset(&template, 0, sizeof(struct pipe_resource));
+   template.target = PIPE_TEXTURE_2D;
+   template.format = XvIDToPipe(xvimage_id);
+   template.last_level = 0;
+   if (vpipe->get_param(vpipe, PIPE_CAP_NPOT_TEXTURES)) {
+      template.width0 = width;
+      template.height0 = height;
+   }
+   else {
+      template.width0 = util_next_power_of_two(width);
+      template.height0 = util_next_power_of_two(height);
+   }
+   template.depth0 = 1;
+   template.usage = PIPE_USAGE_DYNAMIC;
+   template.bind = PIPE_BIND_SAMPLER_VIEW;
+   template.flags = 0;
+
+   subpicture_priv->context = context;
+   tex = vpipe->screen->resource_create(vpipe->screen, &template);
+   subpicture_priv->sfc = vpipe->screen->get_tex_surface(vpipe->screen, tex, 0, 0, 0,
+                                                         PIPE_BIND_SAMPLER_VIEW);
+   pipe_resource_reference(&tex, NULL);
+   if (!subpicture_priv->sfc) {
+      FREE(subpicture_priv);
+      return BadAlloc;
+   }
+
+   subpicture->subpicture_id = XAllocID(dpy);
+   subpicture->context_id = context->context_id;
+   subpicture->xvimage_id = xvimage_id;
+   subpicture->width = width;
+   subpicture->height = height;
+   subpicture->num_palette_entries = 0;
+   subpicture->entry_bytes = PipeToComponentOrder(template.format, subpicture->component_order);
+   subpicture->privData = subpicture_priv;
+
+   SyncHandle();
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p created.\n", subpicture);
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCClearSubpicture(Display *dpy, XvMCSubpicture *subpicture, short x, short y,
+                           unsigned short width, unsigned short height, unsigned int color)
+{
+   XvMCSubpicturePrivate *subpicture_priv;
+   XvMCContextPrivate *context_priv;
+
+   assert(dpy);
+
+   if (!subpicture)
+      return XvMCBadSubpicture;
+
+   subpicture_priv = subpicture->privData;
+   context_priv = subpicture_priv->context->privData;
+   /* TODO: Assert clear rect is within bounds? Or clip? */
+   context_priv->vctx->vpipe->surface_fill(context_priv->vctx->vpipe,
+                                           subpicture_priv->sfc, x, y,
+                                           width, height, color);
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage *image,
+                               short srcx, short srcy, unsigned short width, unsigned short height,
+                               short dstx, short dsty)
+{
+   XvMCSubpicturePrivate *subpicture_priv;
+   XvMCContextPrivate *context_priv;
+   struct pipe_video_context *vpipe;
+   struct pipe_transfer *xfer;
+   unsigned char *src, *dst, *dst_line;
+   unsigned x, y;
+   struct pipe_box dst_box = {dstx, dsty, 0, width, height, 1};
+   struct pipe_subresource sr = {0, 0};
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Compositing subpicture %p.\n", subpicture);
+
+   assert(dpy);
+
+   if (!subpicture)
+      return XvMCBadSubpicture;
+
+   assert(image);
+
+   if (subpicture->xvimage_id != image->id)
+      return BadMatch;
+
+   /* No planar support for now */
+   if (image->num_planes != 1)
+      return BadMatch;
+
+   subpicture_priv = subpicture->privData;
+   context_priv = subpicture_priv->context->privData;
+   vpipe = context_priv->vctx->vpipe;
+
+   /* TODO: Assert rects are within bounds? Or clip? */
+
+   xfer = vpipe->get_transfer(vpipe, subpicture_priv->sfc->texture,
+                              sr, PIPE_TRANSFER_WRITE, &dst_box);
+   if (!xfer)
+      return BadAlloc;
+
+   src = image->data;
+   dst = vpipe->transfer_map(vpipe, xfer);
+   if (!dst) {
+      vpipe->transfer_destroy(vpipe, xfer);
+      return BadAlloc;
+   }
+
+   switch (image->id) {
+      case FOURCC_RGB:
+         assert(subpicture_priv->sfc->format == XvIDToPipe(image->id));
+         for (y = 0; y < height; ++y) {
+            dst_line = dst;
+            for (x = 0; x < width; ++x, src += 3, dst_line += 4) {
+               dst_line[0] = src[2]; /* B */
+               dst_line[1] = src[1]; /* G */
+               dst_line[2] = src[0]; /* R */
+            }
+            dst += xfer->stride;
+         }
+         break;
+      default:
+         XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", image->id);
+   }
+
+   vpipe->transfer_unmap(vpipe, xfer);
+   vpipe->transfer_destroy(vpipe, xfer);
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p composited.\n", subpicture);
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCDestroySubpicture(Display *dpy, XvMCSubpicture *subpicture)
+{
+   XvMCSubpicturePrivate *subpicture_priv;
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying subpicture %p.\n", subpicture);
+
+   assert(dpy);
+
+   if (!subpicture)
+      return XvMCBadSubpicture;
+
+   subpicture_priv = subpicture->privData;
+   pipe_surface_reference(&subpicture_priv->sfc, NULL);
+   FREE(subpicture_priv);
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p destroyed.\n", subpicture);
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCSetSubpicturePalette(Display *dpy, XvMCSubpicture *subpicture, unsigned char *palette)
+{
+   assert(dpy);
+
+   if (!subpicture)
+      return XvMCBadSubpicture;
+
+   assert(palette);
+
+   /* We don't support paletted subpictures */
+   return BadMatch;
+}
+
+PUBLIC
+Status XvMCBlendSubpicture(Display *dpy, XvMCSurface *target_surface, XvMCSubpicture *subpicture,
+                           short subx, short suby, unsigned short subw, unsigned short subh,
+                           short surfx, short surfy, unsigned short surfw, unsigned short surfh)
+{
+   XvMCSurfacePrivate *surface_priv;
+   XvMCSubpicturePrivate *subpicture_priv;
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Associating subpicture %p with surface %p.\n", subpicture, target_surface);
+
+   assert(dpy);
+
+   if (!target_surface)
+      return XvMCBadSurface;
+
+   if (!subpicture)
+      return XvMCBadSubpicture;
+
+   if (target_surface->context_id != subpicture->context_id)
+      return BadMatch;
+
+   /* TODO: Verify against subpicture independent scaling */
+
+   surface_priv = target_surface->privData;
+   subpicture_priv = subpicture->privData;
+
+   /* TODO: Assert rects are within bounds? Or clip? */
+
+   surface_priv->subpicture = subpicture;
+   surface_priv->subx = subx;
+   surface_priv->suby = suby;
+   surface_priv->subw = subw;
+   surface_priv->subh = subh;
+   surface_priv->surfx = surfx;
+   surface_priv->surfy = surfy;
+   surface_priv->surfw = surfw;
+   surface_priv->surfh = surfh;
+   subpicture_priv->surface = target_surface;
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCBlendSubpicture2(Display *dpy, XvMCSurface *source_surface, XvMCSurface *target_surface,
+                            XvMCSubpicture *subpicture, short subx, short suby, unsigned short subw, unsigned short subh,
+                            short surfx, short surfy, unsigned short surfw, unsigned short surfh)
+{
+   assert(dpy);
+
+   if (!source_surface || !target_surface)
+      return XvMCBadSurface;
+
+   if (!subpicture)
+      return XvMCBadSubpicture;
+
+   if (source_surface->context_id != subpicture->context_id)
+      return BadMatch;
+
+   if (source_surface->context_id != subpicture->context_id)
+      return BadMatch;
+
+   /* TODO: Assert rects are within bounds? Or clip? */
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCSyncSubpicture(Display *dpy, XvMCSubpicture *subpicture)
+{
+   assert(dpy);
+
+   if (!subpicture)
+      return XvMCBadSubpicture;
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCFlushSubpicture(Display *dpy, XvMCSubpicture *subpicture)
+{
+   assert(dpy);
+
+   if (!subpicture)
+      return XvMCBadSubpicture;
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCGetSubpictureStatus(Display *dpy, XvMCSubpicture *subpicture, int *status)
+{
+   assert(dpy);
+
+   if (!subpicture)
+      return XvMCBadSubpicture;
+
+   assert(status);
+
+   /* TODO */
+   *status = 0;
+
+   return Success;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/surface.c b/src/gallium/state_trackers/xorg/xvmc/surface.c
new file mode 100644 (file)
index 0000000..0decc45
--- /dev/null
@@ -0,0 +1,501 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <X11/Xlibint.h>
+#include <vl_winsys.h>
+#include <pipe/p_video_context.h>
+#include <pipe/p_video_state.h>
+#include <pipe/p_state.h>
+#include <util/u_inlines.h>
+#include <util/u_memory.h>
+#include <util/u_math.h>
+#include "xvmc_private.h"
+
+static enum pipe_mpeg12_macroblock_type TypeToPipe(int xvmc_mb_type)
+{
+   if (xvmc_mb_type & XVMC_MB_TYPE_INTRA)
+      return PIPE_MPEG12_MACROBLOCK_TYPE_INTRA;
+   if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_FORWARD)
+      return PIPE_MPEG12_MACROBLOCK_TYPE_FWD;
+   if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_BACKWARD)
+      return PIPE_MPEG12_MACROBLOCK_TYPE_BKWD;
+   if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD))
+      return PIPE_MPEG12_MACROBLOCK_TYPE_BI;
+
+   assert(0);
+
+   XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized mb type 0x%08X.\n", xvmc_mb_type);
+
+   return -1;
+}
+
+static enum pipe_mpeg12_picture_type PictureToPipe(int xvmc_pic)
+{
+   switch (xvmc_pic) {
+      case XVMC_TOP_FIELD:
+         return PIPE_MPEG12_PICTURE_TYPE_FIELD_TOP;
+      case XVMC_BOTTOM_FIELD:
+         return PIPE_MPEG12_PICTURE_TYPE_FIELD_BOTTOM;
+      case XVMC_FRAME_PICTURE:
+         return PIPE_MPEG12_PICTURE_TYPE_FRAME;
+      default:
+         assert(0);
+   }
+
+   XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized picture type 0x%08X.\n", xvmc_pic);
+
+   return -1;
+}
+
+static enum pipe_mpeg12_motion_type MotionToPipe(int xvmc_motion_type, int xvmc_dct_type)
+{
+   switch (xvmc_motion_type) {
+      case XVMC_PREDICTION_FRAME:
+         if (xvmc_dct_type == XVMC_DCT_TYPE_FIELD)
+            return PIPE_MPEG12_MOTION_TYPE_16x8;
+         else if (xvmc_dct_type == XVMC_DCT_TYPE_FRAME)
+            return PIPE_MPEG12_MOTION_TYPE_FRAME;
+         break;
+      case XVMC_PREDICTION_FIELD:
+         return PIPE_MPEG12_MOTION_TYPE_FIELD;
+      case XVMC_PREDICTION_DUAL_PRIME:
+         return PIPE_MPEG12_MOTION_TYPE_DUALPRIME;
+      default:
+         assert(0);
+   }
+
+   XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized motion type 0x%08X (with DCT type 0x%08X).\n", xvmc_motion_type, xvmc_dct_type);
+
+   return -1;
+}
+
+#if 0
+static bool
+CreateOrResizeBackBuffer(struct vl_context *vctx, unsigned int width, unsigned int height,
+                         struct pipe_surface **backbuffer)
+{
+   struct pipe_video_context *vpipe;
+   struct pipe_resource template;
+   struct pipe_resource *tex;
+
+   assert(vctx);
+
+   vpipe = vctx->vpipe;
+
+   if (*backbuffer) {
+      if ((*backbuffer)->width != width || (*backbuffer)->height != height)
+         pipe_surface_reference(backbuffer, NULL);
+      else
+         return true;
+   }
+
+   memset(&template, 0, sizeof(struct pipe_resource));
+   template.target = PIPE_TEXTURE_2D;
+   template.format = vctx->vscreen->format;
+   template.last_level = 0;
+   template.width0 = width;
+   template.height0 = height;
+   template.depth0 = 1;
+   template.usage = PIPE_USAGE_DEFAULT;
+   template.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_BLIT_SOURCE;
+   template.flags = 0;
+
+   tex = vpipe->screen->resource_create(vpipe->screen, &template);
+   if (!tex)
+      return false;
+
+   *backbuffer = vpipe->screen->get_tex_surface(vpipe->screen, tex, 0, 0, 0,
+                                                template.bind);
+   pipe_resource_reference(&tex, NULL);
+
+   if (!*backbuffer)
+      return false;
+
+   /* Clear the backbuffer in case the video doesn't cover the whole window */
+   /* FIXME: Need to clear every time a frame moves and leaves dirty rects */
+   vpipe->surface_fill(vpipe, *backbuffer, 0, 0, width, height, 0);
+
+   return true;
+}
+#endif
+
+static void
+MacroBlocksToPipe(struct pipe_screen *screen,
+                  const XvMCMacroBlockArray *xvmc_macroblocks,
+                  const XvMCBlockArray *xvmc_blocks,
+                  unsigned int first_macroblock,
+                  unsigned int num_macroblocks,
+                  struct pipe_mpeg12_macroblock *pipe_macroblocks)
+{
+   unsigned int i, j, k, l;
+   XvMCMacroBlock *xvmc_mb;
+
+   assert(xvmc_macroblocks);
+   assert(xvmc_blocks);
+   assert(pipe_macroblocks);
+   assert(num_macroblocks);
+
+   xvmc_mb = xvmc_macroblocks->macro_blocks + first_macroblock;
+
+   for (i = 0; i < num_macroblocks; ++i) {
+      pipe_macroblocks->base.codec = PIPE_VIDEO_CODEC_MPEG12;
+      pipe_macroblocks->mbx = xvmc_mb->x;
+      pipe_macroblocks->mby = xvmc_mb->y;
+      pipe_macroblocks->mb_type = TypeToPipe(xvmc_mb->macroblock_type);
+      if (pipe_macroblocks->mb_type != PIPE_MPEG12_MACROBLOCK_TYPE_INTRA)
+         pipe_macroblocks->mo_type = MotionToPipe(xvmc_mb->motion_type, xvmc_mb->dct_type);
+      /* Get rid of Valgrind 'undefined' warnings */
+      else
+         pipe_macroblocks->mo_type = -1;
+      pipe_macroblocks->dct_type = xvmc_mb->dct_type == XVMC_DCT_TYPE_FIELD ?
+         PIPE_MPEG12_DCT_TYPE_FIELD : PIPE_MPEG12_DCT_TYPE_FRAME;
+
+      for (j = 0; j < 2; ++j)
+         for (k = 0; k < 2; ++k)
+            for (l = 0; l < 2; ++l)
+               pipe_macroblocks->pmv[j][k][l] = xvmc_mb->PMV[j][k][l];
+
+      pipe_macroblocks->cbp = xvmc_mb->coded_block_pattern;
+      pipe_macroblocks->blocks = xvmc_blocks->blocks + xvmc_mb->index * BLOCK_SIZE_SAMPLES;
+
+      ++pipe_macroblocks;
+      ++xvmc_mb;
+   }
+}
+
+PUBLIC
+Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface)
+{
+   XvMCContextPrivate *context_priv;
+   struct pipe_video_context *vpipe;
+   XvMCSurfacePrivate *surface_priv;
+   struct pipe_resource template;
+   struct pipe_resource *vsfc_tex;
+   struct pipe_surface *vsfc;
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Creating surface %p.\n", surface);
+
+   assert(dpy);
+
+   if (!context)
+      return XvMCBadContext;
+   if (!surface)
+      return XvMCBadSurface;
+
+   context_priv = context->privData;
+   vpipe = context_priv->vctx->vpipe;
+
+   surface_priv = CALLOC(1, sizeof(XvMCSurfacePrivate));
+   if (!surface_priv)
+      return BadAlloc;
+
+   memset(&template, 0, sizeof(struct pipe_resource));
+   template.target = PIPE_TEXTURE_2D;
+   template.format = (enum pipe_format)vpipe->get_param(vpipe, PIPE_CAP_DECODE_TARGET_PREFERRED_FORMAT);
+   template.last_level = 0;
+   if (vpipe->is_format_supported(vpipe, template.format,
+                                  PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET,
+                                  PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO)) {
+      template.width0 = context->width;
+      template.height0 = context->height;
+   }
+   else {
+      assert(vpipe->is_format_supported(vpipe, template.format,
+                                       PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET,
+                                       PIPE_TEXTURE_GEOM_NON_SQUARE));
+      template.width0 = util_next_power_of_two(context->width);
+      template.height0 = util_next_power_of_two(context->height);
+   }
+   template.depth0 = 1;
+   template.usage = PIPE_USAGE_DEFAULT;
+   template.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
+   template.flags = 0;
+   vsfc_tex = vpipe->screen->resource_create(vpipe->screen, &template);
+   if (!vsfc_tex) {
+      FREE(surface_priv);
+      return BadAlloc;
+   }
+
+   vsfc = vpipe->screen->get_tex_surface(vpipe->screen, vsfc_tex, 0, 0, 0,
+                                         PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET);
+   pipe_resource_reference(&vsfc_tex, NULL);
+   if (!vsfc) {
+      FREE(surface_priv);
+      return BadAlloc;
+   }
+
+   surface_priv->pipe_vsfc = vsfc;
+   surface_priv->context = context;
+
+   surface->surface_id = XAllocID(dpy);
+   surface->context_id = context->context_id;
+   surface->surface_type_id = context->surface_type_id;
+   surface->width = context->width;
+   surface->height = context->height;
+   surface->privData = surface_priv;
+
+   SyncHandle();
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p created.\n", surface);
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int picture_structure,
+                         XvMCSurface *target_surface, XvMCSurface *past_surface, XvMCSurface *future_surface,
+                         unsigned int flags, unsigned int num_macroblocks, unsigned int first_macroblock,
+                         XvMCMacroBlockArray *macroblocks, XvMCBlockArray *blocks
+)
+{
+   struct pipe_video_context *vpipe;
+   struct pipe_surface *t_vsfc;
+   struct pipe_surface *p_vsfc;
+   struct pipe_surface *f_vsfc;
+   XvMCContextPrivate *context_priv;
+   XvMCSurfacePrivate *target_surface_priv;
+   XvMCSurfacePrivate *past_surface_priv;
+   XvMCSurfacePrivate *future_surface_priv;
+   struct pipe_mpeg12_macroblock pipe_macroblocks[num_macroblocks];
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Rendering to surface %p.\n", target_surface);
+
+   assert(dpy);
+
+   if (!context || !context->privData)
+      return XvMCBadContext;
+   if (!target_surface || !target_surface->privData)
+      return XvMCBadSurface;
+
+   if (picture_structure != XVMC_TOP_FIELD &&
+       picture_structure != XVMC_BOTTOM_FIELD &&
+       picture_structure != XVMC_FRAME_PICTURE)
+      return BadValue;
+   /* Bkwd pred equivalent to fwd (past && !future) */
+   if (future_surface && !past_surface)
+      return BadMatch;
+
+   assert(context->context_id == target_surface->context_id);
+   assert(!past_surface || context->context_id == past_surface->context_id);
+   assert(!future_surface || context->context_id == future_surface->context_id);
+
+   assert(macroblocks);
+   assert(blocks);
+
+   assert(macroblocks->context_id == context->context_id);
+   assert(blocks->context_id == context->context_id);
+
+   assert(flags == 0 || flags == XVMC_SECOND_FIELD);
+
+   target_surface_priv = target_surface->privData;
+   past_surface_priv = past_surface ? past_surface->privData : NULL;
+   future_surface_priv = future_surface ? future_surface->privData : NULL;
+
+   assert(target_surface_priv->context == context);
+   assert(!past_surface || past_surface_priv->context == context);
+   assert(!future_surface || future_surface_priv->context == context);
+
+   context_priv = context->privData;
+   vpipe = context_priv->vctx->vpipe;
+
+   t_vsfc = target_surface_priv->pipe_vsfc;
+   p_vsfc = past_surface ? past_surface_priv->pipe_vsfc : NULL;
+   f_vsfc = future_surface ? future_surface_priv->pipe_vsfc : NULL;
+
+   MacroBlocksToPipe(vpipe->screen, macroblocks, blocks, first_macroblock,
+                     num_macroblocks, pipe_macroblocks);
+
+   vpipe->set_decode_target(vpipe, t_vsfc);
+   vpipe->decode_macroblocks(vpipe, p_vsfc, f_vsfc, num_macroblocks,
+                             &pipe_macroblocks->base, &target_surface_priv->render_fence);
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for rendering.\n", target_surface);
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface)
+{
+   assert(dpy);
+
+   if (!surface)
+      return XvMCBadSurface;
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface)
+{
+   assert(dpy);
+
+   if (!surface)
+      return XvMCBadSurface;
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
+                      short srcx, short srcy, unsigned short srcw, unsigned short srch,
+                      short destx, short desty, unsigned short destw, unsigned short desth,
+                      int flags)
+{
+   struct pipe_video_context *vpipe;
+   XvMCSurfacePrivate *surface_priv;
+   XvMCContextPrivate *context_priv;
+   XvMCSubpicturePrivate *subpicture_priv;
+   XvMCContext *context;
+   struct pipe_video_rect src_rect = {srcx, srcy, srcw, srch};
+   struct pipe_video_rect dst_rect = {destx, desty, destw, desth};
+   struct pipe_surface *drawable_surface;
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Displaying surface %p.\n", surface);
+
+   assert(dpy);
+
+   if (!surface || !surface->privData)
+      return XvMCBadSurface;
+
+   surface_priv = surface->privData;
+   context = surface_priv->context;
+   context_priv = context->privData;
+
+   drawable_surface = vl_drawable_surface_get(context_priv->vctx->vscreen, drawable);
+   if (!drawable_surface)
+      return BadDrawable;
+
+   assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE);
+   assert(srcx + srcw - 1 < surface->width);
+   assert(srcy + srch - 1 < surface->height);
+   /*
+    * Some apps (mplayer) hit these asserts because they call
+    * this function after the window has been resized by the WM
+    * but before they've handled the corresponding XEvent and
+    * know about the new dimensions. The output should be clipped
+    * until the app updates destw and desth.
+    */
+   /*
+   assert(destx + destw - 1 < drawable_surface->width);
+   assert(desty + desth - 1 < drawable_surface->height);
+    */
+
+   subpicture_priv = surface_priv->subpicture ? surface_priv->subpicture->privData : NULL;
+   vpipe = context_priv->vctx->vpipe;
+
+#if 0
+   if (!CreateOrResizeBackBuffer(context_priv->vctx, width, height, &context_priv->backbuffer))
+      return BadAlloc;
+#endif
+
+   if (subpicture_priv) {
+      struct pipe_video_rect src_rect = {surface_priv->subx, surface_priv->suby, surface_priv->subw, surface_priv->subh};
+      struct pipe_video_rect dst_rect = {surface_priv->surfx, surface_priv->surfy, surface_priv->surfw, surface_priv->surfh};
+      struct pipe_video_rect *src_rects[1] = {&src_rect};
+      struct pipe_video_rect *dst_rects[1] = {&dst_rect};
+
+      XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p has subpicture %p.\n", surface, surface_priv->subpicture);
+
+      assert(subpicture_priv->surface == surface);
+      vpipe->set_picture_layers(vpipe, &subpicture_priv->sfc, src_rects, dst_rects, 1);
+
+      surface_priv->subpicture = NULL;
+      subpicture_priv->surface = NULL;
+   }
+   else
+      vpipe->set_picture_layers(vpipe, NULL, NULL, NULL, 0);
+
+   vpipe->render_picture(vpipe, surface_priv->pipe_vsfc, PictureToPipe(flags), &src_rect,
+                         drawable_surface, &dst_rect, &surface_priv->disp_fence);
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for display. Pushing to front buffer.\n", surface);
+
+   vpipe->screen->flush_frontbuffer
+   (
+      vpipe->screen,
+      drawable_surface,
+      vl_contextprivate_get(context_priv->vctx, drawable_surface)
+   );
+
+   pipe_surface_reference(&drawable_surface, NULL);
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Pushed surface %p to front buffer.\n", surface);
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status)
+{
+   assert(dpy);
+
+   if (!surface)
+      return XvMCBadSurface;
+
+   assert(status);
+
+   *status = 0;
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCDestroySurface(Display *dpy, XvMCSurface *surface)
+{
+   XvMCSurfacePrivate *surface_priv;
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying surface %p.\n", surface);
+
+   assert(dpy);
+
+   if (!surface || !surface->privData)
+      return XvMCBadSurface;
+
+   surface_priv = surface->privData;
+   pipe_surface_reference(&surface_priv->pipe_vsfc, NULL);
+   FREE(surface_priv);
+   surface->privData = NULL;
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p destroyed.\n", surface);
+
+   return Success;
+}
+
+PUBLIC
+Status XvMCHideSurface(Display *dpy, XvMCSurface *surface)
+{
+   assert(dpy);
+
+   if (!surface || !surface->privData)
+      return XvMCBadSurface;
+
+   /* No op, only for overlaid rendering */
+
+   return Success;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/.gitignore b/src/gallium/state_trackers/xorg/xvmc/tests/.gitignore
new file mode 100644 (file)
index 0000000..9a8e05d
--- /dev/null
@@ -0,0 +1,6 @@
+test_context
+test_surface
+test_subpicture
+test_blocks
+test_rendering
+xvmc_bench
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/Makefile b/src/gallium/state_trackers/xorg/xvmc/tests/Makefile
new file mode 100644 (file)
index 0000000..88b0376
--- /dev/null
@@ -0,0 +1,31 @@
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+LIBS = -lXvMCW -lXvMC -lXv -lX11
+
+#############################################
+
+.PHONY: default clean
+
+default: test_context test_surface test_subpicture test_blocks test_rendering xvmc_bench
+
+test_context: test_context.o testlib.o
+       $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+test_surface: test_surface.o testlib.o
+       $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+test_subpicture: test_subpicture.o testlib.o
+       $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+test_blocks: test_blocks.o testlib.o
+       $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+test_rendering: test_rendering.o testlib.o
+       $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+xvmc_bench: xvmc_bench.o testlib.o
+       $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+clean:
+       $(RM) -rf *.o test_context test_surface test_subpicture test_blocks test_rendering xvmc_bench
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c
new file mode 100644 (file)
index 0000000..994e3ca
--- /dev/null
@@ -0,0 +1,111 @@
+/**************************************************************************
+ * 
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include <assert.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+       const unsigned int      width = 16, height = 16;
+       const unsigned int      min_required_blocks = 1, min_required_macroblocks = 1;
+       const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+
+       Display                 *display;
+       XvPortID                port_num;
+       int                     surface_type_id;
+       unsigned int            is_overlay, intra_unsigned;
+       int                     colorkey;
+       XvMCContext             context;
+       XvMCSurface             surface;
+       XvMCBlockArray          blocks = {0};
+       XvMCMacroBlockArray     macroblocks = {0};
+
+       display = XOpenDisplay(NULL);
+
+       if (!GetPort
+       (
+               display,
+               width,
+               height,
+               XVMC_CHROMA_FORMAT_420,
+               mc_types,
+               2,
+               &port_num,
+               &surface_type_id,
+               &is_overlay,
+               &intra_unsigned
+       ))
+       {
+               XCloseDisplay(display);
+               error(1, 0, "Error, unable to find a good port.\n");
+       }
+
+       if (is_overlay)
+       {
+               Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+               XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+       }
+
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+       assert(XvMCCreateSurface(display, &context, &surface) == Success);
+
+       /* Test NULL context */
+       assert(XvMCCreateBlocks(display, NULL, 1, &blocks) == XvMCBadContext);
+       /* Test 0 blocks */
+       assert(XvMCCreateBlocks(display, &context, 0, &blocks) == BadValue);
+       /* Test valid params */
+       assert(XvMCCreateBlocks(display, &context, min_required_blocks, &blocks) == Success);
+       /* Test context id assigned and correct */
+       assert(blocks.context_id == context.context_id);
+       /* Test number of blocks assigned and correct */
+       assert(blocks.num_blocks == min_required_blocks);
+       /* Test block pointer valid */
+       assert(blocks.blocks != NULL);
+       /* Test NULL context */
+       assert(XvMCCreateMacroBlocks(display, NULL, 1, &macroblocks) == XvMCBadContext);
+       /* Test 0 macroblocks */
+       assert(XvMCCreateMacroBlocks(display, &context, 0, &macroblocks) == BadValue);
+       /* Test valid params */
+       assert(XvMCCreateMacroBlocks(display, &context, min_required_macroblocks, &macroblocks) == Success);
+       /* Test context id assigned and correct */
+       assert(macroblocks.context_id == context.context_id);
+       /* Test macroblock pointer valid */
+       assert(macroblocks.macro_blocks != NULL);
+       /* Test valid params */
+       assert(XvMCDestroyMacroBlocks(display, &macroblocks) == Success);
+       /* Test valid params */
+       assert(XvMCDestroyBlocks(display, &blocks) == Success);
+
+       assert(XvMCDestroySurface(display, &surface) == Success);
+       assert(XvMCDestroyContext(display, &context) == Success);
+
+       XvUngrabPort(display, port_num, CurrentTime);
+       XCloseDisplay(display);
+
+       return 0;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_context.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_context.c
new file mode 100644 (file)
index 0000000..3da957c
--- /dev/null
@@ -0,0 +1,119 @@
+/**************************************************************************
+ * 
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include <assert.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+       const unsigned int      width = 16, height = 16;
+       const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+
+       Display                 *display;
+       XvPortID                port_num;
+       int                     surface_type_id;
+       unsigned int            is_overlay, intra_unsigned;
+       int                     colorkey;
+       XvMCContext             context = {0};
+
+       display = XOpenDisplay(NULL);
+
+       if (!GetPort
+       (
+               display,
+               width,
+               height,
+               XVMC_CHROMA_FORMAT_420,
+               mc_types,
+               2,
+               &port_num,
+               &surface_type_id,
+               &is_overlay,
+               &intra_unsigned
+       ))
+       {
+               XCloseDisplay(display);
+               error(1, 0, "Error, unable to find a good port.\n");
+       }
+
+       if (is_overlay)
+       {
+               Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+               XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+       }
+
+       /* Test NULL context */
+       /* XXX: XvMCBadContext not a valid return for XvMCCreateContext in the XvMC API, but openChrome driver returns it */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, NULL) == XvMCBadContext);
+       /* Test invalid port */
+       /* XXX: Success and XvBadPort have the same value, if this call actually gets passed the validation step as of now we'll crash later */
+       assert(XvMCCreateContext(display, -1, surface_type_id, width, height, XVMC_DIRECT, &context) == XvBadPort);
+       /* Test invalid surface */
+       assert(XvMCCreateContext(display, port_num, -1, width, height, XVMC_DIRECT, &context) == BadMatch);
+       /* Test invalid flags */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, -1, &context) == BadValue);
+       /* Test huge width */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, height, XVMC_DIRECT, &context) == BadValue);
+       /* Test huge height */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, 16384, XVMC_DIRECT, &context) == BadValue);
+       /* Test huge width & height */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, 16384, XVMC_DIRECT, &context) == BadValue);
+       /* Test valid params */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+       /* Test context id assigned */
+       assert(context.context_id != 0);
+       /* Test surface type id assigned and correct */
+       assert(context.surface_type_id == surface_type_id);
+       /* Test width & height assigned and correct */
+       assert(context.width == width && context.height == height);
+       /* Test port assigned and correct */
+       assert(context.port == port_num);
+       /* Test flags assigned and correct */
+       assert(context.flags == XVMC_DIRECT);
+       /* Test NULL context */
+       assert(XvMCDestroyContext(display, NULL) == XvMCBadContext);
+       /* Test valid params */
+       assert(XvMCDestroyContext(display, &context) == Success);
+       /* Test awkward but valid width */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height, XVMC_DIRECT, &context) == Success);
+       assert(context.width >= width + 1);
+       assert(XvMCDestroyContext(display, &context) == Success);
+       /* Test awkward but valid height */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height + 1, XVMC_DIRECT, &context) == Success);
+       assert(context.height >= height + 1);
+       assert(XvMCDestroyContext(display, &context) == Success);
+       /* Test awkward but valid width & height */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height + 1, XVMC_DIRECT, &context) == Success);
+       assert(context.width >= width + 1 && context.height >= height + 1);
+       assert(XvMCDestroyContext(display, &context) == Success);
+
+       XvUngrabPort(display, port_num, CurrentTime);
+       XCloseDisplay(display);
+
+       return 0;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c
new file mode 100644 (file)
index 0000000..6058783
--- /dev/null
@@ -0,0 +1,317 @@
+/**************************************************************************
+ * 
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <error.h>
+#include "testlib.h"
+
+#define BLOCK_WIDTH                    8
+#define BLOCK_HEIGHT                   8
+#define BLOCK_SIZE                     (BLOCK_WIDTH * BLOCK_HEIGHT)
+#define MACROBLOCK_WIDTH               16
+#define MACROBLOCK_HEIGHT              16
+#define MACROBLOCK_WIDTH_IN_BLOCKS     (MACROBLOCK_WIDTH / BLOCK_WIDTH)
+#define MACROBLOCK_HEIGHT_IN_BLOCKS    (MACROBLOCK_HEIGHT / BLOCK_HEIGHT)
+#define BLOCKS_PER_MACROBLOCK          6
+
+#define INPUT_WIDTH                    16
+#define INPUT_HEIGHT                   16
+#define INPUT_WIDTH_IN_MACROBLOCKS     (INPUT_WIDTH / MACROBLOCK_WIDTH)
+#define INPUT_HEIGHT_IN_MACROBLOCKS    (INPUT_HEIGHT / MACROBLOCK_HEIGHT)
+#define NUM_MACROBLOCKS                        (INPUT_WIDTH_IN_MACROBLOCKS * INPUT_HEIGHT_IN_MACROBLOCKS)
+
+#define DEFAULT_OUTPUT_WIDTH           INPUT_WIDTH
+#define DEFAULT_OUTPUT_HEIGHT          INPUT_HEIGHT
+#define DEFAULT_ACCEPTABLE_ERR         0.01
+
+void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt);
+void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal);
+
+void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt)
+{
+       int fail = 0;
+       int i;
+
+       *output_width = DEFAULT_OUTPUT_WIDTH;
+       *output_height = DEFAULT_OUTPUT_WIDTH;
+       *acceptable_error = DEFAULT_ACCEPTABLE_ERR;
+       *prompt = 1;
+
+       for (i = 1; i < argc && !fail; ++i)
+       {
+               if (!strcmp(argv[i], "-w"))
+               {
+                       if (sscanf(argv[++i], "%u", output_width) != 1)
+                               fail = 1;
+               }
+               else if (!strcmp(argv[i], "-h"))
+               {
+                       if (sscanf(argv[++i], "%u", output_height) != 1)
+                               fail = 1;
+               }
+               else if (!strcmp(argv[i], "-e"))
+               {
+                       if (sscanf(argv[++i], "%lf", acceptable_error) != 1)
+                               fail = 1;
+               }
+               else if (strcmp(argv[i], "-n"))
+                       *prompt = 0;
+               else
+                       fail = 1;
+       }
+
+       if (fail)
+               error
+               (
+                       1, 0,
+                       "Bad argument.\n"
+                       "\n"
+                       "Usage: %s [options]\n"
+                       "\t-w <width>\tOutput width\n"
+                       "\t-h <height>\tOutput height\n"
+                       "\t-e <error>\tAcceptable margin of error per pixel, from 0 to 1\n"
+                       "\t-n\tDon't prompt for quit\n",
+                       argv[0]
+               );
+}
+
+void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal)
+{
+       unsigned int x, y;
+       unsigned int range = stop - start;
+
+       if (horizontal)
+       {
+               for (y = 0; y < BLOCK_HEIGHT; ++y)
+                       for (x = 0; x < BLOCK_WIDTH; ++x)
+                               block[y * BLOCK_WIDTH + x] = (short)(start + range * (x / (float)(BLOCK_WIDTH - 1)));
+       }
+       else
+       {
+               for (y = 0; y < BLOCK_HEIGHT; ++y)
+                       for (x = 0; x < BLOCK_WIDTH; ++x)
+                               block[y * BLOCK_WIDTH + x] = (short)(start + range * (y / (float)(BLOCK_HEIGHT - 1)));
+       }
+}
+
+int main(int argc, char **argv)
+{
+       unsigned int            output_width;
+       unsigned int            output_height;
+       double                  acceptable_error;
+       int                     prompt;
+       Display                 *display;
+       Window                  root, window;
+       const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+       XvPortID                port_num;
+       int                     surface_type_id;
+       unsigned int            is_overlay, intra_unsigned;
+       int                     colorkey;
+       XvMCContext             context;
+       XvMCSurface             surface;
+       XvMCBlockArray          block_array;
+       XvMCMacroBlockArray     mb_array;
+       int                     mbx, mby, bx, by;
+       XvMCMacroBlock          *mb;
+       short                   *blocks;
+       int                     quit = 0;
+
+       ParseArgs(argc, argv, &output_width, &output_height, &acceptable_error, &prompt);
+
+       display = XOpenDisplay(NULL);
+
+       if (!GetPort
+       (
+               display,
+               INPUT_WIDTH,
+               INPUT_HEIGHT,
+               XVMC_CHROMA_FORMAT_420,
+               mc_types,
+               2,
+               &port_num,
+               &surface_type_id,
+               &is_overlay,
+               &intra_unsigned
+       ))
+       {
+               XCloseDisplay(display);
+               error(1, 0, "Error, unable to find a good port.\n");
+       }
+
+       if (is_overlay)
+       {
+               Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+               XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+       }
+
+       root = XDefaultRootWindow(display);
+       window = XCreateSimpleWindow(display, root, 0, 0, output_width, output_height, 0, 0, colorkey);
+
+       assert(XvMCCreateContext(display, port_num, surface_type_id, INPUT_WIDTH, INPUT_HEIGHT, XVMC_DIRECT, &context) == Success);
+       assert(XvMCCreateSurface(display, &context, &surface) == Success);
+       assert(XvMCCreateBlocks(display, &context, NUM_MACROBLOCKS * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
+       assert(XvMCCreateMacroBlocks(display, &context, NUM_MACROBLOCKS, &mb_array) == Success);
+
+       mb = mb_array.macro_blocks;
+       blocks = block_array.blocks;
+
+       for (mby = 0; mby < INPUT_HEIGHT_IN_MACROBLOCKS; ++mby)
+               for (mbx = 0; mbx < INPUT_WIDTH_IN_MACROBLOCKS; ++mbx)
+               {
+                       mb->x = mbx;
+                       mb->y = mby;
+                       mb->macroblock_type = XVMC_MB_TYPE_INTRA;
+                       /*mb->motion_type = ;*/
+                       /*mb->motion_vertical_field_select = ;*/
+                       mb->dct_type = XVMC_DCT_TYPE_FRAME;
+                       /*mb->PMV[0][0][0] = ;
+                       mb->PMV[0][0][1] = ;
+                       mb->PMV[0][1][0] = ;
+                       mb->PMV[0][1][1] = ;
+                       mb->PMV[1][0][0] = ;
+                       mb->PMV[1][0][1] = ;
+                       mb->PMV[1][1][0] = ;
+                       mb->PMV[1][1][1] = ;*/
+                       mb->index = (mby * INPUT_WIDTH_IN_MACROBLOCKS + mbx) * BLOCKS_PER_MACROBLOCK;
+                       mb->coded_block_pattern = 0x3F;
+
+                       mb++;
+
+                       for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS; ++by)
+                               for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS; ++bx)
+                               {
+                                       const int start = 16, stop = 235, range = stop - start;
+
+                                       Gradient
+                                       (
+                                               blocks,
+                                               (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
+                                               (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
+                                               1
+                                       );
+
+                                       blocks += BLOCK_SIZE;
+                               }
+
+                       for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS / 2; ++by)
+                               for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS / 2; ++bx)
+                               {
+                                       const int start = 16, stop = 240, range = stop - start;
+
+                                       Gradient
+                                       (
+                                               blocks,
+                                               (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
+                                               (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
+                                               1
+                                       );
+
+                                       blocks += BLOCK_SIZE;
+
+                                       Gradient
+                                       (
+                                               blocks,
+                                               (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
+                                               (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
+                                               1
+                                       );
+
+                                       blocks += BLOCK_SIZE;
+                               }
+               }
+
+       XSelectInput(display, window, ExposureMask | KeyPressMask);
+       XMapWindow(display, window);
+       XSync(display, 0);
+
+       /* Test NULL context */
+       assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadContext);
+       /* Test NULL surface */
+       assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadSurface);
+       /* Test bad picture structure */
+       assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == BadValue);
+       /* Test valid params */
+       assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == Success);
+
+       /* Test NULL surface */
+       assert(XvMCPutSurface(display, NULL, window, 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 0, 0, output_width, output_height, XVMC_FRAME_PICTURE) == XvMCBadSurface);
+       /* Test bad window */
+       /* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */
+       /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/
+
+       if (prompt)
+       {
+               puts("Press any button to quit...");
+
+               while (!quit)
+               {
+                       if (XPending(display) > 0)
+                       {
+                               XEvent event;
+
+                               XNextEvent(display, &event);
+
+                               switch (event.type)
+                               {
+                                       case Expose:
+                                       {
+                                               /* Test valid params */
+                                               assert
+                                               (
+                                                       XvMCPutSurface
+                                                       (
+                                                               display, &surface, window,
+                                                               0, 0, INPUT_WIDTH, INPUT_HEIGHT,
+                                                               0, 0, output_width, output_height,
+                                                               XVMC_FRAME_PICTURE
+                                                       ) == Success
+                                               );
+                                               break;
+                                       }
+                                       case KeyPress:
+                                       {
+                                               quit = 1;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       assert(XvMCDestroyBlocks(display, &block_array) == Success);
+       assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
+       assert(XvMCDestroySurface(display, &surface) == Success);
+       assert(XvMCDestroyContext(display, &context) == Success);
+
+       XvUngrabPort(display, port_num, CurrentTime);
+       XDestroyWindow(display, window);
+       XCloseDisplay(display);
+
+       return 0;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_subpicture.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_subpicture.c
new file mode 100644 (file)
index 0000000..20d0907
--- /dev/null
@@ -0,0 +1,182 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <error.h>
+#include <stdio.h>
+#include "testlib.h"
+
+static void PrintGUID(const char *guid)
+{
+       int i;
+       printf("\tguid: ");
+       for (i = 0; i < 4; ++i)
+               printf("%C,", guid[i] == 0 ? '0' : guid[i]);
+       for (; i < 15; ++i)
+               printf("%x,", (unsigned char)guid[i]);
+       printf("%x\n", (unsigned int)guid[15]);
+}
+
+static void PrintComponentOrder(const char *co)
+{
+       int i;
+       printf("\tcomponent_order:\n\t   ");
+       for (i = 0; i < 4; ++i)
+               printf("%C,", co[i] == 0 ? '0' : co[i]);
+       for (; i < 31; ++i)
+               printf("%x,", (unsigned int)co[i]);
+       printf("%x\n", (unsigned int)co[31]);
+}
+
+int main(int argc, char **argv)
+{
+       const unsigned int      width = 16, height = 16;
+       const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+       const unsigned int      subpic_width = 16, subpic_height = 16;
+
+       Display                 *display;
+       XvPortID                port_num;
+       int                     surface_type_id;
+       unsigned int            is_overlay, intra_unsigned;
+       int                     colorkey;
+       XvMCContext             context;
+       XvImageFormatValues     *subpics;
+       int                     num_subpics;
+       XvMCSubpicture          subpicture = {0};
+       int                     i;
+
+       display = XOpenDisplay(NULL);
+
+       if (!GetPort
+       (
+               display,
+               width,
+               height,
+               XVMC_CHROMA_FORMAT_420,
+               mc_types,
+               2,
+               &port_num,
+               &surface_type_id,
+               &is_overlay,
+               &intra_unsigned
+       ))
+       {
+               XCloseDisplay(display);
+               error(1, 0, "Error, unable to find a good port.\n");
+       }
+
+       if (is_overlay)
+       {
+               Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+               XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+       }
+
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+       
+       subpics = XvMCListSubpictureTypes(display, port_num, surface_type_id, &num_subpics);
+       assert((subpics && num_subpics) > 0 || (!subpics && num_subpics == 0));
+       
+       for (i = 0; i < num_subpics; ++i)
+       {
+               printf("Subpicture %d:\n", i);
+               printf("\tid: 0x%08x\n", subpics[i].id);
+               printf("\ttype: %s\n", subpics[i].type == XvRGB ? "XvRGB" : (subpics[i].type == XvYUV ? "XvYUV" : "Unknown"));
+               printf("\tbyte_order: %s\n", subpics[i].byte_order == LSBFirst ? "LSB First" : (subpics[i].byte_order == MSBFirst ? "MSB First" : "Unknown"));
+               PrintGUID(subpics[i].guid);
+               printf("\tbpp: %u\n", subpics[i].bits_per_pixel);
+               printf("\tformat: %s\n", subpics[i].format == XvPacked ? "XvPacked" : (subpics[i].format == XvPlanar ? "XvPlanar" : "Unknown"));
+               printf("\tnum_planes: %u\n", subpics[i].num_planes);
+               
+               if (subpics[i].type == XvRGB)
+               {
+                       printf("\tdepth: %u\n", subpics[i].depth);
+                       printf("\tred_mask: 0x%08x\n", subpics[i].red_mask);
+                       printf("\tgreen_mask: 0x%08x\n", subpics[i].green_mask);
+                       printf("\tblue_mask: 0x%08x\n", subpics[i].blue_mask);
+               }
+               else if (subpics[i].type == XvYUV)
+               {
+                       printf("\ty_sample_bits: %u\n", subpics[i].y_sample_bits);
+                       printf("\tu_sample_bits: %u\n", subpics[i].u_sample_bits);
+                       printf("\tv_sample_bits: %u\n", subpics[i].v_sample_bits);
+                       printf("\thorz_y_period: %u\n", subpics[i].horz_y_period);
+                       printf("\thorz_u_period: %u\n", subpics[i].horz_u_period);
+                       printf("\thorz_v_period: %u\n", subpics[i].horz_v_period);
+                       printf("\tvert_y_period: %u\n", subpics[i].vert_y_period);
+                       printf("\tvert_u_period: %u\n", subpics[i].vert_u_period);
+                       printf("\tvert_v_period: %u\n", subpics[i].vert_v_period);
+               }
+               PrintComponentOrder(subpics[i].component_order);
+               printf("\tscanline_order: %s\n", subpics[i].scanline_order == XvTopToBottom ? "XvTopToBottom" : (subpics[i].scanline_order == XvBottomToTop ? "XvBottomToTop" : "Unknown"));
+       }
+       
+       if (num_subpics == 0)
+       {
+               printf("Subpictures not supported, nothing to test.\n");
+               return 0;
+       }
+
+       /* Test NULL context */
+       assert(XvMCCreateSubpicture(display, NULL, &subpicture, subpic_width, subpic_height, subpics[0].id) == XvMCBadContext);
+       /* Test NULL subpicture */
+       assert(XvMCCreateSubpicture(display, &context, NULL, subpic_width, subpic_height, subpics[0].id) == XvMCBadSubpicture);
+       /* Test invalid subpicture */
+       assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, subpic_height, -1) == BadMatch);
+       /* Test huge width */
+       assert(XvMCCreateSubpicture(display, &context, &subpicture, 16384, subpic_height, subpics[0].id) == BadValue);
+       /* Test huge height */
+       assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, 16384, subpics[0].id) == BadValue);
+       /* Test huge width & height */
+       assert(XvMCCreateSubpicture(display, &context, &subpicture, 16384, 16384, subpics[0].id) == BadValue);
+       for (i = 0; i < num_subpics; ++i)
+       {
+               /* Test valid params */
+               assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, subpic_height, subpics[i].id) == Success);
+               /* Test subpicture id assigned */
+               assert(subpicture.subpicture_id != 0);
+               /* Test context id assigned and correct */
+               assert(subpicture.context_id == context.context_id);
+               /* Test subpicture type id assigned and correct */
+               assert(subpicture.xvimage_id == subpics[i].id);
+               /* Test width & height assigned and correct */
+               assert(subpicture.width == width && subpicture.height == height);
+               /* Test no palette support */
+               assert(subpicture.num_palette_entries == 0 && subpicture.entry_bytes == 0);
+               /* Test valid params */
+               assert(XvMCDestroySubpicture(display, &subpicture) == Success);
+       }
+       /* Test NULL surface */
+       assert(XvMCDestroySubpicture(display, NULL) == XvMCBadSubpicture);
+
+       assert(XvMCDestroyContext(display, &context) == Success);
+
+       XFree(subpics);
+       XvUngrabPort(display, port_num, CurrentTime);
+       XCloseDisplay(display);
+
+       return 0;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c
new file mode 100644 (file)
index 0000000..b65eb26
--- /dev/null
@@ -0,0 +1,98 @@
+/**************************************************************************
+ * 
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include <assert.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+       const unsigned int      width = 16, height = 16;
+       const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+
+       Display                 *display;
+       XvPortID                port_num;
+       int                     surface_type_id;
+       unsigned int            is_overlay, intra_unsigned;
+       int                     colorkey;
+       XvMCContext             context;
+       XvMCSurface             surface = {0};
+
+       display = XOpenDisplay(NULL);
+
+       if (!GetPort
+       (
+               display,
+               width,
+               height,
+               XVMC_CHROMA_FORMAT_420,
+               mc_types,
+               2,
+               &port_num,
+               &surface_type_id,
+               &is_overlay,
+               &intra_unsigned
+       ))
+       {
+               XCloseDisplay(display);
+               error(1, 0, "Error, unable to find a good port.\n");
+       }
+
+       if (is_overlay)
+       {
+               Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+               XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+       }
+
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+
+       /* Test NULL context */
+       assert(XvMCCreateSurface(display, NULL, &surface) == XvMCBadContext);
+       /* Test NULL surface */
+       assert(XvMCCreateSurface(display, &context, NULL) == XvMCBadSurface);
+       /* Test valid params */
+       assert(XvMCCreateSurface(display, &context, &surface) == Success);
+       /* Test surface id assigned */
+       assert(surface.surface_id != 0);
+       /* Test context id assigned and correct */
+       assert(surface.context_id == context.context_id);
+       /* Test surface type id assigned and correct */
+       assert(surface.surface_type_id == surface_type_id);
+       /* Test width & height assigned and correct */
+       assert(surface.width == width && surface.height == height);
+       /* Test valid params */
+       assert(XvMCDestroySurface(display, &surface) == Success);
+       /* Test NULL surface */
+       assert(XvMCDestroySurface(display, NULL) == XvMCBadSurface);
+
+       assert(XvMCDestroyContext(display, &context) == Success);
+
+       XvUngrabPort(display, port_num, CurrentTime);
+       XCloseDisplay(display);
+
+       return 0;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/testlib.c b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.c
new file mode 100644 (file)
index 0000000..142c09b
--- /dev/null
@@ -0,0 +1,146 @@
+/**************************************************************************
+ * 
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "testlib.h"
+#include <stdio.h>
+
+/*
+void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line)
+{
+       fputs(doc_string, stderr);
+       if (!pred)
+               fprintf(stderr, " FAIL!\n\t\"%s\" at %s:%u\n", pred_string, file, line);
+       else
+               fputs(" PASS!\n", stderr);
+}
+*/
+
+int GetPort
+(
+       Display *display,
+       unsigned int width,
+       unsigned int height,
+       unsigned int chroma_format,
+       const unsigned int *mc_types,
+       unsigned int num_mc_types,
+       XvPortID *port_id,
+       int *surface_type_id,
+       unsigned int *is_overlay,
+       unsigned int *intra_unsigned
+)
+{
+       unsigned int    found_port = 0;
+       XvAdaptorInfo   *adaptor_info;
+       unsigned int    num_adaptors;
+       int             num_types;
+       int             ev_base, err_base;
+       unsigned int    i, j, k, l;
+
+       if (!XvMCQueryExtension(display, &ev_base, &err_base))
+               return 0;
+       if (XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info) != Success)
+               return 0;
+
+       for (i = 0; i < num_adaptors && !found_port; ++i)
+       {
+               if (adaptor_info[i].type & XvImageMask)
+               {
+                       XvMCSurfaceInfo *surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types);
+
+                       if (surface_info)
+                       {
+                               for (j = 0; j < num_types && !found_port; ++j)
+                               {
+                                       if
+                                       (
+                                               surface_info[j].chroma_format == chroma_format &&
+                                               surface_info[j].max_width >= width &&
+                                               surface_info[j].max_height >= height
+                                       )
+                                       {
+                                               for (k = 0; k < num_mc_types && !found_port; ++k)
+                                               {
+                                                       if (surface_info[j].mc_type == mc_types[k])
+                                                       {
+                                                               for (l = 0; l < adaptor_info[i].num_ports && !found_port; ++l)
+                                                               {
+                                                                       if (XvGrabPort(display, adaptor_info[i].base_id + l, CurrentTime) == Success)
+                                                                       {
+                                                                               *port_id = adaptor_info[i].base_id + l;
+                                                                               *surface_type_id = surface_info[j].surface_type_id;
+                                                                               *is_overlay = surface_info[j].flags & XVMC_OVERLAID_SURFACE;
+                                                                               *intra_unsigned = surface_info[j].flags & XVMC_INTRA_UNSIGNED;
+                                                                               found_port = 1;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               XFree(surface_info);
+                       }
+               }
+       }
+
+       XvFreeAdaptorInfo(adaptor_info);
+
+       return found_port;
+}
+
+unsigned int align(unsigned int value, unsigned int alignment)
+{
+       return (value + alignment - 1) & ~(alignment - 1);
+}
+
+/* From the glibc manual */
+int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
+{
+       /* Perform the carry for the later subtraction by updating y. */
+       if (x->tv_usec < y->tv_usec)
+       {
+               int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
+               y->tv_usec -= 1000000 * nsec;
+               y->tv_sec += nsec;
+       }
+       if (x->tv_usec - y->tv_usec > 1000000)
+       {
+               int nsec = (x->tv_usec - y->tv_usec) / 1000000;
+               y->tv_usec += 1000000 * nsec;
+               y->tv_sec -= nsec;
+       }
+
+       /*
+        * Compute the time remaining to wait.
+        * tv_usec is certainly positive.
+        */
+       result->tv_sec = x->tv_sec - y->tv_sec;
+       result->tv_usec = x->tv_usec - y->tv_usec;
+
+       /* Return 1 if result is negative. */
+       return x->tv_sec < y->tv_sec;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/testlib.h b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.h
new file mode 100644 (file)
index 0000000..0438e52
--- /dev/null
@@ -0,0 +1,69 @@
+/**************************************************************************
+ * 
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef testlib_h
+#define testlib_h
+
+/*
+#define TEST(pred, doc)        test(pred, #pred, doc, __FILE__, __LINE__)
+
+void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line);
+*/
+
+#include <sys/time.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMClib.h>
+
+/*
+ * display: IN                 A valid X display
+ * width, height: IN           Surface size that the port must display
+ * chroma_format: IN           Chroma format that the port must display
+ * mc_types, num_mc_types: IN  List of MC types that the port must support, first port that matches the first mc_type will be returned
+ * port_id: OUT                        Your port's ID
+ * surface_type_id: OUT                Your port's surface ID
+ * is_overlay: OUT             If 1, port uses overlay surfaces, you need to set a colorkey
+ * intra_unsigned: OUT         If 1, port uses unsigned values for intra-coded blocks
+ */
+int GetPort
+(
+       Display *display,
+       unsigned int width,
+       unsigned int height,
+       unsigned int chroma_format,
+       const unsigned int *mc_types,
+       unsigned int num_mc_types,
+       XvPortID *port_id,
+       int *surface_type_id,
+       unsigned int *is_overlay,
+       unsigned int *intra_unsigned
+);
+
+unsigned int align(unsigned int value, unsigned int alignment);
+
+int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y);
+
+#endif
diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c b/src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c
new file mode 100644 (file)
index 0000000..bf94d85
--- /dev/null
@@ -0,0 +1,300 @@
+/**************************************************************************
+ * 
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <error.h>
+#include <sys/time.h>
+#include "testlib.h"
+
+#define MACROBLOCK_WIDTH               16
+#define MACROBLOCK_HEIGHT              16
+#define BLOCKS_PER_MACROBLOCK          6
+
+#define DEFAULT_INPUT_WIDTH            720
+#define DEFAULT_INPUT_HEIGHT           480
+#define DEFAULT_REPS                   100
+
+#define PIPELINE_STEP_MC               1
+#define PIPELINE_STEP_CSC              2
+#define PIPELINE_STEP_SWAP             4
+
+#define MB_TYPE_I                      1
+#define MB_TYPE_P                      2
+#define MB_TYPE_B                      4
+
+struct Config
+{
+       unsigned int input_width;
+       unsigned int input_height;
+       unsigned int output_width;
+       unsigned int output_height;
+       unsigned int pipeline;
+       unsigned int mb_types;
+       unsigned int reps;
+};
+
+void ParseArgs(int argc, char **argv, struct Config *config);
+
+void ParseArgs(int argc, char **argv, struct Config *config)
+{
+       int fail = 0;
+       int i;
+
+       config->input_width = DEFAULT_INPUT_WIDTH;
+       config->input_height = DEFAULT_INPUT_HEIGHT;
+       config->output_width = 0;
+       config->output_height = 0;
+       config->pipeline = 0;
+       config->mb_types = 0;
+       config->reps = DEFAULT_REPS;
+
+       for (i = 1; i < argc && !fail; ++i)
+       {
+               if (!strcmp(argv[i], "-iw"))
+               {
+                       if (sscanf(argv[++i], "%u", &config->input_width) != 1)
+                               fail = 1;
+               }
+               else if (!strcmp(argv[i], "-ih"))
+               {
+                       if (sscanf(argv[++i], "%u", &config->input_height) != 1)
+                               fail = 1;
+               }
+               else if (!strcmp(argv[i], "-ow"))
+               {
+                       if (sscanf(argv[++i], "%u", &config->output_width) != 1)
+                               fail = 1;
+               }
+               else if (!strcmp(argv[i], "-oh"))
+               {
+                       if (sscanf(argv[++i], "%u", &config->output_height) != 1)
+                               fail = 1;
+               }
+               else if (!strcmp(argv[i], "-p"))
+               {
+                       char *token = strtok(argv[++i], ",");
+
+                       while (token && !fail)
+                       {
+                               if (!strcmp(token, "mc"))
+                                       config->pipeline |= PIPELINE_STEP_MC;
+                               else if (!strcmp(token, "csc"))
+                                       config->pipeline |= PIPELINE_STEP_CSC;
+                               else if (!strcmp(token, "swp"))
+                                       config->pipeline |= PIPELINE_STEP_SWAP;
+                               else
+                                       fail = 1;
+
+                               if (!fail)
+                                       token = strtok(NULL, ",");
+                       }
+               }
+               else if (!strcmp(argv[i], "-mb"))
+               {
+                       char *token = strtok(argv[++i], ",");
+
+                       while (token && !fail)
+                       {
+                               if (strcmp(token, "i"))
+                                       config->mb_types |= MB_TYPE_I;
+                               else if (strcmp(token, "p"))
+                                       config->mb_types |= MB_TYPE_P;
+                               else if (strcmp(token, "b"))
+                                       config->mb_types |= MB_TYPE_B;
+                               else
+                                       fail = 1;
+
+                               if (!fail)
+                                       token = strtok(NULL, ",");
+                       }
+               }
+               else if (!strcmp(argv[i], "-r"))
+               {
+                       if (sscanf(argv[++i], "%u", &config->reps) != 1)
+                               fail = 1;
+               }
+               else
+                       fail = 1;
+       }
+
+       if (fail)
+               error
+               (
+                       1, 0,
+                       "Bad argument.\n"
+                       "\n"
+                       "Usage: %s [options]\n"
+                       "\t-iw <width>\tInput width\n"
+                       "\t-ih <height>\tInput height\n"
+                       "\t-ow <width>\tOutput width\n"
+                       "\t-oh <height>\tOutput height\n"
+                       "\t-p <pipeline>\tPipeline to test\n"
+                       "\t-mb <mb type>\tMacroBlock types to use\n"
+                       "\t-r <reps>\tRepetitions\n\n"
+                       "\tPipeline steps: mc,csc,swap\n"
+                       "\tMB types: i,p,b\n",
+                       argv[0]
+               );
+
+       if (config->output_width == 0)
+               config->output_width = config->input_width;
+       if (config->output_height == 0)
+               config->output_height = config->input_height;
+       if (!config->pipeline)
+               config->pipeline = PIPELINE_STEP_MC | PIPELINE_STEP_CSC | PIPELINE_STEP_SWAP;
+       if (!config->mb_types)
+               config->mb_types = MB_TYPE_I | MB_TYPE_P | MB_TYPE_B;
+}
+
+int main(int argc, char **argv)
+{
+       struct Config           config;
+       Display                 *display;
+       Window                  root, window;
+       const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+       XvPortID                port_num;
+       int                     surface_type_id;
+       unsigned int            is_overlay, intra_unsigned;
+       int                     colorkey;
+       XvMCContext             context;
+       XvMCSurface             surface;
+       XvMCBlockArray          block_array;
+       XvMCMacroBlockArray     mb_array;
+       unsigned int            mbw, mbh;
+       unsigned int            mbx, mby;
+       unsigned int            reps;
+       struct timeval          start, stop, diff;
+       double                  diff_secs;
+
+       ParseArgs(argc, argv, &config);
+
+       mbw = align(config.input_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH;
+       mbh = align(config.input_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT;
+
+       display = XOpenDisplay(NULL);
+
+       if (!GetPort
+       (
+               display,
+               config.input_width,
+               config.input_height,
+               XVMC_CHROMA_FORMAT_420,
+               mc_types,
+               2,
+               &port_num,
+               &surface_type_id,
+               &is_overlay,
+               &intra_unsigned
+       ))
+       {
+               XCloseDisplay(display);
+               error(1, 0, "Error, unable to find a good port.\n");
+       }
+
+       if (is_overlay)
+       {
+               Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+               XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+       }
+
+       root = XDefaultRootWindow(display);
+       window = XCreateSimpleWindow(display, root, 0, 0, config.output_width, config.output_height, 0, 0, colorkey);
+
+       assert(XvMCCreateContext(display, port_num, surface_type_id, config.input_width, config.input_height, XVMC_DIRECT, &context) == Success);
+       assert(XvMCCreateSurface(display, &context, &surface) == Success);
+       assert(XvMCCreateBlocks(display, &context, mbw * mbh * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
+       assert(XvMCCreateMacroBlocks(display, &context, mbw * mbh, &mb_array) == Success);
+
+       for (mby = 0; mby < mbh; ++mby)
+               for (mbx = 0; mbx < mbw; ++mbx)
+               {
+                       mb_array.macro_blocks[mby * mbw + mbx].x = mbx;
+                       mb_array.macro_blocks[mby * mbw + mbx].y = mby;
+                       mb_array.macro_blocks[mby * mbw + mbx].macroblock_type = XVMC_MB_TYPE_INTRA;
+                       /*mb->motion_type = ;*/
+                       /*mb->motion_vertical_field_select = ;*/
+                       mb_array.macro_blocks[mby * mbw + mbx].dct_type = XVMC_DCT_TYPE_FRAME;
+                       /*mb->PMV[0][0][0] = ;
+                       mb->PMV[0][0][1] = ;
+                       mb->PMV[0][1][0] = ;
+                       mb->PMV[0][1][1] = ;
+                       mb->PMV[1][0][0] = ;
+                       mb->PMV[1][0][1] = ;
+                       mb->PMV[1][1][0] = ;
+                       mb->PMV[1][1][1] = ;*/
+                       mb_array.macro_blocks[mby * mbw + mbx].index = (mby * mbw + mbx) * BLOCKS_PER_MACROBLOCK;
+                       mb_array.macro_blocks[mby * mbw + mbx].coded_block_pattern = 0x3F;
+               }
+
+       XSelectInput(display, window, ExposureMask | KeyPressMask);
+       XMapWindow(display, window);
+       XSync(display, 0);
+
+       gettimeofday(&start, NULL);
+
+       for (reps = 0; reps < config.reps; ++reps)
+       {
+               if (config.pipeline & PIPELINE_STEP_MC)
+               {
+                       assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, mbw * mbh, 0, &mb_array, &block_array) == Success);
+                       assert(XvMCFlushSurface(display, &surface) == Success);
+               }
+               if (config.pipeline & PIPELINE_STEP_CSC)
+                       assert(XvMCPutSurface(display, &surface, window, 0, 0, config.input_width, config.input_height, 0, 0, config.output_width, config.output_height, XVMC_FRAME_PICTURE) == Success);
+       }
+
+       gettimeofday(&stop, NULL);
+
+       timeval_subtract(&diff, &stop, &start);
+       diff_secs = (double)diff.tv_sec + (double)diff.tv_usec / 1000000.0;
+
+       printf("XvMC Benchmark\n");
+       printf("Input: %u,%u\nOutput: %u,%u\n", config.input_width, config.input_height, config.output_width, config.output_height);
+       printf("Pipeline: ");
+       if (config.pipeline & PIPELINE_STEP_MC)
+               printf("|mc|");
+       if (config.pipeline & PIPELINE_STEP_CSC)
+               printf("|csc|");
+       if (config.pipeline & PIPELINE_STEP_SWAP)
+               printf("|swap|");
+       printf("\n");
+       printf("Reps: %u\n", config.reps);
+       printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs, config.reps / diff_secs);
+
+       assert(XvMCDestroyBlocks(display, &block_array) == Success);
+       assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
+       assert(XvMCDestroySurface(display, &surface) == Success);
+       assert(XvMCDestroyContext(display, &context) == Success);
+
+       XvUngrabPort(display, port_num, CurrentTime);
+       XDestroyWindow(display, window);
+       XCloseDisplay(display);
+
+       return 0;
+}
diff --git a/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h
new file mode 100644 (file)
index 0000000..1e2dfb4
--- /dev/null
@@ -0,0 +1,102 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef xvmc_private_h
+#define xvmc_private_h
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMClib.h>
+#include <util/u_debug.h>
+
+#define BLOCK_SIZE_SAMPLES 64
+#define BLOCK_SIZE_BYTES (BLOCK_SIZE_SAMPLES * 2)
+
+struct vl_context;
+struct pipe_surface;
+struct pipe_fence_handle;
+
+typedef struct
+{
+   struct vl_context *vctx;
+   struct pipe_surface *backbuffer;
+   unsigned short subpicture_max_width;
+   unsigned short subpicture_max_height;
+} XvMCContextPrivate;
+
+typedef struct
+{
+   struct pipe_surface *pipe_vsfc;
+   struct pipe_fence_handle *render_fence;
+   struct pipe_fence_handle *disp_fence;
+
+   /* The subpicture associated with this surface, if any. */
+   XvMCSubpicture *subpicture;
+   short subx, suby;
+   unsigned short subw, subh;
+   short surfx, surfy;
+   unsigned short surfw, surfh;
+
+   /* Some XvMC functions take a surface but not a context,
+      so we keep track of which context each surface belongs to. */
+   XvMCContext *context;
+} XvMCSurfacePrivate;
+
+typedef struct
+{
+   struct pipe_surface *sfc;
+
+   /* The surface this subpicture is currently associated with, if any. */
+   XvMCSurface *surface;
+
+   /* Some XvMC functions take a subpicture but not a context,
+      so we keep track of which context each subpicture belongs to. */
+   XvMCContext *context;
+} XvMCSubpicturePrivate;
+
+#define XVMC_OUT   0
+#define XVMC_ERR   1
+#define XVMC_WARN  2
+#define XVMC_TRACE 3
+static INLINE void XVMC_MSG(unsigned int level, const char *fmt, ...)
+{
+   static boolean check_dbg_level = TRUE;
+   static unsigned int debug_level;
+
+   if (check_dbg_level) {
+      debug_level = debug_get_num_option("XVMC_DEBUG", 0);
+      check_dbg_level = FALSE;
+   }
+
+   if (level <= debug_level) {
+      va_list ap;
+      va_start(ap, fmt);
+      _debug_vprintf(fmt, ap);
+      va_end(ap);
+   }
+}
+
+#endif /* xvmc_private_h */
diff --git a/src/gallium/targets/Makefile.vdpau b/src/gallium/targets/Makefile.vdpau
new file mode 100644 (file)
index 0000000..e5c3dad
--- /dev/null
@@ -0,0 +1,61 @@
+# This makefile template is used to build libvdpau_g3dvl.so
+
+LIBBASENAME = vdpau_g3dvl
+LIBNAME = lib$(LIBBASENAME).so
+VDPAU_MAJOR = 1
+VDPAU_MINOR = 0
+INCLUDES = -I$(TOP)/src/gallium/include \
+          -I$(TOP)/src/gallium/drivers \
+          -I$(TOP)/src/gallium/auxiliary \
+          -I$(TOP)/src/gallium/winsys/g3dvl \
+          $(DRIVER_INCLUDES)
+DEFINES = -DGALLIUM_TRACE $(DRIVER_DEFINES)
+LIBS = $(EXTRA_LIB_PATH) $(DRIVER_LIBS) -lvdpau -lXext -lX11 -lm
+STATE_TRACKER_LIB = $(TOP)/src/gallium/state_trackers/vdpau/libvdpautracker.a
+
+# XXX: Hack, VDPAU public funcs aren't exported if we link to libvdpautracker.a :(
+OBJECTS = $(C_SOURCES:.c=.o) \
+         $(ASM_SOURCES:.S=.o) \
+         $(TOP)/src/gallium/state_trackers/vdpau/*.o
+
+##### RULES #####
+
+.c.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+.S.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+##### TARGETS #####
+
+default: depend symlinks $(TOP)/$(LIB_DIR)/gallium/$(LIBNAME)
+
+$(TOP)/$(LIB_DIR)/gallium/$(LIBNAME): $(OBJECTS) $(PIPE_DRIVERS) $(STATE_TRACKER_LIB) $(TOP)/$(LIB_DIR)/gallium Makefile
+       $(MKLIB) -o $(LIBBASENAME) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
+               -major $(VDPAU_MAJOR) -minor $(VDPAU_MINOR) $(MKLIB_OPTIONS) \
+               -install $(TOP)/$(LIB_DIR)/gallium \
+               $(OBJECTS) $(STATE_TRACKER_LIB) $(PIPE_DRIVERS) $(LIBS)
+
+$(TOP)/$(LIB_DIR)/gallium:
+       mkdir -p $@
+
+depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
+       rm -f depend
+       touch depend
+       $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(C_SOURCES) \
+               $(ASM_SOURCES) 2> /dev/null
+
+# Emacs tags
+tags:
+       etags `find . -name \*.[ch]` `find ../include`
+
+# Remove .o and backup files
+clean:
+       -rm -f *.o *~ *.so $(SYMLINKS)
+       -rm -f depend depend.bak
+
+#install: $(LIBNAME)
+#      $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+#      $(MINSTALL) -m 755 $(LIBNAME) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+
+include depend
diff --git a/src/gallium/targets/Makefile.xvmc b/src/gallium/targets/Makefile.xvmc
new file mode 100644 (file)
index 0000000..e48906a
--- /dev/null
@@ -0,0 +1,61 @@
+# This makefile template is used to build libXvMCg3dvl.so
+
+LIBBASENAME = XvMCg3dvl
+LIBNAME = lib$(LIBBASENAME).so
+XVMC_MAJOR = 1
+XVMC_MINOR = 0
+INCLUDES = -I$(TOP)/src/gallium/include \
+          -I$(TOP)/src/gallium/drivers \
+          -I$(TOP)/src/gallium/auxiliary \
+          -I$(TOP)/src/gallium/winsys/g3dvl \
+          $(DRIVER_INCLUDES)
+DEFINES = -DGALLIUM_TRACE $(DRIVER_DEFINES)
+LIBS = $(EXTRA_LIB_PATH) $(DRIVER_LIBS) -lXvMC -lXv -lX11 -lm
+STATE_TRACKER_LIB = $(TOP)/src/gallium/state_trackers/xorg/xvmc/libxvmctracker.a
+
+# XXX: Hack, XvMC public funcs aren't exported if we link to libxvmctracker.a :(
+OBJECTS = $(C_SOURCES:.c=.o) \
+         $(ASM_SOURCES:.S=.o) \
+         $(TOP)/src/gallium/state_trackers/xorg/xvmc/*.o
+
+##### RULES #####
+
+.c.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+.S.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+##### TARGETS #####
+
+default: depend symlinks $(TOP)/$(LIB_DIR)/gallium/$(LIBNAME)
+
+$(TOP)/$(LIB_DIR)/gallium/$(LIBNAME): $(OBJECTS) $(PIPE_DRIVERS) $(STATE_TRACKER_LIB) $(TOP)/$(LIB_DIR)/gallium Makefile
+       $(MKLIB) -o $(LIBBASENAME) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
+               -major $(XVMC_MAJOR) -minor $(XVMC_MINOR) $(MKLIB_OPTIONS) \
+               -install $(TOP)/$(LIB_DIR)/gallium \
+               $(OBJECTS) $(STATE_TRACKER_LIB) $(PIPE_DRIVERS) $(LIBS)
+
+$(TOP)/$(LIB_DIR)/gallium:
+       mkdir -p $@
+
+depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
+       rm -f depend
+       touch depend
+       $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(C_SOURCES) \
+               $(ASM_SOURCES) 2> /dev/null
+
+# Emacs tags
+tags:
+       etags `find . -name \*.[ch]` `find ../include`
+
+# Remove .o and backup files
+clean:
+       -rm -f *.o *~ *.so $(SYMLINKS)
+       -rm -f depend depend.bak
+
+#install: $(LIBNAME)
+#      $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+#      $(MINSTALL) -m 755 $(LIBNAME) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+
+include depend
index 2f64f312b841cdad42c8f7120ddd8ac10fd4a5b4..9dfe86c8949cfd396eee481794ac5d6022a5fbff 100644 (file)
@@ -10,6 +10,7 @@ PIPE_DRIVERS = \
        $(TOP)/src/gallium/drivers/rbug/librbug.a \
        $(TOP)/src/gallium/drivers/nvfx/libnvfx.a \
        $(TOP)/src/gallium/drivers/nv50/libnv50.a \
+       $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
        $(TOP)/src/gallium/drivers/nouveau/libnouveau.a
 
 C_SOURCES = \
diff --git a/src/gallium/targets/vdpau-softpipe/Makefile b/src/gallium/targets/vdpau-softpipe/Makefile
new file mode 100644 (file)
index 0000000..29dea50
--- /dev/null
@@ -0,0 +1,19 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+DRIVER_DEFINES = -DGALLIUM_SOFTPIPE
+DRIVER_INCLUDES =
+
+PIPE_DRIVERS = \
+       $(TOP)/src/gallium/winsys/sw/xlib/libws_xlib.a \
+       $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
+       $(TOP)/src/gallium/auxiliary/libgallium.a
+
+C_SOURCES = \
+       $(TOP)/src/gallium/winsys/g3dvl/xlib/xsp_winsys.c
+
+DRIVER_LIBS =
+
+include ../Makefile.vdpau
+
+symlinks:
diff --git a/src/gallium/targets/xvmc-nouveau/Makefile b/src/gallium/targets/xvmc-nouveau/Makefile
new file mode 100644 (file)
index 0000000..fe418b0
--- /dev/null
@@ -0,0 +1,23 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+#LIBNAME =
+
+PIPE_DRIVERS = \
+       $(TOP)/src/gallium/winsys/g3dvl/dri/libvldri.a \
+       $(TOP)/src/gallium/winsys/nouveau/drm/libnouveaudrm.a \
+       $(TOP)/src/gallium/drivers/nvfx/libnvfx.a \
+       $(TOP)/src/gallium/drivers/nv50/libnv50.a \
+       $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
+       $(TOP)/src/gallium/drivers/nouveau/libnouveau.a \
+       $(TOP)/src/gallium/auxiliary/libgallium.a
+
+C_SOURCES = \
+       $(COMMON_GALLIUM_SOURCES) \
+       $(DRIVER_SOURCES)
+
+DRIVER_LIBS = $(shell pkg-config libdrm_nouveau --libs) -lXfixes
+
+include ../Makefile.xvmc
+
+symlinks:
diff --git a/src/gallium/targets/xvmc-softpipe/Makefile b/src/gallium/targets/xvmc-softpipe/Makefile
new file mode 100644 (file)
index 0000000..1e3ff8a
--- /dev/null
@@ -0,0 +1,19 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+DRIVER_DEFINES = -DGALLIUM_SOFTPIPE
+DRIVER_INCLUDES =
+
+PIPE_DRIVERS = \
+       $(TOP)/src/gallium/winsys/sw/xlib/libws_xlib.a \
+       $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
+       $(TOP)/src/gallium/auxiliary/libgallium.a
+
+C_SOURCES = \
+       $(TOP)/src/gallium/winsys/g3dvl/xlib/xsp_winsys.c
+
+DRIVER_LIBS =
+
+include ../Makefile.xvmc
+
+symlinks:
diff --git a/src/gallium/winsys/g3dvl/Makefile b/src/gallium/winsys/g3dvl/Makefile
new file mode 100644 (file)
index 0000000..6c793e0
--- /dev/null
@@ -0,0 +1,12 @@
+# src/gallium/winsys/Makefile
+TOP = ../../../..
+include $(TOP)/configs/current
+
+SUBDIRS = $(GALLIUM_STATE_TRACKERS_DIRS) $(GALLIUM_WINSYS_DIRS)
+
+default install clean:
+       @for dir in $(SUBDIRS) ; do \
+               if [ -d $$dir ] ; then \
+                       (cd $$dir && $(MAKE) $@) || exit 1; \
+               fi \
+       done
diff --git a/src/gallium/winsys/g3dvl/dri/Makefile b/src/gallium/winsys/g3dvl/dri/Makefile
new file mode 100644 (file)
index 0000000..b270e78
--- /dev/null
@@ -0,0 +1,15 @@
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = vldri
+
+LIBRARY_INCLUDES = -I$(TOP)/src/gallium/winsys/g3dvl \
+                   $(shell pkg-config libdrm --cflags-only-I)
+
+C_SOURCES = \
+       driclient.c \
+       XF86dri.c \
+       dri2.c \
+       dri_winsys.c
+
+include ../../../Makefile.template
diff --git a/src/gallium/winsys/g3dvl/dri/XF86dri.c b/src/gallium/winsys/g3dvl/dri/XF86dri.c
new file mode 100644 (file)
index 0000000..831a760
--- /dev/null
@@ -0,0 +1,618 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Jens Owen <jens@tungstengraphics.com>
+ *   Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ */
+
+/* THIS IS NOT AN X CONSORTIUM STANDARD */
+
+#include <X11/Xlibint.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include "xf86dristr.h"
+
+static XExtensionInfo _xf86dri_info_data;
+static XExtensionInfo *xf86dri_info = &_xf86dri_info_data;
+static char xf86dri_extension_name[] = XF86DRINAME;
+
+#define XF86DRICheckExtension(dpy,i,val) \
+  XextCheckExtension (dpy, i, xf86dri_extension_name, val)
+
+/*****************************************************************************
+ *                                                                           *
+ *                        private utility routines                          *
+ *                                                                           *
+ *****************************************************************************/
+
+static int close_display(Display *dpy, XExtCodes *extCodes);
+static /* const */ XExtensionHooks xf86dri_extension_hooks = {
+    NULL,                              /* create_gc */
+    NULL,                              /* copy_gc */
+    NULL,                              /* flush_gc */
+    NULL,                              /* free_gc */
+    NULL,                              /* create_font */
+    NULL,                              /* free_font */
+    close_display,                     /* close_display */
+    NULL,                              /* wire_to_event */
+    NULL,                              /* event_to_wire */
+    NULL,                              /* error */
+    NULL,                              /* error_string */
+};
+
+static XEXT_GENERATE_FIND_DISPLAY (find_display, xf86dri_info, 
+                                  xf86dri_extension_name, 
+                                  &xf86dri_extension_hooks, 
+                                  0, NULL)
+
+static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86dri_info)
+
+
+/*****************************************************************************
+ *                                                                           *
+ *                 public XFree86-DRI Extension routines                    *
+ *                                                                           *
+ *****************************************************************************/
+
+#if 0
+#include <stdio.h>
+#define TRACE(msg)  fprintf(stderr,"XF86DRI%s\n", msg);
+#else
+#define TRACE(msg)
+#endif
+
+#define PUBLIC
+
+PUBLIC Bool XF86DRIQueryExtension (dpy, event_basep, error_basep)
+    Display *dpy;
+    int *event_basep, *error_basep;
+{
+    XExtDisplayInfo *info = find_display (dpy);
+
+    TRACE("QueryExtension...");
+    if (XextHasExtension(info)) {
+       *event_basep = info->codes->first_event;
+       *error_basep = info->codes->first_error;
+        TRACE("QueryExtension... return True");
+       return True;
+    } else {
+        TRACE("QueryExtension... return False");
+       return False;
+    }
+}
+
+PUBLIC Bool XF86DRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion)
+    Display* dpy;
+    int* majorVersion; 
+    int* minorVersion;
+    int* patchVersion;
+{
+    XExtDisplayInfo *info = find_display (dpy);
+    xXF86DRIQueryVersionReply rep;
+    xXF86DRIQueryVersionReq *req;
+
+    TRACE("QueryVersion...");
+    XF86DRICheckExtension (dpy, info, False);
+
+    LockDisplay(dpy);
+    GetReq(XF86DRIQueryVersion, req);
+    req->reqType = info->codes->major_opcode;
+    req->driReqType = X_XF86DRIQueryVersion;
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+        TRACE("QueryVersion... return False");
+       return False;
+    }
+    *majorVersion = rep.majorVersion;
+    *minorVersion = rep.minorVersion;
+    *patchVersion = rep.patchVersion;
+    UnlockDisplay(dpy);
+    SyncHandle();
+    TRACE("QueryVersion... return True");
+    return True;
+}
+
+PUBLIC Bool XF86DRIQueryDirectRenderingCapable(dpy, screen, isCapable)
+    Display* dpy;
+    int screen;
+    Bool* isCapable;
+{
+    XExtDisplayInfo *info = find_display (dpy);
+    xXF86DRIQueryDirectRenderingCapableReply rep;
+    xXF86DRIQueryDirectRenderingCapableReq *req;
+
+    TRACE("QueryDirectRenderingCapable...");
+    XF86DRICheckExtension (dpy, info, False);
+
+    LockDisplay(dpy);
+    GetReq(XF86DRIQueryDirectRenderingCapable, req);
+    req->reqType = info->codes->major_opcode;
+    req->driReqType = X_XF86DRIQueryDirectRenderingCapable;
+    req->screen = screen;
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+        TRACE("QueryDirectRenderingCapable... return False");
+       return False;
+    }
+    *isCapable = rep.isCapable;
+    UnlockDisplay(dpy);
+    SyncHandle();
+    TRACE("QueryDirectRenderingCapable... return True");
+    return True;
+}
+
+PUBLIC Bool XF86DRIOpenConnection(dpy, screen, hSAREA, busIdString)
+    Display* dpy;
+    int screen;
+    drm_handle_t * hSAREA;
+    char **busIdString;
+{
+    XExtDisplayInfo *info = find_display (dpy);
+    xXF86DRIOpenConnectionReply rep;
+    xXF86DRIOpenConnectionReq *req;
+
+    TRACE("OpenConnection...");
+    XF86DRICheckExtension (dpy, info, False);
+
+    LockDisplay(dpy);
+    GetReq(XF86DRIOpenConnection, req);
+    req->reqType = info->codes->major_opcode;
+    req->driReqType = X_XF86DRIOpenConnection;
+    req->screen = screen;
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+        TRACE("OpenConnection... return False");
+       return False;
+    }
+
+    *hSAREA = rep.hSAREALow;
+    if (sizeof(drm_handle_t) == 8) {
+       int shift = 32; /* var to prevent warning on next line */
+       *hSAREA |= ((drm_handle_t) rep.hSAREAHigh) << shift;
+    }
+
+    if (rep.length) {
+        if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) {
+            _XEatData(dpy, ((rep.busIdStringLength+3) & ~3));
+            UnlockDisplay(dpy);
+            SyncHandle();
+            TRACE("OpenConnection... return False");
+            return False;
+        }
+       _XReadPad(dpy, *busIdString, rep.busIdStringLength);
+    } else {
+        *busIdString = NULL;
+    }
+    UnlockDisplay(dpy);
+    SyncHandle();
+    TRACE("OpenConnection... return True");
+    return True;
+}
+
+PUBLIC Bool XF86DRIAuthConnection(dpy, screen, magic)
+    Display* dpy;
+    int screen;
+    drm_magic_t magic;
+{
+    XExtDisplayInfo *info = find_display (dpy);
+    xXF86DRIAuthConnectionReq *req;
+    xXF86DRIAuthConnectionReply rep;
+
+    TRACE("AuthConnection...");
+    XF86DRICheckExtension (dpy, info, False);
+
+    LockDisplay(dpy);
+    GetReq(XF86DRIAuthConnection, req);
+    req->reqType = info->codes->major_opcode;
+    req->driReqType = X_XF86DRIAuthConnection;
+    req->screen = screen;
+    req->magic = magic;
+    rep.authenticated = 0;
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.authenticated) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+        TRACE("AuthConnection... return False");
+       return False;
+    }
+    UnlockDisplay(dpy);
+    SyncHandle();
+    TRACE("AuthConnection... return True");
+    return True;
+}
+
+PUBLIC Bool XF86DRICloseConnection(dpy, screen)
+    Display* dpy;
+    int screen;
+{
+    XExtDisplayInfo *info = find_display (dpy);
+    xXF86DRICloseConnectionReq *req;
+
+    TRACE("CloseConnection...");
+
+    XF86DRICheckExtension (dpy, info, False);
+
+    LockDisplay(dpy);
+    GetReq(XF86DRICloseConnection, req);
+    req->reqType = info->codes->major_opcode;
+    req->driReqType = X_XF86DRICloseConnection;
+    req->screen = screen;
+    UnlockDisplay(dpy);
+    SyncHandle();
+    TRACE("CloseConnection... return True");
+    return True;
+}
+
+PUBLIC Bool XF86DRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion, 
+       ddxDriverMinorVersion, ddxDriverPatchVersion, clientDriverName)
+    Display* dpy;
+    int screen;
+    int* ddxDriverMajorVersion;
+    int* ddxDriverMinorVersion;
+    int* ddxDriverPatchVersion;
+    char** clientDriverName;
+{
+    XExtDisplayInfo *info = find_display (dpy);
+    xXF86DRIGetClientDriverNameReply rep;
+    xXF86DRIGetClientDriverNameReq *req;
+
+    TRACE("GetClientDriverName...");
+    XF86DRICheckExtension (dpy, info, False);
+
+    LockDisplay(dpy);
+    GetReq(XF86DRIGetClientDriverName, req);
+    req->reqType = info->codes->major_opcode;
+    req->driReqType = X_XF86DRIGetClientDriverName;
+    req->screen = screen;
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+        TRACE("GetClientDriverName... return False");
+       return False;
+    }
+
+    *ddxDriverMajorVersion = rep.ddxDriverMajorVersion;
+    *ddxDriverMinorVersion = rep.ddxDriverMinorVersion;
+    *ddxDriverPatchVersion = rep.ddxDriverPatchVersion;
+
+    if (rep.length) {
+        if (!(*clientDriverName = (char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) {
+            _XEatData(dpy, ((rep.clientDriverNameLength+3) & ~3));
+            UnlockDisplay(dpy);
+            SyncHandle();
+            TRACE("GetClientDriverName... return False");
+            return False;
+        }
+       _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength);
+    } else {
+        *clientDriverName = NULL;
+    }
+    UnlockDisplay(dpy);
+    SyncHandle();
+    TRACE("GetClientDriverName... return True");
+    return True;
+}
+
+PUBLIC Bool XF86DRICreateContextWithConfig(dpy, screen, configID, context,
+       hHWContext)
+    Display* dpy;
+    int screen;
+    int configID;
+    XID* context;
+    drm_context_t * hHWContext;
+{
+    XExtDisplayInfo *info = find_display (dpy);
+    xXF86DRICreateContextReply rep;
+    xXF86DRICreateContextReq *req;
+
+    TRACE("CreateContext...");
+    XF86DRICheckExtension (dpy, info, False);
+
+    LockDisplay(dpy);
+    GetReq(XF86DRICreateContext, req);
+    req->reqType = info->codes->major_opcode;
+    req->driReqType = X_XF86DRICreateContext;
+    req->visual = configID;
+    req->screen = screen;
+    *context = XAllocID(dpy);
+    req->context = *context;
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+        TRACE("CreateContext... return False");
+       return False;
+    }
+    *hHWContext = rep.hHWContext;
+    UnlockDisplay(dpy);
+    SyncHandle();
+    TRACE("CreateContext... return True");
+    return True;
+}
+
+PUBLIC Bool XF86DRICreateContext(dpy, screen, visual, context, hHWContext)
+    Display* dpy;
+    int screen;
+    Visual* visual;
+    XID* context;
+    drm_context_t * hHWContext;
+{
+    return XF86DRICreateContextWithConfig( dpy, screen, visual->visualid,
+                                          context, hHWContext );
+}
+
+PUBLIC Bool XF86DRIDestroyContext( Display * ndpy, int screen, 
+    XID context )
+{
+    Display * const dpy = (Display *) ndpy;
+    XExtDisplayInfo *info = find_display (dpy);
+    xXF86DRIDestroyContextReq *req;
+
+    TRACE("DestroyContext...");
+    XF86DRICheckExtension (dpy, info, False);
+
+    LockDisplay(dpy);
+    GetReq(XF86DRIDestroyContext, req);
+    req->reqType = info->codes->major_opcode;
+    req->driReqType = X_XF86DRIDestroyContext;
+    req->screen = screen;
+    req->context = context;
+    UnlockDisplay(dpy);
+    SyncHandle();
+    TRACE("DestroyContext... return True");
+    return True;
+}
+
+PUBLIC Bool XF86DRICreateDrawable( Display * ndpy, int screen, 
+    Drawable drawable, drm_drawable_t * hHWDrawable )
+{
+    Display * const dpy = (Display *) ndpy;
+    XExtDisplayInfo *info = find_display (dpy);
+    xXF86DRICreateDrawableReply rep;
+    xXF86DRICreateDrawableReq *req;
+
+    TRACE("CreateDrawable...");
+    XF86DRICheckExtension (dpy, info, False);
+
+    LockDisplay(dpy);
+    GetReq(XF86DRICreateDrawable, req);
+    req->reqType = info->codes->major_opcode;
+    req->driReqType = X_XF86DRICreateDrawable;
+    req->screen = screen;
+    req->drawable = drawable;
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+        TRACE("CreateDrawable... return False");
+       return False;
+    }
+    *hHWDrawable = rep.hHWDrawable;
+    UnlockDisplay(dpy);
+    SyncHandle();
+    TRACE("CreateDrawable... return True");
+    return True;
+}
+
+PUBLIC Bool XF86DRIDestroyDrawable( Display * ndpy, int screen,
+    Drawable drawable )
+{
+    Display * const dpy = (Display *) ndpy;
+    XExtDisplayInfo *info = find_display (dpy);
+    xXF86DRIDestroyDrawableReq *req;
+
+    TRACE("DestroyDrawable...");
+    XF86DRICheckExtension (dpy, info, False);
+
+    LockDisplay(dpy);
+    GetReq(XF86DRIDestroyDrawable, req);
+    req->reqType = info->codes->major_opcode;
+    req->driReqType = X_XF86DRIDestroyDrawable;
+    req->screen = screen;
+    req->drawable = drawable;
+    UnlockDisplay(dpy);
+    SyncHandle();
+    TRACE("DestroyDrawable... return True");
+    return True;
+}
+
+PUBLIC Bool XF86DRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable,
+    unsigned int* index, unsigned int* stamp,
+    int* X, int* Y, int* W, int* H,
+    int* numClipRects, drm_clip_rect_t ** pClipRects,
+    int* backX, int* backY,
+    int* numBackClipRects, drm_clip_rect_t ** pBackClipRects )
+{
+    XExtDisplayInfo *info = find_display (dpy);
+    xXF86DRIGetDrawableInfoReply rep;
+    xXF86DRIGetDrawableInfoReq *req;
+    int total_rects;
+
+    TRACE("GetDrawableInfo...");
+    XF86DRICheckExtension (dpy, info, False);
+
+    LockDisplay(dpy);
+    GetReq(XF86DRIGetDrawableInfo, req);
+    req->reqType = info->codes->major_opcode;
+    req->driReqType = X_XF86DRIGetDrawableInfo;
+    req->screen = screen;
+    req->drawable = drawable;
+
+    if (!_XReply(dpy, (xReply *)&rep, 1, xFalse)) 
+    {
+       UnlockDisplay(dpy);
+       SyncHandle();
+        TRACE("GetDrawableInfo... return False");
+       return False;
+    }
+    *index = rep.drawableTableIndex;
+    *stamp = rep.drawableTableStamp;
+    *X = (int)rep.drawableX;
+    *Y = (int)rep.drawableY;
+    *W = (int)rep.drawableWidth;
+    *H = (int)rep.drawableHeight;
+    *numClipRects = rep.numClipRects;
+    total_rects = *numClipRects;
+
+    *backX = rep.backX;
+    *backY = rep.backY;
+    *numBackClipRects = rep.numBackClipRects;
+    total_rects += *numBackClipRects;
+
+#if 0
+    /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
+     * backwards compatibility (Because of the >> 2 shift) but the fix
+     * enables multi-threaded apps to work.
+     */
+    if (rep.length !=  ((((SIZEOF(xXF86DRIGetDrawableInfoReply) - 
+                      SIZEOF(xGenericReply) + 
+                      total_rects * sizeof(drm_clip_rect_t)) + 3) & ~3) >> 2)) {
+        _XEatData(dpy, rep.length);
+       UnlockDisplay(dpy);
+       SyncHandle();
+        TRACE("GetDrawableInfo... return False");
+        return False;
+    }
+#endif
+
+    if (*numClipRects) {
+       int len = sizeof(drm_clip_rect_t) * (*numClipRects);
+
+       *pClipRects = (drm_clip_rect_t *)Xcalloc(len, 1);
+       if (*pClipRects) 
+         _XRead(dpy, (char*)*pClipRects, len);
+    } else {
+        *pClipRects = NULL;
+    }
+
+    if (*numBackClipRects) {
+       int len = sizeof(drm_clip_rect_t) * (*numBackClipRects);
+
+       *pBackClipRects = (drm_clip_rect_t *)Xcalloc(len, 1);
+       if (*pBackClipRects) 
+         _XRead(dpy, (char*)*pBackClipRects, len);
+    } else {
+        *pBackClipRects = NULL;
+    }
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+    TRACE("GetDrawableInfo... return True");
+    return True;
+}
+
+PUBLIC Bool XF86DRIGetDeviceInfo(dpy, screen, hFrameBuffer, 
+       fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate)
+    Display* dpy;
+    int screen;
+    drm_handle_t * hFrameBuffer;
+    int* fbOrigin;
+    int* fbSize;
+    int* fbStride;
+    int* devPrivateSize;
+    void** pDevPrivate;
+{
+    XExtDisplayInfo *info = find_display (dpy);
+    xXF86DRIGetDeviceInfoReply rep;
+    xXF86DRIGetDeviceInfoReq *req;
+
+    TRACE("GetDeviceInfo...");
+    XF86DRICheckExtension (dpy, info, False);
+
+    LockDisplay(dpy);
+    GetReq(XF86DRIGetDeviceInfo, req);
+    req->reqType = info->codes->major_opcode;
+    req->driReqType = X_XF86DRIGetDeviceInfo;
+    req->screen = screen;
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+        TRACE("GetDeviceInfo... return False");
+       return False;
+    }
+
+    *hFrameBuffer = rep.hFrameBufferLow;
+    if (sizeof(drm_handle_t) == 8) {
+       int shift = 32; /* var to prevent warning on next line */
+       *hFrameBuffer |= ((drm_handle_t) rep.hFrameBufferHigh) << shift;
+    }
+
+    *fbOrigin = rep.framebufferOrigin;
+    *fbSize = rep.framebufferSize;
+    *fbStride = rep.framebufferStride;
+    *devPrivateSize = rep.devPrivateSize;
+
+    if (rep.length) {
+        if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) {
+            _XEatData(dpy, ((rep.devPrivateSize+3) & ~3));
+            UnlockDisplay(dpy);
+            SyncHandle();
+            TRACE("GetDeviceInfo... return False");
+            return False;
+        }
+       _XRead(dpy, (char*)*pDevPrivate, rep.devPrivateSize);
+    } else {
+        *pDevPrivate = NULL;
+    }
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+    TRACE("GetDeviceInfo... return True");
+    return True;
+}
+
+PUBLIC Bool XF86DRIOpenFullScreen(dpy, screen, drawable)
+    Display* dpy;
+    int screen;
+    Drawable drawable;
+{
+    /* This function and the underlying X protocol are deprecated.
+     */
+    (void) dpy;
+    (void) screen;
+    (void) drawable;
+    return False;
+}
+
+PUBLIC Bool XF86DRICloseFullScreen(dpy, screen, drawable)
+    Display* dpy;
+    int screen;
+    Drawable drawable;
+{
+    /* This function and the underlying X protocol are deprecated.
+     */
+    (void) dpy;
+    (void) screen;
+    (void) drawable;
+    return True;
+}
+
diff --git a/src/gallium/winsys/g3dvl/dri/dri2.c b/src/gallium/winsys/g3dvl/dri/dri2.c
new file mode 100644 (file)
index 0000000..23fb778
--- /dev/null
@@ -0,0 +1,669 @@
+/*
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Kristian Høgsberg (krh@redhat.com)
+ */
+
+
+#define NEED_REPLIES
+#include <stdio.h>
+#include <X11/Xlibint.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include <X11/extensions/dri2proto.h>
+#include "xf86drm.h"
+#include "dri2.h"
+#if 0
+#include "glxclient.h"
+#include "GL/glxext.h"
+#endif
+
+/* Allow the build to work with an older versions of dri2proto.h and
+ * dri2tokens.h.
+ */
+#if DRI2_MINOR < 1
+#undef DRI2_MINOR
+#define DRI2_MINOR 1
+#define X_DRI2GetBuffersWithFormat 7
+#endif
+
+
+static char dri2ExtensionName[] = DRI2_NAME;
+static XExtensionInfo *dri2Info;
+static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
+
+static Bool
+DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire);
+static Status
+DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire);
+
+static /* const */ XExtensionHooks dri2ExtensionHooks = {
+  NULL,                   /* create_gc */
+  NULL,                   /* copy_gc */
+  NULL,                   /* flush_gc */
+  NULL,                   /* free_gc */
+  NULL,                   /* create_font */
+  NULL,                   /* free_font */
+  DRI2CloseDisplay,       /* close_display */
+  DRI2WireToEvent,        /* wire_to_event */
+  DRI2EventToWire,        /* event_to_wire */
+  NULL,                   /* error */
+  NULL,                   /* error_string */
+};
+
+static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
+                                   dri2Info,
+                                   dri2ExtensionName,
+                                   &dri2ExtensionHooks,
+                                   0, NULL)
+
+static Bool
+DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
+{
+#if 0
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   XExtDisplayInfo *glx_info = __glXFindDisplay(dpy);
+
+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+   switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
+
+#ifdef X_DRI2SwapBuffers
+   case DRI2_BufferSwapComplete:
+   {
+      GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
+      xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire;
+      aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
+      aevent->type =
+         (glx_info->codes->first_event + GLX_BufferSwapComplete) & 0x75;
+      aevent->send_event = (awire->type & 0x80) != 0;
+      aevent->display = dpy;
+      aevent->drawable = awire->drawable;
+      switch (awire->event_type) {
+      case DRI2_EXCHANGE_COMPLETE:
+        aevent->event_type = GLX_EXCHANGE_COMPLETE_INTEL;
+        break;
+      case DRI2_BLIT_COMPLETE:
+        aevent->event_type = GLX_BLIT_COMPLETE_INTEL;
+        break;
+      case DRI2_FLIP_COMPLETE:
+        aevent->event_type = GLX_FLIP_COMPLETE_INTEL;
+        break;
+      default:
+        /* unknown swap completion type */
+        return False;
+      }
+      aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
+      aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
+      aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo;
+      return True;
+   }
+#endif
+#ifdef DRI2_InvalidateBuffers
+   case DRI2_InvalidateBuffers:
+   {
+      xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire;
+
+      dri2InvalidateBuffers(dpy, awire->drawable);
+      return False;
+   }
+#endif
+   default:
+      /* client doesn't support server event */
+      break;
+   }
+#endif
+   return False;
+}
+
+/* We don't actually support this.  It doesn't make sense for clients to
+ * send each other DRI2 events.
+ */
+static Status
+DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+
+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+   switch (event->type) {
+   default:
+      /* client doesn't support server event */
+      break;
+   }
+
+   return Success;
+}
+
+Bool
+DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+
+   if (XextHasExtension(info)) {
+      *eventBase = info->codes->first_event;
+      *errorBase = info->codes->first_error;
+      return True;
+   }
+
+   return False;
+}
+
+Bool
+DRI2QueryVersion(Display * dpy, int *major, int *minor)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2QueryVersionReply rep;
+   xDRI2QueryVersionReq *req;
+   int i, nevents;
+
+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+   LockDisplay(dpy);
+   GetReq(DRI2QueryVersion, req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2QueryVersion;
+   req->majorVersion = DRI2_MAJOR;
+   req->minorVersion = DRI2_MINOR;
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return False;
+   }
+   *major = rep.majorVersion;
+   *minor = rep.minorVersion;
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   switch (rep.minorVersion) {
+   case 1:
+          nevents = 0;
+          break;
+   case 2:
+          nevents = 1;
+          break;
+   case 3:
+   default:
+          nevents = 2;
+          break;
+   }
+       
+   for (i = 0; i < nevents; i++) {
+       XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent);
+       XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire);
+   }
+
+   return True;
+}
+
+Bool
+DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2ConnectReply rep;
+   xDRI2ConnectReq *req;
+
+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+   LockDisplay(dpy);
+   GetReq(DRI2Connect, req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2Connect;
+   req->window = window;
+   req->driverType = DRI2DriverDRI;
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return False;
+   }
+
+   if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return False;
+   }
+
+   *driverName = Xmalloc(rep.driverNameLength + 1);
+   if (*driverName == NULL) {
+      _XEatData(dpy,
+                ((rep.driverNameLength + 3) & ~3) +
+                ((rep.deviceNameLength + 3) & ~3));
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return False;
+   }
+   _XReadPad(dpy, *driverName, rep.driverNameLength);
+   (*driverName)[rep.driverNameLength] = '\0';
+
+   *deviceName = Xmalloc(rep.deviceNameLength + 1);
+   if (*deviceName == NULL) {
+      Xfree(*driverName);
+      _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return False;
+   }
+   _XReadPad(dpy, *deviceName, rep.deviceNameLength);
+   (*deviceName)[rep.deviceNameLength] = '\0';
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return True;
+}
+
+Bool
+DRI2Authenticate(Display * dpy, XID window, drm_magic_t magic)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2AuthenticateReq *req;
+   xDRI2AuthenticateReply rep;
+
+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+   LockDisplay(dpy);
+   GetReq(DRI2Authenticate, req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2Authenticate;
+   req->window = window;
+   req->magic = magic;
+
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return False;
+   }
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return rep.authenticated;
+}
+
+void
+DRI2CreateDrawable(Display * dpy, XID drawable)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2CreateDrawableReq *req;
+
+   XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
+
+   LockDisplay(dpy);
+   GetReq(DRI2CreateDrawable, req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2CreateDrawable;
+   req->drawable = drawable;
+   UnlockDisplay(dpy);
+   SyncHandle();
+}
+
+void
+DRI2DestroyDrawable(Display * dpy, XID drawable)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2DestroyDrawableReq *req;
+
+   XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
+
+   XSync(dpy, False);
+
+   LockDisplay(dpy);
+   GetReq(DRI2DestroyDrawable, req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2DestroyDrawable;
+   req->drawable = drawable;
+   UnlockDisplay(dpy);
+   SyncHandle();
+}
+
+DRI2Buffer *
+DRI2GetBuffers(Display * dpy, XID drawable,
+               int *width, int *height,
+               unsigned int *attachments, int count, int *outCount)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2GetBuffersReply rep;
+   xDRI2GetBuffersReq *req;
+   DRI2Buffer *buffers;
+   xDRI2Buffer repBuffer;
+   CARD32 *p;
+   int i;
+
+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+   LockDisplay(dpy);
+   GetReqExtra(DRI2GetBuffers, count * 4, req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2GetBuffers;
+   req->drawable = drawable;
+   req->count = count;
+   p = (CARD32 *) & req[1];
+   for (i = 0; i < count; i++)
+      p[i] = attachments[i];
+
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return NULL;
+   }
+
+   *width = rep.width;
+   *height = rep.height;
+   *outCount = rep.count;
+
+   buffers = Xmalloc(rep.count * sizeof buffers[0]);
+   if (buffers == NULL) {
+      _XEatData(dpy, rep.count * sizeof repBuffer);
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return NULL;
+   }
+
+   for (i = 0; i < rep.count; i++) {
+      _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
+      buffers[i].attachment = repBuffer.attachment;
+      buffers[i].name = repBuffer.name;
+      buffers[i].pitch = repBuffer.pitch;
+      buffers[i].cpp = repBuffer.cpp;
+      buffers[i].flags = repBuffer.flags;
+   }
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return buffers;
+}
+
+
+DRI2Buffer *
+DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
+                         int *width, int *height,
+                         unsigned int *attachments, int count, int *outCount)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2GetBuffersReply rep;
+   xDRI2GetBuffersReq *req;
+   DRI2Buffer *buffers;
+   xDRI2Buffer repBuffer;
+   CARD32 *p;
+   int i;
+
+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+   LockDisplay(dpy);
+   GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2GetBuffersWithFormat;
+   req->drawable = drawable;
+   req->count = count;
+   p = (CARD32 *) & req[1];
+   for (i = 0; i < (count * 2); i++)
+      p[i] = attachments[i];
+
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return NULL;
+   }
+
+   *width = rep.width;
+   *height = rep.height;
+   *outCount = rep.count;
+
+   buffers = Xmalloc(rep.count * sizeof buffers[0]);
+   if (buffers == NULL) {
+      _XEatData(dpy, rep.count * sizeof repBuffer);
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return NULL;
+   }
+
+   for (i = 0; i < rep.count; i++) {
+      _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
+      buffers[i].attachment = repBuffer.attachment;
+      buffers[i].name = repBuffer.name;
+      buffers[i].pitch = repBuffer.pitch;
+      buffers[i].cpp = repBuffer.cpp;
+      buffers[i].flags = repBuffer.flags;
+   }
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return buffers;
+}
+
+
+void
+DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
+               CARD32 dest, CARD32 src)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2CopyRegionReq *req;
+   xDRI2CopyRegionReply rep;
+
+   XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
+
+   LockDisplay(dpy);
+   GetReq(DRI2CopyRegion, req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2CopyRegion;
+   req->drawable = drawable;
+   req->region = region;
+   req->dest = dest;
+   req->src = src;
+
+   _XReply(dpy, (xReply *) & rep, 0, xFalse);
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+}
+
+#ifdef X_DRI2SwapBuffers
+static void
+load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor,
+            CARD64 remainder)
+{
+    req->target_msc_hi = target >> 32;
+    req->target_msc_lo = target & 0xffffffff;
+    req->divisor_hi = divisor >> 32;
+    req->divisor_lo = divisor & 0xffffffff;
+    req->remainder_hi = remainder >> 32;
+    req->remainder_lo = remainder & 0xffffffff;
+}
+
+static CARD64
+vals_to_card64(CARD32 lo, CARD32 hi)
+{
+    return (CARD64)hi << 32 | lo;
+}
+
+void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc,
+                    CARD64 divisor, CARD64 remainder, CARD64 *count)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2SwapBuffersReq *req;
+    xDRI2SwapBuffersReply rep;
+
+    XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
+
+    LockDisplay(dpy);
+    GetReq(DRI2SwapBuffers, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2SwapBuffers;
+    req->drawable = drawable;
+    load_swap_req(req, target_msc, divisor, remainder);
+
+    _XReply(dpy, (xReply *)&rep, 0, xFalse);
+
+    *count = vals_to_card64(rep.swap_lo, rep.swap_hi);
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+}
+#endif
+
+#ifdef X_DRI2GetMSC
+Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc,
+               CARD64 *sbc)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2GetMSCReq *req;
+    xDRI2MSCReply rep;
+
+    XextCheckExtension (dpy, info, dri2ExtensionName, False);
+
+    LockDisplay(dpy);
+    GetReq(DRI2GetMSC, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2GetMSC;
+    req->drawable = drawable;
+
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+       return False;
+    }
+
+    *ust = vals_to_card64(rep.ust_lo, rep.ust_hi);
+    *msc = vals_to_card64(rep.msc_lo, rep.msc_hi);
+    *sbc = vals_to_card64(rep.sbc_lo, rep.sbc_hi);
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    return True;
+}
+#endif
+
+#ifdef X_DRI2WaitMSC
+static void
+load_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor,
+            CARD64 remainder)
+{
+    req->target_msc_hi = target >> 32;
+    req->target_msc_lo = target & 0xffffffff;
+    req->divisor_hi = divisor >> 32;
+    req->divisor_lo = divisor & 0xffffffff;
+    req->remainder_hi = remainder >> 32;
+    req->remainder_lo = remainder & 0xffffffff;
+}
+
+Bool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
+                CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2WaitMSCReq *req;
+    xDRI2MSCReply rep;
+
+    XextCheckExtension (dpy, info, dri2ExtensionName, False);
+
+    LockDisplay(dpy);
+    GetReq(DRI2WaitMSC, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2WaitMSC;
+    req->drawable = drawable;
+    load_msc_req(req, target_msc, divisor, remainder);
+
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+       return False;
+    }
+
+    *ust = ((CARD64)rep.ust_hi << 32) | (CARD64)rep.ust_lo;
+    *msc = ((CARD64)rep.msc_hi << 32) | (CARD64)rep.msc_lo;
+    *sbc = ((CARD64)rep.sbc_hi << 32) | (CARD64)rep.sbc_lo;
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    return True;
+}
+#endif
+
+#ifdef X_DRI2WaitSBC
+static void
+load_sbc_req(xDRI2WaitSBCReq *req, CARD64 target)
+{
+    req->target_sbc_hi = target >> 32;
+    req->target_sbc_lo = target & 0xffffffff;
+}
+
+Bool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
+                CARD64 *msc, CARD64 *sbc)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2WaitSBCReq *req;
+    xDRI2MSCReply rep;
+
+    XextCheckExtension (dpy, info, dri2ExtensionName, False);
+
+    LockDisplay(dpy);
+    GetReq(DRI2WaitSBC, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2WaitSBC;
+    req->drawable = drawable;
+    load_sbc_req(req, target_sbc);
+
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+       return False;
+    }
+
+    *ust = ((CARD64)rep.ust_hi << 32) | rep.ust_lo;
+    *msc = ((CARD64)rep.msc_hi << 32) | rep.msc_lo;
+    *sbc = ((CARD64)rep.sbc_hi << 32) | rep.sbc_lo;
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    return True;
+}
+#endif
+
+#ifdef X_DRI2SwapInterval
+void DRI2SwapInterval(Display *dpy, XID drawable, int interval)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2SwapIntervalReq *req;
+
+    XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
+
+    LockDisplay(dpy);
+    GetReq(DRI2SwapInterval, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2SwapInterval;
+    req->drawable = drawable;
+    req->interval = interval;
+    UnlockDisplay(dpy);
+    SyncHandle();
+}
+#endif
diff --git a/src/gallium/winsys/g3dvl/dri/dri2.h b/src/gallium/winsys/g3dvl/dri/dri2.h
new file mode 100644 (file)
index 0000000..114e9f8
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2007,2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Kristian Høgsberg (krh@redhat.com)
+ */
+
+#ifndef _DRI2_H_
+#define _DRI2_H_
+
+#include <X11/extensions/Xfixes.h>
+#include <X11/extensions/dri2tokens.h>
+
+typedef struct
+{
+   unsigned int attachment;
+   unsigned int name;
+   unsigned int pitch;
+   unsigned int cpp;
+   unsigned int flags;
+} DRI2Buffer;
+
+extern Bool
+DRI2QueryExtension(Display * display, int *eventBase, int *errorBase);
+
+extern Bool
+DRI2QueryVersion(Display * display, int *major, int *minor);
+
+extern Bool
+DRI2Connect(Display * display, XID window,
+            char **driverName, char **deviceName);
+
+extern Bool
+DRI2Authenticate(Display * display, XID window, drm_magic_t magic);
+
+extern void
+DRI2CreateDrawable(Display * display, XID drawable);
+
+extern void
+DRI2DestroyDrawable(Display * display, XID handle);
+
+extern DRI2Buffer*
+DRI2GetBuffers(Display * dpy, XID drawable,
+               int *width, int *height,
+               unsigned int *attachments, int count,
+               int *outCount);
+
+/**
+ * \note
+ * This function is only supported with DRI2 version 1.1 or later.
+ */
+extern DRI2Buffer*
+DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
+                         int *width, int *height,
+                         unsigned int *attachments,
+                         int count, int *outCount);
+
+extern void
+DRI2CopyRegion(Display * dpy, XID drawable,
+               XserverRegion region,
+               CARD32 dest, CARD32 src);
+
+extern void
+DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
+               CARD64 remainder, CARD64 *count);
+
+extern Bool
+DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc, CARD64 *sbc);
+
+extern Bool
+DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
+           CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc);
+
+extern Bool
+DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
+           CARD64 *msc, CARD64 *sbc);
+
+extern void
+DRI2SwapInterval(Display *dpy, XID drawable, int interval);
+
+#endif
diff --git a/src/gallium/winsys/g3dvl/dri/dri_winsys.c b/src/gallium/winsys/g3dvl/dri/dri_winsys.c
new file mode 100644 (file)
index 0000000..0663184
--- /dev/null
@@ -0,0 +1,287 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <vl_winsys.h>
+#include <driclient.h>
+#include <pipe/p_video_context.h>
+#include <pipe/p_state.h>
+#include <util/u_memory.h>
+#include <util/u_hash.h>
+#include <util/u_hash_table.h>
+#include <state_tracker/drm_api.h>
+#include <X11/Xlibint.h>
+
+struct vl_dri_screen
+{
+   struct vl_screen base;
+   struct drm_api *api;
+   dri_screen_t *dri_screen;
+   struct util_hash_table *drawable_table;
+   Drawable last_seen_drawable;
+};
+
+struct vl_dri_context
+{
+   struct vl_context base;
+   int fd;
+};
+
+static struct pipe_surface*
+vl_dri2_get_front(struct vl_dri_screen *vl_dri_scrn, Drawable drawable)
+{
+   int w, h;
+   unsigned int attachments[1] = {DRI_BUFFER_FRONT_LEFT};
+   int count;
+   DRI2Buffer *dri2_front;
+   struct pipe_resource *front_tex;
+   struct pipe_surface *front_surf = NULL;
+
+   assert(vl_dri_scrn);
+
+   dri2_front = DRI2GetBuffers(vl_dri_scrn->dri_screen->display,
+                               drawable, &w, &h, attachments, 1, &count);
+
+   assert(count == 1);
+
+   if (dri2_front) {
+      struct winsys_handle dri2_front_handle =
+      {
+         .type = DRM_API_HANDLE_TYPE_SHARED,
+         .handle = dri2_front->name,
+         .stride = dri2_front->pitch
+      };
+      struct pipe_resource template;
+
+      memset(&template, 0, sizeof(struct pipe_resource));
+      template.target = PIPE_TEXTURE_2D;
+      template.format = PIPE_FORMAT_B8G8R8X8_UNORM;
+      template.last_level = 0;
+      template.width0 = w;
+      template.height0 = h;
+      template.depth0 = 1;
+      template.usage = PIPE_USAGE_STATIC;
+      template.bind = PIPE_BIND_RENDER_TARGET;
+      template.flags = 0;
+
+      front_tex = vl_dri_scrn->base.pscreen->resource_from_handle(vl_dri_scrn->base.pscreen, &template, &dri2_front_handle);
+      if (front_tex)
+         front_surf = vl_dri_scrn->base.pscreen->get_tex_surface(vl_dri_scrn->base.pscreen,
+                                                                 front_tex, 0, 0, 0,
+                                                                 PIPE_BIND_RENDER_TARGET);
+      pipe_resource_reference(&front_tex, NULL);
+      Xfree(dri2_front);
+   }
+
+   return front_surf;
+}
+
+static void
+vl_dri2_flush_frontbuffer(struct pipe_screen *screen,
+                          struct pipe_surface *surf, void *context_private)
+{
+   struct vl_dri_context *vl_dri_ctx = (struct vl_dri_context*)context_private;
+   struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vl_dri_ctx->base.vscreen;
+
+   assert(screen);
+   assert(surf);
+   assert(context_private);
+
+   dri2CopyDrawable(vl_dri_scrn->dri_screen, vl_dri_scrn->last_seen_drawable,
+                    DRI_BUFFER_FRONT_LEFT, DRI_BUFFER_FAKE_FRONT_LEFT);
+}
+
+struct pipe_surface*
+vl_drawable_surface_get(struct vl_screen *vscreen, Drawable drawable)
+{
+   struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vscreen;
+
+   assert(vscreen);
+
+   if (vl_dri_scrn->last_seen_drawable != drawable) {
+      /* Hash table business depends on this equality */
+      assert(None == NULL);
+      Drawable lookup_drawable = (Drawable)util_hash_table_get(vl_dri_scrn->drawable_table, (void*)drawable);
+      if (lookup_drawable == None) {
+         dri2CreateDrawable(vl_dri_scrn->dri_screen, drawable);
+         util_hash_table_set(vl_dri_scrn->drawable_table, (void*)drawable, (void*)drawable);
+      }
+      vl_dri_scrn->last_seen_drawable = drawable;
+   }
+
+   return vl_dri2_get_front(vl_dri_scrn, drawable);
+}
+
+void*
+vl_contextprivate_get(struct vl_context *vctx, struct pipe_surface *displaytarget)
+{
+   return vctx;
+}
+
+static unsigned drawable_hash(void *key)
+{
+   Drawable drawable = (Drawable)key;
+   assert(drawable != None);
+   return util_hash_crc32(&drawable, sizeof(Drawable));
+}
+
+static int drawable_cmp(void *key1, void *key2)
+{
+   Drawable d1 = (Drawable)key1;
+   Drawable d2 = (Drawable)key2;
+   assert(d1 != None);
+   assert(d2 != None);
+   return d1 != d2;
+}
+
+static enum pipe_error
+drawable_destroy(void *key, void *value, void *data)
+{
+   Drawable drawable = (Drawable)key;
+   struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)data;
+
+   assert(drawable != None);
+   assert(value);
+   assert(data);
+
+   dri2DestroyDrawable(vl_dri_scrn->dri_screen, drawable);
+
+   return PIPE_OK;
+}
+
+struct vl_screen*
+vl_screen_create(Display *display, int screen)
+{
+   struct vl_dri_screen *vl_dri_scrn;
+   struct drm_create_screen_arg arg;
+
+   assert(display);
+
+   vl_dri_scrn = CALLOC_STRUCT(vl_dri_screen);
+   if (!vl_dri_scrn)
+      goto no_struct;
+
+   if (dri2CreateScreen(display, screen, &vl_dri_scrn->dri_screen))
+      goto no_dri2screen;
+
+   vl_dri_scrn->api = drm_api_create();
+   if (!vl_dri_scrn->api)
+      goto no_drmapi;
+
+   arg.mode = DRM_CREATE_NORMAL;
+
+   vl_dri_scrn->base.pscreen = vl_dri_scrn->api->create_screen(vl_dri_scrn->api,
+                                                               vl_dri_scrn->dri_screen->fd,
+                                                               &arg);
+
+   if (!vl_dri_scrn->base.pscreen)
+      goto no_pscreen;
+
+   vl_dri_scrn->drawable_table = util_hash_table_create(&drawable_hash, &drawable_cmp);
+   if (!vl_dri_scrn->drawable_table)
+      goto no_hash;
+
+   vl_dri_scrn->last_seen_drawable = None;
+   vl_dri_scrn->base.pscreen->flush_frontbuffer = vl_dri2_flush_frontbuffer;
+
+   return &vl_dri_scrn->base;
+
+no_hash:
+   vl_dri_scrn->base.pscreen->destroy(vl_dri_scrn->base.pscreen);
+no_pscreen:
+   vl_dri_scrn->api->destroy(vl_dri_scrn->api);
+no_drmapi:
+   dri2DestroyScreen(vl_dri_scrn->dri_screen);
+no_dri2screen:
+   FREE(vl_dri_scrn);
+no_struct:
+   return NULL;
+}
+
+void vl_screen_destroy(struct vl_screen *vscreen)
+{
+   struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vscreen;
+
+   assert(vscreen);
+
+   util_hash_table_foreach(vl_dri_scrn->drawable_table, drawable_destroy, vl_dri_scrn);
+   util_hash_table_destroy(vl_dri_scrn->drawable_table);
+   vl_dri_scrn->base.pscreen->destroy(vl_dri_scrn->base.pscreen);
+   if (vl_dri_scrn->api->destroy)
+      vl_dri_scrn->api->destroy(vl_dri_scrn->api);
+   dri2DestroyScreen(vl_dri_scrn->dri_screen);
+   FREE(vl_dri_scrn);
+}
+
+struct vl_context*
+vl_video_create(struct vl_screen *vscreen,
+                enum pipe_video_profile profile,
+                enum pipe_video_chroma_format chroma_format,
+                unsigned width, unsigned height)
+{
+   struct vl_dri_screen *vl_dri_scrn = (struct vl_dri_screen*)vscreen;
+   struct vl_dri_context *vl_dri_ctx;
+
+   vl_dri_ctx = CALLOC_STRUCT(vl_dri_context);
+   if (!vl_dri_ctx)
+      goto no_struct;
+
+   if (!vscreen->pscreen->video_context_create) {
+      debug_printf("[G3DVL] No video support found on %s/%s.\n",
+                   vscreen->pscreen->get_vendor(vscreen->pscreen),
+                   vscreen->pscreen->get_name(vscreen->pscreen));
+      goto no_vpipe;
+   }
+
+   vl_dri_ctx->base.vpipe = vscreen->pscreen->video_context_create(vscreen->pscreen,
+                                                                   profile, chroma_format,
+                                                                   width, height,
+                                                                   vl_dri_ctx);
+
+   if (!vl_dri_ctx->base.vpipe)
+      goto no_vpipe;
+
+   vl_dri_ctx->base.vpipe->priv = vl_dri_ctx;
+   vl_dri_ctx->base.vscreen = vscreen;
+   vl_dri_ctx->fd = vl_dri_scrn->dri_screen->fd;
+
+   return &vl_dri_ctx->base;
+
+no_vpipe:
+   FREE(vl_dri_ctx);
+no_struct:
+   return NULL;
+}
+
+void vl_video_destroy(struct vl_context *vctx)
+{
+   struct vl_dri_context *vl_dri_ctx = (struct vl_dri_context*)vctx;
+
+   assert(vctx);
+
+   vl_dri_ctx->base.vpipe->destroy(vl_dri_ctx->base.vpipe);
+   FREE(vl_dri_ctx);
+}
diff --git a/src/gallium/winsys/g3dvl/dri/driclient.c b/src/gallium/winsys/g3dvl/dri/driclient.c
new file mode 100644 (file)
index 0000000..90e48a7
--- /dev/null
@@ -0,0 +1,388 @@
+#include "driclient.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <X11/Xlibint.h>
+
+int driCreateScreen(Display *display, int screen, dri_screen_t **dri_screen, dri_framebuffer_t *dri_framebuf)
+{
+       int             evbase, errbase;
+       char            *driver_name;
+       int             newly_opened;
+       drm_magic_t     magic;
+       drmVersionPtr   drm_version;
+       drm_handle_t    sarea_handle;
+       char            *bus_id;
+       dri_screen_t    *dri_scrn;
+
+       assert(display);
+       assert(dri_screen);
+
+       if (!XF86DRIQueryExtension(display, &evbase, &errbase))
+               return 1;
+
+       dri_scrn = calloc(1, sizeof(dri_screen_t));
+
+       if (!dri_scrn)
+               return 1;
+
+       if (!XF86DRIQueryVersion(display, &dri_scrn->dri.major, &dri_scrn->dri.minor, &dri_scrn->dri.patch))
+               goto free_screen;
+
+       dri_scrn->display = display;
+       dri_scrn->num = screen;
+       dri_scrn->draw_lock_id = 1;
+
+       if (!XF86DRIOpenConnection(display, screen, &sarea_handle, &bus_id))
+               goto free_screen;
+
+       dri_scrn->fd = -1;
+       dri_scrn->fd = drmOpenOnce(NULL, bus_id, &newly_opened);
+       XFree(bus_id);
+
+       if (dri_scrn->fd < 0)
+               goto close_connection;
+
+       if (drmGetMagic(dri_scrn->fd, &magic))
+               goto close_drm;
+
+       drm_version = drmGetVersion(dri_scrn->fd);
+
+       if (!drm_version)
+               goto close_drm;
+
+       dri_scrn->drm.major = drm_version->version_major;
+       dri_scrn->drm.minor = drm_version->version_minor;
+       dri_scrn->drm.patch = drm_version->version_patchlevel;
+       drmFreeVersion(drm_version);
+
+       if (!XF86DRIAuthConnection(display, screen, magic))
+               goto close_drm;
+
+       if (!XF86DRIGetClientDriverName
+       (
+               display,
+               screen,
+               &dri_scrn->ddx.major,
+               &dri_scrn->ddx.minor,
+               &dri_scrn->ddx.patch,
+               &driver_name
+       ))
+               goto close_drm;
+
+       if (drmMap(dri_scrn->fd, sarea_handle, SAREA_MAX, (drmAddress)&dri_scrn->sarea))
+               goto close_drm;
+
+       dri_scrn->drawable_hash = drmHashCreate();
+
+       if (!dri_scrn->drawable_hash)
+               goto unmap_sarea;
+
+       if (dri_framebuf)
+       {
+               if (!XF86DRIGetDeviceInfo
+               (
+                       display,
+                       screen, &dri_framebuf->drm_handle,
+                       &dri_framebuf->base,
+                       &dri_framebuf->size,
+                       &dri_framebuf->stride,
+                       &dri_framebuf->private_size,
+                       &dri_framebuf->private
+               ))
+                       goto destroy_hash;
+       }
+
+       *dri_screen = dri_scrn;
+
+       return 0;
+
+destroy_hash:
+       drmHashDestroy(dri_scrn->drawable_hash);
+unmap_sarea:
+       drmUnmap(dri_scrn->sarea, SAREA_MAX);
+close_drm:
+       drmCloseOnce(dri_scrn->fd);
+close_connection:
+       XF86DRICloseConnection(display, screen);
+free_screen:
+       free(dri_scrn);
+
+       return 1;
+}
+
+int driDestroyScreen(dri_screen_t *dri_screen)
+{
+       Drawable        draw;
+       dri_drawable_t  *dri_draw;
+
+       assert(dri_screen);
+
+       if (drmHashFirst(dri_screen->drawable_hash, &draw, (void**)&dri_draw))
+       {
+               dri_draw->refcount = 1;
+               driDestroyDrawable(dri_draw);
+
+               while (drmHashNext(dri_screen->drawable_hash, &draw, (void**)&dri_draw))
+               {
+                       dri_draw->refcount = 1;
+                       driDestroyDrawable(dri_draw);
+               }
+       }
+
+       drmHashDestroy(dri_screen->drawable_hash);
+       drmUnmap(dri_screen->sarea, SAREA_MAX);
+       drmCloseOnce(dri_screen->fd);
+       XF86DRICloseConnection(dri_screen->display, dri_screen->num);
+       free(dri_screen);
+
+       return 0;
+}
+
+int driCreateDrawable(dri_screen_t *dri_screen, Drawable drawable, dri_drawable_t **dri_drawable)
+{
+       int             evbase, errbase;
+       dri_drawable_t  *dri_draw;
+
+       assert(dri_screen);
+       assert(dri_drawable);
+
+       if (!XF86DRIQueryExtension(dri_screen->display, &evbase, &errbase))
+               return 1;
+
+       if (!drmHashLookup(dri_screen->drawable_hash, drawable, (void**)dri_drawable))
+       {
+               /* Found */
+               (*dri_drawable)->refcount++;
+               return 0;
+       }
+
+       dri_draw = calloc(1, sizeof(dri_drawable_t));
+
+       if (!dri_draw)
+               return 1;
+
+       if (!XF86DRICreateDrawable(dri_screen->display, 0, drawable, &dri_draw->drm_drawable))
+       {
+               free(dri_draw);
+               return 1;
+       }
+
+       dri_draw->x_drawable = drawable;
+       dri_draw->sarea_index = 0;
+       dri_draw->sarea_stamp = NULL;
+       dri_draw->last_sarea_stamp = 0;
+       dri_draw->dri_screen = dri_screen;
+       dri_draw->refcount = 1;
+
+       if (drmHashInsert(dri_screen->drawable_hash, drawable, dri_draw))
+       {
+               XF86DRIDestroyDrawable(dri_screen->display, dri_screen->num, drawable);
+               free(dri_draw);
+               return 1;
+       }
+
+       if (!dri_draw->sarea_stamp || *dri_draw->sarea_stamp != dri_draw->last_sarea_stamp)
+       {
+               DRM_SPINLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
+
+               if (driUpdateDrawableInfo(dri_draw))
+               {
+                       XF86DRIDestroyDrawable(dri_screen->display, dri_screen->num, drawable);
+                       free(dri_draw);
+                       DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
+                       return 1;
+               }
+
+               DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
+       }
+
+       *dri_drawable = dri_draw;
+
+       return 0;
+}
+
+int driUpdateDrawableInfo(dri_drawable_t *dri_drawable)
+{
+       assert(dri_drawable);
+
+       if (dri_drawable->cliprects)
+       {
+               XFree(dri_drawable->cliprects);
+               dri_drawable->cliprects = NULL;
+       }
+       if (dri_drawable->back_cliprects)
+       {
+               XFree(dri_drawable->back_cliprects);
+               dri_drawable->back_cliprects = NULL;
+       }
+
+       DRM_SPINUNLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id);
+
+       if (!XF86DRIGetDrawableInfo
+       (
+               dri_drawable->dri_screen->display,
+               dri_drawable->dri_screen->num,
+               dri_drawable->x_drawable,
+               &dri_drawable->sarea_index,
+               &dri_drawable->last_sarea_stamp,
+               &dri_drawable->x,
+               &dri_drawable->y,
+               &dri_drawable->w,
+               &dri_drawable->h,
+               &dri_drawable->num_cliprects,
+               &dri_drawable->cliprects,
+               &dri_drawable->back_x,
+               &dri_drawable->back_y,
+               &dri_drawable->num_back_cliprects,
+               &dri_drawable->back_cliprects
+       ))
+       {
+               dri_drawable->sarea_stamp = &dri_drawable->last_sarea_stamp;
+               dri_drawable->num_cliprects = 0;
+               dri_drawable->cliprects = NULL;
+               dri_drawable->num_back_cliprects = 0;
+               dri_drawable->back_cliprects = 0;
+
+               return 1;
+       }
+       else
+               dri_drawable->sarea_stamp = &dri_drawable->dri_screen->sarea->drawableTable[dri_drawable->sarea_index].stamp;
+
+       DRM_SPINLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id);
+
+       return 0;
+}
+
+int driDestroyDrawable(dri_drawable_t *dri_drawable)
+{
+       assert(dri_drawable);
+
+       if (--dri_drawable->refcount == 0)
+       {
+               if (dri_drawable->cliprects)
+                       XFree(dri_drawable->cliprects);
+               if (dri_drawable->back_cliprects)
+                       XFree(dri_drawable->back_cliprects);
+               drmHashDelete(dri_drawable->dri_screen->drawable_hash, dri_drawable->x_drawable);
+               XF86DRIDestroyDrawable(dri_drawable->dri_screen->display, dri_drawable->dri_screen->num, dri_drawable->x_drawable);
+               free(dri_drawable);
+       }
+
+       return 0;
+}
+
+int driCreateContext(dri_screen_t *dri_screen, Visual *visual, dri_context_t **dri_context)
+{
+       int             evbase, errbase;
+       dri_context_t   *dri_ctx;
+
+       assert(dri_screen);
+       assert(visual);
+       assert(dri_context);
+
+       if (!XF86DRIQueryExtension(dri_screen->display, &evbase, &errbase))
+               return 1;
+
+       dri_ctx = calloc(1, sizeof(dri_context_t));
+
+       if (!dri_ctx)
+               return 1;
+
+       if (!XF86DRICreateContext(dri_screen->display, dri_screen->num, visual, &dri_ctx->id, &dri_ctx->drm_context))
+       {
+               free(dri_ctx);
+               return 1;
+       }
+
+       dri_ctx->dri_screen = dri_screen;
+       *dri_context = dri_ctx;
+
+       return 0;
+}
+
+int driDestroyContext(dri_context_t *dri_context)
+{
+       assert(dri_context);
+
+       XF86DRIDestroyContext(dri_context->dri_screen->display, dri_context->dri_screen->num, dri_context->id);
+       free(dri_context);
+
+       return 0;
+}
+
+int dri2CreateScreen(Display *display, int screen, dri_screen_t **dri_screen)
+{
+       dri_screen_t    *dri_scrn;
+       drm_magic_t     magic;
+       char            *drvName;
+       char            *devName;
+
+       dri_scrn = calloc(1, sizeof(dri_screen_t));
+
+       if (!dri_scrn)
+               return 1;
+
+       if (!DRI2Connect(display, XRootWindow(display, screen), &drvName, &devName))
+               goto free_screen;
+
+       dri_scrn->fd = open(devName, O_RDWR);
+       Xfree(drvName);
+       Xfree(devName);
+       if (dri_scrn->fd < 0)
+               goto free_screen;
+
+       if (drmGetMagic(dri_scrn->fd, &magic))
+               goto free_screen;
+
+       if (!DRI2Authenticate(display, RootWindow(display, screen), magic))
+               goto free_screen;
+
+       dri_scrn->display = display;
+       dri_scrn->num = screen;
+       *dri_screen = dri_scrn;
+
+       return 0;
+
+free_screen:
+       free(dri_scrn);
+
+       return 1;
+}
+
+int dri2DestroyScreen(dri_screen_t *dri_screen)
+{
+       /* Not much to do here apparently... */
+       assert(dri_screen);
+       free(dri_screen);
+       return 0;
+}
+
+int dri2CreateDrawable(dri_screen_t *dri_screen, XID drawable)
+{
+       assert(dri_screen);
+       DRI2CreateDrawable(dri_screen->display, drawable);
+       return 0;
+}
+
+int dri2DestroyDrawable(dri_screen_t *dri_screen, XID drawable)
+{
+       assert(dri_screen);
+       DRI2DestroyDrawable(dri_screen->display, drawable);
+       return 0;
+}
+
+int dri2CopyDrawable(dri_screen_t *dri_screen, XID drawable, int dest, int src)
+{
+       XserverRegion region;
+
+       assert(dri_screen);
+       assert(dest >= DRI_BUFFER_FRONT_LEFT && dest <= DRI_BUFFER_DEPTH_STENCIL);
+       assert(src >= DRI_BUFFER_FRONT_LEFT && src <= DRI_BUFFER_DEPTH_STENCIL);
+
+       region = XFixesCreateRegionFromWindow(dri_screen->display, drawable, WindowRegionBounding);
+       DRI2CopyRegion(dri_screen->display, drawable, region, dest, src);
+       XFixesDestroyRegion(dri_screen->display, region);
+
+       return 0;
+}
diff --git a/src/gallium/winsys/g3dvl/dri/driclient.h b/src/gallium/winsys/g3dvl/dri/driclient.h
new file mode 100644 (file)
index 0000000..4e4fd36
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef driclient_h
+#define driclient_h
+
+#include <stdint.h>
+#include <X11/Xmd.h>
+#include <X11/Xlib.h>
+#include <drm_sarea.h>
+//#include <X11/extensions/dri2proto.h>
+#include "xf86dri.h"
+#include "dri2.h"
+
+/* TODO: Bring in DRI XML options */
+
+typedef struct dri_version
+{
+       int major;
+       int minor;
+       int patch;
+} dri_version_t;
+
+typedef struct dri_screen
+{
+       Display                 *display;
+       unsigned int            num;
+       dri_version_t           ddx, dri, drm;
+       int                     draw_lock_id;
+       int                     fd;
+       drm_sarea_t             *sarea;
+       void                    *drawable_hash;
+       void                    *private;
+} dri_screen_t;
+
+struct dri_context;
+
+typedef struct dri_drawable
+{
+       drm_drawable_t          drm_drawable;
+       Drawable                x_drawable;
+       unsigned int            sarea_index;
+       unsigned int            *sarea_stamp;
+       unsigned int            last_sarea_stamp;
+       int                     x, y, w, h;
+       int                     back_x, back_y;
+       int                     num_cliprects, num_back_cliprects;
+       drm_clip_rect_t         *cliprects, *back_cliprects;
+       dri_screen_t            *dri_screen;
+       unsigned int            refcount;
+       void                    *private;
+} dri_drawable_t;
+
+typedef struct dri_context
+{
+       XID                     id;
+       drm_context_t           drm_context;
+       dri_screen_t            *dri_screen;
+       void                    *private;
+} dri_context_t;
+
+typedef struct dri_framebuffer
+{
+       drm_handle_t            drm_handle;
+       int                     base, size, stride;
+       int                     private_size;
+       void                    *private;
+} dri_framebuffer_t;
+
+int driCreateScreen(Display *display, int screen, dri_screen_t **dri_screen, dri_framebuffer_t *dri_framebuf);
+int driDestroyScreen(dri_screen_t *dri_screen);
+int driCreateDrawable(dri_screen_t *dri_screen, Drawable drawable, dri_drawable_t **dri_drawable);
+int driUpdateDrawableInfo(dri_drawable_t *dri_drawable);
+int driDestroyDrawable(dri_drawable_t *dri_drawable);
+int driCreateContext(dri_screen_t *dri_screen, Visual *visual, dri_context_t **dri_context);
+int driDestroyContext(dri_context_t *dri_context);
+
+#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(dri_drawable)                                  \
+do                                                                                     \
+{                                                                                      \
+       if (*(dri_drawable->sarea_stamp) != dri_drawable->last_sarea_stamp)             \
+               driUpdateDrawableInfo(dri_drawable);                                    \
+} while (0)
+
+#define DRI_VALIDATE_DRAWABLE_INFO(dri_screen, dri_drawable)                                   \
+do                                                                                             \
+{                                                                                              \
+       while (*(dri_drawable->sarea_stamp) != dri_drawable->last_sarea_stamp)                  \
+       {                                                                                       \
+               register unsigned int hwContext = dri_screen->sarea->lock.lock &                \
+               ~(DRM_LOCK_HELD | DRM_LOCK_CONT);                                               \
+               DRM_UNLOCK(dri_screen->fd, &dri_screen->sarea->lock, hwContext);                \
+                                                                                               \
+               DRM_SPINLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);      \
+               DRI_VALIDATE_DRAWABLE_INFO_ONCE(dri_drawable);                                  \
+               DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);    \
+                                                                                               \
+               DRM_LIGHT_LOCK(dri_screen->fd, &dri_screen->sarea->lock, hwContext);            \
+       }                                                                                       \
+} while (0)
+
+int dri2CreateScreen(Display *display, int screen, dri_screen_t **dri_screen);
+int dri2DestroyScreen(dri_screen_t *dri_screen);
+int dri2CreateDrawable(dri_screen_t *dri_screen, XID drawable);
+int dri2DestroyDrawable(dri_screen_t *dri_screen, XID drawable);
+int dri2CopyDrawable(dri_screen_t *dri_screen, XID drawable, int dest, int src);
+
+#define DRI_BUFFER_FRONT_LEFT          0
+#define DRI_BUFFER_BACK_LEFT           1
+#define DRI_BUFFER_FRONT_RIGHT         2
+#define DRI_BUFFER_BACK_RIGHT          3
+#define DRI_BUFFER_DEPTH               4
+#define DRI_BUFFER_STENCIL             5
+#define DRI_BUFFER_ACCUM               6
+#define DRI_BUFFER_FAKE_FRONT_LEFT     7
+#define DRI_BUFFER_FAKE_FRONT_RIGHT    8
+#define DRI_BUFFER_DEPTH_STENCIL       9  /**< Only available with DRI2 1.1 */
+
+#endif
+
diff --git a/src/gallium/winsys/g3dvl/dri/xf86dri.h b/src/gallium/winsys/g3dvl/dri/xf86dri.h
new file mode 100644 (file)
index 0000000..baf80a7
--- /dev/null
@@ -0,0 +1,119 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/**
+ * \file xf86dri.h
+ * Protocol numbers and function prototypes for DRI X protocol.
+ *
+ * \author Kevin E. Martin <martin@valinux.com>
+ * \author Jens Owen <jens@tungstengraphics.com>
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ */
+
+#ifndef _XF86DRI_H_
+#define _XF86DRI_H_
+
+#include <X11/Xfuncproto.h>
+#include <xf86drm.h>
+
+#define X_XF86DRIQueryVersion                  0
+#define X_XF86DRIQueryDirectRenderingCapable   1
+#define X_XF86DRIOpenConnection                        2
+#define X_XF86DRICloseConnection               3
+#define X_XF86DRIGetClientDriverName           4
+#define X_XF86DRICreateContext                 5
+#define X_XF86DRIDestroyContext                        6
+#define X_XF86DRICreateDrawable                        7
+#define X_XF86DRIDestroyDrawable               8
+#define X_XF86DRIGetDrawableInfo               9
+#define X_XF86DRIGetDeviceInfo                 10
+#define X_XF86DRIAuthConnection                 11
+#define X_XF86DRIOpenFullScreen                 12   /* Deprecated */
+#define X_XF86DRICloseFullScreen                13   /* Deprecated */
+
+#define XF86DRINumberEvents            0
+
+#define XF86DRIClientNotLocal          0
+#define XF86DRIOperationNotSupported   1
+#define XF86DRINumberErrors            (XF86DRIOperationNotSupported + 1)
+
+#ifndef _XF86DRI_SERVER_
+
+_XFUNCPROTOBEGIN
+
+Bool XF86DRIQueryExtension( Display *dpy, int *event_base, int *error_base );
+
+Bool XF86DRIQueryVersion( Display *dpy, int *majorVersion, int *minorVersion,
+    int *patchVersion );
+
+Bool XF86DRIQueryDirectRenderingCapable( Display *dpy, int screen,
+    Bool *isCapable );
+
+Bool XF86DRIOpenConnection( Display *dpy, int screen, drm_handle_t *hSAREA,
+    char **busIDString );
+
+Bool XF86DRIAuthConnection( Display *dpy, int screen, drm_magic_t magic );
+
+Bool XF86DRICloseConnection( Display *dpy, int screen );
+
+Bool XF86DRIGetClientDriverName( Display *dpy, int screen,
+    int *ddxDriverMajorVersion, int *ddxDriverMinorVersion,
+    int *ddxDriverPatchVersion, char **clientDriverName );
+
+Bool XF86DRICreateContext( Display *dpy, int screen, Visual *visual,
+    XID *ptr_to_returned_context_id, drm_context_t *hHWContext );
+
+Bool XF86DRICreateContextWithConfig( Display *dpy, int screen, int configID,
+    XID *ptr_to_returned_context_id, drm_context_t *hHWContext );
+
+Bool XF86DRIDestroyContext( Display *dpy, int screen,
+    XID context_id );
+
+Bool XF86DRICreateDrawable( Display *dpy, int screen,
+    Drawable drawable, drm_drawable_t *hHWDrawable );
+
+Bool XF86DRIDestroyDrawable( Display *dpy, int screen, 
+    Drawable drawable);
+
+Bool XF86DRIGetDrawableInfo( Display *dpy, int screen, Drawable drawable,
+    unsigned int *index, unsigned int *stamp, 
+    int *X, int *Y, int *W, int *H,
+    int *numClipRects, drm_clip_rect_t ** pClipRects,
+    int *backX, int *backY,
+    int *numBackClipRects, drm_clip_rect_t **pBackClipRects );
+
+Bool XF86DRIGetDeviceInfo( Display *dpy, int screen,
+    drm_handle_t *hFrameBuffer, int *fbOrigin, int *fbSize,
+    int *fbStride, int *devPrivateSize, void **pDevPrivate );
+
+_XFUNCPROTOEND
+
+#endif /* _XF86DRI_SERVER_ */
+
+#endif /* _XF86DRI_H_ */
+
diff --git a/src/gallium/winsys/g3dvl/dri/xf86dristr.h b/src/gallium/winsys/g3dvl/dri/xf86dristr.h
new file mode 100644 (file)
index 0000000..b834bd1
--- /dev/null
@@ -0,0 +1,342 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Jens Owen <jens@tungstengraphics.com>
+ *   Rickard E. (Rik) Fiath <faith@valinux.com>
+ *
+ */
+
+#ifndef _XF86DRISTR_H_
+#define _XF86DRISTR_H_
+
+#include "xf86dri.h"
+
+#define XF86DRINAME "XFree86-DRI"
+
+/* The DRI version number.  This was originally set to be the same of the
+ * XFree86 version number.  However, this version is really indepedent of
+ * the XFree86 version.
+ *
+ * Version History:
+ *    4.0.0: Original
+ *    4.0.1: Patch to bump clipstamp when windows are destroyed, 28 May 02
+ *    4.1.0: Add transition from single to multi in DRMInfo rec, 24 Jun 02
+ */
+#define XF86DRI_MAJOR_VERSION  4
+#define XF86DRI_MINOR_VERSION  1
+#define XF86DRI_PATCH_VERSION  0
+
+typedef struct _XF86DRIQueryVersion {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRIQueryVersion */
+    CARD16     length B16;
+} xXF86DRIQueryVersionReq;
+#define sz_xXF86DRIQueryVersionReq     4
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    CARD16     majorVersion B16;       /* major version of DRI protocol */
+    CARD16     minorVersion B16;       /* minor version of DRI protocol */
+    CARD32     patchVersion B32;       /* patch version of DRI protocol */
+    CARD32     pad3 B32;
+    CARD32     pad4 B32;
+    CARD32     pad5 B32;
+    CARD32     pad6 B32;
+} xXF86DRIQueryVersionReply;
+#define sz_xXF86DRIQueryVersionReply   32
+
+typedef struct _XF86DRIQueryDirectRenderingCapable {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* X_DRIQueryDirectRenderingCapable */
+    CARD16     length B16;
+    CARD32     screen B32;
+} xXF86DRIQueryDirectRenderingCapableReq;
+#define sz_xXF86DRIQueryDirectRenderingCapableReq      8
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    BOOL       isCapable;
+    BOOL       pad2;
+    BOOL       pad3;
+    BOOL       pad4;
+    CARD32     pad5 B32;
+    CARD32     pad6 B32;
+    CARD32     pad7 B32;
+    CARD32     pad8 B32;
+    CARD32     pad9 B32;
+} xXF86DRIQueryDirectRenderingCapableReply;
+#define sz_xXF86DRIQueryDirectRenderingCapableReply    32
+
+typedef struct _XF86DRIOpenConnection {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRIOpenConnection */
+    CARD16     length B16;
+    CARD32     screen B32;
+} xXF86DRIOpenConnectionReq;
+#define sz_xXF86DRIOpenConnectionReq   8
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    CARD32     hSAREALow B32;
+    CARD32     hSAREAHigh B32;
+    CARD32     busIdStringLength B32;
+    CARD32     pad6 B32;
+    CARD32     pad7 B32;
+    CARD32     pad8 B32;
+} xXF86DRIOpenConnectionReply;
+#define sz_xXF86DRIOpenConnectionReply 32
+
+typedef struct _XF86DRIAuthConnection {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRICloseConnection */
+    CARD16     length B16;
+    CARD32     screen B32;
+    CARD32      magic B32;
+} xXF86DRIAuthConnectionReq;
+#define sz_xXF86DRIAuthConnectionReq   12
+
+typedef struct {
+    BYTE        type;
+    BOOL        pad1;
+    CARD16      sequenceNumber B16;
+    CARD32      length B32;
+    CARD32      authenticated B32;
+    CARD32      pad2 B32;
+    CARD32      pad3 B32;
+    CARD32      pad4 B32;
+    CARD32      pad5 B32;
+    CARD32      pad6 B32;
+} xXF86DRIAuthConnectionReply;
+#define zx_xXF86DRIAuthConnectionReply  32
+
+typedef struct _XF86DRICloseConnection {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRICloseConnection */
+    CARD16     length B16;
+    CARD32     screen B32;
+} xXF86DRICloseConnectionReq;
+#define sz_xXF86DRICloseConnectionReq  8
+
+typedef struct _XF86DRIGetClientDriverName {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRIGetClientDriverName */
+    CARD16     length B16;
+    CARD32     screen B32;
+} xXF86DRIGetClientDriverNameReq;
+#define sz_xXF86DRIGetClientDriverNameReq      8
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    CARD32     ddxDriverMajorVersion B32;
+    CARD32     ddxDriverMinorVersion B32;
+    CARD32     ddxDriverPatchVersion B32;
+    CARD32     clientDriverNameLength B32;
+    CARD32     pad5 B32;
+    CARD32     pad6 B32;
+} xXF86DRIGetClientDriverNameReply;
+#define sz_xXF86DRIGetClientDriverNameReply    32
+
+typedef struct _XF86DRICreateContext {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRICreateContext */
+    CARD16     length B16;
+    CARD32     screen B32;
+    CARD32     visual B32;
+    CARD32     context B32;
+} xXF86DRICreateContextReq;
+#define sz_xXF86DRICreateContextReq    16
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    CARD32     hHWContext B32;
+    CARD32     pad2 B32;
+    CARD32     pad3 B32;
+    CARD32     pad4 B32;
+    CARD32     pad5 B32;
+    CARD32     pad6 B32;
+} xXF86DRICreateContextReply;
+#define sz_xXF86DRICreateContextReply  32
+
+typedef struct _XF86DRIDestroyContext {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRIDestroyContext */
+    CARD16     length B16;
+    CARD32     screen B32;
+    CARD32     context B32;
+} xXF86DRIDestroyContextReq;
+#define sz_xXF86DRIDestroyContextReq   12
+
+typedef struct _XF86DRICreateDrawable {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRICreateDrawable */
+    CARD16     length B16;
+    CARD32     screen B32;
+    CARD32     drawable B32;
+} xXF86DRICreateDrawableReq;
+#define sz_xXF86DRICreateDrawableReq   12
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    CARD32     hHWDrawable B32;
+    CARD32     pad2 B32;
+    CARD32     pad3 B32;
+    CARD32     pad4 B32;
+    CARD32     pad5 B32;
+    CARD32     pad6 B32;
+} xXF86DRICreateDrawableReply;
+#define sz_xXF86DRICreateDrawableReply 32
+
+typedef struct _XF86DRIDestroyDrawable {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRIDestroyDrawable */
+    CARD16     length B16;
+    CARD32     screen B32;
+    CARD32     drawable B32;
+} xXF86DRIDestroyDrawableReq;
+#define sz_xXF86DRIDestroyDrawableReq  12
+
+typedef struct _XF86DRIGetDrawableInfo {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRIGetDrawableInfo */
+    CARD16     length B16;
+    CARD32     screen B32;
+    CARD32     drawable B32;
+} xXF86DRIGetDrawableInfoReq;
+#define sz_xXF86DRIGetDrawableInfoReq  12
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    CARD32     drawableTableIndex B32;
+    CARD32     drawableTableStamp B32;
+    INT16      drawableX B16;
+    INT16      drawableY B16;
+    INT16      drawableWidth B16;
+    INT16      drawableHeight B16;
+    CARD32     numClipRects B32;
+    INT16       backX B16;
+    INT16       backY B16;
+    CARD32      numBackClipRects B32;
+} xXF86DRIGetDrawableInfoReply;
+
+#define sz_xXF86DRIGetDrawableInfoReply        36
+
+
+typedef struct _XF86DRIGetDeviceInfo {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRIGetDeviceInfo */
+    CARD16     length B16;
+    CARD32     screen B32;
+} xXF86DRIGetDeviceInfoReq;
+#define sz_xXF86DRIGetDeviceInfoReq    8
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    CARD32     hFrameBufferLow B32;
+    CARD32     hFrameBufferHigh B32;
+    CARD32     framebufferOrigin B32;
+    CARD32     framebufferSize B32;
+    CARD32     framebufferStride B32;
+    CARD32     devPrivateSize B32;
+} xXF86DRIGetDeviceInfoReply;
+#define sz_xXF86DRIGetDeviceInfoReply  32
+
+typedef struct _XF86DRIOpenFullScreen {
+    CARD8       reqType;       /* always DRIReqCode */
+    CARD8       driReqType;    /* always X_DRIOpenFullScreen */
+    CARD16      length B16;
+    CARD32      screen B32;
+    CARD32      drawable B32;
+} xXF86DRIOpenFullScreenReq;
+#define sz_xXF86DRIOpenFullScreenReq    12
+
+typedef struct {
+    BYTE        type;
+    BOOL        pad1;
+    CARD16      sequenceNumber B16;
+    CARD32      length B32;
+    CARD32      isFullScreen B32;
+    CARD32      pad2 B32;
+    CARD32      pad3 B32;
+    CARD32      pad4 B32;
+    CARD32      pad5 B32;
+    CARD32      pad6 B32;
+} xXF86DRIOpenFullScreenReply;
+#define sz_xXF86DRIOpenFullScreenReply  32
+
+typedef struct _XF86DRICloseFullScreen {
+    CARD8       reqType;       /* always DRIReqCode */
+    CARD8       driReqType;    /* always X_DRICloseFullScreen */
+    CARD16      length B16;
+    CARD32      screen B32;
+    CARD32      drawable B32;
+} xXF86DRICloseFullScreenReq;
+#define sz_xXF86DRICloseFullScreenReq   12
+
+typedef struct {
+    BYTE        type;
+    BOOL        pad1;
+    CARD16      sequenceNumber B16;
+    CARD32      length B32;
+    CARD32      pad2 B32;
+    CARD32      pad3 B32;
+    CARD32      pad4 B32;
+    CARD32      pad5 B32;
+    CARD32      pad6 B32;
+    CARD32      pad7 B32;
+} xXF86DRICloseFullScreenReply;
+#define sz_xXF86DRICloseFullScreenReply  32
+
+
+#endif /* _XF86DRISTR_H_ */
diff --git a/src/gallium/winsys/g3dvl/drm/Makefile b/src/gallium/winsys/g3dvl/drm/Makefile
new file mode 100644 (file)
index 0000000..0711f44
--- /dev/null
@@ -0,0 +1,12 @@
+# src/gallium/winsys/Makefile
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+SUBDIRS = $(GALLIUM_WINSYS_DRM_DIRS)
+
+default install clean:
+       @for dir in $(SUBDIRS) ; do \
+               if [ -d $$dir ] ; then \
+                       (cd $$dir && $(MAKE) $@) || exit 1; \
+               fi \
+       done
diff --git a/src/gallium/winsys/g3dvl/drm/Makefile.template b/src/gallium/winsys/g3dvl/drm/Makefile.template
new file mode 100644 (file)
index 0000000..2b79dee
--- /dev/null
@@ -0,0 +1,66 @@
+XVMC_MAJOR = 1
+XVMC_MINOR = 0
+XVMC_LIB = XvMCg3dvl
+XVMC_LIB_NAME = lib$(XVMC_LIB).so
+XVMC_LIB_DEPS = $(EXTRA_LIB_PATH) -lXvMC -lXv -lX11 -lm
+
+###############################################################
+
+INCLUDES = $(DRIVER_INCLUDES) \
+           -I$(TOP)/src/gallium/include \
+           -I$(TOP)/src/gallium/auxiliary \
+           -I$(TOP)/src/gallium/drivers \
+           -I$(TOP)/src/gallium/winsys/g3dvl \
+           -I$(TOP)/src/gallium/winsys/g3dvl/dri
+
+DEFINES += $(DRIVER_DEFINES) \
+           -DGALLIUM_SOFTPIPE \
+           -DGALLIUM_TRACE
+
+# XXX: Hack, if we include libxvmctracker.a in LIBS none of the symbols are
+# pulled in by the linker because xsp_winsys.c doesn't refer to them
+OBJECTS = $(C_SOURCES:.c=.o) $(TOP)/src/gallium/state_trackers/xorg/xvmc/*.o
+
+LIBS = $(TOP)/src/gallium/winsys/g3dvl/dri/libvldri.a \
+       $(PIPE_DRIVERS) \
+       $(TOP)/src/gallium/auxiliary/libgallium.a
+
+.c.o:
+       $(CC) -c $(INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@
+
+.S.o:
+       $(CC) -c $(INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@
+
+.PHONY: default $(TOP)/$(LIB_DIR)/gallium clean
+
+default: depend $(TOP)/$(LIB_DIR)/gallium $(TOP)/$(LIB_DIR)/gallium/$(XVMC_LIB_NAME)
+
+$(TOP)/$(LIB_DIR)/gallium:
+       @mkdir -p $(TOP)/$(LIB_DIR)/gallium
+
+# Make the libXvMCg3dvl.so library
+$(TOP)/$(LIB_DIR)/gallium/$(XVMC_LIB_NAME): $(OBJECTS) $(LIBS) Makefile
+       $(MKLIB) -o $(XVMC_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
+               -major $(XVMC_MAJOR) -minor $(XVMC_MINOR) $(MKLIB_OPTIONS) \
+               -install $(TOP)/$(LIB_DIR)/gallium -id $(INSTALL_LIB_DIR)/lib$(XVMC_LIB).1.dylib \
+               $(XVMC_LIB_DEPS) $(DRIVER_LIB_DEPS) $(OBJECTS) $(LIBS)
+
+depend: $(SOURCES) Makefile
+       $(RM) depend
+       touch depend
+       $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(SOURCES)
+
+#install: default
+#      $(INSTALL) -d $(INSTALL_DIR)/include/GL
+#      $(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR)
+#      $(INSTALL) -m 644 $(TOP)/include/GL/*.h $(INSTALL_DIR)/include/GL
+#      @if [ -e $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) ]; then \
+#              $(INSTALL) $(TOP)/$(LIB_DIR)/libGL* $(INSTALL_DIR)/$(LIB_DIR); \
+#      fi
+
+clean: Makefile
+       $(RM) $(TOP)/$(LIB_DIR)/gallium/$(XVMC_LIB_NAME)
+       $(RM) *.o *~
+       $(RM) depend depend.bak
+
+-include depend
diff --git a/src/gallium/winsys/g3dvl/drm/nouveau/Makefile b/src/gallium/winsys/g3dvl/drm/nouveau/Makefile
new file mode 100644 (file)
index 0000000..5c55186
--- /dev/null
@@ -0,0 +1,23 @@
+# This makefile produces a libXvMCg3dvl.so which is
+# based on DRM/DRI
+
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+C_SOURCES =
+
+DRIVER_INCLUDES = $(shell pkg-config libdrm libdrm_nouveau --cflags-only-I) \
+                   -I$(TOP)/src/gallium/winsys/drm/nouveau
+DRIVER_DEFINES = $(shell pkg-config libdrm libdrm_nouveau --cflags-only-other)
+
+PIPE_DRIVERS = \
+       $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \
+       $(TOP)/src/gallium/drivers/nv30/libnv30.a \
+       $(TOP)/src/gallium/drivers/nv40/libnv40.a \
+       $(TOP)/src/gallium/drivers/nv50/libnv50.a \
+       $(TOP)/src/gallium/drivers/nouveau/libnouveau.a \
+        $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a
+
+DRIVER_LIB_DEPS += $(shell pkg-config libdrm_nouveau --libs)
+
+include ../Makefile.template
diff --git a/src/gallium/winsys/g3dvl/drm/radeon/Makefile b/src/gallium/winsys/g3dvl/drm/radeon/Makefile
new file mode 100644 (file)
index 0000000..0f7fd1c
--- /dev/null
@@ -0,0 +1,20 @@
+# This makefile produces a libXvMCg3dvl.so which is
+# based on DRM/DRI
+
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+C_SOURCES =
+
+DRIVER_INCLUDES = $(shell pkg-config libdrm libdrm_radeon --cflags-only-I) \
+                   -I$(TOP)/src/gallium/winsys/drm/radeon \
+DRIVER_DEFINES = $(shell pkg-config libdrm libdrm_radeon --cflags-only-other)
+
+PIPE_DRIVERS = \
+       $(TOP)/src/gallium/winsys/drm/radeon/core/libradeonwinsys.a \
+       $(TOP)/src/gallium/drivers/r300/libr300.a \
+        $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a
+
+DRIVER_LIB_DEPS += $(shell pkg-config libdrm_radeon --libs)
+
+include ../Makefile.template
diff --git a/src/gallium/winsys/g3dvl/vl_winsys.h b/src/gallium/winsys/g3dvl/vl_winsys.h
new file mode 100644 (file)
index 0000000..3814786
--- /dev/null
@@ -0,0 +1,69 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef vl_winsys_h
+#define vl_winsys_h
+
+#include <X11/Xlib.h>
+#include <pipe/p_defines.h>
+#include <pipe/p_format.h>
+
+struct pipe_screen;
+struct pipe_video_context;
+struct pipe_surface;
+
+struct vl_screen
+{
+   struct pipe_screen *pscreen;
+};
+
+struct vl_context
+{
+   struct vl_screen *vscreen;
+   struct pipe_video_context *vpipe;
+};
+
+struct vl_screen*
+vl_screen_create(Display *display, int screen);
+
+void vl_screen_destroy(struct vl_screen *vscreen);
+
+struct vl_context*
+vl_video_create(struct vl_screen *vscreen,
+                enum pipe_video_profile profile,
+                enum pipe_video_chroma_format chroma_format,
+                unsigned width, unsigned height);
+
+void vl_video_destroy(struct vl_context *vctx);
+
+struct pipe_surface*
+vl_drawable_surface_get(struct vl_screen *vscreen, Drawable drawable);
+
+void*
+vl_contextprivate_get(struct vl_context *vctx, struct pipe_surface *drawable_surface);
+
+#endif
diff --git a/src/gallium/winsys/g3dvl/xlib/xsp_winsys.c b/src/gallium/winsys/g3dvl/xlib/xsp_winsys.c
new file mode 100644 (file)
index 0000000..0a7f324
--- /dev/null
@@ -0,0 +1,202 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <vl_winsys.h>
+#include <X11/Xlibint.h>
+#include <state_tracker/xlib_sw_winsys.h>
+#include <util/u_memory.h>
+#include <util/u_format.h>
+#include <softpipe/sp_public.h>
+#include <softpipe/sp_video_context.h>
+
+struct vl_xsp_screen
+{
+   struct vl_screen base;
+   Display *display;
+   int screen;
+   Visual visual;
+   struct xlib_drawable xdraw;
+   struct pipe_surface *drawable_surface;
+};
+
+struct pipe_surface*
+vl_drawable_surface_get(struct vl_screen *vscreen, Drawable drawable)
+{
+   struct vl_xsp_screen *xsp_screen = (struct vl_xsp_screen*)vscreen;
+   Window root;
+   int x, y;
+   unsigned int width, height;
+   unsigned int border_width;
+   unsigned int depth;
+   struct pipe_resource templat, *drawable_tex;
+   struct pipe_surface *drawable_surface = NULL;
+
+   assert(vscreen);
+   assert(drawable != None);
+
+   if (XGetGeometry(xsp_screen->display, drawable, &root, &x, &y, &width, &height, &border_width, &depth) == BadDrawable)
+      return NULL;
+
+   xsp_screen->xdraw.drawable = drawable;
+
+   if (xsp_screen->drawable_surface) {
+      if (xsp_screen->drawable_surface->width == width &&
+          xsp_screen->drawable_surface->height == height) {
+         pipe_surface_reference(&drawable_surface, xsp_screen->drawable_surface);
+         return drawable_surface;
+      }
+      else
+         pipe_surface_reference(&xsp_screen->drawable_surface, NULL);
+   }
+
+   memset(&templat, 0, sizeof(struct pipe_resource));
+   templat.target = PIPE_TEXTURE_2D;
+   /* XXX: Need to figure out drawable's format */
+   templat.format = PIPE_FORMAT_B8G8R8X8_UNORM;
+   templat.last_level = 0;
+   templat.width0 = width;
+   templat.height0 = height;
+   templat.depth0 = 1;
+   templat.usage = PIPE_USAGE_DEFAULT;
+   templat.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_BLIT_SOURCE;
+   templat.flags = 0;
+
+   drawable_tex = vscreen->pscreen->resource_create(vscreen->pscreen, &templat);
+   if (!drawable_tex)
+      return NULL;
+
+   xsp_screen->drawable_surface = vscreen->pscreen->get_tex_surface(vscreen->pscreen, drawable_tex,
+                                                                    0, 0, 0,
+                                                                    templat.bind);
+   pipe_resource_reference(&drawable_tex, NULL);
+
+   if (!xsp_screen->drawable_surface)
+      return NULL;
+
+   pipe_surface_reference(&drawable_surface, xsp_screen->drawable_surface);
+
+   xsp_screen->xdraw.depth = 24/*util_format_get_blocksizebits(templat.format) /
+                             util_format_get_blockwidth(templat.format)*/;
+
+   return drawable_surface;
+}
+
+void*
+vl_contextprivate_get(struct vl_context *vctx, struct pipe_surface *drawable_surface)
+{
+   struct vl_xsp_screen *xsp_screen = (struct vl_xsp_screen*)vctx->vscreen;
+
+   assert(vctx);
+   assert(drawable_surface);
+   assert(xsp_screen->drawable_surface == drawable_surface);
+
+   return &xsp_screen->xdraw;
+}
+
+struct vl_screen*
+vl_screen_create(Display *display, int screen)
+{
+   struct vl_xsp_screen *xsp_screen;
+   struct sw_winsys *winsys;
+
+   assert(display);
+
+   xsp_screen = CALLOC_STRUCT(vl_xsp_screen);
+   if (!xsp_screen)
+      return NULL;
+
+   winsys = xlib_create_sw_winsys(display);
+   if (!winsys) {
+      FREE(xsp_screen);
+      return NULL;
+   }
+
+   xsp_screen->base.pscreen = softpipe_create_screen(winsys);
+   if (!xsp_screen->base.pscreen) {
+      winsys->destroy(winsys);
+      FREE(xsp_screen);
+      return NULL;
+   }
+
+   xsp_screen->display = display;
+   xsp_screen->screen = screen;
+   xsp_screen->xdraw.visual = XDefaultVisual(display, screen);
+
+   return &xsp_screen->base;
+}
+
+void vl_screen_destroy(struct vl_screen *vscreen)
+{
+   struct vl_xsp_screen *xsp_screen = (struct vl_xsp_screen*)vscreen;
+
+   assert(vscreen);
+
+   pipe_surface_reference(&xsp_screen->drawable_surface, NULL);
+   vscreen->pscreen->destroy(vscreen->pscreen);
+   FREE(vscreen);
+}
+
+struct vl_context*
+vl_video_create(struct vl_screen *vscreen,
+                enum pipe_video_profile profile,
+                enum pipe_video_chroma_format chroma_format,
+                unsigned width, unsigned height)
+{
+   struct pipe_video_context *vpipe;
+   struct vl_context *vctx;
+
+   assert(vscreen);
+   assert(width && height);
+   assert(vscreen->pscreen->video_context_create);
+
+   vpipe = vscreen->pscreen->video_context_create(vscreen->pscreen,
+                                                  profile,
+                                                  chroma_format,
+                                                  width, height, NULL);
+   if (!vpipe)
+      return NULL;
+
+   vctx = CALLOC_STRUCT(vl_context);
+   if (!vctx) {
+      vpipe->destroy(vpipe);
+      return NULL;
+   }
+
+   vpipe->priv = vctx;
+   vctx->vpipe = vpipe;
+   vctx->vscreen = vscreen;
+
+   return vctx;
+}
+
+void vl_video_destroy(struct vl_context *vctx)
+{
+   assert(vctx);
+
+   vctx->vpipe->destroy(vctx->vpipe);
+   FREE(vctx);
+}