VirtualBox

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

Last change on this file since 37613 was 37613, checked in by vboxsync, 14 years ago

wddm/3d: fix snapshots with aero

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