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