VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_context.c@ 55998

Last change on this file since 55998 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: 16.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 "cr_spu.h"
8#include "chromium.h"
9#include "cr_error.h"
10#include "cr_net.h"
11#include "cr_rand.h"
12#include "server_dispatch.h"
13#include "server.h"
14#include "cr_mem.h"
15#include "cr_string.h"
16
17GLint SERVER_DISPATCH_APIENTRY
18crServerDispatchCreateContext(const char *dpyName, GLint visualBits, GLint shareCtx)
19{
20 return crServerDispatchCreateContextEx(dpyName, visualBits, shareCtx, -1, -1);
21}
22
23GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLint shareCtx, GLint preloadCtxID, int32_t internalID)
24{
25 GLint retVal = -1;
26 CRContext *newCtx;
27 CRContextInfo *pContextInfo;
28 GLboolean fFirst = GL_FALSE;
29
30 dpyName = "";
31
32 if (shareCtx > 0) {
33 crWarning("CRServer: context sharing not implemented.");
34 shareCtx = 0;
35 }
36
37 pContextInfo = (CRContextInfo *) crAlloc(sizeof (CRContextInfo));
38 if (!pContextInfo)
39 {
40 crWarning("failed to alloc context info!");
41 return -1;
42 }
43
44 pContextInfo->currentMural = NULL;
45
46 pContextInfo->CreateInfo.requestedVisualBits = visualBits;
47
48 if (cr_server.fVisualBitsDefault)
49 visualBits = cr_server.fVisualBitsDefault;
50
51 pContextInfo->CreateInfo.realVisualBits = visualBits;
52
53 /* Since the Cr server serialized all incoming clients/contexts into
54 * one outgoing GL stream, we only need to create one context for the
55 * head SPU. We'll only have to make it current once too, below.
56 */
57 if (cr_server.firstCallCreateContext) {
58 cr_server.MainContextInfo.CreateInfo.realVisualBits = visualBits;
59 cr_server.MainContextInfo.SpuContext = cr_server.head_spu->dispatch_table.
60 CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.realVisualBits, shareCtx);
61 if (cr_server.MainContextInfo.SpuContext < 0) {
62 crWarning("crServerDispatchCreateContext() failed.");
63 crFree(pContextInfo);
64 return -1;
65 }
66 cr_server.MainContextInfo.pContext = crStateCreateContext(&cr_server.limits, visualBits, NULL);
67 CRASSERT(cr_server.MainContextInfo.pContext);
68 cr_server.firstCallCreateContext = GL_FALSE;
69 fFirst = GL_TRUE;
70
71 cr_server.head_spu->dispatch_table.ChromiumParameteriCR(GL_HH_SET_DEFAULT_SHARED_CTX, cr_server.MainContextInfo.SpuContext);
72 }
73 else {
74 /* second or third or ... context */
75 if (!cr_server.bUseMultipleContexts && ((visualBits & cr_server.MainContextInfo.CreateInfo.realVisualBits) != visualBits)) {
76 int oldSpuContext;
77 /* should never be here */
78 CRASSERT(0);
79 /* the new context needs new visual attributes */
80 cr_server.MainContextInfo.CreateInfo.realVisualBits |= visualBits;
81 crWarning("crServerDispatchCreateContext requires new visual (0x%x).",
82 cr_server.MainContextInfo.CreateInfo.realVisualBits);
83
84 /* Here, we used to just destroy the old rendering context.
85 * Unfortunately, this had the side effect of destroying
86 * all display lists and textures that had been loaded on
87 * the old context as well.
88 *
89 * Now, first try to create a new context, with a suitable
90 * visual, sharing display lists and textures with the
91 * old context. Then destroy the old context.
92 */
93
94 /* create new rendering context with suitable visual */
95 oldSpuContext = cr_server.MainContextInfo.SpuContext;
96 cr_server.MainContextInfo.SpuContext = cr_server.head_spu->dispatch_table.
97 CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.realVisualBits, cr_server.MainContextInfo.SpuContext);
98 /* destroy old rendering context */
99 cr_server.head_spu->dispatch_table.DestroyContext(oldSpuContext);
100 if (cr_server.MainContextInfo.SpuContext < 0) {
101 crWarning("crServerDispatchCreateContext() failed.");
102 crFree(pContextInfo);
103 return -1;
104 }
105
106 /* we do not need to clean up the old default context explicitly, since the above cr_server.head_spu->dispatch_table.DestroyContext call
107 * will do that for us */
108 cr_server.head_spu->dispatch_table.ChromiumParameteriCR(GL_HH_SET_DEFAULT_SHARED_CTX, cr_server.MainContextInfo.SpuContext);
109 }
110 }
111
112 if (cr_server.bUseMultipleContexts) {
113 pContextInfo->SpuContext = cr_server.head_spu->dispatch_table.
114 CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.realVisualBits, cr_server.MainContextInfo.SpuContext);
115 if (pContextInfo->SpuContext < 0) {
116 crWarning("crServerDispatchCreateContext() failed.");
117 crStateEnableDiffOnMakeCurrent(GL_TRUE);
118 cr_server.bUseMultipleContexts = GL_FALSE;
119 if (!fFirst)
120 crError("creating shared context failed, while it is expected to work!");
121 }
122 else if (fFirst)
123 {
124 crStateEnableDiffOnMakeCurrent(GL_FALSE);
125 }
126 }
127 else
128 {
129 pContextInfo->SpuContext = -1;
130 }
131
132 /* Now create a new state-tracker context and initialize the
133 * dispatch function pointers.
134 */
135 newCtx = crStateCreateContextEx(&cr_server.limits, visualBits, NULL, internalID);
136 if (newCtx) {
137 crStateSetCurrentPointers( newCtx, &(cr_server.current) );
138 crStateResetCurrentPointers(&(cr_server.current));
139 retVal = preloadCtxID<0 ? (GLint)crHashtableAllocKeys( cr_server.contextTable, 1 ) : preloadCtxID;
140
141 pContextInfo->pContext = newCtx;
142 Assert(pContextInfo->CreateInfo.realVisualBits == visualBits);
143 pContextInfo->CreateInfo.externalID = retVal;
144 pContextInfo->CreateInfo.pszDpyName = dpyName ? crStrdup(dpyName) : NULL;
145 crHashtableAdd(cr_server.contextTable, retVal, pContextInfo);
146 }
147
148 if (retVal != -1 && !cr_server.bIsInLoadingState) {
149 int pos;
150 for (pos = 0; pos < CR_MAX_CONTEXTS; pos++) {
151 if (cr_server.curClient->contextList[pos] == 0) {
152 cr_server.curClient->contextList[pos] = retVal;
153 break;
154 }
155 }
156 }
157
158 crServerReturnValue( &retVal, sizeof(retVal) );
159
160 return retVal;
161}
162
163static int crServerRemoveClientContext(CRClient *pClient, GLint ctx)
164{
165 int pos;
166
167 for (pos = 0; pos < CR_MAX_CONTEXTS; ++pos)
168 {
169 if (pClient->contextList[pos] == ctx)
170 {
171 pClient->contextList[pos] = 0;
172 return true;
173 }
174 }
175
176 return false;
177}
178
179static void crServerCleanupMuralCtxUsageCB(unsigned long key, void *data1, void *data2)
180{
181 CRMuralInfo *mural = (CRMuralInfo *) data1;
182 CRContext *ctx = (CRContext *) data2;
183
184 CR_STATE_SHAREDOBJ_USAGE_CLEAR(mural, ctx);
185}
186
187void SERVER_DISPATCH_APIENTRY
188crServerDispatchDestroyContext( GLint ctx )
189{
190 CRContextInfo *crCtxInfo;
191 CRContext *crCtx;
192 int32_t client;
193 CRClientNode *pNode;
194 int found=false;
195
196 crCtxInfo = (CRContextInfo *) crHashtableSearch(cr_server.contextTable, ctx);
197 if (!crCtxInfo) {
198 crWarning("CRServer: DestroyContext invalid context %d", ctx);
199 return;
200 }
201 crCtx = crCtxInfo->pContext;
202 CRASSERT(crCtx);
203
204 crDebug("CRServer: DestroyContext context %d", ctx);
205
206 if (cr_server.currentCtxInfo == crCtxInfo)
207 {
208 CRMuralInfo *dummyMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
209 crServerPerformMakeCurrent(dummyMural, &cr_server.MainContextInfo);
210 CRASSERT(cr_server.currentCtxInfo == &cr_server.MainContextInfo);
211 }
212
213 crHashtableWalk(cr_server.muralTable, crServerCleanupMuralCtxUsageCB, crCtx);
214 crCtxInfo->currentMural = NULL;
215 crHashtableDelete(cr_server.contextTable, ctx, NULL);
216 crStateDestroyContext( crCtx );
217
218 if (crCtxInfo->CreateInfo.pszDpyName)
219 crFree(crCtxInfo->CreateInfo.pszDpyName);
220
221 if (crCtxInfo->SpuContext >= 0)
222 cr_server.head_spu->dispatch_table.DestroyContext(crCtxInfo->SpuContext);
223
224 crFree(crCtxInfo);
225
226 if (cr_server.curClient)
227 {
228 /* If we delete our current context, default back to the null context */
229 if (cr_server.curClient->currentCtxInfo == crCtxInfo) {
230 cr_server.curClient->currentContextNumber = -1;
231 cr_server.curClient->currentCtxInfo = &cr_server.MainContextInfo;
232 }
233
234 found = crServerRemoveClientContext(cr_server.curClient, ctx);
235
236 /*Some application call destroy context not in a thread where it was created...have do deal with it.*/
237 if (!found)
238 {
239 for (client=0; client<cr_server.numClients; ++client)
240 {
241 if (cr_server.clients[client]==cr_server.curClient)
242 continue;
243
244 found = crServerRemoveClientContext(cr_server.clients[client], ctx);
245
246 if (found) break;
247 }
248 }
249
250 if (!found)
251 {
252 pNode=cr_server.pCleanupClient;
253
254 while (pNode && !found)
255 {
256 found = crServerRemoveClientContext(pNode->pClient, ctx);
257 pNode = pNode->next;
258 }
259 }
260
261 CRASSERT(found);
262 }
263
264 /*Make sure this context isn't active in other clients*/
265 for (client=0; client<cr_server.numClients; ++client)
266 {
267 if (cr_server.clients[client]->currentCtxInfo == crCtxInfo)
268 {
269 cr_server.clients[client]->currentContextNumber = -1;
270 cr_server.clients[client]->currentCtxInfo = &cr_server.MainContextInfo;
271 }
272 }
273
274 pNode=cr_server.pCleanupClient;
275 while (pNode)
276 {
277 if (pNode->pClient->currentCtxInfo == crCtxInfo)
278 {
279 pNode->pClient->currentContextNumber = -1;
280 pNode->pClient->currentCtxInfo = &cr_server.MainContextInfo;
281 }
282 pNode = pNode->next;
283 }
284
285 CRASSERT(cr_server.currentCtxInfo != crCtxInfo);
286}
287
288void crServerPerformMakeCurrent( CRMuralInfo *mural, CRContextInfo *ctxInfo )
289{
290 CRMuralInfo *oldMural;
291 CRContext *ctx, *oldCtx = NULL;
292 GLuint idDrawFBO, idReadFBO;
293 GLint context = ctxInfo->CreateInfo.externalID;
294 GLint window = mural->CreateInfo.externalID;
295
296 cr_server.bForceMakeCurrentOnClientSwitch = GL_FALSE;
297
298 ctx = ctxInfo->pContext;
299 CRASSERT(ctx);
300
301 oldMural = cr_server.currentMural;
302
303 /* Ubuntu 11.04 hosts misbehave if context window switch is
304 * done with non-default framebuffer object settings.
305 * crStateSwitchPrepare & crStateSwitchPostprocess are supposed to work around this problem
306 * crStateSwitchPrepare restores the FBO state to its default values before the context window switch,
307 * while crStateSwitchPostprocess restores it back to the original values */
308 oldCtx = crStateGetCurrent();
309 if (oldMural && oldMural->fRedirected && crServerSupportRedirMuralFBO())
310 {
311 idDrawFBO = CR_SERVER_FBO_FOR_IDX(oldMural, oldMural->iCurDrawBuffer);
312 idReadFBO = CR_SERVER_FBO_FOR_IDX(oldMural, oldMural->iCurReadBuffer);
313 }
314 else
315 {
316 idDrawFBO = 0;
317 idReadFBO = 0;
318 }
319 crStateSwitchPrepare(cr_server.bUseMultipleContexts ? NULL : ctx, oldCtx, idDrawFBO, idReadFBO);
320
321 if (cr_server.curClient)
322 {
323 /*
324 crDebug("**** %s client %d curCtx=%d curWin=%d", __func__,
325 cr_server.curClient->number, ctxPos, window);
326 */
327 cr_server.curClient->currentContextNumber = context;
328 cr_server.curClient->currentCtxInfo = ctxInfo;
329 cr_server.curClient->currentMural = mural;
330 cr_server.curClient->currentWindow = window;
331
332 CRASSERT(cr_server.curClient->currentCtxInfo);
333 CRASSERT(cr_server.curClient->currentCtxInfo->pContext);
334 }
335
336 /* This is a hack to force updating the 'current' attribs */
337 crStateUpdateColorBits();
338
339 if (ctx)
340 crStateSetCurrentPointers( ctx, &(cr_server.current) );
341
342 /* check if being made current for first time, update viewport */
343#if 0
344 if (ctx) {
345 /* initialize the viewport */
346 if (ctx->viewport.viewportW == 0) {
347 ctx->viewport.viewportW = mural->width;
348 ctx->viewport.viewportH = mural->height;
349 ctx->viewport.scissorW = mural->width;
350 ctx->viewport.scissorH = mural->height;
351 }
352 }
353#endif
354
355 /*
356 crDebug("**** %s currentWindow %d newWindow %d", __func__,
357 cr_server.currentWindow, window);
358 */
359
360 if (1/*cr_server.firstCallMakeCurrent ||
361 cr_server.currentWindow != window ||
362 cr_server.currentNativeWindow != nativeWindow*/) {
363 /* Since the cr server serialized all incoming contexts/clients into
364 * one output stream of GL commands, we only need to call the head
365 * SPU's MakeCurrent() function once.
366 * BUT, if we're rendering to multiple windows, we do have to issue
367 * MakeCurrent() calls sometimes. The same GL context will always be
368 * used though.
369 */
370 cr_server.head_spu->dispatch_table.MakeCurrent( mural->spuWindow,
371 0,
372 ctxInfo->SpuContext >= 0
373 ? ctxInfo->SpuContext
374 : cr_server.MainContextInfo.SpuContext);
375
376 CR_STATE_SHAREDOBJ_USAGE_SET(mural, ctx);
377 if (cr_server.currentCtxInfo)
378 cr_server.currentCtxInfo->currentMural = NULL;
379 ctxInfo->currentMural = mural;
380
381 cr_server.firstCallMakeCurrent = GL_FALSE;
382 cr_server.currentCtxInfo = ctxInfo;
383 cr_server.currentWindow = window;
384 cr_server.currentNativeWindow = 0;
385 cr_server.currentMural = mural;
386 }
387
388 /* This used to be earlier, after crStateUpdateColorBits() call */
389 crStateMakeCurrent( ctx );
390
391 if (mural && mural->fRedirected && crServerSupportRedirMuralFBO())
392 {
393 GLuint id = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
394 if (id != mural->iCurDrawBuffer)
395 {
396 crDebug("DBO draw buffer changed on make current");
397 mural->iCurDrawBuffer = id;
398 }
399
400 id = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
401 if (id != mural->iCurReadBuffer)
402 {
403 crDebug("DBO read buffer changed on make current");
404 mural->iCurReadBuffer = id;
405 }
406
407 idDrawFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer);
408 idReadFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer);
409 }
410 else
411 {
412 idDrawFBO = 0;
413 idReadFBO = 0;
414 }
415 crStateSwitchPostprocess(ctx, cr_server.bUseMultipleContexts ? NULL : oldCtx, idDrawFBO, idReadFBO);
416
417 if (!ctx->framebufferobject.drawFB
418 && (ctx->buffer.drawBuffer == GL_FRONT || ctx->buffer.drawBuffer == GL_FRONT_LEFT)
419 && cr_server.curClient)
420 cr_server.curClient->currentMural->bFbDraw = GL_TRUE;
421
422 if (!mural->fRedirected)
423 {
424 ctx->buffer.width = mural->width;
425 ctx->buffer.height = mural->height;
426 }
427 else
428 {
429 ctx->buffer.width = 0;
430 ctx->buffer.height = 0;
431 }
432}
433
434
435void SERVER_DISPATCH_APIENTRY
436crServerDispatchMakeCurrent( GLint window, GLint nativeWindow, GLint context )
437{
438 CRMuralInfo *mural;
439 CRContextInfo *ctxInfo = NULL;
440
441 if (context >= 0 && window >= 0) {
442 mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
443 if (!mural)
444 {
445 crWarning("CRServer: invalid window %d passed to crServerDispatchMakeCurrent()", window);
446 return;
447 }
448
449 /* Update the state tracker's current context */
450 ctxInfo = (CRContextInfo *) crHashtableSearch(cr_server.contextTable, context);
451 if (!ctxInfo) {
452 crWarning("CRserver: NULL context in MakeCurrent %d", context);
453 return;
454 }
455 }
456 else {
457#if 0
458 oldMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, cr_server.currentWindow);
459 if (oldMural && oldMural->bUseFBO && crServerSupportRedirMuralFBO())
460 {
461 if (!crStateGetCurrent()->framebufferobject.drawFB)
462 {
463 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
464 }
465 if (!crStateGetCurrent()->framebufferobject.readFB)
466 {
467 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
468 }
469 }
470
471 ctxInfo = &cr_server.MainContextInfo;
472 window = -1;
473 mural = NULL;
474#endif
475 cr_server.bForceMakeCurrentOnClientSwitch = GL_TRUE;
476 return;
477 }
478
479 crServerPerformMakeCurrent( mural, ctxInfo );
480}
481
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