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