Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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