VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c@ 44444

Last change on this file since 44444 was 44389, checked in by vboxsync, 12 years ago

crOpenGL: window destuction fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 12.2 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "server.h"
8#include "server_dispatch.h"
9#include "cr_mem.h"
10#include "cr_rand.h"
11#include "cr_string.h"
12
13GLint SERVER_DISPATCH_APIENTRY
14crServerDispatchWindowCreate(const char *dpyName, GLint visBits)
15{
16 return crServerDispatchWindowCreateEx(dpyName, visBits, -1);
17}
18
19GLint crServerMuralInit(CRMuralInfo *mural, const char *dpyName, GLint visBits, GLint preloadWinID)
20{
21 CRMuralInfo *defaultMural;
22 GLint dims[2];
23 GLint windowID = -1;
24 /*
25 * Have first SPU make a new window.
26 */
27 GLint spuWindow = cr_server.head_spu->dispatch_table.WindowCreate( dpyName, visBits );
28 if (spuWindow < 0) {
29 crServerReturnValue( &spuWindow, sizeof(spuWindow) );
30 return spuWindow;
31 }
32
33 /* get initial window size */
34 cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, spuWindow, GL_INT, 2, dims);
35
36 defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0);
37 CRASSERT(defaultMural);
38 mural->gX = 0;
39 mural->gY = 0;
40 mural->width = dims[0];
41 mural->height = dims[1];
42
43 mural->spuWindow = spuWindow;
44 mural->screenId = 0;
45 mural->bVisible = GL_FALSE;
46 mural->fUseFBO = CR_SERVER_REDIR_NONE;
47
48 mural->cVisibleRects = 0;
49 mural->pVisibleRects = NULL;
50 mural->bReceivedRects = GL_FALSE;
51
52 mural->pvOutputRedirectInstance = NULL;
53
54 /* generate ID for this new window/mural (special-case for file conns) */
55 if (cr_server.curClient && cr_server.curClient->conn->type == CR_FILE)
56 windowID = spuWindow;
57 else
58 windowID = preloadWinID<0 ? (GLint)crHashtableAllocKeys( cr_server.muralTable, 1 ) : preloadWinID;
59
60 mural->CreateInfo.visualBits = visBits;
61 mural->CreateInfo.externalID = windowID;
62 mural->CreateInfo.pszDpyName = dpyName ? crStrdup(dpyName) : NULL;
63
64 CR_STATE_SHAREDOBJ_USAGE_INIT(mural);
65
66 crServerSetupOutputRedirect(mural);
67
68 return windowID;
69}
70
71GLint
72crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint preloadWinID)
73{
74 CRMuralInfo *mural;
75 GLint windowID = -1;
76
77 if (cr_server.sharedWindows) {
78 int pos, j;
79
80 /* find empty position in my (curclient) windowList */
81 for (pos = 0; pos < CR_MAX_WINDOWS; pos++) {
82 if (cr_server.curClient->windowList[pos] == 0) {
83 break;
84 }
85 }
86 if (pos == CR_MAX_WINDOWS) {
87 crWarning("Too many windows in crserver!");
88 return -1;
89 }
90
91 /* Look if any other client has a window for this slot */
92 for (j = 0; j < cr_server.numClients; j++) {
93 if (cr_server.clients[j]->windowList[pos] != 0) {
94 /* use that client's window */
95 windowID = cr_server.clients[j]->windowList[pos];
96 cr_server.curClient->windowList[pos] = windowID;
97 crServerReturnValue( &windowID, sizeof(windowID) ); /* real return value */
98 crDebug("CRServer: client %p sharing window %d",
99 cr_server.curClient, windowID);
100 return windowID;
101 }
102 }
103 }
104
105
106 /*
107 * Create a new mural for the new window.
108 */
109 mural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
110 if (!mural)
111 {
112 crWarning("crCalloc failed!");
113 return -1;
114 }
115
116 windowID = crServerMuralInit(mural, dpyName, visBits, preloadWinID);
117 if (windowID < 0)
118 {
119 crWarning("crServerMuralInit failed!");
120 crFree(mural);
121 return windowID;
122 }
123
124 crHashtableAdd(cr_server.muralTable, windowID, mural);
125
126 crDebug("CRServer: client %p created new window %d (SPU window %d)",
127 cr_server.curClient, windowID, mural->spuWindow);
128
129 if (windowID != -1 && !cr_server.bIsInLoadingState) {
130 int pos;
131 for (pos = 0; pos < CR_MAX_WINDOWS; pos++) {
132 if (cr_server.curClient->windowList[pos] == 0) {
133 cr_server.curClient->windowList[pos] = windowID;
134 break;
135 }
136 }
137 }
138
139 crServerReturnValue( &windowID, sizeof(windowID) );
140 return windowID;
141}
142
143static int crServerRemoveClientWindow(CRClient *pClient, GLint window)
144{
145 int pos;
146
147 for (pos = 0; pos < CR_MAX_WINDOWS; ++pos)
148 {
149 if (pClient->windowList[pos] == window)
150 {
151 pClient->windowList[pos] = 0;
152 return true;
153 }
154 }
155
156 return false;
157}
158
159void crServerMuralTerm(CRMuralInfo *mural)
160{
161 if (mural->pvOutputRedirectInstance)
162 {
163 cr_server.outputRedirect.CROREnd(mural->pvOutputRedirectInstance);
164 mural->pvOutputRedirectInstance = NULL;
165 }
166
167 crServerRedirMuralFBO(mural, CR_SERVER_REDIR_NONE);
168 crServerDeleteMuralFBO(mural);
169
170 if (cr_server.currentMural == mural)
171 {
172 CRMuralInfo *dummyMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.visualBits);
173 /* reset the current context to some dummy values to ensure render spu does not switch to a default "0" context,
174 * which might lead to muralFBO (offscreen rendering) gl entities being created in a scope of that context */
175 cr_server.head_spu->dispatch_table.MakeCurrent(dummyMural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
176 cr_server.currentWindow = -1;
177 cr_server.currentMural = NULL;
178 }
179 else
180 {
181 CRASSERT(cr_server.currentWindow != mural->CreateInfo.externalID);
182 }
183
184
185 cr_server.head_spu->dispatch_table.WindowDestroy( mural->spuWindow );
186
187 if (mural->pVisibleRects)
188 {
189 crFree(mural->pVisibleRects);
190 }
191
192 if (mural->CreateInfo.pszDpyName)
193 crFree(mural->CreateInfo.pszDpyName);
194}
195
196static void crServerCleanupCtxMuralRefsCB(unsigned long key, void *data1, void *data2)
197{
198 CRContextInfo *ctxInfo = (CRContextInfo *) data1;
199 CRMuralInfo *mural = (CRMuralInfo *) data2;
200
201 if (ctxInfo->currentMural == mural)
202 ctxInfo->currentMural = NULL;
203}
204
205void SERVER_DISPATCH_APIENTRY
206crServerDispatchWindowDestroy( GLint window )
207{
208 CRMuralInfo *mural;
209 int32_t client;
210 CRClientNode *pNode;
211 int found=false;
212
213 if (!window)
214 {
215 crWarning("Unexpected attempt to delete default mural, ignored!");
216 return;
217 }
218
219 mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
220 if (!mural) {
221 crWarning("CRServer: invalid window %d passed to WindowDestroy()", window);
222 return;
223 }
224
225 crDebug("CRServer: Destroying window %d (spu window %d)", window, mural->spuWindow);
226
227 crHashtableWalk(cr_server.contextTable, crServerCleanupCtxMuralRefsCB, mural);
228
229 crServerMuralTerm(mural);
230
231 CRASSERT(cr_server.currentWindow != window);
232
233 if (cr_server.curClient)
234 {
235 if (cr_server.curClient->currentMural == mural)
236 {
237 cr_server.curClient->currentMural = NULL;
238 cr_server.curClient->currentWindow = -1;
239 }
240
241 found = crServerRemoveClientWindow(cr_server.curClient, window);
242
243 /*Same as with contexts, some apps destroy it not in a thread where it was created*/
244 if (!found)
245 {
246 for (client=0; client<cr_server.numClients; ++client)
247 {
248 if (cr_server.clients[client]==cr_server.curClient)
249 continue;
250
251 found = crServerRemoveClientWindow(cr_server.clients[client], window);
252
253 if (found) break;
254 }
255 }
256
257 if (!found)
258 {
259 pNode=cr_server.pCleanupClient;
260
261 while (pNode && !found)
262 {
263 found = crServerRemoveClientWindow(pNode->pClient, window);
264 pNode = pNode->next;
265 }
266 }
267
268 CRASSERT(found);
269 }
270
271 /*Make sure this window isn't active in other clients*/
272 for (client=0; client<cr_server.numClients; ++client)
273 {
274 if (cr_server.clients[client]->currentMural == mural)
275 {
276 cr_server.clients[client]->currentMural = NULL;
277 cr_server.clients[client]->currentWindow = -1;
278 }
279 }
280
281 pNode=cr_server.pCleanupClient;
282 while (pNode)
283 {
284 if (pNode->pClient->currentMural == mural)
285 {
286 pNode->pClient->currentMural = NULL;
287 pNode->pClient->currentWindow = -1;
288 }
289 pNode = pNode->next;
290 }
291
292 crHashtableDelete(cr_server.muralTable, window, crFree);
293}
294
295void crServerMuralSize(CRMuralInfo *mural, GLint width, GLint height)
296{
297 mural->width = width;
298 mural->height = height;
299
300 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
301 {
302 crStateGetCurrent()->buffer.width = mural->width;
303 crStateGetCurrent()->buffer.height = mural->height;
304 }
305
306 crServerCheckMuralGeometry(mural);
307
308 cr_server.head_spu->dispatch_table.WindowSize(mural->spuWindow, width, height);
309}
310
311void SERVER_DISPATCH_APIENTRY
312crServerDispatchWindowSize( GLint window, GLint width, GLint height )
313{
314 CRMuralInfo *mural;
315
316 /* crDebug("CRServer: Window %d size %d x %d", window, width, height);*/
317 mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
318 if (!mural) {
319#if EXTRA_WARN
320 crWarning("CRServer: invalid window %d passed to WindowSize()", window);
321#endif
322 return;
323 }
324
325 crServerMuralSize(mural, width, height);
326
327 /* Work-around Intel driver bug */
328 CRASSERT(!cr_server.curClient
329 || !cr_server.curClient->currentMural
330 || cr_server.curClient->currentMural == mural);
331 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
332 {
333 CRContextInfo * ctxInfo = cr_server.currentCtxInfo;
334 CRASSERT(ctxInfo);
335 crServerDispatchMakeCurrent(window, 0, ctxInfo->CreateInfo.externalID);
336 }
337}
338
339
340void SERVER_DISPATCH_APIENTRY
341crServerDispatchWindowPosition( GLint window, GLint x, GLint y )
342{
343 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
344 /* crDebug("CRServer: Window %d pos %d, %d", window, x, y);*/
345 if (!mural) {
346#if EXTRA_WARN
347 crWarning("CRServer: invalid window %d passed to WindowPosition()", window);
348#endif
349 return;
350 }
351 mural->gX = x;
352 mural->gY = y;
353
354 crServerCheckMuralGeometry(mural);
355}
356
357void SERVER_DISPATCH_APIENTRY
358crServerDispatchWindowVisibleRegion( GLint window, GLint cRects, GLint *pRects )
359{
360 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
361 if (!mural) {
362#if EXTRA_WARN
363 crWarning("CRServer: invalid window %d passed to WindowVisibleRegion()", window);
364#endif
365 return;
366 }
367
368 if (mural->pVisibleRects)
369 {
370 crFree(mural->pVisibleRects);
371 mural->pVisibleRects = NULL;
372 }
373
374 mural->cVisibleRects = cRects;
375 mural->bReceivedRects = GL_TRUE;
376 if (cRects)
377 {
378 mural->pVisibleRects = (GLint*) crAlloc(4*sizeof(GLint)*cRects);
379 if (!mural->pVisibleRects)
380 {
381 crError("Out of memory in crServerDispatchWindowVisibleRegion");
382 }
383 crMemcpy(mural->pVisibleRects, pRects, 4*sizeof(GLint)*cRects);
384 }
385
386 cr_server.head_spu->dispatch_table.WindowVisibleRegion(mural->spuWindow, cRects, pRects);
387
388 if (mural->pvOutputRedirectInstance)
389 {
390 /* @todo the code assumes that RTRECT == four GLInts. */
391 cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance,
392 cRects, (RTRECT *)pRects);
393 }
394}
395
396
397
398void SERVER_DISPATCH_APIENTRY
399crServerDispatchWindowShow( GLint window, GLint state )
400{
401 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
402 if (!mural) {
403#if EXTRA_WARN
404 crWarning("CRServer: invalid window %d passed to WindowShow()", window);
405#endif
406 return;
407 }
408
409 if (mural->fUseFBO != CR_SERVER_REDIR_FBO_RAM)
410 {
411 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, state);
412 }
413
414 mural->bVisible = state;
415}
416
417
418GLint
419crServerSPUWindowID(GLint serverWindow)
420{
421 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, serverWindow);
422 if (!mural) {
423#if EXTRA_WARN
424 crWarning("CRServer: invalid window %d passed to crServerSPUWindowID()",
425 serverWindow);
426#endif
427 return -1;
428 }
429 return mural->spuWindow;
430}
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