1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2015 Advanced Micro Devices, Inc.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci */
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci#include "state_tracker/st_context.h"
26bf215546Sopenharmony_ci#include "state_tracker/st_cb_bitmap.h"
27bf215546Sopenharmony_ci#include "state_tracker/st_cb_copyimage.h"
28bf215546Sopenharmony_ci#include "state_tracker/st_cb_texture.h"
29bf215546Sopenharmony_ci#include "state_tracker/st_texture.h"
30bf215546Sopenharmony_ci#include "state_tracker/st_util.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "util/u_box.h"
33bf215546Sopenharmony_ci#include "util/format/u_format.h"
34bf215546Sopenharmony_ci#include "util/u_inlines.h"
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci/**
38bf215546Sopenharmony_ci * Return an equivalent canonical format without "X" channels.
39bf215546Sopenharmony_ci *
40bf215546Sopenharmony_ci * Copying between incompatible formats is easier when the format is
41bf215546Sopenharmony_ci * canonicalized, meaning that it is in a standard form.
42bf215546Sopenharmony_ci *
43bf215546Sopenharmony_ci * The returned format has the same component sizes and swizzles as
44bf215546Sopenharmony_ci * the source format, the type is changed to UINT or UNORM, depending on
45bf215546Sopenharmony_ci * which one has the most swizzle combinations in their group.
46bf215546Sopenharmony_ci *
47bf215546Sopenharmony_ci * If it's not an array format, return a memcpy-equivalent array format.
48bf215546Sopenharmony_ci *
49bf215546Sopenharmony_ci * The key feature is that swizzled versions of formats of the same
50bf215546Sopenharmony_ci * component size always return the same component type.
51bf215546Sopenharmony_ci *
52bf215546Sopenharmony_ci * X returns A.
53bf215546Sopenharmony_ci * Luminance, intensity, alpha, depth, stencil, and 8-bit and 16-bit packed
54bf215546Sopenharmony_ci * formats are not supported. (same as ARB_copy_image)
55bf215546Sopenharmony_ci */
56bf215546Sopenharmony_cistatic enum pipe_format
57bf215546Sopenharmony_ciget_canonical_format(struct pipe_screen *screen,
58bf215546Sopenharmony_ci                     enum pipe_format format)
59bf215546Sopenharmony_ci{
60bf215546Sopenharmony_ci   const struct util_format_description *desc =
61bf215546Sopenharmony_ci      util_format_description(format);
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci   /* Packed formats. Return the equivalent array format. */
64bf215546Sopenharmony_ci   if (format == PIPE_FORMAT_R11G11B10_FLOAT ||
65bf215546Sopenharmony_ci       format == PIPE_FORMAT_R9G9B9E5_FLOAT)
66bf215546Sopenharmony_ci      return get_canonical_format(screen, PIPE_FORMAT_R8G8B8A8_UINT);
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci   if (desc->nr_channels == 4 &&
69bf215546Sopenharmony_ci       desc->channel[0].size == 10 &&
70bf215546Sopenharmony_ci       desc->channel[1].size == 10 &&
71bf215546Sopenharmony_ci       desc->channel[2].size == 10 &&
72bf215546Sopenharmony_ci       desc->channel[3].size == 2) {
73bf215546Sopenharmony_ci      if (desc->swizzle[0] == PIPE_SWIZZLE_X &&
74bf215546Sopenharmony_ci          desc->swizzle[1] == PIPE_SWIZZLE_Y &&
75bf215546Sopenharmony_ci          desc->swizzle[2] == PIPE_SWIZZLE_Z)
76bf215546Sopenharmony_ci         return get_canonical_format(screen, PIPE_FORMAT_R8G8B8A8_UINT);
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci      return PIPE_FORMAT_NONE;
79bf215546Sopenharmony_ci   }
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci#define RETURN_FOR_SWIZZLE1(x, format) \
82bf215546Sopenharmony_ci   if (desc->swizzle[0] == PIPE_SWIZZLE_##x) \
83bf215546Sopenharmony_ci      return (screen->get_canonical_format ? \
84bf215546Sopenharmony_ci              screen->get_canonical_format(screen, format) : \
85bf215546Sopenharmony_ci              format)
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci#define RETURN_FOR_SWIZZLE2(x, y, format) \
88bf215546Sopenharmony_ci   if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \
89bf215546Sopenharmony_ci       desc->swizzle[1] == PIPE_SWIZZLE_##y) \
90bf215546Sopenharmony_ci      return (screen->get_canonical_format ? \
91bf215546Sopenharmony_ci              screen->get_canonical_format(screen, format) : \
92bf215546Sopenharmony_ci              format)
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci#define RETURN_FOR_SWIZZLE3(x, y, z, format) \
95bf215546Sopenharmony_ci   if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \
96bf215546Sopenharmony_ci       desc->swizzle[1] == PIPE_SWIZZLE_##y && \
97bf215546Sopenharmony_ci       desc->swizzle[2] == PIPE_SWIZZLE_##z) \
98bf215546Sopenharmony_ci      return (screen->get_canonical_format ? \
99bf215546Sopenharmony_ci              screen->get_canonical_format(screen, format) : \
100bf215546Sopenharmony_ci              format)
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci#define RETURN_FOR_SWIZZLE4(x, y, z, w, format) \
103bf215546Sopenharmony_ci   if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \
104bf215546Sopenharmony_ci       desc->swizzle[1] == PIPE_SWIZZLE_##y && \
105bf215546Sopenharmony_ci       desc->swizzle[2] == PIPE_SWIZZLE_##z && \
106bf215546Sopenharmony_ci       desc->swizzle[3] == PIPE_SWIZZLE_##w) \
107bf215546Sopenharmony_ci      return (screen->get_canonical_format ? \
108bf215546Sopenharmony_ci              screen->get_canonical_format(screen, format) : \
109bf215546Sopenharmony_ci              format)
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci   /* Array formats. */
112bf215546Sopenharmony_ci   if (desc->is_array) {
113bf215546Sopenharmony_ci      switch (desc->nr_channels) {
114bf215546Sopenharmony_ci      case 1:
115bf215546Sopenharmony_ci         switch (desc->channel[0].size) {
116bf215546Sopenharmony_ci         case 8:
117bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE1(X, PIPE_FORMAT_R8_UINT);
118bf215546Sopenharmony_ci            break;
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci         case 16:
121bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE1(X, PIPE_FORMAT_R16_UINT);
122bf215546Sopenharmony_ci            break;
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci         case 32:
125bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE1(X, PIPE_FORMAT_R32_UINT);
126bf215546Sopenharmony_ci            break;
127bf215546Sopenharmony_ci         }
128bf215546Sopenharmony_ci         break;
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci      case 2:
131bf215546Sopenharmony_ci         switch (desc->channel[0].size) {
132bf215546Sopenharmony_ci         case 8:
133bf215546Sopenharmony_ci            /* All formats in each group must be of the same type.
134bf215546Sopenharmony_ci             * We can't use UINT for R8G8 while using UNORM for G8R8.
135bf215546Sopenharmony_ci             */
136bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE2(X, Y, PIPE_FORMAT_R8G8_UNORM);
137bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE2(Y, X, PIPE_FORMAT_G8R8_UNORM);
138bf215546Sopenharmony_ci            break;
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci         case 16:
141bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE2(X, Y, PIPE_FORMAT_R16G16_UNORM);
142bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE2(Y, X, PIPE_FORMAT_G16R16_UNORM);
143bf215546Sopenharmony_ci            break;
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci         case 32:
146bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE2(X, Y, PIPE_FORMAT_R32G32_UINT);
147bf215546Sopenharmony_ci            break;
148bf215546Sopenharmony_ci         }
149bf215546Sopenharmony_ci         break;
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci      case 3:
152bf215546Sopenharmony_ci         switch (desc->channel[0].size) {
153bf215546Sopenharmony_ci         case 8:
154bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE3(X, Y, Z, PIPE_FORMAT_R8G8B8_UINT);
155bf215546Sopenharmony_ci            break;
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci         case 16:
158bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE3(X, Y, Z, PIPE_FORMAT_R16G16B16_UINT);
159bf215546Sopenharmony_ci            break;
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci         case 32:
162bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE3(X, Y, Z, PIPE_FORMAT_R32G32B32_UINT);
163bf215546Sopenharmony_ci            break;
164bf215546Sopenharmony_ci         }
165bf215546Sopenharmony_ci         break;
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci      case 4:
168bf215546Sopenharmony_ci         switch (desc->channel[0].size) {
169bf215546Sopenharmony_ci         case 8:
170bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE4(X, Y, Z, W, PIPE_FORMAT_R8G8B8A8_UNORM);
171bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE4(X, Y, Z, 1, PIPE_FORMAT_R8G8B8A8_UNORM);
172bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE4(Z, Y, X, W, PIPE_FORMAT_B8G8R8A8_UNORM);
173bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE4(Z, Y, X, 1, PIPE_FORMAT_B8G8R8A8_UNORM);
174bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE4(W, Z, Y, X, PIPE_FORMAT_A8B8G8R8_UNORM);
175bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE4(W, Z, Y, 1, PIPE_FORMAT_A8B8G8R8_UNORM);
176bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE4(Y, Z, W, X, PIPE_FORMAT_A8R8G8B8_UNORM);
177bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE4(Y, Z, W, 1, PIPE_FORMAT_A8R8G8B8_UNORM);
178bf215546Sopenharmony_ci            break;
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci         case 16:
181bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE4(X, Y, Z, W, PIPE_FORMAT_R16G16B16A16_UINT);
182bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE4(X, Y, Z, 1, PIPE_FORMAT_R16G16B16A16_UINT);
183bf215546Sopenharmony_ci            break;
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci         case 32:
186bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE4(X, Y, Z, W, PIPE_FORMAT_R32G32B32A32_UINT);
187bf215546Sopenharmony_ci            RETURN_FOR_SWIZZLE4(X, Y, Z, 1, PIPE_FORMAT_R32G32B32A32_UINT);
188bf215546Sopenharmony_ci            break;
189bf215546Sopenharmony_ci         }
190bf215546Sopenharmony_ci      }
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_ci      assert(!"unknown array format");
193bf215546Sopenharmony_ci      return PIPE_FORMAT_NONE;
194bf215546Sopenharmony_ci   }
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_ci   assert(!"unknown packed format");
197bf215546Sopenharmony_ci   return PIPE_FORMAT_NONE;
198bf215546Sopenharmony_ci}
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci/**
201bf215546Sopenharmony_ci * Return true if the swizzle is XYZW in case of a 4-channel format,
202bf215546Sopenharmony_ci * XY in case of a 2-channel format, or X in case of a 1-channel format.
203bf215546Sopenharmony_ci */
204bf215546Sopenharmony_cistatic bool
205bf215546Sopenharmony_cihas_identity_swizzle(const struct util_format_description *desc)
206bf215546Sopenharmony_ci{
207bf215546Sopenharmony_ci   int i;
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci   for (i = 0; i < desc->nr_channels; i++)
210bf215546Sopenharmony_ci      if (desc->swizzle[i] != PIPE_SWIZZLE_X + i)
211bf215546Sopenharmony_ci         return false;
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci   return true;
214bf215546Sopenharmony_ci}
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci/**
217bf215546Sopenharmony_ci * Return a canonical format for the given bits and channel size.
218bf215546Sopenharmony_ci */
219bf215546Sopenharmony_cistatic enum pipe_format
220bf215546Sopenharmony_cicanonical_format_from_bits(struct pipe_screen *screen,
221bf215546Sopenharmony_ci                           unsigned bits,
222bf215546Sopenharmony_ci                           unsigned channel_size)
223bf215546Sopenharmony_ci{
224bf215546Sopenharmony_ci   switch (bits) {
225bf215546Sopenharmony_ci   case 8:
226bf215546Sopenharmony_ci      if (channel_size == 8)
227bf215546Sopenharmony_ci         return get_canonical_format(screen, PIPE_FORMAT_R8_UINT);
228bf215546Sopenharmony_ci      break;
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci   case 16:
231bf215546Sopenharmony_ci      if (channel_size == 8)
232bf215546Sopenharmony_ci         return get_canonical_format(screen, PIPE_FORMAT_R8G8_UINT);
233bf215546Sopenharmony_ci      if (channel_size == 16)
234bf215546Sopenharmony_ci         return get_canonical_format(screen, PIPE_FORMAT_R16_UINT);
235bf215546Sopenharmony_ci      break;
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_ci   case 32:
238bf215546Sopenharmony_ci      if (channel_size == 8)
239bf215546Sopenharmony_ci         return get_canonical_format(screen, PIPE_FORMAT_R8G8B8A8_UINT);
240bf215546Sopenharmony_ci      if (channel_size == 16)
241bf215546Sopenharmony_ci         return get_canonical_format(screen, PIPE_FORMAT_R16G16_UINT);
242bf215546Sopenharmony_ci      if (channel_size == 32)
243bf215546Sopenharmony_ci         return get_canonical_format(screen, PIPE_FORMAT_R32_UINT);
244bf215546Sopenharmony_ci      break;
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci   case 64:
247bf215546Sopenharmony_ci      if (channel_size == 16)
248bf215546Sopenharmony_ci         return get_canonical_format(screen, PIPE_FORMAT_R16G16B16A16_UINT);
249bf215546Sopenharmony_ci      if (channel_size == 32)
250bf215546Sopenharmony_ci         return get_canonical_format(screen, PIPE_FORMAT_R32G32_UINT);
251bf215546Sopenharmony_ci      break;
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci   case 128:
254bf215546Sopenharmony_ci      if (channel_size == 32)
255bf215546Sopenharmony_ci         return get_canonical_format(screen, PIPE_FORMAT_R32G32B32A32_UINT);
256bf215546Sopenharmony_ci      break;
257bf215546Sopenharmony_ci   }
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci   assert(!"impossible format");
260bf215546Sopenharmony_ci   return PIPE_FORMAT_NONE;
261bf215546Sopenharmony_ci}
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_cistatic void
264bf215546Sopenharmony_ciblit(struct pipe_context *pipe,
265bf215546Sopenharmony_ci     struct pipe_resource *dst,
266bf215546Sopenharmony_ci     enum pipe_format dst_format,
267bf215546Sopenharmony_ci     unsigned dst_level,
268bf215546Sopenharmony_ci     unsigned dstx, unsigned dsty, unsigned dstz,
269bf215546Sopenharmony_ci     struct pipe_resource *src,
270bf215546Sopenharmony_ci     enum pipe_format src_format,
271bf215546Sopenharmony_ci     unsigned src_level,
272bf215546Sopenharmony_ci     const struct pipe_box *src_box)
273bf215546Sopenharmony_ci{
274bf215546Sopenharmony_ci   struct pipe_blit_info blit = {{0}};
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_ci   blit.src.resource = src;
277bf215546Sopenharmony_ci   blit.dst.resource = dst;
278bf215546Sopenharmony_ci   blit.src.format = src_format;
279bf215546Sopenharmony_ci   blit.dst.format = dst_format;
280bf215546Sopenharmony_ci   blit.src.level = src_level;
281bf215546Sopenharmony_ci   blit.dst.level = dst_level;
282bf215546Sopenharmony_ci   blit.src.box = *src_box;
283bf215546Sopenharmony_ci   u_box_3d(dstx, dsty, dstz, src_box->width, src_box->height,
284bf215546Sopenharmony_ci            src_box->depth, &blit.dst.box);
285bf215546Sopenharmony_ci   blit.mask = PIPE_MASK_RGBA;
286bf215546Sopenharmony_ci   blit.filter = PIPE_TEX_FILTER_NEAREST;
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci   pipe->blit(pipe, &blit);
289bf215546Sopenharmony_ci}
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_cistatic void
292bf215546Sopenharmony_ciswizzled_copy(struct pipe_context *pipe,
293bf215546Sopenharmony_ci              struct pipe_resource *dst,
294bf215546Sopenharmony_ci              unsigned dst_level,
295bf215546Sopenharmony_ci              unsigned dstx, unsigned dsty, unsigned dstz,
296bf215546Sopenharmony_ci              struct pipe_resource *src,
297bf215546Sopenharmony_ci              unsigned src_level,
298bf215546Sopenharmony_ci              const struct pipe_box *src_box)
299bf215546Sopenharmony_ci{
300bf215546Sopenharmony_ci   const struct util_format_description *src_desc, *dst_desc;
301bf215546Sopenharmony_ci   unsigned bits;
302bf215546Sopenharmony_ci   enum pipe_format blit_src_format, blit_dst_format;
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_ci   /* Get equivalent canonical formats. Those are always array formats and
305bf215546Sopenharmony_ci    * copying between compatible canonical formats behaves either like
306bf215546Sopenharmony_ci    * memcpy or like swizzled memcpy. The idea is that we won't have to care
307bf215546Sopenharmony_ci    * about the channel type from this point on.
308bf215546Sopenharmony_ci    * Only the swizzle and channel size.
309bf215546Sopenharmony_ci    */
310bf215546Sopenharmony_ci   blit_src_format = get_canonical_format(pipe->screen, src->format);
311bf215546Sopenharmony_ci   blit_dst_format = get_canonical_format(pipe->screen, dst->format);
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci   assert(blit_src_format != PIPE_FORMAT_NONE);
314bf215546Sopenharmony_ci   assert(blit_dst_format != PIPE_FORMAT_NONE);
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_ci   src_desc = util_format_description(blit_src_format);
317bf215546Sopenharmony_ci   dst_desc = util_format_description(blit_dst_format);
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci   assert(src_desc->block.bits == dst_desc->block.bits);
320bf215546Sopenharmony_ci   bits = src_desc->block.bits;
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ci   if (dst_desc->channel[0].size == src_desc->channel[0].size) {
323bf215546Sopenharmony_ci      /* Only the swizzle is different, which means we can just blit,
324bf215546Sopenharmony_ci       * e.g. RGBA -> BGRA.
325bf215546Sopenharmony_ci       */
326bf215546Sopenharmony_ci   } else if (has_identity_swizzle(src_desc)) {
327bf215546Sopenharmony_ci      /* Src is unswizzled and dst can be swizzled, so src is typecast
328bf215546Sopenharmony_ci       * to an equivalent dst-compatible format.
329bf215546Sopenharmony_ci       * e.g. R32 -> BGRA8 is realized as RGBA8 -> BGRA8
330bf215546Sopenharmony_ci       */
331bf215546Sopenharmony_ci      blit_src_format =
332bf215546Sopenharmony_ci         canonical_format_from_bits(pipe->screen, bits, dst_desc->channel[0].size);
333bf215546Sopenharmony_ci   } else if (has_identity_swizzle(dst_desc)) {
334bf215546Sopenharmony_ci      /* Dst is unswizzled and src can be swizzled, so dst is typecast
335bf215546Sopenharmony_ci       * to an equivalent src-compatible format.
336bf215546Sopenharmony_ci       * e.g. BGRA8 -> R32 is realized as BGRA8 -> RGBA8
337bf215546Sopenharmony_ci       */
338bf215546Sopenharmony_ci      blit_dst_format =
339bf215546Sopenharmony_ci         canonical_format_from_bits(pipe->screen, bits, src_desc->channel[0].size);
340bf215546Sopenharmony_ci   } else {
341bf215546Sopenharmony_ci      assert(!"This should have been handled by handle_complex_copy.");
342bf215546Sopenharmony_ci      return;
343bf215546Sopenharmony_ci   }
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   blit(pipe, dst, blit_dst_format, dst_level, dstx, dsty, dstz,
346bf215546Sopenharmony_ci        src, blit_src_format, src_level, src_box);
347bf215546Sopenharmony_ci}
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_cistatic bool
350bf215546Sopenharmony_cisame_size_and_swizzle(const struct util_format_description *d1,
351bf215546Sopenharmony_ci                      const struct util_format_description *d2)
352bf215546Sopenharmony_ci{
353bf215546Sopenharmony_ci   int i;
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci   if (d1->layout != d2->layout ||
356bf215546Sopenharmony_ci       d1->nr_channels != d2->nr_channels ||
357bf215546Sopenharmony_ci       d1->is_array != d2->is_array)
358bf215546Sopenharmony_ci      return false;
359bf215546Sopenharmony_ci
360bf215546Sopenharmony_ci   for (i = 0; i < d1->nr_channels; i++) {
361bf215546Sopenharmony_ci      if (d1->channel[i].size != d2->channel[i].size)
362bf215546Sopenharmony_ci         return false;
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_ci      if (d1->swizzle[i] <= PIPE_SWIZZLE_W &&
365bf215546Sopenharmony_ci          d2->swizzle[i] <= PIPE_SWIZZLE_W &&
366bf215546Sopenharmony_ci          d1->swizzle[i] != d2->swizzle[i])
367bf215546Sopenharmony_ci         return false;
368bf215546Sopenharmony_ci   }
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci   return true;
371bf215546Sopenharmony_ci}
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_cistatic struct pipe_resource *
374bf215546Sopenharmony_cicreate_texture(struct pipe_screen *screen, enum pipe_format format,
375bf215546Sopenharmony_ci               unsigned nr_samples, unsigned nr_storage_samples,
376bf215546Sopenharmony_ci               unsigned width, unsigned height, unsigned depth)
377bf215546Sopenharmony_ci{
378bf215546Sopenharmony_ci   struct pipe_resource templ;
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci   memset(&templ, 0, sizeof(templ));
381bf215546Sopenharmony_ci   templ.format = format;
382bf215546Sopenharmony_ci   templ.width0 = width;
383bf215546Sopenharmony_ci   templ.height0 = height;
384bf215546Sopenharmony_ci   templ.depth0 = 1;
385bf215546Sopenharmony_ci   templ.array_size = depth;
386bf215546Sopenharmony_ci   templ.nr_samples = nr_samples;
387bf215546Sopenharmony_ci   templ.nr_storage_samples = nr_storage_samples;
388bf215546Sopenharmony_ci   templ.usage = PIPE_USAGE_DEFAULT;
389bf215546Sopenharmony_ci   templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci   if (depth > 1)
392bf215546Sopenharmony_ci      templ.target = PIPE_TEXTURE_2D_ARRAY;
393bf215546Sopenharmony_ci   else
394bf215546Sopenharmony_ci      templ.target = PIPE_TEXTURE_2D;
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ci   return screen->resource_create(screen, &templ);
397bf215546Sopenharmony_ci}
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci/**
400bf215546Sopenharmony_ci * Handle complex format conversions using 2 blits with a temporary texture
401bf215546Sopenharmony_ci * in between, e.g. blitting from B10G10R10A2 to G16R16.
402bf215546Sopenharmony_ci *
403bf215546Sopenharmony_ci * This example is implemented this way:
404bf215546Sopenharmony_ci * 1) First, blit from B10G10R10A2 to R10G10B10A2, which is canonical, so it
405bf215546Sopenharmony_ci *    can be reinterpreted as a different canonical format of the same bpp,
406bf215546Sopenharmony_ci *    such as R16G16. This blit only swaps R and B 10-bit components.
407bf215546Sopenharmony_ci * 2) Finally, blit the result, which is R10G10B10A2, as R16G16 to G16R16.
408bf215546Sopenharmony_ci *    This blit only swaps R and G 16-bit components.
409bf215546Sopenharmony_ci */
410bf215546Sopenharmony_cistatic bool
411bf215546Sopenharmony_cihandle_complex_copy(struct pipe_context *pipe,
412bf215546Sopenharmony_ci                    struct pipe_resource *dst,
413bf215546Sopenharmony_ci                    unsigned dst_level,
414bf215546Sopenharmony_ci                    unsigned dstx, unsigned dsty, unsigned dstz,
415bf215546Sopenharmony_ci                    struct pipe_resource *src,
416bf215546Sopenharmony_ci                    unsigned src_level,
417bf215546Sopenharmony_ci                    const struct pipe_box *src_box,
418bf215546Sopenharmony_ci                    enum pipe_format noncanon_format,
419bf215546Sopenharmony_ci                    enum pipe_format canon_format)
420bf215546Sopenharmony_ci{
421bf215546Sopenharmony_ci   struct pipe_box temp_box;
422bf215546Sopenharmony_ci   struct pipe_resource *temp = NULL;
423bf215546Sopenharmony_ci   const struct util_format_description *src_desc, *dst_desc;
424bf215546Sopenharmony_ci   const struct util_format_description *canon_desc, *noncanon_desc;
425bf215546Sopenharmony_ci   bool src_is_canon;
426bf215546Sopenharmony_ci   bool src_is_noncanon;
427bf215546Sopenharmony_ci   bool dst_is_canon;
428bf215546Sopenharmony_ci   bool dst_is_noncanon;
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_ci   src_desc = util_format_description(src->format);
431bf215546Sopenharmony_ci   dst_desc = util_format_description(dst->format);
432bf215546Sopenharmony_ci   canon_desc = util_format_description(canon_format);
433bf215546Sopenharmony_ci   noncanon_desc = util_format_description(noncanon_format);
434bf215546Sopenharmony_ci
435bf215546Sopenharmony_ci   src_is_canon = same_size_and_swizzle(src_desc, canon_desc);
436bf215546Sopenharmony_ci   dst_is_canon = same_size_and_swizzle(dst_desc, canon_desc);
437bf215546Sopenharmony_ci   src_is_noncanon = same_size_and_swizzle(src_desc, noncanon_desc);
438bf215546Sopenharmony_ci   dst_is_noncanon = same_size_and_swizzle(dst_desc, noncanon_desc);
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci   if (src_is_noncanon) {
441bf215546Sopenharmony_ci      /* Simple case - only types differ (e.g. UNORM and UINT). */
442bf215546Sopenharmony_ci      if (dst_is_noncanon) {
443bf215546Sopenharmony_ci         blit(pipe, dst, noncanon_format, dst_level, dstx, dsty, dstz, src,
444bf215546Sopenharmony_ci              noncanon_format, src_level, src_box);
445bf215546Sopenharmony_ci         return true;
446bf215546Sopenharmony_ci      }
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_ci      /* Simple case - only types and swizzles differ. */
449bf215546Sopenharmony_ci      if (dst_is_canon) {
450bf215546Sopenharmony_ci         blit(pipe, dst, canon_format, dst_level, dstx, dsty, dstz, src,
451bf215546Sopenharmony_ci              noncanon_format, src_level, src_box);
452bf215546Sopenharmony_ci         return true;
453bf215546Sopenharmony_ci      }
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_ci      /* Use the temporary texture. Src is converted to a canonical format,
456bf215546Sopenharmony_ci       * then proceed the generic swizzled_copy.
457bf215546Sopenharmony_ci       */
458bf215546Sopenharmony_ci      temp = create_texture(pipe->screen, canon_format, src->nr_samples,
459bf215546Sopenharmony_ci                            src->nr_storage_samples, src_box->width,
460bf215546Sopenharmony_ci                            src_box->height, src_box->depth);
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_ci      u_box_3d(0, 0, 0, src_box->width, src_box->height, src_box->depth,
463bf215546Sopenharmony_ci               &temp_box);
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci      blit(pipe, temp, canon_format, 0, 0, 0, 0, src, noncanon_format,
466bf215546Sopenharmony_ci           src_level, src_box);
467bf215546Sopenharmony_ci      swizzled_copy(pipe, dst, dst_level, dstx, dsty, dstz, temp, 0,
468bf215546Sopenharmony_ci                    &temp_box);
469bf215546Sopenharmony_ci      pipe_resource_reference(&temp, NULL);
470bf215546Sopenharmony_ci      return true;
471bf215546Sopenharmony_ci   }
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci   if (dst_is_noncanon) {
474bf215546Sopenharmony_ci      /* Simple case - only types and swizzles differ. */
475bf215546Sopenharmony_ci      if (src_is_canon) {
476bf215546Sopenharmony_ci         blit(pipe, dst, noncanon_format, dst_level, dstx, dsty, dstz, src,
477bf215546Sopenharmony_ci              canon_format, src_level, src_box);
478bf215546Sopenharmony_ci         return true;
479bf215546Sopenharmony_ci      }
480bf215546Sopenharmony_ci
481bf215546Sopenharmony_ci      /* Use the temporary texture. First, use the generic copy, but use
482bf215546Sopenharmony_ci       * a canonical format in the destination. Then convert */
483bf215546Sopenharmony_ci      temp = create_texture(pipe->screen, canon_format, dst->nr_samples,
484bf215546Sopenharmony_ci                            dst->nr_storage_samples, src_box->width,
485bf215546Sopenharmony_ci                            src_box->height, src_box->depth);
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci      u_box_3d(0, 0, 0, src_box->width, src_box->height, src_box->depth,
488bf215546Sopenharmony_ci               &temp_box);
489bf215546Sopenharmony_ci
490bf215546Sopenharmony_ci      swizzled_copy(pipe, temp, 0, 0, 0, 0, src, src_level, src_box);
491bf215546Sopenharmony_ci      blit(pipe, dst, noncanon_format, dst_level, dstx, dsty, dstz, temp,
492bf215546Sopenharmony_ci           canon_format, 0, &temp_box);
493bf215546Sopenharmony_ci      pipe_resource_reference(&temp, NULL);
494bf215546Sopenharmony_ci      return true;
495bf215546Sopenharmony_ci   }
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci   return false;
498bf215546Sopenharmony_ci}
499bf215546Sopenharmony_ci
500bf215546Sopenharmony_cistatic void
501bf215546Sopenharmony_cicopy_image(struct pipe_context *pipe,
502bf215546Sopenharmony_ci           struct pipe_resource *dst,
503bf215546Sopenharmony_ci           unsigned dst_level,
504bf215546Sopenharmony_ci           unsigned dstx, unsigned dsty, unsigned dstz,
505bf215546Sopenharmony_ci           struct pipe_resource *src,
506bf215546Sopenharmony_ci           unsigned src_level,
507bf215546Sopenharmony_ci           const struct pipe_box *src_box)
508bf215546Sopenharmony_ci{
509bf215546Sopenharmony_ci   if (src->format == dst->format ||
510bf215546Sopenharmony_ci       util_format_is_compressed(src->format) ||
511bf215546Sopenharmony_ci       util_format_is_compressed(dst->format)) {
512bf215546Sopenharmony_ci      pipe->resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
513bf215546Sopenharmony_ci                                 src, src_level, src_box);
514bf215546Sopenharmony_ci      return;
515bf215546Sopenharmony_ci   }
516bf215546Sopenharmony_ci
517bf215546Sopenharmony_ci   /* Copying to/from B10G10R10*2 needs 2 blits with R10G10B10A2
518bf215546Sopenharmony_ci    * as a temporary texture in between.
519bf215546Sopenharmony_ci    */
520bf215546Sopenharmony_ci   if (handle_complex_copy(pipe, dst, dst_level, dstx, dsty, dstz, src,
521bf215546Sopenharmony_ci                           src_level, src_box, PIPE_FORMAT_B10G10R10A2_UINT,
522bf215546Sopenharmony_ci                           PIPE_FORMAT_R10G10B10A2_UINT))
523bf215546Sopenharmony_ci      return;
524bf215546Sopenharmony_ci
525bf215546Sopenharmony_ci   /* Copying to/from G8R8 needs 2 blits with R8G8 as a temporary texture
526bf215546Sopenharmony_ci    * in between.
527bf215546Sopenharmony_ci    */
528bf215546Sopenharmony_ci   if (handle_complex_copy(pipe, dst, dst_level, dstx, dsty, dstz, src,
529bf215546Sopenharmony_ci                           src_level, src_box, PIPE_FORMAT_G8R8_UNORM,
530bf215546Sopenharmony_ci                           PIPE_FORMAT_R8G8_UNORM))
531bf215546Sopenharmony_ci      return;
532bf215546Sopenharmony_ci
533bf215546Sopenharmony_ci   /* Copying to/from G16R16 needs 2 blits with R16G16 as a temporary texture
534bf215546Sopenharmony_ci    * in between.
535bf215546Sopenharmony_ci    */
536bf215546Sopenharmony_ci   if (handle_complex_copy(pipe, dst, dst_level, dstx, dsty, dstz, src,
537bf215546Sopenharmony_ci                           src_level, src_box, PIPE_FORMAT_G16R16_UNORM,
538bf215546Sopenharmony_ci                           PIPE_FORMAT_R16G16_UNORM))
539bf215546Sopenharmony_ci      return;
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_ci   /* Only allow non-identity swizzling on RGBA8 formats. */
542bf215546Sopenharmony_ci
543bf215546Sopenharmony_ci   /* Simple copy, memcpy with swizzling, no format conversion. */
544bf215546Sopenharmony_ci   swizzled_copy(pipe, dst, dst_level, dstx, dsty, dstz, src, src_level,
545bf215546Sopenharmony_ci                 src_box);
546bf215546Sopenharmony_ci}
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_cistatic void
549bf215546Sopenharmony_cifallback_copy_image(struct st_context *st,
550bf215546Sopenharmony_ci                    struct gl_texture_image *dst_image,
551bf215546Sopenharmony_ci                    struct pipe_resource *dst_res,
552bf215546Sopenharmony_ci                    int dst_x, int dst_y, int dst_z,
553bf215546Sopenharmony_ci                    struct gl_texture_image *src_image,
554bf215546Sopenharmony_ci                    struct pipe_resource *src_res,
555bf215546Sopenharmony_ci                    int src_x, int src_y, int src_z,
556bf215546Sopenharmony_ci                    int src_w, int src_h)
557bf215546Sopenharmony_ci{
558bf215546Sopenharmony_ci   uint8_t *dst, *src;
559bf215546Sopenharmony_ci   int dst_stride, src_stride;
560bf215546Sopenharmony_ci   struct pipe_transfer *dst_transfer, *src_transfer;
561bf215546Sopenharmony_ci   unsigned line_bytes;
562bf215546Sopenharmony_ci
563bf215546Sopenharmony_ci   bool dst_is_compressed = dst_image && _mesa_is_format_compressed(dst_image->TexFormat);
564bf215546Sopenharmony_ci   bool src_is_compressed = src_image && _mesa_is_format_compressed(src_image->TexFormat);
565bf215546Sopenharmony_ci
566bf215546Sopenharmony_ci   unsigned dst_blk_w = 1, dst_blk_h = 1, src_blk_w = 1, src_blk_h = 1;
567bf215546Sopenharmony_ci   if (dst_image)
568bf215546Sopenharmony_ci      _mesa_get_format_block_size(dst_image->TexFormat, &dst_blk_w, &dst_blk_h);
569bf215546Sopenharmony_ci   if (src_image)
570bf215546Sopenharmony_ci      _mesa_get_format_block_size(src_image->TexFormat, &src_blk_w, &src_blk_h);
571bf215546Sopenharmony_ci
572bf215546Sopenharmony_ci   unsigned dst_w = src_w;
573bf215546Sopenharmony_ci   unsigned dst_h = src_h;
574bf215546Sopenharmony_ci   unsigned lines = src_h;
575bf215546Sopenharmony_ci
576bf215546Sopenharmony_ci   if (src_is_compressed && !dst_is_compressed) {
577bf215546Sopenharmony_ci      dst_w = DIV_ROUND_UP(dst_w, src_blk_w);
578bf215546Sopenharmony_ci      dst_h = DIV_ROUND_UP(dst_h, src_blk_h);
579bf215546Sopenharmony_ci   } else if (!src_is_compressed && dst_is_compressed) {
580bf215546Sopenharmony_ci      dst_w *= dst_blk_w;
581bf215546Sopenharmony_ci      dst_h *= dst_blk_h;
582bf215546Sopenharmony_ci   }
583bf215546Sopenharmony_ci   if (src_is_compressed) {
584bf215546Sopenharmony_ci      lines = DIV_ROUND_UP(lines, src_blk_h);
585bf215546Sopenharmony_ci   }
586bf215546Sopenharmony_ci
587bf215546Sopenharmony_ci   if (src_image)
588bf215546Sopenharmony_ci      line_bytes = _mesa_format_row_stride(src_image->TexFormat, src_w);
589bf215546Sopenharmony_ci   else
590bf215546Sopenharmony_ci      line_bytes = _mesa_format_row_stride(dst_image->TexFormat, dst_w);
591bf215546Sopenharmony_ci
592bf215546Sopenharmony_ci   if (dst_image) {
593bf215546Sopenharmony_ci      st_MapTextureImage(
594bf215546Sopenharmony_ci            st->ctx, dst_image, dst_z,
595bf215546Sopenharmony_ci            dst_x, dst_y, dst_w, dst_h,
596bf215546Sopenharmony_ci            GL_MAP_WRITE_BIT, &dst, &dst_stride);
597bf215546Sopenharmony_ci   } else {
598bf215546Sopenharmony_ci      dst = pipe_texture_map(st->pipe, dst_res, 0, dst_z,
599bf215546Sopenharmony_ci                              PIPE_MAP_WRITE,
600bf215546Sopenharmony_ci                              dst_x, dst_y, dst_w, dst_h,
601bf215546Sopenharmony_ci                              &dst_transfer);
602bf215546Sopenharmony_ci      dst_stride = dst_transfer->stride;
603bf215546Sopenharmony_ci   }
604bf215546Sopenharmony_ci
605bf215546Sopenharmony_ci   if (src_image) {
606bf215546Sopenharmony_ci      st_MapTextureImage(
607bf215546Sopenharmony_ci            st->ctx, src_image, src_z,
608bf215546Sopenharmony_ci            src_x, src_y, src_w, src_h,
609bf215546Sopenharmony_ci            GL_MAP_READ_BIT, &src, &src_stride);
610bf215546Sopenharmony_ci   } else {
611bf215546Sopenharmony_ci      src = pipe_texture_map(st->pipe, src_res, 0, src_z,
612bf215546Sopenharmony_ci                              PIPE_MAP_READ,
613bf215546Sopenharmony_ci                              src_x, src_y, src_w, src_h,
614bf215546Sopenharmony_ci                              &src_transfer);
615bf215546Sopenharmony_ci      src_stride = src_transfer->stride;
616bf215546Sopenharmony_ci   }
617bf215546Sopenharmony_ci
618bf215546Sopenharmony_ci   for (int y = 0; y < lines; y++) {
619bf215546Sopenharmony_ci      memcpy(dst, src, line_bytes);
620bf215546Sopenharmony_ci      dst += dst_stride;
621bf215546Sopenharmony_ci      src += src_stride;
622bf215546Sopenharmony_ci   }
623bf215546Sopenharmony_ci
624bf215546Sopenharmony_ci   if (dst_image) {
625bf215546Sopenharmony_ci      st_UnmapTextureImage(st->ctx, dst_image, dst_z);
626bf215546Sopenharmony_ci   } else {
627bf215546Sopenharmony_ci      pipe_texture_unmap(st->pipe, dst_transfer);
628bf215546Sopenharmony_ci   }
629bf215546Sopenharmony_ci
630bf215546Sopenharmony_ci   if (src_image) {
631bf215546Sopenharmony_ci      st_UnmapTextureImage(st->ctx, src_image, src_z);
632bf215546Sopenharmony_ci   } else {
633bf215546Sopenharmony_ci      pipe_texture_unmap(st->pipe, src_transfer);
634bf215546Sopenharmony_ci   }
635bf215546Sopenharmony_ci}
636bf215546Sopenharmony_ci
637bf215546Sopenharmony_civoid
638bf215546Sopenharmony_cist_CopyImageSubData(struct gl_context *ctx,
639bf215546Sopenharmony_ci                    struct gl_texture_image *src_image,
640bf215546Sopenharmony_ci                    struct gl_renderbuffer *src_renderbuffer,
641bf215546Sopenharmony_ci                    int src_x, int src_y, int src_z,
642bf215546Sopenharmony_ci                    struct gl_texture_image *dst_image,
643bf215546Sopenharmony_ci                    struct gl_renderbuffer *dst_renderbuffer,
644bf215546Sopenharmony_ci                    int dst_x, int dst_y, int dst_z,
645bf215546Sopenharmony_ci                    int src_width, int src_height)
646bf215546Sopenharmony_ci{
647bf215546Sopenharmony_ci   struct st_context *st = st_context(ctx);
648bf215546Sopenharmony_ci   struct pipe_context *pipe = st->pipe;
649bf215546Sopenharmony_ci   struct pipe_resource *src_res, *dst_res;
650bf215546Sopenharmony_ci   struct pipe_box box;
651bf215546Sopenharmony_ci   int src_level, dst_level;
652bf215546Sopenharmony_ci   int orig_src_z = src_z, orig_dst_z = dst_z;
653bf215546Sopenharmony_ci
654bf215546Sopenharmony_ci   st_flush_bitmap_cache(st);
655bf215546Sopenharmony_ci   st_invalidate_readpix_cache(st);
656bf215546Sopenharmony_ci
657bf215546Sopenharmony_ci   if (src_image) {
658bf215546Sopenharmony_ci      struct gl_texture_image *src = src_image;
659bf215546Sopenharmony_ci      struct gl_texture_object *stObj = src_image->TexObject;
660bf215546Sopenharmony_ci      src_res = src->pt;
661bf215546Sopenharmony_ci      src_level = stObj->pt != src_res ? 0 : src_image->Level;
662bf215546Sopenharmony_ci      src_z += src_image->Face;
663bf215546Sopenharmony_ci      if (src_image->TexObject->Immutable) {
664bf215546Sopenharmony_ci         src_level += src_image->TexObject->Attrib.MinLevel;
665bf215546Sopenharmony_ci         src_z += src_image->TexObject->Attrib.MinLayer;
666bf215546Sopenharmony_ci      }
667bf215546Sopenharmony_ci   } else {
668bf215546Sopenharmony_ci      src_res = src_renderbuffer->texture;
669bf215546Sopenharmony_ci      src_level = 0;
670bf215546Sopenharmony_ci   }
671bf215546Sopenharmony_ci
672bf215546Sopenharmony_ci   if (dst_image) {
673bf215546Sopenharmony_ci      struct gl_texture_image *dst = dst_image;
674bf215546Sopenharmony_ci      struct gl_texture_object *stObj = dst_image->TexObject;
675bf215546Sopenharmony_ci      dst_res = dst->pt;
676bf215546Sopenharmony_ci      dst_level = stObj->pt != dst_res ? 0 : dst_image->Level;
677bf215546Sopenharmony_ci      dst_z += dst_image->Face;
678bf215546Sopenharmony_ci      if (dst_image->TexObject->Immutable) {
679bf215546Sopenharmony_ci         dst_level += dst_image->TexObject->Attrib.MinLevel;
680bf215546Sopenharmony_ci         dst_z += dst_image->TexObject->Attrib.MinLayer;
681bf215546Sopenharmony_ci      }
682bf215546Sopenharmony_ci   } else {
683bf215546Sopenharmony_ci      dst_res = dst_renderbuffer->texture;
684bf215546Sopenharmony_ci      dst_level = 0;
685bf215546Sopenharmony_ci   }
686bf215546Sopenharmony_ci
687bf215546Sopenharmony_ci   u_box_2d_zslice(src_x, src_y, src_z, src_width, src_height, &box);
688bf215546Sopenharmony_ci
689bf215546Sopenharmony_ci   if ((src_image && st_compressed_format_fallback(st, src_image->TexFormat)) ||
690bf215546Sopenharmony_ci       (dst_image && st_compressed_format_fallback(st, dst_image->TexFormat))) {
691bf215546Sopenharmony_ci      fallback_copy_image(st, dst_image, dst_res, dst_x, dst_y, orig_dst_z,
692bf215546Sopenharmony_ci                          src_image, src_res, src_x, src_y, orig_src_z,
693bf215546Sopenharmony_ci                          src_width, src_height);
694bf215546Sopenharmony_ci   } else {
695bf215546Sopenharmony_ci      copy_image(pipe, dst_res, dst_level, dst_x, dst_y, dst_z,
696bf215546Sopenharmony_ci                 src_res, src_level, &box);
697bf215546Sopenharmony_ci   }
698bf215546Sopenharmony_ci}
699