egl: new EGL/gallium/softpipe/xlib winsys
authorBrian Paul <brian.paul@tungstengraphics.com>
Thu, 29 May 2008 23:02:55 +0000 (17:02 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Thu, 29 May 2008 23:04:25 +0000 (17:04 -0600)
Checkpoint commit.  Most required code is in place, and compiles, but
totally untested.

src/gallium/winsys/egl_xlib/Makefile [new file with mode: 0644]
src/gallium/winsys/egl_xlib/egl_xlib.c [new file with mode: 0644]
src/gallium/winsys/egl_xlib/sw_winsys.c [new file with mode: 0644]
src/gallium/winsys/egl_xlib/sw_winsys.h [new file with mode: 0644]

diff --git a/src/gallium/winsys/egl_xlib/Makefile b/src/gallium/winsys/egl_xlib/Makefile
new file mode 100644 (file)
index 0000000..fe4b931
--- /dev/null
@@ -0,0 +1,87 @@
+# src/gallium/winsys/egl_xlib/Makefile
+
+# Build softpipe/xlib/EGL driver library/object: "softpipe_egl.so"
+
+
+TOP = ../../../..
+include $(TOP)/configs/current
+
+
+LIBNAME = softpipe_egl.so
+
+
+INCLUDE_DIRS = \
+       -I$(TOP)/include \
+       -I$(TOP)/src/egl/main \
+       -I$(TOP)/src/mesa \
+       -I$(TOP)/src/mesa/main \
+       -I$(TOP)/src/gallium/include \
+       -I$(TOP)/src/gallium/drivers \
+       -I$(TOP)/src/gallium/auxiliary
+
+WINSYS_SOURCES = \
+       egl_xlib.c \
+       sw_winsys.c
+
+WINSYS_OBJECTS = $(WINSYS_SOURCES:.c=.o)
+
+
+LIBS = \
+       $(GALLIUM_DRIVERS) \
+       $(TOP)/src/mesa/libglapi.a \
+       $(TOP)/src/mesa/libmesa.a \
+       $(GALLIUM_AUXILIARIES)
+
+
+LOCAL_CFLAGS = -D_EGL_PLATFORM_X=1
+
+
+.SUFFIXES : .cpp
+
+.c.o:
+       $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(LOCAL_CFLAGS) $< -o $@
+
+.cpp.o:
+       $(CXX) -c $(INCLUDE_DIRS) $(CXXFLAGS) $(LOCAL_CFLAGS) $< -o $@
+
+
+
+default: $(TOP)/$(LIB_DIR)/$(LIBNAME)
+
+
+# Make the softpipe_egl.so library
+$(TOP)/$(LIB_DIR)/$(LIBNAME): $(WINSYS_OBJECTS) $(LIBS)
+       $(TOP)/bin/mklib -o $(LIBNAME) \
+               -linker "$(CC)" \
+               -noprefix \
+               -install $(TOP)/$(LIB_DIR) \
+               $(MKLIB_OPTIONS) $(WINSYS_OBJECTS) \
+               --start-group $(LIBS) --end-group
+
+# $(GL_LIB_DEPS)
+
+
+depend: $(ALL_SOURCES)
+       @ echo "running $(MKDEP)"
+       @ rm -f depend  # workaround oops on gutsy?!?
+       @ touch depend
+       @ $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(ALL_SOURCES) \
+               > /dev/null 2>/dev/null
+
+
+install: default
+       $(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR)
+       @if [ -e $(TOP)/$(LIB_DIR) ]; then \
+               $(INSTALL) $(TOP)/$(LIB_DIR)/$(LIBNAME) $(INSTALL_DIR)/$(LIB_DIR); \
+       fi
+
+
+# Emacs tags
+tags:
+       etags `find . -name \*.[ch]` $(TOP)/include/GL/*.h
+
+clean:
+       -rm -f *.o *~ *.bak
+
+
+include depend
diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c
new file mode 100644 (file)
index 0000000..4741da8
--- /dev/null
@@ -0,0 +1,461 @@
+/**************************************************************************
+ * 
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+/**
+ * EGL / softpipe / xlib winsys module
+ *
+ * Authors: Brian Paul
+ */
+
+
+#include <X11/Xutil.h>
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+#include "pipe/p_state.h"
+#include "pipe/p_util.h"
+#include "pipe/p_winsys.h"
+#include "softpipe/sp_winsys.h"
+
+#include "eglconfig.h"
+#include "eglconfigutil.h"
+#include "eglcontext.h"
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglglobals.h"
+#include "egllog.h"
+#include "eglsurface.h"
+
+#include "state_tracker/st_public.h"
+
+#include "sw_winsys.h"
+
+
+/** subclass of _EGLDriver */
+struct xlib_egl_driver
+{
+   _EGLDriver Base;   /**< base class */
+
+   struct pipe_winsys *winsys;
+   struct pipe_screen *screen;
+};
+
+
+/** subclass of _EGLContext */
+struct xlib_egl_context
+{
+   _EGLContext Base;   /**< base class */
+
+   struct pipe_context *pipe;   /**< Gallium driver context */
+   struct st_context *Context;  /**< Mesa/gallium state tracker context */
+};
+
+
+/** subclass of _EGLSurface */
+struct xlib_egl_surface
+{
+   _EGLSurface Base;   /**< base class */
+
+   Display *Dpy;  /**< The X Display of the window */
+   Window Win;    /**< The user-created window ID */
+   GC Gc;
+   XVisualInfo VisInfo;
+
+   struct pipe_winsys *winsys;
+
+   struct st_framebuffer *Framebuffer;
+};
+
+
+/** cast wrapper */
+static INLINE struct xlib_egl_driver *
+xlib_egl_driver(_EGLDriver *drv)
+{
+   return (struct xlib_egl_driver *) drv;
+}
+
+
+static struct xlib_egl_surface *
+lookup_surface(EGLSurface surf)
+{
+   _EGLSurface *surface = _eglLookupSurface(surf);
+   return (struct xlib_egl_surface *) surface;
+}
+
+
+static struct xlib_egl_context *
+lookup_context(EGLContext surf)
+{
+   _EGLContext *context = _eglLookupContext(surf);
+   return (struct xlib_egl_context *) context;
+}
+
+
+/**
+ * XXX temporary
+ * Need to query X server's GLX visuals.
+ */
+static void
+init_configs(_EGLDriver *drv, EGLDisplay dpy)
+{
+   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   int i;
+
+   for (i = 0; i < 2; i++) {
+      _EGLConfig config;
+      int id = i + 1;
+      _eglInitConfig(&config, id);
+      SET_CONFIG_ATTRIB(&config, EGL_RED_SIZE, 8);
+      SET_CONFIG_ATTRIB(&config, EGL_GREEN_SIZE, 8);
+      SET_CONFIG_ATTRIB(&config, EGL_BLUE_SIZE, 8);
+      SET_CONFIG_ATTRIB(&config, EGL_ALPHA_SIZE, 8);
+      if (i > 0) {
+         SET_CONFIG_ATTRIB(&config, EGL_DEPTH_SIZE, 24);
+         SET_CONFIG_ATTRIB(&config, EGL_STENCIL_SIZE, 8);
+      }
+      _eglAddConfig(disp, &config);
+   }
+}
+
+
+
+/**
+ * Called via eglInitialize(), drv->API.Initialize().
+ */
+static EGLBoolean
+xlib_eglInitialize(_EGLDriver *drv, EGLDisplay dpy,
+                   EGLint *minor, EGLint *major)
+{
+   /* visual configs */
+
+   init_configs(drv, dpy);
+
+
+   drv->Initialized = EGL_TRUE;
+
+   /* we're supporting EGL 1.4 */
+   *minor = 1;
+   *major = 4;
+
+   return EGL_TRUE;
+}
+
+
+/**
+ * Called via eglTerminate(), drv->API.Terminate().
+ */
+static EGLBoolean
+xlib_eglTerminate(_EGLDriver *drv, EGLDisplay dpy)
+{
+
+   return EGL_TRUE;
+}
+
+
+/** Get size of given window */
+static Status
+get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
+{
+   Window root;
+   Status stat;
+   int xpos, ypos;
+   unsigned int w, h, bw, depth;
+   stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
+   *width = w;
+   *height = h;
+   return stat;
+}
+
+
+static void
+display_surface(struct pipe_winsys *pws,
+                struct pipe_surface *psurf,
+                struct xlib_egl_surface *xsurf)
+{
+   XImage *ximage;
+   void *data;
+
+   ximage = XCreateImage(xsurf->Dpy,
+                         xsurf->VisInfo.visual,
+                         xsurf->VisInfo.depth,
+                         ZPixmap, 0,   /* format, offset */
+                         NULL,         /* data */
+                         0, 0,         /* size */
+                         32,           /* bitmap_pad */
+                         0);           /* bytes_per_line */
+
+
+   assert(ximage->format);
+   assert(ximage->bitmap_unit);
+
+   data = pws->buffer_map(pws, psurf->buffer, 0);
+
+   /* update XImage's fields */
+   ximage->data = data;
+   ximage->width = psurf->width;
+   ximage->height = psurf->height;
+   ximage->bytes_per_line = psurf->pitch * psurf->cpp;
+   
+   XPutImage(xsurf->Dpy, xsurf->Win, xsurf->Gc,
+             ximage, 0, 0, 0, 0, psurf->width, psurf->height);
+
+   ximage->data = NULL;
+   XDestroyImage(ximage);
+
+   pws->buffer_unmap(pws, psurf->buffer);
+}
+
+
+
+/** Display gallium surface in X window */
+static void
+flush_frontbuffer(struct pipe_winsys *pws,
+                  struct pipe_surface *psurf,
+                  void *context_private)
+{
+   struct xlib_egl_surface *xsurf = (struct xlib_egl_surface *) context_private;
+   display_surface(pws, psurf, xsurf);
+}
+
+
+
+/**
+ * Called via eglCreateContext(), drv->API.CreateContext().
+ */
+static EGLContext
+xlib_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+                      EGLContext share_list, const EGLint *attrib_list)
+{
+   struct xlib_egl_driver *xdrv = xlib_egl_driver(drv);
+   _EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
+   struct xlib_egl_context *ctx;
+   struct st_context *share_ctx = NULL; /* XXX fix */
+   __GLcontextModes visual;
+
+   ctx = CALLOC_STRUCT(xlib_egl_context);
+   if (!ctx)
+      return EGL_NO_CONTEXT;
+
+   /* let EGL lib init the common stuff */
+   if (!_eglInitContext(drv, dpy, &ctx->Base, config, attrib_list)) {
+      free(ctx);
+      return EGL_NO_CONTEXT;
+   }
+
+   /* create a softpipe context */
+   ctx->pipe = softpipe_create(xdrv->screen, xdrv->winsys, NULL);
+
+   /* Now do xlib / state tracker inits here */
+   _eglConfigToContextModesRec(conf, &visual);
+   ctx->Context = st_create_context(ctx->pipe, &visual, share_ctx);
+
+
+   return _eglGetContextHandle(&ctx->Base);
+}
+
+
+static EGLBoolean
+xlib_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx)
+{
+   struct xlib_egl_context *context = lookup_context(ctx);
+   if (context) {
+      if (context->Base.IsBound) {
+         context->Base.DeletePending = EGL_TRUE;
+      }
+      else {
+         st_destroy_context(context->Context);
+         free(context);
+      }
+      return EGL_TRUE;
+   }
+   else {
+      _eglError(EGL_BAD_CONTEXT, "eglDestroyContext");
+      return EGL_TRUE;
+   }
+}
+
+
+/**
+ * Called via eglMakeCurrent(), drv->API.MakeCurrent().
+ */
+static EGLBoolean
+xlib_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
+                    EGLSurface r, EGLContext context)
+{
+   if (!_eglMakeCurrent(drv, dpy, d, r, context))
+      return EGL_FALSE;
+
+   /* XXX anything todo? */
+
+   return EGL_TRUE;
+}
+
+
+static enum pipe_format
+choose_color_format(const __GLcontextModes *visual)
+{
+   if (visual->redBits == 8 &&
+       visual->greenBits == 8 &&
+       visual->blueBits == 8 &&
+       visual->alphaBits == 8) {
+      /* XXX this really also depends on the ordering of R,G,B,A */
+      return PIPE_FORMAT_A8R8G8B8_UNORM;
+   }
+   else {
+      assert(0);
+      return PIPE_FORMAT_NONE;
+   }
+}
+
+
+static enum pipe_format
+choose_depth_format(const __GLcontextModes *visual)
+{
+   if (visual->depthBits > 0)
+      return PIPE_FORMAT_Z24S8_UNORM;
+   else
+      return PIPE_FORMAT_NONE;
+}
+
+
+static enum pipe_format
+choose_stencil_format(const __GLcontextModes *visual)
+{
+   if (visual->stencilBits > 0)
+      return PIPE_FORMAT_Z24S8_UNORM;
+   else
+      return PIPE_FORMAT_NONE;
+}
+
+
+/**
+ * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
+ */
+static EGLSurface
+xlib_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+                            NativeWindowType window, const EGLint *attrib_list)
+{
+   struct xlib_egl_driver *xdrv = xlib_egl_driver(drv);
+   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
+
+   struct xlib_egl_surface *surf;
+   __GLcontextModes visual;
+   uint width, height;
+
+   surf = CALLOC_STRUCT(xlib_egl_surface);
+   if (!surf)
+      return EGL_NO_SURFACE;
+
+   /* Let EGL lib init the common stuff */
+   if (!_eglInitSurface(drv, dpy, &surf->Base, EGL_WINDOW_BIT,
+                        config, attrib_list)) {
+      free(surf);
+      return EGL_NO_SURFACE;
+   }
+
+   /*
+    * Now init the Xlib and gallium stuff
+    */
+   surf->Win = (Window) window;  /* The X window ID */
+   surf->Dpy = disp->Xdpy;  /* The X display */
+   surf->Gc = XCreateGC(surf->Dpy, surf->Win, 0, NULL);
+
+   surf->winsys = xdrv->winsys;
+
+   _eglConfigToContextModesRec(conf, &visual);
+   get_drawable_size(surf->Dpy, surf->Win, &width, &height);
+
+   /* Create GL statetracker framebuffer */
+   surf->Framebuffer = st_create_framebuffer(&visual,
+                                             choose_color_format(&visual),
+                                             choose_depth_format(&visual),
+                                             choose_stencil_format(&visual),
+                                             width, height,
+                                             (void *) surf);
+   return surf;
+}
+
+
+static EGLBoolean
+xlib_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
+{
+   /* error checking step: */
+   if (!_eglSwapBuffers(drv, dpy, draw))
+      return EGL_FALSE;
+
+   {
+      struct xlib_egl_surface *xsurf = lookup_surface(draw);
+      struct pipe_winsys *pws = xsurf->winsys;
+      struct pipe_surface *psurf =
+         st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT);
+
+      display_surface(pws, psurf, xsurf);
+   }
+
+   return EGL_TRUE;
+}
+
+
+/**
+ * This is the main entrypoint into the driver.
+ * Called by libEGL to instantiate an _EGLDriver object.
+ */
+_EGLDriver *
+_eglMain(_EGLDisplay *dpy, const char *args)
+{
+   struct xlib_egl_driver *xdrv;
+
+   _eglLog(_EGL_INFO, "Entering EGL/Xlib _eglMain(%s)", args);
+
+   xdrv = CALLOC_STRUCT(xlib_egl_driver);
+   if (!xdrv)
+      return NULL;
+
+   _eglInitDriverFallbacks(&xdrv->Base);
+   xdrv->Base.API.Initialize = xlib_eglInitialize;
+   xdrv->Base.API.Terminate = xlib_eglTerminate;
+   xdrv->Base.API.CreateContext = xlib_eglCreateContext;
+   xdrv->Base.API.DestroyContext = xlib_eglDestroyContext;
+   xdrv->Base.API.CreateWindowSurface = xlib_eglCreateWindowSurface;
+   xdrv->Base.API.MakeCurrent = xlib_eglMakeCurrent;
+   xdrv->Base.API.SwapBuffers = xlib_eglSwapBuffers;
+
+
+   xdrv->Base.ClientAPIs = "OpenGL"; /* "OpenGL_ES" */
+   xdrv->Base.Name = "Xlib/softpipe";
+
+   /* create one winsys and use it for all contexts/surfaces */
+   xdrv->winsys = create_sw_winsys();
+   xdrv->winsys->flush_frontbuffer = flush_frontbuffer;
+
+   xdrv->screen = softpipe_create_screen(xdrv->winsys);
+
+
+   return &xdrv->Base;
+}
+
diff --git a/src/gallium/winsys/egl_xlib/sw_winsys.c b/src/gallium/winsys/egl_xlib/sw_winsys.c
new file mode 100644 (file)
index 0000000..0e71bde
--- /dev/null
@@ -0,0 +1,244 @@
+/**************************************************************************
+ * 
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+/**
+ * Totally software-based winsys layer.
+ * Note that the one winsys function that we can't implement here
+ * is flush_frontbuffer().
+ * Whoever uses this code will have to provide that.
+ *
+ * Authors: Brian Paul
+ */
+
+
+#include "pipe/p_winsys.h"
+#include "pipe/p_state.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+
+#include "sw_winsys.h"
+
+
+
+/** Subclass of pipe_winsys */
+struct sw_pipe_winsys
+{
+   struct pipe_winsys Base;
+   /* no extra fields for now */
+};
+
+
+/** subclass of pipe_buffer */
+struct sw_pipe_buffer
+{
+   struct pipe_buffer Base;
+   boolean UserBuffer;  /** Is this a user-space buffer? */
+   void *Data;
+   void *Mapped;
+};
+
+
+/** cast wrapper */
+static INLINE struct sw_pipe_buffer *
+sw_pipe_buffer(struct pipe_buffer *b)
+{
+   return (struct sw_pipe_buffer *) b;
+}
+
+
+
+static const char *
+get_name(struct pipe_winsys *pws)
+{
+   return "software";
+}
+
+
+/** Create new pipe_buffer and allocate storage of given size */
+static struct pipe_buffer *
+buffer_create(struct pipe_winsys *pws, 
+              unsigned alignment, 
+              unsigned usage,
+              unsigned size)
+{
+   struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
+   if (!buffer)
+      return NULL;
+
+   buffer->Base.refcount = 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, MAX2(alignment, 16));
+
+   return &buffer->Base;
+}
+
+
+/**
+ * Create buffer which wraps user-space data.
+ */
+static struct pipe_buffer *
+user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
+{
+   struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
+   if (!buffer)
+      return NULL;
+
+   buffer->Base.refcount = 1;
+   buffer->Base.size = bytes;
+   buffer->UserBuffer = TRUE;
+   buffer->Data = ptr;
+
+   return &buffer->Base;
+}
+
+
+static void *
+buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, unsigned flags)
+{
+   struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
+   buffer->Mapped = buffer->Data;
+   return buffer->Mapped;
+}
+
+
+static void
+buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
+{
+   struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
+   buffer->Mapped = NULL;
+}
+
+
+static void
+buffer_destroy(struct pipe_winsys *pws, struct pipe_buffer *buf)
+{
+   struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
+
+   if (buffer->Data && !buffer->UserBuffer) {
+      align_free(buffer->Data);
+      buffer->Data = NULL;
+   }
+
+   free(buffer);
+}
+
+
+/**
+ * Called via winsys->surface_alloc() to create new surfaces.
+ */
+static struct pipe_surface *
+surface_alloc(struct pipe_winsys *ws)
+{
+   struct pipe_surface *surf = CALLOC_STRUCT(pipe_surface);
+   if (!surf)
+      return NULL;
+
+   surf->refcount = 1;
+   surf->winsys = ws;
+
+   return surf;
+}
+
+
+static void
+surface_release(struct pipe_winsys *winsys, struct pipe_surface **s)
+{
+   struct pipe_surface *surf = *s;
+   assert(!surf->texture);
+   surf->refcount--;
+   if (surf->refcount == 0) {
+      if (surf->buffer)
+         pipe_buffer_reference(winsys, &surf->buffer, NULL);
+      free(surf);
+   }
+   *s = NULL;
+}
+
+
+static void
+fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr,
+                struct pipe_fence_handle *fence)
+{
+   /* no-op */
+}
+
+
+static int
+fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
+                unsigned flag)
+{
+   /* no-op */
+   return 0;
+}
+
+
+static int
+fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
+             unsigned flag)
+{
+   /* no-op */
+   return 0;
+}
+
+
+/**
+ * Create/return a new pipe_winsys object.
+ */
+struct pipe_winsys *
+create_sw_winsys(void)
+{
+   struct sw_pipe_winsys *ws = CALLOC_STRUCT(sw_pipe_winsys);
+   if (!ws)
+      return NULL;
+
+   /* Fill in this struct with callbacks that pipe will need to
+    * communicate with the window system, buffer manager, etc. 
+    */
+   ws->Base.buffer_create = buffer_create;
+   ws->Base.user_buffer_create = user_buffer_create;
+   ws->Base.buffer_map = buffer_map;
+   ws->Base.buffer_unmap = buffer_unmap;
+   ws->Base.buffer_destroy = buffer_destroy;
+
+   ws->Base.surface_alloc = surface_alloc;
+   ws->Base.surface_alloc_storage = NULL; /* unused */
+   ws->Base.surface_release = surface_release;
+
+   ws->Base.fence_reference = fence_reference;
+   ws->Base.fence_signalled = fence_signalled;
+   ws->Base.fence_finish = fence_finish;
+
+   ws->Base.flush_frontbuffer = NULL; /* not implemented here! */
+
+   ws->Base.get_name = get_name;
+
+   return &ws->Base;
+}
diff --git a/src/gallium/winsys/egl_xlib/sw_winsys.h b/src/gallium/winsys/egl_xlib/sw_winsys.h
new file mode 100644 (file)
index 0000000..f96c5a1
--- /dev/null
@@ -0,0 +1,40 @@
+/**************************************************************************
+ * 
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#ifndef SW_WINSYS_H
+#define SW_WINSYS_H
+
+
+struct pipe_winsys;
+
+
+extern struct pipe_winsys *
+create_sw_winsys(void);
+
+
+#endif /* SW_WINSYS_H */