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