1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci /**
29bf215546Sopenharmony_ci  * @file
30bf215546Sopenharmony_ci  *
31bf215546Sopenharmony_ci  * Wrap the cso cache & hash mechanisms in a simplified
32bf215546Sopenharmony_ci  * pipe-driver-specific interface.
33bf215546Sopenharmony_ci  *
34bf215546Sopenharmony_ci  * @author Zack Rusin <zackr@vmware.com>
35bf215546Sopenharmony_ci  * @author Keith Whitwell <keithw@vmware.com>
36bf215546Sopenharmony_ci  */
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci#include "pipe/p_state.h"
39bf215546Sopenharmony_ci#include "util/u_draw.h"
40bf215546Sopenharmony_ci#include "util/u_framebuffer.h"
41bf215546Sopenharmony_ci#include "util/u_helpers.h"
42bf215546Sopenharmony_ci#include "util/u_inlines.h"
43bf215546Sopenharmony_ci#include "util/u_math.h"
44bf215546Sopenharmony_ci#include "util/u_memory.h"
45bf215546Sopenharmony_ci#include "util/u_vbuf.h"
46bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h"
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci#include "cso_cache/cso_context.h"
49bf215546Sopenharmony_ci#include "cso_cache/cso_cache.h"
50bf215546Sopenharmony_ci#include "cso_cache/cso_hash.h"
51bf215546Sopenharmony_ci#include "cso_context.h"
52bf215546Sopenharmony_ci#include "driver_trace/tr_dump.h"
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci/**
55bf215546Sopenharmony_ci * Per-shader sampler information.
56bf215546Sopenharmony_ci */
57bf215546Sopenharmony_cistruct sampler_info
58bf215546Sopenharmony_ci{
59bf215546Sopenharmony_ci   struct cso_sampler *cso_samplers[PIPE_MAX_SAMPLERS];
60bf215546Sopenharmony_ci   void *samplers[PIPE_MAX_SAMPLERS];
61bf215546Sopenharmony_ci};
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_cistruct cso_context {
66bf215546Sopenharmony_ci   struct pipe_context *pipe;
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci   struct u_vbuf *vbuf;
69bf215546Sopenharmony_ci   struct u_vbuf *vbuf_current;
70bf215546Sopenharmony_ci   bool always_use_vbuf;
71bf215546Sopenharmony_ci   bool sampler_format;
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ci   boolean has_geometry_shader;
74bf215546Sopenharmony_ci   boolean has_tessellation;
75bf215546Sopenharmony_ci   boolean has_compute_shader;
76bf215546Sopenharmony_ci   boolean has_streamout;
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci   uint32_t max_fs_samplerviews : 16;
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci   unsigned saved_state;  /**< bitmask of CSO_BIT_x flags */
81bf215546Sopenharmony_ci   unsigned saved_compute_state;  /**< bitmask of CSO_BIT_COMPUTE_x flags */
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci   struct sampler_info fragment_samplers_saved;
84bf215546Sopenharmony_ci   struct sampler_info compute_samplers_saved;
85bf215546Sopenharmony_ci   struct sampler_info samplers[PIPE_SHADER_TYPES];
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   /* Temporary number until cso_single_sampler_done is called.
88bf215546Sopenharmony_ci    * It tracks the highest sampler seen in cso_single_sampler.
89bf215546Sopenharmony_ci    */
90bf215546Sopenharmony_ci   int max_sampler_seen;
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci   unsigned nr_so_targets;
93bf215546Sopenharmony_ci   struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_BUFFERS];
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci   unsigned nr_so_targets_saved;
96bf215546Sopenharmony_ci   struct pipe_stream_output_target *so_targets_saved[PIPE_MAX_SO_BUFFERS];
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci   /** Current and saved state.
99bf215546Sopenharmony_ci    * The saved state is used as a 1-deep stack.
100bf215546Sopenharmony_ci    */
101bf215546Sopenharmony_ci   void *blend, *blend_saved;
102bf215546Sopenharmony_ci   void *depth_stencil, *depth_stencil_saved;
103bf215546Sopenharmony_ci   void *rasterizer, *rasterizer_saved;
104bf215546Sopenharmony_ci   void *fragment_shader, *fragment_shader_saved;
105bf215546Sopenharmony_ci   void *vertex_shader, *vertex_shader_saved;
106bf215546Sopenharmony_ci   void *geometry_shader, *geometry_shader_saved;
107bf215546Sopenharmony_ci   void *tessctrl_shader, *tessctrl_shader_saved;
108bf215546Sopenharmony_ci   void *tesseval_shader, *tesseval_shader_saved;
109bf215546Sopenharmony_ci   void *compute_shader, *compute_shader_saved;
110bf215546Sopenharmony_ci   void *velements, *velements_saved;
111bf215546Sopenharmony_ci   struct pipe_query *render_condition, *render_condition_saved;
112bf215546Sopenharmony_ci   uint render_condition_mode, render_condition_mode_saved;
113bf215546Sopenharmony_ci   boolean render_condition_cond, render_condition_cond_saved;
114bf215546Sopenharmony_ci   bool flatshade_first, flatshade_first_saved;
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci   struct pipe_framebuffer_state fb, fb_saved;
117bf215546Sopenharmony_ci   struct pipe_viewport_state vp, vp_saved;
118bf215546Sopenharmony_ci   unsigned sample_mask, sample_mask_saved;
119bf215546Sopenharmony_ci   unsigned min_samples, min_samples_saved;
120bf215546Sopenharmony_ci   struct pipe_stencil_ref stencil_ref, stencil_ref_saved;
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   /* This should be last to keep all of the above together in memory. */
123bf215546Sopenharmony_ci   struct cso_cache cache;
124bf215546Sopenharmony_ci};
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_cistruct pipe_context *cso_get_pipe_context(struct cso_context *cso)
127bf215546Sopenharmony_ci{
128bf215546Sopenharmony_ci   return cso->pipe;
129bf215546Sopenharmony_ci}
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_cistatic inline boolean delete_cso(struct cso_context *ctx,
132bf215546Sopenharmony_ci                                 void *state, enum cso_cache_type type)
133bf215546Sopenharmony_ci{
134bf215546Sopenharmony_ci   switch (type) {
135bf215546Sopenharmony_ci   case CSO_BLEND:
136bf215546Sopenharmony_ci      if (ctx->blend == ((struct cso_blend*)state)->data)
137bf215546Sopenharmony_ci         return false;
138bf215546Sopenharmony_ci      break;
139bf215546Sopenharmony_ci   case CSO_DEPTH_STENCIL_ALPHA:
140bf215546Sopenharmony_ci      if (ctx->depth_stencil == ((struct cso_depth_stencil_alpha*)state)->data)
141bf215546Sopenharmony_ci         return false;
142bf215546Sopenharmony_ci      break;
143bf215546Sopenharmony_ci   case CSO_RASTERIZER:
144bf215546Sopenharmony_ci      if (ctx->rasterizer == ((struct cso_rasterizer*)state)->data)
145bf215546Sopenharmony_ci         return false;
146bf215546Sopenharmony_ci      break;
147bf215546Sopenharmony_ci   case CSO_VELEMENTS:
148bf215546Sopenharmony_ci      if (ctx->velements == ((struct cso_velements*)state)->data)
149bf215546Sopenharmony_ci         return false;
150bf215546Sopenharmony_ci      break;
151bf215546Sopenharmony_ci   case CSO_SAMPLER:
152bf215546Sopenharmony_ci      /* nothing to do for samplers */
153bf215546Sopenharmony_ci      break;
154bf215546Sopenharmony_ci   default:
155bf215546Sopenharmony_ci      assert(0);
156bf215546Sopenharmony_ci   }
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci   cso_delete_state(ctx->pipe, state, type);
159bf215546Sopenharmony_ci   return true;
160bf215546Sopenharmony_ci}
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_cistatic inline void
163bf215546Sopenharmony_cisanitize_hash(struct cso_hash *hash, enum cso_cache_type type,
164bf215546Sopenharmony_ci              int max_size, void *user_data)
165bf215546Sopenharmony_ci{
166bf215546Sopenharmony_ci   struct cso_context *ctx = (struct cso_context *)user_data;
167bf215546Sopenharmony_ci   /* if we're approach the maximum size, remove fourth of the entries
168bf215546Sopenharmony_ci    * otherwise every subsequent call will go through the same */
169bf215546Sopenharmony_ci   int hash_size = cso_hash_size(hash);
170bf215546Sopenharmony_ci   int max_entries = (max_size > hash_size) ? max_size : hash_size;
171bf215546Sopenharmony_ci   int to_remove =  (max_size < max_entries) * max_entries/4;
172bf215546Sopenharmony_ci   struct cso_hash_iter iter;
173bf215546Sopenharmony_ci   struct cso_sampler **samplers_to_restore = NULL;
174bf215546Sopenharmony_ci   unsigned to_restore = 0;
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci   if (hash_size > max_size)
177bf215546Sopenharmony_ci      to_remove += hash_size - max_size;
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci   if (to_remove == 0)
180bf215546Sopenharmony_ci      return;
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci   if (type == CSO_SAMPLER) {
183bf215546Sopenharmony_ci      int i, j;
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci      samplers_to_restore = MALLOC(PIPE_SHADER_TYPES * PIPE_MAX_SAMPLERS *
186bf215546Sopenharmony_ci                                   sizeof(*samplers_to_restore));
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci      /* Temporarily remove currently bound sampler states from the hash
189bf215546Sopenharmony_ci       * table, to prevent them from being deleted
190bf215546Sopenharmony_ci       */
191bf215546Sopenharmony_ci      for (i = 0; i < PIPE_SHADER_TYPES; i++) {
192bf215546Sopenharmony_ci         for (j = 0; j < PIPE_MAX_SAMPLERS; j++) {
193bf215546Sopenharmony_ci            struct cso_sampler *sampler = ctx->samplers[i].cso_samplers[j];
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci            if (sampler && cso_hash_take(hash, sampler->hash_key))
196bf215546Sopenharmony_ci               samplers_to_restore[to_restore++] = sampler;
197bf215546Sopenharmony_ci         }
198bf215546Sopenharmony_ci      }
199bf215546Sopenharmony_ci   }
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci   iter = cso_hash_first_node(hash);
202bf215546Sopenharmony_ci   while (to_remove) {
203bf215546Sopenharmony_ci      /*remove elements until we're good */
204bf215546Sopenharmony_ci      /*fixme: currently we pick the nodes to remove at random*/
205bf215546Sopenharmony_ci      void *cso = cso_hash_iter_data(iter);
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ci      if (!cso)
208bf215546Sopenharmony_ci         break;
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci      if (delete_cso(ctx, cso, type)) {
211bf215546Sopenharmony_ci         iter = cso_hash_erase(hash, iter);
212bf215546Sopenharmony_ci         --to_remove;
213bf215546Sopenharmony_ci      } else
214bf215546Sopenharmony_ci         iter = cso_hash_iter_next(iter);
215bf215546Sopenharmony_ci   }
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ci   if (type == CSO_SAMPLER) {
218bf215546Sopenharmony_ci      /* Put currently bound sampler states back into the hash table */
219bf215546Sopenharmony_ci      while (to_restore--) {
220bf215546Sopenharmony_ci         struct cso_sampler *sampler = samplers_to_restore[to_restore];
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_ci         cso_hash_insert(hash, sampler->hash_key, sampler);
223bf215546Sopenharmony_ci      }
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci      FREE(samplers_to_restore);
226bf215546Sopenharmony_ci   }
227bf215546Sopenharmony_ci}
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_cistatic void cso_init_vbuf(struct cso_context *cso, unsigned flags)
230bf215546Sopenharmony_ci{
231bf215546Sopenharmony_ci   struct u_vbuf_caps caps;
232bf215546Sopenharmony_ci   bool uses_user_vertex_buffers = !(flags & CSO_NO_USER_VERTEX_BUFFERS);
233bf215546Sopenharmony_ci   bool needs64b = !(flags & CSO_NO_64B_VERTEX_BUFFERS);
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci   u_vbuf_get_caps(cso->pipe->screen, &caps, needs64b);
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_ci   /* Enable u_vbuf if needed. */
238bf215546Sopenharmony_ci   if (caps.fallback_always ||
239bf215546Sopenharmony_ci       (uses_user_vertex_buffers &&
240bf215546Sopenharmony_ci        caps.fallback_only_for_user_vbuffers)) {
241bf215546Sopenharmony_ci      cso->vbuf = u_vbuf_create(cso->pipe, &caps);
242bf215546Sopenharmony_ci      cso->vbuf_current = cso->vbuf;
243bf215546Sopenharmony_ci      cso->always_use_vbuf = caps.fallback_always;
244bf215546Sopenharmony_ci   }
245bf215546Sopenharmony_ci}
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_cistruct cso_context *
248bf215546Sopenharmony_cicso_create_context(struct pipe_context *pipe, unsigned flags)
249bf215546Sopenharmony_ci{
250bf215546Sopenharmony_ci   struct cso_context *ctx = CALLOC_STRUCT(cso_context);
251bf215546Sopenharmony_ci   if (!ctx)
252bf215546Sopenharmony_ci      return NULL;
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   cso_cache_init(&ctx->cache, pipe);
255bf215546Sopenharmony_ci   cso_cache_set_sanitize_callback(&ctx->cache, sanitize_hash, ctx);
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_ci   ctx->pipe = pipe;
258bf215546Sopenharmony_ci   ctx->sample_mask = ~0;
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci   if (!(flags & CSO_NO_VBUF))
261bf215546Sopenharmony_ci      cso_init_vbuf(ctx, flags);
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci   /* Enable for testing: */
264bf215546Sopenharmony_ci   if (0) cso_set_maximum_cache_size(&ctx->cache, 4);
265bf215546Sopenharmony_ci
266bf215546Sopenharmony_ci   if (pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY,
267bf215546Sopenharmony_ci                                PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) {
268bf215546Sopenharmony_ci      ctx->has_geometry_shader = TRUE;
269bf215546Sopenharmony_ci   }
270bf215546Sopenharmony_ci   if (pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_TESS_CTRL,
271bf215546Sopenharmony_ci                                PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) {
272bf215546Sopenharmony_ci      ctx->has_tessellation = TRUE;
273bf215546Sopenharmony_ci   }
274bf215546Sopenharmony_ci   if (pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_COMPUTE,
275bf215546Sopenharmony_ci                                      PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) {
276bf215546Sopenharmony_ci      int supported_irs =
277bf215546Sopenharmony_ci         pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_COMPUTE,
278bf215546Sopenharmony_ci                                        PIPE_SHADER_CAP_SUPPORTED_IRS);
279bf215546Sopenharmony_ci      if (supported_irs & ((1 << PIPE_SHADER_IR_TGSI) |
280bf215546Sopenharmony_ci                           (1 << PIPE_SHADER_IR_NIR))) {
281bf215546Sopenharmony_ci         ctx->has_compute_shader = TRUE;
282bf215546Sopenharmony_ci      }
283bf215546Sopenharmony_ci   }
284bf215546Sopenharmony_ci   if (pipe->screen->get_param(pipe->screen,
285bf215546Sopenharmony_ci                               PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0) {
286bf215546Sopenharmony_ci      ctx->has_streamout = TRUE;
287bf215546Sopenharmony_ci   }
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_ci   if (pipe->screen->get_param(pipe->screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) &
290bf215546Sopenharmony_ci       PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO)
291bf215546Sopenharmony_ci      ctx->sampler_format = true;
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci   ctx->max_fs_samplerviews = pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_FRAGMENT,
294bf215546Sopenharmony_ci                                                             PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS);
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci   ctx->max_sampler_seen = -1;
297bf215546Sopenharmony_ci   return ctx;
298bf215546Sopenharmony_ci}
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_civoid cso_unbind_context(struct cso_context *ctx)
301bf215546Sopenharmony_ci{
302bf215546Sopenharmony_ci   unsigned i;
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_ci   bool dumping = trace_dumping_enabled_locked();
305bf215546Sopenharmony_ci   if (dumping)
306bf215546Sopenharmony_ci      trace_dumping_stop_locked();
307bf215546Sopenharmony_ci   if (ctx->pipe) {
308bf215546Sopenharmony_ci      ctx->pipe->bind_blend_state( ctx->pipe, NULL );
309bf215546Sopenharmony_ci      ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL );
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci      {
312bf215546Sopenharmony_ci         static struct pipe_sampler_view *views[PIPE_MAX_SHADER_SAMPLER_VIEWS] = { NULL };
313bf215546Sopenharmony_ci         static struct pipe_shader_buffer ssbos[PIPE_MAX_SHADER_BUFFERS] = { 0 };
314bf215546Sopenharmony_ci         static void *zeros[PIPE_MAX_SAMPLERS] = { NULL };
315bf215546Sopenharmony_ci         struct pipe_screen *scr = ctx->pipe->screen;
316bf215546Sopenharmony_ci         enum pipe_shader_type sh;
317bf215546Sopenharmony_ci         for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) {
318bf215546Sopenharmony_ci            switch (sh) {
319bf215546Sopenharmony_ci            case PIPE_SHADER_GEOMETRY:
320bf215546Sopenharmony_ci               if (!ctx->has_geometry_shader)
321bf215546Sopenharmony_ci                  continue;
322bf215546Sopenharmony_ci               break;
323bf215546Sopenharmony_ci            case PIPE_SHADER_TESS_CTRL:
324bf215546Sopenharmony_ci            case PIPE_SHADER_TESS_EVAL:
325bf215546Sopenharmony_ci               if (!ctx->has_tessellation)
326bf215546Sopenharmony_ci                  continue;
327bf215546Sopenharmony_ci               break;
328bf215546Sopenharmony_ci            case PIPE_SHADER_COMPUTE:
329bf215546Sopenharmony_ci               if (!ctx->has_compute_shader)
330bf215546Sopenharmony_ci                  continue;
331bf215546Sopenharmony_ci               break;
332bf215546Sopenharmony_ci            default:
333bf215546Sopenharmony_ci               break;
334bf215546Sopenharmony_ci            }
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ci            int maxsam = scr->get_shader_param(scr, sh,
337bf215546Sopenharmony_ci                                               PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS);
338bf215546Sopenharmony_ci            int maxview = scr->get_shader_param(scr, sh,
339bf215546Sopenharmony_ci                                                PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS);
340bf215546Sopenharmony_ci            int maxssbo = scr->get_shader_param(scr, sh,
341bf215546Sopenharmony_ci                                                PIPE_SHADER_CAP_MAX_SHADER_BUFFERS);
342bf215546Sopenharmony_ci            int maxcb = scr->get_shader_param(scr, sh,
343bf215546Sopenharmony_ci                                              PIPE_SHADER_CAP_MAX_CONST_BUFFERS);
344bf215546Sopenharmony_ci            int maximg = scr->get_shader_param(scr, sh,
345bf215546Sopenharmony_ci                                              PIPE_SHADER_CAP_MAX_SHADER_IMAGES);
346bf215546Sopenharmony_ci            assert(maxsam <= PIPE_MAX_SAMPLERS);
347bf215546Sopenharmony_ci            assert(maxview <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
348bf215546Sopenharmony_ci            assert(maxssbo <= PIPE_MAX_SHADER_BUFFERS);
349bf215546Sopenharmony_ci            assert(maxcb <= PIPE_MAX_CONSTANT_BUFFERS);
350bf215546Sopenharmony_ci            assert(maximg <= PIPE_MAX_SHADER_IMAGES);
351bf215546Sopenharmony_ci            if (maxsam > 0) {
352bf215546Sopenharmony_ci               ctx->pipe->bind_sampler_states(ctx->pipe, sh, 0, maxsam, zeros);
353bf215546Sopenharmony_ci            }
354bf215546Sopenharmony_ci            if (maxview > 0) {
355bf215546Sopenharmony_ci               ctx->pipe->set_sampler_views(ctx->pipe, sh, 0, maxview, 0, false, views);
356bf215546Sopenharmony_ci            }
357bf215546Sopenharmony_ci            if (maxssbo > 0) {
358bf215546Sopenharmony_ci               ctx->pipe->set_shader_buffers(ctx->pipe, sh, 0, maxssbo, ssbos, 0);
359bf215546Sopenharmony_ci            }
360bf215546Sopenharmony_ci            if (maximg > 0) {
361bf215546Sopenharmony_ci               ctx->pipe->set_shader_images(ctx->pipe, sh, 0, 0, maximg, NULL);
362bf215546Sopenharmony_ci            }
363bf215546Sopenharmony_ci            for (int i = 0; i < maxcb; i++) {
364bf215546Sopenharmony_ci               ctx->pipe->set_constant_buffer(ctx->pipe, sh, i, false, NULL);
365bf215546Sopenharmony_ci            }
366bf215546Sopenharmony_ci         }
367bf215546Sopenharmony_ci      }
368bf215546Sopenharmony_ci
369bf215546Sopenharmony_ci      ctx->pipe->bind_depth_stencil_alpha_state( ctx->pipe, NULL );
370bf215546Sopenharmony_ci      struct pipe_stencil_ref sr = {0};
371bf215546Sopenharmony_ci      ctx->pipe->set_stencil_ref(ctx->pipe, sr);
372bf215546Sopenharmony_ci      ctx->pipe->bind_fs_state( ctx->pipe, NULL );
373bf215546Sopenharmony_ci      ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, false, NULL);
374bf215546Sopenharmony_ci      ctx->pipe->bind_vs_state( ctx->pipe, NULL );
375bf215546Sopenharmony_ci      ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, false, NULL);
376bf215546Sopenharmony_ci      if (ctx->has_geometry_shader) {
377bf215546Sopenharmony_ci         ctx->pipe->bind_gs_state(ctx->pipe, NULL);
378bf215546Sopenharmony_ci      }
379bf215546Sopenharmony_ci      if (ctx->has_tessellation) {
380bf215546Sopenharmony_ci         ctx->pipe->bind_tcs_state(ctx->pipe, NULL);
381bf215546Sopenharmony_ci         ctx->pipe->bind_tes_state(ctx->pipe, NULL);
382bf215546Sopenharmony_ci      }
383bf215546Sopenharmony_ci      if (ctx->has_compute_shader) {
384bf215546Sopenharmony_ci         ctx->pipe->bind_compute_state(ctx->pipe, NULL);
385bf215546Sopenharmony_ci      }
386bf215546Sopenharmony_ci      ctx->pipe->bind_vertex_elements_state( ctx->pipe, NULL );
387bf215546Sopenharmony_ci
388bf215546Sopenharmony_ci      if (ctx->has_streamout)
389bf215546Sopenharmony_ci         ctx->pipe->set_stream_output_targets(ctx->pipe, 0, NULL, NULL);
390bf215546Sopenharmony_ci   }
391bf215546Sopenharmony_ci
392bf215546Sopenharmony_ci   util_unreference_framebuffer_state(&ctx->fb);
393bf215546Sopenharmony_ci   util_unreference_framebuffer_state(&ctx->fb_saved);
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci   for (i = 0; i < PIPE_MAX_SO_BUFFERS; i++) {
396bf215546Sopenharmony_ci      pipe_so_target_reference(&ctx->so_targets[i], NULL);
397bf215546Sopenharmony_ci      pipe_so_target_reference(&ctx->so_targets_saved[i], NULL);
398bf215546Sopenharmony_ci   }
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_ci   memset(&ctx->samplers, 0, sizeof(ctx->samplers));
401bf215546Sopenharmony_ci   memset(&ctx->nr_so_targets, 0, offsetof(struct cso_context, cache) - offsetof(struct cso_context, nr_so_targets));
402bf215546Sopenharmony_ci   ctx->sample_mask = ~0;
403bf215546Sopenharmony_ci   /*
404bf215546Sopenharmony_ci    * If the cso context is reused (with the same pipe context),
405bf215546Sopenharmony_ci    * need to really make sure the context state doesn't get out of sync.
406bf215546Sopenharmony_ci    */
407bf215546Sopenharmony_ci   ctx->pipe->set_sample_mask(ctx->pipe, ctx->sample_mask);
408bf215546Sopenharmony_ci   if (ctx->pipe->set_min_samples)
409bf215546Sopenharmony_ci      ctx->pipe->set_min_samples(ctx->pipe, ctx->min_samples);
410bf215546Sopenharmony_ci   if (dumping)
411bf215546Sopenharmony_ci      trace_dumping_start_locked();
412bf215546Sopenharmony_ci}
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_ci/**
415bf215546Sopenharmony_ci * Free the CSO context.
416bf215546Sopenharmony_ci */
417bf215546Sopenharmony_civoid cso_destroy_context( struct cso_context *ctx )
418bf215546Sopenharmony_ci{
419bf215546Sopenharmony_ci   cso_unbind_context(ctx);
420bf215546Sopenharmony_ci   cso_cache_delete(&ctx->cache);
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ci   if (ctx->vbuf)
423bf215546Sopenharmony_ci      u_vbuf_destroy(ctx->vbuf);
424bf215546Sopenharmony_ci   FREE( ctx );
425bf215546Sopenharmony_ci}
426bf215546Sopenharmony_ci
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_ci/* Those function will either find the state of the given template
429bf215546Sopenharmony_ci * in the cache or they will create a new state from the given
430bf215546Sopenharmony_ci * template, insert it in the cache and return it.
431bf215546Sopenharmony_ci */
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_ci/*
434bf215546Sopenharmony_ci * If the driver returns 0 from the create method then they will assign
435bf215546Sopenharmony_ci * the data member of the cso to be the template itself.
436bf215546Sopenharmony_ci */
437bf215546Sopenharmony_ci
438bf215546Sopenharmony_cienum pipe_error cso_set_blend(struct cso_context *ctx,
439bf215546Sopenharmony_ci                              const struct pipe_blend_state *templ)
440bf215546Sopenharmony_ci{
441bf215546Sopenharmony_ci   unsigned key_size, hash_key;
442bf215546Sopenharmony_ci   struct cso_hash_iter iter;
443bf215546Sopenharmony_ci   void *handle;
444bf215546Sopenharmony_ci
445bf215546Sopenharmony_ci   key_size = templ->independent_blend_enable ?
446bf215546Sopenharmony_ci      sizeof(struct pipe_blend_state) :
447bf215546Sopenharmony_ci      (char *)&(templ->rt[1]) - (char *)templ;
448bf215546Sopenharmony_ci   hash_key = cso_construct_key((void*)templ, key_size);
449bf215546Sopenharmony_ci   iter = cso_find_state_template(&ctx->cache, hash_key, CSO_BLEND,
450bf215546Sopenharmony_ci                                  (void*)templ, key_size);
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ci   if (cso_hash_iter_is_null(iter)) {
453bf215546Sopenharmony_ci      struct cso_blend *cso = MALLOC(sizeof(struct cso_blend));
454bf215546Sopenharmony_ci      if (!cso)
455bf215546Sopenharmony_ci         return PIPE_ERROR_OUT_OF_MEMORY;
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci      memset(&cso->state, 0, sizeof cso->state);
458bf215546Sopenharmony_ci      memcpy(&cso->state, templ, key_size);
459bf215546Sopenharmony_ci      cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state);
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_ci      iter = cso_insert_state(&ctx->cache, hash_key, CSO_BLEND, cso);
462bf215546Sopenharmony_ci      if (cso_hash_iter_is_null(iter)) {
463bf215546Sopenharmony_ci         FREE(cso);
464bf215546Sopenharmony_ci         return PIPE_ERROR_OUT_OF_MEMORY;
465bf215546Sopenharmony_ci      }
466bf215546Sopenharmony_ci
467bf215546Sopenharmony_ci      handle = cso->data;
468bf215546Sopenharmony_ci   }
469bf215546Sopenharmony_ci   else {
470bf215546Sopenharmony_ci      handle = ((struct cso_blend *)cso_hash_iter_data(iter))->data;
471bf215546Sopenharmony_ci   }
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci   if (ctx->blend != handle) {
474bf215546Sopenharmony_ci      ctx->blend = handle;
475bf215546Sopenharmony_ci      ctx->pipe->bind_blend_state(ctx->pipe, handle);
476bf215546Sopenharmony_ci   }
477bf215546Sopenharmony_ci   return PIPE_OK;
478bf215546Sopenharmony_ci}
479bf215546Sopenharmony_ci
480bf215546Sopenharmony_cistatic void
481bf215546Sopenharmony_cicso_save_blend(struct cso_context *ctx)
482bf215546Sopenharmony_ci{
483bf215546Sopenharmony_ci   assert(!ctx->blend_saved);
484bf215546Sopenharmony_ci   ctx->blend_saved = ctx->blend;
485bf215546Sopenharmony_ci}
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_cistatic void
488bf215546Sopenharmony_cicso_restore_blend(struct cso_context *ctx)
489bf215546Sopenharmony_ci{
490bf215546Sopenharmony_ci   if (ctx->blend != ctx->blend_saved) {
491bf215546Sopenharmony_ci      ctx->blend = ctx->blend_saved;
492bf215546Sopenharmony_ci      ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend_saved);
493bf215546Sopenharmony_ci   }
494bf215546Sopenharmony_ci   ctx->blend_saved = NULL;
495bf215546Sopenharmony_ci}
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_cienum pipe_error
500bf215546Sopenharmony_cicso_set_depth_stencil_alpha(struct cso_context *ctx,
501bf215546Sopenharmony_ci                            const struct pipe_depth_stencil_alpha_state *templ)
502bf215546Sopenharmony_ci{
503bf215546Sopenharmony_ci   unsigned key_size = sizeof(struct pipe_depth_stencil_alpha_state);
504bf215546Sopenharmony_ci   unsigned hash_key = cso_construct_key((void*)templ, key_size);
505bf215546Sopenharmony_ci   struct cso_hash_iter iter = cso_find_state_template(&ctx->cache,
506bf215546Sopenharmony_ci                                                       hash_key,
507bf215546Sopenharmony_ci                                                       CSO_DEPTH_STENCIL_ALPHA,
508bf215546Sopenharmony_ci                                                       (void*)templ, key_size);
509bf215546Sopenharmony_ci   void *handle;
510bf215546Sopenharmony_ci
511bf215546Sopenharmony_ci   if (cso_hash_iter_is_null(iter)) {
512bf215546Sopenharmony_ci      struct cso_depth_stencil_alpha *cso =
513bf215546Sopenharmony_ci         MALLOC(sizeof(struct cso_depth_stencil_alpha));
514bf215546Sopenharmony_ci      if (!cso)
515bf215546Sopenharmony_ci         return PIPE_ERROR_OUT_OF_MEMORY;
516bf215546Sopenharmony_ci
517bf215546Sopenharmony_ci      memcpy(&cso->state, templ, sizeof(*templ));
518bf215546Sopenharmony_ci      cso->data = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe,
519bf215546Sopenharmony_ci                                                              &cso->state);
520bf215546Sopenharmony_ci
521bf215546Sopenharmony_ci      iter = cso_insert_state(&ctx->cache, hash_key,
522bf215546Sopenharmony_ci                              CSO_DEPTH_STENCIL_ALPHA, cso);
523bf215546Sopenharmony_ci      if (cso_hash_iter_is_null(iter)) {
524bf215546Sopenharmony_ci         FREE(cso);
525bf215546Sopenharmony_ci         return PIPE_ERROR_OUT_OF_MEMORY;
526bf215546Sopenharmony_ci      }
527bf215546Sopenharmony_ci
528bf215546Sopenharmony_ci      handle = cso->data;
529bf215546Sopenharmony_ci   }
530bf215546Sopenharmony_ci   else {
531bf215546Sopenharmony_ci      handle = ((struct cso_depth_stencil_alpha *)
532bf215546Sopenharmony_ci                cso_hash_iter_data(iter))->data;
533bf215546Sopenharmony_ci   }
534bf215546Sopenharmony_ci
535bf215546Sopenharmony_ci   if (ctx->depth_stencil != handle) {
536bf215546Sopenharmony_ci      ctx->depth_stencil = handle;
537bf215546Sopenharmony_ci      ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle);
538bf215546Sopenharmony_ci   }
539bf215546Sopenharmony_ci   return PIPE_OK;
540bf215546Sopenharmony_ci}
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_cistatic void
543bf215546Sopenharmony_cicso_save_depth_stencil_alpha(struct cso_context *ctx)
544bf215546Sopenharmony_ci{
545bf215546Sopenharmony_ci   assert(!ctx->depth_stencil_saved);
546bf215546Sopenharmony_ci   ctx->depth_stencil_saved = ctx->depth_stencil;
547bf215546Sopenharmony_ci}
548bf215546Sopenharmony_ci
549bf215546Sopenharmony_cistatic void
550bf215546Sopenharmony_cicso_restore_depth_stencil_alpha(struct cso_context *ctx)
551bf215546Sopenharmony_ci{
552bf215546Sopenharmony_ci   if (ctx->depth_stencil != ctx->depth_stencil_saved) {
553bf215546Sopenharmony_ci      ctx->depth_stencil = ctx->depth_stencil_saved;
554bf215546Sopenharmony_ci      ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe,
555bf215546Sopenharmony_ci                                                ctx->depth_stencil_saved);
556bf215546Sopenharmony_ci   }
557bf215546Sopenharmony_ci   ctx->depth_stencil_saved = NULL;
558bf215546Sopenharmony_ci}
559bf215546Sopenharmony_ci
560bf215546Sopenharmony_ci
561bf215546Sopenharmony_ci
562bf215546Sopenharmony_cienum pipe_error cso_set_rasterizer(struct cso_context *ctx,
563bf215546Sopenharmony_ci                                   const struct pipe_rasterizer_state *templ)
564bf215546Sopenharmony_ci{
565bf215546Sopenharmony_ci   unsigned key_size = sizeof(struct pipe_rasterizer_state);
566bf215546Sopenharmony_ci   unsigned hash_key = cso_construct_key((void*)templ, key_size);
567bf215546Sopenharmony_ci   struct cso_hash_iter iter = cso_find_state_template(&ctx->cache,
568bf215546Sopenharmony_ci                                                       hash_key,
569bf215546Sopenharmony_ci                                                       CSO_RASTERIZER,
570bf215546Sopenharmony_ci                                                       (void*)templ, key_size);
571bf215546Sopenharmony_ci   void *handle = NULL;
572bf215546Sopenharmony_ci
573bf215546Sopenharmony_ci   /* We can't have both point_quad_rasterization (sprites) and point_smooth
574bf215546Sopenharmony_ci    * (round AA points) enabled at the same time.
575bf215546Sopenharmony_ci    */
576bf215546Sopenharmony_ci   assert(!(templ->point_quad_rasterization && templ->point_smooth));
577bf215546Sopenharmony_ci
578bf215546Sopenharmony_ci   if (cso_hash_iter_is_null(iter)) {
579bf215546Sopenharmony_ci      struct cso_rasterizer *cso = MALLOC(sizeof(struct cso_rasterizer));
580bf215546Sopenharmony_ci      if (!cso)
581bf215546Sopenharmony_ci         return PIPE_ERROR_OUT_OF_MEMORY;
582bf215546Sopenharmony_ci
583bf215546Sopenharmony_ci      memcpy(&cso->state, templ, sizeof(*templ));
584bf215546Sopenharmony_ci      cso->data = ctx->pipe->create_rasterizer_state(ctx->pipe, &cso->state);
585bf215546Sopenharmony_ci
586bf215546Sopenharmony_ci      iter = cso_insert_state(&ctx->cache, hash_key, CSO_RASTERIZER, cso);
587bf215546Sopenharmony_ci      if (cso_hash_iter_is_null(iter)) {
588bf215546Sopenharmony_ci         FREE(cso);
589bf215546Sopenharmony_ci         return PIPE_ERROR_OUT_OF_MEMORY;
590bf215546Sopenharmony_ci      }
591bf215546Sopenharmony_ci
592bf215546Sopenharmony_ci      handle = cso->data;
593bf215546Sopenharmony_ci   }
594bf215546Sopenharmony_ci   else {
595bf215546Sopenharmony_ci      handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data;
596bf215546Sopenharmony_ci   }
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ci   if (ctx->rasterizer != handle) {
599bf215546Sopenharmony_ci      ctx->rasterizer = handle;
600bf215546Sopenharmony_ci      ctx->flatshade_first = templ->flatshade_first;
601bf215546Sopenharmony_ci      if (ctx->vbuf)
602bf215546Sopenharmony_ci         u_vbuf_set_flatshade_first(ctx->vbuf, ctx->flatshade_first);
603bf215546Sopenharmony_ci      ctx->pipe->bind_rasterizer_state(ctx->pipe, handle);
604bf215546Sopenharmony_ci   }
605bf215546Sopenharmony_ci   return PIPE_OK;
606bf215546Sopenharmony_ci}
607bf215546Sopenharmony_ci
608bf215546Sopenharmony_cistatic void
609bf215546Sopenharmony_cicso_save_rasterizer(struct cso_context *ctx)
610bf215546Sopenharmony_ci{
611bf215546Sopenharmony_ci   assert(!ctx->rasterizer_saved);
612bf215546Sopenharmony_ci   ctx->rasterizer_saved = ctx->rasterizer;
613bf215546Sopenharmony_ci   ctx->flatshade_first_saved = ctx->flatshade_first;
614bf215546Sopenharmony_ci}
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_cistatic void
617bf215546Sopenharmony_cicso_restore_rasterizer(struct cso_context *ctx)
618bf215546Sopenharmony_ci{
619bf215546Sopenharmony_ci   if (ctx->rasterizer != ctx->rasterizer_saved) {
620bf215546Sopenharmony_ci      ctx->rasterizer = ctx->rasterizer_saved;
621bf215546Sopenharmony_ci      ctx->flatshade_first = ctx->flatshade_first_saved;
622bf215546Sopenharmony_ci      if (ctx->vbuf)
623bf215546Sopenharmony_ci         u_vbuf_set_flatshade_first(ctx->vbuf, ctx->flatshade_first);
624bf215546Sopenharmony_ci      ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved);
625bf215546Sopenharmony_ci   }
626bf215546Sopenharmony_ci   ctx->rasterizer_saved = NULL;
627bf215546Sopenharmony_ci}
628bf215546Sopenharmony_ci
629bf215546Sopenharmony_ci
630bf215546Sopenharmony_civoid cso_set_fragment_shader_handle(struct cso_context *ctx, void *handle )
631bf215546Sopenharmony_ci{
632bf215546Sopenharmony_ci   if (ctx->fragment_shader != handle) {
633bf215546Sopenharmony_ci      ctx->fragment_shader = handle;
634bf215546Sopenharmony_ci      ctx->pipe->bind_fs_state(ctx->pipe, handle);
635bf215546Sopenharmony_ci   }
636bf215546Sopenharmony_ci}
637bf215546Sopenharmony_ci
638bf215546Sopenharmony_cistatic void
639bf215546Sopenharmony_cicso_save_fragment_shader(struct cso_context *ctx)
640bf215546Sopenharmony_ci{
641bf215546Sopenharmony_ci   assert(!ctx->fragment_shader_saved);
642bf215546Sopenharmony_ci   ctx->fragment_shader_saved = ctx->fragment_shader;
643bf215546Sopenharmony_ci}
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_cistatic void
646bf215546Sopenharmony_cicso_restore_fragment_shader(struct cso_context *ctx)
647bf215546Sopenharmony_ci{
648bf215546Sopenharmony_ci   if (ctx->fragment_shader_saved != ctx->fragment_shader) {
649bf215546Sopenharmony_ci      ctx->pipe->bind_fs_state(ctx->pipe, ctx->fragment_shader_saved);
650bf215546Sopenharmony_ci      ctx->fragment_shader = ctx->fragment_shader_saved;
651bf215546Sopenharmony_ci   }
652bf215546Sopenharmony_ci   ctx->fragment_shader_saved = NULL;
653bf215546Sopenharmony_ci}
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_ci
656bf215546Sopenharmony_civoid cso_set_vertex_shader_handle(struct cso_context *ctx, void *handle)
657bf215546Sopenharmony_ci{
658bf215546Sopenharmony_ci   if (ctx->vertex_shader != handle) {
659bf215546Sopenharmony_ci      ctx->vertex_shader = handle;
660bf215546Sopenharmony_ci      ctx->pipe->bind_vs_state(ctx->pipe, handle);
661bf215546Sopenharmony_ci   }
662bf215546Sopenharmony_ci}
663bf215546Sopenharmony_ci
664bf215546Sopenharmony_cistatic void
665bf215546Sopenharmony_cicso_save_vertex_shader(struct cso_context *ctx)
666bf215546Sopenharmony_ci{
667bf215546Sopenharmony_ci   assert(!ctx->vertex_shader_saved);
668bf215546Sopenharmony_ci   ctx->vertex_shader_saved = ctx->vertex_shader;
669bf215546Sopenharmony_ci}
670bf215546Sopenharmony_ci
671bf215546Sopenharmony_cistatic void
672bf215546Sopenharmony_cicso_restore_vertex_shader(struct cso_context *ctx)
673bf215546Sopenharmony_ci{
674bf215546Sopenharmony_ci   if (ctx->vertex_shader_saved != ctx->vertex_shader) {
675bf215546Sopenharmony_ci      ctx->pipe->bind_vs_state(ctx->pipe, ctx->vertex_shader_saved);
676bf215546Sopenharmony_ci      ctx->vertex_shader = ctx->vertex_shader_saved;
677bf215546Sopenharmony_ci   }
678bf215546Sopenharmony_ci   ctx->vertex_shader_saved = NULL;
679bf215546Sopenharmony_ci}
680bf215546Sopenharmony_ci
681bf215546Sopenharmony_ci
682bf215546Sopenharmony_civoid cso_set_framebuffer(struct cso_context *ctx,
683bf215546Sopenharmony_ci                         const struct pipe_framebuffer_state *fb)
684bf215546Sopenharmony_ci{
685bf215546Sopenharmony_ci   if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) {
686bf215546Sopenharmony_ci      util_copy_framebuffer_state(&ctx->fb, fb);
687bf215546Sopenharmony_ci      ctx->pipe->set_framebuffer_state(ctx->pipe, fb);
688bf215546Sopenharmony_ci   }
689bf215546Sopenharmony_ci}
690bf215546Sopenharmony_ci
691bf215546Sopenharmony_cistatic void
692bf215546Sopenharmony_cicso_save_framebuffer(struct cso_context *ctx)
693bf215546Sopenharmony_ci{
694bf215546Sopenharmony_ci   util_copy_framebuffer_state(&ctx->fb_saved, &ctx->fb);
695bf215546Sopenharmony_ci}
696bf215546Sopenharmony_ci
697bf215546Sopenharmony_cistatic void
698bf215546Sopenharmony_cicso_restore_framebuffer(struct cso_context *ctx)
699bf215546Sopenharmony_ci{
700bf215546Sopenharmony_ci   if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) {
701bf215546Sopenharmony_ci      util_copy_framebuffer_state(&ctx->fb, &ctx->fb_saved);
702bf215546Sopenharmony_ci      ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb);
703bf215546Sopenharmony_ci      util_unreference_framebuffer_state(&ctx->fb_saved);
704bf215546Sopenharmony_ci   }
705bf215546Sopenharmony_ci}
706bf215546Sopenharmony_ci
707bf215546Sopenharmony_ci
708bf215546Sopenharmony_civoid cso_set_viewport(struct cso_context *ctx,
709bf215546Sopenharmony_ci                      const struct pipe_viewport_state *vp)
710bf215546Sopenharmony_ci{
711bf215546Sopenharmony_ci   if (memcmp(&ctx->vp, vp, sizeof(*vp))) {
712bf215546Sopenharmony_ci      ctx->vp = *vp;
713bf215546Sopenharmony_ci      ctx->pipe->set_viewport_states(ctx->pipe, 0, 1, vp);
714bf215546Sopenharmony_ci   }
715bf215546Sopenharmony_ci}
716bf215546Sopenharmony_ci
717bf215546Sopenharmony_ci/**
718bf215546Sopenharmony_ci * Setup viewport state for given width and height (position is always (0,0)).
719bf215546Sopenharmony_ci * Invert the Y axis if 'invert' is true.
720bf215546Sopenharmony_ci */
721bf215546Sopenharmony_civoid
722bf215546Sopenharmony_cicso_set_viewport_dims(struct cso_context *ctx,
723bf215546Sopenharmony_ci                      float width, float height, boolean invert)
724bf215546Sopenharmony_ci{
725bf215546Sopenharmony_ci   struct pipe_viewport_state vp;
726bf215546Sopenharmony_ci   vp.scale[0] = width * 0.5f;
727bf215546Sopenharmony_ci   vp.scale[1] = height * (invert ? -0.5f : 0.5f);
728bf215546Sopenharmony_ci   vp.scale[2] = 0.5f;
729bf215546Sopenharmony_ci   vp.translate[0] = 0.5f * width;
730bf215546Sopenharmony_ci   vp.translate[1] = 0.5f * height;
731bf215546Sopenharmony_ci   vp.translate[2] = 0.5f;
732bf215546Sopenharmony_ci   vp.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X;
733bf215546Sopenharmony_ci   vp.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y;
734bf215546Sopenharmony_ci   vp.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z;
735bf215546Sopenharmony_ci   vp.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W;
736bf215546Sopenharmony_ci   cso_set_viewport(ctx, &vp);
737bf215546Sopenharmony_ci}
738bf215546Sopenharmony_ci
739bf215546Sopenharmony_cistatic void
740bf215546Sopenharmony_cicso_save_viewport(struct cso_context *ctx)
741bf215546Sopenharmony_ci{
742bf215546Sopenharmony_ci   ctx->vp_saved = ctx->vp;
743bf215546Sopenharmony_ci}
744bf215546Sopenharmony_ci
745bf215546Sopenharmony_ci
746bf215546Sopenharmony_cistatic void
747bf215546Sopenharmony_cicso_restore_viewport(struct cso_context *ctx)
748bf215546Sopenharmony_ci{
749bf215546Sopenharmony_ci   if (memcmp(&ctx->vp, &ctx->vp_saved, sizeof(ctx->vp))) {
750bf215546Sopenharmony_ci      ctx->vp = ctx->vp_saved;
751bf215546Sopenharmony_ci      ctx->pipe->set_viewport_states(ctx->pipe, 0, 1, &ctx->vp);
752bf215546Sopenharmony_ci   }
753bf215546Sopenharmony_ci}
754bf215546Sopenharmony_ci
755bf215546Sopenharmony_civoid cso_set_sample_mask(struct cso_context *ctx, unsigned sample_mask)
756bf215546Sopenharmony_ci{
757bf215546Sopenharmony_ci   if (ctx->sample_mask != sample_mask) {
758bf215546Sopenharmony_ci      ctx->sample_mask = sample_mask;
759bf215546Sopenharmony_ci      ctx->pipe->set_sample_mask(ctx->pipe, sample_mask);
760bf215546Sopenharmony_ci   }
761bf215546Sopenharmony_ci}
762bf215546Sopenharmony_ci
763bf215546Sopenharmony_cistatic void
764bf215546Sopenharmony_cicso_save_sample_mask(struct cso_context *ctx)
765bf215546Sopenharmony_ci{
766bf215546Sopenharmony_ci   ctx->sample_mask_saved = ctx->sample_mask;
767bf215546Sopenharmony_ci}
768bf215546Sopenharmony_ci
769bf215546Sopenharmony_cistatic void
770bf215546Sopenharmony_cicso_restore_sample_mask(struct cso_context *ctx)
771bf215546Sopenharmony_ci{
772bf215546Sopenharmony_ci   cso_set_sample_mask(ctx, ctx->sample_mask_saved);
773bf215546Sopenharmony_ci}
774bf215546Sopenharmony_ci
775bf215546Sopenharmony_civoid cso_set_min_samples(struct cso_context *ctx, unsigned min_samples)
776bf215546Sopenharmony_ci{
777bf215546Sopenharmony_ci   if (ctx->min_samples != min_samples && ctx->pipe->set_min_samples) {
778bf215546Sopenharmony_ci      ctx->min_samples = min_samples;
779bf215546Sopenharmony_ci      ctx->pipe->set_min_samples(ctx->pipe, min_samples);
780bf215546Sopenharmony_ci   }
781bf215546Sopenharmony_ci}
782bf215546Sopenharmony_ci
783bf215546Sopenharmony_cistatic void
784bf215546Sopenharmony_cicso_save_min_samples(struct cso_context *ctx)
785bf215546Sopenharmony_ci{
786bf215546Sopenharmony_ci   ctx->min_samples_saved = ctx->min_samples;
787bf215546Sopenharmony_ci}
788bf215546Sopenharmony_ci
789bf215546Sopenharmony_cistatic void
790bf215546Sopenharmony_cicso_restore_min_samples(struct cso_context *ctx)
791bf215546Sopenharmony_ci{
792bf215546Sopenharmony_ci   cso_set_min_samples(ctx, ctx->min_samples_saved);
793bf215546Sopenharmony_ci}
794bf215546Sopenharmony_ci
795bf215546Sopenharmony_civoid cso_set_stencil_ref(struct cso_context *ctx,
796bf215546Sopenharmony_ci                         const struct pipe_stencil_ref sr)
797bf215546Sopenharmony_ci{
798bf215546Sopenharmony_ci   if (memcmp(&ctx->stencil_ref, &sr, sizeof(ctx->stencil_ref))) {
799bf215546Sopenharmony_ci      ctx->stencil_ref = sr;
800bf215546Sopenharmony_ci      ctx->pipe->set_stencil_ref(ctx->pipe, sr);
801bf215546Sopenharmony_ci   }
802bf215546Sopenharmony_ci}
803bf215546Sopenharmony_ci
804bf215546Sopenharmony_cistatic void
805bf215546Sopenharmony_cicso_save_stencil_ref(struct cso_context *ctx)
806bf215546Sopenharmony_ci{
807bf215546Sopenharmony_ci   ctx->stencil_ref_saved = ctx->stencil_ref;
808bf215546Sopenharmony_ci}
809bf215546Sopenharmony_ci
810bf215546Sopenharmony_ci
811bf215546Sopenharmony_cistatic void
812bf215546Sopenharmony_cicso_restore_stencil_ref(struct cso_context *ctx)
813bf215546Sopenharmony_ci{
814bf215546Sopenharmony_ci   if (memcmp(&ctx->stencil_ref, &ctx->stencil_ref_saved,
815bf215546Sopenharmony_ci              sizeof(ctx->stencil_ref))) {
816bf215546Sopenharmony_ci      ctx->stencil_ref = ctx->stencil_ref_saved;
817bf215546Sopenharmony_ci      ctx->pipe->set_stencil_ref(ctx->pipe, ctx->stencil_ref);
818bf215546Sopenharmony_ci   }
819bf215546Sopenharmony_ci}
820bf215546Sopenharmony_ci
821bf215546Sopenharmony_civoid cso_set_render_condition(struct cso_context *ctx,
822bf215546Sopenharmony_ci                              struct pipe_query *query,
823bf215546Sopenharmony_ci                              boolean condition,
824bf215546Sopenharmony_ci                              enum pipe_render_cond_flag mode)
825bf215546Sopenharmony_ci{
826bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->pipe;
827bf215546Sopenharmony_ci
828bf215546Sopenharmony_ci   if (ctx->render_condition != query ||
829bf215546Sopenharmony_ci       ctx->render_condition_mode != mode ||
830bf215546Sopenharmony_ci       ctx->render_condition_cond != condition) {
831bf215546Sopenharmony_ci      pipe->render_condition(pipe, query, condition, mode);
832bf215546Sopenharmony_ci      ctx->render_condition = query;
833bf215546Sopenharmony_ci      ctx->render_condition_cond = condition;
834bf215546Sopenharmony_ci      ctx->render_condition_mode = mode;
835bf215546Sopenharmony_ci   }
836bf215546Sopenharmony_ci}
837bf215546Sopenharmony_ci
838bf215546Sopenharmony_cistatic void
839bf215546Sopenharmony_cicso_save_render_condition(struct cso_context *ctx)
840bf215546Sopenharmony_ci{
841bf215546Sopenharmony_ci   ctx->render_condition_saved = ctx->render_condition;
842bf215546Sopenharmony_ci   ctx->render_condition_cond_saved = ctx->render_condition_cond;
843bf215546Sopenharmony_ci   ctx->render_condition_mode_saved = ctx->render_condition_mode;
844bf215546Sopenharmony_ci}
845bf215546Sopenharmony_ci
846bf215546Sopenharmony_cistatic void
847bf215546Sopenharmony_cicso_restore_render_condition(struct cso_context *ctx)
848bf215546Sopenharmony_ci{
849bf215546Sopenharmony_ci   cso_set_render_condition(ctx, ctx->render_condition_saved,
850bf215546Sopenharmony_ci                            ctx->render_condition_cond_saved,
851bf215546Sopenharmony_ci                            ctx->render_condition_mode_saved);
852bf215546Sopenharmony_ci}
853bf215546Sopenharmony_ci
854bf215546Sopenharmony_civoid cso_set_geometry_shader_handle(struct cso_context *ctx, void *handle)
855bf215546Sopenharmony_ci{
856bf215546Sopenharmony_ci   assert(ctx->has_geometry_shader || !handle);
857bf215546Sopenharmony_ci
858bf215546Sopenharmony_ci   if (ctx->has_geometry_shader && ctx->geometry_shader != handle) {
859bf215546Sopenharmony_ci      ctx->geometry_shader = handle;
860bf215546Sopenharmony_ci      ctx->pipe->bind_gs_state(ctx->pipe, handle);
861bf215546Sopenharmony_ci   }
862bf215546Sopenharmony_ci}
863bf215546Sopenharmony_ci
864bf215546Sopenharmony_cistatic void
865bf215546Sopenharmony_cicso_save_geometry_shader(struct cso_context *ctx)
866bf215546Sopenharmony_ci{
867bf215546Sopenharmony_ci   if (!ctx->has_geometry_shader) {
868bf215546Sopenharmony_ci      return;
869bf215546Sopenharmony_ci   }
870bf215546Sopenharmony_ci
871bf215546Sopenharmony_ci   assert(!ctx->geometry_shader_saved);
872bf215546Sopenharmony_ci   ctx->geometry_shader_saved = ctx->geometry_shader;
873bf215546Sopenharmony_ci}
874bf215546Sopenharmony_ci
875bf215546Sopenharmony_cistatic void
876bf215546Sopenharmony_cicso_restore_geometry_shader(struct cso_context *ctx)
877bf215546Sopenharmony_ci{
878bf215546Sopenharmony_ci   if (!ctx->has_geometry_shader) {
879bf215546Sopenharmony_ci      return;
880bf215546Sopenharmony_ci   }
881bf215546Sopenharmony_ci
882bf215546Sopenharmony_ci   if (ctx->geometry_shader_saved != ctx->geometry_shader) {
883bf215546Sopenharmony_ci      ctx->pipe->bind_gs_state(ctx->pipe, ctx->geometry_shader_saved);
884bf215546Sopenharmony_ci      ctx->geometry_shader = ctx->geometry_shader_saved;
885bf215546Sopenharmony_ci   }
886bf215546Sopenharmony_ci   ctx->geometry_shader_saved = NULL;
887bf215546Sopenharmony_ci}
888bf215546Sopenharmony_ci
889bf215546Sopenharmony_civoid cso_set_tessctrl_shader_handle(struct cso_context *ctx, void *handle)
890bf215546Sopenharmony_ci{
891bf215546Sopenharmony_ci   assert(ctx->has_tessellation || !handle);
892bf215546Sopenharmony_ci
893bf215546Sopenharmony_ci   if (ctx->has_tessellation && ctx->tessctrl_shader != handle) {
894bf215546Sopenharmony_ci      ctx->tessctrl_shader = handle;
895bf215546Sopenharmony_ci      ctx->pipe->bind_tcs_state(ctx->pipe, handle);
896bf215546Sopenharmony_ci   }
897bf215546Sopenharmony_ci}
898bf215546Sopenharmony_ci
899bf215546Sopenharmony_cistatic void
900bf215546Sopenharmony_cicso_save_tessctrl_shader(struct cso_context *ctx)
901bf215546Sopenharmony_ci{
902bf215546Sopenharmony_ci   if (!ctx->has_tessellation) {
903bf215546Sopenharmony_ci      return;
904bf215546Sopenharmony_ci   }
905bf215546Sopenharmony_ci
906bf215546Sopenharmony_ci   assert(!ctx->tessctrl_shader_saved);
907bf215546Sopenharmony_ci   ctx->tessctrl_shader_saved = ctx->tessctrl_shader;
908bf215546Sopenharmony_ci}
909bf215546Sopenharmony_ci
910bf215546Sopenharmony_cistatic void
911bf215546Sopenharmony_cicso_restore_tessctrl_shader(struct cso_context *ctx)
912bf215546Sopenharmony_ci{
913bf215546Sopenharmony_ci   if (!ctx->has_tessellation) {
914bf215546Sopenharmony_ci      return;
915bf215546Sopenharmony_ci   }
916bf215546Sopenharmony_ci
917bf215546Sopenharmony_ci   if (ctx->tessctrl_shader_saved != ctx->tessctrl_shader) {
918bf215546Sopenharmony_ci      ctx->pipe->bind_tcs_state(ctx->pipe, ctx->tessctrl_shader_saved);
919bf215546Sopenharmony_ci      ctx->tessctrl_shader = ctx->tessctrl_shader_saved;
920bf215546Sopenharmony_ci   }
921bf215546Sopenharmony_ci   ctx->tessctrl_shader_saved = NULL;
922bf215546Sopenharmony_ci}
923bf215546Sopenharmony_ci
924bf215546Sopenharmony_civoid cso_set_tesseval_shader_handle(struct cso_context *ctx, void *handle)
925bf215546Sopenharmony_ci{
926bf215546Sopenharmony_ci   assert(ctx->has_tessellation || !handle);
927bf215546Sopenharmony_ci
928bf215546Sopenharmony_ci   if (ctx->has_tessellation && ctx->tesseval_shader != handle) {
929bf215546Sopenharmony_ci      ctx->tesseval_shader = handle;
930bf215546Sopenharmony_ci      ctx->pipe->bind_tes_state(ctx->pipe, handle);
931bf215546Sopenharmony_ci   }
932bf215546Sopenharmony_ci}
933bf215546Sopenharmony_ci
934bf215546Sopenharmony_cistatic void
935bf215546Sopenharmony_cicso_save_tesseval_shader(struct cso_context *ctx)
936bf215546Sopenharmony_ci{
937bf215546Sopenharmony_ci   if (!ctx->has_tessellation) {
938bf215546Sopenharmony_ci      return;
939bf215546Sopenharmony_ci   }
940bf215546Sopenharmony_ci
941bf215546Sopenharmony_ci   assert(!ctx->tesseval_shader_saved);
942bf215546Sopenharmony_ci   ctx->tesseval_shader_saved = ctx->tesseval_shader;
943bf215546Sopenharmony_ci}
944bf215546Sopenharmony_ci
945bf215546Sopenharmony_cistatic void
946bf215546Sopenharmony_cicso_restore_tesseval_shader(struct cso_context *ctx)
947bf215546Sopenharmony_ci{
948bf215546Sopenharmony_ci   if (!ctx->has_tessellation) {
949bf215546Sopenharmony_ci      return;
950bf215546Sopenharmony_ci   }
951bf215546Sopenharmony_ci
952bf215546Sopenharmony_ci   if (ctx->tesseval_shader_saved != ctx->tesseval_shader) {
953bf215546Sopenharmony_ci      ctx->pipe->bind_tes_state(ctx->pipe, ctx->tesseval_shader_saved);
954bf215546Sopenharmony_ci      ctx->tesseval_shader = ctx->tesseval_shader_saved;
955bf215546Sopenharmony_ci   }
956bf215546Sopenharmony_ci   ctx->tesseval_shader_saved = NULL;
957bf215546Sopenharmony_ci}
958bf215546Sopenharmony_ci
959bf215546Sopenharmony_civoid cso_set_compute_shader_handle(struct cso_context *ctx, void *handle)
960bf215546Sopenharmony_ci{
961bf215546Sopenharmony_ci   assert(ctx->has_compute_shader || !handle);
962bf215546Sopenharmony_ci
963bf215546Sopenharmony_ci   if (ctx->has_compute_shader && ctx->compute_shader != handle) {
964bf215546Sopenharmony_ci      ctx->compute_shader = handle;
965bf215546Sopenharmony_ci      ctx->pipe->bind_compute_state(ctx->pipe, handle);
966bf215546Sopenharmony_ci   }
967bf215546Sopenharmony_ci}
968bf215546Sopenharmony_ci
969bf215546Sopenharmony_cistatic void
970bf215546Sopenharmony_cicso_save_compute_shader(struct cso_context *ctx)
971bf215546Sopenharmony_ci{
972bf215546Sopenharmony_ci   if (!ctx->has_compute_shader) {
973bf215546Sopenharmony_ci      return;
974bf215546Sopenharmony_ci   }
975bf215546Sopenharmony_ci
976bf215546Sopenharmony_ci   assert(!ctx->compute_shader_saved);
977bf215546Sopenharmony_ci   ctx->compute_shader_saved = ctx->compute_shader;
978bf215546Sopenharmony_ci}
979bf215546Sopenharmony_ci
980bf215546Sopenharmony_cistatic void
981bf215546Sopenharmony_cicso_restore_compute_shader(struct cso_context *ctx)
982bf215546Sopenharmony_ci{
983bf215546Sopenharmony_ci   if (!ctx->has_compute_shader) {
984bf215546Sopenharmony_ci      return;
985bf215546Sopenharmony_ci   }
986bf215546Sopenharmony_ci
987bf215546Sopenharmony_ci   if (ctx->compute_shader_saved != ctx->compute_shader) {
988bf215546Sopenharmony_ci      ctx->pipe->bind_compute_state(ctx->pipe, ctx->compute_shader_saved);
989bf215546Sopenharmony_ci      ctx->compute_shader = ctx->compute_shader_saved;
990bf215546Sopenharmony_ci   }
991bf215546Sopenharmony_ci   ctx->compute_shader_saved = NULL;
992bf215546Sopenharmony_ci}
993bf215546Sopenharmony_ci
994bf215546Sopenharmony_ci
995bf215546Sopenharmony_cistatic void
996bf215546Sopenharmony_cicso_save_compute_samplers(struct cso_context *ctx)
997bf215546Sopenharmony_ci{
998bf215546Sopenharmony_ci   struct sampler_info *info = &ctx->samplers[PIPE_SHADER_COMPUTE];
999bf215546Sopenharmony_ci   struct sampler_info *saved = &ctx->compute_samplers_saved;
1000bf215546Sopenharmony_ci
1001bf215546Sopenharmony_ci   memcpy(saved->cso_samplers, info->cso_samplers,
1002bf215546Sopenharmony_ci          sizeof(info->cso_samplers));
1003bf215546Sopenharmony_ci   memcpy(saved->samplers, info->samplers, sizeof(info->samplers));
1004bf215546Sopenharmony_ci}
1005bf215546Sopenharmony_ci
1006bf215546Sopenharmony_ci
1007bf215546Sopenharmony_cistatic void
1008bf215546Sopenharmony_cicso_restore_compute_samplers(struct cso_context *ctx)
1009bf215546Sopenharmony_ci{
1010bf215546Sopenharmony_ci   struct sampler_info *info = &ctx->samplers[PIPE_SHADER_COMPUTE];
1011bf215546Sopenharmony_ci   struct sampler_info *saved = &ctx->compute_samplers_saved;
1012bf215546Sopenharmony_ci
1013bf215546Sopenharmony_ci   memcpy(info->cso_samplers, saved->cso_samplers,
1014bf215546Sopenharmony_ci          sizeof(info->cso_samplers));
1015bf215546Sopenharmony_ci   memcpy(info->samplers, saved->samplers, sizeof(info->samplers));
1016bf215546Sopenharmony_ci
1017bf215546Sopenharmony_ci   for (int i = PIPE_MAX_SAMPLERS - 1; i >= 0; i--) {
1018bf215546Sopenharmony_ci      if (info->samplers[i]) {
1019bf215546Sopenharmony_ci         ctx->max_sampler_seen = i;
1020bf215546Sopenharmony_ci         break;
1021bf215546Sopenharmony_ci      }
1022bf215546Sopenharmony_ci   }
1023bf215546Sopenharmony_ci
1024bf215546Sopenharmony_ci   cso_single_sampler_done(ctx, PIPE_SHADER_COMPUTE);
1025bf215546Sopenharmony_ci}
1026bf215546Sopenharmony_ci
1027bf215546Sopenharmony_ci
1028bf215546Sopenharmony_cistatic void
1029bf215546Sopenharmony_cicso_set_vertex_elements_direct(struct cso_context *ctx,
1030bf215546Sopenharmony_ci                               const struct cso_velems_state *velems)
1031bf215546Sopenharmony_ci{
1032bf215546Sopenharmony_ci   unsigned key_size, hash_key;
1033bf215546Sopenharmony_ci   struct cso_hash_iter iter;
1034bf215546Sopenharmony_ci   void *handle;
1035bf215546Sopenharmony_ci
1036bf215546Sopenharmony_ci   /* Need to include the count into the stored state data too.
1037bf215546Sopenharmony_ci    * Otherwise first few count pipe_vertex_elements could be identical
1038bf215546Sopenharmony_ci    * even if count is different, and there's no guarantee the hash would
1039bf215546Sopenharmony_ci    * be different in that case neither.
1040bf215546Sopenharmony_ci    */
1041bf215546Sopenharmony_ci   key_size = sizeof(struct pipe_vertex_element) * velems->count +
1042bf215546Sopenharmony_ci              sizeof(unsigned);
1043bf215546Sopenharmony_ci   hash_key = cso_construct_key((void*)velems, key_size);
1044bf215546Sopenharmony_ci   iter = cso_find_state_template(&ctx->cache, hash_key, CSO_VELEMENTS,
1045bf215546Sopenharmony_ci                                  (void*)velems, key_size);
1046bf215546Sopenharmony_ci
1047bf215546Sopenharmony_ci   if (cso_hash_iter_is_null(iter)) {
1048bf215546Sopenharmony_ci      struct cso_velements *cso = MALLOC(sizeof(struct cso_velements));
1049bf215546Sopenharmony_ci      if (!cso)
1050bf215546Sopenharmony_ci         return;
1051bf215546Sopenharmony_ci
1052bf215546Sopenharmony_ci      memcpy(&cso->state, velems, key_size);
1053bf215546Sopenharmony_ci
1054bf215546Sopenharmony_ci      /* Lower 64-bit vertex attributes. */
1055bf215546Sopenharmony_ci      unsigned new_count = velems->count;
1056bf215546Sopenharmony_ci      const struct pipe_vertex_element *new_elems = velems->velems;
1057bf215546Sopenharmony_ci      struct pipe_vertex_element tmp[PIPE_MAX_ATTRIBS];
1058bf215546Sopenharmony_ci      util_lower_uint64_vertex_elements(&new_elems, &new_count, tmp);
1059bf215546Sopenharmony_ci
1060bf215546Sopenharmony_ci      cso->data = ctx->pipe->create_vertex_elements_state(ctx->pipe, new_count,
1061bf215546Sopenharmony_ci                                                          new_elems);
1062bf215546Sopenharmony_ci
1063bf215546Sopenharmony_ci      iter = cso_insert_state(&ctx->cache, hash_key, CSO_VELEMENTS, cso);
1064bf215546Sopenharmony_ci      if (cso_hash_iter_is_null(iter)) {
1065bf215546Sopenharmony_ci         FREE(cso);
1066bf215546Sopenharmony_ci         return;
1067bf215546Sopenharmony_ci      }
1068bf215546Sopenharmony_ci
1069bf215546Sopenharmony_ci      handle = cso->data;
1070bf215546Sopenharmony_ci   }
1071bf215546Sopenharmony_ci   else {
1072bf215546Sopenharmony_ci      handle = ((struct cso_velements *)cso_hash_iter_data(iter))->data;
1073bf215546Sopenharmony_ci   }
1074bf215546Sopenharmony_ci
1075bf215546Sopenharmony_ci   if (ctx->velements != handle) {
1076bf215546Sopenharmony_ci      ctx->velements = handle;
1077bf215546Sopenharmony_ci      ctx->pipe->bind_vertex_elements_state(ctx->pipe, handle);
1078bf215546Sopenharmony_ci   }
1079bf215546Sopenharmony_ci}
1080bf215546Sopenharmony_ci
1081bf215546Sopenharmony_cienum pipe_error
1082bf215546Sopenharmony_cicso_set_vertex_elements(struct cso_context *ctx,
1083bf215546Sopenharmony_ci                        const struct cso_velems_state *velems)
1084bf215546Sopenharmony_ci{
1085bf215546Sopenharmony_ci   struct u_vbuf *vbuf = ctx->vbuf_current;
1086bf215546Sopenharmony_ci
1087bf215546Sopenharmony_ci   if (vbuf) {
1088bf215546Sopenharmony_ci      u_vbuf_set_vertex_elements(vbuf, velems);
1089bf215546Sopenharmony_ci      return PIPE_OK;
1090bf215546Sopenharmony_ci   }
1091bf215546Sopenharmony_ci
1092bf215546Sopenharmony_ci   cso_set_vertex_elements_direct(ctx, velems);
1093bf215546Sopenharmony_ci   return PIPE_OK;
1094bf215546Sopenharmony_ci}
1095bf215546Sopenharmony_ci
1096bf215546Sopenharmony_cistatic void
1097bf215546Sopenharmony_cicso_save_vertex_elements(struct cso_context *ctx)
1098bf215546Sopenharmony_ci{
1099bf215546Sopenharmony_ci   struct u_vbuf *vbuf = ctx->vbuf_current;
1100bf215546Sopenharmony_ci
1101bf215546Sopenharmony_ci   if (vbuf) {
1102bf215546Sopenharmony_ci      u_vbuf_save_vertex_elements(vbuf);
1103bf215546Sopenharmony_ci      return;
1104bf215546Sopenharmony_ci   }
1105bf215546Sopenharmony_ci
1106bf215546Sopenharmony_ci   assert(!ctx->velements_saved);
1107bf215546Sopenharmony_ci   ctx->velements_saved = ctx->velements;
1108bf215546Sopenharmony_ci}
1109bf215546Sopenharmony_ci
1110bf215546Sopenharmony_cistatic void
1111bf215546Sopenharmony_cicso_restore_vertex_elements(struct cso_context *ctx)
1112bf215546Sopenharmony_ci{
1113bf215546Sopenharmony_ci   struct u_vbuf *vbuf = ctx->vbuf_current;
1114bf215546Sopenharmony_ci
1115bf215546Sopenharmony_ci   if (vbuf) {
1116bf215546Sopenharmony_ci      u_vbuf_restore_vertex_elements(vbuf);
1117bf215546Sopenharmony_ci      return;
1118bf215546Sopenharmony_ci   }
1119bf215546Sopenharmony_ci
1120bf215546Sopenharmony_ci   if (ctx->velements != ctx->velements_saved) {
1121bf215546Sopenharmony_ci      ctx->velements = ctx->velements_saved;
1122bf215546Sopenharmony_ci      ctx->pipe->bind_vertex_elements_state(ctx->pipe, ctx->velements_saved);
1123bf215546Sopenharmony_ci   }
1124bf215546Sopenharmony_ci   ctx->velements_saved = NULL;
1125bf215546Sopenharmony_ci}
1126bf215546Sopenharmony_ci
1127bf215546Sopenharmony_ci/* vertex buffers */
1128bf215546Sopenharmony_ci
1129bf215546Sopenharmony_civoid cso_set_vertex_buffers(struct cso_context *ctx,
1130bf215546Sopenharmony_ci                            unsigned start_slot, unsigned count,
1131bf215546Sopenharmony_ci                            unsigned unbind_trailing_count,
1132bf215546Sopenharmony_ci                            bool take_ownership,
1133bf215546Sopenharmony_ci                            const struct pipe_vertex_buffer *buffers)
1134bf215546Sopenharmony_ci{
1135bf215546Sopenharmony_ci   struct u_vbuf *vbuf = ctx->vbuf_current;
1136bf215546Sopenharmony_ci
1137bf215546Sopenharmony_ci   if (!count && !unbind_trailing_count)
1138bf215546Sopenharmony_ci      return;
1139bf215546Sopenharmony_ci
1140bf215546Sopenharmony_ci   if (vbuf) {
1141bf215546Sopenharmony_ci      u_vbuf_set_vertex_buffers(vbuf, start_slot, count, unbind_trailing_count,
1142bf215546Sopenharmony_ci                                take_ownership, buffers);
1143bf215546Sopenharmony_ci      return;
1144bf215546Sopenharmony_ci   }
1145bf215546Sopenharmony_ci
1146bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->pipe;
1147bf215546Sopenharmony_ci   pipe->set_vertex_buffers(pipe, start_slot, count, unbind_trailing_count,
1148bf215546Sopenharmony_ci                            take_ownership, buffers);
1149bf215546Sopenharmony_ci}
1150bf215546Sopenharmony_ci
1151bf215546Sopenharmony_ci/**
1152bf215546Sopenharmony_ci * Set vertex buffers and vertex elements. Skip u_vbuf if it's only needed
1153bf215546Sopenharmony_ci * for user vertex buffers and user vertex buffers are not set by this call.
1154bf215546Sopenharmony_ci * u_vbuf will be disabled. To re-enable u_vbuf, call this function again.
1155bf215546Sopenharmony_ci *
1156bf215546Sopenharmony_ci * Skipping u_vbuf decreases CPU overhead for draw calls that don't need it,
1157bf215546Sopenharmony_ci * such as VBOs, glBegin/End, and display lists.
1158bf215546Sopenharmony_ci *
1159bf215546Sopenharmony_ci * Internal operations that do "save states, draw, restore states" shouldn't
1160bf215546Sopenharmony_ci * use this, because the states are only saved in either cso_context or
1161bf215546Sopenharmony_ci * u_vbuf, not both.
1162bf215546Sopenharmony_ci */
1163bf215546Sopenharmony_civoid
1164bf215546Sopenharmony_cicso_set_vertex_buffers_and_elements(struct cso_context *ctx,
1165bf215546Sopenharmony_ci                                    const struct cso_velems_state *velems,
1166bf215546Sopenharmony_ci                                    unsigned vb_count,
1167bf215546Sopenharmony_ci                                    unsigned unbind_trailing_vb_count,
1168bf215546Sopenharmony_ci                                    bool take_ownership,
1169bf215546Sopenharmony_ci                                    bool uses_user_vertex_buffers,
1170bf215546Sopenharmony_ci                                    const struct pipe_vertex_buffer *vbuffers)
1171bf215546Sopenharmony_ci{
1172bf215546Sopenharmony_ci   struct u_vbuf *vbuf = ctx->vbuf;
1173bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->pipe;
1174bf215546Sopenharmony_ci
1175bf215546Sopenharmony_ci   if (vbuf && (ctx->always_use_vbuf || uses_user_vertex_buffers)) {
1176bf215546Sopenharmony_ci      if (!ctx->vbuf_current) {
1177bf215546Sopenharmony_ci         /* Unbind all buffers in cso_context, because we'll use u_vbuf. */
1178bf215546Sopenharmony_ci         unsigned unbind_vb_count = vb_count + unbind_trailing_vb_count;
1179bf215546Sopenharmony_ci         if (unbind_vb_count)
1180bf215546Sopenharmony_ci            pipe->set_vertex_buffers(pipe, 0, 0, unbind_vb_count, false, NULL);
1181bf215546Sopenharmony_ci
1182bf215546Sopenharmony_ci         /* Unset this to make sure the CSO is re-bound on the next use. */
1183bf215546Sopenharmony_ci         ctx->velements = NULL;
1184bf215546Sopenharmony_ci         ctx->vbuf_current = vbuf;
1185bf215546Sopenharmony_ci         unbind_trailing_vb_count = 0;
1186bf215546Sopenharmony_ci      }
1187bf215546Sopenharmony_ci
1188bf215546Sopenharmony_ci      if (vb_count || unbind_trailing_vb_count) {
1189bf215546Sopenharmony_ci         u_vbuf_set_vertex_buffers(vbuf, 0, vb_count,
1190bf215546Sopenharmony_ci                                   unbind_trailing_vb_count,
1191bf215546Sopenharmony_ci                                   take_ownership, vbuffers);
1192bf215546Sopenharmony_ci      }
1193bf215546Sopenharmony_ci      u_vbuf_set_vertex_elements(vbuf, velems);
1194bf215546Sopenharmony_ci      return;
1195bf215546Sopenharmony_ci   }
1196bf215546Sopenharmony_ci
1197bf215546Sopenharmony_ci   if (ctx->vbuf_current) {
1198bf215546Sopenharmony_ci      /* Unbind all buffers in u_vbuf, because we'll use cso_context. */
1199bf215546Sopenharmony_ci      unsigned unbind_vb_count = vb_count + unbind_trailing_vb_count;
1200bf215546Sopenharmony_ci      if (unbind_vb_count)
1201bf215546Sopenharmony_ci         u_vbuf_set_vertex_buffers(vbuf, 0, 0, unbind_vb_count, false, NULL);
1202bf215546Sopenharmony_ci
1203bf215546Sopenharmony_ci      /* Unset this to make sure the CSO is re-bound on the next use. */
1204bf215546Sopenharmony_ci      u_vbuf_unset_vertex_elements(vbuf);
1205bf215546Sopenharmony_ci      ctx->vbuf_current = NULL;
1206bf215546Sopenharmony_ci      unbind_trailing_vb_count = 0;
1207bf215546Sopenharmony_ci   }
1208bf215546Sopenharmony_ci
1209bf215546Sopenharmony_ci   if (vb_count || unbind_trailing_vb_count) {
1210bf215546Sopenharmony_ci      pipe->set_vertex_buffers(pipe, 0, vb_count, unbind_trailing_vb_count,
1211bf215546Sopenharmony_ci                               take_ownership, vbuffers);
1212bf215546Sopenharmony_ci   }
1213bf215546Sopenharmony_ci   cso_set_vertex_elements_direct(ctx, velems);
1214bf215546Sopenharmony_ci}
1215bf215546Sopenharmony_ci
1216bf215546Sopenharmony_ciALWAYS_INLINE static struct cso_sampler *
1217bf215546Sopenharmony_ciset_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage,
1218bf215546Sopenharmony_ci            unsigned idx, const struct pipe_sampler_state *templ, size_t key_size)
1219bf215546Sopenharmony_ci{
1220bf215546Sopenharmony_ci   unsigned hash_key = cso_construct_key((void*)templ, key_size);
1221bf215546Sopenharmony_ci   struct cso_sampler *cso;
1222bf215546Sopenharmony_ci   struct cso_hash_iter iter =
1223bf215546Sopenharmony_ci      cso_find_state_template(&ctx->cache,
1224bf215546Sopenharmony_ci                              hash_key, CSO_SAMPLER,
1225bf215546Sopenharmony_ci                              (void *) templ, key_size);
1226bf215546Sopenharmony_ci
1227bf215546Sopenharmony_ci   if (cso_hash_iter_is_null(iter)) {
1228bf215546Sopenharmony_ci      cso = MALLOC(sizeof(struct cso_sampler));
1229bf215546Sopenharmony_ci      if (!cso)
1230bf215546Sopenharmony_ci         return false;
1231bf215546Sopenharmony_ci
1232bf215546Sopenharmony_ci      memcpy(&cso->state, templ, sizeof(*templ));
1233bf215546Sopenharmony_ci      cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state);
1234bf215546Sopenharmony_ci      cso->hash_key = hash_key;
1235bf215546Sopenharmony_ci
1236bf215546Sopenharmony_ci      iter = cso_insert_state(&ctx->cache, hash_key, CSO_SAMPLER, cso);
1237bf215546Sopenharmony_ci      if (cso_hash_iter_is_null(iter)) {
1238bf215546Sopenharmony_ci         FREE(cso);
1239bf215546Sopenharmony_ci         return false;
1240bf215546Sopenharmony_ci      }
1241bf215546Sopenharmony_ci   } else {
1242bf215546Sopenharmony_ci      cso = cso_hash_iter_data(iter);
1243bf215546Sopenharmony_ci   }
1244bf215546Sopenharmony_ci   return cso;
1245bf215546Sopenharmony_ci}
1246bf215546Sopenharmony_ci
1247bf215546Sopenharmony_ciALWAYS_INLINE  static bool
1248bf215546Sopenharmony_cicso_set_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage,
1249bf215546Sopenharmony_ci                unsigned idx, const struct pipe_sampler_state *templ, size_t size)
1250bf215546Sopenharmony_ci{
1251bf215546Sopenharmony_ci   struct cso_sampler *cso = set_sampler(ctx, shader_stage, idx, templ, size);
1252bf215546Sopenharmony_ci   ctx->samplers[shader_stage].cso_samplers[idx] = cso;
1253bf215546Sopenharmony_ci   ctx->samplers[shader_stage].samplers[idx] = cso->data;
1254bf215546Sopenharmony_ci   return true;
1255bf215546Sopenharmony_ci}
1256bf215546Sopenharmony_ci
1257bf215546Sopenharmony_civoid
1258bf215546Sopenharmony_cicso_single_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage,
1259bf215546Sopenharmony_ci                   unsigned idx, const struct pipe_sampler_state *templ)
1260bf215546Sopenharmony_ci{
1261bf215546Sopenharmony_ci   size_t size = ctx->sampler_format ? sizeof(struct pipe_sampler_state) :
1262bf215546Sopenharmony_ci                                       offsetof(struct pipe_sampler_state, border_color_format);
1263bf215546Sopenharmony_ci   if (cso_set_sampler(ctx, shader_stage, idx, templ, size))
1264bf215546Sopenharmony_ci      ctx->max_sampler_seen = MAX2(ctx->max_sampler_seen, (int)idx);
1265bf215546Sopenharmony_ci}
1266bf215546Sopenharmony_ci
1267bf215546Sopenharmony_ci/**
1268bf215546Sopenharmony_ci * Send staged sampler state to the driver.
1269bf215546Sopenharmony_ci */
1270bf215546Sopenharmony_civoid
1271bf215546Sopenharmony_cicso_single_sampler_done(struct cso_context *ctx,
1272bf215546Sopenharmony_ci                        enum pipe_shader_type shader_stage)
1273bf215546Sopenharmony_ci{
1274bf215546Sopenharmony_ci   struct sampler_info *info = &ctx->samplers[shader_stage];
1275bf215546Sopenharmony_ci
1276bf215546Sopenharmony_ci   if (ctx->max_sampler_seen == -1)
1277bf215546Sopenharmony_ci      return;
1278bf215546Sopenharmony_ci
1279bf215546Sopenharmony_ci   ctx->pipe->bind_sampler_states(ctx->pipe, shader_stage, 0,
1280bf215546Sopenharmony_ci                                  ctx->max_sampler_seen + 1,
1281bf215546Sopenharmony_ci                                  info->samplers);
1282bf215546Sopenharmony_ci   ctx->max_sampler_seen = -1;
1283bf215546Sopenharmony_ci}
1284bf215546Sopenharmony_ci
1285bf215546Sopenharmony_ciALWAYS_INLINE static int
1286bf215546Sopenharmony_ciset_samplers(struct cso_context *ctx,
1287bf215546Sopenharmony_ci             enum pipe_shader_type shader_stage,
1288bf215546Sopenharmony_ci             unsigned nr,
1289bf215546Sopenharmony_ci             const struct pipe_sampler_state **templates,
1290bf215546Sopenharmony_ci             size_t key_size)
1291bf215546Sopenharmony_ci{
1292bf215546Sopenharmony_ci   int last = -1;
1293bf215546Sopenharmony_ci   for (unsigned i = 0; i < nr; i++) {
1294bf215546Sopenharmony_ci      if (!templates[i])
1295bf215546Sopenharmony_ci         continue;
1296bf215546Sopenharmony_ci
1297bf215546Sopenharmony_ci      /* Reuse the same sampler state CSO if 2 consecutive sampler states
1298bf215546Sopenharmony_ci       * are identical.
1299bf215546Sopenharmony_ci       *
1300bf215546Sopenharmony_ci       * The trivial case where both pointers are equal doesn't occur in
1301bf215546Sopenharmony_ci       * frequented codepaths.
1302bf215546Sopenharmony_ci       *
1303bf215546Sopenharmony_ci       * Reuse rate:
1304bf215546Sopenharmony_ci       * - Borderlands 2: 55%
1305bf215546Sopenharmony_ci       * - Hitman: 65%
1306bf215546Sopenharmony_ci       * - Rocket League: 75%
1307bf215546Sopenharmony_ci       * - Tomb Raider: 50-65%
1308bf215546Sopenharmony_ci       * - XCOM 2: 55%
1309bf215546Sopenharmony_ci       */
1310bf215546Sopenharmony_ci      if (last >= 0 &&
1311bf215546Sopenharmony_ci          !memcmp(templates[i], templates[last],
1312bf215546Sopenharmony_ci                  key_size)) {
1313bf215546Sopenharmony_ci         ctx->samplers[shader_stage].cso_samplers[i] =
1314bf215546Sopenharmony_ci            ctx->samplers[shader_stage].cso_samplers[last];
1315bf215546Sopenharmony_ci         ctx->samplers[shader_stage].samplers[i] =
1316bf215546Sopenharmony_ci            ctx->samplers[shader_stage].samplers[last];
1317bf215546Sopenharmony_ci      } else {
1318bf215546Sopenharmony_ci         /* Look up the sampler state CSO. */
1319bf215546Sopenharmony_ci         cso_set_sampler(ctx, shader_stage, i, templates[i], key_size);
1320bf215546Sopenharmony_ci      }
1321bf215546Sopenharmony_ci
1322bf215546Sopenharmony_ci      last = i;
1323bf215546Sopenharmony_ci   }
1324bf215546Sopenharmony_ci   return last;
1325bf215546Sopenharmony_ci}
1326bf215546Sopenharmony_ci
1327bf215546Sopenharmony_ci/*
1328bf215546Sopenharmony_ci * If the function encouters any errors it will return the
1329bf215546Sopenharmony_ci * last one. Done to always try to set as many samplers
1330bf215546Sopenharmony_ci * as possible.
1331bf215546Sopenharmony_ci */
1332bf215546Sopenharmony_civoid
1333bf215546Sopenharmony_cicso_set_samplers(struct cso_context *ctx,
1334bf215546Sopenharmony_ci                 enum pipe_shader_type shader_stage,
1335bf215546Sopenharmony_ci                 unsigned nr,
1336bf215546Sopenharmony_ci                 const struct pipe_sampler_state **templates)
1337bf215546Sopenharmony_ci{
1338bf215546Sopenharmony_ci   int last = -1;
1339bf215546Sopenharmony_ci
1340bf215546Sopenharmony_ci   /* ensure sampler size is a constant for memcmp */
1341bf215546Sopenharmony_ci   size_t size = ctx->sampler_format ? sizeof(struct pipe_sampler_state) :
1342bf215546Sopenharmony_ci                                       offsetof(struct pipe_sampler_state, border_color_format);
1343bf215546Sopenharmony_ci   last = set_samplers(ctx, shader_stage, nr, templates, size);
1344bf215546Sopenharmony_ci
1345bf215546Sopenharmony_ci   ctx->max_sampler_seen = MAX2(ctx->max_sampler_seen, last);
1346bf215546Sopenharmony_ci   cso_single_sampler_done(ctx, shader_stage);
1347bf215546Sopenharmony_ci}
1348bf215546Sopenharmony_ci
1349bf215546Sopenharmony_cistatic void
1350bf215546Sopenharmony_cicso_save_fragment_samplers(struct cso_context *ctx)
1351bf215546Sopenharmony_ci{
1352bf215546Sopenharmony_ci   struct sampler_info *info = &ctx->samplers[PIPE_SHADER_FRAGMENT];
1353bf215546Sopenharmony_ci   struct sampler_info *saved = &ctx->fragment_samplers_saved;
1354bf215546Sopenharmony_ci
1355bf215546Sopenharmony_ci   memcpy(saved->cso_samplers, info->cso_samplers,
1356bf215546Sopenharmony_ci          sizeof(info->cso_samplers));
1357bf215546Sopenharmony_ci   memcpy(saved->samplers, info->samplers, sizeof(info->samplers));
1358bf215546Sopenharmony_ci}
1359bf215546Sopenharmony_ci
1360bf215546Sopenharmony_ci
1361bf215546Sopenharmony_cistatic void
1362bf215546Sopenharmony_cicso_restore_fragment_samplers(struct cso_context *ctx)
1363bf215546Sopenharmony_ci{
1364bf215546Sopenharmony_ci   struct sampler_info *info = &ctx->samplers[PIPE_SHADER_FRAGMENT];
1365bf215546Sopenharmony_ci   struct sampler_info *saved = &ctx->fragment_samplers_saved;
1366bf215546Sopenharmony_ci
1367bf215546Sopenharmony_ci   memcpy(info->cso_samplers, saved->cso_samplers,
1368bf215546Sopenharmony_ci          sizeof(info->cso_samplers));
1369bf215546Sopenharmony_ci   memcpy(info->samplers, saved->samplers, sizeof(info->samplers));
1370bf215546Sopenharmony_ci
1371bf215546Sopenharmony_ci   for (int i = PIPE_MAX_SAMPLERS - 1; i >= 0; i--) {
1372bf215546Sopenharmony_ci      if (info->samplers[i]) {
1373bf215546Sopenharmony_ci         ctx->max_sampler_seen = i;
1374bf215546Sopenharmony_ci         break;
1375bf215546Sopenharmony_ci      }
1376bf215546Sopenharmony_ci   }
1377bf215546Sopenharmony_ci
1378bf215546Sopenharmony_ci   cso_single_sampler_done(ctx, PIPE_SHADER_FRAGMENT);
1379bf215546Sopenharmony_ci}
1380bf215546Sopenharmony_ci
1381bf215546Sopenharmony_ci
1382bf215546Sopenharmony_civoid
1383bf215546Sopenharmony_cicso_set_stream_outputs(struct cso_context *ctx,
1384bf215546Sopenharmony_ci                       unsigned num_targets,
1385bf215546Sopenharmony_ci                       struct pipe_stream_output_target **targets,
1386bf215546Sopenharmony_ci                       const unsigned *offsets)
1387bf215546Sopenharmony_ci{
1388bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->pipe;
1389bf215546Sopenharmony_ci   uint i;
1390bf215546Sopenharmony_ci
1391bf215546Sopenharmony_ci   if (!ctx->has_streamout) {
1392bf215546Sopenharmony_ci      assert(num_targets == 0);
1393bf215546Sopenharmony_ci      return;
1394bf215546Sopenharmony_ci   }
1395bf215546Sopenharmony_ci
1396bf215546Sopenharmony_ci   if (ctx->nr_so_targets == 0 && num_targets == 0) {
1397bf215546Sopenharmony_ci      /* Nothing to do. */
1398bf215546Sopenharmony_ci      return;
1399bf215546Sopenharmony_ci   }
1400bf215546Sopenharmony_ci
1401bf215546Sopenharmony_ci   /* reference new targets */
1402bf215546Sopenharmony_ci   for (i = 0; i < num_targets; i++) {
1403bf215546Sopenharmony_ci      pipe_so_target_reference(&ctx->so_targets[i], targets[i]);
1404bf215546Sopenharmony_ci   }
1405bf215546Sopenharmony_ci   /* unref extra old targets, if any */
1406bf215546Sopenharmony_ci   for (; i < ctx->nr_so_targets; i++) {
1407bf215546Sopenharmony_ci      pipe_so_target_reference(&ctx->so_targets[i], NULL);
1408bf215546Sopenharmony_ci   }
1409bf215546Sopenharmony_ci
1410bf215546Sopenharmony_ci   pipe->set_stream_output_targets(pipe, num_targets, targets,
1411bf215546Sopenharmony_ci                                   offsets);
1412bf215546Sopenharmony_ci   ctx->nr_so_targets = num_targets;
1413bf215546Sopenharmony_ci}
1414bf215546Sopenharmony_ci
1415bf215546Sopenharmony_cistatic void
1416bf215546Sopenharmony_cicso_save_stream_outputs(struct cso_context *ctx)
1417bf215546Sopenharmony_ci{
1418bf215546Sopenharmony_ci   uint i;
1419bf215546Sopenharmony_ci
1420bf215546Sopenharmony_ci   if (!ctx->has_streamout) {
1421bf215546Sopenharmony_ci      return;
1422bf215546Sopenharmony_ci   }
1423bf215546Sopenharmony_ci
1424bf215546Sopenharmony_ci   ctx->nr_so_targets_saved = ctx->nr_so_targets;
1425bf215546Sopenharmony_ci
1426bf215546Sopenharmony_ci   for (i = 0; i < ctx->nr_so_targets; i++) {
1427bf215546Sopenharmony_ci      assert(!ctx->so_targets_saved[i]);
1428bf215546Sopenharmony_ci      pipe_so_target_reference(&ctx->so_targets_saved[i], ctx->so_targets[i]);
1429bf215546Sopenharmony_ci   }
1430bf215546Sopenharmony_ci}
1431bf215546Sopenharmony_ci
1432bf215546Sopenharmony_cistatic void
1433bf215546Sopenharmony_cicso_restore_stream_outputs(struct cso_context *ctx)
1434bf215546Sopenharmony_ci{
1435bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->pipe;
1436bf215546Sopenharmony_ci   uint i;
1437bf215546Sopenharmony_ci   unsigned offset[PIPE_MAX_SO_BUFFERS];
1438bf215546Sopenharmony_ci
1439bf215546Sopenharmony_ci   if (!ctx->has_streamout) {
1440bf215546Sopenharmony_ci      return;
1441bf215546Sopenharmony_ci   }
1442bf215546Sopenharmony_ci
1443bf215546Sopenharmony_ci   if (ctx->nr_so_targets == 0 && ctx->nr_so_targets_saved == 0) {
1444bf215546Sopenharmony_ci      /* Nothing to do. */
1445bf215546Sopenharmony_ci      return;
1446bf215546Sopenharmony_ci   }
1447bf215546Sopenharmony_ci
1448bf215546Sopenharmony_ci   assert(ctx->nr_so_targets_saved <= PIPE_MAX_SO_BUFFERS);
1449bf215546Sopenharmony_ci   for (i = 0; i < ctx->nr_so_targets_saved; i++) {
1450bf215546Sopenharmony_ci      pipe_so_target_reference(&ctx->so_targets[i], NULL);
1451bf215546Sopenharmony_ci      /* move the reference from one pointer to another */
1452bf215546Sopenharmony_ci      ctx->so_targets[i] = ctx->so_targets_saved[i];
1453bf215546Sopenharmony_ci      ctx->so_targets_saved[i] = NULL;
1454bf215546Sopenharmony_ci      /* -1 means append */
1455bf215546Sopenharmony_ci      offset[i] = (unsigned)-1;
1456bf215546Sopenharmony_ci   }
1457bf215546Sopenharmony_ci   for (; i < ctx->nr_so_targets; i++) {
1458bf215546Sopenharmony_ci      pipe_so_target_reference(&ctx->so_targets[i], NULL);
1459bf215546Sopenharmony_ci   }
1460bf215546Sopenharmony_ci
1461bf215546Sopenharmony_ci   pipe->set_stream_output_targets(pipe, ctx->nr_so_targets_saved,
1462bf215546Sopenharmony_ci                                   ctx->so_targets, offset);
1463bf215546Sopenharmony_ci
1464bf215546Sopenharmony_ci   ctx->nr_so_targets = ctx->nr_so_targets_saved;
1465bf215546Sopenharmony_ci   ctx->nr_so_targets_saved = 0;
1466bf215546Sopenharmony_ci}
1467bf215546Sopenharmony_ci
1468bf215546Sopenharmony_ci
1469bf215546Sopenharmony_ci/**
1470bf215546Sopenharmony_ci * Save all the CSO state items specified by the state_mask bitmask
1471bf215546Sopenharmony_ci * of CSO_BIT_x flags.
1472bf215546Sopenharmony_ci */
1473bf215546Sopenharmony_civoid
1474bf215546Sopenharmony_cicso_save_state(struct cso_context *cso, unsigned state_mask)
1475bf215546Sopenharmony_ci{
1476bf215546Sopenharmony_ci   assert(cso->saved_state == 0);
1477bf215546Sopenharmony_ci
1478bf215546Sopenharmony_ci   cso->saved_state = state_mask;
1479bf215546Sopenharmony_ci
1480bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_BLEND)
1481bf215546Sopenharmony_ci      cso_save_blend(cso);
1482bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_DEPTH_STENCIL_ALPHA)
1483bf215546Sopenharmony_ci      cso_save_depth_stencil_alpha(cso);
1484bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_FRAGMENT_SAMPLERS)
1485bf215546Sopenharmony_ci      cso_save_fragment_samplers(cso);
1486bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_FRAGMENT_SHADER)
1487bf215546Sopenharmony_ci      cso_save_fragment_shader(cso);
1488bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_FRAMEBUFFER)
1489bf215546Sopenharmony_ci      cso_save_framebuffer(cso);
1490bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_GEOMETRY_SHADER)
1491bf215546Sopenharmony_ci      cso_save_geometry_shader(cso);
1492bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_MIN_SAMPLES)
1493bf215546Sopenharmony_ci      cso_save_min_samples(cso);
1494bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_RASTERIZER)
1495bf215546Sopenharmony_ci      cso_save_rasterizer(cso);
1496bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_RENDER_CONDITION)
1497bf215546Sopenharmony_ci      cso_save_render_condition(cso);
1498bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_SAMPLE_MASK)
1499bf215546Sopenharmony_ci      cso_save_sample_mask(cso);
1500bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_STENCIL_REF)
1501bf215546Sopenharmony_ci      cso_save_stencil_ref(cso);
1502bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_STREAM_OUTPUTS)
1503bf215546Sopenharmony_ci      cso_save_stream_outputs(cso);
1504bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_TESSCTRL_SHADER)
1505bf215546Sopenharmony_ci      cso_save_tessctrl_shader(cso);
1506bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_TESSEVAL_SHADER)
1507bf215546Sopenharmony_ci      cso_save_tesseval_shader(cso);
1508bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_VERTEX_ELEMENTS)
1509bf215546Sopenharmony_ci      cso_save_vertex_elements(cso);
1510bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_VERTEX_SHADER)
1511bf215546Sopenharmony_ci      cso_save_vertex_shader(cso);
1512bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_VIEWPORT)
1513bf215546Sopenharmony_ci      cso_save_viewport(cso);
1514bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_PAUSE_QUERIES)
1515bf215546Sopenharmony_ci      cso->pipe->set_active_query_state(cso->pipe, false);
1516bf215546Sopenharmony_ci}
1517bf215546Sopenharmony_ci
1518bf215546Sopenharmony_ci
1519bf215546Sopenharmony_ci/**
1520bf215546Sopenharmony_ci * Restore the state which was saved by cso_save_state().
1521bf215546Sopenharmony_ci */
1522bf215546Sopenharmony_civoid
1523bf215546Sopenharmony_cicso_restore_state(struct cso_context *cso, unsigned unbind)
1524bf215546Sopenharmony_ci{
1525bf215546Sopenharmony_ci   unsigned state_mask = cso->saved_state;
1526bf215546Sopenharmony_ci
1527bf215546Sopenharmony_ci   assert(state_mask);
1528bf215546Sopenharmony_ci
1529bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_DEPTH_STENCIL_ALPHA)
1530bf215546Sopenharmony_ci      cso_restore_depth_stencil_alpha(cso);
1531bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_STENCIL_REF)
1532bf215546Sopenharmony_ci      cso_restore_stencil_ref(cso);
1533bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_FRAGMENT_SHADER)
1534bf215546Sopenharmony_ci      cso_restore_fragment_shader(cso);
1535bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_GEOMETRY_SHADER)
1536bf215546Sopenharmony_ci      cso_restore_geometry_shader(cso);
1537bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_TESSEVAL_SHADER)
1538bf215546Sopenharmony_ci      cso_restore_tesseval_shader(cso);
1539bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_TESSCTRL_SHADER)
1540bf215546Sopenharmony_ci      cso_restore_tessctrl_shader(cso);
1541bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_VERTEX_SHADER)
1542bf215546Sopenharmony_ci      cso_restore_vertex_shader(cso);
1543bf215546Sopenharmony_ci   if (unbind & CSO_UNBIND_FS_SAMPLERVIEWS)
1544bf215546Sopenharmony_ci      cso->pipe->set_sampler_views(cso->pipe, PIPE_SHADER_FRAGMENT, 0, 0,
1545bf215546Sopenharmony_ci                                   cso->max_fs_samplerviews, false, NULL);
1546bf215546Sopenharmony_ci   if (unbind & CSO_UNBIND_FS_SAMPLERVIEW0)
1547bf215546Sopenharmony_ci      cso->pipe->set_sampler_views(cso->pipe, PIPE_SHADER_FRAGMENT, 0, 0,
1548bf215546Sopenharmony_ci                                   1, false, NULL);
1549bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_FRAGMENT_SAMPLERS)
1550bf215546Sopenharmony_ci      cso_restore_fragment_samplers(cso);
1551bf215546Sopenharmony_ci   if (unbind & CSO_UNBIND_FS_IMAGE0)
1552bf215546Sopenharmony_ci      cso->pipe->set_shader_images(cso->pipe, PIPE_SHADER_FRAGMENT, 0, 0, 1, NULL);
1553bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_FRAMEBUFFER)
1554bf215546Sopenharmony_ci      cso_restore_framebuffer(cso);
1555bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_BLEND)
1556bf215546Sopenharmony_ci      cso_restore_blend(cso);
1557bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_RASTERIZER)
1558bf215546Sopenharmony_ci      cso_restore_rasterizer(cso);
1559bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_MIN_SAMPLES)
1560bf215546Sopenharmony_ci      cso_restore_min_samples(cso);
1561bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_RENDER_CONDITION)
1562bf215546Sopenharmony_ci      cso_restore_render_condition(cso);
1563bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_SAMPLE_MASK)
1564bf215546Sopenharmony_ci      cso_restore_sample_mask(cso);
1565bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_VIEWPORT)
1566bf215546Sopenharmony_ci      cso_restore_viewport(cso);
1567bf215546Sopenharmony_ci   if (unbind & CSO_UNBIND_VS_CONSTANTS)
1568bf215546Sopenharmony_ci      cso->pipe->set_constant_buffer(cso->pipe, PIPE_SHADER_VERTEX, 0, false, NULL);
1569bf215546Sopenharmony_ci   if (unbind & CSO_UNBIND_FS_CONSTANTS)
1570bf215546Sopenharmony_ci      cso->pipe->set_constant_buffer(cso->pipe, PIPE_SHADER_FRAGMENT, 0, false, NULL);
1571bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_VERTEX_ELEMENTS)
1572bf215546Sopenharmony_ci      cso_restore_vertex_elements(cso);
1573bf215546Sopenharmony_ci   if (unbind & CSO_UNBIND_VERTEX_BUFFER0)
1574bf215546Sopenharmony_ci      cso->pipe->set_vertex_buffers(cso->pipe, 0, 0, 1, false, NULL);
1575bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_STREAM_OUTPUTS)
1576bf215546Sopenharmony_ci      cso_restore_stream_outputs(cso);
1577bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_PAUSE_QUERIES)
1578bf215546Sopenharmony_ci      cso->pipe->set_active_query_state(cso->pipe, true);
1579bf215546Sopenharmony_ci
1580bf215546Sopenharmony_ci   cso->saved_state = 0;
1581bf215546Sopenharmony_ci}
1582bf215546Sopenharmony_ci
1583bf215546Sopenharmony_ci/**
1584bf215546Sopenharmony_ci * Save all the CSO state items specified by the state_mask bitmask
1585bf215546Sopenharmony_ci * of CSO_BIT_COMPUTE_x flags.
1586bf215546Sopenharmony_ci */
1587bf215546Sopenharmony_civoid
1588bf215546Sopenharmony_cicso_save_compute_state(struct cso_context *cso, unsigned state_mask)
1589bf215546Sopenharmony_ci{
1590bf215546Sopenharmony_ci   assert(cso->saved_compute_state == 0);
1591bf215546Sopenharmony_ci
1592bf215546Sopenharmony_ci   cso->saved_compute_state = state_mask;
1593bf215546Sopenharmony_ci
1594bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_COMPUTE_SHADER)
1595bf215546Sopenharmony_ci      cso_save_compute_shader(cso);
1596bf215546Sopenharmony_ci
1597bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_COMPUTE_SAMPLERS)
1598bf215546Sopenharmony_ci      cso_save_compute_samplers(cso);
1599bf215546Sopenharmony_ci}
1600bf215546Sopenharmony_ci
1601bf215546Sopenharmony_ci
1602bf215546Sopenharmony_ci/**
1603bf215546Sopenharmony_ci * Restore the state which was saved by cso_save_compute_state().
1604bf215546Sopenharmony_ci */
1605bf215546Sopenharmony_civoid
1606bf215546Sopenharmony_cicso_restore_compute_state(struct cso_context *cso)
1607bf215546Sopenharmony_ci{
1608bf215546Sopenharmony_ci   unsigned state_mask = cso->saved_compute_state;
1609bf215546Sopenharmony_ci
1610bf215546Sopenharmony_ci   assert(state_mask);
1611bf215546Sopenharmony_ci
1612bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_COMPUTE_SHADER)
1613bf215546Sopenharmony_ci      cso_restore_compute_shader(cso);
1614bf215546Sopenharmony_ci
1615bf215546Sopenharmony_ci   if (state_mask & CSO_BIT_COMPUTE_SAMPLERS)
1616bf215546Sopenharmony_ci      cso_restore_compute_samplers(cso);
1617bf215546Sopenharmony_ci
1618bf215546Sopenharmony_ci   cso->saved_compute_state = 0;
1619bf215546Sopenharmony_ci}
1620bf215546Sopenharmony_ci
1621bf215546Sopenharmony_ci
1622bf215546Sopenharmony_ci
1623bf215546Sopenharmony_ci/* drawing */
1624bf215546Sopenharmony_ci
1625bf215546Sopenharmony_civoid
1626bf215546Sopenharmony_cicso_draw_vbo(struct cso_context *cso,
1627bf215546Sopenharmony_ci             const struct pipe_draw_info *info,
1628bf215546Sopenharmony_ci             unsigned drawid_offset,
1629bf215546Sopenharmony_ci             const struct pipe_draw_indirect_info *indirect,
1630bf215546Sopenharmony_ci             const struct pipe_draw_start_count_bias draw)
1631bf215546Sopenharmony_ci{
1632bf215546Sopenharmony_ci   struct u_vbuf *vbuf = cso->vbuf_current;
1633bf215546Sopenharmony_ci
1634bf215546Sopenharmony_ci   /* We can't have both indirect drawing and SO-vertex-count drawing */
1635bf215546Sopenharmony_ci   assert(!indirect ||
1636bf215546Sopenharmony_ci          indirect->buffer == NULL ||
1637bf215546Sopenharmony_ci          indirect->count_from_stream_output == NULL);
1638bf215546Sopenharmony_ci
1639bf215546Sopenharmony_ci   /* We can't have SO-vertex-count drawing with an index buffer */
1640bf215546Sopenharmony_ci   assert(info->index_size == 0 ||
1641bf215546Sopenharmony_ci          !indirect ||
1642bf215546Sopenharmony_ci          indirect->count_from_stream_output == NULL);
1643bf215546Sopenharmony_ci
1644bf215546Sopenharmony_ci   if (vbuf) {
1645bf215546Sopenharmony_ci      u_vbuf_draw_vbo(vbuf, info, drawid_offset, indirect, &draw, 1);
1646bf215546Sopenharmony_ci   } else {
1647bf215546Sopenharmony_ci      struct pipe_context *pipe = cso->pipe;
1648bf215546Sopenharmony_ci      pipe->draw_vbo(pipe, info, drawid_offset, indirect, &draw, 1);
1649bf215546Sopenharmony_ci   }
1650bf215546Sopenharmony_ci}
1651bf215546Sopenharmony_ci
1652bf215546Sopenharmony_ci/* info->draw_id can be changed by the callee if increment_draw_id is true. */
1653bf215546Sopenharmony_civoid
1654bf215546Sopenharmony_cicso_multi_draw(struct cso_context *cso,
1655bf215546Sopenharmony_ci               struct pipe_draw_info *info,
1656bf215546Sopenharmony_ci               unsigned drawid_offset,
1657bf215546Sopenharmony_ci               const struct pipe_draw_start_count_bias *draws,
1658bf215546Sopenharmony_ci               unsigned num_draws)
1659bf215546Sopenharmony_ci{
1660bf215546Sopenharmony_ci   struct u_vbuf *vbuf = cso->vbuf_current;
1661bf215546Sopenharmony_ci
1662bf215546Sopenharmony_ci   if (vbuf) {
1663bf215546Sopenharmony_ci      u_vbuf_draw_vbo(vbuf, info, drawid_offset, NULL, draws, num_draws);
1664bf215546Sopenharmony_ci   } else {
1665bf215546Sopenharmony_ci      struct pipe_context *pipe = cso->pipe;
1666bf215546Sopenharmony_ci
1667bf215546Sopenharmony_ci      pipe->draw_vbo(pipe, info, drawid_offset, NULL, draws, num_draws);
1668bf215546Sopenharmony_ci   }
1669bf215546Sopenharmony_ci}
1670bf215546Sopenharmony_ci
1671bf215546Sopenharmony_civoid
1672bf215546Sopenharmony_cicso_draw_arrays(struct cso_context *cso, uint mode, uint start, uint count)
1673bf215546Sopenharmony_ci{
1674bf215546Sopenharmony_ci   struct pipe_draw_info info;
1675bf215546Sopenharmony_ci   struct pipe_draw_start_count_bias draw;
1676bf215546Sopenharmony_ci
1677bf215546Sopenharmony_ci   util_draw_init_info(&info);
1678bf215546Sopenharmony_ci
1679bf215546Sopenharmony_ci   info.mode = mode;
1680bf215546Sopenharmony_ci   info.index_bounds_valid = true;
1681bf215546Sopenharmony_ci   info.min_index = start;
1682bf215546Sopenharmony_ci   info.max_index = start + count - 1;
1683bf215546Sopenharmony_ci
1684bf215546Sopenharmony_ci   draw.start = start;
1685bf215546Sopenharmony_ci   draw.count = count;
1686bf215546Sopenharmony_ci   draw.index_bias = 0;
1687bf215546Sopenharmony_ci
1688bf215546Sopenharmony_ci   cso_draw_vbo(cso, &info, 0, NULL, draw);
1689bf215546Sopenharmony_ci}
1690bf215546Sopenharmony_ci
1691bf215546Sopenharmony_civoid
1692bf215546Sopenharmony_cicso_draw_arrays_instanced(struct cso_context *cso, uint mode,
1693bf215546Sopenharmony_ci                          uint start, uint count,
1694bf215546Sopenharmony_ci                          uint start_instance, uint instance_count)
1695bf215546Sopenharmony_ci{
1696bf215546Sopenharmony_ci   struct pipe_draw_info info;
1697bf215546Sopenharmony_ci   struct pipe_draw_start_count_bias draw;
1698bf215546Sopenharmony_ci
1699bf215546Sopenharmony_ci   util_draw_init_info(&info);
1700bf215546Sopenharmony_ci
1701bf215546Sopenharmony_ci   info.mode = mode;
1702bf215546Sopenharmony_ci   info.index_bounds_valid = true;
1703bf215546Sopenharmony_ci   info.min_index = start;
1704bf215546Sopenharmony_ci   info.max_index = start + count - 1;
1705bf215546Sopenharmony_ci   info.start_instance = start_instance;
1706bf215546Sopenharmony_ci   info.instance_count = instance_count;
1707bf215546Sopenharmony_ci
1708bf215546Sopenharmony_ci   draw.start = start;
1709bf215546Sopenharmony_ci   draw.count = count;
1710bf215546Sopenharmony_ci   draw.index_bias = 0;
1711bf215546Sopenharmony_ci
1712bf215546Sopenharmony_ci   cso_draw_vbo(cso, &info, 0, NULL, draw);
1713bf215546Sopenharmony_ci}
1714