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