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 | #ifndef CR_SERVER_H
|
---|
8 | #define CR_SERVER_H
|
---|
9 |
|
---|
10 | #include "cr_protocol.h"
|
---|
11 | #include "cr_glstate.h"
|
---|
12 | #include "spu_dispatch_table.h"
|
---|
13 |
|
---|
14 | #include "state/cr_currentpointers.h"
|
---|
15 |
|
---|
16 | #include "cr_server.h"
|
---|
17 |
|
---|
18 | #ifdef VBOX_WITH_CRHGSMI
|
---|
19 | # include <VBox/VBoxVideo.h>
|
---|
20 |
|
---|
21 | #include <iprt/cdefs.h>
|
---|
22 |
|
---|
23 | RT_C_DECLS_BEGIN
|
---|
24 |
|
---|
25 | extern uint8_t* g_pvVRamBase;
|
---|
26 | extern uint32_t g_cbVRam;
|
---|
27 | extern HCRHGSMICMDCOMPLETION g_hCrHgsmiCompletion;
|
---|
28 | extern PFNCRHGSMICMDCOMPLETION g_pfnCrHgsmiCompletion;
|
---|
29 |
|
---|
30 | #define VBOXCRHGSMI_PTR(_off, _t) ((_t*)(g_pvVRamBase + (_off)))
|
---|
31 | #define VBOXCRHGSMI_PTR_SAFE(_off, _cb, _t) ((_t*)crServerCrHgsmiPtrGet(_off, _cb))
|
---|
32 |
|
---|
33 | DECLINLINE(void*) crServerCrHgsmiPtrGet(VBOXVIDEOOFFSET offBuffer, uint32_t cbBuffer)
|
---|
34 | {
|
---|
35 | return ((offBuffer) + (cbBuffer) <= g_cbVRam ? VBOXCRHGSMI_PTR(offBuffer, void) : NULL);
|
---|
36 | }
|
---|
37 |
|
---|
38 | DECLINLINE(void) crServerCrHgsmiCmdComplete(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, int cmdProcessingRc)
|
---|
39 | {
|
---|
40 | g_pfnCrHgsmiCompletion(g_hCrHgsmiCompletion, pCmd, cmdProcessingRc);
|
---|
41 | }
|
---|
42 |
|
---|
43 | #define VBOXCRHGSMI_CMD_COMPLETE(_pData, _rc) do { \
|
---|
44 | CRVBOXHGSMI_CMDDATA_ASSERT_ISSET(_pData); \
|
---|
45 | CRVBOXHGSMI_CMDDATA_RC(_pData, _rc); \
|
---|
46 | crServerCrHgsmiCmdComplete((_pData)->pCmd, VINF_SUCCESS); \
|
---|
47 | } while (0)
|
---|
48 |
|
---|
49 | #define VBOXCRHGSMI_CMD_CHECK_COMPLETE(_pData, _rc) do { \
|
---|
50 | if (CRVBOXHGSMI_CMDDATA_IS_SET(_pData)) { \
|
---|
51 | VBOXCRHGSMI_CMD_COMPLETE(_pData, _rc); \
|
---|
52 | } \
|
---|
53 | } while (0)
|
---|
54 |
|
---|
55 | #endif
|
---|
56 |
|
---|
57 | /*
|
---|
58 | * This is the base number for window and context IDs
|
---|
59 | */
|
---|
60 | #define MAGIC_OFFSET 5000
|
---|
61 |
|
---|
62 | extern CRServer cr_server;
|
---|
63 |
|
---|
64 | /* Semaphore wait queue node */
|
---|
65 | typedef struct _wqnode {
|
---|
66 | RunQueue *q;
|
---|
67 | struct _wqnode *next;
|
---|
68 | } wqnode;
|
---|
69 |
|
---|
70 | typedef struct {
|
---|
71 | GLuint count;
|
---|
72 | GLuint num_waiting;
|
---|
73 | RunQueue **waiting;
|
---|
74 | } CRServerBarrier;
|
---|
75 |
|
---|
76 | typedef struct {
|
---|
77 | GLuint count;
|
---|
78 | wqnode *waiting, *tail;
|
---|
79 | } CRServerSemaphore;
|
---|
80 |
|
---|
81 | typedef struct {
|
---|
82 | GLuint id;
|
---|
83 | GLint projParamStart;
|
---|
84 | GLfloat projMat[16]; /* projection matrix, accumulated via calls to */
|
---|
85 | /* glProgramLocalParameterARB, glProgramParameterNV */
|
---|
86 | } CRServerProgram;
|
---|
87 |
|
---|
88 | void crServerSetVBoxConfiguration();
|
---|
89 | void crServerSetVBoxConfigurationHGCM();
|
---|
90 | void crServerInitDispatch(void);
|
---|
91 | void crServerReturnValue( const void *payload, unsigned int payload_len );
|
---|
92 | void crServerWriteback(void);
|
---|
93 | int crServerRecv( CRConnection *conn, CRMessage *msg, unsigned int len );
|
---|
94 | void crServerSerializeRemoteStreams(void);
|
---|
95 | void crServerAddToRunQueue( CRClient *client );
|
---|
96 | void crServerDeleteClient( CRClient *client );
|
---|
97 |
|
---|
98 |
|
---|
99 | void crServerApplyBaseProjection( const CRmatrix *baseProj );
|
---|
100 | void crServerApplyViewMatrix( const CRmatrix *view );
|
---|
101 | void crServerSetOutputBounds( const CRMuralInfo *mural, int extNum );
|
---|
102 | void crServerComputeViewportBounds( const CRViewportState *v, CRMuralInfo *mural );
|
---|
103 |
|
---|
104 | GLboolean crServerInitializeBucketing(CRMuralInfo *mural);
|
---|
105 |
|
---|
106 | void crComputeOverlapGeom(double *quads, int nquad, CRPoly ***res);
|
---|
107 | void crComputeKnockoutGeom(double *quads, int nquad, int my_quad_idx, CRPoly **res);
|
---|
108 |
|
---|
109 | int crServerGetCurrentEye(void);
|
---|
110 |
|
---|
111 | GLboolean crServerClientInBeginEnd(const CRClient *client);
|
---|
112 |
|
---|
113 | GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLint shareCtx, GLint preloadCtxID, int32_t internalID);
|
---|
114 | GLint crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint preloadWinID);
|
---|
115 | GLint crServerMuralInit(CRMuralInfo *mural, const char *dpyName, GLint visBits, GLint preloadWinID);
|
---|
116 | void crServerMuralTerm(CRMuralInfo *mural);
|
---|
117 | void crServerMuralSize(CRMuralInfo *mural, GLint width, GLint height);
|
---|
118 | int crServerMuralSynchRootVr(CRMuralInfo *mural, uint32_t *pcRects, const RTRECT **ppRects);
|
---|
119 |
|
---|
120 | GLint crServerGenerateID(GLint *pCounter);
|
---|
121 |
|
---|
122 | GLint crServerSPUWindowID(GLint serverWindow);
|
---|
123 |
|
---|
124 | GLuint crServerTranslateProgramID(GLuint id);
|
---|
125 |
|
---|
126 | CRMuralInfo * crServerGetDummyMural(GLint visualBits);
|
---|
127 |
|
---|
128 | void crServerSetupOutputRedirect(CRMuralInfo *mural);
|
---|
129 | void crServerCheckMuralGeometry(CRMuralInfo *mural);
|
---|
130 | GLboolean crServerSupportRedirMuralFBO(void);
|
---|
131 |
|
---|
132 | #define CR_SERVER_REDIR_F_NONE 0x00
|
---|
133 | /* the data should be displayed on host (unset when is on or when CR_SERVER_REDIR_F_FBO_RAM_VMFB is set) */
|
---|
134 | #define CR_SERVER_REDIR_F_DISPLAY 0x01
|
---|
135 | /* guest window data get redirected to FBO on host */
|
---|
136 | #define CR_SERVER_REDIR_F_FBO 0x02
|
---|
137 | /* used with CR_SERVER_REDIR_F_FBO only
|
---|
138 | * indicates that FBO data should be copied to RAM for further processing */
|
---|
139 | #define CR_SERVER_REDIR_F_FBO_RAM 0x04
|
---|
140 | /* used with CR_SERVER_REDIR_F_FBO_RAM only
|
---|
141 | * indicates that FBO data should be passed to VRDP backend */
|
---|
142 | #define CR_SERVER_REDIR_F_FBO_RAM_VRDP 0x08
|
---|
143 | /* used with CR_SERVER_REDIR_F_FBO_RAM only
|
---|
144 | * indicates that FBO data should be passed to VM Framebuffer */
|
---|
145 | #define CR_SERVER_REDIR_F_FBO_RAM_VMFB 0x10
|
---|
146 | /* used with CR_SERVER_REDIR_F_FBO_RAM only
|
---|
147 | * makes the RPW (Read Pixels Worker) mechanism to be used for GPU memory aquisition */
|
---|
148 | #define CR_SERVER_REDIR_F_FBO_RPW 0x20
|
---|
149 |
|
---|
150 |
|
---|
151 | #define CR_SERVER_REDIR_F_ALL 0x3f
|
---|
152 |
|
---|
153 | #define CR_SERVER_REDIR_FGROUP_REQUIRE_FBO (CR_SERVER_REDIR_F_ALL & ~CR_SERVER_REDIR_F_DISPLAY)
|
---|
154 | #define CR_SERVER_REDIR_FGROUP_REQUIRE_FBO_RAM (CR_SERVER_REDIR_F_FBO_RAM_VRDP | CR_SERVER_REDIR_F_FBO_RAM_VMFB | CR_SERVER_REDIR_F_FBO_RPW)
|
---|
155 |
|
---|
156 | DECLINLINE(GLuint) crServerRedirModeAdjust(GLuint value)
|
---|
157 | {
|
---|
158 | /* sanitize values */
|
---|
159 | value &= CR_SERVER_REDIR_F_ALL;
|
---|
160 |
|
---|
161 | if (value & CR_SERVER_REDIR_FGROUP_REQUIRE_FBO)
|
---|
162 | value |= CR_SERVER_REDIR_F_FBO;
|
---|
163 | if (value & CR_SERVER_REDIR_FGROUP_REQUIRE_FBO_RAM)
|
---|
164 | value |= CR_SERVER_REDIR_F_FBO_RAM;
|
---|
165 |
|
---|
166 | return value;
|
---|
167 | }
|
---|
168 |
|
---|
169 | int32_t crServerSetOffscreenRenderingMode(GLuint value);
|
---|
170 | void crServerRedirMuralFBO(CRMuralInfo *mural, GLuint redir);
|
---|
171 | void crServerDeleteMuralFBO(CRMuralInfo *mural);
|
---|
172 | void crServerPresentFBO(CRMuralInfo *mural);
|
---|
173 | GLboolean crServerIsRedirectedToFBO();
|
---|
174 | GLuint crServerMuralFBOIdxFromBufferName(CRMuralInfo *mural, GLenum buffer);
|
---|
175 | void crServerMuralFBOSwapBuffers(CRMuralInfo *mural);
|
---|
176 |
|
---|
177 | void crServerVBoxCompositionDisableEnter(CRMuralInfo *mural);
|
---|
178 | void crServerVBoxCompositionDisableLeave(CRMuralInfo *mural, GLboolean fForcePresentOnEnabled);
|
---|
179 | void crServerVBoxCompositionPresent(CRMuralInfo *mural);
|
---|
180 | DECLINLINE(GLboolean) crServerVBoxCompositionPresentNeeded(CRMuralInfo *mural)
|
---|
181 | {
|
---|
182 | return mural->bVisible
|
---|
183 | && mural->width
|
---|
184 | && mural->height
|
---|
185 | && !mural->fRootVrOn ? CrVrScrCompositorEntryIsInList(&mural->CEntry) : CrVrScrCompositorEntryIsInList(&mural->RootVrCEntry);
|
---|
186 | }
|
---|
187 |
|
---|
188 | #define CR_SERVER_FBO_BB_IDX(_mural) ((_mural)->iBbBuffer)
|
---|
189 | #define CR_SERVER_FBO_FB_IDX(_mural) (((_mural)->iBbBuffer + 1) % ((_mural)->cBuffers))
|
---|
190 |
|
---|
191 | int32_t crVBoxServerInternalClientRead(CRClient *pClient, uint8_t *pBuffer, uint32_t *pcbBuffer);
|
---|
192 |
|
---|
193 | PCR_DISPLAY crServerDisplayGetInitialized(uint32_t idScreen);
|
---|
194 |
|
---|
195 | void crServerPerformMakeCurrent( CRMuralInfo *mural, CRContextInfo *ctxInfo );
|
---|
196 |
|
---|
197 | PCR_BLITTER crServerVBoxBlitterGet();
|
---|
198 |
|
---|
199 | DECLINLINE(void) crServerVBoxBlitterWinInit(CR_BLITTER_WINDOW *win, CRMuralInfo *mural)
|
---|
200 | {
|
---|
201 | win->Base.id = mural->spuWindow;
|
---|
202 | win->Base.visualBits = mural->CreateInfo.visualBits;
|
---|
203 | win->width = mural->width;
|
---|
204 | win->height = mural->height;
|
---|
205 | }
|
---|
206 |
|
---|
207 | DECLINLINE(void) crServerVBoxBlitterCtxInit(CR_BLITTER_CONTEXT *ctx, CRContextInfo *ctxInfo)
|
---|
208 | {
|
---|
209 | ctx->Base.id = ctxInfo->SpuContext;
|
---|
210 | if (ctx->Base.id < 0)
|
---|
211 | ctx->Base.id = cr_server.MainContextInfo.SpuContext;
|
---|
212 | ctx->Base.visualBits = cr_server.curClient->currentCtxInfo->CreateInfo.visualBits;
|
---|
213 | }
|
---|
214 |
|
---|
215 | /* display worker thread.
|
---|
216 | * see comments for CR_SERVER_RPW struct definition in cr_server.h */
|
---|
217 | DECLINLINE(void) crServerXchgI8(int8_t *pu8Val1, int8_t *pu8Val2)
|
---|
218 | {
|
---|
219 | int8_t tmp;
|
---|
220 | tmp = *pu8Val1;
|
---|
221 | *pu8Val1 = *pu8Val2;
|
---|
222 | *pu8Val2 = tmp;
|
---|
223 | }
|
---|
224 |
|
---|
225 | #ifdef DEBUG_misha
|
---|
226 | # define CR_SERVER_RPW_DEBUG
|
---|
227 | #endif
|
---|
228 | /* *
|
---|
229 | * _name : Draw, Submitted, Worker, Gpu
|
---|
230 | */
|
---|
231 |
|
---|
232 | #ifdef CR_SERVER_RPW_DEBUG
|
---|
233 | # define crServerRpwEntryDbgVerify(_pE) crServerRpwEntryDbgDoVerify(_pE)
|
---|
234 | #else
|
---|
235 | # define crServerRpwEntryDbgVerify(_pE) do {} while (0)
|
---|
236 | #endif
|
---|
237 |
|
---|
238 |
|
---|
239 | #define CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _name) ((_pEntry)->iTex##_name > 0)
|
---|
240 |
|
---|
241 | #define CR_SERVER_RPW_ENTRY_TEX_INVALIDATE(_pEntry, _name) do { \
|
---|
242 | crServerRpwEntryDbgVerify(_pEntry); \
|
---|
243 | Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _name)); \
|
---|
244 | (_pEntry)->iTex##_name = -(_pEntry)->iTex##_name; \
|
---|
245 | crServerRpwEntryDbgVerify(_pEntry); \
|
---|
246 | } while (0)
|
---|
247 |
|
---|
248 | #define CR_SERVER_RPW_ENTRY_TEX_PROMOTE(_pEntry, _fromName, _toName) do { \
|
---|
249 | crServerRpwEntryDbgVerify(_pEntry); \
|
---|
250 | Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _fromName)); \
|
---|
251 | Assert(!CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _toName)); \
|
---|
252 | crServerXchgI8(&(_pEntry)->iTex##_fromName, &(_pEntry)->iTex##_toName); \
|
---|
253 | crServerRpwEntryDbgVerify(_pEntry); \
|
---|
254 | } while (0)
|
---|
255 |
|
---|
256 | #define CR_SERVER_RPW_ENTRY_TEX_XCHG_VALID(_pEntry, _fromName, _toName) do { \
|
---|
257 | crServerRpwEntryDbgVerify(_pEntry); \
|
---|
258 | Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _fromName)); \
|
---|
259 | Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _toName)); \
|
---|
260 | crServerXchgI8(&(_pEntry)->iTex##_fromName, &(_pEntry)->iTex##_toName); \
|
---|
261 | Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _fromName)); \
|
---|
262 | Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _toName)); \
|
---|
263 | crServerRpwEntryDbgVerify(_pEntry); \
|
---|
264 | } while (0)
|
---|
265 |
|
---|
266 |
|
---|
267 | #define CR_SERVER_RPW_ENTRY_TEX_PROMOTE_KEEPVALID(_pEntry, _fromName, _toName) do { \
|
---|
268 | crServerRpwEntryDbgVerify(_pEntry); \
|
---|
269 | Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _fromName)); \
|
---|
270 | Assert(!CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _toName)); \
|
---|
271 | crServerXchgI8(&(_pEntry)->iTex##_fromName, &(_pEntry)->iTex##_toName); \
|
---|
272 | (_pEntry)->iTex##_fromName = -(_pEntry)->iTex##_fromName; \
|
---|
273 | Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _fromName)); \
|
---|
274 | Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _toName)); \
|
---|
275 | crServerRpwEntryDbgVerify(_pEntry); \
|
---|
276 | } while (0)
|
---|
277 |
|
---|
278 | #define CR_SERVER_RPW_ENTRY_TEX(_pEntry, _name) ((_pEntry)->aidWorkerTexs[(_pEntry)->iTex##_name - 1])
|
---|
279 |
|
---|
280 | #define CR_SERVER_RPW_ENTRY_PBO_NEXT_ID(_i) (((_i) + 1) % 2)
|
---|
281 | #define CR_SERVER_RPW_ENTRY_PBO_IS_ACTIVE(_pEntry) ((_pEntry)->iCurPBO >= 0)
|
---|
282 | #define CR_SERVER_RPW_ENTRY_PBO_CUR(_pEntry) ((_pEntry)->aidPBOs[(_pEntry)->iCurPBO])
|
---|
283 | #define CR_SERVER_RPW_ENTRY_PBO_COMPLETED(_pEntry) ((_pEntry)->aidPBOs[CR_SERVER_RPW_ENTRY_PBO_NEXT_ID((_pEntry)->iCurPBO)])
|
---|
284 | #define CR_SERVER_RPW_ENTRY_PBO_FLIP(_pEntry) do { \
|
---|
285 | (_pEntry)->iCurPBO = CR_SERVER_RPW_ENTRY_PBO_NEXT_ID((_pEntry)->iCurPBO); \
|
---|
286 | } while (0)
|
---|
287 |
|
---|
288 | #ifdef CR_SERVER_RPW_DEBUG
|
---|
289 | DECLINLINE(void) crServerRpwEntryDbgDoVerify(CR_SERVER_RPW_ENTRY *pEntry)
|
---|
290 | {
|
---|
291 | int tstMask = 0;
|
---|
292 | int8_t iVal;
|
---|
293 | Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Draw));
|
---|
294 |
|
---|
295 | #define CR_VERVER_RPW_ENTRY_DBG_CHECKVAL(_v) do { \
|
---|
296 | iVal = RT_ABS(_v); \
|
---|
297 | Assert(iVal > 0); \
|
---|
298 | Assert(iVal < 5); \
|
---|
299 | Assert(!(tstMask & (1 << iVal))); \
|
---|
300 | tstMask |= (1 << iVal); \
|
---|
301 | } while (0)
|
---|
302 |
|
---|
303 | CR_VERVER_RPW_ENTRY_DBG_CHECKVAL(pEntry->iTexDraw);
|
---|
304 | CR_VERVER_RPW_ENTRY_DBG_CHECKVAL(pEntry->iTexSubmitted);
|
---|
305 | CR_VERVER_RPW_ENTRY_DBG_CHECKVAL(pEntry->iTexWorker);
|
---|
306 | CR_VERVER_RPW_ENTRY_DBG_CHECKVAL(pEntry->iTexGpu);
|
---|
307 | Assert(tstMask == 0x1E);
|
---|
308 | }
|
---|
309 | #endif
|
---|
310 |
|
---|
311 | DECLINLINE(bool) crServerRpwIsInitialized(const CR_SERVER_RPW *pWorker)
|
---|
312 | {
|
---|
313 | return !!pWorker->ctxId;
|
---|
314 | }
|
---|
315 | int crServerRpwInit(CR_SERVER_RPW *pWorker);
|
---|
316 | int crServerRpwTerm(CR_SERVER_RPW *pWorker);
|
---|
317 | DECLINLINE(bool) crServerRpwEntryIsInitialized(const CR_SERVER_RPW_ENTRY *pEntry)
|
---|
318 | {
|
---|
319 | return !!pEntry->pfnData;
|
---|
320 | }
|
---|
321 | int crServerRpwEntryInit(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry, uint32_t width, uint32_t height, PFNCR_SERVER_RPW_DATA pfnData);
|
---|
322 | int crServerRpwEntryCleanup(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry);
|
---|
323 | int crServerRpwEntryResize(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry, uint32_t width, uint32_t height);
|
---|
324 | int crServerRpwEntrySubmit(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry);
|
---|
325 | int crServerRpwEntryWaitComplete(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry);
|
---|
326 | int crServerRpwEntryCancel(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry);
|
---|
327 | DECLINLINE(void) crServerRpwEntryDrawSettingsToTex(const CR_SERVER_RPW_ENTRY *pEntry, VBOXVR_TEXTURE *pTex)
|
---|
328 | {
|
---|
329 | pTex->width = pEntry->Size.cx;
|
---|
330 | pTex->height = pEntry->Size.cy;
|
---|
331 | pTex->target = GL_TEXTURE_2D;
|
---|
332 | CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Draw);
|
---|
333 | pTex->hwid = CR_SERVER_RPW_ENTRY_TEX(pEntry, Draw);
|
---|
334 | }
|
---|
335 | /**/
|
---|
336 |
|
---|
337 | typedef struct CR_SERVER_CTX_SWITCH
|
---|
338 | {
|
---|
339 | GLuint idDrawFBO, idReadFBO;
|
---|
340 | CRContext *pNewCtx;
|
---|
341 | CRContext *pOldCtx;
|
---|
342 | } CR_SERVER_CTX_SWITCH;
|
---|
343 |
|
---|
344 | DECLINLINE(void) cr_serverCtxSwitchPrepare(CR_SERVER_CTX_SWITCH *pData, CRContext *pNewCtx)
|
---|
345 | {
|
---|
346 | CRMuralInfo *pCurrentMural = cr_server.currentMural;
|
---|
347 | CRContextInfo *pCurCtxInfo = cr_server.currentCtxInfo;
|
---|
348 | GLuint idDrawFBO, idReadFBO;
|
---|
349 | CRContext *pCurCtx = pCurCtxInfo ? pCurCtxInfo->pContext : NULL;
|
---|
350 |
|
---|
351 | CRASSERT(pCurCtx == crStateGetCurrent());
|
---|
352 |
|
---|
353 | if (pCurrentMural)
|
---|
354 | {
|
---|
355 | idDrawFBO = pCurrentMural->aidFBOs[pCurrentMural->iCurDrawBuffer];
|
---|
356 | idReadFBO = pCurrentMural->aidFBOs[pCurrentMural->iCurReadBuffer];
|
---|
357 | }
|
---|
358 | else
|
---|
359 | {
|
---|
360 | idDrawFBO = 0;
|
---|
361 | idReadFBO = 0;
|
---|
362 | }
|
---|
363 |
|
---|
364 | crStateSwitchPrepare(pNewCtx, pCurCtx, idDrawFBO, idReadFBO);
|
---|
365 |
|
---|
366 | pData->idDrawFBO = idDrawFBO;
|
---|
367 | pData->idReadFBO = idReadFBO;
|
---|
368 | pData->pNewCtx = pNewCtx;
|
---|
369 | pData->pOldCtx = pCurCtx;
|
---|
370 | }
|
---|
371 |
|
---|
372 | DECLINLINE(void) cr_serverCtxSwitchPostprocess(CR_SERVER_CTX_SWITCH *pData)
|
---|
373 | {
|
---|
374 | crStateSwitchPostprocess(pData->pOldCtx, pData->pNewCtx, pData->idDrawFBO, pData->idReadFBO);
|
---|
375 | }
|
---|
376 | RT_C_DECLS_END
|
---|
377 |
|
---|
378 | #endif /* CR_SERVER_H */
|
---|