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 = 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
236static void
237lima_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
248static void
249lima_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
258static void
259lima_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
268static void
269lima_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
278static void
279lima_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
304static void *
305lima_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
317static void
318lima_sampler_state_delete(struct pipe_context *pctx, void *sstate)
319{
320   free(sstate);
321}
322
323static void
324lima_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
349static struct pipe_sampler_view *
350lima_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
373static void
374lima_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
384static void
385lima_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
419static void
420lima_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
428void
429lima_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
469void
470lima_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