st/xorg: adapt to interface changes
[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, 0,
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, 0,
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, 0,
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 /* XXX this used to use resource_copy_region for same-surface copies,
444 * but they were redefined to not allow overlaps (some of the util code
445 * always assumed this anyway).
446 * Drivers should implement accelerated resource_copy_region or it will
447 * be slow - disable for now.
448 */
449 if (0 && exa->copy.src != exa->copy.dst) {
450 exa->copy.use_surface_copy = TRUE;
451 }
452 else {
453 exa->copy.use_surface_copy = FALSE;
454
455 if (exa->copy.dst == exa->copy.src)
456 exa->copy.src_texture = renderer_clone_texture( exa->renderer,
457 exa->copy.src->tex );
458 else
459 pipe_resource_reference(&exa->copy.src_texture,
460 exa->copy.src->tex);
461
462 exa->copy.dst_surface =
463 exa->scrn->get_tex_surface(exa->scrn,
464 exa->copy.dst->tex,
465 0, 0, 0,
466 PIPE_BIND_RENDER_TARGET);
467
468
469 renderer_copy_prepare(exa->renderer,
470 exa->copy.dst_surface,
471 exa->copy.src_texture );
472 }
473
474
475 return TRUE;
476 }
477
478 static void
479 ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
480 int width, int height)
481 {
482 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
483 modesettingPtr ms = modesettingPTR(pScrn);
484 struct exa_context *exa = ms->exa;
485 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
486
487 #if DEBUG_PRINT
488 debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
489 srcX, srcY, dstX, dstY, width, height);
490 #endif
491
492 debug_assert(priv == exa->copy.dst);
493 (void) priv;
494
495 if (exa->copy.use_surface_copy) {
496 struct pipe_subresource subdst, subsrc;
497 subdst.face = 0;
498 subdst.level = 0;
499 subsrc.face = 0;
500 subsrc.level = 0;
501 exa->pipe->resource_copy_region( exa->pipe,
502 exa->copy.dst->tex,
503 subdst,
504 dstX, dstY, 0,
505 exa->copy.src->tex,
506 subsrc,
507 srcX, srcY, 0,
508 width, height );
509 }
510 else {
511 renderer_copy_pixmap(exa->renderer,
512 dstX, dstY,
513 srcX, srcY,
514 width, height,
515 exa->copy.src_texture->width0,
516 exa->copy.src_texture->height0);
517 }
518 }
519
520 static void
521 ExaDoneCopy(PixmapPtr pPixmap)
522 {
523 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
524 modesettingPtr ms = modesettingPTR(pScrn);
525 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
526 struct exa_context *exa = ms->exa;
527
528 if (!priv)
529 return;
530
531 renderer_draw_flush(exa->renderer);
532
533 exa->copy.src = NULL;
534 exa->copy.dst = NULL;
535 pipe_surface_reference(&exa->copy.dst_surface, NULL);
536 pipe_resource_reference(&exa->copy.src_texture, NULL);
537 }
538
539
540
541 static Bool
542 picture_check_formats(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture)
543 {
544 if (pSrc->picture_format == pSrcPicture->format)
545 return TRUE;
546
547 if (pSrc->picture_format != PICT_a8r8g8b8)
548 return FALSE;
549
550 /* pSrc->picture_format == PICT_a8r8g8b8 */
551 switch (pSrcPicture->format) {
552 case PICT_a8r8g8b8:
553 case PICT_x8r8g8b8:
554 case PICT_a8b8g8r8:
555 case PICT_x8b8g8r8:
556 /* just treat these two as x8... */
557 case PICT_r8g8b8:
558 case PICT_b8g8r8:
559 return TRUE;
560 #ifdef PICT_TYPE_BGRA
561 case PICT_b8g8r8a8:
562 case PICT_b8g8r8x8:
563 return FALSE; /* does not support swizzleing the alpha channel yet */
564 case PICT_a2r10g10b10:
565 case PICT_x2r10g10b10:
566 case PICT_a2b10g10r10:
567 case PICT_x2b10g10r10:
568 return FALSE;
569 #endif
570 default:
571 return FALSE;
572 }
573 return FALSE;
574 }
575
576 /***********************************************************************
577 * Composite entrypoints
578 */
579
580 static Bool
581 ExaCheckComposite(int op,
582 PicturePtr pSrcPicture, PicturePtr pMaskPicture,
583 PicturePtr pDstPicture)
584 {
585 ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum];
586 modesettingPtr ms = modesettingPTR(pScrn);
587 struct exa_context *exa = ms->exa;
588
589 #if DEBUG_PRINT
590 debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
591 op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
592 #endif
593
594 if (!exa->accel)
595 return FALSE;
596
597 return xorg_composite_accelerated(op,
598 pSrcPicture,
599 pMaskPicture,
600 pDstPicture);
601 }
602
603
604 static Bool
605 ExaPrepareComposite(int op, PicturePtr pSrcPicture,
606 PicturePtr pMaskPicture, PicturePtr pDstPicture,
607 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
608 {
609 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
610 modesettingPtr ms = modesettingPTR(pScrn);
611 struct exa_context *exa = ms->exa;
612 struct exa_pixmap_priv *priv;
613
614 if (!exa->accel)
615 return FALSE;
616
617 #if DEBUG_PRINT
618 debug_printf("ExaPrepareComposite(%d, src=0x%p, mask=0x%p, dst=0x%p)\n",
619 op, pSrcPicture, pMaskPicture, pDstPicture);
620 debug_printf("\tFormats: src(%s), mask(%s), dst(%s)\n",
621 pSrcPicture ? render_format_name(pSrcPicture->format) : "none",
622 pMaskPicture ? render_format_name(pMaskPicture->format) : "none",
623 pDstPicture ? render_format_name(pDstPicture->format) : "none");
624 #endif
625 if (!exa->pipe)
626 XORG_FALLBACK("accle not enabled");
627
628 priv = exaGetPixmapDriverPrivate(pDst);
629 if (!priv || !priv->tex)
630 XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
631
632 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
633 priv->tex->target, 0,
634 PIPE_BIND_RENDER_TARGET, 0))
635 XORG_FALLBACK("pDst format: %s", util_format_name(priv->tex->format));
636
637 if (priv->picture_format != pDstPicture->format)
638 XORG_FALLBACK("pDst pic_format: %s != %s",
639 render_format_name(priv->picture_format),
640 render_format_name(pDstPicture->format));
641
642 if (pSrc) {
643 priv = exaGetPixmapDriverPrivate(pSrc);
644 if (!priv || !priv->tex)
645 XORG_FALLBACK("pSrc %s", !priv ? "!priv" : "!priv->tex");
646
647 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
648 priv->tex->target, 0,
649 PIPE_BIND_SAMPLER_VIEW, 0))
650 XORG_FALLBACK("pSrc format: %s", util_format_name(priv->tex->format));
651
652 if (!picture_check_formats(priv, pSrcPicture))
653 XORG_FALLBACK("pSrc pic_format: %s != %s",
654 render_format_name(priv->picture_format),
655 render_format_name(pSrcPicture->format));
656
657 }
658
659 if (pMask) {
660 priv = exaGetPixmapDriverPrivate(pMask);
661 if (!priv || !priv->tex)
662 XORG_FALLBACK("pMask %s", !priv ? "!priv" : "!priv->tex");
663
664 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
665 priv->tex->target, 0,
666 PIPE_BIND_SAMPLER_VIEW, 0))
667 XORG_FALLBACK("pMask format: %s", util_format_name(priv->tex->format));
668
669 if (!picture_check_formats(priv, pMaskPicture))
670 XORG_FALLBACK("pMask pic_format: %s != %s",
671 render_format_name(priv->picture_format),
672 render_format_name(pMaskPicture->format));
673 }
674
675 return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
676 pDstPicture,
677 pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
678 pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
679 exaGetPixmapDriverPrivate(pDst));
680 }
681
682 static void
683 ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
684 int dstX, int dstY, int width, int height)
685 {
686 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
687 modesettingPtr ms = modesettingPTR(pScrn);
688 struct exa_context *exa = ms->exa;
689 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
690
691 #if DEBUG_PRINT
692 debug_printf("\tExaComposite(src[%d,%d], mask=[%d, %d], dst=[%d, %d], dim=[%d, %d])\n",
693 srcX, srcY, maskX, maskY, dstX, dstY, width, height);
694 debug_printf("\t Num bound samplers = %d\n",
695 exa->num_bound_samplers);
696 #endif
697
698 xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
699 dstX, dstY, width, height);
700 }
701
702
703
704 static void
705 ExaDoneComposite(PixmapPtr pPixmap)
706 {
707 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
708 modesettingPtr ms = modesettingPTR(pScrn);
709 struct exa_context *exa = ms->exa;
710
711 xorg_composite_done(exa);
712 }
713
714
715 /***********************************************************************
716 * Pixmaps
717 */
718
719 static void *
720 ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
721 {
722 struct exa_pixmap_priv *priv;
723
724 priv = xcalloc(1, sizeof(struct exa_pixmap_priv));
725 if (!priv)
726 return NULL;
727
728 return priv;
729 }
730
731 static void
732 ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
733 {
734 struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
735
736 if (!priv)
737 return;
738
739 pipe_resource_reference(&priv->tex, NULL);
740
741 xfree(priv);
742 }
743
744 static Bool
745 ExaPixmapIsOffscreen(PixmapPtr pPixmap)
746 {
747 struct exa_pixmap_priv *priv;
748
749 priv = exaGetPixmapDriverPrivate(pPixmap);
750
751 if (!priv)
752 return FALSE;
753
754 if (priv->tex)
755 return TRUE;
756
757 return FALSE;
758 }
759
760 int
761 xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
762 {
763 struct exa_pixmap_priv *priv;
764 priv = exaGetPixmapDriverPrivate(pPixmap);
765
766 if (!priv) {
767 FatalError("NO PIXMAP PRIVATE\n");
768 return 0;
769 }
770
771 priv->flags |= PIPE_BIND_SCANOUT;
772
773 return 0;
774 }
775
776 int
777 xorg_exa_set_shared_usage(PixmapPtr pPixmap)
778 {
779 struct exa_pixmap_priv *priv;
780 priv = exaGetPixmapDriverPrivate(pPixmap);
781
782 if (!priv) {
783 FatalError("NO PIXMAP PRIVATE\n");
784 return 0;
785 }
786
787 priv->flags |= PIPE_BIND_SHARED;
788
789 return 0;
790 }
791
792
793
794 static Bool
795 size_match( int width, int tex_width )
796 {
797 #if ROUND_UP_TEXTURES
798 if (width > tex_width)
799 return FALSE;
800
801 if (width * 2 < tex_width)
802 return FALSE;
803
804 return TRUE;
805 #else
806 return width == tex_width;
807 #endif
808 }
809
810 static Bool
811 ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
812 int depth, int bitsPerPixel, int devKind,
813 pointer pPixData)
814 {
815 ScreenPtr pScreen = pPixmap->drawable.pScreen;
816 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
817 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
818 modesettingPtr ms = modesettingPTR(pScrn);
819 struct exa_context *exa = ms->exa;
820
821 if (!priv || pPixData)
822 return FALSE;
823
824 if (0) {
825 debug_printf("%s pixmap %p sz %dx%dx%d devKind %d\n",
826 __FUNCTION__, pPixmap, width, height, bitsPerPixel, devKind);
827
828 if (priv->tex)
829 debug_printf(" ==> old texture %dx%d\n",
830 priv->tex->width0,
831 priv->tex->height0);
832 }
833
834
835 if (depth <= 0)
836 depth = pPixmap->drawable.depth;
837
838 if (bitsPerPixel <= 0)
839 bitsPerPixel = pPixmap->drawable.bitsPerPixel;
840
841 if (width <= 0)
842 width = pPixmap->drawable.width;
843
844 if (height <= 0)
845 height = pPixmap->drawable.height;
846
847 if (width <= 0 || height <= 0 || depth <= 0)
848 return FALSE;
849
850 miModifyPixmapHeader(pPixmap, width, height, depth,
851 bitsPerPixel, devKind, NULL);
852
853 priv->width = width;
854 priv->height = height;
855
856 /* Deal with screen resize */
857 if ((exa->accel || priv->flags) &&
858 (!priv->tex ||
859 !size_match(width, priv->tex->width0) ||
860 !size_match(height, priv->tex->height0) ||
861 priv->tex_flags != priv->flags)) {
862 struct pipe_resource *texture = NULL;
863 struct pipe_resource template;
864
865 memset(&template, 0, sizeof(template));
866 template.target = PIPE_TEXTURE_2D;
867 exa_get_pipe_format(depth, &template.format, &bitsPerPixel, &priv->picture_format);
868 if (ROUND_UP_TEXTURES && priv->flags == 0) {
869 template.width0 = util_next_power_of_two(width);
870 template.height0 = util_next_power_of_two(height);
871 }
872 else {
873 template.width0 = width;
874 template.height0 = height;
875 }
876
877 template.depth0 = 1;
878 template.last_level = 0;
879 template.bind = PIPE_BIND_RENDER_TARGET | priv->flags;
880 priv->tex_flags = priv->flags;
881 texture = exa->scrn->resource_create(exa->scrn, &template);
882
883 if (priv->tex) {
884 struct pipe_subresource subdst, subsrc;
885 struct pipe_surface *src_surf;
886
887 subdst.face = 0;
888 subdst.level = 0;
889 subsrc.face = 0;
890 subsrc.level = 0;
891 exa->pipe->resource_copy_region(exa->pipe, texture,
892 subdst, 0, 0, 0,
893 priv->tex,
894 subsrc, 0, 0, 0,
895 min(width, texture->width0),
896 min(height, texture->height0));
897 }
898
899 pipe_resource_reference(&priv->tex, texture);
900 /* the texture we create has one reference */
901 pipe_resource_reference(&texture, NULL);
902 }
903
904 return TRUE;
905 }
906
907 struct pipe_resource *
908 xorg_exa_get_texture(PixmapPtr pPixmap)
909 {
910 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
911 struct pipe_resource *tex = NULL;
912 pipe_resource_reference(&tex, priv->tex);
913 return tex;
914 }
915
916 Bool
917 xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_resource *tex)
918 {
919 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
920
921 int mask = PIPE_BIND_SHARED | PIPE_BIND_SCANOUT;
922
923 if (!priv)
924 return FALSE;
925
926 if (pPixmap->drawable.width != tex->width0 ||
927 pPixmap->drawable.height != tex->height0)
928 return FALSE;
929
930 pipe_resource_reference(&priv->tex, tex);
931 priv->tex_flags = tex->bind & mask;
932
933 return TRUE;
934 }
935
936 struct pipe_resource *
937 xorg_exa_create_root_texture(ScrnInfoPtr pScrn,
938 int width, int height,
939 int depth, int bitsPerPixel)
940 {
941 modesettingPtr ms = modesettingPTR(pScrn);
942 struct exa_context *exa = ms->exa;
943 struct pipe_resource template;
944 int dummy;
945
946 memset(&template, 0, sizeof(template));
947 template.target = PIPE_TEXTURE_2D;
948 exa_get_pipe_format(depth, &template.format, &bitsPerPixel, &dummy);
949 template.width0 = width;
950 template.height0 = height;
951 template.depth0 = 1;
952 template.last_level = 0;
953 template.bind |= PIPE_BIND_RENDER_TARGET;
954 template.bind |= PIPE_BIND_SCANOUT;
955 template.bind |= PIPE_BIND_SHARED;
956
957 return exa->scrn->resource_create(exa->scrn, &template);
958 }
959
960 void
961 xorg_exa_close(ScrnInfoPtr pScrn)
962 {
963 modesettingPtr ms = modesettingPTR(pScrn);
964 struct exa_context *exa = ms->exa;
965
966 pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL);
967 pipe_sampler_view_reference(&exa->bound_sampler_views[1], NULL);
968
969 renderer_destroy(exa->renderer);
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 xfree(exa);
979 ms->exa = NULL;
980 }
981
982 void *
983 xorg_exa_init(ScrnInfoPtr pScrn, Bool accel)
984 {
985 modesettingPtr ms = modesettingPTR(pScrn);
986 struct exa_context *exa;
987 ExaDriverPtr pExa;
988
989 exa = xcalloc(1, sizeof(struct exa_context));
990 if (!exa)
991 return NULL;
992
993 pExa = exaDriverAlloc();
994 if (!pExa) {
995 goto out_err;
996 }
997
998 memset(pExa, 0, sizeof(*pExa));
999
1000 pExa->exa_major = 2;
1001 pExa->exa_minor = 2;
1002 pExa->memoryBase = 0;
1003 pExa->memorySize = 0;
1004 pExa->offScreenBase = 0;
1005 pExa->pixmapOffsetAlign = 0;
1006 pExa->pixmapPitchAlign = 1;
1007 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
1008 #ifdef EXA_SUPPORTS_PREPARE_AUX
1009 pExa->flags |= EXA_SUPPORTS_PREPARE_AUX;
1010 #endif
1011 #ifdef EXA_MIXED_PIXMAPS
1012 pExa->flags |= EXA_MIXED_PIXMAPS;
1013 #endif
1014 pExa->maxX = 8191; /* FIXME */
1015 pExa->maxY = 8191; /* FIXME */
1016
1017 pExa->WaitMarker = ExaWaitMarker;
1018 pExa->MarkSync = ExaMarkSync;
1019 pExa->PrepareSolid = ExaPrepareSolid;
1020 pExa->Solid = ExaSolid;
1021 pExa->DoneSolid = ExaDoneSolid;
1022 pExa->PrepareCopy = ExaPrepareCopy;
1023 pExa->Copy = ExaCopy;
1024 pExa->DoneCopy = ExaDoneCopy;
1025 pExa->CheckComposite = ExaCheckComposite;
1026 pExa->PrepareComposite = ExaPrepareComposite;
1027 pExa->Composite = ExaComposite;
1028 pExa->DoneComposite = ExaDoneComposite;
1029 pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen;
1030 pExa->DownloadFromScreen = ExaDownloadFromScreen;
1031 pExa->UploadToScreen = ExaUploadToScreen;
1032 pExa->PrepareAccess = ExaPrepareAccess;
1033 pExa->FinishAccess = ExaFinishAccess;
1034 pExa->CreatePixmap = ExaCreatePixmap;
1035 pExa->DestroyPixmap = ExaDestroyPixmap;
1036 pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
1037
1038 if (!exaDriverInit(pScrn->pScreen, pExa)) {
1039 goto out_err;
1040 }
1041
1042 exa->scrn = ms->screen;
1043 exa->pipe = exa->scrn->context_create(exa->scrn, NULL);
1044 if (exa->pipe == NULL)
1045 goto out_err;
1046
1047 /* Share context with DRI */
1048 ms->ctx = exa->pipe;
1049
1050 exa->renderer = renderer_create(exa->pipe);
1051 exa->accel = accel;
1052
1053 return (void *)exa;
1054
1055 out_err:
1056 xorg_exa_close(pScrn);
1057
1058 return NULL;
1059 }
1060
1061 struct pipe_surface *
1062 xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv)
1063 {
1064 return scrn->get_tex_surface(scrn, priv->tex, 0, 0, 0,
1065 PIPE_BIND_RENDER_TARGET);
1066
1067 }
1068
1069 void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
1070 struct pipe_fence_handle **fence)
1071 {
1072 exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
1073 }
1074
1075 void xorg_exa_finish(struct exa_context *exa)
1076 {
1077 struct pipe_fence_handle *fence = NULL;
1078
1079 xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
1080
1081 exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
1082 exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
1083 }
1084