From: Keith Whitwell Date: Sun, 5 Aug 2007 16:23:38 +0000 (+0100) Subject: Add a new interface between softpipe and the window system / buffer manager. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1d1b9e6be45e75ad12a01c82e3c0d55ff9da4183;p=mesa.git Add a new interface between softpipe and the window system / buffer manager. This interface is defined by softpipe and any window system (eg i915pipe) wishing to use softpipe is required to implement the interface. Currently the interface is all about buffer management. Generalizing, each pipe driver will advertise an interface in a similar spirit to this, and again any window system driver wishing to use that rendering pipeline will have to implement the interface it defines. It clearly isn't a one-way street however, as softpipe could just do its own buffer management with malloc. The interaction with a buffer manager is desired to allow us to exercise the hardware swapbuffers functionality of the i915pipe driver, and also to get a feel for the way hardware drivers which really need a buffer manager will work. --- diff --git a/src/mesa/drivers/dri/i915pipe/Makefile b/src/mesa/drivers/dri/i915pipe/Makefile index 617b2c7bce7..4e8d0201962 100644 --- a/src/mesa/drivers/dri/i915pipe/Makefile +++ b/src/mesa/drivers/dri/i915pipe/Makefile @@ -10,7 +10,7 @@ PIPE_DRIVERS = \ $(TOP)/src/mesa/pipe/softpipe/libsoftpipe.a DRIVER_SOURCES = \ - intel_regions.c \ + intel_softpipe.c \ intel_buffer_objects.c \ intel_batchbuffer.c \ intel_mipmap_tree.c \ diff --git a/src/mesa/drivers/dri/i915pipe/intel_context.c b/src/mesa/drivers/dri/i915pipe/intel_context.c index ac04d4e8c22..d43b7841120 100644 --- a/src/mesa/drivers/dri/i915pipe/intel_context.c +++ b/src/mesa/drivers/dri/i915pipe/intel_context.c @@ -54,11 +54,9 @@ #include "intel_buffer_objects.h" #include "intel_fbo.h" -#include "pipe/softpipe/sp_context.h" #include "state_tracker/st_public.h" #include "state_tracker/st_context.h" - #include "drirenderbuffer.h" #include "vblank.h" #include "utils.h" @@ -366,7 +364,7 @@ intelCreateContext(const __GLcontextModes * mesaVis, * Pipe-related setup */ st_create_context( &intel->ctx, - softpipe_create() ); + intel_create_softpipe( intel ) ); /* KW: Not sure I like this - we should only be talking to the * state_tracker. The pipe code will need some way of talking to @@ -375,9 +373,9 @@ intelCreateContext(const __GLcontextModes * mesaVis, * BP: Yes, a temporary hack so we can make jumps between old/new code. */ intel->pipe = intel->ctx.st->pipe; - intel->pipe->screen = intelScreen; - intel->pipe->glctx = ctx; - intel_init_region_functions(intel->pipe); +// intel->pipe->screen = intelScreen; +// intel->pipe->glctx = ctx; +// intel_init_region_functions(intel->pipe); /* * memory pools diff --git a/src/mesa/drivers/dri/i915pipe/intel_context.h b/src/mesa/drivers/dri/i915pipe/intel_context.h index 6c728dfe735..ad55e7eef24 100644 --- a/src/mesa/drivers/dri/i915pipe/intel_context.h +++ b/src/mesa/drivers/dri/i915pipe/intel_context.h @@ -196,6 +196,13 @@ extern void intelFlush(GLcontext * ctx); extern void intelInitDriverFunctions(struct dd_function_table *functions); +/* ================================================================ + * intel_softpipe.c: + */ + +struct pipe_context * +intel_create_softpipe( struct intel_context *intel ); + #define MI_BATCH_BUFFER_END (0xA<<23) diff --git a/src/mesa/drivers/dri/i915pipe/intel_regions.c b/src/mesa/drivers/dri/i915pipe/intel_regions.c deleted file mode 100644 index 75ba1f9cdb0..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_regions.c +++ /dev/null @@ -1,298 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 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. - * - **************************************************************************/ - -/* Provide additional functionality on top of bufmgr buffers: - * - 2d semantics and blit operations - * - refcounting of buffers for multiple images in a buffer. - * - refcounting of buffer mappings. - * - some logic for moving the buffers to the best memory pools for - * given operations. - * - * Most of this is to make it easier to implement the fixed-layout - * mipmap tree required by intel hardware in the face of GL's - * programming interface where each image can be specifed in random - * order and it isn't clear what layout the tree should have until the - * last moment. - */ - -#include "pipe/p_state.h" -#include "pipe/p_context.h" - -#include "intel_context.h" -#include "intel_blit.h" -#include "intel_buffer_objects.h" -#include "dri_bufmgr.h" -#include "intel_batchbuffer.h" - - -#define FILE_DEBUG_FLAG DEBUG_REGION - - -/** XXX temporary helper */ -static intelScreenPrivate * -pipe_screen(struct pipe_context *pipe) -{ - return (intelScreenPrivate *) pipe->screen; -} - - -static void -intel_region_idle(struct pipe_context *pipe, struct pipe_region *region) -{ - DBG("%s\n", __FUNCTION__); - if (region && region->buffer) - driBOWaitIdle(region->buffer, GL_FALSE); -} - -/* XXX: Thread safety? - */ -static GLubyte * -intel_region_map(struct pipe_context *pipe, struct pipe_region *region) -{ - DBG("%s\n", __FUNCTION__); - if (!region->map_refcount++) { - region->map = driBOMap(region->buffer, - DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0); - } - - return region->map; -} - -static void -intel_region_unmap(struct pipe_context *pipe, struct pipe_region *region) -{ - DBG("%s\n", __FUNCTION__); - if (!--region->map_refcount) { - driBOUnmap(region->buffer); - region->map = NULL; - } -} - -static struct pipe_region * -intel_region_alloc(struct pipe_context *pipe, - GLuint cpp, GLuint pitch, GLuint height) -{ - intelScreenPrivate *intelScreen = pipe_screen(pipe); - struct pipe_region *region = calloc(sizeof(*region), 1); - struct intel_context *intel = intelScreenContext(intelScreen); - - DBG("%s\n", __FUNCTION__); - - region->cpp = cpp; - region->pitch = pitch; - region->height = height; /* needed? */ - region->refcount = 1; - - driGenBuffers(intelScreen->regionPool, - "region", 1, ®ion->buffer, 64, - 0, - 0); - - LOCK_HARDWARE(intel); - driBOData(region->buffer, pitch * cpp * height, NULL, 0); - UNLOCK_HARDWARE(intel); - return region; -} - -static void -intel_region_release(struct pipe_context *pipe, struct pipe_region **region) -{ - if (!*region) - return; - - DBG("%s %d\n", __FUNCTION__, (*region)->refcount - 1); - - ASSERT((*region)->refcount > 0); - (*region)->refcount--; - - if ((*region)->refcount == 0) { - assert((*region)->map_refcount == 0); - - driBOUnReference((*region)->buffer); - free(*region); - } - *region = NULL; -} - - - - - - - -/* - * XXX Move this into core Mesa? - */ -static void -_mesa_copy_rect(GLubyte * dst, - GLuint cpp, - GLuint dst_pitch, - GLuint dst_x, - GLuint dst_y, - GLuint width, - GLuint height, - const GLubyte * src, - GLuint src_pitch, GLuint src_x, GLuint src_y) -{ - GLuint i; - - dst_pitch *= cpp; - src_pitch *= cpp; - dst += dst_x * cpp; - src += src_x * cpp; - dst += dst_y * dst_pitch; - src += src_y * dst_pitch; - width *= cpp; - - if (width == dst_pitch && width == src_pitch) - memcpy(dst, src, height * width); - else { - for (i = 0; i < height; i++) { - memcpy(dst, src, width); - dst += dst_pitch; - src += src_pitch; - } - } -} - - -/* Upload data to a rectangular sub-region. Lots of choices how to do this: - * - * - memcpy by span to current destination - * - upload data as new buffer and blit - * - * Currently always memcpy. - */ -static void -intel_region_data(struct pipe_context *pipe, - struct pipe_region *dst, - GLuint dst_offset, - GLuint dstx, GLuint dsty, - const void *src, GLuint src_pitch, - GLuint srcx, GLuint srcy, GLuint width, GLuint height) -{ - intelScreenPrivate *intelScreen = pipe_screen(pipe); - struct intel_context *intel = intelScreenContext(intelScreen); - - DBG("%s\n", __FUNCTION__); - - if (intel == NULL) - return; - - LOCK_HARDWARE(intel); - - _mesa_copy_rect(pipe->region_map(pipe, dst) + dst_offset, - dst->cpp, - dst->pitch, - dstx, dsty, width, height, src, src_pitch, srcx, srcy); - - pipe->region_unmap(pipe, dst); - - UNLOCK_HARDWARE(intel); - -} - -/* Copy rectangular sub-regions. Need better logic about when to - * push buffers into AGP - will currently do so whenever possible. - */ -static void -intel_region_copy(struct pipe_context *pipe, - struct pipe_region *dst, - GLuint dst_offset, - GLuint dstx, GLuint dsty, - const struct pipe_region *src, - GLuint src_offset, - GLuint srcx, GLuint srcy, GLuint width, GLuint height) -{ - intelScreenPrivate *intelScreen = pipe_screen(pipe); - struct intel_context *intel = intelScreenContext(intelScreen); - - DBG("%s\n", __FUNCTION__); - - if (intel == NULL) - return; - - assert(src->cpp == dst->cpp); - - intelEmitCopyBlit(intel, - dst->cpp, - src->pitch, src->buffer, src_offset, - dst->pitch, dst->buffer, dst_offset, - srcx, srcy, dstx, dsty, width, height, - GL_COPY); -} - -/* Fill a rectangular sub-region. Need better logic about when to - * push buffers into AGP - will currently do so whenever possible. - */ -static void -intel_region_fill(struct pipe_context *pipe, - struct pipe_region *dst, - GLuint dst_offset, - GLuint dstx, GLuint dsty, - GLuint width, GLuint height, - GLuint value, GLuint mask) -{ - intelScreenPrivate *intelScreen = pipe_screen(pipe); - struct intel_context *intel = intelScreenContext(intelScreen); - - DBG("%s\n", __FUNCTION__); - - if (intel == NULL) - return; - - intelEmitFillBlit(intel, - dst->cpp, - dst->pitch, dst->buffer, dst_offset, - dstx, dsty, width, height, value, mask); -} - - - -static struct _DriBufferObject * -intel_region_buffer(struct pipe_context *pipe, - struct pipe_region *region, GLuint flag) -{ - return region->buffer; -} - - - -void -intel_init_region_functions(struct pipe_context *pipe) -{ - pipe->region_idle = intel_region_idle; - pipe->region_map = intel_region_map; - pipe->region_unmap = intel_region_unmap; - pipe->region_alloc = intel_region_alloc; - pipe->region_release = intel_region_release; - pipe->region_data = intel_region_data; - pipe->region_copy = intel_region_copy; - pipe->region_fill = intel_region_fill; - pipe->region_buffer = intel_region_buffer; -} - diff --git a/src/mesa/drivers/dri/i915pipe/intel_regions.h b/src/mesa/drivers/dri/i915pipe/intel_regions.h deleted file mode 100644 index 2a3b5b4025c..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_regions.h +++ /dev/null @@ -1,36 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 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 INTEL_REGIONS_H -#define INTEL_REGIONS_H - -#include "mtypes.h" -#include "intel_screen.h" - - - -#endif diff --git a/src/mesa/drivers/dri/i915pipe/intel_softpipe.c b/src/mesa/drivers/dri/i915pipe/intel_softpipe.c new file mode 100644 index 00000000000..4591730a02e --- /dev/null +++ b/src/mesa/drivers/dri/i915pipe/intel_softpipe.c @@ -0,0 +1,182 @@ +/************************************************************************** + * + * Copyright 2006 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 + */ + +#include +#include +#include "dri_bufpool.h" +#include "dri_bufmgr.h" + +/* #include "errno.h" */ +/* #include "string.h" */ +/* #include "imports.h" */ + +#include "intel_context.h" + +#include "pipe/softpipe/sp_winsys.h" + + +struct intel_softpipe_winsys { + struct softpipe_winsys sws; + struct intel_context *intel; +}; + + + +/* Turn the softpipe opaque buffer pointer into a dri_bufmgr opaque + * buffer pointer... + */ +static inline struct _DriBufferObject * +dri_bo( struct softpipe_buffer_handle *bo ) +{ + return (struct _DriBufferObject *)bo; +} + +static inline struct softpipe_buffer_handle * +pipe_bo( struct _DriBufferObject *bo ) +{ + return (struct softpipe_buffer_handle *)bo; +} + +/* Turn a softpipe winsys into an intel/softpipe winsys: + */ +static inline struct intel_softpipe_winsys * +intel_softpipe_winsys( struct softpipe_winsys *sws ) +{ + return (struct intel_softpipe_winsys *)sws; +} + + +/* Most callbacks map direcly onto dri_bufmgr operations: + */ +static void *intel_buffer_map(struct softpipe_winsys *sws, + struct softpipe_buffer_handle *buf ) +{ + return driBOMap( dri_bo(buf), + DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0 ); +} + +static void intel_buffer_unmap(struct softpipe_winsys *sws, + struct softpipe_buffer_handle *buf) +{ + driBOUnmap( dri_bo(buf) ); +} + + +static struct softpipe_buffer_handle * +intel_buffer_reference(struct softpipe_winsys *sws, + struct softpipe_buffer_handle *buf) +{ + return pipe_bo( driBOReference( dri_bo(buf) ) ); +} + +static void intel_buffer_unreference(struct softpipe_winsys *sws, + struct softpipe_buffer_handle *buf) +{ + driBOUnReference( dri_bo(buf) ); +} + +/* Grabs the hardware lock! + */ +static void intel_buffer_data(struct softpipe_winsys *sws, + struct softpipe_buffer_handle *buf, + unsigned size, const void *data ) +{ + struct intel_context *intel = intel_softpipe_winsys(sws)->intel; + + LOCK_HARDWARE( intel ); + driBOData( dri_bo(buf), size, data, 0 ); + UNLOCK_HARDWARE( intel ); +} + +static void intel_buffer_subdata(struct softpipe_winsys *sws, + struct softpipe_buffer_handle *buf, + unsigned long offset, + unsigned long size, + const void *data) +{ + driBOSubData( dri_bo(buf), offset, size, data ); +} + +static void intel_buffer_get_subdata(struct softpipe_winsys *sws, + struct softpipe_buffer_handle *buf, + unsigned long offset, + unsigned long size, + void *data) +{ + driBOGetSubData( dri_bo(buf), offset, size, data ); +} + +/* Softpipe has no concept of pools. We choose the tex/region pool + * for all buffers. + */ +static struct softpipe_buffer_handle * +intel_create_buffer(struct softpipe_winsys *sws, + const char *name, + unsigned alignment) +{ + struct intel_context *intel = intel_softpipe_winsys(sws)->intel; + struct _DriBufferObject *buffer; + + LOCK_HARDWARE( intel ); + driGenBuffers( intel->intelScreen->regionPool, + name, 1, &buffer, alignment, 0, 0 ); + UNLOCK_HARDWARE( intel ); + + return pipe_bo(buffer); +} + + +struct pipe_context * +intel_create_softpipe( struct intel_context *intel ) +{ + struct intel_softpipe_winsys *isws = CALLOC_STRUCT( intel_softpipe_winsys ); + + /* Fill in this struct with callbacks that softpipe will need to + * communicate with the window system, buffer manager, etc. + * + * Softpipe would be happy with a malloc based memory manager, but + * the SwapBuffers implementation in this winsys driver requires + * that rendering be done to an appropriate _DriBufferObject. + */ + isws->sws.create_buffer = intel_create_buffer; + isws->sws.buffer_map = intel_buffer_map; + isws->sws.buffer_unmap = intel_buffer_unmap; + isws->sws.buffer_reference = intel_buffer_reference; + isws->sws.buffer_unreference = intel_buffer_unreference; + isws->sws.buffer_data = intel_buffer_data; + isws->sws.buffer_subdata = intel_buffer_subdata; + isws->sws.buffer_get_subdata = intel_buffer_get_subdata; + isws->intel = intel; + + /* Create the softpipe context: + */ + return softpipe_create( &isws->sws ); +} diff --git a/src/mesa/pipe/p_context.h b/src/mesa/pipe/p_context.h index ac6567f009b..92670c77337 100644 --- a/src/mesa/pipe/p_context.h +++ b/src/mesa/pipe/p_context.h @@ -32,10 +32,6 @@ #include "p_state.h" -/* Kludge: - */ -extern struct pipe_context *softpipe_create( void ); - /* Drawing currently kludged up via the existing tnl/ module. */ struct vertex_buffer; @@ -161,7 +157,8 @@ struct pipe_context { struct pipe_region *dest, GLuint dest_offset, GLuint destx, GLuint desty, - const struct pipe_region *src, + struct pipe_region *src, /* don't make this const - + need to map/unmap */ GLuint src_offset, GLuint srcx, GLuint srcy, GLuint width, GLuint height); @@ -170,14 +167,11 @@ struct pipe_context { GLuint dst_offset, GLuint dstx, GLuint dsty, GLuint width, GLuint height, - GLuint value, GLuint mask); + GLuint value); struct _DriBufferObject *(*region_buffer)(struct pipe_context *pipe, struct pipe_region *region, GLuint flag); - - void *screen; /**< temporary */ - void *glctx; /**< temporary */ }; diff --git a/src/mesa/pipe/p_state.h b/src/mesa/pipe/p_state.h index 699efd5877a..3be1010007a 100644 --- a/src/mesa/pipe/p_state.h +++ b/src/mesa/pipe/p_state.h @@ -235,12 +235,9 @@ struct pipe_sampler_state *** Resource Objects ***/ - -struct _DriBufferObject; - struct pipe_region { - struct _DriBufferObject *buffer; /**< buffer manager's buffer ID */ + void *buffer; /**< driver private buffer handle */ GLuint refcount; /**< Reference count for region */ GLuint cpp; /**< bytes per pixel */ diff --git a/src/mesa/pipe/softpipe/sp_clear.c b/src/mesa/pipe/softpipe/sp_clear.c index d7684d20445..2d69b6e0dca 100644 --- a/src/mesa/pipe/softpipe/sp_clear.c +++ b/src/mesa/pipe/softpipe/sp_clear.c @@ -56,5 +56,5 @@ softpipe_clear(struct pipe_context *pipe, struct pipe_surface *ps, w = softpipe->framebuffer.cbufs[0]->width; h = softpipe->framebuffer.cbufs[0]->height; - pipe->region_fill(pipe, ps->region, 0, x, y, w, h, clearValue, ~0); + pipe->region_fill(pipe, ps->region, 0, x, y, w, h, clearValue); } diff --git a/src/mesa/pipe/softpipe/sp_context.c b/src/mesa/pipe/softpipe/sp_context.c index fe7f2f351a4..22928f7bd64 100644 --- a/src/mesa/pipe/softpipe/sp_context.c +++ b/src/mesa/pipe/softpipe/sp_context.c @@ -39,6 +39,7 @@ #include "sp_state.h" #include "sp_surface.h" #include "sp_prim_setup.h" +#include "sp_winsys.h" @@ -168,7 +169,7 @@ static GLuint softpipe_get_occlusion_counter(struct pipe_context *pipe) } -struct pipe_context *softpipe_create( void ) +struct pipe_context *softpipe_create( struct softpipe_winsys *sws ) { struct softpipe_context *softpipe = CALLOC_STRUCT(softpipe_context); @@ -209,6 +210,8 @@ struct pipe_context *softpipe_create( void ) softpipe->quad.colormask = sp_quad_colormask_stage(softpipe); softpipe->quad.output = sp_quad_output_stage(softpipe); + softpipe->winsys = sws; + /* * Create drawing context and plug our rendering stage into it. */ diff --git a/src/mesa/pipe/softpipe/sp_context.h b/src/mesa/pipe/softpipe/sp_context.h index 3c379c9091a..43fa8acd763 100644 --- a/src/mesa/pipe/softpipe/sp_context.h +++ b/src/mesa/pipe/softpipe/sp_context.h @@ -38,8 +38,8 @@ #include "sp_quad.h" - struct softpipe_surface; +struct softpipe_winsys; struct draw_context; struct draw_stage; @@ -68,6 +68,8 @@ enum interp_mode { struct softpipe_context { struct pipe_context pipe; /**< base class */ + struct softpipe_winsys *winsys; /**< window system interface */ + /* The most recent drawing state as set by the driver: */ diff --git a/src/mesa/pipe/softpipe/sp_region.c b/src/mesa/pipe/softpipe/sp_region.c index 1dbd1609e37..78a0919ad50 100644 --- a/src/mesa/pipe/softpipe/sp_region.c +++ b/src/mesa/pipe/softpipe/sp_region.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -25,74 +25,185 @@ * **************************************************************************/ -/** - * Software-based region allocation and management. - * A hardware driver would override these functions. +/* Provide additional functionality on top of bufmgr buffers: + * - 2d semantics and blit operations (XXX: remove/simplify blits??) + * - refcounting of buffers for multiple images in a buffer. + * - refcounting of buffer mappings. */ - #include "sp_context.h" +#include "sp_winsys.h" #include "sp_region.h" -#include "sp_surface.h" -#include "main/imports.h" +static void +sp_region_idle(struct pipe_context *pipe, struct pipe_region *region) +{ + +} + + +static GLubyte * +sp_region_map(struct pipe_context *pipe, struct pipe_region *region) +{ + struct softpipe_context *sp = softpipe_context( pipe ); + + if (!region->map_refcount++) { + region->map = sp->winsys->buffer_map( sp->winsys, + region->buffer ); + } + + return region->map; +} + +static void +sp_region_unmap(struct pipe_context *pipe, struct pipe_region *region) +{ + struct softpipe_context *sp = softpipe_context( pipe ); + + if (!--region->map_refcount) { + sp->winsys->buffer_unmap( sp->winsys, + region->buffer ); + region->map = NULL; + } +} + static struct pipe_region * sp_region_alloc(struct pipe_context *pipe, - GLuint cpp, GLuint pitch, GLuint height) + GLuint cpp, GLuint pitch, GLuint height) { - struct pipe_region *region = CALLOC_STRUCT(pipe_region); - if (!region) - return NULL; + struct softpipe_context *sp = softpipe_context( pipe ); + struct pipe_region *region = calloc(sizeof(*region), 1); - region->refcount = 1; region->cpp = cpp; region->pitch = pitch; - region->height = height; - region->map = malloc(cpp * pitch * height); + region->height = height; /* needed? */ + region->refcount = 1; + + region->buffer = sp->winsys->create_buffer(sp->winsys, "region", 64 ); + + sp->winsys->buffer_data( sp->winsys, + region->buffer, + pitch * cpp * height, + NULL ); return region; } - static void sp_region_release(struct pipe_context *pipe, struct pipe_region **region) { - assert((*region)->refcount > 0); + struct softpipe_context *sp = softpipe_context( pipe ); + + if (!*region) + return; + + ASSERT((*region)->refcount > 0); (*region)->refcount--; if ((*region)->refcount == 0) { assert((*region)->map_refcount == 0); -#if 0 - if ((*region)->pbo) - (*region)->pbo->region = NULL; - (*region)->pbo = NULL; -#endif - + sp->winsys->buffer_unreference( sp->winsys, + (*region)->buffer ); free(*region); } *region = NULL; } - -static GLubyte * -sp_region_map(struct pipe_context *pipe, struct pipe_region *region) +/* + * XXX Move this into core Mesa? + */ +static void +_mesa_copy_rect(GLubyte * dst, + GLuint cpp, + GLuint dst_pitch, + GLuint dst_x, + GLuint dst_y, + GLuint width, + GLuint height, + const GLubyte * src, + GLuint src_pitch, + GLuint src_x, + GLuint src_y) { - region->map_refcount++; - return region->map; + GLuint i; + + dst_pitch *= cpp; + src_pitch *= cpp; + dst += dst_x * cpp; + src += src_x * cpp; + dst += dst_y * dst_pitch; + src += src_y * dst_pitch; + width *= cpp; + + if (width == dst_pitch && width == src_pitch) + memcpy(dst, src, height * width); + else { + for (i = 0; i < height; i++) { + memcpy(dst, src, width); + dst += dst_pitch; + src += src_pitch; + } + } } +/* Upload data to a rectangular sub-region. Lots of choices how to do this: + * + * - memcpy by span to current destination + * - upload data as new buffer and blit + * + * Currently always memcpy. + */ static void -sp_region_unmap(struct pipe_context *pipe, struct pipe_region *region) +sp_region_data(struct pipe_context *pipe, + struct pipe_region *dst, + GLuint dst_offset, + GLuint dstx, GLuint dsty, + const void *src, GLuint src_pitch, + GLuint srcx, GLuint srcy, GLuint width, GLuint height) { - region->map_refcount--; + _mesa_copy_rect(pipe->region_map(pipe, dst) + dst_offset, + dst->cpp, + dst->pitch, + dstx, dsty, width, height, src, src_pitch, srcx, srcy); + + pipe->region_unmap(pipe, dst); } +/* Assumes all values are within bounds -- no checking at this level - + * do it higher up if required. + */ +static void +sp_region_copy(struct pipe_context *pipe, + struct pipe_region *dst, + GLuint dst_offset, + GLuint dstx, GLuint dsty, + struct pipe_region *src, + GLuint src_offset, + GLuint srcx, GLuint srcy, GLuint width, GLuint height) +{ + assert( dst != src ); + assert( dst->cpp == src->cpp ); + _mesa_copy_rect(pipe->region_map(pipe, dst) + dst_offset, + dst->cpp, + dst->pitch, + dstx, dsty, + width, height, + pipe->region_map(pipe, src) + src_offset, + src->pitch, + srcx, srcy); + pipe->region_unmap(pipe, src); + pipe->region_unmap(pipe, dst); +} + +/* Fill a rectangular sub-region. Need better logic about when to + * push buffers into AGP - will currently do so whenever possible. + */ static GLubyte * get_pointer(struct pipe_region *dst, GLuint x, GLuint y) { @@ -105,93 +216,69 @@ sp_region_fill(struct pipe_context *pipe, struct pipe_region *dst, GLuint dst_offset, GLuint dstx, GLuint dsty, - GLuint width, GLuint height, GLuint value, GLuint mask) + GLuint width, GLuint height, GLuint value) { GLuint i, j; + + (void)pipe->region_map(pipe, dst); + switch (dst->cpp) { - case 1: - { - GLubyte *row = get_pointer(dst, dstx, dsty); - if ((mask & 0xff) == 0xff) { - /* no masking */ - for (i = 0; i < height; i++) { - memset(row, value, width); - row += dst->pitch; - } - } - else { - value &= mask; - mask = ~mask; - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - row[j] = (row[j] & mask) | value; - } - row += dst->pitch; - } - } + case 1: { + GLubyte *row = get_pointer(dst, dstx, dsty); + for (i = 0; i < height; i++) { + memset(row, value, width); + row += dst->pitch; } - break; - case 2: - { - GLushort *row = (GLushort *) get_pointer(dst, dstx, dsty); - if ((mask & 0xffff) == 0xffff) { - /* no masking */ - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) - row[j] = value; - row += dst->pitch; - } - } - else { - value &= mask; - mask = ~mask; - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) - row[j] = (row[j] & mask) | value; - row += dst->pitch; - } - } + } + break; + case 2: { + GLushort *row = (GLushort *) get_pointer(dst, dstx, dsty); + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + row[j] = value; + row += dst->pitch; } - break; - case 4: - { - GLuint *row = (GLuint *) get_pointer(dst, dstx, dsty); - if (mask == 0xffffffff) { - /* no masking */ - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) - row[j] = value; - row += dst->pitch; - } - } - else { - value &= mask; - mask = ~mask; - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) - row[j] = (row[j] & mask) | value; - row += dst->pitch; - } - } + } + break; + case 4: { + GLuint *row = (GLuint *) get_pointer(dst, dstx, dsty); + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + row[j] = value; + row += dst->pitch; } - break; + } + break; default: assert(0); - + break; } + + pipe->region_unmap( pipe, dst ); +} + + + +static struct _DriBufferObject * +sp_region_buffer(struct pipe_context *pipe, + struct pipe_region *region, GLuint flag) +{ + return region->buffer; } + void sp_init_region_functions(struct softpipe_context *sp) { - sp->pipe.region_alloc = sp_region_alloc; - sp->pipe.region_release = sp_region_release; - + sp->pipe.region_idle = sp_region_idle; sp->pipe.region_map = sp_region_map; sp->pipe.region_unmap = sp_region_unmap; - + sp->pipe.region_alloc = sp_region_alloc; + sp->pipe.region_release = sp_region_release; + sp->pipe.region_data = sp_region_data; + sp->pipe.region_copy = sp_region_copy; sp->pipe.region_fill = sp_region_fill; - - /* XXX lots of other region functions needed... */ + sp->pipe.region_buffer = sp_region_buffer; } + diff --git a/src/mesa/pipe/softpipe/sp_winsys.h b/src/mesa/pipe/softpipe/sp_winsys.h new file mode 100644 index 00000000000..43953c648ba --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_winsys.h @@ -0,0 +1,100 @@ +/************************************************************************** + * + * Copyright 2007 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 SP_WINSYS_H +#define SP_WINSYS_H + +#include "main/mtypes.h" + +/* 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. + */ + + +/* Pipe drivers are (meant to be!) independent of both GL and the + * window system. The window system provides a buffer manager and a + * set of additional hooks for things like command buffer submission, + * etc. + * + * There clearly has to be some agreement between the window system + * driver and the hardware driver about the format of command buffers, + * etc. + */ + +struct softpipe_buffer_handle; + +struct softpipe_winsys { + + + /* The buffer manager is modeled after the dri_bugmgr interface, + * but this is the subset that softpipe cares about. Remember that + * softpipe gets to choose the interface it needs, and the window + * systems must then implement that interface (rather than the + * other way around...). + * + * Softpipe only really wants to make system memory allocations, + * right?? + */ + struct softpipe_buffer_handle *(*create_buffer)(struct softpipe_winsys *sws, + const char *name, + unsigned alignment ); + + void *(*buffer_map)( struct softpipe_winsys *sws, + struct softpipe_buffer_handle *buf ); + + void (*buffer_unmap)( struct softpipe_winsys *sws, + struct softpipe_buffer_handle *buf ); + + struct softpipe_buffer_handle *(*buffer_reference)( struct softpipe_winsys *sws, + struct softpipe_buffer_handle *buf ); + + void (*buffer_unreference)( struct softpipe_winsys *sws, + struct softpipe_buffer_handle *buf ); + + void (*buffer_data)(struct softpipe_winsys *sws, + struct softpipe_buffer_handle *buf, + unsigned size, const void *data ); + + void (*buffer_subdata)(struct softpipe_winsys *sws, + struct softpipe_buffer_handle *buf, + unsigned long offset, + unsigned long size, + const void *data); + + void (*buffer_get_subdata)(struct softpipe_winsys *sws, + struct softpipe_buffer_handle *buf, + unsigned long offset, + unsigned long size, + void *data); +}; + + +struct pipe_context *softpipe_create( struct softpipe_winsys * ); + + +#endif /* SP_WINSYS_H */