1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2009 VMware, Inc.  All Rights Reserved.
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 * Surface utility functions.
30bf215546Sopenharmony_ci *
31bf215546Sopenharmony_ci * @author Brian Paul
32bf215546Sopenharmony_ci */
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include "pipe/p_defines.h"
36bf215546Sopenharmony_ci#include "pipe/p_screen.h"
37bf215546Sopenharmony_ci#include "pipe/p_state.h"
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci#include "util/format/u_format.h"
40bf215546Sopenharmony_ci#include "util/u_inlines.h"
41bf215546Sopenharmony_ci#include "util/u_rect.h"
42bf215546Sopenharmony_ci#include "util/u_surface.h"
43bf215546Sopenharmony_ci#include "util/u_pack_color.h"
44bf215546Sopenharmony_ci#include "util/u_memset.h"
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci/**
47bf215546Sopenharmony_ci * Initialize a pipe_surface object.  'view' is considered to have
48bf215546Sopenharmony_ci * uninitialized contents.
49bf215546Sopenharmony_ci */
50bf215546Sopenharmony_civoid
51bf215546Sopenharmony_ciu_surface_default_template(struct pipe_surface *surf,
52bf215546Sopenharmony_ci                           const struct pipe_resource *texture)
53bf215546Sopenharmony_ci{
54bf215546Sopenharmony_ci   memset(surf, 0, sizeof(*surf));
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci   surf->format = texture->format;
57bf215546Sopenharmony_ci}
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci/**
61bf215546Sopenharmony_ci * Copy 3D box from one place to another.
62bf215546Sopenharmony_ci * Position and sizes are in pixels.
63bf215546Sopenharmony_ci */
64bf215546Sopenharmony_civoid
65bf215546Sopenharmony_ciutil_copy_box(ubyte * dst,
66bf215546Sopenharmony_ci              enum pipe_format format,
67bf215546Sopenharmony_ci              unsigned dst_stride, unsigned dst_slice_stride,
68bf215546Sopenharmony_ci              unsigned dst_x, unsigned dst_y, unsigned dst_z,
69bf215546Sopenharmony_ci              unsigned width, unsigned height, unsigned depth,
70bf215546Sopenharmony_ci              const ubyte * src,
71bf215546Sopenharmony_ci              int src_stride, unsigned src_slice_stride,
72bf215546Sopenharmony_ci              unsigned src_x, unsigned src_y, unsigned src_z)
73bf215546Sopenharmony_ci{
74bf215546Sopenharmony_ci   unsigned z;
75bf215546Sopenharmony_ci   dst += dst_z * dst_slice_stride;
76bf215546Sopenharmony_ci   src += src_z * src_slice_stride;
77bf215546Sopenharmony_ci   for (z = 0; z < depth; ++z) {
78bf215546Sopenharmony_ci      util_copy_rect(dst,
79bf215546Sopenharmony_ci                     format,
80bf215546Sopenharmony_ci                     dst_stride,
81bf215546Sopenharmony_ci                     dst_x, dst_y,
82bf215546Sopenharmony_ci                     width, height,
83bf215546Sopenharmony_ci                     src,
84bf215546Sopenharmony_ci                     src_stride,
85bf215546Sopenharmony_ci                     src_x, src_y);
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci      dst += dst_slice_stride;
88bf215546Sopenharmony_ci      src += src_slice_stride;
89bf215546Sopenharmony_ci   }
90bf215546Sopenharmony_ci}
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_civoid
94bf215546Sopenharmony_ciutil_fill_rect(ubyte * dst,
95bf215546Sopenharmony_ci               enum pipe_format format,
96bf215546Sopenharmony_ci               unsigned dst_stride,
97bf215546Sopenharmony_ci               unsigned dst_x,
98bf215546Sopenharmony_ci               unsigned dst_y,
99bf215546Sopenharmony_ci               unsigned width,
100bf215546Sopenharmony_ci               unsigned height,
101bf215546Sopenharmony_ci               union util_color *uc)
102bf215546Sopenharmony_ci{
103bf215546Sopenharmony_ci   const struct util_format_description *desc = util_format_description(format);
104bf215546Sopenharmony_ci   unsigned i, j;
105bf215546Sopenharmony_ci   unsigned width_size;
106bf215546Sopenharmony_ci   int blocksize = desc->block.bits / 8;
107bf215546Sopenharmony_ci   int blockwidth = desc->block.width;
108bf215546Sopenharmony_ci   int blockheight = desc->block.height;
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci   assert(blocksize > 0);
111bf215546Sopenharmony_ci   assert(blockwidth > 0);
112bf215546Sopenharmony_ci   assert(blockheight > 0);
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci   dst_x /= blockwidth;
115bf215546Sopenharmony_ci   dst_y /= blockheight;
116bf215546Sopenharmony_ci   width = (width + blockwidth - 1)/blockwidth;
117bf215546Sopenharmony_ci   height = (height + blockheight - 1)/blockheight;
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci   dst += dst_x * blocksize;
120bf215546Sopenharmony_ci   dst += dst_y * dst_stride;
121bf215546Sopenharmony_ci   width_size = width * blocksize;
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci   switch (blocksize) {
124bf215546Sopenharmony_ci   case 1:
125bf215546Sopenharmony_ci      if(dst_stride == width_size)
126bf215546Sopenharmony_ci         memset(dst, uc->ub, height * width_size);
127bf215546Sopenharmony_ci      else {
128bf215546Sopenharmony_ci         for (i = 0; i < height; i++) {
129bf215546Sopenharmony_ci            memset(dst, uc->ub, width_size);
130bf215546Sopenharmony_ci            dst += dst_stride;
131bf215546Sopenharmony_ci         }
132bf215546Sopenharmony_ci      }
133bf215546Sopenharmony_ci      break;
134bf215546Sopenharmony_ci   case 2:
135bf215546Sopenharmony_ci      for (i = 0; i < height; i++) {
136bf215546Sopenharmony_ci         uint16_t *row = (uint16_t *)dst;
137bf215546Sopenharmony_ci         for (j = 0; j < width; j++)
138bf215546Sopenharmony_ci            *row++ = uc->us;
139bf215546Sopenharmony_ci         dst += dst_stride;
140bf215546Sopenharmony_ci      }
141bf215546Sopenharmony_ci      break;
142bf215546Sopenharmony_ci   case 4:
143bf215546Sopenharmony_ci      for (i = 0; i < height; i++) {
144bf215546Sopenharmony_ci         util_memset32(dst, uc->ui[0], width);
145bf215546Sopenharmony_ci         dst += dst_stride;
146bf215546Sopenharmony_ci      }
147bf215546Sopenharmony_ci      break;
148bf215546Sopenharmony_ci   case 8:
149bf215546Sopenharmony_ci      for (i = 0; i < height; i++) {
150bf215546Sopenharmony_ci         util_memset64(dst, ((uint64_t *)uc)[0], width);
151bf215546Sopenharmony_ci         dst += dst_stride;
152bf215546Sopenharmony_ci      }
153bf215546Sopenharmony_ci      break;
154bf215546Sopenharmony_ci   default:
155bf215546Sopenharmony_ci      for (i = 0; i < height; i++) {
156bf215546Sopenharmony_ci         ubyte *row = dst;
157bf215546Sopenharmony_ci         for (j = 0; j < width; j++) {
158bf215546Sopenharmony_ci            memcpy(row, uc, blocksize);
159bf215546Sopenharmony_ci            row += blocksize;
160bf215546Sopenharmony_ci         }
161bf215546Sopenharmony_ci         dst += dst_stride;
162bf215546Sopenharmony_ci      }
163bf215546Sopenharmony_ci      break;
164bf215546Sopenharmony_ci   }
165bf215546Sopenharmony_ci}
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_civoid
169bf215546Sopenharmony_ciutil_fill_box(ubyte * dst,
170bf215546Sopenharmony_ci              enum pipe_format format,
171bf215546Sopenharmony_ci              unsigned stride,
172bf215546Sopenharmony_ci              unsigned layer_stride,
173bf215546Sopenharmony_ci              unsigned x,
174bf215546Sopenharmony_ci              unsigned y,
175bf215546Sopenharmony_ci              unsigned z,
176bf215546Sopenharmony_ci              unsigned width,
177bf215546Sopenharmony_ci              unsigned height,
178bf215546Sopenharmony_ci              unsigned depth,
179bf215546Sopenharmony_ci              union util_color *uc)
180bf215546Sopenharmony_ci{
181bf215546Sopenharmony_ci   unsigned layer;
182bf215546Sopenharmony_ci   dst += z * layer_stride;
183bf215546Sopenharmony_ci   for (layer = z; layer < depth; layer++) {
184bf215546Sopenharmony_ci      util_fill_rect(dst, format,
185bf215546Sopenharmony_ci                     stride,
186bf215546Sopenharmony_ci                     x, y, width, height, uc);
187bf215546Sopenharmony_ci      dst += layer_stride;
188bf215546Sopenharmony_ci   }
189bf215546Sopenharmony_ci}
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_ci/**
193bf215546Sopenharmony_ci * Fallback function for pipe->resource_copy_region().
194bf215546Sopenharmony_ci * We support copying between different formats (including compressed/
195bf215546Sopenharmony_ci * uncompressed) if the bytes per block or pixel matches.  If copying
196bf215546Sopenharmony_ci * compressed -> uncompressed, the dst region is reduced by the block
197bf215546Sopenharmony_ci * width, height.  If copying uncompressed -> compressed, the dest region
198bf215546Sopenharmony_ci * is expanded by the block width, height.  See GL_ARB_copy_image.
199bf215546Sopenharmony_ci * Note: (X,Y)=(0,0) is always the upper-left corner.
200bf215546Sopenharmony_ci */
201bf215546Sopenharmony_civoid
202bf215546Sopenharmony_ciutil_resource_copy_region(struct pipe_context *pipe,
203bf215546Sopenharmony_ci                          struct pipe_resource *dst,
204bf215546Sopenharmony_ci                          unsigned dst_level,
205bf215546Sopenharmony_ci                          unsigned dst_x, unsigned dst_y, unsigned dst_z,
206bf215546Sopenharmony_ci                          struct pipe_resource *src,
207bf215546Sopenharmony_ci                          unsigned src_level,
208bf215546Sopenharmony_ci                          const struct pipe_box *src_box_in)
209bf215546Sopenharmony_ci{
210bf215546Sopenharmony_ci   struct pipe_transfer *src_trans, *dst_trans;
211bf215546Sopenharmony_ci   uint8_t *dst_map;
212bf215546Sopenharmony_ci   const uint8_t *src_map;
213bf215546Sopenharmony_ci   enum pipe_format src_format;
214bf215546Sopenharmony_ci   enum pipe_format dst_format;
215bf215546Sopenharmony_ci   struct pipe_box src_box, dst_box;
216bf215546Sopenharmony_ci   unsigned src_bs, dst_bs, src_bw, dst_bw, src_bh, dst_bh;
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci   assert(src && dst);
219bf215546Sopenharmony_ci   if (!src || !dst)
220bf215546Sopenharmony_ci      return;
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_ci   assert((src->target == PIPE_BUFFER && dst->target == PIPE_BUFFER) ||
223bf215546Sopenharmony_ci          (src->target != PIPE_BUFFER && dst->target != PIPE_BUFFER));
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci   src_format = src->format;
226bf215546Sopenharmony_ci   dst_format = dst->format;
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci   /* init src box */
229bf215546Sopenharmony_ci   src_box = *src_box_in;
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci   /* init dst box */
232bf215546Sopenharmony_ci   dst_box.x = dst_x;
233bf215546Sopenharmony_ci   dst_box.y = dst_y;
234bf215546Sopenharmony_ci   dst_box.z = dst_z;
235bf215546Sopenharmony_ci   dst_box.width  = src_box.width;
236bf215546Sopenharmony_ci   dst_box.height = src_box.height;
237bf215546Sopenharmony_ci   dst_box.depth  = src_box.depth;
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci   src_bs = util_format_get_blocksize(src_format);
240bf215546Sopenharmony_ci   src_bw = util_format_get_blockwidth(src_format);
241bf215546Sopenharmony_ci   src_bh = util_format_get_blockheight(src_format);
242bf215546Sopenharmony_ci   dst_bs = util_format_get_blocksize(dst_format);
243bf215546Sopenharmony_ci   dst_bw = util_format_get_blockwidth(dst_format);
244bf215546Sopenharmony_ci   dst_bh = util_format_get_blockheight(dst_format);
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci   /* Note: all box positions and sizes are in pixels */
247bf215546Sopenharmony_ci   if (src_bw > 1 && dst_bw == 1) {
248bf215546Sopenharmony_ci      /* Copy from compressed to uncompressed.
249bf215546Sopenharmony_ci       * Shrink dest box by the src block size.
250bf215546Sopenharmony_ci       */
251bf215546Sopenharmony_ci      dst_box.width /= src_bw;
252bf215546Sopenharmony_ci      dst_box.height /= src_bh;
253bf215546Sopenharmony_ci   }
254bf215546Sopenharmony_ci   else if (src_bw == 1 && dst_bw > 1) {
255bf215546Sopenharmony_ci      /* Copy from uncompressed to compressed.
256bf215546Sopenharmony_ci       * Expand dest box by the dest block size.
257bf215546Sopenharmony_ci       */
258bf215546Sopenharmony_ci      dst_box.width *= dst_bw;
259bf215546Sopenharmony_ci      dst_box.height *= dst_bh;
260bf215546Sopenharmony_ci   }
261bf215546Sopenharmony_ci   else {
262bf215546Sopenharmony_ci      /* compressed -> compressed or uncompressed -> uncompressed copy */
263bf215546Sopenharmony_ci      assert(src_bw == dst_bw);
264bf215546Sopenharmony_ci      assert(src_bh == dst_bh);
265bf215546Sopenharmony_ci   }
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci   assert(src_bs == dst_bs);
268bf215546Sopenharmony_ci   if (src_bs != dst_bs) {
269bf215546Sopenharmony_ci      /* This can happen if we fail to do format checking before hand.
270bf215546Sopenharmony_ci       * Don't crash below.
271bf215546Sopenharmony_ci       */
272bf215546Sopenharmony_ci      return;
273bf215546Sopenharmony_ci   }
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci   /* check that region boxes are block aligned */
276bf215546Sopenharmony_ci   assert(src_box.x % src_bw == 0);
277bf215546Sopenharmony_ci   assert(src_box.y % src_bh == 0);
278bf215546Sopenharmony_ci   assert(dst_box.x % dst_bw == 0);
279bf215546Sopenharmony_ci   assert(dst_box.y % dst_bh == 0);
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci   /* check that region boxes are not out of bounds */
282bf215546Sopenharmony_ci   assert(src_box.x + src_box.width <= (int)u_minify(src->width0, src_level));
283bf215546Sopenharmony_ci   assert(src_box.y + src_box.height <= (int)u_minify(src->height0, src_level));
284bf215546Sopenharmony_ci   assert(dst_box.x + dst_box.width <= (int)u_minify(dst->width0, dst_level));
285bf215546Sopenharmony_ci   assert(dst_box.y + dst_box.height <= (int)u_minify(dst->height0, dst_level));
286bf215546Sopenharmony_ci
287bf215546Sopenharmony_ci   /* check that total number of src, dest bytes match */
288bf215546Sopenharmony_ci   assert((src_box.width / src_bw) * (src_box.height / src_bh) * src_bs ==
289bf215546Sopenharmony_ci          (dst_box.width / dst_bw) * (dst_box.height / dst_bh) * dst_bs);
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci   if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
292bf215546Sopenharmony_ci      src_map = pipe->buffer_map(pipe,
293bf215546Sopenharmony_ci                                   src,
294bf215546Sopenharmony_ci                                   src_level,
295bf215546Sopenharmony_ci                                   PIPE_MAP_READ,
296bf215546Sopenharmony_ci                                   &src_box, &src_trans);
297bf215546Sopenharmony_ci      assert(src_map);
298bf215546Sopenharmony_ci      if (!src_map) {
299bf215546Sopenharmony_ci         goto no_src_map_buf;
300bf215546Sopenharmony_ci      }
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci      dst_map = pipe->buffer_map(pipe,
303bf215546Sopenharmony_ci                                   dst,
304bf215546Sopenharmony_ci                                   dst_level,
305bf215546Sopenharmony_ci                                   PIPE_MAP_WRITE |
306bf215546Sopenharmony_ci                                   PIPE_MAP_DISCARD_RANGE, &dst_box,
307bf215546Sopenharmony_ci                                   &dst_trans);
308bf215546Sopenharmony_ci      assert(dst_map);
309bf215546Sopenharmony_ci      if (!dst_map) {
310bf215546Sopenharmony_ci         goto no_dst_map_buf;
311bf215546Sopenharmony_ci      }
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci      assert(src_box.height == 1);
314bf215546Sopenharmony_ci      assert(src_box.depth == 1);
315bf215546Sopenharmony_ci      memcpy(dst_map, src_map, src_box.width);
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci      pipe->buffer_unmap(pipe, dst_trans);
318bf215546Sopenharmony_ci   no_dst_map_buf:
319bf215546Sopenharmony_ci      pipe->buffer_unmap(pipe, src_trans);
320bf215546Sopenharmony_ci   no_src_map_buf:
321bf215546Sopenharmony_ci      ;
322bf215546Sopenharmony_ci   } else {
323bf215546Sopenharmony_ci      src_map = pipe->texture_map(pipe,
324bf215546Sopenharmony_ci                                   src,
325bf215546Sopenharmony_ci                                   src_level,
326bf215546Sopenharmony_ci                                   PIPE_MAP_READ,
327bf215546Sopenharmony_ci                                   &src_box, &src_trans);
328bf215546Sopenharmony_ci      assert(src_map);
329bf215546Sopenharmony_ci      if (!src_map) {
330bf215546Sopenharmony_ci         goto no_src_map;
331bf215546Sopenharmony_ci      }
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_ci      dst_map = pipe->texture_map(pipe,
334bf215546Sopenharmony_ci                                   dst,
335bf215546Sopenharmony_ci                                   dst_level,
336bf215546Sopenharmony_ci                                   PIPE_MAP_WRITE |
337bf215546Sopenharmony_ci                                   PIPE_MAP_DISCARD_RANGE, &dst_box,
338bf215546Sopenharmony_ci                                   &dst_trans);
339bf215546Sopenharmony_ci      assert(dst_map);
340bf215546Sopenharmony_ci      if (!dst_map) {
341bf215546Sopenharmony_ci         goto no_dst_map;
342bf215546Sopenharmony_ci      }
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci      util_copy_box(dst_map,
345bf215546Sopenharmony_ci                    src_format,
346bf215546Sopenharmony_ci                    dst_trans->stride, dst_trans->layer_stride,
347bf215546Sopenharmony_ci                    0, 0, 0,
348bf215546Sopenharmony_ci                    src_box.width, src_box.height, src_box.depth,
349bf215546Sopenharmony_ci                    src_map,
350bf215546Sopenharmony_ci                    src_trans->stride, src_trans->layer_stride,
351bf215546Sopenharmony_ci                    0, 0, 0);
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_ci      pipe->texture_unmap(pipe, dst_trans);
354bf215546Sopenharmony_ci   no_dst_map:
355bf215546Sopenharmony_ci      pipe->texture_unmap(pipe, src_trans);
356bf215546Sopenharmony_ci   no_src_map:
357bf215546Sopenharmony_ci      ;
358bf215546Sopenharmony_ci   }
359bf215546Sopenharmony_ci}
360bf215546Sopenharmony_ci
361bf215546Sopenharmony_cistatic void
362bf215546Sopenharmony_ciutil_clear_color_texture_helper(struct pipe_transfer *dst_trans,
363bf215546Sopenharmony_ci                                ubyte *dst_map,
364bf215546Sopenharmony_ci                                enum pipe_format format,
365bf215546Sopenharmony_ci                                const union pipe_color_union *color,
366bf215546Sopenharmony_ci                                unsigned width, unsigned height, unsigned depth)
367bf215546Sopenharmony_ci{
368bf215546Sopenharmony_ci   union util_color uc;
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci   assert(dst_trans->stride > 0);
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci   util_pack_color_union(format, &uc, color);
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_ci   util_fill_box(dst_map, format,
375bf215546Sopenharmony_ci                 dst_trans->stride, dst_trans->layer_stride,
376bf215546Sopenharmony_ci                 0, 0, 0, width, height, depth, &uc);
377bf215546Sopenharmony_ci}
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_cistatic void
380bf215546Sopenharmony_ciutil_clear_color_texture(struct pipe_context *pipe,
381bf215546Sopenharmony_ci                         struct pipe_resource *texture,
382bf215546Sopenharmony_ci                         enum pipe_format format,
383bf215546Sopenharmony_ci                         const union pipe_color_union *color,
384bf215546Sopenharmony_ci                         unsigned level,
385bf215546Sopenharmony_ci                         unsigned dstx, unsigned dsty, unsigned dstz,
386bf215546Sopenharmony_ci                         unsigned width, unsigned height, unsigned depth)
387bf215546Sopenharmony_ci{
388bf215546Sopenharmony_ci   struct pipe_transfer *dst_trans;
389bf215546Sopenharmony_ci   ubyte *dst_map;
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci   dst_map = pipe_texture_map_3d(pipe,
392bf215546Sopenharmony_ci                                  texture,
393bf215546Sopenharmony_ci                                  level,
394bf215546Sopenharmony_ci                                  PIPE_MAP_WRITE,
395bf215546Sopenharmony_ci                                  dstx, dsty, dstz,
396bf215546Sopenharmony_ci                                  width, height, depth,
397bf215546Sopenharmony_ci                                  &dst_trans);
398bf215546Sopenharmony_ci   if (!dst_map)
399bf215546Sopenharmony_ci      return;
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci   if (dst_trans->stride > 0) {
402bf215546Sopenharmony_ci      util_clear_color_texture_helper(dst_trans, dst_map, format, color,
403bf215546Sopenharmony_ci                                      width, height, depth);
404bf215546Sopenharmony_ci   }
405bf215546Sopenharmony_ci   pipe->texture_unmap(pipe, dst_trans);
406bf215546Sopenharmony_ci}
407bf215546Sopenharmony_ci
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8))
410bf215546Sopenharmony_ci
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci/**
413bf215546Sopenharmony_ci * Fallback for pipe->clear_render_target() function.
414bf215546Sopenharmony_ci * XXX this looks too hackish to be really useful.
415bf215546Sopenharmony_ci * cpp > 4 looks like a gross hack at best...
416bf215546Sopenharmony_ci * Plus can't use these transfer fallbacks when clearing
417bf215546Sopenharmony_ci * multisampled surfaces for instance.
418bf215546Sopenharmony_ci * Clears all bound layers.
419bf215546Sopenharmony_ci */
420bf215546Sopenharmony_civoid
421bf215546Sopenharmony_ciutil_clear_render_target(struct pipe_context *pipe,
422bf215546Sopenharmony_ci                         struct pipe_surface *dst,
423bf215546Sopenharmony_ci                         const union pipe_color_union *color,
424bf215546Sopenharmony_ci                         unsigned dstx, unsigned dsty,
425bf215546Sopenharmony_ci                         unsigned width, unsigned height)
426bf215546Sopenharmony_ci{
427bf215546Sopenharmony_ci   struct pipe_transfer *dst_trans;
428bf215546Sopenharmony_ci   ubyte *dst_map;
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_ci   assert(dst->texture);
431bf215546Sopenharmony_ci   if (!dst->texture)
432bf215546Sopenharmony_ci      return;
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci   if (dst->texture->target == PIPE_BUFFER) {
435bf215546Sopenharmony_ci      /*
436bf215546Sopenharmony_ci       * The fill naturally works on the surface format, however
437bf215546Sopenharmony_ci       * the transfer uses resource format which is just bytes for buffers.
438bf215546Sopenharmony_ci       */
439bf215546Sopenharmony_ci      unsigned dx, w;
440bf215546Sopenharmony_ci      unsigned pixstride = util_format_get_blocksize(dst->format);
441bf215546Sopenharmony_ci      dx = (dst->u.buf.first_element + dstx) * pixstride;
442bf215546Sopenharmony_ci      w = width * pixstride;
443bf215546Sopenharmony_ci      dst_map = pipe_texture_map(pipe,
444bf215546Sopenharmony_ci                                  dst->texture,
445bf215546Sopenharmony_ci                                  0, 0,
446bf215546Sopenharmony_ci                                  PIPE_MAP_WRITE,
447bf215546Sopenharmony_ci                                  dx, 0, w, 1,
448bf215546Sopenharmony_ci                                  &dst_trans);
449bf215546Sopenharmony_ci      if (dst_map) {
450bf215546Sopenharmony_ci         util_clear_color_texture_helper(dst_trans, dst_map, dst->format,
451bf215546Sopenharmony_ci                                         color, width, height, 1);
452bf215546Sopenharmony_ci         pipe->texture_unmap(pipe, dst_trans);
453bf215546Sopenharmony_ci      }
454bf215546Sopenharmony_ci   }
455bf215546Sopenharmony_ci   else {
456bf215546Sopenharmony_ci      unsigned depth = dst->u.tex.last_layer - dst->u.tex.first_layer + 1;
457bf215546Sopenharmony_ci      util_clear_color_texture(pipe, dst->texture, dst->format, color,
458bf215546Sopenharmony_ci                               dst->u.tex.level, dstx, dsty,
459bf215546Sopenharmony_ci                               dst->u.tex.first_layer, width, height, depth);
460bf215546Sopenharmony_ci   }
461bf215546Sopenharmony_ci}
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_cistatic void
464bf215546Sopenharmony_ciutil_fill_zs_rect(ubyte *dst_map,
465bf215546Sopenharmony_ci                  enum pipe_format format,
466bf215546Sopenharmony_ci                  bool need_rmw,
467bf215546Sopenharmony_ci                  unsigned clear_flags,
468bf215546Sopenharmony_ci                  unsigned dst_stride,
469bf215546Sopenharmony_ci                  unsigned width,
470bf215546Sopenharmony_ci                  unsigned height,
471bf215546Sopenharmony_ci                  uint64_t zstencil)
472bf215546Sopenharmony_ci{
473bf215546Sopenharmony_ci   unsigned i, j;
474bf215546Sopenharmony_ci   switch (util_format_get_blocksize(format)) {
475bf215546Sopenharmony_ci   case 1:
476bf215546Sopenharmony_ci      assert(format == PIPE_FORMAT_S8_UINT);
477bf215546Sopenharmony_ci      if(dst_stride == width)
478bf215546Sopenharmony_ci         memset(dst_map, (uint8_t) zstencil, height * width);
479bf215546Sopenharmony_ci      else {
480bf215546Sopenharmony_ci         for (i = 0; i < height; i++) {
481bf215546Sopenharmony_ci            memset(dst_map, (uint8_t) zstencil, width);
482bf215546Sopenharmony_ci            dst_map += dst_stride;
483bf215546Sopenharmony_ci         }
484bf215546Sopenharmony_ci      }
485bf215546Sopenharmony_ci      break;
486bf215546Sopenharmony_ci   case 2:
487bf215546Sopenharmony_ci      assert(format == PIPE_FORMAT_Z16_UNORM);
488bf215546Sopenharmony_ci      for (i = 0; i < height; i++) {
489bf215546Sopenharmony_ci         uint16_t *row = (uint16_t *)dst_map;
490bf215546Sopenharmony_ci         for (j = 0; j < width; j++)
491bf215546Sopenharmony_ci            *row++ = (uint16_t) zstencil;
492bf215546Sopenharmony_ci         dst_map += dst_stride;
493bf215546Sopenharmony_ci      }
494bf215546Sopenharmony_ci      break;
495bf215546Sopenharmony_ci   case 4:
496bf215546Sopenharmony_ci      if (!need_rmw) {
497bf215546Sopenharmony_ci         for (i = 0; i < height; i++) {
498bf215546Sopenharmony_ci            util_memset32(dst_map, (uint32_t)zstencil, width);
499bf215546Sopenharmony_ci            dst_map += dst_stride;
500bf215546Sopenharmony_ci         }
501bf215546Sopenharmony_ci      }
502bf215546Sopenharmony_ci      else {
503bf215546Sopenharmony_ci         uint32_t dst_mask;
504bf215546Sopenharmony_ci         if (format == PIPE_FORMAT_Z24_UNORM_S8_UINT)
505bf215546Sopenharmony_ci            dst_mask = 0x00ffffff;
506bf215546Sopenharmony_ci         else {
507bf215546Sopenharmony_ci            assert(format == PIPE_FORMAT_S8_UINT_Z24_UNORM);
508bf215546Sopenharmony_ci            dst_mask = 0xffffff00;
509bf215546Sopenharmony_ci         }
510bf215546Sopenharmony_ci         if (clear_flags & PIPE_CLEAR_DEPTH)
511bf215546Sopenharmony_ci            dst_mask = ~dst_mask;
512bf215546Sopenharmony_ci         for (i = 0; i < height; i++) {
513bf215546Sopenharmony_ci            uint32_t *row = (uint32_t *)dst_map;
514bf215546Sopenharmony_ci            for (j = 0; j < width; j++) {
515bf215546Sopenharmony_ci               uint32_t tmp = *row & dst_mask;
516bf215546Sopenharmony_ci               *row++ = tmp | ((uint32_t) zstencil & ~dst_mask);
517bf215546Sopenharmony_ci            }
518bf215546Sopenharmony_ci            dst_map += dst_stride;
519bf215546Sopenharmony_ci         }
520bf215546Sopenharmony_ci      }
521bf215546Sopenharmony_ci      break;
522bf215546Sopenharmony_ci   case 8:
523bf215546Sopenharmony_ci      if (!need_rmw) {
524bf215546Sopenharmony_ci         for (i = 0; i < height; i++) {
525bf215546Sopenharmony_ci            util_memset64(dst_map, zstencil, width);
526bf215546Sopenharmony_ci            dst_map += dst_stride;
527bf215546Sopenharmony_ci         }
528bf215546Sopenharmony_ci      }
529bf215546Sopenharmony_ci      else {
530bf215546Sopenharmony_ci         uint64_t src_mask;
531bf215546Sopenharmony_ci
532bf215546Sopenharmony_ci         if (clear_flags & PIPE_CLEAR_DEPTH)
533bf215546Sopenharmony_ci            src_mask = 0x00000000ffffffffull;
534bf215546Sopenharmony_ci         else
535bf215546Sopenharmony_ci            src_mask = 0x000000ff00000000ull;
536bf215546Sopenharmony_ci
537bf215546Sopenharmony_ci         for (i = 0; i < height; i++) {
538bf215546Sopenharmony_ci            uint64_t *row = (uint64_t *)dst_map;
539bf215546Sopenharmony_ci            for (j = 0; j < width; j++) {
540bf215546Sopenharmony_ci               uint64_t tmp = *row & ~src_mask;
541bf215546Sopenharmony_ci               *row++ = tmp | (zstencil & src_mask);
542bf215546Sopenharmony_ci            }
543bf215546Sopenharmony_ci            dst_map += dst_stride;
544bf215546Sopenharmony_ci         }
545bf215546Sopenharmony_ci      }
546bf215546Sopenharmony_ci      break;
547bf215546Sopenharmony_ci   default:
548bf215546Sopenharmony_ci      assert(0);
549bf215546Sopenharmony_ci      break;
550bf215546Sopenharmony_ci   }
551bf215546Sopenharmony_ci}
552bf215546Sopenharmony_ci
553bf215546Sopenharmony_civoid
554bf215546Sopenharmony_ciutil_fill_zs_box(ubyte *dst,
555bf215546Sopenharmony_ci                 enum pipe_format format,
556bf215546Sopenharmony_ci                 bool need_rmw,
557bf215546Sopenharmony_ci                 unsigned clear_flags,
558bf215546Sopenharmony_ci                 unsigned stride,
559bf215546Sopenharmony_ci                 unsigned layer_stride,
560bf215546Sopenharmony_ci                 unsigned width,
561bf215546Sopenharmony_ci                 unsigned height,
562bf215546Sopenharmony_ci                 unsigned depth,
563bf215546Sopenharmony_ci                 uint64_t zstencil)
564bf215546Sopenharmony_ci{
565bf215546Sopenharmony_ci   unsigned layer;
566bf215546Sopenharmony_ci
567bf215546Sopenharmony_ci   for (layer = 0; layer < depth; layer++) {
568bf215546Sopenharmony_ci      util_fill_zs_rect(dst, format, need_rmw, clear_flags, stride,
569bf215546Sopenharmony_ci                        width, height, zstencil);
570bf215546Sopenharmony_ci      dst += layer_stride;
571bf215546Sopenharmony_ci   }
572bf215546Sopenharmony_ci}
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_cistatic void
575bf215546Sopenharmony_ciutil_clear_depth_stencil_texture(struct pipe_context *pipe,
576bf215546Sopenharmony_ci                                 struct pipe_resource *texture,
577bf215546Sopenharmony_ci                                 enum pipe_format format,
578bf215546Sopenharmony_ci                                 unsigned clear_flags,
579bf215546Sopenharmony_ci                                 uint64_t zstencil, unsigned level,
580bf215546Sopenharmony_ci                                 unsigned dstx, unsigned dsty, unsigned dstz,
581bf215546Sopenharmony_ci                                 unsigned width, unsigned height, unsigned depth)
582bf215546Sopenharmony_ci{
583bf215546Sopenharmony_ci   struct pipe_transfer *dst_trans;
584bf215546Sopenharmony_ci   ubyte *dst_map;
585bf215546Sopenharmony_ci   boolean need_rmw = FALSE;
586bf215546Sopenharmony_ci
587bf215546Sopenharmony_ci   if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) &&
588bf215546Sopenharmony_ci       ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
589bf215546Sopenharmony_ci       util_format_is_depth_and_stencil(format))
590bf215546Sopenharmony_ci      need_rmw = TRUE;
591bf215546Sopenharmony_ci
592bf215546Sopenharmony_ci   dst_map = pipe_texture_map_3d(pipe,
593bf215546Sopenharmony_ci                                  texture,
594bf215546Sopenharmony_ci                                  level,
595bf215546Sopenharmony_ci                                  (need_rmw ? PIPE_MAP_READ_WRITE :
596bf215546Sopenharmony_ci                                              PIPE_MAP_WRITE),
597bf215546Sopenharmony_ci                                  dstx, dsty, dstz,
598bf215546Sopenharmony_ci                                  width, height, depth, &dst_trans);
599bf215546Sopenharmony_ci   assert(dst_map);
600bf215546Sopenharmony_ci   if (!dst_map)
601bf215546Sopenharmony_ci      return;
602bf215546Sopenharmony_ci
603bf215546Sopenharmony_ci   assert(dst_trans->stride > 0);
604bf215546Sopenharmony_ci
605bf215546Sopenharmony_ci   util_fill_zs_box(dst_map, format, need_rmw, clear_flags,
606bf215546Sopenharmony_ci                    dst_trans->stride,
607bf215546Sopenharmony_ci                    dst_trans->layer_stride, width, height,
608bf215546Sopenharmony_ci                    depth, zstencil);
609bf215546Sopenharmony_ci
610bf215546Sopenharmony_ci   pipe->texture_unmap(pipe, dst_trans);
611bf215546Sopenharmony_ci}
612bf215546Sopenharmony_ci
613bf215546Sopenharmony_ci
614bf215546Sopenharmony_civoid
615bf215546Sopenharmony_ciutil_clear_texture(struct pipe_context *pipe,
616bf215546Sopenharmony_ci                   struct pipe_resource *tex,
617bf215546Sopenharmony_ci                   unsigned level,
618bf215546Sopenharmony_ci                   const struct pipe_box *box,
619bf215546Sopenharmony_ci                   const void *data)
620bf215546Sopenharmony_ci{
621bf215546Sopenharmony_ci   const struct util_format_description *desc =
622bf215546Sopenharmony_ci          util_format_description(tex->format);
623bf215546Sopenharmony_ci
624bf215546Sopenharmony_ci   if (level > tex->last_level)
625bf215546Sopenharmony_ci      return;
626bf215546Sopenharmony_ci
627bf215546Sopenharmony_ci   if (util_format_is_depth_or_stencil(tex->format)) {
628bf215546Sopenharmony_ci      unsigned clear = 0;
629bf215546Sopenharmony_ci      float depth = 0.0f;
630bf215546Sopenharmony_ci      uint8_t stencil = 0;
631bf215546Sopenharmony_ci      uint64_t zstencil;
632bf215546Sopenharmony_ci
633bf215546Sopenharmony_ci      if (util_format_has_depth(desc)) {
634bf215546Sopenharmony_ci         clear |= PIPE_CLEAR_DEPTH;
635bf215546Sopenharmony_ci         util_format_unpack_z_float(tex->format, &depth, data, 1);
636bf215546Sopenharmony_ci      }
637bf215546Sopenharmony_ci
638bf215546Sopenharmony_ci      if (util_format_has_stencil(desc)) {
639bf215546Sopenharmony_ci         clear |= PIPE_CLEAR_STENCIL;
640bf215546Sopenharmony_ci         util_format_unpack_s_8uint(tex->format, &stencil, data, 1);
641bf215546Sopenharmony_ci      }
642bf215546Sopenharmony_ci
643bf215546Sopenharmony_ci      zstencil = util_pack64_z_stencil(tex->format, depth, stencil);
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci      util_clear_depth_stencil_texture(pipe, tex, tex->format, clear, zstencil,
646bf215546Sopenharmony_ci                                       level, box->x, box->y, box->z,
647bf215546Sopenharmony_ci                                       box->width, box->height, box->depth);
648bf215546Sopenharmony_ci   } else {
649bf215546Sopenharmony_ci      union pipe_color_union color;
650bf215546Sopenharmony_ci      util_format_unpack_rgba(tex->format, color.ui, data, 1);
651bf215546Sopenharmony_ci
652bf215546Sopenharmony_ci      util_clear_color_texture(pipe, tex, tex->format, &color, level,
653bf215546Sopenharmony_ci                               box->x, box->y, box->z,
654bf215546Sopenharmony_ci                               box->width, box->height, box->depth);
655bf215546Sopenharmony_ci   }
656bf215546Sopenharmony_ci}
657bf215546Sopenharmony_ci
658bf215546Sopenharmony_ci
659bf215546Sopenharmony_ci/**
660bf215546Sopenharmony_ci * Fallback for pipe->clear_stencil() function.
661bf215546Sopenharmony_ci * sw fallback doesn't look terribly useful here.
662bf215546Sopenharmony_ci * Plus can't use these transfer fallbacks when clearing
663bf215546Sopenharmony_ci * multisampled surfaces for instance.
664bf215546Sopenharmony_ci * Clears all bound layers.
665bf215546Sopenharmony_ci */
666bf215546Sopenharmony_civoid
667bf215546Sopenharmony_ciutil_clear_depth_stencil(struct pipe_context *pipe,
668bf215546Sopenharmony_ci                         struct pipe_surface *dst,
669bf215546Sopenharmony_ci                         unsigned clear_flags,
670bf215546Sopenharmony_ci                         double depth,
671bf215546Sopenharmony_ci                         unsigned stencil,
672bf215546Sopenharmony_ci                         unsigned dstx, unsigned dsty,
673bf215546Sopenharmony_ci                         unsigned width, unsigned height)
674bf215546Sopenharmony_ci{
675bf215546Sopenharmony_ci   uint64_t zstencil;
676bf215546Sopenharmony_ci   unsigned max_layer;
677bf215546Sopenharmony_ci
678bf215546Sopenharmony_ci   assert(dst->texture);
679bf215546Sopenharmony_ci   if (!dst->texture)
680bf215546Sopenharmony_ci      return;
681bf215546Sopenharmony_ci
682bf215546Sopenharmony_ci   zstencil = util_pack64_z_stencil(dst->format, depth, stencil);
683bf215546Sopenharmony_ci   max_layer = dst->u.tex.last_layer - dst->u.tex.first_layer;
684bf215546Sopenharmony_ci   util_clear_depth_stencil_texture(pipe, dst->texture, dst->format,
685bf215546Sopenharmony_ci                                    clear_flags, zstencil, dst->u.tex.level,
686bf215546Sopenharmony_ci                                    dstx, dsty, dst->u.tex.first_layer,
687bf215546Sopenharmony_ci                                    width, height, max_layer + 1);
688bf215546Sopenharmony_ci}
689bf215546Sopenharmony_ci
690bf215546Sopenharmony_ci
691bf215546Sopenharmony_ci/* Return if the box is totally inside the resource.
692bf215546Sopenharmony_ci */
693bf215546Sopenharmony_cistatic boolean
694bf215546Sopenharmony_ciis_box_inside_resource(const struct pipe_resource *res,
695bf215546Sopenharmony_ci                       const struct pipe_box *box,
696bf215546Sopenharmony_ci                       unsigned level)
697bf215546Sopenharmony_ci{
698bf215546Sopenharmony_ci   unsigned width = 1, height = 1, depth = 1;
699bf215546Sopenharmony_ci
700bf215546Sopenharmony_ci   switch (res->target) {
701bf215546Sopenharmony_ci   case PIPE_BUFFER:
702bf215546Sopenharmony_ci      width = res->width0;
703bf215546Sopenharmony_ci      height = 1;
704bf215546Sopenharmony_ci      depth = 1;
705bf215546Sopenharmony_ci      break;
706bf215546Sopenharmony_ci   case PIPE_TEXTURE_1D:
707bf215546Sopenharmony_ci      width = u_minify(res->width0, level);
708bf215546Sopenharmony_ci      height = 1;
709bf215546Sopenharmony_ci      depth = 1;
710bf215546Sopenharmony_ci      break;
711bf215546Sopenharmony_ci   case PIPE_TEXTURE_2D:
712bf215546Sopenharmony_ci   case PIPE_TEXTURE_RECT:
713bf215546Sopenharmony_ci      width = u_minify(res->width0, level);
714bf215546Sopenharmony_ci      height = u_minify(res->height0, level);
715bf215546Sopenharmony_ci      depth = 1;
716bf215546Sopenharmony_ci      break;
717bf215546Sopenharmony_ci   case PIPE_TEXTURE_3D:
718bf215546Sopenharmony_ci      width = u_minify(res->width0, level);
719bf215546Sopenharmony_ci      height = u_minify(res->height0, level);
720bf215546Sopenharmony_ci      depth = u_minify(res->depth0, level);
721bf215546Sopenharmony_ci      break;
722bf215546Sopenharmony_ci   case PIPE_TEXTURE_CUBE:
723bf215546Sopenharmony_ci      width = u_minify(res->width0, level);
724bf215546Sopenharmony_ci      height = u_minify(res->height0, level);
725bf215546Sopenharmony_ci      depth = 6;
726bf215546Sopenharmony_ci      break;
727bf215546Sopenharmony_ci   case PIPE_TEXTURE_1D_ARRAY:
728bf215546Sopenharmony_ci      width = u_minify(res->width0, level);
729bf215546Sopenharmony_ci      height = 1;
730bf215546Sopenharmony_ci      depth = res->array_size;
731bf215546Sopenharmony_ci      break;
732bf215546Sopenharmony_ci   case PIPE_TEXTURE_2D_ARRAY:
733bf215546Sopenharmony_ci      width = u_minify(res->width0, level);
734bf215546Sopenharmony_ci      height = u_minify(res->height0, level);
735bf215546Sopenharmony_ci      depth = res->array_size;
736bf215546Sopenharmony_ci      break;
737bf215546Sopenharmony_ci   case PIPE_TEXTURE_CUBE_ARRAY:
738bf215546Sopenharmony_ci      width = u_minify(res->width0, level);
739bf215546Sopenharmony_ci      height = u_minify(res->height0, level);
740bf215546Sopenharmony_ci      depth = res->array_size;
741bf215546Sopenharmony_ci      assert(res->array_size % 6 == 0);
742bf215546Sopenharmony_ci      break;
743bf215546Sopenharmony_ci   case PIPE_MAX_TEXTURE_TYPES:
744bf215546Sopenharmony_ci      break;
745bf215546Sopenharmony_ci   }
746bf215546Sopenharmony_ci
747bf215546Sopenharmony_ci   return box->x >= 0 &&
748bf215546Sopenharmony_ci          box->x + box->width <= (int) width &&
749bf215546Sopenharmony_ci          box->y >= 0 &&
750bf215546Sopenharmony_ci          box->y + box->height <= (int) height &&
751bf215546Sopenharmony_ci          box->z >= 0 &&
752bf215546Sopenharmony_ci          box->z + box->depth <= (int) depth;
753bf215546Sopenharmony_ci}
754bf215546Sopenharmony_ci
755bf215546Sopenharmony_cistatic unsigned
756bf215546Sopenharmony_ciget_sample_count(const struct pipe_resource *res)
757bf215546Sopenharmony_ci{
758bf215546Sopenharmony_ci   return res->nr_samples ? res->nr_samples : 1;
759bf215546Sopenharmony_ci}
760bf215546Sopenharmony_ci
761bf215546Sopenharmony_ci
762bf215546Sopenharmony_ci/**
763bf215546Sopenharmony_ci * Check if a blit() command can be implemented with a resource_copy_region().
764bf215546Sopenharmony_ci * If tight_format_check is true, only allow the resource_copy_region() if
765bf215546Sopenharmony_ci * the blit src/dst formats are identical, ignoring the resource formats.
766bf215546Sopenharmony_ci * Otherwise, check for format casting and compatibility.
767bf215546Sopenharmony_ci */
768bf215546Sopenharmony_cibool
769bf215546Sopenharmony_ciutil_can_blit_via_copy_region(const struct pipe_blit_info *blit,
770bf215546Sopenharmony_ci                              bool tight_format_check,
771bf215546Sopenharmony_ci                              bool render_condition_bound)
772bf215546Sopenharmony_ci{
773bf215546Sopenharmony_ci   const struct util_format_description *src_desc, *dst_desc;
774bf215546Sopenharmony_ci
775bf215546Sopenharmony_ci   src_desc = util_format_description(blit->src.resource->format);
776bf215546Sopenharmony_ci   dst_desc = util_format_description(blit->dst.resource->format);
777bf215546Sopenharmony_ci
778bf215546Sopenharmony_ci   if (tight_format_check) {
779bf215546Sopenharmony_ci      /* no format conversions allowed */
780bf215546Sopenharmony_ci      if (blit->src.format != blit->dst.format) {
781bf215546Sopenharmony_ci         return FALSE;
782bf215546Sopenharmony_ci      }
783bf215546Sopenharmony_ci   }
784bf215546Sopenharmony_ci   else {
785bf215546Sopenharmony_ci      /* do loose format compatibility checking */
786bf215546Sopenharmony_ci      if (blit->src.resource->format != blit->src.format ||
787bf215546Sopenharmony_ci          blit->dst.resource->format != blit->dst.format ||
788bf215546Sopenharmony_ci          !util_is_format_compatible(src_desc, dst_desc)) {
789bf215546Sopenharmony_ci         return FALSE;
790bf215546Sopenharmony_ci      }
791bf215546Sopenharmony_ci   }
792bf215546Sopenharmony_ci
793bf215546Sopenharmony_ci   unsigned mask = util_format_get_mask(blit->dst.format);
794bf215546Sopenharmony_ci
795bf215546Sopenharmony_ci   /* No masks, no filtering, no scissor, no blending */
796bf215546Sopenharmony_ci   if ((blit->mask & mask) != mask ||
797bf215546Sopenharmony_ci       blit->filter != PIPE_TEX_FILTER_NEAREST ||
798bf215546Sopenharmony_ci       blit->scissor_enable ||
799bf215546Sopenharmony_ci       blit->num_window_rectangles > 0 ||
800bf215546Sopenharmony_ci       blit->alpha_blend ||
801bf215546Sopenharmony_ci       (blit->render_condition_enable && render_condition_bound)) {
802bf215546Sopenharmony_ci      return FALSE;
803bf215546Sopenharmony_ci   }
804bf215546Sopenharmony_ci
805bf215546Sopenharmony_ci   /* Only the src box can have negative dims for flipping */
806bf215546Sopenharmony_ci   assert(blit->dst.box.width >= 1);
807bf215546Sopenharmony_ci   assert(blit->dst.box.height >= 1);
808bf215546Sopenharmony_ci   assert(blit->dst.box.depth >= 1);
809bf215546Sopenharmony_ci
810bf215546Sopenharmony_ci   /* No scaling or flipping */
811bf215546Sopenharmony_ci   if (blit->src.box.width != blit->dst.box.width ||
812bf215546Sopenharmony_ci       blit->src.box.height != blit->dst.box.height ||
813bf215546Sopenharmony_ci       blit->src.box.depth != blit->dst.box.depth) {
814bf215546Sopenharmony_ci      return FALSE;
815bf215546Sopenharmony_ci   }
816bf215546Sopenharmony_ci
817bf215546Sopenharmony_ci   /* No out-of-bounds access. */
818bf215546Sopenharmony_ci   if (!is_box_inside_resource(blit->src.resource, &blit->src.box,
819bf215546Sopenharmony_ci                               blit->src.level) ||
820bf215546Sopenharmony_ci       !is_box_inside_resource(blit->dst.resource, &blit->dst.box,
821bf215546Sopenharmony_ci                               blit->dst.level)) {
822bf215546Sopenharmony_ci      return FALSE;
823bf215546Sopenharmony_ci   }
824bf215546Sopenharmony_ci
825bf215546Sopenharmony_ci   /* Sample counts must match. */
826bf215546Sopenharmony_ci   if (get_sample_count(blit->src.resource) !=
827bf215546Sopenharmony_ci       get_sample_count(blit->dst.resource)) {
828bf215546Sopenharmony_ci      return FALSE;
829bf215546Sopenharmony_ci   }
830bf215546Sopenharmony_ci
831bf215546Sopenharmony_ci   return TRUE;
832bf215546Sopenharmony_ci}
833bf215546Sopenharmony_ci
834bf215546Sopenharmony_ci
835bf215546Sopenharmony_ci/**
836bf215546Sopenharmony_ci * Try to do a blit using resource_copy_region. The function calls
837bf215546Sopenharmony_ci * resource_copy_region if the blit description is compatible with it.
838bf215546Sopenharmony_ci *
839bf215546Sopenharmony_ci * It returns TRUE if the blit was done using resource_copy_region.
840bf215546Sopenharmony_ci *
841bf215546Sopenharmony_ci * It returns FALSE otherwise and the caller must fall back to a more generic
842bf215546Sopenharmony_ci * codepath for the blit operation. (e.g. by using u_blitter)
843bf215546Sopenharmony_ci */
844bf215546Sopenharmony_cibool
845bf215546Sopenharmony_ciutil_try_blit_via_copy_region(struct pipe_context *ctx,
846bf215546Sopenharmony_ci                              const struct pipe_blit_info *blit,
847bf215546Sopenharmony_ci                              bool render_condition_bound)
848bf215546Sopenharmony_ci{
849bf215546Sopenharmony_ci   if (util_can_blit_via_copy_region(blit, FALSE, render_condition_bound)) {
850bf215546Sopenharmony_ci      ctx->resource_copy_region(ctx, blit->dst.resource, blit->dst.level,
851bf215546Sopenharmony_ci                                blit->dst.box.x, blit->dst.box.y,
852bf215546Sopenharmony_ci                                blit->dst.box.z,
853bf215546Sopenharmony_ci                                blit->src.resource, blit->src.level,
854bf215546Sopenharmony_ci                                &blit->src.box);
855bf215546Sopenharmony_ci      return TRUE;
856bf215546Sopenharmony_ci   }
857bf215546Sopenharmony_ci   else {
858bf215546Sopenharmony_ci      return FALSE;
859bf215546Sopenharmony_ci   }
860bf215546Sopenharmony_ci}
861