diff options
author | Zhenyu Wang <zhenyu.z.wang@intel.com> | 2008-03-20 10:31:57 +0800 |
---|---|---|
committer | Zhenyu Wang <zhenyu.z.wang@intel.com> | 2008-03-20 10:31:57 +0800 |
commit | 224c36cc14a7552bc5df793ad582f0ea5349eb1e (patch) | |
tree | 8cf03bb242d4e4f07f2889acfbb4b4029b72f22d /src | |
parent | 4b9b7b007d729f94b01b0031d8ae478134b501da (diff) | |
parent | 03ccffd5b9b8108166ea143884a1a0a6417f3236 (diff) |
Merge branch 'xvmc'
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 15 | ||||
-rw-r--r-- | src/brw_defines.h | 26 | ||||
-rw-r--r-- | src/brw_structs.h | 107 | ||||
-rw-r--r-- | src/i830.h | 16 | ||||
-rw-r--r-- | src/i830_driver.c | 28 | ||||
-rw-r--r-- | src/i830_hwmc.c | 154 | ||||
-rw-r--r-- | src/i830_hwmc.h | 106 | ||||
-rw-r--r-- | src/i830_memory.c | 22 | ||||
-rw-r--r-- | src/i830_video.c | 65 | ||||
-rw-r--r-- | src/i915_hwmc.c | 873 | ||||
-rw-r--r-- | src/i915_hwmc.h | 61 | ||||
-rw-r--r-- | src/xvmc/Makefile.am | 20 | ||||
-rw-r--r-- | src/xvmc/driDrawable.c | 174 | ||||
-rw-r--r-- | src/xvmc/driDrawable.h | 64 | ||||
-rw-r--r-- | src/xvmc/i915_program.h | 276 | ||||
-rw-r--r-- | src/xvmc/i915_structs.h | 973 | ||||
-rw-r--r-- | src/xvmc/i915_xvmc.c | 2535 | ||||
-rw-r--r-- | src/xvmc/i915_xvmc.h | 117 | ||||
-rw-r--r-- | src/xvmc/intel_batchbuffer.c | 271 | ||||
-rw-r--r-- | src/xvmc/intel_batchbuffer.h | 42 | ||||
-rw-r--r-- | src/xvmc/intel_xvmc.c | 1069 | ||||
-rw-r--r-- | src/xvmc/intel_xvmc.h | 252 | ||||
-rw-r--r-- | src/xvmc/xf86dri.c | 601 | ||||
-rw-r--r-- | src/xvmc/xf86dri.h | 111 | ||||
-rw-r--r-- | src/xvmc/xf86dristr.h | 390 |
25 files changed, 8359 insertions, 9 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 8fc21d3e..7df69b61 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -61,6 +61,13 @@ INTEL_DRI_SRCS = \ i810_hwmc.c \ i830_dri.h +INTEL_XVMC_SRCS = \ + i830_hwmc.h \ + i830_hwmc.c \ + i915_hwmc.c \ + i915_hwmc.h + + intel_drv_la_SOURCES = \ brw_defines.h \ brw_structs.h \ @@ -147,7 +154,8 @@ EXTRA_DIST = \ $(XMODE_SRCS) \ $(INTEL_G4A) \ $(INTEL_G4H) \ - $(INTEL_DRI_SRCS) + $(INTEL_DRI_SRCS) \ + $(INTEL_XVMC_SRCS) if HAVE_GEN4ASM @@ -193,6 +201,11 @@ intel_drv_la_SOURCES += \ $(INTEL_DRI_SRCS) endif +if XVMC +intel_drv_la_SOURCES += \ + $(INTEL_XVMC_SRCS) +endif + install-data-local: install-intel_drv_laLTLIBRARIES (cd $(DESTDIR)$(intel_drv_ladir) && rm -f i810_drv.so && ln -s intel_drv.so i810_drv.so) diff --git a/src/brw_defines.h b/src/brw_defines.h index 93aed544..13cb4396 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 d4fc5c67..ef7906b4 100644 --- a/src/brw_structs.h +++ b/src/brw_structs.h @@ -1342,5 +1342,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 @@ -118,6 +118,12 @@ typedef struct _I830OutputRec I830OutputRec, *I830OutputPtr; #define I830_KERNEL_TEX (1 << 1) /* Allocate texture memory pool */ #endif +#ifdef XvMCExtension +#ifdef ENABLE_XVMC +#define INTEL_XVMC 1 +#endif +#endif + typedef struct _I830Rec *I830Ptr; typedef void (*I830WriteIndexedByteFunc)(I830Ptr pI830, IOADDRESS addr, @@ -406,6 +412,12 @@ typedef struct _I830Rec { /* For Xvideo */ i830_memory *overlay_regs; #endif +#ifdef INTEL_XVMC + /* For XvMC */ + Bool XvMCEnabled; + Bool IsXvMCSurface; +#endif + XF86ModReqInfo shadowReq; /* to test for later libshadow */ Rotation rotation; void (*PointerMoved)(int, int, int); @@ -746,6 +758,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 INTEL_XVMC +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 d5b260c4..98f4261c 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -199,6 +199,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830_bios.h" #include "i830_video.h" +#ifdef INTEL_XVMC +#define _INTEL_XVMC_SERVER_ +#include "i830_hwmc.h" +#endif + #ifdef XF86DRI #include "dri.h" #include <sys/ioctl.h> @@ -298,7 +303,10 @@ typedef enum { OPTION_INTELTEXPOOL, #endif OPTION_TRIPLEBUFFER, - OPTION_FORCEENABLEPIPEA + OPTION_FORCEENABLEPIPEA, +#ifdef INTEL_XVMC + OPTION_XVMC, +#endif } I830Opts; static OptionInfoRec I830Options[] = { @@ -322,6 +330,9 @@ static OptionInfoRec I830Options[] = { #endif {OPTION_TRIPLEBUFFER, "TripleBuffer", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_FORCEENABLEPIPEA, "ForceEnablePipeA", OPTV_BOOLEAN, {0}, FALSE}, +#ifdef INTEL_XVMC + {OPTION_XVMC, "XvMC", OPTV_BOOLEAN, {0}, TRUE}, +#endif {-1, NULL, OPTV_NONE, {0}, FALSE} }; /* *INDENT-ON* */ @@ -1620,6 +1631,15 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->TripleBuffer ? "en" : "dis"); #endif +#ifdef INTEL_XVMC + pI830->XvMCEnabled = FALSE; + from = (!pI830->directRenderingDisabled && + xf86GetOptValBool(pI830->Options, OPTION_XVMC, + &pI830->XvMCEnabled)) ? X_CONFIG : X_DEFAULT; + xf86DrvMsg(pScrn->scrnIndex, from, "Intel XvMC decoder %sabled\n", + pI830->XvMCEnabled ? "en" : "dis"); +#endif + /* * If the driver can do gamma correction, it should call xf86SetGamma() here. */ @@ -3078,6 +3098,12 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) static void I830FreeScreen(int scrnIndex, int flags) { +#ifdef INTEL_XVMC + 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 00000000..7586ff71 --- /dev/null +++ b/src/i830_hwmc.c @@ -0,0 +1,154 @@ +/* + * 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 <zhenyu.z.wang@intel.com> + * + */ +#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 (!pI830->XvMCEnabled) + return 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); + DRIInfoPtr pDRIInfo = pI830->pDRIInfo; + + 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); + } else { + intel_xvmc_finish(pScrn); + pI830->XvMCEnabled = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[XvMC] Failed to initialize XvMC.\n"); + return FALSE; + } + + xf86XvMCRegisterDRInfo(pScreen, INTEL_XVMC_LIBNAME, + pDRIInfo->busIdString, + INTEL_XVMC_MAJOR, INTEL_XVMC_MINOR, INTEL_XVMC_PATCHLEVEL); + return TRUE; +} + +Bool intel_xvmc_init_batch(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC] batch buffer", + &(xvmc_driver->batch), 8 * 1024, + ALIGN_BOTH_ENDS)) + return FALSE; + + if (drmAddMap(pI830->drmSubFD, + (drm_handle_t)(xvmc_driver->batch->offset+pI830->LinearAddr), + xvmc_driver->batch->size, DRM_AGP, 0, + &xvmc_driver->batch_handle) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] drmAddMap(batchbuffer_handle) failed!\n"); + return FALSE; + } + return TRUE; +} + +void intel_xvmc_fini_batch(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (xvmc_driver->batch_handle) { + drmRmMap(pI830->drmSubFD, xvmc_driver->batch_handle); + xvmc_driver->batch_handle = 0; + } + if (xvmc_driver->batch) { + i830_free_memory(pScrn, xvmc_driver->batch); + xvmc_driver->batch = NULL; + } +} diff --git a/src/i830_hwmc.h b/src/i830_hwmc.h new file mode 100644 index 00000000..6920e016 --- /dev/null +++ b/src/i830_hwmc.h @@ -0,0 +1,106 @@ +/* + * 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 <zhenyu.z.wang@intel.com> + * + */ +#ifndef I830_HWMC_H +#define I830_HWMC_H + +#define INTEL_XVMC_LIBNAME "IntelXvMC" +#define INTEL_XVMC_MAJOR 0 +#define INTEL_XVMC_MINOR 1 +#define INTEL_XVMC_PATCHLEVEL 0 + +#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 hwmc_buffer +{ + drm_handle_t handle; + unsigned long offset; + unsigned long size; + unsigned long bus_addr; +}; + +struct _intel_xvmc_common { + unsigned int type; + unsigned int sarea_size; + struct hwmc_buffer batchbuffer; +}; + +/* Intel private XvMC command to DDX driver */ +struct intel_xvmc_command { + unsigned int command; + unsigned int ctxNo; + unsigned int srfNo; + unsigned int subPicNo; + unsigned int flags; + unsigned int real_id; + unsigned int pad[6]; +}; + +#ifdef _INTEL_XVMC_SERVER_ +#include <xf86xvmc.h> + +struct intel_xvmc_driver { + char *name; + XF86MCAdaptorPtr adaptor; + unsigned int flag; + i830_memory *batch; + drm_handle_t batch_handle; + + /* more items for xvmv surface manage? */ + Bool (*init)(ScrnInfoPtr, XF86VideoAdaptorPtr); + void (*fini)(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_put_image_size(ScrnInfoPtr); +extern Bool intel_xvmc_init_batch(ScrnInfoPtr); +extern void intel_xvmc_fini_batch(ScrnInfoPtr); +#endif + +#endif diff --git a/src/i830_memory.c b/src/i830_memory.c index 2cac26b7..9e23c3ca 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -2015,3 +2015,25 @@ 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; + } + + if (!i830_bind_memory(pScrn, *buffer)) + return FALSE; + + return TRUE; +} diff --git a/src/i830_video.c b/src/i830_video.c index c25e9921..0d0a9a03 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -75,6 +75,12 @@ #include "dixstruct.h" #include "fourcc.h" +#ifdef INTEL_XVMC +#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 @@ -254,13 +260,39 @@ 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, +#ifdef INTEL_XVMC + { + /* + * 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 + }, +#endif }; typedef struct { @@ -592,10 +624,21 @@ I830InitVideo(ScreenPtr pScreen) } I830InitOffscreenImages(pScreen); } +#ifdef INTEL_XVMC + Bool ret = FALSE; + if (intel_xvmc_probe(pScrn)) { + if (texturedAdaptor) + ret = intel_xvmc_driver_init(pScreen, texturedAdaptor); + } +#endif if (num_adaptors) xf86XVScreenInit(pScreen, adaptors, num_adaptors); +#ifdef INTEL_XVMC + if (ret) + intel_xvmc_screen_init(pScreen); +#endif xfree(adaptors); } @@ -2277,8 +2320,14 @@ I830PutImage(ScrnInfoPtr pScrn, switch (id) { case FOURCC_YV12: case FOURCC_I420: - srcPitch = (width + 3) & ~3; - srcPitch2 = ((width >> 1) + 3) & ~3; + srcPitch = (width + 0x3) & ~0x3; + srcPitch2 = ((width >> 1) + 0x3) & ~0x3; +#ifdef INTEL_XVMC + if (pI830->IsXvMCSurface) { + srcPitch = (width + 0x3ff) & ~0x3ff; + srcPitch2 = ((width >> 1) + 0x3ff) & ~0x3ff; + } +#endif if (pPriv->textured && IS_I965G(pI830)) destId = FOURCC_YUY2; break; @@ -2533,6 +2582,14 @@ I830QueryImageAttributes(ScrnInfoPtr pScrn, ErrorF("size is %d\n", size); #endif break; +#ifdef INTEL_XVMC + case FOURCC_XVMC: + *h = (*h + 1) & ~1; + size = sizeof(struct intel_xvmc_command); + if (pitches) + pitches[0] = size; + break; +#endif case FOURCC_UYVY: case FOURCC_YUY2: default: diff --git a/src/i915_hwmc.c b/src/i915_hwmc.c new file mode 100644 index 00000000..cdcef5a8 --- /dev/null +++ b/src/i915_hwmc.c @@ -0,0 +1,873 @@ +/* + * 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 <haihao.xiang@intel.com> + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "compiler.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "xf86fbman.h" +#include "regionstr.h" + +#include "i830.h" +#include "i830_dri.h" +#include "i830_video.h" +#include "xf86xv.h" +#include "xf86xvmc.h" +#include <X11/extensions/Xv.h> +#include <X11/extensions/XvMC.h> +#include "xaa.h" +#include "xaalocal.h" +#include "dixstruct.h" +#include "fourcc.h" + +#if defined(X_NEED_XVPRIV_H) || defined (_XF86_FOURCC_H_) +#include "xf86xvpriv.h" +#endif + +#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; +} 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 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 +}; + + +/* + * 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; + } + + + 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; + } + +} + +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 (0) + 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; + } + +} + +/* + * i915_xvmc_create_context + * + * 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 i915_xvmc_create_context (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] i915: XvMC disabled!\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] i915: 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] i915: 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; + } + + /* common context items */ + contextRec->comm.type = xvmc_driver->flag; + contextRec->comm.sarea_size = pDRIInfo->SAREASize; + contextRec->comm.batchbuffer.offset = xvmc_driver->batch->offset; + contextRec->comm.batchbuffer.size = xvmc_driver->batch->size; + contextRec->comm.batchbuffer.handle = xvmc_driver->batch_handle; + + /* i915 private context */ + 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->sarea_priv_offset = sizeof(XF86DRISAREARec); + contextRec->deviceID = pI830DRI->deviceID; + + pXvMC->ncontexts++; + pXvMC->contexts[i] = pContext->context_id; + pXvMC->ctxprivs[i] = ctxpriv; + + return Success; +} + +static int i915_xvmc_create_surface (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] i915: XvMC disabled!\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] i915: Too many surfaces !\n"); + return BadAlloc; + } + + *priv = xcalloc(1, sizeof(I915XvMCCreateSurfaceRec)); + surfaceRec = (I915XvMCCreateSurfaceRec *)*priv; + + if (!*priv) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[XvMC] i915:Unable to allocate surface priv ret memory!\n"); + return BadAlloc; + } + + *num_priv = sizeof(I915XvMCCreateSurfaceRec) >> 2; + sfpriv = (I915XvMCSurfacePriv *)xcalloc(1, sizeof(I915XvMCSurfacePriv)); + + if (!sfpriv) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[XvMC] i915: Unable to allocate surface priv memory!\n"); + xfree(*priv); + *priv = NULL; + *num_priv = 0; + return BadAlloc; + } + + ctx = pSurf->context; + bufsize = SIZE_YUV420(ctx->width, ctx->height); + + if (!i830_allocate_xvmc_buffer(pScrn, "XvMC surface", + &(sfpriv->surface), bufsize, + ALIGN_BOTH_ENDS)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[XvMC] i915 : Failed to allocate XvMC surface space!\n"); + xfree(sfpriv); + xfree(*priv); + *priv = NULL; + *num_priv = 0; + return BadAlloc; + } + + if (0) + 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 i915_xvmc_create_subpict(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] i915: Too many surfaces !\n"); + return BadAlloc; + } + + *priv = xcalloc(1, sizeof(I915XvMCCreateSurfaceRec)); + surfaceRec = (I915XvMCCreateSurfaceRec *)*priv; + + if (!*priv) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[XvMC] i915: 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] i915: 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 i915_xvmc_destroy_context (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 i915_xvmc_destroy_surface (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 i915_xvmc_destroy_subpict (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 i915_xvmc_put_image(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; + struct intel_xvmc_command *xvmc_cmd = (struct intel_xvmc_command *)buf; + int ret; + + if (pI830->XvMCEnabled) { + if (FOURCC_XVMC == id) { + switch (xvmc_cmd->command) { + case INTEL_XVMC_COMMAND_DISPLAY: + if ((xvmc_cmd->srfNo >= I915_XVMC_MAX_SURFACES) || + !pXvMC->surfaces[xvmc_cmd->srfNo] || + !pXvMC->sfprivs[xvmc_cmd->srfNo]) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[XvMC] i915 put image: Invalid parameters!\n"); + return 1; + } + + buf = pI830->FbBase + + pXvMC->sfprivs[xvmc_cmd->srfNo]->surface->offset; + id = xvmc_cmd->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 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; + if (!intel_xvmc_init_batch(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "[XvMC] fail to init batch buffer\n"); + xfree(pXvMC); + return FALSE; + } + initI915XvMC(pXvMC); + + /* set up wrappers */ + pXvMC->savePutImage = XvAdapt->PutImage; + XvAdapt->PutImage = i915_xvmc_put_image; + return TRUE; +} + +static void i915_xvmc_fini(ScrnInfoPtr pScrn) +{ + I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; + + cleanupI915XvMC(pXvMC); + intel_xvmc_fini_batch(pScrn); + xfree(xvmc_driver->devPrivate); +} + +/* 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 = +{ + .name = "Intel(R) Textured Video", + .num_surfaces = ARRARY_SIZE(ppSI), + .surfaces = ppSI, +#if 0 + .num_subpictures = ARRARY_SIZE(i915_subpicture_list), + .subpictures = i915_subpicture_list, +#endif + .num_subpictures = 0, + .subpictures = NULL, + .CreateContext = (xf86XvMCCreateContextProcPtr) i915_xvmc_create_context, + .DestroyContext = (xf86XvMCDestroyContextProcPtr) i915_xvmc_destroy_context, + .CreateSurface = (xf86XvMCCreateSurfaceProcPtr) i915_xvmc_create_surface, + .DestroySurface = (xf86XvMCDestroySurfaceProcPtr) i915_xvmc_destroy_surface, + .CreateSubpicture = (xf86XvMCCreateSubpictureProcPtr) i915_xvmc_create_subpict, + .DestroySubpicture = (xf86XvMCDestroySubpictureProcPtr) i915_xvmc_destroy_subpict, +}; + +/* 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, +}; diff --git a/src/i915_hwmc.h b/src/i915_hwmc.h new file mode 100644 index 00000000..0141fb25 --- /dev/null +++ b/src/i915_hwmc.h @@ -0,0 +1,61 @@ +/* + * 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 <haihao.xiang@intel.com> + * + */ +#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 +{ + 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 */ + unsigned int sarea_priv_offset; + int deviceID; +} I915XvMCCreateContextRec; + +typedef struct +{ + unsigned int srfno; + struct hwmc_buffer srf; +} I915XvMCCreateSurfaceRec; + +#endif /* _I915_HWMC_H */ diff --git a/src/xvmc/Makefile.am b/src/xvmc/Makefile.am index b5c9db9a..cde41f98 100644 --- a/src/xvmc/Makefile.am +++ b/src/xvmc/Makefile.am @@ -1,5 +1,6 @@ -if DRI -lib_LTLIBRARIES=libI810XvMC.la +if XVMC +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 \ + i915_xvmc.c \ + i915_xvmc.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 00000000..83863347 --- /dev/null +++ b/src/xvmc/driDrawable.c @@ -0,0 +1,174 @@ +/***************************************************************************** + * driDrawable.c: Lean Version of DRI utilities. + * + * Copyright (c) 2005 Thomas Hellstrom. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + + +#include <X11/Xlibint.h> +#include <X11/Xutil.h> +#include "xf86drm.h" +#include "drm.h" +#include "xf86dri.h" +#include "drm_sarea.h" +#include "driDrawable.h" + +static unsigned +drawStamp(volatile drm_sarea_t * pSarea, int index) +{ + return pSarea->drawableTable[index].stamp; +} + +int +getDRIDrawableInfoLocked(void *drawHash, Display * display, int screen, + Drawable draw, unsigned lockFlags, int drmFD, drm_context_t drmContext, + drmAddress sarea, Bool updateInfo, drawableInfo ** info, + unsigned long infoSize) +{ + drawableInfo *drawInfo; + void *res; + drm_drawable_t drmDraw = 0; + volatile drm_sarea_t *pSarea = (drm_sarea_t *) sarea; + drm_clip_rect_t *clipFront, *clipBack; + + int ret; + + if (drmHashLookup(drawHash, (unsigned long)draw, &res)) { + + /* + * The drawable is unknown to us. Create it and put it in the + * hash table. + */ + + DRM_UNLOCK(drmFD, &pSarea->lock, drmContext); + if (!uniDRICreateDrawable(display, screen, draw, &drmDraw)) { + DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags); + return 1; + } + DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags); + + drawInfo = (drawableInfo *) malloc(infoSize); + if (!drawInfo) + return 1; + + drawInfo->drmDraw = drmDraw; + drawInfo->stamp = 0; + drawInfo->clipFront = 0; + drawInfo->clipBack = 0; + + drmHashInsert(drawHash, (unsigned long)draw, drawInfo); + + } else { + drawInfo = res; + } + + drawInfo->touched = FALSE; + while (!drawInfo->clipFront + || drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) { + + /* + * The drawable has been touched since we last got info about it. + * obtain new info from the X server. + */ + + drawInfo->touched = TRUE; + + if (updateInfo || !drawInfo->clipFront) { + DRM_UNLOCK(drmFD, &pSarea->lock, drmContext); + + ret = uniDRIGetDrawableInfo(display, screen, draw, + &drawInfo->index, &drawInfo->stamp, &drawInfo->x, + &drawInfo->y, &drawInfo->w, &drawInfo->h, + &drawInfo->numClipFront, &clipFront, + &drawInfo->backX, &drawInfo->backY, + &drawInfo->numClipBack, &clipBack); + + DRM_LIGHT_LOCK(drmFD, &pSarea->lock, drmContext); + + /* + * Error. Probably the drawable is destroyed. Return error and old values. + */ + + if (!ret) { + free(drawInfo); + drawInfo = NULL; + drmHashDelete(drawHash, (unsigned long)draw); + + DRM_UNLOCK(drmFD, &pSarea->lock, drmContext); + uniDRIDestroyDrawable(display, screen, draw); + DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags); + + return 1; + } + + if (drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) { + + /* + * The info is already outdated. Sigh. Have another go. + */ + + XFree(clipFront); + XFree(clipBack); + continue; + } + + if (drawInfo->clipFront) + XFree(drawInfo->clipFront); + drawInfo->clipFront = clipFront; + if (drawInfo->clipBack) + XFree(drawInfo->clipBack); + drawInfo->clipBack = clipBack; + } else { + if (!drawInfo->clipFront) + drawInfo->clipFront = (drm_clip_rect_t *) ~ 0UL; + drawInfo->stamp = drawStamp(pSarea, drawInfo->index); + } + } + *info = drawInfo; + return 0; +} + +void +driDestroyHashContents(void *drawHash) +{ + unsigned long key; + void *content; + drawableInfo *drawInfo; + + if (drmHashFirst(drawHash, &key, &content) < 1) + return; + drawInfo = (drawableInfo *) content; + if (drawInfo->clipBack) + XFree(drawInfo->clipBack); + if (drawInfo->clipFront) + XFree(drawInfo->clipFront); + free(drawInfo); + while (drmHashNext(drawHash, &key, &content) == 1) { + drawInfo = (drawableInfo *) content; + if (drawInfo->clipBack) + XFree(drawInfo->clipBack); + if (drawInfo->clipFront) + XFree(drawInfo->clipFront); + free(drawInfo); + } + + return; +} diff --git a/src/xvmc/driDrawable.h b/src/xvmc/driDrawable.h new file mode 100644 index 00000000..a758c7c7 --- /dev/null +++ b/src/xvmc/driDrawable.h @@ -0,0 +1,64 @@ +/***************************************************************************** + * driDrawable.h: Lean Version of DRI utilities. + * + * Copyright (c) 2005 Thomas Hellstrom. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DRIDRAWABLE_H +#define _DRIDRAWABLE_H + +typedef struct _drawableInfo +{ + drm_drawable_t drmDraw; + unsigned stamp; + unsigned index; + drm_clip_rect_t *clipFront; + drm_clip_rect_t *clipBack; + int x; + int y; + int w; + int h; + int backX; + int backY; + int numClipFront; + int numClipBack; + Bool touched; +} drawableInfo; + +/* + * Get updated info about the drawable "draw". The drawableInfo record returned is malloced + * and administrated internally. Never free it unless you know exactly what you are doing. + * The drm hash table "drawHash" needs to be initialized externally. + */ + +extern int +getDRIDrawableInfoLocked(void *drawHash, Display * display, int screen, + Drawable draw, unsigned lockFlags, int drmFD, drm_context_t drmContext, + drmAddress sarea, Bool updateInfo, drawableInfo ** info, + unsigned long infoSize); + +/* + * Free all resources created by the above function. Typically done on exit. + */ + +extern void driDestroyHashContents(void *drawHash); + +#endif diff --git a/src/xvmc/i915_program.h b/src/xvmc/i915_program.h new file mode 100644 index 00000000..82c920e0 --- /dev/null +++ b/src/xvmc/i915_program.h @@ -0,0 +1,276 @@ +#ifndef _I915_PROGRAM_H +#define _I915_PROGRAM_H + +#define REG_TYPE_R 0 /* temporary regs, no need to + * dcl, must be written before + * read -- Preserved between + * phases. + */ +#define REG_TYPE_T 1 /* Interpolated values, must be + * dcl'ed before use. + * + * 0..7: texture coord, + * 8: diffuse spec, + * 9: specular color, + * 10: fog parameter in w. + */ +#define REG_TYPE_CONST 2 /* Restriction: only one const + * can be referenced per + * instruction, though it may be + * selected for multiple inputs. + * Constants not initialized + * default to zero. + */ +#define REG_TYPE_S 3 /* sampler */ +#define REG_TYPE_OC 4 /* output color (rgba) */ +#define REG_TYPE_OD 5 /* output depth (w), xyz are + * temporaries. If not written, + * interpolated depth is used? + */ +#define REG_TYPE_U 6 /* unpreserved temporaries */ +#define REG_TYPE_MASK 0x7 +#define REG_NR_MASK 0xf + +/* REG_TYPE_T: + */ +#define T_TEX0 0 +#define T_TEX1 1 +#define T_TEX2 2 +#define T_TEX3 3 +#define T_TEX4 4 +#define T_TEX5 5 +#define T_TEX6 6 +#define T_TEX7 7 +#define T_DIFFUSE 8 +#define T_SPECULAR 9 +#define T_FOG_W 10 /* interpolated fog is in W coord */ + +/* Arithmetic instructions */ + +/* .replicate_swizzle == selection and replication of a particular + * scalar channel, ie., .xxxx, .yyyy, .zzzz or .wwww + */ +#define A0_NOP (0x0<<24) /* no operation */ +#define A0_ADD (0x1<<24) /* dst = src0 + src1 */ +#define A0_MOV (0x2<<24) /* dst = src0 */ +#define A0_MUL (0x3<<24) /* dst = src0 * src1 */ +#define A0_MAD (0x4<<24) /* dst = src0 * src1 + src2 */ +#define A0_DP2ADD (0x5<<24) /* dst.xyzw = src0.xy dot src1.xy + src2.replicate_swizzle */ +#define A0_DP3 (0x6<<24) /* dst.xyzw = src0.xyz dot src1.xyz */ +#define A0_DP4 (0x7<<24) /* dst.xyzw = src0.xyzw dot src1.xyzw */ +#define A0_FRC (0x8<<24) /* dst = src0 - floor(src0) */ +#define A0_RCP (0x9<<24) /* dst.xyzw = 1/(src0.replicate_swizzle) */ +#define A0_RSQ (0xa<<24) /* dst.xyzw = 1/(sqrt(abs(src0.replicate_swizzle))) */ +#define A0_EXP (0xb<<24) /* dst.xyzw = exp2(src0.replicate_swizzle) */ +#define A0_LOG (0xc<<24) /* dst.xyzw = log2(abs(src0.replicate_swizzle)) */ +#define A0_CMP (0xd<<24) /* dst = (src0 >= 0.0) ? src1 : src2 */ +#define A0_MIN (0xe<<24) /* dst = (src0 < src1) ? src0 : src1 */ +#define A0_MAX (0xf<<24) /* dst = (src0 >= src1) ? src0 : src1 */ +#define A0_FLR (0x10<<24) /* dst = floor(src0) */ +#define A0_MOD (0x11<<24) /* dst = src0 fmod 1.0 */ +#define A0_TRC (0x12<<24) /* dst = int(src0) */ +#define A0_SGE (0x13<<24) /* dst = src0 >= src1 ? 1.0 : 0.0 */ +#define A0_SLT (0x14<<24) /* dst = src0 < src1 ? 1.0 : 0.0 */ +#define A0_DEST_SATURATE (1<<22) +#define A0_DEST_TYPE_SHIFT 19 +/* Allow: R, OC, OD, U */ +#define A0_DEST_NR_SHIFT 14 +/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */ +#define A0_DEST_CHANNEL_X (1<<10) +#define A0_DEST_CHANNEL_Y (2<<10) +#define A0_DEST_CHANNEL_Z (4<<10) +#define A0_DEST_CHANNEL_W (8<<10) +#define A0_DEST_CHANNEL_ALL (0xf<<10) +#define A0_DEST_CHANNEL_SHIFT 10 +#define A0_SRC0_TYPE_SHIFT 7 +#define A0_SRC0_NR_SHIFT 2 + +#define A0_DEST_CHANNEL_XY (A0_DEST_CHANNEL_X|A0_DEST_CHANNEL_Y) +#define A0_DEST_CHANNEL_XYZ (A0_DEST_CHANNEL_XY|A0_DEST_CHANNEL_Z) + +#define SRC_X 0 +#define SRC_Y 1 +#define SRC_Z 2 +#define SRC_W 3 +#define SRC_ZERO 4 +#define SRC_ONE 5 + +#define A1_SRC0_CHANNEL_X_NEGATE (1<<31) +#define A1_SRC0_CHANNEL_X_SHIFT 28 +#define A1_SRC0_CHANNEL_Y_NEGATE (1<<27) +#define A1_SRC0_CHANNEL_Y_SHIFT 24 +#define A1_SRC0_CHANNEL_Z_NEGATE (1<<23) +#define A1_SRC0_CHANNEL_Z_SHIFT 20 +#define A1_SRC0_CHANNEL_W_NEGATE (1<<19) +#define A1_SRC0_CHANNEL_W_SHIFT 16 +#define A1_SRC1_TYPE_SHIFT 13 +#define A1_SRC1_NR_SHIFT 8 +#define A1_SRC1_CHANNEL_X_NEGATE (1<<7) +#define A1_SRC1_CHANNEL_X_SHIFT 4 +#define A1_SRC1_CHANNEL_Y_NEGATE (1<<3) +#define A1_SRC1_CHANNEL_Y_SHIFT 0 + +#define A2_SRC1_CHANNEL_Z_NEGATE (1<<31) +#define A2_SRC1_CHANNEL_Z_SHIFT 28 +#define A2_SRC1_CHANNEL_W_NEGATE (1<<27) +#define A2_SRC1_CHANNEL_W_SHIFT 24 +#define A2_SRC2_TYPE_SHIFT 21 +#define A2_SRC2_NR_SHIFT 16 +#define A2_SRC2_CHANNEL_X_NEGATE (1<<15) +#define A2_SRC2_CHANNEL_X_SHIFT 12 +#define A2_SRC2_CHANNEL_Y_NEGATE (1<<11) +#define A2_SRC2_CHANNEL_Y_SHIFT 8 +#define A2_SRC2_CHANNEL_Z_NEGATE (1<<7) +#define A2_SRC2_CHANNEL_Z_SHIFT 4 +#define A2_SRC2_CHANNEL_W_NEGATE (1<<3) +#define A2_SRC2_CHANNEL_W_SHIFT 0 + +/* Declaration instructions */ +#define D0_DCL (0x19<<24) /* Declare a t (interpolated attrib) + * register or an s (sampler) + * register. */ +#define D0_SAMPLE_TYPE_SHIFT 22 +#define D0_SAMPLE_TYPE_2D (0x0<<22) +#define D0_SAMPLE_TYPE_CUBE (0x1<<22) +#define D0_SAMPLE_TYPE_VOLUME (0x2<<22) +#define D0_SAMPLE_TYPE_MASK (0x3<<22) + +#define D0_TYPE_SHIFT 19 +/* Allow: T, S */ +#define D0_NR_SHIFT 14 +/* Allow T: 0..10, S: 0..15 */ +#define D0_CHANNEL_X (1<<10) +#define D0_CHANNEL_Y (2<<10) +#define D0_CHANNEL_Z (4<<10) +#define D0_CHANNEL_W (8<<10) +#define D0_CHANNEL_ALL (0xf<<10) +#define D0_CHANNEL_NONE (0<<10) + +#define D0_CHANNEL_XY (D0_CHANNEL_X|D0_CHANNEL_Y) +#define D0_CHANNEL_XYZ (D0_CHANNEL_XY|D0_CHANNEL_Z) + +/* I915 Errata: Do not allow (xz), (xw), (xzw) combinations for diffuse + * or specular declarations. + * + * For T dcls, only allow: (x), (xy), (xyz), (w), (xyzw) + * + * Must be zero for S (sampler) dcls + */ +#define D1_MBZ 0 +#define D2_MBZ 0 + +/* Texture instructions */ +#define T0_TEXLD (0x15<<24) /* Sample texture using predeclared + * sampler and address, and output + * filtered texel data to destination + * register */ +#define T0_TEXLDP (0x16<<24) /* Same as texld but performs a + * perspective divide of the texture + * coordinate .xyz values by .w before + * sampling. */ +#define T0_TEXLDB (0x17<<24) /* Same as texld but biases the + * computed LOD by w. Only S4.6 two's + * comp is used. This implies that a + * float to fixed conversion is + * done. */ +#define T0_TEXKILL (0x18<<24) /* Does not perform a sampling + * operation. Simply kills the pixel + * if any channel of the address + * register is < 0.0. */ +#define T0_DEST_TYPE_SHIFT 19 +/* Allow: R, OC, OD, U */ +/* Note: U (unpreserved) regs do not retain their values between + * phases (cannot be used for feedback) + * + * Note: oC and OD registers can only be used as the destination of a + * texture instruction once per phase (this is an implementation + * restriction). + */ +#define T0_DEST_NR_SHIFT 14 +/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */ +#define T0_SAMPLER_NR_SHIFT 0 /* This field ignored for TEXKILL */ +#define T0_SAMPLER_NR_MASK (0xf<<0) + +#define T1_ADDRESS_REG_TYPE_SHIFT 24 /* Reg to use as texture coord */ +/* Allow R, T, OC, OD -- R, OC, OD are 'dependent' reads, new program phase */ +#define T1_ADDRESS_REG_NR_SHIFT 17 +#define T2_MBZ 0 + + +/* Having zero and one in here makes the definition of swizzle a lot + * easier. + */ +#define UREG_TYPE_SHIFT 29 +#define UREG_NR_SHIFT 24 +#define UREG_CHANNEL_X_NEGATE_SHIFT 23 +#define UREG_CHANNEL_X_SHIFT 20 +#define UREG_CHANNEL_Y_NEGATE_SHIFT 19 +#define UREG_CHANNEL_Y_SHIFT 16 +#define UREG_CHANNEL_Z_NEGATE_SHIFT 15 +#define UREG_CHANNEL_Z_SHIFT 12 +#define UREG_CHANNEL_W_NEGATE_SHIFT 11 +#define UREG_CHANNEL_W_SHIFT 8 +#define UREG_CHANNEL_ZERO_NEGATE_MBZ 5 +#define UREG_CHANNEL_ZERO_SHIFT 4 +#define UREG_CHANNEL_ONE_NEGATE_MBZ 1 +#define UREG_CHANNEL_ONE_SHIFT 0 + +#define UREG_BAD 0xffffffff /* not a valid ureg */ + +#define X SRC_X +#define Y SRC_Y +#define Z SRC_Z +#define W SRC_W +#define ZERO SRC_ZERO +#define ONE SRC_ONE + +/* Construct a ureg: + */ +#define UREG(type, nr) (((type) << UREG_TYPE_SHIFT) | \ + ((nr) << UREG_NR_SHIFT) | \ + (X << UREG_CHANNEL_X_SHIFT) | \ + (Y << UREG_CHANNEL_Y_SHIFT) | \ + (Z << UREG_CHANNEL_Z_SHIFT) | \ + (W << UREG_CHANNEL_W_SHIFT) | \ + (ZERO << UREG_CHANNEL_ZERO_SHIFT) | \ + (ONE << UREG_CHANNEL_ONE_SHIFT)) + +#define GET_CHANNEL_SRC( reg, channel ) ((reg<<(channel*4)) & (0xf<<20)) +#define CHANNEL_SRC( src, channel ) (src>>(channel*4)) + +#define GET_UREG_TYPE(reg) (((reg) >> UREG_TYPE_SHIFT) & REG_TYPE_MASK) +#define GET_UREG_NR(reg) (((reg) >> UREG_NR_SHIFT) & REG_NR_MASK) + +#define UREG_XYZW_CHANNEL_MASK 0x00ffff00 + +#define A0_DEST(reg) (((reg) & UREG_TYPE_NR_MASK) >> UREG_A0_DEST_SHIFT_LEFT) +#define D0_DEST(reg) (((reg) & UREG_TYPE_NR_MASK) >> UREG_A0_DEST_SHIFT_LEFT) +#define T0_DEST(reg) (((reg) & UREG_TYPE_NR_MASK) >> UREG_A0_DEST_SHIFT_LEFT) +#define A0_SRC0(reg) (((reg) & UREG_MASK) >> UREG_A0_SRC0_SHIFT_LEFT) +#define A1_SRC0(reg) (((reg) & UREG_MASK) << UREG_A1_SRC0_SHIFT_RIGHT) +#define A1_SRC1(reg) (((reg) & UREG_MASK) >> UREG_A1_SRC1_SHIFT_LEFT) +#define A2_SRC1(reg) (((reg) & UREG_MASK) << UREG_A2_SRC1_SHIFT_RIGHT) +#define A2_SRC2(reg) (((reg) & UREG_MASK) >> UREG_A2_SRC2_SHIFT_LEFT) + +/* These are special, and don't have swizzle/negate bits. + */ +#define T0_SAMPLER( reg ) (GET_UREG_NR(reg) << T0_SAMPLER_NR_SHIFT) +#define T1_ADDRESS_REG( reg ) ((GET_UREG_NR(reg) << T1_ADDRESS_REG_NR_SHIFT) | \ + (GET_UREG_TYPE(reg) << T1_ADDRESS_REG_TYPE_SHIFT)) + + +/* Macros for translating UREG's into the various register fields used + * by the I915 programmable unit. + */ +#define UREG_A0_DEST_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_DEST_TYPE_SHIFT) +#define UREG_A0_SRC0_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_SRC0_TYPE_SHIFT) +#define UREG_A1_SRC0_SHIFT_RIGHT (A1_SRC0_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT) +#define UREG_A1_SRC1_SHIFT_LEFT (UREG_TYPE_SHIFT - A1_SRC1_TYPE_SHIFT) +#define UREG_A2_SRC1_SHIFT_RIGHT (A2_SRC1_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT) +#define UREG_A2_SRC2_SHIFT_LEFT (UREG_TYPE_SHIFT - A2_SRC2_TYPE_SHIFT) + +#define UREG_MASK 0xffffff00 +#define UREG_TYPE_NR_MASK ((REG_TYPE_MASK << UREG_TYPE_SHIFT) | \ + (REG_NR_MASK << UREG_NR_SHIFT)) + +#endif diff --git a/src/xvmc/i915_structs.h b/src/xvmc/i915_structs.h new file mode 100644 index 00000000..a25d7349 --- /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 <haihao.xiang@intel.com> + * + */ + +#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/i915_xvmc.c b/src/xvmc/i915_xvmc.c new file mode 100644 index 00000000..b30facdf --- /dev/null +++ b/src/xvmc/i915_xvmc.c @@ -0,0 +1,2535 @@ +/* + * 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 <haihao.xiang@intel.com> + * + */ + +#include <pthread.h> +#include <sys/ioctl.h> + +#include "i915_xvmc.h" +#include "i915_structs.h" +#include "i915_program.h" + +#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 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 void i915_flush(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(&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(base, size, 0); + free(base); +} + +static void i915_mc_mpeg_set_origin(XvMCContext *context, XvMCMacroBlock *mb) +{ + struct i915_3dmpeg_set_origin set_origin; + + /* 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(&set_origin, sizeof(set_origin), 0); +} + +static void i915_mc_mpeg_macroblock_ipicture(XvMCContext *context, XvMCMacroBlock *mb) +{ + struct i915_3dmpeg_macroblock_ipicture macroblock_ipicture; + + /* 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(¯oblock_ipicture, sizeof(macroblock_ipicture), 0); +} + + +static void i915_mc_mpeg_macroblock_0mv(XvMCContext *context, XvMCMacroBlock *mb) +{ + struct i915_3dmpeg_macroblock_0mv macroblock_0mv; + + /* 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(¯oblock_0mv, sizeof(macroblock_0mv), 0); +} + +static void i915_mc_mpeg_macroblock_1fbmv(XvMCContext *context, XvMCMacroBlock *mb) +{ + struct i915_3dmpeg_macroblock_1fbmv macroblock_1fbmv; + + /* 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(¯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(¯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(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(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(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; + } + + 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; + } +} + +/* + * 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(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(&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(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(base, size, 0); + free(base); +} + +/* + * Function: i915_release_resource + */ +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); + + 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; + int screen = DefaultScreen(display); + + XVMC_DBG("%s\n", __FUNCTION__); + + 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); + XFree(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->sarea_priv_offset = tmpComm->sarea_priv_offset; + + /* Must free the private data we were passed from X */ + XFree(priv_data); + priv_data = NULL; + + pSAREA = (drm_sarea_t *)xvmc_driver->sarea_address; + pI915XvMC->sarea = (drmI830Sarea*)((char*)pSAREA + pI915XvMC->sarea_priv_offset); + + 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->port = context->port; + pI915XvMC->ref = 1; + return Success; +} + +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; +} + +static Status i915_xvmc_mc_create_surface(Display *display, + XvMCContext *context, XvMCSurface *surface, int priv_count, + CARD32 *priv_data) +{ + Status ret; + i915XvMCContext *pI915XvMC; + i915XvMCSurface *pI915Surface; + I915XvMCCreateSurfaceRec *tmpComm = NULL; + + if (!(pI915XvMC = context->privData)) + return XvMCBadContext; + + XVMC_DBG("%s\n", __FUNCTION__); + + 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); + XFree(priv_data); + return BadAlloc; + } + + PPTHREAD_MUTEX_LOCK(); + surface->privData = (i915XvMCSurface *)malloc(sizeof(i915XvMCSurface)); + + if (!(pI915Surface = surface->privData)) { + PPTHREAD_MUTEX_UNLOCK(); + 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; + + 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; + + XFree(priv_data); + + if (drmMap(xvmc_driver->fd, + pI915Surface->srf.handle, + pI915Surface->srf.size, + (drmAddress *)&pI915Surface->srf.map) != 0) { + XVMC_ERR("mapping surface memory failed!\n"); + _xvmc_destroy_surface(display, surface); + free(pI915Surface); + surface->privData = NULL; + PPTHREAD_MUTEX_UNLOCK(); + return BadAlloc; + } + + pI915XvMC->ref++; + PPTHREAD_MUTEX_UNLOCK(); + return 0; +} + + +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 XvMCBadSurface; + + if (!(pI915XvMC = pI915Surface->privContext)) + return XvMCBadSurface; + + if (pI915Surface->last_flip) + XvMCSyncSurface(display,surface); + + if (pI915Surface->srf.map) + drmUnmap(pI915Surface->srf.map, pI915Surface->srf.size); + + free(pI915Surface); + surface->privData = NULL; + pI915XvMC->ref--; + + return Success; +} + + +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; + + intel_xvmc_context_ptr intel_ctx; + + i915XvMCSurface *privTarget = NULL; + i915XvMCSurface *privFuture = NULL; + i915XvMCSurface *privPast = NULL; + i915XvMCContext *pI915XvMC = NULL; + + XVMC_DBG("%s\n", __FUNCTION__); + + /* 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 XvMCBadContext; + + if (!(privTarget = target_surface->privData)) + return XvMCBadSurface; + + /* Test For YV12 Surface */ + if (context->surface_type_id != FOURCC_YV12) { + XVMC_ERR("HWMC only possible on YV12 Surfaces."); + return BadValue; + } + + intel_ctx = intel_xvmc_find_context(context->context_id); + if (!intel_ctx) { + XVMC_ERR("Can't find intel xvmc context\n"); + 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 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 XvMCBadSurface; + } + + picture_coding_type = MPEG_B_PICTURE; + } + + LOCK_HARDWARE(intel_ctx->hw_context); + 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(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 */ + XVMC_ERR("Invalid Macroblock Parameters found."); + 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 */ + XVMC_ERR("Invalid Macroblock Parameters found."); + break; + } + } /* Field Picture */ + } + + intelFlushBatch(TRUE); + xvmc_driver->last_render = xvmc_driver->alloc.irq_emitted; + privTarget->last_render = xvmc_driver->last_render; + + UNLOCK_HARDWARE(intel_ctx->hw_context); + return 0; +} + +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, struct intel_xvmc_command *data) +{ + i915XvMCContext *pI915XvMC; + i915XvMCSurface *pI915Surface; + i915XvMCSubpicture *pI915SubPic; + + if (!(pI915Surface = surface->privData)) + return XvMCBadSurface; + + if (!(pI915XvMC = pI915Surface->privContext)) + return XvMCBadSurface; + + PPTHREAD_MUTEX_LOCK(); + + data->command = INTEL_XVMC_COMMAND_DISPLAY; + data->ctxNo = pI915XvMC->ctxno; + data->srfNo = pI915Surface->srfNo; + pI915SubPic = pI915Surface->privSubPic; + data->subPicNo = (!pI915SubPic ? 0 : pI915SubPic->srfNo); + data->real_id = FOURCC_YV12; + data->flags = flags; + + PPTHREAD_MUTEX_UNLOCK(); + + return 0; +} + +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 XvMCBadSurface; + + if (!(pI915XvMC = pI915Surface->privContext)) + return XvMCBadSurface; + + PPTHREAD_MUTEX_LOCK(); + 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(); + 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; + } + + PPTHREAD_MUTEX_UNLOCK(); + return 0; +} + +/* XXX WIP code */ +#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 XvMCBadSurface; + + /* Get the associated context pointer */ + if (!(pI915XvMC = pI915Surface->privContext)) + return 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; +} + +Status i915_xvmc_create_subpict(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 XvMCBadContext; + + subpicture->privData = + (i915XvMCSubpicture *)malloc(sizeof(i915XvMCSubpicture)); + + if (!subpicture->privData) + return BadAlloc; + + PPTHREAD_MUTEX_LOCK(); + 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(); + 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); + XFree(priv_data); + free(pI915Subpicture); + subpicture->privData = NULL; + PPTHREAD_MUTEX_UNLOCK(); + 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; + XFree(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(); + 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(); + return BadMatch; + } + + pI915XvMC->ref++; + PPTHREAD_MUTEX_UNLOCK(); + return Success; +} + +Status i915_xvmc_clear_subpict(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 XvMCBadSubpicture; + + if (!(pI915XvMC = pI915Subpicture->privContext)) + return 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; +} + +Status i915_xvmc_composite_subpict(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 XvMCBadSubpicture; + + if (!(pI915XvMC = pI915Subpicture->privContext)) + return 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; +} + + +Status i915_xvmc_destroy_subpict(Display *display, XvMCSubpicture *subpicture) +{ + i915XvMCSubpicture *pI915Subpicture; + i915XvMCContext *pI915XvMC; + + if (!display || !subpicture) + return BadValue; + + if (!(pI915Subpicture = subpicture->privData)) + return XvMCBadSubpicture; + + if (!(pI915XvMC = pI915Subpicture->privContext)) + return XvMCBadSubpicture; + + if (pI915Subpicture->last_render) + XvMCSyncSubpicture(display, subpicture); + + if (pI915Subpicture->srf.map) + drmUnmap(pI915Subpicture->srf.map, pI915Subpicture->srf.size); + + PPTHREAD_MUTEX_LOCK(); + XLockDisplay(display); + _xvmc_destroy_subpicture(display,subpicture); + XUnlockDisplay(display); + + free(pI915Subpicture); + subpicture->privData = NULL; + pI915XvMC->ref--; + PPTHREAD_MUTEX_UNLOCK(); + + return Success; +} + + +Status i915_xvmc_set_subpict_palette(Display *display, + XvMCSubpicture *subpicture, + unsigned char *palette) +{ + i915XvMCSubpicture *pI915Subpicture; + int i, j; + + if (!display || !subpicture) + return BadValue; + + if (!(pI915Subpicture = subpicture->privData)) + return 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; +} + +Status i915_xvmc_blend_subpict(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 XvMCBadSurface; + + if (subpicture) { + if (!(pI915Subpicture = subpicture->privData)) + return XvMCBadSubpicture; + + if ((FOURCC_AI44 != subpicture->xvimage_id) && + (FOURCC_IA44 != subpicture->xvimage_id)) + return XvMCBadSubpicture; + + privTargetSurface->privSubPic = pI915Subpicture; + } else { + privTargetSurface->privSubPic = NULL; + } + + return Success; +} + +Status i915_xvmc_blend_subpict2(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 XvMCBadSurface; + + if (!(privTargetSurface = target_surface->privData)) + return XvMCBadSurface; + + if (!(pI915XvMC = privTargetSurface->privContext)) + return 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 XvMCBadSubpicture; + + if ((FOURCC_AI44 != subpicture->xvimage_id) && + (FOURCC_IA44 != subpicture->xvimage_id)) + return XvMCBadSubpicture; + + privTargetSurface->privSubPic = pI915Subpicture; + } else { + privTargetSurface->privSubPic = NULL; + } + + return Success; +} + +Status i915_xvmc_sync_subpict(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; +} + +Status i915_xvmc_flush_subpict(Display *display, XvMCSubpicture *subpicture) +{ + i915XvMCSubpicture *pI915Subpicture; + + if (!display || !subpicture) + return BadValue; + + if (!(pI915Subpicture = subpicture->privData)) + return XvMCBadSubpicture; + + return Success; +} + +Status i915_xvmc_get_subpict_status(Display *display, XvMCSubpicture *subpicture, + int *stat) +{ + i915XvMCSubpicture *pI915Subpicture; + i915XvMCContext *pI915XvMC; + + if (!display || !subpicture || stat) + return BadValue; + + *stat = 0; + + if (!(pI915Subpicture = subpicture->privData)) + return XvMCBadSubpicture; + + if (!(pI915XvMC = pI915Subpicture->privContext)) + return XvMCBadSubpicture; + + PPTHREAD_MUTEX_LOCK(); + /* FIXME: */ + if (pI915Subpicture->last_render && + (pI915Subpicture->last_render > pI915XvMC->sarea->last_dispatch)) { + *stat |= XVMC_RENDERING; + } + + PPTHREAD_MUTEX_UNLOCK(); + return Success; +} + +#endif + +struct _intel_xvmc_driver i915_xvmc_mc_driver = { + .type = XVMC_I915_MPEG2_MC, + .num_ctx = 0, + .ctx_list = NULL, + .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, +}; diff --git a/src/xvmc/i915_xvmc.h b/src/xvmc/i915_xvmc.h new file mode 100644 index 00000000..af0a77da --- /dev/null +++ b/src/xvmc/i915_xvmc.h @@ -0,0 +1,117 @@ +/* + * 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 <haihao.xiang@intel.com> + * + */ + +#ifndef _I915XVMC_H +#define _I915XVMC_H + +#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 + +/* + * i915XvMCContext: + * Private Context data referenced via the privData + * pointer in the XvMCContext structure. + */ +typedef struct _i915XvMCContext { + unsigned int ctxno; + 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; + volatile drmI830Sarea *sarea; + 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 */ + void *drawHash; + int deviceID; + + intel_xvmc_drm_map_t sis; + intel_xvmc_drm_map_t msb; + intel_xvmc_drm_map_t ssb; + intel_xvmc_drm_map_t psp; + intel_xvmc_drm_map_t psc; + intel_xvmc_drm_map_t corrdata; +} 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]; + intel_xvmc_drm_map_t srf; + i915XvMCContext *privContext; +} i915XvMCSubpicture; + +/* Number of YUV buffers per surface */ +#define I830_MAX_BUFS 2 + +/* + * i915XvMCSurface: Private data structure for each XvMCSurface. This + * structure is referenced by the privData pointer in the XvMCSurface + * structure. + */ +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; + intel_xvmc_drm_map_t srf; + i915XvMCContext *privContext; + i915XvMCSubpicture *privSubPic; /* Subpicture to be blended when + * displaying. NULL if none. */ +} i915XvMCSurface; + +#endif /* _I915XVMC_H */ diff --git a/src/xvmc/intel_batchbuffer.c b/src/xvmc/intel_batchbuffer.c new file mode 100644 index 00000000..a3f82ff1 --- /dev/null +++ b/src/xvmc/intel_batchbuffer.c @@ -0,0 +1,271 @@ +/************************************************************************** + * + * 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 <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <signal.h> +#include <fcntl.h> +#include <dirent.h> +#include <string.h> +#include <assert.h> + +#include <sys/ioctl.h> +#include <X11/Xlibint.h> +#include <fourcc.h> +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvlib.h> +#include <X11/extensions/XvMC.h> +#include <X11/extensions/XvMClib.h> + +#include "intel_xvmc.h" +#include "intel_batchbuffer.h" + +#define MI_BATCH_BUFFER_END (0xA << 23) + +int intelEmitIrqLocked(void) +{ + 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(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); + } +} + +static void intelDestroyBatchBuffer(void) +{ + if (xvmc_driver->alloc.offset) { + xvmc_driver->alloc.ptr = NULL; + xvmc_driver->alloc.offset = 0; + } else if (xvmc_driver->alloc.ptr) { + free(xvmc_driver->alloc.ptr); + xvmc_driver->alloc.ptr = NULL; + } + + memset(&xvmc_driver->batch, 0, sizeof(xvmc_driver->batch)); +} + + +Bool intelInitBatchBuffer(void) +{ + if (drmMap(xvmc_driver->fd, + xvmc_driver->batchbuffer.handle, + xvmc_driver->batchbuffer.size, + (drmAddress *)&xvmc_driver->batchbuffer.map) != 0) { + XVMC_ERR("fail to map batch buffer\n"); + return False; + } + + if (xvmc_driver->batchbuffer.map) { + xvmc_driver->alloc.size = xvmc_driver->batchbuffer.size; + xvmc_driver->alloc.offset = xvmc_driver->batchbuffer.offset; + xvmc_driver->alloc.ptr = xvmc_driver->batchbuffer.map; + } else { + xvmc_driver->alloc.size = 8 * 1024; + xvmc_driver->alloc.offset = 0; + xvmc_driver->alloc.ptr = malloc(xvmc_driver->alloc.size); + } + + xvmc_driver->alloc.active_buf = 0; + assert(xvmc_driver->alloc.ptr); +} + +void intelFiniBatchBuffer(void) +{ + if (xvmc_driver->batchbuffer.map) { + drmUnmap(xvmc_driver->batchbuffer.map, xvmc_driver->batchbuffer.size); + xvmc_driver->batchbuffer.map = NULL; + } + intelDestroyBatchBuffer(); +} + +void intelBatchbufferRequireSpace(unsigned int sz) +{ + if (xvmc_driver->batch.space < sz) + intelFlushBatch(TRUE); +} + +void intelBatchbufferData(const void *data, unsigned bytes, unsigned flags) +{ + assert((bytes & 0x3) == 0); + + intelBatchbufferRequireSpace(bytes); + memcpy(xvmc_driver->batch.ptr, data, bytes); + xvmc_driver->batch.ptr += bytes; + xvmc_driver->batch.space -= bytes; + + assert(xvmc_driver->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(Bool allow_unlock ) +{ + unsigned half = xvmc_driver->alloc.size >> 1; + unsigned buf = (xvmc_driver->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((char *)&dword[0], sizeof(dword)); + xvmc_driver->alloc.irq_emitted = intelEmitIrqLocked(); + + if (xvmc_driver->alloc.irq_emitted) { + intelWaitIrq(xvmc_driver->alloc.irq_emitted); + } + + xvmc_driver->batch.start_offset = xvmc_driver->alloc.offset + buf * half; + xvmc_driver->batch.ptr = (unsigned char *)xvmc_driver->alloc.ptr + buf * half; + xvmc_driver->batch.size = half - 8; + xvmc_driver->batch.space = half - 8; + assert(xvmc_driver->batch.space >= 0); +} + + +void intelFlushBatchLocked(Bool ignore_cliprects, + Bool refill, + Bool allow_unlock) +{ + drmI830BatchBuffer batch; + + if (xvmc_driver->batch.space != xvmc_driver->batch.size) { + + batch.start = xvmc_driver->batch.start_offset; + batch.used = xvmc_driver->batch.size - xvmc_driver->batch.space; + batch.cliprects = 0; + batch.num_cliprects = 0; + batch.DR1 = 0; + batch.DR4 = 0; + + if (xvmc_driver->alloc.offset) { + if ((batch.used & 0x4) == 0) { + ((int *)xvmc_driver->batch.ptr)[0] = 0; + ((int *)xvmc_driver->batch.ptr)[1] = MI_BATCH_BUFFER_END; + batch.used += 0x8; + xvmc_driver->batch.ptr += 0x8; + } else { + ((int *)xvmc_driver->batch.ptr)[0] = MI_BATCH_BUFFER_END; + batch.used += 0x4; + xvmc_driver->batch.ptr += 0x4; + } + } + + xvmc_driver->batch.start_offset += batch.used; + xvmc_driver->batch.size -= batch.used; + + if (xvmc_driver->batch.size < 8) { + refill = TRUE; + xvmc_driver->batch.space = xvmc_driver->batch.size = 0; + } + else { + xvmc_driver->batch.size -= 8; + xvmc_driver->batch.space = xvmc_driver->batch.size; + } + + assert(xvmc_driver->batch.space >= 0); + assert(batch.start >= xvmc_driver->alloc.offset); + assert(batch.start < xvmc_driver->alloc.offset + xvmc_driver->alloc.size); + assert(batch.start + batch.used > xvmc_driver->alloc.offset); + assert(batch.start + batch.used <= xvmc_driver->alloc.offset + xvmc_driver->alloc.size); + + if (xvmc_driver->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 *)xvmc_driver->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(allow_unlock); +} + +void intelFlushBatch(Bool refill ) +{ + intelFlushBatchLocked(FALSE, refill, TRUE); +} + +void intelCmdIoctl(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 00000000..aec71e4a --- /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__, \ + xvmc_driver->batch.space/4); \ + if (xvmc_driver->batch.space < (n)*4) \ + intelFlushBatch(TRUE); \ + batch_ptr = xvmc_driver->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"); \ + xvmc_driver->batch.space -= (batch_ptr - xvmc_driver->batch.ptr); \ + xvmc_driver->batch.ptr = batch_ptr; \ + assert(xvmc_driver->batch.space >= 0); \ + } while(0) + +extern void intelFlushBatch(Bool); +extern void intelBatchbufferData(const void *, unsigned, unsigned); +extern Bool intelInitBatchBuffer(void); +extern void intelFiniBatchBuffer(void); +extern void intelCmdIoctl(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 00000000..489a2c2c --- /dev/null +++ b/src/xvmc/intel_xvmc.c @@ -0,0 +1,1069 @@ +/* + * 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 <zhenyu.z.wang@intel.com> + * + */ +#include "intel_xvmc.h" + +struct _intel_xvmc_driver *xvmc_driver = NULL; +static int error_base; +static int event_base; + +/* locking */ +static void intel_xvmc_try_heavy_lock(drm_context_t ctx) +{ + drmGetLock(xvmc_driver->fd, ctx, 0); +} + +void LOCK_HARDWARE(drm_context_t ctx) +{ + char __ret = 0; + + PPTHREAD_MUTEX_LOCK(); + assert(!xvmc_driver->locked); + + DRM_CAS(xvmc_driver->driHwLock, ctx, + (DRM_LOCK_HELD | ctx), __ret); + + if (__ret) + intel_xvmc_try_heavy_lock(ctx); + + xvmc_driver->locked = 1; +} + +void UNLOCK_HARDWARE(drm_context_t ctx) +{ + xvmc_driver->locked = 0; + DRM_UNLOCK(xvmc_driver->fd, xvmc_driver->driHwLock, ctx); + PPTHREAD_MUTEX_UNLOCK(); +} + +static intel_xvmc_context_ptr intel_xvmc_new_context(Display *dpy) +{ + intel_xvmc_context_ptr ret; + + ret = (intel_xvmc_context_ptr)calloc(1, sizeof(intel_xvmc_context_t)); + if (!ret) + return NULL; + + if (!xvmc_driver->ctx_list) + ret->next = NULL; + else + ret->next = xvmc_driver->ctx_list; + xvmc_driver->ctx_list = ret; + xvmc_driver->num_ctx++; + + return ret; + +} + +static void intel_xvmc_free_context(XID id) +{ + intel_xvmc_context_ptr p = xvmc_driver->ctx_list; + intel_xvmc_context_ptr pre = p; + + while(p) { + if (p->context && p->context->context_id == id) { + if (p == xvmc_driver->ctx_list) + xvmc_driver->ctx_list = p->next; + else + pre->next = p->next; + break; + } + pre = p; + p = p->next; + } + + if (p) { + free(p); + xvmc_driver->num_ctx--; + } +} + +intel_xvmc_context_ptr intel_xvmc_find_context(XID id) +{ + intel_xvmc_context_ptr p = xvmc_driver->ctx_list; + + while(p) { + if (p->context && p->context->context_id == id) + return p; + p = p->next; + } + return NULL; +} + +static intel_xvmc_surface_ptr intel_xvmc_new_surface(Display *dpy) +{ + intel_xvmc_surface_ptr ret; + + ret = (intel_xvmc_surface_ptr)calloc(1, sizeof(intel_xvmc_surface_t)); + if (!ret) + return NULL; + + if (!xvmc_driver->surf_list) + ret->next = NULL; + else + ret->next = xvmc_driver->surf_list; + xvmc_driver->surf_list = ret; + xvmc_driver->num_surf++; + + ret->image = NULL; + ret->gc_init = FALSE; + + return ret; + +} + +static void intel_xvmc_free_surface(XID id) +{ + intel_xvmc_surface_ptr p = xvmc_driver->surf_list; + intel_xvmc_surface_ptr pre = p; + + while(p) { + if (p->surface && p->surface->surface_id == id) { + if (p == xvmc_driver->surf_list) + xvmc_driver->surf_list = p->next; + else + pre->next = p->next; + break; + } + pre = p; + p = p->next; + } + + if (p) { + free(p); + xvmc_driver->num_surf--; + } +} + +intel_xvmc_surface_ptr intel_xvmc_find_surface(XID id) +{ + intel_xvmc_surface_ptr p = xvmc_driver->surf_list; + + while(p) { + if (p->surface && p->surface->surface_id == id) + return p; + p = p->next; + } + return NULL; +} +/* +* Function: XvMCCreateContext +* Description: Create a XvMC context for the given surface parameters. +* Arguments: +* display - Connection to the X server. +* port - XvPortID to use as avertised by the X connection. +* surface_type_id - Unique identifier for the Surface type. +* width - Width of the surfaces. +* height - Height of the surfaces. +* flags - one or more of the following +* XVMC_DIRECT - A direct rendered context is requested. +* +* Notes: surface_type_id and width/height parameters must match those +* returned by XvMCListSurfaceTypes. +* Returns: Status +*/ +Status XvMCCreateContext(Display *display, XvPortID port, + int surface_type_id, int width, int height, + int flags, XvMCContext *context) +{ + 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); + intel_xvmc_context_ptr intel_ctx; + int fd; + + /* Verify Obvious things first */ + if (!display || !context) + return BadValue; + + if (!(flags & XVMC_DIRECT)) { + XVMC_ERR("Indirect Rendering not supported! Using Direct."); + return BadValue; + } + + /* Open DRI Device */ + if((fd = drmOpen("i915", NULL)) < 0) { + XVMC_ERR("DRM Device could not be opened."); + return BadValue; + } + + /* + 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; + } + XVMC_DBG("new context %d created\n", context->context_id); + + comm = (struct _intel_xvmc_common *)priv_data; + + 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); + XFree(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->fd = fd; + + XVMC_INFO("decoder type is %s", intel_xvmc_decoder_string(comm->type)); + + xvmc_driver->sarea_size = comm->sarea_size; + xvmc_driver->batchbuffer.handle = comm->batchbuffer.handle; + xvmc_driver->batchbuffer.offset = comm->batchbuffer.offset; + xvmc_driver->batchbuffer.size = comm->batchbuffer.size; + + /* assign local ctx info */ + intel_ctx = intel_xvmc_new_context(display); + if (!intel_ctx) { + XVMC_ERR("Intel XvMC context create fail\n"); + return BadAlloc; + } + intel_ctx->context = context; + + ret = uniDRIQueryDirectRenderingCapable(display, screen, + &isCapable); + if (!ret || !isCapable) { + XVMC_ERR("Direct Rendering is not available on this system!"); + XFree(priv_data); + return BadValue; + } + + if (!uniDRIOpenConnection(display, screen, + &xvmc_driver->hsarea, &curBusID)) { + XVMC_ERR("Could not open DRI connection to X server!"); + XFree(priv_data); + return BadValue; + } + + strncpy(xvmc_driver->busID, curBusID, 20); + xvmc_driver->busID[20] = '\0'; + XFree(curBusID); + + /* 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 = NULL; + XFree(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 = NULL; + XFree(priv_data); + return BadAlloc; + } + pSAREA = (drm_sarea_t *)xvmc_driver->sarea_address; + xvmc_driver->driHwLock = (drmLock *)&pSAREA->lock; + pthread_mutex_init(&xvmc_driver->ctxmutex, NULL); + + /* context_id is alloc in _xvmc_create_context */ + if (!uniDRICreateContext(display, screen, DefaultVisual(display, screen), + context->context_id, + &intel_ctx->hw_context)) { + XVMC_ERR("Could not create DRI context for xvmc ctx %d.", + context->context_id); + XFree(priv_data); + context->privData = NULL; + drmUnmap(xvmc_driver->sarea_address, xvmc_driver->sarea_size); + 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"); + XFree(priv_data); + drmUnmap(xvmc_driver->sarea_address, xvmc_driver->sarea_size); + return ret; + } + + intelInitBatchBuffer(); + + return Success; +} + +/* + * Function: XvMCDestroyContext + * Description: Destorys the specified context. + * + * Arguments: + * display - Specifies the connection to the server. + * context - The context to be destroyed. + * + */ +Status XvMCDestroyContext(Display *display, XvMCContext *context) +{ + Status ret; + int screen = DefaultScreen(display); + + if (!display || !context) + return XvMCBadContext; + + ret = (xvmc_driver->destroy_context)(display, context); + if (ret) { + XVMC_ERR("destroy context fail\n"); + return ret; + } + + uniDRIDestroyContext(display, screen, context->context_id); + intel_xvmc_free_context(context->context_id); + + ret = _xvmc_destroy_context(display, context); + if (ret != Success) { + XVMC_ERR("_xvmc_destroy_context fail\n"); + return ret; + } + + if (xvmc_driver->num_ctx == 0) { + uniDRICloseConnection(display, screen); + + pthread_mutex_destroy(&xvmc_driver->ctxmutex); + + drmUnmap(xvmc_driver->sarea_address, xvmc_driver->sarea_size); + + if (xvmc_driver->fd >= 0) + drmClose(xvmc_driver->fd); + xvmc_driver->fd = -1; + + intelFiniBatchBuffer(); + } + return Success; +} + +/* + * Function: XvMCCreateSurface + */ +Status XvMCCreateSurface(Display *display, XvMCContext *context, XvMCSurface *surface) +{ + Status ret; + int priv_count; + CARD32 *priv_data; + intel_xvmc_surface_ptr intel_surf = NULL; + + if (!display || !context) + return XvMCBadContext; + + if (!surface) + return XvMCBadSurface; + + intel_surf = intel_xvmc_new_surface(display); + if (!intel_surf) + return BadAlloc; + intel_surf->surface = surface; + + if ((ret = _xvmc_create_surface(display, context, surface, + &priv_count, &priv_data))) { + XVMC_ERR("Unable to create XvMCSurface."); + return ret; + } + + intel_surf->image = XvCreateImage(display, context->port, + FOURCC_XVMC, (char *)&intel_surf->data, surface->width, + surface->height); + if (!intel_surf->image) { + XVMC_ERR("Can't create XvImage for surface\n"); + _xvmc_destroy_surface(display, surface); + intel_xvmc_free_surface(surface->surface_id); + return BadAlloc; + } + intel_surf->image->data = (char *)&intel_surf->data; + + ret = (xvmc_driver->create_surface)(display, context, surface, priv_count, + priv_data); + if (ret) { + XVMC_ERR("create surface failed\n"); + return ret; + } + + return Success; +} + + +/* + * Function: XvMCDestroySurface + */ +Status XvMCDestroySurface(Display *display, XvMCSurface *surface) +{ + intel_xvmc_surface_ptr intel_surf; + + if (!display || !surface) + return XvMCBadSurface; + + intel_surf = intel_xvmc_find_surface(surface->surface_id); + if (!intel_surf) + return XvMCBadSurface; + + XFree(intel_surf->image); + if (intel_surf->gc_init) + XFreeGC(display, intel_surf->gc); + intel_xvmc_free_surface(surface->surface_id); + + (xvmc_driver->destroy_surface)(display, surface); + + _xvmc_destroy_surface(display, surface); + + 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; + } + 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. + */ +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 = Success; + XvMCContext *context; + intel_xvmc_context_ptr intel_ctx; + intel_xvmc_surface_ptr intel_surf; + + if (!display || !surface) + return XvMCBadSurface; + + intel_ctx = intel_xvmc_find_context(surface->context_id); + intel_surf = intel_xvmc_find_surface(surface->surface_id); + if (!intel_ctx || !intel_surf) + return XvMCBadSurface; + context = intel_ctx->context; + + if (intel_surf->gc_init == FALSE) { + intel_surf->gc = XCreateGC(display, draw, 0, NULL); + intel_surf->gc_init = TRUE; + } else if (draw != intel_surf->last_draw) { + XFreeGC(display, intel_surf->gc); + intel_surf->gc = XCreateGC(display, draw, 0, NULL); + } + intel_surf->last_draw = draw; + + /* fill intel_surf->data */ + ret = (xvmc_driver->put_surface)(display, surface, draw, srcx, srcy, + srcw, srch, destx, desty, destw, desth, flags, &intel_surf->data); + if (ret) { + XVMC_ERR("put surface fail\n"); + return ret; + } + + ret = XvPutImage(display, context->port, draw, intel_surf->gc, + intel_surf->image, srcx, srcy, srcw, srch, destx, desty, + destw, desth); + + return ret; +} + +/* + * Function: XvMCSyncSurface + * Arguments: + * display - Connection to the X server + * surface - The surface to synchronize + */ +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; + } + + return Success; +} + +/* + * Function: XvMCHideSurface + * Description: Stops the display of a surface. + * Arguments: + * display - Connection to the X server. + * surface - surface to be hidden. + * + * Returns: Status + */ +Status XvMCHideSurface(Display *display, XvMCSurface *surface) +{ + int stat = 0; + Status ret; + + if (!display || !surface) + return 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: */ + XVMC_ERR("XvMCHideSurface not implemented!\n"); + return BadValue; +} + +/* + * 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) +{ + XVMC_ERR("XvMCCreateSubpicture not implemented!\n"); + 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) +{ + XVMC_ERR("XvMCClearSubpicture not implemented!"); + 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) +{ + XVMC_ERR("XvMCCompositeSubpicture not implemented!"); + 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) +{ + XVMC_ERR("XvMCDestroySubpicture not implemented!"); + 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) +{ + XVMC_ERR("XvMCSetSubpicturePalette not implemented!"); + 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) +{ + XVMC_ERR("XvMCBlendSubpicture not implemented!"); + 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) +{ + XVMC_ERR("XvMCBlendSubpicture2 not implemented!"); + 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) +{ + XVMC_ERR("XvMCSyncSubpicture not implemented!"); + return BadValue; +} + +/* + * 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) +{ + XVMC_ERR("XvMCFlushSubpicture not implemented!"); + return BadValue; +} + +/* + * 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) +{ + XVMC_ERR("XvMCGetSubpictureStatus not implemented!"); + return BadValue; +} + +/* + * 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 + */ +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 00000000..3375ffc4 --- /dev/null +++ b/src/xvmc/intel_xvmc.h @@ -0,0 +1,252 @@ +/* + * 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 <zhenyu.z.wang@intel.com> + * + */ +#ifndef INTEL_XVMC_H +#define INTEL_XVMC_H + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <signal.h> +#include <fcntl.h> +#include <dirent.h> +#include <string.h> +#include <assert.h> +#include <signal.h> + +#include <xf86drm.h> +#include "i830_common.h" +#include "i830_hwmc.h" +#include <X11/X.h> +#include <X11/Xlibint.h> +#include <X11/Xutil.h> +#include <fourcc.h> +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvlib.h> +#include <X11/extensions/XvMC.h> +#include <X11/extensions/XvMClib.h> +#include <drm_sarea.h> + +#include "xf86dri.h" +#include "driDrawable.h" + +#include "intel_batchbuffer.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, + CARD32 **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); + +typedef struct _intel_xvmc_context { + XvMCContext *context; + drm_context_t hw_context; /* context id to kernel drm */ + struct _intel_xvmc_context *next; +} intel_xvmc_context_t, *intel_xvmc_context_ptr; + +typedef struct _intel_xvmc_surface { + XvMCSurface *surface; + XvImage *image; + GC gc; + Bool gc_init; + Drawable last_draw; + struct intel_xvmc_command data; + struct _intel_xvmc_surface *next; +} intel_xvmc_surface_t, *intel_xvmc_surface_ptr; + +typedef struct _intel_xvmc_drm_map { + drm_handle_t handle; + unsigned long offset; + unsigned long size; + unsigned long bus_addr; + drmAddress map; +} intel_xvmc_drm_map_t, *intel_xvmc_drm_map_ptr; + +typedef 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; + + 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; + intel_xvmc_drm_map_t batchbuffer; + unsigned int last_render; + + sigset_t sa_mask; + pthread_mutex_t ctxmutex; + int lock; /* Lightweight lock to avoid locking twice */ + int locked; + drmLock *driHwLock; + + int num_ctx; + intel_xvmc_context_ptr ctx_list; + int num_surf; + intel_xvmc_surface_ptr surf_list; + + void *private; + + /* 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, int priv_count, CARD32 *priv_data); + + 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); + + 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, struct intel_xvmc_command *data); + + Status (*get_surface_status)(Display *display, XvMCSurface *surface, int *stat); + + /* XXX more for vld */ +} intel_xvmc_driver_t, *intel_xvmc_driver_ptr; + +extern struct _intel_xvmc_driver i915_xvmc_mc_driver; +extern struct _intel_xvmc_driver *xvmc_driver; + +#define SET_BLOCKED_SIGSET() 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, &xvmc_driver->sa_mask); \ + } while (0) + +#define RESTORE_BLOCKED_SIGSET() do { \ + pthread_sigmask(SIG_SETMASK, &xvmc_driver->sa_mask, NULL); \ + } while (0) + +#define PPTHREAD_MUTEX_LOCK() do { \ + SET_BLOCKED_SIGSET(); \ + pthread_mutex_lock(&xvmc_driver->ctxmutex); \ + } while (0) + +#define PPTHREAD_MUTEX_UNLOCK() do { \ + pthread_mutex_unlock(&xvmc_driver->ctxmutex); \ + RESTORE_BLOCKED_SIGSET(); \ + } while (0) + +extern void LOCK_HARDWARE(drm_context_t); +extern void UNLOCK_HARDWARE(drm_context_t); + +static inline const char* intel_xvmc_decoder_string(int flag) +{ + switch (flag) { + case XVMC_I915_MPEG2_MC: + return "i915/945 MPEG2 MC decoder"; + case XVMC_I965_MPEG2_MC: + return "i965 MPEG2 MC decoder"; + case XVMC_I945_MPEG2_VLD: + return "i945 MPEG2 VLD decoder"; + case XVMC_I965_MPEG2_VLD: + return "i965 MPEG2 VLD decoder"; + default: + return "Unknown decoder"; + } +} + +extern intel_xvmc_context_ptr intel_xvmc_find_context(XID id); +extern intel_xvmc_surface_ptr intel_xvmc_find_surface(XID id); + +#endif diff --git a/src/xvmc/xf86dri.c b/src/xvmc/xf86dri.c new file mode 100644 index 00000000..798c1a84 --- /dev/null +++ b/src/xvmc/xf86dri.c @@ -0,0 +1,601 @@ +/* $XFree86: xc/lib/GL/dri/XF86dri.c,v 1.13 2002/10/30 12:51:25 alanh Exp $ */ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <martin@valinux.com> + * Jens Owen <jens@tungstengraphics.com> + * Rickard E. (Rik) Faith <faith@valinux.com> + * + */ + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +#define NEED_REPLIES +#include <X11/Xlibint.h> +#include <X11/extensions/Xext.h> +#include <X11/extensions/extutil.h> +#include "xf86dristr.h" + +static XExtensionInfo _xf86dri_info_data; +static XExtensionInfo *xf86dri_info = &_xf86dri_info_data; +static char xf86dri_extension_name[] = XF86DRINAME; + +#define uniDRICheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, xf86dri_extension_name, val) + +/***************************************************************************** + * * + * private utility routines * + * * + *****************************************************************************/ + +static int close_display(Display * dpy, XExtCodes * extCodes); +static /* const */ XExtensionHooks xf86dri_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + close_display, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static +XEXT_GENERATE_FIND_DISPLAY(find_display, xf86dri_info, + xf86dri_extension_name, &xf86dri_extension_hooks, 0, NULL) + + static XEXT_GENERATE_CLOSE_DISPLAY(close_display, xf86dri_info) + +/***************************************************************************** + * * + * public XFree86-DRI Extension routines * + * * + *****************************************************************************/ +#if 0 +#include <stdio.h> +#define TRACE(msg, arg...) fprintf(stderr,"uniDRI" msg "\n", ##arg); +#else +#define TRACE(msg, arg...) +#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... %d.%d.%d return True", rep.majorVersion, + rep.minorVersion, rep.patchVersion); + 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... %s return True", + rep.isCapable ? "true" : "false"); + 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... busid %s return True", + *busIdString ? *busIdString : "null"); + 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... id %d", context); + 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; + 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... id %d", context); + uniDRICheckExtension(dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIDestroyContext, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIDestroyContext; + req->screen = screen; + req->context = context; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("DestroyContext... return True"); + return True; +} + +Bool +uniDRICreateDrawable(Display * ndpy, int screen, + Drawable drawable, drm_drawable_t * hHWDrawable) +{ + Display *const dpy = (Display *) ndpy; + XExtDisplayInfo *info = find_display(dpy); + xXF86DRICreateDrawableReply rep; + xXF86DRICreateDrawableReq *req; + + TRACE("CreateDrawable..."); + uniDRICheckExtension(dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRICreateDrawable, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRICreateDrawable; + req->screen = screen; + req->drawable = drawable; + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("CreateDrawable... return False"); + return False; + } + *hHWDrawable = rep.hHWDrawable; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("CreateDrawable... return True"); + return True; +} + +Bool +uniDRIDestroyDrawable(Display * ndpy, int screen, Drawable drawable) +{ + Display *const dpy = (Display *) ndpy; + XExtDisplayInfo *info = find_display(dpy); + xXF86DRIDestroyDrawableReq *req; + + TRACE("DestroyDrawable..."); + uniDRICheckExtension(dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIDestroyDrawable, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIDestroyDrawable; + req->screen = screen; + req->drawable = drawable; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("DestroyDrawable... return True"); + return True; +} + +Bool +uniDRIGetDrawableInfo(Display * dpy, int screen, Drawable drawable, + unsigned int *index, unsigned int *stamp, + int *X, int *Y, int *W, int *H, + int *numClipRects, drm_clip_rect_t ** pClipRects, + int *backX, int *backY, + int *numBackClipRects, drm_clip_rect_t ** pBackClipRects) +{ + XExtDisplayInfo *info = find_display(dpy); + xXF86DRIGetDrawableInfoReply rep; + xXF86DRIGetDrawableInfoReq *req; + int total_rects; + + TRACE("GetDrawableInfo..."); + uniDRICheckExtension(dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIGetDrawableInfo, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIGetDrawableInfo; + req->screen = screen; + req->drawable = drawable; + + if (!_XReply(dpy, (xReply *) & rep, 1, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDrawableInfo... return False"); + return False; + } + *index = rep.drawableTableIndex; + *stamp = rep.drawableTableStamp; + *X = (int)rep.drawableX; + *Y = (int)rep.drawableY; + *W = (int)rep.drawableWidth; + *H = (int)rep.drawableHeight; + *numClipRects = rep.numClipRects; + total_rects = *numClipRects; + + *backX = rep.backX; + *backY = rep.backY; + *numBackClipRects = rep.numBackClipRects; + total_rects += *numBackClipRects; + +#if 0 + /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks + * backwards compatibility (Because of the >> 2 shift) but the fix + * enables multi-threaded apps to work. + */ + if (rep.length != ((((SIZEOF(xXF86DRIGetDrawableInfoReply) - + SIZEOF(xGenericReply) + + total_rects * sizeof(drm_clip_rect_t)) + + 3) & ~3) >> 2)) { + _XEatData(dpy, rep.length); + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDrawableInfo... return False"); + return False; + } +#endif + + if (*numClipRects) { + int len = sizeof(drm_clip_rect_t) * (*numClipRects); + + *pClipRects = (drm_clip_rect_t *) Xcalloc(len, 1); + if (*pClipRects) + _XRead(dpy, (char *)*pClipRects, len); + } else { + *pClipRects = NULL; + } + + if (*numBackClipRects) { + int len = sizeof(drm_clip_rect_t) * (*numBackClipRects); + + *pBackClipRects = (drm_clip_rect_t *) Xcalloc(len, 1); + if (*pBackClipRects) + _XRead(dpy, (char *)*pBackClipRects, len); + } else { + *pBackClipRects = NULL; + } + + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDrawableInfo... return True"); + return True; +} + +Bool +uniDRIGetDeviceInfo(dpy, screen, hFrameBuffer, + fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate) + Display *dpy; + int screen; + drm_handle_t *hFrameBuffer; + int *fbOrigin; + int *fbSize; + int *fbStride; + int *devPrivateSize; + void **pDevPrivate; +{ + XExtDisplayInfo *info = find_display(dpy); + xXF86DRIGetDeviceInfoReply rep; + xXF86DRIGetDeviceInfoReq *req; + + TRACE("GetDeviceInfo..."); + uniDRICheckExtension(dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIGetDeviceInfo, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIGetDeviceInfo; + req->screen = screen; + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDeviceInfo... return False"); + return False; + } + + *hFrameBuffer = rep.hFrameBufferLow; +#ifdef LONG64 + if (sizeof(drm_handle_t) == 8) { + *hFrameBuffer |= ((unsigned long)rep.hFrameBufferHigh) << 32; + } +#endif + + *fbOrigin = rep.framebufferOrigin; + *fbSize = rep.framebufferSize; + *fbStride = rep.framebufferStride; + *devPrivateSize = rep.devPrivateSize; + + if (rep.length) { + if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) { + _XEatData(dpy, ((rep.devPrivateSize + 3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDeviceInfo... return False"); + return False; + } + _XRead(dpy, (char *)*pDevPrivate, rep.devPrivateSize); + } else { + *pDevPrivate = NULL; + } + + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDeviceInfo... return True"); + return True; +} diff --git a/src/xvmc/xf86dri.h b/src/xvmc/xf86dri.h new file mode 100644 index 00000000..7598bc81 --- /dev/null +++ b/src/xvmc/xf86dri.h @@ -0,0 +1,111 @@ +/* $XFree86: xc/lib/GL/dri/xf86dri.h,v 1.8 2002/10/30 12:51:25 alanh Exp $ */ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/** + * \file xf86dri.h + * Protocol numbers and function prototypes for DRI X protocol. + * + * \author Kevin E. Martin <martin@valinux.com> + * \author Jens Owen <jens@tungstengraphics.com> + * \author Rickard E. (Rik) Faith <faith@valinux.com> + */ + +#ifndef _XF86DRI_H_ +#define _XF86DRI_H_ + +#include <X11/Xfuncproto.h> +#include <xf86drm.h> + +#define X_XF86DRIQueryVersion 0 +#define X_XF86DRIQueryDirectRenderingCapable 1 +#define X_XF86DRIOpenConnection 2 +#define X_XF86DRICloseConnection 3 +#define X_XF86DRIGetClientDriverName 4 +#define X_XF86DRICreateContext 5 +#define X_XF86DRIDestroyContext 6 +#define X_XF86DRICreateDrawable 7 +#define X_XF86DRIDestroyDrawable 8 +#define X_XF86DRIGetDrawableInfo 9 +#define X_XF86DRIGetDeviceInfo 10 +#define X_XF86DRIAuthConnection 11 +#define X_XF86DRIOpenFullScreen 12 /* Deprecated */ +#define X_XF86DRICloseFullScreen 13 /* Deprecated */ + +#define XF86DRINumberEvents 0 + +#define XF86DRIClientNotLocal 0 +#define XF86DRIOperationNotSupported 1 +#define XF86DRINumberErrors (XF86DRIOperationNotSupported + 1) + +#ifndef _XF86DRI_SERVER_ + +_XFUNCPROTOBEGIN + Bool uniDRIQueryExtension(Display * dpy, int *event_base, + int *error_base); + +Bool uniDRIQueryVersion(Display * dpy, int *majorVersion, int *minorVersion, + int *patchVersion); + +Bool uniDRIQueryDirectRenderingCapable(Display * dpy, int screen, + Bool * isCapable); + +Bool uniDRIOpenConnection(Display * dpy, int screen, drm_handle_t * hSAREA, + char **busIDString); + +Bool uniDRIAuthConnection(Display * dpy, int screen, drm_magic_t magic); + +Bool uniDRICloseConnection(Display * dpy, int screen); + +Bool uniDRIGetClientDriverName(Display * dpy, int screen, + int *ddxDriverMajorVersion, int *ddxDriverMinorVersion, + int *ddxDriverPatchVersion, char **clientDriverName); + +/* XvMC context XID is alloced in _xvmc_create_context, so + * don't recreate here */ +Bool uniDRICreateContext(Display * dpy, int screen, Visual * visual, + XID context_id, drm_context_t * hHWContext); + +Bool uniDRICreateContextWithConfig(Display * dpy, int screen, int configID, + XID context_id, drm_context_t * hHWContext); + +extern Bool uniDRIDestroyContext(Display * dpy, int screen, XID context_id); + +extern Bool uniDRICreateDrawable(Display * dpy, int screen, + Drawable drawable, drm_drawable_t * hHWDrawable); + +extern Bool uniDRIDestroyDrawable(Display * dpy, int screen, + Drawable drawable); + +Bool uniDRIGetDeviceInfo(Display * dpy, int screen, + drm_handle_t * hFrameBuffer, int *fbOrigin, int *fbSize, + int *fbStride, int *devPrivateSize, void **pDevPrivate); + +_XFUNCPROTOEND +#endif /* _XF86DRI_SERVER_ */ +#endif /* _XF86DRI_H_ */ diff --git a/src/xvmc/xf86dristr.h b/src/xvmc/xf86dristr.h new file mode 100644 index 00000000..3b43438e --- /dev/null +++ b/src/xvmc/xf86dristr.h @@ -0,0 +1,390 @@ +/* $XFree86: xc/lib/GL/dri/xf86dristr.h,v 1.10 2002/10/30 12:51:25 alanh Exp $ */ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <martin@valinux.com> + * Jens Owen <jens@tungstengraphics.com> + * Rickard E. (Rik) Fiath <faith@valinux.com> + * + */ + +#ifndef _XF86DRISTR_H_ +#define _XF86DRISTR_H_ + +#include "xf86dri.h" + +#define XF86DRINAME "XFree86-DRI" + +/* The DRI version number. This was originally set to be the same of the + * XFree86 version number. However, this version is really indepedent of + * the XFree86 version. + * + * Version History: + * 4.0.0: Original + * 4.0.1: Patch to bump clipstamp when windows are destroyed, 28 May 02 + * 4.1.0: Add transition from single to multi in DRMInfo rec, 24 Jun 02 + */ +#define XF86DRI_MAJOR_VERSION 4 +#define XF86DRI_MINOR_VERSION 1 +#define XF86DRI_PATCH_VERSION 0 + +typedef struct _XF86DRIQueryVersion +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRIQueryVersion */ + CARD16 length B16; +} xXF86DRIQueryVersionReq; + +#define sz_xXF86DRIQueryVersionReq 4 + +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 majorVersion B16; /* major version of DRI protocol */ + CARD16 minorVersion B16; /* minor version of DRI protocol */ + CARD32 patchVersion B32; /* patch version of DRI protocol */ + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86DRIQueryVersionReply; + +#define sz_xXF86DRIQueryVersionReply 32 + +typedef struct _XF86DRIQueryDirectRenderingCapable +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* X_DRIQueryDirectRenderingCapable */ + CARD16 length B16; + CARD32 screen B32; +} xXF86DRIQueryDirectRenderingCapableReq; + +#define sz_xXF86DRIQueryDirectRenderingCapableReq 8 + +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + BOOL isCapable; + BOOL pad2; + BOOL pad3; + BOOL pad4; + CARD32 pad5 B32; + CARD32 pad6 B32; + CARD32 pad7 B32; + CARD32 pad8 B32; + CARD32 pad9 B32; +} xXF86DRIQueryDirectRenderingCapableReply; + +#define sz_xXF86DRIQueryDirectRenderingCapableReply 32 + +typedef struct _XF86DRIOpenConnection +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRIOpenConnection */ + CARD16 length B16; + CARD32 screen B32; +} xXF86DRIOpenConnectionReq; + +#define sz_xXF86DRIOpenConnectionReq 8 + +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 hSAREALow B32; + CARD32 hSAREAHigh B32; + CARD32 busIdStringLength B32; + CARD32 pad6 B32; + CARD32 pad7 B32; + CARD32 pad8 B32; +} xXF86DRIOpenConnectionReply; + +#define sz_xXF86DRIOpenConnectionReply 32 + +typedef struct _XF86DRIAuthConnection +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRICloseConnection */ + CARD16 length B16; + CARD32 screen B32; + CARD32 magic B32; +} xXF86DRIAuthConnectionReq; + +#define sz_xXF86DRIAuthConnectionReq 12 + +typedef struct +{ + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 authenticated B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86DRIAuthConnectionReply; + +#define zx_xXF86DRIAuthConnectionReply 32 + +typedef struct _XF86DRICloseConnection +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRICloseConnection */ + CARD16 length B16; + CARD32 screen B32; +} xXF86DRICloseConnectionReq; + +#define sz_xXF86DRICloseConnectionReq 8 + +typedef struct _XF86DRIGetClientDriverName +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRIGetClientDriverName */ + CARD16 length B16; + CARD32 screen B32; +} xXF86DRIGetClientDriverNameReq; + +#define sz_xXF86DRIGetClientDriverNameReq 8 + +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 ddxDriverMajorVersion B32; + CARD32 ddxDriverMinorVersion B32; + CARD32 ddxDriverPatchVersion B32; + CARD32 clientDriverNameLength B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86DRIGetClientDriverNameReply; + +#define sz_xXF86DRIGetClientDriverNameReply 32 + +typedef struct _XF86DRICreateContext +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRICreateContext */ + CARD16 length B16; + CARD32 screen B32; + CARD32 visual B32; + CARD32 context B32; +} xXF86DRICreateContextReq; + +#define sz_xXF86DRICreateContextReq 16 + +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 hHWContext B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86DRICreateContextReply; + +#define sz_xXF86DRICreateContextReply 32 + +typedef struct _XF86DRIDestroyContext +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRIDestroyContext */ + CARD16 length B16; + CARD32 screen B32; + CARD32 context B32; +} xXF86DRIDestroyContextReq; + +#define sz_xXF86DRIDestroyContextReq 12 + +typedef struct _XF86DRICreateDrawable +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRICreateDrawable */ + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; +} xXF86DRICreateDrawableReq; + +#define sz_xXF86DRICreateDrawableReq 12 + +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 hHWDrawable B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86DRICreateDrawableReply; + +#define sz_xXF86DRICreateDrawableReply 32 + +typedef struct _XF86DRIDestroyDrawable +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRIDestroyDrawable */ + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; +} xXF86DRIDestroyDrawableReq; + +#define sz_xXF86DRIDestroyDrawableReq 12 + +typedef struct _XF86DRIGetDrawableInfo +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRIGetDrawableInfo */ + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; +} xXF86DRIGetDrawableInfoReq; + +#define sz_xXF86DRIGetDrawableInfoReq 12 + +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 drawableTableIndex B32; + CARD32 drawableTableStamp B32; + INT16 drawableX B16; + INT16 drawableY B16; + INT16 drawableWidth B16; + INT16 drawableHeight B16; + CARD32 numClipRects B32; + INT16 backX B16; + INT16 backY B16; + CARD32 numBackClipRects B32; +} xXF86DRIGetDrawableInfoReply; + +#define sz_xXF86DRIGetDrawableInfoReply 36 + +typedef struct _XF86DRIGetDeviceInfo +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRIGetDeviceInfo */ + CARD16 length B16; + CARD32 screen B32; +} xXF86DRIGetDeviceInfoReq; + +#define sz_xXF86DRIGetDeviceInfoReq 8 + +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 hFrameBufferLow B32; + CARD32 hFrameBufferHigh B32; + CARD32 framebufferOrigin B32; + CARD32 framebufferSize B32; + CARD32 framebufferStride B32; + CARD32 devPrivateSize B32; +} xXF86DRIGetDeviceInfoReply; + +#define sz_xXF86DRIGetDeviceInfoReply 32 + +typedef struct _XF86DRIOpenFullScreen +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRIOpenFullScreen */ + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; +} xXF86DRIOpenFullScreenReq; + +#define sz_xXF86DRIOpenFullScreenReq 12 + +typedef struct +{ + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 isFullScreen B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86DRIOpenFullScreenReply; + +#define sz_xXF86DRIOpenFullScreenReply 32 + +typedef struct _XF86DRICloseFullScreen +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRICloseFullScreen */ + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; +} xXF86DRICloseFullScreenReq; + +#define sz_xXF86DRICloseFullScreenReq 12 + +typedef struct +{ + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; + CARD32 pad7 B32; +} xXF86DRICloseFullScreenReply; + +#define sz_xXF86DRICloseFullScreenReply 32 + +#endif /* _XF86DRISTR_H_ */ |