summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2012-06-27 14:48:47 +0200
committerMichel Dänzer <michel@daenzer.net>2012-07-05 19:58:39 +0200
commit9eac8021f3d33a63156f9f5d43a220e88bb3f8db (patch)
treef7061124c079b8c48c8832278b33d97bdde39899 /src
parent060c7836e7f7777bacca4e23f57c5985beab33bc (diff)
EXA: Factor out pixmap BO allocation into a helper function.
Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am4
-rw-r--r--src/radeon.h20
-rw-r--r--src/radeon_bo_helper.c177
-rw-r--r--src/radeon_bo_helper.h31
-rw-r--r--src/radeon_exa.c160
5 files changed, 237 insertions, 155 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 5c095546..e857f21a 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 742a6f85..d357dc13 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 00000000..ccdf7ebe
--- /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 00000000..0f6fffbd
--- /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 99dc453b..d80c7e4f 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;
}