0,0 → 1,224 |
/* |
* 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 <strings.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, true); |
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, true); |
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; |
} |