python: Obtain pipe_screen/pipe_context from the system's OpenGL driver.
authorJosé Fonseca <jfonseca@vmware.com>
Thu, 16 Jul 2009 10:19:06 +0000 (11:19 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Thu, 16 Jul 2009 10:22:56 +0000 (11:22 +0100)
src/gallium/state_trackers/python/SConscript
src/gallium/state_trackers/python/st_hardpipe_winsys.c

index 1581182aec2f8788a0c6ef912e087cecfe36e14d..ec385e7c447f841672f927a88567561c5f6e6923 100644 (file)
@@ -15,6 +15,19 @@ if 'python' in env['statetrackers']:
     
     env.Append(CPPPATH = '.')
 
+    if env['platform'] == 'windows':
+        env.Append(LIBS = [
+            'opengl32',
+            'gdi32',
+            'user32',
+            'kernel32',
+        ])
+    else:
+        env.Append(LIBS = [
+               'GL',
+            'X11',
+        ])
+
     pyst = env.ConvenienceLibrary(
         target = 'pyst',
         source = [
index 8b33c70fd7111e44ae39531c8691c7aeb7f08c9a..43aaaabf2a194f838baf8ae7eb7743860a1e31b0 100644 (file)
 
 /**
  * @file
- * Stub for hardware pipe driver support.
+ * Get a hardware accelerated Gallium screen/context from the OpenGL driver.
  */
 
 
 #include "pipe/p_compiler.h"
 
+#ifdef PIPE_OS_WINDOWS
+#include <windows.h>
+#include <GL/gl.h>
+#else
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+#endif
+
 #include "st_winsys.h"
 
 
+typedef struct pipe_screen * (GLAPIENTRY *PFNGETGALLIUMSCREENMESAPROC) (void);
+typedef struct pipe_context * (GLAPIENTRY* PFNCREATEGALLIUMCONTEXTMESAPROC) (void);
+
+static PFNGETGALLIUMSCREENMESAPROC pfnGetGalliumScreenMESA = NULL;
+static PFNCREATEGALLIUMCONTEXTMESAPROC pfnCreateGalliumContextMESA = NULL;
+
+
 /* XXX: Force init_gallium symbol to be linked */
 extern void init_gallium(void);
 void (*force_init_gallium_linkage)(void) = &init_gallium;
 
 
+#ifdef PIPE_OS_WINDOWS
+
+static INLINE boolean
+st_hardpipe_load(void)
+{
+   WNDCLASS wc;
+   HWND hwnd;
+   HGLRC hglrc;
+   HDC hdc;
+   PIXELFORMATDESCRIPTOR pfd;
+   int iPixelFormat;
+
+   if(pfnGetGalliumScreenMESA && pfnCreateGalliumContextMESA)
+      return TRUE;
+
+   memset(&wc, 0, sizeof wc);
+   wc.lpfnWndProc = DefWindowProc;
+   wc.lpszClassName = "gallium";
+   wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
+   RegisterClass(&wc);
+
+   hwnd = CreateWindow(wc.lpszClassName, "gallium", 0, 0, 0, 0, 0, NULL, 0, wc.hInstance, NULL);
+   if (!hwnd)
+      return FALSE;
+
+   hdc = GetDC(hwnd);
+   if (!hdc)
+      return FALSE;
+
+   pfd.cColorBits = 3;
+   pfd.cRedBits = 1;
+   pfd.cGreenBits = 1;
+   pfd.cBlueBits = 1;
+   pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+   pfd.iLayerType = PFD_MAIN_PLANE;
+   pfd.iPixelType = PFD_TYPE_RGBA;
+   pfd.nSize = sizeof(pfd);
+   pfd.nVersion = 1;
+
+   iPixelFormat = ChoosePixelFormat(hdc, &pfd);
+   if (!iPixelFormat) {
+      pfd.dwFlags |= PFD_DOUBLEBUFFER;
+      iPixelFormat = ChoosePixelFormat(hdc, &pfd);
+   }
+   if (!iPixelFormat)
+      return FALSE;
+
+   SetPixelFormat(hdc, iPixelFormat, &pfd);
+   hglrc = wglCreateContext(hdc);
+   if (!hglrc)
+      return FALSE;
+
+   if (!wglMakeCurrent(hdc, hglrc))
+      return FALSE;
+
+   pfnGetGalliumScreenMESA = (PFNGETGALLIUMSCREENMESAPROC)wglGetProcAddress("wglGetGalliumScreenMESA");
+   if(!pfnGetGalliumScreenMESA)
+      return FALSE;
+
+   pfnCreateGalliumContextMESA = (PFNCREATEGALLIUMCONTEXTMESAPROC)wglGetProcAddress("wglCreateGalliumContextMESA");
+   if(!pfnCreateGalliumContextMESA)
+      return FALSE;
+
+   DestroyWindow(hwnd);
+
+   return TRUE;
+}
+
+#else
+
+static INLINE boolean
+st_hardpipe_load(void)
+{
+   Display *dpy;
+   int scrnum;
+   Window root;
+   int attribSingle[] = {
+      GLX_RGBA,
+      GLX_RED_SIZE, 1,
+      GLX_GREEN_SIZE, 1,
+      GLX_BLUE_SIZE, 1,
+      None };
+   int attribDouble[] = {
+      GLX_RGBA,
+      GLX_RED_SIZE, 1,
+      GLX_GREEN_SIZE, 1,
+      GLX_BLUE_SIZE, 1,
+      GLX_DOUBLEBUFFER,
+      None };
+   XVisualInfo *visinfo;
+   GLXContext ctx = NULL;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   int width = 100, height = 100;
+   Window win;
+
+   dpy = XOpenDisplay(NULL);
+   if (!dpy)
+      return FALSE;
+
+   scrnum = 0;
+   
+   root = RootWindow(dpy, scrnum);
+
+   visinfo = glXChooseVisual(dpy, scrnum, attribSingle);
+   if (!visinfo)
+      visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
+   if (!visinfo)
+      return FALSE;
+      
+   ctx = glXCreateContext( dpy, visinfo, NULL, True );
+
+   if (!ctx)
+      return FALSE;
+
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask;
+   
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+   
+   win = XCreateWindow(dpy, root, 0, 0, width, height,
+                       0, visinfo->depth, InputOutput,
+                       visinfo->visual, mask, &attr);
+
+   if (!glXMakeCurrent(dpy, win, ctx))
+      return FALSE;
+
+   pfnGetGalliumScreenMESA = (PFNGETGALLIUMSCREENMESAPROC)glXGetProcAddressARB((const GLubyte *)"glXGetGalliumScreenMESA");
+   if(!pfnGetGalliumScreenMESA)
+      return FALSE;
+
+   pfnCreateGalliumContextMESA = (PFNCREATEGALLIUMCONTEXTMESAPROC)glXGetProcAddressARB((const GLubyte *)"glXCreateGalliumContextMESA");
+   if(!pfnCreateGalliumContextMESA)
+      return FALSE;
+
+   glXDestroyContext(dpy, ctx);
+   XFree(visinfo);
+   XDestroyWindow(dpy, win);
+   XCloseDisplay(dpy);
+
+   return TRUE;
+}
+
+#endif
+
+
 static struct pipe_screen *
 st_hardpipe_screen_create(void)
 {
-   return st_softpipe_winsys.screen_create();
+   if(st_hardpipe_load())
+      return pfnGetGalliumScreenMESA();
+   else
+      return st_softpipe_winsys.screen_create();
 }
 
 
 static struct pipe_context *
 st_hardpipe_context_create(struct pipe_screen *screen)
 {
-   return st_softpipe_winsys.context_create(screen);
+   if(st_hardpipe_load()) {
+      if(screen == pfnGetGalliumScreenMESA())
+         return pfnCreateGalliumContextMESA();
+      else
+         return NULL;
+   }
+   else
+      return st_softpipe_winsys.context_create(screen);
 }