Revert "st/xorg: fix composite after texture size 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 #include "pipe/p_inlines.h"
45
46 #include "util/u_rect.h"
47 #include "util/u_math.h"
48 #include "util/u_debug.h"
49
50 #define DEBUG_PRINT 0
51
52 /*
53 * Helper functions
54 */
55 struct render_format_str {
56 int format;
57 const char *name;
58 };
59 static const struct render_format_str formats_info[] =
60 {
61 {PICT_a8r8g8b8, "PICT_a8r8g8b8"},
62 {PICT_x8r8g8b8, "PICT_x8r8g8b8"},
63 {PICT_a8b8g8r8, "PICT_a8b8g8r8"},
64 {PICT_x8b8g8r8, "PICT_x8b8g8r8"},
65 #ifdef PICT_TYPE_BGRA
66 {PICT_b8g8r8a8, "PICT_b8g8r8a8"},
67 {PICT_b8g8r8x8, "PICT_b8g8r8x8"},
68 {PICT_a2r10g10b10, "PICT_a2r10g10b10"},
69 {PICT_x2r10g10b10, "PICT_x2r10g10b10"},
70 {PICT_a2b10g10r10, "PICT_a2b10g10r10"},
71 {PICT_x2b10g10r10, "PICT_x2b10g10r10"},
72 #endif
73 {PICT_r8g8b8, "PICT_r8g8b8"},
74 {PICT_b8g8r8, "PICT_b8g8r8"},
75 {PICT_r5g6b5, "PICT_r5g6b5"},
76 {PICT_b5g6r5, "PICT_b5g6r5"},
77 {PICT_a1r5g5b5, "PICT_a1r5g5b5"},
78 {PICT_x1r5g5b5, "PICT_x1r5g5b5"},
79 {PICT_a1b5g5r5, "PICT_a1b5g5r5"},
80 {PICT_x1b5g5r5, "PICT_x1b5g5r5"},
81 {PICT_a4r4g4b4, "PICT_a4r4g4b4"},
82 {PICT_x4r4g4b4, "PICT_x4r4g4b4"},
83 {PICT_a4b4g4r4, "PICT_a4b4g4r4"},
84 {PICT_x4b4g4r4, "PICT_x4b4g4r4"},
85 {PICT_a8, "PICT_a8"},
86 {PICT_r3g3b2, "PICT_r3g3b2"},
87 {PICT_b2g3r3, "PICT_b2g3r3"},
88 {PICT_a2r2g2b2, "PICT_a2r2g2b2"},
89 {PICT_a2b2g2r2, "PICT_a2b2g2r2"},
90 {PICT_c8, "PICT_c8"},
91 {PICT_g8, "PICT_g8"},
92 {PICT_x4a4, "PICT_x4a4"},
93 {PICT_x4c4, "PICT_x4c4"},
94 {PICT_x4g4, "PICT_x4g4"},
95 {PICT_a4, "PICT_a4"},
96 {PICT_r1g2b1, "PICT_r1g2b1"},
97 {PICT_b1g2r1, "PICT_b1g2r1"},
98 {PICT_a1r1g1b1, "PICT_a1r1g1b1"},
99 {PICT_a1b1g1r1, "PICT_a1b1g1r1"},
100 {PICT_c4, "PICT_c4"},
101 {PICT_g4, "PICT_g4"},
102 {PICT_a1, "PICT_a1"},
103 {PICT_g1, "PICT_g1"}
104 };
105 static const char *render_format_name(int format)
106 {
107 int i = 0;
108 for (i = 0; i < sizeof(formats_info)/sizeof(formats_info[0]); ++i) {
109 if (formats_info[i].format == format)
110 return formats_info[i].name;
111 }
112 return NULL;
113 }
114
115 static void
116 exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp, int *picture_format)
117 {
118 switch (depth) {
119 case 32:
120 *format = PIPE_FORMAT_A8R8G8B8_UNORM;
121 *picture_format = PICT_a8r8g8b8;
122 assert(*bbp == 32);
123 break;
124 case 24:
125 *format = PIPE_FORMAT_X8R8G8B8_UNORM;
126 *picture_format = PICT_x8r8g8b8;
127 assert(*bbp == 32);
128 break;
129 case 16:
130 *format = PIPE_FORMAT_R5G6B5_UNORM;
131 *picture_format = PICT_r5g6b5;
132 assert(*bbp == 16);
133 break;
134 case 15:
135 *format = PIPE_FORMAT_A1R5G5B5_UNORM;
136 *picture_format = PICT_x1r5g5b5;
137 assert(*bbp == 16);
138 break;
139 case 8:
140 *format = PIPE_FORMAT_L8_UNORM;
141 *picture_format = PICT_a8;
142 assert(*bbp == 8);
143 break;
144 case 4:
145 case 1:
146 *format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
147 break;
148 default:
149 assert(0);
150 break;
151 }
152 }
153
154
155 /*
156 * Static exported EXA functions
157 */
158
159 static void
160 ExaWaitMarker(ScreenPtr pScreen, int marker)
161 {
162 /* Nothing to do, handled in the PrepareAccess hook */
163 }
164
165 static int
166 ExaMarkSync(ScreenPtr pScreen)
167 {
168 return 1;
169 }
170
171
172 /***********************************************************************
173 * Screen upload/download
174 */
175
176 static Bool
177 ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst,
178 int dst_pitch)
179 {
180 ScreenPtr pScreen = pPix->drawable.pScreen;
181 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
182 modesettingPtr ms = modesettingPTR(pScrn);
183 struct exa_context *exa = ms->exa;
184 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
185 struct pipe_transfer *transfer;
186
187 if (!priv || !priv->tex)
188 return FALSE;
189
190 if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
191 PIPE_REFERENCED_FOR_WRITE)
192 exa->pipe->flush(exa->pipe, 0, NULL);
193
194 transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
195 PIPE_TRANSFER_READ, x, y, w, h);
196 if (!transfer)
197 return FALSE;
198
199 #if DEBUG_PRINT
200 debug_printf("------ ExaDownloadFromScreen(%d, %d, %d, %d, %d)\n",
201 x, y, w, h, dst_pitch);
202 #endif
203
204 util_copy_rect((unsigned char*)dst, &priv->tex->block, dst_pitch, 0, 0,
205 w, h, exa->scrn->transfer_map(exa->scrn, transfer),
206 transfer->stride, 0, 0);
207
208 exa->scrn->transfer_unmap(exa->scrn, transfer);
209 exa->scrn->tex_transfer_destroy(transfer);
210
211 return TRUE;
212 }
213
214 static Bool
215 ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src,
216 int src_pitch)
217 {
218 ScreenPtr pScreen = pPix->drawable.pScreen;
219 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
220 modesettingPtr ms = modesettingPTR(pScrn);
221 struct exa_context *exa = ms->exa;
222 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
223 struct pipe_transfer *transfer;
224
225 if (!priv || !priv->tex)
226 return FALSE;
227
228 /* make sure that any pending operations are flushed to hardware */
229 if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
230 (PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE))
231 xorg_exa_flush(exa, 0, NULL);
232
233 transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
234 PIPE_TRANSFER_WRITE, x, y, w, h);
235 if (!transfer)
236 return FALSE;
237
238 #if DEBUG_PRINT
239 debug_printf("++++++ ExaUploadToScreen(%d, %d, %d, %d, %d)\n",
240 x, y, w, h, src_pitch);
241 #endif
242
243 util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
244 &priv->tex->block, transfer->stride, 0, 0, w, h,
245 (unsigned char*)src, src_pitch, 0, 0);
246
247 exa->scrn->transfer_unmap(exa->scrn, transfer);
248 exa->scrn->tex_transfer_destroy(transfer);
249
250 return TRUE;
251 }
252
253 static Bool
254 ExaPrepareAccess(PixmapPtr pPix, int index)
255 {
256 ScreenPtr pScreen = pPix->drawable.pScreen;
257 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
258 modesettingPtr ms = modesettingPTR(pScrn);
259 struct exa_context *exa = ms->exa;
260 struct exa_pixmap_priv *priv;
261
262 priv = exaGetPixmapDriverPrivate(pPix);
263
264 if (!priv)
265 return FALSE;
266
267 if (!priv->tex)
268 return FALSE;
269
270 if (priv->map_count == 0)
271 {
272 if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
273 PIPE_REFERENCED_FOR_WRITE)
274 exa->pipe->flush(exa->pipe, 0, NULL);
275
276 priv->map_transfer =
277 exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
278 #ifdef EXA_MIXED_PIXMAPS
279 PIPE_TRANSFER_MAP_DIRECTLY |
280 #endif
281 PIPE_TRANSFER_READ_WRITE,
282 0, 0, priv->tex->width[0], priv->tex->height[0]);
283 if (!priv->map_transfer)
284 #ifdef EXA_MIXED_PIXMAPS
285 return FALSE;
286 #else
287 FatalError("failed to create transfer\n");
288 #endif
289
290 pPix->devPrivate.ptr =
291 exa->scrn->transfer_map(exa->scrn, priv->map_transfer);
292 pPix->devKind = priv->map_transfer->stride;
293 }
294
295 priv->map_count++;
296
297 return TRUE;
298 }
299
300 static void
301 ExaFinishAccess(PixmapPtr pPix, int index)
302 {
303 ScreenPtr pScreen = pPix->drawable.pScreen;
304 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
305 modesettingPtr ms = modesettingPTR(pScrn);
306 struct exa_context *exa = ms->exa;
307 struct exa_pixmap_priv *priv;
308 priv = exaGetPixmapDriverPrivate(pPix);
309
310 if (!priv)
311 return;
312
313 if (!priv->map_transfer)
314 return;
315
316 if (--priv->map_count == 0) {
317 assert(priv->map_transfer);
318 exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
319 exa->scrn->tex_transfer_destroy(priv->map_transfer);
320 priv->map_transfer = NULL;
321 pPix->devPrivate.ptr = NULL;
322 }
323 }
324
325 /***********************************************************************
326 * Solid Fills
327 */
328
329 static Bool
330 ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
331 {
332 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
333 modesettingPtr ms = modesettingPTR(pScrn);
334 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
335 struct exa_context *exa = ms->exa;
336
337 #if DEBUG_PRINT
338 debug_printf("ExaPrepareSolid(0x%x)\n", fg);
339 #endif
340 if (!exa->pipe)
341 XORG_FALLBACK("accle not enabled");
342
343 if (!priv || !priv->tex)
344 XORG_FALLBACK("%s", !priv ? "!priv" : "!priv->tex");
345
346 if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
347 XORG_FALLBACK("planeMask is not solid");
348
349 if (alu != GXcopy)
350 XORG_FALLBACK("not GXcopy");
351
352 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
353 priv->tex->target,
354 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
355 XORG_FALLBACK("format %s", pf_name(priv->tex->format));
356 }
357
358 return exa->accel && xorg_solid_bind_state(exa, priv, fg);
359 }
360
361 static void
362 ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
363 {
364 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
365 modesettingPtr ms = modesettingPTR(pScrn);
366 struct exa_context *exa = ms->exa;
367 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
368
369 #if DEBUG_PRINT
370 debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
371 #endif
372
373 if (x0 == 0 && y0 == 0 &&
374 x1 == pPixmap->drawable.width && y1 == pPixmap->drawable.height) {
375 exa->pipe->clear(exa->pipe, PIPE_CLEAR_COLOR, exa->solid_color, 0.0, 0);
376 return;
377 }
378
379 xorg_solid(exa, priv, x0, y0, x1, y1) ;
380 }
381
382
383 static void
384 ExaDoneSolid(PixmapPtr pPixmap)
385 {
386 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
387 modesettingPtr ms = modesettingPTR(pScrn);
388 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
389 struct exa_context *exa = ms->exa;
390
391 if (!priv)
392 return;
393
394 xorg_composite_done(exa);
395 }
396
397 /***********************************************************************
398 * Copy Blits
399 */
400
401 static Bool
402 ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
403 int ydir, int alu, Pixel planeMask)
404 {
405 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
406 modesettingPtr ms = modesettingPTR(pScrn);
407 struct exa_context *exa = ms->exa;
408 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
409 struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
410
411 #if DEBUG_PRINT
412 debug_printf("ExaPrepareCopy\n");
413 #endif
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_TEXTURE_USAGE_RENDER_TARGET, 0))
432 XORG_FALLBACK("pDst format %s", pf_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_TEXTURE_USAGE_SAMPLER, 0))
437 XORG_FALLBACK("pSrc format %s", pf_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_BUFFER_USAGE_GPU_READ);
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_BUFFER_USAGE_GPU_WRITE );
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_texture_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_BUFFER_USAGE_GPU_WRITE);
479
480
481 renderer_copy_prepare(exa->renderer,
482 exa->copy.dst_surface,
483 exa->copy.src_texture );
484 }
485
486
487 return exa->accel;
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
506 if (exa->copy.use_surface_copy) {
507 /* XXX: consider exposing >1 box in surface_copy interface.
508 */
509 exa->pipe->surface_copy( exa->pipe,
510 exa->copy.dst_surface,
511 dstX, dstY,
512 exa->copy.src_surface,
513 srcX, srcY,
514 width, height );
515 }
516 else {
517 renderer_copy_pixmap(exa->renderer,
518 dstX, dstY,
519 srcX, srcY,
520 width, height,
521 exa->copy.src_texture->width[0],
522 exa->copy.src_texture->height[0]);
523 }
524 }
525
526 static void
527 ExaDoneCopy(PixmapPtr pPixmap)
528 {
529 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
530 modesettingPtr ms = modesettingPTR(pScrn);
531 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
532 struct exa_context *exa = ms->exa;
533
534 if (!priv)
535 return;
536
537 renderer_draw_flush(exa->renderer);
538
539 exa->copy.src = NULL;
540 exa->copy.dst = NULL;
541 pipe_surface_reference(&exa->copy.src_surface, NULL);
542 pipe_surface_reference(&exa->copy.dst_surface, NULL);
543 pipe_texture_reference(&exa->copy.src_texture, NULL);
544 }
545
546
547
548 static Bool
549 picture_check_formats(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture)
550 {
551 if (pSrc->picture_format == pSrcPicture->format)
552 return TRUE;
553
554 if (pSrc->picture_format != PICT_a8r8g8b8)
555 return FALSE;
556
557 /* pSrc->picture_format == PICT_a8r8g8b8 */
558 switch (pSrcPicture->format) {
559 case PICT_a8r8g8b8:
560 case PICT_x8r8g8b8:
561 case PICT_a8b8g8r8:
562 case PICT_x8b8g8r8:
563 /* just treat these two as x8... */
564 case PICT_r8g8b8:
565 case PICT_b8g8r8:
566 return TRUE;
567 #ifdef PICT_TYPE_BGRA
568 case PICT_b8g8r8a8:
569 case PICT_b8g8r8x8:
570 return FALSE; /* does not support swizzleing the alpha channel yet */
571 case PICT_a2r10g10b10:
572 case PICT_x2r10g10b10:
573 case PICT_a2b10g10r10:
574 case PICT_x2b10g10r10:
575 return FALSE;
576 #endif
577 default:
578 return FALSE;
579 }
580 return FALSE;
581 }
582
583 /***********************************************************************
584 * Composite entrypoints
585 */
586
587 static Bool
588 ExaCheckComposite(int op,
589 PicturePtr pSrcPicture, PicturePtr pMaskPicture,
590 PicturePtr pDstPicture)
591 {
592 ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum];
593 modesettingPtr ms = modesettingPTR(pScrn);
594 struct exa_context *exa = ms->exa;
595 boolean accelerated = xorg_composite_accelerated(op,
596 pSrcPicture,
597 pMaskPicture,
598 pDstPicture);
599 #if DEBUG_PRINT
600 debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
601 op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
602 #endif
603 return exa->accel && accelerated;
604 }
605
606
607 static Bool
608 ExaPrepareComposite(int op, PicturePtr pSrcPicture,
609 PicturePtr pMaskPicture, PicturePtr pDstPicture,
610 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
611 {
612 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
613 modesettingPtr ms = modesettingPTR(pScrn);
614 struct exa_context *exa = ms->exa;
615 struct exa_pixmap_priv *priv;
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,
634 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
635 XORG_FALLBACK("pDst format: %s", pf_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,
649 PIPE_TEXTURE_USAGE_SAMPLER, 0))
650 XORG_FALLBACK("pSrc format: %s", pf_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,
666 PIPE_TEXTURE_USAGE_SAMPLER, 0))
667 XORG_FALLBACK("pMask format: %s", pf_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 exa->accel &&
676 xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
677 pDstPicture,
678 pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
679 pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
680 exaGetPixmapDriverPrivate(pDst));
681 }
682
683 static void
684 ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
685 int dstX, int dstY, int width, int height)
686 {
687 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
688 modesettingPtr ms = modesettingPTR(pScrn);
689 struct exa_context *exa = ms->exa;
690 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
691
692 #if DEBUG_PRINT
693 debug_printf("\tExaComposite(src[%d,%d], mask=[%d, %d], dst=[%d, %d], dim=[%d, %d])\n",
694 srcX, srcY, maskX, maskY, dstX, dstY, width, height);
695 debug_printf("\t Num bound samplers = %d\n",
696 exa->num_bound_samplers);
697 #endif
698
699 xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
700 dstX, dstY, width, height);
701 }
702
703
704
705 static void
706 ExaDoneComposite(PixmapPtr pPixmap)
707 {
708 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
709 modesettingPtr ms = modesettingPTR(pScrn);
710 struct exa_context *exa = ms->exa;
711
712 xorg_composite_done(exa);
713 }
714
715
716 /***********************************************************************
717 * Pixmaps
718 */
719
720 static void *
721 ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
722 {
723 struct exa_pixmap_priv *priv;
724
725 priv = xcalloc(1, sizeof(struct exa_pixmap_priv));
726 if (!priv)
727 return NULL;
728
729 return priv;
730 }
731
732 static void
733 ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
734 {
735 struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
736
737 if (!priv)
738 return;
739
740 pipe_texture_reference(&priv->tex, NULL);
741
742 xfree(priv);
743 }
744
745 static Bool
746 ExaPixmapIsOffscreen(PixmapPtr pPixmap)
747 {
748 struct exa_pixmap_priv *priv;
749
750 priv = exaGetPixmapDriverPrivate(pPixmap);
751
752 if (!priv)
753 return FALSE;
754
755 if (priv->tex)
756 return TRUE;
757
758 return FALSE;
759 }
760
761 int
762 xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
763 {
764 struct exa_pixmap_priv *priv;
765 priv = exaGetPixmapDriverPrivate(pPixmap);
766
767 if (!priv) {
768 FatalError("NO PIXMAP PRIVATE\n");
769 return 0;
770 }
771
772 priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY;
773
774 return 0;
775 }
776
777 int
778 xorg_exa_set_shared_usage(PixmapPtr pPixmap)
779 {
780 struct exa_pixmap_priv *priv;
781 priv = exaGetPixmapDriverPrivate(pPixmap);
782
783 if (!priv) {
784 FatalError("NO PIXMAP PRIVATE\n");
785 return 0;
786 }
787
788 priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
789
790 return 0;
791 }
792
793 unsigned
794 xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
795 {
796 ScreenPtr pScreen = pPixmap->drawable.pScreen;
797 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
798 modesettingPtr ms = modesettingPTR(pScrn);
799 struct exa_pixmap_priv *priv;
800 unsigned handle;
801 unsigned stride;
802
803 if (!ms->exa) {
804 FatalError("NO MS->EXA\n");
805 return 0;
806 }
807
808 priv = exaGetPixmapDriverPrivate(pPixmap);
809
810 if (!priv) {
811 FatalError("NO PIXMAP PRIVATE\n");
812 return 0;
813 }
814
815 ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle);
816 if (stride_out)
817 *stride_out = stride;
818
819 return handle;
820 }
821
822 static Bool
823 ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
824 int depth, int bitsPerPixel, int devKind,
825 pointer pPixData)
826 {
827 ScreenPtr pScreen = pPixmap->drawable.pScreen;
828 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
829 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
830 modesettingPtr ms = modesettingPTR(pScrn);
831 struct exa_context *exa = ms->exa;
832
833 if (!priv || pPixData)
834 return FALSE;
835
836 if (0) {
837 debug_printf("%s pixmap %p sz %dx%dx%d devKind %d\n",
838 __FUNCTION__, pPixmap, width, height, bitsPerPixel, devKind);
839
840 if (priv->tex)
841 debug_printf(" ==> old texture %dx%d\n",
842 priv->tex->width[0],
843 priv->tex->height[0]);
844 }
845
846
847 if (depth <= 0)
848 depth = pPixmap->drawable.depth;
849
850 if (bitsPerPixel <= 0)
851 bitsPerPixel = pPixmap->drawable.bitsPerPixel;
852
853 if (width <= 0)
854 width = pPixmap->drawable.width;
855
856 if (height <= 0)
857 height = pPixmap->drawable.height;
858
859 if (width <= 0 || height <= 0 || depth <= 0)
860 return FALSE;
861
862 miModifyPixmapHeader(pPixmap, width, height, depth,
863 bitsPerPixel, devKind, NULL);
864
865 /* Deal with screen resize */
866 if ((exa->accel || priv->flags) &&
867 (!priv->tex ||
868 (priv->tex->width[0] != width ||
869 priv->tex->height[0] != height ||
870 priv->tex_flags != priv->flags))) {
871 struct pipe_texture *texture = NULL;
872 struct pipe_texture 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 pf_get_block(template.format, &template.block);
878 #if 1
879 template.width[0] = util_next_power_of_two(width);
880 template.height[0] = util_next_power_of_two(height);
881 #else
882 template.width[0] = width;
883 template.height[0] = height;
884 #endif
885 template.depth[0] = 1;
886 template.last_level = 0;
887 template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
888 priv->tex_flags = priv->flags;
889 texture = exa->scrn->texture_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_BUFFER_USAGE_GPU_WRITE);
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->width[0]),
901 min(height, texture->height[0]));
902 } else {
903 util_surface_copy(exa->pipe, FALSE, dst_surf, 0, 0, src_surf,
904 0, 0, min(width, texture->width[0]),
905 min(height, texture->height[0]));
906 }
907 exa->scrn->tex_surface_destroy(dst_surf);
908 exa->scrn->tex_surface_destroy(src_surf);
909 }
910
911 pipe_texture_reference(&priv->tex, texture);
912 /* the texture we create has one reference */
913 pipe_texture_reference(&texture, NULL);
914 }
915
916 return TRUE;
917 }
918
919 struct pipe_texture *
920 xorg_exa_get_texture(PixmapPtr pPixmap)
921 {
922 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
923 struct pipe_texture *tex = NULL;
924 pipe_texture_reference(&tex, priv->tex);
925 return tex;
926 }
927
928 Bool
929 xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_texture *tex)
930 {
931 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
932
933 int mask = PIPE_TEXTURE_USAGE_PRIMARY | PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
934
935 if (!priv)
936 return FALSE;
937
938 if (pPixmap->drawable.width != tex->width[0] ||
939 pPixmap->drawable.height != tex->height[0])
940 return FALSE;
941
942 pipe_texture_reference(&priv->tex, tex);
943 priv->tex_flags = tex->tex_usage & mask;
944
945 return TRUE;
946 }
947
948 struct pipe_texture *
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_texture 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 pf_get_block(template.format, &template.block);
962 template.width[0] = width;
963 template.height[0] = height;
964 template.depth[0] = 1;
965 template.last_level = 0;
966 template.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
967 template.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
968 template.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
969
970 return exa->scrn->texture_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 renderer_destroy(exa->renderer);
980
981 if (exa->pipe)
982 exa->pipe->destroy(exa->pipe);
983
984 exaDriverFini(pScrn->pScreen);
985 xfree(exa);
986 ms->exa = NULL;
987 }
988
989 void *
990 xorg_exa_init(ScrnInfoPtr pScrn, Bool accel)
991 {
992 modesettingPtr ms = modesettingPTR(pScrn);
993 struct exa_context *exa;
994 ExaDriverPtr pExa;
995
996 exa = xcalloc(1, sizeof(struct exa_context));
997 if (!exa)
998 return NULL;
999
1000 pExa = exaDriverAlloc();
1001 if (!pExa) {
1002 goto out_err;
1003 }
1004
1005 memset(pExa, 0, sizeof(*pExa));
1006
1007 pExa->exa_major = 2;
1008 pExa->exa_minor = 2;
1009 pExa->memoryBase = 0;
1010 pExa->memorySize = 0;
1011 pExa->offScreenBase = 0;
1012 pExa->pixmapOffsetAlign = 0;
1013 pExa->pixmapPitchAlign = 1;
1014 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
1015 #ifdef EXA_SUPPORTS_PREPARE_AUX
1016 pExa->flags |= EXA_SUPPORTS_PREPARE_AUX;
1017 #endif
1018 #ifdef EXA_MIXED_PIXMAPS
1019 pExa->flags |= EXA_MIXED_PIXMAPS;
1020 #endif
1021 pExa->maxX = 8191; /* FIXME */
1022 pExa->maxY = 8191; /* FIXME */
1023
1024 pExa->WaitMarker = ExaWaitMarker;
1025 pExa->MarkSync = ExaMarkSync;
1026 pExa->PrepareSolid = ExaPrepareSolid;
1027 pExa->Solid = ExaSolid;
1028 pExa->DoneSolid = ExaDoneSolid;
1029 pExa->PrepareCopy = ExaPrepareCopy;
1030 pExa->Copy = ExaCopy;
1031 pExa->DoneCopy = ExaDoneCopy;
1032 pExa->CheckComposite = ExaCheckComposite;
1033 pExa->PrepareComposite = ExaPrepareComposite;
1034 pExa->Composite = ExaComposite;
1035 pExa->DoneComposite = ExaDoneComposite;
1036 pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen;
1037 pExa->DownloadFromScreen = ExaDownloadFromScreen;
1038 pExa->UploadToScreen = ExaUploadToScreen;
1039 pExa->PrepareAccess = ExaPrepareAccess;
1040 pExa->FinishAccess = ExaFinishAccess;
1041 pExa->CreatePixmap = ExaCreatePixmap;
1042 pExa->DestroyPixmap = ExaDestroyPixmap;
1043 pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
1044
1045 if (!exaDriverInit(pScrn->pScreen, pExa)) {
1046 goto out_err;
1047 }
1048
1049 exa->scrn = ms->screen;
1050 exa->pipe = ms->api->create_context(ms->api, exa->scrn);
1051 /* Share context with DRI */
1052 ms->ctx = exa->pipe;
1053
1054 exa->renderer = renderer_create(exa->pipe);
1055 exa->accel = accel;
1056
1057 return (void *)exa;
1058
1059 out_err:
1060 xorg_exa_close(pScrn);
1061
1062 return NULL;
1063 }
1064
1065 struct pipe_surface *
1066 xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv)
1067 {
1068 return scrn->get_tex_surface(scrn, priv->tex, 0, 0, 0,
1069 PIPE_BUFFER_USAGE_GPU_READ |
1070 PIPE_BUFFER_USAGE_GPU_WRITE);
1071
1072 }
1073
1074 void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
1075 struct pipe_fence_handle **fence)
1076 {
1077 exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
1078 }
1079
1080 void xorg_exa_finish(struct exa_context *exa)
1081 {
1082 struct pipe_fence_handle *fence = NULL;
1083
1084 xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
1085
1086 exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
1087 exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
1088 }
1089