summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/svga
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/svga')
-rw-r--r--src/gallium/drivers/svga/svga_cmd.c9
-rw-r--r--src/gallium/drivers/svga/svga_cmd.h3
-rw-r--r--src/gallium/drivers/svga/svga_context.h8
-rw-r--r--src/gallium/drivers/svga/svga_pipe_blend.c7
-rw-r--r--src/gallium/drivers/svga/svga_pipe_clear.c4
-rw-r--r--src/gallium/drivers/svga/svga_pipe_misc.c4
-rw-r--r--src/gallium/drivers/svga/svga_pipe_sampler.c4
-rw-r--r--src/gallium/drivers/svga/svga_pipe_vertex.c40
-rw-r--r--src/gallium/drivers/svga/svga_screen.c18
-rw-r--r--src/gallium/drivers/svga/svga_screen_buffer.c403
-rw-r--r--src/gallium/drivers/svga/svga_screen_buffer.h134
-rw-r--r--src/gallium/drivers/svga/svga_screen_texture.c167
-rw-r--r--src/gallium/drivers/svga/svga_screen_texture.h2
-rw-r--r--src/gallium/drivers/svga/svga_state_framebuffer.c287
-rw-r--r--src/gallium/drivers/svga/svga_state_need_swtnl.c14
-rw-r--r--src/gallium/drivers/svga/svga_state_rss.c13
-rw-r--r--src/gallium/drivers/svga/svga_state_vdecl.c59
-rw-r--r--src/gallium/drivers/svga/svga_state_vs.c4
-rw-r--r--src/gallium/drivers/svga/svga_swtnl_state.c4
-rw-r--r--src/gallium/drivers/svga/svga_tgsi_emit.h2
-rw-r--r--src/gallium/drivers/svga/svga_tgsi_insn.c65
-rw-r--r--src/gallium/drivers/svga/svga_winsys.h33
22 files changed, 716 insertions, 568 deletions
diff --git a/src/gallium/drivers/svga/svga_cmd.c b/src/gallium/drivers/svga/svga_cmd.c
index a0da7d7e5d..04307d17fe 100644
--- a/src/gallium/drivers/svga/svga_cmd.c
+++ b/src/gallium/drivers/svga/svga_cmd.c
@@ -478,7 +478,8 @@ SVGA3D_BufferDMA(struct svga_winsys_context *swc,
struct svga_winsys_surface *host,
SVGA3dTransferType transfer, // IN
uint32 size, // IN
- uint32 offset, // IN
+ uint32 guest_offset, // IN
+ uint32 host_offset, // IN
SVGA3dSurfaceDMAFlags flags) // IN
{
SVGA3dCmdSurfaceDMA *cmd;
@@ -517,19 +518,19 @@ SVGA3D_BufferDMA(struct svga_winsys_context *swc,
cmd->transfer = transfer;
box = (SVGA3dCopyBox *)&cmd[1];
- box->x = offset;
+ box->x = host_offset;
box->y = 0;
box->z = 0;
box->w = size;
box->h = 1;
box->d = 1;
- box->srcx = offset;
+ box->srcx = guest_offset;
box->srcy = 0;
box->srcz = 0;
pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + sizeof *box);
pSuffix->suffixSize = sizeof *pSuffix;
- pSuffix->maximumOffset = offset + size;
+ pSuffix->maximumOffset = guest_offset + size;
pSuffix->flags = flags;
swc->commit(swc);
diff --git a/src/gallium/drivers/svga/svga_cmd.h b/src/gallium/drivers/svga/svga_cmd.h
index 8041054769..da9fc4355f 100644
--- a/src/gallium/drivers/svga/svga_cmd.h
+++ b/src/gallium/drivers/svga/svga_cmd.h
@@ -111,7 +111,8 @@ SVGA3D_BufferDMA(struct svga_winsys_context *swc,
struct svga_winsys_surface *host,
SVGA3dTransferType transfer,
uint32 size,
- uint32 offset,
+ uint32 guest_offset,
+ uint32 host_offset,
SVGA3dSurfaceDMAFlags flags);
/*
diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h
index b1022c3c99..1f66437dfe 100644
--- a/src/gallium/drivers/svga/svga_context.h
+++ b/src/gallium/drivers/svga/svga_context.h
@@ -169,6 +169,11 @@ struct svga_sampler_state {
unsigned view_max_lod;
};
+struct svga_velems_state {
+ unsigned count;
+ struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS];
+};
+
/* Use to calculate differences between state emitted to hardware and
* current driver-calculated state.
*/
@@ -178,13 +183,13 @@ struct svga_state
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_velems_state *velems;
struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; /* or texture ID's? */
struct svga_fragment_shader *fs;
struct svga_vertex_shader *vs;
struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS];
- struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS];
struct pipe_buffer *cb[PIPE_SHADER_TYPES];
struct pipe_framebuffer_state framebuffer;
@@ -204,7 +209,6 @@ struct svga_state
unsigned num_samplers;
unsigned num_sampler_views;
- unsigned num_vertex_elements;
unsigned num_vertex_buffers;
unsigned reduced_prim;
diff --git a/src/gallium/drivers/svga/svga_pipe_blend.c b/src/gallium/drivers/svga/svga_pipe_blend.c
index b60117f090..594eec7166 100644
--- a/src/gallium/drivers/svga/svga_pipe_blend.c
+++ b/src/gallium/drivers/svga/svga_pipe_blend.c
@@ -92,6 +92,7 @@ svga_create_blend_state(struct pipe_context *pipe,
if (templ->logicop_enable) {
switch (templ->logicop_func) {
case PIPE_LOGICOP_XOR:
+ case PIPE_LOGICOP_INVERT:
blend->need_white_fragments = TRUE;
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
@@ -125,12 +126,6 @@ svga_create_blend_state(struct pipe_context *pipe,
blend->rt[i].dstblend = SVGA3D_BLENDOP_ONE;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
break;
- case PIPE_LOGICOP_INVERT:
- blend->rt[i].blend_enable = TRUE;
- blend->rt[i].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
- blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
- blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
- break;
case PIPE_LOGICOP_AND:
/* Approximate with minimum - works for the 0 & anything case: */
blend->rt[i].blend_enable = TRUE;
diff --git a/src/gallium/drivers/svga/svga_pipe_clear.c b/src/gallium/drivers/svga/svga_pipe_clear.c
index 409b3b41cb..8483a3fad7 100644
--- a/src/gallium/drivers/svga/svga_pipe_clear.c
+++ b/src/gallium/drivers/svga/svga_pipe_clear.c
@@ -54,7 +54,7 @@ try_clear(struct svga_context *svga,
if ((buffers & PIPE_CLEAR_COLOR) && fb->cbufs[0]) {
flags |= SVGA3D_CLEAR_COLOR;
- util_pack_color(rgba, PIPE_FORMAT_A8R8G8B8_UNORM, &uc);
+ util_pack_color(rgba, PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
rect.w = fb->cbufs[0]->width;
rect.h = fb->cbufs[0]->height;
@@ -63,7 +63,7 @@ try_clear(struct svga_context *svga,
if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && fb->zsbuf) {
flags |= SVGA3D_CLEAR_DEPTH;
- if (svga->curr.framebuffer.zsbuf->format == PIPE_FORMAT_Z24S8_UNORM)
+ if (svga->curr.framebuffer.zsbuf->format == PIPE_FORMAT_S8Z24_UNORM)
flags |= SVGA3D_CLEAR_STENCIL;
rect.w = MAX2(rect.w, fb->zsbuf->width);
diff --git a/src/gallium/drivers/svga/svga_pipe_misc.c b/src/gallium/drivers/svga/svga_pipe_misc.c
index 49b43bebc2..95bf0e6f91 100644
--- a/src/gallium/drivers/svga/svga_pipe_misc.c
+++ b/src/gallium/drivers/svga/svga_pipe_misc.c
@@ -118,10 +118,10 @@ static void svga_set_framebuffer_state(struct pipe_context *pipe,
case PIPE_FORMAT_Z16_UNORM:
svga->curr.depthscale = 1.0f / DEPTH_BIAS_SCALE_FACTOR_D16;
break;
- case PIPE_FORMAT_S8Z24_UNORM:
- case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_Z24S8_UNORM:
case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
svga->curr.depthscale = 1.0f / DEPTH_BIAS_SCALE_FACTOR_D24S8;
break;
case PIPE_FORMAT_Z32_UNORM:
diff --git a/src/gallium/drivers/svga/svga_pipe_sampler.c b/src/gallium/drivers/svga/svga_pipe_sampler.c
index 50fe962b28..ebd1b94997 100644
--- a/src/gallium/drivers/svga/svga_pipe_sampler.c
+++ b/src/gallium/drivers/svga/svga_pipe_sampler.c
@@ -155,7 +155,7 @@ static void svga_bind_sampler_states(struct pipe_context *pipe,
/* Check for no-op */
if (num == svga->curr.num_samplers &&
!memcmp(svga->curr.sampler, sampler, num * sizeof(void *))) {
- debug_printf("sampler noop\n");
+ if (0) debug_printf("sampler noop\n");
return;
}
@@ -226,7 +226,7 @@ static void svga_set_sampler_views(struct pipe_context *pipe,
if (!views[i])
continue;
- if (views[i]->texture->format == PIPE_FORMAT_A8R8G8B8_SRGB)
+ if (views[i]->texture->format == PIPE_FORMAT_B8G8R8A8_SRGB)
flag_srgb |= 1 << i;
if (views[i]->texture->target == PIPE_TEXTURE_1D)
diff --git a/src/gallium/drivers/svga/svga_pipe_vertex.c b/src/gallium/drivers/svga/svga_pipe_vertex.c
index ffc0f99565..1715a47fc6 100644
--- a/src/gallium/drivers/svga/svga_pipe_vertex.c
+++ b/src/gallium/drivers/svga/svga_pipe_vertex.c
@@ -26,6 +26,7 @@
#include "util/u_inlines.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
+#include "util/u_memory.h"
#include "tgsi/tgsi_parse.h"
#include "svga_screen.h"
@@ -49,7 +50,7 @@ static void svga_set_vertex_buffers(struct pipe_context *pipe,
/* Adjust refcounts */
for (i = 0; i < count; i++) {
pipe_buffer_reference(&svga->curr.vb[i].buffer, buffers[i].buffer);
- if (svga_buffer(buffers[i].buffer)->user)
+ if (svga_buffer_is_user_buffer(buffers[i].buffer))
any_user_buffer = TRUE;
}
@@ -64,20 +65,37 @@ static void svga_set_vertex_buffers(struct pipe_context *pipe,
svga->dirty |= SVGA_NEW_VBUFFER;
}
-static void svga_set_vertex_elements(struct pipe_context *pipe,
- unsigned count,
- const struct pipe_vertex_element *elements)
+
+static void *
+svga_create_vertex_elements_state(struct pipe_context *pipe,
+ unsigned count,
+ const struct pipe_vertex_element *attribs)
{
- struct svga_context *svga = svga_context(pipe);
- unsigned i;
+ struct svga_velems_state *velems;
+ assert(count <= PIPE_MAX_ATTRIBS);
+ velems = (struct svga_velems_state *) MALLOC(sizeof(struct svga_velems_state));
+ if (velems) {
+ velems->count = count;
+ memcpy(velems->velem, attribs, sizeof(*attribs) * count);
+ }
+ return velems;
+}
- for (i = 0; i < count; i++)
- svga->curr.ve[i] = elements[i];
+static void svga_bind_vertex_elements_state(struct pipe_context *pipe,
+ void *velems)
+{
+ struct svga_context *svga = svga_context(pipe);
+ struct svga_velems_state *svga_velems = (struct svga_velems_state *) velems;
- svga->curr.num_vertex_elements = count;
+ svga->curr.velems = svga_velems;
svga->dirty |= SVGA_NEW_VELEMENT;
}
+static void svga_delete_vertex_elements_state(struct pipe_context *pipe,
+ void *velems)
+{
+ FREE(velems);
+}
void svga_cleanup_vertex_state( struct svga_context *svga )
{
@@ -91,7 +109,9 @@ void svga_cleanup_vertex_state( struct svga_context *svga )
void svga_init_vertex_functions( struct svga_context *svga )
{
svga->pipe.set_vertex_buffers = svga_set_vertex_buffers;
- svga->pipe.set_vertex_elements = svga_set_vertex_elements;
+ svga->pipe.create_vertex_elements_state = svga_create_vertex_elements_state;
+ svga->pipe.bind_vertex_elements_state = svga_bind_vertex_elements_state;
+ svga->pipe.delete_vertex_elements_state = svga_delete_vertex_elements_state;
}
diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c
index 414ac52e1f..6022c38cfc 100644
--- a/src/gallium/drivers/svga/svga_screen.c
+++ b/src/gallium/drivers/svga/svga_screen.c
@@ -196,23 +196,23 @@ svga_translate_format_cap(enum pipe_format format)
{
switch(format) {
- case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8;
- case PIPE_FORMAT_X8R8G8B8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8;
- case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_B5G6R5_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_R5G6B5;
- case PIPE_FORMAT_A1R5G5B5_UNORM:
+ case PIPE_FORMAT_B5G5R5A1_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5;
- case PIPE_FORMAT_A4R4G4B4_UNORM:
+ case PIPE_FORMAT_B4G4R4A4_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4;
case PIPE_FORMAT_Z16_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_Z_D16;
- case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8;
- case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8;
case PIPE_FORMAT_A8_UNORM:
@@ -254,8 +254,8 @@ svga_is_format_supported( struct pipe_screen *screen,
/* Often unsupported/problematic. This means we end up with the same
* visuals for all virtual hardware implementations.
*/
- case PIPE_FORMAT_A4R4G4B4_UNORM:
- case PIPE_FORMAT_A1R5G5B5_UNORM:
+ case PIPE_FORMAT_B4G4R4A4_UNORM:
+ case PIPE_FORMAT_B5G5R5A1_UNORM:
return FALSE;
/* Simulate ability to render into compressed textures */
diff --git a/src/gallium/drivers/svga/svga_screen_buffer.c b/src/gallium/drivers/svga/svga_screen_buffer.c
index c9e9bef540..1ff6a3a5b3 100644
--- a/src/gallium/drivers/svga/svga_screen_buffer.c
+++ b/src/gallium/drivers/svga/svga_screen_buffer.c
@@ -83,7 +83,7 @@ svga_buffer_create_host_surface(struct svga_screen *ss,
* as svga_screen_surface_create might have passed a recycled host
* buffer.
*/
- sbuf->hw.flags.discard = TRUE;
+ sbuf->dma.flags.discard = TRUE;
SVGA_DBG(DEBUG_DMA, " --> got sid %p sz %d (buffer)\n", sbuf->handle, sbuf->base.size);
}
@@ -109,10 +109,10 @@ svga_buffer_destroy_hw_storage(struct svga_screen *ss, struct svga_buffer *sbuf)
struct svga_winsys_screen *sws = ss->sws;
assert(!sbuf->map.count);
- assert(sbuf->hw.buf);
- if(sbuf->hw.buf) {
- sws->buffer_destroy(sws, sbuf->hw.buf);
- sbuf->hw.buf = NULL;
+ assert(sbuf->hwbuf);
+ if(sbuf->hwbuf) {
+ sws->buffer_destroy(sws, sbuf->hwbuf);
+ sbuf->hwbuf = NULL;
}
}
@@ -151,16 +151,18 @@ static INLINE enum pipe_error
svga_buffer_create_hw_storage(struct svga_screen *ss,
struct svga_buffer *sbuf)
{
- if(!sbuf->hw.buf) {
+ assert(!sbuf->user);
+
+ if(!sbuf->hwbuf) {
unsigned alignment = sbuf->base.alignment;
unsigned usage = 0;
unsigned size = sbuf->base.size;
- sbuf->hw.buf = svga_winsys_buffer_create(ss, alignment, usage, size);
- if(!sbuf->hw.buf)
+ sbuf->hwbuf = svga_winsys_buffer_create(ss, alignment, usage, size);
+ if(!sbuf->hwbuf)
return PIPE_ERROR_OUT_OF_MEMORY;
- assert(!sbuf->needs_flush);
+ assert(!sbuf->dma.pending);
}
return PIPE_OK;
@@ -175,12 +177,11 @@ svga_buffer_upload_command(struct svga_context *svga,
struct svga_buffer *sbuf)
{
struct svga_winsys_context *swc = svga->swc;
- struct svga_winsys_buffer *guest = sbuf->hw.buf;
+ struct svga_winsys_buffer *guest = sbuf->hwbuf;
struct svga_winsys_surface *host = sbuf->handle;
SVGA3dTransferType transfer = SVGA3D_WRITE_HOST_VRAM;
- SVGA3dSurfaceDMAFlags flags = sbuf->hw.flags;
SVGA3dCmdSurfaceDMA *cmd;
- uint32 numBoxes = sbuf->hw.num_ranges;
+ uint32 numBoxes = sbuf->map.num_ranges;
SVGA3dCopyBox *boxes;
SVGA3dCmdSurfaceDMASuffix *pSuffix;
unsigned region_flags;
@@ -218,8 +219,8 @@ svga_buffer_upload_command(struct svga_context *svga,
cmd->transfer = transfer;
- sbuf->hw.boxes = (SVGA3dCopyBox *)&cmd[1];
- sbuf->hw.svga = svga;
+ sbuf->dma.boxes = (SVGA3dCopyBox *)&cmd[1];
+ sbuf->dma.svga = svga;
/* Increment reference count */
dummy = NULL;
@@ -228,9 +229,11 @@ svga_buffer_upload_command(struct svga_context *svga,
pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + numBoxes * sizeof *boxes);
pSuffix->suffixSize = sizeof *pSuffix;
pSuffix->maximumOffset = sbuf->base.size;
- pSuffix->flags = flags;
+ pSuffix->flags = sbuf->dma.flags;
+
+ SVGA_FIFOCommitAll(swc);
- swc->commit(swc);
+ sbuf->dma.flags.discard = FALSE;
return PIPE_OK;
}
@@ -248,10 +251,10 @@ svga_buffer_upload_flush(struct svga_context *svga,
unsigned i;
assert(sbuf->handle);
- assert(sbuf->hw.buf);
- assert(sbuf->hw.num_ranges);
- assert(sbuf->hw.svga == svga);
- assert(sbuf->hw.boxes);
+ assert(sbuf->hwbuf);
+ assert(sbuf->map.num_ranges);
+ assert(sbuf->dma.svga == svga);
+ assert(sbuf->dma.boxes);
/*
* Patch the DMA command with the final copy box.
@@ -259,36 +262,33 @@ svga_buffer_upload_flush(struct svga_context *svga,
SVGA_DBG(DEBUG_DMA, "dma to sid %p\n", sbuf->handle);
- boxes = sbuf->hw.boxes;
- for(i = 0; i < sbuf->hw.num_ranges; ++i) {
+ boxes = sbuf->dma.boxes;
+ for(i = 0; i < sbuf->map.num_ranges; ++i) {
SVGA_DBG(DEBUG_DMA, " bytes %u - %u\n",
- sbuf->hw.ranges[i].start, sbuf->hw.ranges[i].end);
+ sbuf->map.ranges[i].start, sbuf->map.ranges[i].end);
- boxes[i].x = sbuf->hw.ranges[i].start;
+ boxes[i].x = sbuf->map.ranges[i].start;
boxes[i].y = 0;
boxes[i].z = 0;
- boxes[i].w = sbuf->hw.ranges[i].end - sbuf->hw.ranges[i].start;
+ boxes[i].w = sbuf->map.ranges[i].end - sbuf->map.ranges[i].start;
boxes[i].h = 1;
boxes[i].d = 1;
- boxes[i].srcx = sbuf->hw.ranges[i].start;
+ boxes[i].srcx = sbuf->map.ranges[i].start;
boxes[i].srcy = 0;
boxes[i].srcz = 0;
}
- sbuf->hw.num_ranges = 0;
- memset(&sbuf->hw.flags, 0, sizeof sbuf->hw.flags);
+ sbuf->map.num_ranges = 0;
assert(sbuf->head.prev && sbuf->head.next);
LIST_DEL(&sbuf->head);
#ifdef DEBUG
sbuf->head.next = sbuf->head.prev = NULL;
#endif
- sbuf->needs_flush = FALSE;
-
- sbuf->hw.svga = NULL;
- sbuf->hw.boxes = NULL;
+ sbuf->dma.pending = FALSE;
- sbuf->host_written = TRUE;
+ sbuf->dma.svga = NULL;
+ sbuf->dma.boxes = NULL;
/* Decrement reference count */
pipe_reference(&(sbuf->base.reference), NULL);
@@ -297,7 +297,7 @@ svga_buffer_upload_flush(struct svga_context *svga,
/**
- * Queue a DMA upload of a range of this buffer to the host.
+ * Note a dirty range.
*
* This function only notes the range down. It doesn't actually emit a DMA
* upload command. That only happens when a context tries to refer to this
@@ -306,15 +306,24 @@ svga_buffer_upload_flush(struct svga_context *svga,
* We try to lump as many contiguous DMA transfers together as possible.
*/
static void
-svga_buffer_upload_queue(struct svga_buffer *sbuf,
- unsigned start,
- unsigned end)
+svga_buffer_add_range(struct svga_buffer *sbuf,
+ unsigned start,
+ unsigned end)
{
unsigned i;
+ unsigned nearest_range;
+ unsigned nearest_dist;
- assert(sbuf->hw.buf);
assert(end > start);
+ if (sbuf->map.num_ranges < SVGA_BUFFER_MAX_RANGES) {
+ nearest_range = sbuf->map.num_ranges;
+ nearest_dist = ~0;
+ } else {
+ nearest_range = SVGA_BUFFER_MAX_RANGES - 1;
+ nearest_dist = 0;
+ }
+
/*
* Try to grow one of the ranges.
*
@@ -325,12 +334,34 @@ svga_buffer_upload_queue(struct svga_buffer *sbuf,
* buffer should be flushed.
*/
- for(i = 0; i < sbuf->hw.num_ranges; ++i) {
- if(start <= sbuf->hw.ranges[i].end && sbuf->hw.ranges[i].start <= end) {
- sbuf->hw.ranges[i].start = MIN2(sbuf->hw.ranges[i].start, start);
- sbuf->hw.ranges[i].end = MAX2(sbuf->hw.ranges[i].end, end);
+ for(i = 0; i < sbuf->map.num_ranges; ++i) {
+ int left_dist;
+ int right_dist;
+ int dist;
+
+ left_dist = start - sbuf->map.ranges[i].end;
+ right_dist = sbuf->map.ranges[i].start - end;
+ dist = MAX2(left_dist, right_dist);
+
+ if (dist <= 0) {
+ /*
+ * Ranges are contiguous or overlapping -- extend this one and return.
+ */
+
+ sbuf->map.ranges[i].start = MIN2(sbuf->map.ranges[i].start, start);
+ sbuf->map.ranges[i].end = MAX2(sbuf->map.ranges[i].end, end);
return;
}
+ else {
+ /*
+ * Discontiguous ranges -- keep track of the nearest range.
+ */
+
+ if (dist < nearest_dist) {
+ nearest_range = i;
+ nearest_dist = dist;
+ }
+ }
}
/*
@@ -338,20 +369,34 @@ svga_buffer_upload_queue(struct svga_buffer *sbuf,
* pending DMA upload and start clean.
*/
- if(sbuf->needs_flush)
- svga_buffer_upload_flush(sbuf->hw.svga, sbuf);
+ if(sbuf->dma.pending)
+ svga_buffer_upload_flush(sbuf->dma.svga, sbuf);
- assert(!sbuf->needs_flush);
- assert(!sbuf->hw.svga);
- assert(!sbuf->hw.boxes);
+ assert(!sbuf->dma.pending);
+ assert(!sbuf->dma.svga);
+ assert(!sbuf->dma.boxes);
- /*
- * Add a new range.
- */
+ if (sbuf->map.num_ranges < SVGA_BUFFER_MAX_RANGES) {
+ /*
+ * Add a new range.
+ */
+
+ sbuf->map.ranges[sbuf->map.num_ranges].start = start;
+ sbuf->map.ranges[sbuf->map.num_ranges].end = end;
+ ++sbuf->map.num_ranges;
+ } else {
+ /*
+ * Everything else failed, so just extend the nearest range.
+ *
+ * It is OK to do this because we always keep a local copy of the
+ * host buffer data, for SW TNL, and the host never modifies the buffer.
+ */
- sbuf->hw.ranges[sbuf->hw.num_ranges].start = start;
- sbuf->hw.ranges[sbuf->hw.num_ranges].end = end;
- ++sbuf->hw.num_ranges;
+ assert(nearest_range < SVGA_BUFFER_MAX_RANGES);
+ assert(nearest_range < sbuf->map.num_ranges);
+ sbuf->map.ranges[nearest_range].start = MIN2(sbuf->map.ranges[nearest_range].start, start);
+ sbuf->map.ranges[nearest_range].end = MAX2(sbuf->map.ranges[nearest_range].end, end);
+ }
}
@@ -366,55 +411,30 @@ svga_buffer_map_range( struct pipe_screen *screen,
struct svga_buffer *sbuf = svga_buffer( buf );
void *map;
- if(sbuf->swbuf) {
+ if (!sbuf->swbuf && !sbuf->hwbuf) {
+ if (svga_buffer_create_hw_storage(ss, sbuf) != PIPE_OK) {
+ /*
+ * We can't create a hardware buffer big enough, so create a malloc
+ * buffer instead.
+ */
+
+ debug_printf("%s: failed to allocate %u KB of DMA, splitting DMA transfers\n",
+ __FUNCTION__,
+ (sbuf->base.size + 1023)/1024);
+
+ sbuf->swbuf = align_malloc(sbuf->base.size, sbuf->base.alignment);
+ }
+ }
+
+ if (sbuf->swbuf) {
/* User/malloc buffer */
map = sbuf->swbuf;
}
+ else if (sbuf->hwbuf) {
+ map = sws->buffer_map(sws, sbuf->hwbuf, usage);
+ }
else {
- if(!sbuf->hw.buf) {
- if(svga_buffer_create_hw_storage(ss, sbuf) != PIPE_OK)
- return NULL;
-
- /* Populate the hardware storage if the host surface pre-existed */
- if(sbuf->host_written) {
- SVGA3dSurfaceDMAFlags flags;
- enum pipe_error ret;
- struct pipe_fence_handle *fence = NULL;
-
- assert(sbuf->handle);
-
- SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "dma from sid %p (buffer), bytes %u - %u\n",
- sbuf->handle, 0, sbuf->base.size);
-
- memset(&flags, 0, sizeof flags);
-
- ret = SVGA3D_BufferDMA(ss->swc,
- sbuf->hw.buf,
- sbuf->handle,
- SVGA3D_READ_HOST_VRAM,
- sbuf->base.size,
- 0,
- flags);
- if(ret != PIPE_OK) {
- ss->swc->flush(ss->swc, NULL);
-
- ret = SVGA3D_BufferDMA(ss->swc,
- sbuf->hw.buf,
- sbuf->handle,
- SVGA3D_READ_HOST_VRAM,
- sbuf->base.size,
- 0,
- flags);
- assert(ret == PIPE_OK);
- }
-
- ss->swc->flush(ss->swc, &fence);
- sws->fence_finish(sws, fence, 0);
- sws->fence_reference(sws, &fence, NULL);
- }
- }
-
- map = sws->buffer_map(sws, sbuf->hw.buf, usage);
+ map = NULL;
}
if(map) {
@@ -447,8 +467,7 @@ svga_buffer_flush_mapped_range( struct pipe_screen *screen,
assert(sbuf->map.writing);
if(sbuf->map.writing) {
assert(sbuf->map.flush_explicit);
- if(sbuf->hw.buf)
- svga_buffer_upload_queue(sbuf, offset, offset + length);
+ svga_buffer_add_range(sbuf, offset, offset + length);
}
pipe_mutex_unlock(ss->swc_mutex);
}
@@ -467,16 +486,15 @@ svga_buffer_unmap( struct pipe_screen *screen,
if(sbuf->map.count)
--sbuf->map.count;
- if(sbuf->hw.buf)
- sws->buffer_unmap(sws, sbuf->hw.buf);
+ if(sbuf->hwbuf)
+ sws->buffer_unmap(sws, sbuf->hwbuf);
if(sbuf->map.writing) {
if(!sbuf->map.flush_explicit) {
/* No mapped range was flushed -- flush the whole buffer */
SVGA_DBG(DEBUG_DMA, "flushing the whole buffer\n");
- if(sbuf->hw.buf)
- svga_buffer_upload_queue(sbuf, 0, sbuf->base.size);
+ svga_buffer_add_range(sbuf, 0, sbuf->base.size);
}
sbuf->map.writing = FALSE;
@@ -494,12 +512,15 @@ svga_buffer_destroy( struct pipe_buffer *buf )
assert(!p_atomic_read(&buf->reference.count));
- assert(!sbuf->needs_flush);
+ assert(!sbuf->dma.pending);
if(sbuf->handle)
svga_buffer_destroy_host_surface(ss, sbuf);
- if(sbuf->hw.buf)
+ if(sbuf->uploaded.buffer)
+ pipe_buffer_reference(&sbuf->uploaded.buffer, NULL);
+
+ if(sbuf->hwbuf)
svga_buffer_destroy_hw_storage(ss, sbuf);
if(sbuf->swbuf && !sbuf->user)
@@ -596,13 +617,14 @@ svga_screen_init_buffer_functions(struct pipe_screen *screen)
}
-/**
- * Copy the contents of the user buffer / malloc buffer to a hardware buffer.
+/**
+ * Copy the contents of the malloc buffer to a hardware buffer.
*/
static INLINE enum pipe_error
svga_buffer_update_hw(struct svga_screen *ss, struct svga_buffer *sbuf)
{
- if(!sbuf->hw.buf) {
+ assert(!sbuf->user);
+ if(!sbuf->hwbuf) {
enum pipe_error ret;
void *map;
@@ -611,20 +633,20 @@ svga_buffer_update_hw(struct svga_screen *ss, struct svga_buffer *sbuf)
return PIPE_ERROR;
ret = svga_buffer_create_hw_storage(ss, sbuf);
- assert(ret == PIPE_OK);
if(ret != PIPE_OK)
return ret;
pipe_mutex_lock(ss->swc_mutex);
- map = ss->sws->buffer_map(ss->sws, sbuf->hw.buf, PIPE_BUFFER_USAGE_CPU_WRITE);
+ map = ss->sws->buffer_map(ss->sws, sbuf->hwbuf, PIPE_BUFFER_USAGE_CPU_WRITE);
assert(map);
if(!map) {
pipe_mutex_unlock(ss->swc_mutex);
- return PIPE_ERROR_OUT_OF_MEMORY;
+ svga_buffer_destroy_hw_storage(ss, sbuf);
+ return PIPE_ERROR;
}
memcpy(map, sbuf->swbuf, sbuf->base.size);
- ss->sws->buffer_unmap(ss->sws, sbuf->hw.buf);
+ ss->sws->buffer_unmap(ss->sws, sbuf->hwbuf);
/* This user/malloc buffer is now indistinguishable from a gpu buffer */
assert(!sbuf->map.count);
@@ -636,10 +658,89 @@ svga_buffer_update_hw(struct svga_screen *ss, struct svga_buffer *sbuf)
sbuf->swbuf = NULL;
}
- svga_buffer_upload_queue(sbuf, 0, sbuf->base.size);
+ pipe_mutex_unlock(ss->swc_mutex);
}
- pipe_mutex_unlock(ss->swc_mutex);
+ return PIPE_OK;
+}
+
+
+/**
+ * Upload the buffer to the host in a piecewise fashion.
+ *
+ * Used when the buffer is too big to fit in the GMR aperture.
+ */
+static INLINE enum pipe_error
+svga_buffer_upload_piecewise(struct svga_screen *ss,
+ struct svga_context *svga,
+ struct svga_buffer *sbuf)
+{
+ struct svga_winsys_screen *sws = ss->sws;
+ const unsigned alignment = sizeof(void *);
+ const unsigned usage = 0;
+ unsigned i;
+
+ assert(sbuf->map.num_ranges);
+ assert(!sbuf->dma.pending);
+
+ SVGA_DBG(DEBUG_DMA, "dma to sid %p\n", sbuf->handle);
+
+ for (i = 0; i < sbuf->map.num_ranges; ++i) {
+ struct svga_buffer_range *range = &sbuf->map.ranges[i];
+ unsigned offset = range->start;
+ unsigned size = range->end - range->start;
+
+ while (offset < range->end) {
+ struct svga_winsys_buffer *hwbuf;
+ uint8_t *map;
+ enum pipe_error ret;
+
+ if (offset + size > range->end)
+ size = range->end - offset;
+
+ hwbuf = svga_winsys_buffer_create(ss, alignment, usage, size);
+ while (!hwbuf) {
+ size /= 2;
+ if (!size)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+ hwbuf = svga_winsys_buffer_create(ss, alignment, usage, size);
+ }
+
+ SVGA_DBG(DEBUG_DMA, " bytes %u - %u\n",
+ offset, offset + size);
+
+ map = sws->buffer_map(sws, hwbuf,
+ PIPE_BUFFER_USAGE_CPU_WRITE |
+ PIPE_BUFFER_USAGE_DISCARD);
+ assert(map);
+ if (map) {
+ memcpy(map, sbuf->swbuf, size);
+ sws->buffer_unmap(sws, hwbuf);
+ }
+
+ ret = SVGA3D_BufferDMA(svga->swc,
+ hwbuf, sbuf->handle,
+ SVGA3D_WRITE_HOST_VRAM,
+ size, 0, offset, sbuf->dma.flags);
+ if(ret != PIPE_OK) {
+ svga_context_flush(svga, NULL);
+ ret = SVGA3D_BufferDMA(svga->swc,
+ hwbuf, sbuf->handle,
+ SVGA3D_WRITE_HOST_VRAM,
+ size, 0, offset, sbuf->dma.flags);
+ assert(ret == PIPE_OK);
+ }
+
+ sbuf->dma.flags.discard = FALSE;
+
+ sws->buffer_destroy(sws, hwbuf);
+
+ offset += size;
+ }
+ }
+
+ sbuf->map.num_ranges = 0;
+
return PIPE_OK;
}
@@ -659,34 +760,74 @@ svga_buffer_handle(struct svga_context *svga,
sbuf = svga_buffer(buf);
assert(!sbuf->map.count);
+ assert(!sbuf->user);
if(!sbuf->handle) {
ret = svga_buffer_create_host_surface(ss, sbuf);
if(ret != PIPE_OK)
return NULL;
-
- ret = svga_buffer_update_hw(ss, sbuf);
- if(ret != PIPE_OK)
- return NULL;
}
- if(!sbuf->needs_flush && sbuf->hw.num_ranges) {
- /* Queue the buffer for flushing */
- ret = svga_buffer_upload_command(svga, sbuf);
- if(ret != PIPE_OK)
- /* XXX: Should probably have a richer return value */
- return NULL;
-
- assert(sbuf->hw.svga == svga);
+ assert(sbuf->handle);
+
+ if (sbuf->map.num_ranges) {
+ if (!sbuf->dma.pending) {
+ /*
+ * No pending DMA upload yet, so insert a DMA upload command now.
+ */
+
+ /*
+ * Migrate the data from swbuf -> hwbuf if necessary.
+ */
+ ret = svga_buffer_update_hw(ss, sbuf);
+ if (ret == PIPE_OK) {
+ /*
+ * Queue a dma command.
+ */
+
+ ret = svga_buffer_upload_command(svga, sbuf);
+ if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
+ svga_context_flush(svga, NULL);
+ ret = svga_buffer_upload_command(svga, sbuf);
+ assert(ret == PIPE_OK);
+ }
+ if (ret == PIPE_OK) {
+ sbuf->dma.pending = TRUE;
+ assert(!sbuf->head.prev && !sbuf->head.next);
+ LIST_ADDTAIL(&sbuf->head, &svga->dirty_buffers);
+ }
+ }
+ else if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
+ /*
+ * The buffer is too big to fit in the GMR aperture, so break it in
+ * smaller pieces.
+ */
+ ret = svga_buffer_upload_piecewise(ss, svga, sbuf);
+ }
- sbuf->needs_flush = TRUE;
- assert(!sbuf->head.prev && !sbuf->head.next);
- LIST_ADDTAIL(&sbuf->head, &svga->dirty_buffers);
+ if (ret != PIPE_OK) {
+ /*
+ * Something unexpected happened above. There is very little that
+ * we can do other than proceeding while ignoring the dirty ranges.
+ */
+ assert(0);
+ sbuf->map.num_ranges = 0;
+ }
+ }
+ else {
+ /*
+ * There a pending dma already. Make sure it is from this context.
+ */
+ assert(sbuf->dma.svga == svga);
+ }
}
+ assert(!sbuf->map.num_ranges || sbuf->dma.pending);
+
return sbuf->handle;
}
+
struct pipe_buffer *
svga_screen_buffer_wrap_surface(struct pipe_screen *screen,
enum SVGA3dSurfaceFormat format,
@@ -739,7 +880,7 @@ svga_context_flush_buffers(struct svga_context *svga)
sbuf = LIST_ENTRY(struct svga_buffer, curr, head);
assert(p_atomic_read(&sbuf->base.reference.count) != 0);
- assert(sbuf->needs_flush);
+ assert(sbuf->dma.pending);
svga_buffer_upload_flush(svga, sbuf);
diff --git a/src/gallium/drivers/svga/svga_screen_buffer.h b/src/gallium/drivers/svga/svga_screen_buffer.h
index 448ac107c7..8c862fa62d 100644
--- a/src/gallium/drivers/svga/svga_screen_buffer.h
+++ b/src/gallium/drivers/svga/svga_screen_buffer.h
@@ -57,35 +57,6 @@ struct svga_buffer_range
/**
- * Describe a
- *
- * This holds the information to emit a SVGA3dCmdSurfaceDMA.
- */
-struct svga_buffer_upload
-{
- /**
- * Guest memory region.
- */
- struct svga_winsys_buffer *buf;
-
- struct svga_buffer_range ranges[SVGA_BUFFER_MAX_RANGES];
- unsigned num_ranges;
-
- SVGA3dSurfaceDMAFlags flags;
-
- /**
- * Pointer to the DMA copy box *inside* the command buffer.
- */
- SVGA3dCopyBox *boxes;
-
- /**
- * Context that has the pending DMA to this buffer.
- */
- struct svga_context *svga;
-};
-
-
-/**
* SVGA pipe buffer.
*/
struct svga_buffer
@@ -111,14 +82,6 @@ struct svga_buffer
boolean user;
/**
- * DMA'ble memory.
- *
- * A piece of GMR memory. It is created when mapping the buffer, and will be
- * used to upload/download vertex data from the host.
- */
- struct svga_buffer_upload hw;
-
- /**
* Creation key for the host surface handle.
*
* This structure describes all the host surface characteristics so that it
@@ -134,19 +97,94 @@ struct svga_buffer
* trying to bind
*/
struct svga_winsys_surface *handle;
-
+
/**
- * Whether the host has been ever written.
+ * Information about ongoing and past map operations.
*/
- boolean host_written;
-
struct {
+ /**
+ * Number of concurrent mappings.
+ *
+ * XXX: It is impossible to guarantee concurrent maps work in all
+ * circumstances -- pipe_buffers really need transfer objects too.
+ */
unsigned count;
+
+ /**
+ * Whether this buffer is currently mapped for writing.
+ */
boolean writing;
+
+ /**
+ * Whether the application will tell us explicity which ranges it touched
+ * or not.
+ */
boolean flush_explicit;
+
+ /**
+ * Dirty ranges.
+ *
+ * Ranges that were touched by the application and need to be uploaded to
+ * the host.
+ *
+ * This information will be copied into dma.boxes, when emiting the
+ * SVGA3dCmdSurfaceDMA command.
+ */
+ struct svga_buffer_range ranges[SVGA_BUFFER_MAX_RANGES];
+ unsigned num_ranges;
} map;
-
- boolean needs_flush;
+
+ /**
+ * Information about uploaded version of user buffers.
+ */
+ struct {
+ struct pipe_buffer *buffer;
+
+ /**
+ * We combine multiple user buffers into the same hardware buffer. This
+ * is the relative offset within that buffer.
+ */
+ unsigned offset;
+ } uploaded;
+
+ /**
+ * DMA'ble memory.
+ *
+ * A piece of GMR memory, with the same size of the buffer. It is created
+ * when mapping the buffer, and will be used to upload vertex data to the
+ * host.
+ */
+ struct svga_winsys_buffer *hwbuf;
+
+ /**
+ * Information about pending DMA uploads.
+ *
+ */
+ struct {
+ /**
+ * Whether this buffer has an unfinished DMA upload command.
+ *
+ * If not set then the rest of the information is null.
+ */
+ boolean pending;
+
+ SVGA3dSurfaceDMAFlags flags;
+
+ /**
+ * Pointer to the DMA copy box *inside* the command buffer.
+ */
+ SVGA3dCopyBox *boxes;
+
+ /**
+ * Context that has the pending DMA to this buffer.
+ */
+ struct svga_context *svga;
+ } dma;
+
+ /**
+ * Linked list head, used to gather all buffers with pending dma uploads on
+ * a context. It is only valid if the dma.pending is set above.
+ */
struct list_head head;
};
@@ -176,6 +214,16 @@ svga_buffer_is_user_buffer( struct pipe_buffer *buffer )
void
svga_screen_init_buffer_functions(struct pipe_screen *screen);
+
+/**
+ * Get the host surface handle for this buffer.
+ *
+ * This will ensure the host surface is updated, issuing DMAs as needed.
+ *
+ * NOTE: This may insert new commands in the context, so it *must* be called
+ * before reserving command buffer space. And, in order to insert commands
+ * it may need to call svga_context_flush().
+ */
struct svga_winsys_surface *
svga_buffer_handle(struct svga_context *svga,
struct pipe_buffer *buf);
diff --git a/src/gallium/drivers/svga/svga_screen_texture.c b/src/gallium/drivers/svga/svga_screen_texture.c
index 12f3531a1d..5b581debfc 100644
--- a/src/gallium/drivers/svga/svga_screen_texture.c
+++ b/src/gallium/drivers/svga/svga_screen_texture.c
@@ -59,21 +59,21 @@ svga_translate_format(enum pipe_format format)
{
switch(format) {
- case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
return SVGA3D_A8R8G8B8;
- case PIPE_FORMAT_X8R8G8B8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
return SVGA3D_X8R8G8B8;
/* Required for GL2.1:
*/
- case PIPE_FORMAT_A8R8G8B8_SRGB:
+ case PIPE_FORMAT_B8G8R8A8_SRGB:
return SVGA3D_A8R8G8B8;
- case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_B5G6R5_UNORM:
return SVGA3D_R5G6B5;
- case PIPE_FORMAT_A1R5G5B5_UNORM:
+ case PIPE_FORMAT_B5G5R5A1_UNORM:
return SVGA3D_A1R5G5B5;
- case PIPE_FORMAT_A4R4G4B4_UNORM:
+ case PIPE_FORMAT_B4G4R4A4_UNORM:
return SVGA3D_A4R4G4B4;
@@ -83,9 +83,9 @@ svga_translate_format(enum pipe_format format)
*/
case PIPE_FORMAT_Z16_UNORM:
return SVGA3D_Z_D16;
- case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
return SVGA3D_Z_D24S8;
- case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
return SVGA3D_Z_D24X8;
case PIPE_FORMAT_A8_UNORM:
@@ -111,13 +111,13 @@ SVGA3dSurfaceFormat
svga_translate_format_render(enum pipe_format format)
{
switch(format) {
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- case PIPE_FORMAT_X8R8G8B8_UNORM:
- case PIPE_FORMAT_A1R5G5B5_UNORM:
- case PIPE_FORMAT_A4R4G4B4_UNORM:
- case PIPE_FORMAT_R5G6B5_UNORM:
- case PIPE_FORMAT_Z24S8_UNORM:
- case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ case PIPE_FORMAT_B5G5R5A1_UNORM:
+ case PIPE_FORMAT_B4G4R4A4_UNORM:
+ case PIPE_FORMAT_B5G6R5_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_Z32_UNORM:
case PIPE_FORMAT_Z16_UNORM:
case PIPE_FORMAT_L8_UNORM:
@@ -315,7 +315,11 @@ svga_texture_create(struct pipe_screen *screen,
tex->key.cachable = 0;
}
- if(templat->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) {
+ if(templat->tex_usage & PIPE_TEXTURE_USAGE_SHARED) {
+ tex->key.cachable = 0;
+ }
+
+ if(templat->tex_usage & PIPE_TEXTURE_USAGE_SCANOUT) {
tex->key.flags |= SVGA3D_SURFACE_HINT_SCANOUT;
tex->key.cachable = 0;
}
@@ -355,80 +359,18 @@ error1:
}
-static struct pipe_texture *
-svga_texture_blanket(struct pipe_screen * screen,
- const struct pipe_texture *base,
- const unsigned *stride,
- struct pipe_buffer *buffer)
-{
- struct svga_texture *tex;
- struct svga_buffer *sbuf = svga_buffer(buffer);
- struct svga_winsys_screen *sws = svga_winsys_screen(screen);
- assert(screen);
-
- /* Only supports one type */
- if (base->target != PIPE_TEXTURE_2D ||
- base->last_level != 0 ||
- base->depth0 != 1) {
- return NULL;
- }
-
- /**
- * We currently can't do texture blanket on
- * SVGA3D_BUFFER. Need to blit to a temporary surface?
- */
-
- assert(sbuf->handle);
- if (!sbuf->handle)
- return NULL;
-
- if (svga_translate_format(base->format) != sbuf->key.format) {
- unsigned f1 = svga_translate_format(base->format);
- unsigned f2 = sbuf->key.format;
-
- /* It's okay for XRGB and ARGB or depth with/out stencil to get mixed up */
- if ( !( (f1 == SVGA3D_X8R8G8B8 && f2 == SVGA3D_A8R8G8B8) ||
- (f1 == SVGA3D_A8R8G8B8 && f2 == SVGA3D_X8R8G8B8) ||
- (f1 == SVGA3D_Z_D24X8 && f2 == SVGA3D_Z_D24S8) ) ) {
- debug_printf("%s wrong format %u != %u\n", __FUNCTION__, f1, f2);
- return NULL;
- }
- }
-
- tex = CALLOC_STRUCT(svga_texture);
- if (!tex)
- return NULL;
-
- tex->base = *base;
-
-
- if (sbuf->key.format == 1)
- tex->base.format = PIPE_FORMAT_X8R8G8B8_UNORM;
- else if (sbuf->key.format == 2)
- tex->base.format = PIPE_FORMAT_A8R8G8B8_UNORM;
-
- pipe_reference_init(&tex->base.reference, 1);
- tex->base.screen = screen;
-
- SVGA_DBG(DEBUG_DMA, "blanket sid %p\n", sbuf->handle);
-
- /* We don't own this storage, so don't try to cache it.
- */
- assert(sbuf->key.cachable == 0);
- tex->key.cachable = 0;
- sws->surface_reference(sws, &tex->handle, sbuf->handle);
- return &tex->base;
-}
-struct pipe_texture *
-svga_screen_texture_wrap_surface(struct pipe_screen *screen,
- struct pipe_texture *base,
- enum SVGA3dSurfaceFormat format,
- struct svga_winsys_surface *srf)
+static struct pipe_texture *
+svga_screen_texture_from_handle(struct pipe_screen *screen,
+ const struct pipe_texture *base,
+ struct winsys_handle *whandle)
{
+ struct svga_winsys_screen *sws = svga_winsys_screen(screen);
+ struct svga_winsys_surface *srf;
struct svga_texture *tex;
+ enum SVGA3dSurfaceFormat format = 0;
assert(screen);
/* Only supports one type */
@@ -438,6 +380,8 @@ svga_screen_texture_wrap_surface(struct pipe_screen *screen,
return NULL;
}
+ srf = sws->surface_from_handle(sws, whandle, &format);
+
if (!srf)
return NULL;
@@ -462,9 +406,9 @@ svga_screen_texture_wrap_surface(struct pipe_screen *screen,
if (format == 1)
- tex->base.format = PIPE_FORMAT_X8R8G8B8_UNORM;
+ tex->base.format = PIPE_FORMAT_B8G8R8X8_UNORM;
else if (format == 2)
- tex->base.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ tex->base.format = PIPE_FORMAT_B8G8R8A8_UNORM;
pipe_reference_init(&tex->base.reference, 1);
tex->base.screen = screen;
@@ -478,6 +422,22 @@ svga_screen_texture_wrap_surface(struct pipe_screen *screen,
}
+static boolean
+svga_screen_texture_get_handle(struct pipe_screen *screen,
+ struct pipe_texture *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);
+}
+
+
static void
svga_texture_destroy(struct pipe_texture *pt)
{
@@ -955,10 +915,11 @@ void
svga_screen_init_texture_functions(struct pipe_screen *screen)
{
screen->texture_create = svga_texture_create;
+ screen->texture_from_handle = svga_screen_texture_from_handle;
+ screen->texture_get_handle = svga_screen_texture_get_handle;
screen->texture_destroy = svga_texture_destroy;
screen->get_tex_surface = svga_get_tex_surface;
screen->tex_surface_destroy = svga_tex_surface_destroy;
- screen->texture_blanket = svga_texture_blanket;
screen->get_tex_transfer = svga_get_tex_transfer;
screen->transfer_map = svga_transfer_map;
screen->transfer_unmap = svga_transfer_unmap;
@@ -1120,33 +1081,3 @@ svga_destroy_sampler_view_priv(struct svga_sampler_view *v)
pipe_texture_reference(&v->texture, NULL);
FREE(v);
}
-
-boolean
-svga_screen_buffer_from_texture(struct pipe_texture *texture,
- struct pipe_buffer **buffer,
- unsigned *stride)
-{
- struct svga_texture *stex = svga_texture(texture);
-
- *buffer = svga_screen_buffer_wrap_surface
- (texture->screen,
- svga_translate_format(texture->format),
- stex->handle);
-
- *stride = util_format_get_stride(texture->format, texture->width0);
-
- return *buffer != NULL;
-}
-
-
-struct svga_winsys_surface *
-svga_screen_texture_get_winsys_surface(struct pipe_texture *texture)
-{
- struct svga_winsys_screen *sws = svga_winsys_screen(texture->screen);
- struct svga_winsys_surface *vsurf = NULL;
-
- assert(svga_texture(texture)->key.cachable == 0);
- svga_texture(texture)->key.cachable = 0;
- sws->surface_reference(sws, &vsurf, svga_texture(texture)->handle);
- return vsurf;
-}
diff --git a/src/gallium/drivers/svga/svga_screen_texture.h b/src/gallium/drivers/svga/svga_screen_texture.h
index 24c1f78ca5..ca6602b436 100644
--- a/src/gallium/drivers/svga/svga_screen_texture.h
+++ b/src/gallium/drivers/svga/svga_screen_texture.h
@@ -78,7 +78,7 @@ struct svga_texture
{
struct pipe_texture base;
- boolean defined[6][PIPE_MAX_TEXTURE_LEVELS];
+ boolean defined[6][SVGA_MAX_TEXTURE_LEVELS];
struct svga_sampler_view *cached_view;
diff --git a/src/gallium/drivers/svga/svga_state_framebuffer.c b/src/gallium/drivers/svga/svga_state_framebuffer.c
index b4cafb8f21..b710914acd 100644
--- a/src/gallium/drivers/svga/svga_state_framebuffer.c
+++ b/src/gallium/drivers/svga/svga_state_framebuffer.c
@@ -70,7 +70,7 @@ static int emit_framebuffer( struct svga_context *svga,
return ret;
if (curr->zsbuf &&
- curr->zsbuf->format == PIPE_FORMAT_Z24S8_UNORM) {
+ curr->zsbuf->format == PIPE_FORMAT_S8Z24_UNORM) {
ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, curr->zsbuf);
if (ret != PIPE_OK)
return ret;
@@ -120,174 +120,153 @@ static int emit_viewport( struct svga_context *svga,
float fb_width = svga->curr.framebuffer.width;
float fb_height = svga->curr.framebuffer.height;
- memset( &prescale, 0, sizeof(prescale) );
-
- if (svga->curr.rast->templ.bypass_vs_clip_and_viewport) {
-
- /* Avoid POSITIONT as it has a non trivial implementation outside the D3D
- * API. Always generate a vertex shader.
- */
- rect.x = 0;
- rect.y = 0;
- rect.w = svga->curr.framebuffer.width;
- rect.h = svga->curr.framebuffer.height;
-
- prescale.scale[0] = 2.0 / (float)rect.w;
- prescale.scale[1] = - 2.0 / (float)rect.h;
- prescale.scale[2] = 1.0;
- prescale.scale[3] = 1.0;
- prescale.translate[0] = -1.0f;
- prescale.translate[1] = 1.0f;
- prescale.translate[2] = 0;
- prescale.translate[3] = 0;
- prescale.enabled = TRUE;
- } else {
-
- /* Examine gallium viewport transformation and produce a screen
- * rectangle and possibly vertex shader pre-transformation to
- * get the same results.
- */
- float fx = viewport->scale[0] * -1.0 + viewport->translate[0];
- float fy = flip * viewport->scale[1] * -1.0 + viewport->translate[1];
- float fw = viewport->scale[0] * 2;
- float fh = flip * viewport->scale[1] * 2;
-
- SVGA_DBG(DEBUG_VIEWPORT,
- "\ninitial %f,%f %fx%f\n",
- fx,
- fy,
- fw,
- fh);
-
- prescale.scale[0] = 1.0;
- prescale.scale[1] = 1.0;
- prescale.scale[2] = 1.0;
- prescale.scale[3] = 1.0;
- prescale.translate[0] = 0;
- prescale.translate[1] = 0;
- prescale.translate[2] = 0;
- prescale.translate[3] = 0;
- prescale.enabled = TRUE;
-
-
-
- if (fw < 0) {
- prescale.scale[0] *= -1.0;
- prescale.translate[0] += -fw;
- fw = -fw;
- fx = viewport->scale[0] * 1.0 + viewport->translate[0];
- }
+ float fx = viewport->scale[0] * -1.0 + viewport->translate[0];
+ float fy = flip * viewport->scale[1] * -1.0 + viewport->translate[1];
+ float fw = viewport->scale[0] * 2;
+ float fh = flip * viewport->scale[1] * 2;
- if (fh < 0) {
- prescale.scale[1] *= -1.0;
- prescale.translate[1] += -fh;
- fh = -fh;
- fy = flip * viewport->scale[1] * 1.0 + viewport->translate[1];
- }
+ memset( &prescale, 0, sizeof(prescale) );
- if (fx < 0) {
- prescale.translate[0] += fx;
- prescale.scale[0] *= fw / (fw + fx);
- fw += fx;
- fx = 0;
- }
+ /* Examine gallium viewport transformation and produce a screen
+ * rectangle and possibly vertex shader pre-transformation to
+ * get the same results.
+ */
- if (fy < 0) {
- prescale.translate[1] += fy;
- prescale.scale[1] *= fh / (fh + fy);
- fh += fy;
- fy = 0;
- }
+ SVGA_DBG(DEBUG_VIEWPORT,
+ "\ninitial %f,%f %fx%f\n",
+ fx,
+ fy,
+ fw,
+ fh);
+
+ prescale.scale[0] = 1.0;
+ prescale.scale[1] = 1.0;
+ prescale.scale[2] = 1.0;
+ prescale.scale[3] = 1.0;
+ prescale.translate[0] = 0;
+ prescale.translate[1] = 0;
+ prescale.translate[2] = 0;
+ prescale.translate[3] = 0;
+ prescale.enabled = TRUE;
+
+
+
+ if (fw < 0) {
+ prescale.scale[0] *= -1.0;
+ prescale.translate[0] += -fw;
+ fw = -fw;
+ fx = viewport->scale[0] * 1.0 + viewport->translate[0];
+ }
- if (fx + fw > fb_width) {
- prescale.scale[0] *= fw / (fb_width - fx);
- prescale.translate[0] -= fx * (fw / (fb_width - fx));
- prescale.translate[0] += fx;
- fw = fb_width - fx;
-
- }
+ if (fh < 0) {
+ prescale.scale[1] *= -1.0;
+ prescale.translate[1] += -fh;
+ fh = -fh;
+ fy = flip * viewport->scale[1] * 1.0 + viewport->translate[1];
+ }
- if (fy + fh > fb_height) {
- prescale.scale[1] *= fh / (fb_height - fy);
- prescale.translate[1] -= fy * (fh / (fb_height - fy));
- prescale.translate[1] += fy;
- fh = fb_height - fy;
- }
+ if (fx < 0) {
+ prescale.translate[0] += fx;
+ prescale.scale[0] *= fw / (fw + fx);
+ fw += fx;
+ fx = 0;
+ }
- if (fw < 0 || fh < 0) {
- fw = fh = fx = fy = 0;
- degenerate = TRUE;
- goto out;
- }
+ if (fy < 0) {
+ prescale.translate[1] += fy;
+ prescale.scale[1] *= fh / (fh + fy);
+ fh += fy;
+ fy = 0;
+ }
+ if (fx + fw > fb_width) {
+ prescale.scale[0] *= fw / (fb_width - fx);
+ prescale.translate[0] -= fx * (fw / (fb_width - fx));
+ prescale.translate[0] += fx;
+ fw = fb_width - fx;
+
+ }
- /* D3D viewport is integer space. Convert fx,fy,etc. to
- * integers.
- *
- * TODO: adjust pretranslate correct for any subpixel error
- * introduced converting to integers.
- */
- rect.x = fx;
- rect.y = fy;
- rect.w = fw;
- rect.h = fh;
+ if (fy + fh > fb_height) {
+ prescale.scale[1] *= fh / (fb_height - fy);
+ prescale.translate[1] -= fy * (fh / (fb_height - fy));
+ prescale.translate[1] += fy;
+ fh = fb_height - fy;
+ }
- SVGA_DBG(DEBUG_VIEWPORT,
- "viewport error %f,%f %fx%f\n",
- fabs((float)rect.x - fx),
- fabs((float)rect.y - fy),
- fabs((float)rect.w - fw),
- fabs((float)rect.h - fh));
+ if (fw < 0 || fh < 0) {
+ fw = fh = fx = fy = 0;
+ degenerate = TRUE;
+ goto out;
+ }
- SVGA_DBG(DEBUG_VIEWPORT,
- "viewport %d,%d %dx%d\n",
- rect.x,
- rect.y,
- rect.w,
- rect.h);
-
- /* Finally, to get GL rasterization rules, need to tweak the
- * screen-space coordinates slightly relative to D3D which is
- * what hardware implements natively.
- */
- if (svga->curr.rast->templ.gl_rasterization_rules) {
- float adjust_x = 0.0;
- float adjust_y = 0.0;
-
- switch (svga->curr.reduced_prim) {
- case PIPE_PRIM_LINES:
- adjust_x = -0.5;
- adjust_y = 0;
- break;
- case PIPE_PRIM_POINTS:
- case PIPE_PRIM_TRIANGLES:
- adjust_x = -0.375;
- adjust_y = -0.5;
- break;
- }
-
- prescale.translate[0] += adjust_x;
- prescale.translate[1] += adjust_y;
- prescale.translate[2] = 0.5; /* D3D clip space */
- prescale.scale[2] = 0.5; /* D3D clip space */
+ /* D3D viewport is integer space. Convert fx,fy,etc. to
+ * integers.
+ *
+ * TODO: adjust pretranslate correct for any subpixel error
+ * introduced converting to integers.
+ */
+ rect.x = fx;
+ rect.y = fy;
+ rect.w = fw;
+ rect.h = fh;
+
+ SVGA_DBG(DEBUG_VIEWPORT,
+ "viewport error %f,%f %fx%f\n",
+ fabs((float)rect.x - fx),
+ fabs((float)rect.y - fy),
+ fabs((float)rect.w - fw),
+ fabs((float)rect.h - fh));
+
+ SVGA_DBG(DEBUG_VIEWPORT,
+ "viewport %d,%d %dx%d\n",
+ rect.x,
+ rect.y,
+ rect.w,
+ rect.h);
+
+
+ /* Finally, to get GL rasterization rules, need to tweak the
+ * screen-space coordinates slightly relative to D3D which is
+ * what hardware implements natively.
+ */
+ if (svga->curr.rast->templ.gl_rasterization_rules) {
+ float adjust_x = 0.0;
+ float adjust_y = 0.0;
+
+ switch (svga->curr.reduced_prim) {
+ case PIPE_PRIM_LINES:
+ adjust_x = -0.5;
+ adjust_y = 0;
+ break;
+ case PIPE_PRIM_POINTS:
+ case PIPE_PRIM_TRIANGLES:
+ adjust_x = -0.375;
+ adjust_y = -0.5;
+ break;
}
+ prescale.translate[0] += adjust_x;
+ prescale.translate[1] += adjust_y;
+ prescale.translate[2] = 0.5; /* D3D clip space */
+ prescale.scale[2] = 0.5; /* D3D clip space */
+ }
- range_min = viewport->scale[2] * -1.0 + viewport->translate[2];
- range_max = viewport->scale[2] * 1.0 + viewport->translate[2];
- /* D3D (and by implication SVGA) doesn't like dealing with zmax
- * less than zmin. Detect that case, flip the depth range and
- * invert our z-scale factor to achieve the same effect.
- */
- if (range_min > range_max) {
- float range_tmp;
- range_tmp = range_min;
- range_min = range_max;
- range_max = range_tmp;
- prescale.scale[2] = -prescale.scale[2];
- }
+ range_min = viewport->scale[2] * -1.0 + viewport->translate[2];
+ range_max = viewport->scale[2] * 1.0 + viewport->translate[2];
+
+ /* D3D (and by implication SVGA) doesn't like dealing with zmax
+ * less than zmin. Detect that case, flip the depth range and
+ * invert our z-scale factor to achieve the same effect.
+ */
+ if (range_min > range_max) {
+ float range_tmp;
+ range_tmp = range_min;
+ range_min = range_max;
+ range_max = range_tmp;
+ prescale.scale[2] = -prescale.scale[2];
}
if (prescale.enabled) {
diff --git a/src/gallium/drivers/svga/svga_state_need_swtnl.c b/src/gallium/drivers/svga/svga_state_need_swtnl.c
index dd13a89d24..dfaab53aef 100644
--- a/src/gallium/drivers/svga/svga_state_need_swtnl.c
+++ b/src/gallium/drivers/svga/svga_state_need_swtnl.c
@@ -43,7 +43,7 @@ svga_translate_vertex_format(enum pipe_format format)
case PIPE_FORMAT_R32G32_FLOAT: return SVGA3D_DECLTYPE_FLOAT2;
case PIPE_FORMAT_R32G32B32_FLOAT: return SVGA3D_DECLTYPE_FLOAT3;
case PIPE_FORMAT_R32G32B32A32_FLOAT: return SVGA3D_DECLTYPE_FLOAT4;
- case PIPE_FORMAT_B8G8R8A8_UNORM: return SVGA3D_DECLTYPE_D3DCOLOR;
+ case PIPE_FORMAT_A8R8G8B8_UNORM: return SVGA3D_DECLTYPE_D3DCOLOR;
case PIPE_FORMAT_R8G8B8A8_USCALED: return SVGA3D_DECLTYPE_UBYTE4;
case PIPE_FORMAT_R16G16_SSCALED: return SVGA3D_DECLTYPE_SHORT2;
case PIPE_FORMAT_R16G16B16A16_SSCALED: return SVGA3D_DECLTYPE_SHORT4;
@@ -76,8 +76,13 @@ static int update_need_swvfetch( struct svga_context *svga,
unsigned i;
boolean need_swvfetch = FALSE;
- for (i = 0; i < svga->curr.num_vertex_elements; i++) {
- svga->state.sw.ve_format[i] = svga_translate_vertex_format(svga->curr.ve[i].src_format);
+ if (!svga->curr.velems) {
+ /* No vertex elements bound. */
+ return 0;
+ }
+
+ for (i = 0; i < svga->curr.velems->count; i++) {
+ svga->state.sw.ve_format[i] = svga_translate_vertex_format(svga->curr.velems->velem[i].src_format);
if (svga->state.sw.ve_format[i] == SVGA3D_DECLTYPE_MAX) {
need_swvfetch = TRUE;
break;
@@ -129,8 +134,7 @@ static int update_need_pipeline( struct svga_context *svga,
/* SVGA_NEW_CLIP
*/
- if (!svga->curr.rast->templ.bypass_vs_clip_and_viewport &&
- svga->curr.clip.nr) {
+ if (svga->curr.clip.nr) {
SVGA_DBG(DEBUG_SWTNL, "%s: userclip\n", __FUNCTION__);
need_pipeline = TRUE;
}
diff --git a/src/gallium/drivers/svga/svga_state_rss.c b/src/gallium/drivers/svga/svga_state_rss.c
index 107cc403b4..b7195d246b 100644
--- a/src/gallium/drivers/svga/svga_state_rss.c
+++ b/src/gallium/drivers/svga/svga_state_rss.c
@@ -191,15 +191,24 @@ static int emit_rss( struct svga_context *svga,
EMIT_RS( svga, svga->curr.stencil_ref.ref_value[0], STENCILREF, fail );
}
- if (dirty & SVGA_NEW_RAST)
+ if (dirty & (SVGA_NEW_RAST | SVGA_NEW_NEED_PIPELINE))
{
const struct svga_rasterizer_state *curr = svga->curr.rast;
+ unsigned cullmode = curr->cullmode;
/* Shademode: still need to rearrange index list to move
* flat-shading PV first vertex.
*/
EMIT_RS( svga, curr->shademode, SHADEMODE, fail );
- EMIT_RS( svga, curr->cullmode, CULLMODE, fail );
+
+ /* Don't do culling while the software pipeline is active. It
+ * does it for us, and additionally introduces potentially
+ * back-facing triangles.
+ */
+ if (svga->state.sw.need_pipeline)
+ cullmode = SVGA3D_FACE_NONE;
+
+ EMIT_RS( svga, cullmode, CULLMODE, fail );
EMIT_RS( svga, curr->scissortestenable, SCISSORTESTENABLE, fail );
EMIT_RS( svga, curr->multisampleantialias, MULTISAMPLEANTIALIAS, fail );
EMIT_RS( svga, curr->lastpixel, LASTPIXEL, fail );
diff --git a/src/gallium/drivers/svga/svga_state_vdecl.c b/src/gallium/drivers/svga/svga_state_vdecl.c
index d1066ce13b..f531e22304 100644
--- a/src/gallium/drivers/svga/svga_state_vdecl.c
+++ b/src/gallium/drivers/svga/svga_state_vdecl.c
@@ -54,33 +54,30 @@ upload_user_buffers( struct svga_context *svga )
{
if (svga_buffer_is_user_buffer(svga->curr.vb[i].buffer))
{
- struct pipe_buffer *upload_buffer = NULL;
- unsigned offset = /*svga->curr.vb[i].buffer_offset*/ 0;
- unsigned size = svga->curr.vb[i].buffer->size /*- offset*/;
- unsigned upload_offset;
-
- ret = u_upload_buffer( svga->upload_vb,
- offset,
- size,
- svga->curr.vb[i].buffer,
- &upload_offset,
- &upload_buffer );
- if (ret)
- return ret;
-
- if (0)
- debug_printf("%s: %d: orig buf %p upl buf %p ofs %d sz %d\n",
- __FUNCTION__,
- i,
- svga->curr.vb[i].buffer,
- upload_buffer, upload_offset, size);
-
- /* Make sure we release the old buffer and end up with the
- * correct refcount on the uploaded buffer.
- */
- pipe_buffer_reference( &svga->curr.vb[i].buffer, NULL );
- svga->curr.vb[i].buffer = upload_buffer;
- svga->curr.vb[i].buffer_offset = upload_offset;
+ struct svga_buffer *buffer = svga_buffer(svga->curr.vb[i].buffer);
+
+ if (!buffer->uploaded.buffer) {
+ ret = u_upload_buffer( svga->upload_vb,
+ 0,
+ buffer->base.size,
+ &buffer->base,
+ &buffer->uploaded.offset,
+ &buffer->uploaded.buffer );
+ if (ret)
+ return ret;
+
+ if (0)
+ debug_printf("%s: %d: orig buf %p upl buf %p ofs %d sz %d\n",
+ __FUNCTION__,
+ i,
+ buffer,
+ buffer->uploaded.buffer,
+ buffer->uploaded.offset,
+ buffer->base.size);
+ }
+
+ pipe_buffer_reference( &svga->curr.vb[i].buffer, buffer->uploaded.buffer );
+ svga->curr.vb[i].buffer_offset = buffer->uploaded.offset;
}
}
@@ -98,17 +95,17 @@ upload_user_buffers( struct svga_context *svga )
static int emit_hw_vs_vdecl( struct svga_context *svga,
unsigned dirty )
{
- const struct pipe_vertex_element *ve = svga->curr.ve;
+ const struct pipe_vertex_element *ve = svga->curr.velems->velem;
SVGA3dVertexDecl decl;
unsigned i;
- assert(svga->curr.num_vertex_elements >=
+ assert(svga->curr.velems->count >=
svga->curr.vs->base.info.file_count[TGSI_FILE_INPUT]);
svga_hwtnl_reset_vdecl( svga->hwtnl,
- svga->curr.num_vertex_elements );
+ svga->curr.velems->count );
- for (i = 0; i < svga->curr.num_vertex_elements; i++) {
+ for (i = 0; i < svga->curr.velems->count; i++) {
const struct pipe_vertex_buffer *vb = &svga->curr.vb[ve[i].vertex_buffer_index];
unsigned usage, index;
diff --git a/src/gallium/drivers/svga/svga_state_vs.c b/src/gallium/drivers/svga/svga_state_vs.c
index d7999fe53d..781f7bf533 100644
--- a/src/gallium/drivers/svga/svga_state_vs.c
+++ b/src/gallium/drivers/svga/svga_state_vs.c
@@ -186,8 +186,8 @@ static int update_zero_stride( struct svga_context *svga,
svga->curr.zero_stride_vertex_elements = 0;
svga->curr.num_zero_stride_vertex_elements = 0;
- for (i = 0; i < svga->curr.num_vertex_elements; i++) {
- const struct pipe_vertex_element *vel = &svga->curr.ve[i];
+ for (i = 0; i < svga->curr.velems->count; i++) {
+ const struct pipe_vertex_element *vel = &svga->curr.velems->velem[i];
const struct pipe_vertex_buffer *vbuffer = &svga->curr.vb[
vel->vertex_buffer_index];
if (vbuffer->stride == 0) {
diff --git a/src/gallium/drivers/svga/svga_swtnl_state.c b/src/gallium/drivers/svga/svga_swtnl_state.c
index 35f36a828f..246d34e649 100644
--- a/src/gallium/drivers/svga/svga_swtnl_state.c
+++ b/src/gallium/drivers/svga/svga_swtnl_state.c
@@ -99,8 +99,8 @@ static int update_swtnl_draw( struct svga_context *svga,
if (dirty & SVGA_NEW_VELEMENT)
draw_set_vertex_elements(svga->swtnl.draw,
- svga->curr.num_vertex_elements,
- svga->curr.ve );
+ svga->curr.velems->count,
+ svga->curr.velems->velem );
if (dirty & SVGA_NEW_CLIP)
draw_set_clip_state(svga->swtnl.draw,
diff --git a/src/gallium/drivers/svga/svga_tgsi_emit.h b/src/gallium/drivers/svga/svga_tgsi_emit.h
index e8f75485d5..48eced2ece 100644
--- a/src/gallium/drivers/svga/svga_tgsi_emit.h
+++ b/src/gallium/drivers/svga/svga_tgsi_emit.h
@@ -138,6 +138,7 @@ static INLINE boolean emit_dst( struct svga_shader_emitter *emit,
SVGA3dShaderDestToken dest )
{
assert(dest.reserved0);
+ assert(dest.mask);
return svga_shader_emit_dword( emit, dest.value );
}
@@ -267,6 +268,7 @@ static INLINE SVGA3dShaderDestToken
writemask( SVGA3dShaderDestToken dest,
unsigned mask )
{
+ assert(dest.mask & mask);
dest.mask &= mask;
return dest;
}
diff --git a/src/gallium/drivers/svga/svga_tgsi_insn.c b/src/gallium/drivers/svga/svga_tgsi_insn.c
index 87aed39f78..3d4f56a67b 100644
--- a/src/gallium/drivers/svga/svga_tgsi_insn.c
+++ b/src/gallium/drivers/svga/svga_tgsi_insn.c
@@ -112,6 +112,7 @@ translate_dst_register( struct svga_shader_emitter *emit,
}
dest.mask = reg->Register.WriteMask;
+ assert(dest.mask);
if (insn->Instruction.Saturate)
dest.dstMod = SVGA3DDSTMOD_SATURATE;
@@ -1410,34 +1411,42 @@ static boolean emit_tex(struct svga_shader_emitter *emit,
if (compare) {
- SVGA3dShaderDestToken src0_zdivw = get_temp( emit );
- struct src_register tex_src_x = scalar(src(tex_result), TGSI_SWIZZLE_Y);
- struct src_register one =
- scalar( get_zero_immediate( emit ), TGSI_SWIZZLE_W );
-
- /* Divide texcoord R by Q */
- if (!submit_op1( emit, inst_token( SVGA3DOP_RCP ),
- src0_zdivw,
- scalar(src0, TGSI_SWIZZLE_W) ))
- return FALSE;
+ if (dst.mask & TGSI_WRITEMASK_XYZ) {
+ SVGA3dShaderDestToken src0_zdivw = get_temp( emit );
+ struct src_register tex_src_x = scalar(src(tex_result), TGSI_SWIZZLE_Y);
+
+ /* Divide texcoord R by Q */
+ if (!submit_op1( emit, inst_token( SVGA3DOP_RCP ),
+ writemask(src0_zdivw, TGSI_WRITEMASK_X),
+ scalar(src0, TGSI_SWIZZLE_W) ))
+ return FALSE;
- if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ),
- src0_zdivw,
- scalar(src0, TGSI_SWIZZLE_Z),
- src(src0_zdivw) ))
- return FALSE;
+ if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ),
+ writemask(src0_zdivw, TGSI_WRITEMASK_X),
+ scalar(src0, TGSI_SWIZZLE_Z),
+ scalar(src(src0_zdivw), TGSI_SWIZZLE_X) ))
+ return FALSE;
- if (!emit_select(
- emit,
- emit->key.fkey.tex[src1.base.num].compare_func,
- dst,
- src(src0_zdivw),
- tex_src_x))
- return FALSE;
+ if (!emit_select(
+ emit,
+ emit->key.fkey.tex[src1.base.num].compare_func,
+ writemask( dst, TGSI_WRITEMASK_XYZ ),
+ scalar(src(src0_zdivw), TGSI_SWIZZLE_X),
+ tex_src_x))
+ return FALSE;
+ }
- return submit_op1( emit, inst_token( SVGA3DOP_MOV ),
- writemask( dst, TGSI_WRITEMASK_W),
- one );
+ if (dst.mask & TGSI_WRITEMASK_W) {
+ struct src_register one =
+ scalar( get_zero_immediate( emit ), TGSI_SWIZZLE_W );
+
+ if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ),
+ writemask( dst, TGSI_WRITEMASK_W ),
+ one ))
+ return FALSE;
+ }
+
+ return TRUE;
}
else if (!emit->use_sm30 && dst.mask != TGSI_WRITEMASK_XYZW)
{
@@ -1827,13 +1836,13 @@ static boolean emit_exp(struct svga_shader_emitter *emit,
*/
if (dst.mask & TGSI_WRITEMASK_X) {
if (!submit_op2( emit, inst_token( SVGA3DOP_ADD ),
- writemask( dst, dst.mask & TGSI_WRITEMASK_X ),
+ writemask( dst, TGSI_WRITEMASK_X ),
src0,
scalar( negate( src( fraction ) ), TGSI_SWIZZLE_Y ) ) )
return FALSE;
if (!submit_op1( emit, inst_token( SVGA3DOP_EXP ),
- writemask( dst, dst.mask & TGSI_WRITEMASK_X ),
+ writemask( dst, TGSI_WRITEMASK_X ),
scalar( src( dst ), TGSI_SWIZZLE_X ) ) )
return FALSE;
@@ -1845,7 +1854,7 @@ static boolean emit_exp(struct svga_shader_emitter *emit,
*/
if (dst.mask & TGSI_WRITEMASK_Z) {
if (!submit_op1( emit, inst_token( SVGA3DOP_EXPP ),
- writemask( dst, dst.mask & TGSI_WRITEMASK_Z ),
+ writemask( dst, TGSI_WRITEMASK_Z ),
src0 ) )
return FALSE;
}
diff --git a/src/gallium/drivers/svga/svga_winsys.h b/src/gallium/drivers/svga/svga_winsys.h
index b4e3af0eaf..d4bb176f9a 100644
--- a/src/gallium/drivers/svga/svga_winsys.h
+++ b/src/gallium/drivers/svga/svga_winsys.h
@@ -51,6 +51,7 @@ struct pipe_context;
struct pipe_fence_handle;
struct pipe_texture;
struct svga_region;
+struct winsys_handle;
#define SVGA_BUFFER_USAGE_PINNED (PIPE_BUFFER_USAGE_CUSTOM << 0)
@@ -187,6 +188,25 @@ struct svga_winsys_screen
uint32 numMipLevels);
/**
+ * Creates a surface from a winsys handle.
+ * Used to implement pipe_screen::texture_from_handle.
+ */
+ struct svga_winsys_surface *
+ (*surface_from_handle)(struct svga_winsys_screen *sws,
+ struct winsys_handle *whandle,
+ SVGA3dSurfaceFormat *format);
+
+ /**
+ * Get a winsys_handle from a surface.
+ * Used to implement pipe_screen::texture_get_handle.
+ */
+ boolean
+ (*surface_get_handle)(struct svga_winsys_screen *sws,
+ struct svga_winsys_surface *surface,
+ unsigned stride,
+ struct winsys_handle *whandle);
+
+ /**
* Whether this surface is sitting in a validate list
*/
boolean
@@ -284,19 +304,6 @@ svga_screen_buffer_wrap_surface(struct pipe_screen *screen,
struct svga_winsys_surface *srf);
struct svga_winsys_surface *
-svga_screen_texture_get_winsys_surface(struct pipe_texture *texture);
-struct svga_winsys_surface *
svga_screen_buffer_get_winsys_surface(struct pipe_buffer *buffer);
-boolean
-svga_screen_buffer_from_texture(struct pipe_texture *texture,
- struct pipe_buffer **buffer,
- unsigned *stride);
-
-struct pipe_texture *
-svga_screen_texture_wrap_surface(struct pipe_screen *screen,
- struct pipe_texture *base,
- enum SVGA3dSurfaceFormat format,
- struct svga_winsys_surface *srf);
-
#endif /* SVGA_WINSYS_H_ */