gallium: new raw gallium interface to support standalone tests
authorKeith Whitwell <keithw@vmware.com>
Sun, 28 Mar 2010 16:53:58 +0000 (09:53 -0700)
committerKeith Whitwell <keithw@vmware.com>
Sun, 28 Mar 2010 17:42:38 +0000 (10:42 -0700)
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.

13 files changed:
SConstruct
progs/SConscript
progs/gallium/raw/SConscript [new file with mode: 0644]
progs/gallium/raw/clear.c [new file with mode: 0644]
src/gallium/drivers/sw/Makefile [new file with mode: 0644]
src/gallium/drivers/sw/SConscript [new file with mode: 0644]
src/gallium/drivers/sw/sw.c [new file with mode: 0644]
src/gallium/drivers/sw/sw_public.h [new file with mode: 0644]
src/gallium/include/state_tracker/graw.h [new file with mode: 0644]
src/gallium/targets/SConscript
src/gallium/targets/graw-xlib/SConscript [new file with mode: 0644]
src/gallium/targets/graw-xlib/graw.h [new file with mode: 0644]
src/gallium/targets/graw-xlib/graw_xlib.c [new file with mode: 0644]

index 2549a13fffaca4c55e573da9bdeca3a1472309fb..5d44b6efde625f73ed9d104562c461f861f99cc9 100644 (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')))
 
index aa6640cf7a6f1b660aeddbaae25cc594b7142cc5..20be60972d2086c75d8e28de8552506f8ee62d0b 100644 (file)
@@ -56,4 +56,5 @@ SConscript([
     'wgl/SConscript',
     'perf/SConscript',
     'gallium/unit/SConscript',
+    'gallium/raw/SConscript',
 ])
diff --git a/progs/gallium/raw/SConscript b/progs/gallium/raw/SConscript
new file mode 100644 (file)
index 0000000..073b979
--- /dev/null
@@ -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',
+    )
+
diff --git a/progs/gallium/raw/clear.c b/progs/gallium/raw/clear.c
new file mode 100644 (file)
index 0000000..e46d135
--- /dev/null
@@ -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;
+}
diff --git a/src/gallium/drivers/sw/Makefile b/src/gallium/drivers/sw/Makefile
new file mode 100644 (file)
index 0000000..2713a62
--- /dev/null
@@ -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
diff --git a/src/gallium/drivers/sw/SConscript b/src/gallium/drivers/sw/SConscript
new file mode 100644 (file)
index 0000000..6fbbdf3
--- /dev/null
@@ -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')
diff --git a/src/gallium/drivers/sw/sw.c b/src/gallium/drivers/sw/sw.c
new file mode 100644 (file)
index 0000000..9f156df
--- /dev/null
@@ -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;
+}
diff --git a/src/gallium/drivers/sw/sw_public.h b/src/gallium/drivers/sw/sw_public.h
new file mode 100644 (file)
index 0000000..7085c5c
--- /dev/null
@@ -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
diff --git a/src/gallium/include/state_tracker/graw.h b/src/gallium/include/state_tracker/graw.h
new file mode 100644 (file)
index 0000000..a58e18e
--- /dev/null
@@ -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
index 747e64508f74a733b24e51fd5a1dd1a5f28204fb..1292d4f619334037543ae834e76aecc552fde0a8 100644 (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'
diff --git a/src/gallium/targets/graw-xlib/SConscript b/src/gallium/targets/graw-xlib/SConscript
new file mode 100644 (file)
index 0000000..24cea92
--- /dev/null
@@ -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')
diff --git a/src/gallium/targets/graw-xlib/graw.h b/src/gallium/targets/graw-xlib/graw.h
new file mode 100644 (file)
index 0000000..a58e18e
--- /dev/null
@@ -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
diff --git a/src/gallium/targets/graw-xlib/graw_xlib.c b/src/gallium/targets/graw-xlib/graw_xlib.c
new file mode 100644 (file)
index 0000000..fb8ef9d
--- /dev/null
@@ -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 )
+{
+}
+