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