summaryrefslogtreecommitdiff
path: root/src/i810_hwmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/i810_hwmc.c')
-rw-r--r--src/i810_hwmc.c417
1 files changed, 417 insertions, 0 deletions
diff --git a/src/i810_hwmc.c b/src/i810_hwmc.c
new file mode 100644
index 00000000..525ad361
--- /dev/null
+++ b/src/i810_hwmc.c
@@ -0,0 +1,417 @@
+/***************************************************************************
+
+Copyright 2000 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.
+
+**************************************************************************/
+
+/*
+ * i810_hwmc.c: i810 HWMC Driver
+ *
+ * Authors:
+ * Matt Sottek <matthew.j.sottek@intel.com>
+ *
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_hwmc.c,v 1.4 2002/09/11 00:29:32 dawes Exp $ */
+
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "xf86fbman.h"
+#include "regionstr.h"
+
+#include "i810.h"
+#include "i810_dri.h"
+
+#include "xf86xv.h"
+#include "xf86xvmc.h"
+#include "Xv.h"
+#include "XvMC.h"
+#include "xaa.h"
+#include "xaalocal.h"
+#include "dixstruct.h"
+#include "fourcc.h"
+
+int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
+ int *num_priv, long **priv );
+void I810XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext);
+
+int I810XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf,
+ int *num_priv, long **priv );
+void I810XvMCDestroySurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf);
+
+int I810XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf,
+ int *num_priv, long **priv );
+void I810XvMCDestroySubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf);
+
+
+typedef struct {
+ drmContext drmcontext;
+ unsigned int fbBase;
+ unsigned int OverlayOffset;
+ unsigned int OverlaySize;
+ unsigned int SurfacesOffset;
+ unsigned int SurfacesSize;
+ char busIdString[10];
+ char pad[2];
+} I810XvMCCreateContextRec;
+
+
+static int yv12_subpicture_index_list[2] =
+{
+ FOURCC_IA44,
+ FOURCC_AI44
+};
+
+static XF86MCImageIDList yv12_subpicture_list =
+{
+ 2,
+ yv12_subpicture_index_list
+};
+
+static XF86MCSurfaceInfoRec i810_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 i810_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)&i810_YV12_mpg2_surface,
+ (XF86MCSurfaceInfoPtr)&i810_YV12_mpg1_surface
+};
+
+/* List of subpicture types that we support */
+static XF86ImageRec ia44_subpicture = XVIMAGE_IA44;
+static XF86ImageRec ai44_subpicture = XVIMAGE_AI44;
+
+static XF86ImagePtr i810_subpicture_list[2] =
+{
+ (XF86ImagePtr)&ia44_subpicture,
+ (XF86ImagePtr)&ai44_subpicture
+};
+
+/* Fill in the device dependent adaptor record.
+ * This is named "I810 Video Overlay" 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 =
+{
+ "I810 Video Overlay", /* name */
+ 2, /* num_surfaces */
+ ppSI, /* surfaces */
+ 2, /* num_subpictures */
+ i810_subpicture_list, /* subpictures */
+ (xf86XvMCCreateContextProcPtr)I810XvMCCreateContext,
+ (xf86XvMCDestroyContextProcPtr)I810XvMCDestroyContext,
+ (xf86XvMCCreateSurfaceProcPtr)I810XvMCCreateSurface,
+ (xf86XvMCDestroySurfaceProcPtr)I810XvMCDestroySurface,
+ (xf86XvMCCreateSubpictureProcPtr)I810XvMCCreateSubpicture,
+ (xf86XvMCDestroySubpictureProcPtr)I810XvMCDestroySubpicture
+};
+
+static XF86MCAdaptorPtr ppAdapt[1] =
+{
+ (XF86MCAdaptorPtr)&pAdapt
+};
+
+/**************************************************************************
+ *
+ * I810InitMC
+ *
+ * Initialize the hardware motion compenstation extention for this
+ * hardware. The initialization routines want the address of the pointers
+ * to the structures, not the address of the structures. This means we
+ * allocate (or create static?) the pointer memory and pass that
+ * address. This seems a little convoluted.
+ *
+ * We need to allocate memory for the device depended adaptor record.
+ * This is what holds the pointers to all our device functions.
+ *
+ * We need to map the overlay registers into the drm.
+ *
+ * We need to map the surfaces into the drm.
+ *
+ * Inputs:
+ * Screen pointer
+ *
+ * Outputs:
+ * None, this calls the device independent screen initialization
+ * function.
+ *
+ * Revisions:
+ *
+ **************************************************************************/
+void I810InitMC(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ int i;
+
+ /* Clear the Surface Allocation */
+ for(i=0; i<I810_MAX_SURFACES; i++) {
+ pI810->surfaceAllocation[i] = 0;
+ }
+
+ /* Cursor is at a page boundary, Overlay regs are not, don't forget */
+ if (drmAddMap(pI810->drmSubFD, (drmHandle)pI810->CursorStart,
+ 4096, DRM_AGP, 0, &pI810->overlay_map) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap(overlay) failed\n");
+ return;
+ }
+ if (drmAddMap(pI810->drmSubFD, (drmHandle)pI810->MC.Start,
+ pI810->MC.Size, DRM_AGP, 0, &pI810->mc_map) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap(MC) failed\n");
+ return;
+ }
+ xf86XvMCScreenInit(pScreen, 1, ppAdapt);
+}
+
+/**************************************************************************
+ *
+ * I810XvMCCreateContext
+ *
+ * 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;
+ *
+ **************************************************************************/
+
+int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
+ int *num_priv, long **priv )
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ DRIInfoPtr pDRIInfo = pI810->pDRIInfo;
+ I810XvMCCreateContextRec *contextRec;
+
+
+ if(!pI810->directRenderingEnabled) {
+ xf86DrvMsg(X_ERROR, pScrn->scrnIndex,
+ "I810XvMCCreateContext: Cannot use XvMC without DRI!\n");
+ return BadAlloc;
+ }
+
+ /* Context Already in use! */
+ if(pI810->xvmcContext) {
+ xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+ "I810XvMCCreateContext: 2 XvMC Contexts Attempted, not supported.\n");
+ return BadAlloc;
+ }
+
+ *priv = xcalloc(1,sizeof(I810XvMCCreateContextRec));
+ contextRec = (I810XvMCCreateContextRec *)*priv;
+
+ if(!*priv) {
+ *num_priv = 0;
+ return BadAlloc;
+ }
+
+ *num_priv = sizeof(I810XvMCCreateContextRec) >> 2;
+ if(drmCreateContext(pI810->drmSubFD, &(contextRec->drmcontext) ) < 0) {
+ xf86DrvMsg(X_ERROR, pScrn->scrnIndex,
+ "I810XvMCCreateContext: Unable to create DRMContext!\n");
+ xfree(*priv);
+ return BadAlloc;
+ }
+
+ drmAuthMagic(pI810->drmSubFD, pContext->flags);
+
+ pI810->xvmcContext = contextRec->drmcontext;
+ contextRec->fbBase = pScrn->memPhysBase;
+
+ /* Overlay Regs are at 1024 offset into the Cursor Space */
+ contextRec->OverlayOffset = pI810->CursorStart;
+ contextRec->OverlaySize = 4096;
+
+ contextRec->SurfacesOffset = pI810->MC.Start;
+ contextRec->SurfacesSize = pI810->MC.Size;
+ strncpy (contextRec->busIdString, pDRIInfo->busIdString, 9);
+
+ return Success;
+}
+
+
+int I810XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf,
+ int *num_priv, long **priv )
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int i;
+
+ *priv = (long *)xcalloc(2,sizeof(long));
+
+ if(!*priv) {
+ xf86DrvMsg(X_ERROR, pScrn->scrnIndex,
+ "I810XvMCCreateSurface: Unable to allocate memory!\n");
+ *num_priv = 0;
+ return BadAlloc;
+ }
+ *num_priv = 2;
+
+ /* Surface Arrangement is different based on 6 or 7 Surfaces */
+ if(pI810->numSurfaces == 6) {
+ for(i=0; i<pI810->numSurfaces; i++) {
+ if(!pI810->surfaceAllocation[i]) {
+ pI810->surfaceAllocation[i] = pSurf->surface_id;
+ /* Y data starts at 2MB offset, each surface is 576k */
+ (*priv)[0] = (2*1024*1024 + 576*1024 * i);
+ /* UV data starts at 0 offset, each set is 288k */
+ (*priv)[1] = (576*512 * i);
+ return Success;
+ }
+ }
+ }
+ if(pI810->numSurfaces == 7) {
+ for(i=0; i<pI810->numSurfaces; i++) {
+ if(!pI810->surfaceAllocation[i]) {
+ pI810->surfaceAllocation[i] = pSurf->surface_id;
+ /* Y data starts at 2.5MB offset, each surface is 576k */
+ (*priv)[0] = (2*1024*1024 + 512*1024 + 576*1024 * i);
+ /* UV data starts at 0 offset, each set is 288k */
+ (*priv)[1] = (576*512 * i);
+ return Success;
+ }
+ }
+ }
+ (*priv)[0] = 0;
+ (*priv)[1] = 0;
+ return BadAlloc;
+}
+
+int I810XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp,
+ int *num_priv, long **priv )
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int i;
+
+ *priv = (long *)xcalloc(1,sizeof(long));
+
+ if(!*priv) {
+ xf86DrvMsg(X_ERROR, pScrn->scrnIndex,
+ "I810XvMCCreateSubpicture: Unable to allocate memory!\n");
+ *num_priv = 0;
+ return BadAlloc;
+ }
+ *num_priv = 1;
+
+ if(pI810->numSurfaces == 6) {
+ for(i=6; i<8; i++) {
+ if(!pI810->surfaceAllocation[i]) {
+ pI810->surfaceAllocation[i] = pSubp->subpicture_id;
+ /* Subpictures are after the Y surfaces in memory */
+ (*priv)[0] = (2*1024*1024 + 576*1024 * i);
+ return Success;
+ }
+ }
+ }
+ if(pI810->numSurfaces == 7) {
+ for(i=7; i<9; i++) {
+ if(!pI810->surfaceAllocation[i]) {
+ pI810->surfaceAllocation[i] = pSubp->subpicture_id;
+ /* Subpictures are after the Y surfaces in memory */
+ (*priv)[0] = (2*1024*1024 + 512*1024 + 576*1024 * i);
+ return Success;
+ }
+ }
+ }
+
+ (*priv)[0] = 0;
+ return BadAlloc;
+}
+
+void I810XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ drmDestroyContext(pI810->drmSubFD,pI810->xvmcContext);
+ pI810->xvmcContext = 0;
+}
+
+void I810XvMCDestroySurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int i;
+
+ for(i=0; i<I810_MAX_SURFACES; i++) {
+ if(pI810->surfaceAllocation[i] == pSurf->surface_id) {
+ pI810->surfaceAllocation[i] = 0;
+ return;
+ }
+ }
+ return;
+}
+
+void I810XvMCDestroySubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int i;
+
+ for(i=pI810->numSurfaces; i<I810_MAX_SURFACES + I810_MAX_SUBPICTURES; i++) {
+ if(pI810->surfaceAllocation[i] == pSubp->subpicture_id) {
+ pI810->surfaceAllocation[i] = 0;
+ return;
+ }
+ }
+ return;
+}
+
+
+
+
+
+