g3dvl: Move XvMC under the Xorg state tracker.
[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_SOLID 0
51 #define DISABLE_ACCEL 0
52
53 /*
54 * Helper functions
55 */
56
57 static void
58 exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
59 {
60 switch (depth) {
61 case 32:
62 *format = PIPE_FORMAT_A8R8G8B8_UNORM;
63 assert(*bbp == 32);
64 break;
65 case 24:
66 *format = PIPE_FORMAT_X8R8G8B8_UNORM;
67 assert(*bbp == 32);
68 break;
69 case 16:
70 *format = PIPE_FORMAT_R5G6B5_UNORM;
71 assert(*bbp == 16);
72 break;
73 case 15:
74 *format = PIPE_FORMAT_A1R5G5B5_UNORM;
75 assert(*bbp == 16);
76 break;
77 case 8:
78 *format = PIPE_FORMAT_I8_UNORM;
79 assert(*bbp == 8);
80 break;
81 case 4:
82 case 1:
83 *format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
84 break;
85 default:
86 assert(0);
87 break;
88 }
89 }
90
91 static void
92 xorg_exa_init_state(struct exa_context *exa)
93 {
94 struct pipe_depth_stencil_alpha_state dsa;
95
96 /* set common initial clip state */
97 memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
98 cso_set_depth_stencil_alpha(exa->cso, &dsa);
99 }
100
101 static void
102 xorg_exa_common_done(struct exa_context *exa)
103 {
104 exa->copy.src = NULL;
105 exa->copy.dst = NULL;
106 exa->has_solid_color = FALSE;
107 exa->num_bound_samplers = 0;
108 }
109
110 /*
111 * Static exported EXA functions
112 */
113
114 static void
115 ExaWaitMarker(ScreenPtr pScreen, int marker)
116 {
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 PIPE_TRANSFER_READ_WRITE,
213 0, 0, priv->tex->width[0], priv->tex->height[0]);
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 return TRUE;
221 }
222
223 static void
224 ExaFinishAccess(PixmapPtr pPix, int index)
225 {
226 ScreenPtr pScreen = pPix->drawable.pScreen;
227 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
228 modesettingPtr ms = modesettingPTR(pScrn);
229 struct exa_context *exa = ms->exa;
230 struct exa_pixmap_priv *priv;
231 priv = exaGetPixmapDriverPrivate(pPix);
232
233 if (!priv)
234 return;
235
236 if (!priv->map_transfer)
237 return;
238
239 if (--priv->map_count == 0) {
240 assert(priv->map_transfer);
241 exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
242 exa->scrn->tex_transfer_destroy(priv->map_transfer);
243 priv->map_transfer = NULL;
244 pPix->devPrivate.ptr = NULL;
245 }
246 }
247
248 static void
249 ExaDone(PixmapPtr pPixmap)
250 {
251 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
252 modesettingPtr ms = modesettingPTR(pScrn);
253 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
254 struct exa_context *exa = ms->exa;
255
256 if (!priv)
257 return;
258
259 #if 1
260 xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL);
261 #else
262 xorg_exa_finish(exa);
263 #endif
264 xorg_exa_common_done(exa);
265 }
266
267 static void
268 ExaDoneComposite(PixmapPtr pPixmap)
269 {
270 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
271 modesettingPtr ms = modesettingPTR(pScrn);
272 struct exa_context *exa = ms->exa;
273
274 xorg_exa_common_done(exa);
275 }
276
277 static Bool
278 ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
279 {
280 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
281 modesettingPtr ms = modesettingPTR(pScrn);
282 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
283 struct exa_context *exa = ms->exa;
284
285 #if 1
286 debug_printf("ExaPrepareSolid(0x%x)\n", fg);
287 #endif
288 if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
289 return FALSE;
290
291 if (!priv || !priv->tex)
292 return FALSE;
293
294 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
295 priv->tex->target,
296 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
297 return FALSE;
298
299 if (alu != GXcopy)
300 return FALSE;
301
302 if (!exa->pipe)
303 return FALSE;
304
305
306 #if DEBUG_SOLID
307 fg = 0xffff0000;
308 #endif
309
310 #if DISABLE_ACCEL
311 return FALSE;
312 #else
313 return xorg_solid_bind_state(exa, priv, fg);
314 #endif
315 }
316
317 static void
318 ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
319 {
320 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
321 modesettingPtr ms = modesettingPTR(pScrn);
322 struct exa_context *exa = ms->exa;
323 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
324
325 debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
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 debug_printf("ExaPrepareCopy\n");
380
381 if (alu != GXcopy)
382 return FALSE;
383
384 if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
385 return FALSE;
386
387 if (!priv || !src_priv)
388 return FALSE;
389
390 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
391 priv->tex->target,
392 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0) ||
393 !exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format,
394 src_priv->tex->target,
395 PIPE_TEXTURE_USAGE_SAMPLER, 0))
396 return FALSE;
397
398 if (!priv->tex || !src_priv->tex)
399 return FALSE;
400
401 if (!exa->pipe)
402 return FALSE;
403
404 exa->copy.src = src_priv;
405 exa->copy.dst = priv;
406
407 #if DISABLE_ACCEL
408 return FALSE;
409 #else
410 return TRUE;
411 #endif
412 }
413
414 static void
415 ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
416 int width, int height)
417 {
418 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
419 modesettingPtr ms = modesettingPTR(pScrn);
420 struct exa_context *exa = ms->exa;
421 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
422
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
426 debug_assert(priv == exa->copy.dst);
427
428 xorg_copy_pixmap(exa, exa->copy.dst, dstX, dstY,
429 exa->copy.src, srcX, srcY,
430 width, height);
431 }
432
433 static Bool
434 ExaPrepareComposite(int op, PicturePtr pSrcPicture,
435 PicturePtr pMaskPicture, PicturePtr pDstPicture,
436 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
437 {
438 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
439 modesettingPtr ms = modesettingPTR(pScrn);
440 struct exa_context *exa = ms->exa;
441 struct exa_pixmap_priv *priv;
442
443 debug_printf("ExaPrepareComposite\n");
444
445 priv = exaGetPixmapDriverPrivate(pDst);
446 if (!priv || !priv->tex ||
447 !exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
448 priv->tex->target,
449 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
450 return FALSE;
451
452 if (pSrc) {
453 priv = exaGetPixmapDriverPrivate(pSrc);
454 if (!priv || !priv->tex ||
455 !exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
456 priv->tex->target,
457 PIPE_TEXTURE_USAGE_SAMPLER, 0))
458 return FALSE;
459 }
460
461 if (pMask) {
462 priv = exaGetPixmapDriverPrivate(pMask);
463 if (!priv || !priv->tex ||
464 !exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
465 priv->tex->target,
466 PIPE_TEXTURE_USAGE_SAMPLER, 0))
467 return FALSE;
468 }
469
470 #if DISABLE_ACCEL
471 (void) exa;
472 return FALSE;
473 #else
474 return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
475 pDstPicture,
476 pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
477 pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
478 exaGetPixmapDriverPrivate(pDst));
479 #endif
480 }
481
482 static void
483 ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
484 int dstX, int dstY, int width, int height)
485 {
486 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
487 modesettingPtr ms = modesettingPTR(pScrn);
488 struct exa_context *exa = ms->exa;
489 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
490
491 debug_printf("\tExaComposite\n");
492
493 xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
494 dstX, dstY, width, height);
495 }
496
497 static Bool
498 ExaCheckComposite(int op,
499 PicturePtr pSrcPicture, PicturePtr pMaskPicture,
500 PicturePtr pDstPicture)
501 {
502 boolean accelerated = xorg_composite_accelerated(op,
503 pSrcPicture,
504 pMaskPicture,
505 pDstPicture);
506 debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
507 op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
508 return accelerated;
509 }
510
511 static void *
512 ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
513 {
514 struct exa_pixmap_priv *priv;
515
516 priv = xcalloc(1, sizeof(struct exa_pixmap_priv));
517 if (!priv)
518 return NULL;
519
520 return priv;
521 }
522
523 static void
524 ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
525 {
526 struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
527
528 if (!priv)
529 return;
530
531 pipe_texture_reference(&priv->tex, NULL);
532
533 xfree(priv);
534 }
535
536 static Bool
537 ExaPixmapIsOffscreen(PixmapPtr pPixmap)
538 {
539 struct exa_pixmap_priv *priv;
540
541 priv = exaGetPixmapDriverPrivate(pPixmap);
542
543 if (!priv)
544 return FALSE;
545
546 if (priv->tex)
547 return TRUE;
548
549 return FALSE;
550 }
551
552 int
553 xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
554 {
555 struct exa_pixmap_priv *priv;
556 priv = exaGetPixmapDriverPrivate(pPixmap);
557
558 if (!priv) {
559 FatalError("NO PIXMAP PRIVATE\n");
560 return 0;
561 }
562
563 priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY;
564
565 return 0;
566 }
567
568 int
569 xorg_exa_set_shared_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_DISPLAY_TARGET;
580
581 return 0;
582 }
583
584 unsigned
585 xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
586 {
587 ScreenPtr pScreen = pPixmap->drawable.pScreen;
588 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
589 modesettingPtr ms = modesettingPTR(pScrn);
590 struct exa_pixmap_priv *priv;
591 unsigned handle;
592 unsigned stride;
593
594 if (!ms->exa) {
595 FatalError("NO MS->EXA\n");
596 return 0;
597 }
598
599 priv = exaGetPixmapDriverPrivate(pPixmap);
600
601 if (!priv) {
602 FatalError("NO PIXMAP PRIVATE\n");
603 return 0;
604 }
605
606 ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle);
607 if (stride_out)
608 *stride_out = stride;
609
610 return handle;
611 }
612
613 static Bool
614 ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
615 int depth, int bitsPerPixel, int devKind,
616 pointer pPixData)
617 {
618 ScreenPtr pScreen = pPixmap->drawable.pScreen;
619 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
620 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
621 modesettingPtr ms = modesettingPTR(pScrn);
622 struct exa_context *exa = ms->exa;
623
624 if (!priv || pPixData)
625 return FALSE;
626
627 if (depth <= 0)
628 depth = pPixmap->drawable.depth;
629
630 if (bitsPerPixel <= 0)
631 bitsPerPixel = pPixmap->drawable.bitsPerPixel;
632
633 if (width <= 0)
634 width = pPixmap->drawable.width;
635
636 if (height <= 0)
637 height = pPixmap->drawable.height;
638
639 if (width <= 0 || height <= 0 || depth <= 0)
640 return FALSE;
641
642 miModifyPixmapHeader(pPixmap, width, height, depth,
643 bitsPerPixel, devKind, NULL);
644
645 /* Deal with screen resize */
646 if (!priv->tex ||
647 (priv->tex->width[0] != width ||
648 priv->tex->height[0] != height ||
649 priv->tex_flags != priv->flags)) {
650 struct pipe_texture *texture = NULL;
651
652 #ifdef DRM_MODE_FEATURE_DIRTYFB
653 if (priv->flags)
654 #endif
655 {
656 struct pipe_texture template;
657
658 memset(&template, 0, sizeof(template));
659 template.target = PIPE_TEXTURE_2D;
660 exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
661 pf_get_block(template.format, &template.block);
662 template.width[0] = width;
663 template.height[0] = height;
664 template.depth[0] = 1;
665 template.last_level = 0;
666 template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
667 priv->tex_flags = priv->flags;
668 texture = exa->scrn->texture_create(exa->scrn, &template);
669
670 if (priv->tex) {
671 struct pipe_surface *dst_surf;
672 struct pipe_surface *src_surf;
673
674 dst_surf = exa->scrn->get_tex_surface(
675 exa->scrn, texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
676 src_surf = exa_gpu_surface(exa, priv);
677 exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf,
678 0, 0, min(width, texture->width[0]),
679 min(height, texture->height[0]));
680 exa->scrn->tex_surface_destroy(dst_surf);
681 exa->scrn->tex_surface_destroy(src_surf);
682 } else if (pPixmap->devPrivate.ptr) {
683 struct pipe_transfer *transfer;
684
685 if (priv->map_count != 0)
686 FatalError("doing ExaModifyPixmapHeader on mapped buffer\n");
687
688 transfer =
689 exa->scrn->get_tex_transfer(exa->scrn, texture, 0, 0, 0,
690 PIPE_TRANSFER_WRITE,
691 0, 0, width, height);
692 util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
693 &texture->block, transfer->stride, 0, 0,
694 width, height, pPixmap->devPrivate.ptr,
695 pPixmap->devKind, 0, 0);
696 exa->scrn->transfer_unmap(exa->scrn, transfer);
697 exa->scrn->tex_transfer_destroy(transfer);
698
699 xfree(pPixmap->devPrivate.ptr);
700 pPixmap->devPrivate.ptr = NULL;
701 }
702 }
703 #ifdef DRM_MODE_FEATURE_DIRTYFB
704 else {
705 xfree(pPixmap->devPrivate.ptr);
706 pPixmap->devPrivate.ptr = xalloc(pPixmap->drawable.height *
707 pPixmap->devKind);
708 }
709 #endif
710
711 pipe_texture_reference(&priv->tex, texture);
712 /* the texture we create has one reference */
713 pipe_texture_reference(&texture, NULL);
714 }
715
716 return TRUE;
717 }
718
719 struct pipe_texture *
720 xorg_exa_get_texture(PixmapPtr pPixmap)
721 {
722 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
723 struct pipe_texture *tex = NULL;
724 pipe_texture_reference(&tex, priv->tex);
725 return tex;
726 }
727
728 void
729 xorg_exa_close(ScrnInfoPtr pScrn)
730 {
731 modesettingPtr ms = modesettingPTR(pScrn);
732 struct exa_context *exa = ms->exa;
733 struct pipe_constant_buffer *vsbuf = &exa->vs_const_buffer;
734 struct pipe_constant_buffer *fsbuf = &exa->fs_const_buffer;
735
736 if (exa->shaders) {
737 xorg_shaders_destroy(exa->shaders);
738 }
739
740 if (vsbuf && vsbuf->buffer)
741 pipe_buffer_reference(&vsbuf->buffer, NULL);
742
743 if (fsbuf && fsbuf->buffer)
744 pipe_buffer_reference(&fsbuf->buffer, NULL);
745
746 if (exa->cso) {
747 cso_release_all(exa->cso);
748 cso_destroy_context(exa->cso);
749 }
750
751 if (exa->pipe)
752 exa->pipe->destroy(exa->pipe);
753
754 exaDriverFini(pScrn->pScreen);
755 xfree(exa);
756 ms->exa = NULL;
757 }
758
759 void *
760 xorg_exa_init(ScrnInfoPtr pScrn)
761 {
762 modesettingPtr ms = modesettingPTR(pScrn);
763 struct exa_context *exa;
764 ExaDriverPtr pExa;
765
766 exa = xcalloc(1, sizeof(struct exa_context));
767 if (!exa)
768 return NULL;
769
770 pExa = exaDriverAlloc();
771 if (!pExa) {
772 goto out_err;
773 }
774
775 memset(pExa, 0, sizeof(*pExa));
776
777 pExa->exa_major = 2;
778 pExa->exa_minor = 2;
779 pExa->memoryBase = 0;
780 pExa->memorySize = 0;
781 pExa->offScreenBase = 0;
782 pExa->pixmapOffsetAlign = 0;
783 pExa->pixmapPitchAlign = 1;
784 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
785 #ifdef EXA_SUPPORTS_PREPARE_AUX
786 pExa->flags |= EXA_SUPPORTS_PREPARE_AUX;
787 #endif
788 #ifdef EXA_MIXED_PIXMAPS
789 pExa->flags |= EXA_MIXED_PIXMAPS;
790 #endif
791 pExa->maxX = 8191; /* FIXME */
792 pExa->maxY = 8191; /* FIXME */
793
794 pExa->WaitMarker = ExaWaitMarker;
795 pExa->MarkSync = ExaMarkSync;
796 pExa->PrepareSolid = ExaPrepareSolid;
797 pExa->Solid = ExaSolid;
798 pExa->DoneSolid = ExaDone;
799 pExa->PrepareCopy = ExaPrepareCopy;
800 pExa->Copy = ExaCopy;
801 pExa->DoneCopy = ExaDone;
802 pExa->CheckComposite = ExaCheckComposite;
803 pExa->PrepareComposite = ExaPrepareComposite;
804 pExa->Composite = ExaComposite;
805 pExa->DoneComposite = ExaDoneComposite;
806 pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen;
807 pExa->DownloadFromScreen = ExaDownloadFromScreen;
808 pExa->UploadToScreen = ExaUploadToScreen;
809 pExa->PrepareAccess = ExaPrepareAccess;
810 pExa->FinishAccess = ExaFinishAccess;
811 pExa->CreatePixmap = ExaCreatePixmap;
812 pExa->DestroyPixmap = ExaDestroyPixmap;
813 pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
814
815 if (!exaDriverInit(pScrn->pScreen, pExa)) {
816 goto out_err;
817 }
818
819 exa->scrn = ms->screen;
820 exa->pipe = ms->api->create_context(ms->api, exa->scrn);
821 /* Share context with DRI */
822 ms->ctx = exa->pipe;
823
824 exa->cso = cso_create_context(exa->pipe);
825 exa->shaders = xorg_shaders_create(exa);
826
827 xorg_exa_init_state(exa);
828
829 return (void *)exa;
830
831 out_err:
832 xorg_exa_close(pScrn);
833
834 return NULL;
835 }
836
837 struct pipe_surface *
838 exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv)
839 {
840 return exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
841 PIPE_BUFFER_USAGE_GPU_READ |
842 PIPE_BUFFER_USAGE_GPU_WRITE);
843
844 }
845
846 void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
847 struct pipe_fence_handle **fence)
848 {
849 exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
850 }
851
852 void xorg_exa_finish(struct exa_context *exa)
853 {
854 struct pipe_fence_handle *fence = NULL;
855
856 xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
857
858 exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
859 exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
860 }
861