Home | History | Annotate | Download | only in freedreno
      1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
      2 
      3 /*
      4  * Copyright (C) 2012 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_draw.h"
     36 #include "freedreno_context.h"
     37 #include "freedreno_state.h"
     38 #include "freedreno_resource.h"
     39 #include "freedreno_query_hw.h"
     40 #include "freedreno_util.h"
     41 
     42 static void
     43 resource_read(struct fd_batch *batch, struct pipe_resource *prsc)
     44 {
     45 	if (!prsc)
     46 		return;
     47 	fd_batch_resource_used(batch, fd_resource(prsc), false);
     48 }
     49 
     50 static void
     51 resource_written(struct fd_batch *batch, struct pipe_resource *prsc)
     52 {
     53 	if (!prsc)
     54 		return;
     55 	fd_batch_resource_used(batch, fd_resource(prsc), true);
     56 }
     57 
     58 static void
     59 fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
     60 {
     61 	struct fd_context *ctx = fd_context(pctx);
     62 	struct fd_batch *batch = ctx->batch;
     63 	struct pipe_framebuffer_state *pfb = &batch->framebuffer;
     64 	struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx);
     65 	unsigned i, prims, buffers = 0;
     66 
     67 	/* if we supported transform feedback, we'd have to disable this: */
     68 	if (((scissor->maxx - scissor->minx) *
     69 			(scissor->maxy - scissor->miny)) == 0) {
     70 		return;
     71 	}
     72 
     73 	/* TODO: push down the region versions into the tiles */
     74 	if (!fd_render_condition_check(pctx))
     75 		return;
     76 
     77 	/* emulate unsupported primitives: */
     78 	if (!fd_supported_prim(ctx, info->mode)) {
     79 		if (ctx->streamout.num_targets > 0)
     80 			debug_error("stream-out with emulated prims");
     81 		util_primconvert_save_index_buffer(ctx->primconvert, &ctx->indexbuf);
     82 		util_primconvert_save_rasterizer_state(ctx->primconvert, ctx->rasterizer);
     83 		util_primconvert_draw_vbo(ctx->primconvert, info);
     84 		return;
     85 	}
     86 
     87 	if (ctx->in_blit) {
     88 		fd_batch_reset(batch);
     89 		ctx->dirty = ~0;
     90 	}
     91 
     92 	batch->blit = ctx->in_blit;
     93 	batch->back_blit = ctx->in_shadow;
     94 
     95 	/* NOTE: needs to be before resource_written(batch->query_buf), otherwise
     96 	 * query_buf may not be created yet.
     97 	 */
     98 	fd_hw_query_set_stage(batch, batch->draw, FD_STAGE_DRAW);
     99 
    100 	/*
    101 	 * Figure out the buffers/features we need:
    102 	 */
    103 
    104 	pipe_mutex_lock(ctx->screen->lock);
    105 
    106 	if (fd_depth_enabled(ctx)) {
    107 		buffers |= FD_BUFFER_DEPTH;
    108 		resource_written(batch, pfb->zsbuf->texture);
    109 		batch->gmem_reason |= FD_GMEM_DEPTH_ENABLED;
    110 	}
    111 
    112 	if (fd_stencil_enabled(ctx)) {
    113 		buffers |= FD_BUFFER_STENCIL;
    114 		resource_written(batch, pfb->zsbuf->texture);
    115 		batch->gmem_reason |= FD_GMEM_STENCIL_ENABLED;
    116 	}
    117 
    118 	if (fd_logicop_enabled(ctx))
    119 		batch->gmem_reason |= FD_GMEM_LOGICOP_ENABLED;
    120 
    121 	for (i = 0; i < pfb->nr_cbufs; i++) {
    122 		struct pipe_resource *surf;
    123 
    124 		if (!pfb->cbufs[i])
    125 			continue;
    126 
    127 		surf = pfb->cbufs[i]->texture;
    128 
    129 		resource_written(batch, surf);
    130 		buffers |= PIPE_CLEAR_COLOR0 << i;
    131 
    132 		if (surf->nr_samples > 1)
    133 			batch->gmem_reason |= FD_GMEM_MSAA_ENABLED;
    134 
    135 		if (fd_blend_enabled(ctx, i))
    136 			batch->gmem_reason |= FD_GMEM_BLEND_ENABLED;
    137 	}
    138 
    139 	foreach_bit(i, ctx->constbuf[PIPE_SHADER_VERTEX].enabled_mask)
    140 		resource_read(batch, ctx->constbuf[PIPE_SHADER_VERTEX].cb[i].buffer);
    141 	foreach_bit(i, ctx->constbuf[PIPE_SHADER_FRAGMENT].enabled_mask)
    142 		resource_read(batch, ctx->constbuf[PIPE_SHADER_FRAGMENT].cb[i].buffer);
    143 
    144 	/* Mark VBOs as being read */
    145 	foreach_bit(i, ctx->vtx.vertexbuf.enabled_mask) {
    146 		assert(!ctx->vtx.vertexbuf.vb[i].user_buffer);
    147 		resource_read(batch, ctx->vtx.vertexbuf.vb[i].buffer);
    148 	}
    149 
    150 	/* Mark index buffer as being read */
    151 	resource_read(batch, ctx->indexbuf.buffer);
    152 
    153 	/* Mark textures as being read */
    154 	foreach_bit(i, ctx->verttex.valid_textures)
    155 		resource_read(batch, ctx->verttex.textures[i]->texture);
    156 	foreach_bit(i, ctx->fragtex.valid_textures)
    157 		resource_read(batch, ctx->fragtex.textures[i]->texture);
    158 
    159 	/* Mark streamout buffers as being written.. */
    160 	for (i = 0; i < ctx->streamout.num_targets; i++)
    161 		if (ctx->streamout.targets[i])
    162 			resource_written(batch, ctx->streamout.targets[i]->buffer);
    163 
    164 	resource_written(batch, batch->query_buf);
    165 
    166 	pipe_mutex_unlock(ctx->screen->lock);
    167 
    168 	batch->num_draws++;
    169 
    170 	prims = u_reduced_prims_for_vertices(info->mode, info->count);
    171 
    172 	ctx->stats.draw_calls++;
    173 
    174 	/* TODO prims_emitted should be clipped when the stream-out buffer is
    175 	 * not large enough.  See max_tf_vtx().. probably need to move that
    176 	 * into common code.  Although a bit more annoying since a2xx doesn't
    177 	 * use ir3 so no common way to get at the pipe_stream_output_info
    178 	 * which is needed for this calculation.
    179 	 */
    180 	if (ctx->streamout.num_targets > 0)
    181 		ctx->stats.prims_emitted += prims;
    182 	ctx->stats.prims_generated += prims;
    183 
    184 	/* any buffers that haven't been cleared yet, we need to restore: */
    185 	batch->restore |= buffers & (FD_BUFFER_ALL & ~batch->cleared);
    186 	/* and any buffers used, need to be resolved: */
    187 	batch->resolve |= buffers;
    188 
    189 	DBG("%p: %x %ux%u num_draws=%u (%s/%s)", batch, buffers,
    190 		pfb->width, pfb->height, batch->num_draws,
    191 		util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
    192 		util_format_short_name(pipe_surface_format(pfb->zsbuf)));
    193 
    194 	if (ctx->draw_vbo(ctx, info))
    195 		batch->needs_flush = true;
    196 
    197 	for (i = 0; i < ctx->streamout.num_targets; i++)
    198 		ctx->streamout.offsets[i] += info->count;
    199 
    200 	if (fd_mesa_debug & FD_DBG_DDRAW)
    201 		ctx->dirty = 0xffffffff;
    202 
    203 	fd_batch_check_size(batch);
    204 }
    205 
    206 /* Generic clear implementation (partially) using u_blitter: */
    207 static void
    208 fd_blitter_clear(struct pipe_context *pctx, unsigned buffers,
    209 		const union pipe_color_union *color, double depth, unsigned stencil)
    210 {
    211 	struct fd_context *ctx = fd_context(pctx);
    212 	struct pipe_framebuffer_state *pfb = &ctx->batch->framebuffer;
    213 	struct blitter_context *blitter = ctx->blitter;
    214 
    215 	fd_blitter_pipe_begin(ctx, false, true, FD_STAGE_CLEAR);
    216 
    217 	util_blitter_common_clear_setup(blitter, pfb->width, pfb->height,
    218 			buffers, NULL, NULL);
    219 
    220 	struct pipe_stencil_ref sr = {
    221 		.ref_value = { stencil & 0xff }
    222 	};
    223 	pctx->set_stencil_ref(pctx, &sr);
    224 
    225 	struct pipe_constant_buffer cb = {
    226 		.buffer_size = 16,
    227 		.user_buffer = &color->ui,
    228 	};
    229 	pctx->set_constant_buffer(pctx, PIPE_SHADER_FRAGMENT, 0, &cb);
    230 
    231 	if (!ctx->clear_rs_state) {
    232 		const struct pipe_rasterizer_state tmpl = {
    233 			.cull_face = PIPE_FACE_NONE,
    234 			.half_pixel_center = 1,
    235 			.bottom_edge_rule = 1,
    236 			.flatshade = 1,
    237 			.depth_clip = 1,
    238 		};
    239 		ctx->clear_rs_state = pctx->create_rasterizer_state(pctx, &tmpl);
    240 	}
    241 	pctx->bind_rasterizer_state(pctx, ctx->clear_rs_state);
    242 
    243 	struct pipe_viewport_state vp = {
    244 		.scale     = { 0.5f * pfb->width, -0.5f * pfb->height, depth },
    245 		.translate = { 0.5f * pfb->width,  0.5f * pfb->height, 0.0f },
    246 	};
    247 	pctx->set_viewport_states(pctx, 0, 1, &vp);
    248 
    249 	pctx->bind_vertex_elements_state(pctx, ctx->solid_vbuf_state.vtx);
    250 	pctx->set_vertex_buffers(pctx, blitter->vb_slot, 1,
    251 			&ctx->solid_vbuf_state.vertexbuf.vb[0]);
    252 	pctx->set_stream_output_targets(pctx, 0, NULL, NULL);
    253 	pctx->bind_vs_state(pctx, ctx->solid_prog.vp);
    254 	pctx->bind_fs_state(pctx, ctx->solid_prog.fp);
    255 
    256 	struct pipe_draw_info info = {
    257 		.mode = PIPE_PRIM_MAX,    /* maps to DI_PT_RECTLIST */
    258 		.count = 2,
    259 		.max_index = 1,
    260 		.instance_count = 1,
    261 	};
    262 	ctx->draw_vbo(ctx, &info);
    263 
    264 	util_blitter_restore_constant_buffer_state(blitter);
    265 	util_blitter_restore_vertex_states(blitter);
    266 	util_blitter_restore_fragment_states(blitter);
    267 	util_blitter_restore_render_cond(blitter);
    268 	util_blitter_unset_running_flag(blitter);
    269 
    270 	fd_blitter_pipe_end(ctx);
    271 }
    272 
    273 /* TODO figure out how to make better use of existing state mechanism
    274  * for clear (and possibly gmem->mem / mem->gmem) so we can (a) keep
    275  * track of what state really actually changes, and (b) reduce the code
    276  * in the a2xx/a3xx parts.
    277  */
    278 
    279 static void
    280 fd_clear(struct pipe_context *pctx, unsigned buffers,
    281 		const union pipe_color_union *color, double depth, unsigned stencil)
    282 {
    283 	struct fd_context *ctx = fd_context(pctx);
    284 	struct fd_batch *batch = ctx->batch;
    285 	struct pipe_framebuffer_state *pfb = &batch->framebuffer;
    286 	struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx);
    287 	unsigned cleared_buffers;
    288 	int i;
    289 
    290 	/* TODO: push down the region versions into the tiles */
    291 	if (!fd_render_condition_check(pctx))
    292 		return;
    293 
    294 	if (ctx->in_blit) {
    295 		fd_batch_reset(batch);
    296 		ctx->dirty = ~0;
    297 	}
    298 
    299 	/* for bookkeeping about which buffers have been cleared (and thus
    300 	 * can fully or partially skip mem2gmem) we need to ignore buffers
    301 	 * that have already had a draw, in case apps do silly things like
    302 	 * clear after draw (ie. if you only clear the color buffer, but
    303 	 * something like alpha-test causes side effects from the draw in
    304 	 * the depth buffer, etc)
    305 	 */
    306 	cleared_buffers = buffers & (FD_BUFFER_ALL & ~batch->restore);
    307 
    308 	/* do we have full-screen scissor? */
    309 	if (!memcmp(scissor, &ctx->disabled_scissor, sizeof(*scissor))) {
    310 		batch->cleared |= cleared_buffers;
    311 	} else {
    312 		batch->partial_cleared |= cleared_buffers;
    313 		if (cleared_buffers & PIPE_CLEAR_COLOR)
    314 			batch->cleared_scissor.color = *scissor;
    315 		if (cleared_buffers & PIPE_CLEAR_DEPTH)
    316 			batch->cleared_scissor.depth = *scissor;
    317 		if (cleared_buffers & PIPE_CLEAR_STENCIL)
    318 			batch->cleared_scissor.stencil = *scissor;
    319 	}
    320 	batch->resolve |= buffers;
    321 	batch->needs_flush = true;
    322 
    323 	pipe_mutex_lock(ctx->screen->lock);
    324 
    325 	if (buffers & PIPE_CLEAR_COLOR)
    326 		for (i = 0; i < pfb->nr_cbufs; i++)
    327 			if (buffers & (PIPE_CLEAR_COLOR0 << i))
    328 				resource_written(batch, pfb->cbufs[i]->texture);
    329 
    330 	if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) {
    331 		resource_written(batch, pfb->zsbuf->texture);
    332 		batch->gmem_reason |= FD_GMEM_CLEARS_DEPTH_STENCIL;
    333 	}
    334 
    335 	resource_written(batch, batch->query_buf);
    336 
    337 	pipe_mutex_unlock(ctx->screen->lock);
    338 
    339 	DBG("%p: %x %ux%u depth=%f, stencil=%u (%s/%s)", batch, buffers,
    340 		pfb->width, pfb->height, depth, stencil,
    341 		util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
    342 		util_format_short_name(pipe_surface_format(pfb->zsbuf)));
    343 
    344 	/* if per-gen backend doesn't implement ctx->clear() generic
    345 	 * blitter clear:
    346 	 */
    347 	if (!ctx->clear) {
    348 		fd_blitter_clear(pctx, buffers, color, depth, stencil);
    349 		return;
    350 	}
    351 
    352 	fd_hw_query_set_stage(batch, batch->draw, FD_STAGE_CLEAR);
    353 
    354 	ctx->clear(ctx, buffers, color, depth, stencil);
    355 
    356 	ctx->dirty |= FD_DIRTY_ZSA |
    357 			FD_DIRTY_VIEWPORT |
    358 			FD_DIRTY_RASTERIZER |
    359 			FD_DIRTY_SAMPLE_MASK |
    360 			FD_DIRTY_PROG |
    361 			FD_DIRTY_CONSTBUF |
    362 			FD_DIRTY_BLEND |
    363 			FD_DIRTY_FRAMEBUFFER;
    364 
    365 	if (fd_mesa_debug & FD_DBG_DCLEAR)
    366 		ctx->dirty = 0xffffffff;
    367 }
    368 
    369 static void
    370 fd_clear_render_target(struct pipe_context *pctx, struct pipe_surface *ps,
    371 		const union pipe_color_union *color,
    372 		unsigned x, unsigned y, unsigned w, unsigned h,
    373 		bool render_condition_enabled)
    374 {
    375 	DBG("TODO: x=%u, y=%u, w=%u, h=%u", x, y, w, h);
    376 }
    377 
    378 static void
    379 fd_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *ps,
    380 		unsigned buffers, double depth, unsigned stencil,
    381 		unsigned x, unsigned y, unsigned w, unsigned h,
    382 		bool render_condition_enabled)
    383 {
    384 	DBG("TODO: buffers=%u, depth=%f, stencil=%u, x=%u, y=%u, w=%u, h=%u",
    385 			buffers, depth, stencil, x, y, w, h);
    386 }
    387 
    388 void
    389 fd_draw_init(struct pipe_context *pctx)
    390 {
    391 	pctx->draw_vbo = fd_draw_vbo;
    392 	pctx->clear = fd_clear;
    393 	pctx->clear_render_target = fd_clear_render_target;
    394 	pctx->clear_depth_stencil = fd_clear_depth_stencil;
    395 }
    396