Merge branch 'mesa_7_7_branch'
[mesa.git] / src / gallium / state_trackers / xorg / xorg_exa.c
index aa04586455f916f62893ddfa7b2ad5f0dab31b5a..c91dee73463c819d37ad6c93ee58f7183df04f1a 100644 (file)
 #include "pipe/p_format.h"
 #include "pipe/p_context.h"
 #include "pipe/p_state.h"
-#include "pipe/p_inlines.h"
 
+#include "util/u_format.h"
 #include "util/u_rect.h"
+#include "util/u_math.h"
+#include "util/u_debug.h"
 
 #define DEBUG_PRINT 0
+#define ROUND_UP_TEXTURES 1
 
 /*
  * Helper functions
@@ -149,20 +152,6 @@ exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp, int *picture_
     }
 }
 
-static void
-xorg_exa_common_done(struct exa_context *exa)
-{
-   renderer_draw_flush(exa->renderer);
-
-   exa->copy.src = NULL;
-   exa->copy.dst = NULL;
-   pipe_surface_reference(&exa->copy.src_surface, NULL);
-   pipe_surface_reference(&exa->copy.dst_surface, NULL);
-   exa->transform.has_src = FALSE;
-   exa->transform.has_mask = FALSE;
-   exa->has_solid_color = FALSE;
-   exa->num_bound_samplers = 0;
-}
 
 /*
  * Static exported EXA functions
@@ -180,6 +169,11 @@ ExaMarkSync(ScreenPtr pScreen)
    return 1;
 }
 
+
+/***********************************************************************
+ * Screen upload/download
+ */
+
 static Bool
 ExaDownloadFromScreen(PixmapPtr pPix, int x,  int y, int w,  int h, char *dst,
                      int dst_pitch)
@@ -208,7 +202,7 @@ ExaDownloadFromScreen(PixmapPtr pPix, int x,  int y, int w,  int h, char *dst,
                  x, y, w, h, dst_pitch);
 #endif
 
-    util_copy_rect((unsigned char*)dst, &priv->tex->block, dst_pitch, 0, 0,
+    util_copy_rect((unsigned char*)dst, priv->tex->format, dst_pitch, 0, 0,
                   w, h, exa->scrn->transfer_map(exa->scrn, transfer),
                   transfer->stride, 0, 0);
 
@@ -248,7 +242,7 @@ ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src,
 #endif
 
     util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
-                  &priv->tex->block, transfer->stride, 0, 0, w, h,
+                  priv->tex->format, transfer->stride, 0, 0, w, h,
                   (unsigned char*)src, src_pitch, 0, 0);
 
     exa->scrn->transfer_unmap(exa->scrn, transfer);
@@ -280,13 +274,18 @@ ExaPrepareAccess(PixmapPtr pPix, int index)
            PIPE_REFERENCED_FOR_WRITE)
            exa->pipe->flush(exa->pipe, 0, NULL);
 
+        assert(pPix->drawable.width <= priv->tex->width0);
+        assert(pPix->drawable.height <= priv->tex->height0);
+
        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]);
+                                       0, 0, 
+                                        pPix->drawable.width,
+                                        pPix->drawable.height );
        if (!priv->map_transfer)
 #ifdef EXA_MIXED_PIXMAPS
            return FALSE;
@@ -329,29 +328,9 @@ ExaFinishAccess(PixmapPtr pPix, int index)
     }
 }
 
-static void
-ExaDone(PixmapPtr pPixmap)
-{
-    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
-    modesettingPtr ms = modesettingPTR(pScrn);
-    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
-    struct exa_context *exa = ms->exa;
-
-    if (!priv)
-       return;
-
-    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);
-}
+/***********************************************************************
+ * Solid Fills
+ */
 
 static Bool
 ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
@@ -364,6 +343,9 @@ ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
 #if DEBUG_PRINT
     debug_printf("ExaPrepareSolid(0x%x)\n", fg);
 #endif
+    if (!exa->accel)
+       return FALSE;
+
     if (!exa->pipe)
        XORG_FALLBACK("accle not enabled");
 
@@ -382,7 +364,7 @@ ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
        XORG_FALLBACK("format %s", pf_name(priv->tex->format));
     }
 
-    return exa->accel && xorg_solid_bind_state(exa, priv, fg);
+    return xorg_solid_bind_state(exa, priv, fg);
 }
 
 static void
@@ -397,9 +379,34 @@ ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
     debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
 #endif
 
+    if (x0 == 0 && y0 == 0 &&
+        x1 == pPixmap->drawable.width && y1 == pPixmap->drawable.height) {
+       exa->pipe->clear(exa->pipe, PIPE_CLEAR_COLOR, exa->solid_color, 0.0, 0);
+       return;
+    }
+
     xorg_solid(exa, priv, x0, y0, x1, y1) ;
 }
 
+
+static void
+ExaDoneSolid(PixmapPtr pPixmap)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+    modesettingPtr ms = modesettingPTR(pScrn);
+    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
+    struct exa_context *exa = ms->exa;
+
+    if (!priv)
+       return;
+   
+    xorg_composite_done(exa);
+}
+
+/***********************************************************************
+ * Copy Blits
+ */
+
 static Bool
 ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
               int ydir, int alu, Pixel planeMask)
@@ -413,6 +420,10 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
 #if DEBUG_PRINT
     debug_printf("ExaPrepareCopy\n");
 #endif
+
+    if (!exa->accel)
+       return FALSE;
+
     if (!exa->pipe)
        XORG_FALLBACK("accle not enabled");
 
@@ -440,8 +451,17 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
 
     exa->copy.src = src_priv;
     exa->copy.dst = priv;
-    
-    if (exa->pipe->surface_copy) {
+
+    /* For same-surface copies, the pipe->surface_copy path is clearly
+     * superior, providing it is implemented.  In other cases it's not
+     * clear what the better path would be, and eventually we'd
+     * probably want to gather timings and choose dynamically.
+     */
+    if (exa->pipe->surface_copy &&
+        exa->copy.src == exa->copy.dst) {
+
+       exa->copy.use_surface_copy = TRUE;
+       
        exa->copy.src_surface =
           exa->scrn->get_tex_surface( exa->scrn,
                                       exa->copy.src->tex,
@@ -454,9 +474,30 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
                                       0, 0, 0, 
                                       PIPE_BUFFER_USAGE_GPU_WRITE );
     }
+    else {
+       exa->copy.use_surface_copy = FALSE;
 
+       if (exa->copy.dst == exa->copy.src)
+          exa->copy.src_texture = renderer_clone_texture( exa->renderer,
+                                                          exa->copy.src->tex );
+       else
+          pipe_texture_reference(&exa->copy.src_texture,
+                                 exa->copy.src->tex);
 
-    return exa->accel;
+       exa->copy.dst_surface =
+          exa->scrn->get_tex_surface(exa->scrn,
+                                     exa->copy.dst->tex,
+                                     0, 0, 0,
+                                     PIPE_BUFFER_USAGE_GPU_WRITE);
+
+
+       renderer_copy_prepare(exa->renderer, 
+                             exa->copy.dst_surface,
+                             exa->copy.src_texture );
+    }
+
+
+    return TRUE;
 }
 
 static void
@@ -474,8 +515,9 @@ ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
 #endif
 
    debug_assert(priv == exa->copy.dst);
+   (void) priv;
 
-   if (exa->copy.src_surface && exa->copy.dst_surface) {
+   if (exa->copy.use_surface_copy) {
       /* XXX: consider exposing >1 box in surface_copy interface.
        */
       exa->pipe->surface_copy( exa->pipe,
@@ -486,12 +528,36 @@ ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
                              width, height );
    }
    else {
-      renderer_copy_pixmap(exa->renderer, exa->copy.dst, dstX, dstY,
-                           exa->copy.src, srcX, srcY,
-                           width, height);
+      renderer_copy_pixmap(exa->renderer, 
+                           dstX, dstY,
+                           srcX, srcY,
+                           width, height,
+                           exa->copy.src_texture->width0,
+                           exa->copy.src_texture->height0);
    }
 }
 
+static void
+ExaDoneCopy(PixmapPtr pPixmap)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+    modesettingPtr ms = modesettingPTR(pScrn);
+    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
+    struct exa_context *exa = ms->exa;
+
+    if (!priv)
+       return;
+
+   renderer_draw_flush(exa->renderer);
+
+   exa->copy.src = NULL;
+   exa->copy.dst = NULL;
+   pipe_surface_reference(&exa->copy.src_surface, NULL);
+   pipe_surface_reference(&exa->copy.dst_surface, NULL);
+   pipe_texture_reference(&exa->copy.src_texture, NULL);
+}
+
+
 
 static Bool
 picture_check_formats(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture)
@@ -528,6 +594,34 @@ picture_check_formats(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture)
    return FALSE;
 }
 
+/***********************************************************************
+ * Composite entrypoints
+ */
+
+static Bool
+ExaCheckComposite(int op,
+                 PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+                 PicturePtr pDstPicture)
+{
+   ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum];
+   modesettingPtr ms = modesettingPTR(pScrn);
+   struct exa_context *exa = ms->exa;
+
+#if DEBUG_PRINT
+   debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
+                op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
+#endif
+
+   if (!exa->accel)
+       return FALSE;
+
+   return xorg_composite_accelerated(op,
+                                    pSrcPicture,
+                                    pMaskPicture,
+                                    pDstPicture);
+}
+
+
 static Bool
 ExaPrepareComposite(int op, PicturePtr pSrcPicture,
                    PicturePtr pMaskPicture, PicturePtr pDstPicture,
@@ -538,6 +632,9 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture,
    struct exa_context *exa = ms->exa;
    struct exa_pixmap_priv *priv;
 
+   if (!exa->accel)
+       return FALSE;
+
 #if DEBUG_PRINT
    debug_printf("ExaPrepareComposite(%d, src=0x%p, mask=0x%p, dst=0x%p)\n",
                 op, pSrcPicture, pMaskPicture, pDstPicture);
@@ -596,8 +693,7 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture,
                        render_format_name(pMaskPicture->format));
    }
 
-   return exa->accel &&
-          xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
+   return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
                                     pDstPicture,
                                     pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
                                     pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
@@ -624,25 +720,23 @@ ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
                   dstX, dstY, width, height);
 }
 
-static Bool
-ExaCheckComposite(int op,
-                 PicturePtr pSrcPicture, PicturePtr pMaskPicture,
-                 PicturePtr pDstPicture)
+
+
+static void
+ExaDoneComposite(PixmapPtr pPixmap)
 {
-   ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum];
+   ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
    modesettingPtr ms = modesettingPTR(pScrn);
    struct exa_context *exa = ms->exa;
-   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
-   return exa->accel && accelerated;
+
+   xorg_composite_done(exa);
 }
 
+
+/***********************************************************************
+ * Pixmaps
+ */
+
 static void *
 ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
 {
@@ -716,33 +810,22 @@ xorg_exa_set_shared_usage(PixmapPtr pPixmap)
     return 0;
 }
 
-unsigned
-xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
-{
-    ScreenPtr pScreen = pPixmap->drawable.pScreen;
-    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-    modesettingPtr ms = modesettingPTR(pScrn);
-    struct exa_pixmap_priv *priv;
-    unsigned handle;
-    unsigned stride;
 
-    if (!ms->exa) {
-       FatalError("NO MS->EXA\n");
-       return 0;
-    }
-
-    priv = exaGetPixmapDriverPrivate(pPixmap);
 
-    if (!priv) {
-       FatalError("NO PIXMAP PRIVATE\n");
-       return 0;
-    }
+static Bool
+size_match( int width, int tex_width )
+{
+#if ROUND_UP_TEXTURES
+   if (width > tex_width)
+      return FALSE;
 
-    ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle);
-    if (stride_out)
-       *stride_out = stride;
+   if (width * 2 < tex_width)
+      return FALSE;
 
-    return handle;
+   return TRUE;
+#else
+   return width == tex_width;
+#endif
 }
 
 static Bool
@@ -759,6 +842,17 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
     if (!priv || pPixData)
        return FALSE;
 
+    if (0) {
+       debug_printf("%s pixmap %p sz %dx%dx%d devKind %d\n",
+                    __FUNCTION__, pPixmap, width, height, bitsPerPixel, devKind);
+       
+       if (priv->tex)
+          debug_printf("  ==> old texture %dx%d\n",
+                       priv->tex->width0, 
+                       priv->tex->height0);
+    }
+
+
     if (depth <= 0)
        depth = pPixmap->drawable.depth;
 
@@ -777,22 +871,31 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
     miModifyPixmapHeader(pPixmap, width, height, depth,
                             bitsPerPixel, devKind, NULL);
 
+    priv->width = width;
+    priv->height = height;
+
     /* Deal with screen resize */
     if ((exa->accel || priv->flags) &&
         (!priv->tex ||
-         (priv->tex->width[0] != width ||
-          priv->tex->height[0] != height ||
-          priv->tex_flags != priv->flags))) {
+         !size_match(width, priv->tex->width0) ||
+         !size_match(height, priv->tex->height0) ||
+         priv->tex_flags != priv->flags)) {
        struct pipe_texture *texture = NULL;
        struct pipe_texture template;
 
        memset(&template, 0, sizeof(template));
        template.target = PIPE_TEXTURE_2D;
        exa_get_pipe_format(depth, &template.format, &bitsPerPixel, &priv->picture_format);
-       pf_get_block(template.format, &template.block);
-       template.width[0] = width;
-       template.height[0] = height;
-       template.depth[0] = 1;
+        if (ROUND_UP_TEXTURES && priv->flags == 0) {
+           template.width0 = util_next_power_of_two(width);
+           template.height0 = util_next_power_of_two(height);
+        }
+        else {
+           template.width0 = width;
+           template.height0 = height;
+        }
+
+       template.depth0 = 1;
        template.last_level = 0;
        template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
        priv->tex_flags = priv->flags;
@@ -805,15 +908,15 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
            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]));
-        }
+            if (exa->pipe->surface_copy) {
+               exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf,
+                                       0, 0, min(width, texture->width0),
+                                       min(height, texture->height0));
+            } else {
+               util_surface_copy(exa->pipe, FALSE, dst_surf, 0, 0, src_surf,
+                                 0, 0, min(width, texture->width0),
+                                 min(height, texture->height0));
+            }
            exa->scrn->tex_surface_destroy(dst_surf);
            exa->scrn->tex_surface_destroy(src_surf);
        }
@@ -845,8 +948,8 @@ xorg_exa_set_texture(PixmapPtr pPixmap, struct  pipe_texture *tex)
     if (!priv)
        return FALSE;
 
-    if (pPixmap->drawable.width != tex->width[0] ||
-       pPixmap->drawable.height != tex->height[0])
+    if (pPixmap->drawable.width != tex->width0 ||
+       pPixmap->drawable.height != tex->height0)
        return FALSE;
 
     pipe_texture_reference(&priv->tex, tex);
@@ -868,10 +971,9 @@ xorg_exa_create_root_texture(ScrnInfoPtr pScrn,
     memset(&template, 0, sizeof(template));
     template.target = PIPE_TEXTURE_2D;
     exa_get_pipe_format(depth, &template.format, &bitsPerPixel, &dummy);
-    pf_get_block(template.format, &template.block);
-    template.width[0] = width;
-    template.height[0] = height;
-    template.depth[0] = 1;
+    template.width0 = width;
+    template.height0 = height;
+    template.depth0 = 1;
     template.last_level = 0;
     template.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
     template.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
@@ -890,6 +992,9 @@ xorg_exa_close(ScrnInfoPtr pScrn)
 
    if (exa->pipe)
       exa->pipe->destroy(exa->pipe);
+   exa->pipe = NULL;
+   /* Since this was shared be proper with the pointer */
+   ms->ctx = NULL;
 
    exaDriverFini(pScrn->pScreen);
    xfree(exa);
@@ -935,10 +1040,10 @@ xorg_exa_init(ScrnInfoPtr pScrn, Bool accel)
    pExa->MarkSync           = ExaMarkSync;
    pExa->PrepareSolid       = ExaPrepareSolid;
    pExa->Solid              = ExaSolid;
-   pExa->DoneSolid          = ExaDone;
+   pExa->DoneSolid          = ExaDoneSolid;
    pExa->PrepareCopy        = ExaPrepareCopy;
    pExa->Copy               = ExaCopy;
-   pExa->DoneCopy           = ExaDone;
+   pExa->DoneCopy           = ExaDoneCopy;
    pExa->CheckComposite     = ExaCheckComposite;
    pExa->PrepareComposite   = ExaPrepareComposite;
    pExa->Composite          = ExaComposite;