Merge remote-tracking branch 'public/master' into vulkan
[mesa.git] / src / gallium / drivers / freedreno / freedreno_state.c
1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
3 /*
4 * Copyright (C) 2012 Rob Clark <robclark@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@freedesktop.org>
27 */
28
29 #include "pipe/p_state.h"
30 #include "util/u_dual_blend.h"
31 #include "util/u_string.h"
32 #include "util/u_memory.h"
33 #include "util/u_helpers.h"
34
35 #include "freedreno_state.h"
36 #include "freedreno_context.h"
37 #include "freedreno_resource.h"
38 #include "freedreno_texture.h"
39 #include "freedreno_gmem.h"
40 #include "freedreno_util.h"
41
42 /* All the generic state handling.. In case of CSO's that are specific
43 * to the GPU version, when the bind and the delete are common they can
44 * go in here.
45 */
46
47 static void
48 fd_set_blend_color(struct pipe_context *pctx,
49 const struct pipe_blend_color *blend_color)
50 {
51 struct fd_context *ctx = fd_context(pctx);
52 ctx->blend_color = *blend_color;
53 ctx->dirty |= FD_DIRTY_BLEND_COLOR;
54 }
55
56 static void
57 fd_set_stencil_ref(struct pipe_context *pctx,
58 const struct pipe_stencil_ref *stencil_ref)
59 {
60 struct fd_context *ctx = fd_context(pctx);
61 ctx->stencil_ref =* stencil_ref;
62 ctx->dirty |= FD_DIRTY_STENCIL_REF;
63 }
64
65 static void
66 fd_set_clip_state(struct pipe_context *pctx,
67 const struct pipe_clip_state *clip)
68 {
69 struct fd_context *ctx = fd_context(pctx);
70 ctx->ucp = *clip;
71 ctx->dirty |= FD_DIRTY_UCP;
72 }
73
74 static void
75 fd_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
76 {
77 struct fd_context *ctx = fd_context(pctx);
78 ctx->sample_mask = (uint16_t)sample_mask;
79 ctx->dirty |= FD_DIRTY_SAMPLE_MASK;
80 }
81
82 /* notes from calim on #dri-devel:
83 * index==0 will be non-UBO (ie. glUniformXYZ()) all packed together padded
84 * out to vec4's
85 * I should be able to consider that I own the user_ptr until the next
86 * set_constant_buffer() call, at which point I don't really care about the
87 * previous values.
88 * index>0 will be UBO's.. well, I'll worry about that later
89 */
90 static void
91 fd_set_constant_buffer(struct pipe_context *pctx, uint shader, uint index,
92 struct pipe_constant_buffer *cb)
93 {
94 struct fd_context *ctx = fd_context(pctx);
95 struct fd_constbuf_stateobj *so = &ctx->constbuf[shader];
96
97 /* Note that the state tracker can unbind constant buffers by
98 * passing NULL here.
99 */
100 if (unlikely(!cb)) {
101 so->enabled_mask &= ~(1 << index);
102 so->dirty_mask &= ~(1 << index);
103 pipe_resource_reference(&so->cb[index].buffer, NULL);
104 return;
105 }
106
107 pipe_resource_reference(&so->cb[index].buffer, cb->buffer);
108 so->cb[index].buffer_offset = cb->buffer_offset;
109 so->cb[index].buffer_size = cb->buffer_size;
110 so->cb[index].user_buffer = cb->user_buffer;
111
112 so->enabled_mask |= 1 << index;
113 so->dirty_mask |= 1 << index;
114 ctx->dirty |= FD_DIRTY_CONSTBUF;
115 }
116
117 static void
118 fd_set_framebuffer_state(struct pipe_context *pctx,
119 const struct pipe_framebuffer_state *framebuffer)
120 {
121 struct fd_context *ctx = fd_context(pctx);
122 struct pipe_framebuffer_state *cso = &ctx->framebuffer;
123
124 DBG("%d: cbufs[0]=%p, zsbuf=%p", ctx->needs_flush,
125 framebuffer->cbufs[0], framebuffer->zsbuf);
126
127 fd_context_render(pctx);
128
129 if ((cso->width != framebuffer->width) ||
130 (cso->height != framebuffer->height))
131 ctx->needs_rb_fbd = true;
132
133 util_copy_framebuffer_state(cso, framebuffer);
134
135 ctx->dirty |= FD_DIRTY_FRAMEBUFFER;
136
137 ctx->disabled_scissor.minx = 0;
138 ctx->disabled_scissor.miny = 0;
139 ctx->disabled_scissor.maxx = cso->width;
140 ctx->disabled_scissor.maxy = cso->height;
141
142 ctx->dirty |= FD_DIRTY_SCISSOR;
143 }
144
145 static void
146 fd_set_polygon_stipple(struct pipe_context *pctx,
147 const struct pipe_poly_stipple *stipple)
148 {
149 struct fd_context *ctx = fd_context(pctx);
150 ctx->stipple = *stipple;
151 ctx->dirty |= FD_DIRTY_STIPPLE;
152 }
153
154 static void
155 fd_set_scissor_states(struct pipe_context *pctx,
156 unsigned start_slot,
157 unsigned num_scissors,
158 const struct pipe_scissor_state *scissor)
159 {
160 struct fd_context *ctx = fd_context(pctx);
161
162 ctx->scissor = *scissor;
163 ctx->dirty |= FD_DIRTY_SCISSOR;
164 }
165
166 static void
167 fd_set_viewport_states(struct pipe_context *pctx,
168 unsigned start_slot,
169 unsigned num_viewports,
170 const struct pipe_viewport_state *viewport)
171 {
172 struct fd_context *ctx = fd_context(pctx);
173 ctx->viewport = *viewport;
174 ctx->dirty |= FD_DIRTY_VIEWPORT;
175 }
176
177 static void
178 fd_set_vertex_buffers(struct pipe_context *pctx,
179 unsigned start_slot, unsigned count,
180 const struct pipe_vertex_buffer *vb)
181 {
182 struct fd_context *ctx = fd_context(pctx);
183 struct fd_vertexbuf_stateobj *so = &ctx->vtx.vertexbuf;
184 int i;
185
186 /* on a2xx, pitch is encoded in the vtx fetch instruction, so
187 * we need to mark VTXSTATE as dirty as well to trigger patching
188 * and re-emitting the vtx shader:
189 */
190 for (i = 0; i < count; i++) {
191 bool new_enabled = vb && (vb[i].buffer || vb[i].user_buffer);
192 bool old_enabled = so->vb[i].buffer || so->vb[i].user_buffer;
193 uint32_t new_stride = vb ? vb[i].stride : 0;
194 uint32_t old_stride = so->vb[i].stride;
195 if ((new_enabled != old_enabled) || (new_stride != old_stride)) {
196 ctx->dirty |= FD_DIRTY_VTXSTATE;
197 break;
198 }
199 }
200
201 util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, start_slot, count);
202 so->count = util_last_bit(so->enabled_mask);
203
204 ctx->dirty |= FD_DIRTY_VTXBUF;
205 }
206
207 static void
208 fd_set_index_buffer(struct pipe_context *pctx,
209 const struct pipe_index_buffer *ib)
210 {
211 struct fd_context *ctx = fd_context(pctx);
212
213 if (ib) {
214 pipe_resource_reference(&ctx->indexbuf.buffer, ib->buffer);
215 ctx->indexbuf.index_size = ib->index_size;
216 ctx->indexbuf.offset = ib->offset;
217 ctx->indexbuf.user_buffer = ib->user_buffer;
218 } else {
219 pipe_resource_reference(&ctx->indexbuf.buffer, NULL);
220 }
221
222 ctx->dirty |= FD_DIRTY_INDEXBUF;
223 }
224
225 static void
226 fd_blend_state_bind(struct pipe_context *pctx, void *hwcso)
227 {
228 struct fd_context *ctx = fd_context(pctx);
229 struct pipe_blend_state *cso = hwcso;
230 bool old_is_dual = ctx->blend ?
231 ctx->blend->rt[0].blend_enable && util_blend_state_is_dual(ctx->blend, 0) :
232 false;
233 bool new_is_dual = cso ?
234 cso->rt[0].blend_enable && util_blend_state_is_dual(cso, 0) :
235 false;
236 ctx->blend = hwcso;
237 ctx->dirty |= FD_DIRTY_BLEND;
238 if (old_is_dual != new_is_dual)
239 ctx->dirty |= FD_DIRTY_BLEND_DUAL;
240 }
241
242 static void
243 fd_blend_state_delete(struct pipe_context *pctx, void *hwcso)
244 {
245 FREE(hwcso);
246 }
247
248 static void
249 fd_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso)
250 {
251 struct fd_context *ctx = fd_context(pctx);
252 struct pipe_scissor_state *old_scissor = fd_context_get_scissor(ctx);
253
254 ctx->rasterizer = hwcso;
255 ctx->dirty |= FD_DIRTY_RASTERIZER;
256
257 /* if scissor enable bit changed we need to mark scissor
258 * state as dirty as well:
259 * NOTE: we can do a shallow compare, since we only care
260 * if it changed to/from &ctx->disable_scissor
261 */
262 if (old_scissor != fd_context_get_scissor(ctx))
263 ctx->dirty |= FD_DIRTY_SCISSOR;
264 }
265
266 static void
267 fd_rasterizer_state_delete(struct pipe_context *pctx, void *hwcso)
268 {
269 FREE(hwcso);
270 }
271
272 static void
273 fd_zsa_state_bind(struct pipe_context *pctx, void *hwcso)
274 {
275 struct fd_context *ctx = fd_context(pctx);
276 ctx->zsa = hwcso;
277 ctx->dirty |= FD_DIRTY_ZSA;
278 }
279
280 static void
281 fd_zsa_state_delete(struct pipe_context *pctx, void *hwcso)
282 {
283 FREE(hwcso);
284 }
285
286 static void *
287 fd_vertex_state_create(struct pipe_context *pctx, unsigned num_elements,
288 const struct pipe_vertex_element *elements)
289 {
290 struct fd_vertex_stateobj *so = CALLOC_STRUCT(fd_vertex_stateobj);
291
292 if (!so)
293 return NULL;
294
295 memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
296 so->num_elements = num_elements;
297
298 return so;
299 }
300
301 static void
302 fd_vertex_state_delete(struct pipe_context *pctx, void *hwcso)
303 {
304 FREE(hwcso);
305 }
306
307 static void
308 fd_vertex_state_bind(struct pipe_context *pctx, void *hwcso)
309 {
310 struct fd_context *ctx = fd_context(pctx);
311 ctx->vtx.vtx = hwcso;
312 ctx->dirty |= FD_DIRTY_VTXSTATE;
313 }
314
315 static struct pipe_stream_output_target *
316 fd_create_stream_output_target(struct pipe_context *pctx,
317 struct pipe_resource *prsc, unsigned buffer_offset,
318 unsigned buffer_size)
319 {
320 struct pipe_stream_output_target *target;
321
322 target = CALLOC_STRUCT(pipe_stream_output_target);
323 if (!target)
324 return NULL;
325
326 pipe_reference_init(&target->reference, 1);
327 pipe_resource_reference(&target->buffer, prsc);
328
329 target->context = pctx;
330 target->buffer_offset = buffer_offset;
331 target->buffer_size = buffer_size;
332
333 return target;
334 }
335
336 static void
337 fd_stream_output_target_destroy(struct pipe_context *pctx,
338 struct pipe_stream_output_target *target)
339 {
340 pipe_resource_reference(&target->buffer, NULL);
341 FREE(target);
342 }
343
344 static void
345 fd_set_stream_output_targets(struct pipe_context *pctx,
346 unsigned num_targets, struct pipe_stream_output_target **targets,
347 const unsigned *offsets)
348 {
349 struct fd_context *ctx = fd_context(pctx);
350 struct fd_streamout_stateobj *so = &ctx->streamout;
351 unsigned i;
352
353 debug_assert(num_targets <= ARRAY_SIZE(so->targets));
354
355 for (i = 0; i < num_targets; i++) {
356 boolean changed = targets[i] != so->targets[i];
357 boolean append = (offsets[i] == (unsigned)-1);
358
359 if (!changed && append)
360 continue;
361
362 if (!append)
363 so->offsets[i] = offsets[i];
364
365 pipe_so_target_reference(&so->targets[i], targets[i]);
366 }
367
368 for (; i < so->num_targets; i++) {
369 pipe_so_target_reference(&so->targets[i], NULL);
370 }
371
372 so->num_targets = num_targets;
373
374 ctx->dirty |= FD_DIRTY_STREAMOUT;
375 }
376
377 void
378 fd_state_init(struct pipe_context *pctx)
379 {
380 pctx->set_blend_color = fd_set_blend_color;
381 pctx->set_stencil_ref = fd_set_stencil_ref;
382 pctx->set_clip_state = fd_set_clip_state;
383 pctx->set_sample_mask = fd_set_sample_mask;
384 pctx->set_constant_buffer = fd_set_constant_buffer;
385 pctx->set_framebuffer_state = fd_set_framebuffer_state;
386 pctx->set_polygon_stipple = fd_set_polygon_stipple;
387 pctx->set_scissor_states = fd_set_scissor_states;
388 pctx->set_viewport_states = fd_set_viewport_states;
389
390 pctx->set_vertex_buffers = fd_set_vertex_buffers;
391 pctx->set_index_buffer = fd_set_index_buffer;
392
393 pctx->bind_blend_state = fd_blend_state_bind;
394 pctx->delete_blend_state = fd_blend_state_delete;
395
396 pctx->bind_rasterizer_state = fd_rasterizer_state_bind;
397 pctx->delete_rasterizer_state = fd_rasterizer_state_delete;
398
399 pctx->bind_depth_stencil_alpha_state = fd_zsa_state_bind;
400 pctx->delete_depth_stencil_alpha_state = fd_zsa_state_delete;
401
402 pctx->create_vertex_elements_state = fd_vertex_state_create;
403 pctx->delete_vertex_elements_state = fd_vertex_state_delete;
404 pctx->bind_vertex_elements_state = fd_vertex_state_bind;
405
406 pctx->create_stream_output_target = fd_create_stream_output_target;
407 pctx->stream_output_target_destroy = fd_stream_output_target_destroy;
408 pctx->set_stream_output_targets = fd_set_stream_output_targets;
409 }