gallium: change pipe_sampler_view::first_element/last_element -> offset/size
[mesa.git] / src / gallium / drivers / r600 / r600_state.c
index 59fe2f4420fd9001a86c69c6065d8c9c7ea52f93..62b1c2c282a8c2242522183fa5e9a67a974a3eb8 100644 (file)
@@ -143,13 +143,14 @@ static uint32_t r600_translate_dbformat(enum pipe_format format)
 
 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;
+       return r600_translate_texformat(screen, format, NULL, NULL, NULL,
+                                   FALSE) != ~0U;
 }
 
 static bool r600_is_colorbuffer_format_supported(enum chip_class chip, enum pipe_format format)
 {
-       return r600_translate_colorformat(chip, format) != ~0U &&
-              r600_translate_colorswap(format) != ~0U;
+       return r600_translate_colorformat(chip, format, FALSE) != ~0U &&
+              r600_translate_colorswap(format, FALSE) != ~0U;
 }
 
 static bool r600_is_zs_format_supported(enum pipe_format format)
@@ -253,16 +254,26 @@ static void r600_emit_polygon_offset(struct r600_context *rctx, struct r600_atom
        struct r600_poly_offset_state *state = (struct r600_poly_offset_state*)a;
        float offset_units = state->offset_units;
        float offset_scale = state->offset_scale;
-
-       switch (state->zs_format) {
-       case PIPE_FORMAT_Z24X8_UNORM:
-       case PIPE_FORMAT_Z24_UNORM_S8_UINT:
-               offset_units *= 2.0f;
-               break;
-       case PIPE_FORMAT_Z16_UNORM:
-               offset_units *= 4.0f;
-               break;
-       default:;
+       uint32_t pa_su_poly_offset_db_fmt_cntl = 0;
+
+       if (!state->offset_units_unscaled) {
+               switch (state->zs_format) {
+               case PIPE_FORMAT_Z24X8_UNORM:
+               case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+                       offset_units *= 2.0f;
+                       pa_su_poly_offset_db_fmt_cntl =
+                               S_028DF8_POLY_OFFSET_NEG_NUM_DB_BITS((char)-24);
+                       break;
+               case PIPE_FORMAT_Z16_UNORM:
+                       offset_units *= 4.0f;
+                       pa_su_poly_offset_db_fmt_cntl =
+                               S_028DF8_POLY_OFFSET_NEG_NUM_DB_BITS((char)-16);
+                       break;
+               default:
+                       pa_su_poly_offset_db_fmt_cntl =
+                               S_028DF8_POLY_OFFSET_NEG_NUM_DB_BITS((char)-23) |
+                               S_028DF8_POLY_OFFSET_DB_IS_FLOAT_FMT(1);
+               }
        }
 
        radeon_set_context_reg_seq(cs, R_028E00_PA_SU_POLY_OFFSET_FRONT_SCALE, 4);
@@ -270,6 +281,9 @@ static void r600_emit_polygon_offset(struct r600_context *rctx, struct r600_atom
        radeon_emit(cs, fui(offset_units));
        radeon_emit(cs, fui(offset_scale));
        radeon_emit(cs, fui(offset_units));
+
+       radeon_set_context_reg(cs, R_028DF8_PA_SU_POLY_OFFSET_DB_FMT_CNTL,
+                              pa_su_poly_offset_db_fmt_cntl);
 }
 
 static uint32_t r600_get_blend_control(const struct pipe_blend_state *state, unsigned i)
@@ -466,7 +480,6 @@ static void *r600_create_rs_state(struct pipe_context *ctx,
                                S_028A0C_LINE_PATTERN(state->line_stipple_pattern) |
                                S_028A0C_REPEAT_COUNT(state->line_stipple_factor) : 0;
        rs->pa_cl_clip_cntl =
-               S_028810_PS_UCP_MODE(3) |
                S_028810_DX_CLIP_SPACE_DEF(state->clip_halfz) |
                S_028810_ZCLIP_NEAR_DISABLE(!state->depth_clip) |
                S_028810_ZCLIP_FAR_DISABLE(!state->depth_clip) |
@@ -481,6 +494,7 @@ static void *r600_create_rs_state(struct pipe_context *ctx,
        rs->offset_units = state->offset_units;
        rs->offset_scale = state->offset_scale * 16.0f;
        rs->offset_enable = state->offset_point || state->offset_line || state->offset_tri;
+       rs->offset_units_unscaled = state->offset_units_unscaled;
 
        if (state->point_size_per_vertex) {
                psize_min = util_get_min_point_size(state);
@@ -571,7 +585,11 @@ static unsigned r600_tex_filter(unsigned filter, unsigned max_aniso)
 static void *r600_create_sampler_state(struct pipe_context *ctx,
                                        const struct pipe_sampler_state *state)
 {
+       struct r600_common_screen *rscreen = (struct r600_common_screen*)ctx->screen;
        struct r600_pipe_sampler_state *ss = CALLOC_STRUCT(r600_pipe_sampler_state);
+       unsigned max_aniso = rscreen->force_aniso >= 0 ? rscreen->force_aniso
+                                                      : state->max_anisotropy;
+       unsigned max_aniso_ratio = r600_tex_aniso_filter(max_aniso);
 
        if (!ss) {
                return NULL;
@@ -585,10 +603,10 @@ static void *r600_create_sampler_state(struct pipe_context *ctx,
                S_03C000_CLAMP_X(r600_tex_wrap(state->wrap_s)) |
                S_03C000_CLAMP_Y(r600_tex_wrap(state->wrap_t)) |
                S_03C000_CLAMP_Z(r600_tex_wrap(state->wrap_r)) |
-               S_03C000_XY_MAG_FILTER(r600_tex_filter(state->mag_img_filter, state->max_anisotropy)) |
-               S_03C000_XY_MIN_FILTER(r600_tex_filter(state->min_img_filter, state->max_anisotropy)) |
+               S_03C000_XY_MAG_FILTER(r600_tex_filter(state->mag_img_filter, max_aniso)) |
+               S_03C000_XY_MIN_FILTER(r600_tex_filter(state->min_img_filter, max_aniso)) |
                S_03C000_MIP_FILTER(r600_tex_mipfilter(state->min_mip_filter)) |
-               S_03C000_MAX_ANISO_RATIO(r600_tex_aniso_filter(state->max_anisotropy)) |
+               S_03C000_MAX_ANISO_RATIO(max_aniso_ratio) |
                S_03C000_DEPTH_COMPARE_FUNCTION(r600_tex_compare(state->compare_func)) |
                S_03C000_BORDER_COLOR_TYPE(ss->border_color_use ? V_03C000_SQ_TEX_BORDER_COLOR_REGISTER : 0);
        /* R_03C004_SQ_TEX_SAMPLER_WORD1_0 */
@@ -613,8 +631,8 @@ texture_buffer_sampler_view(struct r600_pipe_sampler_view *view,
        struct r600_texture *tmp = (struct r600_texture*)view->base.texture;
        int stride = util_format_get_blocksize(view->base.format);
        unsigned format, num_format, format_comp, endian;
-       uint64_t offset = view->base.u.buf.first_element * stride;
-       unsigned size = (view->base.u.buf.last_element - view->base.u.buf.first_element + 1) * stride;
+       uint64_t offset = view->base.u.buf.offset;
+       unsigned size = view->base.u.buf.size;
 
        r600_vertex_data_type(view->base.format,
                              &format, &num_format, &format_comp,
@@ -655,6 +673,7 @@ r600_create_sampler_view_custom(struct pipe_context *ctx,
        uint32_t word4 = 0, yuv_format = 0, pitch = 0;
        unsigned char swizzle[4], array_mode = 0;
        unsigned width, height, depth, offset_level, last_level;
+       bool do_endian_swap = FALSE;
 
        if (!view)
                return NULL;
@@ -675,16 +694,25 @@ r600_create_sampler_view_custom(struct pipe_context *ctx,
        swizzle[2] = state->swizzle_b;
        swizzle[3] = state->swizzle_a;
 
+       if (R600_BIG_ENDIAN)
+               do_endian_swap = !tmp->db_compatible;
+
        format = r600_translate_texformat(ctx->screen, state->format,
                                          swizzle,
-                                         &word4, &yuv_format);
+                                         &word4, &yuv_format, do_endian_swap);
        assert(format != ~0);
        if (format == ~0) {
                FREE(view);
                return NULL;
        }
 
-       if (tmp->is_depth && !tmp->is_flushing_texture && !r600_can_read_depth(tmp)) {
+       if (state->format == PIPE_FORMAT_X24S8_UINT ||
+           state->format == PIPE_FORMAT_S8X24_UINT ||
+           state->format == PIPE_FORMAT_X32_S8X24_UINT ||
+           state->format == PIPE_FORMAT_S8_UINT)
+               view->is_stencil_sampler = true;
+
+       if (tmp->is_depth && !r600_can_sample_zs(tmp, view->is_stencil_sampler)) {
                if (!r600_init_flushed_depth_texture(ctx, texture, NULL)) {
                        FREE(view);
                        return NULL;
@@ -692,7 +720,7 @@ r600_create_sampler_view_custom(struct pipe_context *ctx,
                tmp = tmp->flushed_depth_texture;
        }
 
-       endian = r600_colorformat_endian_swap(format);
+       endian = r600_colorformat_endian_swap(format, do_endian_swap);
 
        offset_level = state->u.tex.first_level;
        last_level = state->u.tex.last_level - offset_level;
@@ -708,7 +736,9 @@ r600_create_sampler_view_custom(struct pipe_context *ctx,
                depth = texture->array_size;
        } else if (texture->target == PIPE_TEXTURE_CUBE_ARRAY)
                depth = texture->array_size / 6;
+
        switch (tmp->surface.level[offset_level].mode) {
+       default:
        case RADEON_SURF_MODE_LINEAR_ALIGNED:
                array_mode = V_038000_ARRAY_LINEAR_ALIGNED;
                break;
@@ -718,18 +748,8 @@ r600_create_sampler_view_custom(struct pipe_context *ctx,
        case RADEON_SURF_MODE_2D:
                array_mode = V_038000_ARRAY_2D_TILED_THIN1;
                break;
-       case RADEON_SURF_MODE_LINEAR:
-       default:
-               array_mode = V_038000_ARRAY_LINEAR_GENERAL;
-               break;
        }
 
-       if (state->format == PIPE_FORMAT_X24S8_UINT ||
-           state->format == PIPE_FORMAT_S8X24_UINT ||
-           state->format == PIPE_FORMAT_X32_S8X24_UINT ||
-           state->format == PIPE_FORMAT_S8_UINT)
-               view->is_stencil_sampler = true;
-
        view->tex_resource = &tmp->resource;
        view->tex_resource_words[0] = (S_038000_DIM(r600_tex_dim(texture->target, texture->nr_samples)) |
                                       S_038000_TILE_MODE(array_mode) |
@@ -820,23 +840,17 @@ static void r600_init_color_surface(struct r600_context *rctx,
        unsigned offset;
        const struct util_format_description *desc;
        int i;
-       bool blend_bypass = 0, blend_clamp = 1;
+       bool blend_bypass = 0, blend_clamp = 1, do_endian_swap = FALSE;
 
-       if (rtex->is_depth && !rtex->is_flushing_texture && !r600_can_read_depth(rtex)) {
+       if (rtex->db_compatible && !r600_can_sample_zs(rtex, false)) {
                r600_init_flushed_depth_texture(&rctx->b.b, surf->base.texture, NULL);
                rtex = rtex->flushed_depth_texture;
                assert(rtex);
        }
 
        offset = rtex->surface.level[level].offset;
-       if (rtex->surface.level[level].mode == RADEON_SURF_MODE_LINEAR) {
-               assert(surf->base.u.tex.first_layer == surf->base.u.tex.last_layer);
-               offset += rtex->surface.level[level].slice_size *
-                       surf->base.u.tex.first_layer;
-               color_view = 0;
-       } else
-               color_view = S_028080_SLICE_START(surf->base.u.tex.first_layer) |
-                            S_028080_SLICE_MAX(surf->base.u.tex.last_layer);
+       color_view = S_028080_SLICE_START(surf->base.u.tex.first_layer) |
+                    S_028080_SLICE_MAX(surf->base.u.tex.last_layer);
 
        pitch = rtex->surface.level[level].nblk_x / 8 - 1;
        slice = (rtex->surface.level[level].nblk_x * rtex->surface.level[level].nblk_y) / 64;
@@ -845,6 +859,7 @@ static void r600_init_color_surface(struct r600_context *rctx,
        }
        color_info = 0;
        switch (rtex->surface.level[level].mode) {
+       default:
        case RADEON_SURF_MODE_LINEAR_ALIGNED:
                color_info = S_0280A0_ARRAY_MODE(V_038000_ARRAY_LINEAR_ALIGNED);
                break;
@@ -854,10 +869,6 @@ static void r600_init_color_surface(struct r600_context *rctx,
        case RADEON_SURF_MODE_2D:
                color_info = S_0280A0_ARRAY_MODE(V_038000_ARRAY_2D_TILED_THIN1);
                break;
-       case RADEON_SURF_MODE_LINEAR:
-       default:
-               color_info = S_0280A0_ARRAY_MODE(V_038000_ARRAY_LINEAR_GENERAL);
-               break;
        }
 
        desc = util_format_description(surf->base.format);
@@ -883,13 +894,17 @@ static void r600_init_color_surface(struct r600_context *rctx,
                        ntype = V_0280A0_NUMBER_UINT;
        }
 
-       format = r600_translate_colorformat(rctx->b.chip_class, surf->base.format);
+       if (R600_BIG_ENDIAN)
+               do_endian_swap = !rtex->db_compatible;
+
+       format = r600_translate_colorformat(rctx->b.chip_class, surf->base.format,
+                                                     do_endian_swap);
        assert(format != ~0);
 
-       swap = r600_translate_colorswap(surf->base.format);
+       swap = r600_translate_colorswap(surf->base.format, do_endian_swap);
        assert(swap != ~0);
 
-       endian = r600_colorformat_endian_swap(format);
+       endian = r600_colorformat_endian_swap(format, do_endian_swap);
 
        /* set blend bypass according to docs if SINT/UINT or
           8/24 COLOR variants */
@@ -952,10 +967,8 @@ static void r600_init_color_surface(struct r600_context *rctx,
        surf->cb_color_cmask = surf->cb_color_base;
        surf->cb_color_mask = 0;
 
-       pipe_resource_reference((struct pipe_resource**)&surf->cb_buffer_cmask,
-                               &rtex->resource.b.b);
-       pipe_resource_reference((struct pipe_resource**)&surf->cb_buffer_fmask,
-                               &rtex->resource.b.b);
+       r600_resource_reference(&surf->cb_buffer_cmask, &rtex->resource);
+       r600_resource_reference(&surf->cb_buffer_fmask, &rtex->resource);
 
        if (rtex->cmask.size) {
                surf->cb_color_cmask = rtex->cmask.offset >> 8;
@@ -988,7 +1001,7 @@ static void r600_init_color_surface(struct r600_context *rctx,
                        struct pipe_transfer *transfer;
                        void *ptr;
 
-                       pipe_resource_reference((struct pipe_resource**)&rctx->dummy_cmask, NULL);
+                       r600_resource_reference(&rctx->dummy_cmask, NULL);
                        rctx->dummy_cmask = r600_buffer_create_helper(rscreen, cmask.size, cmask.alignment);
 
                        /* Set the contents to 0xCC. */
@@ -996,19 +1009,17 @@ static void r600_init_color_surface(struct r600_context *rctx,
                        memset(ptr, 0xCC, cmask.size);
                        pipe_buffer_unmap(&rctx->b.b, transfer);
                }
-               pipe_resource_reference((struct pipe_resource**)&surf->cb_buffer_cmask,
-                                       &rctx->dummy_cmask->b.b);
+               r600_resource_reference(&surf->cb_buffer_cmask, rctx->dummy_cmask);
 
                /* FMASK. */
                if (!rctx->dummy_fmask ||
                    rctx->dummy_fmask->b.b.width0 < fmask.size ||
                    rctx->dummy_fmask->buf->alignment % fmask.alignment != 0) {
-                       pipe_resource_reference((struct pipe_resource**)&rctx->dummy_fmask, NULL);
+                       r600_resource_reference(&rctx->dummy_fmask, NULL);
                        rctx->dummy_fmask = r600_buffer_create_helper(rscreen, fmask.size, fmask.alignment);
 
                }
-               pipe_resource_reference((struct pipe_resource**)&surf->cb_buffer_fmask,
-                                       &rctx->dummy_fmask->b.b);
+               r600_resource_reference(&surf->cb_buffer_fmask, rctx->dummy_fmask);
 
                /* Init the registers. */
                color_info |= S_0280A0_TILE_MODE(V_0280A0_FRAG_ENABLE);
@@ -1042,7 +1053,6 @@ static void r600_init_depth_surface(struct r600_context *rctx,
                break;
        case RADEON_SURF_MODE_1D:
        case RADEON_SURF_MODE_LINEAR_ALIGNED:
-       case RADEON_SURF_MODE_LINEAR:
        default:
                array_mode = V_0280A0_ARRAY_1D_TILED_THIN1;
                break;
@@ -1058,25 +1068,6 @@ static void r600_init_depth_surface(struct r600_context *rctx,
        surf->db_depth_size = S_028000_PITCH_TILE_MAX(pitch) | S_028000_SLICE_TILE_MAX(slice);
        surf->db_prefetch_limit = (rtex->surface.level[level].nblk_y / 8) - 1;
 
-       switch (surf->base.format) {
-       case PIPE_FORMAT_Z24X8_UNORM:
-       case PIPE_FORMAT_Z24_UNORM_S8_UINT:
-               surf->pa_su_poly_offset_db_fmt_cntl =
-                       S_028DF8_POLY_OFFSET_NEG_NUM_DB_BITS((char)-24);
-               break;
-       case PIPE_FORMAT_Z32_FLOAT:
-       case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
-               surf->pa_su_poly_offset_db_fmt_cntl =
-                       S_028DF8_POLY_OFFSET_NEG_NUM_DB_BITS((char)-23) |
-                       S_028DF8_POLY_OFFSET_DB_IS_FLOAT_FMT(1);
-               break;
-       case PIPE_FORMAT_Z16_UNORM:
-               surf->pa_su_poly_offset_db_fmt_cntl =
-                       S_028DF8_POLY_OFFSET_NEG_NUM_DB_BITS((char)-16);
-               break;
-       default:;
-       }
-
        /* use htile only for first level */
        if (rtex->htile_buffer && !level) {
                surf->db_htile_data_base = 0;
@@ -1098,20 +1089,17 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx,
        struct r600_texture *rtex;
        unsigned i;
 
-       if (rctx->framebuffer.state.nr_cbufs) {
-               rctx->b.flags |= R600_CONTEXT_WAIT_3D_IDLE | R600_CONTEXT_FLUSH_AND_INV;
-               rctx->b.flags |= R600_CONTEXT_FLUSH_AND_INV_CB |
-                                R600_CONTEXT_FLUSH_AND_INV_CB_META;
-       }
-       if (rctx->framebuffer.state.zsbuf) {
-               rctx->b.flags |= R600_CONTEXT_WAIT_3D_IDLE | R600_CONTEXT_FLUSH_AND_INV;
-               rctx->b.flags |= R600_CONTEXT_FLUSH_AND_INV_DB;
-
-               rtex = (struct r600_texture*)rctx->framebuffer.state.zsbuf->texture;
-               if (rctx->b.chip_class >= R700 && rtex->htile_buffer) {
-                       rctx->b.flags |= R600_CONTEXT_FLUSH_AND_INV_DB_META;
-               }
-       }
+       /* Flush TC when changing the framebuffer state, because the only
+        * client not using TC that can change textures is the framebuffer.
+        * Other places don't typically have to flush TC.
+        */
+       rctx->b.flags |= R600_CONTEXT_WAIT_3D_IDLE |
+                        R600_CONTEXT_FLUSH_AND_INV |
+                        R600_CONTEXT_FLUSH_AND_INV_CB |
+                        R600_CONTEXT_FLUSH_AND_INV_CB_META |
+                        R600_CONTEXT_FLUSH_AND_INV_DB |
+                        R600_CONTEXT_FLUSH_AND_INV_DB_META |
+                        R600_CONTEXT_INV_TEX_CACHE;
 
        /* Set the new state. */
        util_copy_framebuffer_state(&rctx->framebuffer.state, state);
@@ -1459,9 +1447,6 @@ static void r600_emit_framebuffer_state(struct r600_context *rctx, struct r600_a
                                                               RADEON_PRIO_DEPTH_BUFFER_MSAA :
                                                               RADEON_PRIO_DEPTH_BUFFER);
 
-               radeon_set_context_reg(cs, R_028DF8_PA_SU_POLY_OFFSET_DB_FMT_CNTL,
-                                      surf->pa_su_poly_offset_db_fmt_cntl);
-
                radeon_set_context_reg_seq(cs, R_028000_DB_DEPTH_SIZE, 2);
                radeon_emit(cs, surf->db_depth_size); /* R_028000_DB_DEPTH_SIZE */
                radeon_emit(cs, surf->db_depth_view); /* R_028004_DB_DEPTH_VIEW */
@@ -1567,8 +1552,8 @@ static void r600_emit_db_state(struct r600_context *rctx, struct r600_atom *atom
                radeon_set_context_reg(cs, R_028014_DB_HTILE_DATA_BASE, a->rsurf->db_htile_data_base);
                reloc_idx = radeon_add_to_buffer_list(&rctx->b, &rctx->b.gfx, rtex->htile_buffer,
                                                  RADEON_USAGE_READWRITE, RADEON_PRIO_HTILE);
-               cs->buf[cs->cdw++] = PKT3(PKT3_NOP, 0, 0);
-               cs->buf[cs->cdw++] = reloc_idx;
+               radeon_emit(cs, PKT3(PKT3_NOP, 0, 0));
+               radeon_emit(cs, reloc_idx);
        } else {
                radeon_set_context_reg(cs, R_028D24_DB_HTILE_SURFACE, 0);
        }
@@ -1978,7 +1963,7 @@ static void r600_emit_gs_rings(struct r600_context *rctx, struct r600_atom *a)
                radeon_emit(cs, PKT3(PKT3_NOP, 0, 0));
                radeon_emit(cs, radeon_add_to_buffer_list(&rctx->b, &rctx->b.gfx, rbuffer,
                                                      RADEON_USAGE_READWRITE,
-                                                     RADEON_PRIO_RINGS_STREAMOUT));
+                                                     RADEON_PRIO_SHADER_RINGS));
                radeon_set_config_reg(cs, R_008C44_SQ_ESGS_RING_SIZE,
                                state->esgs_ring.buffer_size >> 8);
 
@@ -1987,7 +1972,7 @@ static void r600_emit_gs_rings(struct r600_context *rctx, struct r600_atom *a)
                radeon_emit(cs, PKT3(PKT3_NOP, 0, 0));
                radeon_emit(cs, radeon_add_to_buffer_list(&rctx->b, &rctx->b.gfx, rbuffer,
                                                      RADEON_USAGE_READWRITE,
-                                                     RADEON_PRIO_RINGS_STREAMOUT));
+                                                     RADEON_PRIO_SHADER_RINGS));
                radeon_set_config_reg(cs, R_008C4C_SQ_GSVS_RING_SIZE,
                                state->gsvs_ring.buffer_size >> 8);
        } else {
@@ -2476,6 +2461,10 @@ void r600_update_ps_state(struct pipe_context *ctx, struct r600_pipe_shader *sha
 
                tmp = S_028644_SEMANTIC(sid);
 
+               /* D3D 9 behaviour. GL is undefined */
+               if (rshader->input[i].name == TGSI_SEMANTIC_COLOR && rshader->input[i].sid == 0)
+                       tmp |= S_028644_DEFAULT_VAL(3);
+
                if (rshader->input[i].name == TGSI_SEMANTIC_POSITION ||
                        rshader->input[i].interpolate == TGSI_INTERPOLATE_CONSTANT ||
                        (rshader->input[i].interpolate == TGSI_INTERPOLATE_COLOR &&
@@ -2829,13 +2818,12 @@ void r600_update_db_shader_control(struct r600_context * rctx)
 static inline unsigned r600_array_mode(unsigned mode)
 {
        switch (mode) {
+       default:
        case RADEON_SURF_MODE_LINEAR_ALIGNED:   return V_0280A0_ARRAY_LINEAR_ALIGNED;
                break;
        case RADEON_SURF_MODE_1D:               return V_0280A0_ARRAY_1D_TILED_THIN1;
                break;
        case RADEON_SURF_MODE_2D:               return V_0280A0_ARRAY_2D_TILED_THIN1;
-       default:
-       case RADEON_SURF_MODE_LINEAR:           return V_0280A0_ARRAY_LINEAR_GENERAL;
        }
 }
 
@@ -2863,16 +2851,13 @@ static boolean r600_dma_copy_tile(struct r600_context *rctx,
 
        dst_mode = rdst->surface.level[dst_level].mode;
        src_mode = rsrc->surface.level[src_level].mode;
-       /* downcast linear aligned to linear to simplify test */
-       src_mode = src_mode == RADEON_SURF_MODE_LINEAR_ALIGNED ? RADEON_SURF_MODE_LINEAR : src_mode;
-       dst_mode = dst_mode == RADEON_SURF_MODE_LINEAR_ALIGNED ? RADEON_SURF_MODE_LINEAR : dst_mode;
        assert(dst_mode != src_mode);
 
        y = 0;
        lbpp = util_logbase2(bpp);
        pitch_tile_max = ((pitch / bpp) / 8) - 1;
 
-       if (dst_mode == RADEON_SURF_MODE_LINEAR) {
+       if (dst_mode == RADEON_SURF_MODE_LINEAR_ALIGNED) {
                /* T2L */
                array_mode = r600_array_mode(src_mode);
                slice_tile_max = (rsrc->surface.level[src_level].nblk_x * rsrc->surface.level[src_level].nblk_y) / (8*8);
@@ -2921,7 +2906,7 @@ static boolean r600_dma_copy_tile(struct r600_context *rctx,
         */
        cheight = ((R600_DMA_COPY_MAX_SIZE_DW * 4) / pitch) & 0xfffffff8;
        ncopy = (copy_height / cheight) + !!(copy_height % cheight);
-       r600_need_dma_space(&rctx->b, ncopy * 7);
+       r600_need_dma_space(&rctx->b, ncopy * 7, &rdst->resource, &rsrc->resource);
 
        for (i = 0; i < ncopy; i++) {
                cheight = cheight > copy_height ? copy_height : cheight;
@@ -2931,19 +2916,20 @@ static boolean r600_dma_copy_tile(struct r600_context *rctx,
                                      RADEON_PRIO_SDMA_TEXTURE);
                radeon_add_to_buffer_list(&rctx->b, &rctx->b.dma, &rdst->resource, RADEON_USAGE_WRITE,
                                      RADEON_PRIO_SDMA_TEXTURE);
-               cs->buf[cs->cdw++] = DMA_PACKET(DMA_PACKET_COPY, 1, 0, size);
-               cs->buf[cs->cdw++] = base >> 8;
-               cs->buf[cs->cdw++] = (detile << 31) | (array_mode << 27) |
-                                       (lbpp << 24) | ((height - 1) << 10) |
-                                       pitch_tile_max;
-               cs->buf[cs->cdw++] = (slice_tile_max << 12) | (z << 0);
-               cs->buf[cs->cdw++] = (x << 3) | (y << 17);
-               cs->buf[cs->cdw++] = addr & 0xfffffffc;
-               cs->buf[cs->cdw++] = (addr >> 32UL) & 0xff;
+               radeon_emit(cs, DMA_PACKET(DMA_PACKET_COPY, 1, 0, size));
+               radeon_emit(cs, base >> 8);
+               radeon_emit(cs, (detile << 31) | (array_mode << 27) |
+                               (lbpp << 24) | ((height - 1) << 10) |
+                               pitch_tile_max);
+               radeon_emit(cs, (slice_tile_max << 12) | (z << 0));
+               radeon_emit(cs, (x << 3) | (y << 17));
+               radeon_emit(cs, addr & 0xfffffffc);
+               radeon_emit(cs, (addr >> 32UL) & 0xff);
                copy_height -= cheight;
                addr += cheight * pitch;
                y += cheight;
        }
+       r600_dma_emit_wait_idle(&rctx->b);
        return TRUE;
 }
 
@@ -2975,9 +2961,10 @@ static void r600_dma_copy(struct pipe_context *ctx,
                return;
        }
 
-       if (src->format != dst->format || src_box->depth > 1) {
+       if (src_box->depth > 1 ||
+           !r600_prepare_for_dma_blit(&rctx->b, rdst, dst_level, dstx, dsty,
+                                       dstz, rsrc, src_level, src_box))
                goto fallback;
-       }
 
        src_x = util_format_get_nblocksx(src->format, src_box->x);
        dst_x = util_format_get_nblocksx(src->format, dst_x);
@@ -2993,9 +2980,6 @@ static void r600_dma_copy(struct pipe_context *ctx,
 
        dst_mode = rdst->surface.level[dst_level].mode;
        src_mode = rsrc->surface.level[src_level].mode;
-       /* downcast linear aligned to linear to simplify test */
-       src_mode = src_mode == RADEON_SURF_MODE_LINEAR_ALIGNED ? RADEON_SURF_MODE_LINEAR : src_mode;
-       dst_mode = dst_mode == RADEON_SURF_MODE_LINEAR_ALIGNED ? RADEON_SURF_MODE_LINEAR : dst_mode;
 
        if (src_pitch != dst_pitch || src_box->x || dst_x || src_w != dst_w) {
                /* strict requirement on r6xx/r7xx */
@@ -3088,7 +3072,7 @@ void r600_init_state_functions(struct r600_context *rctx)
        r600_init_atom(rctx, &rctx->db_misc_state.atom, id++, r600_emit_db_misc_state, 7);
        r600_init_atom(rctx, &rctx->db_state.atom, id++, r600_emit_db_state, 11);
        r600_init_atom(rctx, &rctx->dsa_state.atom, id++, r600_emit_cso_state, 0);
-       r600_init_atom(rctx, &rctx->poly_offset_state.atom, id++, r600_emit_polygon_offset, 6);
+       r600_init_atom(rctx, &rctx->poly_offset_state.atom, id++, r600_emit_polygon_offset, 9);
        r600_init_atom(rctx, &rctx->rasterizer_state.atom, id++, r600_emit_cso_state, 0);
        r600_add_atom(rctx, &rctx->b.scissors.atom, id++);
        r600_add_atom(rctx, &rctx->b.viewports.atom, id++);