blob: 9d0abd91ef5ba53d1271833707efe4716d5b2846 [file] [log] [blame]
Chia-I Wu84dace92014-08-03 09:55:18 +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 Wu44e42362014-09-02 08:32:09 +080023 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
Chia-I Wu84dace92014-08-03 09:55:18 +080026 */
27
28#define _ISOC11_SOURCE /* for aligned_alloc */
29#include <stdio.h>
30#include <stdlib.h>
31#include <stdarg.h>
32#include <stdbool.h>
33#include <string.h>
34#include <assert.h>
35
36#include <xgl.h>
37#include <xglDbg.h>
38
39#include "icd.h"
40
41struct icd_msg_callback {
42 XGL_DBG_MSG_CALLBACK_FUNCTION func;
43 XGL_VOID *data;
44
45 struct icd_msg_callback *next;
46};
47
48struct icd {
49 struct icd_msg_callback *msg_callbacks;
50
51 bool debug_echo_enable;
52 bool break_on_error;
53 bool break_on_warning;
54
55 XGL_ALLOC_CALLBACKS alloc_callbacks;
Chia-I Wuc217f802014-08-05 10:17:50 +080056 int init_count;
Chia-I Wu84dace92014-08-03 09:55:18 +080057};
58
59static XGL_VOID *default_alloc(XGL_VOID *user_data,
60 XGL_SIZE size,
61 XGL_SIZE alignment,
62 XGL_SYSTEM_ALLOC_TYPE allocType);
63
64static XGL_VOID default_free(XGL_VOID *user_data,
65 XGL_VOID *mem);
66
67static struct icd icd = {
68 .alloc_callbacks = {
69 .pfnAlloc = default_alloc,
70 .pfnFree = default_free,
71 }
72};
73
74void icd_msg(XGL_DBG_MSG_TYPE msg_type,
75 XGL_VALIDATION_LEVEL validation_level,
76 XGL_BASE_OBJECT src_object,
77 XGL_SIZE location,
78 XGL_INT msg_code,
79 const char *msg)
80{
81 const struct icd_msg_callback *cb = icd.msg_callbacks;
82
83 if (icd.debug_echo_enable || !cb) {
84 fputs(msg, stderr);
85 fputc('\n', stderr);
86 }
87
88 while (cb) {
89 cb->func(msg_type, XGL_VALIDATION_LEVEL_0, XGL_NULL_HANDLE, 0,
90 msg_code, (const XGL_CHAR *) msg, cb->data);
91 cb = cb->next;
92 }
93
94 switch (msg_type) {
95 case XGL_DBG_MSG_ERROR:
96 if (icd.break_on_error) {
97 exit(1);
98 }
99 /* fall through */
100 case XGL_DBG_MSG_WARNING:
101 if (icd.break_on_warning) {
102 exit(1);
103 }
104 break;
105 default:
106 break;
107 }
108}
109
110void icd_vlog(XGL_DBG_MSG_TYPE msg_type,
111 XGL_VALIDATION_LEVEL validation_level,
112 XGL_BASE_OBJECT src_object,
113 XGL_SIZE location,
114 XGL_INT msg_code,
115 const char *format, va_list ap)
116{
117 char msg[256];
118 int ret;
119
120 ret = vsnprintf(msg, sizeof(msg), format, ap);
121 if (ret >= sizeof(msg) || ret < 0) {
122 msg[sizeof(msg) - 1] = '\0';
123 }
124
125 icd_msg(msg_type, validation_level, src_object, location, msg_code, msg);
126}
127
128void icd_log(XGL_DBG_MSG_TYPE msg_type,
129 XGL_VALIDATION_LEVEL validation_level,
130 XGL_BASE_OBJECT src_object,
131 XGL_SIZE location,
132 XGL_INT msg_code,
133 const char *format, ...)
134{
135 va_list ap;
136
137 va_start(ap, format);
138 icd_vlog(msg_type, validation_level, src_object,
139 location, msg_code, format, ap);
140 va_end(ap);
141}
142
143void icd_clear_msg_callbacks(void)
144{
145 struct icd_msg_callback *cb = icd.msg_callbacks;
146
147 while (cb) {
148 struct icd_msg_callback *next = cb->next;
149 free(cb);
150 cb = next;
151 }
152
153 icd.msg_callbacks = NULL;
154}
155
Chia-I Wu468e3c32014-08-04 08:03:57 +0800156ICD_EXPORT XGL_RESULT XGLAPI xglDbgRegisterMsgCallback(XGL_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback, XGL_VOID* pUserData)
Chia-I Wu84dace92014-08-03 09:55:18 +0800157{
158 struct icd_msg_callback *cb;
159
160 cb = malloc(sizeof(*cb));
161 if (!cb)
162 return XGL_ERROR_OUT_OF_MEMORY;
163
164 cb->func = pfnMsgCallback;
165 cb->data = pUserData;
166
167 cb->next = icd.msg_callbacks;
168 icd.msg_callbacks = cb;
169
170 return XGL_SUCCESS;
171}
172
Chia-I Wu468e3c32014-08-04 08:03:57 +0800173ICD_EXPORT XGL_RESULT XGLAPI xglDbgUnregisterMsgCallback(XGL_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback)
Chia-I Wu84dace92014-08-03 09:55:18 +0800174{
175 struct icd_msg_callback *cb = icd.msg_callbacks;
176
177 /*
178 * Find the first match (last registered).
179 *
180 * XXX What if the same callback function is registered more than once?
181 */
182 while (cb) {
183 if (cb->func == pfnMsgCallback) {
184 break;
185 }
186
187 cb = cb->next;
188 }
189
190 if (!cb)
191 return XGL_ERROR_INVALID_POINTER;
192
193 free(cb);
194
195 return XGL_SUCCESS;
196}
197
Chia-I Wu468e3c32014-08-04 08:03:57 +0800198ICD_EXPORT XGL_RESULT XGLAPI xglDbgSetGlobalOption(XGL_DBG_GLOBAL_OPTION dbgOption, XGL_SIZE dataSize, const XGL_VOID* pData)
Chia-I Wu84dace92014-08-03 09:55:18 +0800199{
200 XGL_RESULT res = XGL_SUCCESS;
201
202 if (dataSize == 0)
203 return XGL_ERROR_INVALID_VALUE;
204
205 switch (dbgOption) {
206 case XGL_DBG_OPTION_DEBUG_ECHO_ENABLE:
207 icd.debug_echo_enable = *((const bool *) pData);
208 break;
209 case XGL_DBG_OPTION_BREAK_ON_ERROR:
210 icd.break_on_error = *((const bool *) pData);
211 break;
212 case XGL_DBG_OPTION_BREAK_ON_WARNING:
213 icd.break_on_warning = *((const bool *) pData);
214 break;
215 default:
216 res = XGL_ERROR_INVALID_VALUE;
217 break;
218 }
219
220 return res;
221}
222
Chia-I Wuc217f802014-08-05 10:17:50 +0800223XGL_RESULT icd_set_allocator(const XGL_ALLOC_CALLBACKS *alloc_cb)
Chia-I Wu84dace92014-08-03 09:55:18 +0800224{
Chia-I Wuc217f802014-08-05 10:17:50 +0800225 if (icd.init_count) {
Chia-I Wu3a0e3be2014-08-06 12:08:44 +0800226 const XGL_ALLOC_CALLBACKS default_cb = {
227 NULL, default_alloc, default_free
228 };
229
230 if (!alloc_cb)
231 alloc_cb = &default_cb;
232
Chia-I Wuc217f802014-08-05 10:17:50 +0800233 /*
234 * The spec says: Changing the callbacks on subsequent calls to
235 * xglInitAndEnumerateGpus() causes it to fail with
236 * XGL_ERROR_INVALID_POINTER error.
237 */
Chia-I Wu84dace92014-08-03 09:55:18 +0800238 return (memcmp(&icd.alloc_callbacks, alloc_cb, sizeof(*alloc_cb))) ?
239 XGL_ERROR_INVALID_POINTER : XGL_SUCCESS;
240 }
241
242 if (alloc_cb)
243 icd.alloc_callbacks = *alloc_cb;
244
Chia-I Wuc217f802014-08-05 10:17:50 +0800245 icd.init_count++;
Chia-I Wu84dace92014-08-03 09:55:18 +0800246
247 return XGL_SUCCESS;
248}
249
Chia-I Wuc217f802014-08-05 10:17:50 +0800250int icd_get_allocator_id(void)
251{
252 return icd.init_count;
253}
254
Chia-I Wu84dace92014-08-03 09:55:18 +0800255void *icd_alloc(XGL_SIZE size, XGL_SIZE alignment,
256 XGL_SYSTEM_ALLOC_TYPE type)
257{
258 return icd.alloc_callbacks.pfnAlloc(icd.alloc_callbacks.pUserData,
259 size, alignment, type);
260}
261
262void icd_free(void *mem)
263{
264 icd.alloc_callbacks.pfnFree(icd.alloc_callbacks.pUserData, mem);
265}
266
267static bool is_power_of_two(XGL_SIZE v)
268{
269 return !(v & (v - 1));
270}
271
272static XGL_VOID *default_alloc(XGL_VOID *user_data,
273 XGL_SIZE size,
274 XGL_SIZE alignment,
275 XGL_SYSTEM_ALLOC_TYPE allocType)
276{
277 if (alignment <= 1) {
278 return malloc(size);
279 } else if (is_power_of_two(alignment)) {
280 if (alignment < sizeof(void *)) {
281 assert(is_power_of_two(sizeof(void *)));
282 alignment = sizeof(void *);
283 }
284
285 size = (size + alignment - 1) & ~(alignment - 1);
286
287 return aligned_alloc(alignment, size);
288 }
289 else {
290 return NULL;
291 }
292}
293
294static XGL_VOID default_free(XGL_VOID *user_data,
295 XGL_VOID *mem)
296{
297 free(mem);
298}