Path: blob/21.2-virgl/src/hgl/GLRendererRoster.cpp
4558 views
/*1* Copyright 2006-2012 Haiku, Inc. All Rights Reserved.2* Distributed under the terms of the MIT License.3*4* Authors:5* Philippe Houdoin <[email protected]>6* Alexander von Gluck IV <[email protected]>7*/8910#include <driver_settings.h>11#include <image.h>1213#include <kernel/image.h>14#include <private/system/safemode_defs.h>1516#include <Directory.h>17#include <FindDirectory.h>18#include <Path.h>19#include <strings.h>20#include "GLRendererRoster.h"2122#include <new>23#include <string.h>24#include <stdio.h>252627extern "C" status_t _kern_get_safemode_option(const char* parameter,28char* buffer, size_t* _bufferSize);2930GLRendererRoster *GLRendererRoster::fInstance = NULL;3132GLRendererRoster *GLRendererRoster::Roster()33{34if (fInstance == NULL) {35fInstance = new GLRendererRoster();36}37return fInstance;38}3940GLRendererRoster::GLRendererRoster()41:42fSafeMode(false),43fABISubDirectory(NULL)44{45char parameter[32];46size_t parameterLength = sizeof(parameter);4748if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE,49parameter, ¶meterLength) == B_OK) {50if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")51|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")52|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1"))53fSafeMode = true;54}5556if (_kern_get_safemode_option(B_SAFEMODE_DISABLE_USER_ADD_ONS,57parameter, ¶meterLength) == B_OK) {58if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")59|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")60|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1"))61fSafeMode = true;62}6364// We might run in compatibility mode on a system with a different ABI. The65// renderers matching our ABI can usually be found in respective66// subdirectories of the opengl add-ons directories.67system_info info;68if (get_system_info(&info) == B_OK69&& (info.abi & B_HAIKU_ABI_MAJOR)70!= (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR)) {71switch (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR) {72case B_HAIKU_ABI_GCC_2:73fABISubDirectory = "gcc2";74break;75case B_HAIKU_ABI_GCC_4:76fABISubDirectory = "gcc4";77break;78}79}8081AddDefaultPaths();82}838485GLRendererRoster::~GLRendererRoster()86{8788}899091BGLRenderer*92GLRendererRoster::GetRenderer(BGLView *view, ulong options)93{94for (95RendererMap::const_iterator iterator = fRenderers.begin();96iterator != fRenderers.end();97iterator++98) {99renderer_item item = *iterator;100BGLRenderer* renderer;101renderer = item.entry(view, options);102return renderer;103}104return NULL;105}106107108void109GLRendererRoster::AddDefaultPaths()110{111// add user directories first, so that they can override system renderers112const directory_which paths[] = {113B_USER_NONPACKAGED_ADDONS_DIRECTORY,114B_USER_ADDONS_DIRECTORY,115B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY,116B_SYSTEM_ADDONS_DIRECTORY,117};118119for (uint32 i = fSafeMode ? 4 : 0;120i < sizeof(paths) / sizeof(paths[0]); i++) {121BPath path;122status_t status = find_directory(paths[i], &path, true);123if (status == B_OK && path.Append("opengl") == B_OK)124AddPath(path.Path());125}126}127128129status_t130GLRendererRoster::AddPath(const char* path)131{132BDirectory directory(path);133status_t status = directory.InitCheck();134if (status < B_OK)135return status;136137// if a subdirectory for our ABI exists, use that instead138if (fABISubDirectory != NULL) {139BEntry entry(&directory, fABISubDirectory);140if (entry.IsDirectory()) {141status = directory.SetTo(&entry);142if (status != B_OK)143return status;144}145}146147node_ref nodeRef;148status = directory.GetNodeRef(&nodeRef);149if (status < B_OK)150return status;151152int32 count = 0;153int32 files = 0;154155entry_ref ref;156BEntry entry;157while (directory.GetNextRef(&ref) == B_OK) {158entry.SetTo(&ref, true);159if (entry.InitCheck() == B_OK && !entry.IsFile())160continue;161162if (CreateRenderer(ref) == B_OK)163count++;164165files++;166}167168if (files != 0 && count == 0)169return B_BAD_VALUE;170171return B_OK;172}173174175status_t176GLRendererRoster::AddRenderer(InstantiateRenderer entry,177image_id image, const entry_ref* ref, ino_t node)178{179renderer_item item;180item.entry = entry;181item.image = image;182item.node = node;183if (ref != NULL)184item.ref = *ref;185186try {187fRenderers.push_back(item);188} catch (...) {189return B_NO_MEMORY;190}191192return B_OK;193}194195196status_t197GLRendererRoster::CreateRenderer(const entry_ref& ref)198{199BEntry entry(&ref, true);200node_ref nodeRef;201status_t status = entry.GetNodeRef(&nodeRef);202if (status < B_OK)203return status;204205BPath path(&ref);206printf("OpenGL load add-on: %s\n", path.Path());207208image_id image = load_add_on(path.Path());209if (image < B_OK)210return image;211212InstantiateRenderer instantiate_renderer;213214status = get_image_symbol(215image, "instantiate_gl_renderer",216B_SYMBOL_TYPE_TEXT, (void**)&instantiate_renderer217);218219if (status == B_OK) {220if ((status = AddRenderer(instantiate_renderer, image, &ref, nodeRef.node)) != B_OK) {221unload_add_on(image);222return status;223}224printf("OpenGL add-on registered: %s\n", path.Path());225return B_OK;226}227228printf("OpenGL add-on failed to instantiate: %s\n", path.Path());229unload_add_on(image);230231return status;232}233234235