1/* 2 * Copyright © 2007 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 * Authors: 24 * Zhenyu Wang <zhenyu.z.wang@sna.com> 25 * 26 */ 27#ifdef HAVE_CONFIG_H 28#include "config.h" 29#endif 30 31#define _SNA_XVMC_SERVER_ 32#include "sna.h" 33#include "sna_video_hwmc.h" 34 35#include <X11/extensions/Xv.h> 36#include <X11/extensions/XvMC.h> 37#include <fourcc.h> 38 39extern DevPrivateKey XF86XvScreenKey; 40 41static int create_subpicture(XvMCSubpicturePtr sub, int *size, CARD32 **priv) 42{ 43 return Success; 44} 45 46static void destroy_subpicture(XvMCSubpicturePtr sub) 47{ 48} 49 50static int create_surface(XvMCSurfacePtr surface, int *size, CARD32 **priv) 51{ 52 return Success; 53} 54 55static void destroy_surface(XvMCSurfacePtr surface) 56{ 57} 58 59static int create_context(XvPortPtr port, XvMCContextPtr ctx, 60 int *size, CARD32 **out) 61{ 62 struct sna *sna = to_sna_from_screen(ctx->pScreen); 63 struct intel_xvmc_hw_context { 64 unsigned int type; 65 union { 66 struct { 67 unsigned int use_phys_addr : 1; 68 } i915; 69 struct { 70 unsigned int is_g4x:1; 71 unsigned int is_965_q:1; 72 unsigned int is_igdng:1; 73 } i965; 74 }; 75 } *priv; 76 77 ctx->port_priv = port->devPriv.ptr; 78 79 priv = calloc(1, sizeof(*priv)); 80 if (priv == NULL) 81 return BadAlloc; 82 83 if (sna->kgem.gen >= 040) { 84 int devid = intel_get_device_id(sna->dev); 85 86 if (sna->kgem.gen >= 045) 87 priv->type = XVMC_I965_MPEG2_VLD; 88 else 89 priv->type = XVMC_I965_MPEG2_MC; 90 priv->i965.is_g4x = sna->kgem.gen == 045; 91 priv->i965.is_965_q = devid == PCI_CHIP_I965_Q; 92 priv->i965.is_igdng = sna->kgem.gen == 050; 93 } else 94 priv->type = XVMC_I915_MPEG2_MC; 95 96 *size = sizeof(*priv) >> 2; 97 *out = (CARD32 *)priv; 98 return Success; 99} 100 101static void destroy_context(XvMCContextPtr ctx) 102{ 103} 104 105/* i915 hwmc support */ 106static XvMCSurfaceInfoRec i915_YV12_mpg2_surface = { 107 FOURCC_YV12, 108 XVMC_CHROMA_FORMAT_420, 109 0, 110 720, 111 576, 112 720, 113 576, 114 XVMC_MPEG_2, 115 /* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING, */ 116 0, 117 /* &yv12_subpicture_list */ 118 NULL, 119}; 120 121static XvMCSurfaceInfoRec i915_YV12_mpg1_surface = { 122 FOURCC_YV12, 123 XVMC_CHROMA_FORMAT_420, 124 0, 125 720, 126 576, 127 720, 128 576, 129 XVMC_MPEG_1, 130 /* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING, */ 131 0, 132 NULL, 133}; 134 135static XvMCSurfaceInfoPtr surface_info_i915[2] = { 136 &i915_YV12_mpg2_surface, 137 &i915_YV12_mpg1_surface 138}; 139 140/* i965 and later hwmc support */ 141#ifndef XVMC_VLD 142#define XVMC_VLD 0x00020000 143#endif 144 145static XvMCSurfaceInfoRec yv12_mpeg2_vld_surface = { 146 FOURCC_YV12, 147 XVMC_CHROMA_FORMAT_420, 148 0, 149 1936, 150 1096, 151 1920, 152 1080, 153 XVMC_MPEG_2 | XVMC_VLD, 154 XVMC_INTRA_UNSIGNED, 155 NULL 156}; 157 158static XvMCSurfaceInfoRec yv12_mpeg2_i965_surface = { 159 FOURCC_YV12, 160 XVMC_CHROMA_FORMAT_420, 161 0, 162 1936, 163 1096, 164 1920, 165 1080, 166 XVMC_MPEG_2 | XVMC_MOCOMP, 167 /* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING, */ 168 XVMC_INTRA_UNSIGNED, 169 /* &yv12_subpicture_list */ 170 NULL 171}; 172 173static XvMCSurfaceInfoRec yv12_mpeg1_i965_surface = { 174 FOURCC_YV12, 175 XVMC_CHROMA_FORMAT_420, 176 0, 177 1920, 178 1080, 179 1920, 180 1080, 181 XVMC_MPEG_1 | XVMC_MOCOMP, 182 /*XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING | 183 XVMC_INTRA_UNSIGNED, */ 184 XVMC_INTRA_UNSIGNED, 185 186 /*&yv12_subpicture_list */ 187 NULL 188}; 189 190static XvMCSurfaceInfoPtr surface_info_i965[] = { 191 &yv12_mpeg2_i965_surface, 192 &yv12_mpeg1_i965_surface 193}; 194 195static XvMCSurfaceInfoPtr surface_info_vld[] = { 196 &yv12_mpeg2_vld_surface, 197 &yv12_mpeg2_i965_surface, 198}; 199 200/* check chip type and load xvmc driver */ 201void sna_video_xvmc_setup(struct sna *sna, ScreenPtr screen) 202{ 203 XvMCAdaptorRec *adaptors; 204 struct pci_device *pci; 205 const char *name; 206 char bus[64]; 207 int i; 208 209 pci = xf86GetPciInfoForEntity(sna->pEnt->index); 210 if (pci == NULL) 211 return; 212 213 if (!sna->xv.num_adaptors) 214 return; 215 216 if (!xf86LoaderCheckSymbol("XvMCScreenInit")) 217 return; 218 219 /* Needs KMS support. */ 220 if (sna->kgem.gen < 031) 221 return; 222 223 /* Not implemented */ 224 if (sna->kgem.gen >= 060) 225 return; 226 227 adaptors = calloc(sna->xv.num_adaptors, sizeof(XvMCAdaptorRec)); 228 if (adaptors == NULL) 229 return; 230 231 for (i = 0; i< sna->xv.num_adaptors; i++) { 232 adaptors[i].xv_adaptor = &sna->xv.adaptors[i]; 233 234 adaptors[i].num_subpictures = 0; 235 adaptors[i].subpictures = NULL; 236 adaptors[i].CreateContext = create_context; 237 adaptors[i].DestroyContext = destroy_context; 238 adaptors[i].CreateSurface = create_surface; 239 adaptors[i].DestroySurface = destroy_surface; 240 adaptors[i].CreateSubpicture = create_subpicture; 241 adaptors[i].DestroySubpicture = destroy_subpicture; 242 243 if (sna->kgem.gen >= 045) { 244 adaptors[i].num_surfaces = ARRAY_SIZE(surface_info_vld); 245 adaptors[i].surfaces = surface_info_vld; 246 } else if (sna->kgem.gen >= 040) { 247 adaptors[i].num_surfaces = ARRAY_SIZE(surface_info_i965); 248 adaptors[i].surfaces = surface_info_i965; 249 } else { 250 adaptors[i].num_surfaces = ARRAY_SIZE(surface_info_i915); 251 adaptors[i].surfaces = surface_info_i915; 252 } 253 } 254 255 if (XvMCScreenInit(screen, i, adaptors) != Success) { 256 xf86DrvMsg(sna->scrn->scrnIndex, X_INFO, 257 "[XvMC] Failed to initialize XvMC.\n"); 258 free(adaptors); 259 return; 260 } 261 262 sprintf(bus, "pci:%04x:%02x:%02x.%d", 263 pci->domain, pci->bus, pci->dev, pci->func); 264 265 xf86XvMCRegisterDRInfo(screen, (char *)SNA_XVMC_LIBNAME, bus, 266 SNA_XVMC_MAJOR, SNA_XVMC_MINOR, 267 SNA_XVMC_PATCHLEVEL); 268 269 if (sna->kgem.gen >= 045) 270 name = "xvmc_vld"; 271 else if (sna->kgem.gen >= 040) 272 name = "i965_xvmc"; 273 else 274 name = "i915_xvmc"; 275 xf86DrvMsg(sna->scrn->scrnIndex, X_INFO, 276 "[XvMC] %s driver initialized.\n", 277 name); 278} 279