svga: update driver for version 10 GPU interface
authorBrian Paul <brianp@vmware.com>
Thu, 13 Aug 2015 18:00:58 +0000 (11:00 -0700)
committerBrian Paul <brianp@vmware.com>
Wed, 2 Sep 2015 15:27:43 +0000 (09:27 -0600)
This is a squash commit of roughly two years of development work.
Authors include:
  Brian Paul
  Charmaine Lee
  Thomas Hellstrom
  Jakob Bornecrantz
  Sinclair Yeh
  Mingcheng Chen
  Kai Ninomiya
  MengLin Wu

The driver supports OpenGL 3.3.

Signed-off-by: Brian Paul <brianp@vmware.com>
64 files changed:
src/gallium/drivers/svga/Makefile.sources
src/gallium/drivers/svga/svga_cmd.c
src/gallium/drivers/svga/svga_context.c
src/gallium/drivers/svga/svga_context.h
src/gallium/drivers/svga/svga_debug.h
src/gallium/drivers/svga/svga_draw.c
src/gallium/drivers/svga/svga_draw.h
src/gallium/drivers/svga/svga_draw_arrays.c
src/gallium/drivers/svga/svga_draw_elements.c
src/gallium/drivers/svga/svga_draw_private.h
src/gallium/drivers/svga/svga_format.c
src/gallium/drivers/svga/svga_format.h
src/gallium/drivers/svga/svga_pipe_blend.c
src/gallium/drivers/svga/svga_pipe_blit.c
src/gallium/drivers/svga/svga_pipe_clear.c
src/gallium/drivers/svga/svga_pipe_constants.c
src/gallium/drivers/svga/svga_pipe_depthstencil.c
src/gallium/drivers/svga/svga_pipe_draw.c
src/gallium/drivers/svga/svga_pipe_fs.c
src/gallium/drivers/svga/svga_pipe_gs.c
src/gallium/drivers/svga/svga_pipe_misc.c
src/gallium/drivers/svga/svga_pipe_query.c
src/gallium/drivers/svga/svga_pipe_rasterizer.c
src/gallium/drivers/svga/svga_pipe_sampler.c
src/gallium/drivers/svga/svga_pipe_streamout.c
src/gallium/drivers/svga/svga_pipe_vertex.c
src/gallium/drivers/svga/svga_pipe_vs.c
src/gallium/drivers/svga/svga_resource.c
src/gallium/drivers/svga/svga_resource_buffer.c
src/gallium/drivers/svga/svga_resource_buffer.h
src/gallium/drivers/svga/svga_resource_buffer_upload.c
src/gallium/drivers/svga/svga_resource_texture.c
src/gallium/drivers/svga/svga_resource_texture.h
src/gallium/drivers/svga/svga_sampler_view.c
src/gallium/drivers/svga/svga_sampler_view.h
src/gallium/drivers/svga/svga_screen.c
src/gallium/drivers/svga/svga_screen.h
src/gallium/drivers/svga/svga_screen_cache.c
src/gallium/drivers/svga/svga_screen_cache.h
src/gallium/drivers/svga/svga_shader.c
src/gallium/drivers/svga/svga_shader.h
src/gallium/drivers/svga/svga_state.c
src/gallium/drivers/svga/svga_state.h
src/gallium/drivers/svga/svga_state_constants.c
src/gallium/drivers/svga/svga_state_framebuffer.c
src/gallium/drivers/svga/svga_state_fs.c
src/gallium/drivers/svga/svga_state_need_swtnl.c
src/gallium/drivers/svga/svga_state_rss.c
src/gallium/drivers/svga/svga_state_sampler.c
src/gallium/drivers/svga/svga_state_tss.c
src/gallium/drivers/svga/svga_state_vdecl.c
src/gallium/drivers/svga/svga_state_vs.c
src/gallium/drivers/svga/svga_surface.c
src/gallium/drivers/svga/svga_surface.h
src/gallium/drivers/svga/svga_swtnl_backend.c
src/gallium/drivers/svga/svga_swtnl_draw.c
src/gallium/drivers/svga/svga_swtnl_private.h
src/gallium/drivers/svga/svga_swtnl_state.c
src/gallium/drivers/svga/svga_tgsi.c
src/gallium/drivers/svga/svga_tgsi.h
src/gallium/drivers/svga/svga_tgsi_decl_sm30.c
src/gallium/drivers/svga/svga_tgsi_emit.h
src/gallium/drivers/svga/svga_tgsi_insn.c
src/gallium/drivers/svga/svga_tgsi_vgpu10.c

index 276e6a8e2047a6069ae2fe55d256b55104dd4816..0bd4f289781a49bc0c0f7f3424e9c683b7033ff1 100644 (file)
@@ -1,6 +1,7 @@
 C_SOURCES := \
        svga_cmd.c \
        svga_cmd.h \
+       svga_cmd_vgpu10.c \
        svga_context.c \
        svga_context.h \
        svga_debug.h \
@@ -12,6 +13,7 @@ C_SOURCES := \
        svga_format.c \
        svga_format.h \
        svga_hw_reg.h \
+       svga_link.c \
        svga_pipe_blend.c \
        svga_pipe_blit.c \
        svga_pipe_clear.c \
@@ -20,10 +22,12 @@ C_SOURCES := \
        svga_pipe_draw.c \
        svga_pipe_flush.c \
        svga_pipe_fs.c \
+       svga_pipe_gs.c \
        svga_pipe_misc.c \
        svga_pipe_query.c \
        svga_pipe_rasterizer.c \
        svga_pipe_sampler.c \
+        svga_pipe_streamout.c \
        svga_pipe_vertex.c \
        svga_pipe_vs.c \
        svga_public.h \
@@ -44,14 +48,17 @@ C_SOURCES := \
        svga_shader.c \
        svga_shader.h \
        svga_state.c \
+       svga_state.h \
        svga_state_constants.c \
        svga_state_framebuffer.c \
-       svga_state_fs.c \
-       svga_state.h \
        svga_state_need_swtnl.c \
        svga_state_rss.c \
        svga_state_tss.c \
        svga_state_vdecl.c \
+       svga_state_sampler.c \
+       svga_state_fs.c \
+       svga_state_gs.c \
+       svga_state_tgsi_transform.c \
        svga_state_vs.c \
        svga_surface.c \
        svga_surface.h \
@@ -65,6 +72,7 @@ C_SOURCES := \
        svga_tgsi_emit.h \
        svga_tgsi.h \
        svga_tgsi_insn.c \
+       svga_tgsi_vgpu10.c \
        svga_winsys.h \
        \
        svgadump/svga_dump.c \
@@ -74,20 +82,3 @@ C_SOURCES := \
        svgadump/svga_shader.h \
        svgadump/svga_shader_op.c \
        svgadump/svga_shader_op.h
-
-SVGA_H_FILES := \
-       include/includeCheck.h \
-       include/svga3d_caps.h \
-       include/svga3d_cmd.h \
-       include/svga3d_devcaps.h \
-       include/svga3d_limits.h \
-       include/svga3d_reg.h \
-       include/svga3d_shaderdefs.h \
-       include/svga3d_surfacedefs.h \
-       include/svga3d_types.h \
-       include/svga_escape.h \
-       include/svga_overlay.h \
-       include/svga_reg.h \
-       include/svga_types.h \
-       include/vmware_pack_begin.h \
-       include/vmware_pack_end.h
index 1f64980a8ef8fd791fe489fb7644dcd37c574d37..d3cf52f08e26c0250b0302843e8462b807383ea1 100644 (file)
@@ -66,7 +66,7 @@ surface_to_surfaceid(struct svga_winsys_context *swc, // IN
    if (surface) {
       struct svga_surface *s = svga_surface(surface);
       swc->surface_relocation(swc, &id->sid, NULL, s->handle, flags);
-      id->face = s->real_face; /* faces have the same order */
+      id->face = s->real_layer; /* faces have the same order */
       id->mipmap = s->real_level;
    }
    else {
@@ -460,7 +460,7 @@ SVGA3D_SurfaceDMA(struct svga_winsys_context *swc,
 
    swc->surface_relocation(swc, &cmd->host.sid, NULL,
                            texture->handle, surface_flags);
-   cmd->host.face = st->face; /* PIPE_TEX_FACE_* and SVGA3D_CUBEFACE_* match */
+   cmd->host.face = st->slice; /* PIPE_TEX_FACE_* and SVGA3D_CUBEFACE_* match */
    cmd->host.mipmap = st->base.level;
 
    cmd->transfer = transfer;
@@ -842,6 +842,8 @@ SVGA3D_SetShader(struct svga_winsys_context *swc,
 {
    SVGA3dCmdSetShader *cmd;
 
+   assert(type == SVGA3D_SHADERTYPE_VS || type == SVGA3D_SHADERTYPE_PS);
+
    cmd = SVGA3D_FIFOReserve(swc,
                             SVGA_3D_CMD_SET_SHADER, sizeof *cmd,
                             0);
@@ -1385,7 +1387,7 @@ SVGA3D_BeginGBQuery(struct svga_winsys_context *swc,
    if(!cmd)
       return PIPE_ERROR_OUT_OF_MEMORY;
 
-   swc->context_relocation(swc, &cmd->cid);
+   cmd->cid = swc->cid;
    cmd->type = type;
 
    swc->commit(swc);
@@ -1465,7 +1467,7 @@ SVGA3D_EndGBQuery(struct svga_winsys_context *swc,
    if(!cmd)
       return PIPE_ERROR_OUT_OF_MEMORY;
 
-   swc->context_relocation(swc, &cmd->cid);
+   cmd->cid = swc->cid;
    cmd->type = type;
 
    swc->mob_relocation(swc, &cmd->mobid, &cmd->offset, buffer,
@@ -1552,7 +1554,7 @@ SVGA3D_WaitForGBQuery(struct svga_winsys_context *swc,
    if(!cmd)
       return PIPE_ERROR_OUT_OF_MEMORY;
 
-   swc->context_relocation(swc, &cmd->cid);
+   cmd->cid = swc->cid;
    cmd->type = type;
 
    swc->mob_relocation(swc, &cmd->mobid, &cmd->offset, buffer,
@@ -1642,6 +1644,8 @@ SVGA3D_SetGBShader(struct svga_winsys_context *swc,
                    struct svga_winsys_gb_shader *gbshader)
 {
    SVGA3dCmdSetShader *cmd;
+
+   assert(type == SVGA3D_SHADERTYPE_VS || type == SVGA3D_SHADERTYPE_PS);
    
    cmd = SVGA3D_FIFOReserve(swc,
                             SVGA_3D_CMD_SET_SHADER,
@@ -1650,7 +1654,7 @@ SVGA3D_SetGBShader(struct svga_winsys_context *swc,
    if (!cmd)
       return PIPE_ERROR_OUT_OF_MEMORY;
    
-   swc->context_relocation(swc, &cmd->cid);
+   cmd->cid = swc->cid;
    cmd->type = type;
    if (gbshader)
       swc->shader_relocation(swc, &cmd->shid, NULL, NULL, gbshader, 0);
index 673d17ad4a7f177297ccaf32a9fdc9dfb60f2c36..2bf795de22da3251ac076d94001f090906ba2d73 100644 (file)
@@ -30,6 +30,7 @@
 #include "pipe/p_screen.h"
 #include "util/u_memory.h"
 #include "util/u_bitmask.h"
+#include "util/u_upload_mgr.h"
 
 #include "svga_context.h"
 #include "svga_screen.h"
 #include "svga_draw.h"
 #include "svga_debug.h"
 #include "svga_state.h"
+#include "svga_winsys.h"
+
+#define CONST0_UPLOAD_DEFAULT_SIZE 65536
+#define CONST0_UPLOAD_ALIGNMENT 256
 
 DEBUG_GET_ONCE_BOOL_OPTION(no_swtnl, "SVGA_NO_SWTNL", FALSE)
 DEBUG_GET_ONCE_BOOL_OPTION(force_swtnl, "SVGA_FORCE_SWTNL", FALSE);
@@ -53,27 +58,67 @@ DEBUG_GET_ONCE_BOOL_OPTION(force_hw_line_stipple, "SVGA_FORCE_HW_LINE_STIPPLE",
 static void svga_destroy( struct pipe_context *pipe )
 {
    struct svga_context *svga = svga_context( pipe );
-   struct svga_winsys_screen *sws = svga_screen(pipe->screen)->sws;
-   unsigned shader;
+   unsigned shader, i;
+
+   /* free any alternate rasterizer states used for point sprite */
+   for (i = 0; i < Elements(svga->rasterizer_no_cull); i++) {
+      if (svga->rasterizer_no_cull[i]) {
+         pipe->delete_rasterizer_state(pipe, svga->rasterizer_no_cull[i]);
+      }
+   }
+
+   /* free polygon stipple state */
+   if (svga->polygon_stipple.sampler) {
+      pipe->delete_sampler_state(pipe, svga->polygon_stipple.sampler);
+   }
+   if (svga->polygon_stipple.sampler_view) {
+      pipe->sampler_view_destroy(pipe,
+                                 &svga->polygon_stipple.sampler_view->base);
+   }
+   pipe_resource_reference(&svga->polygon_stipple.texture, NULL);
+
+   /* free HW constant buffers */
+   for (shader = 0; shader < Elements(svga->state.hw_draw.constbuf); shader++) {
+      pipe_resource_reference(&svga->state.hw_draw.constbuf[shader], NULL);
+   }
+
+   pipe->delete_blend_state(pipe, svga->noop_blend);
+
+   /* free query gb object */
+   if (svga->gb_query) {
+      pipe->destroy_query(pipe, NULL);
+      svga->gb_query = NULL;
+   }
 
    util_blitter_destroy(svga->blitter);
 
    svga_cleanup_framebuffer( svga );
    svga_cleanup_tss_binding( svga );
 
-   svga_hwtnl_destroy( svga->hwtnl );
-
    svga_cleanup_vertex_state(svga);
    
-   svga->swc->destroy(svga->swc);
-   
    svga_destroy_swtnl( svga );
+   svga_hwtnl_destroy( svga->hwtnl );
 
-   util_bitmask_destroy( svga->shader_id_bm );
+   svga->swc->destroy(svga->swc);
 
+   util_bitmask_destroy(svga->blend_object_id_bm);
+   util_bitmask_destroy(svga->ds_object_id_bm);
+   util_bitmask_destroy(svga->input_element_object_id_bm);
+   util_bitmask_destroy(svga->rast_object_id_bm);
+   util_bitmask_destroy(svga->sampler_object_id_bm);
+   util_bitmask_destroy(svga->sampler_view_id_bm);
+   util_bitmask_destroy(svga->shader_id_bm);
+   util_bitmask_destroy(svga->surface_view_id_bm);
+   util_bitmask_destroy(svga->stream_output_id_bm);
+   util_bitmask_destroy(svga->query_id_bm);
+   u_upload_destroy(svga->const0_upload);
+
+   /* free user's constant buffers */
    for (shader = 0; shader < PIPE_SHADER_TYPES; ++shader) {
-      pipe_resource_reference( &svga->curr.cbufs[shader].buffer, NULL );
-      sws->surface_reference(sws, &svga->state.hw_draw.hw_cb[shader], NULL);
+      for (i = 0; i < Elements(svga->curr.constbufs[shader]); ++i) {
+         pipe_resource_reference(&svga->curr.constbufs[shader][i].buffer, NULL);
+      }
    }
 
    FREE( svga );
@@ -90,7 +135,7 @@ struct pipe_context *svga_context_create(struct pipe_screen *screen,
 
    svga = CALLOC_STRUCT(svga_context);
    if (svga == NULL)
-      goto no_svga;
+      goto cleanup;
 
    LIST_INITHEAD(&svga->dirty_buffers);
 
@@ -100,8 +145,8 @@ struct pipe_context *svga_context_create(struct pipe_screen *screen,
    svga->pipe.clear = svga_clear;
 
    svga->swc = svgascreen->sws->context_create(svgascreen->sws);
-   if(!svga->swc)
-      goto no_swc;
+   if (!svga->swc)
+      goto cleanup;
 
    svga_init_resource_functions(svga);
    svga_init_blend_functions(svga);
@@ -114,11 +159,15 @@ struct pipe_context *svga_context_create(struct pipe_screen *screen,
    svga_init_sampler_functions(svga);
    svga_init_fs_functions(svga);
    svga_init_vs_functions(svga);
+   svga_init_gs_functions(svga);
    svga_init_vertex_functions(svga);
    svga_init_constbuffer_functions(svga);
    svga_init_query_functions(svga);
    svga_init_surface_functions(svga);
+   svga_init_stream_output_functions(svga);
 
+   /* init misc state */
+   svga->curr.sample_mask = ~0;
 
    /* debug */
    svga->debug.no_swtnl = debug_get_option_no_swtnl();
@@ -128,21 +177,54 @@ struct pipe_context *svga_context_create(struct pipe_screen *screen,
    svga->debug.no_line_width = debug_get_option_no_line_width();
    svga->debug.force_hw_line_stipple = debug_get_option_force_hw_line_stipple();
 
-   svga->shader_id_bm = util_bitmask_create();
-   if (svga->shader_id_bm == NULL)
-      goto no_shader_bm;
+   if (!(svga->blend_object_id_bm = util_bitmask_create()))
+      goto cleanup;
+
+   if (!(svga->ds_object_id_bm = util_bitmask_create()))
+      goto cleanup;
+
+   if (!(svga->input_element_object_id_bm = util_bitmask_create()))
+      goto cleanup;
+
+   if (!(svga->rast_object_id_bm = util_bitmask_create()))
+      goto cleanup;
+
+   if (!(svga->sampler_object_id_bm = util_bitmask_create()))
+      goto cleanup;
+
+   if (!(svga->sampler_view_id_bm = util_bitmask_create()))
+      goto cleanup;
+
+   if (!(svga->shader_id_bm = util_bitmask_create()))
+      goto cleanup;
+
+   if (!(svga->surface_view_id_bm = util_bitmask_create()))
+      goto cleanup;
+
+   if (!(svga->stream_output_id_bm = util_bitmask_create()))
+      goto cleanup;
+
+   if (!(svga->query_id_bm = util_bitmask_create()))
+      goto cleanup;
 
    svga->hwtnl = svga_hwtnl_create(svga);
    if (svga->hwtnl == NULL)
-      goto no_hwtnl;
+      goto cleanup;
 
    if (!svga_init_swtnl(svga))
-      goto no_swtnl;
+      goto cleanup;
 
    ret = svga_emit_initial_state( svga );
    if (ret != PIPE_OK)
-      goto no_state;
-   
+      goto cleanup;
+
+   svga->const0_upload = u_upload_create(&svga->pipe,
+                                         CONST0_UPLOAD_DEFAULT_SIZE,
+                                         CONST0_UPLOAD_ALIGNMENT,
+                                         PIPE_BIND_CONSTANT_BUFFER);
+   if (!svga->const0_upload)
+      goto cleanup;
+
    /* Avoid shortcircuiting state with initial value of zero.
     */
    memset(&svga->state.hw_clear, 0xcd, sizeof(svga->state.hw_clear));
@@ -151,24 +233,64 @@ struct pipe_context *svga_context_create(struct pipe_screen *screen,
 
    memset(&svga->state.hw_draw, 0xcd, sizeof(svga->state.hw_draw));
    memset(&svga->state.hw_draw.views, 0x0, sizeof(svga->state.hw_draw.views));
+   memset(&svga->state.hw_draw.num_sampler_views, 0,
+      sizeof(svga->state.hw_draw.num_sampler_views));
    svga->state.hw_draw.num_views = 0;
-   memset(&svga->state.hw_draw.hw_cb, 0x0, sizeof(svga->state.hw_draw.hw_cb));
+
+   /* Initialize the shader pointers */
+   svga->state.hw_draw.vs = NULL;
+   svga->state.hw_draw.gs = NULL;
+   svga->state.hw_draw.fs = NULL;
+   memset(svga->state.hw_draw.constbuf, 0,
+          sizeof(svga->state.hw_draw.constbuf));
+   memset(svga->state.hw_draw.default_constbuf_size, 0,
+          sizeof(svga->state.hw_draw.default_constbuf_size));
+   memset(svga->state.hw_draw.enabled_constbufs, 0,
+          sizeof(svga->state.hw_draw.enabled_constbufs));
+
+   /* Create a no-operation blend state which we will bind whenever the
+    * requested blend state is impossible (e.g. due to having an integer
+    * render target attached).
+    *
+    * XXX: We will probably actually need 16 of these, one for each possible
+    * RGBA color mask (4 bits).  Then, we would bind the one with a color mask
+    * matching the blend state it is replacing.
+    */
+   {
+      struct pipe_blend_state noop_tmpl = {0};
+      unsigned i;
+
+      for (i = 0; i < PIPE_MAX_COLOR_BUFS; ++i) {
+         // Set the color mask to all-ones.  Later this may change.
+         noop_tmpl.rt[i].colormask = PIPE_MASK_RGBA;
+      }
+      svga->noop_blend = svga->pipe.create_blend_state(&svga->pipe, &noop_tmpl);
+   }
 
    svga->dirty = ~0;
 
    return &svga->pipe;
 
-no_state:
+cleanup:
    svga_destroy_swtnl(svga);
-no_swtnl:
-   svga_hwtnl_destroy( svga->hwtnl );
-no_hwtnl:
-   util_bitmask_destroy( svga->shader_id_bm );
-no_shader_bm:
-   svga->swc->destroy(svga->swc);
-no_swc:
+
+   if (svga->const0_upload)
+      u_upload_destroy(svga->const0_upload);
+   if (svga->hwtnl)
+      svga_hwtnl_destroy(svga->hwtnl);
+   if (svga->swc)
+      svga->swc->destroy(svga->swc);
+   util_bitmask_destroy(svga->blend_object_id_bm);
+   util_bitmask_destroy(svga->ds_object_id_bm);
+   util_bitmask_destroy(svga->input_element_object_id_bm);
+   util_bitmask_destroy(svga->rast_object_id_bm);
+   util_bitmask_destroy(svga->sampler_object_id_bm);
+   util_bitmask_destroy(svga->sampler_view_id_bm);
+   util_bitmask_destroy(svga->shader_id_bm);
+   util_bitmask_destroy(svga->surface_view_id_bm);
+   util_bitmask_destroy(svga->stream_output_id_bm);
+   util_bitmask_destroy(svga->query_id_bm);
    FREE(svga);
-no_svga:
    return NULL;
 }
 
@@ -195,11 +317,19 @@ void svga_context_flush( struct svga_context *svga,
    /* To force the re-emission of rendertargets and texture sampler bindings on
     * the next command buffer.
     */
-   svga->rebind.rendertargets = TRUE;
-   svga->rebind.texture_samplers = TRUE;
+   svga->rebind.flags.rendertargets = TRUE;
+   svga->rebind.flags.texture_samplers = TRUE;
+
    if (svga_have_gb_objects(svga)) {
-      svga->rebind.vs = TRUE;
-      svga->rebind.fs = TRUE;
+
+      svga->rebind.flags.constbufs = TRUE;
+      svga->rebind.flags.vs = TRUE;
+      svga->rebind.flags.fs = TRUE;
+      svga->rebind.flags.gs = TRUE;
+
+      if (svga_need_to_rebind_resources(svga)) {
+         svga->rebind.flags.query = TRUE;
+      }
    }
 
    if (SVGA_DEBUG & DEBUG_SYNC) {
@@ -215,6 +345,26 @@ void svga_context_flush( struct svga_context *svga,
 }
 
 
+/**
+ * Flush pending commands and wait for completion with a fence.
+ */
+void
+svga_context_finish(struct svga_context *svga)
+{
+   struct pipe_screen *screen = svga->pipe.screen;
+   struct pipe_fence_handle *fence = NULL;
+
+   svga_context_flush(svga, &fence);
+   svga->pipe.screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
+   screen->fence_reference(screen, &fence, NULL);
+}
+
+
+/**
+ * Emit pending drawing commands to the command buffer.
+ * If the command buffer overflows, we flush it and retry.
+ * \sa svga_hwtnl_flush()
+ */
 void svga_hwtnl_flush_retry( struct svga_context *svga )
 {
    enum pipe_error ret = PIPE_OK;
@@ -225,7 +375,7 @@ void svga_hwtnl_flush_retry( struct svga_context *svga )
       ret = svga_hwtnl_flush( svga->hwtnl );
    }
 
-   assert(ret == 0);
+   assert(ret == PIPE_OK);
 }
 
 
index 2726346bc50653430c01b9d345492425cf49d90c..e8575f36c3b176c614b495191ef7b8d38a6a2886 100644 (file)
@@ -38,7 +38,6 @@
 
 #include "svga_screen.h"
 #include "svga_state.h"
-#include "svga_tgsi.h"
 #include "svga_winsys.h"
 #include "svga_hw_reg.h"
 #include "svga3d_shaderdefs.h"
 #define SVGA_QUERY_DRAW_CALLS   (PIPE_QUERY_DRIVER_SPECIFIC + 0)
 #define SVGA_QUERY_FALLBACKS    (PIPE_QUERY_DRIVER_SPECIFIC + 1)
 #define SVGA_QUERY_MEMORY_USED  (PIPE_QUERY_DRIVER_SPECIFIC + 2)
+#define SVGA_QUERY_MAX          (PIPE_QUERY_DRIVER_SPECIFIC + 3)
 
+/**
+ * Maximum supported number of constant buffers per shader
+ */
+#define SVGA_MAX_CONST_BUFS 14
+
+/**
+ * Maximum constant buffer size that can be set in the
+ * DXSetSingleConstantBuffer command is
+ * DX10 constant buffer element count * 4 4-bytes components
+ */
+#define SVGA_MAX_CONST_BUF_SIZE (4096 * 4 * sizeof(int))
 
 struct draw_vertex_shader;
 struct draw_fragment_shader;
@@ -57,49 +68,16 @@ struct SVGACmdMemory;
 struct util_bitmask;
 
 
-struct svga_shader
-{
-   const struct tgsi_token *tokens;
-
-   struct tgsi_shader_info info;
-
-   /** Head of linked list of variants */
-   struct svga_shader_variant *variants;
-
-   unsigned id;  /**< for debugging only */
-};
-
-
-struct svga_fragment_shader
-{
-   struct svga_shader base;
-
-   struct draw_fragment_shader *draw_shader;
-
-   /** Mask of which generic varying variables are read by this shader */
-   unsigned generic_inputs;
-   /** Table mapping original TGSI generic indexes to low integers */
-   int8_t generic_remap_table[MAX_GENERIC_VARYING];
-};
-
-
-struct svga_vertex_shader
-{
-   struct svga_shader base;
-
-   struct draw_vertex_shader *draw_shader;
-};
-
-
 struct svga_cache_context;
 struct svga_tracked_state;
 
 struct svga_blend_state {
+   unsigned need_white_fragments:1;
+   unsigned independent_blend_enable:1;
+   unsigned alpha_to_coverage:1;
+   unsigned blend_color_alpha:1;  /**< set blend color to alpha value */
 
-   boolean need_white_fragments;
-
-   /* Should be per-render-target:
-    */
+   /** Per-render target state */
    struct {
       uint8_t writemask;
 
@@ -112,8 +90,9 @@ struct svga_blend_state {
       uint8_t srcblend_alpha;
       uint8_t dstblend_alpha;
       uint8_t blendeq_alpha;
+   } rt[PIPE_MAX_COLOR_BUFS];
 
-   } rt[1];
+   SVGA3dBlendStateId id;  /**< vgpu10 */
 };
 
 struct svga_depth_stencil_state {
@@ -139,6 +118,8 @@ struct svga_depth_stencil_state {
    unsigned stencil_writemask:8;
 
    float    alpharef;
+
+   SVGA3dDepthStencilStateId id;  /**< vgpu10 */
 };
 
 #define SVGA_UNFILLED_DISABLE 0
@@ -167,11 +148,13 @@ struct svga_rasterizer_state {
    float pointsize;
    float linewidth;
    
-   unsigned hw_unfilled:16;         /* PIPE_POLYGON_MODE_x */
+   unsigned hw_fillmode:2;         /* PIPE_POLYGON_MODE_x */
 
    /** Which prims do we need help for?  Bitmask of (1 << PIPE_PRIM_x) flags */
    unsigned need_pipeline:16;
 
+   SVGA3dRasterizerStateId id;    /**< vgpu10 */
+
    /** For debugging: */
    const char* need_pipeline_tris_str;
    const char* need_pipeline_lines_str;
@@ -195,15 +178,45 @@ struct svga_sampler_state {
    unsigned min_lod;
    unsigned view_min_lod;
    unsigned view_max_lod;
+
+   SVGA3dSamplerId id;
 };
 
+
+struct svga_pipe_sampler_view
+{
+   struct pipe_sampler_view base;
+
+   SVGA3dShaderResourceViewId id;
+};
+
+
+static inline struct svga_pipe_sampler_view *
+svga_pipe_sampler_view(struct pipe_sampler_view *v)
+{
+   return (struct svga_pipe_sampler_view *) v;
+}
+
+
 struct svga_velems_state {
    unsigned count;
    struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS];
    SVGA3dDeclType decl_type[PIPE_MAX_ATTRIBS]; /**< vertex attrib formats */
-   unsigned adjust_attrib_range; /* bitmask of attrs needing range adjustment */
-   unsigned adjust_attrib_w_1;   /* bitmask of attrs needing w = 1 */
+
+   /** Bitmasks indicating which attributes need format conversion */
+   unsigned adjust_attrib_range;     /**< range adjustment */
+   unsigned attrib_is_pure_int;      /**< pure int */
+   unsigned adjust_attrib_w_1;       /**< set w = 1 */
+   unsigned adjust_attrib_itof;      /**< int->float */
+   unsigned adjust_attrib_utof;      /**< uint->float */
+   unsigned attrib_is_bgra;          /**< R / B swizzling */
+   unsigned attrib_puint_to_snorm;   /**< 10_10_10_2 packed uint -> snorm */
+   unsigned attrib_puint_to_uscaled; /**< 10_10_10_2 packed uint -> uscaled */
+   unsigned attrib_puint_to_sscaled; /**< 10_10_10_2 packed uint -> sscaled */
+
    boolean need_swvfetch;
+
+   SVGA3dElementLayoutId id; /**< VGPU10 */
 };
 
 /* Use to calculate differences between state emitted to hardware and
@@ -214,16 +227,22 @@ struct svga_state
    const struct svga_blend_state *blend;
    const struct svga_depth_stencil_state *depth;
    const struct svga_rasterizer_state *rast;
-   const struct svga_sampler_state *sampler[PIPE_MAX_SAMPLERS];
+   const struct svga_sampler_state *sampler[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
    const struct svga_velems_state *velems;
 
-   struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; /* or texture ID's? */
+   struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; /* or texture ID's? */
    struct svga_fragment_shader *fs;
    struct svga_vertex_shader *vs;
+   struct svga_geometry_shader *user_gs; /* user-specified GS */
+   struct svga_geometry_shader *gs;      /* derived GS */
 
    struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS];
    struct pipe_index_buffer ib;
-   struct pipe_constant_buffer cbufs[PIPE_SHADER_TYPES];
+   /** Constant buffers for each shader.
+    * The size should probably always match with that of
+    * svga_shader_emitter_v10.num_shader_consts.
+    */
+   struct pipe_constant_buffer constbufs[PIPE_SHADER_TYPES][SVGA_MAX_CONST_BUFS];
 
    struct pipe_framebuffer_state framebuffer;
    float depthscale;
@@ -240,8 +259,8 @@ struct svga_state
    struct pipe_clip_state clip;
    struct pipe_viewport_state viewport;
 
-   unsigned num_samplers;
-   unsigned num_sampler_views;
+   unsigned num_samplers[PIPE_SHADER_TYPES];
+   unsigned num_sampler_views[PIPE_SHADER_TYPES];
    unsigned num_vertex_buffers;
    unsigned reduced_prim;
 
@@ -249,6 +268,8 @@ struct svga_state
       unsigned flag_1d;
       unsigned flag_srgb;
    } tex_flags;
+
+   unsigned sample_mask;
 };
 
 struct svga_prescale {
@@ -262,9 +283,7 @@ struct svga_prescale {
  */
 struct svga_hw_clear_state
 {
-   struct {
-      unsigned x,y,w,h;
-   } viewport;
+   SVGA3dRect viewport;
 
    struct {
       float zmin, zmax;
@@ -291,16 +310,29 @@ struct svga_hw_draw_state
    unsigned ts[SVGA3D_PIXEL_SAMPLERREG_MAX][SVGA3D_TS_MAX];
    float cb[PIPE_SHADER_TYPES][SVGA3D_CONSTREG_MAX][4];
 
-   /**
-    * For guest backed shader constants only.
-    */
-   struct svga_winsys_surface *hw_cb[PIPE_SHADER_TYPES];
-
    struct svga_shader_variant *fs;
    struct svga_shader_variant *vs;
+   struct svga_shader_variant *gs;
    struct svga_hw_view_state views[PIPE_MAX_SAMPLERS];
-
    unsigned num_views;
+   struct pipe_resource *constbuf[PIPE_SHADER_TYPES];
+
+   /* Bitmask of enabled constant bufffers */
+   unsigned enabled_constbufs[PIPE_SHADER_TYPES];
+
+   /* VGPU10 HW state (used to prevent emitting redundant state) */
+   SVGA3dDepthStencilStateId depth_stencil_id;
+   unsigned stencil_ref;
+   SVGA3dBlendStateId blend_id;
+   float blend_factor[4];
+   unsigned blend_sample_mask;
+   SVGA3dRasterizerStateId rasterizer_id;
+   SVGA3dElementLayoutId layout_id;
+   SVGA3dPrimitiveType topology;
+
+   /* used for rebinding */
+   unsigned num_sampler_views[PIPE_SHADER_TYPES];
+   unsigned default_constbuf_size[PIPE_SHADER_TYPES];
 };
 
 
@@ -326,12 +358,14 @@ struct svga_sw_state
 struct svga_hw_queue;
 
 struct svga_query;
+struct svga_qmem_alloc_entry;
 
 struct svga_context
 {
    struct pipe_context pipe;
    struct svga_winsys_context *swc;
    struct blitter_context *blitter;
+   struct u_upload_mgr *const0_upload;
 
    struct {
       boolean no_swtnl;
@@ -355,12 +389,42 @@ struct svga_context
       boolean new_vdecl;
    } swtnl;
 
+   /* Bitmask of blend state objects IDs */
+   struct util_bitmask *blend_object_id_bm;
+
+   /* Bitmask of depth/stencil state objects IDs */
+   struct util_bitmask *ds_object_id_bm;
+
+   /* Bitmaks of input element object IDs */
+   struct util_bitmask *input_element_object_id_bm;
+
+   /* Bitmask of rasterizer object IDs */
+   struct util_bitmask *rast_object_id_bm;
+
+   /* Bitmask of sampler state objects IDs */
+   struct util_bitmask *sampler_object_id_bm;
+
+   /* Bitmask of sampler view IDs */
+   struct util_bitmask *sampler_view_id_bm;
+
    /* Bitmask of used shader IDs */
    struct util_bitmask *shader_id_bm;
 
+   /* Bitmask of used surface view IDs */
+   struct util_bitmask *surface_view_id_bm;
+
+   /* Bitmask of used stream output IDs */
+   struct util_bitmask *stream_output_id_bm;
+
+   /* Bitmask of used query IDs */
+   struct util_bitmask *query_id_bm;
+
    struct {
       unsigned dirty[SVGA_STATE_MAX];
 
+      /** bitmasks of which const buffers are changed */
+      unsigned dirty_constbufs[PIPE_SHADER_TYPES];
+
       unsigned texture_timestamp;
 
       /* 
@@ -373,17 +437,28 @@ struct svga_context
    struct svga_state curr;      /* state from the state tracker */
    unsigned dirty;              /* statechanges since last update_state() */
 
-   struct {
-      unsigned rendertargets:1;
-      unsigned texture_samplers:1;
-      unsigned vs:1;
-      unsigned fs:1;
+   union {
+      struct {
+         unsigned rendertargets:1;
+         unsigned texture_samplers:1;
+         unsigned constbufs:1;
+         unsigned vs:1;
+         unsigned fs:1;
+         unsigned gs:1;
+         unsigned query:1;
+      } flags;
+      unsigned val;
    } rebind;
 
    struct svga_hwtnl *hwtnl;
 
-   /** The occlusion query currently in progress */
-   struct svga_query *sq;
+   /** Queries states */
+   struct svga_winsys_gb_query *gb_query;     /**< gb query object, one per context */
+   unsigned gb_query_len;                     /**< gb query object size */
+   struct util_bitmask *gb_query_alloc_mask;  /**< gb query object allocation mask */
+   struct svga_qmem_alloc_entry *gb_query_map[SVGA_QUERY_MAX];
+                                              /**< query mem block mapping */
+   struct svga_query *sq[SVGA_QUERY_MAX];     /**< queries currently in progress */
 
    /** List of buffers with queued transfers */
    struct list_head dirty_buffers;
@@ -391,12 +466,32 @@ struct svga_context
    /** performance / info queries */
    uint64_t num_draw_calls;  /**< SVGA_QUERY_DRAW_CALLS */
    uint64_t num_fallbacks;   /**< SVGA_QUERY_FALLBACKS */
+
+   /** The currently bound stream output targets */
+   unsigned num_so_targets;
+   struct svga_winsys_surface *so_surfaces[SVGA3D_DX_MAX_SOTARGETS];
+   struct pipe_stream_output_target *so_targets[SVGA3D_DX_MAX_SOTARGETS];
+   struct svga_stream_output *current_so;
+
+   /** A blend state with blending disabled, for falling back to when blending
+    * is illegal (e.g. an integer texture is bound)
+    */
+   struct svga_blend_state *noop_blend;
+
+   struct {
+      struct pipe_resource *texture;
+      struct svga_pipe_sampler_view *sampler_view;
+      void *sampler;
+   } polygon_stipple;
+
+   /** Alternate rasterizer states created for point sprite */
+   struct svga_rasterizer_state *rasterizer_no_cull[2];
 };
 
 /* A flag for each state_tracker state object:
  */
 #define SVGA_NEW_BLEND               0x1
-#define SVGA_NEW_DEPTH_STENCIL       0x2
+#define SVGA_NEW_DEPTH_STENCIL_ALPHA 0x2
 #define SVGA_NEW_RAST                0x4
 #define SVGA_NEW_SAMPLER             0x8
 #define SVGA_NEW_TEXTURE             0x10
@@ -422,7 +517,9 @@ struct svga_context
 #define SVGA_NEW_VS_VARIANT          0x1000000
 #define SVGA_NEW_TEXTURE_FLAGS       0x4000000
 #define SVGA_NEW_STENCIL_REF         0x8000000
-
+#define SVGA_NEW_GS                  0x10000000
+#define SVGA_NEW_GS_CONST_BUFFER     0x20000000
+#define SVGA_NEW_GS_VARIANT          0x40000000
 
 
 
@@ -457,11 +554,13 @@ void svga_init_rasterizer_functions( struct svga_context *svga );
 void svga_init_sampler_functions( struct svga_context *svga );
 void svga_init_fs_functions( struct svga_context *svga );
 void svga_init_vs_functions( struct svga_context *svga );
+void svga_init_gs_functions( struct svga_context *svga );
 void svga_init_vertex_functions( struct svga_context *svga );
 void svga_init_constbuffer_functions( struct svga_context *svga );
 void svga_init_draw_functions( struct svga_context *svga );
 void svga_init_query_functions( struct svga_context *svga );
 void svga_init_surface_functions(struct svga_context *svga);
+void svga_init_stream_output_functions( struct svga_context *svga );
 
 void svga_cleanup_vertex_state( struct svga_context *svga );
 void svga_cleanup_tss_binding( struct svga_context *svga );
@@ -470,6 +569,8 @@ void svga_cleanup_framebuffer( struct svga_context *svga );
 void svga_context_flush( struct svga_context *svga,
                          struct pipe_fence_handle **pfence );
 
+void svga_context_finish(struct svga_context *svga);
+
 void svga_hwtnl_flush_retry( struct svga_context *svga );
 void svga_hwtnl_flush_buffer( struct svga_context *svga,
                               struct pipe_resource *buffer );
@@ -504,5 +605,22 @@ svga_have_gb_dma(const struct svga_context *svga)
    return svga_screen(svga->pipe.screen)->sws->have_gb_dma;
 }
 
+static inline boolean
+svga_have_vgpu10(const struct svga_context *svga)
+{
+   return svga_screen(svga->pipe.screen)->sws->have_vgpu10;
+}
+
+static inline boolean
+svga_need_to_rebind_resources(const struct svga_context *svga)
+{
+   return svga_screen(svga->pipe.screen)->sws->need_to_rebind_resources;
+}
+
+static inline boolean
+svga_rects_equal(const SVGA3dRect *r1, const SVGA3dRect *r2)
+{
+   return memcmp(r1, r2, sizeof(*r1)) == 0;
+}
 
 #endif
index 82c9b602d5dd99ccf2d6ea6014457064f886e0d0..039f79d4e99d7a8d49700f27388265b29c684759 100644 (file)
 #include "pipe/p_compiler.h"
 #include "util/u_debug.h"
 
-#define DEBUG_DMA      0x1
-#define DEBUG_TGSI     0x4
-#define DEBUG_PIPE     0x8
-#define DEBUG_STATE    0x10
-#define DEBUG_SCREEN   0x20
-#define DEBUG_TEX      0x40
-#define DEBUG_SWTNL    0x80
-#define DEBUG_CONSTS   0x100
-#define DEBUG_VIEWPORT 0x200
-#define DEBUG_VIEWS    0x400
-#define DEBUG_PERF     0x800    /* print something when we hit any slow path operation */
-#define DEBUG_FLUSH    0x1000   /* flush after every draw */
-#define DEBUG_SYNC     0x2000   /* sync after every flush */
-#define DEBUG_QUERY    0x4000
-#define DEBUG_CACHE    0x8000
+#define DEBUG_DMA          0x1
+#define DEBUG_TGSI         0x4
+#define DEBUG_PIPE         0x8
+#define DEBUG_STATE        0x10
+#define DEBUG_SCREEN       0x20
+#define DEBUG_TEX          0x40
+#define DEBUG_SWTNL        0x80
+#define DEBUG_CONSTS       0x100
+#define DEBUG_VIEWPORT     0x200
+#define DEBUG_VIEWS        0x400
+#define DEBUG_PERF         0x800    /* print something when we hit any slow path operation */
+#define DEBUG_FLUSH        0x1000   /* flush after every draw */
+#define DEBUG_SYNC         0x2000   /* sync after every flush */
+#define DEBUG_QUERY        0x4000
+#define DEBUG_CACHE        0x8000
+#define DEBUG_STREAMOUT    0x10000
 
 #ifdef DEBUG
 extern int SVGA_DEBUG;
index 366a2dccdf128c1487ad8df6e937181f03fac5e0..9b6451da2f950a6992e421580eb1be61f74ea790 100644 (file)
 #include "pipe/p_compiler.h"
 #include "util/u_inlines.h"
 #include "pipe/p_defines.h"
+#include "util/u_helpers.h"
 #include "util/u_memory.h"
 #include "util/u_math.h"
-#include "util/u_upload_mgr.h"
 
 #include "svga_context.h"
 #include "svga_draw.h"
 #include "svga_draw_private.h"
 #include "svga_debug.h"
 #include "svga_screen.h"
+#include "svga_resource.h"
 #include "svga_resource_buffer.h"
 #include "svga_resource_texture.h"
+#include "svga_shader.h"
 #include "svga_surface.h"
 #include "svga_winsys.h"
 #include "svga_cmd.h"
@@ -71,8 +73,8 @@ svga_hwtnl_destroy(struct svga_hwtnl *hwtnl)
       }
    }
 
-   for (i = 0; i < hwtnl->cmd.vdecl_count; i++)
-      pipe_resource_reference(&hwtnl->cmd.vdecl_vb[i], NULL);
+   for (i = 0; i < hwtnl->cmd.vbuf_count; i++)
+      pipe_resource_reference(&hwtnl->cmd.vbufs[i].buffer, NULL);
 
    for (i = 0; i < hwtnl->cmd.prim_count; i++)
       pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
@@ -85,45 +87,55 @@ void
 svga_hwtnl_set_flatshade(struct svga_hwtnl *hwtnl,
                          boolean flatshade, boolean flatshade_first)
 {
-   hwtnl->hw_pv = PV_FIRST;
+   struct svga_screen *svgascreen = svga_screen(hwtnl->svga->pipe.screen);
+
+   /* User-specified PV */
    hwtnl->api_pv = (flatshade && !flatshade_first) ? PV_LAST : PV_FIRST;
+
+   /* Device supported PV */
+   if (svgascreen->haveProvokingVertex) {
+      /* use the mode specified by the user */
+      hwtnl->hw_pv = hwtnl->api_pv;
+   }
+   else {
+      /* the device only support first provoking vertex */
+      hwtnl->hw_pv = PV_FIRST;
+   }
 }
 
 
 void
-svga_hwtnl_set_unfilled(struct svga_hwtnl *hwtnl, unsigned mode)
+svga_hwtnl_set_fillmode(struct svga_hwtnl *hwtnl, unsigned mode)
 {
    hwtnl->api_fillmode = mode;
 }
 
 
 void
-svga_hwtnl_reset_vdecl(struct svga_hwtnl *hwtnl, unsigned count)
+svga_hwtnl_vertex_decls(struct svga_hwtnl *hwtnl,
+                        unsigned count,
+                        const SVGA3dVertexDecl * decls,
+                        const unsigned *buffer_indexes,
+                        SVGA3dElementLayoutId layout_id)
 {
-   unsigned i;
-
    assert(hwtnl->cmd.prim_count == 0);
-
-   for (i = count; i < hwtnl->cmd.vdecl_count; i++) {
-      pipe_resource_reference(&hwtnl->cmd.vdecl_vb[i], NULL);
-   }
-
    hwtnl->cmd.vdecl_count = count;
+   hwtnl->cmd.vdecl_layout_id = layout_id;
+   memcpy(hwtnl->cmd.vdecl, decls, count * sizeof(*decls));
+   memcpy(hwtnl->cmd.vdecl_buffer_index, buffer_indexes,
+          count * sizeof(unsigned));
 }
 
 
+/**
+ * Specify vertex buffers for hardware drawing.
+ */
 void
-svga_hwtnl_vdecl(struct svga_hwtnl *hwtnl,
-                 unsigned i,
-                 const SVGA3dVertexDecl * decl, struct pipe_resource *vb)
+svga_hwtnl_vertex_buffers(struct svga_hwtnl *hwtnl,
+                          unsigned count, struct pipe_vertex_buffer *buffers)
 {
-   assert(hwtnl->cmd.prim_count == 0);
-
-   assert(i < hwtnl->cmd.vdecl_count);
-
-   hwtnl->cmd.vdecl[i] = *decl;
-
-   pipe_resource_reference(&hwtnl->cmd.vdecl_vb[i], vb);
+   util_set_vertex_buffers_count(hwtnl->cmd.vbufs,
+                                 &hwtnl->cmd.vbuf_count, buffers, 0, count);
 }
 
 
@@ -145,8 +157,8 @@ svga_hwtnl_is_buffer_referred(struct svga_hwtnl *hwtnl,
       return FALSE;
    }
 
-   for (i = 0; i < hwtnl->cmd.vdecl_count; ++i) {
-      if (hwtnl->cmd.vdecl_vb[i] == buffer) {
+   for (i = 0; i < hwtnl->cmd.vbuf_count; ++i) {
+      if (hwtnl->cmd.vbufs[i].buffer == buffer) {
          return TRUE;
       }
    }
@@ -161,120 +173,444 @@ svga_hwtnl_is_buffer_referred(struct svga_hwtnl *hwtnl,
 }
 
 
-enum pipe_error
-svga_hwtnl_flush(struct svga_hwtnl *hwtnl)
+static enum pipe_error
+draw_vgpu9(struct svga_hwtnl *hwtnl)
 {
    struct svga_winsys_context *swc = hwtnl->cmd.swc;
    struct svga_context *svga = hwtnl->svga;
    enum pipe_error ret;
+   struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX];
+   struct svga_winsys_surface *ib_handle[QSZ];
+   struct svga_winsys_surface *handle;
+   SVGA3dVertexDecl *vdecl;
+   SVGA3dPrimitiveRange *prim;
+   unsigned i;
 
-   if (hwtnl->cmd.prim_count) {
-      struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX];
-      struct svga_winsys_surface *ib_handle[QSZ];
-      struct svga_winsys_surface *handle;
-      SVGA3dVertexDecl *vdecl;
-      SVGA3dPrimitiveRange *prim;
-      unsigned i;
+   for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
+      unsigned j = hwtnl->cmd.vdecl_buffer_index[i];
+      handle = svga_buffer_handle(svga, hwtnl->cmd.vbufs[j].buffer);
+      if (handle == NULL)
+         return PIPE_ERROR_OUT_OF_MEMORY;
 
-      for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
-         assert(!svga_buffer_is_user_buffer(hwtnl->cmd.vdecl_vb[i]));
-         handle = svga_buffer_handle(svga, hwtnl->cmd.vdecl_vb[i]);
+      vb_handle[i] = handle;
+   }
+
+   for (i = 0; i < hwtnl->cmd.prim_count; i++) {
+      if (hwtnl->cmd.prim_ib[i]) {
+         handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i]);
          if (handle == NULL)
             return PIPE_ERROR_OUT_OF_MEMORY;
+      }
+      else
+         handle = NULL;
+
+      ib_handle[i] = handle;
+   }
+
+   if (svga->rebind.flags.rendertargets) {
+      ret = svga_reemit_framebuffer_bindings(svga);
+      if (ret != PIPE_OK) {
+         return ret;
+      }
+   }
+
+   if (svga->rebind.flags.texture_samplers) {
+      ret = svga_reemit_tss_bindings(svga);
+      if (ret != PIPE_OK) {
+         return ret;
+      }
+   }
+
+   if (svga->rebind.flags.vs) {
+      ret = svga_reemit_vs_bindings(svga);
+      if (ret != PIPE_OK) {
+         return ret;
+      }
+   }
+
+   if (svga->rebind.flags.fs) {
+      ret = svga_reemit_fs_bindings(svga);
+      if (ret != PIPE_OK) {
+         return ret;
+      }
+   }
+
+   SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n",
+            svga->curr.framebuffer.cbufs[0] ?
+            svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL,
+            hwtnl->cmd.prim_count);
 
-         vb_handle[i] = handle;
+   ret = SVGA3D_BeginDrawPrimitives(swc,
+                                    &vdecl,
+                                    hwtnl->cmd.vdecl_count,
+                                    &prim, hwtnl->cmd.prim_count);
+   if (ret != PIPE_OK)
+      return ret;
+
+   memcpy(vdecl,
+          hwtnl->cmd.vdecl,
+          hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]);
+
+   for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
+      /* check for 4-byte alignment */
+      assert(vdecl[i].array.offset % 4 == 0);
+      assert(vdecl[i].array.stride % 4 == 0);
+
+      /* Given rangeHint is considered to be relative to indexBias, and
+       * indexBias varies per primitive, we cannot accurately supply an
+       * rangeHint when emitting more than one primitive per draw command.
+       */
+      if (hwtnl->cmd.prim_count == 1) {
+         vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0];
+         vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1;
+      }
+      else {
+         vdecl[i].rangeHint.first = 0;
+         vdecl[i].rangeHint.last = 0;
       }
 
-      for (i = 0; i < hwtnl->cmd.prim_count; i++) {
-         if (hwtnl->cmd.prim_ib[i]) {
-            assert(!svga_buffer_is_user_buffer(hwtnl->cmd.prim_ib[i]));
-            handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i]);
-            if (handle == NULL)
-               return PIPE_ERROR_OUT_OF_MEMORY;
+      swc->surface_relocation(swc,
+                              &vdecl[i].array.surfaceId,
+                              NULL, vb_handle[i], SVGA_RELOC_READ);
+   }
+
+   memcpy(prim,
+          hwtnl->cmd.prim, hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]);
+
+   for (i = 0; i < hwtnl->cmd.prim_count; i++) {
+      swc->surface_relocation(swc,
+                              &prim[i].indexArray.surfaceId,
+                              NULL, ib_handle[i], SVGA_RELOC_READ);
+      pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
+   }
+
+   SVGA_FIFOCommitAll(swc);
+
+   hwtnl->cmd.prim_count = 0;
+
+   return PIPE_OK;
+}
+
+
+static SVGA3dSurfaceFormat
+xlate_index_format(unsigned indexWidth)
+{
+   if (indexWidth == 2) {
+      return SVGA3D_R16_UINT;
+   }
+   else if (indexWidth == 4) {
+      return SVGA3D_R32_UINT;
+   }
+   else {
+      assert(!"Bad indexWidth");
+      return SVGA3D_R32_UINT;
+   }
+}
+
+
+static enum pipe_error
+validate_sampler_resources(struct svga_context *svga)
+{
+   unsigned shader;
+
+   assert(svga_have_vgpu10(svga));
+
+   for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
+      unsigned count = svga->curr.num_sampler_views[shader];
+      unsigned i;
+      struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS];
+      enum pipe_error ret;
+
+      /*
+       * Reference bound sampler resources to ensure pending updates are
+       * noticed by the device.
+       */
+      for (i = 0; i < count; i++) {
+         struct svga_pipe_sampler_view *sv =
+            svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]);
+
+         if (sv) {
+            if (sv->base.texture->target == PIPE_BUFFER) {
+               surfaces[i] = svga_buffer_handle(svga, sv->base.texture);
+            }
+            else {
+               surfaces[i] = svga_texture(sv->base.texture)->handle;
+            }
          }
          else {
-            handle = NULL;
+            surfaces[i] = NULL;
          }
-
-         ib_handle[i] = handle;
       }
 
-      if (svga->rebind.rendertargets) {
-         ret = svga_reemit_framebuffer_bindings(svga);
-         if (ret != PIPE_OK) {
-            return ret;
-         }
+      if (shader == PIPE_SHADER_FRAGMENT &&
+          svga->curr.rast->templ.poly_stipple_enable) {
+         const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit;
+         struct svga_pipe_sampler_view *sv =
+            svga->polygon_stipple.sampler_view;
+
+         assert(sv);
+         surfaces[unit] = svga_texture(sv->base.texture)->handle;
+         count = MAX2(count, unit+1);
       }
 
-      if (svga->rebind.texture_samplers) {
-         ret = svga_reemit_tss_bindings(svga);
-         if (ret != PIPE_OK) {
-            return ret;
+      /* rebind the shader resources if needed */
+      if (svga->rebind.flags.texture_samplers) {
+         for (i = 0; i < count; i++) {
+            if (surfaces[i]) {
+               ret = svga->swc->resource_rebind(svga->swc,
+                                                surfaces[i],
+                                                NULL,
+                                                SVGA_RELOC_READ);
+               if (ret != PIPE_OK)
+                  return ret;
+            }
          }
       }
+   }
+   svga->rebind.flags.texture_samplers = FALSE;
 
-      if (svga->rebind.vs) {
-         ret = svga_reemit_vs_bindings(svga);
-         if (ret != PIPE_OK) {
-            return ret;
+   return PIPE_OK;
+}
+
+
+static enum pipe_error
+validate_constant_buffers(struct svga_context *svga)
+{
+   unsigned shader;
+
+   assert(svga_have_vgpu10(svga));
+
+   for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
+      enum pipe_error ret;
+      struct svga_buffer *buffer;
+      struct svga_winsys_surface *handle;
+      unsigned enabled_constbufs;
+
+      /* Rebind the default constant buffer if needed */
+      if (svga->rebind.flags.constbufs) {
+         buffer = svga_buffer(svga->state.hw_draw.constbuf[shader]);
+         if (buffer) {
+            ret = svga->swc->resource_rebind(svga->swc,
+                                             buffer->handle,
+                                             NULL,
+                                             SVGA_RELOC_READ);
+            if (ret != PIPE_OK)
+               return ret;
          }
       }
 
-      if (svga->rebind.fs) {
-         ret = svga_reemit_fs_bindings(svga);
-         if (ret != PIPE_OK) {
-            return ret;
+      /*
+       * Reference other bound constant buffers to ensure pending updates are
+       * noticed by the device.
+       */
+      enabled_constbufs = svga->state.hw_draw.enabled_constbufs[shader] & ~1u;
+      while (enabled_constbufs) {
+         unsigned i = u_bit_scan(&enabled_constbufs);
+         buffer = svga_buffer(svga->curr.constbufs[shader][i].buffer);
+         if (buffer) {
+            handle = svga_buffer_handle(svga, &buffer->b.b);
+
+            if (svga->rebind.flags.constbufs) {
+               ret = svga->swc->resource_rebind(svga->swc,
+                                                handle,
+                                                NULL,
+                                                SVGA_RELOC_READ);
+               if (ret != PIPE_OK)
+                  return ret;
+            }
          }
       }
+   }
+   svga->rebind.flags.constbufs = FALSE;
+
+   return PIPE_OK;
+}
 
-      SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n",
-               svga->curr.framebuffer.cbufs[0] ?
-               svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL,
-               hwtnl->cmd.prim_count);
 
-      ret = SVGA3D_BeginDrawPrimitives(swc, &vdecl, hwtnl->cmd.vdecl_count,
-                                       &prim, hwtnl->cmd.prim_count);
+static enum pipe_error
+draw_vgpu10(struct svga_hwtnl *hwtnl,
+            const SVGA3dPrimitiveRange *range,
+            unsigned vcount,
+            unsigned min_index,
+            unsigned max_index, struct pipe_resource *ib,
+            unsigned start_instance, unsigned instance_count)
+{
+   struct svga_context *svga = hwtnl->svga;
+   struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX];
+   struct svga_winsys_surface *ib_handle;
+   const unsigned vbuf_count = hwtnl->cmd.vbuf_count;
+   enum pipe_error ret;
+   unsigned i;
+
+   assert(svga_have_vgpu10(svga));
+   assert(hwtnl->cmd.prim_count == 0);
+
+   /* We need to reemit all the current resource bindings along with the Draw
+    * command to be sure that the referenced resources are available for the
+    * Draw command, just in case the surfaces associated with the resources
+    * are paged out.
+    */
+   if (svga->rebind.val) {
+      ret = svga_rebind_framebuffer_bindings(svga);
       if (ret != PIPE_OK)
          return ret;
 
-      memcpy(vdecl, hwtnl->cmd.vdecl,
-             hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]);
-
-      for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
-         /* Given rangeHint is considered to be relative to indexBias, and 
-          * indexBias varies per primitive, we cannot accurately supply an 
-          * rangeHint when emitting more than one primitive per draw command.
-          */
-         if (hwtnl->cmd.prim_count == 1) {
-            vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0];
-            vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1;
-         }
-         else {
-            vdecl[i].rangeHint.first = 0;
-            vdecl[i].rangeHint.last = 0;
-         }
+      ret = svga_rebind_shaders(svga);
+      if (ret != PIPE_OK)
+         return ret;
+   }
+
+   ret = validate_sampler_resources(svga);
+   if (ret != PIPE_OK)
+      return ret;
 
-         swc->surface_relocation(swc, &vdecl[i].array.surfaceId, NULL,
-                                 vb_handle[i], SVGA_RELOC_READ);
+   ret = validate_constant_buffers(svga);
+   if (ret != PIPE_OK)
+      return ret;
+
+   /* Get handle for each referenced vertex buffer */
+   for (i = 0; i < vbuf_count; i++) {
+      struct svga_buffer *sbuf = svga_buffer(hwtnl->cmd.vbufs[i].buffer);
+
+      if (sbuf) {
+         assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_VERTEX_BUFFER);
+         vb_handle[i] = svga_buffer_handle(svga, &sbuf->b.b);
+         if (vb_handle[i] == NULL)
+            return PIPE_ERROR_OUT_OF_MEMORY;
       }
+      else {
+         vb_handle[i] = NULL;
+      }
+   }
 
-      memcpy(prim, hwtnl->cmd.prim,
-             hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]);
+   /* Get handles for the index buffers */
+   if (ib) {
+      struct svga_buffer *sbuf = svga_buffer(ib);
 
-      for (i = 0; i < hwtnl->cmd.prim_count; i++) {
-         swc->surface_relocation(swc, &prim[i].indexArray.surfaceId, NULL,
-                                 ib_handle[i], SVGA_RELOC_READ);
-         pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
+      assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_INDEX_BUFFER);
+      (void) sbuf; /* silence unused var warning */
+
+      ib_handle = svga_buffer_handle(svga, ib);
+      if (ib_handle == NULL)
+         return PIPE_ERROR_OUT_OF_MEMORY;
+   }
+   else {
+      ib_handle = NULL;
+   }
+
+   /* setup vertex attribute input layout */
+   if (svga->state.hw_draw.layout_id != hwtnl->cmd.vdecl_layout_id) {
+      ret = SVGA3D_vgpu10_SetInputLayout(svga->swc,
+                                         hwtnl->cmd.vdecl_layout_id);
+      if (ret != PIPE_OK)
+         return ret;
+
+      svga->state.hw_draw.layout_id = hwtnl->cmd.vdecl_layout_id;
+   }
+
+   /* setup vertex buffers */
+   {
+      SVGA3dVertexBuffer buffers[PIPE_MAX_ATTRIBS];
+
+      for (i = 0; i < vbuf_count; i++) {
+         buffers[i].stride = hwtnl->cmd.vbufs[i].stride;
+         buffers[i].offset = hwtnl->cmd.vbufs[i].buffer_offset;
+      }
+      if (vbuf_count > 0) {
+         ret = SVGA3D_vgpu10_SetVertexBuffers(svga->swc, vbuf_count,
+                                              0,    /* startBuffer */
+                                              buffers, vb_handle);
+         if (ret != PIPE_OK)
+            return ret;
       }
+   }
+
+   /* Set primitive type (line, tri, etc) */
+   if (svga->state.hw_draw.topology != range->primType) {
+      ret = SVGA3D_vgpu10_SetTopology(svga->swc, range->primType);
+      if (ret != PIPE_OK)
+         return ret;
+
+      svga->state.hw_draw.topology = range->primType;
+   }
 
-      SVGA_FIFOCommitAll(swc);
-      hwtnl->cmd.prim_count = 0;
+   if (ib_handle) {
+      /* indexed drawing */
+      SVGA3dSurfaceFormat indexFormat = xlate_index_format(range->indexWidth);
+
+      /* setup index buffer */
+      ret = SVGA3D_vgpu10_SetIndexBuffer(svga->swc, ib_handle,
+                                         indexFormat,
+                                         range->indexArray.offset);
+      if (ret != PIPE_OK)
+         return ret;
+
+      if (instance_count > 1) {
+         ret = SVGA3D_vgpu10_DrawIndexedInstanced(svga->swc,
+                                                  vcount,
+                                                  instance_count,
+                                                  0, /* startIndexLocation */
+                                                  range->indexBias,
+                                                  start_instance);
+         if (ret != PIPE_OK)
+            return ret;
+      }
+      else {
+         /* non-instanced drawing */
+         ret = SVGA3D_vgpu10_DrawIndexed(svga->swc,
+                                         vcount,
+                                         0,      /* startIndexLocation */
+                                         range->indexBias);
+         if (ret != PIPE_OK)
+            return ret;
+      }
    }
+   else {
+      /* non-indexed drawing */
+      if (instance_count > 1) {
+         ret = SVGA3D_vgpu10_DrawInstanced(svga->swc,
+                                           vcount,
+                                           instance_count,
+                                           range->indexBias,
+                                           start_instance);
+         if (ret != PIPE_OK)
+            return ret;
+      }
+      else {
+         /* non-instanced */
+         ret = SVGA3D_vgpu10_Draw(svga->swc,
+                                  vcount,
+                                  range->indexBias);
+         if (ret != PIPE_OK)
+            return ret;
+      }
+   }
+
+   hwtnl->cmd.prim_count = 0;
 
    return PIPE_OK;
 }
 
 
+
+/**
+ * Emit any pending drawing commands to the command buffer.
+ * When we receive VGPU9 drawing commands we accumulate them and don't
+ * immediately emit them into the command buffer.
+ * This function needs to be called before we change state that could
+ * effect those pending draws.
+ */
+enum pipe_error
+svga_hwtnl_flush(struct svga_hwtnl *hwtnl)
+{
+   if (!svga_have_vgpu10(hwtnl->svga) && hwtnl->cmd.prim_count) {
+      /* we only queue up primitive for VGPU9 */
+      return draw_vgpu9(hwtnl);
+   }
+   return PIPE_OK;
+}
+
+
 void
 svga_hwtnl_set_index_bias(struct svga_hwtnl *hwtnl, int index_bias)
 {
@@ -298,18 +634,28 @@ check_draw_params(struct svga_hwtnl *hwtnl,
 {
    unsigned i;
 
+   assert(!svga_have_vgpu10(hwtnl->svga));
+
    for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
-      struct pipe_resource *vb = hwtnl->cmd.vdecl_vb[i];
-      unsigned size = vb ? vb->width0 : 0;
+      unsigned j = hwtnl->cmd.vdecl_buffer_index[i];
+      const struct pipe_vertex_buffer *vb = &hwtnl->cmd.vbufs[j];
+      unsigned size = vb->buffer ? vb->buffer->width0 : 0;
       unsigned offset = hwtnl->cmd.vdecl[i].array.offset;
       unsigned stride = hwtnl->cmd.vdecl[i].array.stride;
       int index_bias = (int) range->indexBias + hwtnl->index_bias;
       unsigned width;
 
+      if (size == 0)
+         continue;
+
       assert(vb);
       assert(size);
       assert(offset < size);
       assert(min_index <= max_index);
+      (void) width;
+      (void) stride;
+      (void) offset;
+      (void) size;
 
       switch (hwtnl->cmd.vdecl[i].identity.type) {
       case SVGA3D_DECLTYPE_FLOAT1:
@@ -390,6 +736,9 @@ check_draw_params(struct svga_hwtnl *hwtnl,
       assert(size);
       assert(offset < size);
       assert(stride);
+      (void) size;
+      (void) offset;
+      (void) stride;
 
       switch (range->primType) {
       case SVGA3D_PRIMITIVE_POINTLIST:
@@ -421,33 +770,57 @@ check_draw_params(struct svga_hwtnl *hwtnl,
 }
 
 
+/**
+ * All drawing filters down into this function, either directly
+ * on the hardware path or after doing software vertex processing.
+ */
 enum pipe_error
 svga_hwtnl_prim(struct svga_hwtnl *hwtnl,
                 const SVGA3dPrimitiveRange * range,
+                unsigned vcount,
                 unsigned min_index,
-                unsigned max_index, struct pipe_resource *ib)
+                unsigned max_index, struct pipe_resource *ib,
+                unsigned start_instance, unsigned instance_count)
 {
    enum pipe_error ret = PIPE_OK;
 
+   if (svga_have_vgpu10(hwtnl->svga)) {
+      /* draw immediately */
+      ret = draw_vgpu10(hwtnl, range, vcount, min_index, max_index, ib,
+                        start_instance, instance_count);
+      if (ret != PIPE_OK) {
+         svga_context_flush(hwtnl->svga, NULL);
+         ret = draw_vgpu10(hwtnl, range, vcount, min_index, max_index, ib,
+                           start_instance, instance_count);
+         assert(ret == PIPE_OK);
+      }
+   }
+   else {
+      /* batch up drawing commands */
 #ifdef DEBUG
-   check_draw_params(hwtnl, range, min_index, max_index, ib);
+      check_draw_params(hwtnl, range, min_index, max_index, ib);
+      assert(start_instance == 0);
+      assert(instance_count <= 1);
+#else
+      (void) check_draw_params;
 #endif
 
-   if (hwtnl->cmd.prim_count + 1 >= QSZ) {
-      ret = svga_hwtnl_flush(hwtnl);
-      if (ret != PIPE_OK)
-         return ret;
-   }
+      if (hwtnl->cmd.prim_count + 1 >= QSZ) {
+         ret = svga_hwtnl_flush(hwtnl);
+         if (ret != PIPE_OK)
+            return ret;
+      }
 
-   /* min/max indices are relative to bias */
-   hwtnl->cmd.min_index[hwtnl->cmd.prim_count] = min_index;
-   hwtnl->cmd.max_index[hwtnl->cmd.prim_count] = max_index;
+      /* min/max indices are relative to bias */
+      hwtnl->cmd.min_index[hwtnl->cmd.prim_count] = min_index;
+      hwtnl->cmd.max_index[hwtnl->cmd.prim_count] = max_index;
 
-   hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range;
-   hwtnl->cmd.prim[hwtnl->cmd.prim_count].indexBias += hwtnl->index_bias;
+      hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range;
+      hwtnl->cmd.prim[hwtnl->cmd.prim_count].indexBias += hwtnl->index_bias;
 
-   pipe_resource_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib);
-   hwtnl->cmd.prim_count++;
+      pipe_resource_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib);
+      hwtnl->cmd.prim_count++;
+   }
 
    return ret;
 }
index 1db79cd91c77183ef710182a4622e54abf30d8a8..af8ecabcbae8df0073aba639cb95fd866993c157 100644 (file)
@@ -35,54 +35,50 @@ struct svga_winsys_context;
 struct svga_screen;
 struct svga_context;
 struct pipe_resource;
+struct u_upload_mgr;
 
-struct svga_hwtnl *
-svga_hwtnl_create(struct svga_context *svga);
+struct svga_hwtnl *svga_hwtnl_create(struct svga_context *svga);
 
-void svga_hwtnl_destroy( struct svga_hwtnl *hwtnl );
+void svga_hwtnl_destroy(struct svga_hwtnl *hwtnl);
 
-void svga_hwtnl_set_flatshade( struct svga_hwtnl *hwtnl,
-                               boolean flatshade,
-                               boolean flatshade_first );
+void svga_hwtnl_set_flatshade(struct svga_hwtnl *hwtnl,
+                              boolean flatshade, boolean flatshade_first);
 
-void svga_hwtnl_set_unfilled( struct svga_hwtnl *hwtnl,
-                              unsigned mode );
+void svga_hwtnl_set_fillmode(struct svga_hwtnl *hwtnl, unsigned mode);
 
-void svga_hwtnl_vdecl( struct svga_hwtnl *hwtnl,
-                       unsigned i,
-                       const SVGA3dVertexDecl *decl,
-                       struct pipe_resource *vb);
+void
+svga_hwtnl_vertex_decls(struct svga_hwtnl *hwtnl,
+                        unsigned count,
+                        const SVGA3dVertexDecl * decls,
+                        const unsigned *buffer_indexes,
+                        SVGA3dElementLayoutId layoutId);
 
-void svga_hwtnl_reset_vdecl( struct svga_hwtnl *hwtnl,
-                             unsigned count );
+void
+svga_hwtnl_vertex_buffers(struct svga_hwtnl *hwtnl,
+                          unsigned count, struct pipe_vertex_buffer *buffers);
 
-
-enum pipe_error 
-svga_hwtnl_draw_arrays( struct svga_hwtnl *hwtnl,
-                        unsigned prim, 
-                        unsigned start, 
-                        unsigned count);
+enum pipe_error
+svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl,
+                       unsigned prim, unsigned start, unsigned count,
+                       unsigned start_instance, unsigned instance_count);
 
 enum pipe_error
-svga_hwtnl_draw_range_elements( struct svga_hwtnl *hwtnl,
-                                struct pipe_resource *indexBuffer,
-                                unsigned index_size,
-                                int index_bias,
-                                unsigned min_index,
-                                unsigned max_index,
-                                unsigned prim, 
-                                unsigned start, 
-                                unsigned count );
+svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl,
+                               struct pipe_resource *indexBuffer,
+                               unsigned index_size,
+                               int index_bias,
+                               unsigned min_index,
+                               unsigned max_index,
+                               unsigned prim, unsigned start, unsigned count,
+                               unsigned start_instance, unsigned instance_count);
 
 boolean
-svga_hwtnl_is_buffer_referred( struct svga_hwtnl *hwtnl,
-                               struct pipe_resource *buffer );
+svga_hwtnl_is_buffer_referred(struct svga_hwtnl *hwtnl,
+                              struct pipe_resource *buffer);
 
-enum pipe_error
-svga_hwtnl_flush( struct svga_hwtnl *hwtnl );
+enum pipe_error svga_hwtnl_flush(struct svga_hwtnl *hwtnl);
 
-void svga_hwtnl_set_index_bias( struct svga_hwtnl *hwtnl,
-                                int index_bias);
+void svga_hwtnl_set_index_bias(struct svga_hwtnl *hwtnl, int index_bias);
 
 
 #endif /* SVGA_DRAW_H_ */
index d4d77200f59880f83d0600bb3cc5ef0684c0fdf7..5635411d93874e79eda966ea69eec2804c9e147b 100644 (file)
@@ -49,8 +49,8 @@ generate_indices(struct svga_hwtnl *hwtnl,
    struct pipe_resource *dst = NULL;
    void *dst_map = NULL;
 
-   dst = pipe_buffer_create(pipe->screen,
-                            PIPE_BIND_INDEX_BUFFER, PIPE_USAGE_DEFAULT, size);
+   dst = pipe_buffer_create(pipe->screen, PIPE_BIND_INDEX_BUFFER,
+                            PIPE_USAGE_IMMUTABLE, size);
    if (dst == NULL)
       goto fail;
 
@@ -168,7 +168,8 @@ retrieve_or_generate_indices(struct svga_hwtnl *hwtnl,
 
 static enum pipe_error
 simple_draw_arrays(struct svga_hwtnl *hwtnl,
-                   unsigned prim, unsigned start, unsigned count)
+                   unsigned prim, unsigned start, unsigned count,
+                   unsigned start_instance, unsigned instance_count)
 {
    SVGA3dPrimitiveRange range;
    unsigned hw_prim;
@@ -191,13 +192,16 @@ simple_draw_arrays(struct svga_hwtnl *hwtnl,
     * looking at those numbers knows to adjust them by
     * range.indexBias.
     */
-   return svga_hwtnl_prim(hwtnl, &range, 0, count - 1, NULL);
+   return svga_hwtnl_prim(hwtnl, &range, count,
+                          0, count - 1, NULL,
+                          start_instance, instance_count);
 }
 
 
 enum pipe_error
 svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl,
-                       unsigned prim, unsigned start, unsigned count)
+                       unsigned prim, unsigned start, unsigned count,
+                       unsigned start_instance, unsigned instance_count)
 {
    unsigned gen_prim, gen_size, gen_nr, gen_type;
    u_generate_func gen_func;
@@ -228,7 +232,8 @@ svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl,
    }
 
    if (gen_type == U_GENERATE_LINEAR) {
-      return simple_draw_arrays(hwtnl, gen_prim, start, count);
+      return simple_draw_arrays(hwtnl, gen_prim, start, count,
+                                start_instance, instance_count);
    }
    else {
       struct pipe_resource *gen_buf = NULL;
@@ -250,8 +255,9 @@ svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl,
                                                   start,
                                                   0,
                                                   count - 1,
-                                                  gen_prim, 0, gen_nr);
-
+                                                  gen_prim, 0, gen_nr,
+                                                  start_instance,
+                                                  instance_count);
       if (ret != PIPE_OK)
          goto done;
 
index 038500a35bde9b60f58e027dc649f72359c6b273..9df8f6e9beb46112f8da94a1970915bd06c17cb6 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "util/u_inlines.h"
 #include "util/u_prim.h"
+#include "util/u_upload_mgr.h"
 #include "indices/u_indices.h"
 
 #include "svga_cmd.h"
@@ -45,7 +46,7 @@ translate_indices(struct svga_hwtnl *hwtnl, struct pipe_resource *src,
    struct pipe_context *pipe = &hwtnl->svga->pipe;
    struct pipe_transfer *src_transfer = NULL;
    struct pipe_transfer *dst_transfer = NULL;
-   unsigned size;
+   unsigned size = index_size * nr;
    const void *src_map = NULL;
    struct pipe_resource *dst = NULL;
    void *dst_map = NULL;
@@ -98,7 +99,9 @@ svga_hwtnl_simple_draw_range_elements(struct svga_hwtnl *hwtnl,
                                       unsigned index_size, int index_bias,
                                       unsigned min_index, unsigned max_index,
                                       unsigned prim, unsigned start,
-                                      unsigned count)
+                                      unsigned count,
+                                      unsigned start_instance,
+                                      unsigned instance_count)
 {
    SVGA3dPrimitiveRange range;
    unsigned hw_prim;
@@ -109,12 +112,6 @@ svga_hwtnl_simple_draw_range_elements(struct svga_hwtnl *hwtnl,
    if (hw_count == 0)
       return PIPE_OK; /* nothing to draw */
 
-   /* We should never see user-space buffers in the driver.  The vbuf
-    * module should have converted them into real buffers.
-    */
-   if (index_buffer)
-      assert(!svga_buffer_is_user_buffer(index_buffer));
-
    range.primType = hw_prim;
    range.primitiveCount = hw_count;
    range.indexArray.offset = index_offset;
@@ -122,7 +119,9 @@ svga_hwtnl_simple_draw_range_elements(struct svga_hwtnl *hwtnl,
    range.indexWidth = index_size;
    range.indexBias = index_bias;
 
-   return svga_hwtnl_prim(hwtnl, &range, min_index, max_index, index_buffer);
+   return svga_hwtnl_prim(hwtnl, &range, count,
+                          min_index, max_index, index_buffer,
+                          start_instance, instance_count);
 }
 
 
@@ -131,7 +130,8 @@ svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl,
                                struct pipe_resource *index_buffer,
                                unsigned index_size, int index_bias,
                                unsigned min_index, unsigned max_index,
-                               unsigned prim, unsigned start, unsigned count)
+                               unsigned prim, unsigned start, unsigned count,
+                               unsigned start_instance, unsigned instance_count)
 {
    unsigned gen_prim, gen_size, gen_nr, gen_type;
    u_translate_func gen_func;
@@ -165,7 +165,9 @@ svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl,
                                                    index_bias,
                                                    min_index,
                                                    max_index,
-                                                   gen_prim, start, count);
+                                                   gen_prim, start, count,
+                                                   start_instance,
+                                                   instance_count);
    }
    else {
       struct pipe_resource *gen_buf = NULL;
@@ -190,7 +192,9 @@ svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl,
                                                   index_bias,
                                                   min_index,
                                                   max_index,
-                                                  gen_prim, 0, gen_nr);
+                                                  gen_prim, 0, gen_nr,
+                                                  start_instance,
+                                                  instance_count);
       if (ret != PIPE_OK)
          goto done;
 
index 9ab87e8259adb1914f5d60051f17571c7bcbcbdd..c8217422c96a2445f752ccd53bc701f306b5e1cc 100644 (file)
@@ -46,7 +46,11 @@ static const unsigned svga_hw_prims =
     (1 << PIPE_PRIM_LINE_STRIP) |
     (1 << PIPE_PRIM_TRIANGLES) |
     (1 << PIPE_PRIM_TRIANGLE_STRIP) |
-    (1 << PIPE_PRIM_TRIANGLE_FAN));
+    (1 << PIPE_PRIM_TRIANGLE_FAN) |
+    (1 << PIPE_PRIM_LINES_ADJACENCY) |
+    (1 << PIPE_PRIM_LINE_STRIP_ADJACENCY) |
+    (1 << PIPE_PRIM_TRIANGLES_ADJACENCY) |
+    (1 << PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY));
 
 
 /**
@@ -57,8 +61,8 @@ static const unsigned svga_hw_prims =
  * PIPE_PRIM_QUADS, PIPE_PRIM_QUAD_STRIP or PIPE_PRIM_POLYGON.  We convert
  * those to other types of primitives with index/translation code.
  */
-static inline unsigned
-svga_translate_prim(unsigned mode, unsigned vcount,unsigned *prim_count)
+static inline SVGA3dPrimitiveType
+svga_translate_prim(unsigned mode, unsigned vcount, unsigned *prim_count)
 {
    switch (mode) {
    case PIPE_PRIM_POINTS:
@@ -85,6 +89,22 @@ svga_translate_prim(unsigned mode, unsigned vcount,unsigned *prim_count)
       *prim_count = vcount - 2;
       return SVGA3D_PRIMITIVE_TRIANGLEFAN; 
 
+   case PIPE_PRIM_LINES_ADJACENCY:
+      *prim_count = vcount / 4;
+      return SVGA3D_PRIMITIVE_LINELIST_ADJ;
+
+   case PIPE_PRIM_LINE_STRIP_ADJACENCY:
+      *prim_count = vcount - 3;
+      return SVGA3D_PRIMITIVE_LINESTRIP_ADJ;
+
+   case PIPE_PRIM_TRIANGLES_ADJACENCY:
+      *prim_count = vcount / 6;
+      return SVGA3D_PRIMITIVE_TRIANGLELIST_ADJ;
+
+   case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
+      *prim_count = vcount / 2 - 2 ;
+      return SVGA3D_PRIMITIVE_TRIANGLESTRIP_ADJ;
+
    default:
       assert(0);
       *prim_count = 0;
@@ -110,13 +130,19 @@ struct index_cache {
 struct draw_cmd {
    struct svga_winsys_context *swc;
 
+   /* vertex layout info */
    SVGA3dVertexDecl vdecl[SVGA3D_INPUTREG_MAX];
-   struct pipe_resource *vdecl_vb[SVGA3D_INPUTREG_MAX];
    unsigned vdecl_count;
+   SVGA3dElementLayoutId vdecl_layout_id;
+   unsigned vdecl_buffer_index[SVGA3D_INPUTREG_MAX];
+
+   /* vertex buffer info */
+   struct pipe_vertex_buffer vbufs[SVGA3D_INPUTREG_MAX];
+   unsigned vbuf_count;
 
    SVGA3dPrimitiveRange prim[QSZ];
    struct pipe_resource *prim_ib[QSZ];
-   unsigned prim_count;
+   unsigned prim_count;   /**< number of primitives for this draw */
    unsigned min_index[QSZ];
    unsigned max_index[QSZ];
 };
@@ -158,9 +184,11 @@ struct svga_hwtnl {
 enum pipe_error 
 svga_hwtnl_prim( struct svga_hwtnl *hwtnl,
                  const SVGA3dPrimitiveRange *range,
+                 unsigned vcount,
                  unsigned min_index,
                  unsigned max_index,
-                 struct pipe_resource *ib );
+                 struct pipe_resource *ib,
+                 unsigned start_instance, unsigned instance_count);
 
 enum pipe_error
 svga_hwtnl_simple_draw_range_elements( struct svga_hwtnl *hwtnl,
@@ -171,7 +199,9 @@ svga_hwtnl_simple_draw_range_elements( struct svga_hwtnl *hwtnl,
                                        unsigned max_index,
                                        unsigned prim, 
                                        unsigned start,
-                                       unsigned count );
+                                       unsigned count,
+                                       unsigned start_instance,
+                                       unsigned instance_count);
 
 
 #endif
index 8c1b161e6faa91f65d0f8a5f354f4829eaa5e6f7..67f6e51fce6ab4c74c7aa651128c2fc69b730b74 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "pipe/p_format.h"
 #include "util/u_debug.h"
+#include "util/u_format.h"
 #include "util/u_memory.h"
 
 #include "svga_winsys.h"
 #include "svga_format.h"
 
 
+/** Describes mapping from gallium formats to SVGA vertex/pixel formats */
+struct vgpu10_format_entry
+{
+   enum pipe_format pformat;
+   SVGA3dSurfaceFormat vertex_format;
+   SVGA3dSurfaceFormat pixel_format;
+   unsigned flags;
+};
+
+
+static const struct vgpu10_format_entry format_conversion_table[] =
+{
+   /* Gallium format                    SVGA3D vertex format        SVGA3D pixel format          Flags */
+   { PIPE_FORMAT_NONE,                  SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_B8G8R8A8_UNORM,        SVGA3D_B8G8R8A8_UNORM,      SVGA3D_B8G8R8A8_UNORM,       0 },
+   { PIPE_FORMAT_B8G8R8X8_UNORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_B8G8R8X8_UNORM,       0 },
+   { PIPE_FORMAT_A8R8G8B8_UNORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_X8R8G8B8_UNORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_B5G5R5A1_UNORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_B5G5R5A1_UNORM,       0 },
+   { PIPE_FORMAT_B4G4R4A4_UNORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_A4R4G4B4,             0 },
+   { PIPE_FORMAT_B5G6R5_UNORM,          SVGA3D_FORMAT_INVALID,      SVGA3D_B5G6R5_UNORM,         0 },
+   { PIPE_FORMAT_R10G10B10A2_UNORM,     SVGA3D_R10G10B10A2_UNORM,   SVGA3D_R10G10B10A2_UNORM,    0 },
+   { PIPE_FORMAT_L8_UNORM,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A8_UNORM,              SVGA3D_FORMAT_INVALID,      SVGA3D_A8_UNORM,             0 },
+   { PIPE_FORMAT_I8_UNORM,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L8A8_UNORM,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L16_UNORM,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_UYVY,                  SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_YUYV,                  SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_Z16_UNORM,             SVGA3D_FORMAT_INVALID,      SVGA3D_Z_D16,                0 },
+   { PIPE_FORMAT_Z32_UNORM,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_Z32_FLOAT,             SVGA3D_FORMAT_INVALID,      SVGA3D_D32_FLOAT,            0 },
+   { PIPE_FORMAT_Z24_UNORM_S8_UINT,     SVGA3D_FORMAT_INVALID,      SVGA3D_D24_UNORM_S8_UINT,    0 },
+   { PIPE_FORMAT_S8_UINT_Z24_UNORM,     SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_Z24X8_UNORM,           SVGA3D_FORMAT_INVALID,      SVGA3D_D24_UNORM_S8_UINT,    0 },
+   { PIPE_FORMAT_X8Z24_UNORM,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_S8_UINT,               SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R64_FLOAT,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R64G64_FLOAT,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R64G64B64_FLOAT,       SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R64G64B64A64_FLOAT,    SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32_FLOAT,             SVGA3D_R32_FLOAT,           SVGA3D_R32_FLOAT,            0 },
+   { PIPE_FORMAT_R32G32_FLOAT,          SVGA3D_R32G32_FLOAT,        SVGA3D_R32G32_FLOAT,         0 },
+   { PIPE_FORMAT_R32G32B32_FLOAT,       SVGA3D_R32G32B32_FLOAT,     SVGA3D_R32G32B32_FLOAT,      0 },
+   { PIPE_FORMAT_R32G32B32A32_FLOAT,    SVGA3D_R32G32B32A32_FLOAT,  SVGA3D_R32G32B32A32_FLOAT,   0 },
+   { PIPE_FORMAT_R32_UNORM,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32G32_UNORM,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32G32B32_UNORM,       SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32G32B32A32_UNORM,    SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32_USCALED,           SVGA3D_R32_UINT,            SVGA3D_FORMAT_INVALID,       VF_U_TO_F_CAST },
+   { PIPE_FORMAT_R32G32_USCALED,        SVGA3D_R32G32_UINT,         SVGA3D_FORMAT_INVALID,       VF_U_TO_F_CAST },
+   { PIPE_FORMAT_R32G32B32_USCALED,     SVGA3D_R32G32B32_UINT,      SVGA3D_FORMAT_INVALID,       VF_U_TO_F_CAST },
+   { PIPE_FORMAT_R32G32B32A32_USCALED,  SVGA3D_R32G32B32A32_UINT,   SVGA3D_FORMAT_INVALID,       VF_U_TO_F_CAST },
+   { PIPE_FORMAT_R32_SNORM,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32G32_SNORM,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32G32B32_SNORM,       SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32G32B32A32_SNORM,    SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32_SSCALED,           SVGA3D_R32_SINT,            SVGA3D_FORMAT_INVALID,       VF_I_TO_F_CAST },
+   { PIPE_FORMAT_R32G32_SSCALED,        SVGA3D_R32G32_SINT,         SVGA3D_FORMAT_INVALID,       VF_I_TO_F_CAST },
+   { PIPE_FORMAT_R32G32B32_SSCALED,     SVGA3D_R32G32B32_SINT,      SVGA3D_FORMAT_INVALID,       VF_I_TO_F_CAST },
+   { PIPE_FORMAT_R32G32B32A32_SSCALED,  SVGA3D_R32G32B32A32_SINT,   SVGA3D_FORMAT_INVALID,       VF_I_TO_F_CAST },
+   { PIPE_FORMAT_R16_UNORM,             SVGA3D_R16_UNORM,           SVGA3D_R16_UNORM,            0 },
+   { PIPE_FORMAT_R16G16_UNORM,          SVGA3D_R16G16_UNORM,        SVGA3D_R16G16_UNORM,         0 },
+   { PIPE_FORMAT_R16G16B16_UNORM,       SVGA3D_R16G16B16A16_UNORM,  SVGA3D_FORMAT_INVALID,       VF_W_TO_1 },
+   { PIPE_FORMAT_R16G16B16A16_UNORM,    SVGA3D_R16G16B16A16_UNORM,  SVGA3D_R16G16B16A16_UNORM,   0 },
+   { PIPE_FORMAT_R16_USCALED,           SVGA3D_R16_UINT,            SVGA3D_FORMAT_INVALID,       VF_U_TO_F_CAST },
+   { PIPE_FORMAT_R16G16_USCALED,        SVGA3D_R16G16_UINT,         SVGA3D_FORMAT_INVALID,       VF_U_TO_F_CAST },
+   { PIPE_FORMAT_R16G16B16_USCALED,     SVGA3D_R16G16B16A16_UINT,   SVGA3D_FORMAT_INVALID,       VF_W_TO_1 | VF_U_TO_F_CAST },
+   { PIPE_FORMAT_R16G16B16A16_USCALED,  SVGA3D_R16G16B16A16_UINT,   SVGA3D_FORMAT_INVALID,       VF_U_TO_F_CAST },
+   { PIPE_FORMAT_R16_SNORM,             SVGA3D_R16_SNORM,           SVGA3D_R16_SNORM,            0 },
+   { PIPE_FORMAT_R16G16_SNORM,          SVGA3D_R16G16_SNORM,        SVGA3D_R16G16_SNORM,         0 },
+   { PIPE_FORMAT_R16G16B16_SNORM,       SVGA3D_R16G16B16A16_SNORM,  SVGA3D_FORMAT_INVALID,       VF_W_TO_1 },
+   { PIPE_FORMAT_R16G16B16A16_SNORM,    SVGA3D_R16G16B16A16_SNORM,  SVGA3D_R16G16B16A16_SNORM,   0 },
+   { PIPE_FORMAT_R16_SSCALED,           SVGA3D_R16_SINT,            SVGA3D_FORMAT_INVALID,       VF_I_TO_F_CAST },
+   { PIPE_FORMAT_R16G16_SSCALED,        SVGA3D_R16G16_SINT,         SVGA3D_FORMAT_INVALID,       VF_I_TO_F_CAST },
+   { PIPE_FORMAT_R16G16B16_SSCALED,     SVGA3D_R16G16B16A16_SINT,   SVGA3D_FORMAT_INVALID,       VF_W_TO_1 | VF_I_TO_F_CAST },
+   { PIPE_FORMAT_R16G16B16A16_SSCALED,  SVGA3D_R16G16B16A16_SINT,   SVGA3D_FORMAT_INVALID,       VF_I_TO_F_CAST },
+   { PIPE_FORMAT_R8_UNORM,              SVGA3D_R8_UNORM,            SVGA3D_R8_UNORM,             0 },
+   { PIPE_FORMAT_R8G8_UNORM,            SVGA3D_R8G8_UNORM,          SVGA3D_R8G8_UNORM,           0 },
+   { PIPE_FORMAT_R8G8B8_UNORM,          SVGA3D_R8G8B8A8_UNORM,      SVGA3D_FORMAT_INVALID,       VF_W_TO_1 },
+   { PIPE_FORMAT_R8G8B8A8_UNORM,        SVGA3D_R8G8B8A8_UNORM,      SVGA3D_R8G8B8A8_UNORM,       0 },
+   { PIPE_FORMAT_X8B8G8R8_UNORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8_USCALED,            SVGA3D_R8_UINT,             SVGA3D_FORMAT_INVALID,       VF_U_TO_F_CAST },
+   { PIPE_FORMAT_R8G8_USCALED,          SVGA3D_R8G8_UINT,           SVGA3D_FORMAT_INVALID,       VF_U_TO_F_CAST },
+   { PIPE_FORMAT_R8G8B8_USCALED,        SVGA3D_R8G8B8A8_UINT,       SVGA3D_FORMAT_INVALID,       VF_W_TO_1 | VF_U_TO_F_CAST },
+   { PIPE_FORMAT_R8G8B8A8_USCALED,      SVGA3D_R8G8B8A8_UINT,       SVGA3D_FORMAT_INVALID,       VF_U_TO_F_CAST },
+   { 73,                                SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8_SNORM,              SVGA3D_R8_SNORM,            SVGA3D_R8_SNORM,             0 },
+   { PIPE_FORMAT_R8G8_SNORM,            SVGA3D_R8G8_SNORM,          SVGA3D_R8G8_SNORM,           0 },
+   { PIPE_FORMAT_R8G8B8_SNORM,          SVGA3D_R8G8B8A8_SNORM,      SVGA3D_FORMAT_INVALID,       VF_W_TO_1 },
+   { PIPE_FORMAT_R8G8B8A8_SNORM,        SVGA3D_R8G8B8A8_SNORM,      SVGA3D_R8G8B8A8_SNORM,       0 },
+   { 78,                                SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { 79,                                SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { 80,                                SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { 81,                                SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8_SSCALED,            SVGA3D_R8_SINT,             SVGA3D_FORMAT_INVALID,       VF_I_TO_F_CAST },
+   { PIPE_FORMAT_R8G8_SSCALED,          SVGA3D_R8G8_SINT,           SVGA3D_FORMAT_INVALID,       VF_I_TO_F_CAST },
+   { PIPE_FORMAT_R8G8B8_SSCALED,        SVGA3D_R8G8B8A8_SINT,       SVGA3D_FORMAT_INVALID,       VF_W_TO_1 | VF_I_TO_F_CAST },
+   { PIPE_FORMAT_R8G8B8A8_SSCALED,      SVGA3D_R8G8B8A8_SINT,       SVGA3D_FORMAT_INVALID,       VF_I_TO_F_CAST },
+   { 86,                                SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32_FIXED,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32G32_FIXED,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32G32B32_FIXED,       SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32G32B32A32_FIXED,    SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R16_FLOAT,             SVGA3D_R16_FLOAT,           SVGA3D_R16_FLOAT,            0 },
+   { PIPE_FORMAT_R16G16_FLOAT,          SVGA3D_R16G16_FLOAT,        SVGA3D_R16G16_FLOAT,         0 },
+   { PIPE_FORMAT_R16G16B16_FLOAT,       SVGA3D_R16G16B16A16_FLOAT,  SVGA3D_FORMAT_INVALID,       VF_W_TO_1 },
+   { PIPE_FORMAT_R16G16B16A16_FLOAT,    SVGA3D_R16G16B16A16_FLOAT,  SVGA3D_R16G16B16A16_FLOAT,   0 },
+   { PIPE_FORMAT_L8_SRGB,               SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L8A8_SRGB,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8G8B8_SRGB,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A8B8G8R8_SRGB,         SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_X8B8G8R8_SRGB,         SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_B8G8R8A8_SRGB,         SVGA3D_FORMAT_INVALID,      SVGA3D_B8G8R8A8_UNORM_SRGB,  0 },
+   { PIPE_FORMAT_B8G8R8X8_SRGB,         SVGA3D_FORMAT_INVALID,      SVGA3D_B8G8R8X8_UNORM_SRGB,  0 },
+   { PIPE_FORMAT_A8R8G8B8_SRGB,         SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_X8R8G8B8_SRGB,         SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8G8B8A8_SRGB,         SVGA3D_FORMAT_INVALID,      SVGA3D_R8G8B8A8_UNORM_SRGB,  0 },
+   { PIPE_FORMAT_DXT1_RGB,              SVGA3D_FORMAT_INVALID,      SVGA3D_DXT1,                 0 },
+   { PIPE_FORMAT_DXT1_RGBA,             SVGA3D_FORMAT_INVALID,      SVGA3D_DXT1,                 0 },
+   { PIPE_FORMAT_DXT3_RGBA,             SVGA3D_FORMAT_INVALID,      SVGA3D_DXT3,                 0 },
+   { PIPE_FORMAT_DXT5_RGBA,             SVGA3D_FORMAT_INVALID,      SVGA3D_DXT5,                 0 },
+   { PIPE_FORMAT_DXT1_SRGB,             SVGA3D_FORMAT_INVALID,      SVGA3D_DXT1,                 0 },
+   { PIPE_FORMAT_DXT1_SRGBA,            SVGA3D_FORMAT_INVALID,      SVGA3D_DXT1,                 0 },
+   { PIPE_FORMAT_DXT3_SRGBA,            SVGA3D_FORMAT_INVALID,      SVGA3D_DXT3,                 0 },
+   { PIPE_FORMAT_DXT5_SRGBA,            SVGA3D_FORMAT_INVALID,      SVGA3D_DXT5,                 0 },
+   { PIPE_FORMAT_RGTC1_UNORM,           SVGA3D_FORMAT_INVALID,      SVGA3D_BC4_UNORM,            0 },
+   { PIPE_FORMAT_RGTC1_SNORM,           SVGA3D_FORMAT_INVALID,      SVGA3D_BC4_SNORM,            0 },
+   { PIPE_FORMAT_RGTC2_UNORM,           SVGA3D_FORMAT_INVALID,      SVGA3D_BC5_UNORM,            0 },
+   { PIPE_FORMAT_RGTC2_SNORM,           SVGA3D_FORMAT_INVALID,      SVGA3D_BC5_SNORM,            0 },
+   { PIPE_FORMAT_R8G8_B8G8_UNORM,       SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_G8R8_G8B8_UNORM,       SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8SG8SB8UX8U_NORM,     SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R5SG5SB6U_NORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A8B8G8R8_UNORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_B5G5R5X1_UNORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R10G10B10A2_USCALED,   SVGA3D_R10G10B10A2_UNORM,   SVGA3D_FORMAT_INVALID,       VF_PUINT_TO_USCALED },
+   { PIPE_FORMAT_R11G11B10_FLOAT,       SVGA3D_FORMAT_INVALID,      SVGA3D_R11G11B10_FLOAT,      0 },
+   { PIPE_FORMAT_R9G9B9E5_FLOAT,        SVGA3D_FORMAT_INVALID,      SVGA3D_R9G9B9E5_SHAREDEXP,   0 },
+   { PIPE_FORMAT_Z32_FLOAT_S8X24_UINT,  SVGA3D_FORMAT_INVALID,      SVGA3D_D32_FLOAT_S8X24_UINT, 0 },
+   { PIPE_FORMAT_R1_UNORM,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R10G10B10X2_USCALED,   SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R10G10B10X2_SNORM,     SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L4A4_UNORM,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_B10G10R10A2_UNORM,     SVGA3D_R10G10B10A2_UNORM,   SVGA3D_FORMAT_INVALID,       VF_BGRA },
+   { PIPE_FORMAT_R10SG10SB10SA2U_NORM,  SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8G8Bx_SNORM,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8G8B8X8_UNORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_B4G4R4X4_UNORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_X24S8_UINT,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_S8X24_UINT,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_X32_S8X24_UINT,        SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_B2G3R3_UNORM,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L16A16_UNORM,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A16_UNORM,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_I16_UNORM,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_LATC1_UNORM,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_LATC1_SNORM,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_LATC2_UNORM,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_LATC2_SNORM,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A8_SNORM,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L8_SNORM,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L8A8_SNORM,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_I8_SNORM,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A16_SNORM,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L16_SNORM,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L16A16_SNORM,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_I16_SNORM,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A16_FLOAT,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L16_FLOAT,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L16A16_FLOAT,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_I16_FLOAT,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A32_FLOAT,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L32_FLOAT,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L32A32_FLOAT,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_I32_FLOAT,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_YV12,                  SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_YV16,                  SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_IYUV,                  SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_NV12,                  SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_NV21,                  SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A4R4_UNORM,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R4A4_UNORM,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8A8_UNORM,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A8R8_UNORM,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R10G10B10A2_SSCALED,   SVGA3D_R32_UINT,            SVGA3D_FORMAT_INVALID,       VF_PUINT_TO_SSCALED },
+   { PIPE_FORMAT_R10G10B10A2_SNORM,     SVGA3D_R10G10B10A2_UNORM,   SVGA3D_FORMAT_INVALID,       VF_PUINT_TO_SNORM },
+   { PIPE_FORMAT_B10G10R10A2_USCALED,   SVGA3D_R10G10B10A2_UNORM,   SVGA3D_FORMAT_INVALID,       VF_BGRA | VF_PUINT_TO_USCALED },
+   { PIPE_FORMAT_B10G10R10A2_SSCALED,   SVGA3D_R32_UINT,            SVGA3D_FORMAT_INVALID,       VF_BGRA | VF_PUINT_TO_SSCALED },
+   { PIPE_FORMAT_B10G10R10A2_SNORM,     SVGA3D_R10G10B10A2_UNORM,   SVGA3D_FORMAT_INVALID,       VF_BGRA | VF_PUINT_TO_SNORM },
+   { PIPE_FORMAT_R8_UINT,               SVGA3D_R8_UINT,             SVGA3D_R8_UINT,              0 },
+   { PIPE_FORMAT_R8G8_UINT,             SVGA3D_R8G8_UINT,           SVGA3D_R8G8_UINT,            0 },
+   { PIPE_FORMAT_R8G8B8_UINT,           SVGA3D_R8G8B8A8_UINT,       SVGA3D_FORMAT_INVALID,       VF_W_TO_1 },
+   { PIPE_FORMAT_R8G8B8A8_UINT,         SVGA3D_R8G8B8A8_UINT,       SVGA3D_R8G8B8A8_UINT,        0 },
+   { PIPE_FORMAT_R8_SINT,               SVGA3D_R8_SINT,             SVGA3D_R8_SINT,              0 },
+   { PIPE_FORMAT_R8G8_SINT,             SVGA3D_R8G8_SINT,           SVGA3D_R8G8_SINT,            0 },
+   { PIPE_FORMAT_R8G8B8_SINT,           SVGA3D_R8G8B8A8_SINT,       SVGA3D_FORMAT_INVALID,       VF_W_TO_1 },
+   { PIPE_FORMAT_R8G8B8A8_SINT,         SVGA3D_R8G8B8A8_SINT,       SVGA3D_R8G8B8A8_SINT,        0 },
+   { PIPE_FORMAT_R16_UINT,              SVGA3D_R16_UINT,            SVGA3D_R16_UINT,             0 },
+   { PIPE_FORMAT_R16G16_UINT,           SVGA3D_R16G16_UINT,         SVGA3D_R16G16_UINT,          0 },
+   { PIPE_FORMAT_R16G16B16_UINT,        SVGA3D_R16G16B16A16_UINT,   SVGA3D_FORMAT_INVALID,       VF_W_TO_1 },
+   { PIPE_FORMAT_R16G16B16A16_UINT,     SVGA3D_R16G16B16A16_UINT,   SVGA3D_R16G16B16A16_UINT,    0 },
+   { PIPE_FORMAT_R16_SINT,              SVGA3D_R16_SINT,            SVGA3D_R16_SINT,             0 },
+   { PIPE_FORMAT_R16G16_SINT,           SVGA3D_R16G16_SINT,         SVGA3D_R16G16_SINT,          0 },
+   { PIPE_FORMAT_R16G16B16_SINT,        SVGA3D_R16G16B16A16_SINT,   SVGA3D_FORMAT_INVALID,       VF_W_TO_1 },
+   { PIPE_FORMAT_R16G16B16A16_SINT,     SVGA3D_R16G16B16A16_SINT,   SVGA3D_R16G16B16A16_SINT,    0 },
+   { PIPE_FORMAT_R32_UINT,              SVGA3D_R32_UINT,            SVGA3D_R32_UINT,             0 },
+   { PIPE_FORMAT_R32G32_UINT,           SVGA3D_R32G32_UINT,         SVGA3D_R32G32_UINT,          0 },
+   { PIPE_FORMAT_R32G32B32_UINT,        SVGA3D_R32G32B32_UINT,      SVGA3D_R32G32B32_UINT,       0 },
+   { PIPE_FORMAT_R32G32B32A32_UINT,     SVGA3D_R32G32B32A32_UINT,   SVGA3D_R32G32B32A32_UINT,    0 },
+   { PIPE_FORMAT_R32_SINT,              SVGA3D_R32_SINT,            SVGA3D_R32_SINT,             0 },
+   { PIPE_FORMAT_R32G32_SINT,           SVGA3D_R32G32_SINT,         SVGA3D_R32G32_SINT,          0 },
+   { PIPE_FORMAT_R32G32B32_SINT,        SVGA3D_R32G32B32_SINT,      SVGA3D_R32G32B32_SINT,       0 },
+   { PIPE_FORMAT_R32G32B32A32_SINT,     SVGA3D_R32G32B32A32_SINT,   SVGA3D_R32G32B32A32_SINT,    0 },
+   { PIPE_FORMAT_A8_UINT,               SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_I8_UINT,               SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L8_UINT,               SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L8A8_UINT,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A8_SINT,               SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_I8_SINT,               SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L8_SINT,               SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L8A8_SINT,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A16_UINT,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_I16_UINT,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L16_UINT,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L16A16_UINT,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A16_SINT,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_I16_SINT,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L16_SINT,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L16A16_SINT,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A32_UINT,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_I32_UINT,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L32_UINT,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L32A32_UINT,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A32_SINT,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_I32_SINT,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L32_SINT,              SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_L32A32_SINT,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_B10G10R10A2_UINT,      SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_ETC1_RGB8,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8G8_R8B8_UNORM,       SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_G8R8_B8R8_UNORM,       SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8G8B8X8_SNORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8G8B8X8_SRGB,         SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8G8B8X8_UINT,         SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8G8B8X8_SINT,         SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_B10G10R10X2_UNORM,     SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R16G16B16X16_UNORM,    SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R16G16B16X16_SNORM,    SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R16G16B16X16_FLOAT,    SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R16G16B16X16_UINT,     SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R16G16B16X16_SINT,     SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32G32B32X32_FLOAT,    SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32G32B32X32_UINT,     SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32G32B32X32_SINT,     SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8A8_SNORM,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R16A16_UNORM,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R16A16_SNORM,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R16A16_FLOAT,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32A32_FLOAT,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8A8_UINT,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R8A8_SINT,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R16A16_UINT,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R16A16_SINT,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32A32_UINT,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R32A32_SINT,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_R10G10B10A2_UINT,      SVGA3D_R10G10B10A2_UINT,    SVGA3D_R10G10B10A2_UINT,     0 },
+   { PIPE_FORMAT_B5G6R5_SRGB,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_BPTC_RGBA_UNORM,       SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_BPTC_SRGBA,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_BPTC_RGB_FLOAT,        SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_BPTC_RGB_UFLOAT,       SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A8L8_UNORM,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A8L8_SNORM,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A8L8_SRGB,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A16L16_UNORM,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_G8R8_UNORM,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_G8R8_SNORM,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_G16R16_UNORM,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_G16R16_SNORM,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_A8B8G8R8_SNORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_X8B8G8R8_SNORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_ETC2_RGB8,             SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_ETC2_SRGB8,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_ETC2_RGB8A1,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_ETC2_SRGB8A1,          SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_ETC2_RGBA8,            SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_ETC2_SRGBA8,           SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_ETC2_R11_UNORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_ETC2_R11_SNORM,        SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_ETC2_RG11_UNORM,       SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+   { PIPE_FORMAT_ETC2_RG11_SNORM,       SVGA3D_FORMAT_INVALID,      SVGA3D_FORMAT_INVALID,       0 },
+};
+
+
+/**
+ * Translate a gallium vertex format to a vgpu10 vertex format.
+ * Also, return any special vertex format flags.
+ */
+void
+svga_translate_vertex_format_vgpu10(enum pipe_format format,
+                                    SVGA3dSurfaceFormat *svga_format,
+                                    unsigned *vf_flags)
+{
+   assert(format < Elements(format_conversion_table));
+   if (format >= Elements(format_conversion_table)) {
+      format = PIPE_FORMAT_NONE;
+   }
+   *svga_format = format_conversion_table[format].vertex_format;
+   *vf_flags = format_conversion_table[format].flags;
+}
+
+
 /*
  * Translate from gallium format to SVGA3D format.
  */
@@ -41,8 +355,16 @@ svga_translate_format(struct svga_screen *ss,
                       enum pipe_format format,
                       unsigned bind)
 {
-   switch(format) {
+   if (ss->sws->have_vgpu10) {
+      if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) {
+         return format_conversion_table[format].vertex_format;
+      }
+      else {
+         return format_conversion_table[format].pixel_format;
+      }
+   }
 
+   switch(format) {
    case PIPE_FORMAT_B8G8R8A8_UNORM:
       return SVGA3D_A8R8G8B8;
    case PIPE_FORMAT_B8G8R8X8_UNORM:
@@ -70,10 +392,13 @@ svga_translate_format(struct svga_screen *ss,
       return SVGA3D_A16B16G16R16;
 
    case PIPE_FORMAT_Z16_UNORM:
+      assert(!ss->sws->have_vgpu10);
       return bind & PIPE_BIND_SAMPLER_VIEW ? ss->depth.z16 : SVGA3D_Z_D16;
    case PIPE_FORMAT_S8_UINT_Z24_UNORM:
+      assert(!ss->sws->have_vgpu10);
       return bind & PIPE_BIND_SAMPLER_VIEW ? ss->depth.s8z24 : SVGA3D_Z_D24S8;
    case PIPE_FORMAT_X8Z24_UNORM:
+      assert(!ss->sws->have_vgpu10);
       return bind & PIPE_BIND_SAMPLER_VIEW ? ss->depth.x8z24 : SVGA3D_Z_D24X8;
 
    case PIPE_FORMAT_A8_UNORM:
@@ -116,12 +441,17 @@ svga_translate_format(struct svga_screen *ss,
  * Format capability description entry.
  */
 struct format_cap {
+   const char *name;
+
    SVGA3dSurfaceFormat format;
 
    /*
     * Capability index corresponding to the format.
     */
-   SVGA3dDevCapIndex index;
+   SVGA3dDevCapIndex devcap;
+
+   /* size of each pixel/block */
+   unsigned block_width, block_height, block_bytes;
 
    /*
     * Mask of supported SVGA3dFormatOp operations, to be inferred when the
@@ -134,598 +464,1637 @@ struct format_cap {
 /*
  * Format capability description table.
  *
- * Ordererd by increasing SVGA3dSurfaceFormat value, but with gaps.
+ * Ordered by increasing SVGA3dSurfaceFormat value, but with gaps.
+ *
+ * Note: there are some special cases below where we set devcap=0 and
+ * avoid querying the host.  In particular, depth/stencil formats which
+ * can be rendered to and sampled from.  For example, the gallium format
+ * PIPE_FORMAT_Z24_UNORM_S8_UINT is converted to SVGA3D_D24_UNORM_S8_UINT
+ * for rendering but converted to SVGA3D_R24_UNORM_X8_TYPELESS for sampling.
+ * If we want to query if a format supports both rendering and sampling the
+ * host will tell us no for both SVGA3D_D24_UNORM_S8_UINT and
+ * SVGA3D_R24_UNORM_X8_TYPELESS.  So we override the host query for those
+ * formats and report that both can do rendering and sampling.
  */
 static const struct format_cap format_cap_table[] = {
    {
+      "SVGA3D_FORMAT_INVALID",
+      SVGA3D_FORMAT_INVALID, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_X8R8G8B8",
       SVGA3D_X8R8G8B8,
       SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8,
+      1, 1, 4,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
       SVGA3DFORMAT_OP_VOLUMETEXTURE |
       SVGA3DFORMAT_OP_DISPLAYMODE |
-      SVGA3DFORMAT_OP_3DACCELERATION |
-      SVGA3DFORMAT_OP_CONVERT_TO_ARGB |
-      SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_SRGBWRITE |
-      SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET |
       SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
    {
+      "SVGA3D_A8R8G8B8",
       SVGA3D_A8R8G8B8,
       SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8,
+      1, 1, 4,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
       SVGA3DFORMAT_OP_VOLUMETEXTURE |
-      SVGA3DFORMAT_OP_CONVERT_TO_ARGB |
-      SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_SRGBWRITE |
-      SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET |
-      SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET |
       SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
    {
+      "SVGA3D_R5G6B5",
       SVGA3D_R5G6B5,
       SVGA3D_DEVCAP_SURFACEFMT_R5G6B5,
+      1, 1, 2,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
       SVGA3DFORMAT_OP_VOLUMETEXTURE |
       SVGA3DFORMAT_OP_DISPLAYMODE |
-      SVGA3DFORMAT_OP_3DACCELERATION |
-      SVGA3DFORMAT_OP_CONVERT_TO_ARGB |
-      SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_SRGBWRITE |
-      SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET |
       SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
    {
+      "SVGA3D_X1R5G5B5",
       SVGA3D_X1R5G5B5,
       SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5,
+      1, 1, 2,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
       SVGA3DFORMAT_OP_VOLUMETEXTURE |
-      SVGA3DFORMAT_OP_CONVERT_TO_ARGB |
-      SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_SRGBWRITE |
-      SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET |
       SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
    {
+      "SVGA3D_A1R5G5B5",
       SVGA3D_A1R5G5B5,
       SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5,
+      1, 1, 2,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
       SVGA3DFORMAT_OP_VOLUMETEXTURE |
-      SVGA3DFORMAT_OP_CONVERT_TO_ARGB |
-      SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_SRGBWRITE |
-      SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET |
-      SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET |
       SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
    {
+      "SVGA3D_A4R4G4B4",
       SVGA3D_A4R4G4B4,
       SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4,
+      1, 1, 2,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
       SVGA3DFORMAT_OP_VOLUMETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_SRGBWRITE |
-      SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET |
-      SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET |
       SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
-   /*
-    * SVGA3D_Z_D32 is not yet supported, and has no corresponding
-    * SVGA3D_DEVCAP_xxx.
-    */
    {
+      /*
+       * SVGA3D_Z_D32 is not yet supported, and has no corresponding
+       * SVGA3D_DEVCAP_xxx.
+       */
+      "SVGA3D_Z_D32",
+      SVGA3D_Z_D32, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_Z_D16",
       SVGA3D_Z_D16,
       SVGA3D_DEVCAP_SURFACEFMT_Z_D16,
-      SVGA3DFORMAT_OP_ZSTENCIL |
-      SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH
+      1, 1, 2,
+      SVGA3DFORMAT_OP_ZSTENCIL
    },
    {
+      "SVGA3D_Z_D24S8",
       SVGA3D_Z_D24S8,
       SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8,
-      SVGA3DFORMAT_OP_ZSTENCIL |
-      SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH
+      1, 1, 4,
+      SVGA3DFORMAT_OP_ZSTENCIL
    },
    {
+      "SVGA3D_Z_D15S1",
       SVGA3D_Z_D15S1,
       SVGA3D_DEVCAP_MAX,
-      SVGA3DFORMAT_OP_ZSTENCIL |
-      SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH
+      1, 1, 2,
+      SVGA3DFORMAT_OP_ZSTENCIL
    },
    {
+      "SVGA3D_LUMINANCE8",
       SVGA3D_LUMINANCE8,
       SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8,
+      1, 1, 1,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_VOLUMETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN
+      SVGA3DFORMAT_OP_VOLUMETEXTURE
    },
    {
-      SVGA3D_LUMINANCE8_ALPHA8,
-      SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8,
-      SVGA3DFORMAT_OP_TEXTURE |
-      SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_VOLUMETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN
+      /*
+       * SVGA3D_LUMINANCE4_ALPHA4 is not supported, and has no corresponding
+       * SVGA3D_DEVCAP_xxx.
+       */
+      "SVGA3D_LUMINANCE4_ALPHA4",
+      SVGA3D_LUMINANCE4_ALPHA4, 0, 0, 0, 0, 0
    },
-   /*
-    * SVGA3D_LUMINANCE4_ALPHA4 is not supported, and has no corresponding
-    * SVGA3D_DEVCAP_xxx.
-    */
    {
+      "SVGA3D_LUMINANCE16",
       SVGA3D_LUMINANCE16,
       SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16,
+      1, 1, 2,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_VOLUMETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN
+      SVGA3DFORMAT_OP_VOLUMETEXTURE
+   },
+   {
+      "SVGA3D_LUMINANCE8_ALPHA8",
+      SVGA3D_LUMINANCE8_ALPHA8,
+      SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8,
+      1, 1, 2,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE
    },
    {
+      "SVGA3D_DXT1",
       SVGA3D_DXT1,
       SVGA3D_DEVCAP_SURFACEFMT_DXT1,
+      4, 4, 8,
       SVGA3DFORMAT_OP_TEXTURE |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN
+      SVGA3DFORMAT_OP_CUBETEXTURE
    },
    {
+      "SVGA3D_DXT2",
       SVGA3D_DXT2,
       SVGA3D_DEVCAP_SURFACEFMT_DXT2,
+      4, 4, 8,
       SVGA3DFORMAT_OP_TEXTURE |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN
+      SVGA3DFORMAT_OP_CUBETEXTURE
    },
    {
+      "SVGA3D_DXT3",
       SVGA3D_DXT3,
       SVGA3D_DEVCAP_SURFACEFMT_DXT3,
+      4, 4, 16,
       SVGA3DFORMAT_OP_TEXTURE |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN
+      SVGA3DFORMAT_OP_CUBETEXTURE
    },
    {
+      "SVGA3D_DXT4",
       SVGA3D_DXT4,
       SVGA3D_DEVCAP_SURFACEFMT_DXT4,
+      4, 4, 16,
       SVGA3DFORMAT_OP_TEXTURE |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN
+      SVGA3DFORMAT_OP_CUBETEXTURE
    },
    {
+      "SVGA3D_DXT5",
       SVGA3D_DXT5,
       SVGA3D_DEVCAP_SURFACEFMT_DXT5,
+      4, 4, 8,
       SVGA3DFORMAT_OP_TEXTURE |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN
+      SVGA3DFORMAT_OP_CUBETEXTURE
    },
    {
+      "SVGA3D_BUMPU8V8",
       SVGA3D_BUMPU8V8,
       SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8,
+      1, 1, 2,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_VOLUMETEXTURE |
-      SVGA3DFORMAT_OP_BUMPMAP |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN
+      SVGA3DFORMAT_OP_VOLUMETEXTURE
    },
-   /*
-    * SVGA3D_BUMPL6V5U5 is unsupported; it has no corresponding
-    * SVGA3D_DEVCAP_xxx.
-    */
    {
+      /*
+       * SVGA3D_BUMPL6V5U5 is unsupported; it has no corresponding
+       * SVGA3D_DEVCAP_xxx.
+       */
+      "SVGA3D_BUMPL6V5U5",
+      SVGA3D_BUMPL6V5U5, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_BUMPX8L8V8U8",
       SVGA3D_BUMPX8L8V8U8,
       SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8,
+      1, 1, 4,
       SVGA3DFORMAT_OP_TEXTURE |
-      SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_BUMPMAP |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN
+      SVGA3DFORMAT_OP_CUBETEXTURE
+   },
+   {
+      "SVGA3D_FORMAT_DEAD1",
+      SVGA3D_FORMAT_DEAD1, 0, 0, 0, 0, 0
    },
-   /*
-    * SVGA3D_BUMPL8V8U8 is unsupported; it has no corresponding
-    * SVGA3D_DEVCAP_xxx. SVGA3D_BUMPX8L8V8U8 should be used instead.
-    */
    {
+      "SVGA3D_ARGB_S10E5",
       SVGA3D_ARGB_S10E5,
       SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5,
+      1, 1, 2,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
       SVGA3DFORMAT_OP_VOLUMETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_SRGBWRITE |
-      SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET |
       SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
    {
+      "SVGA3D_ARGB_S23E8",
       SVGA3D_ARGB_S23E8,
       SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8,
+      1, 1, 4,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
       SVGA3DFORMAT_OP_VOLUMETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_SRGBWRITE |
-      SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET |
       SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
    {
+      "SVGA3D_A2R10G10B10",
       SVGA3D_A2R10G10B10,
       SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10,
+      1, 1, 4,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
       SVGA3DFORMAT_OP_VOLUMETEXTURE |
-      SVGA3DFORMAT_OP_CONVERT_TO_ARGB |
-      SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_SRGBWRITE |
-      SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET |
       SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
-   /*
-    * SVGA3D_V8U8 is unsupported; it has no corresponding
-    * SVGA3D_DEVCAP_xxx. SVGA3D_BUMPU8V8 should be used instead.
-    */
    {
+      /*
+       * SVGA3D_V8U8 is unsupported; it has no corresponding
+       * SVGA3D_DEVCAP_xxx. SVGA3D_BUMPU8V8 should be used instead.
+       */
+      "SVGA3D_V8U8",
+      SVGA3D_V8U8, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_Q8W8V8U8",
       SVGA3D_Q8W8V8U8,
       SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8,
+      1, 1, 4,
       SVGA3DFORMAT_OP_TEXTURE |
-      SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_BUMPMAP |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN
+      SVGA3DFORMAT_OP_CUBETEXTURE
    },
    {
+      "SVGA3D_CxV8U8",
       SVGA3D_CxV8U8,
       SVGA3D_DEVCAP_SURFACEFMT_CxV8U8,
-      SVGA3DFORMAT_OP_TEXTURE |
-      SVGA3DFORMAT_OP_BUMPMAP |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN
+      1, 1, 2,
+      SVGA3DFORMAT_OP_TEXTURE
+   },
+   {
+      /*
+       * SVGA3D_X8L8V8U8 is unsupported; it has no corresponding
+       * SVGA3D_DEVCAP_xxx. SVGA3D_BUMPX8L8V8U8 should be used instead.
+       */
+      "SVGA3D_X8L8V8U8",
+      SVGA3D_X8L8V8U8, 0, 0, 0, 0, 0
    },
-   /*
-    * SVGA3D_X8L8V8U8 is unsupported; it has no corresponding
-    * SVGA3D_DEVCAP_xxx. SVGA3D_BUMPX8L8V8U8 should be used instead.
-    */
    {
+      "SVGA3D_A2W10V10U10",
       SVGA3D_A2W10V10U10,
       SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10,
-      SVGA3DFORMAT_OP_TEXTURE |
-      SVGA3DFORMAT_OP_BUMPMAP |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE
    },
    {
+      "SVGA3D_ALPHA8",
       SVGA3D_ALPHA8,
       SVGA3D_DEVCAP_SURFACEFMT_ALPHA8,
+      1, 1, 1,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_VOLUMETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN
+      SVGA3DFORMAT_OP_VOLUMETEXTURE
    },
    {
+      "SVGA3D_R_S10E5",
       SVGA3D_R_S10E5,
       SVGA3D_DEVCAP_SURFACEFMT_R_S10E5,
+      1, 1, 2,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_VOLUMETEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_SRGBWRITE |
-      SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET |
       SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
    {
+      "SVGA3D_R_S23E8",
       SVGA3D_R_S23E8,
       SVGA3D_DEVCAP_SURFACEFMT_R_S23E8,
+      1, 1, 4,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_VOLUMETEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_SRGBWRITE |
-      SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET |
       SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
    {
+      "SVGA3D_RG_S10E5",
       SVGA3D_RG_S10E5,
       SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5,
+      1, 1, 2,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_VOLUMETEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_SRGBWRITE |
-      SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET |
       SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
    {
+      "SVGA3D_RG_S23E8",
       SVGA3D_RG_S23E8,
       SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8,
+      1, 1, 4,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_VOLUMETEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN |
-      SVGA3DFORMAT_OP_SRGBREAD |
-      SVGA3DFORMAT_OP_SRGBWRITE |
-      SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET |
       SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
-   /*
-    * SVGA3D_BUFFER is a placeholder format for index/vertex buffers.
-    */
    {
+      /*
+       * SVGA3D_BUFFER is a placeholder format for index/vertex buffers.
+       */
+      "SVGA3D_BUFFER",
+      SVGA3D_BUFFER, 0, 1, 1, 1, 0
+   },
+   {
+      "SVGA3D_Z_D24X8",
       SVGA3D_Z_D24X8,
       SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8,
-      SVGA3DFORMAT_OP_ZSTENCIL |
-      SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH
+      1, 1, 4,
+      SVGA3DFORMAT_OP_ZSTENCIL
    },
    {
+      "SVGA3D_V16U16",
       SVGA3D_V16U16,
       SVGA3D_DEVCAP_SURFACEFMT_V16U16,
+      1, 1, 4,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
-      SVGA3DFORMAT_OP_VOLUMETEXTURE |
-      SVGA3DFORMAT_OP_BUMPMAP |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN
+      SVGA3DFORMAT_OP_VOLUMETEXTURE
    },
    {
+      "SVGA3D_G16R16",
       SVGA3D_G16R16,
       SVGA3D_DEVCAP_SURFACEFMT_G16R16,
+      1, 1, 4,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
       SVGA3DFORMAT_OP_VOLUMETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN |
-      SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET |
       SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
    {
+      "SVGA3D_A16B16G16R16",
       SVGA3D_A16B16G16R16,
       SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16,
+      1, 1, 8,
       SVGA3DFORMAT_OP_TEXTURE |
       SVGA3DFORMAT_OP_CUBETEXTURE |
       SVGA3DFORMAT_OP_VOLUMETEXTURE |
-      SVGA3DFORMAT_OP_OFFSCREENPLAIN |
-      SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET |
       SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
    {
+      "SVGA3D_UYVY",
       SVGA3D_UYVY,
       SVGA3D_DEVCAP_SURFACEFMT_UYVY,
+      0, 0, 0,
       0
    },
    {
+      "SVGA3D_YUY2",
       SVGA3D_YUY2,
       SVGA3D_DEVCAP_SURFACEFMT_YUY2,
+      0, 0, 0,
       0
    },
    {
+      "SVGA3D_NV12",
       SVGA3D_NV12,
       SVGA3D_DEVCAP_SURFACEFMT_NV12,
+      0, 0, 0,
       0
    },
    {
+      "SVGA3D_AYUV",
       SVGA3D_AYUV,
       SVGA3D_DEVCAP_SURFACEFMT_AYUV,
+      0, 0, 0,
       0
    },
    {
-      SVGA3D_Z_DF16,
-      SVGA3D_DEVCAP_SURFACEFMT_Z_DF16,
-      0
+      "SVGA3D_R32G32B32A32_TYPELESS",
+      SVGA3D_R32G32B32A32_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_R32G32B32A32_TYPELESS,
+      1, 1, 16,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
    {
-      SVGA3D_Z_DF24,
-      SVGA3D_DEVCAP_SURFACEFMT_Z_DF24,
-      0
+      "SVGA3D_R32G32B32A32_UINT",
+      SVGA3D_R32G32B32A32_UINT,
+      SVGA3D_DEVCAP_DXFMT_R32G32B32A32_UINT,
+      1, 1, 16,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
    {
-      SVGA3D_Z_D24S8_INT,
-      SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT,
-      0
+      "SVGA3D_R32G32B32A32_SINT",
+      SVGA3D_R32G32B32A32_SINT,
+      SVGA3D_DEVCAP_DXFMT_R32G32B32A32_SINT,
+      1, 1, 16,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
    },
-};
-
-
-/*
- * Get format capabilities from the host.  It takes in consideration
- * deprecated/unsupported formats, and formats which are implicitely assumed to
- * be supported when the host does not provide an explicit capability entry.
- */
-void
-svga_get_format_cap(struct svga_screen *ss,
-                    SVGA3dSurfaceFormat format,
-                    SVGA3dSurfaceFormatCaps *caps)
-{
-   const struct format_cap *entry;
-
-   for (entry = format_cap_table; entry < format_cap_table + Elements(format_cap_table); ++entry) {
-      if (entry->format == format) {
-         struct svga_winsys_screen *sws = ss->sws;
-         SVGA3dDevCapResult result;
-
-         if (sws->get_cap(sws, entry->index, &result)) {
-            /* Explicitly advertised format */
-            caps->value = result.u;
-         } else {
-            /* Implicitly advertised format -- use default caps */
-            caps->value = entry->defaultOperations;
-         }
-
-         return;
-      }
-   }
-
-   /* Unsupported format */
-   caps->value = 0;
-}
-
-
-/**
- * Return block size and bytes per block for the given SVGA3D format.
- * block_width and block_height are one for uncompressed formats and
- * greater than one for compressed formats.
- * Note: we don't handle formats that are unsupported, according to
- * the format_cap_table above.
- */
-void
-svga_format_size(SVGA3dSurfaceFormat format,
-                 unsigned *block_width,
-                 unsigned *block_height,
-                 unsigned *bytes_per_block)
-{
-   *block_width = *block_height = 1;
-
-   switch (format) {
-   case SVGA3D_X8R8G8B8:
-   case SVGA3D_A8R8G8B8:
-      *bytes_per_block = 4;
-      return;
-
-   case SVGA3D_R5G6B5:
-   case SVGA3D_X1R5G5B5:
-   case SVGA3D_A1R5G5B5:
-   case SVGA3D_A4R4G4B4:
-      *bytes_per_block = 2;
-      return;
-
-   case SVGA3D_Z_D32:
-      *bytes_per_block = 4;
-      return;
-
-   case SVGA3D_Z_D16:
-      *bytes_per_block = 2;
-      return;
-
-   case SVGA3D_Z_D24S8:
-      *bytes_per_block = 4;
-      return;
-
-   case SVGA3D_Z_D15S1:
-      *bytes_per_block = 2;
-      return;
-
-   case SVGA3D_LUMINANCE8:
-   case SVGA3D_LUMINANCE4_ALPHA4:
-      *bytes_per_block = 1;
-      return;
-
-   case SVGA3D_LUMINANCE16:
-   case SVGA3D_LUMINANCE8_ALPHA8:
-      *bytes_per_block = 2;
-      return;
-
-   case SVGA3D_DXT1:
-   case SVGA3D_DXT2:
-      *block_width = *block_height = 4;
-      *bytes_per_block = 8;
-      return;
-
-   case SVGA3D_DXT3:
-   case SVGA3D_DXT4:
-   case SVGA3D_DXT5:
-      *block_width = *block_height = 4;
-      *bytes_per_block = 16;
-      return;
-
-   case SVGA3D_BUMPU8V8:
-   case SVGA3D_BUMPL6V5U5:
-      *bytes_per_block = 2;
-      return;
-
-   case SVGA3D_BUMPX8L8V8U8:
-      *bytes_per_block = 4;
-      return;
-
-   case SVGA3D_ARGB_S10E5:
-      *bytes_per_block = 8;
-      return;
-
-   case SVGA3D_ARGB_S23E8:
-      *bytes_per_block = 16;
-      return;
-
-   case SVGA3D_A2R10G10B10:
-      *bytes_per_block = 4;
-      return;
-
-   case SVGA3D_Q8W8V8U8:
-      *bytes_per_block = 4;
-      return;
-
-   case SVGA3D_CxV8U8:
-      *bytes_per_block = 2;
-      return;
-
-   case SVGA3D_X8L8V8U8:
-   case SVGA3D_A2W10V10U10:
-      *bytes_per_block = 4;
-      return;
-
-   case SVGA3D_ALPHA8:
-      *bytes_per_block = 1;
-      return;
-
-   case SVGA3D_R_S10E5:
-      *bytes_per_block = 2;
-      return;
-   case SVGA3D_R_S23E8:
-      *bytes_per_block = 4;
-      return;
-   case SVGA3D_RG_S10E5:
-      *bytes_per_block = 4;
-      return;
-   case SVGA3D_RG_S23E8:
-      *bytes_per_block = 8;
-      return;
-
-   case SVGA3D_BUFFER:
-      *bytes_per_block = 1;
-      return;
-
-   case SVGA3D_Z_D24X8:
-      *bytes_per_block = 4;
-      return;
-
-   case SVGA3D_V16U16:
-      *bytes_per_block = 4;
-      return;
-
-   case SVGA3D_G16R16:
-      *bytes_per_block = 4;
-      return;
-
-   case SVGA3D_A16B16G16R16:
-      *bytes_per_block = 8;
-      return;
-
-   case SVGA3D_Z_DF16:
-      *bytes_per_block = 2;
-      return;
-   case SVGA3D_Z_DF24:
-      *bytes_per_block = 4;
-      return;
-   case SVGA3D_Z_D24S8_INT:
-      *bytes_per_block = 4;
-      return;
-
+   {
+      "SVGA3D_R32G32B32_TYPELESS",
+      SVGA3D_R32G32B32_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_R32G32B32_TYPELESS,
+      1, 1, 12,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R32G32B32_FLOAT",
+      SVGA3D_R32G32B32_FLOAT,
+      SVGA3D_DEVCAP_DXFMT_R32G32B32_FLOAT,
+      1, 1, 12,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R32G32B32_UINT",
+      SVGA3D_R32G32B32_UINT,
+      SVGA3D_DEVCAP_DXFMT_R32G32B32_UINT,
+      1, 1, 12,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R32G32B32_SINT",
+      SVGA3D_R32G32B32_SINT,
+      SVGA3D_DEVCAP_DXFMT_R32G32B32_SINT,
+      1, 1, 12,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16G16B16A16_TYPELESS",
+      SVGA3D_R16G16B16A16_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_R16G16B16A16_TYPELESS,
+      1, 1, 8,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16G16B16A16_UINT",
+      SVGA3D_R16G16B16A16_UINT,
+      SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UINT,
+      1, 1, 8,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16G16B16A16_SNORM",
+      SVGA3D_R16G16B16A16_SNORM,
+      SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SNORM,
+      1, 1, 8,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16G16B16A16_SINT",
+      SVGA3D_R16G16B16A16_SINT,
+      SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SINT,
+      1, 1, 8,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R32G32_TYPELESS",
+      SVGA3D_R32G32_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_R32G32_TYPELESS,
+      1, 1, 8,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R32G32_UINT",
+      SVGA3D_R32G32_UINT,
+      SVGA3D_DEVCAP_DXFMT_R32G32_UINT,
+      1, 1, 8,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R32G32_SINT",
+      SVGA3D_R32G32_SINT,
+      SVGA3D_DEVCAP_DXFMT_R32G32_SINT,
+      1, 1, 8,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R32G8X24_TYPELESS",
+      SVGA3D_R32G8X24_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_R32G8X24_TYPELESS,
+      1, 1, 8,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_ZSTENCIL
+   },
+   {
+      /* Special case: no devcap / report sampler and depth/stencil ability
+       */
+      "SVGA3D_D32_FLOAT_S8X24_UINT",
+      SVGA3D_D32_FLOAT_S8X24_UINT,
+      0, /*SVGA3D_DEVCAP_DXFMT_D32_FLOAT_S8X24_UINT*/
+      1, 1, 8,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_ZSTENCIL
+   },
+   {
+      /* Special case: no devcap / report sampler and depth/stencil ability
+       */
+      "SVGA3D_R32_FLOAT_X8X24_TYPELESS",
+      SVGA3D_R32_FLOAT_X8X24_TYPELESS,
+      0, /*SVGA3D_DEVCAP_DXFMT_R32_FLOAT_X8X24_TYPELESS*/
+      1, 1, 8,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_ZSTENCIL
+   },
+   {
+      "SVGA3D_X32_TYPELESS_G8X24_UINT",
+      SVGA3D_X32_TYPELESS_G8X24_UINT,
+      SVGA3D_DEVCAP_DXFMT_X32_TYPELESS_G8X24_UINT,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R10G10B10A2_TYPELESS",
+      SVGA3D_R10G10B10A2_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_R10G10B10A2_TYPELESS,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R10G10B10A2_UINT",
+      SVGA3D_R10G10B10A2_UINT,
+      SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UINT,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R11G11B10_FLOAT",
+      SVGA3D_R11G11B10_FLOAT,
+      SVGA3D_DEVCAP_DXFMT_R11G11B10_FLOAT,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R8G8B8A8_TYPELESS",
+      SVGA3D_R8G8B8A8_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_R8G8B8A8_TYPELESS,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R8G8B8A8_UNORM",
+      SVGA3D_R8G8B8A8_UNORM,
+      SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R8G8B8A8_UNORM_SRGB",
+      SVGA3D_R8G8B8A8_UNORM_SRGB,
+      SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM_SRGB,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R8G8B8A8_UINT",
+      SVGA3D_R8G8B8A8_UINT,
+      SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UINT,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+      },
+   {
+      "SVGA3D_R8G8B8A8_SINT",
+      SVGA3D_R8G8B8A8_SINT,
+      SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SINT,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16G16_TYPELESS",
+      SVGA3D_R16G16_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_R16G16_TYPELESS,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16G16_UINT",
+      SVGA3D_R16G16_UINT,
+      SVGA3D_DEVCAP_DXFMT_R16G16_UINT,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16G16_SINT",
+      SVGA3D_R16G16_SINT,
+      SVGA3D_DEVCAP_DXFMT_R16G16_SINT,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R32_TYPELESS",
+      SVGA3D_R32_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_R32_TYPELESS,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_ZSTENCIL |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      /* Special case: no devcap / report sampler and depth/stencil ability
+       */
+      "SVGA3D_D32_FLOAT",
+      SVGA3D_D32_FLOAT,
+      0, /*SVGA3D_DEVCAP_DXFMT_D32_FLOAT*/
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_ZSTENCIL
+   },
+   {
+      "SVGA3D_R32_UINT",
+      SVGA3D_R32_UINT,
+      SVGA3D_DEVCAP_DXFMT_R32_UINT,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R32_SINT",
+      SVGA3D_R32_SINT,
+      SVGA3D_DEVCAP_DXFMT_R32_SINT,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R24G8_TYPELESS",
+      SVGA3D_R24G8_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_R24G8_TYPELESS,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_ZSTENCIL
+   },
+   {
+      /* Special case: no devcap / report sampler and depth/stencil ability
+       */
+      "SVGA3D_D24_UNORM_S8_UINT",
+      SVGA3D_D24_UNORM_S8_UINT,
+      0, /*SVGA3D_DEVCAP_DXFMT_D24_UNORM_S8_UINT*/
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_ZSTENCIL
+   },
+   {
+      /* Special case: no devcap / report sampler and depth/stencil ability
+       */
+      "SVGA3D_R24_UNORM_X8_TYPELESS",
+      SVGA3D_R24_UNORM_X8_TYPELESS,
+      0, /*SVGA3D_DEVCAP_DXFMT_R24_UNORM_X8_TYPELESS*/
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_ZSTENCIL
+   },
+   {
+      "SVGA3D_X24_TYPELESS_G8_UINT",
+      SVGA3D_X24_TYPELESS_G8_UINT,
+      SVGA3D_DEVCAP_DXFMT_X24_TYPELESS_G8_UINT,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_ZSTENCIL
+   },
+   {
+      "SVGA3D_R8G8_TYPELESS",
+      SVGA3D_R8G8_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_R8G8_TYPELESS,
+      1, 1, 2,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R8G8_UNORM",
+      SVGA3D_R8G8_UNORM,
+      SVGA3D_DEVCAP_DXFMT_R8G8_UNORM,
+      1, 1, 2,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R8G8_UINT",
+      SVGA3D_R8G8_UINT,
+      SVGA3D_DEVCAP_DXFMT_R8G8_UINT,
+      1, 1, 2,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R8G8_SINT",
+      SVGA3D_R8G8_SINT,
+      SVGA3D_DEVCAP_DXFMT_R8G8_SINT,
+      1, 1, 2,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16_TYPELESS",
+      SVGA3D_R16_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_R16_TYPELESS,
+      1, 1, 2,
+      SVGA3DFORMAT_OP_ZSTENCIL |
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16_UNORM",
+      SVGA3D_R16_UNORM,
+      SVGA3D_DEVCAP_DXFMT_R16_UNORM,
+      1, 1, 2,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16_UINT",
+      SVGA3D_R16_UINT,
+      SVGA3D_DEVCAP_DXFMT_R16_UINT,
+      1, 1, 2,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16_SNORM",
+      SVGA3D_R16_SNORM,
+      SVGA3D_DEVCAP_DXFMT_R16_SNORM,
+      1, 1, 2,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16_SINT",
+      SVGA3D_R16_SINT,
+      SVGA3D_DEVCAP_DXFMT_R16_SINT,
+      1, 1, 2,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R8_TYPELESS",
+      SVGA3D_R8_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_R8_TYPELESS,
+      1, 1, 1,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R8_UNORM",
+      SVGA3D_R8_UNORM,
+      SVGA3D_DEVCAP_DXFMT_R8_UNORM,
+      1, 1, 1,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R8_UINT",
+      SVGA3D_R8_UINT,
+      SVGA3D_DEVCAP_DXFMT_R8_UINT,
+      1, 1, 1,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R8_SNORM",
+      SVGA3D_R8_SNORM,
+      SVGA3D_DEVCAP_DXFMT_R8_SNORM,
+      1, 1, 1,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R8_SINT",
+      SVGA3D_R8_SINT,
+      SVGA3D_DEVCAP_DXFMT_R8_SINT,
+      1, 1, 1,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_P8",
+      SVGA3D_P8, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_R9G9B9E5_SHAREDEXP",
+      SVGA3D_R9G9B9E5_SHAREDEXP,
+      SVGA3D_DEVCAP_DXFMT_R9G9B9E5_SHAREDEXP,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R8G8_B8G8_UNORM",
+      SVGA3D_R8G8_B8G8_UNORM, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_G8R8_G8B8_UNORM",
+      SVGA3D_G8R8_G8B8_UNORM, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_BC1_TYPELESS",
+      SVGA3D_BC1_TYPELESS, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_BC1_UNORM_SRGB",
+      SVGA3D_BC1_UNORM_SRGB, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_BC2_TYPELESS",
+      SVGA3D_BC2_TYPELESS, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_BC2_UNORM_SRGB",
+      SVGA3D_BC2_UNORM_SRGB, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_BC3_TYPELESS",
+      SVGA3D_BC3_TYPELESS, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_BC3_UNORM_SRGB",
+      SVGA3D_BC3_UNORM_SRGB, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_BC4_TYPELESS",
+      SVGA3D_BC4_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_BC4_TYPELESS,
+      4, 4, 8,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE
+   },
+   {
+      "SVGA3D_ATI1",
+      SVGA3D_ATI1, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_BC4_SNORM",
+      SVGA3D_BC4_SNORM,
+      SVGA3D_DEVCAP_DXFMT_BC4_SNORM,
+      4, 4, 8,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE
+   },
+   {
+      "SVGA3D_BC5_TYPELESS",
+      SVGA3D_BC5_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_BC5_TYPELESS,
+      4, 4, 16,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE
+   },
+   {
+      "SVGA3D_ATI2",
+      SVGA3D_ATI2, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_BC5_SNORM",
+      SVGA3D_BC5_SNORM,
+      SVGA3D_DEVCAP_DXFMT_BC5_SNORM,
+      4, 4, 16,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE
+   },
+   {
+      "SVGA3D_R10G10B10_XR_BIAS_A2_UNORM",
+      SVGA3D_R10G10B10_XR_BIAS_A2_UNORM, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_B8G8R8A8_TYPELESS",
+      SVGA3D_B8G8R8A8_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_B8G8R8A8_TYPELESS,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_B8G8R8A8_UNORM_SRGB",
+      SVGA3D_B8G8R8A8_UNORM_SRGB,
+      SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM_SRGB,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_B8G8R8X8_TYPELESS",
+      SVGA3D_B8G8R8X8_TYPELESS,
+      SVGA3D_DEVCAP_DXFMT_B8G8R8X8_TYPELESS,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_B8G8R8X8_UNORM_SRGB",
+      SVGA3D_B8G8R8X8_UNORM_SRGB,
+      SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM_SRGB,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_Z_DF16",
+      SVGA3D_Z_DF16,
+      SVGA3D_DEVCAP_SURFACEFMT_Z_DF16,
+      1, 1, 2,
+      0
+   },
+   {
+      "SVGA3D_Z_DF24",
+      SVGA3D_Z_DF24,
+      SVGA3D_DEVCAP_SURFACEFMT_Z_DF24,
+      1, 1, 4,
+      0
+   },
+   {
+      "SVGA3D_Z_D24S8_INT",
+      SVGA3D_Z_D24S8_INT,
+      SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_ZSTENCIL
+   },
+   {
+      "SVGA3D_YV12",
+      SVGA3D_YV12, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_R32G32B32A32_FLOAT",
+      SVGA3D_R32G32B32A32_FLOAT,
+      SVGA3D_DEVCAP_DXFMT_R32G32B32A32_FLOAT,
+      1, 1, 16,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16G16B16A16_FLOAT",
+      SVGA3D_R16G16B16A16_FLOAT,
+      SVGA3D_DEVCAP_DXFMT_R16G16B16A16_FLOAT,
+      1, 1, 8,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16G16B16A16_UNORM",
+      SVGA3D_R16G16B16A16_UNORM,
+      SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UNORM,
+      1, 1, 8,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R32G32_FLOAT",
+      SVGA3D_R32G32_FLOAT,
+      SVGA3D_DEVCAP_DXFMT_R32G32_FLOAT,
+      1, 1, 8,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R10G10B10A2_UNORM",
+      SVGA3D_R10G10B10A2_UNORM,
+      SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UNORM,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R8G8B8A8_SNORM",
+      SVGA3D_R8G8B8A8_SNORM,
+      SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SNORM,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16G16_FLOAT",
+      SVGA3D_R16G16_FLOAT,
+      SVGA3D_DEVCAP_DXFMT_R16G16_FLOAT,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16G16_UNORM",
+      SVGA3D_R16G16_UNORM,
+      SVGA3D_DEVCAP_DXFMT_R16G16_UNORM,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16G16_SNORM",
+      SVGA3D_R16G16_SNORM,
+      SVGA3D_DEVCAP_DXFMT_R16G16_SNORM,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      /* Special case: no devcap / report sampler, render target and
+       * depth/stencil ability
+       */
+      "SVGA3D_R32_FLOAT",
+      SVGA3D_R32_FLOAT,
+      0, /*SVGA3D_DEVCAP_DXFMT_R32_FLOAT*/
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET |
+      SVGA3DFORMAT_OP_ZSTENCIL
+   },
+   {
+      "SVGA3D_R8G8_SNORM",
+      SVGA3D_R8G8_SNORM,
+      SVGA3D_DEVCAP_DXFMT_R8G8_SNORM,
+      1, 1, 2,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_R16_FLOAT",
+      SVGA3D_R16_FLOAT,
+      SVGA3D_DEVCAP_DXFMT_R16_FLOAT,
+      1, 1, 2,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_D16_UNORM",
+      SVGA3D_D16_UNORM,
+      SVGA3D_DEVCAP_DXFMT_D16_UNORM,
+      1, 1, 2,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_ZSTENCIL
+   },
+   {
+      "SVGA3D_A8_UNORM",
+      SVGA3D_A8_UNORM,
+      SVGA3D_DEVCAP_DXFMT_A8_UNORM,
+      1, 1, 1,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_BC1_UNORM",
+      SVGA3D_BC1_UNORM, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_BC2_UNORM",
+      SVGA3D_BC2_UNORM, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_BC3_UNORM",
+      SVGA3D_BC3_UNORM, 0, 0, 0, 0, 0
+   },
+   {
+      "SVGA3D_B5G6R5_UNORM",
+      SVGA3D_B5G6R5_UNORM,
+      SVGA3D_DEVCAP_DXFMT_B5G6R5_UNORM,
+      1, 1, 2,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_DISPLAYMODE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_B5G5R5A1_UNORM",
+      SVGA3D_B5G5R5A1_UNORM,
+      SVGA3D_DEVCAP_DXFMT_B5G5R5A1_UNORM,
+      1, 1, 2,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_DISPLAYMODE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_B8G8R8A8_UNORM",
+      SVGA3D_B8G8R8A8_UNORM,
+      SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_B8G8R8X8_UNORM",
+      SVGA3D_B8G8R8X8_UNORM,
+      SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM,
+      1, 1, 4,
+      SVGA3DFORMAT_OP_TEXTURE |
+      SVGA3DFORMAT_OP_CUBETEXTURE |
+      SVGA3DFORMAT_OP_VOLUMETEXTURE |
+      SVGA3DFORMAT_OP_DISPLAYMODE |
+      SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
+   },
+   {
+      "SVGA3D_BC4_UNORM",
+     SVGA3D_BC4_UNORM,
+     SVGA3D_DEVCAP_DXFMT_BC4_UNORM,
+     4, 4, 8,
+     SVGA3DFORMAT_OP_TEXTURE |
+     SVGA3DFORMAT_OP_CUBETEXTURE
+   },
+   {
+      "SVGA3D_BC5_UNORM",
+     SVGA3D_BC5_UNORM,
+     SVGA3D_DEVCAP_DXFMT_BC5_UNORM,
+     4, 4, 16,
+     SVGA3DFORMAT_OP_TEXTURE |
+     SVGA3DFORMAT_OP_CUBETEXTURE
+   }
+};
+
+
+/**
+ * Debug only:
+ * 1. check that format_cap_table[i] matches the i-th SVGA3D format.
+ * 2. check that format_conversion_table[i].pformat == i.
+ */
+static void
+check_format_tables(void)
+{
+   static boolean first_call = TRUE;
+
+   if (first_call) {
+      unsigned i;
+
+      STATIC_ASSERT(Elements(format_cap_table) == SVGA3D_FORMAT_MAX);
+      for (i = 0; i < Elements(format_cap_table); i++) {
+         assert(format_cap_table[i].format == i);
+      }
+
+      STATIC_ASSERT(Elements(format_conversion_table) == PIPE_FORMAT_COUNT);
+      for (i = 0; i < Elements(format_conversion_table); i++) {
+         assert(format_conversion_table[i].pformat == i);
+      }
+
+      first_call = FALSE;
+   }
+}
+
+
+/*
+ * Get format capabilities from the host.  It takes in consideration
+ * deprecated/unsupported formats, and formats which are implicitely assumed to
+ * be supported when the host does not provide an explicit capability entry.
+ */
+void
+svga_get_format_cap(struct svga_screen *ss,
+                    SVGA3dSurfaceFormat format,
+                    SVGA3dSurfaceFormatCaps *caps)
+{
+   struct svga_winsys_screen *sws = ss->sws;
+   SVGA3dDevCapResult result;
+   const struct format_cap *entry;
+
+#ifdef DEBUG
+   check_format_tables();
+#else
+   (void) check_format_tables;
+#endif
+
+   assert(format < Elements(format_cap_table));
+   entry = &format_cap_table[format];
+   assert(entry->format == format);
+
+   if (entry->devcap && sws->get_cap(sws, entry->devcap, &result)) {
+      /* Explicitly advertised format */
+      if (entry->devcap > SVGA3D_DEVCAP_DX) {
+         /* Translate DX/VGPU10 format cap to VGPU9 cap */
+         caps->value = 0;
+         if (result.u & SVGA3D_DXFMT_COLOR_RENDERTARGET)
+            caps->value |= SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET;
+         if (!(result.u & SVGA3D_DXFMT_BLENDABLE))
+            caps->value |= SVGA3DFORMAT_OP_NOALPHABLEND;
+         if (result.u & SVGA3D_DXFMT_DEPTH_RENDERTARGET)
+            caps->value |= SVGA3DFORMAT_OP_ZSTENCIL;
+         if (result.u & SVGA3D_DXFMT_SHADER_SAMPLE)
+            caps->value |= (SVGA3DFORMAT_OP_TEXTURE |
+                            SVGA3DFORMAT_OP_CUBETEXTURE);
+         if (result.u & SVGA3D_DXFMT_VOLUME)
+            caps->value |= SVGA3DFORMAT_OP_VOLUMETEXTURE;
+      }
+      else {
+         /* Return VGPU9 format cap as-is */
+         caps->value = result.u;
+      }
+
+   } else {
+      /* Implicitly advertised format -- use default caps */
+      caps->value = entry->defaultOperations;
+   }
+}
+
+
+void
+svga_format_size(SVGA3dSurfaceFormat format,
+                 unsigned *block_width,
+                 unsigned *block_height,
+                 unsigned *bytes_per_block)
+{
+   assert(format < Elements(format_cap_table));
+   *block_width = format_cap_table[format].block_width;
+   *block_height = format_cap_table[format].block_height;
+   *bytes_per_block = format_cap_table[format].block_bytes;
+   /* Make sure the the table entry was valid */
+   if (*block_width == 0)
+      debug_printf("Bad table entry for %s\n", svga_format_name(format));
+   assert(*block_width);
+   assert(*block_height);
+   assert(*bytes_per_block);
+}
+
+
+const char *
+svga_format_name(SVGA3dSurfaceFormat format)
+{
+   assert(format < Elements(format_cap_table));
+   return format_cap_table[format].name;
+}
+
+
+/**
+ * Is the given SVGA3dSurfaceFormat a signed or unsigned integer color format?
+ */
+boolean
+svga_format_is_integer(SVGA3dSurfaceFormat format)
+{
+   switch (format) {
+   case SVGA3D_R32G32B32A32_SINT:
+   case SVGA3D_R32G32B32_SINT:
+   case SVGA3D_R32G32_SINT:
+   case SVGA3D_R32_SINT:
+   case SVGA3D_R16G16B16A16_SINT:
+   case SVGA3D_R16G16_SINT:
+   case SVGA3D_R16_SINT:
+   case SVGA3D_R8G8B8A8_SINT:
+   case SVGA3D_R8G8_SINT:
+   case SVGA3D_R8_SINT:
+   case SVGA3D_R32G32B32A32_UINT:
+   case SVGA3D_R32G32B32_UINT:
+   case SVGA3D_R32G32_UINT:
+   case SVGA3D_R32_UINT:
+   case SVGA3D_R16G16B16A16_UINT:
+   case SVGA3D_R16G16_UINT:
+   case SVGA3D_R16_UINT:
+   case SVGA3D_R8G8B8A8_UINT:
+   case SVGA3D_R8G8_UINT:
+   case SVGA3D_R8_UINT:
+   case SVGA3D_R10G10B10A2_UINT:
+      return TRUE;
+   default:
+      return FALSE;
+   }
+}
+
+
+/**
+ * Given a texture format, return the expected data type returned from
+ * the texture sampler.  For example, UNORM8 formats return floating point
+ * values while SINT formats returned signed integer values.
+ * Note: this function could be moved into the gallum u_format.[ch] code
+ * if it's useful to anyone else.
+ */
+enum tgsi_return_type
+svga_get_texture_datatype(enum pipe_format format)
+{
+   const struct util_format_description *desc = util_format_description(format);
+   enum tgsi_return_type t;
+
+   if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ) {
+      if (util_format_is_depth_or_stencil(format)) {
+         t = TGSI_RETURN_TYPE_FLOAT; /* XXX revisit this */
+      }
+      else if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) {
+         t = TGSI_RETURN_TYPE_FLOAT;
+      }
+      else if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED) {
+         t = desc->channel[0].normalized ? TGSI_RETURN_TYPE_UNORM : TGSI_RETURN_TYPE_UINT;
+      }
+      else if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED) {
+         t = desc->channel[0].normalized ? TGSI_RETURN_TYPE_SNORM : TGSI_RETURN_TYPE_SINT;
+      }
+      else {
+         assert(!"Unexpected channel type in svga_get_texture_datatype()");
+         t = TGSI_RETURN_TYPE_FLOAT;
+      }
+   }
+   else {
+      /* compressed format, shared exponent format, etc. */
+      switch (format) {
+      case PIPE_FORMAT_DXT1_RGB:
+      case PIPE_FORMAT_DXT1_RGBA:
+      case PIPE_FORMAT_DXT3_RGBA:
+      case PIPE_FORMAT_DXT5_RGBA:
+      case PIPE_FORMAT_DXT1_SRGB:
+      case PIPE_FORMAT_DXT1_SRGBA:
+      case PIPE_FORMAT_DXT3_SRGBA:
+      case PIPE_FORMAT_DXT5_SRGBA:
+      case PIPE_FORMAT_RGTC1_UNORM:
+      case PIPE_FORMAT_RGTC2_UNORM:
+      case PIPE_FORMAT_LATC1_UNORM:
+      case PIPE_FORMAT_LATC2_UNORM:
+      case PIPE_FORMAT_ETC1_RGB8:
+         t = TGSI_RETURN_TYPE_UNORM;
+         break;
+      case PIPE_FORMAT_RGTC1_SNORM:
+      case PIPE_FORMAT_RGTC2_SNORM:
+      case PIPE_FORMAT_LATC1_SNORM:
+      case PIPE_FORMAT_LATC2_SNORM:
+      case PIPE_FORMAT_R10G10B10X2_SNORM:
+         t = TGSI_RETURN_TYPE_SNORM;
+         break;
+      case PIPE_FORMAT_R11G11B10_FLOAT:
+      case PIPE_FORMAT_R9G9B9E5_FLOAT:
+         t = TGSI_RETURN_TYPE_FLOAT;
+         break;
+      default:
+         assert(!"Unexpected channel type in svga_get_texture_datatype()");
+         t = TGSI_RETURN_TYPE_FLOAT;
+      }
+   }
+
+   return t;
+}
+
+
+/**
+ * Given an svga context, return true iff there are currently any integer color
+ * buffers attached to the framebuffer.
+ */
+boolean
+svga_has_any_integer_cbufs(const struct svga_context *svga)
+{
+   unsigned i;
+   for (i = 0; i < PIPE_MAX_COLOR_BUFS; ++i) {
+      struct pipe_surface *cbuf = svga->curr.framebuffer.cbufs[i];
+
+      if (cbuf && util_format_is_pure_integer(cbuf->format)) {
+         return TRUE;
+      }
+   }
+   return FALSE;
+}
+
+
+/**
+ * Given an SVGA format, return the corresponding typeless format.
+ * If there is no typeless format, return the format unchanged.
+ */
+SVGA3dSurfaceFormat
+svga_typeless_format(SVGA3dSurfaceFormat format)
+{
+   switch (format) {
+   case SVGA3D_R32G32B32A32_UINT:
+   case SVGA3D_R32G32B32A32_SINT:
+   case SVGA3D_R32G32B32A32_FLOAT:
+      return SVGA3D_R32G32B32A32_TYPELESS;
+   case SVGA3D_R32G32B32_FLOAT:
+   case SVGA3D_R32G32B32_UINT:
+   case SVGA3D_R32G32B32_SINT:
+      return SVGA3D_R32G32B32_TYPELESS;
+   case SVGA3D_R16G16B16A16_UINT:
+   case SVGA3D_R16G16B16A16_UNORM:
+   case SVGA3D_R16G16B16A16_SNORM:
+   case SVGA3D_R16G16B16A16_SINT:
+   case SVGA3D_R16G16B16A16_FLOAT:
+      return SVGA3D_R16G16B16A16_TYPELESS;
+   case SVGA3D_R32G32_UINT:
+   case SVGA3D_R32G32_SINT:
+   case SVGA3D_R32G32_FLOAT:
+      return SVGA3D_R32G32_TYPELESS;
+   case SVGA3D_D32_FLOAT_S8X24_UINT:
+      return SVGA3D_R32G8X24_TYPELESS;
+   case SVGA3D_X32_TYPELESS_G8X24_UINT:
+      return SVGA3D_R32_FLOAT_X8X24_TYPELESS;
+   case SVGA3D_R10G10B10A2_UINT:
+   case SVGA3D_R10G10B10A2_UNORM:
+      return SVGA3D_R10G10B10A2_TYPELESS;
+   case SVGA3D_R8G8B8A8_UNORM:
+   case SVGA3D_R8G8B8A8_SNORM:
+   case SVGA3D_R8G8B8A8_UNORM_SRGB:
+   case SVGA3D_R8G8B8A8_UINT:
+   case SVGA3D_R8G8B8A8_SINT:
+      return SVGA3D_R8G8B8A8_TYPELESS;
+   case SVGA3D_R16G16_UINT:
+   case SVGA3D_R16G16_SINT:
+   case SVGA3D_R16G16_UNORM:
+   case SVGA3D_R16G16_SNORM:
+   case SVGA3D_R16G16_FLOAT:
+      return SVGA3D_R16G16_TYPELESS;
+   case SVGA3D_D32_FLOAT:
+   case SVGA3D_R32_FLOAT:
+   case SVGA3D_R32_UINT:
+   case SVGA3D_R32_SINT:
+      return SVGA3D_R32_TYPELESS;
+   case SVGA3D_D24_UNORM_S8_UINT:
+      return SVGA3D_R24G8_TYPELESS;
+   case SVGA3D_X24_TYPELESS_G8_UINT:
+      return SVGA3D_R24_UNORM_X8_TYPELESS;
+   case SVGA3D_R8G8_UNORM:
+   case SVGA3D_R8G8_SNORM:
+   case SVGA3D_R8G8_UINT:
+   case SVGA3D_R8G8_SINT:
+      return SVGA3D_R8G8_TYPELESS;
+   case SVGA3D_R16_UNORM:
+   case SVGA3D_R16_UINT:
+   case SVGA3D_R16_SNORM:
+   case SVGA3D_R16_SINT:
+   case SVGA3D_R16_FLOAT:
+      return SVGA3D_R16_TYPELESS;
+   case SVGA3D_R8_UNORM:
+   case SVGA3D_R8_UINT:
+   case SVGA3D_R8_SNORM:
+   case SVGA3D_R8_SINT:
+      return SVGA3D_R8_TYPELESS;
+   case SVGA3D_B8G8R8A8_UNORM_SRGB:
+   case SVGA3D_B8G8R8A8_UNORM:
+      return SVGA3D_B8G8R8A8_TYPELESS;
+   case SVGA3D_B8G8R8X8_UNORM_SRGB:
+   case SVGA3D_B8G8R8X8_UNORM:
+      return SVGA3D_B8G8R8X8_TYPELESS;
+   case SVGA3D_BC4_UNORM:
+   case SVGA3D_BC4_SNORM:
+      return SVGA3D_BC4_TYPELESS;
+   case SVGA3D_BC5_UNORM:
+   case SVGA3D_BC5_SNORM:
+      return SVGA3D_BC5_TYPELESS;
+
+   /* Special cases (no corresponding _TYPELESS formats) */
+   case SVGA3D_A8_UNORM:
+   case SVGA3D_A4R4G4B4:
+   case SVGA3D_B5G5R5A1_UNORM:
+   case SVGA3D_B5G6R5_UNORM:
+   case SVGA3D_DXT1:
+   case SVGA3D_DXT2:
+   case SVGA3D_DXT3:
+   case SVGA3D_DXT4:
+   case SVGA3D_DXT5:
+   case SVGA3D_R11G11B10_FLOAT:
+   case SVGA3D_R9G9B9E5_SHAREDEXP:
+   case SVGA3D_Z_D32:
+   case SVGA3D_Z_D16:
+      return format;
    default:
-      debug_printf("format %u\n", (unsigned) format);
-      assert(!"unexpected format in svga_format_size()");
-      *bytes_per_block = 4;
+      debug_printf("Unexpected format %s in %s\n",
+                   svga_format_name(format), __FUNCTION__);
+      return format;
    }
 }
index 94c867acf77f05473e9764fb672a035358cb1f36..0af218cb01a165b8c8df9c4a23630928b30cd898 100644 (file)
@@ -28,6 +28,7 @@
 
 
 #include "pipe/p_format.h"
+#include "svga_context.h"
 #include "svga_types.h"
 #include "svga_reg.h"
 #include "svga3d_reg.h"
 struct svga_screen;
 
 
+/**
+ * Vertex format flags.  These are used to specify that some vertex formats
+ * need extra processing/conversion in the vertex shader.  For example,
+ * setting the W component to 1, or swapping R/B, or converting packed uint
+ * types to signed int/snorm.
+ */
+#define VF_ADJUST_RANGE     (1 << 0)
+#define VF_W_TO_1           (1 << 1)
+#define VF_U_TO_F_CAST      (1 << 2)  /* convert uint to float */
+#define VF_I_TO_F_CAST      (1 << 3)  /* convert sint to float */
+#define VF_BGRA             (1 << 4)  /* swap R/B */
+#define VF_PUINT_TO_SNORM   (1 << 5)  /* 10_10_10_2 to snorm */
+#define VF_PUINT_TO_USCALED (1 << 6)  /* 10_10_10_2 to uscaled */
+#define VF_PUINT_TO_SSCALED (1 << 7)  /* 10_10_10_2 to sscaled */
+
+
+void
+svga_translate_vertex_format_vgpu10(enum pipe_format format,
+                                    SVGA3dSurfaceFormat *svga_format,
+                                    unsigned *vf_flags);
+
 enum SVGA3dSurfaceFormat
 svga_translate_format(struct svga_screen *ss,
                       enum pipe_format format,
@@ -52,5 +74,23 @@ svga_format_size(SVGA3dSurfaceFormat format,
                  unsigned *block_height,
                  unsigned *bytes_per_block);
 
+const char *
+svga_format_name(SVGA3dSurfaceFormat format);
+
+boolean
+svga_format_is_integer(SVGA3dSurfaceFormat format);
+
+enum tgsi_return_type
+svga_get_texture_datatype(enum pipe_format format);
+
+
+// XXX: Move this to svga_context?
+boolean
+svga_has_any_integer_cbufs(const struct svga_context *svga);
+
+
+SVGA3dSurfaceFormat
+svga_typeless_format(SVGA3dSurfaceFormat format);
+
 
 #endif /* SVGA_FORMAT_H_ */
index 2890516c0cf330221d08cf84b38d96afce530675..06bb3e3bd7e29c6a5055c6c2f7405ca6efe23c03 100644 (file)
 #include "pipe/p_defines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
+#include "util/u_bitmask.h"
 
 #include "svga_context.h"
-
 #include "svga_hw_reg.h"
+#include "svga_cmd.h"
 
 
 static inline unsigned
-svga_translate_blend_factor(unsigned factor)
+svga_translate_blend_factor(const struct svga_context *svga, unsigned factor)
 {
    switch (factor) {
    case PIPE_BLENDFACTOR_ZERO:            return SVGA3D_BLENDOP_ZERO;
@@ -50,8 +51,21 @@ svga_translate_blend_factor(unsigned factor)
    case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return SVGA3D_BLENDOP_SRCALPHASAT;
    case PIPE_BLENDFACTOR_CONST_COLOR:     return SVGA3D_BLENDOP_BLENDFACTOR;
    case PIPE_BLENDFACTOR_INV_CONST_COLOR: return SVGA3D_BLENDOP_INVBLENDFACTOR;
-   case PIPE_BLENDFACTOR_CONST_ALPHA:     return SVGA3D_BLENDOP_BLENDFACTOR; /* ? */
-   case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return SVGA3D_BLENDOP_INVBLENDFACTOR; /* ? */
+   case PIPE_BLENDFACTOR_CONST_ALPHA:
+      if (svga_have_vgpu10(svga))
+         return SVGA3D_BLENDOP_BLENDFACTORALPHA;
+      else
+         return SVGA3D_BLENDOP_BLENDFACTOR; /* as close as we can get */
+   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+      if (svga_have_vgpu10(svga))
+         return SVGA3D_BLENDOP_INVBLENDFACTORALPHA;
+      else
+         return SVGA3D_BLENDOP_INVBLENDFACTOR; /* as close as we can get */
+   case PIPE_BLENDFACTOR_SRC1_COLOR:      return SVGA3D_BLENDOP_SRC1COLOR;
+   case PIPE_BLENDFACTOR_INV_SRC1_COLOR:  return SVGA3D_BLENDOP_INVSRC1COLOR;
+   case PIPE_BLENDFACTOR_SRC1_ALPHA:      return SVGA3D_BLENDOP_SRC1ALPHA;
+   case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:  return SVGA3D_BLENDOP_INVSRC1ALPHA;
+   case 0:                                return SVGA3D_BLENDOP_ONE;
    default:
       assert(0);
       return SVGA3D_BLENDOP_ZERO;
@@ -74,18 +88,64 @@ svga_translate_blend_func(unsigned mode)
 }
 
 
+/**
+ * Define a vgpu10 blend state object for the given
+ * svga blend state.
+ */
+static void
+define_blend_state_object(struct svga_context *svga,
+                          struct svga_blend_state *bs)
+{
+   SVGA3dDXBlendStatePerRT perRT[SVGA3D_MAX_RENDER_TARGETS];
+   unsigned try;
+   int i;
+
+   assert(svga_have_vgpu10(svga));
+
+   bs->id = util_bitmask_add(svga->blend_object_id_bm);
+
+   for (i = 0; i < SVGA3D_DX_MAX_RENDER_TARGETS; i++) {
+      perRT[i].blendEnable = bs->rt[i].blend_enable;
+      perRT[i].srcBlend = bs->rt[i].srcblend;
+      perRT[i].destBlend = bs->rt[i].dstblend;
+      perRT[i].blendOp = bs->rt[i].blendeq;
+      perRT[i].srcBlendAlpha = bs->rt[i].srcblend_alpha;
+      perRT[i].destBlendAlpha = bs->rt[i].dstblend_alpha;
+      perRT[i].blendOpAlpha = bs->rt[i].blendeq_alpha;
+      perRT[i].renderTargetWriteMask = bs->rt[i].writemask;
+      perRT[i].logicOpEnable = 0;
+      perRT[i].logicOp = SVGA3D_LOGICOP_COPY;
+      assert(perRT[i].srcBlend == perRT[0].srcBlend);
+   }
+
+   /* Loop in case command buffer is full and we need to flush and retry */
+   for (try = 0; try < 2; try++) {
+      enum pipe_error ret;
+
+      ret = SVGA3D_vgpu10_DefineBlendState(svga->swc,
+                                           bs->id,
+                                           bs->alpha_to_coverage,
+                                           bs->independent_blend_enable,
+                                           perRT);
+      if (ret == PIPE_OK)
+         return;
+      svga_context_flush(svga, NULL);
+   }
+}
+
+
 static void *
 svga_create_blend_state(struct pipe_context *pipe,
                         const struct pipe_blend_state *templ)
 {
+   struct svga_context *svga = svga_context(pipe);
    struct svga_blend_state *blend = CALLOC_STRUCT( svga_blend_state );
    unsigned i;
 
    /* Fill in the per-rendertarget blend state.  We currently only
-    * have one rendertarget.
+    * support independent blend enable and colormask per render target.
     */
-   for (i = 0; i < 1; i++) {
+   for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
       /* No way to set this in SVGA3D, and no way to correctly implement it on
        * top of D3D9 API.  Instead we try to simulate with various blend modes.
        */
@@ -107,6 +167,9 @@ svga_create_blend_state(struct pipe_context *pipe,
             break;
          case PIPE_LOGICOP_COPY:
             blend->rt[i].blend_enable = FALSE;
+            blend->rt[i].srcblend       = SVGA3D_BLENDOP_ONE;
+            blend->rt[i].dstblend       = SVGA3D_BLENDOP_ZERO;
+            blend->rt[i].blendeq        = SVGA3D_BLENDEQ_ADD;
             break;
          case PIPE_LOGICOP_COPY_INVERTED:
             blend->rt[i].blend_enable   = TRUE;
@@ -169,38 +232,99 @@ svga_create_blend_state(struct pipe_context *pipe,
          case PIPE_LOGICOP_EQUIV:
             /* Fill these in with plausible values */
             blend->rt[i].blend_enable = FALSE;
+            blend->rt[i].srcblend       = SVGA3D_BLENDOP_ONE;
+            blend->rt[i].dstblend       = SVGA3D_BLENDOP_ZERO;
+            blend->rt[i].blendeq        = SVGA3D_BLENDEQ_ADD;
             break;
          default:
             assert(0);
             break;
          }
+         blend->rt[i].srcblend_alpha = blend->rt[i].srcblend;
+         blend->rt[i].dstblend_alpha = blend->rt[i].dstblend;
+         blend->rt[i].blendeq_alpha = blend->rt[i].blendeq;
       }
       else {
-         blend->rt[i].blend_enable   = templ->rt[0].blend_enable;
-
-         if (templ->rt[0].blend_enable) {
-            blend->rt[i].srcblend       = svga_translate_blend_factor(templ->rt[0].rgb_src_factor);
-            blend->rt[i].dstblend       = svga_translate_blend_factor(templ->rt[0].rgb_dst_factor);
-            blend->rt[i].blendeq        = svga_translate_blend_func(templ->rt[0].rgb_func);
-            blend->rt[i].srcblend_alpha = svga_translate_blend_factor(templ->rt[0].alpha_src_factor);
-            blend->rt[i].dstblend_alpha = svga_translate_blend_factor(templ->rt[0].alpha_dst_factor);
-            blend->rt[i].blendeq_alpha  = svga_translate_blend_func(templ->rt[0].alpha_func);
+         /* Note: the vgpu10 device does not yet support independent
+          * blend terms per render target.  Target[0] always specifies the
+          * blending terms.
+          */
+         if (templ->independent_blend_enable || templ->rt[0].blend_enable) {
+            /* always use the 0th target's blending terms for now */
+            blend->rt[i].srcblend =
+               svga_translate_blend_factor(svga, templ->rt[0].rgb_src_factor);
+            blend->rt[i].dstblend =
+               svga_translate_blend_factor(svga, templ->rt[0].rgb_dst_factor);
+            blend->rt[i].blendeq =
+               svga_translate_blend_func(templ->rt[0].rgb_func);
+            blend->rt[i].srcblend_alpha =
+               svga_translate_blend_factor(svga, templ->rt[0].alpha_src_factor);
+            blend->rt[i].dstblend_alpha =
+               svga_translate_blend_factor(svga, templ->rt[0].alpha_dst_factor);
+            blend->rt[i].blendeq_alpha =
+               svga_translate_blend_func(templ->rt[0].alpha_func);
 
             if (blend->rt[i].srcblend_alpha != blend->rt[i].srcblend ||
                 blend->rt[i].dstblend_alpha != blend->rt[i].dstblend ||
-                blend->rt[i].blendeq_alpha  != blend->rt[i].blendeq)
-            {
+                blend->rt[i].blendeq_alpha  != blend->rt[i].blendeq) {
                blend->rt[i].separate_alpha_blend_enable = TRUE;
             }
          }
+         else {
+            /* disabled - default blend terms */
+            blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
+            blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
+            blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
+            blend->rt[i].srcblend_alpha = SVGA3D_BLENDOP_ONE;
+            blend->rt[i].dstblend_alpha = SVGA3D_BLENDOP_ZERO;
+            blend->rt[i].blendeq_alpha = SVGA3D_BLENDEQ_ADD;
+         }
+
+         if (templ->independent_blend_enable) {
+            blend->rt[i].blend_enable = templ->rt[i].blend_enable;
+         }
+         else {
+            blend->rt[i].blend_enable = templ->rt[0].blend_enable;
+         }
       }
 
-      blend->rt[i].writemask = templ->rt[0].colormask;
+      /* Some GL blend modes are not supported by the VGPU9 device (there's
+       * no equivalent of PIPE_BLENDFACTOR_[INV_]CONST_ALPHA).
+       * When we set this flag, we copy the constant blend alpha value
+       * to the R, G, B components.
+       * This works as long as the src/dst RGB blend factors doesn't use
+       * PIPE_BLENDFACTOR_CONST_COLOR and PIPE_BLENDFACTOR_CONST_ALPHA
+       * at the same time.  There's no work-around for that.
+       */
+      if (!svga_have_vgpu10(svga)) {
+         if (templ->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_CONST_ALPHA ||
+             templ->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_CONST_ALPHA ||
+             templ->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_INV_CONST_ALPHA ||
+             templ->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_INV_CONST_ALPHA) {
+            blend->blend_color_alpha = TRUE;
+         }
+      }
+
+      if (templ->independent_blend_enable) {
+         blend->rt[i].writemask = templ->rt[i].colormask;
+      }
+      else {
+         blend->rt[i].writemask = templ->rt[0].colormask;
+      }
+   }
+
+   blend->independent_blend_enable = templ->independent_blend_enable;
+
+   blend->alpha_to_coverage = templ->alpha_to_coverage;
+
+   if (svga_have_vgpu10(svga)) {
+      define_blend_state_object(svga, blend);
    }
 
    return blend;
 }
 
+
 static void svga_bind_blend_state(struct pipe_context *pipe,
                                   void *blend)
 {
@@ -210,9 +334,30 @@ static void svga_bind_blend_state(struct pipe_context *pipe,
    svga->dirty |= SVGA_NEW_BLEND;
 }
 
-
-static void svga_delete_blend_state(struct pipe_context *pipe, void *blend)
+static void svga_delete_blend_state(struct pipe_context *pipe,
+                                    void *blend)
 {
+   struct svga_context *svga = svga_context(pipe);
+   struct svga_blend_state *bs =
+      (struct svga_blend_state *) blend;
+
+   if (bs->id != SVGA3D_INVALID_ID) {
+      enum pipe_error ret;
+
+      ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id);
+      if (ret != PIPE_OK) {
+         svga_context_flush(svga, NULL);
+         ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id);
+         assert(ret == PIPE_OK);
+      }
+
+      if (bs->id == svga->state.hw_draw.blend_id)
+         svga->state.hw_draw.blend_id = SVGA3D_INVALID_ID;
+
+      util_bitmask_clear(svga->blend_object_id_bm, bs->id);
+      bs->id = SVGA3D_INVALID_ID;
+   }
+
    FREE(blend);
 }
 
@@ -235,6 +380,3 @@ void svga_init_blend_functions( struct svga_context *svga )
 
    svga->pipe.set_blend_color = svga_set_blend_color;
 }
-
-
-
index dbb9f4b517292983c220f47d6d5ce3c1924cc8c0..2b34f964096f836bf9ff0ec1b83e2f03c3599246 100644 (file)
@@ -29,6 +29,7 @@
 #include "svga_cmd.h"
 #include "svga_surface.h"
 
+//#include "util/u_blit_sw.h"
 #include "util/u_format.h"
 #include "util/u_surface.h"
 
@@ -159,7 +160,8 @@ static void svga_blit(struct pipe_context *pipe,
    struct svga_context *svga = svga_context(pipe);
    struct pipe_blit_info info = *blit_info;
 
-   if (info.src.resource->nr_samples > 1 &&
+   if (!svga_have_vgpu10(svga) &&
+       info.src.resource->nr_samples > 1 &&
        info.dst.resource->nr_samples <= 1 &&
        !util_format_is_depth_or_stencil(info.src.resource->format) &&
        !util_format_is_pure_integer(info.src.resource->format)) {
@@ -171,12 +173,8 @@ static void svga_blit(struct pipe_context *pipe,
       return; /* done */
    }
 
-   if (info.mask & PIPE_MASK_S) {
-      debug_printf("svga: cannot blit stencil, skipping\n");
-      info.mask &= ~PIPE_MASK_S;
-   }
-
-   if (!util_blitter_is_blit_supported(svga->blitter, &info)) {
+   if ((info.mask & PIPE_MASK_S) ||
+       !util_blitter_is_blit_supported(svga->blitter, &info)) {
       debug_printf("svga: blit unsupported %s -> %s\n",
                    util_format_short_name(info.src.resource->format),
                    util_format_short_name(info.dst.resource->format));
@@ -188,9 +186,9 @@ static void svga_blit(struct pipe_context *pipe,
    util_blitter_save_vertex_buffer_slot(svga->blitter, svga->curr.vb);
    util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems);
    util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs);
-   /*util_blitter_save_geometry_shader(svga->blitter, svga->curr.gs);*/
-   /*util_blitter_save_so_targets(svga->blitter, svga->num_so_targets,
-                     (struct pipe_stream_output_target**)svga->so_targets);*/
+   util_blitter_save_geometry_shader(svga->blitter, svga->curr.user_gs);
+   util_blitter_save_so_targets(svga->blitter, svga->num_so_targets,
+                     (struct pipe_stream_output_target**)svga->so_targets);
    util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast);
    util_blitter_save_viewport(svga->blitter, &svga->curr.viewport);
    util_blitter_save_scissor(svga->blitter, &svga->curr.scissor);
@@ -199,14 +197,14 @@ static void svga_blit(struct pipe_context *pipe,
    util_blitter_save_depth_stencil_alpha(svga->blitter,
                                          (void*)svga->curr.depth);
    util_blitter_save_stencil_ref(svga->blitter, &svga->curr.stencil_ref);
-   /*util_blitter_save_sample_mask(svga->blitter, svga->sample_mask);*/
+   util_blitter_save_sample_mask(svga->blitter, svga->curr.sample_mask);
    util_blitter_save_framebuffer(svga->blitter, &svga->curr.framebuffer);
    util_blitter_save_fragment_sampler_states(svga->blitter,
-                     svga->curr.num_samplers,
-                     (void**)svga->curr.sampler);
+                     svga->curr.num_samplers[PIPE_SHADER_FRAGMENT],
+                     (void**)svga->curr.sampler[PIPE_SHADER_FRAGMENT]);
    util_blitter_save_fragment_sampler_views(svga->blitter,
-                     svga->curr.num_sampler_views,
-                     svga->curr.sampler_views);
+                     svga->curr.num_sampler_views[PIPE_SHADER_FRAGMENT],
+                     svga->curr.sampler_views[PIPE_SHADER_FRAGMENT]);
    /*util_blitter_save_render_condition(svga->blitter, svga->render_cond_query,
                                       svga->render_cond_cond, svga->render_cond_mode);*/
    util_blitter_blit(svga->blitter, &info);
index c4edced9baed7249fc367f414f27edc6f82b94d8..bab61780610b6a3baac7097c97792fe3134748ac 100644 (file)
 #include "svga_surface.h"
 
 
+/**
+ * Clear the whole color buffer(s) by drawing a quad.  For VGPU10 we use
+ * this when clearing integer render targets.  We'll also clear the
+ * depth and/or stencil buffers if the clear_buffers mask specifies them.
+ */
+static void
+clear_buffers_with_quad(struct svga_context *svga,
+                        unsigned clear_buffers,
+                        const union pipe_color_union *color,
+                        double depth, unsigned stencil)
+{
+   const struct pipe_framebuffer_state *fb = &svga->curr.framebuffer;
+
+   util_blitter_save_vertex_buffer_slot(svga->blitter, svga->curr.vb);
+   util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems);
+   util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs);
+   util_blitter_save_geometry_shader(svga->blitter, svga->curr.gs);
+   util_blitter_save_so_targets(svga->blitter, svga->num_so_targets,
+                     (struct pipe_stream_output_target**)svga->so_targets);
+   util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast);
+   util_blitter_save_viewport(svga->blitter, &svga->curr.viewport);
+   util_blitter_save_scissor(svga->blitter, &svga->curr.scissor);
+   util_blitter_save_fragment_shader(svga->blitter, svga->curr.fs);
+   util_blitter_save_blend(svga->blitter, (void*)svga->curr.blend);
+   util_blitter_save_depth_stencil_alpha(svga->blitter,
+                                         (void*)svga->curr.depth);
+   util_blitter_save_stencil_ref(svga->blitter, &svga->curr.stencil_ref);
+   util_blitter_save_sample_mask(svga->blitter, svga->curr.sample_mask);
+
+   util_blitter_clear(svga->blitter,
+                      fb->width, fb->height,
+                      1, /* num_layers */
+                      clear_buffers, color,
+                      depth, stencil);
+}
+
+
+/**
+ * Check if any of the color buffers are integer buffers.
+ */
+static boolean
+is_integer_target(struct pipe_framebuffer_state *fb, unsigned buffers)
+{
+   unsigned i;
+
+   for (i = 0; i < fb->nr_cbufs; i++) {
+      if ((buffers & (PIPE_CLEAR_COLOR0 << i)) &&
+          fb->cbufs[i] &&
+          util_format_is_pure_integer(fb->cbufs[i]->format)) {
+         return TRUE;
+      }
+   }
+   return FALSE;
+}
+
+
+/**
+ * Check if the integer values in the clear color can be represented
+ * by floats.  If so, we can use the VGPU10 ClearRenderTargetView command.
+ * Otherwise, we need to clear with a quad.
+ */
+static boolean
+ints_fit_in_floats(const union pipe_color_union *color)
+{
+   const int max = 1 << 24;
+   return (color->i[0] <= max &&
+           color->i[1] <= max &&
+           color->i[2] <= max &&
+           color->i[3] <= max);
+}
+
+
 static enum pipe_error
 try_clear(struct svga_context *svga, 
           unsigned buffers,
@@ -52,7 +124,7 @@ try_clear(struct svga_context *svga,
    if (ret != PIPE_OK)
       return ret;
 
-   if (svga->rebind.rendertargets) {
+   if (svga->rebind.flags.rendertargets) {
       ret = svga_reemit_framebuffer_bindings(svga);
       if (ret != PIPE_OK) {
          return ret;
@@ -71,29 +143,72 @@ try_clear(struct svga_context *svga,
       if (buffers & PIPE_CLEAR_DEPTH)
          flags |= SVGA3D_CLEAR_DEPTH;
 
-      if ((svga->curr.framebuffer.zsbuf->format == PIPE_FORMAT_S8_UINT_Z24_UNORM) &&
-          (buffers & PIPE_CLEAR_STENCIL))
+      if (buffers & PIPE_CLEAR_STENCIL)
          flags |= SVGA3D_CLEAR_STENCIL;
 
       rect.w = MAX2(rect.w, fb->zsbuf->width);
       rect.h = MAX2(rect.h, fb->zsbuf->height);
    }
 
-   if (memcmp(&rect, &svga->state.hw_clear.viewport, sizeof(rect)) != 0) {
+   if (!svga_have_vgpu10(svga) &&
+       !svga_rects_equal(&rect, &svga->state.hw_clear.viewport)) {
       restore_viewport = TRUE;
       ret = SVGA3D_SetViewport(svga->swc, &rect);
       if (ret != PIPE_OK)
          return ret;
    }
 
-   ret = SVGA3D_ClearRect(svga->swc, flags, uc.ui[0], (float) depth, stencil,
-                          rect.x, rect.y, rect.w, rect.h);
-   if (ret != PIPE_OK)
-      return ret;
+   if (svga_have_vgpu10(svga)) {
+      if (flags & SVGA3D_CLEAR_COLOR) {
+         unsigned i;
+
+         if (is_integer_target(fb, buffers) && !ints_fit_in_floats(color)) {
+            clear_buffers_with_quad(svga, buffers, color, depth, stencil);
+            /* We also cleared depth/stencil, so that's done */
+            flags &= ~(SVGA3D_CLEAR_DEPTH | SVGA3D_CLEAR_STENCIL);
+         }
+         else {
+            struct pipe_surface *rtv;
+
+            /* Issue VGPU10 Clear commands */
+            for (i = 0; i < fb->nr_cbufs; i++) {
+               if ((fb->cbufs[i] == NULL) ||
+                   !(buffers & (PIPE_CLEAR_COLOR0 << i)))
+                  continue;
+
+               rtv = svga_validate_surface_view(svga,
+                                                svga_surface(fb->cbufs[i]));
+               if (rtv == NULL)
+                  return PIPE_ERROR_OUT_OF_MEMORY;
+
+               ret = SVGA3D_vgpu10_ClearRenderTargetView(svga->swc,
+                                                         rtv, color->f);
+               if (ret != PIPE_OK)
+                  return ret;
+            }
+         }
+      }
+      if (flags & (SVGA3D_CLEAR_DEPTH | SVGA3D_CLEAR_STENCIL)) {
+         struct pipe_surface *dsv =
+            svga_validate_surface_view(svga, svga_surface(fb->zsbuf));
+         if (dsv == NULL)
+            return PIPE_ERROR_OUT_OF_MEMORY;
+
+         ret = SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv, flags,
+                                                   stencil, (float) depth);
+         if (ret != PIPE_OK)
+            return ret;
+      }
+   }
+   else {
+      ret = SVGA3D_ClearRect(svga->swc, flags, uc.ui[0], (float) depth, stencil,
+                             rect.x, rect.y, rect.w, rect.h);
+      if (ret != PIPE_OK)
+         return ret;
+   }
 
    if (restore_viewport) {
-      memcpy(&rect, &svga->state.hw_clear.viewport, sizeof rect);
-      ret = SVGA3D_SetViewport(svga->swc, &rect);
+      ret = SVGA3D_SetViewport(svga->swc, &svga->state.hw_clear.viewport);
    }
    
    return ret;
index c32b66d416bd2e289ffc1797347af00bf9ea5bfb..8150879ea13b9b826cc56fcd9a250cb3182343f4 100644 (file)
@@ -48,28 +48,46 @@ static void svga_set_constant_buffer(struct pipe_context *pipe,
                                      uint shader, uint index,
                                      struct pipe_constant_buffer *cb)
 {
+   struct svga_screen *svgascreen = svga_screen(pipe->screen);
    struct svga_context *svga = svga_context(pipe);
    struct pipe_resource *buf = cb ? cb->buffer : NULL;
-
-   if (cb && cb->user_buffer) {
-      buf = svga_user_buffer_create(pipe->screen,
-                                    (void *) cb->user_buffer,
-                                    cb->buffer_size,
-                                    PIPE_BIND_CONSTANT_BUFFER);
+   unsigned buffer_size = 0;
+
+   if (cb) {
+      buffer_size = cb->buffer_size;
+      if (cb->user_buffer) {
+         buf = svga_user_buffer_create(pipe->screen,
+                                       (void *) cb->user_buffer,
+                                       cb->buffer_size,
+                                       PIPE_BIND_CONSTANT_BUFFER);
+      }
    }
 
    assert(shader < PIPE_SHADER_TYPES);
-   assert(index == 0);
+   assert(index < Elements(svga->curr.constbufs[shader]));
+   assert(index < svgascreen->max_const_buffers);
+   (void) svgascreen;
+
+   pipe_resource_reference(&svga->curr.constbufs[shader][index].buffer, buf);
+
+   /* Make sure the constant buffer size to be updated is within the
+    * limit supported by the device.
+    */
+   svga->curr.constbufs[shader][index].buffer_size =
+      MIN2(buffer_size, SVGA_MAX_CONST_BUF_SIZE);
 
-   pipe_resource_reference(&svga->curr.cbufs[shader].buffer, buf);
-   svga->curr.cbufs[shader].buffer_size = cb ? cb->buffer_size : 0;
-   svga->curr.cbufs[shader].buffer_offset = cb ? cb->buffer_offset : 0;
-   svga->curr.cbufs[shader].user_buffer = NULL; /* not used */
+   svga->curr.constbufs[shader][index].buffer_offset = cb ? cb->buffer_offset : 0;
+   svga->curr.constbufs[shader][index].user_buffer = NULL; /* not used */
 
    if (shader == PIPE_SHADER_FRAGMENT)
       svga->dirty |= SVGA_NEW_FS_CONST_BUFFER;
-   else
+   else if (shader == PIPE_SHADER_VERTEX)
       svga->dirty |= SVGA_NEW_VS_CONST_BUFFER;
+   else
+      svga->dirty |= SVGA_NEW_GS_CONST_BUFFER;
+
+   /* update bitmask of dirty const buffers */
+   svga->state.dirty_constbufs[shader] |= (1 << index);
 
    if (cb && cb->user_buffer) {
       pipe_resource_reference(&buf, NULL);
index 8db21fd7476bac433b643ae24165740ac24c31cf..5ea623be4d90fa005a591450042bdc571e33d4de 100644 (file)
  *
  **********************************************************/
 
-#include "util/u_inlines.h"
 #include "pipe/p_defines.h"
+#include "util/u_bitmask.h"
+#include "util/u_inlines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 
 #include "svga_context.h"
 #include "svga_hw_reg.h"
+#include "svga_cmd.h"
 
 
 static inline unsigned
@@ -69,10 +71,67 @@ svga_translate_stencil_op(unsigned op)
 }
 
 
+/**
+ * Define a vgpu10 depth/stencil state object for the given
+ * svga depth/stencil state.
+ */
+static void
+define_depth_stencil_state_object(struct svga_context *svga,
+                                  struct svga_depth_stencil_state *ds)
+{
+   unsigned try;
+
+   assert(svga_have_vgpu10(svga));
+
+   ds->id = util_bitmask_add(svga->ds_object_id_bm);
+
+   /* spot check that these comparision tokens are the same */
+   assert(SVGA3D_COMPARISON_NEVER == SVGA3D_CMP_NEVER);
+   assert(SVGA3D_COMPARISON_LESS == SVGA3D_CMP_LESS);
+   assert(SVGA3D_COMPARISON_NOT_EQUAL == SVGA3D_CMP_NOTEQUAL);
+
+   /* Loop in case command buffer is full and we need to flush and retry */
+   for (try = 0; try < 2; try++) {
+      enum pipe_error ret;
+
+      /* Note: we use the ds->stencil[0].enabled value for both the front
+       * and back-face enables.  If single-side stencil is used, we'll have
+       * set the back state the same as the front state.
+       */
+      ret = SVGA3D_vgpu10_DefineDepthStencilState(svga->swc,
+                                                  ds->id,
+                                                  /* depth/Z */
+                                                  ds->zenable,
+                                                  ds->zwriteenable,
+                                                  ds->zfunc,
+                                                  /* Stencil */
+                                                  ds->stencil[0].enabled, /*f|b*/
+                                                  ds->stencil[0].enabled, /*f*/
+                                                  ds->stencil[0].enabled, /*b*/
+                                                  ds->stencil_mask,
+                                                  ds->stencil_writemask,
+                                                  /* front stencil */
+                                                  ds->stencil[0].fail,
+                                                  ds->stencil[0].zfail,
+                                                  ds->stencil[0].pass,
+                                                  ds->stencil[0].func,
+                                                  /* back stencil */
+                                                  ds->stencil[1].fail,
+                                                  ds->stencil[1].zfail,
+                                                  ds->stencil[1].pass,
+                                                  ds->stencil[1].func);
+      if (ret == PIPE_OK)
+         return;
+      svga_context_flush(svga, NULL);
+   }
+}
+
+
 static void *
 svga_create_depth_stencil_state(struct pipe_context *pipe,
                                const struct pipe_depth_stencil_alpha_state *templ)
 {
+   struct svga_context *svga = svga_context(pipe);
    struct svga_depth_stencil_state *ds = CALLOC_STRUCT( svga_depth_stencil_state );
 
    /* Don't try to figure out CW/CCW correspondence with
@@ -92,10 +151,18 @@ svga_create_depth_stencil_state(struct pipe_context *pipe,
       ds->stencil_mask      = templ->stencil[0].valuemask & 0xff;
       ds->stencil_writemask = templ->stencil[0].writemask & 0xff;
    }
+   else {
+      ds->stencil[0].func = SVGA3D_CMP_ALWAYS;
+      ds->stencil[0].fail = SVGA3D_STENCILOP_KEEP;
+      ds->stencil[0].zfail = SVGA3D_STENCILOP_KEEP;
+      ds->stencil[0].pass = SVGA3D_STENCILOP_KEEP;
+   }
 
 
    ds->stencil[1].enabled = templ->stencil[1].enabled;
    if (templ->stencil[1].enabled) {
+      assert(templ->stencil[0].enabled);
+      /* two-sided stencil */
       ds->stencil[1].func   = svga_translate_compare_func(templ->stencil[1].func);
       ds->stencil[1].fail   = svga_translate_stencil_op(templ->stencil[1].fail_op);
       ds->stencil[1].zfail  = svga_translate_stencil_op(templ->stencil[1].zfail_op);
@@ -104,6 +171,13 @@ svga_create_depth_stencil_state(struct pipe_context *pipe,
       ds->stencil_mask      = templ->stencil[1].valuemask & 0xff;
       ds->stencil_writemask = templ->stencil[1].writemask & 0xff;
    }
+   else {
+      /* back face state is same as front-face state */
+      ds->stencil[1].func = ds->stencil[0].func;
+      ds->stencil[1].fail = ds->stencil[0].fail;
+      ds->stencil[1].zfail = ds->stencil[0].zfail;
+      ds->stencil[1].pass = ds->stencil[0].pass;
+   }
 
 
    ds->zenable = templ->depth.enabled;
@@ -111,12 +185,22 @@ svga_create_depth_stencil_state(struct pipe_context *pipe,
       ds->zfunc = svga_translate_compare_func(templ->depth.func);
       ds->zwriteenable = templ->depth.writemask;
    }
+   else {
+      ds->zfunc = SVGA3D_CMP_ALWAYS;
+   }
 
    ds->alphatestenable = templ->alpha.enabled;
    if (ds->alphatestenable) {
       ds->alphafunc = svga_translate_compare_func(templ->alpha.func);
       ds->alpharef = templ->alpha.ref_value;
    }
+   else {
+      ds->alphafunc = SVGA3D_CMP_ALWAYS;
+   }
+
+   if (svga_have_vgpu10(svga)) {
+      define_depth_stencil_state_object(svga, ds);
+   }
 
    return ds;
 }
@@ -126,13 +210,43 @@ static void svga_bind_depth_stencil_state(struct pipe_context *pipe,
 {
    struct svga_context *svga = svga_context(pipe);
 
+   if (svga_have_vgpu10(svga)) {
+      /* flush any previously queued drawing before changing state */
+      svga_hwtnl_flush_retry(svga);
+   }
+
    svga->curr.depth = (const struct svga_depth_stencil_state *)depth_stencil;
-   svga->dirty |= SVGA_NEW_DEPTH_STENCIL;
+   svga->dirty |= SVGA_NEW_DEPTH_STENCIL_ALPHA;
 }
 
 static void svga_delete_depth_stencil_state(struct pipe_context *pipe,
                                             void *depth_stencil)
 {
+   struct svga_context *svga = svga_context(pipe);
+   struct svga_depth_stencil_state *ds =
+      (struct svga_depth_stencil_state *) depth_stencil;
+
+   if (svga_have_vgpu10(svga)) {
+      enum pipe_error ret;
+
+      svga_hwtnl_flush_retry(svga);
+
+      assert(ds->id != SVGA3D_INVALID_ID);
+
+      ret = SVGA3D_vgpu10_DestroyDepthStencilState(svga->swc, ds->id);
+      if (ret != PIPE_OK) {
+         svga_context_flush(svga, NULL);
+         ret = SVGA3D_vgpu10_DestroyDepthStencilState(svga->swc, ds->id);
+         assert(ret == PIPE_OK);
+      }
+
+      if (ds->id == svga->state.hw_draw.depth_stencil_id)
+         svga->state.hw_draw.depth_stencil_id = SVGA3D_INVALID_ID;
+
+      util_bitmask_clear(svga->ds_object_id_bm, ds->id);
+      ds->id = SVGA3D_INVALID_ID;
+   }
+
    FREE(depth_stencil);
 }
 
@@ -142,6 +256,11 @@ static void svga_set_stencil_ref( struct pipe_context *pipe,
 {
    struct svga_context *svga = svga_context(pipe);
 
+   if (svga_have_vgpu10(svga)) {
+      /* flush any previously queued drawing before changing state */
+      svga_hwtnl_flush_retry(svga);
+   }
+
    svga->curr.stencil_ref = *stencil_ref;
 
    svga->dirty |= SVGA_NEW_STENCIL_REF;
@@ -151,6 +270,11 @@ static void
 svga_set_sample_mask(struct pipe_context *pipe,
                      unsigned sample_mask)
 {
+   struct svga_context *svga = svga_context(pipe);
+
+   svga->curr.sample_mask = sample_mask;
+
+   svga->dirty |= SVGA_NEW_BLEND; /* See emit_rss_vgpu10() */
 }
 
 
index 87f6b3d7126246d8c2bceda304aac2d3af76f946..303d4565cdb7648b9a5f26138b023f7ed19a452e 100644 (file)
@@ -27,7 +27,9 @@
 #include "util/u_format.h"
 #include "util/u_inlines.h"
 #include "util/u_prim.h"
+#include "util/u_prim_restart.h"
 #include "util/u_time.h"
+#include "util/u_upload_mgr.h"
 #include "indices/u_indices.h"
 
 #include "svga_hw_reg.h"
 #include "svga_context.h"
 #include "svga_screen.h"
 #include "svga_draw.h"
+#include "svga_shader.h"
 #include "svga_state.h"
 #include "svga_swtnl.h"
 #include "svga_debug.h"
 #include "svga_resource_buffer.h"
 
-
 static enum pipe_error
 retry_draw_range_elements( struct svga_context *svga,
                            struct pipe_resource *index_buffer,
@@ -51,26 +53,31 @@ retry_draw_range_elements( struct svga_context *svga,
                            unsigned prim,
                            unsigned start,
                            unsigned count,
+                           unsigned start_instance,
                            unsigned instance_count,
                            boolean do_retry )
 {
    enum pipe_error ret = PIPE_OK;
 
-   svga_hwtnl_set_unfilled( svga->hwtnl,
-                            svga->curr.rast->hw_unfilled );
-
-   svga_hwtnl_set_flatshade( svga->hwtnl,
-                             svga->curr.rast->templ.flatshade,
-                             svga->curr.rast->templ.flatshade_first );
+   svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode);
 
    ret = svga_update_state( svga, SVGA_STATE_HW_DRAW );
    if (ret != PIPE_OK)
       goto retry;
 
+   /** determine if flatshade is to be used after svga_update_state()
+    *  in case the fragment shader is changed.
+    */
+   svga_hwtnl_set_flatshade(svga->hwtnl,
+                            svga->curr.rast->templ.flatshade ||
+                            svga->state.hw_draw.fs->uses_flat_interp,
+                            svga->curr.rast->templ.flatshade_first);
+
    ret = svga_hwtnl_draw_range_elements( svga->hwtnl,
                                          index_buffer, index_size, index_bias,
                                          min_index, max_index,
-                                         prim, start, count );
+                                         prim, start, count,
+                                         start_instance, instance_count);
    if (ret != PIPE_OK)
       goto retry;
 
@@ -85,7 +92,7 @@ retry:
                                         index_buffer, index_size, index_bias,
                                         min_index, max_index,
                                         prim, start, count,
-                                        instance_count, FALSE );
+                                        start_instance, instance_count, FALSE );
    }
 
    return ret;
@@ -94,27 +101,28 @@ retry:
 
 static enum pipe_error
 retry_draw_arrays( struct svga_context *svga,
-                   unsigned prim,
-                   unsigned start,
-                   unsigned count,
-                   unsigned instance_count,
+                   unsigned prim, unsigned start, unsigned count,
+                   unsigned start_instance, unsigned instance_count,
                    boolean do_retry )
 {
    enum pipe_error ret;
 
-   svga_hwtnl_set_unfilled( svga->hwtnl,
-                            svga->curr.rast->hw_unfilled );
-
-   svga_hwtnl_set_flatshade( svga->hwtnl,
-                             svga->curr.rast->templ.flatshade,
-                             svga->curr.rast->templ.flatshade_first );
+   svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode);
 
    ret = svga_update_state( svga, SVGA_STATE_HW_DRAW );
    if (ret != PIPE_OK)
       goto retry;
 
-   ret = svga_hwtnl_draw_arrays( svga->hwtnl, prim,
-                                 start, count );
+   /** determine if flatshade is to be used after svga_update_state()
+    *  in case the fragment shader is changed.
+    */
+   svga_hwtnl_set_flatshade(svga->hwtnl,
+                            svga->curr.rast->templ.flatshade ||
+                            svga->state.hw_draw.fs->uses_flat_interp,
+                            svga->curr.rast->templ.flatshade_first);
+
+   ret = svga_hwtnl_draw_arrays(svga->hwtnl, prim, start, count,
+                                start_instance, instance_count);
    if (ret != PIPE_OK)
       goto retry;
 
@@ -125,18 +133,41 @@ retry:
    {
       svga_context_flush( svga, NULL );
 
-      return retry_draw_arrays( svga,
-                                prim,
-                                start,
-                                count,
-                                instance_count,
-                                FALSE );
+      return retry_draw_arrays(svga, prim, start, count,
+                               start_instance, instance_count,
+                               FALSE );
    }
 
    return ret;
 }
 
 
+/**
+ * Determine if we need to implement primitive restart with a fallback
+ * path which breaks the original primitive into sub-primitive at the
+ * restart indexes.
+ */
+static boolean
+need_fallback_prim_restart(const struct svga_context *svga,
+                           const struct pipe_draw_info *info)
+{
+   if (info->primitive_restart && info->indexed) {
+      if (!svga_have_vgpu10(svga))
+         return TRUE;
+      else if (!svga->state.sw.need_swtnl) {
+         if (svga->curr.ib.index_size == 1)
+            return TRUE; /* no device support for 1-byte indexes */
+         else if (svga->curr.ib.index_size == 2)
+            return info->restart_index != 0xffff;
+         else
+            return info->restart_index != 0xffffffff;
+      }
+   }
+
+   return FALSE;
+}
+
+
 static void
 svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
 {
@@ -148,7 +179,8 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
 
    svga->num_draw_calls++;  /* for SVGA_QUERY_DRAW_CALLS */
 
-   if (!u_trim_pipe_prim( info->mode, &count ))
+   if (u_reduced_prim(info->mode) == PIPE_PRIM_TRIANGLES &&
+       svga->curr.rast->templ.cull_face == PIPE_FACE_FRONT_AND_BACK)
       return;
 
    /*
@@ -165,6 +197,17 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
       svga->dirty |= SVGA_NEW_REDUCED_PRIMITIVE;
    }
 
+   if (need_fallback_prim_restart(svga, info)) {
+      enum pipe_error r;
+      r = util_draw_vbo_without_prim_restart(pipe, &svga->curr.ib, info);
+      assert(r == PIPE_OK);
+      (void) r;
+      return;
+   }
+
+   if (!u_trim_pipe_prim( info->mode, &count ))
+      return;
+
    needed_swtnl = svga->state.sw.need_swtnl;
 
    svga_update_state_retry( svga, SVGA_STATE_NEED_SWTNL );
@@ -208,17 +251,15 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
                                           info->max_index,
                                           info->mode,
                                           info->start + offset,
-                                          info->count,
+                                          count,
+                                          info->start_instance,
                                           info->instance_count,
                                           TRUE );
       }
       else {
-         ret = retry_draw_arrays( svga,
-                                  info->mode,
-                                  info->start,
-                                  info->count,
-                                  info->instance_count,
-                                  TRUE );
+         ret = retry_draw_arrays(svga, info->mode, info->start, count,
+                                 info->start_instance, info->instance_count,
+                                 TRUE);
       }
    }
 
index 75299c50db714268ed2f06ae3b2cc02f75b8b307..4a9b3c96a54d99c0d2eb4b4cc9aa203f24e0f2f0 100644 (file)
@@ -31,7 +31,6 @@
 #include "draw/draw_context.h"
 
 #include "svga_context.h"
-#include "svga_tgsi.h"
 #include "svga_hw_reg.h"
 #include "svga_cmd.h"
 #include "svga_debug.h"
@@ -63,12 +62,6 @@ svga_create_fs_state(struct pipe_context *pipe,
 
    fs->draw_shader = draw_create_fragment_shader(svga->swtnl.draw, templ);
 
-   if (SVGA_DEBUG & DEBUG_TGSI || 0) {
-      debug_printf("%s id: %u, inputs: %u, outputs: %u\n",
-                   __FUNCTION__, fs->base.id,
-                   fs->base.info.num_inputs, fs->base.info.num_outputs);
-   }
-
    return fs;
 }
 
@@ -94,20 +87,30 @@ svga_delete_fs_state(struct pipe_context *pipe, void *shader)
 
    svga_hwtnl_flush_retry(svga);
 
+   assert(fs->base.parent == NULL);
+
    draw_delete_fragment_shader(svga->swtnl.draw, fs->draw_shader);
 
    for (variant = fs->base.variants; variant; variant = tmp) {
       tmp = variant->next;
 
-      ret = svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_PS, variant);
-      (void) ret;  /* PIPE_ERROR_ not handled yet */
-
-      /*
-       * Remove stale references to this variant to ensure a new variant on the
-       * same address will be detected as a change.
-       */
-      if (variant == svga->state.hw_draw.fs)
+      /* Check if deleting currently bound shader */
+      if (variant == svga->state.hw_draw.fs) {
+         ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_PS, NULL);
+         if (ret != PIPE_OK) {
+            svga_context_flush(svga, NULL);
+            ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_PS, NULL);
+            assert(ret == PIPE_OK);
+         }
          svga->state.hw_draw.fs = NULL;
+      }
+
+      ret = svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_PS, variant);
+      if (ret != PIPE_OK) {
+         svga_context_flush(svga, NULL);
+         ret = svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_PS, variant);
+         assert(ret == PIPE_OK);
+      }
    }
 
    FREE((void *)fs->base.tokens);
index 752c8c700e0cdc0215ce37cfab4c9c38d2211e53..d614e9d6c01a8cb50cfb5c192dd86712344a16d9 100644 (file)
@@ -84,7 +84,7 @@ svga_delete_gs_state(struct pipe_context *pipe, void *shader)
 {
    struct svga_context *svga = svga_context(pipe);
    struct svga_geometry_shader *gs = (struct svga_geometry_shader *)shader;
-   struct svga_geometry_shader *next_gs;  
+   struct svga_geometry_shader *next_gs;
    struct svga_shader_variant *variant, *tmp;
    enum pipe_error ret;
 
@@ -96,9 +96,9 @@ svga_delete_gs_state(struct pipe_context *pipe, void *shader)
 
    /* Free the list of geometry shaders */
    while (gs) {
-      next_gs = (struct svga_geometry_shader *)gs->base.next;  
+      next_gs = (struct svga_geometry_shader *)gs->base.next;
 
-      if (gs->base.stream_output != NULL) 
+      if (gs->base.stream_output != NULL)
          svga_delete_stream_output(svga, gs->base.stream_output);
 
       draw_delete_geometry_shader(svga->swtnl.draw, gs->draw_shader);
index 1df32a13b828d0b6d87cc1f8630a4d745121aa79..c8020da7c7a448e0ecafa360b2aeb362d73ba43b 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "util/u_framebuffer.h"
 #include "util/u_inlines.h"
+#include "util/u_pstipple.h"
 
 #include "svga_context.h"
 #include "svga_screen.h"
@@ -46,10 +47,37 @@ static void svga_set_scissor_states( struct pipe_context *pipe,
 }
 
 
-static void svga_set_polygon_stipple( struct pipe_context *pipe,
-                                      const struct pipe_poly_stipple *stipple )
+static void
+svga_set_polygon_stipple(struct pipe_context *pipe,
+                         const struct pipe_poly_stipple *stipple)
 {
-   /* overridden by the draw module */
+   struct svga_context *svga = svga_context(pipe);
+
+   /* release old texture */
+   pipe_resource_reference(&svga->polygon_stipple.texture, NULL);
+
+   /* release old sampler view */
+   if (svga->polygon_stipple.sampler_view) {
+      pipe->sampler_view_destroy(pipe,
+                                 &svga->polygon_stipple.sampler_view->base);
+   }
+
+   /* create new stipple texture */
+   svga->polygon_stipple.texture =
+      util_pstipple_create_stipple_texture(pipe, stipple->stipple);
+
+   /* create new sampler view */
+   svga->polygon_stipple.sampler_view =
+      (struct svga_pipe_sampler_view *)
+      util_pstipple_create_sampler_view(pipe,
+                                        svga->polygon_stipple.texture);
+
+   /* allocate sampler state, if first time */
+   if (!svga->polygon_stipple.sampler) {
+      svga->polygon_stipple.sampler = util_pstipple_create_sampler(pipe);
+   }
+
+   svga->dirty |= SVGA_NEW_STIPPLE;
 }
 
 
@@ -83,6 +111,11 @@ static void svga_set_framebuffer_state(struct pipe_context *pipe,
    boolean propagate = FALSE;
    unsigned i;
 
+   /* make sure any pending drawing calls are flushed before changing
+    * the framebuffer state
+    */
+   svga_hwtnl_flush_retry(svga);
+
    dst->width = fb->width;
    dst->height = fb->height;
    dst->nr_cbufs = fb->nr_cbufs;
@@ -99,9 +132,6 @@ static void svga_set_framebuffer_state(struct pipe_context *pipe,
    }
 
    if (propagate) {
-      /* make sure that drawing calls comes before propagation calls */
-      svga_hwtnl_flush_retry( svga );
-   
       for (i = 0; i < dst->nr_cbufs; i++) {
          struct pipe_surface *s = i < fb->nr_cbufs ? fb->cbufs[i] : NULL;
          if (dst->cbufs[i] && dst->cbufs[i] != s)
@@ -109,13 +139,30 @@ static void svga_set_framebuffer_state(struct pipe_context *pipe,
       }
    }
 
-   /* XXX: Actually the virtual hardware may support rendertargets with
-    * different size, depending on the host API and driver, but since we cannot
-    * know that make no such assumption here. */
-   for(i = 0; i < fb->nr_cbufs; ++i) {
-      if (fb->zsbuf && fb->cbufs[i]) {
-         assert(fb->zsbuf->width == fb->cbufs[i]->width); 
-         assert(fb->zsbuf->height == fb->cbufs[i]->height); 
+   /* Check that all surfaces are the same size.
+    * Actually, the virtual hardware may support rendertargets with
+    * different size, depending on the host API and driver,
+    */
+   {
+      int width = 0, height = 0;
+      if (fb->zsbuf) {
+         width = fb->zsbuf->width;
+         height = fb->zsbuf->height;
+      }
+      for (i = 0; i < fb->nr_cbufs; ++i) {
+         if (fb->cbufs[i]) {
+            if (width && height) {
+               if (fb->cbufs[i]->width != width ||
+                   fb->cbufs[i]->height != height) {
+                  debug_warning("Mixed-size color and depth/stencil surfaces "
+                                "may not work properly");
+               }
+            }
+            else {
+               width = fb->cbufs[i]->width;
+               height = fb->cbufs[i]->height;
+            }
+         }
       }
    }
 
index 208a2cd14bffab6f4c8cb342c483b46f8325410a..7081e5a1c43f28356b91064b3fe4d2f7c578887b 100644 (file)
@@ -1,5 +1,5 @@
 /**********************************************************
- * Copyright 2008-2009 VMware, Inc.  All rights reserved.
+ * Copyright 2008-2015 VMware, Inc.  All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -25,6 +25,8 @@
 
 #include "pipe/p_state.h"
 #include "pipe/p_context.h"
+
+#include "util/u_bitmask.h"
 #include "util/u_memory.h"
 
 #include "svga_cmd.h"
@@ -42,16 +44,26 @@ struct pipe_query {
    int dummy;
 };
 
-
 struct svga_query {
    struct pipe_query base;
    unsigned type;                  /**< PIPE_QUERY_x or SVGA_QUERY_x */
    SVGA3dQueryType svga_type;      /**< SVGA3D_QUERYTYPE_x or unused */
 
+   unsigned id;                    /** Per-context query identifier */
+
+   struct pipe_fence_handle *fence;
+
    /** For PIPE_QUERY_OCCLUSION_COUNTER / SVGA3D_QUERYTYPE_OCCLUSION */
+
+   /* For VGPU9 */
    struct svga_winsys_buffer *hwbuf;
    volatile SVGA3dQueryResult *queryResult;
-   struct pipe_fence_handle *fence;
+
+   /** For VGPU10 */
+   struct svga_winsys_gb_query *gb_query;
+   SVGA3dDXQueryFlags flags;
+   unsigned offset;                /**< offset to the gb_query memory */
+   struct pipe_query *predicate;   /** The associated query that can be used for predicate */
 
    /** For non-GPU SVGA_QUERY_x queries */
    uint64_t begin_count, end_count;
@@ -72,50 +84,641 @@ svga_get_query_result(struct pipe_context *pipe,
                       boolean wait,
                       union pipe_query_result *result);
 
+static enum pipe_error
+define_query_vgpu9(struct svga_context *svga,
+                   struct svga_query *sq)
+{
+   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+
+   sq->hwbuf = svga_winsys_buffer_create(svga, 1,
+                                         SVGA_BUFFER_USAGE_PINNED,
+                                         sizeof *sq->queryResult);
+   if (!sq->hwbuf)
+      return PIPE_ERROR_OUT_OF_MEMORY;
+
+   sq->queryResult = (SVGA3dQueryResult *)
+                     sws->buffer_map(sws, sq->hwbuf, PIPE_TRANSFER_WRITE);
+   if (!sq->queryResult) {
+      sws->buffer_destroy(sws, sq->hwbuf);
+      return PIPE_ERROR_OUT_OF_MEMORY;
+   }
+
+   sq->queryResult->totalSize = sizeof *sq->queryResult;
+   sq->queryResult->state = SVGA3D_QUERYSTATE_NEW;
+
+   /* We request the buffer to be pinned and assume it is always mapped.
+    * The reason is that we don't want to wait for fences when checking the
+    * query status.
+    */
+   sws->buffer_unmap(sws, sq->hwbuf);
+
+   return PIPE_OK;
+}
+
+static enum pipe_error
+begin_query_vgpu9(struct svga_context *svga, struct svga_query *sq)
+{
+   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+   enum pipe_error ret = PIPE_OK;
+
+   if (sq->queryResult->state == SVGA3D_QUERYSTATE_PENDING) {
+      /* The application doesn't care for the pending query result.
+       * We cannot let go of the existing buffer and just get a new one
+       * because its storage may be reused for other purposes and clobbered
+       * by the host when it determines the query result.  So the only
+       * option here is to wait for the existing query's result -- not a
+       * big deal, given that no sane application would do this.
+       */
+       uint64_t result;
+       svga_get_query_result(&svga->pipe, &sq->base, TRUE, (void*)&result);
+       assert(sq->queryResult->state != SVGA3D_QUERYSTATE_PENDING);
+   }
+
+   sq->queryResult->state = SVGA3D_QUERYSTATE_NEW;
+   sws->fence_reference(sws, &sq->fence, NULL);
+
+   ret = SVGA3D_BeginQuery(svga->swc, sq->svga_type);
+   if (ret != PIPE_OK) {
+      svga_context_flush(svga, NULL);
+      ret = SVGA3D_BeginQuery(svga->swc, sq->svga_type);
+   }
+   return ret;
+}
+
+static enum pipe_error
+end_query_vgpu9(struct svga_context *svga, struct svga_query *sq)
+{
+   enum pipe_error ret = PIPE_OK;
+
+   /* Set to PENDING before sending EndQuery. */
+   sq->queryResult->state = SVGA3D_QUERYSTATE_PENDING;
+
+   ret = SVGA3D_EndQuery(svga->swc, sq->svga_type, sq->hwbuf);
+   if (ret != PIPE_OK) {
+      svga_context_flush(svga, NULL);
+      ret = SVGA3D_EndQuery(svga->swc, sq->svga_type, sq->hwbuf);
+   }
+   return ret;
+}
+
+static boolean
+get_query_result_vgpu9(struct svga_context *svga, struct svga_query *sq,
+                       boolean wait, uint64_t *result)
+{
+   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+   enum pipe_error ret;
+   SVGA3dQueryState state;
+
+   if (!sq->fence) {
+      /* The query status won't be updated by the host unless
+       * SVGA_3D_CMD_WAIT_FOR_QUERY is emitted. Unfortunately this will cause
+       * a synchronous wait on the host.
+       */
+      ret = SVGA3D_WaitForQuery(svga->swc, sq->svga_type, sq->hwbuf);
+      if (ret != PIPE_OK) {
+         svga_context_flush(svga, NULL);
+         ret = SVGA3D_WaitForQuery(svga->swc, sq->svga_type, sq->hwbuf);
+      }
+      assert (ret == PIPE_OK);
+      svga_context_flush(svga, &sq->fence);
+      assert(sq->fence);
+   }
+
+   state = sq->queryResult->state;
+   if (state == SVGA3D_QUERYSTATE_PENDING) {
+      if (!wait)
+         return FALSE;
+      sws->fence_finish(sws, sq->fence, SVGA_FENCE_FLAG_QUERY);
+      state = sq->queryResult->state;
+   }
+
+   assert(state == SVGA3D_QUERYSTATE_SUCCEEDED ||
+          state == SVGA3D_QUERYSTATE_FAILED);
+
+   *result = (uint64_t)sq->queryResult->result32;
+   return TRUE;
+}
+
+
+/**
+ * VGPU10
+ *
+ * There is one query mob allocated for each context to be shared by all
+ * query types. The mob is used to hold queries's state and result. Since
+ * each query result type is of different length, to ease the query allocation
+ * management, the mob is divided into memory blocks. Each memory block
+ * will hold queries of the same type. Multiple memory blocks can be allocated
+ * for a particular query type.
+ *
+ * Currently each memory block is of 184 bytes. We support up to 128
+ * memory blocks. The query memory size is arbitrary right now.
+ * Each occlusion query takes about 8 bytes. One memory block can accomodate
+ * 23 occlusion queries. 128 of those blocks can support up to 2944 occlusion
+ * queries. That seems reasonable for now. If we think this limit is
+ * not enough, we can increase the limit or try to grow the mob in runtime.
+ * Note, SVGA device does not impose one mob per context for queries,
+ * we could allocate multiple mobs for queries; however, wddm KMD does not
+ * currently support that.
+ *
+ * Also note that the GL guest driver does not issue any of the
+ * following commands: DXMoveQuery, DXBindAllQuery & DXReadbackAllQuery.
+ */
+#define SVGA_QUERY_MEM_BLOCK_SIZE    (sizeof(SVGADXQueryResultUnion) * 2)
+#define SVGA_QUERY_MEM_SIZE          (128 * SVGA_QUERY_MEM_BLOCK_SIZE)
+
+struct svga_qmem_alloc_entry
+{
+   unsigned start_offset;               /* start offset of the memory block */
+   unsigned block_index;                /* block index of the memory block */
+   unsigned query_size;                 /* query size in this memory block */
+   unsigned nquery;                     /* number of queries allocated */
+   struct util_bitmask *alloc_mask;     /* allocation mask */
+   struct svga_qmem_alloc_entry *next;  /* next memory block */
+};
+
+
+/**
+ * Allocate a memory block from the query object memory
+ * \return -1 if out of memory, else index of the query memory block
+ */
+static int
+allocate_query_block(struct svga_context *svga)
+{
+   int index;
+   unsigned offset;
+
+   /* Find the next available query block */
+   index = util_bitmask_add(svga->gb_query_alloc_mask);
+
+   if (index == UTIL_BITMASK_INVALID_INDEX)
+      return -1;
+
+   offset = index * SVGA_QUERY_MEM_BLOCK_SIZE;
+   if (offset >= svga->gb_query_len) {
+      unsigned i;
+
+      /**
+       * All the memory blocks are allocated, lets see if there is
+       * any empty memory block around that can be freed up.
+       */
+      index = -1;
+      for (i = 0; i < SVGA_QUERY_MAX && index == -1; i++) {
+         struct svga_qmem_alloc_entry *alloc_entry;
+         struct svga_qmem_alloc_entry *prev_alloc_entry = NULL;
+
+         alloc_entry = svga->gb_query_map[i];
+         while (alloc_entry && index == -1) {
+            if (alloc_entry->nquery == 0) {
+               /* This memory block is empty, it can be recycled. */
+               if (prev_alloc_entry) {
+                  prev_alloc_entry->next = alloc_entry->next;
+               } else {
+                  svga->gb_query_map[i] = alloc_entry->next;
+               }
+               index = alloc_entry->block_index;
+            } else {
+               prev_alloc_entry = alloc_entry;
+               alloc_entry = alloc_entry->next;
+            }
+         }
+      }
+   }
+
+   return index;
+}
+
+/**
+ * Allocate a slot in the specified memory block.
+ * All slots in this memory block are of the same size.
+ *
+ * \return -1 if out of memory, else index of the query slot
+ */
+static int
+allocate_query_slot(struct svga_context *svga,
+                    struct svga_qmem_alloc_entry *alloc)
+{
+   int index;
+   unsigned offset;
+
+   /* Find the next available slot */
+   index = util_bitmask_add(alloc->alloc_mask);
+
+   if (index == UTIL_BITMASK_INVALID_INDEX)
+      return -1;
+
+   offset = index * alloc->query_size;
+   if (offset >= SVGA_QUERY_MEM_BLOCK_SIZE)
+      return -1;
+
+   alloc->nquery++;
+
+   return index;
+}
+
+/**
+ * Deallocate the specified slot in the memory block.
+ * If all slots are freed up, then deallocate the memory block
+ * as well, so it can be allocated for other query type
+ */
+static void
+deallocate_query_slot(struct svga_context *svga,
+                      struct svga_qmem_alloc_entry *alloc,
+                      unsigned index)
+{
+   assert(index != UTIL_BITMASK_INVALID_INDEX);
+
+   util_bitmask_clear(alloc->alloc_mask, index);
+   alloc->nquery--;
+
+   /**
+    * Don't worry about deallocating the empty memory block here.
+    * The empty memory block will be recycled when no more memory block
+    * can be allocated.
+    */
+}
+
+static struct svga_qmem_alloc_entry *
+allocate_query_block_entry(struct svga_context *svga,
+                           unsigned len)
+{
+   struct svga_qmem_alloc_entry *alloc_entry;
+   int block_index = -1;
+
+   block_index = allocate_query_block(svga);
+   if (block_index == -1)
+      return NULL;
+   alloc_entry = CALLOC_STRUCT(svga_qmem_alloc_entry);
+   if (alloc_entry == NULL)
+      return NULL;
+
+   alloc_entry->block_index = block_index;
+   alloc_entry->start_offset = block_index * SVGA_QUERY_MEM_BLOCK_SIZE;
+   alloc_entry->nquery = 0;
+   alloc_entry->alloc_mask = util_bitmask_create();
+   alloc_entry->next = NULL;
+   alloc_entry->query_size = len;
+
+   return alloc_entry;
+}
+
+/**
+ * Allocate a memory slot for a query of the specified type.
+ * It will first search through the memory blocks that are allocated
+ * for the query type. If no memory slot is available, it will try
+ * to allocate another memory block within the query object memory for
+ * this query type.
+ */
+static int
+allocate_query(struct svga_context *svga,
+               SVGA3dQueryType type,
+               unsigned len)
+{
+   struct svga_qmem_alloc_entry *alloc_entry;
+   int slot_index = -1;
+   unsigned offset;
+
+   assert(type < SVGA_QUERY_MAX);
+
+   alloc_entry = svga->gb_query_map[type];
+
+   if (alloc_entry == NULL) {
+      /**
+       * No query memory block has been allocated for this query type,
+       * allocate one now
+       */
+      alloc_entry = allocate_query_block_entry(svga, len);
+      if (alloc_entry == NULL)
+         return -1;
+      svga->gb_query_map[type] = alloc_entry;
+   }
+
+   /* Allocate a slot within the memory block allocated for this query type */
+   slot_index = allocate_query_slot(svga, alloc_entry);
+
+   if (slot_index == -1) {
+      /* This query memory block is full, allocate another one */
+      alloc_entry = allocate_query_block_entry(svga, len);
+      if (alloc_entry == NULL)
+         return -1;
+      alloc_entry->next = svga->gb_query_map[type];
+      svga->gb_query_map[type] = alloc_entry;
+      slot_index = allocate_query_slot(svga, alloc_entry);
+   }
+
+   assert(slot_index != -1);
+   offset = slot_index * len + alloc_entry->start_offset;
+
+   return offset;
+}
+
+
+/**
+ * Deallocate memory slot allocated for the specified query
+ */
+static void
+deallocate_query(struct svga_context *svga,
+                 struct svga_query *sq)
+{
+   struct svga_qmem_alloc_entry *alloc_entry;
+   unsigned slot_index;
+   unsigned offset = sq->offset;
+
+   alloc_entry = svga->gb_query_map[sq->svga_type];
+
+   while (alloc_entry) {
+      if (offset >= alloc_entry->start_offset &&
+          offset < alloc_entry->start_offset + SVGA_QUERY_MEM_BLOCK_SIZE) {
+
+         /* The slot belongs to this memory block, deallocate it */
+         slot_index = (offset - alloc_entry->start_offset) /
+                      alloc_entry->query_size;
+         deallocate_query_slot(svga, alloc_entry, slot_index);
+         alloc_entry = NULL;
+      } else {
+         alloc_entry = alloc_entry->next;
+      }
+   }
+}
+
+
+/**
+ * Destroy the gb query object and all the related query structures
+ */
+static void
+destroy_gb_query_obj(struct svga_context *svga)
+{
+   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+   unsigned i;
+
+   for (i = 0; i < SVGA_QUERY_MAX; i++) {
+      struct svga_qmem_alloc_entry *alloc_entry, *next;
+      alloc_entry = svga->gb_query_map[i];
+      while (alloc_entry) {
+         next = alloc_entry->next;
+         util_bitmask_destroy(alloc_entry->alloc_mask);
+         FREE(alloc_entry);
+         alloc_entry = next;
+      }
+      svga->gb_query_map[i] = NULL;
+   }
+
+   if (svga->gb_query)
+      sws->query_destroy(sws, svga->gb_query);
+   svga->gb_query = NULL;
+
+   util_bitmask_destroy(svga->gb_query_alloc_mask);
+}
+
+/**
+ * Define query and create the gb query object if it is not already created.
+ * There is only one gb query object per context which will be shared by
+ * queries of all types.
+ */
+static enum pipe_error
+define_query_vgpu10(struct svga_context *svga,
+                    struct svga_query *sq, int resultLen)
+{
+   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+   int qlen;
+   enum pipe_error ret = PIPE_OK;
+
+   SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__);
+
+   if (svga->gb_query == NULL) {
+      /* Create a gb query object */
+      svga->gb_query = sws->query_create(sws, SVGA_QUERY_MEM_SIZE);
+      if (!svga->gb_query)
+         return PIPE_ERROR_OUT_OF_MEMORY;
+      svga->gb_query_len = SVGA_QUERY_MEM_SIZE;
+      memset (svga->gb_query_map, 0, sizeof(svga->gb_query_map));
+      svga->gb_query_alloc_mask = util_bitmask_create();
+
+      /* Bind the query object to the context */
+      if (svga->swc->query_bind(svga->swc, svga->gb_query,
+                                SVGA_QUERY_FLAG_SET) != PIPE_OK) {
+         svga_context_flush(svga, NULL);
+         svga->swc->query_bind(svga->swc, svga->gb_query,
+                               SVGA_QUERY_FLAG_SET);
+      }
+   }
+
+   sq->gb_query = svga->gb_query;
+
+   /* Allocate an integer ID for this query */
+   sq->id = util_bitmask_add(svga->query_id_bm);
+   if (sq->id == UTIL_BITMASK_INVALID_INDEX)
+      return PIPE_ERROR_OUT_OF_MEMORY;
+
+   /* Find a slot for this query in the gb object */
+   qlen = resultLen + sizeof(SVGA3dQueryState);
+   sq->offset = allocate_query(svga, sq->svga_type, qlen);
+   if (sq->offset == -1)
+      return PIPE_ERROR_OUT_OF_MEMORY;
+
+   SVGA_DBG(DEBUG_QUERY, "   query type=%d qid=0x%x offset=%d\n",
+            sq->svga_type, sq->id, sq->offset);
+
+   /**
+    * Send SVGA3D commands to define the query
+    */
+   ret = SVGA3D_vgpu10_DefineQuery(svga->swc, sq->id, sq->svga_type, sq->flags);
+   if (ret != PIPE_OK) {
+      svga_context_flush(svga, NULL);
+      ret = SVGA3D_vgpu10_DefineQuery(svga->swc, sq->id, sq->svga_type, sq->flags);
+   }
+   if (ret != PIPE_OK)
+      return PIPE_ERROR_OUT_OF_MEMORY;
+
+   ret = SVGA3D_vgpu10_BindQuery(svga->swc, sq->gb_query, sq->id);
+   if (ret != PIPE_OK) {
+      svga_context_flush(svga, NULL);
+      ret = SVGA3D_vgpu10_BindQuery(svga->swc, sq->gb_query, sq->id);
+   }
+   assert(ret == PIPE_OK);
+
+   ret = SVGA3D_vgpu10_SetQueryOffset(svga->swc, sq->id, sq->offset);
+   if (ret != PIPE_OK) {
+      svga_context_flush(svga, NULL);
+      ret = SVGA3D_vgpu10_SetQueryOffset(svga->swc, sq->id, sq->offset);
+   }
+   assert(ret == PIPE_OK);
+
+   return PIPE_OK;
+}
+
+static enum pipe_error
+destroy_query_vgpu10(struct svga_context *svga, struct svga_query *sq)
+{
+   enum pipe_error ret;
+
+   ret = SVGA3D_vgpu10_DestroyQuery(svga->swc, sq->id);
+
+   /* Deallocate the memory slot allocated for this query */
+   deallocate_query(svga, sq);
+
+   return ret;
+}
+
+
+/**
+ * Rebind queryies to the context.
+ */
+static void
+rebind_vgpu10_query(struct svga_context *svga)
+{
+   if (svga->swc->query_bind(svga->swc, svga->gb_query,
+                             SVGA_QUERY_FLAG_REF) != PIPE_OK) {
+      svga_context_flush(svga, NULL);
+      svga->swc->query_bind(svga->swc, svga->gb_query,
+                            SVGA_QUERY_FLAG_REF);
+   }
+
+   svga->rebind.flags.query = FALSE;
+}
+
+
+static enum pipe_error
+begin_query_vgpu10(struct svga_context *svga, struct svga_query *sq)
+{
+   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+   enum pipe_error ret = PIPE_OK;
+   int status = 0;
+
+   sws->fence_reference(sws, &sq->fence, NULL);
+
+   /* Initialize the query state to NEW */
+   status = sws->query_init(sws, sq->gb_query, sq->offset, SVGA3D_QUERYSTATE_NEW);
+   if (status)
+      return PIPE_ERROR;
+
+   if (svga->rebind.flags.query) {
+      rebind_vgpu10_query(svga);
+   }
+
+   /* Send the BeginQuery command to the device */
+   ret = SVGA3D_vgpu10_BeginQuery(svga->swc, sq->id);
+   if (ret != PIPE_OK) {
+      svga_context_flush(svga, NULL);
+      ret = SVGA3D_vgpu10_BeginQuery(svga->swc, sq->id);
+   }
+   return ret;
+}
+
+static enum pipe_error
+end_query_vgpu10(struct svga_context *svga, struct svga_query *sq)
+{
+   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+   enum pipe_error ret = PIPE_OK;
+
+   if (svga->rebind.flags.query) {
+      rebind_vgpu10_query(svga);
+   }
+
+   ret = SVGA3D_vgpu10_EndQuery(svga->swc, sq->id);
+   if (ret != PIPE_OK) {
+      svga_context_flush(svga, NULL);
+      ret = SVGA3D_vgpu10_EndQuery(svga->swc, sq->id);
+   }
+
+   /* Finish fence is copied here from get_query_result_vgpu10. This helps
+    * with cases where svga_begin_query might be called again before
+    * svga_get_query_result, such as GL_TIME_ELAPSED.
+    */
+   if (!sq->fence) {
+      svga_context_flush(svga, &sq->fence);
+   }
+   sws->fence_finish(sws, sq->fence, SVGA_FENCE_FLAG_QUERY);
+
+   return ret;
+}
+
+static boolean
+get_query_result_vgpu10(struct svga_context *svga, struct svga_query *sq,
+                        boolean wait, void *result, int resultLen)
+{
+   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+   SVGA3dQueryState queryState;
+
+   if (svga->rebind.flags.query) {
+      rebind_vgpu10_query(svga);
+   }
+
+   sws->query_get_result(sws, sq->gb_query, sq->offset, &queryState, result, resultLen);
+
+   if (queryState == SVGA3D_QUERYSTATE_PENDING) {
+      if (!wait)
+         return FALSE;
+      sws->fence_finish(sws, sq->fence, SVGA_FENCE_FLAG_QUERY);
+      sws->query_get_result(sws, sq->gb_query, sq->offset, &queryState, result, resultLen);
+   }
+
+   assert(queryState == SVGA3D_QUERYSTATE_SUCCEEDED ||
+          queryState == SVGA3D_QUERYSTATE_FAILED);
+
+   return TRUE;
+}
 
 static struct pipe_query *
 svga_create_query(struct pipe_context *pipe,
                   unsigned query_type,
                   unsigned index)
 {
-   struct svga_context *svga = svga_context( pipe );
-   struct svga_screen *svgascreen = svga_screen(pipe->screen);
-   struct svga_winsys_screen *sws = svgascreen->sws;
+   struct svga_context *svga = svga_context(pipe);
    struct svga_query *sq;
 
-   SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__);
+   assert(query_type < SVGA_QUERY_MAX);
 
    sq = CALLOC_STRUCT(svga_query);
    if (!sq)
-      goto no_sq;
+      goto fail;
+
+   /* Allocate an integer ID for the query */
+   sq->id = util_bitmask_add(svga->query_id_bm);
+   if (sq->id == UTIL_BITMASK_INVALID_INDEX)
+      goto fail;
+
+   SVGA_DBG(DEBUG_QUERY, "%s type=%d sq=0x%x id=%d\n", __FUNCTION__,
+            query_type, sq, sq->id);
 
    switch (query_type) {
    case PIPE_QUERY_OCCLUSION_COUNTER:
       sq->svga_type = SVGA3D_QUERYTYPE_OCCLUSION;
+      if (svga_have_vgpu10(svga)) {
+         define_query_vgpu10(svga, sq, sizeof(SVGADXOcclusionQueryResult));
 
-      sq->hwbuf = svga_winsys_buffer_create(svga, 1,
-                                            SVGA_BUFFER_USAGE_PINNED,
-                                            sizeof *sq->queryResult);
-      if (!sq->hwbuf) {
-         debug_printf("svga: failed to alloc query object!\n");
-         goto no_hwbuf;
-      }
+         /**
+          * In OpenGL, occlusion counter query can be used in conditional
+          * rendering; however, in DX10, only OCCLUSION_PREDICATE query can
+          * be used for predication. Hence, we need to create an occlusion
+          * predicate query along with the occlusion counter query. So when
+          * the occlusion counter query is used for predication, the associated
+          * query of occlusion predicate type will be used
+          * in the SetPredication command.
+          */
+         sq->predicate = svga_create_query(pipe, PIPE_QUERY_OCCLUSION_PREDICATE, index);
 
-      sq->queryResult = (SVGA3dQueryResult *)
-         sws->buffer_map(sws, sq->hwbuf, PIPE_TRANSFER_WRITE);
-      if (!sq->queryResult) {
-         debug_printf("svga: failed to map query object!\n");
-         goto no_query_result;
+      } else {
+         define_query_vgpu9(svga, sq);
       }
-
-      sq->queryResult->totalSize = sizeof *sq->queryResult;
-      sq->queryResult->state = SVGA3D_QUERYSTATE_NEW;
-
-      /* We request the buffer to be pinned and assume it is always mapped.
-       * The reason is that we don't want to wait for fences when checking the
-       * query status.
-       */
-      sws->buffer_unmap(sws, sq->hwbuf);
+      break;
+   case PIPE_QUERY_OCCLUSION_PREDICATE:
+      assert(svga_have_vgpu10(svga));
+      sq->svga_type = SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE;
+      define_query_vgpu10(svga, sq, sizeof(SVGADXOcclusionPredicateQueryResult));
+      break;
+   case PIPE_QUERY_PRIMITIVES_GENERATED:
+   case PIPE_QUERY_PRIMITIVES_EMITTED:
+   case PIPE_QUERY_SO_STATISTICS:
+      assert(svga_have_vgpu10(svga));
+      sq->svga_type = SVGA3D_QUERYTYPE_STREAMOUTPUTSTATS;
+      define_query_vgpu10(svga, sq,
+                          sizeof(SVGADXStreamOutStatisticsQueryResult));
+      break;
+   case PIPE_QUERY_TIMESTAMP:
+      assert(svga_have_vgpu10(svga));
+      sq->svga_type = SVGA3D_QUERYTYPE_TIMESTAMP;
+      define_query_vgpu10(svga, sq,
+                          sizeof(SVGADXTimestampQueryResult));
       break;
    case SVGA_QUERY_DRAW_CALLS:
    case SVGA_QUERY_FALLBACKS:
@@ -129,28 +732,50 @@ svga_create_query(struct pipe_context *pipe,
 
    return &sq->base;
 
-no_query_result:
-   sws->buffer_destroy(sws, sq->hwbuf);
-no_hwbuf:
+fail:
    FREE(sq);
-no_sq:
    return NULL;
 }
 
-
 static void
 svga_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
 {
-   struct svga_screen *svgascreen = svga_screen(pipe->screen);
-   struct svga_winsys_screen *sws = svgascreen->sws;
-   struct svga_query *sq = svga_query( q );
+   struct svga_context *svga = svga_context(pipe);
+   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+   struct svga_query *sq;
 
-   SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__);
+   if (q == NULL) {
+      return destroy_gb_query_obj(svga);
+   }
+
+   sq = svga_query(q);
+
+   SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d\n", __FUNCTION__,
+            sq, sq->id);
 
    switch (sq->type) {
    case PIPE_QUERY_OCCLUSION_COUNTER:
-      sws->buffer_destroy(sws, sq->hwbuf);
-      sq->hwbuf = NULL;
+      if (svga_have_vgpu10(svga)) {
+         /* make sure to also destroy any associated predicate query */
+         if (sq->predicate)
+            svga_destroy_query(pipe, sq->predicate);
+         destroy_query_vgpu10(svga, sq);
+      } else {
+         sws->buffer_destroy(sws, sq->hwbuf);
+      }
+      sws->fence_reference(sws, &sq->fence, NULL);
+      break;
+   case PIPE_QUERY_OCCLUSION_PREDICATE:
+      assert(svga_have_vgpu10(svga));
+      destroy_query_vgpu10(svga, sq);
+      sws->fence_reference(sws, &sq->fence, NULL);
+      break;
+   case PIPE_QUERY_PRIMITIVES_GENERATED:
+   case PIPE_QUERY_PRIMITIVES_EMITTED:
+   case PIPE_QUERY_SO_STATISTICS:
+   case PIPE_QUERY_TIMESTAMP:
+      assert(svga_have_vgpu10(svga));
+      destroy_query_vgpu10(svga, sq);
       sws->fence_reference(sws, &sq->fence, NULL);
       break;
    case SVGA_QUERY_DRAW_CALLS:
@@ -162,6 +787,9 @@ svga_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
       assert(!"svga: unexpected query type in svga_destroy_query()");
    }
 
+   /* Free the query id */
+   util_bitmask_clear(svga->query_id_bm, sq->id);
+
    FREE(sq);
 }
 
@@ -169,13 +797,15 @@ svga_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
 static boolean
 svga_begin_query(struct pipe_context *pipe, struct pipe_query *q)
 {
-   struct svga_screen *svgascreen = svga_screen(pipe->screen);
-   struct svga_winsys_screen *sws = svgascreen->sws;
-   struct svga_context *svga = svga_context( pipe );
-   struct svga_query *sq = svga_query( q );
+   struct svga_context *svga = svga_context(pipe);
+   struct svga_query *sq = svga_query(q);
    enum pipe_error ret;
 
-   SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__);
+   assert(sq);
+   assert(sq->type < SVGA_QUERY_MAX);
+
+   SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d\n", __FUNCTION__,
+            sq, sq->id);
 
    /* Need to flush out buffered drawing commands so that they don't
     * get counted in the query results.
@@ -184,31 +814,33 @@ svga_begin_query(struct pipe_context *pipe, struct pipe_query *q)
 
    switch (sq->type) {
    case PIPE_QUERY_OCCLUSION_COUNTER:
-      assert(!svga->sq);
-      if (sq->queryResult->state == SVGA3D_QUERYSTATE_PENDING) {
-         /* The application doesn't care for the pending query result.
-          * We cannot let go of the existing buffer and just get a new one
-          * because its storage may be reused for other purposes and clobbered
-          * by the host when it determines the query result.  So the only
-          * option here is to wait for the existing query's result -- not a
-          * big deal, given that no sane application would do this.
-          */
-         uint64_t result;
-         svga_get_query_result(pipe, q, TRUE, (void*)&result);
-         assert(sq->queryResult->state != SVGA3D_QUERYSTATE_PENDING);
-      }
-
-      sq->queryResult->state = SVGA3D_QUERYSTATE_NEW;
-      sws->fence_reference(sws, &sq->fence, NULL);
-
-      ret = SVGA3D_BeginQuery(svga->swc, sq->svga_type);
-      if (ret != PIPE_OK) {
-         svga_context_flush(svga, NULL);
-         ret = SVGA3D_BeginQuery(svga->swc, sq->svga_type);
-         assert(ret == PIPE_OK);
+      if (svga_have_vgpu10(svga)) {
+         ret = begin_query_vgpu10(svga, sq);
+         /* also need to start the associated occlusion predicate query */
+         if (sq->predicate) {
+            enum pipe_error status;
+            status = begin_query_vgpu10(svga, svga_query(sq->predicate));
+            assert(status == PIPE_OK);
+            (void) status;
+         }
+      } else {
+         ret = begin_query_vgpu9(svga, sq);
       }
-
-      svga->sq = sq;
+      assert(ret == PIPE_OK);
+      (void) ret;
+      break;
+   case PIPE_QUERY_OCCLUSION_PREDICATE:
+      assert(svga_have_vgpu10(svga));
+      ret = begin_query_vgpu10(svga, sq);
+      assert(ret == PIPE_OK);
+      break;
+   case PIPE_QUERY_PRIMITIVES_GENERATED:
+   case PIPE_QUERY_PRIMITIVES_EMITTED:
+   case PIPE_QUERY_SO_STATISTICS:
+   case PIPE_QUERY_TIMESTAMP:
+      assert(svga_have_vgpu10(svga));
+      ret = begin_query_vgpu10(svga, sq);
+      assert(ret == PIPE_OK);
       break;
    case SVGA_QUERY_DRAW_CALLS:
       sq->begin_count = svga->num_draw_calls;
@@ -222,6 +854,9 @@ svga_begin_query(struct pipe_context *pipe, struct pipe_query *q)
    default:
       assert(!"unexpected query type in svga_begin_query()");
    }
+
+   svga->sq[sq->type] = sq;
+
    return true;
 }
 
@@ -229,35 +864,57 @@ svga_begin_query(struct pipe_context *pipe, struct pipe_query *q)
 static void
 svga_end_query(struct pipe_context *pipe, struct pipe_query *q)
 {
-   struct svga_context *svga = svga_context( pipe );
-   struct svga_query *sq = svga_query( q );
+   struct svga_context *svga = svga_context(pipe);
+   struct svga_query *sq = svga_query(q);
    enum pipe_error ret;
 
-   SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__);
+   assert(sq);
+   assert(sq->type < SVGA_QUERY_MAX);
+
+   SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d\n", __FUNCTION__,
+            sq, sq->id);
+
+   if (sq->type == PIPE_QUERY_TIMESTAMP && svga->sq[sq->type] != sq)
+      svga_begin_query(pipe, q);
 
    svga_hwtnl_flush_retry(svga);
 
+   assert(svga->sq[sq->type] == sq);
+
    switch (sq->type) {
    case PIPE_QUERY_OCCLUSION_COUNTER:
-      assert(svga->sq == sq);
-
-      /* Set to PENDING before sending EndQuery. */
-      sq->queryResult->state = SVGA3D_QUERYSTATE_PENDING;
-
-      ret = SVGA3D_EndQuery( svga->swc, sq->svga_type, sq->hwbuf);
-      if (ret != PIPE_OK) {
-         svga_context_flush(svga, NULL);
-         ret = SVGA3D_EndQuery( svga->swc, sq->svga_type, sq->hwbuf);
-         assert(ret == PIPE_OK);
+      if (svga_have_vgpu10(svga)) {
+         ret = end_query_vgpu10(svga, sq);
+         /* also need to end the associated occlusion predicate query */
+         if (sq->predicate) {
+            enum pipe_error status;
+            status = end_query_vgpu10(svga, svga_query(sq->predicate));
+            assert(status == PIPE_OK);
+            (void) status;
+         }
+      } else {
+         ret = end_query_vgpu9(svga, sq);
       }
-
+      assert(ret == PIPE_OK);
+      (void) ret;
       /* TODO: Delay flushing. We don't really need to flush here, just ensure
        * that there is one flush before svga_get_query_result attempts to get
        * the result.
        */
       svga_context_flush(svga, NULL);
-
-      svga->sq = NULL;
+      break;
+   case PIPE_QUERY_OCCLUSION_PREDICATE:
+      assert(svga_have_vgpu10(svga));
+      ret = end_query_vgpu10(svga, sq);
+      assert(ret == PIPE_OK);
+      break;
+   case PIPE_QUERY_PRIMITIVES_GENERATED:
+   case PIPE_QUERY_PRIMITIVES_EMITTED:
+   case PIPE_QUERY_SO_STATISTICS:
+   case PIPE_QUERY_TIMESTAMP:
+      assert(svga_have_vgpu10(svga));
+      ret = end_query_vgpu10(svga, sq);
+      assert(ret == PIPE_OK);
       break;
    case SVGA_QUERY_DRAW_CALLS:
       sq->end_count = svga->num_draw_calls;
@@ -271,6 +928,7 @@ svga_end_query(struct pipe_context *pipe, struct pipe_query *q)
    default:
       assert(!"unexpected query type in svga_end_query()");
    }
+   svga->sq[sq->type] = NULL;
 }
 
 
@@ -280,49 +938,75 @@ svga_get_query_result(struct pipe_context *pipe,
                       boolean wait,
                       union pipe_query_result *vresult)
 {
-   struct svga_context *svga = svga_context( pipe );
-   struct svga_screen *svgascreen = svga_screen( pipe->screen );
-   struct svga_winsys_screen *sws = svgascreen->sws;
-   struct svga_query *sq = svga_query( q );
-   SVGA3dQueryState state;
-   uint64_t *result = (uint64_t *) vresult;
+   struct svga_screen *svgascreen = svga_screen(pipe->screen);
+   struct svga_context *svga = svga_context(pipe);
+   struct svga_query *sq = svga_query(q);
+   uint64_t *result = (uint64_t *)vresult;
+   boolean ret = TRUE;
+
+   assert(sq);
 
-   SVGA_DBG(DEBUG_QUERY, "%s wait: %d\n", __FUNCTION__);
+   SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d wait: %d\n",
+            __FUNCTION__, sq, sq->id, wait);
 
    switch (sq->type) {
    case PIPE_QUERY_OCCLUSION_COUNTER:
-      /* The query status won't be updated by the host unless
-       * SVGA_3D_CMD_WAIT_FOR_QUERY is emitted. Unfortunately this will cause
-       * a synchronous wait on the host.
-       */
-      if (!sq->fence) {
-         enum pipe_error ret;
-
-         ret = SVGA3D_WaitForQuery( svga->swc, sq->svga_type, sq->hwbuf);
-         if (ret != PIPE_OK) {
-            svga_context_flush(svga, NULL);
-            ret = SVGA3D_WaitForQuery( svga->swc, sq->svga_type, sq->hwbuf);
-            assert(ret == PIPE_OK);
-         }
-
-         svga_context_flush(svga, &sq->fence);
-
-         assert(sq->fence);
+      if (svga_have_vgpu10(svga)) {
+         SVGADXOcclusionQueryResult occResult;
+         ret = get_query_result_vgpu10(svga, sq, wait,
+                                       (void *)&occResult, sizeof(occResult));
+         *result = (uint64_t)occResult.samplesRendered;
+      } else {
+         ret = get_query_result_vgpu9(svga, sq, wait, (uint64_t *)result);
       }
+      break;
+   case PIPE_QUERY_OCCLUSION_PREDICATE: {
+      SVGADXOcclusionPredicateQueryResult occResult;
+      assert(svga_have_vgpu10(svga));
+      ret = get_query_result_vgpu10(svga, sq, wait,
+                                    (void *)&occResult, sizeof(occResult));
+      vresult->b = occResult.anySamplesRendered != 0;
+      break;
+   }
+   case PIPE_QUERY_SO_STATISTICS: {
+      SVGADXStreamOutStatisticsQueryResult sResult;
+      struct pipe_query_data_so_statistics *pResult =
+         (struct pipe_query_data_so_statistics *)vresult;
 
-      state = sq->queryResult->state;
-      if (state == SVGA3D_QUERYSTATE_PENDING) {
-         if (!wait)
-            return FALSE;
-         sws->fence_finish(sws, sq->fence, SVGA_FENCE_FLAG_QUERY);
-         state = sq->queryResult->state;
-      }
+      assert(svga_have_vgpu10(svga));
+      ret = get_query_result_vgpu10(svga, sq, wait,
+                                    (void *)&sResult, sizeof(sResult));
+      pResult->num_primitives_written = sResult.numPrimitivesWritten;
+      pResult->primitives_storage_needed = sResult.numPrimitivesRequired;
+      break;
+   }
+   case PIPE_QUERY_TIMESTAMP: {
+      SVGADXTimestampQueryResult sResult;
+
+      assert(svga_have_vgpu10(svga));
+      ret = get_query_result_vgpu10(svga, sq, wait,
+                                    (void *)&sResult, sizeof(sResult));
+      *result = (uint64_t)sResult.timestamp;
+      break;
+   }
+   case PIPE_QUERY_PRIMITIVES_GENERATED: {
+      SVGADXStreamOutStatisticsQueryResult sResult;
 
-      assert(state == SVGA3D_QUERYSTATE_SUCCEEDED ||
-             state == SVGA3D_QUERYSTATE_FAILED);
+      assert(svga_have_vgpu10(svga));
+      ret = get_query_result_vgpu10(svga, sq, wait,
+                                    (void *)&sResult, sizeof sResult);
+      *result = (uint64_t)sResult.numPrimitivesRequired;
+      break;
+   }
+   case PIPE_QUERY_PRIMITIVES_EMITTED: {
+      SVGADXStreamOutStatisticsQueryResult sResult;
 
-      *result = (uint64_t) sq->queryResult->result32;
+      assert(svga_have_vgpu10(svga));
+      ret = get_query_result_vgpu10(svga, sq, wait,
+                                    (void *)&sResult, sizeof sResult);
+      *result = (uint64_t)sResult.numPrimitivesWritten;
       break;
+   }
    case SVGA_QUERY_DRAW_CALLS:
       /* fall-through */
    case SVGA_QUERY_FALLBACKS:
@@ -335,9 +1019,73 @@ svga_get_query_result(struct pipe_context *pipe,
       assert(!"unexpected query type in svga_get_query_result");
    }
 
-   SVGA_DBG(DEBUG_QUERY, "%s result %d\n", __FUNCTION__, (unsigned)*result);
+   SVGA_DBG(DEBUG_QUERY, "%s result %d\n", __FUNCTION__, *((uint64_t *)vresult));
 
-   return TRUE;
+   return ret;
+}
+
+static void
+svga_render_condition(struct pipe_context *pipe, struct pipe_query *q,
+                      boolean condition, uint mode)
+{
+   struct svga_context *svga = svga_context(pipe);
+   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+   struct svga_query *sq = svga_query(q);
+   SVGA3dQueryId queryId;
+   enum pipe_error ret;
+
+   SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__);
+
+   assert(svga_have_vgpu10(svga));
+   if (sq == NULL) {
+      queryId = SVGA3D_INVALID_ID;
+   }
+   else {
+      assert(sq->svga_type == SVGA3D_QUERYTYPE_OCCLUSION ||
+             sq->svga_type == SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE);
+
+      if (sq->svga_type == SVGA3D_QUERYTYPE_OCCLUSION) {
+         assert(sq->predicate);
+         /**
+          * For conditional rendering, make sure to use the associated
+          * predicate query.
+          */
+         sq = svga_query(sq->predicate);
+      }
+      queryId = sq->id;
+
+      if ((mode == PIPE_RENDER_COND_WAIT ||
+           mode == PIPE_RENDER_COND_BY_REGION_WAIT) && sq->fence) {
+         sws->fence_finish(sws, sq->fence, SVGA_FENCE_FLAG_QUERY);
+      }
+   }
+
+   ret = SVGA3D_vgpu10_SetPredication(svga->swc, queryId,
+                                      (uint32) condition);
+   if (ret != PIPE_OK) {
+      svga_context_flush(svga, NULL);
+      ret = SVGA3D_vgpu10_SetPredication(svga->swc, queryId,
+                                         (uint32) condition);
+   }
+}
+
+
+/*
+ * This function is a workaround because we lack the ability to query
+ * renderer's time synchornously.
+ */
+static uint64_t
+svga_get_timestamp(struct pipe_context *pipe)
+{
+   struct pipe_query *q = svga_create_query(pipe, PIPE_QUERY_TIMESTAMP, 0);
+   union pipe_query_result result;
+
+   svga_begin_query(pipe, q);
+   svga_end_query(pipe,q);
+   svga_get_query_result(pipe, q, TRUE, &result);
+   svga_destroy_query(pipe, q);
+
+   return result.u64;
 }
 
 
@@ -349,4 +1097,6 @@ svga_init_query_functions(struct svga_context *svga)
    svga->pipe.begin_query = svga_begin_query;
    svga->pipe.end_query = svga_end_query;
    svga->pipe.get_query_result = svga_get_query_result;
+   svga->pipe.render_condition = svga_render_condition;
+   svga->pipe.get_timestamp = svga_get_timestamp;
 }
index 356898a86e7ef2bb484539def9f611897c20e34c..a7aadac0111ae7b9290d7fed44fe146755987ada 100644 (file)
  *
  **********************************************************/
 
+#include "pipe/p_defines.h"
 #include "draw/draw_context.h"
+#include "util/u_bitmask.h"
 #include "util/u_inlines.h"
-#include "pipe/p_defines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 
+#include "svga_cmd.h"
 #include "svga_context.h"
+#include "svga_hw_reg.h"
 #include "svga_screen.h"
 
-#include "svga_hw_reg.h"
 
 /* Hardware frontwinding is always set up as SVGA3D_FRONTWINDING_CW.
  */
@@ -61,6 +63,96 @@ static SVGA3dShadeMode svga_translate_flatshade( unsigned mode )
 }
 
 
+static unsigned
+translate_fill_mode(unsigned fill)
+{
+   switch (fill) {
+   case PIPE_POLYGON_MODE_POINT:
+      return SVGA3D_FILLMODE_POINT;
+   case PIPE_POLYGON_MODE_LINE:
+      return SVGA3D_FILLMODE_LINE;
+   case PIPE_POLYGON_MODE_FILL:
+      return SVGA3D_FILLMODE_FILL;
+   default:
+      assert(!"Bad fill mode");
+      return SVGA3D_FILLMODE_FILL;
+   }
+}
+
+
+static unsigned
+translate_cull_mode(unsigned cull)
+{
+   switch (cull) {
+   case PIPE_FACE_NONE:
+      return SVGA3D_CULL_NONE;
+   case PIPE_FACE_FRONT:
+      return SVGA3D_CULL_FRONT;
+   case PIPE_FACE_BACK:
+      return SVGA3D_CULL_BACK;
+   case PIPE_FACE_FRONT_AND_BACK:
+      /* NOTE: we simply no-op polygon drawing in svga_draw_vbo() */
+      return SVGA3D_CULL_NONE;
+   default:
+      assert(!"Bad cull mode");
+      return SVGA3D_CULL_NONE;
+   }
+}
+
+
+static void
+define_rasterizer_object(struct svga_context *svga,
+                         struct svga_rasterizer_state *rast)
+{
+   unsigned fill_mode = translate_fill_mode(rast->templ.fill_front);
+   unsigned cull_mode = translate_cull_mode(rast->templ.cull_face);
+   int depth_bias = rast->templ.offset_units;
+   float slope_scaled_depth_bias =  rast->templ.offset_scale;
+   float depth_bias_clamp = 0.0; /* XXX fix me */
+   unsigned try;
+   const float line_width = rast->templ.line_width > 0.0f ?
+      rast->templ.line_width : 1.0f;
+   const uint8 line_factor = rast->templ.line_stipple_enable ?
+      rast->templ.line_stipple_factor : 0;
+   const uint16 line_pattern = rast->templ.line_stipple_enable ?
+      rast->templ.line_stipple_pattern : 0;
+
+   rast->id = util_bitmask_add(svga->rast_object_id_bm);
+
+   if (rast->templ.fill_front != rast->templ.fill_back) {
+      /* The VGPU10 device can't handle different front/back fill modes.
+       * We'll handle that with a swtnl/draw fallback.  But we need to
+       * make sure we always fill triangles in that case.
+       */
+      fill_mode = SVGA3D_FILLMODE_FILL;
+   }
+
+   for (try = 0; try < 2; try++) {
+      enum pipe_error ret =
+         SVGA3D_vgpu10_DefineRasterizerState(svga->swc,
+                                             rast->id,
+                                             fill_mode,
+                                             cull_mode,
+                                             rast->templ.front_ccw,
+                                             depth_bias,
+                                             depth_bias_clamp,
+                                             slope_scaled_depth_bias,
+                                             rast->templ.depth_clip,
+                                             rast->templ.scissor,
+                                             rast->templ.multisample,
+                                             rast->templ.line_smooth,
+                                             line_width,
+                                             rast->templ.line_stipple_enable,
+                                             line_factor,
+                                             line_pattern,
+                                             !rast->templ.flatshade_first);
+      if (ret == PIPE_OK)
+         return;
+      svga_context_flush(svga, NULL);
+   }
+}
+
+
 static void *
 svga_create_rasterizer_state(struct pipe_context *pipe,
                              const struct pipe_rasterizer_state *templ)
@@ -92,17 +184,24 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
    rast->antialiasedlineenable = templ->line_smooth;
    rast->lastpixel = templ->line_last_pixel;
    rast->pointsprite = templ->sprite_coord_enable != 0x0;
-   rast->pointsize = templ->point_size;
-   rast->hw_unfilled = PIPE_POLYGON_MODE_FILL;
+
+   if (templ->point_smooth) {
+      /* For smooth points we need to generate fragments for at least
+       * a 2x2 region.  Otherwise the quad we draw may be too small and
+       * we may generate no fragments at all.
+       */
+      rast->pointsize = MAX2(2.0f, templ->point_size);
+   }
+   else {
+      rast->pointsize = templ->point_size;
+   }
+
+   rast->hw_fillmode = PIPE_POLYGON_MODE_FILL;
 
    /* Use swtnl + decomposition implement these:
     */
-   if (templ->poly_stipple_enable) {
-      rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
-      rast->need_pipeline_tris_str = "poly stipple";
-   }
 
-   if (screen->maxLineWidth > 1.0F) {
+   if (templ->line_width <= screen->maxLineWidth) {
       /* pass line width to device */
       rast->linewidth = MAX2(1.0F, templ->line_width);
    }
@@ -129,7 +228,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
       }
    } 
 
-   if (templ->point_smooth) {
+   if (!svga_have_vgpu10(svga) && templ->point_smooth) {
       rast->need_pipeline |= SVGA_PIPELINE_FLAG_POINTS;
       rast->need_pipeline_points_str = "smooth points";
    }
@@ -231,13 +330,13 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
          rast->depthbias = templ->offset_units;
       }
 
-      rast->hw_unfilled = fill;
+      rast->hw_fillmode = fill;
    }
 
    if (rast->need_pipeline & SVGA_PIPELINE_FLAG_TRIS) {
       /* Turn off stuff which will get done in the draw module:
        */
-      rast->hw_unfilled = PIPE_POLYGON_MODE_FILL;
+      rast->hw_fillmode = PIPE_POLYGON_MODE_FILL;
       rast->slopescaledepthbias = 0;
       rast->depthbias = 0;
    }
@@ -249,6 +348,10 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
       debug_printf(" tris: %s \n", rast->need_pipeline_tris_str);
    }
 
+   if (svga_have_vgpu10(svga)) {
+      define_rasterizer_object(svga, rast);
+   }
+
    return rast;
 }
 
@@ -258,18 +361,37 @@ static void svga_bind_rasterizer_state( struct pipe_context *pipe,
    struct svga_context *svga = svga_context(pipe);
    struct svga_rasterizer_state *raster = (struct svga_rasterizer_state *)state;
 
-
-   draw_set_rasterizer_state(svga->swtnl.draw, raster ? &raster->templ : NULL,
-                             state);
    svga->curr.rast = raster;
 
    svga->dirty |= SVGA_NEW_RAST;
+
+   if (raster && raster->templ.poly_stipple_enable) {
+      svga->dirty |= SVGA_NEW_STIPPLE;
+   }
 }
 
-static void svga_delete_rasterizer_state(struct pipe_context *pipe,
-                                         void *raster)
+static void
+svga_delete_rasterizer_state(struct pipe_context *pipe, void *state)
 {
-   FREE(raster);
+   struct svga_context *svga = svga_context(pipe);
+   struct svga_rasterizer_state *raster =
+      (struct svga_rasterizer_state *) state;
+
+   if (svga_have_vgpu10(svga)) {
+      enum pipe_error ret =
+         SVGA3D_vgpu10_DestroyRasterizerState(svga->swc, raster->id);
+      if (ret != PIPE_OK) {
+         svga_context_flush(svga, NULL);
+         ret = SVGA3D_vgpu10_DestroyRasterizerState(svga->swc, raster->id);
+      }
+
+      if (raster->id == svga->state.hw_draw.rasterizer_id)
+         svga->state.hw_draw.rasterizer_id = SVGA3D_INVALID_ID;
+
+      util_bitmask_clear(svga->rast_object_id_bm, raster->id);
+   }
+
+   FREE(state);
 }
 
 
index effd490dd22d2c09ce46cac8d6353a3f9b474799..bb18f5a8247f62cc871e686d1cc6dbe3e81ebef7 100644 (file)
  *
  **********************************************************/
 
-#include "util/u_inlines.h"
 #include "pipe/p_defines.h"
+#include "util/u_bitmask.h"
 #include "util/u_format.h"
+#include "util/u_inlines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 #include "tgsi/tgsi_parse.h"
 
 #include "svga_context.h"
+#include "svga_cmd.h"
+#include "svga_debug.h"
 #include "svga_resource_texture.h"
 
-#include "svga_debug.h"
 
 static inline unsigned
 translate_wrap_mode(unsigned wrap)
@@ -91,6 +93,126 @@ static inline unsigned translate_mip_filter( unsigned filter )
    }
 }
 
+
+static uint8
+translate_comparison_func(unsigned func)
+{
+   switch (func) {
+   case PIPE_FUNC_NEVER:
+      return SVGA3D_COMPARISON_NEVER;
+   case PIPE_FUNC_LESS:
+      return SVGA3D_COMPARISON_LESS;
+   case PIPE_FUNC_EQUAL:
+      return SVGA3D_COMPARISON_EQUAL;
+   case PIPE_FUNC_LEQUAL:
+      return SVGA3D_COMPARISON_LESS_EQUAL;
+   case PIPE_FUNC_GREATER:
+      return SVGA3D_COMPARISON_GREATER;
+   case PIPE_FUNC_NOTEQUAL:
+      return SVGA3D_COMPARISON_NOT_EQUAL;
+   case PIPE_FUNC_GEQUAL:
+      return SVGA3D_COMPARISON_GREATER_EQUAL;
+   case PIPE_FUNC_ALWAYS:
+      return SVGA3D_COMPARISON_ALWAYS;
+   default:
+      assert(!"Invalid comparison function");
+      return SVGA3D_COMPARISON_ALWAYS;
+   }
+}
+
+
+/**
+ * Translate filtering state to vgpu10 format.
+ */
+static SVGA3dFilter
+translate_filter_mode(unsigned img_filter,
+                      unsigned min_filter,
+                      unsigned mag_filter,
+                      boolean anisotropic,
+                      boolean compare)
+{
+   SVGA3dFilter mode = 0;
+
+   if (img_filter == PIPE_TEX_FILTER_LINEAR)
+      mode |= SVGA3D_FILTER_MIP_LINEAR;
+   if (min_filter == PIPE_TEX_FILTER_LINEAR)
+      mode |= SVGA3D_FILTER_MIN_LINEAR;
+   if (mag_filter == PIPE_TEX_FILTER_LINEAR)
+      mode |= SVGA3D_FILTER_MAG_LINEAR;
+   if (anisotropic)
+      mode |= SVGA3D_FILTER_ANISOTROPIC;
+   if (compare)
+      mode |= SVGA3D_FILTER_COMPARE;
+
+   return mode;
+}
+
+
+/**
+ * Define a vgpu10 sampler state.
+ */
+static void
+define_sampler_state_object(struct svga_context *svga,
+                            struct svga_sampler_state *ss,
+                            const struct pipe_sampler_state *ps)
+{
+   uint8_t max_aniso = (uint8_t) 255; /* XXX fix me */
+   boolean anisotropic;
+   uint8 compare_func;
+   SVGA3dFilter filter;
+   SVGA3dRGBAFloat bcolor;
+   unsigned try;
+   float min_lod, max_lod;
+
+   assert(svga_have_vgpu10(svga));
+
+   anisotropic = ss->aniso_level > 1.0f;
+
+   filter = translate_filter_mode(ps->min_mip_filter,
+                                  ps->min_img_filter,
+                                  ps->mag_img_filter,
+                                  anisotropic,
+                                  ss->compare_mode);
+
+   compare_func = translate_comparison_func(ss->compare_func);
+
+   COPY_4V(bcolor.value, ps->border_color.f);
+
+   ss->id = util_bitmask_add(svga->sampler_object_id_bm);
+
+   assert(ps->min_lod <= ps->max_lod);
+
+   if (ps->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
+      /* just use the base level image */
+      min_lod = max_lod = 0.0f;
+   }
+   else {
+      min_lod = ps->min_lod;
+      max_lod = ps->max_lod;
+   }
+
+   /* Loop in case command buffer is full and we need to flush and retry */
+   for (try = 0; try < 2; try++) {
+      enum pipe_error ret =
+         SVGA3D_vgpu10_DefineSamplerState(svga->swc,
+                                          ss->id,
+                                          filter,
+                                          ss->addressu,
+                                          ss->addressv,
+                                          ss->addressw,
+                                          ss->lod_bias, /* float */
+                                          max_aniso,
+                                          compare_func,
+                                          bcolor,
+                                          min_lod,       /* float */
+                                          max_lod);      /* float */
+      if (ret == PIPE_OK)
+         return;
+      svga_context_flush(svga, NULL);
+   }
+}
+
+
 static void *
 svga_create_sampler_state(struct pipe_context *pipe,
                           const struct pipe_sampler_state *sampler)
@@ -141,6 +263,10 @@ svga_create_sampler_state(struct pipe_context *pipe,
       }
    }
 
+   if (svga_have_vgpu10(svga)) {
+      define_sampler_state_object(svga, cso, sampler);
+   }
+
    SVGA_DBG(DEBUG_VIEWS, "min %u, view(min %u, max %u) lod, mipfilter %s\n",
             cso->min_lod, cso->view_min_lod, cso->view_max_lod,
             cso->mipfilter == SVGA3D_TEX_FILTER_NONE ? "SVGA3D_TEX_FILTER_NONE" : "SOMETHING");
@@ -161,19 +287,19 @@ svga_bind_sampler_states(struct pipe_context *pipe,
    assert(shader < PIPE_SHADER_TYPES);
    assert(start + num <= PIPE_MAX_SAMPLERS);
 
-   /* we only support fragment shader samplers at this time */
-   if (shader != PIPE_SHADER_FRAGMENT)
+   /* Pre-VGPU10 only supports FS textures */
+   if (!svga_have_vgpu10(svga) && shader != PIPE_SHADER_FRAGMENT)
       return;
 
    for (i = 0; i < num; i++)
-      svga->curr.sampler[start + i] = samplers[i];
+      svga->curr.sampler[shader][start + i] = samplers[i];
 
    /* find highest non-null sampler[] entry */
    {
-      unsigned j = MAX2(svga->curr.num_samplers, start + num);
-      while (j > 0 && svga->curr.sampler[j - 1] == NULL)
+      unsigned j = MAX2(svga->curr.num_samplers[shader], start + num);
+      while (j > 0 && svga->curr.sampler[shader][j - 1] == NULL)
          j--;
-      svga->curr.num_samplers = j;
+      svga->curr.num_samplers[shader] = j;
    }
 
    svga->dirty |= SVGA_NEW_SAMPLER;
@@ -183,6 +309,22 @@ svga_bind_sampler_states(struct pipe_context *pipe,
 static void svga_delete_sampler_state(struct pipe_context *pipe,
                                       void *sampler)
 {
+   struct svga_sampler_state *ss = (struct svga_sampler_state *) sampler;
+   struct svga_context *svga = svga_context(pipe);
+
+   if (svga_have_vgpu10(svga)) {
+      enum pipe_error ret;
+
+      svga_hwtnl_flush_retry(svga);
+
+      ret = SVGA3D_vgpu10_DestroySamplerState(svga->swc, ss->id);
+      if (ret != PIPE_OK) {
+         svga_context_flush(svga, NULL);
+         ret = SVGA3D_vgpu10_DestroySamplerState(svga->swc, ss->id);
+      }
+      util_bitmask_clear(svga->sampler_object_id_bm, ss->id);
+   }
+
    FREE(sampler);
 }
 
@@ -192,17 +334,21 @@ svga_create_sampler_view(struct pipe_context *pipe,
                          struct pipe_resource *texture,
                          const struct pipe_sampler_view *templ)
 {
-   struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
-
-   if (view) {
-      *view = *templ;
-      view->reference.count = 1;
-      view->texture = NULL;
-      pipe_resource_reference(&view->texture, texture);
-      view->context = pipe;
+   struct svga_pipe_sampler_view *sv = CALLOC_STRUCT(svga_pipe_sampler_view);
+
+   if (!sv) {
+      return NULL;
    }
 
-   return view;
+   sv->base = *templ;
+   sv->base.reference.count = 1;
+   sv->base.texture = NULL;
+   pipe_resource_reference(&sv->base.texture, texture);
+
+   sv->base.context = pipe;
+   sv->id = SVGA3D_INVALID_ID;
+
+   return &sv->base;
 }
 
 
@@ -210,8 +356,37 @@ static void
 svga_sampler_view_destroy(struct pipe_context *pipe,
                           struct pipe_sampler_view *view)
 {
-   pipe_resource_reference(&view->texture, NULL);
-   FREE(view);
+   struct svga_context *svga = svga_context(pipe);
+   struct svga_pipe_sampler_view *sv = svga_pipe_sampler_view(view);
+
+   if (svga_have_vgpu10(svga) && sv->id != SVGA3D_INVALID_ID) {
+      if (view->context != pipe) {
+         /* The SVGA3D device will generate an error (and on Linux, cause
+          * us to abort) if we try to destroy a shader resource view from
+          * a context other than the one it was created with.  Skip the
+          * SVGA3D_vgpu10_DestroyShaderResourceView() and leak the sampler
+          * view for now.  This should only sometimes happen when a shared
+          * texture is deleted.
+          */
+         _debug_printf("context mismatch in %s\n", __func__);
+      }
+      else {
+         enum pipe_error ret;
+
+         svga_hwtnl_flush_retry(svga); /* XXX is this needed? */
+
+         ret = SVGA3D_vgpu10_DestroyShaderResourceView(svga->swc, sv->id);
+         if (ret != PIPE_OK) {
+            svga_context_flush(svga, NULL);
+            ret = SVGA3D_vgpu10_DestroyShaderResourceView(svga->swc, sv->id);
+         }
+         util_bitmask_clear(svga->sampler_view_id_bm, sv->id);
+      }
+   }
+
+   pipe_resource_reference(&sv->base.texture, NULL);
+
+   FREE(sv);
 }
 
 static void
@@ -227,20 +402,20 @@ svga_set_sampler_views(struct pipe_context *pipe,
    uint i;
 
    assert(shader < PIPE_SHADER_TYPES);
-   assert(start + num <= Elements(svga->curr.sampler_views));
+   assert(start + num <= Elements(svga->curr.sampler_views[shader]));
 
-   /* we only support fragment shader sampler views at this time */
-   if (shader != PIPE_SHADER_FRAGMENT)
+   /* Pre-VGPU10 only supports FS textures */
+   if (!svga_have_vgpu10(svga) && shader != PIPE_SHADER_FRAGMENT)
       return;
 
    for (i = 0; i < num; i++) {
-      if (svga->curr.sampler_views[start + i] != views[i]) {
+      if (svga->curr.sampler_views[shader][start + i] != views[i]) {
          /* Note: we're using pipe_sampler_view_release() here to work around
           * a possible crash when the old view belongs to another context that
           * was already destroyed.
           */
-         pipe_sampler_view_release(pipe, &svga->curr.sampler_views[start + i]);
-         pipe_sampler_view_reference(&svga->curr.sampler_views[start + i],
+         pipe_sampler_view_release(pipe, &svga->curr.sampler_views[shader][start + i]);
+         pipe_sampler_view_reference(&svga->curr.sampler_views[shader][start + i],
                                      views[i]);
       }
 
@@ -256,10 +431,10 @@ svga_set_sampler_views(struct pipe_context *pipe,
 
    /* find highest non-null sampler_views[] entry */
    {
-      unsigned j = MAX2(svga->curr.num_sampler_views, start + num);
-      while (j > 0 && svga->curr.sampler_views[j - 1] == NULL)
+      unsigned j = MAX2(svga->curr.num_sampler_views[shader], start + num);
+      while (j > 0 && svga->curr.sampler_views[shader][j - 1] == NULL)
          j--;
-      svga->curr.num_sampler_views = j;
+      svga->curr.num_sampler_views[shader] = j;
    }
 
    svga->dirty |= SVGA_NEW_TEXTURE_BINDING;
index 05672a95165bc470193eeed71056d7bcaf542ab5..1da63204428d90f2da9926a88acea9e8476e69b8 100644 (file)
@@ -38,7 +38,7 @@ struct svga_stream_output_target {
 };
 
 /** cast wrapper */
-static INLINE struct svga_stream_output_target *
+static inline struct svga_stream_output_target *
 svga_stream_output_target(struct pipe_stream_output_target *s)
 {
    return (struct svga_stream_output_target *)s;
index faf77f3ab630391609d9eb15eab48241c5187099..e0932a9dbc1eea24e7669a4376197b3be66f3dbb 100644 (file)
  *
  **********************************************************/
 
+#include "pipe/p_defines.h"
+#include "util/u_bitmask.h"
+#include "util/u_format.h"
 #include "util/u_helpers.h"
 #include "util/u_inlines.h"
-#include "pipe/p_defines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 #include "util/u_transfer.h"
 #include "tgsi/tgsi_parse.h"
 
-#include "svga_screen.h"
-#include "svga_resource_buffer.h"
 #include "svga_context.h"
+#include "svga_cmd.h"
+#include "svga_format.h"
+#include "svga_resource_buffer.h"
+#include "svga_screen.h"
 
 
 static void svga_set_vertex_buffers(struct pipe_context *pipe,
@@ -55,25 +59,33 @@ static void svga_set_index_buffer(struct pipe_context *pipe,
 {
    struct svga_context *svga = svga_context(pipe);
 
-   if (ib) {
-      pipe_resource_reference(&svga->curr.ib.buffer, ib->buffer);
-      memcpy(&svga->curr.ib, ib, sizeof(svga->curr.ib));
-   }
-   else {
-      pipe_resource_reference(&svga->curr.ib.buffer, NULL);
-      memset(&svga->curr.ib, 0, sizeof(svga->curr.ib));
-   }
+   util_set_index_buffer(&svga->curr.ib, ib);
+}
 
-   /* TODO make this more like a state */
+
+/**
+ * Does the given vertex attrib format need range adjustment in the VS?
+ * Range adjustment scales and biases values from [0,1] to [-1,1].
+ * This lets us avoid the swtnl path.
+ */
+static boolean
+attrib_needs_range_adjustment(enum pipe_format format)
+{
+   switch (format) {
+   case PIPE_FORMAT_R8G8B8_SNORM:
+      return TRUE;
+   default:
+      return FALSE;
+   }
 }
 
 
 /**
- * Given a gallium vertex element format, return the corresponding SVGA3D
- * format.  Return SVGA3D_DECLTYPE_MAX for unsupported gallium formats.
+ * Given a gallium vertex element format, return the corresponding
+ * SVGA3dDeclType.
  */
 static SVGA3dDeclType
-translate_vertex_format(enum pipe_format format)
+translate_vertex_format_to_decltype(enum pipe_format format)
 {
    switch (format) {
    case PIPE_FORMAT_R32_FLOAT:            return SVGA3D_DECLTYPE_FLOAT1;
@@ -94,10 +106,10 @@ translate_vertex_format(enum pipe_format format)
    case PIPE_FORMAT_R16G16_FLOAT:         return SVGA3D_DECLTYPE_FLOAT16_2;
    case PIPE_FORMAT_R16G16B16A16_FLOAT:   return SVGA3D_DECLTYPE_FLOAT16_4;
 
-   /* See attrib_needs_adjustment() and attrib_needs_w_to_1() below */
+   /* See attrib_needs_adjustment() and attrib_needs_w_to_1() above */
    case PIPE_FORMAT_R8G8B8_SNORM:         return SVGA3D_DECLTYPE_UBYTE4N;
 
-   /* See attrib_needs_w_to_1() below */
+   /* See attrib_needs_w_to_1() above */
    case PIPE_FORMAT_R16G16B16_SNORM:      return SVGA3D_DECLTYPE_SHORT4N;
    case PIPE_FORMAT_R16G16B16_UNORM:      return SVGA3D_DECLTYPE_USHORT4N;
    case PIPE_FORMAT_R8G8B8_UNORM:         return SVGA3D_DECLTYPE_UBYTE4N;
@@ -111,38 +123,121 @@ translate_vertex_format(enum pipe_format format)
 }
 
 
-/**
- * Does the given vertex attrib format need range adjustment in the VS?
- * Range adjustment scales and biases values from [0,1] to [-1,1].
- * This lets us avoid the swtnl path.
- */
-static boolean
-attrib_needs_range_adjustment(enum pipe_format format)
+static void
+define_input_element_object(struct svga_context *svga,
+                            struct svga_velems_state *velems)
 {
-   switch (format) {
-   case PIPE_FORMAT_R8G8B8_SNORM:
-      return TRUE;
-   default:
-      return FALSE;
+   SVGA3dInputElementDesc elements[PIPE_MAX_ATTRIBS];
+   enum pipe_error ret;
+   unsigned i;
+
+   assert(velems->count <= PIPE_MAX_ATTRIBS);
+   assert(svga_have_vgpu10(svga));
+
+   for (i = 0; i < velems->count; i++) {
+      const struct pipe_vertex_element *elem = velems->velem + i;
+      SVGA3dSurfaceFormat svga_format;
+      unsigned vf_flags;
+
+      svga_translate_vertex_format_vgpu10(elem->src_format,
+                                          &svga_format, &vf_flags);
+
+      velems->decl_type[i] =
+         translate_vertex_format_to_decltype(elem->src_format);
+      elements[i].inputSlot = elem->vertex_buffer_index;
+      elements[i].alignedByteOffset = elem->src_offset;
+      elements[i].format = svga_format;
+
+      if (elem->instance_divisor) {
+         elements[i].inputSlotClass = SVGA3D_INPUT_PER_INSTANCE_DATA;
+         elements[i].instanceDataStepRate = elem->instance_divisor;
+      }
+      else {
+         elements[i].inputSlotClass = SVGA3D_INPUT_PER_VERTEX_DATA;
+         elements[i].instanceDataStepRate = 0;
+      }
+      elements[i].inputRegister = i;
+
+      if (elements[i].format == SVGA3D_FORMAT_INVALID) {
+         velems->need_swvfetch = TRUE;
+      }
+
+      if (util_format_is_pure_integer(elem->src_format)) {
+         velems->attrib_is_pure_int |= (1 << i);
+      }
+
+      if (vf_flags & VF_W_TO_1) {
+         velems->adjust_attrib_w_1 |= (1 << i);
+      }
+
+      if (vf_flags & VF_U_TO_F_CAST) {
+         velems->adjust_attrib_utof |= (1 << i);
+      }
+      else if (vf_flags & VF_I_TO_F_CAST) {
+         velems->adjust_attrib_itof |= (1 << i);
+      }
+
+      if (vf_flags & VF_BGRA) {
+         velems->attrib_is_bgra |= (1 << i);
+      }
+
+      if (vf_flags & VF_PUINT_TO_SNORM) {
+         velems->attrib_puint_to_snorm |= (1 << i);
+      }
+      else if (vf_flags & VF_PUINT_TO_USCALED) {
+         velems->attrib_puint_to_uscaled |= (1 << i);
+      }
+      else if (vf_flags & VF_PUINT_TO_SSCALED) {
+         velems->attrib_puint_to_sscaled |= (1 << i);
+      }
+   }
+
+   velems->id = util_bitmask_add(svga->input_element_object_id_bm);
+
+   ret = SVGA3D_vgpu10_DefineElementLayout(svga->swc, velems->count,
+                                           velems->id, elements);
+   if (ret != PIPE_OK) {
+      svga_context_flush(svga, NULL);
+      ret = SVGA3D_vgpu10_DefineElementLayout(svga->swc, velems->count,
+                                              velems->id, elements);
+      assert(ret == PIPE_OK);
    }
 }
 
 
 /**
- * Does the given vertex attrib format need to have the W component set
- * to one in the VS?
+ * Translate the vertex element types to SVGA3dDeclType and check
+ * for VS-based vertex attribute adjustments.
  */
-static boolean
-attrib_needs_w_to_1(enum pipe_format format)
+static void
+translate_vertex_decls(struct svga_context *svga,
+                       struct svga_velems_state *velems)
 {
-   switch (format) {
-   case PIPE_FORMAT_R8G8B8_SNORM:
-   case PIPE_FORMAT_R8G8B8_UNORM:
-   case PIPE_FORMAT_R16G16B16_SNORM:
-   case PIPE_FORMAT_R16G16B16_UNORM:
-      return TRUE;
-   default:
-      return FALSE;
+   unsigned i;
+
+   assert(!svga_have_vgpu10(svga));
+
+   for (i = 0; i < velems->count; i++) {
+      const enum pipe_format f = velems->velem[i].src_format;
+      SVGA3dSurfaceFormat svga_format;
+      unsigned vf_flags;
+
+      svga_translate_vertex_format_vgpu10(f, &svga_format, &vf_flags);
+
+      velems->decl_type[i] = translate_vertex_format_to_decltype(f);
+      if (velems->decl_type[i] == SVGA3D_DECLTYPE_MAX) {
+         /* Unsupported format - use software fetch */
+         velems->need_swvfetch = TRUE;
+      }
+
+      /* Check for VS-based adjustments */
+      if (attrib_needs_range_adjustment(f)) {
+         velems->adjust_attrib_range |= (1 << i);
+      }
+
+      if (vf_flags & VF_W_TO_1) {
+         velems->adjust_attrib_w_1 |= (1 << i);
+      }
    }
 }
 
@@ -152,53 +247,73 @@ svga_create_vertex_elements_state(struct pipe_context *pipe,
                                   unsigned count,
                                   const struct pipe_vertex_element *attribs)
 {
+   struct svga_context *svga = svga_context(pipe);
    struct svga_velems_state *velems;
+
    assert(count <= PIPE_MAX_ATTRIBS);
    velems = (struct svga_velems_state *) MALLOC(sizeof(struct svga_velems_state));
    if (velems) {
-      unsigned i;
-
       velems->count = count;
       memcpy(velems->velem, attribs, sizeof(*attribs) * count);
 
       velems->need_swvfetch = FALSE;
       velems->adjust_attrib_range = 0x0;
+      velems->attrib_is_pure_int = 0x0;
       velems->adjust_attrib_w_1 = 0x0;
-
-      /* Translate Gallium vertex format to SVGA3dDeclType */
-      for (i = 0; i < count; i++) {
-         enum pipe_format f = attribs[i].src_format;
-         velems->decl_type[i] = translate_vertex_format(f);
-         if (velems->decl_type[i] == SVGA3D_DECLTYPE_MAX) {
-            /* Unsupported format - use software fetch */
-            velems->need_swvfetch = TRUE;
-            break;
-         }
-
-         if (attrib_needs_range_adjustment(f)) {
-            velems->adjust_attrib_range |= (1 << i);
-         }
-         if (attrib_needs_w_to_1(f)) {
-            velems->adjust_attrib_w_1 |= (1 << i);
-         }
+      velems->adjust_attrib_itof = 0x0;
+      velems->adjust_attrib_utof = 0x0;
+      velems->attrib_is_bgra = 0x0;
+      velems->attrib_puint_to_snorm = 0x0;
+      velems->attrib_puint_to_uscaled = 0x0;
+      velems->attrib_puint_to_sscaled = 0x0;
+
+      if (svga_have_vgpu10(svga)) {
+         define_input_element_object(svga, velems);
+      }
+      else {
+         translate_vertex_decls(svga, velems);
       }
    }
    return velems;
 }
 
-static void svga_bind_vertex_elements_state(struct pipe_context *pipe,
-                                            void *velems)
+
+static void
+svga_bind_vertex_elements_state(struct pipe_context *pipe, void *state)
 {
    struct svga_context *svga = svga_context(pipe);
-   struct svga_velems_state *svga_velems = (struct svga_velems_state *) velems;
+   struct svga_velems_state *velems = (struct svga_velems_state *) state;
 
-   svga->curr.velems = svga_velems;
+   svga->curr.velems = velems;
    svga->dirty |= SVGA_NEW_VELEMENT;
 }
 
-static void svga_delete_vertex_elements_state(struct pipe_context *pipe,
-                                              void *velems)
+
+static void
+svga_delete_vertex_elements_state(struct pipe_context *pipe, void *state)
 {
+   struct svga_context *svga = svga_context(pipe);
+   struct svga_velems_state *velems = (struct svga_velems_state *) state;
+
+   if (svga_have_vgpu10(svga)) {
+      enum pipe_error ret;
+
+      svga_hwtnl_flush_retry(svga);
+
+      ret = SVGA3D_vgpu10_DestroyElementLayout(svga->swc, velems->id);
+      if (ret != PIPE_OK) {
+         svga_context_flush(svga, NULL);
+         ret = SVGA3D_vgpu10_DestroyElementLayout(svga->swc, velems->id);
+         assert(ret == PIPE_OK);
+      }
+
+      if (velems->id == svga->state.hw_draw.layout_id)
+         svga->state.hw_draw.layout_id = SVGA3D_INVALID_ID;
+
+      util_bitmask_clear(svga->input_element_object_id_bm, velems->id);
+      velems->id = SVGA3D_INVALID_ID;
+   }
+
    FREE(velems);
 }
 
@@ -219,5 +334,3 @@ void svga_init_vertex_functions( struct svga_context *svga )
    svga->pipe.bind_vertex_elements_state = svga_bind_vertex_elements_state;
    svga->pipe.delete_vertex_elements_state = svga_delete_vertex_elements_state;
 }
-
-
index c3ac663b4a2ec4feb82655c1d8cfa71701d84b45..630f4907895ba7e1ccf8d6045151cfa1517f4136 100644 (file)
 #include "tgsi/tgsi_text.h"
 
 #include "svga_context.h"
-#include "svga_tgsi.h"
 #include "svga_hw_reg.h"
 #include "svga_cmd.h"
 #include "svga_debug.h"
 #include "svga_shader.h"
+#include "svga_streamout.h"
 
 
 /**
@@ -100,6 +100,7 @@ svga_create_vs_state(struct pipe_context *pipe,
 {
    struct svga_context *svga = svga_context(pipe);
    struct svga_vertex_shader *vs = CALLOC_STRUCT(svga_vertex_shader);
+
    if (!vs)
       return NULL;
 
@@ -123,10 +124,12 @@ svga_create_vs_state(struct pipe_context *pipe,
 
    vs->base.id = svga->debug.shader_id++;
 
-   if (SVGA_DEBUG & DEBUG_TGSI || 0) {
-      debug_printf("%s id: %u, inputs: %u, outputs: %u\n",
-                   __FUNCTION__, vs->base.id,
-                   vs->base.info.num_inputs, vs->base.info.num_outputs);
+   vs->generic_outputs = svga_get_generic_outputs_mask(&vs->base.info);
+
+   /* check for any stream output declarations */
+   if (templ->stream_output.num_outputs) {
+      vs->base.stream_output = svga_create_stream_output(svga, &vs->base,
+                                                         &templ->stream_output);
    }
 
    return vs;
@@ -139,6 +142,17 @@ svga_bind_vs_state(struct pipe_context *pipe, void *shader)
    struct svga_vertex_shader *vs = (struct svga_vertex_shader *)shader;
    struct svga_context *svga = svga_context(pipe);
 
+   if (vs == svga->curr.vs)
+      return;
+
+   /* If the currently bound vertex shader has a generated geometry shader,
+    * then unbind the geometry shader before binding a new vertex shader.
+    * We need to unbind the geometry shader here because there is no
+    * pipe_shader associated with the generated geometry shader.
+    */
+   if (svga->curr.vs != NULL && svga->curr.vs->gs != NULL)
+      svga->pipe.bind_gs_state(&svga->pipe, NULL);
+
    svga->curr.vs = vs;
    svga->dirty |= SVGA_NEW_VS;
 }
@@ -154,20 +168,40 @@ svga_delete_vs_state(struct pipe_context *pipe, void *shader)
 
    svga_hwtnl_flush_retry(svga);
 
+   assert(vs->base.parent == NULL);
+
+   /* Check if there is a generated geometry shader to go with this
+    * vertex shader. If there is, then delete the geometry shader as well.
+    */
+   if (vs->gs != NULL) {
+      svga->pipe.delete_gs_state(&svga->pipe, vs->gs);
+   }
+
+   if (vs->base.stream_output != NULL)
+      svga_delete_stream_output(svga, vs->base.stream_output);
+
    draw_delete_vertex_shader(svga->swtnl.draw, vs->draw_shader);
 
    for (variant = vs->base.variants; variant; variant = tmp) {
       tmp = variant->next;
 
-      ret = svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_VS, variant);
-      (void) ret;  /* PIPE_ERROR_ not handled yet */
-
-      /*
-       * Remove stale references to this variant to ensure a new variant on the
-       * same address will be detected as a change.
-       */
-      if (variant == svga->state.hw_draw.vs)
+      /* Check if deleting currently bound shader */
+      if (variant == svga->state.hw_draw.vs) {
+         ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_VS, NULL);
+         if (ret != PIPE_OK) {
+            svga_context_flush(svga, NULL);
+            ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_VS, NULL);
+            assert(ret == PIPE_OK);
+         }
          svga->state.hw_draw.vs = NULL;
+      }
+
+      ret = svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_VS, variant);
+      if (ret != PIPE_OK) {
+         svga_context_flush(svga, NULL);
+         ret = svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_VS, variant);
+         assert(ret == PIPE_OK);
+      }
    }
 
    FREE((void *)vs->base.tokens);
index b295b44ea376ee6cad0fb5d21c5549248ed85168..a910ae0ca723dc79822dce6dd32d5af9ff9345cf 100644 (file)
@@ -69,18 +69,21 @@ svga_can_create_resource(struct pipe_screen *screen,
    struct svga_winsys_screen *sws = svgascreen->sws;
    SVGA3dSurfaceFormat format;
    SVGA3dSize base_level_size;
-   uint32 numFaces;
    uint32 numMipLevels;
+   uint32 arraySize;
 
    if (res->target == PIPE_BUFFER) {
       format = SVGA3D_BUFFER;
       base_level_size.width = res->width0;
       base_level_size.height = 1;
       base_level_size.depth = 1;
-      numFaces = 1;
       numMipLevels = 1;
+      arraySize = 1;
 
    } else {
+      if (res->target == PIPE_TEXTURE_CUBE)
+         assert(res->array_size == 6);
+
       format = svga_translate_format(svgascreen, res->format, res->bind);
       if (format == SVGA3D_FORMAT_INVALID)
          return FALSE;
@@ -88,12 +91,12 @@ svga_can_create_resource(struct pipe_screen *screen,
       base_level_size.width = res->width0;
       base_level_size.height = res->height0;
       base_level_size.depth = res->depth0;
-      numFaces = (res->target == PIPE_TEXTURE_CUBE) ? 6 : 1;
       numMipLevels = res->last_level + 1;
+      arraySize = res->array_size;
    }
 
    return sws->surface_can_create(sws, format, base_level_size, 
-                                  numFaces, numMipLevels);
+                                  arraySize, numMipLevels);
 }
 
 
index 13f85cddbd526e3613f000afc16224cca0d43cb8..7ef36b367d3723e807bc389835d018d55189e3bd 100644 (file)
@@ -48,7 +48,8 @@
 static inline boolean
 svga_buffer_needs_hw_storage(unsigned usage)
 {
-   return usage & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER);
+   return (usage & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER |
+                    PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_STREAM_OUTPUT)) != 0;
 }
 
 
@@ -87,6 +88,26 @@ svga_buffer_transfer_map(struct pipe_context *pipe,
    transfer->usage = usage;
    transfer->box = *box;
 
+   if ((usage & PIPE_TRANSFER_READ) && sbuf->dirty) {
+      /* Only need to test for vgpu10 since only vgpu10 features (streamout,
+       * buffer copy) can modify buffers on the device.
+       */
+      if (svga_have_vgpu10(svga)) {
+         enum pipe_error ret;
+         assert(sbuf->handle);
+         ret = SVGA3D_vgpu10_ReadbackSubResource(svga->swc, sbuf->handle, 0);
+         if (ret != PIPE_OK) {
+            svga_context_flush(svga, NULL);
+            ret = SVGA3D_vgpu10_ReadbackSubResource(svga->swc, sbuf->handle, 0);
+            assert(ret == PIPE_OK);
+         }
+
+         svga_context_finish(svga);
+
+         sbuf->dirty = FALSE;
+      }
+   }
+
    if (usage & PIPE_TRANSFER_WRITE) {
       if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
          /*
@@ -343,13 +364,43 @@ svga_buffer_create(struct pipe_screen *screen,
    sbuf->b.vtbl = &svga_buffer_vtbl;
    pipe_reference_init(&sbuf->b.b.reference, 1);
    sbuf->b.b.screen = screen;
+   sbuf->bind_flags = template->bind;
+
+   if (template->bind & PIPE_BIND_CONSTANT_BUFFER) {
+      /* Constant buffers can only have the PIPE_BIND_CONSTANT_BUFFER
+       * flag set.
+       */
+      if (ss->sws->have_vgpu10) {
+         sbuf->bind_flags = PIPE_BIND_CONSTANT_BUFFER;
+
+         /* Constant buffer size needs to be in multiples of 16. */
+         sbuf->b.b.width0 = align(sbuf->b.b.width0, 16);
+      }
+   }
 
    if(svga_buffer_needs_hw_storage(template->bind)) {
+
+      /* If the buffer will be used for vertex/index/stream data, set all
+       * the flags so that the buffer will be accepted for all those uses.
+       * Note that the PIPE_BIND_ flags we get from the state tracker are
+       * just a hint about how the buffer may be used.  And OpenGL buffer
+       * object may be used for many different things.
+       */
+      if (!(template->bind & PIPE_BIND_CONSTANT_BUFFER)) {
+         /* Not a constant buffer.  The buffer may be used for vertex data,
+          * indexes or stream-out.
+          */
+         sbuf->bind_flags |= (PIPE_BIND_VERTEX_BUFFER |
+                              PIPE_BIND_INDEX_BUFFER);
+         if (ss->sws->have_vgpu10)
+            sbuf->bind_flags |= PIPE_BIND_STREAM_OUTPUT;
+      }
+
       if(svga_buffer_create_host_surface(ss, sbuf) != PIPE_OK)
          goto error2;
    }
    else {
-      sbuf->swbuf = align_malloc(template->width0, 64);
+      sbuf->swbuf = align_malloc(sbuf->b.b.width0, 64);
       if(!sbuf->swbuf)
          goto error2;
    }
@@ -357,7 +408,7 @@ svga_buffer_create(struct pipe_screen *screen,
    debug_reference(&sbuf->b.b.reference,
                    (debug_reference_descriptor)debug_describe_resource, 0);
 
-   sbuf->size = util_resource_size(template);
+   sbuf->size = util_resource_size(&sbuf->b.b);
    ss->total_resource_bytes += sbuf->size;
 
    return &sbuf->b.b; 
@@ -391,6 +442,7 @@ svga_user_buffer_create(struct pipe_screen *screen,
    sbuf->b.b.depth0 = 1;
    sbuf->b.b.array_size = 1;
 
+   sbuf->bind_flags = bind;
    sbuf->swbuf = ptr;
    sbuf->user = TRUE;
 
index e838beb666181547be686eea9e56f3c86061641a..75e12c3220ceee2cf9d9d25776f814a9c0dd4f5f 100644 (file)
@@ -65,6 +65,9 @@ struct svga_buffer
 {
    struct u_resource b;
 
+   /** This is a superset of b.b.bind */
+   unsigned bind_flags;
+
    /**
     * Regular (non DMA'able) memory.
     * 
@@ -187,6 +190,8 @@ struct svga_buffer
    struct list_head head;
 
    unsigned size;  /**< Approximate size in bytes */
+
+   boolean dirty;  /**< Need to do a readback before mapping? */
 };
 
 
index 5686531f988faebf5614ffeff5b0a52023ece32b..69e5f75e208fb072370a7ce1d0dfb18a218f2b10 100644 (file)
@@ -149,10 +149,22 @@ svga_buffer_create_host_surface(struct svga_screen *ss,
       sbuf->key.flags = 0;
 
       sbuf->key.format = SVGA3D_BUFFER;
-      if (sbuf->b.b.bind & PIPE_BIND_VERTEX_BUFFER)
+      if (sbuf->bind_flags & PIPE_BIND_VERTEX_BUFFER) {
          sbuf->key.flags |= SVGA3D_SURFACE_HINT_VERTEXBUFFER;
-      if (sbuf->b.b.bind & PIPE_BIND_INDEX_BUFFER)
+         sbuf->key.flags |= SVGA3D_SURFACE_BIND_VERTEX_BUFFER;
+      }
+      if (sbuf->bind_flags & PIPE_BIND_INDEX_BUFFER) {
          sbuf->key.flags |= SVGA3D_SURFACE_HINT_INDEXBUFFER;
+         sbuf->key.flags |= SVGA3D_SURFACE_BIND_INDEX_BUFFER;
+      }
+      if (sbuf->bind_flags & PIPE_BIND_CONSTANT_BUFFER)
+         sbuf->key.flags |= SVGA3D_SURFACE_BIND_CONSTANT_BUFFER;
+
+      if (sbuf->bind_flags & PIPE_BIND_STREAM_OUTPUT)
+         sbuf->key.flags |= SVGA3D_SURFACE_BIND_STREAM_OUTPUT;
+
+      if (sbuf->bind_flags & PIPE_BIND_SAMPLER_VIEW)
+         sbuf->key.flags |= SVGA3D_SURFACE_BIND_SHADER_RESOURCE;
 
       sbuf->key.size.width = sbuf->b.b.width0;
       sbuf->key.size.height = 1;
@@ -161,10 +173,12 @@ svga_buffer_create_host_surface(struct svga_screen *ss,
       sbuf->key.numFaces = 1;
       sbuf->key.numMipLevels = 1;
       sbuf->key.cachable = 1;
+      sbuf->key.arraySize = 1;
 
       SVGA_DBG(DEBUG_DMA, "surface_create for buffer sz %d\n", sbuf->b.b.width0);
 
-      sbuf->handle = svga_screen_surface_create(ss, &sbuf->key);
+      sbuf->handle = svga_screen_surface_create(ss, sbuf->b.b.bind,
+                                                sbuf->b.b.usage, &sbuf->key);
       if (!sbuf->handle)
          return PIPE_ERROR_OUT_OF_MEMORY;
 
@@ -203,8 +217,8 @@ svga_buffer_upload_gb_command(struct svga_context *svga,
                              struct svga_buffer *sbuf)
 {
    struct svga_winsys_context *swc = svga->swc;
-   SVGA3dCmdUpdateGBImage *cmd;
-   struct svga_3d_update_gb_image *ccmd = NULL;
+   SVGA3dCmdUpdateGBImage *update_cmd;
+   struct svga_3d_update_gb_image *whole_update_cmd = NULL;
    uint32 numBoxes = sbuf->map.num_ranges;
    struct pipe_resource *dummy;
    unsigned int i;
@@ -214,68 +228,78 @@ svga_buffer_upload_gb_command(struct svga_context *svga,
 
    if (sbuf->dma.flags.discard) {
       struct svga_3d_invalidate_gb_image *cicmd = NULL;
-      SVGA3dCmdInvalidateGBImage *icmd;
+      SVGA3dCmdInvalidateGBImage *invalidate_cmd;
+      const unsigned total_commands_size =
+         sizeof(*invalidate_cmd) + numBoxes * sizeof(*whole_update_cmd);
 
       /* Allocate FIFO space for one INVALIDATE_GB_IMAGE command followed by
        * 'numBoxes' UPDATE_GB_IMAGE commands.  Allocate all at once rather
        * than with separate commands because we need to properly deal with
        * filling the command buffer.
        */
-      icmd = SVGA3D_FIFOReserve(swc,
-                               SVGA_3D_CMD_INVALIDATE_GB_IMAGE,
-                               sizeof *icmd + numBoxes * sizeof *ccmd,
-                               2);
-      if (!icmd)
+      invalidate_cmd = SVGA3D_FIFOReserve(swc,
+                                          SVGA_3D_CMD_INVALIDATE_GB_IMAGE,
+                                          total_commands_size, 1 + numBoxes);
+      if (!invalidate_cmd)
         return PIPE_ERROR_OUT_OF_MEMORY;
 
-      cicmd = container_of(icmd, cicmd, body);
-      cicmd->header.size = sizeof *icmd;
-      swc->surface_relocation(swc, &icmd->image.sid, NULL, sbuf->handle,
+      cicmd = container_of(invalidate_cmd, cicmd, body);
+      cicmd->header.size = sizeof(*invalidate_cmd);
+      swc->surface_relocation(swc, &invalidate_cmd->image.sid, NULL, sbuf->handle,
                               (SVGA_RELOC_WRITE |
                                SVGA_RELOC_INTERNAL |
                                SVGA_RELOC_DMA));
-      icmd->image.face = 0;
-      icmd->image.mipmap = 0;
+      invalidate_cmd->image.face = 0;
+      invalidate_cmd->image.mipmap = 0;
 
+      /* The whole_update_command is a SVGA3dCmdHeader plus the
+       * SVGA3dCmdUpdateGBImage command.
+       */
+      whole_update_cmd = (struct svga_3d_update_gb_image *) &invalidate_cmd[1];
       /* initialize the first UPDATE_GB_IMAGE command */
-      ccmd = (struct svga_3d_update_gb_image *) &icmd[1];
-      ccmd->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
-      cmd = &ccmd->body;
+      whole_update_cmd->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
+      update_cmd = &whole_update_cmd->body;
 
    } else {
       /* Allocate FIFO space for 'numBoxes' UPDATE_GB_IMAGE commands */
-      cmd = SVGA3D_FIFOReserve(swc,
-                              SVGA_3D_CMD_UPDATE_GB_IMAGE,
-                              sizeof *cmd + (numBoxes - 1) * sizeof *ccmd,
-                              1);
-      if (!cmd)
+      const unsigned total_commands_size =
+         sizeof(*update_cmd) + (numBoxes - 1) * sizeof(*whole_update_cmd);
+
+      update_cmd = SVGA3D_FIFOReserve(swc,
+                                      SVGA_3D_CMD_UPDATE_GB_IMAGE,
+                                      total_commands_size, numBoxes);
+      if (!update_cmd)
         return PIPE_ERROR_OUT_OF_MEMORY;
 
-      ccmd = container_of(cmd, ccmd, body);
+      /* The whole_update_command is a SVGA3dCmdHeader plus the
+       * SVGA3dCmdUpdateGBImage command.
+       */
+      whole_update_cmd = container_of(update_cmd, whole_update_cmd, body);
    }
 
    /* Init the first UPDATE_GB_IMAGE command */
-   ccmd->header.size = sizeof *cmd;
-   swc->surface_relocation(swc, &cmd->image.sid, NULL, sbuf->handle,
+   whole_update_cmd->header.size = sizeof(*update_cmd);
+   swc->surface_relocation(swc, &update_cmd->image.sid, NULL, sbuf->handle,
                           SVGA_RELOC_WRITE | SVGA_RELOC_INTERNAL);
-   cmd->image.face = 0;
-   cmd->image.mipmap = 0;
+   update_cmd->image.face = 0;
+   update_cmd->image.mipmap = 0;
 
    /* Save pointer to the first UPDATE_GB_IMAGE command so that we can
     * fill in the box info below.
     */
-   sbuf->dma.updates = ccmd;
+   sbuf->dma.updates = whole_update_cmd;
 
    /*
-    * Copy the relocation info, face and mipmap to all
-    * subsequent commands. NOTE: For winsyses that actually
-    * patch the image.sid member at flush time, this will fail
-    * miserably. For those we need to add as many relocations
-    * as there are copy boxes.
+    * Copy the face, mipmap, etc. info to all subsequent commands.
+    * Also do the surface relocation for each subsequent command.
     */
-
    for (i = 1; i < numBoxes; ++i) {
-      memcpy(++ccmd, sbuf->dma.updates, sizeof *ccmd);
+      whole_update_cmd++;
+      memcpy(whole_update_cmd, sbuf->dma.updates, sizeof(*whole_update_cmd));
+
+      swc->surface_relocation(swc, &whole_update_cmd->body.image.sid, NULL,
+                              sbuf->handle,
+                              SVGA_RELOC_WRITE | SVGA_RELOC_INTERNAL);
    }
 
    /* Increment reference count */
index 64fd245c0e1199109030010b2b427a4f90cb94e5..90787be80730609f8d3ec4966b68fdeebf7fe951 100644 (file)
 #include "svga_debug.h"
 
 
-/* XXX: This isn't a real hardware flag, but just a hack for kernel to
- * know about primary surfaces. Find a better way to accomplish this.
- */
-#define SVGA3D_SURFACE_HINT_SCANOUT (1 << 9)
-
-
 static void
 svga_transfer_dma_band(struct svga_context *svga,
                        struct svga_transfer *st,
@@ -59,10 +53,10 @@ svga_transfer_dma_band(struct svga_context *svga,
                        unsigned y, unsigned h, unsigned srcy,
                        SVGA3dSurfaceDMAFlags flags)
 {
-   struct svga_texture *texture = svga_texture(st->base.resource); 
+   struct svga_texture *texture = svga_texture(st->base.resource);
    SVGA3dCopyBox box;
    enum pipe_error ret;
+
    assert(!st->use_direct_map);
 
    box.x = st->base.box.x;
@@ -75,28 +69,23 @@ svga_transfer_dma_band(struct svga_context *svga,
    box.srcy = srcy;
    box.srcz = 0;
 
-   if (st->base.resource->target == PIPE_TEXTURE_CUBE) {
-      st->face = st->base.box.z;
-      box.z = 0;
-   }
-   else
-      st->face = 0;
-
-   SVGA_DBG(DEBUG_DMA, "dma %s sid %p, face %u, (%u, %u, %u) - (%u, %u, %u), %ubpp\n",
-                transfer == SVGA3D_WRITE_HOST_VRAM ? "to" : "from", 
-                texture->handle,
-                st->face,
-                st->base.box.x,
-                y,
-                box.z,
-                st->base.box.x + st->base.box.width,
-                y + h,
-                box.z + 1,
-                util_format_get_blocksize(texture->b.b.format) * 8 /
-                (util_format_get_blockwidth(texture->b.b.format)*util_format_get_blockheight(texture->b.b.format)));
+   SVGA_DBG(DEBUG_DMA, "dma %s sid %p, face %u, (%u, %u, %u) - "
+            "(%u, %u, %u), %ubpp\n",
+            transfer == SVGA3D_WRITE_HOST_VRAM ? "to" : "from",
+            texture->handle,
+            st->slice,
+            st->base.box.x,
+            y,
+            box.z,
+            st->base.box.x + st->base.box.width,
+            y + h,
+            box.z + 1,
+            util_format_get_blocksize(texture->b.b.format) * 8 /
+            (util_format_get_blockwidth(texture->b.b.format)
+             * util_format_get_blockheight(texture->b.b.format)));
 
    ret = SVGA3D_SurfaceDMA(svga->swc, st, transfer, &box, 1, flags);
-   if(ret != PIPE_OK) {
+   if (ret != PIPE_OK) {
       svga_context_flush(svga, NULL);
       ret = SVGA3D_SurfaceDMA(svga->swc, st, transfer, &box, 1, flags);
       assert(ret == PIPE_OK);
@@ -110,7 +99,7 @@ svga_transfer_dma(struct svga_context *svga,
                   SVGA3dTransferType transfer,
                   SVGA3dSurfaceDMAFlags flags)
 {
-   struct svga_texture *texture = svga_texture(st->base.resource); 
+   struct svga_texture *texture = svga_texture(st->base.resource);
    struct svga_screen *screen = svga_screen(texture->b.b.screen);
    struct svga_winsys_screen *sws = screen->sws;
    struct pipe_fence_handle *fence = NULL;
@@ -126,14 +115,13 @@ svga_transfer_dma(struct svga_context *svga,
     */
    svga_surfaces_flush( svga );
 
-   if(!st->swbuf) {
+   if (!st->swbuf) {
       /* Do the DMA transfer in a single go */
-
       svga_transfer_dma_band(svga, st, transfer,
                              st->base.box.y, st->base.box.height, 0,
                              flags);
 
-      if(transfer == SVGA3D_READ_HOST_VRAM) {
+      if (transfer == SVGA3D_READ_HOST_VRAM) {
          svga_context_flush(svga, &fence);
          sws->fence_finish(sws, fence, 0);
          sws->fence_reference(sws, &fence, NULL);
@@ -141,10 +129,13 @@ svga_transfer_dma(struct svga_context *svga,
    }
    else {
       int y, h, srcy;
-      unsigned blockheight = util_format_get_blockheight(st->base.resource->format);
+      unsigned blockheight =
+         util_format_get_blockheight(st->base.resource->format);
+
       h = st->hw_nblocksy * blockheight;
       srcy = 0;
-      for(y = 0; y < st->base.box.height; y += h) {
+
+      for (y = 0; y < st->base.box.height; y += h) {
          unsigned offset, length;
          void *hw, *sw;
 
@@ -158,7 +149,7 @@ svga_transfer_dma(struct svga_context *svga,
          offset = y * st->base.stride / blockheight;
          length = h * st->base.stride / blockheight;
 
-         sw = (uint8_t *)st->swbuf + offset;
+         sw = (uint8_t *) st->swbuf + offset;
 
          if (transfer == SVGA3D_WRITE_HOST_VRAM) {
             unsigned usage = PIPE_TRANSFER_WRITE;
@@ -184,16 +175,15 @@ svga_transfer_dma(struct svga_context *svga,
           * Prevent the texture contents to be discarded on the next band
           * upload.
           */
-
          flags.discard = FALSE;
 
-         if(transfer == SVGA3D_READ_HOST_VRAM) {
+         if (transfer == SVGA3D_READ_HOST_VRAM) {
             svga_context_flush(svga, &fence);
             sws->fence_finish(sws, fence, 0);
 
             hw = sws->buffer_map(sws, st->hwbuf, PIPE_TRANSFER_READ);
             assert(hw);
-            if(hw) {
+            if (hw) {
                memcpy(sw, hw, length);
                sws->buffer_unmap(sws, st->hwbuf);
             }
@@ -203,19 +193,22 @@ svga_transfer_dma(struct svga_context *svga,
 }
 
 
-static boolean 
+static boolean
 svga_texture_get_handle(struct pipe_screen *screen,
-                               struct pipe_resource *texture,
-                               struct winsys_handle *whandle)
+                        struct pipe_resource *texture,
+                        struct winsys_handle *whandle)
 {
    struct svga_winsys_screen *sws = svga_winsys_screen(texture->screen);
    unsigned stride;
 
    assert(svga_texture(texture)->key.cachable == 0);
    svga_texture(texture)->key.cachable = 0;
+
    stride = util_format_get_nblocksx(texture->format, texture->width0) *
             util_format_get_blocksize(texture->format);
-   return sws->surface_get_handle(sws, svga_texture(texture)->handle, stride, whandle);
+
+   return sws->surface_get_handle(sws, svga_texture(texture)->handle,
+                                  stride, whandle);
 }
 
 
@@ -238,6 +231,7 @@ svga_texture_destroy(struct pipe_screen *screen,
 
    ss->total_resource_bytes -= tex->size;
 
+   FREE(tex->defined);
    FREE(tex->rendered_to);
    FREE(tex);
 }
@@ -274,10 +268,43 @@ need_tex_readback(struct pipe_transfer *transfer)
 }
 
 
+static enum pipe_error
+readback_image_vgpu9(struct svga_context *svga,
+                   struct svga_winsys_surface *surf,
+                   unsigned slice,
+                   unsigned level)
+{
+   enum pipe_error ret;
+
+   ret = SVGA3D_ReadbackGBImage(svga->swc, surf, slice, level);
+   if (ret != PIPE_OK) {
+      svga_context_flush(svga, NULL);
+      ret = SVGA3D_ReadbackGBImage(svga->swc, surf, slice, level);
+   }
+   return ret;
+}
+
+
+static enum pipe_error
+readback_image_vgpu10(struct svga_context *svga,
+                    struct svga_winsys_surface *surf,
+                    unsigned slice,
+                    unsigned level,
+                    unsigned numMipLevels)
+{
+   enum pipe_error ret;
+   unsigned subResource;
+
+   subResource = slice * numMipLevels + level;
+   ret = SVGA3D_vgpu10_ReadbackSubResource(svga->swc, surf, subResource);
+   if (ret != PIPE_OK) {
+      svga_context_flush(svga, NULL);
+      ret = SVGA3D_vgpu10_ReadbackSubResource(svga->swc, surf, subResource);
+   }
+   return ret;
+}
+
 
-/* XXX: Still implementing this as if it was a screen function, but
- * can now modify it to queue transfers on the context.
- */
 static void *
 svga_texture_transfer_map(struct pipe_context *pipe,
                           struct pipe_resource *texture,
@@ -289,6 +316,7 @@ svga_texture_transfer_map(struct pipe_context *pipe,
    struct svga_context *svga = svga_context(pipe);
    struct svga_screen *ss = svga_screen(pipe->screen);
    struct svga_winsys_screen *sws = ss->sws;
+   struct svga_texture *tex = svga_texture(texture);
    struct svga_transfer *st;
    unsigned nblocksx, nblocksy;
    boolean use_direct_map = svga_have_gb_objects(svga) &&
@@ -326,25 +354,34 @@ svga_texture_transfer_map(struct pipe_context *pipe,
    }
 
    pipe_resource_reference(&st->base.resource, texture);
+
    st->base.level = level;
    st->base.usage = usage;
    st->base.box = *box;
    st->base.stride = nblocksx*util_format_get_blocksize(texture->format);
    st->base.layer_stride = st->base.stride * nblocksy;
 
+   switch (tex->b.b.target) {
+   case PIPE_TEXTURE_CUBE:
+   case PIPE_TEXTURE_2D_ARRAY:
+   case PIPE_TEXTURE_1D_ARRAY:
+      st->slice = st->base.box.z;
+      st->base.box.z = 0;   /* so we don't apply double offsets below */
+      break;
+   default:
+      st->slice = 0;
+      break;
+   }
+
    if (!use_direct_map) {
       /* Use a DMA buffer */
       st->hw_nblocksy = nblocksy;
 
-      st->hwbuf = svga_winsys_buffer_create(svga,
-                                            1, 
-                                            0,
-                                            st->hw_nblocksy * st->base.stride * d);
+      st->hwbuf = svga_winsys_buffer_create(svga, 1, 0,
+                                   st->hw_nblocksy * st->base.stride * d);
       while(!st->hwbuf && (st->hw_nblocksy /= 2)) {
-         st->hwbuf = svga_winsys_buffer_create(svga,
-                                               1, 
-                                               0,
-                                               st->hw_nblocksy * st->base.stride * d);
+         st->hwbuf = svga_winsys_buffer_create(svga, 1, 0,
+                                   st->hw_nblocksy * st->base.stride * d);
       }
 
       if (!st->hwbuf) {
@@ -352,8 +389,8 @@ svga_texture_transfer_map(struct pipe_context *pipe,
          return NULL;
       }
 
-      if(st->hw_nblocksy < nblocksy) {
-         /* We couldn't allocate a hardware buffer big enough for the transfer, 
+      if (st->hw_nblocksy < nblocksy) {
+         /* We couldn't allocate a hardware buffer big enough for the transfer,
           * so allocate regular malloc memory instead */
          if (0) {
             debug_printf("%s: failed to allocate %u KB of DMA, "
@@ -379,45 +416,27 @@ svga_texture_transfer_map(struct pipe_context *pipe,
       }
    } else {
       struct pipe_transfer *transfer = &st->base;
-      struct svga_texture *tex = svga_texture(transfer->resource);
       struct svga_winsys_surface *surf = tex->handle;
-      unsigned face;
-
-      assert(surf);
 
-      if (tex->b.b.target == PIPE_TEXTURE_CUBE) {
-        face = transfer->box.z;
-      } else {
-        face = 0;
+      if (!surf) {
+         FREE(st);
+         return NULL;
       }
 
       if (need_tex_readback(transfer)) {
-        SVGA3dBox box;
         enum pipe_error ret;
 
-        box.x = transfer->box.x;
-        box.y = transfer->box.y;
-        box.w = transfer->box.width;
-        box.h = transfer->box.height;
-        box.d = transfer->box.depth;
-        if (tex->b.b.target == PIPE_TEXTURE_CUBE) {
-           box.z = 0;
-        }
-        else {
-           box.z = transfer->box.z;
-        }
-
-         (void) box;  /* not used at this time */
-
          svga_surfaces_flush(svga);
 
-        ret = SVGA3D_ReadbackGBImage(svga->swc, surf, face, transfer->level);
+         if (svga_have_vgpu10(svga)) {
+            ret = readback_image_vgpu10(svga, surf, st->slice, transfer->level,
+                                        tex->b.b.last_level + 1);
+         } else {
+            ret = readback_image_vgpu9(svga, surf, st->slice, transfer->level);
+         }
 
-        if (ret != PIPE_OK) {
-           svga_context_flush(svga, NULL);
-           ret = SVGA3D_ReadbackGBImage(svga->swc, surf, face, transfer->level);
-           assert(ret == PIPE_OK);
-        }
+         assert(ret == PIPE_OK);
+         (void) ret;
 
         svga_context_flush(svga, NULL);
 
@@ -425,7 +444,7 @@ svga_texture_transfer_map(struct pipe_context *pipe,
           * Note: if PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE were specified
           * we could potentially clear the flag for all faces/layers/mips.
           */
-         svga_clear_texture_rendered_to(tex, face, transfer->level);
+         svga_clear_texture_rendered_to(tex, st->slice, transfer->level);
       }
       else {
         assert(transfer->usage & PIPE_TRANSFER_WRITE);
@@ -451,17 +470,15 @@ svga_texture_transfer_map(struct pipe_context *pipe,
       return sws->buffer_map(sws, st->hwbuf, usage);
    }
    else {
-      struct svga_screen *screen = svga_screen(svga->pipe.screen);
-      SVGA3dSurfaceFormat format;
       SVGA3dSize baseLevelSize;
       struct svga_texture *tex = svga_texture(texture);
       struct svga_winsys_surface *surf = tex->handle;
       uint8_t *map;
       boolean retry;
-      unsigned face, offset, mip_width, mip_height;
-      unsigned xoffset = box->x;
-      unsigned yoffset = box->y;
-      unsigned zoffset = box->z;
+      unsigned offset, mip_width, mip_height;
+      unsigned xoffset = st->base.box.x;
+      unsigned yoffset = st->base.box.y;
+      unsigned zoffset = st->base.box.z;
 
       map = svga->swc->surface_map(svga->swc, surf, usage, &retry);
       if (map == NULL && retry) {
@@ -484,21 +501,13 @@ svga_texture_transfer_map(struct pipe_context *pipe,
       /**
        * Compute the offset to the specific texture slice in the buffer.
        */
-      if (tex->b.b.target == PIPE_TEXTURE_CUBE) {
-         face = zoffset;
-         zoffset = 0;
-      } else {
-         face = 0;
-      }
-
-      format = svga_translate_format(screen, tex->b.b.format, 0);
       baseLevelSize.width = tex->b.b.width0;
       baseLevelSize.height = tex->b.b.height0;
       baseLevelSize.depth = tex->b.b.depth0;
 
-      offset = svga3dsurface_get_image_offset(format, baseLevelSize,
+      offset = svga3dsurface_get_image_offset(tex->key.format, baseLevelSize,
                                               tex->b.b.last_level + 1, /* numMips */
-                                              face, level);
+                                              st->slice, level);
       if (level > 0) {
          assert(offset > 0);
       }
@@ -506,7 +515,8 @@ svga_texture_transfer_map(struct pipe_context *pipe,
       mip_width = u_minify(tex->b.b.width0, level);
       mip_height = u_minify(tex->b.b.height0, level);
 
-      offset += svga3dsurface_get_pixel_offset(format, mip_width, mip_height,
+      offset += svga3dsurface_get_pixel_offset(tex->key.format,
+                                               mip_width, mip_height,
                                                xoffset, yoffset, zoffset);
 
       return (void *) (map + offset);
@@ -541,9 +551,45 @@ svga_texture_surface_unmap(struct svga_context *svga,
 }
 
 
-/* XXX: Still implementing this as if it was a screen function, but
- * can now modify it to queue transfers on the context.
- */
+static enum pipe_error
+update_image_vgpu9(struct svga_context *svga,
+                   struct svga_winsys_surface *surf,
+                   const SVGA3dBox *box,
+                   unsigned slice,
+                   unsigned level)
+{
+   enum pipe_error ret;
+
+   ret = SVGA3D_UpdateGBImage(svga->swc, surf, box, slice, level);
+   if (ret != PIPE_OK) {
+      svga_context_flush(svga, NULL);
+      ret = SVGA3D_UpdateGBImage(svga->swc, surf, box, slice, level);
+   }
+   return ret;
+}
+
+
+static enum pipe_error
+update_image_vgpu10(struct svga_context *svga,
+                    struct svga_winsys_surface *surf,
+                    const SVGA3dBox *box,
+                    unsigned slice,
+                    unsigned level,
+                    unsigned numMipLevels)
+{
+   enum pipe_error ret;
+   unsigned subResource;
+
+   subResource = slice * numMipLevels + level;
+   ret = SVGA3D_vgpu10_UpdateSubResource(svga->swc, surf, box, subResource);
+   if (ret != PIPE_OK) {
+      svga_context_flush(svga, NULL);
+      ret = SVGA3D_vgpu10_UpdateSubResource(svga->swc, surf, box, subResource);
+   }
+   return ret;
+}
+
+
 static void
 svga_texture_transfer_unmap(struct pipe_context *pipe,
                            struct pipe_transfer *transfer)
@@ -579,26 +625,25 @@ svga_texture_transfer_unmap(struct pipe_context *pipe,
    } else if (transfer->usage & PIPE_TRANSFER_WRITE) {
       struct svga_winsys_surface *surf =
         svga_texture(transfer->resource)->handle;
-      unsigned face;
       SVGA3dBox box;
       enum pipe_error ret;
 
       assert(svga_have_gb_objects(svga));
 
       /* update the effected region */
-      if (tex->b.b.target == PIPE_TEXTURE_CUBE) {
-        face = transfer->box.z;
-      } else {
-        face = 0;
-      }
-
       box.x = transfer->box.x;
       box.y = transfer->box.y;
-      if (tex->b.b.target == PIPE_TEXTURE_CUBE) {
+      switch (tex->b.b.target) {
+      case PIPE_TEXTURE_CUBE:
+      case PIPE_TEXTURE_2D_ARRAY:
          box.z = 0;
-      }
-      else {
+         break;
+      case PIPE_TEXTURE_1D_ARRAY:
+         box.y = box.z = 0;
+         break;
+      default:
          box.z = transfer->box.z;
+         break;
       }
       box.w = transfer->box.width;
       box.h = transfer->box.height;
@@ -610,18 +655,21 @@ svga_texture_transfer_unmap(struct pipe_context *pipe,
                       box.x, box.y, box.z,
                       box.w, box.h, box.d);
 
-      ret = SVGA3D_UpdateGBImage(svga->swc, surf, &box, face, transfer->level);
-      if (ret != PIPE_OK) {
-         svga_context_flush(svga, NULL);
-         ret = SVGA3D_UpdateGBImage(svga->swc, surf, &box, face, transfer->level);
-         assert(ret == PIPE_OK);
+      if (svga_have_vgpu10(svga)) {
+         ret = update_image_vgpu10(svga, surf, &box, st->slice, transfer->level,
+                                   tex->b.b.last_level + 1);
+      } else {
+         ret = update_image_vgpu9(svga, surf, &box, st->slice, transfer->level);
       }
+
+      assert(ret == PIPE_OK);
+      (void) ret;
    }
 
    ss->texture_timestamp++;
    svga_age_texture_view(tex, transfer->level);
    if (transfer->resource->target == PIPE_TEXTURE_CUBE)
-      svga_define_texture_level(tex, transfer->box.z, transfer->level);
+      svga_define_texture_level(tex, st->slice, transfer->level);
    else
       svga_define_texture_level(tex, 0, transfer->level);
 
@@ -635,7 +683,18 @@ svga_texture_transfer_unmap(struct pipe_context *pipe,
 }
 
 
-struct u_resource_vtbl svga_texture_vtbl = 
+/**
+ * Does format store depth values?
+ */
+static inline boolean
+format_has_depth(enum pipe_format format)
+{
+   const struct util_format_description *desc = util_format_description(format);
+   return util_format_has_depth(desc);
+}
+
+
+struct u_resource_vtbl svga_texture_vtbl =
 {
    svga_texture_get_handle,          /* get_handle */
    svga_texture_destroy,             /* resource_destroy */
@@ -651,57 +710,119 @@ svga_texture_create(struct pipe_screen *screen,
                     const struct pipe_resource *template)
 {
    struct svga_screen *svgascreen = svga_screen(screen);
-   struct svga_texture *tex = CALLOC_STRUCT(svga_texture);
+   struct svga_texture *tex;
+   unsigned bindings = template->bind;
 
-   if (!tex)
-      goto error1;
+   assert(template->last_level < SVGA_MAX_TEXTURE_LEVELS);
+   if (template->last_level >= SVGA_MAX_TEXTURE_LEVELS) {
+      return NULL;
+   }
+
+   tex = CALLOC_STRUCT(svga_texture);
+   if (!tex) {
+      return NULL;
+   }
+
+   tex->defined = CALLOC(template->depth0 * template->array_size,
+                         sizeof(tex->defined[0]));
+   if (!tex->defined) {
+      FREE(tex);
+      return NULL;
+   }
+
+   tex->rendered_to = CALLOC(template->depth0 * template->array_size,
+                             sizeof(tex->rendered_to[0]));
+   if (!tex->rendered_to) {
+      FREE(tex->defined);
+      FREE(tex);
+      return NULL;
+   }
 
    tex->b.b = *template;
    tex->b.vtbl = &svga_texture_vtbl;
    pipe_reference_init(&tex->b.b.reference, 1);
    tex->b.b.screen = screen;
 
-   assert(template->last_level < SVGA_MAX_TEXTURE_LEVELS);
-   if(template->last_level >= SVGA_MAX_TEXTURE_LEVELS)
-      goto error2;
-   
    tex->key.flags = 0;
    tex->key.size.width = template->width0;
    tex->key.size.height = template->height0;
    tex->key.size.depth = template->depth0;
+   tex->key.arraySize = 1;
+   tex->key.numFaces = 1;
+   tex->key.sampleCount = template->nr_samples;
 
-   if(template->target == PIPE_TEXTURE_CUBE) {
-      tex->key.flags |= SVGA3D_SURFACE_CUBEMAP;
-      tex->key.numFaces = 6;
-   }
-   else {
-      tex->key.numFaces = 1;
+   if (template->nr_samples > 1) {
+      tex->key.flags |= SVGA3D_SURFACE_MASKABLE_ANTIALIAS;
    }
 
-   if (template->target == PIPE_TEXTURE_3D) {
-      tex->key.flags |= SVGA3D_SURFACE_VOLUME;
+   if (svgascreen->sws->have_vgpu10) {
+      switch (template->target) {
+      case PIPE_TEXTURE_1D:
+         tex->key.flags |= SVGA3D_SURFACE_1D;
+         break;
+      case PIPE_TEXTURE_1D_ARRAY:
+         tex->key.flags |= SVGA3D_SURFACE_1D;
+         /* fall-through */
+      case PIPE_TEXTURE_2D_ARRAY:
+         tex->key.flags |= SVGA3D_SURFACE_ARRAY;
+         tex->key.arraySize = template->array_size;
+         break;
+      case PIPE_TEXTURE_3D:
+         tex->key.flags |= SVGA3D_SURFACE_VOLUME;
+         break;
+      case PIPE_TEXTURE_CUBE:
+         tex->key.flags |= (SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_ARRAY);
+         tex->key.numFaces = 6;
+         break;
+      default:
+         break;
+      }
+   }
+   else {
+      switch (template->target) {
+      case PIPE_TEXTURE_3D:
+         tex->key.flags |= SVGA3D_SURFACE_VOLUME;
+         break;
+      case PIPE_TEXTURE_CUBE:
+         tex->key.flags |= SVGA3D_SURFACE_CUBEMAP;
+         tex->key.numFaces = 6;
+         break;
+      default:
+         break;
+      }
    }
 
    tex->key.cachable = 1;
 
-   if (template->bind & PIPE_BIND_SAMPLER_VIEW)
+   if (bindings & PIPE_BIND_SAMPLER_VIEW) {
       tex->key.flags |= SVGA3D_SURFACE_HINT_TEXTURE;
+      tex->key.flags |= SVGA3D_SURFACE_BIND_SHADER_RESOURCE;
+
+      if (!(bindings & PIPE_BIND_RENDER_TARGET)) {
+         /* Also check if the format is renderable */
+         if (screen->is_format_supported(screen, template->format,
+                                         template->target,
+                                         template->nr_samples,
+                                         PIPE_BIND_RENDER_TARGET)) {
+            bindings |= PIPE_BIND_RENDER_TARGET;
+         }
+      }
+   }
 
-   if (template->bind & PIPE_BIND_DISPLAY_TARGET) {
+   if (bindings & PIPE_BIND_DISPLAY_TARGET) {
       tex->key.cachable = 0;
    }
 
-   if (template->bind & PIPE_BIND_SHARED) {
+   if (bindings & PIPE_BIND_SHARED) {
       tex->key.cachable = 0;
    }
 
-   if (template->bind & (PIPE_BIND_SCANOUT |
-                         PIPE_BIND_CURSOR)) {
-      tex->key.flags |= SVGA3D_SURFACE_HINT_SCANOUT;
+   if (bindings & (PIPE_BIND_SCANOUT | PIPE_BIND_CURSOR)) {
+      tex->key.scanout = 1;
       tex->key.cachable = 0;
    }
 
-   /* 
+   /*
     * Note: Previously we never passed the
     * SVGA3D_SURFACE_HINT_RENDERTARGET hint. Mesa cannot
     * know beforehand whether a texture will be used as a rendertarget or not
@@ -712,23 +833,55 @@ svga_texture_create(struct pipe_screen *screen,
     * (XA for example) uses it accurately and certain device versions
     * relies on it in certain situations to render correctly.
     */
-   if((template->bind & PIPE_BIND_RENDER_TARGET) &&
-      !util_format_is_s3tc(template->format))
+   if ((bindings & PIPE_BIND_RENDER_TARGET) &&
+       !util_format_is_s3tc(template->format)) {
       tex->key.flags |= SVGA3D_SURFACE_HINT_RENDERTARGET;
-   
-   if(template->bind & PIPE_BIND_DEPTH_STENCIL)
+      tex->key.flags |= SVGA3D_SURFACE_BIND_RENDER_TARGET;
+   }
+
+   if (bindings & PIPE_BIND_DEPTH_STENCIL) {
       tex->key.flags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL;
-   
+      tex->key.flags |= SVGA3D_SURFACE_BIND_DEPTH_STENCIL;
+   }
+
    tex->key.numMipLevels = template->last_level + 1;
-   
-   tex->key.format = svga_translate_format(svgascreen, template->format, template->bind);
-   if(tex->key.format == SVGA3D_FORMAT_INVALID)
-      goto error2;
+
+   tex->key.format = svga_translate_format(svgascreen, template->format,
+                                           bindings);
+   if (tex->key.format == SVGA3D_FORMAT_INVALID) {
+      FREE(tex->defined);
+      FREE(tex->rendered_to);
+      FREE(tex);
+      return NULL;
+   }
+
+   /* Use typeless formats for sRGB and depth resources.  Typeless
+    * formats can be reinterpreted as other formats.  For example,
+    * SVGA3D_R8G8B8A8_UNORM_TYPELESS can be interpreted as
+    * SVGA3D_R8G8B8A8_UNORM_SRGB or SVGA3D_R8G8B8A8_UNORM.
+    */
+   if (svgascreen->sws->have_vgpu10 &&
+       (util_format_is_srgb(template->format) ||
+        format_has_depth(template->format))) {
+      SVGA3dSurfaceFormat typeless = svga_typeless_format(tex->key.format);
+      if (0) {
+         debug_printf("Convert resource type %s -> %s (bind 0x%x)\n",
+                      svga_format_name(tex->key.format),
+                      svga_format_name(typeless),
+                      bindings);
+      }
+      tex->key.format = typeless;
+   }
 
    SVGA_DBG(DEBUG_DMA, "surface_create for texture\n", tex->handle);
-   tex->handle = svga_screen_surface_create(svgascreen, &tex->key);
-   if (!tex->handle)
-       goto error2;
+   tex->handle = svga_screen_surface_create(svgascreen, bindings,
+                                            tex->b.b.usage, &tex->key);
+   if (!tex->handle) {
+      FREE(tex->defined);
+      FREE(tex->rendered_to);
+      FREE(tex);
+      return NULL;
+   }
 
    SVGA_DBG(DEBUG_DMA, "  --> got sid %p (texture)\n", tex->handle);
 
@@ -738,18 +891,7 @@ svga_texture_create(struct pipe_screen *screen,
    tex->size = util_resource_size(template);
    svgascreen->total_resource_bytes += tex->size;
 
-   tex->rendered_to = CALLOC(template->depth0 * template->array_size,
-                             sizeof(tex->rendered_to[0]));
-   if (!tex->rendered_to)
-      goto error2;
-
    return &tex->b.b;
-
-error2:
-   FREE(tex->rendered_to);
-   FREE(tex);
-error1:
-   return NULL;
 }
 
 
@@ -777,16 +919,28 @@ svga_texture_from_handle(struct pipe_screen *screen,
    if (!srf)
       return NULL;
 
-   if (svga_translate_format(svga_screen(screen), template->format, template->bind) != format) {
-      unsigned f1 = svga_translate_format(svga_screen(screen), template->format, template->bind);
+   if (svga_translate_format(svga_screen(screen), template->format,
+                             template->bind) != format) {
+      unsigned f1 = svga_translate_format(svga_screen(screen),
+                                          template->format, template->bind);
       unsigned f2 = format;
 
-      /* It's okay for XRGB and ARGB or depth with/out stencil to get mixed up */
-      if ( !( (f1 == SVGA3D_X8R8G8B8 && f2 == SVGA3D_A8R8G8B8) ||
+      /* It's okay for XRGB and ARGB or depth with/out stencil to get mixed up.
+       */
+      if (f1 == SVGA3D_B8G8R8A8_UNORM)
+         f1 = SVGA3D_A8R8G8B8;
+      if (f1 == SVGA3D_B8G8R8X8_UNORM)
+         f1 = SVGA3D_X8R8G8B8;
+
+      if ( !( (f1 == f2) ||
+              (f1 == SVGA3D_X8R8G8B8 && f2 == SVGA3D_A8R8G8B8) ||
+              (f1 == SVGA3D_X8R8G8B8 && f2 == SVGA3D_B8G8R8X8_UNORM) ||
               (f1 == SVGA3D_A8R8G8B8 && f2 == SVGA3D_X8R8G8B8) ||
+              (f1 == SVGA3D_A8R8G8B8 && f2 == SVGA3D_B8G8R8A8_UNORM) ||
               (f1 == SVGA3D_Z_D24X8 && f2 == SVGA3D_Z_D24S8) ||
               (f1 == SVGA3D_Z_DF24 && f2 == SVGA3D_Z_D24S8_INT) ) ) {
-         debug_printf("%s wrong format %u != %u\n", __FUNCTION__, f1, f2);
+         debug_printf("%s wrong format %s != %s\n", __FUNCTION__,
+                      svga_format_name(f1), svga_format_name(f2));
          return NULL;
       }
    }
@@ -795,6 +949,13 @@ svga_texture_from_handle(struct pipe_screen *screen,
    if (!tex)
       return NULL;
 
+   tex->defined = CALLOC(template->depth0 * template->array_size,
+                         sizeof(tex->defined[0]));
+   if (!tex->defined) {
+      FREE(tex);
+      return NULL;
+   }
+
    tex->b.b = *template;
    tex->b.vtbl = &svga_texture_vtbl;
    pipe_reference_init(&tex->b.b.reference, 1);
@@ -803,9 +964,11 @@ svga_texture_from_handle(struct pipe_screen *screen,
    SVGA_DBG(DEBUG_DMA, "wrap surface sid %p\n", srf);
 
    tex->key.cachable = 0;
+   tex->key.format = format;
    tex->handle = srf;
 
    tex->rendered_to = CALLOC(1, sizeof(tex->rendered_to[0]));
+   tex->imported = TRUE;
 
    return &tex->b.b;
 }
index 19dadfb88285647f10807a4bc2bb41dd8da1b090..0326907240e172bddf8a8a96b3d1e4ab282161d6 100644 (file)
@@ -51,7 +51,7 @@ struct svga_texture
 {
    struct u_resource b;
 
-   boolean defined[6][SVGA_MAX_TEXTURE_LEVELS];
+   ushort *defined;
    
    struct svga_sampler_view *cached_view;
 
@@ -77,6 +77,12 @@ struct svga_texture
     */
    struct svga_winsys_surface *handle;
 
+   /**
+    * Whether the host side surface is imported and not created by this
+    * driver.
+    */
+   boolean imported;
+
    unsigned size;  /**< Approximate size in bytes */
 
    /** array indexed by cube face or 3D/array slice, one bit per mipmap level */
@@ -91,7 +97,7 @@ struct svga_transfer
 {
    struct pipe_transfer base;
 
-   unsigned face;
+   unsigned slice;  /**< array slice or cube face */
 
    struct svga_winsys_buffer *hwbuf;
 
@@ -135,29 +141,6 @@ svga_age_texture_view(struct svga_texture *tex, unsigned level)
 }
 
 
-/**
- * Mark the given texture face/level as being defined.
- */
-static inline void
-svga_define_texture_level(struct svga_texture *tex,
-                          unsigned face,unsigned level)
-{
-   assert(face < Elements(tex->defined));
-   assert(level < Elements(tex->defined[0]));
-   tex->defined[face][level] = TRUE;
-}
-
-
-static inline bool
-svga_is_texture_level_defined(const struct svga_texture *tex,
-                              unsigned face, unsigned level)
-{
-   assert(face < Elements(tex->defined));
-   assert(level < Elements(tex->defined[0]));
-   return tex->defined[face][level];
-}
-
-
 /** For debugging, check that face and level are legal */
 static inline void
 check_face_level(const struct svga_texture *tex,
@@ -177,6 +160,27 @@ check_face_level(const struct svga_texture *tex,
 }
 
 
+/**
+ * Mark the given texture face/level as being defined.
+ */
+static inline void
+svga_define_texture_level(struct svga_texture *tex,
+                          unsigned face,unsigned level)
+{
+   check_face_level(tex, face, level);
+   tex->defined[face] |= 1 << level;
+}
+
+
+static inline bool
+svga_is_texture_level_defined(const struct svga_texture *tex,
+                              unsigned face, unsigned level)
+{
+   check_face_level(tex, face, level);
+   return (tex->defined[face] & (1 << level)) != 0;
+}
+
+
 static inline void
 svga_set_texture_rendered_to(struct svga_texture *tex,
                              unsigned face, unsigned level)
index 55dc49f2d2c7e6b98ec29d8acd4e95017042f580..ffa5bce80c0bff3bec55ced699ebd5bcdc5363f9 100644 (file)
@@ -67,7 +67,7 @@ svga_get_tex_sampler_view(struct pipe_context *pipe,
    assert(pt);
    assert(min_lod <= max_lod);
    assert(max_lod <= pt->last_level);
-
+   assert(!svga_have_vgpu10(svga));
 
    /* Is a view needed */
    {
@@ -143,10 +143,12 @@ svga_get_tex_sampler_view(struct pipe_context *pipe,
             pt->last_level);
 
    sv->age = tex->age;
-   sv->handle = svga_texture_view_surface(svga, tex, flags, format,
+   sv->handle = svga_texture_view_surface(svga, tex,
+                                          PIPE_BIND_SAMPLER_VIEW,
+                                          flags, format,
                                           min_lod,
                                           max_lod - min_lod + 1,
-                                          -1, -1,
+                                          -1, 1, -1,
                                           &sv->key);
 
    if (!sv->handle) {
@@ -177,6 +179,7 @@ svga_validate_sampler_view(struct svga_context *svga, struct svga_sampler_view *
    unsigned k;
 
    assert(svga);
+   assert(!svga_have_vgpu10(svga));
 
    if (v->handle == tex->handle)
       return;
index 7f14323f84fdaf789031f2621ad64757e6110fa1..acd7ae0ca24d582a99b1ae0b73b11e3fd064c08b 100644 (file)
@@ -36,6 +36,7 @@ struct pipe_context;
 struct pipe_screen;
 struct svga_context;
 struct svga_winsys_surface;
+struct svga_surface;
 enum SVGA3dSurfaceFormat;
 
 
@@ -97,5 +98,8 @@ svga_sampler_view_reference(struct svga_sampler_view **ptr, struct svga_sampler_
    *ptr = v;
 }
 
+boolean
+svga_check_sampler_view_resource_collision(struct svga_context *svga,
+                                           struct svga_winsys_surface *res);
 
 #endif
index 66c3deaa9e7be6774f0f60b3f5c4890794c6ae9d..f2ae40b4fad991323dced78fdcb0765c4c44958e 100644 (file)
 #include "svga_context.h"
 #include "svga_format.h"
 #include "svga_screen.h"
+#include "svga_tgsi.h"
 #include "svga_resource_texture.h"
 #include "svga_resource.h"
 #include "svga_debug.h"
 
 #include "svga3d_shaderdefs.h"
+#include "VGPU10ShaderTokens.h"
 
+/* NOTE: this constant may get moved into a svga3d*.h header file */
+#define SVGA3D_DX_MAX_RESOURCE_SIZE (128 * 1024 * 1024)
 
 #ifdef DEBUG
 int SVGA_DEBUG = 0;
 
 static const struct debug_named_value svga_debug_flags[] = {
-   { "dma",      DEBUG_DMA, NULL },
-   { "tgsi",     DEBUG_TGSI, NULL },
-   { "pipe",     DEBUG_PIPE, NULL },
-   { "state",    DEBUG_STATE, NULL },
-   { "screen",   DEBUG_SCREEN, NULL },
-   { "tex",      DEBUG_TEX, NULL },
-   { "swtnl",    DEBUG_SWTNL, NULL },
-   { "const",    DEBUG_CONSTS, NULL },
-   { "viewport", DEBUG_VIEWPORT, NULL },
-   { "views",    DEBUG_VIEWS, NULL },
-   { "perf",     DEBUG_PERF, NULL },
-   { "flush",    DEBUG_FLUSH, NULL },
-   { "sync",     DEBUG_SYNC, NULL },
-   { "cache",    DEBUG_CACHE, NULL },
+   { "dma",         DEBUG_DMA, NULL },
+   { "tgsi",        DEBUG_TGSI, NULL },
+   { "pipe",        DEBUG_PIPE, NULL },
+   { "state",       DEBUG_STATE, NULL },
+   { "screen",      DEBUG_SCREEN, NULL },
+   { "tex",         DEBUG_TEX, NULL },
+   { "swtnl",       DEBUG_SWTNL, NULL },
+   { "const",       DEBUG_CONSTS, NULL },
+   { "viewport",    DEBUG_VIEWPORT, NULL },
+   { "views",       DEBUG_VIEWS, NULL },
+   { "perf",        DEBUG_PERF, NULL },
+   { "flush",       DEBUG_FLUSH, NULL },
+   { "sync",        DEBUG_SYNC, NULL },
+   { "cache",       DEBUG_CACHE, NULL },
+   { "streamout",   DEBUG_STREAMOUT, NULL },
+   { "query",       DEBUG_QUERY, NULL },
    DEBUG_NAMED_VALUE_END
 };
 #endif
@@ -80,18 +86,52 @@ svga_get_name( struct pipe_screen *pscreen )
     */
    build = "build: DEBUG;";
    mutex = "mutex: " PIPE_ATOMIC ";";
-#ifdef HAVE_LLVM
-   llvm = "LLVM;";
-#endif
 #else
    build = "build: RELEASE;";
 #endif
+#ifdef HAVE_LLVM
+   llvm = "LLVM;";
+#endif
 
    util_snprintf(name, sizeof(name), "SVGA3D; %s %s %s", build, mutex, llvm);
    return name;
 }
 
 
+/** Helper for querying float-valued device cap */
+static float
+get_float_cap(struct svga_winsys_screen *sws, unsigned cap, float defaultVal)
+{
+   SVGA3dDevCapResult result;
+   if (sws->get_cap(sws, cap, &result))
+      return result.f;
+   else
+      return defaultVal;
+}
+
+
+/** Helper for querying uint-valued device cap */
+static unsigned
+get_uint_cap(struct svga_winsys_screen *sws, unsigned cap, unsigned defaultVal)
+{
+   SVGA3dDevCapResult result;
+   if (sws->get_cap(sws, cap, &result))
+      return result.u;
+   else
+      return defaultVal;
+}
+
+
+/** Helper for querying boolean-valued device cap */
+static boolean
+get_bool_cap(struct svga_winsys_screen *sws, unsigned cap, boolean defaultVal)
+{
+   SVGA3dDevCapResult result;
+   if (sws->get_cap(sws, cap, &result))
+      return result.b;
+   else
+      return defaultVal;
+}
 
 
 static float
@@ -99,7 +139,6 @@ svga_get_paramf(struct pipe_screen *screen, enum pipe_capf param)
 {
    struct svga_screen *svgascreen = svga_screen(screen);
    struct svga_winsys_screen *sws = svgascreen->sws;
-   SVGA3dDevCapResult result;
 
    switch (param) {
    case PIPE_CAPF_MAX_LINE_WIDTH:
@@ -113,12 +152,11 @@ svga_get_paramf(struct pipe_screen *screen, enum pipe_capf param)
       return svgascreen->maxPointSize;
 
    case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
-      if(!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY, &result))
-         return 4.0f;
-      return (float) result.u;
+      return (float) get_uint_cap(sws, SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY, 4);
 
    case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
       return 15.0;
+
    case PIPE_CAPF_GUARD_BAND_LEFT:
    case PIPE_CAPF_GUARD_BAND_TOP:
    case PIPE_CAPF_GUARD_BAND_RIGHT:
@@ -145,7 +183,12 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_TWO_SIDED_STENCIL:
       return 1;
    case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
-      return 0;
+      /*
+       * "In virtually every OpenGL implementation and hardware,
+       * GL_MAX_DUAL_SOURCE_DRAW_BUFFERS is 1"
+       * http://www.opengl.org/wiki/Blending
+       */
+      return sws->have_vgpu10 ? 1 : 0;
    case PIPE_CAP_ANISOTROPIC_FILTER:
       return 1;
    case PIPE_CAP_POINT_SPRITE:
@@ -158,6 +201,8 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
       return 1;
    case PIPE_CAP_QUERY_TIME_ELAPSED:
       return 0;
+   case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
+      return sws->have_vgpu10;
    case PIPE_CAP_TEXTURE_SHADOW_MAP:
       return 1;
    case PIPE_CAP_TEXTURE_SWIZZLE:
@@ -170,7 +215,7 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_USER_CONSTANT_BUFFERS:
       return 1;
    case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
-      return 16;
+      return 256;
 
    case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
       {
@@ -199,17 +244,20 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
       return MIN2(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS),
                   12 /* 2048x2048 */);
 
+   case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
+      return sws->have_vgpu10 ? SVGA3D_MAX_SURFACE_ARRAYSIZE : 0;
+
    case PIPE_CAP_BLEND_EQUATION_SEPARATE: /* req. for GL 1.5 */
       return 1;
 
    case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
       return 1;
    case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
-      return 0;
+      return sws->have_vgpu10;
    case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
       return 0;
    case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
-      return 1;
+      return !sws->have_vgpu10;
 
    case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
       return 1; /* The color outputs of vertex shaders are not clamped */
@@ -222,7 +270,7 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
       return 1; /* expected for GL_ARB_framebuffer_object */
 
    case PIPE_CAP_GLSL_FEATURE_LEVEL:
-      return 120;
+      return sws->have_vgpu10 ? 330 : 120;
 
    case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
       return 0;
@@ -230,49 +278,65 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_SM3:
       return 1;
 
-   /* Unsupported features */
-   case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
-   case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
-   case PIPE_CAP_SHADER_STENCIL_EXPORT:
    case PIPE_CAP_DEPTH_CLIP_DISABLE:
-   case PIPE_CAP_SEAMLESS_CUBE_MAP:
-   case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
    case PIPE_CAP_INDEP_BLEND_ENABLE:
-   case PIPE_CAP_INDEP_BLEND_FUNC:
-   case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
-   case PIPE_CAP_PRIMITIVE_RESTART:
+   case PIPE_CAP_CONDITIONAL_RENDER:
+   case PIPE_CAP_QUERY_TIMESTAMP:
    case PIPE_CAP_TGSI_INSTANCEID:
    case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
-   case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
+   case PIPE_CAP_SEAMLESS_CUBE_MAP:
+   case PIPE_CAP_FAKE_SW_MSAA:
+      return sws->have_vgpu10;
+
+   case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
+      return sws->have_vgpu10 ? SVGA3D_DX_MAX_SOTARGETS : 0;
+   case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
+      return sws->have_vgpu10 ? 4 : 0;
+   case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
+      return sws->have_vgpu10 ? SVGA3D_MAX_STREAMOUT_DECLS : 0;
+   case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
+      return 0;
+   case PIPE_CAP_TEXTURE_MULTISAMPLE:
+      return svgascreen->ms_samples ? 1 : 0;
+
+   case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
+      return SVGA3D_DX_MAX_RESOURCE_SIZE;
+
    case PIPE_CAP_MIN_TEXEL_OFFSET:
+      return sws->have_vgpu10 ? VGPU10_MIN_TEXEL_FETCH_OFFSET : 0;
    case PIPE_CAP_MAX_TEXEL_OFFSET:
+      return sws->have_vgpu10 ? VGPU10_MAX_TEXEL_FETCH_OFFSET : 0;
+
    case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET:
    case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET:
-   case PIPE_CAP_CONDITIONAL_RENDER:
-   case PIPE_CAP_TEXTURE_BARRIER:
-   case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
-   case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
-   case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
+      return 0;
+
    case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:
+      return sws->have_vgpu10 ? 256 : 0;
    case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
+      return sws->have_vgpu10 ? 1024 : 0;
+
+   case PIPE_CAP_PRIMITIVE_RESTART:
+      return 1; /* may be a sw fallback, depending on restart index */
+
+   /* Unsupported features */
+   case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
+   case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+   case PIPE_CAP_SHADER_STENCIL_EXPORT:
+   case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
+   case PIPE_CAP_INDEP_BLEND_FUNC:
+   case PIPE_CAP_TEXTURE_BARRIER:
    case PIPE_CAP_MAX_VERTEX_STREAMS:
    case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
-   case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
-   case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
    case PIPE_CAP_COMPUTE:
    case PIPE_CAP_START_INSTANCE:
-   case PIPE_CAP_QUERY_TIMESTAMP:
-   case PIPE_CAP_TEXTURE_MULTISAMPLE:
    case PIPE_CAP_CUBE_MAP_ARRAY:
-   case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
    case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
    case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
-   case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
    case PIPE_CAP_TGSI_VS_LAYER_VIEWPORT:
    case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
    case PIPE_CAP_TEXTURE_GATHER_SM5:
    case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT:
-   case PIPE_CAP_FAKE_SW_MSAA:
    case PIPE_CAP_TEXTURE_QUERY_LOD:
    case PIPE_CAP_SAMPLE_SHADING:
    case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
@@ -288,8 +352,10 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
       return 0;
    case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
       return 64;
+   case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
+   case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
    case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
-      return 1;
+      return 1;  /* need 4-byte alignment for all offsets and strides */
    case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:
       return 2048;
    case PIPE_CAP_MAX_VIEWPORTS:
@@ -320,11 +386,16 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
    return 0;
 }
 
-static int svga_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap param)
+
+static int
+vgpu9_get_shader_param(struct pipe_screen *screen, unsigned shader,
+                       enum pipe_shader_cap param)
 {
    struct svga_screen *svgascreen = svga_screen(screen);
    struct svga_winsys_screen *sws = svgascreen->sws;
-   SVGA3dDevCapResult result;
+   unsigned val;
+
+   assert(!sws->have_vgpu10);
 
    switch (shader)
    {
@@ -347,9 +418,8 @@ static int svga_get_shader_param(struct pipe_screen *screen, unsigned shader, en
       case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
          return 1;
       case PIPE_SHADER_CAP_MAX_TEMPS:
-         if (!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS, &result))
-            return 32;
-         return MIN2(result.u, SVGA3D_TEMPREG_MAX);
+         val = get_uint_cap(sws, SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS, 32);
+         return MIN2(val, SVGA3D_TEMPREG_MAX);
       case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
         /* 
          * Although PS 3.0 has some addressing abilities it can only represent
@@ -392,9 +462,8 @@ static int svga_get_shader_param(struct pipe_screen *screen, unsigned shader, en
       {
       case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
       case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
-         if (!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS, &result))
-            return 512;
-         return result.u;
+         return get_uint_cap(sws, SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS,
+                             512);
       case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
       case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
          /* XXX: until we have vertex texture support */
@@ -410,9 +479,8 @@ static int svga_get_shader_param(struct pipe_screen *screen, unsigned shader, en
       case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
          return 1;
       case PIPE_SHADER_CAP_MAX_TEMPS:
-         if (!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS, &result))
-            return 32;
-         return MIN2(result.u, SVGA3D_TEMPREG_MAX);
+         val = get_uint_cap(sws, SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS, 32);
+         return MIN2(val, SVGA3D_TEMPREG_MAX);
       case PIPE_SHADER_CAP_MAX_PREDS:
          return 1;
       case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
@@ -459,8 +527,102 @@ static int svga_get_shader_param(struct pipe_screen *screen, unsigned shader, en
 }
 
 
+static int
+vgpu10_get_shader_param(struct pipe_screen *screen, unsigned shader,
+                        enum pipe_shader_cap param)
+{
+   struct svga_screen *svgascreen = svga_screen(screen);
+   struct svga_winsys_screen *sws = svgascreen->sws;
+
+   assert(sws->have_vgpu10);
+   (void) sws;  /* silence unused var warnings in non-debug builds */
+
+   /* Only VS, GS, FS supported */
+   if (shader != PIPE_SHADER_VERTEX &&
+       shader != PIPE_SHADER_GEOMETRY &&
+       shader != PIPE_SHADER_FRAGMENT) {
+      return 0;
+   }
+
+   /* NOTE: we do not query the device for any caps/limits at this time */
+
+   /* Generally the same limits for vertex, geometry and fragment shaders */
+   switch (param) {
+   case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
+   case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
+   case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
+   case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
+      return 64 * 1024;
+   case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
+      return 64;
+   case PIPE_SHADER_CAP_MAX_INPUTS:
+      if (shader == PIPE_SHADER_FRAGMENT)
+         return VGPU10_MAX_FS_INPUTS;
+      else if (shader == PIPE_SHADER_GEOMETRY)
+         return VGPU10_MAX_GS_INPUTS;
+      else
+         return VGPU10_MAX_VS_INPUTS;
+   case PIPE_SHADER_CAP_MAX_OUTPUTS:
+      if (shader == PIPE_SHADER_FRAGMENT)
+         return VGPU10_MAX_FS_OUTPUTS;
+      else if (shader == PIPE_SHADER_GEOMETRY)
+         return VGPU10_MAX_GS_OUTPUTS;
+      else
+         return VGPU10_MAX_VS_OUTPUTS;
+   case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
+      return VGPU10_MAX_CONSTANT_BUFFER_ELEMENT_COUNT * sizeof(float[4]);
+   case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
+      return svgascreen->max_const_buffers;
+   case PIPE_SHADER_CAP_MAX_TEMPS:
+      return VGPU10_MAX_TEMPS;
+   case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
+   case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
+   case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
+   case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
+      return TRUE; /* XXX verify */
+   case PIPE_SHADER_CAP_MAX_PREDS:
+      return 0;
+   case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
+   case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
+   case PIPE_SHADER_CAP_SUBROUTINES:
+   case PIPE_SHADER_CAP_INTEGERS:
+      return TRUE;
+   case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
+   case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
+      return SVGA3D_DX_MAX_SAMPLERS;
+   case PIPE_SHADER_CAP_PREFERRED_IR:
+      return PIPE_SHADER_IR_TGSI;
+   case PIPE_SHADER_CAP_DOUBLES:
+   case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
+   case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:
+   case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
+   case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
+      return 0;
+   default:
+      debug_printf("Unexpected vgpu10 shader query %u\n", param);
+      return 0;
+   }
+   return 0;
+}
+
+
+static int
+svga_get_shader_param(struct pipe_screen *screen, unsigned shader,
+                      enum pipe_shader_cap param)
+{
+   struct svga_screen *svgascreen = svga_screen(screen);
+   struct svga_winsys_screen *sws = svgascreen->sws;
+   if (sws->have_vgpu10) {
+      return vgpu10_get_shader_param(screen, shader, param);
+   }
+   else {
+      return vgpu9_get_shader_param(screen, shader, param);
+   }
+}
+
+
 /**
- * Implemnt pipe_screen::is_format_supported().
+ * Implement pipe_screen::is_format_supported().
  * \param bindings  bitmask of PIPE_BIND_x flags
  */
 static boolean
@@ -478,7 +640,12 @@ svga_is_format_supported( struct pipe_screen *screen,
    assert(bindings);
 
    if (sample_count > 1) {
-      return FALSE;
+      /* 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);
@@ -486,6 +653,22 @@ svga_is_format_supported( struct pipe_screen *screen,
       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.
@@ -498,6 +681,12 @@ svga_is_format_supported( struct pipe_screen *screen,
       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.
        */
@@ -516,22 +705,32 @@ svga_is_format_supported( struct pipe_screen *screen,
 
    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.offscreenRenderTarget = 1;
+      mask.value |= SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET;
    }
    if (bindings & PIPE_BIND_DEPTH_STENCIL) {
-      mask.zStencil = 1;
+      mask.value |= SVGA3DFORMAT_OP_ZSTENCIL;
    }
    if (bindings & PIPE_BIND_SAMPLER_VIEW) {
-      mask.texture = 1;
+      mask.value |= SVGA3DFORMAT_OP_TEXTURE;
    }
 
    if (target == PIPE_TEXTURE_CUBE) {
-      mask.cubeTexture = 1;
+      mask.value |= SVGA3DFORMAT_OP_CUBETEXTURE;
    }
-   if (target == PIPE_TEXTURE_3D) {
-      mask.volumeTexture = 1;
+   else if (target == PIPE_TEXTURE_3D) {
+      mask.value |= SVGA3DFORMAT_OP_VOLUMETEXTURE;
    }
 
    return (caps.value & mask.value) == mask.value;
@@ -611,8 +810,6 @@ svga_screen_create(struct svga_winsys_screen *sws)
 {
    struct svga_screen *svgascreen;
    struct pipe_screen *screen;
-   SVGA3dDevCapResult result;
-   boolean use_vs30, use_ps30;
 
 #ifdef DEBUG
    SVGA_DEBUG = debug_get_flags_option("SVGA_DEBUG", svga_debug_flags, 0 );
@@ -642,6 +839,7 @@ svga_screen_create(struct svga_winsys_screen *sws)
    screen->get_param = svga_get_param;
    screen->get_shader_param = svga_get_shader_param;
    screen->get_paramf = svga_get_paramf;
+   screen->get_timestamp = NULL;
    screen->is_format_supported = svga_is_format_supported;
    screen->context_create = svga_context_create;
    screen->fence_reference = svga_fence_reference;
@@ -657,18 +855,6 @@ svga_screen_create(struct svga_winsys_screen *sws)
       svgascreen->hw_version = SVGA3D_HWVERSION_WS65_B1;
    }
 
-   use_ps30 =
-      sws->get_cap(sws, SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION, &result) &&
-      result.u >= SVGA3DPSVERSION_30 ? TRUE : FALSE;
-
-   use_vs30 =
-      sws->get_cap(sws, SVGA3D_DEVCAP_VERTEX_SHADER_VERSION, &result) &&
-      result.u >= SVGA3DVSVERSION_30 ? TRUE : FALSE;
-
-   /* we require Shader model 3.0 or later */
-   if (!use_ps30 || !use_vs30)
-      goto error2;
-
    /*
     * The D16, D24X8, and D24S8 formats always do an implicit shadow compare
     * when sampled from, where as the DF16, DF24, and D24S8_INT do not.  So
@@ -716,46 +902,77 @@ svga_screen_create(struct svga_winsys_screen *sws)
 
    /* Query device caps
     */
-   if (!sws->get_cap(sws, SVGA3D_DEVCAP_LINE_STIPPLE, &result))
-      svgascreen->haveLineStipple = FALSE;
-   else
-      svgascreen->haveLineStipple = result.u;
+   if (sws->have_vgpu10) {
+      svgascreen->haveProvokingVertex
+         = get_bool_cap(sws, SVGA3D_DEVCAP_DX_PROVOKING_VERTEX, FALSE);
+      svgascreen->haveLineSmooth = TRUE;
+      svgascreen->maxPointSize = 80.0F;
+      svgascreen->max_color_buffers = SVGA3D_DX_MAX_RENDER_TARGETS;
+
+      /* Multisample samples per pixel */
+      svgascreen->ms_samples =
+         get_uint_cap(sws, SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES, 0);
+
+      /* Maximum number of constant buffers */
+      svgascreen->max_const_buffers =
+         get_uint_cap(sws, SVGA3D_DEVCAP_DX_MAX_CONSTANT_BUFFERS, 1);
+      assert(svgascreen->max_const_buffers <= SVGA_MAX_CONST_BUFS);
+   }
+   else {
+      /* VGPU9 */
+      unsigned vs_ver = get_uint_cap(sws, SVGA3D_DEVCAP_VERTEX_SHADER_VERSION,
+                                     SVGA3DVSVERSION_NONE);
+      unsigned fs_ver = get_uint_cap(sws, SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION,
+                                     SVGA3DPSVERSION_NONE);
+
+      /* we require Shader model 3.0 or later */
+      if (fs_ver < SVGA3DPSVERSION_30 || vs_ver < SVGA3DVSVERSION_30) {
+         goto error2;
+      }
 
-   if (!sws->get_cap(sws, SVGA3D_DEVCAP_LINE_AA, &result))
-      svgascreen->haveLineSmooth = FALSE;
-   else
-      svgascreen->haveLineSmooth = result.u;
+      svgascreen->haveProvokingVertex = FALSE;
 
-   if (!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_LINE_WIDTH, &result))
-      svgascreen->maxLineWidth = 1.0F;
-   else
-      svgascreen->maxLineWidth = result.f;
+      svgascreen->haveLineSmooth =
+         get_bool_cap(sws, SVGA3D_DEVCAP_LINE_AA, FALSE);
 
-   if (!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH, &result))
-      svgascreen->maxLineWidthAA = 1.0F;
-   else
-      svgascreen->maxLineWidthAA = result.f;
+      svgascreen->maxPointSize =
+         get_float_cap(sws, SVGA3D_DEVCAP_MAX_POINT_SIZE, 1.0f);
+      /* Keep this to a reasonable size to avoid failures in conform/pntaa.c */
+      svgascreen->maxPointSize = MIN2(svgascreen->maxPointSize, 80.0f);
+
+      /* The SVGA3D device always supports 4 targets at this time, regardless
+       * of what querying SVGA3D_DEVCAP_MAX_RENDER_TARGETS might return.
+       */
+      svgascreen->max_color_buffers = 4;
+
+      /* Only support one constant buffer
+       */
+      svgascreen->max_const_buffers = 1;
 
-   if (0)
+      /* No multisampling */
+      svgascreen->ms_samples = 0;
+   }
+
+   /* common VGPU9 / VGPU10 caps */
+   svgascreen->haveLineStipple =
+      get_bool_cap(sws, SVGA3D_DEVCAP_LINE_STIPPLE, FALSE);
+
+   svgascreen->maxLineWidth =
+      get_float_cap(sws, SVGA3D_DEVCAP_MAX_LINE_WIDTH, 1.0f);
+
+   svgascreen->maxLineWidthAA =
+      get_float_cap(sws, SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH, 1.0f);
+
+   if (0) {
+      debug_printf("svga: haveProvokingVertex %u\n",
+                   svgascreen->haveProvokingVertex);
       debug_printf("svga: haveLineStip %u  "
                    "haveLineSmooth %u  maxLineWidth %f\n",
                    svgascreen->haveLineStipple, svgascreen->haveLineSmooth,
                    svgascreen->maxLineWidth);
-
-   if (!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_POINT_SIZE, &result)) {
-      svgascreen->maxPointSize = 1.0F;
-   } else {
-      /* Keep this to a reasonable size to avoid failures in
-       * conform/pntaa.c:
-       */
-      svgascreen->maxPointSize = MIN2(result.f, 80.0f);
+      debug_printf("svga: maxPointSize %g\n", svgascreen->maxPointSize);
    }
 
-   /* The SVGA3D device always supports 4 targets at this time, regardless
-    * of what querying SVGA3D_DEVCAP_MAX_RENDER_TARGETS might return.
-    */
-   svgascreen->max_color_buffers = 4;
-
    pipe_mutex_init(svgascreen->tex_mutex);
    pipe_mutex_init(svgascreen->swc_mutex);
 
index ea1e743dfe5d991d20ced57cbcc3568e745b8f78..5581d2e1ffdac2e5f1efc939c4d9e90aef774ea3 100644 (file)
@@ -1,4 +1,4 @@
-/**********************************************************
+ /**********************************************************
  * Copyright 2008-2009 VMware, Inc.  All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person
@@ -48,10 +48,13 @@ struct svga_screen
    SVGA3dHardwareVersion hw_version;
 
    /** Device caps */
+   boolean haveProvokingVertex;
    boolean haveLineStipple, haveLineSmooth;
    float maxLineWidth, maxLineWidthAA;
    float maxPointSize;
    unsigned max_color_buffers;
+   unsigned max_const_buffers;
+   unsigned ms_samples;
 
    struct {
       boolean force_level_surface_view;
@@ -69,6 +72,7 @@ struct svga_screen
    /* which formats to translate depth formats into */
    struct {
      enum SVGA3dSurfaceFormat z16;
+
      /* note gallium order */
      enum SVGA3dSurfaceFormat x8z24;
      enum SVGA3dSurfaceFormat s8z24;
index f99a0b305a7615ee0a27e485b1f7c2e96ca6c908..5b4412957157607a9ceb95ecb5f251f17712e464 100644 (file)
@@ -115,8 +115,14 @@ svga_screen_cache_lookup(struct svga_screen *svgascreen,
 
       assert(entry->handle);
 
+      /* If the key matches and the fence is signalled (the surface is no
+       * longer needed) the lookup was successful.  We found a surface that
+       * can be reused.
+       * We unlink the surface from the cache entry and we add the entry to
+       * the 'empty' list.
+       */
       if (memcmp(&entry->key, key, sizeof *key) == 0 &&
-         sws->fence_signalled(sws, entry->fence, 0) == 0) {
+          sws->fence_signalled(sws, entry->fence, 0) == 0) {
          unsigned surf_size;
 
          assert(sws->surface_is_flushed(sws, entry->handle));
@@ -124,10 +130,13 @@ svga_screen_cache_lookup(struct svga_screen *svgascreen,
          handle = entry->handle; /* Reference is transfered here. */
          entry->handle = NULL;
 
+         /* Remove from hash table */
          LIST_DEL(&entry->bucket_head);
 
+         /* remove from LRU list */
          LIST_DEL(&entry->head);
 
+         /* Add the cache entry (but not the surface!) to the empty list */
          LIST_ADD(&entry->head, &cache->empty);
 
          /* update the cache size */
@@ -195,7 +204,8 @@ svga_screen_cache_shrink(struct svga_screen *svgascreen,
 
 
 /**
- * Transfers a handle reference.
+ * Add a surface to the cache.  This is done when the driver deletes
+ * the surface.  Note: transfers a handle reference.
  */
 static void
 svga_screen_cache_add(struct svga_screen *svgascreen,
@@ -207,17 +217,17 @@ svga_screen_cache_add(struct svga_screen *svgascreen,
    struct svga_host_surface_cache_entry *entry = NULL;
    struct svga_winsys_surface *handle = *p_handle;
    unsigned surf_size;
-   
+
    assert(key->cachable);
 
    if (!handle)
       return;
-   
+
    surf_size = surface_size(key);
 
    *p_handle = NULL;
    pipe_mutex_lock(cache->mutex);
-   
+
    if (surf_size >= SVGA_HOST_SURFACE_CACHE_BYTES) {
       /* this surface is too large to cache, just free it */
       sws->surface_reference(sws, &handle, NULL);
@@ -245,10 +255,13 @@ svga_screen_cache_add(struct svga_screen *svgascreen,
    }
 
    if (!LIST_IS_EMPTY(&cache->empty)) {
-      /* use the first empty entry */
+      /* An empty entry has no surface associated with it.
+       * Use the first empty entry.
+       */
       entry = LIST_ENTRY(struct svga_host_surface_cache_entry,
                          cache->empty.next, head);
 
+      /* Remove from LRU list */
       LIST_DEL(&entry->head);
    }
    else if (!LIST_IS_EMPTY(&cache->unused)) {
@@ -262,12 +275,15 @@ svga_screen_cache_add(struct svga_screen *svgascreen,
 
       sws->surface_reference(sws, &entry->handle, NULL);
 
+      /* Remove from hash table */
       LIST_DEL(&entry->bucket_head);
 
+      /* Remove from LRU list */
       LIST_DEL(&entry->head);
    }
 
    if (entry) {
+      assert(entry->handle == NULL);
       entry->handle = handle;
       memcpy(&entry->key, key, sizeof entry->key);
 
@@ -304,6 +320,7 @@ svga_screen_cache_flush(struct svga_screen *svgascreen,
 
    pipe_mutex_lock(cache->mutex);
 
+   /* Loop over entries in the validated list */
    curr = cache->validated.next;
    next = curr->next;
    while (curr != &cache->validated) {
@@ -312,12 +329,15 @@ svga_screen_cache_flush(struct svga_screen *svgascreen,
       assert(entry->handle);
 
       if (sws->surface_is_flushed(sws, entry->handle)) {
+         /* remove entry from LRU list */
          LIST_DEL(&entry->head);
 
          svgascreen->sws->fence_reference(svgascreen->sws, &entry->fence, fence);
 
+         /* Add entry to the unused list */
          LIST_ADD(&entry->head, &cache->unused);
 
+         /* Add entry to the hash table bucket */
          bucket = svga_screen_cache_bucket(&entry->key);
          LIST_ADD(&entry->bucket_head, &cache->bucket[bucket]);
       }
@@ -388,9 +408,12 @@ svga_screen_cache_init(struct svga_screen *svgascreen)
  * Allocate a new host-side surface.  If the surface is marked as cachable,
  * first try re-using a surface in the cache of freed surfaces.  Otherwise,
  * allocate a new surface.
+ * \param bind_flags  bitmask of PIPE_BIND_x flags
+ * \param usage  one of PIPE_USAGE_x values
  */
 struct svga_winsys_surface *
 svga_screen_surface_create(struct svga_screen *svgascreen,
+                           unsigned bind_flags, unsigned usage,
                            struct svga_host_surface_cache_key *key)
 {
    struct svga_winsys_screen *sws = svgascreen->sws;
@@ -398,17 +421,20 @@ svga_screen_surface_create(struct svga_screen *svgascreen,
    boolean cachable = SVGA_SURFACE_CACHE_ENABLED && key->cachable;
 
    SVGA_DBG(DEBUG_CACHE|DEBUG_DMA,
-            "%s sz %dx%dx%d mips %d faces %d cachable %d\n",
+            "%s sz %dx%dx%d mips %d faces %d arraySize %d cachable %d\n",
             __FUNCTION__,
             key->size.width,
             key->size.height,
             key->size.depth,
             key->numMipLevels,
             key->numFaces,
+            key->arraySize,
             key->cachable);
 
    if (cachable) {
       if (key->format == SVGA3D_BUFFER) {
+         SVGA3dSurfaceFlags hint_flag;
+
          /* For buffers, round the buffer size up to the nearest power
           * of two to increase the probability of cache hits.  Keep
           * texture surface dimensions unchanged.
@@ -417,15 +443,33 @@ svga_screen_surface_create(struct svga_screen *svgascreen,
          while (size < key->size.width)
             size <<= 1;
          key->size.width = size;
-        /* Since we're reusing buffers we're effectively transforming all
-         * of them into dynamic buffers.
-         *
-         * It would be nice to not cache long lived static buffers. But there
-         * is no way to detect the long lived from short lived ones yet. A
-         * good heuristic would be buffer size.
-         */
-        key->flags &= ~SVGA3D_SURFACE_HINT_STATIC;
-        key->flags |= SVGA3D_SURFACE_HINT_DYNAMIC;
+
+         /* Determine whether the buffer is static or dynamic.
+          * This is a bit of a heuristic which can be tuned as needed.
+          */
+         if (usage == PIPE_USAGE_DEFAULT ||
+             usage == PIPE_USAGE_IMMUTABLE) {
+            hint_flag = SVGA3D_SURFACE_HINT_STATIC;
+         }
+         else if (bind_flags & PIPE_BIND_INDEX_BUFFER) {
+            /* Index buffers don't change too often.  Mark them as static.
+             */
+            hint_flag = SVGA3D_SURFACE_HINT_STATIC;
+         }
+         else {
+            /* Since we're reusing buffers we're effectively transforming all
+             * of them into dynamic buffers.
+             *
+             * It would be nice to not cache long lived static buffers. But there
+             * is no way to detect the long lived from short lived ones yet. A
+             * good heuristic would be buffer size.
+             */
+            hint_flag = SVGA3D_SURFACE_HINT_DYNAMIC;
+         }
+
+         key->flags &= ~(SVGA3D_SURFACE_HINT_STATIC |
+                         SVGA3D_SURFACE_HINT_DYNAMIC);
+         key->flags |= hint_flag;
       }
 
       handle = svga_screen_cache_lookup(svgascreen, key);
@@ -436,25 +480,32 @@ svga_screen_surface_create(struct svga_screen *svgascreen,
                      key->size.width);
          else
             SVGA_DBG(DEBUG_CACHE|DEBUG_DMA,
-                     "reuse sid %p sz %dx%dx%d mips %d faces %d\n", handle,
+                     "reuse sid %p sz %dx%dx%d mips %d faces %d arraySize %d\n", handle,
                      key->size.width,
                      key->size.height,
                      key->size.depth,
                      key->numMipLevels,
-                     key->numFaces);
+                     key->numFaces,
+                     key->arraySize);
       }
    }
 
    if (!handle) {
+      unsigned usage = 0;
+
+      if (!key->cachable)
+         usage |= SVGA_SURFACE_USAGE_SHARED;
+      if (key->scanout)
+         usage |= SVGA_SURFACE_USAGE_SCANOUT;
+
       handle = sws->surface_create(sws,
                                    key->flags,
                                    key->format,
-                                   key->cachable ?
-                                   0 : SVGA_SURFACE_USAGE_SHARED,
+                                   usage,
                                    key->size,
-                                   key->numFaces,
+                                   key->numFaces * key->arraySize,
                                    key->numMipLevels,
-                                   0);
+                                   key->sampleCount);
       if (handle)
          SVGA_DBG(DEBUG_CACHE|DEBUG_DMA,
                   "  CREATE sid %p sz %dx%dx%d\n",
index 56ac62b39c1cfa58e6f31503eddbf9376a77e8b8..424eb2c5ae1f78aee54ccc784691d592a9e572f0 100644 (file)
@@ -62,9 +62,12 @@ struct svga_host_surface_cache_key
    SVGA3dSurfaceFlags flags;
    SVGA3dSurfaceFormat format;
    SVGA3dSize size;
-   uint32_t numFaces:24;
-   uint32_t numMipLevels:7;
+   uint32_t numFaces:3;
+   uint32_t arraySize:16;
+   uint32_t numMipLevels:6;
    uint32_t cachable:1;         /* False if this is a shared surface */
+   uint32_t sampleCount:5;
+   uint32_t scanout:1;
 };
 
 
@@ -137,6 +140,7 @@ svga_screen_cache_init(struct svga_screen *svgascreen);
 
 struct svga_winsys_surface *
 svga_screen_surface_create(struct svga_screen *svgascreen,
+                           unsigned bind_flags, unsigned usage,
                            struct svga_host_surface_cache_key *key);
 
 void
index 46efa07df2db11cf7eea4b4950a4326f9494138d..d46e7ebbc38e7aac162c9c9bd3bf69998fb87cc5 100644 (file)
 #include "util/u_memory.h"
 #include "svga_context.h"
 #include "svga_cmd.h"
+#include "svga_format.h"
 #include "svga_shader.h"
 
 
+/**
+ * This bit isn't really used anywhere.  It only serves to help
+ * generate a unique "signature" for the vertex shader output bitmask.
+ * Shader input/output signatures are used to resolve shader linking
+ * issues.
+ */
+#define FOG_GENERIC_BIT (((uint64_t) 1) << 63)
+
+
+/**
+ * Use the shader info to generate a bitmask indicating which generic
+ * inputs are used by the shader.  A set bit indicates that GENERIC[i]
+ * is used.
+ */
+uint64_t
+svga_get_generic_inputs_mask(const struct tgsi_shader_info *info)
+{
+   unsigned i;
+   uint64_t mask = 0x0;
+
+   for (i = 0; i < info->num_inputs; i++) {
+      if (info->input_semantic_name[i] == TGSI_SEMANTIC_GENERIC) {
+         unsigned j = info->input_semantic_index[i];
+         assert(j < sizeof(mask) * 8);
+         mask |= ((uint64_t) 1) << j;
+      }
+   }
+
+   return mask;
+}
+
+
+/**
+ * Scan shader info to return a bitmask of written outputs.
+ */
+uint64_t
+svga_get_generic_outputs_mask(const struct tgsi_shader_info *info)
+{
+   unsigned i;
+   uint64_t mask = 0x0;
+
+   for (i = 0; i < info->num_outputs; i++) {
+      switch (info->output_semantic_name[i]) {
+      case TGSI_SEMANTIC_GENERIC:
+         {
+            unsigned j = info->output_semantic_index[i];
+            assert(j < sizeof(mask) * 8);
+            mask |= ((uint64_t) 1) << j;
+         }
+         break;
+      case TGSI_SEMANTIC_FOG:
+         mask |= FOG_GENERIC_BIT;
+         break;
+      }
+   }
+
+   return mask;
+}
+
+
+
+/**
+ * Given a mask of used generic variables (as returned by the above functions)
+ * fill in a table which maps those indexes to small integers.
+ * This table is used by the remap_generic_index() function in
+ * svga_tgsi_decl_sm30.c
+ * Example: if generics_mask = binary(1010) it means that GENERIC[1] and
+ * GENERIC[3] are used.  The remap_table will contain:
+ *   table[1] = 0;
+ *   table[3] = 1;
+ * The remaining table entries will be filled in with the next unused
+ * generic index (in this example, 2).
+ */
+void
+svga_remap_generics(uint64_t generics_mask,
+                    int8_t remap_table[MAX_GENERIC_VARYING])
+{
+   /* Note texcoord[0] is reserved so start at 1 */
+   unsigned count = 1, i;
+
+   for (i = 0; i < MAX_GENERIC_VARYING; i++) {
+      remap_table[i] = -1;
+   }
+
+   /* for each bit set in generic_mask */
+   while (generics_mask) {
+      unsigned index = ffsll(generics_mask) - 1;
+      remap_table[index] = count++;
+      generics_mask &= ~((uint64_t) 1 << index);
+   }
+}
+
+
+/**
+ * Use the generic remap table to map a TGSI generic varying variable
+ * index to a small integer.  If the remapping table doesn't have a
+ * valid value for the given index (the table entry is -1) it means
+ * the fragment shader doesn't use that VS output.  Just allocate
+ * the next free value in that case.  Alternately, we could cull
+ * VS instructions that write to register, or replace the register
+ * with a dummy temp register.
+ * XXX TODO: we should do one of the later as it would save precious
+ * texcoord registers.
+ */
+int
+svga_remap_generic_index(int8_t remap_table[MAX_GENERIC_VARYING],
+                         int generic_index)
+{
+   assert(generic_index < MAX_GENERIC_VARYING);
+
+   if (generic_index >= MAX_GENERIC_VARYING) {
+      /* just don't return a random/garbage value */
+      generic_index = MAX_GENERIC_VARYING - 1;
+   }
+
+   if (remap_table[generic_index] == -1) {
+      /* This is a VS output that has no matching PS input.  Find a
+       * free index.
+       */
+      int i, max = 0;
+      for (i = 0; i < MAX_GENERIC_VARYING; i++) {
+         max = MAX2(max, remap_table[i]);
+      }
+      remap_table[generic_index] = max + 1;
+   }
+
+   return remap_table[generic_index];
+}
+
+
+/**
+ * Initialize the shader-neutral fields of svga_compile_key from context
+ * state.  This is basically the texture-related state.
+ */
+void
+svga_init_shader_key_common(const struct svga_context *svga, unsigned shader,
+                            struct svga_compile_key *key)
+{
+   unsigned i, idx = 0;
+
+   assert(shader < Elements(svga->curr.num_sampler_views));
+
+   for (i = 0; i < svga->curr.num_sampler_views[shader]; i++) {
+      struct pipe_sampler_view *view = svga->curr.sampler_views[shader][i];
+      if (view) {
+         assert(svga->curr.sampler[shader][i]);
+         assert(view->texture);
+         assert(view->texture->target < (1 << 4)); /* texture_target:4 */
+
+         key->tex[i].texture_target = view->texture->target;
+
+         /* 1D/2D array textures with one slice are treated as non-arrays
+          * by the SVGA3D device.  Convert the texture type here so that
+          * we emit the right TEX/SAMPLE instruction in the shader.
+          */
+         if (view->texture->array_size == 1) {
+            if (view->texture->target == PIPE_TEXTURE_1D_ARRAY) {
+               key->tex[i].texture_target = PIPE_TEXTURE_1D;
+            }
+            else if (view->texture->target == PIPE_TEXTURE_2D_ARRAY) {
+               key->tex[i].texture_target = PIPE_TEXTURE_2D;
+            }
+         }
+
+         key->tex[i].texture_msaa = view->texture->nr_samples > 1;
+         if (!svga->curr.sampler[shader][i]->normalized_coords) {
+            assert(idx < (1 << 5));  /* width_height_idx:5 bitfield */
+            key->tex[i].width_height_idx = idx++;
+            key->tex[i].unnormalized = TRUE;
+            ++key->num_unnormalized_coords;
+         }
+
+         key->tex[i].swizzle_r = view->swizzle_r;
+         key->tex[i].swizzle_g = view->swizzle_g;
+         key->tex[i].swizzle_b = view->swizzle_b;
+         key->tex[i].swizzle_a = view->swizzle_a;
+
+         key->tex[i].return_type = svga_get_texture_datatype(view->format);
+      }
+   }
+   key->num_textures = svga->curr.num_sampler_views[shader];
+}
+
+
+/** Search for a compiled shader variant with the same compile key */
+struct svga_shader_variant *
+svga_search_shader_key(const struct svga_shader *shader,
+                       const struct svga_compile_key *key)
+{
+   struct svga_shader_variant *variant = shader->variants;
+
+   assert(key);
+
+   for ( ; variant; variant = variant->next) {
+      if (svga_compile_keys_equal(key, &variant->key))
+         return variant;
+   }
+   return NULL;
+}
+
+/** Search for a shader with the same token key */
+struct svga_shader *
+svga_search_shader_token_key(struct svga_shader *pshader,
+                             const struct svga_token_key *key)
+{
+   struct svga_shader *shader = pshader;
+
+   assert(key);
+
+   for ( ; shader; shader = shader->next) {
+      if (memcmp(key, &shader->token_key, sizeof(struct svga_token_key)) == 0)
+         return shader;
+   }
+   return NULL;
+}
+
+/**
+ * Helper function to define a gb shader for non-vgpu10 device
+ */
+static enum pipe_error
+define_gb_shader_vgpu9(struct svga_context *svga,
+                       SVGA3dShaderType type,
+                       struct svga_shader_variant *variant,
+                       unsigned codeLen)
+{
+   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+   enum pipe_error ret;
+
+   /**
+    * Create gb memory for the shader and upload the shader code.
+    * Kernel module will allocate an id for the shader and issue
+    * the DefineGBShader command.
+    */
+   variant->gb_shader = sws->shader_create(sws, type,
+                                           variant->tokens, codeLen);
+
+   if (!variant->gb_shader)
+      return PIPE_ERROR_OUT_OF_MEMORY;
+
+   ret = SVGA3D_BindGBShader(svga->swc, variant->gb_shader);
+
+   return ret;
+}
+
+/**
+ * Helper function to define a gb shader for vgpu10 device
+ */
+static enum pipe_error
+define_gb_shader_vgpu10(struct svga_context *svga,
+                        SVGA3dShaderType type,
+                        struct svga_shader_variant *variant,
+                        unsigned codeLen)
+{
+   struct svga_winsys_context *swc = svga->swc;
+   enum pipe_error ret;
+
+   /**
+    * Shaders in VGPU10 enabled device reside in the device COTable.
+    * SVGA driver will allocate an integer ID for the shader and
+    * issue DXDefineShader and DXBindShader commands.
+    */
+   variant->id = util_bitmask_add(svga->shader_id_bm);
+   if (variant->id == UTIL_BITMASK_INVALID_INDEX) {
+      return PIPE_ERROR_OUT_OF_MEMORY;
+   }
+
+   /* Create gb memory for the shader and upload the shader code */
+   variant->gb_shader = swc->shader_create(swc,
+                                           variant->id, type,
+                                           variant->tokens, codeLen);
+
+   if (!variant->gb_shader) {
+      /* Free the shader ID */
+      assert(variant->id != UTIL_BITMASK_INVALID_INDEX);
+      goto fail_no_allocation;
+   }
+
+   /**
+    * Since we don't want to do any flush within state emission to avoid
+    * partial state in a command buffer, it's important to make sure that
+    * there is enough room to send both the DXDefineShader & DXBindShader
+    * commands in the same command buffer. So let's send both
+    * commands in one command reservation. If it fails, we'll undo
+    * the shader creation and return an error.
+    */
+   ret = SVGA3D_vgpu10_DefineAndBindShader(swc, variant->gb_shader,
+                                           variant->id, type, codeLen);
+
+   if (ret != PIPE_OK)
+      goto fail;
+
+   return PIPE_OK;
+
+fail:
+   swc->shader_destroy(swc, variant->gb_shader);
+   variant->gb_shader = NULL;
+
+fail_no_allocation:
+   util_bitmask_clear(svga->shader_id_bm, variant->id);
+   variant->id = UTIL_BITMASK_INVALID_INDEX;
+
+   return PIPE_ERROR_OUT_OF_MEMORY;
+}
 
 /**
  * Issue the SVGA3D commands to define a new shader.
- * \param result  contains the shader tokens, etc.  The result->id field will
- *                be set here.
+ * \param variant  contains the shader tokens, etc.  The result->id field will
+ *                 be set here.
  */
 enum pipe_error
 svga_define_shader(struct svga_context *svga,
@@ -42,27 +346,17 @@ svga_define_shader(struct svga_context *svga,
                    struct svga_shader_variant *variant)
 {
    unsigned codeLen = variant->nr_tokens * sizeof(variant->tokens[0]);
+   enum pipe_error ret;
 
-   if (svga_have_gb_objects(svga)) {
-      struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
-      enum pipe_error ret;
-
-      variant->gb_shader = sws->shader_create(sws, type,
-                                              variant->tokens, codeLen);
-      if (!variant->gb_shader)
-         return PIPE_ERROR_OUT_OF_MEMORY;
-
-      ret = SVGA3D_BindGBShader(svga->swc, variant->gb_shader);
-      if (ret != PIPE_OK) {
-         sws->shader_destroy(sws, variant->gb_shader);
-         variant->gb_shader = NULL;
-      }
+   variant->id = UTIL_BITMASK_INVALID_INDEX;
 
-      return ret;
+   if (svga_have_gb_objects(svga)) {
+      if (svga_have_vgpu10(svga))
+         return define_gb_shader_vgpu10(svga, type, variant, codeLen);
+      else
+         return define_gb_shader_vgpu9(svga, type, variant, codeLen);
    }
    else {
-      enum pipe_error ret;
-
       /* Allocate an integer ID for the shader */
       variant->id = util_bitmask_add(svga->shader_id_bm);
       if (variant->id == UTIL_BITMASK_INVALID_INDEX) {
@@ -80,14 +374,45 @@ svga_define_shader(struct svga_context *svga,
          assert(variant->id != UTIL_BITMASK_INVALID_INDEX);
          util_bitmask_clear(svga->shader_id_bm, variant->id);
          variant->id = UTIL_BITMASK_INVALID_INDEX;
-         return ret;
       }
    }
 
-   return PIPE_OK;
+   return ret;
 }
 
 
+/**
+ * Issue the SVGA3D commands to set/bind a shader.
+ * \param result  the shader to bind.
+ */
+enum pipe_error
+svga_set_shader(struct svga_context *svga,
+                SVGA3dShaderType type,
+                struct svga_shader_variant *variant)
+{
+   enum pipe_error ret;
+   unsigned id = variant ? variant->id : SVGA3D_INVALID_ID;
+
+   assert(type == SVGA3D_SHADERTYPE_VS ||
+          type == SVGA3D_SHADERTYPE_GS ||
+          type == SVGA3D_SHADERTYPE_PS);
+
+   if (svga_have_gb_objects(svga)) {
+      struct svga_winsys_gb_shader *gbshader =
+         variant ? variant->gb_shader : NULL;
+
+      if (svga_have_vgpu10(svga))
+         ret = SVGA3D_vgpu10_SetShader(svga->swc, type, gbshader, id);
+      else
+         ret = SVGA3D_SetGBShader(svga->swc, type, gbshader);
+   }
+   else {
+      ret = SVGA3D_SetShader(svga->swc, type, id);
+   }
+
+   return ret;
+}
+
 
 enum pipe_error
 svga_destroy_shader_variant(struct svga_context *svga,
@@ -96,32 +421,92 @@ svga_destroy_shader_variant(struct svga_context *svga,
 {
    enum pipe_error ret = PIPE_OK;
 
-   if (svga_have_gb_objects(svga)) {
-      struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
-
-      sws->shader_destroy(sws, variant->gb_shader);
+   if (svga_have_gb_objects(svga) && variant->gb_shader) {
+      if (svga_have_vgpu10(svga)) {
+         struct svga_winsys_context *swc = svga->swc;
+         swc->shader_destroy(swc, variant->gb_shader);
+         ret = SVGA3D_vgpu10_DestroyShader(svga->swc, variant->id);
+         if (ret != PIPE_OK) {
+            /* flush and try again */
+            svga_context_flush(svga, NULL);
+            ret = SVGA3D_vgpu10_DestroyShader(svga->swc, variant->id);
+         }
+         util_bitmask_clear(svga->shader_id_bm, variant->id);
+      }
+      else {
+         struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+         sws->shader_destroy(sws, variant->gb_shader);
+      }
       variant->gb_shader = NULL;
-      goto end;
    }
-
-   /* first try */
-   if (variant->id != UTIL_BITMASK_INVALID_INDEX) {
-      ret = SVGA3D_DestroyShader(svga->swc, variant->id, type);
-
-      if (ret != PIPE_OK) {
-         /* flush and try again */
-         svga_context_flush(svga, NULL);
-
+   else {
+      if (variant->id != UTIL_BITMASK_INVALID_INDEX) {
          ret = SVGA3D_DestroyShader(svga->swc, variant->id, type);
-         assert(ret == PIPE_OK);
+         if (ret != PIPE_OK) {
+            /* flush and try again */
+            svga_context_flush(svga, NULL);
+            ret = SVGA3D_DestroyShader(svga->swc, variant->id, type);
+            assert(ret == PIPE_OK);
+         }
+         util_bitmask_clear(svga->shader_id_bm, variant->id);
       }
-
-      util_bitmask_clear(svga->shader_id_bm, variant->id);
    }
 
-end:
    FREE((unsigned *)variant->tokens);
    FREE(variant);
 
    return ret;
 }
+
+/*
+ * Rebind shaders.
+ * Called at the beginning of every new command buffer to ensure that
+ * shaders are properly paged-in. Instead of sending the SetShader
+ * command, this function sends a private allocation command to
+ * page in a shader. This avoids emitting redundant state to the device
+ * just to page in a resource.
+ */
+enum pipe_error
+svga_rebind_shaders(struct svga_context *svga)
+{
+   struct svga_winsys_context *swc = svga->swc;
+   struct svga_hw_draw_state *hw = &svga->state.hw_draw;
+   enum pipe_error ret;
+
+   assert(svga_have_vgpu10(svga));
+
+   /**
+    * If the underlying winsys layer does not need resource rebinding,
+    * just clear the rebind flags and return.
+    */
+   if (swc->resource_rebind == NULL) {
+      svga->rebind.flags.vs = 0;
+      svga->rebind.flags.gs = 0;
+      svga->rebind.flags.fs = 0;
+
+      return PIPE_OK;
+   }
+
+   if (svga->rebind.flags.vs && hw->vs && hw->vs->gb_shader) {
+      ret = swc->resource_rebind(swc, NULL, hw->vs->gb_shader, SVGA_RELOC_READ);
+      if (ret != PIPE_OK)
+         return ret;
+   }
+   svga->rebind.flags.vs = 0;
+
+   if (svga->rebind.flags.gs && hw->gs && hw->gs->gb_shader) {
+      ret = swc->resource_rebind(swc, NULL, hw->gs->gb_shader, SVGA_RELOC_READ);
+      if (ret != PIPE_OK)
+         return ret;
+   }
+   svga->rebind.flags.gs = 0;
+
+   if (svga->rebind.flags.fs && hw->fs && hw->fs->gb_shader) {
+      ret = swc->resource_rebind(swc, NULL, hw->fs->gb_shader, SVGA_RELOC_READ);
+      if (ret != PIPE_OK)
+         return ret;
+   }
+   svga->rebind.flags.fs = 0;
+
+   return PIPE_OK;
+}
index 5102159b96a4a8ce300d7ccaa2596ad920948408..b0800c1ecad1936837c8864af44a770f62cf520e 100644 (file)
 #define SVGA_SHADER_H
 
 #include "svga3d_reg.h"
+#include "svga_context.h"
+#include "svga_streamout.h"
 
-struct svga_shader_variant;
+
+/**
+ * We use a 64-bit mask to keep track of the generic indexes.
+ * This is the maximum semantic index for a TGSI GENERIC[i] register.
+ */
+#define MAX_GENERIC_VARYING 64
+
+
+struct svga_context;
+
+
+struct svga_compile_key
+{
+   /* vertex shader only */
+   struct {
+      uint64_t fs_generic_inputs;
+      unsigned passthrough:1;
+      unsigned need_prescale:1;
+      unsigned undo_viewport:1;
+      unsigned allow_psiz:1;
+      /** The following are all 32-bit bitmasks (per VS input) */
+      unsigned adjust_attrib_range;
+      unsigned attrib_is_pure_int;
+      unsigned adjust_attrib_w_1;
+      unsigned adjust_attrib_itof;
+      unsigned adjust_attrib_utof;
+      unsigned attrib_is_bgra;
+      unsigned attrib_puint_to_snorm;
+      unsigned attrib_puint_to_uscaled;
+      unsigned attrib_puint_to_sscaled;
+   } vs;
+
+   /* geometry shader only */
+   struct {
+      uint64_t vs_generic_outputs;
+      unsigned need_prescale:1;
+      unsigned writes_psize:1;
+      unsigned wide_point:1;
+   } gs;
+
+   /* fragment shader only */
+   struct {
+      uint64_t vs_generic_outputs;
+      uint64_t gs_generic_outputs;
+      unsigned light_twoside:1;
+      unsigned front_ccw:1;
+      unsigned white_fragments:1;
+      unsigned flatshade:1;
+      unsigned pstipple:1;
+      unsigned alpha_func:4;  /**< SVGA3D_CMP_x */
+      unsigned write_color0_to_n_cbufs:4;
+      unsigned aa_point:1;
+      int aa_point_coord_index;
+      float alpha_ref;
+   } fs;
+
+   /* any shader type */
+   int8_t generic_remap_table[MAX_GENERIC_VARYING];
+   unsigned num_textures:8;
+   unsigned num_unnormalized_coords:8;
+   unsigned clip_plane_enable:PIPE_MAX_CLIP_PLANES;
+   unsigned sprite_origin_lower_left:1;
+   unsigned sprite_coord_enable;
+   struct {
+      unsigned compare_mode:1;
+      unsigned compare_func:3;
+      unsigned unnormalized:1;
+      unsigned width_height_idx:5; /**< texture unit */
+      unsigned texture_target:4;   /**< PIPE_TEXTURE_x */
+      unsigned texture_msaa:1;    /**< A multisample texture? */
+      unsigned sprite_texgen:1;
+      unsigned swizzle_r:3;
+      unsigned swizzle_g:3;
+      unsigned swizzle_b:3;
+      unsigned swizzle_a:3;
+      unsigned return_type:3;  /**< TGSI_RETURN_TYPE_x */
+   } tex[PIPE_MAX_SAMPLERS];
+   /* Note: svga_compile_keys_equal() depends on the variable-size
+    * tex[] array being at the end of this structure.
+    */
+};
+
+/* A key for a variant of token string of a shader */
+struct svga_token_key {
+   struct {
+      unsigned sprite_coord_enable:24;
+      unsigned sprite_origin_upper_left:1;
+      unsigned point_pos_stream_out:1;
+      unsigned writes_psize:1;
+      unsigned aa_point:1;
+   } gs;
+};
+
+/**
+ * A single TGSI shader may be compiled into different variants of
+ * SVGA3D shaders depending on the compile key.  Each user shader
+ * will have a linked list of these variants.
+ */
+struct svga_shader_variant
+{
+   const struct svga_shader *shader;
+
+   /** Parameters used to generate this variant */
+   struct svga_compile_key key;
+
+   /* Compiled shader tokens:
+    */
+   const unsigned *tokens;
+   unsigned nr_tokens;
+
+   /** Per-context shader identifier used with SVGA_3D_CMD_SHADER_DEFINE,
+    * SVGA_3D_CMD_SET_SHADER and SVGA_3D_CMD_SHADER_DESTROY.
+    */
+   unsigned id;
+
+   /** Start of extra constants (number of float[4] constants) */
+   unsigned extra_const_start;
+
+   /* GB object buffer containing the bytecode */
+   struct svga_winsys_gb_shader *gb_shader;
+
+   boolean uses_flat_interp;   /** TRUE if flat interpolation qualifier is
+                                *  applied to any of the varyings.
+                                */
+
+   /** For FS-based polygon stipple */
+   unsigned pstipple_sampler_unit;
+
+   /** Next variant */
+   struct svga_shader_variant *next;
+};
+
+
+struct svga_shader
+{
+   const struct tgsi_token *tokens;
+   struct svga_token_key token_key;     /* token key for the token string */
+   struct tgsi_shader_info info;
+
+   /* List of shaders with tokens derived from the same token string */
+   struct svga_shader *next;
+   struct svga_shader *parent;   /* shader with the original token string */
+
+   struct svga_stream_output *stream_output;
+
+   /** Head of linked list of compiled variants */
+   struct svga_shader_variant *variants;
+
+   unsigned id;  /**< for debugging only */
+};
+
+
+struct svga_fragment_shader
+{
+   struct svga_shader base;
+
+   struct draw_fragment_shader *draw_shader;
+
+   /** Mask of which generic varying variables are read by this shader */
+   uint64_t generic_inputs;
+
+   /** Table mapping original TGSI generic indexes to low integers */
+   int8_t generic_remap_table[MAX_GENERIC_VARYING];
+};
+
+
+struct svga_vertex_shader
+{
+   struct svga_shader base;
+
+   struct draw_vertex_shader *draw_shader;
+
+   /** Mask of which generic varying variables are written by this shader */
+   uint64_t generic_outputs;
+
+   /** Generated geometry shader that goes with this vertex shader */
+   struct svga_geometry_shader *gs;
+};
+
+
+struct svga_geometry_shader
+{
+   struct svga_shader base;
+
+   struct draw_geometry_shader *draw_shader;
+
+   /** Table mapping original TGSI generic indexes to low integers */
+   int8_t generic_remap_table[MAX_GENERIC_VARYING];
+   uint64_t generic_outputs;
+
+   unsigned aa_point_coord_index; /* generic index for aa point coord */
+
+   unsigned wide_point:1;      /* set if the shader emulates wide point */
+};
+
+
+static inline boolean
+svga_compile_keys_equal(const struct svga_compile_key *a,
+                        const struct svga_compile_key *b)
+{
+   unsigned key_size =
+      (const char *) &a->tex[a->num_textures] - (const char *) a;
+
+   return memcmp(a, b, key_size) == 0;
+}
+
+
+uint64_t
+svga_get_generic_inputs_mask(const struct tgsi_shader_info *info);
+
+uint64_t
+svga_get_generic_outputs_mask(const struct tgsi_shader_info *info);
+
+void
+svga_remap_generics(uint64_t generics_mask,
+                    int8_t remap_table[MAX_GENERIC_VARYING]);
+
+int
+svga_remap_generic_index(int8_t remap_table[MAX_GENERIC_VARYING],
+                         int generic_index);
+
+void
+svga_init_shader_key_common(const struct svga_context *svga, unsigned shader,
+                            struct svga_compile_key *key);
+
+struct svga_shader_variant *
+svga_search_shader_key(const struct svga_shader *shader,
+                       const struct svga_compile_key *key);
+
+struct svga_shader *
+svga_search_shader_token_key(struct svga_shader *shader,
+                             const struct svga_token_key *key);
 
 enum pipe_error
 svga_define_shader(struct svga_context *svga,
                    SVGA3dShaderType type,
                    struct svga_shader_variant *variant);
 
+enum pipe_error
+svga_set_shader(struct svga_context *svga,
+                SVGA3dShaderType type,
+                struct svga_shader_variant *variant);
+
 enum pipe_error
 svga_destroy_shader_variant(struct svga_context *svga,
                             SVGA3dShaderType type,
                             struct svga_shader_variant *variant);
 
+enum pipe_error
+svga_rebind_shaders(struct svga_context *svga);
 
 /**
  * Check if a shader's bytecode exceeds the device limits.
@@ -62,4 +302,40 @@ svga_shader_too_large(const struct svga_context *svga,
 }
 
 
+/**
+ * Convert from PIPE_SHADER_* to SVGA3D_SHADERTYPE_*
+ */
+static inline SVGA3dShaderType
+svga_shader_type(unsigned shader)
+{
+   switch (shader) {
+   case PIPE_SHADER_VERTEX:
+      return SVGA3D_SHADERTYPE_VS;
+   case PIPE_SHADER_GEOMETRY:
+      return SVGA3D_SHADERTYPE_GS;
+   case PIPE_SHADER_FRAGMENT:
+      return SVGA3D_SHADERTYPE_PS;
+   default:
+      assert(!"Invalid shader type");
+      return SVGA3D_SHADERTYPE_VS;
+   }
+}
+
+
+/** Does the current VS have stream output? */
+static inline boolean
+svga_have_vs_streamout(const struct svga_context *svga)
+{
+   return svga->curr.vs != NULL && svga->curr.vs->base.stream_output != NULL;
+}
+
+
+/** Does the current GS have stream output? */
+static inline boolean
+svga_have_gs_streamout(const struct svga_context *svga)
+{
+   return svga->curr.gs != NULL && svga->curr.gs->base.stream_output != NULL;
+}
+
+
 #endif /* SVGA_SHADER_H */
index b0bc867f63a08da8318d6ab759b1b3cad68a509d..37d16dc9afe9ec20f6cb9f6b95188d721639fd90 100644 (file)
@@ -23,6 +23,7 @@
  *
  **********************************************************/
 
+#include "util/u_bitmask.h"
 #include "util/u_debug.h"
 #include "pipe/p_defines.h"
 #include "util/u_memory.h"
@@ -63,14 +64,19 @@ static const struct svga_tracked_state *hw_clear_state[] =
  */
 static const struct svga_tracked_state *hw_draw_state[] =
 {
+   &svga_need_tgsi_transform,
    &svga_hw_fs,
+   &svga_hw_gs,
    &svga_hw_vs,
    &svga_hw_rss,
-   &svga_hw_tss,
-   &svga_hw_tss_binding,
+   &svga_hw_sampler,           /* VGPU10 */
+   &svga_hw_sampler_bindings,  /* VGPU10 */
+   &svga_hw_tss,               /* pre-VGPU10 */
+   &svga_hw_tss_binding,       /* pre-VGPU10 */
    &svga_hw_clip_planes,
    &svga_hw_vdecl,
    &svga_hw_fs_constants,
+   &svga_hw_gs_constants,
    &svga_hw_vs_constants,
    NULL
 };
@@ -255,23 +261,55 @@ do {                                            \
  */
 enum pipe_error svga_emit_initial_state( struct svga_context *svga )
 {
-   SVGA3dRenderState *rs;
-   unsigned count = 0;
-   const unsigned COUNT = 2;
-   enum pipe_error ret;
-
-   ret = SVGA3D_BeginSetRenderState( svga->swc, &rs, COUNT );
-   if (ret != PIPE_OK)
+   if (svga_have_vgpu10(svga)) {
+      SVGA3dRasterizerStateId id = util_bitmask_add(svga->rast_object_id_bm);
+      enum pipe_error ret;
+
+      /* XXX preliminary code */
+      ret = SVGA3D_vgpu10_DefineRasterizerState(svga->swc,
+                                             id,
+                                             SVGA3D_FILLMODE_FILL,
+                                             SVGA3D_CULL_NONE,
+                                             1, /* frontCounterClockwise */
+                                             0, /* depthBias */
+                                             0.0f, /* depthBiasClamp */
+                                             0.0f, /* slopeScaledDepthBiasClamp */
+                                             0, /* depthClampEnable */
+                                             0, /* scissorEnable */
+                                             0, /* multisampleEnable */
+                                             0, /* aalineEnable */
+                                             1.0f, /* lineWidth */
+                                             0, /* lineStippleEnable */
+                                             0, /* lineStippleFactor */
+                                             0, /* lineStipplePattern */
+                                             0); /* provokingVertexLast */
+
+
+      assert(ret == PIPE_OK);
+
+      ret = SVGA3D_vgpu10_SetRasterizerState(svga->swc, id);
       return ret;
+   }
+   else {
+      SVGA3dRenderState *rs;
+      unsigned count = 0;
+      const unsigned COUNT = 2;
+      enum pipe_error ret;
 
-   /* Always use D3D style coordinate space as this is the only one
-    * which is implemented on all backends.
-    */
-   EMIT_RS(rs, count, SVGA3D_RS_COORDINATETYPE, SVGA3D_COORDINATE_LEFTHANDED );
-   EMIT_RS(rs, count, SVGA3D_RS_FRONTWINDING, SVGA3D_FRONTWINDING_CW );
-   
-   assert( COUNT == count );
-   SVGA_FIFOCommitAll( svga->swc );
+      ret = SVGA3D_BeginSetRenderState( svga->swc, &rs, COUNT );
+      if (ret != PIPE_OK)
+         return ret;
 
-   return PIPE_OK;
+      /* Always use D3D style coordinate space as this is the only one
+       * which is implemented on all backends.
+       */
+      EMIT_RS(rs, count, SVGA3D_RS_COORDINATETYPE,
+              SVGA3D_COORDINATE_LEFTHANDED );
+      EMIT_RS(rs, count, SVGA3D_RS_FRONTWINDING, SVGA3D_FRONTWINDING_CW );
+
+      assert( COUNT == count );
+      SVGA_FIFOCommitAll( svga->swc );
+
+      return PIPE_OK;
+   }
 }
index 3325626a4d1d4663c05134b89553c7437d1943ae..04b20e161feceee4a6c095ab20abf1e863cf8059 100644 (file)
@@ -57,14 +57,20 @@ extern struct svga_tracked_state svga_hw_framebuffer;
 
 /* HW_DRAW
  */
+extern struct svga_tracked_state svga_need_tgsi_transform;
 extern struct svga_tracked_state svga_hw_vs;
 extern struct svga_tracked_state svga_hw_fs;
+extern struct svga_tracked_state svga_hw_gs;
 extern struct svga_tracked_state svga_hw_rss;
+extern struct svga_tracked_state svga_hw_pstipple;
+extern struct svga_tracked_state svga_hw_sampler;
+extern struct svga_tracked_state svga_hw_sampler_bindings;
 extern struct svga_tracked_state svga_hw_tss;
 extern struct svga_tracked_state svga_hw_tss_binding;
 extern struct svga_tracked_state svga_hw_clip_planes;
 extern struct svga_tracked_state svga_hw_vdecl;
 extern struct svga_tracked_state svga_hw_fs_constants;
+extern struct svga_tracked_state svga_hw_gs_constants;
 extern struct svga_tracked_state svga_hw_vs_constants;
 
 /* SWTNL_DRAW
@@ -93,10 +99,14 @@ enum pipe_error svga_emit_initial_state( struct svga_context *svga );
 
 enum pipe_error svga_reemit_framebuffer_bindings( struct svga_context *svga );
 
+enum pipe_error svga_rebind_framebuffer_bindings( struct svga_context *svga );
+
 enum pipe_error svga_reemit_tss_bindings( struct svga_context *svga );
 
 enum pipe_error svga_reemit_vs_bindings(struct svga_context *svga);
 
 enum pipe_error svga_reemit_fs_bindings(struct svga_context *svga);
 
+enum pipe_error svga_reemit_gs_bindings(struct svga_context *svga);
+
 #endif
index 1e1fbb099c67e7ba69b5df2f6758f9c79ee50962..e0bbe013c02ac062a4f9af62612aa23fcbfe62cf 100644 (file)
@@ -1,3 +1,4 @@
+
 /**********************************************************
  * Copyright 2008-2009 VMware, Inc.  All rights reserved.
  *
  *
  **********************************************************/
 
+#include "util/u_format.h"
 #include "util/u_inlines.h"
 #include "util/u_memory.h"
 #include "pipe/p_defines.h"
+#include "util/u_upload_mgr.h"
 
 #include "svga_screen.h"
 #include "svga_context.h"
@@ -34,6 +37,7 @@
 #include "svga_tgsi.h"
 #include "svga_debug.h"
 #include "svga_resource_buffer.h"
+#include "svga_shader.h"
 
 #include "svga_hw_reg.h"
 
 /** Guest-backed surface constant buffers must be this size */
 #define GB_CONSTBUF_SIZE (SVGA3D_CONSTREG_MAX)
 
+
 /**
- * Convert from PIPE_SHADER_* to SVGA3D_SHADERTYPE_*
+ * Emit any extra shader-type-independent shader constants into the buffer
+ * pointed to by 'dest'.
+ * \return number of float[4] constants put into the 'dest' buffer
  */
 static unsigned
-svga_shader_type(unsigned shader)
+svga_get_extra_constants_common(struct svga_context *svga,
+                                const struct svga_shader_variant *variant,
+                                unsigned shader, float *dest)
 {
-   switch (shader) {
-   case PIPE_SHADER_VERTEX:
-      return SVGA3D_SHADERTYPE_VS;
-   case PIPE_SHADER_FRAGMENT:
-      return SVGA3D_SHADERTYPE_PS;
-   default:
-      assert(!"Unexpected shader type");
-      return SVGA3D_SHADERTYPE_VS;
+   uint32_t *dest_u = (uint32_t *) dest;  // uint version of dest
+   unsigned i;
+   unsigned count = 0;
+
+   for (i = 0; i < variant->key.num_textures; i++) {
+      struct pipe_sampler_view *sv = svga->curr.sampler_views[shader][i];
+      if (sv) {
+         struct pipe_resource *tex = sv->texture;
+         /* Scaling factors needed for handling unnormalized texture coordinates
+          * for texture rectangles.
+          */
+         if (variant->key.tex[i].unnormalized) {
+            /* debug/sanity check */
+            assert(variant->key.tex[i].width_height_idx == count);
+
+            *dest++ = 1.0 / (float)tex->width0;
+            *dest++ = 1.0 / (float)tex->height0;
+            *dest++ = 1.0;
+            *dest++ = 1.0;
+
+            count++;
+         }
+
+         /* Store the sizes for texture buffers.
+         */
+         if (tex->target == PIPE_BUFFER) {
+            unsigned bytes_per_element = util_format_get_blocksize(sv->format);
+            *dest_u++ = tex->width0 / bytes_per_element;
+            *dest_u++ = 1;
+            *dest_u++ = 1;
+            *dest_u++ = 1;
+
+            count++;
+         }
+      }
    }
+
+   return count;
 }
 
 
 /**
  * Emit any extra fragment shader constants into the buffer pointed
  * to by 'dest'.
- * In particular, these would be the scaling factors needed for handling
- * unnormalized texture coordinates for texture rectangles.
  * \return number of float[4] constants put into the dest buffer
  */
 static unsigned
 svga_get_extra_fs_constants(struct svga_context *svga, float *dest)
 {
    const struct svga_shader_variant *variant = svga->state.hw_draw.fs;
-   const struct svga_fs_compile_key *key = &variant->key.fkey;
    unsigned count = 0;
 
-   /* SVGA_NEW_VS_VARIANT
-    */
-   if (key->num_unnormalized_coords) {
-      unsigned i;
+   count += svga_get_extra_constants_common(svga, variant,
+                                            PIPE_SHADER_FRAGMENT, dest);
 
-      for (i = 0; i < key->num_textures; i++) {
-         if (key->tex[i].unnormalized) {
-            struct pipe_resource *tex = svga->curr.sampler_views[i]->texture;
+   assert(count <= MAX_EXTRA_CONSTS);
 
-            /* debug/sanity check */
-            assert(key->tex[i].width_height_idx == count);
+   return count;
+}
 
-            *dest++ = 1.0 / (float)tex->width0;
-            *dest++ = 1.0 / (float)tex->height0;
-            *dest++ = 1.0;
-            *dest++ = 1.0;
+/**
+ * Emit extra constants needed for prescale computation into the
+ * the buffer pointed to by '*dest'. The updated buffer pointer
+ * will be returned in 'dest'.
+ */
+static unsigned
+svga_get_prescale_constants(struct svga_context *svga, float **dest)
+{
+   memcpy(*dest, svga->state.hw_clear.prescale.scale, 4 * sizeof(float));
+   *dest += 4;
 
-            count++;
-         }
-      }
-   }
+   memcpy(*dest, svga->state.hw_clear.prescale.translate, 4 * sizeof(float));
+   *dest += 4;
 
-   assert(count <= MAX_EXTRA_CONSTS);
+   return 2;
+}
 
-   return count;
+/**
+ * Emit extra constants needed for point sprite emulation.
+ */
+static unsigned
+svga_get_pt_sprite_constants(struct svga_context *svga, float **dest)
+{
+   struct svga_screen *screen = svga_screen(svga->pipe.screen);
+   float *dst = *dest;
+
+   dst[0] = 1.0 / (svga->curr.viewport.scale[0] * 2);
+   dst[1] = 1.0 / (svga->curr.viewport.scale[1] * 2);
+   dst[2] = svga->curr.rast->pointsize;
+   dst[3] = screen->maxPointSize;
+   *dest = *dest + 4;
+   return 1;
 }
 
+/**
+ * Emit user-defined clip plane coefficients into the buffer pointed to
+ * by '*dest'. The updated buffer pointer will be returned in 'dest'.
+ */
+static unsigned
+svga_get_clip_plane_constants(struct svga_context *svga,
+                              const struct svga_shader_variant *variant,
+                              float **dest)
+{
+   unsigned count = 0;
+
+   /* SVGA_NEW_CLIP */
+   if (svga_have_vgpu10(svga)) {
+      /* append user-defined clip plane coefficients onto constant buffer */
+      unsigned clip_planes = variant->key.clip_plane_enable;
+      while (clip_planes) {
+         int i = u_bit_scan(&clip_planes);
+         COPY_4V(*dest, svga->curr.clip.ucp[i]);
+         *dest += 4;
+         count += 1;
+      }
+   }
+   return count;
+}
 
 /**
  * Emit any extra vertex shader constants into the buffer pointed
@@ -124,26 +198,71 @@ static unsigned
 svga_get_extra_vs_constants(struct svga_context *svga, float *dest)
 {
    const struct svga_shader_variant *variant = svga->state.hw_draw.vs;
-   const struct svga_vs_compile_key *key = &variant->key.vkey;
    unsigned count = 0;
 
    /* SVGA_NEW_VS_VARIANT
     */
-   if (key->need_prescale) {
-      memcpy(dest, svga->state.hw_clear.prescale.scale, 4 * sizeof(float));
-      dest += 4;
+   if (variant->key.vs.need_prescale) {
+      count += svga_get_prescale_constants(svga, &dest);
+   }
 
-      memcpy(dest, svga->state.hw_clear.prescale.translate, 4 * sizeof(float));
+   if (variant->key.vs.undo_viewport) {
+      /* Used to convert window coords back to NDC coords */
+      dest[0] = 1.0f / svga->curr.viewport.scale[0];
+      dest[1] = 1.0f / svga->curr.viewport.scale[1];
+      dest[2] = -svga->curr.viewport.translate[0];
+      dest[3] = -svga->curr.viewport.translate[1];
       dest += 4;
-
-      count = 2;
+      count += 1;
    }
 
+   /* SVGA_NEW_CLIP */
+   count += svga_get_clip_plane_constants(svga, variant, &dest);
+
+   /* common constants */
+   count += svga_get_extra_constants_common(svga, variant,
+                                            PIPE_SHADER_VERTEX, dest);
+
    assert(count <= MAX_EXTRA_CONSTS);
 
    return count;
 }
 
+/**
+ * Emit any extra geometry shader constants into the buffer pointed
+ * to by 'dest'.
+ */
+static unsigned
+svga_get_extra_gs_constants(struct svga_context *svga, float *dest)
+{
+   const struct svga_shader_variant *variant = svga->state.hw_draw.gs;
+   unsigned count = 0;
+
+   /* SVGA_NEW_GS_VARIANT
+    */
+
+   /* Constants for point sprite
+    * These are used in the transformed gs that supports point sprite.
+    * They need to be added before the prescale constants.
+    */
+   if (variant->key.gs.wide_point) {
+      count += svga_get_pt_sprite_constants(svga, &dest);
+   }
+
+   if (variant->key.gs.need_prescale) {
+      count += svga_get_prescale_constants(svga, &dest);
+   }
+
+   /* SVGA_NEW_CLIP */
+   count += svga_get_clip_plane_constants(svga, variant, &dest);
+
+   /* common constants */
+   count += svga_get_extra_constants_common(svga, variant,
+                                            PIPE_SHADER_GEOMETRY, dest);
+
+   assert(count <= MAX_EXTRA_CONSTS);
+   return count;
+}
 
 /**
  * Check and emit one shader constant register.
@@ -159,6 +278,7 @@ emit_const(struct svga_context *svga, unsigned shader, unsigned i,
 
    assert(shader < PIPE_SHADER_TYPES);
    assert(i < SVGA3D_CONSTREG_MAX);
+   assert(!svga_have_vgpu10(svga));
 
    if (memcmp(svga->state.hw_draw.cb[shader][i], value,
               4 * sizeof(float)) != 0) {
@@ -202,6 +322,10 @@ emit_const_range(struct svga_context *svga,
    unsigned i, j;
    enum pipe_error ret;
 
+   assert(shader == PIPE_SHADER_VERTEX ||
+          shader == PIPE_SHADER_FRAGMENT);
+   assert(!svga_have_vgpu10(svga));
+
 #ifdef DEBUG
    if (offset + count > SVGA3D_CONSTREG_MAX) {
       debug_printf("svga: too many constants (offset %u + count %u = %u (max = %u))\n",
@@ -307,10 +431,12 @@ emit_const_range(struct svga_context *svga,
 
 /**
  * Emit all the constants in a constant buffer for a shader stage.
+ * On VGPU10, emit_consts_vgpu10 is used instead.
  */
 static enum pipe_error
-emit_consts(struct svga_context *svga, unsigned shader)
+emit_consts_vgpu9(struct svga_context *svga, unsigned shader)
 {
+   const struct pipe_constant_buffer *cbuf;
    struct svga_screen *ss = svga_screen(svga->pipe.screen);
    struct pipe_transfer *transfer = NULL;
    unsigned count;
@@ -320,53 +446,284 @@ emit_consts(struct svga_context *svga, unsigned shader)
    const unsigned offset = 0;
 
    assert(shader < PIPE_SHADER_TYPES);
+   assert(!svga_have_vgpu10(svga));
+   /* Only one constant buffer per shader is supported before VGPU10.
+    * This is only an approximate check against that.
+    */
+   assert(svga->curr.constbufs[shader][1].buffer == NULL);
 
-   if (svga->curr.cbufs[shader].buffer == NULL)
-      goto done;
+   cbuf = &svga->curr.constbufs[shader][0];
 
-   data = (const float (*)[4])pipe_buffer_map(&svga->pipe,
-                                              svga->curr.cbufs[shader].buffer,
-                                              PIPE_TRANSFER_READ,
-                                             &transfer);
-   if (data == NULL) {
-      ret = PIPE_ERROR_OUT_OF_MEMORY;
-      goto done;
-   }
+   if (svga->curr.constbufs[shader][0].buffer) {
+      /* emit user-provided constants */
+      data = (const float (*)[4])
+         pipe_buffer_map(&svga->pipe, svga->curr.constbufs[shader][0].buffer,
+                         PIPE_TRANSFER_READ, &transfer);
+      if (data == NULL) {
+         return PIPE_ERROR_OUT_OF_MEMORY;
+      }
 
-   /* sanity check */
-   assert(svga->curr.cbufs[shader].buffer->width0 >=
-          svga->curr.cbufs[shader].buffer_size);
+      /* sanity check */
+      assert(cbuf->buffer->width0 >=
+             cbuf->buffer_size);
 
-   /* Use/apply the constant buffer size and offsets here */
-   count = svga->curr.cbufs[shader].buffer_size / (4 * sizeof(float));
-   data += svga->curr.cbufs[shader].buffer_offset / (4 * sizeof(float));
+      /* Use/apply the constant buffer size and offsets here */
+      count = cbuf->buffer_size / (4 * sizeof(float));
+      data += cbuf->buffer_offset / (4 * sizeof(float));
+
+      if (ss->hw_version >= SVGA3D_HWVERSION_WS8_B1) {
+         ret = emit_const_range( svga, shader, offset, count, data );
+      }
+      else {
+         for (i = 0; i < count; i++) {
+            ret = emit_const( svga, shader, offset + i, data[i] );
+            if (ret != PIPE_OK) {
+               break;
+            }
+         }
+      }
+
+      pipe_buffer_unmap(&svga->pipe, transfer);
 
-   if (ss->hw_version >= SVGA3D_HWVERSION_WS8_B1) {
-      ret = emit_const_range( svga, shader, offset, count, data );
       if (ret != PIPE_OK) {
-         goto done;
+         return ret;
       }
-   } else {
-      for (i = 0; i < count; i++) {
-         ret = emit_const( svga, shader, offset + i, data[i] );
-         if (ret != PIPE_OK) {
-            goto done;
+   }
+
+   /* emit extra shader constants */
+   {
+      const struct svga_shader_variant *variant = NULL;
+      unsigned offset;
+      float extras[MAX_EXTRA_CONSTS][4];
+      unsigned count, i;
+
+      switch (shader) {
+      case PIPE_SHADER_VERTEX:
+         variant = svga->state.hw_draw.vs;
+         count = svga_get_extra_vs_constants(svga, (float *) extras);
+         break;
+      case PIPE_SHADER_FRAGMENT:
+         variant = svga->state.hw_draw.fs;
+         count = svga_get_extra_fs_constants(svga, (float *) extras);
+         break;
+      default:
+         assert(!"Unexpected shader type");
+         count = 0;
+      }
+
+      assert(variant);
+      offset = variant->shader->info.file_max[TGSI_FILE_CONSTANT] + 1;
+      assert(count <= Elements(extras));
+
+      if (count > 0) {
+         if (ss->hw_version >= SVGA3D_HWVERSION_WS8_B1) {
+            ret = emit_const_range(svga, shader, offset, count,
+                                   (const float (*) [4])extras);
+         }
+         else {
+            for (i = 0; i < count; i++) {
+               ret = emit_const(svga, shader, offset + i, extras[i]);
+               if (ret != PIPE_OK)
+                  return ret;
+            }
          }
       }
    }
 
-done:
-   if (data)
-      pipe_buffer_unmap(&svga->pipe, transfer);
+   return ret;
+}
+
+
+
+static enum pipe_error
+emit_constbuf_vgpu10(struct svga_context *svga, unsigned shader)
+{
+   const struct pipe_constant_buffer *cbuf;
+   struct pipe_resource *dst_buffer = NULL;
+   enum pipe_error ret = PIPE_OK;
+   struct pipe_transfer *src_transfer;
+   struct svga_winsys_surface *dst_handle;
+   float extras[MAX_EXTRA_CONSTS][4];
+   unsigned extra_count, extra_size, extra_offset;
+   unsigned new_buf_size;
+   void *src_map = NULL, *dst_map;
+   unsigned offset;
+   const struct svga_shader_variant *variant;
+
+   assert(shader == PIPE_SHADER_VERTEX ||
+          shader == PIPE_SHADER_GEOMETRY ||
+          shader == PIPE_SHADER_FRAGMENT);
+
+   cbuf = &svga->curr.constbufs[shader][0];
+
+   switch (shader) {
+   case PIPE_SHADER_VERTEX:
+      variant = svga->state.hw_draw.vs;
+      extra_count = svga_get_extra_vs_constants(svga, (float *) extras);
+      break;
+   case PIPE_SHADER_FRAGMENT:
+      variant = svga->state.hw_draw.fs;
+      extra_count = svga_get_extra_fs_constants(svga, (float *) extras);
+      break;
+   case PIPE_SHADER_GEOMETRY:
+      variant = svga->state.hw_draw.gs;
+      extra_count = svga_get_extra_gs_constants(svga, (float *) extras);
+      break;
+   default:
+      assert(!"Unexpected shader type");
+      /* Don't return an error code since we don't want to keep re-trying
+       * this function and getting stuck in an infinite loop.
+       */
+      return PIPE_OK;
+   }
+
+   assert(variant);
+
+   /* Compute extra constants size and offset in bytes */
+   extra_size = extra_count * 4 * sizeof(float);
+   extra_offset = 4 * sizeof(float) * variant->extra_const_start;
+
+   if (cbuf->buffer_size + extra_size == 0)
+      return PIPE_OK;  /* nothing to do */
+
+   /* Typically, the cbuf->buffer here is a user-space buffer so mapping
+    * it is really cheap.  If we ever get real HW buffers for constants
+    * we should void mapping and instead use a ResourceCopy command.
+    */
+   if (cbuf->buffer_size > 0) {
+      src_map = pipe_buffer_map_range(&svga->pipe, cbuf->buffer,
+                                      cbuf->buffer_offset, cbuf->buffer_size,
+                                      PIPE_TRANSFER_READ, &src_transfer);
+      assert(src_map);
+      if (!src_map) {
+         return PIPE_ERROR_OUT_OF_MEMORY;
+      }
+   }
+
+   /* The new/dest buffer's size must be large enough to hold the original,
+    * user-specified constants, plus the extra constants.
+    * The size of the original constant buffer _should_ agree with what the
+    * shader is expecting, but it might not (it's not enforced anywhere by
+    * gallium).
+    */
+   new_buf_size = MAX2(cbuf->buffer_size, extra_offset) + extra_size;
+
+   /* According to the DX10 spec, the constant buffer size must be
+    * in multiples of 16.
+    */
+   new_buf_size = align(new_buf_size, 16);
+
+   ret = u_upload_alloc(svga->const0_upload, 0, new_buf_size, &offset,
+                        &dst_buffer, &dst_map);
+   if (ret != PIPE_OK || !dst_map) {
+      if (src_map)
+         pipe_buffer_unmap(&svga->pipe, src_transfer);
+      return PIPE_ERROR_OUT_OF_MEMORY;
+   }
+
+   if (src_map) {
+      memcpy(dst_map, src_map, cbuf->buffer_size);
+      pipe_buffer_unmap(&svga->pipe, src_transfer);
+   }
+
+   if (extra_size) {
+      assert(extra_offset + extra_size <= new_buf_size);
+      memcpy((char *) dst_map + extra_offset, extras, extra_size);
+   }
+   u_upload_unmap(svga->const0_upload);
+
+   /* Issue the SetSingleConstantBuffer command */
+   dst_handle = svga_buffer_handle(svga, dst_buffer);
+   if (!dst_handle) {
+      pipe_resource_reference(&dst_buffer, NULL);
+      return PIPE_ERROR_OUT_OF_MEMORY;
+   }
+
+   assert(new_buf_size % 16 == 0);
+   ret = SVGA3D_vgpu10_SetSingleConstantBuffer(svga->swc,
+                                               0, /* index */
+                                               svga_shader_type(shader),
+                                               dst_handle,
+                                               offset,
+                                               new_buf_size);
+
+   if (ret != PIPE_OK) {
+      pipe_resource_reference(&dst_buffer, NULL);
+      return ret;
+   }
+
+   /* Save this const buffer until it's replaced in the future.
+    * Otherwise, all references to the buffer will go away after the
+    * command buffer is submitted, it'll get recycled and we will have
+    * incorrect constant buffer bindings.
+    */
+   pipe_resource_reference(&svga->state.hw_draw.constbuf[shader], dst_buffer);
+
+   svga->state.hw_draw.default_constbuf_size[shader] = new_buf_size;
+
+   pipe_resource_reference(&dst_buffer, NULL);
 
    return ret;
 }
 
 
+static enum pipe_error
+emit_consts_vgpu10(struct svga_context *svga, unsigned shader)
+{
+   enum pipe_error ret;
+   unsigned dirty_constbufs;
+   unsigned enabled_constbufs;
+
+   /* Emit 0th constant buffer (with extra constants) */
+   ret = emit_constbuf_vgpu10(svga, shader);
+   if (ret != PIPE_OK) {
+      return ret;
+   }
+
+   enabled_constbufs = svga->state.hw_draw.enabled_constbufs[shader] | 1u;
+
+   /* Emit other constant buffers (UBOs) */
+   dirty_constbufs = svga->state.dirty_constbufs[shader] & ~1u;
+
+   while (dirty_constbufs) {
+      unsigned index = u_bit_scan(&dirty_constbufs);
+      unsigned offset = svga->curr.constbufs[shader][index].buffer_offset;
+      unsigned size = svga->curr.constbufs[shader][index].buffer_size;
+      struct svga_buffer *buffer =
+         svga_buffer(svga->curr.constbufs[shader][index].buffer);
+      struct svga_winsys_surface *handle;
+
+      if (buffer) {
+         handle = svga_buffer_handle(svga, &buffer->b.b);
+         enabled_constbufs |= 1 << index;
+      }
+      else {
+         handle = NULL;
+         enabled_constbufs &= ~(1 << index);
+         assert(offset == 0);
+         assert(size == 0);
+      }
+
+      assert(size % 16 == 0);
+      ret = SVGA3D_vgpu10_SetSingleConstantBuffer(svga->swc,
+                                                  index,
+                                                  svga_shader_type(shader),
+                                                  handle,
+                                                  offset,
+                                                  size);
+      if (ret != PIPE_OK)
+         return ret;
+   }
+
+   svga->state.hw_draw.enabled_constbufs[shader] = enabled_constbufs;
+   svga->state.dirty_constbufs[shader] = 0;
+
+   return ret;
+}
+
 static enum pipe_error
 emit_fs_consts(struct svga_context *svga, unsigned dirty)
 {
-   struct svga_screen *ss = svga_screen(svga->pipe.screen);
    const struct svga_shader_variant *variant = svga->state.hw_draw.fs;
    enum pipe_error ret = PIPE_OK;
 
@@ -377,28 +734,11 @@ emit_fs_consts(struct svga_context *svga, unsigned dirty)
 
    /* SVGA_NEW_FS_CONST_BUFFER
     */
-   ret = emit_consts( svga, PIPE_SHADER_FRAGMENT );
-   if (ret != PIPE_OK)
-      return ret;
-
-   /* emit extra shader constants */
-   {
-      unsigned offset = variant->shader->info.file_max[TGSI_FILE_CONSTANT] + 1;
-      float extras[MAX_EXTRA_CONSTS][4];
-      unsigned count, i;
-
-      count = svga_get_extra_fs_constants(svga, (float *) extras);
-
-      if (ss->hw_version >= SVGA3D_HWVERSION_WS8_B1) {
-         ret = emit_const_range(svga, PIPE_SHADER_FRAGMENT, offset, count,
-                                (const float (*) [4])extras);
-      } else {
-         for (i = 0; i < count; i++) {
-            ret = emit_const(svga, PIPE_SHADER_FRAGMENT, offset + i, extras[i]);
-            if (ret != PIPE_OK)
-               return ret;
-         }
-      }
+   if (svga_have_vgpu10(svga)) {
+      ret = emit_consts_vgpu10(svga, PIPE_SHADER_FRAGMENT);
+   }
+   else {
+      ret = emit_consts_vgpu9(svga, PIPE_SHADER_FRAGMENT);
    }
 
    return ret;
@@ -419,7 +759,6 @@ struct svga_tracked_state svga_hw_fs_constants =
 static enum pipe_error
 emit_vs_consts(struct svga_context *svga, unsigned dirty)
 {
-   struct svga_screen *ss = svga_screen(svga->pipe.screen);
    const struct svga_shader_variant *variant = svga->state.hw_draw.vs;
    enum pipe_error ret = PIPE_OK;
 
@@ -430,29 +769,11 @@ emit_vs_consts(struct svga_context *svga, unsigned dirty)
 
    /* SVGA_NEW_VS_CONST_BUFFER
     */
-   ret = emit_consts( svga, PIPE_SHADER_VERTEX );
-   if (ret != PIPE_OK)
-      return ret;
-
-   /* emit extra shader constants */
-   {
-      unsigned offset = variant->shader->info.file_max[TGSI_FILE_CONSTANT] + 1;
-      float extras[MAX_EXTRA_CONSTS][4];
-      unsigned count, i;
-
-      count = svga_get_extra_vs_constants(svga, (float *) extras);
-      assert(count <= Elements(extras));
-
-      if (ss->hw_version >= SVGA3D_HWVERSION_WS8_B1) {
-         ret = emit_const_range(svga, PIPE_SHADER_VERTEX, offset, count,
-                                (const float (*) [4]) extras);
-      } else {
-         for (i = 0; i < count; i++) {
-            ret = emit_const(svga, PIPE_SHADER_VERTEX, offset + i, extras[i]);
-            if (ret != PIPE_OK)
-               return ret;
-         }
-      }
+   if (svga_have_vgpu10(svga)) {
+      ret = emit_consts_vgpu10(svga, PIPE_SHADER_VERTEX);
+   }
+   else {
+      ret = emit_consts_vgpu9(svga, PIPE_SHADER_VERTEX);
    }
 
    return ret;
@@ -467,3 +788,42 @@ struct svga_tracked_state svga_hw_vs_constants =
     SVGA_NEW_VS_VARIANT),
    emit_vs_consts
 };
+
+
+static enum pipe_error
+emit_gs_consts(struct svga_context *svga, unsigned dirty)
+{
+   const struct svga_shader_variant *variant = svga->state.hw_draw.gs;
+   enum pipe_error ret = PIPE_OK;
+
+   /* SVGA_NEW_GS_VARIANT
+    */
+   if (variant == NULL)
+      return PIPE_OK;
+
+   /* SVGA_NEW_GS_CONST_BUFFER
+    */
+   if (svga_have_vgpu10(svga)) {
+      /**
+       * If only the rasterizer state has changed and the current geometry
+       * shader does not emit wide points, then there is no reason to
+       * re-emit the GS constants, so skip it.
+       */
+      if (dirty == SVGA_NEW_RAST && !variant->key.gs.wide_point)
+         return PIPE_OK;
+
+      ret = emit_consts_vgpu10(svga, PIPE_SHADER_GEOMETRY);
+   }
+
+   return ret;
+}
+
+
+struct svga_tracked_state svga_hw_gs_constants =
+{
+   "hw gs params",
+   (SVGA_NEW_GS_CONST_BUFFER |
+    SVGA_NEW_RAST |
+    SVGA_NEW_GS_VARIANT),
+   emit_gs_consts
+};
index 1c174da31300dd496d6ca1d51f6f8e82551803fa..9abacc9fa204451f859822a39a4257b9a2e12b8b 100644 (file)
 #include "util/u_inlines.h"
 #include "pipe/p_defines.h"
 #include "util/u_math.h"
+#include "util/u_format.h"
 
 #include "svga_context.h"
 #include "svga_state.h"
 #include "svga_cmd.h"
 #include "svga_debug.h"
 #include "svga_screen.h"
+#include "svga_surface.h"
 
 
 /*
 #define MAX_RT_PER_BATCH 8
 
 
-/***********************************************************************
- * Hardware state update
- */
-
 
 static enum pipe_error
-emit_framebuffer( struct svga_context *svga,
-                  unsigned dirty )
+emit_fb_vgpu9(struct svga_context *svga)
 {
    struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
    const struct pipe_framebuffer_state *curr = &svga->curr.framebuffer;
    struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
-   boolean reemit = svga->rebind.rendertargets;
+   boolean reemit = svga->rebind.flags.rendertargets;
    unsigned i;
    enum pipe_error ret;
 
+   assert(!svga_have_vgpu10(svga));
+
    /*
     * We need to reemit non-null surface bindings, even when they are not
     * dirty, to ensure that the resources are paged in.
     */
 
    for (i = 0; i < svgascreen->max_color_buffers; i++) {
-      if (curr->cbufs[i] != hw->cbufs[i] ||
-          (reemit && hw->cbufs[i])) {
+      if ((curr->cbufs[i] != hw->cbufs[i]) || (reemit && hw->cbufs[i])) {
          if (svga->curr.nr_fbs++ > MAX_RT_PER_BATCH)
             return PIPE_ERROR_OUT_OF_MEMORY;
 
@@ -82,14 +80,13 @@ emit_framebuffer( struct svga_context *svga,
       }
    }
 
-   if (curr->zsbuf != hw->zsbuf ||
-       (reemit && hw->zsbuf)) {
+   if ((curr->zsbuf != hw->zsbuf) || (reemit && hw->zsbuf)) {
       ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_DEPTH, curr->zsbuf);
       if (ret != PIPE_OK)
          return ret;
 
       if (curr->zsbuf &&
-          curr->zsbuf->format == PIPE_FORMAT_S8_UINT_Z24_UNORM) {
+          util_format_is_depth_and_stencil(curr->zsbuf->format)) {
          ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL,
                                       curr->zsbuf);
          if (ret != PIPE_OK)
@@ -104,8 +101,6 @@ emit_framebuffer( struct svga_context *svga,
       pipe_surface_reference(&hw->zsbuf, curr->zsbuf);
    }
 
-   svga->rebind.rendertargets = FALSE;
-
    return PIPE_OK;
 }
 
@@ -118,15 +113,15 @@ emit_framebuffer( struct svga_context *svga,
  * Called at the beginning of every new command buffer to ensure that
  * non-dirty rendertargets are properly paged-in.
  */
-enum pipe_error
-svga_reemit_framebuffer_bindings(struct svga_context *svga)
+static enum pipe_error
+svga_reemit_framebuffer_bindings_vgpu9(struct svga_context *svga)
 {
    struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
    struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
    unsigned i;
    enum pipe_error ret;
 
-   assert(svga->rebind.rendertargets);
+   assert(!svga_have_vgpu10(svga));
 
    for (i = 0; i < svgascreen->max_color_buffers; i++) {
       if (hw->cbufs[i]) {
@@ -145,7 +140,7 @@ svga_reemit_framebuffer_bindings(struct svga_context *svga)
       }
 
       if (hw->zsbuf &&
-          hw->zsbuf->format == PIPE_FORMAT_S8_UINT_Z24_UNORM) {
+          util_format_is_depth_and_stencil(hw->zsbuf->format)) {
          ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, hw->zsbuf);
          if (ret != PIPE_OK) {
             return ret;
@@ -159,7 +154,161 @@ svga_reemit_framebuffer_bindings(struct svga_context *svga)
       }
    }
 
-   svga->rebind.rendertargets = FALSE;
+   return PIPE_OK;
+}
+
+
+
+static enum pipe_error
+emit_fb_vgpu10(struct svga_context *svga)
+{
+   const struct svga_screen *ss = svga_screen(svga->pipe.screen);
+   struct pipe_surface *rtv[SVGA3D_MAX_RENDER_TARGETS];
+   struct pipe_surface *dsv;
+   struct pipe_framebuffer_state *curr = &svga->curr.framebuffer;
+   struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
+   const unsigned num_color = MAX2(curr->nr_cbufs, hw->nr_cbufs);
+   unsigned i;
+   enum pipe_error ret;
+
+   assert(svga_have_vgpu10(svga));
+
+   /* Setup render targets array.  Note that we loop over the max of the
+    * number of previously bound buffers and the new buffers to unbind
+    * any previously bound buffers when the new number of buffers is less
+    * than the old number of buffers.
+    */
+   for (i = 0; i < num_color; i++) {
+      if (curr->cbufs[i]) {
+         rtv[i] = svga_validate_surface_view(svga,
+                                             svga_surface(curr->cbufs[i]));
+         if (rtv[i] == NULL) {
+            return PIPE_ERROR_OUT_OF_MEMORY;
+         }
+
+         assert(svga_surface(rtv[i])->view_id != SVGA3D_INVALID_ID);
+      }
+      else {
+         rtv[i] = NULL;
+      }
+   }
+
+   /* Setup depth stencil view */
+   if (curr->zsbuf) {
+      dsv = svga_validate_surface_view(svga, svga_surface(curr->zsbuf));
+      if (dsv == NULL) {
+         return PIPE_ERROR_OUT_OF_MEMORY;
+      }
+   }
+   else {
+      dsv = NULL;
+   }
+
+   ret = SVGA3D_vgpu10_SetRenderTargets(svga->swc, num_color, rtv, dsv);
+   if (ret != PIPE_OK)
+      return ret;
+
+   for (i = 0; i < ss->max_color_buffers; i++) {
+      if (hw->cbufs[i] != curr->cbufs[i]) {
+         /* propagate the backed view surface before unbinding it */
+         if (hw->cbufs[i] && svga_surface(hw->cbufs[i])->backed) {
+            svga_propagate_surface(svga,
+                                   &svga_surface(hw->cbufs[i])->backed->base);
+         }
+         pipe_surface_reference(&hw->cbufs[i], curr->cbufs[i]);
+      }
+   }
+   hw->nr_cbufs = curr->nr_cbufs;
+
+   if (hw->zsbuf != curr->zsbuf) {
+      /* propagate the backed view surface before unbinding it */
+      if (hw->zsbuf && svga_surface(hw->zsbuf)->backed) {
+         svga_propagate_surface(svga, &svga_surface(hw->zsbuf)->backed->base);
+      }
+      pipe_surface_reference(&hw->zsbuf, curr->zsbuf);
+   }
+
+   return ret;
+}
+
+
+static enum pipe_error
+emit_framebuffer(struct svga_context *svga, unsigned dirty)
+{
+   if (svga_have_vgpu10(svga)) {
+      return emit_fb_vgpu10(svga);
+   }
+   else {
+      return emit_fb_vgpu9(svga);
+   }
+}
+
+
+/*
+ * Rebind rendertargets.
+ *
+ * Similar to emit_framebuffer, but without any state checking/update.
+ *
+ * Called at the beginning of every new command buffer to ensure that
+ * non-dirty rendertargets are properly paged-in.
+ */
+enum pipe_error
+svga_reemit_framebuffer_bindings(struct svga_context *svga)
+{
+   enum pipe_error ret;
+
+   assert(svga->rebind.flags.rendertargets);
+
+   if (svga_have_vgpu10(svga)) {
+      ret = emit_fb_vgpu10(svga);
+   }
+   else {
+      ret = svga_reemit_framebuffer_bindings_vgpu9(svga);
+   }
+
+   svga->rebind.flags.rendertargets = FALSE;
+
+   return ret;
+}
+
+
+/*
+ * Send a private allocation command to page in rendertargets resource.
+ */
+enum pipe_error
+svga_rebind_framebuffer_bindings(struct svga_context *svga)
+{
+   const struct svga_screen *ss = svga_screen(svga->pipe.screen);
+   struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
+   unsigned i;
+   enum pipe_error ret;
+
+   assert(svga_have_vgpu10(svga));
+
+   if (!svga->rebind.flags.rendertargets)
+      return PIPE_OK;
+
+   for (i = 0; i < ss->max_color_buffers; i++) {
+      if (hw->cbufs[i]) {
+         ret = svga->swc->resource_rebind(svga->swc,
+                                          svga_surface(hw->cbufs[i])->handle,
+                                          NULL,
+                                          SVGA_RELOC_WRITE);
+         if (ret != PIPE_OK)
+            return ret;
+      }
+   }
+
+   if (hw->zsbuf) {
+      ret = svga->swc->resource_rebind(svga->swc,
+                                       svga_surface(hw->zsbuf)->handle,
+                                       NULL,
+                                       SVGA_RELOC_WRITE);
+      if (ret != PIPE_OK)
+         return ret;
+   }
+
+   svga->rebind.flags.rendertargets = 0;
 
    return PIPE_OK;
 }
@@ -202,6 +351,7 @@ emit_viewport( struct svga_context *svga,
    float fy = flip * viewport->scale[1] * -1.0f + viewport->translate[1];
    float fw =        viewport->scale[0] * 2.0f;
    float fh = flip * viewport->scale[1] * 2.0f;
+   boolean emit_vgpu10_viewport = FALSE;
 
    memset( &prescale, 0, sizeof(prescale) );
 
@@ -225,7 +375,16 @@ emit_viewport( struct svga_context *svga,
    prescale.translate[1] = 0;
    prescale.translate[2] = 0;
    prescale.translate[3] = 0;
-   prescale.enabled = TRUE;
+
+   /* Enable prescale to adjust vertex positions to match
+      VGPU10 convention only if rasterization is enabled.
+    */
+   if (svga->curr.rast->templ.rasterizer_discard) {
+      degenerate = TRUE;
+      goto out;
+   } else {
+      prescale.enabled = TRUE;
+   }
 
    if (fw < 0) {
       prescale.scale[0] *= -1.0f;
@@ -235,7 +394,14 @@ emit_viewport( struct svga_context *svga,
    }
 
    if (fh < 0.0) {
-      prescale.translate[1] = fh - 1.0f + fy * 2.0f;
+      if (svga_have_vgpu10(svga)) {
+         /* floating point viewport params below */
+         prescale.translate[1] = fh + fy * 2.0f;
+      }
+      else {
+         /* integer viewport params below */
+         prescale.translate[1] = fh - 1.0f + fy * 2.0f;
+      }
       fh = -fh;
       fy -= fh;
       prescale.scale[1] = -1.0f;
@@ -321,19 +487,31 @@ emit_viewport( struct svga_context *svga,
       float adjust_x = 0.0;
       float adjust_y = 0.0;
 
-      switch (svga->curr.reduced_prim) {
-      case PIPE_PRIM_POINTS:
-         adjust_x = -0.375;
-         adjust_y = -0.75;
-         break;
-      case PIPE_PRIM_LINES:
-         adjust_x = -0.5;
-         adjust_y = 0;
-         break;
-      case PIPE_PRIM_TRIANGLES:
-         adjust_x = -0.5;
-         adjust_y = -0.5;
-         break;
+      if (svga_have_vgpu10(svga)) {
+         /* Normally, we don't have to do any sub-pixel coordinate
+          * adjustments for VGPU10.  But when we draw wide points with
+          * a GS we need an X adjustment in order to be conformant.
+          */
+         if (svga->curr.reduced_prim == PIPE_PRIM_POINTS &&
+             svga->curr.rast->pointsize > 1.0f) {
+            adjust_x = 0.5;
+         }
+      }
+      else {
+         switch (svga->curr.reduced_prim) {
+         case PIPE_PRIM_POINTS:
+            adjust_x = -0.375;
+            adjust_y = -0.75;
+            break;
+         case PIPE_PRIM_LINES:
+            adjust_x = -0.5;
+            adjust_y = 0;
+            break;
+         case PIPE_PRIM_TRIANGLES:
+            adjust_x = -0.5;
+            adjust_y = -0.5;
+            break;
+         }
       }
 
       if (invertY)
@@ -360,6 +538,17 @@ emit_viewport( struct svga_context *svga,
       prescale.scale[2] = -prescale.scale[2];
    }
 
+   /* If zmin is less than 0, clamp zmin to 0 and adjust the prescale.
+    * zmin can be set to -1 when viewport->scale[2] is set to 1 and
+    * viewport->translate[2] is set to 0 in the blit code.
+    */
+   if (range_min < 0.0f) {
+      range_min = -0.5f * viewport->scale[2] + 0.5f + viewport->translate[2];
+      range_max = 0.5f * viewport->scale[2] + 0.5f + viewport->translate[2];
+      prescale.scale[2] *= 2.0f;
+      prescale.translate[2] -= 0.5f;
+   }
+
    if (prescale.enabled) {
       float H[2];
       float J[2];
@@ -428,21 +617,49 @@ out:
       prescale.enabled = FALSE;
    }
 
-   if (memcmp(&rect, &svga->state.hw_clear.viewport, sizeof(rect)) != 0) {
-      ret = SVGA3D_SetViewport(svga->swc, &rect);
-      if(ret != PIPE_OK)
-         return ret;
+   if (!svga_rects_equal(&rect, &svga->state.hw_clear.viewport)) {
+      if (svga_have_vgpu10(svga)) {
+         emit_vgpu10_viewport = TRUE;
+      }
+      else {
+         ret = SVGA3D_SetViewport(svga->swc, &rect);
+         if (ret != PIPE_OK)
+            return ret;
 
-      memcpy(&svga->state.hw_clear.viewport, &rect, sizeof(rect));
-      assert(sizeof(rect) == sizeof(svga->state.hw_clear.viewport));
+         svga->state.hw_clear.viewport = rect;
+      }
    }
 
    if (svga->state.hw_clear.depthrange.zmin != range_min ||
-       svga->state.hw_clear.depthrange.zmax != range_max) {
-      ret = SVGA3D_SetZRange(svga->swc, range_min, range_max );
-      if(ret != PIPE_OK)
+       svga->state.hw_clear.depthrange.zmax != range_max)
+   {
+      if (svga_have_vgpu10(svga)) {
+         emit_vgpu10_viewport = TRUE;
+      }
+      else {
+         ret = SVGA3D_SetZRange(svga->swc, range_min, range_max );
+         if (ret != PIPE_OK)
+            return ret;
+
+         svga->state.hw_clear.depthrange.zmin = range_min;
+         svga->state.hw_clear.depthrange.zmax = range_max;
+      }
+   }
+
+   if (emit_vgpu10_viewport) {
+      SVGA3dViewport vp;
+      vp.x = (float) rect.x;
+      vp.y = (float) rect.y;
+      vp.width = (float) rect.w;
+      vp.height = (float) rect.h;
+      vp.minDepth = range_min;
+      vp.maxDepth = range_max;
+      ret = SVGA3D_vgpu10_SetViewports(svga->swc, 1, &vp);
+      if (ret != PIPE_OK)
          return ret;
 
+      svga->state.hw_clear.viewport = rect;
+
       svga->state.hw_clear.depthrange.zmin = range_min;
       svga->state.hw_clear.depthrange.zmax = range_max;
    }
@@ -475,14 +692,27 @@ emit_scissor_rect( struct svga_context *svga,
                    unsigned dirty )
 {
    const struct pipe_scissor_state *scissor = &svga->curr.scissor;
-   SVGA3dRect rect;
 
-   rect.x = scissor->minx;
-   rect.y = scissor->miny;
-   rect.w = scissor->maxx - scissor->minx; /* + 1 ?? */
-   rect.h = scissor->maxy - scissor->miny; /* + 1 ?? */
+   if (svga_have_vgpu10(svga)) {
+      SVGASignedRect rect;
+
+      rect.left = scissor->minx;
+      rect.top = scissor->miny;
+      rect.right = scissor->maxx;
+      rect.bottom = scissor->maxy;
+
+      return SVGA3D_vgpu10_SetScissorRects(svga->swc, 1, &rect);
+   }
+   else {
+      SVGA3dRect rect;
 
-   return SVGA3D_SetScissorRect(svga->swc, &rect);
+      rect.x = scissor->minx;
+      rect.y = scissor->miny;
+      rect.w = scissor->maxx - scissor->minx; /* + 1 ?? */
+      rect.h = scissor->maxy - scissor->miny; /* + 1 ?? */
+
+      return SVGA3D_SetScissorRect(svga->swc, &rect);
+   }
 }
 
 
@@ -527,9 +757,15 @@ emit_clip_planes( struct svga_context *svga,
       plane[2] = 2.0f * c;
       plane[3] = d - c;
 
-      ret = SVGA3D_SetClipPlane(svga->swc, i, plane);
-      if(ret != PIPE_OK)
-         return ret;
+      if (svga_have_vgpu10(svga)) {
+         //debug_printf("XXX emit DX10 clip plane\n");
+         ret = PIPE_OK;
+      }
+      else {
+         ret = SVGA3D_SetClipPlane(svga->swc, i, plane);
+         if (ret != PIPE_OK)
+            return ret;
+      }
    }
 
    return PIPE_OK;
index 8cdce742b3bb6c18e695ce0bbfc730b6ef6edc4f..849319d3cf3ac13f35dcfaecfd05b5bd83d9a4fa 100644 (file)
 #include "svga_shader.h"
 #include "svga_resource_texture.h"
 #include "svga_tgsi.h"
+#include "svga_format.h"
 
 #include "svga_hw_reg.h"
 
 
 
-static inline int
-compare_fs_keys(const struct svga_fs_compile_key *a,
-                const struct svga_fs_compile_key *b)
-{
-   unsigned keysize_a = svga_fs_key_size( a );
-   unsigned keysize_b = svga_fs_key_size( b );
-
-   if (keysize_a != keysize_b) {
-      return (int)(keysize_a - keysize_b);
-   }
-   return memcmp( a, b, keysize_a );
-}
-
-
-/** Search for a fragment shader variant */
-static struct svga_shader_variant *
-search_fs_key(const struct svga_fragment_shader *fs,
-              const struct svga_fs_compile_key *key)
-{
-   struct svga_shader_variant *variant = fs->base.variants;
-
-   assert(key);
-
-   for ( ; variant; variant = variant->next) {
-      if (compare_fs_keys( key, &variant->key.fkey ) == 0)
-         return variant;
-   }
-   
-   return NULL;
-}
-
-
 /**
  * If we fail to compile a fragment shader (because it uses too many
  * registers, for example) we'll use a dummy/fallback shader that
@@ -111,13 +80,29 @@ get_dummy_fragment_shader(void)
 }
 
 
+static struct svga_shader_variant *
+translate_fragment_program(struct svga_context *svga,
+                           const struct svga_fragment_shader *fs,
+                           const struct svga_compile_key *key)
+{
+   if (svga_have_vgpu10(svga)) {
+      return svga_tgsi_vgpu10_translate(svga, &fs->base, key,
+                                        PIPE_SHADER_FRAGMENT);
+   }
+   else {
+      return svga_tgsi_vgpu9_translate(&fs->base, key, PIPE_SHADER_FRAGMENT);
+   }
+}
+
+
 /**
  * Replace the given shader's instruction with a simple constant-color
  * shader.  We use this when normal shader translation fails.
  */
 static struct svga_shader_variant *
-get_compiled_dummy_shader(struct svga_fragment_shader *fs,
-                          const struct svga_fs_compile_key *key)
+get_compiled_dummy_shader(struct svga_context *svga,
+                          struct svga_fragment_shader *fs,
+                          const struct svga_compile_key *key)
 {
    const struct tgsi_token *dummy = get_dummy_fragment_shader();
    struct svga_shader_variant *variant;
@@ -129,7 +114,7 @@ get_compiled_dummy_shader(struct svga_fragment_shader *fs,
    FREE((void *) fs->base.tokens);
    fs->base.tokens = dummy;
 
-   variant = svga_translate_fragment_program(fs, key);
+   variant = translate_fragment_program(svga, fs, key);
    return variant;
 }
 
@@ -140,17 +125,17 @@ get_compiled_dummy_shader(struct svga_fragment_shader *fs,
 static enum pipe_error
 compile_fs(struct svga_context *svga,
            struct svga_fragment_shader *fs,
-           const struct svga_fs_compile_key *key,
+           const struct svga_compile_key *key,
            struct svga_shader_variant **out_variant)
 {
    struct svga_shader_variant *variant;
    enum pipe_error ret = PIPE_ERROR;
 
-   variant = svga_translate_fragment_program( fs, key );
+   variant = translate_fragment_program(svga, fs, key);
    if (variant == NULL) {
       debug_printf("Failed to compile fragment shader,"
                    " using dummy shader instead.\n");
-      variant = get_compiled_dummy_shader(fs, key);
+      variant = get_compiled_dummy_shader(svga, fs, key);
       if (!variant) {
          ret = PIPE_ERROR;
          goto fail;
@@ -159,10 +144,11 @@ compile_fs(struct svga_context *svga,
 
    if (svga_shader_too_large(svga, variant)) {
       /* too big, use dummy shader */
-      debug_printf("Shader too large (%lu bytes),"
+      debug_printf("Shader too large (%u bytes),"
                    " using dummy shader instead.\n",
-                   (unsigned long ) variant->nr_tokens * sizeof(variant->tokens[0]));
-      variant = get_compiled_dummy_shader(fs, key);
+                   (unsigned) (variant->nr_tokens
+                               * sizeof(variant->tokens[0])));
+      variant = get_compiled_dummy_shader(svga, fs, key);
       if (!variant) {
          ret = PIPE_ERROR;
          goto fail;
@@ -197,23 +183,45 @@ fail:
 static enum pipe_error
 make_fs_key(const struct svga_context *svga,
             struct svga_fragment_shader *fs,
-            struct svga_fs_compile_key *key)
+            struct svga_compile_key *key)
 {
+   const unsigned shader = PIPE_SHADER_FRAGMENT;
    unsigned i;
-   int idx = 0;
 
    memset(key, 0, sizeof *key);
 
+   memcpy(key->generic_remap_table, fs->generic_remap_table,
+          sizeof(fs->generic_remap_table));
+
+   /* SVGA_NEW_GS, SVGA_NEW_VS
+    */
+   if (svga->curr.gs) {
+      key->fs.gs_generic_outputs = svga->curr.gs->generic_outputs;
+   } else {
+      key->fs.vs_generic_outputs = svga->curr.vs->generic_outputs;
+   }
+
    /* Only need fragment shader fixup for twoside lighting if doing
     * hwtnl.  Otherwise the draw module does the whole job for us.
     *
     * SVGA_NEW_SWTNL
     */
    if (!svga->state.sw.need_swtnl) {
-      /* SVGA_NEW_RAST
+      /* SVGA_NEW_RAST, SVGA_NEW_REDUCED_PRIMITIVE
        */
-      key->light_twoside = svga->curr.rast->templ.light_twoside;
-      key->front_ccw = svga->curr.rast->templ.front_ccw;
+      key->fs.light_twoside = svga->curr.rast->templ.light_twoside;
+      key->fs.front_ccw = svga->curr.rast->templ.front_ccw;
+      key->fs.pstipple = (svga->curr.rast->templ.poly_stipple_enable &&
+                          svga->curr.reduced_prim == PIPE_PRIM_TRIANGLES);
+      key->fs.aa_point = (svga->curr.rast->templ.point_smooth &&
+                          svga->curr.reduced_prim == PIPE_PRIM_POINTS &&
+                          (svga->curr.rast->pointsize > 1.0 ||
+                           svga->curr.vs->base.info.writes_psize));
+      if (key->fs.aa_point) {
+         assert(svga->curr.gs != NULL);
+         assert(svga->curr.gs->aa_point_coord_index != -1);
+         key->fs.aa_point_coord_index = svga->curr.gs->aa_point_coord_index;
+      }
    }
 
    /* The blend workaround for simulating logicop xor behaviour
@@ -231,7 +239,7 @@ make_fs_key(const struct svga_context *svga,
     * SVGA_NEW_BLEND
     */
    if (svga->curr.blend->need_white_fragments) {
-      key->white_fragments = 1;
+      key->fs.white_fragments = 1;
    }
 
 #ifdef DEBUG
@@ -241,22 +249,23 @@ make_fs_key(const struct svga_context *svga,
     */
    {
       static boolean warned = FALSE;
-      unsigned i, n = MAX2(svga->curr.num_sampler_views,
-                           svga->curr.num_samplers);
+      unsigned i, n = MAX2(svga->curr.num_sampler_views[shader],
+                           svga->curr.num_samplers[shader]);
       /* Only warn once to prevent too much debug output */
       if (!warned) {
-         if (svga->curr.num_sampler_views != svga->curr.num_samplers) {
+         if (svga->curr.num_sampler_views[shader] !=
+             svga->curr.num_samplers[shader]) {
             debug_printf("svga: mismatched number of sampler views (%u) "
                          "vs. samplers (%u)\n",
-                         svga->curr.num_sampler_views,
-                         svga->curr.num_samplers);
+                         svga->curr.num_sampler_views[shader],
+                         svga->curr.num_samplers[shader]);
          }
          for (i = 0; i < n; i++) {
-            if ((svga->curr.sampler_views[i] == NULL) !=
-                (svga->curr.sampler[i] == NULL))
+            if ((svga->curr.sampler_views[shader][i] == NULL) !=
+                (svga->curr.sampler[shader][i] == NULL))
                debug_printf("sampler_view[%u] = %p but sampler[%u] = %p\n",
-                            i, svga->curr.sampler_views[i],
-                            i, svga->curr.sampler[i]);
+                            i, svga->curr.sampler_views[shader][i],
+                            i, svga->curr.sampler[shader][i]);
          }
          warned = TRUE;
       }
@@ -268,68 +277,62 @@ make_fs_key(const struct svga_context *svga,
     *
     * SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER
     */
-   for (i = 0; i < svga->curr.num_sampler_views; i++) {
-      if (svga->curr.sampler_views[i] && svga->curr.sampler[i]) {
-         assert(svga->curr.sampler_views[i]->texture);
-         key->tex[i].texture_target = svga->curr.sampler_views[i]->texture->target;
-         if (!svga->curr.sampler[i]->normalized_coords) {
-            key->tex[i].width_height_idx = idx++;
-            key->tex[i].unnormalized = TRUE;
-            ++key->num_unnormalized_coords;
-         }
-
-         key->tex[i].swizzle_r = svga->curr.sampler_views[i]->swizzle_r;
-         key->tex[i].swizzle_g = svga->curr.sampler_views[i]->swizzle_g;
-         key->tex[i].swizzle_b = svga->curr.sampler_views[i]->swizzle_b;
-         key->tex[i].swizzle_a = svga->curr.sampler_views[i]->swizzle_a;
-      }
-   }
-   key->num_textures = svga->curr.num_sampler_views;
-
-   idx = 0;
-   for (i = 0; i < svga->curr.num_samplers; ++i) {
-      if (svga->curr.sampler_views[i] && svga->curr.sampler[i]) {
-         struct pipe_resource *tex = svga->curr.sampler_views[i]->texture;
-         struct svga_texture *stex = svga_texture(tex);
-         SVGA3dSurfaceFormat format = stex->key.format;
-
-         if (format == SVGA3D_Z_D16 ||
-             format == SVGA3D_Z_D24X8 ||
-             format == SVGA3D_Z_D24S8) {
-            /* If we're sampling from a SVGA3D_Z_D16, SVGA3D_Z_D24X8,
-             * or SVGA3D_Z_D24S8 surface, we'll automatically get
-             * shadow comparison.  But we only get LEQUAL mode.
-             * Set TEX_COMPARE_NONE here so we don't emit the extra FS
-             * code for shadow comparison.
-             */
-            key->tex[i].compare_mode = PIPE_TEX_COMPARE_NONE;
-            key->tex[i].compare_func = PIPE_FUNC_NEVER;
-            /* These depth formats _only_ support comparison mode and
-             * not ordinary sampling so warn if the later is expected.
-             */
-            if (svga->curr.sampler[i]->compare_mode !=
-                PIPE_TEX_COMPARE_R_TO_TEXTURE) {
-               debug_warn_once("Unsupported shadow compare mode");
-            }                   
-            /* The only supported comparison mode is LEQUAL */
-            if (svga->curr.sampler[i]->compare_func != PIPE_FUNC_LEQUAL) {
-               debug_warn_once("Unsupported shadow compare function");
+   svga_init_shader_key_common(svga, shader, key);
+
+   for (i = 0; i < svga->curr.num_samplers[shader]; ++i) {
+      struct pipe_sampler_view *view = svga->curr.sampler_views[shader][i];
+      const struct svga_sampler_state *sampler = svga->curr.sampler[shader][i];
+      if (view) {
+         struct pipe_resource *tex = view->texture;
+         if (tex->target != PIPE_BUFFER) {
+            struct svga_texture *stex = svga_texture(tex);
+            SVGA3dSurfaceFormat format = stex->key.format;
+
+            if (!svga_have_vgpu10(svga) &&
+                (format == SVGA3D_Z_D16 ||
+                 format == SVGA3D_Z_D24X8 ||
+                 format == SVGA3D_Z_D24S8)) {
+               /* If we're sampling from a SVGA3D_Z_D16, SVGA3D_Z_D24X8,
+                * or SVGA3D_Z_D24S8 surface, we'll automatically get
+                * shadow comparison.  But we only get LEQUAL mode.
+                * Set TEX_COMPARE_NONE here so we don't emit the extra FS
+                * code for shadow comparison.
+                */
+               key->tex[i].compare_mode = PIPE_TEX_COMPARE_NONE;
+               key->tex[i].compare_func = PIPE_FUNC_NEVER;
+               /* These depth formats _only_ support comparison mode and
+                * not ordinary sampling so warn if the later is expected.
+                */
+               if (sampler->compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+                  debug_warn_once("Unsupported shadow compare mode");
+               }
+               /* The shader translation code can emit code to
+                * handle ALWAYS and NEVER compare functions
+                */
+               else if (sampler->compare_func == PIPE_FUNC_ALWAYS ||
+                        sampler->compare_func == PIPE_FUNC_NEVER) {
+                  key->tex[i].compare_mode = sampler->compare_mode;
+                  key->tex[i].compare_func = sampler->compare_func;
+               }
+               else if (sampler->compare_func != PIPE_FUNC_LEQUAL) {
+                  debug_warn_once("Unsupported shadow compare function");
+               }
+            }
+            else {
+               /* For other texture formats, just use the compare func/mode
+                * as-is.  Should be no-ops for color textures.  For depth
+                * textures, we do not get automatic depth compare.  We have
+                * to do it ourselves in the shader.  And we don't get PCF.
+                */
+               key->tex[i].compare_mode = sampler->compare_mode;
+               key->tex[i].compare_func = sampler->compare_func;
             }
-         }
-         else {
-            /* For other texture formats, just use the compare func/mode
-             * as-is.  Should be no-ops for color textures.  For depth
-             * textures, we do not get automatic depth compare.  We have
-             * to do it ourselves in the shader.  And we don't get PCF.
-             */
-            key->tex[i].compare_mode = svga->curr.sampler[i]->compare_mode;
-            key->tex[i].compare_func = svga->curr.sampler[i]->compare_func;
          }
       }
    }
 
    /* sprite coord gen state */
-   for (i = 0; i < svga->curr.num_samplers; ++i) {
+   for (i = 0; i < svga->curr.num_samplers[shader]; ++i) {
       key->tex[i].sprite_texgen =
          svga->curr.rast->templ.sprite_coord_enable & (1 << i);
    }
@@ -337,10 +340,25 @@ make_fs_key(const struct svga_context *svga,
    key->sprite_origin_lower_left = (svga->curr.rast->templ.sprite_coord_mode
                                     == PIPE_SPRITE_COORD_LOWER_LEFT);
 
+   key->fs.flatshade = svga->curr.rast->templ.flatshade;
+
+   /* SVGA_NEW_DEPTH_STENCIL_ALPHA */
+   if (svga_have_vgpu10(svga)) {
+      /* Alpha testing is not supported in integer-valued render targets. */
+      if (svga_has_any_integer_cbufs(svga)) {
+         key->fs.alpha_func = SVGA3D_CMP_ALWAYS;
+         key->fs.alpha_ref = 0;
+      }
+      else {
+         key->fs.alpha_func = svga->curr.depth->alphafunc;
+         key->fs.alpha_ref = svga->curr.depth->alpharef;
+      }
+   }
+
    /* SVGA_NEW_FRAME_BUFFER */
    if (fs->base.info.properties[TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS]) {
       /* Replicate color0 output to N colorbuffers */
-      key->write_color0_to_n_cbufs = svga->curr.framebuffer.nr_cbufs;
+      key->fs.write_color0_to_n_cbufs = svga->curr.framebuffer.nr_cbufs;
    }
 
    return PIPE_OK;
@@ -355,18 +373,32 @@ svga_reemit_fs_bindings(struct svga_context *svga)
 {
    enum pipe_error ret;
 
-   assert(svga->rebind.fs);
+   assert(svga->rebind.flags.fs);
    assert(svga_have_gb_objects(svga));
 
    if (!svga->state.hw_draw.fs)
       return PIPE_OK;
 
-   ret = SVGA3D_SetGBShader(svga->swc, SVGA3D_SHADERTYPE_PS,
-                            svga->state.hw_draw.fs->gb_shader);
+   if (!svga_need_to_rebind_resources(svga)) {
+      ret =  svga->swc->resource_rebind(svga->swc, NULL,
+                                        svga->state.hw_draw.fs->gb_shader,
+                                        SVGA_RELOC_READ);
+      goto out;
+   }
+
+   if (svga_have_vgpu10(svga))
+      ret = SVGA3D_vgpu10_SetShader(svga->swc, SVGA3D_SHADERTYPE_PS,
+                                    svga->state.hw_draw.fs->gb_shader,
+                                    svga->state.hw_draw.fs->id);
+   else
+      ret = SVGA3D_SetGBShader(svga->swc, SVGA3D_SHADERTYPE_PS,
+                               svga->state.hw_draw.fs->gb_shader);
+
+ out:
    if (ret != PIPE_OK)
       return ret;
 
-   svga->rebind.fs = FALSE;
+   svga->rebind.flags.fs = FALSE;
    return PIPE_OK;
 }
 
@@ -378,7 +410,7 @@ emit_hw_fs(struct svga_context *svga, unsigned dirty)
    struct svga_shader_variant *variant = NULL;
    enum pipe_error ret = PIPE_OK;
    struct svga_fragment_shader *fs = svga->curr.fs;
-   struct svga_fs_compile_key key;
+   struct svga_compile_key key;
 
    /* SVGA_NEW_BLEND
     * SVGA_NEW_TEXTURE_BINDING
@@ -386,14 +418,16 @@ emit_hw_fs(struct svga_context *svga, unsigned dirty)
     * SVGA_NEW_NEED_SWTNL
     * SVGA_NEW_SAMPLER
     * SVGA_NEW_FRAME_BUFFER
+    * SVGA_NEW_DEPTH_STENCIL_ALPHA
+    * SVGA_NEW_VS
     */
-   ret = make_fs_key( svga, fs, &key );
+   ret = make_fs_key(svga, fs, &key);
    if (ret != PIPE_OK)
       return ret;
 
-   variant = search_fs_key( fs, &key );
+   variant = svga_search_shader_key(&fs->base, &key);
    if (!variant) {
-      ret = compile_fs( svga, fs, &key, &variant );
+      ret = compile_fs(svga, fs, &key, &variant);
       if (ret != PIPE_OK)
          return ret;
    }
@@ -401,22 +435,14 @@ emit_hw_fs(struct svga_context *svga, unsigned dirty)
    assert(variant);
 
    if (variant != svga->state.hw_draw.fs) {
-      if (svga_have_gb_objects(svga)) {
-         ret = SVGA3D_SetGBShader(svga->swc, SVGA3D_SHADERTYPE_PS,
-                                  variant->gb_shader);
-         if (ret != PIPE_OK)
-            return ret;
+      ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_PS, variant);
+      if (ret != PIPE_OK)
+         return ret;
 
-         svga->rebind.fs = FALSE;
-      }
-      else {
-         ret = SVGA3D_SetShader(svga->swc, SVGA3D_SHADERTYPE_PS, variant->id);
-         if (ret != PIPE_OK)
-            return ret;
-      }
+      svga->rebind.flags.fs = FALSE;
 
       svga->dirty |= SVGA_NEW_FS_VARIANT;
-      svga->state.hw_draw.fs = variant;      
+      svga->state.hw_draw.fs = variant;
    }
 
    return PIPE_OK;
@@ -426,11 +452,15 @@ struct svga_tracked_state svga_hw_fs =
 {
    "fragment shader (hwtnl)",
    (SVGA_NEW_FS |
+    SVGA_NEW_GS |
+    SVGA_NEW_VS |
     SVGA_NEW_TEXTURE_BINDING |
     SVGA_NEW_NEED_SWTNL |
     SVGA_NEW_RAST |
+    SVGA_NEW_REDUCED_PRIMITIVE |
     SVGA_NEW_SAMPLER |
     SVGA_NEW_FRAME_BUFFER |
+    SVGA_NEW_DEPTH_STENCIL_ALPHA |
     SVGA_NEW_BLEND),
    emit_hw_fs
 };
index cac39d62fd1b55291898b73b734e074d72465a2d..429241e64e27d963406963b239e7ae30b01d79b8 100644 (file)
@@ -26,6 +26,7 @@
 #include "util/u_inlines.h"
 #include "pipe/p_state.h"
 #include "svga_context.h"
+#include "svga_shader.h"
 #include "svga_state.h"
 #include "svga_debug.h"
 #include "svga_hw_reg.h"
@@ -91,7 +92,7 @@ update_need_pipeline(struct svga_context *svga, unsigned dirty)
       unsigned generic_inputs =
          svga->curr.fs ? svga->curr.fs->generic_inputs : 0;
 
-      if (sprite_coord_gen &&
+      if (!svga_have_vgpu10(svga) && sprite_coord_gen &&
           (generic_inputs & ~sprite_coord_gen)) {
          /* The fragment shader is using some generic inputs that are
           * not being replaced by auto-generated point/sprite coords (and
index ebb98373e2b300c3c120a872da0a07e40fce88c6..d43894d71b186aa88e77dbed6b5cb37cf6206dd4 100644 (file)
  *
  **********************************************************/
 
+#include "pipe/p_defines.h"
+#include "util/u_bitmask.h"
 #include "util/u_format.h"
 #include "util/u_inlines.h"
 #include "util/u_memory.h"
-#include "pipe/p_defines.h"
 #include "util/u_math.h"
+#include "util/u_memory.h"
 
 #include "svga_context.h"
 #include "svga_screen.h"
 #include "svga_state.h"
 #include "svga_cmd.h"
+#include "svga_format.h"
+#include "svga_shader.h"
 
 
 struct rs_queue {
@@ -77,7 +81,7 @@ svga_queue_rs( struct rs_queue *q,
  * the "to" state.
  */
 static enum pipe_error
-emit_rss(struct svga_context *svga, unsigned dirty)
+emit_rss_vgpu9(struct svga_context *svga, unsigned dirty)
 {
    struct svga_screen *screen = svga_screen(svga->pipe.screen);
    struct rs_queue queue;
@@ -85,7 +89,7 @@ emit_rss(struct svga_context *svga, unsigned dirty)
 
    queue.rs_count = 0;
 
-   if (dirty & SVGA_NEW_BLEND) {
+   if (dirty & (SVGA_NEW_BLEND | SVGA_NEW_BLEND_COLOR)) {
       const struct svga_blend_state *curr = svga->curr.blend;
 
       EMIT_RS( svga, curr->rt[0].writemask, COLORWRITEENABLE, fail );
@@ -119,7 +123,7 @@ emit_rss(struct svga_context *svga, unsigned dirty)
       EMIT_RS( svga, color, BLENDCOLOR, fail );
    }
 
-   if (dirty & (SVGA_NEW_DEPTH_STENCIL | SVGA_NEW_RAST)) {
+   if (dirty & (SVGA_NEW_DEPTH_STENCIL_ALPHA | SVGA_NEW_RAST)) {
       const struct svga_depth_stencil_state *curr = svga->curr.depth; 
       const struct svga_rasterizer_state *rast = svga->curr.rast; 
 
@@ -300,6 +304,151 @@ fail:
    return PIPE_ERROR_OUT_OF_MEMORY;
 }
 
+/** Returns a non-culling rasterizer state object to be used with
+ *  point sprite.
+ */
+static struct svga_rasterizer_state *
+get_no_cull_rasterizer_state(struct svga_context *svga)
+{
+   const struct svga_rasterizer_state *r = svga->curr.rast;
+   unsigned int aa_point = r->templ.point_smooth;
+
+   if (!svga->rasterizer_no_cull[aa_point]) {
+      struct pipe_rasterizer_state rast;
+
+      memset(&rast, 0, sizeof(rast));
+      rast.flatshade = 1;
+      rast.front_ccw = 1;
+      rast.point_smooth = r->templ.point_smooth;
+
+      /* All rasterizer states have the same half_pixel_center,
+       * bottom_edge_rule and clip_halfz values since they are
+       * constant for a context. If we ever implement
+       * GL_ARB_clip_control, the clip_halfz field would have to be observed.
+       */
+      rast.half_pixel_center = r->templ.half_pixel_center;
+      rast.bottom_edge_rule = r->templ.bottom_edge_rule;
+      rast.clip_halfz = r->templ.clip_halfz;
+
+      svga->rasterizer_no_cull[aa_point] =
+               svga->pipe.create_rasterizer_state(&svga->pipe, &rast);
+   }
+   return svga->rasterizer_no_cull[aa_point];
+}
+
+static enum pipe_error
+emit_rss_vgpu10(struct svga_context *svga, unsigned dirty)
+{
+   enum pipe_error ret = PIPE_OK;
+
+   svga_hwtnl_flush_retry(svga);
+
+   if (dirty & (SVGA_NEW_BLEND | SVGA_NEW_BLEND_COLOR)) {
+      const struct svga_blend_state *curr;
+      float blend_factor[4];
+
+      if (svga_has_any_integer_cbufs(svga)) {
+         /* Blending is not supported in integer-valued render targets. */
+         curr = svga->noop_blend;
+         blend_factor[0] =
+         blend_factor[1] =
+         blend_factor[2] =
+         blend_factor[3] = 0;
+      }
+      else {
+         curr = svga->curr.blend;
+
+         if (curr->blend_color_alpha) {
+            blend_factor[0] =
+            blend_factor[1] =
+            blend_factor[2] =
+            blend_factor[3] = svga->curr.blend_color.color[3];
+         }
+         else {
+            blend_factor[0] = svga->curr.blend_color.color[0];
+            blend_factor[1] = svga->curr.blend_color.color[1];
+            blend_factor[2] = svga->curr.blend_color.color[2];
+            blend_factor[3] = svga->curr.blend_color.color[3];
+         }
+      }
+
+      /* Set/bind the blend state object */
+      if (svga->state.hw_draw.blend_id != curr->id ||
+          svga->state.hw_draw.blend_factor[0] != blend_factor[0] ||
+          svga->state.hw_draw.blend_factor[1] != blend_factor[1] ||
+          svga->state.hw_draw.blend_factor[2] != blend_factor[2] ||
+          svga->state.hw_draw.blend_factor[3] != blend_factor[3] ||
+          svga->state.hw_draw.blend_sample_mask != svga->curr.sample_mask) {
+         ret = SVGA3D_vgpu10_SetBlendState(svga->swc, curr->id,
+                                           blend_factor,
+                                           svga->curr.sample_mask);
+         if (ret != PIPE_OK)
+            return ret;
+
+         svga->state.hw_draw.blend_id = curr->id;
+         svga->state.hw_draw.blend_factor[0] = blend_factor[0];
+         svga->state.hw_draw.blend_factor[1] = blend_factor[1];
+         svga->state.hw_draw.blend_factor[2] = blend_factor[2];
+         svga->state.hw_draw.blend_factor[3] = blend_factor[3];
+         svga->state.hw_draw.blend_sample_mask = svga->curr.sample_mask;
+      }
+   }
+
+   if (dirty & (SVGA_NEW_DEPTH_STENCIL_ALPHA | SVGA_NEW_STENCIL_REF)) {
+      const struct svga_depth_stencil_state *curr = svga->curr.depth;
+      unsigned curr_ref = svga->curr.stencil_ref.ref_value[0];
+
+      if (curr->id != svga->state.hw_draw.depth_stencil_id ||
+          curr_ref != svga->state.hw_draw.stencil_ref) {
+         /* Set/bind the depth/stencil state object */
+         ret = SVGA3D_vgpu10_SetDepthStencilState(svga->swc, curr->id,
+                                                  curr_ref);
+         if (ret != PIPE_OK)
+            return ret;
+
+         svga->state.hw_draw.depth_stencil_id = curr->id;
+         svga->state.hw_draw.stencil_ref = curr_ref;
+      }
+   }
+
+   if (dirty & (SVGA_NEW_REDUCED_PRIMITIVE | SVGA_NEW_RAST)) {
+      const struct svga_rasterizer_state *rast;
+
+      if (svga->curr.reduced_prim == PIPE_PRIM_POINTS &&
+          svga->curr.gs && svga->curr.gs->wide_point) {
+
+         /* If we are drawing a point sprite, we will need to
+          * bind a non-culling rasterizer state object
+          */
+         rast = get_no_cull_rasterizer_state(svga);
+      }
+      else {
+         rast = svga->curr.rast;
+      }
+
+      if (svga->state.hw_draw.rasterizer_id != rast->id) {
+         /* Set/bind the rasterizer state object */
+         ret = SVGA3D_vgpu10_SetRasterizerState(svga->swc, rast->id);
+         if (ret != PIPE_OK)
+            return ret;
+         svga->state.hw_draw.rasterizer_id = rast->id;
+      }
+   }
+   return PIPE_OK;
+}
+
+
+static enum pipe_error
+emit_rss(struct svga_context *svga, unsigned dirty)
+{
+   if (svga_have_vgpu10(svga)) {
+      return emit_rss_vgpu10(svga, dirty);
+   }
+   else {
+      return emit_rss_vgpu9(svga, dirty);
+   }
+}
+
 
 struct svga_tracked_state svga_hw_rss = 
 {
@@ -307,11 +456,12 @@ struct svga_tracked_state svga_hw_rss =
 
    (SVGA_NEW_BLEND |
     SVGA_NEW_BLEND_COLOR |
-    SVGA_NEW_DEPTH_STENCIL |
+    SVGA_NEW_DEPTH_STENCIL_ALPHA |
     SVGA_NEW_STENCIL_REF |
     SVGA_NEW_RAST |
     SVGA_NEW_FRAME_BUFFER |
-    SVGA_NEW_NEED_PIPELINE),
+    SVGA_NEW_NEED_PIPELINE |
+    SVGA_NEW_REDUCED_PRIMITIVE),
 
    emit_rss
 };
index e350f540335a750563ded3247e9490c28272cc9f..1c6913e4a2666fb5b6531bea226413ec5a5e426b 100644 (file)
@@ -45,7 +45,7 @@
 
 
 /** Get resource handle for a texture or buffer */
-static INLINE struct svga_winsys_surface *
+static inline struct svga_winsys_surface *
 svga_resource_handle(struct pipe_resource *res)
 {
    if (res->target == PIPE_BUFFER) {
@@ -111,7 +111,7 @@ svga_validate_pipe_sampler_view(struct svga_context *svga,
 
       if (texture->target == PIPE_BUFFER) {
          viewDesc.buffer.firstElement = sv->base.u.buf.first_element;
-         viewDesc.buffer.numElements = (sv->base.u.buf.last_element - 
+         viewDesc.buffer.numElements = (sv->base.u.buf.last_element -
                                         sv->base.u.buf.first_element + 1);
       }
       else {
@@ -122,13 +122,13 @@ svga_validate_pipe_sampler_view(struct svga_context *svga,
       }
 
       /* arraySize in viewDesc specifies the number of array slices in a
-       * texture array. For 3D texture, last_layer in 
+       * 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 || 
+      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);
 
index 41334bd7cb9f1871341ed8704fb7af85c6f52ab1..a13980d0e13303ee9723f8f0d9a671615a5eb3c5 100644 (file)
 #include "svga_sampler_view.h"
 #include "svga_winsys.h"
 #include "svga_context.h"
+#include "svga_shader.h"
 #include "svga_state.h"
 #include "svga_cmd.h"
 
 
+/**
+ * Called when tearing down a context to free resources and samplers.
+ */
 void svga_cleanup_tss_binding(struct svga_context *svga)
 {
+   const unsigned shader = PIPE_SHADER_FRAGMENT;
    unsigned i;
-   unsigned count = MAX2( svga->curr.num_sampler_views,
-                          svga->state.hw_draw.num_views );
 
-   for (i = 0; i < count; i++) {
+   for (i = 0; i < Elements(svga->state.hw_draw.views); i++) {
       struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
-
-      svga_sampler_view_reference(&view->v, NULL);
-      pipe_sampler_view_release(&svga->pipe, &svga->curr.sampler_views[i]);
-      pipe_resource_reference( &view->texture, NULL );
-
-      view->dirty = 1;
+      if (view) {
+         svga_sampler_view_reference(&view->v, NULL);
+         pipe_sampler_view_release(&svga->pipe,
+                                   &svga->curr.sampler_views[shader][i]);
+         pipe_resource_reference(&view->texture, NULL);
+         view->dirty = TRUE;
+      }
    }
 }
 
@@ -63,73 +67,113 @@ struct bind_queue {
 };
 
 
+/**
+ * Update the texture binding for one texture unit.
+ */
+static void
+emit_tex_binding_unit(struct svga_context *svga,
+                      unsigned unit,
+                      const struct svga_sampler_state *s,
+                      const struct pipe_sampler_view *sv,
+                      struct svga_hw_view_state *view,
+                      boolean reemit,
+                      struct bind_queue *queue)
+{
+   struct pipe_resource *texture = NULL;
+   unsigned last_level, min_lod, max_lod;
+
+   /* get min max lod */
+   if (sv && s) {
+      if (s->mipfilter == SVGA3D_TEX_FILTER_NONE) {
+         /* just use the base level image */
+         min_lod = max_lod = sv->u.tex.first_level;
+      }
+      else {
+         last_level = MIN2(sv->u.tex.last_level, sv->texture->last_level);
+         min_lod = MAX2(0, (s->view_min_lod + sv->u.tex.first_level));
+         min_lod = MIN2(min_lod, last_level);
+         max_lod = MIN2(s->view_max_lod + sv->u.tex.first_level, last_level);
+      }
+      texture = sv->texture;
+   }
+   else {
+      min_lod = 0;
+      max_lod = 0;
+   }
+
+   if (view->texture != texture ||
+       view->min_lod != min_lod ||
+       view->max_lod != max_lod) {
+
+      svga_sampler_view_reference(&view->v, NULL);
+      pipe_resource_reference( &view->texture, texture );
+
+      view->dirty = TRUE;
+      view->min_lod = min_lod;
+      view->max_lod = max_lod;
+
+      if (texture) {
+         view->v = svga_get_tex_sampler_view(&svga->pipe,
+                                             texture,
+                                             min_lod,
+                                             max_lod);
+      }
+   }
+
+   /*
+    * We need to reemit non-null texture bindings, even when they are not
+    * dirty, to ensure that the resources are paged in.
+    */
+   if (view->dirty || (reemit && view->v)) {
+      queue->bind[queue->bind_count].unit = unit;
+      queue->bind[queue->bind_count].view = view;
+      queue->bind_count++;
+   }
+
+   if (!view->dirty && view->v) {
+      svga_validate_sampler_view(svga, view->v);
+   }
+}
+
+
 static enum pipe_error
 update_tss_binding(struct svga_context *svga, 
                    unsigned dirty )
 {
-   boolean reemit = svga->rebind.texture_samplers;
+   const unsigned shader = PIPE_SHADER_FRAGMENT;
+   boolean reemit = svga->rebind.flags.texture_samplers;
    unsigned i;
-   unsigned count = MAX2( svga->curr.num_sampler_views,
+   unsigned count = MAX2( svga->curr.num_sampler_views[shader],
                           svga->state.hw_draw.num_views );
-   unsigned min_lod;
-   unsigned max_lod;
 
    struct bind_queue queue;
 
+   if (svga_have_vgpu10(svga))
+      return PIPE_OK;
+
    queue.bind_count = 0;
    
    for (i = 0; i < count; i++) {
-      const struct svga_sampler_state *s = svga->curr.sampler[i];
-      struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
-      struct pipe_resource *texture = NULL;
-      struct pipe_sampler_view *sv = svga->curr.sampler_views[i];
-
-      /* get min max lod */
-      if (sv && s) {
-         min_lod = MAX2(0, (s->view_min_lod + sv->u.tex.first_level));
-         max_lod = MIN2(s->view_max_lod + sv->u.tex.first_level,
-                        sv->texture->last_level);
-         texture = sv->texture;
-      } else {
-         min_lod = 0;
-         max_lod = 0;
-      }
-
-      if (view->texture != texture ||
-          view->min_lod != min_lod ||
-          view->max_lod != max_lod) {
-
-         svga_sampler_view_reference(&view->v, NULL);
-         pipe_resource_reference( &view->texture, texture );
-
-         view->dirty = TRUE;
-         view->min_lod = min_lod;
-         view->max_lod = max_lod;
-
-         if (texture)
-            view->v = svga_get_tex_sampler_view(&svga->pipe, 
-                                                texture, 
-                                                min_lod,
-                                                max_lod);
-      }
-
-      /*
-       * We need to reemit non-null texture bindings, even when they are not
-       * dirty, to ensure that the resources are paged in.
-       */
-
-      if (view->dirty ||
-          (reemit && view->v)) {
-         queue.bind[queue.bind_count].unit = i;
-         queue.bind[queue.bind_count].view = view;
-         queue.bind_count++;
-      } 
-      if (!view->dirty && view->v) {
-         svga_validate_sampler_view(svga, view->v);
-      }
+      emit_tex_binding_unit(svga, i,
+                            svga->curr.sampler[shader][i],
+                            svga->curr.sampler_views[shader][i],
+                            &svga->state.hw_draw.views[i],
+                            reemit,
+                            &queue);
    }
 
-   svga->state.hw_draw.num_views = svga->curr.num_sampler_views;
+   svga->state.hw_draw.num_views = svga->curr.num_sampler_views[shader];
+
+   /* Polygon stipple */
+   if (svga->curr.rast->templ.poly_stipple_enable) {
+      const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit;
+      emit_tex_binding_unit(svga, unit,
+                            svga->polygon_stipple.sampler,
+                            &svga->polygon_stipple.sampler_view->base,
+                            &svga->state.hw_draw.views[unit],
+                            reemit,
+                            &queue);
+   }
 
    if (queue.bind_count) {
       SVGA3dTextureState *ts;
@@ -163,7 +207,7 @@ update_tss_binding(struct svga_context *svga,
       SVGA_FIFOCommitAll( svga->swc );
    }
 
-   svga->rebind.texture_samplers = FALSE;
+   svga->rebind.flags.texture_samplers = FALSE;
 
    return PIPE_OK;
 
@@ -187,7 +231,8 @@ svga_reemit_tss_bindings(struct svga_context *svga)
    enum pipe_error ret;
    struct bind_queue queue;
 
-   assert(svga->rebind.texture_samplers);
+   assert(!svga_have_vgpu10(svga));
+   assert(svga->rebind.flags.texture_samplers);
 
    queue.bind_count = 0;
 
@@ -201,6 +246,18 @@ svga_reemit_tss_bindings(struct svga_context *svga)
       }
    }
 
+   /* Polygon stipple */
+   if (svga->curr.rast->templ.poly_stipple_enable) {
+      const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit;
+      struct svga_hw_view_state *view = &svga->state.hw_draw.views[unit];
+
+      if (view->v) {
+         queue.bind[queue.bind_count].unit = unit;
+         queue.bind[queue.bind_count].view = view;
+         queue.bind_count++;
+      }
+   }
+
    if (queue.bind_count) {
       SVGA3dTextureState *ts;
 
@@ -229,7 +286,7 @@ svga_reemit_tss_bindings(struct svga_context *svga)
       SVGA_FIFOCommitAll(svga->swc);
    }
 
-   svga->rebind.texture_samplers = FALSE;
+   svga->rebind.flags.texture_samplers = FALSE;
 
    return PIPE_OK;
 }
@@ -238,6 +295,7 @@ svga_reemit_tss_bindings(struct svga_context *svga)
 struct svga_tracked_state svga_hw_tss_binding = {
    "texture binding emit",
    SVGA_NEW_TEXTURE_BINDING |
+   SVGA_NEW_STIPPLE |
    SVGA_NEW_SAMPLER,
    update_tss_binding
 };
@@ -252,78 +310,98 @@ struct ts_queue {
 };
 
 
-#define EMIT_TS(svga, unit, val, token, fail)                           \
+static inline void
+svga_queue_tss( struct ts_queue *q,
+                unsigned unit,
+                unsigned tss,
+                unsigned value )
+{
+   assert(q->ts_count < sizeof(q->ts)/sizeof(q->ts[0]));
+   q->ts[q->ts_count].stage = unit;
+   q->ts[q->ts_count].name = tss;
+   q->ts[q->ts_count].value = value;
+   q->ts_count++;
+}
+
+
+#define EMIT_TS(svga, unit, val, token)                                 \
 do {                                                                    \
    assert(unit < Elements(svga->state.hw_draw.ts));                     \
    assert(SVGA3D_TS_##token < Elements(svga->state.hw_draw.ts[unit]));  \
    if (svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] != val) {        \
-      svga_queue_tss( &queue, unit, SVGA3D_TS_##token, val );           \
+      svga_queue_tss( queue, unit, SVGA3D_TS_##token, val );            \
       svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] = val;            \
    }                                                                    \
 } while (0)
 
-#define EMIT_TS_FLOAT(svga, unit, fvalue, token, fail)                  \
+#define EMIT_TS_FLOAT(svga, unit, fvalue, token)                        \
 do {                                                                    \
    unsigned val = fui(fvalue);                                          \
    assert(unit < Elements(svga->state.hw_draw.ts));                     \
    assert(SVGA3D_TS_##token < Elements(svga->state.hw_draw.ts[unit]));  \
    if (svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] != val) {        \
-      svga_queue_tss( &queue, unit, SVGA3D_TS_##token, val );           \
+      svga_queue_tss( queue, unit, SVGA3D_TS_##token, val );            \
       svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] = val;            \
    }                                                                    \
 } while (0)
 
 
-static inline void 
-svga_queue_tss( struct ts_queue *q,
-                unsigned unit,
-                unsigned tss,
-                unsigned value )
+/**
+ * Emit texture sampler state (tss) for one texture unit.
+ */
+static void
+emit_tss_unit(struct svga_context *svga, unsigned unit,
+              const struct svga_sampler_state *state,
+              struct ts_queue *queue)
 {
-   assert(q->ts_count < sizeof(q->ts)/sizeof(q->ts[0]));
-   q->ts[q->ts_count].stage = unit;
-   q->ts[q->ts_count].name = tss;
-   q->ts[q->ts_count].value = value;
-   q->ts_count++;
+   EMIT_TS(svga, unit, state->mipfilter, MIPFILTER);
+   EMIT_TS(svga, unit, state->min_lod, TEXTURE_MIPMAP_LEVEL);
+   EMIT_TS(svga, unit, state->magfilter, MAGFILTER);
+   EMIT_TS(svga, unit, state->minfilter, MINFILTER);
+   EMIT_TS(svga, unit, state->aniso_level, TEXTURE_ANISOTROPIC_LEVEL);
+   EMIT_TS_FLOAT(svga, unit, state->lod_bias, TEXTURE_LOD_BIAS);
+   EMIT_TS(svga, unit, state->addressu, ADDRESSU);
+   EMIT_TS(svga, unit, state->addressw, ADDRESSW);
+   EMIT_TS(svga, unit, state->bordercolor, BORDERCOLOR);
+   // TEXCOORDINDEX -- hopefully not needed
+
+   if (svga->curr.tex_flags.flag_1d & (1 << unit))
+      EMIT_TS(svga, unit, SVGA3D_TEX_ADDRESS_WRAP, ADDRESSV);
+   else
+      EMIT_TS(svga, unit, state->addressv, ADDRESSV);
+
+   if (svga->curr.tex_flags.flag_srgb & (1 << unit))
+      EMIT_TS_FLOAT(svga, unit, 2.2f, GAMMA);
+   else
+      EMIT_TS_FLOAT(svga, unit, 1.0f, GAMMA);
 }
 
-
 static enum pipe_error
 update_tss(struct svga_context *svga, 
            unsigned dirty )
 {
+   const unsigned shader = PIPE_SHADER_FRAGMENT;
    unsigned i;
    struct ts_queue queue;
 
-   queue.ts_count = 0;
-   for (i = 0; i < svga->curr.num_samplers; i++) {
-      if (svga->curr.sampler[i]) {
-         const struct svga_sampler_state *curr = svga->curr.sampler[i];
-
-         EMIT_TS(svga, i, curr->mipfilter, MIPFILTER, fail);
-         EMIT_TS(svga, i, curr->min_lod, TEXTURE_MIPMAP_LEVEL, fail);
-         EMIT_TS(svga, i, curr->magfilter, MAGFILTER, fail);
-         EMIT_TS(svga, i, curr->minfilter, MINFILTER, fail);
-         EMIT_TS(svga, i, curr->aniso_level, TEXTURE_ANISOTROPIC_LEVEL, fail);
-         EMIT_TS_FLOAT(svga, i, curr->lod_bias, TEXTURE_LOD_BIAS, fail);
-         EMIT_TS(svga, i, curr->addressu, ADDRESSU, fail);
-         EMIT_TS(svga, i, curr->addressw, ADDRESSW, fail);
-         EMIT_TS(svga, i, curr->bordercolor, BORDERCOLOR, fail);
-         // TEXCOORDINDEX -- hopefully not needed
-
-         if (svga->curr.tex_flags.flag_1d & (1 << i)) {
-            EMIT_TS(svga, i, SVGA3D_TEX_ADDRESS_WRAP, ADDRESSV, fail);
-         }
-         else
-            EMIT_TS(svga, i, curr->addressv, ADDRESSV, fail);
-
-         if (svga->curr.tex_flags.flag_srgb & (1 << i))
-            EMIT_TS_FLOAT(svga, i, 2.2f, GAMMA, fail);
-         else
-            EMIT_TS_FLOAT(svga, i, 1.0f, GAMMA, fail);
+   if (svga_have_vgpu10(svga))
+      return PIPE_OK;
 
+   queue.ts_count = 0;
+   for (i = 0; i < svga->curr.num_samplers[shader]; i++) {
+      if (svga->curr.sampler[shader][i]) {
+         const struct svga_sampler_state *curr = svga->curr.sampler[shader][i];
+         emit_tss_unit(svga, i, curr, &queue);
       }
    }
+
+   /* polygon stipple sampler */
+   if (svga->curr.rast->templ.poly_stipple_enable) {
+      emit_tss_unit(svga,
+                    svga->state.hw_draw.fs->pstipple_sampler_unit,
+                    svga->polygon_stipple.sampler,
+                    &queue);
+   }
  
    if (queue.ts_count) {
       SVGA3dTextureState *ts;
@@ -357,6 +435,7 @@ fail:
 struct svga_tracked_state svga_hw_tss = {
    "texture state emit",
    (SVGA_NEW_SAMPLER |
+    SVGA_NEW_STIPPLE |
     SVGA_NEW_TEXTURE_FLAGS),
    update_tss
 };
index a33eda3836605ed6b99b911d31d176df6b3edad2..e1b6a1c2a44d0bc54d57e9fc15a62869e33f730d 100644 (file)
@@ -33,6 +33,7 @@
 #include "svga_draw.h"
 #include "svga_tgsi.h"
 #include "svga_screen.h"
+#include "svga_shader.h"
 #include "svga_resource_buffer.h"
 #include "svga_hw_reg.h"
 
@@ -42,16 +43,14 @@ static enum pipe_error
 emit_hw_vs_vdecl(struct svga_context *svga, unsigned dirty)
 {
    const struct pipe_vertex_element *ve = svga->curr.velems->velem;
+   SVGA3dVertexDecl decls[SVGA3D_INPUTREG_MAX];
+   unsigned buffer_indexes[SVGA3D_INPUTREG_MAX];
    unsigned i;
    unsigned neg_bias = 0;
 
    assert(svga->curr.velems->count >=
           svga->curr.vs->base.info.file_count[TGSI_FILE_INPUT]);
 
-   /* specify number of vertex element declarations to come */
-   svga_hwtnl_reset_vdecl( svga->hwtnl,
-                           svga->curr.velems->count );
-
    /**
     * We can't set the VDECL offset to something negative, so we
     * must calculate a common negative additional index bias, and modify
@@ -70,15 +69,16 @@ emit_hw_vs_vdecl(struct svga_context *svga, unsigned dirty)
    for (i = 0; i < svga->curr.velems->count; i++) {
       const struct pipe_vertex_buffer *vb =
          &svga->curr.vb[ve[i].vertex_buffer_index];
-      const struct svga_buffer *buffer;
+      struct svga_buffer *buffer;
       unsigned int offset = vb->buffer_offset + ve[i].src_offset;
+      unsigned tmp_neg_bias = 0;
 
       if (!vb->buffer)
          continue;
 
       buffer = svga_buffer(vb->buffer);
       if (buffer->uploaded.start > offset) {
-         unsigned tmp_neg_bias = buffer->uploaded.start - offset;
+         tmp_neg_bias = buffer->uploaded.start - offset;
          if (vb->stride)
             tmp_neg_bias = (tmp_neg_bias + vb->stride - 1) / vb->stride;
          neg_bias = MAX2(neg_bias, tmp_neg_bias);
@@ -89,8 +89,7 @@ emit_hw_vs_vdecl(struct svga_context *svga, unsigned dirty)
       const struct pipe_vertex_buffer *vb =
          &svga->curr.vb[ve[i].vertex_buffer_index];
       unsigned usage, index;
-      const struct svga_buffer *buffer;
-      SVGA3dVertexDecl decl;
+      struct svga_buffer *buffer;
 
       if (!vb->buffer)
          continue;
@@ -100,29 +99,37 @@ emit_hw_vs_vdecl(struct svga_context *svga, unsigned dirty)
 
       /* SVGA_NEW_VELEMENT
        */
-      decl.identity.type = svga->curr.velems->decl_type[i];
-      decl.identity.method = SVGA3D_DECLMETHOD_DEFAULT;
-      decl.identity.usage = usage;
-      decl.identity.usageIndex = index;
-      decl.array.stride = vb->stride;
+      decls[i].identity.type = svga->curr.velems->decl_type[i];
+      decls[i].identity.method = SVGA3D_DECLMETHOD_DEFAULT;
+      decls[i].identity.usage = usage;
+      decls[i].identity.usageIndex = index;
+      decls[i].array.stride = vb->stride;
 
       /* Compensate for partially uploaded vbo, and
        * for the negative index bias.
        */
-      decl.array.offset = (vb->buffer_offset
+      decls[i].array.offset = (vb->buffer_offset
                            + ve[i].src_offset
                           + neg_bias * vb->stride
                           - buffer->uploaded.start);
 
-      assert(decl.array.offset >= 0);
+      assert(decls[i].array.offset >= 0);
+
+      buffer_indexes[i] = ve[i].vertex_buffer_index;
 
-      svga_hwtnl_vdecl( svga->hwtnl,
-                        i,
-                        &decl,
-                        buffer->uploaded.buffer ? buffer->uploaded.buffer :
-                        vb->buffer );
+      assert(!buffer->uploaded.buffer);
    }
 
+   svga_hwtnl_vertex_decls(svga->hwtnl,
+                           svga->curr.velems->count,
+                           decls,
+                           buffer_indexes,
+                           svga->curr.velems->id);
+
+   svga_hwtnl_vertex_buffers(svga->hwtnl,
+                             svga->curr.num_vertex_buffers,
+                             svga->curr.vb);
+
    svga_hwtnl_set_index_bias( svga->hwtnl, -(int) neg_bias );
    return PIPE_OK;
 }
index c2a0f1ee6b15d2fc754ae109a07fc45f5d06d896..45dcb5d0f7631bfad0365a37d5fa868edbe913d5 100644 (file)
@@ -25,7 +25,6 @@
 
 #include "util/u_inlines.h"
 #include "pipe/p_defines.h"
-#include "util/u_format.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 #include "util/u_bitmask.h"
 #include "svga_hw_reg.h"
 
 
-static inline int
-compare_vs_keys(const struct svga_vs_compile_key *a,
-                const struct svga_vs_compile_key *b)
-{
-   unsigned keysize = svga_vs_key_size( a );
-   return memcmp( a, b, keysize );
-}
-
-
-/** Search for a vertex shader variant */
-static struct svga_shader_variant *
-search_vs_key(const struct svga_vertex_shader *vs,
-              const struct svga_vs_compile_key *key)
-{
-   struct svga_shader_variant *variant = vs->base.variants;
-
-   assert(key);
-
-   for ( ; variant; variant = variant->next) {
-      if (compare_vs_keys( key, &variant->key.vkey ) == 0)
-         return variant;
-   }
-   
-   return NULL;
-}
-
-
 /**
  * If we fail to compile a vertex shader we'll use a dummy/fallback shader
  * that simply emits a (0,0,0,1) vertex position.
@@ -99,13 +71,29 @@ get_dummy_vertex_shader(void)
 }
 
 
+static struct svga_shader_variant *
+translate_vertex_program(struct svga_context *svga,
+                         const struct svga_vertex_shader *vs,
+                         const struct svga_compile_key *key)
+{
+   if (svga_have_vgpu10(svga)) {
+      return svga_tgsi_vgpu10_translate(svga, &vs->base, key,
+                                        PIPE_SHADER_VERTEX);
+   }
+   else {
+      return svga_tgsi_vgpu9_translate(&vs->base, key, PIPE_SHADER_VERTEX);
+   }
+}
+
+
 /**
  * Replace the given shader's instruction with a simple / dummy shader.
  * We use this when normal shader translation fails.
  */
 static struct svga_shader_variant *
-get_compiled_dummy_vertex_shader(struct svga_vertex_shader *vs,
-                                 const struct svga_vs_compile_key *key)
+get_compiled_dummy_vertex_shader(struct svga_context *svga,
+                                 struct svga_vertex_shader *vs,
+                                 const struct svga_compile_key *key)
 {
    const struct tgsi_token *dummy = get_dummy_vertex_shader();
    struct svga_shader_variant *variant;
@@ -117,7 +105,7 @@ get_compiled_dummy_vertex_shader(struct svga_vertex_shader *vs,
    FREE((void *) vs->base.tokens);
    vs->base.tokens = dummy;
 
-   variant = svga_translate_vertex_program(vs, key);
+   variant = translate_vertex_program(svga, vs, key);
    return variant;
 }
 
@@ -128,16 +116,17 @@ get_compiled_dummy_vertex_shader(struct svga_vertex_shader *vs,
 static enum pipe_error
 compile_vs(struct svga_context *svga,
            struct svga_vertex_shader *vs,
-           const struct svga_vs_compile_key *key,
+           const struct svga_compile_key *key,
            struct svga_shader_variant **out_variant)
 {
    struct svga_shader_variant *variant;
    enum pipe_error ret = PIPE_ERROR;
 
-   variant = svga_translate_vertex_program( vs, key );
+   variant = translate_vertex_program(svga, vs, key);
    if (variant == NULL) {
-      /* some problem during translation, try the dummy shader */
-      variant = get_compiled_dummy_vertex_shader(vs, key);
+      debug_printf("Failed to compile vertex shader,"
+                   " using dummy shader instead.\n");
+      variant = get_compiled_dummy_vertex_shader(svga, vs, key);
       if (!variant) {
          ret = PIPE_ERROR;
          goto fail;
@@ -146,11 +135,11 @@ compile_vs(struct svga_context *svga,
 
    if (svga_shader_too_large(svga, variant)) {
       /* too big, use dummy shader */
-      debug_printf("Shader too large (%lu bytes),"
+      debug_printf("Shader too large (%u bytes),"
                    " using dummy shader instead.\n",
-                   (unsigned long ) variant->nr_tokens
-                   * sizeof(variant->tokens[0]));
-      variant = get_compiled_dummy_vertex_shader(vs, key);
+                   (unsigned) (variant->nr_tokens
+                               * sizeof(variant->tokens[0])));
+      variant = get_compiled_dummy_vertex_shader(svga, vs, key);
       if (!variant) {
          ret = PIPE_ERROR;
          goto fail;
@@ -163,10 +152,6 @@ compile_vs(struct svga_context *svga,
 
    *out_variant = variant;
 
-   /* insert variants at head of linked list */
-   variant->next = vs->base.variants;
-   vs->base.variants = variant;
-
    return PIPE_OK;
 
 fail:
@@ -179,18 +164,44 @@ fail:
 /* SVGA_NEW_PRESCALE, SVGA_NEW_RAST, SVGA_NEW_FS
  */
 static void
-make_vs_key(struct svga_context *svga, struct svga_vs_compile_key *key)
+make_vs_key(struct svga_context *svga, struct svga_compile_key *key)
 {
+   const unsigned shader = PIPE_SHADER_VERTEX;
+
    memset(key, 0, sizeof *key);
-   key->need_prescale = svga->state.hw_clear.prescale.enabled;
-   key->allow_psiz = svga->curr.rast->templ.point_size_per_vertex;
+
+   if (svga->state.sw.need_swtnl && svga_have_vgpu10(svga)) {
+      /* Set both of these flags, to match compile_passthrough_vs() */
+      key->vs.passthrough = 1;
+      key->vs.undo_viewport = 1;
+      return;
+   }
+
+   key->vs.need_prescale = svga->state.hw_clear.prescale.enabled &&
+                           (svga->curr.gs == NULL);
+   key->vs.allow_psiz = svga->curr.rast->templ.point_size_per_vertex;
 
    /* SVGA_NEW_FS */
-   key->fs_generic_inputs = svga->curr.fs->generic_inputs;
+   key->vs.fs_generic_inputs = svga->curr.fs->generic_inputs;
+
+   svga_remap_generics(key->vs.fs_generic_inputs, key->generic_remap_table);
 
    /* SVGA_NEW_VELEMENT */
-   key->adjust_attrib_range = svga->curr.velems->adjust_attrib_range;
-   key->adjust_attrib_w_1 = svga->curr.velems->adjust_attrib_w_1;
+   key->vs.adjust_attrib_range = svga->curr.velems->adjust_attrib_range;
+   key->vs.adjust_attrib_w_1 = svga->curr.velems->adjust_attrib_w_1;
+   key->vs.attrib_is_pure_int = svga->curr.velems->attrib_is_pure_int;
+   key->vs.adjust_attrib_itof = svga->curr.velems->adjust_attrib_itof;
+   key->vs.adjust_attrib_utof = svga->curr.velems->adjust_attrib_utof;
+   key->vs.attrib_is_bgra = svga->curr.velems->attrib_is_bgra;
+   key->vs.attrib_puint_to_snorm = svga->curr.velems->attrib_puint_to_snorm;
+   key->vs.attrib_puint_to_uscaled = svga->curr.velems->attrib_puint_to_uscaled;
+   key->vs.attrib_puint_to_sscaled = svga->curr.velems->attrib_puint_to_sscaled;
+
+   /* SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER */
+   svga_init_shader_key_common(svga, shader, key);
+
+   /* SVGA_NEW_RAST */
+   key->clip_plane_enable = svga->curr.rast->templ.clip_plane_enable;
 }
 
 
@@ -201,63 +212,196 @@ enum pipe_error
 svga_reemit_vs_bindings(struct svga_context *svga)
 {
    enum pipe_error ret;
-   struct svga_winsys_gb_shader *gbshader =
-      svga->state.hw_draw.vs ? svga->state.hw_draw.vs->gb_shader : NULL;
+   struct svga_winsys_gb_shader *gbshader = NULL;
+   SVGA3dShaderId shaderId = SVGA3D_INVALID_ID;
 
-   assert(svga->rebind.vs);
+   assert(svga->rebind.flags.vs);
    assert(svga_have_gb_objects(svga));
 
-   ret = SVGA3D_SetGBShader(svga->swc, SVGA3D_SHADERTYPE_VS, gbshader);
+   if (svga->state.hw_draw.vs) {
+      gbshader = svga->state.hw_draw.vs->gb_shader;
+      shaderId = svga->state.hw_draw.vs->id;
+   }
+
+   if (!svga_need_to_rebind_resources(svga)) {
+      ret =  svga->swc->resource_rebind(svga->swc, NULL, gbshader,
+                                        SVGA_RELOC_READ);
+      goto out;
+   }
+
+   if (svga_have_vgpu10(svga))
+      ret = SVGA3D_vgpu10_SetShader(svga->swc, SVGA3D_SHADERTYPE_VS,
+                                    gbshader, shaderId);
+   else
+      ret = SVGA3D_SetGBShader(svga->swc, SVGA3D_SHADERTYPE_VS, gbshader);
+
+ out:
    if (ret != PIPE_OK)
       return ret;
 
-   svga->rebind.vs = FALSE;
+   svga->rebind.flags.vs = FALSE;
    return PIPE_OK;
 }
 
 
+/**
+ * The current vertex shader is already executed by the 'draw'
+ * module, so we just need to generate a simple vertex shader
+ * to pass through all those VS outputs that will
+ * be consumed by the fragment shader.
+ * Used when we employ the 'draw' module.
+ */
 static enum pipe_error
-emit_hw_vs(struct svga_context *svga, unsigned dirty)
+compile_passthrough_vs(struct svga_context *svga,
+                       struct svga_vertex_shader *vs,
+                       struct svga_fragment_shader *fs,
+                       struct svga_shader_variant **out_variant)
 {
    struct svga_shader_variant *variant = NULL;
+   unsigned num_inputs;
+   unsigned i;
+   unsigned num_elements;
+   struct svga_vertex_shader new_vs;
+   struct ureg_src src[PIPE_MAX_SHADER_INPUTS];
+   struct ureg_dst dst[PIPE_MAX_SHADER_OUTPUTS];
+   struct ureg_program *ureg;
+   unsigned num_tokens;
+   struct svga_compile_key key;
+   enum pipe_error ret;
+
+   assert(svga_have_vgpu10(svga));
+   assert(fs);
+
+   num_inputs = fs->base.info.num_inputs;
+
+   ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
+   if (!ureg)
+      return PIPE_ERROR_OUT_OF_MEMORY;
+
+   /* draw will always add position */
+   dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
+   src[0] = ureg_DECL_vs_input(ureg, 0);
+   num_elements = 1;
+
+   /**
+    * swtnl backend redefines the input layout based on the
+    * fragment shader's inputs. So we only need to passthrough
+    * those inputs that will be consumed by the fragment shader.
+    * Note: DX10 requires the number of vertex elements
+    * specified in the input layout to be no less than the
+    * number of inputs to the vertex shader.
+    */
+   for (i = 0; i < num_inputs; i++) {
+      switch (fs->base.info.input_semantic_name[i]) {
+      case TGSI_SEMANTIC_COLOR:
+      case TGSI_SEMANTIC_GENERIC:
+      case TGSI_SEMANTIC_FOG:
+         dst[num_elements] = ureg_DECL_output(ureg,
+                                fs->base.info.input_semantic_name[i],
+                                fs->base.info.input_semantic_index[i]);
+         src[num_elements] = ureg_DECL_vs_input(ureg, num_elements);
+         num_elements++;
+         break;
+      default:
+         break;
+      }
+   }
+
+   for (i = 0; i < num_elements; i++) {
+      ureg_MOV(ureg, dst[i], src[i]);
+   }
+
+   ureg_END(ureg);
+
+   memset(&new_vs, 0, sizeof(new_vs));
+   new_vs.base.tokens = ureg_get_tokens(ureg, &num_tokens);
+   tgsi_scan_shader(new_vs.base.tokens, &new_vs.base.info);
+
+   memset(&key, 0, sizeof(key));
+   key.vs.undo_viewport = 1;
+
+   ret = compile_vs(svga, &new_vs, &key, &variant);
+   if (ret != PIPE_OK)
+      return ret;
+
+   ureg_free_tokens(new_vs.base.tokens);
+   ureg_destroy(ureg);
+
+   /* Overwrite the variant key to indicate it's a pass-through VS */
+   memset(&variant->key, 0, sizeof(variant->key));
+   variant->key.vs.passthrough = 1;
+   variant->key.vs.undo_viewport = 1;
+
+   *out_variant = variant;
+
+   return PIPE_OK;
+}
+
+
+static enum pipe_error
+emit_hw_vs(struct svga_context *svga, unsigned dirty)
+{
+   struct svga_shader_variant *variant;
+   struct svga_vertex_shader *vs = svga->curr.vs;
+   struct svga_fragment_shader *fs = svga->curr.fs;
    enum pipe_error ret = PIPE_OK;
+   struct svga_compile_key key;
+
+   /* If there is an active geometry shader, and it has stream output
+    * defined, then we will skip the stream output from the vertex shader
+    */
+   if (!svga_have_gs_streamout(svga)) {
+      /* No GS stream out */
+      if (svga_have_vs_streamout(svga)) {
+         /* Set VS stream out */
+         svga_set_stream_output(svga, vs->base.stream_output);
+      }
+      else {
+         /* turn off stream out */
+         svga_set_stream_output(svga, NULL);
+      }
+   }
 
    /* SVGA_NEW_NEED_SWTNL */
-   if (!svga->state.sw.need_swtnl) {
-      struct svga_vertex_shader *vs = svga->curr.vs;
-      struct svga_vs_compile_key key;
+   if (svga->state.sw.need_swtnl && !svga_have_vgpu10(svga)) {
+      /* No vertex shader is needed */
+      variant = NULL;
+   }
+   else {
+      make_vs_key(svga, &key);
 
-      make_vs_key( svga, &key );
+      /* See if we already have a VS variant that matches the key */
+      variant = svga_search_shader_key(&vs->base, &key);
 
-      variant = search_vs_key( vs, &key );
       if (!variant) {
-         ret = compile_vs( svga, vs, &key, &variant );
+         /* Create VS variant now */
+         if (key.vs.passthrough) {
+            ret = compile_passthrough_vs(svga, vs, fs, &variant);
+         }
+         else {
+            ret = compile_vs(svga, vs, &key, &variant);
+         }
          if (ret != PIPE_OK)
             return ret;
-      }
 
-      assert(variant);
+         /* insert the new variant at head of linked list */
+         assert(variant);
+         variant->next = vs->base.variants;
+         vs->base.variants = variant;
+      }
    }
 
    if (variant != svga->state.hw_draw.vs) {
-      if (svga_have_gb_objects(svga)) {
-         struct svga_winsys_gb_shader *gbshader =
-            variant ? variant->gb_shader : NULL;
-         ret = SVGA3D_SetGBShader(svga->swc, SVGA3D_SHADERTYPE_VS, gbshader);
-         if (ret != PIPE_OK)
-            return ret;
-
-         svga->rebind.vs = FALSE;
-      }
-      else {
-         unsigned id = variant ? variant->id : SVGA_ID_INVALID;
-         ret = SVGA3D_SetShader(svga->swc, SVGA3D_SHADERTYPE_VS, id);
+      /* Bind the new variant */
+      if (variant) {
+         ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_VS, variant);
          if (ret != PIPE_OK)
             return ret;
+         svga->rebind.flags.vs = FALSE;
       }
 
       svga->dirty |= SVGA_NEW_VS_VARIANT;
-      svga->state.hw_draw.vs = variant;      
+      svga->state.hw_draw.vs = variant;
    }
 
    return PIPE_OK;
@@ -268,6 +412,9 @@ struct svga_tracked_state svga_hw_vs =
    "vertex shader (hwtnl)",
    (SVGA_NEW_VS |
     SVGA_NEW_FS |
+    SVGA_NEW_TEXTURE_BINDING |
+    SVGA_NEW_SAMPLER |
+    SVGA_NEW_RAST |
     SVGA_NEW_PRESCALE |
     SVGA_NEW_VELEMENT |
     SVGA_NEW_NEED_SWTNL),
index 85d015460070f871c439cb7805be6ea731d89cd9..79981dcf5ff1b95723437bf57d8ddb24f2219e66 100644 (file)
@@ -29,6 +29,7 @@
 #include "pipe/p_defines.h"
 #include "util/u_inlines.h"
 #include "os/os_thread.h"
+#include "util/u_bitmask.h"
 #include "util/u_format.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 #include "svga_format.h"
 #include "svga_screen.h"
 #include "svga_context.h"
+#include "svga_sampler_view.h"
 #include "svga_resource_texture.h"
 #include "svga_surface.h"
 #include "svga_debug.h"
 
+static void svga_mark_surface_dirty(struct pipe_surface *surf);
 
 void
 svga_texture_copy_handle(struct svga_context *svga,
                          struct svga_winsys_surface *src_handle,
                          unsigned src_x, unsigned src_y, unsigned src_z,
-                         unsigned src_level, unsigned src_face,
+                         unsigned src_level, unsigned src_layer,
                          struct svga_winsys_surface *dst_handle,
                          unsigned dst_x, unsigned dst_y, unsigned dst_z,
-                         unsigned dst_level, unsigned dst_face,
+                         unsigned dst_level, unsigned dst_layer,
                          unsigned width, unsigned height, unsigned depth)
 {
    struct svga_surface dst, src;
@@ -59,12 +62,12 @@ svga_texture_copy_handle(struct svga_context *svga,
 
    src.handle = src_handle;
    src.real_level = src_level;
-   src.real_face = src_face;
+   src.real_layer = src_layer;
    src.real_zslice = 0;
 
    dst.handle = dst_handle;
    dst.real_level = dst_level;
-   dst.real_face = dst_face;
+   dst.real_layer = dst_layer;
    dst.real_zslice = 0;
 
    box.x = dst_x;
@@ -103,11 +106,13 @@ svga_texture_copy_handle(struct svga_context *svga,
 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 face_pick,
+                          int layer_pick,
+                          unsigned num_layers,
                           int zslice_pick,
                           struct svga_host_surface_cache_key *key) /* OUT */
 {
@@ -117,8 +122,8 @@ svga_texture_view_surface(struct svga_context *svga,
    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);
+            "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;
@@ -127,12 +132,20 @@ svga_texture_view_surface(struct svga_context *svga,
    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 && face_pick < 0) {
+   if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) {
       key->flags |= SVGA3D_SURFACE_CUBEMAP;
       key->numFaces = 6;
-   } else {
-      key->numFaces = 1;
+   } 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) {
@@ -141,7 +154,7 @@ svga_texture_view_surface(struct svga_context *svga,
    }
 
    SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n");
-   handle = svga_screen_surface_create(ss, key);
+   handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT, key);
    if (!handle) {
       key->cachable = 0;
       return NULL;
@@ -149,15 +162,15 @@ svga_texture_view_surface(struct svga_context *svga,
 
    SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle);
 
-   if (face_pick < 0)
-      face_pick = 0;
+   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; j++) {
-         if (svga_is_texture_level_defined(tex, j + face_pick, i + start_mip)) {
+      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);
@@ -166,7 +179,7 @@ svga_texture_view_surface(struct svga_context *svga,
                                      tex->handle, 
                                      0, 0, z_offset, 
                                      i + start_mip, 
-                                     j + face_pick,
+                                     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),
@@ -179,33 +192,43 @@ svga_texture_view_surface(struct svga_context *svga,
 }
 
 
+/**
+ * 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(struct pipe_context *pipe,
-                    struct pipe_resource *pt,
-                    const struct pipe_surface *surf_tmpl)
+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 face, zslice;
-   boolean view = FALSE;
-   SVGA3dSurfaceFlags flags;
+   unsigned layer, zslice, bind;
+   unsigned nlayers = 1;
+   SVGA3dSurfaceFlags flags = 0;
    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;
+      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 {
-      face = 0;
+      layer = 0;
       zslice = surf_tmpl->u.tex.first_layer;
    }
 
@@ -218,25 +241,93 @@ svga_create_surface(struct pipe_context *pipe,
    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;
+      flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL |
+              SVGA3D_SURFACE_BIND_DEPTH_STENCIL;
+      bind = PIPE_BIND_DEPTH_STENCIL;
    }
    else {
-      flags = SVGA3D_SURFACE_HINT_RENDERTARGET;
+      flags = SVGA3D_SURFACE_HINT_RENDERTARGET |
+              SVGA3D_SURFACE_BIND_RENDER_TARGET;
+      bind = PIPE_BIND_RENDER_TARGET;
    }
 
-   format = svga_translate_format(ss, surf_tmpl->format, 0);
+   if (tex->imported)
+      format = tex->key.format;
+   else
+      format = svga_translate_format(ss, surf_tmpl->format, bind);
+
    assert(format != SVGA3D_FORMAT_INVALID);
 
-   if (svga_screen(screen)->debug.force_surface_view)
-      view = TRUE;
+   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;
+         }
+      }
 
-   /* Currently only used for compressed textures */
-   if (format != svga_translate_format(ss, surf_tmpl->format, 0)) {
-      view = TRUE;
+      /* 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);
+      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;
    }
 
+   return &s->base;
+}
+
+
+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 pipe_screen *screen = pipe->screen;
+   boolean view = FALSE;
+
+   if (svga_screen(screen)->debug.force_surface_view)
+      view = TRUE;
+
    if (surf_tmpl->u.tex.level != 0 &&
        svga_screen(screen)->debug.force_level_surface_view)
       view = TRUE;
@@ -244,47 +335,170 @@ svga_create_surface(struct pipe_context *pipe,
    if (pt->target == PIPE_TEXTURE_3D)
       view = TRUE;
 
-   if (svga_screen(screen)->debug.no_surface_view)
+   if (svga_have_vgpu10(svga) || 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);
+   return svga_create_surface_view(pipe, pt, surf_tmpl, view);
+}
 
-      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;
+/**
+ * Clone the surface view and its associated resource.
+ */
+static struct svga_surface *
+create_backed_surface_view(struct svga_context *svga, struct svga_surface *s)
+{
+   struct svga_surface *bs = s->backed;
+
+   if (bs == NULL) {
+      struct svga_texture *tex = svga_texture(s->base.texture);
+      struct pipe_surface *backed_view;
+
+      backed_view = svga_create_surface_view(&svga->pipe,
+                                             &tex->b.b,
+                                             &s->base,
+                                             TRUE);
+
+      bs = svga_surface(backed_view);
+      s->backed = bs;
    }
 
+   svga_mark_surface_dirty(&bs->base);
+
+   return bs;
+}
+
+/**
+ * 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;
+   int try;
+
+   assert(svga_have_vgpu10(svga));
+
+   /**
+    * 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.
+    */
+   if (svga_check_sampler_view_resource_collision(svga, s->handle)) {
+      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->view_id == SVGA3D_INVALID_ID) {
+      SVGA3dResourceType resType;
+      SVGA3dRenderTargetViewDesc desc;
+
+      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);
+
+      switch (s->base.texture->target) {
+      case PIPE_TEXTURE_1D:
+      case PIPE_TEXTURE_1D_ARRAY:
+         resType = SVGA3D_RESOURCE_TEXTURE1D;
+         break;
+      case PIPE_TEXTURE_RECT:
+      case PIPE_TEXTURE_2D:
+      case PIPE_TEXTURE_2D_ARRAY:
+      case PIPE_TEXTURE_CUBE:
+         /* drawing to cube map is treated as drawing to 2D array */
+         resType = SVGA3D_RESOURCE_TEXTURE2D;
+         break;
+      case PIPE_TEXTURE_3D:
+         resType = SVGA3D_RESOURCE_TEXTURE3D;
+         break;
+      default:
+         assert(!"Unexpected texture target");
+         resType = SVGA3D_RESOURCE_TEXTURE2D;
+      }
+
+      for (try = 0; try < 2; try++) {
+         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 {
+            ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc,
+                                                       s->view_id,
+                                                       s->handle,
+                                                       s->key.format,
+                                                       resType,
+                                                       &desc);
+         }
+         if (ret == PIPE_OK)
+            break;
+         svga_context_flush(svga, NULL);
+      }
+
+      assert(ret == PIPE_OK);
+      if (ret != PIPE_OK) {
+         util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
+         s->view_id = SVGA3D_INVALID_ID;
+      }
+   }
    return &s->base;
 }
 
 
+
 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);
 }
@@ -302,11 +516,8 @@ svga_mark_surface_dirty(struct pipe_surface *surf)
 
       if (s->handle == tex->handle) {
          /* hmm so 3d textures always have all their slices marked ? */
-         if (surf->texture->target == PIPE_TEXTURE_CUBE)
-            svga_define_texture_level(tex, surf->u.tex.first_layer,
-                                      surf->u.tex.level);
-         else
-            svga_define_texture_level(tex, 0, surf->u.tex.level);
+         svga_define_texture_level(tex, surf->u.tex.first_layer,
+                                   surf->u.tex.level);
       }
       else {
          /* this will happen later in svga_propagate_surface */
@@ -345,18 +556,26 @@ 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;
+   unsigned zslice, layer;
+   unsigned nlayers = 1;
+   unsigned i;
 
    if (!s->dirty)
       return;
 
    if (surf->texture->target == PIPE_TEXTURE_CUBE) {
       zslice = 0;
-      face = surf->u.tex.first_layer;
+      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;
-      face = 0;
+      layer = 0;
    }
 
    s->dirty = FALSE;
@@ -367,12 +586,14 @@ svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf)
       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);
+      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);
+      }
    }
 }
 
@@ -390,10 +611,76 @@ svga_surface_needs_propagation(const struct pipe_surface *surf)
 }
 
 
+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;
 }
index 2fa72a1c8f0afb24308beaebda55aa2b8ff2c0a9..0e5794b0b3806e0b88ebbc2554a57c5b447060c3 100644 (file)
@@ -47,11 +47,15 @@ struct svga_surface
    struct svga_host_surface_cache_key key;
    struct svga_winsys_surface *handle;
 
-   unsigned real_face;
+   unsigned real_layer;
    unsigned real_level;
    unsigned real_zslice;
 
    boolean dirty;
+
+   /* VGPU10 */
+   SVGA3dRenderTargetViewId view_id;
+   struct svga_surface *backed;
 };
 
 
@@ -64,11 +68,13 @@ svga_surface_needs_propagation(const struct pipe_surface *surf);
 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 face_pick,
+                          int layer_pick,
+                          unsigned num_layers,
                           int zslice_pick,
                           struct svga_host_surface_cache_key *key); /* OUT */
 
@@ -99,4 +105,8 @@ svga_surface_const(const struct pipe_surface *surface)
    return (const struct svga_surface *)surface;
 }
 
+struct pipe_surface *
+svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s);
+
+
 #endif
index ded8bcbd536ad05858429261343a22e627717eaa..4bdb21a98427991779638827f53b583692d99e16 100644 (file)
@@ -40,6 +40,7 @@
 #include "svga_reg.h"
 #include "svga3d_reg.h"
 #include "svga_draw.h"
+#include "svga_shader.h"
 #include "svga_swtnl_private.h"
 
 
@@ -129,9 +130,12 @@ svga_vbuf_render_map_vertices( struct vbuf_render *render )
                                          PIPE_TRANSFER_DISCARD_RANGE |
                                          PIPE_TRANSFER_UNSYNCHRONIZED,
                                          &svga_render->vbuf_transfer);
-      if (ptr)
+      if (ptr) {
+         svga_render->vbuf_ptr = ptr;
          return ptr + svga_render->vbuf_offset;
+      }
       else {
+         svga_render->vbuf_ptr = NULL;
          svga_render->vbuf_transfer = NULL;
          return NULL;
       }
@@ -154,6 +158,18 @@ svga_vbuf_render_unmap_vertices( struct vbuf_render *render,
 
    offset = svga_render->vbuf_offset + svga_render->vertex_size * min_index;
    length = svga_render->vertex_size * (max_index + 1 - min_index);
+
+   if (0) {
+      /* dump vertex data */
+      const float *f = (const float *) ((char *) svga_render->vbuf_ptr +
+                                        svga_render->vbuf_offset);
+      unsigned i;
+      debug_printf("swtnl vertex data:\n");
+      for (i = 0; i < length / 4; i += 4) {
+         debug_printf("%u: %f %f %f %f\n", i, f[i], f[i+1], f[i+2], f[i+3]);
+      }
+   }
+
    pipe_buffer_flush_mapped_range(&svga->pipe,
                                  svga_render->vbuf_transfer,
                                  offset, length);
@@ -178,6 +194,7 @@ svga_vbuf_submit_state( struct svga_vbuf_render *svga_render )
    SVGA3dVertexDecl vdecl[PIPE_MAX_ATTRIBS];
    enum pipe_error ret;
    unsigned i;
+   static const unsigned zero[PIPE_MAX_ATTRIBS] = {0};
 
    /* if the vdecl or vbuf hasn't changed do nothing */
    if (!svga->swtnl.new_vdecl)
@@ -192,18 +209,27 @@ svga_vbuf_submit_state( struct svga_vbuf_render *svga_render )
       ret = svga_hwtnl_flush(svga->hwtnl);
       /* if we hit this path we might become synced with hw */
       svga->swtnl.new_vbuf = TRUE;
-      assert(ret == 0);
+      assert(ret == PIPE_OK);
    }
 
-   svga_hwtnl_reset_vdecl(svga->hwtnl, svga_render->vdecl_count);
-
    for (i = 0; i < svga_render->vdecl_count; i++) {
       vdecl[i].array.offset += svga_render->vdecl_offset;
+   }
 
-      svga_hwtnl_vdecl( svga->hwtnl,
-                        i,
-                        &vdecl[i],
-                        svga_render->vbuf );
+   svga_hwtnl_vertex_decls(svga->hwtnl,
+                           svga_render->vdecl_count,
+                           vdecl,
+                           zero,
+                           svga_render->layout_id);
+
+   /* Specify the vertex buffer (there's only ever one) */
+   {
+      struct pipe_vertex_buffer vb;
+      vb.buffer = svga_render->vbuf;
+      vb.buffer_offset = svga_render->vdecl_offset;
+      vb.stride = vdecl[0].array.stride;
+      vb.user_buffer = NULL;
+      svga_hwtnl_vertex_buffers(svga->hwtnl, 1, &vb);
    }
 
    /* We have already taken care of flatshading, so let the hwtnl
@@ -211,15 +237,15 @@ svga_vbuf_submit_state( struct svga_vbuf_render *svga_render )
     */
    if (svga->state.sw.need_pipeline) {
       svga_hwtnl_set_flatshade(svga->hwtnl, FALSE, FALSE);
-      svga_hwtnl_set_unfilled(svga->hwtnl, PIPE_POLYGON_MODE_FILL);
+      svga_hwtnl_set_fillmode(svga->hwtnl, PIPE_POLYGON_MODE_FILL);
    }
    else {
       svga_hwtnl_set_flatshade( svga->hwtnl,
-                                svga->curr.rast->templ.flatshade,
+                                svga->curr.rast->templ.flatshade ||
+                                svga->state.hw_draw.fs->uses_flat_interp,
                                 svga->curr.rast->templ.flatshade_first );
 
-      svga_hwtnl_set_unfilled( svga->hwtnl,
-                               svga->curr.rast->hw_unfilled );
+      svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode);
    }
 
    svga->swtnl.new_vdecl = FALSE;
@@ -227,13 +253,15 @@ svga_vbuf_submit_state( struct svga_vbuf_render *svga_render )
 
 static void
 svga_vbuf_render_draw_arrays( struct vbuf_render *render,
-                              unsigned start,
-                              uint nr )
+                              unsigned start, uint nr )
 {
    struct svga_vbuf_render *svga_render = svga_vbuf_render(render);
    struct svga_context *svga = svga_render->svga;
    unsigned bias = (svga_render->vbuf_offset - svga_render->vdecl_offset) / svga_render->vertex_size;
    enum pipe_error ret = PIPE_OK;
+   /* instancing will already have been resolved at this point by 'draw' */
+   const unsigned start_instance = 0;
+   const unsigned instance_count = 1;
 
    /* off to hardware */
    svga_vbuf_submit_state(svga_render);
@@ -244,10 +272,13 @@ svga_vbuf_render_draw_arrays( struct vbuf_render *render,
     */
    svga_update_state_retry( svga, SVGA_STATE_HW_DRAW );
 
-   ret = svga_hwtnl_draw_arrays(svga->hwtnl, svga_render->prim, start + bias, nr);
+   ret = svga_hwtnl_draw_arrays(svga->hwtnl, svga_render->prim, start + bias, nr,
+                                start_instance, instance_count);
    if (ret != PIPE_OK) {
       svga_context_flush(svga, NULL);
-      ret = svga_hwtnl_draw_arrays(svga->hwtnl, svga_render->prim, start + bias, nr);
+      ret = svga_hwtnl_draw_arrays(svga->hwtnl, svga_render->prim,
+                                   start + bias, nr,
+                                   start_instance, instance_count);
       svga->swtnl.new_vbuf = TRUE;
       assert(ret == PIPE_OK);
    }
@@ -265,6 +296,9 @@ svga_vbuf_render_draw_elements( struct vbuf_render *render,
    int bias = (svga_render->vbuf_offset - svga_render->vdecl_offset) / svga_render->vertex_size;
    boolean ret;
    size_t size = 2 * nr_indices;
+   /* instancing will already have been resolved at this point by 'draw' */
+   const unsigned start_instance = 0;
+   const unsigned instance_count = 1;
 
    assert(( svga_render->vbuf_offset - svga_render->vdecl_offset) % svga_render->vertex_size == 0);
    
@@ -299,7 +333,8 @@ svga_vbuf_render_draw_elements( struct vbuf_render *render,
                                         svga_render->min_index,
                                         svga_render->max_index,
                                         svga_render->prim,
-                                        svga_render->ibuf_offset / 2, nr_indices);
+                                        svga_render->ibuf_offset / 2, nr_indices,
+                                        start_instance, instance_count);
    if(ret != PIPE_OK) {
       svga_context_flush(svga, NULL);
       ret = svga_hwtnl_draw_range_elements(svga->hwtnl,
@@ -309,7 +344,9 @@ svga_vbuf_render_draw_elements( struct vbuf_render *render,
                                            svga_render->min_index,
                                            svga_render->max_index,
                                            svga_render->prim,
-                                           svga_render->ibuf_offset / 2, nr_indices);
+                                           svga_render->ibuf_offset / 2,
+                                           nr_indices,
+                                           start_instance, instance_count);
       svga->swtnl.new_vbuf = TRUE;
       assert(ret == PIPE_OK);
    }
@@ -349,6 +386,7 @@ svga_vbuf_render_create( struct svga_context *svga )
    svga_render->vbuf_size = 0;
    svga_render->ibuf_alloc_size = 4*1024;
    svga_render->vbuf_alloc_size = 64*1024;
+   svga_render->layout_id = SVGA3D_INVALID_ID;
    svga_render->base.max_vertex_buffer_bytes = 64*1024/10;
    svga_render->base.max_indices = 65536;
    svga_render->base.get_vertex_info = svga_vbuf_render_get_vertex_info;
index 832249523cc1b34cfd8f55ea632af119e3a890ba..6a8e857cee85d1f3039064b9eaa8a5dffb8c2317 100644 (file)
@@ -42,9 +42,9 @@ svga_swtnl_draw_vbo(struct svga_context *svga,
 {
    struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = { 0 };
    struct pipe_transfer *ib_transfer = NULL;
-   struct pipe_transfer *cb_transfer = NULL;
+   struct pipe_transfer *cb_transfer[SVGA_MAX_CONST_BUFS] = { 0 };
    struct draw_context *draw = svga->swtnl.draw;
-   unsigned i;
+   unsigned i, old_num_vertex_buffers;
    const void *map;
    enum pipe_error ret;
 
@@ -76,6 +76,7 @@ svga_swtnl_draw_vbo(struct svga_context *svga,
          draw_set_mapped_vertex_buffer(draw, i, map, ~0);
       }
    }
+   old_num_vertex_buffers = svga->curr.num_vertex_buffers;
 
    /* Map index buffer, if present */
    map = NULL;
@@ -88,16 +89,21 @@ svga_swtnl_draw_vbo(struct svga_context *svga,
                        svga->curr.ib.index_size, ~0);
    }
 
-   if (svga->curr.cbufs[PIPE_SHADER_VERTEX].buffer) {
+   /* Map constant buffers */
+   for (i = 0; i < Elements(svga->curr.constbufs[PIPE_SHADER_VERTEX]); ++i) {
+      if (svga->curr.constbufs[PIPE_SHADER_VERTEX][i].buffer == NULL) {
+         continue;
+      }
+
       map = pipe_buffer_map(&svga->pipe,
-                            svga->curr.cbufs[PIPE_SHADER_VERTEX].buffer,
+                            svga->curr.constbufs[PIPE_SHADER_VERTEX][i].buffer,
                             PIPE_TRANSFER_READ,
-                           &cb_transfer);
+                            &cb_transfer[i]);
       assert(map);
       draw_set_mapped_constant_buffer(
-         draw, PIPE_SHADER_VERTEX, 0,
+         draw, PIPE_SHADER_VERTEX, i,
          map,
-         svga->curr.cbufs[PIPE_SHADER_VERTEX].buffer->width0);
+         svga->curr.constbufs[PIPE_SHADER_VERTEX][i].buffer->width0);
    }
 
    draw_vbo(draw, info);
@@ -105,8 +111,8 @@ svga_swtnl_draw_vbo(struct svga_context *svga,
    draw_flush(svga->swtnl.draw);
 
    /* Ensure the draw module didn't touch this */
-   assert(i == svga->curr.num_vertex_buffers);
-   
+   assert(old_num_vertex_buffers == svga->curr.num_vertex_buffers);
+
    /*
     * unmap vertex/index buffers
     */
@@ -122,8 +128,10 @@ svga_swtnl_draw_vbo(struct svga_context *svga,
       draw_set_indexes(draw, NULL, 0, 0);
    }
 
-   if (svga->curr.cbufs[PIPE_SHADER_VERTEX].buffer) {
-      pipe_buffer_unmap(&svga->pipe, cb_transfer);
+   for (i = 0; i < Elements(svga->curr.constbufs[PIPE_SHADER_VERTEX]); ++i) {
+      if (svga->curr.constbufs[PIPE_SHADER_VERTEX][i].buffer) {
+         pipe_buffer_unmap(&svga->pipe, cb_transfer[i]);
+      }
    }
 
    /* Now safe to remove the need_swtnl flag in any update_state call */
@@ -167,9 +175,6 @@ boolean svga_init_swtnl( struct svga_context *svga )
    if (!screen->haveLineSmooth)
       draw_install_aaline_stage(svga->swtnl.draw, &svga->pipe);
 
-   /* always install polygon stipple stage */
-   draw_install_pstipple_stage(svga->swtnl.draw, &svga->pipe);
-
    /* enable/disable line stipple stage depending on device caps */
    draw_enable_line_stipple(svga->swtnl.draw, !screen->haveLineStipple);
 
index e2106e1e8e6112093752bc73297f3712e80ebb38..0a226abca88b4789f50a92469342f8707e34b06f 100644 (file)
@@ -43,6 +43,8 @@ struct svga_vbuf_render {
 
    unsigned vertex_size;
 
+   SVGA3dElementLayoutId layout_id; /**< current element layout id */
+
    unsigned prim;
 
    struct pipe_resource *vbuf;
@@ -50,6 +52,8 @@ struct svga_vbuf_render {
    struct pipe_transfer *vbuf_transfer;
    struct pipe_transfer *ibuf_transfer;
 
+   void *vbuf_ptr;
+
    /* current size of buffer */
    size_t vbuf_size;
    size_t ibuf_size;
index e62698e11f4d76eb51414dd1627403968ffc6516..79dc0bf580c087847417fc7bdaeeba67a3067045 100644 (file)
 
 #include "draw/draw_context.h"
 #include "draw/draw_vbuf.h"
+#include "util/u_bitmask.h"
 #include "util/u_inlines.h"
 #include "pipe/p_state.h"
 
+#include "svga_cmd.h"
 #include "svga_context.h"
+#include "svga_shader.h"
 #include "svga_swtnl.h"
 #include "svga_state.h"
 #include "svga_tgsi.h"
@@ -51,30 +54,37 @@ static void set_draw_viewport( struct svga_context *svga )
    float adjx = 0.0f;
    float adjy = 0.0f;
 
-   switch (svga->curr.reduced_prim) {
-   case PIPE_PRIM_POINTS:
-      adjx = SVGA_POINT_ADJ_X;
-      adjy = SVGA_POINT_ADJ_Y;
-      break;
-   case PIPE_PRIM_LINES:
-      /* XXX: This is to compensate for the fact that wide lines are
-       * going to be drawn with triangles, but we're not catching all
-       * cases where that will happen.
-       */
-      if (svga->curr.rast->need_pipeline & SVGA_PIPELINE_FLAG_LINES)
-      {
-         adjx = SVGA_LINE_ADJ_X + 0.175f;
-         adjy = SVGA_LINE_ADJ_Y - 0.175f;
+   if (svga_have_vgpu10(svga)) {
+      if (svga->curr.reduced_prim == PIPE_PRIM_TRIANGLES) {
+         adjy = 0.25;
       }
-      else {
-         adjx = SVGA_LINE_ADJ_X;
-         adjy = SVGA_LINE_ADJ_Y;
+   }
+   else {
+      switch (svga->curr.reduced_prim) {
+      case PIPE_PRIM_POINTS:
+         adjx = SVGA_POINT_ADJ_X;
+         adjy = SVGA_POINT_ADJ_Y;
+         break;
+      case PIPE_PRIM_LINES:
+         /* XXX: This is to compensate for the fact that wide lines are
+          * going to be drawn with triangles, but we're not catching all
+          * cases where that will happen.
+          */
+         if (svga->curr.rast->need_pipeline & SVGA_PIPELINE_FLAG_LINES)
+         {
+            adjx = SVGA_LINE_ADJ_X + 0.175f;
+            adjy = SVGA_LINE_ADJ_Y - 0.175f;
+         }
+         else {
+            adjx = SVGA_LINE_ADJ_X;
+            adjy = SVGA_LINE_ADJ_Y;
+         }
+         break;
+      case PIPE_PRIM_TRIANGLES:
+         adjx += SVGA_TRIANGLE_ADJ_X;
+         adjy += SVGA_TRIANGLE_ADJ_Y;
+         break;
       }
-      break;
-   case PIPE_PRIM_TRIANGLES:
-      adjx += SVGA_TRIANGLE_ADJ_X;
-      adjy += SVGA_TRIANGLE_ADJ_Y;
-      break;
    }
 
    vp.translate[0] += adjx;
@@ -150,6 +160,59 @@ struct svga_tracked_state svga_update_swtnl_draw =
 };
 
 
+static SVGA3dSurfaceFormat
+translate_vertex_format(SVGA3dDeclType format)
+{
+   switch (format) {
+   case SVGA3D_DECLTYPE_FLOAT1:
+      return SVGA3D_R32_FLOAT;
+   case SVGA3D_DECLTYPE_FLOAT2:
+      return SVGA3D_R32G32_FLOAT;
+   case SVGA3D_DECLTYPE_FLOAT3:
+      return SVGA3D_R32G32B32_FLOAT;
+   case SVGA3D_DECLTYPE_FLOAT4:
+      return SVGA3D_R32G32B32A32_FLOAT;
+   default:
+      assert(!"Unexpected format in translate_vertex_format()");
+      return SVGA3D_R32G32B32A32_FLOAT;
+   }
+}
+
+
+static SVGA3dElementLayoutId
+svga_vdecl_to_input_element(struct svga_context *svga,
+                            const SVGA3dVertexDecl *vdecl, unsigned num_decls)
+{
+   SVGA3dElementLayoutId id;
+   SVGA3dInputElementDesc elements[PIPE_MAX_ATTRIBS];
+   enum pipe_error ret;
+   unsigned i;
+
+   assert(num_decls <= PIPE_MAX_ATTRIBS);
+   assert(svga_have_vgpu10(svga));
+
+   for (i = 0; i < num_decls; i++) {
+      elements[i].inputSlot = 0; /* vertex buffer index */
+      elements[i].alignedByteOffset = vdecl[i].array.offset;
+      elements[i].format = translate_vertex_format(vdecl[i].identity.type);
+      elements[i].inputSlotClass = SVGA3D_INPUT_PER_VERTEX_DATA;
+      elements[i].instanceDataStepRate = 0;
+      elements[i].inputRegister = i;
+   }
+
+   id = util_bitmask_add(svga->input_element_object_id_bm);
+
+   ret = SVGA3D_vgpu10_DefineElementLayout(svga->swc, num_decls, id, elements);
+   if (ret != PIPE_OK) {
+      svga_context_flush(svga, NULL);
+      ret = SVGA3D_vgpu10_DefineElementLayout(svga->swc, num_decls, id, elements);
+      assert(ret == PIPE_OK);
+   }
+
+   return id;
+}
+
+
 enum pipe_error
 svga_swtnl_update_vdecl( struct svga_context *svga )
 {
@@ -164,16 +227,19 @@ svga_swtnl_update_vdecl( struct svga_context *svga )
    int nr_decls = 0;
    int src;
    unsigned i;
+   int any_change;
 
    memset(vinfo, 0, sizeof(*vinfo));
    memset(vdecl, 0, sizeof(vdecl));
 
    draw_prepare_shader_outputs(draw);
+
    /* always add position */
    src = draw_find_shader_output(draw, TGSI_SEMANTIC_POSITION, 0);
    draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_LINEAR, src);
    vinfo->attrib[0].emit = EMIT_4F;
    vdecl[0].array.offset = offset;
+   vdecl[0].identity.method = SVGA3D_DECLMETHOD_DEFAULT;
    vdecl[0].identity.type = SVGA3D_DECLTYPE_FLOAT4;
    vdecl[0].identity.usage = SVGA3D_DECLUSAGE_POSITIONT;
    vdecl[0].identity.usageIndex = 0;
@@ -225,16 +291,67 @@ svga_swtnl_update_vdecl( struct svga_context *svga )
    draw_compute_vertex_size(vinfo);
 
    svga_render->vdecl_count = nr_decls;
-   for (i = 0; i < svga_render->vdecl_count; i++)
+   for (i = 0; i < svga_render->vdecl_count; i++) {
       vdecl[i].array.stride = offset;
+   }
 
-   if (memcmp(svga_render->vdecl, vdecl, sizeof(vdecl)) == 0)
-      return PIPE_OK;
+   any_change = memcmp(svga_render->vdecl, vdecl, sizeof(vdecl));
+
+   if (svga_have_vgpu10(svga)) {
+      enum pipe_error ret;
+
+      if (!any_change && svga_render->layout_id != SVGA3D_INVALID_ID) {
+         return PIPE_OK;
+      }
+
+      if (svga_render->layout_id != SVGA3D_INVALID_ID) {
+         /* destroy old */
+         ret = SVGA3D_vgpu10_DestroyElementLayout(svga->swc,
+                                                  svga_render->layout_id);
+         if (ret != PIPE_OK) {
+            svga_context_flush(svga, NULL);
+            ret = SVGA3D_vgpu10_DestroyElementLayout(svga->swc,
+                                                     svga_render->layout_id);
+            assert(ret == PIPE_OK);
+         }
+
+         /**
+          * reset current layout id state after the element layout is
+          * destroyed, so that if a new layout has the same layout id, we
+          * will know to re-issue the SetInputLayout command.
+          */
+         if (svga->state.hw_draw.layout_id == svga_render->layout_id)
+            svga->state.hw_draw.layout_id = SVGA3D_INVALID_ID;
+
+         util_bitmask_clear(svga->input_element_object_id_bm,
+                            svga_render->layout_id);
+      }
+
+      svga_render->layout_id =
+         svga_vdecl_to_input_element(svga, vdecl, nr_decls);
+
+      /* bind new */
+      if (svga->state.hw_draw.layout_id != svga_render->layout_id) {
+         ret = SVGA3D_vgpu10_SetInputLayout(svga->swc, svga_render->layout_id);
+         if (ret != PIPE_OK) {
+            svga_context_flush(svga, NULL);
+            ret = SVGA3D_vgpu10_SetInputLayout(svga->swc,
+                                               svga_render->layout_id);
+            assert(ret == PIPE_OK);
+         }
+
+         svga->state.hw_draw.layout_id = svga_render->layout_id;
+      }
+   }
+   else {
+      if (!any_change)
+         return PIPE_OK;
+   }
 
    memcpy(svga_render->vdecl, vdecl, sizeof(vdecl));
    svga->swtnl.new_vdecl = TRUE;
 
-   return PIPE_OK;
+   return 0;
 }
 
 
index 2e2ff5e467381c6be96074ce3bc5bdb83228d9b2..9a6fb465ccb2e6b05c695c3469fff489ef92f67a 100644 (file)
@@ -37,6 +37,7 @@
 #include "svgadump/svga_shader_dump.h"
 
 #include "svga_context.h"
+#include "svga_shader.h"
 #include "svga_tgsi.h"
 #include "svga_tgsi_emit.h"
 #include "svga_debug.h"
@@ -165,97 +166,6 @@ svga_shader_emit_header(struct svga_shader_emitter *emit)
 }
 
 
-/**
- * Use the shader info to generate a bitmask indicating which generic
- * inputs are used by the shader.  A set bit indicates that GENERIC[i]
- * is used.
- */
-unsigned
-svga_get_generic_inputs_mask(const struct tgsi_shader_info *info)
-{
-   unsigned i, mask = 0x0;
-
-   for (i = 0; i < info->num_inputs; i++) {
-      if (info->input_semantic_name[i] == TGSI_SEMANTIC_GENERIC) {
-         unsigned j = info->input_semantic_index[i];
-         assert(j < sizeof(mask) * 8);
-         mask |= 1 << j;
-      }
-   }
-
-   return mask;
-}
-
-
-/**
- * Given a mask of used generic variables (as returned by the above functions)
- * fill in a table which maps those indexes to small integers.
- * This table is used by the remap_generic_index() function in
- * svga_tgsi_decl_sm30.c
- * Example: if generics_mask = binary(1010) it means that GENERIC[1] and
- * GENERIC[3] are used.  The remap_table will contain:
- *   table[1] = 0;
- *   table[3] = 1;
- * The remaining table entries will be filled in with the next unused
- * generic index (in this example, 2).
- */
-void
-svga_remap_generics(unsigned generics_mask,
-                    int8_t remap_table[MAX_GENERIC_VARYING])
-{
-   /* Note texcoord[0] is reserved so start at 1 */
-   unsigned count = 1, i;
-
-   for (i = 0; i < MAX_GENERIC_VARYING; i++) {
-      remap_table[i] = -1;
-   }
-
-   /* for each bit set in generic_mask */
-   while (generics_mask) {
-      unsigned index = ffs(generics_mask) - 1;
-      remap_table[index] = count++;
-      generics_mask &= ~(1 << index);
-   }
-}
-
-
-/**
- * Use the generic remap table to map a TGSI generic varying variable
- * index to a small integer.  If the remapping table doesn't have a
- * valid value for the given index (the table entry is -1) it means
- * the fragment shader doesn't use that VS output.  Just allocate
- * the next free value in that case.  Alternately, we could cull
- * VS instructions that write to register, or replace the register
- * with a dummy temp register.
- * XXX TODO: we should do one of the later as it would save precious
- * texcoord registers.
- */
-int
-svga_remap_generic_index(int8_t remap_table[MAX_GENERIC_VARYING],
-                         int generic_index)
-{
-   assert(generic_index < MAX_GENERIC_VARYING);
-
-   if (generic_index >= MAX_GENERIC_VARYING) {
-      /* just don't return a random/garbage value */
-      generic_index = MAX_GENERIC_VARYING - 1;
-   }
-
-   if (remap_table[generic_index] == -1) {
-      /* This is a VS output that has no matching PS input.  Find a
-       * free index.
-       */
-      int i, max = 0;
-      for (i = 0; i < MAX_GENERIC_VARYING; i++) {
-         max = MAX2(max, remap_table[i]);
-      }
-      remap_table[generic_index] = max + 1;
-   }
-
-   return remap_table[generic_index];
-}
-
-
 /**
  * Parse TGSI shader and translate to SVGA/DX9 serialized
  * representation.
@@ -264,9 +174,9 @@ svga_remap_generic_index(int8_t remap_table[MAX_GENERIC_VARYING],
  * can be dynamically grown.  Once we've finished and know how large
  * it is, it will be copied to a hardware buffer for upload.
  */
-static struct svga_shader_variant *
-svga_tgsi_translate(const struct svga_shader *shader,
-                    const struct svga_compile_key *key, unsigned unit)
+struct svga_shader_variant *
+svga_tgsi_vgpu9_translate(const struct svga_shader *shader,
+                          const struct svga_compile_key *key, unsigned unit)
 {
    struct svga_shader_variant *variant = NULL;
    struct svga_shader_emitter emit;
@@ -288,10 +198,10 @@ svga_tgsi_translate(const struct svga_shader *shader,
    emit.imm_start = emit.info.file_max[TGSI_FILE_CONSTANT] + 1;
 
    if (unit == PIPE_SHADER_FRAGMENT)
-      emit.imm_start += key->fkey.num_unnormalized_coords;
+      emit.imm_start += key->num_unnormalized_coords;
 
    if (unit == PIPE_SHADER_VERTEX) {
-      emit.imm_start += key->vkey.need_prescale ? 2 : 0;
+      emit.imm_start += key->vs.need_prescale ? 2 : 0;
    }
 
    emit.nr_hw_float_const =
@@ -327,7 +237,11 @@ svga_tgsi_translate(const struct svga_shader *shader,
    memcpy(&variant->key, key, sizeof(*key));
    variant->id = UTIL_BITMASK_INVALID_INDEX;
 
-   if (SVGA_DEBUG & DEBUG_TGSI) {
+   variant->pstipple_sampler_unit = emit.pstipple_sampler_unit;
+
+#if 0
+   if (!svga_shader_verify(variant->tokens, variant->nr_tokens) ||
+       SVGA_DEBUG & DEBUG_TGSI) {
       debug_printf("#####################################\n");
       debug_printf("Shader %u below\n", shader->id);
       tgsi_dump(shader->tokens, 0);
@@ -337,6 +251,7 @@ svga_tgsi_translate(const struct svga_shader *shader,
       }
       debug_printf("#####################################\n");
    }
+#endif
 
    return variant;
 
@@ -345,39 +260,3 @@ svga_tgsi_translate(const struct svga_shader *shader,
    FREE(emit.buf);
    return NULL;
 }
-
-
-struct svga_shader_variant *
-svga_translate_fragment_program(const struct svga_fragment_shader *fs,
-                                const struct svga_fs_compile_key *fkey)
-{
-   struct svga_compile_key key;
-
-   memset(&key, 0, sizeof(key));
-
-   memcpy(&key.fkey, fkey, sizeof *fkey);
-
-   memcpy(key.generic_remap_table, fs->generic_remap_table,
-          sizeof(fs->generic_remap_table));
-
-   return svga_tgsi_translate(&fs->base, &key, PIPE_SHADER_FRAGMENT);
-}
-
-
-struct svga_shader_variant *
-svga_translate_vertex_program(const struct svga_vertex_shader *vs,
-                              const struct svga_vs_compile_key *vkey)
-{
-   struct svga_compile_key key;
-
-   memset(&key, 0, sizeof(key));
-
-   memcpy(&key.vkey, vkey, sizeof *vkey);
-
-   /* Note: we could alternately store the remap table in the vkey but
-    * that would make it larger.  We just regenerate it here instead.
-    */
-   svga_remap_generics(vkey->fs_generic_inputs, key.generic_remap_table);
-
-   return svga_tgsi_translate(&vs->base, &key, PIPE_SHADER_VERTEX);
-}
index 5c47a4ad39f43f0b9df74b5f8fa2a8d4af824981..207a3f0a8457dd1034349f2ada8b888a8f8c2bff 100644 (file)
 #ifndef SVGA_TGSI_H
 #define SVGA_TGSI_H
 
-#include "pipe/p_state.h"
+#include "pipe/p_compiler.h"
+#include "svga3d_reg.h"
 
-#include "svga_hw_reg.h"
 
+#define MAX_VGPU10_ADDR_REGS 2
 
-/**
- * We use a 32-bit mask to keep track of the generic indexes.
- */
-#define MAX_GENERIC_VARYING 32
-
-
-struct svga_fragment_shader;
-struct svga_vertex_shader;
+struct svga_compile_key;
+struct svga_context;
 struct svga_shader;
-struct tgsi_shader_info;
-struct tgsi_token;
-
-
-struct svga_vs_compile_key
-{
-   unsigned fs_generic_inputs;
-   unsigned need_prescale:1;
-   unsigned allow_psiz:1;
-   unsigned adjust_attrib_range:16;
-   unsigned adjust_attrib_w_1:16;
-};
-
-struct svga_fs_compile_key
-{
-   unsigned light_twoside:1;
-   unsigned front_ccw:1;
-   unsigned white_fragments:1;
-   unsigned write_color0_to_n_cbufs:3;
-   unsigned num_textures:8;
-   unsigned num_unnormalized_coords:8;
-   unsigned sprite_origin_lower_left:1;
-   struct {
-      unsigned compare_mode:1;
-      unsigned compare_func:3;
-      unsigned unnormalized:1;
-      unsigned width_height_idx:7;
-      unsigned texture_target:8;
-      unsigned sprite_texgen:1;
-      unsigned swizzle_r:3;
-      unsigned swizzle_g:3;
-      unsigned swizzle_b:3;
-      unsigned swizzle_a:3;
-   } tex[PIPE_MAX_SAMPLERS];
-};
-
-/**
- * Key/index for identifying shader variants.
- */
-struct svga_compile_key {
-   struct svga_vs_compile_key vkey;
-   struct svga_fs_compile_key fkey;
-   int8_t generic_remap_table[MAX_GENERIC_VARYING];
-};
-
-
-/**
- * A single TGSI shader may be compiled into different variants of
- * SVGA3D shaders depending on the compile key.  Each user shader
- * will have a linked list of these variants.
- */
-struct svga_shader_variant
-{
-   const struct svga_shader *shader;
-
-   /** Parameters used to generate this variant */
-   struct svga_compile_key key;
-
-   /* Compiled shader tokens:
-    */
-   const unsigned *tokens;
-   unsigned nr_tokens;
-
-   /** Per-context shader identifier used with SVGA_3D_CMD_SHADER_DEFINE,
-    * SVGA_3D_CMD_SET_SHADER and SVGA_3D_CMD_SHADER_DESTROY.
-    */
-   unsigned id;
-   
-   /* GB object buffer containing the bytecode */
-   struct svga_winsys_gb_shader *gb_shader;
-
-   /** Next variant */
-   struct svga_shader_variant *next;
-};
+struct svga_shader_variant;
 
 
 /* TGSI doesn't provide use with VS input semantics (they're actually
@@ -140,37 +62,16 @@ static inline void svga_generate_vdecl_semantics( unsigned idx,
 
 
 
-static inline unsigned svga_vs_key_size( const struct svga_vs_compile_key *key )
-{
-   return sizeof *key;
-}
-
-static inline unsigned svga_fs_key_size( const struct svga_fs_compile_key *key )
-{
-   return (const char *)&key->tex[key->num_textures] - (const char *)key;
-}
-
 struct svga_shader_variant *
-svga_translate_fragment_program( const struct svga_fragment_shader *fs,
-                                 const struct svga_fs_compile_key *fkey );
+svga_tgsi_vgpu9_translate(const struct svga_shader *shader,
+                          const struct svga_compile_key *key, unsigned unit);
 
 struct svga_shader_variant *
-svga_translate_vertex_program( const struct svga_vertex_shader *fs,
-                               const struct svga_vs_compile_key *vkey );
-
-
-unsigned
-svga_get_generic_inputs_mask(const struct tgsi_shader_info *info);
-
-unsigned
-svga_get_generic_outputs_mask(const struct tgsi_shader_info *info);
-
-void
-svga_remap_generics(unsigned generics_mask,
-                    int8_t remap_table[MAX_GENERIC_VARYING]);
+svga_tgsi_vgpu10_translate(struct svga_context *svga,
+                           const struct svga_shader *shader,
+                           const struct svga_compile_key *key,
+                           unsigned unit);
 
-int
-svga_remap_generic_index(int8_t remap_table[MAX_GENERIC_VARYING],
-                         int generic_index);
+boolean svga_shader_verify(const uint32_t *tokens, unsigned nr_tokens);
 
 #endif
index 42d6f489bc5b679e06667632e90664e1f7a881a1..ca4009b9e38082685a27729bc29c7a0b9ae051a8 100644 (file)
@@ -216,7 +216,7 @@ ps30_input(struct svga_shader_emitter *emit,
 
       return emit_decl( emit, reg, 0, 0 );
    }
-   else if (emit->key.fkey.light_twoside &&
+   else if (emit->key.fs.light_twoside &&
             (semantic.Name == TGSI_SEMANTIC_COLOR)) {
 
       if (!translate_vs_ps_semantic( emit, semantic, &usage, &index ))
@@ -285,9 +285,9 @@ ps30_input(struct svga_shader_emitter *emit,
          return FALSE;
 
       if (semantic.Name == TGSI_SEMANTIC_GENERIC &&
-          emit->key.fkey.sprite_origin_lower_left &&
+          emit->key.sprite_origin_lower_left &&
           index >= 1 &&
-          emit->key.fkey.tex[index - 1].sprite_texgen) {
+          emit->key.tex[index - 1].sprite_texgen) {
          /* This is a sprite texture coord with lower-left origin.
           * We need to invert the texture T coordinate since the SVGA3D
           * device only supports an upper-left origin.
@@ -329,7 +329,7 @@ ps30_output(struct svga_shader_emitter *emit,
    switch (semantic.Name) {
    case TGSI_SEMANTIC_COLOR:
       if (emit->unit == PIPE_SHADER_FRAGMENT) {
-         if (emit->key.fkey.white_fragments) {
+         if (emit->key.fs.white_fragments) {
             /* Used for XOR logicop mode */
             emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
                                                   emit->nr_hw_temp++ );
@@ -337,14 +337,14 @@ ps30_output(struct svga_shader_emitter *emit,
             emit->true_color_output[idx] = dst_register(SVGA3DREG_COLOROUT, 
                                                         semantic.Index);
          }
-         else if (emit->key.fkey.write_color0_to_n_cbufs) {
+         else if (emit->key.fs.write_color0_to_n_cbufs) {
             /* We'll write color output [0] to all render targets.
              * Prepare all the output registers here, but only when the
              * semantic.Index == 0 so we don't do this more than once.
              */
             if (semantic.Index == 0) {
                unsigned i;
-               for (i = 0; i < emit->key.fkey.write_color0_to_n_cbufs; i++) {
+               for (i = 0; i < emit->key.fs.write_color0_to_n_cbufs; i++) {
                   emit->output_map[idx+i] = dst_register(SVGA3DREG_TEMP,
                                                      emit->nr_hw_temp++);
                   emit->temp_color_output[i] = emit->output_map[idx+i];
@@ -487,7 +487,7 @@ vs30_output(struct svga_shader_emitter *emit,
       /* This has the effect of not declaring psiz (below) and not 
        * emitting the final MOV to true_psiz in the postamble.
        */
-      if (!emit->key.vkey.allow_psiz)
+      if (!emit->key.vs.allow_psiz)
          return TRUE;
 
       emit->true_psiz = dcl.dst;
@@ -517,7 +517,7 @@ vs30_output(struct svga_shader_emitter *emit,
 static ubyte
 svga_tgsi_sampler_type(const struct svga_shader_emitter *emit, int idx)
 {
-   switch (emit->key.fkey.tex[idx].texture_target) {
+   switch (emit->key.tex[idx].texture_target) {
    case PIPE_TEXTURE_1D:
       return SVGA3DSAMP_2D;
    case PIPE_TEXTURE_2D:
index 1a1dac23507ce7da30652b47b25f55598e349491..0b82483ab2ef72132d6b91bff1a80cb883bd590d 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "tgsi/tgsi_scan.h"
 #include "svga_hw_reg.h"
+#include "svga_shader.h"
 #include "svga_tgsi.h"
 #include "svga3d_shaderdefs.h"
 
@@ -130,6 +131,8 @@ struct svga_shader_emitter
    struct svga_arl_consts arl_consts[12];
    int num_arl_consts;
    int current_arl;
+
+   unsigned pstipple_sampler_unit;
 };
 
 
index bac956066a555eb001af6ab1030aa125cda738c5..00c91a4fa61ac26df4e66b52f367534be20f98a8 100644 (file)
@@ -29,6 +29,7 @@
 #include "tgsi/tgsi_parse.h"
 #include "util/u_memory.h"
 #include "util/u_math.h"
+#include "util/u_pstipple.h"
 
 #include "svga_tgsi_emit.h"
 #include "svga_context.h"
@@ -862,7 +863,7 @@ create_common_immediate( struct svga_shader_emitter *emit )
    idx++;
 
    /* Emit constant {2, 0, 0, 0} (only the 2 is used for now) */
-   if (emit->key.vkey.adjust_attrib_range) {
+   if (emit->key.vs.adjust_attrib_range) {
       if (!emit_def_const( emit, SVGA3D_CONST_TYPE_FLOAT,
                            idx, 2.0f, 0.0f, 0.0f, 0.0f ))
          return FALSE;
@@ -1015,7 +1016,7 @@ get_tex_dimensions( struct svga_shader_emitter *emit, int sampler_num )
    struct src_register reg;
 
    /* the width/height indexes start right after constants */
-   idx = emit->key.fkey.tex[sampler_num].width_height_idx +
+   idx = emit->key.tex[sampler_num].width_height_idx +
          emit->info.file_max[TGSI_FILE_CONSTANT] + 1;
 
    reg = src_register( SVGA3DREG_CONST, idx );
@@ -1723,7 +1724,7 @@ emit_tex2(struct svga_shader_emitter *emit,
    texcoord = translate_src_register( emit, &insn->Src[0] );
    sampler = translate_src_register( emit, &insn->Src[1] );
 
-   if (emit->key.fkey.tex[sampler.base.num].unnormalized ||
+   if (emit->key.tex[sampler.base.num].unnormalized ||
        emit->dynamic_branching_level > 0)
       tmp = get_temp( emit );
 
@@ -1755,7 +1756,7 @@ emit_tex2(struct svga_shader_emitter *emit,
 
    /* Explicit normalization of texcoords:
     */
-   if (emit->key.fkey.tex[sampler.base.num].unnormalized) {
+   if (emit->key.tex[sampler.base.num].unnormalized) {
       struct src_register wh = get_tex_dimensions( emit, sampler.base.num );
 
       /* MUL  tmp, SRC0, WH */
@@ -1891,14 +1892,14 @@ emit_tex(struct svga_shader_emitter *emit,
    const unsigned unit = src1.base.num;
 
    /* check for shadow samplers */
-   boolean compare = (emit->key.fkey.tex[unit].compare_mode ==
+   boolean compare = (emit->key.tex[unit].compare_mode ==
                       PIPE_TEX_COMPARE_R_TO_TEXTURE);
 
    /* texture swizzle */
-   boolean swizzle = (emit->key.fkey.tex[unit].swizzle_r != PIPE_SWIZZLE_RED ||
-                      emit->key.fkey.tex[unit].swizzle_g != PIPE_SWIZZLE_GREEN ||
-                      emit->key.fkey.tex[unit].swizzle_b != PIPE_SWIZZLE_BLUE ||
-                      emit->key.fkey.tex[unit].swizzle_a != PIPE_SWIZZLE_ALPHA);
+   boolean swizzle = (emit->key.tex[unit].swizzle_r != PIPE_SWIZZLE_RED ||
+                      emit->key.tex[unit].swizzle_g != PIPE_SWIZZLE_GREEN ||
+                      emit->key.tex[unit].swizzle_b != PIPE_SWIZZLE_BLUE ||
+                      emit->key.tex[unit].swizzle_a != PIPE_SWIZZLE_ALPHA);
 
    boolean saturate = insn->Instruction.Saturate;
 
@@ -1965,7 +1966,7 @@ emit_tex(struct svga_shader_emitter *emit,
 
          /* Compare texture sample value against R component of texcoord */
          if (!emit_select(emit,
-                          emit->key.fkey.tex[unit].compare_func,
+                          emit->key.tex[unit].compare_func,
                           writemask( dst2, TGSI_WRITEMASK_XYZ ),
                           r_coord,
                           tex_src_x))
@@ -1991,10 +1992,10 @@ emit_tex(struct svga_shader_emitter *emit,
       /* swizzle from tex_result to dst (handles saturation too, if any) */
       emit_tex_swizzle(emit,
                        dst, src(tex_result),
-                       emit->key.fkey.tex[unit].swizzle_r,
-                       emit->key.fkey.tex[unit].swizzle_g,
-                       emit->key.fkey.tex[unit].swizzle_b,
-                       emit->key.fkey.tex[unit].swizzle_a);
+                       emit->key.tex[unit].swizzle_r,
+                       emit->key.tex[unit].swizzle_g,
+                       emit->key.tex[unit].swizzle_b,
+                       emit->key.tex[unit].swizzle_a);
    }
 
    return TRUE;
@@ -3113,7 +3114,7 @@ make_immediate(struct svga_shader_emitter *emit,
 static boolean
 emit_vs_preamble(struct svga_shader_emitter *emit)
 {
-   if (!emit->key.vkey.need_prescale) {
+   if (!emit->key.vs.need_prescale) {
       if (!make_immediate( emit, 0, 0, .5, .5,
                            &emit->imm_0055))
          return FALSE;
@@ -3190,7 +3191,7 @@ emit_ps_postamble(struct svga_shader_emitter *emit)
           * logicop workaround.
           */
          if (emit->unit == PIPE_SHADER_FRAGMENT &&
-             emit->key.fkey.white_fragments) {
+             emit->key.fs.white_fragments) {
             struct src_register one = get_one_immediate(emit);
 
             if (!submit_op1( emit,
@@ -3200,7 +3201,7 @@ emit_ps_postamble(struct svga_shader_emitter *emit)
                return FALSE;
          }
          else if (emit->unit == PIPE_SHADER_FRAGMENT &&
-                  i < emit->key.fkey.write_color0_to_n_cbufs) {
+                  i < emit->key.fs.write_color0_to_n_cbufs) {
             /* Write temp color output [0] to true output [i] */
             if (!submit_op1(emit, inst_token(SVGA3DOP_MOV),
                             emit->true_color_output[i],
@@ -3244,7 +3245,7 @@ emit_vs_postamble(struct svga_shader_emitter *emit)
    /* Need to perform various manipulations on vertex position to cope
     * with the different GL and D3D clip spaces.
     */
-   if (emit->key.vkey.need_prescale) {
+   if (emit->key.vs.need_prescale) {
       SVGA3dShaderDestToken temp_pos = emit->temp_pos;
       SVGA3dShaderDestToken depth = emit->depth_pos;
       SVGA3dShaderDestToken pos = emit->true_pos;
@@ -3372,7 +3373,7 @@ emit_light_twoside(struct svga_shader_emitter *emit)
 
    if_token = inst_token( SVGA3DOP_IFC );
 
-   if (emit->key.fkey.front_ccw)
+   if (emit->key.fs.front_ccw)
       if_token.control = SVGA3DOPCOMP_LT;
    else
       if_token.control = SVGA3DOPCOMP_GT;
@@ -3423,7 +3424,7 @@ emit_frontface(struct svga_shader_emitter *emit)
    temp = dst_register( SVGA3DREG_TEMP,
                         emit->nr_hw_temp++ );
 
-   if (emit->key.fkey.front_ccw) {
+   if (emit->key.fs.front_ccw) {
       pass = get_zero_immediate(emit);
       fail = get_one_immediate(emit);
    } else {
@@ -3494,8 +3495,8 @@ emit_inverted_texcoords(struct svga_shader_emitter *emit)
 static boolean
 emit_adjusted_vertex_attribs(struct svga_shader_emitter *emit)
 {
-   unsigned adjust_mask = (emit->key.vkey.adjust_attrib_range |
-                           emit->key.vkey.adjust_attrib_w_1);
+   unsigned adjust_mask = (emit->key.vs.adjust_attrib_range |
+                           emit->key.vs.adjust_attrib_w_1);
  
    while (adjust_mask) {
       /* Adjust vertex attrib range and/or set W component = 1 */
@@ -3506,7 +3507,7 @@ emit_adjusted_vertex_attribs(struct svga_shader_emitter *emit)
       tmp = src_register(SVGA3DREG_TEMP, emit->nr_hw_temp);
       emit->nr_hw_temp++;
 
-      if (emit->key.vkey.adjust_attrib_range & (1 << index)) {
+      if (emit->key.vs.adjust_attrib_range & (1 << index)) {
          /* The vertex input/attribute is supposed to be a signed value in
           * the range [-1,1] but we actually fetched/converted it to the
           * range [0,1].  This most likely happens when the app specifies a
@@ -3558,7 +3559,7 @@ emit_adjusted_vertex_attribs(struct svga_shader_emitter *emit)
             return FALSE;
       }
 
-      if (emit->key.vkey.adjust_attrib_w_1 & (1 << index)) {
+      if (emit->key.vs.adjust_attrib_w_1 & (1 << index)) {
          /* move 1 into W position of tmp */
          if (!submit_op1(emit,
                          inst_token(SVGA3DOP_MOV),
@@ -3588,10 +3589,10 @@ needs_to_create_common_immediate(const struct svga_shader_emitter *emit)
    unsigned i;
 
    if (emit->unit == PIPE_SHADER_FRAGMENT) {
-      if (emit->key.fkey.light_twoside)
+      if (emit->key.fs.light_twoside)
          return TRUE;
 
-      if (emit->key.fkey.white_fragments)
+      if (emit->key.fs.white_fragments)
          return TRUE;
 
       if (emit->emit_frontface)
@@ -3606,16 +3607,16 @@ needs_to_create_common_immediate(const struct svga_shader_emitter *emit)
          return TRUE;
 
       /* look for any PIPE_SWIZZLE_ZERO/ONE terms */
-      for (i = 0; i < emit->key.fkey.num_textures; i++) {
-         if (emit->key.fkey.tex[i].swizzle_r > PIPE_SWIZZLE_ALPHA ||
-             emit->key.fkey.tex[i].swizzle_g > PIPE_SWIZZLE_ALPHA ||
-             emit->key.fkey.tex[i].swizzle_b > PIPE_SWIZZLE_ALPHA ||
-             emit->key.fkey.tex[i].swizzle_a > PIPE_SWIZZLE_ALPHA)
+      for (i = 0; i < emit->key.num_textures; i++) {
+         if (emit->key.tex[i].swizzle_r > PIPE_SWIZZLE_ALPHA ||
+             emit->key.tex[i].swizzle_g > PIPE_SWIZZLE_ALPHA ||
+             emit->key.tex[i].swizzle_b > PIPE_SWIZZLE_ALPHA ||
+             emit->key.tex[i].swizzle_a > PIPE_SWIZZLE_ALPHA)
             return TRUE;
       }
 
-      for (i = 0; i < emit->key.fkey.num_textures; i++) {
-         if (emit->key.fkey.tex[i].compare_mode
+      for (i = 0; i < emit->key.num_textures; i++) {
+         if (emit->key.tex[i].compare_mode
              == PIPE_TEX_COMPARE_R_TO_TEXTURE)
             return TRUE;
       }
@@ -3623,8 +3624,8 @@ needs_to_create_common_immediate(const struct svga_shader_emitter *emit)
    else if (emit->unit == PIPE_SHADER_VERTEX) {
       if (emit->info.opcode_count[TGSI_OPCODE_CMP] >= 1)
          return TRUE;
-      if (emit->key.vkey.adjust_attrib_range ||
-          emit->key.vkey.adjust_attrib_w_1)
+      if (emit->key.vs.adjust_attrib_range ||
+          emit->key.vs.adjust_attrib_w_1)
          return TRUE;
    }
 
@@ -3772,7 +3773,7 @@ svga_shader_emit_helpers(struct svga_shader_emitter *emit)
       if (!emit_ps_preamble( emit ))
          return FALSE;
 
-      if (emit->key.fkey.light_twoside) {
+      if (emit->key.fs.light_twoside) {
          if (!emit_light_twoside( emit ))
             return FALSE;
       }
@@ -3787,14 +3788,14 @@ svga_shader_emit_helpers(struct svga_shader_emitter *emit)
    }
    else {
       assert(emit->unit == PIPE_SHADER_VERTEX);
-      if (emit->key.vkey.adjust_attrib_range ||
-          emit->key.vkey.adjust_attrib_w_1) {
-         if (!emit_adjusted_vertex_attribs(emit))
+      if (emit->key.vs.adjust_attrib_range) {
+         if (!emit_adjusted_vertex_attribs(emit) ||
+             emit->key.vs.adjust_attrib_w_1) {
             return FALSE;
+         }
       }
    }
 
-
    return TRUE;
 }
 
@@ -3808,10 +3809,30 @@ svga_shader_emit_instructions(struct svga_shader_emitter *emit,
                               const struct tgsi_token *tokens)
 {
    struct tgsi_parse_context parse;
+   const struct tgsi_token *new_tokens = NULL;
    boolean ret = TRUE;
    boolean helpers_emitted = FALSE;
    unsigned line_nr = 0;
 
+   if (emit->unit == PIPE_SHADER_FRAGMENT && emit->key.fs.pstipple) {
+      unsigned unit;
+
+      new_tokens = util_pstipple_create_fragment_shader(tokens, &unit, 0);
+
+      if (new_tokens) {
+         /* Setup texture state for stipple */
+         emit->key.tex[unit].texture_target = PIPE_TEXTURE_2D;
+         emit->key.tex[unit].swizzle_r = TGSI_SWIZZLE_X;
+         emit->key.tex[unit].swizzle_g = TGSI_SWIZZLE_Y;
+         emit->key.tex[unit].swizzle_b = TGSI_SWIZZLE_Z;
+         emit->key.tex[unit].swizzle_a = TGSI_SWIZZLE_W;
+
+         emit->pstipple_sampler_unit = unit;
+
+         tokens = new_tokens;
+      }
+   }
+
    tgsi_parse_init( &parse, tokens );
    emit->internal_imm_count = 0;
 
@@ -3878,5 +3899,9 @@ svga_shader_emit_instructions(struct svga_shader_emitter *emit,
 
 done:
    tgsi_parse_free( &parse );
+   if (new_tokens) {
+      tgsi_free_tokens(new_tokens);
+   }
+
    return ret;
 }
index 60928d7a790e5d64646435dbfb25a6100fc46dd3..e4f027b956781ca73ea3b1b063358e16bbb50d9b 100644 (file)
@@ -281,7 +281,7 @@ free_emitter(struct svga_shader_emitter_v10 *emit)
    FREE(emit);
 }
 
-static INLINE boolean
+static inline boolean
 reserve(struct svga_shader_emitter_v10 *emit,
         unsigned nr_dwords)
 {
@@ -1459,7 +1459,7 @@ absolute_src(const struct tgsi_full_src_register *reg)
 
 
 /** Return the named swizzle term from the src register */
-static INLINE unsigned
+static inline unsigned
 get_swizzle(const struct tgsi_full_src_register *reg, unsigned term)
 {
    switch (term) {