1 /**************************************************************************
2 
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4 All Rights Reserved.
5 Copyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org>
6   Based on code from i830_xaa.c.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sub license, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15 
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial portions
18 of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
24 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 SOFTWARE 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 
49 static 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 
68 static 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
88 DevPrivateKeyRec uxa_pixmap_index;
89 #else
90 int uxa_pixmap_index;
91 #endif
92 
93 static void
gen6_context_switch(intel_screen_private * intel,int new_mode)94 gen6_context_switch(intel_screen_private *intel,
95 		    int new_mode)
96 {
97 	intel_batch_submit(intel->scrn);
98 }
99 
100 static void
gen5_context_switch(intel_screen_private * intel,int new_mode)101 gen5_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 
121 static void
gen4_context_switch(intel_screen_private * intel,int new_mode)122 gen4_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 
132 Bool
intel_uxa_get_aperture_space(ScrnInfoPtr scrn,drm_intel_bo ** bo_table,int num_bos)133 intel_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 
157 static Bool
intel_uxa_check_solid(DrawablePtr drawable,int alu,Pixel planemask)158 intel_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 static Bool
intel_uxa_check_bo_tiling(intel_screen_private * intel,PixmapPtr pixmap,unsigned * tiling_out)180 intel_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  */
200 static Bool
intel_uxa_prepare_solid(PixmapPtr pixmap,int alu,Pixel planemask,Pixel fg)201 intel_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 
intel_uxa_solid(PixmapPtr pixmap,int x1,int y1,int x2,int y2)237 static 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  */
290 static Bool
intel_uxa_check_copy(PixmapPtr source,PixmapPtr dest,int alu,Pixel planemask)291 intel_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 
322 static Bool
intel_uxa_prepare_copy(PixmapPtr source,PixmapPtr dest,int xdir,int ydir,int alu,Pixel planemask)323 intel_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 
358 static void
intel_uxa_copy(PixmapPtr dest,int src_x1,int src_y1,int dst_x1,int dst_y1,int w,int h)359 intel_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 
intel_uxa_done(PixmapPtr pixmap)445 static 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  */
i830_done_composite(PixmapPtr dest)467 static 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 
481 static Bool
_intel_transform_point(PictTransformPtr transform,float x,float y,float result[3])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  */
502 Bool
intel_uxa_get_transformed_coordinates(int x,int y,PictTransformPtr transform,float * x_out,float * y_out)503 intel_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  */
527 Bool
intel_uxa_get_transformed_coordinates_3d(int x,int y,PictTransformPtr transform,float * x_out,float * y_out,float * w_out)528 intel_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  */
intel_uxa_transform_is_affine(PictTransformPtr t)554 Bool 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 
intel_uxa_get_pixmap_bo(PixmapPtr pixmap)561 dri_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 
intel_get_tile_width(intel_screen_private * intel,int tiling,int pitch)572 static 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 
intel_uxa_set_pixmap_bo(PixmapPtr pixmap,dri_bo * bo)589 void 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 
603 free_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 
intel_uxa_prepare_access(PixmapPtr pixmap,uxa_access_t access)676 static 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 
intel_uxa_finish_access(PixmapPtr pixmap,uxa_access_t access)706 static 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 
intel_uxa_pixmap_put_image(PixmapPtr pixmap,char * src,int src_pitch,int x,int y,int w,int h)718 static 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 
intel_uxa_put_image(PixmapPtr pixmap,int x,int y,int w,int h,char * src,int src_pitch)752 static 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 
intel_uxa_pixmap_get_image(PixmapPtr pixmap,int x,int y,int w,int h,char * dst,int dst_pitch)839 static 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 
intel_uxa_get_image(PixmapPtr pixmap,int x,int y,int w,int h,char * dst,int dst_pitch)870 static 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 
intel_cache_expire(OsTimerPtr timer,CARD32 now,pointer data)931 static 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 
intel_flush_rendering(intel_screen_private * intel)948 static 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 
intel_throttle(intel_screen_private * intel)967 static void intel_throttle(intel_screen_private *intel)
968 {
969 	drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE);
970 }
971 
intel_uxa_block_handler(intel_screen_private * intel)972 void 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 
982 static PixmapPtr
intel_uxa_create_pixmap(ScreenPtr screen,int w,int h,int depth,unsigned usage)983 intel_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 
1073 fallback_priv:
1074 	free(priv);
1075 fallback_pixmap:
1076 	fbDestroyPixmap(pixmap);
1077 	if (new_pixmap)
1078 		return new_pixmap;
1079 	else
1080 		return fbCreatePixmap(screen, w, h, depth, usage);
1081 }
1082 
intel_uxa_destroy_pixmap(PixmapPtr pixmap)1083 static 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 
intel_uxa_create_screen_resources(ScreenPtr screen)1091 Bool 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 
1128 err:
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
1138 static Bool
intel_uxa_share_pixmap_backing(PixmapPtr ppix,ScreenPtr slave,void ** fd_handle)1139 intel_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 
1187 static Bool
intel_uxa_set_shared_pixmap_backing(PixmapPtr ppix,void * fd_handle)1188 intel_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 
1206 static void
intel_limits_init(intel_screen_private * intel)1207 intel_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 
intel_option_accel_none(intel_screen_private * intel)1258 static 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 
intel_option_accel_blt(intel_screen_private * intel)1269 static 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  */
IntelEmitInvarientState(ScrnInfoPtr scrn)1287 void 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 
intel_uxa_init(ScreenPtr screen)1303 Bool 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