xorg_exa.c revision b97547027e0f049d1ceef7863815d53e471fb18c
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 1
52
53/*
54 * Helper functions
55 */
56
57static void
58exa_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
91static void
92xorg_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
101static void
102xorg_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
114static void
115ExaWaitMarker(ScreenPtr pScreen, int marker)
116{
117}
118
119static int
120ExaMarkSync(ScreenPtr pScreen)
121{
122    return 1;
123}
124
125static Bool
126ExaDownloadFromScreen(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
158static Bool
159ExaUploadToScreen(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
187static Bool
188ExaPrepareAccess(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
223static void
224ExaFinishAccess(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
248static void
249ExaDone(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
267static void
268ExaDoneComposite(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
277static Bool
278ExaPrepareSolid(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
317static void
318ExaSolid(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
369static Bool
370ExaPrepareCopy(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
414static void
415ExaCopy(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
433static Bool
434ExaPrepareComposite(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
442   debug_printf("ExaPrepareComposite\n");
443
444#if DISABLE_ACCEL
445   (void) exa;
446   return FALSE;
447#else
448   return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
449                                    pDstPicture,
450                                    exaGetPixmapDriverPrivate(pSrc),
451                                    exaGetPixmapDriverPrivate(pMask),
452                                    exaGetPixmapDriverPrivate(pDst));
453#endif
454}
455
456static void
457ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
458	     int dstX, int dstY, int width, int height)
459{
460   ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
461   modesettingPtr ms = modesettingPTR(pScrn);
462   struct exa_context *exa = ms->exa;
463   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
464
465   debug_printf("\tExaComposite\n");
466
467   xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
468                  dstX, dstY, width, height);
469}
470
471static Bool
472ExaCheckComposite(int op,
473		  PicturePtr pSrcPicture, PicturePtr pMaskPicture,
474		  PicturePtr pDstPicture)
475{
476   boolean accelerated = xorg_composite_accelerated(op,
477                                                    pSrcPicture,
478                                                    pMaskPicture,
479                                                    pDstPicture);
480   debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
481                op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
482   return accelerated;
483}
484
485static void *
486ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
487{
488    struct exa_pixmap_priv *priv;
489
490    priv = xcalloc(1, sizeof(struct exa_pixmap_priv));
491    if (!priv)
492	return NULL;
493
494    return priv;
495}
496
497static void
498ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
499{
500    struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
501
502    if (!priv)
503	return;
504
505    pipe_texture_reference(&priv->tex, NULL);
506
507    xfree(priv);
508}
509
510static Bool
511ExaPixmapIsOffscreen(PixmapPtr pPixmap)
512{
513    struct exa_pixmap_priv *priv;
514
515    priv = exaGetPixmapDriverPrivate(pPixmap);
516
517    if (!priv)
518	return FALSE;
519
520    if (priv->tex)
521	return TRUE;
522
523    return FALSE;
524}
525
526int
527xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
528{
529    struct exa_pixmap_priv *priv;
530    priv = exaGetPixmapDriverPrivate(pPixmap);
531
532    if (!priv) {
533	FatalError("NO PIXMAP PRIVATE\n");
534	return 0;
535    }
536
537    priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY;
538
539    return 0;
540}
541
542int
543xorg_exa_set_shared_usage(PixmapPtr pPixmap)
544{
545    struct exa_pixmap_priv *priv;
546    priv = exaGetPixmapDriverPrivate(pPixmap);
547
548    if (!priv) {
549	FatalError("NO PIXMAP PRIVATE\n");
550	return 0;
551    }
552
553    priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
554
555    return 0;
556}
557
558unsigned
559xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
560{
561    ScreenPtr pScreen = pPixmap->drawable.pScreen;
562    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
563    modesettingPtr ms = modesettingPTR(pScrn);
564    struct exa_pixmap_priv *priv;
565    unsigned handle;
566    unsigned stride;
567
568    if (!ms->exa) {
569	FatalError("NO MS->EXA\n");
570	return 0;
571    }
572
573    priv = exaGetPixmapDriverPrivate(pPixmap);
574
575    if (!priv) {
576	FatalError("NO PIXMAP PRIVATE\n");
577	return 0;
578    }
579
580    ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle);
581    if (stride_out)
582	*stride_out = stride;
583
584    return handle;
585}
586
587static Bool
588ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
589		      int depth, int bitsPerPixel, int devKind,
590		      pointer pPixData)
591{
592    ScreenPtr pScreen = pPixmap->drawable.pScreen;
593    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
594    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
595    modesettingPtr ms = modesettingPTR(pScrn);
596    struct exa_context *exa = ms->exa;
597
598    if (!priv || pPixData)
599	return FALSE;
600
601    if (depth <= 0)
602	depth = pPixmap->drawable.depth;
603
604    if (bitsPerPixel <= 0)
605	bitsPerPixel = pPixmap->drawable.bitsPerPixel;
606
607    if (width <= 0)
608	width = pPixmap->drawable.width;
609
610    if (height <= 0)
611	height = pPixmap->drawable.height;
612
613    if (width <= 0 || height <= 0 || depth <= 0)
614	return FALSE;
615
616    miModifyPixmapHeader(pPixmap, width, height, depth,
617			     bitsPerPixel, devKind, NULL);
618
619    /* Deal with screen resize */
620    if (!priv->tex ||
621        (priv->tex->width[0] != width ||
622         priv->tex->height[0] != height ||
623         priv->tex_flags != priv->flags)) {
624	struct pipe_texture *texture = NULL;
625
626#ifdef DRM_MODE_FEATURE_DIRTYFB
627	if (priv->flags)
628#endif
629	{
630	    struct pipe_texture template;
631
632	    memset(&template, 0, sizeof(template));
633	    template.target = PIPE_TEXTURE_2D;
634	    exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
635	    pf_get_block(template.format, &template.block);
636	    template.width[0] = width;
637	    template.height[0] = height;
638	    template.depth[0] = 1;
639	    template.last_level = 0;
640	    template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
641	    priv->tex_flags = priv->flags;
642	    texture = exa->scrn->texture_create(exa->scrn, &template);
643
644	    if (priv->tex) {
645		struct pipe_surface *dst_surf;
646                struct pipe_surface *src_surf;
647
648		dst_surf = exa->scrn->get_tex_surface(
649                   exa->scrn, texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
650		src_surf = exa_gpu_surface(exa, priv);
651		exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf,
652                                        0, 0, min(width, texture->width[0]),
653                                        min(height, texture->height[0]));
654		exa->scrn->tex_surface_destroy(dst_surf);
655		exa->scrn->tex_surface_destroy(src_surf);
656	    } else if (pPixmap->devPrivate.ptr) {
657		struct pipe_transfer *transfer;
658
659		if (priv->map_count != 0)
660		     FatalError("doing ExaModifyPixmapHeader on mapped buffer\n");
661
662		transfer =
663		    exa->scrn->get_tex_transfer(exa->scrn, texture, 0, 0, 0,
664						PIPE_TRANSFER_WRITE,
665						0, 0, width, height);
666		util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
667			       &texture->block, transfer->stride, 0, 0,
668			       width, height, pPixmap->devPrivate.ptr,
669			       pPixmap->devKind, 0, 0);
670		exa->scrn->transfer_unmap(exa->scrn, transfer);
671		exa->scrn->tex_transfer_destroy(transfer);
672
673		xfree(pPixmap->devPrivate.ptr);
674		pPixmap->devPrivate.ptr = NULL;
675	    }
676	}
677#ifdef DRM_MODE_FEATURE_DIRTYFB
678	else {
679	    xfree(pPixmap->devPrivate.ptr);
680	    pPixmap->devPrivate.ptr = xalloc(pPixmap->drawable.height *
681					     pPixmap->devKind);
682	}
683#endif
684
685	pipe_texture_reference(&priv->tex, texture);
686	/* the texture we create has one reference */
687	pipe_texture_reference(&texture, NULL);
688    }
689
690    return TRUE;
691}
692
693struct pipe_texture *
694xorg_exa_get_texture(PixmapPtr pPixmap)
695{
696   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
697   struct pipe_texture *tex = NULL;
698   pipe_texture_reference(&tex, priv->tex);
699   return tex;
700}
701
702void
703xorg_exa_close(ScrnInfoPtr pScrn)
704{
705   modesettingPtr ms = modesettingPTR(pScrn);
706   struct exa_context *exa = ms->exa;
707   struct pipe_constant_buffer *vsbuf = &exa->vs_const_buffer;
708   struct pipe_constant_buffer *fsbuf = &exa->fs_const_buffer;
709
710   if (exa->shaders) {
711      xorg_shaders_destroy(exa->shaders);
712   }
713
714   if (vsbuf && vsbuf->buffer)
715      pipe_buffer_reference(&vsbuf->buffer, NULL);
716
717   if (fsbuf && fsbuf->buffer)
718      pipe_buffer_reference(&fsbuf->buffer, NULL);
719
720   if (exa->cso) {
721      cso_release_all(exa->cso);
722      cso_destroy_context(exa->cso);
723   }
724
725   if (exa->pipe)
726      exa->pipe->destroy(exa->pipe);
727
728   exaDriverFini(pScrn->pScreen);
729   xfree(exa);
730   ms->exa = NULL;
731}
732
733void *
734xorg_exa_init(ScrnInfoPtr pScrn)
735{
736   modesettingPtr ms = modesettingPTR(pScrn);
737   struct exa_context *exa;
738   ExaDriverPtr pExa;
739
740   exa = xcalloc(1, sizeof(struct exa_context));
741   if (!exa)
742      return NULL;
743
744   pExa = exaDriverAlloc();
745   if (!pExa) {
746      goto out_err;
747   }
748
749   memset(pExa, 0, sizeof(*pExa));
750
751   pExa->exa_major         = 2;
752   pExa->exa_minor         = 2;
753   pExa->memoryBase        = 0;
754   pExa->memorySize        = 0;
755   pExa->offScreenBase     = 0;
756   pExa->pixmapOffsetAlign = 0;
757   pExa->pixmapPitchAlign  = 1;
758   pExa->flags             = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
759#ifdef EXA_SUPPORTS_PREPARE_AUX
760   pExa->flags            |= EXA_SUPPORTS_PREPARE_AUX;
761#endif
762#ifdef EXA_MIXED_PIXMAPS
763   pExa->flags            |= EXA_MIXED_PIXMAPS;
764#endif
765   pExa->maxX              = 8191; /* FIXME */
766   pExa->maxY              = 8191; /* FIXME */
767
768   pExa->WaitMarker         = ExaWaitMarker;
769   pExa->MarkSync           = ExaMarkSync;
770   pExa->PrepareSolid       = ExaPrepareSolid;
771   pExa->Solid              = ExaSolid;
772   pExa->DoneSolid          = ExaDone;
773   pExa->PrepareCopy        = ExaPrepareCopy;
774   pExa->Copy               = ExaCopy;
775   pExa->DoneCopy           = ExaDone;
776   pExa->CheckComposite     = ExaCheckComposite;
777   pExa->PrepareComposite   = ExaPrepareComposite;
778   pExa->Composite          = ExaComposite;
779   pExa->DoneComposite      = ExaDoneComposite;
780   pExa->PixmapIsOffscreen  = ExaPixmapIsOffscreen;
781   pExa->DownloadFromScreen = ExaDownloadFromScreen;
782   pExa->UploadToScreen     = ExaUploadToScreen;
783   pExa->PrepareAccess      = ExaPrepareAccess;
784   pExa->FinishAccess       = ExaFinishAccess;
785   pExa->CreatePixmap       = ExaCreatePixmap;
786   pExa->DestroyPixmap      = ExaDestroyPixmap;
787   pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
788
789   if (!exaDriverInit(pScrn->pScreen, pExa)) {
790      goto out_err;
791   }
792
793   exa->scrn = ms->screen;
794   exa->pipe = ms->api->create_context(ms->api, exa->scrn);
795   /* Share context with DRI */
796   ms->ctx = exa->pipe;
797
798   exa->cso = cso_create_context(exa->pipe);
799   exa->shaders = xorg_shaders_create(exa);
800
801   xorg_exa_init_state(exa);
802
803   return (void *)exa;
804
805out_err:
806   xorg_exa_close(pScrn);
807
808   return NULL;
809}
810
811struct pipe_surface *
812exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv)
813{
814   return exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
815                                     PIPE_BUFFER_USAGE_GPU_READ |
816                                     PIPE_BUFFER_USAGE_GPU_WRITE);
817
818}
819
820void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
821                    struct pipe_fence_handle **fence)
822{
823   exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
824}
825
826void xorg_exa_finish(struct exa_context *exa)
827{
828   struct pipe_fence_handle *fence = NULL;
829
830   xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
831
832   exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
833   exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
834}
835
836