diff --git a/src/Makefile.am b/src/Makefile.am index 118d4b1..7ae552e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -59,6 +59,10 @@ INTEL_DRI_SRCS = \ i810_dri.h \ i830_dri.c \ i810_hwmc.c \ + i830_hwmc.h \ + i830_hwmc.c \ + i915_hwmc.c \ + i915_hwmc.h \ i830_dri.h intel_drv_la_SOURCES = \ diff --git a/src/brw_defines.h b/src/brw_defines.h index 93aed54..13cb439 100644 --- a/src/brw_defines.h +++ b/src/brw_defines.h @@ -842,6 +842,30 @@ #define R02_PRIM_END 0x1 #define R02_PRIM_START 0x2 - +/* media pipeline */ + +#define BRW_VFE_MODE_GENERIC 0x0 +#define BRW_VFE_MODE_VLD_MPEG2 0x1 +#define BRW_VFE_MODE_IS 0x2 +#define BRW_VFE_MODE_AVC_MC 0x4 +#define BRW_VFE_MODE_AVC_IT 0x7 +#define BRW_VFE_MODE_VC1_IT 0xB + +#define BRW_VFE_DEBUG_COUNTER_FREE 0 +#define BRW_VFE_DEBUG_COUNTER_FROZEN 1 +#define BRW_VFE_DEBUG_COUNTER_ONCE 2 +#define BRW_VFE_DEBUG_COUNTER_ALWAYS 3 + +/* VLD_STATE */ +#define BRW_MPEG_TOP_FIELD 1 +#define BRW_MPEG_BOTTOM_FIELD 2 +#define BRW_MPEG_FRAME 3 +#define BRW_MPEG_QSCALE_LINEAR 0 +#define BRW_MPEG_QSCALE_NONLINEAR 1 +#define BRW_MPEG_ZIGZAG_SCAN 0 +#define BRW_MPEG_ALTER_VERTICAL_SCAN 1 +#define BRW_MPEG_I_PICTURE 1 +#define BRW_MPEG_P_PICTURE 2 +#define BRW_MPEG_B_PICTURE 3 #endif diff --git a/src/brw_structs.h b/src/brw_structs.h index 28d8e12..7a18b91 100644 --- a/src/brw_structs.h +++ b/src/brw_structs.h @@ -1336,5 +1336,112 @@ struct brw_instruction } bits3; }; +/* media pipeline */ + +struct brw_vfe_state { + struct { + unsigned int per_thread_scratch_space:4; + unsigned int pad3:3; + unsigned int extend_vfe_state_present:1; + unsigned int pad2:2; + unsigned int scratch_base:22; + } vfe0; + + struct { + unsigned int debug_counter_control:2; + unsigned int children_present:1; + unsigned int vfe_mode:4; + unsigned int pad2:2; + unsigned int num_urb_entries:7; + unsigned int urb_entry_alloc_size:9; + unsigned int max_threads:7; + } vfe1; + + struct { + unsigned int pad4:4; + unsigned int interface_descriptor_base:28; + } vfe2; +}; + +struct brw_vld_state { + struct { + unsigned int pad6:6; + unsigned int scan_order:1; + unsigned int intra_vlc_format:1; + unsigned int quantizer_scale_type:1; + unsigned int concealment_motion_vector:1; + unsigned int frame_predict_frame_dct:1; + unsigned int top_field_first:1; + unsigned int picture_structure:2; + unsigned int intra_dc_precision:2; + unsigned int f_code_0_0:4; + unsigned int f_code_0_1:4; + unsigned int f_code_1_0:4; + unsigned int f_code_1_1:4; + } vld0; + + struct { + unsigned int pad2:9; + unsigned int picture_coding_type:2; + unsigned int pad:21; + } vld1; + + struct { + unsigned int index_0:4; + unsigned int index_1:4; + unsigned int index_2:4; + unsigned int index_3:4; + unsigned int index_4:4; + unsigned int index_5:4; + unsigned int index_6:4; + unsigned int index_7:4; + } desc_remap_table0; + + struct { + unsigned int index_8:4; + unsigned int index_9:4; + unsigned int index_10:4; + unsigned int index_11:4; + unsigned int index_12:4; + unsigned int index_13:4; + unsigned int index_14:4; + unsigned int index_15:4; + } desc_remap_table1; +}; + +struct brw_interface_descriptor { + struct { + unsigned int grf_reg_blocks:4; + unsigned int pad:2; + unsigned int kernel_start_pointer:26; + } desc0; + + struct { + unsigned int pad:7; + unsigned int software_exception:1; + unsigned int pad2:3; + unsigned int maskstack_exception:1; + unsigned int pad3:1; + unsigned int illegal_opcode_exception:1; + unsigned int pad4:2; + unsigned int floating_point_mode:1; + unsigned int thread_priority:1; + unsigned int single_program_flow:1; + unsigned int pad5:1; + unsigned int const_urb_entry_read_offset:6; + unsigned int const_urb_entry_read_len:6; + } desc1; + + struct { + unsigned int pad:2; + unsigned int sampler_count:3; + unsigned int sampler_state_pointer:27; + } desc2; + + struct { + unsigned int binding_table_entry_count:5; + unsigned int binding_table_pointer:27; + } desc3; +}; #endif diff --git a/src/i830.h b/src/i830.h index 57f0544..08deb1e 100644 --- a/src/i830.h +++ b/src/i830.h @@ -345,6 +345,12 @@ typedef struct _I830Rec { /* For Xvideo */ i830_memory *overlay_regs; #endif +#ifdef XvMCExtension + /* For XvMC */ + Bool XvMCEnabled; + Bool IsXvMCSurface; +#endif + XF86ModReqInfo shadowReq; /* to test for later libshadow */ Rotation rotation; void (*PointerMoved)(int, int, int); @@ -678,6 +684,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); +#ifdef XvMCExtension +Bool i830_allocate_xvmc_buffer(ScrnInfoPtr pScrn, const char *name, + i830_memory **buffer, unsigned long size, int flags); +#endif extern Bool I830IsPrimary(ScrnInfoPtr pScrn); diff --git a/src/i830_driver.c b/src/i830_driver.c index eacaefc..baf10c1 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -200,6 +200,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830_bios.h" #include "i830_video.h" +#ifdef XvMCExtension +#define _INTEL_XVMC_SERVER_ +#include "i830_hwmc.h" +#endif + #ifdef XF86DRI #include "dri.h" #include @@ -2960,6 +2965,12 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) static void I830FreeScreen(int scrnIndex, int flags) { +#ifdef XvMCExtension + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + I830Ptr pI830 = I830PTR(pScrn); + if (pI830->XvMCEnabled) + intel_xvmc_finish(xf86Screens[scrnIndex]); +#endif I830FreeRec(xf86Screens[scrnIndex]); if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) vgaHWFreeHWRec(xf86Screens[scrnIndex]); diff --git a/src/i830_hwmc.c b/src/i830_hwmc.c new file mode 100644 index 0000000..432733c --- /dev/null +++ b/src/i830_hwmc.c @@ -0,0 +1,118 @@ +/* + * Copyright © 2007 Intel Corporation + * + * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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: + * Zhenyu Wang + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define _INTEL_XVMC_SERVER_ +#include "i830.h" +#include "i830_hwmc.h" + +struct intel_xvmc_driver *xvmc_driver; + +/* set global current driver for xvmc */ +Bool intel_xvmc_set_driver(struct intel_xvmc_driver *d) +{ + if (xvmc_driver) { + ErrorF("XvMC driver already set!\n"); + return FALSE; + } else + xvmc_driver = d; + return TRUE; +} + +/* check chip type and load xvmc driver */ +/* This must be first called! */ +Bool intel_xvmc_probe(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + Bool ret = FALSE; + + if (IS_I9XX(pI830)) { + if (!IS_I965G(pI830)) + ret = intel_xvmc_set_driver(&i915_xvmc_driver); + /* + else + ret = intel_xvmc_set_driver(&i965_xvmc_driver); + */ + } else { + ErrorF("Your chipset doesn't support XvMC.\n"); + return FALSE; + } + return TRUE; +} + +void intel_xvmc_finish(ScrnInfoPtr pScrn) +{ + if (!xvmc_driver) + return; + (*xvmc_driver->fini)(pScrn); +} + +Bool intel_xvmc_driver_init(ScreenPtr pScreen, XF86VideoAdaptorPtr xv_adaptor) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if (!xvmc_driver) { + ErrorF("Failed to probe XvMC driver.\n"); + return FALSE; + } + + if (!(*xvmc_driver->init)(pScrn, xv_adaptor)) { + ErrorF("XvMC driver initialize failed.\n"); + return FALSE; + } + return TRUE; +} + +Bool intel_xvmc_screen_init(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + + if (!xvmc_driver) + return FALSE; + + if (xf86XvMCScreenInit(pScreen, 1, &xvmc_driver->adaptor)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[XvMC] %s driver initialized.\n", + xvmc_driver->name); + pI830->XvMCEnabled = TRUE; + } else { + intel_xvmc_finish(pScrn); + pI830->XvMCEnabled = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[XvMC] Failed to initialize XvMC.\n"); + return FALSE; + } + return TRUE; +} + +int intel_xvmc_putimage_size(ScrnInfoPtr pScrn) +{ + return (*xvmc_driver->putimage_size)(pScrn); +} diff --git a/src/i830_hwmc.h b/src/i830_hwmc.h new file mode 100644 index 0000000..97fe4fd --- /dev/null +++ b/src/i830_hwmc.h @@ -0,0 +1,77 @@ +/* + * Copyright © 2007 Intel Corporation + * + * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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: + * Zhenyu Wang + * + */ +#ifndef I830_HWMC_H +#define I830_HWMC_H + +#define FOURCC_XVMC (('C' << 24) + ('M' << 16) + ('V' << 8) + 'X') + +/* + * Commands that client submits through XvPutImage: + */ + +#define INTEL_XVMC_COMMAND_DISPLAY 0x00 +#define INTEL_XVMC_COMMAND_UNDISPLAY 0x01 + +/* hw xvmc support type */ +#define XVMC_I915_MPEG2_MC 0x01 +#define XVMC_I965_MPEG2_MC 0x02 +#define XVMC_I945_MPEG2_VLD 0x04 +#define XVMC_I965_MPEG2_VLD 0x08 + +/* common header for context private */ +struct _intel_xvmc_common { + unsigned int type; + unsigned int sarea_size; +}; + +#ifdef _INTEL_XVMC_SERVER_ +#include + +struct intel_xvmc_driver { + char *name; + XF86MCAdaptorPtr adaptor; + unsigned int flag; + /* more items for xvmv surface manage? */ + Bool (*init)(ScrnInfoPtr, XF86VideoAdaptorPtr); + void (*fini)(ScrnInfoPtr); + int (*putimage_size)(ScrnInfoPtr); + void* devPrivate; +}; + +extern struct intel_xvmc_driver *xvmc_driver; +extern struct intel_xvmc_driver i915_xvmc_driver; +/* extern struct intel_xvmc_driver i965_xvmc_driver; */ + +extern Bool intel_xvmc_set_driver(struct intel_xvmc_driver *); +extern Bool intel_xvmc_probe(ScrnInfoPtr); +extern Bool intel_xvmc_driver_init(ScreenPtr, XF86VideoAdaptorPtr); +extern Bool intel_xvmc_screen_init(ScreenPtr); +extern void intel_xvmc_finish(ScrnInfoPtr); +extern int intel_xvmc_putimage_size(ScrnInfoPtr); +#endif + +#endif diff --git a/src/i830_memory.c b/src/i830_memory.c index 7b89c40..e7fdc9c 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -1991,3 +1991,22 @@ I830CheckAvailableMemory(ScrnInfoPtr pScrn) return maxPages * 4; } + +/* + * Allocate memory for MC compensation + */ +Bool i830_allocate_xvmc_buffer(ScrnInfoPtr pScrn, const char *name, + i830_memory **buffer, unsigned long size, + int flags) +{ + *buffer = i830_allocate_memory(pScrn, name, size, + GTT_PAGE_SIZE, flags); + + if (!*buffer) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate memory for %s.\n", name); + return FALSE; + } + + return TRUE; +} diff --git a/src/i830_video.c b/src/i830_video.c index 5325bbd..5cc291d 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -74,6 +74,12 @@ #include "dixstruct.h" #include "fourcc.h" +#ifdef XvMCExtension +#define _INTEL_XVMC_SERVER_ +#include "i830_hwmc.h" +#include "i915_hwmc.h" +#endif + #ifndef USE_USLEEP_FOR_VIDEO #define USE_USLEEP_FOR_VIDEO 0 #endif @@ -252,13 +258,37 @@ static XF86AttributeRec GammaAttributes[GAMMA_ATTRIBUTES] = { {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA5"} }; -#define NUM_IMAGES 4 +#define NUM_IMAGES 5 static XF86ImageRec Images[NUM_IMAGES] = { XVIMAGE_YUY2, XVIMAGE_YV12, XVIMAGE_I420, - XVIMAGE_UYVY + XVIMAGE_UYVY, + { + /* + * Below, a dummy picture type that is used in XvPutImage only to do + * an overlay update. Introduced for the XvMC client lib. + * Defined to have a zero data size. + */ + FOURCC_XVMC, + XvYUV, + LSBFirst, + {'X', 'V', 'M', 'C', + 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00, + 0x38, 0x9B, 0x71}, + 12, + XvPlanar, + 3, + 0, 0, 0, 0, + 8, 8, 8, + 1, 2, 2, + 1, 2, 2, + {'Y', 'V', 'U', + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + XvTopToBottom + }, }; typedef struct { @@ -529,6 +559,7 @@ I830InitVideo(ScreenPtr pScreen) XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL; int num_adaptors; + Bool ret = FALSE; #if 0 { @@ -591,10 +622,20 @@ I830InitVideo(ScreenPtr pScreen) } I830InitOffscreenImages(pScreen); } +#ifdef XvMCExtension + if (intel_xvmc_probe(pScrn)) { + if (texturedAdaptor) + ret = intel_xvmc_driver_init(pScreen, texturedAdaptor); + } +#endif if (num_adaptors) xf86XVScreenInit(pScreen, adaptors, num_adaptors); +#ifdef XvMCExtension + if (ret) + intel_xvmc_screen_init(pScreen); +#endif xfree(adaptors); } @@ -2244,8 +2285,15 @@ I830PutImage(ScrnInfoPtr pScrn, switch (id) { case FOURCC_YV12: case FOURCC_I420: - srcPitch = (width + 3) & ~3; - srcPitch2 = ((width >> 1) + 3) & ~3; + //XXX + if (pI830->IsXvMCSurface) { + srcPitch = (width + 0x3ff) & ~0x3ff; + srcPitch2 = ((width >> 1) + 0x3ff) & ~0x3ff; + } else { + srcPitch = (width + 0x3) & ~0x3; + srcPitch2 = ((width >> 1) + 0x3) & ~0x3; + } + if (pPriv->textured && IS_I965G(pI830)) destId = FOURCC_YUY2; break; @@ -2500,6 +2548,12 @@ I830QueryImageAttributes(ScrnInfoPtr pScrn, ErrorF("size is %d\n", size); #endif break; + case FOURCC_XVMC: + *h = (*h + 1) & ~1; + size = intel_xvmc_putimage_size(pScrn); + if (pitches) + pitches[0] = size; + break; case FOURCC_UYVY: case FOURCC_YUY2: default: diff --git a/src/i915_hwmc.c b/src/i915_hwmc.c new file mode 100644 index 0000000..6ab00e2 --- /dev/null +++ b/src/i915_hwmc.c @@ -0,0 +1,896 @@ +/* + * Copyright © 2006 Intel Corporation + * + * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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: + * Xiang Haihao + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#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 +#include +#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 + +#define _INTEL_XVMC_SERVER_ +#include "i915_hwmc.h" + +#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]; + drm_handle_t surface_handle; +} I915XvMCSurfacePriv; + +typedef struct _I915XvMCContextPriv +{ + i830_memory *mcStaticIndirectState; + drm_handle_t sis_handle; + i830_memory *mcSamplerState; + drm_handle_t ssb_handle; + i830_memory *mcMapState; + drm_handle_t msb_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; + i830_memory *mcBatchBuffer; + drm_handle_t batchbuffer_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; + PutImageFuncPtr savePutImage; +} 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,*/ + 0, + /* &yv12_subpicture_list*/ + NULL, +}; + +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,*/ + 0, + /* &yv12_subpicture_list*/ + NULL, +}; + +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 */ + 0, + NULL, +#if 0 + ARRARY_SIZE(i915_subpicture_list), /* num_subpictures */ + i915_subpicture_list, /* subpictures */ +#endif + (xf86XvMCCreateContextProcPtr)I915XvMCCreateContext, + (xf86XvMCDestroyContextProcPtr)I915XvMCDestroyContext, + (xf86XvMCCreateSurfaceProcPtr)I915XvMCCreateSurface, + (xf86XvMCDestroySurfaceProcPtr)I915XvMCDestroySurface, + (xf86XvMCCreateSubpictureProcPtr)I915XvMCCreateSubpicture, + (xf86XvMCDestroySubpictureProcPtr)I915XvMCDestroySubpicture +}; + +/* + * 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; + } + xvmc->ncontexts = 0; + xvmc->nsurfaces = 0; +} + +static void cleanupI915XvMC(I915XvMCPtr xvmc) +{ + 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->mcSamplerState->offset + pI830->LinearAddr), + ctxpriv->mcSamplerState->size, DRM_AGP, 0, + (drmAddress)&ctxpriv->ssb_handle) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] drmAddMap(ssb_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->mcPixelShaderProgram->offset + pI830->LinearAddr), + ctxpriv->mcPixelShaderProgram->size, DRM_AGP, 0, + (drmAddress)&ctxpriv->psp_handle) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] drmAddMap(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] drmAddMap(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; + } + + if (drmAddMap(pI830->drmSubFD, + (drm_handle_t)(ctxpriv->mcBatchBuffer->offset + pI830->LinearAddr), + ctxpriv->mcBatchBuffer->size, DRM_AGP, 0, + (drmAddress)&ctxpriv->batchbuffer_handle) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] drmAddMap(batchbuffer_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->ssb_handle) { + drmRmMap(pI830->drmSubFD, ctxpriv->ssb_handle); + ctxpriv->ssb_handle = 0; + } + + if (ctxpriv->msb_handle) { + drmRmMap(pI830->drmSubFD, ctxpriv->msb_handle); + ctxpriv->msb_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; + } + + if (ctxpriv->batchbuffer_handle) { + drmRmMap(pI830->drmSubFD, ctxpriv->batchbuffer_handle); + ctxpriv->batchbuffer_handle = 0; + } +} + +static Bool i915_allocate_xvmc_buffers(ScrnInfoPtr pScrn, I915XvMCContextPriv *ctxpriv) +{ + I830Ptr pI830 = I830PTR(pScrn); + int flags = ALIGN_BOTH_ENDS; + + if (IS_I915G(pI830) || IS_I915GM(pI830) || + IS_I945G(pI830) || IS_I945GM(pI830)) + flags |= NEED_PHYSICAL_ADDR; + + if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Static Indirect State", + &(ctxpriv->mcStaticIndirectState), 4 * 1024, + flags)) { + return FALSE; + } + + if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Sampler State", + &(ctxpriv->mcSamplerState), 4 * 1024, + flags)) { + return FALSE; + } + + if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Map State", + &(ctxpriv->mcMapState), 4 * 1024, + flags)) { + return FALSE; + } + + if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Pixel Shader Program", + &(ctxpriv->mcPixelShaderProgram), 4 * 1024, + flags)) { + return FALSE; + } + + if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Pixel Shader Constants", + &(ctxpriv->mcPixelShaderConstants), 4 * 1024, + flags)) { + return FALSE; + } + + if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Correction Data Buffer", + &(ctxpriv->mcCorrdata), 512 * 1024, + ALIGN_BOTH_ENDS)) { + return FALSE; + } + + if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]batch buffer", + &(ctxpriv->mcBatchBuffer), 8 * 1024, + ALIGN_BOTH_ENDS)) { + return FALSE; + } + + i830_describe_allocations(pScrn, 1, ""); + 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->mcSamplerState) { + i830_free_memory(pScrn, ctxpriv->mcSamplerState); + ctxpriv->mcSamplerState = NULL; + } + + if (ctxpriv->mcMapState) { + i830_free_memory(pScrn, ctxpriv->mcMapState); + ctxpriv->mcMapState = 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; + } + + if (ctxpriv->mcBatchBuffer) { + i830_free_memory(pScrn, ctxpriv->mcBatchBuffer); + ctxpriv->mcBatchBuffer = 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; + I830DRIPtr pI830DRI = pDRIInfo->devPrivate; + I915XvMCCreateContextRec *contextRec = NULL; + I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; + I915XvMCContextPriv *ctxpriv = NULL; + int i; + + *priv = NULL; + *num_priv = 0; + + if (!pI830->XvMCEnabled) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[XvMC] I915XvMCCreateContext: Cannot use XvMC!\n"); + return BadAlloc; + } + + for (i = 0; i < I915_XVMC_MAX_CONTEXTS; i++) { + if (!pXvMC->contexts[i]) + break; + } + + if (i == I915_XVMC_MAX_CONTEXTS || + 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; + + 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->comm.type = xvmc_driver->flag; + contextRec->comm.sarea_size = pDRIInfo->SAREASize; + contextRec->ctxno = i; + contextRec->sis.handle = ctxpriv->sis_handle; + contextRec->sis.offset = ctxpriv->mcStaticIndirectState->offset; + contextRec->sis.size = ctxpriv->mcStaticIndirectState->size; + contextRec->sis.bus_addr = ctxpriv->mcStaticIndirectState->bus_addr; + contextRec->ssb.handle = ctxpriv->ssb_handle; + contextRec->ssb.offset = ctxpriv->mcSamplerState->offset; + contextRec->ssb.size = ctxpriv->mcSamplerState->size; + contextRec->ssb.bus_addr = ctxpriv->mcSamplerState->bus_addr; + contextRec->msb.handle = ctxpriv->msb_handle; + contextRec->msb.offset = ctxpriv->mcMapState->offset; + contextRec->msb.size = ctxpriv->mcMapState->size; + contextRec->msb.bus_addr = ctxpriv->mcMapState->bus_addr; + contextRec->psp.handle = ctxpriv->psp_handle; + contextRec->psp.offset = ctxpriv->mcPixelShaderProgram->offset; + contextRec->psp.size = ctxpriv->mcPixelShaderProgram->size; + contextRec->psp.bus_addr = ctxpriv->mcPixelShaderProgram->bus_addr; + contextRec->psc.handle = ctxpriv->psc_handle; + contextRec->psc.offset = ctxpriv->mcPixelShaderConstants->offset; + contextRec->psc.size = ctxpriv->mcPixelShaderConstants->size; + contextRec->psc.bus_addr = ctxpriv->mcPixelShaderConstants->bus_addr; + contextRec->corrdata.handle = ctxpriv->corrdata_handle; + contextRec->corrdata.offset = ctxpriv->mcCorrdata->offset; + contextRec->corrdata.size = ctxpriv->mcCorrdata->size; + contextRec->batchbuffer.handle = ctxpriv->batchbuffer_handle; + contextRec->batchbuffer.offset = ctxpriv->mcBatchBuffer->offset; + contextRec->batchbuffer.size = ctxpriv->mcBatchBuffer->size; + contextRec->sarea_priv_offset = sizeof(XF86DRISAREARec); + contextRec->depth = pScrn->bitsPerPixel; + contextRec->deviceID = pI830DRI->deviceID; + + 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 = (I915XvMCPtr)xvmc_driver->devPrivate; + I915XvMCSurfacePriv *sfpriv = NULL; + I915XvMCCreateSurfaceRec *surfaceRec = NULL; + XvMCContextPtr ctx = NULL; + unsigned int srfno; + unsigned long bufsize; + + if (!pI830->XvMCEnabled) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[XvMC] I915XvMCCreateContext: Cannot use XvMC!\n"); + return BadAlloc; + } + + *priv = NULL; + *num_priv = 0; + + for (srfno = 0; srfno < I915_XVMC_MAX_SURFACES; ++srfno) { + if (!pXvMC->surfaces[srfno]) + break; + } + + if (srfno == I915_XVMC_MAX_SURFACES || + pXvMC->nsurfaces >= I915_XVMC_MAX_SURFACES) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[XvMC] I915XvMCCreateSurface: Too many surfaces !\n"); + return BadAlloc; + } + + *priv = xcalloc(1, sizeof(I915XvMCCreateSurfaceRec)); + surfaceRec = (I915XvMCCreateSurfaceRec *)*priv; + + if (!*priv) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[XvMC] I915XvMCCreateSurface: Unable to allocate memory!\n"); + return BadAlloc; + } + + *num_priv = sizeof(I915XvMCCreateSurfaceRec) >> 2; + sfpriv = (I915XvMCSurfacePriv *)xcalloc(1, sizeof(I915XvMCSurfacePriv)); + + if (!sfpriv) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[XvMC] I915XvMCCreateSurface: Unable to allocate memory!\n"); + xfree(*priv); + *priv = NULL; + *num_priv = 0; + return BadAlloc; + } + + ctx = pSurf->context; + bufsize = SIZE_YUV420(ctx->width, ctx->height); + + /* FIXME xvmc ttm */ + if (!i830_allocate_xvmc_buffer(pScrn, "XvMC surface", + &(sfpriv->surface), bufsize, + ALIGN_BOTH_ENDS)) { + 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; + } + i830_describe_allocations(pScrn, 1, ""); + if (drmAddMap(pI830->drmSubFD, + (drm_handle_t)(sfpriv->surface->offset + pI830->LinearAddr), + sfpriv->surface->size, DRM_AGP, 0, + (drmAddress)&sfpriv->surface_handle) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] drmAddMap(surface_handle) failed!\n"); + i830_free_memory(pScrn, sfpriv->surface); + xfree(sfpriv); + xfree(*priv); + *priv = NULL; + *num_priv = 0; + return BadAlloc; + } + + surfaceRec->srfno = srfno; + surfaceRec->srf.handle = sfpriv->surface_handle; + surfaceRec->srf.offset = sfpriv->surface->offset; + surfaceRec->srf.size = sfpriv->surface->size; + + pXvMC->surfaces[srfno] = pSurf->surface_id; + pXvMC->sfprivs[srfno]= sfpriv; + pXvMC->nsurfaces++; + + return Success; +} + +static int I915XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp, + int *num_priv, long **priv ) +{ + I830Ptr pI830 = I830PTR(pScrn); + I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; + I915XvMCSurfacePriv *sfpriv = NULL; + I915XvMCCreateSurfaceRec *surfaceRec = NULL; + XvMCContextPtr ctx = NULL; + unsigned int srfno; + unsigned int bufsize; + + *priv = NULL; + *num_priv = 0; + + for (srfno = 0; srfno < I915_XVMC_MAX_SURFACES; ++srfno) { + if (!pXvMC->surfaces[srfno]) + break; + } + + if (srfno == I915_XVMC_MAX_SURFACES || + pXvMC->nsurfaces >= I915_XVMC_MAX_SURFACES) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[XvMC] I915XvMCCreateSubpicture: Too many surfaces !\n"); + return BadAlloc; + } + + *priv = xcalloc(1, sizeof(I915XvMCCreateSurfaceRec)); + surfaceRec = (I915XvMCCreateSurfaceRec *)*priv; + + if (!*priv) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[XvMC] I915XvMCCreateSubpicture: Unable to allocate memory!\n"); + return BadAlloc; + } + + *num_priv = sizeof(I915XvMCCreateSurfaceRec) >> 2; + sfpriv = (I915XvMCSurfacePriv *)xcalloc(1, sizeof(I915XvMCSurfacePriv)); + + if (!sfpriv) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[XvMC] I915XvMCCreateSubpicture: Unable to allocate memory!\n"); + xfree(*priv); + *priv = NULL; + *num_priv = 0; + return BadAlloc; + } + + ctx = pSubp->context; + bufsize = SIZE_XX44(ctx->width, ctx->height); + + if (!i830_allocate_xvmc_buffer(pScrn, "XvMC surface", + &(sfpriv->surface), bufsize, + ALIGN_BOTH_ENDS)) { + 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; + } + + if (drmAddMap(pI830->drmSubFD, + (drm_handle_t)(sfpriv->surface->offset + pI830->LinearAddr), + sfpriv->surface->size, DRM_AGP, 0, + (drmAddress)&sfpriv->surface_handle) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] drmAddMap(surface_handle) failed!\n"); + i830_free_memory(pScrn, sfpriv->surface); + xfree(sfpriv); + xfree(*priv); + *priv = NULL; + *num_priv = 0; + return BadAlloc; + } + + surfaceRec->srfno = srfno; + surfaceRec->srf.handle = sfpriv->surface_handle; + surfaceRec->srf.offset = sfpriv->surface->offset; + surfaceRec->srf.size = sfpriv->surface->size; + + pXvMC->sfprivs[srfno] = sfpriv; + pXvMC->surfaces[srfno] = pSubp->subpicture_id; + pXvMC->nsurfaces++; + + return Success; +} + +static void I915XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext) +{ + I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; + 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 = (I915XvMCPtr)xvmc_driver->devPrivate; + int i; + + for (i = 0; i < I915_XVMC_MAX_SURFACES; i++) { + if (pXvMC->surfaces[i] == pSurf->surface_id) { + drmRmMap(pI830->drmSubFD, pXvMC->sfprivs[i]->surface_handle); + 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 = (I915XvMCPtr)xvmc_driver->devPrivate; + int i; + + for (i = 0; i < I915_XVMC_MAX_SURFACES; i++) { + if (pXvMC->surfaces[i] == pSubp->subpicture_id) { + drmRmMap(pI830->drmSubFD, pXvMC->sfprivs[i]->surface_handle); + 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 I915XvMCPutImage(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) +{ + I830Ptr pI830 = I830PTR(pScrn); + I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; + I915XvMCCommandBuffer *i915XvMCData = (I915XvMCCommandBuffer *)buf; + int ret; + + if (pI830->XvMCEnabled) { + if (FOURCC_XVMC == id) { + switch (i915XvMCData->command) { + case INTEL_XVMC_COMMAND_DISPLAY: + if ((i915XvMCData->srfNo >= I915_XVMC_MAX_SURFACES) || + !pXvMC->surfaces[i915XvMCData->srfNo] || + !pXvMC->sfprivs[i915XvMCData->srfNo]) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[XvMC] I915XvMCPutImage: Invalid parameters !\n"); + return 1; + } + + buf = pI830->FbBase + pXvMC->sfprivs[i915XvMCData->srfNo]->surface->offset; + id = i915XvMCData->real_id; + pI830->IsXvMCSurface = 1; + break; + default: + return 0; + } + } + } + + ret = pXvMC->savePutImage(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); + pI830->IsXvMCSurface = 0; + return ret; +} + +static int i915_xvmc_putimage_size(ScrnInfoPtr pScrn) +{ + return sizeof(I915XvMCCommandBuffer); +} + +static Bool i915_xvmc_init(ScrnInfoPtr pScrn, XF86VideoAdaptorPtr XvAdapt) +{ + I915XvMCPtr pXvMC; + + pXvMC = (I915XvMCPtr)xcalloc(1, sizeof(I915XvMC)); + if (!pXvMC) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "[XvMC] alloc driver private failed!\n"); + return FALSE; + } + xvmc_driver->devPrivate = (void*)pXvMC; + initI915XvMC(pXvMC); + + /* set up wrappers */ + pXvMC->savePutImage = XvAdapt->PutImage; + XvAdapt->PutImage = I915XvMCPutImage; + return TRUE; +} + +static void i915_xvmc_fini(ScrnInfoPtr pScrn) +{ + I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; + + cleanupI915XvMC(pXvMC); + xfree(xvmc_driver->devPrivate); +} + +/* new xvmc driver interface */ +struct intel_xvmc_driver i915_xvmc_driver = { + .name = "i915_xvmc", + .adaptor = &pAdapt, + .flag = XVMC_I915_MPEG2_MC, + .init = i915_xvmc_init, + .fini = i915_xvmc_fini, + .putimage_size = i915_xvmc_putimage_size, +}; diff --git a/src/i915_hwmc.h b/src/i915_hwmc.h new file mode 100644 index 0000000..d110661 --- /dev/null +++ b/src/i915_hwmc.h @@ -0,0 +1,80 @@ +/* + * Copyright © 2006 Intel Corporation + * + * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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: + * Xiang Haihao + * + */ +#ifndef _I915_HWMC_H +#define _I915_HWMC_H + +#include "i830_hwmc.h" + +#define STRIDE(w) (((w) + 0x3ff) & ~0x3ff) +#define SIZE_Y420(w, h) (h * STRIDE(w)) +#define SIZE_UV420(w, h) ((h >> 1) * STRIDE(w >> 1)) +#define SIZE_YUV420(w, h) (h * (STRIDE(w) + STRIDE(w >> 1))) +#define SIZE_XX44(w, h) (h * STRIDE(w)) + +#define I915_NUM_XVMC_ATTRIBUTES 0x02 +#define I915_XVMC_VALID 0x80000000 + +typedef struct +{ + unsigned int command; + unsigned int ctxNo; + unsigned int srfNo; + unsigned int subPicNo; + int real_id; +} I915XvMCCommandBuffer; + +struct hwmc_buffer +{ + drm_handle_t handle; + unsigned long offset; + unsigned long size; + unsigned long bus_addr; +}; + +typedef struct +{ + struct _intel_xvmc_common comm; + unsigned int ctxno; /* XvMC private context reference number */ + struct hwmc_buffer sis; + struct hwmc_buffer ssb; + struct hwmc_buffer msb; + struct hwmc_buffer psp; + struct hwmc_buffer psc; + struct hwmc_buffer corrdata;/* Correction Data Buffer */ + struct hwmc_buffer batchbuffer; + unsigned int sarea_priv_offset; + unsigned int depth; + int deviceID; +} I915XvMCCreateContextRec; + +typedef struct +{ + unsigned int srfno; + struct hwmc_buffer srf; +} I915XvMCCreateSurfaceRec; + +#endif /* _I915_HWMC_H */ diff --git a/src/xvmc/I915XvMC.c b/src/xvmc/I915XvMC.c new file mode 100644 index 0000000..687d54f --- /dev/null +++ b/src/xvmc/I915XvMC.c @@ -0,0 +1,3020 @@ +/* + * Copyright © 2006 Intel Corporation + * + * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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: + * Xiang Haihao + * + */ + +#include +#include + +#include "I915XvMC.h" +#include "i915_structs.h" +#include "i915_program.h" +#include "intel_batchbuffer.h" + +#define SAREAPTR(ctx) ((drmI830Sarea *) \ + (((CARD8 *)(ctx)->sarea_address) + \ + (ctx)->sarea_priv_offset)) + +#define YOFFSET(surface) (surface->srf.offset) +#define UOFFSET(surface) (surface->srf.offset + \ + SIZE_Y420(surface->width, surface->height) + \ + SIZE_UV420(surface->width, surface->height)) +#define VOFFSET(surface) (surface->srf.offset + \ + SIZE_Y420(surface->width, surface->height)) + +/* Lookup tables to speed common calculations */ +static unsigned int 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 Status i915_xvmc_mc_create_context(Display* display, XvMCContext *context, int priv_count, CARD32* priv_data); +static Status i915_xvmc_mc_destroy_context(Display* display, XvMCContext *context); +static Status i915_xvmc_mc_create_surface(Display* display, XvMCContext *context, XvMCSurface *surface); +static Status i915_xvmc_mc_destroy_surface(Display* display, XvMCSurface *surface); +static Status i915_xvmc_mc_render_surface(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); +static Status i915_xvmc_mc_put_surface(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); +static Status i915_xvmc_mc_get_surface_status(Display *display, XvMCSurface *surface, int *stat); +//XXX +static int i915_xvmc_mc_init() +{return 0;} +static void i915_xvmc_mc_fini() +{} + +struct _intel_xvmc_driver i915_xvmc_mc_driver = { + .type = XVMC_I915_MPEG2_MC, + .init = i915_xvmc_mc_init, + .fini = i915_xvmc_mc_fini, + .create_context = i915_xvmc_mc_create_context, + .destroy_context = i915_xvmc_mc_destroy_context, + .create_surface = i915_xvmc_mc_create_surface, + .destroy_surface = i915_xvmc_mc_destroy_surface, + .render_surface = i915_xvmc_mc_render_surface, + .put_surface = i915_xvmc_mc_put_surface, + .get_surface_status = i915_xvmc_mc_get_surface_status, +}; + +static int findOverlap(unsigned int width, unsigned int height, + short *dstX, short *dstY, + short *srcX, short *srcY, + unsigned short *areaW, unsigned short *areaH) +{ + int w, h; + unsigned int 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 __inline__ void renderError(void) +{ + XVMC_ERR("Invalid Macroblock Parameters found."); +} + +static void I915XvMCContendedLock(i915XvMCContext *pI915XvMC, drmLockFlags flags) +{ + drmGetLock(xvmc_driver->fd, pI915XvMC->hHWContext, flags); +} + +#define SET_BLOCKED_SIGSET(pI915XvMC) do { \ + sigset_t bl_mask; \ + sigfillset(&bl_mask); \ + sigdelset(&bl_mask, SIGFPE); \ + sigdelset(&bl_mask, SIGILL); \ + sigdelset(&bl_mask, SIGSEGV); \ + sigdelset(&bl_mask, SIGBUS); \ + sigdelset(&bl_mask, SIGKILL); \ + pthread_sigmask(SIG_SETMASK, &bl_mask, &pI915XvMC->sa_mask); \ + } while (0) + +#define RESTORE_BLOCKED_SIGSET(pI915XvMC) do { \ + pthread_sigmask(SIG_SETMASK, &pI915XvMC->sa_mask, NULL); \ + } while (0) + +#define PPTHREAD_MUTEX_LOCK(pI915XvMC) do { \ + SET_BLOCKED_SIGSET(pI915XvMC); \ + pthread_mutex_lock(&pI915XvMC->ctxmutex); \ + } while (0) + +#define PPTHREAD_MUTEX_UNLOCK(pI915XvMC) do { \ + pthread_mutex_unlock(&pI915XvMC->ctxmutex); \ + RESTORE_BLOCKED_SIGSET(pI915XvMC); \ + } while (0) + +/* Lock the hardware and validate our state. + */ +static void LOCK_HARDWARE(i915XvMCContext *pI915XvMC) +{ + char __ret = 0; + + PPTHREAD_MUTEX_LOCK(pI915XvMC); + 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(xvmc_driver->fd, pI915XvMC->driHwLock, + pI915XvMC->hHWContext); + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); +} + +static void i915_flush(i915XvMCContext *pI915XvMC, int map, int render) +{ + struct i915_mi_flush mi_flush; + + 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 = map; + mi_flush.dw0.render_cache_flush_inhibit = render; + + intelBatchbufferData(pI915XvMC, &mi_flush, sizeof(mi_flush), 0); +} + +/* for MC picture rendering */ +static void i915_mc_static_indirect_state_buffer(XvMCContext *context, + XvMCSurface *surface, + unsigned int picture_structure, + unsigned int flags, + 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 int w = surface->width, h = surface->height; + + /* 3DSTATE_BUFFER_INFO */ + /* DEST Y */ + 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 */ /* FIXME: tiled y for performance */ + buffer_info->dw1.tiled_surface = 0; /* linear */ + buffer_info->dw1.walk = TILEWALK_XMAJOR; + buffer_info->dw1.pitch = (pI915Surface->yStride >> 2); /* in DWords */ + buffer_info->dw2.base_address = (YOFFSET(pI915Surface) >> 2); /* starting DWORD address */ + + /* DEST U */ + ++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 = (pI915Surface->uvStride >> 2); /* in DWords */ + buffer_info->dw2.base_address = (UOFFSET(pI915Surface) >> 2); /* starting DWORD address */ + + /* DEST V */ + ++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 = (pI915Surface->uvStride >> 2); /* in Dwords */ + buffer_info->dw2.base_address = (VOFFSET(pI915Surface) >> 2); /* starting DWORD address */ + + /* 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; /* 0.5 */ + dest_buffer_variables->dw1.dest_h_bias = 8; /* 0.5 */ + dest_buffer_variables->dw1.color_fmt = COLORBUFFER_8BIT; + dest_buffer_variables->dw1.v_ls = 0; + dest_buffer_variables->dw1.v_ls_offset = 0; + + if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) { + ; + } else if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_TOP_FIELD) { + dest_buffer_variables->dw1.v_ls = 1; + } else if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_BOTTOM_FIELD) { + dest_buffer_variables->dw1.v_ls = 1; + dest_buffer_variables->dw1.v_ls_offset = 1; + } + + /* 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.decode_mode = MPEG_DECODE_MC; + dest_buffer_variables_mpeg->dw1.rcontrol = 0; /* for MPEG-1/MPEG-2 */ + dest_buffer_variables_mpeg->dw1.bidir_avrg_control = 0; /* for MPEG-1/MPEG-2/MPEG-4 */ + dest_buffer_variables_mpeg->dw1.abort_on_error = 1; + dest_buffer_variables_mpeg->dw1.intra8 = 0; /* 16-bit formatted correction data */ + dest_buffer_variables_mpeg->dw1.tff = 1; + + if (picture_structure & XVMC_FRAME_PICTURE) { + ; + } else if (picture_structure & XVMC_TOP_FIELD) { + if (flags & XVMC_SECOND_FIELD) + dest_buffer_variables_mpeg->dw1.tff = 0; + else + dest_buffer_variables_mpeg->dw1.tff = 1; + } else if (picture_structure & XVMC_BOTTOM_FIELD) { + if (flags & XVMC_SECOND_FIELD) + dest_buffer_variables_mpeg->dw1.tff = 1; + else + dest_buffer_variables_mpeg->dw1.tff = 0; + } + + dest_buffer_variables_mpeg->dw1.v_subsample_factor = MC_SUB_1V; + dest_buffer_variables_mpeg->dw1.h_subsample_factor = MC_SUB_1H; + dest_buffer_variables_mpeg->dw1.picture_width = (w >> 4); /* in macroblocks */ + dest_buffer_variables_mpeg->dw2.picture_coding_type = picture_coding_type; + + /* 3DSATE_BUFFER_INFO */ + /* CORRECTION DATA */ + 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.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 >> 2); /* starting DWORD address */ +} + +static void i915_mc_map_state_buffer(XvMCContext *context, + i915XvMCSurface *privTarget, + i915XvMCSurface *privPast, + i915XvMCSurface *privFuture) +{ + struct i915_3dstate_map_state *map_state; + struct texture_map *tm; + i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; + unsigned int w = context->width, h = context->height; + + /* 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 (Past) */ + 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 = (YOFFSET(privPast) >> 2); + tm->tm1.tile_walk = TILEWALK_XMAJOR; /* FIXME: tiled y for performace */ + tm->tm1.tiled_surface = 0; + tm->tm1.utilize_fence_regs = 0; + tm->tm1.texel_fmt = 0; /* 8bit */ + tm->tm1.surface_fmt = 1; /* 8bit */ + 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 = (privPast->yStride >> 2) - 1; /* in DWords - 1 */ + + /* texture map: Backward (Future) */ + ++tm; + memset(tm, 0, sizeof(*tm)); + tm->tm0.v_ls_offset = 0; + tm->tm0.v_ls = 0; + tm->tm0.base_address = (YOFFSET(privFuture) >> 2); + tm->tm1.tile_walk = TILEWALK_XMAJOR; + tm->tm1.tiled_surface = 0; + tm->tm1.utilize_fence_regs = 0; + tm->tm1.texel_fmt = 0; /* 8bit */ + tm->tm1.surface_fmt = 1; /* 8bit */ + 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 = (privFuture->yStride >> 2) - 1; + + /* 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 = (UOFFSET(privPast) >> 2); + tm->tm1.tile_walk = TILEWALK_XMAJOR; + tm->tm1.tiled_surface = 0; + tm->tm1.utilize_fence_regs = 0; + tm->tm1.texel_fmt = 0; /* 8bit */ + tm->tm1.surface_fmt = 1; /* 8bit */ + 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 = (privPast->uvStride >> 2) - 1; /* in DWords - 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 = (UOFFSET(privFuture) >> 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) - 1; + tm->tm1.height = (h >> 1) - 1; + tm->tm2.depth = 0; + tm->tm2.max_lod = 0; + tm->tm2.cube_face = 0; + tm->tm2.pitch = (privFuture->uvStride >> 2) - 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 = (VOFFSET(privPast) >> 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) - 1; + tm->tm1.height = (h >> 1) - 1; + tm->tm2.depth = 0; + tm->tm2.max_lod = 0; + tm->tm2.cube_face = 0; + tm->tm2.pitch = (privPast->uvStride >> 2) - 1; /* in DWords - 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 = (VOFFSET(privFuture) >> 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) - 1; + tm->tm1.height = (h >> 1) - 1; + tm->tm2.depth = 0; + tm->tm2.max_lod = 0; + tm->tm2.cube_face = 0; + tm->tm2.pitch = (privFuture->uvStride >> 2) - 1; +} + +static void i915_mc_load_sis_msb_buffers(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 int size; + int mem_select = 1; + + /* 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 = (size >> 2) - 2; + + if (pI915XvMC->deviceID == PCI_CHIP_I915_G || + pI915XvMC->deviceID == PCI_CHIP_I915_GM || + pI915XvMC->deviceID == PCI_CHIP_I945_G || + pI915XvMC->deviceID == PCI_CHIP_I945_GM) + mem_select = 0; + + load_indirect->dw0.mem_select = mem_select; + + /* SIS */ + sis = (sis_state *)(++load_indirect); + sis->dw0.valid = 1; + sis->dw0.force = 1; + sis->dw1.length = 16; // 4 * 3 + 2 + 3 - 1 + + if (mem_select) + sis->dw0.buffer_address = (pI915XvMC->sis.offset >> 2); + else + sis->dw0.buffer_address = (pI915XvMC->sis.bus_addr >> 2); + + /* MSB */ + msb = (msb_state *)(++sis); + msb->dw0.valid = 1; + msb->dw0.force = 1; + msb->dw1.length = 23; // 3 * 8 - 1 + + if (mem_select) + msb->dw0.buffer_address = (pI915XvMC->msb.offset >> 2); + else + msb->dw0.buffer_address = (pI915XvMC->msb.bus_addr >> 2); + + 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, 0, sizeof(set_origin)); + 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_ipicture(XvMCContext *context, XvMCMacroBlock *mb) +{ + struct i915_3dmpeg_macroblock_ipicture macroblock_ipicture; + i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; + + /* 3DMPEG_MACROBLOCK_IPICTURE */ + memset(¯oblock_ipicture, 0, sizeof(macroblock_ipicture)); + macroblock_ipicture.dw0.type = CMD_3D; + macroblock_ipicture.dw0.opcode = OPC_3DMPEG_MACROBLOCK_IPICTURE; + macroblock_ipicture.dw0.dct_type = (mb->dct_type == XVMC_DCT_TYPE_FIELD); + + intelBatchbufferData(pI915XvMC, ¯oblock_ipicture, sizeof(macroblock_ipicture), 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, 0, sizeof(macroblock_0mv)); + 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.mb_intra = 1; /* should be 1 */ + 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) + macroblock_0mv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME; +*/ + + macroblock_0mv.header.dw1.motion_type = 0; // (mb->motion_type & 0x3); + macroblock_0mv.header.dw1.vertical_field_select = 0; // mb->motion_vertical_field_select & 0xf; + macroblock_0mv.header.dw1.coded_block_pattern = mb->coded_block_pattern; + macroblock_0mv.header.dw1.skipped_macroblocks = 0; + + 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, 0, sizeof(macroblock_1fbmv)); + 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.mb_intra = 0; /* should be 0 */ + macroblock_1fbmv.header.dw1.forward = ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0); + macroblock_1fbmv.header.dw1.backward = ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0); + 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 & 0x3f)) + macroblock_1fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME; + + macroblock_1fbmv.header.dw1.motion_type = (mb->motion_type & 0x03); + macroblock_1fbmv.header.dw1.vertical_field_select = (mb->motion_vertical_field_select & 0x0f); + macroblock_1fbmv.header.dw1.coded_block_pattern = mb->coded_block_pattern; + macroblock_1fbmv.header.dw1.skipped_macroblocks = 0; + + fmv.s[0] = mb->PMV[0][0][0]; + fmv.s[1] = mb->PMV[0][0][1]; + bmv.s[0] = mb->PMV[0][1][0]; + bmv.s[1] = mb->PMV[0][1][1]; + + 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, unsigned int ps) +{ + 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, 0, sizeof(macroblock_2fbmv)); + macroblock_2fbmv.header.dw0.type = CMD_3D; + macroblock_2fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK; + macroblock_2fbmv.header.dw0.length = 4; + macroblock_2fbmv.header.dw1.mb_intra = 0; /* should be 0 */ + macroblock_2fbmv.header.dw1.forward = ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0); + macroblock_2fbmv.header.dw1.backward = ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0); + 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 & 0x3f)) + macroblock_2fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME; + + macroblock_2fbmv.header.dw1.motion_type = (mb->motion_type & 0x03); + macroblock_2fbmv.header.dw1.vertical_field_select = (mb->motion_vertical_field_select & 0x0f); + macroblock_2fbmv.header.dw1.coded_block_pattern = mb->coded_block_pattern; + macroblock_2fbmv.header.dw1.skipped_macroblocks = 0; + + fmv.s[0] = mb->PMV[0][0][0]; + fmv.s[1] = mb->PMV[0][0][1]; + fmv.s[2] = mb->PMV[1][0][0]; + fmv.s[3] = mb->PMV[1][0][1]; + bmv.s[0] = mb->PMV[0][1][0]; + bmv.s[1] = mb->PMV[0][1][1]; + bmv.s[2] = mb->PMV[1][1][0]; + bmv.s[3] = mb->PMV[1][1][1]; + + if ((ps & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) { + if ((mb->motion_type & 3) == XVMC_PREDICTION_FIELD) { + fmv.s[0] = mb->PMV[0][0][0]; + fmv.s[1] = mb->PMV[0][0][1] >> 1; + fmv.s[2] = mb->PMV[1][0][0]; + fmv.s[3] = mb->PMV[1][0][1] >> 1; + bmv.s[0] = mb->PMV[0][1][0]; + bmv.s[1] = mb->PMV[0][1][1] >> 1; + bmv.s[2] = mb->PMV[1][1][0]; + bmv.s[3] = mb->PMV[1][1][1] >> 1; + } else if ((mb->motion_type & 3) == XVMC_PREDICTION_DUAL_PRIME) { + fmv.s[0] = mb->PMV[0][0][0]; + fmv.s[1] = mb->PMV[0][0][1] >> 1; + fmv.s[2] = mb->PMV[0][0][0]; + fmv.s[3] = mb->PMV[0][0][1] >> 1; // MPEG2 MV[0][1] isn't used + bmv.s[0] = mb->PMV[1][0][0]; + bmv.s[1] = mb->PMV[1][0][1] >> 1; + bmv.s[2] = mb->PMV[1][1][0]; + bmv.s[3] = mb->PMV[1][1][1] >> 1; + } + } + + 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; /* 0.0 */ + ts->ts0.shadow_enable = 0; + ts->ts0.max_anisotropy = ANISORATIO_2; + ts->ts0.shadow_function = PREFILTEROP_ALWAYS; + ts->ts1.min_lod = 0; /* 0.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; /* 0.0 */ + ts->ts0.shadow_enable = 0; + ts->ts0.max_anisotropy = ANISORATIO_2; + ts->ts0.shadow_function = PREFILTEROP_ALWAYS; + ts->ts1.min_lod = 0; /* 0.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 = 1; + ts->ts1.east_deinterlacer = 0; + ts->ts2.default_color = 0; +} + +static void i915_inst_arith(unsigned int *inst, + unsigned int op, + unsigned int dest, + unsigned int mask, + unsigned int saturate, + unsigned int src0, unsigned int src1, unsigned int src2) +{ + dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)); + *inst = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0)); + inst++; + *inst = (A1_SRC0(src0) | A1_SRC1(src1)); + inst++; + *inst = (A2_SRC1(src1) | A2_SRC2(src2)); +} + +static void i915_inst_decl(unsigned int *inst, + unsigned int type, + unsigned int nr, + unsigned int d0_flags) +{ + unsigned int reg = UREG(type, nr); + + *inst = (D0_DCL | D0_DEST(reg) | d0_flags); + inst++; + *inst = D1_MBZ; + inst++; + *inst = D2_MBZ; +} + +static void i915_inst_texld(unsigned int *inst, + unsigned int op, + unsigned int dest, + unsigned int coord, + unsigned int sampler) +{ + dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)); + *inst = (op | T0_DEST(dest) | T0_SAMPLER(sampler)); + inst++; + *inst = T1_ADDRESS_REG(coord); + inst++; + *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 int *inst; + unsigned int 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; + /* mov oC, c0.0000 */ + inst = (unsigned int*)(++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; + /* dcl t0.xy */ + inst = (unsigned int*)(++pixel_shader_program); + i915_inst_decl(inst, REG_TYPE_T, T_TEX0, D0_CHANNEL_XY); + /* dcl t1.xy */ + inst += 3; + i915_inst_decl(inst, REG_TYPE_T, T_TEX1, D0_CHANNEL_XY); + /* dcl_2D s0 */ + inst += 3; + i915_inst_decl(inst, REG_TYPE_S, 0, D0_SAMPLE_TYPE_2D); + /* texld r0, t0, s0 */ + inst += 3; + dest = UREG(REG_TYPE_R, 0); + src0 = UREG(REG_TYPE_T, 0); /* COORD */ + src1 = UREG(REG_TYPE_S, 0); /* SAMPLER */ + i915_inst_texld(inst, T0_TEXLD, dest, src0, src1); + /* mov oC, r0 */ + inst += 3; + dest = UREG(REG_TYPE_OC, 0); + src0 = UREG(REG_TYPE_R, 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; + /* dcl t2.xy */ + inst = (unsigned int*)(++pixel_shader_program); + i915_inst_decl(inst, REG_TYPE_T, T_TEX2, D0_CHANNEL_XY); + /* dcl t3.xy */ + inst += 3; + i915_inst_decl(inst, REG_TYPE_T, T_TEX3, D0_CHANNEL_XY); + /* dcl_2D s1 */ + inst += 3; + i915_inst_decl(inst, REG_TYPE_S, 1, D0_SAMPLE_TYPE_2D); + /* texld r0, t2, s1 */ + inst += 3; + dest = UREG(REG_TYPE_R, 0); + src0 = UREG(REG_TYPE_T, 2); /* COORD */ + src1 = UREG(REG_TYPE_S, 1); /* SAMPLER */ + i915_inst_texld(inst, T0_TEXLD, dest, src0, src1); + /* mov oC, r0 */ + inst += 3; + dest = UREG(REG_TYPE_OC, 0); + src0 = UREG(REG_TYPE_R, 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; + /* dcl t0.xy */ + inst = (unsigned int*)(++pixel_shader_program); + i915_inst_decl(inst, REG_TYPE_T, T_TEX0, D0_CHANNEL_XY); + /* dcl t1.xy */ + inst += 3; + i915_inst_decl(inst, REG_TYPE_T, T_TEX1, D0_CHANNEL_XY); + /* dcl t2.xy */ + inst += 3; + i915_inst_decl(inst, REG_TYPE_T, T_TEX2, D0_CHANNEL_XY); + /* dcl t3.xy */ + inst += 3; + i915_inst_decl(inst, REG_TYPE_T, T_TEX3, D0_CHANNEL_XY); + /* dcl_2D s0 */ + inst += 3; + i915_inst_decl(inst, REG_TYPE_S, 0, D0_SAMPLE_TYPE_2D); + /* dcl_2D s1 */ + inst += 3; + i915_inst_decl(inst, REG_TYPE_S, 1, D0_SAMPLE_TYPE_2D); + /* texld r0, t0, s0 */ + inst += 3; + dest = UREG(REG_TYPE_R, 0); + src0 = UREG(REG_TYPE_T, 0); /* COORD */ + src1 = UREG(REG_TYPE_S, 0); /* SAMPLER */ + i915_inst_texld(inst, T0_TEXLD, dest, src0, src1); + /* texld r1, t2, s1 */ + inst += 3; + dest = UREG(REG_TYPE_R, 1); + src0 = UREG(REG_TYPE_T, 2); /* COORD */ + src1 = UREG(REG_TYPE_S, 1); /* SAMPLER */ + i915_inst_texld(inst, T0_TEXLD, dest, src0, src1); + /* add r0, r0, r1 */ + 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, + 0 /* A0_DEST_SATURATE */, src0, src1, src2); + /* mul oC, r0, c0 */ + inst += 3; + dest = UREG(REG_TYPE_OC, 0); + src0 = UREG(REG_TYPE_R, 0); + src1 = UREG(REG_TYPE_CONST, 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 int size; + void *base = NULL; + int mem_select = 1; + + /* 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 = (size >> 2) - 2; + + 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 = (size >> 2) - 2; + + if (pI915XvMC->deviceID == PCI_CHIP_I915_G || + pI915XvMC->deviceID == PCI_CHIP_I915_GM || + pI915XvMC->deviceID == PCI_CHIP_I945_G || + pI915XvMC->deviceID == PCI_CHIP_I945_GM) + mem_select = 0; + + load_indirect->dw0.mem_select = mem_select; + + /* 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.force = 1; + ssb->dw1.length = 7; /* 8 - 1 */ + + if (mem_select) + ssb->dw0.buffer_address = (pI915XvMC->ssb.offset >> 2); + else + ssb->dw0.buffer_address = (pI915XvMC->ssb.bus_addr >> 2); + + /* PSP */ + psp = (psp_state *)(++ssb); + psp->dw0.valid = 1; + psp->dw0.force = 1; + psp->dw1.length = 66; /* 4 + 16 + 16 + 31 - 1 */ + + if (mem_select) + psp->dw0.buffer_address = (pI915XvMC->psp.offset >> 2); + else + psp->dw0.buffer_address = (pI915XvMC->psp.bus_addr >> 2); + + /* PSC */ + psc = (psc_state *)(++psp); + psc->dw0.valid = 1; + psc->dw0.force = 1; + psc->dw1.length = 5; /* 6 - 1 */ + + if (mem_select) + psc->dw0.buffer_address = (pI915XvMC->psc.offset >> 2); + else + psc->dw0.buffer_address = (pI915XvMC->psc.bus_addr >> 2); + + intelBatchbufferData(pI915XvMC, base, size, 0); + free(base); +} + +static void i915_mc_invalidate_subcontext_buffers(XvMCContext *context, unsigned int mask) +{ + struct i915_3dstate_load_indirect *load_indirect = NULL; + sis_state *sis = NULL; + dis_state *dis = NULL; + ssb_state *ssb = NULL; + msb_state *msb = NULL; + psp_state *psp = NULL; + psc_state *psc = NULL; + i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; + unsigned int size; + void *base = NULL, *ptr = NULL; + + size = sizeof(*load_indirect); + if (mask & BLOCK_SIS) + size += sizeof(*sis); + if (mask & BLOCK_DIS) + size += sizeof(*dis); + if (mask & BLOCK_SSB) + size += sizeof(*ssb); + if (mask & BLOCK_MSB) + size += sizeof(*msb); + if (mask & BLOCK_PSP) + size += sizeof(*psp); + if (mask & BLOCK_PSC) + size += sizeof(*psc); + + if (size == sizeof(*load_indirect)) { + XVMC_ERR("There must be at least one bit set\n"); + return; + } + + /* 3DSTATE_LOAD_INDIRECT */ + 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; + + if (pI915XvMC->deviceID == PCI_CHIP_I915_G || + pI915XvMC->deviceID == PCI_CHIP_I915_GM || + pI915XvMC->deviceID == PCI_CHIP_I945_G || + pI915XvMC->deviceID == PCI_CHIP_I945_GM) + load_indirect->dw0.mem_select = 0; + else + load_indirect->dw0.mem_select = 1; + + load_indirect->dw0.block_mask = mask; + load_indirect->dw0.length = (size >> 2) - 2; + ptr = ++load_indirect; + + /* SIS */ + if (mask & BLOCK_SIS) { + sis = (sis_state *)ptr; + sis->dw0.valid = 0; + sis->dw0.buffer_address = 0; + sis->dw1.length = 0; + ptr = ++sis; + } + + /* DIS */ + if (mask & BLOCK_DIS) { + dis = (dis_state *)ptr; + dis->dw0.valid = 0; + dis->dw0.reset = 0; + dis->dw0.buffer_address = 0; + ptr = ++dis; + } + + /* SSB */ + if (mask & BLOCK_SSB) { + ssb = (ssb_state *)ptr; + ssb->dw0.valid = 0; + ssb->dw0.buffer_address = 0; + ssb->dw1.length = 0; + ptr = ++ssb; + } + + /* MSB */ + if (mask & BLOCK_MSB) { + msb = (msb_state *)ptr; + msb->dw0.valid = 0; + msb->dw0.buffer_address = 0; + msb->dw1.length = 0; + ptr = ++msb; + } + + /* PSP */ + if (mask & BLOCK_PSP) { + psp = (psp_state *)ptr; + psp->dw0.valid = 0; + psp->dw0.buffer_address = 0; + psp->dw1.length = 0; + ptr = ++psp; + } + + /* PSC */ + if (mask & BLOCK_PSC) { + psc = (psc_state *)ptr; + psc->dw0.valid = 0; + psc->dw0.buffer_address = 0; + psc->dw1.length = 0; + ptr = ++psc; + } + + intelBatchbufferData(pI915XvMC, base, size, 0); + free(base); +} + +static int i915_xvmc_map_buffers(i915XvMCContext *pI915XvMC) +{ + if (drmMap(xvmc_driver->fd, + pI915XvMC->sis.handle, + pI915XvMC->sis.size, + (drmAddress *)&pI915XvMC->sis.map) != 0) { + return -1; + } + + if (drmMap(xvmc_driver->fd, + pI915XvMC->ssb.handle, + pI915XvMC->ssb.size, + (drmAddress *)&pI915XvMC->ssb.map) != 0) { + return -1; + } + + if (drmMap(xvmc_driver->fd, + pI915XvMC->msb.handle, + pI915XvMC->msb.size, + (drmAddress *)&pI915XvMC->msb.map) != 0) { + return -1; + } + + if (drmMap(xvmc_driver->fd, + pI915XvMC->psp.handle, + pI915XvMC->psp.size, + (drmAddress *)&pI915XvMC->psp.map) != 0) { + return -1; + } + + if (drmMap(xvmc_driver->fd, + pI915XvMC->psc.handle, + pI915XvMC->psc.size, + (drmAddress *)&pI915XvMC->psc.map) != 0) { + return -1; + } + + if (drmMap(xvmc_driver->fd, + pI915XvMC->corrdata.handle, + pI915XvMC->corrdata.size, + (drmAddress *)&pI915XvMC->corrdata.map) != 0) { + return -1; + } + + if (drmMap(xvmc_driver->fd, + pI915XvMC->batchbuffer.handle, + pI915XvMC->batchbuffer.size, + (drmAddress *)&pI915XvMC->batchbuffer.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->ssb.map) { + drmUnmap(pI915XvMC->ssb.map, pI915XvMC->ssb.size); + pI915XvMC->ssb.map = NULL; + } + + if (pI915XvMC->msb.map) { + drmUnmap(pI915XvMC->msb.map, pI915XvMC->msb.size); + pI915XvMC->msb.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; + } + + if (pI915XvMC->batchbuffer.map) { + drmUnmap(pI915XvMC->batchbuffer.map, pI915XvMC->batchbuffer.size); + pI915XvMC->batchbuffer.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 int 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 = VOFFSET(privTarget); + 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 = (privTarget->uvStride >> 2) - 1; /* in DWords - 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 = YOFFSET(privTarget); + 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 = (privTarget->yStride >> 2) - 1; /* in DWords - 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 = UOFFSET(privTarget); + 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 = (privTarget->uvStride >> 2) - 1; /* in DWords - 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 = 1; + 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 = 2; + ts->ts1.east_deinterlacer = 0; + ts->ts2.default_color = 0; +} + +static void i915_yuv2rgb_static_indirect_state_buffer(XvMCSurface *surface, + unsigned int 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 int *inst; + unsigned int 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; + /* dcl t0.xy */ + inst = (unsigned int*)(++pixel_shader_program); + i915_inst_decl(inst, REG_TYPE_T, T_TEX0, D0_CHANNEL_XY); + /* dcl t1.xy */ + inst += 3; + i915_inst_decl(inst, REG_TYPE_T, T_TEX1, D0_CHANNEL_XY); + /* dcl_2D s0 */ + inst += 3; + i915_inst_decl(inst, REG_TYPE_S, 0, D0_SAMPLE_TYPE_2D); + /* dcl_2D s1 */ + inst += 3; + i915_inst_decl(inst, REG_TYPE_S, 1, D0_SAMPLE_TYPE_2D); + /* dcl_2D s2 */ + inst += 3; + i915_inst_decl(inst, REG_TYPE_S, 2, D0_SAMPLE_TYPE_2D); + /* texld r0 t1 s0 */ + inst += 3; + dest = UREG(REG_TYPE_R, 0); + src0 = UREG(REG_TYPE_T, 1); /* COORD */ + src1 = UREG(REG_TYPE_S, 0); /* SAMPLER */ + i915_inst_texld(inst, T0_TEXLD, dest, src0, src1); + /* texld r0 t0 s1 */ + inst += 3; + dest = UREG(REG_TYPE_R, 0); + src0 = UREG(REG_TYPE_T, 0); /* COORD */ + src1 = UREG(REG_TYPE_S, 1); /* SAMPLER */ + i915_inst_texld(inst, T0_TEXLD, dest, src0, src1); + /* texld oC t1 s2 */ + inst += 3; + dest = UREG(REG_TYPE_OC, 0); + src0 = UREG(REG_TYPE_T, 1); /* COORD */ + src1 = UREG(REG_TYPE_S, 2); /* SAMPLER */ + 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 int 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.mem_select = 1; /* Bearlake only */ + 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: +***************************************************************************/ +//XXX +static void i915_release_resource(Display *display, XvMCContext *context) +{ + i915XvMCContext *pI915XvMC; + int screen = DefaultScreen(display); + + if (!(pI915XvMC = context->privData)) + return; + + pI915XvMC->ref--; + i915_xvmc_unmap_buffers(pI915XvMC); + + driDestroyHashContents(pI915XvMC->drawHash); + drmHashDestroy(pI915XvMC->drawHash); + + pthread_mutex_destroy(&pI915XvMC->ctxmutex); + + XLockDisplay(display); + uniDRIDestroyContext(display, screen, pI915XvMC->id); + XUnlockDisplay(display); + + intelDestroyBatchBuffer(pI915XvMC); + + drmUnmap(xvmc_driver->sarea_address, xvmc_driver->sarea_size); + + if (xvmc_driver->fd >= 0) + drmClose(xvmc_driver->fd); + xvmc_driver->fd = -1; + + XLockDisplay(display); + uniDRICloseConnection(display, screen); + _xvmc_destroy_context(display, context); + XUnlockDisplay(display); + + free(pI915XvMC); + context->privData = NULL; +} + +static Status i915_xvmc_mc_create_context(Display *display, XvMCContext *context, + int priv_count, CARD32 *priv_data) +{ + i915XvMCContext *pI915XvMC = NULL; + I915XvMCCreateContextRec *tmpComm = NULL; + Status ret; + drm_sarea_t *pSAREA; + char *curBusID; + uint magic; + int major, minor; + int isCapable; + + if (priv_count != (sizeof(I915XvMCCreateContextRec) >> 2)) { + XVMC_ERR("_xvmc_create_context() returned incorrect data size!"); + XVMC_INFO("\tExpected %d, got %d", + (int)(sizeof(I915XvMCCreateContextRec) >> 2),priv_count); + _xvmc_destroy_context(display, context); + free(priv_data); + context->privData = NULL; + return BadValue; + } + + context->privData = (void *)calloc(1, sizeof(i915XvMCContext)); + if (!context->privData) { + XVMC_ERR("Unable to allocate resources for XvMC context."); + return BadAlloc; + } + pI915XvMC = (i915XvMCContext *)context->privData; + + tmpComm = (I915XvMCCreateContextRec *)priv_data; + pI915XvMC->ctxno = tmpComm->ctxno; + pI915XvMC->deviceID = tmpComm->deviceID; + pI915XvMC->sis.handle = tmpComm->sis.handle; + pI915XvMC->sis.offset = tmpComm->sis.offset; + pI915XvMC->sis.size = tmpComm->sis.size; + pI915XvMC->ssb.handle = tmpComm->ssb.handle; + pI915XvMC->ssb.offset = tmpComm->ssb.offset; + pI915XvMC->ssb.size = tmpComm->ssb.size; + pI915XvMC->msb.handle = tmpComm->msb.handle; + pI915XvMC->msb.offset = tmpComm->msb.offset; + pI915XvMC->msb.size = tmpComm->msb.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; + + if (pI915XvMC->deviceID == PCI_CHIP_I915_G || + pI915XvMC->deviceID == PCI_CHIP_I915_GM || + pI915XvMC->deviceID == PCI_CHIP_I945_G || + pI915XvMC->deviceID == PCI_CHIP_I945_GM) { + pI915XvMC->sis.bus_addr = tmpComm->sis.bus_addr; + pI915XvMC->ssb.bus_addr = tmpComm->ssb.bus_addr; + pI915XvMC->msb.bus_addr = tmpComm->msb.bus_addr; + pI915XvMC->psp.bus_addr = tmpComm->psp.bus_addr; + pI915XvMC->psc.bus_addr = tmpComm->psc.bus_addr; + } + + pI915XvMC->corrdata.handle = tmpComm->corrdata.handle; + pI915XvMC->corrdata.offset = tmpComm->corrdata.offset; + pI915XvMC->corrdata.size = tmpComm->corrdata.size; + pI915XvMC->batchbuffer.handle = tmpComm->batchbuffer.handle; + pI915XvMC->batchbuffer.offset = tmpComm->batchbuffer.offset; + pI915XvMC->batchbuffer.size = tmpComm->batchbuffer.size; + pI915XvMC->sarea_priv_offset = tmpComm->sarea_priv_offset; + pI915XvMC->depth = tmpComm->depth; + + /* Must free the private data we were passed from X */ + free(priv_data); + priv_data = NULL; + + pSAREA = (drm_sarea_t *)xvmc_driver->sarea_address; + pI915XvMC->driHwLock = (drmLock *)&pSAREA->lock; + pI915XvMC->sarea = (drmI830Sarea*)((char*)pSAREA + pI915XvMC->sarea_priv_offset); + /* + * XXX we don't need to bother X for DRI context, as we're not DRI. */ +#if 0 + ret = XMatchVisualInfo(display, xvmc_driver->screen, + (pI915XvMC->depth == 32) ? 24 : pI915XvMC->depth, TrueColor, + &pI915XvMC->visualInfo); + + if (!ret) { + XVMC_ERR("Could not find a matching TrueColor visual."); + 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)) { + XVMC_ERR("Could not create DRI context."); + free(pI915XvMC); + context->privData = NULL; + drmUnmap(pI915XvMC->sarea_address, pI915XvMC->sarea_size); + return BadAlloc; + } +#endif + + if (NULL == (pI915XvMC->drawHash = drmHashCreate())) { + XVMC_ERR("Could not allocate drawable hash table."); + free(pI915XvMC); + context->privData = NULL; + return BadAlloc; + } + + if (i915_xvmc_map_buffers(pI915XvMC)) { + i915_xvmc_unmap_buffers(pI915XvMC); + free(pI915XvMC); + context->privData = NULL; + return BadAlloc; + } + + /* Initialize private context values */ + pI915XvMC->yStride = STRIDE(context->width); + pI915XvMC->uvStride = STRIDE(context->width >> 1); + pI915XvMC->haveXv = 0; + pI915XvMC->dual_prime = 0; + pI915XvMC->last_flip = 0; + pI915XvMC->locked = 0; + pI915XvMC->port = context->port; + pthread_mutex_init(&pI915XvMC->ctxmutex, NULL); + /* XXX */ + 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 +***************************************************************************/ +static int i915_xvmc_mc_destroy_context(Display *display, XvMCContext *context) +{ + i915XvMCContext *pI915XvMC; + + if (!(pI915XvMC = context->privData)) + return XvMCBadContext; + + /* Pass Control to the X server to destroy the drm_context_t */ + i915_release_resource(display,context); + return Success; +} + +/*************************************************************************** +// Function: XvMCCreateSurface +***************************************************************************/ +static Status i915_xvmc_mc_create_surface(Display *display, XvMCContext *context, XvMCSurface *surface) +{ + Status ret; + i915XvMCContext *pI915XvMC; + i915XvMCSurface *pI915Surface; + I915XvMCCreateSurfaceRec *tmpComm = NULL; + int priv_count; + uint *priv_data; + + if (!display || !context || !display) + return BadValue; + + if (!(pI915XvMC = context->privData)) + return (error_base + XvMCBadContext); + + PPTHREAD_MUTEX_LOCK(pI915XvMC); + surface->privData = (i915XvMCSurface *)malloc(sizeof(i915XvMCSurface)); + + if (!(pI915Surface = surface->privData)) { + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return BadAlloc; + } + + /* Initialize private values */ + pI915Surface->last_render = 0; + pI915Surface->last_flip = 0; + pI915Surface->yStride = pI915XvMC->yStride; + pI915Surface->uvStride = pI915XvMC->uvStride; + pI915Surface->width = context->width; + pI915Surface->height = context->height; + pI915Surface->privContext = pI915XvMC; + pI915Surface->privSubPic = NULL; + pI915Surface->srf.map = NULL; + XLockDisplay(display); + + if ((ret = _xvmc_create_surface(display, context, surface, + &priv_count, &priv_data))) { + XUnlockDisplay(display); + XVMC_ERR("Unable to create XvMCSurface."); + free(pI915Surface); + surface->privData = NULL; + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return ret; + } + + XUnlockDisplay(display); + + if (priv_count != (sizeof(I915XvMCCreateSurfaceRec) >> 2)) { + XVMC_ERR("_xvmc_create_surface() returned incorrect data size!"); + XVMC_INFO("\tExpected %d, got %d", + (int)(sizeof(I915XvMCCreateSurfaceRec) >> 2), priv_count); + _xvmc_destroy_surface(display, surface); + free(priv_data); + free(pI915Surface); + surface->privData = NULL; + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return BadAlloc; + } + + tmpComm = (I915XvMCCreateSurfaceRec *)priv_data; + + pI915Surface->srfNo = tmpComm->srfno; + pI915Surface->srf.handle = tmpComm->srf.handle; + pI915Surface->srf.offset = tmpComm->srf.offset; + pI915Surface->srf.size = tmpComm->srf.size; + free(priv_data); + + if (drmMap(xvmc_driver->fd, + pI915Surface->srf.handle, + pI915Surface->srf.size, + (drmAddress *)&pI915Surface->srf.map) != 0) { + _xvmc_destroy_surface(display, surface); + free(pI915Surface); + surface->privData = NULL; + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return BadAlloc; + } + + pI915XvMC->ref++; + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return 0; +} + + +/*************************************************************************** +// Function: XvMCDestroySurface +***************************************************************************/ +static int i915_xvmc_mc_destroy_surface(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); + + if (pI915Surface->srf.map) + drmUnmap(pI915Surface->srf.map, pI915Surface->srf.size); + + XLockDisplay(display); + _xvmc_destroy_surface(display, surface); + XUnlockDisplay(display); + + free(pI915Surface); + surface->privData = NULL; + pI915XvMC->ref--; + + 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. +***************************************************************************/ +static int i915_xvmc_mc_render_surface(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; + int picture_coding_type = MPEG_I_PICTURE; + /* 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 || !context || !target_surface) { + XVMC_ERR("Invalid Display, Context or Target!"); + return BadValue; + } + + if (!num_macroblocks) + return Success; + + if (!macroblock_array || !blocks) { + XVMC_ERR("Invalid block data!"); + return BadValue; + } + + if (macroblock_array->num_blocks < (num_macroblocks + first_macroblock)) { + XVMC_ERR("Too many macroblocks requested for MB array size."); + 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) { + XVMC_ERR("HWMC only possible on YV12 Surfaces."); + return BadValue; + } + + /* P Frame Test */ + if (!past_surface) { + /* Just to avoid some ifs later. */ + privPast = privTarget; + } else { + if (!(privPast = past_surface->privData)) { + XVMC_ERR("Invalid Past Surface!"); + return (error_base + XvMCBadSurface); + } + + picture_coding_type = MPEG_P_PICTURE; + } + + /* B Frame Test */ + if (!future_surface) { + privFuture = privPast; // privTarget; + } else { + if (!past_surface) { + XVMC_ERR("No Past Surface!"); + return BadValue; + } + + if (!(privFuture = future_surface->privData)) { + XVMC_ERR("Invalid Future Surface!"); + return (error_base + XvMCBadSurface); + } + + picture_coding_type = MPEG_B_PICTURE; + } + + LOCK_HARDWARE(pI915XvMC); + 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; + XVMC_INFO("reset x"); + } + + if (mb->y > (target_surface->height >> 4)) { + mb->y = 0; + XVMC_INFO("reset y"); + } + + /* Catch no pattern case */ + if (!(mb->macroblock_type & XVMC_MB_TYPE_PATTERN) && + !(mb->macroblock_type & XVMC_MB_TYPE_INTRA) && + mb->coded_block_pattern) { + mb->coded_block_pattern = 0; + XVMC_INFO("no coded blocks present!"); + } + + bspm = mb_bytes[mb->coded_block_pattern]; + + if (!bspm) + continue; + + corrdata_size += bspm; + + if (corrdata_size > pI915XvMC->corrdata.size) { + XVMC_ERR("correction data buffer overflow."); + break; + } + memcpy(corrdata_ptr, block_ptr, bspm); + corrdata_ptr += bspm; + } + + i915_flush(pI915XvMC, 1, 0); + // i915_mc_invalidate_subcontext_buffers(context, BLOCK_SIS | BLOCK_DIS | BLOCK_SSB + // | BLOCK_MSB | BLOCK_PSP | BLOCK_PSC); + + 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, flags, + picture_coding_type); + i915_mc_map_state_buffer(context, privTarget, privPast, privFuture); + i915_mc_load_sis_msb_buffers(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_ipicture(context, mb); + } else if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) { /* Frame Picture */ + switch (mb->motion_type & 3) { + case XVMC_PREDICTION_FIELD: /* Field Based */ + i915_mc_mpeg_macroblock_2fbmv(context, mb, picture_structure); + break; + + case XVMC_PREDICTION_FRAME: /* Frame Based */ + i915_mc_mpeg_macroblock_1fbmv(context, mb); + break; + + case XVMC_PREDICTION_DUAL_PRIME: /* Dual Prime */ + i915_mc_mpeg_macroblock_2fbmv(context, mb, picture_structure); + break; + + default: /* No Motion Type */ + renderError(); + break; + } + } else { /* Frame Picture */ + switch (mb->motion_type & 3) { + case XVMC_PREDICTION_FIELD: /* Field Based */ + i915_mc_mpeg_macroblock_1fbmv(context, mb); + break; + + case XVMC_PREDICTION_16x8: /* 16x8 MC */ + i915_mc_mpeg_macroblock_2fbmv(context, mb, picture_structure); + break; + + case XVMC_PREDICTION_DUAL_PRIME: /* Dual Prime */ + i915_mc_mpeg_macroblock_1fbmv(context, mb); + break; + + default: /* No Motion Type */ + renderError(); + break; + } + } /* Field Picture */ + } + + intelFlushBatch(pI915XvMC, TRUE); + pI915XvMC->last_render = pI915XvMC->alloc.irq_emitted; + privTarget->last_render = pI915XvMC->last_render; + + UNLOCK_HARDWARE(pI915XvMC); + return 0; +} + +/*************************************************************************** +// 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. +***************************************************************************/ +static int i915_xvmc_mc_put_surface(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); + + PPTHREAD_MUTEX_LOCK(pI915XvMC); + /* + if (getDRIDrawableInfoLocked(pI915XvMC->drawHash, display, + pI915XvMC->screen, draw, 0, pI915XvMC->fd, pI915XvMC->hHWContext, + pI915XvMC->sarea_address, FALSE, &drawInfo, sizeof(*drawInfo))) { + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + 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 = INTEL_XVMC_COMMAND_DISPLAY; + buf.ctxNo = pI915XvMC->ctxno; + buf.srfNo = pI915Surface->srfNo; + pI915SubPic = pI915Surface->privSubPic; + buf.subPicNo = (!pI915SubPic ? 0 : pI915SubPic->srfNo); + 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); + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + + return ret; + } + + XSync(display, 0); + XUnlockDisplay(display); + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + + return 0; +} + +/*************************************************************************** +// Function: XvMCSyncSurface +// Arguments: +// display - Connection to the X server +// surface - The surface to synchronize +// Info: +// Returns: Status +***************************************************************************/ +#if 0 +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; +} +#endif + +/*************************************************************************** +// 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. +***************************************************************************/ +static int i915_xvmc_mc_get_surface_status(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); + PPTHREAD_MUTEX_LOCK(pI915XvMC); + if (pI915Surface->last_flip) { + /* This can not happen */ + if (pI915XvMC->last_flip < pI915Surface->last_flip) { + XVMC_ERR("Context last flip is less than surface last flip."); + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + 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); + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return 0; +} + +/*************************************************************************** +// +// 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 +***************************************************************************/ +#if 0 +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) +{ + Status ret; + i915XvMCContext *pI915XvMC; + i915XvMCSubpicture *pI915Subpicture; + I915XvMCCreateSurfaceRec *tmpComm = NULL; + int priv_count; + uint *priv_data; + + 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; + + PPTHREAD_MUTEX_LOCK(pI915XvMC); + subpicture->context_id = context->context_id; + subpicture->xvimage_id = xvimage_id; + subpicture->width = width; + subpicture->height = height; + pI915Subpicture = (i915XvMCSubpicture *)subpicture->privData; + + XLockDisplay(display); + if ((ret = _xvmc_create_subpicture(display, context, subpicture, + &priv_count, &priv_data))) { + XUnlockDisplay(display); + XVMC_ERR("Unable to create XvMCSubpicture."); + free(pI915Subpicture); + subpicture->privData = NULL; + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return ret; + } + XUnlockDisplay(display); + + if (priv_count != (sizeof(I915XvMCCreateSurfaceRec) >> 2)) { + XVMC_ERR("_xvmc_create_subpicture() returned incorrect data size!"); + XVMC_INFO("\tExpected %d, got %d", + (int)(sizeof(I915XvMCCreateSurfaceRec) >> 2), priv_count); + XLockDisplay(display); + _xvmc_destroy_subpicture(display, subpicture); + XUnlockDisplay(display); + free(priv_data); + free(pI915Subpicture); + subpicture->privData = NULL; + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return BadAlloc; + } + + tmpComm = (I915XvMCCreateSurfaceRec *)priv_data; + pI915Subpicture->srfNo = tmpComm->srfno; + pI915Subpicture->srf.handle = tmpComm->srf.handle; + pI915Subpicture->srf.offset = tmpComm->srf.offset; + pI915Subpicture->srf.size = tmpComm->srf.size; + free(priv_data); + + if (drmMap(pI915XvMC->fd, + pI915Subpicture->srf.handle, + pI915Subpicture->srf.size, + (drmAddress *)&pI915Subpicture->srf.map) != 0) { + XLockDisplay(display); + _xvmc_destroy_subpicture(display, subpicture); + XUnlockDisplay(display); + free(pI915Subpicture); + subpicture->privData = NULL; + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return BadAlloc; + } + + /* 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->pitch = ((subpicture->width + 3) & ~3); + + switch(subpicture->xvimage_id) { + case FOURCC_IA44: + case FOURCC_AI44: + break; + + default: + drmUnmap(pI915Subpicture->srf.map, pI915Subpicture->srf.size); + XLockDisplay(display); + _xvmc_destroy_subpicture(display, subpicture); + XUnlockDisplay(display); + free(pI915Subpicture); + subpicture->privData = NULL; + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return BadMatch; + } + + pI915XvMC->ref++; + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + 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); + + if (pI915Subpicture->srf.map) + drmUnmap(pI915Subpicture->srf.map, pI915Subpicture->srf.size); + + PPTHREAD_MUTEX_LOCK(pI915XvMC); + XLockDisplay(display); + _xvmc_destroy_subpicture(display,subpicture); + XUnlockDisplay(display); + + free(pI915Subpicture); + subpicture->privData = NULL; + pI915XvMC->ref--; + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + + 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); + PPTHREAD_MUTEX_LOCK(pI915XvMC); + /* FIXME: */ + if (pI915Subpicture->last_render && + (pI915Subpicture->last_render > pI915XvMC->sarea->last_dispatch)) { + *stat |= XVMC_RENDERING; + } + + // UNLOCK_HARDWARE(pI915XvMC); + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return Success; +} + +#endif diff --git a/src/xvmc/I915XvMC.h b/src/xvmc/I915XvMC.h new file mode 100644 index 0000000..b1d3117 --- /dev/null +++ b/src/xvmc/I915XvMC.h @@ -0,0 +1,156 @@ +/* + * Copyright © 2006 Intel Corporation + * + * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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: + * Xiang Haihao + * + */ + +#ifndef _I915XVMC_H +#define _I915XVMC_H + +/* #define XVMC_DEBUG(x) do {x; }while(0); */ +#define XVMC_DEBUG(x) + +#include "intel_xvmc.h" +#include "i915_hwmc.h" + +#define I915_SUBPIC_PALETTE_SIZE 16 +#define MAX_SUBCONTEXT_LEN 1024 + +#define PCI_CHIP_I915_G 0x2582 +#define PCI_CHIP_I915_GM 0x2592 +#define PCI_CHIP_I945_G 0x2772 +#define PCI_CHIP_I945_GM 0x27A2 +#define PCI_CHIP_I945_GME 0x27AE +#define PCI_CHIP_G33_G 0x29C2 +#define PCI_CHIP_Q35_G 0x29B2 +#define PCI_CHIP_Q33_G 0x29D2 + +/*************************************************************************** +// i915XvMCDrmMap: Holds the data about the DRM maps +***************************************************************************/ +typedef struct _i915XvMCDrmMap { + drm_handle_t handle; + unsigned long offset; + unsigned long size; + unsigned long bus_addr; + drmAddress map; +} i915XvMCDrmMap, *i915XvMCDrmMapPtr; + +/*************************************************************************** +// i915XvMCContext: Private Context data referenced via the privData +// pointer in the XvMCContext structure. +***************************************************************************/ +typedef struct _i915XvMCContext { + unsigned int ctxno; + unsigned int last_render; + unsigned int last_flip; + unsigned int dual_prime; /* Flag to identify when dual prime is in use. */ + unsigned int yStride; + unsigned int uvStride; + unsigned short ref; + pthread_mutex_t ctxmutex; + int lock; /* Lightweight lock to avoid locking twice */ + int locked; + volatile drmI830Sarea *sarea; + + drmLock *driHwLock; + drm_context_t hHWContext; /* drmcontext; */ + unsigned int sarea_priv_offset; /* Offset in sarea to private part */ + unsigned int depth; + XvPortID port; /* Xv Port ID when displaying */ + 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 */ + GC gc; /* X GC needed for displaying */ + Drawable draw; /* Drawable to undisplay from */ + XID id; + XVisualInfo visualInfo; + void *drawHash; + int deviceID; + + i915XvMCDrmMap sis; + i915XvMCDrmMap msb; + i915XvMCDrmMap ssb; + i915XvMCDrmMap psp; + i915XvMCDrmMap psc; + + i915XvMCDrmMap corrdata; + i915XvMCDrmMap batchbuffer; + + sigset_t sa_mask; + + struct { + unsigned int start_offset; + unsigned int size; + unsigned int space; + unsigned char *ptr; + } batch; + + struct + { + void *ptr; + unsigned int size; + unsigned int offset; + unsigned int active_buf; + unsigned int 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 int srfNo; + unsigned int last_render; + unsigned int last_flip; + unsigned int pitch; + unsigned char palette[3][16]; + i915XvMCDrmMap srf; + 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 int srfNo; /* XvMC private surface numbers */ + unsigned int last_render; + unsigned int last_flip; + unsigned int yStride; /* Stride of YUV420 Y component. */ + unsigned int uvStride; + unsigned int width; /* Dimensions */ + unsigned int height; + i915XvMCDrmMap srf; + i915XvMCContext *privContext; + i915XvMCSubpicture *privSubPic; /* Subpicture to be blended when + * displaying. NULL if none. */ +} i915XvMCSurface; + +#endif /* _I915XVMC_H */ diff --git a/src/xvmc/Makefile.am b/src/xvmc/Makefile.am index b5c9db9..09c8c4d 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 libIntelXvMC.la + libI810XvMC_la_SOURCES = I810XvMC.c \ I810XvMC.h @@ -7,4 +8,19 @@ 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@ + +libIntelXvMC_la_SOURCES = intel_xvmc.c \ + intel_xvmc.h \ + I915XvMC.c \ + I915XvMC.h \ + intel_batchbuffer.c \ + intel_batchbuffer.h \ + xf86dri.c \ + xf86dri.h \ + xf86dristr.h \ + driDrawable.c \ + driDrawable.h +libIntelXvMC_la_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(top_srcdir)/src -DTRUE=1 -DFALSE=0 +libIntelXvMC_la_LDFLAGS = -version-number 1:0:0 +libIntelXvMC_la_LIBADD = @DRI_LIBS@ endif diff --git a/src/xvmc/driDrawable.c b/src/xvmc/driDrawable.c new file mode 100644 index 0000000..8386334 --- /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 +#include +#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 0000000..a758c7c --- /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 0000000..82c920e --- /dev/null +++ b/src/xvmc/i915_program.h @@ -0,0 +1,276 @@ +#ifndef _I915_PROGRAM_H +#define _I915_PROGRAM_H + +#define REG_TYPE_R 0 /* temporary regs, no need to + * dcl, must be written before + * read -- Preserved between + * phases. + */ +#define REG_TYPE_T 1 /* Interpolated values, must be + * dcl'ed before use. + * + * 0..7: texture coord, + * 8: diffuse spec, + * 9: specular color, + * 10: fog parameter in w. + */ +#define REG_TYPE_CONST 2 /* Restriction: only one const + * can be referenced per + * instruction, though it may be + * selected for multiple inputs. + * Constants not initialized + * default to zero. + */ +#define REG_TYPE_S 3 /* sampler */ +#define REG_TYPE_OC 4 /* output color (rgba) */ +#define REG_TYPE_OD 5 /* output depth (w), xyz are + * temporaries. If not written, + * interpolated depth is used? + */ +#define REG_TYPE_U 6 /* unpreserved temporaries */ +#define REG_TYPE_MASK 0x7 +#define REG_NR_MASK 0xf + +/* REG_TYPE_T: + */ +#define T_TEX0 0 +#define T_TEX1 1 +#define T_TEX2 2 +#define T_TEX3 3 +#define T_TEX4 4 +#define T_TEX5 5 +#define T_TEX6 6 +#define T_TEX7 7 +#define T_DIFFUSE 8 +#define T_SPECULAR 9 +#define T_FOG_W 10 /* interpolated fog is in W coord */ + +/* Arithmetic instructions */ + +/* .replicate_swizzle == selection and replication of a particular + * scalar channel, ie., .xxxx, .yyyy, .zzzz or .wwww + */ +#define A0_NOP (0x0<<24) /* no operation */ +#define A0_ADD (0x1<<24) /* dst = src0 + src1 */ +#define A0_MOV (0x2<<24) /* dst = src0 */ +#define A0_MUL (0x3<<24) /* dst = src0 * src1 */ +#define A0_MAD (0x4<<24) /* dst = src0 * src1 + src2 */ +#define A0_DP2ADD (0x5<<24) /* dst.xyzw = src0.xy dot src1.xy + src2.replicate_swizzle */ +#define A0_DP3 (0x6<<24) /* dst.xyzw = src0.xyz dot src1.xyz */ +#define A0_DP4 (0x7<<24) /* dst.xyzw = src0.xyzw dot src1.xyzw */ +#define A0_FRC (0x8<<24) /* dst = src0 - floor(src0) */ +#define A0_RCP (0x9<<24) /* dst.xyzw = 1/(src0.replicate_swizzle) */ +#define A0_RSQ (0xa<<24) /* dst.xyzw = 1/(sqrt(abs(src0.replicate_swizzle))) */ +#define A0_EXP (0xb<<24) /* dst.xyzw = exp2(src0.replicate_swizzle) */ +#define A0_LOG (0xc<<24) /* dst.xyzw = log2(abs(src0.replicate_swizzle)) */ +#define A0_CMP (0xd<<24) /* dst = (src0 >= 0.0) ? src1 : src2 */ +#define A0_MIN (0xe<<24) /* dst = (src0 < src1) ? src0 : src1 */ +#define A0_MAX (0xf<<24) /* dst = (src0 >= src1) ? src0 : src1 */ +#define A0_FLR (0x10<<24) /* dst = floor(src0) */ +#define A0_MOD (0x11<<24) /* dst = src0 fmod 1.0 */ +#define A0_TRC (0x12<<24) /* dst = int(src0) */ +#define A0_SGE (0x13<<24) /* dst = src0 >= src1 ? 1.0 : 0.0 */ +#define A0_SLT (0x14<<24) /* dst = src0 < src1 ? 1.0 : 0.0 */ +#define A0_DEST_SATURATE (1<<22) +#define A0_DEST_TYPE_SHIFT 19 +/* Allow: R, OC, OD, U */ +#define A0_DEST_NR_SHIFT 14 +/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */ +#define A0_DEST_CHANNEL_X (1<<10) +#define A0_DEST_CHANNEL_Y (2<<10) +#define A0_DEST_CHANNEL_Z (4<<10) +#define A0_DEST_CHANNEL_W (8<<10) +#define A0_DEST_CHANNEL_ALL (0xf<<10) +#define A0_DEST_CHANNEL_SHIFT 10 +#define A0_SRC0_TYPE_SHIFT 7 +#define A0_SRC0_NR_SHIFT 2 + +#define A0_DEST_CHANNEL_XY (A0_DEST_CHANNEL_X|A0_DEST_CHANNEL_Y) +#define A0_DEST_CHANNEL_XYZ (A0_DEST_CHANNEL_XY|A0_DEST_CHANNEL_Z) + +#define SRC_X 0 +#define SRC_Y 1 +#define SRC_Z 2 +#define SRC_W 3 +#define SRC_ZERO 4 +#define SRC_ONE 5 + +#define A1_SRC0_CHANNEL_X_NEGATE (1<<31) +#define A1_SRC0_CHANNEL_X_SHIFT 28 +#define A1_SRC0_CHANNEL_Y_NEGATE (1<<27) +#define A1_SRC0_CHANNEL_Y_SHIFT 24 +#define A1_SRC0_CHANNEL_Z_NEGATE (1<<23) +#define A1_SRC0_CHANNEL_Z_SHIFT 20 +#define A1_SRC0_CHANNEL_W_NEGATE (1<<19) +#define A1_SRC0_CHANNEL_W_SHIFT 16 +#define A1_SRC1_TYPE_SHIFT 13 +#define A1_SRC1_NR_SHIFT 8 +#define A1_SRC1_CHANNEL_X_NEGATE (1<<7) +#define A1_SRC1_CHANNEL_X_SHIFT 4 +#define A1_SRC1_CHANNEL_Y_NEGATE (1<<3) +#define A1_SRC1_CHANNEL_Y_SHIFT 0 + +#define A2_SRC1_CHANNEL_Z_NEGATE (1<<31) +#define A2_SRC1_CHANNEL_Z_SHIFT 28 +#define A2_SRC1_CHANNEL_W_NEGATE (1<<27) +#define A2_SRC1_CHANNEL_W_SHIFT 24 +#define A2_SRC2_TYPE_SHIFT 21 +#define A2_SRC2_NR_SHIFT 16 +#define A2_SRC2_CHANNEL_X_NEGATE (1<<15) +#define A2_SRC2_CHANNEL_X_SHIFT 12 +#define A2_SRC2_CHANNEL_Y_NEGATE (1<<11) +#define A2_SRC2_CHANNEL_Y_SHIFT 8 +#define A2_SRC2_CHANNEL_Z_NEGATE (1<<7) +#define A2_SRC2_CHANNEL_Z_SHIFT 4 +#define A2_SRC2_CHANNEL_W_NEGATE (1<<3) +#define A2_SRC2_CHANNEL_W_SHIFT 0 + +/* Declaration instructions */ +#define D0_DCL (0x19<<24) /* Declare a t (interpolated attrib) + * register or an s (sampler) + * register. */ +#define D0_SAMPLE_TYPE_SHIFT 22 +#define D0_SAMPLE_TYPE_2D (0x0<<22) +#define D0_SAMPLE_TYPE_CUBE (0x1<<22) +#define D0_SAMPLE_TYPE_VOLUME (0x2<<22) +#define D0_SAMPLE_TYPE_MASK (0x3<<22) + +#define D0_TYPE_SHIFT 19 +/* Allow: T, S */ +#define D0_NR_SHIFT 14 +/* Allow T: 0..10, S: 0..15 */ +#define D0_CHANNEL_X (1<<10) +#define D0_CHANNEL_Y (2<<10) +#define D0_CHANNEL_Z (4<<10) +#define D0_CHANNEL_W (8<<10) +#define D0_CHANNEL_ALL (0xf<<10) +#define D0_CHANNEL_NONE (0<<10) + +#define D0_CHANNEL_XY (D0_CHANNEL_X|D0_CHANNEL_Y) +#define D0_CHANNEL_XYZ (D0_CHANNEL_XY|D0_CHANNEL_Z) + +/* I915 Errata: Do not allow (xz), (xw), (xzw) combinations for diffuse + * or specular declarations. + * + * For T dcls, only allow: (x), (xy), (xyz), (w), (xyzw) + * + * Must be zero for S (sampler) dcls + */ +#define D1_MBZ 0 +#define D2_MBZ 0 + +/* Texture instructions */ +#define T0_TEXLD (0x15<<24) /* Sample texture using predeclared + * sampler and address, and output + * filtered texel data to destination + * register */ +#define T0_TEXLDP (0x16<<24) /* Same as texld but performs a + * perspective divide of the texture + * coordinate .xyz values by .w before + * sampling. */ +#define T0_TEXLDB (0x17<<24) /* Same as texld but biases the + * computed LOD by w. Only S4.6 two's + * comp is used. This implies that a + * float to fixed conversion is + * done. */ +#define T0_TEXKILL (0x18<<24) /* Does not perform a sampling + * operation. Simply kills the pixel + * if any channel of the address + * register is < 0.0. */ +#define T0_DEST_TYPE_SHIFT 19 +/* Allow: R, OC, OD, U */ +/* Note: U (unpreserved) regs do not retain their values between + * phases (cannot be used for feedback) + * + * Note: oC and OD registers can only be used as the destination of a + * texture instruction once per phase (this is an implementation + * restriction). + */ +#define T0_DEST_NR_SHIFT 14 +/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */ +#define T0_SAMPLER_NR_SHIFT 0 /* This field ignored for TEXKILL */ +#define T0_SAMPLER_NR_MASK (0xf<<0) + +#define T1_ADDRESS_REG_TYPE_SHIFT 24 /* Reg to use as texture coord */ +/* Allow R, T, OC, OD -- R, OC, OD are 'dependent' reads, new program phase */ +#define T1_ADDRESS_REG_NR_SHIFT 17 +#define T2_MBZ 0 + + +/* Having zero and one in here makes the definition of swizzle a lot + * easier. + */ +#define UREG_TYPE_SHIFT 29 +#define UREG_NR_SHIFT 24 +#define UREG_CHANNEL_X_NEGATE_SHIFT 23 +#define UREG_CHANNEL_X_SHIFT 20 +#define UREG_CHANNEL_Y_NEGATE_SHIFT 19 +#define UREG_CHANNEL_Y_SHIFT 16 +#define UREG_CHANNEL_Z_NEGATE_SHIFT 15 +#define UREG_CHANNEL_Z_SHIFT 12 +#define UREG_CHANNEL_W_NEGATE_SHIFT 11 +#define UREG_CHANNEL_W_SHIFT 8 +#define UREG_CHANNEL_ZERO_NEGATE_MBZ 5 +#define UREG_CHANNEL_ZERO_SHIFT 4 +#define UREG_CHANNEL_ONE_NEGATE_MBZ 1 +#define UREG_CHANNEL_ONE_SHIFT 0 + +#define UREG_BAD 0xffffffff /* not a valid ureg */ + +#define X SRC_X +#define Y SRC_Y +#define Z SRC_Z +#define W SRC_W +#define ZERO SRC_ZERO +#define ONE SRC_ONE + +/* Construct a ureg: + */ +#define UREG(type, nr) (((type) << UREG_TYPE_SHIFT) | \ + ((nr) << UREG_NR_SHIFT) | \ + (X << UREG_CHANNEL_X_SHIFT) | \ + (Y << UREG_CHANNEL_Y_SHIFT) | \ + (Z << UREG_CHANNEL_Z_SHIFT) | \ + (W << UREG_CHANNEL_W_SHIFT) | \ + (ZERO << UREG_CHANNEL_ZERO_SHIFT) | \ + (ONE << UREG_CHANNEL_ONE_SHIFT)) + +#define GET_CHANNEL_SRC( reg, channel ) ((reg<<(channel*4)) & (0xf<<20)) +#define CHANNEL_SRC( src, channel ) (src>>(channel*4)) + +#define GET_UREG_TYPE(reg) (((reg) >> UREG_TYPE_SHIFT) & REG_TYPE_MASK) +#define GET_UREG_NR(reg) (((reg) >> UREG_NR_SHIFT) & REG_NR_MASK) + +#define UREG_XYZW_CHANNEL_MASK 0x00ffff00 + +#define A0_DEST(reg) (((reg) & UREG_TYPE_NR_MASK) >> UREG_A0_DEST_SHIFT_LEFT) +#define D0_DEST(reg) (((reg) & UREG_TYPE_NR_MASK) >> UREG_A0_DEST_SHIFT_LEFT) +#define T0_DEST(reg) (((reg) & UREG_TYPE_NR_MASK) >> UREG_A0_DEST_SHIFT_LEFT) +#define A0_SRC0(reg) (((reg) & UREG_MASK) >> UREG_A0_SRC0_SHIFT_LEFT) +#define A1_SRC0(reg) (((reg) & UREG_MASK) << UREG_A1_SRC0_SHIFT_RIGHT) +#define A1_SRC1(reg) (((reg) & UREG_MASK) >> UREG_A1_SRC1_SHIFT_LEFT) +#define A2_SRC1(reg) (((reg) & UREG_MASK) << UREG_A2_SRC1_SHIFT_RIGHT) +#define A2_SRC2(reg) (((reg) & UREG_MASK) >> UREG_A2_SRC2_SHIFT_LEFT) + +/* These are special, and don't have swizzle/negate bits. + */ +#define T0_SAMPLER( reg ) (GET_UREG_NR(reg) << T0_SAMPLER_NR_SHIFT) +#define T1_ADDRESS_REG( reg ) ((GET_UREG_NR(reg) << T1_ADDRESS_REG_NR_SHIFT) | \ + (GET_UREG_TYPE(reg) << T1_ADDRESS_REG_TYPE_SHIFT)) + + +/* Macros for translating UREG's into the various register fields used + * by the I915 programmable unit. + */ +#define UREG_A0_DEST_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_DEST_TYPE_SHIFT) +#define UREG_A0_SRC0_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_SRC0_TYPE_SHIFT) +#define UREG_A1_SRC0_SHIFT_RIGHT (A1_SRC0_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT) +#define UREG_A1_SRC1_SHIFT_LEFT (UREG_TYPE_SHIFT - A1_SRC1_TYPE_SHIFT) +#define UREG_A2_SRC1_SHIFT_RIGHT (A2_SRC1_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT) +#define UREG_A2_SRC2_SHIFT_LEFT (UREG_TYPE_SHIFT - A2_SRC2_TYPE_SHIFT) + +#define UREG_MASK 0xffffff00 +#define UREG_TYPE_NR_MASK ((REG_TYPE_MASK << UREG_TYPE_SHIFT) | \ + (REG_NR_MASK << UREG_NR_SHIFT)) + +#endif diff --git a/src/xvmc/i915_structs.h b/src/xvmc/i915_structs.h new file mode 100644 index 0000000..a25d734 --- /dev/null +++ b/src/xvmc/i915_structs.h @@ -0,0 +1,973 @@ +/* + * Copyright © 2006 Intel Corporation + * + * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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: + * Xiang Haihao + * + */ + +#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; +}; + +/* BLT */ +#define CMD_2D 0x02 +#define OPC_COLOR_BLT (0x40) + +struct i915_color_blt +{ + struct { + unsigned length : 5; + unsigned pad0 : 15; + unsigned bpp_mask : 2; + unsigned opcode : 7; + unsigned type : 3; + } dw0; + + struct { + unsigned pitch : 16; + unsigned rop : 8; + unsigned color_depth : 2; + unsigned pad0 : 6; + } dw1; + + struct { + unsigned width : 16; + unsigned height : 16; + } dw2; + + struct { + unsigned address; + } dw3; + + struct { + unsigned pattern; + } dw4; +}; + +/* 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_SCISSOR_ENABLE (0x10 + (0x1c << 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_3DSTATE_MODES_5 (0x0c) +#define OPC_3DSTATE_COORD_SET_BINDINGS (0x16) +#define OPC_3DPRIMITIVE (0x1f) + +#define OPC_3DSTATE_DRAWING_RECTANGLE (0x80 + (0x1d << 8)) +#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 mb_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 BUFFERID_DEPTH 7 + +#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_8BIT 0x00 +#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 + +#define MC_SUB_1H 0 +#define MC_SUB_2H 1 +#define MC_SUB_4H 2 + +#define MC_SUB_1V 0 +#define MC_SUB_2V 1 + +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 decode_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 map_mask : 16; + unsigned pad0 : 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 0000000..8b6ff11 --- /dev/null +++ b/src/xvmc/intel_batchbuffer.c @@ -0,0 +1,255 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "I915XvMC.h" +#include "intel_batchbuffer.h" + +#define MI_BATCH_BUFFER_END (0xA << 23) + +int intelEmitIrqLocked(i915XvMCContext *pI915XvMC) +{ + drmI830IrqEmit ie; + int ret, seq; + + ie.irq_seq = &seq; + ret = drmCommandWriteRead(xvmc_driver->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(xvmc_driver->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) { + pI915XvMC->alloc.ptr = NULL; + pI915XvMC->alloc.offset = 0; + } else if (pI915XvMC->alloc.ptr) { + free(pI915XvMC->alloc.ptr); + pI915XvMC->alloc.ptr = NULL; + } + + memset(&pI915XvMC->batch, 0, sizeof(pI915XvMC->batch)); +} + + +void intelInitBatchBuffer(i915XvMCContext *pI915XvMC) +{ + if (pI915XvMC->batchbuffer.map) { + pI915XvMC->alloc.size = pI915XvMC->batchbuffer.size; + pI915XvMC->alloc.offset = pI915XvMC->batchbuffer.offset; + pI915XvMC->alloc.ptr = pI915XvMC->batchbuffer.map; + } else { + pI915XvMC->alloc.size = 8 * 1024; + pI915XvMC->alloc.offset = 0; + 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 & 0x3) == 0); + + intelBatchbufferRequireSpace(pI915XvMC, bytes); + memcpy(pI915XvMC->batch.ptr, data, bytes); + pI915XvMC->batch.ptr += bytes; + pI915XvMC->batch.space -= bytes; + + assert(pI915XvMC->batch.space >= 0); +} + +#define MI_FLUSH ((0 << 29) | (4 << 23)) +#define FLUSH_MAP_CACHE (1 << 0) +#define FLUSH_RENDER_CACHE (0 << 2) +#define FLUSH_WRITE_DIRTY_STATE (1 << 4) +void intelRefillBatchLocked(i915XvMCContext *pI915XvMC, Bool allow_unlock ) +{ + unsigned half = pI915XvMC->alloc.size >> 1; + unsigned buf = (pI915XvMC->alloc.active_buf ^= 1); + unsigned dword[2]; + + dword[0] = MI_FLUSH | FLUSH_WRITE_DIRTY_STATE | FLUSH_RENDER_CACHE | FLUSH_MAP_CACHE; + dword[1] = 0; + intelCmdIoctl(pI915XvMC, (char *)&dword[0], sizeof(dword)); + pI915XvMC->alloc.irq_emitted = intelEmitIrqLocked(pI915XvMC); + + if (pI915XvMC->alloc.irq_emitted) { + intelWaitIrq(pI915XvMC, pI915XvMC->alloc.irq_emitted); + } + + 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) { + if ((batch.used & 0x4) == 0) { + ((int *)pI915XvMC->batch.ptr)[0] = 0; + ((int *)pI915XvMC->batch.ptr)[1] = MI_BATCH_BUFFER_END; + batch.used += 0x8; + pI915XvMC->batch.ptr += 0x8; + } else { + ((int *)pI915XvMC->batch.ptr)[0] = MI_BATCH_BUFFER_END; + batch.used += 0x4; + pI915XvMC->batch.ptr += 0x4; + } + } + + 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) { + if (drmCommandWrite(xvmc_driver->fd, DRM_I830_BATCHBUFFER, &batch, sizeof(batch))) { + fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n", -errno); + exit(1); + } + } 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(xvmc_driver->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(xvmc_driver->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 0000000..5b3e8e1 --- /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/intel_xvmc.c b/src/xvmc/intel_xvmc.c new file mode 100644 index 0000000..804ce49 --- /dev/null +++ b/src/xvmc/intel_xvmc.c @@ -0,0 +1,1309 @@ +/* + * Copyright © 2007 Intel Corporation + * + * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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: + * Zhenyu Wang + * + */ +#include "intel_xvmc.h" + +struct _intel_xvmc_driver *xvmc_driver = NULL; +static int error_base; +static int event_base; + +/* +* 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) +{ + Status ret; + drm_sarea_t *pSAREA; + char *curBusID; + CARD32 *priv_data = NULL; + struct _intel_xvmc_common *comm; + drm_magic_t magic; + int major, minor; + int priv_count; + int isCapable; + int screen = DefaultScreen(display); + + /* Verify Obvious things first */ + if (!display || !context) + return BadValue; + + if (!(flags & XVMC_DIRECT)) { + XVMC_ERR("Indirect Rendering not supported! Using Direct."); + return BadValue; + } + + /* 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; + } +*/ + /* + Width, Height, and flags are checked against surface_type_id + and port for validity inside the X server, no need to check + 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; + + if (!XvMCQueryExtension(display, &event_base, &error_base)) { + XVMC_ERR("XvMCExtension is not available!"); + return BadValue; + } + ret = XvMCQueryVersion(display, &major, &minor); + if (ret) { + XVMC_ERR("XvMCQueryVersion Failed, unable to determine protocol version."); + return ret; + } + + /* XXX: major and minor could be checked in future for XvMC + * protocol capability (i.e H.264/AVC decode available) + */ + + /* + 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))) { + XVMC_ERR("Unable to create XvMC Context."); + return ret; + } + + comm = (struct _intel_xvmc_common *)priv_data; + XVMC_INFO("hw xvmc type %d", comm->type); + //XXX: how to handle different driver types + if (xvmc_driver == NULL || xvmc_driver->type != comm->type) { + switch (comm->type) { + case XVMC_I915_MPEG2_MC: + xvmc_driver = &i915_xvmc_mc_driver; + break; + case XVMC_I965_MPEG2_MC: + case XVMC_I945_MPEG2_VLD: + case XVMC_I965_MPEG2_VLD: + default: + XVMC_ERR("unimplemented xvmc type %d", comm->type); + free(priv_data); + priv_data = NULL; + return BadValue; + } + } else { + XVMC_ERR("wrong hw xvmc type returned\n"); + free(priv_data); + priv_data = NULL; + return BadValue; + } + + if (xvmc_driver == NULL || xvmc_driver->type != comm->type) { + XVMC_ERR("fail to load xvmc driver for type %d\n", comm->type); + return BadValue; + } + xvmc_driver->sarea_size = comm->sarea_size; + + ret = uniDRIQueryDirectRenderingCapable(display, screen, + &isCapable); + if (!ret || !isCapable) { + XVMC_ERR("Direct Rendering is not available on this system!"); + free(priv_data); + return BadValue; + } + + if (!uniDRIOpenConnection(display, screen, + &xvmc_driver->hsarea, &curBusID)) { + XVMC_ERR("Could not open DRI connection to X server!"); + free(priv_data); + return BadValue; + } + + strncpy(xvmc_driver->busID, curBusID, 20); + xvmc_driver->busID[20] = '\0'; + free(curBusID); + + /* Open DRI Device */ + if((xvmc_driver->fd = drmOpen("i915", NULL)) < 0) { + XVMC_ERR("DRM Device could not be opened."); + //(xvmc_driver->fini)(); + xvmc_driver = NULL; + free(priv_data); + return BadValue; + } + + /* Get magic number */ + drmGetMagic(xvmc_driver->fd, &magic); + // context->flags = (unsigned long)magic; + + if (!uniDRIAuthConnection(display, screen, magic)) { + XVMC_ERR("[XvMC]: X server did not allow DRI. Check permissions."); + //(xvmc_driver->fini)(); + xvmc_driver = NULL; + free(priv_data); + return BadAlloc; + } + + /* + * Map DRI Sarea. we always want it right? + */ + if (drmMap(xvmc_driver->fd, xvmc_driver->hsarea, + xvmc_driver->sarea_size, &xvmc_driver->sarea_address) < 0) { + XVMC_ERR("Unable to map DRI SAREA.\n"); + //(xvmc_driver->fini)(); + xvmc_driver = NULL; + free(priv_data); + return BadAlloc; + } + + /* call driver hook. + * driver hook should free priv_data after return if success.*/ + ret = (xvmc_driver->create_context)(display, context, priv_count, priv_data); + if (ret) { + XVMC_ERR("driver create context failed\n"); + free(priv_data); + drmUnmap(xvmc_driver->sarea_address, xvmc_driver->sarea_size); + return ret; + } + + /* FIXME batch buffer */ + //intelInitBatchBuffer(xvmc_driver); + + 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) +{ + Status ret; + + if (!display || !context) + return XvMCBadContext; + + ret = (xvmc_driver->destroy_context)(display, context); + if (ret) { + XVMC_ERR("destroy context fail\n"); + return ret; + } + + /* Pass Control to the X server to destroy the drm_context_t */ + //XXX move generic destroy method here + //i915_release_resource(display,context); + return Success; +} + +/*************************************************************************** +// Function: XvMCCreateSurface +***************************************************************************/ +Status XvMCCreateSurface(Display *display, XvMCContext *context, XvMCSurface *surface) +{ + Status ret; +// i915XvMCContext *pI915XvMC; +// i915XvMCSurface *pI915Surface; +// I915XvMCCreateSurfaceRec *tmpComm = NULL; +// int priv_count; +// uint *priv_data; + + if (!display || !context) + return XvMCBadContext; + + if (!surface) + return XvMCBadSurface; + + ret = (xvmc_driver->create_surface)(display, context, surface); + if (ret) { + XVMC_ERR("create surface failed\n"); + return ret; + } + +#if 0 + if (!(pI915XvMC = context->privData)) + return (error_base + XvMCBadContext); + + PPTHREAD_MUTEX_LOCK(pI915XvMC); + surface->privData = (i915XvMCSurface *)malloc(sizeof(i915XvMCSurface)); + + if (!(pI915Surface = surface->privData)) { + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return BadAlloc; + } + + /* Initialize private values */ + pI915Surface->last_render = 0; + pI915Surface->last_flip = 0; + pI915Surface->yStride = pI915XvMC->yStride; + pI915Surface->uvStride = pI915XvMC->uvStride; + pI915Surface->width = context->width; + pI915Surface->height = context->height; + pI915Surface->privContext = pI915XvMC; + pI915Surface->privSubPic = NULL; + pI915Surface->srf.map = NULL; + XLockDisplay(display); + + if ((ret = _xvmc_create_surface(display, context, surface, + &priv_count, &priv_data))) { + XUnlockDisplay(display); + XVMC_ERR("Unable to create XvMCSurface."); + free(pI915Surface); + surface->privData = NULL; + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return ret; + } + + XUnlockDisplay(display); + + if (priv_count != (sizeof(I915XvMCCreateSurfaceRec) >> 2)) { + XVMC_ERR("_xvmc_create_surface() returned incorrect data size!"); + XVMC_INFO("\tExpected %d, got %d", + (int)(sizeof(I915XvMCCreateSurfaceRec) >> 2), priv_count); + _xvmc_destroy_surface(display, surface); + free(priv_data); + free(pI915Surface); + surface->privData = NULL; + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return BadAlloc; + } + + tmpComm = (I915XvMCCreateSurfaceRec *)priv_data; + + pI915Surface->srfNo = tmpComm->srfno; + pI915Surface->srf.handle = tmpComm->srf.handle; + pI915Surface->srf.offset = tmpComm->srf.offset; + pI915Surface->srf.size = tmpComm->srf.size; + free(priv_data); + + if (drmMap(pI915XvMC->fd, + pI915Surface->srf.handle, + pI915Surface->srf.size, + (drmAddress *)&pI915Surface->srf.map) != 0) { + _xvmc_destroy_surface(display, surface); + free(pI915Surface); + surface->privData = NULL; + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return BadAlloc; + } + + pI915XvMC->ref++; + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); +#endif + + return Success; +} + + +/*************************************************************************** +// Function: XvMCDestroySurface +***************************************************************************/ +Status XvMCDestroySurface(Display *display, XvMCSurface *surface) +{ +// i915XvMCSurface *pI915Surface; +// i915XvMCContext *pI915XvMC; + + if (!display || !surface) + return XvMCBadSurface; + + (xvmc_driver->destroy_surface)(display, surface); + +#if 0 + if (!(pI915Surface = surface->privData)) + return (error_base + XvMCBadSurface); + + if (!(pI915XvMC = pI915Surface->privContext)) + return (error_base + XvMCBadSurface); + + if (pI915Surface->last_flip) + XvMCSyncSurface(display,surface); + + if (pI915Surface->srf.map) + drmUnmap(pI915Surface->srf.map, pI915Surface->srf.size); + + XLockDisplay(display); + _xvmc_destroy_surface(display, surface); + XUnlockDisplay(display); + + free(pI915Surface); + surface->privData = NULL; + pI915XvMC->ref--; +#endif + + 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. +***************************************************************************/ +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) +{ + Status ret; + + if (!display || !context) { + XVMC_ERR("Invalid Display, Context or Target!"); + return XvMCBadContext; + } + if (!target_surface) + return XvMCBadSurface; + + ret = (xvmc_driver->render_surface)(display, context, picture_structure, + target_surface, past_surface, future_surface, flags, + num_macroblocks, first_macroblock, macroblock_array, + blocks); + + if (ret) { + XVMC_ERR("render surface fail\n"); + return ret; + } +#if 0 + int i; + int picture_coding_type = MPEG_I_PICTURE; + /* 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 || !context || !target_surface) { + XVMC_ERR("Invalid Display, Context or Target!"); + return BadValue; + } + + if (!num_macroblocks) + return Success; + + if (!macroblock_array || !blocks) { + XVMC_ERR("Invalid block data!"); + return BadValue; + } + + if (macroblock_array->num_blocks < (num_macroblocks + first_macroblock)) { + XVMC_ERR("Too many macroblocks requested for MB array size."); + 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) { + XVMC_ERR("HWMC only possible on YV12 Surfaces."); + return BadValue; + } + + /* P Frame Test */ + if (!past_surface) { + /* Just to avoid some ifs later. */ + privPast = privTarget; + } else { + if (!(privPast = past_surface->privData)) { + XVMC_ERR("Invalid Past Surface!"); + return (error_base + XvMCBadSurface); + } + + picture_coding_type = MPEG_P_PICTURE; + } + + /* B Frame Test */ + if (!future_surface) { + privFuture = privPast; // privTarget; + } else { + if (!past_surface) { + XVMC_ERR("No Past Surface!"); + return BadValue; + } + + if (!(privFuture = future_surface->privData)) { + XVMC_ERR("Invalid Future Surface!"); + return (error_base + XvMCBadSurface); + } + + picture_coding_type = MPEG_B_PICTURE; + } + + LOCK_HARDWARE(pI915XvMC); + 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; + XVMC_INFO("reset x"); + } + + if (mb->y > (target_surface->height >> 4)) { + mb->y = 0; + XVMC_INFO("reset y"); + } + + /* Catch no pattern case */ + if (!(mb->macroblock_type & XVMC_MB_TYPE_PATTERN) && + !(mb->macroblock_type & XVMC_MB_TYPE_INTRA) && + mb->coded_block_pattern) { + mb->coded_block_pattern = 0; + XVMC_INFO("no coded blocks present!"); + } + + bspm = mb_bytes[mb->coded_block_pattern]; + + if (!bspm) + continue; + + corrdata_size += bspm; + + if (corrdata_size > pI915XvMC->corrdata.size) { + XVMC_ERR("correction data buffer overflow."); + break; + } + memcpy(corrdata_ptr, block_ptr, bspm); + corrdata_ptr += bspm; + } + + i915_flush(pI915XvMC, 1, 0); + // i915_mc_invalidate_subcontext_buffers(context, BLOCK_SIS | BLOCK_DIS | BLOCK_SSB + // | BLOCK_MSB | BLOCK_PSP | BLOCK_PSC); + + 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, flags, + picture_coding_type); + i915_mc_map_state_buffer(context, privTarget, privPast, privFuture); + i915_mc_load_sis_msb_buffers(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_ipicture(context, mb); + } else if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) { /* Frame Picture */ + switch (mb->motion_type & 3) { + case XVMC_PREDICTION_FIELD: /* Field Based */ + i915_mc_mpeg_macroblock_2fbmv(context, mb, picture_structure); + break; + + case XVMC_PREDICTION_FRAME: /* Frame Based */ + i915_mc_mpeg_macroblock_1fbmv(context, mb); + break; + + case XVMC_PREDICTION_DUAL_PRIME: /* Dual Prime */ + i915_mc_mpeg_macroblock_2fbmv(context, mb, picture_structure); + break; + + default: /* No Motion Type */ + renderError(); + break; + } + } else { /* Frame Picture */ + switch (mb->motion_type & 3) { + case XVMC_PREDICTION_FIELD: /* Field Based */ + i915_mc_mpeg_macroblock_1fbmv(context, mb); + break; + + case XVMC_PREDICTION_16x8: /* 16x8 MC */ + i915_mc_mpeg_macroblock_2fbmv(context, mb, picture_structure); + break; + + case XVMC_PREDICTION_DUAL_PRIME: /* Dual Prime */ + i915_mc_mpeg_macroblock_1fbmv(context, mb); + break; + + default: /* No Motion Type */ + renderError(); + break; + } + } /* Field Picture */ + } + + intelFlushBatch(pI915XvMC, TRUE); + pI915XvMC->last_render = pI915XvMC->alloc.irq_emitted; + privTarget->last_render = pI915XvMC->last_render; + + UNLOCK_HARDWARE(pI915XvMC); +#endif + 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) +{ + Status ret; + + if (!display || !surface) + return XvMCBadSurface; + + ret = (xvmc_driver->put_surface)(display, surface, draw, srcx, srcy, + srcw, srch, destx, desty, destw, desth, flags); + if (ret) { + XVMC_ERR("put surface fail\n"); + return ret; + } + +#if 0 + 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); + + PPTHREAD_MUTEX_LOCK(pI915XvMC); + /* + if (getDRIDrawableInfoLocked(pI915XvMC->drawHash, display, + pI915XvMC->screen, draw, 0, pI915XvMC->fd, pI915XvMC->hHWContext, + pI915XvMC->sarea_address, FALSE, &drawInfo, sizeof(*drawInfo))) { + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + 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 = INTEL_XVMC_COMMAND_DISPLAY; + buf.ctxNo = pI915XvMC->ctxno; + buf.srfNo = pI915Surface->srfNo; + pI915SubPic = pI915Surface->privSubPic; + buf.subPicNo = (!pI915SubPic ? 0 : pI915SubPic->srfNo); + 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); + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + + return ret; + } + + XSync(display, 0); + XUnlockDisplay(display); + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); +#endif + + 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; + + if (!display || !surface) + return XvMCBadSurface; + + 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) +{ + if (!display || !surface) + return XvMCBadSurface; + 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) +{ + Status ret; + + if (!display || !surface || !stat) + return XvMCBadSurface; + + ret = (xvmc_driver->get_surface_status)(display, surface, stat); + if (ret) { + XVMC_ERR("get surface status fail\n"); + return ret; + } + +#if 0 + 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); + PPTHREAD_MUTEX_LOCK(pI915XvMC); + if (pI915Surface->last_flip) { + /* This can not happen */ + if (pI915XvMC->last_flip < pI915Surface->last_flip) { + XVMC_ERR("Context last flip is less than surface last flip."); + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + 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); + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); +#endif + + 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 +***************************************************************************/ +//XXX this seems broken now +Status XvMCHideSurface(Display *display, XvMCSurface *surface) +{ +// i915XvMCSurface *pI915Surface; +// i915XvMCContext *pI915XvMC; + int stat = 0; + Status ret; + + if (!display || !surface) + return XvMCBadSurface; + +#if 0 + if (!(pI915Surface = surface->privData)) + return (error_base + XvMCBadSurface); + + /* Get the associated context pointer */ + if (!(pI915XvMC = pI915Surface->privContext)) + return (error_base + XvMCBadSurface); +#endif + + 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) +{ + return BadValue; +} + +/*************************************************************************** +// 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) +{ + return BadValue; +} + +/*************************************************************************** +// 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) +{ + return BadValue; +} + + +/*************************************************************************** +// 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) +{ + return BadValue; +} + + +/*************************************************************************** +// 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) +{ + return BadValue; +} + +/*************************************************************************** +// 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) +{ + return BadValue; +} + +/*************************************************************************** +// 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) +{ + return BadValue; +} + +/*************************************************************************** +// 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) +{ + return BadValue; +#if 0 + Status ret; + int stat = 0; + + if (!display || !subpicture) + + do { + ret = XvMCGetSubpictureStatus(display, subpicture, &stat); + } while(!ret && (stat & XVMC_RENDERING)); + + return ret; +#endif +} + +/*************************************************************************** +// 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) +{ + return BadValue; +#if 0 + i915XvMCSubpicture *pI915Subpicture; + + if (!display || !subpicture) + return BadValue; + + if (!(pI915Subpicture = subpicture->privData)) + return (error_base + XvMCBadSubpicture); + + return Success; +#endif +} + +/*************************************************************************** +// 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) +{ + return BadValue; +#if 0 + 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); + PPTHREAD_MUTEX_LOCK(pI915XvMC); + /* FIXME: */ + if (pI915Subpicture->last_render && + (pI915Subpicture->last_render > pI915XvMC->sarea->last_dispatch)) { + *stat |= XVMC_RENDERING; + } + + // UNLOCK_HARDWARE(pI915XvMC); + PPTHREAD_MUTEX_UNLOCK(pI915XvMC); + return Success; +#endif +} + +/*************************************************************************** +// 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) +{ + /* now XvMC has no extra attribs than Xv */ + *number = 0; + return NULL; +} + +/*************************************************************************** +// 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) +{ + 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) +{ + return Success; +} diff --git a/src/xvmc/intel_xvmc.h b/src/xvmc/intel_xvmc.h new file mode 100644 index 0000000..56e44e1 --- /dev/null +++ b/src/xvmc/intel_xvmc.h @@ -0,0 +1,156 @@ +/* + * Copyright © 2007 Intel Corporation + * + * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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: + * Zhenyu Wang + * + */ +#ifndef INTEL_XVMC_H +#define INTEL_XVMC_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "i830_common.h" +#include "i830_hwmc.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xf86dri.h" +#include "driDrawable.h" + +#define DEBUG 0 + +#define XVMC_ERR(s, arg...) \ + do { \ + fprintf(stderr, "intel_xvmc err: " s "\n", ##arg); \ + } while (0) + +#define XVMC_INFO(s, arg...) \ + do { \ + fprintf(stderr, "intel_xvmc info: " s "\n", ##arg); \ + } while (0) + +#define XVMC_DBG(s, arg...) \ + do { \ + if (DEBUG) \ + fprintf(stderr, "intel_xvmc debug: " s "\n", ##arg); \ + } while (0) + +/* 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, CARD32 **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); + + +struct _intel_xvmc_driver { + int type; /* hw xvmc type - i830_hwmc.h */ + int screen; /* current screen num*/ + + int fd; /* drm file handler */ + drm_handle_t hsarea; /* DRI open connect */ + char busID[32]; + + unsigned int sarea_size; + drmAddress sarea_address; + + void *private; + + /* XXX: remove? */ + int (*init)(void); + void (*fini)(void); + + /* driver specific xvmc callbacks */ + Status (*create_context)(Display* display, XvMCContext *context, + int priv_count, CARD32 *priv_data); + + Status (*destroy_context)(Display* display, XvMCContext *context); + + Status (*create_surface)(Display* display, XvMCContext *context, + XvMCSurface *surface); + + Status (*destroy_surface)(Display* display, XvMCSurface *surface); + + Status (*render_surface)(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); + + /* XXX this should be same for all drivers */ + Status (*put_surface)(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); + + Status (*get_surface_status)(Display *display, XvMCSurface *surface, int *stat); + + /* XXX more for vld */ +}; + +extern struct _intel_xvmc_driver i915_xvmc_mc_driver; +extern struct _intel_xvmc_driver *xvmc_driver; + +#endif diff --git a/src/xvmc/xf86dri.c b/src/xvmc/xf86dri.c new file mode 100644 index 0000000..1feb232 --- /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 + * Jens Owen + * Rickard E. (Rik) Faith + * + */ + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +#define NEED_REPLIES +#include +#include +#include +#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 +#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 0000000..d7580a1 --- /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 + * \author Jens Owen + * \author Rickard E. (Rik) Faith + */ + +#ifndef _XF86DRI_H_ +#define _XF86DRI_H_ + +#include +#include + +#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 0000000..3b43438 --- /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 + * Jens Owen + * Rickard E. (Rik) Fiath + * + */ + +#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_ */