VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c@ 23274

Last change on this file since 23274 was 23274, checked in by vboxsync, 15 years ago

crOpenGL: snapshots support for GLSL shaders

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 12.2 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 "state.h"
8#include "cr_mem.h"
9#include "cr_error.h"
10#include "cr_spu.h"
11
12#ifdef CHROMIUM_THREADSAFE
13CRtsd __contextTSD;
14#else
15CRContext *__currentContext = NULL;
16#endif
17
18CRStateBits *__currentBits = NULL;
19GLboolean g_availableContexts[CR_MAX_CONTEXTS];
20
21static CRContext *defaultContext = NULL;
22
23
24
25/**
26 * Allocate a new shared state object.
27 * Contains texture objects, display lists, etc.
28 */
29static CRSharedState *
30crStateAllocShared(void)
31{
32 CRSharedState *s = (CRSharedState *) crCalloc(sizeof(CRSharedState));
33 if (s) {
34 s->textureTable = crAllocHashtable();
35 s->dlistTable = crAllocHashtable();
36 s->refCount = 1; /* refcount is number of contexts using this state */
37 }
38 return s;
39}
40
41
42
43/**
44 * Callback used for crFreeHashtable().
45 */
46static void
47DeleteTextureCallback(void *texObj)
48{
49 crStateDeleteTextureObject((CRTextureObj *) texObj);
50}
51
52
53/**
54 * Decrement shared state's refcount and delete when it hits zero.
55 */
56static void
57crStateFreeShared(CRSharedState *s)
58{
59 s->refCount--;
60 if (s->refCount <= 0) {
61 crFreeHashtable(s->textureTable, DeleteTextureCallback);
62 crFreeHashtable(s->dlistTable, crFree); /* call crFree for each entry */
63 crFree(s);
64 }
65}
66
67
68/*
69 * Helper for crStateCreateContext, below.
70 */
71static CRContext *
72crStateCreateContextId(int i, const CRLimitsState *limits,
73 GLint visBits, CRContext *shareCtx)
74{
75 CRContext *ctx = (CRContext *) crCalloc( sizeof( *ctx ) );
76 int j;
77 int node32 = i >> 5;
78 int node = i & 0x1f;
79
80 ctx->id = i;
81 ctx->flush_func = NULL;
82 for (j=0;j<CR_MAX_BITARRAY;j++){
83 if (j == node32) {
84 ctx->bitid[j] = (1 << node);
85 } else {
86 ctx->bitid[j] = 0;
87 }
88 ctx->neg_bitid[j] = ~(ctx->bitid[j]);
89 }
90
91 if (shareCtx) {
92 CRASSERT(shareCtx->shared);
93 ctx->shared = shareCtx->shared;
94 ctx->shared->refCount ++;
95 }
96 else {
97 ctx->shared = crStateAllocShared();
98 }
99
100 /* use Chromium's OpenGL defaults */
101 crStateLimitsInit( &(ctx->limits) );
102 crStateExtensionsInit( &(ctx->limits), &(ctx->extensions) );
103
104 crStateBufferObjectInit( ctx ); /* must precede client state init! */
105 crStateClientInit( &(ctx->client) );
106
107 crStateBufferInit( ctx );
108 crStateCurrentInit( ctx );
109 crStateEvaluatorInit( ctx );
110 crStateFogInit( ctx );
111 crStateHintInit( ctx );
112 crStateLightingInit( ctx );
113 crStateLineInit( ctx );
114 crStateListsInit( ctx );
115 crStateMultisampleInit( ctx );
116 crStateOcclusionInit( ctx );
117 crStatePixelInit( ctx );
118 crStatePolygonInit( ctx );
119 crStatePointInit( ctx );
120 crStateProgramInit( ctx );
121 crStateRegCombinerInit( ctx );
122 crStateStencilInit( ctx );
123 crStateTextureInit( ctx );
124 crStateTransformInit( ctx );
125 crStateViewportInit ( ctx );
126 crStateFramebufferObjectInit(ctx);
127 crStateGLSLInit(ctx);
128
129 /* This has to come last. */
130 crStateAttribInit( &(ctx->attrib) );
131
132 ctx->renderMode = GL_RENDER;
133
134 /* Initialize values that depend on the visual mode */
135 if (visBits & CR_DOUBLE_BIT) {
136 ctx->limits.doubleBuffer = GL_TRUE;
137 }
138 if (visBits & CR_RGB_BIT) {
139 ctx->limits.redBits = 8;
140 ctx->limits.greenBits = 8;
141 ctx->limits.blueBits = 8;
142 if (visBits & CR_ALPHA_BIT) {
143 ctx->limits.alphaBits = 8;
144 }
145 }
146 else {
147 ctx->limits.indexBits = 8;
148 }
149 if (visBits & CR_DEPTH_BIT) {
150 ctx->limits.depthBits = 24;
151 }
152 if (visBits & CR_STENCIL_BIT) {
153 ctx->limits.stencilBits = 8;
154 }
155 if (visBits & CR_ACCUM_BIT) {
156 ctx->limits.accumRedBits = 16;
157 ctx->limits.accumGreenBits = 16;
158 ctx->limits.accumBlueBits = 16;
159 if (visBits & CR_ALPHA_BIT) {
160 ctx->limits.accumAlphaBits = 16;
161 }
162 }
163 if (visBits & CR_STEREO_BIT) {
164 ctx->limits.stereo = GL_TRUE;
165 }
166 if (visBits & CR_MULTISAMPLE_BIT) {
167 ctx->limits.sampleBuffers = 1;
168 ctx->limits.samples = 4;
169 ctx->multisample.enabled = GL_TRUE;
170 }
171
172 if (visBits & CR_OVERLAY_BIT) {
173 ctx->limits.level = 1;
174 }
175
176 return ctx;
177}
178
179/*@todo crStateAttribDestroy*/
180static void
181crStateFreeContext(CRContext *ctx)
182{
183 crStateClientDestroy( &(ctx->client) );
184 crStateLimitsDestroy( &(ctx->limits) );
185 crStateBufferObjectDestroy( ctx );
186 crStateEvaluatorDestroy( ctx );
187 crStateListsDestroy( ctx );
188 crStateLightingDestroy( ctx );
189 crStateOcclusionDestroy( ctx );
190 crStateProgramDestroy( ctx );
191 crStateTextureDestroy( ctx );
192 crStateTransformDestroy( ctx );
193 crStateFreeShared(ctx->shared);
194 crStateFramebufferObjectDestroy(ctx);
195 crStateGLSLDestroy(ctx);
196 crFree( ctx );
197}
198
199
200/*
201 * Allocate the state (dirty) bits data structures.
202 * This should be called before we create any contexts.
203 * We'll also create the default/NULL context at this time and make
204 * it the current context by default. This means that if someone
205 * tries to set GL state before calling MakeCurrent() they'll be
206 * modifying the default state object, and not segfaulting on a NULL
207 * pointer somewhere.
208 */
209void crStateInit(void)
210{
211 unsigned int i;
212
213 /* Purely initialize the context bits */
214 if (!__currentBits) {
215 __currentBits = (CRStateBits *) crCalloc( sizeof(CRStateBits) );
216 crStateClientInitBits( &(__currentBits->client) );
217 crStateLightingInitBits( &(__currentBits->lighting) );
218 } else
219 crWarning("State tracker is being re-initialized..\n");
220
221 for (i=0;i<CR_MAX_CONTEXTS;i++)
222 g_availableContexts[i] = 0;
223
224 if (defaultContext) {
225 /* Free the default/NULL context.
226 * Ensures context bits are reset */
227 crStateFreeContext(defaultContext);
228 }
229
230 /* Reset diff_api */
231 crMemZero(&diff_api, sizeof(SPUDispatchTable));
232
233 /* Allocate the default/NULL context */
234 defaultContext = crStateCreateContextId(0, NULL, CR_RGB_BIT, NULL);
235 CRASSERT(g_availableContexts[0] == 0);
236 g_availableContexts[0] = 1; /* in use forever */
237
238#ifdef CHROMIUM_THREADSAFE
239 crSetTSD(&__contextTSD, defaultContext);
240#else
241 __currentContext = defaultContext;
242#endif
243}
244
245
246
247/*
248 * Notes on context switching and the "default context".
249 *
250 * See the paper "Tracking Graphics State for Networked Rendering"
251 * by Ian Buck, Greg Humphries and Pat Hanrahan for background
252 * information about how the state tracker and context switching
253 * works.
254 *
255 * When we make a new context current, we call crStateSwitchContext()
256 * in order to transform the 'from' context into the 'to' context
257 * (i.e. the old context to the new context). The transformation
258 * is accomplished by calling GL functions through the 'diff_api'
259 * so that the downstream GL machine (represented by the __currentContext
260 * structure) is updated to reflect the new context state. Finally,
261 * we point __currentContext to the new context.
262 *
263 * A subtle problem we have to deal with is context destruction.
264 * This issue arose while testing with Glean. We found that when
265 * the currently bound context was getting destroyed that state
266 * tracking was incorrect when a subsequent new context was activated.
267 * In DestroyContext, the __hwcontext was being set to NULL and effectively
268 * going away. Later in MakeCurrent we had no idea what the state of the
269 * downstream GL machine was (since __hwcontext was gone). This meant
270 * we had nothing to 'diff' against and the downstream GL machine was
271 * in an unknown state.
272 *
273 * The solution to this problem is the "default/NULL" context. The
274 * default context is created the first time CreateContext is called
275 * and is never freed. Whenever we get a crStateMakeCurrent(NULL) call
276 * or destroy the currently bound context in crStateDestroyContext()
277 * we call crStateSwitchContext() to switch to the default context and
278 * then set the __currentContext pointer to point to the default context.
279 * This ensures that the dirty bits are updated and the diff_api functions
280 * are called to keep the downstream GL machine in a known state.
281 * Finally, the __hwcontext variable is no longer needed now.
282 *
283 * Yeah, this is kind of a mind-bender, but it really solves the problem
284 * pretty cleanly.
285 *
286 * -Brian
287 */
288
289
290CRContext *
291crStateCreateContext(const CRLimitsState *limits, GLint visBits, CRContext *share)
292{
293 int i;
294
295 /* Must have created the default context via crStateInit() first */
296 CRASSERT(defaultContext);
297
298 for (i = 1 ; i < CR_MAX_CONTEXTS ; i++)
299 {
300 if (!g_availableContexts[i])
301 {
302 g_availableContexts[i] = 1; /* it's no longer available */
303 return crStateCreateContextId( i, limits, visBits, share );
304 }
305 }
306 crError( "Out of available contexts in crStateCreateContexts (max %d)",
307 CR_MAX_CONTEXTS );
308 /* never get here */
309 return NULL;
310}
311
312CRContext *
313crStateCreateContextEx(const CRLimitsState *limits, GLint visBits, CRContext *share, GLint presetID)
314{
315 if (presetID>0)
316 {
317 CRASSERT(!g_availableContexts[presetID]);
318 g_availableContexts[presetID] = 1;
319 return crStateCreateContextId(presetID, limits, visBits, share);
320 }
321 else return crStateCreateContext(limits, visBits, share);
322}
323
324void crStateDestroyContext( CRContext *ctx )
325{
326 CRContext *current = GetCurrentContext();
327
328 if (current == ctx) {
329 /* destroying the current context - have to be careful here */
330 CRASSERT(defaultContext);
331 /* Check to see if the differencer exists first,
332 we may not have one, aka the packspu */
333 if (diff_api.AlphaFunc)
334 crStateSwitchContext(current, defaultContext);
335#ifdef CHROMIUM_THREADSAFE
336 crSetTSD(&__contextTSD, defaultContext);
337#else
338 __currentContext = defaultContext;
339#endif
340 /* ensure matrix state is also current */
341 crStateMatrixMode(defaultContext->transform.matrixMode);
342 }
343 g_availableContexts[ctx->id] = 0;
344
345 crStateFreeContext(ctx);
346}
347
348
349void crStateMakeCurrent( CRContext *ctx )
350{
351 CRContext *current = GetCurrentContext();
352
353 if (ctx == NULL)
354 ctx = defaultContext;
355
356 if (current == ctx)
357 return; /* no-op */
358
359 CRASSERT(ctx);
360
361 if (current) {
362 /* Check to see if the differencer exists first,
363 we may not have one, aka the packspu */
364 if (diff_api.AlphaFunc)
365 crStateSwitchContext( current, ctx );
366 }
367
368#ifdef CHROMIUM_THREADSAFE
369 crSetTSD(&__contextTSD, ctx);
370#else
371 __currentContext = ctx;
372#endif
373
374 /* ensure matrix state is also current */
375 crStateMatrixMode(ctx->transform.matrixMode);
376}
377
378
379/*
380 * As above, but don't call crStateSwitchContext().
381 */
382void crStateSetCurrent( CRContext *ctx )
383{
384 CRContext *current = GetCurrentContext();
385
386 if (ctx == NULL)
387 ctx = defaultContext;
388
389 if (current == ctx)
390 return; /* no-op */
391
392 CRASSERT(ctx);
393
394#ifdef CHROMIUM_THREADSAFE
395 crSetTSD(&__contextTSD, ctx);
396#else
397 __currentContext = ctx;
398#endif
399
400 /* ensure matrix state is also current */
401 crStateMatrixMode(ctx->transform.matrixMode);
402}
403
404
405CRContext *crStateGetCurrent(void)
406{
407 return GetCurrentContext();
408}
409
410
411void crStateUpdateColorBits(void)
412{
413 /* This is a hack to force updating the 'current' attribs */
414 CRStateBits *sb = GetCurrentBits();
415 FILLDIRTY(sb->current.dirty);
416 FILLDIRTY(sb->current.vertexAttrib[VERT_ATTRIB_COLOR0]);
417}
418
419
420void STATE_APIENTRY
421crStateChromiumParameteriCR( GLenum target, GLint value )
422{
423 /* This no-op function helps smooth code-gen */
424}
425
426void STATE_APIENTRY
427crStateChromiumParameterfCR( GLenum target, GLfloat value )
428{
429 /* This no-op function helps smooth code-gen */
430}
431
432void STATE_APIENTRY
433crStateChromiumParametervCR( GLenum target, GLenum type, GLsizei count, const GLvoid *values )
434{
435 /* This no-op function helps smooth code-gen */
436}
437
438void STATE_APIENTRY
439crStateGetChromiumParametervCR( GLenum target, GLuint index, GLenum type, GLsizei count, GLvoid *values )
440{
441 /* This no-op function helps smooth code-gen */
442}
443
444void STATE_APIENTRY
445crStateReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
446 GLenum format, GLenum type, GLvoid *pixels )
447{
448 /* This no-op function helps smooth code-gen */
449}
450
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