VirtualBox

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

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

crOpenGL: misc bugfixes and cleanup

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