VirtualBox

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

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

crOpenGL: bugfixes, more on new command submission

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