summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/svga/svga_surface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/svga/svga_surface.c')
-rw-r--r--src/gallium/drivers/svga/svga_surface.c419
1 files changed, 353 insertions, 66 deletions
diff --git a/src/gallium/drivers/svga/svga_surface.c b/src/gallium/drivers/svga/svga_surface.c
index 85d01546007..79981dcf5ff 100644
--- a/src/gallium/drivers/svga/svga_surface.c
+++ b/src/gallium/drivers/svga/svga_surface.c
@@ -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"
@@ -36,19 +37,21 @@
#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;
}