blob: 2b22da0fd93184226abd01e81cbcb48520d6e32a [file] [log] [blame]
Chia-I Wue54854a2014-08-05 10:23:50 +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#include "kmd/winsys.h"
26#include "dispatch_tables.h"
27#include "gpu.h"
28#include "dev.h"
29
30static struct intel_queue *queue_create(struct intel_dev *dev,
31 XGL_QUEUE_TYPE type)
32{
33 struct intel_queue *queue;
34
35 queue = icd_alloc(sizeof(*queue), 0, XGL_SYSTEM_ALLOC_API_OBJECT);
36 if (!queue)
37 return NULL;
38
39 memset(queue, 0, sizeof(*queue));
40 queue->dev = dev;
41
42 queue->base.dispatch = dev->base.dispatch;
43 if (dev->base.dbg) {
44 queue->base.dbg =
45 intel_base_dbg_create(XGL_DBG_OBJECT_QUEUE, NULL, 0);
46 if (!queue->base.dbg) {
47 icd_free(queue);
48 return NULL;
49 }
50 }
51
52 return queue;
53}
54
55static void queue_destroy(struct intel_queue *queue)
56{
57 if (queue->base.dbg)
58 intel_base_dbg_destroy(queue->base.dbg);
59 icd_free(queue);
60}
61
62static struct intel_dev_dbg *dev_dbg_create(const XGL_DEVICE_CREATE_INFO *info)
63{
64 struct intel_dev_dbg *dbg;
65
66 dbg = icd_alloc(sizeof(*dbg), 0, XGL_SYSTEM_ALLOC_DEBUG);
67 if (!dbg)
68 return NULL;
69
70 memset(dbg, 0, sizeof(*dbg));
71
72 if (!intel_base_dbg_init(&dbg->base, XGL_DBG_OBJECT_DEVICE,
73 info, sizeof(*info))) {
74 icd_free(dbg);
75 return NULL;
76 }
77
78 return dbg;
79}
80
81static void dev_dbg_destroy(struct intel_dev_dbg *dbg)
82{
83 struct intel_dev_dbg_msg_filter *filter;
84
85 filter = dbg->filters;
86 while (filter) {
87 struct intel_dev_dbg_msg_filter *next = filter->next;
88 icd_free(filter);
89 filter = next;
90 }
91
92 intel_base_dbg_cleanup(&dbg->base);
93 icd_free(dbg);
94}
95
96static XGL_RESULT dev_create_queues(struct intel_dev *dev,
97 const XGL_DEVICE_QUEUE_CREATE_INFO *queues,
98 XGL_UINT count)
99{
100 XGL_UINT i;
101
102 if (!count)
103 return XGL_ERROR_INVALID_POINTER;
104
105 for (i = 0; i < count; i++) {
106 const XGL_DEVICE_QUEUE_CREATE_INFO *q = &queues[i];
107 XGL_RESULT ret = XGL_SUCCESS;
108
109 if (q->queueNodeIndex >= INTEL_GPU_ENGINE_COUNT ||
110 q->queueCount > 1 ||
111 dev->queues[q->queueNodeIndex]) {
112 ret = XGL_ERROR_INVALID_POINTER;
113 }
114 else {
115 dev->queues[q->queueNodeIndex] =
116 queue_create(dev, q->queueNodeIndex);
117 if (!dev->queues[q->queueNodeIndex])
118 ret = XGL_ERROR_OUT_OF_MEMORY;
119 }
120
121 if (ret != XGL_SUCCESS) {
122 XGL_UINT j;
123 for (j = 0; j < i; j++)
124 queue_destroy(dev->queues[j]);
125
126 return ret;
127 }
128 }
129
130 return XGL_SUCCESS;
131}
132
133XGL_RESULT intel_dev_create(struct intel_gpu *gpu,
134 const XGL_DEVICE_CREATE_INFO *info,
135 struct intel_dev **dev_ret)
136{
137 const struct icd_dispatch_table *dispatch;
138 struct intel_dev_dbg *dbg;
139 struct intel_dev *dev;
140 XGL_RESULT ret;
141
142 if (info->extensionCount)
143 return XGL_ERROR_INVALID_EXTENSION;
144
145 if (gpu->fd >= 0)
146 return XGL_ERROR_DEVICE_ALREADY_CREATED;
147
148 dev = icd_alloc(sizeof(*dev), 0, XGL_SYSTEM_ALLOC_API_OBJECT);
149 if (!dev)
150 return XGL_ERROR_OUT_OF_MEMORY;
151
152 memset(dev, 0, sizeof(*dev));
153 dev->gpu = gpu;
154
155 ret = intel_gpu_open(gpu);
156 if (ret != XGL_SUCCESS) {
157 intel_dev_destroy(dev);
158 return ret;
159 }
160
161 dev->winsys = intel_winsys_create_for_fd(gpu->fd);
162 if (!dev->winsys) {
163 icd_log(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, XGL_NULL_HANDLE,
164 0, 0, "failed to create device winsys for %s", gpu->path);
165 intel_dev_destroy(dev);
166 return XGL_ERROR_UNKNOWN;
167 }
168
169 ret = dev_create_queues(dev, info->pRequestedQueues,
170 info->queueRecordCount);
171 if (ret != XGL_SUCCESS) {
172 intel_dev_destroy(dev);
173 return ret;
174 }
175
176 if (info->flags & XGL_DEVICE_CREATE_VALIDATION_BIT) {
177 dispatch = &intel_debug_dispatch_table;
178 dbg = dev_dbg_create(info);
179
180 if (!dbg) {
181 icd_log(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0,
182 XGL_NULL_HANDLE, 0, 0,
183 "failed to create device debug layer for %s", gpu->path);
184 return XGL_ERROR_OUT_OF_MEMORY;
185 }
186 } else {
187 dispatch = &intel_normal_dispatch_table;
188 dbg = NULL;
189 }
190
191 dev->base.dispatch = dispatch;
192 dev->base.dbg = &dbg->base;
193
194 *dev_ret = dev;
195
196 return XGL_SUCCESS;
197}
198
199void intel_dev_destroy(struct intel_dev *dev)
200{
201 XGL_UINT i;
202
203 if (dev->base.dbg)
204 dev_dbg_destroy((struct intel_dev_dbg *) dev->base.dbg);
205
206 for (i = 0; i < ARRAY_SIZE(dev->queues); i++) {
207 if (dev->queues[i])
208 queue_destroy(dev->queues[i]);
209 }
210
211 if (dev->winsys)
212 intel_winsys_destroy(dev->winsys);
213
214 if (dev->gpu->fd >= 0)
215 intel_gpu_close(dev->gpu);
216
217 icd_free(dev);
218}
219
220void intel_dev_get_heap_props(const struct intel_dev *dev,
221 XGL_MEMORY_HEAP_PROPERTIES *props)
222{
223 props->structSize = sizeof(XGL_MEMORY_HEAP_PROPERTIES);
224
225 props->heapMemoryType = XGL_HEAP_MEMORY_LOCAL;
226
227 props->heapSize = 0xffffffff; /* TODO system memory size */
228
229 props->pageSize = 4096;
230 props->flags = XGL_MEMORY_HEAP_CPU_VISIBLE_BIT |
231 XGL_MEMORY_HEAP_CPU_GPU_COHERENT_BIT |
232 XGL_MEMORY_HEAP_CPU_WRITE_COMBINED_BIT |
233 XGL_MEMORY_HEAP_HOLDS_PINNED_BIT |
234 XGL_MEMORY_HEAP_SHAREABLE_BIT;
235
236 props->gpuReadPerfRating = 100.0f;
237 props->gpuWritePerfRating = 100.0f;
238 props->cpuReadPerfRating = 10.0f;
239 props->cpuWritePerfRating = 80.0f;
240}
241
242XGL_RESULT intel_dev_add_msg_filter(struct intel_dev *dev,
243 XGL_INT msg_code,
244 XGL_DBG_MSG_FILTER filter)
245{
246 struct intel_dev_dbg *dbg = intel_dev_dbg(dev);
247 struct intel_dev_dbg_msg_filter *f = dbg->filters;
248
249 assert(filter != XGL_DBG_MSG_FILTER_NONE);
250
251 while (f) {
252 if (f->msg_code == msg_code)
253 break;
254 f = f->next;
255 }
256
257 if (f) {
258 if (f->filter != filter) {
259 f->filter = filter;
260 f->triggered = false;
261 }
262 } else {
263 f = icd_alloc(sizeof(*f), 0, XGL_SYSTEM_ALLOC_DEBUG);
264 if (!f)
265 return XGL_ERROR_OUT_OF_MEMORY;
266
267 f->msg_code = msg_code;
268 f->filter = filter;
269 f->triggered = false;
270
271 f->next = dbg->filters;
272 dbg->filters = f;
273 }
274
275 return XGL_SUCCESS;
276}
277
278void intel_dev_remove_msg_filter(struct intel_dev *dev,
279 XGL_INT msg_code)
280{
281 struct intel_dev_dbg *dbg = intel_dev_dbg(dev);
282 struct intel_dev_dbg_msg_filter *f = dbg->filters, *prev = NULL;
283
284 while (f) {
285 if (f->msg_code == msg_code) {
286 if (prev)
287 prev->next = f->next;
288 else
289 dbg->filters = f->next;
290
291 icd_free(f);
292 break;
293 }
294
295 prev = f;
296 f = f->next;
297 }
298}