Merge branch 'mesa_7_6_branch'
[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 "cso_cache/cso_context.h"
47
48 #include "util/u_rect.h"
49
50 #define DEBUG_PRINT 0
51 #define DEBUG_SOLID 0
52 #define DISABLE_ACCEL 0
53
54 /*
55 * Helper functions
56 */
57
58 static void
59 exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
60 {
61 switch (depth) {
62 case 32:
63 *format = PIPE_FORMAT_A8R8G8B8_UNORM;
64 assert(*bbp == 32);
65 break;
66 case 24:
67 *format = PIPE_FORMAT_X8R8G8B8_UNORM;
68 assert(*bbp == 32);
69 break;
70 case 16:
71 *format = PIPE_FORMAT_R5G6B5_UNORM;
72 assert(*bbp == 16);
73 break;
74 case 15:
75 *format = PIPE_FORMAT_A1R5G5B5_UNORM;
76 assert(*bbp == 16);
77 break;
78 case 8:
79 *format = PIPE_FORMAT_I8_UNORM;
80 assert(*bbp == 8);
81 break;
82 case 4:
83 case 1:
84 *format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
85 break;
86 default:
87 assert(0);
88 break;
89 }
90 }
91
92 static void
93 xorg_exa_init_state(struct exa_context *exa)
94 {
95 struct pipe_depth_stencil_alpha_state dsa;
96
97 /* set common initial clip state */
98 memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
99 cso_set_depth_stencil_alpha(exa->cso, &dsa);
100 }
101
102 static void
103 xorg_exa_common_done(struct exa_context *exa)
104 {
105 exa->copy.src = NULL;
106 exa->copy.dst = NULL;
107 exa->has_solid_color = FALSE;
108 exa->num_bound_samplers = 0;
109 }
110
111 /*
112 * Static exported EXA functions
113 */
114
115 static void
116 ExaWaitMarker(ScreenPtr pScreen, int marker)
117 {
118 }
119
120 static int
121 ExaMarkSync(ScreenPtr pScreen)
122 {
123 return 1;
124 }
125
126 static Bool
127 ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst,
128 int dst_pitch)
129 {
130 ScreenPtr pScreen = pPix->drawable.pScreen;
131 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
132 modesettingPtr ms = modesettingPTR(pScrn);
133 struct exa_context *exa = ms->exa;
134 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
135 struct pipe_transfer *transfer;
136
137 if (!priv || !priv->tex)
138 return FALSE;
139
140 if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
141 PIPE_REFERENCED_FOR_WRITE)
142 exa->pipe->flush(exa->pipe, 0, NULL);
143
144 transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
145 PIPE_TRANSFER_READ, x, y, w, h);
146 if (!transfer)
147 return FALSE;
148
149 util_copy_rect((unsigned char*)dst, &priv->tex->block, dst_pitch, 0, 0,
150 w, h, exa->scrn->transfer_map(exa->scrn, transfer),
151 transfer->stride, 0, 0);
152
153 exa->scrn->transfer_unmap(exa->scrn, transfer);
154 exa->scrn->tex_transfer_destroy(transfer);
155
156 return TRUE;
157 }
158
159 static Bool
160 ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src,
161 int src_pitch)
162 {
163 ScreenPtr pScreen = pPix->drawable.pScreen;
164 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
165 modesettingPtr ms = modesettingPTR(pScrn);
166 struct exa_context *exa = ms->exa;
167 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
168 struct pipe_transfer *transfer;
169
170 if (!priv || !priv->tex)
171 return FALSE;
172
173 transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
174 PIPE_TRANSFER_WRITE, x, y, w, h);
175 if (!transfer)
176 return FALSE;
177
178 util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
179 &priv->tex->block, transfer->stride, 0, 0, w, h,
180 (unsigned char*)src, src_pitch, 0, 0);
181
182 exa->scrn->transfer_unmap(exa->scrn, transfer);
183 exa->scrn->tex_transfer_destroy(transfer);
184
185 return TRUE;
186 }
187
188 static Bool
189 ExaPrepareAccess(PixmapPtr pPix, int index)
190 {
191 ScreenPtr pScreen = pPix->drawable.pScreen;
192 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
193 modesettingPtr ms = modesettingPTR(pScrn);
194 struct exa_context *exa = ms->exa;
195 struct exa_pixmap_priv *priv;
196
197 priv = exaGetPixmapDriverPrivate(pPix);
198
199 if (!priv)
200 return FALSE;
201
202 if (!priv->tex)
203 return FALSE;
204
205 if (priv->map_count == 0)
206 {
207 if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
208 PIPE_REFERENCED_FOR_WRITE)
209 exa->pipe->flush(exa->pipe, 0, NULL);
210
211 priv->map_transfer =
212 exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
213 #ifdef EXA_MIXED_PIXMAPS
214 PIPE_TRANSFER_MAP_DIRECTLY |
215 #endif
216 PIPE_TRANSFER_READ_WRITE,
217 0, 0, priv->tex->width[0], priv->tex->height[0]);
218 if (!priv->map_transfer)
219 return FALSE;
220
221 pPix->devPrivate.ptr =
222 exa->scrn->transfer_map(exa->scrn, priv->map_transfer);
223 pPix->devKind = priv->map_transfer->stride;
224 }
225
226 priv->map_count++;
227
228 return TRUE;
229 }
230
231 static void
232 ExaFinishAccess(PixmapPtr pPix, int index)
233 {
234 ScreenPtr pScreen = pPix->drawable.pScreen;
235 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
236 modesettingPtr ms = modesettingPTR(pScrn);
237 struct exa_context *exa = ms->exa;
238 struct exa_pixmap_priv *priv;
239 priv = exaGetPixmapDriverPrivate(pPix);
240
241 if (!priv)
242 return;
243
244 if (!priv->map_transfer)
245 return;
246
247 if (--priv->map_count == 0) {
248 assert(priv->map_transfer);
249 exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
250 exa->scrn->tex_transfer_destroy(priv->map_transfer);
251 priv->map_transfer = NULL;
252 pPix->devPrivate.ptr = NULL;
253 }
254 }
255
256 static void
257 ExaDone(PixmapPtr pPixmap)
258 {
259 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
260 modesettingPtr ms = modesettingPTR(pScrn);
261 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
262 struct exa_context *exa = ms->exa;
263
264 if (!priv)
265 return;
266
267 #if 1
268 xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL);
269 #else
270 xorg_exa_finish(exa);
271 #endif
272 xorg_exa_common_done(exa);
273 }
274
275 static void
276 ExaDoneComposite(PixmapPtr pPixmap)
277 {
278 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
279 modesettingPtr ms = modesettingPTR(pScrn);
280 struct exa_context *exa = ms->exa;
281
282 xorg_exa_common_done(exa);
283 }
284
285 static Bool
286 ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
287 {
288 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
289 modesettingPtr ms = modesettingPTR(pScrn);
290 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
291 struct exa_context *exa = ms->exa;
292
293 #if DEBUG_PRINT
294 debug_printf("ExaPrepareSolid(0x%x)\n", fg);
295 #endif
296 if (!exa->pipe)
297 XORG_FALLBACK("solid accle not enabled");
298
299 if (!priv || !priv->tex)
300 XORG_FALLBACK("solid !priv || !priv->tex");
301
302 if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
303 XORG_FALLBACK("solid planeMask is not solid");
304
305 if (alu != GXcopy)
306 XORG_FALLBACK("solid not GXcopy");
307
308 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
309 priv->tex->target,
310 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
311 XORG_FALLBACK("solid bad format %s", pf_name(priv->tex->format));
312 }
313
314 #if DEBUG_SOLID
315 fg = 0xffff0000;
316 #endif
317
318 #if DISABLE_ACCEL
319 return FALSE;
320 #else
321 return xorg_solid_bind_state(exa, priv, fg);
322 #endif
323 }
324
325 static void
326 ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
327 {
328 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
329 modesettingPtr ms = modesettingPTR(pScrn);
330 struct exa_context *exa = ms->exa;
331 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
332
333 #if DEBUG_PRINT
334 debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
335 #endif
336
337 #if 0
338 if (x0 == 0 && y0 == 0 &&
339 x1 == priv->tex->width[0] &&
340 y1 == priv->tex->height[0]) {
341 exa->ctx->clear(exa->pipe, PIPE_CLEAR_COLOR,
342 exa->solid_color, 1., 0);
343 } else
344 #endif
345
346 #if DEBUG_SOLID
347 exa->solid_color[0] = 0.f;
348 exa->solid_color[1] = 1.f;
349 exa->solid_color[2] = 0.f;
350 exa->solid_color[3] = 1.f;
351 xorg_solid(exa, priv, 0, 0, 1024, 768);
352 exa->solid_color[0] = 1.f;
353 exa->solid_color[1] = 0.f;
354 exa->solid_color[2] = 0.f;
355 exa->solid_color[3] = 1.f;
356 xorg_solid(exa, priv, 0, 0, 300, 300);
357 xorg_solid(exa, priv, 300, 300, 350, 350);
358 xorg_solid(exa, priv, 350, 350, 500, 500);
359
360 xorg_solid(exa, priv,
361 priv->tex->width[0] - 10,
362 priv->tex->height[0] - 10,
363 priv->tex->width[0],
364 priv->tex->height[0]);
365
366 exa->solid_color[0] = 0.f;
367 exa->solid_color[1] = 0.f;
368 exa->solid_color[2] = 1.f;
369 exa->solid_color[3] = 1.f;
370
371 exa->has_solid_color = FALSE;
372 ExaPrepareCopy(pPixmap, pPixmap, 0, 0, GXcopy, 0xffffffff);
373 ExaCopy(pPixmap, 0, 0, 50, 50, 500, 500);
374 #else
375 xorg_solid(exa, priv, x0, y0, x1, y1) ;
376 #endif
377 }
378
379 static Bool
380 ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
381 int ydir, int alu, Pixel planeMask)
382 {
383 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
384 modesettingPtr ms = modesettingPTR(pScrn);
385 struct exa_context *exa = ms->exa;
386 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
387 struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
388
389 #if DEBUG_PRINT
390 debug_printf("ExaPrepareCopy\n");
391 #endif
392 if (!exa->pipe)
393 XORG_FALLBACK("copy accle not enabled");
394
395 if (!priv || !src_priv)
396 XORG_FALLBACK("copy !priv || !src_priv");
397
398 if (!priv->tex || !src_priv->tex)
399 XORG_FALLBACK("copy !priv->tex || !src_priv->tex");
400
401 if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
402 XORG_FALLBACK("copy planeMask is not solid");
403
404 if (alu != GXcopy)
405 XORG_FALLBACK("copy alu not GXcopy");
406
407 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
408 priv->tex->target,
409 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
410 XORG_FALLBACK("copy pDst format %s", pf_name(priv->tex->format));
411
412 if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format,
413 src_priv->tex->target,
414 PIPE_TEXTURE_USAGE_SAMPLER, 0))
415 XORG_FALLBACK("copy pSrc format %s", pf_name(src_priv->tex->format));
416
417 exa->copy.src = src_priv;
418 exa->copy.dst = priv;
419
420 #if DISABLE_ACCEL
421 return FALSE;
422 #else
423 return TRUE;
424 #endif
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 xorg_copy_pixmap(exa, 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\n");
460 #endif
461 if (!exa->pipe)
462 XORG_FALLBACK("comp accle not enabled");
463
464 priv = exaGetPixmapDriverPrivate(pDst);
465 if (!priv || !priv->tex)
466 XORG_FALLBACK("comp pDst %s", !priv ? "!priv" : "!priv->tex");
467
468 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
469 priv->tex->target,
470 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
471 XORG_FALLBACK("copy pDst format: %s", pf_name(priv->tex->format));
472
473 if (pSrc) {
474 priv = exaGetPixmapDriverPrivate(pSrc);
475 if (!priv || !priv->tex)
476 XORG_FALLBACK("comp pSrc %s", !priv ? "!priv" : "!priv->tex");
477
478 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
479 priv->tex->target,
480 PIPE_TEXTURE_USAGE_SAMPLER, 0))
481 XORG_FALLBACK("copy pSrc format: %s", pf_name(priv->tex->format));
482 }
483
484 if (pMask) {
485 priv = exaGetPixmapDriverPrivate(pMask);
486 if (!priv || !priv->tex)
487 XORG_FALLBACK("comp pMask %s", !priv ? "!priv" : "!priv->tex");
488
489 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
490 priv->tex->target,
491 PIPE_TEXTURE_USAGE_SAMPLER, 0))
492 XORG_FALLBACK("copy pMask format: %s", pf_name(priv->tex->format));
493 }
494
495 #if DISABLE_ACCEL
496 (void) exa;
497 return FALSE;
498 #else
499 return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
500 pDstPicture,
501 pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
502 pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
503 exaGetPixmapDriverPrivate(pDst));
504 #endif
505 }
506
507 static void
508 ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
509 int dstX, int dstY, int width, int height)
510 {
511 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
512 modesettingPtr ms = modesettingPTR(pScrn);
513 struct exa_context *exa = ms->exa;
514 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
515
516 #if DEBUG_PRINT
517 debug_printf("\tExaComposite\n");
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 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 = exa_gpu_surface(exa, priv);
701 exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf,
702 0, 0, min(width, texture->width[0]),
703 min(height, texture->height[0]));
704 exa->scrn->tex_surface_destroy(dst_surf);
705 exa->scrn->tex_surface_destroy(src_surf);
706 }
707
708 pipe_texture_reference(&priv->tex, texture);
709 /* the texture we create has one reference */
710 pipe_texture_reference(&texture, NULL);
711 }
712
713 return TRUE;
714 }
715
716 struct pipe_texture *
717 xorg_exa_get_texture(PixmapPtr pPixmap)
718 {
719 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
720 struct pipe_texture *tex = NULL;
721 pipe_texture_reference(&tex, priv->tex);
722 return tex;
723 }
724
725 void
726 xorg_exa_close(ScrnInfoPtr pScrn)
727 {
728 modesettingPtr ms = modesettingPTR(pScrn);
729 struct exa_context *exa = ms->exa;
730 struct pipe_constant_buffer *vsbuf = &exa->vs_const_buffer;
731 struct pipe_constant_buffer *fsbuf = &exa->fs_const_buffer;
732
733 if (exa->shaders) {
734 xorg_shaders_destroy(exa->shaders);
735 }
736
737 if (vsbuf && vsbuf->buffer)
738 pipe_buffer_reference(&vsbuf->buffer, NULL);
739
740 if (fsbuf && fsbuf->buffer)
741 pipe_buffer_reference(&fsbuf->buffer, NULL);
742
743 if (exa->cso) {
744 cso_release_all(exa->cso);
745 cso_destroy_context(exa->cso);
746 }
747
748 if (exa->pipe)
749 exa->pipe->destroy(exa->pipe);
750
751 exaDriverFini(pScrn->pScreen);
752 xfree(exa);
753 ms->exa = NULL;
754 }
755
756 void *
757 xorg_exa_init(ScrnInfoPtr pScrn)
758 {
759 modesettingPtr ms = modesettingPTR(pScrn);
760 struct exa_context *exa;
761 ExaDriverPtr pExa;
762
763 exa = xcalloc(1, sizeof(struct exa_context));
764 if (!exa)
765 return NULL;
766
767 pExa = exaDriverAlloc();
768 if (!pExa) {
769 goto out_err;
770 }
771
772 memset(pExa, 0, sizeof(*pExa));
773
774 pExa->exa_major = 2;
775 pExa->exa_minor = 2;
776 pExa->memoryBase = 0;
777 pExa->memorySize = 0;
778 pExa->offScreenBase = 0;
779 pExa->pixmapOffsetAlign = 0;
780 pExa->pixmapPitchAlign = 1;
781 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
782 #ifdef EXA_SUPPORTS_PREPARE_AUX
783 pExa->flags |= EXA_SUPPORTS_PREPARE_AUX;
784 #endif
785 #ifdef EXA_MIXED_PIXMAPS
786 pExa->flags |= EXA_MIXED_PIXMAPS;
787 #endif
788 pExa->maxX = 8191; /* FIXME */
789 pExa->maxY = 8191; /* FIXME */
790
791 pExa->WaitMarker = ExaWaitMarker;
792 pExa->MarkSync = ExaMarkSync;
793 pExa->PrepareSolid = ExaPrepareSolid;
794 pExa->Solid = ExaSolid;
795 pExa->DoneSolid = ExaDone;
796 pExa->PrepareCopy = ExaPrepareCopy;
797 pExa->Copy = ExaCopy;
798 pExa->DoneCopy = ExaDone;
799 pExa->CheckComposite = ExaCheckComposite;
800 pExa->PrepareComposite = ExaPrepareComposite;
801 pExa->Composite = ExaComposite;
802 pExa->DoneComposite = ExaDoneComposite;
803 pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen;
804 pExa->DownloadFromScreen = ExaDownloadFromScreen;
805 pExa->UploadToScreen = ExaUploadToScreen;
806 pExa->PrepareAccess = ExaPrepareAccess;
807 pExa->FinishAccess = ExaFinishAccess;
808 pExa->CreatePixmap = ExaCreatePixmap;
809 pExa->DestroyPixmap = ExaDestroyPixmap;
810 pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
811
812 if (!exaDriverInit(pScrn->pScreen, pExa)) {
813 goto out_err;
814 }
815
816 exa->scrn = ms->screen;
817 exa->pipe = ms->api->create_context(ms->api, exa->scrn);
818 /* Share context with DRI */
819 ms->ctx = exa->pipe;
820
821 exa->cso = cso_create_context(exa->pipe);
822 exa->shaders = xorg_shaders_create(exa);
823
824 xorg_exa_init_state(exa);
825
826 return (void *)exa;
827
828 out_err:
829 xorg_exa_close(pScrn);
830
831 return NULL;
832 }
833
834 struct pipe_surface *
835 exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv)
836 {
837 return exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
838 PIPE_BUFFER_USAGE_GPU_READ |
839 PIPE_BUFFER_USAGE_GPU_WRITE);
840
841 }
842
843 void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
844 struct pipe_fence_handle **fence)
845 {
846 exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
847 }
848
849 void xorg_exa_finish(struct exa_context *exa)
850 {
851 struct pipe_fence_handle *fence = NULL;
852
853 xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
854
855 exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
856 exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
857 }
858