renderspu.c revision 20b47de42f313ea11cdf2fc23e1217c5b3a1f556
/* Copyright (c) 2001, Stanford University
* All rights reserved
*
* See the file LICENSE.txt for information on redistributing this software.
*/
#include "cr_environment.h"
#include "cr_string.h"
#include "cr_error.h"
#include "cr_mem.h"
#include "cr_spu.h"
#include "cr_environment.h"
#include "renderspu.h"
#include "cr_extstring.h"
static void
DoSync(void)
{
if (render_spu.is_swap_master)
{
int a;
for (a = 0; a < render_spu.num_swap_clients; a++)
{
}
for (a = 0; a < render_spu.num_swap_clients; a++)
}
else
{
}
}
/*
* Visual functions
*/
/**
* used for debugging and giving info to the user.
*/
void
{
s[0] = 0;
if (visAttribs & CR_RGB_BIT)
crStrcat(s, "RGB");
if (visAttribs & CR_ALPHA_BIT)
crStrcat(s, "A");
if (visAttribs & CR_DOUBLE_BIT)
crStrcat(s, ", Doublebuffer");
if (visAttribs & CR_STEREO_BIT)
crStrcat(s, ", Stereo");
if (visAttribs & CR_DEPTH_BIT)
crStrcat(s, ", Z");
if (visAttribs & CR_STENCIL_BIT)
crStrcat(s, ", Stencil");
if (visAttribs & CR_ACCUM_BIT)
crStrcat(s, ", Accum");
if (visAttribs & CR_MULTISAMPLE_BIT)
crStrcat(s, ", Multisample");
if (visAttribs & CR_OVERLAY_BIT)
crStrcat(s, ", Overlay");
if (visAttribs & CR_PBUFFER_BIT)
crStrcat(s, ", PBuffer");
}
{
return renderspu_SystemInitVisual(pVisInfo);
}
/*
* Find a VisualInfo which matches the given display name and attribute
* bitmask, or return a pointer to a new visual.
*/
{
int i;
if (!displayName)
displayName = "";
/* first, try to find a match */
for (i = 0; i < render_spu.numVisuals; i++) {
return &(render_spu.visuals[i]);
}
}
for (i = 0; i < render_spu.numVisuals; i++) {
return &(render_spu.visuals[i]);
}
}
#endif
{
crWarning("Render SPU: Couldn't create a visual, too many visuals already");
return NULL;
}
/* create a new visual */
i = render_spu.numVisuals;
return &(render_spu.visuals[i]);
}
else {
crWarning("Render SPU: Couldn't get a visual, renderspu_SystemInitVisual failed");
return NULL;
}
}
static ContextInfo * renderspuCreateContextInternal(const char *dpyName, GLint visBits, GLint idCtx, ContextInfo * sharedContext)
{
if (idCtx <= 0)
{
if (idCtx <= 0)
{
crWarning("failed to allocate context id");
return NULL;
}
}
else
{
{
return NULL;
}
}
if (!visual)
return NULL;
if (!context)
return NULL;
return NULL;
/*
crDebug("Render SPU: CreateContext(%s, 0x%x) returning %d",
dpyName, visBits, context->BltInfo.Base.id);
*/
if (sharedContext)
return context;
}
{
if (shareCtx) {
}
if (context)
return -1;
}
/*
* Context functions
*/
{
}
{
if (context->extensionString) {
}
}
{
if (!cRefs)
else
return cRefs;
}
{
/* invalidate the context id to mark it as deleted */
/* some drivers do not like when the base (shared) context is deleted before its referals,
* this is why we keep a context refference counting the base (shared) context will be destroyed as soon as*/
return renderspuContextRelease( context );
}
static void RENDER_APIENTRY
{
if (ctx == CR_RENDER_DEFAULT_CONTEXT_ID)
{
crWarning("request to destroy a default context, ignoring");
return;
}
{
if (!context)
{
crWarning("request to delete inexistent context");
return;
}
}
curCtx = GET_CONTEXT_VAL();
{
curCtx = GET_CONTEXT_VAL();
}
}
void RENDER_APIENTRY
{
/*
crDebug("%s win=%d native=0x%x ctx=%d", __FUNCTION__, crWindow, (int) nativeWindow, ctx);
*/
{
#ifdef CHROMIUM_THREADSAFE
#else
#endif
if (!window)
{
return;
}
if (!context)
{
return;
}
if (!context->everCurrent) {
/* print OpenGL info */
/*
crDebug( "Render SPU: GL_EXTENSIONS: %s", render_spu.ws.glGetString( GL_EXTENSIONS ) );
*/
else
}
/* Window[CR_RENDER_DEFAULT_CONTEXT_ID] is special, it's the default window and normally hidden.
* If the mapPending flag is set, then we should now make the window
* visible.
*/
/*renderspu_SystemShowWindow( window, GL_TRUE );*/
}
}
{
#ifdef CHROMIUM_THREADSAFE
#else
#endif
}
else
{
}
}
{
/* Set window->title, replacing %i with the window ID number */
{
if (s) {
int i, j, k;
CRASSERT(k < 10);
i++; /* skip the 'i' after the '%' */
j = i + k;
;
}
else {
}
}
/*
crDebug("Render SPU: Creating window (visBits=0x%x, id=%d)", visBits, window->BltInfo.Base.id);
*/
{
crWarning( "Render SPU: Couldn't create a window, renderspu_SystemCreateWindow failed" );
return GL_FALSE;
}
return GL_TRUE;
}
/*
* Window functions
*/
{
if (id <= 0)
{
if (id <= 0)
{
crWarning("failed to allocate window id");
return -1;
}
}
else
{
{
return -1;
}
}
if (!visual)
{
crWarning( "Render SPU: Couldn't create a window, renderspuFindVisual returned NULL" );
return -1;
}
/* Allocate WindowInfo */
if (!window)
{
crWarning( "Render SPU: Couldn't create a window" );
return -1;
}
|| ((render_spu.render_to_app_window || render_spu.render_to_crut_window) && !crGetenv("CRNEWSERVER")))
showIt = 0;
else
/*
crDebug("Render SPU: Creating window (visBits=0x%x, id=%d)", visBits, window->BltInfo.Base.id);
*/
{
crWarning( "Render SPU: Couldn't create a window, renderspu_SystemCreateWindow failed" );
return -1;
}
}
{
}
{
(void) key;
{
pCtx->currentWindow=0;
}
}
{
/* ensure no concurrent draws can take place */
/* check if this window is bound to some ctx. Note: window pointer is already freed here */
/* restore current context */
{
{
renderspuMakeCurrent(pOldCtx&&pOldCtx->currentWindow ? pOldCtx->currentWindow->BltInfo.Base.id:CR_RENDER_DEFAULT_WINDOW_ID, 0,
}
}
}
void
{
if (win == CR_RENDER_DEFAULT_WINDOW_ID)
{
crWarning("request to destroy a default mural, ignoring");
return;
}
if (window) {
/* remove window info from hash table, and free it */
}
else {
}
}
static void RENDER_APIENTRY
{
if (window) {
{
/* window is resized, compositor data is no longer valid
* this set also ensures all redraw operations are done in the redraw thread
* and that no redraw is started until new Present request comes containing a valid presentation data */
renderspu_SystemWindowSize( window, w, h );
}
}
else {
}
}
static void RENDER_APIENTRY
{
if (!render_spu.ignore_window_moves) {
if (window) {
renderspu_SystemWindowPosition( window, x, y );
window->x = x;
window->y = y;
}
else {
}
}
}
static void RENDER_APIENTRY
{
if (window) {
}
else {
}
}
static void RENDER_APIENTRY
{
if (window) {
if (window->nativeWindow) {
/* We're rendering back to the native app window instead of the
* new window which we (the Render SPU) created earlier.
* So, we never want to show the Render SPU's window.
*/
flag = 0;
}
{
}
}
else {
}
}
static void RENDER_APIENTRY
renderspuVBoxPresentComposition( GLint win, struct VBOXVR_SCR_COMPOSITOR * pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
{
if (window) {
if (pCompositor)
{
}
}
else {
}
}
void renderspuVBoxCompositorBlitStretched ( struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter, GLfloat scaleX, GLfloat scaleY)
{
{
int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions);
if (RT_SUCCESS(rc))
{
uint32_t i;
{
}
}
else
{
}
}
}
void renderspuVBoxCompositorBlit ( struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter)
{
{
int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions);
if (RT_SUCCESS(rc))
{
}
else
{
}
}
}
{
return;
if (render_spu.blitterTable)
{
{
}
}
else
{
}
}
{
if (!pBlitter)
{
if (render_spu.blitterTable)
{
}
if (!pBlitter)
{
int rc;
if (!pBlitter)
{
crWarning("failed to allocate blitter");
return NULL;
}
/* @todo: this is the assumption that crserverlib uses context 1 as a default one
* need to do it in a more proper way */
if (!RT_SUCCESS(rc))
{
return NULL;
}
if (render_spu.blitterTable)
{
}
}
if (render_spu.blitterTable)
}
return pBlitter;
}
{
int rc;
if (pCtx)
{
if (pCtx->currentWindow)
{
}
}
if (!RT_SUCCESS(rc))
{
return rc;
}
return VINF_SUCCESS;
}
PCR_BLITTER renderspuVBoxPresentBlitterGetAndEnter( WindowInfo *window, int32_t i32MakeCurrentUserData )
{
if (pBlitter)
{
if (RT_SUCCESS(rc))
{
return pBlitter;
}
}
return NULL;
}
PCR_BLITTER renderspuVBoxPresentBlitterEnsureCreated( WindowInfo *window, int32_t i32MakeCurrentUserData )
{
{
struct VBOXVR_SCR_COMPOSITOR * pTmpCompositor;
/* just use compositor lock to synchronize */
if (pTmpCompositor)
{
if (pBlitter)
{
if (!CrBltIsEverEntered(pBlitter))
{
if (RT_SUCCESS(rc))
{
}
else
{
}
}
}
else
{
crWarning("renderspuVBoxPresentBlitterGet failed");
}
}
else
{
crWarning("renderspuVBoxCompositorAcquire failed");
}
}
}
void renderspuVBoxPresentCompositionGeneric( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR * pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry, int32_t i32MakeCurrentUserData )
{
if (!pBlitter)
return;
}
{
int rc;
/* renderspuVBoxCompositorSet can be invoked from the chromium thread only and is not reentrant,
* no need to synch here
* the lock is actually needed to ensure we're in synch with the redraw thread */
return;
if (RT_SUCCESS(rc))
{
return;
}
else
{
}
}
{
}
{
/* we need to clear window compositor, which is not that trivial though,
* since the lock order used in presentation thread is compositor lock() -> hash table lock (aquired for id->window resolution)
* this is why, to prevent potential deadlocks, we use crHashtableWalkUnlocked that does not hold the table lock
* we are can be sure noone will modify the table here since renderspuVBoxCompositorClearAll can be called in the command (hgcm) thread only,
* and the table can be modified from that thread only as well */
}
{
if (RT_SUCCESS(rc))
{
if (pCompositor)
return pCompositor;
/* if no compositor is set, release the lock and return */
}
else
{
}
return NULL;
}
{
return rc;
}
{
return rc;
}
int renderspuVBoxCompositorTryAcquire(WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR **ppCompositor)
{
if (RT_SUCCESS(rc))
{
if (*ppCompositor)
return VINF_SUCCESS;
/* if no compositor is set, release the lock and return */
}
else
{
*ppCompositor = NULL;
}
return rc;
}
{
int rc;
if (!RT_SUCCESS(rc))
{
}
}
/*
* Set the current raster position to the given window coordinate.
*/
static void
{
/* Push current matrix mode and viewport attributes */
/* Setup projection parameters */
/* set the raster (window) position */
/* huh ? */
/* restore matrices, viewport and matrix mode */
}
/*
* Draw the mouse pointer bitmap at (x,y) in window coords.
*/
{
#define POINTER_WIDTH 32
#define POINTER_HEIGHT 32
/* Somebody artistic could probably do better here */
static const char *pointerImage[POINTER_HEIGHT] =
{
"XX..............................",
"XXXX............................",
".XXXXX..........................",
".XXXXXXX........................",
"..XXXXXXXX......................",
"..XXXXXXXXXX....................",
"...XXXXXXXXXXX..................",
"...XXXXXXXXXXXXX................",
"....XXXXXXXXXXXXXX..............",
"....XXXXXXXXXXXXXXXX............",
".....XXXXXXXXXXXXXXXXX..........",
".....XXXXXXXXXXXXXXXXXXX........",
"......XXXXXXXXXXXXXXXXXXXX......",
"......XXXXXXXXXXXXXXXXXXXXXX....",
".......XXXXXXXXXXXXXXXXXXXXXXX..",
".......XXXXXXXXXXXXXXXXXXXXXXXX.",
"........XXXXXXXXXXXXX...........",
"........XXXXXXXX.XXXXX..........",
".........XXXXXX...XXXXX.........",
".........XXXXX.....XXXXX........",
"..........XXX.......XXXXX.......",
"..........XX.........XXXXX......",
"......................XXXXX.....",
".......................XXXXX....",
"........................XXX.....",
".........................X......",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................"
};
if (firstCall) {
/* Convert pointerImage into pointerBitmap */
GLint i, j;
for (i = 0; i < POINTER_HEIGHT; i++) {
for (j = 0; j < POINTER_WIDTH; j++) {
}
}
}
}
/* save current raster pos */
SetRasterPos(x, y);
(const GLubyte *) pointerBitmap);
/* restore current raster pos */
if (lighting)
if (depthTest)
if (scissorTest)
}
{
if (!w)
{
return;
}
if (flags & CR_SUPPRESS_SWAP_BIT)
{
return;
}
if (render_spu.drawCursor)
DoSync();
renderspu_SystemSwapBuffers( w, flags );
}
/*
* Barrier functions
* Normally, we'll have a crserver somewhere that handles the barrier calls.
* However, if we're running the render SPU on the client node, then we
* should handle barriers here. The threadtest demo illustrates this.
* If we have N threads calling using this SPU we need these barrier
* functions to synchronize them.
*/
{
Barrier *b;
if (render_spu.ignore_papi)
return;
if (b) {
/* HACK -- this allows everybody to create a barrier, and all
but the first creation are ignored, assuming the count
match. */
crError( "Render SPU: Barrier name=%u created with count=%u, but already "
}
}
else {
}
}
{
if (render_spu.ignore_papi)
return;
}
{
Barrier *b;
if (render_spu.ignore_papi)
return;
if (b) {
crWaitBarrier( &(b->barrier) );
}
else {
}
}
/*
* Semaphore functions
* XXX we should probably implement these too, for the same reason as
* barriers (see above).
*/
{
(void) name;
(void) count;
}
{
(void) name;
}
{
(void) name;
}
{
(void) name;
}
/*
* Misc functions
*/
{
switch (target)
{
break;
default:
// crWarning("Unhandled target in renderspuChromiumParameteriCR()");
break;
}
}
static void RENDER_APIENTRY
{
(void) target;
(void) value;
#if 0
switch (target) {
default:
crWarning("Unhandled target in renderspuChromiumParameterfCR()");
break;
}
#endif
}
static void RENDER_APIENTRY
{
int client_num;
unsigned short port;
switch (target) {
case GL_GATHER_CONNECT_CR:
else
{
crError("Oh bother! duplicate GL_GATHER_CONNECT_CR getting through");
}
{
{
case CR_TCPIP:
crDebug("Render SPU: AcceptClient from %s on %d",
break;
case CR_GM:
break;
default:
crError("Render SPU: Unknown Network Type to Open Gather Connection");
}
{
}
else
{
}
{
}
}
break;
case GL_GATHER_DRAWPIXELS_CR:
{
{
}
else
{
crError("Render SPU: expecting MESSAGE_GATHER. got crap! (%d of %d)",
}
}
/*
* We're only hitting the case if we're not actually calling
* child.SwapBuffers from readback, so a switch about which
* call to DoSync() we really want [this one, or the one
* in SwapBuffers above] is not necessary -- karl
*/
DoSync();
sizeof(CRMessageHeader));
break;
case GL_CURSOR_POSITION_CR:
}
else {
crWarning("Render SPU: Bad type or count for ChromiumParametervCR(GL_CURSOR_POSITION_CR)");
}
break;
case GL_WINDOW_SIZE_CR:
/* XXX this is old code that should be removed.
* NOTE: we can only resize the default (id=CR_RENDER_DEFAULT_WINDOW_ID) window!!!
*/
{
GLint w, h;
if (window)
{
renderspu_SystemWindowSize(window, w, h);
}
}
break;
default:
#if 0
#endif
break;
}
}
static void RENDER_APIENTRY
{
switch (target) {
case GL_WINDOW_SIZE_CR:
{
if (window)
{
renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
size[0] = w;
size[1] = h;
}
}
break;
case GL_WINDOW_POSITION_CR:
/* return window position, as a screen coordinate */
{
GLint x, y, w, h;
if (window)
{
renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
pos[0] = x;/*window->x;*/
}
}
break;
case GL_MAX_WINDOW_SIZE_CR:
{
if (window)
{
}
}
break;
default:
; /* nothing - silence compiler */
}
}
static void RENDER_APIENTRY
{
(void) bounds;
(void) payload;
(void) len;
(void) num_opcodes;
/* draw the bounding box */
if (render_spu.draw_bbox) {
GLint x, y, w, h;
renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
}
}
static void RENDER_APIENTRY
{
(void) writeback;
}
static void
remove_trailing_space(char *s)
{
int k = crStrlen(s);
while (k > 0 && s[k-1] == ' ')
k--;
s[k] = 0;
}
static const GLubyte * RENDER_APIENTRY
{
static char tempStr[1000];
if (pname == GL_EXTENSIONS)
{
const char *nativeExt;
return NULL;
if (!nativeExt) {
return NULL;
}
if (context->extensionString)
}
else if (pname == GL_VERSION)
else if (pname == GL_RENDERER) {
#ifdef VBOX
snprintf(tempStr, sizeof(tempStr), "Chromium (%s)", (char *) render_spu.ws.glGetString(GL_RENDERER));
#else
#endif
}
#ifdef CR_OPENGL_VERSION_2_0
else if (pname == GL_SHADING_LANGUAGE_VERSION)
#endif
#ifdef GL_CR_real_vendor_strings
else if (pname == GL_REAL_VENDOR)
else if (pname == GL_REAL_VERSION)
else if (pname == GL_REAL_RENDERER)
else if (pname == GL_REAL_EXTENSIONS)
#endif
else
return NULL;
}
{
if (!pWindow)
{
return;
}
}
i++;
/* These are the functions which the render SPU implements, not OpenGL.
*/
int
{
int i = 0;
return i;
}