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/format/u_format.h"
27 #include "util/u_memory.h"
28 #include "util/u_inlines.h"
29 #include "util/u_helpers.h"
30 #include "util/u_debug.h"
31 #include "util/u_framebuffer.h"
32 #include "util/u_viewport.h"
33
34 #include "pipe/p_state.h"
35
36 #include "lima_screen.h"
37 #include "lima_context.h"
38 #include "lima_format.h"
39 #include "lima_resource.h"
40
41 static void
lima_set_framebuffer_state(struct pipe_context * pctx,const struct pipe_framebuffer_state * framebuffer)42 lima_set_framebuffer_state(struct pipe_context *pctx,
43 const struct pipe_framebuffer_state *framebuffer)
44 {
45 struct lima_context *ctx = lima_context(pctx);
46
47 /* make sure there are always single job in this context */
48 if (lima_debug & LIMA_DEBUG_SINGLE_JOB)
49 lima_flush(ctx);
50
51 struct lima_context_framebuffer *fb = &ctx->framebuffer;
52
53 util_copy_framebuffer_state(&fb->base, framebuffer);
54
55 ctx->job = NULL;
56 ctx->dirty |= LIMA_CONTEXT_DIRTY_FRAMEBUFFER;
57 }
58
59 static void
lima_set_polygon_stipple(struct pipe_context * pctx,const struct pipe_poly_stipple * stipple)60 lima_set_polygon_stipple(struct pipe_context *pctx,
61 const struct pipe_poly_stipple *stipple)
62 {
63
64 }
65
66 static void *
lima_create_depth_stencil_alpha_state(struct pipe_context * pctx,const struct pipe_depth_stencil_alpha_state * cso)67 lima_create_depth_stencil_alpha_state(struct pipe_context *pctx,
68 const struct pipe_depth_stencil_alpha_state *cso)
69 {
70 struct lima_depth_stencil_alpha_state *so;
71
72 so = CALLOC_STRUCT(lima_depth_stencil_alpha_state);
73 if (!so)
74 return NULL;
75
76 so->base = *cso;
77
78 return so;
79 }
80
81 static void
lima_bind_depth_stencil_alpha_state(struct pipe_context * pctx,void * hwcso)82 lima_bind_depth_stencil_alpha_state(struct pipe_context *pctx, void *hwcso)
83 {
84 struct lima_context *ctx = lima_context(pctx);
85
86 ctx->zsa = hwcso;
87 ctx->dirty |= LIMA_CONTEXT_DIRTY_ZSA;
88 }
89
90 static void
lima_delete_depth_stencil_alpha_state(struct pipe_context * pctx,void * hwcso)91 lima_delete_depth_stencil_alpha_state(struct pipe_context *pctx, void *hwcso)
92 {
93 FREE(hwcso);
94 }
95
96 static void *
lima_create_rasterizer_state(struct pipe_context * pctx,const struct pipe_rasterizer_state * cso)97 lima_create_rasterizer_state(struct pipe_context *pctx,
98 const struct pipe_rasterizer_state *cso)
99 {
100 struct lima_rasterizer_state *so;
101
102 so = CALLOC_STRUCT(lima_rasterizer_state);
103 if (!so)
104 return NULL;
105
106 so->base = *cso;
107
108 return so;
109 }
110
111 static void
lima_bind_rasterizer_state(struct pipe_context * pctx,void * hwcso)112 lima_bind_rasterizer_state(struct pipe_context *pctx, void *hwcso)
113 {
114 struct lima_context *ctx = lima_context(pctx);
115
116 ctx->rasterizer = hwcso;
117 ctx->dirty |= LIMA_CONTEXT_DIRTY_RASTERIZER;
118 }
119
120 static void
lima_delete_rasterizer_state(struct pipe_context * pctx,void * hwcso)121 lima_delete_rasterizer_state(struct pipe_context *pctx, void *hwcso)
122 {
123 FREE(hwcso);
124 }
125
126 static void *
lima_create_blend_state(struct pipe_context * pctx,const struct pipe_blend_state * cso)127 lima_create_blend_state(struct pipe_context *pctx,
128 const struct pipe_blend_state *cso)
129 {
130 struct lima_blend_state *so;
131
132 so = CALLOC_STRUCT(lima_blend_state);
133 if (!so)
134 return NULL;
135
136 so->base = *cso;
137
138 return so;
139 }
140
141 static void
lima_bind_blend_state(struct pipe_context * pctx,void * hwcso)142 lima_bind_blend_state(struct pipe_context *pctx, void *hwcso)
143 {
144 struct lima_context *ctx = lima_context(pctx);
145
146 ctx->blend = hwcso;
147 ctx->dirty |= LIMA_CONTEXT_DIRTY_BLEND;
148 }
149
150 static void
lima_delete_blend_state(struct pipe_context * pctx,void * hwcso)151 lima_delete_blend_state(struct pipe_context *pctx, void *hwcso)
152 {
153 FREE(hwcso);
154 }
155
156 static void *
lima_create_vertex_elements_state(struct pipe_context * pctx,unsigned num_elements,const struct pipe_vertex_element * elements)157 lima_create_vertex_elements_state(struct pipe_context *pctx, unsigned num_elements,
158 const struct pipe_vertex_element *elements)
159 {
160 struct lima_vertex_element_state *so;
161
162 so = CALLOC_STRUCT(lima_vertex_element_state);
163 if (!so)
164 return NULL;
165
166 memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
167 so->num_elements = num_elements;
168
169 return so;
170 }
171
172 static void
lima_bind_vertex_elements_state(struct pipe_context * pctx,void * hwcso)173 lima_bind_vertex_elements_state(struct pipe_context *pctx, void *hwcso)
174 {
175 struct lima_context *ctx = lima_context(pctx);
176
177 ctx->vertex_elements = hwcso;
178 ctx->dirty |= LIMA_CONTEXT_DIRTY_VERTEX_ELEM;
179 }
180
181 static void
lima_delete_vertex_elements_state(struct pipe_context * pctx,void * hwcso)182 lima_delete_vertex_elements_state(struct pipe_context *pctx, void *hwcso)
183 {
184 FREE(hwcso);
185 }
186
187 static void
lima_set_vertex_buffers(struct pipe_context * pctx,unsigned start_slot,unsigned count,unsigned unbind_num_trailing_slots,bool take_ownership,const struct pipe_vertex_buffer * vb)188 lima_set_vertex_buffers(struct pipe_context *pctx,
189 unsigned start_slot, unsigned count,
190 unsigned unbind_num_trailing_slots,
191 bool take_ownership,
192 const struct pipe_vertex_buffer *vb)
193 {
194 struct lima_context *ctx = lima_context(pctx);
195 struct lima_context_vertex_buffer *so = &ctx->vertex_buffers;
196
197 util_set_vertex_buffers_mask(so->vb, &so->enabled_mask,
198 vb, start_slot, count,
199 unbind_num_trailing_slots,
200 take_ownership);
201 so->count = util_last_bit(so->enabled_mask);
202
203 ctx->dirty |= LIMA_CONTEXT_DIRTY_VERTEX_BUFF;
204 }
205
206 static void
lima_set_viewport_states(struct pipe_context * pctx,unsigned start_slot,unsigned num_viewports,const struct pipe_viewport_state * viewport)207 lima_set_viewport_states(struct pipe_context *pctx,
208 unsigned start_slot,
209 unsigned num_viewports,
210 const struct pipe_viewport_state *viewport)
211 {
212 struct lima_context *ctx = lima_context(pctx);
213
214 /* reverse calculate the parameter of glViewport */
215 ctx->viewport.left = ctx->ext_viewport.left =
216 viewport->translate[0] - fabsf(viewport->scale[0]);
217 ctx->viewport.right = ctx->ext_viewport.right =
218 viewport->translate[0] + fabsf(viewport->scale[0]);
219 ctx->viewport.bottom = ctx->ext_viewport.bottom =
220 viewport->translate[1] - fabsf(viewport->scale[1]);
221 ctx->viewport.top = ctx->ext_viewport.top =
222 viewport->translate[1] + fabsf(viewport->scale[1]);
223
224 /* reverse calculate the parameter of glDepthRange */
225 float near, far;
226 bool halfz = ctx->rasterizer && ctx->rasterizer->base.clip_halfz;
227 util_viewport_zmin_zmax(viewport, halfz, &near, &far);
228
229 ctx->viewport.near = ctx->rasterizer && ctx->rasterizer->base.depth_clip_near ? near : 0.0f;
230 ctx->viewport.far = ctx->rasterizer && ctx->rasterizer->base.depth_clip_far ? far : 1.0f;
231
232 ctx->viewport.transform = *viewport;
233 ctx->dirty |= LIMA_CONTEXT_DIRTY_VIEWPORT;
234 }
235
236 static void
lima_set_scissor_states(struct pipe_context * pctx,unsigned start_slot,unsigned num_scissors,const struct pipe_scissor_state * scissor)237 lima_set_scissor_states(struct pipe_context *pctx,
238 unsigned start_slot,
239 unsigned num_scissors,
240 const struct pipe_scissor_state *scissor)
241 {
242 struct lima_context *ctx = lima_context(pctx);
243
244 ctx->scissor = *scissor;
245 ctx->dirty |= LIMA_CONTEXT_DIRTY_SCISSOR;
246 }
247
248 static void
lima_set_blend_color(struct pipe_context * pctx,const struct pipe_blend_color * blend_color)249 lima_set_blend_color(struct pipe_context *pctx,
250 const struct pipe_blend_color *blend_color)
251 {
252 struct lima_context *ctx = lima_context(pctx);
253
254 ctx->blend_color = *blend_color;
255 ctx->dirty |= LIMA_CONTEXT_DIRTY_BLEND_COLOR;
256 }
257
258 static void
lima_set_stencil_ref(struct pipe_context * pctx,const struct pipe_stencil_ref stencil_ref)259 lima_set_stencil_ref(struct pipe_context *pctx,
260 const struct pipe_stencil_ref stencil_ref)
261 {
262 struct lima_context *ctx = lima_context(pctx);
263
264 ctx->stencil_ref = stencil_ref;
265 ctx->dirty |= LIMA_CONTEXT_DIRTY_STENCIL_REF;
266 }
267
268 static void
lima_set_clip_state(struct pipe_context * pctx,const struct pipe_clip_state * clip)269 lima_set_clip_state(struct pipe_context *pctx,
270 const struct pipe_clip_state *clip)
271 {
272 struct lima_context *ctx = lima_context(pctx);
273 ctx->clip = *clip;
274
275 ctx->dirty |= LIMA_CONTEXT_DIRTY_CLIP;
276 }
277
278 static void
lima_set_constant_buffer(struct pipe_context * pctx,enum pipe_shader_type shader,uint index,bool pass_reference,const struct pipe_constant_buffer * cb)279 lima_set_constant_buffer(struct pipe_context *pctx,
280 enum pipe_shader_type shader, uint index,
281 bool pass_reference,
282 const struct pipe_constant_buffer *cb)
283 {
284 struct lima_context *ctx = lima_context(pctx);
285 struct lima_context_constant_buffer *so = ctx->const_buffer + shader;
286
287 assert(index == 0);
288
289 if (unlikely(!cb)) {
290 so->buffer = NULL;
291 so->size = 0;
292 } else {
293 assert(!cb->buffer);
294
295 so->buffer = cb->user_buffer + cb->buffer_offset;
296 so->size = cb->buffer_size;
297 }
298
299 so->dirty = true;
300 ctx->dirty |= LIMA_CONTEXT_DIRTY_CONST_BUFF;
301
302 }
303
304 static void *
lima_create_sampler_state(struct pipe_context * pctx,const struct pipe_sampler_state * cso)305 lima_create_sampler_state(struct pipe_context *pctx,
306 const struct pipe_sampler_state *cso)
307 {
308 struct lima_sampler_state *so = CALLOC_STRUCT(lima_sampler_state);
309 if (!so)
310 return NULL;
311
312 memcpy(so, cso, sizeof(*cso));
313
314 return so;
315 }
316
317 static void
lima_sampler_state_delete(struct pipe_context * pctx,void * sstate)318 lima_sampler_state_delete(struct pipe_context *pctx, void *sstate)
319 {
320 free(sstate);
321 }
322
323 static void
lima_sampler_states_bind(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start,unsigned nr,void ** hwcso)324 lima_sampler_states_bind(struct pipe_context *pctx,
325 enum pipe_shader_type shader, unsigned start,
326 unsigned nr, void **hwcso)
327 {
328 struct lima_context *ctx = lima_context(pctx);
329 struct lima_texture_stateobj *lima_tex = &ctx->tex_stateobj;
330 unsigned i;
331 unsigned new_nr = 0;
332
333 assert(start == 0);
334
335 for (i = 0; i < nr; i++) {
336 if (hwcso[i])
337 new_nr = i + 1;
338 lima_tex->samplers[i] = hwcso[i];
339 }
340
341 for (; i < lima_tex->num_samplers; i++) {
342 lima_tex->samplers[i] = NULL;
343 }
344
345 lima_tex->num_samplers = new_nr;
346 ctx->dirty |= LIMA_CONTEXT_DIRTY_TEXTURES;
347 }
348
349 static struct pipe_sampler_view *
lima_create_sampler_view(struct pipe_context * pctx,struct pipe_resource * prsc,const struct pipe_sampler_view * cso)350 lima_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
351 const struct pipe_sampler_view *cso)
352 {
353 struct lima_sampler_view *so = CALLOC_STRUCT(lima_sampler_view);
354
355 if (!so)
356 return NULL;
357
358 so->base = *cso;
359
360 pipe_reference(NULL, &prsc->reference);
361 so->base.texture = prsc;
362 so->base.reference.count = 1;
363 so->base.context = pctx;
364
365 uint8_t sampler_swizzle[4] = { cso->swizzle_r, cso->swizzle_g,
366 cso->swizzle_b, cso->swizzle_a };
367 const uint8_t *format_swizzle = lima_format_get_texel_swizzle(cso->format);
368 util_format_compose_swizzles(format_swizzle, sampler_swizzle, so->swizzle);
369
370 return &so->base;
371 }
372
373 static void
lima_sampler_view_destroy(struct pipe_context * pctx,struct pipe_sampler_view * pview)374 lima_sampler_view_destroy(struct pipe_context *pctx,
375 struct pipe_sampler_view *pview)
376 {
377 struct lima_sampler_view *view = lima_sampler_view(pview);
378
379 pipe_resource_reference(&pview->texture, NULL);
380
381 free(view);
382 }
383
384 static void
lima_set_sampler_views(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start,unsigned nr,unsigned unbind_num_trailing_slots,bool take_ownership,struct pipe_sampler_view ** views)385 lima_set_sampler_views(struct pipe_context *pctx,
386 enum pipe_shader_type shader,
387 unsigned start, unsigned nr,
388 unsigned unbind_num_trailing_slots,
389 bool take_ownership,
390 struct pipe_sampler_view **views)
391 {
392 struct lima_context *ctx = lima_context(pctx);
393 struct lima_texture_stateobj *lima_tex = &ctx->tex_stateobj;
394 int i;
395 unsigned new_nr = 0;
396
397 assert(start == 0);
398
399 for (i = 0; i < nr; i++) {
400 if (views[i])
401 new_nr = i + 1;
402
403 if (take_ownership) {
404 pipe_sampler_view_reference(&lima_tex->textures[i], NULL);
405 lima_tex->textures[i] = views[i];
406 } else {
407 pipe_sampler_view_reference(&lima_tex->textures[i], views[i]);
408 }
409 }
410
411 for (; i < lima_tex->num_textures; i++) {
412 pipe_sampler_view_reference(&lima_tex->textures[i], NULL);
413 }
414
415 lima_tex->num_textures = new_nr;
416 ctx->dirty |= LIMA_CONTEXT_DIRTY_TEXTURES;
417 }
418
419 static void
lima_set_sample_mask(struct pipe_context * pctx,unsigned sample_mask)420 lima_set_sample_mask(struct pipe_context *pctx,
421 unsigned sample_mask)
422 {
423 struct lima_context *ctx = lima_context(pctx);
424 ctx->sample_mask = sample_mask & ((1 << LIMA_MAX_SAMPLES) - 1);
425 ctx->dirty |= LIMA_CONTEXT_DIRTY_SAMPLE_MASK;
426 }
427
428 void
lima_state_init(struct lima_context * ctx)429 lima_state_init(struct lima_context *ctx)
430 {
431 ctx->base.set_framebuffer_state = lima_set_framebuffer_state;
432 ctx->base.set_polygon_stipple = lima_set_polygon_stipple;
433 ctx->base.set_viewport_states = lima_set_viewport_states;
434 ctx->base.set_scissor_states = lima_set_scissor_states;
435 ctx->base.set_blend_color = lima_set_blend_color;
436 ctx->base.set_stencil_ref = lima_set_stencil_ref;
437 ctx->base.set_clip_state = lima_set_clip_state;
438
439 ctx->base.set_vertex_buffers = lima_set_vertex_buffers;
440 ctx->base.set_constant_buffer = lima_set_constant_buffer;
441
442 ctx->base.create_depth_stencil_alpha_state = lima_create_depth_stencil_alpha_state;
443 ctx->base.bind_depth_stencil_alpha_state = lima_bind_depth_stencil_alpha_state;
444 ctx->base.delete_depth_stencil_alpha_state = lima_delete_depth_stencil_alpha_state;
445
446 ctx->base.create_rasterizer_state = lima_create_rasterizer_state;
447 ctx->base.bind_rasterizer_state = lima_bind_rasterizer_state;
448 ctx->base.delete_rasterizer_state = lima_delete_rasterizer_state;
449
450 ctx->base.create_blend_state = lima_create_blend_state;
451 ctx->base.bind_blend_state = lima_bind_blend_state;
452 ctx->base.delete_blend_state = lima_delete_blend_state;
453
454 ctx->base.create_vertex_elements_state = lima_create_vertex_elements_state;
455 ctx->base.bind_vertex_elements_state = lima_bind_vertex_elements_state;
456 ctx->base.delete_vertex_elements_state = lima_delete_vertex_elements_state;
457
458 ctx->base.create_sampler_state = lima_create_sampler_state;
459 ctx->base.delete_sampler_state = lima_sampler_state_delete;
460 ctx->base.bind_sampler_states = lima_sampler_states_bind;
461
462 ctx->base.create_sampler_view = lima_create_sampler_view;
463 ctx->base.sampler_view_destroy = lima_sampler_view_destroy;
464 ctx->base.set_sampler_views = lima_set_sampler_views;
465
466 ctx->base.set_sample_mask = lima_set_sample_mask;
467 }
468
469 void
lima_state_fini(struct lima_context * ctx)470 lima_state_fini(struct lima_context *ctx)
471 {
472 struct lima_context_vertex_buffer *so = &ctx->vertex_buffers;
473
474 util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, NULL,
475 0, 0, ARRAY_SIZE(so->vb), false);
476
477 pipe_surface_reference(&ctx->framebuffer.base.cbufs[0], NULL);
478 pipe_surface_reference(&ctx->framebuffer.base.zsbuf, NULL);
479 }
480