gallium: new raw gallium interface to support standalone tests

Provides basic window system integration behind a simple interface,
allowing tests to be written without dependency on either the driver
or window system.

With a lot of work, could turn into something like glut for gallium.
This commit is contained in:
Keith Whitwell 2010-03-28 09:53:58 -07:00
parent f97f46f269
commit db5c2235d1
13 changed files with 543 additions and 1 deletions

View File

@ -52,7 +52,7 @@ opts.Add(ListVariable('statetrackers', 'state trackers to build', default_statet
opts.Add(ListVariable('drivers', 'pipe drivers to build', default_drivers,
['softpipe', 'failover', 'svga', 'i915', 'i965', 'trace', 'r300', 'identity', 'llvmpipe']))
opts.Add(ListVariable('winsys', 'winsys drivers to build', default_winsys,
['xlib', 'vmware', 'i915', 'i965', 'gdi', 'radeon']))
['xlib', 'vmware', 'i915', 'i965', 'gdi', 'radeon', 'graw-xlib']))
opts.Add(EnumVariable('MSVS_VERSION', 'MS Visual C++ version', None, allowed_values=('7.1', '8.0', '9.0')))

View File

@ -56,4 +56,5 @@ SConscript([
'wgl/SConscript',
'perf/SConscript',
'gallium/unit/SConscript',
'gallium/raw/SConscript',
])

View File

@ -0,0 +1,17 @@
Import('*')
env = env.Clone()
env.Prepend(LIBPATH = [graw.dir])
env.Prepend(LIBS = [graw.name])
progs = [
'clear'
]
for prog in progs:
env.Program(
target = prog,
source = prog + '.c',
)

85
progs/gallium/raw/clear.c Normal file
View File

@ -0,0 +1,85 @@
/* Display a cleared blue window. This demo has no dependencies on
* any utility code, just the graw interface and gallium.
*/
#include "state_tracker/graw.h"
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include <unistd.h> /* for sleep() */
enum pipe_format formats[] = {
PIPE_FORMAT_R8G8B8A8_UNORM,
PIPE_FORMAT_B8G8R8A8_UNORM,
PIPE_FORMAT_NONE
};
static const int WIDTH = 300;
static const int HEIGHT = 300;
int main( int argc, char *argv[] )
{
struct pipe_screen *screen;
struct pipe_context *pipe;
struct pipe_surface *surf;
struct pipe_framebuffer_state fb;
struct pipe_texture *tex, templat;
void *window = NULL;
float clear_color[4] = {1,0,1,1};
int i;
screen = graw_init();
if (screen == NULL)
exit(1);
for (i = 0;
window == NULL && formats[i] != PIPE_FORMAT_NONE;
i++) {
window = graw_create_window(0,0,300,300, formats[i]);
}
if (window == NULL)
exit(2);
pipe = screen->context_create(screen, NULL);
if (pipe == NULL)
exit(3);
templat.target = PIPE_TEXTURE_2D;
templat.format = formats[i];
templat.width0 = WIDTH;
templat.height0 = HEIGHT;
templat.depth0 = 1;
templat.last_level = 0;
templat.nr_samples = 1;
templat.tex_usage = (PIPE_TEXTURE_USAGE_RENDER_TARGET |
PIPE_TEXTURE_USAGE_DISPLAY_TARGET);
tex = screen->texture_create(screen,
&templat);
if (tex == NULL)
exit(4);
surf = screen->get_tex_surface(screen, tex, 0, 0, 0,
PIPE_TEXTURE_USAGE_RENDER_TARGET |
PIPE_TEXTURE_USAGE_DISPLAY_TARGET);
if (surf == NULL)
exit(5);
memset(&fb, 0, sizeof fb);
fb.nr_cbufs = 1;
fb.width = WIDTH;
fb.height = HEIGHT;
fb.cbufs[0] = surf;
pipe->set_framebuffer_state(pipe, &fb);
pipe->clear(pipe, PIPE_CLEAR_COLOR, clear_color, 0, 0);
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
screen->flush_frontbuffer(screen, surf, window);
sleep(100);
return 0;
}

View File

@ -0,0 +1,10 @@
# Meta-driver which combines whichever software rasterizers have been
# built into a single convenience library.
TOP = ../../../..
include $(TOP)/configs/current
C_SOURCES = \
sw.c
include ../../Makefile.template

View File

@ -0,0 +1,42 @@
#######################################################################
# SConscript for swrast convenience library
#
# This is a meta-driver which consists of any and all of the software
# rasterizers into a single driver. A software rasterizer is defined
# as any driver which takes an sw_winsys pointer as the only argument
# to create_screen.
#
# XXX: unfortunately users of this driver still need to link in any
# extra libraries needed for the particular driver (eg llvm for
# llvmpipe). Not sure how to get around this.
Import('*')
if not set(('softpipe', 'llvmpipe', 'cell')).intersection(env['drivers']):
print 'warning: no supported pipe driver: skipping build of sw meta-driver'
Return()
env = env.Clone()
if 'softpipe' in env['drivers']:
env.Append(CPPDEFINES = 'GALLIUM_SOFTPIPE')
env.Prepend(LIBS = [softpipe])
if 'llvmpipe' in env['drivers']:
env.Tool('llvm')
if 'LLVM_VERSION' in env:
env.Append(CPPDEFINES = 'GALLIUM_LLVMPIPE')
env.Tool('udis86')
env.Prepend(LIBS = [llvmpipe])
if 'cell' in env['drivers']:
env.Append(CPPDEFINES = 'GALLIUM_CELL')
env.Prepend(LIBS = [cell])
sw = env.ConvenienceLibrary(
target = 'sw',
source = [
'sw.c',
]
)
Export('sw')

View File

@ -0,0 +1,59 @@
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
#include "target-helpers/wrap_screen.h"
#include "sw_public.h"
#include "state_tracker/sw_winsys.h"
/* Helper function to choose and instantiate one of the software rasterizers:
* cell, llvmpipe, softpipe.
*/
#ifdef GALLIUM_SOFTPIPE
#include "softpipe/sp_public.h"
#endif
#ifdef GALLIUM_LLVMPIPE
#include "llvmpipe/lp_public.h"
#endif
#ifdef GALLIUM_CELL
#include "cell/ppu/cell_public.h"
#endif
struct pipe_screen *
swrast_create_screen(struct sw_winsys *winsys)
{
const char *default_driver;
const char *driver;
struct pipe_screen *screen = NULL;
#if defined(GALLIUM_CELL)
default_driver = "cell";
#elif defined(GALLIUM_LLVMPIPE)
default_driver = "llvmpipe";
#elif defined(GALLIUM_SOFTPIPE)
default_driver = "softpipe";
#else
default_driver = "";
#endif
driver = debug_get_option("GALLIUM_DRIVER", default_driver);
#if defined(GALLIUM_CELL)
if (screen == NULL && strcmp(driver, "cell") == 0)
screen = cell_create_screen( winsys );
#endif
#if defined(GALLIUM_LLVMPIPE)
if (screen == NULL && strcmp(driver, "llvmpipe") == 0)
screen = llvmpipe_create_screen( winsys );
#endif
#if defined(GALLIUM_SOFTPIPE)
if (screen == NULL)
screen = softpipe_create_screen( winsys );
#endif
return screen;
}

View File

@ -0,0 +1,13 @@
#ifndef SW_PUBLIC_H
#define SW_PUBLIC_H
/* A convenience library, primarily to isolate the logic required to
* figure out which if any software rasterizers have been built and
* select between them.
*/
struct sw_winsys;
struct pipe_screen *
swrast_create_screen(struct sw_winsys *winsys);
#endif

View File

@ -0,0 +1,36 @@
#ifndef GALLIUM_RAW_H
#define GALLIUM_RAW_H
/* This is an API for exercising gallium functionality in a
* platform-neutral fashion. Whatever platform integration is
* necessary to implement this interface is orchestrated by the
* individual target building this entity.
*
* For instance, the graw-xlib target includes code to implent these
* interfaces on top of the X window system.
*
* Programs using this interface may additionally benefit from some of
* the utilities currently in the libgallium.a library, especially
* those for parsing text representations of TGSI shaders.
*/
#include "pipe/p_format.h"
struct pipe_screen;
struct pipe_screen *graw_init( void );
/* Returns a handle to be used with flush_frontbuffer()/present().
*
* Query format support with screen::is_format_supported and usage
* XXX.
*/
void *graw_create_window( int x,
int y,
unsigned width,
unsigned height,
enum pipe_format format );
void graw_destroy_window( void *handle );
#endif

View File

@ -10,6 +10,11 @@ if 'gdi' in env['winsys']:
'libgl-gdi/SConscript',
])
if 'graw-xlib' in env['winsys']:
SConscript([
'graw-xlib/SConscript',
])
if env['dri']:
SConscript([
'SConscript.dri'

View File

@ -0,0 +1,57 @@
#######################################################################
# SConscript for xlib winsys
Import('*')
if env['platform'] != 'linux':
Return()
if not set(('softpipe', 'llvmpipe', 'cell')).intersection(env['drivers']):
print 'warning: no supported pipe driver: skipping build of xlib libGL.so'
Return()
env = env.Clone()
env.Prepend(LIBS = [
ws_xlib,
trace,
identity,
# gallium,
])
env.Append(CPPPATH = [
'#src/gallium/drivers',
])
sources = [
'graw_xlib.c',
]
if 'softpipe' in env['drivers']:
env.Append(CPPDEFINES = 'GALLIUM_SOFTPIPE')
env.Prepend(LIBS = [softpipe])
if 'llvmpipe' in env['drivers']:
env.Tool('llvm')
if 'LLVM_VERSION' in env:
env.Append(CPPDEFINES = 'GALLIUM_LLVMPIPE')
env.Tool('udis86')
env.Prepend(LIBS = [llvmpipe])
# Need this for trace, identity drivers referenced by
# gallium_wrap_screen().
#
env.Prepend(LIBS = [gallium])
# TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions
graw = env.SharedLibrary(
target ='graw',
source = sources,
)
env.InstallSharedLibrary(graw, version=(1, 0))
graw = env.FindIxes(graw, 'SHLIBPREFIX', 'SHLIBSUFFIX')
Export('graw')

View File

@ -0,0 +1,36 @@
#ifndef GALLIUM_RAW_H
#define GALLIUM_RAW_H
/* This is an API for exercising gallium functionality in a
* platform-neutral fashion. Whatever platform integration is
* necessary to implement this interface is orchestrated by the
* individual target building this entity.
*
* For instance, the graw-xlib target includes code to implent these
* interfaces on top of the X window system.
*
* Programs using this interface may additionally benefit from some of
* the utilities currently in the libgallium.a library, especially
* those for parsing text representations of TGSI shaders.
*/
#include "pipe/p_format.h"
struct pipe_screen;
struct pipe_screen *graw_init( void );
/* Returns a handle to be used with flush_frontbuffer()/present().
*
* Query format support with screen::is_format_supported and usage
* XXX.
*/
void *graw_create_window( int x,
int y,
unsigned width,
unsigned height,
enum pipe_format format );
void graw_destroy_window( void *handle );
#endif

View File

@ -0,0 +1,181 @@
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "target-helpers/wrap_screen.h"
#include "state_tracker/xlib_sw_winsys.h"
#ifdef GALLIUM_SOFTPIPE
#include "softpipe/sp_public.h"
#endif
#ifdef GALLIUM_LLVMPIPE
#include "llvmpipe/lp_public.h"
#endif
/* Haven't figured out a decent way to build the helper code yet -
* #include it here temporarily.
*/
#include "sw/sw_public.h"
#include "sw/sw.c"
#include "graw.h"
#include <X11/Xlib.h>
#include <X11/Xlibint.h>
#include <X11/Xutil.h>
#include <stdio.h>
static struct {
Display *display;
} graw;
struct pipe_screen *
graw_init( void )
{
const char *default_driver;
const char *driver;
struct pipe_screen *screen = NULL;
struct sw_winsys *winsys = NULL;
graw.display = XOpenDisplay(NULL);
if (graw.display == NULL)
return NULL;
/* Create the underlying winsys, which performs presents to Xlib
* drawables:
*/
winsys = xlib_create_sw_winsys( graw.display );
if (winsys == NULL)
return NULL;
#if defined(GALLIUM_LLVMPIPE)
default_driver = "llvmpipe";
#elif defined(GALLIUM_SOFTPIPE)
default_driver = "softpipe";
#else
default_driver = "";
#endif
driver = debug_get_option("GALLIUM_DRIVER", default_driver);
#if defined(GALLIUM_LLVMPIPE)
if (screen == NULL && strcmp(driver, "llvmpipe") == 0)
screen = llvmpipe_create_screen( winsys );
#endif
#if defined(GALLIUM_SOFTPIPE)
if (screen == NULL)
screen = softpipe_create_screen( winsys );
#endif
/* Inject any wrapping layers we want to here:
*/
return gallium_wrap_screen( screen );
}
void *
graw_create_window( int x,
int y,
unsigned width,
unsigned height,
enum pipe_format format )
{
struct xlib_drawable *handle = NULL;
XSetWindowAttributes attr;
Window root;
Window win = 0;
XVisualInfo templat, *visinfo = NULL;
unsigned mask;
int n;
int scrnum;
scrnum = DefaultScreen( graw.display );
root = RootWindow( graw.display, scrnum );
if (format != PIPE_FORMAT_R8G8B8A8_UNORM)
goto fail;
if (graw.display == NULL)
goto fail;
handle = CALLOC_STRUCT(xlib_drawable);
if (handle == NULL)
goto fail;
mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
templat.screen = DefaultScreen(graw.display);
templat.depth = 32;
templat.class = TrueColor;
visinfo = XGetVisualInfo(graw.display, mask, &templat, &n);
if (!visinfo) {
printf("Error: couldn't get an RGB, Double-buffered visual\n");
exit(1);
}
/* window attributes */
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap( graw.display, root, visinfo->visual, AllocNone);
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
/* XXX this is a bad way to get a borderless window! */
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
win = XCreateWindow( graw.display, root, x, y, width, height,
0, visinfo->depth, InputOutput,
visinfo->visual, mask, &attr );
/* set hints and properties */
{
char *name = NULL;
XSizeHints sizehints;
sizehints.x = x;
sizehints.y = y;
sizehints.width = width;
sizehints.height = height;
sizehints.flags = USSize | USPosition;
XSetNormalHints(graw.display, win, &sizehints);
XSetStandardProperties(graw.display, win, name, name,
None, (char **)NULL, 0, &sizehints);
}
XFree(visinfo);
XMapWindow(graw.display, win);
while (1) {
XEvent e;
XNextEvent( graw.display, &e );
if (e.type == MapNotify && e.xmap.window == win) {
break;
}
}
handle->visual = visinfo->visual;
handle->drawable = (Drawable)win;
handle->depth = visinfo->depth;
return (void *)handle;
fail:
FREE(handle);
XFree(visinfo);
if (win)
XDestroyWindow(graw.display, win);
return NULL;
}
void
graw_destroy_window( void *xlib_drawable )
{
}