VirtualBox

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

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

crOpenGL: correct way of dealing with CreateInfo

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