Browse Source

svga: convert to use pipe_resrource

As with others so far, a fairly shallow conversion.
gallium-buffer-usage-cleanup
Keith Whitwell 16 years ago
parent
commit
a79f6a4a08
39 changed files with 2150 additions and 1882 deletions
  1. 8
    3
      src/gallium/drivers/svga/Makefile
  2. 6
    5
      src/gallium/drivers/svga/svga_cmd.c
  3. 5
    64
      src/gallium/drivers/svga/svga_context.c
  4. 1
    1
      src/gallium/drivers/svga/svga_context.h
  5. 8
    7
      src/gallium/drivers/svga/svga_draw.c
  6. 6
    6
      src/gallium/drivers/svga/svga_draw_arrays.c
  7. 12
    12
      src/gallium/drivers/svga/svga_draw_elements.c
  8. 2
    1
      src/gallium/drivers/svga/svga_pipe_blit.c
  9. 1
    1
      src/gallium/drivers/svga/svga_pipe_clear.c
  10. 3
    3
      src/gallium/drivers/svga/svga_pipe_draw.c
  11. 1
    1
      src/gallium/drivers/svga/svga_pipe_flush.c
  12. 1
    1
      src/gallium/drivers/svga/svga_pipe_misc.c
  13. 1
    1
      src/gallium/drivers/svga/svga_pipe_query.c
  14. 4
    4
      src/gallium/drivers/svga/svga_pipe_sampler.c
  15. 4
    4
      src/gallium/drivers/svga/svga_pipe_vertex.c
  16. 33
    169
      src/gallium/drivers/svga/svga_resource.c
  17. 43
    0
      src/gallium/drivers/svga/svga_resource.h
  18. 354
    0
      src/gallium/drivers/svga/svga_resource_buffer.c
  19. 20
    15
      src/gallium/drivers/svga/svga_resource_buffer.h
  20. 2
    0
      src/gallium/drivers/svga/svga_resource_buffer_host.c
  21. 90
    346
      src/gallium/drivers/svga/svga_resource_buffer_upload.c
  22. 54
    0
      src/gallium/drivers/svga/svga_resource_buffer_upload.h
  23. 635
    0
      src/gallium/drivers/svga/svga_resource_texture.c
  24. 16
    82
      src/gallium/drivers/svga/svga_resource_texture.h
  25. 198
    0
      src/gallium/drivers/svga/svga_sampler_view.c
  26. 97
    0
      src/gallium/drivers/svga/svga_sampler_view.h
  27. 4
    4
      src/gallium/drivers/svga/svga_screen.c
  28. 0
    1099
      src/gallium/drivers/svga/svga_screen_texture.c
  29. 7
    5
      src/gallium/drivers/svga/svga_state_constants.c
  30. 4
    4
      src/gallium/drivers/svga/svga_state_tss.c
  31. 5
    5
      src/gallium/drivers/svga/svga_state_vdecl.c
  32. 10
    4
      src/gallium/drivers/svga/svga_state_vs.c
  33. 384
    0
      src/gallium/drivers/svga/svga_surface.c
  34. 85
    0
      src/gallium/drivers/svga/svga_surface.h
  35. 1
    1
      src/gallium/drivers/svga/svga_swtnl.h
  36. 17
    16
      src/gallium/drivers/svga/svga_swtnl_backend.c
  37. 20
    12
      src/gallium/drivers/svga/svga_swtnl_draw.c
  38. 4
    2
      src/gallium/drivers/svga/svga_swtnl_private.h
  39. 4
    4
      src/gallium/drivers/svga/svga_winsys.h

+ 8
- 3
src/gallium/drivers/svga/Makefile View File

@@ -27,8 +27,6 @@ C_SOURCES = \
svga_pipe_vertex.c \
svga_pipe_vs.c \
svga_screen.c \
svga_screen_buffer.c \
svga_screen_texture.c \
svga_screen_cache.c \
svga_state.c \
svga_state_need_swtnl.c \
@@ -45,7 +43,14 @@ C_SOURCES = \
svga_tgsi.c \
svga_tgsi_decl_sm20.c \
svga_tgsi_decl_sm30.c \
svga_tgsi_insn.c
svga_tgsi_insn.c \
svga_sampler_view.c \
svga_surface.c \
svga_resource.c \
svga_resource_texture.c \
svga_resource_buffer.c \
svga_resource_buffer_upload.c


LIBRARY_INCLUDES = \
-I$(TOP)/src/gallium/drivers/svga/include

+ 6
- 5
src/gallium/drivers/svga/svga_cmd.c View File

@@ -31,8 +31,9 @@
*/

#include "svga_winsys.h"
#include "svga_screen_buffer.h"
#include "svga_screen_texture.h"
#include "svga_resource_buffer.h"
#include "svga_resource_texture.h"
#include "svga_surface.h"
#include "svga_cmd.h"

/*
@@ -423,7 +424,7 @@ SVGA3D_SurfaceDMA(struct svga_winsys_context *swc,
const SVGA3dCopyBox *boxes, // IN
uint32 numBoxes) // IN
{
struct svga_resource *resource = svga_texture(st->base.resource);
struct svga_texture *texture = svga_texture(st->base.resource);
SVGA3dCmdSurfaceDMA *cmd;
SVGA3dCmdSurfaceDMASuffix *pSuffix;
uint32 boxesSize = sizeof *boxes * numBoxes;
@@ -454,8 +455,8 @@ SVGA3D_SurfaceDMA(struct svga_winsys_context *swc,
cmd->guest.pitch = st->base.stride;

swc->surface_relocation(swc, &cmd->host.sid, texture->handle, surface_flags);
cmd->host.face = st->base.face; /* PIPE_TEX_FACE_* and SVGA3D_CUBEFACE_* match */
cmd->host.mipmap = st->base.level;
cmd->host.face = st->base.sr.face; /* PIPE_TEX_FACE_* and SVGA3D_CUBEFACE_* match */
cmd->host.mipmap = st->base.sr.level;

cmd->transfer = transfer;


+ 5
- 64
src/gallium/drivers/svga/svga_context.c View File

@@ -34,8 +34,9 @@

#include "svga_context.h"
#include "svga_screen.h"
#include "svga_screen_texture.h"
#include "svga_screen_buffer.h"
#include "svga_resource_texture.h"
#include "svga_resource_buffer.h"
#include "svga_resource.h"
#include "svga_winsys.h"
#include "svga_swtnl.h"
#include "svga_draw.h"
@@ -71,59 +72,6 @@ static void svga_destroy( struct pipe_context *pipe )
FREE( svga );
}

static unsigned int
svga_is_texture_referenced( struct pipe_context *pipe,
struct pipe_texture *texture,
unsigned face, unsigned level)
{
struct svga_texture *tex = svga_texture(texture);
struct svga_screen *ss = svga_screen(pipe->screen);

/**
* The screen does not cache texture writes.
*/

if (!tex->handle || ss->sws->surface_is_flushed(ss->sws, tex->handle))
return PIPE_UNREFERENCED;

/**
* sws->surface_is_flushed() does not distinguish between read references
* and write references. So assume a reference is both.
*/

return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
}

static unsigned int
svga_is_buffer_referenced( struct pipe_context *pipe,
struct pipe_buffer *buf)

{
struct svga_screen *ss = svga_screen(pipe->screen);
struct svga_buffer *sbuf = svga_buffer(buf);

/**
* XXX: Check this.
* The screen may cache buffer writes, but when we map, we map out
* of those cached writes, so we don't need to set a
* PIPE_REFERENCED_FOR_WRITE flag for cached buffers.
*/

if (!sbuf->handle || ss->sws->surface_is_flushed(ss->sws, sbuf->handle))
return PIPE_UNREFERENCED;

/**
* sws->surface_is_flushed() does not distinguish between read references
* and write references. So assume a reference is both,
* however, we make an exception for index- and vertex buffers, to avoid
* a flush in st_bufferobj_get_subdata, during display list replay.
*/

if (sbuf->base.usage & (PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_INDEX))
return PIPE_REFERENCED_FOR_READ;

return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
}


struct pipe_context *svga_context_create( struct pipe_screen *screen,
@@ -147,14 +95,7 @@ struct pipe_context *svga_context_create( struct pipe_screen *screen,
if(!svga->swc)
goto no_swc;

/*
svga->rm_context = rm_create_context( &svga->base,
svgascreen->rm_screen,
&svga_rm_context_callbacks );
svga_init_resource_functions(svga);
*/
svga_init_texture_functions(&svga->pipe);

svga_init_blend_functions(svga);
svga_init_blit_functions(svga);
svga_init_depth_stencil_functions(svga);
@@ -187,14 +128,14 @@ struct pipe_context *svga_context_create( struct pipe_screen *screen,
if (svga->vs_bm == NULL)
goto no_vs_bm;

svga->upload_ib = u_upload_create( svga->pipe.screen,
svga->upload_ib = u_upload_create( &svga->pipe,
32 * 1024,
16,
PIPE_BUFFER_USAGE_INDEX );
if (svga->upload_ib == NULL)
goto no_upload_ib;

svga->upload_vb = u_upload_create( svga->pipe.screen,
svga->upload_vb = u_upload_create( &svga->pipe,
128 * 1024,
16,
PIPE_BUFFER_USAGE_VERTEX );

+ 1
- 1
src/gallium/drivers/svga/svga_context.h View File

@@ -254,7 +254,7 @@ struct svga_hw_clear_state

struct svga_hw_view_state
{
struct pipe_texture *texture;
struct pipe_resource *texture;
struct svga_sampler_view *v;
unsigned min_lod;
unsigned max_lod;

+ 8
- 7
src/gallium/drivers/svga/svga_draw.c View File

@@ -34,8 +34,9 @@
#include "svga_draw_private.h"
#include "svga_debug.h"
#include "svga_screen.h"
#include "svga_screen_buffer.h"
#include "svga_screen_texture.h"
#include "svga_resource_buffer.h"
#include "svga_resource_texture.h"
#include "svga_surface.h"
#include "svga_winsys.h"
#include "svga_cmd.h"

@@ -103,7 +104,7 @@ void svga_hwtnl_reset_vdecl( struct svga_hwtnl *hwtnl,
assert(hwtnl->cmd.prim_count == 0);

for (i = count; i < hwtnl->cmd.vdecl_count; i++) {
pipe_buffer_reference(&hwtnl->cmd.vdecl_vb[i],
pipe_resource_reference(&hwtnl->cmd.vdecl_vb[i],
NULL);
}

@@ -209,7 +210,7 @@ svga_hwtnl_flush( struct svga_hwtnl *hwtnl )
&prim[i].indexArray.surfaceId,
ib_handle[i],
PIPE_BUFFER_USAGE_GPU_READ);
pipe_buffer_reference(&hwtnl->cmd.prim_ib[i], NULL);
pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
}
SVGA_FIFOCommitAll( swc );
@@ -240,7 +241,7 @@ enum pipe_error svga_hwtnl_prim( struct svga_hwtnl *hwtnl,
unsigned i;
for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
struct pipe_resource *vb = hwtnl->cmd.vdecl_vb[i];
unsigned size = vb ? vb->size : 0;
unsigned size = vb ? vb->width0 : 0;
unsigned offset = hwtnl->cmd.vdecl[i].array.offset;
unsigned stride = hwtnl->cmd.vdecl[i].array.stride;
unsigned index_bias = range->indexBias;
@@ -323,7 +324,7 @@ enum pipe_error svga_hwtnl_prim( struct svga_hwtnl *hwtnl,
assert(range->indexWidth == range->indexArray.stride);

if(ib) {
unsigned size = ib->size;
unsigned size = ib->width0;
unsigned offset = range->indexArray.offset;
unsigned stride = range->indexArray.stride;
unsigned count;
@@ -374,7 +375,7 @@ enum pipe_error svga_hwtnl_prim( struct svga_hwtnl *hwtnl,

hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range;

pipe_buffer_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib);
pipe_resource_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib);
hwtnl->cmd.prim_count++;

return ret;

+ 6
- 6
src/gallium/drivers/svga/svga_draw_arrays.c View File

@@ -98,7 +98,7 @@ static enum pipe_error retrieve_or_generate_indices( struct svga_hwtnl *hwtnl,
unsigned gen_nr,
unsigned gen_size,
u_generate_func generate,
struct pipe_buffer **out_buf )
struct pipe_resource **out_buf )
{
enum pipe_error ret = PIPE_OK;
int i;
@@ -119,7 +119,7 @@ static enum pipe_error retrieve_or_generate_indices( struct svga_hwtnl *hwtnl,
}
else if (gen_type == U_GENERATE_REUSABLE)
{
pipe_buffer_reference( &hwtnl->index_cache[prim][i].buffer,
pipe_resource_reference( &hwtnl->index_cache[prim][i].buffer,
NULL );

if (DBG)
@@ -151,7 +151,7 @@ static enum pipe_error retrieve_or_generate_indices( struct svga_hwtnl *hwtnl,

assert (smallest != IDX_CACHE_MAX);

pipe_buffer_reference( &hwtnl->index_cache[prim][smallest].buffer,
pipe_resource_reference( &hwtnl->index_cache[prim][smallest].buffer,
NULL );

if (DBG)
@@ -173,7 +173,7 @@ static enum pipe_error retrieve_or_generate_indices( struct svga_hwtnl *hwtnl,

hwtnl->index_cache[prim][i].generate = generate;
hwtnl->index_cache[prim][i].gen_nr = gen_nr;
pipe_buffer_reference( &hwtnl->index_cache[prim][i].buffer,
pipe_resource_reference( &hwtnl->index_cache[prim][i].buffer,
*out_buf );

if (DBG)
@@ -261,7 +261,7 @@ svga_hwtnl_draw_arrays( struct svga_hwtnl *hwtnl,
return simple_draw_arrays( hwtnl, gen_prim, start, count );
}
else {
struct pipe_buffer *gen_buf = NULL;
struct pipe_resource *gen_buf = NULL;

/* Need to draw as indexed primitive.
* Potentially need to run the gen func to build an index buffer.
@@ -290,7 +290,7 @@ svga_hwtnl_draw_arrays( struct svga_hwtnl *hwtnl,

done:
if (gen_buf)
pipe_buffer_reference( &gen_buf, NULL );
pipe_resource_reference( &gen_buf, NULL );

return ret;
}

+ 12
- 12
src/gallium/drivers/svga/svga_draw_elements.c View File

@@ -30,7 +30,7 @@
#include "svga_cmd.h"
#include "svga_draw.h"
#include "svga_draw_private.h"
#include "svga_screen_buffer.h"
#include "svga_resource_buffer.h"
#include "svga_winsys.h"
#include "svga_context.h"

@@ -39,22 +39,22 @@

static enum pipe_error
translate_indices( struct svga_hwtnl *hwtnl,
struct pipe_buffer *src,
struct pipe_resource *src,
unsigned offset,
unsigned nr,
unsigned index_size,
u_translate_func translate,
struct pipe_buffer **out_buf )
struct pipe_resource **out_buf )
{
struct pipe_context *pipe = &hwtnl->svga->pipe;
struct pipe_transfer *src_transfer = NULL;
struct pipe_transfer *dst_transfer = NULL;
unsigned size = index_size * nr;
const void *src_map = NULL;
struct pipe_buffer *dst = NULL;
struct pipe_resource *dst = NULL;
void *dst_map = NULL;

dst = pipe_buffer_create( screen, 32,
dst = pipe_buffer_create( pipe->screen, 32,
PIPE_BUFFER_USAGE_INDEX |
PIPE_BUFFER_USAGE_CPU_WRITE |
PIPE_BUFFER_USAGE_GPU_READ,
@@ -99,7 +99,7 @@ fail:

enum pipe_error
svga_hwtnl_simple_draw_range_elements( struct svga_hwtnl *hwtnl,
struct pipe_buffer *index_buffer,
struct pipe_resource *index_buffer,
unsigned index_size,
unsigned min_index,
unsigned max_index,
@@ -108,7 +108,7 @@ svga_hwtnl_simple_draw_range_elements( struct svga_hwtnl *hwtnl,
unsigned count,
unsigned bias )
{
struct pipe_buffer *upload_buffer = NULL;
struct pipe_resource *upload_buffer = NULL;
SVGA3dPrimitiveRange range;
unsigned hw_prim;
unsigned hw_count;
@@ -122,7 +122,7 @@ svga_hwtnl_simple_draw_range_elements( struct svga_hwtnl *hwtnl,
if (index_buffer &&
svga_buffer_is_user_buffer(index_buffer))
{
assert( index_buffer->size >= index_offset + count * index_size );
assert( index_buffer->width0 >= index_offset + count * index_size );

ret = u_upload_buffer( hwtnl->upload_ib,
index_offset,
@@ -153,7 +153,7 @@ svga_hwtnl_simple_draw_range_elements( struct svga_hwtnl *hwtnl,

done:
if (upload_buffer)
pipe_buffer_reference( &upload_buffer, NULL );
pipe_resource_reference( &upload_buffer, NULL );

return ret;
}
@@ -163,7 +163,7 @@ done:

enum pipe_error
svga_hwtnl_draw_range_elements( struct svga_hwtnl *hwtnl,
struct pipe_buffer *index_buffer,
struct pipe_resource *index_buffer,
unsigned index_size,
unsigned min_index,
unsigned max_index,
@@ -211,7 +211,7 @@ svga_hwtnl_draw_range_elements( struct svga_hwtnl *hwtnl,
gen_prim, start, count, bias );
}
else {
struct pipe_buffer *gen_buf = NULL;
struct pipe_resource *gen_buf = NULL;

/* Need to allocate a new index buffer and run the translate
* func to populate it. Could potentially cache this translated
@@ -244,7 +244,7 @@ svga_hwtnl_draw_range_elements( struct svga_hwtnl *hwtnl,

done:
if (gen_buf)
pipe_buffer_reference( &gen_buf, NULL );
pipe_resource_reference( &gen_buf, NULL );

return ret;
}

+ 2
- 1
src/gallium/drivers/svga/svga_pipe_blit.c View File

@@ -23,10 +23,11 @@
*
**********************************************************/

#include "svga_screen_texture.h"
#include "svga_resource_texture.h"
#include "svga_context.h"
#include "svga_debug.h"
#include "svga_cmd.h"
#include "svga_surface.h"

#define FILE_DEBUG_FLAG DEBUG_BLIT


+ 1
- 1
src/gallium/drivers/svga/svga_pipe_clear.c View File

@@ -31,7 +31,7 @@

#include "svga_context.h"
#include "svga_state.h"
#include "svga_screen_texture.h"
#include "svga_surface.h"


static enum pipe_error

+ 3
- 3
src/gallium/drivers/svga/svga_pipe_draw.c View File

@@ -42,7 +42,7 @@

static enum pipe_error
retry_draw_range_elements( struct svga_context *svga,
struct pipe_buffer *index_buffer,
struct pipe_resource *index_buffer,
unsigned index_size,
unsigned min_index,
unsigned max_index,
@@ -150,7 +150,7 @@ retry:

static void
svga_draw_range_elements( struct pipe_context *pipe,
struct pipe_buffer *index_buffer,
struct pipe_resource *index_buffer,
unsigned index_size,
unsigned min_index,
unsigned max_index,
@@ -224,7 +224,7 @@ svga_draw_range_elements( struct pipe_context *pipe,

static void
svga_draw_elements( struct pipe_context *pipe,
struct pipe_buffer *index_buffer,
struct pipe_resource *index_buffer,
unsigned index_size,
unsigned prim, unsigned start, unsigned count)
{

+ 1
- 1
src/gallium/drivers/svga/svga_pipe_flush.c View File

@@ -25,7 +25,7 @@

#include "pipe/p_defines.h"
#include "svga_screen.h"
#include "svga_screen_texture.h"
#include "svga_surface.h"
#include "svga_context.h"
#include "svga_debug.h"


+ 1
- 1
src/gallium/drivers/svga/svga_pipe_misc.c View File

@@ -28,7 +28,7 @@
#include "util/u_inlines.h"

#include "svga_context.h"
#include "svga_screen_texture.h"
#include "svga_surface.h"


static void svga_set_scissor_state( struct pipe_context *pipe,

+ 1
- 1
src/gallium/drivers/svga/svga_pipe_query.c View File

@@ -30,7 +30,7 @@
#include "svga_cmd.h"
#include "svga_context.h"
#include "svga_screen.h"
#include "svga_screen_buffer.h"
#include "svga_resource_buffer.h"
#include "svga_winsys.h"
#include "svga_debug.h"


+ 4
- 4
src/gallium/drivers/svga/svga_pipe_sampler.c View File

@@ -30,7 +30,7 @@
#include "tgsi/tgsi_parse.h"

#include "svga_context.h"
#include "svga_screen_texture.h"
#include "svga_resource_texture.h"

#include "svga_debug.h"

@@ -178,7 +178,7 @@ static void svga_delete_sampler_state(struct pipe_context *pipe,

static struct pipe_sampler_view *
svga_create_sampler_view(struct pipe_context *pipe,
struct pipe_texture *texture,
struct pipe_resource *texture,
const struct pipe_sampler_view *templ)
{
struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
@@ -187,7 +187,7 @@ svga_create_sampler_view(struct pipe_context *pipe,
*view = *templ;
view->reference.count = 1;
view->texture = NULL;
pipe_texture_reference(&view->texture, texture);
pipe_resource_reference(&view->texture, texture);
view->context = pipe;
}

@@ -199,7 +199,7 @@ static void
svga_sampler_view_destroy(struct pipe_context *pipe,
struct pipe_sampler_view *view)
{
pipe_texture_reference(&view->texture, NULL);
pipe_resource_reference(&view->texture, NULL);
FREE(view);
}


+ 4
- 4
src/gallium/drivers/svga/svga_pipe_vertex.c View File

@@ -30,7 +30,7 @@
#include "tgsi/tgsi_parse.h"

#include "svga_screen.h"
#include "svga_screen_buffer.h"
#include "svga_resource_buffer.h"
#include "svga_context.h"


@@ -49,13 +49,13 @@ 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);
pipe_resource_reference(&svga->curr.vb[i].buffer, buffers[i].buffer);
if (svga_buffer_is_user_buffer(buffers[i].buffer))
any_user_buffer = TRUE;
}

for ( ; i < svga->curr.num_vertex_buffers; i++)
pipe_buffer_reference(&svga->curr.vb[i].buffer, NULL);
pipe_resource_reference(&svga->curr.vb[i].buffer, NULL);

/* Copy remaining data */
memcpy(svga->curr.vb, buffers, count * sizeof buffers[0]);
@@ -102,7 +102,7 @@ void svga_cleanup_vertex_state( struct svga_context *svga )
unsigned i;
for (i = 0 ; i < svga->curr.num_vertex_buffers; i++)
pipe_buffer_reference(&svga->curr.vb[i].buffer, NULL);
pipe_resource_reference(&svga->curr.vb[i].buffer, NULL);
}



+ 33
- 169
src/gallium/drivers/svga/svga_resource.c View File

@@ -1,191 +1,55 @@
/**********************************************************
* Copyright 2008-2009 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************/
#include "util/u_debug.h"

#include "svga_cmd.h"

#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "os/os_thread.h"
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"

#include "svga_screen.h"
#include "svga_resource.h"
#include "svga_resource_buffer.h"
#include "svga_resource_texture.h"
#include "svga_context.h"
#include "svga_screen_texture.h"
#include "svga_screen_buffer.h"
#include "svga_winsys.h"
#include "svga_debug.h"
#include "svga_screen_buffer.h"
#include "svga_screen.h"

#include <util/u_string.h>

/* Use the pipe resource_manager module to implemen the new-style
* driver functions in terms of the old ones we have already.
*/
static struct pipe_resource *
svga_resource_create(struct pipe_screen *screen,
const struct pipe_resource *template)
{
struct svga_screen *ss = svga_screen(screen);
return rm_resource_create(ss->rm_screen,
template);
}

static struct pipe_resource *
svga_resource_from_handle(struct pipe_screen *screen,
const struct pipe_resource *template,
struct winsys_handle *handle)
const struct pipe_resource *template)
{
struct svga_screen *ss = svga_screen(screen);
return rm_resource_from_handle(ss->rm_screen,
template,
handle);
}
if (template->target == PIPE_BUFFER)
return svga_buffer_create(screen, template);
else
return svga_resource_create(screen, template);

boolean svga_resource_get_handle(struct pipe_screen *screen,
struct pipe_resource *resource,
struct winsys_handle *handle)
{
struct svga_screen *ss = svga_screen(screen);
return rm_resource_get_handle(ss->rm_screen,
resource,
handle);
}


void svga_resource_destroy(struct pipe_screen *screen,
struct pipe_resource *resource)
{
struct svga_screen *ss = svga_screen(screen);
rm_resource_destroy(ss->rm_screen,
resource);
}

struct pipe_transfer *svga_get_transfer(struct pipe_context *pipe,
struct pipe_resource *resource,
struct pipe_subresource sr,
enum pipe_transfer_usage usage,
const struct pipe_box *box)
{
struct svga_context *sc = svga_context(pipe);
return rm_get_transfer(sc->rm_context,
resource,
sr,
usage,
box);
}

void svga_transfer_destroy(struct pipe_context *pipe,
struct pipe_transfer *transfer)
{
struct svga_context *sc = svga_context(pipe);
rm_transfer_destroy(sc->rm_context,
transfer);
}

void *svga_transfer_map( struct pipe_context *pipe,
struct pipe_transfer *transfer )
{
struct svga_context *sc = svga_context(pipe);
return rm_transfer_map(sc->rm_context,
transfer);
}

void svga_transfer_flush_region( struct pipe_context *pipe,
struct pipe_transfer *transfer,
const struct pipe_box *box )
{
struct svga_context *sc = svga_context(pipe);
rm_transfer_flush_region(sc->rm_context,
transfer,
box);
}

void svga_transfer_unmap( struct pipe_context *pipe,
struct pipe_transfer *transfer )
static struct pipe_resource *
svga_resource_from_handle(struct pipe_screen * screen,
const struct pipe_resource *template,
struct winsys_handle *whandle)
{
struct svga_context *sc = svga_context(pipe);
rm_transfer_unmap(sc->rm_context,
transfer);
if (template->target == PIPE_BUFFER)
return NULL;
else
return svga_resource_from_handle(screen, template, whandle);
}


void svga_transfer_inline_write( struct pipe_context *pipe,
struct pipe_resource *resource,
struct pipe_subresource sr,
enum pipe_transfer_usage usage,
const struct pipe_box *box,
const void *data )
{
struct svga_context *sc = svga_context(pipe);
rm_transfer_inline_write(sc->rm_context,
resource,
sr,
usage,
box,
data);
}

void svga_transfer_inline_read( struct pipe_context *pipe,
struct pipe_resource *resource,
struct pipe_subresource sr,
enum pipe_transfer_usage usage,
const struct pipe_box *box,
void *data )
void
svga_init_resource_functions(struct svga_context *svga)
{
struct svga_context *sc = svga_context(pipe);
rm_transfer_inline_read(sc->rm_context,
resource,
sr,
usage,
box,
data);
svga->pipe.get_transfer = u_get_transfer_vtbl;
svga->pipe.transfer_map = u_transfer_map_vtbl;
svga->pipe.transfer_flush_region = u_transfer_flush_region_vtbl;
svga->pipe.transfer_unmap = u_transfer_unmap_vtbl;
svga->pipe.transfer_destroy = u_transfer_destroy_vtbl;
svga->pipe.transfer_inline_write = u_transfer_inline_write_vtbl;
}



void
svga_init_resource_functions(struct pipe_context *pipe)
svga_init_screen_resource_functions(struct svga_screen *is)
{
pipe->get_transfer = svga_get_transfer;
pipe->transfer_map = svga_transfer_map;
pipe->transfer_unmap = svga_transfer_unmap;
pipe->transfer_destroy = svga_transfer_destroy;
is->screen.resource_create = svga_resource_create;
is->screen.resource_from_handle = svga_resource_from_handle;
is->screen.resource_get_handle = u_resource_get_handle_vtbl;
is->screen.resource_destroy = u_resource_destroy_vtbl;
is->screen.user_buffer_create = svga_user_buffer_create;
}


void
svga_screen_init_resource_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;
}


+ 43
- 0
src/gallium/drivers/svga/svga_resource.h View File

@@ -0,0 +1,43 @@
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/

#ifndef SVGA_RESOURCE_H
#define SVGA_RESOURCE_H

struct svga_screen;

#include "util/u_debug.h"

struct svga_context;
struct svga_screen;


void svga_init_screen_resource_functions(struct svga_screen *is);
void svga_init_resource_functions(struct svga_context *svga );


#endif /* SVGA_RESOURCE_H */

+ 354
- 0
src/gallium/drivers/svga/svga_resource_buffer.c View File

@@ -0,0 +1,354 @@
/**********************************************************
* Copyright 2008-2009 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************/

#include "svga_cmd.h"

#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "os/os_thread.h"
#include "util/u_math.h"
#include "util/u_memory.h"

#include "svga_context.h"
#include "svga_screen.h"
#include "svga_resource_buffer.h"
#include "svga_resource_buffer_upload.h"
#include "svga_winsys.h"
#include "svga_debug.h"


/**
* Vertex and index buffers need hardware backing. Constant buffers
* do not. No other types of buffers currently supported.
*/
static INLINE boolean
svga_buffer_needs_hw_storage(unsigned usage)
{
return usage & (PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_INDEX);
}


static unsigned int
svga_buffer_is_referenced( struct pipe_context *pipe,
struct pipe_resource *buf,
unsigned face, unsigned level)
{
struct svga_screen *ss = svga_screen(pipe->screen);
struct svga_buffer *sbuf = svga_buffer(buf);

/**
* XXX: Check this.
* The screen may cache buffer writes, but when we map, we map out
* of those cached writes, so we don't need to set a
* PIPE_REFERENCED_FOR_WRITE flag for cached buffers.
*/

if (!sbuf->handle || ss->sws->surface_is_flushed(ss->sws, sbuf->handle))
return PIPE_UNREFERENCED;

/**
* sws->surface_is_flushed() does not distinguish between read references
* and write references. So assume a reference is both,
* however, we make an exception for index- and vertex buffers, to avoid
* a flush in st_bufferobj_get_subdata, during display list replay.
*/

if (sbuf->b.b.usage & (PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_INDEX))
return PIPE_REFERENCED_FOR_READ;

return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
}






static void *
svga_buffer_map_range( struct pipe_screen *screen,
struct pipe_resource *buf,
unsigned offset,
unsigned length,
unsigned usage )
{
struct svga_screen *ss = svga_screen(screen);
struct svga_winsys_screen *sws = ss->sws;
struct svga_buffer *sbuf = svga_buffer( buf );
void *map;

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->b.b.width0 + 1023)/1024);

sbuf->swbuf = align_malloc(sbuf->b.b.width0, 16);
}
}

if (sbuf->swbuf) {
/* User/malloc buffer */
map = sbuf->swbuf;
}
else if (sbuf->hwbuf) {
map = sws->buffer_map(sws, sbuf->hwbuf, usage);
}
else {
map = NULL;
}

if(map) {
pipe_mutex_lock(ss->swc_mutex);

++sbuf->map.count;

if (usage & PIPE_TRANSFER_WRITE) {
assert(sbuf->map.count <= 1);
sbuf->map.writing = TRUE;
if (usage & PIPE_TRANSFER_FLUSH_EXPLICIT)
sbuf->map.flush_explicit = TRUE;
}
pipe_mutex_unlock(ss->swc_mutex);
}
return map;
}



static void
svga_buffer_flush_mapped_range( struct pipe_screen *screen,
struct pipe_resource *buf,
unsigned offset, unsigned length)
{
struct svga_buffer *sbuf = svga_buffer( buf );
struct svga_screen *ss = svga_screen(screen);
pipe_mutex_lock(ss->swc_mutex);
assert(sbuf->map.writing);
if(sbuf->map.writing) {
assert(sbuf->map.flush_explicit);
svga_buffer_add_range(sbuf, offset, offset + length);
}
pipe_mutex_unlock(ss->swc_mutex);
}

static void
svga_buffer_unmap( struct pipe_screen *screen,
struct pipe_resource *buf)
{
struct svga_screen *ss = svga_screen(screen);
struct svga_winsys_screen *sws = ss->sws;
struct svga_buffer *sbuf = svga_buffer( buf );
pipe_mutex_lock(ss->swc_mutex);
assert(sbuf->map.count);
if(sbuf->map.count)
--sbuf->map.count;

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");
svga_buffer_add_range(sbuf, 0, sbuf->b.b.width0);
}
sbuf->map.writing = FALSE;
sbuf->map.flush_explicit = FALSE;
}

pipe_mutex_unlock(ss->swc_mutex);
}



static void
svga_buffer_destroy( struct pipe_screen *screen,
struct pipe_resource *buf )
{
struct svga_screen *ss = svga_screen(screen);
struct svga_buffer *sbuf = svga_buffer( buf );

assert(!p_atomic_read(&buf->reference.count));
assert(!sbuf->dma.pending);

if(sbuf->handle)
svga_buffer_destroy_host_surface(ss, sbuf);
if(sbuf->uploaded.buffer)
pipe_resource_reference(&sbuf->uploaded.buffer, NULL);

if(sbuf->hwbuf)
svga_buffer_destroy_hw_storage(ss, sbuf);
if(sbuf->swbuf && !sbuf->user)
align_free(sbuf->swbuf);
FREE(sbuf);
}


/* Keep the original code more or less intact, implement transfers in
* terms of the old functions.
*/
static void *
svga_buffer_transfer_map( struct pipe_context *pipe,
struct pipe_transfer *transfer )
{
uint8_t *map = svga_buffer_map_range( pipe->screen,
transfer->resource,
transfer->box.x,
transfer->box.width,
transfer->usage );
if (map == NULL)
return NULL;

/* map_buffer() returned a pointer to the beginning of the buffer,
* but transfers are expected to return a pointer to just the
* region specified in the box.
*/
return map + transfer->box.x;
}



static void svga_buffer_transfer_flush_region( struct pipe_context *pipe,
struct pipe_transfer *transfer,
const struct pipe_box *box)
{
assert(box->x + box->width <= transfer->box.width);

svga_buffer_flush_mapped_range(pipe->screen,
transfer->resource,
transfer->box.x + box->x,
box->width);
}

static void svga_buffer_transfer_unmap( struct pipe_context *pipe,
struct pipe_transfer *transfer )
{
svga_buffer_unmap(pipe->screen,
transfer->resource);
}







struct u_resource_vtbl svga_buffer_vtbl =
{
u_default_resource_get_handle, /* get_handle */
svga_buffer_destroy, /* resource_destroy */
svga_buffer_is_referenced, /* is_resource_referenced */
u_default_get_transfer, /* get_transfer */
u_default_transfer_destroy, /* transfer_destroy */
svga_buffer_transfer_map, /* transfer_map */
svga_buffer_transfer_flush_region, /* transfer_flush_region */
svga_buffer_transfer_unmap, /* transfer_unmap */
u_default_transfer_inline_write /* transfer_inline_write */
};



struct pipe_resource *
svga_buffer_create(struct pipe_screen *screen,
const struct pipe_resource *template)
{
struct svga_screen *ss = svga_screen(screen);
struct svga_buffer *sbuf;
sbuf = CALLOC_STRUCT(svga_buffer);
if(!sbuf)
goto error1;
sbuf->b.b = *template;
sbuf->b.vtbl = &svga_buffer_vtbl;
pipe_reference_init(&sbuf->b.b.reference, 1);
sbuf->b.b.screen = screen;

if(svga_buffer_needs_hw_storage(template->usage)) {
if(svga_buffer_create_host_surface(ss, sbuf) != PIPE_OK)
goto error2;
}
else {
sbuf->swbuf = align_malloc(template->width0, 64);
if(!sbuf->swbuf)
goto error2;
}
return &sbuf->b.b;

error2:
FREE(sbuf);
error1:
return NULL;
}

struct pipe_resource *
svga_user_buffer_create(struct pipe_screen *screen,
void *ptr,
unsigned bytes,
unsigned usage)
{
struct svga_buffer *sbuf;
sbuf = CALLOC_STRUCT(svga_buffer);
if(!sbuf)
goto no_sbuf;
pipe_reference_init(&sbuf->b.b.reference, 1);
sbuf->b.vtbl = &svga_buffer_vtbl;
sbuf->b.b.screen = screen;
sbuf->b.b.format = PIPE_FORMAT_R8_UNORM; /* ?? */
sbuf->b.b.usage = PIPE_BUFFER_USAGE_CPU_READ | usage;
sbuf->b.b.width0 = bytes;
sbuf->b.b.height0 = 1;
sbuf->b.b.depth0 = 1;

sbuf->swbuf = ptr;
sbuf->user = TRUE;
return &sbuf->b.b;

no_sbuf:
return NULL;
}




src/gallium/drivers/svga/svga_screen_buffer.h → src/gallium/drivers/svga/svga_resource_buffer.h View File

@@ -29,15 +29,13 @@

#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "piperesource/rm_public.h"
#include "util/u_transfer.h"

#include "util/u_double_list.h"

#include "svga_screen_cache.h"


#define SVGA_BUFFER_MAGIC 0x344f9005

/**
* Maximum number of discontiguous ranges
*/
@@ -50,6 +48,8 @@ struct svga_winsys_buffer;
struct svga_winsys_surface;


extern struct u_resource_vtbl svga_buffer_vtbl;

struct svga_buffer_range
{
unsigned start;
@@ -62,12 +62,7 @@ struct svga_buffer_range
*/
struct svga_buffer
{
struct pipe_buffer base;

/**
* Marker to detect bad casts in runtime.
*/
uint32_t magic;
struct u_resource b;

/**
* Regular (non DMA'able) memory.
@@ -139,7 +134,7 @@ struct svga_buffer
* Information about uploaded version of user buffers.
*/
struct {
struct pipe_buffer *buffer;
struct pipe_resource *buffer;

/**
* We combine multiple user buffers into the same hardware buffer. This
@@ -191,10 +186,10 @@ struct svga_buffer


static INLINE struct svga_buffer *
svga_buffer(struct pipe_buffer *buffer)
svga_buffer(struct pipe_resource *buffer)
{
if (buffer) {
assert(((struct svga_buffer *)buffer)->magic == SVGA_BUFFER_MAGIC);
assert(((struct svga_buffer *)buffer)->b.vtbl == &svga_buffer_vtbl);
return (struct svga_buffer *)buffer;
}
return NULL;
@@ -206,14 +201,24 @@ svga_buffer(struct pipe_buffer *buffer)
* decide to use an alternate upload path for these buffers.
*/
static INLINE boolean
svga_buffer_is_user_buffer( struct pipe_buffer *buffer )
svga_buffer_is_user_buffer( struct pipe_resource *buffer )
{
return svga_buffer(buffer)->user;
}


void
svga_screen_init_buffer_functions(struct pipe_screen *screen);


struct pipe_resource *
svga_user_buffer_create(struct pipe_screen *screen,
void *ptr,
unsigned bytes,
unsigned usage);

struct pipe_resource *
svga_buffer_create(struct pipe_screen *screen,
const struct pipe_resource *template);



/**

+ 2
- 0
src/gallium/drivers/svga/svga_resource_buffer_host.c View File

@@ -0,0 +1,2 @@



src/gallium/drivers/svga/svga_screen_buffer.c → src/gallium/drivers/svga/svga_resource_buffer_upload.c View File

@@ -34,88 +34,14 @@

#include "svga_context.h"
#include "svga_screen.h"
#include "svga_screen_buffer.h"
#include "svga_resource_buffer.h"
#include "svga_resource_buffer_upload.h"
#include "svga_winsys.h"
#include "svga_debug.h"


/**
* Vertex and index buffers have to be treated slightly differently from
* regular guest memory regions because the SVGA device sees them as
* surfaces, and the state tracker can create/destroy without the pipe
* driver, therefore we must do the uploads from the vws.
/* Allocate a winsys_buffer (ie. DMA, aka GMR memory).
*/
static INLINE boolean
svga_buffer_needs_hw_storage(unsigned usage)
{
return usage & (PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_INDEX);
}


static INLINE enum pipe_error
svga_buffer_create_host_surface(struct svga_screen *ss,
struct svga_buffer *sbuf)
{
if(!sbuf->handle) {
sbuf->key.flags = 0;
sbuf->key.format = SVGA3D_BUFFER;
if(sbuf->base.usage & PIPE_BUFFER_USAGE_VERTEX)
sbuf->key.flags |= SVGA3D_SURFACE_HINT_VERTEXBUFFER;
if(sbuf->base.usage & PIPE_BUFFER_USAGE_INDEX)
sbuf->key.flags |= SVGA3D_SURFACE_HINT_INDEXBUFFER;
sbuf->key.size.width = sbuf->base.size;
sbuf->key.size.height = 1;
sbuf->key.size.depth = 1;
sbuf->key.numFaces = 1;
sbuf->key.numMipLevels = 1;
sbuf->key.cachable = 1;
SVGA_DBG(DEBUG_DMA, "surface_create for buffer sz %d\n", sbuf->base.size);

sbuf->handle = svga_screen_surface_create(ss, &sbuf->key);
if(!sbuf->handle)
return PIPE_ERROR_OUT_OF_MEMORY;
/* Always set the discard flag on the first time the buffer is written
* as svga_screen_surface_create might have passed a recycled host
* buffer.
*/
sbuf->dma.flags.discard = TRUE;

SVGA_DBG(DEBUG_DMA, " --> got sid %p sz %d (buffer)\n", sbuf->handle, sbuf->base.size);
}
return PIPE_OK;
}


static INLINE void
svga_buffer_destroy_host_surface(struct svga_screen *ss,
struct svga_buffer *sbuf)
{
if(sbuf->handle) {
SVGA_DBG(DEBUG_DMA, " ungrab sid %p sz %d\n", sbuf->handle, sbuf->base.size);
svga_screen_surface_destroy(ss, &sbuf->key, &sbuf->handle);
}
}


static INLINE void
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->hwbuf);
if(sbuf->hwbuf) {
sws->buffer_destroy(sws, sbuf->hwbuf);
sbuf->hwbuf = NULL;
}
}

struct svga_winsys_buffer *
svga_winsys_buffer_create( struct svga_screen *ss,
unsigned alignment,
@@ -142,21 +68,36 @@ svga_winsys_buffer_create( struct svga_screen *ss,
}


void
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->hwbuf);
if(sbuf->hwbuf) {
sws->buffer_destroy(sws, sbuf->hwbuf);
sbuf->hwbuf = NULL;
}
}



/**
* Allocate DMA'ble storage for the buffer.
*
* Called before mapping a buffer.
*/
static INLINE enum pipe_error
enum pipe_error
svga_buffer_create_hw_storage(struct svga_screen *ss,
struct svga_buffer *sbuf)
{
assert(!sbuf->user);

if(!sbuf->hwbuf) {
unsigned alignment = sbuf->base.alignment;
unsigned alignment = 16;
unsigned usage = 0;
unsigned size = sbuf->base.size;
unsigned size = sbuf->b.b.width0;
sbuf->hwbuf = svga_winsys_buffer_create(ss, alignment, usage, size);
if(!sbuf->hwbuf)
@@ -169,6 +110,58 @@ svga_buffer_create_hw_storage(struct svga_screen *ss,
}



enum pipe_error
svga_buffer_create_host_surface(struct svga_screen *ss,
struct svga_buffer *sbuf)
{
if(!sbuf->handle) {
sbuf->key.flags = 0;
sbuf->key.format = SVGA3D_BUFFER;
if(sbuf->b.b.usage & PIPE_BUFFER_USAGE_VERTEX)
sbuf->key.flags |= SVGA3D_SURFACE_HINT_VERTEXBUFFER;
if(sbuf->b.b.usage & PIPE_BUFFER_USAGE_INDEX)
sbuf->key.flags |= SVGA3D_SURFACE_HINT_INDEXBUFFER;
sbuf->key.size.width = sbuf->b.b.width0;
sbuf->key.size.height = 1;
sbuf->key.size.depth = 1;
sbuf->key.numFaces = 1;
sbuf->key.numMipLevels = 1;
sbuf->key.cachable = 1;
SVGA_DBG(DEBUG_DMA, "surface_create for buffer sz %d\n", sbuf->b.b.width0);

sbuf->handle = svga_screen_surface_create(ss, &sbuf->key);
if(!sbuf->handle)
return PIPE_ERROR_OUT_OF_MEMORY;
/* Always set the discard flag on the first time the buffer is written
* as svga_screen_surface_create might have passed a recycled host
* buffer.
*/
sbuf->dma.flags.discard = TRUE;

SVGA_DBG(DEBUG_DMA, " --> got sid %p sz %d (buffer)\n", sbuf->handle, sbuf->b.b.width0);
}
return PIPE_OK;
}


void
svga_buffer_destroy_host_surface(struct svga_screen *ss,
struct svga_buffer *sbuf)
{
if(sbuf->handle) {
SVGA_DBG(DEBUG_DMA, " ungrab sid %p sz %d\n", sbuf->handle, sbuf->b.b.width0);
svga_screen_surface_destroy(ss, &sbuf->key, &sbuf->handle);
}
}


/**
* Variant of SVGA3D_BufferDMA which leaves the copy box temporarily in blank.
*/
@@ -186,7 +179,7 @@ svga_buffer_upload_command(struct svga_context *svga,
SVGA3dCmdSurfaceDMASuffix *pSuffix;
unsigned region_flags;
unsigned surface_flags;
struct pipe_buffer *dummy;
struct pipe_resource *dummy;

if(transfer == SVGA3D_WRITE_HOST_VRAM) {
region_flags = PIPE_BUFFER_USAGE_GPU_READ;
@@ -224,11 +217,11 @@ svga_buffer_upload_command(struct svga_context *svga,

/* Increment reference count */
dummy = NULL;
pipe_buffer_reference(&dummy, &sbuf->base);
pipe_resource_reference(&dummy, &sbuf->b.b);

pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + numBoxes * sizeof *boxes);
pSuffix->suffixSize = sizeof *pSuffix;
pSuffix->maximumOffset = sbuf->base.size;
pSuffix->maximumOffset = sbuf->b.b.width0;
pSuffix->flags = sbuf->dma.flags;

SVGA_FIFOCommitAll(swc);
@@ -291,11 +284,12 @@ svga_buffer_upload_flush(struct svga_context *svga,
sbuf->dma.boxes = NULL;

/* Decrement reference count */
pipe_reference(&(sbuf->base.reference), NULL);
pipe_reference(&(sbuf->b.b.reference), NULL);
sbuf = NULL;
}



/**
* Note a dirty range.
*
@@ -305,7 +299,7 @@ svga_buffer_upload_flush(struct svga_context *svga,
*
* We try to lump as many contiguous DMA transfers together as possible.
*/
static void
void
svga_buffer_add_range(struct svga_buffer *sbuf,
unsigned start,
unsigned end)
@@ -330,7 +324,7 @@ svga_buffer_add_range(struct svga_buffer *sbuf,
* Note that it is not this function task to care about overlapping ranges,
* as the GMR was already given so it is too late to do anything. Situations
* where overlapping ranges may pose a problem should be detected via
* pipe_context::is_buffer_referenced and the context that refers to the
* pipe_context::is_resource_referenced and the context that refers to the
* buffer should be flushed.
*/

@@ -400,222 +394,6 @@ svga_buffer_add_range(struct svga_buffer *sbuf,
}


static void *
svga_buffer_map_range( struct pipe_screen *screen,
struct pipe_buffer *buf,
unsigned offset, unsigned length,
unsigned usage )
{
struct svga_screen *ss = svga_screen(screen);
struct svga_winsys_screen *sws = ss->sws;
struct svga_buffer *sbuf = svga_buffer( buf );
void *map;

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 {
map = NULL;
}

if(map) {
pipe_mutex_lock(ss->swc_mutex);

++sbuf->map.count;

if (usage & PIPE_BUFFER_USAGE_CPU_WRITE) {
assert(sbuf->map.count <= 1);
sbuf->map.writing = TRUE;
if (usage & PIPE_BUFFER_USAGE_FLUSH_EXPLICIT)
sbuf->map.flush_explicit = TRUE;
}
pipe_mutex_unlock(ss->swc_mutex);
}
return map;
}

static void
svga_buffer_flush_mapped_range( struct pipe_screen *screen,
struct pipe_buffer *buf,
unsigned offset, unsigned length)
{
struct svga_buffer *sbuf = svga_buffer( buf );
struct svga_screen *ss = svga_screen(screen);
pipe_mutex_lock(ss->swc_mutex);
assert(sbuf->map.writing);
if(sbuf->map.writing) {
assert(sbuf->map.flush_explicit);
svga_buffer_add_range(sbuf, offset, offset + length);
}
pipe_mutex_unlock(ss->swc_mutex);
}

static void
svga_buffer_unmap( struct pipe_screen *screen,
struct pipe_buffer *buf)
{
struct svga_screen *ss = svga_screen(screen);
struct svga_winsys_screen *sws = ss->sws;
struct svga_buffer *sbuf = svga_buffer( buf );
pipe_mutex_lock(ss->swc_mutex);
assert(sbuf->map.count);
if(sbuf->map.count)
--sbuf->map.count;

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");
svga_buffer_add_range(sbuf, 0, sbuf->base.size);
}
sbuf->map.writing = FALSE;
sbuf->map.flush_explicit = FALSE;
}

pipe_mutex_unlock(ss->swc_mutex);
}

static void
svga_buffer_destroy( struct pipe_buffer *buf )
{
struct svga_screen *ss = svga_screen(buf->screen);
struct svga_buffer *sbuf = svga_buffer( buf );

assert(!p_atomic_read(&buf->reference.count));
assert(!sbuf->dma.pending);

if(sbuf->handle)
svga_buffer_destroy_host_surface(ss, sbuf);
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)
align_free(sbuf->swbuf);
FREE(sbuf);
}

static struct pipe_buffer *
svga_buffer_create(struct pipe_screen *screen,
unsigned alignment,
unsigned usage,
unsigned size)
{
struct svga_screen *ss = svga_screen(screen);
struct svga_buffer *sbuf;
assert(size);
assert(alignment);

sbuf = CALLOC_STRUCT(svga_buffer);
if(!sbuf)
goto error1;
sbuf->magic = SVGA_BUFFER_MAGIC;
pipe_reference_init(&sbuf->base.reference, 1);
sbuf->base.screen = screen;
sbuf->base.alignment = alignment;
sbuf->base.usage = usage;
sbuf->base.size = size;

if(svga_buffer_needs_hw_storage(usage)) {
if(svga_buffer_create_host_surface(ss, sbuf) != PIPE_OK)
goto error2;
}
else {
if(alignment < sizeof(void*))
alignment = sizeof(void*);

usage |= PIPE_BUFFER_USAGE_CPU_READ_WRITE;
sbuf->swbuf = align_malloc(size, alignment);
if(!sbuf->swbuf)
goto error2;
}
return &sbuf->base;

error2:
FREE(sbuf);
error1:
return NULL;
}

static struct pipe_buffer *
svga_user_buffer_create(struct pipe_screen *screen,
void *ptr,
unsigned bytes)
{
struct svga_buffer *sbuf;
sbuf = CALLOC_STRUCT(svga_buffer);
if(!sbuf)
goto no_sbuf;
sbuf->magic = SVGA_BUFFER_MAGIC;
sbuf->swbuf = ptr;
sbuf->user = TRUE;
pipe_reference_init(&sbuf->base.reference, 1);
sbuf->base.screen = screen;
sbuf->base.alignment = 1;
sbuf->base.usage = 0;
sbuf->base.size = bytes;
return &sbuf->base;

no_sbuf:
return NULL;
}

void
svga_screen_init_buffer_functions(struct pipe_screen *screen)
{
screen->buffer_create = svga_buffer_create;
screen->user_buffer_create = svga_user_buffer_create;
screen->buffer_map_range = svga_buffer_map_range;
screen->buffer_flush_mapped_range = svga_buffer_flush_mapped_range;
screen->buffer_unmap = svga_buffer_unmap;
screen->buffer_destroy = svga_buffer_destroy;
}


/**
* Copy the contents of the malloc buffer to a hardware buffer.
@@ -645,7 +423,7 @@ svga_buffer_update_hw(struct svga_screen *ss, struct svga_buffer *sbuf)
return PIPE_ERROR;
}

memcpy(map, sbuf->swbuf, sbuf->base.size);
memcpy(map, sbuf->swbuf, sbuf->b.b.width0);
ss->sws->buffer_unmap(ss->sws, sbuf->hwbuf);

/* This user/malloc buffer is now indistinguishable from a gpu buffer */
@@ -710,8 +488,8 @@ svga_buffer_upload_piecewise(struct svga_screen *ss,
offset, offset + size);

map = sws->buffer_map(sws, hwbuf,
PIPE_BUFFER_USAGE_CPU_WRITE |
PIPE_BUFFER_USAGE_DISCARD);
PIPE_TRANSFER_WRITE |
PIPE_TRANSFER_DISCARD);
assert(map);
if (map) {
memcpy(map, sbuf->swbuf, size);
@@ -745,9 +523,14 @@ svga_buffer_upload_piecewise(struct svga_screen *ss,
}




/* Get (or create/upload) the winsys surface handle so that we can
* refer to this buffer in fifo commands.
*/
struct svga_winsys_surface *
svga_buffer_handle(struct svga_context *svga,
struct pipe_buffer *buf)
struct pipe_resource *buf)
{
struct pipe_screen *screen = svga->pipe.screen;
struct svga_screen *ss = svga_screen(screen);
@@ -828,45 +611,6 @@ svga_buffer_handle(struct svga_context *svga,
}


struct pipe_buffer *
svga_screen_buffer_wrap_surface(struct pipe_screen *screen,
enum SVGA3dSurfaceFormat format,
struct svga_winsys_surface *srf)
{
struct pipe_buffer *buf;
struct svga_buffer *sbuf;
struct svga_winsys_screen *sws = svga_winsys_screen(screen);

buf = svga_buffer_create(screen, 0, SVGA_BUFFER_USAGE_WRAPPED, 0);
if (!buf)
return NULL;

sbuf = svga_buffer(buf);

/*
* We are not the creator of this surface and therefore we must not
* cache it for reuse. Set the cacheable flag to zero in the key to
* prevent this.
*/
sbuf->key.format = format;
sbuf->key.cachable = 0;
sws->surface_reference(sws, &sbuf->handle, srf);

return buf;
}


struct svga_winsys_surface *
svga_screen_buffer_get_winsys_surface(struct pipe_buffer *buffer)
{
struct svga_winsys_screen *sws = svga_winsys_screen(buffer->screen);
struct svga_winsys_surface *vsurf = NULL;

assert(svga_buffer(buffer)->key.cachable == 0);
svga_buffer(buffer)->key.cachable = 0;
sws->surface_reference(sws, &vsurf, svga_buffer(buffer)->handle);
return vsurf;
}

void
svga_context_flush_buffers(struct svga_context *svga)
@@ -879,7 +623,7 @@ svga_context_flush_buffers(struct svga_context *svga)
while(curr != &svga->dirty_buffers) {
sbuf = LIST_ENTRY(struct svga_buffer, curr, head);

assert(p_atomic_read(&sbuf->base.reference.count) != 0);
assert(p_atomic_read(&sbuf->b.b.reference.count) != 0);
assert(sbuf->dma.pending);
svga_buffer_upload_flush(svga, sbuf);

+ 54
- 0
src/gallium/drivers/svga/svga_resource_buffer_upload.h View File

@@ -0,0 +1,54 @@
/**********************************************************
* Copyright 2008-2009 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************/

#ifndef SVGA_BUFFER_UPLOAD_H
#define SVGA_BUFFER_UPLOAD_H


void
svga_buffer_add_range(struct svga_buffer *sbuf,
unsigned start,
unsigned end);

enum pipe_error
svga_buffer_create_hw_storage(struct svga_screen *ss,
struct svga_buffer *sbuf);

void
svga_buffer_destroy_hw_storage(struct svga_screen *ss,
struct svga_buffer *sbuf);

enum pipe_error
svga_buffer_create_host_surface(struct svga_screen *ss,
struct svga_buffer *sbuf);

void
svga_buffer_destroy_host_surface(struct svga_screen *ss,
struct svga_buffer *sbuf);




#endif /* SVGA_BUFFER_H */

+ 635
- 0
src/gallium/drivers/svga/svga_resource_texture.c View File

@@ -0,0 +1,635 @@
/**********************************************************
* Copyright 2008-2009 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************/

#include "svga_cmd.h"

#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "os/os_thread.h"
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"

#include "svga_screen.h"
#include "svga_context.h"
#include "svga_resource_texture.h"
#include "svga_resource_buffer.h"
#include "svga_sampler_view.h"
#include "svga_winsys.h"
#include "svga_debug.h"

#include <util/u_string.h>


/* XXX: This isn't a real hardware flag, but just a hack for kernel to
* know about primary surfaces. Find a better way to accomplish this.
*/
#define SVGA3D_SURFACE_HINT_SCANOUT (1 << 9)


static unsigned int
svga_texture_is_referenced( struct pipe_context *pipe,
struct pipe_resource *texture,
unsigned face, unsigned level)
{
struct svga_texture *tex = svga_texture(texture);
struct svga_screen *ss = svga_screen(pipe->screen);

/**
* The screen does not cache texture writes.
*/

if (!tex->handle || ss->sws->surface_is_flushed(ss->sws, tex->handle))
return PIPE_UNREFERENCED;

/**
* sws->surface_is_flushed() does not distinguish between read references
* and write references. So assume a reference is both.
*/

return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
}



/*
* Helper function and arrays
*/

SVGA3dSurfaceFormat
svga_translate_format(enum pipe_format format)
{
switch(format) {
case PIPE_FORMAT_B8G8R8A8_UNORM:
return SVGA3D_A8R8G8B8;
case PIPE_FORMAT_B8G8R8X8_UNORM:
return SVGA3D_X8R8G8B8;

/* Required for GL2.1:
*/
case PIPE_FORMAT_B8G8R8A8_SRGB:
return SVGA3D_A8R8G8B8;

case PIPE_FORMAT_B5G6R5_UNORM:
return SVGA3D_R5G6B5;
case PIPE_FORMAT_B5G5R5A1_UNORM:
return SVGA3D_A1R5G5B5;
case PIPE_FORMAT_B4G4R4A4_UNORM:
return SVGA3D_A4R4G4B4;

/* XXX: Doesn't seem to work properly.
case PIPE_FORMAT_Z32_UNORM:
return SVGA3D_Z_D32;
*/
case PIPE_FORMAT_Z16_UNORM:
return SVGA3D_Z_D16;
case PIPE_FORMAT_S8Z24_UNORM:
return SVGA3D_Z_D24S8;
case PIPE_FORMAT_X8Z24_UNORM:
return SVGA3D_Z_D24X8;

case PIPE_FORMAT_A8_UNORM:
return SVGA3D_ALPHA8;
case PIPE_FORMAT_L8_UNORM:
return SVGA3D_LUMINANCE8;

case PIPE_FORMAT_DXT1_RGB:
case PIPE_FORMAT_DXT1_RGBA:
return SVGA3D_DXT1;
case PIPE_FORMAT_DXT3_RGBA:
return SVGA3D_DXT3;
case PIPE_FORMAT_DXT5_RGBA:
return SVGA3D_DXT5;

default:
return SVGA3D_FORMAT_INVALID;
}
}


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

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

default:
return SVGA3D_FORMAT_INVALID;
}
}


static INLINE void
svga_transfer_dma_band(struct svga_transfer *st,
SVGA3dTransferType transfer,
unsigned y, unsigned h, unsigned srcy)
{
struct svga_texture *texture = svga_texture(st->base.resource);
struct svga_screen *screen = svga_screen(texture->b.b.screen);
SVGA3dCopyBox box;
enum pipe_error ret;
SVGA_DBG(DEBUG_DMA, "dma %s sid %p, face %u, (%u, %u, %u) - (%u, %u, %u), %ubpp\n",
transfer == SVGA3D_WRITE_HOST_VRAM ? "to" : "from",
texture->handle,
st->base.sr.face,
st->base.box.x,
y,
st->base.box.z,
st->base.box.x + st->base.box.width,
y + h,
st->base.box.z + 1,
util_format_get_blocksize(texture->b.b.format) * 8 /
(util_format_get_blockwidth(texture->b.b.format)*util_format_get_blockheight(texture->b.b.format)));
box.x = st->base.box.x;
box.y = y;
box.z = st->base.box.z;
box.w = st->base.box.width;
box.h = h;
box.d = 1;
box.srcx = 0;
box.srcy = srcy;
box.srcz = 0;

pipe_mutex_lock(screen->swc_mutex);
ret = SVGA3D_SurfaceDMA(screen->swc, st, transfer, &box, 1);
if(ret != PIPE_OK) {
screen->swc->flush(screen->swc, NULL);
ret = SVGA3D_SurfaceDMA(screen->swc, st, transfer, &box, 1);
assert(ret == PIPE_OK);
}
pipe_mutex_unlock(screen->swc_mutex);
}


static INLINE void
svga_transfer_dma(struct svga_transfer *st,
SVGA3dTransferType transfer)
{
struct svga_texture *texture = svga_texture(st->base.resource);
struct svga_screen *screen = svga_screen(texture->b.b.screen);
struct svga_winsys_screen *sws = screen->sws;
struct pipe_fence_handle *fence = NULL;
if (transfer == SVGA3D_READ_HOST_VRAM) {
SVGA_DBG(DEBUG_PERF, "%s: readback transfer\n", __FUNCTION__);
}


if(!st->swbuf) {
/* Do the DMA transfer in a single go */
svga_transfer_dma_band(st, transfer, st->base.box.y, st->base.box.height, 0);

if(transfer == SVGA3D_READ_HOST_VRAM) {
svga_screen_flush(screen, &fence);
sws->fence_finish(sws, fence, 0);
sws->fence_reference(sws, &fence, NULL);
}
}
else {
unsigned y, h, srcy;
unsigned blockheight = util_format_get_blockheight(st->base.resource->format);
h = st->hw_nblocksy * blockheight;
srcy = 0;
for(y = 0; y < st->base.box.height; y += h) {
unsigned offset, length;
void *hw, *sw;

if (y + h > st->base.box.height)
h = st->base.box.height - y;

/* Transfer band must be aligned to pixel block boundaries */
assert(y % blockheight == 0);
assert(h % blockheight == 0);
offset = y * st->base.stride / blockheight;
length = h * st->base.stride / blockheight;

sw = (uint8_t *)st->swbuf + offset;
if(transfer == SVGA3D_WRITE_HOST_VRAM) {
/* Wait for the previous DMAs to complete */
/* TODO: keep one DMA (at half the size) in the background */
if(y) {
svga_screen_flush(screen, &fence);
sws->fence_finish(sws, fence, 0);
sws->fence_reference(sws, &fence, NULL);
}

hw = sws->buffer_map(sws, st->hwbuf, PIPE_BUFFER_USAGE_CPU_WRITE);
assert(hw);
if(hw) {
memcpy(hw, sw, length);
sws->buffer_unmap(sws, st->hwbuf);
}
}
svga_transfer_dma_band(st, transfer, y, h, srcy);
if(transfer == SVGA3D_READ_HOST_VRAM) {
svga_screen_flush(screen, &fence);
sws->fence_finish(sws, fence, 0);

hw = sws->buffer_map(sws, st->hwbuf, PIPE_BUFFER_USAGE_CPU_READ);
assert(hw);
if(hw) {
memcpy(sw, hw, length);
sws->buffer_unmap(sws, st->hwbuf);
}
}
}
}
}





static boolean
svga_texture_get_handle(struct pipe_screen *screen,
struct pipe_resource *texture,
struct winsys_handle *whandle)
{
struct svga_winsys_screen *sws = svga_winsys_screen(texture->screen);
unsigned stride;

assert(svga_texture(texture)->key.cachable == 0);
svga_texture(texture)->key.cachable = 0;
stride = util_format_get_nblocksx(texture->format, texture->width0) *
util_format_get_blocksize(texture->format);
return sws->surface_get_handle(sws, svga_texture(texture)->handle, stride, whandle);
}


static void
svga_texture_destroy(struct pipe_screen *screen,
struct pipe_resource *pt)
{
struct svga_screen *ss = svga_screen(screen);
struct svga_texture *tex = (struct svga_texture *)pt;

ss->texture_timestamp++;

svga_sampler_view_reference(&tex->cached_view, NULL);

/*
DBG("%s deleting %p\n", __FUNCTION__, (void *) tex);
*/
SVGA_DBG(DEBUG_DMA, "unref sid %p (texture)\n", tex->handle);
svga_screen_surface_destroy(ss, &tex->key, &tex->handle);

FREE(tex);
}







/* XXX: Still implementing this as if it was a screen function, but
* can now modify it to queue transfers on the context.
*/
static struct pipe_transfer *
svga_texture_get_transfer(struct pipe_context *pipe,
struct pipe_resource *texture,
struct pipe_subresource sr,
enum pipe_transfer_usage usage,
const struct pipe_box *box)
{
struct svga_screen *ss = svga_screen(pipe->screen);
struct svga_winsys_screen *sws = ss->sws;
struct svga_transfer *st;
unsigned nblocksx = util_format_get_nblocksx(texture->format, box->width);
unsigned nblocksy = util_format_get_nblocksy(texture->format, box->height);

/* We can't map texture storage directly */
if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
return NULL;

st = CALLOC_STRUCT(svga_transfer);
if (!st)
return NULL;
pipe_resource_reference(&st->base.resource, texture);
st->base.sr = sr;
st->base.usage = usage;
st->base.box = *box;
st->base.stride = nblocksx*util_format_get_blocksize(texture->format);
st->base.slice_stride = 0;

st->hw_nblocksy = nblocksy;
st->hwbuf = svga_winsys_buffer_create(ss,
1,
0,
st->hw_nblocksy*st->base.stride);
while(!st->hwbuf && (st->hw_nblocksy /= 2)) {
st->hwbuf = svga_winsys_buffer_create(ss,
1,
0,
st->hw_nblocksy*st->base.stride);
}

if(!st->hwbuf)
goto no_hwbuf;

if(st->hw_nblocksy < nblocksy) {
/* We couldn't allocate a hardware buffer big enough for the transfer,
* so allocate regular malloc memory instead */
debug_printf("%s: failed to allocate %u KB of DMA, splitting into %u x %u KB DMA transfers\n",
__FUNCTION__,
(nblocksy*st->base.stride + 1023)/1024,
(nblocksy + st->hw_nblocksy - 1)/st->hw_nblocksy,
(st->hw_nblocksy*st->base.stride + 1023)/1024);
st->swbuf = MALLOC(nblocksy*st->base.stride);
if(!st->swbuf)
goto no_swbuf;
}
if (usage & PIPE_TRANSFER_READ)
svga_transfer_dma(st, SVGA3D_READ_HOST_VRAM);

return &st->base;

no_swbuf:
sws->buffer_destroy(sws, st->hwbuf);
no_hwbuf:
FREE(st);
return NULL;
}


/* XXX: Still implementing this as if it was a screen function, but
* can now modify it to queue transfers on the context.
*/
static void *
svga_texture_transfer_map( struct pipe_context *pipe,
struct pipe_transfer *transfer )
{
struct svga_screen *ss = svga_screen(pipe->screen);
struct svga_winsys_screen *sws = ss->sws;
struct svga_transfer *st = svga_transfer(transfer);

if(st->swbuf)
return st->swbuf;
else
/* The wait for read transfers already happened when svga_transfer_dma
* was called. */
return sws->buffer_map(sws, st->hwbuf, transfer->usage);
}


/* XXX: Still implementing this as if it was a screen function, but
* can now modify it to queue transfers on the context.
*/
static void
svga_texture_transfer_unmap(struct pipe_context *pipe,
struct pipe_transfer *transfer)
{
struct svga_screen *ss = svga_screen(pipe->screen);
struct svga_winsys_screen *sws = ss->sws;
struct svga_transfer *st = svga_transfer(transfer);
if(!st->swbuf)
sws->buffer_unmap(sws, st->hwbuf);
}


static void
svga_texture_transfer_destroy(struct pipe_context *pipe,
struct pipe_transfer *transfer)
{
struct svga_texture *tex = svga_texture(transfer->resource);
struct svga_screen *ss = svga_screen(pipe->screen);
struct svga_winsys_screen *sws = ss->sws;
struct svga_transfer *st = svga_transfer(transfer);

if (st->base.usage & PIPE_TRANSFER_WRITE) {
svga_transfer_dma(st, SVGA3D_WRITE_HOST_VRAM);
ss->texture_timestamp++;
tex->view_age[transfer->sr.level] = ++(tex->age);
tex->defined[transfer->sr.face][transfer->sr.level] = TRUE;
}

pipe_resource_reference(&st->base.resource, NULL);
FREE(st->swbuf);
sws->buffer_destroy(sws, st->hwbuf);
FREE(st);
}





struct u_resource_vtbl svga_texture_vtbl =
{
svga_texture_get_handle, /* get_handle */
svga_texture_destroy, /* resource_destroy */
svga_texture_is_referenced, /* is_resource_referenced */
svga_texture_get_transfer, /* get_transfer */
svga_texture_transfer_destroy, /* transfer_destroy */
svga_texture_transfer_map, /* transfer_map */
u_default_transfer_flush_region, /* transfer_flush_region */
svga_texture_transfer_unmap, /* transfer_unmap */
u_default_transfer_inline_write /* transfer_inline_write */
};




struct pipe_resource *
svga_texture_create(struct pipe_screen *screen,
const struct pipe_resource *template)
{
struct svga_screen *svgascreen = svga_screen(screen);
struct svga_texture *tex = CALLOC_STRUCT(svga_texture);
if (!tex)
goto error1;

tex->b.b = *template;
tex->b.vtbl = &svga_texture_vtbl;
pipe_reference_init(&tex->b.b.reference, 1);
tex->b.b.screen = screen;

assert(template->last_level < SVGA_MAX_TEXTURE_LEVELS);
if(template->last_level >= SVGA_MAX_TEXTURE_LEVELS)
goto error2;
tex->key.flags = 0;
tex->key.size.width = template->width0;
tex->key.size.height = template->height0;
tex->key.size.depth = template->depth0;
if(template->target == PIPE_TEXTURE_CUBE) {
tex->key.flags |= SVGA3D_SURFACE_CUBEMAP;
tex->key.numFaces = 6;
}
else {
tex->key.numFaces = 1;
}

tex->key.cachable = 1;

if(template->tex_usage & PIPE_TEXTURE_USAGE_SAMPLER)
tex->key.flags |= SVGA3D_SURFACE_HINT_TEXTURE;

if(template->tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
tex->key.cachable = 0;
}

if(template->tex_usage & PIPE_TEXTURE_USAGE_SHARED) {
tex->key.cachable = 0;
}

if(template->tex_usage & PIPE_TEXTURE_USAGE_SCANOUT) {
tex->key.flags |= SVGA3D_SURFACE_HINT_SCANOUT;
tex->key.cachable = 0;
}
/*
* XXX: Never pass the SVGA3D_SURFACE_HINT_RENDERTARGET hint. Mesa cannot
* know beforehand whether a texture will be used as a rendertarget or not
* and it always requests PIPE_TEXTURE_USAGE_RENDER_TARGET, therefore
* passing the SVGA3D_SURFACE_HINT_RENDERTARGET here defeats its purpose.
*/
#if 0
if((template->tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) &&
!util_format_is_compressed(template->format))
tex->key.flags |= SVGA3D_SURFACE_HINT_RENDERTARGET;
#endif
if(template->tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL)
tex->key.flags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL;
tex->key.numMipLevels = template->last_level + 1;
tex->key.format = svga_translate_format(template->format);
if(tex->key.format == SVGA3D_FORMAT_INVALID)
goto error2;

SVGA_DBG(DEBUG_DMA, "surface_create for texture\n", tex->handle);
tex->handle = svga_screen_surface_create(svgascreen, &tex->key);
if (tex->handle)
SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture)\n", tex->handle);

return &tex->b.b;

error2:
FREE(tex);
error1:
return NULL;
}




struct pipe_resource *
svga_texture_from_handle(struct pipe_screen *screen,
const struct pipe_resource *template,
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 */
if (template->target != PIPE_TEXTURE_2D ||
template->last_level != 0 ||
template->depth0 != 1) {
return NULL;
}

srf = sws->surface_from_handle(sws, whandle, &format);

if (!srf)
return NULL;

if (svga_translate_format(template->format) != format) {
unsigned f1 = svga_translate_format(template->format);
unsigned f2 = format;

/* It's okay for XRGB and ARGB or depth with/out stencil to get mixed up */
if ( !( (f1 == SVGA3D_X8R8G8B8 && f2 == SVGA3D_A8R8G8B8) ||
(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->b.b = *template;
tex->b.vtbl = &svga_texture_vtbl;
pipe_reference_init(&tex->b.b.reference, 1);
tex->b.b.screen = screen;

if (format == SVGA3D_X8R8G8B8)
tex->b.b.format = PIPE_FORMAT_B8G8R8X8_UNORM;
else if (format == SVGA3D_A8R8G8B8)
tex->b.b.format = PIPE_FORMAT_B8G8R8A8_UNORM;
else {
/* ?? */
}

SVGA_DBG(DEBUG_DMA, "wrap surface sid %p\n", srf);

tex->key.cachable = 0;
tex->handle = srf;

return &tex->b.b;
}


src/gallium/drivers/svga/svga_screen_texture.h → src/gallium/drivers/svga/svga_resource_texture.h View File

@@ -29,8 +29,8 @@

#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "piperesource/rm_public.h"
#include "util/u_inlines.h"
#include "util/u_transfer.h"
#include "svga_screen_cache.h"

struct pipe_context;
@@ -43,41 +43,12 @@ enum SVGA3dSurfaceFormat;
#define SVGA_MAX_TEXTURE_LEVELS 16


/**
* A sampler's view into a texture
*
* We currently cache one sampler view on
* the texture and in there by holding a reference
* from the texture to the sampler view.
*
* Because of this we can not hold a refernce to the
* texture from the sampler view. So the user
* of the sampler views must make sure that the
* texture has a reference take for as long as
* the sampler view is refrenced.
*
* Just unreferencing the sampler_view before the
* texture is enough.
*/
struct svga_sampler_view
{
struct pipe_reference reference;

struct pipe_texture *texture;

int min_lod;
int max_lod;

unsigned age;

struct svga_host_surface_cache_key key;
struct svga_winsys_surface *handle;
};
extern struct u_resource_vtbl svga_texture_vtbl;


struct svga_texture
{
struct pipe_texture base;
struct u_resource b;

boolean defined[6][SVGA_MAX_TEXTURE_LEVELS];
@@ -107,21 +78,9 @@ struct svga_texture
};


struct svga_surface
{
struct pipe_surface base;

struct svga_host_surface_cache_key key;
struct svga_winsys_surface *handle;

unsigned real_face;
unsigned real_level;
unsigned real_zslice;

boolean dirty;
};


/* Note this is only used for texture (not buffer) transfers:
*/
struct svga_transfer
{
struct pipe_transfer base;
@@ -137,18 +96,13 @@ struct svga_transfer
};


static INLINE struct svga_texture *
svga_texture(struct pipe_texture *texture)
static INLINE struct svga_texture *svga_texture( struct pipe_resource *resource )
{
return (struct svga_texture *)texture;
struct svga_texture *tex = (struct svga_texture *)resource;
assert(tex == NULL || tex->b.vtbl == &svga_texture_vtbl);
return tex;
}

static INLINE struct svga_surface *
svga_surface(struct pipe_surface *surface)
{
assert(surface);
return (struct svga_surface *)surface;
}

static INLINE struct svga_transfer *
svga_transfer(struct pipe_transfer *transfer)
@@ -157,38 +111,18 @@ svga_transfer(struct pipe_transfer *transfer)
return (struct svga_transfer *)transfer;
}

extern struct svga_sampler_view *
svga_get_tex_sampler_view(struct pipe_context *pipe,
struct pipe_texture *pt,
unsigned min_lod, unsigned max_lod);

void
svga_validate_sampler_view(struct svga_context *svga, struct svga_sampler_view *v);

void
svga_destroy_sampler_view_priv(struct svga_sampler_view *v);

static INLINE void
svga_sampler_view_reference(struct svga_sampler_view **ptr, struct svga_sampler_view *v)
{
struct svga_sampler_view *old = *ptr;

if (pipe_reference(&(*ptr)->reference, &v->reference))
svga_destroy_sampler_view_priv(old);
*ptr = v;
}

extern void
svga_propagate_surface(struct pipe_context *pipe, struct pipe_surface *surf);
struct pipe_resource *
svga_texture_create(struct pipe_screen *screen,
const struct pipe_resource *template);

extern boolean
svga_surface_needs_propagation(struct pipe_surface *surf);
struct pipe_resource *
svga_texture_from_handle(struct pipe_screen * screen,
const struct pipe_resource *template,
struct winsys_handle *whandle);

extern void
svga_screen_init_texture_functions(struct pipe_screen *screen);

void
svga_init_texture_functions(struct pipe_context *pipe);

enum SVGA3dSurfaceFormat
svga_translate_format(enum pipe_format format);

+ 198
- 0
src/gallium/drivers/svga/svga_sampler_view.c View File

@@ -0,0 +1,198 @@
/**********************************************************
* Copyright 2008-2009 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************/

#include "svga_cmd.h"

#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "os/os_thread.h"
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"

#include "svga_screen.h"
#include "svga_context.h"
#include "svga_resource_texture.h"
#include "svga_sampler_view.h"
#include "svga_winsys.h"
#include "svga_debug.h"

#include <util/u_string.h>


struct svga_sampler_view *
svga_get_tex_sampler_view(struct pipe_context *pipe,
struct pipe_resource *pt,
unsigned min_lod, unsigned max_lod)
{
struct svga_screen *ss = svga_screen(pt->screen);
struct svga_texture *tex = svga_texture(pt);
struct svga_sampler_view *sv = NULL;
SVGA3dSurfaceFormat format = svga_translate_format(pt->format);
boolean view = TRUE;

assert(pt);
assert(min_lod >= 0);
assert(min_lod <= max_lod);
assert(max_lod <= pt->last_level);


/* Is a view needed */
{
/*
* Can't control max lod. For first level views and when we only
* look at one level we disable mip filtering to achive the same
* results as a view.
*/
if (min_lod == 0 && max_lod >= pt->last_level)
view = FALSE;

if (util_format_is_compressed(pt->format) && view) {
format = svga_translate_format_render(pt->format);
}

if (ss->debug.no_sampler_view)
view = FALSE;

if (ss->debug.force_sampler_view)
view = TRUE;
}

/* First try the cache */
if (view) {
pipe_mutex_lock(ss->tex_mutex);
if (tex->cached_view &&
tex->cached_view->min_lod == min_lod &&
tex->cached_view->max_lod == max_lod) {
svga_sampler_view_reference(&sv, tex->cached_view);
pipe_mutex_unlock(ss->tex_mutex);
SVGA_DBG(DEBUG_VIEWS, "svga: Sampler view: reuse %p, %u %u, last %u\n",
pt, min_lod, max_lod, pt->last_level);
svga_validate_sampler_view(svga_context(pipe), sv);
return sv;
}
pipe_mutex_unlock(ss->tex_mutex);
}

sv = CALLOC_STRUCT(svga_sampler_view);
pipe_reference_init(&sv->reference, 1);
pipe_resource_reference(&sv->texture, pt);
sv->min_lod = min_lod;
sv->max_lod = max_lod;

/* No view needed just use the whole texture */
if (!view) {
SVGA_DBG(DEBUG_VIEWS,
"svga: Sampler view: no %p, mips %u..%u, nr %u, size (%ux%ux%u), last %u\n",
pt, min_lod, max_lod,
max_lod - min_lod + 1,
pt->width0,
pt->height0,
pt->depth0,
pt->last_level);
sv->key.cachable = 0;
sv->handle = tex->handle;
return sv;
}

SVGA_DBG(DEBUG_VIEWS,
"svga: Sampler view: yes %p, mips %u..%u, nr %u, size (%ux%ux%u), last %u\n",
pt, min_lod, max_lod,
max_lod - min_lod + 1,
pt->width0,
pt->height0,
pt->depth0,
pt->last_level);

sv->age = tex->age;
sv->handle = svga_texture_view_surface(pipe, tex, format,
min_lod,
max_lod - min_lod + 1,
-1, -1,
&sv->key);

if (!sv->handle) {
assert(0);
sv->key.cachable = 0;
sv->handle = tex->handle;
return sv;
}

pipe_mutex_lock(ss->tex_mutex);
svga_sampler_view_reference(&tex->cached_view, sv);
pipe_mutex_unlock(ss->tex_mutex);

return sv;
}

void
svga_validate_sampler_view(struct svga_context *svga, struct svga_sampler_view *v)
{
struct svga_texture *tex = svga_texture(v->texture);
unsigned numFaces;
unsigned age = 0;
int i, k;

assert(svga);

if (v->handle == tex->handle)
return;

age = tex->age;

if(tex->b.b.target == PIPE_TEXTURE_CUBE)
numFaces = 6;
else
numFaces = 1;

for (i = v->min_lod; i <= v->max_lod; i++) {
for (k = 0; k < numFaces; k++) {
if (v->age < tex->view_age[i])
svga_texture_copy_handle(svga, NULL,
tex->handle, 0, 0, 0, i, k,
v->handle, 0, 0, 0, i - v->min_lod, k,
u_minify(tex->b.b.width0, i),
u_minify(tex->b.b.height0, i),
u_minify(tex->b.b.depth0, i));
}
}

v->age = age;
}

void
svga_destroy_sampler_view_priv(struct svga_sampler_view *v)
{
struct svga_texture *tex = svga_texture(v->texture);

if(v->handle != tex->handle) {
struct svga_screen *ss = svga_screen(v->texture->screen);
SVGA_DBG(DEBUG_DMA, "unref sid %p (sampler view)\n", v->handle);
svga_screen_surface_destroy(ss, &v->key, &v->handle);
}
pipe_resource_reference(&v->texture, NULL);
FREE(v);
}

+ 97
- 0
src/gallium/drivers/svga/svga_sampler_view.h View File

@@ -0,0 +1,97 @@
/**********************************************************
* Copyright 2008-2009 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************/

#ifndef SVGA_SAMPLER_VIEW_H
#define SVGA_SAMPLER_VIEW_H


#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "util/u_inlines.h"
#include "svga_screen_cache.h"

struct pipe_context;
struct pipe_screen;
struct svga_context;
struct svga_winsys_surface;
enum SVGA3dSurfaceFormat;


/**
* A sampler's view into a texture
*
* We currently cache one sampler view on
* the texture and in there by holding a reference
* from the texture to the sampler view.
*
* Because of this we can not hold a refernce to the
* texture from the sampler view. So the user
* of the sampler views must make sure that the
* texture has a reference take for as long as
* the sampler view is refrenced.
*
* Just unreferencing the sampler_view before the
* texture is enough.
*/
struct svga_sampler_view
{
struct pipe_reference reference;

struct pipe_resource *texture;

int min_lod;
int max_lod;

unsigned age;

struct svga_host_surface_cache_key key;
struct svga_winsys_surface *handle;
};



extern struct svga_sampler_view *
svga_get_tex_sampler_view(struct pipe_context *pipe,
struct pipe_resource *pt,
unsigned min_lod, unsigned max_lod);

void
svga_validate_sampler_view(struct svga_context *svga, struct svga_sampler_view *v);

void
svga_destroy_sampler_view_priv(struct svga_sampler_view *v);

static INLINE void
svga_sampler_view_reference(struct svga_sampler_view **ptr, struct svga_sampler_view *v)
{
struct svga_sampler_view *old = *ptr;

if (pipe_reference(&(*ptr)->reference, &v->reference))
svga_destroy_sampler_view_priv(old);
*ptr = v;
}


#endif

+ 4
- 4
src/gallium/drivers/svga/svga_screen.c View File

@@ -31,8 +31,9 @@
#include "svga_winsys.h"
#include "svga_context.h"
#include "svga_screen.h"
#include "svga_screen_texture.h"
#include "svga_screen_buffer.h"
#include "svga_resource_texture.h"
#include "svga_resource_buffer.h"
#include "svga_resource.h"
#include "svga_debug.h"

#include "svga3d_shaderdefs.h"
@@ -397,8 +398,7 @@ svga_screen_create(struct svga_winsys_screen *sws)
screen->fence_finish = svga_fence_finish;
svgascreen->sws = sws;

svga_screen_init_texture_functions(screen);
svga_screen_init_buffer_functions(screen);
svga_init_screen_resource_functions(svgascreen);

svgascreen->use_ps30 =
sws->get_cap(sws, SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION, &result) &&

+ 0
- 1099
src/gallium/drivers/svga/svga_screen_texture.c
File diff suppressed because it is too large
View File


+ 7
- 5
src/gallium/drivers/svga/svga_state_constants.c View File

@@ -82,6 +82,7 @@ static int emit_consts( struct svga_context *svga,
int offset,
int unit )
{
struct pipe_transfer *transfer = NULL;
struct pipe_screen *screen = svga->pipe.screen;
unsigned count;
const float (*data)[4] = NULL;
@@ -91,11 +92,12 @@ static int emit_consts( struct svga_context *svga,
if (svga->curr.cb[unit] == NULL)
goto done;

count = svga->curr.cb[unit]->size / (4 * sizeof(float));
count = svga->curr.cb[unit]->width0 / (4 * sizeof(float));

data = (const float (*)[4])pipe_buffer_map(screen,
data = (const float (*)[4])pipe_buffer_map(&svga->pipe,
svga->curr.cb[unit],
PIPE_BUFFER_USAGE_CPU_READ);
PIPE_BUFFER_USAGE_CPU_READ,
&transfer);
if (data == NULL) {
ret = PIPE_ERROR_OUT_OF_MEMORY;
goto done;
@@ -109,7 +111,7 @@ static int emit_consts( struct svga_context *svga,

done:
if (data)
pipe_buffer_unmap(screen, svga->curr.cb[unit]);
pipe_buffer_unmap(&svga->pipe, svga->curr.cb[unit], transfer);

return ret;
}
@@ -137,7 +139,7 @@ static int emit_fs_consts( struct svga_context *svga,

for (i = 0; i < key->num_textures; i++) {
if (key->tex[i].unnormalized) {
struct pipe_texture *tex = svga->curr.sampler_views[i]->texture;
struct pipe_resource *tex = svga->curr.sampler_views[i]->texture;
float data[4];

data[0] = 1.0 / (float)tex->width0;

+ 4
- 4
src/gallium/drivers/svga/svga_state_tss.c View File

@@ -27,7 +27,7 @@
#include "pipe/p_defines.h"
#include "util/u_math.h"

#include "svga_screen_texture.h"
#include "svga_sampler_view.h"
#include "svga_winsys.h"
#include "svga_context.h"
#include "svga_state.h"
@@ -45,7 +45,7 @@ void svga_cleanup_tss_binding(struct svga_context *svga)

svga_sampler_view_reference(&view->v, NULL);
pipe_sampler_view_reference( &svga->curr.sampler_views[i], NULL );
pipe_texture_reference( &view->texture, NULL );
pipe_resource_reference( &view->texture, NULL );

view->dirty = 1;
}
@@ -77,7 +77,7 @@ update_tss_binding(struct svga_context *svga,
for (i = 0; i < count; i++) {
const struct svga_sampler_state *s = svga->curr.sampler[i];
struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
struct pipe_texture *texture = NULL;
struct pipe_resource *texture = NULL;

/* get min max lod */
if (svga->curr.sampler_views[i]) {
@@ -94,7 +94,7 @@ update_tss_binding(struct svga_context *svga,
view->max_lod != max_lod) {

svga_sampler_view_reference(&view->v, NULL);
pipe_texture_reference( &view->texture, texture );
pipe_resource_reference( &view->texture, texture );

view->dirty = TRUE;
view->min_lod = min_lod;

+ 5
- 5
src/gallium/drivers/svga/svga_state_vdecl.c View File

@@ -33,7 +33,7 @@
#include "svga_draw.h"
#include "svga_tgsi.h"
#include "svga_screen.h"
#include "svga_screen_buffer.h"
#include "svga_resource_buffer.h"

#include "svga_hw_reg.h"

@@ -59,8 +59,8 @@ upload_user_buffers( struct svga_context *svga )
if (!buffer->uploaded.buffer) {
ret = u_upload_buffer( svga->upload_vb,
0,
buffer->base.size,
&buffer->base,
buffer->b.b.width0,
&buffer->b.b,
&buffer->uploaded.offset,
&buffer->uploaded.buffer );
if (ret)
@@ -73,10 +73,10 @@ upload_user_buffers( struct svga_context *svga )
buffer,
buffer->uploaded.buffer,
buffer->uploaded.offset,
buffer->base.size);
buffer->b.b.width0);
}

pipe_buffer_reference( &svga->curr.vb[i].buffer, buffer->uploaded.buffer );
pipe_resource_reference( &svga->curr.vb[i].buffer, buffer->uploaded.buffer );
svga->curr.vb[i].buffer_offset = buffer->uploaded.offset;
}
}

+ 10
- 4
src/gallium/drivers/svga/svga_state_vs.c View File

@@ -190,9 +190,11 @@ static int update_zero_stride( struct svga_context *svga,
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) {
unsigned const_idx =
svga->curr.num_zero_stride_vertex_elements;
struct pipe_transfer *transfer;
struct translate *translate;
struct translate_key key;
void *mapped_buffer;
@@ -218,19 +220,23 @@ static int update_zero_stride( struct svga_context *svga,

assert(vel->src_offset == 0);
mapped_buffer = pipe_buffer_map_range(svga->pipe.screen,
mapped_buffer = pipe_buffer_map_range(&svga->pipe,
vbuffer->buffer,
vel->src_offset,
util_format_get_blocksize(vel->src_format),
PIPE_BUFFER_USAGE_CPU_READ);
PIPE_BUFFER_USAGE_CPU_READ,
&transfer);

translate->set_buffer(translate, vel->vertex_buffer_index,
mapped_buffer,
vbuffer->stride);
translate->run(translate, 0, 1, 0,
svga->curr.zero_stride_constants);

pipe_buffer_unmap(svga->pipe.screen,
vbuffer->buffer);
pipe_buffer_unmap(&svga->pipe,
vbuffer->buffer,
transfer);

translate->release(translate);
}
}

+ 384
- 0
src/gallium/drivers/svga/svga_surface.c View File

@@ -0,0 +1,384 @@
/**********************************************************
* Copyright 2008-2009 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************/

#include "svga_cmd.h"

#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "os/os_thread.h"
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"

#include "svga_screen.h"
#include "svga_context.h"
#include "svga_resource_texture.h"
#include "svga_surface.h"
#include "svga_winsys.h"
#include "svga_debug.h"

#include <util/u_string.h>


static void
svga_texture_copy_handle(struct svga_context *svga,
struct svga_screen *ss,
struct svga_winsys_surface *src_handle,
unsigned src_x, unsigned src_y, unsigned src_z,
unsigned src_level, unsigned src_face,
struct svga_winsys_surface *dst_handle,
unsigned dst_x, unsigned dst_y, unsigned dst_z,
unsigned dst_level, unsigned dst_face,
unsigned width, unsigned height, unsigned depth)
{
struct svga_surface dst, src;
enum pipe_error ret;
SVGA3dCopyBox box, *boxes;

assert(svga || ss);

src.handle = src_handle;
src.real_level = src_level;
src.real_face = src_face;
src.real_zslice = 0;

dst.handle = dst_handle;
dst.real_level = dst_level;
dst.real_face = dst_face;
dst.real_zslice = 0;

box.x = dst_x;
box.y = dst_y;
box.z = dst_z;
box.w = width;
box.h = height;
box.d = depth;
box.srcx = src_x;
box.srcy = src_y;
box.srcz = src_z;

/*
SVGA_DBG(DEBUG_VIEWS, "mipcopy src: %p %u (%ux%ux%u), dst: %p %u (%ux%ux%u)\n",
src_handle, src_level, src_x, src_y, src_z,
dst_handle, dst_level, dst_x, dst_y, dst_z);
*/

if (svga) {
ret = SVGA3D_BeginSurfaceCopy(svga->swc,
&src.base,
&dst.base,
&boxes, 1);
if(ret != PIPE_OK) {
svga_context_flush(svga, NULL);
ret = SVGA3D_BeginSurfaceCopy(svga->swc,
&src.base,
&dst.base,
&boxes, 1);
assert(ret == PIPE_OK);
}
*boxes = box;
SVGA_FIFOCommitAll(svga->swc);
} else {
pipe_mutex_lock(ss->swc_mutex);
ret = SVGA3D_BeginSurfaceCopy(ss->swc,
&src.base,
&dst.base,
&boxes, 1);
if(ret != PIPE_OK) {
ss->swc->flush(ss->swc, NULL);
ret = SVGA3D_BeginSurfaceCopy(ss->swc,
&src.base,
&dst.base,
&boxes, 1);
assert(ret == PIPE_OK);
}
*boxes = box;
SVGA_FIFOCommitAll(ss->swc);
pipe_mutex_unlock(ss->swc_mutex);
}
}


struct svga_winsys_surface *
svga_texture_view_surface(struct pipe_context *pipe,
struct svga_texture *tex,
SVGA3dSurfaceFormat format,
unsigned start_mip,
unsigned num_mip,
int face_pick,
int zslice_pick,
struct svga_host_surface_cache_key *key) /* OUT */
{
struct svga_screen *ss = svga_screen(pipe->screen);
struct svga_winsys_surface *handle;
uint32_t i, j;
unsigned z_offset = 0;

SVGA_DBG(DEBUG_PERF,
"svga: Create surface view: face %d zslice %d mips %d..%d\n",
face_pick, zslice_pick, start_mip, start_mip+num_mip-1);

key->flags = 0;
key->format = format;
key->numMipLevels = num_mip;
key->size.width = u_minify(tex->b.b.width0, start_mip);
key->size.height = u_minify(tex->b.b.height0, start_mip);
key->size.depth = zslice_pick < 0 ? u_minify(tex->b.b.depth0, start_mip) : 1;
key->cachable = 1;
assert(key->size.depth == 1);
if(tex->b.b.target == PIPE_TEXTURE_CUBE && face_pick < 0) {
key->flags |= SVGA3D_SURFACE_CUBEMAP;
key->numFaces = 6;
} else {
key->numFaces = 1;
}

if(key->format == SVGA3D_FORMAT_INVALID) {
key->cachable = 0;
return NULL;
}

SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n");
handle = svga_screen_surface_create(ss, key);
if (!handle) {
key->cachable = 0;
return NULL;
}

SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle);

if (face_pick < 0)
face_pick = 0;

if (zslice_pick >= 0)
z_offset = zslice_pick;

for (i = 0; i < key->numMipLevels; i++) {
for (j = 0; j < key->numFaces; j++) {
if(tex->defined[j + face_pick][i + start_mip]) {
unsigned depth = (zslice_pick < 0 ?
u_minify(tex->b.b.depth0, i + start_mip) :
1);

svga_texture_copy_handle(svga_context(pipe),
ss,
tex->handle,
0, 0, z_offset,
i + start_mip,
j + face_pick,
handle, 0, 0, 0, i, j,
u_minify(tex->b.b.width0, i + start_mip),
u_minify(tex->b.b.height0, i + start_mip),
depth);
}
}
}

return handle;
}


static struct pipe_surface *
svga_get_tex_surface(struct pipe_screen *screen,
struct pipe_resource *pt,
unsigned face, unsigned level, unsigned zslice,
unsigned flags)
{
struct svga_texture *tex = svga_texture(pt);
struct svga_surface *s;
boolean render = flags & PIPE_BUFFER_USAGE_GPU_WRITE ? TRUE : FALSE;
boolean view = FALSE;
SVGA3dSurfaceFormat format;

s = CALLOC_STRUCT(svga_surface);
if (!s)
return NULL;

pipe_reference_init(&s->base.reference, 1);
pipe_resource_reference(&s->base.texture, pt);
s->base.format = pt->format;
s->base.width = u_minify(pt->width0, level);
s->base.height = u_minify(pt->height0, level);
s->base.usage = flags;
s->base.level = level;
s->base.face = face;
s->base.zslice = zslice;

if (!render)
format = svga_translate_format(pt->format);
else
format = svga_translate_format_render(pt->format);

assert(format != SVGA3D_FORMAT_INVALID);
assert(!(flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE));


if (svga_screen(screen)->debug.force_surface_view)
view = TRUE;

/* Currently only used for compressed textures */
if (render &&
format != svga_translate_format(pt->format)) {
view = TRUE;
}

if (level != 0 &&
svga_screen(screen)->debug.force_level_surface_view)
view = TRUE;

if (pt->target == PIPE_TEXTURE_3D)
view = TRUE;

if (svga_screen(screen)->debug.no_surface_view)
view = FALSE;

if (view) {
SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: yes %p, level %u face %u z %u, %p\n",
pt, level, face, zslice, s);

s->handle = svga_texture_view_surface(NULL, tex, format, level, 1, face, zslice,
&s->key);
s->real_face = 0;
s->real_level = 0;
s->real_zslice = 0;
} else {
SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: no %p, level %u, face %u, z %u, %p\n",
pt, level, face, zslice, s);

memset(&s->key, 0, sizeof s->key);
s->handle = tex->handle;
s->real_face = face;
s->real_level = level;
s->real_zslice = zslice;
}

return &s->base;
}


static void
svga_tex_surface_destroy(struct pipe_surface *surf)
{
struct svga_surface *s = svga_surface(surf);
struct svga_texture *t = svga_texture(surf->texture);
struct svga_screen *ss = svga_screen(surf->texture->screen);

if(s->handle != t->handle) {
SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle);
svga_screen_surface_destroy(ss, &s->key, &s->handle);
}

pipe_resource_reference(&surf->texture, NULL);
FREE(surf);
}


static INLINE void
svga_mark_surface_dirty(struct pipe_surface *surf)
{
struct svga_surface *s = svga_surface(surf);

if(!s->dirty) {
struct svga_texture *tex = svga_texture(surf->texture);

s->dirty = TRUE;

if (s->handle == tex->handle)
tex->defined[surf->face][surf->level] = TRUE;
else {
/* this will happen later in svga_propagate_surface */
}
}
}


void svga_mark_surfaces_dirty(struct svga_context *svga)
{
unsigned i;

for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
if (svga->curr.framebuffer.cbufs[i])
svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]);
}
if (svga->curr.framebuffer.zsbuf)
svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf);
}


/**
* Progagate any changes from surfaces to texture.
* pipe is optional context to inline the blit command in.
*/
void
svga_propagate_surface(struct pipe_context *pipe, struct pipe_surface *surf)
{
struct svga_surface *s = svga_surface(surf);
struct svga_texture *tex = svga_texture(surf->texture);
struct svga_screen *ss = svga_screen(surf->texture->screen);

if (!s->dirty)
return;

s->dirty = FALSE;
ss->texture_timestamp++;
tex->view_age[surf->level] = ++(tex->age);

if (s->handle != tex->handle) {
SVGA_DBG(DEBUG_VIEWS, "svga: Surface propagate: tex %p, level %u, from %p\n", tex, surf->level, surf);
svga_texture_copy_handle(svga_context(pipe), ss,
s->handle, 0, 0, 0, s->real_level, s->real_face,
tex->handle, 0, 0, surf->zslice, surf->level, surf->face,
u_minify(tex->b.b.width0, surf->level),
u_minify(tex->b.b.height0, surf->level), 1);
tex->defined[surf->face][surf->level] = TRUE;
}
}

/**
* Check if we should call svga_propagate_surface on the surface.
*/
boolean
svga_surface_needs_propagation(struct pipe_surface *surf)
{
struct svga_surface *s = svga_surface(surf);
struct svga_texture *tex = svga_texture(surf->texture);

return s->dirty && s->handle != tex->handle;
}






void
svga_screen_init_surface_functions(struct pipe_screen *screen)
{
screen->get_tex_surface = svga_get_tex_surface;
screen->tex_surface_destroy = svga_tex_surface_destroy;
}


+ 85
- 0
src/gallium/drivers/svga/svga_surface.h View File

@@ -0,0 +1,85 @@
/**********************************************************
* Copyright 2008-2009 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************/

#ifndef SVGA_SURFACE_H
#define SVGA_SURFACE_H


#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "util/u_inlines.h"
#include "svga_screen_cache.h"

struct pipe_context;
struct pipe_screen;
struct svga_context;
struct svga_texture;
struct svga_winsys_surface;
enum SVGA3dSurfaceFormat;


struct svga_surface
{
struct pipe_surface base;

struct svga_host_surface_cache_key key;
struct svga_winsys_surface *handle;

unsigned real_face;
unsigned real_level;
unsigned real_zslice;

boolean dirty;
};


extern void
svga_propagate_surface(struct pipe_context *pipe, struct pipe_surface *surf);

extern boolean
svga_surface_needs_propagation(struct pipe_surface *surf);

struct svga_winsys_surface *
svga_texture_view_surface(struct pipe_context *pipe,
struct svga_texture *tex,
SVGA3dSurfaceFormat format,
unsigned start_mip,
unsigned num_mip,
int face_pick,
int zslice_pick,
struct svga_host_surface_cache_key *key); /* OUT */


static INLINE struct svga_surface *
svga_surface(struct pipe_surface *surface)
{
assert(surface);
return (struct svga_surface *)surface;
}

void
svga_screen_init_surface_functions(struct pipe_screen *screen);

#endif

+ 1
- 1
src/gallium/drivers/svga/svga_swtnl.h View File

@@ -40,7 +40,7 @@ void svga_destroy_swtnl( struct svga_context *svga );

enum pipe_error
svga_swtnl_draw_range_elements(struct svga_context *svga,
struct pipe_buffer *indexBuffer,
struct pipe_resource *indexBuffer,
unsigned indexSize,
unsigned min_index,
unsigned max_index,

+ 17
- 16
src/gallium/drivers/svga/svga_swtnl_backend.c View File

@@ -79,9 +79,9 @@ svga_vbuf_render_allocate_vertices( struct vbuf_render *render,
new_vbuf = TRUE;

if (new_vbuf)
pipe_buffer_reference(&svga_render->vbuf, NULL);
pipe_resource_reference(&svga_render->vbuf, NULL);
if (new_ibuf)
pipe_buffer_reference(&svga_render->ibuf, NULL);
pipe_resource_reference(&svga_render->ibuf, NULL);

if (!svga_render->vbuf) {
svga_render->vbuf_size = MAX2(size, svga_render->vbuf_alloc_size);
@@ -117,14 +117,14 @@ svga_vbuf_render_map_vertices( struct vbuf_render *render )
{
struct svga_vbuf_render *svga_render = svga_vbuf_render(render);
struct svga_context *svga = svga_render->svga;
struct pipe_screen *screen = svga->pipe.screen;

char *ptr = (char*)pipe_buffer_map(screen,
char *ptr = (char*)pipe_buffer_map(&svga->pipe,
svga_render->vbuf,
PIPE_BUFFER_USAGE_CPU_WRITE |
PIPE_BUFFER_USAGE_FLUSH_EXPLICIT |
PIPE_BUFFER_USAGE_DISCARD |
PIPE_BUFFER_USAGE_UNSYNCHRONIZED);
PIPE_TRANSFER_WRITE |
PIPE_TRANSFER_FLUSH_EXPLICIT |
PIPE_TRANSFER_DISCARD |
PIPE_TRANSFER_UNSYNCHRONIZED,
&svga_render->vbuf_transfer);
return ptr + svga_render->vbuf_offset;
}

@@ -135,14 +135,15 @@ svga_vbuf_render_unmap_vertices( struct vbuf_render *render,
{
struct svga_vbuf_render *svga_render = svga_vbuf_render(render);
struct svga_context *svga = svga_render->svga;
struct pipe_screen *screen = svga->pipe.screen;
unsigned offset, length;
size_t used = svga_render->vertex_size * ((size_t)max_index + 1);

offset = svga_render->vbuf_offset + svga_render->vertex_size * min_index;
length = svga_render->vertex_size * (max_index + 1 - min_index);
pipe_buffer_flush_mapped_range(screen, svga_render->vbuf, offset, length);
pipe_buffer_unmap(screen, svga_render->vbuf);
pipe_buffer_flush_mapped_range(&svga->pipe,
svga_render->vbuf_transfer,
offset, length);
pipe_buffer_unmap(&svga->pipe, svga_render->vbuf, svga_render->vbuf_transfer);
svga_render->min_index = min_index;
svga_render->max_index = max_index;
svga_render->vbuf_used = MAX2(svga_render->vbuf_used, used);
@@ -255,7 +256,7 @@ svga_vbuf_render_draw( struct vbuf_render *render,
assert(( svga_render->vbuf_offset - svga_render->vdecl_offset) % svga_render->vertex_size == 0);
if (svga_render->ibuf_size < svga_render->ibuf_offset + size)
pipe_buffer_reference(&svga_render->ibuf, NULL);
pipe_resource_reference(&svga_render->ibuf, NULL);

if (!svga_render->ibuf) {
svga_render->ibuf_size = MAX2(size, svga_render->ibuf_alloc_size);
@@ -266,8 +267,8 @@ svga_vbuf_render_draw( struct vbuf_render *render,
svga_render->ibuf_offset = 0;
}

pipe_buffer_write_nooverlap(screen, svga_render->ibuf,
svga_render->ibuf_offset, 2 * nr_indices, indices);
pipe_buffer_write_nooverlap(&svga->pipe, svga_render->ibuf,
svga_render->ibuf_offset, 2 * nr_indices, indices);


/* off to hardware */
@@ -315,8 +316,8 @@ svga_vbuf_render_destroy( struct vbuf_render *render )
{
struct svga_vbuf_render *svga_render = svga_vbuf_render(render);

pipe_buffer_reference(&svga_render->vbuf, NULL);
pipe_buffer_reference(&svga_render->ibuf, NULL);
pipe_resource_reference(&svga_render->vbuf, NULL);
pipe_resource_reference(&svga_render->ibuf, NULL);
FREE(svga_render);
}


+ 20
- 12
src/gallium/drivers/svga/svga_swtnl_draw.c View File

@@ -37,12 +37,15 @@

enum pipe_error
svga_swtnl_draw_range_elements(struct svga_context *svga,
struct pipe_buffer *indexBuffer,
struct pipe_resource *indexBuffer,
unsigned indexSize,
unsigned min_index,
unsigned max_index,
unsigned prim, unsigned start, unsigned count)
{
struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
struct pipe_transfer *ib_transfer;
struct pipe_transfer *cb_transfer;
struct draw_context *draw = svga->swtnl.draw;
unsigned i;
const void *map;
@@ -64,17 +67,19 @@ svga_swtnl_draw_range_elements(struct svga_context *svga,
* Map vertex buffers
*/
for (i = 0; i < svga->curr.num_vertex_buffers; i++) {
map = pipe_buffer_map(svga->pipe.screen,
map = pipe_buffer_map(&svga->pipe,
svga->curr.vb[i].buffer,
PIPE_BUFFER_USAGE_CPU_READ);
PIPE_BUFFER_USAGE_CPU_READ,
&vb_transfer[i]);

draw_set_mapped_vertex_buffer(draw, i, map);
}

/* Map index buffer, if present */
if (indexBuffer) {
map = pipe_buffer_map(svga->pipe.screen, indexBuffer,
PIPE_BUFFER_USAGE_CPU_READ);
map = pipe_buffer_map(&svga->pipe, indexBuffer,
PIPE_BUFFER_USAGE_CPU_READ,
&ib_transfer);

draw_set_mapped_element_buffer_range(draw,
indexSize,
@@ -84,14 +89,15 @@ svga_swtnl_draw_range_elements(struct svga_context *svga,
}
if (svga->curr.cb[PIPE_SHADER_VERTEX]) {
map = pipe_buffer_map(svga->pipe.screen,
map = pipe_buffer_map(&svga->pipe,
svga->curr.cb[PIPE_SHADER_VERTEX],
PIPE_BUFFER_USAGE_CPU_READ);
PIPE_BUFFER_USAGE_CPU_READ,
&cb_transfer);
assert(map);
draw_set_mapped_constant_buffer(
draw, PIPE_SHADER_VERTEX, 0,
map,
svga->curr.cb[PIPE_SHADER_VERTEX]->size);
svga->curr.cb[PIPE_SHADER_VERTEX]->width0);
}

draw_arrays(svga->swtnl.draw, prim, start, count);
@@ -105,18 +111,20 @@ svga_swtnl_draw_range_elements(struct svga_context *svga,
* unmap vertex/index buffers
*/
for (i = 0; i < svga->curr.num_vertex_buffers; i++) {
pipe_buffer_unmap(svga->pipe.screen, svga->curr.vb[i].buffer);
pipe_buffer_unmap(&svga->pipe, svga->curr.vb[i].buffer,
vb_transfer[i]);
draw_set_mapped_vertex_buffer(draw, i, NULL);
}

if (indexBuffer) {
pipe_buffer_unmap(svga->pipe.screen, indexBuffer);
pipe_buffer_unmap(&svga->pipe, indexBuffer, ib_transfer);
draw_set_mapped_element_buffer(draw, 0, NULL);
}

if (svga->curr.cb[PIPE_SHADER_VERTEX]) {
pipe_buffer_unmap(svga->pipe.screen,
svga->curr.cb[PIPE_SHADER_VERTEX]);
pipe_buffer_unmap(&svga->pipe,
svga->curr.cb[PIPE_SHADER_VERTEX],
cb_transfer);
}

return ret;

+ 4
- 2
src/gallium/drivers/svga/svga_swtnl_private.h View File

@@ -45,8 +45,10 @@ struct svga_vbuf_render {

unsigned prim;

struct pipe_buffer *vbuf;
struct pipe_buffer *ibuf;
struct pipe_resource *vbuf;
struct pipe_resource *ibuf;
struct pipe_transfer *vbuf_transfer;
struct pipe_transfer *ibuf_transfer;

/* current size of buffer */
size_t vbuf_size;

+ 4
- 4
src/gallium/drivers/svga/svga_winsys.h View File

@@ -189,7 +189,7 @@ struct svga_winsys_screen

/**
* Creates a surface from a winsys handle.
* Used to implement pipe_screen::texture_from_handle.
* Used to implement pipe_screen::resource_from_handle.
*/
struct svga_winsys_surface *
(*surface_from_handle)(struct svga_winsys_screen *sws,
@@ -198,7 +198,7 @@ struct svga_winsys_screen

/**
* Get a winsys_handle from a surface.
* Used to implement pipe_screen::texture_get_handle.
* Used to implement pipe_screen::resource_get_handle.
*/
boolean
(*surface_get_handle)(struct svga_winsys_screen *sws,
@@ -294,12 +294,12 @@ svga_screen_create(struct svga_winsys_screen *sws);
struct svga_winsys_screen *
svga_winsys_screen(struct pipe_screen *screen);

struct pipe_buffer *
struct pipe_resource *
svga_screen_buffer_wrap_surface(struct pipe_screen *screen,
enum SVGA3dSurfaceFormat format,
struct svga_winsys_surface *srf);

struct svga_winsys_surface *
svga_screen_buffer_get_winsys_surface(struct pipe_buffer *buffer);
svga_screen_buffer_get_winsys_surface(struct pipe_resource *buffer);

#endif /* SVGA_WINSYS_H_ */

Loading…
Cancel
Save