SVGA3dSurfaceFormat
svga_translate_format_render(enum pipe_format format)
{
   switch(format) { 
   case PIPE_FORMAT_B8G8R8A8_UNORM:
   case PIPE_FORMAT_B8G8R8X8_UNORM:
   case PIPE_FORMAT_B5G5R5A1_UNORM:
   case PIPE_FORMAT_B4G4R4A4_UNORM:
   case PIPE_FORMAT_B5G6R5_UNORM:
   case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
   case PIPE_FORMAT_X8Z24_UNORM:
   case PIPE_FORMAT_Z32_UNORM:
   case PIPE_FORMAT_Z16_UNORM:
   case PIPE_FORMAT_L8_UNORM:
      return svga_translate_format(format);

#if 1
   /* For on host conversion */
   case PIPE_FORMAT_DXT1_RGB:
      return SVGA3D_X8R8G8B8;
   case PIPE_FORMAT_DXT1_RGBA:
   case PIPE_FORMAT_DXT3_RGBA:
   case PIPE_FORMAT_DXT5_RGBA:
      return SVGA3D_A8R8G8B8;
#endif

   default:
      return SVGA3D_FORMAT_INVALID;
   }
}
Esempio n. 2
0
SVGA3dSurfaceFormat
svga_translate_format_render(enum pipe_format format)
{
    switch(format) {
    case PIPE_FORMAT_B8G8R8A8_UNORM:
    case PIPE_FORMAT_B8G8R8X8_UNORM:
    case PIPE_FORMAT_B5G5R5A1_UNORM:
    case PIPE_FORMAT_B4G4R4A4_UNORM:
    case PIPE_FORMAT_B5G6R5_UNORM:
    case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
    case PIPE_FORMAT_X8Z24_UNORM:
    case PIPE_FORMAT_Z32_UNORM:
    case PIPE_FORMAT_Z16_UNORM:
    case PIPE_FORMAT_L8_UNORM:
        return svga_translate_format(format);

    default:
        return SVGA3D_FORMAT_INVALID;
    }
}
Esempio n. 3
0
/**
 * Implement pipe_screen::is_format_supported().
 * \param bindings  bitmask of PIPE_BIND_x flags
 */
static boolean
svga_is_format_supported( struct pipe_screen *screen,
                          enum pipe_format format,
                          enum pipe_texture_target target,
                          unsigned sample_count,
                          unsigned bindings)
{
   struct svga_screen *ss = svga_screen(screen);
   SVGA3dSurfaceFormat svga_format;
   SVGA3dSurfaceFormatCaps caps;
   SVGA3dSurfaceFormatCaps mask;

   assert(bindings);

   if (sample_count > 1) {
      /* In ms_samples, if bit N is set it means that we support
       * multisample with N+1 samples per pixel.
       */
      if ((ss->ms_samples & (1 << (sample_count - 1))) == 0) {
         return FALSE;
      }
   }

   svga_format = svga_translate_format(ss, format, bindings);
   if (svga_format == SVGA3D_FORMAT_INVALID) {
      return FALSE;
   }

   /* we don't support sRGB rendering into display targets */
   if (util_format_is_srgb(format) && (bindings & PIPE_BIND_DISPLAY_TARGET)) {
      return FALSE;
   }

   /*
    * For VGPU10 vertex formats, skip querying host capabilities
    */

   if (ss->sws->have_vgpu10 && (bindings & PIPE_BIND_VERTEX_BUFFER)) {
      SVGA3dSurfaceFormat svga_format;
      unsigned flags;
      svga_translate_vertex_format_vgpu10(format, &svga_format, &flags);
      return svga_format != SVGA3D_FORMAT_INVALID;
   }

   /*
    * Override host capabilities, so that we end up with the same
    * visuals for all virtual hardware implementations.
    */

   if (bindings & PIPE_BIND_DISPLAY_TARGET) {
      switch (svga_format) {
      case SVGA3D_A8R8G8B8:
      case SVGA3D_X8R8G8B8:
      case SVGA3D_R5G6B5:
         break;

      /* VGPU10 formats */
      case SVGA3D_B8G8R8A8_UNORM:
      case SVGA3D_B8G8R8X8_UNORM:
      case SVGA3D_B5G6R5_UNORM:
         break;

      /* Often unsupported/problematic. This means we end up with the same
       * visuals for all virtual hardware implementations.
       */
      case SVGA3D_A4R4G4B4:
      case SVGA3D_A1R5G5B5:
         return FALSE;
         
      default:
         return FALSE;
      }
   }
   
   /*
    * Query the host capabilities.
    */

   svga_get_format_cap(ss, svga_format, &caps);

   if (bindings & PIPE_BIND_RENDER_TARGET) {
      /* Check that the color surface is blendable, unless it's an
       * integer format.
       */
      if (!svga_format_is_integer(svga_format) &&
          (caps.value & SVGA3DFORMAT_OP_NOALPHABLEND)) {
         return FALSE;
      }
   }

   mask.value = 0;
   if (bindings & PIPE_BIND_RENDER_TARGET) {
      mask.value |= SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET;
   }
   if (bindings & PIPE_BIND_DEPTH_STENCIL) {
      mask.value |= SVGA3DFORMAT_OP_ZSTENCIL;
   }
   if (bindings & PIPE_BIND_SAMPLER_VIEW) {
      mask.value |= SVGA3DFORMAT_OP_TEXTURE;
   }

   if (target == PIPE_TEXTURE_CUBE) {
      mask.value |= SVGA3DFORMAT_OP_CUBETEXTURE;
   }
   else if (target == PIPE_TEXTURE_3D) {
      mask.value |= SVGA3DFORMAT_OP_VOLUMETEXTURE;
   }

   return (caps.value & mask.value) == mask.value;
}
Esempio n. 4
0
/**
 * Implemnt pipe_screen::is_format_supported().
 * \param bindings  bitmask of PIPE_BIND_x flags
 */
static boolean
svga_is_format_supported( struct pipe_screen *screen,
                          enum pipe_format format,
                          enum pipe_texture_target target,
                          unsigned sample_count,
                          unsigned bindings)
{
   struct svga_screen *ss = svga_screen(screen);
   SVGA3dSurfaceFormat svga_format;
   SVGA3dSurfaceFormatCaps caps;
   SVGA3dSurfaceFormatCaps mask;

   assert(bindings);

   if (sample_count > 1) {
      return FALSE;
   }

   svga_format = svga_translate_format(ss, format, bindings);
   if (svga_format == SVGA3D_FORMAT_INVALID) {
      return FALSE;
   }

   /*
    * Override host capabilities, so that we end up with the same
    * visuals for all virtual hardware implementations.
    */

   if (bindings & PIPE_BIND_DISPLAY_TARGET) {
      switch (svga_format) {
      case SVGA3D_A8R8G8B8:
      case SVGA3D_X8R8G8B8:
      case SVGA3D_R5G6B5:
         break;

      /* Often unsupported/problematic. This means we end up with the same
       * visuals for all virtual hardware implementations.
       */
      case SVGA3D_A4R4G4B4:
      case SVGA3D_A1R5G5B5:
         return FALSE;
         
      default:
         return FALSE;
      }
   }
   
   /*
    * Query the host capabilities.
    */

   svga_get_format_cap(ss, svga_format, &caps);

   mask.value = 0;
   if (bindings & PIPE_BIND_RENDER_TARGET) {
      mask.offscreenRenderTarget = 1;
   }
   if (bindings & PIPE_BIND_DEPTH_STENCIL) {
      mask.zStencil = 1;
   }
   if (bindings & PIPE_BIND_SAMPLER_VIEW) {
      mask.texture = 1;
   }

   if (target == PIPE_TEXTURE_CUBE) {
      mask.cubeTexture = 1;
   }
   if (target == PIPE_TEXTURE_3D) {
      mask.volumeTexture = 1;
   }

   return (caps.value & mask.value) == mask.value;
}
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
/**
 * Create a DX ShaderResourceSamplerView for the given pipe_sampler_view,
 * if needed.
 */
enum pipe_error
svga_validate_pipe_sampler_view(struct svga_context *svga,
                                struct svga_pipe_sampler_view *sv)
{
   enum pipe_error ret = PIPE_OK;

   if (sv->id == SVGA3D_INVALID_ID) {
      struct svga_screen *ss = svga_screen(svga->pipe.screen);
      struct pipe_resource *texture = sv->base.texture;
      struct svga_winsys_surface *surface = svga_resource_handle(texture);
      SVGA3dSurfaceFormat format;
      SVGA3dResourceType resourceDim;
      SVGA3dShaderResourceViewDesc viewDesc;
      enum pipe_format viewFormat = sv->base.format;

      /* vgpu10 cannot create a BGRX view for a BGRA resource, so force it to
       * create a BGRA view (and vice versa).
       */
      if (viewFormat == PIPE_FORMAT_B8G8R8X8_UNORM &&
          svga_texture_device_format_has_alpha(texture)) {
         viewFormat = PIPE_FORMAT_B8G8R8A8_UNORM;
      }
      else if (viewFormat == PIPE_FORMAT_B8G8R8A8_UNORM &&
               !svga_texture_device_format_has_alpha(texture)) {
         viewFormat = PIPE_FORMAT_B8G8R8X8_UNORM;
      }

      format = svga_translate_format(ss, viewFormat,
                                     PIPE_BIND_SAMPLER_VIEW);
      assert(format != SVGA3D_FORMAT_INVALID);

      /* Convert the format to a sampler-friendly format, if needed */
      format = svga_sampler_format(format);

      if (texture->target == PIPE_BUFFER) {
         unsigned elem_size = util_format_get_blocksize(sv->base.format);

         viewDesc.buffer.firstElement = sv->base.u.buf.offset / elem_size;
         viewDesc.buffer.numElements = sv->base.u.buf.size / elem_size;
      }
      else {
         viewDesc.tex.mostDetailedMip = sv->base.u.tex.first_level;
         viewDesc.tex.firstArraySlice = sv->base.u.tex.first_layer;
         viewDesc.tex.mipLevels = (sv->base.u.tex.last_level -
                                   sv->base.u.tex.first_level + 1);
      }

      /* arraySize in viewDesc specifies the number of array slices in a
       * texture array. For 3D texture, last_layer in
       * pipe_sampler_view specifies the last slice of the texture
       * which is different from the last slice in a texture array,
       * hence we need to set arraySize to 1 explicitly.
       */
      viewDesc.tex.arraySize =
         (texture->target == PIPE_TEXTURE_3D ||
          texture->target == PIPE_BUFFER) ? 1 :
            (sv->base.u.tex.last_layer - sv->base.u.tex.first_layer + 1);

      switch (texture->target) {
      case PIPE_BUFFER:
         resourceDim = SVGA3D_RESOURCE_BUFFER;
         break;
      case PIPE_TEXTURE_1D:
      case PIPE_TEXTURE_1D_ARRAY:
         resourceDim = SVGA3D_RESOURCE_TEXTURE1D;
         break;
      case PIPE_TEXTURE_RECT:
      case PIPE_TEXTURE_2D:
      case PIPE_TEXTURE_2D_ARRAY:
         resourceDim = SVGA3D_RESOURCE_TEXTURE2D;
         break;
      case PIPE_TEXTURE_3D:
         resourceDim = SVGA3D_RESOURCE_TEXTURE3D;
         break;
      case PIPE_TEXTURE_CUBE:
      case PIPE_TEXTURE_CUBE_ARRAY:
         resourceDim = SVGA3D_RESOURCE_TEXTURECUBE;
         break;

      default:
         assert(!"Unexpected texture type");
         resourceDim = SVGA3D_RESOURCE_TEXTURE2D;
      }

      sv->id = util_bitmask_add(svga->sampler_view_id_bm);

      ret = SVGA3D_vgpu10_DefineShaderResourceView(svga->swc,
                                                   sv->id,
                                                   surface,
                                                   format,
                                                   resourceDim,
                                                   &viewDesc);
      if (ret != PIPE_OK) {
         util_bitmask_clear(svga->sampler_view_id_bm, sv->id);
         sv->id = SVGA3D_INVALID_ID;
      }
   }

   return ret;
}
Esempio n. 8
0
/**
 * 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;
}
Esempio n. 9
0
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;
}