diff options
author | Alexander von Gluck IV <[email protected]> | 2013-12-31 15:39:49 -0600 |
---|---|---|
committer | Alexander von Gluck IV <[email protected]> | 2014-01-06 15:50:21 -0600 |
commit | 61ef697afc0ad509dcabdecfc424f27b5966969c (patch) | |
tree | b099044ff97e9a0f4522b8c59adaaec82d6ace28 /src/hgl/GLRendererRoster.cpp | |
parent | b236314a1107214210c429295fac8a5bdf457772 (diff) |
haiku libGL: Move from gallium target to src/hgl
* The Haiku renderers need to link to libGL to function properly
in all usage contexts. As mesa drivers build before gallium
targets, we couldn't properly link the mesa swrast driver to
the gallium libGL target for Haiku.
* This is likely better as it mimics how glx is laid out ensuring
the Haiku libGL is better understood.
* All renderers properly link in libGL now.
Acked-by: Brian Paul <[email protected]>
Diffstat (limited to 'src/hgl/GLRendererRoster.cpp')
-rw-r--r-- | src/hgl/GLRendererRoster.cpp | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/src/hgl/GLRendererRoster.cpp b/src/hgl/GLRendererRoster.cpp new file mode 100644 index 00000000000..1712a871c98 --- /dev/null +++ b/src/hgl/GLRendererRoster.cpp @@ -0,0 +1,224 @@ +/* + * Copyright 2006-2012 Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Philippe Houdoin <[email protected]> + * Alexander von Gluck IV <[email protected]> + */ + + +#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, ¶meterLength) == 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, ¶meterLength) == 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_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; +} |