blob: 5da4d41d8396fa9d9dd5c79c5418be495bfeaf26 [file] [log] [blame]
Chia-I Wu15d86772015-02-21 14:00:17 +08001/*
2 * XGL
3 *
4 * Copyright (C) 2014-2015 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 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28#define _ISOC11_SOURCE /* for aligned_alloc() */
29#include <stdlib.h>
30#include <stdio.h>
31#include <string.h>
32#include "icd-instance.h"
33
34static void * XGLAPI default_alloc(void *user_data, size_t size,
35 size_t alignment,
36 XGL_SYSTEM_ALLOC_TYPE allocType)
37{
38 if (alignment <= 1) {
39 return malloc(size);
Ian Elliott323a4872015-03-06 13:49:44 -070040 } else if (u_is_pow2((unsigned int) alignment)) {
Chia-I Wu15d86772015-02-21 14:00:17 +080041 if (alignment < sizeof(void *)) {
42 assert(u_is_pow2(sizeof(void*)));
43 alignment = sizeof(void *);
44 }
45
46 size = (size + alignment - 1) & ~(alignment - 1);
47
48 return aligned_alloc(alignment, size);
49 }
50 else {
51 return NULL;
52 }
53}
54
55static void XGLAPI default_free(void *user_data, void *ptr)
56{
57 free(ptr);
58}
59
60struct icd_instance *icd_instance_create(const XGL_APPLICATION_INFO *app_info,
61 const XGL_ALLOC_CALLBACKS *alloc_cb)
62{
63 static const XGL_ALLOC_CALLBACKS default_alloc_cb = {
64 .pfnAlloc = default_alloc,
65 .pfnFree = default_free,
66 };
67 struct icd_instance *instance;
68 const char *name;
69 size_t len;
70
71 if (!alloc_cb)
72 alloc_cb = &default_alloc_cb;
73
74 instance = alloc_cb->pfnAlloc(alloc_cb->pUserData, sizeof(*instance), 0,
75 XGL_SYSTEM_ALLOC_API_OBJECT);
76 if (!instance)
77 return NULL;
78
79 memset(instance, 0, sizeof(*instance));
80
81 name = (app_info->pAppName) ? app_info->pAppName : "unnamed";
82 len = strlen(name);
83 instance->name = alloc_cb->pfnAlloc(alloc_cb->pUserData, len + 1, 0,
84 XGL_SYSTEM_ALLOC_INTERNAL);
85 if (!instance->name) {
86 alloc_cb->pfnFree(alloc_cb->pUserData, instance);
87 return NULL;
88 }
89
90 memcpy(instance->name, name, len);
91 instance->name[len] = '\0';
92
93 instance->alloc_cb = *alloc_cb;
94
95 return instance;
96}
97
98void icd_instance_destroy(struct icd_instance *instance)
99{
100 struct icd_instance_logger *logger;
101
102 for (logger = instance->loggers; logger; logger = logger->next) {
103 struct icd_instance_logger *next = logger->next;
104
105 icd_instance_free(instance, logger);
106 logger = next;
107 }
108
109 icd_instance_free(instance, instance->name);
110 icd_instance_free(instance, instance);
111}
112
113XGL_RESULT icd_instance_set_bool(struct icd_instance *instance,
114 XGL_DBG_GLOBAL_OPTION option, bool yes)
115{
116 XGL_RESULT res = XGL_SUCCESS;
117
118 switch (option) {
119 case XGL_DBG_OPTION_DEBUG_ECHO_ENABLE:
120 instance->debug_echo_enable = yes;
121 break;
122 case XGL_DBG_OPTION_BREAK_ON_ERROR:
123 instance->break_on_error = yes;
124 break;
125 case XGL_DBG_OPTION_BREAK_ON_WARNING:
126 instance->break_on_warning = yes;
127 break;
128 default:
129 res = XGL_ERROR_INVALID_VALUE;
130 break;
131 }
132
133 return res;
134}
135
136XGL_RESULT icd_instance_add_logger(struct icd_instance *instance,
137 XGL_DBG_MSG_CALLBACK_FUNCTION func,
138 void *user_data)
139{
140 struct icd_instance_logger *logger;
141
142 for (logger = instance->loggers; logger; logger = logger->next) {
143 if (logger->func == func)
144 break;
145 }
146
147 if (!logger) {
148 logger = icd_instance_alloc(instance, sizeof(*logger), 0,
149 XGL_SYSTEM_ALLOC_DEBUG);
150 if (!logger)
151 return XGL_ERROR_OUT_OF_MEMORY;
152
153 logger->func = func;
154 logger->next = instance->loggers;
155 instance->loggers = logger;
156 }
157
158 logger->user_data = user_data;
159
160 return XGL_SUCCESS;
161}
162
163XGL_RESULT icd_instance_remove_logger(struct icd_instance *instance,
164 XGL_DBG_MSG_CALLBACK_FUNCTION func)
165{
166 struct icd_instance_logger *logger, *prev;
167
168 for (prev = NULL, logger = instance->loggers; logger;
169 prev = logger, logger = logger->next) {
170 if (logger->func == func)
171 break;
172 }
173
174 if (!logger)
175 return XGL_ERROR_INVALID_POINTER;
176
177 if (prev)
178 prev->next = logger->next;
179 else
180 instance->loggers = logger->next;
181
182 icd_instance_free(instance, logger);
183
184 return XGL_SUCCESS;
185}
186
187void icd_instance_log(const struct icd_instance *instance,
188 XGL_DBG_MSG_TYPE msg_type,
189 XGL_VALIDATION_LEVEL validation_level,
190 XGL_BASE_OBJECT src_object,
191 size_t location, int32_t msg_code,
192 const char *msg)
193{
194 const struct icd_instance_logger *logger;
195
196 if (instance->debug_echo_enable || !instance->loggers) {
197 fputs(msg, stderr);
198 fputc('\n', stderr);
199 }
200
201 for (logger = instance->loggers; logger; logger = logger->next) {
202 logger->func(msg_type, validation_level, src_object, location,
203 msg_code, msg, logger->user_data);
204 }
205
206 switch (msg_type) {
207 case XGL_DBG_MSG_ERROR:
208 if (instance->break_on_error)
209 abort();
210 /* fall through */
211 case XGL_DBG_MSG_WARNING:
212 if (instance->break_on_warning)
213 abort();
214 break;
215 default:
216 break;
217 }
218}