xorg_exa.c revision 4322346f3fd03788a79d056ca7bce2db25bc9d88
1/*
2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 *
26 * Author: Alan Hourihane <alanh@tungstengraphics.com>
27 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
28 *
29 */
30
31#include "xorg_exa.h"
32#include "xorg_tracker.h"
33#include "xorg_composite.h"
34#include "xorg_exa_tgsi.h"
35
36#include <xorg-server.h>
37#include <xf86.h>
38#include <picturestr.h>
39#include <picture.h>
40
41#include "pipe/p_format.h"
42#include "pipe/p_context.h"
43#include "pipe/p_state.h"
44#include "pipe/p_inlines.h"
45
46#include "util/u_rect.h"
47
48#define DEBUG_PRINT 0
49#define ACCEL_ENABLED TRUE
50
51/*
52 * Helper functions
53 */
54
55static void
56exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
57{
58    switch (depth) {
59    case 32:
60	*format = PIPE_FORMAT_A8R8G8B8_UNORM;
61	assert(*bbp == 32);
62	break;
63    case 24:
64	*format = PIPE_FORMAT_X8R8G8B8_UNORM;
65	assert(*bbp == 32);
66	break;
67    case 16:
68	*format = PIPE_FORMAT_R5G6B5_UNORM;
69	assert(*bbp == 16);
70	break;
71    case 15:
72	*format = PIPE_FORMAT_A1R5G5B5_UNORM;
73	assert(*bbp == 16);
74	break;
75    case 8:
76	*format = PIPE_FORMAT_L8_UNORM;
77	assert(*bbp == 8);
78	break;
79    case 4:
80    case 1:
81	*format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
82	break;
83    default:
84	assert(0);
85	break;
86    }
87}
88
89static void
90xorg_exa_common_done(struct exa_context *exa)
91{
92   exa->copy.src = NULL;
93   exa->copy.dst = NULL;
94   exa->transform.has_src = FALSE;
95   exa->transform.has_mask = FALSE;
96   exa->has_solid_color = FALSE;
97   exa->num_bound_samplers = 0;
98}
99
100/*
101 * Static exported EXA functions
102 */
103
104static void
105ExaWaitMarker(ScreenPtr pScreen, int marker)
106{
107   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
108   modesettingPtr ms = modesettingPTR(pScrn);
109   struct exa_context *exa = ms->exa;
110
111#if 0
112   xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL);
113#else
114   xorg_exa_finish(exa);
115#endif
116}
117
118static int
119ExaMarkSync(ScreenPtr pScreen)
120{
121   return 1;
122}
123
124static Bool
125ExaDownloadFromScreen(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#if DEBUG_PRINT
148    debug_printf("------ ExaDownloadFromScreen(%d, %d, %d, %d, %d)\n",
149                 x, y, w, h, dst_pitch);
150#endif
151
152    util_copy_rect((unsigned char*)dst, &priv->tex->block, dst_pitch, 0, 0,
153		   w, h, exa->scrn->transfer_map(exa->scrn, transfer),
154		   transfer->stride, 0, 0);
155
156    exa->scrn->transfer_unmap(exa->scrn, transfer);
157    exa->scrn->tex_transfer_destroy(transfer);
158
159    return TRUE;
160}
161
162static Bool
163ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src,
164		  int src_pitch)
165{
166    ScreenPtr pScreen = pPix->drawable.pScreen;
167    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
168    modesettingPtr ms = modesettingPTR(pScrn);
169    struct exa_context *exa = ms->exa;
170    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
171    struct pipe_transfer *transfer;
172
173    if (!priv || !priv->tex)
174	return FALSE;
175
176    transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
177					   PIPE_TRANSFER_WRITE, x, y, w, h);
178    if (!transfer)
179	return FALSE;
180
181#if DEBUG_PRINT
182    debug_printf("++++++ ExaUploadToScreen(%d, %d, %d, %d, %d)\n",
183                 x, y, w, h, src_pitch);
184#endif
185
186    util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
187		   &priv->tex->block, transfer->stride, 0, 0, w, h,
188		   (unsigned char*)src, src_pitch, 0, 0);
189
190    exa->scrn->transfer_unmap(exa->scrn, transfer);
191    exa->scrn->tex_transfer_destroy(transfer);
192
193    return TRUE;
194}
195
196static Bool
197ExaPrepareAccess(PixmapPtr pPix, int index)
198{
199    ScreenPtr pScreen = pPix->drawable.pScreen;
200    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
201    modesettingPtr ms = modesettingPTR(pScrn);
202    struct exa_context *exa = ms->exa;
203    struct exa_pixmap_priv *priv;
204
205    priv = exaGetPixmapDriverPrivate(pPix);
206
207    if (!priv)
208	return FALSE;
209
210    if (!priv->tex)
211	return FALSE;
212
213    if (priv->map_count == 0)
214    {
215	if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
216	    PIPE_REFERENCED_FOR_WRITE)
217	    exa->pipe->flush(exa->pipe, 0, NULL);
218
219	priv->map_transfer =
220	    exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
221#ifdef EXA_MIXED_PIXMAPS
222					PIPE_TRANSFER_MAP_DIRECTLY |
223#endif
224					PIPE_TRANSFER_READ_WRITE,
225					0, 0, priv->tex->width[0], priv->tex->height[0]);
226	if (!priv->map_transfer)
227#ifdef EXA_MIXED_PIXMAPS
228	    return FALSE;
229#else
230	    FatalError("failed to create transfer\n");
231#endif
232
233	pPix->devPrivate.ptr =
234	    exa->scrn->transfer_map(exa->scrn, priv->map_transfer);
235	pPix->devKind = priv->map_transfer->stride;
236    }
237
238    priv->map_count++;
239
240    return TRUE;
241}
242
243static void
244ExaFinishAccess(PixmapPtr pPix, int index)
245{
246    ScreenPtr pScreen = pPix->drawable.pScreen;
247    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
248    modesettingPtr ms = modesettingPTR(pScrn);
249    struct exa_context *exa = ms->exa;
250    struct exa_pixmap_priv *priv;
251    priv = exaGetPixmapDriverPrivate(pPix);
252
253    if (!priv)
254	return;
255
256    if (!priv->map_transfer)
257	return;
258
259    if (--priv->map_count == 0) {
260	assert(priv->map_transfer);
261	exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
262	exa->scrn->tex_transfer_destroy(priv->map_transfer);
263	priv->map_transfer = NULL;
264	pPix->devPrivate.ptr = NULL;
265    }
266}
267
268static void
269ExaDone(PixmapPtr pPixmap)
270{
271    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
272    modesettingPtr ms = modesettingPTR(pScrn);
273    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
274    struct exa_context *exa = ms->exa;
275
276    if (!priv)
277	return;
278
279    renderer_draw_flush(exa->renderer);
280
281    xorg_exa_common_done(exa);
282}
283
284static void
285ExaDoneComposite(PixmapPtr pPixmap)
286{
287   ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
288   modesettingPtr ms = modesettingPTR(pScrn);
289   struct exa_context *exa = ms->exa;
290
291   xorg_exa_common_done(exa);
292}
293
294static Bool
295ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
296{
297    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
298    modesettingPtr ms = modesettingPTR(pScrn);
299    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
300    struct exa_context *exa = ms->exa;
301
302#if DEBUG_PRINT
303    debug_printf("ExaPrepareSolid(0x%x)\n", fg);
304#endif
305    if (!exa->pipe)
306	XORG_FALLBACK("accle not enabled");
307
308    if (!priv || !priv->tex)
309	XORG_FALLBACK("%s", !priv ? "!priv" : "!priv->tex");
310
311    if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
312	XORG_FALLBACK("planeMask is not solid");
313
314    if (alu != GXcopy)
315	XORG_FALLBACK("not GXcopy");
316
317    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
318                                        priv->tex->target,
319                                        PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
320	XORG_FALLBACK("format %s", pf_name(priv->tex->format));
321    }
322
323    return ACCEL_ENABLED && xorg_solid_bind_state(exa, priv, fg);
324}
325
326static void
327ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
328{
329    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
330    modesettingPtr ms = modesettingPTR(pScrn);
331    struct exa_context *exa = ms->exa;
332    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
333
334#if DEBUG_PRINT
335    debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
336#endif
337
338    xorg_solid(exa, priv, x0, y0, x1, y1) ;
339}
340
341static Bool
342ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
343	       int ydir, int alu, Pixel planeMask)
344{
345    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
346    modesettingPtr ms = modesettingPTR(pScrn);
347    struct exa_context *exa = ms->exa;
348    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
349    struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
350
351#if DEBUG_PRINT
352    debug_printf("ExaPrepareCopy\n");
353#endif
354    if (!exa->pipe)
355	XORG_FALLBACK("accle not enabled");
356
357    if (!priv || !priv->tex)
358	XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
359
360    if (!src_priv || !src_priv->tex)
361	XORG_FALLBACK("pSrc %s", !src_priv ? "!priv" : "!priv->tex");
362
363    if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
364	XORG_FALLBACK("planeMask is not solid");
365
366    if (alu != GXcopy)
367	XORG_FALLBACK("alu not GXcopy");
368
369    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
370                                        priv->tex->target,
371                                        PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
372	XORG_FALLBACK("pDst format %s", pf_name(priv->tex->format));
373
374    if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format,
375                                        src_priv->tex->target,
376                                        PIPE_TEXTURE_USAGE_SAMPLER, 0))
377	XORG_FALLBACK("pSrc format %s", pf_name(src_priv->tex->format));
378
379    exa->copy.src = src_priv;
380    exa->copy.dst = priv;
381
382    return ACCEL_ENABLED;
383}
384
385static void
386ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
387	int width, int height)
388{
389   ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
390   modesettingPtr ms = modesettingPTR(pScrn);
391   struct exa_context *exa = ms->exa;
392   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
393
394#if DEBUG_PRINT
395   debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
396                srcX, srcY, dstX, dstY, width, height);
397#endif
398
399   debug_assert(priv == exa->copy.dst);
400
401   renderer_copy_pixmap(exa->renderer, exa->copy.dst, dstX, dstY,
402                        exa->copy.src, srcX, srcY,
403                        width, height);
404}
405
406static Bool
407ExaPrepareComposite(int op, PicturePtr pSrcPicture,
408		    PicturePtr pMaskPicture, PicturePtr pDstPicture,
409		    PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
410{
411   ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
412   modesettingPtr ms = modesettingPTR(pScrn);
413   struct exa_context *exa = ms->exa;
414   struct exa_pixmap_priv *priv;
415
416#if DEBUG_PRINT
417   debug_printf("ExaPrepareComposite(%d, src=0x%p, mask=0x%p, dst=0x%p)\n",
418                op, pSrcPicture, pMaskPicture, pDstPicture);
419#endif
420   if (!exa->pipe)
421      XORG_FALLBACK("accle not enabled");
422
423   priv = exaGetPixmapDriverPrivate(pDst);
424   if (!priv || !priv->tex)
425      XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
426
427   if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
428                                       priv->tex->target,
429                                       PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
430      XORG_FALLBACK("pDst format: %s", pf_name(priv->tex->format));
431
432   if (pSrc) {
433      priv = exaGetPixmapDriverPrivate(pSrc);
434      if (!priv || !priv->tex)
435         XORG_FALLBACK("pSrc %s", !priv ? "!priv" : "!priv->tex");
436
437      if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
438                                          priv->tex->target,
439                                          PIPE_TEXTURE_USAGE_SAMPLER, 0))
440         XORG_FALLBACK("pSrc format: %s", pf_name(priv->tex->format));
441   }
442
443   if (pMask) {
444      priv = exaGetPixmapDriverPrivate(pMask);
445      if (!priv || !priv->tex)
446         XORG_FALLBACK("pMask %s", !priv ? "!priv" : "!priv->tex");
447
448      if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
449                                          priv->tex->target,
450                                          PIPE_TEXTURE_USAGE_SAMPLER, 0))
451         XORG_FALLBACK("pMask format: %s", pf_name(priv->tex->format));
452   }
453
454   return ACCEL_ENABLED &&
455          xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
456                                    pDstPicture,
457                                    pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
458                                    pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
459                                    exaGetPixmapDriverPrivate(pDst));
460}
461
462static void
463ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
464	     int dstX, int dstY, int width, int height)
465{
466   ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
467   modesettingPtr ms = modesettingPTR(pScrn);
468   struct exa_context *exa = ms->exa;
469   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
470
471#if DEBUG_PRINT
472   debug_printf("\tExaComposite(src[%d,%d], mask=[%d, %d], dst=[%d, %d], dim=[%d, %d])\n",
473                srcX, srcY, maskX, maskY, dstX, dstY, width, height);
474   debug_printf("\t   Num bound samplers = %d\n",
475                exa->num_bound_samplers);
476#endif
477
478   xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
479                  dstX, dstY, width, height);
480}
481
482static Bool
483ExaCheckComposite(int op,
484		  PicturePtr pSrcPicture, PicturePtr pMaskPicture,
485		  PicturePtr pDstPicture)
486{
487   boolean accelerated = xorg_composite_accelerated(op,
488                                                    pSrcPicture,
489                                                    pMaskPicture,
490                                                    pDstPicture);
491#if DEBUG_PRINT
492   debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
493                op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
494#endif
495   return ACCEL_ENABLED && accelerated;
496}
497
498static void *
499ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
500{
501    struct exa_pixmap_priv *priv;
502
503    priv = xcalloc(1, sizeof(struct exa_pixmap_priv));
504    if (!priv)
505	return NULL;
506
507    return priv;
508}
509
510static void
511ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
512{
513    struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
514
515    if (!priv)
516	return;
517
518    pipe_texture_reference(&priv->tex, NULL);
519
520    xfree(priv);
521}
522
523static Bool
524ExaPixmapIsOffscreen(PixmapPtr pPixmap)
525{
526    struct exa_pixmap_priv *priv;
527
528    priv = exaGetPixmapDriverPrivate(pPixmap);
529
530    if (!priv)
531	return FALSE;
532
533    if (priv->tex)
534	return TRUE;
535
536    return FALSE;
537}
538
539int
540xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
541{
542    struct exa_pixmap_priv *priv;
543    priv = exaGetPixmapDriverPrivate(pPixmap);
544
545    if (!priv) {
546	FatalError("NO PIXMAP PRIVATE\n");
547	return 0;
548    }
549
550    priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY;
551
552    return 0;
553}
554
555int
556xorg_exa_set_shared_usage(PixmapPtr pPixmap)
557{
558    struct exa_pixmap_priv *priv;
559    priv = exaGetPixmapDriverPrivate(pPixmap);
560
561    if (!priv) {
562	FatalError("NO PIXMAP PRIVATE\n");
563	return 0;
564    }
565
566    priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
567
568    return 0;
569}
570
571unsigned
572xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
573{
574    ScreenPtr pScreen = pPixmap->drawable.pScreen;
575    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
576    modesettingPtr ms = modesettingPTR(pScrn);
577    struct exa_pixmap_priv *priv;
578    unsigned handle;
579    unsigned stride;
580
581    if (!ms->exa) {
582	FatalError("NO MS->EXA\n");
583	return 0;
584    }
585
586    priv = exaGetPixmapDriverPrivate(pPixmap);
587
588    if (!priv) {
589	FatalError("NO PIXMAP PRIVATE\n");
590	return 0;
591    }
592
593    ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle);
594    if (stride_out)
595	*stride_out = stride;
596
597    return handle;
598}
599
600static Bool
601ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
602		      int depth, int bitsPerPixel, int devKind,
603		      pointer pPixData)
604{
605    ScreenPtr pScreen = pPixmap->drawable.pScreen;
606    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
607    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
608    modesettingPtr ms = modesettingPTR(pScrn);
609    struct exa_context *exa = ms->exa;
610
611    if (!priv || pPixData)
612	return FALSE;
613
614    if (depth <= 0)
615	depth = pPixmap->drawable.depth;
616
617    if (bitsPerPixel <= 0)
618	bitsPerPixel = pPixmap->drawable.bitsPerPixel;
619
620    if (width <= 0)
621	width = pPixmap->drawable.width;
622
623    if (height <= 0)
624	height = pPixmap->drawable.height;
625
626    if (width <= 0 || height <= 0 || depth <= 0)
627	return FALSE;
628
629    miModifyPixmapHeader(pPixmap, width, height, depth,
630			     bitsPerPixel, devKind, NULL);
631
632    /* Deal with screen resize */
633    if (!priv->tex ||
634        (priv->tex->width[0] != width ||
635         priv->tex->height[0] != height ||
636         priv->tex_flags != priv->flags)) {
637	struct pipe_texture *texture = NULL;
638	struct pipe_texture template;
639
640	memset(&template, 0, sizeof(template));
641	template.target = PIPE_TEXTURE_2D;
642	exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
643	pf_get_block(template.format, &template.block);
644	template.width[0] = width;
645	template.height[0] = height;
646	template.depth[0] = 1;
647	template.last_level = 0;
648	template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
649	priv->tex_flags = priv->flags;
650	texture = exa->scrn->texture_create(exa->scrn, &template);
651
652	if (priv->tex) {
653	    struct pipe_surface *dst_surf;
654	    struct pipe_surface *src_surf;
655
656	    dst_surf = exa->scrn->get_tex_surface(
657		exa->scrn, texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
658	    src_surf = xorg_gpu_surface(exa->pipe->screen, priv);
659        if (exa->pipe->surface_copy) {
660            exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf,
661                        0, 0, min(width, texture->width[0]),
662                        min(height, texture->height[0]));
663        } else {
664            util_surface_copy(exa->pipe, FALSE, dst_surf, 0, 0, src_surf,
665                        0, 0, min(width, texture->width[0]),
666                        min(height, texture->height[0]));
667        }
668	    exa->scrn->tex_surface_destroy(dst_surf);
669	    exa->scrn->tex_surface_destroy(src_surf);
670	}
671
672	pipe_texture_reference(&priv->tex, texture);
673	/* the texture we create has one reference */
674	pipe_texture_reference(&texture, NULL);
675    }
676
677    return TRUE;
678}
679
680struct pipe_texture *
681xorg_exa_get_texture(PixmapPtr pPixmap)
682{
683   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
684   struct pipe_texture *tex = NULL;
685   pipe_texture_reference(&tex, priv->tex);
686   return tex;
687}
688
689Bool
690xorg_exa_set_texture(PixmapPtr pPixmap, struct  pipe_texture *tex)
691{
692    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
693
694    int mask = PIPE_TEXTURE_USAGE_PRIMARY | PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
695
696    if (!priv)
697	return FALSE;
698
699    if (pPixmap->drawable.width != tex->width[0] ||
700	pPixmap->drawable.height != tex->height[0])
701	return FALSE;
702
703    pipe_texture_reference(&priv->tex, tex);
704    priv->tex_flags = tex->tex_usage & mask;
705
706    return TRUE;
707}
708
709struct pipe_texture *
710xorg_exa_create_root_texture(ScrnInfoPtr pScrn,
711			     int width, int height,
712			     int depth, int bitsPerPixel)
713{
714    modesettingPtr ms = modesettingPTR(pScrn);
715    struct exa_context *exa = ms->exa;
716    struct pipe_texture template;
717
718    memset(&template, 0, sizeof(template));
719    template.target = PIPE_TEXTURE_2D;
720    exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
721    pf_get_block(template.format, &template.block);
722    template.width[0] = width;
723    template.height[0] = height;
724    template.depth[0] = 1;
725    template.last_level = 0;
726    template.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
727    template.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
728    template.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
729
730    return exa->scrn->texture_create(exa->scrn, &template);
731}
732
733void
734xorg_exa_close(ScrnInfoPtr pScrn)
735{
736   modesettingPtr ms = modesettingPTR(pScrn);
737   struct exa_context *exa = ms->exa;
738
739   renderer_destroy(exa->renderer);
740
741   if (exa->pipe)
742      exa->pipe->destroy(exa->pipe);
743
744   exaDriverFini(pScrn->pScreen);
745   xfree(exa);
746   ms->exa = NULL;
747}
748
749void *
750xorg_exa_init(ScrnInfoPtr pScrn)
751{
752   modesettingPtr ms = modesettingPTR(pScrn);
753   struct exa_context *exa;
754   ExaDriverPtr pExa;
755
756   exa = xcalloc(1, sizeof(struct exa_context));
757   if (!exa)
758      return NULL;
759
760   pExa = exaDriverAlloc();
761   if (!pExa) {
762      goto out_err;
763   }
764
765   memset(pExa, 0, sizeof(*pExa));
766
767   pExa->exa_major         = 2;
768   pExa->exa_minor         = 2;
769   pExa->memoryBase        = 0;
770   pExa->memorySize        = 0;
771   pExa->offScreenBase     = 0;
772   pExa->pixmapOffsetAlign = 0;
773   pExa->pixmapPitchAlign  = 1;
774   pExa->flags             = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
775#ifdef EXA_SUPPORTS_PREPARE_AUX
776   pExa->flags            |= EXA_SUPPORTS_PREPARE_AUX;
777#endif
778#ifdef EXA_MIXED_PIXMAPS
779   pExa->flags            |= EXA_MIXED_PIXMAPS;
780#endif
781   pExa->maxX              = 8191; /* FIXME */
782   pExa->maxY              = 8191; /* FIXME */
783
784   pExa->WaitMarker         = ExaWaitMarker;
785   pExa->MarkSync           = ExaMarkSync;
786   pExa->PrepareSolid       = ExaPrepareSolid;
787   pExa->Solid              = ExaSolid;
788   pExa->DoneSolid          = ExaDone;
789   pExa->PrepareCopy        = ExaPrepareCopy;
790   pExa->Copy               = ExaCopy;
791   pExa->DoneCopy           = ExaDone;
792   pExa->CheckComposite     = ExaCheckComposite;
793   pExa->PrepareComposite   = ExaPrepareComposite;
794   pExa->Composite          = ExaComposite;
795   pExa->DoneComposite      = ExaDoneComposite;
796   pExa->PixmapIsOffscreen  = ExaPixmapIsOffscreen;
797   pExa->DownloadFromScreen = ExaDownloadFromScreen;
798   pExa->UploadToScreen     = ExaUploadToScreen;
799   pExa->PrepareAccess      = ExaPrepareAccess;
800   pExa->FinishAccess       = ExaFinishAccess;
801   pExa->CreatePixmap       = ExaCreatePixmap;
802   pExa->DestroyPixmap      = ExaDestroyPixmap;
803   pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
804
805   if (!exaDriverInit(pScrn->pScreen, pExa)) {
806      goto out_err;
807   }
808
809   exa->scrn = ms->screen;
810   exa->pipe = ms->api->create_context(ms->api, exa->scrn);
811   /* Share context with DRI */
812   ms->ctx = exa->pipe;
813
814   exa->renderer = renderer_create(exa->pipe);
815
816   return (void *)exa;
817
818out_err:
819   xorg_exa_close(pScrn);
820
821   return NULL;
822}
823
824struct pipe_surface *
825xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv)
826{
827   return scrn->get_tex_surface(scrn, priv->tex, 0, 0, 0,
828                                PIPE_BUFFER_USAGE_GPU_READ |
829                                PIPE_BUFFER_USAGE_GPU_WRITE);
830
831}
832
833void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
834                    struct pipe_fence_handle **fence)
835{
836   exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
837}
838
839void xorg_exa_finish(struct exa_context *exa)
840{
841   struct pipe_fence_handle *fence = NULL;
842
843   xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
844
845   exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
846   exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
847}
848
849