xorg_exa.c revision decf6ed810eae473d043a4a399a5a84f1378a725
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
50/*
51 * Helper functions
52 */
53struct render_format_str {
54   int format;
55   const char *name;
56};
57static const struct render_format_str formats_info[] =
58{
59   {PICT_a8r8g8b8, "PICT_a8r8g8b8"},
60   {PICT_x8r8g8b8, "PICT_x8r8g8b8"},
61   {PICT_a8b8g8r8, "PICT_a8b8g8r8"},
62   {PICT_x8b8g8r8, "PICT_x8b8g8r8"},
63#ifdef PICT_TYPE_BGRA
64   {PICT_b8g8r8a8, "PICT_b8g8r8a8"},
65   {PICT_b8g8r8x8, "PICT_b8g8r8x8"},
66   {PICT_a2r10g10b10, "PICT_a2r10g10b10"},
67   {PICT_x2r10g10b10, "PICT_x2r10g10b10"},
68   {PICT_a2b10g10r10, "PICT_a2b10g10r10"},
69   {PICT_x2b10g10r10, "PICT_x2b10g10r10"},
70#endif
71   {PICT_r8g8b8, "PICT_r8g8b8"},
72   {PICT_b8g8r8, "PICT_b8g8r8"},
73   {PICT_r5g6b5, "PICT_r5g6b5"},
74   {PICT_b5g6r5, "PICT_b5g6r5"},
75   {PICT_a1r5g5b5, "PICT_a1r5g5b5"},
76   {PICT_x1r5g5b5, "PICT_x1r5g5b5"},
77   {PICT_a1b5g5r5, "PICT_a1b5g5r5"},
78   {PICT_x1b5g5r5, "PICT_x1b5g5r5"},
79   {PICT_a4r4g4b4, "PICT_a4r4g4b4"},
80   {PICT_x4r4g4b4, "PICT_x4r4g4b4"},
81   {PICT_a4b4g4r4, "PICT_a4b4g4r4"},
82   {PICT_x4b4g4r4, "PICT_x4b4g4r4"},
83   {PICT_a8, "PICT_a8"},
84   {PICT_r3g3b2, "PICT_r3g3b2"},
85   {PICT_b2g3r3, "PICT_b2g3r3"},
86   {PICT_a2r2g2b2, "PICT_a2r2g2b2"},
87   {PICT_a2b2g2r2, "PICT_a2b2g2r2"},
88   {PICT_c8, "PICT_c8"},
89   {PICT_g8, "PICT_g8"},
90   {PICT_x4a4, "PICT_x4a4"},
91   {PICT_x4c4, "PICT_x4c4"},
92   {PICT_x4g4, "PICT_x4g4"},
93   {PICT_a4, "PICT_a4"},
94   {PICT_r1g2b1, "PICT_r1g2b1"},
95   {PICT_b1g2r1, "PICT_b1g2r1"},
96   {PICT_a1r1g1b1, "PICT_a1r1g1b1"},
97   {PICT_a1b1g1r1, "PICT_a1b1g1r1"},
98   {PICT_c4, "PICT_c4"},
99   {PICT_g4, "PICT_g4"},
100   {PICT_a1, "PICT_a1"},
101   {PICT_g1, "PICT_g1"}
102};
103static const char *render_format_name(int format)
104{
105   int i = 0;
106   for (i = 0; i < sizeof(formats_info)/sizeof(formats_info[0]); ++i) {
107      if (formats_info[i].format == format)
108         return formats_info[i].name;
109   }
110   return NULL;
111}
112
113static void
114exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp, int *picture_format)
115{
116    switch (depth) {
117    case 32:
118	*format = PIPE_FORMAT_A8R8G8B8_UNORM;
119	*picture_format = PICT_a8r8g8b8;
120	assert(*bbp == 32);
121	break;
122    case 24:
123	*format = PIPE_FORMAT_X8R8G8B8_UNORM;
124	*picture_format = PICT_x8r8g8b8;
125	assert(*bbp == 32);
126	break;
127    case 16:
128	*format = PIPE_FORMAT_R5G6B5_UNORM;
129	*picture_format = PICT_r5g6b5;
130	assert(*bbp == 16);
131	break;
132    case 15:
133	*format = PIPE_FORMAT_A1R5G5B5_UNORM;
134	*picture_format = PICT_x1r5g5b5;
135	assert(*bbp == 16);
136	break;
137    case 8:
138	*format = PIPE_FORMAT_L8_UNORM;
139	*picture_format = PICT_a8;
140	assert(*bbp == 8);
141	break;
142    case 4:
143    case 1:
144	*format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
145	break;
146    default:
147	assert(0);
148	break;
149    }
150}
151
152static void
153xorg_exa_common_done(struct exa_context *exa)
154{
155   renderer_draw_flush(exa->renderer);
156
157   exa->copy.src = NULL;
158   exa->copy.dst = NULL;
159   exa->transform.has_src = FALSE;
160   exa->transform.has_mask = FALSE;
161   exa->has_solid_color = FALSE;
162   exa->num_bound_samplers = 0;
163}
164
165/*
166 * Static exported EXA functions
167 */
168
169static void
170ExaWaitMarker(ScreenPtr pScreen, int marker)
171{
172   /* Nothing to do, handled in the PrepareAccess hook */
173}
174
175static int
176ExaMarkSync(ScreenPtr pScreen)
177{
178   return 1;
179}
180
181static Bool
182ExaDownloadFromScreen(PixmapPtr pPix, int x,  int y, int w,  int h, char *dst,
183		      int dst_pitch)
184{
185    ScreenPtr pScreen = pPix->drawable.pScreen;
186    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
187    modesettingPtr ms = modesettingPTR(pScrn);
188    struct exa_context *exa = ms->exa;
189    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
190    struct pipe_transfer *transfer;
191
192    if (!priv || !priv->tex)
193	return FALSE;
194
195    if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
196	PIPE_REFERENCED_FOR_WRITE)
197	exa->pipe->flush(exa->pipe, 0, NULL);
198
199    transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
200					   PIPE_TRANSFER_READ, x, y, w, h);
201    if (!transfer)
202	return FALSE;
203
204#if DEBUG_PRINT
205    debug_printf("------ ExaDownloadFromScreen(%d, %d, %d, %d, %d)\n",
206                 x, y, w, h, dst_pitch);
207#endif
208
209    util_copy_rect((unsigned char*)dst, priv->tex->format, dst_pitch, 0, 0,
210		   w, h, exa->scrn->transfer_map(exa->scrn, transfer),
211		   transfer->stride, 0, 0);
212
213    exa->scrn->transfer_unmap(exa->scrn, transfer);
214    exa->scrn->tex_transfer_destroy(transfer);
215
216    return TRUE;
217}
218
219static Bool
220ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src,
221		  int src_pitch)
222{
223    ScreenPtr pScreen = pPix->drawable.pScreen;
224    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
225    modesettingPtr ms = modesettingPTR(pScrn);
226    struct exa_context *exa = ms->exa;
227    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
228    struct pipe_transfer *transfer;
229
230    if (!priv || !priv->tex)
231	return FALSE;
232
233    /* make sure that any pending operations are flushed to hardware */
234    if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
235	(PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE))
236	xorg_exa_flush(exa, 0, NULL);
237
238    transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
239					   PIPE_TRANSFER_WRITE, x, y, w, h);
240    if (!transfer)
241	return FALSE;
242
243#if DEBUG_PRINT
244    debug_printf("++++++ ExaUploadToScreen(%d, %d, %d, %d, %d)\n",
245                 x, y, w, h, src_pitch);
246#endif
247
248    util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
249		   priv->tex->format, transfer->stride, 0, 0, w, h,
250		   (unsigned char*)src, src_pitch, 0, 0);
251
252    exa->scrn->transfer_unmap(exa->scrn, transfer);
253    exa->scrn->tex_transfer_destroy(transfer);
254
255    return TRUE;
256}
257
258static Bool
259ExaPrepareAccess(PixmapPtr pPix, int index)
260{
261    ScreenPtr pScreen = pPix->drawable.pScreen;
262    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
263    modesettingPtr ms = modesettingPTR(pScrn);
264    struct exa_context *exa = ms->exa;
265    struct exa_pixmap_priv *priv;
266
267    priv = exaGetPixmapDriverPrivate(pPix);
268
269    if (!priv)
270	return FALSE;
271
272    if (!priv->tex)
273	return FALSE;
274
275    if (priv->map_count == 0)
276    {
277	if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
278	    PIPE_REFERENCED_FOR_WRITE)
279	    exa->pipe->flush(exa->pipe, 0, NULL);
280
281	priv->map_transfer =
282	    exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
283#ifdef EXA_MIXED_PIXMAPS
284					PIPE_TRANSFER_MAP_DIRECTLY |
285#endif
286					PIPE_TRANSFER_READ_WRITE,
287					0, 0, priv->tex->width0, priv->tex->height0);
288	if (!priv->map_transfer)
289#ifdef EXA_MIXED_PIXMAPS
290	    return FALSE;
291#else
292	    FatalError("failed to create transfer\n");
293#endif
294
295	pPix->devPrivate.ptr =
296	    exa->scrn->transfer_map(exa->scrn, priv->map_transfer);
297	pPix->devKind = priv->map_transfer->stride;
298    }
299
300    priv->map_count++;
301
302    return TRUE;
303}
304
305static void
306ExaFinishAccess(PixmapPtr pPix, int index)
307{
308    ScreenPtr pScreen = pPix->drawable.pScreen;
309    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
310    modesettingPtr ms = modesettingPTR(pScrn);
311    struct exa_context *exa = ms->exa;
312    struct exa_pixmap_priv *priv;
313    priv = exaGetPixmapDriverPrivate(pPix);
314
315    if (!priv)
316	return;
317
318    if (!priv->map_transfer)
319	return;
320
321    if (--priv->map_count == 0) {
322	assert(priv->map_transfer);
323	exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
324	exa->scrn->tex_transfer_destroy(priv->map_transfer);
325	priv->map_transfer = NULL;
326	pPix->devPrivate.ptr = NULL;
327    }
328}
329
330static void
331ExaDone(PixmapPtr pPixmap)
332{
333    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
334    modesettingPtr ms = modesettingPTR(pScrn);
335    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
336    struct exa_context *exa = ms->exa;
337
338    if (!priv)
339	return;
340
341    xorg_exa_common_done(exa);
342}
343
344static void
345ExaDoneComposite(PixmapPtr pPixmap)
346{
347   ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
348   modesettingPtr ms = modesettingPTR(pScrn);
349   struct exa_context *exa = ms->exa;
350
351   xorg_exa_common_done(exa);
352}
353
354static Bool
355ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
356{
357    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
358    modesettingPtr ms = modesettingPTR(pScrn);
359    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
360    struct exa_context *exa = ms->exa;
361
362#if DEBUG_PRINT
363    debug_printf("ExaPrepareSolid(0x%x)\n", fg);
364#endif
365    if (!exa->pipe)
366	XORG_FALLBACK("accle not enabled");
367
368    if (!priv || !priv->tex)
369	XORG_FALLBACK("%s", !priv ? "!priv" : "!priv->tex");
370
371    if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
372	XORG_FALLBACK("planeMask is not solid");
373
374    if (alu != GXcopy)
375	XORG_FALLBACK("not GXcopy");
376
377    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
378                                        priv->tex->target,
379                                        PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
380	XORG_FALLBACK("format %s", pf_name(priv->tex->format));
381    }
382
383    return exa->accel && xorg_solid_bind_state(exa, priv, fg);
384}
385
386static void
387ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
388{
389    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
390    modesettingPtr ms = modesettingPTR(pScrn);
391    struct exa_context *exa = ms->exa;
392    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
393
394#if DEBUG_PRINT
395    debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
396#endif
397
398    xorg_solid(exa, priv, x0, y0, x1, y1) ;
399}
400
401static Bool
402ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
403	       int ydir, int alu, Pixel planeMask)
404{
405    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
406    modesettingPtr ms = modesettingPTR(pScrn);
407    struct exa_context *exa = ms->exa;
408    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
409    struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
410
411#if DEBUG_PRINT
412    debug_printf("ExaPrepareCopy\n");
413#endif
414    if (!exa->pipe)
415	XORG_FALLBACK("accle not enabled");
416
417    if (!priv || !priv->tex)
418	XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
419
420    if (!src_priv || !src_priv->tex)
421	XORG_FALLBACK("pSrc %s", !src_priv ? "!priv" : "!priv->tex");
422
423    if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
424	XORG_FALLBACK("planeMask is not solid");
425
426    if (alu != GXcopy)
427	XORG_FALLBACK("alu not GXcopy");
428
429    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
430                                        priv->tex->target,
431                                        PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
432	XORG_FALLBACK("pDst format %s", pf_name(priv->tex->format));
433
434    if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format,
435                                        src_priv->tex->target,
436                                        PIPE_TEXTURE_USAGE_SAMPLER, 0))
437	XORG_FALLBACK("pSrc format %s", pf_name(src_priv->tex->format));
438
439    exa->copy.src = src_priv;
440    exa->copy.dst = priv;
441
442    return exa->accel;
443}
444
445static void
446ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
447	int width, int height)
448{
449   ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
450   modesettingPtr ms = modesettingPTR(pScrn);
451   struct exa_context *exa = ms->exa;
452   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
453
454#if DEBUG_PRINT
455   debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
456                srcX, srcY, dstX, dstY, width, height);
457#endif
458
459   debug_assert(priv == exa->copy.dst);
460
461   renderer_copy_pixmap(exa->renderer, exa->copy.dst, dstX, dstY,
462                        exa->copy.src, srcX, srcY,
463                        width, height);
464}
465
466static Bool
467picture_check_formats(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture)
468{
469   if (pSrc->picture_format == pSrcPicture->format)
470      return TRUE;
471
472   if (pSrc->picture_format != PICT_a8r8g8b8)
473      return FALSE;
474
475   /* pSrc->picture_format == PICT_a8r8g8b8 */
476   switch (pSrcPicture->format) {
477   case PICT_a8r8g8b8:
478   case PICT_x8r8g8b8:
479   case PICT_a8b8g8r8:
480   case PICT_x8b8g8r8:
481   /* just treat these two as x8... */
482   case PICT_r8g8b8:
483   case PICT_b8g8r8:
484      return TRUE;
485#ifdef PICT_TYPE_BGRA
486   case PICT_b8g8r8a8:
487   case PICT_b8g8r8x8:
488      return FALSE; /* does not support swizzleing the alpha channel yet */
489   case PICT_a2r10g10b10:
490   case PICT_x2r10g10b10:
491   case PICT_a2b10g10r10:
492   case PICT_x2b10g10r10:
493      return FALSE;
494#endif
495   default:
496      return FALSE;
497   }
498   return FALSE;
499}
500
501static Bool
502ExaPrepareComposite(int op, PicturePtr pSrcPicture,
503		    PicturePtr pMaskPicture, PicturePtr pDstPicture,
504		    PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
505{
506   ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
507   modesettingPtr ms = modesettingPTR(pScrn);
508   struct exa_context *exa = ms->exa;
509   struct exa_pixmap_priv *priv;
510
511#if DEBUG_PRINT
512   debug_printf("ExaPrepareComposite(%d, src=0x%p, mask=0x%p, dst=0x%p)\n",
513                op, pSrcPicture, pMaskPicture, pDstPicture);
514   debug_printf("\tFormats: src(%s), mask(%s), dst(%s)\n",
515                pSrcPicture ? render_format_name(pSrcPicture->format) : "none",
516                pMaskPicture ? render_format_name(pMaskPicture->format) : "none",
517                pDstPicture ? render_format_name(pDstPicture->format) : "none");
518#endif
519   if (!exa->pipe)
520      XORG_FALLBACK("accle not enabled");
521
522   priv = exaGetPixmapDriverPrivate(pDst);
523   if (!priv || !priv->tex)
524      XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
525
526   if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
527                                       priv->tex->target,
528                                       PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
529      XORG_FALLBACK("pDst format: %s", pf_name(priv->tex->format));
530
531   if (priv->picture_format != pDstPicture->format)
532      XORG_FALLBACK("pDst pic_format: %s != %s",
533                    render_format_name(priv->picture_format),
534                    render_format_name(pDstPicture->format));
535
536   if (pSrc) {
537      priv = exaGetPixmapDriverPrivate(pSrc);
538      if (!priv || !priv->tex)
539         XORG_FALLBACK("pSrc %s", !priv ? "!priv" : "!priv->tex");
540
541      if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
542                                          priv->tex->target,
543                                          PIPE_TEXTURE_USAGE_SAMPLER, 0))
544         XORG_FALLBACK("pSrc format: %s", pf_name(priv->tex->format));
545
546      if (!picture_check_formats(priv, pSrcPicture))
547         XORG_FALLBACK("pSrc pic_format: %s != %s",
548                       render_format_name(priv->picture_format),
549                       render_format_name(pSrcPicture->format));
550
551      if (priv->picture_format == PICT_a8)
552         XORG_FALLBACK("pSrc pic_format == PICT_a8");
553   }
554
555   if (pMask) {
556      priv = exaGetPixmapDriverPrivate(pMask);
557      if (!priv || !priv->tex)
558         XORG_FALLBACK("pMask %s", !priv ? "!priv" : "!priv->tex");
559
560      if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
561                                          priv->tex->target,
562                                          PIPE_TEXTURE_USAGE_SAMPLER, 0))
563         XORG_FALLBACK("pMask format: %s", pf_name(priv->tex->format));
564
565      if (!picture_check_formats(priv, pMaskPicture))
566         XORG_FALLBACK("pMask pic_format: %s != %s",
567                       render_format_name(priv->picture_format),
568                       render_format_name(pMaskPicture->format));
569   }
570
571   return exa->accel &&
572          xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
573                                    pDstPicture,
574                                    pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
575                                    pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
576                                    exaGetPixmapDriverPrivate(pDst));
577}
578
579static void
580ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
581	     int dstX, int dstY, int width, int height)
582{
583   ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
584   modesettingPtr ms = modesettingPTR(pScrn);
585   struct exa_context *exa = ms->exa;
586   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
587
588#if DEBUG_PRINT
589   debug_printf("\tExaComposite(src[%d,%d], mask=[%d, %d], dst=[%d, %d], dim=[%d, %d])\n",
590                srcX, srcY, maskX, maskY, dstX, dstY, width, height);
591   debug_printf("\t   Num bound samplers = %d\n",
592                exa->num_bound_samplers);
593#endif
594
595   xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
596                  dstX, dstY, width, height);
597}
598
599static Bool
600ExaCheckComposite(int op,
601		  PicturePtr pSrcPicture, PicturePtr pMaskPicture,
602		  PicturePtr pDstPicture)
603{
604   ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum];
605   modesettingPtr ms = modesettingPTR(pScrn);
606   struct exa_context *exa = ms->exa;
607   boolean accelerated = xorg_composite_accelerated(op,
608                                                    pSrcPicture,
609                                                    pMaskPicture,
610                                                    pDstPicture);
611#if DEBUG_PRINT
612   debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
613                op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
614#endif
615   return exa->accel && accelerated;
616}
617
618static void *
619ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
620{
621    struct exa_pixmap_priv *priv;
622
623    priv = xcalloc(1, sizeof(struct exa_pixmap_priv));
624    if (!priv)
625	return NULL;
626
627    return priv;
628}
629
630static void
631ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
632{
633    struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
634
635    if (!priv)
636	return;
637
638    pipe_texture_reference(&priv->tex, NULL);
639
640    xfree(priv);
641}
642
643static Bool
644ExaPixmapIsOffscreen(PixmapPtr pPixmap)
645{
646    struct exa_pixmap_priv *priv;
647
648    priv = exaGetPixmapDriverPrivate(pPixmap);
649
650    if (!priv)
651	return FALSE;
652
653    if (priv->tex)
654	return TRUE;
655
656    return FALSE;
657}
658
659int
660xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
661{
662    struct exa_pixmap_priv *priv;
663    priv = exaGetPixmapDriverPrivate(pPixmap);
664
665    if (!priv) {
666	FatalError("NO PIXMAP PRIVATE\n");
667	return 0;
668    }
669
670    priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY;
671
672    return 0;
673}
674
675int
676xorg_exa_set_shared_usage(PixmapPtr pPixmap)
677{
678    struct exa_pixmap_priv *priv;
679    priv = exaGetPixmapDriverPrivate(pPixmap);
680
681    if (!priv) {
682	FatalError("NO PIXMAP PRIVATE\n");
683	return 0;
684    }
685
686    priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
687
688    return 0;
689}
690
691unsigned
692xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
693{
694    ScreenPtr pScreen = pPixmap->drawable.pScreen;
695    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
696    modesettingPtr ms = modesettingPTR(pScrn);
697    struct exa_pixmap_priv *priv;
698    unsigned handle;
699    unsigned stride;
700
701    if (!ms->exa) {
702	FatalError("NO MS->EXA\n");
703	return 0;
704    }
705
706    priv = exaGetPixmapDriverPrivate(pPixmap);
707
708    if (!priv) {
709	FatalError("NO PIXMAP PRIVATE\n");
710	return 0;
711    }
712
713    ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle);
714    if (stride_out)
715	*stride_out = stride;
716
717    return handle;
718}
719
720static Bool
721ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
722		      int depth, int bitsPerPixel, int devKind,
723		      pointer pPixData)
724{
725    ScreenPtr pScreen = pPixmap->drawable.pScreen;
726    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
727    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
728    modesettingPtr ms = modesettingPTR(pScrn);
729    struct exa_context *exa = ms->exa;
730
731    if (!priv || pPixData)
732	return FALSE;
733
734    if (depth <= 0)
735	depth = pPixmap->drawable.depth;
736
737    if (bitsPerPixel <= 0)
738	bitsPerPixel = pPixmap->drawable.bitsPerPixel;
739
740    if (width <= 0)
741	width = pPixmap->drawable.width;
742
743    if (height <= 0)
744	height = pPixmap->drawable.height;
745
746    if (width <= 0 || height <= 0 || depth <= 0)
747	return FALSE;
748
749    miModifyPixmapHeader(pPixmap, width, height, depth,
750			     bitsPerPixel, devKind, NULL);
751
752    /* Deal with screen resize */
753    if ((exa->accel || priv->flags) &&
754        (!priv->tex ||
755         (priv->tex->width0 != width ||
756          priv->tex->height0 != height ||
757          priv->tex_flags != priv->flags))) {
758	struct pipe_texture *texture = NULL;
759	struct pipe_texture template;
760
761	memset(&template, 0, sizeof(template));
762	template.target = PIPE_TEXTURE_2D;
763	exa_get_pipe_format(depth, &template.format, &bitsPerPixel, &priv->picture_format);
764	template.width0 = width;
765	template.height0 = height;
766	template.depth0 = 1;
767	template.last_level = 0;
768	template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
769	priv->tex_flags = priv->flags;
770	texture = exa->scrn->texture_create(exa->scrn, &template);
771
772	if (priv->tex) {
773	    struct pipe_surface *dst_surf;
774	    struct pipe_surface *src_surf;
775
776	    dst_surf = exa->scrn->get_tex_surface(
777		exa->scrn, texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
778	    src_surf = xorg_gpu_surface(exa->pipe->screen, priv);
779        if (exa->pipe->surface_copy) {
780            exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf,
781                        0, 0, min(width, texture->width0),
782                        min(height, texture->height0));
783        } else {
784            util_surface_copy(exa->pipe, FALSE, dst_surf, 0, 0, src_surf,
785                        0, 0, min(width, texture->width0),
786                        min(height, texture->height0));
787        }
788	    exa->scrn->tex_surface_destroy(dst_surf);
789	    exa->scrn->tex_surface_destroy(src_surf);
790	}
791
792	pipe_texture_reference(&priv->tex, texture);
793	/* the texture we create has one reference */
794	pipe_texture_reference(&texture, NULL);
795    }
796
797    return TRUE;
798}
799
800struct pipe_texture *
801xorg_exa_get_texture(PixmapPtr pPixmap)
802{
803   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
804   struct pipe_texture *tex = NULL;
805   pipe_texture_reference(&tex, priv->tex);
806   return tex;
807}
808
809Bool
810xorg_exa_set_texture(PixmapPtr pPixmap, struct  pipe_texture *tex)
811{
812    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
813
814    int mask = PIPE_TEXTURE_USAGE_PRIMARY | PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
815
816    if (!priv)
817	return FALSE;
818
819    if (pPixmap->drawable.width != tex->width0 ||
820	pPixmap->drawable.height != tex->height0)
821	return FALSE;
822
823    pipe_texture_reference(&priv->tex, tex);
824    priv->tex_flags = tex->tex_usage & mask;
825
826    return TRUE;
827}
828
829struct pipe_texture *
830xorg_exa_create_root_texture(ScrnInfoPtr pScrn,
831			     int width, int height,
832			     int depth, int bitsPerPixel)
833{
834    modesettingPtr ms = modesettingPTR(pScrn);
835    struct exa_context *exa = ms->exa;
836    struct pipe_texture template;
837    int dummy;
838
839    memset(&template, 0, sizeof(template));
840    template.target = PIPE_TEXTURE_2D;
841    exa_get_pipe_format(depth, &template.format, &bitsPerPixel, &dummy);
842    template.width0 = width;
843    template.height0 = height;
844    template.depth0 = 1;
845    template.last_level = 0;
846    template.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
847    template.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
848    template.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
849
850    return exa->scrn->texture_create(exa->scrn, &template);
851}
852
853void
854xorg_exa_close(ScrnInfoPtr pScrn)
855{
856   modesettingPtr ms = modesettingPTR(pScrn);
857   struct exa_context *exa = ms->exa;
858
859   renderer_destroy(exa->renderer);
860
861   if (exa->pipe)
862      exa->pipe->destroy(exa->pipe);
863
864   exaDriverFini(pScrn->pScreen);
865   xfree(exa);
866   ms->exa = NULL;
867}
868
869void *
870xorg_exa_init(ScrnInfoPtr pScrn, Bool accel)
871{
872   modesettingPtr ms = modesettingPTR(pScrn);
873   struct exa_context *exa;
874   ExaDriverPtr pExa;
875
876   exa = xcalloc(1, sizeof(struct exa_context));
877   if (!exa)
878      return NULL;
879
880   pExa = exaDriverAlloc();
881   if (!pExa) {
882      goto out_err;
883   }
884
885   memset(pExa, 0, sizeof(*pExa));
886
887   pExa->exa_major         = 2;
888   pExa->exa_minor         = 2;
889   pExa->memoryBase        = 0;
890   pExa->memorySize        = 0;
891   pExa->offScreenBase     = 0;
892   pExa->pixmapOffsetAlign = 0;
893   pExa->pixmapPitchAlign  = 1;
894   pExa->flags             = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
895#ifdef EXA_SUPPORTS_PREPARE_AUX
896   pExa->flags            |= EXA_SUPPORTS_PREPARE_AUX;
897#endif
898#ifdef EXA_MIXED_PIXMAPS
899   pExa->flags            |= EXA_MIXED_PIXMAPS;
900#endif
901   pExa->maxX              = 8191; /* FIXME */
902   pExa->maxY              = 8191; /* FIXME */
903
904   pExa->WaitMarker         = ExaWaitMarker;
905   pExa->MarkSync           = ExaMarkSync;
906   pExa->PrepareSolid       = ExaPrepareSolid;
907   pExa->Solid              = ExaSolid;
908   pExa->DoneSolid          = ExaDone;
909   pExa->PrepareCopy        = ExaPrepareCopy;
910   pExa->Copy               = ExaCopy;
911   pExa->DoneCopy           = ExaDone;
912   pExa->CheckComposite     = ExaCheckComposite;
913   pExa->PrepareComposite   = ExaPrepareComposite;
914   pExa->Composite          = ExaComposite;
915   pExa->DoneComposite      = ExaDoneComposite;
916   pExa->PixmapIsOffscreen  = ExaPixmapIsOffscreen;
917   pExa->DownloadFromScreen = ExaDownloadFromScreen;
918   pExa->UploadToScreen     = ExaUploadToScreen;
919   pExa->PrepareAccess      = ExaPrepareAccess;
920   pExa->FinishAccess       = ExaFinishAccess;
921   pExa->CreatePixmap       = ExaCreatePixmap;
922   pExa->DestroyPixmap      = ExaDestroyPixmap;
923   pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
924
925   if (!exaDriverInit(pScrn->pScreen, pExa)) {
926      goto out_err;
927   }
928
929   exa->scrn = ms->screen;
930   exa->pipe = ms->api->create_context(ms->api, exa->scrn);
931   /* Share context with DRI */
932   ms->ctx = exa->pipe;
933
934   exa->renderer = renderer_create(exa->pipe);
935   exa->accel = accel;
936
937   return (void *)exa;
938
939out_err:
940   xorg_exa_close(pScrn);
941
942   return NULL;
943}
944
945struct pipe_surface *
946xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv)
947{
948   return scrn->get_tex_surface(scrn, priv->tex, 0, 0, 0,
949                                PIPE_BUFFER_USAGE_GPU_READ |
950                                PIPE_BUFFER_USAGE_GPU_WRITE);
951
952}
953
954void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
955                    struct pipe_fence_handle **fence)
956{
957   exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
958}
959
960void xorg_exa_finish(struct exa_context *exa)
961{
962   struct pipe_fence_handle *fence = NULL;
963
964   xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
965
966   exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
967   exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
968}
969
970