VirtualBox

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

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

crOpenGL: resource sharing between contexts

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