summaryrefslogtreecommitdiff
path: root/src/i965_hwmc.c
diff options
context:
space:
mode:
authorZou Nan hai <nanhai.zou@intel.com>2008-06-24 16:43:40 +0800
committerZou Nan hai <nanhai.zou@intel.com>2008-06-24 16:43:40 +0800
commit277632d8c37cf43c7c1178ae7d5a2e6d5705968c (patch)
tree7e51ae501f9ca0d125386a3a40805c8c57ff7382 /src/i965_hwmc.c
parent6b6be2b2a7179c1c9fa12989e16076aae105f4e2 (diff)
965 xvmc, current only frame based DCT_type support
Diffstat (limited to 'src/i965_hwmc.c')
-rw-r--r--src/i965_hwmc.c318
1 files changed, 318 insertions, 0 deletions
diff --git a/src/i965_hwmc.c b/src/i965_hwmc.c
new file mode 100644
index 00000000..8446c522
--- /dev/null
+++ b/src/i965_hwmc.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright © 2008 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.
+ *
+ * Author:
+ * Zou Nan hai <nanhai.zou@intel.com>
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/XvMC.h>
+#include <fourcc.h>
+#include <errno.h>
+
+#include "i830.h"
+#include "i830_dri.h"
+#define _INTEL_XVMC_SERVER_
+#include "i830_hwmc.h"
+#include "i965_hwmc.h"
+
+#define STRIDE(w) (w)
+#define SIZE_YUV420(w, h) (h * (STRIDE(w) + STRIDE(w >> 1)))
+
+static PutImageFuncPtr XvPutImage;
+
+static int alloc_drm_memory_tiled(ScrnInfoPtr pScrn,
+ struct drm_memory_block *mem,
+ char *name, size_t size, unsigned long pitch, unsigned long alignment)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ if ((mem->buffer = i830_allocate_memory_tiled(pScrn,
+ name, size, pitch,
+ GTT_PAGE_SIZE, ALIGN_BOTH_ENDS, TILE_XMAJOR)) == NULL) {
+ ErrorF("Fail to alloc \n");
+ return BadAlloc;
+ }
+
+ if (drmAddMap(pI830->drmSubFD,
+ (drm_handle_t)(mem->buffer->offset + pI830->LinearAddr),
+ size, DRM_AGP, 0,
+ (drmAddress)&mem->handle) < 0) {
+ ErrorF("Fail to map %d \n", errno);
+ i830_free_memory(pScrn, mem->buffer);
+ return BadAlloc;
+ }
+
+ mem->size = size;
+ mem->offset = mem->buffer->offset;
+ return Success;
+}
+static int alloc_drm_memory(ScrnInfoPtr pScrn,
+ struct drm_memory_block *mem,
+ char *name, size_t size)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ if ((mem->buffer = i830_allocate_memory(pScrn,
+ name, size,
+ GTT_PAGE_SIZE, ALIGN_BOTH_ENDS)) == NULL) {
+ ErrorF("Fail to alloc \n");
+ return BadAlloc;
+ }
+
+ if (drmAddMap(pI830->drmSubFD,
+ (drm_handle_t)(mem->buffer->offset + pI830->LinearAddr),
+ size, DRM_AGP, 0,
+ (drmAddress)&mem->handle) < 0) {
+ ErrorF("Fail to map %d \n", errno);
+ i830_free_memory(pScrn, mem->buffer);
+ return BadAlloc;
+ }
+
+ mem->size = size;
+ mem->offset = mem->buffer->offset;
+ return Success;
+}
+
+static void free_drm_memory(ScrnInfoPtr pScrn,
+ struct drm_memory_block *mem)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ drmRmMap(pI830->drmSubFD, mem->handle);
+ i830_free_memory(pScrn, mem->buffer);
+}
+
+static int create_context(ScrnInfoPtr pScrn,
+ XvMCContextPtr context, int *num_privates, CARD32 **private)
+{
+ struct i965_xvmc_context *private_context, *context_dup;
+ I830Ptr I830 = I830PTR(pScrn);
+ DRIInfoPtr driinfo = I830->pDRIInfo;
+
+ unsigned int blocknum =
+ (((context->width + 15)/16)*((context->height+15)/16));
+ unsigned int blocksize = 6*blocknum*64*sizeof(short);
+ blocksize = (blocksize + 4095)&(~4095);
+ if ((private_context = Xcalloc(sizeof(*private_context))) == NULL) {
+ ErrorF("XVMC Can not allocate private context\n");
+ return BadAlloc;
+ }
+
+ if ((context_dup = Xcalloc(sizeof(*private_context))) == NULL) {
+ ErrorF("XVMC Can not allocate private context\n");
+ return BadAlloc;
+ }
+
+ private_context->comm.type = xvmc_driver->flag;
+ private_context->comm.sarea_size = driinfo->SAREASize;
+ private_context->comm.batchbuffer.offset = xvmc_driver->batch->offset;
+ private_context->comm.batchbuffer.size = xvmc_driver->batch->size;
+ private_context->comm.batchbuffer.handle = xvmc_driver->batch_handle;
+
+ if (alloc_drm_memory(pScrn, &private_context->static_buffer,
+ "XVMC static buffers",
+ I965_MC_STATIC_BUFFER_SIZE)) {
+ ErrorF("Unable to allocate and map static buffer for XVMC\n");
+ return BadAlloc;
+ }
+
+ if (alloc_drm_memory(pScrn, &private_context->blocks,
+ "XVMC blocks", blocksize)) {
+ ErrorF("Unable to allocate and map block buffer for XVMC\n");
+ return BadAlloc;
+ }
+ *num_privates = sizeof(*private_context)/sizeof(CARD32);
+ *private = (CARD32 *)private_context;
+ memcpy(context_dup, private_context, sizeof(*private_context));
+ context->driver_priv = context_dup;
+
+ return Success;
+}
+
+static void destroy_context(ScrnInfoPtr pScrn, XvMCContextPtr context)
+{
+ struct i965_xvmc_context *private_context;
+ private_context = context->driver_priv;
+ free_drm_memory(pScrn, &private_context->static_buffer);
+ Xfree(private_context);
+}
+
+static int create_surface(ScrnInfoPtr pScrn, XvMCSurfacePtr surface,
+ int *num_priv, CARD32 **priv)
+{
+ XvMCContextPtr ctx = surface->context;
+ struct i965_xvmc_surface *priv_surface, *surface_dup;
+ struct i965_xvmc_context *priv_ctx = ctx->driver_priv;
+ size_t bufsize = SIZE_YUV420(ctx->width, ctx->height);
+ int i;
+ for (i = 0 ; i < I965_MAX_SURFACES; i++) {
+ if (priv_ctx->surfaces[i] == NULL) {
+ priv_surface = Xcalloc(sizeof(*priv_surface));
+ if (priv_surface == NULL)
+ return BadAlloc;
+ surface_dup = Xcalloc(sizeof(*priv_surface));
+ if (surface_dup == NULL)
+ return BadAlloc;
+
+ priv_surface->no = i;
+ priv_surface->handle = priv_surface;
+ priv_ctx->surfaces[i] = surface->driver_priv
+ = priv_surface;
+ if (alloc_drm_memory(pScrn, &priv_surface->buffer,
+ "surface buffer\n", (bufsize+0xFFF)&~(0xFFF))) {
+ ErrorF("Unable to allocate surface buffer\n");
+ return BadAlloc;
+ }
+ memcpy(surface_dup, priv_surface, sizeof(*priv_surface));
+ *num_priv = sizeof(*priv_surface)/sizeof(CARD32);
+ *priv = (CARD32 *)surface_dup;
+ break;
+ }
+ }
+
+ if (i >= I965_MAX_SURFACES) {
+ ErrorF("I965 XVMC too many surfaces in one context\n");
+ return BadAlloc;
+ }
+
+ return Success;
+}
+
+static void destory_surface(ScrnInfoPtr pScrn, XvMCSurfacePtr surface)
+{
+ XvMCContextPtr ctx = surface->context;
+ struct i965_xvmc_surface *priv_surface = surface->driver_priv;
+ struct i965_xvmc_context *priv_ctx = ctx->driver_priv;
+ priv_ctx->surfaces[priv_surface->no] = NULL;
+ free_drm_memory(pScrn, &priv_surface->buffer);
+ Xfree(priv_surface);
+}
+
+static int create_subpicture(ScrnInfoPtr pScrn, XvMCSubpicturePtr subpicture,
+ int *num_priv, CARD32 **priv)
+{
+ return Success;
+}
+
+static void destroy_subpicture(ScrnInfoPtr pScrn, XvMCSubpicturePtr subpicture)
+{
+}
+static int 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);
+ struct intel_xvmc_command *cmd = (struct intel_xvmc_command *)buf;
+ if (id == FOURCC_XVMC) {
+ buf = pI830->FbBase + cmd->surf_offset;
+ XvPutImage(pScrn, src_x, src_y, drw_x, drw_y, src_w, src_h,
+ drw_w, drw_h, FOURCC_I420, buf, width, height, sync, clipBoxes,
+ data, pDraw);
+ }else
+ XvPutImage(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);
+ return Success;
+}
+
+static Bool init(ScrnInfoPtr screen_info, XF86VideoAdaptorPtr adaptor)
+{
+ if (!intel_xvmc_init_batch(screen_info)) {
+ ErrorF("[XvMC] fail to init batch buffer\n");
+ return FALSE;
+ }
+ XvPutImage = adaptor->PutImage;
+ adaptor->PutImage = put_image;
+
+ return TRUE;
+}
+
+static void fini(ScrnInfoPtr screen_info)
+{
+}
+
+static XF86MCSurfaceInfoRec yv12_mpeg2_surface =
+{
+ FOURCC_YV12,
+ XVMC_CHROMA_FORMAT_420,
+ 0,
+ 1920,
+ 1080,
+ 1920,
+ 1080,
+ XVMC_MPEG_2|XVMC_MOCOMP,
+ /* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING,*/
+ XVMC_INTRA_UNSIGNED,
+ /* &yv12_subpicture_list*/
+ NULL
+};
+
+static XF86MCSurfaceInfoRec yv12_mpeg1_surface =
+{
+ FOURCC_YV12,
+ XVMC_CHROMA_FORMAT_420,
+ 0,
+ 1920,
+ 1080,
+ 1920,
+ 1080,
+ XVMC_MPEG_1|XVMC_MOCOMP,
+ /*XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
+ XVMC_INTRA_UNSIGNED,*/
+ XVMC_INTRA_UNSIGNED,
+
+ /*&yv12_subpicture_list*/
+ NULL
+};
+
+static XF86MCSurfaceInfoPtr surface_info[] = {
+ &yv12_mpeg2_surface,
+ &yv12_mpeg1_surface
+};
+
+static XF86MCAdaptorRec adaptor = {
+ .name = "Intel(R) Textured Video",
+ .num_surfaces = sizeof(surface_info)/sizeof(surface_info[0]),
+ .surfaces = surface_info,
+
+ .CreateContext = create_context,
+ .DestroyContext = destroy_context,
+ .CreateSurface = create_surface,
+ .DestroySurface = destory_surface,
+ .CreateSubpicture = create_subpicture,
+ .DestroySubpicture = destroy_subpicture
+};
+
+struct intel_xvmc_driver i965_xvmc_driver = {
+ .name = "i965_xvmc",
+ .adaptor = &adaptor,
+ .flag = XVMC_I965_MPEG2_MC,
+ .init = init,
+ .fini = fini
+};
+