1 /*
2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 *
26 * Author: Alan Hourihane <alanh@tungstengraphics.com>
27 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
28 *
29 */
30
31 #include "xorg_exa.h"
32 #include "xorg_tracker.h"
33 #include "xorg_composite.h"
34 #include "xorg_exa_tgsi.h"
35
36 #include <xorg-server.h>
37 #include <xf86.h>
38 #include <picturestr.h>
39 #include <picture.h>
40
41 #include "pipe/p_format.h"
42 #include "pipe/p_context.h"
43 #include "pipe/p_state.h"
44
45 #include "util/u_rect.h"
46 #include "util/u_math.h"
47 #include "util/u_debug.h"
48 #include "util/u_format.h"
49 #include "util/u_box.h"
50 #include "util/u_surface.h"
51
52 #define ROUND_UP_TEXTURES 1
53
54 static INLINE void
55 exa_debug_printf(const char *format, ...) _util_printf_format(1,2);
56
57 static INLINE void
exa_debug_printf(const char * format,...)58 exa_debug_printf(const char *format, ...)
59 {
60 #if 0
61 va_list ap;
62 va_start(ap, format);
63 _debug_vprintf(format, ap);
64 va_end(ap);
65 #else
66 (void) format; /* silence warning */
67 #endif
68 }
69
70 /*
71 * Helper functions
72 */
73 struct render_format_str {
74 int format;
75 const char *name;
76 };
77 static const struct render_format_str formats_info[] =
78 {
79 {PICT_a8r8g8b8, "PICT_a8r8g8b8"},
80 {PICT_x8r8g8b8, "PICT_x8r8g8b8"},
81 {PICT_a8b8g8r8, "PICT_a8b8g8r8"},
82 {PICT_x8b8g8r8, "PICT_x8b8g8r8"},
83 #ifdef PICT_TYPE_BGRA
84 {PICT_b8g8r8a8, "PICT_b8g8r8a8"},
85 {PICT_b8g8r8x8, "PICT_b8g8r8x8"},
86 {PICT_a2r10g10b10, "PICT_a2r10g10b10"},
87 {PICT_x2r10g10b10, "PICT_x2r10g10b10"},
88 {PICT_a2b10g10r10, "PICT_a2b10g10r10"},
89 {PICT_x2b10g10r10, "PICT_x2b10g10r10"},
90 #endif
91 {PICT_r8g8b8, "PICT_r8g8b8"},
92 {PICT_b8g8r8, "PICT_b8g8r8"},
93 {PICT_r5g6b5, "PICT_r5g6b5"},
94 {PICT_b5g6r5, "PICT_b5g6r5"},
95 {PICT_a1r5g5b5, "PICT_a1r5g5b5"},
96 {PICT_x1r5g5b5, "PICT_x1r5g5b5"},
97 {PICT_a1b5g5r5, "PICT_a1b5g5r5"},
98 {PICT_x1b5g5r5, "PICT_x1b5g5r5"},
99 {PICT_a4r4g4b4, "PICT_a4r4g4b4"},
100 {PICT_x4r4g4b4, "PICT_x4r4g4b4"},
101 {PICT_a4b4g4r4, "PICT_a4b4g4r4"},
102 {PICT_x4b4g4r4, "PICT_x4b4g4r4"},
103 {PICT_a8, "PICT_a8"},
104 {PICT_r3g3b2, "PICT_r3g3b2"},
105 {PICT_b2g3r3, "PICT_b2g3r3"},
106 {PICT_a2r2g2b2, "PICT_a2r2g2b2"},
107 {PICT_a2b2g2r2, "PICT_a2b2g2r2"},
108 {PICT_c8, "PICT_c8"},
109 {PICT_g8, "PICT_g8"},
110 {PICT_x4a4, "PICT_x4a4"},
111 {PICT_x4c4, "PICT_x4c4"},
112 {PICT_x4g4, "PICT_x4g4"},
113 {PICT_a4, "PICT_a4"},
114 {PICT_r1g2b1, "PICT_r1g2b1"},
115 {PICT_b1g2r1, "PICT_b1g2r1"},
116 {PICT_a1r1g1b1, "PICT_a1r1g1b1"},
117 {PICT_a1b1g1r1, "PICT_a1b1g1r1"},
118 {PICT_c4, "PICT_c4"},
119 {PICT_g4, "PICT_g4"},
120 {PICT_a1, "PICT_a1"},
121 {PICT_g1, "PICT_g1"}
122 };
render_format_name(int format)123 static const char *render_format_name(int format)
124 {
125 int i = 0;
126 for (i = 0; i < sizeof(formats_info)/sizeof(formats_info[0]); ++i) {
127 if (formats_info[i].format == format)
128 return formats_info[i].name;
129 }
130 return NULL;
131 }
132
133 static void
exa_get_pipe_format(int depth,enum pipe_format * format,int * bbp,int * picture_format)134 exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp, int *picture_format)
135 {
136 switch (depth) {
137 case 32:
138 *format = PIPE_FORMAT_B8G8R8A8_UNORM;
139 *picture_format = PICT_a8r8g8b8;
140 assert(*bbp == 32);
141 break;
142 case 24:
143 *format = PIPE_FORMAT_B8G8R8X8_UNORM;
144 *picture_format = PICT_x8r8g8b8;
145 assert(*bbp == 32);
146 break;
147 case 16:
148 *format = PIPE_FORMAT_B5G6R5_UNORM;
149 *picture_format = PICT_r5g6b5;
150 assert(*bbp == 16);
151 break;
152 case 15:
153 *format = PIPE_FORMAT_B5G5R5A1_UNORM;
154 *picture_format = PICT_x1r5g5b5;
155 assert(*bbp == 16);
156 break;
157 case 8:
158 *format = PIPE_FORMAT_L8_UNORM;
159 *picture_format = PICT_a8;
160 assert(*bbp == 8);
161 break;
162 case 4:
163 case 1:
164 *format = PIPE_FORMAT_B8G8R8A8_UNORM; /* bad bad bad */
165 break;
166 default:
167 assert(0);
168 break;
169 }
170 }
171
172
173 /*
174 * Static exported EXA functions
175 */
176
177 static void
ExaWaitMarker(ScreenPtr pScreen,int marker)178 ExaWaitMarker(ScreenPtr pScreen, int marker)
179 {
180 /* Nothing to do, handled in the PrepareAccess hook */
181 }
182
183 static int
ExaMarkSync(ScreenPtr pScreen)184 ExaMarkSync(ScreenPtr pScreen)
185 {
186 return 1;
187 }
188
189
190 /***********************************************************************
191 * Screen upload/download
192 */
193
194 static Bool
ExaDownloadFromScreen(PixmapPtr pPix,int x,int y,int w,int h,char * dst,int dst_pitch)195 ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst,
196 int dst_pitch)
197 {
198 ScreenPtr pScreen = pPix->drawable.pScreen;
199 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
200 modesettingPtr ms = modesettingPTR(pScrn);
201 struct exa_context *exa = ms->exa;
202 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
203 struct pipe_transfer *transfer;
204
205 if (!priv || !priv->tex)
206 return FALSE;
207
208 transfer = pipe_get_transfer(exa->pipe, priv->tex, 0, 0,
209 PIPE_TRANSFER_READ, x, y, w, h);
210 if (!transfer)
211 return FALSE;
212
213 exa_debug_printf("------ ExaDownloadFromScreen(%d, %d, %d, %d, %d)\n",
214 x, y, w, h, dst_pitch);
215
216 util_copy_rect((unsigned char*)dst, priv->tex->format, dst_pitch, 0, 0,
217 w, h, exa->pipe->transfer_map(exa->pipe, transfer),
218 transfer->stride, 0, 0);
219
220 exa->pipe->transfer_unmap(exa->pipe, transfer);
221 exa->pipe->transfer_destroy(exa->pipe, transfer);
222
223 return TRUE;
224 }
225
226 static Bool
ExaUploadToScreen(PixmapPtr pPix,int x,int y,int w,int h,char * src,int src_pitch)227 ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src,
228 int src_pitch)
229 {
230 ScreenPtr pScreen = pPix->drawable.pScreen;
231 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
232 modesettingPtr ms = modesettingPTR(pScrn);
233 struct exa_context *exa = ms->exa;
234 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
235 struct pipe_transfer *transfer;
236
237 if (!priv || !priv->tex)
238 return FALSE;
239
240 transfer = pipe_get_transfer(exa->pipe, priv->tex, 0, 0,
241 PIPE_TRANSFER_WRITE, x, y, w, h);
242 if (!transfer)
243 return FALSE;
244
245 exa_debug_printf("++++++ ExaUploadToScreen(%d, %d, %d, %d, %d)\n",
246 x, y, w, h, src_pitch);
247
248 util_copy_rect(exa->pipe->transfer_map(exa->pipe, transfer),
249 priv->tex->format, transfer->stride, 0, 0, w, h,
250 (unsigned char*)src, src_pitch, 0, 0);
251
252 exa->pipe->transfer_unmap(exa->pipe, transfer);
253 exa->pipe->transfer_destroy(exa->pipe, transfer);
254
255 return TRUE;
256 }
257
258 static Bool
ExaPrepareAccess(PixmapPtr pPix,int index)259 ExaPrepareAccess(PixmapPtr pPix, int index)
260 {
261 ScreenPtr pScreen = pPix->drawable.pScreen;
262 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
263 modesettingPtr ms = modesettingPTR(pScrn);
264 struct exa_context *exa = ms->exa;
265 struct exa_pixmap_priv *priv;
266
267 priv = exaGetPixmapDriverPrivate(pPix);
268
269 if (!priv)
270 return FALSE;
271
272 if (!priv->tex)
273 return FALSE;
274
275 exa_debug_printf("ExaPrepareAccess %d\n", index);
276
277 if (priv->map_count == 0)
278 {
279 assert(pPix->drawable.width <= priv->tex->width0);
280 assert(pPix->drawable.height <= priv->tex->height0);
281
282 priv->map_transfer =
283 pipe_get_transfer(exa->pipe, priv->tex, 0, 0,
284 #ifdef EXA_MIXED_PIXMAPS
285 PIPE_TRANSFER_MAP_DIRECTLY |
286 #endif
287 PIPE_TRANSFER_READ_WRITE,
288 0, 0,
289 pPix->drawable.width,
290 pPix->drawable.height );
291 if (!priv->map_transfer)
292 #ifdef EXA_MIXED_PIXMAPS
293 return FALSE;
294 #else
295 FatalError("failed to create transfer\n");
296 #endif
297
298 pPix->devPrivate.ptr =
299 exa->pipe->transfer_map(exa->pipe, priv->map_transfer);
300 pPix->devKind = priv->map_transfer->stride;
301 }
302
303 priv->map_count++;
304
305 exa_debug_printf("ExaPrepareAccess %d prepared\n", index);
306
307 return TRUE;
308 }
309
310 static void
ExaFinishAccess(PixmapPtr pPix,int index)311 ExaFinishAccess(PixmapPtr pPix, int index)
312 {
313 ScreenPtr pScreen = pPix->drawable.pScreen;
314 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
315 modesettingPtr ms = modesettingPTR(pScrn);
316 struct exa_context *exa = ms->exa;
317 struct exa_pixmap_priv *priv;
318 priv = exaGetPixmapDriverPrivate(pPix);
319
320 if (!priv)
321 return;
322
323 if (!priv->map_transfer)
324 return;
325
326 exa_debug_printf("ExaFinishAccess %d\n", index);
327
328 if (--priv->map_count == 0) {
329 assert(priv->map_transfer);
330 exa->pipe->transfer_unmap(exa->pipe, priv->map_transfer);
331 exa->pipe->transfer_destroy(exa->pipe, priv->map_transfer);
332 priv->map_transfer = NULL;
333 pPix->devPrivate.ptr = NULL;
334 }
335
336 exa_debug_printf("ExaFinishAccess %d finished\n", index);
337 }
338
339 /***********************************************************************
340 * Solid Fills
341 */
342
343 static Bool
ExaPrepareSolid(PixmapPtr pPixmap,int alu,Pixel planeMask,Pixel fg)344 ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
345 {
346 ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
347 modesettingPtr ms = modesettingPTR(pScrn);
348 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
349 struct exa_context *exa = ms->exa;
350
351 exa_debug_printf("ExaPrepareSolid(0x%x)\n", fg);
352
353 if (!exa->accel)
354 return FALSE;
355
356 if (!exa->pipe)
357 XORG_FALLBACK("accel not enabled");
358
359 if (!priv || !priv->tex)
360 XORG_FALLBACK("%s", !priv ? "!priv" : "!priv->tex");
361
362 if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
363 XORG_FALLBACK("planeMask is not solid");
364
365 if (alu != GXcopy)
366 XORG_FALLBACK("not GXcopy");
367
368 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
369 priv->tex->target, 0,
370 PIPE_BIND_RENDER_TARGET)) {
371 XORG_FALLBACK("format %s", util_format_name(priv->tex->format));
372 }
373
374 return xorg_solid_bind_state(exa, priv, fg);
375 }
376
377 static void
ExaSolid(PixmapPtr pPixmap,int x0,int y0,int x1,int y1)378 ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
379 {
380 ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
381 modesettingPtr ms = modesettingPTR(pScrn);
382 struct exa_context *exa = ms->exa;
383 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
384
385 exa_debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
386
387 if (x0 == 0 && y0 == 0 &&
388 x1 == pPixmap->drawable.width && y1 == pPixmap->drawable.height) {
389 union pipe_color_union solid_color;
390 solid_color.f[0] = exa->solid_color[0];
391 solid_color.f[1] = exa->solid_color[1];
392 solid_color.f[2] = exa->solid_color[2];
393 solid_color.f[3] = exa->solid_color[3];
394 exa->pipe->clear(exa->pipe, PIPE_CLEAR_COLOR, &solid_color, 0.0, 0);
395 return;
396 }
397
398 xorg_solid(exa, priv, x0, y0, x1, y1) ;
399 }
400
401
402 static void
ExaDoneSolid(PixmapPtr pPixmap)403 ExaDoneSolid(PixmapPtr pPixmap)
404 {
405 ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
406 modesettingPtr ms = modesettingPTR(pScrn);
407 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
408 struct exa_context *exa = ms->exa;
409
410 if (!priv)
411 return;
412
413 exa_debug_printf("ExaDoneSolid\n");
414 xorg_composite_done(exa);
415 exa_debug_printf("ExaDoneSolid done\n");
416 }
417
418 /***********************************************************************
419 * Copy Blits
420 */
421
422 static Bool
ExaPrepareCopy(PixmapPtr pSrcPixmap,PixmapPtr pDstPixmap,int xdir,int ydir,int alu,Pixel planeMask)423 ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
424 int ydir, int alu, Pixel planeMask)
425 {
426 ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
427 modesettingPtr ms = modesettingPTR(pScrn);
428 struct exa_context *exa = ms->exa;
429 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
430 struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
431
432 exa_debug_printf("ExaPrepareCopy\n");
433
434 if (!exa->accel)
435 return FALSE;
436
437 if (!exa->pipe)
438 XORG_FALLBACK("accel not enabled");
439
440 if (!priv || !priv->tex)
441 XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
442
443 if (!src_priv || !src_priv->tex)
444 XORG_FALLBACK("pSrc %s", !src_priv ? "!priv" : "!priv->tex");
445
446 if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
447 XORG_FALLBACK("planeMask is not solid");
448
449 if (alu != GXcopy)
450 XORG_FALLBACK("alu not GXcopy");
451
452 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
453 priv->tex->target, 0,
454 PIPE_BIND_RENDER_TARGET))
455 XORG_FALLBACK("pDst format %s", util_format_name(priv->tex->format));
456
457 if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format,
458 src_priv->tex->target, 0,
459 PIPE_BIND_SAMPLER_VIEW))
460 XORG_FALLBACK("pSrc format %s", util_format_name(src_priv->tex->format));
461
462 exa->copy.src = src_priv;
463 exa->copy.dst = priv;
464
465 return TRUE;
466 }
467
468 static void
ExaCopy(PixmapPtr pDstPixmap,int srcX,int srcY,int dstX,int dstY,int width,int height)469 ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
470 int width, int height)
471 {
472 ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
473 modesettingPtr ms = modesettingPTR(pScrn);
474 struct exa_context *exa = ms->exa;
475 struct pipe_box src_box;
476
477 exa_debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
478 srcX, srcY, dstX, dstY, width, height);
479
480 debug_assert(exaGetPixmapDriverPrivate(pDstPixmap) == exa->copy.dst);
481
482 u_box_2d(srcX, srcY, width, height, &src_box);
483
484 /* If source and destination overlap, we have to copy to/from a scratch
485 * pixmap.
486 */
487 if (exa->copy.dst == exa->copy.src &&
488 !((dstX + width) < srcX || dstX > (srcX + width) ||
489 (dstY + height) < srcY || dstY > (srcY + height))) {
490 struct exa_pixmap_priv *tmp_priv;
491
492 if (!exa->copy.tmp_pix) {
493 exa->copy.tmp_pix = pScrn->pScreen->CreatePixmap(pScrn->pScreen,
494 pDstPixmap->drawable.width,
495 pDstPixmap->drawable.height,
496 pDstPixmap->drawable.depth,
497 pDstPixmap->drawable.width);
498 exaMoveInPixmap(exa->copy.tmp_pix);
499 }
500
501 tmp_priv = exaGetPixmapDriverPrivate(exa->copy.tmp_pix);
502
503 exa->pipe->resource_copy_region( exa->pipe,
504 tmp_priv->tex,
505 0,
506 srcX, srcY, 0,
507 exa->copy.src->tex,
508 0, &src_box);
509 exa->pipe->resource_copy_region( exa->pipe,
510 exa->copy.dst->tex,
511 0,
512 dstX, dstY, 0,
513 tmp_priv->tex,
514 0, &src_box);
515 } else
516 exa->pipe->resource_copy_region( exa->pipe,
517 exa->copy.dst->tex,
518 0,
519 dstX, dstY, 0,
520 exa->copy.src->tex,
521 0, &src_box);
522 }
523
524 static void
ExaDoneCopy(PixmapPtr pPixmap)525 ExaDoneCopy(PixmapPtr pPixmap)
526 {
527 ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
528 modesettingPtr ms = modesettingPTR(pScrn);
529 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
530 struct exa_context *exa = ms->exa;
531
532 if (!priv)
533 return;
534
535 exa_debug_printf("ExaDoneCopy\n");
536
537 if (exa->copy.tmp_pix) {
538 pScrn->pScreen->DestroyPixmap(exa->copy.tmp_pix);
539 exa->copy.tmp_pix = NULL;
540 }
541 exa->copy.src = NULL;
542 exa->copy.dst = NULL;
543
544 exa_debug_printf("ExaDoneCopy done\n");
545 }
546
547
548
549 static Bool
picture_check_formats(struct exa_pixmap_priv * pSrc,PicturePtr pSrcPicture)550 picture_check_formats(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture)
551 {
552 if (pSrc->picture_format == pSrcPicture->format)
553 return TRUE;
554
555 if (pSrc->picture_format != PICT_a8r8g8b8)
556 return FALSE;
557
558 /* pSrc->picture_format == PICT_a8r8g8b8 */
559 switch (pSrcPicture->format) {
560 case PICT_a8r8g8b8:
561 case PICT_x8r8g8b8:
562 case PICT_a8b8g8r8:
563 case PICT_x8b8g8r8:
564 /* just treat these two as x8... */
565 case PICT_r8g8b8:
566 case PICT_b8g8r8:
567 return TRUE;
568 #ifdef PICT_TYPE_BGRA
569 case PICT_b8g8r8a8:
570 case PICT_b8g8r8x8:
571 return FALSE; /* does not support swizzleing the alpha channel yet */
572 case PICT_a2r10g10b10:
573 case PICT_x2r10g10b10:
574 case PICT_a2b10g10r10:
575 case PICT_x2b10g10r10:
576 return FALSE;
577 #endif
578 default:
579 return FALSE;
580 }
581 return FALSE;
582 }
583
584 /***********************************************************************
585 * Composite entrypoints
586 */
587
588 static Bool
ExaCheckComposite(int op,PicturePtr pSrcPicture,PicturePtr pMaskPicture,PicturePtr pDstPicture)589 ExaCheckComposite(int op,
590 PicturePtr pSrcPicture, PicturePtr pMaskPicture,
591 PicturePtr pDstPicture)
592 {
593 ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPicture->pDrawable->pScreen);
594 modesettingPtr ms = modesettingPTR(pScrn);
595 struct exa_context *exa = ms->exa;
596 Bool accelerated = exa->accel && xorg_composite_accelerated(op,
597 pSrcPicture,
598 pMaskPicture,
599 pDstPicture);
600
601 exa_debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
602 op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
603
604 return accelerated;
605 }
606
607
608 static Bool
ExaPrepareComposite(int op,PicturePtr pSrcPicture,PicturePtr pMaskPicture,PicturePtr pDstPicture,PixmapPtr pSrc,PixmapPtr pMask,PixmapPtr pDst)609 ExaPrepareComposite(int op, PicturePtr pSrcPicture,
610 PicturePtr pMaskPicture, PicturePtr pDstPicture,
611 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
612 {
613 ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
614 modesettingPtr ms = modesettingPTR(pScrn);
615 struct exa_context *exa = ms->exa;
616 struct exa_pixmap_priv *priv;
617
618 if (!exa->accel)
619 return FALSE;
620
621 exa_debug_printf("ExaPrepareComposite(%d, src=0x%p, mask=0x%p, dst=0x%p)\n",
622 op, pSrcPicture, pMaskPicture, pDstPicture);
623 exa_debug_printf("\tFormats: src(%s), mask(%s), dst(%s)\n",
624 pSrcPicture ? render_format_name(pSrcPicture->format) : "none",
625 pMaskPicture ? render_format_name(pMaskPicture->format) : "none",
626 pDstPicture ? render_format_name(pDstPicture->format) : "none");
627
628 if (!exa->pipe)
629 XORG_FALLBACK("accel not enabled");
630
631 priv = exaGetPixmapDriverPrivate(pDst);
632 if (!priv || !priv->tex)
633 XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
634
635 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
636 priv->tex->target, 0,
637 PIPE_BIND_RENDER_TARGET))
638 XORG_FALLBACK("pDst format: %s", util_format_name(priv->tex->format));
639
640 if (priv->picture_format != pDstPicture->format)
641 XORG_FALLBACK("pDst pic_format: %s != %s",
642 render_format_name(priv->picture_format),
643 render_format_name(pDstPicture->format));
644
645 if (pSrc) {
646 priv = exaGetPixmapDriverPrivate(pSrc);
647 if (!priv || !priv->tex)
648 XORG_FALLBACK("pSrc %s", !priv ? "!priv" : "!priv->tex");
649
650 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
651 priv->tex->target, 0,
652 PIPE_BIND_SAMPLER_VIEW))
653 XORG_FALLBACK("pSrc format: %s", util_format_name(priv->tex->format));
654
655 if (!picture_check_formats(priv, pSrcPicture))
656 XORG_FALLBACK("pSrc pic_format: %s != %s",
657 render_format_name(priv->picture_format),
658 render_format_name(pSrcPicture->format));
659
660 }
661
662 if (pMask) {
663 priv = exaGetPixmapDriverPrivate(pMask);
664 if (!priv || !priv->tex)
665 XORG_FALLBACK("pMask %s", !priv ? "!priv" : "!priv->tex");
666
667 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
668 priv->tex->target, 0,
669 PIPE_BIND_SAMPLER_VIEW))
670 XORG_FALLBACK("pMask format: %s", util_format_name(priv->tex->format));
671
672 if (!picture_check_formats(priv, pMaskPicture))
673 XORG_FALLBACK("pMask pic_format: %s != %s",
674 render_format_name(priv->picture_format),
675 render_format_name(pMaskPicture->format));
676 }
677
678 return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
679 pDstPicture,
680 pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
681 pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
682 exaGetPixmapDriverPrivate(pDst));
683 }
684
685 static void
ExaComposite(PixmapPtr pDst,int srcX,int srcY,int maskX,int maskY,int dstX,int dstY,int width,int height)686 ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
687 int dstX, int dstY, int width, int height)
688 {
689 ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
690 modesettingPtr ms = modesettingPTR(pScrn);
691 struct exa_context *exa = ms->exa;
692 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
693
694 exa_debug_printf("\tExaComposite(src[%d,%d], mask=[%d, %d], dst=[%d, %d], dim=[%d, %d])\n",
695 srcX, srcY, maskX, maskY, dstX, dstY, width, height);
696 exa_debug_printf("\t Num bound samplers = %d\n",
697 exa->num_bound_samplers);
698
699 xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
700 dstX, dstY, width, height);
701 }
702
703
704
705 static void
ExaDoneComposite(PixmapPtr pPixmap)706 ExaDoneComposite(PixmapPtr pPixmap)
707 {
708 ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
709 modesettingPtr ms = modesettingPTR(pScrn);
710 struct exa_context *exa = ms->exa;
711
712 xorg_composite_done(exa);
713 }
714
715
716 /***********************************************************************
717 * Pixmaps
718 */
719
720 static void *
ExaCreatePixmap(ScreenPtr pScreen,int size,int align)721 ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
722 {
723 struct exa_pixmap_priv *priv;
724
725 priv = calloc(1, sizeof(struct exa_pixmap_priv));
726 if (!priv)
727 return NULL;
728
729 return priv;
730 }
731
732 static void
ExaDestroyPixmap(ScreenPtr pScreen,void * dPriv)733 ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
734 {
735 struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
736
737 if (!priv)
738 return;
739
740 pipe_resource_reference(&priv->tex, NULL);
741
742 free(priv);
743 }
744
745 static Bool
ExaPixmapIsOffscreen(PixmapPtr pPixmap)746 ExaPixmapIsOffscreen(PixmapPtr pPixmap)
747 {
748 struct exa_pixmap_priv *priv;
749
750 priv = exaGetPixmapDriverPrivate(pPixmap);
751
752 if (!priv)
753 return FALSE;
754
755 if (priv->tex)
756 return TRUE;
757
758 return FALSE;
759 }
760
761 int
xorg_exa_set_displayed_usage(PixmapPtr pPixmap)762 xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
763 {
764 struct exa_pixmap_priv *priv;
765 priv = exaGetPixmapDriverPrivate(pPixmap);
766
767 if (!priv) {
768 FatalError("NO PIXMAP PRIVATE\n");
769 return 0;
770 }
771
772 priv->flags |= PIPE_BIND_SCANOUT;
773
774 return 0;
775 }
776
777 int
xorg_exa_set_shared_usage(PixmapPtr pPixmap)778 xorg_exa_set_shared_usage(PixmapPtr pPixmap)
779 {
780 struct exa_pixmap_priv *priv;
781 priv = exaGetPixmapDriverPrivate(pPixmap);
782
783 if (!priv) {
784 FatalError("NO PIXMAP PRIVATE\n");
785 return 0;
786 }
787
788 priv->flags |= PIPE_BIND_SHARED;
789
790 return 0;
791 }
792
793
794
795 static Bool
size_match(int width,int tex_width)796 size_match( int width, int tex_width )
797 {
798 #if ROUND_UP_TEXTURES
799 if (width > tex_width)
800 return FALSE;
801
802 if (width * 2 < tex_width)
803 return FALSE;
804
805 return TRUE;
806 #else
807 return width == tex_width;
808 #endif
809 }
810
811 static Bool
ExaModifyPixmapHeader(PixmapPtr pPixmap,int width,int height,int depth,int bitsPerPixel,int devKind,pointer pPixData)812 ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
813 int depth, int bitsPerPixel, int devKind,
814 pointer pPixData)
815 {
816 ScreenPtr pScreen = pPixmap->drawable.pScreen;
817 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
818 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
819 modesettingPtr ms = modesettingPTR(pScrn);
820 struct exa_context *exa = ms->exa;
821
822 if (!priv || pPixData)
823 return FALSE;
824
825 if (0) {
826 debug_printf("%s pixmap %p sz %dx%dx%d devKind %d\n",
827 __FUNCTION__, pPixmap, width, height, bitsPerPixel, devKind);
828
829 if (priv->tex)
830 debug_printf(" ==> old texture %dx%d\n",
831 priv->tex->width0,
832 priv->tex->height0);
833 }
834
835
836 if (depth <= 0)
837 depth = pPixmap->drawable.depth;
838
839 if (bitsPerPixel <= 0)
840 bitsPerPixel = pPixmap->drawable.bitsPerPixel;
841
842 if (width <= 0)
843 width = pPixmap->drawable.width;
844
845 if (height <= 0)
846 height = pPixmap->drawable.height;
847
848 if (width <= 0 || height <= 0 || depth <= 0)
849 return FALSE;
850
851 miModifyPixmapHeader(pPixmap, width, height, depth,
852 bitsPerPixel, devKind, NULL);
853
854 priv->width = width;
855 priv->height = height;
856
857 /* Deal with screen resize */
858 if ((exa->accel || priv->flags) &&
859 (!priv->tex ||
860 !size_match(width, priv->tex->width0) ||
861 !size_match(height, priv->tex->height0) ||
862 priv->tex_flags != priv->flags)) {
863 struct pipe_resource *texture = NULL;
864 struct pipe_resource template;
865
866 memset(&template, 0, sizeof(template));
867 template.target = PIPE_TEXTURE_2D;
868 exa_get_pipe_format(depth, &template.format, &bitsPerPixel, &priv->picture_format);
869 if (ROUND_UP_TEXTURES && priv->flags == 0) {
870 template.width0 = util_next_power_of_two(width);
871 template.height0 = util_next_power_of_two(height);
872 }
873 else {
874 template.width0 = width;
875 template.height0 = height;
876 }
877
878 template.depth0 = 1;
879 template.array_size = 1;
880 template.last_level = 0;
881 template.bind = PIPE_BIND_RENDER_TARGET | priv->flags;
882 priv->tex_flags = priv->flags;
883 texture = exa->scrn->resource_create(exa->scrn, &template);
884
885 if (priv->tex) {
886 struct pipe_box src_box;
887 u_box_origin_2d(min(width, texture->width0),
888 min(height, texture->height0),
889 &src_box);
890 exa->pipe->resource_copy_region(exa->pipe, texture,
891 0, 0, 0, 0,
892 priv->tex,
893 0, &src_box);
894 }
895
896 pipe_resource_reference(&priv->tex, texture);
897 /* the texture we create has one reference */
898 pipe_resource_reference(&texture, NULL);
899 }
900
901 return TRUE;
902 }
903
904 struct pipe_resource *
xorg_exa_get_texture(PixmapPtr pPixmap)905 xorg_exa_get_texture(PixmapPtr pPixmap)
906 {
907 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
908 struct pipe_resource *tex = NULL;
909 pipe_resource_reference(&tex, priv->tex);
910 return tex;
911 }
912
913 Bool
xorg_exa_set_texture(PixmapPtr pPixmap,struct pipe_resource * tex)914 xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_resource *tex)
915 {
916 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
917
918 int mask = PIPE_BIND_SHARED | PIPE_BIND_SCANOUT;
919
920 if (!priv)
921 return FALSE;
922
923 if (pPixmap->drawable.width != tex->width0 ||
924 pPixmap->drawable.height != tex->height0)
925 return FALSE;
926
927 pipe_resource_reference(&priv->tex, tex);
928 priv->tex_flags = tex->bind & mask;
929
930 return TRUE;
931 }
932
933 struct pipe_resource *
xorg_exa_create_root_texture(ScrnInfoPtr pScrn,int width,int height,int depth,int bitsPerPixel)934 xorg_exa_create_root_texture(ScrnInfoPtr pScrn,
935 int width, int height,
936 int depth, int bitsPerPixel)
937 {
938 modesettingPtr ms = modesettingPTR(pScrn);
939 struct exa_context *exa = ms->exa;
940 struct pipe_resource template;
941 int dummy;
942
943 memset(&template, 0, sizeof(template));
944 template.target = PIPE_TEXTURE_2D;
945 exa_get_pipe_format(depth, &template.format, &bitsPerPixel, &dummy);
946 template.width0 = width;
947 template.height0 = height;
948 template.depth0 = 1;
949 template.array_size = 1;
950 template.last_level = 0;
951 template.bind |= PIPE_BIND_RENDER_TARGET;
952 template.bind |= PIPE_BIND_SCANOUT;
953 template.bind |= PIPE_BIND_SHARED;
954
955 return exa->scrn->resource_create(exa->scrn, &template);
956 }
957
958 void
xorg_exa_close(ScrnInfoPtr pScrn)959 xorg_exa_close(ScrnInfoPtr pScrn)
960 {
961 modesettingPtr ms = modesettingPTR(pScrn);
962 struct exa_context *exa = ms->exa;
963
964 pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL);
965 pipe_sampler_view_reference(&exa->bound_sampler_views[1], NULL);
966
967 renderer_destroy(exa->renderer);
968
969 xorg_exa_finish(exa);
970
971 if (exa->pipe)
972 exa->pipe->destroy(exa->pipe);
973 exa->pipe = NULL;
974 /* Since this was shared be proper with the pointer */
975 ms->ctx = NULL;
976
977 exaDriverFini(pScrn->pScreen);
978 free(exa);
979 ms->exa = NULL;
980 }
981
982 void *
xorg_exa_init(ScrnInfoPtr pScrn,Bool accel)983 xorg_exa_init(ScrnInfoPtr pScrn, Bool accel)
984 {
985 modesettingPtr ms = modesettingPTR(pScrn);
986 struct exa_context *exa;
987 ExaDriverPtr pExa;
988 CustomizerPtr cust = ms->cust;
989
990 exa = calloc(1, sizeof(struct exa_context));
991 if (!exa)
992 return NULL;
993
994 exa->scrn = ms->screen;
995 exa->pipe = exa->scrn->context_create(exa->scrn, NULL);
996 if (exa->pipe == NULL)
997 goto out_err;
998
999 pExa = exaDriverAlloc();
1000 if (!pExa) {
1001 goto out_err;
1002 }
1003
1004 pExa->exa_major = 2;
1005 pExa->exa_minor = 2;
1006 pExa->memoryBase = 0;
1007 pExa->memorySize = 0;
1008 pExa->offScreenBase = 0;
1009 pExa->pixmapOffsetAlign = 0;
1010 pExa->pixmapPitchAlign = 1;
1011 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
1012 #ifdef EXA_SUPPORTS_PREPARE_AUX
1013 pExa->flags |= EXA_SUPPORTS_PREPARE_AUX;
1014 #endif
1015 #ifdef EXA_MIXED_PIXMAPS
1016 pExa->flags |= EXA_MIXED_PIXMAPS;
1017 #endif
1018
1019 pExa->maxX = pExa->maxY =
1020 1 << (exa->scrn->get_param(exa->scrn, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
1021
1022 pExa->WaitMarker = ExaWaitMarker;
1023 pExa->MarkSync = ExaMarkSync;
1024 pExa->PrepareSolid = ExaPrepareSolid;
1025 pExa->Solid = ExaSolid;
1026 pExa->DoneSolid = ExaDoneSolid;
1027 pExa->PrepareCopy = ExaPrepareCopy;
1028 pExa->Copy = ExaCopy;
1029 pExa->DoneCopy = ExaDoneCopy;
1030 pExa->CheckComposite = ExaCheckComposite;
1031 pExa->PrepareComposite = ExaPrepareComposite;
1032 pExa->Composite = ExaComposite;
1033 pExa->DoneComposite = ExaDoneComposite;
1034 pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen;
1035 pExa->DownloadFromScreen = ExaDownloadFromScreen;
1036 pExa->UploadToScreen = ExaUploadToScreen;
1037 pExa->PrepareAccess = ExaPrepareAccess;
1038 pExa->FinishAccess = ExaFinishAccess;
1039 pExa->CreatePixmap = ExaCreatePixmap;
1040 pExa->DestroyPixmap = ExaDestroyPixmap;
1041 pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
1042
1043 if (!exaDriverInit(pScrn->pScreen, pExa)) {
1044 goto out_err;
1045 }
1046
1047 /* Share context with DRI */
1048 ms->ctx = exa->pipe;
1049 if (cust && cust->winsys_context_throttle)
1050 cust->winsys_context_throttle(cust, ms->ctx, THROTTLE_RENDER);
1051
1052 exa->renderer = renderer_create(exa->pipe);
1053 exa->accel = accel;
1054
1055 return (void *)exa;
1056
1057 out_err:
1058 xorg_exa_close(pScrn);
1059 free(exa);
1060
1061 return NULL;
1062 }
1063
1064 struct pipe_surface *
xorg_gpu_surface(struct pipe_context * pipe,struct exa_pixmap_priv * priv)1065 xorg_gpu_surface(struct pipe_context *pipe, struct exa_pixmap_priv *priv)
1066 {
1067 struct pipe_surface surf_tmpl;
1068 memset(&surf_tmpl, 0, sizeof(surf_tmpl));
1069 u_surface_default_template(&surf_tmpl, priv->tex,
1070 PIPE_BIND_RENDER_TARGET);
1071
1072 return pipe->create_surface(pipe, priv->tex, &surf_tmpl);
1073
1074 }
1075
xorg_exa_flush(struct exa_context * exa,struct pipe_fence_handle ** fence)1076 void xorg_exa_flush(struct exa_context *exa,
1077 struct pipe_fence_handle **fence)
1078 {
1079 exa->pipe->flush(exa->pipe, fence);
1080 }
1081
xorg_exa_finish(struct exa_context * exa)1082 void xorg_exa_finish(struct exa_context *exa)
1083 {
1084 struct pipe_fence_handle *fence = NULL;
1085
1086 xorg_exa_flush(exa, &fence);
1087
1088 exa->pipe->screen->fence_finish(exa->pipe->screen, fence,
1089 PIPE_TIMEOUT_INFINITE);
1090 exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
1091 }
1092
1093