1/* 2 * Copyright © 2008 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Author: 24 * Zou Nan hai <nanhai.zou@intel.com> 25 * 26 */ 27#ifdef HAVE_CONFIG_H 28#include "config.h" 29#endif 30 31#include <X11/extensions/Xv.h> 32#include <X11/extensions/XvMC.h> 33#include <fourcc.h> 34#include <errno.h> 35 36#include "i830.h" 37#include "i830_dri.h" 38#define _INTEL_XVMC_SERVER_ 39#include "i830_hwmc.h" 40#include "i965_hwmc.h" 41#include "intel_bufmgr.h" 42 43#define STRIDE(w) (w) 44#define SIZE_YUV420(w, h) (h * (STRIDE(w) + STRIDE(w >> 1))) 45#define VLD_MAX_SLICE_LEN (32*1024) 46 47#ifndef XVMC_VLD 48#define XVMC_VLD 0x00020000 49#endif 50 51static PutImageFuncPtr XvPutImage; 52 53 54static int create_context(ScrnInfoPtr pScrn, 55 XvMCContextPtr context, int *num_privates, CARD32 **private) 56{ 57 struct i965_xvmc_context *private_context, *context_dup; 58 I830Ptr I830 = I830PTR(pScrn); 59 60 unsigned int blocknum = 61 (((context->width + 15)/16)*((context->height+15)/16)); 62 unsigned int blocksize = 6*blocknum*64*sizeof(short); 63 blocksize = (blocksize + 4095)&(~4095); 64 if ((private_context = Xcalloc(sizeof(*private_context))) == NULL) { 65 ErrorF("XVMC Can not allocate private context\n"); 66 return BadAlloc; 67 } 68 69 if ((context_dup = Xcalloc(sizeof(*private_context))) == NULL) { 70 ErrorF("XVMC Can not allocate private context\n"); 71 return BadAlloc; 72 } 73 74 private_context->is_g4x = IS_G4X(I830); 75 private_context->is_965_q = IS_965_Q(I830); 76 private_context->is_igdng = IS_IGDNG(I830); 77 private_context->comm.kernel_exec_fencing = I830->kernel_exec_fencing; 78 private_context->comm.type = xvmc_driver->flag; 79 80 *num_privates = sizeof(*private_context)/sizeof(CARD32); 81 *private = (CARD32 *)private_context; 82 memcpy(context_dup, private_context, sizeof(*private_context)); 83 context->driver_priv = context_dup; 84 85 return Success; 86} 87 88static void destroy_context(ScrnInfoPtr pScrn, XvMCContextPtr context) 89{ 90 struct i965_xvmc_context *private_context; 91 private_context = context->driver_priv; 92 Xfree(private_context); 93} 94 95static int create_surface(ScrnInfoPtr pScrn, XvMCSurfacePtr surface, 96 int *num_priv, CARD32 **priv) 97{ 98 XvMCContextPtr ctx = surface->context; 99 100 struct i965_xvmc_surface *priv_surface, *surface_dup; 101 struct i965_xvmc_context *priv_ctx = ctx->driver_priv; 102 int i; 103 for (i = 0 ; i < I965_MAX_SURFACES; i++) { 104 if (priv_ctx->surfaces[i] == NULL) { 105 priv_surface = Xcalloc(sizeof(*priv_surface)); 106 if (priv_surface == NULL) 107 return BadAlloc; 108 surface_dup = Xcalloc(sizeof(*priv_surface)); 109 if (surface_dup == NULL) 110 return BadAlloc; 111 112 priv_surface->no = i; 113 priv_surface->handle = priv_surface; 114 priv_surface->w = ctx->width; 115 priv_surface->h = ctx->height; 116 priv_ctx->surfaces[i] = surface->driver_priv 117 = priv_surface; 118 memcpy(surface_dup, priv_surface, sizeof(*priv_surface)); 119 *num_priv = sizeof(*priv_surface)/sizeof(CARD32); 120 *priv = (CARD32 *)surface_dup; 121 break; 122 } 123 } 124 125 if (i >= I965_MAX_SURFACES) { 126 ErrorF("I965 XVMC too many surfaces in one context\n"); 127 return BadAlloc; 128 } 129 130 return Success; 131} 132 133static void destory_surface(ScrnInfoPtr pScrn, XvMCSurfacePtr surface) 134{ 135 XvMCContextPtr ctx = surface->context; 136 struct i965_xvmc_surface *priv_surface = surface->driver_priv; 137 struct i965_xvmc_context *priv_ctx = ctx->driver_priv; 138 priv_ctx->surfaces[priv_surface->no] = NULL; 139 Xfree(priv_surface); 140} 141 142static int create_subpicture(ScrnInfoPtr pScrn, XvMCSubpicturePtr subpicture, 143 int *num_priv, CARD32 **priv) 144{ 145 return Success; 146} 147 148static void destroy_subpicture(ScrnInfoPtr pScrn, XvMCSubpicturePtr subpicture) 149{ 150} 151 152static int put_image(ScrnInfoPtr pScrn, 153 short src_x, short src_y, 154 short drw_x, short drw_y, short src_w, 155 short src_h, short drw_w, short drw_h, 156 int id, unsigned char *buf, short width, 157 short height, Bool sync, RegionPtr clipBoxes, pointer data, 158 DrawablePtr pDraw) 159{ 160 I830Ptr pI830 = I830PTR(pScrn); 161 struct intel_xvmc_command *cmd = (struct intel_xvmc_command *)buf; 162 dri_bo *bo; 163 164 if (id == FOURCC_XVMC) { 165 bo = intel_bo_gem_create_from_name(pI830->bufmgr, "surface", cmd->handle); 166 dri_bo_pin(bo, 0x1000); 167 buf = pI830->FbBase + bo->offset; 168 } 169 XvPutImage(pScrn, src_x, src_y, drw_x, drw_y, src_w, src_h, 170 drw_w, drw_h, id, buf, width, height, sync, clipBoxes, 171 data, pDraw); 172 173 if (id == FOURCC_XVMC) { 174 dri_bo_unpin(bo); 175 dri_bo_unreference(bo); 176 } 177 178 return Success; 179} 180 181static Bool init(ScrnInfoPtr screen_info, XF86VideoAdaptorPtr adaptor) 182{ 183 XvPutImage = adaptor->PutImage; 184 adaptor->PutImage = put_image; 185 186 return TRUE; 187} 188 189static void fini(ScrnInfoPtr screen_info) 190{ 191} 192 193static XF86MCSurfaceInfoRec yv12_mpeg2_vld_surface = 194{ 195 FOURCC_YV12, 196 XVMC_CHROMA_FORMAT_420, 197 0, 198 1936, 199 1096, 200 1920, 201 1080, 202 XVMC_MPEG_2|XVMC_VLD, 203 XVMC_INTRA_UNSIGNED, 204 NULL 205}; 206 207static XF86MCSurfaceInfoRec yv12_mpeg2_surface = 208{ 209 FOURCC_YV12, 210 XVMC_CHROMA_FORMAT_420, 211 0, 212 1936, 213 1096, 214 1920, 215 1080, 216 XVMC_MPEG_2|XVMC_MOCOMP, 217 /* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING,*/ 218 XVMC_INTRA_UNSIGNED, 219 /* &yv12_subpicture_list*/ 220 NULL 221}; 222 223static XF86MCSurfaceInfoRec yv12_mpeg1_surface = 224{ 225 FOURCC_YV12, 226 XVMC_CHROMA_FORMAT_420, 227 0, 228 1920, 229 1080, 230 1920, 231 1080, 232 XVMC_MPEG_1|XVMC_MOCOMP, 233 /*XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING | 234 XVMC_INTRA_UNSIGNED,*/ 235 XVMC_INTRA_UNSIGNED, 236 237 /*&yv12_subpicture_list*/ 238 NULL 239}; 240 241static XF86MCSurfaceInfoPtr surface_info[] = { 242 &yv12_mpeg2_surface, 243 &yv12_mpeg1_surface 244}; 245 246static XF86MCSurfaceInfoPtr surface_info_vld[] = { 247 &yv12_mpeg2_vld_surface, 248 &yv12_mpeg2_surface, 249}; 250 251static XF86MCAdaptorRec adaptor_vld = { 252 .name = "Intel(R) Textured Video", 253 .num_surfaces = sizeof(surface_info_vld)/sizeof(surface_info_vld[0]), 254 .surfaces = surface_info_vld, 255 256 .CreateContext = create_context, 257 .DestroyContext = destroy_context, 258 .CreateSurface = create_surface, 259 .DestroySurface = destory_surface, 260 .CreateSubpicture = create_subpicture, 261 .DestroySubpicture = destroy_subpicture 262}; 263 264static XF86MCAdaptorRec adaptor = { 265 .name = "Intel(R) Textured Video", 266 .num_surfaces = sizeof(surface_info)/sizeof(surface_info[0]), 267 .surfaces = surface_info, 268 269 .CreateContext = create_context, 270 .DestroyContext = destroy_context, 271 .CreateSurface = create_surface, 272 .DestroySurface = destory_surface, 273 .CreateSubpicture = create_subpicture, 274 .DestroySubpicture = destroy_subpicture 275}; 276 277struct intel_xvmc_driver i965_xvmc_driver = { 278 .name = "i965_xvmc", 279 .adaptor = &adaptor, 280 .flag = XVMC_I965_MPEG2_MC, 281 .init = init, 282 .fini = fini 283}; 284 285struct intel_xvmc_driver vld_xvmc_driver = { 286 .name = "xvmc_vld", 287 .adaptor = &adaptor_vld, 288 .flag = XVMC_I965_MPEG2_VLD, 289 .init = init, 290 .fini = fini 291}; 292 293