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