blob: 6d8779516605f4926338c6a716ff37d79201af67 [file] [log] [blame]
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001/*
2 * XGL
3 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
Chia-I Wu701f3f62014-09-02 08:32:09 +080023 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
Jon Ashburn01e2d662014-11-14 09:52:42 -070026 * Jon Ashburn <jon@lunarg.com>
Chia-I Wu701f3f62014-09-02 08:32:09 +080027 * Courtney Goeltzenleuchter <courtney@lunarg.com>
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080028 */
Jon Ashburn6b4d70c2014-10-22 18:13:16 -060029#define _GNU_SOURCE
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080030#include <stdio.h>
31#include <stdlib.h>
32#include <stdarg.h>
33#include <stdbool.h>
34#include <string.h>
35
Chia-I Wu13a61a52014-08-04 11:18:20 +080036#include <sys/types.h>
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070037#if defined(WIN32)
38#include "dirent_on_windows.h"
39#else // WIN32
Chia-I Wu13a61a52014-08-04 11:18:20 +080040#include <dirent.h>
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070041#endif // WIN32
42#include "loader_platform.h"
Chia-I Wuf46b81a2015-01-04 11:12:47 +080043#include "table_ops.h"
Chia-I Wu19300602014-08-04 08:03:57 +080044#include "loader.h"
Courtney Goeltzenleuchter64ca9232015-02-10 18:40:14 -070045#include "xglIcd.h"
Ian Elliott655cad72015-02-12 17:08:34 -070046// The following is #included again to catch certain OS-specific functions
47// being used:
48#include "loader_platform.h"
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080049
Jon Ashburn1beab2d2015-01-26 14:51:40 -070050struct loader_instance {
Jon Ashburn1beab2d2015-01-26 14:51:40 -070051 struct loader_icd *icds;
52 struct loader_instance *next;
53};
54
Jon Ashburn6b4d70c2014-10-22 18:13:16 -060055struct loader_layers {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070056 loader_platform_dl_handle lib_handle;
Jon Ashburnb8358052014-11-18 09:06:04 -070057 char name[256];
58};
59
60struct layer_name_pair {
61 char *layer_name;
62 const char *lib_name;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -060063};
64
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080065struct loader_icd {
Jon Ashburn46d1f582015-01-28 11:01:35 -070066 const struct loader_scanned_icds *scanned_icds;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080067
Jon Ashburn876b1ac2014-10-17 15:09:07 -060068 XGL_LAYER_DISPATCH_TABLE *loader_dispatch;
Mark Lobodzinski17caf572015-01-29 08:55:56 -060069 uint32_t layer_count[XGL_MAX_PHYSICAL_GPUS];
Jon Ashburn6b4d70c2014-10-22 18:13:16 -060070 struct loader_layers layer_libs[XGL_MAX_PHYSICAL_GPUS][MAX_LAYER_LIBRARIES];
Jon Ashburnd09bd102014-10-22 21:15:26 -060071 XGL_BASE_LAYER_OBJECT *wrappedGpus[XGL_MAX_PHYSICAL_GPUS];
Mark Lobodzinski17caf572015-01-29 08:55:56 -060072 uint32_t gpu_count;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -060073 XGL_BASE_LAYER_OBJECT *gpus;
Jon Ashburndf7d5842014-10-16 15:48:50 -060074
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080075 struct loader_icd *next;
76};
77
Jon Ashburnd38bfb12014-10-14 19:15:22 -060078
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080079struct loader_msg_callback {
80 XGL_DBG_MSG_CALLBACK_FUNCTION func;
Mark Lobodzinski17caf572015-01-29 08:55:56 -060081 void *data;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080082
83 struct loader_msg_callback *next;
84};
85
Jon Ashburn46d1f582015-01-28 11:01:35 -070086struct loader_scanned_icds {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070087 loader_platform_dl_handle handle;
Jon Ashburn46d1f582015-01-28 11:01:35 -070088 xglGetProcAddrType GetProcAddr;
Jon Ashburn46888392015-01-29 15:45:51 -070089 xglCreateInstanceType CreateInstance;
90 xglDestroyInstanceType DestroyInstance;
Jon Ashburn4c392fb2015-01-28 19:57:09 -070091 xglEnumerateGpusType EnumerateGpus;
Jon Ashburn46888392015-01-29 15:45:51 -070092 XGL_INSTANCE instance;
Jon Ashburn46d1f582015-01-28 11:01:35 -070093 struct loader_scanned_icds *next;
94};
Jon Ashburnd38bfb12014-10-14 19:15:22 -060095
Jon Ashburn1beab2d2015-01-26 14:51:40 -070096// Note: Since the following is a static structure, all members are initialized
97// to zero.
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080098static struct {
Jon Ashburn1beab2d2015-01-26 14:51:40 -070099 struct loader_instance *instances;
Jon Ashburn46d1f582015-01-28 11:01:35 -0700100 bool icds_scanned;
101 struct loader_scanned_icds *scanned_icd_list;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600102 bool layer_scanned;
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -0700103 char *layer_dirs;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600104 unsigned int scanned_layer_count;
105 char *scanned_layer_names[MAX_LAYER_LIBRARIES];
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800106 struct loader_msg_callback *msg_callbacks;
107
108 bool debug_echo_enable;
109 bool break_on_error;
110 bool break_on_warning;
111} loader;
112
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700113
Ian Elliott4470a302015-02-17 10:33:47 -0700114#if defined(WIN32)
115// For ICD developers, look in the registry, and look for an environment
116// variable for a path(s) where to find the ICD(s):
117static char *loader_get_registry_and_env(const char *env_var,
118 const char *registry_value)
119{
120 char *env_str = getenv(env_var);
121 size_t env_len = (env_str == NULL) ? 0 : strlen(env_str);
122#define INITIAL_STR_LEN 1024
123 char *registry_str = malloc(INITIAL_STR_LEN);
124 DWORD registry_len = INITIAL_STR_LEN;
125 DWORD registry_value_type;
126 LONG registry_return_value;
127 char *rtn_str = NULL;
128 size_t rtn_len;
129
130 registry_return_value = RegGetValue(HKEY_LOCAL_MACHINE, "Software\\XGL",
131 registry_value,
132 (RRF_RT_REG_SZ | RRF_ZEROONFAILURE),
133 &registry_value_type,
134 (PVOID) registry_str,
135 &registry_len);
136
137 if (registry_return_value == ERROR_MORE_DATA) {
138 registry_str = realloc(registry_str, registry_len);
139 registry_return_value = RegGetValue(HKEY_LOCAL_MACHINE, "Software\\XGL",
140 registry_value,
141 (RRF_RT_REG_SZ | RRF_ZEROONFAILURE),
142 &registry_value_type,
143 (PVOID) registry_str,
144 &registry_len);
145 }
146
147 rtn_len = env_len + registry_len + 1;
148 if (rtn_len <= 2) {
149 // We found neither the desired registry value, nor the environment
150 // variable; return NULL:
151 return NULL;
152 } else {
153 // We found something, and so we need to allocate memory for the string
154 // to return:
155 rtn_str = malloc(rtn_len);
156 }
157
158 if (registry_return_value != ERROR_SUCCESS) {
159 // We didn't find the desired registry value, and so we must have found
160 // only the environment variable:
161 _snprintf(rtn_str, rtn_len, "%s", env_str);
162 } else if (env_str != NULL) {
163 // We found both the desired registry value and the environment
164 // variable, so concatenate them both:
165 _snprintf(rtn_str, rtn_len, "%s;%s", registry_str, env_str);
166 } else {
167 // We must have only found the desired registry value:
168 _snprintf(rtn_str, rtn_len, "%s", registry_str);
169 }
170
171 free(registry_str);
172
173 return(rtn_str);
174}
175#endif // WIN32
176
177
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800178static XGL_RESULT loader_msg_callback_add(XGL_DBG_MSG_CALLBACK_FUNCTION func,
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600179 void *data)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800180{
181 struct loader_msg_callback *cb;
182
183 cb = malloc(sizeof(*cb));
184 if (!cb)
185 return XGL_ERROR_OUT_OF_MEMORY;
186
187 cb->func = func;
188 cb->data = data;
189
190 cb->next = loader.msg_callbacks;
191 loader.msg_callbacks = cb;
192
193 return XGL_SUCCESS;
194}
195
196static XGL_RESULT loader_msg_callback_remove(XGL_DBG_MSG_CALLBACK_FUNCTION func)
197{
198 struct loader_msg_callback *cb = loader.msg_callbacks;
199
200 /*
201 * Find the first match (last registered).
202 *
203 * XXX What if the same callback function is registered more than once?
204 */
205 while (cb) {
206 if (cb->func == func) {
207 break;
208 }
209
210 cb = cb->next;
211 }
212
213 if (!cb)
214 return XGL_ERROR_INVALID_POINTER;
215
216 free(cb);
217
218 return XGL_SUCCESS;
219}
220
221static void loader_msg_callback_clear(void)
222{
223 struct loader_msg_callback *cb = loader.msg_callbacks;
224
225 while (cb) {
226 struct loader_msg_callback *next = cb->next;
227 free(cb);
228 cb = next;
229 }
230
231 loader.msg_callbacks = NULL;
232}
233
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600234static void loader_log(XGL_DBG_MSG_TYPE msg_type, int32_t msg_code,
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800235 const char *format, ...)
236{
237 const struct loader_msg_callback *cb = loader.msg_callbacks;
238 char msg[256];
239 va_list ap;
240 int ret;
241
242 va_start(ap, format);
243 ret = vsnprintf(msg, sizeof(msg), format, ap);
Ian Elliott42045842015-02-13 14:29:21 -0700244 if ((ret >= (int) sizeof(msg)) || ret < 0) {
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800245 msg[sizeof(msg) - 1] = '\0';
246 }
247 va_end(ap);
248
249 if (loader.debug_echo_enable || !cb) {
250 fputs(msg, stderr);
251 fputc('\n', stderr);
252 }
253
254 while (cb) {
255 cb->func(msg_type, XGL_VALIDATION_LEVEL_0, XGL_NULL_HANDLE, 0,
Chia-I Wuf1a5a742014-12-27 15:16:07 +0800256 msg_code, msg, cb->data);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800257 cb = cb->next;
258 }
259
260 switch (msg_type) {
261 case XGL_DBG_MSG_ERROR:
262 if (loader.break_on_error) {
263 exit(1);
264 }
265 /* fall through */
266 case XGL_DBG_MSG_WARNING:
267 if (loader.break_on_warning) {
268 exit(1);
269 }
270 break;
271 default:
272 break;
273 }
274}
275
276static void
277loader_icd_destroy(struct loader_icd *icd)
278{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700279 loader_platform_close_library(icd->scanned_icds->handle);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800280 free(icd);
281}
282
283static struct loader_icd *
Jon Ashburn46d1f582015-01-28 11:01:35 -0700284loader_icd_create(const struct loader_scanned_icds *scanned)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800285{
286 struct loader_icd *icd;
287
288 icd = malloc(sizeof(*icd));
289 if (!icd)
290 return NULL;
291
Courtney Goeltzenleuchter55001bb2014-10-28 10:29:27 -0600292 memset(icd, 0, sizeof(*icd));
293
Jon Ashburn46d1f582015-01-28 11:01:35 -0700294 icd->scanned_icds = scanned;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800295
296 return icd;
297}
298
299static XGL_RESULT loader_icd_register_msg_callbacks(const struct loader_icd *icd)
300{
301 const struct loader_msg_callback *cb = loader.msg_callbacks;
302 XGL_RESULT res;
303
304 while (cb) {
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600305 for (uint32_t i = 0; i < icd->gpu_count; i++) {
Jon Ashburn01e2d662014-11-14 09:52:42 -0700306 res = (icd->loader_dispatch + i)->DbgRegisterMsgCallback(cb->func, cb->data);
307 if (res != XGL_SUCCESS) {
308 break;
309 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800310 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800311 cb = cb->next;
312 }
313
314 /* roll back on errors */
315 if (cb) {
316 const struct loader_msg_callback *tmp = loader.msg_callbacks;
317
318 while (tmp != cb) {
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600319 for (uint32_t i = 0; i < icd->gpu_count; i++) {
Jon Ashburn01e2d662014-11-14 09:52:42 -0700320 (icd->loader_dispatch + i)->DbgUnregisterMsgCallback(cb->func);
321 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800322 tmp = tmp->next;
323 }
324
325 return res;
326 }
327
328 return XGL_SUCCESS;
329}
330
331static XGL_RESULT loader_icd_set_global_options(const struct loader_icd *icd)
332{
333#define SETB(icd, opt, val) do { \
334 if (val) { \
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600335 for (uint32_t i = 0; i < icd->gpu_count; i++) { \
Jon Ashburn01e2d662014-11-14 09:52:42 -0700336 const XGL_RESULT res = \
337 (icd->loader_dispatch + i)->DbgSetGlobalOption(opt, sizeof(val), &val); \
338 if (res != XGL_SUCCESS) \
339 return res; \
340 } \
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800341 } \
342} while (0)
343 SETB(icd, XGL_DBG_OPTION_DEBUG_ECHO_ENABLE, loader.debug_echo_enable);
344 SETB(icd, XGL_DBG_OPTION_BREAK_ON_ERROR, loader.break_on_error);
345 SETB(icd, XGL_DBG_OPTION_BREAK_ON_WARNING, loader.break_on_warning);
346#undef SETB
347
348return XGL_SUCCESS;
349}
350
Jon Ashburn46888392015-01-29 15:45:51 -0700351static struct loader_icd *loader_icd_add(struct loader_instance *ptr_inst,
352 const struct loader_scanned_icds *scanned)
Chia-I Wu13a61a52014-08-04 11:18:20 +0800353{
354 struct loader_icd *icd;
355
Jon Ashburn46d1f582015-01-28 11:01:35 -0700356 icd = loader_icd_create(scanned);
Chia-I Wu13a61a52014-08-04 11:18:20 +0800357 if (!icd)
358 return NULL;
359
Chia-I Wu13a61a52014-08-04 11:18:20 +0800360 /* prepend to the list */
Jon Ashburn46888392015-01-29 15:45:51 -0700361 icd->next = ptr_inst->icds;
362 ptr_inst->icds = icd;
Chia-I Wu13a61a52014-08-04 11:18:20 +0800363
364 return icd;
365}
366
Jon Ashburn46d1f582015-01-28 11:01:35 -0700367static void loader_scanned_icd_add(const char *filename)
368{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700369 loader_platform_dl_handle handle;
Jon Ashburn46888392015-01-29 15:45:51 -0700370 void *fp_gpa, *fp_enumerate, *fp_create_inst, *fp_destroy_inst;
Jon Ashburn46d1f582015-01-28 11:01:35 -0700371 struct loader_scanned_icds *new_node;
372
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700373 // Used to call: dlopen(filename, RTLD_LAZY);
374 handle = loader_platform_open_library(filename);
Jon Ashburn46d1f582015-01-28 11:01:35 -0700375 if (!handle) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700376 loader_log(XGL_DBG_MSG_WARNING, 0, loader_platform_open_library_error(filename));
Jon Ashburn46d1f582015-01-28 11:01:35 -0700377 return;
378 }
379
380#define LOOKUP(func_ptr, func) do { \
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700381 func_ptr = (xgl ##func## Type) loader_platform_get_proc_address(handle, "xgl" #func); \
Jon Ashburn46d1f582015-01-28 11:01:35 -0700382 if (!func_ptr) { \
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700383 loader_log(XGL_DBG_MSG_WARNING, 0, loader_platform_get_proc_address_error("xgl" #func)); \
Jon Ashburn46d1f582015-01-28 11:01:35 -0700384 return; \
385 } \
386} while (0)
387
388 LOOKUP(fp_gpa, GetProcAddr);
Jon Ashburn46888392015-01-29 15:45:51 -0700389 LOOKUP(fp_create_inst, CreateInstance);
390 LOOKUP(fp_destroy_inst, DestroyInstance);
Jon Ashburn4c392fb2015-01-28 19:57:09 -0700391 LOOKUP(fp_enumerate, EnumerateGpus);
Jon Ashburn46d1f582015-01-28 11:01:35 -0700392#undef LOOKUP
393
394 new_node = (struct loader_scanned_icds *) malloc(sizeof(struct loader_scanned_icds));
395 if (!new_node) {
396 loader_log(XGL_DBG_MSG_WARNING, 0, "Out of memory can't add icd");
397 return;
398 }
399
400 new_node->handle = handle;
401 new_node->GetProcAddr = fp_gpa;
Jon Ashburn46888392015-01-29 15:45:51 -0700402 new_node->CreateInstance = fp_create_inst;
403 new_node->DestroyInstance = fp_destroy_inst;
Jon Ashburn4c392fb2015-01-28 19:57:09 -0700404 new_node->EnumerateGpus = fp_enumerate;
Jon Ashburn46d1f582015-01-28 11:01:35 -0700405 new_node->next = loader.scanned_icd_list;
406 loader.scanned_icd_list = new_node;
407}
408
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700409
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600410/**
411 * Try to \c loader_icd_scan XGL driver(s).
412 *
413 * This function scans the default system path or path
414 * specified by the \c LIBXGL_DRIVERS_PATH environment variable in
415 * order to find loadable XGL ICDs with the name of libXGL_*.
416 *
417 * \returns
418 * void; but side effect is to set loader_icd_scanned to true
419 */
420static void loader_icd_scan(void)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800421{
Ian Elliott4470a302015-02-17 10:33:47 -0700422 const char *p, *next;
423 char *libPaths = NULL;
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600424 DIR *sysdir;
425 struct dirent *dent;
426 char icd_library[1024];
Jon Ashburn5cda59c2014-10-03 16:31:35 -0600427 char path[1024];
Ian Elliott19628802015-02-04 12:06:46 -0700428 uint32_t len;
Ian Elliott4470a302015-02-17 10:33:47 -0700429#if defined(WIN32)
430 bool must_free_libPaths;
431 libPaths = loader_get_registry_and_env(DRIVER_PATH_ENV,
432 DRIVER_PATH_REGISTRY_VALUE);
433 if (libPaths != NULL) {
434 must_free_libPaths = true;
435 } else {
436 must_free_libPaths = false;
437 libPaths = DEFAULT_XGL_DRIVERS_PATH;
438 }
439#else // WIN32
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600440 if (geteuid() == getuid()) {
Ian Elliott4470a302015-02-17 10:33:47 -0700441 /* Don't allow setuid apps to use the DRIVER_PATH_ENV env var: */
442 libPaths = getenv(DRIVER_PATH_ENV);
443 }
444 if (libPaths == NULL) {
445 libPaths = DEFAULT_XGL_DRIVERS_PATH;
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600446 }
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700447#endif // WIN32
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800448
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600449 for (p = libPaths; *p; p = next) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700450 next = strchr(p, PATH_SEPERATOR);
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600451 if (next == NULL) {
Ian Elliott19628802015-02-04 12:06:46 -0700452 len = (uint32_t) strlen(p);
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600453 next = p + len;
454 }
455 else {
Ian Elliott19628802015-02-04 12:06:46 -0700456 len = (uint32_t) (next - p);
Jon Ashburn5cda59c2014-10-03 16:31:35 -0600457 sprintf(path, "%.*s", (len > sizeof(path) - 1) ? (int) sizeof(path) - 1 : len, p);
458 p = path;
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600459 next++;
460 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800461
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700462 // TODO/TBD: Do we want to do this on Windows, or just let Windows take
463 // care of its own search path (which it apparently has)?
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600464 sysdir = opendir(p);
465 if (sysdir) {
466 dent = readdir(sysdir);
467 while (dent) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700468 /* Look for ICDs starting with XGL_DRIVER_LIBRARY_PREFIX and
469 * ending with XGL_LIBRARY_SUFFIX
470 */
471 if (!strncmp(dent->d_name,
472 XGL_DRIVER_LIBRARY_PREFIX,
473 XGL_DRIVER_LIBRARY_PREFIX_LEN)) {
Ian Elliott19628802015-02-04 12:06:46 -0700474 uint32_t nlen = (uint32_t) strlen(dent->d_name);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700475 const char *suf = dent->d_name + nlen - XGL_LIBRARY_SUFFIX_LEN;
476 if ((nlen > XGL_LIBRARY_SUFFIX_LEN) &&
477 !strncmp(suf,
478 XGL_LIBRARY_SUFFIX,
479 XGL_LIBRARY_SUFFIX_LEN)) {
480 snprintf(icd_library, 1024, "%s" DIRECTORY_SYMBOL "%s", p,dent->d_name);
481 loader_scanned_icd_add(icd_library);
482 }
483 }
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600484
485 dent = readdir(sysdir);
486 }
487 closedir(sysdir);
488 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800489 }
490
Ian Elliott4470a302015-02-17 10:33:47 -0700491#if defined(WIN32)
492 // Free any allocated memory:
493 if (must_free_libPaths) {
494 free(libPaths);
495 }
496#endif // WIN32
497
498 // Note that we've scanned for ICDs:
Jon Ashburn46d1f582015-01-28 11:01:35 -0700499 loader.icds_scanned = true;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800500}
501
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600502
Ian Elliott4470a302015-02-17 10:33:47 -0700503static void layer_lib_scan(void)
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600504{
505 const char *p, *next;
Ian Elliott4470a302015-02-17 10:33:47 -0700506 char *libPaths = NULL;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600507 DIR *curdir;
508 struct dirent *dent;
Ian Elliott4470a302015-02-17 10:33:47 -0700509 size_t len, i;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600510 char temp_str[1024];
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600511
Ian Elliott4470a302015-02-17 10:33:47 -0700512#if defined(WIN32)
513 bool must_free_libPaths;
514 libPaths = loader_get_registry_and_env(LAYERS_PATH_ENV,
515 LAYERS_PATH_REGISTRY_VALUE);
516 if (libPaths != NULL) {
517 must_free_libPaths = true;
518 } else {
519 must_free_libPaths = false;
520 libPaths = DEFAULT_XGL_LAYERS_PATH;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600521 }
Ian Elliott4470a302015-02-17 10:33:47 -0700522#else // WIN32
523 if (geteuid() == getuid()) {
524 /* Don't allow setuid apps to use the DRIVER_PATH_ENV env var: */
Courtney Goeltzenleuchter66b72f92015-02-18 20:03:02 -0700525 libPaths = getenv(LAYERS_PATH_ENV);
Ian Elliott4470a302015-02-17 10:33:47 -0700526 }
527 if (libPaths == NULL) {
528 libPaths = DEFAULT_XGL_LAYERS_PATH;
529 }
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700530#endif // WIN32
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600531
Ian Elliott4470a302015-02-17 10:33:47 -0700532 if (libPaths == NULL) {
533 // Have no paths to search:
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -0700534 return;
535 }
Ian Elliott4470a302015-02-17 10:33:47 -0700536 len = strlen(libPaths);
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -0700537 loader.layer_dirs = malloc(len+1);
Ian Elliott4470a302015-02-17 10:33:47 -0700538 if (loader.layer_dirs == NULL) {
539 free(libPaths);
Courtney Goeltzenleuchtera66265b2014-12-02 18:12:51 -0700540 return;
Ian Elliott4470a302015-02-17 10:33:47 -0700541 }
542 // Alloc passed, so we know there is enough space to hold the string, don't
543 // need strncpy
544 strcpy(loader.layer_dirs, libPaths);
545#if defined(WIN32)
546 // Free any allocated memory:
547 if (must_free_libPaths) {
548 free(libPaths);
549 must_free_libPaths = false;
550 }
551#endif // WIN32
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -0700552 libPaths = loader.layer_dirs;
553
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600554 /* cleanup any previously scanned libraries */
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600555 for (i = 0; i < loader.scanned_layer_count; i++) {
556 if (loader.scanned_layer_names[i] != NULL)
557 free(loader.scanned_layer_names[i]);
558 loader.scanned_layer_names[i] = NULL;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600559 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600560 loader.scanned_layer_count = 0;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600561
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600562 for (p = libPaths; *p; p = next) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700563 next = strchr(p, PATH_SEPERATOR);
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600564 if (next == NULL) {
Ian Elliott19628802015-02-04 12:06:46 -0700565 len = (uint32_t) strlen(p);
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600566 next = p + len;
567 }
568 else {
Ian Elliott19628802015-02-04 12:06:46 -0700569 len = (uint32_t) (next - p);
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600570 *(char *) next = '\0';
571 next++;
572 }
573
574 curdir = opendir(p);
575 if (curdir) {
576 dent = readdir(curdir);
577 while (dent) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700578 /* Look for layers starting with XGL_LAYER_LIBRARY_PREFIX and
579 * ending with XGL_LIBRARY_SUFFIX
580 */
581 if (!strncmp(dent->d_name,
582 XGL_LAYER_LIBRARY_PREFIX,
583 XGL_LAYER_LIBRARY_PREFIX_LEN)) {
Ian Elliott19628802015-02-04 12:06:46 -0700584 uint32_t nlen = (uint32_t) strlen(dent->d_name);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700585 const char *suf = dent->d_name + nlen - XGL_LIBRARY_SUFFIX_LEN;
586 if ((nlen > XGL_LIBRARY_SUFFIX_LEN) &&
587 !strncmp(suf,
588 XGL_LIBRARY_SUFFIX,
589 XGL_LIBRARY_SUFFIX_LEN)) {
590 loader_platform_dl_handle handle;
591 snprintf(temp_str, sizeof(temp_str), "%s" DIRECTORY_SYMBOL "%s",p,dent->d_name);
592 // Used to call: dlopen(temp_str, RTLD_LAZY)
593 if ((handle = loader_platform_open_library(temp_str)) == NULL) {
594 dent = readdir(curdir);
595 continue;
596 }
597 if (loader.scanned_layer_count == MAX_LAYER_LIBRARIES) {
598 loader_log(XGL_DBG_MSG_ERROR, 0, "%s ignored: max layer libraries exceed", temp_str);
599 break;
600 }
601 if ((loader.scanned_layer_names[loader.scanned_layer_count] = malloc(strlen(temp_str) + 1)) == NULL) {
602 loader_log(XGL_DBG_MSG_ERROR, 0, "%s ignored: out of memory", temp_str);
603 break;
604 }
605 strcpy(loader.scanned_layer_names[loader.scanned_layer_count], temp_str);
606 loader.scanned_layer_count++;
607 loader_platform_close_library(handle);
608 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600609 }
610
611 dent = readdir(curdir);
612 }
613 closedir(curdir);
614 }
615 }
616
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600617 loader.layer_scanned = true;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600618}
619
Mark Lobodzinski391bb6d2015-01-09 15:12:03 -0600620static void loader_init_dispatch_table(XGL_LAYER_DISPATCH_TABLE *tab, xglGetProcAddrType fpGPA, XGL_PHYSICAL_GPU gpu)
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600621{
Chia-I Wuf46b81a2015-01-04 11:12:47 +0800622 loader_initialize_dispatch_table(tab, fpGPA, gpu);
623
Jon Ashburnf7bcf9b2014-10-15 15:30:23 -0600624 if (tab->EnumerateLayers == NULL)
625 tab->EnumerateLayers = xglEnumerateLayers;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600626}
627
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600628static struct loader_icd * loader_get_icd(const XGL_BASE_LAYER_OBJECT *gpu, uint32_t *gpu_index)
Jon Ashburn876b1ac2014-10-17 15:09:07 -0600629{
Jon Ashburn98bd4542015-01-29 16:44:24 -0700630 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
631 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
632 for (uint32_t i = 0; i < icd->gpu_count; i++)
633 if ((icd->gpus + i) == gpu || (icd->gpus +i)->baseObject ==
634 gpu->baseObject) {
635 *gpu_index = i;
636 return icd;
637 }
638 }
Jon Ashburn876b1ac2014-10-17 15:09:07 -0600639 }
640 return NULL;
641}
642
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600643static bool loader_layers_activated(const struct loader_icd *icd, const uint32_t gpu_index)
Jon Ashburn876b1ac2014-10-17 15:09:07 -0600644{
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600645 if (icd->layer_count[gpu_index])
646 return true;
647 else
648 return false;
Jon Ashburn876b1ac2014-10-17 15:09:07 -0600649}
650
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600651static void loader_init_layer_libs(struct loader_icd *icd, uint32_t gpu_index, struct layer_name_pair * pLayerNames, uint32_t count)
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600652{
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600653 if (!icd)
654 return;
Jon Ashburndf7d5842014-10-16 15:48:50 -0600655
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600656 struct loader_layers *obj;
657 bool foundLib;
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600658 for (uint32_t i = 0; i < count; i++) {
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600659 foundLib = false;
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600660 for (uint32_t j = 0; j < icd->layer_count[gpu_index]; j++) {
Jon Ashburnb8358052014-11-18 09:06:04 -0700661 if (icd->layer_libs[gpu_index][j].lib_handle && !strcmp(icd->layer_libs[gpu_index][j].name, (char *) pLayerNames[i].layer_name)) {
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600662 foundLib = true;
663 break;
664 }
665 }
666 if (!foundLib) {
667 obj = &(icd->layer_libs[gpu_index][i]);
Jon Ashburnb8358052014-11-18 09:06:04 -0700668 strncpy(obj->name, (char *) pLayerNames[i].layer_name, sizeof(obj->name) - 1);
669 obj->name[sizeof(obj->name) - 1] = '\0';
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700670 // Used to call: dlopen(pLayerNames[i].lib_name, RTLD_LAZY | RTLD_DEEPBIND)
671 if ((obj->lib_handle = loader_platform_open_library(pLayerNames[i].lib_name)) == NULL) {
672 loader_log(XGL_DBG_MSG_ERROR, 0, loader_platform_open_library_error(pLayerNames[i].lib_name));
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600673 continue;
674 } else {
Jon Ashburnb8358052014-11-18 09:06:04 -0700675 loader_log(XGL_DBG_MSG_UNKNOWN, 0, "Inserting layer %s from library %s", pLayerNames[i].layer_name, pLayerNames[i].lib_name);
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600676 }
Jon Ashburnb8358052014-11-18 09:06:04 -0700677 free(pLayerNames[i].layer_name);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600678 icd->layer_count[gpu_index]++;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600679 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600680 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600681}
682
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600683static bool find_layer_name(struct loader_icd *icd, uint32_t gpu_index, const char * layer_name, const char **lib_name)
Jon Ashburnb8358052014-11-18 09:06:04 -0700684{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700685 loader_platform_dl_handle handle;
Mark Lobodzinski391bb6d2015-01-09 15:12:03 -0600686 xglEnumerateLayersType fpEnumerateLayers;
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600687 char layer_buf[16][256];
688 char * layers[16];
Jon Ashburnb8358052014-11-18 09:06:04 -0700689
690 for (int i = 0; i < 16; i++)
691 layers[i] = &layer_buf[i][0];
692
693 for (unsigned int j = 0; j < loader.scanned_layer_count; j++) {
694 *lib_name = loader.scanned_layer_names[j];
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700695 // Used to call: dlopen(*lib_name, RTLD_LAZY)
696 if ((handle = loader_platform_open_library(*lib_name)) == NULL)
Jon Ashburnb8358052014-11-18 09:06:04 -0700697 continue;
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700698 if ((fpEnumerateLayers = (xglEnumerateLayersType) loader_platform_get_proc_address(handle, "xglEnumerateLayers")) == NULL) {
Jon Ashburnb8358052014-11-18 09:06:04 -0700699 char * lib_str = malloc(strlen(*lib_name) + 1 + strlen(layer_name));
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700700 //use default layer name
701 snprintf(lib_str, strlen(*lib_name) + strlen(layer_name),
702 XGL_DRIVER_LIBRARY_PREFIX "%s" XGL_LIBRARY_SUFFIX,
703 layer_name);
704 loader_platform_close_library(handle);
705 if (!strcmp(*lib_name, lib_str)) {
Jon Ashburnb8358052014-11-18 09:06:04 -0700706 free(lib_str);
707 return true;
708 }
709 else {
710 free(lib_str);
711 continue;
712 }
713 }
714 else {
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600715 size_t cnt;
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700716 fpEnumerateLayers(NULL, 16, 256, &cnt, layers, (char *) icd->gpus + gpu_index);
Jon Ashburnb8358052014-11-18 09:06:04 -0700717 for (unsigned int i = 0; i < cnt; i++) {
718 if (!strcmp((char *) layers[i], layer_name)) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700719 loader_platform_close_library(handle);
Jon Ashburnb8358052014-11-18 09:06:04 -0700720 return true;
721 }
722 }
723 }
724
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700725 loader_platform_close_library(handle);
Jon Ashburnb8358052014-11-18 09:06:04 -0700726 }
727
728 return false;
729}
730
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600731static uint32_t loader_get_layer_env(struct loader_icd *icd, uint32_t gpu_index, struct layer_name_pair *pLayerNames)
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600732{
Ian Elliott4470a302015-02-17 10:33:47 -0700733 char *layerEnv;
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600734 uint32_t len, count = 0;
Jon Ashburnd09bd102014-10-22 21:15:26 -0600735 char *p, *pOrig, *next, *name;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600736
Ian Elliott4470a302015-02-17 10:33:47 -0700737#if defined(WIN32)
738 layerEnv = loader_get_registry_and_env(LAYER_NAMES_ENV,
739 LAYER_NAMES_REGISTRY_VALUE);
740#else // WIN32
741 layerEnv = getenv(LAYER_NAMES_ENV);
742#endif // WIN32
743 if (layerEnv == NULL) {
Jon Ashburn3fb55442014-10-23 10:29:09 -0600744 return 0;
Ian Elliott4470a302015-02-17 10:33:47 -0700745 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600746 p = malloc(strlen(layerEnv) + 1);
Ian Elliott4470a302015-02-17 10:33:47 -0700747 if (p == NULL) {
748#if defined(WIN32)
749 free(layerEnv);
750#endif // WIN32
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600751 return 0;
Ian Elliott4470a302015-02-17 10:33:47 -0700752 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600753 strcpy(p, layerEnv);
Ian Elliott4470a302015-02-17 10:33:47 -0700754#if defined(WIN32)
755 free(layerEnv);
756#endif // WIN32
Jon Ashburnd09bd102014-10-22 21:15:26 -0600757 pOrig = p;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600758
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600759 while (p && *p && count < MAX_LAYER_LIBRARIES) {
Jon Ashburnb8358052014-11-18 09:06:04 -0700760 const char *lib_name = NULL;
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700761 next = strchr(p, PATH_SEPERATOR);
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600762 if (next == NULL) {
Ian Elliott19628802015-02-04 12:06:46 -0700763 len = (uint32_t) strlen(p);
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600764 next = p + len;
765 }
766 else {
Ian Elliott19628802015-02-04 12:06:46 -0700767 len = (uint32_t) (next - p);
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600768 *(char *) next = '\0';
769 next++;
770 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600771 name = basename(p);
Jon Ashburnb8358052014-11-18 09:06:04 -0700772 if (!find_layer_name(icd, gpu_index, name, &lib_name)) {
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600773 p = next;
774 continue;
775 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600776
Ian Elliott19628802015-02-04 12:06:46 -0700777 len = (uint32_t) strlen(name);
Jon Ashburnb8358052014-11-18 09:06:04 -0700778 pLayerNames[count].layer_name = malloc(len + 1);
779 if (!pLayerNames[count].layer_name) {
Jon Ashburnd09bd102014-10-22 21:15:26 -0600780 free(pOrig);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600781 return count;
Jon Ashburnd09bd102014-10-22 21:15:26 -0600782 }
Jon Ashburnb8358052014-11-18 09:06:04 -0700783 strncpy((char *) pLayerNames[count].layer_name, name, len);
784 pLayerNames[count].layer_name[len] = '\0';
785 pLayerNames[count].lib_name = lib_name;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600786 count++;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600787 p = next;
788
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600789 };
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600790
Jon Ashburnd09bd102014-10-22 21:15:26 -0600791 free(pOrig);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600792 return count;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600793}
794
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600795static uint32_t loader_get_layer_libs(struct loader_icd *icd, uint32_t gpu_index, const XGL_DEVICE_CREATE_INFO* pCreateInfo, struct layer_name_pair **ppLayerNames)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600796{
Jon Ashburnb8358052014-11-18 09:06:04 -0700797 static struct layer_name_pair layerNames[MAX_LAYER_LIBRARIES];
Courtney Goeltzenleuchter89ba9282015-02-17 14:21:21 -0700798 int env_layer_count = 0;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600799
800 *ppLayerNames = &layerNames[0];
Courtney Goeltzenleuchter89ba9282015-02-17 14:21:21 -0700801 /* Load any layers specified in the environment first */
802 env_layer_count = loader_get_layer_env(icd, gpu_index, layerNames);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600803
Chia-I Wub0a2cc92015-01-28 14:00:47 +0800804 const XGL_LAYER_CREATE_INFO *pCi =
805 (const XGL_LAYER_CREATE_INFO *) pCreateInfo->pNext;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600806
807 while (pCi) {
808 if (pCi->sType == XGL_STRUCTURE_TYPE_LAYER_CREATE_INFO) {
809 const char *name;
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600810 uint32_t len;
Courtney Goeltzenleuchter89ba9282015-02-17 14:21:21 -0700811 for (uint32_t i = env_layer_count; i < (env_layer_count + pCi->layerCount); i++) {
Jon Ashburnb8358052014-11-18 09:06:04 -0700812 const char * lib_name = NULL;
Chia-I Wuf1a5a742014-12-27 15:16:07 +0800813 name = *(pCi->ppActiveLayerNames + i);
Jon Ashburnb8358052014-11-18 09:06:04 -0700814 if (!find_layer_name(icd, gpu_index, name, &lib_name))
815 return loader_get_layer_env(icd, gpu_index, layerNames);
Ian Elliott19628802015-02-04 12:06:46 -0700816 len = (uint32_t) strlen(name);
Jon Ashburnb8358052014-11-18 09:06:04 -0700817 layerNames[i].layer_name = malloc(len + 1);
818 if (!layerNames[i].layer_name)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600819 return i;
Jon Ashburnb8358052014-11-18 09:06:04 -0700820 strncpy((char *) layerNames[i].layer_name, name, len);
821 layerNames[i].layer_name[len] = '\0';
822 layerNames[i].lib_name = lib_name;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600823 }
Courtney Goeltzenleuchter61e10b62015-01-07 10:17:44 -0700824 return pCi->layerCount + loader_get_layer_env(icd, gpu_index, layerNames);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600825 }
826 pCi = pCi->pNext;
827 }
Jon Ashburnb8358052014-11-18 09:06:04 -0700828 return loader_get_layer_env(icd, gpu_index, layerNames);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600829}
830
Jon Ashburn46d1f582015-01-28 11:01:35 -0700831static void loader_deactivate_layer(const struct loader_instance *instance)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600832{
833 struct loader_icd *icd;
834 struct loader_layers *libs;
835
Jon Ashburn46d1f582015-01-28 11:01:35 -0700836 for (icd = instance->icds; icd; icd = icd->next) {
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600837 if (icd->gpus)
838 free(icd->gpus);
839 icd->gpus = NULL;
840 if (icd->loader_dispatch)
841 free(icd->loader_dispatch);
842 icd->loader_dispatch = NULL;
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600843 for (uint32_t j = 0; j < icd->gpu_count; j++) {
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600844 if (icd->layer_count[j] > 0) {
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600845 for (uint32_t i = 0; i < icd->layer_count[j]; i++) {
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600846 libs = &(icd->layer_libs[j][i]);
847 if (libs->lib_handle)
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700848 loader_platform_close_library(libs->lib_handle);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600849 libs->lib_handle = NULL;
850 }
Jon Ashburnd09bd102014-10-22 21:15:26 -0600851 if (icd->wrappedGpus[j])
852 free(icd->wrappedGpus[j]);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600853 }
854 icd->layer_count[j] = 0;
855 }
856 icd->gpu_count = 0;
857 }
858}
859
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600860extern uint32_t loader_activate_layers(XGL_PHYSICAL_GPU gpu, const XGL_DEVICE_CREATE_INFO* pCreateInfo)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600861{
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600862 uint32_t gpu_index;
863 uint32_t count;
Jon Ashburnb8358052014-11-18 09:06:04 -0700864 struct layer_name_pair *pLayerNames;
Jon Ashburnf2610012014-10-24 15:48:55 -0600865 struct loader_icd *icd = loader_get_icd((const XGL_BASE_LAYER_OBJECT *) gpu, &gpu_index);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600866
867 if (!icd)
868 return 0;
869 assert(gpu_index < XGL_MAX_PHYSICAL_GPUS);
870
871 /* activate any layer libraries */
872 if (!loader_layers_activated(icd, gpu_index)) {
Jon Ashburnf2610012014-10-24 15:48:55 -0600873 XGL_BASE_LAYER_OBJECT *gpuObj = (XGL_BASE_LAYER_OBJECT *) gpu;
874 XGL_BASE_LAYER_OBJECT *nextGpuObj, *baseObj = gpuObj->baseObject;
Mark Lobodzinski391bb6d2015-01-09 15:12:03 -0600875 xglGetProcAddrType nextGPA = xglGetProcAddr;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600876
Jon Ashburnb8358052014-11-18 09:06:04 -0700877 count = loader_get_layer_libs(icd, gpu_index, pCreateInfo, &pLayerNames);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600878 if (!count)
879 return 0;
Jon Ashburnb8358052014-11-18 09:06:04 -0700880 loader_init_layer_libs(icd, gpu_index, pLayerNames, count);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600881
Jon Ashburnd09bd102014-10-22 21:15:26 -0600882 icd->wrappedGpus[gpu_index] = malloc(sizeof(XGL_BASE_LAYER_OBJECT) * icd->layer_count[gpu_index]);
883 if (! icd->wrappedGpus[gpu_index])
884 loader_log(XGL_DBG_MSG_ERROR, 0, "Failed to malloc Gpu objects for layer");
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600885 for (int32_t i = icd->layer_count[gpu_index] - 1; i >= 0; i--) {
Jon Ashburnd09bd102014-10-22 21:15:26 -0600886 nextGpuObj = (icd->wrappedGpus[gpu_index] + i);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600887 nextGpuObj->pGPA = nextGPA;
Jon Ashburnf2610012014-10-24 15:48:55 -0600888 nextGpuObj->baseObject = baseObj;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600889 nextGpuObj->nextObject = gpuObj;
890 gpuObj = nextGpuObj;
891
Jon Ashburn79113cc2014-12-01 14:22:40 -0700892 char funcStr[256];
893 snprintf(funcStr, 256, "%sGetProcAddr",icd->layer_libs[gpu_index][i].name);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700894 if ((nextGPA = (xglGetProcAddrType) loader_platform_get_proc_address(icd->layer_libs[gpu_index][i].lib_handle, funcStr)) == NULL)
895 nextGPA = (xglGetProcAddrType) loader_platform_get_proc_address(icd->layer_libs[gpu_index][i].lib_handle, "xglGetProcAddr");
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600896 if (!nextGPA) {
Jon Ashburnb8358052014-11-18 09:06:04 -0700897 loader_log(XGL_DBG_MSG_ERROR, 0, "Failed to find xglGetProcAddr in layer %s", icd->layer_libs[gpu_index][i].name);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600898 continue;
899 }
900
Jon Ashburnf2610012014-10-24 15:48:55 -0600901 if (i == 0) {
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600902 loader_init_dispatch_table(icd->loader_dispatch + gpu_index, nextGPA, gpuObj);
Jon Ashburnf2610012014-10-24 15:48:55 -0600903 //Insert the new wrapped objects into the list with loader object at head
904 ((XGL_BASE_LAYER_OBJECT *) gpu)->nextObject = gpuObj;
905 ((XGL_BASE_LAYER_OBJECT *) gpu)->pGPA = nextGPA;
906 gpuObj = icd->wrappedGpus[gpu_index] + icd->layer_count[gpu_index] - 1;
907 gpuObj->nextObject = baseObj;
Jon Ashburn46d1f582015-01-28 11:01:35 -0700908 gpuObj->pGPA = icd->scanned_icds->GetProcAddr;
Jon Ashburnf2610012014-10-24 15:48:55 -0600909 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600910
911 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600912 }
913 else {
914 //make sure requested Layers matches currently activated Layers
Jon Ashburnb8358052014-11-18 09:06:04 -0700915 count = loader_get_layer_libs(icd, gpu_index, pCreateInfo, &pLayerNames);
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600916 for (uint32_t i = 0; i < count; i++) {
Jon Ashburnb8358052014-11-18 09:06:04 -0700917 if (strcmp(icd->layer_libs[gpu_index][i].name, pLayerNames[i].layer_name)) {
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600918 loader_log(XGL_DBG_MSG_ERROR, 0, "Layers activated != Layers requested");
919 break;
920 }
921 }
922 if (count != icd->layer_count[gpu_index]) {
Jon Ashburnb8358052014-11-18 09:06:04 -0700923 loader_log(XGL_DBG_MSG_ERROR, 0, "Number of Layers activated != number requested");
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600924 }
925 }
926 return icd->layer_count[gpu_index];
927}
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600928
Jon Ashburn1beab2d2015-01-26 14:51:40 -0700929LOADER_EXPORT XGL_RESULT XGLAPI xglCreateInstance(
930 const XGL_APPLICATION_INFO* pAppInfo,
931 const XGL_ALLOC_CALLBACKS* pAllocCb,
932 XGL_INSTANCE* pInstance)
933{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700934 static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_icd);
935 static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_layer);
Jon Ashburn1beab2d2015-01-26 14:51:40 -0700936 struct loader_instance *ptr_instance = NULL;
Jon Ashburn46888392015-01-29 15:45:51 -0700937 struct loader_scanned_icds *scanned_icds;
938 struct loader_icd *icd;
Ian Elliott55dbc5b2015-02-19 15:49:03 -0700939 XGL_RESULT res = XGL_ERROR_INITIALIZATION_FAILED;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600940
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700941 /* Scan/discover all ICD libraries in a single-threaded manner */
942 loader_platform_thread_once(&once_icd, loader_icd_scan);
Jon Ashburn46888392015-01-29 15:45:51 -0700943
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700944 /* get layer libraries in a single-threaded manner */
945 loader_platform_thread_once(&once_layer, layer_lib_scan);
Jon Ashburn46888392015-01-29 15:45:51 -0700946
Jon Ashburn1beab2d2015-01-26 14:51:40 -0700947 ptr_instance = (struct loader_instance*) malloc(sizeof(struct loader_instance));
948 if (ptr_instance == NULL) {
949 return XGL_ERROR_OUT_OF_MEMORY;
950 }
951 memset(ptr_instance, 0, sizeof(struct loader_instance));
952
Jon Ashburn1beab2d2015-01-26 14:51:40 -0700953 ptr_instance->next = loader.instances;
954 loader.instances = ptr_instance;
955
Jon Ashburn46888392015-01-29 15:45:51 -0700956 scanned_icds = loader.scanned_icd_list;
957 while (scanned_icds) {
958 icd = loader_icd_add(ptr_instance, scanned_icds);
959 if (icd) {
960 res = scanned_icds->CreateInstance(pAppInfo, pAllocCb,
961 &(scanned_icds->instance));
962 if (res != XGL_SUCCESS)
963 {
964 ptr_instance->icds = ptr_instance->icds->next;
965 loader_icd_destroy(icd);
966 scanned_icds->instance = NULL;
967 loader_log(XGL_DBG_MSG_WARNING, 0,
968 "ICD ignored: failed to CreateInstance on device");
969 }
970 }
971 scanned_icds = scanned_icds->next;
972 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -0700973
Ian Elliotteb450762015-02-05 15:19:15 -0700974 if (ptr_instance->icds == NULL) {
975 return XGL_ERROR_INCOMPATIBLE_DRIVER;
976 }
Jon Ashburn46888392015-01-29 15:45:51 -0700977
978 *pInstance = (XGL_INSTANCE) ptr_instance;
Jon Ashburn1beab2d2015-01-26 14:51:40 -0700979 return XGL_SUCCESS;
980}
981
982LOADER_EXPORT XGL_RESULT XGLAPI xglDestroyInstance(
983 XGL_INSTANCE instance)
984{
985 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Jon Ashburn46888392015-01-29 15:45:51 -0700986 struct loader_scanned_icds *scanned_icds;
987 XGL_RESULT res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -0700988
989 // Remove this instance from the list of instances:
990 struct loader_instance *prev = NULL;
991 struct loader_instance *next = loader.instances;
992 while (next != NULL) {
993 if (next == ptr_instance) {
994 // Remove this instance from the list:
995 if (prev)
996 prev->next = next->next;
Jon Ashburnc5c49602015-02-03 09:26:59 -0700997 else
998 loader.instances = next->next;
Jon Ashburn1beab2d2015-01-26 14:51:40 -0700999 break;
1000 }
1001 prev = next;
1002 next = next->next;
1003 }
1004 if (next == NULL) {
1005 // This must be an invalid instance handle or empty list
1006 return XGL_ERROR_INVALID_HANDLE;
1007 }
1008
Jon Ashburn46888392015-01-29 15:45:51 -07001009 // cleanup any prior layer initializations
1010 loader_deactivate_layer(ptr_instance);
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001011
Jon Ashburn46888392015-01-29 15:45:51 -07001012 scanned_icds = loader.scanned_icd_list;
1013 while (scanned_icds) {
1014 if (scanned_icds->instance)
1015 res = scanned_icds->DestroyInstance(scanned_icds->instance);
1016 if (res != XGL_SUCCESS)
1017 loader_log(XGL_DBG_MSG_WARNING, 0,
1018 "ICD ignored: failed to DestroyInstance on device");
1019 scanned_icds->instance = NULL;
1020 scanned_icds = scanned_icds->next;
1021 }
1022
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001023 free(ptr_instance);
1024
1025 return XGL_SUCCESS;
1026}
1027
1028LOADER_EXPORT XGL_RESULT XGLAPI xglEnumerateGpus(
1029
1030 XGL_INSTANCE instance,
1031 uint32_t maxGpus,
1032 uint32_t* pGpuCount,
1033 XGL_PHYSICAL_GPU* pGpus)
1034{
Jon Ashburn4c392fb2015-01-28 19:57:09 -07001035 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
1036 struct loader_icd *icd;
Jon Ashburn8d66a052015-01-29 15:47:01 -07001037 uint32_t count = 0;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07001038 XGL_RESULT res;
1039
1040 //in spirit of XGL don't error check on the instance parameter
1041 icd = ptr_instance->icds;
1042 while (icd) {
1043 XGL_PHYSICAL_GPU gpus[XGL_MAX_PHYSICAL_GPUS];
1044 XGL_BASE_LAYER_OBJECT * wrapped_gpus;
1045 xglGetProcAddrType get_proc_addr = icd->scanned_icds->GetProcAddr;
Jon Ashburn8d66a052015-01-29 15:47:01 -07001046 uint32_t n, max = maxGpus - count;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07001047
1048 if (max > XGL_MAX_PHYSICAL_GPUS) {
1049 max = XGL_MAX_PHYSICAL_GPUS;
1050 }
1051
Jon Ashburn46888392015-01-29 15:45:51 -07001052 res = icd->scanned_icds->EnumerateGpus(icd->scanned_icds->instance,
1053 max, &n,
Jon Ashburn4c392fb2015-01-28 19:57:09 -07001054 gpus);
1055 if (res == XGL_SUCCESS && n) {
1056 wrapped_gpus = (XGL_BASE_LAYER_OBJECT*) malloc(n *
1057 sizeof(XGL_BASE_LAYER_OBJECT));
1058 icd->gpus = wrapped_gpus;
1059 icd->gpu_count = n;
1060 icd->loader_dispatch = (XGL_LAYER_DISPATCH_TABLE *) malloc(n *
1061 sizeof(XGL_LAYER_DISPATCH_TABLE));
Ian Elliott19628802015-02-04 12:06:46 -07001062 for (unsigned int i = 0; i < n; i++) {
Jon Ashburn4c392fb2015-01-28 19:57:09 -07001063 (wrapped_gpus + i)->baseObject = gpus[i];
1064 (wrapped_gpus + i)->pGPA = get_proc_addr;
1065 (wrapped_gpus + i)->nextObject = gpus[i];
1066 memcpy(pGpus + count, &wrapped_gpus, sizeof(*pGpus));
1067 loader_init_dispatch_table(icd->loader_dispatch + i,
1068 get_proc_addr, gpus[i]);
Courtney Goeltzenleuchter64ca9232015-02-10 18:40:14 -07001069
1070 /* Verify ICD compatibility */
1071 if (!valid_loader_magic_value(gpus[i])) {
1072 loader_log(XGL_DBG_MSG_WARNING, 0,
1073 "Loader: Incompatible ICD, first dword must be initialized to ICD_LOADER_MAGIC. See loader/README.md for details.\n");
1074 assert(0);
1075 }
1076
Jon Ashburn4c392fb2015-01-28 19:57:09 -07001077 const XGL_LAYER_DISPATCH_TABLE **disp;
1078 disp = (const XGL_LAYER_DISPATCH_TABLE **) gpus[i];
1079 *disp = icd->loader_dispatch + i;
1080 }
1081
1082 if (loader_icd_set_global_options(icd) != XGL_SUCCESS ||
1083 loader_icd_register_msg_callbacks(icd) != XGL_SUCCESS) {
1084 loader_log(XGL_DBG_MSG_WARNING, 0,
1085 "ICD ignored: failed to migrate settings");
1086 loader_icd_destroy(icd);
1087 }
1088 count += n;
1089
1090 if (count >= maxGpus) {
1091 break;
1092 }
1093 }
1094
1095 icd = icd->next;
1096 }
1097
1098 /* we have nothing to log anymore */
1099 loader_msg_callback_clear();
1100
1101 *pGpuCount = count;
1102
1103 return (count > 0) ? XGL_SUCCESS : res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001104}
1105
1106LOADER_EXPORT void * XGLAPI xglGetProcAddr(XGL_PHYSICAL_GPU gpu, const char * pName)
1107{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001108 if (gpu == NULL) {
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001109 return NULL;
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001110 }
Jon Ashburn891537f2014-10-22 12:42:13 -06001111 XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) gpu;
Jon Ashburnf2610012014-10-24 15:48:55 -06001112 XGL_LAYER_DISPATCH_TABLE * disp_table = * (XGL_LAYER_DISPATCH_TABLE **) gpuw->baseObject;
Chia-I Wuf46b81a2015-01-04 11:12:47 +08001113 void *addr;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001114
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001115 if (disp_table == NULL)
1116 return NULL;
1117
Chia-I Wuf46b81a2015-01-04 11:12:47 +08001118 addr = loader_lookup_dispatch_table(disp_table, pName);
1119 if (addr)
1120 return addr;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001121 else {
Jon Ashburnf2610012014-10-24 15:48:55 -06001122 if (disp_table->GetProcAddr == NULL)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001123 return NULL;
Jon Ashburnf2610012014-10-24 15:48:55 -06001124 return disp_table->GetProcAddr(gpuw->nextObject, pName);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001125 }
1126}
1127
Mark Lobodzinski17caf572015-01-29 08:55:56 -06001128LOADER_EXPORT XGL_RESULT XGLAPI xglEnumerateLayers(XGL_PHYSICAL_GPU gpu, size_t maxLayerCount, size_t maxStringSize, size_t* pOutLayerCount, char* const* pOutLayers, void* pReserved)
Jon Ashburnf7bcf9b2014-10-15 15:30:23 -06001129{
Mark Lobodzinski17caf572015-01-29 08:55:56 -06001130 uint32_t gpu_index;
Ian Elliott19628802015-02-04 12:06:46 -07001131 size_t count = 0;
Jon Ashburn1323eb72014-12-02 13:03:09 -07001132 char *lib_name;
1133 struct loader_icd *icd = loader_get_icd((const XGL_BASE_LAYER_OBJECT *) gpu, &gpu_index);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001134 loader_platform_dl_handle handle;
Mark Lobodzinski391bb6d2015-01-09 15:12:03 -06001135 xglEnumerateLayersType fpEnumerateLayers;
Mark Lobodzinski17caf572015-01-29 08:55:56 -06001136 char layer_buf[16][256];
1137 char * layers[16];
Jon Ashburnf7bcf9b2014-10-15 15:30:23 -06001138
Jon Ashburn1323eb72014-12-02 13:03:09 -07001139 if (pOutLayerCount == NULL || pOutLayers == NULL)
Jon Ashburnf7bcf9b2014-10-15 15:30:23 -06001140 return XGL_ERROR_INVALID_POINTER;
1141
Jon Ashburn46d1f582015-01-28 11:01:35 -07001142 if (!icd)
1143 return XGL_ERROR_UNAVAILABLE;
1144
Jon Ashburn1323eb72014-12-02 13:03:09 -07001145 for (int i = 0; i < 16; i++)
1146 layers[i] = &layer_buf[i][0];
1147
1148 for (unsigned int j = 0; j < loader.scanned_layer_count && count < maxLayerCount; j++) {
1149 lib_name = loader.scanned_layer_names[j];
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001150 // Used to call: dlopen(*lib_name, RTLD_LAZY)
1151 if ((handle = loader_platform_open_library(lib_name)) == NULL)
Jon Ashburn1323eb72014-12-02 13:03:09 -07001152 continue;
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001153 if ((fpEnumerateLayers = loader_platform_get_proc_address(handle, "xglEnumerateLayers")) == NULL) {
1154 //use default layer name based on library name XGL_LAYER_LIBRARY_PREFIX<name>.XGL_LIBRARY_SUFFIX
Jon Ashburn1323eb72014-12-02 13:03:09 -07001155 char *pEnd, *cpyStr;
Ian Elliott42045842015-02-13 14:29:21 -07001156 size_t siz;
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001157 loader_platform_close_library(handle);
Jon Ashburn1323eb72014-12-02 13:03:09 -07001158 lib_name = basename(lib_name);
1159 pEnd = strrchr(lib_name, '.');
Ian Elliott19628802015-02-04 12:06:46 -07001160 siz = (int) (pEnd - lib_name - strlen(XGL_LAYER_LIBRARY_PREFIX) + 1);
Jon Ashburn1323eb72014-12-02 13:03:09 -07001161 if (pEnd == NULL || siz <= 0)
1162 continue;
1163 cpyStr = malloc(siz);
1164 if (cpyStr == NULL) {
1165 free(cpyStr);
1166 continue;
1167 }
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001168 strncpy(cpyStr, lib_name + strlen(XGL_LAYER_LIBRARY_PREFIX), siz);
Jon Ashburn1323eb72014-12-02 13:03:09 -07001169 cpyStr[siz - 1] = '\0';
1170 if (siz > maxStringSize)
Ian Elliott19628802015-02-04 12:06:46 -07001171 siz = (int) maxStringSize;
Jon Ashburn1323eb72014-12-02 13:03:09 -07001172 strncpy((char *) (pOutLayers[count]), cpyStr, siz);
1173 pOutLayers[count][siz - 1] = '\0';
1174 count++;
1175 free(cpyStr);
1176 }
1177 else {
Mark Lobodzinski17caf572015-01-29 08:55:56 -06001178 size_t cnt;
1179 uint32_t n;
Jon Ashburn1323eb72014-12-02 13:03:09 -07001180 XGL_RESULT res;
Ian Elliott19628802015-02-04 12:06:46 -07001181 n = (uint32_t) ((maxStringSize < 256) ? maxStringSize : 256);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001182 res = fpEnumerateLayers(NULL, 16, n, &cnt, layers, (char *) icd->gpus + gpu_index);
1183 loader_platform_close_library(handle);
Jon Ashburn1323eb72014-12-02 13:03:09 -07001184 if (res != XGL_SUCCESS)
1185 continue;
1186 if (cnt + count > maxLayerCount)
1187 cnt = maxLayerCount - count;
Ian Elliott19628802015-02-04 12:06:46 -07001188 for (uint32_t i = (uint32_t) count; i < cnt + count; i++) {
Jon Ashburn1323eb72014-12-02 13:03:09 -07001189 strncpy((char *) (pOutLayers[i]), (char *) layers[i - count], n);
1190 if (n > 0)
1191 pOutLayers[i - count][n - 1] = '\0';
1192 }
1193 count += cnt;
1194 }
1195 }
1196
Jon Ashburnf7bcf9b2014-10-15 15:30:23 -06001197 *pOutLayerCount = count;
1198
Jon Ashburnf7bcf9b2014-10-15 15:30:23 -06001199 return XGL_SUCCESS;
1200}
1201
Mark Lobodzinski17caf572015-01-29 08:55:56 -06001202LOADER_EXPORT XGL_RESULT XGLAPI xglDbgRegisterMsgCallback(XGL_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback, void* pUserData)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001203{
Jon Ashburn01e2d662014-11-14 09:52:42 -07001204 const struct loader_icd *icd;
Jon Ashburn98bd4542015-01-29 16:44:24 -07001205 struct loader_instance *inst;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001206 XGL_RESULT res;
Mark Lobodzinski17caf572015-01-29 08:55:56 -06001207 uint32_t gpu_idx;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001208
Jon Ashburn46d1f582015-01-28 11:01:35 -07001209 if (!loader.icds_scanned) {
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001210 return loader_msg_callback_add(pfnMsgCallback, pUserData);
1211 }
1212
Jon Ashburn98bd4542015-01-29 16:44:24 -07001213 for (inst = loader.instances; inst; inst = inst->next) {
1214 for (icd = inst->icds; icd; icd = icd->next) {
1215 for (uint32_t i = 0; i < icd->gpu_count; i++) {
1216 res = (icd->loader_dispatch + i)->DbgRegisterMsgCallback(
1217 pfnMsgCallback, pUserData);
1218 if (res != XGL_SUCCESS) {
1219 gpu_idx = i;
1220 break;
1221 }
Jon Ashburn01e2d662014-11-14 09:52:42 -07001222 }
Jon Ashburn98bd4542015-01-29 16:44:24 -07001223 if (res != XGL_SUCCESS)
1224 break;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001225 }
Jon Ashburn01e2d662014-11-14 09:52:42 -07001226 if (res != XGL_SUCCESS)
1227 break;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001228 }
1229
1230 /* roll back on errors */
1231 if (icd) {
Jon Ashburn98bd4542015-01-29 16:44:24 -07001232 for (struct loader_instance *tmp_inst = loader.instances;
1233 tmp_inst != inst; tmp_inst = tmp_inst->next) {
1234 for (const struct loader_icd * tmp = tmp_inst->icds; tmp != icd;
1235 tmp = tmp->next) {
1236 for (uint32_t i = 0; i < icd->gpu_count; i++)
1237 (tmp->loader_dispatch + i)->DbgUnregisterMsgCallback(pfnMsgCallback);
1238 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001239 }
Jon Ashburn01e2d662014-11-14 09:52:42 -07001240 /* and gpus on current icd */
Mark Lobodzinski17caf572015-01-29 08:55:56 -06001241 for (uint32_t i = 0; i < gpu_idx; i++)
Jon Ashburn01e2d662014-11-14 09:52:42 -07001242 (icd->loader_dispatch + i)->DbgUnregisterMsgCallback(pfnMsgCallback);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001243
1244 return res;
1245 }
1246
1247 return XGL_SUCCESS;
1248}
1249
Chia-I Wu19300602014-08-04 08:03:57 +08001250LOADER_EXPORT XGL_RESULT XGLAPI xglDbgUnregisterMsgCallback(XGL_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001251{
Jon Ashburn98bd4542015-01-29 16:44:24 -07001252 XGL_RESULT res = XGL_SUCCESS;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001253
Jon Ashburn46d1f582015-01-28 11:01:35 -07001254 if (!loader.icds_scanned) {
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001255 return loader_msg_callback_remove(pfnMsgCallback);
1256 }
1257
Jon Ashburn98bd4542015-01-29 16:44:24 -07001258 for (struct loader_instance *inst = loader.instances; inst;
1259 inst = inst->next) {
1260 for (const struct loader_icd * icd = inst->icds; icd;
1261 icd = icd->next) {
1262 for (uint32_t i = 0; i < icd->gpu_count; i++) {
1263 XGL_RESULT r;
1264 r = (icd->loader_dispatch + i)->DbgUnregisterMsgCallback(pfnMsgCallback);
1265 if (r != XGL_SUCCESS) {
1266 res = r;
1267 }
Jon Ashburn01e2d662014-11-14 09:52:42 -07001268 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001269 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001270 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001271 return res;
1272}
1273
Mark Lobodzinski17caf572015-01-29 08:55:56 -06001274LOADER_EXPORT XGL_RESULT XGLAPI xglDbgSetGlobalOption(XGL_DBG_GLOBAL_OPTION dbgOption, size_t dataSize, const void* pData)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001275{
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001276 XGL_RESULT res = XGL_SUCCESS;
1277
Jon Ashburn46d1f582015-01-28 11:01:35 -07001278 if (!loader.icds_scanned) {
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001279 if (dataSize == 0)
1280 return XGL_ERROR_INVALID_VALUE;
1281
1282 switch (dbgOption) {
1283 case XGL_DBG_OPTION_DEBUG_ECHO_ENABLE:
1284 loader.debug_echo_enable = *((const bool *) pData);
1285 break;
1286 case XGL_DBG_OPTION_BREAK_ON_ERROR:
1287 loader.break_on_error = *((const bool *) pData);
1288 break;
1289 case XGL_DBG_OPTION_BREAK_ON_WARNING:
1290 loader.break_on_warning = *((const bool *) pData);
1291 break;
1292 default:
1293 res = XGL_ERROR_INVALID_VALUE;
1294 break;
1295 }
1296
1297 return res;
1298 }
1299
Jon Ashburn98bd4542015-01-29 16:44:24 -07001300 for (struct loader_instance *inst = loader.instances; inst;
1301 inst = inst->next) {
1302 for (const struct loader_icd * icd = inst->icds; icd;
1303 icd = icd->next) {
1304 for (uint32_t i = 0; i < icd->gpu_count; i++) {
1305 XGL_RESULT r;
1306 r = (icd->loader_dispatch + i)->DbgSetGlobalOption(dbgOption,
1307 dataSize, pData);
1308 /* unfortunately we cannot roll back */
1309 if (r != XGL_SUCCESS) {
1310 res = r;
1311 }
Jon Ashburn01e2d662014-11-14 09:52:42 -07001312 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001313 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001314 }
1315
1316 return res;
1317}