VirtualBox

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

Last change on this file since 21127 was 21127, checked in by vboxsync, 16 years ago

crOpenGL: fix window/context management for multithreaded apps

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 9.1 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 CRCreateInfo_t *pCreateInfo;
28
29 if (shareCtx > 0) {
30 crWarning("CRServer: context sharing not implemented.");
31 shareCtx = 0;
32 }
33
34 /* Since the Cr server serialized all incoming clients/contexts into
35 * one outgoing GL stream, we only need to create one context for the
36 * head SPU. We'll only have to make it current once too, below.
37 */
38 if (cr_server.firstCallCreateContext) {
39 cr_server.SpuContextVisBits = visualBits;
40 cr_server.SpuContext = cr_server.head_spu->dispatch_table.
41 CreateContext(dpyName, cr_server.SpuContextVisBits, shareCtx);
42 if (cr_server.SpuContext < 0) {
43 crWarning("crServerDispatchCreateContext() failed.");
44 return -1;
45 }
46 cr_server.firstCallCreateContext = GL_FALSE;
47 }
48 else {
49 /* second or third or ... context */
50 if ((visualBits & cr_server.SpuContextVisBits) != visualBits) {
51 int oldSpuContext;
52
53 /* the new context needs new visual attributes */
54 cr_server.SpuContextVisBits |= visualBits;
55 crDebug("crServerDispatchCreateContext requires new visual (0x%x).",
56 cr_server.SpuContextVisBits);
57
58 /* Here, we used to just destroy the old rendering context.
59 * Unfortunately, this had the side effect of destroying
60 * all display lists and textures that had been loaded on
61 * the old context as well.
62 *
63 * Now, first try to create a new context, with a suitable
64 * visual, sharing display lists and textures with the
65 * old context. Then destroy the old context.
66 */
67
68 /* create new rendering context with suitable visual */
69 oldSpuContext = cr_server.SpuContext;
70 cr_server.SpuContext = cr_server.head_spu->dispatch_table.
71 CreateContext(dpyName, cr_server.SpuContextVisBits, cr_server.SpuContext);
72 /* destroy old rendering context */
73 cr_server.head_spu->dispatch_table.DestroyContext(oldSpuContext);
74 if (cr_server.SpuContext < 0) {
75 crWarning("crServerDispatchCreateContext() failed.");
76 return -1;
77 }
78 }
79 }
80
81 /* Now create a new state-tracker context and initialize the
82 * dispatch function pointers.
83 */
84 newCtx = crStateCreateContextEx(&cr_server.limits, visualBits, NULL, internalID);
85 if (newCtx) {
86 crStateSetCurrentPointers( newCtx, &(cr_server.current) );
87 crStateResetCurrentPointers(&(cr_server.current));
88 retVal = preloadCtxID<0 ? crServerGenerateID(&cr_server.idsPool.freeContextID) : preloadCtxID;
89 crHashtableAdd(cr_server.contextTable, retVal, newCtx);
90
91 pCreateInfo = (CRCreateInfo_t *) crAlloc(sizeof(CRCreateInfo_t));
92 pCreateInfo->pszDpyName = dpyName ? crStrdup(dpyName) : NULL;
93 pCreateInfo->visualBits = visualBits;
94 pCreateInfo->internalID = newCtx->id;
95 crHashtableAdd(cr_server.pContextCreateInfoTable, retVal, pCreateInfo);
96 }
97
98 if (retVal != -1 && !cr_server.bIsInLoadingState) {
99 int pos;
100 for (pos = 0; pos < CR_MAX_CONTEXTS; pos++) {
101 if (cr_server.curClient->contextList[pos] == 0) {
102 cr_server.curClient->contextList[pos] = retVal;
103 break;
104 }
105 }
106 }
107
108 crServerReturnValue( &retVal, sizeof(retVal) );
109
110 return retVal;
111}
112
113void SERVER_DISPATCH_APIENTRY
114crServerDispatchDestroyContext( GLint ctx )
115{
116 CRContext *crCtx;
117
118 crCtx = (CRContext *) crHashtableSearch(cr_server.contextTable, ctx);
119 if (!crCtx) {
120 crWarning("CRServer: DestroyContext invalid context %d", ctx);
121 return;
122 }
123
124 crDebug("CRServer: DestroyContext context %d", ctx);
125
126 crHashtableDelete(cr_server.contextTable, ctx, NULL);
127 crStateDestroyContext( crCtx );
128 crHashtableDelete(cr_server.pContextCreateInfoTable, ctx, crServerCreateInfoDeleteCB);
129
130 if (cr_server.curClient)
131 {
132 int32_t pos;
133
134 /* If we delete our current context, default back to the null context */
135 if (cr_server.curClient->currentCtx == crCtx) {
136 cr_server.curClient->currentContextNumber = -1;
137 cr_server.curClient->currentCtx = cr_server.DummyContext;
138 }
139
140 for (pos = 0; pos < CR_MAX_CONTEXTS; ++pos)
141 if (cr_server.curClient->contextList[pos] == ctx)
142 {
143 cr_server.curClient->contextList[pos] = 0;
144 break;
145 }
146 CRASSERT(pos<CR_MAX_CONTEXTS);
147 }
148}
149
150
151void SERVER_DISPATCH_APIENTRY
152crServerDispatchMakeCurrent( GLint window, GLint nativeWindow, GLint context )
153{
154 CRMuralInfo *mural;
155 CRContext *ctx;
156
157 if (context >= 0 && window >= 0) {
158 mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
159 if (!mural && window == MAGIC_OFFSET &&
160 !cr_server.clients[0]->conn->actual_network) {
161 /* We're reading from a file and not a real network connection so
162 * we have to fudge the window id here.
163 */
164 window = 0;
165 mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0);
166 }
167 CRASSERT(mural);
168
169 /* Update the state tracker's current context */
170 ctx = (CRContext *) crHashtableSearch(cr_server.contextTable, context);
171 if (!ctx) {
172 crWarning("CRserver: NULL context in MakeCurrent %d", context);
173 return;
174 }
175 }
176 else {
177 ctx = cr_server.DummyContext;
178 window = -1;
179 mural = NULL;
180 return;
181 }
182
183 /*
184 crDebug("**** %s client %d curCtx=%d curWin=%d", __func__,
185 cr_server.curClient->number, ctxPos, window);
186 */
187 cr_server.curClient->currentContextNumber = context;
188 cr_server.curClient->currentCtx = ctx;
189 cr_server.curClient->currentMural = mural;
190 cr_server.curClient->currentWindow = window;
191
192 CRASSERT(cr_server.curClient->currentCtx);
193
194 /* This is a hack to force updating the 'current' attribs */
195 crStateUpdateColorBits();
196
197 if (ctx)
198 crStateSetCurrentPointers( ctx, &(cr_server.current) );
199
200 /* check if being made current for first time, update viewport */
201 if (ctx) {
202 /* initialize the viewport */
203 if (ctx->viewport.viewportW == 0) {
204 ctx->viewport.viewportW = mural->width;
205 ctx->viewport.viewportH = mural->height;
206 ctx->viewport.scissorW = mural->width;
207 ctx->viewport.scissorH = mural->height;
208 }
209 }
210
211 /*
212 crDebug("**** %s currentWindow %d newWindow %d", __func__,
213 cr_server.currentWindow, window);
214 */
215
216 if (1/*cr_server.firstCallMakeCurrent ||
217 cr_server.currentWindow != window ||
218 cr_server.currentNativeWindow != nativeWindow*/) {
219 /* Since the cr server serialized all incoming contexts/clients into
220 * one output stream of GL commands, we only need to call the head
221 * SPU's MakeCurrent() function once.
222 * BUT, if we're rendering to multiple windows, we do have to issue
223 * MakeCurrent() calls sometimes. The same GL context will always be
224 * used though.
225 */
226 cr_server.head_spu->dispatch_table.MakeCurrent( mural->spuWindow,
227 nativeWindow,
228 cr_server.SpuContext );
229 cr_server.firstCallMakeCurrent = GL_FALSE;
230 cr_server.currentWindow = window;
231 cr_server.currentNativeWindow = nativeWindow;
232
233 /* Set initial raster/window position for this context.
234 * The position has to be translated according to the tile origin.
235 */
236 if (mural->numExtents > 0)
237 {
238 GLint x = -mural->extents[0].imagewindow.x1;
239 GLint y = -mural->extents[0].imagewindow.y1;
240 cr_server.head_spu->dispatch_table.WindowPos2iARB(x, y);
241 /* This MakeCurrent is a bit redundant (we do it again below)
242 * but it's only done the first time we activate a context.
243 */
244 crStateMakeCurrent(ctx);
245 crStateWindowPos2iARB(x, y);
246 }
247 }
248
249 /* This used to be earlier, after crStateUpdateColorBits() call */
250 crStateMakeCurrent( ctx );
251
252 /* This is pessimistic - we really don't have to invalidate the viewport
253 * info every time we MakeCurrent, but play it safe for now.
254 */
255 mural->viewportValidated = GL_FALSE;
256}
257
Note: See TracBrowser for help on using the repository browser.

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