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 "freedreno_context.h"
     30 #include "freedreno_draw.h"
     31 #include "freedreno_fence.h"
     32 #include "freedreno_program.h"
     33 #include "freedreno_resource.h"
     34 #include "freedreno_texture.h"
     35 #include "freedreno_state.h"
     36 #include "freedreno_gmem.h"
     37 #include "freedreno_query.h"
     38 #include "freedreno_query_hw.h"
     39 #include "freedreno_util.h"
     40 
     41 static void
     42 fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence,
     43 		unsigned flags)
     44 {
     45 	struct fd_context *ctx = fd_context(pctx);
     46 
     47 	if (flags & PIPE_FLUSH_FENCE_FD)
     48 		ctx->batch->needs_out_fence_fd = true;
     49 
     50 	if (!ctx->screen->reorder) {
     51 		fd_batch_flush(ctx->batch, true);
     52 	} else {
     53 		fd_bc_flush(&ctx->screen->batch_cache, ctx);
     54 	}
     55 
     56 	if (fence) {
     57 		/* if there hasn't been any rendering submitted yet, we might not
     58 		 * have actually created a fence
     59 		 */
     60 		if (!ctx->last_fence || ctx->batch->needs_out_fence_fd) {
     61 			ctx->batch->needs_flush = true;
     62 			fd_gmem_render_noop(ctx->batch);
     63 			fd_batch_reset(ctx->batch);
     64 		}
     65 		fd_fence_ref(pctx->screen, fence, ctx->last_fence);
     66 	}
     67 }
     68 
     69 /**
     70  * emit marker string as payload of a no-op packet, which can be
     71  * decoded by cffdump.
     72  */
     73 static void
     74 fd_emit_string_marker(struct pipe_context *pctx, const char *string, int len)
     75 {
     76 	struct fd_context *ctx = fd_context(pctx);
     77 	struct fd_ringbuffer *ring;
     78 	const uint32_t *buf = (const void *)string;
     79 
     80 	if (!ctx->batch)
     81 		return;
     82 
     83 	ring = ctx->batch->draw;
     84 
     85 	/* max packet size is 0x3fff dwords: */
     86 	len = MIN2(len, 0x3fff * 4);
     87 
     88 	if (ctx->screen->gpu_id >= 500)
     89 		OUT_PKT7(ring, CP_NOP, align(len, 4) / 4);
     90 	else
     91 		OUT_PKT3(ring, CP_NOP, align(len, 4) / 4);
     92 	while (len >= 4) {
     93 		OUT_RING(ring, *buf);
     94 		buf++;
     95 		len -= 4;
     96 	}
     97 
     98 	/* copy remainder bytes without reading past end of input string: */
     99 	if (len > 0) {
    100 		uint32_t w = 0;
    101 		memcpy(&w, buf, len);
    102 		OUT_RING(ring, w);
    103 	}
    104 }
    105 
    106 void
    107 fd_context_destroy(struct pipe_context *pctx)
    108 {
    109 	struct fd_context *ctx = fd_context(pctx);
    110 	unsigned i;
    111 
    112 	DBG("");
    113 
    114 	if (ctx->screen->reorder)
    115 		util_queue_destroy(&ctx->flush_queue);
    116 
    117 	fd_batch_reference(&ctx->batch, NULL);  /* unref current batch */
    118 	fd_bc_invalidate_context(ctx);
    119 
    120 	fd_fence_ref(pctx->screen, &ctx->last_fence, NULL);
    121 
    122 	fd_prog_fini(pctx);
    123 	fd_hw_query_fini(pctx);
    124 
    125 	if (ctx->blitter)
    126 		util_blitter_destroy(ctx->blitter);
    127 
    128 	if (ctx->clear_rs_state)
    129 		pctx->delete_rasterizer_state(pctx, ctx->clear_rs_state);
    130 
    131 	if (ctx->primconvert)
    132 		util_primconvert_destroy(ctx->primconvert);
    133 
    134 	slab_destroy_child(&ctx->transfer_pool);
    135 
    136 	for (i = 0; i < ARRAY_SIZE(ctx->pipe); i++) {
    137 		struct fd_vsc_pipe *pipe = &ctx->pipe[i];
    138 		if (!pipe->bo)
    139 			break;
    140 		fd_bo_del(pipe->bo);
    141 	}
    142 
    143 	fd_device_del(ctx->dev);
    144 
    145 	if (fd_mesa_debug & (FD_DBG_BSTAT | FD_DBG_MSGS)) {
    146 		printf("batch_total=%u, batch_sysmem=%u, batch_gmem=%u, batch_restore=%u\n",
    147 			(uint32_t)ctx->stats.batch_total, (uint32_t)ctx->stats.batch_sysmem,
    148 			(uint32_t)ctx->stats.batch_gmem, (uint32_t)ctx->stats.batch_restore);
    149 	}
    150 
    151 	FREE(ctx);
    152 }
    153 
    154 static void
    155 fd_set_debug_callback(struct pipe_context *pctx,
    156 		const struct pipe_debug_callback *cb)
    157 {
    158 	struct fd_context *ctx = fd_context(pctx);
    159 
    160 	if (cb)
    161 		ctx->debug = *cb;
    162 	else
    163 		memset(&ctx->debug, 0, sizeof(ctx->debug));
    164 }
    165 
    166 /* TODO we could combine a few of these small buffers (solid_vbuf,
    167  * blit_texcoord_vbuf, and vsc_size_mem, into a single buffer and
    168  * save a tiny bit of memory
    169  */
    170 
    171 static struct pipe_resource *
    172 create_solid_vertexbuf(struct pipe_context *pctx)
    173 {
    174 	static const float init_shader_const[] = {
    175 			-1.000000, +1.000000, +1.000000,
    176 			+1.000000, -1.000000, +1.000000,
    177 	};
    178 	struct pipe_resource *prsc = pipe_buffer_create(pctx->screen,
    179 			PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE, sizeof(init_shader_const));
    180 	pipe_buffer_write(pctx, prsc, 0,
    181 			sizeof(init_shader_const), init_shader_const);
    182 	return prsc;
    183 }
    184 
    185 static struct pipe_resource *
    186 create_blit_texcoord_vertexbuf(struct pipe_context *pctx)
    187 {
    188 	struct pipe_resource *prsc = pipe_buffer_create(pctx->screen,
    189 			PIPE_BIND_CUSTOM, PIPE_USAGE_DYNAMIC, 16);
    190 	return prsc;
    191 }
    192 
    193 void
    194 fd_context_setup_common_vbos(struct fd_context *ctx)
    195 {
    196 	struct pipe_context *pctx = &ctx->base;
    197 
    198 	ctx->solid_vbuf = create_solid_vertexbuf(pctx);
    199 	ctx->blit_texcoord_vbuf = create_blit_texcoord_vertexbuf(pctx);
    200 
    201 	/* setup solid_vbuf_state: */
    202 	ctx->solid_vbuf_state.vtx = pctx->create_vertex_elements_state(
    203 			pctx, 1, (struct pipe_vertex_element[]){{
    204 				.vertex_buffer_index = 0,
    205 				.src_offset = 0,
    206 				.src_format = PIPE_FORMAT_R32G32B32_FLOAT,
    207 			}});
    208 	ctx->solid_vbuf_state.vertexbuf.count = 1;
    209 	ctx->solid_vbuf_state.vertexbuf.vb[0].stride = 12;
    210 	ctx->solid_vbuf_state.vertexbuf.vb[0].buffer = ctx->solid_vbuf;
    211 
    212 	/* setup blit_vbuf_state: */
    213 	ctx->blit_vbuf_state.vtx = pctx->create_vertex_elements_state(
    214 			pctx, 2, (struct pipe_vertex_element[]){{
    215 				.vertex_buffer_index = 0,
    216 				.src_offset = 0,
    217 				.src_format = PIPE_FORMAT_R32G32_FLOAT,
    218 			}, {
    219 				.vertex_buffer_index = 1,
    220 				.src_offset = 0,
    221 				.src_format = PIPE_FORMAT_R32G32B32_FLOAT,
    222 			}});
    223 	ctx->blit_vbuf_state.vertexbuf.count = 2;
    224 	ctx->blit_vbuf_state.vertexbuf.vb[0].stride = 8;
    225 	ctx->blit_vbuf_state.vertexbuf.vb[0].buffer = ctx->blit_texcoord_vbuf;
    226 	ctx->blit_vbuf_state.vertexbuf.vb[1].stride = 12;
    227 	ctx->blit_vbuf_state.vertexbuf.vb[1].buffer = ctx->solid_vbuf;
    228 }
    229 
    230 void
    231 fd_context_cleanup_common_vbos(struct fd_context *ctx)
    232 {
    233 	struct pipe_context *pctx = &ctx->base;
    234 
    235 	pctx->delete_vertex_elements_state(pctx, ctx->solid_vbuf_state.vtx);
    236 	pctx->delete_vertex_elements_state(pctx, ctx->blit_vbuf_state.vtx);
    237 
    238 	pipe_resource_reference(&ctx->solid_vbuf, NULL);
    239 	pipe_resource_reference(&ctx->blit_texcoord_vbuf, NULL);
    240 }
    241 
    242 struct pipe_context *
    243 fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen,
    244 		const uint8_t *primtypes, void *priv)
    245 {
    246 	struct fd_screen *screen = fd_screen(pscreen);
    247 	struct pipe_context *pctx;
    248 	int i;
    249 
    250 	ctx->screen = screen;
    251 
    252 	ctx->primtypes = primtypes;
    253 	ctx->primtype_mask = 0;
    254 	for (i = 0; i < PIPE_PRIM_MAX; i++)
    255 		if (primtypes[i])
    256 			ctx->primtype_mask |= (1 << i);
    257 
    258 	/* need some sane default in case state tracker doesn't
    259 	 * set some state:
    260 	 */
    261 	ctx->sample_mask = 0xffff;
    262 
    263 	pctx = &ctx->base;
    264 	pctx->screen = pscreen;
    265 	pctx->priv = priv;
    266 	pctx->flush = fd_context_flush;
    267 	pctx->emit_string_marker = fd_emit_string_marker;
    268 	pctx->set_debug_callback = fd_set_debug_callback;
    269 	pctx->create_fence_fd = fd_create_fence_fd;
    270 	pctx->fence_server_sync = fd_fence_server_sync;
    271 
    272 	/* TODO what about compute?  Ideally it creates it's own independent
    273 	 * batches per compute job (since it isn't using tiling, so no point
    274 	 * in getting involved with the re-ordering madness)..
    275 	 */
    276 	if (!screen->reorder) {
    277 		ctx->batch = fd_bc_alloc_batch(&screen->batch_cache, ctx);
    278 	}
    279 
    280 	slab_create_child(&ctx->transfer_pool, &screen->transfer_pool);
    281 
    282 	fd_draw_init(pctx);
    283 	fd_resource_context_init(pctx);
    284 	fd_query_context_init(pctx);
    285 	fd_texture_init(pctx);
    286 	fd_state_init(pctx);
    287 	fd_hw_query_init(pctx);
    288 
    289 	ctx->blitter = util_blitter_create(pctx);
    290 	if (!ctx->blitter)
    291 		goto fail;
    292 
    293 	ctx->primconvert = util_primconvert_create(pctx, ctx->primtype_mask);
    294 	if (!ctx->primconvert)
    295 		goto fail;
    296 
    297 	return pctx;
    298 
    299 fail:
    300 	pctx->destroy(pctx);
    301 	return NULL;
    302 }
    303