GLRendererRoster.cpp revision 848b8605
1848b8605Smrg/*
2848b8605Smrg * Copyright 2006-2012 Haiku, Inc. All Rights Reserved.
3848b8605Smrg * Distributed under the terms of the MIT License.
4848b8605Smrg *
5848b8605Smrg * Authors:
6848b8605Smrg *		Philippe Houdoin <philippe.houdoin@free.fr>
7848b8605Smrg *		Alexander von Gluck IV <kallisti5@unixzen.com>
8848b8605Smrg */
9848b8605Smrg
10848b8605Smrg
11848b8605Smrg#include <driver_settings.h>
12848b8605Smrg#include <image.h>
13848b8605Smrg
14848b8605Smrg#include <kernel/image.h>
15848b8605Smrg#include <system/safemode_defs.h>
16848b8605Smrg
17848b8605Smrg#include <Directory.h>
18848b8605Smrg#include <FindDirectory.h>
19848b8605Smrg#include <Path.h>
20848b8605Smrg#include <String.h>
21848b8605Smrg#include "GLDispatcher.h"
22848b8605Smrg#include "GLRendererRoster.h"
23848b8605Smrg
24848b8605Smrg#include <new>
25848b8605Smrg#include <string.h>
26848b8605Smrg
27848b8605Smrg
28848b8605Smrgextern "C" status_t _kern_get_safemode_option(const char* parameter,
29848b8605Smrg	char* buffer, size_t* _bufferSize);
30848b8605Smrg
31848b8605Smrg
32848b8605SmrgGLRendererRoster::GLRendererRoster(BGLView* view, ulong options)
33848b8605Smrg	:
34848b8605Smrg	fNextID(0),
35848b8605Smrg	fView(view),
36848b8605Smrg	fOptions(options),
37848b8605Smrg	fSafeMode(false),
38848b8605Smrg	fABISubDirectory(NULL)
39848b8605Smrg{
40848b8605Smrg	char parameter[32];
41848b8605Smrg	size_t parameterLength = sizeof(parameter);
42848b8605Smrg
43848b8605Smrg	if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE,
44848b8605Smrg		parameter, &parameterLength) == B_OK) {
45848b8605Smrg		if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
46848b8605Smrg			|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
47848b8605Smrg			|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1"))
48848b8605Smrg			fSafeMode = true;
49848b8605Smrg	}
50848b8605Smrg
51848b8605Smrg	if (_kern_get_safemode_option(B_SAFEMODE_DISABLE_USER_ADD_ONS,
52848b8605Smrg		parameter, &parameterLength) == B_OK) {
53848b8605Smrg		if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
54848b8605Smrg			|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
55848b8605Smrg			|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1"))
56848b8605Smrg			fSafeMode = true;
57848b8605Smrg	}
58848b8605Smrg
59848b8605Smrg	// We might run in compatibility mode on a system with a different ABI. The
60848b8605Smrg	// renderers matching our ABI can usually be found in respective
61848b8605Smrg	// subdirectories of the opengl add-ons directories.
62848b8605Smrg	system_info info;
63848b8605Smrg	if (get_system_info(&info) == B_OK
64848b8605Smrg		&& (info.abi & B_HAIKU_ABI_MAJOR)
65848b8605Smrg			!= (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR)) {
66848b8605Smrg			switch (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR) {
67848b8605Smrg				case B_HAIKU_ABI_GCC_2:
68848b8605Smrg					fABISubDirectory = "gcc2";
69848b8605Smrg					break;
70848b8605Smrg				case B_HAIKU_ABI_GCC_4:
71848b8605Smrg					fABISubDirectory = "gcc4";
72848b8605Smrg					break;
73848b8605Smrg			}
74848b8605Smrg	}
75848b8605Smrg
76848b8605Smrg	AddDefaultPaths();
77848b8605Smrg}
78848b8605Smrg
79848b8605Smrg
80848b8605SmrgGLRendererRoster::~GLRendererRoster()
81848b8605Smrg{
82848b8605Smrg
83848b8605Smrg}
84848b8605Smrg
85848b8605Smrg
86848b8605SmrgBGLRenderer*
87848b8605SmrgGLRendererRoster::GetRenderer(int32 id)
88848b8605Smrg{
89848b8605Smrg	RendererMap::const_iterator iterator = fRenderers.find(id);
90848b8605Smrg	if (iterator == fRenderers.end())
91848b8605Smrg		return NULL;
92848b8605Smrg
93848b8605Smrg	struct renderer_item item = iterator->second;
94848b8605Smrg	return item.renderer;
95848b8605Smrg}
96848b8605Smrg
97848b8605Smrg
98848b8605Smrgvoid
99848b8605SmrgGLRendererRoster::AddDefaultPaths()
100848b8605Smrg{
101848b8605Smrg	// add user directories first, so that they can override system renderers
102848b8605Smrg	const directory_which paths[] = {
103848b8605Smrg		B_USER_NONPACKAGED_ADDONS_DIRECTORY,
104848b8605Smrg		B_USER_ADDONS_DIRECTORY,
105848b8605Smrg		B_SYSTEM_ADDONS_DIRECTORY,
106848b8605Smrg	};
107848b8605Smrg
108848b8605Smrg	for (uint32 i = fSafeMode ? 4 : 0;
109848b8605Smrg		i < sizeof(paths) / sizeof(paths[0]); i++) {
110848b8605Smrg		BPath path;
111848b8605Smrg		status_t status = find_directory(paths[i], &path, true);
112848b8605Smrg		if (status == B_OK && path.Append("opengl") == B_OK)
113848b8605Smrg			AddPath(path.Path());
114848b8605Smrg	}
115848b8605Smrg}
116848b8605Smrg
117848b8605Smrg
118848b8605Smrgstatus_t
119848b8605SmrgGLRendererRoster::AddPath(const char* path)
120848b8605Smrg{
121848b8605Smrg	BDirectory directory(path);
122848b8605Smrg	status_t status = directory.InitCheck();
123848b8605Smrg	if (status < B_OK)
124848b8605Smrg		return status;
125848b8605Smrg
126848b8605Smrg	// if a subdirectory for our ABI exists, use that instead
127848b8605Smrg	if (fABISubDirectory != NULL) {
128848b8605Smrg		BEntry entry(&directory, fABISubDirectory);
129848b8605Smrg		if (entry.IsDirectory()) {
130848b8605Smrg			status = directory.SetTo(&entry);
131848b8605Smrg			if (status != B_OK)
132848b8605Smrg				return status;
133848b8605Smrg		}
134848b8605Smrg	}
135848b8605Smrg
136848b8605Smrg	node_ref nodeRef;
137848b8605Smrg	status = directory.GetNodeRef(&nodeRef);
138848b8605Smrg	if (status < B_OK)
139848b8605Smrg		return status;
140848b8605Smrg
141848b8605Smrg	int32 count = 0;
142848b8605Smrg	int32 files = 0;
143848b8605Smrg
144848b8605Smrg	entry_ref ref;
145848b8605Smrg	BEntry entry;
146848b8605Smrg	while (directory.GetNextRef(&ref) == B_OK) {
147848b8605Smrg		entry.SetTo(&ref);
148848b8605Smrg		if (entry.InitCheck() == B_OK && !entry.IsFile())
149848b8605Smrg			continue;
150848b8605Smrg
151848b8605Smrg		if (CreateRenderer(ref) == B_OK)
152848b8605Smrg			count++;
153848b8605Smrg
154848b8605Smrg		files++;
155848b8605Smrg	}
156848b8605Smrg
157848b8605Smrg	if (files != 0 && count == 0)
158848b8605Smrg		return B_BAD_VALUE;
159848b8605Smrg
160848b8605Smrg	return B_OK;
161848b8605Smrg}
162848b8605Smrg
163848b8605Smrg
164848b8605Smrgstatus_t
165848b8605SmrgGLRendererRoster::AddRenderer(BGLRenderer* renderer,
166848b8605Smrg	image_id image, const entry_ref* ref, ino_t node)
167848b8605Smrg{
168848b8605Smrg	renderer_item item;
169848b8605Smrg	item.renderer = renderer;
170848b8605Smrg	item.image = image;
171848b8605Smrg	item.node = node;
172848b8605Smrg	if (ref != NULL)
173848b8605Smrg		item.ref = *ref;
174848b8605Smrg
175848b8605Smrg	try {
176848b8605Smrg		fRenderers[fNextID] = item;
177848b8605Smrg	} catch (...) {
178848b8605Smrg		return B_NO_MEMORY;
179848b8605Smrg	}
180848b8605Smrg
181848b8605Smrg	renderer->fOwningRoster = this;
182848b8605Smrg	renderer->fID = fNextID++;
183848b8605Smrg	return B_OK;
184848b8605Smrg}
185848b8605Smrg
186848b8605Smrg
187848b8605Smrgstatus_t
188848b8605SmrgGLRendererRoster::CreateRenderer(const entry_ref& ref)
189848b8605Smrg{
190848b8605Smrg	BEntry entry(&ref);
191848b8605Smrg	node_ref nodeRef;
192848b8605Smrg	status_t status = entry.GetNodeRef(&nodeRef);
193848b8605Smrg	if (status < B_OK)
194848b8605Smrg		return status;
195848b8605Smrg
196848b8605Smrg	BPath path(&ref);
197848b8605Smrg	image_id image = load_add_on(path.Path());
198848b8605Smrg	if (image < B_OK)
199848b8605Smrg		return image;
200848b8605Smrg
201848b8605Smrg	BGLRenderer* (*instantiate_renderer)
202848b8605Smrg		(BGLView* view, ulong options, BGLDispatcher* dispatcher);
203848b8605Smrg
204848b8605Smrg	status = get_image_symbol(image, "instantiate_gl_renderer",
205848b8605Smrg		B_SYMBOL_TYPE_TEXT, (void**)&instantiate_renderer);
206848b8605Smrg	if (status == B_OK) {
207848b8605Smrg		BGLRenderer* renderer
208848b8605Smrg			= instantiate_renderer(fView, fOptions, new BGLDispatcher());
209848b8605Smrg		if (!renderer) {
210848b8605Smrg			unload_add_on(image);
211848b8605Smrg			return B_UNSUPPORTED;
212848b8605Smrg		}
213848b8605Smrg
214848b8605Smrg		if (AddRenderer(renderer, image, &ref, nodeRef.node) != B_OK) {
215848b8605Smrg			renderer->Release();
216848b8605Smrg			// this will delete the renderer
217848b8605Smrg			unload_add_on(image);
218848b8605Smrg		}
219848b8605Smrg		return B_OK;
220848b8605Smrg	}
221848b8605Smrg	unload_add_on(image);
222848b8605Smrg
223848b8605Smrg	return status;
224848b8605Smrg}
225