static struct pipe_surface * svga_get_tex_surface(struct pipe_screen *screen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags) { struct svga_texture *tex = svga_texture(pt); struct svga_surface *s; boolean render = (flags & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL)) ? TRUE : FALSE; boolean view = FALSE; SVGA3dSurfaceFormat format; s = CALLOC_STRUCT(svga_surface); if (!s) return NULL; pipe_reference_init(&s->base.reference, 1); pipe_resource_reference(&s->base.texture, pt); s->base.format = pt->format; s->base.width = u_minify(pt->width0, level); s->base.height = u_minify(pt->height0, level); s->base.usage = flags; s->base.level = level; s->base.face = face; s->base.zslice = zslice; if (!render) format = svga_translate_format(pt->format); else format = svga_translate_format_render(pt->format); assert(format != SVGA3D_FORMAT_INVALID); if (svga_screen(screen)->debug.force_surface_view) view = TRUE; /* Currently only used for compressed textures */ if (render && format != svga_translate_format(pt->format)) { view = TRUE; } if (level != 0 && svga_screen(screen)->debug.force_level_surface_view) view = TRUE; if (pt->target == PIPE_TEXTURE_3D) view = TRUE; if (svga_screen(screen)->debug.no_surface_view) view = FALSE; if (view) { SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: yes %p, level %u face %u z %u, %p\n", pt, level, face, zslice, s); s->handle = svga_texture_view_surface(NULL, tex, format, level, 1, face, zslice, &s->key); s->real_face = 0; s->real_level = 0; s->real_zslice = 0; } else { SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: no %p, level %u, face %u, z %u, %p\n", pt, level, face, zslice, s); memset(&s->key, 0, sizeof s->key); s->handle = tex->handle; s->real_face = face; s->real_level = level; s->real_zslice = zslice; } return &s->base; }
/** * A helper function to create a surface view. * The view boolean flag specifies whether svga_texture_view_surface() * will be called to create a cloned surface and resource for the view. */ static struct pipe_surface * svga_create_surface_view(struct pipe_context *pipe, struct pipe_resource *pt, const struct pipe_surface *surf_tmpl, boolean view) { struct svga_context *svga = svga_context(pipe); struct svga_texture *tex = svga_texture(pt); struct pipe_screen *screen = pipe->screen; struct svga_screen *ss = svga_screen(screen); struct svga_surface *s; unsigned layer, zslice, bind; unsigned nlayers = 1; SVGA3dSurfaceFlags flags = 0; SVGA3dSurfaceFormat format; s = CALLOC_STRUCT(svga_surface); if (!s) return NULL; 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) { layer = surf_tmpl->u.tex.first_layer; zslice = 0; nlayers = surf_tmpl->u.tex.last_layer - surf_tmpl->u.tex.first_layer + 1; } else { layer = 0; zslice = surf_tmpl->u.tex.first_layer; } pipe_reference_init(&s->base.reference, 1); pipe_resource_reference(&s->base.texture, pt); s->base.context = pipe; s->base.format = surf_tmpl->format; s->base.width = u_minify(pt->width0, surf_tmpl->u.tex.level); s->base.height = u_minify(pt->height0, surf_tmpl->u.tex.level); s->base.u.tex.level = surf_tmpl->u.tex.level; s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer; s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer; s->view_id = SVGA3D_INVALID_ID; s->backed = NULL; if (util_format_is_depth_or_stencil(surf_tmpl->format)) { flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_BIND_DEPTH_STENCIL; bind = PIPE_BIND_DEPTH_STENCIL; } else { flags = SVGA3D_SURFACE_HINT_RENDERTARGET | SVGA3D_SURFACE_BIND_RENDER_TARGET; bind = PIPE_BIND_RENDER_TARGET; } if (tex->imported) format = tex->key.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", pt, surf_tmpl->u.tex.level, layer, zslice, s); if (svga_have_vgpu10(svga)) { switch (pt->target) { case PIPE_TEXTURE_1D: flags |= SVGA3D_SURFACE_1D; break; case PIPE_TEXTURE_1D_ARRAY: flags |= SVGA3D_SURFACE_1D | SVGA3D_SURFACE_ARRAY; break; case PIPE_TEXTURE_2D_ARRAY: flags |= SVGA3D_SURFACE_ARRAY; break; case PIPE_TEXTURE_3D: flags |= SVGA3D_SURFACE_VOLUME; break; case PIPE_TEXTURE_CUBE: if (nlayers == 6) flags |= SVGA3D_SURFACE_CUBEMAP; break; default: break; } } /* 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, surf_tmpl->u.tex.level, 1, layer, nlayers, zslice, &s->key); if (!s->handle) { FREE(s); return NULL; } 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", pt, surf_tmpl->u.tex.level, layer, zslice, s); memset(&s->key, 0, sizeof s->key); s->key.format = format; s->handle = tex->handle; s->real_layer = layer; s->real_zslice = zslice; s->real_level = surf_tmpl->u.tex.level; } svga->hud.num_surface_views++; return &s->base; }
struct svga_sampler_view * svga_get_tex_sampler_view(struct pipe_context *pipe, struct pipe_resource *pt, unsigned min_lod, unsigned max_lod) { struct svga_context *svga = svga_context(pipe); struct svga_screen *ss = svga_screen(pipe->screen); struct svga_texture *tex = svga_texture(pt); struct svga_sampler_view *sv = NULL; SVGA3dSurfaceFlags flags = SVGA3D_SURFACE_HINT_TEXTURE; SVGA3dSurfaceFormat format = svga_translate_format(ss, pt->format, PIPE_BIND_SAMPLER_VIEW); boolean view = TRUE; assert(pt); assert(min_lod <= max_lod); assert(max_lod <= pt->last_level); assert(!svga_have_vgpu10(svga)); /* Is a view needed */ { /* * Can't control max lod. For first level views and when we only * look at one level we disable mip filtering to achive the same * results as a view. */ if (min_lod == 0 && max_lod >= pt->last_level) view = FALSE; if (ss->debug.no_sampler_view) view = FALSE; if (ss->debug.force_sampler_view) view = TRUE; } /* First try the cache */ if (view) { mtx_lock(&ss->tex_mutex); if (tex->cached_view && tex->cached_view->min_lod == min_lod && tex->cached_view->max_lod == max_lod) { svga_sampler_view_reference(&sv, tex->cached_view); mtx_unlock(&ss->tex_mutex); SVGA_DBG(DEBUG_VIEWS, "svga: Sampler view: reuse %p, %u %u, last %u\n", pt, min_lod, max_lod, pt->last_level); svga_validate_sampler_view(svga_context(pipe), sv); return sv; } mtx_unlock(&ss->tex_mutex); } sv = CALLOC_STRUCT(svga_sampler_view); if (!sv) return NULL; pipe_reference_init(&sv->reference, 1); /* Note: we're not refcounting the texture resource here to avoid * a circular dependency. */ sv->texture = pt; sv->min_lod = min_lod; sv->max_lod = max_lod; /* No view needed just use the whole texture */ if (!view) { SVGA_DBG(DEBUG_VIEWS, "svga: Sampler view: no %p, mips %u..%u, nr %u, size (%ux%ux%u), last %u\n", pt, min_lod, max_lod, max_lod - min_lod + 1, pt->width0, pt->height0, pt->depth0, pt->last_level); sv->key.cachable = 0; sv->handle = tex->handle; debug_reference(&sv->reference, (debug_reference_descriptor)svga_debug_describe_sampler_view, 0); return sv; } SVGA_DBG(DEBUG_VIEWS, "svga: Sampler view: yes %p, mips %u..%u, nr %u, size (%ux%ux%u), last %u\n", pt, min_lod, max_lod, max_lod - min_lod + 1, pt->width0, pt->height0, pt->depth0, pt->last_level); sv->age = tex->age; sv->handle = svga_texture_view_surface(svga, tex, PIPE_BIND_SAMPLER_VIEW, flags, format, min_lod, max_lod - min_lod + 1, -1, 1, -1, FALSE, &sv->key); if (!sv->handle) { sv->key.cachable = 0; sv->handle = tex->handle; debug_reference(&sv->reference, (debug_reference_descriptor) svga_debug_describe_sampler_view, 0); return sv; } mtx_lock(&ss->tex_mutex); svga_sampler_view_reference(&tex->cached_view, sv); mtx_unlock(&ss->tex_mutex); debug_reference(&sv->reference, (debug_reference_descriptor) svga_debug_describe_sampler_view, 0); return sv; }
static struct pipe_surface * svga_create_surface(struct pipe_context *pipe, struct pipe_resource *pt, const struct pipe_surface *surf_tmpl) { struct svga_context *svga = svga_context(pipe); struct svga_texture *tex = svga_texture(pt); struct pipe_screen *screen = pipe->screen; struct svga_screen *ss = svga_screen(screen); struct svga_surface *s; unsigned face, zslice; boolean view = FALSE; SVGA3dSurfaceFlags flags; SVGA3dSurfaceFormat format; assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); s = CALLOC_STRUCT(svga_surface); if (!s) return NULL; if (pt->target == PIPE_TEXTURE_CUBE) { face = surf_tmpl->u.tex.first_layer; zslice = 0; } else { face = 0; zslice = surf_tmpl->u.tex.first_layer; } pipe_reference_init(&s->base.reference, 1); pipe_resource_reference(&s->base.texture, pt); s->base.context = pipe; s->base.format = surf_tmpl->format; s->base.width = u_minify(pt->width0, surf_tmpl->u.tex.level); s->base.height = u_minify(pt->height0, surf_tmpl->u.tex.level); s->base.u.tex.level = surf_tmpl->u.tex.level; s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer; s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer; if (util_format_is_depth_or_stencil(surf_tmpl->format)) { flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL; } else { flags = SVGA3D_SURFACE_HINT_RENDERTARGET; } format = svga_translate_format(ss, surf_tmpl->format, 0); assert(format != SVGA3D_FORMAT_INVALID); if (svga_screen(screen)->debug.force_surface_view) view = TRUE; /* Currently only used for compressed textures */ if (format != svga_translate_format(ss, surf_tmpl->format, 0)) { view = TRUE; } if (surf_tmpl->u.tex.level != 0 && svga_screen(screen)->debug.force_level_surface_view) view = TRUE; if (pt->target == PIPE_TEXTURE_3D) view = TRUE; if (svga_screen(screen)->debug.no_surface_view) view = FALSE; if (view) { SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: yes %p, level %u face %u z %u, %p\n", pt, surf_tmpl->u.tex.level, face, zslice, s); s->handle = svga_texture_view_surface(svga, tex, flags, format, surf_tmpl->u.tex.level, 1, face, zslice, &s->key); s->real_face = 0; s->real_level = 0; s->real_zslice = 0; } else { SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: no %p, level %u, face %u, z %u, %p\n", pt, surf_tmpl->u.tex.level, face, zslice, s); memset(&s->key, 0, sizeof s->key); s->handle = tex->handle; s->real_face = face; s->real_zslice = zslice; s->real_level = surf_tmpl->u.tex.level; } return &s->base; }