VirtualBox

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

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

crOpenGL: saved state fixes & improvements

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