lima: use imul for calculations with intrinsic src
[mesa.git] / src / gallium / drivers / lima / lima_state.c
1 /*
2 * Copyright (c) 2011-2013 Luc Verhaegen <libv@skynet.be>
3 * Copyright (c) 2017-2019 Lima Project
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 */
25
26 #include "util/u_memory.h"
27 #include "util/u_inlines.h"
28 #include "util/u_helpers.h"
29 #include "util/u_debug.h"
30
31 #include "pipe/p_state.h"
32
33 #include "lima_screen.h"
34 #include "lima_context.h"
35 #include "lima_resource.h"
36
37 static void
38 lima_set_framebuffer_state(struct pipe_context *pctx,
39 const struct pipe_framebuffer_state *framebuffer)
40 {
41 struct lima_context *ctx = lima_context(pctx);
42
43 /* submit need framebuffer info, flush before change it */
44 lima_flush(ctx);
45
46 struct lima_context_framebuffer *fb = &ctx->framebuffer;
47
48 fb->base.samples = framebuffer->samples;
49
50 fb->base.nr_cbufs = framebuffer->nr_cbufs;
51 pipe_surface_reference(&fb->base.cbufs[0], framebuffer->cbufs[0]);
52 pipe_surface_reference(&fb->base.zsbuf, framebuffer->zsbuf);
53
54 /* need align here? */
55 fb->base.width = framebuffer->width;
56 fb->base.height = framebuffer->height;
57
58 int width = align(framebuffer->width, 16) >> 4;
59 int height = align(framebuffer->height, 16) >> 4;
60 if (fb->tiled_w != width || fb->tiled_h != height) {
61 struct lima_screen *screen = lima_screen(ctx->base.screen);
62
63 fb->tiled_w = width;
64 fb->tiled_h = height;
65
66 fb->shift_h = 0;
67 fb->shift_w = 0;
68
69 int limit = screen->plb_max_blk;
70 while ((width * height) > limit) {
71 if (width >= height) {
72 width = (width + 1) >> 1;
73 fb->shift_w++;
74 } else {
75 height = (height + 1) >> 1;
76 fb->shift_h++;
77 }
78 }
79
80 fb->block_w = width;
81 fb->block_h = height;
82
83 fb->shift_min = MIN3(fb->shift_w, fb->shift_h, 2);
84
85 debug_printf("fb dim change tiled=%d/%d block=%d/%d shift=%d/%d/%d\n",
86 fb->tiled_w, fb->tiled_h, fb->block_w, fb->block_h,
87 fb->shift_w, fb->shift_h, fb->shift_min);
88 }
89
90 ctx->dirty |= LIMA_CONTEXT_DIRTY_FRAMEBUFFER;
91 }
92
93 static void
94 lima_set_polygon_stipple(struct pipe_context *pctx,
95 const struct pipe_poly_stipple *stipple)
96 {
97
98 }
99
100 static void *
101 lima_create_depth_stencil_alpha_state(struct pipe_context *pctx,
102 const struct pipe_depth_stencil_alpha_state *cso)
103 {
104 struct lima_depth_stencil_alpha_state *so;
105
106 so = CALLOC_STRUCT(lima_depth_stencil_alpha_state);
107 if (!so)
108 return NULL;
109
110 so->base = *cso;
111
112 return so;
113 }
114
115 static void
116 lima_bind_depth_stencil_alpha_state(struct pipe_context *pctx, void *hwcso)
117 {
118 struct lima_context *ctx = lima_context(pctx);
119
120 ctx->zsa = hwcso;
121 ctx->dirty |= LIMA_CONTEXT_DIRTY_ZSA;
122 }
123
124 static void
125 lima_delete_depth_stencil_alpha_state(struct pipe_context *pctx, void *hwcso)
126 {
127 FREE(hwcso);
128 }
129
130 static void *
131 lima_create_rasterizer_state(struct pipe_context *pctx,
132 const struct pipe_rasterizer_state *cso)
133 {
134 struct lima_rasterizer_state *so;
135
136 so = CALLOC_STRUCT(lima_rasterizer_state);
137 if (!so)
138 return NULL;
139
140 so->base = *cso;
141
142 return so;
143 }
144
145 static void
146 lima_bind_rasterizer_state(struct pipe_context *pctx, void *hwcso)
147 {
148 struct lima_context *ctx = lima_context(pctx);
149
150 ctx->rasterizer = hwcso;
151 ctx->dirty |= LIMA_CONTEXT_DIRTY_RASTERIZER;
152 }
153
154 static void
155 lima_delete_rasterizer_state(struct pipe_context *pctx, void *hwcso)
156 {
157 FREE(hwcso);
158 }
159
160 static void *
161 lima_create_blend_state(struct pipe_context *pctx,
162 const struct pipe_blend_state *cso)
163 {
164 struct lima_blend_state *so;
165
166 so = CALLOC_STRUCT(lima_blend_state);
167 if (!so)
168 return NULL;
169
170 so->base = *cso;
171
172 return so;
173 }
174
175 static void
176 lima_bind_blend_state(struct pipe_context *pctx, void *hwcso)
177 {
178 struct lima_context *ctx = lima_context(pctx);
179
180 ctx->blend = hwcso;
181 ctx->dirty |= LIMA_CONTEXT_DIRTY_BLEND;
182 }
183
184 static void
185 lima_delete_blend_state(struct pipe_context *pctx, void *hwcso)
186 {
187 FREE(hwcso);
188 }
189
190 static void *
191 lima_create_vertex_elements_state(struct pipe_context *pctx, unsigned num_elements,
192 const struct pipe_vertex_element *elements)
193 {
194 struct lima_vertex_element_state *so;
195
196 so = CALLOC_STRUCT(lima_vertex_element_state);
197 if (!so)
198 return NULL;
199
200 memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
201 so->num_elements = num_elements;
202
203 return so;
204 }
205
206 static void
207 lima_bind_vertex_elements_state(struct pipe_context *pctx, void *hwcso)
208 {
209 struct lima_context *ctx = lima_context(pctx);
210
211 ctx->vertex_elements = hwcso;
212 ctx->dirty |= LIMA_CONTEXT_DIRTY_VERTEX_ELEM;
213 }
214
215 static void
216 lima_delete_vertex_elements_state(struct pipe_context *pctx, void *hwcso)
217 {
218 FREE(hwcso);
219 }
220
221 static void
222 lima_set_vertex_buffers(struct pipe_context *pctx,
223 unsigned start_slot, unsigned count,
224 const struct pipe_vertex_buffer *vb)
225 {
226 struct lima_context *ctx = lima_context(pctx);
227 struct lima_context_vertex_buffer *so = &ctx->vertex_buffers;
228
229 util_set_vertex_buffers_mask(so->vb + start_slot, &so->enabled_mask,
230 vb, start_slot, count);
231 so->count = util_last_bit(so->enabled_mask);
232
233 ctx->dirty |= LIMA_CONTEXT_DIRTY_VERTEX_BUFF;
234 }
235
236 static void
237 lima_set_viewport_states(struct pipe_context *pctx,
238 unsigned start_slot,
239 unsigned num_viewports,
240 const struct pipe_viewport_state *viewport)
241 {
242 struct lima_context *ctx = lima_context(pctx);
243
244 /* reverse calculate the parameter of glViewport */
245 ctx->viewport.left = viewport->translate[0] - fabsf(viewport->scale[0]);
246 ctx->viewport.right = viewport->translate[0] + fabsf(viewport->scale[0]);
247 ctx->viewport.bottom = viewport->translate[1] - fabsf(viewport->scale[1]);
248 ctx->viewport.top = viewport->translate[1] + fabsf(viewport->scale[1]);
249
250 /* reverse calculate the parameter of glDepthRange */
251 float near, far;
252 near = viewport->translate[2] - viewport->scale[2];
253 far = viewport->translate[2] + viewport->scale[2];
254
255 ctx->viewport.near = MIN2(near, far);
256 ctx->viewport.far = MAX2(near, far);
257
258 ctx->viewport.transform = *viewport;
259 ctx->dirty |= LIMA_CONTEXT_DIRTY_VIEWPORT;
260 }
261
262 static void
263 lima_set_scissor_states(struct pipe_context *pctx,
264 unsigned start_slot,
265 unsigned num_scissors,
266 const struct pipe_scissor_state *scissor)
267 {
268 struct lima_context *ctx = lima_context(pctx);
269
270 ctx->scissor = *scissor;
271 ctx->dirty |= LIMA_CONTEXT_DIRTY_SCISSOR;
272 }
273
274 static void
275 lima_set_blend_color(struct pipe_context *pctx,
276 const struct pipe_blend_color *blend_color)
277 {
278 struct lima_context *ctx = lima_context(pctx);
279
280 ctx->blend_color = *blend_color;
281 ctx->dirty |= LIMA_CONTEXT_DIRTY_BLEND_COLOR;
282 }
283
284 static void
285 lima_set_stencil_ref(struct pipe_context *pctx,
286 const struct pipe_stencil_ref *stencil_ref)
287 {
288 struct lima_context *ctx = lima_context(pctx);
289
290 ctx->stencil_ref = *stencil_ref;
291 ctx->dirty |= LIMA_CONTEXT_DIRTY_STENCIL_REF;
292 }
293
294 static void
295 lima_set_constant_buffer(struct pipe_context *pctx,
296 enum pipe_shader_type shader, uint index,
297 const struct pipe_constant_buffer *cb)
298 {
299 struct lima_context *ctx = lima_context(pctx);
300 struct lima_context_constant_buffer *so = ctx->const_buffer + shader;
301
302 assert(index == 0);
303
304 if (unlikely(!cb)) {
305 so->buffer = NULL;
306 so->size = 0;
307 } else {
308 assert(!cb->buffer);
309
310 so->buffer = cb->user_buffer + cb->buffer_offset;
311 so->size = cb->buffer_size;
312 }
313
314 so->dirty = true;
315 ctx->dirty |= LIMA_CONTEXT_DIRTY_CONST_BUFF;
316
317 }
318
319 static void *
320 lima_create_sampler_state(struct pipe_context *pctx,
321 const struct pipe_sampler_state *cso)
322 {
323 struct lima_sampler_state *so = CALLOC_STRUCT(lima_sampler_state);
324 if (!so)
325 return NULL;
326
327 memcpy(so, cso, sizeof(*cso));
328
329 return so;
330 }
331
332 static void
333 lima_sampler_state_delete(struct pipe_context *pctx, void *sstate)
334 {
335 free(sstate);
336 }
337
338 static void
339 lima_sampler_states_bind(struct pipe_context *pctx,
340 enum pipe_shader_type shader, unsigned start,
341 unsigned nr, void **hwcso)
342 {
343 struct lima_context *ctx = lima_context(pctx);
344 struct lima_texture_stateobj *lima_tex = &ctx->tex_stateobj;
345 unsigned i;
346 unsigned new_nr = 0;
347
348 assert(start == 0);
349
350 for (i = 0; i < nr; i++) {
351 if (hwcso[i])
352 new_nr = i + 1;
353 lima_tex->samplers[i] = hwcso[i];
354 }
355
356 for (; i < lima_tex->num_samplers; i++) {
357 lima_tex->samplers[i] = NULL;
358 }
359
360 lima_tex->num_samplers = new_nr;
361 ctx->dirty |= LIMA_CONTEXT_DIRTY_TEXTURES;
362 }
363
364 static struct pipe_sampler_view *
365 lima_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
366 const struct pipe_sampler_view *cso)
367 {
368 struct lima_sampler_view *so = CALLOC_STRUCT(lima_sampler_view);
369
370 if (!so)
371 return NULL;
372
373 so->base = *cso;
374
375 pipe_reference(NULL, &prsc->reference);
376 so->base.texture = prsc;
377 so->base.reference.count = 1;
378 so->base.context = pctx;
379
380 return &so->base;
381 }
382
383 static void
384 lima_sampler_view_destroy(struct pipe_context *pctx,
385 struct pipe_sampler_view *pview)
386 {
387 struct lima_sampler_view *view = lima_sampler_view(pview);
388
389 pipe_resource_reference(&pview->texture, NULL);
390
391 free(view);
392 }
393
394 static void
395 lima_set_sampler_views(struct pipe_context *pctx,
396 enum pipe_shader_type shader,
397 unsigned start, unsigned nr,
398 struct pipe_sampler_view **views)
399 {
400 struct lima_context *ctx = lima_context(pctx);
401 struct lima_texture_stateobj *lima_tex = &ctx->tex_stateobj;
402 int i;
403 unsigned new_nr = 0;
404
405 assert(start == 0);
406
407 for (i = 0; i < nr; i++) {
408 if (views[i])
409 new_nr = i + 1;
410 pipe_sampler_view_reference(&lima_tex->textures[i], views[i]);
411 }
412
413 for (; i < lima_tex->num_textures; i++) {
414 pipe_sampler_view_reference(&lima_tex->textures[i], NULL);
415 }
416
417 lima_tex->num_textures = new_nr;
418 ctx->dirty |= LIMA_CONTEXT_DIRTY_TEXTURES;
419 }
420
421 static void
422 lima_set_sample_mask(struct pipe_context *pctx,
423 unsigned sample_mask)
424 {
425 }
426
427 void
428 lima_state_init(struct lima_context *ctx)
429 {
430 ctx->base.set_framebuffer_state = lima_set_framebuffer_state;
431 ctx->base.set_polygon_stipple = lima_set_polygon_stipple;
432 ctx->base.set_viewport_states = lima_set_viewport_states;
433 ctx->base.set_scissor_states = lima_set_scissor_states;
434 ctx->base.set_blend_color = lima_set_blend_color;
435 ctx->base.set_stencil_ref = lima_set_stencil_ref;
436
437 ctx->base.set_vertex_buffers = lima_set_vertex_buffers;
438 ctx->base.set_constant_buffer = lima_set_constant_buffer;
439
440 ctx->base.create_depth_stencil_alpha_state = lima_create_depth_stencil_alpha_state;
441 ctx->base.bind_depth_stencil_alpha_state = lima_bind_depth_stencil_alpha_state;
442 ctx->base.delete_depth_stencil_alpha_state = lima_delete_depth_stencil_alpha_state;
443
444 ctx->base.create_rasterizer_state = lima_create_rasterizer_state;
445 ctx->base.bind_rasterizer_state = lima_bind_rasterizer_state;
446 ctx->base.delete_rasterizer_state = lima_delete_rasterizer_state;
447
448 ctx->base.create_blend_state = lima_create_blend_state;
449 ctx->base.bind_blend_state = lima_bind_blend_state;
450 ctx->base.delete_blend_state = lima_delete_blend_state;
451
452 ctx->base.create_vertex_elements_state = lima_create_vertex_elements_state;
453 ctx->base.bind_vertex_elements_state = lima_bind_vertex_elements_state;
454 ctx->base.delete_vertex_elements_state = lima_delete_vertex_elements_state;
455
456 ctx->base.create_sampler_state = lima_create_sampler_state;
457 ctx->base.delete_sampler_state = lima_sampler_state_delete;
458 ctx->base.bind_sampler_states = lima_sampler_states_bind;
459
460 ctx->base.create_sampler_view = lima_create_sampler_view;
461 ctx->base.sampler_view_destroy = lima_sampler_view_destroy;
462 ctx->base.set_sampler_views = lima_set_sampler_views;
463
464 ctx->base.set_sample_mask = lima_set_sample_mask;
465 }
466
467 void
468 lima_state_fini(struct lima_context *ctx)
469 {
470 struct lima_context_vertex_buffer *so = &ctx->vertex_buffers;
471
472 util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, NULL,
473 0, ARRAY_SIZE(so->vb));
474
475 pipe_surface_reference(&ctx->framebuffer.base.cbufs[0], NULL);
476 pipe_surface_reference(&ctx->framebuffer.base.zsbuf, NULL);
477 }