diff options
author | Michal Krol <[email protected]> | 2010-03-10 15:49:30 +0100 |
---|---|---|
committer | Michal Krol <[email protected]> | 2010-03-10 15:49:30 +0100 |
commit | 3ce4375912c8ea488460e593e07c5bb15b92dca9 (patch) | |
tree | 1011fa439bd829fd46a44fd99478135848800e73 /src/gallium/drivers/svga | |
parent | f59f28093ea827bd234d8e1a36bdd56a9fce5f09 (diff) | |
parent | 9b348d0ed125a22be3f318ac60cef6f201edfdab (diff) |
Merge branch 'master' into gallium-sampler-view
Conflicts:
src/gallium/auxiliary/Makefile
src/gallium/auxiliary/SConscript
src/gallium/auxiliary/tgsi/tgsi_exec.c
src/gallium/auxiliary/util/u_blitter.c
src/gallium/drivers/i915/i915_context.h
src/gallium/drivers/i965/brw_context.h
src/gallium/drivers/llvmpipe/lp_context.h
src/gallium/drivers/nv50/nv50_context.h
src/gallium/drivers/nv50/nv50_state_validate.c
src/gallium/drivers/nv50/nv50_tex.c
src/gallium/drivers/r300/r300_blit.c
src/gallium/drivers/r300/r300_context.h
src/gallium/drivers/r300/r300_emit.c
src/gallium/drivers/r300/r300_state.c
src/gallium/drivers/softpipe/sp_context.h
src/gallium/drivers/svga/svga_context.h
src/gallium/drivers/svga/svga_pipe_sampler.c
Diffstat (limited to 'src/gallium/drivers/svga')
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 a0da7d7e5d5..04307d17fe0 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 80410547690..da9fc4355fa 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 b1022c3c996..1f66437dfe1 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 b60117f090e..594eec7166e 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 409b3b41cbc..8483a3fad74 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 49b43bebc29..95bf0e6f91b 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 50fe962b28d..ebd1b949972 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 ffc0f99565b..1715a47fc62 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 414ac52e1f6..6022c38cfca 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 c9e9bef5406..1ff6a3a5b31 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 448ac107c7f..8c862fa62d6 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 12f3531a1df..5b581debfc7 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 24c1f78ca55..ca6602b4369 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 b4cafb8f219..b710914acda 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 dd13a89d24d..dfaab53aef4 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 107cc403b4d..b7195d246bc 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 d1066ce13b0..f531e223048 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 d7999fe53d2..781f7bf5339 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 35f36a828fd..246d34e649e 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 e8f75485d55..48eced2ecea 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 87aed39f78f..3d4f56a67bd 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 b4e3af0eafc..d4bb176f9a8 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_ */ |