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.
This commit is contained in:
Keith Whitwell 2007-08-05 17:23:38 +01:00
parent 5e7921b778
commit 1d1b9e6be4
13 changed files with 497 additions and 461 deletions

View file

@ -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 \

View file

@ -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

View file

@ -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)

View file

@ -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, &region->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;
}

View file

@ -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

View file

@ -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 <keithw-at-tungstengraphics-dot-com>
*/
#include <stdlib.h>
#include <xf86drm.h>
#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 );
}

View file

@ -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 */
};

View file

@ -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 */

View file

@ -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);
}

View file

@ -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.
*/

View file

@ -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:
*/

View file

@ -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)
{
region->map_refcount++;
return region->map;
}
/*
* XXX Move this into core Mesa?
*/
static void
sp_region_unmap(struct pipe_context *pipe, struct pipe_region *region)
_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--;
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_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)
{
_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;
}

View file

@ -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 */