VirtualBox

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

Last change on this file since 50274 was 50274, checked in by vboxsync, 11 years ago

crOpenGL/osx: impl async window modifications & present handling to prevent deadlocking

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