VirtualBox

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

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

Host 3D: extend SPU structure with interface for save/restore internal SPU state; provide plug for Expando SPU saving state; drop unused and confusing stuff from DLM module.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.9 KB
Line 
1/* $Id: dlm_lists.c 56473 2015-06-17 11:08:31Z 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 crDebug("Display Lists: create new with guest ID %u.", listIdentifier);
99}
100
101
102/* This small utility routine is used to traverse a buffer
103 * list, freeing each buffer. It is used to free the buffer
104 * list in the DLMListInfo structure, both when freeing the
105 * entire structure and when freeing just the retained content.
106 */
107static void free_instance_list(DLMInstanceList * instance)
108{
109 while (instance)
110 {
111 DLMInstanceList *nextInstance = instance->next;
112 crFree(instance);
113 instance = nextInstance;
114 }
115}
116
117/* This utility routine frees a DLMListInfo structure and all
118 * of its components. It is used directly, when deleting a
119 * single list; it is also used as a callback function for
120 * hash tree operations (Free and Replace).
121 *
122 * The parameter is listed as a (void *) instead of a (DLMListInfo *)
123 * in order that the function can be used as a callback routine for
124 * the hash table functions. The (void *) designation causes no
125 * other harm, save disabling type-checking on the pointer argument
126 * of the function.
127 */
128void crdlm_free_list(void *parm)
129{
130 DLMListInfo *listInfo = (DLMListInfo *) parm;
131
132 free_instance_list(listInfo->first);
133 listInfo->first = listInfo->last = NULL;
134
135 /* The references list has no allocated information; it's
136 * just a set of entries. So we don't need to free any
137 * information as each entry is deleted.
138 */
139 crFreeHashtable(listInfo->references, NULL);
140
141 crFree(listInfo);
142}
143
144
145void DLM_APIENTRY crDLMEndList(void)
146{
147 CRDLMContextState *listState = CURRENT_STATE();
148
149 /* Error check: cannot call EndList without a (successful)
150 * preceding NewList.
151 *
152 * The caller is expected to check for glNewList within
153 * a glBegin/glEnd sequence.
154 */
155 if (listState == NULL)
156 {
157 crWarning("DLM error: EndList called with no current state (%s line %d)\n",
158 __FILE__, __LINE__);
159 return;
160 }
161 if (listState->currentListInfo == NULL)
162 {
163 crdlm_error(__LINE__, __FILE__, GL_INVALID_OPERATION,
164 "EndList called while no display list was open");
165 return;
166 }
167
168 DLM_LOCK(listState->dlm)
169
170 /* This function will either replace the list information that's
171 * already present with our new list information, freeing the
172 * former list information; or will add the new information
173 * to the set of display lists, depending on whether the
174 * list already exists or not.
175 */
176 crHashtableReplace(listState->dlm->displayLists,
177 listState->currentListIdentifier,
178 listState->currentListInfo, crdlm_free_list);
179
180 DLM_UNLOCK(listState->dlm)
181
182 /* reset the current state to show the list had been ended */
183 listState->currentListIdentifier = 0;
184 listState->currentListInfo = NULL;
185 listState->currentListMode = GL_FALSE;
186}
187
188
189void DLM_APIENTRY crDLMDeleteLists(GLuint firstListIdentifier, GLsizei range)
190{
191 CRDLMContextState *listState = CURRENT_STATE();
192 register int i;
193
194 if (listState == NULL)
195 {
196 crWarning
197 ("DLM error: DeleteLists(%d,%d) called with no current state (%s line %d)\n",
198 (int) firstListIdentifier, (int) range, __FILE__, __LINE__);
199 return;
200 }
201 if (range < 0)
202 {
203 char msg[1000];
204 sprintf(msg, "DeleteLists called with range (%d) less than zero", (int) range);
205 crdlm_error(__LINE__, __FILE__, GL_INVALID_VALUE, msg);
206 return;
207 }
208
209 /* Interestingly, there doesn't seem to be an error for deleting
210 * display list 0, which cannot exist.
211 *
212 * We could delete the desired lists by walking the entire hash of
213 * display lists and looking for and deleting any in our range; or we
214 * could delete lists one by one. The former is faster if the hashing
215 * algorithm is inefficient or if we're deleting all or most of our
216 * lists; the latter is faster if we're deleting a relatively small
217 * number of lists.
218 *
219 * For now, we'll go with the latter; it's also easier to implement
220 * given the current functions available.
221 */
222 DLM_LOCK(listState->dlm)
223 for (i = 0; i < range; i++)
224 {
225 crHashtableDelete(listState->dlm->displayLists,
226 firstListIdentifier + i, crdlm_free_list);
227 }
228 DLM_UNLOCK(listState->dlm)
229}
230
231GLboolean DLM_APIENTRY crDLMIsList(GLuint list)
232{
233 CRDLMContextState *listState = CURRENT_STATE();
234
235 if (listState == NULL)
236 {
237 crWarning
238 ("DLM error: IsLists(%d) called with no current state (%s line %d)\n",
239 (int) list, __FILE__, __LINE__);
240 return 0;
241 }
242
243 if (list == 0)
244 return GL_FALSE;
245
246 return crHashtableIsKeyUsed(listState->dlm->displayLists, list);
247}
248
249GLuint DLM_APIENTRY crDLMGenLists(GLsizei range)
250{
251 CRDLMContextState *listState = CURRENT_STATE();
252
253 if (listState == NULL)
254 {
255 crWarning
256 ("DLM error: GenLists(%d) called with no current state (%s line %d)\n",
257 (int) range, __FILE__, __LINE__);
258 return 0;
259 }
260
261 return crHashtableAllocKeys(listState->dlm->displayLists, range);
262}
263
264void DLM_APIENTRY crDLMListBase( GLuint base )
265{
266 CRDLMContextState *listState = CURRENT_STATE();
267
268 if (listState == NULL)
269 {
270 crWarning
271 ("DLM error: ListBase(%d) called with no current state (%s line %d)\n",
272 (int) base, __FILE__, __LINE__);
273 return;
274 }
275
276 listState->listBase = base;
277}
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