VirtualBox

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

Last change on this file since 39751 was 39602, checked in by vboxsync, 13 years ago

wine/XPDM: 1. Additional swapchain creation fixes 2. De-libwine'ize wined3d 3. Single context per swapchain 4. wine & crOgl current context sync fixes 5. Proper Get/ReleaseDC handling

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