1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bf215546Sopenharmony_ci * SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci * Authors:
24bf215546Sopenharmony_ci *    Rob Clark <robclark@freedesktop.org>
25bf215546Sopenharmony_ci */
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "pipe/p_state.h"
28bf215546Sopenharmony_ci#include "util/u_dual_blend.h"
29bf215546Sopenharmony_ci#include "util/u_helpers.h"
30bf215546Sopenharmony_ci#include "util/u_memory.h"
31bf215546Sopenharmony_ci#include "util/u_string.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci#include "freedreno_context.h"
34bf215546Sopenharmony_ci#include "freedreno_gmem.h"
35bf215546Sopenharmony_ci#include "freedreno_query_hw.h"
36bf215546Sopenharmony_ci#include "freedreno_resource.h"
37bf215546Sopenharmony_ci#include "freedreno_state.h"
38bf215546Sopenharmony_ci#include "freedreno_texture.h"
39bf215546Sopenharmony_ci#include "freedreno_util.h"
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci#define get_safe(ptr, field) ((ptr) ? (ptr)->field : 0)
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci/* All the generic state handling.. In case of CSO's that are specific
44bf215546Sopenharmony_ci * to the GPU version, when the bind and the delete are common they can
45bf215546Sopenharmony_ci * go in here.
46bf215546Sopenharmony_ci */
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_cistatic void
49bf215546Sopenharmony_ciupdate_draw_cost(struct fd_context *ctx) assert_dt
50bf215546Sopenharmony_ci{
51bf215546Sopenharmony_ci   struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci   ctx->draw_cost = pfb->nr_cbufs;
54bf215546Sopenharmony_ci   for (unsigned i = 0; i < pfb->nr_cbufs; i++)
55bf215546Sopenharmony_ci      if (fd_blend_enabled(ctx, i))
56bf215546Sopenharmony_ci         ctx->draw_cost++;
57bf215546Sopenharmony_ci   if (fd_depth_enabled(ctx))
58bf215546Sopenharmony_ci      ctx->draw_cost++;
59bf215546Sopenharmony_ci   if (fd_depth_write_enabled(ctx))
60bf215546Sopenharmony_ci      ctx->draw_cost++;
61bf215546Sopenharmony_ci}
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_cistatic void
64bf215546Sopenharmony_cifd_set_blend_color(struct pipe_context *pctx,
65bf215546Sopenharmony_ci                   const struct pipe_blend_color *blend_color) in_dt
66bf215546Sopenharmony_ci{
67bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
68bf215546Sopenharmony_ci   ctx->blend_color = *blend_color;
69bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_BLEND_COLOR);
70bf215546Sopenharmony_ci}
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_cistatic void
73bf215546Sopenharmony_cifd_set_stencil_ref(struct pipe_context *pctx,
74bf215546Sopenharmony_ci                   const struct pipe_stencil_ref stencil_ref) in_dt
75bf215546Sopenharmony_ci{
76bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
77bf215546Sopenharmony_ci   ctx->stencil_ref = stencil_ref;
78bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_STENCIL_REF);
79bf215546Sopenharmony_ci}
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_cistatic void
82bf215546Sopenharmony_cifd_set_clip_state(struct pipe_context *pctx,
83bf215546Sopenharmony_ci                  const struct pipe_clip_state *clip) in_dt
84bf215546Sopenharmony_ci{
85bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
86bf215546Sopenharmony_ci   ctx->ucp = *clip;
87bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_UCP);
88bf215546Sopenharmony_ci}
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_cistatic void
91bf215546Sopenharmony_cifd_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask) in_dt
92bf215546Sopenharmony_ci{
93bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
94bf215546Sopenharmony_ci   ctx->sample_mask = (uint16_t)sample_mask;
95bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_SAMPLE_MASK);
96bf215546Sopenharmony_ci}
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_cistatic void
99bf215546Sopenharmony_cifd_set_min_samples(struct pipe_context *pctx, unsigned min_samples) in_dt
100bf215546Sopenharmony_ci{
101bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
102bf215546Sopenharmony_ci   ctx->min_samples = min_samples;
103bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_MIN_SAMPLES);
104bf215546Sopenharmony_ci}
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci/* notes from calim on #dri-devel:
107bf215546Sopenharmony_ci * index==0 will be non-UBO (ie. glUniformXYZ()) all packed together padded
108bf215546Sopenharmony_ci * out to vec4's
109bf215546Sopenharmony_ci * I should be able to consider that I own the user_ptr until the next
110bf215546Sopenharmony_ci * set_constant_buffer() call, at which point I don't really care about the
111bf215546Sopenharmony_ci * previous values.
112bf215546Sopenharmony_ci * index>0 will be UBO's.. well, I'll worry about that later
113bf215546Sopenharmony_ci */
114bf215546Sopenharmony_cistatic void
115bf215546Sopenharmony_cifd_set_constant_buffer(struct pipe_context *pctx, enum pipe_shader_type shader,
116bf215546Sopenharmony_ci                       uint index, bool take_ownership,
117bf215546Sopenharmony_ci                       const struct pipe_constant_buffer *cb) in_dt
118bf215546Sopenharmony_ci{
119bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
120bf215546Sopenharmony_ci   struct fd_constbuf_stateobj *so = &ctx->constbuf[shader];
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   util_copy_constant_buffer(&so->cb[index], cb, take_ownership);
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   /* Note that gallium frontends can unbind constant buffers by
125bf215546Sopenharmony_ci    * passing NULL here.
126bf215546Sopenharmony_ci    */
127bf215546Sopenharmony_ci   if (unlikely(!cb)) {
128bf215546Sopenharmony_ci      so->enabled_mask &= ~(1 << index);
129bf215546Sopenharmony_ci      return;
130bf215546Sopenharmony_ci   }
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   so->enabled_mask |= 1 << index;
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci   fd_context_dirty_shader(ctx, shader, FD_DIRTY_SHADER_CONST);
135bf215546Sopenharmony_ci   fd_resource_set_usage(cb->buffer, FD_DIRTY_CONST);
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci   if (index > 0) {
138bf215546Sopenharmony_ci      assert(!cb->user_buffer);
139bf215546Sopenharmony_ci      ctx->dirty |= FD_DIRTY_RESOURCE;
140bf215546Sopenharmony_ci   }
141bf215546Sopenharmony_ci}
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_cistatic void
144bf215546Sopenharmony_cifd_set_shader_buffers(struct pipe_context *pctx, enum pipe_shader_type shader,
145bf215546Sopenharmony_ci                      unsigned start, unsigned count,
146bf215546Sopenharmony_ci                      const struct pipe_shader_buffer *buffers,
147bf215546Sopenharmony_ci                      unsigned writable_bitmask) in_dt
148bf215546Sopenharmony_ci{
149bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
150bf215546Sopenharmony_ci   struct fd_shaderbuf_stateobj *so = &ctx->shaderbuf[shader];
151bf215546Sopenharmony_ci   const unsigned modified_bits = u_bit_consecutive(start, count);
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci   so->enabled_mask &= ~modified_bits;
154bf215546Sopenharmony_ci   so->writable_mask &= ~modified_bits;
155bf215546Sopenharmony_ci   so->writable_mask |= writable_bitmask << start;
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   for (unsigned i = 0; i < count; i++) {
158bf215546Sopenharmony_ci      unsigned n = i + start;
159bf215546Sopenharmony_ci      struct pipe_shader_buffer *buf = &so->sb[n];
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci      if (buffers && buffers[i].buffer) {
162bf215546Sopenharmony_ci         if ((buf->buffer == buffers[i].buffer) &&
163bf215546Sopenharmony_ci             (buf->buffer_offset == buffers[i].buffer_offset) &&
164bf215546Sopenharmony_ci             (buf->buffer_size == buffers[i].buffer_size))
165bf215546Sopenharmony_ci            continue;
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci         buf->buffer_offset = buffers[i].buffer_offset;
168bf215546Sopenharmony_ci         buf->buffer_size = buffers[i].buffer_size;
169bf215546Sopenharmony_ci         pipe_resource_reference(&buf->buffer, buffers[i].buffer);
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci         fd_resource_set_usage(buffers[i].buffer, FD_DIRTY_SSBO);
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci         so->enabled_mask |= BIT(n);
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_ci         if (writable_bitmask & BIT(i)) {
176bf215546Sopenharmony_ci            struct fd_resource *rsc = fd_resource(buf->buffer);
177bf215546Sopenharmony_ci            util_range_add(&rsc->b.b, &rsc->valid_buffer_range,
178bf215546Sopenharmony_ci                           buf->buffer_offset,
179bf215546Sopenharmony_ci                           buf->buffer_offset + buf->buffer_size);
180bf215546Sopenharmony_ci         }
181bf215546Sopenharmony_ci      } else {
182bf215546Sopenharmony_ci         pipe_resource_reference(&buf->buffer, NULL);
183bf215546Sopenharmony_ci      }
184bf215546Sopenharmony_ci   }
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci   fd_context_dirty_shader(ctx, shader, FD_DIRTY_SHADER_SSBO);
187bf215546Sopenharmony_ci}
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_civoid
190bf215546Sopenharmony_cifd_set_shader_images(struct pipe_context *pctx, enum pipe_shader_type shader,
191bf215546Sopenharmony_ci                     unsigned start, unsigned count,
192bf215546Sopenharmony_ci                     unsigned unbind_num_trailing_slots,
193bf215546Sopenharmony_ci                     const struct pipe_image_view *images) in_dt
194bf215546Sopenharmony_ci{
195bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
196bf215546Sopenharmony_ci   struct fd_shaderimg_stateobj *so = &ctx->shaderimg[shader];
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci   unsigned mask = 0;
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci   if (images) {
201bf215546Sopenharmony_ci      for (unsigned i = 0; i < count; i++) {
202bf215546Sopenharmony_ci         unsigned n = i + start;
203bf215546Sopenharmony_ci         struct pipe_image_view *buf = &so->si[n];
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci         if ((buf->resource == images[i].resource) &&
206bf215546Sopenharmony_ci             (buf->format == images[i].format) &&
207bf215546Sopenharmony_ci             (buf->access == images[i].access) &&
208bf215546Sopenharmony_ci             !memcmp(&buf->u, &images[i].u, sizeof(buf->u)))
209bf215546Sopenharmony_ci            continue;
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci         mask |= BIT(n);
212bf215546Sopenharmony_ci         util_copy_image_view(buf, &images[i]);
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ci         if (buf->resource) {
215bf215546Sopenharmony_ci            fd_resource_set_usage(buf->resource, FD_DIRTY_IMAGE);
216bf215546Sopenharmony_ci            so->enabled_mask |= BIT(n);
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci            if ((buf->access & PIPE_IMAGE_ACCESS_WRITE) &&
219bf215546Sopenharmony_ci                (buf->resource->target == PIPE_BUFFER)) {
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ci               struct fd_resource *rsc = fd_resource(buf->resource);
222bf215546Sopenharmony_ci               util_range_add(&rsc->b.b, &rsc->valid_buffer_range,
223bf215546Sopenharmony_ci                              buf->u.buf.offset,
224bf215546Sopenharmony_ci                              buf->u.buf.offset + buf->u.buf.size);
225bf215546Sopenharmony_ci            }
226bf215546Sopenharmony_ci         } else {
227bf215546Sopenharmony_ci            so->enabled_mask &= ~BIT(n);
228bf215546Sopenharmony_ci         }
229bf215546Sopenharmony_ci      }
230bf215546Sopenharmony_ci   } else {
231bf215546Sopenharmony_ci      mask = (BIT(count) - 1) << start;
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ci      for (unsigned i = 0; i < count; i++) {
234bf215546Sopenharmony_ci         unsigned n = i + start;
235bf215546Sopenharmony_ci         struct pipe_image_view *img = &so->si[n];
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_ci         pipe_resource_reference(&img->resource, NULL);
238bf215546Sopenharmony_ci      }
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_ci      so->enabled_mask &= ~mask;
241bf215546Sopenharmony_ci   }
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci   for (unsigned i = 0; i < unbind_num_trailing_slots; i++)
244bf215546Sopenharmony_ci      pipe_resource_reference(&so->si[i + start + count].resource, NULL);
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci   so->enabled_mask &=
247bf215546Sopenharmony_ci      ~(BITFIELD_MASK(unbind_num_trailing_slots) << (start + count));
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_ci   fd_context_dirty_shader(ctx, shader, FD_DIRTY_SHADER_IMAGE);
250bf215546Sopenharmony_ci}
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_civoid
253bf215546Sopenharmony_cifd_set_framebuffer_state(struct pipe_context *pctx,
254bf215546Sopenharmony_ci                         const struct pipe_framebuffer_state *framebuffer)
255bf215546Sopenharmony_ci{
256bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
257bf215546Sopenharmony_ci   struct pipe_framebuffer_state *cso;
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci   DBG("%ux%u, %u layers, %u samples", framebuffer->width, framebuffer->height,
260bf215546Sopenharmony_ci       framebuffer->layers, framebuffer->samples);
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ci   cso = &ctx->framebuffer;
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_ci   if (util_framebuffer_state_equal(cso, framebuffer))
265bf215546Sopenharmony_ci      return;
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci   /* Do this *after* checking that the framebuffer state is actually
268bf215546Sopenharmony_ci    * changing.  In the fd_blitter_clear() path, we get a pfb update
269bf215546Sopenharmony_ci    * to restore the current pfb state, which should not trigger us
270bf215546Sopenharmony_ci    * to flush (as that can cause the batch to be freed at a point
271bf215546Sopenharmony_ci    * before fd_clear() returns, but after the point where it expects
272bf215546Sopenharmony_ci    * flushes to potentially happen.
273bf215546Sopenharmony_ci    */
274bf215546Sopenharmony_ci   fd_context_switch_from(ctx);
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_ci   util_copy_framebuffer_state(cso, framebuffer);
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci   cso->samples = util_framebuffer_get_num_samples(cso);
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci   if (ctx->screen->reorder) {
281bf215546Sopenharmony_ci      struct fd_batch *old_batch = NULL;
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci      fd_batch_reference(&old_batch, ctx->batch);
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci      if (likely(old_batch))
286bf215546Sopenharmony_ci         fd_batch_finish_queries(old_batch);
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci      fd_batch_reference(&ctx->batch, NULL);
289bf215546Sopenharmony_ci      fd_context_all_dirty(ctx);
290bf215546Sopenharmony_ci      ctx->update_active_queries = true;
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci      fd_batch_reference(&old_batch, NULL);
293bf215546Sopenharmony_ci   } else if (ctx->batch) {
294bf215546Sopenharmony_ci      DBG("%d: cbufs[0]=%p, zsbuf=%p", ctx->batch->needs_flush,
295bf215546Sopenharmony_ci          framebuffer->cbufs[0], framebuffer->zsbuf);
296bf215546Sopenharmony_ci      fd_batch_flush(ctx->batch);
297bf215546Sopenharmony_ci   }
298bf215546Sopenharmony_ci
299bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_FRAMEBUFFER);
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci   ctx->disabled_scissor.minx = 0;
302bf215546Sopenharmony_ci   ctx->disabled_scissor.miny = 0;
303bf215546Sopenharmony_ci   ctx->disabled_scissor.maxx = cso->width;
304bf215546Sopenharmony_ci   ctx->disabled_scissor.maxy = cso->height;
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_SCISSOR);
307bf215546Sopenharmony_ci   update_draw_cost(ctx);
308bf215546Sopenharmony_ci}
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_cistatic void
311bf215546Sopenharmony_cifd_set_polygon_stipple(struct pipe_context *pctx,
312bf215546Sopenharmony_ci                       const struct pipe_poly_stipple *stipple) in_dt
313bf215546Sopenharmony_ci{
314bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
315bf215546Sopenharmony_ci   ctx->stipple = *stipple;
316bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_STIPPLE);
317bf215546Sopenharmony_ci}
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_cistatic void
320bf215546Sopenharmony_cifd_set_scissor_states(struct pipe_context *pctx, unsigned start_slot,
321bf215546Sopenharmony_ci                      unsigned num_scissors,
322bf215546Sopenharmony_ci                      const struct pipe_scissor_state *scissor) in_dt
323bf215546Sopenharmony_ci{
324bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci   ctx->scissor = *scissor;
327bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_SCISSOR);
328bf215546Sopenharmony_ci}
329bf215546Sopenharmony_ci
330bf215546Sopenharmony_cistatic void
331bf215546Sopenharmony_cifd_set_viewport_states(struct pipe_context *pctx, unsigned start_slot,
332bf215546Sopenharmony_ci                       unsigned num_viewports,
333bf215546Sopenharmony_ci                       const struct pipe_viewport_state *viewport) in_dt
334bf215546Sopenharmony_ci{
335bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
336bf215546Sopenharmony_ci   struct pipe_scissor_state *scissor = &ctx->viewport_scissor;
337bf215546Sopenharmony_ci   float minx, miny, maxx, maxy;
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_ci   ctx->viewport = *viewport;
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci   /* see si_get_scissor_from_viewport(): */
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci   /* Convert (-1, -1) and (1, 1) from clip space into window space. */
344bf215546Sopenharmony_ci   minx = -viewport->scale[0] + viewport->translate[0];
345bf215546Sopenharmony_ci   miny = -viewport->scale[1] + viewport->translate[1];
346bf215546Sopenharmony_ci   maxx = viewport->scale[0] + viewport->translate[0];
347bf215546Sopenharmony_ci   maxy = viewport->scale[1] + viewport->translate[1];
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci   /* Handle inverted viewports. */
350bf215546Sopenharmony_ci   if (minx > maxx) {
351bf215546Sopenharmony_ci      swap(minx, maxx);
352bf215546Sopenharmony_ci   }
353bf215546Sopenharmony_ci   if (miny > maxy) {
354bf215546Sopenharmony_ci      swap(miny, maxy);
355bf215546Sopenharmony_ci   }
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_ci   const float max_dims = ctx->screen->gen >= 4 ? 16384.f : 4096.f;
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci   /* Clamp, convert to integer and round up the max bounds. */
360bf215546Sopenharmony_ci   scissor->minx = CLAMP(minx, 0.f, max_dims);
361bf215546Sopenharmony_ci   scissor->miny = CLAMP(miny, 0.f, max_dims);
362bf215546Sopenharmony_ci   scissor->maxx = CLAMP(ceilf(maxx), 0.f, max_dims);
363bf215546Sopenharmony_ci   scissor->maxy = CLAMP(ceilf(maxy), 0.f, max_dims);
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_VIEWPORT);
366bf215546Sopenharmony_ci}
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_cistatic void
369bf215546Sopenharmony_cifd_set_vertex_buffers(struct pipe_context *pctx, unsigned start_slot,
370bf215546Sopenharmony_ci                      unsigned count, unsigned unbind_num_trailing_slots,
371bf215546Sopenharmony_ci                      bool take_ownership,
372bf215546Sopenharmony_ci                      const struct pipe_vertex_buffer *vb) in_dt
373bf215546Sopenharmony_ci{
374bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
375bf215546Sopenharmony_ci   struct fd_vertexbuf_stateobj *so = &ctx->vtx.vertexbuf;
376bf215546Sopenharmony_ci   int i;
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci   /* on a2xx, pitch is encoded in the vtx fetch instruction, so
379bf215546Sopenharmony_ci    * we need to mark VTXSTATE as dirty as well to trigger patching
380bf215546Sopenharmony_ci    * and re-emitting the vtx shader:
381bf215546Sopenharmony_ci    */
382bf215546Sopenharmony_ci   if (ctx->screen->gen < 3) {
383bf215546Sopenharmony_ci      for (i = 0; i < count; i++) {
384bf215546Sopenharmony_ci         bool new_enabled = vb && vb[i].buffer.resource;
385bf215546Sopenharmony_ci         bool old_enabled = so->vb[start_slot + i].buffer.resource != NULL;
386bf215546Sopenharmony_ci         uint32_t new_stride = vb ? vb[i].stride : 0;
387bf215546Sopenharmony_ci         uint32_t old_stride = so->vb[start_slot + i].stride;
388bf215546Sopenharmony_ci         if ((new_enabled != old_enabled) || (new_stride != old_stride)) {
389bf215546Sopenharmony_ci            fd_context_dirty(ctx, FD_DIRTY_VTXSTATE);
390bf215546Sopenharmony_ci            break;
391bf215546Sopenharmony_ci         }
392bf215546Sopenharmony_ci      }
393bf215546Sopenharmony_ci   }
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci   util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, start_slot,
396bf215546Sopenharmony_ci                                count, unbind_num_trailing_slots,
397bf215546Sopenharmony_ci                                take_ownership);
398bf215546Sopenharmony_ci   so->count = util_last_bit(so->enabled_mask);
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_ci   if (!vb)
401bf215546Sopenharmony_ci      return;
402bf215546Sopenharmony_ci
403bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_VTXBUF);
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_ci   for (unsigned i = 0; i < count; i++) {
406bf215546Sopenharmony_ci      assert(!vb[i].is_user_buffer);
407bf215546Sopenharmony_ci      fd_resource_set_usage(vb[i].buffer.resource, FD_DIRTY_VTXBUF);
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci      /* Robust buffer access: Return undefined data (the start of the buffer)
410bf215546Sopenharmony_ci       * instead of process termination or a GPU hang in case of overflow.
411bf215546Sopenharmony_ci       */
412bf215546Sopenharmony_ci      if (vb[i].buffer.resource &&
413bf215546Sopenharmony_ci          unlikely(vb[i].buffer_offset >= vb[i].buffer.resource->width0)) {
414bf215546Sopenharmony_ci         so->vb[start_slot + i].buffer_offset = 0;
415bf215546Sopenharmony_ci      }
416bf215546Sopenharmony_ci   }
417bf215546Sopenharmony_ci}
418bf215546Sopenharmony_ci
419bf215546Sopenharmony_cistatic void
420bf215546Sopenharmony_cifd_blend_state_bind(struct pipe_context *pctx, void *hwcso) in_dt
421bf215546Sopenharmony_ci{
422bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
423bf215546Sopenharmony_ci   struct pipe_blend_state *cso = hwcso;
424bf215546Sopenharmony_ci   bool old_is_dual = ctx->blend ? ctx->blend->rt[0].blend_enable &&
425bf215546Sopenharmony_ci                                      util_blend_state_is_dual(ctx->blend, 0)
426bf215546Sopenharmony_ci                                 : false;
427bf215546Sopenharmony_ci   bool new_is_dual =
428bf215546Sopenharmony_ci      cso ? cso->rt[0].blend_enable && util_blend_state_is_dual(cso, 0) : false;
429bf215546Sopenharmony_ci   ctx->blend = hwcso;
430bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_BLEND);
431bf215546Sopenharmony_ci   if (old_is_dual != new_is_dual)
432bf215546Sopenharmony_ci      fd_context_dirty(ctx, FD_DIRTY_BLEND_DUAL);
433bf215546Sopenharmony_ci   update_draw_cost(ctx);
434bf215546Sopenharmony_ci}
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_cistatic void
437bf215546Sopenharmony_cifd_blend_state_delete(struct pipe_context *pctx, void *hwcso) in_dt
438bf215546Sopenharmony_ci{
439bf215546Sopenharmony_ci   FREE(hwcso);
440bf215546Sopenharmony_ci}
441bf215546Sopenharmony_ci
442bf215546Sopenharmony_cistatic void
443bf215546Sopenharmony_cifd_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso) in_dt
444bf215546Sopenharmony_ci{
445bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
446bf215546Sopenharmony_ci   struct pipe_scissor_state *old_scissor = fd_context_get_scissor(ctx);
447bf215546Sopenharmony_ci   bool discard = get_safe(ctx->rasterizer, rasterizer_discard);
448bf215546Sopenharmony_ci   unsigned clip_plane_enable = get_safe(ctx->rasterizer, clip_plane_enable);
449bf215546Sopenharmony_ci
450bf215546Sopenharmony_ci   ctx->rasterizer = hwcso;
451bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_RASTERIZER);
452bf215546Sopenharmony_ci
453bf215546Sopenharmony_ci   if (ctx->rasterizer && ctx->rasterizer->scissor) {
454bf215546Sopenharmony_ci      ctx->current_scissor = &ctx->scissor;
455bf215546Sopenharmony_ci   } else {
456bf215546Sopenharmony_ci      ctx->current_scissor = &ctx->disabled_scissor;
457bf215546Sopenharmony_ci   }
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_ci   /* if scissor enable bit changed we need to mark scissor
460bf215546Sopenharmony_ci    * state as dirty as well:
461bf215546Sopenharmony_ci    * NOTE: we can do a shallow compare, since we only care
462bf215546Sopenharmony_ci    * if it changed to/from &ctx->disable_scissor
463bf215546Sopenharmony_ci    */
464bf215546Sopenharmony_ci   if (old_scissor != fd_context_get_scissor(ctx))
465bf215546Sopenharmony_ci      fd_context_dirty(ctx, FD_DIRTY_SCISSOR);
466bf215546Sopenharmony_ci
467bf215546Sopenharmony_ci   if (discard != get_safe(ctx->rasterizer, rasterizer_discard))
468bf215546Sopenharmony_ci      fd_context_dirty(ctx, FD_DIRTY_RASTERIZER_DISCARD);
469bf215546Sopenharmony_ci
470bf215546Sopenharmony_ci   if (clip_plane_enable != get_safe(ctx->rasterizer, clip_plane_enable))
471bf215546Sopenharmony_ci      fd_context_dirty(ctx, FD_DIRTY_RASTERIZER_CLIP_PLANE_ENABLE);
472bf215546Sopenharmony_ci}
473bf215546Sopenharmony_ci
474bf215546Sopenharmony_cistatic void
475bf215546Sopenharmony_cifd_rasterizer_state_delete(struct pipe_context *pctx, void *hwcso) in_dt
476bf215546Sopenharmony_ci{
477bf215546Sopenharmony_ci   FREE(hwcso);
478bf215546Sopenharmony_ci}
479bf215546Sopenharmony_ci
480bf215546Sopenharmony_cistatic void
481bf215546Sopenharmony_cifd_zsa_state_bind(struct pipe_context *pctx, void *hwcso) in_dt
482bf215546Sopenharmony_ci{
483bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
484bf215546Sopenharmony_ci   ctx->zsa = hwcso;
485bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_ZSA);
486bf215546Sopenharmony_ci   update_draw_cost(ctx);
487bf215546Sopenharmony_ci}
488bf215546Sopenharmony_ci
489bf215546Sopenharmony_cistatic void
490bf215546Sopenharmony_cifd_zsa_state_delete(struct pipe_context *pctx, void *hwcso) in_dt
491bf215546Sopenharmony_ci{
492bf215546Sopenharmony_ci   FREE(hwcso);
493bf215546Sopenharmony_ci}
494bf215546Sopenharmony_ci
495bf215546Sopenharmony_cistatic void *
496bf215546Sopenharmony_cifd_vertex_state_create(struct pipe_context *pctx, unsigned num_elements,
497bf215546Sopenharmony_ci                       const struct pipe_vertex_element *elements)
498bf215546Sopenharmony_ci{
499bf215546Sopenharmony_ci   struct fd_vertex_stateobj *so = CALLOC_STRUCT(fd_vertex_stateobj);
500bf215546Sopenharmony_ci
501bf215546Sopenharmony_ci   if (!so)
502bf215546Sopenharmony_ci      return NULL;
503bf215546Sopenharmony_ci
504bf215546Sopenharmony_ci   memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
505bf215546Sopenharmony_ci   so->num_elements = num_elements;
506bf215546Sopenharmony_ci
507bf215546Sopenharmony_ci   return so;
508bf215546Sopenharmony_ci}
509bf215546Sopenharmony_ci
510bf215546Sopenharmony_cistatic void
511bf215546Sopenharmony_cifd_vertex_state_delete(struct pipe_context *pctx, void *hwcso) in_dt
512bf215546Sopenharmony_ci{
513bf215546Sopenharmony_ci   FREE(hwcso);
514bf215546Sopenharmony_ci}
515bf215546Sopenharmony_ci
516bf215546Sopenharmony_cistatic void
517bf215546Sopenharmony_cifd_vertex_state_bind(struct pipe_context *pctx, void *hwcso) in_dt
518bf215546Sopenharmony_ci{
519bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
520bf215546Sopenharmony_ci   ctx->vtx.vtx = hwcso;
521bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_VTXSTATE);
522bf215546Sopenharmony_ci}
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_cistatic struct pipe_stream_output_target *
525bf215546Sopenharmony_cifd_create_stream_output_target(struct pipe_context *pctx,
526bf215546Sopenharmony_ci                               struct pipe_resource *prsc,
527bf215546Sopenharmony_ci                               unsigned buffer_offset, unsigned buffer_size)
528bf215546Sopenharmony_ci{
529bf215546Sopenharmony_ci   struct fd_stream_output_target *target;
530bf215546Sopenharmony_ci   struct fd_resource *rsc = fd_resource(prsc);
531bf215546Sopenharmony_ci
532bf215546Sopenharmony_ci   target = CALLOC_STRUCT(fd_stream_output_target);
533bf215546Sopenharmony_ci   if (!target)
534bf215546Sopenharmony_ci      return NULL;
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci   pipe_reference_init(&target->base.reference, 1);
537bf215546Sopenharmony_ci   pipe_resource_reference(&target->base.buffer, prsc);
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_ci   target->base.context = pctx;
540bf215546Sopenharmony_ci   target->base.buffer_offset = buffer_offset;
541bf215546Sopenharmony_ci   target->base.buffer_size = buffer_size;
542bf215546Sopenharmony_ci
543bf215546Sopenharmony_ci   target->offset_buf = pipe_buffer_create(
544bf215546Sopenharmony_ci      pctx->screen, PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE, sizeof(uint32_t));
545bf215546Sopenharmony_ci
546bf215546Sopenharmony_ci   assert(rsc->b.b.target == PIPE_BUFFER);
547bf215546Sopenharmony_ci   util_range_add(&rsc->b.b, &rsc->valid_buffer_range, buffer_offset,
548bf215546Sopenharmony_ci                  buffer_offset + buffer_size);
549bf215546Sopenharmony_ci
550bf215546Sopenharmony_ci   return &target->base;
551bf215546Sopenharmony_ci}
552bf215546Sopenharmony_ci
553bf215546Sopenharmony_cistatic void
554bf215546Sopenharmony_cifd_stream_output_target_destroy(struct pipe_context *pctx,
555bf215546Sopenharmony_ci                                struct pipe_stream_output_target *target)
556bf215546Sopenharmony_ci{
557bf215546Sopenharmony_ci   struct fd_stream_output_target *cso = fd_stream_output_target(target);
558bf215546Sopenharmony_ci
559bf215546Sopenharmony_ci   pipe_resource_reference(&cso->base.buffer, NULL);
560bf215546Sopenharmony_ci   pipe_resource_reference(&cso->offset_buf, NULL);
561bf215546Sopenharmony_ci
562bf215546Sopenharmony_ci   FREE(target);
563bf215546Sopenharmony_ci}
564bf215546Sopenharmony_ci
565bf215546Sopenharmony_cistatic void
566bf215546Sopenharmony_cifd_set_stream_output_targets(struct pipe_context *pctx, unsigned num_targets,
567bf215546Sopenharmony_ci                             struct pipe_stream_output_target **targets,
568bf215546Sopenharmony_ci                             const unsigned *offsets) in_dt
569bf215546Sopenharmony_ci{
570bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
571bf215546Sopenharmony_ci   struct fd_streamout_stateobj *so = &ctx->streamout;
572bf215546Sopenharmony_ci   unsigned i;
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ci   assert(num_targets <= ARRAY_SIZE(so->targets));
575bf215546Sopenharmony_ci
576bf215546Sopenharmony_ci   /* Older targets need sw stats enabled for streamout emulation in VS: */
577bf215546Sopenharmony_ci   if (ctx->screen->gen < 5) {
578bf215546Sopenharmony_ci      if (num_targets && !so->num_targets) {
579bf215546Sopenharmony_ci         ctx->stats_users++;
580bf215546Sopenharmony_ci      } else if (so->num_targets && !num_targets) {
581bf215546Sopenharmony_ci         ctx->stats_users--;
582bf215546Sopenharmony_ci      }
583bf215546Sopenharmony_ci   }
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci   for (i = 0; i < num_targets; i++) {
586bf215546Sopenharmony_ci      boolean changed = targets[i] != so->targets[i];
587bf215546Sopenharmony_ci      boolean reset = (offsets[i] != (unsigned)-1);
588bf215546Sopenharmony_ci
589bf215546Sopenharmony_ci      so->reset |= (reset << i);
590bf215546Sopenharmony_ci
591bf215546Sopenharmony_ci      if (!changed && !reset)
592bf215546Sopenharmony_ci         continue;
593bf215546Sopenharmony_ci
594bf215546Sopenharmony_ci      /* Note that all SO targets will be reset at once at a
595bf215546Sopenharmony_ci       * BeginTransformFeedback().
596bf215546Sopenharmony_ci       */
597bf215546Sopenharmony_ci      if (reset) {
598bf215546Sopenharmony_ci         so->offsets[i] = offsets[i];
599bf215546Sopenharmony_ci         ctx->streamout.verts_written = 0;
600bf215546Sopenharmony_ci      }
601bf215546Sopenharmony_ci
602bf215546Sopenharmony_ci      pipe_so_target_reference(&so->targets[i], targets[i]);
603bf215546Sopenharmony_ci   }
604bf215546Sopenharmony_ci
605bf215546Sopenharmony_ci   for (; i < so->num_targets; i++) {
606bf215546Sopenharmony_ci      pipe_so_target_reference(&so->targets[i], NULL);
607bf215546Sopenharmony_ci   }
608bf215546Sopenharmony_ci
609bf215546Sopenharmony_ci   so->num_targets = num_targets;
610bf215546Sopenharmony_ci
611bf215546Sopenharmony_ci   fd_context_dirty(ctx, FD_DIRTY_STREAMOUT);
612bf215546Sopenharmony_ci}
613bf215546Sopenharmony_ci
614bf215546Sopenharmony_cistatic void
615bf215546Sopenharmony_cifd_bind_compute_state(struct pipe_context *pctx, void *state) in_dt
616bf215546Sopenharmony_ci{
617bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
618bf215546Sopenharmony_ci   ctx->compute = state;
619bf215546Sopenharmony_ci   /* NOTE: Don't mark FD_DIRTY_PROG for compute specific state */
620bf215546Sopenharmony_ci   ctx->dirty_shader[PIPE_SHADER_COMPUTE] |= FD_DIRTY_SHADER_PROG;
621bf215546Sopenharmony_ci}
622bf215546Sopenharmony_ci
623bf215546Sopenharmony_ci/* TODO pipe_context::set_compute_resources() should DIAF and clover
624bf215546Sopenharmony_ci * should be updated to use pipe_context::set_constant_buffer() and
625bf215546Sopenharmony_ci * pipe_context::set_shader_images().  Until then just directly frob
626bf215546Sopenharmony_ci * the UBO/image state to avoid the rest of the driver needing to
627bf215546Sopenharmony_ci * know about this bastard api..
628bf215546Sopenharmony_ci */
629bf215546Sopenharmony_cistatic void
630bf215546Sopenharmony_cifd_set_compute_resources(struct pipe_context *pctx, unsigned start,
631bf215546Sopenharmony_ci                         unsigned count, struct pipe_surface **prscs) in_dt
632bf215546Sopenharmony_ci{
633bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
634bf215546Sopenharmony_ci   struct fd_constbuf_stateobj *so = &ctx->constbuf[PIPE_SHADER_COMPUTE];
635bf215546Sopenharmony_ci
636bf215546Sopenharmony_ci   for (unsigned i = 0; i < count; i++) {
637bf215546Sopenharmony_ci      const uint32_t index = i + start + 1;   /* UBOs start at index 1 */
638bf215546Sopenharmony_ci
639bf215546Sopenharmony_ci      if (!prscs) {
640bf215546Sopenharmony_ci         util_copy_constant_buffer(&so->cb[index], NULL, false);
641bf215546Sopenharmony_ci         so->enabled_mask &= ~(1 << index);
642bf215546Sopenharmony_ci      } else if (prscs[i]->format == PIPE_FORMAT_NONE) {
643bf215546Sopenharmony_ci         struct pipe_constant_buffer cb = {
644bf215546Sopenharmony_ci               .buffer = prscs[i]->texture,
645bf215546Sopenharmony_ci         };
646bf215546Sopenharmony_ci         util_copy_constant_buffer(&so->cb[index], &cb, false);
647bf215546Sopenharmony_ci         so->enabled_mask |= (1 << index);
648bf215546Sopenharmony_ci      } else {
649bf215546Sopenharmony_ci         // TODO images
650bf215546Sopenharmony_ci         unreachable("finishme");
651bf215546Sopenharmony_ci      }
652bf215546Sopenharmony_ci   }
653bf215546Sopenharmony_ci}
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_ci/* used by clover to bind global objects, returning the bo address
656bf215546Sopenharmony_ci * via handles[n]
657bf215546Sopenharmony_ci */
658bf215546Sopenharmony_cistatic void
659bf215546Sopenharmony_cifd_set_global_binding(struct pipe_context *pctx, unsigned first, unsigned count,
660bf215546Sopenharmony_ci                      struct pipe_resource **prscs, uint32_t **handles) in_dt
661bf215546Sopenharmony_ci{
662bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
663bf215546Sopenharmony_ci   struct fd_global_bindings_stateobj *so = &ctx->global_bindings;
664bf215546Sopenharmony_ci   unsigned mask = 0;
665bf215546Sopenharmony_ci
666bf215546Sopenharmony_ci   if (prscs) {
667bf215546Sopenharmony_ci      for (unsigned i = 0; i < count; i++) {
668bf215546Sopenharmony_ci         unsigned n = i + first;
669bf215546Sopenharmony_ci
670bf215546Sopenharmony_ci         mask |= BIT(n);
671bf215546Sopenharmony_ci
672bf215546Sopenharmony_ci         pipe_resource_reference(&so->buf[n], prscs[i]);
673bf215546Sopenharmony_ci
674bf215546Sopenharmony_ci         if (so->buf[n]) {
675bf215546Sopenharmony_ci            struct fd_resource *rsc = fd_resource(so->buf[n]);
676bf215546Sopenharmony_ci            uint32_t offset = *handles[i];
677bf215546Sopenharmony_ci            uint64_t iova = fd_bo_get_iova(rsc->bo) + offset;
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_ci            /* Yes, really, despite what the type implies: */
680bf215546Sopenharmony_ci            memcpy(handles[i], &iova, sizeof(iova));
681bf215546Sopenharmony_ci         }
682bf215546Sopenharmony_ci
683bf215546Sopenharmony_ci         if (prscs[i])
684bf215546Sopenharmony_ci            so->enabled_mask |= BIT(n);
685bf215546Sopenharmony_ci         else
686bf215546Sopenharmony_ci            so->enabled_mask &= ~BIT(n);
687bf215546Sopenharmony_ci      }
688bf215546Sopenharmony_ci   } else {
689bf215546Sopenharmony_ci      mask = (BIT(count) - 1) << first;
690bf215546Sopenharmony_ci
691bf215546Sopenharmony_ci      for (unsigned i = 0; i < count; i++) {
692bf215546Sopenharmony_ci         unsigned n = i + first;
693bf215546Sopenharmony_ci         pipe_resource_reference(&so->buf[n], NULL);
694bf215546Sopenharmony_ci      }
695bf215546Sopenharmony_ci
696bf215546Sopenharmony_ci      so->enabled_mask &= ~mask;
697bf215546Sopenharmony_ci   }
698bf215546Sopenharmony_ci}
699bf215546Sopenharmony_ci
700bf215546Sopenharmony_civoid
701bf215546Sopenharmony_cifd_state_init(struct pipe_context *pctx)
702bf215546Sopenharmony_ci{
703bf215546Sopenharmony_ci   pctx->set_blend_color = fd_set_blend_color;
704bf215546Sopenharmony_ci   pctx->set_stencil_ref = fd_set_stencil_ref;
705bf215546Sopenharmony_ci   pctx->set_clip_state = fd_set_clip_state;
706bf215546Sopenharmony_ci   pctx->set_sample_mask = fd_set_sample_mask;
707bf215546Sopenharmony_ci   pctx->set_min_samples = fd_set_min_samples;
708bf215546Sopenharmony_ci   pctx->set_constant_buffer = fd_set_constant_buffer;
709bf215546Sopenharmony_ci   pctx->set_shader_buffers = fd_set_shader_buffers;
710bf215546Sopenharmony_ci   pctx->set_shader_images = fd_set_shader_images;
711bf215546Sopenharmony_ci   pctx->set_framebuffer_state = fd_set_framebuffer_state;
712bf215546Sopenharmony_ci   pctx->set_polygon_stipple = fd_set_polygon_stipple;
713bf215546Sopenharmony_ci   pctx->set_scissor_states = fd_set_scissor_states;
714bf215546Sopenharmony_ci   pctx->set_viewport_states = fd_set_viewport_states;
715bf215546Sopenharmony_ci
716bf215546Sopenharmony_ci   pctx->set_vertex_buffers = fd_set_vertex_buffers;
717bf215546Sopenharmony_ci
718bf215546Sopenharmony_ci   pctx->bind_blend_state = fd_blend_state_bind;
719bf215546Sopenharmony_ci   pctx->delete_blend_state = fd_blend_state_delete;
720bf215546Sopenharmony_ci
721bf215546Sopenharmony_ci   pctx->bind_rasterizer_state = fd_rasterizer_state_bind;
722bf215546Sopenharmony_ci   pctx->delete_rasterizer_state = fd_rasterizer_state_delete;
723bf215546Sopenharmony_ci
724bf215546Sopenharmony_ci   pctx->bind_depth_stencil_alpha_state = fd_zsa_state_bind;
725bf215546Sopenharmony_ci   pctx->delete_depth_stencil_alpha_state = fd_zsa_state_delete;
726bf215546Sopenharmony_ci
727bf215546Sopenharmony_ci   if (!pctx->create_vertex_elements_state)
728bf215546Sopenharmony_ci      pctx->create_vertex_elements_state = fd_vertex_state_create;
729bf215546Sopenharmony_ci   pctx->delete_vertex_elements_state = fd_vertex_state_delete;
730bf215546Sopenharmony_ci   pctx->bind_vertex_elements_state = fd_vertex_state_bind;
731bf215546Sopenharmony_ci
732bf215546Sopenharmony_ci   pctx->create_stream_output_target = fd_create_stream_output_target;
733bf215546Sopenharmony_ci   pctx->stream_output_target_destroy = fd_stream_output_target_destroy;
734bf215546Sopenharmony_ci   pctx->set_stream_output_targets = fd_set_stream_output_targets;
735bf215546Sopenharmony_ci
736bf215546Sopenharmony_ci   if (has_compute(fd_screen(pctx->screen))) {
737bf215546Sopenharmony_ci      pctx->bind_compute_state = fd_bind_compute_state;
738bf215546Sopenharmony_ci      pctx->set_compute_resources = fd_set_compute_resources;
739bf215546Sopenharmony_ci      pctx->set_global_binding = fd_set_global_binding;
740bf215546Sopenharmony_ci   }
741bf215546Sopenharmony_ci}
742