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.
This commit is contained in:
Keith Whitwell
2010-03-04 16:09:33 +00:00
parent c7f7a309af
commit 94ce4eb3c2
28 changed files with 768 additions and 1680 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
/**************************************************************************
*
* 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
@@ -18,56 +18,38 @@
* 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
#include "pipe/p_defines.h"
struct pipe_screen;
struct pipe_winsys;
struct pipe_context;
struct pipe_texture;
struct pipe_buffer;
struct softpipe_buffer
{
struct pipe_buffer base;
boolean userBuffer; /** Is this a user-space buffer? */
void *data;
};
/**
* 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);
boolean
softpipe_get_texture_buffer( struct pipe_texture *texture,
struct pipe_buffer **buf,
unsigned *stride );
#ifdef __cplusplus
/** Cast wrapper */
static INLINE struct softpipe_buffer *
softpipe_buffer( struct pipe_buffer *buf )
{
return (struct softpipe_buffer *)buf;
}
#endif
#endif /* SP_WINSYS_H */
void
softpipe_init_screen_buffer_funcs(struct pipe_screen *screen);
#endif /* SP_BUFFER_H */

View File

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

View File

@@ -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);
}
/*
* 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 */
softpipe_unmap_constant_buffers(sp);
sp->dirty_render_cache = TRUE;
}

View File

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

View File

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

View File

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

View File

@@ -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;
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
spt->buffer = screen->surface_buffer_create( screen,
/* 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,
spt->base.format,
usage,
tex_usage,
16,
&spt->stride[0] );
return spt->buffer != NULL;
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) {
/* Texture blanket is going away.
*/
debug_printf("softpipe_texture_blanket() not implemented!");
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;
}
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 (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;
}

View File

@@ -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 pipe_buffer *buffer;
struct sw_displaytarget *dt;
/**
* Malloc'ed data for regular textures, or a mapping to dt above.
*/
void *data;
/* True if texture images are power-of-two in all dimensions:
*/

View File

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

View File

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

View File

@@ -18,7 +18,7 @@ if env['platform'] == 'windows':
'ws2_32',
])
sources = []
sources = ['gdi_sw_winsys.c']
drivers = []
if 'softpipe' in env['drivers']:

View File

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

View File

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

View File

@@ -29,6 +29,7 @@ DEFINES += \
XLIB_WINSYS_SOURCES = \
xlib.c \
xlib_cell.c \
xlib_sw_winsys.c \
xlib_llvmpipe.c \
xlib_softpipe.c

View File

@@ -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']:

View File

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

View File

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

View File

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

View File

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

View File

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