1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "util/u_rect.h"
29bf215546Sopenharmony_ci#include "util/u_surface.h"
30bf215546Sopenharmony_ci#include "util/u_memset.h"
31bf215546Sopenharmony_ci#include "lp_context.h"
32bf215546Sopenharmony_ci#include "lp_flush.h"
33bf215546Sopenharmony_ci#include "lp_limits.h"
34bf215546Sopenharmony_ci#include "lp_surface.h"
35bf215546Sopenharmony_ci#include "lp_texture.h"
36bf215546Sopenharmony_ci#include "lp_query.h"
37bf215546Sopenharmony_ci#include "lp_rast.h"
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_cistatic void
40bf215546Sopenharmony_cilp_resource_copy_ms(struct pipe_context *pipe,
41bf215546Sopenharmony_ci                    struct pipe_resource *dst, unsigned dst_level,
42bf215546Sopenharmony_ci                    unsigned dstx, unsigned dsty, unsigned dstz,
43bf215546Sopenharmony_ci                    struct pipe_resource *src, unsigned src_level,
44bf215546Sopenharmony_ci                    const struct pipe_box *src_box)
45bf215546Sopenharmony_ci{
46bf215546Sopenharmony_ci   struct pipe_box dst_box = *src_box;
47bf215546Sopenharmony_ci   enum pipe_format src_format;
48bf215546Sopenharmony_ci   dst_box.x = dstx;
49bf215546Sopenharmony_ci   dst_box.y = dsty;
50bf215546Sopenharmony_ci   dst_box.z = dstz;
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   src_format = src->format;
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci   for (unsigned i = 0; i < MAX2(src->nr_samples, dst->nr_samples); i++) {
55bf215546Sopenharmony_ci      struct pipe_transfer *src_trans, *dst_trans;
56bf215546Sopenharmony_ci      const uint8_t *src_map = llvmpipe_transfer_map_ms(pipe,
57bf215546Sopenharmony_ci                                                        src, 0, PIPE_MAP_READ, MIN2(i, src->nr_samples - 1),
58bf215546Sopenharmony_ci                                                        src_box,
59bf215546Sopenharmony_ci                                                        &src_trans);
60bf215546Sopenharmony_ci      if (!src_map)
61bf215546Sopenharmony_ci         return;
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci      uint8_t *dst_map = llvmpipe_transfer_map_ms(pipe,
64bf215546Sopenharmony_ci                                                  dst, 0, PIPE_MAP_WRITE, i,
65bf215546Sopenharmony_ci                                                  &dst_box,
66bf215546Sopenharmony_ci                                                  &dst_trans);
67bf215546Sopenharmony_ci      if (!dst_map) {
68bf215546Sopenharmony_ci         pipe->texture_unmap(pipe, src_trans);
69bf215546Sopenharmony_ci         return;
70bf215546Sopenharmony_ci      }
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci      util_copy_box(dst_map,
73bf215546Sopenharmony_ci                    src_format,
74bf215546Sopenharmony_ci                    dst_trans->stride, dst_trans->layer_stride,
75bf215546Sopenharmony_ci                    0, 0, 0,
76bf215546Sopenharmony_ci                    src_box->width, src_box->height, src_box->depth,
77bf215546Sopenharmony_ci                    src_map,
78bf215546Sopenharmony_ci                    src_trans->stride, src_trans->layer_stride,
79bf215546Sopenharmony_ci                    0, 0, 0);
80bf215546Sopenharmony_ci      pipe->texture_unmap(pipe, dst_trans);
81bf215546Sopenharmony_ci      pipe->texture_unmap(pipe, src_trans);
82bf215546Sopenharmony_ci   }
83bf215546Sopenharmony_ci}
84bf215546Sopenharmony_cistatic void
85bf215546Sopenharmony_cilp_resource_copy(struct pipe_context *pipe,
86bf215546Sopenharmony_ci                 struct pipe_resource *dst, unsigned dst_level,
87bf215546Sopenharmony_ci                 unsigned dstx, unsigned dsty, unsigned dstz,
88bf215546Sopenharmony_ci                 struct pipe_resource *src, unsigned src_level,
89bf215546Sopenharmony_ci                 const struct pipe_box *src_box)
90bf215546Sopenharmony_ci{
91bf215546Sopenharmony_ci   llvmpipe_flush_resource(pipe,
92bf215546Sopenharmony_ci                           dst, dst_level,
93bf215546Sopenharmony_ci                           FALSE, /* read_only */
94bf215546Sopenharmony_ci                           TRUE, /* cpu_access */
95bf215546Sopenharmony_ci                           FALSE, /* do_not_block */
96bf215546Sopenharmony_ci                           "blit dest");
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci   llvmpipe_flush_resource(pipe,
99bf215546Sopenharmony_ci                           src, src_level,
100bf215546Sopenharmony_ci                           TRUE, /* read_only */
101bf215546Sopenharmony_ci                           TRUE, /* cpu_access */
102bf215546Sopenharmony_ci                           FALSE, /* do_not_block */
103bf215546Sopenharmony_ci                           "blit src");
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci   if (dst->nr_samples > 1 &&
106bf215546Sopenharmony_ci       (dst->nr_samples == src->nr_samples ||
107bf215546Sopenharmony_ci       (src->nr_samples == 1 && dst->nr_samples > 1))) {
108bf215546Sopenharmony_ci      lp_resource_copy_ms(pipe, dst, dst_level, dstx, dsty, dstz,
109bf215546Sopenharmony_ci                          src, src_level, src_box);
110bf215546Sopenharmony_ci      return;
111bf215546Sopenharmony_ci   }
112bf215546Sopenharmony_ci   util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
113bf215546Sopenharmony_ci                             src, src_level, src_box);
114bf215546Sopenharmony_ci}
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_cistatic void lp_blit(struct pipe_context *pipe,
118bf215546Sopenharmony_ci                    const struct pipe_blit_info *blit_info)
119bf215546Sopenharmony_ci{
120bf215546Sopenharmony_ci   struct llvmpipe_context *lp = llvmpipe_context(pipe);
121bf215546Sopenharmony_ci   struct pipe_blit_info info = *blit_info;
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci   if (blit_info->render_condition_enable && !llvmpipe_check_render_cond(lp))
124bf215546Sopenharmony_ci      return;
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci   if (util_try_blit_via_copy_region(pipe, &info, lp->render_cond_query != NULL)) {
127bf215546Sopenharmony_ci      return; /* done */
128bf215546Sopenharmony_ci   }
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci   if (blit_info->src.resource->format == blit_info->src.format &&
131bf215546Sopenharmony_ci       blit_info->dst.resource->format == blit_info->dst.format &&
132bf215546Sopenharmony_ci       blit_info->src.format == blit_info->dst.format &&
133bf215546Sopenharmony_ci       blit_info->src.resource->nr_samples > 1 &&
134bf215546Sopenharmony_ci       blit_info->dst.resource->nr_samples < 2 &&
135bf215546Sopenharmony_ci       blit_info->sample0_only) {
136bf215546Sopenharmony_ci      util_resource_copy_region(pipe, blit_info->dst.resource, blit_info->dst.level, blit_info->dst.box.x, blit_info->dst.box.y, blit_info->dst.box.z,
137bf215546Sopenharmony_ci                                blit_info->src.resource, blit_info->src.level, &blit_info->src.box);
138bf215546Sopenharmony_ci      return;
139bf215546Sopenharmony_ci   }
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci   if (!util_blitter_is_blit_supported(lp->blitter, &info)) {
142bf215546Sopenharmony_ci      debug_printf("llvmpipe: blit unsupported %s -> %s\n",
143bf215546Sopenharmony_ci                   util_format_short_name(info.src.resource->format),
144bf215546Sopenharmony_ci                   util_format_short_name(info.dst.resource->format));
145bf215546Sopenharmony_ci      return;
146bf215546Sopenharmony_ci   }
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci   /* for 32-bit unorm depth, avoid the conversions to float and back,
149bf215546Sopenharmony_ci      which can introduce accuracy errors. */
150bf215546Sopenharmony_ci   if (blit_info->src.format == PIPE_FORMAT_Z32_UNORM &&
151bf215546Sopenharmony_ci       blit_info->dst.format == PIPE_FORMAT_Z32_UNORM && info.filter == PIPE_TEX_FILTER_NEAREST) {
152bf215546Sopenharmony_ci      info.src.format = PIPE_FORMAT_R32_UINT;
153bf215546Sopenharmony_ci      info.dst.format = PIPE_FORMAT_R32_UINT;
154bf215546Sopenharmony_ci      info.mask = PIPE_MASK_R;
155bf215546Sopenharmony_ci   }
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   util_blitter_save_vertex_buffer_slot(lp->blitter, lp->vertex_buffer);
158bf215546Sopenharmony_ci   util_blitter_save_vertex_elements(lp->blitter, (void*)lp->velems);
159bf215546Sopenharmony_ci   util_blitter_save_vertex_shader(lp->blitter, (void*)lp->vs);
160bf215546Sopenharmony_ci   util_blitter_save_geometry_shader(lp->blitter, (void*)lp->gs);
161bf215546Sopenharmony_ci   util_blitter_save_so_targets(lp->blitter, lp->num_so_targets,
162bf215546Sopenharmony_ci                                (struct pipe_stream_output_target**)lp->so_targets);
163bf215546Sopenharmony_ci   util_blitter_save_rasterizer(lp->blitter, (void*)lp->rasterizer);
164bf215546Sopenharmony_ci   util_blitter_save_viewport(lp->blitter, &lp->viewports[0]);
165bf215546Sopenharmony_ci   util_blitter_save_scissor(lp->blitter, &lp->scissors[0]);
166bf215546Sopenharmony_ci   util_blitter_save_fragment_shader(lp->blitter, lp->fs);
167bf215546Sopenharmony_ci   util_blitter_save_blend(lp->blitter, (void*)lp->blend);
168bf215546Sopenharmony_ci   util_blitter_save_tessctrl_shader(lp->blitter, (void*)lp->tcs);
169bf215546Sopenharmony_ci   util_blitter_save_tesseval_shader(lp->blitter, (void*)lp->tes);
170bf215546Sopenharmony_ci   util_blitter_save_depth_stencil_alpha(lp->blitter, (void*)lp->depth_stencil);
171bf215546Sopenharmony_ci   util_blitter_save_stencil_ref(lp->blitter, &lp->stencil_ref);
172bf215546Sopenharmony_ci   util_blitter_save_sample_mask(lp->blitter, lp->sample_mask, lp->min_samples);
173bf215546Sopenharmony_ci   util_blitter_save_framebuffer(lp->blitter, &lp->framebuffer);
174bf215546Sopenharmony_ci   util_blitter_save_fragment_sampler_states(lp->blitter,
175bf215546Sopenharmony_ci                     lp->num_samplers[PIPE_SHADER_FRAGMENT],
176bf215546Sopenharmony_ci                     (void**)lp->samplers[PIPE_SHADER_FRAGMENT]);
177bf215546Sopenharmony_ci   util_blitter_save_fragment_sampler_views(lp->blitter,
178bf215546Sopenharmony_ci                     lp->num_sampler_views[PIPE_SHADER_FRAGMENT],
179bf215546Sopenharmony_ci                     lp->sampler_views[PIPE_SHADER_FRAGMENT]);
180bf215546Sopenharmony_ci   util_blitter_save_render_condition(lp->blitter, lp->render_cond_query,
181bf215546Sopenharmony_ci                                      lp->render_cond_cond, lp->render_cond_mode);
182bf215546Sopenharmony_ci   util_blitter_blit(lp->blitter, &info);
183bf215546Sopenharmony_ci}
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_cistatic void
187bf215546Sopenharmony_cilp_flush_resource(struct pipe_context *ctx, struct pipe_resource *resource)
188bf215546Sopenharmony_ci{
189bf215546Sopenharmony_ci   llvmpipe_flush_resource(ctx, resource, 0, true, true, false, "resource");
190bf215546Sopenharmony_ci}
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_cistatic struct pipe_surface *
194bf215546Sopenharmony_cillvmpipe_create_surface(struct pipe_context *pipe,
195bf215546Sopenharmony_ci                        struct pipe_resource *pt,
196bf215546Sopenharmony_ci                        const struct pipe_surface *surf_tmpl)
197bf215546Sopenharmony_ci{
198bf215546Sopenharmony_ci   struct pipe_surface *ps;
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci   if (!(pt->bind & (PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET))) {
201bf215546Sopenharmony_ci      debug_printf("Illegal surface creation without bind flag\n");
202bf215546Sopenharmony_ci      if (util_format_is_depth_or_stencil(surf_tmpl->format)) {
203bf215546Sopenharmony_ci         pt->bind |= PIPE_BIND_DEPTH_STENCIL;
204bf215546Sopenharmony_ci      }
205bf215546Sopenharmony_ci      else {
206bf215546Sopenharmony_ci         pt->bind |= PIPE_BIND_RENDER_TARGET;
207bf215546Sopenharmony_ci      }
208bf215546Sopenharmony_ci   }
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci   ps = CALLOC_STRUCT(pipe_surface);
211bf215546Sopenharmony_ci   if (ps) {
212bf215546Sopenharmony_ci      pipe_reference_init(&ps->reference, 1);
213bf215546Sopenharmony_ci      pipe_resource_reference(&ps->texture, pt);
214bf215546Sopenharmony_ci      ps->context = pipe;
215bf215546Sopenharmony_ci      ps->format = surf_tmpl->format;
216bf215546Sopenharmony_ci      if (llvmpipe_resource_is_texture(pt)) {
217bf215546Sopenharmony_ci         assert(surf_tmpl->u.tex.level <= pt->last_level);
218bf215546Sopenharmony_ci         assert(surf_tmpl->u.tex.first_layer <= surf_tmpl->u.tex.last_layer);
219bf215546Sopenharmony_ci         ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
220bf215546Sopenharmony_ci         ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
221bf215546Sopenharmony_ci         ps->u.tex.level = surf_tmpl->u.tex.level;
222bf215546Sopenharmony_ci         ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
223bf215546Sopenharmony_ci         ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
224bf215546Sopenharmony_ci      }
225bf215546Sopenharmony_ci      else {
226bf215546Sopenharmony_ci         /* setting width as number of elements should get us correct renderbuffer width */
227bf215546Sopenharmony_ci         ps->width = surf_tmpl->u.buf.last_element - surf_tmpl->u.buf.first_element + 1;
228bf215546Sopenharmony_ci         ps->height = pt->height0;
229bf215546Sopenharmony_ci         ps->u.buf.first_element = surf_tmpl->u.buf.first_element;
230bf215546Sopenharmony_ci         ps->u.buf.last_element = surf_tmpl->u.buf.last_element;
231bf215546Sopenharmony_ci         assert(ps->u.buf.first_element <= ps->u.buf.last_element);
232bf215546Sopenharmony_ci         assert(util_format_get_blocksize(surf_tmpl->format) *
233bf215546Sopenharmony_ci                (ps->u.buf.last_element + 1) <= pt->width0);
234bf215546Sopenharmony_ci      }
235bf215546Sopenharmony_ci   }
236bf215546Sopenharmony_ci   return ps;
237bf215546Sopenharmony_ci}
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_cistatic void
241bf215546Sopenharmony_cillvmpipe_surface_destroy(struct pipe_context *pipe,
242bf215546Sopenharmony_ci                         struct pipe_surface *surf)
243bf215546Sopenharmony_ci{
244bf215546Sopenharmony_ci   /* Effectively do the texture_update work here - if texture images
245bf215546Sopenharmony_ci    * needed post-processing to put them into hardware layout, this is
246bf215546Sopenharmony_ci    * where it would happen.  For llvmpipe, nothing to do.
247bf215546Sopenharmony_ci    */
248bf215546Sopenharmony_ci   assert(surf->texture);
249bf215546Sopenharmony_ci   pipe_resource_reference(&surf->texture, NULL);
250bf215546Sopenharmony_ci   FREE(surf);
251bf215546Sopenharmony_ci}
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_cistatic void
256bf215546Sopenharmony_cillvmpipe_get_sample_position(struct pipe_context *pipe,
257bf215546Sopenharmony_ci                             unsigned sample_count,
258bf215546Sopenharmony_ci                             unsigned sample_index,
259bf215546Sopenharmony_ci                             float *out_value)
260bf215546Sopenharmony_ci{
261bf215546Sopenharmony_ci   switch (sample_count) {
262bf215546Sopenharmony_ci   case 4:
263bf215546Sopenharmony_ci      out_value[0] = lp_sample_pos_4x[sample_index][0];
264bf215546Sopenharmony_ci      out_value[1] = lp_sample_pos_4x[sample_index][1];
265bf215546Sopenharmony_ci      break;
266bf215546Sopenharmony_ci   default:
267bf215546Sopenharmony_ci      break;
268bf215546Sopenharmony_ci   }
269bf215546Sopenharmony_ci}
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_cistatic void
272bf215546Sopenharmony_cilp_clear_color_texture_helper(struct pipe_transfer *dst_trans,
273bf215546Sopenharmony_ci                                ubyte *dst_map,
274bf215546Sopenharmony_ci                                enum pipe_format format,
275bf215546Sopenharmony_ci                                const union pipe_color_union *color,
276bf215546Sopenharmony_ci                                unsigned width, unsigned height, unsigned depth)
277bf215546Sopenharmony_ci{
278bf215546Sopenharmony_ci   union util_color uc;
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci   assert(dst_trans->stride > 0);
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_ci   util_pack_color_union(format, &uc, color);
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci   util_fill_box(dst_map, format,
285bf215546Sopenharmony_ci                 dst_trans->stride, dst_trans->layer_stride,
286bf215546Sopenharmony_ci                 0, 0, 0, width, height, depth, &uc);
287bf215546Sopenharmony_ci}
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_cistatic void
290bf215546Sopenharmony_cilp_clear_color_texture_msaa(struct pipe_context *pipe,
291bf215546Sopenharmony_ci                            struct pipe_resource *texture,
292bf215546Sopenharmony_ci                            enum pipe_format format,
293bf215546Sopenharmony_ci                            const union pipe_color_union *color,
294bf215546Sopenharmony_ci                            unsigned sample,
295bf215546Sopenharmony_ci                            const struct pipe_box *box)
296bf215546Sopenharmony_ci{
297bf215546Sopenharmony_ci   struct pipe_transfer *dst_trans;
298bf215546Sopenharmony_ci   ubyte *dst_map;
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_ci   dst_map = llvmpipe_transfer_map_ms(pipe, texture, 0, PIPE_MAP_WRITE,
301bf215546Sopenharmony_ci                                      sample, box, &dst_trans);
302bf215546Sopenharmony_ci   if (!dst_map)
303bf215546Sopenharmony_ci      return;
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci   if (dst_trans->stride > 0) {
306bf215546Sopenharmony_ci      lp_clear_color_texture_helper(dst_trans, dst_map, format, color,
307bf215546Sopenharmony_ci                                    box->width, box->height, box->depth);
308bf215546Sopenharmony_ci   }
309bf215546Sopenharmony_ci   pipe->texture_unmap(pipe, dst_trans);
310bf215546Sopenharmony_ci}
311bf215546Sopenharmony_ci
312bf215546Sopenharmony_cistatic void
313bf215546Sopenharmony_cillvmpipe_clear_render_target(struct pipe_context *pipe,
314bf215546Sopenharmony_ci                             struct pipe_surface *dst,
315bf215546Sopenharmony_ci                             const union pipe_color_union *color,
316bf215546Sopenharmony_ci                             unsigned dstx, unsigned dsty,
317bf215546Sopenharmony_ci                             unsigned width, unsigned height,
318bf215546Sopenharmony_ci                             bool render_condition_enabled)
319bf215546Sopenharmony_ci{
320bf215546Sopenharmony_ci   struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ci   if (render_condition_enabled && !llvmpipe_check_render_cond(llvmpipe))
323bf215546Sopenharmony_ci      return;
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ci   width = MIN2(width, dst->texture->width0 - dstx);
326bf215546Sopenharmony_ci   height = MIN2(height, dst->texture->height0 - dsty);
327bf215546Sopenharmony_ci
328bf215546Sopenharmony_ci   if (dst->texture->nr_samples > 1) {
329bf215546Sopenharmony_ci      struct pipe_box box;
330bf215546Sopenharmony_ci      u_box_2d(dstx, dsty, width, height, &box);
331bf215546Sopenharmony_ci      if (dst->texture->target != PIPE_BUFFER) {
332bf215546Sopenharmony_ci         box.z = dst->u.tex.first_layer;
333bf215546Sopenharmony_ci         box.depth = dst->u.tex.last_layer - dst->u.tex.first_layer + 1;
334bf215546Sopenharmony_ci      }
335bf215546Sopenharmony_ci      for (unsigned s = 0; s < util_res_sample_count(dst->texture); s++) {
336bf215546Sopenharmony_ci         lp_clear_color_texture_msaa(pipe, dst->texture, dst->format,
337bf215546Sopenharmony_ci                                     color, s, &box);
338bf215546Sopenharmony_ci      }
339bf215546Sopenharmony_ci   } else
340bf215546Sopenharmony_ci      util_clear_render_target(pipe, dst, color,
341bf215546Sopenharmony_ci                               dstx, dsty, width, height);
342bf215546Sopenharmony_ci}
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_cistatic void
346bf215546Sopenharmony_cilp_clear_depth_stencil_texture_msaa(struct pipe_context *pipe,
347bf215546Sopenharmony_ci                                    struct pipe_resource *texture,
348bf215546Sopenharmony_ci                                    enum pipe_format format,
349bf215546Sopenharmony_ci                                    unsigned clear_flags,
350bf215546Sopenharmony_ci                                    uint64_t zstencil, unsigned sample,
351bf215546Sopenharmony_ci                                    const struct pipe_box *box)
352bf215546Sopenharmony_ci{
353bf215546Sopenharmony_ci   struct pipe_transfer *dst_trans;
354bf215546Sopenharmony_ci   ubyte *dst_map;
355bf215546Sopenharmony_ci   boolean need_rmw = FALSE;
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_ci   if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) &&
358bf215546Sopenharmony_ci       ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
359bf215546Sopenharmony_ci       util_format_is_depth_and_stencil(format))
360bf215546Sopenharmony_ci      need_rmw = TRUE;
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_ci   dst_map = llvmpipe_transfer_map_ms(pipe,
363bf215546Sopenharmony_ci                                      texture,
364bf215546Sopenharmony_ci                                      0,
365bf215546Sopenharmony_ci                                      (need_rmw ? PIPE_MAP_READ_WRITE :
366bf215546Sopenharmony_ci                                       PIPE_MAP_WRITE),
367bf215546Sopenharmony_ci                                      sample, box, &dst_trans);
368bf215546Sopenharmony_ci   assert(dst_map);
369bf215546Sopenharmony_ci   if (!dst_map)
370bf215546Sopenharmony_ci      return;
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci   assert(dst_trans->stride > 0);
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_ci   util_fill_zs_box(dst_map, format, need_rmw, clear_flags,
375bf215546Sopenharmony_ci		    dst_trans->stride, dst_trans->layer_stride,
376bf215546Sopenharmony_ci		    box->width, box->height, box->depth, zstencil);
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci   pipe->texture_unmap(pipe, dst_trans);
379bf215546Sopenharmony_ci}
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_cistatic void
382bf215546Sopenharmony_cillvmpipe_clear_depth_stencil(struct pipe_context *pipe,
383bf215546Sopenharmony_ci                             struct pipe_surface *dst,
384bf215546Sopenharmony_ci                             unsigned clear_flags,
385bf215546Sopenharmony_ci                             double depth,
386bf215546Sopenharmony_ci                             unsigned stencil,
387bf215546Sopenharmony_ci                             unsigned dstx, unsigned dsty,
388bf215546Sopenharmony_ci                             unsigned width, unsigned height,
389bf215546Sopenharmony_ci                             bool render_condition_enabled)
390bf215546Sopenharmony_ci{
391bf215546Sopenharmony_ci   struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
392bf215546Sopenharmony_ci
393bf215546Sopenharmony_ci   if (render_condition_enabled && !llvmpipe_check_render_cond(llvmpipe))
394bf215546Sopenharmony_ci      return;
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ci   width = MIN2(width, dst->texture->width0 - dstx);
397bf215546Sopenharmony_ci   height = MIN2(height, dst->texture->height0 - dsty);
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci   if (dst->texture->nr_samples > 1) {
400bf215546Sopenharmony_ci      uint64_t zstencil = util_pack64_z_stencil(dst->format, depth, stencil);
401bf215546Sopenharmony_ci      struct pipe_box box;
402bf215546Sopenharmony_ci      u_box_2d(dstx, dsty, width, height, &box);
403bf215546Sopenharmony_ci      if (dst->texture->target != PIPE_BUFFER) {
404bf215546Sopenharmony_ci         box.z = dst->u.tex.first_layer;
405bf215546Sopenharmony_ci         box.depth = dst->u.tex.last_layer - dst->u.tex.first_layer + 1;
406bf215546Sopenharmony_ci      }
407bf215546Sopenharmony_ci      for (unsigned s = 0; s < util_res_sample_count(dst->texture); s++)
408bf215546Sopenharmony_ci         lp_clear_depth_stencil_texture_msaa(pipe, dst->texture,
409bf215546Sopenharmony_ci                                             dst->format, clear_flags,
410bf215546Sopenharmony_ci                                             zstencil, s, &box);
411bf215546Sopenharmony_ci   } else
412bf215546Sopenharmony_ci      util_clear_depth_stencil(pipe, dst, clear_flags,
413bf215546Sopenharmony_ci                               depth, stencil,
414bf215546Sopenharmony_ci                               dstx, dsty, width, height);
415bf215546Sopenharmony_ci}
416bf215546Sopenharmony_ci
417bf215546Sopenharmony_cistatic void
418bf215546Sopenharmony_cillvmpipe_clear_texture(struct pipe_context *pipe,
419bf215546Sopenharmony_ci                       struct pipe_resource *tex,
420bf215546Sopenharmony_ci                       unsigned level,
421bf215546Sopenharmony_ci                       const struct pipe_box *box,
422bf215546Sopenharmony_ci                       const void *data)
423bf215546Sopenharmony_ci{
424bf215546Sopenharmony_ci   const struct util_format_description *desc =
425bf215546Sopenharmony_ci          util_format_description(tex->format);
426bf215546Sopenharmony_ci   if (tex->nr_samples <= 1) {
427bf215546Sopenharmony_ci      util_clear_texture(pipe, tex, level, box, data);
428bf215546Sopenharmony_ci      return;
429bf215546Sopenharmony_ci   }
430bf215546Sopenharmony_ci   union pipe_color_union color;
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_ci   if (util_format_is_depth_or_stencil(tex->format)) {
433bf215546Sopenharmony_ci      unsigned clear = 0;
434bf215546Sopenharmony_ci      float depth = 0.0f;
435bf215546Sopenharmony_ci      uint8_t stencil = 0;
436bf215546Sopenharmony_ci      uint64_t zstencil;
437bf215546Sopenharmony_ci
438bf215546Sopenharmony_ci      if (util_format_has_depth(desc)) {
439bf215546Sopenharmony_ci         clear |= PIPE_CLEAR_DEPTH;
440bf215546Sopenharmony_ci         util_format_unpack_z_float(tex->format, &depth, data, 1);
441bf215546Sopenharmony_ci      }
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_ci      if (util_format_has_stencil(desc)) {
444bf215546Sopenharmony_ci         clear |= PIPE_CLEAR_STENCIL;
445bf215546Sopenharmony_ci         util_format_unpack_s_8uint(tex->format, &stencil, data, 1);
446bf215546Sopenharmony_ci      }
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_ci      zstencil = util_pack64_z_stencil(tex->format, depth, stencil);
449bf215546Sopenharmony_ci
450bf215546Sopenharmony_ci      for (unsigned s = 0; s < util_res_sample_count(tex); s++)
451bf215546Sopenharmony_ci         lp_clear_depth_stencil_texture_msaa(pipe, tex, tex->format, clear, zstencil,
452bf215546Sopenharmony_ci                                             s, box);
453bf215546Sopenharmony_ci   } else {
454bf215546Sopenharmony_ci      util_format_unpack_rgba(tex->format, color.ui, data, 1);
455bf215546Sopenharmony_ci
456bf215546Sopenharmony_ci      for (unsigned s = 0; s < util_res_sample_count(tex); s++) {
457bf215546Sopenharmony_ci         lp_clear_color_texture_msaa(pipe, tex, tex->format, &color, s,
458bf215546Sopenharmony_ci                                     box);
459bf215546Sopenharmony_ci      }
460bf215546Sopenharmony_ci   }
461bf215546Sopenharmony_ci}
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_cistatic void
464bf215546Sopenharmony_cillvmpipe_clear_buffer(struct pipe_context *pipe,
465bf215546Sopenharmony_ci                      struct pipe_resource *res,
466bf215546Sopenharmony_ci                      unsigned offset,
467bf215546Sopenharmony_ci                      unsigned size,
468bf215546Sopenharmony_ci                      const void *clear_value,
469bf215546Sopenharmony_ci                      int clear_value_size)
470bf215546Sopenharmony_ci{
471bf215546Sopenharmony_ci   struct pipe_transfer *dst_t;
472bf215546Sopenharmony_ci   struct pipe_box box;
473bf215546Sopenharmony_ci   char *dst;
474bf215546Sopenharmony_ci   u_box_1d(offset, size, &box);
475bf215546Sopenharmony_ci
476bf215546Sopenharmony_ci   dst = pipe->buffer_map(pipe,
477bf215546Sopenharmony_ci                            res,
478bf215546Sopenharmony_ci                            0,
479bf215546Sopenharmony_ci                            PIPE_MAP_WRITE,
480bf215546Sopenharmony_ci                            &box,
481bf215546Sopenharmony_ci                            &dst_t);
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci   switch (clear_value_size) {
484bf215546Sopenharmony_ci   case 1:
485bf215546Sopenharmony_ci      memset(dst, *(uint8_t *)clear_value, size);
486bf215546Sopenharmony_ci      break;
487bf215546Sopenharmony_ci   case 4:
488bf215546Sopenharmony_ci      util_memset32(dst, *(uint32_t *)clear_value, size / 4);
489bf215546Sopenharmony_ci      break;
490bf215546Sopenharmony_ci   default:
491bf215546Sopenharmony_ci      for (unsigned i = 0; i < size; i += clear_value_size)
492bf215546Sopenharmony_ci         memcpy(&dst[i], clear_value, clear_value_size);
493bf215546Sopenharmony_ci      break;
494bf215546Sopenharmony_ci   }
495bf215546Sopenharmony_ci   pipe->buffer_unmap(pipe, dst_t);
496bf215546Sopenharmony_ci}
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_civoid
499bf215546Sopenharmony_cillvmpipe_init_surface_functions(struct llvmpipe_context *lp)
500bf215546Sopenharmony_ci{
501bf215546Sopenharmony_ci   lp->pipe.clear_render_target = llvmpipe_clear_render_target;
502bf215546Sopenharmony_ci   lp->pipe.clear_depth_stencil = llvmpipe_clear_depth_stencil;
503bf215546Sopenharmony_ci   lp->pipe.create_surface = llvmpipe_create_surface;
504bf215546Sopenharmony_ci   lp->pipe.surface_destroy = llvmpipe_surface_destroy;
505bf215546Sopenharmony_ci   /* These are not actually functions dealing with surfaces */
506bf215546Sopenharmony_ci   lp->pipe.clear_texture = llvmpipe_clear_texture;
507bf215546Sopenharmony_ci   lp->pipe.clear_buffer = llvmpipe_clear_buffer;
508bf215546Sopenharmony_ci   lp->pipe.resource_copy_region = lp_resource_copy;
509bf215546Sopenharmony_ci   lp->pipe.blit = lp_blit;
510bf215546Sopenharmony_ci   lp->pipe.flush_resource = lp_flush_resource;
511bf215546Sopenharmony_ci   lp->pipe.get_sample_position = llvmpipe_get_sample_position;
512bf215546Sopenharmony_ci}
513