VirtualBox

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

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

Host 3D: Chromium server: add Expando SPU and DLM module in order to record and save OpenGL Display Lists (currently disabled).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.8 KB
Line 
1/* $Id: dlm_lists.c 54905 2015-03-23 11:20:58Z vboxsync $ */
2#include <float.h>
3#include "cr_dlm.h"
4#include "cr_mem.h"
5#include "dlm.h"
6
7
8
9/* This file defines the display list functions such as NewList, EndList,
10 * IsList, DeleteLists, etc.
11 * Generally, SPUs will call these as needed to implement display lists.
12 * See the expando, replicate, and tilesort SPUs for examples.
13 *
14 * The functions which compile GL functions into our display lists are named:
15 * void DLM_APIENTRY crdlm_<function name>
16 * where <function_name> is the Chromium function name (which in
17 * turn is the GL function name with the "gl" prefix removed).
18 *
19 * All these entry points require that a CRDLMContextState structure
20 * be created (with crDLMNewContext()) and assigned to the current
21 * thread (with crDLMSetCurrentState()).
22 */
23
24
25/*
26 * Begin compiling a list.
27 */
28void DLM_APIENTRY
29crDLMNewList(GLuint listIdentifier, GLenum mode)
30{
31 DLMListInfo *listInfo;
32 CRDLMContextState *listState = CURRENT_STATE();
33
34 /* Error checks: 0 is not a valid identifier, and
35 * we can't call NewList if NewList has been called
36 * more recently than EndList.
37 *
38 * The caller is expected to check for an improper
39 * mode parameter (GL_INVALID_ENUM), or for a NewList
40 * within a glBegin/glEnd (GL_INVALID_OPERATION).
41 */
42 if (listState == NULL)
43 {
44 crWarning("DLM error: NewList(%d,%d) called with no current state (%s line %d)\n",
45 (int) listIdentifier, (int) mode, __FILE__, __LINE__);
46 return;
47 }
48
49 if (listIdentifier == 0)
50 {
51 crdlm_error(__LINE__, __FILE__, GL_INVALID_VALUE,
52 "NewList called with a list identifier of 0");
53 return;
54 }
55
56 if (listState->currentListInfo != NULL)
57 {
58 char msg[1000];
59 sprintf(msg, "NewList called with display list %d while display list %d was already open",
60 (int) listIdentifier, (int) listState->currentListIdentifier);
61 crdlm_error(__LINE__, __FILE__, GL_INVALID_OPERATION, msg);
62 return;
63 }
64
65 listInfo = (DLMListInfo *) crCalloc(sizeof(DLMListInfo));
66 if (!(listInfo))
67 {
68 char msg[1000];
69 sprintf(msg, "could not allocate %u bytes of memory in NewList",
70 (unsigned) sizeof(DLMListInfo));
71 crdlm_error(__LINE__, __FILE__, GL_OUT_OF_MEMORY, msg);
72 return;
73 }
74
75 listInfo->first = listInfo->last = NULL;
76 listInfo->stateFirst = listInfo->stateLast = NULL;
77 listInfo->references = crAllocHashtable();
78 if (!(listInfo->references))
79 {
80 crFree(listInfo);
81 crdlm_error(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
82 "could not allocate memory in NewList");
83 return;
84 }
85 listInfo->numInstances = 0;
86 listInfo->listSent = GL_FALSE;
87 listInfo->bbox.xmin = FLT_MAX;
88 listInfo->bbox.xmax = -FLT_MAX;
89 listInfo->bbox.ymin = FLT_MAX;
90 listInfo->bbox.ymax = -FLT_MAX;
91 listInfo->bbox.zmin = FLT_MAX;
92 listInfo->bbox.zmax = -FLT_MAX;
93
94 listState->currentListInfo = listInfo;
95 listState->currentListIdentifier = listIdentifier;
96 listState->currentListMode = mode;
97}
98
99
100/* This small utility routine is used to traverse a buffer
101 * list, freeing each buffer. It is used to free the buffer
102 * list in the DLMListInfo structure, both when freeing the
103 * entire structure and when freeing just the retained content.
104 */
105static void free_instance_list(DLMInstanceList * instance)
106{
107 while (instance)
108 {
109 DLMInstanceList *nextInstance = instance->next;
110 crFree(instance);
111 instance = nextInstance;
112 }
113}
114
115/* This utility routine frees a DLMListInfo structure and all
116 * of its components. It is used directly, when deleting a
117 * single list; it is also used as a callback function for
118 * hash tree operations (Free and Replace).
119 *
120 * The parameter is listed as a (void *) instead of a (DLMListInfo *)
121 * in order that the function can be used as a callback routine for
122 * the hash table functions. The (void *) designation causes no
123 * other harm, save disabling type-checking on the pointer argument
124 * of the function.
125 */
126void crdlm_free_list(void *parm)
127{
128 DLMListInfo *listInfo = (DLMListInfo *) parm;
129
130 free_instance_list(listInfo->first);
131 listInfo->first = listInfo->last = NULL;
132
133 /* The references list has no allocated information; it's
134 * just a set of entries. So we don't need to free any
135 * information as each entry is deleted.
136 */
137 crFreeHashtable(listInfo->references, NULL);
138
139 crFree(listInfo);
140}
141
142
143void DLM_APIENTRY crDLMEndList(void)
144{
145 CRDLMContextState *listState = CURRENT_STATE();
146
147 /* Error check: cannot call EndList without a (successful)
148 * preceding NewList.
149 *
150 * The caller is expected to check for glNewList within
151 * a glBegin/glEnd sequence.
152 */
153 if (listState == NULL)
154 {
155 crWarning("DLM error: EndList called with no current state (%s line %d)\n",
156 __FILE__, __LINE__);
157 return;
158 }
159 if (listState->currentListInfo == NULL)
160 {
161 crdlm_error(__LINE__, __FILE__, GL_INVALID_OPERATION,
162 "EndList called while no display list was open");
163 return;
164 }
165
166 DLM_LOCK(listState->dlm)
167
168 /* This function will either replace the list information that's
169 * already present with our new list information, freeing the
170 * former list information; or will add the new information
171 * to the set of display lists, depending on whether the
172 * list already exists or not.
173 */
174 crHashtableReplace(listState->dlm->displayLists,
175 listState->currentListIdentifier,
176 listState->currentListInfo, crdlm_free_list);
177
178 DLM_UNLOCK(listState->dlm)
179
180 /* reset the current state to show the list had been ended */
181 listState->currentListIdentifier = 0;
182 listState->currentListInfo = NULL;
183 listState->currentListMode = GL_FALSE;
184}
185
186
187void DLM_APIENTRY crDLMDeleteLists(GLuint firstListIdentifier, GLsizei range)
188{
189 CRDLMContextState *listState = CURRENT_STATE();
190 register int i;
191
192 if (listState == NULL)
193 {
194 crWarning
195 ("DLM error: DeleteLists(%d,%d) called with no current state (%s line %d)\n",
196 (int) firstListIdentifier, (int) range, __FILE__, __LINE__);
197 return;
198 }
199 if (range < 0)
200 {
201 char msg[1000];
202 sprintf(msg, "DeleteLists called with range (%d) less than zero", (int) range);
203 crdlm_error(__LINE__, __FILE__, GL_INVALID_VALUE, msg);
204 return;
205 }
206
207 /* Interestingly, there doesn't seem to be an error for deleting
208 * display list 0, which cannot exist.
209 *
210 * We could delete the desired lists by walking the entire hash of
211 * display lists and looking for and deleting any in our range; or we
212 * could delete lists one by one. The former is faster if the hashing
213 * algorithm is inefficient or if we're deleting all or most of our
214 * lists; the latter is faster if we're deleting a relatively small
215 * number of lists.
216 *
217 * For now, we'll go with the latter; it's also easier to implement
218 * given the current functions available.
219 */
220 DLM_LOCK(listState->dlm)
221 for (i = 0; i < range; i++)
222 {
223 crHashtableDelete(listState->dlm->displayLists,
224 firstListIdentifier + i, crdlm_free_list);
225 }
226 DLM_UNLOCK(listState->dlm)
227}
228
229GLboolean DLM_APIENTRY crDLMIsList(GLuint list)
230{
231 CRDLMContextState *listState = CURRENT_STATE();
232
233 if (listState == NULL)
234 {
235 crWarning
236 ("DLM error: IsLists(%d) called with no current state (%s line %d)\n",
237 (int) list, __FILE__, __LINE__);
238 return 0;
239 }
240
241 if (list == 0)
242 return GL_FALSE;
243
244 return crHashtableIsKeyUsed(listState->dlm->displayLists, list);
245}
246
247GLuint DLM_APIENTRY crDLMGenLists(GLsizei range)
248{
249 CRDLMContextState *listState = CURRENT_STATE();
250
251 if (listState == NULL)
252 {
253 crWarning
254 ("DLM error: GenLists(%d) called with no current state (%s line %d)\n",
255 (int) range, __FILE__, __LINE__);
256 return 0;
257 }
258
259 return crHashtableAllocKeys(listState->dlm->displayLists, range);
260}
261
262void DLM_APIENTRY crDLMListBase( GLuint base )
263{
264 CRDLMContextState *listState = CURRENT_STATE();
265
266 if (listState == NULL)
267 {
268 crWarning
269 ("DLM error: ListBase(%d) called with no current state (%s line %d)\n",
270 (int) base, __FILE__, __LINE__);
271 return;
272 }
273
274 listState->listBase = base;
275}
Note: See TracBrowser for help on using the repository browser.

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