VirtualBox

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

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

crOpenGL: proper support for GL_NONE,AUX,etc. for offscreen rendering

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

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