From: Michel Dänzer <michel.daen...@amd.com>

Signed-off-by: Michel Dänzer <michel.daen...@amd.com>
---
 src/Makefile.am        |    4 +-
 src/radeon.h           |   20 ++++++
 src/radeon_bo_helper.c |  177 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/radeon_bo_helper.h |   31 +++++++++
 src/radeon_exa.c       |  160 ++-----------------------------------------
 5 files changed, 237 insertions(+), 155 deletions(-)
 create mode 100644 src/radeon_bo_helper.c
 create mode 100644 src/radeon_bo_helper.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 5c09554..e857f21 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,7 +28,8 @@
 
 radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS)
 
-RADEON_KMS_SRCS=radeon_dri2.c radeon_kms.c drmmode_display.c radeon_vbo.c
+RADEON_KMS_SRCS=radeon_dri2.c radeon_kms.c drmmode_display.c radeon_vbo.c \
+       radeon_bo_helper.c
 
 RADEON_EXA_SOURCES = radeon_exa.c r600_exa.c r6xx_accel.c 
r600_textured_videofuncs.c r600_shader.c radeon_exa_shared.c \
        evergreen_exa.c evergreen_accel.c evergreen_shader.c 
evergreen_textured_videofuncs.c cayman_accel.c cayman_shader.c
@@ -82,6 +83,7 @@ EXTRA_DIST = \
        ati.h \
        ativersion.h \
        bicubic_table.h \
+       radeon_bo_helper.h \
        radeon_drm.h \
        radeon_exa_render.c \
        radeon_exa_funcs.c \
diff --git a/src/radeon.h b/src/radeon.h
index 742a6f8..d357dc1 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -665,4 +665,24 @@ enum {
     RADEON_CREATE_PIXMAP_SZBUFFER = 0x80000000, /* for eg */
 };
 
+
+/* Compute log base 2 of val. */
+static __inline__ int
+RADEONLog2(int val)
+{
+       int bits;
+#if (defined __i386__ || defined __x86_64__) && (defined __GNUC__)
+       __asm volatile("bsrl    %1, %0"
+               : "=r" (bits)
+               : "c" (val)
+       );
+       return bits;
+#else
+       for (bits = 0; val != 0; val >>= 1, ++bits)
+               ;
+       return bits - 1;
+#endif
+}
+
+
 #endif /* _RADEON_H_ */
diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c
new file mode 100644
index 0000000..ccdf7eb
--- /dev/null
+++ b/src/radeon_bo_helper.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2012  Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "radeon.h"
+
+
+static const unsigned MicroBlockTable[5][3][2] = {
+    /*linear  tiled   square-tiled */
+    {{32, 1}, {8, 4}, {0, 0}}, /*   8 bits per pixel */
+    {{16, 1}, {8, 2}, {4, 4}}, /*  16 bits per pixel */
+    {{ 8, 1}, {4, 2}, {0, 0}}, /*  32 bits per pixel */
+    {{ 4, 1}, {0, 0}, {2, 2}}, /*  64 bits per pixel */
+    {{ 2, 1}, {0, 0}, {0, 0}}  /* 128 bits per pixel */
+};
+
+/* Return true if macrotiling can be enabled */
+static Bool RADEONMacroSwitch(int width, int height, int bpp,
+                              uint32_t flags, Bool rv350_mode)
+{
+    unsigned tilew, tileh, microtiled, logbpp;
+
+    logbpp = RADEONLog2(bpp / 8);
+    if (logbpp > 4)
+        return 0;
+
+    microtiled = !!(flags & RADEON_TILING_MICRO);
+    tilew = MicroBlockTable[logbpp][microtiled][0] * 8;
+    tileh = MicroBlockTable[logbpp][microtiled][1] * 8;
+
+    /* See TX_FILTER1_n.MACRO_SWITCH. */
+    if (rv350_mode) {
+        return width >= tilew && height >= tileh;
+    } else {
+        return width > tilew && height > tileh;
+    }
+}
+
+/* Calculate appropriate tiling and pitch for a pixmap and allocate a BO that
+ * can hold it.
+ */
+struct radeon_bo*
+radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
+                      int usage_hint, int bitsPerPixel, int *new_pitch,
+                      struct radeon_surface *new_surface, uint32_t *new_tiling)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    int pitch, base_align;
+    uint32_t size, heighta;
+    int cpp = bitsPerPixel / 8;
+    uint32_t tiling = 0;
+    struct radeon_surface surface;
+    struct radeon_bo *bo;
+
+    if (usage_hint) {
+       if (info->allowColorTiling) {
+           if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO)
+               tiling |= RADEON_TILING_MACRO;
+           if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO)
+                tiling |= RADEON_TILING_MICRO;
+       }
+       if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH)
+               tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO;
+
+    }
+
+    /* Small pixmaps must not be macrotiled on R300, hw cannot sample them
+     * correctly because samplers automatically switch to macrolinear. */
+    if (info->ChipFamily >= CHIP_FAMILY_R300 &&
+        info->ChipFamily <= CHIP_FAMILY_RS740 &&
+        (tiling & RADEON_TILING_MACRO) &&
+        !RADEONMacroSwitch(width, height, bitsPerPixel, tiling,
+                           info->ChipFamily >= CHIP_FAMILY_RV350)) {
+        tiling &= ~RADEON_TILING_MACRO;
+    }
+
+    heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling));
+    pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * 
cpp;
+    base_align = drmmode_get_base_align(pScrn, cpp, tiling);
+    size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE);
+    memset(&surface, 0, sizeof(struct radeon_surface));
+
+    if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
+               if (width) {
+                       surface.npix_x = width;
+                       /* need to align height to 8 for old kernel */
+                       surface.npix_y = RADEON_ALIGN(height, 8);
+                       surface.npix_z = 1;
+                       surface.blk_w = 1;
+                       surface.blk_h = 1;
+                       surface.blk_d = 1;
+                       surface.array_size = 1;
+                       surface.last_level = 0;
+                       surface.bpe = cpp;
+                       surface.nsamples = 1;
+                       if (height < 64) {
+                               /* disable 2d tiling for small surface to work 
around
+                                * the fact that ddx align height to 8 pixel 
for old
+                                * obscure reason i can't remember
+                                */
+                               tiling &= ~RADEON_TILING_MACRO;
+                       }
+                       surface.flags = RADEON_SURF_SCANOUT;
+                       surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, 
TYPE);
+                       surface.flags |= 
RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
+                       if ((tiling & RADEON_TILING_MICRO)) {
+                               surface.flags = RADEON_SURF_CLR(surface.flags, 
MODE);
+                               surface.flags |= 
RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
+                       }
+                       if ((tiling & RADEON_TILING_MACRO)) {
+                               surface.flags = RADEON_SURF_CLR(surface.flags, 
MODE);
+                               surface.flags |= 
RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
+                       }
+                       if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) {
+                               surface.flags |= RADEON_SURF_ZBUFFER;
+                               surface.flags |= RADEON_SURF_SBUFFER;
+                       }
+                       if (radeon_surface_best(info->surf_man, &surface)) {
+                               return NULL;
+                       }
+                       if (radeon_surface_init(info->surf_man, &surface)) {
+                               return NULL;
+                       }
+                       size = surface.bo_size;
+                       base_align = surface.bo_alignment;
+                       pitch = surface.level[0].pitch_bytes;
+                       tiling = 0;
+                       switch (surface.level[0].mode) {
+                       case RADEON_SURF_MODE_2D:
+                               tiling |= RADEON_TILING_MACRO;
+                               tiling |= surface.bankw << 
RADEON_TILING_EG_BANKW_SHIFT;
+                               tiling |= surface.bankh << 
RADEON_TILING_EG_BANKH_SHIFT;
+                               tiling |= surface.mtilea << 
RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
+                               tiling |= eg_tile_split(surface.tile_split) << 
RADEON_TILING_EG_TILE_SPLIT_SHIFT;
+                               tiling |= 
eg_tile_split(surface.stencil_tile_split) << 
RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT;
+                               break;
+                       case RADEON_SURF_MODE_1D:
+                               tiling |= RADEON_TILING_MICRO;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+
+    bo = radeon_bo_open(info->bufmgr, 0, size, base_align,
+                       RADEON_GEM_DOMAIN_VRAM, 0);
+
+    if (bo && tiling && radeon_bo_set_tiling(bo, tiling, pitch) == 0)
+       *new_tiling = tiling;
+
+    *new_surface = surface;
+    *new_pitch = pitch;
+    return bo;
+}
diff --git a/src/radeon_bo_helper.h b/src/radeon_bo_helper.h
new file mode 100644
index 0000000..0f6fffb
--- /dev/null
+++ b/src/radeon_bo_helper.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2012  Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef RADEON_BO_HELPER_H
+#define RADEON_BO_HELPER_H 1
+
+extern struct radeon_bo*
+radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
+                      int usage_hint, int bitsPerPixel, int *new_pitch,
+                      struct radeon_surface *new_surface, uint32_t 
*new_tiling);
+
+#endif /* RADEON_BO_HELPER_H */
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 99dc453..d80c7e4 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -37,6 +37,7 @@
 #include "radeon_reg.h"
 #include "r600_reg.h"
 #include "radeon_drm.h"
+#include "radeon_bo_helper.h"
 #include "radeon_probe.h"
 #include "radeon_version.h"
 #include "radeon_exa_shared.h"
@@ -70,24 +71,6 @@ static struct {
     { RADEON_ROP3_ONE,  RADEON_ROP3_ONE  }  /* GXset          */
 };
 
-/* Compute log base 2 of val. */
-static __inline__ int
-RADEONLog2(int val)
-{
-       int bits;
-#if (defined __i386__ || defined __x86_64__) && (defined __GNUC__)
-       __asm volatile("bsrl    %1, %0"
-               : "=r" (bits)
-               : "c" (val)
-       );
-       return bits;
-#else
-       for (bits = 0; val != 0; val >>= 1, ++bits)
-               ;
-       return bits - 1;
-#endif
-}
-
 static __inline__ uint32_t F_TO_DW(float val)
 {
     union {
@@ -292,37 +275,6 @@ void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, 
int align)
 
 }
 
-static const unsigned MicroBlockTable[5][3][2] = {
-    /*linear  tiled   square-tiled */
-    {{32, 1}, {8, 4}, {0, 0}}, /*   8 bits per pixel */
-    {{16, 1}, {8, 2}, {4, 4}}, /*  16 bits per pixel */
-    {{ 8, 1}, {4, 2}, {0, 0}}, /*  32 bits per pixel */
-    {{ 4, 1}, {0, 0}, {2, 2}}, /*  64 bits per pixel */
-    {{ 2, 1}, {0, 0}, {0, 0}}  /* 128 bits per pixel */
-};
-
-/* Return true if macrotiling can be enabled */
-static Bool RADEONMacroSwitch(int width, int height, int bpp,
-                              uint32_t flags, Bool rv350_mode)
-{
-    unsigned tilew, tileh, microtiled, logbpp;
-
-    logbpp = RADEONLog2(bpp / 8);
-    if (logbpp > 4)
-        return 0;
-
-    microtiled = !!(flags & RADEON_TILING_MICRO);
-    tilew = MicroBlockTable[logbpp][microtiled][0] * 8;
-    tileh = MicroBlockTable[logbpp][microtiled][1] * 8;
-
-    /* See TX_FILTER1_n.MACRO_SWITCH. */
-    if (rv350_mode) {
-        return width >= tilew && height >= tileh;
-    } else {
-        return width > tilew && height > tileh;
-    }
-}
-
 void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
                             int depth, int usage_hint, int bitsPerPixel,
                             int *new_pitch)
@@ -330,11 +282,6 @@ void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, 
int height,
     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
     RADEONInfoPtr info = RADEONPTR(pScrn);
     struct radeon_exa_pixmap_priv *new_priv;
-    int pitch, base_align;
-    uint32_t size, heighta;
-    uint32_t tiling = 0;
-    int cpp = bitsPerPixel / 8;
-    struct radeon_surface surface;
 
 #ifdef EXA_MIXED_PIXMAPS
     if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) {
@@ -344,120 +291,25 @@ void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int 
width, int height,
     }
 #endif
 
-    if (usage_hint) {
-       if (info->allowColorTiling) {
-           if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO)
-               tiling |= RADEON_TILING_MACRO;
-           if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO)
-                tiling |= RADEON_TILING_MICRO;
-       }
-       if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH)
-               tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO;
-               
-    }
-
-    /* Small pixmaps must not be macrotiled on R300, hw cannot sample them
-     * correctly because samplers automatically switch to macrolinear. */
-    if (info->ChipFamily >= CHIP_FAMILY_R300 &&
-        info->ChipFamily <= CHIP_FAMILY_RS740 &&
-        (tiling & RADEON_TILING_MACRO) &&
-        !RADEONMacroSwitch(width, height, bitsPerPixel, tiling,
-                           info->ChipFamily >= CHIP_FAMILY_RV350)) {
-        tiling &= ~RADEON_TILING_MACRO;
-    }
-
-    heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling));
-    pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * 
cpp;
-    base_align = drmmode_get_base_align(pScrn, cpp, tiling);
-    size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE);
-    memset(&surface, 0, sizeof(struct radeon_surface));
-
-    if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
-               if (width) {
-                       surface.npix_x = width;
-                       /* need to align height to 8 for old kernel */
-                       surface.npix_y = RADEON_ALIGN(height, 8);
-                       surface.npix_z = 1;
-                       surface.blk_w = 1;
-                       surface.blk_h = 1;
-                       surface.blk_d = 1;
-                       surface.array_size = 1;
-                       surface.last_level = 0;
-                       surface.bpe = cpp;
-                       surface.nsamples = 1;
-                       if (height < 64) {
-                               /* disable 2d tiling for small surface to work 
around
-                                * the fact that ddx align height to 8 pixel 
for old
-                                * obscure reason i can't remember
-                                */
-                               tiling &= ~RADEON_TILING_MACRO;
-                       }
-                       surface.flags = RADEON_SURF_SCANOUT;
-                       surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, 
TYPE);
-                       surface.flags |= 
RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
-                       if ((tiling & RADEON_TILING_MICRO)) {
-                               surface.flags = RADEON_SURF_CLR(surface.flags, 
MODE);
-                               surface.flags |= 
RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
-                       }
-                       if ((tiling & RADEON_TILING_MACRO)) {
-                               surface.flags = RADEON_SURF_CLR(surface.flags, 
MODE);
-                               surface.flags |= 
RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
-                       }
-                       if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) {
-                               surface.flags |= RADEON_SURF_ZBUFFER;
-                               surface.flags |= RADEON_SURF_SBUFFER;
-                       }
-                       if (radeon_surface_best(info->surf_man, &surface)) {
-                               return NULL;
-                       }
-                       if (radeon_surface_init(info->surf_man, &surface)) {
-                               return NULL;
-                       }
-                       size = surface.bo_size;
-                       base_align = surface.bo_alignment;
-                       pitch = surface.level[0].pitch_bytes;
-                       tiling = 0;
-                       switch (surface.level[0].mode) {
-                       case RADEON_SURF_MODE_2D:
-                               tiling |= RADEON_TILING_MACRO;
-                               tiling |= surface.bankw << 
RADEON_TILING_EG_BANKW_SHIFT;
-                               tiling |= surface.bankh << 
RADEON_TILING_EG_BANKH_SHIFT;
-                               tiling |= surface.mtilea << 
RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
-                               tiling |= eg_tile_split(surface.tile_split) << 
RADEON_TILING_EG_TILE_SPLIT_SHIFT;
-                               tiling |= 
eg_tile_split(surface.stencil_tile_split) << 
RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT;
-                               break;
-                       case RADEON_SURF_MODE_1D:
-                               tiling |= RADEON_TILING_MICRO;
-                               break;
-                       default:
-                               break;
-                       }
-               }
-       }
-
     new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv));
     if (!new_priv) {
        return NULL;
     }
 
-    if (size == 0) {
+    if (width == 0 || height == 0) {
        return new_priv;
     }
 
-    *new_pitch = pitch;
-
-    new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, base_align,
-                                 RADEON_GEM_DOMAIN_VRAM, 0);
+    new_priv->bo = radeon_alloc_pixmap_bo(pScrn, width, height, depth,
+                                         usage_hint, bitsPerPixel, new_pitch,
+                                         &new_priv->surface,
+                                         &new_priv->tiling_flags);
     if (!new_priv->bo) {
        free(new_priv);
        ErrorF("Failed to alloc memory\n");
        return NULL;
     }
 
-    if (tiling && !radeon_bo_set_tiling(new_priv->bo, tiling, *new_pitch))
-       new_priv->tiling_flags = tiling;
-
-    new_priv->surface = surface;
     return new_priv;
 }
 
-- 
1.7.10.4


_______________________________________________
xorg-driver-ati mailing list
xorg-driver-ati@lists.x.org
http://lists.x.org/mailman/listinfo/xorg-driver-ati

Reply via email to