--- /dev/null
+/*
+ * Copyright © 2014 Broadcom
+ *
+ * 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 (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+/**
+ * @file vc4_formats.c
+ *
+ * Contains the table and accessors for VC4 texture and render target format
+ * support.
+ *
+ * The hardware has limited support for texture formats, and extremely limited
+ * support for render target formats. As a result, we emulate other formats
+ * in our shader code, and this stores the table for doing so.
+ */
+
+#include "util/u_format.h"
+#include "util/macros.h"
+
+#include "vc4_context.h"
+
+#define RT_NO 0
+#define RT_RGBA8888 1
+#define RT_RGB565 2
+
+struct vc4_format {
+ /** Set if the pipe format is defined in the table. */
+ bool present;
+
+ /** Set to 0 if unsupported, 1 if RGBA8888, 2 if rgb565. */
+ uint8_t rt_type;
+
+ /** One of VC4_TEXTURE_TYPE_*. */
+ uint8_t tex_type;
+
+ /**
+ * Swizzle to apply to the RGBA shader output for storing to the tile
+ * buffer, to the RGBA tile buffer to produce shader input (for
+ * blending), and for turning the rgba8888 texture sampler return
+ * value into shader rgba values.
+ */
+ uint8_t swizzle[4];
+};
+
+#define SWIZ(x,y,z,w) { \
+ UTIL_FORMAT_SWIZZLE_##x, \
+ UTIL_FORMAT_SWIZZLE_##y, \
+ UTIL_FORMAT_SWIZZLE_##z, \
+ UTIL_FORMAT_SWIZZLE_##w \
+}
+
+#define FORMAT(pipe, rt, tex, swiz) \
+ [PIPE_FORMAT_##pipe] = { true, RT_##rt, VC4_TEXTURE_TYPE_##tex, swiz }
+
+static const struct vc4_format vc4_format_table[] = {
+ FORMAT(R8G8B8A8_UNORM, RGBA8888, RGBA8888, SWIZ(X, Y, Z, W)),
+ FORMAT(R8G8B8X8_UNORM, RGBA8888, RGBA8888, SWIZ(X, Y, Z, 1)),
+ FORMAT(R8G8B8A8_SRGB, RGBA8888, RGBA8888, SWIZ(X, Y, Z, W)),
+ FORMAT(R8G8B8X8_SRGB, RGBA8888, RGBA8888, SWIZ(X, Y, Z, 1)),
+
+ FORMAT(B8G8R8A8_UNORM, RGBA8888, RGBA8888, SWIZ(Z, Y, X, W)),
+ FORMAT(B8G8R8X8_UNORM, RGBA8888, RGBA8888, SWIZ(Z, Y, X, 1)),
+ FORMAT(B8G8R8A8_SRGB, RGBA8888, RGBA8888, SWIZ(Z, Y, X, W)),
+ FORMAT(B8G8R8X8_SRGB, RGBA8888, RGBA8888, SWIZ(Z, Y, X, 1)),
+
+ FORMAT(B5G6R5_UNORM, RGB565, RGB565, SWIZ(X, Y, Z, 1)),
+
+ /* Depth sampling will be handled by doing nearest filtering and not
+ * unpacking the RGBA value.
+ */
+ FORMAT(Z24_UNORM_S8_UINT, NO, RGBA8888, SWIZ(X, Y, Z, W)),
+ FORMAT(Z24X8_UNORM, NO, RGBA8888, SWIZ(X, Y, Z, W)),
+
+ FORMAT(B4G4R4A4_UNORM, NO, RGBA4444, SWIZ(Y, Z, W, X)),
+ FORMAT(B4G4R4X4_UNORM, NO, RGBA4444, SWIZ(Y, Z, W, 1)),
+
+ /* It looks like 5551 in the hardware is the other way around from
+ * gallium.
+ */
+
+ FORMAT(A8_UNORM, NO, ALPHA, SWIZ(0, 0, 0, W)),
+ FORMAT(L8_UNORM, NO, ALPHA, SWIZ(W, W, W, 1)),
+ FORMAT(I8_UNORM, NO, ALPHA, SWIZ(W, W, W, W)),
+ FORMAT(R8_UNORM, NO, ALPHA, SWIZ(W, 0, 0, 1)),
+
+ FORMAT(L8A8_UNORM, NO, LUMALPHA, SWIZ(X, X, X, W)),
+ FORMAT(R8G8_UNORM, NO, LUMALPHA, SWIZ(X, W, 0, 1)),
+};
+
+static const struct vc4_format *
+get_format(enum pipe_format f)
+{
+ if (f > ARRAY_SIZE(vc4_format_table) ||
+ !vc4_format_table[f].present)
+ return NULL;
+ else
+ return &vc4_format_table[f];
+}
+
+bool
+vc4_rt_format_supported(enum pipe_format f)
+{
+ const struct vc4_format *vf = get_format(f);
+
+ if (!vf)
+ return false;
+
+ return vf->rt_type != RT_NO;
+}
+
+bool
+vc4_rt_format_is_565(enum pipe_format f)
+{
+ const struct vc4_format *vf = get_format(f);
+
+ if (!vf)
+ return false;
+
+ return vf->rt_type == RT_RGB565;
+}
+
+bool
+vc4_tex_format_supported(enum pipe_format f)
+{
+ const struct vc4_format *vf = get_format(f);
+
+ return vf != NULL;
+}
+
+uint8_t
+vc4_get_tex_format(enum pipe_format f)
+{
+ const struct vc4_format *vf = get_format(f);
+
+ if (!vf)
+ return 0;
+
+ return vf->tex_type;
+}
+
+const uint8_t *
+vc4_get_format_swizzle(enum pipe_format f)
+{
+ const struct vc4_format *vf = get_format(f);
+ static const uint8_t fallback[] = {0, 1, 2, 3};
+
+ if (!vf)
+ return fallback;
+
+ return vf->swizzle;
+}
for (int i = 0; i < 4; i++)
unpacked[i] = qir_R4_UNPACK(c, i);
+ enum pipe_format format = trans->key->tex_format[unit];
+ const uint8_t *swiz = vc4_get_format_swizzle(format);
for (int i = 0; i < 4; i++) {
if (!(tgsi_inst->Dst[0].Register.WriteMask & (1 << i)))
continue;
- enum pipe_format format = trans->key->tex_format[unit];
- const struct util_format_description *desc =
- util_format_description(format);
-
- uint8_t swiz = desc->swizzle[i];
-
update_dst(trans, tgsi_inst, i,
- get_swizzled_channel(trans, unpacked, swiz));
+ get_swizzled_channel(trans, unpacked, swiz[i]));
}
}
struct qreg t = qir_get_temp(c);
- const struct util_format_description *format_desc =
- util_format_description(trans->fs_key->color_format);
-
struct qreg src_color[4] = {
trans->outputs[0], trans->outputs[1],
trans->outputs[2], trans->outputs[3],
};
+ enum pipe_format color_format = trans->fs_key->color_format;
+ const uint8_t *format_swiz = vc4_get_format_swizzle(color_format);
+ struct qreg tlb_read_color[4] = { c->undef, c->undef, c->undef, c->undef };
struct qreg dst_color[4] = { c->undef, c->undef, c->undef, c->undef };
if (trans->fs_key->blend.blend_enable ||
trans->fs_key->blend.colormask != 0xf) {
qir_emit(c, qir_inst(QOP_TLB_COLOR_READ, c->undef,
c->undef, c->undef));
- for (int i = 0; i < 4; i++) {
- dst_color[i] = qir_R4_UNPACK(c, i);
-
- /* XXX: Swizzles? */
- }
+ for (int i = 0; i < 4; i++)
+ tlb_read_color[i] = qir_R4_UNPACK(c, i);
+ for (int i = 0; i < 4; i++)
+ dst_color[i] = get_swizzled_channel(trans,
+ tlb_read_color,
+ format_swiz[i]);
}
struct qreg blend_color[4];
struct qreg swizzled_outputs[4];
for (int i = 0; i < 4; i++) {
- swizzled_outputs[i] =
- get_swizzled_channel(trans, blend_color,
- format_desc->swizzle[i]);
+ swizzled_outputs[i] = get_swizzled_channel(trans, blend_color,
+ format_swiz[i]);
}
if (trans->fs_key->depth_enabled) {
return 0;
}
-static uint8_t
-vc4_get_texture_format(enum pipe_format format)
-{
- switch (format) {
- case PIPE_FORMAT_B8G8R8A8_UNORM:
- return 0;
- case PIPE_FORMAT_B8G8R8X8_UNORM:
- return 1;
- case PIPE_FORMAT_R8G8B8A8_UNORM:
- return 0;
- case PIPE_FORMAT_R8G8B8X8_UNORM:
- return 1;
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- return 0;
- case PIPE_FORMAT_X8R8G8B8_UNORM:
- return 1;
- case PIPE_FORMAT_A8B8G8R8_UNORM:
- return 0;
- case PIPE_FORMAT_X8B8G8R8_UNORM:
- return 1;
-/*
- case PIPE_FORMAT_R4G4B4A4_UNORM:
- return 2;
- case PIPE_FORMAT_R5G5B5A1_UNORM:
- return 3;
- case PIPE_FORMAT_R5G6B5_UNORM:
- return 4;
-*/
- case PIPE_FORMAT_L8_UNORM:
- return 5;
- case PIPE_FORMAT_A8_UNORM:
- return 6;
- case PIPE_FORMAT_L8A8_UNORM:
- return 7;
- /* XXX: ETC1 and more*/
- default:
- return ~0;
- }
-}
-
static boolean
vc4_screen_is_format_supported(struct pipe_screen *pscreen,
enum pipe_format format,
}
if ((usage & PIPE_BIND_RENDER_TARGET) &&
- (format == PIPE_FORMAT_B8G8R8A8_UNORM ||
- format == PIPE_FORMAT_B8G8R8X8_UNORM || /* XXX: really? */
- format == PIPE_FORMAT_R8G8B8A8_UNORM ||
- format == PIPE_FORMAT_R8G8B8X8_UNORM || /* XXX: really? */
- format == PIPE_FORMAT_A8B8G8R8_UNORM ||
- format == PIPE_FORMAT_X8B8G8R8_UNORM || /* XXX: really? */
- format == PIPE_FORMAT_A8R8G8B8_UNORM ||
- format == PIPE_FORMAT_X8R8G8B8_UNORM || /* XXX: really? */
- format == PIPE_FORMAT_R16G16B16A16_FLOAT)) {
+ vc4_rt_format_supported(format)) {
retval |= PIPE_BIND_RENDER_TARGET;
}
if ((usage & PIPE_BIND_SAMPLER_VIEW) &&
- (vc4_get_texture_format(format) != ~0)) {
+ (vc4_tex_format_supported(format))) {
retval |= PIPE_BIND_SAMPLER_VIEW;
}