+/* Return true for non-compressed and non-YUV formats. */
+static boolean r300_format_is_plain(enum pipe_format format)
+{
+ const struct util_format_description *desc = util_format_description(format);
+
+ if (!format) {
+ return FALSE;
+ }
+
+ return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN;
+}
+
+/* Translate a pipe_format into a useful texture format for sampling.
+ *
+ * Some special formats are translated directly using R300_EASY_TX_FORMAT,
+ * but the majority of them is translated in a generic way, automatically
+ * supporting all the formats hw can support.
+ *
+ * R300_EASY_TX_FORMAT swizzles the texture.
+ * Note the signature of R300_EASY_TX_FORMAT:
+ * R300_EASY_TX_FORMAT(B, G, R, A, FORMAT);
+ *
+ * The FORMAT specifies how the texture sampler will treat the texture, and
+ * makes available X, Y, Z, W, ZERO, and ONE for swizzling. */
+static uint32_t r300_translate_texformat(enum pipe_format format)
+{
+ uint32_t result = 0;
+ const struct util_format_description *desc;
+ unsigned i;
+ boolean uniform = TRUE;
+ const uint32_t swizzle_shift[4] = {
+ R300_TX_FORMAT_R_SHIFT,
+ R300_TX_FORMAT_G_SHIFT,
+ R300_TX_FORMAT_B_SHIFT,
+ R300_TX_FORMAT_A_SHIFT
+ };
+ const uint32_t swizzle[4] = {
+ R300_TX_FORMAT_X,
+ R300_TX_FORMAT_Y,
+ R300_TX_FORMAT_Z,
+ R300_TX_FORMAT_W
+ };
+ const uint32_t sign_bit[4] = {
+ R300_TX_FORMAT_SIGNED_X,
+ R300_TX_FORMAT_SIGNED_Y,
+ R300_TX_FORMAT_SIGNED_Z,
+ R300_TX_FORMAT_SIGNED_W,
+ };
+
+ desc = util_format_description(format);
+
+ /* Colorspace (return non-RGB formats directly). */
+ switch (desc->colorspace) {
+ /* Depth stencil formats. */
+ case UTIL_FORMAT_COLORSPACE_ZS:
+ switch (format) {
+ case PIPE_FORMAT_Z16_UNORM:
+ return R300_EASY_TX_FORMAT(X, X, X, X, X16);
+ case PIPE_FORMAT_X8Z24_UNORM:
+ case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+ return R300_EASY_TX_FORMAT(X, X, X, X, W24_FP);
+ default:
+ return ~0; /* Unsupported. */
+ }
+
+ /* YUV formats. */
+ case UTIL_FORMAT_COLORSPACE_YUV:
+ result |= R300_TX_FORMAT_YUV_TO_RGB;
+
+ switch (format) {
+ case PIPE_FORMAT_UYVY:
+ return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) | result;
+ case PIPE_FORMAT_YUYV:
+ return R300_EASY_TX_FORMAT(X, Y, Z, ONE, VYUY422) | result;
+ default:
+ return ~0; /* Unsupported/unknown. */
+ }
+
+ /* Add gamma correction. */
+ case UTIL_FORMAT_COLORSPACE_SRGB:
+ result |= R300_TX_FORMAT_GAMMA;
+ break;
+
+ default:;
+ }
+
+ /* Add swizzle. */
+ for (i = 0; i < 4; i++) {
+ switch (desc->swizzle[i]) {
+ case UTIL_FORMAT_SWIZZLE_X:
+ case UTIL_FORMAT_SWIZZLE_NONE:
+ result |= swizzle[0] << swizzle_shift[i];
+ break;
+ case UTIL_FORMAT_SWIZZLE_Y:
+ result |= swizzle[1] << swizzle_shift[i];
+ break;
+ case UTIL_FORMAT_SWIZZLE_Z:
+ result |= swizzle[2] << swizzle_shift[i];
+ break;
+ case UTIL_FORMAT_SWIZZLE_W:
+ result |= swizzle[3] << swizzle_shift[i];
+ break;
+ case UTIL_FORMAT_SWIZZLE_0:
+ result |= R300_TX_FORMAT_ZERO << swizzle_shift[i];
+ break;
+ case UTIL_FORMAT_SWIZZLE_1:
+ result |= R300_TX_FORMAT_ONE << swizzle_shift[i];
+ break;
+ default:
+ return ~0; /* Unsupported. */
+ }
+ }
+
+ /* S3TC formats. */
+ if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
+ switch (format) {
+ case PIPE_FORMAT_DXT1_RGB:
+ case PIPE_FORMAT_DXT1_RGBA:
+ case PIPE_FORMAT_DXT1_SRGB:
+ case PIPE_FORMAT_DXT1_SRGBA:
+ return R300_TX_FORMAT_DXT1 | result;
+ case PIPE_FORMAT_DXT3_RGBA:
+ case PIPE_FORMAT_DXT3_SRGBA:
+ return R300_TX_FORMAT_DXT3 | result;
+ case PIPE_FORMAT_DXT5_RGBA:
+ case PIPE_FORMAT_DXT5_SRGBA:
+ return R300_TX_FORMAT_DXT5 | result;
+ default:
+ return ~0; /* Unsupported/unknown. */
+ }
+ }
+
+ /* Add sign. */
+ for (i = 0; i < desc->nr_channels; i++) {
+ if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {
+ result |= sign_bit[i];
+ }
+ }
+
+ /* RGTC formats. */
+ if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) {
+ switch (format) {
+ case PIPE_FORMAT_RGTC1_UNORM:
+ case PIPE_FORMAT_RGTC1_SNORM:
+ return R500_TX_FORMAT_ATI1N | result;
+ case PIPE_FORMAT_RGTC2_UNORM:
+ case PIPE_FORMAT_RGTC2_SNORM:
+ return R400_TX_FORMAT_ATI2N | result;
+ default:
+ return ~0; /* Unsupported/unknown. */
+ }
+ }
+
+ /* See whether the components are of the same size. */
+ for (i = 1; i < desc->nr_channels; i++) {
+ uniform = uniform && desc->channel[0].size == desc->channel[i].size;
+ }
+
+ /* Non-uniform formats. */
+ if (!uniform) {
+ switch (desc->nr_channels) {
+ case 3:
+ if (desc->channel[0].size == 5 &&
+ desc->channel[1].size == 6 &&
+ desc->channel[2].size == 5) {
+ return R300_TX_FORMAT_Z5Y6X5 | result;
+ }
+ if (desc->channel[0].size == 5 &&
+ desc->channel[1].size == 5 &&
+ desc->channel[2].size == 6) {
+ return R300_TX_FORMAT_Z6Y5X5 | result;
+ }
+ return ~0; /* Unsupported/unknown. */
+
+ case 4:
+ if (desc->channel[0].size == 5 &&
+ desc->channel[1].size == 5 &&
+ desc->channel[2].size == 5 &&
+ desc->channel[3].size == 1) {
+ return R300_TX_FORMAT_W1Z5Y5X5 | result;
+ }
+ if (desc->channel[0].size == 10 &&
+ desc->channel[1].size == 10 &&
+ desc->channel[2].size == 10 &&
+ desc->channel[3].size == 2) {
+ return R300_TX_FORMAT_W2Z10Y10X10 | result;
+ }
+ }
+ return ~0; /* Unsupported/unknown. */
+ }
+
+ /* And finally, uniform formats. */
+ switch (desc->channel[0].type) {
+ case UTIL_FORMAT_TYPE_UNSIGNED:
+ case UTIL_FORMAT_TYPE_SIGNED:
+ if (!desc->channel[0].normalized &&
+ desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) {
+ return ~0;
+ }
+
+ switch (desc->channel[0].size) {
+ case 4:
+ switch (desc->nr_channels) {
+ case 2:
+ return R300_TX_FORMAT_Y4X4 | result;
+ case 4:
+ return R300_TX_FORMAT_W4Z4Y4X4 | result;
+ }
+ return ~0;
+
+ case 8:
+ switch (desc->nr_channels) {
+ case 1:
+ return R300_TX_FORMAT_X8 | result;
+ case 2:
+ return R300_TX_FORMAT_Y8X8 | result;
+ case 4:
+ return R300_TX_FORMAT_W8Z8Y8X8 | result;
+ }
+ return ~0;
+
+ case 16:
+ switch (desc->nr_channels) {
+ case 1:
+ return R300_TX_FORMAT_X16 | result;
+ case 2:
+ return R300_TX_FORMAT_Y16X16 | result;
+ case 4:
+ return R300_TX_FORMAT_W16Z16Y16X16 | result;
+ }
+ }
+ return ~0;
+
+#if defined(ENABLE_FLOAT_TEXTURES)
+ case UTIL_FORMAT_TYPE_FLOAT:
+ switch (desc->channel[0].size) {
+ case 16:
+ switch (desc->nr_channels) {
+ case 1:
+ return R300_TX_FORMAT_16F | result;
+ case 2:
+ return R300_TX_FORMAT_16F_16F | result;
+ case 4:
+ return R300_TX_FORMAT_16F_16F_16F_16F | result;
+ }
+ return ~0;
+
+ case 32:
+ switch (desc->nr_channels) {
+ case 1:
+ return R300_TX_FORMAT_32F | result;
+ case 2:
+ return R300_TX_FORMAT_32F_32F | result;
+ case 4:
+ return R300_TX_FORMAT_32F_32F_32F_32F | result;
+ }
+ }
+#endif
+ }
+
+ return ~0; /* Unsupported/unknown. */
+}
+
+static uint32_t r500_tx_format_msb_bit(enum pipe_format format)
+{
+ switch (format) {
+ case PIPE_FORMAT_RGTC1_UNORM:
+ case PIPE_FORMAT_RGTC1_SNORM:
+ return R500_TXFORMAT_MSB;
+ default:
+ return 0;
+ }
+}
+
+/* Buffer formats. */
+
+/* Colorbuffer formats. This is the unswizzled format of the RB3D block's
+ * output. For the swizzling of the targets, check the shader's format. */
+static uint32_t r300_translate_colorformat(enum pipe_format format)
+{
+ switch (format) {
+ /* 8-bit buffers. */
+ case PIPE_FORMAT_A8_UNORM:
+ case PIPE_FORMAT_I8_UNORM:
+ case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_R8_UNORM:
+ case PIPE_FORMAT_R8_SNORM:
+ return R300_COLOR_FORMAT_I8;
+
+ /* 16-bit buffers. */
+ case PIPE_FORMAT_B5G6R5_UNORM:
+ return R300_COLOR_FORMAT_RGB565;
+ case PIPE_FORMAT_B5G5R5A1_UNORM:
+ case PIPE_FORMAT_B5G5R5X1_UNORM:
+ return R300_COLOR_FORMAT_ARGB1555;
+ case PIPE_FORMAT_B4G4R4A4_UNORM:
+ return R300_COLOR_FORMAT_ARGB4444;
+
+ /* 32-bit buffers. */
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ case PIPE_FORMAT_A8B8G8R8_UNORM:
+ case PIPE_FORMAT_R8G8B8A8_SNORM:
+ case PIPE_FORMAT_X8B8G8R8_UNORM:
+ case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
+ return R300_COLOR_FORMAT_ARGB8888;
+ case PIPE_FORMAT_R10G10B10A2_UNORM:
+ return R500_COLOR_FORMAT_ARGB2101010; /* R5xx-only? */
+
+ /* 64-bit buffers. */
+ case PIPE_FORMAT_R16G16B16A16_UNORM:
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+#if defined(ENABLE_FLOAT_TEXTURES)
+ case PIPE_FORMAT_R16G16B16A16_FLOAT:
+#endif
+ return R300_COLOR_FORMAT_ARGB16161616;
+
+ /* 128-bit buffers. */
+#if defined(ENABLE_FLOAT_TEXTURES)
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ return R300_COLOR_FORMAT_ARGB32323232;
+#endif
+
+ /* YUV buffers. */
+ case PIPE_FORMAT_UYVY:
+ return R300_COLOR_FORMAT_YVYU;
+ case PIPE_FORMAT_YUYV:
+ return R300_COLOR_FORMAT_VYUY;
+ default:
+ return ~0; /* Unsupported. */
+ }
+}
+
+/* Depthbuffer and stencilbuffer. Thankfully, we only support two flavors. */
+static uint32_t r300_translate_zsformat(enum pipe_format format)
+{
+ switch (format) {
+ /* 16-bit depth, no stencil */
+ case PIPE_FORMAT_Z16_UNORM:
+ return R300_DEPTHFORMAT_16BIT_INT_Z;
+ /* 24-bit depth, ignored stencil */
+ case PIPE_FORMAT_X8Z24_UNORM:
+ /* 24-bit depth, 8-bit stencil */
+ case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+ return R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;
+ default:
+ return ~0; /* Unsupported. */
+ }
+}
+
+/* Shader output formats. This is essentially the swizzle from the shader
+ * to the RB3D block.
+ *
+ * Note that formats are stored from C3 to C0. */
+static uint32_t r300_translate_out_fmt(enum pipe_format format)
+{
+ uint32_t modifier = 0;
+ unsigned i;
+ const struct util_format_description *desc;
+ static const uint32_t sign_bit[4] = {
+ R300_OUT_SIGN(0x1),
+ R300_OUT_SIGN(0x2),
+ R300_OUT_SIGN(0x4),
+ R300_OUT_SIGN(0x8),
+ };
+
+ desc = util_format_description(format);
+
+ /* Specifies how the shader output is written to the fog unit. */
+ if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) {
+ if (desc->channel[0].size == 32) {
+ modifier |= R300_US_OUT_FMT_C4_32_FP;
+ } else {
+ modifier |= R300_US_OUT_FMT_C4_16_FP;
+ }
+ } else {
+ if (desc->channel[0].size == 16) {
+ modifier |= R300_US_OUT_FMT_C4_16;
+ } else {
+ /* C4_8 seems to be used for the formats whose pixel size
+ * is <= 32 bits. */
+ modifier |= R300_US_OUT_FMT_C4_8;
+ }
+ }
+
+ /* Add sign. */
+ for (i = 0; i < 4; i++)
+ if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {
+ modifier |= sign_bit[i];
+ }
+
+ /* Add swizzles and return. */
+ switch (format) {
+ /* 8-bit outputs.
+ * COLORFORMAT_I8 stores the C2 component. */
+ case PIPE_FORMAT_A8_UNORM:
+ return modifier | R300_C2_SEL_A;
+ case PIPE_FORMAT_I8_UNORM:
+ case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_R8_UNORM:
+ case PIPE_FORMAT_R8_SNORM:
+ return modifier | R300_C2_SEL_R;
+
+ /* BGRA outputs. */
+ case PIPE_FORMAT_B5G6R5_UNORM:
+ case PIPE_FORMAT_B5G5R5A1_UNORM:
+ case PIPE_FORMAT_B5G5R5X1_UNORM:
+ case PIPE_FORMAT_B4G4R4A4_UNORM:
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ return modifier |
+ R300_C0_SEL_B | R300_C1_SEL_G |
+ R300_C2_SEL_R | R300_C3_SEL_A;
+
+ /* ARGB outputs. */
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ return modifier |
+ R300_C0_SEL_A | R300_C1_SEL_R |
+ R300_C2_SEL_G | R300_C3_SEL_B;
+
+ /* ABGR outputs. */
+ case PIPE_FORMAT_A8B8G8R8_UNORM:
+ case PIPE_FORMAT_X8B8G8R8_UNORM:
+ return modifier |
+ R300_C0_SEL_A | R300_C1_SEL_B |
+ R300_C2_SEL_G | R300_C3_SEL_R;
+
+ /* RGBA outputs. */
+ case PIPE_FORMAT_R8G8B8A8_SNORM:
+ case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
+ case PIPE_FORMAT_R10G10B10A2_UNORM:
+ case PIPE_FORMAT_R16G16B16A16_UNORM:
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ //case PIPE_FORMAT_R16G16B16A16_FLOAT: /* not in pipe_format */
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ return modifier |
+ R300_C0_SEL_R | R300_C1_SEL_G |
+ R300_C2_SEL_B | R300_C3_SEL_A;
+
+ default:
+ return ~0; /* Unsupported. */
+ }
+}
+
+boolean r300_is_colorbuffer_format_supported(enum pipe_format format)
+{
+ return r300_translate_colorformat(format) != ~0 &&
+ r300_translate_out_fmt(format) != ~0;
+}
+
+boolean r300_is_zs_format_supported(enum pipe_format format)
+{
+ return r300_translate_zsformat(format) != ~0;
+}
+
+boolean r300_is_sampler_format_supported(enum pipe_format format)
+{
+ return r300_translate_texformat(format) != ~0;
+}
+