void svga_validate_sampler_view(struct svga_context *svga, struct svga_sampler_view *v) { struct svga_texture *tex = svga_texture(v->texture); unsigned numFaces; unsigned age = 0; int i; unsigned k; assert(svga); assert(!svga_have_vgpu10(svga)); if (v->handle == tex->handle) return; age = tex->age; if (tex->b.b.target == PIPE_TEXTURE_CUBE) numFaces = 6; else numFaces = 1; for (i = v->min_lod; i <= v->max_lod; i++) { for (k = 0; k < numFaces; k++) { assert(i < ARRAY_SIZE(tex->view_age)); if (v->age < tex->view_age[i]) svga_texture_copy_handle(svga, tex->handle, 0, 0, 0, i, k, v->handle, 0, 0, 0, i - v->min_lod, k, u_minify(tex->b.b.width0, i), u_minify(tex->b.b.height0, i), u_minify(tex->b.b.depth0, i)); } } v->age = age; }
/** * Progagate any changes from surfaces to texture. * pipe is optional context to inline the blit command in. */ void svga_propagate_surface(struct pipe_context *pipe, struct pipe_surface *surf) { struct svga_surface *s = svga_surface(surf); struct svga_texture *tex = svga_texture(surf->texture); struct svga_screen *ss = svga_screen(surf->texture->screen); if (!s->dirty) return; s->dirty = FALSE; ss->texture_timestamp++; tex->view_age[surf->level] = ++(tex->age); if (s->handle != tex->handle) { SVGA_DBG(DEBUG_VIEWS, "svga: Surface propagate: tex %p, level %u, from %p\n", tex, surf->level, surf); svga_texture_copy_handle(svga_context(pipe), s->handle, 0, 0, 0, s->real_level, s->real_face, tex->handle, 0, 0, surf->zslice, surf->level, surf->face, u_minify(tex->b.b.width0, surf->level), u_minify(tex->b.b.height0, surf->level), 1); tex->defined[surf->face][surf->level] = TRUE; } }
/** * Progagate any changes from surfaces to texture. * pipe is optional context to inline the blit command in. */ void svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf) { 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, face; if (!s->dirty) return; if (surf->texture->target == PIPE_TEXTURE_CUBE) { zslice = 0; face = surf->u.tex.first_layer; } else { zslice = surf->u.tex.first_layer; face = 0; } s->dirty = FALSE; ss->texture_timestamp++; svga_age_texture_view(tex, surf->u.tex.level); if (s->handle != tex->handle) { SVGA_DBG(DEBUG_VIEWS, "svga: Surface propagate: tex %p, level %u, from %p\n", tex, surf->u.tex.level, surf); svga_texture_copy_handle(svga, s->handle, 0, 0, 0, s->real_level, s->real_face, tex->handle, 0, 0, zslice, surf->u.tex.level, face, 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, face, surf->u.tex.level); } }
/* XXX still have doubts about this... */ static void svga_surface_copy(struct pipe_context *pipe, struct pipe_resource* dst_tex, unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource* src_tex, unsigned src_level, const struct pipe_box *src_box) { struct svga_context *svga = svga_context(pipe); struct svga_texture *stex, *dtex; /* struct pipe_screen *screen = pipe->screen; SVGA3dCopyBox *box; enum pipe_error ret; struct pipe_surface *srcsurf, *dstsurf;*/ unsigned dst_face, dst_z, src_face, src_z; /* Emit buffered drawing commands, and any back copies. */ svga_surfaces_flush( svga ); /* Fallback for buffers. */ if (dst_tex->target == PIPE_BUFFER && src_tex->target == PIPE_BUFFER) { util_resource_copy_region(pipe, dst_tex, dst_level, dstx, dsty, dstz, src_tex, src_level, src_box); return; } stex = svga_texture(src_tex); dtex = svga_texture(dst_tex); #if 0 srcsurf = screen->get_tex_surface(screen, src_tex, src_level, src_box->z, src_box->z, PIPE_BIND_SAMPLER_VIEW); dstsurf = screen->get_tex_surface(screen, dst_tex, dst_level, dst_box->z, dst_box->z, PIPE_BIND_RENDER_TARGET); SVGA_DBG(DEBUG_DMA, "blit to sid %p (%d,%d), from sid %p (%d,%d) sz %dx%d\n", svga_surface(dstsurf)->handle, dstx, dsty, svga_surface(srcsurf)->handle, src_box->x, src_box->y, width, height); ret = SVGA3D_BeginSurfaceCopy(svga->swc, srcsurf, dstsurf, &box, 1); if(ret != PIPE_OK) { svga_context_flush(svga, NULL); ret = SVGA3D_BeginSurfaceCopy(svga->swc, srcsurf, dstsurf, &box, 1); assert(ret == PIPE_OK); } box->x = dstx; box->y = dsty; box->z = 0; box->w = width; box->h = height; box->d = 1; box->srcx = src_box->x; box->srcy = src_box->y; box->srcz = 0; SVGA_FIFOCommitAll(svga->swc); svga_surface(dstsurf)->dirty = TRUE; svga_propagate_surface(pipe, dstsurf); pipe_surface_reference(&srcsurf, NULL); pipe_surface_reference(&dstsurf, NULL); #else if (src_tex->target == PIPE_TEXTURE_CUBE) { src_face = src_box->z; src_z = 0; assert(src_box->depth == 1); } else { src_face = 0; src_z = src_box->z; } /* different src/dst type???*/ if (dst_tex->target == PIPE_TEXTURE_CUBE) { dst_face = dstz; dst_z = 0; assert(src_box->depth == 1); } else { dst_face = 0; dst_z = dstz; } svga_texture_copy_handle(svga, stex->handle, src_box->x, src_box->y, src_z, src_level, src_face, dtex->handle, dstx, dsty, dst_z, dst_level, dst_face, src_box->width, src_box->height, src_box->depth); #endif }
struct svga_winsys_surface * svga_texture_view_surface(struct pipe_context *pipe, struct svga_texture *tex, SVGA3dSurfaceFormat format, unsigned start_mip, unsigned num_mip, int face_pick, int zslice_pick, struct svga_host_surface_cache_key *key) /* OUT */ { struct svga_screen *ss = svga_screen(pipe->screen); struct svga_winsys_surface *handle; uint32_t i, j; unsigned z_offset = 0; SVGA_DBG(DEBUG_PERF, "svga: Create surface view: face %d zslice %d mips %d..%d\n", face_pick, zslice_pick, start_mip, start_mip+num_mip-1); key->flags = 0; key->format = format; key->numMipLevels = num_mip; key->size.width = u_minify(tex->b.b.width0, start_mip); key->size.height = u_minify(tex->b.b.height0, start_mip); key->size.depth = zslice_pick < 0 ? u_minify(tex->b.b.depth0, start_mip) : 1; key->cachable = 1; assert(key->size.depth == 1); if(tex->b.b.target == PIPE_TEXTURE_CUBE && face_pick < 0) { key->flags |= SVGA3D_SURFACE_CUBEMAP; key->numFaces = 6; } else { key->numFaces = 1; } if(key->format == SVGA3D_FORMAT_INVALID) { key->cachable = 0; return NULL; } SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n"); handle = svga_screen_surface_create(ss, key); if (!handle) { key->cachable = 0; return NULL; } SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle); if (face_pick < 0) face_pick = 0; if (zslice_pick >= 0) z_offset = zslice_pick; for (i = 0; i < key->numMipLevels; i++) { for (j = 0; j < key->numFaces; j++) { if(tex->defined[j + face_pick][i + start_mip]) { unsigned depth = (zslice_pick < 0 ? u_minify(tex->b.b.depth0, i + start_mip) : 1); svga_texture_copy_handle(svga_context(pipe), tex->handle, 0, 0, z_offset, i + start_mip, j + face_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); } } } return handle; }
/** * Try region copy using one of the region copy commands */ static bool try_copy_region(struct svga_context *svga, const struct pipe_blit_info *blit) { unsigned src_layer_face, src_z, dst_layer_face, dst_z; if (!can_blit_via_svga_copy_region(svga, blit)) return false; adjust_z_layer(blit->src.resource->target, blit->src.box.z, &src_layer_face, &src_z); adjust_z_layer(blit->dst.resource->target, blit->dst.box.z, &dst_layer_face, &dst_z); if (can_blit_via_copy_region_vgpu10(svga, blit)) { svga_toggle_render_condition(svga, blit->render_condition_enable, FALSE); copy_region_vgpu10(svga, blit->src.resource, blit->src.box.x, blit->src.box.y, src_z, blit->src.level, src_layer_face, blit->dst.resource, blit->dst.box.x, blit->dst.box.y, dst_z, blit->dst.level, dst_layer_face, blit->src.box.width, blit->src.box.height, blit->src.box.depth); svga_toggle_render_condition(svga, blit->render_condition_enable, TRUE); return true; } if (can_blit_via_surface_copy(svga, blit)) { struct svga_texture *stex = svga_texture(blit->src.resource); struct svga_texture *dtex = svga_texture(blit->dst.resource); svga_surfaces_flush(svga); svga_texture_copy_handle(svga, stex->handle, blit->src.box.x, blit->src.box.y, src_z, blit->src.level, src_layer_face, dtex->handle, blit->dst.box.x, blit->dst.box.y, dst_z, blit->dst.level, dst_layer_face, blit->src.box.width, blit->src.box.height, blit->src.box.depth); svga_define_texture_level(dtex, dst_layer_face, blit->dst.level); svga_set_texture_rendered_to(dtex, dst_layer_face, blit->dst.level); return true; } if (can_blit_via_intra_surface_copy(svga, blit)) { intra_surface_copy(svga, blit->src.resource, blit->src.box.x, blit->src.box.y, src_z, blit->src.level, src_layer_face, blit->dst.box.x, blit->dst.box.y, dst_z, blit->src.box.width, blit->src.box.height, blit->src.box.depth); return true; } return false; }
static void svga_surface_destroy(struct pipe_context *pipe, struct pipe_surface *surf) { struct svga_context *svga = svga_context(pipe); struct svga_surface *s = svga_surface(surf); struct svga_texture *t = svga_texture(surf->texture); struct svga_screen *ss = svga_screen(surf->texture->screen); enum pipe_error ret = PIPE_OK; /* 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) { SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle); svga_screen_surface_destroy(ss, &s->key, &s->handle); } 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); } 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); } pipe_resource_reference(&surf->texture, NULL); FREE(surf); svga->hud.num_surface_views--; } 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) { s->dirty = TRUE; if (s->handle == tex->handle) { /* hmm so 3d textures always have all their slices marked ? */ svga_define_texture_level(tex, surf->u.tex.first_layer, surf->u.tex.level); } 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. */ 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; for (i = 0; i < svgascreen->max_color_buffers; 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); } /** * Progagate any changes from surfaces to texture. * pipe is optional context to inline the blit command in. */ void svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf) { 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; } s->dirty = FALSE; ss->texture_timestamp++; svga_age_texture_view(tex, surf->u.tex.level); if (s->handle != tex->handle) { 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); } } } /** * Check if we should call svga_propagate_surface on the surface. */ boolean svga_surface_needs_propagation(const struct pipe_surface *surf) { const struct svga_surface *s = svga_surface_const(surf); struct svga_texture *tex = svga_texture(surf->texture); return s->dirty && s->handle != tex->handle; } static void svga_get_sample_position(struct pipe_context *context, unsigned sample_count, unsigned sample_index, float *pos_out) { /* We can't actually query the device to learn the sample positions. * These were grabbed from nvidia's driver. */ static const float pos1[1][2] = { { 0.5, 0.5 } }; static const float pos4[4][2] = { { 0.375000, 0.125000 }, { 0.875000, 0.375000 }, { 0.125000, 0.625000 }, { 0.625000, 0.875000 } }; static const float pos8[8][2] = { { 0.562500, 0.312500 }, { 0.437500, 0.687500 }, { 0.812500, 0.562500 }, { 0.312500, 0.187500 }, { 0.187500, 0.812500 }, { 0.062500, 0.437500 }, { 0.687500, 0.937500 }, { 0.937500, 0.062500 } }; static const float pos16[16][2] = { { 0.187500, 0.062500 }, { 0.437500, 0.187500 }, { 0.062500, 0.312500 }, { 0.312500, 0.437500 }, { 0.687500, 0.062500 }, { 0.937500, 0.187500 }, { 0.562500, 0.312500 }, { 0.812500, 0.437500 }, { 0.187500, 0.562500 }, { 0.437500, 0.687500 }, { 0.062500, 0.812500 }, { 0.312500, 0.937500 }, { 0.687500, 0.562500 }, { 0.937500, 0.687500 }, { 0.562500, 0.812500 }, { 0.812500, 0.937500 } }; const float (*positions)[2]; switch (sample_count) { case 4: positions = pos4; break; case 8: positions = pos8; break; case 16: positions = pos16; break; default: positions = pos1; } pos_out[0] = positions[sample_index][0]; pos_out[1] = positions[sample_index][1]; } void svga_init_surface_functions(struct svga_context *svga) { svga->pipe.create_surface = svga_create_surface; svga->pipe.surface_destroy = svga_surface_destroy; svga->pipe.get_sample_position = svga_get_sample_position; }
struct svga_winsys_surface * svga_texture_view_surface(struct svga_context *svga, struct svga_texture *tex, unsigned bind_flags, SVGA3dSurfaceFlags flags, SVGA3dSurfaceFormat format, unsigned start_mip, unsigned num_mip, int layer_pick, unsigned num_layers, int zslice_pick, 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; 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); key->flags = flags; key->format = format; key->numMipLevels = num_mip; key->size.width = u_minify(tex->b.b.width0, start_mip); key->size.height = u_minify(tex->b.b.height0, start_mip); key->size.depth = zslice_pick < 0 ? u_minify(tex->b.b.depth0, start_mip) : 1; key->cachable = 1; key->arraySize = 1; key->numFaces = 1; key->sampleCount = tex->b.b.nr_samples; if (key->sampleCount > 1) { key->flags |= SVGA3D_SURFACE_MASKABLE_ANTIALIAS; } if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) { key->flags |= SVGA3D_SURFACE_CUBEMAP; key->numFaces = 6; } else if (tex->b.b.target == PIPE_TEXTURE_1D_ARRAY || tex->b.b.target == PIPE_TEXTURE_2D_ARRAY) { key->arraySize = num_layers; } if (key->format == SVGA3D_FORMAT_INVALID) { key->cachable = 0; return NULL; } 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; } SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle); 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); } } } return handle; }