Home | History | Annotate | Download | only in a3xx
      1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
      2 
      3 /*
      4  * Copyright (C) 2013 Rob Clark <robclark (at) freedesktop.org>
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the next
     14  * paragraph) shall be included in all copies or substantial portions of the
     15  * Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24  *
     25  * Authors:
     26  *    Rob Clark <robclark (at) freedesktop.org>
     27  */
     28 
     29 #include "pipe/p_state.h"
     30 #include "util/u_string.h"
     31 #include "util/u_memory.h"
     32 #include "util/u_prim.h"
     33 #include "util/u_format.h"
     34 
     35 #include "freedreno_state.h"
     36 #include "freedreno_resource.h"
     37 
     38 #include "fd3_draw.h"
     39 #include "fd3_context.h"
     40 #include "fd3_emit.h"
     41 #include "fd3_program.h"
     42 #include "fd3_format.h"
     43 #include "fd3_zsa.h"
     44 
     45 static inline uint32_t
     46 add_sat(uint32_t a, int32_t b)
     47 {
     48 	int64_t ret = (uint64_t)a + (int64_t)b;
     49 	if (ret > ~0U)
     50 		return ~0U;
     51 	if (ret < 0)
     52 		return 0;
     53 	return (uint32_t)ret;
     54 }
     55 
     56 static void
     57 draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring,
     58 		struct fd3_emit *emit, unsigned index_offset)
     59 {
     60 	const struct pipe_draw_info *info = emit->info;
     61 	enum pc_di_primtype primtype = ctx->primtypes[info->mode];
     62 
     63 	fd3_emit_state(ctx, ring, emit);
     64 
     65 	if (emit->dirty & (FD_DIRTY_VTXBUF | FD_DIRTY_VTXSTATE))
     66 		fd3_emit_vertex_bufs(ring, emit);
     67 
     68 	OUT_PKT0(ring, REG_A3XX_PC_VERTEX_REUSE_BLOCK_CNTL, 1);
     69 	OUT_RING(ring, 0x0000000b);             /* PC_VERTEX_REUSE_BLOCK_CNTL */
     70 
     71 	OUT_PKT0(ring, REG_A3XX_VFD_INDEX_MIN, 4);
     72 	OUT_RING(ring, add_sat(info->min_index, info->index_bias)); /* VFD_INDEX_MIN */
     73 	OUT_RING(ring, add_sat(info->max_index, info->index_bias)); /* VFD_INDEX_MAX */
     74 	OUT_RING(ring, info->start_instance);   /* VFD_INSTANCEID_OFFSET */
     75 	OUT_RING(ring, info->index_size ? info->index_bias : info->start); /* VFD_INDEX_OFFSET */
     76 
     77 	OUT_PKT0(ring, REG_A3XX_PC_RESTART_INDEX, 1);
     78 	OUT_RING(ring, info->primitive_restart ? /* PC_RESTART_INDEX */
     79 			info->restart_index : 0xffffffff);
     80 
     81 	/* points + psize -> spritelist: */
     82 	if (ctx->rasterizer->point_size_per_vertex &&
     83 			fd3_emit_get_vp(emit)->writes_psize &&
     84 			(info->mode == PIPE_PRIM_POINTS))
     85 		primtype = DI_PT_POINTLIST_PSIZE;
     86 
     87 	fd_draw_emit(ctx->batch, ring, primtype,
     88 			emit->key.binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY,
     89 			info, index_offset);
     90 }
     91 
     92 /* fixup dirty shader state in case some "unrelated" (from the state-
     93  * tracker's perspective) state change causes us to switch to a
     94  * different variant.
     95  */
     96 static void
     97 fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key)
     98 {
     99 	struct fd3_context *fd3_ctx = fd3_context(ctx);
    100 	struct ir3_shader_key *last_key = &fd3_ctx->last_key;
    101 
    102 	if (!ir3_shader_key_equal(last_key, key)) {
    103 		if (ir3_shader_key_changes_fs(last_key, key)) {
    104 			ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= FD_DIRTY_SHADER_PROG;
    105 			ctx->dirty |= FD_DIRTY_PROG;
    106 		}
    107 
    108 		if (ir3_shader_key_changes_vs(last_key, key)) {
    109 			ctx->dirty_shader[PIPE_SHADER_VERTEX] |= FD_DIRTY_SHADER_PROG;
    110 			ctx->dirty |= FD_DIRTY_PROG;
    111 		}
    112 
    113 		fd3_ctx->last_key = *key;
    114 	}
    115 }
    116 
    117 static bool
    118 fd3_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info,
    119              unsigned index_offset)
    120 {
    121 	struct fd3_context *fd3_ctx = fd3_context(ctx);
    122 	struct fd3_emit emit = {
    123 		.debug = &ctx->debug,
    124 		.vtx  = &ctx->vtx,
    125 		.prog = &ctx->prog,
    126 		.info = info,
    127 		.key = {
    128 			.color_two_side = ctx->rasterizer->light_twoside,
    129 			.vclamp_color = ctx->rasterizer->clamp_vertex_color,
    130 			.fclamp_color = ctx->rasterizer->clamp_fragment_color,
    131 			.half_precision = ctx->in_blit &&
    132 					fd_half_precision(&ctx->batch->framebuffer),
    133 			.has_per_samp = (fd3_ctx->fsaturate || fd3_ctx->vsaturate),
    134 			.vsaturate_s = fd3_ctx->vsaturate_s,
    135 			.vsaturate_t = fd3_ctx->vsaturate_t,
    136 			.vsaturate_r = fd3_ctx->vsaturate_r,
    137 			.fsaturate_s = fd3_ctx->fsaturate_s,
    138 			.fsaturate_t = fd3_ctx->fsaturate_t,
    139 			.fsaturate_r = fd3_ctx->fsaturate_r,
    140 		},
    141 		.rasterflat = ctx->rasterizer->flatshade,
    142 		.sprite_coord_enable = ctx->rasterizer->sprite_coord_enable,
    143 		.sprite_coord_mode = ctx->rasterizer->sprite_coord_mode,
    144 	};
    145 
    146 	if (fd3_needs_manual_clipping(ctx->prog.vp, ctx->rasterizer))
    147 		emit.key.ucp_enables = ctx->rasterizer->clip_plane_enable;
    148 
    149 	fixup_shader_state(ctx, &emit.key);
    150 
    151 	unsigned dirty = ctx->dirty;
    152 
    153 	/* do regular pass first, since that is more likely to fail compiling: */
    154 
    155 	if (!(fd3_emit_get_vp(&emit) && fd3_emit_get_fp(&emit)))
    156 		return false;
    157 
    158 	emit.key.binning_pass = false;
    159 	emit.dirty = dirty;
    160 	draw_impl(ctx, ctx->batch->draw, &emit, index_offset);
    161 
    162 	/* and now binning pass: */
    163 	emit.key.binning_pass = true;
    164 	emit.dirty = dirty & ~(FD_DIRTY_BLEND);
    165 	emit.vp = NULL;   /* we changed key so need to refetch vp */
    166 	emit.fp = NULL;
    167 	draw_impl(ctx, ctx->batch->binning, &emit, index_offset);
    168 
    169 	fd_context_all_clean(ctx);
    170 
    171 	return true;
    172 }
    173 
    174 void
    175 fd3_draw_init(struct pipe_context *pctx)
    176 {
    177 	struct fd_context *ctx = fd_context(pctx);
    178 	ctx->draw_vbo = fd3_draw_vbo;
    179 }
    180