1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
4 * Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
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:
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
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
26 * Rob Clark <robclark@freedesktop.org>
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"
35 #include "freedreno_state.h"
36 #include "freedreno_resource.h"
39 #include "fd3_context.h"
41 #include "fd3_program.h"
42 #include "fd3_format.h"
45 static inline uint32_t
46 add_sat(uint32_t a
, int32_t b
)
48 int64_t ret
= (uint64_t)a
+ (int64_t)b
;
57 draw_impl(struct fd_context
*ctx
, struct fd_ringbuffer
*ring
,
58 struct fd3_emit
*emit
)
60 const struct pipe_draw_info
*info
= emit
->info
;
61 enum pc_di_primtype primtype
= ctx
->primtypes
[info
->mode
];
63 fd3_emit_state(ctx
, ring
, emit
);
65 if (emit
->dirty
& (FD_DIRTY_VTXBUF
| FD_DIRTY_VTXSTATE
))
66 fd3_emit_vertex_bufs(ring
, emit
);
68 OUT_PKT0(ring
, REG_A3XX_PC_VERTEX_REUSE_BLOCK_CNTL
, 1);
69 OUT_RING(ring
, 0x0000000b); /* PC_VERTEX_REUSE_BLOCK_CNTL */
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 */
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);
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
;
87 fd_draw_emit(ctx
->batch
, ring
, primtype
,
88 emit
->key
.binning_pass
? IGNORE_VISIBILITY
: USE_VISIBILITY
,
92 /* fixup dirty shader state in case some "unrelated" (from the state-
93 * tracker's perspective) state change causes us to switch to a
97 fixup_shader_state(struct fd_context
*ctx
, struct ir3_shader_key
*key
)
99 struct fd3_context
*fd3_ctx
= fd3_context(ctx
);
100 struct ir3_shader_key
*last_key
= &fd3_ctx
->last_key
;
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
;
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
;
113 fd3_ctx
->last_key
= *key
;
118 fd3_draw_vbo(struct fd_context
*ctx
, const struct pipe_draw_info
*info
,
119 unsigned index_offset
)
121 struct fd3_context
*fd3_ctx
= fd3_context(ctx
);
122 struct fd3_emit emit
= {
123 .debug
= &ctx
->debug
,
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
,
141 .rasterflat
= ctx
->rasterizer
->flatshade
,
142 .sprite_coord_enable
= ctx
->rasterizer
->sprite_coord_enable
,
143 .sprite_coord_mode
= ctx
->rasterizer
->sprite_coord_mode
,
146 if (fd3_needs_manual_clipping(ctx
->prog
.vp
, ctx
->rasterizer
))
147 emit
.key
.ucp_enables
= ctx
->rasterizer
->clip_plane_enable
;
149 fixup_shader_state(ctx
, &emit
.key
);
151 unsigned dirty
= ctx
->dirty
;
153 /* do regular pass first, since that is more likely to fail compiling: */
155 if (!(fd3_emit_get_vp(&emit
) && fd3_emit_get_fp(&emit
)))
158 emit
.key
.binning_pass
= false;
160 draw_impl(ctx
, ctx
->batch
->draw
, &emit
);
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 */
167 draw_impl(ctx
, ctx
->batch
->binning
, &emit
);
169 fd_context_all_clean(ctx
);
175 fd3_draw_init(struct pipe_context
*pctx
)
177 struct fd_context
*ctx
= fd_context(pctx
);
178 ctx
->draw_vbo
= fd3_draw_vbo
;