summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/freedreno
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/freedreno')
-rw-r--r--src/gallium/drivers/freedreno/a6xx/fd6_blitter.c28
-rw-r--r--src/gallium/drivers/freedreno/a6xx/fd6_format.c37
-rw-r--r--src/gallium/drivers/freedreno/a6xx/fd6_format.h3
-rw-r--r--src/gallium/drivers/freedreno/a6xx/fd6_gmem.c25
-rw-r--r--src/gallium/drivers/freedreno/a6xx/fd6_image.c4
-rw-r--r--src/gallium/drivers/freedreno/a6xx/fd6_screen.c2
-rw-r--r--src/gallium/drivers/freedreno/a6xx/fd6_texture.c8
7 files changed, 64 insertions, 43 deletions
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c
index 546661b06bf..3e14e71933d 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c
@@ -102,15 +102,6 @@ can_do_blit(const struct pipe_blit_info *info)
fail_if(util_format_is_compressed(info->src.format) &&
info->src.format != info->dst.format);
- /* hw ignores {SRC,DST}_INFO.COLOR_SWAP if {SRC,DST}_INFO.TILE_MODE
- * is set (not linear). We can kind of get around that when tiling/
- * untiling by setting both src and dst COLOR_SWAP=WZYX, but that
- * means the formats must match:
- */
- fail_if((fd_resource(info->dst.resource)->tile_mode ||
- fd_resource(info->src.resource)->tile_mode) &&
- info->dst.format != info->src.format);
-
/* src box can be inverted, which we don't support.. dst box cannot: */
fail_if((info->src.box.width < 0) || (info->src.box.height < 0));
@@ -358,8 +349,8 @@ emit_blit_texture(struct fd_ringbuffer *ring, const struct pipe_blit_info *info)
dtile = fd_resource_level_linear(info->dst.resource, info->dst.level) ?
TILE6_LINEAR : dst->tile_mode;
- sswap = fd6_pipe2swap(info->src.format);
- dswap = fd6_pipe2swap(info->dst.format);
+ sswap = stile ? WZYX : fd6_pipe2swap(info->src.format);
+ dswap = dtile ? WZYX : fd6_pipe2swap(info->dst.format);
if (util_format_is_compressed(info->src.format)) {
debug_assert(info->src.format == info->dst.format);
@@ -386,16 +377,6 @@ emit_blit_texture(struct fd_ringbuffer *ring, const struct pipe_blit_info *info)
uint32_t width = DIV_ROUND_UP(u_minify(src->base.width0, info->src.level), blockwidth) * nelements;
uint32_t height = DIV_ROUND_UP(u_minify(src->base.height0, info->src.level), blockheight);
- /* if dtile, then dswap ignored by hw, and likewise if stile then sswap
- * ignored by hw.. but in this case we have already rejected the blit
- * if src and dst formats differ, so juse use WZYX for both src and
- * dst swap mode (so we don't change component order)
- */
- if (stile || dtile) {
- debug_assert(info->src.format == info->dst.format);
- sswap = dswap = WZYX;
- }
-
OUT_PKT7(ring, CP_SET_MARKER, 1);
OUT_RING(ring, A2XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE));
@@ -582,5 +563,8 @@ fd6_tile_mode(const struct pipe_resource *tmpl)
/* basically just has to be a format we can blit, so uploads/downloads
* via linear staging buffer works:
*/
- return TILE6_3;
+ if (ok_format(tmpl->format))
+ return TILE6_3;
+
+ return TILE6_LINEAR;
}
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_format.c b/src/gallium/drivers/freedreno/a6xx/fd6_format.c
index 6a55d4e6388..dc1a54243a3 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_format.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_format.c
@@ -29,6 +29,7 @@
#include "util/u_format.h"
#include "fd6_format.h"
+#include "freedreno_resource.h"
/* Specifies the table of all the formats and their features. Also supplies
@@ -419,8 +420,8 @@ fd6_pipe2depth(enum pipe_format format)
}
}
-static inline enum a6xx_tex_swiz
-tex_swiz(unsigned swiz)
+enum a6xx_tex_swiz
+fd6_pipe2swiz(unsigned swiz)
{
switch (swiz) {
default:
@@ -434,19 +435,37 @@ tex_swiz(unsigned swiz)
}
uint32_t
-fd6_tex_swiz(enum pipe_format format, unsigned swizzle_r, unsigned swizzle_g,
+fd6_tex_swiz(struct pipe_resource *prsc, unsigned swizzle_r, unsigned swizzle_g,
unsigned swizzle_b, unsigned swizzle_a)
{
const struct util_format_description *desc =
- util_format_description(format);
+ util_format_description(prsc->format);
unsigned char swiz[4] = {
swizzle_r, swizzle_g, swizzle_b, swizzle_a,
- }, rswiz[4];
+ }, rswiz[4], *swizp;
util_format_compose_swizzles(desc->swizzle, swiz, rswiz);
- return A6XX_TEX_CONST_0_SWIZ_X(tex_swiz(rswiz[0])) |
- A6XX_TEX_CONST_0_SWIZ_Y(tex_swiz(rswiz[1])) |
- A6XX_TEX_CONST_0_SWIZ_Z(tex_swiz(rswiz[2])) |
- A6XX_TEX_CONST_0_SWIZ_W(tex_swiz(rswiz[3]));
+ if (fd_resource(prsc)->tile_mode) {
+ /* for tiled modes, we don't get SWAP, so manually apply that
+ * extra step of swizzle:
+ */
+ enum a3xx_color_swap swap = fd6_pipe2swap(prsc->format);
+ unsigned char swapswiz[][4] = {
+ [WZYX] = { 0, 1, 2, 3 },
+ [WXYZ] = { 2, 1, 0, 3 },
+ [ZYXW] = { 3, 0, 1, 2 },
+ [XYZW] = { 3, 2, 1, 0 },
+ };
+
+ util_format_compose_swizzles(swapswiz[swap], rswiz, swiz);
+ swizp = swiz;
+ } else {
+ swizp = rswiz;
+ }
+
+ return A6XX_TEX_CONST_0_SWIZ_X(fd6_pipe2swiz(swizp[0])) |
+ A6XX_TEX_CONST_0_SWIZ_Y(fd6_pipe2swiz(swizp[1])) |
+ A6XX_TEX_CONST_0_SWIZ_Z(fd6_pipe2swiz(swizp[2])) |
+ A6XX_TEX_CONST_0_SWIZ_W(fd6_pipe2swiz(swizp[3]));
}
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_format.h b/src/gallium/drivers/freedreno/a6xx/fd6_format.h
index 56166dc4505..bc188ca17a8 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_format.h
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_format.h
@@ -38,8 +38,9 @@ enum a6xx_color_fmt fd6_pipe2color(enum pipe_format format);
enum a3xx_color_swap fd6_pipe2swap(enum pipe_format format);
enum a6xx_tex_fetchsize fd6_pipe2fetchsize(enum pipe_format format);
enum a6xx_depth_format fd6_pipe2depth(enum pipe_format format);
+enum a6xx_tex_swiz fd6_pipe2swiz(unsigned swiz);
-uint32_t fd6_tex_swiz(enum pipe_format format, unsigned swizzle_r,
+uint32_t fd6_tex_swiz(struct pipe_resource *prsc, unsigned swizzle_r,
unsigned swizzle_g, unsigned swizzle_b, unsigned swizzle_a);
static inline enum a6xx_2d_ifmt
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
index 75d8025e2a6..cb5c582476f 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
@@ -64,6 +64,7 @@ emit_mrt(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb,
struct fd_resource_slice *slice = NULL;
uint32_t stride = 0;
uint32_t offset = 0;
+ uint32_t tile_mode;
if (!pfb->cbufs[i])
continue;
@@ -79,7 +80,6 @@ emit_mrt(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb,
uint32_t base = gmem ? gmem->cbuf_base[i] : 0;
slice = fd_resource_slice(rsc, psurf->u.tex.level);
format = fd6_pipe2color(pformat);
- swap = fd6_pipe2swap(pformat);
sint = util_format_is_pure_sint(pformat);
uint = util_format_is_pure_uint(pformat);
@@ -90,13 +90,20 @@ emit_mrt(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb,
psurf->u.tex.first_layer);
stride = slice->pitch * rsc->cpp * pfb->samples;
+ swap = rsc->tile_mode ? WZYX : fd6_pipe2swap(pformat);
+
+ if (rsc->tile_mode &&
+ fd_resource_level_linear(psurf->texture, psurf->u.tex.level))
+ tile_mode = TILE6_LINEAR;
+ else
+ tile_mode = rsc->tile_mode;
debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
debug_assert((offset + slice->size0) <= fd_bo_size(rsc->bo));
OUT_PKT4(ring, REG_A6XX_RB_MRT_BUF_INFO(i), 6);
OUT_RING(ring, A6XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format) |
- A6XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(rsc->tile_mode) |
+ A6XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(tile_mode) |
A6XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap));
OUT_RING(ring, A6XX_RB_MRT_PITCH(stride));
OUT_RING(ring, A6XX_RB_MRT_ARRAY_PITCH(slice->size0));
@@ -617,18 +624,20 @@ emit_blit(struct fd_batch *batch,
enum a6xx_color_fmt format = fd6_pipe2color(pfmt);
uint32_t stride = slice->pitch * rsc->cpp;
uint32_t size = slice->size0;
- enum a3xx_color_swap swap = fd6_pipe2swap(pfmt);
+ enum a3xx_color_swap swap = rsc->tile_mode ? WZYX : fd6_pipe2swap(pfmt);
enum a3xx_msaa_samples samples =
fd_msaa_samples(rsc->base.nr_samples);
+ uint32_t tile_mode;
- // TODO: tile mode
- // bool tiled;
- // tiled = rsc->tile_mode &&
- // !fd_resource_level_linear(&rsc->base, psurf->u.tex.level);
+ if (rsc->tile_mode &&
+ fd_resource_level_linear(&rsc->base, psurf->u.tex.level))
+ tile_mode = TILE6_LINEAR;
+ else
+ tile_mode = rsc->tile_mode;
OUT_PKT4(ring, REG_A6XX_RB_BLIT_DST_INFO, 5);
OUT_RING(ring,
- A6XX_RB_BLIT_DST_INFO_TILE_MODE(TILE6_LINEAR) |
+ A6XX_RB_BLIT_DST_INFO_TILE_MODE(tile_mode) |
A6XX_RB_BLIT_DST_INFO_SAMPLES(samples) |
A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(format) |
A6XX_RB_BLIT_DST_INFO_COLOR_SWAP(swap));
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_image.c b/src/gallium/drivers/freedreno/a6xx/fd6_image.c
index e79ee2f90ad..f7419d8d9ac 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_image.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_image.c
@@ -43,6 +43,7 @@ static enum a6xx_state_block imgsb[] = {
};
struct fd6_image {
+ struct pipe_resource *prsc;
enum pipe_format pfmt;
enum a6xx_tex_fmt fmt;
enum a6xx_tex_fetchsize fetchsize;
@@ -70,6 +71,7 @@ static void translate_image(struct fd6_image *img, struct pipe_image_view *pimg)
return;
}
+ img->prsc = prsc;
img->pfmt = format;
img->fmt = fd6_pipe2tex(format);
img->fetchsize = fd6_pipe2fetchsize(format);
@@ -112,7 +114,7 @@ static void emit_image_tex(struct fd_ringbuffer *ring, unsigned slot,
OUT_RING(ring, CP_LOAD_STATE6_2_EXT_SRC_ADDR_HI(0));
OUT_RING(ring, A6XX_TEX_CONST_0_FMT(img->fmt) |
- fd6_tex_swiz(img->pfmt, PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y,
+ fd6_tex_swiz(img->prsc, PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y,
PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W) |
COND(img->srgb, A6XX_TEX_CONST_0_SRGB));
OUT_RING(ring, A6XX_TEX_CONST_1_WIDTH(img->width) |
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_screen.c b/src/gallium/drivers/freedreno/a6xx/fd6_screen.c
index 910a71ccc96..be92d4a877b 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_screen.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_screen.c
@@ -29,6 +29,7 @@
#include "util/u_format.h"
#include "fd6_screen.h"
+#include "fd6_blitter.h"
#include "fd6_context.h"
#include "fd6_format.h"
#include "fd6_resource.h"
@@ -134,4 +135,5 @@ fd6_screen_init(struct pipe_screen *pscreen)
pscreen->is_format_supported = fd6_screen_is_format_supported;
screen->setup_slices = fd6_setup_slices;
+ screen->tile_mode = fd6_tile_mode;
}
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_texture.c b/src/gallium/drivers/freedreno/a6xx/fd6_texture.c
index e516e94b0d9..af5f49fd3f2 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_texture.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_texture.c
@@ -246,7 +246,7 @@ fd6_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
so->texconst0 =
A6XX_TEX_CONST_0_FMT(fd6_pipe2tex(format)) |
A6XX_TEX_CONST_0_SAMPLES(fd_msaa_samples(prsc->nr_samples)) |
- fd6_tex_swiz(format, cso->swizzle_r, cso->swizzle_g,
+ fd6_tex_swiz(prsc, cso->swizzle_r, cso->swizzle_g,
cso->swizzle_b, cso->swizzle_a);
/* NOTE: since we sample z24s8 using 8888_UINT format, the swizzle
@@ -257,8 +257,12 @@ fd6_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
* Note that gallium expects stencil sampler to return (s,s,s,s)
* which isn't quite true. To make that happen we'd have to massage
* the swizzle. But in practice only the .x component is used.
+ *
+ * Skip this in the tile case because tiled formats are not swapped
+ * and we have already applied the inverse swap in fd6_tex_swiz()
+ * to componsate for that.
*/
- if (format == PIPE_FORMAT_X24S8_UINT) {
+ if ((format == PIPE_FORMAT_X24S8_UINT) && !rsc->tile_mode) {
so->texconst0 |= A6XX_TEX_CONST_0_SWAP(XYZW);
}