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