VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/dlm/dlm_lists.c@ 56922

Last change on this file since 56922 was 56922, checked in by vboxsync, 10 years ago

3D: Display List: Expando SPU and DLM module code significantly reworked (diff unreadable); first revision when glxgears can be saved and successfully restored; more testing and debugging needed; prelimenary tested ane enabled for Mac hosts only.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.0 KB
Line 
1/* $Id: dlm_lists.c 56922 2015-07-13 10:23:52Z vboxsync $ */
2
3/** @file
4 * Implementation of all the Display Lists related routines:
5 *
6 * glGenLists, glDeleteLists, glNewList, glEndList, glCallList, glCallLists,
7 * glListBase and glIsList.
8 *
9 * Provide OpenGL IDs mapping between host and guest.
10 */
11
12/*
13 * Copyright (C) 2015 Oracle Corporation
14 *
15 * This file is part of VirtualBox Open Source Edition (OSE), as
16 * available from http://www.virtualbox.org. This file is free software;
17 * you can redistribute it and/or modify it under the terms of the GNU
18 * General Public License (GPL) as published by the Free Software
19 * Foundation, in version 2 as it comes in the "COPYING" file of the
20 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
21 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
22 */
23
24#include <float.h>
25#include "cr_dlm.h"
26#include "cr_mem.h"
27#include "dlm.h"
28
29
30/**
31 * Destroy each list entry.
32 */
33static void crdlmFreeDisplayListElements(DLMInstanceList *instance)
34{
35 while (instance)
36 {
37 DLMInstanceList *nextInstance = instance->next;
38 crFree(instance);
39 instance = nextInstance;
40 }
41}
42
43
44/**
45 * A callback routine used when iterating over all
46 * available lists in order to remove them.
47 *
48 * NOTE: @param pParam2 might be NULL.
49 */
50void crdlmFreeDisplayListResourcesCb(void *pParm1, void *pParam2)
51{
52 DLMListInfo *pListInfo = (DLMListInfo *)pParm1;
53 SPUDispatchTable *dispatchTable = (SPUDispatchTable *)pParam2;
54
55 if (pListInfo)
56 {
57 crdlmFreeDisplayListElements(pListInfo->first);
58 pListInfo->first = pListInfo->last = NULL;
59
60 /* Free host OpenGL resources. */
61 if (dispatchTable)
62 dispatchTable->DeleteLists(pListInfo->hwid, 1);
63
64 crFree(pListInfo);
65 }
66}
67
68
69/**
70 * Generate host and guest IDs, setup IDs mapping between host and guest.
71 */
72GLuint DLM_APIENTRY crDLMGenLists(GLsizei range, SPUDispatchTable *dispatchTable)
73{
74 CRDLMContextState *listState = CURRENT_STATE();
75 GLuint idHostRangeStart = 0;
76 GLuint idGuestRangeStart = 0;
77
78 crDebug("DLM: GenLists(%d) (DLM=%p).", range, listState ? listState->dlm : 0);
79
80 if (listState)
81 {
82 idHostRangeStart = dispatchTable->GenLists(range);
83 if (idHostRangeStart > 0)
84 {
85 idGuestRangeStart = crHashtableAllocKeys(listState->dlm->displayLists, range);
86 if (idGuestRangeStart > 0)
87 {
88 GLuint i;
89 bool fSuccess = true;
90
91 /* Now have successfully generated IDs range for host and guest. Let's make IDs association. */
92 for (i = 0; i < (GLuint)range; i++)
93 {
94 DLMListInfo *pListInfo;
95
96 pListInfo = (DLMListInfo *)crCalloc(sizeof(DLMListInfo));
97 if (pListInfo)
98 {
99 crMemset(pListInfo, 0, sizeof(DLMListInfo));
100 pListInfo->hwid = idHostRangeStart + i;
101
102 /* Insert pre-initialized list data which contains IDs mapping into the hash. */
103 crHashtableReplace(listState->dlm->displayLists, idGuestRangeStart + i, pListInfo, NULL);
104 }
105 else
106 {
107 fSuccess = false;
108 break;
109 }
110 }
111
112 /* All structures allocated and initialized successfully. */
113 if (fSuccess)
114 return idGuestRangeStart;
115
116 /* Rollback some data was not allocated. */
117 crDLMDeleteLists(idGuestRangeStart, range, NULL /* we do DeleteLists() later in this routine */ );
118 }
119 else
120 crDebug("DLM: Can't allocate Display List IDs range for the guest.");
121
122 dispatchTable->DeleteLists(idHostRangeStart, range);
123 }
124 else
125 crDebug("DLM: Can't allocate Display List IDs range on the host side.");
126 }
127 else
128 crDebug("DLM: GenLists(%u) called with no current state.", range);
129
130 /* Can't reserve IDs range. */
131 return 0;
132}
133
134
135/**
136 * Release host and guest IDs, free memory resources.
137 */
138void DLM_APIENTRY crDLMDeleteLists(GLuint list, GLsizei range, SPUDispatchTable *dispatchTable)
139{
140 CRDLMContextState *listState = CURRENT_STATE();
141
142 crDebug("DLM: DeleteLists(%u, %d) (DLM=%p).", list, range, listState ? listState->dlm : 0);
143
144 if (listState)
145 {
146 if (range >= 0)
147 {
148 int i;
149
150 /* Free resources: host memory, host IDs and guest IDs. */
151 DLM_LOCK(listState->dlm)
152 for (i = 0; i < range; i++)
153 crHashtableDeleteEx(listState->dlm->displayLists, list + i, crdlmFreeDisplayListResourcesCb, dispatchTable);
154 DLM_UNLOCK(listState->dlm)
155 }
156 else
157 crDebug("DLM: DeleteLists(%u, %d) not allowed.", list, range);
158 }
159 else
160 crDebug("DLM: DeleteLists(%u, %d) called with no current state.", list, range);
161}
162
163
164/**
165 * Start recording a list.
166 */
167void DLM_APIENTRY
168crDLMNewList(GLuint list, GLenum mode, SPUDispatchTable *dispatchTable)
169{
170 DLMListInfo *listInfo;
171 CRDLMContextState *listState = CURRENT_STATE();
172
173 crDebug("DLM: NewList(%u, %u) (DLM=%p).", list, mode, listState ? listState->dlm : 0);
174
175 if (listState)
176 {
177 /* Valid list ID should be > 0. */
178 if (list > 0)
179 {
180 if (listState->currentListInfo == NULL)
181 {
182 listInfo = (DLMListInfo *)crHashtableSearch(listState->dlm->displayLists, list);
183 if (listInfo)
184 {
185 listInfo->first = listInfo->last = NULL;
186 listInfo->stateFirst = listInfo->stateLast = NULL;
187
188 listInfo->numInstances = 0;
189
190 listState->currentListInfo = listInfo;
191 listState->currentListIdentifier = list;
192 listState->currentListMode = mode;
193
194 dispatchTable->NewList(listInfo->hwid, mode);
195
196 crDebug("DLM: create new list with [guest, host] ID pair [%u, %u].", list, listInfo->hwid);
197
198 return;
199 }
200 else
201 crDebug("DLM: Requested Display List %u was not previously reserved with glGenLists().", list);
202 }
203 else
204 crDebug("DLM: NewList called with display list %u while display list %u was already open.", list, listState->currentListIdentifier);
205 }
206 else
207 crDebug("DLM: NewList called with a list identifier of 0.");
208 }
209 else
210 crDebug("DLM: NewList(%u, %u) called with no current state.\n", list, mode);
211}
212
213
214/**
215 * Stop recording a list.
216 */
217void DLM_APIENTRY crDLMEndList(SPUDispatchTable *dispatchTable)
218{
219 CRDLMContextState *listState = CURRENT_STATE();
220
221 crDebug("DLM: EndList() (DLM=%p).", listState ? listState->dlm : 0);
222
223 if (listState)
224 {
225 /* Check if list was ever started. */
226 if (listState->currentListInfo)
227 {
228 /* reset the current state to show the list had been ended */
229 listState->currentListIdentifier = 0;
230 listState->currentListInfo = NULL;
231 listState->currentListMode = GL_FALSE;
232
233 dispatchTable->EndList();
234 }
235 else
236 crDebug("DLM: glEndList() is assuming glNewList() was issued previously.");
237 }
238 else
239 crDebug("DLM: EndList called with no current state.");
240}
241
242
243/**
244 * Execute list on hardware and cach ethis call if we currently recording a list.
245 */
246void DLM_APIENTRY crDLMCallList(GLuint list, SPUDispatchTable *dispatchTable)
247{
248 CRDLMContextState *listState = CURRENT_STATE();
249
250 //crDebug("DLM: CallList(%u).", list);
251
252 if (listState)
253 {
254 DLMListInfo *listInfo;
255
256 /* Add to calls cache if we recording a list. */
257 if (listState->currentListInfo)
258 crDLMCompileCallList(list);
259
260 /* Find hwid for list. */
261 listInfo = (DLMListInfo *)crHashtableSearch(listState->dlm->displayLists, list);
262 if (listInfo)
263 dispatchTable->CallList(listInfo->hwid);
264 else
265 crDebug("DLM: CallList(%u) issued for non-existent list.", list);
266 }
267 else
268 crDebug("DLM: CallList(%u) called with no current state.", list);
269}
270
271
272/* Helper for crDLMCallLists().
273 * We need to extract list ID by index from array of given type and cast it to GLuint.
274 * Please replece it w/ something more elegant if better solution will be found!
275 */
276inline GLuint crDLMGetListByIndex(const GLvoid *aValues, GLsizei index, GLenum type)
277{
278 GLuint element = 0;
279
280 switch (type)
281 {
282#define CRDLM_LIST_BY_INDEX_HANDLE_TYPE(_type_name, _size_of_type) \
283 case _type_name: \
284 { \
285 crMemcpy((void *)&element, (void *)((void *)(aValues) + (index * (_size_of_type))) \
286 , (_size_of_type)); \
287 break; \
288 }
289
290 CRDLM_LIST_BY_INDEX_HANDLE_TYPE(GL_BYTE, sizeof(GLbyte));
291 CRDLM_LIST_BY_INDEX_HANDLE_TYPE(GL_UNSIGNED_BYTE, sizeof(GLubyte));
292 CRDLM_LIST_BY_INDEX_HANDLE_TYPE(GL_SHORT, sizeof(GLshort));
293 CRDLM_LIST_BY_INDEX_HANDLE_TYPE(GL_UNSIGNED_SHORT, sizeof(GLushort));
294 CRDLM_LIST_BY_INDEX_HANDLE_TYPE(GL_INT, sizeof(GLint));
295 CRDLM_LIST_BY_INDEX_HANDLE_TYPE(GL_UNSIGNED_INT, sizeof(GLuint));
296 CRDLM_LIST_BY_INDEX_HANDLE_TYPE(GL_FLOAT, sizeof(GLfloat));
297 CRDLM_LIST_BY_INDEX_HANDLE_TYPE(GL_2_BYTES, 2);
298 CRDLM_LIST_BY_INDEX_HANDLE_TYPE(GL_3_BYTES, 3);
299 CRDLM_LIST_BY_INDEX_HANDLE_TYPE(GL_4_BYTES, 4);
300
301 default:
302 crError("DLM: attempt to pass to crDLMCallLists() unknown type: %u.", index);
303
304#undef CRDLM_LIST_BY_INDEX_HANDLE_TYPE
305 }
306
307 return element;
308}
309
310/**
311 * Execute lists on hardware and cach ethis call if we currently recording a list.
312 */
313void DLM_APIENTRY crDLMCallLists(GLsizei n, GLenum type, const GLvoid *lists, SPUDispatchTable *dispatchTable)
314{
315 CRDLMContextState *listState = CURRENT_STATE();
316
317 crDebug("DLM: CallLists(%d, %u, %p).", n, type, lists);
318
319 if (listState)
320 {
321 GLsizei i;
322
323 /* Add to calls cache if we recording a list. */
324 if (listState->currentListInfo)
325 crDLMCompileCallLists(n, type, lists);
326
327 /* This is sad, but we need to translate guest IDs into host ones.
328 * Since spec does not promise that @param lists conain contiguous set of IDs,
329 * the only way to do that is to iterate over each guest ID and perform translation.
330 * This might have negative performance impact. */
331 for (i = 0; i < n; i++)
332 {
333 DLMListInfo *listInfo;
334 GLuint guest_id = crDLMGetListByIndex(lists, n, type);
335
336 if (guest_id > 0)
337 {
338 listInfo = (DLMListInfo *)crHashtableSearch(listState->dlm->displayLists, guest_id);
339 if (listInfo)
340 dispatchTable->CallList(listInfo->hwid);
341 else
342 crDebug("DLM: CallLists(%d, %u, %p) was unabbe to resolve host ID for guest ID %u.", n, type, lists, guest_id);
343 }
344 else
345 crDebug("DLM: CallLists(%d, %u, %p) received bad array of IDs.", n, type, lists);
346 }
347 }
348 else
349 crDebug("DLM: CallLists(%d, %u, %p) called with no current state.", n, type, lists);
350}
351
352
353/**
354 * Set list base, remember its value and add call to the cache.
355 */
356void DLM_APIENTRY crDLMListBase(GLuint base, SPUDispatchTable *dispatchTable)
357{
358 CRDLMContextState *listState = CURRENT_STATE();
359
360 crDebug("DLM: ListBase(%u).", base);
361
362 if (listState)
363 {
364 listState->listBase = base;
365 crDLMCompileListBase(base);
366 dispatchTable->ListBase(base);
367 }
368 else
369 crDebug("DLM: ListBase(%u) called with no current state.", base);
370}
371
372
373/**
374 * Check if specified list ID belongs to valid Display List.
375 * Positive result is only returned in case both conditions below are satisfied:
376 *
377 * - given list found in DLM hash table (i.e., it was previously allocated
378 * with crDLMGenLists and still not released with crDLMDeleteLists);
379 *
380 * - list is valid on the host side.
381 */
382GLboolean DLM_APIENTRY crDLMIsList(GLuint list, SPUDispatchTable *dispatchTable)
383{
384 CRDLMContextState *listState = CURRENT_STATE();
385
386 crDebug("DLM: IsList(%u).", list);
387
388 if (listState)
389 {
390 if (list > 0)
391 {
392 DLMListInfo *listInfo = (DLMListInfo *)crHashtableSearch(listState->dlm->displayLists, list);
393 if (listInfo)
394 {
395 if (dispatchTable->IsList(listInfo->hwid))
396 return true;
397 else
398 crDebug("DLM: list [%u, %u] not found on the host side.", list, listInfo->hwid);
399 }
400 else
401 crDebug("DLM: list %u not found in guest cache.", list);
402 }
403 else
404 crDebug("DLM: IsList(%u) is not allowed.", list);
405 }
406 else
407 crDebug("DLM: IsList(%u) called with no current state.", list);
408
409 return false;
410}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette