sna_video_hwmc.c revision 03b705cf
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		if (sna->kgem.gen >= 045)
85			priv->type = XVMC_I965_MPEG2_VLD;
86		else
87			priv->type = XVMC_I965_MPEG2_MC;
88		priv->i965.is_g4x = sna->kgem.gen == 045;
89		priv->i965.is_965_q = sna->PciInfo->device_id == PCI_CHIP_I965_Q;
90		priv->i965.is_igdng = sna->kgem.gen == 050;
91	} else
92		priv->type = XVMC_I915_MPEG2_MC;
93
94	*size = sizeof(*priv) >> 2;
95	*out = (CARD32 *)priv;
96	return Success;
97}
98
99static void destroy_context(XvMCContextPtr ctx)
100{
101}
102
103/* i915 hwmc support */
104static XvMCSurfaceInfoRec i915_YV12_mpg2_surface = {
105	FOURCC_YV12,
106	XVMC_CHROMA_FORMAT_420,
107	0,
108	720,
109	576,
110	720,
111	576,
112	XVMC_MPEG_2,
113	/* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING, */
114	0,
115	/* &yv12_subpicture_list */
116	NULL,
117};
118
119static XvMCSurfaceInfoRec i915_YV12_mpg1_surface = {
120	FOURCC_YV12,
121	XVMC_CHROMA_FORMAT_420,
122	0,
123	720,
124	576,
125	720,
126	576,
127	XVMC_MPEG_1,
128	/* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING, */
129	0,
130	NULL,
131};
132
133static XvMCSurfaceInfoPtr surface_info_i915[2] = {
134	&i915_YV12_mpg2_surface,
135	&i915_YV12_mpg1_surface
136};
137
138/* i965 and later hwmc support */
139#ifndef XVMC_VLD
140#define XVMC_VLD  0x00020000
141#endif
142
143static XvMCSurfaceInfoRec yv12_mpeg2_vld_surface = {
144	FOURCC_YV12,
145	XVMC_CHROMA_FORMAT_420,
146	0,
147	1936,
148	1096,
149	1920,
150	1080,
151	XVMC_MPEG_2 | XVMC_VLD,
152	XVMC_INTRA_UNSIGNED,
153	NULL
154};
155
156static XvMCSurfaceInfoRec yv12_mpeg2_i965_surface = {
157	FOURCC_YV12,
158	XVMC_CHROMA_FORMAT_420,
159	0,
160	1936,
161	1096,
162	1920,
163	1080,
164	XVMC_MPEG_2 | XVMC_MOCOMP,
165	/* XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING, */
166	XVMC_INTRA_UNSIGNED,
167	/* &yv12_subpicture_list */
168	NULL
169};
170
171static XvMCSurfaceInfoRec yv12_mpeg1_i965_surface = {
172	FOURCC_YV12,
173	XVMC_CHROMA_FORMAT_420,
174	0,
175	1920,
176	1080,
177	1920,
178	1080,
179	XVMC_MPEG_1 | XVMC_MOCOMP,
180	/*XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
181	   XVMC_INTRA_UNSIGNED, */
182	XVMC_INTRA_UNSIGNED,
183
184	/*&yv12_subpicture_list */
185	NULL
186};
187
188static XvMCSurfaceInfoPtr surface_info_i965[] = {
189	&yv12_mpeg2_i965_surface,
190	&yv12_mpeg1_i965_surface
191};
192
193static XvMCSurfaceInfoPtr surface_info_vld[] = {
194	&yv12_mpeg2_vld_surface,
195	&yv12_mpeg2_i965_surface,
196};
197
198/* check chip type and load xvmc driver */
199void sna_video_xvmc_setup(struct sna *sna, ScreenPtr screen)
200{
201	XvMCAdaptorRec *adaptors;
202	const char *name;
203	char bus[64];
204	int i;
205
206	if (!sna->xv.num_adaptors)
207		return;
208
209	if (!xf86LoaderCheckSymbol("XvMCScreenInit"))
210		return;
211
212	/* Needs KMS support. */
213	if (sna->kgem.gen < 031)
214		return;
215
216	/* Not implemented */
217	if (sna->kgem.gen >= 060)
218		return;
219
220	adaptors = calloc(sna->xv.num_adaptors, sizeof(XvMCAdaptorRec));
221	if (adaptors == NULL)
222		return;
223
224	for (i = 0; i< sna->xv.num_adaptors; i++) {
225		adaptors[i].xv_adaptor = &sna->xv.adaptors[i];
226
227		adaptors[i].num_subpictures = 0;
228		adaptors[i].subpictures = NULL;
229		adaptors[i].CreateContext = create_context;
230		adaptors[i].DestroyContext = destroy_context;
231		adaptors[i].CreateSurface = create_surface;
232		adaptors[i].DestroySurface = destroy_surface;
233		adaptors[i].CreateSubpicture = create_subpicture;
234		adaptors[i].DestroySubpicture = destroy_subpicture;
235
236		if (sna->kgem.gen >= 045) {
237			adaptors[i].num_surfaces = ARRAY_SIZE(surface_info_vld);
238			adaptors[i].surfaces = surface_info_vld;
239		} else if (sna->kgem.gen >= 040) {
240			adaptors[i].num_surfaces = ARRAY_SIZE(surface_info_i965);
241			adaptors[i].surfaces = surface_info_i965;
242		} else {
243			adaptors[i].num_surfaces = ARRAY_SIZE(surface_info_i915);
244			adaptors[i].surfaces = surface_info_i915;
245		}
246	}
247
248	if (XvMCScreenInit(screen, i, adaptors) != Success) {
249		xf86DrvMsg(sna->scrn->scrnIndex, X_INFO,
250			   "[XvMC] Failed to initialize XvMC.\n");
251		free(adaptors);
252		return;
253	}
254
255	sprintf(bus, "pci:%04x:%02x:%02x.%d",
256		sna->PciInfo->domain,
257		sna->PciInfo->bus, sna->PciInfo->dev, sna->PciInfo->func);
258
259	xf86XvMCRegisterDRInfo(screen, (char *)SNA_XVMC_LIBNAME, bus,
260			       SNA_XVMC_MAJOR, SNA_XVMC_MINOR,
261			       SNA_XVMC_PATCHLEVEL);
262
263	if (sna->kgem.gen >= 045)
264		name = "xvmc_vld";
265	else if (sna->kgem.gen >= 040)
266		name = "i965_xvmc";
267	else
268		name = "i915_xvmc";
269	xf86DrvMsg(sna->scrn->scrnIndex, X_INFO,
270		   "[XvMC] %s driver initialized.\n",
271		   name);
272}
273