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