Home | History | Annotate | Download | only in svga
      1 /**********************************************************
      2  * Copyright 2008-2009 VMware, Inc.  All rights reserved.
      3  *
      4  * Permission is hereby granted, free of charge, to any person
      5  * obtaining a copy of this software and associated documentation
      6  * files (the "Software"), to deal in the Software without
      7  * restriction, including without limitation the rights to use, copy,
      8  * modify, merge, publish, distribute, sublicense, and/or sell copies
      9  * of the Software, and to permit persons to whom the Software is
     10  * furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice shall be
     13  * included in all copies or substantial portions of the Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  * SOFTWARE.
     23  *
     24  **********************************************************/
     25 
     26 #include "svga_context.h"
     27 #include "svga_debug.h"
     28 #include "svga_cmd.h"
     29 #include "svga_format.h"
     30 #include "svga_resource_buffer.h"
     31 #include "svga_resource_texture.h"
     32 #include "svga_surface.h"
     33 
     34 //#include "util/u_blit_sw.h"
     35 #include "util/u_format.h"
     36 #include "util/u_surface.h"
     37 
     38 #define FILE_DEBUG_FLAG DEBUG_BLIT
     39 
     40 
     41 /**
     42  * Copy an image between textures with the vgpu10 CopyRegion command.
     43  */
     44 static void
     45 copy_region_vgpu10(struct svga_context *svga, struct pipe_resource *src_tex,
     46                     unsigned src_x, unsigned src_y, unsigned src_z,
     47                     unsigned src_level, unsigned src_face,
     48                     struct pipe_resource *dst_tex,
     49                     unsigned dst_x, unsigned dst_y, unsigned dst_z,
     50                     unsigned dst_level, unsigned dst_face,
     51                     unsigned width, unsigned height, unsigned depth)
     52 {
     53    enum pipe_error ret;
     54    uint32 srcSubResource, dstSubResource;
     55    struct svga_texture *dtex, *stex;
     56    SVGA3dCopyBox box;
     57 
     58    stex = svga_texture(src_tex);
     59    dtex = svga_texture(dst_tex);
     60 
     61    box.x = dst_x;
     62    box.y = dst_y;
     63    box.z = dst_z;
     64    box.w = width;
     65    box.h = height;
     66    box.d = depth;
     67    box.srcx = src_x;
     68    box.srcy = src_y;
     69    box.srcz = src_z;
     70 
     71    srcSubResource = src_face * (src_tex->last_level + 1) + src_level;
     72    dstSubResource = dst_face * (dst_tex->last_level + 1) + dst_level;
     73 
     74    ret = SVGA3D_vgpu10_PredCopyRegion(svga->swc,
     75                                       dtex->handle, dstSubResource,
     76                                       stex->handle, srcSubResource, &box);
     77    if (ret != PIPE_OK) {
     78       svga_context_flush(svga, NULL);
     79       ret = SVGA3D_vgpu10_PredCopyRegion(svga->swc,
     80                                          dtex->handle, dstSubResource,
     81                                          stex->handle, srcSubResource, &box);
     82       assert(ret == PIPE_OK);
     83    }
     84 
     85    /* Mark the texture subresource as defined. */
     86    svga_define_texture_level(dtex, dst_face, dst_level);
     87 
     88    /* Mark the texture subresource as rendered-to. */
     89    svga_set_texture_rendered_to(dtex, dst_face, dst_level);
     90 }
     91 
     92 
     93 /**
     94  * For some texture types, we need to move the z (slice) coordinate
     95  * to the layer value.  For example, to select the z=3 slice of a 2D ARRAY
     96  * texture, we need to use layer=3 and set z=0.
     97  */
     98 static void
     99 adjust_z_layer(enum pipe_texture_target target,
    100                int z_in, unsigned *layer_out, unsigned *z_out)
    101 {
    102    if (target == PIPE_TEXTURE_CUBE ||
    103        target == PIPE_TEXTURE_2D_ARRAY ||
    104        target == PIPE_TEXTURE_1D_ARRAY) {
    105       *layer_out = z_in;
    106       *z_out = 0;
    107    }
    108    else {
    109       *layer_out = 0;
    110       *z_out = z_in;
    111    }
    112 }
    113 
    114 
    115 static void
    116 svga_resource_copy_region(struct pipe_context *pipe,
    117                           struct pipe_resource *dst_tex,
    118                           unsigned dst_level,
    119                           unsigned dstx, unsigned dsty, unsigned dstz,
    120                           struct pipe_resource *src_tex,
    121                           unsigned src_level,
    122                           const struct pipe_box *src_box)
    123 {
    124    struct svga_context *svga = svga_context(pipe);
    125    struct svga_texture *stex, *dtex;
    126    unsigned dst_face_layer, dst_z, src_face_layer, src_z;
    127 
    128    /* Emit buffered drawing commands, and any back copies.
    129     */
    130    svga_surfaces_flush( svga );
    131 
    132    if (dst_tex->target == PIPE_BUFFER && src_tex->target == PIPE_BUFFER) {
    133       /* can't copy within the same buffer, unfortunately */
    134       if (svga_have_vgpu10(svga) && src_tex != dst_tex) {
    135          enum pipe_error ret;
    136          struct svga_winsys_surface *src_surf;
    137          struct svga_winsys_surface *dst_surf;
    138          struct svga_buffer *dbuffer = svga_buffer(dst_tex);
    139 
    140          src_surf = svga_buffer_handle(svga, src_tex);
    141          dst_surf = svga_buffer_handle(svga, dst_tex);
    142 
    143          ret = SVGA3D_vgpu10_BufferCopy(svga->swc, src_surf, dst_surf,
    144                                         src_box->x, dstx, src_box->width);
    145          if (ret != PIPE_OK) {
    146             svga_context_flush(svga, NULL);
    147             ret = SVGA3D_vgpu10_BufferCopy(svga->swc, src_surf, dst_surf,
    148                                            src_box->x, dstx, src_box->width);
    149             assert(ret == PIPE_OK);
    150          }
    151 
    152          dbuffer->dirty = TRUE;
    153       }
    154       else {
    155          /* use map/memcpy fallback */
    156          util_resource_copy_region(pipe, dst_tex, dst_level, dstx,
    157                                    dsty, dstz, src_tex, src_level, src_box);
    158       }
    159       return;
    160    }
    161 
    162    stex = svga_texture(src_tex);
    163    dtex = svga_texture(dst_tex);
    164 
    165    adjust_z_layer(src_tex->target, src_box->z, &src_face_layer, &src_z);
    166    adjust_z_layer(dst_tex->target, dstz, &dst_face_layer, &dst_z);
    167 
    168    if (svga_have_vgpu10(svga)) {
    169       /* vgpu10 */
    170       if (util_format_is_compressed(src_tex->format) ==
    171           util_format_is_compressed(dst_tex->format) &&
    172           stex->handle != dtex->handle &&
    173           svga_resource_type(src_tex->target) ==
    174           svga_resource_type(dst_tex->target) &&
    175           stex->b.b.nr_samples == dtex->b.b.nr_samples) {
    176          copy_region_vgpu10(svga,
    177                             src_tex,
    178                             src_box->x, src_box->y, src_z,
    179                             src_level, src_face_layer,
    180                             dst_tex,
    181                             dstx, dsty, dst_z,
    182                             dst_level, dst_face_layer,
    183                             src_box->width, src_box->height, src_box->depth);
    184       }
    185       else {
    186          util_resource_copy_region(pipe, dst_tex, dst_level, dstx, dsty, dstz,
    187                                    src_tex, src_level, src_box);
    188       }
    189    }
    190    else {
    191       /* vgpu9 */
    192       if (src_tex->format == dst_tex->format) {
    193          svga_texture_copy_handle(svga,
    194                                   stex->handle,
    195                                   src_box->x, src_box->y, src_z,
    196                                   src_level, src_face_layer,
    197                                   dtex->handle,
    198                                   dstx, dsty, dst_z,
    199                                    dst_level, dst_face_layer,
    200                                   src_box->width, src_box->height,
    201                                   src_box->depth);
    202       }
    203       else {
    204          util_resource_copy_region(pipe, dst_tex, dst_level, dstx, dsty, dstz,
    205                                    src_tex, src_level, src_box);
    206       }
    207    }
    208 
    209    /* Mark the destination image as being defined */
    210    svga_define_texture_level(dtex, dst_face_layer, dst_level);
    211 }
    212 
    213 
    214 /**
    215  * Are the given pipe formats compatible, in terms of vgpu10's
    216  * PredCopyRegion() command?
    217  */
    218 static bool
    219 formats_compatible(const struct svga_screen *ss,
    220                    enum pipe_format src_fmt,
    221                    enum pipe_format dst_fmt)
    222 {
    223    SVGA3dSurfaceFormat src_svga_fmt, dst_svga_fmt;
    224 
    225    src_svga_fmt = svga_translate_format(ss, src_fmt, PIPE_BIND_SAMPLER_VIEW);
    226    dst_svga_fmt = svga_translate_format(ss, dst_fmt, PIPE_BIND_SAMPLER_VIEW);
    227 
    228    src_svga_fmt = svga_typeless_format(src_svga_fmt);
    229    dst_svga_fmt = svga_typeless_format(dst_svga_fmt);
    230 
    231    return src_svga_fmt == dst_svga_fmt;
    232 }
    233 
    234 
    235 /**
    236  * The state tracker implements some resource copies with blits (for
    237  * GL_ARB_copy_image).  This function checks if we should really do the blit
    238  * with a VGPU10 CopyRegion command or software fallback (for incompatible
    239  * src/dst formats).
    240  */
    241 static bool
    242 can_blit_via_copy_region_vgpu10(struct svga_context *svga,
    243                                 const struct pipe_blit_info *blit_info)
    244 {
    245    struct svga_texture *dtex, *stex;
    246 
    247    if (!svga_have_vgpu10(svga))
    248       return false;
    249 
    250    stex = svga_texture(blit_info->src.resource);
    251    dtex = svga_texture(blit_info->dst.resource);
    252 
    253    /* can't copy within one resource */
    254    if (stex->handle == dtex->handle)
    255       return false;
    256 
    257    /* can't copy between different resource types */
    258    if (svga_resource_type(blit_info->src.resource->target) !=
    259        svga_resource_type(blit_info->dst.resource->target))
    260       return false;
    261 
    262    /* check that the blit src/dst regions are same size, no flipping, etc. */
    263    if (blit_info->src.box.width != blit_info->dst.box.width ||
    264        blit_info->src.box.height != blit_info->dst.box.height)
    265       return false;
    266 
    267    /* check that sample counts are the same */
    268    if (stex->b.b.nr_samples != dtex->b.b.nr_samples)
    269       return false;
    270 
    271    /* For depth+stencil formats, copy with mask != PIPE_MASK_ZS is not
    272     * supported
    273     */
    274    if (util_format_is_depth_and_stencil(blit_info->src.format) &&
    275       blit_info->mask != (PIPE_MASK_ZS))
    276      return false;
    277 
    278    if (blit_info->alpha_blend ||
    279        (svga->render_condition && blit_info->render_condition_enable) ||
    280        blit_info->scissor_enable)
    281       return false;
    282 
    283    return formats_compatible(svga_screen(svga->pipe.screen),
    284                              blit_info->src.resource->format,
    285                              blit_info->dst.resource->format);
    286 }
    287 
    288 
    289 /**
    290  * A helper function to determine if the specified view format
    291  * is compatible with the surface format.
    292  * It is compatible if the view format is the same as the surface format,
    293  * or the associated svga format for the surface is a typeless format, or
    294  * the view format is an adjusted format for BGRX/BGRA resource.
    295  */
    296 static bool
    297 is_view_format_compatible(enum pipe_format surf_fmt,
    298                           SVGA3dSurfaceFormat surf_svga_fmt,
    299                           enum pipe_format view_fmt)
    300 {
    301    if (surf_fmt == view_fmt || svga_format_is_typeless(surf_svga_fmt))
    302       return true;
    303 
    304    if ((surf_fmt == PIPE_FORMAT_B8G8R8X8_UNORM &&
    305         view_fmt == PIPE_FORMAT_B8G8R8A8_UNORM) ||
    306        (surf_fmt == PIPE_FORMAT_B8G8R8A8_UNORM &&
    307         view_fmt == PIPE_FORMAT_B8G8R8X8_UNORM))
    308       return true;
    309 
    310    return false;
    311 }
    312 
    313 
    314 static void
    315 svga_blit(struct pipe_context *pipe,
    316           const struct pipe_blit_info *blit_info)
    317 {
    318    struct svga_context *svga = svga_context(pipe);
    319    struct pipe_blit_info blit = *blit_info;
    320    struct pipe_resource *src = blit.src.resource;
    321    struct pipe_resource *dst = blit.dst.resource;
    322    struct pipe_resource *newSrc = NULL;
    323    struct pipe_resource *newDst = NULL;
    324    bool can_create_src_view;
    325    bool can_create_dst_view;
    326 
    327    if (!svga_have_vgpu10(svga) &&
    328        blit.src.resource->nr_samples > 1 &&
    329        blit.dst.resource->nr_samples <= 1 &&
    330        !util_format_is_depth_or_stencil(blit.src.resource->format) &&
    331        !util_format_is_pure_integer(blit.src.resource->format)) {
    332       debug_printf("svga: color resolve unimplemented\n");
    333       return;
    334    }
    335 
    336    if (can_blit_via_copy_region_vgpu10(svga, blit_info)) {
    337       unsigned src_face, src_z, dst_face, dst_z;
    338 
    339       adjust_z_layer(blit.src.resource->target, blit.src.box.z,
    340                      &src_face, &src_z);
    341 
    342       adjust_z_layer(blit.dst.resource->target, blit.dst.box.z,
    343                      &dst_face, &dst_z);
    344 
    345       copy_region_vgpu10(svga,
    346                          blit.src.resource,
    347                          blit.src.box.x, blit.src.box.y, src_z,
    348                          blit.src.level, src_face,
    349                          blit.dst.resource,
    350                          blit.dst.box.x, blit.dst.box.y, dst_z,
    351                          blit.dst.level, dst_face,
    352                          blit.src.box.width, blit.src.box.height,
    353                          blit.src.box.depth);
    354       return;
    355    }
    356 
    357    if (util_can_blit_via_copy_region(blit_info, TRUE) ||
    358        util_can_blit_via_copy_region(blit_info, FALSE)) {
    359       util_resource_copy_region(pipe, blit.dst.resource,
    360                                 blit.dst.level,
    361                                 blit.dst.box.x, blit.dst.box.y,
    362                                 blit.dst.box.z, blit.src.resource,
    363                                 blit.src.level, &blit.src.box);
    364       return; /* done */
    365    }
    366 
    367    /* Check if we can create shader resource view and
    368     * render target view for the quad blitter to work
    369     */
    370    can_create_src_view =
    371       is_view_format_compatible(src->format, svga_texture(src)->key.format,
    372                                 blit.src.format);
    373 
    374    can_create_dst_view =
    375       is_view_format_compatible(dst->format, svga_texture(dst)->key.format,
    376                                 blit.dst.format);
    377 
    378    if ((blit.mask & PIPE_MASK_S) ||
    379        ((!can_create_dst_view || !can_create_src_view)
    380         && !svga_have_vgpu10(svga)) ||
    381        !util_blitter_is_blit_supported(svga->blitter, &blit)) {
    382       debug_printf("svga: blit unsupported %s -> %s\n",
    383                    util_format_short_name(blit.src.resource->format),
    384                    util_format_short_name(blit.dst.resource->format));
    385       return;
    386    }
    387 
    388    /* XXX turn off occlusion and streamout queries */
    389 
    390    util_blitter_save_vertex_buffer_slot(svga->blitter, svga->curr.vb);
    391    util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems);
    392    util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs);
    393    util_blitter_save_geometry_shader(svga->blitter, svga->curr.user_gs);
    394    util_blitter_save_so_targets(svga->blitter, svga->num_so_targets,
    395                      (struct pipe_stream_output_target**)svga->so_targets);
    396    util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast);
    397    util_blitter_save_viewport(svga->blitter, &svga->curr.viewport);
    398    util_blitter_save_scissor(svga->blitter, &svga->curr.scissor);
    399    util_blitter_save_fragment_shader(svga->blitter, svga->curr.fs);
    400    util_blitter_save_blend(svga->blitter, (void*)svga->curr.blend);
    401    util_blitter_save_depth_stencil_alpha(svga->blitter,
    402                                          (void*)svga->curr.depth);
    403    util_blitter_save_stencil_ref(svga->blitter, &svga->curr.stencil_ref);
    404    util_blitter_save_sample_mask(svga->blitter, svga->curr.sample_mask);
    405    util_blitter_save_framebuffer(svga->blitter, &svga->curr.framebuffer);
    406    util_blitter_save_fragment_sampler_states(svga->blitter,
    407                      svga->curr.num_samplers[PIPE_SHADER_FRAGMENT],
    408                      (void**)svga->curr.sampler[PIPE_SHADER_FRAGMENT]);
    409    util_blitter_save_fragment_sampler_views(svga->blitter,
    410                      svga->curr.num_sampler_views[PIPE_SHADER_FRAGMENT],
    411                      svga->curr.sampler_views[PIPE_SHADER_FRAGMENT]);
    412    /*util_blitter_save_render_condition(svga->blitter, svga->render_cond_query,
    413                                       svga->render_cond_cond, svga->render_cond_mode);*/
    414 
    415    if (!can_create_src_view) {
    416       struct pipe_resource template;
    417       unsigned src_face, src_z;
    418 
    419       /**
    420        * If the source blit format is not compatible with the source resource
    421        * format, we will not be able to create a shader resource view.
    422        * In order to avoid falling back to software blit, we'll create
    423        * a new resource in the blit format, and use DXCopyResource to
    424        * copy from the original format to the new format. The new
    425        * resource will be used for the blit in util_blitter_blit().
    426        */
    427       template = *src;
    428       template.format = blit.src.format;
    429       newSrc = svga_texture_create(svga->pipe.screen, &template);
    430       if (newSrc == NULL) {
    431          debug_printf("svga_blit: fails to create temporary src\n");
    432          return;
    433       }
    434 
    435       /* Copy from original resource to the temporary resource */
    436       adjust_z_layer(blit.src.resource->target, blit.src.box.z,
    437                      &src_face, &src_z);
    438 
    439       copy_region_vgpu10(svga,
    440                          blit.src.resource,
    441                          blit.src.box.x, blit.src.box.y, src_z,
    442                          blit.src.level, src_face,
    443                          newSrc,
    444                          blit.src.box.x, blit.src.box.y, src_z,
    445                          blit.src.level, src_face,
    446                          blit.src.box.width, blit.src.box.height,
    447                          blit.src.box.depth);
    448 
    449       blit.src.resource = newSrc;
    450    }
    451 
    452    if (!can_create_dst_view) {
    453       struct pipe_resource template;
    454 
    455       /**
    456        * If the destination blit format is not compatible with the destination
    457        * resource format, we will not be able to create a render target view.
    458        * In order to avoid falling back to software blit, we'll create
    459        * a new resource in the blit format, and use DXPredCopyRegion
    460        * after the blit to copy from the blit format back to the resource
    461        * format.
    462        */
    463       template = *dst;
    464       template.format = blit.dst.format;
    465       newDst = svga_texture_create(svga->pipe.screen, &template);
    466       if (newDst == NULL) {
    467          debug_printf("svga_blit: fails to create temporary dst\n");
    468          return;
    469       }
    470 
    471       blit.dst.resource = newDst;
    472    }
    473 
    474    util_blitter_blit(svga->blitter, &blit);
    475 
    476    if (blit.dst.resource != dst) {
    477       unsigned dst_face, dst_z;
    478 
    479       adjust_z_layer(blit.dst.resource->target, blit.dst.box.z,
    480                      &dst_face, &dst_z);
    481 
    482       /**
    483        * A temporary resource was created for the blit, we need to
    484        * copy from the temporary resource back to the original destination.
    485        */
    486       copy_region_vgpu10(svga,
    487                          blit.dst.resource,
    488                          blit.dst.box.x, blit.dst.box.y, dst_z,
    489                          blit.dst.level, dst_face,
    490                          dst,
    491                          blit.dst.box.x, blit.dst.box.y, dst_z,
    492                          blit.dst.level, dst_face,
    493                          blit.dst.box.width, blit.dst.box.height,
    494                          blit.dst.box.depth);
    495 
    496       /* unreference the temporary resource */
    497       pipe_resource_reference(&newDst, NULL);
    498       blit.dst.resource = dst;
    499    }
    500 
    501    if (blit.src.resource != src) {
    502       /* unreference the temporary resource */
    503       pipe_resource_reference(&newSrc, NULL);
    504       blit.src.resource = src;
    505    }
    506 }
    507 
    508 
    509 static void
    510 svga_flush_resource(struct pipe_context *pipe,
    511                     struct pipe_resource *resource)
    512 {
    513 }
    514 
    515 
    516 void
    517 svga_init_blit_functions(struct svga_context *svga)
    518 {
    519    svga->pipe.resource_copy_region = svga_resource_copy_region;
    520    svga->pipe.blit = svga_blit;
    521    svga->pipe.flush_resource = svga_flush_resource;
    522 }
    523