context.c revision a804628e06a5bd14e9af77943922ffd9649c221c
a4544a5a0e622ef69e38641f87ab1b5685e05911Phill Cunnington/* Copyright (c) 2001, Stanford University
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * All rights reserved
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * See the file LICENSE.txt for information on redistributing this software.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * \mainpage OpenGL_stub
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * \section OpenGL_stubIntroduction Introduction
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Chromium consists of all the top-level files in the cr
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * directory. The OpenGL_stub module basically takes care of API dispatch,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * and OpenGL state management.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This file manages OpenGL rendering contexts in the faker library.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The big issue is switching between Chromium and native GL context
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * management. This is where we support multiple client OpenGL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * windows. Typically, one window is handled by Chromium while any
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * other windows are handled by the native OpenGL library.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include "chromium.h"
c64331fa7c7a38e49ed3b4194ccdffd41af0ff02Peter Major#include "cr_error.h"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include "cr_spu.h"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include "cr_mem.h"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include "cr_string.h"
6c56bf78246f18c9c14c17ef3ed65065ce178ffdTom Rumsey#include "cr_environment.h"
6c56bf78246f18c9c14c17ef3ed65065ce178ffdTom Rumsey#include "stub.h"
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott/**
bf2a56fd7e5b3bb37378e87e32829a01402d27f0Tom Rumsey * This function should be called from MakeCurrent(). It'll detect if
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott * we're in a multi-thread situation, and do the right thing for dispatch.
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott */
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott#ifdef CHROMIUM_THREADSAFE
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott static void
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert WapshottstubCheckMultithread( void )
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott{
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott static unsigned long knownID;
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott static GLboolean firstCall = GL_TRUE;
32b36b012d0b3ab28eecb13555b3925237c2c5a9Peter Major
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott if (stub.threadSafe)
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott return; /* nothing new, nothing to do */
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott
6309b849c2de831a0eaed9c27b5794bed9bd8fd1Neil Madden if (firstCall) {
c64331fa7c7a38e49ed3b4194ccdffd41af0ff02Peter Major knownID = crThreadID();
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott firstCall = GL_FALSE;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else if (knownID != crThreadID()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* going thread-safe now! */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster stub.threadSafe = GL_TRUE;
a90aba9cbcbb8e7fe95e45590d853959efe0d354Tom Rumsey crSPUCopyDispatchTable(&glim, &stubThreadsafeDispatch);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Install the given dispatch table as the table used for all gl* calls.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster static void
c64331fa7c7a38e49ed3b4194ccdffd41af0ff02Peter MajorstubSetDispatch( SPUDispatchTable *table )
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott{
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott CRASSERT(table);
26304a2a091af368cfc16c977bcce6d17195360aTom Rumsey
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifdef CHROMIUM_THREADSAFE
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* always set the per-thread dispatch pointer */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster crSetTSD(&stub.dispatchTSD, (void *) table);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (stub.threadSafe) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott /* Do nothing - the thread-safe dispatch functions will call GetTSD()
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott * to get a pointer to the dispatch table, and jump through it.
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey */
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey else
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#endif
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey /* Single thread mode - just install the caller's dispatch table */
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey /* This conditional is an optimization to try to avoid unnecessary
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey * copying. It seems to work with atlantis, multiwin, etc. but
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey * _could_ be a problem. (Brian)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey */
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey if (glim.copy_of != table->copy_of)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey crSPUCopyDispatchTable(&glim, table);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey}
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumseyvoid stubForcedFlush(GLint con)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey{
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#if 0
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey GLint buffer;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey stub.spu->dispatch_table.GetIntegerv(GL_DRAW_BUFFER, &buffer);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey stub.spu->dispatch_table.DrawBuffer(GL_FRONT);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey stub.spu->dispatch_table.Flush();
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey stub.spu->dispatch_table.DrawBuffer(buffer);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#else
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey if (con)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott stub.spu->dispatch_table.VBoxConFlush(con);
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott else
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott {
6309b849c2de831a0eaed9c27b5794bed9bd8fd1Neil Madden stub.spu->dispatch_table.Flush();
a90aba9cbcbb8e7fe95e45590d853959efe0d354Tom Rumsey }
a90aba9cbcbb8e7fe95e45590d853959efe0d354Tom Rumsey#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottvoid stubConChromiumParameteriCR(GLint con, GLenum param, GLint value)
7ea769c9edcf1a585b7e3b0b532f790efed64b21David Luna{
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott// if (con)
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott stub.spu->dispatch_table.VBoxConChromiumParameteriCR(con, param, value);
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell// else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster// crError("VBoxConChromiumParameteriCR called with null connection");
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott}
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottvoid stubConChromiumParametervCR(GLint con, GLenum target, GLenum type, GLsizei count, const GLvoid *values)
6309b849c2de831a0eaed9c27b5794bed9bd8fd1Neil Madden{
a90aba9cbcbb8e7fe95e45590d853959efe0d354Tom Rumsey// if (con)
a90aba9cbcbb8e7fe95e45590d853959efe0d354Tom Rumsey stub.spu->dispatch_table.VBoxConChromiumParametervCR(con, target, type, count, values);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster// else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster// crError("VBoxConChromiumParameteriCR called with null connection");
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott}
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshottvoid stubConFlush(GLint con)
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott{
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott if (con)
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott stub.spu->dispatch_table.VBoxConFlush(con);
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott else
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott crError("stubConFlush called with null connection");
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott}
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshottstatic void stubWindowCleanupForContextsCB(unsigned long key, void *data1, void *data2)
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott{
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott ContextInfo *context = (ContextInfo *) data1;
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott
6309b849c2de831a0eaed9c27b5794bed9bd8fd1Neil Madden CRASSERT(context);
6309b849c2de831a0eaed9c27b5794bed9bd8fd1Neil Madden
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott if (context->currentDrawable == data2)
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott context->currentDrawable = NULL;
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott}
c6c8bcf74a1e796c167156af1cc1a5d95c67aceaRobert Wapshott
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumseyvoid stubDestroyWindow( GLint con, GLint window )
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell{
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell WindowInfo *winInfo = (WindowInfo *)
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell crHashtableSearch(stub.windowTable, (unsigned int) window);
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell if (winInfo && winInfo->type == CHROMIUM && stub.spu)
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster crHashtableLock(stub.windowTable);
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell
be367fb48c4c5a05214aab48aea9f09703b63a97Craig McDonnell stub.spu->dispatch_table.VBoxWindowDestroy(con, winInfo->spuWindow );
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#ifdef WINDOWS
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (winInfo->hVisibleRegion != INVALID_HANDLE_VALUE)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell DeleteObject(winInfo->hVisibleRegion);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#elif defined(GLX)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (winInfo->pVisibleRegions)
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell {
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell XFree(winInfo->pVisibleRegions);
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey# ifdef CR_NEWWINTRACK
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell if (winInfo->syncDpy)
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell {
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell XCloseDisplay(winInfo->syncDpy);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster# endif
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster stubForcedFlush(con);
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster crHashtableWalk(stub.contextTable, stubWindowCleanupForContextsCB, winInfo);
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey crHashtableDelete(stub.windowTable, window, crFree);
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell crHashtableUnlock(stub.windowTable);
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell }
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell}
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell/**
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell * Create a new _Chromium_ window, not GLX, WGL or CGL.
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell * Called by crWindowCreate() only.
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell */
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell GLint
786bac66d599daf6355e45e64da84c846a857552Craig McDonnellstubNewWindow( const char *dpyName, GLint visBits )
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell{
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell WindowInfo *winInfo;
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell GLint spuWin, size[2];
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell spuWin = stub.spu->dispatch_table.WindowCreate( dpyName, visBits );
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (spuWin < 0) {
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell return -1;
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell winInfo = (WindowInfo *) crCalloc(sizeof(WindowInfo));
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell if (!winInfo) {
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell stub.spu->dispatch_table.WindowDestroy(spuWin);
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell return -1;
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell }
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell winInfo->type = CHROMIUM;
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell /* Ask the head SPU for the initial window size */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster size[0] = size[1] = 0;
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell stub.spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, 0, GL_INT, 2, size);
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell if (size[0] == 0 && size[1] == 0) {
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell /* use some reasonable defaults */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster size[0] = size[1] = 512;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster winInfo->width = size[0];
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey winInfo->height = size[1];
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#ifdef VBOX_WITH_WDDM
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey if (stub.bRunningUnderWDDM)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey crError("Should not be here: WindowCreate/Destroy & VBoxPackGetInjectID require connection id!");
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey winInfo->mapped = 0;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey else
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#endif
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey winInfo->mapped = 1;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!dpyName)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey dpyName = "";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster crStrncpy(winInfo->dpyName, dpyName, MAX_DPY_NAME);
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell winInfo->dpyName[MAX_DPY_NAME-1] = 0;
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell /* Use spuWin as the hash table index and GLX/WGL handle */
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell#ifdef WINDOWS
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell winInfo->drawable = (HDC) spuWin;
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell winInfo->hVisibleRegion = INVALID_HANDLE_VALUE;
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell#elif defined(Darwin)
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell winInfo->drawable = (CGSWindowID) spuWin;
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell#elif defined(GLX)
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell winInfo->drawable = (GLXDrawable) spuWin;
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell winInfo->pVisibleRegions = NULL;
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell winInfo->cVisibleRegions = 0;
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifdef CR_NEWWINTRACK
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster winInfo->u32ClientID = stub.spu->dispatch_table.VBoxPackGetInjectID(0);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey winInfo->spuWindow = spuWin;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster crHashtableAdd(stub.windowTable, (unsigned int) spuWin, winInfo);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return spuWin;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#ifdef GLX
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumseystatic XErrorHandler oldErrorHandler;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumseystatic unsigned char lastXError = Success;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumseystatic int
c5b669842423d36fc543ddd3ea318bbae4231ecfTom RumseyerrorHandler (Display *dpy, XErrorEvent *e)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey{
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell lastXError = e->error_code;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey return 0;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey}
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#endif
d552ef9965b495ec6fa5f89b12ad638ad4cc87f4Tony Bamford
a19a421277791c670d5a4ebcd6d7af7de159d271Tom RumseyGLboolean
a19a421277791c670d5a4ebcd6d7af7de159d271Tom RumseystubIsWindowVisible(WindowInfo *win)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey{
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#if defined(WINDOWS)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey# ifdef VBOX_WITH_WDDM
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey if (stub.bRunningUnderWDDM)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return win->mapped;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey# endif
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey return GL_TRUE;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#elif defined(Darwin)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey return GL_TRUE;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#elif defined(GLX)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey Display *dpy = stubGetWindowDisplay(win);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey if (dpy)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey XWindowAttributes attr;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey XLOCK(dpy);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey XGetWindowAttributes(dpy, win->drawable, &attr);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey XUNLOCK(dpy);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey if (attr.map_state == IsUnmapped)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey return GL_FALSE;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey# if 1
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey return GL_TRUE;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey# else
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell if (attr.override_redirect)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey return GL_TRUE;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey if (!stub.bXExtensionsChecked)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey stubCheckXExtensions(win);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey if (!stub.bHaveXComposite)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey {
8a888dac872ea5d7dd9ce4a0739c4065d544f275Tom Rumsey return GL_TRUE;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey else
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey Pixmap p;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
d552ef9965b495ec6fa5f89b12ad638ad4cc87f4Tony Bamford crLockMutex(&stub.mutex);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey XLOCK(dpy);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey XSync(dpy, false);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey oldErrorHandler = XSetErrorHandler(errorHandler);
8a888dac872ea5d7dd9ce4a0739c4065d544f275Tom Rumsey /*@todo this will create new pixmap for window every call*/
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey p = XCompositeNameWindowPixmap(dpy, win->drawable);
6309b849c2de831a0eaed9c27b5794bed9bd8fd1Neil Madden XSync(dpy, false);
8a888dac872ea5d7dd9ce4a0739c4065d544f275Tom Rumsey XSetErrorHandler(oldErrorHandler);
8a888dac872ea5d7dd9ce4a0739c4065d544f275Tom Rumsey XUNLOCK(dpy);
8a888dac872ea5d7dd9ce4a0739c4065d544f275Tom Rumsey
a90aba9cbcbb8e7fe95e45590d853959efe0d354Tom Rumsey switch (lastXError)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey case Success:
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey XFreePixmap(dpy, p);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey crUnlockMutex(&stub.mutex);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey return GL_FALSE;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey break;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey case BadMatch:
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey /*Window isn't redirected*/
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey lastXError = Success;
a90aba9cbcbb8e7fe95e45590d853959efe0d354Tom Rumsey break;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey default:
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey crWarning("Unexpected XError %i", (int)lastXError);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey lastXError = Success;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey crUnlockMutex(&stub.mutex);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey return GL_TRUE;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey# endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey /* probably created by crWindowCreate() */
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey return win->mapped;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#endif
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
a90aba9cbcbb8e7fe95e45590d853959efe0d354Tom Rumsey
a90aba9cbcbb8e7fe95e45590d853959efe0d354Tom Rumsey/**
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey * Given a Windows HDC or GLX Drawable, return the corresponding
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey * WindowInfo structure. Create a new one if needed.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
a19a421277791c670d5a4ebcd6d7af7de159d271Tom RumseyWindowInfo *
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#ifdef WINDOWS
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey stubGetWindowInfo( HDC drawable )
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#elif defined(Darwin)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey stubGetWindowInfo( CGSWindowID drawable )
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#elif defined(GLX)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom RumseystubGetWindowInfo( Display *dpy, GLXDrawable drawable )
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#endif
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey{
6309b849c2de831a0eaed9c27b5794bed9bd8fd1Neil Madden#ifndef WINDOWS
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey WindowInfo *winInfo = (WindowInfo *) crHashtableSearch(stub.windowTable, (unsigned int) drawable);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#else
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey WindowInfo *winInfo;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey HWND hwnd;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey hwnd = WindowFromDC(drawable);
32b36b012d0b3ab28eecb13555b3925237c2c5a9Peter Major
c64331fa7c7a38e49ed3b4194ccdffd41af0ff02Peter Major if (!hwnd)
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey return NULL;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey winInfo = (WindowInfo *) crHashtableSearch(stub.windowTable, (unsigned int) hwnd);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#endif
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey if (!winInfo) {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey winInfo = (WindowInfo *) crCalloc(sizeof(WindowInfo));
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey if (!winInfo)
bf2a56fd7e5b3bb37378e87e32829a01402d27f0Tom Rumsey return NULL;
bf2a56fd7e5b3bb37378e87e32829a01402d27f0Tom Rumsey#ifdef GLX
bf2a56fd7e5b3bb37378e87e32829a01402d27f0Tom Rumsey crStrncpy(winInfo->dpyName, DisplayString(dpy), MAX_DPY_NAME);
bf2a56fd7e5b3bb37378e87e32829a01402d27f0Tom Rumsey winInfo->dpyName[MAX_DPY_NAME-1] = 0;
bf2a56fd7e5b3bb37378e87e32829a01402d27f0Tom Rumsey winInfo->dpy = dpy;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey winInfo->pVisibleRegions = NULL;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#elif defined(Darwin)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey winInfo->connection = _CGSDefaultConnection(); // store our connection as default
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#elif defined(WINDOWS)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey winInfo->hVisibleRegion = INVALID_HANDLE_VALUE;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey winInfo->hWnd = hwnd;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#endif
a90aba9cbcbb8e7fe95e45590d853959efe0d354Tom Rumsey winInfo->drawable = drawable;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey winInfo->type = UNDECIDED;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey winInfo->spuWindow = -1;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#ifdef VBOX_WITH_WDDM
fc8409d20f991d53ac0c4708efa04c121b73c449Tom Rumsey if (stub.bRunningUnderWDDM)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey winInfo->mapped = 0;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey else
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#endif
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey winInfo->mapped = -1; /* don't know */
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey winInfo->pOwner = NULL;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#ifdef CR_NEWWINTRACK
a90aba9cbcbb8e7fe95e45590d853959efe0d354Tom Rumsey winInfo->u32ClientID = -1;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#endif
95cd88252d8ce7d506cf8b1dccdc4d531de5dab6Tom Rumsey#ifndef WINDOWS
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey crHashtableAdd(stub.windowTable, (unsigned int) drawable, winInfo);
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell#else
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey crHashtableAdd(stub.windowTable, (unsigned int) hwnd, winInfo);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#ifdef WINDOWS
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster winInfo->drawable = drawable;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
d552ef9965b495ec6fa5f89b12ad638ad4cc87f4Tony Bamford#endif
d552ef9965b495ec6fa5f89b12ad638ad4cc87f4Tony Bamford return winInfo;
d552ef9965b495ec6fa5f89b12ad638ad4cc87f4Tony Bamford}
d552ef9965b495ec6fa5f89b12ad638ad4cc87f4Tony Bamford
d552ef9965b495ec6fa5f89b12ad638ad4cc87f4Tony Bamfordstatic void stubWindowCheckOwnerCB(unsigned long key, void *data1, void *data2);
d552ef9965b495ec6fa5f89b12ad638ad4cc87f4Tony Bamford
d552ef9965b495ec6fa5f89b12ad638ad4cc87f4Tony Bamfordstatic void
d552ef9965b495ec6fa5f89b12ad638ad4cc87f4Tony BamfordstubContextFree( ContextInfo *context )
d552ef9965b495ec6fa5f89b12ad638ad4cc87f4Tony Bamford{
d552ef9965b495ec6fa5f89b12ad638ad4cc87f4Tony Bamford crMemZero(context, sizeof(ContextInfo)); /* just to be safe */
d552ef9965b495ec6fa5f89b12ad638ad4cc87f4Tony Bamford crFree(context);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
4e28a378d7cafffd7988c4c3783c820db42ffb9dAndrew Forrest
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic void
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterstubDestroyContextLocked( ContextInfo *context )
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster unsigned long contextId = context->id;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (context->type == NATIVE) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifdef WINDOWS
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster stub.wsInterface.wglDeleteContext( context->hglrc );
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott#elif defined(Darwin)
786bac66d599daf6355e45e64da84c846a857552Craig McDonnell stub.wsInterface.CGLDestroyContext( context->cglc );
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#elif defined(GLX)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster stub.wsInterface.glXDestroyContext( context->dpy, context->glxContext );
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else if (context->type == CHROMIUM) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Have pack SPU or tilesort SPU, etc. destroy the context */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster CRASSERT(context->spuContext >= 0);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster stub.spu->dispatch_table.DestroyContext( context->spuContext );
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster crHashtableWalk(stub.windowTable, stubWindowCheckOwnerCB, context);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (context->spuConnection)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey stub.spu->dispatch_table.VBoxConDestroy(context->spuConnection);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey context->spuConnection = 0;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#endif
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#ifdef GLX
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey crFreeHashtable(context->pGLXPixmapsHash, crFree);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#endif
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey crHashtableDelete(stub.contextTable, contextId, NULL);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey}
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#ifdef CHROMIUM_THREADSAFE
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumseystatic DECLCALLBACK(void) stubContextDtor(void*pvContext)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey{
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey stubContextFree((ContextInfo*)pvContext);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey}
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#endif
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey/**
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey * Allocate a new ContextInfo object, initialize it, put it into the
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey * context hash table. If type==CHROMIUM, call the head SPU's
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey * CreateContext() function too.
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey */
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey ContextInfo *
a19a421277791c670d5a4ebcd6d7af7de159d271Tom RumseystubNewContext( const char *dpyName, GLint visBits, ContextType type,
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey unsigned long shareCtx
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey , struct VBOXUHGSMI *pHgsmi
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#endif
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey )
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey{
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey GLint spuContext = -1, spuShareCtx = 0, spuConnection = 0;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey ContextInfo *context;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey if (shareCtx > 0) {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey /* translate shareCtx to a SPU context ID */
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey context = (ContextInfo *)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey crHashtableSearch(stub.contextTable, shareCtx);
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey if (context)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey spuShareCtx = context->spuContext;
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey }
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey if (type == CHROMIUM) {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey if (pHgsmi)
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey {
a19a421277791c670d5a4ebcd6d7af7de159d271Tom Rumsey spuConnection = stub.spu->dispatch_table.VBoxConCreate(pHgsmi);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!spuConnection)
{
crWarning("VBoxConCreate failed");
return NULL;
}
}
#endif
spuContext
= stub.spu->dispatch_table.VBoxCreateContext(spuConnection, dpyName, visBits, spuShareCtx);
if (spuContext < 0)
{
crWarning("VBoxCreateContext failed");
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
if (spuConnection)
stub.spu->dispatch_table.VBoxConDestroy(spuConnection);
#endif
return NULL;
}
}
context = crCalloc(sizeof(ContextInfo));
if (!context) {
stub.spu->dispatch_table.DestroyContext(spuContext);
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
if (spuConnection)
stub.spu->dispatch_table.VBoxConDestroy(spuConnection);
#endif
return NULL;
}
if (!dpyName)
dpyName = "";
context->id = stub.freeContextNumber++;
context->type = type;
context->spuContext = spuContext;
context->visBits = visBits;
context->currentDrawable = NULL;
crStrncpy(context->dpyName, dpyName, MAX_DPY_NAME);
context->dpyName[MAX_DPY_NAME-1] = 0;
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
context->spuConnection = spuConnection;
context->pHgsmi = pHgsmi;
#endif
#ifdef CHROMIUM_THREADSAFE
VBoxTlsRefInit(context, stubContextDtor);
#endif
#if defined(GLX) || defined(DARWIN)
context->share = (ContextInfo *)
crHashtableSearch(stub.contextTable, (unsigned long) shareCtx);
#endif
#ifdef GLX
context->pGLXPixmapsHash = crAllocHashtable();
context->damageQueryFailed = GL_FALSE;
context->damageEventsBase = 0;
#endif
crHashtableAdd(stub.contextTable, context->id, (void *) context);
return context;
}
#ifdef Darwin
#define SET_ATTR(l,i,a) ( (l)[(i)++] = (a) )
#define SET_ATTR_V(l,i,a,v) ( SET_ATTR(l,i,a), SET_ATTR(l,i,v) )
void stubSetPFA( ContextInfo *ctx, CGLPixelFormatAttribute *attribs, int size, GLint *num ) {
GLuint visual = ctx->visBits;
int i = 0;
CRASSERT(visual & CR_RGB_BIT);
SET_ATTR_V(attribs, i, kCGLPFAColorSize, 8);
if( visual & CR_DEPTH_BIT )
SET_ATTR_V(attribs, i, kCGLPFADepthSize, 16);
if( visual & CR_ACCUM_BIT )
SET_ATTR_V(attribs, i, kCGLPFAAccumSize, 1);
if( visual & CR_STENCIL_BIT )
SET_ATTR_V(attribs, i, kCGLPFAStencilSize, 1);
if( visual & CR_ALPHA_BIT )
SET_ATTR_V(attribs, i, kCGLPFAAlphaSize, 1);
if( visual & CR_DOUBLE_BIT )
SET_ATTR(attribs, i, kCGLPFADoubleBuffer);
if( visual & CR_STEREO_BIT )
SET_ATTR(attribs, i, kCGLPFAStereo);
/* SET_ATTR_V(attribs, i, kCGLPFASampleBuffers, 1);
SET_ATTR_V(attribs, i, kCGLPFASamples, 0);
SET_ATTR_V(attribs, i, kCGLPFADisplayMask, 0); */
SET_ATTR(attribs, i, kCGLPFABackingStore);
SET_ATTR(attribs, i, kCGLPFAWindow);
SET_ATTR_V(attribs, i, kCGLPFADisplayMask, ctx->disp_mask);
SET_ATTR(attribs, i, 0);
*num = i;
}
#endif
/**
* This creates a native GLX/WGL context.
*/
static GLboolean
InstantiateNativeContext( WindowInfo *window, ContextInfo *context )
{
#ifdef WINDOWS
context->hglrc = stub.wsInterface.wglCreateContext( window->drawable );
return context->hglrc ? GL_TRUE : GL_FALSE;
#elif defined(Darwin)
CGLContextObj shareCtx = NULL;
CGLPixelFormatObj pix;
long npix;
CGLPixelFormatAttribute attribs[16];
GLint ind = 0;
if( context->share ) {
if( context->cglc != context->share->cglc ) {
crWarning("CGLCreateContext() is trying to share a non-existant "
"CGL context. Setting share context to zero.");
shareCtx = 0;
}
else
shareCtx = context->cglc;
}
stubSetPFA( context, attribs, 16, &ind );
stub.wsInterface.CGLChoosePixelFormat( attribs, &pix, &npix );
stub.wsInterface.CGLCreateContext( pix, shareCtx, &context->cglc );
if( !context->cglc )
crError("InstantiateNativeContext: Couldn't Create the context!");
stub.wsInterface.CGLDestroyPixelFormat( pix );
if( context->parambits ) {
/* Set the delayed parameters */
if( context->parambits & VISBIT_SWAP_RECT )
stub.wsInterface.CGLSetParameter( context->cglc, kCGLCPSwapRectangle, context->swap_rect );
if( context->parambits & VISBIT_SWAP_INTERVAL )
stub.wsInterface.CGLSetParameter( context->cglc, kCGLCPSwapInterval, &(context->swap_interval) );
if( context->parambits & VISBIT_CLIENT_STORAGE )
stub.wsInterface.CGLSetParameter( context->cglc, kCGLCPClientStorage, (long*)&(context->client_storage) );
context->parambits = 0;
}
return context->cglc ? GL_TRUE : GL_FALSE;
#elif defined(GLX)
GLXContext shareCtx = 0;
/* sort out context sharing here */
if (context->share) {
if (context->glxContext != context->share->glxContext) {
crWarning("glXCreateContext() is trying to share a non-existant "
"GLX context. Setting share context to zero.");
shareCtx = 0;
}
else {
shareCtx = context->glxContext;
}
}
context->glxContext = stub.wsInterface.glXCreateContext( window->dpy,
context->visual, shareCtx, context->direct );
return context->glxContext ? GL_TRUE : GL_FALSE;
#endif
}
/**
* Utility functions to get window size and titlebar text.
*/
#ifdef WINDOWS
void
stubGetWindowGeometry(const WindowInfo *window, int *x, int *y,
unsigned int *w, unsigned int *h )
{
RECT rect;
if (!window->drawable || !window->hWnd) {
*w = *h = 0;
return;
}
if (window->hWnd!=WindowFromDC(window->drawable))
{
crWarning("Window(%i) DC is no longer valid", window->spuWindow);
return;
}
if (!GetClientRect(window->hWnd, &rect))
{
crWarning("GetClientRect failed for %p", window->hWnd);
*w = *h = 0;
return;
}
*w = rect.right - rect.left;
*h = rect.bottom - rect.top;
if (!ClientToScreen( window->hWnd, (LPPOINT) &rect ))
{
crWarning("ClientToScreen failed for %p", window->hWnd);
*w = *h = 0;
return;
}
*x = rect.left;
*y = rect.top;
}
static void
GetWindowTitle( const WindowInfo *window, char *title )
{
/* XXX - we don't handle recurseUp */
if (window->hWnd)
GetWindowText(window->hWnd, title, 100);
else
title[0] = 0;
}
static void
GetCursorPosition(WindowInfo *window, int pos[2])
{
RECT rect;
POINT point;
GLint size[2], x, y;
unsigned int NativeHeight, NativeWidth, ChromiumHeight, ChromiumWidth;
float WidthRatio, HeightRatio;
static int DebugFlag = 0;
// apparently the "window" parameter passed to this
// function contains the native window information
HWND NATIVEhwnd = window->hWnd;
if (NATIVEhwnd!=WindowFromDC(window->drawable))
{
crWarning("Window(%i) DC is no longer valid", window->spuWindow);
return;
}
// get the native window's height and width
stubGetWindowGeometry(window, &x, &y, &NativeWidth, &NativeHeight);
// get the spu window's height and width
stub.spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, window->spuWindow, GL_INT, 2, size);
ChromiumWidth = size[0];
ChromiumHeight = size[1];
// get the ratio of the size of the native window to the cr window
WidthRatio = (float)ChromiumWidth / (float)NativeWidth;
HeightRatio = (float)ChromiumHeight / (float)NativeHeight;
// output some debug information at the beginning
if(DebugFlag)
{
DebugFlag = 0;
crDebug("Native Window Handle = %d", NATIVEhwnd);
crDebug("Native Width = %i", NativeWidth);
crDebug("Native Height = %i", NativeHeight);
crDebug("Chromium Width = %i", ChromiumWidth);
crDebug("Chromium Height = %i", ChromiumHeight);
}
if (NATIVEhwnd)
{
GetClientRect( NATIVEhwnd, &rect );
GetCursorPos (&point);
// make sure these coordinates are relative to the native window,
// not the whole desktop
ScreenToClient(NATIVEhwnd, &point);
// calculate the new position of the virtual cursor
pos[0] = (int)(point.x * WidthRatio);
pos[1] = (int)((NativeHeight - point.y) * HeightRatio);
}
else
{
pos[0] = 0;
pos[1] = 0;
}
}
#elif defined(Darwin)
extern OSStatus CGSGetScreenRectForWindow( CGSConnectionID cid, CGSWindowID wid, float *outRect );
extern OSStatus CGSGetWindowBounds( CGSConnectionID cid, CGSWindowID wid, float *bounds );
void
stubGetWindowGeometry( const WindowInfo *window, int *x, int *y, unsigned int *w, unsigned int *h )
{
float rect[4];
if( !window ||
!window->connection ||
!window->drawable ||
CGSGetWindowBounds( window->connection, window->drawable, rect ) != noErr )
{
*x = *y = 0;
*w = *h = 0;
} else {
*x = (int) rect[0];
*y = (int) rect[1];
*w = (int) rect[2];
*h = (int) rect[3];
}
}
static void
GetWindowTitle( const WindowInfo *window, char *title )
{
/* XXX \todo Darwin window Title */
title[0] = '\0';
}
static void
GetCursorPosition( const WindowInfo *window, int pos[2] )
{
Point mouse_pos;
float window_rect[4];
GetMouse( &mouse_pos );
CGSGetScreenRectForWindow( window->connection, window->drawable, window_rect );
pos[0] = mouse_pos.h - (int) window_rect[0];
pos[1] = (int) window_rect[3] - (mouse_pos.v - (int) window_rect[1]);
/*crDebug( "%i %i", pos[0], pos[1] );*/
}
#elif defined(GLX)
void
stubGetWindowGeometry(WindowInfo *window, int *x, int *y, unsigned int *w, unsigned int *h)
{
Window root, child;
unsigned int border, depth;
Display *dpy;
dpy = stubGetWindowDisplay(window);
//@todo: Performing those checks is expensive operation, especially for simple apps with high FPS.
// Disabling those triples glxgears fps, thus using xevents instead of per frame polling is much more preferred.
//@todo: Check similar on windows guests, though doubtful as there're no XSync like calls on windows.
if (window && dpy)
{
XLOCK(dpy);
}
if (!window
|| !dpy
|| !window->drawable
|| !XGetGeometry(dpy, window->drawable, &root, x, y, w, h, &border, &depth)
|| !XTranslateCoordinates(dpy, window->drawable, root, 0, 0, x, y, &child))
{
crWarning("Failed to get windows geometry for %p, try xwininfo", window);
*x = *y = 0;
*w = *h = 0;
}
if (window && dpy)
{
XUNLOCK(dpy);
}
}
static char *
GetWindowTitleHelper( Display *dpy, Window window, GLboolean recurseUp )
{
while (1) {
char *name;
if (!XFetchName(dpy, window, &name))
return NULL;
if (name[0]) {
return name;
}
else if (recurseUp) {
/* This window has no name, try the parent */
Status stat;
Window root, parent, *children;
unsigned int numChildren;
stat = XQueryTree( dpy, window, &root, &parent,
&children, &numChildren );
if (!stat || window == root)
return NULL;
if (children)
XFree(children);
window = parent;
}
else {
XFree(name);
return NULL;
}
}
}
static void
GetWindowTitle( const WindowInfo *window, char *title )
{
char *t = GetWindowTitleHelper(window->dpy, window->drawable, GL_TRUE);
if (t) {
crStrcpy(title, t);
XFree(t);
}
else {
title[0] = 0;
}
}
/**
*Return current cursor position in local window coords.
*/
static void
GetCursorPosition(WindowInfo *window, int pos[2] )
{
int rootX, rootY;
Window root, child;
unsigned int mask;
int x, y;
XLOCK(window->dpy);
Bool q = XQueryPointer(window->dpy, window->drawable, &root, &child,
&rootX, &rootY, &pos[0], &pos[1], &mask);
if (q) {
unsigned int w, h;
stubGetWindowGeometry( window, &x, &y, &w, &h );
/* invert Y */
pos[1] = (int) h - pos[1] - 1;
}
else {
pos[0] = pos[1] = 0;
}
XUNLOCK(window->dpy);
}
#endif
/**
* This function is called by MakeCurrent() and determines whether or
* not a new rendering context should be bound to Chromium or the native
* OpenGL.
* \return GL_FALSE if native OpenGL should be used, or GL_TRUE if Chromium
* should be used.
*/
static GLboolean
stubCheckUseChromium( WindowInfo *window )
{
int x, y;
unsigned int w, h;
/* If the provided window is CHROMIUM, we're clearly intended
* to create a CHROMIUM context.
*/
if (window->type == CHROMIUM)
return GL_TRUE;
if (stub.ignoreFreeglutMenus) {
const char *glutMenuTitle = "freeglut menu";
char title[1000];
GetWindowTitle(window, title);
if (crStrcmp(title, glutMenuTitle) == 0) {
crDebug("GL faker: Ignoring freeglut menu window");
return GL_FALSE;
}
}
/* If the user's specified a window count for Chromium, see if
* this window satisfies that criterium.
*/
stub.matchChromiumWindowCounter++;
if (stub.matchChromiumWindowCount > 0) {
if (stub.matchChromiumWindowCounter != stub.matchChromiumWindowCount) {
crDebug("Using native GL, app window doesn't meet match_window_count");
return GL_FALSE;
}
}
/* If the user's specified a window list to ignore, see if this
* window satisfies that criterium.
*/
if (stub.matchChromiumWindowID) {
GLuint i;
for (i = 0; i <= stub.numIgnoreWindowID; i++) {
if (stub.matchChromiumWindowID[i] == stub.matchChromiumWindowCounter) {
crDebug("Ignore window ID %d, using native GL", stub.matchChromiumWindowID[i]);
return GL_FALSE;
}
}
}
/* If the user's specified a minimum window size for Chromium, see if
* this window satisfies that criterium.
*/
if (stub.minChromiumWindowWidth > 0 &&
stub.minChromiumWindowHeight > 0) {
stubGetWindowGeometry( window, &x, &y, &w, &h );
if (w >= stub.minChromiumWindowWidth &&
h >= stub.minChromiumWindowHeight) {
/* Check for maximum sized window now too */
if (stub.maxChromiumWindowWidth &&
stub.maxChromiumWindowHeight) {
if (w < stub.maxChromiumWindowWidth &&
h < stub.maxChromiumWindowHeight)
return GL_TRUE;
else
return GL_FALSE;
}
return GL_TRUE;
}
crDebug("Using native GL, app window doesn't meet minimum_window_size");
return GL_FALSE;
}
else if (stub.matchWindowTitle) {
/* If the user's specified a window title for Chromium, see if this
* window satisfies that criterium.
*/
GLboolean wildcard = GL_FALSE;
char title[1000];
char *titlePattern;
int len;
/* check for leading '*' wildcard */
if (stub.matchWindowTitle[0] == '*') {
titlePattern = crStrdup( stub.matchWindowTitle + 1 );
wildcard = GL_TRUE;
}
else {
titlePattern = crStrdup( stub.matchWindowTitle );
}
/* check for trailing '*' wildcard */
len = crStrlen(titlePattern);
if (len > 0 && titlePattern[len - 1] == '*') {
titlePattern[len - 1] = '\0'; /* terminate here */
wildcard = GL_TRUE;
}
GetWindowTitle( window, title );
if (title[0]) {
if (wildcard) {
if (crStrstr(title, titlePattern)) {
crFree(titlePattern);
return GL_TRUE;
}
}
else if (crStrcmp(title, titlePattern) == 0) {
crFree(titlePattern);
return GL_TRUE;
}
}
crFree(titlePattern);
crDebug("Using native GL, app window title doesn't match match_window_title string (\"%s\" != \"%s\")", title, stub.matchWindowTitle);
return GL_FALSE;
}
/* Window title and size don't matter */
CRASSERT(stub.minChromiumWindowWidth == 0);
CRASSERT(stub.minChromiumWindowHeight == 0);
CRASSERT(stub.matchWindowTitle == NULL);
/* User hasn't specified a width/height or window title.
* We'll use chromium for this window (and context) if no other is.
*/
return GL_TRUE; /* use Chromium! */
}
static void stubWindowCheckOwnerCB(unsigned long key, void *data1, void *data2)
{
WindowInfo *pWindow = (WindowInfo *) data1;
ContextInfo *pCtx = (ContextInfo *) data2;
if (pWindow->pOwner == pCtx)
{
#ifdef WINDOWS
/* Note: can't use WindowFromDC(context->pOwnWindow->drawable) here
because GL context is already released from DC and actual guest window
could be destroyed.
*/
stubDestroyWindow(CR_CTX_CON(pCtx), (GLint)pWindow->hWnd);
#else
stubDestroyWindow(CR_CTX_CON(pCtx), (GLint)pWindow->drawable);
#endif
}
}
GLboolean stubCtxCreate(ContextInfo *context)
{
/*
* Create a Chromium context.
*/
#if defined(GLX) || defined(DARWIN)
GLint spuShareCtx = context->share ? context->share->spuContext : 0;
#else
GLint spuShareCtx = 0;
#endif
GLint spuConnection = 0;
CRASSERT(stub.spu);
CRASSERT(stub.spu->dispatch_table.CreateContext);
context->type = CHROMIUM;
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
if (context->pHgsmi)
{
spuConnection = stub.spu->dispatch_table.VBoxConCreate(context->pHgsmi);
if (!spuConnection)
{
crWarning("VBoxConCreate failed");
return GL_FALSE;
}
context->spuConnection = spuConnection;
}
#endif
context->spuContext
= stub.spu->dispatch_table.VBoxCreateContext(spuConnection, context->dpyName,
context->visBits,
spuShareCtx);
return GL_TRUE;
}
GLboolean stubCtxCheckCreate(ContextInfo *context)
{
if (context->type == UNDECIDED)
return stubCtxCreate(context);
return CHROMIUM == context->type;
}
GLboolean
stubMakeCurrent( WindowInfo *window, ContextInfo *context )
{
GLboolean retVal;
/*
* Get WindowInfo and ContextInfo pointers.
*/
if (!context || !window) {
ContextInfo * currentContext = stubGetCurrentContext();
if (currentContext)
currentContext->currentDrawable = NULL;
if (context)
context->currentDrawable = NULL;
stubSetCurrentContext(NULL);
return GL_TRUE; /* OK */
}
#ifdef CHROMIUM_THREADSAFE
stubCheckMultithread();
#endif
if (context->type == UNDECIDED) {
/* Here's where we really create contexts */
#ifdef CHROMIUM_THREADSAFE
crLockMutex(&stub.mutex);
#endif
if (stubCheckUseChromium(window)) {
GLint spuConnection = 0;
if (!stubCtxCreate(context))
{
crWarning("stubCtxCreate failed");
return GL_FALSE;
}
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
spuConnection = context->spuConnection;
#endif
if (window->spuWindow == -1)
{
/*crDebug("(1)stubMakeCurrent ctx=%p(%i) window=%p(%i)", context, context->spuContext, window, window->spuWindow);*/
window->spuWindow = stub.spu->dispatch_table.VBoxWindowCreate(spuConnection, window->dpyName, context->visBits );
#ifdef CR_NEWWINTRACK
window->u32ClientID = stub.spu->dispatch_table.VBoxPackGetInjectID(spuConnection);
#endif
}
}
else {
/*
* Create a native OpenGL context.
*/
if (!InstantiateNativeContext(window, context))
{
#ifdef CHROMIUM_THREADSAFE
crUnlockMutex(&stub.mutex);
#endif
return 0; /* false */
}
context->type = NATIVE;
}
#ifdef CHROMIUM_THREADSAFE
crUnlockMutex(&stub.mutex);
#endif
}
if (context->type == NATIVE) {
/*
* Native OpenGL MakeCurrent().
*/
#ifdef WINDOWS
retVal = (GLboolean) stub.wsInterface.wglMakeCurrent( window->drawable, context->hglrc );
#elif defined(Darwin)
// XXX \todo We need to differentiate between these two..
retVal = ( stub.wsInterface.CGLSetSurface(context->cglc, window->connection, window->drawable, window->surface) == noErr );
retVal = ( stub.wsInterface.CGLSetCurrentContext(context->cglc) == noErr );
#elif defined(GLX)
retVal = (GLboolean) stub.wsInterface.glXMakeCurrent( window->dpy, window->drawable, context->glxContext );
#endif
}
else {
/*
* SPU chain MakeCurrent().
*/
CRASSERT(context->type == CHROMIUM);
CRASSERT(context->spuContext >= 0);
/*if (context->currentDrawable && context->currentDrawable != window)
crDebug("Rebinding context %p to a different window", context);*/
if (window->type == NATIVE) {
crWarning("Can't rebind a chromium context to a native window\n");
retVal = 0;
}
else {
if (window->spuWindow == -1)
{
/*crDebug("(2)stubMakeCurrent ctx=%p(%i) window=%p(%i)", context, context->spuContext, window, window->spuWindow);*/
window->spuWindow = stub.spu->dispatch_table.VBoxWindowCreate(
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
context->spuConnection,
#else
0,
#endif
window->dpyName, context->visBits );
#ifdef CR_NEWWINTRACK
window->u32ClientID = stub.spu->dispatch_table.VBoxPackGetInjectID(
# if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
context->spuConnection
# else
0
# endif
);
#endif
if (context->currentDrawable && context->currentDrawable->type==CHROMIUM
&& context->currentDrawable->pOwner==context)
{
#ifdef WINDOWS
if (context->currentDrawable->hWnd!=WindowFromDC(context->currentDrawable->drawable))
{
stubDestroyWindow(CR_CTX_CON(context), (GLint)context->currentDrawable->hWnd);
}
#else
Window root;
int x, y;
unsigned int border, depth, w, h;
XLOCK(context->currentDrawable->dpy);
if (!XGetGeometry(context->currentDrawable->dpy, context->currentDrawable->drawable, &root, &x, &y, &w, &h, &border, &depth))
{
stubDestroyWindow(CR_CTX_CON(context), (GLint)context->currentDrawable->drawable);
}
XUNLOCK(context->currentDrawable->dpy);
#endif
}
}
if (window->spuWindow != (GLint)window->drawable)
stub.spu->dispatch_table.MakeCurrent( window->spuWindow, (GLint) window->drawable, context->spuContext );
else
stub.spu->dispatch_table.MakeCurrent( window->spuWindow, 0, /* native window handle */ context->spuContext );
retVal = 1;
}
}
window->type = context->type;
window->pOwner = context;
context->currentDrawable = window;
stubSetCurrentContext(context);
if (retVal) {
/* Now, if we've transitions from Chromium to native rendering, or
* vice versa, we have to change all the OpenGL entrypoint pointers.
*/
if (context->type == NATIVE) {
/* Switch to native API */
/*printf(" Switching to native API\n");*/
stubSetDispatch(&stub.nativeDispatch);
}
else if (context->type == CHROMIUM) {
/* Switch to stub (SPU) API */
/*printf(" Switching to spu API\n");*/
stubSetDispatch(&stub.spuDispatch);
}
else {
/* no API switch needed */
}
}
if (!window->width && window->type == CHROMIUM) {
/* One time window setup */
int x, y;
unsigned int winW, winH;
stubGetWindowGeometry( window, &x, &y, &winW, &winH );
/* If we're not using GLX/WGL (no app window) we'll always get
* a width and height of zero here. In that case, skip the viewport
* call since we're probably using a tilesort SPU with fake_window_dims
* which the tilesort SPU will use for the viewport.
*/
window->width = winW;
window->height = winH;
#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
if (stubIsWindowVisible(window))
#endif
{
if (stub.trackWindowSize)
stub.spuDispatch.WindowSize( window->spuWindow, winW, winH );
if (stub.trackWindowPos)
stub.spuDispatch.WindowPosition(window->spuWindow, x, y);
if (winW > 0 && winH > 0)
stub.spu->dispatch_table.Viewport( 0, 0, winW, winH );
}
#ifdef VBOX_WITH_WDDM
if (stub.trackWindowVisibleRgn)
stub.spu->dispatch_table.WindowVisibleRegion(window->spuWindow, 0, NULL);
#endif
}
/* Update window mapping state.
* Basically, this lets us hide render SPU windows which correspond
* to unmapped application windows. Without this, "pertly" (for example)
* opens *lots* of temporary windows which otherwise clutter the screen.
*/
if (stub.trackWindowVisibility && window->type == CHROMIUM && window->drawable) {
const int mapped = stubIsWindowVisible(window);
if (mapped != window->mapped) {
crDebug("Dispatched: WindowShow(%i, %i)", window->spuWindow, mapped);
stub.spu->dispatch_table.WindowShow(window->spuWindow, mapped);
window->mapped = mapped;
}
}
return retVal;
}
void
stubDestroyContext( unsigned long contextId )
{
ContextInfo *context;
if (!stub.contextTable) {
return;
}
/* the lock order is windowTable->contextTable (see wglMakeCurrent_prox, glXMakeCurrent)
* this is why we need to take a windowTable lock since we will later do stub.windowTable access & locking */
crHashtableLock(stub.windowTable);
crHashtableLock(stub.contextTable);
context = (ContextInfo *) crHashtableSearch(stub.contextTable, contextId);
CRASSERT(context);
stubDestroyContextLocked(context);
#ifdef CHROMIUM_THREADSAFE
if (stubGetCurrentContext() == context) {
stubSetCurrentContext(NULL);
}
VBoxTlsRefMarkDestroy(context);
VBoxTlsRefRelease(context);
#else
if (stubGetCurrentContext() == context) {
stubSetCurrentContext(NULL);
}
stubContextFree(context);
#endif
crHashtableUnlock(stub.contextTable);
crHashtableUnlock(stub.windowTable);
}
void
stubSwapBuffers(WindowInfo *window, GLint flags)
{
if (!window)
return;
/* Determine if this window is being rendered natively or through
* Chromium.
*/
if (window->type == NATIVE) {
/*printf("*** Swapping native window %d\n", (int) drawable);*/
#ifdef WINDOWS
(void) stub.wsInterface.wglSwapBuffers( window->drawable );
#elif defined(Darwin)
/* ...is this ok? */
/* stub.wsInterface.CGLFlushDrawable( context->cglc ); */
crDebug("stubSwapBuffers: unable to swap (no context!)");
#elif defined(GLX)
stub.wsInterface.glXSwapBuffers( window->dpy, window->drawable );
#endif
}
else if (window->type == CHROMIUM) {
/* Let the SPU do the buffer swap */
/*printf("*** Swapping chromium window %d\n", (int) drawable);*/
if (stub.appDrawCursor) {
int pos[2];
GetCursorPosition(window, pos);
stub.spu->dispatch_table.ChromiumParametervCR(GL_CURSOR_POSITION_CR, GL_INT, 2, pos);
}
stub.spu->dispatch_table.SwapBuffers( window->spuWindow, flags );
}
else {
crDebug("Calling SwapBuffers on a window we haven't seen before (no-op).");
}
}