Home | History | Annotate | Download | only in state_tracker
      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  */
     55 static enum pipe_format
     56 get_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  */
    194 static bool
    195 has_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  */
    209 static enum pipe_format
    210 canonical_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 
    251 static void
    252 blit(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 
    279 static void
    280 swizzled_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 
    337 static bool
    338 same_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 
    361 static struct pipe_resource *
    362 create_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  */
    397 static bool
    398 handle_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 
    487 static void
    488 copy_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 */
    536 static void
    537 fallback_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 
    619 static void
    620 st_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 
    682 void
    683 st_init_copy_image_functions(struct dd_function_table *functions)
    684 {
    685    functions->CopyImageSubData = st_CopyImageSubData;
    686 }
    687