haiku: Build Haiku's libGL from within Mesa
authorAlexander von Gluck IV <kallisti5@unixzen.com>
Tue, 1 Oct 2013 21:03:48 +0000 (21:03 +0000)
committerAlexander von Gluck IV <kallisti5@unixzen.com>
Fri, 4 Oct 2013 23:20:09 +0000 (18:20 -0500)
* This in essence means that Mesa would be
  taking control of Haiku's OpenGL kit.
* This works by dispatching renderers from the
  OpenGL add-ons directory

src/gallium/SConscript
src/gallium/targets/libgl-haiku/GLDispatcher.cpp [new file with mode: 0644]
src/gallium/targets/libgl-haiku/GLDispatcher.h [new file with mode: 0644]
src/gallium/targets/libgl-haiku/GLRenderer.cpp [new file with mode: 0644]
src/gallium/targets/libgl-haiku/GLRendererRoster.cpp [new file with mode: 0644]
src/gallium/targets/libgl-haiku/GLRendererRoster.h [new file with mode: 0644]
src/gallium/targets/libgl-haiku/GLView.cpp [new file with mode: 0644]
src/gallium/targets/libgl-haiku/SConscript [new file with mode: 0644]

index ca75f37f9d99f4a42816dc52fb036293888031f3..9a25ccafb10e77bb04a58963f6b169608c02b6d2 100644 (file)
@@ -122,6 +122,7 @@ if not env['embedded']:
     if env['platform'] == 'haiku':
         SConscript([
             'targets/haiku-softpipe/SConscript',
+            'targets/libgl-haiku/SConscript',
         ])
 
     if env['dri']:
diff --git a/src/gallium/targets/libgl-haiku/GLDispatcher.cpp b/src/gallium/targets/libgl-haiku/GLDispatcher.cpp
new file mode 100644 (file)
index 0000000..46b91d5
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000-2012 Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Brian Paul <brian.e.paul@gmail.com>
+ *             Philippe Houdoin <philippe.houdoin@free.fr>
+ *             Alexander von Gluck IV <kallisti5@unixzen.com>
+ */
+
+
+extern "C" {
+#include "glapi/glapi.h"
+#include "glapi/glapi_priv.h"
+
+/*
+ * NOTE: this file portion implements C-based dispatch of the OpenGL entrypoints
+ * (glAccum, glBegin, etc).
+ * This code IS NOT USED if we're compiling on an x86 system and using
+ * the glapi_x86.S assembly code.
+ */
+#if !(defined(USE_X86_ASM) || defined(USE_SPARC_ASM))
+
+#define KEYWORD1 PUBLIC
+#define KEYWORD2
+#define NAME(func) gl##func
+
+#define DISPATCH(func, args, msg)                                      \
+       const struct _glapi_table* dispatch;                                    \
+       dispatch = _glapi_Dispatch ? _glapi_Dispatch : _glapi_get_dispatch();\
+       (dispatch->func) args
+
+#define RETURN_DISPATCH(func, args, msg)                               \
+       const struct _glapi_table* dispatch;                                    \
+       dispatch = _glapi_Dispatch ? _glapi_Dispatch : _glapi_get_dispatch();\
+       return (dispatch->func) args
+
+#endif
+}
+
+
+/* NOTE: this file portion implement a thin OpenGL entrypoints dispatching
+       C++ wrapper class
+ */
+
+#include "GLDispatcher.h"
+
+BGLDispatcher::BGLDispatcher()
+{
+}
+
+
+BGLDispatcher::~BGLDispatcher()
+{
+}
+
+
+status_t
+BGLDispatcher::CheckTable(const struct _glapi_table* table)
+{
+       _glapi_check_table(table ? table : _glapi_get_dispatch());
+       return B_OK;
+}
+
+
+status_t
+BGLDispatcher::SetTable(struct _glapi_table* table)
+{
+       _glapi_set_dispatch(table);
+       return B_OK;
+}
diff --git a/src/gallium/targets/libgl-haiku/GLDispatcher.h b/src/gallium/targets/libgl-haiku/GLDispatcher.h
new file mode 100644 (file)
index 0000000..44bca8c
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000-2012 Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Brian Paul <brian.e.paul@gmail.com>
+ *             Philippe Houdoin <philippe.houdoin@free.fr>
+ */
+#ifndef GLDISPATCHER_H
+#define GLDISPATCHER_H
+
+
+#include <BeBuild.h>
+#include <GL/gl.h>
+#include <SupportDefs.h>
+
+#include "glheader.h"
+
+extern "C" {
+#include "glapi/glapi.h"
+}
+
+
+class BGLDispatcher
+{
+               // Private unimplemented copy constructors
+               BGLDispatcher(const BGLDispatcher &);
+               BGLDispatcher & operator=(const BGLDispatcher &);
+
+       public:
+               BGLDispatcher();
+               ~BGLDispatcher();
+
+               void                                    SetCurrentContext(void* context);
+               void*                                   CurrentContext();
+
+               struct _glapi_table*    Table();
+               status_t                                CheckTable(
+                                                                       const struct _glapi_table* dispatch = NULL);
+               status_t                                SetTable(struct _glapi_table* dispatch);
+               uint32                                  TableSize();
+
+               const _glapi_proc               operator[](const char* functionName);
+               const char*                             operator[](uint32 offset);
+
+               const _glapi_proc               AddressOf(const char* functionName);
+               uint32                                  OffsetOf(const char* functionName);
+};
+
+
+// Inlines methods
+inline void
+BGLDispatcher::SetCurrentContext(void* context)
+{
+       _glapi_set_context(context);
+}
+
+
+inline void*
+BGLDispatcher::CurrentContext()
+{
+       return _glapi_get_context();
+}
+
+
+inline struct _glapi_table*
+BGLDispatcher::Table()
+{
+       return _glapi_get_dispatch();
+}
+
+
+inline uint32
+BGLDispatcher::TableSize()
+{
+       return _glapi_get_dispatch_table_size();
+}
+
+
+inline const _glapi_proc
+BGLDispatcher::operator[](const char* functionName)
+{
+       return _glapi_get_proc_address(functionName);
+}
+
+
+inline const char*
+BGLDispatcher::operator[](uint32 offset)
+{
+       return _glapi_get_proc_name((GLuint) offset);
+}
+
+
+inline const _glapi_proc
+BGLDispatcher::AddressOf(const char* functionName)
+{
+       return _glapi_get_proc_address(functionName);
+}
+
+
+inline uint32
+BGLDispatcher::OffsetOf(const char* functionName)
+{
+       return (uint32) _glapi_get_proc_offset(functionName);
+}
+
+
+#endif // GLDISPATCHER_H
diff --git a/src/gallium/targets/libgl-haiku/GLRenderer.cpp b/src/gallium/targets/libgl-haiku/GLRenderer.cpp
new file mode 100644 (file)
index 0000000..4573a64
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2006-2008, Philippe Houdoin. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include <kernel/image.h>
+
+#include "GLRenderer.h"
+
+#include "GLDispatcher.h"
+
+
+BGLRenderer::BGLRenderer(BGLView* view, ulong glOptions,
+       BGLDispatcher* dispatcher)
+       :
+       fRefCount(1),
+       fView(view),
+       fOptions(glOptions),
+       fDispatcher(dispatcher)
+{
+}
+
+
+BGLRenderer::~BGLRenderer()
+{
+       delete fDispatcher;
+}
+
+
+void
+BGLRenderer::Acquire()
+{
+       atomic_add(&fRefCount, 1);
+}
+
+
+void
+BGLRenderer::Release()
+{
+       if (atomic_add(&fRefCount, -1) < 1)
+               delete this;
+}
+
+
+void
+BGLRenderer::LockGL()
+{
+}
+
+
+void
+BGLRenderer::UnlockGL()
+{
+}
+
+
+void
+BGLRenderer::SwapBuffers(bool VSync)
+{
+}
+
+
+void
+BGLRenderer::Draw(BRect updateRect)
+{
+}
+
+
+status_t
+BGLRenderer::CopyPixelsOut(BPoint source, BBitmap* dest)
+{
+       return B_ERROR;
+}
+
+
+status_t
+BGLRenderer::CopyPixelsIn(BBitmap* source, BPoint dest)
+{
+       return B_ERROR;
+}
+
+
+void
+BGLRenderer::FrameResized(float width, float height)
+{
+}
+
+
+void
+BGLRenderer::DirectConnected(direct_buffer_info* info)
+{
+}
+
+
+void
+BGLRenderer::EnableDirectMode(bool enabled)
+{
+}
+
+
+status_t BGLRenderer::_Reserved_Renderer_0(int32 n, void* p) { return B_ERROR; }
+status_t BGLRenderer::_Reserved_Renderer_1(int32 n, void* p) { return B_ERROR; }
+status_t BGLRenderer::_Reserved_Renderer_2(int32 n, void* p) { return B_ERROR; }
+status_t BGLRenderer::_Reserved_Renderer_3(int32 n, void* p) { return B_ERROR; }
+status_t BGLRenderer::_Reserved_Renderer_4(int32 n, void* p) { return B_ERROR; }
diff --git a/src/gallium/targets/libgl-haiku/GLRendererRoster.cpp b/src/gallium/targets/libgl-haiku/GLRendererRoster.cpp
new file mode 100644 (file)
index 0000000..70bc412
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2006-2012 Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Philippe Houdoin <philippe.houdoin@free.fr>
+ *             Alexander von Gluck IV <kallisti5@unixzen.com>
+ */
+
+
+#include <driver_settings.h>
+#include <image.h>
+
+#include <kernel/image.h>
+#include <system/safemode_defs.h>
+
+#include <Directory.h>
+#include <FindDirectory.h>
+#include <Path.h>
+#include <String.h>
+#include "GLDispatcher.h"
+#include "GLRendererRoster.h"
+
+#include <new>
+#include <string.h>
+
+
+extern "C" status_t _kern_get_safemode_option(const char* parameter,
+       char* buffer, size_t* _bufferSize);
+
+
+GLRendererRoster::GLRendererRoster(BGLView* view, ulong options)
+       :
+       fNextID(0),
+       fView(view),
+       fOptions(options),
+       fSafeMode(false),
+       fABISubDirectory(NULL)
+{
+       char parameter[32];
+       size_t parameterLength = sizeof(parameter);
+
+       if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE,
+               parameter, &parameterLength) == B_OK) {
+               if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
+                       || !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
+                       || !strcasecmp(parameter, "enable") || !strcmp(parameter, "1"))
+                       fSafeMode = true;
+       }
+
+       if (_kern_get_safemode_option(B_SAFEMODE_DISABLE_USER_ADD_ONS,
+               parameter, &parameterLength) == B_OK) {
+               if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
+                       || !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
+                       || !strcasecmp(parameter, "enable") || !strcmp(parameter, "1"))
+                       fSafeMode = true;
+       }
+
+       // We might run in compatibility mode on a system with a different ABI. The
+       // renderers matching our ABI can usually be found in respective
+       // subdirectories of the opengl add-ons directories.
+       system_info info;
+       if (get_system_info(&info) == B_OK
+               && (info.abi & B_HAIKU_ABI_MAJOR)
+                       != (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR)) {
+                       switch (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR) {
+                               case B_HAIKU_ABI_GCC_2:
+                                       fABISubDirectory = "gcc2";
+                                       break;
+                               case B_HAIKU_ABI_GCC_4:
+                                       fABISubDirectory = "gcc4";
+                                       break;
+                       }
+       }
+
+       AddDefaultPaths();
+}
+
+
+GLRendererRoster::~GLRendererRoster()
+{
+
+}
+
+
+BGLRenderer*
+GLRendererRoster::GetRenderer(int32 id)
+{
+       RendererMap::const_iterator iterator = fRenderers.find(id);
+       if (iterator == fRenderers.end())
+               return NULL;
+
+       struct renderer_item item = iterator->second;
+       return item.renderer;
+}
+
+
+void
+GLRendererRoster::AddDefaultPaths()
+{
+       // add user directories first, so that they can override system renderers
+       const directory_which paths[] = {
+               B_USER_NONPACKAGED_ADDONS_DIRECTORY,
+               B_USER_ADDONS_DIRECTORY,
+               B_COMMON_NONPACKAGED_ADDONS_DIRECTORY,
+               B_COMMON_ADDONS_DIRECTORY,
+               B_SYSTEM_ADDONS_DIRECTORY,
+       };
+
+       for (uint32 i = fSafeMode ? 4 : 0;
+               i < sizeof(paths) / sizeof(paths[0]); i++) {
+               BPath path;
+               status_t status = find_directory(paths[i], &path, true);
+               if (status == B_OK && path.Append("opengl") == B_OK)
+                       AddPath(path.Path());
+       }
+}
+
+
+status_t
+GLRendererRoster::AddPath(const char* path)
+{
+       BDirectory directory(path);
+       status_t status = directory.InitCheck();
+       if (status < B_OK)
+               return status;
+
+       // if a subdirectory for our ABI exists, use that instead
+       if (fABISubDirectory != NULL) {
+               BEntry entry(&directory, fABISubDirectory);
+               if (entry.IsDirectory()) {
+                       status = directory.SetTo(&entry);
+                       if (status != B_OK)
+                               return status;
+               }
+       }
+
+       node_ref nodeRef;
+       status = directory.GetNodeRef(&nodeRef);
+       if (status < B_OK)
+               return status;
+
+       int32 count = 0;
+       int32 files = 0;
+
+       entry_ref ref;
+       BEntry entry;
+       while (directory.GetNextRef(&ref) == B_OK) {
+               entry.SetTo(&ref);
+               if (entry.InitCheck() == B_OK && !entry.IsFile())
+                       continue;
+
+               if (CreateRenderer(ref) == B_OK)
+                       count++;
+
+               files++;
+       }
+
+       if (files != 0 && count == 0)
+               return B_BAD_VALUE;
+
+       return B_OK;
+}
+
+
+status_t
+GLRendererRoster::AddRenderer(BGLRenderer* renderer,
+       image_id image, const entry_ref* ref, ino_t node)
+{
+       renderer_item item;
+       item.renderer = renderer;
+       item.image = image;
+       item.node = node;
+       if (ref != NULL)
+               item.ref = *ref;
+
+       try {
+               fRenderers[fNextID] = item;
+       } catch (...) {
+               return B_NO_MEMORY;
+       }
+
+       renderer->fOwningRoster = this;
+       renderer->fID = fNextID++;
+       return B_OK;
+}
+
+
+status_t
+GLRendererRoster::CreateRenderer(const entry_ref& ref)
+{
+       BEntry entry(&ref);
+       node_ref nodeRef;
+       status_t status = entry.GetNodeRef(&nodeRef);
+       if (status < B_OK)
+               return status;
+
+       BPath path(&ref);
+       image_id image = load_add_on(path.Path());
+       if (image < B_OK)
+               return image;
+
+       BGLRenderer* (*instantiate_renderer)
+               (BGLView* view, ulong options, BGLDispatcher* dispatcher);
+
+       status = get_image_symbol(image, "instantiate_gl_renderer",
+               B_SYMBOL_TYPE_TEXT, (void**)&instantiate_renderer);
+       if (status == B_OK) {
+               BGLRenderer* renderer
+                       = instantiate_renderer(fView, fOptions, new BGLDispatcher());
+               if (!renderer) {
+                       unload_add_on(image);
+                       return B_UNSUPPORTED;
+               }
+
+               if (AddRenderer(renderer, image, &ref, nodeRef.node) != B_OK) {
+                       renderer->Release();
+                       // this will delete the renderer
+                       unload_add_on(image);
+               }
+               return B_OK;
+       }
+       unload_add_on(image);
+
+       return status;
+}
diff --git a/src/gallium/targets/libgl-haiku/GLRendererRoster.h b/src/gallium/targets/libgl-haiku/GLRendererRoster.h
new file mode 100644 (file)
index 0000000..5c8da27
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2006-2012, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Philippe Houdoin <philippe.houdoin@free.fr>
+ */
+#ifndef _GLRENDERER_ROSTER_H
+#define _GLRENDERER_ROSTER_H
+
+
+#include <GLRenderer.h>
+
+#include <map>
+
+
+struct renderer_item {
+       BGLRenderer* renderer;
+       entry_ref       ref;
+       ino_t           node;
+       image_id        image;
+};
+
+typedef std::map<renderer_id, renderer_item> RendererMap;
+
+
+class GLRendererRoster {
+       public:
+               GLRendererRoster(BGLView* view, ulong options);
+               virtual ~GLRendererRoster();
+
+               BGLRenderer* GetRenderer(int32 id = 0);
+
+       private:
+               void AddDefaultPaths();
+               status_t AddPath(const char* path);
+               status_t AddRenderer(BGLRenderer* renderer,
+                       image_id image, const entry_ref* ref, ino_t node);
+               status_t CreateRenderer(const entry_ref& ref);
+
+               RendererMap     fRenderers;
+               int32           fNextID;
+               BGLView*        fView;
+               ulong           fOptions;
+               bool            fSafeMode;
+               const char*     fABISubDirectory;
+
+};
+
+
+#endif /* _GLRENDERER_ROSTER_H */
diff --git a/src/gallium/targets/libgl-haiku/GLView.cpp b/src/gallium/targets/libgl-haiku/GLView.cpp
new file mode 100644 (file)
index 0000000..9ae5b5c
--- /dev/null
@@ -0,0 +1,643 @@
+/*
+ * Copyright 2006-2012, Haiku. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Jérôme Duval, korli@users.berlios.de
+ *             Philippe Houdoin, philippe.houdoin@free.fr
+ *             Stefano Ceccherini, burton666@libero.it
+ */
+
+#include <kernel/image.h>
+
+#include <GLView.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <DirectWindow.h>
+#include <GLRenderer.h>
+
+#include "interface/DirectWindowPrivate.h"
+#include "GLDispatcher.h"
+#include "GLRendererRoster.h"
+
+
+struct glview_direct_info {
+       direct_buffer_info* direct_info;
+       bool direct_connected;
+       bool enable_direct_mode;
+
+       glview_direct_info();
+       ~glview_direct_info();
+};
+
+
+BGLView::BGLView(BRect rect, const char* name, ulong resizingMode, ulong mode,
+       ulong options)
+       :
+       BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS),
+               //  | B_FULL_UPDATE_ON_RESIZE)
+       fGc(NULL),
+       fOptions(options),
+       fDitherCount(0),
+       fDrawLock("BGLView draw lock"),
+       fDisplayLock("BGLView display lock"),
+       fClipInfo(NULL),
+       fRenderer(NULL),
+       fRoster(NULL),
+       fDitherMap(NULL)
+{
+       fRoster = new GLRendererRoster(this, options);
+}
+
+
+BGLView::~BGLView()
+{
+       delete fClipInfo;
+       if (fRenderer)
+               fRenderer->Release();
+}
+
+
+void
+BGLView::LockGL()
+{
+       // TODO: acquire the OpenGL API lock it on this glview
+
+       fDisplayLock.Lock();
+       if (fRenderer)
+               fRenderer->LockGL();
+}
+
+
+void
+BGLView::UnlockGL()
+{
+       if (fRenderer)
+               fRenderer->UnlockGL();
+       fDisplayLock.Unlock();
+
+       // TODO: release the GL API lock to others glviews
+}
+
+
+void
+BGLView::SwapBuffers()
+{
+       SwapBuffers(false);
+}
+
+
+void
+BGLView::SwapBuffers(bool vSync)
+{
+       if (fRenderer) {
+               _LockDraw();
+               fRenderer->SwapBuffers(vSync);
+               _UnlockDraw();
+       }
+}
+
+
+BView*
+BGLView::EmbeddedView()
+{
+       return NULL;
+}
+
+
+void*
+BGLView::GetGLProcAddress(const char* procName)
+{
+       BGLDispatcher* glDispatcher = NULL;
+
+       if (fRenderer)
+               glDispatcher = fRenderer->GLDispatcher();
+
+       if (glDispatcher)
+               return (void*)glDispatcher->AddressOf(procName);
+
+       return NULL;
+}
+
+
+status_t
+BGLView::CopyPixelsOut(BPoint source, BBitmap* dest)
+{
+       if (!fRenderer)
+               return B_ERROR;
+
+       if (!dest || !dest->Bounds().IsValid())
+               return B_BAD_VALUE;
+
+       return fRenderer->CopyPixelsOut(source, dest);
+}
+
+
+status_t
+BGLView::CopyPixelsIn(BBitmap* source, BPoint dest)
+{
+       if (!fRenderer)
+               return B_ERROR;
+
+       if (!source || !source->Bounds().IsValid())
+               return B_BAD_VALUE;
+
+       return fRenderer->CopyPixelsIn(source, dest);
+}
+
+
+/*!    Mesa's GLenum is not ulong but uint, so we can't use GLenum
+       without breaking this method signature.
+       Instead, we have to use the effective BeOS's SGI OpenGL GLenum type:
+       unsigned long.
+ */
+void
+BGLView::ErrorCallback(unsigned long errorCode)
+{
+       char msg[32];
+       sprintf(msg, "GL: Error code $%04lx.", errorCode);
+       // TODO: under BeOS R5, it call debugger(msg);
+       fprintf(stderr, "%s\n", msg);
+}
+
+
+void
+BGLView::Draw(BRect updateRect)
+{
+       if (fRenderer) {
+               _LockDraw();
+               fRenderer->Draw(updateRect);
+               _UnlockDraw();
+               return;
+       }
+       // TODO: auto-size and center the string
+       MovePenTo(8, 32);
+       DrawString("No OpenGL renderer available!");
+}
+
+
+void
+BGLView::AttachedToWindow()
+{
+       BView::AttachedToWindow();
+
+       fBounds = Bounds();
+       for (BView* view = this; view != NULL; view = view->Parent())
+               view->ConvertToParent(&fBounds);
+
+       fRenderer = fRoster->GetRenderer();
+       if (fRenderer != NULL) {
+               // Jackburton: The following code was commented because it doesn't look
+               // good in "direct" mode:
+               // when the window is moved, the app_server doesn't paint the view's
+               // background, and the stuff behind the window itself shows up.
+               // Setting the view color to black, instead, looks a bit more elegant.
+#if 0
+               // Don't paint white window background when resized
+               SetViewColor(B_TRANSPARENT_32_BIT);
+#else
+               SetViewColor(0, 0, 0);
+#endif
+
+               // Set default OpenGL viewport:
+               LockGL();
+               glViewport(0, 0, Bounds().IntegerWidth(), Bounds().IntegerHeight());
+               UnlockGL();
+               fRenderer->FrameResized(Bounds().IntegerWidth(),
+                       Bounds().IntegerHeight());
+
+               if (fClipInfo) {
+                       fRenderer->DirectConnected(fClipInfo->direct_info);
+                       fRenderer->EnableDirectMode(fClipInfo->enable_direct_mode);
+               }
+
+               return;
+       }
+
+       fprintf(stderr, "no renderer found! \n");
+
+       // No Renderer, no rendering. Setup a minimal "No Renderer" string drawing
+       // context
+       SetFont(be_bold_font);
+       // SetFontSize(16);
+}
+
+
+void
+BGLView::AllAttached()
+{
+       BView::AllAttached();
+}
+
+
+void
+BGLView::DetachedFromWindow()
+{
+       if (fRenderer)
+               fRenderer->Release();
+       fRenderer = NULL;
+
+       BView::DetachedFromWindow();
+}
+
+
+void
+BGLView::AllDetached()
+{
+       BView::AllDetached();
+}
+
+
+void
+BGLView::FrameResized(float width, float height)
+{
+       fBounds = Bounds();
+       for (BView* v = this; v; v = v->Parent())
+               v->ConvertToParent(&fBounds);
+
+       if (fRenderer) {
+               LockGL();
+               _LockDraw();
+               _CallDirectConnected();
+               fRenderer->FrameResized(width, height);
+               _UnlockDraw();
+               UnlockGL();
+       }
+
+       BView::FrameResized(width, height);
+}
+
+
+status_t
+BGLView::Perform(perform_code d, void* arg)
+{
+       return BView::Perform(d, arg);
+}
+
+
+status_t
+BGLView::Archive(BMessage* data, bool deep) const
+{
+       return BView::Archive(data, deep);
+}
+
+
+void
+BGLView::MessageReceived(BMessage* msg)
+{
+       BView::MessageReceived(msg);
+}
+
+
+void
+BGLView::SetResizingMode(uint32 mode)
+{
+       BView::SetResizingMode(mode);
+}
+
+
+void
+BGLView::GetPreferredSize(float* _width, float* _height)
+{
+       if (_width)
+               *_width = 0;
+       if (_height)
+               *_height = 0;
+}
+
+
+void
+BGLView::Show()
+{
+       BView::Show();
+}
+
+
+void
+BGLView::Hide()
+{
+       BView::Hide();
+}
+
+
+BHandler*
+BGLView::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier,
+       int32 form, const char* property)
+{
+       return BView::ResolveSpecifier(msg, index, specifier, form, property);
+}
+
+
+status_t
+BGLView::GetSupportedSuites(BMessage* data)
+{
+       return BView::GetSupportedSuites(data);
+}
+
+
+void
+BGLView::DirectConnected(direct_buffer_info* info)
+{
+       if (fClipInfo == NULL) {
+               fClipInfo = new (std::nothrow) glview_direct_info();
+               if (fClipInfo == NULL)
+                       return;
+       }
+
+       direct_buffer_info* localInfo = fClipInfo->direct_info;
+
+       switch (info->buffer_state & B_DIRECT_MODE_MASK) {
+               case B_DIRECT_START:
+                       fClipInfo->direct_connected = true;
+                       memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
+                       _UnlockDraw();
+                       break;
+
+               case B_DIRECT_MODIFY:
+                       _LockDraw();
+                       memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
+                       _UnlockDraw();
+                       break;
+
+               case B_DIRECT_STOP:
+                       fClipInfo->direct_connected = false;
+                       _LockDraw();
+                       break;
+       }
+
+       if (fRenderer)
+               _CallDirectConnected();
+}
+
+
+void
+BGLView::EnableDirectMode(bool enabled)
+{
+       if (fRenderer)
+               fRenderer->EnableDirectMode(enabled);
+       if (fClipInfo == NULL) {
+               fClipInfo = new (std::nothrow) glview_direct_info();
+               if (fClipInfo == NULL)
+                       return;
+       }
+
+       fClipInfo->enable_direct_mode = enabled;
+}
+
+
+void
+BGLView::_LockDraw()
+{
+       if (!fClipInfo || !fClipInfo->enable_direct_mode)
+               return;
+
+       fDrawLock.Lock();
+}
+
+
+void
+BGLView::_UnlockDraw()
+{
+       if (!fClipInfo || !fClipInfo->enable_direct_mode)
+               return;
+
+       fDrawLock.Unlock();
+}
+
+
+void
+BGLView::_CallDirectConnected()
+{
+       if (!fClipInfo)
+               return;
+
+       direct_buffer_info* localInfo = fClipInfo->direct_info;
+       direct_buffer_info* info = (direct_buffer_info*)malloc(
+               DIRECT_BUFFER_INFO_AREA_SIZE);
+       if (info == NULL)
+               return;
+
+       memcpy(info, localInfo, DIRECT_BUFFER_INFO_AREA_SIZE);
+
+       // Collect the rects into a BRegion, then clip to the view's bounds
+       BRegion region;
+       for (uint32 c = 0; c < localInfo->clip_list_count; c++)
+               region.Include(localInfo->clip_list[c]);
+       BRegion boundsRegion = fBounds.OffsetByCopy(localInfo->window_bounds.left,
+               localInfo->window_bounds.top);
+       info->window_bounds = boundsRegion.RectAtInt(0);
+               // window_bounds are now view bounds
+       region.IntersectWith(&boundsRegion);
+
+       info->clip_list_count = region.CountRects();
+       info->clip_bounds = region.FrameInt();
+
+       for (uint32 c = 0; c < info->clip_list_count; c++)
+               info->clip_list[c] = region.RectAtInt(c);
+       fRenderer->DirectConnected(info);
+       free(info);
+}
+
+
+//---- virtual reserved methods ----------
+
+
+void BGLView::_ReservedGLView1() {}
+void BGLView::_ReservedGLView2() {}
+void BGLView::_ReservedGLView3() {}
+void BGLView::_ReservedGLView4() {}
+void BGLView::_ReservedGLView5() {}
+void BGLView::_ReservedGLView6() {}
+void BGLView::_ReservedGLView7() {}
+void BGLView::_ReservedGLView8() {}
+
+
+// #pragma mark -
+
+
+// BeOS compatibility: contrary to others BView's contructors,
+// BGLView one wants a non-const name argument.
+BGLView::BGLView(BRect rect, char* name, ulong resizingMode, ulong mode,
+       ulong options)
+       :
+       BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS),
+       fGc(NULL),
+       fOptions(options),
+       fDitherCount(0),
+       fDrawLock("BGLView draw lock"),
+       fDisplayLock("BGLView display lock"),
+       fClipInfo(NULL),
+       fRenderer(NULL),
+       fRoster(NULL),
+       fDitherMap(NULL)
+{
+       fRoster = new GLRendererRoster(this, options);
+}
+
+
+#if 0
+// TODO: implement BGLScreen class...
+
+
+BGLScreen::BGLScreen(char* name, ulong screenMode, ulong options,
+               status_t* error, bool debug)
+       :
+       BWindowScreen(name, screenMode, error, debug)
+{
+}
+
+
+BGLScreen::~BGLScreen()
+{
+}
+
+
+void
+BGLScreen::LockGL()
+{
+}
+
+
+void
+BGLScreen::UnlockGL()
+{
+}
+
+
+void
+BGLScreen::SwapBuffers()
+{
+}
+
+
+void
+BGLScreen::ErrorCallback(unsigned long errorCode)
+{
+       // Mesa's GLenum is not ulong but uint!
+       char msg[32];
+       sprintf(msg, "GL: Error code $%04lx.", errorCode);
+       // debugger(msg);
+       fprintf(stderr, "%s\n", msg);
+       return;
+}
+
+
+void
+BGLScreen::ScreenConnected(bool enabled)
+{
+}
+
+
+void
+BGLScreen::FrameResized(float width, float height)
+{
+       return BWindowScreen::FrameResized(width, height);
+}
+
+
+status_t
+BGLScreen::Perform(perform_code d, void* arg)
+{
+       return BWindowScreen::Perform(d, arg);
+}
+
+
+status_t
+BGLScreen::Archive(BMessage* data, bool deep) const
+{
+       return BWindowScreen::Archive(data, deep);
+}
+
+
+void
+BGLScreen::MessageReceived(BMessage* msg)
+{
+       BWindowScreen::MessageReceived(msg);
+}
+
+
+void
+BGLScreen::Show()
+{
+       BWindowScreen::Show();
+}
+
+
+void
+BGLScreen::Hide()
+{
+       BWindowScreen::Hide();
+}
+
+
+BHandler*
+BGLScreen::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier,
+       int32 form, const char* property)
+{
+       return BWindowScreen::ResolveSpecifier(msg, index, specifier,
+               form, property);
+}
+
+
+status_t
+BGLScreen::GetSupportedSuites(BMessage* data)
+{
+       return BWindowScreen::GetSupportedSuites(data);
+}
+
+
+//---- virtual reserved methods ----------
+
+void BGLScreen::_ReservedGLScreen1() {}
+void BGLScreen::_ReservedGLScreen2() {}
+void BGLScreen::_ReservedGLScreen3() {}
+void BGLScreen::_ReservedGLScreen4() {}
+void BGLScreen::_ReservedGLScreen5() {}
+void BGLScreen::_ReservedGLScreen6() {}
+void BGLScreen::_ReservedGLScreen7() {}
+void BGLScreen::_ReservedGLScreen8() {}
+#endif
+
+
+const char* color_space_name(color_space space)
+{
+#define C2N(a) case a: return #a
+
+       switch (space) {
+       C2N(B_RGB24);
+       C2N(B_RGB32);
+       C2N(B_RGBA32);
+       C2N(B_RGB32_BIG);
+       C2N(B_RGBA32_BIG);
+       C2N(B_GRAY8);
+       C2N(B_GRAY1);
+       C2N(B_RGB16);
+       C2N(B_RGB15);
+       C2N(B_RGBA15);
+       C2N(B_CMAP8);
+       default:
+               return "Unknown!";
+       };
+
+#undef C2N
+};
+
+
+glview_direct_info::glview_direct_info()
+{
+       // TODO: See direct_window_data() in app_server's ServerWindow.cpp
+       direct_info = (direct_buffer_info*)calloc(1, DIRECT_BUFFER_INFO_AREA_SIZE);
+       direct_connected = false;
+       enable_direct_mode = false;
+}
+
+
+glview_direct_info::~glview_direct_info()
+{
+       free(direct_info);
+}
+
diff --git a/src/gallium/targets/libgl-haiku/SConscript b/src/gallium/targets/libgl-haiku/SConscript
new file mode 100644 (file)
index 0000000..2e6b628
--- /dev/null
@@ -0,0 +1,34 @@
+#######################################################################
+# SConscript for Haiku OpenGL kit
+
+Import('*')
+
+env = env.Clone()
+
+env.Append(CPPPATH = [
+    '#/src/mapi',
+    '#/src/mesa',
+    '#/src/mesa/main',
+    '/boot/system/develop/headers/private',
+    Dir('../../../mapi'), # src/mapi build path for python-generated GL API files/headers
+])
+
+env.Prepend(LIBS = [
+    glapi
+])
+
+sources = [
+    'GLView.cpp',
+    'GLRenderer.cpp',
+    'GLRendererRoster.cpp',
+    'GLDispatcher.cpp',
+]
+
+# libGL.so
+libgl = env.SharedLibrary(
+    target ='GL',
+    source = sources,
+    SHLIBSUFFIX = env['SHLIBSUFFIX'],
+)
+
+env.Alias('libgl-haiku', libgl)