+/**
+ * Create a DX RenderTarget/DepthStencil View for the given surface,
+ * if needed.
+ */
+struct pipe_surface *
+svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s)
+{
+ enum pipe_error ret = PIPE_OK;
+ 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
+ * target view and a shader resource view simultanously.
+ * So first check if the resource bound to this surface view collides with
+ * a sampler view. If so, then we will clone this surface view and its
+ * associated resource. We will then use the cloned surface view for
+ * render target.
+ */
+ for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
+ if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) {
+ SVGA_DBG(DEBUG_VIEWS,
+ "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 && 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;
+ desc.tex.arraySize =
+ s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1;
+
+ s->view_id = util_bitmask_add(svga->surface_view_id_bm);
+
+ resType = svga_resource_type(s->base.texture->target);
+
+ 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;
+ }
+
+ ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc,
+ s->view_id,
+ s->handle,
+ view_format,
+ resType,
+ &desc);
+ }
+
+ if (ret != PIPE_OK) {
+ util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
+ s->view_id = SVGA3D_INVALID_ID;
+ s = NULL;
+ }
+ }
+
+ SVGA_STATS_TIME_POP(svga_sws(svga));
+
+ return s ? &s->base : NULL;
+}
+
+