static SPUFunctions *
renderSPUInit( int id, SPU *child, SPU *self,
               unsigned int context_id, unsigned int num_contexts )
{
    int numFuncs, numSpecial;
    GLint defaultWin, defaultCtx;
    WindowInfo *windowInfo;
    const char * pcpwSetting;
    int rc;

    (void) child;
    (void) context_id;
    (void) num_contexts;

    self->privatePtr = (void *) &render_spu;

#ifdef CHROMIUM_THREADSAFE
    crDebug("Render SPU: thread-safe");
#endif

    crMemZero(&render_spu, sizeof(render_spu));

    render_spu.id = id;
    renderspuSetVBoxConfiguration(&render_spu);

    if (render_spu.swap_master_url)
        swapsyncConnect();


    /* Get our special functions. */
    numSpecial = renderspuCreateFunctions( _cr_render_table );

#ifdef RT_OS_WINDOWS
    /* Start thread to create windows and process window messages */
    crDebug("RenderSPU: Starting windows serving thread");
    render_spu.hWinThreadReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!render_spu.hWinThreadReadyEvent)
    {
        crError("RenderSPU: Failed to create WinThreadReadyEvent! (%x)", GetLastError());
        return NULL;
    }

    if (!CreateThread(NULL, 0, renderSPUWindowThreadProc, 0, 0, &render_spu.dwWinThreadId))
    {
        crError("RenderSPU: Failed to start windows thread! (%x)", GetLastError());
        return NULL;
    }
    WaitForSingleObject(render_spu.hWinThreadReadyEvent, INFINITE);
#endif

    /* Get the OpenGL functions. */
    numFuncs = crLoadOpenGL( &render_spu.ws, _cr_render_table + numSpecial );
    if (numFuncs == 0) {
        crError("The render SPU was unable to load the native OpenGL library");
        return NULL;
    }

    numFuncs += numSpecial;

    render_spu.contextTable = crAllocHashtableEx(1, INT32_MAX);
    render_spu.windowTable = crAllocHashtableEx(1, INT32_MAX);

    render_spu.dummyWindowTable = crAllocHashtable();

    pcpwSetting = crGetenv("CR_RENDER_ENABLE_SINGLE_PRESENT_CONTEXT");
    if (pcpwSetting)
    {
        if (pcpwSetting[0] == '0')
            pcpwSetting = NULL;
    }

    if (pcpwSetting)
    {
        /* TODO: need proper blitter synchronization, do not use so far!
         * the problem is that rendering can be done in multiple thread: the main command (hgcm) thread and the redraw thread
         * we currently use per-window synchronization, while we'll need a per-blitter synchronization if one blitter is used for multiple windows
         * this is not done currently */
        crWarning("TODO: need proper blitter synchronization, do not use so far!");
        render_spu.blitterTable = crAllocHashtable();
        CRASSERT(render_spu.blitterTable);
    }
    else
        render_spu.blitterTable = NULL;

    CRASSERT(render_spu.default_visual & CR_RGB_BIT);
    
    rc = renderspu_SystemInit();
    if (!RT_SUCCESS(rc))
    {
        crError("renderspu_SystemInit failed rc %d", rc);
        return NULL;
    }
#ifdef USE_OSMESA
    if (render_spu.use_osmesa) {
        if (!crLoadOSMesa(&render_spu.OSMesaCreateContext,
                          &render_spu.OSMesaMakeCurrent,
                          &render_spu.OSMesaDestroyContext)) {
            crError("Unable to load OSMesa library");
        }
    }
#endif

#ifdef DARWIN
# ifdef VBOX_WITH_COCOA_QT
# else /* VBOX_WITH_COCOA_QT */
    render_spu.hRootVisibleRegion = 0;
    render_spu.currentBufferName = 1;
    render_spu.uiDockUpdateTS = 0;
    /* Create a mutex for synchronizing events from the main Qt thread & this
       thread */
    RTSemFastMutexCreate(&render_spu.syncMutex);
    /* Create our window groups */
    CreateWindowGroup(kWindowGroupAttrMoveTogether | kWindowGroupAttrLayerTogether | kWindowGroupAttrSharedActivation | kWindowGroupAttrHideOnCollapse | kWindowGroupAttrFixedLevel, &render_spu.pMasterGroup);
    CreateWindowGroup(kWindowGroupAttrMoveTogether | kWindowGroupAttrLayerTogether | kWindowGroupAttrSharedActivation | kWindowGroupAttrHideOnCollapse | kWindowGroupAttrFixedLevel, &render_spu.pParentGroup);
    /* Make the correct z-layering */
    SendWindowGroupBehind (render_spu.pParentGroup, render_spu.pMasterGroup);
    /* and set the gParentGroup as parent for gMasterGroup. */
    SetWindowGroupParent (render_spu.pMasterGroup, render_spu.pParentGroup);
    /* Install the event handlers */
    EventTypeSpec eventList[] =
    {
        {kEventClassVBox, kEventVBoxUpdateContext}, /* Update the context after show/size/move events */
        {kEventClassVBox, kEventVBoxBoundsChanged}  /* Clip/Pos the OpenGL windows when the main window is changed in pos/size */
    };
    /* We need to process events from our main window */
    render_spu.hParentEventHandler = NewEventHandlerUPP(windowEvtHndlr);
    InstallApplicationEventHandler (render_spu.hParentEventHandler,
                                    GetEventTypeCount(eventList), eventList,
                                    NULL, NULL);
    render_spu.fInit = true;
# endif /* VBOX_WITH_COCOA_QT */
#endif /* DARWIN */

    /*
     * Create the default window and context.  Their indexes are zero and
     * a client can use them without calling CreateContext or WindowCreate.
     */
    crDebug("Render SPU: Creating default window (visBits=0x%x, id=0)",
            render_spu.default_visual);
    defaultWin = renderspuWindowCreateEx( NULL, render_spu.default_visual, CR_RENDER_DEFAULT_WINDOW_ID );
    if (defaultWin != CR_RENDER_DEFAULT_WINDOW_ID) {
        crError("Render SPU: Couldn't get a double-buffered, RGB visual with Z!");
        return NULL;
    }
    crDebug( "Render SPU: WindowCreate returned %d (0=normal)", defaultWin );

    crDebug("Render SPU: Creating default context, visBits=0x%x",
            render_spu.default_visual );
    defaultCtx = renderspuCreateContextEx( NULL, render_spu.default_visual, CR_RENDER_DEFAULT_CONTEXT_ID, 0 );
    if (defaultCtx != CR_RENDER_DEFAULT_CONTEXT_ID) {
        crError("Render SPU: failed to create default context!");
        return NULL;
    }

    renderspuMakeCurrent( defaultWin, 0, defaultCtx );

    /* Get windowInfo for the default window */
    windowInfo = (WindowInfo *) crHashtableSearch(render_spu.windowTable, CR_RENDER_DEFAULT_WINDOW_ID);
    CRASSERT(windowInfo);
    windowInfo->mapPending = GL_TRUE;

    /*
     * Get the OpenGL extension functions.
     * SIGH -- we have to wait until the very bitter end to load the
     * extensions, because the context has to be bound before
     * wglGetProcAddress will work correctly.  No such issue with GLX though.
     */
    numFuncs += crLoadOpenGLExtensions( &render_spu.ws, _cr_render_table + numFuncs );
    CRASSERT(numFuncs < 1000);

#ifdef WINDOWS
    /*
     * Same problem as above, these are extensions so we need to
     * load them after a context has been bound. As they're WGL
     * extensions too, we can't simply tag them into the spu_loader.
     * So we do them here for now.
     * Grrr, NVIDIA driver uses EXT for GetExtensionsStringEXT,
     * but ARB for others. Need further testing here....
     */
    render_spu.ws.wglGetExtensionsStringEXT =
        (wglGetExtensionsStringEXTFunc_t)
        render_spu.ws.wglGetProcAddress( "wglGetExtensionsStringEXT" );
    render_spu.ws.wglChoosePixelFormatEXT =
        (wglChoosePixelFormatEXTFunc_t)
        render_spu.ws.wglGetProcAddress( "wglChoosePixelFormatARB" );
    render_spu.ws.wglGetPixelFormatAttribivEXT =
        (wglGetPixelFormatAttribivEXTFunc_t)
        render_spu.ws.wglGetProcAddress( "wglGetPixelFormatAttribivARB" );
    render_spu.ws.wglGetPixelFormatAttribfvEXT =
        (wglGetPixelFormatAttribfvEXTFunc_t)
        render_spu.ws.wglGetProcAddress( "wglGetPixelFormatAttribfvARB" );

    if (render_spu.ws.wglGetProcAddress("glCopyTexSubImage3D"))
    {
        _cr_render_table[numFuncs].name = crStrdup("CopyTexSubImage3D");
        _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glCopyTexSubImage3D");
        ++numFuncs;
        crDebug("Render SPU: Found glCopyTexSubImage3D function");
    }

    if (render_spu.ws.wglGetProcAddress("glDrawRangeElements"))
    {
        _cr_render_table[numFuncs].name = crStrdup("DrawRangeElements");
        _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glDrawRangeElements");
        ++numFuncs;
        crDebug("Render SPU: Found glDrawRangeElements function");
    }

    if (render_spu.ws.wglGetProcAddress("glTexSubImage3D"))
    {
        _cr_render_table[numFuncs].name = crStrdup("TexSubImage3D");
        _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glTexSubImage3D");
        ++numFuncs;
        crDebug("Render SPU: Found glTexSubImage3D function");
    }

    if (render_spu.ws.wglGetProcAddress("glTexImage3D"))
    {
        _cr_render_table[numFuncs].name = crStrdup("TexImage3D");
        _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glTexImage3D");
        ++numFuncs;
        crDebug("Render SPU: Found glTexImage3D function");
    }

    if (render_spu.ws.wglGetExtensionsStringEXT) {
        crDebug("WGL - found wglGetExtensionsStringEXT\n");
    }
    if (render_spu.ws.wglChoosePixelFormatEXT) {
        crDebug("WGL - found wglChoosePixelFormatEXT\n");
    }
#endif

    render_spu.barrierHash = crAllocHashtable();

    render_spu.cursorX = 0;
    render_spu.cursorY = 0;
    render_spu.use_L2 = 0;

    render_spu.gather_conns = NULL;

    numFuncs = renderspu_SystemPostprocessFunctions(_cr_render_table, numFuncs, RT_ELEMENTS(_cr_render_table));

    crDebug("Render SPU: ---------- End of Init -------------");

    return &render_functions;
}
Example #2
0
void renderspu_SystemMakeCurrent( WindowInfo *window, GLint nativeWindow, ContextInfo *context )
{
    CRASSERT(render_spu.ws.wglMakeCurrent);

    if (context && window) {
        if (window->visual != context->visual) {
            /*
             * XXX have to revisit this issue!!!
             *
             * But for now we destroy the current window
             * and re-create it with the context's visual abilities
             */

            /*@todo Chromium has no correct code to remove window ids and associated info from 
             * various tables. This is hack which just hides the root case.
             */
            crDebug("Recreating window in renderspu_SystemMakeCurrent\n");
            renderspu_SystemDestroyWindow( window );
            renderspu_SystemVBoxCreateWindow( context->visual, window->visible, window );
        }

        if (render_spu.render_to_app_window && nativeWindow)
        {
            /* The render_to_app_window option 
             * is set and we've got a nativeWindow
             * handle, save the handle for 
             * later calls to swapbuffers().
             *
             * NOTE: This doesn't work, except 
             * for software driven Mesa.
             * We'd need to object link the 
             * crappfaker and crserver to be able to share
             * the HDC values between processes.. FIXME!
             */
            if (context->shared)
            {
                /* first make sure we have shared context created */
                renderspuChkActivateSharedContext(context->shared);
            }

            window->nativeWindow = (HDC) nativeWindow;
            if (context->hRC == 0) {
                context->hRC = render_spu.ws.wglCreateContext( window->nativeWindow );
                if (!context->hRC)
                {
                    crError( "(MakeCurrent) Couldn't create the context for the window (error 0x%x)", GetLastError() );
                }
            }

            if (context->shared
                    && context->shared->hRC
                    && context->hRC)
            {
                /* share lists */
                render_spu.ws.wglShareLists(context->shared->hRC, context->hRC);
            }

            render_spu.ws.wglMakeCurrent( window->nativeWindow, context->hRC );
        }
        else
        {
            if (!context->hRC) {
                if (context->shared)
                {
                    /* first make sure we have shared context created */
                    renderspuChkActivateSharedContext(context->shared);
                }

                context->hRC = render_spu.ws.wglCreateContext(window->device_context);
                if (!context->hRC)
                {
                    crError( "Render SPU: (MakeCurrent) Couldn't create the context for the window (error 0x%x)", GetLastError() );
                }

                if (context->shared
                        && context->shared->hRC
                        && context->hRC)
                {
                    /* share lists */
                    render_spu.ws.wglShareLists(context->shared->hRC, context->hRC);
                }

                /*Requery ext function pointers, we skip dummy ctx as it should never be used with ext functions*/
                if (0 && context->id)
                {
                    int numFuncs, i;
                    SPUNamedFunctionTable ext_table[1000];


                    crDebug("Default server ctx created, requerying ext functions");
                    /*requery ext functions*/
                    numFuncs = renderspuCreateFunctions(ext_table);
                    numFuncs += crLoadOpenGLExtensions( &render_spu.ws, ext_table+numFuncs);
                    CRASSERT(numFuncs < 1000);

                    /*change spu dispatch*/
                    crSPUChangeDispatch(&render_spu.self, ext_table);


                    /*cleanup temp table*/
                    for (i=0; i<numFuncs; ++i)
                    {
                        if (ext_table[i].name) crFree(ext_table[i].name);
                    }
                }
            }

            /*crDebug("MakeCurrent 0x%x, 0x%x", window->device_context, context->hRC);*/
            if (!render_spu.ws.wglMakeCurrent(window->device_context, context->hRC))
            {
                DWORD err = GetLastError();
                crError("Render SPU: (MakeCurrent) failed to make 0x%x, 0x%x current with 0x%x error.", window->device_context, context->hRC, err);
            }
        }

        renderspuAtiQuirk_ChkApply();
    }
    else {
        render_spu.ws.wglMakeCurrent( 0, 0 );
    }
}