/* fixup dirty shader state in case some "unrelated" (from the state- * tracker's perspective) state change causes us to switch to a * different variant. */ static void fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key) { struct fd3_context *fd3_ctx = fd3_context(ctx); struct ir3_shader_key *last_key = &fd3_ctx->last_key; if (!ir3_shader_key_equal(last_key, key)) { ctx->dirty |= FD_DIRTY_PROG; if (last_key->has_per_samp || key->has_per_samp) { if ((last_key->vsaturate_s != key->vsaturate_s) || (last_key->vsaturate_t != key->vsaturate_t) || (last_key->vsaturate_r != key->vsaturate_r) || (last_key->vinteger_s != key->vinteger_s)) ctx->prog.dirty |= FD_SHADER_DIRTY_VP; if ((last_key->fsaturate_s != key->fsaturate_s) || (last_key->fsaturate_t != key->fsaturate_t) || (last_key->fsaturate_r != key->fsaturate_r) || (last_key->finteger_s != key->finteger_s)) ctx->prog.dirty |= FD_SHADER_DIRTY_FP; } if (last_key->color_two_side != key->color_two_side) ctx->prog.dirty |= FD_SHADER_DIRTY_FP; if (last_key->half_precision != key->half_precision) ctx->prog.dirty |= FD_SHADER_DIRTY_FP; fd3_ctx->last_key = *key; } }
static bool fd3_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, unsigned index_offset) { struct fd3_context *fd3_ctx = fd3_context(ctx); struct fd3_emit emit = { .debug = &ctx->debug, .vtx = &ctx->vtx, .prog = &ctx->prog, .info = info, .key = { .color_two_side = ctx->rasterizer->light_twoside, .vclamp_color = ctx->rasterizer->clamp_vertex_color, .fclamp_color = ctx->rasterizer->clamp_fragment_color, .half_precision = ctx->in_blit && fd_half_precision(&ctx->batch->framebuffer), .has_per_samp = (fd3_ctx->fsaturate || fd3_ctx->vsaturate), .vsaturate_s = fd3_ctx->vsaturate_s, .vsaturate_t = fd3_ctx->vsaturate_t, .vsaturate_r = fd3_ctx->vsaturate_r, .fsaturate_s = fd3_ctx->fsaturate_s, .fsaturate_t = fd3_ctx->fsaturate_t, .fsaturate_r = fd3_ctx->fsaturate_r, }, .rasterflat = ctx->rasterizer->flatshade, .sprite_coord_enable = ctx->rasterizer->sprite_coord_enable, .sprite_coord_mode = ctx->rasterizer->sprite_coord_mode, }; if (fd3_needs_manual_clipping(ctx->prog.vp, ctx->rasterizer)) emit.key.ucp_enables = ctx->rasterizer->clip_plane_enable; fixup_shader_state(ctx, &emit.key); unsigned dirty = ctx->dirty; /* do regular pass first, since that is more likely to fail compiling: */ if (!(fd3_emit_get_vp(&emit) && fd3_emit_get_fp(&emit))) return false; emit.key.binning_pass = false; emit.dirty = dirty; draw_impl(ctx, ctx->batch->draw, &emit, index_offset); /* and now binning pass: */ emit.key.binning_pass = true; emit.dirty = dirty & ~(FD_DIRTY_BLEND); emit.vp = NULL; /* we changed key so need to refetch vp */ emit.fp = NULL; draw_impl(ctx, ctx->batch->binning, &emit, index_offset); fd_context_all_clean(ctx); return true; }
/* binning pass cmds for a clear: * NOTE: newer blob drivers don't use binning for clear, which is probably * preferable since it is low vtx count. However that doesn't seem to * actually work for me. Not sure if it is depending on support for * clear pass (rather than using solid-fill shader), or something else * that newer blob is doing differently. Once that is figured out, we * can remove fd3_clear_binning(). */ static void fd3_clear_binning(struct fd_context *ctx, unsigned dirty) { struct fd3_context *fd3_ctx = fd3_context(ctx); struct fd_ringbuffer *ring = ctx->binning_ring; fd3_emit_state(ctx, ring, &ctx->solid_prog, dirty, true); fd3_emit_vertex_bufs(ring, &ctx->solid_prog, (struct fd3_vertex_buf[]) { { .prsc = fd3_ctx->solid_vbuf, .stride = 12, .format = PIPE_FORMAT_R32G32B32_FLOAT }, }, 1);
/* binning pass cmds for a clear: * NOTE: newer blob drivers don't use binning for clear, which is probably * preferable since it is low vtx count. However that doesn't seem to * actually work for me. Not sure if it is depending on support for * clear pass (rather than using solid-fill shader), or something else * that newer blob is doing differently. Once that is figured out, we * can remove fd3_clear_binning(). */ static void fd3_clear_binning(struct fd_context *ctx, unsigned dirty) { struct fd3_context *fd3_ctx = fd3_context(ctx); struct fd_ringbuffer *ring = ctx->binning_ring; struct fd3_emit emit = { .vtx = &fd3_ctx->solid_vbuf_state, .prog = &ctx->solid_prog, .key = { .binning_pass = true, .half_precision = true, }, .dirty = dirty, };
static void fd3_context_destroy(struct pipe_context *pctx) { struct fd3_context *fd3_ctx = fd3_context(fd_context(pctx)); util_dynarray_fini(&fd3_ctx->rbrc_patches); fd_bo_del(fd3_ctx->vs_pvt_mem); fd_bo_del(fd3_ctx->fs_pvt_mem); fd_bo_del(fd3_ctx->vsc_size_mem); pipe_resource_reference(&fd3_ctx->solid_vbuf, NULL); pipe_resource_reference(&fd3_ctx->blit_texcoord_vbuf, NULL); fd_context_destroy(pctx); }
static void fd3_sampler_states_bind(struct pipe_context *pctx, enum pipe_shader_type shader, unsigned start, unsigned nr, void **hwcso) { struct fd_context *ctx = fd_context(pctx); struct fd3_context *fd3_ctx = fd3_context(ctx); uint16_t saturate_s = 0, saturate_t = 0, saturate_r = 0; unsigned i; if (!hwcso) nr = 0; for (i = 0; i < nr; i++) { if (hwcso[i]) { struct fd3_sampler_stateobj *sampler = fd3_sampler_stateobj(hwcso[i]); if (sampler->saturate_s) saturate_s |= (1 << i); if (sampler->saturate_t) saturate_t |= (1 << i); if (sampler->saturate_r) saturate_r |= (1 << i); } } fd_sampler_states_bind(pctx, shader, start, nr, hwcso); if (shader == PIPE_SHADER_FRAGMENT) { fd3_ctx->fsaturate = (saturate_s != 0) || (saturate_t != 0) || (saturate_r != 0); fd3_ctx->fsaturate_s = saturate_s; fd3_ctx->fsaturate_t = saturate_t; fd3_ctx->fsaturate_r = saturate_r; } else if (shader == PIPE_SHADER_VERTEX) { fd3_ctx->vsaturate = (saturate_s != 0) || (saturate_t != 0) || (saturate_r != 0); fd3_ctx->vsaturate_s = saturate_s; fd3_ctx->vsaturate_t = saturate_t; fd3_ctx->vsaturate_r = saturate_r; } }
static void fd3_context_destroy(struct pipe_context *pctx) { struct fd3_context *fd3_ctx = fd3_context(fd_context(pctx)); fd_bo_del(fd3_ctx->vs_pvt_mem); fd_bo_del(fd3_ctx->fs_pvt_mem); fd_bo_del(fd3_ctx->vsc_size_mem); fd_context_cleanup_common_vbos(&fd3_ctx->base); u_upload_destroy(fd3_ctx->border_color_uploader); fd_hw_query_fini(pctx); fd_context_destroy(pctx); }
static void fd3_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info) { struct fd3_context *fd3_ctx = fd3_context(ctx); struct pipe_framebuffer_state *pfb = &ctx->framebuffer; struct fd3_emit emit = { .vtx = &ctx->vtx, .prog = &ctx->prog, .info = info, .key = { /* do binning pass first: */ .binning_pass = true, .color_two_side = ctx->rasterizer ? ctx->rasterizer->light_twoside : false, .alpha = util_format_is_alpha(pipe_surface_format(pfb->cbufs[0])), // TODO set .half_precision based on render target format, // ie. float16 and smaller use half, float32 use full.. .half_precision = !!(fd_mesa_debug & FD_DBG_FRAGHALF), .has_per_samp = (fd3_ctx->fsaturate || fd3_ctx->vsaturate || fd3_ctx->vinteger_s || fd3_ctx->finteger_s), .vsaturate_s = fd3_ctx->vsaturate_s, .vsaturate_t = fd3_ctx->vsaturate_t, .vsaturate_r = fd3_ctx->vsaturate_r, .fsaturate_s = fd3_ctx->fsaturate_s, .fsaturate_t = fd3_ctx->fsaturate_t, .fsaturate_r = fd3_ctx->fsaturate_r, .vinteger_s = fd3_ctx->vinteger_s, .finteger_s = fd3_ctx->finteger_s, }, .format = pipe_surface_format(pfb->cbufs[0]), .rasterflat = ctx->rasterizer && ctx->rasterizer->flatshade, }; unsigned dirty; fixup_shader_state(ctx, &emit.key); dirty = ctx->dirty; emit.dirty = dirty & ~(FD_DIRTY_BLEND); draw_impl(ctx, ctx->binning_ring, &emit); /* and now regular (non-binning) pass: */ emit.key.binning_pass = false; emit.dirty = dirty; emit.vp = NULL; /* we changed key so need to refetch vp */ draw_impl(ctx, ctx->ring, &emit); }
/* fixup dirty shader state in case some "unrelated" (from the state- * tracker's perspective) state change causes us to switch to a * different variant. */ static void fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key) { struct fd3_context *fd3_ctx = fd3_context(ctx); struct ir3_shader_key *last_key = &fd3_ctx->last_key; if (!ir3_shader_key_equal(last_key, key)) { if (ir3_shader_key_changes_fs(last_key, key)) { ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= FD_DIRTY_SHADER_PROG; ctx->dirty |= FD_DIRTY_PROG; } if (ir3_shader_key_changes_vs(last_key, key)) { ctx->dirty_shader[PIPE_SHADER_VERTEX] |= FD_DIRTY_SHADER_PROG; ctx->dirty |= FD_DIRTY_PROG; } fd3_ctx->last_key = *key; } }
static void emit_binning_workaround(struct fd_context *ctx) { struct fd3_context *fd3_ctx = fd3_context(ctx); struct fd_gmem_stateobj *gmem = &ctx->gmem; struct fd_ringbuffer *ring = ctx->ring; OUT_PKT0(ring, REG_A3XX_RB_MODE_CONTROL, 2); OUT_RING(ring, A3XX_RB_MODE_CONTROL_RENDER_MODE(RB_RESOLVE_PASS) | A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE); OUT_RING(ring, A3XX_RB_RENDER_CONTROL_BIN_WIDTH(32) | A3XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE | A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_NEVER)); OUT_PKT0(ring, REG_A3XX_RB_COPY_CONTROL, 4); OUT_RING(ring, A3XX_RB_COPY_CONTROL_MSAA_RESOLVE(MSAA_ONE) | A3XX_RB_COPY_CONTROL_MODE(0) | A3XX_RB_COPY_CONTROL_GMEM_BASE(0)); OUT_RELOC(ring, fd_resource(fd3_ctx->solid_vbuf)->bo, 0x20, 0, -1); /* RB_COPY_DEST_BASE */ OUT_RING(ring, A3XX_RB_COPY_DEST_PITCH_PITCH(128)); OUT_RING(ring, A3XX_RB_COPY_DEST_INFO_TILE(LINEAR) | A3XX_RB_COPY_DEST_INFO_FORMAT(RB_R8G8B8A8_UNORM) | A3XX_RB_COPY_DEST_INFO_SWAP(WZYX) | A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE(0xf) | A3XX_RB_COPY_DEST_INFO_ENDIAN(ENDIAN_NONE)); OUT_PKT0(ring, REG_A3XX_GRAS_SC_CONTROL, 1); OUT_RING(ring, A3XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RESOLVE_PASS) | A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) | A3XX_GRAS_SC_CONTROL_RASTER_MODE(1)); fd_wfi(ctx, ring); fd3_program_emit(ring, &ctx->solid_prog, key); fd3_emit_vertex_bufs(ring, fd3_shader_variant(ctx->solid_prog.vp, key), (struct fd3_vertex_buf[]) {{ .prsc = fd3_ctx->solid_vbuf, .stride = 12, .format = PIPE_FORMAT_R32G32B32_FLOAT, }}, 1);
static void fd3_draw(struct fd_context *ctx, const struct pipe_draw_info *info) { unsigned dirty = ctx->dirty; struct fd3_shader_key key = { /* do binning pass first: */ .binning_pass = true, .color_two_side = ctx->rasterizer ? ctx->rasterizer->light_twoside : false, // TODO set .half_precision based on render target format, // ie. float16 and smaller use half, float32 use full.. .half_precision = !!(fd_mesa_debug & FD_DBG_FRAGHALF), }; draw_impl(ctx, info, ctx->binning_ring, dirty & ~(FD_DIRTY_BLEND), key); /* and now regular (non-binning) pass: */ key.binning_pass = false; draw_impl(ctx, info, ctx->ring, dirty, key); } /* binning pass cmds for a clear: * NOTE: newer blob drivers don't use binning for clear, which is probably * preferable since it is low vtx count. However that doesn't seem to * actually work for me. Not sure if it is depending on support for * clear pass (rather than using solid-fill shader), or something else * that newer blob is doing differently. Once that is figured out, we * can remove fd3_clear_binning(). */ static void fd3_clear_binning(struct fd_context *ctx, unsigned dirty) { struct fd3_context *fd3_ctx = fd3_context(ctx); struct fd_ringbuffer *ring = ctx->binning_ring; struct fd3_shader_key key = { .binning_pass = true, .half_precision = true, }; fd3_emit_state(ctx, ring, &ctx->solid_prog, dirty, key); fd3_emit_vertex_bufs(ring, fd3_shader_variant(ctx->solid_prog.vp, key), (struct fd3_vertex_buf[]) {{ .prsc = fd3_ctx->solid_vbuf, .stride = 12, .format = PIPE_FORMAT_R32G32B32_FLOAT, }}, 1); OUT_PKT0(ring, REG_A3XX_PC_PRIM_VTX_CNTL, 1); OUT_RING(ring, A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC(0) | A3XX_PC_PRIM_VTX_CNTL_POLYMODE_FRONT_PTYPE(PC_DRAW_TRIANGLES) | A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE(PC_DRAW_TRIANGLES) | A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST); OUT_PKT0(ring, REG_A3XX_VFD_INDEX_MIN, 4); OUT_RING(ring, 0); /* VFD_INDEX_MIN */ OUT_RING(ring, 2); /* VFD_INDEX_MAX */ OUT_RING(ring, 0); /* VFD_INSTANCEID_OFFSET */ OUT_RING(ring, 0); /* VFD_INDEX_OFFSET */ OUT_PKT0(ring, REG_A3XX_PC_RESTART_INDEX, 1); OUT_RING(ring, 0xffffffff); /* PC_RESTART_INDEX */ OUT_PKT3(ring, CP_EVENT_WRITE, 1); OUT_RING(ring, PERFCOUNTER_STOP); fd_draw(ctx, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY, DI_SRC_SEL_AUTO_INDEX, 2, INDEX_SIZE_IGN, 0, 0, NULL); } static void fd3_clear(struct fd_context *ctx, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil) { struct fd3_context *fd3_ctx = fd3_context(ctx); struct fd_ringbuffer *ring = ctx->ring; unsigned dirty = ctx->dirty; unsigned ce, i; struct fd3_shader_key key = { .half_precision = true, }; dirty &= FD_DIRTY_VIEWPORT | FD_DIRTY_FRAMEBUFFER | FD_DIRTY_SCISSOR; dirty |= FD_DIRTY_PROG; fd3_clear_binning(ctx, dirty); /* emit generic state now: */ fd3_emit_state(ctx, ring, &ctx->solid_prog, dirty, key); OUT_PKT0(ring, REG_A3XX_RB_BLEND_ALPHA, 1); OUT_RING(ring, A3XX_RB_BLEND_ALPHA_UINT(0xff) | A3XX_RB_BLEND_ALPHA_FLOAT(1.0)); OUT_PKT0(ring, REG_A3XX_RB_RENDER_CONTROL, 1); OUT_RINGP(ring, A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_NEVER), &fd3_ctx->rbrc_patches); if (buffers & PIPE_CLEAR_DEPTH) { OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1); OUT_RING(ring, A3XX_RB_DEPTH_CONTROL_Z_WRITE_ENABLE | A3XX_RB_DEPTH_CONTROL_Z_ENABLE | A3XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_ALWAYS)); OUT_PKT0(ring, REG_A3XX_GRAS_CL_VPORT_ZOFFSET, 2); OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZOFFSET(0.0)); OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZSCALE(depth)); ctx->dirty |= FD_DIRTY_VIEWPORT; } else { OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1); OUT_RING(ring, A3XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_NEVER)); } if (buffers & PIPE_CLEAR_STENCIL) { OUT_PKT0(ring, REG_A3XX_RB_STENCILREFMASK, 2); OUT_RING(ring, A3XX_RB_STENCILREFMASK_STENCILREF(stencil) | A3XX_RB_STENCILREFMASK_STENCILMASK(stencil) | A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff)); OUT_RING(ring, A3XX_RB_STENCILREFMASK_STENCILREF(0) | A3XX_RB_STENCILREFMASK_STENCILMASK(0) | 0xff000000 | // XXX ??? A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff)); OUT_PKT0(ring, REG_A3XX_RB_STENCIL_CONTROL, 1); OUT_RING(ring, A3XX_RB_STENCIL_CONTROL_STENCIL_ENABLE | A3XX_RB_STENCIL_CONTROL_FUNC(FUNC_ALWAYS) | A3XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_REPLACE) | A3XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_NEVER) | A3XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP)); } else { OUT_PKT0(ring, REG_A3XX_RB_STENCILREFMASK, 2); OUT_RING(ring, A3XX_RB_STENCILREFMASK_STENCILREF(0) | A3XX_RB_STENCILREFMASK_STENCILMASK(0) | A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(0)); OUT_RING(ring, A3XX_RB_STENCILREFMASK_BF_STENCILREF(0) | A3XX_RB_STENCILREFMASK_BF_STENCILMASK(0) | A3XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(0)); OUT_PKT0(ring, REG_A3XX_RB_STENCIL_CONTROL, 1); OUT_RING(ring, A3XX_RB_STENCIL_CONTROL_FUNC(FUNC_NEVER) | A3XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_NEVER) | A3XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP)); } if (buffers & PIPE_CLEAR_COLOR) { ce = 0xf; } else { ce = 0x0; } for (i = 0; i < 4; i++) { OUT_PKT0(ring, REG_A3XX_RB_MRT_CONTROL(i), 1); OUT_RING(ring, A3XX_RB_MRT_CONTROL_ROP_CODE(ROP_COPY) | A3XX_RB_MRT_CONTROL_DITHER_MODE(DITHER_ALWAYS) | A3XX_RB_MRT_CONTROL_COMPONENT_ENABLE(ce)); OUT_PKT0(ring, REG_A3XX_RB_MRT_BLEND_CONTROL(i), 1); OUT_RING(ring, A3XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(FACTOR_ONE) | A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(BLEND_DST_PLUS_SRC) | A3XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(FACTOR_ZERO) | A3XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(FACTOR_ONE) | A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(BLEND_DST_PLUS_SRC) | A3XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(FACTOR_ZERO) | A3XX_RB_MRT_BLEND_CONTROL_CLAMP_ENABLE); } OUT_PKT0(ring, REG_A3XX_GRAS_SU_MODE_CONTROL, 1); OUT_RING(ring, A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(0)); fd3_emit_vertex_bufs(ring, fd3_shader_variant(ctx->solid_prog.vp, key), (struct fd3_vertex_buf[]) {{ .prsc = fd3_ctx->solid_vbuf, .stride = 12, .format = PIPE_FORMAT_R32G32B32_FLOAT, }}, 1); fd_wfi(ctx, ring); fd3_emit_constant(ring, SB_FRAG_SHADER, 0, 0, 4, color->ui, NULL); OUT_PKT0(ring, REG_A3XX_PC_PRIM_VTX_CNTL, 1); OUT_RING(ring, A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC(0) | A3XX_PC_PRIM_VTX_CNTL_POLYMODE_FRONT_PTYPE(PC_DRAW_TRIANGLES) | A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE(PC_DRAW_TRIANGLES) | A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST); OUT_PKT0(ring, REG_A3XX_VFD_INDEX_MIN, 4); OUT_RING(ring, 0); /* VFD_INDEX_MIN */ OUT_RING(ring, 2); /* VFD_INDEX_MAX */ OUT_RING(ring, 0); /* VFD_INSTANCEID_OFFSET */ OUT_RING(ring, 0); /* VFD_INDEX_OFFSET */ OUT_PKT0(ring, REG_A3XX_PC_RESTART_INDEX, 1); OUT_RING(ring, 0xffffffff); /* PC_RESTART_INDEX */ OUT_PKT3(ring, CP_EVENT_WRITE, 1); OUT_RING(ring, PERFCOUNTER_STOP); fd_draw(ctx, ring, DI_PT_RECTLIST, USE_VISIBILITY, DI_SRC_SEL_AUTO_INDEX, 2, INDEX_SIZE_IGN, 0, 0, NULL); } void fd3_draw_init(struct pipe_context *pctx) { struct fd_context *ctx = fd_context(pctx); ctx->draw = fd3_draw; ctx->clear = fd3_clear; }
emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring, enum adreno_state_block sb, struct fd_texture_stateobj *tex) { static const unsigned tex_off[] = { [SB_VERT_TEX] = VERT_TEX_OFF, [SB_FRAG_TEX] = FRAG_TEX_OFF, }; static const enum adreno_state_block mipaddr[] = { [SB_VERT_TEX] = SB_VERT_MIPADDR, [SB_FRAG_TEX] = SB_FRAG_MIPADDR, }; static const uint32_t bcolor_reg[] = { [SB_VERT_TEX] = REG_A3XX_TPL1_TP_VS_BORDER_COLOR_BASE_ADDR, [SB_FRAG_TEX] = REG_A3XX_TPL1_TP_FS_BORDER_COLOR_BASE_ADDR, }; struct fd3_context *fd3_ctx = fd3_context(ctx); bool needs_border = false; unsigned i, j; if (tex->num_samplers > 0) { /* output sampler state: */ OUT_PKT3(ring, CP_LOAD_STATE, 2 + (2 * tex->num_samplers)); OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(tex_off[sb]) | CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) | CP_LOAD_STATE_0_STATE_BLOCK(sb) | CP_LOAD_STATE_0_NUM_UNIT(tex->num_samplers)); OUT_RING(ring, CP_LOAD_STATE_1_STATE_TYPE(ST_SHADER) | CP_LOAD_STATE_1_EXT_SRC_ADDR(0)); for (i = 0; i < tex->num_samplers; i++) { static const struct fd3_sampler_stateobj dummy_sampler = {}; const struct fd3_sampler_stateobj *sampler = tex->samplers[i] ?
static void fd3_emit_tile_gmem2mem(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, uint32_t bin_w, uint32_t bin_h) { struct fd3_context *fd3_ctx = fd3_context(ctx); struct fd_ringbuffer *ring = ctx->ring; struct pipe_framebuffer_state *pfb = &ctx->framebuffer; OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1); OUT_RING(ring, A3XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_NEVER)); OUT_PKT0(ring, REG_A3XX_RB_STENCIL_CONTROL, 1); OUT_RING(ring, A3XX_RB_STENCIL_CONTROL_FUNC(FUNC_NEVER) | A3XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_NEVER) | A3XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP)); OUT_PKT0(ring, REG_A3XX_RB_STENCILREFMASK, 2); OUT_RING(ring, 0xff000000 | A3XX_RB_STENCILREFMASK_STENCILREF(0) | A3XX_RB_STENCILREFMASK_STENCILMASK(0) | A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff)); OUT_RING(ring, 0xff000000 | A3XX_RB_STENCILREFMASK_STENCILREF(0) | A3XX_RB_STENCILREFMASK_STENCILMASK(0) | A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff)); OUT_PKT0(ring, REG_A3XX_GRAS_SU_MODE_CONTROL, 1); OUT_RING(ring, A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(0)); OUT_PKT0(ring, REG_A3XX_GRAS_CL_CLIP_CNTL, 1); OUT_RING(ring, 0x00000000); /* GRAS_CL_CLIP_CNTL */ OUT_PKT0(ring, REG_A3XX_GRAS_CL_VPORT_XOFFSET, 6); OUT_RING(ring, A3XX_GRAS_CL_VPORT_XOFFSET((float)pfb->width/2.0 - 0.5)); OUT_RING(ring, A3XX_GRAS_CL_VPORT_XSCALE((float)pfb->width/2.0)); OUT_RING(ring, A3XX_GRAS_CL_VPORT_YOFFSET((float)pfb->height/2.0 - 0.5)); OUT_RING(ring, A3XX_GRAS_CL_VPORT_YSCALE(-(float)pfb->height/2.0)); OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZOFFSET(0.0)); OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZSCALE(1.0)); OUT_PKT0(ring, REG_A3XX_RB_MODE_CONTROL, 1); OUT_RING(ring, A3XX_RB_MODE_CONTROL_RENDER_MODE(RB_RESOLVE_PASS) | A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE); fd3_emit_rbrc_draw_state(ring, A3XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE | A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_NEVER)); OUT_PKT0(ring, REG_A3XX_GRAS_SC_CONTROL, 1); OUT_RING(ring, A3XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RESOLVE_PASS) | A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) | A3XX_GRAS_SC_CONTROL_RASTER_MODE(1)); OUT_PKT0(ring, REG_A3XX_PC_PRIM_VTX_CNTL, 1); OUT_RING(ring, A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC(0) | A3XX_PC_PRIM_VTX_CNTL_POLYMODE_FRONT_PTYPE(PC_DRAW_TRIANGLES) | A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE(PC_DRAW_TRIANGLES) | A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST); OUT_PKT0(ring, REG_A3XX_GRAS_SC_WINDOW_SCISSOR_TL, 2); OUT_RING(ring, A3XX_GRAS_SC_WINDOW_SCISSOR_TL_X(0) | A3XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(0)); OUT_RING(ring, A3XX_GRAS_SC_WINDOW_SCISSOR_BR_X(pfb->width - 1) | A3XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(pfb->height - 1)); OUT_PKT0(ring, REG_A3XX_VFD_INDEX_MIN, 4); OUT_RING(ring, 0); /* VFD_INDEX_MIN */ OUT_RING(ring, 2); /* VFD_INDEX_MAX */ OUT_RING(ring, 0); /* VFD_INSTANCEID_OFFSET */ OUT_RING(ring, 0); /* VFD_INDEX_OFFSET */ fd3_program_emit(ring, &ctx->solid_prog); fd3_emit_vertex_bufs(ring, &ctx->solid_prog, (struct fd3_vertex_buf[]) { { .prsc = fd3_ctx->solid_vbuf, .stride = 12, .format = PIPE_FORMAT_R32G32B32_FLOAT }, }, 1);
static void fd3_clear(struct fd_context *ctx, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil) { struct fd3_context *fd3_ctx = fd3_context(ctx); struct fd_ringbuffer *ring = ctx->ring; unsigned ce, i; /* emit generic state now: */ fd3_emit_state(ctx, ctx->dirty & (FD_DIRTY_VIEWPORT | FD_DIRTY_FRAMEBUFFER | FD_DIRTY_SCISSOR)); OUT_PKT0(ring, REG_A3XX_RB_BLEND_ALPHA, 1); OUT_RING(ring, A3XX_RB_BLEND_ALPHA_UINT(0xff) | A3XX_RB_BLEND_ALPHA_FLOAT(1.0)); fd3_emit_rbrc_draw_state(ring, A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_NEVER)); if (buffers & PIPE_CLEAR_DEPTH) { OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1); OUT_RING(ring, A3XX_RB_DEPTH_CONTROL_Z_WRITE_ENABLE | A3XX_RB_DEPTH_CONTROL_Z_ENABLE | A3XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_ALWAYS)); OUT_PKT0(ring, REG_A3XX_GRAS_CL_VPORT_ZOFFSET, 2); OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZOFFSET(0.0)); OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZSCALE(depth)); ctx->dirty |= FD_DIRTY_VIEWPORT; } else { OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1); OUT_RING(ring, A3XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_NEVER)); } if (buffers & PIPE_CLEAR_STENCIL) { OUT_PKT0(ring, REG_A3XX_RB_STENCILREFMASK, 2); OUT_RING(ring, A3XX_RB_STENCILREFMASK_STENCILREF(stencil) | A3XX_RB_STENCILREFMASK_STENCILMASK(stencil) | A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff)); OUT_RING(ring, A3XX_RB_STENCILREFMASK_STENCILREF(0) | A3XX_RB_STENCILREFMASK_STENCILMASK(0) | 0xff000000 | // XXX ??? A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff)); OUT_PKT0(ring, REG_A3XX_RB_STENCIL_CONTROL, 1); OUT_RING(ring, A3XX_RB_STENCIL_CONTROL_STENCIL_ENABLE | A3XX_RB_STENCIL_CONTROL_FUNC(FUNC_ALWAYS) | A3XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_REPLACE) | A3XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_NEVER) | A3XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP)); } else { OUT_PKT0(ring, REG_A3XX_RB_STENCILREFMASK, 2); OUT_RING(ring, A3XX_RB_STENCILREFMASK_STENCILREF(0) | A3XX_RB_STENCILREFMASK_STENCILMASK(0) | A3XX_RB_STENCILREFMASK_STENCILWRITEMASK(0)); OUT_RING(ring, A3XX_RB_STENCILREFMASK_BF_STENCILREF(0) | A3XX_RB_STENCILREFMASK_BF_STENCILMASK(0) | A3XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(0)); OUT_PKT0(ring, REG_A3XX_RB_STENCIL_CONTROL, 1); OUT_RING(ring, A3XX_RB_STENCIL_CONTROL_FUNC(FUNC_NEVER) | A3XX_RB_STENCIL_CONTROL_FAIL(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZPASS(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZFAIL(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_FUNC_BF(FUNC_NEVER) | A3XX_RB_STENCIL_CONTROL_FAIL_BF(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) | A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP)); } if (buffers & PIPE_CLEAR_COLOR) { ce = 0xf; } else { ce = 0x0; } for (i = 0; i < 4; i++) { OUT_PKT0(ring, REG_A3XX_RB_MRT_CONTROL(i), 1); OUT_RING(ring, A3XX_RB_MRT_CONTROL_ROP_CODE(12) | A3XX_RB_MRT_CONTROL_DITHER_MODE(DITHER_ALWAYS) | A3XX_RB_MRT_CONTROL_COMPONENT_ENABLE(ce)); OUT_PKT0(ring, REG_A3XX_RB_MRT_BLEND_CONTROL(i), 1); OUT_RING(ring, A3XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(FACTOR_ONE) | A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(BLEND_DST_PLUS_SRC) | A3XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(FACTOR_ZERO) | A3XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(FACTOR_ONE) | A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(BLEND_DST_PLUS_SRC) | A3XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(FACTOR_ZERO) | A3XX_RB_MRT_BLEND_CONTROL_CLAMP_ENABLE); } OUT_PKT0(ring, REG_A3XX_GRAS_SU_MODE_CONTROL, 1); OUT_RING(ring, A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(0)); fd3_program_emit(ring, &ctx->solid_prog); fd3_emit_vertex_bufs(ring, &ctx->solid_prog, (struct fd3_vertex_buf[]) { { .prsc = fd3_ctx->solid_vbuf, .stride = 12, .format = PIPE_FORMAT_R32G32B32_FLOAT }, }, 1);