1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
|
/* Copyright (c) 2001, Stanford University
* All rights reserved.
*
* See the file LICENSE.txt for information on redistributing this software.
*/
#ifndef CR_RENDERSPU_H
#define CR_RENDERSPU_H
#ifdef WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <iprt/win/windows.h>
#define RENDER_APIENTRY __stdcall
#define snprintf _snprintf
#elif defined(DARWIN)
# ifndef VBOX_WITH_COCOA_QT
# include <AGL/AGL.h>
# else
# include "renderspu_cocoa_helper.h"
# endif
#define RENDER_APIENTRY
#else
#include <GL/glx.h>
#define RENDER_APIENTRY
#endif
#include "cr_threads.h"
#include "cr_spu.h"
#include "cr_hash.h"
#include "cr_server.h"
#include "cr_blitter.h"
#include "cr_compositor.h"
#include <iprt/cdefs.h>
#include <iprt/critsect.h>
#if defined(GLX) /* @todo: unify windows and glx thread creation code */
#include <iprt/thread.h>
#include <iprt/semaphore.h>
/* special window id used for representing the command window CRWindowInfo */
#define CR_RENDER_WINCMD_ID (INT32_MAX-2)
AssertCompile(CR_RENDER_WINCMD_ID != CR_RENDER_DEFAULT_WINDOW_ID);
/* CRHashTable is using unsigned long keys, we use it to trore X Window -> CRWindowInfo association */
AssertCompile(sizeof (Window) == sizeof (unsigned long));
#endif
#define MAX_VISUALS 32
#ifdef RT_OS_DARWIN
# ifndef VBOX_WITH_COCOA_QT
enum
{
/* Event classes */
kEventClassVBox = 'vbox',
/* Event kinds */
kEventVBoxShowWindow = 'swin',
kEventVBoxHideWindow = 'hwin',
kEventVBoxMoveWindow = 'mwin',
kEventVBoxResizeWindow = 'rwin',
kEventVBoxDisposeWindow = 'dwin',
kEventVBoxUpdateDock = 'udck',
kEventVBoxUpdateContext = 'uctx',
kEventVBoxBoundsChanged = 'bchg'
};
pascal OSStatus windowEvtHndlr(EventHandlerCallRef myHandler, EventRef event, void* userData);
# endif
#endif /* RT_OS_DARWIN */
/**
* Visual info
*/
typedef struct {
GLbitfield visAttribs;
const char *displayName;
#if defined(WINDOWS)
// HDC device_context;
#elif defined(DARWIN)
# ifndef VBOX_WITH_COCOA_QT
WindowRef window;
# endif
#elif defined(GLX)
Display *dpy;
XVisualInfo *visual;
#ifdef GLX_VERSION_1_3
GLXFBConfig fbconfig;
#endif /* GLX_VERSION_1_3 */
#endif
} VisualInfo;
/**
* Window info
*/
typedef struct WindowInfo {
int x, y;
// int width, height;
// int id; /**< integer window ID */
CR_BLITTER_WINDOW BltInfo;
VisualInfo *visual;
volatile uint32_t cRefs;
GLboolean mapPending;
GLboolean visible;
GLboolean everCurrent; /**< has this window ever been bound? */
char *title;
const VBOXVR_SCR_COMPOSITOR *pCompositor;
/* the composotor lock is used to synchronize the current compositor access,
* i.e. the compositor can be accessed by a gui refraw thread,
* while chromium thread might try to set a new compositor
* note that the compositor internally has its own lock to be used for accessing its data
* see CrVrScrCompositorLock/Unlock; renderspu and crserverlib would use it for compositor data access */
RTCRITSECT CompositorLock;
PCR_BLITTER pBlitter;
#if defined(WINDOWS)
HDC nativeWindow; /**< for render_to_app_window */
HWND hWnd;
HDC device_context;
HDC redraw_device_context;
HRGN hRgn;
#elif defined(DARWIN)
# ifndef VBOX_WITH_COCOA_QT
WindowRef window;
WindowRef nativeWindow; /**< for render_to_app_window */
WindowRef appWindow;
EventHandlerUPP event_handler;
GLint bufferName;
AGLContext dummyContext;
RgnHandle hVisibleRegion;
/* unsigned long context_ptr; */
# else
NativeNSViewRef window;
NativeNSViewRef nativeWindow; /**< for render_to_app_window */
NativeNSOpenGLContextRef *currentCtx;
# endif
#elif defined(GLX)
Window window;
Window nativeWindow; /**< for render_to_app_window */
Window appWindow; /**< Same as nativeWindow but for garbage collections purposes */
#endif
int nvSwapGroup;
#ifdef USE_OSMESA
GLubyte *buffer; /**< for rendering to off screen buffer. */
int in_buffer_width;
int in_buffer_height;
#endif
} WindowInfo;
/**
* Context Info
*/
typedef struct _ContextInfo {
// int id; /**< integer context ID */
CR_BLITTER_CONTEXT BltInfo;
VisualInfo *visual;
GLboolean everCurrent;
GLboolean haveWindowPosARB;
WindowInfo *currentWindow;
#if defined(WINDOWS)
HGLRC hRC;
#elif defined(DARWIN)
# ifndef VBOX_WITH_COCOA_QT
AGLContext context;
# else
NativeNSOpenGLContextRef context;
# endif
#elif defined(GLX)
GLXContext context;
#endif
struct _ContextInfo *shared;
char *extensionString;
volatile uint32_t cRefs;
} ContextInfo;
/**
* Barrier info
*/
typedef struct {
CRbarrier barrier;
GLuint count;
} Barrier;
#ifdef GLX
typedef enum
{
CR_RENDER_WINCMD_TYPE_UNDEFINED = 0,
/* create the window (not used for now) */
CR_RENDER_WINCMD_TYPE_WIN_CREATE,
/* destroy the window (not used for now) */
CR_RENDER_WINCMD_TYPE_WIN_DESTROY,
/* notify the WinCmd thread about window creation */
CR_RENDER_WINCMD_TYPE_WIN_ON_CREATE,
/* notify the WinCmd thread about window destroy */
CR_RENDER_WINCMD_TYPE_WIN_ON_DESTROY,
/* nop used to synchronize with the WinCmd thread */
CR_RENDER_WINCMD_TYPE_NOP,
/* exit Win Cmd thread */
CR_RENDER_WINCMD_TYPE_EXIT,
} CR_RENDER_WINCMD_TYPE;
typedef struct CR_RENDER_WINCMD
{
/* command type */
CR_RENDER_WINCMD_TYPE enmCmd;
/* command result */
int rc;
/* valid for WIN_CREATE & WIN_DESTROY only */
WindowInfo *pWindow;
} CR_RENDER_WINCMD, *PCR_RENDER_WINCMD;
#endif
#ifdef RT_OS_DARWIN
typedef void (*PFNDELETE_OBJECT)(GLhandleARB obj);
typedef void (*PFNGET_ATTACHED_OBJECTS)( GLhandleARB containerObj, GLsizei maxCount, GLsizei * count, GLhandleARB * obj );
typedef GLhandleARB (*PFNGET_HANDLE)(GLenum pname);
typedef void (*PFNGET_INFO_LOG)( GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog );
typedef void (*PFNGET_OBJECT_PARAMETERFV)( GLhandleARB obj, GLenum pname, GLfloat * params );
typedef void (*PFNGET_OBJECT_PARAMETERIV)( GLhandleARB obj, GLenum pname, GLint * params );
#endif
typedef DECLCALLBACKPTR(void, PFNVCRSERVER_CLIENT_CALLOUT_CB)(void *pvCb);
typedef DECLCALLBACKPTR(void, PFNVCRSERVER_CLIENT_CALLOUT)(PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb, void*pvCb);
/**
* Renderspu state info
*/
typedef struct {
SPUDispatchTable self;
int id;
/** config options */
/*@{*/
char *window_title;
int defaultX, defaultY;
unsigned int defaultWidth, defaultHeight;
int default_visual;
int use_L2;
int fullscreen, ontop;
char display_string[100];
#if defined(GLX)
int try_direct;
int force_direct;
int sync;
#endif
int force_present_main_thread;
int render_to_app_window;
int render_to_crut_window;
int crut_drawable;
int resizable;
int use_lut8, lut8[3][256];
int borderless;
int nvSwapGroup;
int ignore_papi;
int ignore_window_moves;
int pbufferWidth, pbufferHeight;
int use_glxchoosevisual;
int draw_bbox;
/*@}*/
CRServer *server;
int gather_port;
int gather_userbuf_size;
CRConnection **gather_conns;
GLint drawCursor;
GLint cursorX, cursorY;
int numVisuals;
VisualInfo visuals[MAX_VISUALS];
CRHashTable *windowTable;
CRHashTable *contextTable;
CRHashTable *dummyWindowTable;
ContextInfo *defaultSharedContext;
#ifndef CHROMIUM_THREADSAFE
ContextInfo *currentContext;
#endif
crOpenGLInterface ws; /**< Window System interface */
CRHashTable *barrierHash;
int is_swap_master, num_swap_clients;
int swap_mtu;
char *swap_master_url;
CRConnection **swap_conns;
SPUDispatchTable blitterDispatch;
CRHashTable *blitterTable;
PFNVCRSERVER_CLIENT_CALLOUT pfnClientCallout;
#ifdef USE_OSMESA
/** Off screen rendering hooks. */
int use_osmesa;
OSMesaContext (*OSMesaCreateContext)( GLenum format, OSMesaContext sharelist );
GLboolean (* OSMesaMakeCurrent)( OSMesaContext ctx,
GLubyte *buffer,
GLenum type,
GLsizei width,
GLsizei height );
void (*OSMesaDestroyContext)( OSMesaContext ctx );
#endif
#if defined(GLX)
RTTHREAD hWinCmdThread;
VisualInfo WinCmdVisual;
WindowInfo WinCmdWindow;
RTSEMEVENT hWinCmdCompleteEvent;
/* display connection used to send data to the WinCmd thread */
Display *pCommunicationDisplay;
Atom WinCmdAtom;
/* X Window -> CRWindowInfo table */
CRHashTable *pWinToInfoTable;
#endif
#ifdef RT_OS_WINDOWS
DWORD dwWinThreadId;
HANDLE hWinThreadReadyEvent;
#endif
#ifdef RT_OS_DARWIN
# ifdef VBOX_WITH_COCOA_QT
PFNDELETE_OBJECT pfnDeleteObject;
PFNGET_ATTACHED_OBJECTS pfnGetAttachedObjects;
PFNGET_HANDLE pfnGetHandle;
PFNGET_INFO_LOG pfnGetInfoLog;
PFNGET_OBJECT_PARAMETERFV pfnGetObjectParameterfv;
PFNGET_OBJECT_PARAMETERIV pfnGetObjectParameteriv;
CR_GLSL_CACHE GlobalShaders;
# else
RgnHandle hRootVisibleRegion;
RTSEMFASTMUTEX syncMutex;
EventHandlerUPP hParentEventHandler;
WindowGroupRef pParentGroup;
WindowGroupRef pMasterGroup;
GLint currentBufferName;
uint64_t uiDockUpdateTS;
bool fInit;
# endif
#endif /* RT_OS_DARWIN */
/* If TRUE, render should tell window server to prevent artificial content
* up-scaling when displayed on HiDPI monitor. */
bool fUnscaledHiDPI;
} RenderSPU;
#ifdef RT_OS_WINDOWS
/* Asks window thread to create new window.
msg.lParam - holds pointer to CREATESTRUCT structure
note that lpCreateParams is used to specify address to store handle of created window
msg.wParam - unused, should be NULL
*/
#define WM_VBOX_RENDERSPU_CREATE_WINDOW (WM_APP+1)
typedef struct _VBOX_RENDERSPU_DESTROY_WINDOW {
HWND hWnd; /* handle to window to destroy */
} VBOX_RENDERSPU_DESTROY_WINDOW;
/* Asks window thread to destroy previously created window.
msg.lParam - holds pointer to RENDERSPU_VBOX_WINDOW_DESTROY structure
msg.wParam - unused, should be NULL
*/
#define WM_VBOX_RENDERSPU_DESTROY_WINDOW (WM_APP+2)
#endif
extern RenderSPU render_spu;
/* @todo remove this hack */
extern uint64_t render_spu_parent_window_id;
#ifdef CHROMIUM_THREADSAFE
extern CRtsd _RenderTSD;
#define GET_CONTEXT_VAL() ((ContextInfo *) crGetTSD(&_RenderTSD))
#define SET_CONTEXT_VAL(_v) do { \
crSetTSD(&_RenderTSD, (_v)); \
} while (0)
#else
#define GET_CONTEXT_VAL() (render_spu.currentContext)
#define SET_CONTEXT_VAL(_v) do { \
render_spu.currentContext = (_v); \
} while (0)
#endif
#define GET_CONTEXT(T) ContextInfo *T = GET_CONTEXT_VAL()
extern void renderspuSetDefaultSharedContext(ContextInfo *pCtx);
extern void renderspuSetVBoxConfiguration( RenderSPU *spu );
extern void renderspuMakeVisString( GLbitfield visAttribs, char *s );
extern VisualInfo *renderspuFindVisual(const char *displayName, GLbitfield visAttribs );
extern GLboolean renderspu_SystemInitVisual( VisualInfo *visual );
extern GLboolean renderspu_SystemCreateContext( VisualInfo *visual, ContextInfo *context, ContextInfo *sharedContext );
extern void renderspu_SystemDestroyContext( ContextInfo *context );
extern GLboolean renderspu_SystemCreateWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window );
extern GLboolean renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window );
extern void renderspu_SystemDestroyWindow( WindowInfo *window );
extern void renderspu_SystemWindowSize( WindowInfo *window, GLint w, GLint h );
extern void renderspu_SystemGetWindowGeometry( WindowInfo *window, GLint *x, GLint *y, GLint *w, GLint *h );
extern void renderspu_SystemGetMaxWindowSize( WindowInfo *window, GLint *w, GLint *h );
extern void renderspu_SystemWindowPosition( WindowInfo *window, GLint x, GLint y );
extern void renderspu_SystemWindowVisibleRegion(WindowInfo *window, GLint cRects, const GLint* pRects);
extern GLboolean renderspu_SystemWindowNeedEmptyPresent(WindowInfo *window);
extern int renderspu_SystemInit();
extern int renderspu_SystemTerm();
extern void renderspu_SystemDefaultSharedContextChanged(ContextInfo *fromContext, ContextInfo *toContext);
extern void renderspu_SystemShowWindow( WindowInfo *window, GLboolean showIt );
extern void renderspu_SystemMakeCurrent( WindowInfo *window, GLint windowInfor, ContextInfo *context );
extern void renderspu_SystemSwapBuffers( WindowInfo *window, GLint flags );
extern void renderspu_SystemReparentWindow(WindowInfo *window);
extern void renderspu_SystemVBoxPresentComposition( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry );
uint32_t renderspu_SystemPostprocessFunctions(SPUNamedFunctionTable *aFunctions, uint32_t cFunctions, uint32_t cTable);
extern void renderspu_GCWindow(void);
extern int renderspuCreateFunctions( SPUNamedFunctionTable table[] );
extern GLboolean renderspuVBoxCompositorSet( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor);
extern void renderspuVBoxCompositorClearAll();
extern int renderspuVBoxCompositorLock(WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR **ppCompositor);
extern int renderspuVBoxCompositorUnlock(WindowInfo *window);
extern const struct VBOXVR_SCR_COMPOSITOR * renderspuVBoxCompositorAcquire( WindowInfo *window);
extern int renderspuVBoxCompositorTryAcquire(WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR **ppCompositor);
extern void renderspuVBoxCompositorRelease( WindowInfo *window);
extern void renderspuVBoxPresentCompositionGeneric( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor,
const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry, int32_t i32MakeCurrentUserData,
bool fRedraw);
extern PCR_BLITTER renderspuVBoxPresentBlitterGet( WindowInfo *window );
void renderspuVBoxPresentBlitterCleanup( WindowInfo *window );
extern int renderspuVBoxPresentBlitterEnter( PCR_BLITTER pBlitter, int32_t i32MakeCurrentUserData );
extern PCR_BLITTER renderspuVBoxPresentBlitterGetAndEnter( WindowInfo *window, int32_t i32MakeCurrentUserData, bool fRedraw );
extern PCR_BLITTER renderspuVBoxPresentBlitterEnsureCreated( WindowInfo *window, int32_t i32MakeCurrentUserData );
WindowInfo* renderspuWinCreate(GLint visBits, GLint id);
void renderspuWinTermOnShutdown(WindowInfo *window);
void renderspuWinTerm( WindowInfo *window );
void renderspuWinCleanup(WindowInfo *window);
void renderspuWinDestroy(WindowInfo *window);
GLboolean renderspuWinInitWithVisual( WindowInfo *window, VisualInfo *visual, GLboolean showIt, GLint id );
GLboolean renderspuWinInit(WindowInfo *pWindow, const char *dpyName, GLint visBits, GLint id);
DECLINLINE(void) renderspuWinRetain(WindowInfo *window)
{
ASMAtomicIncU32(&window->cRefs);
}
DECLINLINE(bool) renderspuWinIsTermed(WindowInfo *window)
{
return window->BltInfo.Base.id < 0;
}
DECLINLINE(void) renderspuWinRelease(WindowInfo *window)
{
uint32_t cRefs = ASMAtomicDecU32(&window->cRefs);
if (!cRefs)
{
renderspuWinDestroy(window);
}
}
extern WindowInfo* renderspuGetDummyWindow(GLint visBits);
extern void renderspuPerformMakeCurrent(WindowInfo *window, GLint nativeWindow, ContextInfo *context);
extern GLboolean renderspuInitVisual(VisualInfo *pVisInfo, const char *displayName, GLbitfield visAttribs);
extern void renderspuVBoxCompositorBlit ( const struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter);
extern void renderspuVBoxCompositorBlitStretched ( const struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter, GLfloat scaleX, GLfloat scaleY);
extern GLint renderspuCreateContextEx(const char *dpyName, GLint visBits, GLint id, GLint shareCtx);
extern GLint renderspuWindowCreateEx( const char *dpyName, GLint visBits, GLint id );
extern GLint RENDER_APIENTRY renderspuWindowCreate( const char *dpyName, GLint visBits );
void RENDER_APIENTRY renderspuWindowDestroy( GLint win );
extern GLint RENDER_APIENTRY renderspuCreateContext( const char *dpyname, GLint visBits, GLint shareCtx );
extern void RENDER_APIENTRY renderspuMakeCurrent(GLint crWindow, GLint nativeWindow, GLint ctx);
extern void RENDER_APIENTRY renderspuSwapBuffers( GLint window, GLint flags );
extern uint32_t renderspuContextMarkDeletedAndRelease( ContextInfo *context );
int renderspuDefaultCtxInit();
void renderspuCleanupBase(bool fDeleteTables);
ContextInfo * renderspuDefaultSharedContextAcquire();
void renderspuDefaultSharedContextRelease(ContextInfo * pCtx);
uint32_t renderspuContextRelease(ContextInfo *context);
uint32_t renderspuContextRetain(ContextInfo *context);
bool renderspuCalloutAvailable();
bool renderspuCalloutClient(PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb, void *pvCb);
#ifdef __cplusplus
extern "C" {
#endif
DECLEXPORT(void) renderspuSetWindowId(uint64_t winId);
DECLEXPORT(void) renderspuReparentWindow(GLint window);
DECLEXPORT(void) renderspuSetUnscaledHiDPI(bool fEnable);
#ifdef __cplusplus
}
#endif
#endif /* CR_RENDERSPU_H */
|