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