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
41static void
42lima_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
59static void
60lima_set_polygon_stipple(struct pipe_context *pctx,
61                         const struct pipe_poly_stipple *stipple)
62{
63
64}
65
66static void *
67lima_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
81static void
82lima_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
90static void
91lima_delete_depth_stencil_alpha_state(struct pipe_context *pctx, void *hwcso)
92{
93   FREE(hwcso);
94}
95
96static void *
97lima_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
111static void
112lima_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
120static void
121lima_delete_rasterizer_state(struct pipe_context *pctx, void *hwcso)
122{
123   FREE(hwcso);
124}
125
126static void *
127lima_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
141static void
142lima_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
150static void
151lima_delete_blend_state(struct pipe_context *pctx, void *hwcso)
152{
153   FREE(hwcso);
154}
155
156static void *
157lima_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
172static void
173lima_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
181static void
182lima_delete_vertex_elements_state(struct pipe_context *pctx, void *hwcso)
183{
184   FREE(hwcso);
185}
186
187static void
188lima_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
206static void
207lima_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
232static void
233lima_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
244static void
245lima_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
254static void
255lima_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
264static void
265lima_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
274static void
275lima_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
300static void *
301lima_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
313static void
314lima_sampler_state_delete(struct pipe_context *pctx, void *sstate)
315{
316   free(sstate);
317}
318
319static void
320lima_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
345static struct pipe_sampler_view *
346lima_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
369static void
370lima_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
380static void
381lima_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
415static void
416lima_set_sample_mask(struct pipe_context *pctx,
417                     unsigned sample_mask)
418{
419}
420
421void
422lima_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
462void
463lima_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