"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/drivers/r300/r300_transfer.c" (16 Sep 2020, 9556 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "r300_transfer.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
    3  * Copyright 2010 Marek Olšák <maraeo@gmail.com>
    4  *
    5  * Permission is hereby granted, free of charge, to any person obtaining a
    6  * copy of this software and associated documentation files (the "Software"),
    7  * to deal in the Software without restriction, including without limitation
    8  * on the rights to use, copy, modify, merge, publish, distribute, sub
    9  * license, and/or sell copies of the Software, and to permit persons to whom
   10  * the Software is furnished to do so, subject to the following conditions:
   11  *
   12  * The above copyright notice and this permission notice (including the next
   13  * paragraph) shall be included in all copies or substantial portions of the
   14  * Software.
   15  *
   16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
   19  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
   20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
   21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
   22  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
   23 
   24 #include "r300_transfer.h"
   25 #include "r300_texture_desc.h"
   26 #include "r300_screen_buffer.h"
   27 
   28 #include "util/u_memory.h"
   29 #include "util/format/u_format.h"
   30 #include "util/u_box.h"
   31 
   32 struct r300_transfer {
   33     /* Parent class */
   34     struct pipe_transfer transfer;
   35 
   36     /* Offset from start of buffer. */
   37     unsigned offset;
   38 
   39     /* Linear texture. */
   40     struct r300_resource *linear_texture;
   41 };
   42 
   43 /* Convenience cast wrapper. */
   44 static inline struct r300_transfer*
   45 r300_transfer(struct pipe_transfer* transfer)
   46 {
   47     return (struct r300_transfer*)transfer;
   48 }
   49 
   50 /* Copy from a tiled texture to a detiled one. */
   51 static void r300_copy_from_tiled_texture(struct pipe_context *ctx,
   52                                          struct r300_transfer *r300transfer)
   53 {
   54     struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer;
   55     struct pipe_resource *src = transfer->resource;
   56     struct pipe_resource *dst = &r300transfer->linear_texture->b.b;
   57 
   58     if (src->nr_samples <= 1) {
   59         ctx->resource_copy_region(ctx, dst, 0, 0, 0, 0,
   60                                   src, transfer->level, &transfer->box);
   61     } else {
   62         /* Resolve the resource. */
   63         struct pipe_blit_info blit;
   64 
   65         memset(&blit, 0, sizeof(blit));
   66         blit.src.resource = src;
   67         blit.src.format = src->format;
   68         blit.src.level = transfer->level;
   69         blit.src.box = transfer->box;
   70         blit.dst.resource = dst;
   71         blit.dst.format = dst->format;
   72         blit.dst.box.width = transfer->box.width;
   73         blit.dst.box.height = transfer->box.height;
   74         blit.dst.box.depth = transfer->box.depth;
   75         blit.mask = PIPE_MASK_RGBA;
   76         blit.filter = PIPE_TEX_FILTER_NEAREST;
   77 
   78         ctx->blit(ctx, &blit);
   79     }
   80 }
   81 
   82 /* Copy a detiled texture to a tiled one. */
   83 static void r300_copy_into_tiled_texture(struct pipe_context *ctx,
   84                                          struct r300_transfer *r300transfer)
   85 {
   86     struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer;
   87     struct pipe_resource *tex = transfer->resource;
   88     struct pipe_box src_box;
   89 
   90     u_box_3d(0, 0, 0,
   91              transfer->box.width, transfer->box.height, transfer->box.depth,
   92              &src_box);
   93 
   94     ctx->resource_copy_region(ctx, tex, transfer->level,
   95                               transfer->box.x, transfer->box.y, transfer->box.z,
   96                               &r300transfer->linear_texture->b.b, 0, &src_box);
   97 
   98     /* XXX remove this. */
   99     r300_flush(ctx, 0, NULL);
  100 }
  101 
  102 void *
  103 r300_texture_transfer_map(struct pipe_context *ctx,
  104                           struct pipe_resource *texture,
  105                           unsigned level,
  106                           unsigned usage,
  107                           const struct pipe_box *box,
  108                           struct pipe_transfer **transfer)
  109 {
  110     struct r300_context *r300 = r300_context(ctx);
  111     struct r300_resource *tex = r300_resource(texture);
  112     struct r300_transfer *trans;
  113     boolean referenced_cs, referenced_hw;
  114     enum pipe_format format = tex->b.b.format;
  115     char *map;
  116 
  117     referenced_cs =
  118         r300->rws->cs_is_buffer_referenced(r300->cs, tex->buf, RADEON_USAGE_READWRITE);
  119     if (referenced_cs) {
  120         referenced_hw = TRUE;
  121     } else {
  122         referenced_hw =
  123             !r300->rws->buffer_wait(tex->buf, 0, RADEON_USAGE_READWRITE);
  124     }
  125 
  126     trans = CALLOC_STRUCT(r300_transfer);
  127     if (trans) {
  128         /* Initialize the transfer object. */
  129         trans->transfer.resource = texture;
  130         trans->transfer.level = level;
  131         trans->transfer.usage = usage;
  132         trans->transfer.box = *box;
  133 
  134         /* If the texture is tiled, we must create a temporary detiled texture
  135          * for this transfer.
  136          * Also make write transfers pipelined. */
  137         if (tex->tex.microtile || tex->tex.macrotile[level] ||
  138             (referenced_hw && !(usage & PIPE_TRANSFER_READ) &&
  139              r300_is_blit_supported(texture->format))) {
  140             struct pipe_resource base;
  141 
  142             if (r300->blitter->running) {
  143                 fprintf(stderr, "r300: ERROR: Blitter recursion in texture_get_transfer.\n");
  144                 os_break();
  145             }
  146 
  147             memset(&base, 0, sizeof(base));
  148             base.target = PIPE_TEXTURE_2D;
  149             base.format = texture->format;
  150             base.width0 = box->width;
  151             base.height0 = box->height;
  152             base.depth0 = 1;
  153             base.array_size = 1;
  154             base.usage = PIPE_USAGE_STAGING;
  155             base.flags = R300_RESOURCE_FLAG_TRANSFER;
  156 
  157             /* We must set the correct texture target and dimensions if needed for a 3D transfer. */
  158             if (box->depth > 1 && util_max_layer(texture, level) > 0) {
  159                 base.target = texture->target;
  160 
  161                 if (base.target == PIPE_TEXTURE_3D) {
  162                     base.depth0 = util_next_power_of_two(box->depth);
  163                 }
  164             }
  165 
  166             /* Create the temporary texture. */
  167             trans->linear_texture = r300_resource(
  168                ctx->screen->resource_create(ctx->screen,
  169                                             &base));
  170 
  171             if (!trans->linear_texture) {
  172                 /* Oh crap, the thing can't create the texture.
  173                  * Let's flush and try again. */
  174                 r300_flush(ctx, 0, NULL);
  175 
  176                 trans->linear_texture = r300_resource(
  177                    ctx->screen->resource_create(ctx->screen,
  178                                                 &base));
  179 
  180                 if (!trans->linear_texture) {
  181                     fprintf(stderr,
  182                             "r300: Failed to create a transfer object.\n");
  183                     FREE(trans);
  184                     return NULL;
  185                 }
  186             }
  187 
  188             assert(!trans->linear_texture->tex.microtile &&
  189                    !trans->linear_texture->tex.macrotile[0]);
  190 
  191             /* Set the stride. */
  192             trans->transfer.stride =
  193                     trans->linear_texture->tex.stride_in_bytes[0];
  194             trans->transfer.layer_stride =
  195                     trans->linear_texture->tex.layer_size_in_bytes[0];
  196 
  197             if (usage & PIPE_TRANSFER_READ) {
  198                 /* We cannot map a tiled texture directly because the data is
  199                  * in a different order, therefore we do detiling using a blit. */
  200                 r300_copy_from_tiled_texture(ctx, trans);
  201 
  202                 /* Always referenced in the blit. */
  203                 r300_flush(ctx, 0, NULL);
  204             }
  205         } else {
  206             /* Unpipelined transfer. */
  207             trans->transfer.stride = tex->tex.stride_in_bytes[level];
  208             trans->transfer.layer_stride = tex->tex.layer_size_in_bytes[level];
  209             trans->offset = r300_texture_get_offset(tex, level, box->z);
  210 
  211             if (referenced_cs &&
  212                 !(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
  213                 r300_flush(ctx, 0, NULL);
  214             }
  215         }
  216     }
  217 
  218     if (trans->linear_texture) {
  219         /* The detiled texture is of the same size as the region being mapped
  220          * (no offset needed). */
  221         map = r300->rws->buffer_map(trans->linear_texture->buf,
  222                                     r300->cs, usage);
  223         if (!map) {
  224             pipe_resource_reference(
  225                 (struct pipe_resource**)&trans->linear_texture, NULL);
  226             FREE(trans);
  227             return NULL;
  228         }
  229     *transfer = &trans->transfer;
  230         return map;
  231     } else {
  232         /* Tiling is disabled. */
  233         map = r300->rws->buffer_map(tex->buf, r300->cs, usage);
  234         if (!map) {
  235             FREE(trans);
  236             return NULL;
  237         }
  238 
  239     *transfer = &trans->transfer;
  240         return map + trans->offset +
  241             box->y / util_format_get_blockheight(format) * trans->transfer.stride +
  242             box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
  243     }
  244 }
  245 
  246 void r300_texture_transfer_unmap(struct pipe_context *ctx,
  247                  struct pipe_transfer *transfer)
  248 {
  249     struct r300_transfer *trans = r300_transfer(transfer);
  250 
  251     if (trans->linear_texture) {
  252         if (transfer->usage & PIPE_TRANSFER_WRITE) {
  253             r300_copy_into_tiled_texture(ctx, trans);
  254         }
  255 
  256         pipe_resource_reference(
  257             (struct pipe_resource**)&trans->linear_texture, NULL);
  258     }
  259     FREE(transfer);
  260 }