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 = viewport->translate[0] - fabsf(viewport->scale[0]);
216 ctx->viewport.right = viewport->translate[0] + fabsf(viewport->scale[0]);
217 ctx->viewport.bottom = viewport->translate[1] - fabsf(viewport->scale[1]);
218 ctx->viewport.top = viewport->translate[1] + fabsf(viewport->scale[1]);
219
220 /* reverse calculate the parameter of glDepthRange */
221 float near, far;
222 bool halfz = ctx->rasterizer && ctx->rasterizer->base.clip_halfz;
223 util_viewport_zmin_zmax(viewport, halfz, &near, &far);
224
225 ctx->viewport.near = ctx->rasterizer && ctx->rasterizer->base.depth_clip_near ? near : 0.0f;
226 ctx->viewport.far = ctx->rasterizer && ctx->rasterizer->base.depth_clip_far ? far : 1.0f;
227
228 ctx->viewport.transform = *viewport;
229 ctx->dirty |= LIMA_CONTEXT_DIRTY_VIEWPORT;
230 }
231
232 static void
lima_set_scissor_states(struct pipe_context * pctx,unsigned start_slot,unsigned num_scissors,const struct pipe_scissor_state * scissor)233 lima_set_scissor_states(struct pipe_context *pctx,
234 unsigned start_slot,
235 unsigned num_scissors,
236 const struct pipe_scissor_state *scissor)
237 {
238 struct lima_context *ctx = lima_context(pctx);
239
240 ctx->scissor = *scissor;
241 ctx->dirty |= LIMA_CONTEXT_DIRTY_SCISSOR;
242 }
243
244 static void
lima_set_blend_color(struct pipe_context * pctx,const struct pipe_blend_color * blend_color)245 lima_set_blend_color(struct pipe_context *pctx,
246 const struct pipe_blend_color *blend_color)
247 {
248 struct lima_context *ctx = lima_context(pctx);
249
250 ctx->blend_color = *blend_color;
251 ctx->dirty |= LIMA_CONTEXT_DIRTY_BLEND_COLOR;
252 }
253
254 static void
lima_set_stencil_ref(struct pipe_context * pctx,const struct pipe_stencil_ref stencil_ref)255 lima_set_stencil_ref(struct pipe_context *pctx,
256 const struct pipe_stencil_ref stencil_ref)
257 {
258 struct lima_context *ctx = lima_context(pctx);
259
260 ctx->stencil_ref = stencil_ref;
261 ctx->dirty |= LIMA_CONTEXT_DIRTY_STENCIL_REF;
262 }
263
264 static void
lima_set_clip_state(struct pipe_context * pctx,const struct pipe_clip_state * clip)265 lima_set_clip_state(struct pipe_context *pctx,
266 const struct pipe_clip_state *clip)
267 {
268 struct lima_context *ctx = lima_context(pctx);
269 ctx->clip = *clip;
270
271 ctx->dirty |= LIMA_CONTEXT_DIRTY_CLIP;
272 }
273
274 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)275 lima_set_constant_buffer(struct pipe_context *pctx,
276 enum pipe_shader_type shader, uint index,
277 bool pass_reference,
278 const struct pipe_constant_buffer *cb)
279 {
280 struct lima_context *ctx = lima_context(pctx);
281 struct lima_context_constant_buffer *so = ctx->const_buffer + shader;
282
283 assert(index == 0);
284
285 if (unlikely(!cb)) {
286 so->buffer = NULL;
287 so->size = 0;
288 } else {
289 assert(!cb->buffer);
290
291 so->buffer = cb->user_buffer + cb->buffer_offset;
292 so->size = cb->buffer_size;
293 }
294
295 so->dirty = true;
296 ctx->dirty |= LIMA_CONTEXT_DIRTY_CONST_BUFF;
297
298 }
299
300 static void *
lima_create_sampler_state(struct pipe_context * pctx,const struct pipe_sampler_state * cso)301 lima_create_sampler_state(struct pipe_context *pctx,
302 const struct pipe_sampler_state *cso)
303 {
304 struct lima_sampler_state *so = CALLOC_STRUCT(lima_sampler_state);
305 if (!so)
306 return NULL;
307
308 memcpy(so, cso, sizeof(*cso));
309
310 return so;
311 }
312
313 static void
lima_sampler_state_delete(struct pipe_context * pctx,void * sstate)314 lima_sampler_state_delete(struct pipe_context *pctx, void *sstate)
315 {
316 free(sstate);
317 }
318
319 static void
lima_sampler_states_bind(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start,unsigned nr,void ** hwcso)320 lima_sampler_states_bind(struct pipe_context *pctx,
321 enum pipe_shader_type shader, unsigned start,
322 unsigned nr, void **hwcso)
323 {
324 struct lima_context *ctx = lima_context(pctx);
325 struct lima_texture_stateobj *lima_tex = &ctx->tex_stateobj;
326 unsigned i;
327 unsigned new_nr = 0;
328
329 assert(start == 0);
330
331 for (i = 0; i < nr; i++) {
332 if (hwcso[i])
333 new_nr = i + 1;
334 lima_tex->samplers[i] = hwcso[i];
335 }
336
337 for (; i < lima_tex->num_samplers; i++) {
338 lima_tex->samplers[i] = NULL;
339 }
340
341 lima_tex->num_samplers = new_nr;
342 ctx->dirty |= LIMA_CONTEXT_DIRTY_TEXTURES;
343 }
344
345 static struct pipe_sampler_view *
lima_create_sampler_view(struct pipe_context * pctx,struct pipe_resource * prsc,const struct pipe_sampler_view * cso)346 lima_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
347 const struct pipe_sampler_view *cso)
348 {
349 struct lima_sampler_view *so = CALLOC_STRUCT(lima_sampler_view);
350
351 if (!so)
352 return NULL;
353
354 so->base = *cso;
355
356 pipe_reference(NULL, &prsc->reference);
357 so->base.texture = prsc;
358 so->base.reference.count = 1;
359 so->base.context = pctx;
360
361 uint8_t sampler_swizzle[4] = { cso->swizzle_r, cso->swizzle_g,
362 cso->swizzle_b, cso->swizzle_a };
363 const uint8_t *format_swizzle = lima_format_get_texel_swizzle(cso->format);
364 util_format_compose_swizzles(format_swizzle, sampler_swizzle, so->swizzle);
365
366 return &so->base;
367 }
368
369 static void
lima_sampler_view_destroy(struct pipe_context * pctx,struct pipe_sampler_view * pview)370 lima_sampler_view_destroy(struct pipe_context *pctx,
371 struct pipe_sampler_view *pview)
372 {
373 struct lima_sampler_view *view = lima_sampler_view(pview);
374
375 pipe_resource_reference(&pview->texture, NULL);
376
377 free(view);
378 }
379
380 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)381 lima_set_sampler_views(struct pipe_context *pctx,
382 enum pipe_shader_type shader,
383 unsigned start, unsigned nr,
384 unsigned unbind_num_trailing_slots,
385 bool take_ownership,
386 struct pipe_sampler_view **views)
387 {
388 struct lima_context *ctx = lima_context(pctx);
389 struct lima_texture_stateobj *lima_tex = &ctx->tex_stateobj;
390 int i;
391 unsigned new_nr = 0;
392
393 assert(start == 0);
394
395 for (i = 0; i < nr; i++) {
396 if (views[i])
397 new_nr = i + 1;
398
399 if (take_ownership) {
400 pipe_sampler_view_reference(&lima_tex->textures[i], NULL);
401 lima_tex->textures[i] = views[i];
402 } else {
403 pipe_sampler_view_reference(&lima_tex->textures[i], views[i]);
404 }
405 }
406
407 for (; i < lima_tex->num_textures; i++) {
408 pipe_sampler_view_reference(&lima_tex->textures[i], NULL);
409 }
410
411 lima_tex->num_textures = new_nr;
412 ctx->dirty |= LIMA_CONTEXT_DIRTY_TEXTURES;
413 }
414
415 static void
lima_set_sample_mask(struct pipe_context * pctx,unsigned sample_mask)416 lima_set_sample_mask(struct pipe_context *pctx,
417 unsigned sample_mask)
418 {
419 }
420
421 void
lima_state_init(struct lima_context * ctx)422 lima_state_init(struct lima_context *ctx)
423 {
424 ctx->base.set_framebuffer_state = lima_set_framebuffer_state;
425 ctx->base.set_polygon_stipple = lima_set_polygon_stipple;
426 ctx->base.set_viewport_states = lima_set_viewport_states;
427 ctx->base.set_scissor_states = lima_set_scissor_states;
428 ctx->base.set_blend_color = lima_set_blend_color;
429 ctx->base.set_stencil_ref = lima_set_stencil_ref;
430 ctx->base.set_clip_state = lima_set_clip_state;
431
432 ctx->base.set_vertex_buffers = lima_set_vertex_buffers;
433 ctx->base.set_constant_buffer = lima_set_constant_buffer;
434
435 ctx->base.create_depth_stencil_alpha_state = lima_create_depth_stencil_alpha_state;
436 ctx->base.bind_depth_stencil_alpha_state = lima_bind_depth_stencil_alpha_state;
437 ctx->base.delete_depth_stencil_alpha_state = lima_delete_depth_stencil_alpha_state;
438
439 ctx->base.create_rasterizer_state = lima_create_rasterizer_state;
440 ctx->base.bind_rasterizer_state = lima_bind_rasterizer_state;
441 ctx->base.delete_rasterizer_state = lima_delete_rasterizer_state;
442
443 ctx->base.create_blend_state = lima_create_blend_state;
444 ctx->base.bind_blend_state = lima_bind_blend_state;
445 ctx->base.delete_blend_state = lima_delete_blend_state;
446
447 ctx->base.create_vertex_elements_state = lima_create_vertex_elements_state;
448 ctx->base.bind_vertex_elements_state = lima_bind_vertex_elements_state;
449 ctx->base.delete_vertex_elements_state = lima_delete_vertex_elements_state;
450
451 ctx->base.create_sampler_state = lima_create_sampler_state;
452 ctx->base.delete_sampler_state = lima_sampler_state_delete;
453 ctx->base.bind_sampler_states = lima_sampler_states_bind;
454
455 ctx->base.create_sampler_view = lima_create_sampler_view;
456 ctx->base.sampler_view_destroy = lima_sampler_view_destroy;
457 ctx->base.set_sampler_views = lima_set_sampler_views;
458
459 ctx->base.set_sample_mask = lima_set_sample_mask;
460 }
461
462 void
lima_state_fini(struct lima_context * ctx)463 lima_state_fini(struct lima_context *ctx)
464 {
465 struct lima_context_vertex_buffer *so = &ctx->vertex_buffers;
466
467 util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, NULL,
468 0, 0, ARRAY_SIZE(so->vb), false);
469
470 pipe_surface_reference(&ctx->framebuffer.base.cbufs[0], NULL);
471 pipe_surface_reference(&ctx->framebuffer.base.zsbuf, NULL);
472 }
473