diff options
author | Keith Whitwell <keithw@vmware.com> | 2010-03-04 16:09:33 +0000 |
---|---|---|
committer | Keith Whitwell <keithw@vmware.com> | 2010-03-04 16:09:33 +0000 |
commit | 94ce4eb3c27706d992226d847d123c46b14b1c4f (patch) | |
tree | 051157b0c0a2717484e2c0e41551c1e75f0cb289 | |
parent | c7f7a309af54c76eccb451aa0c4f007656ebe7e1 (diff) |
softpipe: rework to use the llvmpipe winsys
Promote the llvmpipe winsys more or less unchanged to
state_trackers/sw_winsys.h.
Some minor breakages:
- softpipe::texture_blanket is broken, but scheduled for removal anyway.
- haven't fixed up g3vdl yet.
28 files changed, 767 insertions, 1679 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index f84ede675b..8816440a50 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -167,7 +167,7 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen, unsigned geom_flags ) { struct llvmpipe_screen *screen = llvmpipe_screen(_screen); - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; const struct util_format_description *format_desc; format_desc = util_format_description(format); @@ -258,7 +258,7 @@ llvmpipe_flush_frontbuffer(struct pipe_screen *_screen, void *context_private) { struct llvmpipe_screen *screen = llvmpipe_screen(_screen); - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; struct llvmpipe_texture *texture = llvmpipe_texture(surface->texture); assert(texture->dt); @@ -271,7 +271,7 @@ static void llvmpipe_destroy_screen( struct pipe_screen *_screen ) { struct llvmpipe_screen *screen = llvmpipe_screen(_screen); - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; lp_jit_screen_cleanup(screen); @@ -288,7 +288,7 @@ llvmpipe_destroy_screen( struct pipe_screen *_screen ) * Note: we're not presently subclassing pipe_screen (no llvmpipe_screen). */ struct pipe_screen * -llvmpipe_create_screen(struct llvmpipe_winsys *winsys) +llvmpipe_create_screen(struct sw_winsys *winsys) { struct llvmpipe_screen *screen = CALLOC_STRUCT(llvmpipe_screen); diff --git a/src/gallium/drivers/llvmpipe/lp_screen.h b/src/gallium/drivers/llvmpipe/lp_screen.h index 4a1b4d6f3e..3211822b53 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.h +++ b/src/gallium/drivers/llvmpipe/lp_screen.h @@ -43,14 +43,14 @@ #include "pipe/p_defines.h" -struct llvmpipe_winsys; +struct sw_winsys; struct llvmpipe_screen { struct pipe_screen base; - struct llvmpipe_winsys *winsys; + struct sw_winsys *winsys; LLVMModuleRef module; LLVMExecutionEngineRef engine; diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index aebed85fbb..72b19d0b05 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -479,7 +479,7 @@ lp_setup_set_sampler_textures( struct setup_context *setup, */ struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen); - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; jit_tex->data = winsys->displaytarget_map(winsys, lp_tex->dt, PIPE_BUFFER_USAGE_CPU_READ); assert(jit_tex->data); diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index 7f45635542..aed9ed6175 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -93,7 +93,7 @@ static boolean llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, struct llvmpipe_texture *lpt) { - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; /* Round up the surface size to a multiple of the tile size to * avoid tile clipping. @@ -187,7 +187,7 @@ llvmpipe_texture_destroy(struct pipe_texture *pt) if (lpt->dt) { /* display target */ - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; winsys->displaytarget_destroy(winsys, lpt->dt); } else { @@ -357,7 +357,7 @@ llvmpipe_transfer_map( struct pipe_screen *_screen, if (lpt->dt) { /* display target */ - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; map = winsys->displaytarget_map(winsys, lpt->dt, pipe_transfer_buffer_flags(transfer)); @@ -398,7 +398,7 @@ llvmpipe_transfer_unmap(struct pipe_screen *screen, if (lpt->dt) { /* display target */ - struct llvmpipe_winsys *winsys = lp_screen->winsys; + struct sw_winsys *winsys = lp_screen->winsys; winsys->displaytarget_unmap(winsys, lpt->dt); } } diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h index 87c905bc02..6a6d9f9222 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.h +++ b/src/gallium/drivers/llvmpipe/lp_texture.h @@ -35,7 +35,8 @@ struct pipe_context; struct pipe_screen; struct llvmpipe_context; -struct llvmpipe_displaytarget; + +struct sw_displaytarget; struct llvmpipe_texture @@ -49,7 +50,7 @@ struct llvmpipe_texture * Display target, for textures with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET * usage. */ - struct llvmpipe_displaytarget *dt; + struct sw_displaytarget *dt; /** * Malloc'ed data for regular textures, or a mapping to dt above. diff --git a/src/gallium/drivers/softpipe/Makefile b/src/gallium/drivers/softpipe/Makefile index e4ac49fa85..1c6e4ae076 100644 --- a/src/gallium/drivers/softpipe/Makefile +++ b/src/gallium/drivers/softpipe/Makefile @@ -6,6 +6,7 @@ LIBNAME = softpipe C_SOURCES = \ sp_fs_exec.c \ sp_fs_sse.c \ + sp_buffer.c \ sp_clear.c \ sp_flush.c \ sp_query.c \ @@ -32,7 +33,6 @@ C_SOURCES = \ sp_tex_tile_cache.c \ sp_tile_cache.c \ sp_surface.c \ - sp_video_context.c \ - sp_winsys.c + sp_video_context.c include ../../Makefile.template diff --git a/src/gallium/drivers/softpipe/SConscript b/src/gallium/drivers/softpipe/SConscript index 3042e556c6..27ab00b036 100644 --- a/src/gallium/drivers/softpipe/SConscript +++ b/src/gallium/drivers/softpipe/SConscript @@ -7,6 +7,7 @@ softpipe = env.ConvenienceLibrary( source = [ 'sp_fs_exec.c', 'sp_fs_sse.c', + 'sp_buffer.c', 'sp_clear.c', 'sp_context.c', 'sp_draw_arrays.c', @@ -33,8 +34,7 @@ softpipe = env.ConvenienceLibrary( 'sp_tex_tile_cache.c', 'sp_texture.c', 'sp_tile_cache.c', - 'sp_video_context.c', - 'sp_winsys.c' + 'sp_video_context.c' ]) Export('softpipe') diff --git a/src/gallium/drivers/softpipe/sp_buffer.c b/src/gallium/drivers/softpipe/sp_buffer.c new file mode 100644 index 0000000000..8f39025086 --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_buffer.c @@ -0,0 +1,118 @@ +/************************************************************************** + * + * Copyright 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, 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 VMWARE 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. + * + **************************************************************************/ + + +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_math.h" + +#include "sp_screen.h" +#include "sp_buffer.h" + + +static void * +softpipe_buffer_map(struct pipe_screen *screen, + struct pipe_buffer *buf, + unsigned flags) +{ + struct softpipe_buffer *softpipe_buf = softpipe_buffer(buf); + return softpipe_buf->data; +} + + +static void +softpipe_buffer_unmap(struct pipe_screen *screen, + struct pipe_buffer *buf) +{ +} + + +static void +softpipe_buffer_destroy(struct pipe_buffer *buf) +{ + struct softpipe_buffer *sbuf = softpipe_buffer(buf); + + if (!sbuf->userBuffer) + align_free(sbuf->data); + + FREE(sbuf); +} + + +static struct pipe_buffer * +softpipe_buffer_create(struct pipe_screen *screen, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct softpipe_buffer *buffer = CALLOC_STRUCT(softpipe_buffer); + + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.screen = screen; + buffer->base.alignment = MAX2(alignment, 16); + buffer->base.usage = usage; + buffer->base.size = size; + + buffer->data = align_malloc(size, alignment); + + return &buffer->base; +} + + +/** + * Create buffer which wraps user-space data. + */ +static struct pipe_buffer * +softpipe_user_buffer_create(struct pipe_screen *screen, + void *ptr, + unsigned bytes) +{ + struct softpipe_buffer *buffer; + + buffer = CALLOC_STRUCT(softpipe_buffer); + if(!buffer) + return NULL; + + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.screen = screen; + buffer->base.size = bytes; + buffer->userBuffer = TRUE; + buffer->data = ptr; + + return &buffer->base; +} + + +void +softpipe_init_screen_buffer_funcs(struct pipe_screen *screen) +{ + screen->buffer_create = softpipe_buffer_create; + screen->user_buffer_create = softpipe_user_buffer_create; + screen->buffer_map = softpipe_buffer_map; + screen->buffer_unmap = softpipe_buffer_unmap; + screen->buffer_destroy = softpipe_buffer_destroy; +} diff --git a/src/gallium/drivers/softpipe/sp_winsys.h b/src/gallium/drivers/softpipe/sp_buffer.h index 6e3920c49b..9d8e56a176 100644 --- a/src/gallium/drivers/softpipe/sp_winsys.h +++ b/src/gallium/drivers/softpipe/sp_buffer.h @@ -1,8 +1,8 @@ /************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * + * Copyright 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 @@ -10,64 +10,46 @@ * 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 + * IN NO EVENT SHALL VMWARE 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. - * + * **************************************************************************/ -/* This is the interface that softpipe requires any window system - * hosting it to implement. This is the only include file in softpipe - * which is public. - */ +#ifndef SP_BUFFER_H +#define SP_BUFFER_H +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" -#ifndef SP_WINSYS_H -#define SP_WINSYS_H -#ifdef __cplusplus -extern "C" { -#endif +struct softpipe_buffer +{ + struct pipe_buffer base; + boolean userBuffer; /** Is this a user-space buffer? */ + void *data; +}; -#include "pipe/p_defines.h" -struct pipe_screen; -struct pipe_winsys; -struct pipe_context; -struct pipe_texture; -struct pipe_buffer; - - - -/** - * Create a softpipe screen that uses the - * given winsys for allocating buffers. - */ -struct pipe_screen *softpipe_create_screen( struct pipe_winsys * ); - -/** - * Create a softpipe screen that uses - * regular malloc to create all its buffers. - */ -struct pipe_screen *softpipe_create_screen_malloc(void); +/** Cast wrapper */ +static INLINE struct softpipe_buffer * +softpipe_buffer( struct pipe_buffer *buf ) +{ + return (struct softpipe_buffer *)buf; +} -boolean -softpipe_get_texture_buffer( struct pipe_texture *texture, - struct pipe_buffer **buf, - unsigned *stride ); +void +softpipe_init_screen_buffer_funcs(struct pipe_screen *screen); -#ifdef __cplusplus -} -#endif -#endif /* SP_WINSYS_H */ +#endif /* SP_BUFFER_H */ diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index ddc35bcd62..53eecd1cbf 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -210,7 +210,7 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->dump_fs = debug_get_bool_option( "GALLIUM_DUMP_FS", FALSE ); softpipe->dump_gs = debug_get_bool_option( "SOFTPIPE_DUMP_GS", FALSE ); - softpipe->pipe.winsys = screen->winsys; + softpipe->pipe.winsys = NULL; softpipe->pipe.screen = screen; softpipe->pipe.destroy = softpipe_destroy; softpipe->pipe.priv = priv; diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c index b2acc36bf7..0899e1145a 100644 --- a/src/gallium/drivers/softpipe/sp_draw_arrays.c +++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c @@ -40,83 +40,13 @@ #include "sp_context.h" #include "sp_query.h" #include "sp_state.h" +#include "sp_buffer.h" #include "draw/draw_context.h" -static void -softpipe_map_constant_buffers(struct softpipe_context *sp) -{ - struct pipe_winsys *ws = sp->pipe.winsys; - uint i; - - for (i = 0; i < PIPE_SHADER_TYPES; i++) { - uint j; - - for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) { - if (sp->constants[i][j] && sp->constants[i][j]->size) { - sp->mapped_constants[i][j] = ws->buffer_map(ws, - sp->constants[i][j], - PIPE_BUFFER_USAGE_CPU_READ); - } - } - } - - for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { - if (sp->constants[PIPE_SHADER_VERTEX][i]) { - draw_set_mapped_constant_buffer(sp->draw, - PIPE_SHADER_VERTEX, - i, - sp->mapped_constants[PIPE_SHADER_VERTEX][i], - sp->constants[PIPE_SHADER_VERTEX][i]->size); - } - if (sp->constants[PIPE_SHADER_GEOMETRY][i]) { - draw_set_mapped_constant_buffer(sp->draw, - PIPE_SHADER_GEOMETRY, - i, - sp->mapped_constants[PIPE_SHADER_GEOMETRY][i], - sp->constants[PIPE_SHADER_GEOMETRY][i]->size); - } - } -} - - -static void -softpipe_unmap_constant_buffers(struct softpipe_context *sp) -{ - struct pipe_winsys *ws = sp->pipe.winsys; - uint i; - /* really need to flush all prims since the vert/frag shaders const buffers - * are going away now. - */ - draw_flush(sp->draw); - - for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { - draw_set_mapped_constant_buffer(sp->draw, - PIPE_SHADER_VERTEX, - i, - NULL, - 0); - draw_set_mapped_constant_buffer(sp->draw, - PIPE_SHADER_GEOMETRY, - i, - NULL, - 0); - } - - for (i = 0; i < PIPE_SHADER_TYPES; i++) { - uint j; - - for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) { - if (sp->constants[i][j] && sp->constants[i][j]->size) { - ws->buffer_unmap(ws, sp->constants[i][j]); - } - sp->mapped_constants[i][j] = NULL; - } - } -} /** @@ -261,25 +191,16 @@ softpipe_draw_range_elements_instanced(struct pipe_context *pipe, } softpipe_map_transfers(sp); - softpipe_map_constant_buffers(sp); /* Map vertex buffers */ for (i = 0; i < sp->num_vertex_buffers; i++) { - void *buf; - - buf = pipe_buffer_map(pipe->screen, - sp->vertex_buffer[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); + void *buf = softpipe_buffer(sp->vertex_buffer[i].buffer)->data; draw_set_mapped_vertex_buffer(draw, i, buf); } /* Map index buffer, if present */ if (indexBuffer) { - void *mapped_indexes; - - mapped_indexes = pipe_buffer_map(pipe->screen, - indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); + void *mapped_indexes = softpipe_buffer(indexBuffer)->data; draw_set_mapped_element_buffer_range(draw, indexSize, minIndex, @@ -300,15 +221,18 @@ softpipe_draw_range_elements_instanced(struct pipe_context *pipe, /* unmap vertex/index buffers - will cause draw module to flush */ for (i = 0; i < sp->num_vertex_buffers; i++) { draw_set_mapped_vertex_buffer(draw, i, NULL); - pipe_buffer_unmap(pipe->screen, sp->vertex_buffer[i].buffer); } if (indexBuffer) { draw_set_mapped_element_buffer(draw, 0, NULL); - pipe_buffer_unmap(pipe->screen, indexBuffer); } - /* Note: leave drawing surfaces mapped */ - softpipe_unmap_constant_buffers(sp); + /* + * TODO: Flush only when a user vertex/index buffer is present + * (or even better, modify draw module to do this + * internally when this condition is seen?) + */ + draw_flush(draw); + /* Note: leave drawing surfaces mapped */ sp->dirty_render_cache = TRUE; } diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index 6ec63fe698..107631f6b5 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -32,10 +32,12 @@ #include "pipe/p_defines.h" #include "pipe/p_screen.h" +#include "state_tracker/sw_winsys.h" + #include "sp_texture.h" -#include "sp_winsys.h" #include "sp_screen.h" #include "sp_context.h" +#include "sp_buffer.h" static const char * @@ -145,6 +147,8 @@ softpipe_is_format_supported( struct pipe_screen *screen, unsigned tex_usage, unsigned geom_flags ) { + struct sw_winsys *winsys = softpipe_screen(screen)->winsys; + assert(target == PIPE_TEXTURE_1D || target == PIPE_TEXTURE_2D || target == PIPE_TEXTURE_3D || @@ -166,15 +170,25 @@ softpipe_is_format_supported( struct pipe_screen *screen, case PIPE_FORMAT_NONE: return FALSE; default: - return TRUE; + break; } + + if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) { + if(!winsys->is_displaytarget_format_supported(winsys, format)) + return FALSE; + } + + /* XXX: this is often a lie. Pull in logic from llvmpipe to fix. + */ + return TRUE; } static void softpipe_destroy_screen( struct pipe_screen *screen ) { - struct pipe_winsys *winsys = screen->winsys; + struct softpipe_screen *sp_screen = softpipe_screen(screen); + struct sw_winsys *winsys = sp_screen->winsys; if(winsys->destroy) winsys->destroy(winsys); @@ -183,21 +197,37 @@ softpipe_destroy_screen( struct pipe_screen *screen ) } +/* This is often overriden by the co-state tracker. + */ +static void +softpipe_flush_frontbuffer(struct pipe_screen *_screen, + struct pipe_surface *surface, + void *context_private) +{ + struct softpipe_screen *screen = softpipe_screen(_screen); + struct sw_winsys *winsys = screen->winsys; + struct softpipe_texture *texture = softpipe_texture(surface->texture); + + assert(texture->dt); + if (texture->dt) + winsys->displaytarget_display(winsys, texture->dt, context_private); +} /** * Create a new pipe_screen object * Note: we're not presently subclassing pipe_screen (no softpipe_screen). */ struct pipe_screen * -softpipe_create_screen(struct pipe_winsys *winsys) +softpipe_create_screen(struct sw_winsys *winsys) { struct softpipe_screen *screen = CALLOC_STRUCT(softpipe_screen); if (!screen) return NULL; - screen->base.winsys = winsys; + screen->winsys = winsys; + screen->base.winsys = NULL; screen->base.destroy = softpipe_destroy_screen; screen->base.get_name = softpipe_get_name; @@ -206,9 +236,10 @@ softpipe_create_screen(struct pipe_winsys *winsys) screen->base.get_paramf = softpipe_get_paramf; screen->base.is_format_supported = softpipe_is_format_supported; screen->base.context_create = softpipe_create_context; + screen->base.flush_frontbuffer = softpipe_flush_frontbuffer; softpipe_init_screen_texture_funcs(&screen->base); - u_simple_screen_init(&screen->base); + softpipe_init_screen_buffer_funcs(&screen->base); return &screen->base; } diff --git a/src/gallium/drivers/softpipe/sp_screen.h b/src/gallium/drivers/softpipe/sp_screen.h index 3d4bfd3e84..4d7d8bada2 100644 --- a/src/gallium/drivers/softpipe/sp_screen.h +++ b/src/gallium/drivers/softpipe/sp_screen.h @@ -35,10 +35,13 @@ #include "pipe/p_defines.h" +struct sw_winsys; struct softpipe_screen { struct pipe_screen base; + struct sw_winsys *winsys; + /* Increments whenever textures are modified. Contexts can track * this. */ @@ -55,4 +58,13 @@ softpipe_screen( struct pipe_screen *pipe ) } + +/** + * Create a softpipe screen that uses the + * given winsys for allocating buffers. + */ +struct pipe_screen *softpipe_create_screen( struct sw_winsys * ); + + + #endif /* SP_SCREEN_H */ diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_fs.c index c88e213751..cd0e905bc9 100644 --- a/src/gallium/drivers/softpipe/sp_state_fs.c +++ b/src/gallium/drivers/softpipe/sp_state_fs.c @@ -28,6 +28,7 @@ #include "sp_context.h" #include "sp_state.h" #include "sp_fs.h" +#include "sp_buffer.h" #include "pipe/p_defines.h" #include "util/u_memory.h" @@ -163,26 +164,35 @@ softpipe_delete_vs_state(struct pipe_context *pipe, void *vs) FREE( state ); } - - void softpipe_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_buffer *buf) + struct pipe_buffer *constants) { struct softpipe_context *softpipe = softpipe_context(pipe); + unsigned size = constants ? constants->size : 0; + const void *data = constants ? softpipe_buffer(constants)->data : NULL; assert(shader < PIPE_SHADER_TYPES); - assert(index < PIPE_MAX_CONSTANT_BUFFERS); + assert(index == 0); + + if(softpipe->constants[shader][index] == constants) + return; draw_flush(softpipe->draw); /* note: reference counting */ - pipe_buffer_reference(&softpipe->constants[shader][index], buf); + pipe_buffer_reference(&softpipe->constants[shader][index], constants); + + if(shader == PIPE_SHADER_VERTEX) { + draw_set_mapped_constant_buffer(softpipe->draw, PIPE_SHADER_VERTEX, 0, + data, size); + } softpipe->dirty |= SP_NEW_CONSTANTS; } + void * softpipe_create_gs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index 32d261b5ff..9641652da8 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -40,7 +40,8 @@ #include "sp_context.h" #include "sp_texture.h" #include "sp_screen.h" -#include "sp_winsys.h" + +#include "state_tracker/sw_winsys.h" /** @@ -72,11 +73,9 @@ softpipe_texture_layout(struct pipe_screen *screen, depth = u_minify(depth, 1); } - spt->buffer = screen->buffer_create(screen, 32, - PIPE_BUFFER_USAGE_PIXEL, - buffer_size); + spt->data = align_malloc(buffer_size, 16); - return spt->buffer != NULL; + return spt->data != NULL; } @@ -87,19 +86,18 @@ static boolean softpipe_displaytarget_layout(struct pipe_screen *screen, struct softpipe_texture * spt) { - unsigned usage = (PIPE_BUFFER_USAGE_CPU_READ_WRITE | - PIPE_BUFFER_USAGE_GPU_READ_WRITE); - unsigned tex_usage = spt->base.tex_usage; - - spt->buffer = screen->surface_buffer_create( screen, - spt->base.width0, - spt->base.height0, - spt->base.format, - usage, - tex_usage, - &spt->stride[0]); - - return spt->buffer != NULL; + struct sw_winsys *winsys = softpipe_screen(screen)->winsys; + + /* Round up the surface size to a multiple of the tile size? + */ + spt->dt = winsys->displaytarget_create(winsys, + spt->base.format, + spt->base.width0, + spt->base.height0, + 16, + &spt->stride[0] ); + + return spt->dt != NULL; } @@ -149,37 +147,29 @@ softpipe_texture_blanket(struct pipe_screen * screen, const unsigned *stride, struct pipe_buffer *buffer) { - struct softpipe_texture *spt; - assert(screen); - - /* Only supports one type */ - if (base->target != PIPE_TEXTURE_2D || - base->last_level != 0 || - base->depth0 != 1) { - return NULL; - } - - spt = CALLOC_STRUCT(softpipe_texture); - if (!spt) - return NULL; - - spt->base = *base; - pipe_reference_init(&spt->base.reference, 1); - spt->base.screen = screen; - spt->stride[0] = stride[0]; - - pipe_buffer_reference(&spt->buffer, buffer); - - return &spt->base; + /* Texture blanket is going away. + */ + debug_printf("softpipe_texture_blanket() not implemented!"); + return NULL; } static void softpipe_texture_destroy(struct pipe_texture *pt) { + struct softpipe_screen *screen = softpipe_screen(pt->screen); struct softpipe_texture *spt = softpipe_texture(pt); - pipe_buffer_reference(&spt->buffer, NULL); + if (spt->dt) { + /* display target */ + struct sw_winsys *winsys = screen->winsys; + winsys->displaytarget_destroy(winsys, spt->dt); + } + else { + /* regular texture */ + align_free(spt->data); + } + FREE(spt); } @@ -359,9 +349,20 @@ softpipe_transfer_map( struct pipe_screen *screen, spt = softpipe_texture(transfer->texture); format = transfer->texture->format; - map = pipe_buffer_map(screen, spt->buffer, pipe_transfer_buffer_flags(transfer)); - if (map == NULL) - return NULL; + if (spt->dt) { + /* display target */ + struct sw_winsys *winsys = softpipe_screen(screen)->winsys; + + map = winsys->displaytarget_map(winsys, spt->dt, + pipe_transfer_buffer_flags(transfer)); + if (map == NULL) + return NULL; + } + else { + map = spt->data; + if (map == NULL) + return NULL; + } /* May want to different things here depending on read/write nature * of the map: @@ -393,7 +394,11 @@ softpipe_transfer_unmap(struct pipe_screen *screen, assert(transfer->texture); spt = softpipe_texture(transfer->texture); - pipe_buffer_unmap( screen, spt->buffer ); + if (spt->dt) { + /* display target */ + struct sw_winsys *winsys = softpipe_screen(screen)->winsys; + winsys->displaytarget_unmap(winsys, spt->dt); + } if (transfer->usage & PIPE_TRANSFER_WRITE) { /* Mark the texture as dirty to expire the tile caches. */ @@ -474,24 +479,4 @@ softpipe_init_screen_texture_funcs(struct pipe_screen *screen) } -/** - * Return pipe_buffer handle and stride for given texture object. - * XXX used for??? - */ -boolean -softpipe_get_texture_buffer( struct pipe_texture *texture, - struct pipe_buffer **buf, - unsigned *stride ) -{ - struct softpipe_texture *tex = (struct softpipe_texture *) texture; - if (!tex) - return FALSE; - - pipe_buffer_reference(buf, tex->buffer); - - if (stride) - *stride = tex->stride[0]; - - return TRUE; -} diff --git a/src/gallium/drivers/softpipe/sp_texture.h b/src/gallium/drivers/softpipe/sp_texture.h index 2ef64e1e7c..e8d17ce7da 100644 --- a/src/gallium/drivers/softpipe/sp_texture.h +++ b/src/gallium/drivers/softpipe/sp_texture.h @@ -45,9 +45,16 @@ struct softpipe_texture unsigned long level_offset[PIPE_MAX_TEXTURE_LEVELS]; unsigned stride[PIPE_MAX_TEXTURE_LEVELS]; - /* The data is held here: + /** + * Display target, for textures with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET + * usage. + */ + struct sw_displaytarget *dt; + + /** + * Malloc'ed data for regular textures, or a mapping to dt above. */ - struct pipe_buffer *buffer; + void *data; /* True if texture images are power-of-two in all dimensions: */ diff --git a/src/gallium/drivers/softpipe/sp_winsys.c b/src/gallium/drivers/softpipe/sp_winsys.c deleted file mode 100644 index 0a6245ed2c..0000000000 --- a/src/gallium/drivers/softpipe/sp_winsys.c +++ /dev/null @@ -1,245 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA - * 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 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 - * THE COPYRIGHT HOLDERS, AUTHORS 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ - -/** - * @file - * Malloc softpipe winsys. Uses malloc for all memory allocations. - * - * @author Keith Whitwell - * @author Brian Paul - * @author Jose Fonseca - */ - - -#include "util/u_simple_screen.h"/* port to just p_screen */ -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" -#include "util/u_inlines.h" -#include "pipe/p_format.h" -#include "pipe/p_context.h" -#include "sp_winsys.h" - - -struct st_softpipe_buffer -{ - struct pipe_buffer base; - boolean userBuffer; /** Is this a user-space buffer? */ - void *data; - void *mapped; -}; - - -/** Cast wrapper */ -static INLINE struct st_softpipe_buffer * -st_softpipe_buffer( struct pipe_buffer *buf ) -{ - return (struct st_softpipe_buffer *)buf; -} - - -static void * -st_softpipe_buffer_map(struct pipe_winsys *winsys, - struct pipe_buffer *buf, - unsigned flags) -{ - struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf); - st_softpipe_buf->mapped = st_softpipe_buf->data; - return st_softpipe_buf->mapped; -} - - -static void -st_softpipe_buffer_unmap(struct pipe_winsys *winsys, - struct pipe_buffer *buf) -{ - struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf); - st_softpipe_buf->mapped = NULL; -} - - -static void -st_softpipe_buffer_destroy(struct pipe_buffer *buf) -{ - struct st_softpipe_buffer *oldBuf = st_softpipe_buffer(buf); - - if (oldBuf->data) { - if (!oldBuf->userBuffer) - align_free(oldBuf->data); - - oldBuf->data = NULL; - } - - FREE(oldBuf); -} - - -static void -st_softpipe_flush_frontbuffer(struct pipe_winsys *winsys, - struct pipe_surface *surf, - void *context_private) -{ -} - - - -static const char * -st_softpipe_get_name(struct pipe_winsys *winsys) -{ - return "softpipe"; -} - - -static struct pipe_buffer * -st_softpipe_buffer_create(struct pipe_winsys *winsys, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct st_softpipe_buffer *buffer = CALLOC_STRUCT(st_softpipe_buffer); - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.alignment = alignment; - buffer->base.usage = usage; - buffer->base.size = size; - - buffer->data = align_malloc(size, alignment); - - return &buffer->base; -} - - -/** - * Create buffer which wraps user-space data. - */ -static struct pipe_buffer * -st_softpipe_user_buffer_create(struct pipe_winsys *winsys, - void *ptr, - unsigned bytes) -{ - struct st_softpipe_buffer *buffer; - - buffer = CALLOC_STRUCT(st_softpipe_buffer); - if(!buffer) - return NULL; - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.size = bytes; - buffer->userBuffer = TRUE; - buffer->data = ptr; - - return &buffer->base; -} - - -static struct pipe_buffer * -st_softpipe_surface_buffer_create(struct pipe_winsys *winsys, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - const unsigned alignment = 64; - unsigned nblocksy; - - nblocksy = util_format_get_nblocksy(format, height); - *stride = align(util_format_get_stride(format, width), alignment); - - return winsys->buffer_create(winsys, alignment, - usage, - *stride * nblocksy); -} - - -static void -st_softpipe_fence_reference(struct pipe_winsys *winsys, - struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) -{ -} - - -static int -st_softpipe_fence_signalled(struct pipe_winsys *winsys, - struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static int -st_softpipe_fence_finish(struct pipe_winsys *winsys, - struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static void -st_softpipe_destroy(struct pipe_winsys *winsys) -{ - FREE(winsys); -} - - -struct pipe_screen * -softpipe_create_screen_malloc(void) -{ - static struct pipe_winsys *winsys; - struct pipe_screen *screen; - - winsys = CALLOC_STRUCT(pipe_winsys); - if(!winsys) - return NULL; - - winsys->destroy = st_softpipe_destroy; - - winsys->buffer_create = st_softpipe_buffer_create; - winsys->user_buffer_create = st_softpipe_user_buffer_create; - winsys->buffer_map = st_softpipe_buffer_map; - winsys->buffer_unmap = st_softpipe_buffer_unmap; - winsys->buffer_destroy = st_softpipe_buffer_destroy; - - winsys->surface_buffer_create = st_softpipe_surface_buffer_create; - - winsys->fence_reference = st_softpipe_fence_reference; - winsys->fence_signalled = st_softpipe_fence_signalled; - winsys->fence_finish = st_softpipe_fence_finish; - - winsys->flush_frontbuffer = st_softpipe_flush_frontbuffer; - winsys->get_name = st_softpipe_get_name; - - screen = softpipe_create_screen(winsys); - if(!screen) - st_softpipe_destroy(winsys); - - return screen; -} diff --git a/src/gallium/drivers/llvmpipe/lp_winsys.h b/src/gallium/include/state_tracker/sw_winsys.h index ce11fa9304..719c3f3eee 100644 --- a/src/gallium/drivers/llvmpipe/lp_winsys.h +++ b/src/gallium/include/state_tracker/sw_winsys.h @@ -27,12 +27,12 @@ /** * @file - * llvmpipe public interface. + * Software rasterizer winsys. */ -#ifndef LP_WINSYS_H -#define LP_WINSYS_H +#ifndef SW_WINSYS_H +#define SW_WINSYS_H #include "pipe/p_compiler.h" /* for boolean */ @@ -51,23 +51,23 @@ struct pipe_context; /** * Opaque pointer. */ -struct llvmpipe_displaytarget; +struct sw_displaytarget; /** - * This is the interface that llvmpipe expects any window system + * This is the interface that sw expects any window system * hosting it to implement. * - * llvmpipe is for the most part a self sufficient driver. The only thing it + * sw is for the most part a self sufficient driver. The only thing it * does not know is how to display a surface. */ -struct llvmpipe_winsys +struct sw_winsys { void - (*destroy)( struct llvmpipe_winsys *ws ); + (*destroy)( struct sw_winsys *ws ); boolean - (*is_displaytarget_format_supported)( struct llvmpipe_winsys *ws, + (*is_displaytarget_format_supported)( struct sw_winsys *ws, enum pipe_format format ); /** @@ -81,21 +81,21 @@ struct llvmpipe_winsys * with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET flag to get the underlying * storage. */ - struct llvmpipe_displaytarget * - (*displaytarget_create)( struct llvmpipe_winsys *ws, + struct sw_displaytarget * + (*displaytarget_create)( struct sw_winsys *ws, enum pipe_format format, unsigned width, unsigned height, unsigned alignment, unsigned *stride ); void * - (*displaytarget_map)( struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt, + (*displaytarget_map)( struct sw_winsys *ws, + struct sw_displaytarget *dt, unsigned flags ); void - (*displaytarget_unmap)( struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt ); + (*displaytarget_unmap)( struct sw_winsys *ws, + struct sw_displaytarget *dt ); /** * @sa pipe_screen:flush_frontbuffer. @@ -103,23 +103,19 @@ struct llvmpipe_winsys * This call will likely become asynchronous eventually. */ void - (*displaytarget_display)( struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt, + (*displaytarget_display)( struct sw_winsys *ws, + struct sw_displaytarget *dt, void *context_private ); void - (*displaytarget_destroy)( struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt ); + (*displaytarget_destroy)( struct sw_winsys *ws, + struct sw_displaytarget *dt ); }; -struct pipe_screen * -llvmpipe_create_screen( struct llvmpipe_winsys * ); - - #ifdef __cplusplus } #endif -#endif /* LP_WINSYS_H */ +#endif /* SW_WINSYS_H */ diff --git a/src/gallium/winsys/gdi/SConscript b/src/gallium/winsys/gdi/SConscript index 4cbc86f331..4b32aa27e1 100644 --- a/src/gallium/winsys/gdi/SConscript +++ b/src/gallium/winsys/gdi/SConscript @@ -18,7 +18,7 @@ if env['platform'] == 'windows': 'ws2_32', ]) - sources = [] + sources = ['gdi_sw_winsys.c'] drivers = [] if 'softpipe' in env['drivers']: diff --git a/src/gallium/winsys/gdi/gdi_llvmpipe_winsys.c b/src/gallium/winsys/gdi/gdi_llvmpipe_winsys.c index a9fa03b8e5..3d317c70dd 100644 --- a/src/gallium/winsys/gdi/gdi_llvmpipe_winsys.c +++ b/src/gallium/winsys/gdi/gdi_llvmpipe_winsys.c @@ -36,153 +36,8 @@ #include <windows.h> -#include "pipe/p_format.h" -#include "pipe/p_context.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" -#include "llvmpipe/lp_winsys.h" +#include "gdi_winsys.h" #include "llvmpipe/lp_texture.h" -#include "stw_winsys.h" - - -struct gdi_llvmpipe_displaytarget -{ - enum pipe_format format; - unsigned width; - unsigned height; - unsigned stride; - - unsigned size; - - void *data; - - BITMAPINFO bmi; -}; - - -/** Cast wrapper */ -static INLINE struct gdi_llvmpipe_displaytarget * -gdi_llvmpipe_displaytarget( struct llvmpipe_displaytarget *buf ) -{ - return (struct gdi_llvmpipe_displaytarget *)buf; -} - - -static boolean -gdi_llvmpipe_is_displaytarget_format_supported( struct llvmpipe_winsys *ws, - enum pipe_format format ) -{ - switch(format) { - case PIPE_FORMAT_B8G8R8X8_UNORM: - case PIPE_FORMAT_B8G8R8A8_UNORM: - return TRUE; - - /* TODO: Support other formats possible with BMPs, as described in - * http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx */ - - default: - return FALSE; - } -} - - -static void * -gdi_llvmpipe_displaytarget_map(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt, - unsigned flags ) -{ - struct gdi_llvmpipe_displaytarget *gdt = gdi_llvmpipe_displaytarget(dt); - - return gdt->data; -} - - -static void -gdi_llvmpipe_displaytarget_unmap(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt ) -{ - -} - - -static void -gdi_llvmpipe_displaytarget_destroy(struct llvmpipe_winsys *winsys, - struct llvmpipe_displaytarget *dt) -{ - struct gdi_llvmpipe_displaytarget *gdt = gdi_llvmpipe_displaytarget(dt); - - align_free(gdt->data); - FREE(gdt); -} - - -static struct llvmpipe_displaytarget * -gdi_llvmpipe_displaytarget_create(struct llvmpipe_winsys *winsys, - enum pipe_format format, - unsigned width, unsigned height, - unsigned alignment, - unsigned *stride) -{ - struct gdi_llvmpipe_displaytarget *gdt; - unsigned cpp; - unsigned bpp; - - gdt = CALLOC_STRUCT(gdi_llvmpipe_displaytarget); - if(!gdt) - goto no_gdt; - - gdt->format = format; - gdt->width = width; - gdt->height = height; - - bpp = util_format_get_blocksizebits(format); - cpp = util_format_get_blocksize(format); - - gdt->stride = align(width * cpp, alignment); - gdt->size = gdt->stride * height; - - gdt->data = align_malloc(gdt->size, alignment); - if(!gdt->data) - goto no_data; - - gdt->bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - gdt->bmi.bmiHeader.biWidth = gdt->stride / cpp; - gdt->bmi.bmiHeader.biHeight= -(long)height; - gdt->bmi.bmiHeader.biPlanes = 1; - gdt->bmi.bmiHeader.biBitCount = bpp; - gdt->bmi.bmiHeader.biCompression = BI_RGB; - gdt->bmi.bmiHeader.biSizeImage = 0; - gdt->bmi.bmiHeader.biXPelsPerMeter = 0; - gdt->bmi.bmiHeader.biYPelsPerMeter = 0; - gdt->bmi.bmiHeader.biClrUsed = 0; - gdt->bmi.bmiHeader.biClrImportant = 0; - - *stride = gdt->stride; - return (struct llvmpipe_displaytarget *)gdt; - -no_data: - FREE(gdt); -no_gdt: - return NULL; -} - - -static void -gdi_llvmpipe_displaytarget_display(struct llvmpipe_winsys *winsys, - struct llvmpipe_displaytarget *dt, - void *context_private) -{ - assert(0); -} - - -static void -gdi_llvmpipe_destroy(struct llvmpipe_winsys *winsys) -{ - FREE(winsys); -} static struct pipe_screen * @@ -191,18 +46,10 @@ gdi_llvmpipe_screen_create(void) static struct llvmpipe_winsys *winsys; struct pipe_screen *screen; - winsys = CALLOC_STRUCT(llvmpipe_winsys); + winsys = gdi_create_sw_winsys(); if(!winsys) goto no_winsys; - winsys->destroy = gdi_llvmpipe_destroy; - winsys->is_displaytarget_format_supported = gdi_llvmpipe_is_displaytarget_format_supported; - winsys->displaytarget_create = gdi_llvmpipe_displaytarget_create; - winsys->displaytarget_map = gdi_llvmpipe_displaytarget_map; - winsys->displaytarget_unmap = gdi_llvmpipe_displaytarget_unmap; - winsys->displaytarget_display = gdi_llvmpipe_displaytarget_display; - winsys->displaytarget_destroy = gdi_llvmpipe_displaytarget_destroy; - screen = llvmpipe_create_screen(winsys); if(!screen) goto no_screen; diff --git a/src/gallium/winsys/gdi/gdi_softpipe_winsys.c b/src/gallium/winsys/gdi/gdi_softpipe_winsys.c index 71360e55aa..56e84fd066 100644 --- a/src/gallium/winsys/gdi/gdi_softpipe_winsys.c +++ b/src/gallium/winsys/gdi/gdi_softpipe_winsys.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2008 Tungsten Graphics, Inc., Bismarck, ND., USA + * Copyright 2009 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -28,257 +28,58 @@ /** * @file - * Softpipe support. + * LLVMpipe support. * - * @author Keith Whitwell - * @author Brian Paul - * @author Jose Fonseca + * @author Jose Fonseca <jfonseca@vmware.com> */ #include <windows.h> -#include "util/u_simple_screen.h" -#include "pipe/p_format.h" -#include "pipe/p_context.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" -#include "softpipe/sp_winsys.h" +#include "gdi_winsys.h" #include "softpipe/sp_texture.h" -#include "stw_winsys.h" - - -struct gdi_softpipe_buffer -{ - struct pipe_buffer base; - boolean userBuffer; /** Is this a user-space buffer? */ - void *data; - void *mapped; -}; - - -/** Cast wrapper */ -static INLINE struct gdi_softpipe_buffer * -gdi_softpipe_buffer( struct pipe_buffer *buf ) -{ - return (struct gdi_softpipe_buffer *)buf; -} - - -static void * -gdi_softpipe_buffer_map(struct pipe_winsys *winsys, - struct pipe_buffer *buf, - unsigned flags) -{ - struct gdi_softpipe_buffer *gdi_softpipe_buf = gdi_softpipe_buffer(buf); - gdi_softpipe_buf->mapped = gdi_softpipe_buf->data; - return gdi_softpipe_buf->mapped; -} - - -static void -gdi_softpipe_buffer_unmap(struct pipe_winsys *winsys, - struct pipe_buffer *buf) -{ - struct gdi_softpipe_buffer *gdi_softpipe_buf = gdi_softpipe_buffer(buf); - gdi_softpipe_buf->mapped = NULL; -} - - -static void -gdi_softpipe_buffer_destroy(struct pipe_buffer *buf) -{ - struct gdi_softpipe_buffer *oldBuf = gdi_softpipe_buffer(buf); - - if (oldBuf->data) { - if (!oldBuf->userBuffer) - align_free(oldBuf->data); - - oldBuf->data = NULL; - } - - FREE(oldBuf); -} - - -static const char * -gdi_softpipe_get_name(struct pipe_winsys *winsys) -{ - return "softpipe"; -} - - -static struct pipe_buffer * -gdi_softpipe_buffer_create(struct pipe_winsys *winsys, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct gdi_softpipe_buffer *buffer = CALLOC_STRUCT(gdi_softpipe_buffer); - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.alignment = alignment; - buffer->base.usage = usage; - buffer->base.size = size; - - buffer->data = align_malloc(size, alignment); - - return &buffer->base; -} - - -/** - * Create buffer which wraps user-space data. - */ -static struct pipe_buffer * -gdi_softpipe_user_buffer_create(struct pipe_winsys *winsys, - void *ptr, - unsigned bytes) -{ - struct gdi_softpipe_buffer *buffer; - - buffer = CALLOC_STRUCT(gdi_softpipe_buffer); - if(!buffer) - return NULL; - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.size = bytes; - buffer->userBuffer = TRUE; - buffer->data = ptr; - - return &buffer->base; -} - - -static struct pipe_buffer * -gdi_softpipe_surface_buffer_create(struct pipe_winsys *winsys, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - const unsigned alignment = 64; - unsigned nblocksy; - - nblocksy = util_format_get_nblocksy(format, height); - *stride = align(util_format_get_stride(format, width), alignment); - - return winsys->buffer_create(winsys, alignment, - usage, - *stride * nblocksy); -} - - -static void -gdi_softpipe_dummy_flush_frontbuffer(struct pipe_winsys *winsys, - struct pipe_surface *surface, - void *context_private) -{ - assert(0); -} - - -static void -gdi_softpipe_fence_reference(struct pipe_winsys *winsys, - struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) -{ -} - - -static int -gdi_softpipe_fence_signalled(struct pipe_winsys *winsys, - struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static int -gdi_softpipe_fence_finish(struct pipe_winsys *winsys, - struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static void -gdi_softpipe_destroy(struct pipe_winsys *winsys) -{ - FREE(winsys); -} static struct pipe_screen * gdi_softpipe_screen_create(void) { - static struct pipe_winsys *winsys; + static struct softpipe_winsys *winsys; struct pipe_screen *screen; - winsys = CALLOC_STRUCT(pipe_winsys); + winsys = gdi_create_sw_winsys(); if(!winsys) - return NULL; - - winsys->destroy = gdi_softpipe_destroy; - - winsys->buffer_create = gdi_softpipe_buffer_create; - winsys->user_buffer_create = gdi_softpipe_user_buffer_create; - winsys->buffer_map = gdi_softpipe_buffer_map; - winsys->buffer_unmap = gdi_softpipe_buffer_unmap; - winsys->buffer_destroy = gdi_softpipe_buffer_destroy; - - winsys->surface_buffer_create = gdi_softpipe_surface_buffer_create; - - winsys->fence_reference = gdi_softpipe_fence_reference; - winsys->fence_signalled = gdi_softpipe_fence_signalled; - winsys->fence_finish = gdi_softpipe_fence_finish; - - winsys->flush_frontbuffer = gdi_softpipe_dummy_flush_frontbuffer; - winsys->get_name = gdi_softpipe_get_name; + goto no_winsys; screen = softpipe_create_screen(winsys); if(!screen) - gdi_softpipe_destroy(winsys); + goto no_screen; return screen; + +no_screen: + FREE(winsys); +no_winsys: + return NULL; } + + static void gdi_softpipe_present(struct pipe_screen *screen, struct pipe_surface *surface, HDC hDC) { struct softpipe_texture *texture; - struct gdi_softpipe_buffer *buffer; - BITMAPINFO bmi; + struct gdi_softpipe_displaytarget *gdt; texture = softpipe_texture(surface->texture); - - buffer = gdi_softpipe_buffer(texture->buffer); - - memset(&bmi, 0, sizeof(BITMAPINFO)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = texture->stride[surface->level] / util_format_get_blocksize(surface->format); - bmi.bmiHeader.biHeight= -(long)surface->height; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = util_format_get_blocksizebits(surface->format); - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = 0; - bmi.bmiHeader.biXPelsPerMeter = 0; - bmi.bmiHeader.biYPelsPerMeter = 0; - bmi.bmiHeader.biClrUsed = 0; - bmi.bmiHeader.biClrImportant = 0; + gdt = gdi_softpipe_displaytarget(texture->dt); StretchDIBits(hDC, - 0, 0, surface->width, surface->height, - 0, 0, surface->width, surface->height, - buffer->data, &bmi, 0, SRCCOPY); + 0, 0, gdt->width, gdt->height, + 0, 0, gdt->width, gdt->height, + gdt->data, &gdt->bmi, 0, SRCCOPY); } diff --git a/src/gallium/winsys/xlib/Makefile b/src/gallium/winsys/xlib/Makefile index 824c666ae3..129300423a 100644 --- a/src/gallium/winsys/xlib/Makefile +++ b/src/gallium/winsys/xlib/Makefile @@ -29,6 +29,7 @@ DEFINES += \ XLIB_WINSYS_SOURCES = \ xlib.c \ xlib_cell.c \ + xlib_sw_winsys.c \ xlib_llvmpipe.c \ xlib_softpipe.c diff --git a/src/gallium/winsys/xlib/SConscript b/src/gallium/winsys/xlib/SConscript index 8c9d318af2..92e508ee50 100644 --- a/src/gallium/winsys/xlib/SConscript +++ b/src/gallium/winsys/xlib/SConscript @@ -36,7 +36,7 @@ drivers = [trace] if 'softpipe' in env['drivers']: env.Append(CPPDEFINES = 'GALLIUM_SOFTPIPE') - sources += ['xlib_softpipe.c'] + sources += ['xlib_softpipe.c', 'xlib_sw_winsys.c'] drivers += [softpipe] if 'llvmpipe' in env['drivers']: @@ -44,7 +44,7 @@ if 'llvmpipe' in env['drivers']: if 'LLVM_VERSION' in env: env.Append(CPPDEFINES = 'GALLIUM_LLVMPIPE') env.Tool('udis86') - sources += ['xlib_llvmpipe.c'] + sources += ['xlib_llvmpipe.c', 'xlib_sw_winsys.c'] drivers += [llvmpipe] if 'cell' in env['drivers']: diff --git a/src/gallium/winsys/xlib/xlib.c b/src/gallium/winsys/xlib/xlib.c index 67617a470d..9b91c980d1 100644 --- a/src/gallium/winsys/xlib/xlib.c +++ b/src/gallium/winsys/xlib/xlib.c @@ -33,9 +33,7 @@ #include "xlib.h" #include "xm_winsys.h" - -#include <stdlib.h> -#include <assert.h> +#include "util/u_debug.h" /* Todo, replace all this with callback-structs provided by the * individual implementations. diff --git a/src/gallium/winsys/xlib/xlib.h b/src/gallium/winsys/xlib/xlib.h index 8e091d0c08..7f9f910b88 100644 --- a/src/gallium/winsys/xlib/xlib.h +++ b/src/gallium/winsys/xlib/xlib.h @@ -9,5 +9,12 @@ extern struct xm_driver xlib_softpipe_driver; extern struct xm_driver xlib_llvmpipe_driver; extern struct xm_driver xlib_cell_driver; +/* Internal: + */ +struct sw_winsys; +struct sw_displaytarget; +struct sw_winsys *xlib_create_sw_winsys( void ); +void xlib_sw_display(struct xmesa_buffer *xm_buffer, + struct sw_displaytarget *dt); #endif diff --git a/src/gallium/winsys/xlib/xlib_llvmpipe.c b/src/gallium/winsys/xlib/xlib_llvmpipe.c index 6cebd4c201..9929ba52e7 100644 --- a/src/gallium/winsys/xlib/xlib_llvmpipe.c +++ b/src/gallium/winsys/xlib/xlib_llvmpipe.c @@ -33,367 +33,16 @@ */ -#if defined(GALLIUM_LLVMPIPE) - -#include "xm_api.h" -#undef ASSERT -#undef Elements - -#include "util/u_simple_screen.h" -#include "pipe/p_format.h" -#include "pipe/p_context.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" -#include "llvmpipe/lp_winsys.h" -#include "llvmpipe/lp_texture.h" #include "xlib.h" -/** - * Subclass of pipe_buffer for Xlib winsys. - * Low-level OS/window system memory buffer - */ -struct xm_displaytarget -{ - enum pipe_format format; - unsigned width; - unsigned height; - unsigned stride; - - void *data; - void *mapped; - - XImage *tempImage; -#ifdef USE_XSHM - int shm; - XShmSegmentInfo shminfo; -#endif -}; - - -/** - * Subclass of llvmpipe_winsys for Xlib winsys - */ -struct xmesa_llvmpipe_winsys -{ - struct llvmpipe_winsys base; -/* struct xmesa_visual *xm_visual; */ -}; - - - -/** Cast wrapper */ -static INLINE struct xm_displaytarget * -xm_displaytarget( struct llvmpipe_displaytarget *dt ) -{ - return (struct xm_displaytarget *)dt; -} - - -/** - * X Shared Memory Image extension code - */ - -#ifdef USE_XSHM - -static volatile int mesaXErrorFlag = 0; - -/** - * Catches potential Xlib errors. - */ -static int -mesaHandleXError(Display *dpy, XErrorEvent *event) -{ - (void) dpy; - (void) event; - mesaXErrorFlag = 1; - return 0; -} - - -static char *alloc_shm(struct xm_displaytarget *buf, unsigned size) -{ - XShmSegmentInfo *const shminfo = & buf->shminfo; - - shminfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777); - if (shminfo->shmid < 0) { - return NULL; - } - - shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); - if (shminfo->shmaddr == (char *) -1) { - shmctl(shminfo->shmid, IPC_RMID, 0); - return NULL; - } - - shminfo->readOnly = False; - return shminfo->shmaddr; -} - - -/** - * Allocate a shared memory XImage back buffer for the given XMesaBuffer. - */ -static void -alloc_shm_ximage(struct xm_displaytarget *xm_buffer, - struct xmesa_buffer *xmb, - unsigned width, unsigned height) -{ - /* - * We have to do a _lot_ of error checking here to be sure we can - * really use the XSHM extension. It seems different servers trigger - * errors at different points if the extension won't work. Therefore - * we have to be very careful... - */ - int (*old_handler)(Display *, XErrorEvent *); - - xm_buffer->tempImage = XShmCreateImage(xmb->xm_visual->display, - xmb->xm_visual->visinfo->visual, - xmb->xm_visual->visinfo->depth, - ZPixmap, - NULL, - &xm_buffer->shminfo, - width, height); - if (xm_buffer->tempImage == NULL) { - xm_buffer->shm = 0; - return; - } - - - mesaXErrorFlag = 0; - old_handler = XSetErrorHandler(mesaHandleXError); - /* This may trigger the X protocol error we're ready to catch: */ - XShmAttach(xmb->xm_visual->display, &xm_buffer->shminfo); - XSync(xmb->xm_visual->display, False); - - if (mesaXErrorFlag) { - /* we are on a remote display, this error is normal, don't print it */ - XFlush(xmb->xm_visual->display); - mesaXErrorFlag = 0; - XDestroyImage(xm_buffer->tempImage); - xm_buffer->tempImage = NULL; - xm_buffer->shm = 0; - (void) XSetErrorHandler(old_handler); - return; - } - - xm_buffer->shm = 1; -} - -#endif /* USE_XSHM */ - -static boolean -xm_is_displaytarget_format_supported( struct llvmpipe_winsys *ws, - enum pipe_format format ) -{ - /* TODO: check visuals or other sensible thing here */ - return TRUE; -} - - -static void * -xm_displaytarget_map(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt, - unsigned flags) -{ - struct xm_displaytarget *xm_dt = xm_displaytarget(dt); - xm_dt->mapped = xm_dt->data; - return xm_dt->mapped; -} - -static void -xm_displaytarget_unmap(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt) -{ - struct xm_displaytarget *xm_dt = xm_displaytarget(dt); - xm_dt->mapped = NULL; -} - -static void -xm_displaytarget_destroy(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt) -{ - struct xm_displaytarget *xm_dt = xm_displaytarget(dt); - - if (xm_dt->data) { -#ifdef USE_XSHM - if (xm_dt->shminfo.shmid >= 0) { - shmdt(xm_dt->shminfo.shmaddr); - shmctl(xm_dt->shminfo.shmid, IPC_RMID, 0); - - xm_dt->shminfo.shmid = -1; - xm_dt->shminfo.shmaddr = (char *) -1; - } - else -#endif - FREE(xm_dt->data); - } - - FREE(xm_dt); -} - - -/** - * Display/copy the image in the surface into the X window specified - * by the XMesaBuffer. - */ -static void -xm_llvmpipe_display(struct xmesa_buffer *xm_buffer, - struct llvmpipe_displaytarget *dt) -{ - XImage *ximage; - struct xm_displaytarget *xm_dt = xm_displaytarget(dt); - static boolean no_swap = 0; - static boolean firsttime = 1; - - if (firsttime) { - no_swap = getenv("SP_NO_RAST") != NULL; - firsttime = 0; - } - - if (no_swap) - return; - -#ifdef USE_XSHM - if (xm_dt->shm) - { - if (xm_dt->tempImage == NULL) - { - assert(util_format_get_blockwidth(xm_dt->format) == 1); - assert(util_format_get_blockheight(xm_dt->format) == 1); - alloc_shm_ximage(xm_dt, xm_buffer, - xm_dt->stride / util_format_get_blocksize(xm_dt->format), - xm_dt->height); - } - - ximage = xm_dt->tempImage; - ximage->data = xm_dt->data; - - /* _debug_printf("XSHM\n"); */ - XShmPutImage(xm_buffer->xm_visual->display, xm_buffer->drawable, xm_buffer->gc, - ximage, 0, 0, 0, 0, xm_dt->width, xm_dt->height, False); - } - else -#endif - { - /* display image in Window */ - ximage = xm_dt->tempImage; - ximage->data = xm_dt->data; - - /* check that the XImage has been previously initialized */ - assert(ximage->format); - assert(ximage->bitmap_unit); - - /* update XImage's fields */ - ximage->width = xm_dt->width; - ximage->height = xm_dt->height; - ximage->bytes_per_line = xm_dt->stride; - - /* _debug_printf("XPUT\n"); */ - XPutImage(xm_buffer->xm_visual->display, xm_buffer->drawable, xm_buffer->gc, - ximage, 0, 0, 0, 0, xm_dt->width, xm_dt->height); - } -} - -/** - * Display/copy the image in the surface into the X window specified - * by the XMesaBuffer. - */ -static void -xm_displaytarget_display(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt, - void *context_private) -{ - XMesaContext xmctx = (XMesaContext) context_private; - struct xmesa_buffer *xm_buffer = xmctx->xm_buffer; - xm_llvmpipe_display(xm_buffer, dt); -} - -static struct llvmpipe_displaytarget * -xm_displaytarget_create(struct llvmpipe_winsys *winsys, - enum pipe_format format, - unsigned width, unsigned height, - unsigned alignment, - unsigned *stride) -{ - struct xm_displaytarget *xm_dt = CALLOC_STRUCT(xm_displaytarget); - unsigned nblocksy, size; - - xm_dt = CALLOC_STRUCT(xm_displaytarget); - if(!xm_dt) - goto no_xm_dt; - - xm_dt->format = format; - xm_dt->width = width; - xm_dt->height = height; - - nblocksy = util_format_get_nblocksy(format, height); - xm_dt->stride = align(util_format_get_stride(format, width), alignment); - size = xm_dt->stride * nblocksy; - -#ifdef USE_XSHM - if (!debug_get_bool_option("XLIB_NO_SHM", FALSE)) - { - xm_dt->shminfo.shmid = -1; - xm_dt->shminfo.shmaddr = (char *) -1; - xm_dt->shm = TRUE; - - xm_dt->data = alloc_shm(xm_dt, size); - if(!xm_dt->data) - goto no_data; - } -#endif - - if(!xm_dt->data) { - xm_dt->data = align_malloc(size, alignment); - if(!xm_dt->data) - goto no_data; - } - - *stride = xm_dt->stride; - return (struct llvmpipe_displaytarget *)xm_dt; - -no_data: - FREE(xm_dt); -no_xm_dt: - return NULL; -} - - -static void -xm_destroy( struct llvmpipe_winsys *ws ) -{ - FREE(ws); -} - - -static struct llvmpipe_winsys * -xlib_create_llvmpipe_winsys( void ) -{ - struct xmesa_llvmpipe_winsys *ws; - - ws = CALLOC_STRUCT(xmesa_llvmpipe_winsys); - if (!ws) - return NULL; - - ws->base.destroy = xm_destroy; - - ws->base.is_displaytarget_format_supported = xm_is_displaytarget_format_supported; - - ws->base.displaytarget_create = xm_displaytarget_create; - ws->base.displaytarget_map = xm_displaytarget_map; - ws->base.displaytarget_unmap = xm_displaytarget_unmap; - ws->base.displaytarget_destroy = xm_displaytarget_destroy; - - ws->base.displaytarget_display = xm_displaytarget_display; - - return &ws->base; -} +#if defined(GALLIUM_LLVMPIPE) +#include "llvmpipe/lp_texture.h" +#include "llvmpipe/lp_winsys.h" +#include "state_tracker/sw_winsys.h" static struct pipe_screen * xlib_create_llvmpipe_screen( void ) @@ -401,7 +50,7 @@ xlib_create_llvmpipe_screen( void ) struct llvmpipe_winsys *winsys; struct pipe_screen *screen; - winsys = xlib_create_llvmpipe_winsys(); + winsys = xlib_create_sw_winsys(); if (winsys == NULL) return NULL; @@ -427,7 +76,7 @@ xlib_llvmpipe_display_surface(struct xmesa_buffer *xm_buffer, assert(texture->dt); if (texture->dt) - xm_llvmpipe_display(xm_buffer, texture->dt); + xlib_sw_display(xm_buffer, texture->dt); } diff --git a/src/gallium/winsys/xlib/xlib_softpipe.c b/src/gallium/winsys/xlib/xlib_softpipe.c index 716338aef4..df93de551c 100644 --- a/src/gallium/winsys/xlib/xlib_softpipe.c +++ b/src/gallium/winsys/xlib/xlib_softpipe.c @@ -26,461 +26,19 @@ * **************************************************************************/ -/* - * Authors: - * Keith Whitwell - * Brian Paul - */ - - -#include "xm_api.h" - -#undef ASSERT -#undef Elements - -#include "util/u_simple_screen.h" -#include "pipe/p_format.h" -#include "pipe/p_context.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" -#include "softpipe/sp_winsys.h" -#include "softpipe/sp_texture.h" #include "xlib.h" - -/** - * Subclass of pipe_buffer for Xlib winsys. - * Low-level OS/window system memory buffer - */ -struct xm_buffer -{ - struct pipe_buffer base; - boolean userBuffer; /** Is this a user-space buffer? */ - void *data; - void *mapped; - - XImage *tempImage; -#ifdef USE_XSHM - boolean shm; /** Is this a shared memory buffer? */ - XShmSegmentInfo shminfo; -#endif -}; - - -/** - * Subclass of pipe_winsys for Xlib winsys - */ -struct xmesa_pipe_winsys -{ - struct pipe_winsys base; -/* struct xmesa_visual *xm_visual; */ -}; - - - -/** Cast wrapper */ -static INLINE struct xm_buffer * -xm_buffer( struct pipe_buffer *buf ) -{ - return (struct xm_buffer *)buf; -} - - -/** - * X Shared Memory Image extension code - */ - -#ifdef USE_XSHM - -static volatile int mesaXErrorFlag = 0; - -/** - * Catches potential Xlib errors. - */ -static int -mesaHandleXError(Display *dpy, XErrorEvent *event) -{ - (void) dpy; - (void) event; - mesaXErrorFlag = 1; - return 0; -} - - -static char *alloc_shm(struct xm_buffer *buf, unsigned size) -{ - XShmSegmentInfo *const shminfo = & buf->shminfo; - - shminfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777); - if (shminfo->shmid < 0) { - return NULL; - } - - shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); - if (shminfo->shmaddr == (char *) -1) { - shmctl(shminfo->shmid, IPC_RMID, 0); - return NULL; - } - - shminfo->readOnly = False; - return shminfo->shmaddr; -} - - -/** - * Allocate a shared memory XImage back buffer for the given XMesaBuffer. - */ -static void -alloc_shm_ximage(struct xm_buffer *b, struct xmesa_buffer *xmb, - unsigned width, unsigned height) -{ - /* - * We have to do a _lot_ of error checking here to be sure we can - * really use the XSHM extension. It seems different servers trigger - * errors at different points if the extension won't work. Therefore - * we have to be very careful... - */ - int (*old_handler)(Display *, XErrorEvent *); - - b->tempImage = XShmCreateImage(xmb->xm_visual->display, - xmb->xm_visual->visinfo->visual, - xmb->xm_visual->visinfo->depth, - ZPixmap, - NULL, - &b->shminfo, - width, height); - if (b->tempImage == NULL) { - b->shm = FALSE; - return; - } - - - mesaXErrorFlag = 0; - old_handler = XSetErrorHandler(mesaHandleXError); - /* This may trigger the X protocol error we're ready to catch: */ - XShmAttach(xmb->xm_visual->display, &b->shminfo); - XSync(xmb->xm_visual->display, False); - - if (mesaXErrorFlag) { - /* we are on a remote display, this error is normal, don't print it */ - XFlush(xmb->xm_visual->display); - mesaXErrorFlag = 0; - XDestroyImage(b->tempImage); - b->tempImage = NULL; - b->shm = FALSE; - (void) XSetErrorHandler(old_handler); - return; - } - - b->shm = TRUE; -} - -#endif /* USE_XSHM */ - - - -/* Most callbacks map direcly onto dri_bufmgr operations: - */ -static void * -xm_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, - unsigned flags) -{ - struct xm_buffer *xm_buf = xm_buffer(buf); - xm_buf->mapped = xm_buf->data; - return xm_buf->mapped; -} - -static void -xm_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf) -{ - struct xm_buffer *xm_buf = xm_buffer(buf); - xm_buf->mapped = NULL; -} - -static void -xm_buffer_destroy(struct pipe_buffer *buf) -{ - struct xm_buffer *oldBuf = xm_buffer(buf); - - /* - * Note oldBuf->data may point to one of three things: - * 1. XShm shared memory image data - * 2. User-provided (wrapped) memory, see xm_user_buffer_create() - * 3. Regular, malloc'd memory - * We need to be careful with freeing that data now. - */ - - if (oldBuf->data) { -#ifdef USE_XSHM - if (oldBuf->shminfo.shmid >= 0) { - shmdt(oldBuf->shminfo.shmaddr); - shmctl(oldBuf->shminfo.shmid, IPC_RMID, 0); - - oldBuf->shminfo.shmid = -1; - oldBuf->shminfo.shmaddr = (char *) -1; - } - - if (oldBuf->shm) { - oldBuf->data = NULL; - } - - if (oldBuf->tempImage) { - XDestroyImage(oldBuf->tempImage); - oldBuf->tempImage = NULL; - } -#endif - - if (oldBuf->data && !oldBuf->userBuffer) { - /* this was regular malloc'd memory */ - align_free(oldBuf->data); - } - - oldBuf->data = NULL; - } - - free(oldBuf); -} - - -/** - * Display/copy the image in the surface into the X window specified - * by the XMesaBuffer. - */ -static void -xlib_softpipe_display_surface(struct xmesa_buffer *b, - struct pipe_surface *surf) -{ - XImage *ximage; - struct softpipe_texture *spt = softpipe_texture(surf->texture); - struct xm_buffer *xm_buf = xm_buffer(spt->buffer); - static boolean no_swap = 0; - static boolean firsttime = 1; - - if (firsttime) { - no_swap = getenv("SP_NO_RAST") != NULL; - firsttime = 0; - } - - if (no_swap) - return; - -#ifdef USE_XSHM - if (xm_buf->shm) - { - if (xm_buf->tempImage == NULL) - { - assert(util_format_get_blockwidth(surf->texture->format) == 1); - assert(util_format_get_blockheight(surf->texture->format) == 1); - alloc_shm_ximage(xm_buf, b, spt->stride[surf->level] / - util_format_get_blocksize(surf->texture->format), surf->height); - } - - ximage = xm_buf->tempImage; - ximage->data = xm_buf->data; - - /* _debug_printf("XSHM\n"); */ - XShmPutImage(b->xm_visual->display, b->drawable, b->gc, - ximage, 0, 0, 0, 0, surf->width, surf->height, False); - } - else -#endif - { - /* display image in Window */ - ximage = b->tempImage; - ximage->data = xm_buf->data; - - /* check that the XImage has been previously initialized */ - assert(ximage->format); - assert(ximage->bitmap_unit); - - /* update XImage's fields */ - ximage->width = surf->width; - ximage->height = surf->height; - ximage->bytes_per_line = spt->stride[surf->level]; - - /* _debug_printf("XPUT\n"); */ - XPutImage(b->xm_visual->display, b->drawable, b->gc, - ximage, 0, 0, 0, 0, surf->width, surf->height); - } -} - - -static void -xm_flush_frontbuffer(struct pipe_winsys *pws, - struct pipe_surface *surf, - void *context_private) -{ - /* - * The front color buffer is actually just another XImage buffer. - * This function copies that XImage to the actual X Window. - */ - XMesaContext xmctx = (XMesaContext) context_private; - xlib_softpipe_display_surface(xmctx->xm_buffer, surf); - xmesa_check_and_update_buffer_size(xmctx, xmctx->xm_buffer); -} - - - -static const char * -xm_get_name(struct pipe_winsys *pws) -{ - return "Xlib"; -} - - -static struct pipe_buffer * -xm_buffer_create(struct pipe_winsys *pws, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer); - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.alignment = alignment; - buffer->base.usage = usage; - buffer->base.size = size; - - /* align to 16-byte multiple for Cell */ - buffer->data = align_malloc(size, max(alignment, 16)); - - return &buffer->base; -} - - -/** - * Create buffer which wraps user-space data. - */ -static struct pipe_buffer * -xm_user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes) -{ - struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer); - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.size = bytes; - buffer->userBuffer = TRUE; - buffer->data = ptr; - - return &buffer->base; -} - - -static struct pipe_buffer * -xm_surface_buffer_create(struct pipe_winsys *winsys, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - const unsigned alignment = 64; - unsigned nblocksy, size; - - nblocksy = util_format_get_nblocksy(format, height); - *stride = align(util_format_get_stride(format, width), alignment); - size = *stride * nblocksy; - -#ifdef USE_XSHM - if (!debug_get_bool_option("XLIB_NO_SHM", FALSE)) - { - struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer); - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.alignment = alignment; - buffer->base.usage = usage; - buffer->base.size = size; - buffer->userBuffer = FALSE; - buffer->shminfo.shmid = -1; - buffer->shminfo.shmaddr = (char *) -1; - buffer->shm = TRUE; - - buffer->data = alloc_shm(buffer, size); - if (!buffer->data) - goto out; - - return &buffer->base; - - out: - if (buffer) - FREE(buffer); - } -#endif - - - return winsys->buffer_create(winsys, alignment, - usage, - size); -} - - -/* - * Fence functions - basically nothing to do, as we don't create any actual - * fence objects. - */ - -static void -xm_fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) -{ -} - - -static int -xm_fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static int -xm_fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - - -static struct pipe_winsys * -xlib_create_softpipe_winsys( void ) -{ - static struct xmesa_pipe_winsys *ws = NULL; - - if (!ws) { - ws = CALLOC_STRUCT(xmesa_pipe_winsys); - - /* Fill in this struct with callbacks that pipe will need to - * communicate with the window system, buffer manager, etc. - */ - ws->base.buffer_create = xm_buffer_create; - ws->base.user_buffer_create = xm_user_buffer_create; - ws->base.buffer_map = xm_buffer_map; - ws->base.buffer_unmap = xm_buffer_unmap; - ws->base.buffer_destroy = xm_buffer_destroy; - - ws->base.surface_buffer_create = xm_surface_buffer_create; - - ws->base.fence_reference = xm_fence_reference; - ws->base.fence_signalled = xm_fence_signalled; - ws->base.fence_finish = xm_fence_finish; - - ws->base.flush_frontbuffer = xm_flush_frontbuffer; - ws->base.get_name = xm_get_name; - } - - return &ws->base; -} - +#include "softpipe/sp_texture.h" +#include "softpipe/sp_screen.h" +#include "state_tracker/sw_winsys.h" static struct pipe_screen * xlib_create_softpipe_screen( void ) { - struct pipe_winsys *winsys; + struct sw_winsys *winsys; struct pipe_screen *screen; - winsys = xlib_create_softpipe_winsys(); + winsys = xlib_create_sw_winsys(); if (winsys == NULL) return NULL; @@ -498,6 +56,18 @@ fail: } +static void +xlib_softpipe_display_surface(struct xmesa_buffer *xm_buffer, + struct pipe_surface *surf) +{ + struct softpipe_texture *texture = softpipe_texture(surf->texture); + + assert(texture->dt); + if (texture->dt) + xlib_sw_display(xm_buffer, texture->dt); +} + + struct xm_driver xlib_softpipe_driver = { .create_pipe_screen = xlib_create_softpipe_screen, diff --git a/src/gallium/winsys/xlib/xlib_sw_winsys.c b/src/gallium/winsys/xlib/xlib_sw_winsys.c new file mode 100644 index 0000000000..e4b02ba093 --- /dev/null +++ b/src/gallium/winsys/xlib/xlib_sw_winsys.c @@ -0,0 +1,394 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA + * 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 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 + * THE COPYRIGHT HOLDERS, AUTHORS 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. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ + +/* + * Authors: + * Keith Whitwell + * Brian Paul + */ + + + +#include "xm_api.h" + +#undef ASSERT +#undef Elements + +#include "pipe/p_format.h" +#include "pipe/p_context.h" +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "util/u_math.h" +#include "util/u_memory.h" + +#include "state_tracker/sw_winsys.h" + +#include "xlib.h" + +/** + * Subclass of pipe_buffer for Xlib winsys. + * Low-level OS/window system memory buffer + */ +struct xm_displaytarget +{ + enum pipe_format format; + unsigned width; + unsigned height; + unsigned stride; + + void *data; + void *mapped; + + XImage *tempImage; +#ifdef USE_XSHM + int shm; + XShmSegmentInfo shminfo; +#endif +}; + + +/** + * Subclass of sw_winsys for Xlib winsys + */ +struct xmesa_sw_winsys +{ + struct sw_winsys base; +/* struct xmesa_visual *xm_visual; */ +}; + + + +/** Cast wrapper */ +static INLINE struct xm_displaytarget * +xm_displaytarget( struct sw_displaytarget *dt ) +{ + return (struct xm_displaytarget *)dt; +} + + +/** + * X Shared Memory Image extension code + */ + +#ifdef USE_XSHM + +static volatile int mesaXErrorFlag = 0; + +/** + * Catches potential Xlib errors. + */ +static int +mesaHandleXError(Display *dpy, XErrorEvent *event) +{ + (void) dpy; + (void) event; + mesaXErrorFlag = 1; + return 0; +} + + +static char *alloc_shm(struct xm_displaytarget *buf, unsigned size) +{ + XShmSegmentInfo *const shminfo = & buf->shminfo; + + shminfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777); + if (shminfo->shmid < 0) { + return NULL; + } + + shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); + if (shminfo->shmaddr == (char *) -1) { + shmctl(shminfo->shmid, IPC_RMID, 0); + return NULL; + } + + shminfo->readOnly = False; + return shminfo->shmaddr; +} + + +/** + * Allocate a shared memory XImage back buffer for the given XMesaBuffer. + */ +static void +alloc_shm_ximage(struct xm_displaytarget *xm_buffer, + struct xmesa_buffer *xmb, + unsigned width, unsigned height) +{ + /* + * We have to do a _lot_ of error checking here to be sure we can + * really use the XSHM extension. It seems different servers trigger + * errors at different points if the extension won't work. Therefore + * we have to be very careful... + */ + int (*old_handler)(Display *, XErrorEvent *); + + xm_buffer->tempImage = XShmCreateImage(xmb->xm_visual->display, + xmb->xm_visual->visinfo->visual, + xmb->xm_visual->visinfo->depth, + ZPixmap, + NULL, + &xm_buffer->shminfo, + width, height); + if (xm_buffer->tempImage == NULL) { + xm_buffer->shm = 0; + return; + } + + + mesaXErrorFlag = 0; + old_handler = XSetErrorHandler(mesaHandleXError); + /* This may trigger the X protocol error we're ready to catch: */ + XShmAttach(xmb->xm_visual->display, &xm_buffer->shminfo); + XSync(xmb->xm_visual->display, False); + + if (mesaXErrorFlag) { + /* we are on a remote display, this error is normal, don't print it */ + XFlush(xmb->xm_visual->display); + mesaXErrorFlag = 0; + XDestroyImage(xm_buffer->tempImage); + xm_buffer->tempImage = NULL; + xm_buffer->shm = 0; + (void) XSetErrorHandler(old_handler); + return; + } + + xm_buffer->shm = 1; +} + +#endif /* USE_XSHM */ + +static boolean +xm_is_displaytarget_format_supported( struct sw_winsys *ws, + enum pipe_format format ) +{ + /* TODO: check visuals or other sensible thing here */ + return TRUE; +} + + +static void * +xm_displaytarget_map(struct sw_winsys *ws, + struct sw_displaytarget *dt, + unsigned flags) +{ + struct xm_displaytarget *xm_dt = xm_displaytarget(dt); + xm_dt->mapped = xm_dt->data; + return xm_dt->mapped; +} + +static void +xm_displaytarget_unmap(struct sw_winsys *ws, + struct sw_displaytarget *dt) +{ + struct xm_displaytarget *xm_dt = xm_displaytarget(dt); + xm_dt->mapped = NULL; +} + +static void +xm_displaytarget_destroy(struct sw_winsys *ws, + struct sw_displaytarget *dt) +{ + struct xm_displaytarget *xm_dt = xm_displaytarget(dt); + + if (xm_dt->data) { +#ifdef USE_XSHM + if (xm_dt->shminfo.shmid >= 0) { + shmdt(xm_dt->shminfo.shmaddr); + shmctl(xm_dt->shminfo.shmid, IPC_RMID, 0); + + xm_dt->shminfo.shmid = -1; + xm_dt->shminfo.shmaddr = (char *) -1; + } + else +#endif + FREE(xm_dt->data); + } + + FREE(xm_dt); +} + + +/** + * Display/copy the image in the surface into the X window specified + * by the XMesaBuffer. + */ +void +xlib_sw_display(struct xmesa_buffer *xm_buffer, + struct sw_displaytarget *dt) +{ + XImage *ximage; + struct xm_displaytarget *xm_dt = xm_displaytarget(dt); + static boolean no_swap = 0; + static boolean firsttime = 1; + + if (firsttime) { + no_swap = getenv("SP_NO_RAST") != NULL; + firsttime = 0; + } + + if (no_swap) + return; + +#ifdef USE_XSHM + if (xm_dt->shm) + { + if (xm_dt->tempImage == NULL) + { + assert(util_format_get_blockwidth(xm_dt->format) == 1); + assert(util_format_get_blockheight(xm_dt->format) == 1); + alloc_shm_ximage(xm_dt, xm_buffer, + xm_dt->stride / util_format_get_blocksize(xm_dt->format), + xm_dt->height); + } + + ximage = xm_dt->tempImage; + ximage->data = xm_dt->data; + + /* _debug_printf("XSHM\n"); */ + XShmPutImage(xm_buffer->xm_visual->display, xm_buffer->drawable, xm_buffer->gc, + ximage, 0, 0, 0, 0, xm_dt->width, xm_dt->height, False); + } + else +#endif + { + /* display image in Window */ + ximage = xm_dt->tempImage; + ximage->data = xm_dt->data; + + /* check that the XImage has been previously initialized */ + assert(ximage->format); + assert(ximage->bitmap_unit); + + /* update XImage's fields */ + ximage->width = xm_dt->width; + ximage->height = xm_dt->height; + ximage->bytes_per_line = xm_dt->stride; + + /* _debug_printf("XPUT\n"); */ + XPutImage(xm_buffer->xm_visual->display, xm_buffer->drawable, xm_buffer->gc, + ximage, 0, 0, 0, 0, xm_dt->width, xm_dt->height); + } +} + +/** + * Display/copy the image in the surface into the X window specified + * by the XMesaBuffer. + */ +static void +xm_displaytarget_display(struct sw_winsys *ws, + struct sw_displaytarget *dt, + void *context_private) +{ + XMesaContext xmctx = (XMesaContext) context_private; + struct xmesa_buffer *xm_buffer = xmctx->xm_buffer; + xm_sw_display(xm_buffer, dt); +} + + +static struct sw_displaytarget * +xm_displaytarget_create(struct sw_winsys *winsys, + enum pipe_format format, + unsigned width, unsigned height, + unsigned alignment, + unsigned *stride) +{ + struct xm_displaytarget *xm_dt = CALLOC_STRUCT(xm_displaytarget); + unsigned nblocksy, size; + + xm_dt = CALLOC_STRUCT(xm_displaytarget); + if(!xm_dt) + goto no_xm_dt; + + xm_dt->format = format; + xm_dt->width = width; + xm_dt->height = height; + + nblocksy = util_format_get_nblocksy(format, height); + xm_dt->stride = align(util_format_get_stride(format, width), alignment); + size = xm_dt->stride * nblocksy; + +#ifdef USE_XSHM + if (!debug_get_bool_option("XLIB_NO_SHM", FALSE)) + { + xm_dt->shminfo.shmid = -1; + xm_dt->shminfo.shmaddr = (char *) -1; + xm_dt->shm = TRUE; + + xm_dt->data = alloc_shm(xm_dt, size); + if(!xm_dt->data) + goto no_data; + } +#endif + + if(!xm_dt->data) { + xm_dt->data = align_malloc(size, alignment); + if(!xm_dt->data) + goto no_data; + } + + *stride = xm_dt->stride; + return (struct sw_displaytarget *)xm_dt; + +no_data: + FREE(xm_dt); +no_xm_dt: + return NULL; +} + + +static void +xm_destroy( struct sw_winsys *ws ) +{ + FREE(ws); +} + + +struct sw_winsys * +xlib_create_sw_winsys( void ) +{ + struct xmesa_sw_winsys *ws; + + ws = CALLOC_STRUCT(xmesa_sw_winsys); + if (!ws) + return NULL; + + ws->base.destroy = xm_destroy; + + ws->base.is_displaytarget_format_supported = xm_is_displaytarget_format_supported; + + ws->base.displaytarget_create = xm_displaytarget_create; + ws->base.displaytarget_map = xm_displaytarget_map; + ws->base.displaytarget_unmap = xm_displaytarget_unmap; + ws->base.displaytarget_destroy = xm_displaytarget_destroy; + + ws->base.displaytarget_display = xm_displaytarget_display; + + return &ws->base; +} + |