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