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