Home | History | Annotate | Download | only in xorg
      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 (at) tungstengraphics.com>
     27  * Author: Jakob Bornecrantz <wallbraker (at) 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 
     54 static INLINE void
     55 exa_debug_printf(const char *format, ...) _util_printf_format(1,2);
     56 
     57 static INLINE void
     58 exa_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  */
     73 struct render_format_str {
     74    int format;
     75    const char *name;
     76 };
     77 static 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 };
    123 static 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 
    133 static void
    134 exa_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 
    177 static void
    178 ExaWaitMarker(ScreenPtr pScreen, int marker)
    179 {
    180    /* Nothing to do, handled in the PrepareAccess hook */
    181 }
    182 
    183 static int
    184 ExaMarkSync(ScreenPtr pScreen)
    185 {
    186    return 1;
    187 }
    188 
    189 
    190 /***********************************************************************
    191  * Screen upload/download
    192  */
    193 
    194 static Bool
    195 ExaDownloadFromScreen(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 
    226 static Bool
    227 ExaUploadToScreen(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 
    258 static Bool
    259 ExaPrepareAccess(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 
    310 static void
    311 ExaFinishAccess(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 
    343 static Bool
    344 ExaPrepareSolid(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 
    377 static void
    378 ExaSolid(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 
    402 static void
    403 ExaDoneSolid(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 
    422 static Bool
    423 ExaPrepareCopy(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 
    468 static void
    469 ExaCopy(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 
    524 static void
    525 ExaDoneCopy(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 
    549 static Bool
    550 picture_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 
    588 static Bool
    589 ExaCheckComposite(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 
    608 static Bool
    609 ExaPrepareComposite(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 
    685 static void
    686 ExaComposite(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 
    705 static void
    706 ExaDoneComposite(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 
    720 static void *
    721 ExaCreatePixmap(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 
    732 static void
    733 ExaDestroyPixmap(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 
    745 static Bool
    746 ExaPixmapIsOffscreen(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 
    761 int
    762 xorg_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 
    777 int
    778 xorg_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 
    795 static Bool
    796 size_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 
    811 static Bool
    812 ExaModifyPixmapHeader(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 
    904 struct pipe_resource *
    905 xorg_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 
    913 Bool
    914 xorg_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 
    933 struct pipe_resource *
    934 xorg_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 
    958 void
    959 xorg_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 
    982 void *
    983 xorg_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    pExa->exa_major         = 2;
   1005    pExa->exa_minor         = 2;
   1006    pExa->memoryBase        = 0;
   1007    pExa->memorySize        = 0;
   1008    pExa->offScreenBase     = 0;
   1009    pExa->pixmapOffsetAlign = 0;
   1010    pExa->pixmapPitchAlign  = 1;
   1011    pExa->flags             = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
   1012 #ifdef EXA_SUPPORTS_PREPARE_AUX
   1013    pExa->flags            |= EXA_SUPPORTS_PREPARE_AUX;
   1014 #endif
   1015 #ifdef EXA_MIXED_PIXMAPS
   1016    pExa->flags            |= EXA_MIXED_PIXMAPS;
   1017 #endif
   1018 
   1019    pExa->maxX = pExa->maxY =
   1020    1 << (exa->scrn->get_param(exa->scrn, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
   1021 
   1022    pExa->WaitMarker         = ExaWaitMarker;
   1023    pExa->MarkSync           = ExaMarkSync;
   1024    pExa->PrepareSolid       = ExaPrepareSolid;
   1025    pExa->Solid              = ExaSolid;
   1026    pExa->DoneSolid          = ExaDoneSolid;
   1027    pExa->PrepareCopy        = ExaPrepareCopy;
   1028    pExa->Copy               = ExaCopy;
   1029    pExa->DoneCopy           = ExaDoneCopy;
   1030    pExa->CheckComposite     = ExaCheckComposite;
   1031    pExa->PrepareComposite   = ExaPrepareComposite;
   1032    pExa->Composite          = ExaComposite;
   1033    pExa->DoneComposite      = ExaDoneComposite;
   1034    pExa->PixmapIsOffscreen  = ExaPixmapIsOffscreen;
   1035    pExa->DownloadFromScreen = ExaDownloadFromScreen;
   1036    pExa->UploadToScreen     = ExaUploadToScreen;
   1037    pExa->PrepareAccess      = ExaPrepareAccess;
   1038    pExa->FinishAccess       = ExaFinishAccess;
   1039    pExa->CreatePixmap       = ExaCreatePixmap;
   1040    pExa->DestroyPixmap      = ExaDestroyPixmap;
   1041    pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
   1042 
   1043    if (!exaDriverInit(pScrn->pScreen, pExa)) {
   1044       goto out_err;
   1045    }
   1046 
   1047    /* Share context with DRI */
   1048    ms->ctx = exa->pipe;
   1049    if (cust && cust->winsys_context_throttle)
   1050        cust->winsys_context_throttle(cust, ms->ctx, THROTTLE_RENDER);
   1051 
   1052    exa->renderer = renderer_create(exa->pipe);
   1053    exa->accel = accel;
   1054 
   1055    return (void *)exa;
   1056 
   1057 out_err:
   1058    xorg_exa_close(pScrn);
   1059    free(exa);
   1060 
   1061    return NULL;
   1062 }
   1063 
   1064 struct pipe_surface *
   1065 xorg_gpu_surface(struct pipe_context *pipe, struct exa_pixmap_priv *priv)
   1066 {
   1067    struct pipe_surface surf_tmpl;
   1068    memset(&surf_tmpl, 0, sizeof(surf_tmpl));
   1069    u_surface_default_template(&surf_tmpl, priv->tex,
   1070                               PIPE_BIND_RENDER_TARGET);
   1071 
   1072    return pipe->create_surface(pipe, priv->tex, &surf_tmpl);
   1073 
   1074 }
   1075 
   1076 void xorg_exa_flush(struct exa_context *exa,
   1077                     struct pipe_fence_handle **fence)
   1078 {
   1079    exa->pipe->flush(exa->pipe, fence);
   1080 }
   1081 
   1082 void xorg_exa_finish(struct exa_context *exa)
   1083 {
   1084    struct pipe_fence_handle *fence = NULL;
   1085 
   1086    xorg_exa_flush(exa, &fence);
   1087 
   1088    exa->pipe->screen->fence_finish(exa->pipe->screen, fence,
   1089                                    PIPE_TIMEOUT_INFINITE);
   1090    exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
   1091 }
   1092 
   1093