/** * 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_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; }