1428d7b3dSmrg/*
2428d7b3dSmrg * Copyright © 2007 Intel Corporation
3428d7b3dSmrg *
4428d7b3dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5428d7b3dSmrg * copy of this software and associated documentation files (the "Software"),
6428d7b3dSmrg * to deal in the Software without restriction, including without limitation
7428d7b3dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8428d7b3dSmrg * and/or sell copies of the Software, and to permit persons to whom the
9428d7b3dSmrg * Software is furnished to do so, subject to the following conditions:
10428d7b3dSmrg *
11428d7b3dSmrg * The above copyright notice and this permission notice (including the next
12428d7b3dSmrg * paragraph) shall be included in all copies or substantial portions of the
13428d7b3dSmrg * Software.
14428d7b3dSmrg *
15428d7b3dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16428d7b3dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17428d7b3dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18428d7b3dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19428d7b3dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20428d7b3dSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21428d7b3dSmrg * SOFTWARE.
22428d7b3dSmrg *
23428d7b3dSmrg * Authors:
24428d7b3dSmrg *    Zhenyu Wang <zhenyu.z.wang@intel.com>
25428d7b3dSmrg *
26428d7b3dSmrg */
27428d7b3dSmrg#include "intel_xvmc_private.h"
28428d7b3dSmrg#include <xcb/xcb.h>
29428d7b3dSmrg#include <xcb/xcb_aux.h>
30428d7b3dSmrg#include <xcb/dri2.h>
31428d7b3dSmrg#include <X11/Xlib-xcb.h>
32428d7b3dSmrg#include <X11/extensions/dri2tokens.h>
33428d7b3dSmrg
34428d7b3dSmrg/* global */
35428d7b3dSmrgstruct _intel_xvmc_driver *xvmc_driver = NULL;
36428d7b3dSmrg
37428d7b3dSmrg/* Lookup tables to speed common calculations for coded_block_pattern */
38428d7b3dSmrg/* each block is ((8*8) * sizeof(short)) */
39428d7b3dSmrgunsigned int mb_bytes_420[] = {
40428d7b3dSmrg	0,			/* 0 */
41428d7b3dSmrg	128,			/* 1 */
42428d7b3dSmrg	128,			/* 10 */
43428d7b3dSmrg	256,			/* 11 */
44428d7b3dSmrg	128,			/* 100 */
45428d7b3dSmrg	256,			/* 101 */
46428d7b3dSmrg	256,			/* 110 */
47428d7b3dSmrg	384,			/* 111 */
48428d7b3dSmrg	128,			/* 1000 */
49428d7b3dSmrg	256,			/* 1001 */
50428d7b3dSmrg	256,			/* 1010 */
51428d7b3dSmrg	384,			/* 1011 */
52428d7b3dSmrg	256,			/* 1100 */
53428d7b3dSmrg	384,			/* 1101 */
54428d7b3dSmrg	384,			/* 1110 */
55428d7b3dSmrg	512,			/* 1111 */
56428d7b3dSmrg	128,			/* 10000 */
57428d7b3dSmrg	256,			/* 10001 */
58428d7b3dSmrg	256,			/* 10010 */
59428d7b3dSmrg	384,			/* 10011 */
60428d7b3dSmrg	256,			/* 10100 */
61428d7b3dSmrg	384,			/* 10101 */
62428d7b3dSmrg	384,			/* 10110 */
63428d7b3dSmrg	512,			/* 10111 */
64428d7b3dSmrg	256,			/* 11000 */
65428d7b3dSmrg	384,			/* 11001 */
66428d7b3dSmrg	384,			/* 11010 */
67428d7b3dSmrg	512,			/* 11011 */
68428d7b3dSmrg	384,			/* 11100 */
69428d7b3dSmrg	512,			/* 11101 */
70428d7b3dSmrg	512,			/* 11110 */
71428d7b3dSmrg	640,			/* 11111 */
72428d7b3dSmrg	128,			/* 100000 */
73428d7b3dSmrg	256,			/* 100001 */
74428d7b3dSmrg	256,			/* 100010 */
75428d7b3dSmrg	384,			/* 100011 */
76428d7b3dSmrg	256,			/* 100100 */
77428d7b3dSmrg	384,			/* 100101 */
78428d7b3dSmrg	384,			/* 100110 */
79428d7b3dSmrg	512,			/* 100111 */
80428d7b3dSmrg	256,			/* 101000 */
81428d7b3dSmrg	384,			/* 101001 */
82428d7b3dSmrg	384,			/* 101010 */
83428d7b3dSmrg	512,			/* 101011 */
84428d7b3dSmrg	384,			/* 101100 */
85428d7b3dSmrg	512,			/* 101101 */
86428d7b3dSmrg	512,			/* 101110 */
87428d7b3dSmrg	640,			/* 101111 */
88428d7b3dSmrg	256,			/* 110000 */
89428d7b3dSmrg	384,			/* 110001 */
90428d7b3dSmrg	384,			/* 110010 */
91428d7b3dSmrg	512,			/* 110011 */
92428d7b3dSmrg	384,			/* 110100 */
93428d7b3dSmrg	512,			/* 110101 */
94428d7b3dSmrg	512,			/* 110110 */
95428d7b3dSmrg	640,			/* 110111 */
96428d7b3dSmrg	384,			/* 111000 */
97428d7b3dSmrg	512,			/* 111001 */
98428d7b3dSmrg	512,			/* 111010 */
99428d7b3dSmrg	640,			/* 111011 */
100428d7b3dSmrg	512,			/* 111100 */
101428d7b3dSmrg	640,			/* 111101 */
102428d7b3dSmrg	640,			/* 111110 */
103428d7b3dSmrg	768			/* 111111 */
104428d7b3dSmrg};
105428d7b3dSmrg
106428d7b3dSmrgstatic int
107428d7b3dSmrgdri2_connect(Display *display)
108428d7b3dSmrg{
109428d7b3dSmrg	xcb_dri2_query_version_cookie_t query_version_cookie;
110428d7b3dSmrg	xcb_dri2_query_version_reply_t *query_version_reply;
111428d7b3dSmrg	xcb_dri2_connect_cookie_t connect_cookie;
112428d7b3dSmrg	xcb_dri2_connect_reply_t *connect_reply;
113428d7b3dSmrg	xcb_dri2_authenticate_cookie_t auth_cookie;
114428d7b3dSmrg	xcb_dri2_authenticate_reply_t *auth_reply;
115428d7b3dSmrg	xcb_screen_t *root;
116428d7b3dSmrg	xcb_connection_t *c = XGetXCBConnection(display);
117428d7b3dSmrg	drm_magic_t magic;
118428d7b3dSmrg	const xcb_query_extension_reply_t *dri2_reply;
119428d7b3dSmrg	char *device_name;
120428d7b3dSmrg	int len;
121428d7b3dSmrg
122428d7b3dSmrg	root = xcb_aux_get_screen(c, DefaultScreen(display));
123428d7b3dSmrg
124428d7b3dSmrg	dri2_reply = xcb_get_extension_data(c, &xcb_dri2_id);
125428d7b3dSmrg
126428d7b3dSmrg	if (!dri2_reply) {
127428d7b3dSmrg		XVMC_ERR("DRI2 required");
128428d7b3dSmrg		return BadValue;
129428d7b3dSmrg	}
130428d7b3dSmrg
131428d7b3dSmrg	/* Query the extension and make our first use of it at the same time. */
132428d7b3dSmrg	query_version_cookie = xcb_dri2_query_version(c, 1, 0);
133428d7b3dSmrg	connect_cookie = xcb_dri2_connect(c, root->root, DRI2DriverDRI);
134428d7b3dSmrg
135428d7b3dSmrg	query_version_reply =
136428d7b3dSmrg		xcb_dri2_query_version_reply(c, query_version_cookie, NULL);
137428d7b3dSmrg	connect_reply = xcb_dri2_connect_reply(c, connect_cookie, NULL);
138428d7b3dSmrg
139428d7b3dSmrg	if (!query_version_reply) {
140428d7b3dSmrg		XVMC_ERR("DRI2 required");
141428d7b3dSmrg		return BadValue;
142428d7b3dSmrg	}
143428d7b3dSmrg	free(query_version_reply);
144428d7b3dSmrg
145428d7b3dSmrg	len = xcb_dri2_connect_device_name_length(connect_reply);
146428d7b3dSmrg	device_name = malloc(len + 1);
147428d7b3dSmrg	if (!device_name) {
148428d7b3dSmrg		XVMC_ERR("malloc failure");
149428d7b3dSmrg		return BadAlloc;
150428d7b3dSmrg	}
151428d7b3dSmrg	strncpy(device_name, xcb_dri2_connect_device_name(connect_reply), len);
152428d7b3dSmrg	device_name[len] = 0;
153428d7b3dSmrg	xvmc_driver->fd = open(device_name, O_RDWR);
154428d7b3dSmrg	free(device_name);
155428d7b3dSmrg	free(connect_reply);
156428d7b3dSmrg	if (xvmc_driver->fd < 0) {
157428d7b3dSmrg		XVMC_ERR("Failed to open drm device: %s\n", strerror(errno));
158428d7b3dSmrg		return BadValue;
159428d7b3dSmrg	}
160428d7b3dSmrg
161428d7b3dSmrg	if (drmGetMagic(xvmc_driver->fd, &magic)) {
162428d7b3dSmrg		XVMC_ERR("Failed to get magic\n");
163428d7b3dSmrg		return BadValue;
164428d7b3dSmrg	}
165428d7b3dSmrg
166428d7b3dSmrg	auth_cookie = xcb_dri2_authenticate(c, root->root, magic);
167428d7b3dSmrg	auth_reply = xcb_dri2_authenticate_reply(c, auth_cookie, NULL);
168428d7b3dSmrg	if (!auth_reply) {
169428d7b3dSmrg		XVMC_ERR("Failed to authenticate magic %d\n", magic);
170428d7b3dSmrg		return BadValue;
171428d7b3dSmrg	}
172428d7b3dSmrg	free(auth_reply);
173428d7b3dSmrg
174428d7b3dSmrg	return Success;
175428d7b3dSmrg}
176428d7b3dSmrg
177428d7b3dSmrg/*
178428d7b3dSmrg* Function: XvMCCreateContext
179428d7b3dSmrg* Description: Create a XvMC context for the given surface parameters.
180428d7b3dSmrg* Arguments:
181428d7b3dSmrg*   display - Connection to the X server.
182428d7b3dSmrg*   port - XvPortID to use as avertised by the X connection.
183428d7b3dSmrg*   surface_type_id - Unique identifier for the Surface type.
184428d7b3dSmrg*   width - Width of the surfaces.
185428d7b3dSmrg*   height - Height of the surfaces.
186428d7b3dSmrg*   flags - one or more of the following
187428d7b3dSmrg*      XVMC_DIRECT - A direct rendered context is requested.
188428d7b3dSmrg*
189428d7b3dSmrg* Notes: surface_type_id and width/height parameters must match those
190428d7b3dSmrg*        returned by XvMCListSurfaceTypes.
191428d7b3dSmrg* Returns: Status
192428d7b3dSmrg*/
193428d7b3dSmrg_X_EXPORT Status XvMCCreateContext(Display * display, XvPortID port,
194428d7b3dSmrg				   int surface_type_id, int width, int height,
195428d7b3dSmrg				   int flags, XvMCContext * context)
196428d7b3dSmrg{
197428d7b3dSmrg	Status ret;
198428d7b3dSmrg	CARD32 *priv_data = NULL;
199428d7b3dSmrg	struct intel_xvmc_hw_context *comm;
200428d7b3dSmrg	int major, minor;
201428d7b3dSmrg	int error_base;
202428d7b3dSmrg	int event_base;
203428d7b3dSmrg	int priv_count;
204428d7b3dSmrg
205428d7b3dSmrg	/* Verify Obvious things first */
206428d7b3dSmrg	if (!display || !context)
207428d7b3dSmrg		return BadValue;
208428d7b3dSmrg
209428d7b3dSmrg	if (!(flags & XVMC_DIRECT)) {
210428d7b3dSmrg		XVMC_ERR("Indirect Rendering not supported! Using Direct.");
211428d7b3dSmrg		return BadValue;
212428d7b3dSmrg	}
213428d7b3dSmrg
214428d7b3dSmrg	/*
215428d7b3dSmrg	   Width, Height, and flags are checked against surface_type_id
216428d7b3dSmrg	   and port for validity inside the X server, no need to check
217428d7b3dSmrg	   here.
218428d7b3dSmrg	 */
219428d7b3dSmrg	context->surface_type_id = surface_type_id;
220428d7b3dSmrg	context->width = (unsigned short)((width + 15) & ~15);
221428d7b3dSmrg	context->height = (unsigned short)((height + 15) & ~15);
222428d7b3dSmrg	context->flags = flags;
223428d7b3dSmrg	context->port = port;
224428d7b3dSmrg
225428d7b3dSmrg	if (!XvMCQueryExtension(display, &event_base, &error_base)) {
226428d7b3dSmrg		XVMC_ERR("XvMCExtension is not available!");
227428d7b3dSmrg		return BadValue;
228428d7b3dSmrg	}
229428d7b3dSmrg
230428d7b3dSmrg	ret = XvMCQueryVersion(display, &major, &minor);
231428d7b3dSmrg	if (ret) {
232428d7b3dSmrg		XVMC_ERR
233428d7b3dSmrg		    ("XvMCQueryVersion Failed, unable to determine protocol version.");
234428d7b3dSmrg		return ret;
235428d7b3dSmrg	}
236428d7b3dSmrg
237428d7b3dSmrg	/* XXX: major and minor could be checked in future for XvMC
238428d7b3dSmrg	 * protocol capability (i.e H.264/AVC decode available)
239428d7b3dSmrg	 */
240428d7b3dSmrg
241428d7b3dSmrg	/*
242428d7b3dSmrg	   Pass control to the X server to create a drm_context_t for us and
243428d7b3dSmrg	   validate the with/height and flags.
244428d7b3dSmrg	 */
245428d7b3dSmrg	if ((ret =
246428d7b3dSmrg	     _xvmc_create_context(display, context, &priv_count, &priv_data))) {
247428d7b3dSmrg		XVMC_ERR("Unable to create XvMC Context.");
248428d7b3dSmrg		return ret;
249428d7b3dSmrg	}
250428d7b3dSmrg
251428d7b3dSmrg	comm = (struct intel_xvmc_hw_context *)priv_data;
252428d7b3dSmrg
253428d7b3dSmrg	if (xvmc_driver == NULL || xvmc_driver->type != comm->type) {
254428d7b3dSmrg		switch (comm->type) {
255428d7b3dSmrg		case XVMC_I915_MPEG2_MC:
256428d7b3dSmrg			xvmc_driver = &i915_xvmc_mc_driver;
257428d7b3dSmrg			break;
258428d7b3dSmrg		case XVMC_I965_MPEG2_MC:
259428d7b3dSmrg			xvmc_driver = &i965_xvmc_mc_driver;
260428d7b3dSmrg			break;
261428d7b3dSmrg		case XVMC_I965_MPEG2_VLD:
262428d7b3dSmrg			xvmc_driver = &xvmc_vld_driver;
263428d7b3dSmrg			break;
264428d7b3dSmrg		case XVMC_I945_MPEG2_VLD:
265428d7b3dSmrg		default:
266428d7b3dSmrg			XVMC_ERR("unimplemented xvmc type %d", comm->type);
267428d7b3dSmrg			XFree(priv_data);
268428d7b3dSmrg			priv_data = NULL;
269428d7b3dSmrg			return BadValue;
270428d7b3dSmrg		}
271428d7b3dSmrg	}
272428d7b3dSmrg
273428d7b3dSmrg	if (xvmc_driver == NULL || xvmc_driver->type != comm->type) {
274428d7b3dSmrg		XVMC_ERR("fail to load xvmc driver for type %d\n", comm->type);
275428d7b3dSmrg		return BadValue;
276428d7b3dSmrg	}
277428d7b3dSmrg
278428d7b3dSmrg	XVMC_INFO("decoder type is %s", intel_xvmc_decoder_string(comm->type));
279428d7b3dSmrg
280428d7b3dSmrg	/* check DRI2 */
281428d7b3dSmrg	ret = Success;
282428d7b3dSmrg	xvmc_driver->fd = -1;
283428d7b3dSmrg
284428d7b3dSmrg	ret = dri2_connect(display);
285428d7b3dSmrg	if (ret != Success) {
286428d7b3dSmrg		XFree(priv_data);
287428d7b3dSmrg		context->privData = NULL;
288428d7b3dSmrg		if (xvmc_driver->fd >= 0)
289428d7b3dSmrg			close(xvmc_driver->fd);
290428d7b3dSmrg		xvmc_driver = NULL;
291428d7b3dSmrg		return ret;
292428d7b3dSmrg	}
293428d7b3dSmrg
294428d7b3dSmrg	if ((xvmc_driver->bufmgr =
295428d7b3dSmrg	     intel_bufmgr_gem_init(xvmc_driver->fd, 1024 * 64)) == NULL) {
296428d7b3dSmrg		XVMC_ERR("Can't init bufmgr\n");
297428d7b3dSmrg		return BadAlloc;
298428d7b3dSmrg	}
299428d7b3dSmrg	drm_intel_bufmgr_gem_enable_reuse(xvmc_driver->bufmgr);
300428d7b3dSmrg
301428d7b3dSmrg	if (!intelInitBatchBuffer()) {
302428d7b3dSmrg		XFree(priv_data);
303428d7b3dSmrg		context->privData = NULL;
304428d7b3dSmrg
305428d7b3dSmrg		dri_bufmgr_destroy(xvmc_driver->bufmgr);
306428d7b3dSmrg		xvmc_driver = NULL;
307428d7b3dSmrg
308428d7b3dSmrg		return BadAlloc;
309428d7b3dSmrg	}
310428d7b3dSmrg
311428d7b3dSmrg	/* call driver hook.
312428d7b3dSmrg	 * driver hook should free priv_data after return if success.*/
313428d7b3dSmrg	ret =
314428d7b3dSmrg	    (xvmc_driver->create_context) (display, context, priv_count,
315428d7b3dSmrg					   priv_data);
316428d7b3dSmrg	if (ret) {
317428d7b3dSmrg		XVMC_ERR("driver create context failed\n");
318428d7b3dSmrg		intelFiniBatchBuffer();
319428d7b3dSmrg
320428d7b3dSmrg		XFree(priv_data);
321428d7b3dSmrg		context->privData = NULL;
322428d7b3dSmrg
323428d7b3dSmrg		dri_bufmgr_destroy(xvmc_driver->bufmgr);
324428d7b3dSmrg		xvmc_driver = NULL;
325428d7b3dSmrg		return ret;
326428d7b3dSmrg	}
327428d7b3dSmrg
328428d7b3dSmrg	sigfillset(&xvmc_driver->sa_mask);
329428d7b3dSmrg	sigdelset(&xvmc_driver->sa_mask, SIGFPE);
330428d7b3dSmrg	sigdelset(&xvmc_driver->sa_mask, SIGILL);
331428d7b3dSmrg	sigdelset(&xvmc_driver->sa_mask, SIGSEGV);
332428d7b3dSmrg	sigdelset(&xvmc_driver->sa_mask, SIGBUS);
333428d7b3dSmrg	sigdelset(&xvmc_driver->sa_mask, SIGKILL);
334428d7b3dSmrg	pthread_mutex_init(&xvmc_driver->ctxmutex, NULL);
335428d7b3dSmrg
336428d7b3dSmrg	intel_xvmc_dump_open();
337428d7b3dSmrg
338428d7b3dSmrg	return Success;
339428d7b3dSmrg}
340428d7b3dSmrg
341428d7b3dSmrg/*
342428d7b3dSmrg * Function: XvMCDestroyContext
343428d7b3dSmrg * Description: Destorys the specified context.
344428d7b3dSmrg *
345428d7b3dSmrg * Arguments:
346428d7b3dSmrg *   display - Specifies the connection to the server.
347428d7b3dSmrg *   context - The context to be destroyed.
348428d7b3dSmrg *
349428d7b3dSmrg */
350428d7b3dSmrg_X_EXPORT Status XvMCDestroyContext(Display * display, XvMCContext * context)
351428d7b3dSmrg{
352428d7b3dSmrg	Status ret;
353428d7b3dSmrg	int screen;
354428d7b3dSmrg
355428d7b3dSmrg	if (!display || !context)
356428d7b3dSmrg		return XvMCBadContext;
357428d7b3dSmrg	screen = DefaultScreen(display);
358428d7b3dSmrg	ret = (xvmc_driver->destroy_context) (display, context);
359428d7b3dSmrg	if (ret) {
360428d7b3dSmrg		XVMC_ERR("destroy context fail\n");
361428d7b3dSmrg		return ret;
362428d7b3dSmrg	}
363428d7b3dSmrg
364428d7b3dSmrg	intelFiniBatchBuffer();
365428d7b3dSmrg
366428d7b3dSmrg	dri_bufmgr_destroy(xvmc_driver->bufmgr);
367428d7b3dSmrg
368428d7b3dSmrg	ret = _xvmc_destroy_context(display, context);
369428d7b3dSmrg	if (ret != Success) {
370428d7b3dSmrg		XVMC_ERR("_xvmc_destroy_context fail\n");
371428d7b3dSmrg		return ret;
372428d7b3dSmrg	}
373428d7b3dSmrg
374428d7b3dSmrg	if (xvmc_driver->num_ctx == 0) {
375428d7b3dSmrg		pthread_mutex_destroy(&xvmc_driver->ctxmutex);
376428d7b3dSmrg
377428d7b3dSmrg		if (xvmc_driver->fd >= 0)
378428d7b3dSmrg			close(xvmc_driver->fd);
379428d7b3dSmrg
380428d7b3dSmrg		xvmc_driver->fd = -1;
381428d7b3dSmrg		intel_xvmc_dump_close();
382428d7b3dSmrg	}
383428d7b3dSmrg	return Success;
384428d7b3dSmrg}
385428d7b3dSmrg
386428d7b3dSmrg/*
387428d7b3dSmrg * Function: XvMCCreateSurface
388428d7b3dSmrg */
389428d7b3dSmrg_X_EXPORT Status XvMCCreateSurface(Display * display, XvMCContext * context,
390428d7b3dSmrg				   XvMCSurface * surface)
391428d7b3dSmrg{
392428d7b3dSmrg	Status ret;
393428d7b3dSmrg	int priv_count;
394428d7b3dSmrg	CARD32 *priv_data;
395428d7b3dSmrg	intel_xvmc_surface_ptr intel_surf = NULL;
396428d7b3dSmrg	struct intel_xvmc_context *intel_ctx;
397428d7b3dSmrg
398428d7b3dSmrg	if (!display || !context)
399428d7b3dSmrg		return XvMCBadContext;
400428d7b3dSmrg
401428d7b3dSmrg	if (!surface)
402428d7b3dSmrg		return XvMCBadSurface;
403428d7b3dSmrg
404428d7b3dSmrg	intel_ctx = context->privData;
405428d7b3dSmrg
406428d7b3dSmrg	if ((ret = _xvmc_create_surface(display, context, surface,
407428d7b3dSmrg					&priv_count, &priv_data))) {
408428d7b3dSmrg		XVMC_ERR("Unable to create XvMCSurface.");
409428d7b3dSmrg		return ret;
410428d7b3dSmrg	}
411428d7b3dSmrg
412428d7b3dSmrg	XFree(priv_data);
413428d7b3dSmrg
414428d7b3dSmrg	surface->privData = calloc(1, sizeof(struct intel_xvmc_surface));
415428d7b3dSmrg
416428d7b3dSmrg	if (!(intel_surf = surface->privData))
417428d7b3dSmrg		goto out_xvmc;
418428d7b3dSmrg
419428d7b3dSmrg	intel_surf->bo = drm_intel_bo_alloc(xvmc_driver->bufmgr,
420428d7b3dSmrg					      "surface",
421428d7b3dSmrg					      intel_ctx->surface_bo_size,
422428d7b3dSmrg					      GTT_PAGE_SIZE);
423428d7b3dSmrg	if (!intel_surf->bo)
424428d7b3dSmrg		goto out_surf;
425428d7b3dSmrg
426428d7b3dSmrg	if (drm_intel_bo_flink(intel_surf->bo, &intel_surf->gem_handle))
427428d7b3dSmrg		goto out_bo;
428428d7b3dSmrg
429428d7b3dSmrg	intel_surf = surface->privData;
430428d7b3dSmrg	intel_surf->context = context;
431428d7b3dSmrg
432428d7b3dSmrg	intel_surf->image = XvCreateImage(display, context->port,
433428d7b3dSmrg					  FOURCC_XVMC,
434428d7b3dSmrg					  (char *) &intel_surf->gem_handle,
435428d7b3dSmrg					  surface->width, surface->height);
436428d7b3dSmrg	if (!intel_surf->image) {
437428d7b3dSmrg		XVMC_ERR("Can't create XvImage for surface\n");
438428d7b3dSmrg		goto out_bo;
439428d7b3dSmrg	}
440428d7b3dSmrg
441428d7b3dSmrg	return Success;
442428d7b3dSmrg
443428d7b3dSmrgout_bo:
444428d7b3dSmrg	drm_intel_bo_unreference(intel_surf->bo);
445428d7b3dSmrgout_surf:
446428d7b3dSmrg	free(intel_surf);
447428d7b3dSmrgout_xvmc:
448428d7b3dSmrg	_xvmc_destroy_surface(display, surface);
449428d7b3dSmrg	return BadAlloc;
450428d7b3dSmrg}
451428d7b3dSmrg
452428d7b3dSmrg/*
453428d7b3dSmrg * Function: XvMCDestroySurface
454428d7b3dSmrg */
455428d7b3dSmrg_X_EXPORT Status XvMCDestroySurface(Display * display, XvMCSurface * surface)
456428d7b3dSmrg{
457428d7b3dSmrg	intel_xvmc_surface_ptr intel_surf;
458428d7b3dSmrg
459428d7b3dSmrg	if (!display || !surface)
460428d7b3dSmrg		return XvMCBadSurface;
461428d7b3dSmrg
462428d7b3dSmrg	intel_surf = surface->privData;
463428d7b3dSmrg	if (!intel_surf)
464428d7b3dSmrg		return XvMCBadSurface;
465428d7b3dSmrg
466428d7b3dSmrg	XFree(intel_surf->image);
467428d7b3dSmrg	if (intel_surf->gc_init)
468428d7b3dSmrg		XFreeGC(display, intel_surf->gc);
469428d7b3dSmrg
470428d7b3dSmrg	drm_intel_bo_unreference(intel_surf->bo);
471428d7b3dSmrg
472428d7b3dSmrg	free(intel_surf);
473428d7b3dSmrg
474428d7b3dSmrg	_xvmc_destroy_surface(display, surface);
475428d7b3dSmrg
476428d7b3dSmrg	return Success;
477428d7b3dSmrg}
478428d7b3dSmrg
479428d7b3dSmrg/*
480428d7b3dSmrg * Function: XvMCCreateBlocks
481428d7b3dSmrg */
482428d7b3dSmrg_X_EXPORT Status XvMCCreateBlocks(Display * display, XvMCContext * context,
483428d7b3dSmrg				  unsigned int num_blocks,
484428d7b3dSmrg				  XvMCBlockArray * block)
485428d7b3dSmrg{
486428d7b3dSmrg	if (!display || !context || !num_blocks || !block)
487428d7b3dSmrg		return BadValue;
488428d7b3dSmrg
489428d7b3dSmrg	memset(block, 0, sizeof(XvMCBlockArray));
490428d7b3dSmrg
491428d7b3dSmrg	if (!
492428d7b3dSmrg	    (block->blocks =
493428d7b3dSmrg	     (short *)malloc((num_blocks << 6) * sizeof(short))))
494428d7b3dSmrg		return BadAlloc;
495428d7b3dSmrg
496428d7b3dSmrg	block->num_blocks = num_blocks;
497428d7b3dSmrg	block->context_id = context->context_id;
498428d7b3dSmrg	block->privData = NULL;
499428d7b3dSmrg
500428d7b3dSmrg	return Success;
501428d7b3dSmrg}
502428d7b3dSmrg
503428d7b3dSmrg/*
504428d7b3dSmrg * Function: XvMCDestroyBlocks
505428d7b3dSmrg */
506428d7b3dSmrg_X_EXPORT Status XvMCDestroyBlocks(Display * display, XvMCBlockArray * block)
507428d7b3dSmrg{
508428d7b3dSmrg	if (!display || !block)
509428d7b3dSmrg		return BadValue;
510428d7b3dSmrg
511428d7b3dSmrg	if (block->blocks)
512428d7b3dSmrg		free(block->blocks);
513428d7b3dSmrg
514428d7b3dSmrg	block->context_id = 0;
515428d7b3dSmrg	block->num_blocks = 0;
516428d7b3dSmrg	block->blocks = NULL;
517428d7b3dSmrg	block->privData = NULL;
518428d7b3dSmrg
519428d7b3dSmrg	return Success;
520428d7b3dSmrg}
521428d7b3dSmrg
522428d7b3dSmrg/*
523428d7b3dSmrg * Function: XvMCCreateMacroBlocks
524428d7b3dSmrg */
525428d7b3dSmrg_X_EXPORT Status XvMCCreateMacroBlocks(Display * display, XvMCContext * context,
526428d7b3dSmrg				       unsigned int num_blocks,
527428d7b3dSmrg				       XvMCMacroBlockArray * blocks)
528428d7b3dSmrg{
529428d7b3dSmrg	if (!display || !context || !blocks || !num_blocks)
530428d7b3dSmrg		return BadValue;
531428d7b3dSmrg
532428d7b3dSmrg	memset(blocks, 0, sizeof(XvMCMacroBlockArray));
533428d7b3dSmrg	blocks->macro_blocks =
534428d7b3dSmrg	    (XvMCMacroBlock *) malloc(num_blocks * sizeof(XvMCMacroBlock));
535428d7b3dSmrg
536428d7b3dSmrg	if (!blocks->macro_blocks)
537428d7b3dSmrg		return BadAlloc;
538428d7b3dSmrg
539428d7b3dSmrg	blocks->num_blocks = num_blocks;
540428d7b3dSmrg	blocks->context_id = context->context_id;
541428d7b3dSmrg	blocks->privData = NULL;
542428d7b3dSmrg
543428d7b3dSmrg	return Success;
544428d7b3dSmrg}
545428d7b3dSmrg
546428d7b3dSmrg/*
547428d7b3dSmrg * Function: XvMCDestroyMacroBlocks
548428d7b3dSmrg */
549428d7b3dSmrg_X_EXPORT Status XvMCDestroyMacroBlocks(Display * display,
550428d7b3dSmrg					XvMCMacroBlockArray * block)
551428d7b3dSmrg{
552428d7b3dSmrg	if (!display || !block)
553428d7b3dSmrg		return BadValue;
554428d7b3dSmrg	if (block->macro_blocks)
555428d7b3dSmrg		free(block->macro_blocks);
556428d7b3dSmrg
557428d7b3dSmrg	block->context_id = 0;
558428d7b3dSmrg	block->num_blocks = 0;
559428d7b3dSmrg	block->macro_blocks = NULL;
560428d7b3dSmrg	block->privData = NULL;
561428d7b3dSmrg
562428d7b3dSmrg	return Success;
563428d7b3dSmrg}
564428d7b3dSmrg
565428d7b3dSmrg/*
566428d7b3dSmrg * Function: XvMCRenderSurface
567428d7b3dSmrg *
568428d7b3dSmrg * Description: This function does the actual HWMC. Given a list of
569428d7b3dSmrg *  macroblock structures it dispatched the hardware commands to execute
570428d7b3dSmrg *  them.
571428d7b3dSmrg */
572428d7b3dSmrg_X_EXPORT Status XvMCRenderSurface(Display * display, XvMCContext * context,
573428d7b3dSmrg				   unsigned int picture_structure,
574428d7b3dSmrg				   XvMCSurface * target_surface,
575428d7b3dSmrg				   XvMCSurface * past_surface,
576428d7b3dSmrg				   XvMCSurface * future_surface,
577428d7b3dSmrg				   unsigned int flags,
578428d7b3dSmrg				   unsigned int num_macroblocks,
579428d7b3dSmrg				   unsigned int first_macroblock,
580428d7b3dSmrg				   XvMCMacroBlockArray * macroblock_array,
581428d7b3dSmrg				   XvMCBlockArray * blocks)
582428d7b3dSmrg{
583428d7b3dSmrg	Status ret;
584428d7b3dSmrg
585428d7b3dSmrg	if (!display || !context) {
586428d7b3dSmrg		XVMC_ERR("Invalid Display, Context or Target!");
587428d7b3dSmrg		return XvMCBadContext;
588428d7b3dSmrg	}
589428d7b3dSmrg	if (!target_surface)
590428d7b3dSmrg		return XvMCBadSurface;
591428d7b3dSmrg
592428d7b3dSmrg	intel_xvmc_dump_render(context, picture_structure, target_surface,
593428d7b3dSmrg			       past_surface, future_surface, flags,
594428d7b3dSmrg			       num_macroblocks, first_macroblock,
595428d7b3dSmrg			       macroblock_array, blocks);
596428d7b3dSmrg
597428d7b3dSmrg	ret =
598428d7b3dSmrg	    (xvmc_driver->render_surface) (display, context, picture_structure,
599428d7b3dSmrg					   target_surface, past_surface,
600428d7b3dSmrg					   future_surface, flags,
601428d7b3dSmrg					   num_macroblocks, first_macroblock,
602428d7b3dSmrg					   macroblock_array, blocks);
603428d7b3dSmrg
604428d7b3dSmrg	if (ret) {
605428d7b3dSmrg		XVMC_ERR("render surface fail\n");
606428d7b3dSmrg		return ret;
607428d7b3dSmrg	}
608428d7b3dSmrg	return Success;
609428d7b3dSmrg}
610428d7b3dSmrg
611428d7b3dSmrg/*
612428d7b3dSmrg * Function: XvMCPutSurface
613428d7b3dSmrg *
614428d7b3dSmrg * Description:
615428d7b3dSmrg * Arguments:
616428d7b3dSmrg *  display: Connection to X server
617428d7b3dSmrg *  surface: Surface to be displayed
618428d7b3dSmrg *  draw: X Drawable on which to display the surface
619428d7b3dSmrg *  srcx: X coordinate of the top left corner of the region to be
620428d7b3dSmrg *          displayed within the surface.
621428d7b3dSmrg *  srcy: Y coordinate of the top left corner of the region to be
622428d7b3dSmrg *          displayed within the surface.
623428d7b3dSmrg *  srcw: Width of the region to be displayed.
624428d7b3dSmrg *  srch: Height of the region to be displayed.
625428d7b3dSmrg *  destx: X cordinate of the top left corner of the destination region
626428d7b3dSmrg *         in the drawable coordinates.
627428d7b3dSmrg *  desty: Y cordinate of the top left corner of the destination region
628428d7b3dSmrg *         in the drawable coordinates.
629428d7b3dSmrg *  destw: Width of the destination region.
630428d7b3dSmrg *  desth: Height of the destination region.
631428d7b3dSmrg *  flags: One or more of the following.
632428d7b3dSmrg *	XVMC_TOP_FIELD - Display only the Top field of the surface.
633428d7b3dSmrg *	XVMC_BOTTOM_FIELD - Display only the Bottom Field of the surface.
634428d7b3dSmrg *	XVMC_FRAME_PICTURE - Display both fields or frame.
635428d7b3dSmrg */
636428d7b3dSmrg_X_EXPORT Status XvMCPutSurface(Display * display, XvMCSurface * surface,
637428d7b3dSmrg				Drawable draw, short srcx, short srcy,
638428d7b3dSmrg				unsigned short srcw, unsigned short srch,
639428d7b3dSmrg				short destx, short desty,
640428d7b3dSmrg				unsigned short destw, unsigned short desth,
641428d7b3dSmrg				int flags)
642428d7b3dSmrg{
643428d7b3dSmrg	XvMCContext *context;
644428d7b3dSmrg	intel_xvmc_surface_ptr intel_surf;
645428d7b3dSmrg
646428d7b3dSmrg	if (!display || !surface)
647428d7b3dSmrg		return XvMCBadSurface;
648428d7b3dSmrg
649428d7b3dSmrg	intel_surf = surface->privData;
650428d7b3dSmrg	if (!intel_surf)
651428d7b3dSmrg		return XvMCBadSurface;
652428d7b3dSmrg
653428d7b3dSmrg	context = intel_surf->context;
654428d7b3dSmrg	if (!context)
655428d7b3dSmrg		return XvMCBadSurface;
656428d7b3dSmrg
657428d7b3dSmrg	if (intel_surf->gc_init == FALSE) {
658428d7b3dSmrg		intel_surf->gc = XCreateGC(display, draw, 0, NULL);
659428d7b3dSmrg		intel_surf->gc_init = TRUE;
660428d7b3dSmrg	} else if (draw != intel_surf->last_draw) {
661428d7b3dSmrg		XFreeGC(display, intel_surf->gc);
662428d7b3dSmrg		intel_surf->gc = XCreateGC(display, draw, 0, NULL);
663428d7b3dSmrg	}
664428d7b3dSmrg	intel_surf->last_draw = draw;
665428d7b3dSmrg
666428d7b3dSmrg	return XvPutImage(display, context->port, draw, intel_surf->gc,
667428d7b3dSmrg			  intel_surf->image, srcx, srcy, srcw, srch, destx,
668428d7b3dSmrg			  desty, destw, desth);
669428d7b3dSmrg}
670428d7b3dSmrg
671428d7b3dSmrg/*
672428d7b3dSmrg * Function: XvMCSyncSurface
673428d7b3dSmrg * Arguments:
674428d7b3dSmrg *   display - Connection to the X server
675428d7b3dSmrg *   surface - The surface to synchronize
676428d7b3dSmrg */
677428d7b3dSmrg_X_EXPORT Status XvMCSyncSurface(Display * display, XvMCSurface * surface)
678428d7b3dSmrg{
679428d7b3dSmrg	if (!display || !surface)
680428d7b3dSmrg		return XvMCBadSurface;
681428d7b3dSmrg
682428d7b3dSmrg	return Success;
683428d7b3dSmrg}
684428d7b3dSmrg
685428d7b3dSmrg/*
686428d7b3dSmrg * Function: XvMCFlushSurface
687428d7b3dSmrg * Description:
688428d7b3dSmrg *   This function commits pending rendering requests to ensure that they
689428d7b3dSmrg *   wll be completed in a finite amount of time.
690428d7b3dSmrg * Arguments:
691428d7b3dSmrg *   display - Connection to X server
692428d7b3dSmrg *   surface - Surface to flush
693428d7b3dSmrg * Returns: Status
694428d7b3dSmrg */
695428d7b3dSmrg_X_EXPORT Status XvMCFlushSurface(Display * display, XvMCSurface * surface)
696428d7b3dSmrg{
697428d7b3dSmrg	if (!display || !surface)
698428d7b3dSmrg		return XvMCBadSurface;
699428d7b3dSmrg
700428d7b3dSmrg	return Success;
701428d7b3dSmrg}
702428d7b3dSmrg
703428d7b3dSmrg/*
704428d7b3dSmrg * Function: XvMCGetSurfaceStatus
705428d7b3dSmrg * Description:
706428d7b3dSmrg * Arguments:
707428d7b3dSmrg *  display: connection to X server
708428d7b3dSmrg *  surface: The surface to query
709428d7b3dSmrg *  stat: One of the Following
710428d7b3dSmrg *    XVMC_RENDERING - The last XvMCRenderSurface command has not
711428d7b3dSmrg *                     completed.
712428d7b3dSmrg *    XVMC_DISPLAYING - The surface is currently being displayed or a
713428d7b3dSmrg *                     display is pending.
714428d7b3dSmrg */
715428d7b3dSmrg_X_EXPORT Status XvMCGetSurfaceStatus(Display * display, XvMCSurface * surface,
716428d7b3dSmrg				      int *stat)
717428d7b3dSmrg{
718428d7b3dSmrg	if (!display || !surface || !stat)
719428d7b3dSmrg		return XvMCBadSurface;
720428d7b3dSmrg
721428d7b3dSmrg	*stat = 0;
722428d7b3dSmrg
723428d7b3dSmrg	return Success;
724428d7b3dSmrg}
725428d7b3dSmrg
726428d7b3dSmrg/*
727428d7b3dSmrg * Function: XvMCHideSurface
728428d7b3dSmrg * Description: Stops the display of a surface.
729428d7b3dSmrg * Arguments:
730428d7b3dSmrg *   display - Connection to the X server.
731428d7b3dSmrg *   surface - surface to be hidden.
732428d7b3dSmrg *
733428d7b3dSmrg * Returns: Status
734428d7b3dSmrg */
735428d7b3dSmrg_X_EXPORT Status XvMCHideSurface(Display * display, XvMCSurface * surface)
736428d7b3dSmrg{
737428d7b3dSmrg	if (!display || !surface)
738428d7b3dSmrg		return XvMCBadSurface;
739428d7b3dSmrg
740428d7b3dSmrg	return Success;
741428d7b3dSmrg}
742428d7b3dSmrg
743428d7b3dSmrg/*
744428d7b3dSmrg * Function: XvMCCreateSubpicture
745428d7b3dSmrg * Description: This creates a subpicture by filling out the XvMCSubpicture
746428d7b3dSmrg *              structure passed to it and returning Success.
747428d7b3dSmrg * Arguments:
748428d7b3dSmrg *   display - Connection to the X server.
749428d7b3dSmrg *   context - The context to create the subpicture for.
750428d7b3dSmrg *   subpicture - Pre-allocated XvMCSubpicture structure to be filled in.
751428d7b3dSmrg *   width - of subpicture
752428d7b3dSmrg *   height - of subpicture
753428d7b3dSmrg *   xvimage_id - The id describing the XvImage format.
754428d7b3dSmrg *
755428d7b3dSmrg * Returns: Status
756428d7b3dSmrg */
757428d7b3dSmrg_X_EXPORT Status XvMCCreateSubpicture(Display * display, XvMCContext * context,
758428d7b3dSmrg				      XvMCSubpicture * subpicture,
759428d7b3dSmrg				      unsigned short width,
760428d7b3dSmrg				      unsigned short height, int xvimage_id)
761428d7b3dSmrg{
762428d7b3dSmrg	XVMC_ERR("XvMCCreateSubpicture not implemented!\n");
763428d7b3dSmrg	return BadValue;
764428d7b3dSmrg}
765428d7b3dSmrg
766428d7b3dSmrg/*
767428d7b3dSmrg * Function: XvMCClearSubpicture
768428d7b3dSmrg * Description: Clear the area of the given subpicture to "color".
769428d7b3dSmrg *              structure passed to it and returning Success.
770428d7b3dSmrg * Arguments:
771428d7b3dSmrg *   display - Connection to the X server.
772428d7b3dSmrg *   subpicture - Subpicture to clear.
773428d7b3dSmrg *   x, y, width, height - rectangle in the subpicture to clear.
774428d7b3dSmrg *   color - The data to file the rectangle with.
775428d7b3dSmrg *
776428d7b3dSmrg * Returns: Status
777428d7b3dSmrg */
778428d7b3dSmrg_X_EXPORT Status XvMCClearSubpicture(Display * display,
779428d7b3dSmrg				     XvMCSubpicture * subpicture, short x,
780428d7b3dSmrg				     short y, unsigned short width,
781428d7b3dSmrg				     unsigned short height, unsigned int color)
782428d7b3dSmrg{
783428d7b3dSmrg	XVMC_ERR("XvMCClearSubpicture not implemented!");
784428d7b3dSmrg	return BadValue;
785428d7b3dSmrg}
786428d7b3dSmrg
787428d7b3dSmrg/*
788428d7b3dSmrg * Function: XvMCCompositeSubpicture
789428d7b3dSmrg * Description: Composite the XvImae on the subpicture. This composit uses
790428d7b3dSmrg *              non-premultiplied alpha. Destination alpha is utilized
791428d7b3dSmrg *              except for with indexed subpictures. Indexed subpictures
792428d7b3dSmrg *              use a simple "replace".
793428d7b3dSmrg * Arguments:
794428d7b3dSmrg *   display - Connection to the X server.
795428d7b3dSmrg *   subpicture - Subpicture to clear.
796428d7b3dSmrg *   image - the XvImage to be used as the source of the composite.
797428d7b3dSmrg *   srcx, srcy, width, height - The rectangle from the image to be used.
798428d7b3dSmrg *   dstx, dsty - location in the subpicture to composite the source.
799428d7b3dSmrg *
800428d7b3dSmrg * Returns: Status
801428d7b3dSmrg */
802428d7b3dSmrg_X_EXPORT Status XvMCCompositeSubpicture(Display * display,
803428d7b3dSmrg					 XvMCSubpicture * subpicture,
804428d7b3dSmrg					 XvImage * image, short srcx,
805428d7b3dSmrg					 short srcy, unsigned short width,
806428d7b3dSmrg					 unsigned short height, short dstx,
807428d7b3dSmrg					 short dsty)
808428d7b3dSmrg{
809428d7b3dSmrg	XVMC_ERR("XvMCCompositeSubpicture not implemented!");
810428d7b3dSmrg	return BadValue;
811428d7b3dSmrg}
812428d7b3dSmrg
813428d7b3dSmrg/*
814428d7b3dSmrg * Function: XvMCDestroySubpicture
815428d7b3dSmrg * Description: Destroys the specified subpicture.
816428d7b3dSmrg * Arguments:
817428d7b3dSmrg *   display - Connection to the X server.
818428d7b3dSmrg *   subpicture - Subpicture to be destroyed.
819428d7b3dSmrg *
820428d7b3dSmrg * Returns: Status
821428d7b3dSmrg */
822428d7b3dSmrg_X_EXPORT Status XvMCDestroySubpicture(Display * display,
823428d7b3dSmrg				       XvMCSubpicture * subpicture)
824428d7b3dSmrg{
825428d7b3dSmrg	XVMC_ERR("XvMCDestroySubpicture not implemented!");
826428d7b3dSmrg	return BadValue;
827428d7b3dSmrg}
828428d7b3dSmrg
829428d7b3dSmrg/*
830428d7b3dSmrg * Function: XvMCSetSubpicturePalette
831428d7b3dSmrg * Description: Set the subpictures palette
832428d7b3dSmrg * Arguments:
833428d7b3dSmrg *   display - Connection to the X server.
834428d7b3dSmrg *   subpicture - Subpiture to set palette for.
835428d7b3dSmrg *   palette - A pointer to an array holding the palette data. The array
836428d7b3dSmrg *     is num_palette_entries * entry_bytes in size.
837428d7b3dSmrg * Returns: Status
838428d7b3dSmrg */
839428d7b3dSmrg_X_EXPORT Status XvMCSetSubpicturePalette(Display * display,
840428d7b3dSmrg					  XvMCSubpicture * subpicture,
841428d7b3dSmrg					  unsigned char *palette)
842428d7b3dSmrg{
843428d7b3dSmrg	XVMC_ERR("XvMCSetSubpicturePalette not implemented!");
844428d7b3dSmrg	return BadValue;
845428d7b3dSmrg}
846428d7b3dSmrg
847428d7b3dSmrg/*
848428d7b3dSmrg * Function: XvMCBlendSubpicture
849428d7b3dSmrg * Description:
850428d7b3dSmrg *    The behavior of this function is different depending on whether
851428d7b3dSmrg *    or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo.
852428d7b3dSmrg *    i915 only support frontend behavior.
853428d7b3dSmrg *
854428d7b3dSmrg *    XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior):
855428d7b3dSmrg *
856428d7b3dSmrg *    XvMCBlendSubpicture is a no-op in this case.
857428d7b3dSmrg *
858428d7b3dSmrg * Arguments:
859428d7b3dSmrg *   display - Connection to the X server.
860428d7b3dSmrg *   subpicture - The subpicture to be blended into the video.
861428d7b3dSmrg *   target_surface - The surface to be displayed with the blended subpic.
862428d7b3dSmrg *   source_surface - Source surface prior to blending.
863428d7b3dSmrg *   subx, suby, subw, subh - The rectangle from the subpicture to use.
864428d7b3dSmrg *   surfx, surfy, surfw, surfh - The rectangle in the surface to blend
865428d7b3dSmrg *      blend the subpicture rectangle into. Scaling can ocure if
866428d7b3dSmrg *      XVMC_SUBPICTURE_INDEPENDENT_SCALING is set.
867428d7b3dSmrg *
868428d7b3dSmrg * Returns: Status
869428d7b3dSmrg */
870428d7b3dSmrg_X_EXPORT Status XvMCBlendSubpicture(Display * display,
871428d7b3dSmrg				     XvMCSurface * target_surface,
872428d7b3dSmrg				     XvMCSubpicture * subpicture, short subx,
873428d7b3dSmrg				     short suby, unsigned short subw,
874428d7b3dSmrg				     unsigned short subh, short surfx,
875428d7b3dSmrg				     short surfy, unsigned short surfw,
876428d7b3dSmrg				     unsigned short surfh)
877428d7b3dSmrg{
878428d7b3dSmrg	XVMC_ERR("XvMCBlendSubpicture not implemented!");
879428d7b3dSmrg	return BadValue;
880428d7b3dSmrg}
881428d7b3dSmrg
882428d7b3dSmrg/*
883428d7b3dSmrg * Function: XvMCBlendSubpicture2
884428d7b3dSmrg * Description:
885428d7b3dSmrg *    The behavior of this function is different depending on whether
886428d7b3dSmrg *    or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo.
887428d7b3dSmrg *    i915 only supports frontend blending.
888428d7b3dSmrg *
889428d7b3dSmrg *    XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior):
890428d7b3dSmrg *
891428d7b3dSmrg *    XvMCBlendSubpicture2 blends the source_surface and subpicture and
892428d7b3dSmrg *    puts it in the target_surface.  This does not effect the status of
893428d7b3dSmrg *    the source surface but will cause the target_surface to query
894428d7b3dSmrg *    XVMC_RENDERING until the blend is completed.
895428d7b3dSmrg *
896428d7b3dSmrg * Arguments:
897428d7b3dSmrg *   display - Connection to the X server.
898428d7b3dSmrg *   subpicture - The subpicture to be blended into the video.
899428d7b3dSmrg *   target_surface - The surface to be displayed with the blended subpic.
900428d7b3dSmrg *   source_surface - Source surface prior to blending.
901428d7b3dSmrg *   subx, suby, subw, subh - The rectangle from the subpicture to use.
902428d7b3dSmrg *   surfx, surfy, surfw, surfh - The rectangle in the surface to blend
903428d7b3dSmrg *      blend the subpicture rectangle into. Scaling can ocure if
904428d7b3dSmrg *      XVMC_SUBPICTURE_INDEPENDENT_SCALING is set.
905428d7b3dSmrg *
906428d7b3dSmrg * Returns: Status
907428d7b3dSmrg */
908428d7b3dSmrg_X_EXPORT Status XvMCBlendSubpicture2(Display * display,
909428d7b3dSmrg				      XvMCSurface * source_surface,
910428d7b3dSmrg				      XvMCSurface * target_surface,
911428d7b3dSmrg				      XvMCSubpicture * subpicture,
912428d7b3dSmrg				      short subx, short suby,
913428d7b3dSmrg				      unsigned short subw, unsigned short subh,
914428d7b3dSmrg				      short surfx, short surfy,
915428d7b3dSmrg				      unsigned short surfw,
916428d7b3dSmrg				      unsigned short surfh)
917428d7b3dSmrg{
918428d7b3dSmrg	XVMC_ERR("XvMCBlendSubpicture2 not implemented!");
919428d7b3dSmrg	return BadValue;
920428d7b3dSmrg}
921428d7b3dSmrg
922428d7b3dSmrg/*
923428d7b3dSmrg * Function: XvMCSyncSubpicture
924428d7b3dSmrg * Description: This function blocks until all composite/clear requests on
925428d7b3dSmrg *              the subpicture have been complete.
926428d7b3dSmrg * Arguments:
927428d7b3dSmrg *   display - Connection to the X server.
928428d7b3dSmrg *   subpicture - The subpicture to synchronize
929428d7b3dSmrg *
930428d7b3dSmrg * Returns: Status
931428d7b3dSmrg */
932428d7b3dSmrg_X_EXPORT Status XvMCSyncSubpicture(Display * display,
933428d7b3dSmrg				    XvMCSubpicture * subpicture)
934428d7b3dSmrg{
935428d7b3dSmrg	XVMC_ERR("XvMCSyncSubpicture not implemented!");
936428d7b3dSmrg	return BadValue;
937428d7b3dSmrg}
938428d7b3dSmrg
939428d7b3dSmrg/*
940428d7b3dSmrg * Function: XvMCFlushSubpicture
941428d7b3dSmrg * Description: This function commits pending composite/clear requests to
942428d7b3dSmrg *              ensure that they will be completed in a finite amount of
943428d7b3dSmrg *              time.
944428d7b3dSmrg * Arguments:
945428d7b3dSmrg *   display - Connection to the X server.
946428d7b3dSmrg *   subpicture - The subpicture whos compsiting should be flushed
947428d7b3dSmrg *
948428d7b3dSmrg * Returns: Status
949428d7b3dSmrg */
950428d7b3dSmrg_X_EXPORT Status XvMCFlushSubpicture(Display * display,
951428d7b3dSmrg				     XvMCSubpicture * subpicture)
952428d7b3dSmrg{
953428d7b3dSmrg	XVMC_ERR("XvMCFlushSubpicture not implemented!");
954428d7b3dSmrg	return BadValue;
955428d7b3dSmrg}
956428d7b3dSmrg
957428d7b3dSmrg/*
958428d7b3dSmrg * Function: XvMCGetSubpictureStatus
959428d7b3dSmrg * Description: This function gets the current status of a subpicture
960428d7b3dSmrg *
961428d7b3dSmrg * Arguments:
962428d7b3dSmrg *   display - Connection to the X server.
963428d7b3dSmrg *   subpicture - The subpicture whos status is being queried
964428d7b3dSmrg *   stat - The status of the subpicture. It can be any of the following
965428d7b3dSmrg *          OR'd together:
966428d7b3dSmrg *          XVMC_RENDERING  - Last composite or clear request not completed
967428d7b3dSmrg *          XVMC_DISPLAYING - Suppicture currently being displayed.
968428d7b3dSmrg *
969428d7b3dSmrg * Returns: Status
970428d7b3dSmrg */
971428d7b3dSmrg_X_EXPORT Status XvMCGetSubpictureStatus(Display * display,
972428d7b3dSmrg					 XvMCSubpicture * subpicture, int *stat)
973428d7b3dSmrg{
974428d7b3dSmrg	XVMC_ERR("XvMCGetSubpictureStatus not implemented!");
975428d7b3dSmrg	return BadValue;
976428d7b3dSmrg}
977428d7b3dSmrg
978428d7b3dSmrg/*
979428d7b3dSmrg * Function: XvMCQueryAttributes
980428d7b3dSmrg * Description: An array of XvAttributes of size "number" is returned by
981428d7b3dSmrg *   this function. If there are no attributes, NULL is returned and number
982428d7b3dSmrg *   is set to 0. The array may be freed with free().
983428d7b3dSmrg *
984428d7b3dSmrg * Arguments:
985428d7b3dSmrg *   display - Connection to the X server.
986428d7b3dSmrg *   context - The context whos attributes we are querying.
987428d7b3dSmrg *   number - The returned number of recognized atoms
988428d7b3dSmrg *
989428d7b3dSmrg * Returns:
990428d7b3dSmrg *  An array of XvAttributes.
991428d7b3dSmrg */
992428d7b3dSmrg_X_EXPORT XvAttribute *XvMCQueryAttributes(Display * display,
993428d7b3dSmrg					   XvMCContext * context, int *number)
994428d7b3dSmrg{
995428d7b3dSmrg	/* now XvMC has no extra attribs than Xv */
996428d7b3dSmrg	*number = 0;
997428d7b3dSmrg	return NULL;
998428d7b3dSmrg}
999428d7b3dSmrg
1000428d7b3dSmrg/*
1001428d7b3dSmrg * Function: XvMCSetAttribute
1002428d7b3dSmrg * Description: This function sets a context-specific attribute.
1003428d7b3dSmrg *
1004428d7b3dSmrg * Arguments:
1005428d7b3dSmrg *   display - Connection to the X server.
1006428d7b3dSmrg *   context - The context whos attributes we are querying.
1007428d7b3dSmrg *   attribute - The X atom of the attribute to be changed.
1008428d7b3dSmrg *   value - The new value for the attribute.
1009428d7b3dSmrg *
1010428d7b3dSmrg * Returns:
1011428d7b3dSmrg *  Status
1012428d7b3dSmrg */
1013428d7b3dSmrg_X_EXPORT Status XvMCSetAttribute(Display * display, XvMCContext * context,
1014428d7b3dSmrg				  Atom attribute, int value)
1015428d7b3dSmrg{
1016428d7b3dSmrg	return Success;
1017428d7b3dSmrg}
1018428d7b3dSmrg
1019428d7b3dSmrg/*
1020428d7b3dSmrg * Function: XvMCGetAttribute
1021428d7b3dSmrg * Description: This function queries a context-specific attribute and
1022428d7b3dSmrg *   returns the value.
1023428d7b3dSmrg *
1024428d7b3dSmrg * Arguments:
1025428d7b3dSmrg *   display - Connection to the X server.
1026428d7b3dSmrg *   context - The context whos attributes we are querying.
1027428d7b3dSmrg *   attribute - The X atom of the attribute to be queried
1028428d7b3dSmrg *   value - The returned attribute value
1029428d7b3dSmrg *
1030428d7b3dSmrg * Returns:
1031428d7b3dSmrg *  Status
1032428d7b3dSmrg */
1033428d7b3dSmrg_X_EXPORT Status XvMCGetAttribute(Display * display, XvMCContext * context,
1034428d7b3dSmrg				  Atom attribute, int *value)
1035428d7b3dSmrg{
1036428d7b3dSmrg	return Success;
1037428d7b3dSmrg}
1038428d7b3dSmrg
1039428d7b3dSmrg_X_EXPORT Status XvMCBeginSurface(Display * display, XvMCContext * context,
1040428d7b3dSmrg				  XvMCSurface * target,
1041428d7b3dSmrg				  XvMCSurface * past,
1042428d7b3dSmrg				  XvMCSurface * future,
1043428d7b3dSmrg				  const XvMCMpegControl * control)
1044428d7b3dSmrg{
1045428d7b3dSmrg	if (xvmc_driver->begin_surface(display, context,
1046428d7b3dSmrg				       target, past, future, control)) {
1047428d7b3dSmrg		XVMC_ERR("BeginSurface fail\n");
1048428d7b3dSmrg		return BadValue;
1049428d7b3dSmrg	}
1050428d7b3dSmrg	return Success;
1051428d7b3dSmrg}
1052428d7b3dSmrg
1053428d7b3dSmrg_X_EXPORT Status XvMCLoadQMatrix(Display * display, XvMCContext * context,
1054428d7b3dSmrg				 const XvMCQMatrix * qmx)
1055428d7b3dSmrg{
1056428d7b3dSmrg	if (xvmc_driver->load_qmatrix(display, context, qmx)) {
1057428d7b3dSmrg		XVMC_ERR("LoadQMatrix fail\n");
1058428d7b3dSmrg		return BadValue;
1059428d7b3dSmrg	}
1060428d7b3dSmrg	return Success;
1061428d7b3dSmrg}
1062428d7b3dSmrg
1063428d7b3dSmrg_X_EXPORT Status XvMCPutSlice(Display * display, XvMCContext * context,
1064428d7b3dSmrg			      char *slice, int nbytes)
1065428d7b3dSmrg{
1066428d7b3dSmrg	if (xvmc_driver->put_slice(display, context, (unsigned char *) slice, nbytes)) {
1067428d7b3dSmrg		XVMC_ERR("PutSlice fail\n");
1068428d7b3dSmrg		return BadValue;
1069428d7b3dSmrg	}
1070428d7b3dSmrg	return Success;
1071428d7b3dSmrg}
1072428d7b3dSmrg
1073428d7b3dSmrg_X_EXPORT Status XvMCPutSlice2(Display * display, XvMCContext * context,
1074428d7b3dSmrg			       char *slice, int nbytes, int slice_code)
1075428d7b3dSmrg{
1076428d7b3dSmrg	if (xvmc_driver->put_slice2
1077428d7b3dSmrg	    (display, context, (unsigned char *) slice, nbytes, slice_code)) {
1078428d7b3dSmrg		XVMC_ERR("PutSlice2 fail\n");
1079428d7b3dSmrg		return BadValue;
1080428d7b3dSmrg	}
1081428d7b3dSmrg	return Success;
1082428d7b3dSmrg}
1083