VirtualBox

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

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

crOpenGL: glGetError fixes

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

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