VirtualBox

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

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

crOpemGL: bugfix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 13.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
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 GLint spuWindow;
25 VBOXVR_TEXTURE Tex = {0};
26
27 int rc = CrVrScrCompositorInit(&mural->Compositor);
28 if (!RT_SUCCESS(rc))
29 {
30 crWarning("CrVrScrCompositorInit failed, rc %d", rc);
31 return -1;
32 }
33
34 /*
35 * Have first SPU make a new window.
36 */
37 spuWindow = cr_server.head_spu->dispatch_table.WindowCreate( dpyName, visBits );
38 if (spuWindow < 0) {
39 CrVrScrCompositorTerm(&mural->Compositor);
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 Tex.width = dims[0];
47 Tex.height = dims[1];
48 Tex.target = GL_TEXTURE_2D;
49 Tex.hwid = 0;
50 CrVrScrCompositorEntryInit(&mural->CEntry, &Tex);
51
52 defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0);
53 CRASSERT(defaultMural);
54 mural->gX = 0;
55 mural->gY = 0;
56 mural->width = dims[0];
57 mural->height = dims[1];
58
59 mural->spuWindow = spuWindow;
60 mural->screenId = 0;
61 mural->bVisible = GL_FALSE;
62 mural->fUseFBO = CR_SERVER_REDIR_NONE;
63
64 mural->cVisibleRects = 0;
65 mural->pVisibleRects = NULL;
66 mural->bReceivedRects = GL_FALSE;
67
68 mural->pvOutputRedirectInstance = NULL;
69
70 /* generate ID for this new window/mural (special-case for file conns) */
71 if (cr_server.curClient && cr_server.curClient->conn->type == CR_FILE)
72 windowID = spuWindow;
73 else
74 windowID = preloadWinID<0 ? (GLint)crHashtableAllocKeys( cr_server.muralTable, 1 ) : preloadWinID;
75
76 mural->CreateInfo.visualBits = visBits;
77 mural->CreateInfo.externalID = windowID;
78 mural->CreateInfo.pszDpyName = dpyName ? crStrdup(dpyName) : NULL;
79
80 CR_STATE_SHAREDOBJ_USAGE_INIT(mural);
81
82 crServerSetupOutputRedirect(mural);
83
84 return windowID;
85}
86
87GLint
88crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint preloadWinID)
89{
90 CRMuralInfo *mural;
91 GLint windowID = -1;
92
93 if (cr_server.sharedWindows) {
94 int pos, j;
95
96 /* find empty position in my (curclient) windowList */
97 for (pos = 0; pos < CR_MAX_WINDOWS; pos++) {
98 if (cr_server.curClient->windowList[pos] == 0) {
99 break;
100 }
101 }
102 if (pos == CR_MAX_WINDOWS) {
103 crWarning("Too many windows in crserver!");
104 return -1;
105 }
106
107 /* Look if any other client has a window for this slot */
108 for (j = 0; j < cr_server.numClients; j++) {
109 if (cr_server.clients[j]->windowList[pos] != 0) {
110 /* use that client's window */
111 windowID = cr_server.clients[j]->windowList[pos];
112 cr_server.curClient->windowList[pos] = windowID;
113 crServerReturnValue( &windowID, sizeof(windowID) ); /* real return value */
114 crDebug("CRServer: client %p sharing window %d",
115 cr_server.curClient, windowID);
116 return windowID;
117 }
118 }
119 }
120
121
122 /*
123 * Create a new mural for the new window.
124 */
125 mural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
126 if (!mural)
127 {
128 crWarning("crCalloc failed!");
129 return -1;
130 }
131
132 windowID = crServerMuralInit(mural, dpyName, visBits, preloadWinID);
133 if (windowID < 0)
134 {
135 crWarning("crServerMuralInit failed!");
136 crServerReturnValue( &windowID, sizeof(windowID) );
137 crFree(mural);
138 return windowID;
139 }
140
141 crHashtableAdd(cr_server.muralTable, windowID, mural);
142
143 crDebug("CRServer: client %p created new window %d (SPU window %d)",
144 cr_server.curClient, windowID, mural->spuWindow);
145
146 if (windowID != -1 && !cr_server.bIsInLoadingState) {
147 int pos;
148 for (pos = 0; pos < CR_MAX_WINDOWS; pos++) {
149 if (cr_server.curClient->windowList[pos] == 0) {
150 cr_server.curClient->windowList[pos] = windowID;
151 break;
152 }
153 }
154 }
155
156 /* ensure we have a dummy mural created right away to avoid potential deadlocks on VM shutdown */
157 crServerGetDummyMural(mural->CreateInfo.visualBits);
158
159 crServerReturnValue( &windowID, sizeof(windowID) );
160 return windowID;
161}
162
163static int crServerRemoveClientWindow(CRClient *pClient, GLint window)
164{
165 int pos;
166
167 for (pos = 0; pos < CR_MAX_WINDOWS; ++pos)
168 {
169 if (pClient->windowList[pos] == window)
170 {
171 pClient->windowList[pos] = 0;
172 return true;
173 }
174 }
175
176 return false;
177}
178
179void crServerMuralTerm(CRMuralInfo *mural)
180{
181 if (mural->pvOutputRedirectInstance)
182 {
183 cr_server.outputRedirect.CROREnd(mural->pvOutputRedirectInstance);
184 mural->pvOutputRedirectInstance = NULL;
185 }
186
187 crServerRedirMuralFBO(mural, CR_SERVER_REDIR_NONE);
188 crServerDeleteMuralFBO(mural);
189
190 if (cr_server.currentMural == mural)
191 {
192 CRMuralInfo *dummyMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.visualBits);
193 /* reset the current context to some dummy values to ensure render spu does not switch to a default "0" context,
194 * which might lead to muralFBO (offscreen rendering) gl entities being created in a scope of that context */
195 cr_server.head_spu->dispatch_table.MakeCurrent(dummyMural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
196 cr_server.currentWindow = -1;
197 cr_server.currentMural = NULL;
198 }
199 else
200 {
201 CRASSERT(cr_server.currentWindow != mural->CreateInfo.externalID);
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
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 CrVrScrCompositorTerm(&mural->Compositor);
313
314 crHashtableDelete(cr_server.muralTable, window, crFree);
315}
316
317void crServerMuralSize(CRMuralInfo *mural, GLint width, GLint height)
318{
319 if (mural->width != width || mural->height != height)
320 {
321 VBOXVR_TEXTURE Tex;
322 Tex.width = width;
323 Tex.height = height;
324 Tex.target = GL_TEXTURE_2D;
325 Tex.hwid = 0;
326 CrVrScrCompositorLock(&mural->Compositor);
327 CrVrScrCompositorEntryRemove(&mural->Compositor, &mural->CEntry);
328 CrVrScrCompositorUnlock(&mural->Compositor);
329 CrVrScrCompositorEntryInit(&mural->CEntry, &Tex);
330 mural->width = width;
331 mural->height = height;
332 }
333
334 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
335 {
336 crStateGetCurrent()->buffer.width = mural->width;
337 crStateGetCurrent()->buffer.height = mural->height;
338 }
339
340 crServerCheckMuralGeometry(mural);
341
342 cr_server.head_spu->dispatch_table.WindowSize(mural->spuWindow, width, height);
343}
344
345void SERVER_DISPATCH_APIENTRY
346crServerDispatchWindowSize( GLint window, GLint width, GLint height )
347{
348 CRMuralInfo *mural;
349
350 /* crDebug("CRServer: Window %d size %d x %d", window, width, height);*/
351 mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
352 if (!mural) {
353#if EXTRA_WARN
354 crWarning("CRServer: invalid window %d passed to WindowSize()", window);
355#endif
356 return;
357 }
358
359 crServerMuralSize(mural, width, height);
360
361 /* Work-around Intel driver bug */
362 CRASSERT(!cr_server.curClient
363 || !cr_server.curClient->currentMural
364 || cr_server.curClient->currentMural == mural);
365 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
366 {
367 CRContextInfo * ctxInfo = cr_server.currentCtxInfo;
368 CRASSERT(ctxInfo);
369 crServerDispatchMakeCurrent(window, 0, ctxInfo->CreateInfo.externalID);
370 }
371}
372
373
374void SERVER_DISPATCH_APIENTRY
375crServerDispatchWindowPosition( GLint window, GLint x, GLint y )
376{
377 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
378 RTPOINT Pos;
379 /* crDebug("CRServer: Window %d pos %d, %d", window, x, y);*/
380 if (!mural) {
381#if EXTRA_WARN
382 crWarning("CRServer: invalid window %d passed to WindowPosition()", window);
383#endif
384 return;
385 }
386 mural->gX = x;
387 mural->gY = y;
388
389 Pos.x = x;
390 Pos.y = y;
391
392 CrVrScrCompositorLock(&mural->Compositor);
393 CrVrScrCompositorEntryPosSet(&mural->Compositor, &mural->CEntry, &Pos);
394 CrVrScrCompositorUnlock(&mural->Compositor);
395
396 crServerCheckMuralGeometry(mural);
397}
398
399void SERVER_DISPATCH_APIENTRY
400crServerDispatchWindowVisibleRegion( GLint window, GLint cRects, GLint *pRects )
401{
402 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
403 if (!mural) {
404#if EXTRA_WARN
405 crWarning("CRServer: invalid window %d passed to WindowVisibleRegion()", window);
406#endif
407 return;
408 }
409
410 if (mural->pVisibleRects)
411 {
412 crFree(mural->pVisibleRects);
413 mural->pVisibleRects = NULL;
414 }
415
416 mural->cVisibleRects = cRects;
417 mural->bReceivedRects = GL_TRUE;
418 if (cRects)
419 {
420 mural->pVisibleRects = (GLint*) crAlloc(4*sizeof(GLint)*cRects);
421 if (!mural->pVisibleRects)
422 {
423 crError("Out of memory in crServerDispatchWindowVisibleRegion");
424 }
425 crMemcpy(mural->pVisibleRects, pRects, 4*sizeof(GLint)*cRects);
426 }
427
428 cr_server.head_spu->dispatch_table.WindowVisibleRegion(mural->spuWindow, cRects, pRects);
429
430 if (mural->pvOutputRedirectInstance)
431 {
432 /* @todo the code assumes that RTRECT == four GLInts. */
433 cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance,
434 cRects, (RTRECT *)pRects);
435 }
436
437 CrVrScrCompositorLock(&mural->Compositor);
438 CrVrScrCompositorEntryRegionsSet(&mural->Compositor, &mural->CEntry, NULL, cRects, (const RTRECT *)pRects);
439 CrVrScrCompositorUnlock(&mural->Compositor);
440}
441
442
443
444void SERVER_DISPATCH_APIENTRY
445crServerDispatchWindowShow( GLint window, GLint state )
446{
447 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
448 if (!mural) {
449#if EXTRA_WARN
450 crWarning("CRServer: invalid window %d passed to WindowShow()", window);
451#endif
452 return;
453 }
454
455 if (mural->fUseFBO != CR_SERVER_REDIR_FBO_RAM)
456 {
457 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, state);
458 }
459
460 mural->bVisible = state;
461}
462
463
464GLint
465crServerSPUWindowID(GLint serverWindow)
466{
467 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, serverWindow);
468 if (!mural) {
469#if EXTRA_WARN
470 crWarning("CRServer: invalid window %d passed to crServerSPUWindowID()",
471 serverWindow);
472#endif
473 return -1;
474 }
475 return mural->spuWindow;
476}
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