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