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_cmd.h"
     27 
     28 #include "pipe/p_state.h"
     29 #include "pipe/p_defines.h"
     30 #include "util/u_inlines.h"
     31 #include "os/os_thread.h"
     32 #include "util/u_bitmask.h"
     33 #include "util/u_format.h"
     34 #include "util/u_math.h"
     35 #include "util/u_memory.h"
     36 
     37 #include "svga_format.h"
     38 #include "svga_screen.h"
     39 #include "svga_context.h"
     40 #include "svga_sampler_view.h"
     41 #include "svga_resource_texture.h"
     42 #include "svga_surface.h"
     43 #include "svga_debug.h"
     44 
     45 static void svga_mark_surface_dirty(struct pipe_surface *surf);
     46 
     47 void
     48 svga_texture_copy_handle(struct svga_context *svga,
     49                          struct svga_winsys_surface *src_handle,
     50                          unsigned src_x, unsigned src_y, unsigned src_z,
     51                          unsigned src_level, unsigned src_layer,
     52                          struct svga_winsys_surface *dst_handle,
     53                          unsigned dst_x, unsigned dst_y, unsigned dst_z,
     54                          unsigned dst_level, unsigned dst_layer,
     55                          unsigned width, unsigned height, unsigned depth)
     56 {
     57    struct svga_surface dst, src;
     58    enum pipe_error ret;
     59    SVGA3dCopyBox box, *boxes;
     60 
     61    assert(svga);
     62 
     63    src.handle = src_handle;
     64    src.real_level = src_level;
     65    src.real_layer = src_layer;
     66    src.real_zslice = 0;
     67 
     68    dst.handle = dst_handle;
     69    dst.real_level = dst_level;
     70    dst.real_layer = dst_layer;
     71    dst.real_zslice = 0;
     72 
     73    box.x = dst_x;
     74    box.y = dst_y;
     75    box.z = dst_z;
     76    box.w = width;
     77    box.h = height;
     78    box.d = depth;
     79    box.srcx = src_x;
     80    box.srcy = src_y;
     81    box.srcz = src_z;
     82 
     83 /*
     84    SVGA_DBG(DEBUG_VIEWS, "mipcopy src: %p %u (%ux%ux%u), dst: %p %u (%ux%ux%u)\n",
     85             src_handle, src_level, src_x, src_y, src_z,
     86             dst_handle, dst_level, dst_x, dst_y, dst_z);
     87 */
     88 
     89    ret = SVGA3D_BeginSurfaceCopy(svga->swc,
     90                                  &src.base,
     91                                  &dst.base,
     92                                  &boxes, 1);
     93    if (ret != PIPE_OK) {
     94       svga_context_flush(svga, NULL);
     95       ret = SVGA3D_BeginSurfaceCopy(svga->swc,
     96                                     &src.base,
     97                                     &dst.base,
     98                                     &boxes, 1);
     99       assert(ret == PIPE_OK);
    100    }
    101    *boxes = box;
    102    SVGA_FIFOCommitAll(svga->swc);
    103 }
    104 
    105 
    106 struct svga_winsys_surface *
    107 svga_texture_view_surface(struct svga_context *svga,
    108                           struct svga_texture *tex,
    109                           unsigned bind_flags,
    110                           SVGA3dSurfaceFlags flags,
    111                           SVGA3dSurfaceFormat format,
    112                           unsigned start_mip,
    113                           unsigned num_mip,
    114                           int layer_pick,
    115                           unsigned num_layers,
    116                           int zslice_pick,
    117                           struct svga_host_surface_cache_key *key) /* OUT */
    118 {
    119    struct svga_screen *ss = svga_screen(svga->pipe.screen);
    120    struct svga_winsys_surface *handle;
    121    uint32_t i, j;
    122    unsigned z_offset = 0;
    123    boolean validated;
    124 
    125    SVGA_DBG(DEBUG_PERF,
    126             "svga: Create surface view: layer %d zslice %d mips %d..%d\n",
    127             layer_pick, zslice_pick, start_mip, start_mip+num_mip-1);
    128 
    129    key->flags = flags;
    130    key->format = format;
    131    key->numMipLevels = num_mip;
    132    key->size.width = u_minify(tex->b.b.width0, start_mip);
    133    key->size.height = u_minify(tex->b.b.height0, start_mip);
    134    key->size.depth = zslice_pick < 0 ? u_minify(tex->b.b.depth0, start_mip) : 1;
    135    key->cachable = 1;
    136    key->arraySize = 1;
    137    key->numFaces = 1;
    138 
    139    /* single sample surface can be treated as non-multisamples surface */
    140    key->sampleCount = tex->b.b.nr_samples > 1 ? tex->b.b.nr_samples : 0;
    141 
    142    if (key->sampleCount > 1) {
    143       key->flags |= SVGA3D_SURFACE_MASKABLE_ANTIALIAS;
    144    }
    145 
    146    if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) {
    147       key->flags |= SVGA3D_SURFACE_CUBEMAP;
    148       key->numFaces = 6;
    149    } else if (tex->b.b.target == PIPE_TEXTURE_1D_ARRAY ||
    150               tex->b.b.target == PIPE_TEXTURE_2D_ARRAY) {
    151       key->arraySize = num_layers;
    152    }
    153 
    154    if (key->format == SVGA3D_FORMAT_INVALID) {
    155       key->cachable = 0;
    156       return NULL;
    157    }
    158 
    159    SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n");
    160    handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT,
    161                                        &validated, key);
    162    if (!handle) {
    163       key->cachable = 0;
    164       return NULL;
    165    }
    166 
    167    SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle);
    168 
    169    if (layer_pick < 0)
    170       layer_pick = 0;
    171 
    172    if (zslice_pick >= 0)
    173       z_offset = zslice_pick;
    174 
    175    for (i = 0; i < key->numMipLevels; i++) {
    176       for (j = 0; j < key->numFaces * key->arraySize; j++) {
    177          if (svga_is_texture_level_defined(tex, j + layer_pick, i + start_mip)) {
    178             unsigned depth = (zslice_pick < 0 ?
    179                               u_minify(tex->b.b.depth0, i + start_mip) :
    180                               1);
    181 
    182             svga_texture_copy_handle(svga,
    183                                      tex->handle,
    184                                      0, 0, z_offset,
    185                                      i + start_mip,
    186                                      j + layer_pick,
    187                                      handle, 0, 0, 0, i, j,
    188                                      u_minify(tex->b.b.width0, i + start_mip),
    189                                      u_minify(tex->b.b.height0, i + start_mip),
    190                                      depth);
    191          }
    192       }
    193    }
    194 
    195    return handle;
    196 }
    197 
    198 
    199 /**
    200  * A helper function to create a surface view.
    201  * The view boolean flag specifies whether svga_texture_view_surface()
    202  * will be called to create a cloned surface and resource for the view.
    203  */
    204 static struct pipe_surface *
    205 svga_create_surface_view(struct pipe_context *pipe,
    206                          struct pipe_resource *pt,
    207                          const struct pipe_surface *surf_tmpl,
    208                          boolean view)
    209 {
    210    struct svga_context *svga = svga_context(pipe);
    211    struct svga_texture *tex = svga_texture(pt);
    212    struct pipe_screen *screen = pipe->screen;
    213    struct svga_screen *ss = svga_screen(screen);
    214    struct svga_surface *s;
    215    unsigned layer, zslice, bind;
    216    unsigned nlayers = 1;
    217    SVGA3dSurfaceFlags flags = 0;
    218    SVGA3dSurfaceFormat format;
    219    struct pipe_surface *retVal = NULL;
    220 
    221    s = CALLOC_STRUCT(svga_surface);
    222    if (!s)
    223       return NULL;
    224 
    225    SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_CREATESURFACEVIEW);
    226 
    227    if (pt->target == PIPE_TEXTURE_CUBE) {
    228       layer = surf_tmpl->u.tex.first_layer;
    229       zslice = 0;
    230    }
    231    else if (pt->target == PIPE_TEXTURE_1D_ARRAY ||
    232             pt->target == PIPE_TEXTURE_2D_ARRAY) {
    233       layer = surf_tmpl->u.tex.first_layer;
    234       zslice = 0;
    235       nlayers = surf_tmpl->u.tex.last_layer - surf_tmpl->u.tex.first_layer + 1;
    236    }
    237    else {
    238       layer = 0;
    239       zslice = surf_tmpl->u.tex.first_layer;
    240    }
    241 
    242    pipe_reference_init(&s->base.reference, 1);
    243    pipe_resource_reference(&s->base.texture, pt);
    244    s->base.context = pipe;
    245    s->base.format = surf_tmpl->format;
    246    s->base.width = u_minify(pt->width0, surf_tmpl->u.tex.level);
    247    s->base.height = u_minify(pt->height0, surf_tmpl->u.tex.level);
    248    s->base.u.tex.level = surf_tmpl->u.tex.level;
    249    s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
    250    s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
    251    s->view_id = SVGA3D_INVALID_ID;
    252 
    253    s->backed = NULL;
    254 
    255    if (util_format_is_depth_or_stencil(surf_tmpl->format)) {
    256       flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL |
    257               SVGA3D_SURFACE_BIND_DEPTH_STENCIL;
    258       bind = PIPE_BIND_DEPTH_STENCIL;
    259    }
    260    else {
    261       flags = SVGA3D_SURFACE_HINT_RENDERTARGET |
    262               SVGA3D_SURFACE_BIND_RENDER_TARGET;
    263       bind = PIPE_BIND_RENDER_TARGET;
    264    }
    265 
    266    if (tex->imported)
    267       format = tex->key.format;
    268    else
    269       format = svga_translate_format(ss, surf_tmpl->format, bind);
    270 
    271    assert(format != SVGA3D_FORMAT_INVALID);
    272 
    273    if (view) {
    274       SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: yes %p, level %u layer %u z %u, %p\n",
    275                pt, surf_tmpl->u.tex.level, layer, zslice, s);
    276 
    277       if (svga_have_vgpu10(svga)) {
    278          switch (pt->target) {
    279          case PIPE_TEXTURE_1D:
    280             flags |= SVGA3D_SURFACE_1D;
    281             break;
    282          case PIPE_TEXTURE_1D_ARRAY:
    283             flags |= SVGA3D_SURFACE_1D | SVGA3D_SURFACE_ARRAY;
    284             break;
    285          case PIPE_TEXTURE_2D_ARRAY:
    286             flags |= SVGA3D_SURFACE_ARRAY;
    287             break;
    288          case PIPE_TEXTURE_3D:
    289             flags |= SVGA3D_SURFACE_VOLUME;
    290             break;
    291          case PIPE_TEXTURE_CUBE:
    292             if (nlayers == 6)
    293                flags |= SVGA3D_SURFACE_CUBEMAP;
    294             break;
    295          default:
    296             break;
    297          }
    298       }
    299 
    300       /* When we clone the surface view resource, use the format used in
    301        * the creation of the original resource.
    302        */
    303       s->handle = svga_texture_view_surface(svga, tex, bind, flags,
    304                                             tex->key.format,
    305                                             surf_tmpl->u.tex.level, 1,
    306                                             layer, nlayers, zslice, &s->key);
    307       if (!s->handle) {
    308          FREE(s);
    309          goto done;
    310       }
    311 
    312       s->key.format = format;
    313       s->real_layer = 0;
    314       s->real_level = 0;
    315       s->real_zslice = 0;
    316    } else {
    317       SVGA_DBG(DEBUG_VIEWS,
    318                "svga: Surface view: no %p, level %u, layer %u, z %u, %p\n",
    319                pt, surf_tmpl->u.tex.level, layer, zslice, s);
    320 
    321       memset(&s->key, 0, sizeof s->key);
    322       s->key.format = format;
    323       s->handle = tex->handle;
    324       s->real_layer = layer;
    325       s->real_zslice = zslice;
    326       s->real_level = surf_tmpl->u.tex.level;
    327    }
    328 
    329    svga->hud.num_surface_views++;
    330    retVal = &s->base;
    331 
    332 done:
    333    SVGA_STATS_TIME_POP(ss->sws);
    334    return retVal;
    335 }
    336 
    337 
    338 static struct pipe_surface *
    339 svga_create_surface(struct pipe_context *pipe,
    340                     struct pipe_resource *pt,
    341                     const struct pipe_surface *surf_tmpl)
    342 {
    343    struct svga_context *svga = svga_context(pipe);
    344    struct pipe_screen *screen = pipe->screen;
    345    struct pipe_surface *surf = NULL;
    346    boolean view = FALSE;
    347 
    348    SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATESURFACE);
    349 
    350    if (svga_screen(screen)->debug.force_surface_view)
    351       view = TRUE;
    352 
    353    if (surf_tmpl->u.tex.level != 0 &&
    354        svga_screen(screen)->debug.force_level_surface_view)
    355       view = TRUE;
    356 
    357    if (pt->target == PIPE_TEXTURE_3D)
    358       view = TRUE;
    359 
    360    if (svga_have_vgpu10(svga) || svga_screen(screen)->debug.no_surface_view)
    361       view = FALSE;
    362 
    363    surf = svga_create_surface_view(pipe, pt, surf_tmpl, view);
    364 
    365    SVGA_STATS_TIME_POP(svga_sws(svga));
    366 
    367    return surf;
    368 }
    369 
    370 
    371 /**
    372  * Clone the surface view and its associated resource.
    373  */
    374 static struct svga_surface *
    375 create_backed_surface_view(struct svga_context *svga, struct svga_surface *s)
    376 {
    377    SVGA_STATS_TIME_PUSH(svga_sws(svga),
    378                         SVGA_STATS_TIME_CREATEBACKEDSURFACEVIEW);
    379 
    380    if (!s->backed) {
    381       struct svga_texture *tex = svga_texture(s->base.texture);
    382       struct pipe_surface *backed_view;
    383 
    384       backed_view = svga_create_surface_view(&svga->pipe,
    385                                              &tex->b.b,
    386                                              &s->base,
    387                                              TRUE);
    388       if (!backed_view)
    389          return NULL;
    390 
    391       s->backed = svga_surface(backed_view);
    392    }
    393 
    394    svga_mark_surface_dirty(&s->backed->base);
    395 
    396    SVGA_STATS_TIME_POP(svga_sws(svga));
    397 
    398    return s->backed;
    399 }
    400 
    401 /**
    402  * Create a DX RenderTarget/DepthStencil View for the given surface,
    403  * if needed.
    404  */
    405 struct pipe_surface *
    406 svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s)
    407 {
    408    enum pipe_error ret = PIPE_OK;
    409    enum pipe_shader_type shader;
    410 
    411    assert(svga_have_vgpu10(svga));
    412    assert(s);
    413 
    414    SVGA_STATS_TIME_PUSH(svga_sws(svga),
    415                         SVGA_STATS_TIME_VALIDATESURFACEVIEW);
    416 
    417    /**
    418     * DX spec explicitly specifies that no resource can be bound to a render
    419     * target view and a shader resource view simultanously.
    420     * So first check if the resource bound to this surface view collides with
    421     * a sampler view. If so, then we will clone this surface view and its
    422     * associated resource. We will then use the cloned surface view for
    423     * render target.
    424     */
    425    for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
    426       if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) {
    427          SVGA_DBG(DEBUG_VIEWS,
    428                   "same resource used in shaderResource and renderTarget 0x%x\n",
    429                   s->handle);
    430          s = create_backed_surface_view(svga, s);
    431          /* s may be null here if the function failed */
    432          break;
    433       }
    434    }
    435 
    436    if (s && s->view_id == SVGA3D_INVALID_ID) {
    437       SVGA3dResourceType resType;
    438       SVGA3dRenderTargetViewDesc desc;
    439       struct svga_texture *stex = svga_texture(s->base.texture);
    440 
    441       if (stex->validated == FALSE) {
    442          assert(stex->handle);
    443 
    444          /* We are about to render into a surface that has not been validated.
    445           * First invalidate the surface so that the device does not
    446           * need to update the host-side copy with the invalid
    447           * content when the associated mob is first bound to the surface.
    448           */
    449          ret = SVGA3D_InvalidateGBSurface(svga->swc, stex->handle);
    450          if (ret != PIPE_OK) {
    451             s = NULL;
    452             goto done;
    453          }
    454          stex->validated = TRUE;
    455       }
    456 
    457       desc.tex.mipSlice = s->real_level;
    458       desc.tex.firstArraySlice = s->real_layer + s->real_zslice;
    459       desc.tex.arraySize =
    460          s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1;
    461 
    462       s->view_id = util_bitmask_add(svga->surface_view_id_bm);
    463 
    464       resType = svga_resource_type(s->base.texture->target);
    465 
    466       if (util_format_is_depth_or_stencil(s->base.format)) {
    467          ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc,
    468                                                     s->view_id,
    469                                                     s->handle,
    470                                                     s->key.format,
    471                                                     resType,
    472                                                     &desc);
    473       }
    474       else {
    475          SVGA3dSurfaceFormat view_format = s->key.format;
    476          const struct svga_texture *stex = svga_texture(s->base.texture);
    477 
    478          /* Can't create RGBA render target view of a RGBX surface so adjust
    479           * the view format.  We do something similar for texture samplers in
    480           * svga_validate_pipe_sampler_view().
    481           */
    482          if (view_format == SVGA3D_B8G8R8A8_UNORM &&
    483              (stex->key.format == SVGA3D_B8G8R8X8_UNORM ||
    484               stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) {
    485             view_format = SVGA3D_B8G8R8X8_UNORM;
    486          }
    487 
    488          ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc,
    489                                                     s->view_id,
    490                                                     s->handle,
    491                                                     view_format,
    492                                                     resType,
    493                                                     &desc);
    494       }
    495 
    496       if (ret != PIPE_OK) {
    497          util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
    498          s->view_id = SVGA3D_INVALID_ID;
    499          s = NULL;
    500       }
    501    }
    502 
    503 done:
    504    SVGA_STATS_TIME_POP(svga_sws(svga));
    505 
    506    return s ? &s->base : NULL;
    507 }
    508 
    509 
    510 
    511 static void
    512 svga_surface_destroy(struct pipe_context *pipe,
    513                      struct pipe_surface *surf)
    514 {
    515    struct svga_context *svga = svga_context(pipe);
    516    struct svga_surface *s = svga_surface(surf);
    517    struct svga_texture *t = svga_texture(surf->texture);
    518    struct svga_screen *ss = svga_screen(surf->texture->screen);
    519    enum pipe_error ret = PIPE_OK;
    520 
    521    SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE);
    522 
    523    /* Destroy the backed view surface if it exists */
    524    if (s->backed) {
    525       svga_surface_destroy(pipe, &s->backed->base);
    526       s->backed = NULL;
    527    }
    528 
    529    if (s->handle != t->handle) {
    530       SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle);
    531       svga_screen_surface_destroy(ss, &s->key, &s->handle);
    532    }
    533 
    534    if (s->view_id != SVGA3D_INVALID_ID) {
    535       unsigned try;
    536 
    537       assert(svga_have_vgpu10(svga));
    538       for (try = 0; try < 2; try++) {
    539          if (util_format_is_depth_or_stencil(s->base.format)) {
    540             ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id);
    541          }
    542          else {
    543             ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id);
    544          }
    545          if (ret == PIPE_OK)
    546             break;
    547          svga_context_flush(svga, NULL);
    548       }
    549       assert(ret == PIPE_OK);
    550       util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
    551    }
    552 
    553    pipe_resource_reference(&surf->texture, NULL);
    554    FREE(surf);
    555 
    556    svga->hud.num_surface_views--;
    557    SVGA_STATS_TIME_POP(ss->sws);
    558 }
    559 
    560 
    561 static void
    562 svga_mark_surface_dirty(struct pipe_surface *surf)
    563 {
    564    struct svga_surface *s = svga_surface(surf);
    565    struct svga_texture *tex = svga_texture(surf->texture);
    566 
    567    if (!s->dirty) {
    568       s->dirty = TRUE;
    569 
    570       if (s->handle == tex->handle) {
    571          /* hmm so 3d textures always have all their slices marked ? */
    572          svga_define_texture_level(tex, surf->u.tex.first_layer,
    573                                    surf->u.tex.level);
    574       }
    575       else {
    576          /* this will happen later in svga_propagate_surface */
    577       }
    578    }
    579 
    580    /* Increment the view_age and texture age for this surface's mipmap
    581     * level so that any sampler views into the texture are re-validated too.
    582     */
    583    svga_age_texture_view(tex, surf->u.tex.level);
    584 }
    585 
    586 
    587 void
    588 svga_mark_surfaces_dirty(struct svga_context *svga)
    589 {
    590    unsigned i;
    591 
    592    for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) {
    593       if (svga->curr.framebuffer.cbufs[i])
    594          svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]);
    595    }
    596    if (svga->curr.framebuffer.zsbuf)
    597       svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf);
    598 }
    599 
    600 
    601 /**
    602  * Progagate any changes from surfaces to texture.
    603  * pipe is optional context to inline the blit command in.
    604  */
    605 void
    606 svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf)
    607 {
    608    struct svga_surface *s = svga_surface(surf);
    609    struct svga_texture *tex = svga_texture(surf->texture);
    610    struct svga_screen *ss = svga_screen(surf->texture->screen);
    611 
    612    if (!s->dirty)
    613       return;
    614 
    615    SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_PROPAGATESURFACE);
    616 
    617    s->dirty = FALSE;
    618    ss->texture_timestamp++;
    619    svga_age_texture_view(tex, surf->u.tex.level);
    620 
    621    if (s->handle != tex->handle) {
    622       unsigned zslice, layer;
    623       unsigned nlayers = 1;
    624       unsigned i;
    625 
    626       if (surf->texture->target == PIPE_TEXTURE_CUBE) {
    627          zslice = 0;
    628          layer = surf->u.tex.first_layer;
    629       }
    630       else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY ||
    631                surf->texture->target == PIPE_TEXTURE_2D_ARRAY) {
    632          zslice = 0;
    633          layer = surf->u.tex.first_layer;
    634          nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1;
    635       }
    636       else {
    637          zslice = surf->u.tex.first_layer;
    638          layer = 0;
    639       }
    640 
    641       SVGA_DBG(DEBUG_VIEWS,
    642                "svga: Surface propagate: tex %p, level %u, from %p\n",
    643                tex, surf->u.tex.level, surf);
    644       for (i = 0; i < nlayers; i++) {
    645          svga_texture_copy_handle(svga,
    646                                   s->handle, 0, 0, 0, s->real_level,
    647                                   s->real_layer + i,
    648                                   tex->handle, 0, 0, zslice, surf->u.tex.level,
    649                                   layer + i,
    650                                   u_minify(tex->b.b.width0, surf->u.tex.level),
    651                                   u_minify(tex->b.b.height0, surf->u.tex.level),
    652                                   1);
    653          svga_define_texture_level(tex, layer + i, surf->u.tex.level);
    654       }
    655    }
    656 
    657    SVGA_STATS_TIME_POP(ss->sws);
    658 }
    659 
    660 
    661 /**
    662  * If any of the render targets are in backing texture views, propagate any
    663  * changes to them back to the original texture.
    664  */
    665 void
    666 svga_propagate_rendertargets(struct svga_context *svga)
    667 {
    668    unsigned i;
    669 
    670    /* Note that we examine the svga->state.hw_draw.framebuffer surfaces,
    671     * not the svga->curr.framebuffer surfaces, because it's the former
    672     * surfaces which may be backing surface views (the actual render targets).
    673     */
    674    for (i = 0; i < svga->state.hw_draw.num_rendertargets; i++) {
    675       struct pipe_surface *s = svga->state.hw_draw.rtv[i];
    676       if (s) {
    677          svga_propagate_surface(svga, s);
    678       }
    679    }
    680 
    681    if (svga->state.hw_draw.dsv) {
    682       svga_propagate_surface(svga, svga->state.hw_draw.dsv);
    683    }
    684 }
    685 
    686 
    687 /**
    688  * Check if we should call svga_propagate_surface on the surface.
    689  */
    690 boolean
    691 svga_surface_needs_propagation(const struct pipe_surface *surf)
    692 {
    693    const struct svga_surface *s = svga_surface_const(surf);
    694    struct svga_texture *tex = svga_texture(surf->texture);
    695 
    696    return s->dirty && s->handle != tex->handle;
    697 }
    698 
    699 
    700 static void
    701 svga_get_sample_position(struct pipe_context *context,
    702                          unsigned sample_count, unsigned sample_index,
    703                          float *pos_out)
    704 {
    705    /* We can't actually query the device to learn the sample positions.
    706     * These were grabbed from nvidia's driver.
    707     */
    708    static const float pos1[1][2] = {
    709       { 0.5, 0.5 }
    710    };
    711    static const float pos4[4][2] = {
    712       { 0.375000, 0.125000 },
    713       { 0.875000, 0.375000 },
    714       { 0.125000, 0.625000 },
    715       { 0.625000, 0.875000 }
    716    };
    717    static const float pos8[8][2] = {
    718       { 0.562500, 0.312500 },
    719       { 0.437500, 0.687500 },
    720       { 0.812500, 0.562500 },
    721       { 0.312500, 0.187500 },
    722       { 0.187500, 0.812500 },
    723       { 0.062500, 0.437500 },
    724       { 0.687500, 0.937500 },
    725       { 0.937500, 0.062500 }
    726    };
    727    static const float pos16[16][2] = {
    728       { 0.187500, 0.062500 },
    729       { 0.437500, 0.187500 },
    730       { 0.062500, 0.312500 },
    731       { 0.312500, 0.437500 },
    732       { 0.687500, 0.062500 },
    733       { 0.937500, 0.187500 },
    734       { 0.562500, 0.312500 },
    735       { 0.812500, 0.437500 },
    736       { 0.187500, 0.562500 },
    737       { 0.437500, 0.687500 },
    738       { 0.062500, 0.812500 },
    739       { 0.312500, 0.937500 },
    740       { 0.687500, 0.562500 },
    741       { 0.937500, 0.687500 },
    742       { 0.562500, 0.812500 },
    743       { 0.812500, 0.937500 }
    744    };
    745    const float (*positions)[2];
    746 
    747    switch (sample_count) {
    748    case 4:
    749       positions = pos4;
    750       break;
    751    case 8:
    752       positions = pos8;
    753       break;
    754    case 16:
    755       positions = pos16;
    756       break;
    757    default:
    758       positions = pos1;
    759    }
    760 
    761    pos_out[0] = positions[sample_index][0];
    762    pos_out[1] = positions[sample_index][1];
    763 }
    764 
    765 
    766 void
    767 svga_init_surface_functions(struct svga_context *svga)
    768 {
    769    svga->pipe.create_surface = svga_create_surface;
    770    svga->pipe.surface_destroy = svga_surface_destroy;
    771    svga->pipe.get_sample_position = svga_get_sample_position;
    772 }
    773