summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am2
-rw-r--r--src/i830.h15
-rw-r--r--src/i830_driver.c6
-rw-r--r--src/i830_memory.c38
-rw-r--r--src/i830_video.c17
-rw-r--r--src/i830_video.h1
-rw-r--r--src/i915_hwmc.c932
-rw-r--r--src/i915_hwmc.h64
-rw-r--r--src/xvmc/I915XvMC.c3056
-rw-r--r--src/xvmc/I915XvMC.h178
-rw-r--r--src/xvmc/Makefile.am16
-rw-r--r--src/xvmc/driDrawable.c174
-rw-r--r--src/xvmc/driDrawable.h64
-rw-r--r--src/xvmc/i915_program.h276
-rw-r--r--src/xvmc/i915_structs.h898
-rw-r--r--src/xvmc/intel_batchbuffer.c197
-rw-r--r--src/xvmc/intel_batchbuffer.h42
-rw-r--r--src/xvmc/xf86dri.c599
-rw-r--r--src/xvmc/xf86dri.h109
-rw-r--r--src/xvmc/xf86dristr.h390
20 files changed, 7072 insertions, 2 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 858ffd17..028dcfdd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,6 +59,8 @@ INTEL_DRI_SRCS = \
i810_dri.h \
i830_dri.c \
i810_hwmc.c \
+ i915_hwmc.c \
+ i915_hwmc.h \
i830_dri.h
intel_drv_la_SOURCES = \
diff --git a/src/i830.h b/src/i830.h
index aa2b240c..21497820 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -309,6 +309,11 @@ typedef struct _I830Rec {
/* For Xvideo */
i830_memory *overlay_regs;
#endif
+
+ /* For XvMC */
+ void *xvmc;
+ Bool XvMCEnabled;
+
XF86ModReqInfo shadowReq; /* to test for later libshadow */
Rotation rotation;
void (*PointerMoved)(int, int, int);
@@ -644,7 +649,10 @@ extern long I830CheckAvailableMemory(ScrnInfoPtr pScrn);
Bool i830_allocate_2d_memory(ScrnInfoPtr pScrn);
Bool i830_allocate_texture_memory(ScrnInfoPtr pScrn);
Bool i830_allocate_3d_memory(ScrnInfoPtr pScrn);
-
+Bool i830_allocate_xvmc_surface(ScrnInfoPtr pScrn, i830_memory **surface,
+ unsigned long size);
+Bool i830_allocate_xvmc_buffer(ScrnInfoPtr pScrn, const char *name,
+ i830_memory **buffer, unsigned long size);
extern Bool I830IsPrimary(ScrnInfoPtr pScrn);
extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
@@ -738,6 +746,11 @@ static inline int i830_fb_compression_supported(I830Ptr pI830)
return TRUE;
}
+/* i915 XvMC */
+int I915XvMCInitXv(ScrnInfoPtr, XF86VideoAdaptorPtr);
+void I915InitMC(ScreenPtr);
+unsigned long I915XvMCPutImageSize(ScrnInfoPtr);
+
extern const int I830PatternROP[16];
extern const int I830CopyROP[16];
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 9bb12c6b..9cae2911 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2720,6 +2720,12 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
if (pI830->directRenderingEnabled) {
pI830->directRenderingEnabled = I830DRIFinishScreenInit(pScreen);
}
+
+#ifdef XvMCExtension
+ if ((pI830->directRenderingEnabled) && IS_I9XX(pI830)) {
+ I915InitMC(pScreen);
+ }
+#endif
#endif
/* Setup 3D engine, needed for rotation too */
diff --git a/src/i830_memory.c b/src/i830_memory.c
index b38a5dfe..7022167b 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1758,4 +1758,42 @@ i830_xf86AllocateOffscreenLinear(ScreenPtr pScreen, int length,
return linear;
}
+
+/*
+ * Allocate memory for XvMC surface
+ */
+Bool
+i830_allocate_xvmc_surface(ScrnInfoPtr pScrn, i830_memory **surface, unsigned long size)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ *surface = i830_allocate_memory(pScrn, "XvMC surface", size,
+ GTT_PAGE_SIZE, ALIGN_BOTH_ENDS);
+
+ if (!*surface) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate XvMC surface space.\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ * Allocate memory for MC compensation
+ */
+Bool i830_allocate_xvmc_buffer(ScrnInfoPtr pScrn, const char *name, i830_memory **buffer, unsigned long size)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ *buffer = i830_allocate_memory(pScrn, name, size,
+ GTT_PAGE_SIZE, ALIGN_BOTH_ENDS);
+
+ if (!*buffer) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate memory for %s.\n", name);
+ return FALSE;
+ }
+ return TRUE;
+}
#endif
diff --git a/src/i830_video.c b/src/i830_video.c
index b4f9e746..4f5ab434 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -74,6 +74,8 @@
#include "dixstruct.h"
#include "fourcc.h"
+#include "i915_hwmc.h"
+
#ifndef USE_USLEEP_FOR_VIDEO
#define USE_USLEEP_FOR_VIDEO 0
#endif
@@ -576,6 +578,11 @@ I830InitVideo(ScreenPtr pScreen)
if (texturedAdaptor != NULL) {
adaptors[num_adaptors++] = texturedAdaptor;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n");
+
+#ifdef XF86DRI
+ if (pI830->XvMCEnabled && IS_I9XX(pI830))
+ I915XvMCInitXv(pScrn, texturedAdaptor);
+#endif
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to set up textured video\n");
@@ -2587,6 +2594,16 @@ I830QueryImageAttributes(ScrnInfoPtr pScrn,
ErrorF("size is %d\n", size);
#endif
break;
+ case FOURCC_XVMC:
+ *h = (*h + 1) & ~1;
+#ifdef XF86DRI
+ size = I915XvMCPutImageSize(pScrn);
+#else
+ size = 0;
+#endif
+ if (pitches)
+ pitches[0] = size;
+ break;
case FOURCC_UYVY:
case FOURCC_YUY2:
default:
diff --git a/src/i830_video.h b/src/i830_video.h
index 7e2d1498..67022f6a 100644
--- a/src/i830_video.h
+++ b/src/i830_video.h
@@ -77,6 +77,7 @@ typedef struct {
int oneLineMode;
int scaleRatio;
Bool textured;
+ void *xvmc_priv;
} I830PortPrivRec, *I830PortPrivPtr;
#define GET_PORT_PRIVATE(pScrn) \
diff --git a/src/i915_hwmc.c b/src/i915_hwmc.c
new file mode 100644
index 00000000..119b9084
--- /dev/null
+++ b/src/i915_hwmc.c
@@ -0,0 +1,932 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "compiler.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "xf86fbman.h"
+#include "regionstr.h"
+
+#include "i830.h"
+#include "i830_dri.h"
+#include "i830_video.h"
+#include "xf86xv.h"
+#include "xf86xvmc.h"
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/XvMC.h>
+#include "xaa.h"
+#include "xaalocal.h"
+#include "dixstruct.h"
+#include "fourcc.h"
+
+#if defined(X_NEED_XVPRIV_H) || defined (_XF86_FOURCC_H_)
+#include "xf86xvpriv.h"
+#endif
+
+#include "i915_hwmc.h"
+
+#define MAKE_ATOM(a) MakeAtom(a, strlen(a), TRUE)
+
+/*
+ * List Attributes for the XvMC extension to handle:
+ * As long as the attribute is supported by the Xv adaptor, it needs only to
+ * be added here to be supported also by XvMC.
+ * Currently, only colorkey seems to be supported by Xv for Putimage.
+ */
+static char *attrXvMC[I915_NUM_XVMC_ATTRIBUTES] = {
+ "XV_BRIGHTNESS",
+ "XV_CONTRAST",
+};
+static Atom attrAtoms[I915_NUM_XVMC_ATTRIBUTES];
+
+typedef struct
+{
+ unsigned ctxDisplaying;
+ int xvmc_port;
+ I915XvMCAttrHolder xvAttr;
+ int newAttribute;
+
+ SetPortAttributeFuncPtr SetPortAttribute;
+ GetPortAttributeFuncPtr GetPortAttribute;
+ PutImageFuncPtr PutImage;
+} I915XvMCXVPriv;
+
+#define I915_XVMC_MAX_BUFFERS 2
+#define I915_XVMC_MAX_CONTEXTS 4
+#define I915_XVMC_MAX_SURFACES 20
+
+typedef struct _I915XvMCSurfacePriv
+{
+ i830_memory *surface;
+ unsigned long offsets[I915_XVMC_MAX_BUFFERS];
+} I915XvMCSurfacePriv;
+
+typedef struct _I915XvMCContextPriv
+{
+ i830_memory *mcStaticIndirectState;
+ drm_handle_t sis_handle;
+ i830_memory *mcMapState;
+ drm_handle_t msb_handle;
+ i830_memory *mcSamplerState;
+ drm_handle_t ssb_handle;
+ i830_memory *mcPixelShaderProgram;
+ drm_handle_t psp_handle;
+ i830_memory *mcPixelShaderConstants;
+ drm_handle_t psc_handle;
+ i830_memory *mcCorrdata;
+ drm_handle_t corrdata_handle;
+} I915XvMCContextPriv;
+
+typedef struct _I915XvMC
+{
+ XID contexts[I915_XVMC_MAX_CONTEXTS];
+ XID surfaces[I915_XVMC_MAX_SURFACES];
+ I915XvMCSurfacePriv *sfprivs[I915_XVMC_MAX_SURFACES];
+ I915XvMCContextPriv *ctxprivs[I915_XVMC_MAX_CONTEXTS];
+ int ncontexts,nsurfaces;
+} I915XvMC, *I915XvMCPtr;
+
+#define ARRARY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+static int I915XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
+ int *num_priv, long **priv );
+static void I915XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext);
+
+static int I915XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf,
+ int *num_priv, long **priv );
+static void I915XvMCDestroySurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf);
+
+static int I915XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf,
+ int *num_priv, long **priv );
+static void I915XvMCDestroySubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf);
+
+static int yv12_subpicture_index_list[2] =
+{
+ FOURCC_IA44,
+ FOURCC_AI44
+};
+
+static XF86MCImageIDList yv12_subpicture_list =
+{
+ ARRARY_SIZE(yv12_subpicture_index_list),
+ yv12_subpicture_index_list
+};
+
+static XF86MCSurfaceInfoRec i915_YV12_mpg2_surface =
+{
+ FOURCC_YV12,
+ XVMC_CHROMA_FORMAT_420,
+ 0,
+ 720,
+ 576,
+ 720,
+ 576,
+ XVMC_MPEG_2,
+ XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
+ XVMC_INTRA_UNSIGNED,
+ &yv12_subpicture_list
+};
+
+static XF86MCSurfaceInfoRec i915_YV12_mpg1_surface =
+{
+ FOURCC_YV12,
+ XVMC_CHROMA_FORMAT_420,
+ 0,
+ 720,
+ 576,
+ 720,
+ 576,
+ XVMC_MPEG_1,
+ XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
+ XVMC_INTRA_UNSIGNED,
+ &yv12_subpicture_list
+};
+
+static XF86MCSurfaceInfoPtr ppSI[2] =
+{
+ (XF86MCSurfaceInfoPtr)&i915_YV12_mpg2_surface,
+ (XF86MCSurfaceInfoPtr)&i915_YV12_mpg1_surface
+};
+
+/* List of subpicture types that we support */
+static XF86ImageRec ia44_subpicture = XVIMAGE_IA44;
+static XF86ImageRec ai44_subpicture = XVIMAGE_AI44;
+
+static XF86ImagePtr i915_subpicture_list[2] =
+{
+ (XF86ImagePtr)&ia44_subpicture,
+ (XF86ImagePtr)&ai44_subpicture
+};
+
+/* Fill in the device dependent adaptor record.
+ * This is named "Intel(R) Textured Video" because this code falls under the
+ * XV extenstion, the name must match or it won't be used.
+ *
+ * Surface and Subpicture - see above
+ * Function pointers to functions below
+ */
+static XF86MCAdaptorRec pAdapt =
+{
+ "Intel(R) Textured Video", /* name */
+ ARRARY_SIZE(ppSI), /* num_surfaces */
+ ppSI, /* surfaces */
+ ARRARY_SIZE(i915_subpicture_list), /* num_subpictures */
+ i915_subpicture_list, /* subpictures */
+ (xf86XvMCCreateContextProcPtr)I915XvMCCreateContext,
+ (xf86XvMCDestroyContextProcPtr)I915XvMCDestroyContext,
+ (xf86XvMCCreateSurfaceProcPtr)I915XvMCCreateSurface,
+ (xf86XvMCDestroySurfaceProcPtr)I915XvMCDestroySurface,
+ (xf86XvMCCreateSubpictureProcPtr)I915XvMCCreateSubpicture,
+ (xf86XvMCDestroySubpictureProcPtr)I915XvMCDestroySubpicture
+};
+
+static XF86MCAdaptorPtr ppAdapt[1] =
+{
+ (XF86MCAdaptorPtr)&pAdapt
+};
+
+static unsigned int stride(int w)
+{
+ return (w + 31) & ~31;
+}
+
+static unsigned long size_yuv420(int w, int h)
+{
+ unsigned yPitch = stride(w);
+
+ return h * (yPitch + (yPitch >> 1));
+}
+
+static unsigned long size_xx44(int w, int h)
+{
+ return h * stride(w);
+}
+
+/*
+ * Init and clean up the screen private parts of XvMC.
+ */
+static void initI915XvMC(I915XvMCPtr xvmc)
+{
+ unsigned int i;
+
+ for (i = 0; i < I915_XVMC_MAX_CONTEXTS; i++) {
+ xvmc->contexts[i] = 0;
+ xvmc->ctxprivs[i] = NULL;
+ }
+
+ for (i = 0; i < I915_XVMC_MAX_SURFACES; i++) {
+ xvmc->surfaces[i] = 0;
+ xvmc->sfprivs[i] = NULL;
+ }
+}
+
+static void cleanupI915XvMC(I915XvMCPtr xvmc, XF86VideoAdaptorPtr * XvAdaptors, int XvAdaptorCount)
+{
+ unsigned int i;
+
+ for (i = 0; i < I915_XVMC_MAX_CONTEXTS; i++) {
+ xvmc->contexts[i] = 0;
+
+ if (xvmc->ctxprivs[i]) {
+ xfree(xvmc->ctxprivs[i]);
+ xvmc->ctxprivs[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < I915_XVMC_MAX_SURFACES; i++) {
+ xvmc->surfaces[i] = 0;
+
+ if (xvmc->sfprivs[i]) {
+ xfree(xvmc->sfprivs[i]);
+ xvmc->sfprivs[i] = NULL;
+ }
+ }
+}
+
+static Bool i915_map_xvmc_buffers(ScrnInfoPtr pScrn, I915XvMCContextPriv *ctxpriv)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (drmAddMap(pI830->drmSubFD,
+ (drm_handle_t)(ctxpriv->mcStaticIndirectState->offset + pI830->LinearAddr),
+ ctxpriv->mcStaticIndirectState->size, DRM_AGP, 0,
+ (drmAddress)&ctxpriv->sis_handle) < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[drm] drmAddMap(sis_handle) failed!\n");
+ return FALSE;
+ }
+
+ if (drmAddMap(pI830->drmSubFD,
+ (drm_handle_t)(ctxpriv->mcMapState->offset + pI830->LinearAddr),
+ ctxpriv->mcMapState->size, DRM_AGP, 0,
+ (drmAddress)&ctxpriv->msb_handle) < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[drm] drmAddMap(msb_handle) failed!\n");
+ return FALSE;
+ }
+
+ if (drmAddMap(pI830->drmSubFD,
+ (drm_handle_t)(ctxpriv->mcSamplerState->offset + pI830->LinearAddr),
+ ctxpriv->mcSamplerState->size, DRM_AGP, 0,
+ (drmAddress)&ctxpriv->ssb_handle) < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[drm] drmAddress(ssb_handle) failed!\n");
+ return FALSE;
+ }
+
+ if (drmAddMap(pI830->drmSubFD,
+ (drm_handle_t)(ctxpriv->mcPixelShaderProgram->offset + pI830->LinearAddr),
+ ctxpriv->mcPixelShaderProgram->size, DRM_AGP, 0,
+ (drmAddress)&ctxpriv->psp_handle) < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[drm] drmAddress(psp_handle) failed!\n");
+ return FALSE;
+ }
+
+ if (drmAddMap(pI830->drmSubFD,
+ (drm_handle_t)(ctxpriv->mcPixelShaderConstants->offset + pI830->LinearAddr),
+ ctxpriv->mcPixelShaderConstants->size, DRM_AGP, 0,
+ (drmAddress)&ctxpriv->psc_handle) < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[drm] drmAddress(psc_handle) failed!\n");
+ return FALSE;
+ }
+
+ if (drmAddMap(pI830->drmSubFD,
+ (drm_handle_t)(ctxpriv->mcCorrdata->offset + pI830->LinearAddr),
+ ctxpriv->mcCorrdata->size, DRM_AGP, 0,
+ (drmAddress)&ctxpriv->corrdata_handle) < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[drm] drmAddMap(corrdata_handle) failed!\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void i915_unmap_xvmc_buffers(ScrnInfoPtr pScrn, I915XvMCContextPriv *ctxpriv)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (ctxpriv->sis_handle) {
+ drmRmMap(pI830->drmSubFD, ctxpriv->sis_handle);
+ ctxpriv->sis_handle = 0;
+ }
+
+ if (ctxpriv->msb_handle) {
+ drmRmMap(pI830->drmSubFD, ctxpriv->msb_handle);
+ ctxpriv->msb_handle = 0;
+ }
+
+ if (ctxpriv->ssb_handle) {
+ drmRmMap(pI830->drmSubFD, ctxpriv->ssb_handle);
+ ctxpriv->ssb_handle = 0;
+ }
+
+ if (ctxpriv->psp_handle) {
+ drmRmMap(pI830->drmSubFD, ctxpriv->psp_handle);
+ ctxpriv->psp_handle = 0;
+ }
+
+ if (ctxpriv->psc_handle) {
+ drmRmMap(pI830->drmSubFD, ctxpriv->psc_handle);
+ ctxpriv->psc_handle = 0;
+ }
+
+ if (ctxpriv->corrdata_handle) {
+ drmRmMap(pI830->drmSubFD, ctxpriv->corrdata_handle);
+ ctxpriv->corrdata_handle = 0;
+ }
+}
+
+static Bool i915_allocate_xvmc_buffers(ScrnInfoPtr pScrn, I915XvMCContextPriv *ctxpriv)
+{
+ if (!i830_allocate_xvmc_buffer(pScrn, "Static Indirect State",
+ &(ctxpriv->mcStaticIndirectState), 512)) {
+ return FALSE;
+ }
+
+ if (!i830_allocate_xvmc_buffer(pScrn, "Map State",
+ &(ctxpriv->mcMapState), 512)) {
+ return FALSE;
+ }
+
+ if (!i830_allocate_xvmc_buffer(pScrn, "Sampler State",
+ &(ctxpriv->mcSamplerState), 512)) {
+ return FALSE;
+ }
+
+ if (!i830_allocate_xvmc_buffer(pScrn, "Pixel Shader Program",
+ &(ctxpriv->mcPixelShaderProgram), 512)) {
+ return FALSE;
+ }
+
+ if (!i830_allocate_xvmc_buffer(pScrn, "Pixel Shader Constants",
+ &(ctxpriv->mcPixelShaderConstants), 128)) {
+ return FALSE;
+ }
+
+ if (!i830_allocate_xvmc_buffer(pScrn, "Correction Data Buffer",
+ &(ctxpriv->mcCorrdata), 2 * 1024 * 1024)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void i915_free_xvmc_buffers(ScrnInfoPtr pScrn, I915XvMCContextPriv *ctxpriv)
+{
+ if (ctxpriv->mcStaticIndirectState) {
+ i830_free_memory(pScrn, ctxpriv->mcStaticIndirectState);
+ ctxpriv->mcStaticIndirectState = NULL;
+ }
+
+ if (ctxpriv->mcMapState) {
+ i830_free_memory(pScrn, ctxpriv->mcMapState);
+ ctxpriv->mcMapState = NULL;
+ }
+
+ if (ctxpriv->mcSamplerState) {
+ i830_free_memory(pScrn, ctxpriv->mcSamplerState);
+ ctxpriv->mcSamplerState = NULL;
+ }
+
+ if (ctxpriv->mcPixelShaderProgram) {
+ i830_free_memory(pScrn, ctxpriv->mcPixelShaderProgram);
+ ctxpriv->mcPixelShaderProgram = NULL;
+ }
+
+ if (ctxpriv->mcPixelShaderConstants) {
+ i830_free_memory(pScrn, ctxpriv->mcPixelShaderConstants);
+ ctxpriv->mcPixelShaderConstants = NULL;
+ }
+
+ if (ctxpriv->mcCorrdata) {
+ i830_free_memory(pScrn, ctxpriv->mcCorrdata);
+ ctxpriv->mcCorrdata = NULL;
+ }
+}
+
+/**************************************************************************
+ *
+ * I915XvMCCreateContext
+ *
+ * Some info about the private data:
+ *
+ * Set *num_priv to the number of 32bit words that make up the size of
+ * of the data that priv will point to.
+ *
+ * *priv = (long *) xcalloc (elements, sizeof(element))
+ * *num_priv = (elements * sizeof(element)) >> 2;
+ *
+ **************************************************************************/
+
+static int I915XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
+ int *num_priv, long **priv )
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ DRIInfoPtr pDRIInfo = pI830->pDRIInfo;
+ I915XvMCCreateContextRec *contextRec = NULL;
+ I915XvMCPtr pXvMC = pI830->xvmc;
+ I915XvMCContextPriv *ctxpriv = NULL;
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)pContext->port_priv;
+ I830PortPrivPtr pPriv = (I830PortPrivPtr)portPriv->DevPriv.ptr;
+ I915XvMCXVPriv *vx = (I915XvMCXVPriv *)pPriv->xvmc_priv;
+
+ int i;
+
+ *priv = NULL;
+ *num_priv = 0;
+
+ if (!pI830->directRenderingEnabled) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[XvMC] I915XvMCCreateContext: Cannot use XvMC without DRI!\n");
+ return BadAlloc;
+ }
+
+ if (pXvMC->ncontexts >= I915_XVMC_MAX_CONTEXTS) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[XvMC] I915XvMCCreateContext: Out of contexts.\n");
+ return BadAlloc;
+ }
+
+ *priv = xcalloc(1, sizeof(I915XvMCCreateContextRec));
+ contextRec = (I915XvMCCreateContextRec *)*priv;
+
+ if (!*priv) {
+ *num_priv = 0;
+ return BadAlloc;
+ }
+
+ *num_priv = sizeof(I915XvMCCreateContextRec) >> 2;
+
+ for (i = 0; i < I915_XVMC_MAX_CONTEXTS; i++) {
+ if (!pXvMC->contexts[i])
+ break;
+ }
+
+ ctxpriv = (I915XvMCContextPriv *)xcalloc(1, sizeof(I915XvMCContextPriv));
+
+ if (!ctxpriv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[XvMC] I915XvMCCreateContext: Unable to allocate memory!\n");
+ xfree(*priv);
+ *priv = NULL;
+ *num_priv = 0;
+ return BadAlloc;
+ }
+
+ if (!i915_allocate_xvmc_buffers(pScrn, ctxpriv)) {
+ i915_free_xvmc_buffers(pScrn, ctxpriv);
+ xfree(ctxpriv);
+ ctxpriv = NULL;
+ xfree(*priv);
+ *priv = NULL;
+ *num_priv = 0;
+ return BadAlloc;
+ }
+
+ if (!i915_map_xvmc_buffers(pScrn, ctxpriv)) {
+ i915_unmap_xvmc_buffers(pScrn, ctxpriv);
+ i915_free_xvmc_buffers(pScrn, ctxpriv);
+ xfree(ctxpriv);
+ ctxpriv = NULL;
+ xfree(*priv);
+ *priv = NULL;
+ *num_priv = 0;
+ return BadAlloc;
+ }
+
+ contextRec->ctxno = i;
+ contextRec->sis.handle = ctxpriv->sis_handle;
+ contextRec->sis.offset = ctxpriv->mcStaticIndirectState->offset;
+ contextRec->sis.size = ctxpriv->mcStaticIndirectState->size;
+ contextRec->msb.handle = ctxpriv->msb_handle;
+ contextRec->msb.offset = ctxpriv->mcMapState->offset;
+ contextRec->msb.size = ctxpriv->mcMapState->size;
+ contextRec->ssb.handle = ctxpriv->ssb_handle;
+ contextRec->ssb.offset = ctxpriv->mcSamplerState->offset;
+ contextRec->ssb.size = ctxpriv->mcSamplerState->size;
+ contextRec->psp.handle = ctxpriv->psp_handle;
+ contextRec->psp.offset = ctxpriv->mcPixelShaderProgram->offset;
+ contextRec->psp.size = ctxpriv->mcPixelShaderProgram->size;
+ contextRec->psc.handle = ctxpriv->psc_handle;
+ contextRec->psc.offset = ctxpriv->mcPixelShaderConstants->offset;
+ contextRec->psc.size = ctxpriv->mcPixelShaderConstants->size;
+ contextRec->corrdata.handle = ctxpriv->corrdata_handle;
+ contextRec->corrdata.offset = ctxpriv->mcCorrdata->offset;
+ contextRec->corrdata.size = ctxpriv->mcCorrdata->size;
+ contextRec->sarea_size = pDRIInfo->SAREASize;
+ contextRec->sarea_priv_offset = sizeof(XF86DRISAREARec);
+ contextRec->screen = pScrn->pScreen->myNum;
+ contextRec->depth = pScrn->bitsPerPixel;
+ contextRec->initAttrs = vx->xvAttr;
+
+ pXvMC->ncontexts++;
+ pXvMC->contexts[i] = pContext->context_id;
+ pXvMC->ctxprivs[i] = ctxpriv;
+
+ return Success;
+}
+
+static int I915XvMCCreateSurface(ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf,
+ int *num_priv, long **priv )
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I915XvMCPtr pXvMC = pI830->xvmc;
+ I915XvMCSurfacePriv *sfpriv = NULL;
+ XvMCContextPtr ctx = NULL;
+ unsigned int sfno, i, nbuffers;
+ unsigned long bufsize;
+
+ *priv = NULL;
+ *num_priv = 0;
+
+ if (pXvMC->nsurfaces >= I915_XVMC_MAX_SURFACES) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[XvMC] I915XvMCCreateSurface: Too many surfaces !\n");
+ return BadAlloc;
+ }
+
+ sfpriv = (I915XvMCSurfacePriv *)xcalloc(1, sizeof(I915XvMCSurfacePriv));
+
+ if (!sfpriv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[XvMC] I915XvMCCreateSurface: Unable to allocate memory!\n");
+ return BadAlloc;
+ }
+
+ nbuffers = 1;
+ *num_priv = nbuffers + 2;
+ *priv = (long *)xcalloc(*num_priv, sizeof(unsigned long));
+
+ if (!*priv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[XvMC] I915XvMCCreateSurface: Unable to allocate memory!\n");
+ xfree(sfpriv);
+ *num_priv = 0;
+ return BadAlloc;
+ }
+
+ ctx = pSurf->context;
+ bufsize = size_yuv420(ctx->width, ctx->height);
+
+ if (!i830_allocate_xvmc_surface(pScrn, &(sfpriv->surface), nbuffers * bufsize)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[XvMC] I915XvMCCreateSurface: Failed to allocate XvMC surface space!\n");
+ xfree(sfpriv);
+ xfree(*priv);
+ *priv = NULL;
+ *num_priv = 0;
+ return BadAlloc;
+ }
+
+ for (sfno = 0; sfno < I915_XVMC_MAX_SURFACES; ++sfno) {
+ if (!pXvMC->surfaces[sfno])
+ break;
+ }
+
+ (*priv)[0] = sfno;
+ (*priv)[1] = nbuffers;
+ (*priv)[2] = sfpriv->offsets[0] = sfpriv->surface->offset;
+
+ for (i = 1; i < nbuffers; ++i) {
+ (*priv)[i + 2] = sfpriv->offsets[i] = sfpriv->offsets[i - 1] + bufsize;
+ }
+
+ pXvMC->surfaces[sfno] = pSurf->surface_id;
+ pXvMC->sfprivs[sfno]= sfpriv;
+ pXvMC->nsurfaces++;
+
+ return Success;
+}
+
+static int I915XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp,
+ int *num_priv, long **priv )
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I915XvMCPtr pXvMC = pI830->xvmc;
+ I915XvMCSurfacePriv *sfpriv = NULL;
+ XvMCContextPtr ctx = NULL;
+ unsigned srfno;
+ unsigned bufsize;
+
+ if (I915_XVMC_MAX_SURFACES == pXvMC->nsurfaces) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[XvMC] I915XvMCCreateSubpicture: Too many surfaces !\n");
+ return BadAlloc;
+ }
+
+ sfpriv = (I915XvMCSurfacePriv *)xcalloc(1, sizeof(I915XvMCSurfacePriv));
+
+ if (!sfpriv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[XvMC] I915XvMCCreateSubpicture: Unable to allocate memory!\n");
+ *num_priv = 0;
+ return BadAlloc;
+ }
+
+ *priv = (INT32 *)xcalloc(3, sizeof(INT32));
+
+ if (!*priv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[XvMC] I915XvMCCreateSubpicture: Unable to allocate memory!\n");
+ *num_priv = 0;
+ xfree(sfpriv);
+ return BadAlloc;
+ }
+
+ *num_priv = 2;
+ ctx = pSubp->context;
+ bufsize = size_xx44(ctx->width, ctx->height);
+
+ if (!i830_allocate_xvmc_surface(pScrn, &(sfpriv->surface), bufsize)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[XvMC] I915XvMCCreateSurface: Failed to allocate XvMC surface space!\n");
+ xfree(sfpriv);
+ sfpriv = NULL;
+ xfree(*priv);
+ *priv = NULL;
+ *num_priv = 0;
+ return BadAlloc;
+ }
+
+ for (srfno = 0; srfno < I915_XVMC_MAX_SURFACES; ++srfno) {
+ if (0 == pXvMC->sfprivs[srfno])
+ break;
+ }
+
+ (*priv)[0] = srfno;
+ (*priv)[1] = sfpriv->offsets[0] = sfpriv->surface->offset;
+ pXvMC->sfprivs[srfno] = sfpriv;
+ pXvMC->surfaces[srfno] = pSubp->subpicture_id;
+ pXvMC->nsurfaces++;
+
+ return Success;
+}
+
+static void I915XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I915XvMCPtr pXvMC = pI830->xvmc;
+ int i;
+
+ for (i = 0; i < I915_XVMC_MAX_CONTEXTS; i++) {
+ if (pXvMC->contexts[i] == pContext->context_id) {
+ i915_unmap_xvmc_buffers(pScrn, pXvMC->ctxprivs[i]);
+ i915_free_xvmc_buffers(pScrn, pXvMC->ctxprivs[i]);
+ xfree(pXvMC->ctxprivs[i]);
+ pXvMC->ctxprivs[i] = 0;
+ pXvMC->ncontexts--;
+ pXvMC->contexts[i] = 0;
+ return;
+ }
+ }
+
+ return;
+}
+
+static void I915XvMCDestroySurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I915XvMCPtr pXvMC = pI830->xvmc;
+ int i;
+
+ for (i = 0; i < I915_XVMC_MAX_SURFACES; i++) {
+ if (pXvMC->surfaces[i] == pSurf->surface_id) {
+ i830_free_memory(pScrn, pXvMC->sfprivs[i]->surface);
+ xfree(pXvMC->sfprivs[i]);
+ pXvMC->nsurfaces--;
+ pXvMC->sfprivs[i] = 0;
+ pXvMC->surfaces[i] = 0;
+ return;
+ }
+ }
+
+ return;
+}
+
+static void I915XvMCDestroySubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I915XvMCPtr pXvMC = pI830->xvmc;
+ int i;
+
+ for (i = 0; i < I915_XVMC_MAX_SURFACES; i++) {
+ if (pXvMC->surfaces[i] == pSubp->subpicture_id) {
+ i830_free_memory(pScrn, pXvMC->sfprivs[i]->surface);
+ xfree(pXvMC->sfprivs[i]);
+ pXvMC->nsurfaces--;
+ pXvMC->sfprivs[i] = 0;
+ pXvMC->surfaces[i] = 0;
+ return;
+ }
+ }
+
+ return;
+}
+
+/*
+ *
+ */
+static int I915XvMCInterceptXvGetAttribute(ScrnInfoPtr pScrn, Atom attribute,
+ INT32 * value, pointer data)
+{
+ unsigned i;
+ I830PortPrivPtr pPriv = (I830PortPrivPtr)data;
+ I915XvMCXVPriv *vx = (I915XvMCXVPriv *)pPriv->xvmc_priv;
+
+ if (I830PTR(pScrn)->XvMCEnabled) {
+ for (i = 0; i < vx->xvAttr.numAttr; ++i) {
+ if (vx->xvAttr.attributes[i].attribute == attribute) {
+ *value = vx->xvAttr.attributes[i].value;
+ return Success;
+ }
+ }
+ }
+
+ return vx->GetPortAttribute(pScrn, attribute, value, data);
+}
+
+static int I915XvMCInterceptXvAttribute(ScrnInfoPtr pScrn, Atom attribute,
+ INT32 value, pointer data)
+{
+ unsigned i;
+ I830PortPrivPtr pPriv = (I830PortPrivPtr)data;
+ I915XvMCXVPriv *vx = (I915XvMCXVPriv *)pPriv->xvmc_priv;
+
+ if (I830PTR(pScrn)->XvMCEnabled) {
+ for (i = 0; i < vx->xvAttr.numAttr; ++i) {
+ if (vx->xvAttr.attributes[i].attribute == attribute) {
+ vx->xvAttr.attributes[i].value = value;
+ return Success;
+ }
+ }
+ }
+
+ return vx->SetPortAttribute(pScrn, attribute, value, data);
+}
+
+static int I915XvMCDisplayAttributes(ScrnInfoPtr pScrn,
+ const I915XvMCAttrHolder * ah, I830PortPrivPtr pPriv)
+{
+ I915XvMCXVPriv *vx = (I915XvMCXVPriv *) pPriv->xvmc_priv;
+ unsigned i;
+ int ret;
+
+ for (i = 0; i < ah->numAttr; ++i) {
+ ret = vx->SetPortAttribute(pScrn, ah->attributes[i].attribute,
+ ah->attributes[i].value, pPriv);
+ if (ret)
+ return ret;
+ }
+
+ return Success;
+}
+
+static int I915XvMCInterceptPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
+ short drw_x, short drw_y, short src_w,
+ short src_h, short drw_w, short drw_h,
+ int id, unsigned char *buf, short width,
+ short height, Bool sync, RegionPtr clipBoxes, pointer data,
+ DrawablePtr pDraw)
+{
+ I830PortPrivPtr pPriv = (I830PortPrivPtr)data;
+ I915XvMCXVPriv *vx = (I915XvMCXVPriv *)pPriv->xvmc_priv;
+
+ if (I830PTR(pScrn)->XvMCEnabled) {
+ if (FOURCC_XVMC == id) {
+ I830Ptr pI830 = I830PTR(pScrn);
+ I915XvMCPtr pXvMC = pI830->xvmc;
+ I915XvMCCommandBuffer *i915XvMCData = (I915XvMCCommandBuffer *)buf;
+ int i;
+
+ switch (i915XvMCData->command) {
+ case I915_XVMC_COMMAND_ATTRIBUTES:
+ if ((i915XvMCData->ctxNo | I915_XVMC_VALID) != vx->ctxDisplaying)
+ return 1;
+
+ I915XvMCDisplayAttributes(pScrn, &i915XvMCData->attrib, pPriv);
+ return 0;
+
+ case I915_XVMC_COMMAND_DISPLAY:
+ for (i = 0; i < I915_XVMC_MAX_SURFACES; i++) {
+ if (pXvMC->surfaces[i] == i915XvMCData->srfNo) {
+ i830_memory *mem = pXvMC->sfprivs[i]->surface;
+ buf = pI830 + mem->offset;
+ id = i915XvMCData->real_id;
+ break;
+ }
+ }
+
+ if (i >= I915_XVMC_MAX_SURFACES)
+ return 1;
+
+ break;
+
+ default:
+ return 0;
+ }
+ }
+ }
+
+ return vx->PutImage(pScrn, src_x, src_y, drw_x, drw_y, src_w, src_h,
+ drw_w, drw_h, id, buf, width, height, sync, clipBoxes, data, pDraw);
+}
+
+/*********************************** Public Function **************************************/
+
+/**************************************************************************
+ *
+ * I915InitMC
+ *
+ * Inputs:
+ * Screen pointer
+ *
+ * Outputs:
+ * None
+ *
+ **************************************************************************/
+void I915InitMC(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ I915XvMCPtr pXvMC = NULL;
+
+ pI830->XvMCEnabled = FALSE;
+ if (!pI830->directRenderingEnabled) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "[XvMC] Cannot use XvMC without DRI!\n");
+ return;
+ }
+
+ pXvMC = (I915XvMCPtr)calloc(1, sizeof(I915XvMC));
+ if (!pXvMC) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "[XvMC] Failure!\n");
+ return;
+ }
+
+ pI830->xvmc = pXvMC;
+ initI915XvMC(pXvMC);
+ xf86XvMCScreenInit(pScreen, 1, ppAdapt);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[XvMC] Initialized XvMC extension.\n");
+ pI830->XvMCEnabled = TRUE;
+}
+
+int I915XvMCInitXv(ScrnInfoPtr pScrn, XF86VideoAdaptorPtr XvAdapt)
+{
+ I830PortPrivPtr pPriv;
+ I915XvMCXVPriv *vx;
+ unsigned i, j;
+
+ for (j = 0; j < XvAdapt->nPorts; ++j) {
+ pPriv = (I830PortPrivPtr) XvAdapt->pPortPrivates[j].ptr;
+
+ if (NULL == (pPriv->xvmc_priv = xcalloc(1, sizeof(I915XvMCXVPriv)))) {
+ return BadAlloc;
+ }
+
+ for (i = 0; i < I915_NUM_XVMC_ATTRIBUTES; ++i) {
+ attrAtoms[i] = MAKE_ATOM(attrXvMC[i]);
+ }
+
+ vx = (I915XvMCXVPriv *) pPriv->xvmc_priv;
+
+ vx->ctxDisplaying = 0;
+ vx->xvAttr.numAttr = I915_NUM_XVMC_ATTRIBUTES;
+ vx->xvmc_port = -1;
+ vx->newAttribute = 1;
+
+ /* set up wrappers */
+ vx->GetPortAttribute = XvAdapt->GetPortAttribute;
+ vx->SetPortAttribute = XvAdapt->SetPortAttribute;
+ vx->PutImage = XvAdapt->PutImage;
+
+ XvAdapt->GetPortAttribute = I915XvMCInterceptXvGetAttribute;
+ XvAdapt->SetPortAttribute = I915XvMCInterceptXvAttribute;
+ XvAdapt->PutImage = I915XvMCInterceptPutImage;
+
+ for (i = 0; i < I915_NUM_XVMC_ATTRIBUTES; ++i) {
+ vx->xvAttr.attributes[i].attribute = attrAtoms[i];
+ vx->xvAttr.attributes[i].value = 0;
+ vx->GetPortAttribute(pScrn, attrAtoms[i],
+ &(vx->xvAttr.attributes[i].value), pPriv);
+ }
+ }
+ return Success;
+}
+
+unsigned long I915XvMCPutImageSize(ScrnInfoPtr pScrn)
+{
+ if (I830PTR(pScrn)->XvMCEnabled)
+ return sizeof(I915XvMCCommandBuffer);
+
+ return 0;
+}
diff --git a/src/i915_hwmc.h b/src/i915_hwmc.h
new file mode 100644
index 00000000..882dea0f
--- /dev/null
+++ b/src/i915_hwmc.h
@@ -0,0 +1,64 @@
+#ifndef _I915_HWMC_H
+#define _I915_HWMC_H
+
+#define FOURCC_XVMC (('C' << 24) + ('M' << 16) + ('V' << 8) + 'X')
+
+#define I915_NUM_XVMC_ATTRIBUTES 0x02
+#define I915_XVMC_VALID 0x80000000
+
+/*
+ * Commands that client submits through XvPutImage:
+ */
+
+#define I915_XVMC_COMMAND_DISPLAY 0x00
+#define I915_XVMC_COMMAND_UNDISPLAY 0x01
+#define I915_XVMC_COMMAND_ATTRIBUTES 0x02
+
+typedef struct
+{
+ INT32 attribute;
+ INT32 value;
+} I915AttrPair;
+
+typedef struct
+{
+ unsigned numAttr;
+ I915AttrPair attributes[I915_NUM_XVMC_ATTRIBUTES];
+} I915XvMCAttrHolder;
+
+typedef struct
+{
+ unsigned command;
+ unsigned ctxNo;
+ unsigned srfNo;
+ unsigned subPicNo;
+ I915XvMCAttrHolder attrib;
+ int real_id;
+ unsigned pad;
+} I915XvMCCommandBuffer;
+
+struct hwmc_buffer
+{
+ unsigned handle;
+ unsigned offset;
+ unsigned size;
+};
+
+typedef struct
+{
+ unsigned ctxno; /* XvMC private context reference number */
+ drm_context_t drmcontext;
+ struct hwmc_buffer sis; /* Static Indirect State Buffer */
+ struct hwmc_buffer msb; /* Map State Block */
+ struct hwmc_buffer ssb; /* Sampler State Block */
+ struct hwmc_buffer psp; /* Pixel Shader Program Buffer */
+ struct hwmc_buffer psc; /* Pixel Shader Constants Buffer */
+ struct hwmc_buffer corrdata;/* Correction Data Buffer */
+ unsigned sarea_size;
+ unsigned sarea_priv_offset;
+ unsigned screen;
+ unsigned depth;
+ I915XvMCAttrHolder initAttrs;
+} I915XvMCCreateContextRec;
+
+#endif /* _I915_HWMC_H */
diff --git a/src/xvmc/I915XvMC.c b/src/xvmc/I915XvMC.c
new file mode 100644
index 00000000..685eea41
--- /dev/null
+++ b/src/xvmc/I915XvMC.c
@@ -0,0 +1,3056 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+#include <assert.h>
+
+#include <pthread.h>
+#include <sys/ioctl.h>
+#include <X11/Xlibint.h>
+#include <fourcc.h>
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XvMC.h>
+#include <X11/extensions/XvMClib.h>
+#include <xf86drm.h>
+#include <drm_sarea.h>
+
+#include "I915XvMC.h"
+#include "i915_structs.h"
+#include "i915_program.h"
+#include "intel_batchbuffer.h"
+#include "xf86dri.h"
+#include "driDrawable.h"
+
+#define SAREAPTR(ctx) ((drmI830Sarea *) \
+ (((CARD8 *)(ctx)->sarea_address) + \
+ (ctx)->sarea_priv_offset))
+
+/* Lookup tables to speed common calculations */
+static unsigned mb_bytes[] = {
+ 000, 128, 128, 256, 128, 256, 256, 384, // 0
+ 128, 256, 256, 384, 256, 384, 384, 512, // 1
+ 128, 256, 256, 384, 256, 384, 384, 512, // 10
+ 256, 384, 384, 512, 384, 512, 512, 640, // 11
+ 128, 256, 256, 384, 256, 384, 384, 512, // 100
+ 256, 384, 384, 512, 384, 512, 512, 640, // 101
+ 256, 384, 384, 512, 384, 512, 512, 640, // 110
+ 384, 512, 512, 640, 512, 640, 640, 768 // 111
+};
+
+typedef union {
+ short s[4];
+ uint u[2];
+} su_t;
+
+static char I915KernelDriverName[] = "i915";
+static int error_base;
+static int event_base;
+
+static int findOverlap(unsigned width, unsigned height,
+ short *dstX, short *dstY,
+ short *srcX, short *srcY,
+ unsigned short *areaW, unsigned short *areaH)
+{
+ int w, h;
+ unsigned mWidth, mHeight;
+
+ w = *areaW;
+ h = *areaH;
+
+ if ((*dstX >= width) || (*dstY >= height))
+ return 1;
+
+ if (*dstX < 0) {
+ w += *dstX;
+ *srcX -= *dstX;
+ *dstX = 0;
+ }
+
+ if (*dstY < 0) {
+ h += *dstY;
+ *srcY -= *dstY;
+ *dstY = 0;
+ }
+
+ if ((w <= 0) || ((h <= 0)))
+ return 1;
+
+ mWidth = width - *dstX;
+ mHeight = height - *dstY;
+ *areaW = (w <= mWidth) ? w : mWidth;
+ *areaH = (h <= mHeight) ? h : mHeight;
+ return 0;
+}
+
+static void setupAttribDesc(Display * display, XvPortID port,
+ const I915XvMCAttrHolder * attrib, XvAttribute attribDesc[])
+{
+ XvAttribute *XvAttribs, *curAD;
+ int num;
+ unsigned i, j;
+
+ XLockDisplay(display);
+ XvAttribs = XvQueryPortAttributes(display, port, &num);
+ for (i = 0; i < attrib->numAttr; ++i) {
+ curAD = attribDesc + i;
+ curAD->flags = 0;
+ curAD->min_value = 0;
+ curAD->max_value = 0;
+ curAD->name = NULL;
+ for (j = 0; j < num; ++j) {
+ if (attrib->attributes[i].attribute ==
+ XInternAtom(display, XvAttribs[j].name, TRUE)) {
+ *curAD = XvAttribs[j];
+ curAD->name = strdup(XvAttribs[j].name);
+ break;
+ }
+ }
+ }
+ if (XvAttribs)
+ XFree(XvAttribs);
+ XUnlockDisplay(display);
+}
+
+static void releaseAttribDesc(int numAttr, XvAttribute attribDesc[])
+{
+ int i;
+
+ for (i = 0; i < numAttr; ++i) {
+ if (attribDesc[i].name)
+ free(attribDesc[i].name);
+ }
+}
+
+static __inline__ void renderError(void)
+{
+ printf("Invalid Macroblock Parameters found.\n");
+ return;
+}
+
+static void I915XvMCContendedLock(i915XvMCContext *pI915XvMC, unsigned flags)
+{
+ drmGetLock(pI915XvMC->fd, pI915XvMC->hHWContext, flags);
+}
+
+/* Lock the hardware and validate our state.
+ */
+static void LOCK_HARDWARE(i915XvMCContext *pI915XvMC)
+{
+ char __ret = 0;
+ pthread_mutex_lock(&pI915XvMC->ctxmutex);
+ assert(!pI915XvMC->locked);
+
+ DRM_CAS(pI915XvMC->driHwLock, pI915XvMC->hHWContext,
+ (DRM_LOCK_HELD|pI915XvMC->hHWContext), __ret);
+
+ if (__ret)
+ I915XvMCContendedLock(pI915XvMC, 0);
+
+ pI915XvMC->locked = 1;
+}
+
+/* Unlock the hardware using the global current context
+ */
+static void UNLOCK_HARDWARE(i915XvMCContext *pI915XvMC)
+{
+ pI915XvMC->locked = 0;
+ DRM_UNLOCK(pI915XvMC->fd, pI915XvMC->driHwLock,
+ pI915XvMC->hHWContext);
+ pthread_mutex_unlock(&pI915XvMC->ctxmutex);
+}
+
+static unsigned stride(int w)
+{
+ return (w + 31) & ~31;
+}
+
+static unsigned long size_y(int w, int h)
+{
+ return stride(w) * h;
+}
+
+static unsigned long size_yuv420(int w, int h)
+{
+ unsigned yPitch = stride(w);
+
+ return h * (yPitch + (yPitch >> 1));
+}
+
+static void i915_flush(i915XvMCContext *pI915XvMC)
+{
+ struct i915_mi_flush mi_flush;
+ unsigned cmd[2];
+
+ memset(&mi_flush, 0, sizeof(mi_flush));
+ mi_flush.dw0.type = CMD_MI;
+ mi_flush.dw0.opcode = OPC_MI_FLUSH;
+ mi_flush.dw0.map_cache_invalidate = 1;
+ mi_flush.dw0.render_cache_flush_inhibit = 1;
+
+ cmd[0] = *(unsigned *)((char *)&mi_flush);
+ cmd[1] = 0;
+ intelCmdIoctl(pI915XvMC, (char *)&cmd[0], sizeof(cmd));
+}
+
+/* for MC picture rendering */
+static void i915_mc_static_indirect_state_buffer(XvMCContext *context,
+ XvMCSurface *surface,
+ unsigned int picture_coding_type)
+{
+ struct i915_3dstate_buffer_info *buffer_info;
+ struct i915_3dstate_dest_buffer_variables *dest_buffer_variables;
+ struct i915_3dstate_dest_buffer_variables_mpeg *dest_buffer_variables_mpeg;
+ i915XvMCSurface *pI915Surface = (i915XvMCSurface *)surface->privData;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData;
+ unsigned w = surface->width, h = surface->height;
+
+ /* 3DSTATE_BUFFER_INFO */
+ buffer_info = (struct i915_3dstate_buffer_info *)pI915XvMC->sis.map;
+ memset(buffer_info, 0, sizeof(*buffer_info));
+ buffer_info->dw0.type = CMD_3D;
+ buffer_info->dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
+ buffer_info->dw0.length = 1;
+ buffer_info->dw1.aux_id = 0;
+ buffer_info->dw1.buffer_id = BUFFERID_COLOR_BACK;
+ buffer_info->dw1.fence_regs = 0; /* disabled */
+ buffer_info->dw1.tiled_surface = 0; /* linear */
+ buffer_info->dw1.walk = TILEWALK_XMAJOR;
+ buffer_info->dw1.pitch = stride(w);
+ buffer_info->dw2.base_address = pI915Surface->offsets[pI915Surface->curbuf];
+
+ ++buffer_info;
+ memset(buffer_info, 0, sizeof(*buffer_info));
+ buffer_info->dw0.type = CMD_3D;
+ buffer_info->dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
+ buffer_info->dw0.length = 1;
+ buffer_info->dw1.aux_id = 0;
+ buffer_info->dw1.buffer_id = BUFFERID_COLOR_AUX;
+ buffer_info->dw1.fence_regs = 0;
+ buffer_info->dw1.tiled_surface = 0;
+ buffer_info->dw1.walk = TILEWALK_XMAJOR;
+ buffer_info->dw1.pitch = stride(w) >> 1;
+ buffer_info->dw2.base_address = pI915Surface->offsets[pI915Surface->curbuf]
+ + size_y(w, h);
+
+ ++buffer_info;
+ memset(buffer_info, 0, sizeof(*buffer_info));
+ buffer_info->dw0.type = CMD_3D;
+ buffer_info->dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
+ buffer_info->dw0.length = 1;
+ buffer_info->dw1.aux_id = 1;
+ buffer_info->dw1.buffer_id = BUFFERID_COLOR_AUX;
+ buffer_info->dw1.fence_regs = 0;
+ buffer_info->dw1.tiled_surface = 0;
+ buffer_info->dw1.walk = TILEWALK_XMAJOR;
+ buffer_info->dw1.pitch = stride(w) >> 1;
+ buffer_info->dw2.base_address = pI915Surface->offsets[pI915Surface->curbuf]
+ + size_y(w, h) + (size_y(w, h) >> 2);
+
+ /* 3DSTATE_DEST_BUFFER_VARIABLES */
+ dest_buffer_variables = (struct i915_3dstate_dest_buffer_variables *)(++buffer_info);
+ memset(dest_buffer_variables, 0, sizeof(*dest_buffer_variables));
+ dest_buffer_variables->dw0.type = CMD_3D;
+ dest_buffer_variables->dw0.opcode = OPC_3DSTATE_DEST_BUFFER_VARIABLES;
+ dest_buffer_variables->dw0.length = 0;
+ dest_buffer_variables->dw1.v_ls = 0; /* FIXME */
+ dest_buffer_variables->dw1.v_ls_offset = 0;
+
+ /* 3DSTATE_DEST_BUFFER_VARIABLES_MPEG */
+ dest_buffer_variables_mpeg = (struct i915_3dstate_dest_buffer_variables_mpeg *)(++dest_buffer_variables);
+ memset(dest_buffer_variables_mpeg, 0, sizeof(*dest_buffer_variables_mpeg));
+ dest_buffer_variables_mpeg->dw0.type = CMD_3D;
+ dest_buffer_variables_mpeg->dw0.opcode = OPC_3DSTATE_DEST_BUFFER_VARIABLES_MPEG;
+ dest_buffer_variables_mpeg->dw0.length = 1;
+ dest_buffer_variables_mpeg->dw1.decoder_mode = MPEG_DECODE_MC;
+ dest_buffer_variables_mpeg->dw1.rcontrol = 0; /* for MPEG-2/MPEG-1 */
+ dest_buffer_variables_mpeg->dw1.bidir_avrg_control = 0;
+ dest_buffer_variables_mpeg->dw1.intra8 = 0; /* FIXME ? */
+ dest_buffer_variables_mpeg->dw1.tff = 0; /* FIXME */
+ dest_buffer_variables_mpeg->dw1.picture_width = w >> 4;
+ dest_buffer_variables_mpeg->dw2.picture_coding_type = picture_coding_type;
+
+ /* 3DSATE_BUFFER_INFO */
+ buffer_info = (struct i915_3dstate_buffer_info *)(++dest_buffer_variables_mpeg);
+ memset(buffer_info, 0, sizeof(*buffer_info));
+ buffer_info->dw0.type = CMD_3D;
+ buffer_info->dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
+ buffer_info->dw0.length = 1;
+ buffer_info->dw1.aux_id = 0;
+ buffer_info->dw1.buffer_id = BUFFERID_MC_INTRA_CORR;
+ buffer_info->dw1.buffer_id = BUFFERID_MC_INTRA_CORR;
+ buffer_info->dw1.aux_id = 0;
+ buffer_info->dw1.fence_regs = 0;
+ buffer_info->dw1.tiled_surface = 0;
+ buffer_info->dw1.walk = 0;
+ buffer_info->dw1.pitch = 0;
+ buffer_info->dw2.base_address = pI915XvMC->corrdata.offset;
+}
+
+static void i915_mc_map_state_buffer(XvMCContext *context,
+ XvMCSurface *target_surface,
+ XvMCSurface *past_surface,
+ XvMCSurface *future_surface)
+{
+ struct i915_3dstate_map_state *map_state;
+ struct texture_map *tm;
+ i915XvMCSurface *privTarget = NULL;
+ i915XvMCSurface *privPast = NULL;
+ i915XvMCSurface *privFuture = NULL;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData;
+ unsigned w = target_surface->width, h = target_surface->height;
+
+ privTarget = (i915XvMCSurface *)target_surface->privData;
+
+ /* P Frame Test */
+ if (!past_surface) {
+ privPast = privTarget;
+ } else {
+ if (!past_surface->privData) {
+ printf("Error, Invalid Past Surface!\n");
+ return;
+ }
+
+ privPast = (i915XvMCSurface *)past_surface->privData;
+ }
+
+ /* B Frame Test */
+ if (!future_surface) {
+ privFuture = privPast;
+ } else {
+ if (!future_surface->privData || !past_surface) {
+ printf("Error, Invalid Future Surface or No Past Surface!\n");
+ return;
+ }
+
+ privFuture = (i915XvMCSurface *)future_surface->privData;
+ }
+
+
+ /* 3DSATE_MAP_STATE: Y */
+ map_state = (struct i915_3dstate_map_state *)pI915XvMC->msb.map;
+ memset(map_state, 0, sizeof(*map_state));
+ map_state->dw0.type = CMD_3D;
+ map_state->dw0.opcode = OPC_3DSTATE_MAP_STATE;
+ map_state->dw0.retain = 1;
+ map_state->dw0.length = 6;
+ map_state->dw1.map_mask = MAP_MAP0 | MAP_MAP1;
+
+ /* texture map: Forward */
+ tm = (struct texture_map *)(++map_state);
+ memset(tm, 0, sizeof(*tm));
+ tm->tm0.v_ls_offset = 0;
+ tm->tm0.v_ls = 0;
+ tm->tm0.base_address = privPast->offsets[privPast->curbuf];
+ tm->tm1.tile_walk = TILEWALK_XMAJOR;
+ tm->tm1.tiled_surface = 0;
+ tm->tm1.utilize_fence_regs = 0;
+ tm->tm1.texel_fmt = 0;
+ tm->tm1.surface_fmt = 1;
+ tm->tm1.width = w;
+ tm->tm1.height = h;
+ tm->tm2.depth = 0;
+ tm->tm2.max_lod = 0;
+ tm->tm2.cube_face = 0;
+ tm->tm2.pitch = stride(w);
+
+ /* texture map: Backward */
+ ++tm;
+ memset(tm, 0, sizeof(*tm));
+ tm->tm0.v_ls_offset = 0;
+ tm->tm0.v_ls = 0;
+ tm->tm0.base_address = privFuture->offsets[privFuture->curbuf];
+ tm->tm1.tile_walk = TILEWALK_XMAJOR;
+ tm->tm1.tiled_surface = 0;
+ tm->tm1.utilize_fence_regs = 0;
+ tm->tm1.texel_fmt = 0;
+ tm->tm1.surface_fmt = 1;
+ tm->tm1.width = w;
+ tm->tm1.height = h;
+ tm->tm2.depth = 0;
+ tm->tm2.max_lod = 0;
+ tm->tm2.cube_face = 0;
+ tm->tm2.pitch = stride(w);
+
+ /* 3DSATE_MAP_STATE: U*/
+ map_state = (struct i915_3dstate_map_state *)(++tm);
+ memset(map_state, 0, sizeof(*map_state));
+ map_state->dw0.type = CMD_3D;
+ map_state->dw0.opcode = OPC_3DSTATE_MAP_STATE;
+ map_state->dw0.retain = 1;
+ map_state->dw0.length = 6;
+ map_state->dw1.map_mask = MAP_MAP0 | MAP_MAP1;
+
+ /* texture map: Forward */
+ tm = (struct texture_map *)(++map_state);
+ memset(tm, 0, sizeof(*tm));
+ tm->tm0.v_ls_offset = 0;
+ tm->tm0.v_ls = 0;
+ tm->tm0.base_address = privPast->offsets[privPast->curbuf] + size_y(w, h);
+ tm->tm1.tile_walk = TILEWALK_XMAJOR;
+ tm->tm1.tiled_surface = 0;
+ tm->tm1.utilize_fence_regs = 0;
+ tm->tm1.texel_fmt = 0;
+ tm->tm1.surface_fmt = 1;
+ tm->tm1.width = w >> 1;
+ tm->tm1.height = h >> 1;
+ tm->tm2.depth = 0;
+ tm->tm2.max_lod = 0;
+ tm->tm2.cube_face = 0;
+ tm->tm2.pitch = stride(w) >> 1;
+
+ /* texture map: Backward */
+ ++tm;
+ memset(tm, 0, sizeof(*tm));
+ tm->tm0.v_ls_offset = 0;
+ tm->tm0.v_ls = 0;
+ tm->tm0.base_address = privFuture->offsets[privFuture->curbuf] + size_y(w, h);
+ tm->tm1.tile_walk = TILEWALK_XMAJOR;
+ tm->tm1.tiled_surface = 0;
+ tm->tm1.utilize_fence_regs = 0;
+ tm->tm1.texel_fmt = 0;
+ tm->tm1.surface_fmt = 1;
+ tm->tm1.width = w >> 1;
+ tm->tm1.height = h >> 1;
+ tm->tm2.depth = 0;
+ tm->tm2.max_lod = 0;
+ tm->tm2.cube_face = 0;
+ tm->tm2.pitch = stride(w) >> 1;
+
+ /* 3DSATE_MAP_STATE: V */
+ map_state = (struct i915_3dstate_map_state *)(++tm);
+ memset(map_state, 0, sizeof(*map_state));
+ map_state->dw0.type = CMD_3D;
+ map_state->dw0.opcode = OPC_3DSTATE_MAP_STATE;
+ map_state->dw0.retain = 1;
+ map_state->dw0.length = 6;
+ map_state->dw1.map_mask = MAP_MAP0 | MAP_MAP1;
+
+ /* texture map: Forward */
+ tm = (struct texture_map *)(++map_state);
+ memset(tm, 0, sizeof(*tm));
+ tm->tm0.v_ls_offset = 0;
+ tm->tm0.v_ls = 0;
+ tm->tm0.base_address = privPast->offsets[privPast->curbuf] + size_y(w, h) + (size_y(w, h) >> 2);
+ tm->tm1.tile_walk = TILEWALK_XMAJOR;
+ tm->tm1.tiled_surface = 0;
+ tm->tm1.utilize_fence_regs = 0;
+ tm->tm1.texel_fmt = 0;
+ tm->tm1.surface_fmt = 1;
+ tm->tm1.width = w >> 1;
+ tm->tm1.height = h >> 1;
+ tm->tm2.depth = 0;
+ tm->tm2.max_lod = 0;
+ tm->tm2.cube_face = 0;
+ tm->tm2.pitch = stride(w) >> 1;
+
+ /* texture map: Backward */
+ ++tm;
+ memset(tm, 0, sizeof(*tm));
+ tm->tm0.v_ls_offset = 0;
+ tm->tm0.v_ls = 0;
+ tm->tm0.base_address = privFuture->offsets[privFuture->curbuf] + size_y(w, h) + (size_y(w, h) >> 2);
+ tm->tm1.tile_walk = TILEWALK_XMAJOR;
+ tm->tm1.tiled_surface = 0;
+ tm->tm1.utilize_fence_regs = 0;
+ tm->tm1.texel_fmt = 0;
+ tm->tm1.surface_fmt = 1;
+ tm->tm1.width = w >> 1;
+ tm->tm1.height = h >> 1;
+ tm->tm2.depth = 0;
+ tm->tm2.max_lod = 0;
+ tm->tm2.cube_face = 0;
+ tm->tm2.pitch = stride(w) >> 1;
+}
+
+static void i915_mc_load_indirect_buffer(XvMCContext *context)
+{
+ struct i915_3dstate_load_indirect *load_indirect;
+ sis_state *sis = NULL;
+ msb_state *msb = NULL;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData;
+ void *base = NULL;
+ unsigned size;
+
+ /* 3DSTATE_LOAD_INDIRECT */
+ size = sizeof(*load_indirect) + sizeof(*sis) + sizeof(*msb);
+ base = calloc(1, size);
+ load_indirect = (struct i915_3dstate_load_indirect *)base;
+ load_indirect->dw0.type = CMD_3D;
+ load_indirect->dw0.opcode = OPC_3DSTATE_LOAD_INDIRECT;
+ load_indirect->dw0.block_mask = BLOCK_SIS | BLOCK_MSB;
+ load_indirect->dw0.length = 3;
+
+ /* SIS */
+ sis = (sis_state *)(++load_indirect);
+ sis->dw0.valid = 1;
+ sis->dw0.buffer_address = pI915XvMC->sis.offset;
+ sis->dw1.length = 16; // 4 * 3 + 2 + 3 - 1
+
+ /* MSB */
+ msb = (msb_state *)(++sis);
+ msb->dw0.valid = 1;
+ msb->dw0.buffer_address = pI915XvMC->msb.offset;
+ msb->dw1.length = 23; // 3 * 8 - 1
+
+ intelBatchbufferData(pI915XvMC, base, size, 0);
+ free(base);
+}
+
+static void i915_mc_mpeg_set_origin(XvMCContext *context, XvMCMacroBlock *mb)
+{
+ struct i915_3dmpeg_set_origin set_origin;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData;
+
+ /* 3DMPEG_SET_ORIGIN */
+ memset(&set_origin, sizeof(set_origin), 0);
+ set_origin.dw0.type = CMD_3D;
+ set_origin.dw0.opcode = OPC_3DMPEG_SET_ORIGIN;
+ set_origin.dw0.length = 0;
+ set_origin.dw1.h_origin = mb->x;
+ set_origin.dw1.v_origin = mb->y;
+
+ intelBatchbufferData(pI915XvMC, &set_origin, sizeof(set_origin), 0);
+}
+
+static void i915_mc_mpeg_macroblock_0mv(XvMCContext *context, XvMCMacroBlock *mb)
+{
+ struct i915_3dmpeg_macroblock_0mv macroblock_0mv;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData;
+
+ /* 3DMPEG_MACROBLOCK(0mv) */
+ memset(&macroblock_0mv, sizeof(macroblock_0mv), 0);
+ macroblock_0mv.header.dw0.type = CMD_3D;
+ macroblock_0mv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK;
+ macroblock_0mv.header.dw0.length = 0;
+ macroblock_0mv.header.dw1.intra = (mb->macroblock_type & XVMC_MB_TYPE_INTRA);
+ macroblock_0mv.header.dw1.forward = 0; /* should be 0 */
+ macroblock_0mv.header.dw1.backward = 0; /* should be 0 */
+ macroblock_0mv.header.dw1.h263_4mv = 0; /* should be 0 */
+ macroblock_0mv.header.dw1.dct_type = (mb->dct_type == XVMC_DCT_TYPE_FIELD);
+
+ if (!mb->coded_block_pattern) /* FIXME */
+ macroblock_0mv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME;
+
+ macroblock_0mv.header.dw1.motion_type = mb->motion_type;
+ macroblock_0mv.header.dw1.vertical_field_select = mb->motion_vertical_field_select;
+ macroblock_0mv.header.dw1.coded_block_pattern = mb->coded_block_pattern; /* FIXME */
+ macroblock_0mv.header.dw1.skipped_macroblocks = 0; /* FIXME */
+
+ intelBatchbufferData(pI915XvMC, &macroblock_0mv, sizeof(macroblock_0mv), 0);
+}
+
+static void i915_mc_mpeg_macroblock_1fbmv(XvMCContext *context, XvMCMacroBlock *mb)
+{
+ struct i915_3dmpeg_macroblock_1fbmv macroblock_1fbmv;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData;
+
+ /* Motion Vectors */
+ su_t fmv;
+ su_t bmv;
+
+ /* 3DMPEG_MACROBLOCK(1fbmv) */
+ memset(&macroblock_1fbmv, sizeof(macroblock_1fbmv), 0);
+ macroblock_1fbmv.header.dw0.type = CMD_3D;
+ macroblock_1fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK;
+ macroblock_1fbmv.header.dw0.length = 2;
+ macroblock_1fbmv.header.dw1.intra = (mb->macroblock_type & XVMC_MB_TYPE_INTRA);
+ macroblock_1fbmv.header.dw1.forward = (mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD);
+ macroblock_1fbmv.header.dw1.backward = (mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD);
+ macroblock_1fbmv.header.dw1.h263_4mv = 0; /* should be 0 */
+ macroblock_1fbmv.header.dw1.dct_type = (mb->dct_type == XVMC_DCT_TYPE_FIELD);
+
+ if (!mb->coded_block_pattern) /* FIXME */
+ macroblock_1fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME;
+
+ macroblock_1fbmv.header.dw1.motion_type = mb->motion_type;
+ macroblock_1fbmv.header.dw1.vertical_field_select = mb->motion_vertical_field_select;
+ macroblock_1fbmv.header.dw1.coded_block_pattern = mb->coded_block_pattern; /* FIXME */
+ macroblock_1fbmv.header.dw1.skipped_macroblocks = 0; /* FIXME */
+
+ fmv.s[0] = mb->PMV[0][0][1];
+ fmv.s[1] = mb->PMV[0][0][0];
+ bmv.s[0] = mb->PMV[0][1][1];
+ bmv.s[1] = mb->PMV[0][1][0];
+
+ macroblock_1fbmv.dw2 = fmv.u[0];
+ macroblock_1fbmv.dw3 = bmv.u[0];
+
+ intelBatchbufferData(pI915XvMC, &macroblock_1fbmv, sizeof(macroblock_1fbmv), 0);
+}
+
+static void i915_mc_mpeg_macroblock_2fbmv(XvMCContext *context, XvMCMacroBlock *mb)
+{
+ struct i915_3dmpeg_macroblock_2fbmv macroblock_2fbmv;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData;
+
+ /* Motion Vectors */
+ su_t fmv;
+ su_t bmv;
+
+ /* 3DMPEG_MACROBLOCK(2fbmv) */
+ memset(&macroblock_2fbmv, sizeof(macroblock_2fbmv), 0);
+ macroblock_2fbmv.header.dw0.type = CMD_3D;
+ macroblock_2fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK;
+ macroblock_2fbmv.header.dw0.length = 2;
+ macroblock_2fbmv.header.dw1.intra = (mb->macroblock_type & XVMC_MB_TYPE_INTRA);
+ macroblock_2fbmv.header.dw1.forward = (mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD);
+ macroblock_2fbmv.header.dw1.backward = (mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD);
+ macroblock_2fbmv.header.dw1.h263_4mv = 0; /* should be 0 */
+ macroblock_2fbmv.header.dw1.dct_type = (mb->dct_type == XVMC_DCT_TYPE_FIELD);
+
+ if (!mb->coded_block_pattern) /* FIXME */
+ macroblock_2fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME;
+
+ macroblock_2fbmv.header.dw1.motion_type = mb->motion_type;
+ macroblock_2fbmv.header.dw1.vertical_field_select = mb->motion_vertical_field_select;
+ macroblock_2fbmv.header.dw1.coded_block_pattern = mb->coded_block_pattern; /* FIXME */
+ macroblock_2fbmv.header.dw1.skipped_macroblocks = 0; /* FIXME */
+
+ fmv.s[0] = mb->PMV[0][0][1];
+ fmv.s[1] = mb->PMV[0][0][0];
+ fmv.s[2] = mb->PMV[1][0][1];
+ fmv.s[3] = mb->PMV[1][0][0];
+ bmv.s[0] = mb->PMV[0][1][1];
+ bmv.s[1] = mb->PMV[0][1][0];
+ bmv.s[2] = mb->PMV[1][1][1];
+ bmv.s[3] = mb->PMV[1][1][0];
+
+ macroblock_2fbmv.dw2 = fmv.u[0];
+ macroblock_2fbmv.dw3 = bmv.u[0];
+ macroblock_2fbmv.dw4 = fmv.u[1];
+ macroblock_2fbmv.dw5 = bmv.u[1];
+
+ intelBatchbufferData(pI915XvMC, &macroblock_2fbmv, sizeof(macroblock_2fbmv), 0);
+}
+
+/* for MC context initialization */
+static void i915_mc_sampler_state_buffer(XvMCContext *context)
+{
+ struct i915_3dstate_sampler_state *sampler_state;
+ struct texture_sampler *ts;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData;
+
+ /* 3DSATE_SAMPLER_STATE */
+ sampler_state = (struct i915_3dstate_sampler_state *)pI915XvMC->ssb.map;
+ memset(sampler_state, 0, sizeof(*sampler_state));
+ sampler_state->dw0.type = CMD_3D;
+ sampler_state->dw0.opcode = OPC_3DSTATE_SAMPLER_STATE;
+ sampler_state->dw0.length = 6;
+ sampler_state->dw1.sampler_masker = SAMPLER_SAMPLER0 | SAMPLER_SAMPLER1;
+
+ /* Sampler 0 */
+ ts = (struct texture_sampler *)(++sampler_state);
+ memset(ts, 0, sizeof(*ts));
+ ts->ts0.reverse_gamma = 0;
+ ts->ts0.planar2packet = 0;
+ ts->ts0.color_conversion = 0;
+ ts->ts0.chromakey_index = 0;
+ ts->ts0.base_level = 0;
+ ts->ts0.mip_filter = MIPFILTER_NONE; /* NONE */
+ ts->ts0.mag_filter = MAPFILTER_LINEAR; /* LINEAR */
+ ts->ts0.min_filter = MAPFILTER_LINEAR; /* LINEAR */
+ ts->ts0.lod_bias = 0;
+ ts->ts0.shadow_enable = 0;
+ ts->ts0.max_anisotropy = ANISORATIO_2;
+ ts->ts0.shadow_function = PREFILTEROP_ALWAYS;
+ ts->ts1.min_lod = 0; /* Maximum Mip Level */
+ ts->ts1.kill_pixel = 0;
+ ts->ts1.keyed_texture_filter = 0;
+ ts->ts1.chromakey_enable = 0;
+ ts->ts1.tcx_control = TEXCOORDMODE_CLAMP;
+ ts->ts1.tcy_control = TEXCOORDMODE_CLAMP;
+ ts->ts1.tcz_control = TEXCOORDMODE_CLAMP;
+ ts->ts1.normalized_coor = 0;
+ ts->ts1.map_index = 0;
+ ts->ts1.east_deinterlacer = 0;
+ ts->ts2.default_color = 0;
+
+ /* Sampler 1 */
+ ++ts;
+ memset(ts, 0, sizeof(*ts));
+ ts->ts0.reverse_gamma = 0;
+ ts->ts0.planar2packet = 0;
+ ts->ts0.color_conversion = 0;
+ ts->ts0.chromakey_index = 0;
+ ts->ts0.base_level = 0;
+ ts->ts0.mip_filter = MIPFILTER_NONE; /* NONE */
+ ts->ts0.mag_filter = MAPFILTER_LINEAR; /* LINEAR */
+ ts->ts0.min_filter = MAPFILTER_LINEAR; /* LINEAR */
+ ts->ts0.lod_bias = 0;
+ ts->ts0.shadow_enable = 0;
+ ts->ts0.max_anisotropy = ANISORATIO_2;
+ ts->ts0.shadow_function = PREFILTEROP_ALWAYS;
+ ts->ts1.min_lod = 0; /* Maximum Mip Level */
+ ts->ts1.kill_pixel = 0;
+ ts->ts1.keyed_texture_filter = 0;
+ ts->ts1.chromakey_enable = 0;
+ ts->ts1.tcx_control = TEXCOORDMODE_CLAMP;
+ ts->ts1.tcy_control = TEXCOORDMODE_CLAMP;
+ ts->ts1.tcz_control = TEXCOORDMODE_CLAMP;
+ ts->ts1.normalized_coor = 0;
+ ts->ts1.map_index = 0;
+ ts->ts1.east_deinterlacer = 0;
+ ts->ts2.default_color = 0;
+}
+
+static void i915_inst_arith(unsigned *inst,
+ unsigned op,
+ unsigned dest,
+ unsigned mask,
+ unsigned saturate,
+ unsigned src0, unsigned src1, unsigned src2)
+{
+ dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
+ *(inst++) = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0));
+ *(inst++) = (A1_SRC0(src0) | A1_SRC1(src1));
+ *(inst++) = (A2_SRC1(src1) | A2_SRC2(src2));
+}
+
+static void i915_inst_decl(unsigned *inst,
+ unsigned type,
+ unsigned nr,
+ unsigned d0_flags)
+{
+ unsigned reg = UREG(type, nr);
+
+ *(inst++) = (D0_DCL | D0_DEST(reg) | d0_flags);
+ *(inst++) = D1_MBZ;
+ *(inst++) = D2_MBZ;
+}
+
+static void i915_inst_texld(unsigned *inst,
+ unsigned op,
+ unsigned dest,
+ unsigned sampler,
+ unsigned coord)
+{
+ dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
+ *(inst++) = (op | T0_DEST(dest) | T0_SAMPLER(sampler));
+ *(inst++) = T1_ADDRESS_REG(coord);
+ *(inst++) = T2_MBZ;
+}
+
+static void i915_mc_pixel_shader_program_buffer(XvMCContext *context)
+{
+ struct i915_3dstate_pixel_shader_program *pixel_shader_program;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData;
+ unsigned *inst;
+ unsigned dest, src0, src1, src2;
+
+ /* Shader 0 */
+ pixel_shader_program = (struct i915_3dstate_pixel_shader_program *)pI915XvMC->psp.map;
+ memset(pixel_shader_program, 0, sizeof(*pixel_shader_program));
+ pixel_shader_program->dw0.type = CMD_3D;
+ pixel_shader_program->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
+ pixel_shader_program->dw0.retain = 1;
+ pixel_shader_program->dw0.length = 2;
+ inst = (unsigned *)(++pixel_shader_program);
+ dest = UREG(REG_TYPE_OC, 0);
+ src0 = UREG(REG_TYPE_CONST, 0);
+ src1 = 0;
+ src2 = 0;
+ i915_inst_arith(inst, A0_MOV, dest, A0_DEST_CHANNEL_ALL,
+ A0_DEST_SATURATE, src0, src1, src2);
+ inst += 3;
+
+ /* Shader 1 */
+ pixel_shader_program = (struct i915_3dstate_pixel_shader_program *)inst;
+ memset(pixel_shader_program, 0, sizeof(*pixel_shader_program));
+ pixel_shader_program->dw0.type = CMD_3D;
+ pixel_shader_program->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
+ pixel_shader_program->dw0.retain = 1;
+ pixel_shader_program->dw0.length = 14;
+ inst = (unsigned *)(++pixel_shader_program);
+ i915_inst_decl(inst, REG_TYPE_T, T_TEX0, D0_CHANNEL_XY);
+ inst += 3;
+ i915_inst_decl(inst, REG_TYPE_T, T_TEX1, D0_CHANNEL_XY);
+ inst += 3;
+ i915_inst_decl(inst, REG_TYPE_S, 0, D0_SAMPLE_TYPE_2D);
+ inst += 3;
+ dest = UREG(REG_TYPE_R, 0);
+ src0 = UREG(REG_TYPE_S, 0); /* SAMPLER */
+ src1 = UREG(REG_TYPE_T, 0); /* COORD */
+ i915_inst_texld(inst, T0_TEXLD, dest, src0, src1);
+ inst += 3;
+ dest = UREG(REG_TYPE_OC, 0);
+ src0 = UREG(REG_TYPE_S, 0);
+ src1 = src2 = 0;
+ i915_inst_arith(inst, A0_MOV, dest, A0_DEST_CHANNEL_ALL,
+ A0_DEST_SATURATE, src0, src1, src2);
+ inst += 3;
+
+ /* Shader 2 */
+ pixel_shader_program = (struct i915_3dstate_pixel_shader_program *)inst;
+ memset(pixel_shader_program, 0, sizeof(*pixel_shader_program));
+ pixel_shader_program->dw0.type = CMD_3D;
+ pixel_shader_program->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
+ pixel_shader_program->dw0.retain = 1;
+ pixel_shader_program->dw0.length = 14;
+ inst = (unsigned *)(++pixel_shader_program);
+ i915_inst_decl(inst, REG_TYPE_T, T_TEX2, D0_CHANNEL_XY);
+ inst += 3;
+ i915_inst_decl(inst, REG_TYPE_T, T_TEX3, D0_CHANNEL_XY);
+ inst += 3;
+ i915_inst_decl(inst, REG_TYPE_S, 1, D0_SAMPLE_TYPE_2D);
+ inst += 3;
+ dest = UREG(REG_TYPE_R, 0);
+ src0 = UREG(REG_TYPE_S, 1); /* SAMPLER */
+ src1 = UREG(REG_TYPE_T, 2); /* COORD */
+ i915_inst_texld(inst, T0_TEXLD, dest, src0, src1);
+ inst += 3;
+ dest = UREG(REG_TYPE_OC, 0);
+ src0 = UREG(REG_TYPE_S, 0);
+ src1 = src2 = 0;
+ i915_inst_arith(inst, A0_MOV, dest, A0_DEST_CHANNEL_ALL,
+ A0_DEST_SATURATE, src0, src1, src2);
+ inst += 3;
+
+ /* Shader 3 */
+ pixel_shader_program = (struct i915_3dstate_pixel_shader_program *)inst;
+ memset(pixel_shader_program, 0, sizeof(*pixel_shader_program));
+ pixel_shader_program->dw0.type = CMD_3D;
+ pixel_shader_program->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
+ pixel_shader_program->dw0.retain = 1;
+ pixel_shader_program->dw0.length = 29;
+ inst = (unsigned *)(++pixel_shader_program);
+ i915_inst_decl(inst, REG_TYPE_T, T_TEX0, D0_CHANNEL_XY);
+ inst += 3;
+ i915_inst_decl(inst, REG_TYPE_T, T_TEX1, D0_CHANNEL_XY);
+ inst += 3;
+ i915_inst_decl(inst, REG_TYPE_T, T_TEX2, D0_CHANNEL_XY);
+ inst += 3;
+ i915_inst_decl(inst, REG_TYPE_T, T_TEX3, D0_CHANNEL_XY);
+ inst += 3;
+ i915_inst_decl(inst, REG_TYPE_S, 0, D0_SAMPLE_TYPE_2D);
+ inst += 3;
+ i915_inst_decl(inst, REG_TYPE_S, 1, D0_SAMPLE_TYPE_2D);
+ inst += 3;
+ dest = UREG(REG_TYPE_R, 0);
+ src0 = UREG(REG_TYPE_S, 0); /* SAMPLER */
+ src1 = UREG(REG_TYPE_T, 0); /* COORD */
+ i915_inst_texld(inst, T0_TEXLD, dest, src0, src1);
+ inst += 3;
+ dest = UREG(REG_TYPE_R, 1);
+ src0 = UREG(REG_TYPE_S, 1); /* SAMPLER */
+ src1 = UREG(REG_TYPE_T, 2); /* COORD */
+ i915_inst_texld(inst, T0_TEXLD, dest, src0, src1);
+ inst += 3;
+ dest = UREG(REG_TYPE_R, 0);
+ src0 = UREG(REG_TYPE_R, 0);
+ src1 = UREG(REG_TYPE_R, 1);
+ src2 = 0;
+ i915_inst_arith(inst, A0_ADD, dest, A0_DEST_CHANNEL_ALL,
+ A0_DEST_SATURATE, src0, src1, src2);
+ inst += 3;
+ dest = UREG(REG_TYPE_OC, 0);
+ src0 = UREG(REG_TYPE_R, 0);
+ src1 = UREG(REG_TYPE_OC, 0);
+ src2 = 0;
+ i915_inst_arith(inst, A0_MUL, dest, A0_DEST_CHANNEL_ALL,
+ A0_DEST_SATURATE, src0, src1, src2);
+ inst += 3;
+}
+
+static void i915_mc_pixel_shader_constants_buffer(XvMCContext *context)
+{
+ struct i915_3dstate_pixel_shader_constants *pixel_shader_constants;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData;
+ float *value;
+
+ pixel_shader_constants = (struct i915_3dstate_pixel_shader_constants *)pI915XvMC->psc.map;
+ memset(pixel_shader_constants, 0, sizeof(*pixel_shader_constants));
+ pixel_shader_constants->dw0.type = CMD_3D;
+ pixel_shader_constants->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_CONSTANTS;
+ pixel_shader_constants->dw0.length = 4;
+ pixel_shader_constants->dw1.reg_mask = REG_CR0;
+ value = (float *)(++pixel_shader_constants);
+ *(value++) = 0.5;
+ *(value++) = 0.5;
+ *(value++) = 0.5;
+ *(value++) = 0.5;
+}
+
+static void i915_mc_one_time_state_initialization(XvMCContext *context)
+{
+ struct i915_3dstate_load_state_immediate_1 *load_state_immediate_1 = NULL;
+ struct s3_dword *s3 = NULL;
+ struct s6_dword *s6 = NULL;
+ struct i915_3dstate_load_indirect *load_indirect = NULL;
+ dis_state *dis = NULL;
+ ssb_state *ssb = NULL;
+ psp_state *psp = NULL;
+ psc_state *psc = NULL;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData;
+ unsigned size;
+ void *base = NULL;
+
+ /* 3DSTATE_LOAD_STATE_IMMEDIATE_1 */
+ size = sizeof(*load_state_immediate_1) + sizeof(*s3) + sizeof(*s6);
+ base = calloc(1, size);
+ load_state_immediate_1 = (struct i915_3dstate_load_state_immediate_1 *)base;
+ load_state_immediate_1->dw0.type = CMD_3D;
+ load_state_immediate_1->dw0.opcode = OPC_3DSTATE_LOAD_STATE_IMMEDIATE_1;
+ load_state_immediate_1->dw0.load_s3 = 1;
+ load_state_immediate_1->dw0.load_s6 = 1;
+ load_state_immediate_1->dw0.length = 1;
+
+ s3 = (struct s3_dword *)(++load_state_immediate_1);
+ s3->set0_pcd = 1;
+ s3->set1_pcd = 1;
+ s3->set2_pcd = 1;
+ s3->set3_pcd = 1;
+ s3->set4_pcd = 1;
+ s3->set5_pcd = 1;
+ s3->set6_pcd = 1;
+ s3->set7_pcd = 1;
+
+ s6 = (struct s6_dword *)(++s3);
+ s6->alpha_test_enable = 0;
+ s6->alpha_test_function = 0;
+ s6->alpha_reference_value = 0;
+ s6->depth_test_enable = 1;
+ s6->depth_test_function = 0;
+ s6->color_buffer_blend = 0;
+ s6->color_blend_function = 0;
+ s6->src_blend_factor = 1;
+ s6->dest_blend_factor = 1;
+ s6->depth_buffer_write = 0;
+ s6->color_buffer_write = 1;
+ s6->triangle_pv = 0;
+
+ intelBatchbufferData(pI915XvMC, base, size, 0);
+ free(base);
+
+ /* 3DSTATE_LOAD_INDIRECT */
+ size = sizeof(*load_indirect) + sizeof(*dis) + sizeof(*ssb) + sizeof(*psp) + sizeof(*psc);
+ base = calloc(1, size);
+ load_indirect = (struct i915_3dstate_load_indirect *)base;
+ load_indirect->dw0.type = CMD_3D;
+ load_indirect->dw0.opcode = OPC_3DSTATE_LOAD_INDIRECT;
+ load_indirect->dw0.block_mask = BLOCK_DIS | BLOCK_SSB | BLOCK_PSP | BLOCK_PSC;
+ load_indirect->dw0.length = 6;
+
+ /* DIS */
+ dis = (dis_state *)(++load_indirect);
+ dis->dw0.valid = 0;
+ dis->dw0.reset = 0;
+ dis->dw0.buffer_address = 0;
+
+ /* SSB */
+ ssb = (ssb_state *)(++dis);
+ ssb->dw0.valid = 1;
+ ssb->dw0.buffer_address = pI915XvMC->ssb.offset;
+ ssb->dw1.length = 8;
+
+ /* PSP */
+ psp = (psp_state *)(++ssb);
+ psp->dw0.valid = 1;
+ psp->dw0.buffer_address = pI915XvMC->psp.offset;
+ psp->dw1.length = 67; // 4 + 16 + 16 + 31
+
+ /* PSC */
+ psc = (psc_state *)(++psp);
+ psc->dw0.valid = 1;
+ psc->dw0.buffer_address = pI915XvMC->psc.offset;
+ psc->dw1.length = 6;
+
+ intelBatchbufferData(pI915XvMC, base, size, 0);
+ free(base);
+}
+
+static int i915_xvmc_map_buffers(i915XvMCContext *pI915XvMC)
+{
+ if (drmMap(pI915XvMC->fd,
+ pI915XvMC->sis.handle,
+ pI915XvMC->sis.size,
+ (drmAddress *)pI915XvMC->sis.map) != 0) {
+ return -1;
+ }
+
+ if (drmMap(pI915XvMC->fd,
+ pI915XvMC->msb.handle,
+ pI915XvMC->msb.size,
+ (drmAddress *)pI915XvMC->msb.map) != 0) {
+ return -1;
+ }
+
+ if (drmMap(pI915XvMC->fd,
+ pI915XvMC->ssb.handle,
+ pI915XvMC->ssb.size,
+ (drmAddress *)pI915XvMC->ssb.map) != 0) {
+ return -1;
+ }
+
+ if (drmMap(pI915XvMC->fd,
+ pI915XvMC->psp.handle,
+ pI915XvMC->psp.size,
+ (drmAddress *)pI915XvMC->psp.map) != 0) {
+ return -1;
+ }
+
+ if (drmMap(pI915XvMC->fd,
+ pI915XvMC->psc.handle,
+ pI915XvMC->psc.size,
+ (drmAddress *)pI915XvMC->psc.map) != 0) {
+ return -1;
+ }
+
+ if (drmMap(pI915XvMC->fd,
+ pI915XvMC->corrdata.handle,
+ pI915XvMC->corrdata.size,
+ (drmAddress *)pI915XvMC->corrdata.map) != 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static void i915_xvmc_unmap_buffers(i915XvMCContext *pI915XvMC)
+{
+ if (pI915XvMC->sis.map) {
+ drmUnmap(pI915XvMC->sis.map, pI915XvMC->sis.size);
+ pI915XvMC->sis.map = NULL;
+ }
+
+ if (pI915XvMC->msb.map) {
+ drmUnmap(pI915XvMC->msb.map, pI915XvMC->msb.size);
+ pI915XvMC->msb.map = NULL;
+ }
+
+ if (pI915XvMC->ssb.map) {
+ drmUnmap(pI915XvMC->ssb.map, pI915XvMC->ssb.size);
+ pI915XvMC->ssb.map = NULL;
+ }
+
+ if (pI915XvMC->psp.map) {
+ drmUnmap(pI915XvMC->psp.map, pI915XvMC->psp.size);
+ pI915XvMC->psp.map = NULL;
+ }
+
+ if (pI915XvMC->psc.map) {
+ drmUnmap(pI915XvMC->psc.map, pI915XvMC->psc.size);
+ pI915XvMC->psc.map = NULL;
+ }
+
+ if (pI915XvMC->corrdata.map) {
+ drmUnmap(pI915XvMC->corrdata.map, pI915XvMC->corrdata.size);
+ pI915XvMC->corrdata.map = NULL;
+ }
+}
+
+/*
+ * Video post processing
+ */
+static void i915_yuv2rgb_map_state_buffer(XvMCSurface *target_surface)
+{
+ struct i915_3dstate_map_state *map_state;
+ struct texture_map *tm;
+ i915XvMCSurface *privTarget = NULL;
+ i915XvMCContext *pI915XvMC = NULL;
+ unsigned w = target_surface->width, h = target_surface->height;
+
+ privTarget = (i915XvMCSurface *)target_surface->privData;
+ pI915XvMC = (i915XvMCContext *)privTarget->privContext;
+ /* 3DSATE_MAP_STATE */
+ map_state = (struct i915_3dstate_map_state *)pI915XvMC->msb.map;
+ memset(map_state, 0, sizeof(*map_state));
+ map_state->dw0.type = CMD_3D;
+ map_state->dw0.opcode = OPC_3DSTATE_MAP_STATE;
+ map_state->dw0.retain = 0;
+ map_state->dw0.length = 9;
+ map_state->dw1.map_mask = MAP_MAP0 | MAP_MAP1 | MAP_MAP2;
+
+ /* texture map 0: V Plane */
+ tm = (struct texture_map *)(++map_state);
+ memset(tm, 0, sizeof(*tm));
+ tm->tm0.v_ls_offset = 0;
+ tm->tm0.v_ls = 0;
+ tm->tm0.base_address = privTarget->offsets[privTarget->curbuf] + size_y(w, h);
+ tm->tm1.tile_walk = TILEWALK_XMAJOR;
+ tm->tm1.tiled_surface = 0;
+ tm->tm1.utilize_fence_regs = 1;
+ tm->tm1.texel_fmt = 0;
+ tm->tm1.surface_fmt = 1;
+ tm->tm1.width = (w >> 1) - 1;
+ tm->tm1.height = (h >> 1) - 1;
+ tm->tm2.depth = 0;
+ tm->tm2.max_lod = 0;
+ tm->tm2.cube_face = 0;
+ tm->tm2.pitch = (stride(w) >> 1) - 1;
+
+ /* texture map 1: Y Plane */
+ ++tm;
+ memset(tm, 0, sizeof(*tm));
+ tm->tm0.v_ls_offset = 0;
+ tm->tm0.v_ls = 0;
+ tm->tm0.base_address = privTarget->offsets[privTarget->curbuf];
+ tm->tm1.tile_walk = TILEWALK_XMAJOR;
+ tm->tm1.tiled_surface = 0;
+ tm->tm1.utilize_fence_regs = 1;
+ tm->tm1.texel_fmt = 0;
+ tm->tm1.surface_fmt = 1;
+ tm->tm1.width = w - 1;
+ tm->tm1.height = h - 1;
+ tm->tm2.depth = 0;
+ tm->tm2.max_lod = 0;
+ tm->tm2.cube_face = 0;
+ tm->tm2.pitch = stride(w) - 1;
+
+ /* texture map 2: U Plane */
+ ++tm;
+ memset(tm, 0, sizeof(*tm));
+ tm->tm0.v_ls_offset = 0;
+ tm->tm0.v_ls = 0;
+ tm->tm0.base_address = privTarget->offsets[privTarget->curbuf] + size_y(w, h) + (size_y(w, h) >> 2);
+ tm->tm1.tile_walk = TILEWALK_XMAJOR;
+ tm->tm1.tiled_surface = 0;
+ tm->tm1.utilize_fence_regs = 1;
+ tm->tm1.texel_fmt = 0;
+ tm->tm1.surface_fmt = 1;
+ tm->tm1.width = (w >> 1) - 1;
+ tm->tm1.height = (h >> 1) - 1;
+ tm->tm2.depth = 0;
+ tm->tm2.max_lod = 0;
+ tm->tm2.cube_face = 0;
+ tm->tm2.pitch = (stride(w) >> 1) - 1;
+}
+
+static void i915_yuv2rgb_sampler_state_buffer(XvMCSurface *surface)
+{
+ struct i915_3dstate_sampler_state *sampler_state;
+ struct texture_sampler *ts;
+ i915XvMCSurface *privSurface = (i915XvMCSurface *)surface->privData;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *)privSurface->privContext;
+
+ /* 3DSATE_SAMPLER_STATE */
+ sampler_state = (struct i915_3dstate_sampler_state *)pI915XvMC->ssb.map;
+ memset(sampler_state, 0, sizeof(*sampler_state));
+ sampler_state->dw0.type = CMD_3D;
+ sampler_state->dw0.opcode = OPC_3DSTATE_SAMPLER_STATE;
+ sampler_state->dw0.length = 9;
+ sampler_state->dw1.sampler_masker = SAMPLER_SAMPLER0 | SAMPLER_SAMPLER1 | SAMPLER_SAMPLER2;
+
+ /* Sampler 0 */
+ ts = (struct texture_sampler *)(++sampler_state);
+ memset(ts, 0, sizeof(*ts));
+ ts->ts0.reverse_gamma = 0;
+ ts->ts0.planar2packet = 1;
+ ts->ts0.color_conversion = 1;
+ ts->ts0.chromakey_index = 0;
+ ts->ts0.base_level = 0;
+ ts->ts0.mip_filter = MIPFILTER_NONE; /* NONE */
+ ts->ts0.mag_filter = MAPFILTER_LINEAR; /* LINEAR */
+ ts->ts0.min_filter = MAPFILTER_LINEAR; /* LINEAR */
+ ts->ts0.lod_bias = 0;
+ ts->ts0.shadow_enable = 0;
+ ts->ts0.max_anisotropy = ANISORATIO_2;
+ ts->ts0.shadow_function = PREFILTEROP_ALWAYS;
+ ts->ts1.min_lod = 0; /* Maximum Mip Level */
+ ts->ts1.kill_pixel = 0;
+ ts->ts1.keyed_texture_filter = 0;
+ ts->ts1.chromakey_enable = 0;
+ ts->ts1.tcx_control = TEXCOORDMODE_CLAMP;
+ ts->ts1.tcy_control = TEXCOORDMODE_CLAMP;
+ ts->ts1.tcz_control = TEXCOORDMODE_CLAMP;
+ ts->ts1.normalized_coor = 0;
+ ts->ts1.map_index = 0;
+ ts->ts1.east_deinterlacer = 0;
+ ts->ts2.default_color = 0;
+
+ /* Sampler 1 */
+ ++ts;
+ memset(ts, 0, sizeof(*ts));
+ ts->ts0.reverse_gamma = 0;
+ ts->ts0.planar2packet = 1;
+ ts->ts0.color_conversion = 1;
+ ts->ts0.chromakey_index = 0;
+ ts->ts0.base_level = 0;
+ ts->ts0.mip_filter = MIPFILTER_NONE; /* NONE */
+ ts->ts0.mag_filter = MAPFILTER_LINEAR; /* LINEAR */
+ ts->ts0.min_filter = MAPFILTER_LINEAR; /* LINEAR */
+ ts->ts0.lod_bias = 0;
+ ts->ts0.shadow_enable = 0;
+ ts->ts0.max_anisotropy = ANISORATIO_2;
+ ts->ts0.shadow_function = PREFILTEROP_ALWAYS;
+ ts->ts1.min_lod = 0; /* Maximum Mip Level */
+ ts->ts1.kill_pixel = 0;
+ ts->ts1.keyed_texture_filter = 0;
+ ts->ts1.chromakey_enable = 0;
+ ts->ts1.tcx_control = TEXCOORDMODE_CLAMP;
+ ts->ts1.tcy_control = TEXCOORDMODE_CLAMP;
+ ts->ts1.tcz_control = TEXCOORDMODE_CLAMP;
+ ts->ts1.normalized_coor = 0;
+ ts->ts1.map_index = 0;
+ ts->ts1.east_deinterlacer = 0;
+ ts->ts2.default_color = 0;
+
+ /* Sampler 2 */
+ ++ts;
+ memset(ts, 0, sizeof(*ts));
+ ts->ts0.reverse_gamma = 0;
+ ts->ts0.planar2packet = 1;
+ ts->ts0.color_conversion = 1;
+ ts->ts0.chromakey_index = 0;
+ ts->ts0.base_level = 0;
+ ts->ts0.mip_filter = MIPFILTER_NONE; /* NONE */
+ ts->ts0.mag_filter = MAPFILTER_LINEAR; /* LINEAR */
+ ts->ts0.min_filter = MAPFILTER_LINEAR; /* LINEAR */
+ ts->ts0.lod_bias = 0;
+ ts->ts0.shadow_enable = 0;
+ ts->ts0.max_anisotropy = ANISORATIO_2;
+ ts->ts0.shadow_function = PREFILTEROP_ALWAYS;
+ ts->ts1.min_lod = 0; /* Maximum Mip Level */
+ ts->ts1.kill_pixel = 0;
+ ts->ts1.keyed_texture_filter = 0;
+ ts->ts1.chromakey_enable = 0;
+ ts->ts1.tcx_control = TEXCOORDMODE_CLAMP;
+ ts->ts1.tcy_control = TEXCOORDMODE_CLAMP;
+ ts->ts1.tcz_control = TEXCOORDMODE_CLAMP;
+ ts->ts1.normalized_coor = 0;
+ ts->ts1.map_index = 0;
+ ts->ts1.east_deinterlacer = 0;
+ ts->ts2.default_color = 0;
+}
+
+static void i915_yuv2rgb_static_indirect_state_buffer(XvMCSurface *surface,
+ unsigned dstaddr,
+ int dstpitch)
+{
+ struct i915_3dstate_buffer_info *buffer_info;
+ struct i915_3dstate_dest_buffer_variables *dest_buffer_variables;
+ i915XvMCSurface *privSurface = (i915XvMCSurface *)surface->privData;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *)privSurface->privContext;
+
+ /* 3DSTATE_BUFFER_INFO */
+ buffer_info = (struct i915_3dstate_buffer_info *)pI915XvMC->sis.map;
+ memset(buffer_info, 0, sizeof(*buffer_info));
+ buffer_info->dw0.type = CMD_3D;
+ buffer_info->dw0.opcode = OPC_3DSTATE_BUFFER_INFO;
+ buffer_info->dw0.length = 1;
+ buffer_info->dw1.aux_id = 0;
+ buffer_info->dw1.buffer_id = BUFFERID_COLOR_BACK;
+ buffer_info->dw1.fence_regs = 1;
+ buffer_info->dw1.tiled_surface = 0; /* linear */
+ buffer_info->dw1.walk = TILEWALK_XMAJOR;
+ buffer_info->dw1.pitch = dstpitch;
+ buffer_info->dw2.base_address = dstaddr;
+
+ /* 3DSTATE_DEST_BUFFER_VARIABLES */
+ dest_buffer_variables = (struct i915_3dstate_dest_buffer_variables *)(++buffer_info);
+ memset(dest_buffer_variables, 0, sizeof(*dest_buffer_variables));
+ dest_buffer_variables->dw0.type = CMD_3D;
+ dest_buffer_variables->dw0.opcode = OPC_3DSTATE_DEST_BUFFER_VARIABLES;
+ dest_buffer_variables->dw0.length = 0;
+ dest_buffer_variables->dw1.dest_v_bias = 8; /* FIXME 0x1000 .5 ??? */
+ dest_buffer_variables->dw1.dest_h_bias = 8;
+ dest_buffer_variables->dw1.color_fmt = COLORBUFFER_A8R8G8B8; /* FIXME */
+}
+
+static void i915_yuv2rgb_pixel_shader_program_buffer(XvMCSurface *surface)
+{
+ struct i915_3dstate_pixel_shader_program *pixel_shader_program;
+ i915XvMCSurface *privSurface = (i915XvMCSurface *)surface->privData;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *)privSurface->privContext;
+ unsigned *inst;
+ unsigned dest, src0, src1;
+
+ /* Shader 0 */
+ pixel_shader_program = (struct i915_3dstate_pixel_shader_program *)pI915XvMC->psp.map;
+ memset(pixel_shader_program, 0, sizeof(*pixel_shader_program));
+ pixel_shader_program->dw0.type = CMD_3D;
+ pixel_shader_program->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM;
+ pixel_shader_program->dw0.retain = 0;
+ pixel_shader_program->dw0.length = 23;
+ inst = (unsigned *)(++pixel_shader_program);
+ i915_inst_decl(inst, REG_TYPE_T, T_TEX0, D0_CHANNEL_XY);
+ inst += 3;
+ i915_inst_decl(inst, REG_TYPE_T, T_TEX1, D0_CHANNEL_XY);
+ inst += 3;
+ i915_inst_decl(inst, REG_TYPE_S, 0, D0_SAMPLE_TYPE_2D);
+ inst += 3;
+ i915_inst_decl(inst, REG_TYPE_S, 1, D0_SAMPLE_TYPE_2D);
+ inst += 3;
+ i915_inst_decl(inst, REG_TYPE_S, 2, D0_SAMPLE_TYPE_2D);
+ inst += 3;
+ dest = UREG(REG_TYPE_R, 0);
+ src0 = UREG(REG_TYPE_S, 0); /* SAMPLER */
+ src1 = UREG(REG_TYPE_T, 1); /* COORD */
+ i915_inst_texld(inst, T0_TEXLD, dest, src0, src1);
+ inst += 3;
+ dest = UREG(REG_TYPE_R, 0);
+ src0 = UREG(REG_TYPE_S, 1); /* SAMPLER */
+ src1 = UREG(REG_TYPE_T, 0); /* COORD */
+ i915_inst_texld(inst, T0_TEXLD, dest, src0, src1);
+ inst += 3;
+ dest = UREG(REG_TYPE_OC, 0);
+ src0 = UREG(REG_TYPE_S, 2);
+ src1 = UREG(REG_TYPE_T, 1);
+ i915_inst_texld(inst, T0_TEXLD, dest, src0, src1);
+}
+
+static void i915_yuv2rgb_proc(XvMCSurface *surface)
+{
+ i915XvMCSurface *privSurface = (i915XvMCSurface *)surface->privData;
+ i915XvMCContext *pI915XvMC = (i915XvMCContext *)privSurface->privContext;
+ struct i915_3dstate_load_state_immediate_1 *load_state_immediate_1 = NULL;
+ struct s2_dword *s2 = NULL;
+ struct s3_dword *s3 = NULL;
+ struct s4_dword *s4 = NULL;
+ struct s5_dword *s5 = NULL;
+ struct s6_dword *s6 = NULL;
+ struct s7_dword *s7 = NULL;
+ struct i915_3dstate_scissor_rectangle scissor_rectangle;
+ struct i915_3dstate_load_indirect *load_indirect = NULL;
+ sis_state *sis = NULL;
+ ssb_state *ssb = NULL;
+ msb_state *msb = NULL;
+ psp_state *psp = NULL;
+ struct i915_3dprimitive *_3dprimitive = NULL;
+ struct vertex_data *vd = NULL;
+ unsigned size;
+ void *base = NULL;
+
+ /* 3DSTATE_LOAD_STATE_IMMEDIATE_1 */
+ size = sizeof(*load_state_immediate_1) + sizeof(*s2) + sizeof(*s3) +
+ sizeof(*s4) + sizeof(*s5) + sizeof(*s6) + sizeof(*s7);
+ base = calloc(1, size);
+ load_state_immediate_1 = (struct i915_3dstate_load_state_immediate_1 *)base;
+ load_state_immediate_1->dw0.type = CMD_3D;
+ load_state_immediate_1->dw0.opcode = OPC_3DSTATE_LOAD_STATE_IMMEDIATE_1;
+ load_state_immediate_1->dw0.load_s2 = 1;
+ load_state_immediate_1->dw0.load_s3 = 1;
+ load_state_immediate_1->dw0.load_s4 = 1;
+ load_state_immediate_1->dw0.load_s5 = 1;
+ load_state_immediate_1->dw0.load_s6 = 1;
+ load_state_immediate_1->dw0.load_s7 = 1;
+ load_state_immediate_1->dw0.length = 5;
+
+ s2 = (struct s2_dword *)(++load_state_immediate_1);
+ s2->set0_texcoord_fmt = TEXCOORDFMT_2FP;
+ s2->set1_texcoord_fmt = TEXCOORDFMT_2FP;
+ s2->set2_texcoord_fmt = TEXCOORDFMT_NOT_PRESENT;
+ s2->set3_texcoord_fmt = TEXCOORDFMT_NOT_PRESENT;
+ s2->set4_texcoord_fmt = TEXCOORDFMT_NOT_PRESENT;
+ s2->set5_texcoord_fmt = TEXCOORDFMT_NOT_PRESENT;
+ s2->set6_texcoord_fmt = TEXCOORDFMT_NOT_PRESENT;
+ s2->set7_texcoord_fmt = TEXCOORDFMT_NOT_PRESENT;
+
+ s3 = (struct s3_dword *)(++s2);
+ s4 = (struct s4_dword *)(++s3);
+ s4->position_mask = VERTEXHAS_XY;
+ s4->cull_mode = CULLMODE_NONE;
+ s4->color_shade_mode = SHADEMODE_FLAT;
+ s4->specular_shade_mode = SHADEMODE_FLAT;
+ s4->fog_shade_mode = SHADEMODE_FLAT;
+ s4->alpha_shade_mode = SHADEMODE_FLAT;
+ s4->line_width = 0x2; /* FIXME: 1.0??? */
+ s4->point_width = 0x1;
+
+ s5 = (struct s5_dword *)(++s4);
+ s6 = (struct s6_dword *)(++s5);
+ s6->src_blend_factor = 1;
+ s6->dest_blend_factor = 1;
+ s6->color_buffer_write = 1;
+
+ s7 = (struct s7_dword *)(++s6);
+ intelBatchbufferData(pI915XvMC, base, size, 0);
+ free(base);
+
+ /* 3DSTATE_3DSTATE_SCISSOR_RECTANGLE */
+ scissor_rectangle.dw0.type = CMD_3D;
+ scissor_rectangle.dw0.opcode = OPC_3DSTATE_SCISSOR_RECTANGLE;
+ scissor_rectangle.dw0.length = 1;
+ scissor_rectangle.dw1.min_x = 0;
+ scissor_rectangle.dw1.min_y = 0;
+ scissor_rectangle.dw2.max_x = 2047;
+ scissor_rectangle.dw2.max_y = 2047;
+ intelBatchbufferData(pI915XvMC, &scissor_rectangle, sizeof(scissor_rectangle), 0);
+
+ /* 3DSTATE_LOAD_INDIRECT */
+ size = sizeof(*load_indirect) + sizeof(*sis) + sizeof(*ssb) + sizeof(*msb) + sizeof(*psp);
+ base = calloc(1, size);
+ load_indirect = (struct i915_3dstate_load_indirect *)base;
+ load_indirect->dw0.type = CMD_3D;
+ load_indirect->dw0.opcode = OPC_3DSTATE_LOAD_INDIRECT;
+ load_indirect->dw0.block_mask = BLOCK_SIS | BLOCK_SSB | BLOCK_MSB | BLOCK_PSP;
+ load_indirect->dw0.length = 7;
+
+ /* SIS */
+ sis = (sis_state *)(++load_indirect);
+ sis->dw0.valid = 1;
+ sis->dw0.buffer_address = pI915XvMC->sis.offset;
+ sis->dw1.length = ((sizeof(struct i915_3dstate_buffer_info) +
+ sizeof(struct i915_3dstate_dest_buffer_variables)) >> 2) - 1;
+
+ /* SSB */
+ ssb = (ssb_state *)(++sis);
+ ssb->dw0.valid = 1;
+ ssb->dw0.buffer_address = pI915XvMC->ssb.offset;
+ ssb->dw1.length = ((sizeof(struct i915_3dstate_sampler_state) +
+ sizeof(struct texture_sampler) * 3) >> 2) - 1;
+
+ /* MSB */
+ msb = (msb_state *)(++ssb);
+ msb->dw0.valid = 1;
+ msb->dw0.buffer_address = pI915XvMC->msb.offset;
+ msb->dw1.length = ((sizeof(struct i915_3dstate_map_state) +
+ sizeof(struct texture_map) * 3) >> 2) - 1;
+
+ /* PSP */
+ psp = (psp_state *)(++msb);
+ psp->dw0.valid = 1;
+ psp->dw0.buffer_address = pI915XvMC->psp.offset;
+ psp->dw1.length = ((sizeof(struct i915_3dstate_pixel_shader_program) +
+ sizeof(union shader_inst)) >> 2) - 1;
+
+ intelBatchbufferData(pI915XvMC, base, size, 0);
+ free(base);
+
+ /* 3DPRIMITIVE */
+ size = sizeof(*_3dprimitive) + sizeof(*vd) * 3;
+ base = calloc(1, size);
+ _3dprimitive = (struct i915_3dprimitive *)base;
+ _3dprimitive->dw0.inline_prim.type = CMD_3D;
+ _3dprimitive->dw0.inline_prim.opcode = OPC_3DPRIMITIVE;
+ _3dprimitive->dw0.inline_prim.vertex_location = VERTEX_INLINE;
+ _3dprimitive->dw0.inline_prim.prim = PRIM_RECTLIST;
+ _3dprimitive->dw0.inline_prim.length = size - 2;
+
+ vd = (struct vertex_data *)(++_3dprimitive);
+ vd->x = 0; /* FIXME!!! */
+ vd->x = 0; /* FIXME */
+ vd->tc0.tcx = 0;
+ vd->tc0.tcy = 0;
+ vd->tc1.tcx = 0;
+ vd->tc1.tcy = 0;
+
+ ++vd;
+ vd->x = 0; /* FIXME!!! */
+ vd->x = 0; /* FIXME */
+ vd->tc0.tcx = 0;
+ vd->tc0.tcy = 0;
+ vd->tc1.tcx = 0;
+ vd->tc1.tcy = 0;
+
+ ++vd;
+ vd->x = 0; /* FIXME!!! */
+ vd->x = 0; /* FIXME */
+ vd->tc0.tcx = 0;
+ vd->tc0.tcy = 0;
+ vd->tc1.tcx = 0;
+ vd->tc1.tcy = 0;
+
+ intelBatchbufferData(pI915XvMC, base, size, 0);
+ free(base);
+}
+
+/***************************************************************************
+// Function: i915_release_resource
+// Description:
+***************************************************************************/
+static void i915_release_resource(Display *display, XvMCContext *context)
+{
+ i915XvMCContext *pI915XvMC;
+
+ if (!display || !context)
+ return;
+
+ if (!(pI915XvMC = context->privData))
+ return;
+
+ pI915XvMC->ref--;
+ i915_xvmc_unmap_buffers(pI915XvMC);
+ releaseAttribDesc(pI915XvMC->attrib.numAttr, pI915XvMC->attribDesc);
+
+ driDestroyHashContents(pI915XvMC->drawHash);
+ drmHashDestroy(pI915XvMC->drawHash);
+
+ pthread_mutex_destroy(&pI915XvMC->ctxmutex);
+
+ XLockDisplay(display);
+ uniDRIDestroyContext(display, pI915XvMC->screen, pI915XvMC->id);
+ XUnlockDisplay(display);
+
+ intelDestroyBatchBuffer(pI915XvMC);
+ drmUnmap(pI915XvMC->sarea_address, pI915XvMC->sarea_size);
+
+ if (pI915XvMC->fd >= 0)
+ drmClose(pI915XvMC->fd);
+ pI915XvMC->fd = -1;
+
+ XLockDisplay(display);
+ uniDRICloseConnection(display, pI915XvMC->screen);
+ _xvmc_destroy_context(display, context);
+ XUnlockDisplay(display);
+
+ free(pI915XvMC);
+ context->privData = NULL;
+}
+
+/***************************************************************************
+// Function: XvMCCreateContext
+// Description: Create a XvMC context for the given surface parameters.
+// Arguments:
+// display - Connection to the X server.
+// port - XvPortID to use as avertised by the X connection.
+// surface_type_id - Unique identifier for the Surface type.
+// width - Width of the surfaces.
+// height - Height of the surfaces.
+// flags - one or more of the following
+// XVMC_DIRECT - A direct rendered context is requested.
+//
+// Notes: surface_type_id and width/height parameters must match those
+// returned by XvMCListSurfaceTypes.
+// Returns: Status
+***************************************************************************/
+Status XvMCCreateContext(Display *display, XvPortID port,
+ int surface_type_id, int width, int height,
+ int flags, XvMCContext *context)
+{
+ i915XvMCContext *pI915XvMC = NULL;
+ I915XvMCCreateContextRec *tmpComm = NULL;
+ Status ret;
+ drm_sarea_t *pSAREA;
+ char *curBusID;
+ uint *priv_data = NULL;
+ uint magic;
+ int major, minor;
+ int priv_count;
+ int isCapable;
+
+ /* Verify Obvious things first */
+ if (!display || !context)
+ return BadValue;
+
+ if (!(flags & XVMC_DIRECT)) {
+ /* Indirect */
+ printf("Indirect Rendering not supported! Using Direct.\n");
+ return BadAccess;
+ }
+
+ /* Limit use to root for now */
+ /* FIXME: remove it ??? */
+ if (geteuid()) {
+ printf("Use of XvMC on i915 is currently limited to root\n");
+ return BadAccess;
+ }
+
+ /*
+ *FIXME: Check $DISPLAY for legal values here
+ */
+ context->surface_type_id = surface_type_id;
+ context->width = (unsigned short)((width + 15) & ~15);
+ context->height = (unsigned short)((height + 15) & ~15);
+ context->flags = flags;
+ context->port = port;
+
+ /*
+ Width, Height, and flags are checked against surface_type_id
+ and port for validity inside the X server, no need to check
+ here.
+ */
+
+ /* Verify the XvMC extension exists */
+ XLockDisplay(display);
+ if (!XvMCQueryExtension(display, &event_base, &error_base)) {
+ printf("XvMCExtension is not available!\n");
+ XUnlockDisplay(display);
+ return BadAlloc;
+ }
+ /* Verify XvMC version */
+ ret = XvMCQueryVersion(display, &major, &minor);
+ if (ret) {
+ printf("XvMCQueryVersion Failed, unable to determine protocol version\n");
+ }
+ XUnlockDisplay(display);
+ /* FIXME: Check Major and Minor here */
+
+ /* Allocate private Context data */
+ context->privData = (void *)malloc(sizeof(i915XvMCContext));
+ if (!context->privData) {
+ printf("Unable to allocate resources for XvMC context.\n");
+ return BadAlloc;
+ }
+ pI915XvMC = (i915XvMCContext *)context->privData;
+
+ /* Check for drm */
+ if (!drmAvailable()) {
+ printf("Direct Rendering is not avilable on this system!\n");
+ free(pI915XvMC);
+ context->privData = NULL;
+ return BadAccess;
+ }
+
+ /*
+ Pass control to the X server to create a drm_context_t for us and
+ validate the with/height and flags.
+ */
+ if ((ret = _xvmc_create_context(display, context, &priv_count, &priv_data))) {
+ printf("Unable to create XvMC Context.\n");
+ free(pI915XvMC);
+ context->privData = NULL;
+ return ret;
+ }
+
+ if (priv_count != (sizeof(I915XvMCCreateContextRec) >> 2)) {
+ printf("_xvmc_create_context() returned incorrect data size!\n");
+ printf("\tExpected %d, got %d\n",
+ (int)(sizeof(I915XvMCCreateContextRec) >> 2),priv_count);
+ _xvmc_destroy_context(display, context);
+ free(priv_data);
+ free(pI915XvMC);
+ context->privData = NULL;
+ return BadAlloc;
+ }
+
+ tmpComm = (I915XvMCCreateContextRec *)priv_data;
+ pI915XvMC->ctxno = tmpComm->ctxno;
+ pI915XvMC->sis.handle = tmpComm->sis.handle;
+ pI915XvMC->sis.offset = tmpComm->sis.offset;
+ pI915XvMC->sis.size = tmpComm->sis.size;
+ pI915XvMC->msb.handle = tmpComm->msb.handle;
+ pI915XvMC->msb.offset = tmpComm->msb.offset;
+ pI915XvMC->msb.size = tmpComm->msb.size;
+ pI915XvMC->ssb.handle = tmpComm->ssb.handle;
+ pI915XvMC->ssb.offset = tmpComm->ssb.offset;
+ pI915XvMC->ssb.size = tmpComm->ssb.size;
+ pI915XvMC->psp.handle = tmpComm->psp.handle;
+ pI915XvMC->psp.offset = tmpComm->psp.offset;
+ pI915XvMC->psp.size = tmpComm->psp.size;
+ pI915XvMC->psc.handle = tmpComm->psc.handle;
+ pI915XvMC->psc.offset = tmpComm->psc.offset;
+ pI915XvMC->psc.size = tmpComm->psc.size;
+ pI915XvMC->corrdata.handle = tmpComm->corrdata.handle;
+ pI915XvMC->corrdata.offset = tmpComm->corrdata.offset;
+ pI915XvMC->corrdata.size = tmpComm->corrdata.size;
+ pI915XvMC->sarea_size = tmpComm->sarea_size;
+ pI915XvMC->sarea_priv_offset = tmpComm->sarea_priv_offset;
+ pI915XvMC->screen = tmpComm->screen;
+ pI915XvMC->depth = tmpComm->depth;
+ pI915XvMC->attrib = tmpComm->initAttrs;
+
+ /* Must free the private data we were passed from X */
+ free(priv_data);
+ priv_data = NULL;
+
+ XLockDisplay(display);
+ ret = uniDRIQueryDirectRenderingCapable(display, pI915XvMC->screen,
+ &isCapable);
+ if (!ret || !isCapable) {
+ XUnlockDisplay(display);
+ fprintf(stderr,
+ "Direct Rendering is not available on this system!\n");
+ free(pI915XvMC);
+ context->privData = NULL;
+ return BadAlloc;
+ }
+
+ if (!uniDRIOpenConnection(display, pI915XvMC->screen,
+ &pI915XvMC->hsarea, &curBusID)) {
+ XUnlockDisplay(display);
+ fprintf(stderr, "Could not open DRI connection to X server!\n");
+ free(pI915XvMC);
+ context->privData = NULL;
+ return BadAlloc;
+ }
+ XUnlockDisplay(display);
+
+ strncpy(pI915XvMC->busIdString, curBusID, 20);
+ pI915XvMC->busIdString[20] = '\0';
+ free(curBusID);
+
+ /* Open DRI Device */
+ if((pI915XvMC->fd = drmOpen(I915KernelDriverName, NULL)) < 0) {
+ printf("DRM Device for %s could not be opened.\n", I915KernelDriverName);
+ free(pI915XvMC);
+ context->privData = NULL;
+ return BadAccess;
+ } /* !pI915XvMC->fd */
+
+ /* Get magic number */
+ drmGetMagic(pI915XvMC->fd, &magic);
+ // context->flags = (unsigned long)magic;
+
+ XLockDisplay(display);
+ if (!uniDRIAuthConnection(display, pI915XvMC->screen, magic)) {
+ XUnlockDisplay(display);
+ fprintf(stderr,
+ "[XvMC]: X server did not allow DRI. Check permissions.\n");
+ free(pI915XvMC);
+ context->privData = NULL;
+ return BadAlloc;
+ }
+ XUnlockDisplay(display);
+
+ /*
+ * Map DRI Sarea.
+ */
+ if (drmMap(pI915XvMC->fd, pI915XvMC->hsarea,
+ pI915XvMC->sarea_size, &pI915XvMC->sarea_address) < 0) {
+ fprintf(stderr, "Unable to map DRI SAREA.\n");
+ free(pI915XvMC);
+ context->privData = NULL;
+ return BadAlloc;
+ }
+
+ pSAREA = (drm_sarea_t *)pI915XvMC->sarea_address;
+ pI915XvMC->driHwLock = (drmLock *)&pSAREA->lock;
+ pI915XvMC->sarea = SAREAPTR(pI915XvMC);
+ XLockDisplay(display);
+ ret = XMatchVisualInfo(display, pI915XvMC->screen,
+ (pI915XvMC->depth == 32) ? 24 : pI915XvMC->depth, TrueColor,
+ &pI915XvMC->visualInfo);
+ XUnlockDisplay(display);
+
+ if (!ret) {
+ fprintf(stderr,
+ "[XvMC]: Could not find a matching TrueColor visual.\n");
+ free(pI915XvMC);
+ context->privData = NULL;
+ drmUnmap(pI915XvMC->sarea_address, pI915XvMC->sarea_size);
+ return BadAlloc;
+ }
+
+ if (!uniDRICreateContext(display, pI915XvMC->screen,
+ pI915XvMC->visualInfo.visual, &pI915XvMC->id,
+ &pI915XvMC->hHWContext)) {
+
+ fprintf(stderr, "[XvMC]: Could not create DRI context.\n");
+ free(pI915XvMC);
+ context->privData = NULL;
+ drmUnmap(pI915XvMC->sarea_address, pI915XvMC->sarea_size);
+ return BadAlloc;
+ }
+
+ if (NULL == (pI915XvMC->drawHash = drmHashCreate())) {
+ fprintf(stderr,
+ "[XvMC]: Could not allocate drawable hash table.\n");
+ free(pI915XvMC);
+ context->privData = NULL;
+ drmUnmap(pI915XvMC->sarea_address, pI915XvMC->sarea_size);
+ return BadAlloc;
+ }
+
+ if (i915_xvmc_map_buffers(pI915XvMC)) {
+ i915_xvmc_unmap_buffers(pI915XvMC);
+ free(pI915XvMC);
+ context->privData = NULL;
+ drmUnmap(pI915XvMC->sarea_address, pI915XvMC->sarea_size);
+ return BadAlloc;
+ }
+
+ /* Initialize private context values */
+ setupAttribDesc(display, port, &pI915XvMC->attrib, pI915XvMC->attribDesc);
+ pI915XvMC->yStride = (width + 31) & ~31;
+ pI915XvMC->haveXv = 0;
+ pI915XvMC->attribChanged = 1;
+ pI915XvMC->dual_prime = 0;
+ pI915XvMC->last_flip = 0;
+ pI915XvMC->locked = 0;
+ pI915XvMC->port = context->port;
+ pthread_mutex_init(&pI915XvMC->ctxmutex, NULL);
+ intelInitBatchBuffer(pI915XvMC);
+ pI915XvMC->ref = 1;
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCDestroyContext
+// Description: Destorys the specified context.
+//
+// Arguments:
+// display - Specifies the connection to the server.
+// context - The context to be destroyed.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCDestroyContext(Display *display, XvMCContext *context)
+{
+ i915XvMCContext *pI915XvMC;
+
+ if (!display || !context)
+ return BadValue;
+
+ if (!(pI915XvMC = context->privData))
+ return (error_base + XvMCBadContext);
+
+ /* Pass Control to the X server to destroy the drm_context_t */
+ i915_release_resource(display,context);
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCCreateSurface
+***************************************************************************/
+Status XvMCCreateSurface(Display *display, XvMCContext *context, XvMCSurface *surface)
+{
+ Status ret;
+ i915XvMCContext *pI915XvMC;
+ i915XvMCSurface *pI915Surface;
+ int priv_count, i;
+ uint *priv_data;
+
+ if (!display || !context || !display)
+ return BadValue;
+
+ if (!(pI915XvMC = context->privData))
+ return (error_base + XvMCBadContext);
+
+ pthread_mutex_lock(&pI915XvMC->ctxmutex);
+ surface->privData = (i915XvMCSurface *)malloc(sizeof(i915XvMCSurface));
+
+ if (!(pI915Surface = surface->privData)) {
+ pthread_mutex_unlock(&pI915XvMC->ctxmutex);
+ return BadAlloc;
+ }
+
+ /* Initialize private values */
+ pI915Surface->last_render = 0;
+ pI915Surface->last_flip = 0;
+ pI915Surface->yStride = pI915XvMC->yStride;
+ pI915Surface->width = context->width;
+ pI915Surface->height = context->height;
+ pI915Surface->privContext = pI915XvMC;
+ pI915Surface->privSubPic = NULL;
+
+ XLockDisplay(display);
+
+ if ((ret = _xvmc_create_surface(display, context, surface,
+ &priv_count, &priv_data))) {
+ XUnlockDisplay(display);
+ printf("Unable to create XvMCSurface.\n");
+ free(pI915Surface);
+ surface->privData = NULL;
+ pthread_mutex_unlock(&pI915XvMC->ctxmutex);
+ return ret;
+ }
+
+ XUnlockDisplay(display);
+ pI915Surface->srfNo = priv_data[0];
+ pI915Surface->num_buffers = priv_data[1];
+ pI915Surface->curbuf = 0;
+
+ for (i = 0; i < pI915Surface->num_buffers; ++i)
+ pI915Surface->offsets[i] = priv_data[i + 2];
+
+ free(priv_data);
+ pI915XvMC->ref++;
+ pthread_mutex_unlock(&pI915XvMC->ctxmutex);
+
+ return Success;
+}
+
+
+/***************************************************************************
+// Function: XvMCDestroySurface
+***************************************************************************/
+Status XvMCDestroySurface(Display *display, XvMCSurface *surface)
+{
+ i915XvMCSurface *pI915Surface;
+ i915XvMCContext *pI915XvMC;
+
+ if (!display || !surface)
+ return BadValue;
+
+ if (!(pI915Surface = surface->privData))
+ return (error_base + XvMCBadSurface);
+
+ if (!(pI915XvMC = pI915Surface->privContext))
+ return (error_base + XvMCBadSurface);
+
+ if (pI915Surface->last_flip)
+ XvMCSyncSurface(display,surface);
+
+ XLockDisplay(display);
+ _xvmc_destroy_surface(display,surface);
+ XUnlockDisplay(display);
+
+ free(pI915Surface);
+ surface->privData = NULL;
+ pI915XvMC->ref--;
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCCreateBlocks
+***************************************************************************/
+Status XvMCCreateBlocks(Display *display, XvMCContext *context,
+ unsigned int num_blocks,
+ XvMCBlockArray *block)
+{
+ if (!display || !context || !num_blocks || !block)
+ return BadValue;
+
+ memset(block, 0, sizeof(XvMCBlockArray));
+
+ if (!(block->blocks = (short *)malloc(num_blocks << 6 * sizeof(short))))
+ return BadAlloc;
+
+ block->num_blocks = num_blocks;
+ block->context_id = context->context_id;
+ block->privData = NULL;
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCDestroyBlocks
+***************************************************************************/
+Status XvMCDestroyBlocks(Display *display, XvMCBlockArray *block)
+{
+ if (!display || block)
+ return BadValue;
+
+ if (block->blocks)
+ free(block->blocks);
+
+ block->context_id = 0;
+ block->num_blocks = 0;
+ block->blocks = NULL;
+ block->privData = NULL;
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCCreateMacroBlocks
+***************************************************************************/
+Status XvMCCreateMacroBlocks(Display *display, XvMCContext *context,
+ unsigned int num_blocks,
+ XvMCMacroBlockArray *blocks)
+{
+ if (!display || !context || !blocks || !num_blocks)
+ return BadValue;
+
+ memset(blocks, 0, sizeof(XvMCMacroBlockArray));
+ blocks->macro_blocks = (XvMCMacroBlock *)malloc(num_blocks * sizeof(XvMCMacroBlock));
+
+ if (!blocks->macro_blocks)
+ return BadAlloc;
+
+ blocks->num_blocks = num_blocks;
+ blocks->context_id = context->context_id;
+ blocks->privData = NULL;
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCDestroyMacroBlocks
+***************************************************************************/
+Status XvMCDestroyMacroBlocks(Display *display, XvMCMacroBlockArray *block)
+{
+ if (!display || !block)
+ return BadValue;
+ if (block->macro_blocks)
+ free(block->macro_blocks);
+
+ block->context_id = 0;
+ block->num_blocks = 0;
+ block->macro_blocks = NULL;
+ block->privData = NULL;
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCRenderSurface
+// Description: This function does the actual HWMC. Given a list of
+// macroblock structures it dispatched the hardware commands to execute
+// them. DMA buffer containing Y data are dispatched as they fill up
+// U and V DMA buffers are queued until all Y's are done. This minimizes
+// the context flipping and flushing required when switching between Y
+// U and V surfaces.
+***************************************************************************/
+Status XvMCRenderSurface(Display *display, 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 *macroblock_array,
+ XvMCBlockArray *blocks)
+{
+ int i;
+
+ /* correction data buffer */
+ char *corrdata_ptr;
+ int corrdata_size = 0;
+
+ /* Block Pointer */
+ short *block_ptr;
+ /* Current Macroblock Pointer */
+ XvMCMacroBlock *mb;
+
+ i915XvMCSurface *privTarget = NULL;
+ i915XvMCSurface *privFuture = NULL;
+ i915XvMCSurface *privPast = NULL;
+ i915XvMCContext *pI915XvMC = NULL;
+
+ /* Check Parameters for validity */
+ if (!display) {
+ printf("Error, Invalid display!\n");
+ return BadValue;
+ }
+
+ if (!display || !context || !target_surface) {
+ printf("Error, Invalid Display, Context or Target!\n");
+ return BadValue;
+ }
+
+ if (!num_macroblocks)
+ return Success;
+
+ if (!macroblock_array || !blocks) {
+ printf("Error, Invalid block data!\n");
+ return BadValue;
+ }
+
+ if (macroblock_array->num_blocks < (num_macroblocks + first_macroblock)) {
+ printf("Error, Too many macroblocks requested for MB array size.\n");
+ return BadValue;
+ }
+
+ if (!(pI915XvMC = context->privData))
+ return (error_base + XvMCBadContext);
+
+ if (!(privTarget = target_surface->privData))
+ return (error_base + XvMCBadSurface);
+
+ /* Test For YV12 Surface */
+ if (context->surface_type_id != FOURCC_YV12) {
+ printf("Error, HWMC only possible on YV12 Surfaces\n");
+ return BadValue;
+ }
+
+ /* P Frame Test */
+ if (!past_surface) {
+ /* Just to avoid some ifs later. */
+ privPast = privTarget;
+ } else {
+ if (!(privPast = past_surface->privData)) {
+ printf("Error, Invalid Past Surface!\n");
+ return (error_base + XvMCBadSurface);
+ }
+ }
+
+ /* B Frame Test */
+ if (!future_surface) {
+ privFuture = privTarget;
+ } else {
+ if (!past_surface) {
+ printf("Error, No Past Surface!\n");
+ return BadValue;
+ }
+
+ if (!(privFuture = future_surface->privData)) {
+ printf("Error, Invalid Future Surface!\n");
+ return (error_base + XvMCBadSurface);
+ }
+ }
+
+ corrdata_ptr = pI915XvMC->corrdata.map;
+ corrdata_size = 0;
+
+ for (i = first_macroblock; i < (num_macroblocks + first_macroblock); i++) {
+ int bspm = 0;
+ mb = &macroblock_array->macro_blocks[i];
+ block_ptr = &(blocks->blocks[mb->index << 6]);
+
+ /* Lockup can happen if the coordinates are too far out of range */
+ if(mb->x > (target_surface->width >> 4)) {
+ mb->x = 0;
+ }
+ if(mb->y > (target_surface->height >> 4)) {
+ mb->y = 0;
+ }
+
+ /* Catch no pattern case */
+ if (!(mb->macroblock_type & XVMC_MB_TYPE_PATTERN)) {
+ mb->coded_block_pattern = 0;
+ }
+
+ if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
+ bspm = 768;
+ } else {
+ bspm = mb_bytes[mb->coded_block_pattern];
+ }
+
+ corrdata_size += bspm;
+
+ if (corrdata_size > pI915XvMC->corrdata.size) {
+ printf("Error, correction data buffer overflow\n");
+ break;
+ }
+
+ memcpy(corrdata_ptr, block_ptr, bspm);
+ corrdata_ptr += bspm;
+ }
+
+ /* Lock For DMA */
+ LOCK_HARDWARE(pI915XvMC);
+ i915_mc_sampler_state_buffer(context);
+ i915_mc_pixel_shader_program_buffer(context);
+ i915_mc_pixel_shader_constants_buffer(context);
+ i915_mc_one_time_state_initialization(context);
+
+ i915_mc_static_indirect_state_buffer(context, target_surface, picture_structure);
+ i915_mc_map_state_buffer(context, target_surface, past_surface, future_surface);
+ i915_flush(pI915XvMC);
+ i915_mc_load_indirect_buffer(context);
+ i915_mc_mpeg_set_origin(context, &macroblock_array->macro_blocks[first_macroblock]);
+ for (i = first_macroblock; i < (num_macroblocks + first_macroblock); i++) {
+ mb = &macroblock_array->macro_blocks[i];
+
+ /* Intra Blocks */
+ if (mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
+ i915_mc_mpeg_macroblock_0mv(context, mb);
+ continue;
+ }
+
+ /* Frame Picture */
+ if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) {
+ switch (mb->motion_type & 3) {
+ case XVMC_PREDICTION_FIELD: /* Field Based */
+ i915_mc_mpeg_macroblock_2fbmv(context, mb);
+ continue;
+
+ case XVMC_PREDICTION_FRAME: /* Frame Based */
+ i915_mc_mpeg_macroblock_1fbmv(context, mb);
+ continue;
+
+ case XVMC_PREDICTION_DUAL_PRIME: /* Dual Prime */
+ i915_mc_mpeg_macroblock_2fbmv(context, mb);
+ continue;
+
+ default: /* No Motion Type */
+ renderError();
+ continue;
+ }
+ } else { /* Frame Picture */
+ switch (mb->motion_type & 3) {
+ case XVMC_PREDICTION_FIELD: /* Field Based */
+ i915_mc_mpeg_macroblock_1fbmv(context, mb);
+ continue;
+
+ case XVMC_PREDICTION_16x8: /* 16x8 MC */
+ i915_mc_mpeg_macroblock_2fbmv(context, mb);
+ continue;
+
+ case XVMC_PREDICTION_DUAL_PRIME: /* Dual Prime */
+ i915_mc_mpeg_macroblock_1fbmv(context, mb);
+ continue;
+
+ default: /* No Motion Type */
+ renderError();
+ continue;
+ }
+ } /* Field Picture */
+ }
+
+ intelFlushBatch(pI915XvMC, TRUE);
+ pI915XvMC->last_render = pI915XvMC->alloc.irq_emitted;
+ privTarget->last_render = pI915XvMC->last_render;
+
+ UNLOCK_HARDWARE(pI915XvMC);
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCPutSurface
+// Description:
+// Arguments:
+// display: Connection to X server
+// surface: Surface to be displayed
+// draw: X Drawable on which to display the surface
+// srcx: X coordinate of the top left corner of the region to be
+// displayed within the surface.
+// srcy: Y coordinate of the top left corner of the region to be
+// displayed within the surface.
+// srcw: Width of the region to be displayed.
+// srch: Height of the region to be displayed.
+// destx: X cordinate of the top left corner of the destination region
+// in the drawable coordinates.
+// desty: Y cordinate of the top left corner of the destination region
+// in the drawable coordinates.
+// destw: Width of the destination region.
+// desth: Height of the destination region.
+// flags: One or more of the following.
+// XVMC_TOP_FIELD - Display only the Top field of the surface.
+// XVMC_BOTTOM_FIELD - Display only the Bottom Field of the surface.
+// XVMC_FRAME_PICTURE - Display both fields or frame.
+//
+// Info: Portions of this function derived from i915_video.c (XFree86)
+//
+// This function is organized so that we wait as long as possible before
+// touching the overlay registers. Since we don't know that the last
+// flip has happened yet we want to give the overlay as long as
+// possible to catch up before we have to check on its progress. This
+// makes it unlikely that we have to wait on the last flip.
+***************************************************************************/
+Status XvMCPutSurface(Display *display,XvMCSurface *surface,
+ Drawable draw, short srcx, short srcy,
+ unsigned short srcw, unsigned short srch,
+ short destx, short desty,
+ unsigned short destw, unsigned short desth,
+ int flags)
+{
+ i915XvMCContext *pI915XvMC;
+ i915XvMCSurface *pI915Surface;
+ i915XvMCSubpicture *pI915SubPic;
+ I915XvMCCommandBuffer buf;
+
+ drawableInfo *drawInfo;
+ Status ret;
+
+ if (!display || !surface)
+ return BadValue;
+
+ if (!(pI915Surface = surface->privData))
+ return (error_base + XvMCBadSurface);
+
+ if (!(pI915XvMC = pI915Surface->privContext))
+ return (error_base + XvMCBadSurface);
+
+ pthread_mutex_lock(&pI915XvMC->ctxmutex);
+ if (getDRIDrawableInfoLocked(pI915XvMC->drawHash, display,
+ pI915XvMC->screen, draw, 0, pI915XvMC->fd, pI915XvMC->hHWContext,
+ pI915XvMC->sarea_address, FALSE, &drawInfo, sizeof(*drawInfo))) {
+ pthread_mutex_unlock(&pI915XvMC->ctxmutex);
+ return BadAccess;
+ }
+
+ if (!pI915XvMC->haveXv) {
+ pI915XvMC->xvImage =
+ XvCreateImage(display, pI915XvMC->port, FOURCC_XVMC,
+ (char *)&buf, pI915Surface->width, pI915Surface->height);
+ pI915XvMC->gc = XCreateGC(display, draw, 0, 0);
+ pI915XvMC->haveXv = 1;
+ }
+
+ pI915XvMC->draw = draw;
+ pI915XvMC->xvImage->data = (char *)&buf;
+
+ buf.command = I915_XVMC_COMMAND_DISPLAY;
+ buf.ctxNo = pI915XvMC->ctxno;
+ buf.srfNo = pI915Surface->srfNo;
+ pI915SubPic = pI915Surface->privSubPic;
+ buf.subPicNo = (!pI915SubPic ? 0 : pI915SubPic->srfNo);
+ buf.attrib = pI915XvMC->attrib;
+ buf.real_id = FOURCC_YV12;
+
+ XLockDisplay(display);
+
+ if ((ret = XvPutImage(display, pI915XvMC->port, draw, pI915XvMC->gc,
+ pI915XvMC->xvImage, srcx, srcy, srcw, srch,
+ destx, desty, destw, desth))) {
+ XUnlockDisplay(display);
+ pthread_mutex_unlock(&pI915XvMC->ctxmutex);
+
+ return ret;
+ }
+
+ XSync(display, 0);
+ XUnlockDisplay(display);
+ pI915XvMC->attribChanged = 0;
+ pthread_mutex_unlock(&pI915XvMC->ctxmutex);
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCSyncSurface
+// Arguments:
+// display - Connection to the X server
+// surface - The surface to synchronize
+// Info:
+// Returns: Status
+***************************************************************************/
+Status XvMCSyncSurface(Display *display, XvMCSurface *surface)
+{
+ Status ret;
+ int stat = 0;
+
+ do {
+ ret = XvMCGetSurfaceStatus(display, surface, &stat);
+ } while (!ret && (stat & XVMC_RENDERING));
+
+ return ret;
+}
+
+/***************************************************************************
+// Function: XvMCFlushSurface
+// Description:
+// This function commits pending rendering requests to ensure that they
+// wll be completed in a finite amount of time.
+// Arguments:
+// display - Connection to X server
+// surface - Surface to flush
+// Returns: Status
+***************************************************************************/
+Status XvMCFlushSurface(Display * display, XvMCSurface *surface)
+{
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCGetSurfaceStatus
+// Description:
+// Arguments:
+// display: connection to X server
+// surface: The surface to query
+// stat: One of the Following
+// XVMC_RENDERING - The last XvMCRenderSurface command has not
+// completed.
+// XVMC_DISPLAYING - The surface is currently being displayed or a
+// display is pending.
+***************************************************************************/
+Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface, int *stat)
+{
+ i915XvMCSurface *pI915Surface;
+ i915XvMCContext *pI915XvMC;
+
+ if (!display || !surface || !stat)
+ return BadValue;
+
+ *stat = 0;
+
+ if (!(pI915Surface = surface->privData))
+ return (error_base + XvMCBadSurface);
+
+ if (!(pI915XvMC = pI915Surface->privContext))
+ return (error_base + XvMCBadSurface);
+
+ LOCK_HARDWARE(pI915XvMC);
+
+ if (pI915Surface->last_flip) {
+ /* This can not happen */
+ if (pI915XvMC->last_flip < pI915Surface->last_flip) {
+ printf("Error: Context last flip is less than surface last flip.\n");
+ return BadValue;
+ }
+
+ /*
+ If the context has 2 or more flips after this surface it
+ cannot be displaying. Don't bother to check.
+ */
+ if (!(pI915XvMC->last_flip > (pI915Surface->last_flip + 1))) {
+ /*
+ If this surface was the last flipped it is either displaying
+ or about to be so don't bother checking.
+ */
+ if (pI915XvMC->last_flip == pI915Surface->last_flip) {
+ *stat |= XVMC_DISPLAYING;
+ }
+ }
+ }
+
+ if (pI915Surface->last_render &&
+ (pI915Surface->last_render > pI915XvMC->sarea->last_dispatch)) {
+ *stat |= XVMC_RENDERING;
+ }
+
+ UNLOCK_HARDWARE(pI915XvMC);
+ return Success;
+}
+
+/***************************************************************************
+//
+// Surface manipulation functions
+//
+***************************************************************************/
+
+/***************************************************************************
+// Function: XvMCHideSurface
+// Description: Stops the display of a surface.
+// Arguments:
+// display - Connection to the X server.
+// surface - surface to be hidden.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCHideSurface(Display *display, XvMCSurface *surface)
+{
+ i915XvMCSurface *pI915Surface;
+ i915XvMCContext *pI915XvMC;
+ int stat = 0, ret;
+
+ if (!display || !surface)
+ return BadValue;
+
+ if (!(pI915Surface = surface->privData))
+ return (error_base + XvMCBadSurface);
+
+ /* Get the associated context pointer */
+ if (!(pI915XvMC = pI915Surface->privContext))
+ return (error_base + XvMCBadSurface);
+
+ XvMCSyncSurface(display, surface);
+
+ /*
+ Get the status of the surface, if it is not currently displayed
+ we don't need to worry about it.
+ */
+ if ((ret = XvMCGetSurfaceStatus(display, surface, &stat)) != Success)
+ return ret;
+
+ if (!(stat & XVMC_DISPLAYING))
+ return Success;
+
+ /* FIXME: */
+ return Success;
+}
+
+/***************************************************************************
+//
+// Functions that deal with subpictures
+//
+***************************************************************************/
+
+
+
+/***************************************************************************
+// Function: XvMCCreateSubpicture
+// Description: This creates a subpicture by filling out the XvMCSubpicture
+// structure passed to it and returning Success.
+// Arguments:
+// display - Connection to the X server.
+// context - The context to create the subpicture for.
+// subpicture - Pre-allocated XvMCSubpicture structure to be filled in.
+// width - of subpicture
+// height - of subpicture
+// xvimage_id - The id describing the XvImage format.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCCreateSubpicture(Display *display, XvMCContext *context,
+ XvMCSubpicture *subpicture,
+ unsigned short width, unsigned short height,
+ int xvimage_id)
+{
+ i915XvMCContext *pI915XvMC;
+ i915XvMCSubpicture *pI915Subpicture;
+ int priv_count;
+ uint *priv_data;
+ Status ret;
+
+ if (!subpicture || !context || !display)
+ return BadValue;
+
+ pI915XvMC = (i915XvMCContext *)context->privData;
+
+ if (!pI915XvMC)
+ return (error_base + XvMCBadContext);
+
+ subpicture->privData =
+ (i915XvMCSubpicture *)malloc(sizeof(i915XvMCSubpicture));
+
+ if (!subpicture->privData)
+ return BadAlloc;
+
+
+ subpicture->context_id = context->context_id;
+ subpicture->xvimage_id = xvimage_id;
+ subpicture->width = width;
+ subpicture->height = height;
+ pI915Subpicture = (i915XvMCSubpicture *)subpicture->privData;
+
+ if ((ret = _xvmc_create_subpicture(display, context, subpicture,
+ &priv_count, &priv_data))) {
+ printf("Unable to create XvMCSubpicture.\n");
+ free(pI915Subpicture);
+ return ret;
+ }
+
+ if (priv_count != 2) {
+ printf("_xvmc_create_subpicture() returned incorrect data size.\n");
+ printf("Expected 2 got %d\n",priv_count);
+ free(priv_data);
+ free(pI915Subpicture);
+ subpicture->privData = NULL;
+ return BadAlloc;
+ }
+
+ free(priv_data);
+ /* subpicture */
+ subpicture->num_palette_entries = I915_SUBPIC_PALETTE_SIZE;
+ subpicture->entry_bytes = 3;
+ strncpy(subpicture->component_order, "YUV", 4);
+
+ /* Initialize private values */
+ pI915Subpicture->privContext = pI915XvMC;
+ pI915Subpicture->last_render= 0;
+ pI915Subpicture->last_flip = 0;
+ pI915Subpicture->srfNo = priv_data[0];
+ pI915Subpicture->offset = priv_data[1];
+ pI915Subpicture->pitch = ((subpicture->width + 31) & ~31);
+
+ switch(subpicture->xvimage_id) {
+ case FOURCC_IA44:
+ case FOURCC_AI44:
+ break;
+
+ default:
+ free(pI915Subpicture);
+ subpicture->privData = NULL;
+ return BadMatch;
+ }
+
+ pI915XvMC->ref++;
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCClearSubpicture
+// Description: Clear the area of the given subpicture to "color".
+// structure passed to it and returning Success.
+// Arguments:
+// display - Connection to the X server.
+// subpicture - Subpicture to clear.
+// x, y, width, height - rectangle in the subpicture to clear.
+// color - The data to file the rectangle with.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCClearSubpicture(Display *display, XvMCSubpicture *subpicture,
+ short x, short y,
+ unsigned short width, unsigned short height,
+ unsigned int color)
+{
+ i915XvMCContext *pI915XvMC;
+ i915XvMCSubpicture *pI915Subpicture;
+
+ if (!display || !subpicture)
+ return BadValue;
+
+ if (!(pI915Subpicture = subpicture->privData))
+ return (error_base + XvMCBadSubpicture);
+
+ if (!(pI915XvMC = pI915Subpicture->privContext))
+ return (error_base + XvMCBadSubpicture);
+
+ if ((x < 0) || (x + width) > subpicture->width)
+ return BadValue;
+
+ if ((y < 0) || (y + height) > subpicture->height)
+ return BadValue;
+
+ /* FIXME: clear the area */
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCCompositeSubpicture
+// Description: Composite the XvImae on the subpicture. This composit uses
+// non-premultiplied alpha. Destination alpha is utilized
+// except for with indexed subpictures. Indexed subpictures
+// use a simple "replace".
+// Arguments:
+// display - Connection to the X server.
+// subpicture - Subpicture to clear.
+// image - the XvImage to be used as the source of the composite.
+// srcx, srcy, width, height - The rectangle from the image to be used.
+// dstx, dsty - location in the subpicture to composite the source.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCCompositeSubpicture(Display *display, XvMCSubpicture *subpicture,
+ XvImage *image,
+ short srcx, short srcy,
+ unsigned short width, unsigned short height,
+ short dstx, short dsty)
+{
+ i915XvMCContext *pI915XvMC;
+ i915XvMCSubpicture *pI915Subpicture;
+
+ if (!display || !subpicture)
+ return BadValue;
+
+ if (!(pI915Subpicture = subpicture->privData))
+ return (error_base + XvMCBadSubpicture);
+
+ if (!(pI915XvMC = pI915Subpicture->privContext))
+ return (error_base + XvMCBadSubpicture);
+
+ if ((srcx < 0) || (srcx + width) > subpicture->width)
+ return BadValue;
+
+ if ((srcy < 0) || (srcy + height) > subpicture->height)
+ return BadValue;
+
+ if ((dstx < 0) || (dstx + width) > subpicture->width)
+ return BadValue;
+
+ if ((dsty < 0) || (dsty + width) > subpicture->height)
+ return BadValue;
+
+ if (image->id != subpicture->xvimage_id)
+ return BadMatch;
+
+ /* FIXME */
+ return Success;
+}
+
+
+/***************************************************************************
+// Function: XvMCDestroySubpicture
+// Description: Destroys the specified subpicture.
+// Arguments:
+// display - Connection to the X server.
+// subpicture - Subpicture to be destroyed.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCDestroySubpicture(Display *display, XvMCSubpicture *subpicture)
+{
+ i915XvMCSubpicture *pI915Subpicture;
+ i915XvMCContext *pI915XvMC;
+
+ if (!display || !subpicture)
+ return BadValue;
+
+ if (!(pI915Subpicture = subpicture->privData))
+ return (error_base + XvMCBadSubpicture);
+
+ if (!(pI915XvMC = pI915Subpicture->privContext))
+ return (error_base + XvMCBadSubpicture);
+
+ if (pI915Subpicture->last_render)
+ XvMCSyncSubpicture(display, subpicture);
+
+ XLockDisplay(display);
+ _xvmc_destroy_subpicture(display,subpicture);
+ XUnlockDisplay(display);
+
+ free(pI915Subpicture);
+ subpicture->privData = NULL;
+ pI915XvMC->ref--;
+
+ return Success;
+}
+
+
+/***************************************************************************
+// Function: XvMCSetSubpicturePalette
+// Description: Set the subpictures palette
+// Arguments:
+// display - Connection to the X server.
+// subpicture - Subpiture to set palette for.
+// palette - A pointer to an array holding the palette data. The array
+// is num_palette_entries * entry_bytes in size.
+// Returns: Status
+***************************************************************************/
+
+Status XvMCSetSubpicturePalette(Display *display, XvMCSubpicture *subpicture,
+ unsigned char *palette)
+{
+ i915XvMCSubpicture *pI915Subpicture;
+ int i, j;
+
+ if (!display || !subpicture)
+ return BadValue;
+
+ if (!(pI915Subpicture = subpicture->privData))
+ return (error_base + XvMCBadSubpicture);
+
+ j = 0;
+ for (i = 0; i < 16; i++) {
+ pI915Subpicture->palette[0][i] = palette[j++];
+ pI915Subpicture->palette[1][i] = palette[j++];
+ pI915Subpicture->palette[2][i] = palette[j++];
+ }
+
+ /* FIXME: Update the subpicture with the new palette */
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCBlendSubpicture
+// Description:
+// The behavior of this function is different depending on whether
+// or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo.
+// i915 only support frontend behavior.
+//
+// XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior):
+//
+// XvMCBlendSubpicture is a no-op in this case.
+//
+// Arguments:
+// display - Connection to the X server.
+// subpicture - The subpicture to be blended into the video.
+// target_surface - The surface to be displayed with the blended subpic.
+// source_surface - Source surface prior to blending.
+// subx, suby, subw, subh - The rectangle from the subpicture to use.
+// surfx, surfy, surfw, surfh - The rectangle in the surface to blend
+// blend the subpicture rectangle into. Scaling can ocure if
+// XVMC_SUBPICTURE_INDEPENDENT_SCALING is set.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCBlendSubpicture(Display *display, 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)
+{
+ i915XvMCSubpicture *pI915Subpicture;
+ i915XvMCSurface *privTargetSurface;
+
+ if (!display || !target_surface)
+ return BadValue;
+
+ if (!(privTargetSurface = target_surface->privData))
+ return (error_base + XvMCBadSurface);
+
+ if (subpicture) {
+ if (!(pI915Subpicture = subpicture->privData))
+ return (error_base + XvMCBadSubpicture);
+
+ if ((FOURCC_AI44 != subpicture->xvimage_id) &&
+ (FOURCC_IA44 != subpicture->xvimage_id))
+ return (error_base + XvMCBadSubpicture);
+
+ privTargetSurface->privSubPic = pI915Subpicture;
+ } else {
+ privTargetSurface->privSubPic = NULL;
+ }
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCBlendSubpicture2
+// Description:
+// The behavior of this function is different depending on whether
+// or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo.
+// i915 only supports frontend blending.
+//
+// XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior):
+//
+// XvMCBlendSubpicture2 blends the source_surface and subpicture and
+// puts it in the target_surface. This does not effect the status of
+// the source surface but will cause the target_surface to query
+// XVMC_RENDERING until the blend is completed.
+//
+// Arguments:
+// display - Connection to the X server.
+// subpicture - The subpicture to be blended into the video.
+// target_surface - The surface to be displayed with the blended subpic.
+// source_surface - Source surface prior to blending.
+// subx, suby, subw, subh - The rectangle from the subpicture to use.
+// surfx, surfy, surfw, surfh - The rectangle in the surface to blend
+// blend the subpicture rectangle into. Scaling can ocure if
+// XVMC_SUBPICTURE_INDEPENDENT_SCALING is set.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCBlendSubpicture2(Display *display,
+ 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)
+{
+ i915XvMCContext *pI915XvMC;
+ i915XvMCSubpicture *pI915Subpicture;
+ i915XvMCSurface *privSourceSurface;
+ i915XvMCSurface *privTargetSurface;
+
+ if (!display || !source_surface || !target_surface)
+ return BadValue;
+
+ if (!(privSourceSurface = source_surface->privData))
+ return (error_base + XvMCBadSurface);
+
+ if (!(privTargetSurface = target_surface->privData))
+ return (error_base + XvMCBadSurface);
+
+ if (!(pI915XvMC = privTargetSurface->privContext))
+ return (error_base + XvMCBadSurface);
+
+ if (((surfx + surfw) > privTargetSurface->width) ||
+ ((surfy + surfh) > privTargetSurface->height))
+ return BadValue;
+
+ if ((privSourceSurface->width != privTargetSurface->width) ||
+ (privTargetSurface->height != privTargetSurface->height))
+ return BadValue;
+
+ if (XvMCSyncSurface(display, source_surface))
+ return BadValue;
+
+ /* FIXME: update Target Surface */
+
+ if (subpicture) {
+ if (((subx + subw) > subpicture->width) ||
+ ((suby + subh) > subpicture->height))
+ return BadValue;
+
+ if (!(pI915Subpicture = subpicture->privData))
+ return (error_base + XvMCBadSubpicture);
+
+ if ((FOURCC_AI44 != subpicture->xvimage_id) &&
+ (FOURCC_IA44 != subpicture->xvimage_id))
+ return (error_base + XvMCBadSubpicture);
+
+ privTargetSurface->privSubPic = pI915Subpicture;
+ } else {
+ privTargetSurface->privSubPic = NULL;
+ }
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCSyncSubpicture
+// Description: This function blocks until all composite/clear requests on
+// the subpicture have been complete.
+// Arguments:
+// display - Connection to the X server.
+// subpicture - The subpicture to synchronize
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCSyncSubpicture(Display *display, XvMCSubpicture *subpicture)
+{
+ Status ret;
+ int stat = 0;
+
+ if (!display || !subpicture)
+ return BadValue;
+
+ do {
+ ret = XvMCGetSubpictureStatus(display, subpicture, &stat);
+ } while(!ret && (stat & XVMC_RENDERING));
+
+ return ret;
+}
+
+/***************************************************************************
+// Function: XvMCFlushSubpicture
+// Description: This function commits pending composite/clear requests to
+// ensure that they will be completed in a finite amount of
+// time.
+// Arguments:
+// display - Connection to the X server.
+// subpicture - The subpicture whos compsiting should be flushed
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCFlushSubpicture(Display *display, XvMCSubpicture *subpicture)
+{
+ i915XvMCSubpicture *pI915Subpicture;
+
+ if (!display || !subpicture)
+ return BadValue;
+
+ if (!(pI915Subpicture = subpicture->privData))
+ return (error_base + XvMCBadSubpicture);
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCGetSubpictureStatus
+// Description: This function gets the current status of a subpicture
+//
+// Arguments:
+// display - Connection to the X server.
+// subpicture - The subpicture whos status is being queried
+// stat - The status of the subpicture. It can be any of the following
+// OR'd together:
+// XVMC_RENDERING - Last composite or clear request not completed
+// XVMC_DISPLAYING - Suppicture currently being displayed.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCGetSubpictureStatus(Display *display, XvMCSubpicture *subpicture,
+ int *stat)
+{
+ i915XvMCSubpicture *pI915Subpicture;
+ i915XvMCContext *pI915XvMC;
+
+ if (!display || !subpicture || stat)
+ return BadValue;
+
+ *stat = 0;
+
+ if (!(pI915Subpicture = subpicture->privData))
+ return (error_base + XvMCBadSubpicture);
+
+ if (!(pI915XvMC = pI915Subpicture->privContext))
+ return (error_base + XvMCBadSubpicture);
+
+ LOCK_HARDWARE(pI915XvMC);
+ /* FIXME: */
+ if (pI915Subpicture->last_render &&
+ (pI915Subpicture->last_render > pI915XvMC->sarea->last_dispatch)) {
+ *stat |= XVMC_RENDERING;
+ }
+
+ UNLOCK_HARDWARE(pI915XvMC);
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCQueryAttributes
+// Description: An array of XvAttributes of size "number" is returned by
+// this function. If there are no attributes, NULL is returned and number
+// is set to 0. The array may be freed with xfree().
+//
+// Arguments:
+// display - Connection to the X server.
+// context - The context whos attributes we are querying.
+// number - The returned number of recognized atoms
+//
+// Returns:
+// An array of XvAttributes.
+***************************************************************************/
+XvAttribute *XvMCQueryAttributes(Display *display, XvMCContext *context,
+ int *number)
+{
+ i915XvMCContext *pI915XvMC;
+ XvAttribute *attributes;
+
+ if (!number)
+ return NULL;
+
+ *number = 0;
+
+ if (!display || !context)
+ return NULL;
+
+ if (!(pI915XvMC = context->privData))
+ return NULL;
+
+ pthread_mutex_lock(&pI915XvMC->ctxmutex);
+ if (NULL != (attributes = (XvAttribute *)
+ malloc(I915_NUM_XVMC_ATTRIBUTES * sizeof(XvAttribute)))) {
+ memcpy(attributes, pI915XvMC->attribDesc, I915_NUM_XVMC_ATTRIBUTES);
+ *number = I915_NUM_XVMC_ATTRIBUTES;
+ }
+ pthread_mutex_unlock(&pI915XvMC->ctxmutex);
+
+ return attributes;
+}
+
+/***************************************************************************
+// Function: XvMCSetAttribute
+// Description: This function sets a context-specific attribute.
+//
+// Arguments:
+// display - Connection to the X server.
+// context - The context whos attributes we are querying.
+// attribute - The X atom of the attribute to be changed.
+// value - The new value for the attribute.
+//
+// Returns:
+// Status
+***************************************************************************/
+Status XvMCSetAttribute(Display *display, XvMCContext *context,
+ Atom attribute, int value)
+{
+ i915XvMCContext *pI915XvMC;
+ I915XvMCCommandBuffer buf;
+ int found = 0;
+ unsigned i;
+
+ if (!display)
+ return BadValue;
+
+ if (!context || !(pI915XvMC = context->privData))
+ return (error_base + XvMCBadContext);
+
+ pthread_mutex_lock(&pI915XvMC->ctxmutex);
+ for (i = 0; i < pI915XvMC->attrib.numAttr; ++i) {
+ if (attribute == pI915XvMC->attrib.attributes[i].attribute) {
+ if ((!(pI915XvMC->attribDesc[i].flags & XvSettable)) ||
+ value < pI915XvMC->attribDesc[i].min_value ||
+ value > pI915XvMC->attribDesc[i].max_value)
+ return BadValue;
+
+ pI915XvMC->attrib.attributes[i].value = value;
+ found = 1;
+ pI915XvMC->attribChanged = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ pthread_mutex_unlock(&pI915XvMC->ctxmutex);
+ return BadMatch;
+ }
+
+ if (pI915XvMC->haveXv) {
+ buf.command = I915_XVMC_COMMAND_ATTRIBUTES;
+ pI915XvMC->xvImage->data = (char *)&buf;
+ buf.ctxNo = pI915XvMC->ctxno | I915_XVMC_VALID;
+ buf.attrib = pI915XvMC->attrib;
+ XLockDisplay(display);
+ pI915XvMC->attribChanged =
+ XvPutImage(display, pI915XvMC->port, pI915XvMC->draw,
+ pI915XvMC->gc, pI915XvMC->xvImage, 0, 0, 1, 1, 0, 0, 1, 1);
+ XUnlockDisplay(display);
+ }
+
+ pthread_mutex_unlock(&pI915XvMC->ctxmutex);
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCGetAttribute
+// Description: This function queries a context-specific attribute and
+// returns the value.
+//
+// Arguments:
+// display - Connection to the X server.
+// context - The context whos attributes we are querying.
+// attribute - The X atom of the attribute to be queried
+// value - The returned attribute value
+//
+// Returns:
+// Status
+// Notes:
+***************************************************************************/
+Status XvMCGetAttribute(Display *display, XvMCContext *context,
+ Atom attribute, int *value)
+{
+ i915XvMCContext *pI915XvMC;
+ int found = 0;
+ unsigned i;
+
+ if (!display || !value)
+ return BadValue;
+
+ if (!context || !(pI915XvMC = context->privData))
+ return (error_base + XvMCBadContext);
+
+ pthread_mutex_lock(&pI915XvMC->ctxmutex);
+ for (i = 0; i < pI915XvMC->attrib.numAttr; ++i) {
+ if (attribute == pI915XvMC->attrib.attributes[i].attribute) {
+ if (pI915XvMC->attribDesc[i].flags & XvGettable) {
+ *value = pI915XvMC->attrib.attributes[i].value;
+ found = 1;
+ break;
+ }
+ }
+ }
+ pthread_mutex_unlock(&pI915XvMC->ctxmutex);
+
+ if (!found)
+ return BadMatch;
+
+ return Success;
+}
diff --git a/src/xvmc/I915XvMC.h b/src/xvmc/I915XvMC.h
new file mode 100644
index 00000000..08170834
--- /dev/null
+++ b/src/xvmc/I915XvMC.h
@@ -0,0 +1,178 @@
+/***************************************************************************
+
+Copyright 2001 Intel Corporation. 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 INTEL, 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 _I915XVMC_H
+#define _I915XVMC_H
+
+/* #define XVMC_DEBUG(x) do {x; }while(0); */
+#define XVMC_DEBUG(x)
+
+#include "xf86drm.h"
+#include "i830_common.h"
+#include "i915_hwmc.h"
+#include <X11/Xlibint.h>
+#include <X11/Xutil.h>
+
+#define I915_SUBPIC_PALETTE_SIZE 16
+
+/***************************************************************************
+// i915XvMCDrmMap: Holds the data about the DRM maps
+***************************************************************************/
+typedef struct _i915XvMCDrmMap {
+ drm_handle_t handle;
+ unsigned offset;
+ unsigned size;
+ drmAddress map;
+} i915XvMCDrmMap, *i915XvMCDrmMapPtr;
+
+/***************************************************************************
+// i915XvMCContext: Private Context data referenced via the privData
+// pointer in the XvMCContext structure.
+***************************************************************************/
+typedef struct _i915XvMCContext {
+ unsigned ctxno;
+ int fd; /* File descriptor for /dev/dri */
+ unsigned last_render;
+ unsigned last_flip;
+ unsigned dual_prime; /* Flag to identify when dual prime is in use. */
+ unsigned yStride;
+ unsigned short ref;
+ pthread_mutex_t ctxmutex;
+ char busIdString[21]; /* PCI:0:1:0 or PCI:0:2:0 */
+ int lock; /* Lightweight lock to avoid locking twice */
+ int locked;
+ volatile drmI830Sarea *sarea;
+
+ drmLock *driHwLock;
+ drm_context_t hHWContext; /* drmcontext; */
+ drm_handle_t hsarea; /* Handle to drm shared memory area */
+ drmAddress sarea_address; /* Virtual address of shared memory area */
+ unsigned sarea_size; /* Size of drm shared memory area */
+ unsigned sarea_priv_offset; /* Offset in sarea to private part */
+ unsigned screen;
+ unsigned depth;
+ XvPortID port; /* Xv Port ID when displaying */
+ I915XvMCAttrHolder attrib; /* This contexts attributes and their values */
+ XvAttribute attribDesc[I915_NUM_XVMC_ATTRIBUTES]; /* Attribute decriptions */
+ int haveXv; /* Have I initialized the Xv
+ * connection for this surface? */
+ XvImage *xvImage; /* Fake Xv Image used for command
+ * buffer transport to the X server */
+ int attribChanged; /* Attributes have changed and need to
+ * be uploaded to Xv at next frame
+ * display */
+ GC gc; /* X GC needed for displaying */
+ Drawable draw; /* Drawable to undisplay from */
+ XID id;
+ XVisualInfo visualInfo;
+ void *drawHash;
+
+ i915XvMCDrmMap sis;
+ i915XvMCDrmMap msb;
+ i915XvMCDrmMap ssb;
+ i915XvMCDrmMap psp;
+ i915XvMCDrmMap psc;
+ i915XvMCDrmMap corrdata;
+
+ struct {
+ unsigned start_offset;
+ unsigned size;
+ unsigned space;
+ unsigned char *ptr;
+ } batch;
+
+ struct
+ {
+ void *ptr;
+ unsigned size;
+ unsigned offset;
+ unsigned active_buf;
+ unsigned irq_emitted;
+ } alloc;
+} i915XvMCContext;
+
+/***************************************************************************
+// i915XvMCSubpicture: Private data structure for each XvMCSubpicture. This
+// structure is referenced by the privData pointer in the XvMCSubpicture
+// structure.
+***************************************************************************/
+typedef struct _i915XvMCSubpicture {
+ unsigned srfNo;
+ unsigned last_render;
+ unsigned last_flip;
+ unsigned offset;
+ unsigned pitch;
+ unsigned char palette[3][16];
+ i915XvMCContext *privContext;
+} i915XvMCSubpicture;
+
+/***************************************************************************
+// i915XvMCSurface: Private data structure for each XvMCSurface. This
+// structure is referenced by the privData pointer in the XvMCSurface
+// structure.
+***************************************************************************/
+#define I830_MAX_BUFS 2 /*Number of YUV buffers per surface */
+typedef struct _i915XvMCSurface {
+ unsigned srfNo; /* XvMC private surface numbers */
+ unsigned num_buffers; /* Number of picture buffers */
+ unsigned curbuf; /* Which is the current buffer? */
+ unsigned offsets[I830_MAX_BUFS]; /* Offsets of picture buffers */
+ unsigned last_render;
+ unsigned last_flip;
+ unsigned yStride; /* Stride of YUV420 Y component. */
+ unsigned width; /* Dimensions */
+ unsigned height;
+ i915XvMCContext *privContext;
+ i915XvMCSubpicture *privSubPic; /* Subpicture to be blended when
+ * displaying. NULL if none. */
+} i915XvMCSurface;
+
+/* Subpicture fourcc */
+#define FOURCC_IA44 0x34344149
+
+/*
+ Definitions for temporary wire protocol hooks to be replaced
+ when a HW independent libXvMC is created.
+*/
+extern Status _xvmc_create_context(Display *dpy, XvMCContext *context,
+ int *priv_count, uint **priv_data);
+
+extern Status _xvmc_destroy_context(Display *dpy, XvMCContext *context);
+
+extern Status _xvmc_create_surface(Display *dpy, XvMCContext *context,
+ XvMCSurface *surface, int *priv_count,
+ uint **priv_data);
+
+extern Status _xvmc_destroy_surface(Display *dpy, XvMCSurface *surface);
+
+extern Status _xvmc_create_subpicture(Display *dpy, XvMCContext *context,
+ XvMCSubpicture *subpicture,
+ int *priv_count, uint **priv_data);
+
+extern Status _xvmc_destroy_subpicture(Display *dpy,
+ XvMCSubpicture *subpicture);
+
+#endif /* _I915XVMC_H */
diff --git a/src/xvmc/Makefile.am b/src/xvmc/Makefile.am
index b5c9db9a..67338092 100644
--- a/src/xvmc/Makefile.am
+++ b/src/xvmc/Makefile.am
@@ -1,5 +1,6 @@
if DRI
-lib_LTLIBRARIES=libI810XvMC.la
+lib_LTLIBRARIES=libI810XvMC.la libI915XvMC.la
+
libI810XvMC_la_SOURCES = I810XvMC.c \
I810XvMC.h
@@ -7,4 +8,17 @@ libI810XvMC_la_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ \
-I$(top_srcdir)/src -DTRUE=1 -DFALSE=0
libI810XvMC_la_LDFLAGS = -version-number 1:0:0
libI810XvMC_la_LIBADD = @DRI_LIBS@
+
+libI915XvMC_la_SOURCES = I915XvMC.c \
+ I915XvMC.h \
+ intel_batchbuffer.c \
+ intel_batchbuffer.h \
+ xf86dri.c \
+ xf86dri.h \
+ xf86dristr.h \
+ driDrawable.c \
+ driDrawable.h
+libI915XvMC_la_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(top_srcdir)/src -DTRUE=1 -DFALSE=0
+libI915XvMC_la_LDFLAGS = -version-number 1:0:0
+libI915XvMC_la_LIBADD = @DRI_LIBS@
endif
diff --git a/src/xvmc/driDrawable.c b/src/xvmc/driDrawable.c
new file mode 100644
index 00000000..83863347
--- /dev/null
+++ b/src/xvmc/driDrawable.c
@@ -0,0 +1,174 @@
+/*****************************************************************************
+ * driDrawable.c: Lean Version of DRI utilities.
+ *
+ * Copyright (c) 2005 Thomas Hellstrom. 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, 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
+ * AUTHOR(S) OR 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.
+ */
+
+
+#include <X11/Xlibint.h>
+#include <X11/Xutil.h>
+#include "xf86drm.h"
+#include "drm.h"
+#include "xf86dri.h"
+#include "drm_sarea.h"
+#include "driDrawable.h"
+
+static unsigned
+drawStamp(volatile drm_sarea_t * pSarea, int index)
+{
+ return pSarea->drawableTable[index].stamp;
+}
+
+int
+getDRIDrawableInfoLocked(void *drawHash, Display * display, int screen,
+ Drawable draw, unsigned lockFlags, int drmFD, drm_context_t drmContext,
+ drmAddress sarea, Bool updateInfo, drawableInfo ** info,
+ unsigned long infoSize)
+{
+ drawableInfo *drawInfo;
+ void *res;
+ drm_drawable_t drmDraw = 0;
+ volatile drm_sarea_t *pSarea = (drm_sarea_t *) sarea;
+ drm_clip_rect_t *clipFront, *clipBack;
+
+ int ret;
+
+ if (drmHashLookup(drawHash, (unsigned long)draw, &res)) {
+
+ /*
+ * The drawable is unknown to us. Create it and put it in the
+ * hash table.
+ */
+
+ DRM_UNLOCK(drmFD, &pSarea->lock, drmContext);
+ if (!uniDRICreateDrawable(display, screen, draw, &drmDraw)) {
+ DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags);
+ return 1;
+ }
+ DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags);
+
+ drawInfo = (drawableInfo *) malloc(infoSize);
+ if (!drawInfo)
+ return 1;
+
+ drawInfo->drmDraw = drmDraw;
+ drawInfo->stamp = 0;
+ drawInfo->clipFront = 0;
+ drawInfo->clipBack = 0;
+
+ drmHashInsert(drawHash, (unsigned long)draw, drawInfo);
+
+ } else {
+ drawInfo = res;
+ }
+
+ drawInfo->touched = FALSE;
+ while (!drawInfo->clipFront
+ || drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) {
+
+ /*
+ * The drawable has been touched since we last got info about it.
+ * obtain new info from the X server.
+ */
+
+ drawInfo->touched = TRUE;
+
+ if (updateInfo || !drawInfo->clipFront) {
+ DRM_UNLOCK(drmFD, &pSarea->lock, drmContext);
+
+ ret = uniDRIGetDrawableInfo(display, screen, draw,
+ &drawInfo->index, &drawInfo->stamp, &drawInfo->x,
+ &drawInfo->y, &drawInfo->w, &drawInfo->h,
+ &drawInfo->numClipFront, &clipFront,
+ &drawInfo->backX, &drawInfo->backY,
+ &drawInfo->numClipBack, &clipBack);
+
+ DRM_LIGHT_LOCK(drmFD, &pSarea->lock, drmContext);
+
+ /*
+ * Error. Probably the drawable is destroyed. Return error and old values.
+ */
+
+ if (!ret) {
+ free(drawInfo);
+ drawInfo = NULL;
+ drmHashDelete(drawHash, (unsigned long)draw);
+
+ DRM_UNLOCK(drmFD, &pSarea->lock, drmContext);
+ uniDRIDestroyDrawable(display, screen, draw);
+ DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags);
+
+ return 1;
+ }
+
+ if (drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) {
+
+ /*
+ * The info is already outdated. Sigh. Have another go.
+ */
+
+ XFree(clipFront);
+ XFree(clipBack);
+ continue;
+ }
+
+ if (drawInfo->clipFront)
+ XFree(drawInfo->clipFront);
+ drawInfo->clipFront = clipFront;
+ if (drawInfo->clipBack)
+ XFree(drawInfo->clipBack);
+ drawInfo->clipBack = clipBack;
+ } else {
+ if (!drawInfo->clipFront)
+ drawInfo->clipFront = (drm_clip_rect_t *) ~ 0UL;
+ drawInfo->stamp = drawStamp(pSarea, drawInfo->index);
+ }
+ }
+ *info = drawInfo;
+ return 0;
+}
+
+void
+driDestroyHashContents(void *drawHash)
+{
+ unsigned long key;
+ void *content;
+ drawableInfo *drawInfo;
+
+ if (drmHashFirst(drawHash, &key, &content) < 1)
+ return;
+ drawInfo = (drawableInfo *) content;
+ if (drawInfo->clipBack)
+ XFree(drawInfo->clipBack);
+ if (drawInfo->clipFront)
+ XFree(drawInfo->clipFront);
+ free(drawInfo);
+ while (drmHashNext(drawHash, &key, &content) == 1) {
+ drawInfo = (drawableInfo *) content;
+ if (drawInfo->clipBack)
+ XFree(drawInfo->clipBack);
+ if (drawInfo->clipFront)
+ XFree(drawInfo->clipFront);
+ free(drawInfo);
+ }
+
+ return;
+}
diff --git a/src/xvmc/driDrawable.h b/src/xvmc/driDrawable.h
new file mode 100644
index 00000000..a758c7c7
--- /dev/null
+++ b/src/xvmc/driDrawable.h
@@ -0,0 +1,64 @@
+/*****************************************************************************
+ * driDrawable.h: Lean Version of DRI utilities.
+ *
+ * Copyright (c) 2005 Thomas Hellstrom. 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, 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
+ * AUTHOR(S) OR 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.
+ */
+
+#ifndef _DRIDRAWABLE_H
+#define _DRIDRAWABLE_H
+
+typedef struct _drawableInfo
+{
+ drm_drawable_t drmDraw;
+ unsigned stamp;
+ unsigned index;
+ drm_clip_rect_t *clipFront;
+ drm_clip_rect_t *clipBack;
+ int x;
+ int y;
+ int w;
+ int h;
+ int backX;
+ int backY;
+ int numClipFront;
+ int numClipBack;
+ Bool touched;
+} drawableInfo;
+
+/*
+ * Get updated info about the drawable "draw". The drawableInfo record returned is malloced
+ * and administrated internally. Never free it unless you know exactly what you are doing.
+ * The drm hash table "drawHash" needs to be initialized externally.
+ */
+
+extern int
+getDRIDrawableInfoLocked(void *drawHash, Display * display, int screen,
+ Drawable draw, unsigned lockFlags, int drmFD, drm_context_t drmContext,
+ drmAddress sarea, Bool updateInfo, drawableInfo ** info,
+ unsigned long infoSize);
+
+/*
+ * Free all resources created by the above function. Typically done on exit.
+ */
+
+extern void driDestroyHashContents(void *drawHash);
+
+#endif
diff --git a/src/xvmc/i915_program.h b/src/xvmc/i915_program.h
new file mode 100644
index 00000000..d11a5189
--- /dev/null
+++ b/src/xvmc/i915_program.h
@@ -0,0 +1,276 @@
+#ifndef _I915_PROGRAM_H
+#define _I915_PROGRAM_H
+
+#define REG_TYPE_R 0 /* temporary regs, no need to
+ * dcl, must be written before
+ * read -- Preserved between
+ * phases.
+ */
+#define REG_TYPE_T 1 /* Interpolated values, must be
+ * dcl'ed before use.
+ *
+ * 0..7: texture coord,
+ * 8: diffuse spec,
+ * 9: specular color,
+ * 10: fog parameter in w.
+ */
+#define REG_TYPE_CONST 2 /* Restriction: only one const
+ * can be referenced per
+ * instruction, though it may be
+ * selected for multiple inputs.
+ * Constants not initialized
+ * default to zero.
+ */
+#define REG_TYPE_S 3 /* sampler */
+#define REG_TYPE_OC 4 /* output color (rgba) */
+#define REG_TYPE_OD 5 /* output depth (w), xyz are
+ * temporaries. If not written,
+ * interpolated depth is used?
+ */
+#define REG_TYPE_U 6 /* unpreserved temporaries */
+#define REG_TYPE_MASK 0x7
+#define REG_NR_MASK 0xf
+
+/* REG_TYPE_T:
+ */
+#define T_TEX0 0
+#define T_TEX1 1
+#define T_TEX2 2
+#define T_TEX3 3
+#define T_TEX4 4
+#define T_TEX5 5
+#define T_TEX6 6
+#define T_TEX7 7
+#define T_DIFFUSE 8
+#define T_SPECULAR 9
+#define T_FOG_W 10 /* interpolated fog is in W coord */
+
+/* Arithmetic instructions */
+
+/* .replicate_swizzle == selection and replication of a particular
+ * scalar channel, ie., .xxxx, .yyyy, .zzzz or .wwww
+ */
+#define A0_NOP (0x0<<24) /* no operation */
+#define A0_ADD (0x1<<24) /* dst = src0 + src1 */
+#define A0_MOV (0x2<<24) /* dst = src0 */
+#define A0_MUL (0x3<<24) /* dst = src0 * src1 */
+#define A0_MAD (0x4<<24) /* dst = src0 * src1 + src2 */
+#define A0_DP2ADD (0x5<<24) /* dst.xyzw = src0.xy dot src1.xy + src2.replicate_swizzle */
+#define A0_DP3 (0x6<<24) /* dst.xyzw = src0.xyz dot src1.xyz */
+#define A0_DP4 (0x7<<24) /* dst.xyzw = src0.xyzw dot src1.xyzw */
+#define A0_FRC (0x8<<24) /* dst = src0 - floor(src0) */
+#define A0_RCP (0x9<<24) /* dst.xyzw = 1/(src0.replicate_swizzle) */
+#define A0_RSQ (0xa<<24) /* dst.xyzw = 1/(sqrt(abs(src0.replicate_swizzle))) */
+#define A0_EXP (0xb<<24) /* dst.xyzw = exp2(src0.replicate_swizzle) */
+#define A0_LOG (0xc<<24) /* dst.xyzw = log2(abs(src0.replicate_swizzle)) */
+#define A0_CMP (0xd<<24) /* dst = (src0 >= 0.0) ? src1 : src2 */
+#define A0_MIN (0xe<<24) /* dst = (src0 < src1) ? src0 : src1 */
+#define A0_MAX (0xf<<24) /* dst = (src0 >= src1) ? src0 : src1 */
+#define A0_FLR (0x10<<24) /* dst = floor(src0) */
+#define A0_MOD (0x11<<24) /* dst = src0 fmod 1.0 */
+#define A0_TRC (0x12<<24) /* dst = int(src0) */
+#define A0_SGE (0x13<<24) /* dst = src0 >= src1 ? 1.0 : 0.0 */
+#define A0_SLT (0x14<<24) /* dst = src0 < src1 ? 1.0 : 0.0 */
+#define A0_DEST_SATURATE (1<<22)
+#define A0_DEST_TYPE_SHIFT 19
+/* Allow: R, OC, OD, U */
+#define A0_DEST_NR_SHIFT 14
+/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
+#define A0_DEST_CHANNEL_X (1<<10)
+#define A0_DEST_CHANNEL_Y (2<<10)
+#define A0_DEST_CHANNEL_Z (4<<10)
+#define A0_DEST_CHANNEL_W (8<<10)
+#define A0_DEST_CHANNEL_ALL (0xf<<10)
+#define A0_DEST_CHANNEL_SHIFT 10
+#define A0_SRC0_TYPE_SHIFT 7
+#define A0_SRC0_NR_SHIFT 2
+
+#define A0_DEST_CHANNEL_XY (A0_DEST_CHANNEL_X|A0_DEST_CHANNEL_Y)
+#define A0_DEST_CHANNEL_XYZ (A0_DEST_CHANNEL_XY|A0_DEST_CHANNEL_Z)
+
+#define SRC_X 0
+#define SRC_Y 1
+#define SRC_Z 2
+#define SRC_W 3
+#define SRC_ZERO 4
+#define SRC_ONE 5
+
+#define A1_SRC0_CHANNEL_X_NEGATE (1<<31)
+#define A1_SRC0_CHANNEL_X_SHIFT 28
+#define A1_SRC0_CHANNEL_Y_NEGATE (1<<27)
+#define A1_SRC0_CHANNEL_Y_SHIFT 24
+#define A1_SRC0_CHANNEL_Z_NEGATE (1<<23)
+#define A1_SRC0_CHANNEL_Z_SHIFT 20
+#define A1_SRC0_CHANNEL_W_NEGATE (1<<19)
+#define A1_SRC0_CHANNEL_W_SHIFT 16
+#define A1_SRC1_TYPE_SHIFT 13
+#define A1_SRC1_NR_SHIFT 8
+#define A1_SRC1_CHANNEL_X_NEGATE (1<<7)
+#define A1_SRC1_CHANNEL_X_SHIFT 4
+#define A1_SRC1_CHANNEL_Y_NEGATE (1<<3)
+#define A1_SRC1_CHANNEL_Y_SHIFT 0
+
+#define A2_SRC1_CHANNEL_Z_NEGATE (1<<31)
+#define A2_SRC1_CHANNEL_Z_SHIFT 28
+#define A2_SRC1_CHANNEL_W_NEGATE (1<<27)
+#define A2_SRC1_CHANNEL_W_SHIFT 24
+#define A2_SRC2_TYPE_SHIFT 21
+#define A2_SRC2_NR_SHIFT 16
+#define A2_SRC2_CHANNEL_X_NEGATE (1<<15)
+#define A2_SRC2_CHANNEL_X_SHIFT 12
+#define A2_SRC2_CHANNEL_Y_NEGATE (1<<11)
+#define A2_SRC2_CHANNEL_Y_SHIFT 8
+#define A2_SRC2_CHANNEL_Z_NEGATE (1<<7)
+#define A2_SRC2_CHANNEL_Z_SHIFT 4
+#define A2_SRC2_CHANNEL_W_NEGATE (1<<3)
+#define A2_SRC2_CHANNEL_W_SHIFT 0
+
+/* Declaration instructions */
+#define D0_DCL (0x19<<24) /* Declare a t (interpolated attrib)
+ * register or an s (sampler)
+ * register. */
+#define D0_SAMPLE_TYPE_SHIFT 22
+#define D0_SAMPLE_TYPE_2D (0x0<<22)
+#define D0_SAMPLE_TYPE_CUBE (0x1<<22)
+#define D0_SAMPLE_TYPE_VOLUME (0x2<<22)
+#define D0_SAMPLE_TYPE_MASK (0x3<<22)
+
+#define D0_TYPE_SHIFT 19
+/* Allow: T, S */
+#define D0_NR_SHIFT 14
+/* Allow T: 0..10, S: 0..15 */
+#define D0_CHANNEL_X (1<<10)
+#define D0_CHANNEL_Y (2<<10)
+#define D0_CHANNEL_Z (4<<10)
+#define D0_CHANNEL_W (8<<10)
+#define D0_CHANNEL_ALL (0xf<<10)
+#define D0_CHANNEL_NONE (0<<10)
+
+#define D0_CHANNEL_XY (D0_CHANNEL_X|D0_CHANNEL_Y)
+#define D0_CHANNEL_XYZ (D0_CHANNEL_XY|D0_CHANNEL_Z)
+
+/* I915 Errata: Do not allow (xz), (xw), (xzw) combinations for diffuse
+ * or specular declarations.
+ *
+ * For T dcls, only allow: (x), (xy), (xyz), (w), (xyzw)
+ *
+ * Must be zero for S (sampler) dcls
+ */
+#define D1_MBZ 0
+#define D2_MBZ 0
+
+/* Texture instructions */
+#define T0_TEXLD (0x15<<24) /* Sample texture using predeclared
+ * sampler and address, and output
+ * filtered texel data to destination
+ * register */
+#define T0_TEXLDP (0x16<<24) /* Same as texld but performs a
+ * perspective divide of the texture
+ * coordinate .xyz values by .w before
+ * sampling. */
+#define T0_TEXLDB (0x17<<24) /* Same as texld but biases the
+ * computed LOD by w. Only S4.6 two's
+ * comp is used. This implies that a
+ * float to fixed conversion is
+ * done. */
+#define T0_TEXKILL (0x18<<24) /* Does not perform a sampling
+ * operation. Simply kills the pixel
+ * if any channel of the address
+ * register is < 0.0. */
+#define T0_DEST_TYPE_SHIFT 19
+/* Allow: R, OC, OD, U */
+/* Note: U (unpreserved) regs do not retain their values between
+ * phases (cannot be used for feedback)
+ *
+ * Note: oC and OD registers can only be used as the destination of a
+ * texture instruction once per phase (this is an implementation
+ * restriction).
+ */
+#define T0_DEST_NR_SHIFT 14
+/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
+#define T0_SAMPLER_NR_SHIFT 0 /* This field ignored for TEXKILL */
+#define T0_SAMPLER_NR_MASK (0xf<<0)
+
+#define T1_ADDRESS_REG_TYPE_SHIFT 24 /* Reg to use as texture coord */
+/* Allow R, T, OC, OD -- R, OC, OD are 'dependent' reads, new program phase */
+#define T1_ADDRESS_REG_NR_SHIFT 17
+#define T2_MBZ 0
+
+
+/* Having zero and one in here makes the definition of swizzle a lot
+ * easier.
+ */
+#define UREG_TYPE_SHIFT 29
+#define UREG_NR_SHIFT 24
+#define UREG_CHANNEL_X_NEGATE_SHIFT 23
+#define UREG_CHANNEL_X_SHIFT 20
+#define UREG_CHANNEL_Y_NEGATE_SHIFT 19
+#define UREG_CHANNEL_Y_SHIFT 16
+#define UREG_CHANNEL_Z_NEGATE_SHIFT 15
+#define UREG_CHANNEL_Z_SHIFT 12
+#define UREG_CHANNEL_W_NEGATE_SHIFT 11
+#define UREG_CHANNEL_W_SHIFT 8
+#define UREG_CHANNEL_ZERO_NEGATE_MBZ 5
+#define UREG_CHANNEL_ZERO_SHIFT 4
+#define UREG_CHANNEL_ONE_NEGATE_MBZ 1
+#define UREG_CHANNEL_ONE_SHIFT 0
+
+#define UREG_BAD 0xffffffff /* not a valid ureg */
+
+#define X SRC_X
+#define Y SRC_Y
+#define Z SRC_Z
+#define W SRC_W
+#define ZERO SRC_ZERO
+#define ONE SRC_ONE
+
+/* Construct a ureg:
+ */
+#define UREG(type, nr) (((type) << UREG_TYPE_SHIFT) | \
+ ((nr) << UREG_NR_SHIFT) | \
+ (X << UREG_CHANNEL_X_SHIFT) | \
+ (Y << UREG_CHANNEL_Y_SHIFT) | \
+ (Z << UREG_CHANNEL_Z_SHIFT) | \
+ (W << UREG_CHANNEL_W_SHIFT) | \
+ (ZERO << UREG_CHANNEL_ZERO_SHIFT) | \
+ (ONE << UREG_CHANNEL_ONE_SHIFT))
+
+#define GET_CHANNEL_SRC( reg, channel ) ((reg<<(channel*4)) & (0xf<<20))
+#define CHANNEL_SRC( src, channel ) (src>>(channel*4))
+
+#define GET_UREG_TYPE(reg) (((reg)>>UREG_TYPE_SHIFT)&REG_TYPE_MASK)
+#define GET_UREG_NR(reg) (((reg)>>UREG_NR_SHIFT)&REG_NR_MASK)
+
+#define UREG_XYZW_CHANNEL_MASK 0x00ffff00
+
+#define A0_DEST(reg) (((reg) & UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT)
+#define D0_DEST(reg) (((reg) & UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT)
+#define T0_DEST(reg) (((reg) & UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT)
+#define A0_SRC0(reg) (((reg) & UREG_MASK)>>UREG_A0_SRC0_SHIFT_LEFT)
+#define A1_SRC0(reg) (((reg) & UREG_MASK)<<UREG_A1_SRC0_SHIFT_RIGHT)
+#define A1_SRC1(reg) (((reg) & UREG_MASK)>>UREG_A1_SRC1_SHIFT_LEFT)
+#define A2_SRC1(reg) (((reg) & UREG_MASK)<<UREG_A2_SRC1_SHIFT_RIGHT)
+#define A2_SRC2(reg) (((reg) & UREG_MASK)>>UREG_A2_SRC2_SHIFT_LEFT)
+
+/* These are special, and don't have swizzle/negate bits.
+ */
+#define T0_SAMPLER( reg ) (GET_UREG_NR(reg)<<T0_SAMPLER_NR_SHIFT)
+#define T1_ADDRESS_REG( reg ) ((GET_UREG_NR(reg)<<T1_ADDRESS_REG_NR_SHIFT) | \
+ (GET_UREG_TYPE(reg)<<T1_ADDRESS_REG_TYPE_SHIFT))
+
+
+/* Macros for translating UREG's into the various register fields used
+ * by the I915 programmable unit.
+ */
+#define UREG_A0_DEST_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_DEST_TYPE_SHIFT)
+#define UREG_A0_SRC0_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_SRC0_TYPE_SHIFT)
+#define UREG_A1_SRC0_SHIFT_RIGHT (A1_SRC0_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT)
+#define UREG_A1_SRC1_SHIFT_LEFT (UREG_TYPE_SHIFT - A1_SRC1_TYPE_SHIFT)
+#define UREG_A2_SRC1_SHIFT_RIGHT (A2_SRC1_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT)
+#define UREG_A2_SRC2_SHIFT_LEFT (UREG_TYPE_SHIFT - A2_SRC2_TYPE_SHIFT)
+
+#define UREG_MASK 0xffffff00
+#define UREG_TYPE_NR_MASK ((REG_TYPE_MASK << UREG_TYPE_SHIFT) | \
+ (REG_NR_MASK << UREG_NR_SHIFT))
+
+#endif
diff --git a/src/xvmc/i915_structs.h b/src/xvmc/i915_structs.h
new file mode 100644
index 00000000..c9545afb
--- /dev/null
+++ b/src/xvmc/i915_structs.h
@@ -0,0 +1,898 @@
+#ifndef _I915_STRUCTS_H
+#define _I915_STRUCTS_H
+
+/* MI_INSTRUCTION */
+#define CMD_MI 0x00
+
+#define OPC_MI_FLUSH (0x04)
+
+struct i915_mi_flush
+{
+ struct {
+ unsigned map_cache_invalidate : 1;
+ unsigned pad0 : 1;
+ unsigned render_cache_flush_inhibit : 1;
+ unsigned scene_count : 1;
+ unsigned end_scene : 1;
+ unsigned pad1 : 18;
+ unsigned opcode : 6;
+ unsigned type : 3;
+ } dw0;
+};
+
+/* 3D_INSTRUCTION */
+#define CMD_3D 0x03
+
+#define OPC_3DMPEG_MACROBLOCK_IPICTURE (0x01 + (0x1e << 5))
+#define OPC_3DMPEG_SET_ORIGIN (0x10 + (0x1e << 5))
+#define OPC_3DMPEG_MACROBLOCK (0x11 + (0x1e << 5))
+#define OPC_3DMPEG_SLICE (0x12 + (0x1e << 5))
+#define OPC_3DMPEG_QM_PALETTE_LOAD (0x13 + (0x1e << 5))
+
+#define OPC_3DSTATE_MAP_STATE (0x00 + (0x1d << 8))
+#define OPC_3DSTATE_SAMPLER_STATE (0x01 + (0x1d << 8))
+#define OPC_3DSTATE_LOAD_STATE_IMMEDIATE_1 (0x04 + (0x1d << 8))
+#define OPC_3DSTATE_PIXEL_SHADER_PROGRAM (0x05 + (0x1d << 8))
+#define OPC_3DSTATE_PIXEL_SHADER_CONSTANTS (0x06 + (0x1d << 8))
+#define OPC_3DSTATE_LOAD_INDIRECT (0x07 + (0x1d << 8))
+
+#define OPC_3DPRIMITIVE (0x1f)
+
+#define OPC_3DSTATE_SCISSOR_RECTANGLE (0x81 + (0x1d << 8))
+#define OPC_3DSTATE_DEST_BUFFER_VARIABLES (0x85 + (0x1d << 8))
+#define OPC_3DSTATE_DEST_BUFFER_VARIABLES_MPEG (0x87 + (0x1d << 8))
+#define OPC_3DSTATE_BUFFER_INFO (0x8e + (0x1d << 8))
+
+/*
+ * 3DMPEG instructions
+ */
+struct i915_3dmpeg_macroblock_header
+{
+ struct {
+ unsigned length : 19;
+ unsigned opcode : 10;
+ unsigned type : 3;
+ } dw0;
+
+ struct {
+ unsigned intra : 1;
+ unsigned forward : 1;
+ unsigned backward : 1;
+ unsigned h263_4mv : 1;
+ unsigned pad0 : 1;
+ unsigned dct_type : 1;
+ unsigned pad1 : 2;
+ unsigned motion_type : 2;
+ unsigned pad2 : 2;
+ unsigned vertical_field_select : 4;
+ unsigned coded_block_pattern : 6;
+ unsigned pad3 : 2;
+ unsigned skipped_macroblocks : 7;
+ unsigned pad4 : 1;
+ } dw1;
+};
+
+struct i915_3dmpeg_macroblock_0mv
+{
+ struct i915_3dmpeg_macroblock_header header;
+};
+
+struct i915_3dmpeg_macroblock_1fbmv
+{
+ struct i915_3dmpeg_macroblock_header header;
+ unsigned dw2;
+ unsigned dw3;
+};
+struct i915_3dmpeg_macroblock_2fbmv
+{
+ struct i915_3dmpeg_macroblock_header header;
+ unsigned dw2;
+ unsigned dw3;
+ unsigned dw4;
+ unsigned dw5;
+};
+
+struct i915_3dmpeg_macroblock_5fmv
+{
+ struct i915_3dmpeg_macroblock_header header;
+ unsigned dw2;
+ unsigned dw3;
+ unsigned dw4;
+ unsigned dw5;
+ unsigned dw6;
+};
+
+struct i915_3dmpeg_macroblock_ipicture
+{
+ struct {
+ unsigned pad0 : 5;
+ unsigned dct_type : 1;
+ unsigned pad1 : 13;
+ unsigned opcode : 10;
+ unsigned type : 3;
+ } dw0;
+};
+
+struct i915_3dmpeg_set_origin
+{
+ struct {
+ unsigned length : 19;
+ unsigned opcode : 10;
+ unsigned type : 3;
+ } dw0;
+
+ struct {
+ unsigned v_origin : 7;
+ unsigned pad0 : 1;
+ unsigned h_origin : 7;
+ unsigned pad1 : 17;
+ } dw1;
+};
+
+struct i915_3dmpeg_slice
+{
+ struct {
+ unsigned length : 19;
+ unsigned opcode : 10;
+ unsigned type : 3;
+ } dw0;
+
+ struct {
+ unsigned fst_mb_bit_off : 3;
+ unsigned pad0 : 5;
+ unsigned mb_count : 7;
+ unsigned pad1 : 1;
+ unsigned v_position : 7;
+ unsigned pad2 : 1;
+ unsigned h_position : 7;
+ unsigned pad3 : 1;
+ } dw1;
+
+ struct {
+ unsigned length_minus_one : 17;
+ unsigned pad0 : 7;
+ unsigned qt_scale_code : 5;
+ unsigned pad1 : 3;
+ } dw2;
+};
+
+struct i915_3dmpeg_qm_palette_load
+{
+ struct {
+ unsigned length : 4;
+ unsigned pad0 : 15;
+ unsigned opcode : 10;
+ unsigned type : 3;
+ } dw0;
+
+ unsigned quantmatrix[16];
+};
+
+
+/*
+ * 3DSTATE instruction
+ */
+#define BUFFERID_COLOR_BACK 3
+#define BUFFERID_COLOR_AUX 4
+#define BUFFERID_MC_INTRA_CORR 5
+
+#define TILEWALK_XMAJOR 0
+#define TILEWALK_YMAJOR 1
+
+struct i915_3dstate_buffer_info
+{
+ struct {
+ unsigned length : 16;
+ unsigned opcode : 13;
+ unsigned type : 3;
+ } dw0;
+
+ struct {
+ unsigned pad0 : 2;
+ unsigned pitch : 12;
+ unsigned pad1 : 7;
+ unsigned walk : 1;
+ unsigned tiled_surface : 1;
+ unsigned fence_regs : 1;
+ unsigned buffer_id : 4;
+ unsigned aux_id : 1;
+ unsigned pad2 : 3;
+ } dw1;
+
+ struct {
+ unsigned pad0 : 2;
+ unsigned base_address : 27;
+ unsigned pad1 : 3;
+ } dw2;
+};
+
+#define COLORBUFFER_X1R5G5B5 0x01
+#define COLORBUFFER_R5G6B5 0x02
+#define COLORBUFFER_A8R8G8B8 0x03
+#define COLORBUFFER_YCRCB_SWAP 0x04
+#define COLORBUFFER_YCRCB_NORMAL 0x05
+#define COLORBUFFER_YCRCB_SWAPUV 0x06
+#define COLORBUFFER_YCRCB_SWAPUVY 0x07
+#define COLORBUFFER_A4R4G4B4 0x08
+#define COLORBUFFER_A1R5G5B5 0x09
+#define COLORBUFFER_A2R10G10B10 0x0a
+
+
+struct i915_3dstate_dest_buffer_variables
+{
+ struct {
+ unsigned length : 16;
+ unsigned opcode : 13;
+ unsigned type : 3;
+ } dw0;
+
+ struct {
+ unsigned v_ls_offset : 1;
+ unsigned v_ls : 1;
+ unsigned depth_fmt : 2;
+ unsigned pad0 : 4;
+ unsigned color_fmt : 4;
+ unsigned yuv422_select : 3;
+ unsigned pad1 : 1;
+ unsigned dest_v_bias : 4;
+ unsigned dest_h_bias : 4;
+ unsigned dither_enhancement : 1;
+ unsigned linear_gamma : 1;
+ unsigned dither_pattern : 2;
+ unsigned lod_preclamp : 1;
+ unsigned edt_zone : 1; /* early depth test in zone rendering */
+ unsigned texture_default_color : 1;
+ unsigned edt_classic : 1; /* early depth test in classic mode */
+ } dw1;
+};
+
+#define MPEG_DECODE_MC 0
+#define MPEG_DECODE_VLD_IDCT_MC 1
+
+#define MPEG_I_PICTURE 1
+#define MPEG_P_PICTURE 2
+#define MPEG_B_PICTURE 3
+
+struct i915_3dstate_dest_buffer_variables_mpeg
+{
+ struct {
+ unsigned length : 16;
+ unsigned opcode : 13;
+ unsigned type : 3;
+ } dw0;
+
+ struct {
+ unsigned picture_width : 7;
+ unsigned pad0 : 1;
+ unsigned v_subsample_factor : 2;
+ unsigned h_subsample_factor : 2;
+ unsigned tff : 1;
+ unsigned mismatch : 1;
+ unsigned pad1 : 1;
+ unsigned intra8 : 1;
+ unsigned abort_on_error : 8;
+ unsigned pad2 : 4;
+ unsigned bidir_avrg_control : 1;
+ unsigned rcontrol : 1;
+ unsigned decoder_mode : 2;
+ } dw1;
+
+ struct {
+ unsigned pad0 : 1;
+ unsigned picture_coding_type : 2;
+ unsigned pad1 : 2;
+ unsigned scan_order : 1;
+ unsigned pad2 : 2;
+ unsigned q_scale_type : 1;
+ unsigned concealment : 1;
+ unsigned fpf_dct : 1;
+ unsigned pad3 : 2;
+ unsigned intra_dc : 2;
+ unsigned intra_vlc : 1;
+ unsigned f_code00 : 4;
+ unsigned f_code01 : 4;
+ unsigned f_code10 : 4;
+ unsigned f_code11 : 4;
+ } dw2;
+};
+
+#define MAP_MAP0 0x0001
+#define MAP_MAP1 0x0002
+#define MAP_MAP2 0x0004
+#define MAP_MAP3 0x0008
+#define MAP_MAP4 0x0010
+#define MAP_MAP5 0x0020
+#define MAP_MAP6 0x0040
+#define MAP_MAP7 0x0080
+#define MAP_MAP8 0x0100
+#define MAP_MAP9 0x0200
+#define MAP_MAP10 0x0400
+#define MAP_MAP11 0x0800
+#define MAP_MAP12 0x1000
+#define MAP_MAP13 0x2000
+#define MAP_MAP14 0x4000
+#define MAP_MAP15 0x8000
+
+struct texture_map
+{
+ struct {
+ unsigned v_ls_offset : 1;
+ unsigned v_ls : 1;
+ unsigned base_address : 27;
+ unsigned pad0 : 2;
+ unsigned untrusted : 1;
+ } tm0;
+
+ struct {
+ unsigned tile_walk : 1;
+ unsigned tiled_surface : 1;
+ unsigned utilize_fence_regs : 1;
+ unsigned texel_fmt : 4;
+ unsigned surface_fmt : 3;
+ unsigned width : 11;
+ unsigned height : 11;
+ } tm1;
+
+ struct {
+ unsigned depth : 8;
+ unsigned mipmap_layout : 1;
+ unsigned max_lod : 6;
+ unsigned cube_face : 6;
+ unsigned pitch : 11;
+ } tm2;
+};
+
+struct i915_3dstate_map_state
+{
+ struct {
+ unsigned length : 6;
+ unsigned pad0 : 9;
+ unsigned retain : 1;
+ unsigned opcode : 13;
+ unsigned type : 3;
+ } dw0;
+
+ struct {
+ unsigned pad0 : 16;
+ unsigned map_mask : 16;
+ } dw1;
+// struct texture_map *tms;
+};
+
+#define SAMPLER_SAMPLER0 0x0001
+#define SAMPLER_SAMPLER1 0x0002
+#define SAMPLER_SAMPLER2 0x0004
+#define SAMPLER_SAMPLER3 0x0008
+#define SAMPLER_SAMPLER4 0x0010
+#define SAMPLER_SAMPLER5 0x0020
+#define SAMPLER_SAMPLER6 0x0040
+#define SAMPLER_SAMPLER7 0x0080
+#define SAMPLER_SAMPLER8 0x0100
+#define SAMPLER_SAMPLER9 0x0200
+#define SAMPLER_SAMPLER10 0x0400
+#define SAMPLER_SAMPLER11 0x0800
+#define SAMPLER_SAMPLER12 0x1000
+#define SAMPLER_SAMPLER13 0x2000
+#define SAMPLER_SAMPLER14 0x4000
+#define SAMPLER_SAMPLER15 0x8000
+
+#define MIPFILTER_NONE 0
+#define MIPFILTER_NEAREST 1
+#define MIPFILTER_LINEAR 3
+
+#define MAPFILTER_NEAREST 0
+#define MAPFILTER_LINEAR 1
+#define MAPFILTER_ANISOTROPIC 2
+#define MAPFILTER_4X4_1 3
+#define MAPFILTER_4X4_2 4
+#define MAPFILTER_4X4_FLAT 5
+#define MAPFILTER_MONO 6
+
+#define ANISORATIO_2 0
+#define ANISORATIO_4 1
+
+#define PREFILTEROP_ALWAYS 0
+#define PREFILTEROP_NEVER 1
+#define PREFILTEROP_LESS 2
+#define PREFILTEROP_EQUAL 3
+#define PREFILTEROP_LEQUAL 4
+#define PREFILTEROP_GREATER 5
+#define PREFILTEROP_NOTEQUAL 6
+#define PREFILTEROP_GEQUAL 7
+
+#define TEXCOORDMODE_WRAP 0
+#define TEXCOORDMODE_MIRROR 1
+#define TEXCOORDMODE_CLAMP 2
+#define TEXCOORDMODE_CUBE 3
+#define TEXCOORDMODE_CLAMP_BORDER 4
+#define TEXCOORDMODE_MIRROR_ONCE 5
+
+struct texture_sampler
+{
+ struct {
+ unsigned shadow_function : 3;
+ unsigned max_anisotropy : 1;
+ unsigned shadow_enable : 1;
+ unsigned lod_bias : 9;
+ unsigned min_filter : 3;
+ unsigned mag_filter : 3;
+ unsigned mip_filter : 2;
+ unsigned base_level : 5;
+ unsigned chromakey_index : 2;
+ unsigned color_conversion : 1;
+ unsigned planar2packet : 1;
+ unsigned reverse_gamma : 1;
+ } ts0;
+
+ struct {
+ unsigned east_deinterlacer : 1;
+ unsigned map_index : 4;
+ unsigned normalized_coor : 1;
+ unsigned tcz_control : 3;
+ unsigned tcy_control : 3;
+ unsigned tcx_control : 3;
+ unsigned chromakey_enable : 1;
+ unsigned keyed_texture_filter : 1;
+ unsigned kill_pixel : 1;
+ unsigned pad0 : 6;
+ unsigned min_lod : 8;
+ } ts1;
+
+ struct {
+ unsigned default_color;
+ } ts2;
+};
+
+struct i915_3dstate_sampler_state
+{
+ struct {
+ unsigned length : 6;
+ unsigned pad0 : 10;
+ unsigned opcode : 13;
+ unsigned type : 3;
+ } dw0;
+
+ struct {
+ unsigned sampler_masker : 16;
+ unsigned pad0 : 16;
+ } dw1;
+};
+
+struct arithmetic_inst
+{
+ struct {
+ unsigned pad0 : 2;
+ unsigned src0_reg : 5;
+ unsigned src0_reg_t : 3;
+ unsigned dest_channel_mask : 4;
+ unsigned dest_reg : 4;
+ unsigned pad1 : 1;
+ unsigned dest_reg_t: 3;
+ unsigned dest_saturate : 1;
+ unsigned pad2 : 1;
+ unsigned opcode : 5;
+ unsigned pad3 : 3;
+ } dw0;
+
+ struct {
+ unsigned src1_y_select : 3;
+ unsigned src1_y_negate : 1;
+ unsigned src1_x_select : 3;
+ unsigned src1_x_negate : 1;
+ unsigned src1_reg : 5;
+ unsigned src1_reg_t : 3;
+ unsigned src0_w_select : 3;
+ unsigned src0_w_negate : 1;
+ unsigned src0_z_select : 3;
+ unsigned src0_z_negate : 1;
+ unsigned src0_y_select : 3;
+ unsigned src0_y_negate : 1;
+ unsigned src0_x_select : 3;
+ unsigned src0_x_negate : 1;
+ } dw1;
+
+ struct {
+ unsigned src2_w_select : 3;
+ unsigned src2_w_negate : 1;
+ unsigned src2_z_select : 3;
+ unsigned src2_z_negate : 1;
+ unsigned src2_y_select : 3;
+ unsigned src2_y_negate : 1;
+ unsigned src2_x_select : 3;
+ unsigned src2_x_negate : 1;
+ unsigned src2_reg : 5;
+ unsigned src2_reg_t : 3;
+ unsigned src1_w_select : 3;
+ unsigned src1_w_negate : 1;
+ unsigned src1_z_select : 3;
+ unsigned src1_z_negate : 1;
+ } dw2;
+};
+
+struct texture_inst
+{
+ struct {
+ unsigned sampler_reg : 4;
+ unsigned pad0 : 10;
+ unsigned dest_reg : 4;
+ unsigned pad1 : 1;
+ unsigned dest_reg_t : 3;
+ unsigned pad2 : 2;
+ unsigned opcode : 5;
+ unsigned pad3 : 3;
+ } dw0;
+
+ struct {
+ unsigned pad0 : 16;
+ unsigned address_reg : 5;
+ unsigned pad1 : 3;
+ unsigned address_reg_t : 3;
+ unsigned pad2 : 5;
+ } dw1;
+
+ struct {
+ unsigned pad0;
+ } dw2;
+};
+
+struct declaration_inst
+{
+ struct {
+ unsigned pad0 : 10;
+ unsigned decl_channel_mask : 4;
+ unsigned decl_reg : 4;
+ unsigned pad1 : 1;
+ unsigned decl_reg_t : 2;
+ unsigned pad2 : 1;
+ unsigned sampler_type : 2;
+ unsigned opcode : 5;
+ unsigned pad3 : 3;
+ } dw0;
+
+ struct {
+ unsigned pad0;
+ } dw1;
+
+ struct {
+ unsigned pad0;
+ } dw2;
+};
+
+union shader_inst
+{
+ struct arithmetic_inst a;
+ struct texture_inst t;
+ struct declaration_inst d;
+};
+
+struct i915_3dstate_pixel_shader_program
+{
+ struct {
+ unsigned length : 9;
+ unsigned pad0 : 6;
+ unsigned retain : 1;
+ unsigned opcode : 13;
+ unsigned type : 3;
+ } dw0;
+
+ // union shader_inst *insts;
+};
+
+#define REG_CR0 0x00000001
+#define REG_CR1 0x00000002
+#define REG_CR2 0x00000004
+#define REG_CR3 0x00000008
+#define REG_CR4 0x00000010
+#define REG_CR5 0x00000020
+#define REG_CR6 0x00000040
+#define REG_CR7 0x00000080
+#define REG_CR8 0x00000100
+#define REG_CR9 0x00000200
+#define REG_CR10 0x00000400
+#define REG_CR11 0x00000800
+#define REG_CR12 0x00001000
+#define REG_CR13 0x00002000
+#define REG_CR14 0x00004000
+#define REG_CR15 0x00008000
+#define REG_CR16 0x00010000
+#define REG_CR17 0x00020000
+#define REG_CR18 0x00040000
+#define REG_CR19 0x00080000
+#define REG_CR20 0x00100000
+#define REG_CR21 0x00200000
+#define REG_CR22 0x00400000
+#define REG_CR23 0x00800000
+#define REG_CR24 0x01000000
+#define REG_CR25 0x02000000
+#define REG_CR26 0x04000000
+#define REG_CR27 0x08000000
+#define REG_CR28 0x10000000
+#define REG_CR29 0x20000000
+#define REG_CR30 0x40000000
+#define REG_CR31 0x80000000
+
+struct shader_constant
+{
+ float x;
+ float y;
+ float z;
+ float w;
+};
+
+struct i915_3dstate_pixel_shader_constants
+{
+ struct {
+ unsigned length : 8;
+ unsigned pad0 : 8;
+ unsigned opcode : 13;
+ unsigned type : 3;
+ } dw0;
+
+ struct {
+ unsigned reg_mask;
+ } dw1;
+ // struct shader_constant *consts;
+};
+
+#define BLOCK_SIS 0x01
+#define BLOCK_DIS 0x02
+#define BLOCK_SSB 0x04
+#define BLOCK_MSB 0x08
+#define BLOCK_PSP 0x10
+#define BLOCK_PSC 0x20
+
+typedef struct _state_ddword
+{
+ struct {
+ unsigned valid : 1;
+ unsigned force : 1;
+ unsigned buffer_address : 30;
+ } dw0;
+
+ struct {
+ unsigned length : 9;
+ unsigned pad0 : 23;
+ } dw1;
+} sis_state, ssb_state, msb_state, psp_state, psc_state;
+
+typedef struct _state_dword
+{
+ struct {
+ unsigned valid : 1;
+ unsigned reset : 1;
+ unsigned buffer_address : 30;
+ } dw0;
+} dis_state;
+
+struct i915_3dstate_load_indirect
+{
+ struct {
+ unsigned length : 8;
+ unsigned block_mask : 6;
+ unsigned mem_select : 1;
+ unsigned pad0 : 1;
+ unsigned opcode : 13;
+ unsigned type : 3;
+ } dw0;
+};
+
+#define TEXCOORDFMT_2FP 0x00
+#define TEXCOORDFMT_3FP 0x01
+#define TEXCOORDFMT_4FP 0x02
+#define TEXCOORDFMT_1FP 0x03
+#define TEXCOORDFMT_2FP_16 0x04
+#define TEXCOORDFMT_4FP_16 0x05
+#define TEXCOORDFMT_NOT_PRESENT 0x0f
+struct s2_dword
+{
+ unsigned set0_texcoord_fmt : 4;
+ unsigned set1_texcoord_fmt : 4;
+ unsigned set2_texcoord_fmt : 4;
+ unsigned set3_texcoord_fmt : 4;
+ unsigned set4_texcoord_fmt : 4;
+ unsigned set5_texcoord_fmt : 4;
+ unsigned set6_texcoord_fmt : 4;
+ unsigned set7_texcoord_fmt : 4;
+};
+
+struct s3_dword
+{
+ unsigned set0_pcd : 1;
+ unsigned set0_ws_tcz : 1;
+ unsigned set0_ws_tcy : 1;
+ unsigned set0_ws_tcx : 1;
+ unsigned set1_pcd : 1;
+ unsigned set1_ws_tcz : 1;
+ unsigned set1_ws_tcy : 1;
+ unsigned set1_ws_tcx : 1;
+ unsigned set2_pcd : 1;
+ unsigned set2_ws_tcz : 1;
+ unsigned set2_ws_tcy : 1;
+ unsigned set2_ws_tcx : 1;
+ unsigned set3_pcd : 1;
+ unsigned set3_ws_tcz : 1;
+ unsigned set3_ws_tcy : 1;
+ unsigned set3_ws_tcx : 1;
+ unsigned set4_pcd : 1;
+ unsigned set4_ws_tcz : 1;
+ unsigned set4_ws_tcy : 1;
+ unsigned set4_ws_tcx : 1;
+ unsigned set5_pcd : 1;
+ unsigned set5_ws_tcz : 1;
+ unsigned set5_ws_tcy : 1;
+ unsigned set5_ws_tcx : 1;
+ unsigned set6_pcd : 1;
+ unsigned set6_ws_tcz : 1;
+ unsigned set6_ws_tcy : 1;
+ unsigned set6_ws_tcx : 1;
+ unsigned set7_pcd : 1;
+ unsigned set7_ws_tcz : 1;
+ unsigned set7_ws_tcy : 1;
+ unsigned set7_ws_tcx : 1;
+};
+
+#define VERTEXHAS_XYZ 1
+#define VERTEXHAS_XYZW 2
+#define VERTEXHAS_XY 3
+#define VERTEXHAS_XYW 4
+
+#define CULLMODE_BOTH 0
+#define CULLMODE_NONE 1
+#define CULLMODE_CW 2
+#define CULLMODE_CCW 3
+
+#define SHADEMODE_LINEAR 0
+#define SHADEMODE_FLAT 1
+struct s4_dword
+{
+ unsigned anti_aliasing_enable : 1;
+ unsigned sprite_point_enable : 1;
+ unsigned fog_parameter_present : 1;
+ unsigned local_depth_offset_enable : 1;
+ unsigned force_specular_diffuse_color : 1;
+ unsigned force_default_diffuse_color : 1;
+ unsigned position_mask : 3;
+ unsigned local_depth_offset_present : 1;
+ unsigned diffuse_color_presetn : 1;
+ unsigned specular_color_fog_factor_present : 1;
+ unsigned point_width_present : 1;
+ unsigned cull_mode : 2;
+ unsigned color_shade_mode : 1;
+ unsigned specular_shade_mode : 1;
+ unsigned fog_shade_mode : 1;
+ unsigned alpha_shade_mode : 1;
+ unsigned line_width : 4;
+ unsigned point_width : 9;
+};
+
+struct s5_dword
+{
+ unsigned logic_op_enable : 1;
+ unsigned color_dither_enable : 1;
+ unsigned stencil_test_enable : 1;
+ unsigned stencil_buffer_write_enable : 1;
+ unsigned stencil_pass_depth_pass_op : 3;
+ unsigned stencil_pass_depth_fail_op : 3;
+ unsigned stencil_fail_op : 3;
+ unsigned stencil_test_function : 3;
+ unsigned stencil_reference_value : 8;
+ unsigned fog_enable : 1;
+ unsigned global_depth_offset_enable : 1;
+ unsigned last_pixel_enable : 1;
+ unsigned force_default_point_width : 1;
+ unsigned color_buffer_component_write_disable : 4;
+};
+
+struct s6_dword
+{
+ unsigned triangle_pv : 2;
+ unsigned color_buffer_write : 1;
+ unsigned depth_buffer_write : 1;
+ unsigned dest_blend_factor : 4;
+ unsigned src_blend_factor : 4;
+ unsigned color_blend_function : 3;
+ unsigned color_buffer_blend : 1;
+ unsigned depth_test_function : 3;
+ unsigned depth_test_enable : 1;
+ unsigned alpha_reference_value : 8;
+ unsigned alpha_test_function : 3;
+ unsigned alpha_test_enable : 1;
+
+};
+
+struct s7_dword
+{
+ unsigned global_depth_offset_const;
+};
+
+struct i915_3dstate_load_state_immediate_1
+{
+ struct {
+ unsigned length : 4;
+ unsigned load_s0 : 1;
+ unsigned load_s1 : 1;
+ unsigned load_s2 : 1;
+ unsigned load_s3 : 1;
+ unsigned load_s4 : 1;
+ unsigned load_s5 : 1;
+ unsigned load_s6 : 1;
+ unsigned load_s7 : 1;
+ unsigned pad0 : 4;
+ unsigned opcode : 13;
+ unsigned type : 3;
+ } dw0;
+};
+
+struct i915_3dstate_scissor_rectangle
+{
+ struct {
+ unsigned length : 16;
+ unsigned opcode : 13;
+ unsigned type : 3;
+ } dw0;
+
+ struct {
+ unsigned min_x : 16;
+ unsigned min_y : 16;
+ } dw1;
+
+ struct {
+ unsigned max_x : 16;
+ unsigned max_y : 16;
+ } dw2;
+};
+
+#define VERTEX_INLINE 0x00
+#define VERTEX_INDIRECT 0x01
+
+#define PRIM_TRILIST 0x00
+#define PRIM_TRISTRIP 0x01
+#define PRIM_TRISTRIP_REVERSE 0x02
+#define PRIM_TRIFAN 0x03
+#define PRIM_POLYGON 0x04
+#define PRIM_LINELIST 0x05
+#define PRIM_LINESTRIP 0x06
+#define PRIM_RECTLIST 0x07
+#define PRIM_POINTLIST 0x08
+#define PRIM_DIB 0x09
+#define PRIM_CLEAR_RECT 0x0a
+#define PRIM_ZONE_INIT 0x0d
+
+struct texture_coordinate_set
+{
+ unsigned tcx;
+ unsigned tcy;
+};
+
+struct vertex_data
+{
+ unsigned x;
+ unsigned y;
+ struct texture_coordinate_set tc0;
+ struct texture_coordinate_set tc1;
+};
+
+struct i915_3dprimitive
+{
+ union {
+ struct {
+ unsigned length : 18;
+ unsigned prim : 5;
+ unsigned vertex_location : 1;
+ unsigned opcode : 5;
+ unsigned type : 3;
+ } inline_prim;
+
+ struct {
+ unsigned vertex_count : 16;
+ unsigned pad0 : 1;
+ unsigned vertex_access_mode : 1;
+ unsigned prim : 5;
+ unsigned vertex_location : 1;
+ unsigned opcode : 5;
+ unsigned type : 3;
+ } indirect_prim;
+ } dw0;
+};
+
+#endif /*_I915_STRUCTS_H */
diff --git a/src/xvmc/intel_batchbuffer.c b/src/xvmc/intel_batchbuffer.c
new file mode 100644
index 00000000..ef38a44a
--- /dev/null
+++ b/src/xvmc/intel_batchbuffer.c
@@ -0,0 +1,197 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+#include <X11/Xlibint.h>
+#include <fourcc.h>
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XvMC.h>
+#include <X11/extensions/XvMClib.h>
+
+#include "I915XvMC.h"
+#include "intel_batchbuffer.h"
+
+int intelEmitIrqLocked(i915XvMCContext *pI915XvMC)
+{
+ drmI830IrqEmit ie;
+ int ret, seq;
+
+ ie.irq_seq = &seq;
+ ret = drmCommandWriteRead(pI915XvMC->fd, DRM_I830_IRQ_EMIT,
+ &ie, sizeof(ie));
+
+ if ( ret ) {
+ fprintf(stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret);
+ exit(1);
+ }
+
+ return seq;
+}
+
+void intelWaitIrq(i915XvMCContext *pI915XvMC, int seq)
+{
+ int ret;
+ drmI830IrqWait iw;
+
+ iw.irq_seq = seq;
+
+ do {
+ ret = drmCommandWrite(pI915XvMC->fd, DRM_I830_IRQ_WAIT, &iw, sizeof(iw) );
+ } while (ret == -EAGAIN || ret == -EINTR);
+
+ if (ret) {
+ fprintf(stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret);
+ exit(1);
+ }
+}
+
+void intelDestroyBatchBuffer(i915XvMCContext *pI915XvMC)
+{
+ if (pI915XvMC->alloc.offset) {
+ // FIXME: free the memory allocated from AGP
+ } else if (pI915XvMC->alloc.ptr) {
+ free(pI915XvMC->alloc.ptr);
+ pI915XvMC->alloc.ptr = NULL;
+ }
+
+ memset(&pI915XvMC->batch, 0, sizeof(pI915XvMC->batch));
+}
+
+
+void intelInitBatchBuffer(i915XvMCContext *pI915XvMC)
+{
+ pI915XvMC->alloc.offset = 0;
+ pI915XvMC->alloc.size = 16 * 1024;
+ pI915XvMC->alloc.ptr = malloc(pI915XvMC->alloc.size);
+ pI915XvMC->alloc.active_buf = 0;
+
+ assert(pI915XvMC->alloc.ptr);
+}
+
+void intelBatchbufferRequireSpace(i915XvMCContext *pI915XvMC, unsigned sz)
+{
+ if (pI915XvMC->batch.space < sz)
+ intelFlushBatch(pI915XvMC, TRUE);
+}
+
+void intelBatchbufferData(i915XvMCContext *pI915XvMC, const void *data,
+ unsigned bytes, unsigned flags)
+{
+ assert((bytes & 3) == 0);
+ intelBatchbufferRequireSpace(pI915XvMC, bytes);
+ memcpy(pI915XvMC->batch.ptr, data, bytes);
+ pI915XvMC->batch.ptr += bytes;
+ pI915XvMC->batch.space -= bytes;
+ assert(pI915XvMC->batch.space >= 0);
+}
+
+void intelRefillBatchLocked(i915XvMCContext *pI915XvMC, Bool allow_unlock )
+{
+ unsigned last_irq = pI915XvMC->alloc.irq_emitted;
+ unsigned half = pI915XvMC->alloc.size >> 1;
+ unsigned buf = (pI915XvMC->alloc.active_buf ^= 1);
+
+ pI915XvMC->alloc.irq_emitted = intelEmitIrqLocked(pI915XvMC);
+
+ if (last_irq) {
+ intelWaitIrq(pI915XvMC, last_irq);
+ }
+
+ pI915XvMC->batch.start_offset = pI915XvMC->alloc.offset + buf * half;
+ pI915XvMC->batch.ptr = (unsigned char *)pI915XvMC->alloc.ptr + buf * half;
+ pI915XvMC->batch.size = half - 8;
+ pI915XvMC->batch.space = half - 8;
+ assert(pI915XvMC->batch.space >= 0);
+}
+
+
+void intelFlushBatchLocked(i915XvMCContext *pI915XvMC,
+ Bool ignore_cliprects,
+ Bool refill,
+ Bool allow_unlock)
+{
+ drmI830BatchBuffer batch;
+
+ if (pI915XvMC->batch.space != pI915XvMC->batch.size) {
+
+ batch.start = pI915XvMC->batch.start_offset;
+ batch.used = pI915XvMC->batch.size - pI915XvMC->batch.space;
+ batch.cliprects = 0;
+ batch.num_cliprects = 0;
+ batch.DR1 = 0;
+ batch.DR4 = 0;
+
+ if (pI915XvMC->alloc.offset) {
+ // FIXME: MI_BATCH_BUFFER_END
+ }
+
+ pI915XvMC->batch.start_offset += batch.used;
+ pI915XvMC->batch.size -= batch.used;
+
+ if (pI915XvMC->batch.size < 8) {
+ refill = TRUE;
+ pI915XvMC->batch.space = pI915XvMC->batch.size = 0;
+ }
+ else {
+ pI915XvMC->batch.size -= 8;
+ pI915XvMC->batch.space = pI915XvMC->batch.size;
+ }
+
+ assert(pI915XvMC->batch.space >= 0);
+ assert(batch.start >= pI915XvMC->alloc.offset);
+ assert(batch.start < pI915XvMC->alloc.offset + pI915XvMC->alloc.size);
+ assert(batch.start + batch.used > pI915XvMC->alloc.offset);
+ assert(batch.start + batch.used <= pI915XvMC->alloc.offset + pI915XvMC->alloc.size);
+
+ if (pI915XvMC->alloc.offset) {
+ // DRM_I830_BATCHBUFFER
+ } else {
+ drmI830CmdBuffer cmd;
+ cmd.buf = (char *)pI915XvMC->alloc.ptr + batch.start;
+ cmd.sz = batch.used;
+ cmd.DR1 = batch.DR1;
+ cmd.DR4 = batch.DR4;
+ cmd.num_cliprects = batch.num_cliprects;
+ cmd.cliprects = batch.cliprects;
+
+ if (drmCommandWrite(pI915XvMC->fd, DRM_I830_CMDBUFFER,
+ &cmd, sizeof(cmd))) {
+ fprintf(stderr, "DRM_I915_CMDBUFFER: %d\n", -errno);
+ exit(1);
+ }
+ }
+ }
+
+ if (refill)
+ intelRefillBatchLocked(pI915XvMC, allow_unlock);
+}
+
+void intelFlushBatch(i915XvMCContext *pI915XvMC, Bool refill )
+{
+ intelFlushBatchLocked(pI915XvMC, FALSE, refill, TRUE);
+}
+
+void intelCmdIoctl(i915XvMCContext *pI915XvMC, char *buf, unsigned used)
+{
+ drmI830CmdBuffer cmd;
+
+ cmd.buf = buf;
+ cmd.sz = used;
+ cmd.cliprects = 0;
+ cmd.num_cliprects = 0;
+ cmd.DR1 = 0;
+ cmd.DR4 = 0;
+
+ if (drmCommandWrite(pI915XvMC->fd, DRM_I830_CMDBUFFER,
+ &cmd, sizeof(cmd))) {
+ fprintf(stderr, "DRM_I830_CMDBUFFER: %d\n", -errno);
+ exit(1);
+ }
+}
diff --git a/src/xvmc/intel_batchbuffer.h b/src/xvmc/intel_batchbuffer.h
new file mode 100644
index 00000000..5b3e8e1b
--- /dev/null
+++ b/src/xvmc/intel_batchbuffer.h
@@ -0,0 +1,42 @@
+#ifndef _INTEL_BATCHBUFFER_H
+#define _INTEL_BATCHBUFFER_H
+
+/* #define VERBOSE 0 */
+#ifndef VERBOSE
+extern int VERBOSE;
+#endif
+
+#define BATCH_LOCALS char *batch_ptr;
+
+#define BEGIN_BATCH(n) \
+ do { \
+ if (VERBOSE) fprintf(stderr, \
+ "BEGIN_BATCH(%ld) in %s, %d dwords free\n", \
+ ((unsigned long)n), __FUNCTION__, \
+ pI915XvMC->batch.space/4); \
+ if (pI915XvMC->batch.space < (n)*4) \
+ intelFlushBatch(pI915XvMC, TRUE); \
+ batch_ptr = pI915XvMC->batch.ptr; \
+ } while (0)
+
+#define OUT_BATCH(n) \
+ do { \
+ *(GLuint *)batch_ptr = (n); \
+ if (VERBOSE) fprintf(stderr, " -- %08x at %s/%d\n", (n), __FILE__, __LINE__); \
+ batch_ptr += 4; \
+ } while (0)
+
+#define ADVANCE_BATCH() \
+ do { \
+ if (VERBOSE) fprintf(stderr, "ADVANCE_BATCH()\n"); \
+ pI915XvMC->batch.space -= (batch_ptr - pI915XvMC->batch.ptr); \
+ pI915XvMC->batch.ptr = batch_ptr; \
+ assert(pI915XvMC->batch.space >= 0); \
+ } while(0)
+
+extern void intelFlushBatch(i915XvMCContext *, Bool);
+extern void intelBatchbufferData(i915XvMCContext *, const void *, unsigned, unsigned);
+extern void intelInitBatchBuffer(i915XvMCContext *);
+extern void intelDestroyBatchBuffer(i915XvMCContext *);
+extern void intelCmdIoctl(i915XvMCContext *, char *, unsigned);
+#endif /* _INTEL_BATCHBUFFER_H */
diff --git a/src/xvmc/xf86dri.c b/src/xvmc/xf86dri.c
new file mode 100644
index 00000000..1feb2329
--- /dev/null
+++ b/src/xvmc/xf86dri.c
@@ -0,0 +1,599 @@
+/* $XFree86: xc/lib/GL/dri/XF86dri.c,v 1.13 2002/10/30 12:51:25 alanh Exp $ */
+/**************************************************************************
+
+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 */
+
+#define NEED_REPLIES
+#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 uniDRICheckExtension(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,"uniDRI%s\n", msg);
+#else
+#define TRACE(msg)
+#endif
+ Bool uniDRIQueryExtension(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;
+ }
+}
+
+Bool
+uniDRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion)
+ Display *dpy;
+ int *majorVersion;
+ int *minorVersion;
+ int *patchVersion;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIQueryVersionReply rep;
+ xXF86DRIQueryVersionReq *req;
+
+ TRACE("QueryVersion...");
+ uniDRICheckExtension(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;
+}
+
+Bool
+uniDRIQueryDirectRenderingCapable(dpy, screen, isCapable)
+ Display *dpy;
+ int screen;
+ Bool *isCapable;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIQueryDirectRenderingCapableReply rep;
+ xXF86DRIQueryDirectRenderingCapableReq *req;
+
+ TRACE("QueryDirectRenderingCapable...");
+ uniDRICheckExtension(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;
+}
+
+Bool
+uniDRIOpenConnection(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...");
+ uniDRICheckExtension(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;
+#ifdef LONG64
+ if (sizeof(drm_handle_t) == 8) {
+ *hSAREA |= ((unsigned long)rep.hSAREAHigh) << 32;
+ }
+#endif
+ 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;
+}
+
+Bool
+uniDRIAuthConnection(dpy, screen, magic)
+ Display *dpy;
+ int screen;
+ drm_magic_t magic;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIAuthConnectionReq *req;
+ xXF86DRIAuthConnectionReply rep;
+
+ TRACE("AuthConnection...");
+ uniDRICheckExtension(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;
+}
+
+Bool
+uniDRICloseConnection(dpy, screen)
+ Display *dpy;
+ int screen;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRICloseConnectionReq *req;
+
+ TRACE("CloseConnection...");
+
+ uniDRICheckExtension(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;
+}
+
+Bool
+uniDRIGetClientDriverName(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...");
+ uniDRICheckExtension(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;
+}
+
+Bool
+uniDRICreateContextWithConfig(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...");
+ uniDRICheckExtension(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;
+}
+
+Bool
+uniDRICreateContext(dpy, screen, visual, context, hHWContext)
+ Display *dpy;
+ int screen;
+ Visual *visual;
+ XID *context;
+ drm_context_t *hHWContext;
+{
+ return uniDRICreateContextWithConfig(dpy, screen, visual->visualid,
+ context, hHWContext);
+}
+
+Bool
+uniDRIDestroyContext(Display * ndpy, int screen, XID context)
+{
+ Display *const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIDestroyContextReq *req;
+
+ TRACE("DestroyContext...");
+ uniDRICheckExtension(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;
+}
+
+Bool
+uniDRICreateDrawable(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...");
+ uniDRICheckExtension(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;
+}
+
+Bool
+uniDRIDestroyDrawable(Display * ndpy, int screen, Drawable drawable)
+{
+ Display *const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIDestroyDrawableReq *req;
+
+ TRACE("DestroyDrawable...");
+ uniDRICheckExtension(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;
+}
+
+Bool
+uniDRIGetDrawableInfo(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...");
+ uniDRICheckExtension(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;
+}
+
+Bool
+uniDRIGetDeviceInfo(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...");
+ uniDRICheckExtension(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;
+#ifdef LONG64
+ if (sizeof(drm_handle_t) == 8) {
+ *hFrameBuffer |= ((unsigned long)rep.hFrameBufferHigh) << 32;
+ }
+#endif
+
+ *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;
+}
diff --git a/src/xvmc/xf86dri.h b/src/xvmc/xf86dri.h
new file mode 100644
index 00000000..d7580a1b
--- /dev/null
+++ b/src/xvmc/xf86dri.h
@@ -0,0 +1,109 @@
+/* $XFree86: xc/lib/GL/dri/xf86dri.h,v 1.8 2002/10/30 12:51:25 alanh Exp $ */
+/**************************************************************************
+
+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 uniDRIQueryExtension(Display * dpy, int *event_base,
+ int *error_base);
+
+Bool uniDRIQueryVersion(Display * dpy, int *majorVersion, int *minorVersion,
+ int *patchVersion);
+
+Bool uniDRIQueryDirectRenderingCapable(Display * dpy, int screen,
+ Bool * isCapable);
+
+Bool uniDRIOpenConnection(Display * dpy, int screen, drm_handle_t * hSAREA,
+ char **busIDString);
+
+Bool uniDRIAuthConnection(Display * dpy, int screen, drm_magic_t magic);
+
+Bool uniDRICloseConnection(Display * dpy, int screen);
+
+Bool uniDRIGetClientDriverName(Display * dpy, int screen,
+ int *ddxDriverMajorVersion, int *ddxDriverMinorVersion,
+ int *ddxDriverPatchVersion, char **clientDriverName);
+
+Bool uniDRICreateContext(Display * dpy, int screen, Visual * visual,
+ XID * ptr_to_returned_context_id, drm_context_t * hHWContext);
+
+Bool uniDRICreateContextWithConfig(Display * dpy, int screen, int configID,
+ XID * ptr_to_returned_context_id, drm_context_t * hHWContext);
+
+extern Bool uniDRIDestroyContext(Display * dpy, int screen, XID context_id);
+
+extern Bool uniDRICreateDrawable(Display * dpy, int screen,
+ Drawable drawable, drm_drawable_t * hHWDrawable);
+
+extern Bool uniDRIDestroyDrawable(Display * dpy, int screen,
+ Drawable drawable);
+
+Bool uniDRIGetDeviceInfo(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/xvmc/xf86dristr.h b/src/xvmc/xf86dristr.h
new file mode 100644
index 00000000..3b43438e
--- /dev/null
+++ b/src/xvmc/xf86dristr.h
@@ -0,0 +1,390 @@
+/* $XFree86: xc/lib/GL/dri/xf86dristr.h,v 1.10 2002/10/30 12:51:25 alanh Exp $ */
+/**************************************************************************
+
+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_ */