diff options
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/i830.h | 15 | ||||
-rw-r--r-- | src/i830_driver.c | 6 | ||||
-rw-r--r-- | src/i830_memory.c | 38 | ||||
-rw-r--r-- | src/i830_video.c | 17 | ||||
-rw-r--r-- | src/i830_video.h | 1 | ||||
-rw-r--r-- | src/i915_hwmc.c | 932 | ||||
-rw-r--r-- | src/i915_hwmc.h | 64 | ||||
-rw-r--r-- | src/xvmc/I915XvMC.c | 3056 | ||||
-rw-r--r-- | src/xvmc/I915XvMC.h | 178 | ||||
-rw-r--r-- | src/xvmc/Makefile.am | 16 | ||||
-rw-r--r-- | src/xvmc/driDrawable.c | 174 | ||||
-rw-r--r-- | src/xvmc/driDrawable.h | 64 | ||||
-rw-r--r-- | src/xvmc/i915_program.h | 276 | ||||
-rw-r--r-- | src/xvmc/i915_structs.h | 898 | ||||
-rw-r--r-- | src/xvmc/intel_batchbuffer.c | 197 | ||||
-rw-r--r-- | src/xvmc/intel_batchbuffer.h | 42 | ||||
-rw-r--r-- | src/xvmc/xf86dri.c | 599 | ||||
-rw-r--r-- | src/xvmc/xf86dri.h | 109 | ||||
-rw-r--r-- | src/xvmc/xf86dristr.h | 390 |
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 = \ @@ -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(¯oblock_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, ¯oblock_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(¯oblock_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, ¯oblock_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(¯oblock_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, ¯oblock_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 = ¯oblock_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, ¯oblock_array->macro_blocks[first_macroblock]); + for (i = first_macroblock; i < (num_macroblocks + first_macroblock); i++) { + mb = ¯oblock_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)®_TYPE_MASK) +#define GET_UREG_NR(reg) (((reg)>>UREG_NR_SHIFT)®_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_ */ |