1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2009 Marek Olšák <maraeo@gmail.com>
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
7bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
8bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
9bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
10bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
11bf215546Sopenharmony_ci * the following conditions:
12bf215546Sopenharmony_ci *
13bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
14bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
15bf215546Sopenharmony_ci * of the Software.
16bf215546Sopenharmony_ci *
17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24bf215546Sopenharmony_ci *
25bf215546Sopenharmony_ci **************************************************************************/
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci/**
28bf215546Sopenharmony_ci * @file
29bf215546Sopenharmony_ci * Blitter utility to facilitate acceleration of the clear, clear_render_target,
30bf215546Sopenharmony_ci * clear_depth_stencil, resource_copy_region, and blit functions.
31bf215546Sopenharmony_ci *
32bf215546Sopenharmony_ci * @author Marek Olšák
33bf215546Sopenharmony_ci */
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include "pipe/p_context.h"
36bf215546Sopenharmony_ci#include "pipe/p_defines.h"
37bf215546Sopenharmony_ci#include "util/u_inlines.h"
38bf215546Sopenharmony_ci#include "pipe/p_shader_tokens.h"
39bf215546Sopenharmony_ci#include "pipe/p_state.h"
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci#include "util/format/u_format.h"
42bf215546Sopenharmony_ci#include "util/u_memory.h"
43bf215546Sopenharmony_ci#include "util/u_math.h"
44bf215546Sopenharmony_ci#include "util/u_blitter.h"
45bf215546Sopenharmony_ci#include "util/u_draw_quad.h"
46bf215546Sopenharmony_ci#include "util/u_sampler.h"
47bf215546Sopenharmony_ci#include "util/u_simple_shaders.h"
48bf215546Sopenharmony_ci#include "util/u_surface.h"
49bf215546Sopenharmony_ci#include "util/u_texture.h"
50bf215546Sopenharmony_ci#include "util/u_upload_mgr.h"
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci#define INVALID_PTR ((void*)~0)
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci#define GET_CLEAR_BLEND_STATE_IDX(clear_buffers) \
55bf215546Sopenharmony_ci   ((clear_buffers) / PIPE_CLEAR_COLOR0)
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci#define NUM_RESOLVE_FRAG_SHADERS 5 /* MSAA 2x, 4x, 8x, 16x, 32x */
58bf215546Sopenharmony_ci#define GET_MSAA_RESOLVE_FS_IDX(nr_samples) (util_logbase2(nr_samples)-1)
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_cistruct blitter_context_priv
61bf215546Sopenharmony_ci{
62bf215546Sopenharmony_ci   struct blitter_context base;
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci   float vertices[4][2][4];   /**< {pos, color} or {pos, texcoord} */
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci   /* Templates for various state objects. */
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci   /* Constant state objects. */
69bf215546Sopenharmony_ci   /* Vertex shaders. */
70bf215546Sopenharmony_ci   void *vs; /**< Vertex shader which passes {pos, generic} to the output.*/
71bf215546Sopenharmony_ci   void *vs_nogeneric;
72bf215546Sopenharmony_ci   void *vs_pos_only[4]; /**< Vertex shader which passes pos to the output
73bf215546Sopenharmony_ci                              for clear_buffer.*/
74bf215546Sopenharmony_ci   void *vs_layered; /**< Vertex shader which sets LAYER = INSTANCEID. */
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   /* Fragment shaders. */
77bf215546Sopenharmony_ci   void *fs_empty;
78bf215546Sopenharmony_ci   void *fs_write_one_cbuf;
79bf215546Sopenharmony_ci   void *fs_clear_all_cbufs;
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci   /* FS which outputs a color from a texture where
82bf215546Sopenharmony_ci    * the 1st index indicates the texture type / destination type,
83bf215546Sopenharmony_ci    * the 2nd index is the PIPE_TEXTURE_* to be sampled,
84bf215546Sopenharmony_ci    * the 3rd index is 0 = use TEX, 1 = use TXF.
85bf215546Sopenharmony_ci    */
86bf215546Sopenharmony_ci   void *fs_texfetch_col[5][PIPE_MAX_TEXTURE_TYPES][2];
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci   /* FS which outputs a depth from a texture, where
89bf215546Sopenharmony_ci    * the 1st index is the PIPE_TEXTURE_* to be sampled,
90bf215546Sopenharmony_ci    * the 2nd index is 0 = use TEX, 1 = use TXF.
91bf215546Sopenharmony_ci    */
92bf215546Sopenharmony_ci   void *fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES][2];
93bf215546Sopenharmony_ci   void *fs_texfetch_depthstencil[PIPE_MAX_TEXTURE_TYPES][2];
94bf215546Sopenharmony_ci   void *fs_texfetch_stencil[PIPE_MAX_TEXTURE_TYPES][2];
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci   /* FS which outputs one sample from a multisample texture. */
97bf215546Sopenharmony_ci   void *fs_texfetch_col_msaa[5][PIPE_MAX_TEXTURE_TYPES];
98bf215546Sopenharmony_ci   void *fs_texfetch_depth_msaa[PIPE_MAX_TEXTURE_TYPES][2];
99bf215546Sopenharmony_ci   void *fs_texfetch_depthstencil_msaa[PIPE_MAX_TEXTURE_TYPES][2];
100bf215546Sopenharmony_ci   void *fs_texfetch_stencil_msaa[PIPE_MAX_TEXTURE_TYPES][2];
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci   /* FS which outputs an average of all samples. */
103bf215546Sopenharmony_ci   void *fs_resolve[PIPE_MAX_TEXTURE_TYPES][NUM_RESOLVE_FRAG_SHADERS][2];
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci   /* FS which unpacks color to ZS or packs ZS to color, matching
106bf215546Sopenharmony_ci    * the ZS format. See util_blitter_get_color_format_for_zs().
107bf215546Sopenharmony_ci    */
108bf215546Sopenharmony_ci   void *fs_pack_color_zs[TGSI_TEXTURE_COUNT][10];
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci   /* FS which is meant for replicating indevidual stencil-buffer bits */
111bf215546Sopenharmony_ci   void *fs_stencil_blit_fallback[2];
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci   /* Blend state. */
114bf215546Sopenharmony_ci   void *blend[PIPE_MASK_RGBA+1][2]; /**< blend state with writemask */
115bf215546Sopenharmony_ci   void *blend_clear[GET_CLEAR_BLEND_STATE_IDX(PIPE_CLEAR_COLOR)+1];
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci   /* Depth stencil alpha state. */
118bf215546Sopenharmony_ci   void *dsa_write_depth_stencil;
119bf215546Sopenharmony_ci   void *dsa_write_depth_keep_stencil;
120bf215546Sopenharmony_ci   void *dsa_keep_depth_stencil;
121bf215546Sopenharmony_ci   void *dsa_keep_depth_write_stencil;
122bf215546Sopenharmony_ci   void *dsa_replicate_stencil_bit[8];
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   /* Vertex elements states. */
125bf215546Sopenharmony_ci   void *velem_state;
126bf215546Sopenharmony_ci   void *velem_state_readbuf[4]; /**< X, XY, XYZ, XYZW */
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   /* Sampler state. */
129bf215546Sopenharmony_ci   void *sampler_state;
130bf215546Sopenharmony_ci   void *sampler_state_linear;
131bf215546Sopenharmony_ci   void *sampler_state_rect;
132bf215546Sopenharmony_ci   void *sampler_state_rect_linear;
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci   /* Rasterizer state. */
135bf215546Sopenharmony_ci   void *rs_state[2][2];  /**< [scissor][msaa] */
136bf215546Sopenharmony_ci   void *rs_discard_state;
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   /* Destination surface dimensions. */
139bf215546Sopenharmony_ci   unsigned dst_width;
140bf215546Sopenharmony_ci   unsigned dst_height;
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   void *custom_vs;
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci   bool has_geometry_shader;
145bf215546Sopenharmony_ci   bool has_tessellation;
146bf215546Sopenharmony_ci   bool has_layered;
147bf215546Sopenharmony_ci   bool has_stream_out;
148bf215546Sopenharmony_ci   bool has_stencil_export;
149bf215546Sopenharmony_ci   bool has_texture_multisample;
150bf215546Sopenharmony_ci   bool has_tex_lz;
151bf215546Sopenharmony_ci   bool has_txf;
152bf215546Sopenharmony_ci   bool has_sample_shading;
153bf215546Sopenharmony_ci   bool cube_as_2darray;
154bf215546Sopenharmony_ci   bool has_texrect;
155bf215546Sopenharmony_ci   bool cached_all_shaders;
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   /* The Draw module overrides these functions.
158bf215546Sopenharmony_ci    * Always create the blitter before Draw. */
159bf215546Sopenharmony_ci   void   (*bind_fs_state)(struct pipe_context *, void *);
160bf215546Sopenharmony_ci   void   (*delete_fs_state)(struct pipe_context *, void *);
161bf215546Sopenharmony_ci};
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_cistruct blitter_context *util_blitter_create(struct pipe_context *pipe)
164bf215546Sopenharmony_ci{
165bf215546Sopenharmony_ci   struct blitter_context_priv *ctx;
166bf215546Sopenharmony_ci   struct pipe_blend_state blend;
167bf215546Sopenharmony_ci   struct pipe_depth_stencil_alpha_state dsa;
168bf215546Sopenharmony_ci   struct pipe_rasterizer_state rs_state;
169bf215546Sopenharmony_ci   struct pipe_sampler_state sampler_state;
170bf215546Sopenharmony_ci   struct pipe_vertex_element velem[2];
171bf215546Sopenharmony_ci   unsigned i, j;
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci   ctx = CALLOC_STRUCT(blitter_context_priv);
174bf215546Sopenharmony_ci   if (!ctx)
175bf215546Sopenharmony_ci      return NULL;
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci   ctx->base.pipe = pipe;
178bf215546Sopenharmony_ci   ctx->base.draw_rectangle = util_blitter_draw_rectangle;
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci   ctx->bind_fs_state = pipe->bind_fs_state;
181bf215546Sopenharmony_ci   ctx->delete_fs_state = pipe->delete_fs_state;
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_ci   /* init state objects for them to be considered invalid */
184bf215546Sopenharmony_ci   ctx->base.saved_blend_state = INVALID_PTR;
185bf215546Sopenharmony_ci   ctx->base.saved_dsa_state = INVALID_PTR;
186bf215546Sopenharmony_ci   ctx->base.saved_rs_state = INVALID_PTR;
187bf215546Sopenharmony_ci   ctx->base.saved_fs = INVALID_PTR;
188bf215546Sopenharmony_ci   ctx->base.saved_vs = INVALID_PTR;
189bf215546Sopenharmony_ci   ctx->base.saved_gs = INVALID_PTR;
190bf215546Sopenharmony_ci   ctx->base.saved_velem_state = INVALID_PTR;
191bf215546Sopenharmony_ci   ctx->base.saved_fb_state.nr_cbufs = ~0;
192bf215546Sopenharmony_ci   ctx->base.saved_num_sampler_views = ~0;
193bf215546Sopenharmony_ci   ctx->base.saved_num_sampler_states = ~0;
194bf215546Sopenharmony_ci   ctx->base.saved_num_so_targets = ~0;
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_ci   ctx->has_geometry_shader =
197bf215546Sopenharmony_ci      pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY,
198bf215546Sopenharmony_ci                                     PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci   ctx->has_tessellation =
201bf215546Sopenharmony_ci      pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_TESS_CTRL,
202bf215546Sopenharmony_ci                                     PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci   ctx->has_stream_out =
205bf215546Sopenharmony_ci      pipe->screen->get_param(pipe->screen,
206bf215546Sopenharmony_ci                              PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0;
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci   ctx->has_stencil_export =
209bf215546Sopenharmony_ci         pipe->screen->get_param(pipe->screen,
210bf215546Sopenharmony_ci                                 PIPE_CAP_SHADER_STENCIL_EXPORT);
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci   ctx->has_texture_multisample =
213bf215546Sopenharmony_ci      pipe->screen->get_param(pipe->screen, PIPE_CAP_TEXTURE_MULTISAMPLE);
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci   ctx->has_tex_lz = pipe->screen->get_param(pipe->screen,
216bf215546Sopenharmony_ci                                             PIPE_CAP_TGSI_TEX_TXF_LZ);
217bf215546Sopenharmony_ci   ctx->has_txf = pipe->screen->get_param(pipe->screen,
218bf215546Sopenharmony_ci                                          PIPE_CAP_GLSL_FEATURE_LEVEL) > 130;
219bf215546Sopenharmony_ci   ctx->has_sample_shading = pipe->screen->get_param(pipe->screen,
220bf215546Sopenharmony_ci                                                     PIPE_CAP_SAMPLE_SHADING);
221bf215546Sopenharmony_ci   ctx->cube_as_2darray = pipe->screen->get_param(pipe->screen,
222bf215546Sopenharmony_ci                                                  PIPE_CAP_SAMPLER_VIEW_TARGET);
223bf215546Sopenharmony_ci   ctx->has_texrect = pipe->screen->get_param(pipe->screen, PIPE_CAP_TEXRECT);
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci   /* blend state objects */
226bf215546Sopenharmony_ci   memset(&blend, 0, sizeof(blend));
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci   for (i = 0; i <= PIPE_MASK_RGBA; i++) {
229bf215546Sopenharmony_ci      for (j = 0; j < 2; j++) {
230bf215546Sopenharmony_ci         memset(&blend.rt[0], 0, sizeof(blend.rt[0]));
231bf215546Sopenharmony_ci         blend.rt[0].colormask = i;
232bf215546Sopenharmony_ci         if (j) {
233bf215546Sopenharmony_ci            blend.rt[0].blend_enable = 1;
234bf215546Sopenharmony_ci            blend.rt[0].rgb_func = PIPE_BLEND_ADD;
235bf215546Sopenharmony_ci            blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
236bf215546Sopenharmony_ci            blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
237bf215546Sopenharmony_ci            blend.rt[0].alpha_func = PIPE_BLEND_ADD;
238bf215546Sopenharmony_ci            blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
239bf215546Sopenharmony_ci            blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
240bf215546Sopenharmony_ci         }
241bf215546Sopenharmony_ci         ctx->blend[i][j] = pipe->create_blend_state(pipe, &blend);
242bf215546Sopenharmony_ci      }
243bf215546Sopenharmony_ci   }
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci   /* depth stencil alpha state objects */
246bf215546Sopenharmony_ci   memset(&dsa, 0, sizeof(dsa));
247bf215546Sopenharmony_ci   ctx->dsa_keep_depth_stencil =
248bf215546Sopenharmony_ci      pipe->create_depth_stencil_alpha_state(pipe, &dsa);
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci   dsa.depth_enabled = 1;
251bf215546Sopenharmony_ci   dsa.depth_writemask = 1;
252bf215546Sopenharmony_ci   dsa.depth_func = PIPE_FUNC_ALWAYS;
253bf215546Sopenharmony_ci   ctx->dsa_write_depth_keep_stencil =
254bf215546Sopenharmony_ci      pipe->create_depth_stencil_alpha_state(pipe, &dsa);
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci   dsa.stencil[0].enabled = 1;
257bf215546Sopenharmony_ci   dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
258bf215546Sopenharmony_ci   dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
259bf215546Sopenharmony_ci   dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
260bf215546Sopenharmony_ci   dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
261bf215546Sopenharmony_ci   dsa.stencil[0].valuemask = 0xff;
262bf215546Sopenharmony_ci   dsa.stencil[0].writemask = 0xff;
263bf215546Sopenharmony_ci   ctx->dsa_write_depth_stencil =
264bf215546Sopenharmony_ci      pipe->create_depth_stencil_alpha_state(pipe, &dsa);
265bf215546Sopenharmony_ci
266bf215546Sopenharmony_ci   dsa.depth_enabled = 0;
267bf215546Sopenharmony_ci   dsa.depth_writemask = 0;
268bf215546Sopenharmony_ci   ctx->dsa_keep_depth_write_stencil =
269bf215546Sopenharmony_ci      pipe->create_depth_stencil_alpha_state(pipe, &dsa);
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci   /* sampler state */
272bf215546Sopenharmony_ci   memset(&sampler_state, 0, sizeof(sampler_state));
273bf215546Sopenharmony_ci   sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
274bf215546Sopenharmony_ci   sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
275bf215546Sopenharmony_ci   sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
276bf215546Sopenharmony_ci   sampler_state.normalized_coords = 1;
277bf215546Sopenharmony_ci   ctx->sampler_state = pipe->create_sampler_state(pipe, &sampler_state);
278bf215546Sopenharmony_ci   if (ctx->has_texrect) {
279bf215546Sopenharmony_ci      sampler_state.normalized_coords = 0;
280bf215546Sopenharmony_ci      ctx->sampler_state_rect = pipe->create_sampler_state(pipe, &sampler_state);
281bf215546Sopenharmony_ci   }
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci   sampler_state.min_img_filter = PIPE_TEX_FILTER_LINEAR;
284bf215546Sopenharmony_ci   sampler_state.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
285bf215546Sopenharmony_ci   sampler_state.normalized_coords = 1;
286bf215546Sopenharmony_ci   ctx->sampler_state_linear = pipe->create_sampler_state(pipe, &sampler_state);
287bf215546Sopenharmony_ci   if (ctx->has_texrect) {
288bf215546Sopenharmony_ci      sampler_state.normalized_coords = 0;
289bf215546Sopenharmony_ci      ctx->sampler_state_rect_linear = pipe->create_sampler_state(pipe, &sampler_state);
290bf215546Sopenharmony_ci   }
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci   /* rasterizer state */
293bf215546Sopenharmony_ci   memset(&rs_state, 0, sizeof(rs_state));
294bf215546Sopenharmony_ci   rs_state.cull_face = PIPE_FACE_NONE;
295bf215546Sopenharmony_ci   rs_state.half_pixel_center = 1;
296bf215546Sopenharmony_ci   rs_state.bottom_edge_rule = 1;
297bf215546Sopenharmony_ci   rs_state.flatshade = 1;
298bf215546Sopenharmony_ci   rs_state.depth_clip_near = 1;
299bf215546Sopenharmony_ci   rs_state.depth_clip_far = 1;
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci   unsigned scissor, msaa;
302bf215546Sopenharmony_ci   for (scissor = 0; scissor < 2; scissor++) {
303bf215546Sopenharmony_ci      for (msaa = 0; msaa < 2; msaa++) {
304bf215546Sopenharmony_ci         rs_state.scissor = scissor;
305bf215546Sopenharmony_ci         rs_state.multisample = msaa;
306bf215546Sopenharmony_ci         ctx->rs_state[scissor][msaa] =
307bf215546Sopenharmony_ci            pipe->create_rasterizer_state(pipe, &rs_state);
308bf215546Sopenharmony_ci      }
309bf215546Sopenharmony_ci   }
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci   if (ctx->has_stream_out) {
312bf215546Sopenharmony_ci      rs_state.scissor = rs_state.multisample = 0;
313bf215546Sopenharmony_ci      rs_state.rasterizer_discard = 1;
314bf215546Sopenharmony_ci      ctx->rs_discard_state = pipe->create_rasterizer_state(pipe, &rs_state);
315bf215546Sopenharmony_ci   }
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci   ctx->base.cb_slot = 0; /* 0 for now */
318bf215546Sopenharmony_ci   ctx->base.vb_slot = 0; /* 0 for now */
319bf215546Sopenharmony_ci
320bf215546Sopenharmony_ci   /* vertex elements states */
321bf215546Sopenharmony_ci   memset(&velem[0], 0, sizeof(velem[0]) * 2);
322bf215546Sopenharmony_ci   for (i = 0; i < 2; i++) {
323bf215546Sopenharmony_ci      velem[i].src_offset = i * 4 * sizeof(float);
324bf215546Sopenharmony_ci      velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
325bf215546Sopenharmony_ci      velem[i].vertex_buffer_index = ctx->base.vb_slot;
326bf215546Sopenharmony_ci   }
327bf215546Sopenharmony_ci   ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci   if (ctx->has_stream_out) {
330bf215546Sopenharmony_ci      static enum pipe_format formats[4] = {
331bf215546Sopenharmony_ci         PIPE_FORMAT_R32_UINT,
332bf215546Sopenharmony_ci         PIPE_FORMAT_R32G32_UINT,
333bf215546Sopenharmony_ci         PIPE_FORMAT_R32G32B32_UINT,
334bf215546Sopenharmony_ci         PIPE_FORMAT_R32G32B32A32_UINT
335bf215546Sopenharmony_ci      };
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_ci      for (i = 0; i < 4; i++) {
338bf215546Sopenharmony_ci         velem[0].src_format = formats[i];
339bf215546Sopenharmony_ci         velem[0].vertex_buffer_index = ctx->base.vb_slot;
340bf215546Sopenharmony_ci         ctx->velem_state_readbuf[i] =
341bf215546Sopenharmony_ci               pipe->create_vertex_elements_state(pipe, 1, &velem[0]);
342bf215546Sopenharmony_ci      }
343bf215546Sopenharmony_ci   }
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   ctx->has_layered =
346bf215546Sopenharmony_ci      pipe->screen->get_param(pipe->screen, PIPE_CAP_VS_INSTANCEID) &&
347bf215546Sopenharmony_ci      pipe->screen->get_param(pipe->screen, PIPE_CAP_VS_LAYER_VIEWPORT);
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci   /* set invariant vertex coordinates */
350bf215546Sopenharmony_ci   for (i = 0; i < 4; i++) {
351bf215546Sopenharmony_ci      ctx->vertices[i][0][2] = 0; /*v.z*/
352bf215546Sopenharmony_ci      ctx->vertices[i][0][3] = 1; /*v.w*/
353bf215546Sopenharmony_ci   }
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci   return &ctx->base;
356bf215546Sopenharmony_ci}
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_civoid *util_blitter_get_noop_blend_state(struct blitter_context *blitter)
359bf215546Sopenharmony_ci{
360bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_ci   return ctx->blend[0][0];
363bf215546Sopenharmony_ci}
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_civoid *util_blitter_get_noop_dsa_state(struct blitter_context *blitter)
366bf215546Sopenharmony_ci{
367bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
368bf215546Sopenharmony_ci
369bf215546Sopenharmony_ci   return ctx->dsa_keep_depth_stencil;
370bf215546Sopenharmony_ci}
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_civoid *util_blitter_get_discard_rasterizer_state(struct blitter_context *blitter)
373bf215546Sopenharmony_ci{
374bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_ci   return ctx->rs_discard_state;
377bf215546Sopenharmony_ci}
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_cistatic void bind_vs_pos_only(struct blitter_context_priv *ctx,
380bf215546Sopenharmony_ci                             unsigned num_so_channels)
381bf215546Sopenharmony_ci{
382bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
383bf215546Sopenharmony_ci   int index = num_so_channels ? num_so_channels - 1 : 0;
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci   if (!ctx->vs_pos_only[index]) {
386bf215546Sopenharmony_ci      struct pipe_stream_output_info so;
387bf215546Sopenharmony_ci      static const enum tgsi_semantic semantic_names[] =
388bf215546Sopenharmony_ci         { TGSI_SEMANTIC_POSITION };
389bf215546Sopenharmony_ci      const uint semantic_indices[] = { 0 };
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci      memset(&so, 0, sizeof(so));
392bf215546Sopenharmony_ci      so.num_outputs = 1;
393bf215546Sopenharmony_ci      so.output[0].num_components = num_so_channels;
394bf215546Sopenharmony_ci      so.stride[0] = num_so_channels;
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ci      ctx->vs_pos_only[index] =
397bf215546Sopenharmony_ci         util_make_vertex_passthrough_shader_with_so(pipe, 1, semantic_names,
398bf215546Sopenharmony_ci                                                     semantic_indices, false,
399bf215546Sopenharmony_ci                                                     false, &so);
400bf215546Sopenharmony_ci   }
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_ci   pipe->bind_vs_state(pipe, ctx->vs_pos_only[index]);
403bf215546Sopenharmony_ci}
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_cistatic void *get_vs_passthrough_pos_generic(struct blitter_context *blitter)
406bf215546Sopenharmony_ci{
407bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
408bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ci   if (!ctx->vs) {
411bf215546Sopenharmony_ci      static const enum tgsi_semantic semantic_names[] =
412bf215546Sopenharmony_ci         { TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_GENERIC };
413bf215546Sopenharmony_ci      const uint semantic_indices[] = { 0, 0 };
414bf215546Sopenharmony_ci      ctx->vs =
415bf215546Sopenharmony_ci         util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
416bf215546Sopenharmony_ci                                             semantic_indices, false);
417bf215546Sopenharmony_ci   }
418bf215546Sopenharmony_ci   return ctx->vs;
419bf215546Sopenharmony_ci}
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_cistatic void *get_vs_passthrough_pos(struct blitter_context *blitter)
422bf215546Sopenharmony_ci{
423bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
424bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ci   if (!ctx->vs_nogeneric) {
427bf215546Sopenharmony_ci      static const enum tgsi_semantic semantic_names[] =
428bf215546Sopenharmony_ci         { TGSI_SEMANTIC_POSITION };
429bf215546Sopenharmony_ci      const uint semantic_indices[] = { 0 };
430bf215546Sopenharmony_ci
431bf215546Sopenharmony_ci      ctx->vs_nogeneric =
432bf215546Sopenharmony_ci         util_make_vertex_passthrough_shader(pipe, 1,
433bf215546Sopenharmony_ci                                             semantic_names,
434bf215546Sopenharmony_ci                                             semantic_indices, false);
435bf215546Sopenharmony_ci   }
436bf215546Sopenharmony_ci   return ctx->vs_nogeneric;
437bf215546Sopenharmony_ci}
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_cistatic void *get_vs_layered(struct blitter_context *blitter)
440bf215546Sopenharmony_ci{
441bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
442bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_ci   if (!ctx->vs_layered) {
445bf215546Sopenharmony_ci      ctx->vs_layered = util_make_layered_clear_vertex_shader(pipe);
446bf215546Sopenharmony_ci   }
447bf215546Sopenharmony_ci   return ctx->vs_layered;
448bf215546Sopenharmony_ci}
449bf215546Sopenharmony_ci
450bf215546Sopenharmony_cistatic void bind_fs_empty(struct blitter_context_priv *ctx)
451bf215546Sopenharmony_ci{
452bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_ci   if (!ctx->fs_empty) {
455bf215546Sopenharmony_ci      assert(!ctx->cached_all_shaders);
456bf215546Sopenharmony_ci      ctx->fs_empty = util_make_empty_fragment_shader(pipe);
457bf215546Sopenharmony_ci   }
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_ci   ctx->bind_fs_state(pipe, ctx->fs_empty);
460bf215546Sopenharmony_ci}
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_cistatic void bind_fs_write_one_cbuf(struct blitter_context_priv *ctx)
463bf215546Sopenharmony_ci{
464bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
465bf215546Sopenharmony_ci
466bf215546Sopenharmony_ci   if (!ctx->fs_write_one_cbuf) {
467bf215546Sopenharmony_ci      assert(!ctx->cached_all_shaders);
468bf215546Sopenharmony_ci      ctx->fs_write_one_cbuf =
469bf215546Sopenharmony_ci         util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,
470bf215546Sopenharmony_ci                                               TGSI_INTERPOLATE_CONSTANT, false);
471bf215546Sopenharmony_ci   }
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci   ctx->bind_fs_state(pipe, ctx->fs_write_one_cbuf);
474bf215546Sopenharmony_ci}
475bf215546Sopenharmony_ci
476bf215546Sopenharmony_cistatic void bind_fs_clear_all_cbufs(struct blitter_context_priv *ctx)
477bf215546Sopenharmony_ci{
478bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
479bf215546Sopenharmony_ci
480bf215546Sopenharmony_ci   if (!ctx->fs_clear_all_cbufs) {
481bf215546Sopenharmony_ci      assert(!ctx->cached_all_shaders);
482bf215546Sopenharmony_ci      ctx->fs_clear_all_cbufs = util_make_fs_clear_all_cbufs(pipe);
483bf215546Sopenharmony_ci   }
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_ci   ctx->bind_fs_state(pipe, ctx->fs_clear_all_cbufs);
486bf215546Sopenharmony_ci}
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_civoid util_blitter_destroy(struct blitter_context *blitter)
489bf215546Sopenharmony_ci{
490bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
491bf215546Sopenharmony_ci   struct pipe_context *pipe = blitter->pipe;
492bf215546Sopenharmony_ci   unsigned i, j, f;
493bf215546Sopenharmony_ci
494bf215546Sopenharmony_ci   for (i = 0; i <= PIPE_MASK_RGBA; i++)
495bf215546Sopenharmony_ci      for (j = 0; j < 2; j++)
496bf215546Sopenharmony_ci         pipe->delete_blend_state(pipe, ctx->blend[i][j]);
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci   for (i = 0; i < ARRAY_SIZE(ctx->blend_clear); i++) {
499bf215546Sopenharmony_ci      if (ctx->blend_clear[i])
500bf215546Sopenharmony_ci         pipe->delete_blend_state(pipe, ctx->blend_clear[i]);
501bf215546Sopenharmony_ci   }
502bf215546Sopenharmony_ci   pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
503bf215546Sopenharmony_ci   pipe->delete_depth_stencil_alpha_state(pipe,
504bf215546Sopenharmony_ci                                          ctx->dsa_write_depth_keep_stencil);
505bf215546Sopenharmony_ci   pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
506bf215546Sopenharmony_ci   pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
507bf215546Sopenharmony_ci
508bf215546Sopenharmony_ci   for (i = 0; i < ARRAY_SIZE(ctx->dsa_replicate_stencil_bit); i++) {
509bf215546Sopenharmony_ci      if (ctx->dsa_replicate_stencil_bit[i])
510bf215546Sopenharmony_ci         pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_replicate_stencil_bit[i]);
511bf215546Sopenharmony_ci   }
512bf215546Sopenharmony_ci
513bf215546Sopenharmony_ci   unsigned scissor, msaa;
514bf215546Sopenharmony_ci   for (scissor = 0; scissor < 2; scissor++) {
515bf215546Sopenharmony_ci      for (msaa = 0; msaa < 2; msaa++) {
516bf215546Sopenharmony_ci         pipe->delete_rasterizer_state(pipe, ctx->rs_state[scissor][msaa]);
517bf215546Sopenharmony_ci      }
518bf215546Sopenharmony_ci   }
519bf215546Sopenharmony_ci
520bf215546Sopenharmony_ci   if (ctx->rs_discard_state)
521bf215546Sopenharmony_ci      pipe->delete_rasterizer_state(pipe, ctx->rs_discard_state);
522bf215546Sopenharmony_ci   if (ctx->vs)
523bf215546Sopenharmony_ci      pipe->delete_vs_state(pipe, ctx->vs);
524bf215546Sopenharmony_ci   if (ctx->vs_nogeneric)
525bf215546Sopenharmony_ci      pipe->delete_vs_state(pipe, ctx->vs_nogeneric);
526bf215546Sopenharmony_ci   for (i = 0; i < 4; i++)
527bf215546Sopenharmony_ci      if (ctx->vs_pos_only[i])
528bf215546Sopenharmony_ci         pipe->delete_vs_state(pipe, ctx->vs_pos_only[i]);
529bf215546Sopenharmony_ci   if (ctx->vs_layered)
530bf215546Sopenharmony_ci      pipe->delete_vs_state(pipe, ctx->vs_layered);
531bf215546Sopenharmony_ci   pipe->delete_vertex_elements_state(pipe, ctx->velem_state);
532bf215546Sopenharmony_ci   for (i = 0; i < 4; i++) {
533bf215546Sopenharmony_ci      if (ctx->velem_state_readbuf[i]) {
534bf215546Sopenharmony_ci         pipe->delete_vertex_elements_state(pipe, ctx->velem_state_readbuf[i]);
535bf215546Sopenharmony_ci      }
536bf215546Sopenharmony_ci   }
537bf215546Sopenharmony_ci
538bf215546Sopenharmony_ci   for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) {
539bf215546Sopenharmony_ci      for (unsigned type = 0; type < ARRAY_SIZE(ctx->fs_texfetch_col); ++type) {
540bf215546Sopenharmony_ci         for (unsigned inst = 0; inst < 2; inst++) {
541bf215546Sopenharmony_ci            if (ctx->fs_texfetch_col[type][i][inst])
542bf215546Sopenharmony_ci               ctx->delete_fs_state(pipe, ctx->fs_texfetch_col[type][i][inst]);
543bf215546Sopenharmony_ci         }
544bf215546Sopenharmony_ci         if (ctx->fs_texfetch_col_msaa[type][i])
545bf215546Sopenharmony_ci            ctx->delete_fs_state(pipe, ctx->fs_texfetch_col_msaa[type][i]);
546bf215546Sopenharmony_ci      }
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_ci      for (unsigned inst = 0; inst < 2; inst++) {
549bf215546Sopenharmony_ci         if (ctx->fs_texfetch_depth[i][inst])
550bf215546Sopenharmony_ci            ctx->delete_fs_state(pipe, ctx->fs_texfetch_depth[i][inst]);
551bf215546Sopenharmony_ci         if (ctx->fs_texfetch_depthstencil[i][inst])
552bf215546Sopenharmony_ci            ctx->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil[i][inst]);
553bf215546Sopenharmony_ci         if (ctx->fs_texfetch_stencil[i][inst])
554bf215546Sopenharmony_ci            ctx->delete_fs_state(pipe, ctx->fs_texfetch_stencil[i][inst]);
555bf215546Sopenharmony_ci      }
556bf215546Sopenharmony_ci
557bf215546Sopenharmony_ci      for (unsigned ss = 0; ss < 2; ss++) {
558bf215546Sopenharmony_ci         if (ctx->fs_texfetch_depth_msaa[i][ss])
559bf215546Sopenharmony_ci            ctx->delete_fs_state(pipe, ctx->fs_texfetch_depth_msaa[i][ss]);
560bf215546Sopenharmony_ci         if (ctx->fs_texfetch_depthstencil_msaa[i][ss])
561bf215546Sopenharmony_ci            ctx->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil_msaa[i][ss]);
562bf215546Sopenharmony_ci         if (ctx->fs_texfetch_stencil_msaa[i][ss])
563bf215546Sopenharmony_ci            ctx->delete_fs_state(pipe, ctx->fs_texfetch_stencil_msaa[i][ss]);
564bf215546Sopenharmony_ci      }
565bf215546Sopenharmony_ci
566bf215546Sopenharmony_ci      for (j = 0; j< ARRAY_SIZE(ctx->fs_resolve[i]); j++)
567bf215546Sopenharmony_ci         for (f = 0; f < 2; f++)
568bf215546Sopenharmony_ci            if (ctx->fs_resolve[i][j][f])
569bf215546Sopenharmony_ci               ctx->delete_fs_state(pipe, ctx->fs_resolve[i][j][f]);
570bf215546Sopenharmony_ci   }
571bf215546Sopenharmony_ci
572bf215546Sopenharmony_ci   for (i = 0; i < ARRAY_SIZE(ctx->fs_pack_color_zs); i++) {
573bf215546Sopenharmony_ci      for (j = 0; j < ARRAY_SIZE(ctx->fs_pack_color_zs[0]); j++) {
574bf215546Sopenharmony_ci         if (ctx->fs_pack_color_zs[i][j])
575bf215546Sopenharmony_ci            ctx->delete_fs_state(pipe, ctx->fs_pack_color_zs[i][j]);
576bf215546Sopenharmony_ci      }
577bf215546Sopenharmony_ci   }
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_ci   if (ctx->fs_empty)
580bf215546Sopenharmony_ci      ctx->delete_fs_state(pipe, ctx->fs_empty);
581bf215546Sopenharmony_ci   if (ctx->fs_write_one_cbuf)
582bf215546Sopenharmony_ci      ctx->delete_fs_state(pipe, ctx->fs_write_one_cbuf);
583bf215546Sopenharmony_ci   if (ctx->fs_clear_all_cbufs)
584bf215546Sopenharmony_ci      ctx->delete_fs_state(pipe, ctx->fs_clear_all_cbufs);
585bf215546Sopenharmony_ci
586bf215546Sopenharmony_ci   for (i = 0; i < ARRAY_SIZE(ctx->fs_stencil_blit_fallback); ++i)
587bf215546Sopenharmony_ci      if (ctx->fs_stencil_blit_fallback[i])
588bf215546Sopenharmony_ci         ctx->delete_fs_state(pipe, ctx->fs_stencil_blit_fallback[i]);
589bf215546Sopenharmony_ci
590bf215546Sopenharmony_ci   if (ctx->sampler_state_rect_linear)
591bf215546Sopenharmony_ci      pipe->delete_sampler_state(pipe, ctx->sampler_state_rect_linear);
592bf215546Sopenharmony_ci   if (ctx->sampler_state_rect)
593bf215546Sopenharmony_ci      pipe->delete_sampler_state(pipe, ctx->sampler_state_rect);
594bf215546Sopenharmony_ci   pipe->delete_sampler_state(pipe, ctx->sampler_state_linear);
595bf215546Sopenharmony_ci   pipe->delete_sampler_state(pipe, ctx->sampler_state);
596bf215546Sopenharmony_ci   FREE(ctx);
597bf215546Sopenharmony_ci}
598bf215546Sopenharmony_ci
599bf215546Sopenharmony_civoid util_blitter_set_texture_multisample(struct blitter_context *blitter,
600bf215546Sopenharmony_ci                                          bool supported)
601bf215546Sopenharmony_ci{
602bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
603bf215546Sopenharmony_ci
604bf215546Sopenharmony_ci   ctx->has_texture_multisample = supported;
605bf215546Sopenharmony_ci}
606bf215546Sopenharmony_ci
607bf215546Sopenharmony_civoid util_blitter_set_running_flag(struct blitter_context *blitter)
608bf215546Sopenharmony_ci{
609bf215546Sopenharmony_ci   if (blitter->running) {
610bf215546Sopenharmony_ci      _debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",
611bf215546Sopenharmony_ci                    __LINE__);
612bf215546Sopenharmony_ci   }
613bf215546Sopenharmony_ci   blitter->running = true;
614bf215546Sopenharmony_ci
615bf215546Sopenharmony_ci   blitter->pipe->set_active_query_state(blitter->pipe, false);
616bf215546Sopenharmony_ci}
617bf215546Sopenharmony_ci
618bf215546Sopenharmony_civoid util_blitter_unset_running_flag(struct blitter_context *blitter)
619bf215546Sopenharmony_ci{
620bf215546Sopenharmony_ci   if (!blitter->running) {
621bf215546Sopenharmony_ci      _debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",
622bf215546Sopenharmony_ci                    __LINE__);
623bf215546Sopenharmony_ci   }
624bf215546Sopenharmony_ci   blitter->running = false;
625bf215546Sopenharmony_ci
626bf215546Sopenharmony_ci   blitter->pipe->set_active_query_state(blitter->pipe, true);
627bf215546Sopenharmony_ci}
628bf215546Sopenharmony_ci
629bf215546Sopenharmony_cistatic void blitter_check_saved_vertex_states(ASSERTED struct blitter_context_priv *ctx)
630bf215546Sopenharmony_ci{
631bf215546Sopenharmony_ci   assert(ctx->base.saved_vs != INVALID_PTR);
632bf215546Sopenharmony_ci   assert(!ctx->has_geometry_shader || ctx->base.saved_gs != INVALID_PTR);
633bf215546Sopenharmony_ci   assert(!ctx->has_tessellation || ctx->base.saved_tcs != INVALID_PTR);
634bf215546Sopenharmony_ci   assert(!ctx->has_tessellation || ctx->base.saved_tes != INVALID_PTR);
635bf215546Sopenharmony_ci   assert(!ctx->has_stream_out || ctx->base.saved_num_so_targets != ~0u);
636bf215546Sopenharmony_ci   assert(ctx->base.saved_rs_state != INVALID_PTR);
637bf215546Sopenharmony_ci}
638bf215546Sopenharmony_ci
639bf215546Sopenharmony_civoid util_blitter_restore_vertex_states(struct blitter_context *blitter)
640bf215546Sopenharmony_ci{
641bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
642bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
643bf215546Sopenharmony_ci   unsigned i;
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci   /* Vertex buffer. */
646bf215546Sopenharmony_ci   if (ctx->base.saved_vertex_buffer.buffer.resource) {
647bf215546Sopenharmony_ci      pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, 0, true,
648bf215546Sopenharmony_ci                               &ctx->base.saved_vertex_buffer);
649bf215546Sopenharmony_ci      ctx->base.saved_vertex_buffer.buffer.resource = NULL;
650bf215546Sopenharmony_ci   }
651bf215546Sopenharmony_ci
652bf215546Sopenharmony_ci   /* Vertex elements. */
653bf215546Sopenharmony_ci   if (ctx->base.saved_velem_state != INVALID_PTR) {
654bf215546Sopenharmony_ci      pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state);
655bf215546Sopenharmony_ci      ctx->base.saved_velem_state = INVALID_PTR;
656bf215546Sopenharmony_ci   }
657bf215546Sopenharmony_ci
658bf215546Sopenharmony_ci   /* Vertex shader. */
659bf215546Sopenharmony_ci   pipe->bind_vs_state(pipe, ctx->base.saved_vs);
660bf215546Sopenharmony_ci   ctx->base.saved_vs = INVALID_PTR;
661bf215546Sopenharmony_ci
662bf215546Sopenharmony_ci   /* Geometry shader. */
663bf215546Sopenharmony_ci   if (ctx->has_geometry_shader) {
664bf215546Sopenharmony_ci      pipe->bind_gs_state(pipe, ctx->base.saved_gs);
665bf215546Sopenharmony_ci      ctx->base.saved_gs = INVALID_PTR;
666bf215546Sopenharmony_ci   }
667bf215546Sopenharmony_ci
668bf215546Sopenharmony_ci   if (ctx->has_tessellation) {
669bf215546Sopenharmony_ci      pipe->bind_tcs_state(pipe, ctx->base.saved_tcs);
670bf215546Sopenharmony_ci      pipe->bind_tes_state(pipe, ctx->base.saved_tes);
671bf215546Sopenharmony_ci      ctx->base.saved_tcs = INVALID_PTR;
672bf215546Sopenharmony_ci      ctx->base.saved_tes = INVALID_PTR;
673bf215546Sopenharmony_ci   }
674bf215546Sopenharmony_ci
675bf215546Sopenharmony_ci   /* Stream outputs. */
676bf215546Sopenharmony_ci   if (ctx->has_stream_out) {
677bf215546Sopenharmony_ci      unsigned offsets[PIPE_MAX_SO_BUFFERS];
678bf215546Sopenharmony_ci      for (i = 0; i < ctx->base.saved_num_so_targets; i++)
679bf215546Sopenharmony_ci         offsets[i] = (unsigned)-1;
680bf215546Sopenharmony_ci      pipe->set_stream_output_targets(pipe,
681bf215546Sopenharmony_ci                                      ctx->base.saved_num_so_targets,
682bf215546Sopenharmony_ci                                      ctx->base.saved_so_targets, offsets);
683bf215546Sopenharmony_ci
684bf215546Sopenharmony_ci      for (i = 0; i < ctx->base.saved_num_so_targets; i++)
685bf215546Sopenharmony_ci         pipe_so_target_reference(&ctx->base.saved_so_targets[i], NULL);
686bf215546Sopenharmony_ci
687bf215546Sopenharmony_ci      ctx->base.saved_num_so_targets = ~0;
688bf215546Sopenharmony_ci   }
689bf215546Sopenharmony_ci
690bf215546Sopenharmony_ci   /* Rasterizer. */
691bf215546Sopenharmony_ci   pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state);
692bf215546Sopenharmony_ci   ctx->base.saved_rs_state = INVALID_PTR;
693bf215546Sopenharmony_ci}
694bf215546Sopenharmony_ci
695bf215546Sopenharmony_cistatic void blitter_check_saved_fragment_states(ASSERTED struct blitter_context_priv *ctx)
696bf215546Sopenharmony_ci{
697bf215546Sopenharmony_ci   assert(ctx->base.saved_fs != INVALID_PTR);
698bf215546Sopenharmony_ci   assert(ctx->base.saved_dsa_state != INVALID_PTR);
699bf215546Sopenharmony_ci   assert(ctx->base.saved_blend_state != INVALID_PTR);
700bf215546Sopenharmony_ci}
701bf215546Sopenharmony_ci
702bf215546Sopenharmony_civoid util_blitter_restore_fragment_states(struct blitter_context *blitter)
703bf215546Sopenharmony_ci{
704bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
705bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
706bf215546Sopenharmony_ci
707bf215546Sopenharmony_ci   /* Fragment shader. */
708bf215546Sopenharmony_ci   ctx->bind_fs_state(pipe, ctx->base.saved_fs);
709bf215546Sopenharmony_ci   ctx->base.saved_fs = INVALID_PTR;
710bf215546Sopenharmony_ci
711bf215546Sopenharmony_ci   /* Depth, stencil, alpha. */
712bf215546Sopenharmony_ci   pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state);
713bf215546Sopenharmony_ci   ctx->base.saved_dsa_state = INVALID_PTR;
714bf215546Sopenharmony_ci
715bf215546Sopenharmony_ci   /* Blend state. */
716bf215546Sopenharmony_ci   pipe->bind_blend_state(pipe, ctx->base.saved_blend_state);
717bf215546Sopenharmony_ci   ctx->base.saved_blend_state = INVALID_PTR;
718bf215546Sopenharmony_ci
719bf215546Sopenharmony_ci   /* Sample mask. */
720bf215546Sopenharmony_ci   if (ctx->base.is_sample_mask_saved) {
721bf215546Sopenharmony_ci      pipe->set_sample_mask(pipe, ctx->base.saved_sample_mask);
722bf215546Sopenharmony_ci      ctx->base.is_sample_mask_saved = false;
723bf215546Sopenharmony_ci   }
724bf215546Sopenharmony_ci
725bf215546Sopenharmony_ci   if (ctx->base.saved_min_samples != ~0 && pipe->set_min_samples)
726bf215546Sopenharmony_ci      pipe->set_min_samples(pipe, ctx->base.saved_min_samples);
727bf215546Sopenharmony_ci   ctx->base.saved_min_samples = ~0;
728bf215546Sopenharmony_ci
729bf215546Sopenharmony_ci   /* Miscellaneous states. */
730bf215546Sopenharmony_ci   /* XXX check whether these are saved and whether they need to be restored
731bf215546Sopenharmony_ci    * (depending on the operation) */
732bf215546Sopenharmony_ci   pipe->set_stencil_ref(pipe, ctx->base.saved_stencil_ref);
733bf215546Sopenharmony_ci
734bf215546Sopenharmony_ci   if (!blitter->skip_viewport_restore)
735bf215546Sopenharmony_ci      pipe->set_viewport_states(pipe, 0, 1, &ctx->base.saved_viewport);
736bf215546Sopenharmony_ci
737bf215546Sopenharmony_ci   if (blitter->saved_num_window_rectangles) {
738bf215546Sopenharmony_ci      pipe->set_window_rectangles(pipe,
739bf215546Sopenharmony_ci                                  blitter->saved_window_rectangles_include,
740bf215546Sopenharmony_ci                                  blitter->saved_num_window_rectangles,
741bf215546Sopenharmony_ci                                  blitter->saved_window_rectangles);
742bf215546Sopenharmony_ci   }
743bf215546Sopenharmony_ci}
744bf215546Sopenharmony_ci
745bf215546Sopenharmony_cistatic void blitter_check_saved_fb_state(ASSERTED struct blitter_context_priv *ctx)
746bf215546Sopenharmony_ci{
747bf215546Sopenharmony_ci   assert(ctx->base.saved_fb_state.nr_cbufs != (ubyte) ~0);
748bf215546Sopenharmony_ci}
749bf215546Sopenharmony_ci
750bf215546Sopenharmony_cistatic void blitter_disable_render_cond(struct blitter_context_priv *ctx)
751bf215546Sopenharmony_ci{
752bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
753bf215546Sopenharmony_ci
754bf215546Sopenharmony_ci   if (ctx->base.saved_render_cond_query) {
755bf215546Sopenharmony_ci      pipe->render_condition(pipe, NULL, false, 0);
756bf215546Sopenharmony_ci   }
757bf215546Sopenharmony_ci}
758bf215546Sopenharmony_ci
759bf215546Sopenharmony_civoid util_blitter_restore_render_cond(struct blitter_context *blitter)
760bf215546Sopenharmony_ci{
761bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
762bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
763bf215546Sopenharmony_ci
764bf215546Sopenharmony_ci   if (ctx->base.saved_render_cond_query) {
765bf215546Sopenharmony_ci      pipe->render_condition(pipe, ctx->base.saved_render_cond_query,
766bf215546Sopenharmony_ci                             ctx->base.saved_render_cond_cond,
767bf215546Sopenharmony_ci                             ctx->base.saved_render_cond_mode);
768bf215546Sopenharmony_ci      ctx->base.saved_render_cond_query = NULL;
769bf215546Sopenharmony_ci   }
770bf215546Sopenharmony_ci}
771bf215546Sopenharmony_ci
772bf215546Sopenharmony_civoid util_blitter_restore_fb_state(struct blitter_context *blitter)
773bf215546Sopenharmony_ci{
774bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
775bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
776bf215546Sopenharmony_ci
777bf215546Sopenharmony_ci   pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state);
778bf215546Sopenharmony_ci   util_unreference_framebuffer_state(&ctx->base.saved_fb_state);
779bf215546Sopenharmony_ci}
780bf215546Sopenharmony_ci
781bf215546Sopenharmony_cistatic void blitter_check_saved_textures(ASSERTED struct blitter_context_priv *ctx)
782bf215546Sopenharmony_ci{
783bf215546Sopenharmony_ci   assert(ctx->base.saved_num_sampler_states != ~0u);
784bf215546Sopenharmony_ci   assert(ctx->base.saved_num_sampler_views != ~0u);
785bf215546Sopenharmony_ci}
786bf215546Sopenharmony_ci
787bf215546Sopenharmony_cistatic void util_blitter_restore_textures_internal(struct blitter_context *blitter, unsigned count)
788bf215546Sopenharmony_ci{
789bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
790bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
791bf215546Sopenharmony_ci   unsigned i;
792bf215546Sopenharmony_ci
793bf215546Sopenharmony_ci   /* Fragment sampler states. */
794bf215546Sopenharmony_ci   void *states[2] = {NULL};
795bf215546Sopenharmony_ci   assert(count <= ARRAY_SIZE(states));
796bf215546Sopenharmony_ci   if (ctx->base.saved_num_sampler_states)
797bf215546Sopenharmony_ci      pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0,
798bf215546Sopenharmony_ci                                ctx->base.saved_num_sampler_states,
799bf215546Sopenharmony_ci                                ctx->base.saved_sampler_states);
800bf215546Sopenharmony_ci   else if (count)
801bf215546Sopenharmony_ci      pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0,
802bf215546Sopenharmony_ci                                count,
803bf215546Sopenharmony_ci                                states);
804bf215546Sopenharmony_ci
805bf215546Sopenharmony_ci   ctx->base.saved_num_sampler_states = ~0;
806bf215546Sopenharmony_ci
807bf215546Sopenharmony_ci   /* Fragment sampler views. */
808bf215546Sopenharmony_ci   if (ctx->base.saved_num_sampler_views)
809bf215546Sopenharmony_ci      pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0,
810bf215546Sopenharmony_ci                              ctx->base.saved_num_sampler_views, 0, true,
811bf215546Sopenharmony_ci                              ctx->base.saved_sampler_views);
812bf215546Sopenharmony_ci   else if (count)
813bf215546Sopenharmony_ci      pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0,
814bf215546Sopenharmony_ci                              0, count, true,
815bf215546Sopenharmony_ci                              NULL);
816bf215546Sopenharmony_ci
817bf215546Sopenharmony_ci   /* Just clear them to NULL because set_sampler_views(take_ownership = true). */
818bf215546Sopenharmony_ci   for (i = 0; i < ctx->base.saved_num_sampler_views; i++)
819bf215546Sopenharmony_ci      ctx->base.saved_sampler_views[i] = NULL;
820bf215546Sopenharmony_ci
821bf215546Sopenharmony_ci   ctx->base.saved_num_sampler_views = ~0;
822bf215546Sopenharmony_ci}
823bf215546Sopenharmony_ci
824bf215546Sopenharmony_civoid util_blitter_restore_textures(struct blitter_context *blitter)
825bf215546Sopenharmony_ci{
826bf215546Sopenharmony_ci   util_blitter_restore_textures_internal(blitter, 0);
827bf215546Sopenharmony_ci}
828bf215546Sopenharmony_ci
829bf215546Sopenharmony_civoid util_blitter_restore_constant_buffer_state(struct blitter_context *blitter)
830bf215546Sopenharmony_ci{
831bf215546Sopenharmony_ci   struct pipe_context *pipe = blitter->pipe;
832bf215546Sopenharmony_ci
833bf215546Sopenharmony_ci   pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, blitter->cb_slot,
834bf215546Sopenharmony_ci                             true, &blitter->saved_fs_constant_buffer);
835bf215546Sopenharmony_ci   blitter->saved_fs_constant_buffer.buffer = NULL;
836bf215546Sopenharmony_ci}
837bf215546Sopenharmony_ci
838bf215546Sopenharmony_cistatic void blitter_set_rectangle(struct blitter_context_priv *ctx,
839bf215546Sopenharmony_ci                                  int x1, int y1, int x2, int y2,
840bf215546Sopenharmony_ci                                  float depth)
841bf215546Sopenharmony_ci{
842bf215546Sopenharmony_ci   /* set vertex positions */
843bf215546Sopenharmony_ci   ctx->vertices[0][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v0.x*/
844bf215546Sopenharmony_ci   ctx->vertices[0][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v0.y*/
845bf215546Sopenharmony_ci
846bf215546Sopenharmony_ci   ctx->vertices[1][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v1.x*/
847bf215546Sopenharmony_ci   ctx->vertices[1][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v1.y*/
848bf215546Sopenharmony_ci
849bf215546Sopenharmony_ci   ctx->vertices[2][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v2.x*/
850bf215546Sopenharmony_ci   ctx->vertices[2][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v2.y*/
851bf215546Sopenharmony_ci
852bf215546Sopenharmony_ci   ctx->vertices[3][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v3.x*/
853bf215546Sopenharmony_ci   ctx->vertices[3][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v3.y*/
854bf215546Sopenharmony_ci
855bf215546Sopenharmony_ci   for (unsigned i = 0; i < 4; ++i)
856bf215546Sopenharmony_ci      ctx->vertices[i][0][2] = depth;
857bf215546Sopenharmony_ci
858bf215546Sopenharmony_ci   /* viewport */
859bf215546Sopenharmony_ci   struct pipe_viewport_state viewport;
860bf215546Sopenharmony_ci   viewport.scale[0] = 0.5f * ctx->dst_width;
861bf215546Sopenharmony_ci   viewport.scale[1] = 0.5f * ctx->dst_height;
862bf215546Sopenharmony_ci   viewport.scale[2] = 1.0f;
863bf215546Sopenharmony_ci   viewport.translate[0] = 0.5f * ctx->dst_width;
864bf215546Sopenharmony_ci   viewport.translate[1] = 0.5f * ctx->dst_height;
865bf215546Sopenharmony_ci   viewport.translate[2] = 0.0f;
866bf215546Sopenharmony_ci   viewport.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X;
867bf215546Sopenharmony_ci   viewport.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y;
868bf215546Sopenharmony_ci   viewport.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z;
869bf215546Sopenharmony_ci   viewport.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W;
870bf215546Sopenharmony_ci   ctx->base.pipe->set_viewport_states(ctx->base.pipe, 0, 1, &viewport);
871bf215546Sopenharmony_ci}
872bf215546Sopenharmony_ci
873bf215546Sopenharmony_cistatic void blitter_set_clear_color(struct blitter_context_priv *ctx,
874bf215546Sopenharmony_ci                                    const float color[4])
875bf215546Sopenharmony_ci{
876bf215546Sopenharmony_ci   int i;
877bf215546Sopenharmony_ci
878bf215546Sopenharmony_ci   if (color) {
879bf215546Sopenharmony_ci      for (i = 0; i < 4; i++)
880bf215546Sopenharmony_ci         memcpy(&ctx->vertices[i][1][0], color, sizeof(uint32_t) * 4);
881bf215546Sopenharmony_ci   } else {
882bf215546Sopenharmony_ci      for (i = 0; i < 4; i++)
883bf215546Sopenharmony_ci         memset(&ctx->vertices[i][1][0], 0, sizeof(uint32_t) * 4);
884bf215546Sopenharmony_ci   }
885bf215546Sopenharmony_ci}
886bf215546Sopenharmony_ci
887bf215546Sopenharmony_cistatic void get_texcoords(struct pipe_sampler_view *src,
888bf215546Sopenharmony_ci                          unsigned src_width0, unsigned src_height0,
889bf215546Sopenharmony_ci                          int x1, int y1, int x2, int y2,
890bf215546Sopenharmony_ci                          float layer, unsigned sample,
891bf215546Sopenharmony_ci                          bool uses_txf, union blitter_attrib *out)
892bf215546Sopenharmony_ci{
893bf215546Sopenharmony_ci   unsigned level = src->u.tex.first_level;
894bf215546Sopenharmony_ci   bool normalized = !uses_txf &&
895bf215546Sopenharmony_ci                        src->target != PIPE_TEXTURE_RECT &&
896bf215546Sopenharmony_ci                        src->texture->nr_samples <= 1;
897bf215546Sopenharmony_ci
898bf215546Sopenharmony_ci   if (normalized) {
899bf215546Sopenharmony_ci      out->texcoord.x1 = x1 / (float)u_minify(src_width0,  level);
900bf215546Sopenharmony_ci      out->texcoord.y1 = y1 / (float)u_minify(src_height0, level);
901bf215546Sopenharmony_ci      out->texcoord.x2 = x2 / (float)u_minify(src_width0,  level);
902bf215546Sopenharmony_ci      out->texcoord.y2 = y2 / (float)u_minify(src_height0, level);
903bf215546Sopenharmony_ci   } else {
904bf215546Sopenharmony_ci      out->texcoord.x1 = x1;
905bf215546Sopenharmony_ci      out->texcoord.y1 = y1;
906bf215546Sopenharmony_ci      out->texcoord.x2 = x2;
907bf215546Sopenharmony_ci      out->texcoord.y2 = y2;
908bf215546Sopenharmony_ci   }
909bf215546Sopenharmony_ci
910bf215546Sopenharmony_ci   out->texcoord.z = 0;
911bf215546Sopenharmony_ci   out->texcoord.w = 0;
912bf215546Sopenharmony_ci
913bf215546Sopenharmony_ci   /* Set the layer. */
914bf215546Sopenharmony_ci   switch (src->target) {
915bf215546Sopenharmony_ci   case PIPE_TEXTURE_3D:
916bf215546Sopenharmony_ci      {
917bf215546Sopenharmony_ci         float r = layer;
918bf215546Sopenharmony_ci
919bf215546Sopenharmony_ci         if (!uses_txf)
920bf215546Sopenharmony_ci            r /= u_minify(src->texture->depth0, src->u.tex.first_level);
921bf215546Sopenharmony_ci
922bf215546Sopenharmony_ci         out->texcoord.z = r;
923bf215546Sopenharmony_ci      }
924bf215546Sopenharmony_ci      break;
925bf215546Sopenharmony_ci
926bf215546Sopenharmony_ci   case PIPE_TEXTURE_1D_ARRAY:
927bf215546Sopenharmony_ci      out->texcoord.y1 = out->texcoord.y2 = layer;
928bf215546Sopenharmony_ci      break;
929bf215546Sopenharmony_ci
930bf215546Sopenharmony_ci   case PIPE_TEXTURE_2D_ARRAY:
931bf215546Sopenharmony_ci      out->texcoord.z = layer;
932bf215546Sopenharmony_ci      out->texcoord.w = sample;
933bf215546Sopenharmony_ci      break;
934bf215546Sopenharmony_ci
935bf215546Sopenharmony_ci   case PIPE_TEXTURE_CUBE_ARRAY:
936bf215546Sopenharmony_ci      out->texcoord.w = (unsigned)layer / 6;
937bf215546Sopenharmony_ci      break;
938bf215546Sopenharmony_ci
939bf215546Sopenharmony_ci   case PIPE_TEXTURE_2D:
940bf215546Sopenharmony_ci      out->texcoord.w = sample;
941bf215546Sopenharmony_ci      break;
942bf215546Sopenharmony_ci
943bf215546Sopenharmony_ci   default:;
944bf215546Sopenharmony_ci   }
945bf215546Sopenharmony_ci}
946bf215546Sopenharmony_ci
947bf215546Sopenharmony_cistatic void blitter_set_dst_dimensions(struct blitter_context_priv *ctx,
948bf215546Sopenharmony_ci                                       unsigned width, unsigned height)
949bf215546Sopenharmony_ci{
950bf215546Sopenharmony_ci   ctx->dst_width = width;
951bf215546Sopenharmony_ci   ctx->dst_height = height;
952bf215546Sopenharmony_ci}
953bf215546Sopenharmony_ci
954bf215546Sopenharmony_cistatic void set_texcoords_in_vertices(const union blitter_attrib *attrib,
955bf215546Sopenharmony_ci                                      float *out, unsigned stride)
956bf215546Sopenharmony_ci{
957bf215546Sopenharmony_ci   out[0] = attrib->texcoord.x1;
958bf215546Sopenharmony_ci   out[1] = attrib->texcoord.y1;
959bf215546Sopenharmony_ci   out += stride;
960bf215546Sopenharmony_ci   out[0] = attrib->texcoord.x2;
961bf215546Sopenharmony_ci   out[1] = attrib->texcoord.y1;
962bf215546Sopenharmony_ci   out += stride;
963bf215546Sopenharmony_ci   out[0] = attrib->texcoord.x2;
964bf215546Sopenharmony_ci   out[1] = attrib->texcoord.y2;
965bf215546Sopenharmony_ci   out += stride;
966bf215546Sopenharmony_ci   out[0] = attrib->texcoord.x1;
967bf215546Sopenharmony_ci   out[1] = attrib->texcoord.y2;
968bf215546Sopenharmony_ci}
969bf215546Sopenharmony_ci
970bf215546Sopenharmony_cistatic void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
971bf215546Sopenharmony_ci                                         enum pipe_format src_format,
972bf215546Sopenharmony_ci                                         enum pipe_format dst_format,
973bf215546Sopenharmony_ci                                         enum pipe_texture_target target,
974bf215546Sopenharmony_ci                                         unsigned src_nr_samples,
975bf215546Sopenharmony_ci                                         unsigned dst_nr_samples,
976bf215546Sopenharmony_ci                                         unsigned filter,
977bf215546Sopenharmony_ci                                         bool use_txf)
978bf215546Sopenharmony_ci{
979bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
980bf215546Sopenharmony_ci   enum tgsi_texture_type tgsi_tex =
981bf215546Sopenharmony_ci      util_pipe_tex_to_tgsi_tex(target, src_nr_samples);
982bf215546Sopenharmony_ci   enum tgsi_return_type stype;
983bf215546Sopenharmony_ci   enum tgsi_return_type dtype;
984bf215546Sopenharmony_ci   unsigned type;
985bf215546Sopenharmony_ci
986bf215546Sopenharmony_ci   assert(target < PIPE_MAX_TEXTURE_TYPES);
987bf215546Sopenharmony_ci
988bf215546Sopenharmony_ci   if (util_format_is_pure_uint(src_format)) {
989bf215546Sopenharmony_ci      stype = TGSI_RETURN_TYPE_UINT;
990bf215546Sopenharmony_ci      if (util_format_is_pure_uint(dst_format)) {
991bf215546Sopenharmony_ci         dtype = TGSI_RETURN_TYPE_UINT;
992bf215546Sopenharmony_ci         type = 0;
993bf215546Sopenharmony_ci      } else {
994bf215546Sopenharmony_ci         assert(util_format_is_pure_sint(dst_format));
995bf215546Sopenharmony_ci         dtype = TGSI_RETURN_TYPE_SINT;
996bf215546Sopenharmony_ci         type = 1;
997bf215546Sopenharmony_ci      }
998bf215546Sopenharmony_ci   } else if (util_format_is_pure_sint(src_format)) {
999bf215546Sopenharmony_ci      stype = TGSI_RETURN_TYPE_SINT;
1000bf215546Sopenharmony_ci      if (util_format_is_pure_sint(dst_format)) {
1001bf215546Sopenharmony_ci         dtype = TGSI_RETURN_TYPE_SINT;
1002bf215546Sopenharmony_ci         type = 2;
1003bf215546Sopenharmony_ci      } else {
1004bf215546Sopenharmony_ci         assert(util_format_is_pure_uint(dst_format));
1005bf215546Sopenharmony_ci         dtype = TGSI_RETURN_TYPE_UINT;
1006bf215546Sopenharmony_ci         type = 3;
1007bf215546Sopenharmony_ci      }
1008bf215546Sopenharmony_ci   } else {
1009bf215546Sopenharmony_ci      assert(!util_format_is_pure_uint(dst_format) &&
1010bf215546Sopenharmony_ci             !util_format_is_pure_sint(dst_format));
1011bf215546Sopenharmony_ci      dtype = stype = TGSI_RETURN_TYPE_FLOAT;
1012bf215546Sopenharmony_ci      type = 4;
1013bf215546Sopenharmony_ci   }
1014bf215546Sopenharmony_ci
1015bf215546Sopenharmony_ci   if (src_nr_samples > 1) {
1016bf215546Sopenharmony_ci      void **shader;
1017bf215546Sopenharmony_ci
1018bf215546Sopenharmony_ci      /* OpenGL requires that integer textures just copy 1 sample instead
1019bf215546Sopenharmony_ci       * of averaging.
1020bf215546Sopenharmony_ci       */
1021bf215546Sopenharmony_ci      if (dst_nr_samples <= 1 &&
1022bf215546Sopenharmony_ci          stype != TGSI_RETURN_TYPE_UINT &&
1023bf215546Sopenharmony_ci          stype != TGSI_RETURN_TYPE_SINT) {
1024bf215546Sopenharmony_ci         /* The destination has one sample, so we'll do color resolve. */
1025bf215546Sopenharmony_ci         unsigned index = GET_MSAA_RESOLVE_FS_IDX(src_nr_samples);
1026bf215546Sopenharmony_ci
1027bf215546Sopenharmony_ci         assert(filter < 2);
1028bf215546Sopenharmony_ci
1029bf215546Sopenharmony_ci         shader = &ctx->fs_resolve[target][index][filter];
1030bf215546Sopenharmony_ci
1031bf215546Sopenharmony_ci         if (!*shader) {
1032bf215546Sopenharmony_ci            assert(!ctx->cached_all_shaders);
1033bf215546Sopenharmony_ci            if (filter == PIPE_TEX_FILTER_LINEAR) {
1034bf215546Sopenharmony_ci               *shader = util_make_fs_msaa_resolve_bilinear(pipe, tgsi_tex,
1035bf215546Sopenharmony_ci                                                   src_nr_samples,
1036bf215546Sopenharmony_ci                                                   stype);
1037bf215546Sopenharmony_ci            }
1038bf215546Sopenharmony_ci            else {
1039bf215546Sopenharmony_ci               *shader = util_make_fs_msaa_resolve(pipe, tgsi_tex,
1040bf215546Sopenharmony_ci                                                   src_nr_samples,
1041bf215546Sopenharmony_ci                                                   stype);
1042bf215546Sopenharmony_ci            }
1043bf215546Sopenharmony_ci         }
1044bf215546Sopenharmony_ci      }
1045bf215546Sopenharmony_ci      else {
1046bf215546Sopenharmony_ci         /* The destination has multiple samples, we'll do
1047bf215546Sopenharmony_ci          * an MSAA->MSAA copy.
1048bf215546Sopenharmony_ci          */
1049bf215546Sopenharmony_ci         shader = &ctx->fs_texfetch_col_msaa[type][target];
1050bf215546Sopenharmony_ci
1051bf215546Sopenharmony_ci         /* Create the fragment shader on-demand. */
1052bf215546Sopenharmony_ci         if (!*shader) {
1053bf215546Sopenharmony_ci            assert(!ctx->cached_all_shaders);
1054bf215546Sopenharmony_ci            *shader = util_make_fs_blit_msaa_color(pipe, tgsi_tex, stype, dtype,
1055bf215546Sopenharmony_ci                                                   ctx->has_sample_shading);
1056bf215546Sopenharmony_ci         }
1057bf215546Sopenharmony_ci      }
1058bf215546Sopenharmony_ci
1059bf215546Sopenharmony_ci      return *shader;
1060bf215546Sopenharmony_ci   } else {
1061bf215546Sopenharmony_ci      void **shader;
1062bf215546Sopenharmony_ci
1063bf215546Sopenharmony_ci      if (use_txf)
1064bf215546Sopenharmony_ci         shader = &ctx->fs_texfetch_col[type][target][1];
1065bf215546Sopenharmony_ci      else
1066bf215546Sopenharmony_ci         shader = &ctx->fs_texfetch_col[type][target][0];
1067bf215546Sopenharmony_ci
1068bf215546Sopenharmony_ci      /* Create the fragment shader on-demand. */
1069bf215546Sopenharmony_ci      if (!*shader) {
1070bf215546Sopenharmony_ci         assert(!ctx->cached_all_shaders);
1071bf215546Sopenharmony_ci         *shader = util_make_fragment_tex_shader(pipe, tgsi_tex,
1072bf215546Sopenharmony_ci                                                 TGSI_INTERPOLATE_LINEAR,
1073bf215546Sopenharmony_ci                                                 stype, dtype,
1074bf215546Sopenharmony_ci                                                 ctx->has_tex_lz, use_txf);
1075bf215546Sopenharmony_ci      }
1076bf215546Sopenharmony_ci
1077bf215546Sopenharmony_ci      return *shader;
1078bf215546Sopenharmony_ci   }
1079bf215546Sopenharmony_ci}
1080bf215546Sopenharmony_ci
1081bf215546Sopenharmony_cistatic inline
1082bf215546Sopenharmony_civoid *blitter_get_fs_pack_color_zs(struct blitter_context_priv *ctx,
1083bf215546Sopenharmony_ci                                   enum pipe_texture_target target,
1084bf215546Sopenharmony_ci                                   unsigned nr_samples,
1085bf215546Sopenharmony_ci                                   enum pipe_format zs_format,
1086bf215546Sopenharmony_ci                                   bool dst_is_color)
1087bf215546Sopenharmony_ci{
1088bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
1089bf215546Sopenharmony_ci   enum tgsi_texture_type tgsi_tex =
1090bf215546Sopenharmony_ci      util_pipe_tex_to_tgsi_tex(target, nr_samples);
1091bf215546Sopenharmony_ci   int format_index = zs_format == PIPE_FORMAT_Z24_UNORM_S8_UINT ? 0 :
1092bf215546Sopenharmony_ci                      zs_format == PIPE_FORMAT_S8_UINT_Z24_UNORM ? 1 :
1093bf215546Sopenharmony_ci                      zs_format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ? 2 :
1094bf215546Sopenharmony_ci                      zs_format == PIPE_FORMAT_Z24X8_UNORM ? 3 :
1095bf215546Sopenharmony_ci                      zs_format == PIPE_FORMAT_X8Z24_UNORM ? 4 : -1;
1096bf215546Sopenharmony_ci
1097bf215546Sopenharmony_ci   if (format_index == -1) {
1098bf215546Sopenharmony_ci      assert(0);
1099bf215546Sopenharmony_ci      return NULL;
1100bf215546Sopenharmony_ci   }
1101bf215546Sopenharmony_ci
1102bf215546Sopenharmony_ci   /* The first 5 shaders pack ZS to color, the last 5 shaders unpack color
1103bf215546Sopenharmony_ci    * to ZS.
1104bf215546Sopenharmony_ci    */
1105bf215546Sopenharmony_ci   if (dst_is_color)
1106bf215546Sopenharmony_ci      format_index += 5;
1107bf215546Sopenharmony_ci
1108bf215546Sopenharmony_ci   void **shader = &ctx->fs_pack_color_zs[tgsi_tex][format_index];
1109bf215546Sopenharmony_ci
1110bf215546Sopenharmony_ci   /* Create the fragment shader on-demand. */
1111bf215546Sopenharmony_ci   if (!*shader) {
1112bf215546Sopenharmony_ci      assert(!ctx->cached_all_shaders);
1113bf215546Sopenharmony_ci      *shader = util_make_fs_pack_color_zs(pipe, tgsi_tex, zs_format,
1114bf215546Sopenharmony_ci                                           dst_is_color);
1115bf215546Sopenharmony_ci   }
1116bf215546Sopenharmony_ci   return *shader;
1117bf215546Sopenharmony_ci}
1118bf215546Sopenharmony_ci
1119bf215546Sopenharmony_cistatic inline
1120bf215546Sopenharmony_civoid *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
1121bf215546Sopenharmony_ci                                    enum pipe_texture_target target,
1122bf215546Sopenharmony_ci                                    unsigned src_samples, unsigned dst_samples,
1123bf215546Sopenharmony_ci                                    bool use_txf)
1124bf215546Sopenharmony_ci{
1125bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
1126bf215546Sopenharmony_ci
1127bf215546Sopenharmony_ci   assert(target < PIPE_MAX_TEXTURE_TYPES);
1128bf215546Sopenharmony_ci
1129bf215546Sopenharmony_ci   if (src_samples > 1) {
1130bf215546Sopenharmony_ci      bool sample_shading = ctx->has_sample_shading && src_samples > 1 &&
1131bf215546Sopenharmony_ci                            src_samples == dst_samples;
1132bf215546Sopenharmony_ci      void **shader = &ctx->fs_texfetch_depth_msaa[target][sample_shading];
1133bf215546Sopenharmony_ci
1134bf215546Sopenharmony_ci      /* Create the fragment shader on-demand. */
1135bf215546Sopenharmony_ci      if (!*shader) {
1136bf215546Sopenharmony_ci         enum tgsi_texture_type tgsi_tex;
1137bf215546Sopenharmony_ci         assert(!ctx->cached_all_shaders);
1138bf215546Sopenharmony_ci         tgsi_tex = util_pipe_tex_to_tgsi_tex(target, src_samples);
1139bf215546Sopenharmony_ci         *shader = util_make_fs_blit_msaa_depth(pipe, tgsi_tex, sample_shading);
1140bf215546Sopenharmony_ci      }
1141bf215546Sopenharmony_ci
1142bf215546Sopenharmony_ci      return *shader;
1143bf215546Sopenharmony_ci   } else {
1144bf215546Sopenharmony_ci      void **shader;
1145bf215546Sopenharmony_ci
1146bf215546Sopenharmony_ci      if (use_txf)
1147bf215546Sopenharmony_ci         shader = &ctx->fs_texfetch_depth[target][1];
1148bf215546Sopenharmony_ci      else
1149bf215546Sopenharmony_ci         shader = &ctx->fs_texfetch_depth[target][0];
1150bf215546Sopenharmony_ci
1151bf215546Sopenharmony_ci      /* Create the fragment shader on-demand. */
1152bf215546Sopenharmony_ci      if (!*shader) {
1153bf215546Sopenharmony_ci         enum tgsi_texture_type tgsi_tex;
1154bf215546Sopenharmony_ci         assert(!ctx->cached_all_shaders);
1155bf215546Sopenharmony_ci         tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
1156bf215546Sopenharmony_ci         *shader = util_make_fs_blit_zs(pipe, PIPE_MASK_Z, tgsi_tex,
1157bf215546Sopenharmony_ci                                        ctx->has_tex_lz, use_txf);
1158bf215546Sopenharmony_ci      }
1159bf215546Sopenharmony_ci
1160bf215546Sopenharmony_ci      return *shader;
1161bf215546Sopenharmony_ci   }
1162bf215546Sopenharmony_ci}
1163bf215546Sopenharmony_ci
1164bf215546Sopenharmony_cistatic inline
1165bf215546Sopenharmony_civoid *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,
1166bf215546Sopenharmony_ci                                           enum pipe_texture_target target,
1167bf215546Sopenharmony_ci                                           unsigned src_samples,
1168bf215546Sopenharmony_ci                                           unsigned dst_samples, bool use_txf)
1169bf215546Sopenharmony_ci{
1170bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
1171bf215546Sopenharmony_ci
1172bf215546Sopenharmony_ci   assert(target < PIPE_MAX_TEXTURE_TYPES);
1173bf215546Sopenharmony_ci
1174bf215546Sopenharmony_ci   if (src_samples > 1) {
1175bf215546Sopenharmony_ci      bool sample_shading = ctx->has_sample_shading && src_samples > 1 &&
1176bf215546Sopenharmony_ci                            src_samples == dst_samples;
1177bf215546Sopenharmony_ci      void **shader = &ctx->fs_texfetch_depthstencil_msaa[target][sample_shading];
1178bf215546Sopenharmony_ci
1179bf215546Sopenharmony_ci      /* Create the fragment shader on-demand. */
1180bf215546Sopenharmony_ci      if (!*shader) {
1181bf215546Sopenharmony_ci         enum tgsi_texture_type tgsi_tex;
1182bf215546Sopenharmony_ci         assert(!ctx->cached_all_shaders);
1183bf215546Sopenharmony_ci         tgsi_tex = util_pipe_tex_to_tgsi_tex(target, src_samples);
1184bf215546Sopenharmony_ci         *shader = util_make_fs_blit_msaa_depthstencil(pipe, tgsi_tex,
1185bf215546Sopenharmony_ci                                                       sample_shading);
1186bf215546Sopenharmony_ci      }
1187bf215546Sopenharmony_ci
1188bf215546Sopenharmony_ci      return *shader;
1189bf215546Sopenharmony_ci   } else {
1190bf215546Sopenharmony_ci      void **shader;
1191bf215546Sopenharmony_ci
1192bf215546Sopenharmony_ci      if (use_txf)
1193bf215546Sopenharmony_ci         shader = &ctx->fs_texfetch_depthstencil[target][1];
1194bf215546Sopenharmony_ci      else
1195bf215546Sopenharmony_ci         shader = &ctx->fs_texfetch_depthstencil[target][0];
1196bf215546Sopenharmony_ci
1197bf215546Sopenharmony_ci      /* Create the fragment shader on-demand. */
1198bf215546Sopenharmony_ci      if (!*shader) {
1199bf215546Sopenharmony_ci         enum tgsi_texture_type tgsi_tex;
1200bf215546Sopenharmony_ci         assert(!ctx->cached_all_shaders);
1201bf215546Sopenharmony_ci         tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
1202bf215546Sopenharmony_ci         *shader = util_make_fs_blit_zs(pipe, PIPE_MASK_ZS, tgsi_tex,
1203bf215546Sopenharmony_ci                                        ctx->has_tex_lz, use_txf);
1204bf215546Sopenharmony_ci      }
1205bf215546Sopenharmony_ci
1206bf215546Sopenharmony_ci      return *shader;
1207bf215546Sopenharmony_ci   }
1208bf215546Sopenharmony_ci}
1209bf215546Sopenharmony_ci
1210bf215546Sopenharmony_cistatic inline
1211bf215546Sopenharmony_civoid *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
1212bf215546Sopenharmony_ci                                      enum pipe_texture_target target,
1213bf215546Sopenharmony_ci                                      unsigned src_samples, unsigned dst_samples,
1214bf215546Sopenharmony_ci                                      bool use_txf)
1215bf215546Sopenharmony_ci{
1216bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
1217bf215546Sopenharmony_ci
1218bf215546Sopenharmony_ci   assert(target < PIPE_MAX_TEXTURE_TYPES);
1219bf215546Sopenharmony_ci
1220bf215546Sopenharmony_ci   if (src_samples > 1) {
1221bf215546Sopenharmony_ci      bool sample_shading = ctx->has_sample_shading && src_samples > 1 &&
1222bf215546Sopenharmony_ci                            src_samples == dst_samples;
1223bf215546Sopenharmony_ci      void **shader = &ctx->fs_texfetch_stencil_msaa[target][sample_shading];
1224bf215546Sopenharmony_ci
1225bf215546Sopenharmony_ci      /* Create the fragment shader on-demand. */
1226bf215546Sopenharmony_ci      if (!*shader) {
1227bf215546Sopenharmony_ci         enum tgsi_texture_type tgsi_tex;
1228bf215546Sopenharmony_ci         assert(!ctx->cached_all_shaders);
1229bf215546Sopenharmony_ci         tgsi_tex = util_pipe_tex_to_tgsi_tex(target, src_samples);
1230bf215546Sopenharmony_ci         *shader = util_make_fs_blit_msaa_stencil(pipe, tgsi_tex,
1231bf215546Sopenharmony_ci                                                  sample_shading);
1232bf215546Sopenharmony_ci      }
1233bf215546Sopenharmony_ci
1234bf215546Sopenharmony_ci      return *shader;
1235bf215546Sopenharmony_ci   } else {
1236bf215546Sopenharmony_ci      void **shader;
1237bf215546Sopenharmony_ci
1238bf215546Sopenharmony_ci      if (use_txf)
1239bf215546Sopenharmony_ci         shader = &ctx->fs_texfetch_stencil[target][1];
1240bf215546Sopenharmony_ci      else
1241bf215546Sopenharmony_ci         shader = &ctx->fs_texfetch_stencil[target][0];
1242bf215546Sopenharmony_ci
1243bf215546Sopenharmony_ci      /* Create the fragment shader on-demand. */
1244bf215546Sopenharmony_ci      if (!*shader) {
1245bf215546Sopenharmony_ci         enum tgsi_texture_type tgsi_tex;
1246bf215546Sopenharmony_ci         assert(!ctx->cached_all_shaders);
1247bf215546Sopenharmony_ci         tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
1248bf215546Sopenharmony_ci         *shader = util_make_fs_blit_zs(pipe, PIPE_MASK_S, tgsi_tex,
1249bf215546Sopenharmony_ci                                        ctx->has_tex_lz, use_txf);
1250bf215546Sopenharmony_ci      }
1251bf215546Sopenharmony_ci
1252bf215546Sopenharmony_ci      return *shader;
1253bf215546Sopenharmony_ci   }
1254bf215546Sopenharmony_ci}
1255bf215546Sopenharmony_ci
1256bf215546Sopenharmony_ci
1257bf215546Sopenharmony_ci/**
1258bf215546Sopenharmony_ci * Generate and save all fragment shaders that we will ever need for
1259bf215546Sopenharmony_ci * blitting.  Drivers which use the 'draw' fallbacks will typically use
1260bf215546Sopenharmony_ci * this to make sure we generate/use shaders that don't go through the
1261bf215546Sopenharmony_ci * draw module's wrapper functions.
1262bf215546Sopenharmony_ci */
1263bf215546Sopenharmony_civoid util_blitter_cache_all_shaders(struct blitter_context *blitter)
1264bf215546Sopenharmony_ci{
1265bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1266bf215546Sopenharmony_ci   struct pipe_context *pipe = blitter->pipe;
1267bf215546Sopenharmony_ci   struct pipe_screen *screen = pipe->screen;
1268bf215546Sopenharmony_ci   unsigned samples, j, f, target, max_samples, use_txf;
1269bf215546Sopenharmony_ci   bool has_arraytex, has_cubearraytex;
1270bf215546Sopenharmony_ci
1271bf215546Sopenharmony_ci   max_samples = ctx->has_texture_multisample ? 2 : 1;
1272bf215546Sopenharmony_ci   has_arraytex = screen->get_param(screen,
1273bf215546Sopenharmony_ci                                    PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS) != 0;
1274bf215546Sopenharmony_ci   has_cubearraytex = screen->get_param(screen,
1275bf215546Sopenharmony_ci                                    PIPE_CAP_CUBE_MAP_ARRAY) != 0;
1276bf215546Sopenharmony_ci
1277bf215546Sopenharmony_ci   /* It only matters if i <= 1 or > 1. */
1278bf215546Sopenharmony_ci   for (samples = 1; samples <= max_samples; samples++) {
1279bf215546Sopenharmony_ci      for (target = PIPE_TEXTURE_1D; target < PIPE_MAX_TEXTURE_TYPES; target++) {
1280bf215546Sopenharmony_ci         for (use_txf = 0; use_txf <= ctx->has_txf; use_txf++) {
1281bf215546Sopenharmony_ci            if (!has_arraytex &&
1282bf215546Sopenharmony_ci                (target == PIPE_TEXTURE_1D_ARRAY ||
1283bf215546Sopenharmony_ci                 target == PIPE_TEXTURE_2D_ARRAY)) {
1284bf215546Sopenharmony_ci               continue;
1285bf215546Sopenharmony_ci            }
1286bf215546Sopenharmony_ci            if (!has_cubearraytex &&
1287bf215546Sopenharmony_ci                (target == PIPE_TEXTURE_CUBE_ARRAY))
1288bf215546Sopenharmony_ci               continue;
1289bf215546Sopenharmony_ci            if (!ctx->has_texrect &&
1290bf215546Sopenharmony_ci                (target == PIPE_TEXTURE_RECT))
1291bf215546Sopenharmony_ci               continue;
1292bf215546Sopenharmony_ci
1293bf215546Sopenharmony_ci            if (samples > 1 &&
1294bf215546Sopenharmony_ci                (target != PIPE_TEXTURE_2D &&
1295bf215546Sopenharmony_ci                 target != PIPE_TEXTURE_2D_ARRAY))
1296bf215546Sopenharmony_ci               continue;
1297bf215546Sopenharmony_ci
1298bf215546Sopenharmony_ci            if (samples > 1 && use_txf)
1299bf215546Sopenharmony_ci               continue; /* TXF is the only option, use_txf has no effect */
1300bf215546Sopenharmony_ci
1301bf215546Sopenharmony_ci            /* If samples == 1, the shaders read one texel. If samples >= 1,
1302bf215546Sopenharmony_ci             * they read one sample.
1303bf215546Sopenharmony_ci             */
1304bf215546Sopenharmony_ci            blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_FLOAT,
1305bf215546Sopenharmony_ci                                        PIPE_FORMAT_R32_FLOAT, target,
1306bf215546Sopenharmony_ci                                        samples, samples, 0, use_txf);
1307bf215546Sopenharmony_ci            blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_UINT,
1308bf215546Sopenharmony_ci                                        PIPE_FORMAT_R32_UINT, target,
1309bf215546Sopenharmony_ci                                        samples, samples, 0, use_txf);
1310bf215546Sopenharmony_ci            blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_UINT,
1311bf215546Sopenharmony_ci                                        PIPE_FORMAT_R32_SINT, target,
1312bf215546Sopenharmony_ci                                        samples, samples, 0, use_txf);
1313bf215546Sopenharmony_ci            blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_SINT,
1314bf215546Sopenharmony_ci                                        PIPE_FORMAT_R32_SINT, target,
1315bf215546Sopenharmony_ci                                        samples, samples, 0, use_txf);
1316bf215546Sopenharmony_ci            blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_SINT,
1317bf215546Sopenharmony_ci                                        PIPE_FORMAT_R32_UINT, target,
1318bf215546Sopenharmony_ci                                        samples, samples, 0, use_txf);
1319bf215546Sopenharmony_ci            blitter_get_fs_texfetch_depth(ctx, target, samples, samples, use_txf);
1320bf215546Sopenharmony_ci            if (ctx->has_stencil_export) {
1321bf215546Sopenharmony_ci               blitter_get_fs_texfetch_depthstencil(ctx, target, samples, samples, use_txf);
1322bf215546Sopenharmony_ci               blitter_get_fs_texfetch_stencil(ctx, target, samples, samples, use_txf);
1323bf215546Sopenharmony_ci            }
1324bf215546Sopenharmony_ci
1325bf215546Sopenharmony_ci            if (samples == 2) {
1326bf215546Sopenharmony_ci               blitter_get_fs_texfetch_depth(ctx, target, samples, 1, use_txf);
1327bf215546Sopenharmony_ci               if (ctx->has_stencil_export) {
1328bf215546Sopenharmony_ci                  blitter_get_fs_texfetch_depthstencil(ctx, target, samples, 1, use_txf);
1329bf215546Sopenharmony_ci                  blitter_get_fs_texfetch_stencil(ctx, target, samples, 1, use_txf);
1330bf215546Sopenharmony_ci               }
1331bf215546Sopenharmony_ci            }
1332bf215546Sopenharmony_ci
1333bf215546Sopenharmony_ci            if (samples == 1)
1334bf215546Sopenharmony_ci               continue;
1335bf215546Sopenharmony_ci
1336bf215546Sopenharmony_ci            /* MSAA resolve shaders. */
1337bf215546Sopenharmony_ci            for (j = 2; j < 32; j++) {
1338bf215546Sopenharmony_ci               if (!screen->is_format_supported(screen, PIPE_FORMAT_R32_FLOAT,
1339bf215546Sopenharmony_ci                                                target, j, j,
1340bf215546Sopenharmony_ci                                                PIPE_BIND_SAMPLER_VIEW)) {
1341bf215546Sopenharmony_ci                  continue;
1342bf215546Sopenharmony_ci               }
1343bf215546Sopenharmony_ci
1344bf215546Sopenharmony_ci               for (f = 0; f < 2; f++) {
1345bf215546Sopenharmony_ci                  if (f != PIPE_TEX_FILTER_NEAREST && use_txf)
1346bf215546Sopenharmony_ci                     continue;
1347bf215546Sopenharmony_ci
1348bf215546Sopenharmony_ci                  blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_FLOAT,
1349bf215546Sopenharmony_ci                                              PIPE_FORMAT_R32_FLOAT, target,
1350bf215546Sopenharmony_ci                                              j, 1, f, use_txf);
1351bf215546Sopenharmony_ci                  blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_UINT,
1352bf215546Sopenharmony_ci                                              PIPE_FORMAT_R32_UINT, target,
1353bf215546Sopenharmony_ci                                              j, 1, f, use_txf);
1354bf215546Sopenharmony_ci                  blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_SINT,
1355bf215546Sopenharmony_ci                                              PIPE_FORMAT_R32_SINT, target,
1356bf215546Sopenharmony_ci                                              j, 1, f, use_txf);
1357bf215546Sopenharmony_ci               }
1358bf215546Sopenharmony_ci            }
1359bf215546Sopenharmony_ci         }
1360bf215546Sopenharmony_ci      }
1361bf215546Sopenharmony_ci   }
1362bf215546Sopenharmony_ci
1363bf215546Sopenharmony_ci   ctx->fs_empty = util_make_empty_fragment_shader(pipe);
1364bf215546Sopenharmony_ci
1365bf215546Sopenharmony_ci   ctx->fs_write_one_cbuf =
1366bf215546Sopenharmony_ci      util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,
1367bf215546Sopenharmony_ci                                            TGSI_INTERPOLATE_CONSTANT, false);
1368bf215546Sopenharmony_ci
1369bf215546Sopenharmony_ci   ctx->fs_clear_all_cbufs = util_make_fs_clear_all_cbufs(pipe);
1370bf215546Sopenharmony_ci
1371bf215546Sopenharmony_ci   ctx->cached_all_shaders = true;
1372bf215546Sopenharmony_ci}
1373bf215546Sopenharmony_ci
1374bf215546Sopenharmony_cistatic void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx,
1375bf215546Sopenharmony_ci                                               bool scissor, bool msaa)
1376bf215546Sopenharmony_ci{
1377bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
1378bf215546Sopenharmony_ci
1379bf215546Sopenharmony_ci   if (ctx->base.saved_num_window_rectangles)
1380bf215546Sopenharmony_ci      pipe->set_window_rectangles(pipe, false, 0, NULL);
1381bf215546Sopenharmony_ci
1382bf215546Sopenharmony_ci   pipe->bind_rasterizer_state(pipe, ctx->rs_state[scissor][msaa]);
1383bf215546Sopenharmony_ci
1384bf215546Sopenharmony_ci   if (ctx->has_geometry_shader)
1385bf215546Sopenharmony_ci      pipe->bind_gs_state(pipe, NULL);
1386bf215546Sopenharmony_ci   if (ctx->has_tessellation) {
1387bf215546Sopenharmony_ci      pipe->bind_tcs_state(pipe, NULL);
1388bf215546Sopenharmony_ci      pipe->bind_tes_state(pipe, NULL);
1389bf215546Sopenharmony_ci   }
1390bf215546Sopenharmony_ci   if (ctx->has_stream_out)
1391bf215546Sopenharmony_ci      pipe->set_stream_output_targets(pipe, 0, NULL, NULL);
1392bf215546Sopenharmony_ci}
1393bf215546Sopenharmony_ci
1394bf215546Sopenharmony_cistatic void blitter_draw(struct blitter_context_priv *ctx,
1395bf215546Sopenharmony_ci                         void *vertex_elements_cso,
1396bf215546Sopenharmony_ci                         blitter_get_vs_func get_vs,
1397bf215546Sopenharmony_ci                         int x1, int y1, int x2, int y2, float depth,
1398bf215546Sopenharmony_ci                         unsigned num_instances)
1399bf215546Sopenharmony_ci{
1400bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
1401bf215546Sopenharmony_ci   struct pipe_vertex_buffer vb = {0};
1402bf215546Sopenharmony_ci
1403bf215546Sopenharmony_ci   blitter_set_rectangle(ctx, x1, y1, x2, y2, depth);
1404bf215546Sopenharmony_ci
1405bf215546Sopenharmony_ci   vb.stride = 8 * sizeof(float);
1406bf215546Sopenharmony_ci
1407bf215546Sopenharmony_ci   u_upload_data(pipe->stream_uploader, 0, sizeof(ctx->vertices), 4, ctx->vertices,
1408bf215546Sopenharmony_ci                 &vb.buffer_offset, &vb.buffer.resource);
1409bf215546Sopenharmony_ci   if (!vb.buffer.resource)
1410bf215546Sopenharmony_ci      return;
1411bf215546Sopenharmony_ci   u_upload_unmap(pipe->stream_uploader);
1412bf215546Sopenharmony_ci
1413bf215546Sopenharmony_ci   pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, 0, false, &vb);
1414bf215546Sopenharmony_ci   pipe->bind_vertex_elements_state(pipe, vertex_elements_cso);
1415bf215546Sopenharmony_ci   pipe->bind_vs_state(pipe, get_vs(&ctx->base));
1416bf215546Sopenharmony_ci
1417bf215546Sopenharmony_ci   if (ctx->base.use_index_buffer) {
1418bf215546Sopenharmony_ci      /* Note that for V3D,
1419bf215546Sopenharmony_ci       * dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_* require
1420bf215546Sopenharmony_ci       * that the last vert of the two tris be the same.
1421bf215546Sopenharmony_ci       */
1422bf215546Sopenharmony_ci      static uint8_t indices[6] = { 0, 1, 2, 0, 3, 2 };
1423bf215546Sopenharmony_ci      util_draw_elements_instanced(pipe, indices, 1, 0,
1424bf215546Sopenharmony_ci                                   PIPE_PRIM_TRIANGLES, 0, 6,
1425bf215546Sopenharmony_ci                                   0, num_instances);
1426bf215546Sopenharmony_ci   } else {
1427bf215546Sopenharmony_ci      util_draw_arrays_instanced(pipe, PIPE_PRIM_TRIANGLE_FAN, 0, 4,
1428bf215546Sopenharmony_ci                                 0, num_instances);
1429bf215546Sopenharmony_ci   }
1430bf215546Sopenharmony_ci   pipe_resource_reference(&vb.buffer.resource, NULL);
1431bf215546Sopenharmony_ci}
1432bf215546Sopenharmony_ci
1433bf215546Sopenharmony_civoid util_blitter_draw_rectangle(struct blitter_context *blitter,
1434bf215546Sopenharmony_ci                                 void *vertex_elements_cso,
1435bf215546Sopenharmony_ci                                 blitter_get_vs_func get_vs,
1436bf215546Sopenharmony_ci                                 int x1, int y1, int x2, int y2,
1437bf215546Sopenharmony_ci                                 float depth, unsigned num_instances,
1438bf215546Sopenharmony_ci                                 enum blitter_attrib_type type,
1439bf215546Sopenharmony_ci                                 const union blitter_attrib *attrib)
1440bf215546Sopenharmony_ci{
1441bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1442bf215546Sopenharmony_ci   unsigned i;
1443bf215546Sopenharmony_ci
1444bf215546Sopenharmony_ci   switch (type) {
1445bf215546Sopenharmony_ci      case UTIL_BLITTER_ATTRIB_COLOR:
1446bf215546Sopenharmony_ci         blitter_set_clear_color(ctx, attrib->color);
1447bf215546Sopenharmony_ci         break;
1448bf215546Sopenharmony_ci
1449bf215546Sopenharmony_ci      case UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW:
1450bf215546Sopenharmony_ci         for (i = 0; i < 4; i++) {
1451bf215546Sopenharmony_ci            ctx->vertices[i][1][2] = attrib->texcoord.z;
1452bf215546Sopenharmony_ci            ctx->vertices[i][1][3] = attrib->texcoord.w;
1453bf215546Sopenharmony_ci         }
1454bf215546Sopenharmony_ci         set_texcoords_in_vertices(attrib, &ctx->vertices[0][1][0], 8);
1455bf215546Sopenharmony_ci         break;
1456bf215546Sopenharmony_ci      case UTIL_BLITTER_ATTRIB_TEXCOORD_XY:
1457bf215546Sopenharmony_ci         /* We clean-up the ZW components, just in case we used before XYZW,
1458bf215546Sopenharmony_ci          * to avoid feeding in the shader with wrong values (like on the lod)
1459bf215546Sopenharmony_ci          */
1460bf215546Sopenharmony_ci         for (i = 0; i < 4; i++) {
1461bf215546Sopenharmony_ci            ctx->vertices[i][1][2] = 0;
1462bf215546Sopenharmony_ci            ctx->vertices[i][1][3] = 0;
1463bf215546Sopenharmony_ci         }
1464bf215546Sopenharmony_ci         set_texcoords_in_vertices(attrib, &ctx->vertices[0][1][0], 8);
1465bf215546Sopenharmony_ci         break;
1466bf215546Sopenharmony_ci
1467bf215546Sopenharmony_ci      default:;
1468bf215546Sopenharmony_ci   }
1469bf215546Sopenharmony_ci
1470bf215546Sopenharmony_ci   blitter_draw(ctx, vertex_elements_cso, get_vs, x1, y1, x2, y2, depth,
1471bf215546Sopenharmony_ci                num_instances);
1472bf215546Sopenharmony_ci}
1473bf215546Sopenharmony_ci
1474bf215546Sopenharmony_cistatic void *get_clear_blend_state(struct blitter_context_priv *ctx,
1475bf215546Sopenharmony_ci                                   unsigned clear_buffers)
1476bf215546Sopenharmony_ci{
1477bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
1478bf215546Sopenharmony_ci   int index;
1479bf215546Sopenharmony_ci
1480bf215546Sopenharmony_ci   clear_buffers &= PIPE_CLEAR_COLOR;
1481bf215546Sopenharmony_ci
1482bf215546Sopenharmony_ci   /* Return an existing blend state. */
1483bf215546Sopenharmony_ci   if (!clear_buffers)
1484bf215546Sopenharmony_ci      return ctx->blend[0][0];
1485bf215546Sopenharmony_ci
1486bf215546Sopenharmony_ci   index = GET_CLEAR_BLEND_STATE_IDX(clear_buffers);
1487bf215546Sopenharmony_ci
1488bf215546Sopenharmony_ci   if (ctx->blend_clear[index])
1489bf215546Sopenharmony_ci      return ctx->blend_clear[index];
1490bf215546Sopenharmony_ci
1491bf215546Sopenharmony_ci   /* Create a new one. */
1492bf215546Sopenharmony_ci   {
1493bf215546Sopenharmony_ci      struct pipe_blend_state blend = {0};
1494bf215546Sopenharmony_ci      unsigned i;
1495bf215546Sopenharmony_ci
1496bf215546Sopenharmony_ci      blend.independent_blend_enable = 1;
1497bf215546Sopenharmony_ci
1498bf215546Sopenharmony_ci      for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
1499bf215546Sopenharmony_ci         if (clear_buffers & (PIPE_CLEAR_COLOR0 << i)) {
1500bf215546Sopenharmony_ci            blend.rt[i].colormask = PIPE_MASK_RGBA;
1501bf215546Sopenharmony_ci            blend.max_rt = i;
1502bf215546Sopenharmony_ci         }
1503bf215546Sopenharmony_ci      }
1504bf215546Sopenharmony_ci
1505bf215546Sopenharmony_ci      ctx->blend_clear[index] = pipe->create_blend_state(pipe, &blend);
1506bf215546Sopenharmony_ci   }
1507bf215546Sopenharmony_ci   return ctx->blend_clear[index];
1508bf215546Sopenharmony_ci}
1509bf215546Sopenharmony_ci
1510bf215546Sopenharmony_civoid util_blitter_common_clear_setup(struct blitter_context *blitter,
1511bf215546Sopenharmony_ci                                     unsigned width, unsigned height,
1512bf215546Sopenharmony_ci                                     unsigned clear_buffers,
1513bf215546Sopenharmony_ci                                     void *custom_blend, void *custom_dsa)
1514bf215546Sopenharmony_ci{
1515bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1516bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
1517bf215546Sopenharmony_ci
1518bf215546Sopenharmony_ci   util_blitter_set_running_flag(blitter);
1519bf215546Sopenharmony_ci   blitter_check_saved_vertex_states(ctx);
1520bf215546Sopenharmony_ci   blitter_check_saved_fragment_states(ctx);
1521bf215546Sopenharmony_ci   blitter_disable_render_cond(ctx);
1522bf215546Sopenharmony_ci
1523bf215546Sopenharmony_ci   /* bind states */
1524bf215546Sopenharmony_ci   if (custom_blend) {
1525bf215546Sopenharmony_ci      pipe->bind_blend_state(pipe, custom_blend);
1526bf215546Sopenharmony_ci   } else {
1527bf215546Sopenharmony_ci      pipe->bind_blend_state(pipe, get_clear_blend_state(ctx, clear_buffers));
1528bf215546Sopenharmony_ci   }
1529bf215546Sopenharmony_ci
1530bf215546Sopenharmony_ci   if (custom_dsa) {
1531bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe, custom_dsa);
1532bf215546Sopenharmony_ci   } else if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
1533bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
1534bf215546Sopenharmony_ci   } else if (clear_buffers & PIPE_CLEAR_DEPTH) {
1535bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
1536bf215546Sopenharmony_ci   } else if (clear_buffers & PIPE_CLEAR_STENCIL) {
1537bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
1538bf215546Sopenharmony_ci   } else {
1539bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
1540bf215546Sopenharmony_ci   }
1541bf215546Sopenharmony_ci
1542bf215546Sopenharmony_ci   pipe->set_sample_mask(pipe, ~0);
1543bf215546Sopenharmony_ci   if (pipe->set_min_samples)
1544bf215546Sopenharmony_ci      pipe->set_min_samples(pipe, 1);
1545bf215546Sopenharmony_ci   blitter_set_dst_dimensions(ctx, width, height);
1546bf215546Sopenharmony_ci}
1547bf215546Sopenharmony_ci
1548bf215546Sopenharmony_cistatic void util_blitter_clear_custom(struct blitter_context *blitter,
1549bf215546Sopenharmony_ci                                      unsigned width, unsigned height,
1550bf215546Sopenharmony_ci                                      unsigned num_layers,
1551bf215546Sopenharmony_ci                                      unsigned clear_buffers,
1552bf215546Sopenharmony_ci                                      const union pipe_color_union *color,
1553bf215546Sopenharmony_ci                                      double depth, unsigned stencil,
1554bf215546Sopenharmony_ci                                      void *custom_blend, void *custom_dsa,
1555bf215546Sopenharmony_ci                                      bool msaa)
1556bf215546Sopenharmony_ci{
1557bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1558bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
1559bf215546Sopenharmony_ci   struct pipe_stencil_ref sr = { { 0 } };
1560bf215546Sopenharmony_ci
1561bf215546Sopenharmony_ci   assert(ctx->has_layered || num_layers <= 1);
1562bf215546Sopenharmony_ci
1563bf215546Sopenharmony_ci   util_blitter_common_clear_setup(blitter, width, height, clear_buffers,
1564bf215546Sopenharmony_ci                                   custom_blend, custom_dsa);
1565bf215546Sopenharmony_ci
1566bf215546Sopenharmony_ci   sr.ref_value[0] = stencil & 0xff;
1567bf215546Sopenharmony_ci   pipe->set_stencil_ref(pipe, sr);
1568bf215546Sopenharmony_ci
1569bf215546Sopenharmony_ci   bool pass_generic = (clear_buffers & PIPE_CLEAR_COLOR) != 0;
1570bf215546Sopenharmony_ci   enum blitter_attrib_type type = UTIL_BLITTER_ATTRIB_NONE;
1571bf215546Sopenharmony_ci
1572bf215546Sopenharmony_ci   if (pass_generic) {
1573bf215546Sopenharmony_ci      struct pipe_constant_buffer cb = {
1574bf215546Sopenharmony_ci         .user_buffer = color->f,
1575bf215546Sopenharmony_ci         .buffer_size = 4 * sizeof(float),
1576bf215546Sopenharmony_ci      };
1577bf215546Sopenharmony_ci      pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, blitter->cb_slot,
1578bf215546Sopenharmony_ci                                false, &cb);
1579bf215546Sopenharmony_ci      bind_fs_clear_all_cbufs(ctx);
1580bf215546Sopenharmony_ci   } else {
1581bf215546Sopenharmony_ci      bind_fs_empty(ctx);
1582bf215546Sopenharmony_ci   }
1583bf215546Sopenharmony_ci
1584bf215546Sopenharmony_ci   if (num_layers > 1 && ctx->has_layered) {
1585bf215546Sopenharmony_ci      blitter_get_vs_func get_vs = get_vs_layered;
1586bf215546Sopenharmony_ci
1587bf215546Sopenharmony_ci      blitter_set_common_draw_rect_state(ctx, false, msaa);
1588bf215546Sopenharmony_ci      blitter->draw_rectangle(blitter, ctx->velem_state, get_vs,
1589bf215546Sopenharmony_ci                              0, 0, width, height,
1590bf215546Sopenharmony_ci                              (float) depth, num_layers, type, NULL);
1591bf215546Sopenharmony_ci   } else {
1592bf215546Sopenharmony_ci      blitter_get_vs_func get_vs;
1593bf215546Sopenharmony_ci
1594bf215546Sopenharmony_ci      if (pass_generic)
1595bf215546Sopenharmony_ci         get_vs = get_vs_passthrough_pos_generic;
1596bf215546Sopenharmony_ci      else
1597bf215546Sopenharmony_ci         get_vs = get_vs_passthrough_pos;
1598bf215546Sopenharmony_ci
1599bf215546Sopenharmony_ci      blitter_set_common_draw_rect_state(ctx, false, msaa);
1600bf215546Sopenharmony_ci      blitter->draw_rectangle(blitter, ctx->velem_state, get_vs,
1601bf215546Sopenharmony_ci                              0, 0, width, height,
1602bf215546Sopenharmony_ci                              (float) depth, 1, type, NULL);
1603bf215546Sopenharmony_ci   }
1604bf215546Sopenharmony_ci
1605bf215546Sopenharmony_ci   util_blitter_restore_vertex_states(blitter);
1606bf215546Sopenharmony_ci   util_blitter_restore_fragment_states(blitter);
1607bf215546Sopenharmony_ci   util_blitter_restore_constant_buffer_state(blitter);
1608bf215546Sopenharmony_ci   util_blitter_restore_render_cond(blitter);
1609bf215546Sopenharmony_ci   util_blitter_unset_running_flag(blitter);
1610bf215546Sopenharmony_ci}
1611bf215546Sopenharmony_ci
1612bf215546Sopenharmony_civoid util_blitter_clear(struct blitter_context *blitter,
1613bf215546Sopenharmony_ci                        unsigned width, unsigned height, unsigned num_layers,
1614bf215546Sopenharmony_ci                        unsigned clear_buffers,
1615bf215546Sopenharmony_ci                        const union pipe_color_union *color,
1616bf215546Sopenharmony_ci                        double depth, unsigned stencil,
1617bf215546Sopenharmony_ci                        bool msaa)
1618bf215546Sopenharmony_ci{
1619bf215546Sopenharmony_ci   util_blitter_clear_custom(blitter, width, height, num_layers,
1620bf215546Sopenharmony_ci                             clear_buffers, color, depth, stencil,
1621bf215546Sopenharmony_ci                             NULL, NULL, msaa);
1622bf215546Sopenharmony_ci}
1623bf215546Sopenharmony_ci
1624bf215546Sopenharmony_civoid util_blitter_custom_clear_depth(struct blitter_context *blitter,
1625bf215546Sopenharmony_ci                                     unsigned width, unsigned height,
1626bf215546Sopenharmony_ci                                     double depth, void *custom_dsa)
1627bf215546Sopenharmony_ci{
1628bf215546Sopenharmony_ci   static const union pipe_color_union color;
1629bf215546Sopenharmony_ci   util_blitter_clear_custom(blitter, width, height, 0, 0, &color, depth, 0,
1630bf215546Sopenharmony_ci                             NULL, custom_dsa, false);
1631bf215546Sopenharmony_ci}
1632bf215546Sopenharmony_ci
1633bf215546Sopenharmony_civoid util_blitter_default_dst_texture(struct pipe_surface *dst_templ,
1634bf215546Sopenharmony_ci                                      struct pipe_resource *dst,
1635bf215546Sopenharmony_ci                                      unsigned dstlevel,
1636bf215546Sopenharmony_ci                                      unsigned dstz)
1637bf215546Sopenharmony_ci{
1638bf215546Sopenharmony_ci   memset(dst_templ, 0, sizeof(*dst_templ));
1639bf215546Sopenharmony_ci   dst_templ->format = util_format_linear(dst->format);
1640bf215546Sopenharmony_ci   dst_templ->u.tex.level = dstlevel;
1641bf215546Sopenharmony_ci   dst_templ->u.tex.first_layer = dstz;
1642bf215546Sopenharmony_ci   dst_templ->u.tex.last_layer = dstz;
1643bf215546Sopenharmony_ci}
1644bf215546Sopenharmony_ci
1645bf215546Sopenharmony_cistatic struct pipe_surface *
1646bf215546Sopenharmony_ciutil_blitter_get_next_surface_layer(struct pipe_context *pipe,
1647bf215546Sopenharmony_ci                                    struct pipe_surface *surf)
1648bf215546Sopenharmony_ci{
1649bf215546Sopenharmony_ci   struct pipe_surface dst_templ;
1650bf215546Sopenharmony_ci
1651bf215546Sopenharmony_ci   memset(&dst_templ, 0, sizeof(dst_templ));
1652bf215546Sopenharmony_ci   dst_templ.format = surf->format;
1653bf215546Sopenharmony_ci   dst_templ.u.tex.level = surf->u.tex.level;
1654bf215546Sopenharmony_ci   dst_templ.u.tex.first_layer = surf->u.tex.first_layer + 1;
1655bf215546Sopenharmony_ci   dst_templ.u.tex.last_layer = surf->u.tex.last_layer + 1;
1656bf215546Sopenharmony_ci
1657bf215546Sopenharmony_ci   return pipe->create_surface(pipe, surf->texture, &dst_templ);
1658bf215546Sopenharmony_ci}
1659bf215546Sopenharmony_ci
1660bf215546Sopenharmony_civoid util_blitter_default_src_texture(struct blitter_context *blitter,
1661bf215546Sopenharmony_ci                                      struct pipe_sampler_view *src_templ,
1662bf215546Sopenharmony_ci                                      struct pipe_resource *src,
1663bf215546Sopenharmony_ci                                      unsigned srclevel)
1664bf215546Sopenharmony_ci{
1665bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1666bf215546Sopenharmony_ci
1667bf215546Sopenharmony_ci   memset(src_templ, 0, sizeof(*src_templ));
1668bf215546Sopenharmony_ci
1669bf215546Sopenharmony_ci   if (ctx->cube_as_2darray &&
1670bf215546Sopenharmony_ci       (src->target == PIPE_TEXTURE_CUBE ||
1671bf215546Sopenharmony_ci        src->target == PIPE_TEXTURE_CUBE_ARRAY))
1672bf215546Sopenharmony_ci      src_templ->target = PIPE_TEXTURE_2D_ARRAY;
1673bf215546Sopenharmony_ci   else
1674bf215546Sopenharmony_ci      src_templ->target = src->target;
1675bf215546Sopenharmony_ci
1676bf215546Sopenharmony_ci   src_templ->format = util_format_linear(src->format);
1677bf215546Sopenharmony_ci   src_templ->u.tex.first_level = srclevel;
1678bf215546Sopenharmony_ci   src_templ->u.tex.last_level = srclevel;
1679bf215546Sopenharmony_ci   src_templ->u.tex.first_layer = 0;
1680bf215546Sopenharmony_ci   src_templ->u.tex.last_layer =
1681bf215546Sopenharmony_ci      src->target == PIPE_TEXTURE_3D ? u_minify(src->depth0, srclevel) - 1
1682bf215546Sopenharmony_ci                                     : (unsigned)(src->array_size - 1);
1683bf215546Sopenharmony_ci   src_templ->swizzle_r = PIPE_SWIZZLE_X;
1684bf215546Sopenharmony_ci   src_templ->swizzle_g = PIPE_SWIZZLE_Y;
1685bf215546Sopenharmony_ci   src_templ->swizzle_b = PIPE_SWIZZLE_Z;
1686bf215546Sopenharmony_ci   src_templ->swizzle_a = PIPE_SWIZZLE_W;
1687bf215546Sopenharmony_ci}
1688bf215546Sopenharmony_ci
1689bf215546Sopenharmony_cistatic bool is_blit_generic_supported(struct blitter_context *blitter,
1690bf215546Sopenharmony_ci                                      const struct pipe_resource *dst,
1691bf215546Sopenharmony_ci                                      enum pipe_format dst_format,
1692bf215546Sopenharmony_ci                                      const struct pipe_resource *src,
1693bf215546Sopenharmony_ci                                      enum pipe_format src_format,
1694bf215546Sopenharmony_ci                                      unsigned mask)
1695bf215546Sopenharmony_ci{
1696bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1697bf215546Sopenharmony_ci   struct pipe_screen *screen = ctx->base.pipe->screen;
1698bf215546Sopenharmony_ci
1699bf215546Sopenharmony_ci   if (dst) {
1700bf215546Sopenharmony_ci      unsigned bind;
1701bf215546Sopenharmony_ci      const struct util_format_description *desc =
1702bf215546Sopenharmony_ci            util_format_description(dst_format);
1703bf215546Sopenharmony_ci      bool dst_has_stencil = util_format_has_stencil(desc);
1704bf215546Sopenharmony_ci
1705bf215546Sopenharmony_ci      /* Stencil export must be supported for stencil copy. */
1706bf215546Sopenharmony_ci      if ((mask & PIPE_MASK_S) && dst_has_stencil &&
1707bf215546Sopenharmony_ci          !ctx->has_stencil_export) {
1708bf215546Sopenharmony_ci         return false;
1709bf215546Sopenharmony_ci      }
1710bf215546Sopenharmony_ci
1711bf215546Sopenharmony_ci      if (dst_has_stencil || util_format_has_depth(desc))
1712bf215546Sopenharmony_ci         bind = PIPE_BIND_DEPTH_STENCIL;
1713bf215546Sopenharmony_ci      else
1714bf215546Sopenharmony_ci         bind = PIPE_BIND_RENDER_TARGET;
1715bf215546Sopenharmony_ci
1716bf215546Sopenharmony_ci      if (!screen->is_format_supported(screen, dst_format, dst->target,
1717bf215546Sopenharmony_ci                                       dst->nr_samples, dst->nr_storage_samples,
1718bf215546Sopenharmony_ci                                       bind)) {
1719bf215546Sopenharmony_ci         return false;
1720bf215546Sopenharmony_ci      }
1721bf215546Sopenharmony_ci   }
1722bf215546Sopenharmony_ci
1723bf215546Sopenharmony_ci   if (src) {
1724bf215546Sopenharmony_ci      if (src->nr_samples > 1 && !ctx->has_texture_multisample) {
1725bf215546Sopenharmony_ci         return false;
1726bf215546Sopenharmony_ci      }
1727bf215546Sopenharmony_ci
1728bf215546Sopenharmony_ci      if (!screen->is_format_supported(screen, src_format, src->target,
1729bf215546Sopenharmony_ci                                       src->nr_samples, src->nr_storage_samples,
1730bf215546Sopenharmony_ci                                       PIPE_BIND_SAMPLER_VIEW)) {
1731bf215546Sopenharmony_ci         return false;
1732bf215546Sopenharmony_ci      }
1733bf215546Sopenharmony_ci
1734bf215546Sopenharmony_ci      /* Check stencil sampler support for stencil copy. */
1735bf215546Sopenharmony_ci      if (mask & PIPE_MASK_S) {
1736bf215546Sopenharmony_ci         if (util_format_has_stencil(util_format_description(src_format))) {
1737bf215546Sopenharmony_ci            enum pipe_format stencil_format =
1738bf215546Sopenharmony_ci               util_format_stencil_only(src_format);
1739bf215546Sopenharmony_ci            assert(stencil_format != PIPE_FORMAT_NONE);
1740bf215546Sopenharmony_ci
1741bf215546Sopenharmony_ci            if (stencil_format != src_format &&
1742bf215546Sopenharmony_ci                !screen->is_format_supported(screen, stencil_format,
1743bf215546Sopenharmony_ci                                             src->target, src->nr_samples,
1744bf215546Sopenharmony_ci                                             src->nr_storage_samples,
1745bf215546Sopenharmony_ci                                             PIPE_BIND_SAMPLER_VIEW)) {
1746bf215546Sopenharmony_ci               return false;
1747bf215546Sopenharmony_ci            }
1748bf215546Sopenharmony_ci         }
1749bf215546Sopenharmony_ci      }
1750bf215546Sopenharmony_ci   }
1751bf215546Sopenharmony_ci
1752bf215546Sopenharmony_ci   return true;
1753bf215546Sopenharmony_ci}
1754bf215546Sopenharmony_ci
1755bf215546Sopenharmony_cibool util_blitter_is_copy_supported(struct blitter_context *blitter,
1756bf215546Sopenharmony_ci                                    const struct pipe_resource *dst,
1757bf215546Sopenharmony_ci                                    const struct pipe_resource *src)
1758bf215546Sopenharmony_ci{
1759bf215546Sopenharmony_ci   return is_blit_generic_supported(blitter, dst, dst->format,
1760bf215546Sopenharmony_ci                                    src, src->format, PIPE_MASK_RGBAZS);
1761bf215546Sopenharmony_ci}
1762bf215546Sopenharmony_ci
1763bf215546Sopenharmony_cibool util_blitter_is_blit_supported(struct blitter_context *blitter,
1764bf215546Sopenharmony_ci                                    const struct pipe_blit_info *info)
1765bf215546Sopenharmony_ci{
1766bf215546Sopenharmony_ci   return is_blit_generic_supported(blitter,
1767bf215546Sopenharmony_ci                                    info->dst.resource, info->dst.format,
1768bf215546Sopenharmony_ci                                    info->src.resource, info->src.format,
1769bf215546Sopenharmony_ci                                    info->mask);
1770bf215546Sopenharmony_ci}
1771bf215546Sopenharmony_ci
1772bf215546Sopenharmony_civoid util_blitter_copy_texture(struct blitter_context *blitter,
1773bf215546Sopenharmony_ci                               struct pipe_resource *dst,
1774bf215546Sopenharmony_ci                               unsigned dst_level,
1775bf215546Sopenharmony_ci                               unsigned dstx, unsigned dsty, unsigned dstz,
1776bf215546Sopenharmony_ci                               struct pipe_resource *src,
1777bf215546Sopenharmony_ci                               unsigned src_level,
1778bf215546Sopenharmony_ci                               const struct pipe_box *srcbox)
1779bf215546Sopenharmony_ci{
1780bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1781bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
1782bf215546Sopenharmony_ci   struct pipe_surface *dst_view, dst_templ;
1783bf215546Sopenharmony_ci   struct pipe_sampler_view src_templ, *src_view;
1784bf215546Sopenharmony_ci   struct pipe_box dstbox;
1785bf215546Sopenharmony_ci
1786bf215546Sopenharmony_ci   assert(dst && src);
1787bf215546Sopenharmony_ci   assert(src->target < PIPE_MAX_TEXTURE_TYPES);
1788bf215546Sopenharmony_ci
1789bf215546Sopenharmony_ci   u_box_3d(dstx, dsty, dstz, abs(srcbox->width), abs(srcbox->height),
1790bf215546Sopenharmony_ci            abs(srcbox->depth), &dstbox);
1791bf215546Sopenharmony_ci
1792bf215546Sopenharmony_ci   /* Initialize the surface. */
1793bf215546Sopenharmony_ci   util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz);
1794bf215546Sopenharmony_ci   dst_view = pipe->create_surface(pipe, dst, &dst_templ);
1795bf215546Sopenharmony_ci
1796bf215546Sopenharmony_ci   /* Initialize the sampler view. */
1797bf215546Sopenharmony_ci   util_blitter_default_src_texture(blitter, &src_templ, src, src_level);
1798bf215546Sopenharmony_ci   src_view = pipe->create_sampler_view(pipe, src, &src_templ);
1799bf215546Sopenharmony_ci
1800bf215546Sopenharmony_ci   /* Copy. */
1801bf215546Sopenharmony_ci   util_blitter_blit_generic(blitter, dst_view, &dstbox,
1802bf215546Sopenharmony_ci                             src_view, srcbox, src->width0, src->height0,
1803bf215546Sopenharmony_ci                             PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL,
1804bf215546Sopenharmony_ci                             false, false, 0);
1805bf215546Sopenharmony_ci
1806bf215546Sopenharmony_ci   pipe_surface_reference(&dst_view, NULL);
1807bf215546Sopenharmony_ci   pipe_sampler_view_reference(&src_view, NULL);
1808bf215546Sopenharmony_ci}
1809bf215546Sopenharmony_ci
1810bf215546Sopenharmony_cistatic void
1811bf215546Sopenharmony_ciblitter_draw_tex(struct blitter_context_priv *ctx,
1812bf215546Sopenharmony_ci                 int dst_x1, int dst_y1, int dst_x2, int dst_y2,
1813bf215546Sopenharmony_ci                 struct pipe_sampler_view *src,
1814bf215546Sopenharmony_ci                 unsigned src_width0, unsigned src_height0,
1815bf215546Sopenharmony_ci                 int src_x1, int src_y1, int src_x2, int src_y2,
1816bf215546Sopenharmony_ci                 float layer, unsigned sample,
1817bf215546Sopenharmony_ci                 bool uses_txf, enum blitter_attrib_type type)
1818bf215546Sopenharmony_ci{
1819bf215546Sopenharmony_ci   union blitter_attrib coord;
1820bf215546Sopenharmony_ci   blitter_get_vs_func get_vs = get_vs_passthrough_pos_generic;
1821bf215546Sopenharmony_ci
1822bf215546Sopenharmony_ci   get_texcoords(src, src_width0, src_height0,
1823bf215546Sopenharmony_ci                 src_x1, src_y1, src_x2, src_y2, layer, sample,
1824bf215546Sopenharmony_ci                 uses_txf, &coord);
1825bf215546Sopenharmony_ci
1826bf215546Sopenharmony_ci   if (src->target == PIPE_TEXTURE_CUBE ||
1827bf215546Sopenharmony_ci       src->target == PIPE_TEXTURE_CUBE_ARRAY) {
1828bf215546Sopenharmony_ci      float face_coord[4][2];
1829bf215546Sopenharmony_ci
1830bf215546Sopenharmony_ci      set_texcoords_in_vertices(&coord, &face_coord[0][0], 2);
1831bf215546Sopenharmony_ci      util_map_texcoords2d_onto_cubemap((unsigned)layer % 6,
1832bf215546Sopenharmony_ci                                        /* pointer, stride in floats */
1833bf215546Sopenharmony_ci                                        &face_coord[0][0], 2,
1834bf215546Sopenharmony_ci                                        &ctx->vertices[0][1][0], 8,
1835bf215546Sopenharmony_ci                                        false);
1836bf215546Sopenharmony_ci      for (unsigned i = 0; i < 4; i++)
1837bf215546Sopenharmony_ci         ctx->vertices[i][1][3] = coord.texcoord.w;
1838bf215546Sopenharmony_ci
1839bf215546Sopenharmony_ci      /* Cubemaps don't use draw_rectangle. */
1840bf215546Sopenharmony_ci      blitter_draw(ctx, ctx->velem_state, get_vs,
1841bf215546Sopenharmony_ci                   dst_x1, dst_y1, dst_x2, dst_y2, 0, 1);
1842bf215546Sopenharmony_ci   } else {
1843bf215546Sopenharmony_ci      ctx->base.draw_rectangle(&ctx->base, ctx->velem_state, get_vs,
1844bf215546Sopenharmony_ci                               dst_x1, dst_y1, dst_x2, dst_y2,
1845bf215546Sopenharmony_ci                               0, 1, type, &coord);
1846bf215546Sopenharmony_ci   }
1847bf215546Sopenharmony_ci}
1848bf215546Sopenharmony_ci
1849bf215546Sopenharmony_cistatic void do_blits(struct blitter_context_priv *ctx,
1850bf215546Sopenharmony_ci                     struct pipe_surface *dst,
1851bf215546Sopenharmony_ci                     const struct pipe_box *dstbox,
1852bf215546Sopenharmony_ci                     struct pipe_sampler_view *src,
1853bf215546Sopenharmony_ci                     unsigned src_width0,
1854bf215546Sopenharmony_ci                     unsigned src_height0,
1855bf215546Sopenharmony_ci                     const struct pipe_box *srcbox,
1856bf215546Sopenharmony_ci                     bool is_zsbuf,
1857bf215546Sopenharmony_ci                     bool uses_txf, bool sample0_only,
1858bf215546Sopenharmony_ci                     unsigned dst_sample)
1859bf215546Sopenharmony_ci{
1860bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
1861bf215546Sopenharmony_ci   unsigned src_samples = src->texture->nr_samples;
1862bf215546Sopenharmony_ci   unsigned dst_samples = dst->texture->nr_samples;
1863bf215546Sopenharmony_ci   bool sample_shading = ctx->has_sample_shading && src_samples > 1 &&
1864bf215546Sopenharmony_ci                         src_samples == dst_samples && !sample0_only;
1865bf215546Sopenharmony_ci   enum pipe_texture_target src_target = src->target;
1866bf215546Sopenharmony_ci   struct pipe_framebuffer_state fb_state = {0};
1867bf215546Sopenharmony_ci
1868bf215546Sopenharmony_ci   /* Initialize framebuffer state. */
1869bf215546Sopenharmony_ci   fb_state.width = dst->width;
1870bf215546Sopenharmony_ci   fb_state.height = dst->height;
1871bf215546Sopenharmony_ci   fb_state.nr_cbufs = is_zsbuf ? 0 : 1;
1872bf215546Sopenharmony_ci
1873bf215546Sopenharmony_ci   blitter_set_dst_dimensions(ctx, fb_state.width, fb_state.height);
1874bf215546Sopenharmony_ci
1875bf215546Sopenharmony_ci   if ((src_target == PIPE_TEXTURE_1D ||
1876bf215546Sopenharmony_ci        src_target == PIPE_TEXTURE_2D ||
1877bf215546Sopenharmony_ci        src_target == PIPE_TEXTURE_RECT) &&
1878bf215546Sopenharmony_ci       (src_samples <= 1 || sample_shading)) {
1879bf215546Sopenharmony_ci      /* Set framebuffer state. */
1880bf215546Sopenharmony_ci      if (is_zsbuf) {
1881bf215546Sopenharmony_ci         fb_state.zsbuf = dst;
1882bf215546Sopenharmony_ci      } else {
1883bf215546Sopenharmony_ci         fb_state.cbufs[0] = dst;
1884bf215546Sopenharmony_ci      }
1885bf215546Sopenharmony_ci      pipe->set_framebuffer_state(pipe, &fb_state);
1886bf215546Sopenharmony_ci
1887bf215546Sopenharmony_ci      /* Draw. */
1888bf215546Sopenharmony_ci      pipe->set_sample_mask(pipe, dst_sample ? BITFIELD_BIT(dst_sample - 1) : ~0);
1889bf215546Sopenharmony_ci      if (pipe->set_min_samples)
1890bf215546Sopenharmony_ci         pipe->set_min_samples(pipe, sample_shading ? dst_samples : 1);
1891bf215546Sopenharmony_ci      blitter_draw_tex(ctx, dstbox->x, dstbox->y,
1892bf215546Sopenharmony_ci                       dstbox->x + dstbox->width,
1893bf215546Sopenharmony_ci                       dstbox->y + dstbox->height,
1894bf215546Sopenharmony_ci                       src, src_width0, src_height0, srcbox->x, srcbox->y,
1895bf215546Sopenharmony_ci                       srcbox->x + srcbox->width, srcbox->y + srcbox->height,
1896bf215546Sopenharmony_ci                       0, 0, uses_txf, UTIL_BLITTER_ATTRIB_TEXCOORD_XY);
1897bf215546Sopenharmony_ci   } else {
1898bf215546Sopenharmony_ci      /* Draw the quad with the generic codepath. */
1899bf215546Sopenharmony_ci      int dst_z;
1900bf215546Sopenharmony_ci      for (dst_z = 0; dst_z < dstbox->depth; dst_z++) {
1901bf215546Sopenharmony_ci         struct pipe_surface *old;
1902bf215546Sopenharmony_ci         bool flipped = (srcbox->depth < 0);
1903bf215546Sopenharmony_ci         float depth_center_offset = 0.0;
1904bf215546Sopenharmony_ci         int src_depth = abs(srcbox->depth);
1905bf215546Sopenharmony_ci         float src_z_step = src_depth / (float)dstbox->depth;
1906bf215546Sopenharmony_ci
1907bf215546Sopenharmony_ci         /* Scale Z properly if the blit is scaled.
1908bf215546Sopenharmony_ci          *
1909bf215546Sopenharmony_ci          * When downscaling, we want the coordinates centered, so that
1910bf215546Sopenharmony_ci          * mipmapping works for 3D textures. For example, when generating
1911bf215546Sopenharmony_ci          * a 4x4x4 level, this wouldn't average the pixels:
1912bf215546Sopenharmony_ci          *
1913bf215546Sopenharmony_ci          *   src Z:  0 1 2 3 4 5 6 7
1914bf215546Sopenharmony_ci          *   dst Z:  0   1   2   3
1915bf215546Sopenharmony_ci          *
1916bf215546Sopenharmony_ci          * Because the pixels are not centered below the pixels of the higher
1917bf215546Sopenharmony_ci          * level. Therefore, we want this:
1918bf215546Sopenharmony_ci          *   src Z:  0 1 2 3 4 5 6 7
1919bf215546Sopenharmony_ci          *   dst Z:   0   1   2   3
1920bf215546Sopenharmony_ci          *
1921bf215546Sopenharmony_ci          * This calculation is taken from the radv driver.
1922bf215546Sopenharmony_ci          */
1923bf215546Sopenharmony_ci         if (src_target == PIPE_TEXTURE_3D)
1924bf215546Sopenharmony_ci            depth_center_offset = 0.5 / dstbox->depth * src_depth;
1925bf215546Sopenharmony_ci
1926bf215546Sopenharmony_ci         if (flipped) {
1927bf215546Sopenharmony_ci            src_z_step *= - 1;
1928bf215546Sopenharmony_ci            depth_center_offset *= -1;
1929bf215546Sopenharmony_ci         }
1930bf215546Sopenharmony_ci
1931bf215546Sopenharmony_ci         float src_z = dst_z * src_z_step + depth_center_offset;
1932bf215546Sopenharmony_ci
1933bf215546Sopenharmony_ci         /* Set framebuffer state. */
1934bf215546Sopenharmony_ci         if (is_zsbuf) {
1935bf215546Sopenharmony_ci            fb_state.zsbuf = dst;
1936bf215546Sopenharmony_ci         } else {
1937bf215546Sopenharmony_ci            fb_state.cbufs[0] = dst;
1938bf215546Sopenharmony_ci         }
1939bf215546Sopenharmony_ci         pipe->set_framebuffer_state(pipe, &fb_state);
1940bf215546Sopenharmony_ci
1941bf215546Sopenharmony_ci         /* See if we need to blit a multisample or singlesample buffer. */
1942bf215546Sopenharmony_ci         if (sample0_only || (src_samples == dst_samples && dst_samples > 1)) {
1943bf215546Sopenharmony_ci            /* MSAA copy. */
1944bf215546Sopenharmony_ci            unsigned i, max_sample = sample0_only ? 0 : dst_samples - 1;
1945bf215546Sopenharmony_ci
1946bf215546Sopenharmony_ci            if (sample_shading) {
1947bf215546Sopenharmony_ci               assert(dst_sample == 0);
1948bf215546Sopenharmony_ci               pipe->set_sample_mask(pipe, ~0);
1949bf215546Sopenharmony_ci               if (pipe->set_min_samples)
1950bf215546Sopenharmony_ci                  pipe->set_min_samples(pipe, max_sample);
1951bf215546Sopenharmony_ci               blitter_draw_tex(ctx, dstbox->x, dstbox->y,
1952bf215546Sopenharmony_ci                                dstbox->x + dstbox->width,
1953bf215546Sopenharmony_ci                                dstbox->y + dstbox->height,
1954bf215546Sopenharmony_ci                                src, src_width0, src_height0,
1955bf215546Sopenharmony_ci                                srcbox->x, srcbox->y,
1956bf215546Sopenharmony_ci                                srcbox->x + srcbox->width,
1957bf215546Sopenharmony_ci                                srcbox->y + srcbox->height,
1958bf215546Sopenharmony_ci                                srcbox->z + src_z, 0, uses_txf,
1959bf215546Sopenharmony_ci                                UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW);
1960bf215546Sopenharmony_ci            } else {
1961bf215546Sopenharmony_ci               if (pipe->set_min_samples)
1962bf215546Sopenharmony_ci                  pipe->set_min_samples(pipe, 1);
1963bf215546Sopenharmony_ci
1964bf215546Sopenharmony_ci               for (i = 0; i <= max_sample; i++) {
1965bf215546Sopenharmony_ci                  pipe->set_sample_mask(pipe, 1 << i);
1966bf215546Sopenharmony_ci                  blitter_draw_tex(ctx, dstbox->x, dstbox->y,
1967bf215546Sopenharmony_ci                                   dstbox->x + dstbox->width,
1968bf215546Sopenharmony_ci                                   dstbox->y + dstbox->height,
1969bf215546Sopenharmony_ci                                   src, src_width0, src_height0,
1970bf215546Sopenharmony_ci                                   srcbox->x, srcbox->y,
1971bf215546Sopenharmony_ci                                   srcbox->x + srcbox->width,
1972bf215546Sopenharmony_ci                                   srcbox->y + srcbox->height,
1973bf215546Sopenharmony_ci                                   srcbox->z + src_z, i, uses_txf,
1974bf215546Sopenharmony_ci                                   UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW);
1975bf215546Sopenharmony_ci               }
1976bf215546Sopenharmony_ci            }
1977bf215546Sopenharmony_ci         } else {
1978bf215546Sopenharmony_ci            /* Normal copy, MSAA upsampling, or MSAA resolve. */
1979bf215546Sopenharmony_ci            pipe->set_sample_mask(pipe, dst_sample ? BITFIELD_BIT(dst_sample - 1) : ~0);
1980bf215546Sopenharmony_ci            if (pipe->set_min_samples)
1981bf215546Sopenharmony_ci               pipe->set_min_samples(pipe, 1);
1982bf215546Sopenharmony_ci            blitter_draw_tex(ctx, dstbox->x, dstbox->y,
1983bf215546Sopenharmony_ci                             dstbox->x + dstbox->width,
1984bf215546Sopenharmony_ci                             dstbox->y + dstbox->height,
1985bf215546Sopenharmony_ci                             src, src_width0, src_height0,
1986bf215546Sopenharmony_ci                             srcbox->x, srcbox->y,
1987bf215546Sopenharmony_ci                             srcbox->x + srcbox->width,
1988bf215546Sopenharmony_ci                             srcbox->y + srcbox->height,
1989bf215546Sopenharmony_ci                             srcbox->z + src_z, 0, uses_txf,
1990bf215546Sopenharmony_ci                             UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW);
1991bf215546Sopenharmony_ci         }
1992bf215546Sopenharmony_ci
1993bf215546Sopenharmony_ci         /* Get the next surface or (if this is the last iteration)
1994bf215546Sopenharmony_ci          * just unreference the last one. */
1995bf215546Sopenharmony_ci         old = dst;
1996bf215546Sopenharmony_ci         if (dst_z < dstbox->depth-1) {
1997bf215546Sopenharmony_ci            dst = util_blitter_get_next_surface_layer(ctx->base.pipe, dst);
1998bf215546Sopenharmony_ci         }
1999bf215546Sopenharmony_ci         if (dst_z) {
2000bf215546Sopenharmony_ci            pipe_surface_reference(&old, NULL);
2001bf215546Sopenharmony_ci         }
2002bf215546Sopenharmony_ci      }
2003bf215546Sopenharmony_ci   }
2004bf215546Sopenharmony_ci}
2005bf215546Sopenharmony_ci
2006bf215546Sopenharmony_civoid util_blitter_blit_generic(struct blitter_context *blitter,
2007bf215546Sopenharmony_ci                               struct pipe_surface *dst,
2008bf215546Sopenharmony_ci                               const struct pipe_box *dstbox,
2009bf215546Sopenharmony_ci                               struct pipe_sampler_view *src,
2010bf215546Sopenharmony_ci                               const struct pipe_box *srcbox,
2011bf215546Sopenharmony_ci                               unsigned src_width0, unsigned src_height0,
2012bf215546Sopenharmony_ci                               unsigned mask, unsigned filter,
2013bf215546Sopenharmony_ci                               const struct pipe_scissor_state *scissor,
2014bf215546Sopenharmony_ci                               bool alpha_blend, bool sample0_only,
2015bf215546Sopenharmony_ci                               unsigned dst_sample)
2016bf215546Sopenharmony_ci{
2017bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
2018bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
2019bf215546Sopenharmony_ci   enum pipe_texture_target src_target = src->target;
2020bf215546Sopenharmony_ci   unsigned src_samples = src->texture->nr_samples;
2021bf215546Sopenharmony_ci   unsigned dst_samples = dst->texture->nr_samples;
2022bf215546Sopenharmony_ci   void *sampler_state;
2023bf215546Sopenharmony_ci   const struct util_format_description *src_desc =
2024bf215546Sopenharmony_ci         util_format_description(src->format);
2025bf215546Sopenharmony_ci   const struct util_format_description *dst_desc =
2026bf215546Sopenharmony_ci         util_format_description(dst->format);
2027bf215546Sopenharmony_ci
2028bf215546Sopenharmony_ci   bool src_has_color = src_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS;
2029bf215546Sopenharmony_ci   bool src_has_depth = util_format_has_depth(src_desc);
2030bf215546Sopenharmony_ci   bool src_has_stencil = util_format_has_stencil(src_desc);
2031bf215546Sopenharmony_ci
2032bf215546Sopenharmony_ci   bool dst_has_color = mask & PIPE_MASK_RGBA &&
2033bf215546Sopenharmony_ci                        dst_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS;
2034bf215546Sopenharmony_ci   bool dst_has_depth = mask & PIPE_MASK_Z &&
2035bf215546Sopenharmony_ci                        util_format_has_depth(dst_desc);
2036bf215546Sopenharmony_ci   bool dst_has_stencil = ctx->has_stencil_export &&
2037bf215546Sopenharmony_ci                          mask & PIPE_MASK_S &&
2038bf215546Sopenharmony_ci                          util_format_has_stencil(dst_desc);
2039bf215546Sopenharmony_ci
2040bf215546Sopenharmony_ci   /* Return if there is nothing to do. */
2041bf215546Sopenharmony_ci   if (!dst_has_color && !dst_has_depth && !dst_has_stencil) {
2042bf215546Sopenharmony_ci      return;
2043bf215546Sopenharmony_ci   }
2044bf215546Sopenharmony_ci
2045bf215546Sopenharmony_ci   bool is_scaled = dstbox->width != abs(srcbox->width) ||
2046bf215546Sopenharmony_ci                    dstbox->height != abs(srcbox->height);
2047bf215546Sopenharmony_ci
2048bf215546Sopenharmony_ci   if (src_has_stencil || !is_scaled)
2049bf215546Sopenharmony_ci      filter = PIPE_TEX_FILTER_NEAREST;
2050bf215546Sopenharmony_ci
2051bf215546Sopenharmony_ci   bool use_txf = false;
2052bf215546Sopenharmony_ci
2053bf215546Sopenharmony_ci   /* Don't support scaled blits. The TXF shader uses F2I for rounding. */
2054bf215546Sopenharmony_ci   if (ctx->has_txf &&
2055bf215546Sopenharmony_ci       !is_scaled &&
2056bf215546Sopenharmony_ci       filter == PIPE_TEX_FILTER_NEAREST &&
2057bf215546Sopenharmony_ci       src->target != PIPE_TEXTURE_CUBE &&
2058bf215546Sopenharmony_ci       src->target != PIPE_TEXTURE_CUBE_ARRAY) {
2059bf215546Sopenharmony_ci      int src_width = u_minify(src_width0, src->u.tex.first_level);
2060bf215546Sopenharmony_ci      int src_height = u_minify(src_height0, src->u.tex.first_level);
2061bf215546Sopenharmony_ci      int src_depth = src->u.tex.last_layer + 1;
2062bf215546Sopenharmony_ci      struct pipe_box box = *srcbox;
2063bf215546Sopenharmony_ci
2064bf215546Sopenharmony_ci      /* Eliminate negative width/height/depth. */
2065bf215546Sopenharmony_ci      if (box.width < 0) {
2066bf215546Sopenharmony_ci         box.x += box.width;
2067bf215546Sopenharmony_ci         box.width *= -1;
2068bf215546Sopenharmony_ci      }
2069bf215546Sopenharmony_ci      if (box.height < 0) {
2070bf215546Sopenharmony_ci         box.y += box.height;
2071bf215546Sopenharmony_ci         box.height *= -1;
2072bf215546Sopenharmony_ci      }
2073bf215546Sopenharmony_ci      if (box.depth < 0) {
2074bf215546Sopenharmony_ci         box.z += box.depth;
2075bf215546Sopenharmony_ci         box.depth *= -1;
2076bf215546Sopenharmony_ci      }
2077bf215546Sopenharmony_ci
2078bf215546Sopenharmony_ci      /* See if srcbox is in bounds. TXF doesn't clamp the coordinates. */
2079bf215546Sopenharmony_ci      use_txf =
2080bf215546Sopenharmony_ci         box.x >= 0 && box.x < src_width &&
2081bf215546Sopenharmony_ci         box.y >= 0 && box.y < src_height &&
2082bf215546Sopenharmony_ci         box.z >= 0 && box.z < src_depth &&
2083bf215546Sopenharmony_ci         box.x + box.width > 0 && box.x + box.width <= src_width &&
2084bf215546Sopenharmony_ci         box.y + box.height > 0 && box.y + box.height <= src_height &&
2085bf215546Sopenharmony_ci         box.z + box.depth > 0 && box.z + box.depth <= src_depth;
2086bf215546Sopenharmony_ci   }
2087bf215546Sopenharmony_ci
2088bf215546Sopenharmony_ci   /* Check whether the states are properly saved. */
2089bf215546Sopenharmony_ci   util_blitter_set_running_flag(blitter);
2090bf215546Sopenharmony_ci   blitter_check_saved_vertex_states(ctx);
2091bf215546Sopenharmony_ci   blitter_check_saved_fragment_states(ctx);
2092bf215546Sopenharmony_ci   blitter_check_saved_textures(ctx);
2093bf215546Sopenharmony_ci   blitter_check_saved_fb_state(ctx);
2094bf215546Sopenharmony_ci   blitter_disable_render_cond(ctx);
2095bf215546Sopenharmony_ci
2096bf215546Sopenharmony_ci   /* Blend, DSA, fragment shader. */
2097bf215546Sopenharmony_ci   if (dst_has_depth && dst_has_stencil) {
2098bf215546Sopenharmony_ci      pipe->bind_blend_state(pipe, ctx->blend[0][0]);
2099bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe,
2100bf215546Sopenharmony_ci                                           ctx->dsa_write_depth_stencil);
2101bf215546Sopenharmony_ci      if (src_has_color) {
2102bf215546Sopenharmony_ci         assert(use_txf);
2103bf215546Sopenharmony_ci         ctx->bind_fs_state(pipe,
2104bf215546Sopenharmony_ci            blitter_get_fs_pack_color_zs(ctx, src_target,
2105bf215546Sopenharmony_ci                                         src_samples, dst->format, false));
2106bf215546Sopenharmony_ci      } else {
2107bf215546Sopenharmony_ci         ctx->bind_fs_state(pipe,
2108bf215546Sopenharmony_ci            blitter_get_fs_texfetch_depthstencil(ctx, src_target, src_samples,
2109bf215546Sopenharmony_ci                                                 dst_samples, use_txf));
2110bf215546Sopenharmony_ci      }
2111bf215546Sopenharmony_ci   } else if (dst_has_depth) {
2112bf215546Sopenharmony_ci      pipe->bind_blend_state(pipe, ctx->blend[0][0]);
2113bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe,
2114bf215546Sopenharmony_ci                                           ctx->dsa_write_depth_keep_stencil);
2115bf215546Sopenharmony_ci      if (src_has_color &&
2116bf215546Sopenharmony_ci          (src->format == PIPE_FORMAT_R32_UINT ||
2117bf215546Sopenharmony_ci           src->format == PIPE_FORMAT_R32G32_UINT)) {
2118bf215546Sopenharmony_ci         assert(use_txf);
2119bf215546Sopenharmony_ci         ctx->bind_fs_state(pipe,
2120bf215546Sopenharmony_ci            blitter_get_fs_pack_color_zs(ctx, src_target,
2121bf215546Sopenharmony_ci                                         src_samples, dst->format, false));
2122bf215546Sopenharmony_ci      } else {
2123bf215546Sopenharmony_ci         ctx->bind_fs_state(pipe,
2124bf215546Sopenharmony_ci            blitter_get_fs_texfetch_depth(ctx, src_target, src_samples,
2125bf215546Sopenharmony_ci                                          dst_samples, use_txf));
2126bf215546Sopenharmony_ci      }
2127bf215546Sopenharmony_ci   } else if (dst_has_stencil) {
2128bf215546Sopenharmony_ci      pipe->bind_blend_state(pipe, ctx->blend[0][0]);
2129bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe,
2130bf215546Sopenharmony_ci                                           ctx->dsa_keep_depth_write_stencil);
2131bf215546Sopenharmony_ci
2132bf215546Sopenharmony_ci      assert(src_has_stencil); /* unpacking from color is unsupported */
2133bf215546Sopenharmony_ci      ctx->bind_fs_state(pipe,
2134bf215546Sopenharmony_ci         blitter_get_fs_texfetch_stencil(ctx, src_target, src_samples,
2135bf215546Sopenharmony_ci                                         dst_samples, use_txf));
2136bf215546Sopenharmony_ci   } else {
2137bf215546Sopenharmony_ci      unsigned colormask = mask & PIPE_MASK_RGBA;
2138bf215546Sopenharmony_ci
2139bf215546Sopenharmony_ci      pipe->bind_blend_state(pipe, ctx->blend[colormask][alpha_blend]);
2140bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
2141bf215546Sopenharmony_ci
2142bf215546Sopenharmony_ci      if (src_has_depth &&
2143bf215546Sopenharmony_ci          (dst->format == PIPE_FORMAT_R32_UINT ||
2144bf215546Sopenharmony_ci           dst->format == PIPE_FORMAT_R32G32_UINT)) {
2145bf215546Sopenharmony_ci         assert(use_txf);
2146bf215546Sopenharmony_ci         ctx->bind_fs_state(pipe,
2147bf215546Sopenharmony_ci            blitter_get_fs_pack_color_zs(ctx, src_target,
2148bf215546Sopenharmony_ci                                         src_samples, src->format, true));
2149bf215546Sopenharmony_ci      } else {
2150bf215546Sopenharmony_ci         ctx->bind_fs_state(pipe,
2151bf215546Sopenharmony_ci            blitter_get_fs_texfetch_col(ctx, src->format, dst->format, src_target,
2152bf215546Sopenharmony_ci                                        src_samples, dst_samples, filter,
2153bf215546Sopenharmony_ci                                        use_txf));
2154bf215546Sopenharmony_ci      }
2155bf215546Sopenharmony_ci   }
2156bf215546Sopenharmony_ci
2157bf215546Sopenharmony_ci   /* Set the linear filter only for scaled color non-MSAA blits. */
2158bf215546Sopenharmony_ci   if (filter == PIPE_TEX_FILTER_LINEAR) {
2159bf215546Sopenharmony_ci      if (src_target == PIPE_TEXTURE_RECT && ctx->has_texrect) {
2160bf215546Sopenharmony_ci         sampler_state = ctx->sampler_state_rect_linear;
2161bf215546Sopenharmony_ci      } else {
2162bf215546Sopenharmony_ci         sampler_state = ctx->sampler_state_linear;
2163bf215546Sopenharmony_ci      }
2164bf215546Sopenharmony_ci   } else {
2165bf215546Sopenharmony_ci      if (src_target == PIPE_TEXTURE_RECT && ctx->has_texrect) {
2166bf215546Sopenharmony_ci         sampler_state = ctx->sampler_state_rect;
2167bf215546Sopenharmony_ci      } else {
2168bf215546Sopenharmony_ci         sampler_state = ctx->sampler_state;
2169bf215546Sopenharmony_ci      }
2170bf215546Sopenharmony_ci   }
2171bf215546Sopenharmony_ci
2172bf215546Sopenharmony_ci   /* Set samplers. */
2173bf215546Sopenharmony_ci   unsigned count = 0;
2174bf215546Sopenharmony_ci   if (src_has_depth && src_has_stencil &&
2175bf215546Sopenharmony_ci       (dst_has_color || (dst_has_depth && dst_has_stencil))) {
2176bf215546Sopenharmony_ci      /* Setup two samplers, one for depth and the other one for stencil. */
2177bf215546Sopenharmony_ci      struct pipe_sampler_view templ;
2178bf215546Sopenharmony_ci      struct pipe_sampler_view *views[2];
2179bf215546Sopenharmony_ci      void *samplers[2] = {sampler_state, sampler_state};
2180bf215546Sopenharmony_ci
2181bf215546Sopenharmony_ci      templ = *src;
2182bf215546Sopenharmony_ci      templ.format = util_format_stencil_only(templ.format);
2183bf215546Sopenharmony_ci      assert(templ.format != PIPE_FORMAT_NONE);
2184bf215546Sopenharmony_ci
2185bf215546Sopenharmony_ci      views[0] = src;
2186bf215546Sopenharmony_ci      views[1] = pipe->create_sampler_view(pipe, src->texture, &templ);
2187bf215546Sopenharmony_ci
2188bf215546Sopenharmony_ci      count = 2;
2189bf215546Sopenharmony_ci      pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 2, 0, false, views);
2190bf215546Sopenharmony_ci      pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0, 2, samplers);
2191bf215546Sopenharmony_ci
2192bf215546Sopenharmony_ci      pipe_sampler_view_reference(&views[1], NULL);
2193bf215546Sopenharmony_ci   } else if (src_has_stencil && dst_has_stencil) {
2194bf215546Sopenharmony_ci      /* Set a stencil-only sampler view for it not to sample depth instead. */
2195bf215546Sopenharmony_ci      struct pipe_sampler_view templ;
2196bf215546Sopenharmony_ci      struct pipe_sampler_view *view;
2197bf215546Sopenharmony_ci
2198bf215546Sopenharmony_ci      templ = *src;
2199bf215546Sopenharmony_ci      templ.format = util_format_stencil_only(templ.format);
2200bf215546Sopenharmony_ci      assert(templ.format != PIPE_FORMAT_NONE);
2201bf215546Sopenharmony_ci
2202bf215546Sopenharmony_ci      view = pipe->create_sampler_view(pipe, src->texture, &templ);
2203bf215546Sopenharmony_ci
2204bf215546Sopenharmony_ci      count = 1;
2205bf215546Sopenharmony_ci      pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 1, 0, false, &view);
2206bf215546Sopenharmony_ci      pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT,
2207bf215546Sopenharmony_ci                                0, 1, &sampler_state);
2208bf215546Sopenharmony_ci
2209bf215546Sopenharmony_ci      pipe_sampler_view_reference(&view, NULL);
2210bf215546Sopenharmony_ci   } else {
2211bf215546Sopenharmony_ci      count = 1;
2212bf215546Sopenharmony_ci      pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 1, 0, false, &src);
2213bf215546Sopenharmony_ci      pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT,
2214bf215546Sopenharmony_ci                                0, 1, &sampler_state);
2215bf215546Sopenharmony_ci   }
2216bf215546Sopenharmony_ci
2217bf215546Sopenharmony_ci   if (scissor) {
2218bf215546Sopenharmony_ci      pipe->set_scissor_states(pipe, 0, 1, scissor);
2219bf215546Sopenharmony_ci   }
2220bf215546Sopenharmony_ci
2221bf215546Sopenharmony_ci   blitter_set_common_draw_rect_state(ctx, scissor != NULL, dst_samples > 1);
2222bf215546Sopenharmony_ci
2223bf215546Sopenharmony_ci   do_blits(ctx, dst, dstbox, src, src_width0, src_height0,
2224bf215546Sopenharmony_ci            srcbox, dst_has_depth || dst_has_stencil, use_txf, sample0_only,
2225bf215546Sopenharmony_ci            dst_sample);
2226bf215546Sopenharmony_ci
2227bf215546Sopenharmony_ci   util_blitter_restore_vertex_states(blitter);
2228bf215546Sopenharmony_ci   util_blitter_restore_fragment_states(blitter);
2229bf215546Sopenharmony_ci   util_blitter_restore_textures_internal(blitter, count);
2230bf215546Sopenharmony_ci   util_blitter_restore_fb_state(blitter);
2231bf215546Sopenharmony_ci   if (scissor) {
2232bf215546Sopenharmony_ci      pipe->set_scissor_states(pipe, 0, 1, &ctx->base.saved_scissor);
2233bf215546Sopenharmony_ci   }
2234bf215546Sopenharmony_ci   util_blitter_restore_render_cond(blitter);
2235bf215546Sopenharmony_ci   util_blitter_unset_running_flag(blitter);
2236bf215546Sopenharmony_ci}
2237bf215546Sopenharmony_ci
2238bf215546Sopenharmony_civoid
2239bf215546Sopenharmony_ciutil_blitter_blit(struct blitter_context *blitter,
2240bf215546Sopenharmony_ci                  const struct pipe_blit_info *info)
2241bf215546Sopenharmony_ci{
2242bf215546Sopenharmony_ci   struct pipe_resource *dst = info->dst.resource;
2243bf215546Sopenharmony_ci   struct pipe_resource *src = info->src.resource;
2244bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
2245bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
2246bf215546Sopenharmony_ci   struct pipe_surface *dst_view, dst_templ;
2247bf215546Sopenharmony_ci   struct pipe_sampler_view src_templ, *src_view;
2248bf215546Sopenharmony_ci
2249bf215546Sopenharmony_ci   /* Initialize the surface. */
2250bf215546Sopenharmony_ci   util_blitter_default_dst_texture(&dst_templ, dst, info->dst.level,
2251bf215546Sopenharmony_ci                                    info->dst.box.z);
2252bf215546Sopenharmony_ci   dst_templ.format = info->dst.format;
2253bf215546Sopenharmony_ci   dst_view = pipe->create_surface(pipe, dst, &dst_templ);
2254bf215546Sopenharmony_ci
2255bf215546Sopenharmony_ci   /* Initialize the sampler view. */
2256bf215546Sopenharmony_ci   util_blitter_default_src_texture(blitter, &src_templ, src, info->src.level);
2257bf215546Sopenharmony_ci   src_templ.format = info->src.format;
2258bf215546Sopenharmony_ci   src_view = pipe->create_sampler_view(pipe, src, &src_templ);
2259bf215546Sopenharmony_ci
2260bf215546Sopenharmony_ci   /* Copy. */
2261bf215546Sopenharmony_ci   util_blitter_blit_generic(blitter, dst_view, &info->dst.box,
2262bf215546Sopenharmony_ci                             src_view, &info->src.box, src->width0, src->height0,
2263bf215546Sopenharmony_ci                             info->mask, info->filter,
2264bf215546Sopenharmony_ci                             info->scissor_enable ? &info->scissor : NULL,
2265bf215546Sopenharmony_ci                             info->alpha_blend, info->sample0_only,
2266bf215546Sopenharmony_ci                             info->dst_sample);
2267bf215546Sopenharmony_ci
2268bf215546Sopenharmony_ci   pipe_surface_reference(&dst_view, NULL);
2269bf215546Sopenharmony_ci   pipe_sampler_view_reference(&src_view, NULL);
2270bf215546Sopenharmony_ci}
2271bf215546Sopenharmony_ci
2272bf215546Sopenharmony_civoid util_blitter_generate_mipmap(struct blitter_context *blitter,
2273bf215546Sopenharmony_ci                                  struct pipe_resource *tex,
2274bf215546Sopenharmony_ci                                  enum pipe_format format,
2275bf215546Sopenharmony_ci                                  unsigned base_level, unsigned last_level,
2276bf215546Sopenharmony_ci                                  unsigned first_layer, unsigned last_layer)
2277bf215546Sopenharmony_ci{
2278bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
2279bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
2280bf215546Sopenharmony_ci   struct pipe_surface dst_templ, *dst_view;
2281bf215546Sopenharmony_ci   struct pipe_sampler_view src_templ, *src_view;
2282bf215546Sopenharmony_ci   bool is_depth;
2283bf215546Sopenharmony_ci   void *sampler_state;
2284bf215546Sopenharmony_ci   const struct util_format_description *desc =
2285bf215546Sopenharmony_ci         util_format_description(format);
2286bf215546Sopenharmony_ci   unsigned src_level;
2287bf215546Sopenharmony_ci   unsigned target = tex->target;
2288bf215546Sopenharmony_ci
2289bf215546Sopenharmony_ci   if (ctx->cube_as_2darray &&
2290bf215546Sopenharmony_ci       (target == PIPE_TEXTURE_CUBE || target == PIPE_TEXTURE_CUBE_ARRAY))
2291bf215546Sopenharmony_ci      target = PIPE_TEXTURE_2D_ARRAY;
2292bf215546Sopenharmony_ci
2293bf215546Sopenharmony_ci   assert(tex->nr_samples <= 1);
2294bf215546Sopenharmony_ci   /* Disallow stencil formats without depth. */
2295bf215546Sopenharmony_ci   assert(!util_format_has_stencil(desc) || util_format_has_depth(desc));
2296bf215546Sopenharmony_ci
2297bf215546Sopenharmony_ci   is_depth = desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS;
2298bf215546Sopenharmony_ci
2299bf215546Sopenharmony_ci   /* Check whether the states are properly saved. */
2300bf215546Sopenharmony_ci   util_blitter_set_running_flag(blitter);
2301bf215546Sopenharmony_ci   blitter_check_saved_vertex_states(ctx);
2302bf215546Sopenharmony_ci   blitter_check_saved_fragment_states(ctx);
2303bf215546Sopenharmony_ci   blitter_check_saved_textures(ctx);
2304bf215546Sopenharmony_ci   blitter_check_saved_fb_state(ctx);
2305bf215546Sopenharmony_ci   blitter_disable_render_cond(ctx);
2306bf215546Sopenharmony_ci
2307bf215546Sopenharmony_ci   /* Set states. */
2308bf215546Sopenharmony_ci   if (is_depth) {
2309bf215546Sopenharmony_ci      pipe->bind_blend_state(pipe, ctx->blend[0][0]);
2310bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe,
2311bf215546Sopenharmony_ci                                           ctx->dsa_write_depth_keep_stencil);
2312bf215546Sopenharmony_ci      ctx->bind_fs_state(pipe,
2313bf215546Sopenharmony_ci                         blitter_get_fs_texfetch_depth(ctx, target, 1, 1, false));
2314bf215546Sopenharmony_ci   } else {
2315bf215546Sopenharmony_ci      pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA][0]);
2316bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
2317bf215546Sopenharmony_ci      ctx->bind_fs_state(pipe,
2318bf215546Sopenharmony_ci            blitter_get_fs_texfetch_col(ctx, tex->format, tex->format, target,
2319bf215546Sopenharmony_ci                                        1, 1, PIPE_TEX_FILTER_LINEAR, false));
2320bf215546Sopenharmony_ci   }
2321bf215546Sopenharmony_ci
2322bf215546Sopenharmony_ci   if (target == PIPE_TEXTURE_RECT) {
2323bf215546Sopenharmony_ci      sampler_state = ctx->sampler_state_rect_linear;
2324bf215546Sopenharmony_ci   } else {
2325bf215546Sopenharmony_ci      sampler_state = ctx->sampler_state_linear;
2326bf215546Sopenharmony_ci   }
2327bf215546Sopenharmony_ci   pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT,
2328bf215546Sopenharmony_ci                             0, 1, &sampler_state);
2329bf215546Sopenharmony_ci
2330bf215546Sopenharmony_ci   blitter_set_common_draw_rect_state(ctx, false, false);
2331bf215546Sopenharmony_ci
2332bf215546Sopenharmony_ci   for (src_level = base_level; src_level < last_level; src_level++) {
2333bf215546Sopenharmony_ci      struct pipe_box dstbox = {0}, srcbox = {0};
2334bf215546Sopenharmony_ci      unsigned dst_level = src_level + 1;
2335bf215546Sopenharmony_ci
2336bf215546Sopenharmony_ci      dstbox.width = u_minify(tex->width0, dst_level);
2337bf215546Sopenharmony_ci      dstbox.height = u_minify(tex->height0, dst_level);
2338bf215546Sopenharmony_ci
2339bf215546Sopenharmony_ci      srcbox.width = u_minify(tex->width0, src_level);
2340bf215546Sopenharmony_ci      srcbox.height = u_minify(tex->height0, src_level);
2341bf215546Sopenharmony_ci
2342bf215546Sopenharmony_ci      if (target == PIPE_TEXTURE_3D) {
2343bf215546Sopenharmony_ci         dstbox.depth = util_num_layers(tex, dst_level);
2344bf215546Sopenharmony_ci         srcbox.depth = util_num_layers(tex, src_level);
2345bf215546Sopenharmony_ci      } else {
2346bf215546Sopenharmony_ci         dstbox.z = srcbox.z = first_layer;
2347bf215546Sopenharmony_ci         dstbox.depth = srcbox.depth = last_layer - first_layer + 1;
2348bf215546Sopenharmony_ci      }
2349bf215546Sopenharmony_ci
2350bf215546Sopenharmony_ci      /* Initialize the surface. */
2351bf215546Sopenharmony_ci      util_blitter_default_dst_texture(&dst_templ, tex, dst_level,
2352bf215546Sopenharmony_ci                                       first_layer);
2353bf215546Sopenharmony_ci      dst_templ.format = format;
2354bf215546Sopenharmony_ci      dst_view = pipe->create_surface(pipe, tex, &dst_templ);
2355bf215546Sopenharmony_ci
2356bf215546Sopenharmony_ci      /* Initialize the sampler view. */
2357bf215546Sopenharmony_ci      util_blitter_default_src_texture(blitter, &src_templ, tex, src_level);
2358bf215546Sopenharmony_ci      src_templ.format = format;
2359bf215546Sopenharmony_ci      src_view = pipe->create_sampler_view(pipe, tex, &src_templ);
2360bf215546Sopenharmony_ci
2361bf215546Sopenharmony_ci      pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 1, 0, false, &src_view);
2362bf215546Sopenharmony_ci
2363bf215546Sopenharmony_ci      do_blits(ctx, dst_view, &dstbox, src_view, tex->width0, tex->height0,
2364bf215546Sopenharmony_ci               &srcbox, is_depth, false, false, 0);
2365bf215546Sopenharmony_ci
2366bf215546Sopenharmony_ci      pipe_surface_reference(&dst_view, NULL);
2367bf215546Sopenharmony_ci      pipe_sampler_view_reference(&src_view, NULL);
2368bf215546Sopenharmony_ci   }
2369bf215546Sopenharmony_ci
2370bf215546Sopenharmony_ci   util_blitter_restore_vertex_states(blitter);
2371bf215546Sopenharmony_ci   util_blitter_restore_fragment_states(blitter);
2372bf215546Sopenharmony_ci   util_blitter_restore_textures_internal(blitter, 1);
2373bf215546Sopenharmony_ci   util_blitter_restore_fb_state(blitter);
2374bf215546Sopenharmony_ci   util_blitter_restore_render_cond(blitter);
2375bf215546Sopenharmony_ci   util_blitter_unset_running_flag(blitter);
2376bf215546Sopenharmony_ci}
2377bf215546Sopenharmony_ci
2378bf215546Sopenharmony_ci/* Clear a region of a color surface to a constant value. */
2379bf215546Sopenharmony_civoid util_blitter_clear_render_target(struct blitter_context *blitter,
2380bf215546Sopenharmony_ci                                      struct pipe_surface *dstsurf,
2381bf215546Sopenharmony_ci                                      const union pipe_color_union *color,
2382bf215546Sopenharmony_ci                                      unsigned dstx, unsigned dsty,
2383bf215546Sopenharmony_ci                                      unsigned width, unsigned height)
2384bf215546Sopenharmony_ci{
2385bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
2386bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
2387bf215546Sopenharmony_ci   struct pipe_framebuffer_state fb_state;
2388bf215546Sopenharmony_ci   bool msaa;
2389bf215546Sopenharmony_ci   unsigned num_layers;
2390bf215546Sopenharmony_ci
2391bf215546Sopenharmony_ci   assert(dstsurf->texture);
2392bf215546Sopenharmony_ci   if (!dstsurf->texture)
2393bf215546Sopenharmony_ci      return;
2394bf215546Sopenharmony_ci
2395bf215546Sopenharmony_ci   /* check the saved state */
2396bf215546Sopenharmony_ci   util_blitter_set_running_flag(blitter);
2397bf215546Sopenharmony_ci   blitter_check_saved_vertex_states(ctx);
2398bf215546Sopenharmony_ci   blitter_check_saved_fragment_states(ctx);
2399bf215546Sopenharmony_ci   blitter_check_saved_fb_state(ctx);
2400bf215546Sopenharmony_ci   blitter_disable_render_cond(ctx);
2401bf215546Sopenharmony_ci
2402bf215546Sopenharmony_ci   /* bind states */
2403bf215546Sopenharmony_ci   pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA][0]);
2404bf215546Sopenharmony_ci   pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
2405bf215546Sopenharmony_ci   bind_fs_write_one_cbuf(ctx);
2406bf215546Sopenharmony_ci
2407bf215546Sopenharmony_ci   /* set a framebuffer state */
2408bf215546Sopenharmony_ci   fb_state.width = dstsurf->width;
2409bf215546Sopenharmony_ci   fb_state.height = dstsurf->height;
2410bf215546Sopenharmony_ci   fb_state.nr_cbufs = 1;
2411bf215546Sopenharmony_ci   fb_state.cbufs[0] = dstsurf;
2412bf215546Sopenharmony_ci   fb_state.zsbuf = NULL;
2413bf215546Sopenharmony_ci   pipe->set_framebuffer_state(pipe, &fb_state);
2414bf215546Sopenharmony_ci   pipe->set_sample_mask(pipe, ~0);
2415bf215546Sopenharmony_ci   if (pipe->set_min_samples)
2416bf215546Sopenharmony_ci      pipe->set_min_samples(pipe, 1);
2417bf215546Sopenharmony_ci   msaa = util_framebuffer_get_num_samples(&fb_state) > 1;
2418bf215546Sopenharmony_ci
2419bf215546Sopenharmony_ci   blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
2420bf215546Sopenharmony_ci
2421bf215546Sopenharmony_ci   union blitter_attrib attrib;
2422bf215546Sopenharmony_ci   memcpy(attrib.color, color->ui, sizeof(color->ui));
2423bf215546Sopenharmony_ci
2424bf215546Sopenharmony_ci   num_layers = dstsurf->u.tex.last_layer - dstsurf->u.tex.first_layer + 1;
2425bf215546Sopenharmony_ci   if (num_layers > 1 && ctx->has_layered) {
2426bf215546Sopenharmony_ci      blitter_set_common_draw_rect_state(ctx, false, msaa);
2427bf215546Sopenharmony_ci      blitter->draw_rectangle(blitter, ctx->velem_state, get_vs_layered,
2428bf215546Sopenharmony_ci                              dstx, dsty, dstx+width, dsty+height, 0,
2429bf215546Sopenharmony_ci                              num_layers, UTIL_BLITTER_ATTRIB_COLOR, &attrib);
2430bf215546Sopenharmony_ci   } else {
2431bf215546Sopenharmony_ci      blitter_set_common_draw_rect_state(ctx, false, msaa);
2432bf215546Sopenharmony_ci      blitter->draw_rectangle(blitter, ctx->velem_state,
2433bf215546Sopenharmony_ci                              get_vs_passthrough_pos_generic,
2434bf215546Sopenharmony_ci                              dstx, dsty, dstx+width, dsty+height, 0,
2435bf215546Sopenharmony_ci                              1, UTIL_BLITTER_ATTRIB_COLOR, &attrib);
2436bf215546Sopenharmony_ci   }
2437bf215546Sopenharmony_ci
2438bf215546Sopenharmony_ci   util_blitter_restore_vertex_states(blitter);
2439bf215546Sopenharmony_ci   util_blitter_restore_fragment_states(blitter);
2440bf215546Sopenharmony_ci   util_blitter_restore_fb_state(blitter);
2441bf215546Sopenharmony_ci   util_blitter_restore_render_cond(blitter);
2442bf215546Sopenharmony_ci   util_blitter_unset_running_flag(blitter);
2443bf215546Sopenharmony_ci}
2444bf215546Sopenharmony_ci
2445bf215546Sopenharmony_ci/* Clear a region of a depth stencil surface. */
2446bf215546Sopenharmony_civoid util_blitter_clear_depth_stencil(struct blitter_context *blitter,
2447bf215546Sopenharmony_ci                                      struct pipe_surface *dstsurf,
2448bf215546Sopenharmony_ci                                      unsigned clear_flags,
2449bf215546Sopenharmony_ci                                      double depth,
2450bf215546Sopenharmony_ci                                      unsigned stencil,
2451bf215546Sopenharmony_ci                                      unsigned dstx, unsigned dsty,
2452bf215546Sopenharmony_ci                                      unsigned width, unsigned height)
2453bf215546Sopenharmony_ci{
2454bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
2455bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
2456bf215546Sopenharmony_ci   struct pipe_framebuffer_state fb_state;
2457bf215546Sopenharmony_ci   struct pipe_stencil_ref sr = { { 0 } };
2458bf215546Sopenharmony_ci   unsigned num_layers;
2459bf215546Sopenharmony_ci
2460bf215546Sopenharmony_ci   assert(dstsurf->texture);
2461bf215546Sopenharmony_ci   if (!dstsurf->texture)
2462bf215546Sopenharmony_ci      return;
2463bf215546Sopenharmony_ci
2464bf215546Sopenharmony_ci   /* check the saved state */
2465bf215546Sopenharmony_ci   util_blitter_set_running_flag(blitter);
2466bf215546Sopenharmony_ci   blitter_check_saved_vertex_states(ctx);
2467bf215546Sopenharmony_ci   blitter_check_saved_fragment_states(ctx);
2468bf215546Sopenharmony_ci   blitter_check_saved_fb_state(ctx);
2469bf215546Sopenharmony_ci   blitter_disable_render_cond(ctx);
2470bf215546Sopenharmony_ci
2471bf215546Sopenharmony_ci   /* bind states */
2472bf215546Sopenharmony_ci   pipe->bind_blend_state(pipe, ctx->blend[0][0]);
2473bf215546Sopenharmony_ci   if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
2474bf215546Sopenharmony_ci      sr.ref_value[0] = stencil & 0xff;
2475bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
2476bf215546Sopenharmony_ci      pipe->set_stencil_ref(pipe, sr);
2477bf215546Sopenharmony_ci   }
2478bf215546Sopenharmony_ci   else if (clear_flags & PIPE_CLEAR_DEPTH) {
2479bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
2480bf215546Sopenharmony_ci   }
2481bf215546Sopenharmony_ci   else if (clear_flags & PIPE_CLEAR_STENCIL) {
2482bf215546Sopenharmony_ci      sr.ref_value[0] = stencil & 0xff;
2483bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
2484bf215546Sopenharmony_ci      pipe->set_stencil_ref(pipe, sr);
2485bf215546Sopenharmony_ci   }
2486bf215546Sopenharmony_ci   else
2487bf215546Sopenharmony_ci      /* hmm that should be illegal probably, or make it a no-op somewhere */
2488bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
2489bf215546Sopenharmony_ci
2490bf215546Sopenharmony_ci   bind_fs_empty(ctx);
2491bf215546Sopenharmony_ci
2492bf215546Sopenharmony_ci   /* set a framebuffer state */
2493bf215546Sopenharmony_ci   fb_state.width = dstsurf->width;
2494bf215546Sopenharmony_ci   fb_state.height = dstsurf->height;
2495bf215546Sopenharmony_ci   fb_state.nr_cbufs = 0;
2496bf215546Sopenharmony_ci   fb_state.cbufs[0] = NULL;
2497bf215546Sopenharmony_ci   fb_state.zsbuf = dstsurf;
2498bf215546Sopenharmony_ci   pipe->set_framebuffer_state(pipe, &fb_state);
2499bf215546Sopenharmony_ci   pipe->set_sample_mask(pipe, ~0);
2500bf215546Sopenharmony_ci   if (pipe->set_min_samples)
2501bf215546Sopenharmony_ci      pipe->set_min_samples(pipe, 1);
2502bf215546Sopenharmony_ci
2503bf215546Sopenharmony_ci   blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
2504bf215546Sopenharmony_ci
2505bf215546Sopenharmony_ci   num_layers = dstsurf->u.tex.last_layer - dstsurf->u.tex.first_layer + 1;
2506bf215546Sopenharmony_ci   if (num_layers > 1 && ctx->has_layered) {
2507bf215546Sopenharmony_ci      blitter_set_common_draw_rect_state(ctx, false, false);
2508bf215546Sopenharmony_ci      blitter->draw_rectangle(blitter, ctx->velem_state, get_vs_layered,
2509bf215546Sopenharmony_ci                              dstx, dsty, dstx+width, dsty+height, depth,
2510bf215546Sopenharmony_ci                              num_layers, UTIL_BLITTER_ATTRIB_NONE, NULL);
2511bf215546Sopenharmony_ci   } else {
2512bf215546Sopenharmony_ci      blitter_set_common_draw_rect_state(ctx, false, false);
2513bf215546Sopenharmony_ci      blitter->draw_rectangle(blitter, ctx->velem_state,
2514bf215546Sopenharmony_ci                              get_vs_passthrough_pos,
2515bf215546Sopenharmony_ci                              dstx, dsty, dstx+width, dsty+height, depth, 1,
2516bf215546Sopenharmony_ci                              UTIL_BLITTER_ATTRIB_NONE, NULL);
2517bf215546Sopenharmony_ci   }
2518bf215546Sopenharmony_ci
2519bf215546Sopenharmony_ci   util_blitter_restore_vertex_states(blitter);
2520bf215546Sopenharmony_ci   util_blitter_restore_fragment_states(blitter);
2521bf215546Sopenharmony_ci   util_blitter_restore_fb_state(blitter);
2522bf215546Sopenharmony_ci   util_blitter_restore_render_cond(blitter);
2523bf215546Sopenharmony_ci   util_blitter_unset_running_flag(blitter);
2524bf215546Sopenharmony_ci}
2525bf215546Sopenharmony_ci
2526bf215546Sopenharmony_ci/* draw a rectangle across a region using a custom dsa stage - for r600g */
2527bf215546Sopenharmony_civoid util_blitter_custom_depth_stencil(struct blitter_context *blitter,
2528bf215546Sopenharmony_ci                                       struct pipe_surface *zsurf,
2529bf215546Sopenharmony_ci                                       struct pipe_surface *cbsurf,
2530bf215546Sopenharmony_ci                                       unsigned sample_mask,
2531bf215546Sopenharmony_ci                                       void *dsa_stage, float depth)
2532bf215546Sopenharmony_ci{
2533bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
2534bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
2535bf215546Sopenharmony_ci   struct pipe_framebuffer_state fb_state;
2536bf215546Sopenharmony_ci
2537bf215546Sopenharmony_ci   assert(zsurf->texture);
2538bf215546Sopenharmony_ci   if (!zsurf->texture)
2539bf215546Sopenharmony_ci      return;
2540bf215546Sopenharmony_ci
2541bf215546Sopenharmony_ci   /* check the saved state */
2542bf215546Sopenharmony_ci   util_blitter_set_running_flag(blitter);
2543bf215546Sopenharmony_ci   blitter_check_saved_vertex_states(ctx);
2544bf215546Sopenharmony_ci   blitter_check_saved_fragment_states(ctx);
2545bf215546Sopenharmony_ci   blitter_check_saved_fb_state(ctx);
2546bf215546Sopenharmony_ci   blitter_disable_render_cond(ctx);
2547bf215546Sopenharmony_ci
2548bf215546Sopenharmony_ci   /* bind states */
2549bf215546Sopenharmony_ci   pipe->bind_blend_state(pipe, cbsurf ? ctx->blend[PIPE_MASK_RGBA][0] :
2550bf215546Sopenharmony_ci                                         ctx->blend[0][0]);
2551bf215546Sopenharmony_ci   pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage);
2552bf215546Sopenharmony_ci   if (cbsurf)
2553bf215546Sopenharmony_ci      bind_fs_write_one_cbuf(ctx);
2554bf215546Sopenharmony_ci   else
2555bf215546Sopenharmony_ci      bind_fs_empty(ctx);
2556bf215546Sopenharmony_ci
2557bf215546Sopenharmony_ci   /* set a framebuffer state */
2558bf215546Sopenharmony_ci   fb_state.width = zsurf->width;
2559bf215546Sopenharmony_ci   fb_state.height = zsurf->height;
2560bf215546Sopenharmony_ci   fb_state.nr_cbufs = 1;
2561bf215546Sopenharmony_ci   if (cbsurf) {
2562bf215546Sopenharmony_ci      fb_state.cbufs[0] = cbsurf;
2563bf215546Sopenharmony_ci      fb_state.nr_cbufs = 1;
2564bf215546Sopenharmony_ci   } else {
2565bf215546Sopenharmony_ci      fb_state.cbufs[0] = NULL;
2566bf215546Sopenharmony_ci      fb_state.nr_cbufs = 0;
2567bf215546Sopenharmony_ci   }
2568bf215546Sopenharmony_ci   fb_state.zsbuf = zsurf;
2569bf215546Sopenharmony_ci   pipe->set_framebuffer_state(pipe, &fb_state);
2570bf215546Sopenharmony_ci   pipe->set_sample_mask(pipe, sample_mask);
2571bf215546Sopenharmony_ci   if (pipe->set_min_samples)
2572bf215546Sopenharmony_ci      pipe->set_min_samples(pipe, 1);
2573bf215546Sopenharmony_ci
2574bf215546Sopenharmony_ci   blitter_set_common_draw_rect_state(ctx, false,
2575bf215546Sopenharmony_ci      util_framebuffer_get_num_samples(&fb_state) > 1);
2576bf215546Sopenharmony_ci   blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height);
2577bf215546Sopenharmony_ci   blitter->draw_rectangle(blitter, ctx->velem_state, get_vs_passthrough_pos,
2578bf215546Sopenharmony_ci                           0, 0, zsurf->width, zsurf->height, depth,
2579bf215546Sopenharmony_ci                           1, UTIL_BLITTER_ATTRIB_NONE, NULL);
2580bf215546Sopenharmony_ci
2581bf215546Sopenharmony_ci   util_blitter_restore_vertex_states(blitter);
2582bf215546Sopenharmony_ci   util_blitter_restore_fragment_states(blitter);
2583bf215546Sopenharmony_ci   util_blitter_restore_fb_state(blitter);
2584bf215546Sopenharmony_ci   util_blitter_restore_render_cond(blitter);
2585bf215546Sopenharmony_ci   util_blitter_unset_running_flag(blitter);
2586bf215546Sopenharmony_ci}
2587bf215546Sopenharmony_ci
2588bf215546Sopenharmony_civoid util_blitter_clear_buffer(struct blitter_context *blitter,
2589bf215546Sopenharmony_ci                               struct pipe_resource *dst,
2590bf215546Sopenharmony_ci                               unsigned offset, unsigned size,
2591bf215546Sopenharmony_ci                               unsigned num_channels,
2592bf215546Sopenharmony_ci                               const union pipe_color_union *clear_value)
2593bf215546Sopenharmony_ci{
2594bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
2595bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
2596bf215546Sopenharmony_ci   struct pipe_vertex_buffer vb = {0};
2597bf215546Sopenharmony_ci   struct pipe_stream_output_target *so_target = NULL;
2598bf215546Sopenharmony_ci   unsigned offsets[PIPE_MAX_SO_BUFFERS] = {0};
2599bf215546Sopenharmony_ci
2600bf215546Sopenharmony_ci   assert(num_channels >= 1);
2601bf215546Sopenharmony_ci   assert(num_channels <= 4);
2602bf215546Sopenharmony_ci
2603bf215546Sopenharmony_ci   /* IMPORTANT:  DON'T DO ANY BOUNDS CHECKING HERE!
2604bf215546Sopenharmony_ci    *
2605bf215546Sopenharmony_ci    * R600 uses this to initialize texture resources, so width0 might not be
2606bf215546Sopenharmony_ci    * what you think it is.
2607bf215546Sopenharmony_ci    */
2608bf215546Sopenharmony_ci
2609bf215546Sopenharmony_ci   /* Streamout is required. */
2610bf215546Sopenharmony_ci   if (!ctx->has_stream_out) {
2611bf215546Sopenharmony_ci      assert(!"Streamout unsupported in util_blitter_clear_buffer()");
2612bf215546Sopenharmony_ci      return;
2613bf215546Sopenharmony_ci   }
2614bf215546Sopenharmony_ci
2615bf215546Sopenharmony_ci   /* Some alignment is required. */
2616bf215546Sopenharmony_ci   if (offset % 4 != 0 || size % 4 != 0) {
2617bf215546Sopenharmony_ci      assert(!"Bad alignment in util_blitter_clear_buffer()");
2618bf215546Sopenharmony_ci      return;
2619bf215546Sopenharmony_ci   }
2620bf215546Sopenharmony_ci
2621bf215546Sopenharmony_ci   u_upload_data(pipe->stream_uploader, 0, num_channels*4, 4, clear_value,
2622bf215546Sopenharmony_ci                 &vb.buffer_offset, &vb.buffer.resource);
2623bf215546Sopenharmony_ci   if (!vb.buffer.resource)
2624bf215546Sopenharmony_ci      goto out;
2625bf215546Sopenharmony_ci
2626bf215546Sopenharmony_ci   vb.stride = 0;
2627bf215546Sopenharmony_ci
2628bf215546Sopenharmony_ci   util_blitter_set_running_flag(blitter);
2629bf215546Sopenharmony_ci   blitter_check_saved_vertex_states(ctx);
2630bf215546Sopenharmony_ci   blitter_disable_render_cond(ctx);
2631bf215546Sopenharmony_ci
2632bf215546Sopenharmony_ci   pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, 0, false, &vb);
2633bf215546Sopenharmony_ci   pipe->bind_vertex_elements_state(pipe,
2634bf215546Sopenharmony_ci                                    ctx->velem_state_readbuf[num_channels-1]);
2635bf215546Sopenharmony_ci   bind_vs_pos_only(ctx, num_channels);
2636bf215546Sopenharmony_ci   if (ctx->has_geometry_shader)
2637bf215546Sopenharmony_ci      pipe->bind_gs_state(pipe, NULL);
2638bf215546Sopenharmony_ci   if (ctx->has_tessellation) {
2639bf215546Sopenharmony_ci      pipe->bind_tcs_state(pipe, NULL);
2640bf215546Sopenharmony_ci      pipe->bind_tes_state(pipe, NULL);
2641bf215546Sopenharmony_ci   }
2642bf215546Sopenharmony_ci   pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state);
2643bf215546Sopenharmony_ci
2644bf215546Sopenharmony_ci   so_target = pipe->create_stream_output_target(pipe, dst, offset, size);
2645bf215546Sopenharmony_ci   pipe->set_stream_output_targets(pipe, 1, &so_target, offsets);
2646bf215546Sopenharmony_ci
2647bf215546Sopenharmony_ci   util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 4);
2648bf215546Sopenharmony_ci
2649bf215546Sopenharmony_ciout:
2650bf215546Sopenharmony_ci   util_blitter_restore_vertex_states(blitter);
2651bf215546Sopenharmony_ci   util_blitter_restore_render_cond(blitter);
2652bf215546Sopenharmony_ci   util_blitter_unset_running_flag(blitter);
2653bf215546Sopenharmony_ci   pipe_so_target_reference(&so_target, NULL);
2654bf215546Sopenharmony_ci   pipe_resource_reference(&vb.buffer.resource, NULL);
2655bf215546Sopenharmony_ci}
2656bf215546Sopenharmony_ci
2657bf215546Sopenharmony_ci/* probably radeon specific */
2658bf215546Sopenharmony_civoid util_blitter_custom_resolve_color(struct blitter_context *blitter,
2659bf215546Sopenharmony_ci                                       struct pipe_resource *dst,
2660bf215546Sopenharmony_ci                                       unsigned dst_level,
2661bf215546Sopenharmony_ci                                       unsigned dst_layer,
2662bf215546Sopenharmony_ci                                       struct pipe_resource *src,
2663bf215546Sopenharmony_ci                                       unsigned src_layer,
2664bf215546Sopenharmony_ci                                       unsigned sample_mask,
2665bf215546Sopenharmony_ci                                       void *custom_blend,
2666bf215546Sopenharmony_ci                                       enum pipe_format format)
2667bf215546Sopenharmony_ci{
2668bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
2669bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
2670bf215546Sopenharmony_ci   struct pipe_framebuffer_state fb_state;
2671bf215546Sopenharmony_ci   struct pipe_surface *srcsurf, *dstsurf, surf_tmpl;
2672bf215546Sopenharmony_ci
2673bf215546Sopenharmony_ci   util_blitter_set_running_flag(blitter);
2674bf215546Sopenharmony_ci   blitter_check_saved_vertex_states(ctx);
2675bf215546Sopenharmony_ci   blitter_check_saved_fragment_states(ctx);
2676bf215546Sopenharmony_ci   blitter_disable_render_cond(ctx);
2677bf215546Sopenharmony_ci
2678bf215546Sopenharmony_ci   /* bind states */
2679bf215546Sopenharmony_ci   pipe->bind_blend_state(pipe, custom_blend);
2680bf215546Sopenharmony_ci   pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
2681bf215546Sopenharmony_ci   bind_fs_write_one_cbuf(ctx);
2682bf215546Sopenharmony_ci   pipe->set_sample_mask(pipe, sample_mask);
2683bf215546Sopenharmony_ci   if (pipe->set_min_samples)
2684bf215546Sopenharmony_ci      pipe->set_min_samples(pipe, 1);
2685bf215546Sopenharmony_ci
2686bf215546Sopenharmony_ci   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
2687bf215546Sopenharmony_ci   surf_tmpl.format = format;
2688bf215546Sopenharmony_ci   surf_tmpl.u.tex.level = dst_level;
2689bf215546Sopenharmony_ci   surf_tmpl.u.tex.first_layer = dst_layer;
2690bf215546Sopenharmony_ci   surf_tmpl.u.tex.last_layer = dst_layer;
2691bf215546Sopenharmony_ci
2692bf215546Sopenharmony_ci   dstsurf = pipe->create_surface(pipe, dst, &surf_tmpl);
2693bf215546Sopenharmony_ci
2694bf215546Sopenharmony_ci   surf_tmpl.u.tex.level = 0;
2695bf215546Sopenharmony_ci   surf_tmpl.u.tex.first_layer = src_layer;
2696bf215546Sopenharmony_ci   surf_tmpl.u.tex.last_layer = src_layer;
2697bf215546Sopenharmony_ci
2698bf215546Sopenharmony_ci   srcsurf = pipe->create_surface(pipe, src, &surf_tmpl);
2699bf215546Sopenharmony_ci
2700bf215546Sopenharmony_ci   /* set a framebuffer state */
2701bf215546Sopenharmony_ci   fb_state.width = src->width0;
2702bf215546Sopenharmony_ci   fb_state.height = src->height0;
2703bf215546Sopenharmony_ci   fb_state.nr_cbufs = 2;
2704bf215546Sopenharmony_ci   fb_state.cbufs[0] = srcsurf;
2705bf215546Sopenharmony_ci   fb_state.cbufs[1] = dstsurf;
2706bf215546Sopenharmony_ci   fb_state.zsbuf = NULL;
2707bf215546Sopenharmony_ci   pipe->set_framebuffer_state(pipe, &fb_state);
2708bf215546Sopenharmony_ci
2709bf215546Sopenharmony_ci   blitter_set_common_draw_rect_state(ctx, false,
2710bf215546Sopenharmony_ci      util_framebuffer_get_num_samples(&fb_state) > 1);
2711bf215546Sopenharmony_ci   blitter_set_dst_dimensions(ctx, src->width0, src->height0);
2712bf215546Sopenharmony_ci   blitter->draw_rectangle(blitter, ctx->velem_state, get_vs_passthrough_pos,
2713bf215546Sopenharmony_ci                           0, 0, src->width0, src->height0,
2714bf215546Sopenharmony_ci                           0, 1, UTIL_BLITTER_ATTRIB_NONE, NULL);
2715bf215546Sopenharmony_ci   util_blitter_restore_fb_state(blitter);
2716bf215546Sopenharmony_ci   util_blitter_restore_vertex_states(blitter);
2717bf215546Sopenharmony_ci   util_blitter_restore_fragment_states(blitter);
2718bf215546Sopenharmony_ci   util_blitter_restore_render_cond(blitter);
2719bf215546Sopenharmony_ci   util_blitter_unset_running_flag(blitter);
2720bf215546Sopenharmony_ci
2721bf215546Sopenharmony_ci   pipe_surface_reference(&srcsurf, NULL);
2722bf215546Sopenharmony_ci   pipe_surface_reference(&dstsurf, NULL);
2723bf215546Sopenharmony_ci}
2724bf215546Sopenharmony_ci
2725bf215546Sopenharmony_civoid util_blitter_custom_color(struct blitter_context *blitter,
2726bf215546Sopenharmony_ci                               struct pipe_surface *dstsurf,
2727bf215546Sopenharmony_ci                               void *custom_blend)
2728bf215546Sopenharmony_ci{
2729bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
2730bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
2731bf215546Sopenharmony_ci   struct pipe_framebuffer_state fb_state;
2732bf215546Sopenharmony_ci
2733bf215546Sopenharmony_ci   assert(dstsurf->texture);
2734bf215546Sopenharmony_ci   if (!dstsurf->texture)
2735bf215546Sopenharmony_ci      return;
2736bf215546Sopenharmony_ci
2737bf215546Sopenharmony_ci   /* check the saved state */
2738bf215546Sopenharmony_ci   util_blitter_set_running_flag(blitter);
2739bf215546Sopenharmony_ci   blitter_check_saved_vertex_states(ctx);
2740bf215546Sopenharmony_ci   blitter_check_saved_fragment_states(ctx);
2741bf215546Sopenharmony_ci   blitter_check_saved_fb_state(ctx);
2742bf215546Sopenharmony_ci   blitter_disable_render_cond(ctx);
2743bf215546Sopenharmony_ci
2744bf215546Sopenharmony_ci   /* bind states */
2745bf215546Sopenharmony_ci   pipe->bind_blend_state(pipe, custom_blend ? custom_blend
2746bf215546Sopenharmony_ci                                             : ctx->blend[PIPE_MASK_RGBA][0]);
2747bf215546Sopenharmony_ci   pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
2748bf215546Sopenharmony_ci   bind_fs_write_one_cbuf(ctx);
2749bf215546Sopenharmony_ci
2750bf215546Sopenharmony_ci   /* set a framebuffer state */
2751bf215546Sopenharmony_ci   fb_state.width = dstsurf->width;
2752bf215546Sopenharmony_ci   fb_state.height = dstsurf->height;
2753bf215546Sopenharmony_ci   fb_state.nr_cbufs = 1;
2754bf215546Sopenharmony_ci   fb_state.cbufs[0] = dstsurf;
2755bf215546Sopenharmony_ci   fb_state.zsbuf = NULL;
2756bf215546Sopenharmony_ci   pipe->set_framebuffer_state(pipe, &fb_state);
2757bf215546Sopenharmony_ci   pipe->set_sample_mask(pipe, ~0);
2758bf215546Sopenharmony_ci   if (pipe->set_min_samples)
2759bf215546Sopenharmony_ci      pipe->set_min_samples(pipe, 1);
2760bf215546Sopenharmony_ci
2761bf215546Sopenharmony_ci   blitter_set_common_draw_rect_state(ctx, false,
2762bf215546Sopenharmony_ci      util_framebuffer_get_num_samples(&fb_state) > 1);
2763bf215546Sopenharmony_ci   blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
2764bf215546Sopenharmony_ci   blitter->draw_rectangle(blitter, ctx->velem_state, get_vs_passthrough_pos,
2765bf215546Sopenharmony_ci                           0, 0, dstsurf->width, dstsurf->height,
2766bf215546Sopenharmony_ci                           0, 1, UTIL_BLITTER_ATTRIB_NONE, NULL);
2767bf215546Sopenharmony_ci
2768bf215546Sopenharmony_ci   util_blitter_restore_vertex_states(blitter);
2769bf215546Sopenharmony_ci   util_blitter_restore_fragment_states(blitter);
2770bf215546Sopenharmony_ci   util_blitter_restore_fb_state(blitter);
2771bf215546Sopenharmony_ci   util_blitter_restore_render_cond(blitter);
2772bf215546Sopenharmony_ci   util_blitter_unset_running_flag(blitter);
2773bf215546Sopenharmony_ci}
2774bf215546Sopenharmony_ci
2775bf215546Sopenharmony_cistatic void *get_custom_vs(struct blitter_context *blitter)
2776bf215546Sopenharmony_ci{
2777bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
2778bf215546Sopenharmony_ci
2779bf215546Sopenharmony_ci   return ctx->custom_vs;
2780bf215546Sopenharmony_ci}
2781bf215546Sopenharmony_ci
2782bf215546Sopenharmony_ci/**
2783bf215546Sopenharmony_ci * Performs a custom blit to the destination surface, using the VS and FS
2784bf215546Sopenharmony_ci * provided.
2785bf215546Sopenharmony_ci *
2786bf215546Sopenharmony_ci * Used by vc4 for the 8-bit linear-to-tiled blit.
2787bf215546Sopenharmony_ci */
2788bf215546Sopenharmony_civoid util_blitter_custom_shader(struct blitter_context *blitter,
2789bf215546Sopenharmony_ci                                struct pipe_surface *dstsurf,
2790bf215546Sopenharmony_ci                                void *custom_vs, void *custom_fs)
2791bf215546Sopenharmony_ci{
2792bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
2793bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
2794bf215546Sopenharmony_ci   struct pipe_framebuffer_state fb_state = { 0 };
2795bf215546Sopenharmony_ci
2796bf215546Sopenharmony_ci   ctx->custom_vs = custom_vs;
2797bf215546Sopenharmony_ci
2798bf215546Sopenharmony_ci   assert(dstsurf->texture);
2799bf215546Sopenharmony_ci   if (!dstsurf->texture)
2800bf215546Sopenharmony_ci      return;
2801bf215546Sopenharmony_ci
2802bf215546Sopenharmony_ci   /* check the saved state */
2803bf215546Sopenharmony_ci   util_blitter_set_running_flag(blitter);
2804bf215546Sopenharmony_ci   blitter_check_saved_vertex_states(ctx);
2805bf215546Sopenharmony_ci   blitter_check_saved_fragment_states(ctx);
2806bf215546Sopenharmony_ci   blitter_check_saved_fb_state(ctx);
2807bf215546Sopenharmony_ci   blitter_disable_render_cond(ctx);
2808bf215546Sopenharmony_ci
2809bf215546Sopenharmony_ci   /* bind states */
2810bf215546Sopenharmony_ci   pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA][0]);
2811bf215546Sopenharmony_ci   pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
2812bf215546Sopenharmony_ci   pipe->bind_fs_state(pipe, custom_fs);
2813bf215546Sopenharmony_ci
2814bf215546Sopenharmony_ci   /* set a framebuffer state */
2815bf215546Sopenharmony_ci   fb_state.width = dstsurf->width;
2816bf215546Sopenharmony_ci   fb_state.height = dstsurf->height;
2817bf215546Sopenharmony_ci   fb_state.nr_cbufs = 1;
2818bf215546Sopenharmony_ci   fb_state.cbufs[0] = dstsurf;
2819bf215546Sopenharmony_ci   pipe->set_framebuffer_state(pipe, &fb_state);
2820bf215546Sopenharmony_ci   pipe->set_sample_mask(pipe, ~0);
2821bf215546Sopenharmony_ci   if (pipe->set_min_samples)
2822bf215546Sopenharmony_ci      pipe->set_min_samples(pipe, 1);
2823bf215546Sopenharmony_ci
2824bf215546Sopenharmony_ci   blitter_set_common_draw_rect_state(ctx, false,
2825bf215546Sopenharmony_ci      util_framebuffer_get_num_samples(&fb_state) > 1);
2826bf215546Sopenharmony_ci   blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
2827bf215546Sopenharmony_ci   blitter->draw_rectangle(blitter, ctx->velem_state, get_custom_vs,
2828bf215546Sopenharmony_ci                           0, 0, dstsurf->width, dstsurf->height,
2829bf215546Sopenharmony_ci                           0, 1, UTIL_BLITTER_ATTRIB_NONE, NULL);
2830bf215546Sopenharmony_ci
2831bf215546Sopenharmony_ci   util_blitter_restore_vertex_states(blitter);
2832bf215546Sopenharmony_ci   util_blitter_restore_fragment_states(blitter);
2833bf215546Sopenharmony_ci   util_blitter_restore_fb_state(blitter);
2834bf215546Sopenharmony_ci   util_blitter_restore_render_cond(blitter);
2835bf215546Sopenharmony_ci   util_blitter_unset_running_flag(blitter);
2836bf215546Sopenharmony_ci}
2837bf215546Sopenharmony_ci
2838bf215546Sopenharmony_cistatic void *
2839bf215546Sopenharmony_ciget_stencil_blit_fallback_fs(struct blitter_context_priv *ctx, bool msaa_src)
2840bf215546Sopenharmony_ci{
2841bf215546Sopenharmony_ci   if (!ctx->fs_stencil_blit_fallback[msaa_src]) {
2842bf215546Sopenharmony_ci      ctx->fs_stencil_blit_fallback[msaa_src] =
2843bf215546Sopenharmony_ci         util_make_fs_stencil_blit(ctx->base.pipe, msaa_src);
2844bf215546Sopenharmony_ci   }
2845bf215546Sopenharmony_ci
2846bf215546Sopenharmony_ci   return ctx->fs_stencil_blit_fallback[msaa_src];
2847bf215546Sopenharmony_ci}
2848bf215546Sopenharmony_ci
2849bf215546Sopenharmony_cistatic void *
2850bf215546Sopenharmony_ciget_stencil_blit_fallback_dsa(struct blitter_context_priv *ctx, unsigned i)
2851bf215546Sopenharmony_ci{
2852bf215546Sopenharmony_ci   assert(i < ARRAY_SIZE(ctx->dsa_replicate_stencil_bit));
2853bf215546Sopenharmony_ci   if (!ctx->dsa_replicate_stencil_bit[i]) {
2854bf215546Sopenharmony_ci      struct pipe_depth_stencil_alpha_state dsa = { 0 };
2855bf215546Sopenharmony_ci      dsa.depth_func = PIPE_FUNC_ALWAYS;
2856bf215546Sopenharmony_ci      dsa.stencil[0].enabled = 1;
2857bf215546Sopenharmony_ci      dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
2858bf215546Sopenharmony_ci      dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
2859bf215546Sopenharmony_ci      dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
2860bf215546Sopenharmony_ci      dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
2861bf215546Sopenharmony_ci      dsa.stencil[0].valuemask = 0xff;
2862bf215546Sopenharmony_ci      dsa.stencil[0].writemask = 1u << i;
2863bf215546Sopenharmony_ci
2864bf215546Sopenharmony_ci      ctx->dsa_replicate_stencil_bit[i] =
2865bf215546Sopenharmony_ci         ctx->base.pipe->create_depth_stencil_alpha_state(ctx->base.pipe, &dsa);
2866bf215546Sopenharmony_ci   }
2867bf215546Sopenharmony_ci   return ctx->dsa_replicate_stencil_bit[i];
2868bf215546Sopenharmony_ci}
2869bf215546Sopenharmony_ci
2870bf215546Sopenharmony_ci/**
2871bf215546Sopenharmony_ci * Performs a series of draws to implement stencil blits texture without
2872bf215546Sopenharmony_ci * requiring stencil writes, updating a single bit per pixel at the time.
2873bf215546Sopenharmony_ci */
2874bf215546Sopenharmony_civoid
2875bf215546Sopenharmony_ciutil_blitter_stencil_fallback(struct blitter_context *blitter,
2876bf215546Sopenharmony_ci                              struct pipe_resource *dst,
2877bf215546Sopenharmony_ci                              unsigned dst_level,
2878bf215546Sopenharmony_ci                              const struct pipe_box *dstbox,
2879bf215546Sopenharmony_ci                              struct pipe_resource *src,
2880bf215546Sopenharmony_ci                              unsigned src_level,
2881bf215546Sopenharmony_ci                              const struct pipe_box *srcbox,
2882bf215546Sopenharmony_ci                              const struct pipe_scissor_state *scissor)
2883bf215546Sopenharmony_ci{
2884bf215546Sopenharmony_ci   struct blitter_context_priv *ctx = (struct blitter_context_priv *)blitter;
2885bf215546Sopenharmony_ci   struct pipe_context *pipe = ctx->base.pipe;
2886bf215546Sopenharmony_ci
2887bf215546Sopenharmony_ci   /* check the saved state */
2888bf215546Sopenharmony_ci   util_blitter_set_running_flag(blitter);
2889bf215546Sopenharmony_ci   blitter_check_saved_vertex_states(ctx);
2890bf215546Sopenharmony_ci   blitter_check_saved_fragment_states(ctx);
2891bf215546Sopenharmony_ci   blitter_check_saved_fb_state(ctx);
2892bf215546Sopenharmony_ci   blitter_disable_render_cond(ctx);
2893bf215546Sopenharmony_ci
2894bf215546Sopenharmony_ci   /* Initialize the surface. */
2895bf215546Sopenharmony_ci   struct pipe_surface *dst_view, dst_templ;
2896bf215546Sopenharmony_ci   util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstbox->z);
2897bf215546Sopenharmony_ci   dst_view = pipe->create_surface(pipe, dst, &dst_templ);
2898bf215546Sopenharmony_ci
2899bf215546Sopenharmony_ci   /* Initialize the sampler view. */
2900bf215546Sopenharmony_ci   struct pipe_sampler_view src_templ, *src_view;
2901bf215546Sopenharmony_ci   util_blitter_default_src_texture(blitter, &src_templ, src, src_level);
2902bf215546Sopenharmony_ci   src_templ.format = util_format_stencil_only(src_templ.format);
2903bf215546Sopenharmony_ci   src_view = pipe->create_sampler_view(pipe, src, &src_templ);
2904bf215546Sopenharmony_ci
2905bf215546Sopenharmony_ci   /* bind states */
2906bf215546Sopenharmony_ci   pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA][0]);
2907bf215546Sopenharmony_ci   pipe->bind_fs_state(pipe,
2908bf215546Sopenharmony_ci      get_stencil_blit_fallback_fs(ctx, src->nr_samples > 1));
2909bf215546Sopenharmony_ci
2910bf215546Sopenharmony_ci   /* set a framebuffer state */
2911bf215546Sopenharmony_ci   struct pipe_framebuffer_state fb_state = { 0 };
2912bf215546Sopenharmony_ci   fb_state.width = dstbox->x + dstbox->width;
2913bf215546Sopenharmony_ci   fb_state.height = dstbox->y + dstbox->height;
2914bf215546Sopenharmony_ci   fb_state.zsbuf = dst_view;
2915bf215546Sopenharmony_ci   pipe->set_framebuffer_state(pipe, &fb_state);
2916bf215546Sopenharmony_ci   pipe->set_sample_mask(pipe, ~0);
2917bf215546Sopenharmony_ci   if (pipe->set_min_samples)
2918bf215546Sopenharmony_ci      pipe->set_min_samples(pipe, 1);
2919bf215546Sopenharmony_ci
2920bf215546Sopenharmony_ci   blitter_set_common_draw_rect_state(ctx, scissor != NULL,
2921bf215546Sopenharmony_ci      util_framebuffer_get_num_samples(&fb_state) > 1);
2922bf215546Sopenharmony_ci   blitter_set_dst_dimensions(ctx, dst_view->width, dst_view->height);
2923bf215546Sopenharmony_ci
2924bf215546Sopenharmony_ci   if (scissor) {
2925bf215546Sopenharmony_ci      pipe->clear_depth_stencil(pipe, dst_view, PIPE_CLEAR_STENCIL, 0.0, 0,
2926bf215546Sopenharmony_ci                                MAX2(dstbox->x, scissor->minx),
2927bf215546Sopenharmony_ci                                MAX2(dstbox->y, scissor->miny),
2928bf215546Sopenharmony_ci                                MIN2(dstbox->x + dstbox->width, scissor->maxx) - dstbox->x,
2929bf215546Sopenharmony_ci                                MIN2(dstbox->y + dstbox->height, scissor->maxy) - dstbox->y,
2930bf215546Sopenharmony_ci                                true);
2931bf215546Sopenharmony_ci      pipe->set_scissor_states(pipe, 0, 1, scissor);
2932bf215546Sopenharmony_ci   } else {
2933bf215546Sopenharmony_ci      pipe->clear_depth_stencil(pipe, dst_view, PIPE_CLEAR_STENCIL, 0.0, 0,
2934bf215546Sopenharmony_ci                                dstbox->x, dstbox->y,
2935bf215546Sopenharmony_ci                                dstbox->width, dstbox->height,
2936bf215546Sopenharmony_ci                                true);
2937bf215546Sopenharmony_ci   }
2938bf215546Sopenharmony_ci
2939bf215546Sopenharmony_ci   pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 1, 0, false, &src_view);
2940bf215546Sopenharmony_ci   pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0, 1, &ctx->sampler_state);
2941bf215546Sopenharmony_ci
2942bf215546Sopenharmony_ci   unsigned stencil_bits =
2943bf215546Sopenharmony_ci      util_format_get_component_bits(dst->format,
2944bf215546Sopenharmony_ci                                     UTIL_FORMAT_COLORSPACE_ZS, 1);
2945bf215546Sopenharmony_ci
2946bf215546Sopenharmony_ci   struct pipe_stencil_ref sr = { { (1u << stencil_bits) - 1 } };
2947bf215546Sopenharmony_ci   pipe->set_stencil_ref(pipe, sr);
2948bf215546Sopenharmony_ci
2949bf215546Sopenharmony_ci   union blitter_attrib coord;
2950bf215546Sopenharmony_ci   get_texcoords(src_view, src->width0, src->height0,
2951bf215546Sopenharmony_ci                 srcbox->x, srcbox->y,
2952bf215546Sopenharmony_ci                 srcbox->x + srcbox->width, srcbox->y + srcbox->height,
2953bf215546Sopenharmony_ci                 srcbox->z, 0, true,
2954bf215546Sopenharmony_ci                 &coord);
2955bf215546Sopenharmony_ci
2956bf215546Sopenharmony_ci   for (int i = 0; i < stencil_bits; ++i) {
2957bf215546Sopenharmony_ci      uint32_t mask = 1 << i;
2958bf215546Sopenharmony_ci      struct pipe_constant_buffer cb = {
2959bf215546Sopenharmony_ci         .user_buffer = &mask,
2960bf215546Sopenharmony_ci         .buffer_size = sizeof(mask),
2961bf215546Sopenharmony_ci      };
2962bf215546Sopenharmony_ci      pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, blitter->cb_slot,
2963bf215546Sopenharmony_ci                                false, &cb);
2964bf215546Sopenharmony_ci
2965bf215546Sopenharmony_ci      pipe->bind_depth_stencil_alpha_state(pipe,
2966bf215546Sopenharmony_ci         get_stencil_blit_fallback_dsa(ctx, i));
2967bf215546Sopenharmony_ci
2968bf215546Sopenharmony_ci      blitter->draw_rectangle(blitter, ctx->velem_state,
2969bf215546Sopenharmony_ci                              get_vs_passthrough_pos_generic,
2970bf215546Sopenharmony_ci                              dstbox->x, dstbox->y,
2971bf215546Sopenharmony_ci                              dstbox->x + dstbox->width,
2972bf215546Sopenharmony_ci                              dstbox->y + dstbox->height,
2973bf215546Sopenharmony_ci                              0, 1,
2974bf215546Sopenharmony_ci                              UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW,
2975bf215546Sopenharmony_ci                              &coord);
2976bf215546Sopenharmony_ci   }
2977bf215546Sopenharmony_ci
2978bf215546Sopenharmony_ci   if (scissor)
2979bf215546Sopenharmony_ci      pipe->set_scissor_states(pipe, 0, 1, &ctx->base.saved_scissor);
2980bf215546Sopenharmony_ci
2981bf215546Sopenharmony_ci   util_blitter_restore_vertex_states(blitter);
2982bf215546Sopenharmony_ci   util_blitter_restore_fragment_states(blitter);
2983bf215546Sopenharmony_ci   util_blitter_restore_textures_internal(blitter, 1);
2984bf215546Sopenharmony_ci   util_blitter_restore_fb_state(blitter);
2985bf215546Sopenharmony_ci   util_blitter_restore_render_cond(blitter);
2986bf215546Sopenharmony_ci   util_blitter_restore_constant_buffer_state(blitter);
2987bf215546Sopenharmony_ci   util_blitter_unset_running_flag(blitter);
2988bf215546Sopenharmony_ci
2989bf215546Sopenharmony_ci   pipe_surface_reference(&dst_view, NULL);
2990bf215546Sopenharmony_ci   pipe_sampler_view_reference(&src_view, NULL);
2991bf215546Sopenharmony_ci}
2992