1/**************************************************************************
2
3Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4All Rights Reserved.
5Copyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org>
6  Based on code from i830_xaa.c.
7
8Permission is hereby granted, free of charge, to any person obtaining a
9copy of this software and associated documentation files (the
10"Software"), to deal in the Software without restriction, including
11without limitation the rights to use, copy, modify, merge, publish,
12distribute, sub license, and/or sell copies of the Software, and to
13permit persons to whom the Software is furnished to do so, subject to
14the following conditions:
15
16The above copyright notice and this permission notice (including the
17next paragraph) shall be included in all copies or substantial portions
18of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
24ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28**************************************************************************/
29
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
34#include "xorg-server.h"
35#include <xf86.h>
36#include <xf86drm.h>
37#include <xaarop.h>
38#include <string.h>
39#include <errno.h>
40#include <unistd.h>
41
42#include "intel.h"
43#include "intel_uxa.h"
44
45#include "i830_reg.h"
46#include "i915_drm.h"
47#include "brw_defines.h"
48
49static const int I830CopyROP[16] = {
50	ROP_0,			/* GXclear */
51	ROP_DSa,		/* GXand */
52	ROP_SDna,		/* GXandReverse */
53	ROP_S,			/* GXcopy */
54	ROP_DSna,		/* GXandInverted */
55	ROP_D,			/* GXnoop */
56	ROP_DSx,		/* GXxor */
57	ROP_DSo,		/* GXor */
58	ROP_DSon,		/* GXnor */
59	ROP_DSxn,		/* GXequiv */
60	ROP_Dn,			/* GXinvert */
61	ROP_SDno,		/* GXorReverse */
62	ROP_Sn,			/* GXcopyInverted */
63	ROP_DSno,		/* GXorInverted */
64	ROP_DSan,		/* GXnand */
65	ROP_1			/* GXset */
66};
67
68static const int I830PatternROP[16] = {
69	ROP_0,
70	ROP_DPa,
71	ROP_PDna,
72	ROP_P,
73	ROP_DPna,
74	ROP_D,
75	ROP_DPx,
76	ROP_DPo,
77	ROP_DPon,
78	ROP_PDxn,
79	ROP_Dn,
80	ROP_PDno,
81	ROP_Pn,
82	ROP_DPno,
83	ROP_DPan,
84	ROP_1
85};
86
87#if HAS_DEVPRIVATEKEYREC
88DevPrivateKeyRec uxa_pixmap_index;
89#else
90int uxa_pixmap_index;
91#endif
92
93static void
94gen6_context_switch(intel_screen_private *intel,
95		    int new_mode)
96{
97	intel_batch_submit(intel->scrn);
98}
99
100static void
101gen5_context_switch(intel_screen_private *intel,
102		    int new_mode)
103{
104	/* Ironlake has a limitation that a 3D or Media command can't
105	 * be the first command after a BLT, unless it's
106	 * non-pipelined.  Instead of trying to track it and emit a
107	 * command at the right time, we just emit a dummy
108	 * non-pipelined 3D instruction after each blit.
109	 */
110
111	if (new_mode == I915_EXEC_BLT) {
112		OUT_BATCH(MI_FLUSH |
113			  MI_STATE_INSTRUCTION_CACHE_FLUSH |
114			  MI_INHIBIT_RENDER_CACHE_FLUSH);
115	} else {
116		OUT_BATCH(CMD_POLY_STIPPLE_OFFSET << 16);
117		OUT_BATCH(0);
118	}
119}
120
121static void
122gen4_context_switch(intel_screen_private *intel,
123		    int new_mode)
124{
125	if (new_mode == I915_EXEC_BLT) {
126		OUT_BATCH(MI_FLUSH |
127			  MI_STATE_INSTRUCTION_CACHE_FLUSH |
128			  MI_INHIBIT_RENDER_CACHE_FLUSH);
129	}
130}
131
132Bool
133intel_uxa_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table,
134			 int num_bos)
135{
136	intel_screen_private *intel = intel_get_screen_private(scrn);
137
138	if (intel->batch_bo == NULL) {
139		intel_uxa_debug_fallback(scrn, "VT inactive\n");
140		return FALSE;
141	}
142
143	bo_table[0] = intel->batch_bo;
144	if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 0) {
145		intel_batch_submit(scrn);
146		bo_table[0] = intel->batch_bo;
147		if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) !=
148		    0) {
149			intel_uxa_debug_fallback(scrn, "Couldn't get aperture "
150					    "space for BOs\n");
151			return FALSE;
152		}
153	}
154	return TRUE;
155}
156
157static Bool
158intel_uxa_check_solid(DrawablePtr drawable, int alu, Pixel planemask)
159{
160	ScrnInfoPtr scrn = xf86ScreenToScrn(drawable->pScreen);
161
162	if (!UXA_PM_IS_SOLID(drawable, planemask)) {
163		intel_uxa_debug_fallback(scrn, "planemask is not solid\n");
164		return FALSE;
165	}
166
167	switch (drawable->bitsPerPixel) {
168	case 8:
169	case 16:
170	case 32:
171		break;
172	default:
173		return FALSE;
174	}
175
176	return TRUE;
177}
178
179/**
180 * Sets up hardware state for a series of solid fills.
181 */
182static Bool
183intel_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg)
184{
185	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
186	intel_screen_private *intel = intel_get_screen_private(scrn);
187	drm_intel_bo *bo_table[] = {
188		NULL,		/* batch_bo */
189		intel_uxa_get_pixmap_bo(pixmap),
190	};
191
192	if (!intel_uxa_check_pitch_2d(pixmap))
193		return FALSE;
194
195	if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
196		return FALSE;
197
198	intel->BR[13] = (I830PatternROP[alu] & 0xff) << 16;
199	switch (pixmap->drawable.bitsPerPixel) {
200	case 8:
201		break;
202	case 16:
203		/* RGB565 */
204		intel->BR[13] |= (1 << 24);
205		break;
206	case 32:
207		/* RGB8888 */
208		intel->BR[13] |= ((1 << 24) | (1 << 25));
209		break;
210	}
211	intel->BR[16] = fg;
212
213	return TRUE;
214}
215
216static void intel_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2)
217{
218	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
219	intel_screen_private *intel = intel_get_screen_private(scrn);
220	unsigned long pitch;
221	uint32_t cmd;
222
223	if (x1 < 0)
224		x1 = 0;
225	if (y1 < 0)
226		y1 = 0;
227	if (x2 > pixmap->drawable.width)
228		x2 = pixmap->drawable.width;
229	if (y2 > pixmap->drawable.height)
230		y2 = pixmap->drawable.height;
231
232	if (x2 <= x1 || y2 <= y1)
233		return;
234
235	pitch = intel_pixmap_pitch(pixmap);
236
237	{
238		int len = INTEL_INFO(intel)->gen >= 0100 ? 7 : 6;
239		BEGIN_BATCH_BLT(len);
240
241		cmd = XY_COLOR_BLT_CMD | (len - 2);
242
243		if (pixmap->drawable.bitsPerPixel == 32)
244			cmd |=
245			    XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB;
246
247		if (INTEL_INFO(intel)->gen >= 040 && intel_uxa_pixmap_tiled(pixmap)) {
248			assert((pitch % 512) == 0);
249			pitch >>= 2;
250			cmd |= XY_COLOR_BLT_TILED;
251		}
252
253		OUT_BATCH(cmd);
254
255		OUT_BATCH(intel->BR[13] | pitch);
256		OUT_BATCH((y1 << 16) | (x1 & 0xffff));
257		OUT_BATCH((y2 << 16) | (x2 & 0xffff));
258		OUT_RELOC_PIXMAP_FENCED(pixmap, I915_GEM_DOMAIN_RENDER,
259					I915_GEM_DOMAIN_RENDER, 0);
260		OUT_BATCH(intel->BR[16]);
261		ADVANCE_BATCH();
262	}
263}
264
265/**
266 * TODO:
267 *   - support planemask using FULL_BLT_CMD?
268 */
269static Bool
270intel_uxa_check_copy(PixmapPtr source, PixmapPtr dest,
271		    int alu, Pixel planemask)
272{
273	ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen);
274
275	if (!UXA_PM_IS_SOLID(&source->drawable, planemask)) {
276		intel_uxa_debug_fallback(scrn, "planemask is not solid");
277		return FALSE;
278	}
279
280	if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel) {
281		intel_uxa_debug_fallback(scrn, "mixed bpp copies unsupported\n");
282		return FALSE;
283	}
284	switch (source->drawable.bitsPerPixel) {
285	case 8:
286	case 16:
287	case 32:
288		break;
289	default:
290		return FALSE;
291	}
292
293	if (!intel_uxa_check_pitch_2d(source))
294		return FALSE;
295	if (!intel_uxa_check_pitch_2d(dest))
296		return FALSE;
297
298	return TRUE;
299}
300
301static Bool
302intel_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir,
303		      int ydir, int alu, Pixel planemask)
304{
305	ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen);
306	intel_screen_private *intel = intel_get_screen_private(scrn);
307	drm_intel_bo *bo_table[] = {
308		NULL,		/* batch_bo */
309		intel_uxa_get_pixmap_bo(source),
310		intel_uxa_get_pixmap_bo(dest),
311	};
312
313	if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
314		return FALSE;
315
316	intel->render_source = source;
317
318	intel->BR[13] = I830CopyROP[alu] << 16;
319	switch (source->drawable.bitsPerPixel) {
320	case 8:
321		break;
322	case 16:
323		intel->BR[13] |= (1 << 24);
324		break;
325	case 32:
326		intel->BR[13] |= ((1 << 25) | (1 << 24));
327		break;
328	}
329
330	return TRUE;
331}
332
333static void
334intel_uxa_copy(PixmapPtr dest, int src_x1, int src_y1, int dst_x1,
335	      int dst_y1, int w, int h)
336{
337	ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen);
338	intel_screen_private *intel = intel_get_screen_private(scrn);
339	uint32_t cmd;
340	int dst_x2, dst_y2, src_x2, src_y2;
341	unsigned int dst_pitch, src_pitch;
342
343	dst_x2 = dst_x1 + w;
344	dst_y2 = dst_y1 + h;
345
346	/* XXX Fixup extents as a lamentable workaround for missing
347	 * source clipping in the upper layers.
348	 */
349	if (dst_x1 < 0)
350		src_x1 -= dst_x1, dst_x1 = 0;
351	if (dst_y1 < 0)
352		src_y1 -= dst_y1, dst_y1 = 0;
353	if (dst_x2 > dest->drawable.width)
354		dst_x2 = dest->drawable.width;
355	if (dst_y2 > dest->drawable.height)
356		dst_y2 = dest->drawable.height;
357
358	src_x2 = src_x1 + (dst_x2 - dst_x1);
359	src_y2 = src_y1 + (dst_y2 - dst_y1);
360
361	if (src_x1 < 0)
362		dst_x1 -= src_x1, src_x1 = 0;
363	if (src_y1 < 0)
364		dst_y1 -= src_y1, src_y1 = 0;
365	if (src_x2 > intel->render_source->drawable.width)
366		dst_x2 -= src_x2 - intel->render_source->drawable.width;
367	if (src_y2 > intel->render_source->drawable.height)
368		dst_y2 -= src_y2 - intel->render_source->drawable.height;
369
370	if (dst_x2 <= dst_x1 || dst_y2 <= dst_y1)
371		return;
372
373	dst_pitch = intel_pixmap_pitch(dest);
374	src_pitch = intel_pixmap_pitch(intel->render_source);
375
376	{
377		int len = INTEL_INFO(intel)->gen >= 0100 ? 10 : 8;
378		BEGIN_BATCH_BLT(len);
379
380		cmd = XY_SRC_COPY_BLT_CMD | (len - 2);
381
382		if (dest->drawable.bitsPerPixel == 32)
383			cmd |=
384			    XY_SRC_COPY_BLT_WRITE_ALPHA |
385			    XY_SRC_COPY_BLT_WRITE_RGB;
386
387		if (INTEL_INFO(intel)->gen >= 040) {
388			if (intel_uxa_pixmap_tiled(dest)) {
389				assert((dst_pitch % 512) == 0);
390				dst_pitch >>= 2;
391				cmd |= XY_SRC_COPY_BLT_DST_TILED;
392			}
393
394			if (intel_uxa_pixmap_tiled(intel->render_source)) {
395				assert((src_pitch % 512) == 0);
396				src_pitch >>= 2;
397				cmd |= XY_SRC_COPY_BLT_SRC_TILED;
398			}
399		}
400
401		OUT_BATCH(cmd);
402
403		OUT_BATCH(intel->BR[13] | dst_pitch);
404		OUT_BATCH((dst_y1 << 16) | (dst_x1 & 0xffff));
405		OUT_BATCH((dst_y2 << 16) | (dst_x2 & 0xffff));
406		OUT_RELOC_PIXMAP_FENCED(dest,
407					I915_GEM_DOMAIN_RENDER,
408					I915_GEM_DOMAIN_RENDER,
409					0);
410		OUT_BATCH((src_y1 << 16) | (src_x1 & 0xffff));
411		OUT_BATCH(src_pitch);
412		OUT_RELOC_PIXMAP_FENCED(intel->render_source,
413					I915_GEM_DOMAIN_RENDER, 0,
414					0);
415
416		ADVANCE_BATCH();
417	}
418}
419
420static void intel_uxa_done(PixmapPtr pixmap)
421{
422	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
423	intel_screen_private *intel = intel_get_screen_private(scrn);
424
425	if (INTEL_INFO(intel)->gen >= 060) {
426		/* workaround a random BLT hang */
427		BEGIN_BATCH_BLT(3);
428		OUT_BATCH(XY_SETUP_CLIP_BLT_CMD | (3 - 2));
429		OUT_BATCH(0);
430		OUT_BATCH(0);
431		ADVANCE_BATCH();
432	}
433
434	intel_uxa_debug_flush(scrn);
435}
436
437/**
438 * Do any cleanup from the Composite operation.
439 *
440 * This is shared between i830 through i965.
441 */
442static void i830_done_composite(PixmapPtr dest)
443{
444	ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen);
445	intel_screen_private *intel = intel_get_screen_private(scrn);
446
447	if (intel->vertex_flush)
448		intel->vertex_flush(intel);
449
450	intel_uxa_debug_flush(scrn);
451}
452
453#define xFixedToFloat(val) \
454	((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0))
455
456static Bool
457_intel_transform_point(PictTransformPtr transform,
458		       float x, float y, float result[3])
459{
460	int j;
461
462	for (j = 0; j < 3; j++) {
463		result[j] = (xFixedToFloat(transform->matrix[j][0]) * x +
464			     xFixedToFloat(transform->matrix[j][1]) * y +
465			     xFixedToFloat(transform->matrix[j][2]));
466	}
467	if (!result[2])
468		return FALSE;
469	return TRUE;
470}
471
472/**
473 * Returns the floating-point coordinates transformed by the given transform.
474 *
475 * transform may be null.
476 */
477Bool
478intel_uxa_get_transformed_coordinates(int x, int y, PictTransformPtr transform,
479				  float *x_out, float *y_out)
480{
481	if (transform == NULL) {
482		*x_out = x;
483		*y_out = y;
484	} else {
485		float result[3];
486
487		if (!_intel_transform_point(transform,
488					    x, y,
489					    result))
490			return FALSE;
491		*x_out = result[0] / result[2];
492		*y_out = result[1] / result[2];
493	}
494	return TRUE;
495}
496
497/**
498 * Returns the un-normalized floating-point coordinates transformed by the given transform.
499 *
500 * transform may be null.
501 */
502Bool
503intel_uxa_get_transformed_coordinates_3d(int x, int y, PictTransformPtr transform,
504				     float *x_out, float *y_out, float *w_out)
505{
506	if (transform == NULL) {
507		*x_out = x;
508		*y_out = y;
509		*w_out = 1;
510	} else {
511		float result[3];
512
513		if (!_intel_transform_point(transform,
514					    x, y,
515					    result))
516			return FALSE;
517		*x_out = result[0];
518		*y_out = result[1];
519		*w_out = result[2];
520	}
521	return TRUE;
522}
523
524/**
525 * Returns whether the provided transform is affine.
526 *
527 * transform may be null.
528 */
529Bool intel_uxa_transform_is_affine(PictTransformPtr t)
530{
531	if (t == NULL)
532		return TRUE;
533	return t->matrix[2][0] == 0 && t->matrix[2][1] == 0;
534}
535
536dri_bo *intel_uxa_get_pixmap_bo(PixmapPtr pixmap)
537{
538	struct intel_uxa_pixmap *intel;
539
540	intel = intel_uxa_get_pixmap_private(pixmap);
541	if (intel == NULL)
542		return NULL;
543
544	return intel->bo;
545}
546
547static unsigned intel_get_tile_width(intel_screen_private *intel, int tiling, int pitch)
548{
549	unsigned long tile_width;
550
551	if (tiling == I915_TILING_NONE)
552		return 4;
553
554	tile_width = (tiling == I915_TILING_Y) ? 128 : 512;
555	if (INTEL_INFO(intel)->gen >= 040)
556		return tile_width;
557
558	while (tile_width < pitch)
559		tile_width <<= 1;
560
561	return tile_width;
562}
563
564void intel_uxa_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo)
565{
566	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
567	intel_screen_private *intel = intel_get_screen_private(scrn);
568	struct intel_uxa_pixmap *priv;
569
570	priv = intel_uxa_get_pixmap_private(pixmap);
571	if (priv == NULL && bo == NULL)
572		return;
573
574	if (priv != NULL) {
575		if (priv->bo == bo)
576			return;
577
578free_priv:
579		dri_bo_unreference(priv->bo);
580		list_del(&priv->batch);
581
582		free(priv);
583		priv = NULL;
584	}
585
586	if (bo != NULL) {
587		uint32_t tiling, swizzle_mode;
588		unsigned tile_width;
589		int size, stride;
590
591		priv = calloc(1, sizeof (struct intel_uxa_pixmap));
592		if (priv == NULL)
593			goto BAIL;
594
595		list_init(&priv->batch);
596
597		dri_bo_reference(bo);
598		priv->bo = bo;
599
600		if (drm_intel_bo_get_tiling(bo, &tiling, &swizzle_mode)) {
601			bo = NULL;
602			goto free_priv;
603		}
604
605		priv->tiling = tiling;
606		priv->busy = -1;
607		priv->offscreen = 1;
608
609		stride = (pixmap->drawable.width * pixmap->drawable.bitsPerPixel + 7) / 8;
610		tile_width = intel_get_tile_width(intel, tiling, stride);
611		stride = ALIGN(stride, tile_width);
612
613		if (intel_pixmap_pitch(pixmap) < stride ||
614		    intel_pixmap_pitch(pixmap) & (tile_width - 1) ||
615		    intel_pixmap_pitch(pixmap) >= KB(32)) {
616			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
617				   "%s: stride on buffer object does not match constraints: stride=%d, must be greater than %d, but less than %d, and have alignment at least %d\n",
618				   __FUNCTION__, intel_pixmap_pitch(pixmap), stride, KB(32), tile_width);
619			bo = NULL;
620			goto free_priv;
621		}
622
623		if (tiling != I915_TILING_NONE) {
624			int height;
625
626			if (IS_GEN2(intel))
627				height = 16;
628			else if (tiling == I915_TILING_X)
629				height = 8;
630			else
631				height = 32;
632
633			height = ALIGN(pixmap->drawable.height, height);
634			size = intel_get_fence_size(intel, intel_pixmap_pitch(pixmap) * height);
635		} else
636			size = intel_pixmap_pitch(pixmap) * pixmap->drawable.height;
637
638		if (bo->size < size || bo->size > intel->max_bo_size) {
639			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
640				   "%s: size of buffer object does not match constraints: size=%ld, must be greater than %d, but less than %d\n",
641				   __FUNCTION__, (long)bo->size, size, intel->max_bo_size);
642			bo = NULL;
643			goto free_priv;
644		}
645	}
646
647  BAIL:
648	intel_uxa_set_pixmap_private(pixmap, priv);
649}
650
651static Bool intel_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access)
652{
653	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
654	intel_screen_private *intel = intel_get_screen_private(scrn);
655	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap);
656	dri_bo *bo = priv->bo;
657	int ret;
658
659	/* When falling back to swrast, flush all pending operations */
660	if (access == UXA_ACCESS_RW || priv->dirty)
661		intel_batch_submit(scrn);
662
663	assert(bo->size <= intel->max_gtt_map_size);
664	ret = drm_intel_gem_bo_map_gtt(bo);
665	if (ret) {
666		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
667			   "%s: bo map (use gtt? %d, access %d) failed: %s\n",
668			   __FUNCTION__,
669			   priv->tiling || bo->size <= intel->max_gtt_map_size,
670			   access,
671			   strerror(-ret));
672		return FALSE;
673	}
674
675	pixmap->devPrivate.ptr = bo->virtual;
676	priv->busy = 0;
677
678	return TRUE;
679}
680
681static void intel_uxa_finish_access(PixmapPtr pixmap, uxa_access_t access)
682{
683	struct intel_uxa_pixmap *priv;
684
685	priv = intel_uxa_get_pixmap_private(pixmap);
686	if (priv == NULL)
687		return;
688
689	drm_intel_gem_bo_unmap_gtt(priv->bo);
690	pixmap->devPrivate.ptr = NULL;
691}
692
693static Bool intel_uxa_pixmap_put_image(PixmapPtr pixmap,
694				       char *src, int src_pitch,
695				       int x, int y, int w, int h)
696{
697	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap);
698	int stride = intel_pixmap_pitch(pixmap);
699	int cpp = pixmap->drawable.bitsPerPixel/8;
700	int ret = FALSE;
701
702	if (priv == NULL || priv->bo == NULL)
703		return FALSE;
704
705	if (priv->tiling == I915_TILING_NONE &&
706	    (h == 1 || (src_pitch == stride && w == pixmap->drawable.width))) {
707		return drm_intel_bo_subdata(priv->bo, y*stride + x*cpp, stride*(h-1) + w*cpp, src) == 0;
708	} else if (drm_intel_gem_bo_map_gtt(priv->bo) == 0) {
709		char *dst = priv->bo->virtual;
710		int row_length = w * cpp;
711		int num_rows = h;
712		if (row_length == src_pitch && src_pitch == stride)
713			num_rows = 1, row_length *= h;
714		dst += y * stride + x * cpp;
715		do {
716			memcpy (dst, src, row_length);
717			src += src_pitch;
718			dst += stride;
719		} while (--num_rows);
720		drm_intel_gem_bo_unmap_gtt(priv->bo);
721		ret = TRUE;
722	}
723
724	return ret;
725}
726
727static Bool intel_uxa_put_image(PixmapPtr pixmap,
728				int x, int y,
729				int w, int h,
730				char *src, int src_pitch)
731{
732	struct intel_uxa_pixmap *priv;
733
734	priv = intel_uxa_get_pixmap_private(pixmap);
735	if (!intel_uxa_pixmap_is_busy(priv)) {
736		/* bo is not busy so can be replaced without a stall, upload in-place. */
737		return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, x, y, w, h);
738	} else {
739		ScreenPtr screen = pixmap->drawable.pScreen;
740
741		if (!priv->pinned &&
742		    x == 0 && y == 0 &&
743		    w == pixmap->drawable.width &&
744		    h == pixmap->drawable.height)
745		{
746			intel_screen_private *intel = intel_get_screen_private(xf86ScreenToScrn(screen));
747			uint32_t tiling = priv->tiling;
748			int size, stride;
749			dri_bo *bo;
750
751			/* Replace busy bo. */
752			size = intel_compute_size(intel,
753                                                  w, h,
754                                                  pixmap->drawable.bitsPerPixel, pixmap->usage_hint,
755                                                  &tiling, &stride);
756			if (size > intel->max_gtt_map_size)
757				return FALSE;
758
759			bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0);
760			if (bo == NULL)
761				return FALSE;
762
763			if (tiling != I915_TILING_NONE)
764				drm_intel_bo_set_tiling(bo, &tiling, stride);
765			priv->tiling = tiling;
766
767			screen->ModifyPixmapHeader(pixmap,
768						   w, h,
769						   0, 0,
770						   stride, NULL);
771			intel_uxa_set_pixmap_bo(pixmap, bo);
772			dri_bo_unreference(bo);
773
774			return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, 0, 0, w, h);
775		}
776		else
777		{
778			PixmapPtr scratch;
779			Bool ret;
780
781			/* Upload to a linear buffer and queue a blit.  */
782			scratch = (*screen->CreatePixmap)(screen, w, h,
783							  pixmap->drawable.depth,
784							  UXA_CREATE_PIXMAP_FOR_MAP);
785			if (!scratch)
786				return FALSE;
787
788			if (!intel_uxa_pixmap_is_offscreen(scratch)) {
789				screen->DestroyPixmap(scratch);
790				return FALSE;
791			}
792
793			ret = intel_uxa_pixmap_put_image(scratch, src, src_pitch, 0, 0, w, h);
794			if (ret) {
795				GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen);
796				if (gc) {
797					ValidateGC(&pixmap->drawable, gc);
798
799					(*gc->ops->CopyArea)(&scratch->drawable,
800							     &pixmap->drawable,
801							     gc, 0, 0, w, h, x, y);
802
803					FreeScratchGC(gc);
804				} else
805					ret = FALSE;
806			}
807
808			(*screen->DestroyPixmap)(scratch);
809			return ret;
810		}
811	}
812}
813
814static Bool intel_uxa_pixmap_get_image(PixmapPtr pixmap,
815				       int x, int y, int w, int h,
816				       char *dst, int dst_pitch)
817{
818	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap);
819	int stride = intel_pixmap_pitch(pixmap);
820	int cpp = pixmap->drawable.bitsPerPixel/8;
821
822	/* assert(priv->tiling == I915_TILING_NONE); */
823	if (h == 1 || (dst_pitch == stride && w == pixmap->drawable.width)) {
824		return drm_intel_bo_get_subdata(priv->bo, y*stride + x*cpp, (h-1)*stride + w*cpp, dst) == 0;
825	} else {
826		char *src;
827
828		if (drm_intel_gem_bo_map_gtt(priv->bo))
829		    return FALSE;
830
831		src = (char *) priv->bo->virtual + y * stride + x * cpp;
832		w *= cpp;
833		do {
834			memcpy(dst, src, w);
835			src += stride;
836			dst += dst_pitch;
837		} while (--h);
838
839		drm_intel_gem_bo_unmap_gtt(priv->bo);
840
841		return TRUE;
842	}
843}
844
845static Bool intel_uxa_get_image(PixmapPtr pixmap,
846				int x, int y,
847				int w, int h,
848				char *dst, int dst_pitch)
849{
850	struct intel_uxa_pixmap *priv;
851	PixmapPtr scratch = NULL;
852	Bool ret;
853
854	/* The presumption is that we wish to keep the target hot, so
855	 * copy to a new bo and move that to the CPU in preference to
856	 * causing ping-pong of the original.
857	 *
858	 * Also the gpu is much faster at detiling.
859	 */
860
861	priv = intel_uxa_get_pixmap_private(pixmap);
862	if (intel_uxa_pixmap_is_busy(priv) || priv->tiling != I915_TILING_NONE) {
863		ScreenPtr screen = pixmap->drawable.pScreen;
864		GCPtr gc;
865
866		/* Copy to a linear buffer and pull.  */
867		scratch = screen->CreatePixmap(screen, w, h,
868					       pixmap->drawable.depth,
869					       INTEL_CREATE_PIXMAP_TILING_NONE);
870		if (!scratch)
871			return FALSE;
872
873		if (!intel_uxa_pixmap_is_offscreen(scratch)) {
874			screen->DestroyPixmap(scratch);
875			return FALSE;
876		}
877
878		gc = GetScratchGC(pixmap->drawable.depth, screen);
879		if (!gc) {
880			screen->DestroyPixmap(scratch);
881			return FALSE;
882		}
883
884		ValidateGC(&pixmap->drawable, gc);
885
886		gc->ops->CopyArea(&pixmap->drawable,
887				  &scratch->drawable,
888				  gc, x, y, w, h, 0, 0);
889
890		FreeScratchGC(gc);
891
892		intel_batch_submit(xf86ScreenToScrn(screen));
893
894		x = y = 0;
895		pixmap = scratch;
896	}
897
898	ret = intel_uxa_pixmap_get_image(pixmap, x, y, w, h, dst, dst_pitch);
899
900	if (scratch)
901		scratch->drawable.pScreen->DestroyPixmap(scratch);
902
903	return ret;
904}
905
906static CARD32 intel_cache_expire(OsTimerPtr timer, CARD32 now, pointer data)
907{
908	intel_screen_private *intel = data;
909
910	/* We just want to create and destroy a bo as this causes libdrm
911	 * to reap its caches. However, since we can't remove that buffer
912	 * from the cache due to its own activity, we want to use something
913	 * that we know we will reuse later. The most frequently reused buffer
914	 * we have is the batchbuffer, and the best way to trigger its
915	 * reallocation is to submit a flush.
916	 */
917	intel_batch_emit_flush(intel->scrn);
918	intel_batch_submit(intel->scrn);
919
920	return 0;
921}
922
923static void intel_flush_rendering(intel_screen_private *intel)
924{
925	if (intel->needs_flush == 0)
926		return;
927
928	if (intel->has_kernel_flush) {
929		intel_batch_submit(intel->scrn);
930		drm_intel_bo_busy(intel->front_buffer);
931	} else {
932		intel_batch_emit_flush(intel->scrn);
933		intel_batch_submit(intel->scrn);
934	}
935
936	intel->cache_expire = TimerSet(intel->cache_expire, 0, 3000,
937				       intel_cache_expire, intel);
938
939	intel->needs_flush = 0;
940}
941
942static void intel_throttle(intel_screen_private *intel)
943{
944	drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE);
945}
946
947void intel_uxa_block_handler(intel_screen_private *intel)
948{
949	/* Emit a flush of the rendering cache, or on the 965
950	 * and beyond rendering results may not hit the
951	 * framebuffer until significantly later.
952	 */
953	intel_flush_rendering(intel);
954	intel_throttle(intel);
955}
956
957static PixmapPtr
958intel_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth,
959			unsigned usage)
960{
961	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
962	intel_screen_private *intel = intel_get_screen_private(scrn);
963	struct intel_uxa_pixmap *priv;
964	PixmapPtr pixmap, new_pixmap = NULL;
965
966	if (w > 32767 || h > 32767)
967		return NullPixmap;
968
969	if (depth == 1 || intel->force_fallback)
970		return fbCreatePixmap(screen, w, h, depth, usage);
971
972	if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32)
973		return fbCreatePixmap(screen, w, h, depth, usage);
974
975	pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
976	if (pixmap == NullPixmap)
977		return pixmap;
978
979	if (w && h) {
980		unsigned int size, tiling;
981		int stride;
982
983		/* Always attempt to tile, compute_size() will remove the
984		 * tiling for pixmaps that are either too large or too small
985		 * to be effectively tiled.
986		 */
987		tiling = I915_TILING_X;
988		if (usage & INTEL_CREATE_PIXMAP_TILING_Y)
989			tiling = I915_TILING_Y;
990		if (usage == UXA_CREATE_PIXMAP_FOR_MAP || usage & INTEL_CREATE_PIXMAP_TILING_NONE)
991			tiling = I915_TILING_NONE;
992
993#ifdef CREATE_PIXMAP_USAGE_SHARED
994		if (usage == CREATE_PIXMAP_USAGE_SHARED)
995			tiling = I915_TILING_NONE;
996#endif
997		/* if tiling is off force to none */
998		if (!intel->tiling)
999			tiling = I915_TILING_NONE;
1000
1001		if (tiling != I915_TILING_NONE && !(usage & INTEL_CREATE_PIXMAP_DRI2)) {
1002		    if (h <= 4)
1003			tiling = I915_TILING_NONE;
1004		    if (h <= 16 && tiling == I915_TILING_Y)
1005			tiling = I915_TILING_X;
1006		}
1007		size = intel_compute_size(intel,
1008                                          w, h, pixmap->drawable.bitsPerPixel, usage,
1009                                          &tiling, &stride);
1010
1011		/* Fail very large allocations.  Large BOs will tend to hit SW fallbacks
1012		 * frequently, and also will tend to fail to successfully map when doing
1013		 * SW fallbacks because we overcommit address space for BO access.
1014		 */
1015		if (size > intel->max_bo_size || stride >= KB(32))
1016			goto fallback_pixmap;
1017
1018		priv = calloc(1, sizeof (struct intel_uxa_pixmap));
1019		if (priv == NULL)
1020			goto fallback_pixmap;
1021
1022		if (usage == UXA_CREATE_PIXMAP_FOR_MAP) {
1023			priv->busy = 0;
1024			priv->bo = drm_intel_bo_alloc(intel->bufmgr,
1025						      "pixmap", size, 0);
1026		} else {
1027			priv->busy = -1;
1028			priv->bo = drm_intel_bo_alloc_for_render(intel->bufmgr,
1029								 "pixmap",
1030								 size, 0);
1031		}
1032		if (!priv->bo)
1033			goto fallback_priv;
1034
1035		if (tiling != I915_TILING_NONE)
1036			drm_intel_bo_set_tiling(priv->bo, &tiling, stride);
1037		priv->tiling = tiling;
1038		priv->offscreen = 1;
1039
1040		list_init(&priv->batch);
1041		intel_uxa_set_pixmap_private(pixmap, priv);
1042
1043		screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL);
1044	}
1045
1046	return pixmap;
1047
1048fallback_priv:
1049	free(priv);
1050fallback_pixmap:
1051	fbDestroyPixmap(pixmap);
1052	if (new_pixmap)
1053		return new_pixmap;
1054	else
1055		return fbCreatePixmap(screen, w, h, depth, usage);
1056}
1057
1058static Bool intel_uxa_destroy_pixmap(PixmapPtr pixmap)
1059{
1060	if (pixmap->refcnt == 1)
1061		intel_uxa_set_pixmap_bo(pixmap, NULL);
1062	fbDestroyPixmap(pixmap);
1063	return TRUE;
1064}
1065
1066Bool intel_uxa_create_screen_resources(ScreenPtr screen)
1067{
1068	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1069	PixmapPtr pixmap;
1070	intel_screen_private *intel = intel_get_screen_private(scrn);
1071	dri_bo *bo = intel->front_buffer;
1072	int old_width, old_height, old_pitch;
1073
1074	if (!uxa_resources_init(screen))
1075		return FALSE;
1076
1077	if (drm_intel_gem_bo_map_gtt(bo))
1078		return FALSE;
1079
1080	pixmap = screen->GetScreenPixmap(screen);
1081	old_width = pixmap->drawable.width;
1082	old_height = pixmap->drawable.height;
1083	old_pitch = pixmap->devKind;
1084
1085	if (!screen->ModifyPixmapHeader(pixmap,
1086					scrn->virtualX,
1087					scrn->virtualY,
1088					-1, -1,
1089					intel->front_pitch,
1090					NULL))
1091		return FALSE;
1092
1093	intel_uxa_set_pixmap_bo(pixmap, bo);
1094	if (intel_uxa_get_pixmap_private(pixmap) == NULL)
1095		goto err;
1096
1097	intel_uxa_get_pixmap_private(pixmap)->pinned |= PIN_SCANOUT;
1098	scrn->displayWidth = intel->front_pitch / intel->cpp;
1099
1100	return TRUE;
1101
1102err:
1103	screen->ModifyPixmapHeader(pixmap,
1104				   old_width, old_height, -1, -1, old_pitch, NULL);
1105	return FALSE;
1106}
1107
1108#ifdef CREATE_PIXMAP_USAGE_SHARED
1109static Bool
1110intel_uxa_share_pixmap_backing(PixmapPtr ppix, ScreenPtr slave, void **fd_handle)
1111{
1112	ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen);
1113	intel_screen_private *intel = intel_get_screen_private(scrn);
1114	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(ppix);
1115	unsigned int size, tiling, swizzle;
1116	dri_bo *bo = intel_uxa_get_pixmap_bo(ppix), *newbo;
1117	int stride;
1118	int handle;
1119
1120	if (drm_intel_bo_references(intel->batch_bo, bo))
1121		intel_batch_submit(intel->scrn);
1122
1123	drm_intel_bo_get_tiling(bo, &tiling, &swizzle);
1124
1125	if (tiling == I915_TILING_X) {
1126		if (priv->pinned)
1127			return FALSE;
1128
1129	        tiling = I915_TILING_NONE;
1130
1131		size = intel_compute_size(intel,
1132                                          ppix->drawable.width, ppix->drawable.height,
1133                                          ppix->drawable.bitsPerPixel, INTEL_CREATE_PIXMAP_DRI2,
1134                                          &tiling, &stride);
1135
1136		newbo = drm_intel_bo_alloc_for_render(intel->bufmgr,
1137						      "pixmap",
1138						      size, 0);
1139
1140		if (tiling != I915_TILING_NONE)
1141			drm_intel_bo_set_tiling(newbo, &tiling, stride);
1142		priv->tiling = tiling;
1143		intel_uxa_set_pixmap_bo(ppix, newbo);
1144
1145		ppix->drawable.pScreen->ModifyPixmapHeader(ppix, ppix->drawable.width,
1146					   ppix->drawable.height, 0, 0,
1147					   stride, NULL);
1148		bo = newbo;
1149	}
1150	drm_intel_bo_get_tiling(bo, &tiling, &swizzle);
1151	drm_intel_bo_gem_export_to_prime(bo, &handle);
1152	priv->pinned |= PIN_PRIME;
1153
1154	*fd_handle = (void *)(long)handle;
1155	return TRUE;
1156}
1157
1158static Bool
1159intel_uxa_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle)
1160{
1161	ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen);
1162	intel_screen_private *intel = intel_get_screen_private(scrn);
1163	dri_bo *bo;
1164	int ihandle = (int)(long)fd_handle;
1165
1166	/* force untiled for now */
1167	bo = drm_intel_bo_gem_create_from_prime(intel->bufmgr, ihandle, 0);
1168	if (!bo)
1169		return FALSE;
1170
1171	intel_uxa_set_pixmap_bo(ppix, bo);
1172	close(ihandle);
1173	return TRUE;
1174}
1175#endif
1176
1177static void
1178intel_limits_init(intel_screen_private *intel)
1179{
1180	/* Limits are described in the BLT engine chapter under Graphics Data Size
1181	 * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
1182	 * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
1183	 *
1184	 * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
1185	 *
1186	 * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
1187	 * i965 limits 3D surface to 4kB-aligned offset if tiled.
1188	 * i965 limits 3D surfaces to w,h of ?,8192.
1189	 * i965 limits 3D surface to pitch of 1B - 128kB.
1190	 * i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
1191	 * i965 limits 3D surface pitch alignment to 512B if tiled.
1192	 * i965 limits 3D destination drawing rect to w,h of 8192,8192.
1193	 *
1194	 * i915 limits 3D textures to 4B-aligned offset if un-tiled.
1195	 * i915 limits 3D textures to ~4kB-aligned offset if tiled.
1196	 * i915 limits 3D textures to width,height of 2048,2048.
1197	 * i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
1198	 * i915 limits 3D destination to ~4kB-aligned offset if tiled.
1199	 * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
1200	 * i915 limits 3D destination to pitch 64B-aligned if used with depth.
1201	 * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
1202	 * i915 limits 3D destination to POT aligned pitch if tiled.
1203	 * i915 limits 3D destination drawing rect to w,h of 2048,2048.
1204	 *
1205	 * i845 limits 3D textures to 4B-aligned offset if un-tiled.
1206	 * i845 limits 3D textures to ~4kB-aligned offset if tiled.
1207	 * i845 limits 3D textures to width,height of 2048,2048.
1208	 * i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
1209	 * i845 limits 3D destination to 4B-aligned offset if un-tiled.
1210	 * i845 limits 3D destination to ~4kB-aligned offset if tiled.
1211	 * i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
1212	 * i845 limits 3D destination drawing rect to w,h of 2048,2048.
1213	 *
1214	 * For the tiled issues, the only tiled buffer we draw to should be
1215	 * the front, which will have an appropriate pitch/offset already set up,
1216	 * so UXA doesn't need to worry.
1217	 */
1218	if (INTEL_INFO(intel)->gen >= 040) {
1219		intel->accel_pixmap_offset_alignment = 4 * 2;
1220		intel->accel_max_x = 8192;
1221		intel->accel_max_y = 8192;
1222	} else {
1223		intel->accel_pixmap_offset_alignment = 4;
1224		intel->accel_max_x = 2048;
1225		intel->accel_max_y = 2048;
1226	}
1227}
1228
1229static Bool intel_option_accel_none(intel_screen_private *intel)
1230{
1231	const char *s;
1232
1233	s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD);
1234	if (s == NULL)
1235		return IS_DEFAULT_ACCEL_METHOD(NOACCEL);
1236
1237	return strcasecmp(s, "none") == 0;
1238}
1239
1240static Bool intel_option_accel_blt(intel_screen_private *intel)
1241{
1242	const char *s;
1243
1244	s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD);
1245	if (s == NULL)
1246		return FALSE;
1247
1248	return strcasecmp(s, "blt") == 0;
1249}
1250
1251/**
1252 * Intialiazes the hardware for the 3D pipeline use in the 2D driver.
1253 *
1254 * Some state caching is performed to avoid redundant state emits.  This
1255 * function is also responsible for marking the state as clobbered for DRI
1256 * clients.
1257 */
1258void IntelEmitInvarientState(ScrnInfoPtr scrn)
1259{
1260	intel_screen_private *intel = intel_get_screen_private(scrn);
1261
1262	/* If we've emitted our state since the last clobber by another client,
1263	 * skip it.
1264	 */
1265	if (intel->last_3d != LAST_3D_OTHER)
1266		return;
1267
1268	if (IS_GEN2(intel))
1269		I830EmitInvarientState(scrn);
1270	else if IS_GEN3(intel)
1271		I915EmitInvarientState(scrn);
1272}
1273
1274Bool intel_uxa_init(ScreenPtr screen)
1275{
1276	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1277	intel_screen_private *intel = intel_get_screen_private(scrn);
1278
1279	intel_batch_init(scrn);
1280
1281	if (INTEL_INFO(intel)->gen >= 040 && INTEL_INFO(intel)->gen < 0100)
1282		gen4_render_state_init(scrn);
1283
1284#if HAS_DIXREGISTERPRIVATEKEY
1285	if (!dixRegisterPrivateKey(&uxa_pixmap_index, PRIVATE_PIXMAP, 0))
1286#else
1287	if (!dixRequestPrivate(&uxa_pixmap_index, 0))
1288#endif
1289		return FALSE;
1290
1291	intel_limits_init(intel);
1292
1293	intel->uxa_driver = uxa_driver_alloc();
1294	if (intel->uxa_driver == NULL)
1295		return FALSE;
1296
1297	memset(intel->uxa_driver, 0, sizeof(*intel->uxa_driver));
1298
1299	intel->uxa_driver->uxa_major = 1;
1300	intel->uxa_driver->uxa_minor = 0;
1301
1302	intel->prim_offset = 0;
1303	intel->vertex_count = 0;
1304	intel->vertex_offset = 0;
1305	intel->vertex_used = 0;
1306	intel->floats_per_vertex = 0;
1307	intel->last_floats_per_vertex = 0;
1308	intel->vertex_bo = NULL;
1309	intel->surface_used = 0;
1310	intel->surface_reloc = 0;
1311
1312	/* Solid fill */
1313	intel->uxa_driver->check_solid = intel_uxa_check_solid;
1314	intel->uxa_driver->prepare_solid = intel_uxa_prepare_solid;
1315	intel->uxa_driver->solid = intel_uxa_solid;
1316	intel->uxa_driver->done_solid = intel_uxa_done;
1317
1318	/* Copy */
1319	intel->uxa_driver->check_copy = intel_uxa_check_copy;
1320	intel->uxa_driver->prepare_copy = intel_uxa_prepare_copy;
1321	intel->uxa_driver->copy = intel_uxa_copy;
1322	intel->uxa_driver->done_copy = intel_uxa_done;
1323
1324	/* Composite */
1325	if (intel_option_accel_blt(intel)) {
1326	} else if (INTEL_INFO(intel)->gen < 030) {
1327		intel->uxa_driver->check_composite = i830_check_composite;
1328		intel->uxa_driver->check_composite_target = i830_check_composite_target;
1329		intel->uxa_driver->check_composite_texture = i830_check_composite_texture;
1330		intel->uxa_driver->prepare_composite = i830_prepare_composite;
1331		intel->uxa_driver->composite = i830_composite;
1332		intel->uxa_driver->done_composite = i830_done_composite;
1333
1334		intel->vertex_flush = i830_vertex_flush;
1335		intel->batch_commit_notify = i830_batch_commit_notify;
1336	} else if (INTEL_INFO(intel)->gen < 040) {
1337		intel->uxa_driver->check_composite = i915_check_composite;
1338		intel->uxa_driver->check_composite_target = i915_check_composite_target;
1339		intel->uxa_driver->check_composite_texture = i915_check_composite_texture;
1340		intel->uxa_driver->prepare_composite = i915_prepare_composite;
1341		intel->uxa_driver->composite = i915_composite;
1342		intel->uxa_driver->done_composite = i830_done_composite;
1343
1344		intel->vertex_flush = i915_vertex_flush;
1345		intel->batch_commit_notify = i915_batch_commit_notify;
1346	} else if (INTEL_INFO(intel)->gen < 0100) {
1347		intel->uxa_driver->check_composite = i965_check_composite;
1348		intel->uxa_driver->check_composite_texture = i965_check_composite_texture;
1349		intel->uxa_driver->prepare_composite = i965_prepare_composite;
1350		intel->uxa_driver->composite = i965_composite;
1351		intel->uxa_driver->done_composite = i830_done_composite;
1352
1353		intel->vertex_flush = i965_vertex_flush;
1354		intel->batch_flush = i965_batch_flush;
1355		intel->batch_commit_notify = i965_batch_commit_notify;
1356
1357		if (INTEL_INFO(intel)->gen < 050) {
1358			intel->context_switch = gen4_context_switch;
1359		} else if (INTEL_INFO(intel)->gen < 060) {
1360			intel->context_switch = gen5_context_switch;
1361		} else {
1362			intel->context_switch = gen6_context_switch;
1363		}
1364	}
1365
1366	/* PutImage */
1367	intel->uxa_driver->put_image = intel_uxa_put_image;
1368	intel->uxa_driver->get_image = intel_uxa_get_image;
1369
1370	intel->uxa_driver->prepare_access = intel_uxa_prepare_access;
1371	intel->uxa_driver->finish_access = intel_uxa_finish_access;
1372	intel->uxa_driver->pixmap_is_offscreen = intel_uxa_pixmap_is_offscreen;
1373
1374	screen->CreatePixmap = intel_uxa_create_pixmap;
1375	screen->DestroyPixmap = intel_uxa_destroy_pixmap;
1376
1377#ifdef CREATE_PIXMAP_USAGE_SHARED
1378	screen->SharePixmapBacking = intel_uxa_share_pixmap_backing;
1379	screen->SetSharedPixmapBacking = intel_uxa_set_shared_pixmap_backing;
1380#endif
1381
1382	if (!uxa_driver_init(screen, intel->uxa_driver)) {
1383		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1384			   "UXA initialization failed\n");
1385		free(intel->uxa_driver);
1386		return FALSE;
1387	}
1388
1389	if (intel_option_accel_none(intel))
1390		intel->force_fallback = 1;
1391
1392	uxa_set_fallback_debug(screen, intel->fallback_debug);
1393	uxa_set_force_fallback(screen, intel->force_fallback);
1394
1395	intel->flush_rendering = intel_flush_rendering;
1396	return TRUE;
1397}
1398