1/***************************************************************************
2
3 Copyright 2000-2011 Intel Corporation.  All Rights Reserved.
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the
7 "Software"), to deal in the Software without restriction, including
8 without limitation the rights to use, copy, modify, merge, publish,
9 distribute, sub license, and/or sell copies of the Software, and to
10 permit persons to whom the Software is furnished to do so, subject to
11 the following conditions:
12
13 The above copyright notice and this permission notice (including the
14 next paragraph) shall be included in all copies or substantial portions
15 of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
21 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
23 THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 **************************************************************************/
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#include "sna.h"
32#include "sna_video.h"
33
34#include "intel_options.h"
35
36#include <xf86drm.h>
37#include <xf86xv.h>
38#include <xf86Crtc.h>
39#include <X11/extensions/Xv.h>
40#include <fourcc.h>
41#include <i915_drm.h>
42#include <errno.h>
43
44#define fourcc_code(a,b,c,d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
45#define DRM_FORMAT_RGB565       fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */
46#define DRM_FORMAT_XRGB8888     fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */
47#define DRM_FORMAT_YUYV         fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */
48#define DRM_FORMAT_UYVY         fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */
49
50#define LOCAL_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct local_mode_set_plane)
51struct local_mode_set_plane {
52	uint32_t plane_id;
53	uint32_t crtc_id;
54	uint32_t fb_id; /* fb object contains surface format type */
55	uint32_t flags;
56
57	/* Signed dest location allows it to be partially off screen */
58	int32_t crtc_x, crtc_y;
59	uint32_t crtc_w, crtc_h;
60
61	/* Source values are 16.16 fixed point */
62	uint32_t src_x, src_y;
63	uint32_t src_h, src_w;
64};
65
66#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, true)
67
68static Atom xvColorKey, xvAlwaysOnTop, xvSyncToVblank;
69
70static XvFormatRec formats[] = { {15}, {16}, {24} };
71static const XvImageRec images[] = { XVIMAGE_YUY2, XVIMAGE_UYVY, XVMC_RGB888, XVMC_RGB565 };
72static const XvAttributeRec attribs[] = {
73	{ XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_COLORKEY" },
74	{ XvSettable | XvGettable, 0, 1, (char *)"XV_ALWAYS_ON_TOP" },
75};
76
77static int sna_video_sprite_stop(ddStopVideo_ARGS)
78{
79	struct sna_video *video = port->devPriv.ptr;
80	struct local_mode_set_plane s;
81	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(video->sna->scrn);
82	int i;
83
84	for (i = 0; i < config->num_crtc; i++) {
85		xf86CrtcPtr crtc = config->crtc[i];
86		int pipe;
87
88		if (sna_crtc_id(crtc) == 0)
89			break;
90
91		pipe = sna_crtc_to_pipe(crtc);
92		if (video->bo[pipe] == NULL)
93			continue;
94
95		memset(&s, 0, sizeof(s));
96		s.plane_id = sna_crtc_to_sprite(crtc);
97		if (drmIoctl(video->sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s))
98			xf86DrvMsg(video->sna->scrn->scrnIndex, X_ERROR,
99				   "failed to disable plane\n");
100
101		if (video->bo[pipe])
102			kgem_bo_destroy(&video->sna->kgem, video->bo[pipe]);
103		video->bo[pipe] = NULL;
104	}
105
106	sna_window_set_port((WindowPtr)draw, NULL);
107
108	return Success;
109}
110
111static int sna_video_sprite_set_attr(ddSetPortAttribute_ARGS)
112{
113	struct sna_video *video = port->devPriv.ptr;
114
115	if (attribute == xvColorKey) {
116		video->color_key_changed = ~0;
117		video->color_key = value;
118		RegionEmpty(&video->clip);
119		DBG(("COLORKEY = %ld\n", (long)value));
120	} else if (attribute == xvSyncToVblank) {
121		DBG(("%s: SYNC_TO_VBLANK: %d -> %d\n", __FUNCTION__,
122		     video->SyncToVblank, !!value));
123		video->SyncToVblank = !!value;
124	} else if (attribute == xvAlwaysOnTop) {
125		DBG(("%s: ALWAYS_ON_TOP: %d -> %d\n", __FUNCTION__,
126		     video->AlwaysOnTop, !!value));
127		video->color_key_changed = ~0;
128		video->AlwaysOnTop = !!value;
129	} else
130		return BadMatch;
131
132	return Success;
133}
134
135static int sna_video_sprite_get_attr(ddGetPortAttribute_ARGS)
136{
137	struct sna_video *video = port->devPriv.ptr;
138
139	if (attribute == xvColorKey)
140		*value = video->color_key;
141	else if (attribute == xvAlwaysOnTop)
142		*value = video->AlwaysOnTop;
143	else if (attribute == xvSyncToVblank)
144		*value = video->SyncToVblank;
145	else
146		return BadMatch;
147
148	return Success;
149}
150
151static int sna_video_sprite_best_size(ddQueryBestSize_ARGS)
152{
153	struct sna_video *video = port->devPriv.ptr;
154	struct sna *sna = video->sna;
155
156	if (sna->kgem.gen >= 075) {
157		*p_w = vid_w;
158		*p_h = vid_h;
159	} else {
160		*p_w = drw_w;
161		*p_h = drw_h;
162	}
163
164	return Success;
165}
166
167static void
168update_dst_box_to_crtc_coords(struct sna *sna, xf86CrtcPtr crtc, BoxPtr dstBox)
169{
170	ScrnInfoPtr scrn = sna->scrn;
171	int tmp;
172
173	switch (crtc->rotation & 0xf) {
174	case RR_Rotate_0:
175		dstBox->x1 -= crtc->x;
176		dstBox->x2 -= crtc->x;
177		dstBox->y1 -= crtc->y;
178		dstBox->y2 -= crtc->y;
179		break;
180
181	case RR_Rotate_90:
182		tmp = dstBox->x1;
183		dstBox->x1 = dstBox->y1 - crtc->x;
184		dstBox->y1 = scrn->virtualX - tmp - crtc->y;
185		tmp = dstBox->x2;
186		dstBox->x2 = dstBox->y2 - crtc->x;
187		dstBox->y2 = scrn->virtualX - tmp - crtc->y;
188		tmp = dstBox->y1;
189		dstBox->y1 = dstBox->y2;
190		dstBox->y2 = tmp;
191		break;
192
193	case RR_Rotate_180:
194		tmp = dstBox->x1;
195		dstBox->x1 = scrn->virtualX - dstBox->x2 - crtc->x;
196		dstBox->x2 = scrn->virtualX - tmp - crtc->x;
197		tmp = dstBox->y1;
198		dstBox->y1 = scrn->virtualY - dstBox->y2 - crtc->y;
199		dstBox->y2 = scrn->virtualY - tmp - crtc->y;
200		break;
201
202	case RR_Rotate_270:
203		tmp = dstBox->x1;
204		dstBox->x1 = scrn->virtualY - dstBox->y1 - crtc->x;
205		dstBox->y1 = tmp - crtc->y;
206		tmp = dstBox->x2;
207		dstBox->x2 = scrn->virtualY - dstBox->y2 - crtc->x;
208		dstBox->y2 = tmp - crtc->y;
209		tmp = dstBox->x1;
210		dstBox->x1 = dstBox->x2;
211		dstBox->x2 = tmp;
212		break;
213	}
214}
215
216static bool
217sna_video_sprite_show(struct sna *sna,
218		      struct sna_video *video,
219		      struct sna_video_frame *frame,
220		      xf86CrtcPtr crtc,
221		      BoxPtr dstBox)
222{
223	struct local_mode_set_plane s;
224	int pipe = sna_crtc_to_pipe(crtc);
225
226	/* XXX handle video spanning multiple CRTC */
227
228	VG_CLEAR(s);
229	s.plane_id = sna_crtc_to_sprite(crtc);
230
231#define DRM_I915_SET_SPRITE_COLORKEY 0x2b
232#define LOCAL_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct local_intel_sprite_colorkey)
233#define LOCAL_IOCTL_MODE_ADDFB2 DRM_IOWR(0xb8, struct local_mode_fb_cmd2)
234
235	if (video->color_key_changed & (1 << pipe) && video->has_color_key) {
236		struct local_intel_sprite_colorkey {
237			uint32_t plane_id;
238			uint32_t min_value;
239			uint32_t channel_mask;
240			uint32_t max_value;
241			uint32_t flags;
242		} set;
243
244		DBG(("%s: updating color key: %x\n",
245		     __FUNCTION__, video->color_key));
246
247		set.plane_id = s.plane_id;
248		set.min_value = video->color_key;
249		set.max_value = video->color_key; /* not used for destkey */
250		set.channel_mask = 0x7 << 24 | 0xff << 16 | 0xff << 8 | 0xff << 0;
251		set.flags = 0;
252		if (!video->AlwaysOnTop)
253			set.flags |= 1 << 1; /* COLORKEY_DESTINATION */
254
255		if (drmIoctl(sna->kgem.fd,
256			     LOCAL_IOCTL_I915_SET_SPRITE_COLORKEY,
257			     &set)) {
258			xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
259				   "failed to update color key, disabling future updates\n");
260			video->has_color_key = false;
261		}
262
263		video->color_key_changed &= ~(1 << pipe);
264	}
265
266	if (video->bo[pipe] == frame->bo)
267		return true;
268
269	update_dst_box_to_crtc_coords(sna, crtc, dstBox);
270	if (frame->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
271		int tmp = frame->width;
272		frame->width = frame->height;
273		frame->height = tmp;
274	}
275
276	if (frame->bo->delta == 0) {
277		struct local_mode_fb_cmd2 {
278			uint32_t fb_id;
279			uint32_t width, height;
280			uint32_t pixel_format;
281			uint32_t flags;
282
283			uint32_t handles[4];
284			uint32_t pitches[4]; /* pitch for each plane */
285			uint32_t offsets[4]; /* offset of each plane */
286		} f;
287		bool purged = true;
288
289		memset(&f, 0, sizeof(f));
290		f.width = frame->width;
291		f.height = frame->height;
292		f.handles[0] = frame->bo->handle;
293		f.pitches[0] = frame->pitch[0];
294
295		switch (frame->id) {
296		case FOURCC_RGB565:
297			f.pixel_format = DRM_FORMAT_RGB565;
298			purged = sna->scrn->depth != 16;
299			break;
300		case FOURCC_RGB888:
301			f.pixel_format = DRM_FORMAT_XRGB8888;
302			purged = sna->scrn->depth != 24;
303			break;
304		case FOURCC_UYVY:
305			f.pixel_format = DRM_FORMAT_UYVY;
306			break;
307		case FOURCC_YUY2:
308		default:
309			f.pixel_format = DRM_FORMAT_YUYV;
310			break;
311		}
312
313		DBG(("%s: creating new fb for handle=%d, width=%d, height=%d, stride=%d, format=%x\n",
314		     __FUNCTION__, frame->bo->handle, frame->width, frame->height,
315		     f.pitches[0], f.pixel_format));
316
317		if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_ADDFB2, &f)) {
318			ERR(("%s: ADDFB2 failed, errno=%d\n", __FUNCTION__, errno));
319			xf86DrvMsg(sna->scrn->scrnIndex,
320				   X_ERROR, "failed to add fb, unable to update video\n");
321			return false;
322		}
323
324		frame->bo->delta = f.fb_id;
325
326		frame->bo->scanout = true;
327		/* Don't allow the scanout to be cached if not suitable for front */
328		frame->bo->purged = purged;
329	}
330
331	assert(frame->bo->scanout);
332	assert(frame->bo->delta);
333
334	s.crtc_id = sna_crtc_id(crtc);
335	s.fb_id = frame->bo->delta;
336	s.flags = 0;
337	s.crtc_x = dstBox->x1;
338	s.crtc_y = dstBox->y1;
339	s.crtc_w = dstBox->x2 - dstBox->x1;
340	s.crtc_h = dstBox->y2 - dstBox->y1;
341	s.src_x = 0;
342	s.src_y = 0;
343	s.src_w = (frame->image.x2 - frame->image.x1) << 16;
344	s.src_h = (frame->image.y2 - frame->image.y1) << 16;
345
346	DBG(("%s: updating crtc=%d, plane=%d, handle=%d [fb %d], dst=(%d,%d)x(%d,%d), src=(%d,%d)x(%d,%d)\n",
347	     __FUNCTION__, s.crtc_id, s.plane_id, frame->bo->handle, s.fb_id,
348	     s.crtc_x, s.crtc_y, s.crtc_w, s.crtc_h,
349	     s.src_x >> 16, s.src_y >> 16, s.src_w >> 16, s.src_h >> 16));
350
351	if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s)) {
352		DBG(("SET_PLANE failed: ret=%d\n", errno));
353		memset(&s, 0, sizeof(s));
354		s.plane_id = video->plane;
355		(void)drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s);
356		if (video->bo[pipe]) {
357			kgem_bo_destroy(&sna->kgem, video->bo[pipe]);
358			video->bo[pipe] = NULL;
359		}
360		return false;
361	}
362
363	frame->bo->domain = DOMAIN_NONE;
364
365	if (video->bo[pipe])
366		kgem_bo_destroy(&sna->kgem, video->bo[pipe]);
367	video->bo[pipe] = kgem_bo_reference(frame->bo);
368	return true;
369}
370
371static int sna_video_sprite_put_image(ddPutImage_ARGS)
372{
373	struct sna_video *video = port->devPriv.ptr;
374	struct sna *sna = video->sna;
375	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
376	RegionRec clip;
377	int ret, i;
378
379	clip.extents.x1 = draw->x + drw_x;
380	clip.extents.y1 = draw->y + drw_y;
381	clip.extents.x2 = clip.extents.x1 + drw_w;
382	clip.extents.y2 = clip.extents.y1 + drw_h;
383	clip.data = NULL;
384
385	DBG(("%s: always_on_top=%d\n", __FUNCTION__, video->AlwaysOnTop));
386	if (!video->AlwaysOnTop)
387		RegionIntersect(&clip, &clip, gc->pCompositeClip);
388
389	DBG(("%s: src=(%d, %d),(%d, %d), dst=(%d, %d),(%d, %d), id=%d, sizep=%dx%d, sync?=%d\n",
390	     __FUNCTION__,
391	     src_x, src_y, src_w, src_h,
392	     drw_x, drw_y, drw_w, drw_h,
393	     format->id, width, height, sync));
394
395	DBG(("%s: region %d:(%d, %d), (%d, %d)\n", __FUNCTION__,
396	     region_num_rects(&clip),
397	     clip.extents.x1, clip.extents.y1,
398	     clip.extents.x2, clip.extents.y2));
399
400	if (RegionNil(&clip)) {
401		ret = Success;
402		goto err;
403	}
404
405	for (i = 0; i < config->num_crtc; i++) {
406		xf86CrtcPtr crtc = config->crtc[i];
407		struct sna_video_frame frame;
408		int pipe;
409		INT32 x1, x2, y1, y2;
410		BoxRec dst;
411		RegionRec reg;
412		Rotation rotation;
413
414		if (sna_crtc_id(crtc) == 0)
415			break;
416
417		pipe = sna_crtc_to_pipe(crtc);
418
419		sna_video_frame_init(video, format->id, width, height, &frame);
420
421		reg.extents = crtc->bounds;
422		reg.data = NULL;
423		RegionIntersect(&reg, &reg, &clip);
424		if (RegionNil(&reg)) {
425off:
426			if (video->bo[pipe]) {
427				struct local_mode_set_plane s;
428				memset(&s, 0, sizeof(s));
429				s.plane_id = sna_crtc_to_sprite(crtc);
430				if (drmIoctl(video->sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s))
431					xf86DrvMsg(video->sna->scrn->scrnIndex, X_ERROR,
432						   "failed to disable plane\n");
433				video->bo[pipe] = NULL;
434			}
435			continue;
436		}
437
438		x1 = src_x;
439		x2 = src_x + src_w;
440		y1 = src_y;
441		y2 = src_y + src_h;
442
443		dst = clip.extents;
444
445		ret = xf86XVClipVideoHelper(&dst, &x1, &x2, &y1, &y2,
446					    &reg, frame.width, frame.height);
447		RegionUninit(&reg);
448		if (!ret)
449			goto off;
450
451		frame.src.x1 = x1 >> 16;
452		frame.src.y1 = y1 >> 16;
453		frame.src.x2 = (x2 + 0xffff) >> 16;
454		frame.src.y2 = (y2 + 0xffff) >> 16;
455
456		frame.image.x1 = frame.src.x1 & ~1;
457		frame.image.x2 = ALIGN(frame.src.x2, 2);
458		if (is_planar_fourcc(frame.id)) {
459			frame.image.y1 = frame.src.y1 & ~1;
460			frame.image.y2 = ALIGN(frame.src.y2, 2);
461		} else {
462			frame.image.y1 = frame.src.y1;
463			frame.image.y2 = frame.src.y2;
464		}
465
466		/* if sprite can't handle rotation natively, store it for the copy func */
467		rotation = RR_Rotate_0;
468		if (!sna_crtc_set_sprite_rotation(crtc, crtc->rotation)) {
469			sna_crtc_set_sprite_rotation(crtc, RR_Rotate_0);
470			rotation = crtc->rotation;
471		}
472		sna_video_frame_set_rotation(video, &frame, rotation);
473
474		if (xvmc_passthrough(format->id)) {
475			DBG(("%s: using passthough, name=%d\n",
476			     __FUNCTION__, *(uint32_t *)buf));
477
478			if (*(uint32_t*)buf == 0)
479				goto err;
480
481			frame.bo = kgem_create_for_name(&sna->kgem, *(uint32_t*)buf);
482			if (frame.bo == NULL) {
483				ret = BadAlloc;
484				goto err;
485			}
486
487			if (kgem_bo_size(frame.bo) < frame.size) {
488				DBG(("%s: bo size=%d, expected=%d\n",
489				     __FUNCTION__, kgem_bo_size(frame.bo), frame.size));
490				kgem_bo_destroy(&sna->kgem, frame.bo);
491				ret = BadAlloc;
492				goto err;
493			}
494
495			frame.image.x1 = 0;
496			frame.image.y1 = 0;
497			frame.image.x2 = frame.width;
498			frame.image.y2 = frame.height;
499		} else {
500			frame.bo = sna_video_buffer(video, &frame);
501			if (frame.bo == NULL) {
502				DBG(("%s: failed to allocate video bo\n", __FUNCTION__));
503				ret = BadAlloc;
504				goto err;
505			}
506
507			if (!sna_video_copy_data(video, &frame, buf)) {
508				DBG(("%s: failed to copy video data\n", __FUNCTION__));
509				ret = BadAlloc;
510				goto err;
511			}
512		}
513
514		ret = Success;
515		if (!sna_video_sprite_show(sna, video, &frame, crtc, &dst)) {
516			DBG(("%s: failed to show video frame\n", __FUNCTION__));
517			ret = BadAlloc;
518		}
519
520		frame.bo->domain = DOMAIN_NONE;
521		if (xvmc_passthrough(format->id))
522			kgem_bo_destroy(&sna->kgem, frame.bo);
523		else
524			sna_video_buffer_fini(video);
525
526		if (ret != Success)
527			goto err;
528	}
529
530	if (!video->AlwaysOnTop && !RegionEqual(&video->clip, &clip) &&
531	    sna_blt_fill_boxes(sna, GXcopy,
532			       __sna_pixmap_get_bo(sna->front),
533			       sna->front->drawable.bitsPerPixel,
534			       video->color_key,
535			       region_rects(&clip),
536			       region_num_rects(&clip)))
537		RegionCopy(&video->clip, &clip);
538	sna_window_set_port((WindowPtr)draw, port);
539
540	return Success;
541
542err:
543#if XORG_XV_VERSION < 2
544	(void)sna_video_sprite_stop(client, port, draw);
545#else
546	(void)sna_video_sprite_stop(port, draw);
547#endif
548	return ret;
549}
550
551static int sna_video_sprite_query(ddQueryImageAttributes_ARGS)
552{
553	struct sna_video *video = port->devPriv.ptr;
554	struct sna_video_frame frame;
555	int size;
556
557	if (*w > video->sna->mode.max_crtc_width)
558		*w = video->sna->mode.max_crtc_width;
559	if (*h > video->sna->mode.max_crtc_height)
560		*h = video->sna->mode.max_crtc_height;
561
562	if (offsets)
563		offsets[0] = 0;
564
565	switch (format->id) {
566	case FOURCC_RGB888:
567	case FOURCC_RGB565:
568		if (pitches) {
569			sna_video_frame_init(video, format->id, *w, *h, &frame);
570			sna_video_frame_set_rotation(video, &frame, RR_Rotate_0);
571			pitches[0] = frame.pitch[0];
572		}
573		size = 4;
574		break;
575
576	default:
577		*w = (*w + 1) & ~1;
578		*h = (*h + 1) & ~1;
579
580		size = *w << 1;
581		if (pitches)
582			pitches[0] = size;
583		size *= *h;
584		break;
585	}
586
587	return size;
588}
589
590static int sna_video_sprite_color_key(struct sna *sna)
591{
592	ScrnInfoPtr scrn = sna->scrn;
593	int color_key;
594
595	if (xf86GetOptValInteger(sna->Options, OPTION_VIDEO_KEY,
596				 &color_key)) {
597	} else if (xf86GetOptValInteger(sna->Options, OPTION_COLOR_KEY,
598					&color_key)) {
599	} else {
600		color_key =
601		    (1 << scrn->offset.red) |
602		    (1 << scrn->offset.green) |
603		    (((scrn->mask.blue >> scrn->offset.blue) - 1) << scrn->offset.blue);
604	}
605
606	return color_key & ((1 << scrn->depth) - 1);
607}
608
609static bool sna_video_has_sprites(struct sna *sna)
610{
611	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
612	int i;
613
614	DBG(("%s: num_crtc=%d\n", __FUNCTION__, sna->mode.num_real_crtc));
615
616	if (sna->mode.num_real_crtc == 0)
617		return false;
618
619	for (i = 0; i < sna->mode.num_real_crtc; i++) {
620		if (!sna_crtc_to_sprite(config->crtc[i])) {
621			DBG(("%s: no sprite found on pipe %d\n", __FUNCTION__, sna_crtc_to_pipe(config->crtc[i])));
622			return false;
623		}
624	}
625
626	DBG(("%s: yes\n", __FUNCTION__));
627	return true;
628}
629
630void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
631{
632	XvAdaptorPtr adaptor;
633	struct sna_video *video;
634	XvPortPtr port;
635
636	if (!sna_video_has_sprites(sna))
637		return;
638
639	adaptor = sna_xv_adaptor_alloc(sna);
640	if (!adaptor)
641		return;
642
643	video = calloc(1, sizeof(*video));
644	port = calloc(1, sizeof(*port));
645	if (video == NULL || port == NULL) {
646		free(video);
647		free(port);
648		sna->xv.num_adaptors--;
649		return;
650	}
651
652	adaptor->type = XvInputMask | XvImageMask;
653	adaptor->pScreen = screen;
654	adaptor->name = (char *)"Intel(R) Video Sprite";
655	adaptor->nEncodings = 1;
656	adaptor->pEncodings = xnfalloc(sizeof(XvEncodingRec));
657	adaptor->pEncodings[0].id = 0;
658	adaptor->pEncodings[0].pScreen = screen;
659	adaptor->pEncodings[0].name = (char *)"XV_IMAGE";
660	adaptor->pEncodings[0].width = sna->mode.max_crtc_width;
661	adaptor->pEncodings[0].height = sna->mode.max_crtc_height;
662	adaptor->pEncodings[0].rate.numerator = 1;
663	adaptor->pEncodings[0].rate.denominator = 1;
664	adaptor->pFormats = formats;
665	adaptor->nFormats = sna_xv_fixup_formats(screen, formats,
666						 ARRAY_SIZE(formats));
667	adaptor->nAttributes = ARRAY_SIZE(attribs);
668	adaptor->pAttributes = (XvAttributeRec *)attribs;
669	adaptor->pImages = (XvImageRec *)images;
670	adaptor->nImages = 3;
671	if (sna->kgem.gen == 071)
672		adaptor->nImages = 4;
673
674#if XORG_XV_VERSION < 2
675	adaptor->ddAllocatePort = sna_xv_alloc_port;
676	adaptor->ddFreePort = sna_xv_free_port;
677#endif
678	adaptor->ddPutVideo = NULL;
679	adaptor->ddPutStill = NULL;
680	adaptor->ddGetVideo = NULL;
681	adaptor->ddGetStill = NULL;
682	adaptor->ddStopVideo = sna_video_sprite_stop;
683	adaptor->ddSetPortAttribute = sna_video_sprite_set_attr;
684	adaptor->ddGetPortAttribute = sna_video_sprite_get_attr;
685	adaptor->ddQueryBestSize = sna_video_sprite_best_size;
686	adaptor->ddPutImage = sna_video_sprite_put_image;
687	adaptor->ddQueryImageAttributes = sna_video_sprite_query;
688
689	adaptor->nPorts = 1;
690	adaptor->pPorts = port;
691
692	adaptor->base_id = port->id = FakeClientID(0);
693	AddResource(port->id, XvGetRTPort(), port);
694	port->pAdaptor = adaptor;
695	port->pNotify =  NULL;
696	port->pDraw =  NULL;
697	port->client =  NULL;
698	port->grab.client =  NULL;
699	port->time = currentTime;
700	port->devPriv.ptr = video;
701
702	video->sna = sna;
703	video->alignment = 64;
704	video->color_key = sna_video_sprite_color_key(sna);
705	video->color_key_changed = ~0;
706	video->has_color_key = true;
707	video->brightness = -19;	/* (255/219) * -16 */
708	video->contrast = 75;	/* 255/219 * 64 */
709	video->saturation = 146;	/* 128/112 * 128 */
710	video->desired_crtc = NULL;
711	video->gamma5 = 0xc0c0c0;
712	video->gamma4 = 0x808080;
713	video->gamma3 = 0x404040;
714	video->gamma2 = 0x202020;
715	video->gamma1 = 0x101010;
716	video->gamma0 = 0x080808;
717	RegionNull(&video->clip);
718	video->SyncToVblank = 1;
719
720	xvColorKey = MAKE_ATOM("XV_COLORKEY");
721	xvAlwaysOnTop = MAKE_ATOM("XV_ALWAYS_ON_TOP");
722	xvSyncToVblank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
723
724	DBG(("%s: '%s' initialized %d ports\n", __FUNCTION__, adaptor->name, adaptor->nPorts));
725}
726