VirtualBox

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

最後變更 在這個檔案從44196是 43932,由 vboxsync 提交於 12 年 前

crOpenGL: host offscreen rendering to fix gnome-shell issues, repaint problems and more

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette