GLRendererRoster.cpp revision 01e04c3f
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>
15af69d88dSmrg#include <system/safemode_defs.h>
16af69d88dSmrg
17af69d88dSmrg#include <Directory.h>
18af69d88dSmrg#include <FindDirectory.h>
19af69d88dSmrg#include <Path.h>
2001e04c3fSmrg#include <strings.h>
21af69d88dSmrg#include "GLDispatcher.h"
22af69d88dSmrg#include "GLRendererRoster.h"
23af69d88dSmrg
24af69d88dSmrg#include <new>
25af69d88dSmrg#include <string.h>
26af69d88dSmrg
27af69d88dSmrg
28af69d88dSmrgextern "C" status_t _kern_get_safemode_option(const char* parameter,
29af69d88dSmrg	char* buffer, size_t* _bufferSize);
30af69d88dSmrg
31af69d88dSmrg
32af69d88dSmrgGLRendererRoster::GLRendererRoster(BGLView* view, ulong options)
33af69d88dSmrg	:
34af69d88dSmrg	fNextID(0),
35af69d88dSmrg	fView(view),
36af69d88dSmrg	fOptions(options),
37af69d88dSmrg	fSafeMode(false),
38af69d88dSmrg	fABISubDirectory(NULL)
39af69d88dSmrg{
40af69d88dSmrg	char parameter[32];
41af69d88dSmrg	size_t parameterLength = sizeof(parameter);
42af69d88dSmrg
43af69d88dSmrg	if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE,
44af69d88dSmrg		parameter, &parameterLength) == B_OK) {
45af69d88dSmrg		if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
46af69d88dSmrg			|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
47af69d88dSmrg			|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1"))
48af69d88dSmrg			fSafeMode = true;
49af69d88dSmrg	}
50af69d88dSmrg
51af69d88dSmrg	if (_kern_get_safemode_option(B_SAFEMODE_DISABLE_USER_ADD_ONS,
52af69d88dSmrg		parameter, &parameterLength) == B_OK) {
53af69d88dSmrg		if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
54af69d88dSmrg			|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
55af69d88dSmrg			|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1"))
56af69d88dSmrg			fSafeMode = true;
57af69d88dSmrg	}
58af69d88dSmrg
59af69d88dSmrg	// We might run in compatibility mode on a system with a different ABI. The
60af69d88dSmrg	// renderers matching our ABI can usually be found in respective
61af69d88dSmrg	// subdirectories of the opengl add-ons directories.
62af69d88dSmrg	system_info info;
63af69d88dSmrg	if (get_system_info(&info) == B_OK
64af69d88dSmrg		&& (info.abi & B_HAIKU_ABI_MAJOR)
65af69d88dSmrg			!= (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR)) {
66af69d88dSmrg			switch (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR) {
67af69d88dSmrg				case B_HAIKU_ABI_GCC_2:
68af69d88dSmrg					fABISubDirectory = "gcc2";
69af69d88dSmrg					break;
70af69d88dSmrg				case B_HAIKU_ABI_GCC_4:
71af69d88dSmrg					fABISubDirectory = "gcc4";
72af69d88dSmrg					break;
73af69d88dSmrg			}
74af69d88dSmrg	}
75af69d88dSmrg
76af69d88dSmrg	AddDefaultPaths();
77af69d88dSmrg}
78af69d88dSmrg
79af69d88dSmrg
80af69d88dSmrgGLRendererRoster::~GLRendererRoster()
81af69d88dSmrg{
82af69d88dSmrg
83af69d88dSmrg}
84af69d88dSmrg
85af69d88dSmrg
86af69d88dSmrgBGLRenderer*
87af69d88dSmrgGLRendererRoster::GetRenderer(int32 id)
88af69d88dSmrg{
89af69d88dSmrg	RendererMap::const_iterator iterator = fRenderers.find(id);
90af69d88dSmrg	if (iterator == fRenderers.end())
91af69d88dSmrg		return NULL;
92af69d88dSmrg
93af69d88dSmrg	struct renderer_item item = iterator->second;
94af69d88dSmrg	return item.renderer;
95af69d88dSmrg}
96af69d88dSmrg
97af69d88dSmrg
98af69d88dSmrgvoid
99af69d88dSmrgGLRendererRoster::AddDefaultPaths()
100af69d88dSmrg{
101af69d88dSmrg	// add user directories first, so that they can override system renderers
102af69d88dSmrg	const directory_which paths[] = {
103af69d88dSmrg		B_USER_NONPACKAGED_ADDONS_DIRECTORY,
104af69d88dSmrg		B_USER_ADDONS_DIRECTORY,
105af69d88dSmrg		B_SYSTEM_ADDONS_DIRECTORY,
106af69d88dSmrg	};
107af69d88dSmrg
108af69d88dSmrg	for (uint32 i = fSafeMode ? 4 : 0;
109af69d88dSmrg		i < sizeof(paths) / sizeof(paths[0]); i++) {
110af69d88dSmrg		BPath path;
111af69d88dSmrg		status_t status = find_directory(paths[i], &path, true);
112af69d88dSmrg		if (status == B_OK && path.Append("opengl") == B_OK)
113af69d88dSmrg			AddPath(path.Path());
114af69d88dSmrg	}
115af69d88dSmrg}
116af69d88dSmrg
117af69d88dSmrg
118af69d88dSmrgstatus_t
119af69d88dSmrgGLRendererRoster::AddPath(const char* path)
120af69d88dSmrg{
121af69d88dSmrg	BDirectory directory(path);
122af69d88dSmrg	status_t status = directory.InitCheck();
123af69d88dSmrg	if (status < B_OK)
124af69d88dSmrg		return status;
125af69d88dSmrg
126af69d88dSmrg	// if a subdirectory for our ABI exists, use that instead
127af69d88dSmrg	if (fABISubDirectory != NULL) {
128af69d88dSmrg		BEntry entry(&directory, fABISubDirectory);
129af69d88dSmrg		if (entry.IsDirectory()) {
130af69d88dSmrg			status = directory.SetTo(&entry);
131af69d88dSmrg			if (status != B_OK)
132af69d88dSmrg				return status;
133af69d88dSmrg		}
134af69d88dSmrg	}
135af69d88dSmrg
136af69d88dSmrg	node_ref nodeRef;
137af69d88dSmrg	status = directory.GetNodeRef(&nodeRef);
138af69d88dSmrg	if (status < B_OK)
139af69d88dSmrg		return status;
140af69d88dSmrg
141af69d88dSmrg	int32 count = 0;
142af69d88dSmrg	int32 files = 0;
143af69d88dSmrg
144af69d88dSmrg	entry_ref ref;
145af69d88dSmrg	BEntry entry;
146af69d88dSmrg	while (directory.GetNextRef(&ref) == B_OK) {
14701e04c3fSmrg		entry.SetTo(&ref, true);
148af69d88dSmrg		if (entry.InitCheck() == B_OK && !entry.IsFile())
149af69d88dSmrg			continue;
150af69d88dSmrg
151af69d88dSmrg		if (CreateRenderer(ref) == B_OK)
152af69d88dSmrg			count++;
153af69d88dSmrg
154af69d88dSmrg		files++;
155af69d88dSmrg	}
156af69d88dSmrg
157af69d88dSmrg	if (files != 0 && count == 0)
158af69d88dSmrg		return B_BAD_VALUE;
159af69d88dSmrg
160af69d88dSmrg	return B_OK;
161af69d88dSmrg}
162af69d88dSmrg
163af69d88dSmrg
164af69d88dSmrgstatus_t
165af69d88dSmrgGLRendererRoster::AddRenderer(BGLRenderer* renderer,
166af69d88dSmrg	image_id image, const entry_ref* ref, ino_t node)
167af69d88dSmrg{
168af69d88dSmrg	renderer_item item;
169af69d88dSmrg	item.renderer = renderer;
170af69d88dSmrg	item.image = image;
171af69d88dSmrg	item.node = node;
172af69d88dSmrg	if (ref != NULL)
173af69d88dSmrg		item.ref = *ref;
174af69d88dSmrg
175af69d88dSmrg	try {
176af69d88dSmrg		fRenderers[fNextID] = item;
177af69d88dSmrg	} catch (...) {
178af69d88dSmrg		return B_NO_MEMORY;
179af69d88dSmrg	}
180af69d88dSmrg
181af69d88dSmrg	renderer->fOwningRoster = this;
182af69d88dSmrg	renderer->fID = fNextID++;
183af69d88dSmrg	return B_OK;
184af69d88dSmrg}
185af69d88dSmrg
186af69d88dSmrg
187af69d88dSmrgstatus_t
188af69d88dSmrgGLRendererRoster::CreateRenderer(const entry_ref& ref)
189af69d88dSmrg{
19001e04c3fSmrg	BEntry entry(&ref, true);
191af69d88dSmrg	node_ref nodeRef;
192af69d88dSmrg	status_t status = entry.GetNodeRef(&nodeRef);
193af69d88dSmrg	if (status < B_OK)
194af69d88dSmrg		return status;
195af69d88dSmrg
196af69d88dSmrg	BPath path(&ref);
197af69d88dSmrg	image_id image = load_add_on(path.Path());
198af69d88dSmrg	if (image < B_OK)
199af69d88dSmrg		return image;
200af69d88dSmrg
201af69d88dSmrg	BGLRenderer* (*instantiate_renderer)
202af69d88dSmrg		(BGLView* view, ulong options, BGLDispatcher* dispatcher);
203af69d88dSmrg
204af69d88dSmrg	status = get_image_symbol(image, "instantiate_gl_renderer",
205af69d88dSmrg		B_SYMBOL_TYPE_TEXT, (void**)&instantiate_renderer);
206af69d88dSmrg	if (status == B_OK) {
207af69d88dSmrg		BGLRenderer* renderer
208af69d88dSmrg			= instantiate_renderer(fView, fOptions, new BGLDispatcher());
209af69d88dSmrg		if (!renderer) {
210af69d88dSmrg			unload_add_on(image);
211af69d88dSmrg			return B_UNSUPPORTED;
212af69d88dSmrg		}
213af69d88dSmrg
214af69d88dSmrg		if (AddRenderer(renderer, image, &ref, nodeRef.node) != B_OK) {
215af69d88dSmrg			renderer->Release();
216af69d88dSmrg			// this will delete the renderer
217af69d88dSmrg			unload_add_on(image);
218af69d88dSmrg		}
219af69d88dSmrg		return B_OK;
220af69d88dSmrg	}
221af69d88dSmrg	unload_add_on(image);
222af69d88dSmrg
223af69d88dSmrg	return status;
224af69d88dSmrg}
225