st/xorg: lots of fixes related to compositing
[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
48 #define DEBUG_PRINT 0
49 #define DEBUG_SOLID 0
50 #define ACCEL_ENABLED TRUE
51
52 /*
53 * Helper functions
54 */
55
56 static void
57 exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
58 {
59 switch (depth) {
60 case 32:
61 *format = PIPE_FORMAT_A8R8G8B8_UNORM;
62 assert(*bbp == 32);
63 break;
64 case 24:
65 *format = PIPE_FORMAT_X8R8G8B8_UNORM;
66 assert(*bbp == 32);
67 break;
68 case 16:
69 *format = PIPE_FORMAT_R5G6B5_UNORM;
70 assert(*bbp == 16);
71 break;
72 case 15:
73 *format = PIPE_FORMAT_A1R5G5B5_UNORM;
74 assert(*bbp == 16);
75 break;
76 case 8:
77 *format = PIPE_FORMAT_L8_UNORM;
78 assert(*bbp == 8);
79 break;
80 case 4:
81 case 1:
82 *format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
83 break;
84 default:
85 assert(0);
86 break;
87 }
88 }
89
90 static void
91 xorg_exa_common_done(struct exa_context *exa)
92 {
93 exa->copy.src = NULL;
94 exa->copy.dst = NULL;
95 exa->transform.has_src = FALSE;
96 exa->transform.has_mask = FALSE;
97 exa->has_solid_color = FALSE;
98 exa->num_bound_samplers = 0;
99 }
100
101 /*
102 * Static exported EXA functions
103 */
104
105 static void
106 ExaWaitMarker(ScreenPtr pScreen, int marker)
107 {
108 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
109 modesettingPtr ms = modesettingPTR(pScrn);
110 struct exa_context *exa = ms->exa;
111
112 #if 0
113 xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL);
114 #else
115 xorg_exa_finish(exa);
116 #endif
117 }
118
119 static int
120 ExaMarkSync(ScreenPtr pScreen)
121 {
122 return 1;
123 }
124
125 static Bool
126 ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst,
127 int dst_pitch)
128 {
129 ScreenPtr pScreen = pPix->drawable.pScreen;
130 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
131 modesettingPtr ms = modesettingPTR(pScrn);
132 struct exa_context *exa = ms->exa;
133 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
134 struct pipe_transfer *transfer;
135
136 if (!priv || !priv->tex)
137 return FALSE;
138
139 if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
140 PIPE_REFERENCED_FOR_WRITE)
141 exa->pipe->flush(exa->pipe, 0, NULL);
142
143 transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
144 PIPE_TRANSFER_READ, x, y, w, h);
145 if (!transfer)
146 return FALSE;
147
148 #if DEBUG_PRINT
149 debug_printf("------ ExaDownloadFromScreen(%d, %d, %d, %d, %d)\n",
150 x, y, w, h, dst_pitch);
151 #endif
152
153 util_copy_rect((unsigned char*)dst, &priv->tex->block, dst_pitch, 0, 0,
154 w, h, exa->scrn->transfer_map(exa->scrn, transfer),
155 transfer->stride, 0, 0);
156
157 exa->scrn->transfer_unmap(exa->scrn, transfer);
158 exa->scrn->tex_transfer_destroy(transfer);
159
160 return TRUE;
161 }
162
163 static Bool
164 ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src,
165 int src_pitch)
166 {
167 ScreenPtr pScreen = pPix->drawable.pScreen;
168 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
169 modesettingPtr ms = modesettingPTR(pScrn);
170 struct exa_context *exa = ms->exa;
171 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
172 struct pipe_transfer *transfer;
173
174 if (!priv || !priv->tex)
175 return FALSE;
176
177 transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
178 PIPE_TRANSFER_WRITE, x, y, w, h);
179 if (!transfer)
180 return FALSE;
181
182 #if DEBUG_PRINT
183 debug_printf("++++++ ExaUploadToScreen(%d, %d, %d, %d, %d)\n",
184 x, y, w, h, src_pitch);
185 #endif
186
187 util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
188 &priv->tex->block, transfer->stride, 0, 0, w, h,
189 (unsigned char*)src, src_pitch, 0, 0);
190
191 exa->scrn->transfer_unmap(exa->scrn, transfer);
192 exa->scrn->tex_transfer_destroy(transfer);
193
194 return TRUE;
195 }
196
197 static Bool
198 ExaPrepareAccess(PixmapPtr pPix, int index)
199 {
200 ScreenPtr pScreen = pPix->drawable.pScreen;
201 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
202 modesettingPtr ms = modesettingPTR(pScrn);
203 struct exa_context *exa = ms->exa;
204 struct exa_pixmap_priv *priv;
205
206 priv = exaGetPixmapDriverPrivate(pPix);
207
208 if (!priv)
209 return FALSE;
210
211 if (!priv->tex)
212 return FALSE;
213
214 if (priv->map_count == 0)
215 {
216 if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
217 PIPE_REFERENCED_FOR_WRITE)
218 exa->pipe->flush(exa->pipe, 0, NULL);
219
220 priv->map_transfer =
221 exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
222 #ifdef EXA_MIXED_PIXMAPS
223 PIPE_TRANSFER_MAP_DIRECTLY |
224 #endif
225 PIPE_TRANSFER_READ_WRITE,
226 0, 0, priv->tex->width[0], priv->tex->height[0]);
227 if (!priv->map_transfer)
228 #ifdef EXA_MIXED_PIXMAPS
229 return FALSE;
230 #else
231 FatalError("failed to create transfer\n");
232 #endif
233
234 pPix->devPrivate.ptr =
235 exa->scrn->transfer_map(exa->scrn, priv->map_transfer);
236 pPix->devKind = priv->map_transfer->stride;
237 }
238
239 priv->map_count++;
240
241 return TRUE;
242 }
243
244 static void
245 ExaFinishAccess(PixmapPtr pPix, int index)
246 {
247 ScreenPtr pScreen = pPix->drawable.pScreen;
248 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
249 modesettingPtr ms = modesettingPTR(pScrn);
250 struct exa_context *exa = ms->exa;
251 struct exa_pixmap_priv *priv;
252 priv = exaGetPixmapDriverPrivate(pPix);
253
254 if (!priv)
255 return;
256
257 if (!priv->map_transfer)
258 return;
259
260 if (--priv->map_count == 0) {
261 assert(priv->map_transfer);
262 exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
263 exa->scrn->tex_transfer_destroy(priv->map_transfer);
264 priv->map_transfer = NULL;
265 pPix->devPrivate.ptr = NULL;
266 }
267 }
268
269 static void
270 ExaDone(PixmapPtr pPixmap)
271 {
272 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
273 modesettingPtr ms = modesettingPTR(pScrn);
274 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
275 struct exa_context *exa = ms->exa;
276
277 if (!priv)
278 return;
279
280 xorg_exa_common_done(exa);
281 }
282
283 static void
284 ExaDoneComposite(PixmapPtr pPixmap)
285 {
286 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
287 modesettingPtr ms = modesettingPTR(pScrn);
288 struct exa_context *exa = ms->exa;
289
290 xorg_exa_common_done(exa);
291 }
292
293 static Bool
294 ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
295 {
296 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
297 modesettingPtr ms = modesettingPTR(pScrn);
298 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
299 struct exa_context *exa = ms->exa;
300
301 #if DEBUG_PRINT
302 debug_printf("ExaPrepareSolid(0x%x)\n", fg);
303 #endif
304 if (!exa->pipe)
305 XORG_FALLBACK("accle not enabled");
306
307 if (!priv || !priv->tex)
308 XORG_FALLBACK("%s", !priv ? "!priv" : "!priv->tex");
309
310 if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
311 XORG_FALLBACK("planeMask is not solid");
312
313 if (alu != GXcopy)
314 XORG_FALLBACK("not GXcopy");
315
316 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
317 priv->tex->target,
318 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
319 XORG_FALLBACK("format %s", pf_name(priv->tex->format));
320 }
321
322 #if DEBUG_SOLID
323 fg = 0xffff0000;
324 #endif
325
326 return ACCEL_ENABLED && xorg_solid_bind_state(exa, priv, fg);
327 }
328
329 static void
330 ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
331 {
332 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
333 modesettingPtr ms = modesettingPTR(pScrn);
334 struct exa_context *exa = ms->exa;
335 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
336
337 #if DEBUG_PRINT
338 debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
339 #endif
340
341 #if 0
342 if (x0 == 0 && y0 == 0 &&
343 x1 == priv->tex->width[0] &&
344 y1 == priv->tex->height[0]) {
345 exa->ctx->clear(exa->pipe, PIPE_CLEAR_COLOR,
346 exa->solid_color, 1., 0);
347 } else
348 #endif
349
350 #if DEBUG_SOLID
351 exa->solid_color[0] = 0.f;
352 exa->solid_color[1] = 1.f;
353 exa->solid_color[2] = 0.f;
354 exa->solid_color[3] = 1.f;
355 xorg_solid(exa, priv, 0, 0, 1024, 768);
356 exa->solid_color[0] = 1.f;
357 exa->solid_color[1] = 0.f;
358 exa->solid_color[2] = 0.f;
359 exa->solid_color[3] = 1.f;
360 xorg_solid(exa, priv, 0, 0, 300, 300);
361 xorg_solid(exa, priv, 300, 300, 350, 350);
362 xorg_solid(exa, priv, 350, 350, 500, 500);
363
364 xorg_solid(exa, priv,
365 priv->tex->width[0] - 10,
366 priv->tex->height[0] - 10,
367 priv->tex->width[0],
368 priv->tex->height[0]);
369
370 exa->solid_color[0] = 0.f;
371 exa->solid_color[1] = 0.f;
372 exa->solid_color[2] = 1.f;
373 exa->solid_color[3] = 1.f;
374
375 exa->has_solid_color = FALSE;
376 ExaPrepareCopy(pPixmap, pPixmap, 0, 0, GXcopy, 0xffffffff);
377 ExaCopy(pPixmap, 0, 0, 50, 50, 500, 500);
378 #else
379 xorg_solid(exa, priv, x0, y0, x1, y1) ;
380 #endif
381 }
382
383 static Bool
384 ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
385 int ydir, int alu, Pixel planeMask)
386 {
387 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
388 modesettingPtr ms = modesettingPTR(pScrn);
389 struct exa_context *exa = ms->exa;
390 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
391 struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
392
393 #if DEBUG_PRINT
394 debug_printf("ExaPrepareCopy\n");
395 #endif
396 if (!exa->pipe)
397 XORG_FALLBACK("accle not enabled");
398
399 if (!priv || !priv->tex)
400 XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
401
402 if (!src_priv || !src_priv->tex)
403 XORG_FALLBACK("pSrc %s", !src_priv ? "!priv" : "!priv->tex");
404
405 if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
406 XORG_FALLBACK("planeMask is not solid");
407
408 if (alu != GXcopy)
409 XORG_FALLBACK("alu not GXcopy");
410
411 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
412 priv->tex->target,
413 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
414 XORG_FALLBACK("pDst format %s", pf_name(priv->tex->format));
415
416 if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format,
417 src_priv->tex->target,
418 PIPE_TEXTURE_USAGE_SAMPLER, 0))
419 XORG_FALLBACK("pSrc format %s", pf_name(src_priv->tex->format));
420
421 exa->copy.src = src_priv;
422 exa->copy.dst = priv;
423
424 return ACCEL_ENABLED;
425 }
426
427 static void
428 ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
429 int width, int height)
430 {
431 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
432 modesettingPtr ms = modesettingPTR(pScrn);
433 struct exa_context *exa = ms->exa;
434 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
435
436 #if DEBUG_PRINT
437 debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
438 srcX, srcY, dstX, dstY, width, height);
439 #endif
440
441 debug_assert(priv == exa->copy.dst);
442
443 renderer_copy_pixmap(exa->renderer, exa->copy.dst, dstX, dstY,
444 exa->copy.src, srcX, srcY,
445 width, height);
446 }
447
448 static Bool
449 ExaPrepareComposite(int op, PicturePtr pSrcPicture,
450 PicturePtr pMaskPicture, PicturePtr pDstPicture,
451 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
452 {
453 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
454 modesettingPtr ms = modesettingPTR(pScrn);
455 struct exa_context *exa = ms->exa;
456 struct exa_pixmap_priv *priv;
457
458 #if DEBUG_PRINT
459 debug_printf("ExaPrepareComposite(%d, src=0x%p, mask=0x%p, dst=0x%p)\n",
460 op, pSrcPicture, pMaskPicture, pDstPicture);
461 #endif
462 if (!exa->pipe)
463 XORG_FALLBACK("accle not enabled");
464
465 priv = exaGetPixmapDriverPrivate(pDst);
466 if (!priv || !priv->tex)
467 XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
468
469 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
470 priv->tex->target,
471 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
472 XORG_FALLBACK("pDst format: %s", pf_name(priv->tex->format));
473
474 if (pSrc) {
475 priv = exaGetPixmapDriverPrivate(pSrc);
476 if (!priv || !priv->tex)
477 XORG_FALLBACK("pSrc %s", !priv ? "!priv" : "!priv->tex");
478
479 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
480 priv->tex->target,
481 PIPE_TEXTURE_USAGE_SAMPLER, 0))
482 XORG_FALLBACK("pSrc format: %s", pf_name(priv->tex->format));
483 }
484
485 if (pMask) {
486 priv = exaGetPixmapDriverPrivate(pMask);
487 if (!priv || !priv->tex)
488 XORG_FALLBACK("pMask %s", !priv ? "!priv" : "!priv->tex");
489
490 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
491 priv->tex->target,
492 PIPE_TEXTURE_USAGE_SAMPLER, 0))
493 XORG_FALLBACK("pMask format: %s", pf_name(priv->tex->format));
494 }
495
496 return ACCEL_ENABLED &&
497 xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
498 pDstPicture,
499 pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
500 pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
501 exaGetPixmapDriverPrivate(pDst));
502 }
503
504 static void
505 ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
506 int dstX, int dstY, int width, int height)
507 {
508 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
509 modesettingPtr ms = modesettingPTR(pScrn);
510 struct exa_context *exa = ms->exa;
511 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
512
513 #if DEBUG_PRINT
514 debug_printf("\tExaComposite(src[%d,%d], mask=[%d, %d], dst=[%d, %d], dim=[%d, %d])\n",
515 srcX, srcY, maskX, maskY, dstX, dstY, width, height);
516 debug_printf("\t Num bound samplers = %d\n",
517 exa->num_bound_samplers);
518 #endif
519
520 xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
521 dstX, dstY, width, height);
522 }
523
524 static Bool
525 ExaCheckComposite(int op,
526 PicturePtr pSrcPicture, PicturePtr pMaskPicture,
527 PicturePtr pDstPicture)
528 {
529 boolean accelerated = xorg_composite_accelerated(op,
530 pSrcPicture,
531 pMaskPicture,
532 pDstPicture);
533 #if DEBUG_PRINT
534 debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
535 op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
536 #endif
537 return ACCEL_ENABLED && accelerated;
538 }
539
540 static void *
541 ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
542 {
543 struct exa_pixmap_priv *priv;
544
545 priv = xcalloc(1, sizeof(struct exa_pixmap_priv));
546 if (!priv)
547 return NULL;
548
549 return priv;
550 }
551
552 static void
553 ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
554 {
555 struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
556
557 if (!priv)
558 return;
559
560 pipe_texture_reference(&priv->tex, NULL);
561
562 xfree(priv);
563 }
564
565 static Bool
566 ExaPixmapIsOffscreen(PixmapPtr pPixmap)
567 {
568 struct exa_pixmap_priv *priv;
569
570 priv = exaGetPixmapDriverPrivate(pPixmap);
571
572 if (!priv)
573 return FALSE;
574
575 if (priv->tex)
576 return TRUE;
577
578 return FALSE;
579 }
580
581 int
582 xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
583 {
584 struct exa_pixmap_priv *priv;
585 priv = exaGetPixmapDriverPrivate(pPixmap);
586
587 if (!priv) {
588 FatalError("NO PIXMAP PRIVATE\n");
589 return 0;
590 }
591
592 priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY;
593
594 return 0;
595 }
596
597 int
598 xorg_exa_set_shared_usage(PixmapPtr pPixmap)
599 {
600 struct exa_pixmap_priv *priv;
601 priv = exaGetPixmapDriverPrivate(pPixmap);
602
603 if (!priv) {
604 FatalError("NO PIXMAP PRIVATE\n");
605 return 0;
606 }
607
608 priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
609
610 return 0;
611 }
612
613 unsigned
614 xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
615 {
616 ScreenPtr pScreen = pPixmap->drawable.pScreen;
617 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
618 modesettingPtr ms = modesettingPTR(pScrn);
619 struct exa_pixmap_priv *priv;
620 unsigned handle;
621 unsigned stride;
622
623 if (!ms->exa) {
624 FatalError("NO MS->EXA\n");
625 return 0;
626 }
627
628 priv = exaGetPixmapDriverPrivate(pPixmap);
629
630 if (!priv) {
631 FatalError("NO PIXMAP PRIVATE\n");
632 return 0;
633 }
634
635 ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle);
636 if (stride_out)
637 *stride_out = stride;
638
639 return handle;
640 }
641
642 static Bool
643 ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
644 int depth, int bitsPerPixel, int devKind,
645 pointer pPixData)
646 {
647 ScreenPtr pScreen = pPixmap->drawable.pScreen;
648 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
649 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
650 modesettingPtr ms = modesettingPTR(pScrn);
651 struct exa_context *exa = ms->exa;
652
653 if (!priv || pPixData)
654 return FALSE;
655
656 if (depth <= 0)
657 depth = pPixmap->drawable.depth;
658
659 if (bitsPerPixel <= 0)
660 bitsPerPixel = pPixmap->drawable.bitsPerPixel;
661
662 if (width <= 0)
663 width = pPixmap->drawable.width;
664
665 if (height <= 0)
666 height = pPixmap->drawable.height;
667
668 if (width <= 0 || height <= 0 || depth <= 0)
669 return FALSE;
670
671 miModifyPixmapHeader(pPixmap, width, height, depth,
672 bitsPerPixel, devKind, NULL);
673
674 /* Deal with screen resize */
675 if (!priv->tex ||
676 (priv->tex->width[0] != width ||
677 priv->tex->height[0] != height ||
678 priv->tex_flags != priv->flags)) {
679 struct pipe_texture *texture = NULL;
680 struct pipe_texture template;
681
682 memset(&template, 0, sizeof(template));
683 template.target = PIPE_TEXTURE_2D;
684 exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
685 pf_get_block(template.format, &template.block);
686 template.width[0] = width;
687 template.height[0] = height;
688 template.depth[0] = 1;
689 template.last_level = 0;
690 template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
691 priv->tex_flags = priv->flags;
692 texture = exa->scrn->texture_create(exa->scrn, &template);
693
694 if (priv->tex) {
695 struct pipe_surface *dst_surf;
696 struct pipe_surface *src_surf;
697
698 dst_surf = exa->scrn->get_tex_surface(
699 exa->scrn, texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
700 src_surf = xorg_gpu_surface(exa->pipe->screen, priv);
701 if (exa->pipe->surface_copy) {
702 exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf,
703 0, 0, min(width, texture->width[0]),
704 min(height, texture->height[0]));
705 } else {
706 util_surface_copy(exa->pipe, FALSE, dst_surf, 0, 0, src_surf,
707 0, 0, min(width, texture->width[0]),
708 min(height, texture->height[0]));
709 }
710 exa->scrn->tex_surface_destroy(dst_surf);
711 exa->scrn->tex_surface_destroy(src_surf);
712 }
713
714 pipe_texture_reference(&priv->tex, texture);
715 /* the texture we create has one reference */
716 pipe_texture_reference(&texture, NULL);
717 }
718
719 return TRUE;
720 }
721
722 struct pipe_texture *
723 xorg_exa_get_texture(PixmapPtr pPixmap)
724 {
725 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
726 struct pipe_texture *tex = NULL;
727 pipe_texture_reference(&tex, priv->tex);
728 return tex;
729 }
730
731 Bool
732 xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_texture *tex)
733 {
734 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
735
736 int mask = PIPE_TEXTURE_USAGE_PRIMARY | PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
737
738 if (!priv)
739 return FALSE;
740
741 if (pPixmap->drawable.width != tex->width[0] ||
742 pPixmap->drawable.height != tex->height[0])
743 return FALSE;
744
745 pipe_texture_reference(&priv->tex, tex);
746 priv->tex_flags = tex->tex_usage & mask;
747
748 return TRUE;
749 }
750
751 struct pipe_texture *
752 xorg_exa_create_root_texture(ScrnInfoPtr pScrn,
753 int width, int height,
754 int depth, int bitsPerPixel)
755 {
756 modesettingPtr ms = modesettingPTR(pScrn);
757 struct exa_context *exa = ms->exa;
758 struct pipe_texture template;
759
760 memset(&template, 0, sizeof(template));
761 template.target = PIPE_TEXTURE_2D;
762 exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
763 pf_get_block(template.format, &template.block);
764 template.width[0] = width;
765 template.height[0] = height;
766 template.depth[0] = 1;
767 template.last_level = 0;
768 template.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
769 template.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
770 template.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
771
772 return exa->scrn->texture_create(exa->scrn, &template);
773 }
774
775 void
776 xorg_exa_close(ScrnInfoPtr pScrn)
777 {
778 modesettingPtr ms = modesettingPTR(pScrn);
779 struct exa_context *exa = ms->exa;
780
781 renderer_destroy(exa->renderer);
782
783 if (exa->pipe)
784 exa->pipe->destroy(exa->pipe);
785
786 exaDriverFini(pScrn->pScreen);
787 xfree(exa);
788 ms->exa = NULL;
789 }
790
791 void *
792 xorg_exa_init(ScrnInfoPtr pScrn)
793 {
794 modesettingPtr ms = modesettingPTR(pScrn);
795 struct exa_context *exa;
796 ExaDriverPtr pExa;
797
798 exa = xcalloc(1, sizeof(struct exa_context));
799 if (!exa)
800 return NULL;
801
802 pExa = exaDriverAlloc();
803 if (!pExa) {
804 goto out_err;
805 }
806
807 memset(pExa, 0, sizeof(*pExa));
808
809 pExa->exa_major = 2;
810 pExa->exa_minor = 2;
811 pExa->memoryBase = 0;
812 pExa->memorySize = 0;
813 pExa->offScreenBase = 0;
814 pExa->pixmapOffsetAlign = 0;
815 pExa->pixmapPitchAlign = 1;
816 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
817 #ifdef EXA_SUPPORTS_PREPARE_AUX
818 pExa->flags |= EXA_SUPPORTS_PREPARE_AUX;
819 #endif
820 #ifdef EXA_MIXED_PIXMAPS
821 pExa->flags |= EXA_MIXED_PIXMAPS;
822 #endif
823 pExa->maxX = 8191; /* FIXME */
824 pExa->maxY = 8191; /* FIXME */
825
826 pExa->WaitMarker = ExaWaitMarker;
827 pExa->MarkSync = ExaMarkSync;
828 pExa->PrepareSolid = ExaPrepareSolid;
829 pExa->Solid = ExaSolid;
830 pExa->DoneSolid = ExaDone;
831 pExa->PrepareCopy = ExaPrepareCopy;
832 pExa->Copy = ExaCopy;
833 pExa->DoneCopy = ExaDone;
834 pExa->CheckComposite = ExaCheckComposite;
835 pExa->PrepareComposite = ExaPrepareComposite;
836 pExa->Composite = ExaComposite;
837 pExa->DoneComposite = ExaDoneComposite;
838 pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen;
839 pExa->DownloadFromScreen = ExaDownloadFromScreen;
840 pExa->UploadToScreen = ExaUploadToScreen;
841 pExa->PrepareAccess = ExaPrepareAccess;
842 pExa->FinishAccess = ExaFinishAccess;
843 pExa->CreatePixmap = ExaCreatePixmap;
844 pExa->DestroyPixmap = ExaDestroyPixmap;
845 pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
846
847 if (!exaDriverInit(pScrn->pScreen, pExa)) {
848 goto out_err;
849 }
850
851 exa->scrn = ms->screen;
852 exa->pipe = ms->api->create_context(ms->api, exa->scrn);
853 /* Share context with DRI */
854 ms->ctx = exa->pipe;
855
856 exa->renderer = renderer_create(exa->pipe);
857
858 return (void *)exa;
859
860 out_err:
861 xorg_exa_close(pScrn);
862
863 return NULL;
864 }
865
866 struct pipe_surface *
867 xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv)
868 {
869 return scrn->get_tex_surface(scrn, priv->tex, 0, 0, 0,
870 PIPE_BUFFER_USAGE_GPU_READ |
871 PIPE_BUFFER_USAGE_GPU_WRITE);
872
873 }
874
875 void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
876 struct pipe_fence_handle **fence)
877 {
878 exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
879 }
880
881 void xorg_exa_finish(struct exa_context *exa)
882 {
883 struct pipe_fence_handle *fence = NULL;
884
885 xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
886
887 exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
888 exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
889 }
890