1af69d88dSmrg/* 2af69d88dSmrg * Copyright 2006-2012 Haiku, Inc. All Rights Reserved. 3af69d88dSmrg * Distributed under the terms of the MIT License. 4af69d88dSmrg * 5af69d88dSmrg * Authors: 6af69d88dSmrg * Philippe Houdoin <philippe.houdoin@free.fr> 7af69d88dSmrg * Alexander von Gluck IV <kallisti5@unixzen.com> 8af69d88dSmrg */ 9af69d88dSmrg 10af69d88dSmrg 11af69d88dSmrg#include <driver_settings.h> 12af69d88dSmrg#include <image.h> 13af69d88dSmrg 14af69d88dSmrg#include <kernel/image.h> 157ec681f3Smrg#include <private/system/safemode_defs.h> 16af69d88dSmrg 17af69d88dSmrg#include <Directory.h> 18af69d88dSmrg#include <FindDirectory.h> 19af69d88dSmrg#include <Path.h> 2001e04c3fSmrg#include <strings.h> 21af69d88dSmrg#include "GLRendererRoster.h" 22af69d88dSmrg 23af69d88dSmrg#include <new> 24af69d88dSmrg#include <string.h> 257ec681f3Smrg#include <stdio.h> 26af69d88dSmrg 27af69d88dSmrg 28af69d88dSmrgextern "C" status_t _kern_get_safemode_option(const char* parameter, 29af69d88dSmrg char* buffer, size_t* _bufferSize); 30af69d88dSmrg 317ec681f3SmrgGLRendererRoster *GLRendererRoster::fInstance = NULL; 32af69d88dSmrg 337ec681f3SmrgGLRendererRoster *GLRendererRoster::Roster() 347ec681f3Smrg{ 357ec681f3Smrg if (fInstance == NULL) { 367ec681f3Smrg fInstance = new GLRendererRoster(); 377ec681f3Smrg } 387ec681f3Smrg return fInstance; 397ec681f3Smrg} 407ec681f3Smrg 417ec681f3SmrgGLRendererRoster::GLRendererRoster() 42af69d88dSmrg : 43af69d88dSmrg fSafeMode(false), 44af69d88dSmrg fABISubDirectory(NULL) 45af69d88dSmrg{ 46af69d88dSmrg char parameter[32]; 47af69d88dSmrg size_t parameterLength = sizeof(parameter); 48af69d88dSmrg 49af69d88dSmrg if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, 50af69d88dSmrg parameter, ¶meterLength) == B_OK) { 51af69d88dSmrg if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on") 52af69d88dSmrg || !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes") 53af69d88dSmrg || !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) 54af69d88dSmrg fSafeMode = true; 55af69d88dSmrg } 56af69d88dSmrg 57af69d88dSmrg if (_kern_get_safemode_option(B_SAFEMODE_DISABLE_USER_ADD_ONS, 58af69d88dSmrg parameter, ¶meterLength) == B_OK) { 59af69d88dSmrg if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on") 60af69d88dSmrg || !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes") 61af69d88dSmrg || !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) 62af69d88dSmrg fSafeMode = true; 63af69d88dSmrg } 64af69d88dSmrg 65af69d88dSmrg // We might run in compatibility mode on a system with a different ABI. The 66af69d88dSmrg // renderers matching our ABI can usually be found in respective 67af69d88dSmrg // subdirectories of the opengl add-ons directories. 68af69d88dSmrg system_info info; 69af69d88dSmrg if (get_system_info(&info) == B_OK 70af69d88dSmrg && (info.abi & B_HAIKU_ABI_MAJOR) 71af69d88dSmrg != (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR)) { 72af69d88dSmrg switch (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR) { 73af69d88dSmrg case B_HAIKU_ABI_GCC_2: 74af69d88dSmrg fABISubDirectory = "gcc2"; 75af69d88dSmrg break; 76af69d88dSmrg case B_HAIKU_ABI_GCC_4: 77af69d88dSmrg fABISubDirectory = "gcc4"; 78af69d88dSmrg break; 79af69d88dSmrg } 80af69d88dSmrg } 81af69d88dSmrg 82af69d88dSmrg AddDefaultPaths(); 83af69d88dSmrg} 84af69d88dSmrg 85af69d88dSmrg 86af69d88dSmrgGLRendererRoster::~GLRendererRoster() 87af69d88dSmrg{ 88af69d88dSmrg 89af69d88dSmrg} 90af69d88dSmrg 91af69d88dSmrg 92af69d88dSmrgBGLRenderer* 937ec681f3SmrgGLRendererRoster::GetRenderer(BGLView *view, ulong options) 94af69d88dSmrg{ 957ec681f3Smrg for ( 967ec681f3Smrg RendererMap::const_iterator iterator = fRenderers.begin(); 977ec681f3Smrg iterator != fRenderers.end(); 987ec681f3Smrg iterator++ 997ec681f3Smrg ) { 1007ec681f3Smrg renderer_item item = *iterator; 1017ec681f3Smrg BGLRenderer* renderer; 1027ec681f3Smrg renderer = item.entry(view, options); 1037ec681f3Smrg return renderer; 1047ec681f3Smrg } 1057ec681f3Smrg return NULL; 106af69d88dSmrg} 107af69d88dSmrg 108af69d88dSmrg 109af69d88dSmrgvoid 110af69d88dSmrgGLRendererRoster::AddDefaultPaths() 111af69d88dSmrg{ 112af69d88dSmrg // add user directories first, so that they can override system renderers 113af69d88dSmrg const directory_which paths[] = { 114af69d88dSmrg B_USER_NONPACKAGED_ADDONS_DIRECTORY, 115af69d88dSmrg B_USER_ADDONS_DIRECTORY, 1167ec681f3Smrg B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY, 117af69d88dSmrg B_SYSTEM_ADDONS_DIRECTORY, 118af69d88dSmrg }; 119af69d88dSmrg 120af69d88dSmrg for (uint32 i = fSafeMode ? 4 : 0; 121af69d88dSmrg i < sizeof(paths) / sizeof(paths[0]); i++) { 122af69d88dSmrg BPath path; 123af69d88dSmrg status_t status = find_directory(paths[i], &path, true); 124af69d88dSmrg if (status == B_OK && path.Append("opengl") == B_OK) 125af69d88dSmrg AddPath(path.Path()); 126af69d88dSmrg } 127af69d88dSmrg} 128af69d88dSmrg 129af69d88dSmrg 130af69d88dSmrgstatus_t 131af69d88dSmrgGLRendererRoster::AddPath(const char* path) 132af69d88dSmrg{ 133af69d88dSmrg BDirectory directory(path); 134af69d88dSmrg status_t status = directory.InitCheck(); 135af69d88dSmrg if (status < B_OK) 136af69d88dSmrg return status; 137af69d88dSmrg 138af69d88dSmrg // if a subdirectory for our ABI exists, use that instead 139af69d88dSmrg if (fABISubDirectory != NULL) { 140af69d88dSmrg BEntry entry(&directory, fABISubDirectory); 141af69d88dSmrg if (entry.IsDirectory()) { 142af69d88dSmrg status = directory.SetTo(&entry); 143af69d88dSmrg if (status != B_OK) 144af69d88dSmrg return status; 145af69d88dSmrg } 146af69d88dSmrg } 147af69d88dSmrg 148af69d88dSmrg node_ref nodeRef; 149af69d88dSmrg status = directory.GetNodeRef(&nodeRef); 150af69d88dSmrg if (status < B_OK) 151af69d88dSmrg return status; 152af69d88dSmrg 153af69d88dSmrg int32 count = 0; 154af69d88dSmrg int32 files = 0; 155af69d88dSmrg 156af69d88dSmrg entry_ref ref; 157af69d88dSmrg BEntry entry; 158af69d88dSmrg while (directory.GetNextRef(&ref) == B_OK) { 15901e04c3fSmrg entry.SetTo(&ref, true); 160af69d88dSmrg if (entry.InitCheck() == B_OK && !entry.IsFile()) 161af69d88dSmrg continue; 162af69d88dSmrg 163af69d88dSmrg if (CreateRenderer(ref) == B_OK) 164af69d88dSmrg count++; 165af69d88dSmrg 166af69d88dSmrg files++; 167af69d88dSmrg } 168af69d88dSmrg 169af69d88dSmrg if (files != 0 && count == 0) 170af69d88dSmrg return B_BAD_VALUE; 171af69d88dSmrg 172af69d88dSmrg return B_OK; 173af69d88dSmrg} 174af69d88dSmrg 175af69d88dSmrg 176af69d88dSmrgstatus_t 1777ec681f3SmrgGLRendererRoster::AddRenderer(InstantiateRenderer entry, 178af69d88dSmrg image_id image, const entry_ref* ref, ino_t node) 179af69d88dSmrg{ 180af69d88dSmrg renderer_item item; 1817ec681f3Smrg item.entry = entry; 182af69d88dSmrg item.image = image; 183af69d88dSmrg item.node = node; 184af69d88dSmrg if (ref != NULL) 185af69d88dSmrg item.ref = *ref; 186af69d88dSmrg 187af69d88dSmrg try { 1887ec681f3Smrg fRenderers.push_back(item); 189af69d88dSmrg } catch (...) { 190af69d88dSmrg return B_NO_MEMORY; 191af69d88dSmrg } 192af69d88dSmrg 193af69d88dSmrg return B_OK; 194af69d88dSmrg} 195af69d88dSmrg 196af69d88dSmrg 197af69d88dSmrgstatus_t 198af69d88dSmrgGLRendererRoster::CreateRenderer(const entry_ref& ref) 199af69d88dSmrg{ 20001e04c3fSmrg BEntry entry(&ref, true); 201af69d88dSmrg node_ref nodeRef; 202af69d88dSmrg status_t status = entry.GetNodeRef(&nodeRef); 203af69d88dSmrg if (status < B_OK) 204af69d88dSmrg return status; 205af69d88dSmrg 206af69d88dSmrg BPath path(&ref); 2077ec681f3Smrg printf("OpenGL load add-on: %s\n", path.Path()); 2087ec681f3Smrg 209af69d88dSmrg image_id image = load_add_on(path.Path()); 210af69d88dSmrg if (image < B_OK) 211af69d88dSmrg return image; 212af69d88dSmrg 2137ec681f3Smrg InstantiateRenderer instantiate_renderer; 214af69d88dSmrg 2157ec681f3Smrg status = get_image_symbol( 2167ec681f3Smrg image, "instantiate_gl_renderer", 2177ec681f3Smrg B_SYMBOL_TYPE_TEXT, (void**)&instantiate_renderer 2187ec681f3Smrg ); 219af69d88dSmrg 2207ec681f3Smrg if (status == B_OK) { 2217ec681f3Smrg if ((status = AddRenderer(instantiate_renderer, image, &ref, nodeRef.node)) != B_OK) { 222af69d88dSmrg unload_add_on(image); 2237ec681f3Smrg return status; 224af69d88dSmrg } 2257ec681f3Smrg printf("OpenGL add-on registered: %s\n", path.Path()); 226af69d88dSmrg return B_OK; 227af69d88dSmrg } 2287ec681f3Smrg 2297ec681f3Smrg printf("OpenGL add-on failed to instantiate: %s\n", path.Path()); 230af69d88dSmrg unload_add_on(image); 231af69d88dSmrg 232af69d88dSmrg return status; 233af69d88dSmrg} 234