As with others so far, a fairly shallow conversion.gallium-buffer-usage-cleanup
| @@ -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 | |||
| @@ -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; | |||
| @@ -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 ); | |||
| @@ -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; | |||
| @@ -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; | |||
| @@ -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; | |||
| } | |||
| @@ -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; | |||
| } | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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) | |||
| { | |||
| @@ -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" | |||
| @@ -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, | |||
| @@ -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" | |||
| @@ -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); | |||
| } | |||
| @@ -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); | |||
| } | |||
| @@ -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; | |||
| } | |||
| @@ -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 */ | |||
| @@ -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; | |||
| } | |||
| @@ -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); | |||
| /** | |||
| @@ -0,0 +1,2 @@ | |||
| @@ -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); | |||
| @@ -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 */ | |||
| @@ -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; | |||
| } | |||
| @@ -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); | |||
| @@ -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); | |||
| } | |||
| @@ -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 | |||
| @@ -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) && | |||
| @@ -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; | |||
| @@ -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; | |||
| @@ -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; | |||
| } | |||
| } | |||
| @@ -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); | |||
| } | |||
| } | |||
| @@ -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; | |||
| } | |||
| @@ -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 | |||
| @@ -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, | |||
| @@ -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); | |||
| } | |||
| @@ -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; | |||
| @@ -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; | |||
| @@ -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_ */ | |||