gallium: Permit surface_copy and surface_fill to be NULL.
[mesa.git] / src / gallium / state_trackers / xorg / xorg_exa.c
index 3c90c2c9429fc453d25ed8a12bfef5196c8b7178..4988af48641c96a3dbbabe66ac6ed2a2cb297365 100644 (file)
@@ -31,6 +31,7 @@
 #include "xorg_exa.h"
 #include "xorg_tracker.h"
 #include "xorg_composite.h"
+#include "xorg_exa_tgsi.h"
 
 #include <xorg-server.h>
 #include <xf86.h>
 #include "pipe/p_state.h"
 #include "pipe/p_inlines.h"
 
-#include "cso_cache/cso_context.h"
-
 #include "util/u_rect.h"
 
+#define DEBUG_PRINT 0
+#define DEBUG_SOLID 0
+#define DISABLE_ACCEL 0
+
 /*
  * Helper functions
  */
@@ -71,6 +74,9 @@ exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
        assert(*bbp == 16);
        break;
     case 8:
+       *format = PIPE_FORMAT_A8_UNORM;
+       assert(*bbp == 8);
+       break;
     case 4:
     case 1:
        *format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
@@ -81,6 +87,15 @@ exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
     }
 }
 
+static void
+xorg_exa_common_done(struct exa_context *exa)
+{
+   exa->copy.src = NULL;
+   exa->copy.dst = NULL;
+   exa->has_solid_color = FALSE;
+   exa->num_bound_samplers = 0;
+}
+
 /*
  * Static exported EXA functions
  */
@@ -96,6 +111,68 @@ ExaMarkSync(ScreenPtr pScreen)
     return 1;
 }
 
+static Bool
+ExaDownloadFromScreen(PixmapPtr pPix, int x,  int y, int w,  int h, char *dst,
+                     int dst_pitch)
+{
+    ScreenPtr pScreen = pPix->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    modesettingPtr ms = modesettingPTR(pScrn);
+    struct exa_context *exa = ms->exa;
+    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
+    struct pipe_transfer *transfer;
+
+    if (!priv || !priv->tex)
+       return FALSE;
+
+    if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
+       PIPE_REFERENCED_FOR_WRITE)
+       exa->pipe->flush(exa->pipe, 0, NULL);
+
+    transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
+                                          PIPE_TRANSFER_READ, x, y, w, h);
+    if (!transfer)
+       return FALSE;
+
+    util_copy_rect((unsigned char*)dst, &priv->tex->block, dst_pitch, 0, 0,
+                  w, h, exa->scrn->transfer_map(exa->scrn, transfer),
+                  transfer->stride, 0, 0);
+
+    exa->scrn->transfer_unmap(exa->scrn, transfer);
+    exa->scrn->tex_transfer_destroy(transfer);
+
+    return TRUE;
+}
+
+static Bool
+ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src,
+                 int src_pitch)
+{
+    ScreenPtr pScreen = pPix->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    modesettingPtr ms = modesettingPTR(pScrn);
+    struct exa_context *exa = ms->exa;
+    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
+    struct pipe_transfer *transfer;
+
+    if (!priv || !priv->tex)
+       return FALSE;
+
+    transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
+                                          PIPE_TRANSFER_WRITE, x, y, w, h);
+    if (!transfer)
+       return FALSE;
+
+    util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
+                  &priv->tex->block, transfer->stride, 0, 0, w, h,
+                  (unsigned char*)src, src_pitch, 0, 0);
+
+    exa->scrn->transfer_unmap(exa->scrn, transfer);
+    exa->scrn->tex_transfer_destroy(transfer);
+
+    return TRUE;
+}
+
 static Bool
 ExaPrepareAccess(PixmapPtr pPix, int index)
 {
@@ -113,18 +190,33 @@ ExaPrepareAccess(PixmapPtr pPix, int index)
     if (!priv->tex)
        return FALSE;
 
-    if (priv->map_count++ == 0)
+    if (priv->map_count == 0)
     {
+       if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
+           PIPE_REFERENCED_FOR_WRITE)
+           exa->pipe->flush(exa->pipe, 0, NULL);
+
        priv->map_transfer =
            exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
+#ifdef EXA_MIXED_PIXMAPS
+                                       PIPE_TRANSFER_MAP_DIRECTLY |
+#endif
                                        PIPE_TRANSFER_READ_WRITE,
                                        0, 0, priv->tex->width[0], priv->tex->height[0]);
+       if (!priv->map_transfer)
+#ifdef EXA_MIXED_PIXMAPS
+           return FALSE;
+#else
+           FatalError("failed to create transfer\n");
+#endif
 
        pPix->devPrivate.ptr =
            exa->scrn->transfer_map(exa->scrn, priv->map_transfer);
        pPix->devKind = priv->map_transfer->stride;
     }
 
+    priv->map_count++;
+
     return TRUE;
 }
 
@@ -149,6 +241,7 @@ ExaFinishAccess(PixmapPtr pPix, int index)
        exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
        exa->scrn->tex_transfer_destroy(priv->map_transfer);
        priv->map_transfer = NULL;
+       pPix->devPrivate.ptr = NULL;
     }
 }
 
@@ -163,15 +256,22 @@ ExaDone(PixmapPtr pPixmap)
     if (!priv)
        return;
 
-    if (priv->src_surf)
-       exa->scrn->tex_surface_destroy(priv->src_surf);
-    priv->src_surf = NULL;
+#if 1
+    xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL);
+#else
+    xorg_exa_finish(exa);
+#endif
+    xorg_exa_common_done(exa);
 }
 
 static void
 ExaDoneComposite(PixmapPtr pPixmap)
 {
+   ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+   modesettingPtr ms = modesettingPTR(pScrn);
+   struct exa_context *exa = ms->exa;
 
+   xorg_exa_common_done(exa);
 }
 
 static Bool
@@ -182,27 +282,36 @@ ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
     struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
     struct exa_context *exa = ms->exa;
 
-    if (1)
-        return FALSE;
+#if DEBUG_PRINT
+    debug_printf("ExaPrepareSolid(0x%x)\n", fg);
+#endif
+    if (!exa->pipe)
+       XORG_FALLBACK("accle not enabled");
 
-    if (pPixmap->drawable.depth < 15)
-       return FALSE;
+    if (!priv || !priv->tex)
+       XORG_FALLBACK("%s", !priv ? "!priv" : "!priv->tex");
 
     if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
-       return FALSE;
-
-    if (!priv || !priv->tex)
-       return FALSE;
+       XORG_FALLBACK("planeMask is not solid");
 
     if (alu != GXcopy)
-       return FALSE;
+       XORG_FALLBACK("not GXcopy");
 
-    if (!exa->ctx || !exa->ctx->surface_fill)
-       return FALSE;
+    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
+                                        priv->tex->target,
+                                        PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
+       XORG_FALLBACK("format %s", pf_name(priv->tex->format));
+    }
 
-    priv->color = fg;
+#if DEBUG_SOLID
+    fg = 0xffff0000;
+#endif
 
-    return TRUE;
+#if DISABLE_ACCEL
+    return FALSE;
+#else
+    return xorg_solid_bind_state(exa, priv, fg);
+#endif
 }
 
 static void
@@ -212,15 +321,51 @@ ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
     modesettingPtr ms = modesettingPTR(pScrn);
     struct exa_context *exa = ms->exa;
     struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
-    struct pipe_surface *surf =
-       exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
-                                  PIPE_BUFFER_USAGE_GPU_READ |
-                                  PIPE_BUFFER_USAGE_GPU_WRITE);
 
-    exa->ctx->surface_fill(exa->ctx, surf, x0, y0, x1 - x0, y1 - y0,
-                          priv->color);
+#if DEBUG_PRINT
+    debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
+#endif
+
+#if 0
+    if (x0 == 0 && y0 == 0 &&
+        x1 == priv->tex->width[0] &&
+        y1 == priv->tex->height[0]) {
+       exa->ctx->clear(exa->pipe, PIPE_CLEAR_COLOR,
+                       exa->solid_color, 1., 0);
+    } else
+#endif
 
-    exa->scrn->tex_surface_destroy(surf);
+#if DEBUG_SOLID
+       exa->solid_color[0] = 0.f;
+       exa->solid_color[1] = 1.f;
+       exa->solid_color[2] = 0.f;
+       exa->solid_color[3] = 1.f;
+    xorg_solid(exa, priv, 0, 0, 1024, 768);
+       exa->solid_color[0] = 1.f;
+       exa->solid_color[1] = 0.f;
+       exa->solid_color[2] = 0.f;
+       exa->solid_color[3] = 1.f;
+       xorg_solid(exa, priv, 0, 0, 300, 300);
+       xorg_solid(exa, priv, 300, 300, 350, 350);
+       xorg_solid(exa, priv, 350, 350, 500, 500);
+
+       xorg_solid(exa, priv,
+               priv->tex->width[0] - 10,
+               priv->tex->height[0] - 10,
+               priv->tex->width[0],
+               priv->tex->height[0]);
+
+    exa->solid_color[0] = 0.f;
+    exa->solid_color[1] = 0.f;
+    exa->solid_color[2] = 1.f;
+    exa->solid_color[3] = 1.f;
+
+    exa->has_solid_color = FALSE;
+    ExaPrepareCopy(pPixmap, pPixmap, 0, 0, GXcopy, 0xffffffff);
+    ExaCopy(pPixmap, 0, 0, 50, 50, 500, 500);
+#else
+    xorg_solid(exa, priv, x0, y0, x1, y1) ;
+#endif
 }
 
 static Bool
@@ -233,51 +378,63 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
     struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
     struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
 
-    if (1)
-        return FALSE;
+#if DEBUG_PRINT
+    debug_printf("ExaPrepareCopy\n");
+#endif
+    if (!exa->pipe)
+       XORG_FALLBACK("accle not enabled");
 
-    if (alu != GXcopy)
-       return FALSE;
+    if (!priv || !priv->tex)
+       XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
 
-    if (pSrcPixmap->drawable.depth < 15 || pDstPixmap->drawable.depth < 15)
-       return FALSE;
+    if (!src_priv || !src_priv->tex)
+       XORG_FALLBACK("pSrc %s", !src_priv ? "!priv" : "!priv->tex");
 
     if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
-       return FALSE;
+       XORG_FALLBACK("planeMask is not solid");
 
-    if (!priv || !src_priv)
-       return FALSE;
+    if (alu != GXcopy)
+       XORG_FALLBACK("alu not GXcopy");
 
-    if (!priv->tex || !src_priv->tex)
-       return FALSE;
+    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
+                                        priv->tex->target,
+                                        PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
+       XORG_FALLBACK("pDst format %s", pf_name(priv->tex->format));
 
-    if (!exa->ctx || !exa->ctx->surface_copy)
-       return FALSE;
+    if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format,
+                                        src_priv->tex->target,
+                                        PIPE_TEXTURE_USAGE_SAMPLER, 0))
+       XORG_FALLBACK("pSrc format %s", pf_name(src_priv->tex->format));
 
-    priv->src_surf =
-       exa->scrn->get_tex_surface(exa->scrn, src_priv->tex, 0, 0, 0,
-                                  PIPE_BUFFER_USAGE_GPU_READ |
-                                  PIPE_BUFFER_USAGE_GPU_WRITE);
+    exa->copy.src = src_priv;
+    exa->copy.dst = priv;
 
+#if DISABLE_ACCEL
+    return FALSE;
+#else
     return TRUE;
+#endif
 }
 
 static void
 ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
        int width, int height)
 {
-    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
-    modesettingPtr ms = modesettingPTR(pScrn);
-    struct exa_context *exa = ms->exa;
-    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
-    struct pipe_surface *surf =
-       exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
-                                  PIPE_BUFFER_USAGE_GPU_READ |
-                                  PIPE_BUFFER_USAGE_GPU_WRITE);
-
-    exa->ctx->surface_copy(exa->ctx, surf, dstX, dstY, priv->src_surf,
-                          srcX, srcY, width, height);
-    exa->scrn->tex_surface_destroy(surf);
+   ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+   modesettingPtr ms = modesettingPTR(pScrn);
+   struct exa_context *exa = ms->exa;
+   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
+
+#if DEBUG_PRINT
+   debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
+                srcX, srcY, dstX, dstY, width, height);
+#endif
+
+   debug_assert(priv == exa->copy.dst);
+
+   renderer_copy_pixmap(exa->renderer, exa->copy.dst, dstX, dstY,
+                        exa->copy.src, srcX, srcY,
+                        width, height);
 }
 
 static Bool
@@ -288,9 +445,55 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture,
    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
    modesettingPtr ms = modesettingPTR(pScrn);
    struct exa_context *exa = ms->exa;
+   struct exa_pixmap_priv *priv;
 
+#if DEBUG_PRINT
+   debug_printf("ExaPrepareComposite\n");
+#endif
+   if (!exa->pipe)
+      XORG_FALLBACK("accle not enabled");
+
+   priv = exaGetPixmapDriverPrivate(pDst);
+   if (!priv || !priv->tex)
+      XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
+
+   if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
+                                       priv->tex->target,
+                                       PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
+      XORG_FALLBACK("pDst format: %s", pf_name(priv->tex->format));
+
+   if (pSrc) {
+      priv = exaGetPixmapDriverPrivate(pSrc);
+      if (!priv || !priv->tex)
+         XORG_FALLBACK("pSrc %s", !priv ? "!priv" : "!priv->tex");
+
+      if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
+                                          priv->tex->target,
+                                          PIPE_TEXTURE_USAGE_SAMPLER, 0))
+         XORG_FALLBACK("pSrc format: %s", pf_name(priv->tex->format));
+   }
+
+   if (pMask) {
+      priv = exaGetPixmapDriverPrivate(pMask);
+      if (!priv || !priv->tex)
+         XORG_FALLBACK("pMask %s", !priv ? "!priv" : "!priv->tex");
+
+      if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
+                                          priv->tex->target,
+                                          PIPE_TEXTURE_USAGE_SAMPLER, 0))
+         XORG_FALLBACK("pMask format: %s", pf_name(priv->tex->format));
+   }
+
+#if DISABLE_ACCEL
+   (void) exa;
+   return FALSE;
+#else
    return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
-                                    pDstPicture);
+                                    pDstPicture,
+                                    pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
+                                    pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
+                                    exaGetPixmapDriverPrivate(pDst));
+#endif
 }
 
 static void
@@ -302,6 +505,10 @@ ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
    struct exa_context *exa = ms->exa;
    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
 
+#if DEBUG_PRINT
+   debug_printf("\tExaComposite(src[%d,%d], mask=[%d, %d], dst=[%d, %d], dim=[%d, %d])\n", srcX, srcY, maskX, maskY, dstX, dstY, width, height);
+#endif
+
    xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
                   dstX, dstY, width, height);
 }
@@ -311,10 +518,18 @@ ExaCheckComposite(int op,
                  PicturePtr pSrcPicture, PicturePtr pMaskPicture,
                  PicturePtr pDstPicture)
 {
-   return xorg_composite_accelerated(op,
-                                     pSrcPicture,
-                                     pMaskPicture,
-                                     pDstPicture);
+   boolean accelerated = xorg_composite_accelerated(op,
+                                                    pSrcPicture,
+                                                    pMaskPicture,
+                                                    pDstPicture);
+#if DEBUG_PRINT
+   debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
+                op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
+#endif
+#if DISABLE_ACCEL
+   accelerated = FALSE;
+#endif
+   return accelerated;
 }
 
 static void *
@@ -333,14 +548,11 @@ static void
 ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
 {
     struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
-    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-    modesettingPtr ms = modesettingPTR(pScrn);
 
     if (!priv)
        return;
 
-    if (priv->tex)
-       ms->screen->texture_destroy(priv->tex);
+    pipe_texture_reference(&priv->tex, NULL);
 
     xfree(priv);
 }
@@ -372,11 +584,7 @@ xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
        return 0;
     }
 
-    if (priv->flags & ~PIPE_TEXTURE_USAGE_PRIMARY) {
-       FatalError("BAD FLAGS\n");
-       return 0;
-    }
-    priv->flags = PIPE_TEXTURE_USAGE_PRIMARY;
+    priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY;
 
     return 0;
 }
@@ -392,11 +600,7 @@ xorg_exa_set_shared_usage(PixmapPtr pPixmap)
        return 0;
     }
 
-    if (priv->flags & ~PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
-       FatalError("BAD FLAGS\n");
-       return 0;
-    }
-    priv->flags = PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
+    priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
 
     return 0;
 }
@@ -408,7 +612,6 @@ xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     modesettingPtr ms = modesettingPTR(pScrn);
     struct exa_pixmap_priv *priv;
-    struct pipe_buffer *buffer = NULL;
     unsigned handle;
     unsigned stride;
 
@@ -424,9 +627,7 @@ xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
        return 0;
     }
 
-    ms->api->buffer_from_texture(ms->api, priv->tex, &buffer, &stride);
-    ms->api->handle_from_buffer(ms->api, ms->screen, buffer, &handle);
-    pipe_buffer_reference(&buffer, NULL);
+    ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle);
     if (stride_out)
        *stride_out = stride;
 
@@ -444,7 +645,7 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
     modesettingPtr ms = modesettingPTR(pScrn);
     struct exa_context *exa = ms->exa;
 
-    if (!priv)
+    if (!priv || pPixData)
        return FALSE;
 
     if (depth <= 0)
@@ -466,17 +667,11 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
                             bitsPerPixel, devKind, NULL);
 
     /* Deal with screen resize */
-    if (priv->tex && (priv->tex->width[0] != width ||
-                     priv->tex->height[0] != height ||
-                     priv->tex_flags != priv->flags)) {
-       pipe_texture_reference(&priv->tex, NULL);
-    }
-
-    if (!priv->tex
-#ifdef DRM_MODE_FEATURE_DIRTYFB
-       && priv->flags
-#endif
-       ) {
+    if (!priv->tex ||
+        (priv->tex->width[0] != width ||
+         priv->tex->height[0] != height ||
+         priv->tex_flags != priv->flags)) {
+       struct pipe_texture *texture = NULL;
        struct pipe_texture template;
 
        memset(&template, 0, sizeof(template));
@@ -489,27 +684,31 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
        template.last_level = 0;
        template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
        priv->tex_flags = priv->flags;
-       priv->tex = exa->scrn->texture_create(exa->scrn, &template);
-    }
-
-#ifdef DRM_MODE_FEATURE_DIRTYFB
-    if (!priv->tex) {
-       if (pPixData)
-           pPixmap->devPrivate.ptr = pPixData;
-       else
-           pPixmap->devPrivate.ptr = xalloc(pPixmap->drawable.height * pPixmap->devKind);
-    } else
-#endif
-    if (pPixData) {
-       struct pipe_transfer *transfer =
-           exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
-                                       PIPE_TRANSFER_WRITE,
-                                       0, 0, width, height);
-        util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
-                       &priv->tex->block, transfer->stride, 0, 0,
-                       width, height, pPixData, pPixmap->devKind, 0, 0);
-        exa->scrn->transfer_unmap(exa->scrn, transfer);
-        exa->scrn->tex_transfer_destroy(transfer);
+       texture = exa->scrn->texture_create(exa->scrn, &template);
+
+       if (priv->tex) {
+           struct pipe_surface *dst_surf;
+           struct pipe_surface *src_surf;
+
+           dst_surf = exa->scrn->get_tex_surface(
+               exa->scrn, texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
+           src_surf = xorg_gpu_surface(exa->pipe->screen, priv);
+        if (exa->pipe->surface_copy) {
+            exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf,
+                        0, 0, min(width, texture->width[0]),
+                        min(height, texture->height[0]));
+        } else {
+            util_surface_copy(exa->pipe, FALSE, dst_surf, 0, 0, src_surf,
+                        0, 0, min(width, texture->width[0]),
+                        min(height, texture->height[0]));
+        }
+           exa->scrn->tex_surface_destroy(dst_surf);
+           exa->scrn->tex_surface_destroy(src_surf);
+       }
+
+       pipe_texture_reference(&priv->tex, texture);
+       /* the texture we create has one reference */
+       pipe_texture_reference(&texture, NULL);
     }
 
     return TRUE;
@@ -518,96 +717,125 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
 struct pipe_texture *
 xorg_exa_get_texture(PixmapPtr pPixmap)
 {
-    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
-    struct pipe_texture *tex = NULL;
-    pipe_texture_reference(&tex, priv->tex);
-    return tex;
+   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
+   struct pipe_texture *tex = NULL;
+   pipe_texture_reference(&tex, priv->tex);
+   return tex;
 }
 
 void
 xorg_exa_close(ScrnInfoPtr pScrn)
 {
-    modesettingPtr ms = modesettingPTR(pScrn);
-    struct exa_context *exa = ms->exa;
+   modesettingPtr ms = modesettingPTR(pScrn);
+   struct exa_context *exa = ms->exa;
 
-    if (exa->cso) {
-       cso_release_all(exa->cso);
-       cso_destroy_context(exa->cso);
-    }
+   renderer_destroy(exa->renderer);
 
-    if (exa->ctx)
-       exa->ctx->destroy(exa->ctx);
+   if (exa->pipe)
+      exa->pipe->destroy(exa->pipe);
 
-    exaDriverFini(pScrn->pScreen);
-    xfree(exa);
-    ms->exa = NULL;
+   exaDriverFini(pScrn->pScreen);
+   xfree(exa);
+   ms->exa = NULL;
 }
 
 void *
 xorg_exa_init(ScrnInfoPtr pScrn)
 {
-    modesettingPtr ms = modesettingPTR(pScrn);
-    struct exa_context *exa;
-    ExaDriverPtr pExa;
-
-    exa = xcalloc(1, sizeof(struct exa_context));
-    if (!exa)
-       return NULL;
-
-    pExa = exaDriverAlloc();
-    if (!pExa) {
-       goto out_err;
-    }
+   modesettingPtr ms = modesettingPTR(pScrn);
+   struct exa_context *exa;
+   ExaDriverPtr pExa;
+
+   exa = xcalloc(1, sizeof(struct exa_context));
+   if (!exa)
+      return NULL;
+
+   pExa = exaDriverAlloc();
+   if (!pExa) {
+      goto out_err;
+   }
+
+   memset(pExa, 0, sizeof(*pExa));
+
+   pExa->exa_major         = 2;
+   pExa->exa_minor         = 2;
+   pExa->memoryBase        = 0;
+   pExa->memorySize        = 0;
+   pExa->offScreenBase     = 0;
+   pExa->pixmapOffsetAlign = 0;
+   pExa->pixmapPitchAlign  = 1;
+   pExa->flags             = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
+#ifdef EXA_SUPPORTS_PREPARE_AUX
+   pExa->flags            |= EXA_SUPPORTS_PREPARE_AUX;
+#endif
+#ifdef EXA_MIXED_PIXMAPS
+   pExa->flags            |= EXA_MIXED_PIXMAPS;
+#endif
+   pExa->maxX              = 8191; /* FIXME */
+   pExa->maxY              = 8191; /* FIXME */
+
+   pExa->WaitMarker         = ExaWaitMarker;
+   pExa->MarkSync           = ExaMarkSync;
+   pExa->PrepareSolid       = ExaPrepareSolid;
+   pExa->Solid              = ExaSolid;
+   pExa->DoneSolid          = ExaDone;
+   pExa->PrepareCopy        = ExaPrepareCopy;
+   pExa->Copy               = ExaCopy;
+   pExa->DoneCopy           = ExaDone;
+   pExa->CheckComposite     = ExaCheckComposite;
+   pExa->PrepareComposite   = ExaPrepareComposite;
+   pExa->Composite          = ExaComposite;
+   pExa->DoneComposite      = ExaDoneComposite;
+   pExa->PixmapIsOffscreen  = ExaPixmapIsOffscreen;
+   pExa->DownloadFromScreen = ExaDownloadFromScreen;
+   pExa->UploadToScreen     = ExaUploadToScreen;
+   pExa->PrepareAccess      = ExaPrepareAccess;
+   pExa->FinishAccess       = ExaFinishAccess;
+   pExa->CreatePixmap       = ExaCreatePixmap;
+   pExa->DestroyPixmap      = ExaDestroyPixmap;
+   pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
+
+   if (!exaDriverInit(pScrn->pScreen, pExa)) {
+      goto out_err;
+   }
+
+   exa->scrn = ms->screen;
+   exa->pipe = ms->api->create_context(ms->api, exa->scrn);
+   /* Share context with DRI */
+   ms->ctx = exa->pipe;
+
+   exa->renderer = renderer_create(exa->pipe);
+
+   return (void *)exa;
+
+out_err:
+   xorg_exa_close(pScrn);
+
+   return NULL;
+}
 
-    memset(pExa, 0, sizeof(*pExa));
-
-    pExa->exa_major         = 2;
-    pExa->exa_minor         = 2;
-    pExa->memoryBase        = 0;
-    pExa->memorySize        = 0;
-    pExa->offScreenBase     = 0;
-    pExa->pixmapOffsetAlign = 0;
-    pExa->pixmapPitchAlign  = 1;
-    pExa->flags             = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
-    pExa->maxX              = 8191; /* FIXME */
-    pExa->maxY              = 8191; /* FIXME */
-
-    pExa->WaitMarker         = ExaWaitMarker;
-    pExa->MarkSync           = ExaMarkSync;
-    pExa->PrepareSolid       = ExaPrepareSolid;
-    pExa->Solid              = ExaSolid;
-    pExa->DoneSolid          = ExaDone;
-    pExa->PrepareCopy        = ExaPrepareCopy;
-    pExa->Copy               = ExaCopy;
-    pExa->DoneCopy           = ExaDone;
-    pExa->CheckComposite     = ExaCheckComposite;
-    pExa->PrepareComposite   = ExaPrepareComposite;
-    pExa->Composite          = ExaComposite;
-    pExa->DoneComposite      = ExaDoneComposite;
-    pExa->PixmapIsOffscreen  = ExaPixmapIsOffscreen;
-    pExa->PrepareAccess      = ExaPrepareAccess;
-    pExa->FinishAccess       = ExaFinishAccess;
-    pExa->CreatePixmap       = ExaCreatePixmap;
-    pExa->DestroyPixmap      = ExaDestroyPixmap;
-    pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
-
-    if (!exaDriverInit(pScrn->pScreen, pExa)) {
-       goto out_err;
-    }
+struct pipe_surface *
+xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv)
+{
+   return scrn->get_tex_surface(scrn, priv->tex, 0, 0, 0,
+                                PIPE_BUFFER_USAGE_GPU_READ |
+                                PIPE_BUFFER_USAGE_GPU_WRITE);
 
-    exa->scrn = ms->screen;
-    exa->ctx = ms->api->create_context(ms->api, exa->scrn);
-    /* Share context with DRI */
-    ms->ctx = exa->ctx;
+}
 
-    exa->cso = cso_create_context(exa->ctx);
+void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
+                    struct pipe_fence_handle **fence)
+{
+   exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
+}
 
-    return (void *)exa;
+void xorg_exa_finish(struct exa_context *exa)
+{
+   struct pipe_fence_handle *fence = NULL;
 
-  out_err:
-    xorg_exa_close(pScrn);
+   xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
 
-    return NULL;
+   exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
+   exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
 }
 
-/* vim: set sw=4 ts=8 sts=4: */