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