r600g: fix up vs export handling
[mesa.git] / src / gallium / drivers / r600 / evergreen_state.c
index dfe789649297f9a9bc660a5139850084d4449355..bc6039dd40c72d99d61b5a90eaf928f994bc3c5b 100644 (file)
 #include "r600_resource.h"
 #include "r600_shader.h"
 #include "r600_pipe.h"
-#include "eg_state_inlines.h"
+#include "r600_formats.h"
+
+static uint32_t r600_translate_blend_function(int blend_func)
+{
+       switch (blend_func) {
+       case PIPE_BLEND_ADD:
+               return V_028780_COMB_DST_PLUS_SRC;
+       case PIPE_BLEND_SUBTRACT:
+               return V_028780_COMB_SRC_MINUS_DST;
+       case PIPE_BLEND_REVERSE_SUBTRACT:
+               return V_028780_COMB_DST_MINUS_SRC;
+       case PIPE_BLEND_MIN:
+               return V_028780_COMB_MIN_DST_SRC;
+       case PIPE_BLEND_MAX:
+               return V_028780_COMB_MAX_DST_SRC;
+       default:
+               R600_ERR("Unknown blend function %d\n", blend_func);
+               assert(0);
+               break;
+       }
+       return 0;
+}
+
+static uint32_t r600_translate_blend_factor(int blend_fact)
+{
+       switch (blend_fact) {
+       case PIPE_BLENDFACTOR_ONE:
+               return V_028780_BLEND_ONE;
+       case PIPE_BLENDFACTOR_SRC_COLOR:
+               return V_028780_BLEND_SRC_COLOR;
+       case PIPE_BLENDFACTOR_SRC_ALPHA:
+               return V_028780_BLEND_SRC_ALPHA;
+       case PIPE_BLENDFACTOR_DST_ALPHA:
+               return V_028780_BLEND_DST_ALPHA;
+       case PIPE_BLENDFACTOR_DST_COLOR:
+               return V_028780_BLEND_DST_COLOR;
+       case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+               return V_028780_BLEND_SRC_ALPHA_SATURATE;
+       case PIPE_BLENDFACTOR_CONST_COLOR:
+               return V_028780_BLEND_CONST_COLOR;
+       case PIPE_BLENDFACTOR_CONST_ALPHA:
+               return V_028780_BLEND_CONST_ALPHA;
+       case PIPE_BLENDFACTOR_ZERO:
+               return V_028780_BLEND_ZERO;
+       case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+               return V_028780_BLEND_ONE_MINUS_SRC_COLOR;
+       case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+               return V_028780_BLEND_ONE_MINUS_SRC_ALPHA;
+       case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+               return V_028780_BLEND_ONE_MINUS_DST_ALPHA;
+       case PIPE_BLENDFACTOR_INV_DST_COLOR:
+               return V_028780_BLEND_ONE_MINUS_DST_COLOR;
+       case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+               return V_028780_BLEND_ONE_MINUS_CONST_COLOR;
+       case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+               return V_028780_BLEND_ONE_MINUS_CONST_ALPHA;
+       case PIPE_BLENDFACTOR_SRC1_COLOR:
+               return V_028780_BLEND_SRC1_COLOR;
+       case PIPE_BLENDFACTOR_SRC1_ALPHA:
+               return V_028780_BLEND_SRC1_ALPHA;
+       case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+               return V_028780_BLEND_INV_SRC1_COLOR;
+       case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+               return V_028780_BLEND_INV_SRC1_ALPHA;
+       default:
+               R600_ERR("Bad blend factor %d not supported!\n", blend_fact);
+               assert(0);
+               break;
+       }
+       return 0;
+}
+
+static uint32_t r600_translate_stencil_op(int s_op)
+{
+       switch (s_op) {
+       case PIPE_STENCIL_OP_KEEP:
+               return V_028800_STENCIL_KEEP;
+       case PIPE_STENCIL_OP_ZERO:
+               return V_028800_STENCIL_ZERO;
+       case PIPE_STENCIL_OP_REPLACE:
+               return V_028800_STENCIL_REPLACE;
+       case PIPE_STENCIL_OP_INCR:
+               return V_028800_STENCIL_INCR;
+       case PIPE_STENCIL_OP_DECR:
+               return V_028800_STENCIL_DECR;
+       case PIPE_STENCIL_OP_INCR_WRAP:
+               return V_028800_STENCIL_INCR_WRAP;
+       case PIPE_STENCIL_OP_DECR_WRAP:
+               return V_028800_STENCIL_DECR_WRAP;
+       case PIPE_STENCIL_OP_INVERT:
+               return V_028800_STENCIL_INVERT;
+       default:
+               R600_ERR("Unknown stencil op %d", s_op);
+               assert(0);
+               break;
+       }
+       return 0;
+}
+
+static uint32_t r600_translate_fill(uint32_t func)
+{
+       switch(func) {
+       case PIPE_POLYGON_MODE_FILL:
+               return 2;
+       case PIPE_POLYGON_MODE_LINE:
+               return 1;
+       case PIPE_POLYGON_MODE_POINT:
+               return 0;
+       default:
+               assert(0);
+               return 0;
+       }
+}
+
+/* translates straight */
+static uint32_t r600_translate_ds_func(int func)
+{
+       return func;
+}
+
+static unsigned r600_tex_wrap(unsigned wrap)
+{
+       switch (wrap) {
+       default:
+       case PIPE_TEX_WRAP_REPEAT:
+               return V_03C000_SQ_TEX_WRAP;
+       case PIPE_TEX_WRAP_CLAMP:
+               return V_03C000_SQ_TEX_CLAMP_HALF_BORDER;
+       case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+               return V_03C000_SQ_TEX_CLAMP_LAST_TEXEL;
+       case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+               return V_03C000_SQ_TEX_CLAMP_BORDER;
+       case PIPE_TEX_WRAP_MIRROR_REPEAT:
+               return V_03C000_SQ_TEX_MIRROR;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP:
+               return V_03C000_SQ_TEX_MIRROR_ONCE_HALF_BORDER;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+               return V_03C000_SQ_TEX_MIRROR_ONCE_LAST_TEXEL;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+               return V_03C000_SQ_TEX_MIRROR_ONCE_BORDER;
+       }
+}
+
+static unsigned r600_tex_filter(unsigned filter)
+{
+       switch (filter) {
+       default:
+       case PIPE_TEX_FILTER_NEAREST:
+               return V_03C000_SQ_TEX_XY_FILTER_POINT;
+       case PIPE_TEX_FILTER_LINEAR:
+               return V_03C000_SQ_TEX_XY_FILTER_BILINEAR;
+       }
+}
+
+static unsigned r600_tex_mipfilter(unsigned filter)
+{
+       switch (filter) {
+       case PIPE_TEX_MIPFILTER_NEAREST:
+               return V_03C000_SQ_TEX_Z_FILTER_POINT;
+       case PIPE_TEX_MIPFILTER_LINEAR:
+               return V_03C000_SQ_TEX_Z_FILTER_LINEAR;
+       default:
+       case PIPE_TEX_MIPFILTER_NONE:
+               return V_03C000_SQ_TEX_Z_FILTER_NONE;
+       }
+}
+
+static unsigned r600_tex_compare(unsigned compare)
+{
+       switch (compare) {
+       default:
+       case PIPE_FUNC_NEVER:
+               return V_03C000_SQ_TEX_DEPTH_COMPARE_NEVER;
+       case PIPE_FUNC_LESS:
+               return V_03C000_SQ_TEX_DEPTH_COMPARE_LESS;
+       case PIPE_FUNC_EQUAL:
+               return V_03C000_SQ_TEX_DEPTH_COMPARE_EQUAL;
+       case PIPE_FUNC_LEQUAL:
+               return V_03C000_SQ_TEX_DEPTH_COMPARE_LESSEQUAL;
+       case PIPE_FUNC_GREATER:
+               return V_03C000_SQ_TEX_DEPTH_COMPARE_GREATER;
+       case PIPE_FUNC_NOTEQUAL:
+               return V_03C000_SQ_TEX_DEPTH_COMPARE_NOTEQUAL;
+       case PIPE_FUNC_GEQUAL:
+               return V_03C000_SQ_TEX_DEPTH_COMPARE_GREATEREQUAL;
+       case PIPE_FUNC_ALWAYS:
+               return V_03C000_SQ_TEX_DEPTH_COMPARE_ALWAYS;
+       }
+}
+
+static unsigned r600_tex_dim(unsigned dim)
+{
+       switch (dim) {
+       default:
+       case PIPE_TEXTURE_1D:
+               return V_030000_SQ_TEX_DIM_1D;
+       case PIPE_TEXTURE_1D_ARRAY:
+               return V_030000_SQ_TEX_DIM_1D_ARRAY;
+       case PIPE_TEXTURE_2D:
+       case PIPE_TEXTURE_RECT:
+               return V_030000_SQ_TEX_DIM_2D;
+       case PIPE_TEXTURE_2D_ARRAY:
+               return V_030000_SQ_TEX_DIM_2D_ARRAY;
+       case PIPE_TEXTURE_3D:
+               return V_030000_SQ_TEX_DIM_3D;
+       case PIPE_TEXTURE_CUBE:
+               return V_030000_SQ_TEX_DIM_CUBEMAP;
+       }
+}
+
+static uint32_t r600_translate_dbformat(enum pipe_format format)
+{
+       switch (format) {
+       case PIPE_FORMAT_Z16_UNORM:
+               return V_028040_Z_16;
+       case PIPE_FORMAT_Z24X8_UNORM:
+               return V_028040_Z_24;
+       case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+               return V_028040_Z_24;
+       default:
+               return ~0U;
+       }
+}
+
+static uint32_t r600_translate_stencilformat(enum pipe_format format)
+{
+       if (format == PIPE_FORMAT_Z24_UNORM_S8_USCALED)
+               return 1;
+       else
+               return 0;
+}
+
+static uint32_t r600_translate_colorswap(enum pipe_format format)
+{
+       switch (format) {
+       /* 8-bit buffers. */
+       case PIPE_FORMAT_L4A4_UNORM:
+               return V_028C70_SWAP_ALT;
+
+       case PIPE_FORMAT_A8_UNORM:
+               return V_028C70_SWAP_ALT_REV;
+       case PIPE_FORMAT_I8_UNORM:
+       case PIPE_FORMAT_L8_UNORM:
+       case PIPE_FORMAT_L8_SRGB:
+       case PIPE_FORMAT_R8_UNORM:
+       case PIPE_FORMAT_R8_SNORM:
+               return V_028C70_SWAP_STD;
+
+       /* 16-bit buffers. */
+       case PIPE_FORMAT_B5G6R5_UNORM:
+               return V_028C70_SWAP_STD_REV;
+
+       case PIPE_FORMAT_B5G5R5A1_UNORM:
+       case PIPE_FORMAT_B5G5R5X1_UNORM:
+               return V_028C70_SWAP_ALT;
+
+       case PIPE_FORMAT_B4G4R4A4_UNORM:
+       case PIPE_FORMAT_B4G4R4X4_UNORM:
+               return V_028C70_SWAP_ALT;
+
+       case PIPE_FORMAT_Z16_UNORM:
+               return V_028C70_SWAP_STD;
+
+       case PIPE_FORMAT_L8A8_UNORM:
+       case PIPE_FORMAT_L8A8_SRGB:
+               return V_028C70_SWAP_ALT;
+       case PIPE_FORMAT_R8G8_UNORM:
+               return V_028C70_SWAP_STD;
+
+       case PIPE_FORMAT_R16_UNORM:
+       case PIPE_FORMAT_R16_FLOAT:
+               return V_028C70_SWAP_STD;
+
+       /* 32-bit buffers. */
+       case PIPE_FORMAT_A8B8G8R8_SRGB:
+               return V_028C70_SWAP_STD_REV;
+       case PIPE_FORMAT_B8G8R8A8_SRGB:
+               return V_028C70_SWAP_ALT;
+
+       case PIPE_FORMAT_B8G8R8A8_UNORM:
+       case PIPE_FORMAT_B8G8R8X8_UNORM:
+               return V_028C70_SWAP_ALT;
+
+       case PIPE_FORMAT_A8R8G8B8_UNORM:
+       case PIPE_FORMAT_X8R8G8B8_UNORM:
+               return V_028C70_SWAP_ALT_REV;
+       case PIPE_FORMAT_R8G8B8A8_SNORM:
+       case PIPE_FORMAT_R8G8B8A8_UNORM:
+       case PIPE_FORMAT_R8G8B8X8_UNORM:
+               return V_028C70_SWAP_STD;
+
+       case PIPE_FORMAT_A8B8G8R8_UNORM:
+       case PIPE_FORMAT_X8B8G8R8_UNORM:
+       /* case PIPE_FORMAT_R8SG8SB8UX8U_NORM: */
+               return V_028C70_SWAP_STD_REV;
+
+       case PIPE_FORMAT_Z24X8_UNORM:
+       case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+               return V_028C70_SWAP_STD;
+
+       case PIPE_FORMAT_X8Z24_UNORM:
+       case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+               return V_028C70_SWAP_STD;
+
+       case PIPE_FORMAT_R10G10B10A2_UNORM:
+       case PIPE_FORMAT_R10G10B10X2_SNORM:
+       case PIPE_FORMAT_R10SG10SB10SA2U_NORM:
+               return V_028C70_SWAP_STD;
+
+       case PIPE_FORMAT_B10G10R10A2_UNORM:
+               return V_028C70_SWAP_ALT;
+
+       case PIPE_FORMAT_R11G11B10_FLOAT:
+       case PIPE_FORMAT_R32_FLOAT:
+       case PIPE_FORMAT_R16G16_FLOAT:
+       case PIPE_FORMAT_R16G16_UNORM:
+               return V_028C70_SWAP_STD;
+
+       /* 64-bit buffers. */
+       case PIPE_FORMAT_R32G32_FLOAT:
+       case PIPE_FORMAT_R16G16B16A16_UNORM:
+       case PIPE_FORMAT_R16G16B16A16_SNORM:
+       case PIPE_FORMAT_R16G16B16A16_FLOAT:
+
+       /* 128-bit buffers. */
+       case PIPE_FORMAT_R32G32B32A32_FLOAT:
+       case PIPE_FORMAT_R32G32B32A32_SNORM:
+       case PIPE_FORMAT_R32G32B32A32_UNORM:
+               return V_028C70_SWAP_STD;
+       default:
+               R600_ERR("unsupported colorswap format %d\n", format);
+               return ~0U;
+       }
+       return ~0U;
+}
+
+static uint32_t r600_translate_colorformat(enum pipe_format format)
+{
+       switch (format) {
+       /* 8-bit buffers. */
+       case PIPE_FORMAT_L4A4_UNORM:
+               return V_028C70_COLOR_4_4;
+
+       case PIPE_FORMAT_A8_UNORM:
+       case PIPE_FORMAT_I8_UNORM:
+       case PIPE_FORMAT_L8_UNORM:
+       case PIPE_FORMAT_L8_SRGB:
+       case PIPE_FORMAT_R8_UNORM:
+       case PIPE_FORMAT_R8_SNORM:
+               return V_028C70_COLOR_8;
+
+       /* 16-bit buffers. */
+       case PIPE_FORMAT_B5G6R5_UNORM:
+               return V_028C70_COLOR_5_6_5;
+
+       case PIPE_FORMAT_B5G5R5A1_UNORM:
+       case PIPE_FORMAT_B5G5R5X1_UNORM:
+               return V_028C70_COLOR_1_5_5_5;
+
+       case PIPE_FORMAT_B4G4R4A4_UNORM:
+       case PIPE_FORMAT_B4G4R4X4_UNORM:
+               return V_028C70_COLOR_4_4_4_4;
+
+       case PIPE_FORMAT_Z16_UNORM:
+               return V_028C70_COLOR_16;
+
+       case PIPE_FORMAT_L8A8_UNORM:
+       case PIPE_FORMAT_L8A8_SRGB:
+       case PIPE_FORMAT_R8G8_UNORM:
+               return V_028C70_COLOR_8_8;
+
+       case PIPE_FORMAT_R16_UNORM:
+               return V_028C70_COLOR_16;
+
+       case PIPE_FORMAT_R16_FLOAT:
+               return V_028C70_COLOR_16_FLOAT;
+
+       /* 32-bit buffers. */
+       case PIPE_FORMAT_A8B8G8R8_SRGB:
+       case PIPE_FORMAT_A8B8G8R8_UNORM:
+       case PIPE_FORMAT_A8R8G8B8_UNORM:
+       case PIPE_FORMAT_B8G8R8A8_SRGB:
+       case PIPE_FORMAT_B8G8R8A8_UNORM:
+       case PIPE_FORMAT_B8G8R8X8_UNORM:
+       case PIPE_FORMAT_R8G8B8A8_SNORM:
+       case PIPE_FORMAT_R8G8B8A8_UNORM:
+       case PIPE_FORMAT_R8G8B8X8_UNORM:
+       case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
+       case PIPE_FORMAT_X8B8G8R8_UNORM:
+       case PIPE_FORMAT_X8R8G8B8_UNORM:
+       case PIPE_FORMAT_R8G8B8_UNORM:
+               return V_028C70_COLOR_8_8_8_8;
+
+       case PIPE_FORMAT_R10G10B10A2_UNORM:
+       case PIPE_FORMAT_R10G10B10X2_SNORM:
+       case PIPE_FORMAT_B10G10R10A2_UNORM:
+       case PIPE_FORMAT_R10SG10SB10SA2U_NORM:
+               return V_028C70_COLOR_2_10_10_10;
+
+       case PIPE_FORMAT_Z24X8_UNORM:
+       case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+               return V_028C70_COLOR_8_24;
+
+       case PIPE_FORMAT_X8Z24_UNORM:
+       case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+               return V_028C70_COLOR_24_8;
+
+       case PIPE_FORMAT_R32_FLOAT:
+               return V_028C70_COLOR_32_FLOAT;
+
+       case PIPE_FORMAT_R16G16_FLOAT:
+               return V_028C70_COLOR_16_16_FLOAT;
+
+       case PIPE_FORMAT_R16G16_SSCALED:
+       case PIPE_FORMAT_R16G16_UNORM:
+               return V_028C70_COLOR_16_16;
+
+       case PIPE_FORMAT_R11G11B10_FLOAT:
+               return V_028C70_COLOR_10_11_11_FLOAT;
+
+       /* 64-bit buffers. */
+       case PIPE_FORMAT_R16G16B16_USCALED:
+       case PIPE_FORMAT_R16G16B16A16_USCALED:
+       case PIPE_FORMAT_R16G16B16_SSCALED:
+       case PIPE_FORMAT_R16G16B16A16_SSCALED:
+       case PIPE_FORMAT_R16G16B16A16_UNORM:
+       case PIPE_FORMAT_R16G16B16A16_SNORM:
+               return V_028C70_COLOR_16_16_16_16;
+
+       case PIPE_FORMAT_R16G16B16_FLOAT:
+       case PIPE_FORMAT_R16G16B16A16_FLOAT:
+               return V_028C70_COLOR_16_16_16_16_FLOAT;
+
+       case PIPE_FORMAT_R32G32_FLOAT:
+               return V_028C70_COLOR_32_32_FLOAT;
+
+       case PIPE_FORMAT_R32G32_USCALED:
+       case PIPE_FORMAT_R32G32_SSCALED:
+               return V_028C70_COLOR_32_32;
+
+       /* 96-bit buffers. */
+       case PIPE_FORMAT_R32G32B32_FLOAT:
+               return V_028C70_COLOR_32_32_32_FLOAT;
+
+       /* 128-bit buffers. */
+       case PIPE_FORMAT_R32G32B32A32_SNORM:
+       case PIPE_FORMAT_R32G32B32A32_UNORM:
+               return V_028C70_COLOR_32_32_32_32;
+       case PIPE_FORMAT_R32G32B32A32_FLOAT:
+               return V_028C70_COLOR_32_32_32_32_FLOAT;
+
+       /* YUV buffers. */
+       case PIPE_FORMAT_UYVY:
+       case PIPE_FORMAT_YUYV:
+       default:
+               return ~0U; /* Unsupported. */
+       }
+}
+
+static uint32_t r600_colorformat_endian_swap(uint32_t colorformat)
+{
+       if (R600_BIG_ENDIAN) {
+               switch(colorformat) {
+               case V_028C70_COLOR_4_4:
+                       return ENDIAN_NONE;
+
+               /* 8-bit buffers. */
+               case V_028C70_COLOR_8:
+                       return ENDIAN_NONE;
+
+               /* 16-bit buffers. */
+               case V_028C70_COLOR_5_6_5:
+               case V_028C70_COLOR_1_5_5_5:
+               case V_028C70_COLOR_4_4_4_4:
+               case V_028C70_COLOR_16:
+               case V_028C70_COLOR_8_8:
+                       return ENDIAN_8IN16;
+
+               /* 32-bit buffers. */
+               case V_028C70_COLOR_8_8_8_8:
+               case V_028C70_COLOR_2_10_10_10:
+               case V_028C70_COLOR_8_24:
+               case V_028C70_COLOR_24_8:
+               case V_028C70_COLOR_32_FLOAT:
+               case V_028C70_COLOR_16_16_FLOAT:
+               case V_028C70_COLOR_16_16:
+                       return ENDIAN_8IN32;
+
+               /* 64-bit buffers. */
+               case V_028C70_COLOR_16_16_16_16:
+               case V_028C70_COLOR_16_16_16_16_FLOAT:
+                       return ENDIAN_8IN16;
+
+               case V_028C70_COLOR_32_32_FLOAT:
+               case V_028C70_COLOR_32_32:
+                       return ENDIAN_8IN32;
+
+               /* 96-bit buffers. */
+               case V_028C70_COLOR_32_32_32_FLOAT:
+               /* 128-bit buffers. */
+               case V_028C70_COLOR_32_32_32_32_FLOAT:
+               case V_028C70_COLOR_32_32_32_32:
+                       return ENDIAN_8IN32;
+               default:
+                       return ENDIAN_NONE; /* Unsupported. */
+               }
+       } else {
+               return ENDIAN_NONE;
+       }
+}
+
+static bool r600_is_sampler_format_supported(struct pipe_screen *screen, enum pipe_format format)
+{
+       return r600_translate_texformat(screen, format, NULL, NULL, NULL) != ~0U;
+}
+
+static bool r600_is_colorbuffer_format_supported(enum pipe_format format)
+{
+       return r600_translate_colorformat(format) != ~0U &&
+               r600_translate_colorswap(format) != ~0U;
+}
+
+static bool r600_is_zs_format_supported(enum pipe_format format)
+{
+       return r600_translate_dbformat(format) != ~0U;
+}
+
+boolean evergreen_is_format_supported(struct pipe_screen *screen,
+                                     enum pipe_format format,
+                                     enum pipe_texture_target target,
+                                     unsigned sample_count,
+                                     unsigned usage)
+{
+       unsigned retval = 0;
+
+       if (target >= PIPE_MAX_TEXTURE_TYPES) {
+               R600_ERR("r600: unsupported texture type %d\n", target);
+               return FALSE;
+       }
+
+       if (!util_format_is_supported(format, usage))
+               return FALSE;
+
+       /* Multisample */
+       if (sample_count > 1)
+               return FALSE;
+
+       if ((usage & PIPE_BIND_SAMPLER_VIEW) &&
+           r600_is_sampler_format_supported(screen, format)) {
+               retval |= PIPE_BIND_SAMPLER_VIEW;
+       }
+
+       if ((usage & (PIPE_BIND_RENDER_TARGET |
+                     PIPE_BIND_DISPLAY_TARGET |
+                     PIPE_BIND_SCANOUT |
+                     PIPE_BIND_SHARED)) &&
+           r600_is_colorbuffer_format_supported(format)) {
+               retval |= usage &
+                         (PIPE_BIND_RENDER_TARGET |
+                          PIPE_BIND_DISPLAY_TARGET |
+                          PIPE_BIND_SCANOUT |
+                          PIPE_BIND_SHARED);
+       }
+
+       if ((usage & PIPE_BIND_DEPTH_STENCIL) &&
+           r600_is_zs_format_supported(format)) {
+               retval |= PIPE_BIND_DEPTH_STENCIL;
+       }
+
+       if ((usage & PIPE_BIND_VERTEX_BUFFER) &&
+           r600_is_vertex_format_supported(format)) {
+               retval |= PIPE_BIND_VERTEX_BUFFER;
+       }
+
+       if (usage & PIPE_BIND_TRANSFER_READ)
+               retval |= PIPE_BIND_TRANSFER_READ;
+       if (usage & PIPE_BIND_TRANSFER_WRITE)
+               retval |= PIPE_BIND_TRANSFER_WRITE;
+
+       return retval == usage;
+}
 
 static void evergreen_set_blend_color(struct pipe_context *ctx,
                                        const struct pipe_blend_color *state)
@@ -77,13 +657,11 @@ static void *evergreen_create_blend_state(struct pipe_context *ctx,
        u32 color_control, target_mask;
        /* FIXME there is more then 8 framebuffer */
        unsigned blend_cntl[8];
-       enum radeon_family family;
 
        if (blend == NULL) {
                return NULL;
        }
 
-       family = r600_get_family(rctx->radeon);
        rstate = &blend->rstate;
 
        rstate->id = R600_PIPE_STATE_BLEND;
@@ -110,7 +688,7 @@ static void *evergreen_create_blend_state(struct pipe_context *ctx,
        r600_pipe_state_add_reg(rstate, R_028808_CB_COLOR_CONTROL,
                                color_control, 0xFFFFFFFD, NULL);
 
-       if (family != CHIP_CAYMAN)
+       if (rctx->chip_class != CAYMAN)
                r600_pipe_state_add_reg(rstate, R_028C3C_PA_SC_AA_MASK, 0xFFFFFFFF, 0xFFFFFFFF, NULL);
        else {
                r600_pipe_state_add_reg(rstate, CM_R_028C38_PA_SC_AA_MASK_X0Y0_X1Y0, 0xFFFFFFFF, 0xFFFFFFFF, NULL);
@@ -247,9 +825,6 @@ static void *evergreen_create_rs_state(struct pipe_context *ctx,
        unsigned tmp;
        unsigned prov_vtx = 1, polygon_dual_mode;
        unsigned clip_rule;
-       enum radeon_family family;
-
-       family = r600_get_family(rctx->radeon);
 
        if (rs == NULL) {
                return NULL;
@@ -308,7 +883,7 @@ static void *evergreen_create_rs_state(struct pipe_context *ctx,
        tmp = (unsigned)state->line_width * 8;
        r600_pipe_state_add_reg(rstate, R_028A08_PA_SU_LINE_CNTL, S_028A08_WIDTH(tmp), 0xFFFFFFFF, NULL);
 
-       if (family == CHIP_CAYMAN) {
+       if (rctx->chip_class == CAYMAN) {
                r600_pipe_state_add_reg(rstate, CM_R_028BDC_PA_SC_LINE_CNTL, 0x00000400, 0xFFFFFFFF, NULL);
                r600_pipe_state_add_reg(rstate, CM_R_028BE4_PA_SU_VTX_CNTL,
                                        S_028C08_PIX_CENTER_HALF(state->gl_rasterization_rules),
@@ -867,14 +1442,11 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx,
        struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
        struct r600_pipe_state *rstate = CALLOC_STRUCT(r600_pipe_state);
        u32 shader_mask, tl, br, target_mask;
-       enum radeon_family family;
        int tl_x, tl_y, br_x, br_y;
 
        if (rstate == NULL)
                return;
 
-       family = r600_get_family(rctx->radeon);
-
        evergreen_context_flush_dest_caches(&rctx->ctx);
        rctx->ctx.num_dest_buffers = state->nr_cbufs;
 
@@ -885,6 +1457,7 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx,
 
        /* build states */
        rctx->have_depth_fb = 0;
+       rctx->nr_cbufs = state->nr_cbufs;
        for (int i = 0; i < state->nr_cbufs; i++) {
                evergreen_cb(rctx, rstate, state, i);
        }
@@ -910,7 +1483,7 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx,
        if (br_y == 0)
                tl_y = 1;
        /* cayman hw workaround */
-       if (family == CHIP_CAYMAN) {
+       if (rctx->chip_class == CAYMAN) {
                if (br_x == 1 && br_y == 1)
                        br_x = 2;
        }
@@ -954,7 +1527,7 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx,
                                shader_mask, 0xFFFFFFFF, NULL);
 
 
-       if (family == CHIP_CAYMAN) {
+       if (rctx->chip_class == CAYMAN) {
                r600_pipe_state_add_reg(rstate, CM_R_028BE0_PA_SC_AA_CONFIG,
                                        0x00000000, 0xFFFFFFFF, NULL);
        } else {
@@ -1141,9 +1714,9 @@ void evergreen_init_config(struct r600_pipe_context *rctx)
        enum radeon_family family;
        unsigned tmp;
 
-       family = r600_get_family(rctx->radeon);
+       family = rctx->family;
 
-       if (family == CHIP_CAYMAN) {
+       if (rctx->chip_class == CAYMAN) {
                cayman_init_config(rctx);
                return;
        }
@@ -1453,6 +2026,11 @@ void evergreen_init_config(struct r600_pipe_context *rctx)
        tmp |= S_008C28_NUM_LS_STACK_ENTRIES(num_ls_stack_entries);
        r600_pipe_state_add_reg(rstate, R_008C28_SQ_STACK_RESOURCE_MGMT_3, tmp, 0xFFFFFFFF, NULL);
 
+       tmp = 0;
+       tmp |= S_008E2C_NUM_PS_LDS(0x1000);
+       tmp |= S_008E2C_NUM_LS_LDS(0x1000);
+       r600_pipe_state_add_reg(rstate, R_008E2C_SQ_LDS_RESOURCE_MGMT, tmp, 0xFFFFFFFF, NULL);
+
        r600_pipe_state_add_reg(rstate, R_009100_SPI_CONFIG_CNTL, 0x0, 0xFFFFFFFF, NULL);
        r600_pipe_state_add_reg(rstate, R_00913C_SPI_CONFIG_CNTL_1, S_00913C_VTX_DONE_DELAY(4), 0xFFFFFFFF, NULL);
 
@@ -1631,7 +2209,10 @@ void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader
                    rshader->output[i].name == TGSI_SEMANTIC_STENCIL)
                        exports_ps |= 1;
                else if (rshader->output[i].name == TGSI_SEMANTIC_COLOR) {
-                       num_cout++;
+                       if (rshader->fs_write_all)
+                               num_cout = rshader->nr_cbufs;
+                       else
+                               num_cout++;
                }
        }
        exports_ps |= S_02884C_EXPORT_COLORS(num_cout);
@@ -1717,7 +2298,7 @@ void evergreen_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shader
        struct r600_pipe_state *rstate = &shader->rstate;
        struct r600_shader *rshader = &shader->shader;
        unsigned spi_vs_out_id[10];
-       unsigned i, tmp;
+       unsigned i, tmp, nparams;
 
        /* clear previous register */
        rstate->nregs = 0;
@@ -1736,9 +2317,17 @@ void evergreen_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shader
                                        spi_vs_out_id[i], 0xFFFFFFFF, NULL);
        }
 
+       /* Certain attributes (position, psize, etc.) don't count as params.
+        * VS is required to export at least one param and r600_shader_from_tgsi()
+        * takes care of adding a dummy export.
+        */
+       nparams = rshader->noutput - rshader->npos;
+       if (nparams < 1)
+               nparams = 1;
+
        r600_pipe_state_add_reg(rstate,
                        R_0286C4_SPI_VS_OUT_CONFIG,
-                       S_0286C4_VS_EXPORT_COUNT(rshader->noutput - 2),
+                       S_0286C4_VS_EXPORT_COUNT(nparams - 1),
                        0xFFFFFFFF, NULL);
        r600_pipe_state_add_reg(rstate,
                        R_028860_SQ_PGM_RESOURCES_VS,