X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fsvga%2Fsvga_surface.c;h=73208cf58ac2c8bac71c2497007657c863b28418;hb=e3841368f34afe844bab25010b89f497cacc1dad;hp=4b0f9417c3273c06723906642aeaa3ef907e4ce3;hpb=b2fd41ce465e16a178d51000b843b5228640b670;p=mesa.git diff --git a/src/gallium/drivers/svga/svga_surface.c b/src/gallium/drivers/svga/svga_surface.c index 4b0f9417c32..73208cf58ac 100644 --- a/src/gallium/drivers/svga/svga_surface.c +++ b/src/gallium/drivers/svga/svga_surface.c @@ -44,6 +44,44 @@ static void svga_mark_surface_dirty(struct pipe_surface *surf); +void +svga_texture_copy_region(struct svga_context *svga, + struct svga_winsys_surface *src_handle, + unsigned srcSubResource, + unsigned src_x, unsigned src_y, unsigned src_z, + struct svga_winsys_surface *dst_handle, + unsigned dstSubResource, + unsigned dst_x, unsigned dst_y, unsigned dst_z, + unsigned width, unsigned height, unsigned depth) +{ + enum pipe_error ret; + SVGA3dCopyBox box; + + assert(svga_have_vgpu10(svga)); + + box.x = dst_x; + box.y = dst_y; + box.z = dst_z; + box.w = width; + box.h = height; + box.d = depth; + box.srcx = src_x; + box.srcy = src_y; + box.srcz = src_z; + + ret = SVGA3D_vgpu10_PredCopyRegion(svga->swc, + dst_handle, dstSubResource, + src_handle, srcSubResource, &box); + if (ret != PIPE_OK) { + svga_context_flush(svga, NULL); + ret = SVGA3D_vgpu10_PredCopyRegion(svga->swc, + dst_handle, dstSubResource, + src_handle, srcSubResource, &box); + assert(ret == PIPE_OK); + } +} + + void svga_texture_copy_handle(struct svga_context *svga, struct svga_winsys_surface *src_handle, @@ -103,28 +141,84 @@ svga_texture_copy_handle(struct svga_context *svga, } +/* A helper function to sync up the two surface handles. + */ +static void +svga_texture_copy_handle_resource(struct svga_context *svga, + struct svga_texture *src_tex, + struct svga_winsys_surface *dst, + unsigned int numMipLevels, + unsigned int numLayers, + int zslice_pick, + unsigned int mipoffset, + unsigned int layeroffset) +{ + unsigned int i, j; + unsigned int zoffset = 0; + + /* A negative zslice_pick implies zoffset at 0, and depth to copy is + * from the depth of the texture at the particular mipmap level. + */ + if (zslice_pick >= 0) + zoffset = zslice_pick; + + for (i = 0; i < numMipLevels; i++) { + unsigned int miplevel = i + mipoffset; + + for (j = 0; j < numLayers; j++) { + if (svga_is_texture_level_defined(src_tex, j+layeroffset, miplevel)) { + unsigned depth = (zslice_pick < 0 ? + u_minify(src_tex->b.b.depth0, miplevel) : 1); + + if (src_tex->b.b.nr_samples > 1) { + unsigned subResource = j * numMipLevels + i; + svga_texture_copy_region(svga, src_tex->handle, + subResource, 0, 0, zoffset, + dst, subResource, 0, 0, 0, + src_tex->b.b.width0, src_tex->b.b.height0, depth); + } + else { + svga_texture_copy_handle(svga, + src_tex->handle, + 0, 0, zoffset, + miplevel, + j + layeroffset, + dst, 0, 0, 0, i, j, + u_minify(src_tex->b.b.width0, miplevel), + u_minify(src_tex->b.b.height0, miplevel), + depth); + } + } + } + } +} + + struct svga_winsys_surface * svga_texture_view_surface(struct svga_context *svga, struct svga_texture *tex, unsigned bind_flags, - SVGA3dSurfaceFlags flags, + SVGA3dSurfaceAllFlags flags, SVGA3dSurfaceFormat format, unsigned start_mip, unsigned num_mip, int layer_pick, unsigned num_layers, int zslice_pick, + boolean cacheable, struct svga_host_surface_cache_key *key) /* OUT */ { struct svga_screen *ss = svga_screen(svga->pipe.screen); - struct svga_winsys_surface *handle; - uint32_t i, j; - unsigned z_offset = 0; + struct svga_winsys_surface *handle = NULL; + boolean validated; + boolean needCopyResource; - SVGA_DBG(DEBUG_PERF, + SVGA_DBG(DEBUG_PERF, "svga: Create surface view: layer %d zslice %d mips %d..%d\n", layer_pick, zslice_pick, start_mip, start_mip+num_mip-1); + SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_EMULATESURFACEVIEW); + key->flags = flags; key->format = format; key->numMipLevels = num_mip; @@ -134,12 +228,15 @@ svga_texture_view_surface(struct svga_context *svga, key->cachable = 1; key->arraySize = 1; key->numFaces = 1; - key->sampleCount = tex->b.b.nr_samples; + + /* single sample surface can be treated as non-multisamples surface */ + key->sampleCount = tex->b.b.nr_samples > 1 ? tex->b.b.nr_samples : 0; if (key->sampleCount > 1) { - key->flags |= SVGA3D_SURFACE_MASKABLE_ANTIALIAS; + assert(ss->sws->have_sm4_1); + key->flags |= SVGA3D_SURFACE_MULTISAMPLE; } - + if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) { key->flags |= SVGA3D_SURFACE_CUBEMAP; key->numFaces = 6; @@ -150,14 +247,28 @@ svga_texture_view_surface(struct svga_context *svga, if (key->format == SVGA3D_FORMAT_INVALID) { key->cachable = 0; - return NULL; + goto done; + } + + if (cacheable && tex->backed_handle && + memcmp(key, &tex->backed_key, sizeof *key) == 0) { + handle = tex->backed_handle; + needCopyResource = tex->backed_age < tex->age; + } else { + SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n"); + handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT, + &validated, key); + needCopyResource = TRUE; + + if (cacheable && !tex->backed_handle) { + tex->backed_handle = handle; + memcpy(&tex->backed_key, key, sizeof *key); + } } - SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n"); - handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT, key); if (!handle) { key->cachable = 0; - return NULL; + goto done; } SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle); @@ -165,29 +276,17 @@ svga_texture_view_surface(struct svga_context *svga, if (layer_pick < 0) layer_pick = 0; - if (zslice_pick >= 0) - z_offset = zslice_pick; - - for (i = 0; i < key->numMipLevels; i++) { - for (j = 0; j < key->numFaces * key->arraySize; j++) { - if (svga_is_texture_level_defined(tex, j + layer_pick, i + start_mip)) { - unsigned depth = (zslice_pick < 0 ? - u_minify(tex->b.b.depth0, i + start_mip) : - 1); - - svga_texture_copy_handle(svga, - tex->handle, - 0, 0, z_offset, - i + start_mip, - j + layer_pick, - handle, 0, 0, 0, i, j, - u_minify(tex->b.b.width0, i + start_mip), - u_minify(tex->b.b.height0, i + start_mip), - depth); - } - } + if (needCopyResource) { + svga_texture_copy_handle_resource(svga, tex, handle, + key->numMipLevels, + key->numFaces * key->arraySize, + zslice_pick, start_mip, layer_pick); + tex->backed_age = tex->age; } +done: + SVGA_STATS_TIME_POP(ss->sws); + return handle; } @@ -210,19 +309,23 @@ svga_create_surface_view(struct pipe_context *pipe, struct svga_surface *s; unsigned layer, zslice, bind; unsigned nlayers = 1; - SVGA3dSurfaceFlags flags = 0; + SVGA3dSurfaceAllFlags flags = 0; SVGA3dSurfaceFormat format; + struct pipe_surface *retVal = NULL; s = CALLOC_STRUCT(svga_surface); if (!s) return NULL; + SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_CREATESURFACEVIEW); + if (pt->target == PIPE_TEXTURE_CUBE) { layer = surf_tmpl->u.tex.first_layer; zslice = 0; } else if (pt->target == PIPE_TEXTURE_1D_ARRAY || - pt->target == PIPE_TEXTURE_2D_ARRAY) { + pt->target == PIPE_TEXTURE_2D_ARRAY || + pt->target == PIPE_TEXTURE_CUBE_ARRAY) { layer = surf_tmpl->u.tex.first_layer; zslice = 0; nlayers = surf_tmpl->u.tex.last_layer - surf_tmpl->u.tex.first_layer + 1; @@ -256,15 +359,23 @@ svga_create_surface_view(struct pipe_context *pipe, bind = PIPE_BIND_RENDER_TARGET; } - if (tex->imported) + if (tex->imported) { + /* imported resource (a window) */ format = tex->key.format; - else + if (util_format_is_srgb(surf_tmpl->format)) { + /* sRGB rendering to window */ + format = svga_linear_to_srgb(format); + } + } + else { format = svga_translate_format(ss, surf_tmpl->format, bind); + } assert(format != SVGA3D_FORMAT_INVALID); if (view) { - SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: yes %p, level %u layer %u z %u, %p\n", + SVGA_DBG(DEBUG_VIEWS, + "New backed surface view: resource %p, level %u layer %u z %u, %p\n", pt, surf_tmpl->u.tex.level, layer, zslice, s); if (svga_have_vgpu10(svga)) { @@ -285,6 +396,10 @@ svga_create_surface_view(struct pipe_context *pipe, if (nlayers == 6) flags |= SVGA3D_SURFACE_CUBEMAP; break; + case PIPE_TEXTURE_CUBE_ARRAY: + if (nlayers % 6 == 0) + flags |= SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_ARRAY; + break; default: break; } @@ -293,15 +408,23 @@ svga_create_surface_view(struct pipe_context *pipe, /* When we clone the surface view resource, use the format used in * the creation of the original resource. */ - s->handle = svga_texture_view_surface(svga, tex, bind, flags, tex->key.format, + s->handle = svga_texture_view_surface(svga, tex, bind, flags, + tex->key.format, surf_tmpl->u.tex.level, 1, - layer, nlayers, zslice, &s->key); + layer, nlayers, zslice, + TRUE, &s->key); + if (!s->handle) { + FREE(s); + goto done; + } + s->key.format = format; s->real_layer = 0; s->real_level = 0; s->real_zslice = 0; } else { - SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: no %p, level %u, layer %u, z %u, %p\n", + SVGA_DBG(DEBUG_VIEWS, + "New surface view: resource %p, level %u, layer %u, z %u, %p\n", pt, surf_tmpl->u.tex.level, layer, zslice, s); memset(&s->key, 0, sizeof s->key); @@ -312,7 +435,12 @@ svga_create_surface_view(struct pipe_context *pipe, s->real_level = surf_tmpl->u.tex.level; } - return &s->base; + svga->hud.num_surface_views++; + retVal = &s->base; + +done: + SVGA_STATS_TIME_POP(ss->sws); + return retVal; } @@ -323,8 +451,11 @@ svga_create_surface(struct pipe_context *pipe, { struct svga_context *svga = svga_context(pipe); struct pipe_screen *screen = pipe->screen; + struct pipe_surface *surf = NULL; boolean view = FALSE; + SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATESURFACE); + if (svga_screen(screen)->debug.force_surface_view) view = TRUE; @@ -338,7 +469,11 @@ svga_create_surface(struct pipe_context *pipe, if (svga_have_vgpu10(svga) || svga_screen(screen)->debug.no_surface_view) view = FALSE; - return svga_create_surface_view(pipe, pt, surf_tmpl, view); + surf = svga_create_surface_view(pipe, pt, surf_tmpl, view); + + SVGA_STATS_TIME_POP(svga_sws(svga)); + + return surf; } @@ -348,24 +483,60 @@ svga_create_surface(struct pipe_context *pipe, static struct svga_surface * create_backed_surface_view(struct svga_context *svga, struct svga_surface *s) { - struct svga_surface *bs = s->backed; + struct svga_texture *tex = svga_texture(s->base.texture); - if (bs == NULL) { - struct svga_texture *tex = svga_texture(s->base.texture); + if (!s->backed) { struct pipe_surface *backed_view; + SVGA_STATS_TIME_PUSH(svga_sws(svga), + SVGA_STATS_TIME_CREATEBACKEDSURFACEVIEW); + backed_view = svga_create_surface_view(&svga->pipe, &tex->b.b, &s->base, TRUE); + if (!backed_view) + goto done; + + s->backed = svga_surface(backed_view); + + SVGA_STATS_TIME_POP(svga_sws(svga)); + } + else if (s->backed->age < tex->age) { + /* + * There is already an existing backing surface, but we still need to + * sync the backing resource if the original resource has been modified + * since the last copy. + */ + struct svga_surface *bs = s->backed; + unsigned int layer, zslice; + + assert(bs->handle); - bs = svga_surface(backed_view); - s->backed = bs; + switch (tex->b.b.target) { + case PIPE_TEXTURE_CUBE: + case PIPE_TEXTURE_CUBE_ARRAY: + case PIPE_TEXTURE_1D_ARRAY: + case PIPE_TEXTURE_2D_ARRAY: + layer = s->base.u.tex.first_layer; + zslice = 0; + break; + default: + layer = 0; + zslice = s->base.u.tex.first_layer; + } + + svga_texture_copy_handle_resource(svga, tex, bs->handle, + bs->key.numMipLevels, + bs->key.numFaces * bs->key.arraySize, + zslice, s->base.u.tex.level, layer); } - svga_mark_surface_dirty(&bs->base); + svga_mark_surface_dirty(&s->backed->base); + s->backed->age = tex->age; - return bs; +done: + return s->backed; } /** @@ -376,10 +547,13 @@ struct pipe_surface * svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s) { enum pipe_error ret = PIPE_OK; - int try; - unsigned shader; + enum pipe_shader_type shader; assert(svga_have_vgpu10(svga)); + assert(s); + + SVGA_STATS_TIME_PUSH(svga_sws(svga), + SVGA_STATS_TIME_VALIDATESURFACEVIEW); /** * DX spec explicitly specifies that no resource can be bound to a render @@ -395,13 +569,35 @@ svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s) "same resource used in shaderResource and renderTarget 0x%x\n", s->handle); s = create_backed_surface_view(svga, s); + + if (s) + svga->state.hw_draw.has_backed_views = TRUE; + + /* s may be null here if the function failed */ break; } } - if (s->view_id == SVGA3D_INVALID_ID) { + if (s && s->view_id == SVGA3D_INVALID_ID) { SVGA3dResourceType resType; SVGA3dRenderTargetViewDesc desc; + struct svga_texture *stex = svga_texture(s->base.texture); + + if (stex->validated == FALSE) { + assert(stex->handle); + + /* We are about to render into a surface that has not been validated. + * First invalidate the surface so that the device does not + * need to update the host-side copy with the invalid + * content when the associated mob is first bound to the surface. + */ + if (svga->swc->surface_invalidate(svga->swc, stex->handle) != PIPE_OK) { + svga_context_flush(svga, NULL); + ret = svga->swc->surface_invalidate(svga->swc, stex->handle); + assert(ret == PIPE_OK); + } + stex->validated = TRUE; + } desc.tex.mipSlice = s->real_level; desc.tex.firstArraySlice = s->real_layer + s->real_zslice; @@ -410,55 +606,48 @@ svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s) s->view_id = util_bitmask_add(svga->surface_view_id_bm); - switch (s->base.texture->target) { - case PIPE_TEXTURE_1D: - case PIPE_TEXTURE_1D_ARRAY: - resType = SVGA3D_RESOURCE_TEXTURE1D; - break; - case PIPE_TEXTURE_RECT: - case PIPE_TEXTURE_2D: - case PIPE_TEXTURE_2D_ARRAY: - case PIPE_TEXTURE_CUBE: - /* drawing to cube map is treated as drawing to 2D array */ - resType = SVGA3D_RESOURCE_TEXTURE2D; - break; - case PIPE_TEXTURE_3D: - resType = SVGA3D_RESOURCE_TEXTURE3D; - break; - default: - assert(!"Unexpected texture target"); - resType = SVGA3D_RESOURCE_TEXTURE2D; - } + resType = svga_resource_type(s->base.texture->target); - for (try = 0; try < 2; try++) { - if (util_format_is_depth_or_stencil(s->base.format)) { - ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc, - s->view_id, - s->handle, - s->key.format, - resType, - &desc); - } - else { - ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc, - s->view_id, - s->handle, - s->key.format, - resType, - &desc); + if (util_format_is_depth_or_stencil(s->base.format)) { + ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc, + s->view_id, + s->handle, + s->key.format, + resType, + &desc); + } + else { + SVGA3dSurfaceFormat view_format = s->key.format; + const struct svga_texture *stex = svga_texture(s->base.texture); + + /* Can't create RGBA render target view of a RGBX surface so adjust + * the view format. We do something similar for texture samplers in + * svga_validate_pipe_sampler_view(). + */ + if (view_format == SVGA3D_B8G8R8A8_UNORM && + (stex->key.format == SVGA3D_B8G8R8X8_UNORM || + stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) { + view_format = SVGA3D_B8G8R8X8_UNORM; } - if (ret == PIPE_OK) - break; - svga_context_flush(svga, NULL); + + ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc, + s->view_id, + s->handle, + view_format, + resType, + &desc); } - assert(ret == PIPE_OK); if (ret != PIPE_OK) { util_bitmask_clear(svga->surface_view_id_bm, s->view_id); s->view_id = SVGA3D_INVALID_ID; + s = NULL; } } - return &s->base; + + SVGA_STATS_TIME_POP(svga_sws(svga)); + + return s ? &s->base : NULL; } @@ -473,13 +662,18 @@ svga_surface_destroy(struct pipe_context *pipe, struct svga_screen *ss = svga_screen(surf->texture->screen); enum pipe_error ret = PIPE_OK; + SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE); + /* Destroy the backed view surface if it exists */ if (s->backed) { svga_surface_destroy(pipe, &s->backed->base); s->backed = NULL; } - if (s->handle != t->handle) { + /* Destroy the surface handle if this is a backed handle and + * it is not being cached in the texture. + */ + if (s->handle != t->handle && s->handle != t->backed_handle) { SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle); svga_screen_surface_destroy(ss, &s->key, &s->handle); } @@ -487,35 +681,48 @@ svga_surface_destroy(struct pipe_context *pipe, if (s->view_id != SVGA3D_INVALID_ID) { unsigned try; - assert(svga_have_vgpu10(svga)); - for (try = 0; try < 2; try++) { - if (util_format_is_depth_or_stencil(s->base.format)) { - ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id); - } - else { - ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id); + /* The SVGA3D device will generate a device error if the + * render target view or depth stencil view is destroyed from + * a context other than the one it was created with. + * Similar to shader resource view, in this case, we will skip + * the destroy for now. + */ + if (surf->context != pipe) { + _debug_printf("context mismatch in %s\n", __func__); + } + else { + assert(svga_have_vgpu10(svga)); + for (try = 0; try < 2; try++) { + if (util_format_is_depth_or_stencil(s->base.format)) { + ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id); + } + else { + ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id); + } + if (ret == PIPE_OK) + break; + svga_context_flush(svga, NULL); } - if (ret == PIPE_OK) - break; - svga_context_flush(svga, NULL); + assert(ret == PIPE_OK); + util_bitmask_clear(svga->surface_view_id_bm, s->view_id); } - assert(ret == PIPE_OK); - util_bitmask_clear(svga->surface_view_id_bm, s->view_id); } pipe_resource_reference(&surf->texture, NULL); FREE(surf); + + svga->hud.num_surface_views--; + SVGA_STATS_TIME_POP(ss->sws); } -static void +static void svga_mark_surface_dirty(struct pipe_surface *surf) { struct svga_surface *s = svga_surface(surf); + struct svga_texture *tex = svga_texture(surf->texture); if (!s->dirty) { - struct svga_texture *tex = svga_texture(surf->texture); - s->dirty = TRUE; if (s->handle == tex->handle) { @@ -526,27 +733,43 @@ svga_mark_surface_dirty(struct pipe_surface *surf) else { /* this will happen later in svga_propagate_surface */ } + } - /* Increment the view_age and texture age for this surface's mipmap - * level so that any sampler views into the texture are re-validated too. - */ + /* Increment the view_age and texture age for this surface's mipmap + * level so that any sampler views into the texture are re-validated too. + * Note: we age the texture for backed surface view only when the + * backed surface is propagated to the original surface. + */ + if (s->handle == tex->handle) svga_age_texture_view(tex, surf->u.tex.level); - } } void svga_mark_surfaces_dirty(struct svga_context *svga) { - struct svga_screen *svgascreen = svga_screen(svga->pipe.screen); unsigned i; + struct svga_hw_clear_state *hw = &svga->state.hw_clear; + + if (svga_have_vgpu10(svga)) { - for (i = 0; i < svgascreen->max_color_buffers; i++) { - if (svga->curr.framebuffer.cbufs[i]) - svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]); + /* For VGPU10, mark the dirty bit in the rendertarget/depth stencil view surface. + * This surface can be the backed surface. + */ + for (i = 0; i < hw->num_rendertargets; i++) { + if (hw->rtv[i]) + svga_mark_surface_dirty(hw->rtv[i]); + } + if (hw->dsv) + svga_mark_surface_dirty(hw->dsv); + } else { + for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) { + if (svga->curr.framebuffer.cbufs[i]) + svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]); + } + if (svga->curr.framebuffer.zsbuf) + svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf); } - if (svga->curr.framebuffer.zsbuf) - svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf); } @@ -555,50 +778,128 @@ svga_mark_surfaces_dirty(struct svga_context *svga) * pipe is optional context to inline the blit command in. */ void -svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf) +svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf, + boolean reset) { struct svga_surface *s = svga_surface(surf); struct svga_texture *tex = svga_texture(surf->texture); struct svga_screen *ss = svga_screen(surf->texture->screen); - unsigned zslice, layer; - unsigned nlayers = 1; - unsigned i; if (!s->dirty) return; - if (surf->texture->target == PIPE_TEXTURE_CUBE) { - zslice = 0; - layer = surf->u.tex.first_layer; - } - else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY || - surf->texture->target == PIPE_TEXTURE_2D_ARRAY) { - zslice = 0; - layer = surf->u.tex.first_layer; - nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1; - } - else { - zslice = surf->u.tex.first_layer; - layer = 0; - } + SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_PROPAGATESURFACE); + + /* Reset the dirty flag if specified. This is to ensure that + * the dirty flag will not be reset and stay unset when the backing + * surface is still being bound and rendered to. + * The reset flag will be set to TRUE when the surface is propagated + * and will be unbound. + */ + s->dirty = !reset; - s->dirty = FALSE; ss->texture_timestamp++; svga_age_texture_view(tex, surf->u.tex.level); if (s->handle != tex->handle) { + unsigned zslice, layer; + unsigned nlayers = 1; + unsigned i; + unsigned numMipLevels = tex->b.b.last_level + 1; + unsigned srcLevel = s->real_level; + unsigned dstLevel = surf->u.tex.level; + unsigned width = u_minify(tex->b.b.width0, dstLevel); + unsigned height = u_minify(tex->b.b.height0, dstLevel); + + if (surf->texture->target == PIPE_TEXTURE_CUBE) { + zslice = 0; + layer = surf->u.tex.first_layer; + } + else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY || + surf->texture->target == PIPE_TEXTURE_2D_ARRAY || + surf->texture->target == PIPE_TEXTURE_CUBE_ARRAY) { + zslice = 0; + layer = surf->u.tex.first_layer; + nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1; + } + else { + zslice = surf->u.tex.first_layer; + layer = 0; + } + SVGA_DBG(DEBUG_VIEWS, - "svga: Surface propagate: tex %p, level %u, from %p\n", - tex, surf->u.tex.level, surf); - for (i = 0; i < nlayers; i++) { - svga_texture_copy_handle(svga, - s->handle, 0, 0, 0, s->real_level, s->real_layer + i, - tex->handle, 0, 0, zslice, surf->u.tex.level, layer + i, - u_minify(tex->b.b.width0, surf->u.tex.level), - u_minify(tex->b.b.height0, surf->u.tex.level), 1); - svga_define_texture_level(tex, layer + i, surf->u.tex.level); + "Propagate surface %p to resource %p, level %u\n", + surf, tex, surf->u.tex.level); + + if (svga_have_vgpu10(svga)) { + unsigned srcSubResource, dstSubResource; + + for (i = 0; i < nlayers; i++) { + srcSubResource = (s->real_layer + i) * numMipLevels + srcLevel; + dstSubResource = (layer + i) * numMipLevels + dstLevel; + + svga_texture_copy_region(svga, + s->handle, srcSubResource, 0, 0, 0, + tex->handle, dstSubResource, 0, 0, zslice, + width, height, 1); + svga_define_texture_level(tex, layer + i, dstLevel); + } + } + else { + for (i = 0; i < nlayers; i++) { + svga_texture_copy_handle(svga, + s->handle, 0, 0, 0, srcLevel, + s->real_layer + i, + tex->handle, 0, 0, zslice, dstLevel, + layer + i, + width, height, 1); + + svga_define_texture_level(tex, layer + i, dstLevel); + } + } + + /* Sync the surface view age with the texture age */ + s->age = tex->age; + + /* If this backed surface is cached in the texture, + * update the backed age as well. + */ + if (tex->backed_handle == s->handle) { + tex->backed_age = tex->age; + } + } + + SVGA_STATS_TIME_POP(ss->sws); +} + + +/** + * If any of the render targets are in backing texture views, propagate any + * changes to them back to the original texture. + */ +void +svga_propagate_rendertargets(struct svga_context *svga) +{ + unsigned i; + + /* Early exit if there is no backing texture views in use */ + if (!svga->state.hw_draw.has_backed_views) + return; + + /* Note that we examine the svga->state.hw_draw.framebuffer surfaces, + * not the svga->curr.framebuffer surfaces, because it's the former + * surfaces which may be backing surface views (the actual render targets). + */ + for (i = 0; i < svga->state.hw_clear.num_rendertargets; i++) { + struct pipe_surface *s = svga->state.hw_clear.rtv[i]; + if (s) { + svga_propagate_surface(svga, s, FALSE); } } + + if (svga->state.hw_clear.dsv) { + svga_propagate_surface(svga, svga->state.hw_clear.dsv, FALSE); + } } @@ -626,6 +927,10 @@ svga_get_sample_position(struct pipe_context *context, static const float pos1[1][2] = { { 0.5, 0.5 } }; + static const float pos2[2][2] = { + { 0.75, 0.75 }, + { 0.25, 0.25 } + }; static const float pos4[4][2] = { { 0.375000, 0.125000 }, { 0.875000, 0.375000 }, @@ -663,6 +968,9 @@ svga_get_sample_position(struct pipe_context *context, const float (*positions)[2]; switch (sample_count) { + case 2: + positions = pos2; + break; case 4: positions = pos4; break;