ovr_sdk

diff LibOVR/Src/Displays/OVR_Linux_SDKWindow.cpp @ 0:1b39a1b46319

initial 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 14 Jan 2015 06:51:16 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/LibOVR/Src/Displays/OVR_Linux_SDKWindow.cpp	Wed Jan 14 06:51:16 2015 +0200
     1.3 @@ -0,0 +1,649 @@
     1.4 +/*******************************************************************************
     1.5 +
     1.6 +Filename    :   OVR_Linux_SDKWindow.cpp
     1.7 +Content     :   SDK generated Linux window.
     1.8 +Created     :   October 1, 2014
     1.9 +Authors     :   James Hughes
    1.10 +
    1.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
    1.12 +
    1.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
    1.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
    1.15 +which is provided at the time of installation or download, or which 
    1.16 +otherwise accompanies this software in either electronic or hard copy form.
    1.17 +
    1.18 +You may obtain a copy of the License at
    1.19 +
    1.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
    1.21 +
    1.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
    1.23 +distributed under the License is distributed on an "AS IS" BASIS,
    1.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    1.25 +See the License for the specific language governing permissions and
    1.26 +limitations under the License.
    1.27 +
    1.28 +*******************************************************************************/
    1.29 +
    1.30 +#include "OVR_Linux_SDKWindow.h"
    1.31 +#include "../Kernel/OVR_Log.h"
    1.32 +#include "../Kernel/OVR_Log.h"
    1.33 +#include "../../../3rdParty/EDID/edid.h"
    1.34 +
    1.35 +namespace OVR {
    1.36 +
    1.37 +// Forward declarations
    1.38 +static Window       constructWindow(struct _XDisplay* display, int xscreen,
    1.39 +                                    XVisualInfo* xvisual,
    1.40 +                                    const LinuxDeviceScreen& screen);
    1.41 +
    1.42 +static XRRModeInfo* findModeByXID(XRRScreenResources* screen, RRMode xid)
    1.43 +{
    1.44 +  for (int m = 0; m < screen->nmode; ++m)
    1.45 +  {
    1.46 +    XRRModeInfo* mode = &screen->modes[m];
    1.47 +    if (xid == mode->id)
    1.48 +    {
    1.49 +      return mode;
    1.50 +    }
    1.51 +  }
    1.52 +  return NULL;
    1.53 +}
    1.54 +
    1.55 +/// Retrieves a list of available device screens on which we can build
    1.56 +/// SDK windows. Returns number of devices found.
    1.57 +///   screens        Array which this function will populate.
    1.58 +///   maxNumScreens  Maximum number of screens to store in screens.
    1.59 +static int getDeviceScreens(LinuxDeviceScreen* screens, int maxNumDevices)
    1.60 +{
    1.61 +    struct _XDisplay* disp = XOpenDisplay(NULL);
    1.62 +    if (!disp)
    1.63 +    {
    1.64 +        OVR::LogError("[SDKWindow] Unable to open X Display.");
    1.65 +        return 0;
    1.66 +    }
    1.67 +
    1.68 +    int numDevices = 0;
    1.69 +    int numScreens = XScreenCount(disp);
    1.70 +    for (int i = 0; i < numScreens; ++i)
    1.71 +    {
    1.72 +        // Screen root is used to detect what video output the crtc is using.
    1.73 +        Window sr                  = XRootWindow(disp, i);
    1.74 +        XRRScreenResources* screen = XRRGetScreenResources(disp, sr);
    1.75 +
    1.76 +        for (int ii = 0; ii < screen->ncrtc; ++ii)
    1.77 +        {
    1.78 +            XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(disp, screen, screen->crtcs[ii]);
    1.79 +
    1.80 +            if (0 == crtcInfo->noutput)
    1.81 +            {
    1.82 +                XRRFreeCrtcInfo(crtcInfo);
    1.83 +                continue;
    1.84 +            }
    1.85 +
    1.86 +            bool foundOutput = false;
    1.87 +            RROutput output = crtcInfo->outputs[0];
    1.88 +            for (int k = 0; k < crtcInfo->noutput; ++k)
    1.89 +            {
    1.90 +                XRROutputInfo* outputInfo =
    1.91 +                    XRRGetOutputInfo(disp, screen, crtcInfo->outputs[k]);
    1.92 +                for (int kk = 0 ; kk < outputInfo->nmode; ++kk)
    1.93 +                {
    1.94 +                    if (outputInfo->modes[kk] == crtcInfo->mode)
    1.95 +                    {
    1.96 +                        output = crtcInfo->outputs[k];
    1.97 +                        foundOutput = true;
    1.98 +                        break;
    1.99 +                    }
   1.100 +                }
   1.101 +                XRRFreeOutputInfo(outputInfo);
   1.102 +                if (foundOutput) { break; }
   1.103 +            }
   1.104 +
   1.105 +            if (!foundOutput)
   1.106 +            {
   1.107 +                XRRFreeCrtcInfo(crtcInfo);
   1.108 +                continue;
   1.109 +            }
   1.110 +
   1.111 +            XRROutputInfo* outputInfo = XRRGetOutputInfo(disp, screen, output);
   1.112 +            if (RR_Connected != outputInfo->connection)
   1.113 +            {
   1.114 +                XRRFreeOutputInfo(outputInfo);
   1.115 +                XRRFreeCrtcInfo(crtcInfo);
   1.116 +                continue;
   1.117 +            }
   1.118 +
   1.119 +            // Read EDID associated with crtc.
   1.120 +            MonitorInfo* mi = read_edid_data(disp, output);
   1.121 +            if (mi == NULL)
   1.122 +            {
   1.123 +                XRRFreeOutputInfo(outputInfo);
   1.124 +                XRRFreeCrtcInfo(crtcInfo);
   1.125 +                continue;
   1.126 +            }
   1.127 +
   1.128 +            if (strcmp(mi->manufacturer_code, "OVR") == 0)
   1.129 +            {
   1.130 +                XRRModeInfo* modeInfo = findModeByXID(screen, crtcInfo->mode);
   1.131 +
   1.132 +                DistortionRotation desiredRot = DistRotateNone;
   1.133 +                if (mi->product_code == 3)
   1.134 +                {
   1.135 +                    // This is a DK2, we may have to rotate our output.
   1.136 +                    // If we don't have to, we should alert the user that
   1.137 +                    // rotating the display using the DM or graphics
   1.138 +                    // card settings is highly non-optimal.
   1.139 +                    desiredRot = DistRotateCCW90;
   1.140 +                    if (crtcInfo->rotation != RR_Rotate_0)
   1.141 +                    {
   1.142 +                        OVR::LogError("Please do not rotate your rift's screen.");
   1.143 +
   1.144 +                        if (crtcInfo->rotation == RR_Rotate_90)
   1.145 +                        {
   1.146 +                            // The user has manually rotated the screen.
   1.147 +                            // So apply no rotation on our end.
   1.148 +                            desiredRot = DistRotateNone;
   1.149 +                        }
   1.150 +                    }
   1.151 +                }
   1.152 +                else
   1.153 +                {
   1.154 +                    if (crtcInfo->rotation != RR_Rotate_0)
   1.155 +                    {
   1.156 +                        OVR::LogError("Please do not rotate your rift's screen.");
   1.157 +                    }
   1.158 +                }
   1.159 +
   1.160 +                int width = modeInfo->width;
   1.161 +                int height = modeInfo->height;
   1.162 +
   1.163 +                // Swap width / height if display is rotated (shouldn't be on linux).
   1.164 +                if (   crtcInfo->rotation == RR_Rotate_90
   1.165 +                    || crtcInfo->rotation == RR_Rotate_270)
   1.166 +                {
   1.167 +                    width  = modeInfo->height;
   1.168 +                    height = modeInfo->width;
   1.169 +                }
   1.170 +
   1.171 +                // Push detected monitor.
   1.172 +                screens[numDevices].set(i, screen->crtcs[ii], desiredRot,
   1.173 +                                        mi->product_code, width, height,
   1.174 +                                        crtcInfo->x, crtcInfo->y);
   1.175 +                ++numDevices;
   1.176 +            }
   1.177 +
   1.178 +            delete mi;
   1.179 +
   1.180 +            if (numDevices == maxNumDevices)
   1.181 +            {
   1.182 +                XRRFreeOutputInfo(outputInfo);
   1.183 +                XRRFreeCrtcInfo(crtcInfo);
   1.184 +                XRRFreeScreenResources(screen);
   1.185 +                OVR::LogError("[SDKWindow] Maxed out number of devices..");
   1.186 +                XCloseDisplay(disp);
   1.187 +                return numDevices;
   1.188 +            }
   1.189 +
   1.190 +            XRRFreeOutputInfo(outputInfo);
   1.191 +            XRRFreeCrtcInfo(crtcInfo);
   1.192 +        }
   1.193 +
   1.194 +        XRRFreeScreenResources(screen);
   1.195 +    }
   1.196 +    XCloseDisplay(disp);
   1.197 +    return numDevices;
   1.198 +}
   1.199 +
   1.200 +
   1.201 +LinuxDeviceScreen SDKWindow::findDevScreenForHMD(const ovrHmd& hmd)
   1.202 +{
   1.203 +    return findDevScreenForDevID(hmd->DisplayDeviceName);
   1.204 +}
   1.205 +
   1.206 +LinuxDeviceScreen SDKWindow::findDevScreenForDevID(const char* deviceIDIn)
   1.207 +{
   1.208 +    const int maxNumDevices = 5;
   1.209 +    LinuxDeviceScreen screens[maxNumDevices];
   1.210 +    int numDevices = getDeviceScreens(screens, maxNumDevices);
   1.211 +
   1.212 +    if (numDevices > 0)
   1.213 +    {
   1.214 +        // Identify target for SDK window via hmd info.
   1.215 +        for (int i = 0; i < numDevices; ++i)
   1.216 +        {
   1.217 +            LinuxDeviceScreen& screen = screens[i];
   1.218 +
   1.219 +            char deviceID[32];
   1.220 +            OVR_sprintf(deviceID, 32, "OVR%04d-%d",
   1.221 +                        screen.productCode, screen.crtcid);
   1.222 +
   1.223 +            if (strcmp(deviceIDIn, deviceID) == 0)
   1.224 +            {
   1.225 +                return screen;
   1.226 +            }
   1.227 +        }
   1.228 +    }
   1.229 +
   1.230 +    return LinuxDeviceScreen();
   1.231 +}
   1.232 +
   1.233 +DistortionRotation SDKWindow::getRotation(const ovrHmd& hmd)
   1.234 +{
   1.235 +    LinuxDeviceScreen screen = findDevScreenForHMD(hmd);
   1.236 +    if (screen.isValid())
   1.237 +    {
   1.238 +        return screen.rotation;
   1.239 +    }
   1.240 +    else
   1.241 +    {
   1.242 +        return DistRotateNone;
   1.243 +    }
   1.244 +}
   1.245 +
   1.246 +
   1.247 +bool SDKWindow::getVisualFromDrawable(GLXDrawable drawable, XVisualInfo* vinfoOut)
   1.248 +{
   1.249 +    struct _XDisplay* display = glXGetCurrentDisplay();
   1.250 +
   1.251 +    unsigned int value;
   1.252 +    glXQueryDrawable(display, drawable, GLX_FBCONFIG_ID, &value);
   1.253 +    const int attribs[] = {GLX_FBCONFIG_ID, (int)value, None};
   1.254 +    int screen;
   1.255 +    glXQueryContext(display, glXGetCurrentContext(), GLX_SCREEN, &screen);
   1.256 +    int numElems;
   1.257 +    GLXFBConfig* config = glXChooseFBConfig(display, screen, attribs, &numElems);
   1.258 +    if (numElems > 0)
   1.259 +    {
   1.260 +        XVisualInfo* chosen = glXGetVisualFromFBConfig(display, *config);
   1.261 +        *vinfoOut = *chosen;
   1.262 +        XFree(config);
   1.263 +        return true;
   1.264 +    }
   1.265 +    return false;
   1.266 +}
   1.267 +
   1.268 +SDKWindow::SDKWindow(const ovrHmd& hmd) :
   1.269 +    mXDisplay(NULL),
   1.270 +    mXScreen(-1),
   1.271 +    mXVisual(NULL),
   1.272 +    mXUniqueContext(-1),
   1.273 +    mXWindow(0),
   1.274 +    mFBConfigID(0)
   1.275 +{
   1.276 +    OVR_UNUSED(hmd);
   1.277 +}
   1.278 +
   1.279 +SDKWindow::~SDKWindow()
   1.280 +{
   1.281 +    if (mXWindow)
   1.282 +    {
   1.283 +        XDeleteContext(mXDisplay, mXWindow, mXUniqueContext);
   1.284 +        XUnmapWindow(mXDisplay, mXWindow);
   1.285 +        XDestroyWindow(mXDisplay, mXWindow);
   1.286 +        mXWindow = static_cast<Window>(0);
   1.287 +    }
   1.288 +
   1.289 +    if (mXVisual)
   1.290 +    {
   1.291 +        XFree(mXVisual);
   1.292 +        mXVisual = NULL;
   1.293 +    }
   1.294 +
   1.295 +    if (mXDisplay)
   1.296 +    {
   1.297 +        XCloseDisplay(mXDisplay);
   1.298 +    }
   1.299 +}
   1.300 +
   1.301 +void SDKWindow::buildVisualAndWindow(const LinuxDeviceScreen& devScreen)
   1.302 +{
   1.303 +    mXDisplay       = XOpenDisplay(NULL);
   1.304 +    mXUniqueContext = XUniqueContext();
   1.305 +    mXScreen        = devScreen.screen;
   1.306 +    mFBConfigID     = chooseFBConfigID(mXDisplay, mXScreen);
   1.307 +
   1.308 +    mXVisual = getVisual(mXDisplay, mFBConfigID, mXScreen);
   1.309 +    if (mXVisual != NULL)
   1.310 +    {
   1.311 +        mXWindow = constructWindow(mXDisplay, mXScreen, mXVisual, devScreen);
   1.312 +        mDeviceScreen = devScreen;
   1.313 +    }
   1.314 +}
   1.315 +
   1.316 +// Used in chooseVisual. May need to expose this to the end use so they can
   1.317 +// choose an appropriate framebuffer configuration.
   1.318 +struct FBConfig
   1.319 +{
   1.320 +  FBConfig() :
   1.321 +      redBits(8),
   1.322 +      greenBits(8),
   1.323 +      blueBits(8),
   1.324 +      alphaBits(8),
   1.325 +      depthBits(8),
   1.326 +      stencilBits(-1),
   1.327 +      doubleBuffer(true),
   1.328 +      auxBuffers(-1)
   1.329 +  {}
   1.330 +
   1.331 +  int  redBits;
   1.332 +  int  greenBits;
   1.333 +  int  blueBits;
   1.334 +  int  alphaBits;
   1.335 +  int  depthBits;
   1.336 +  int  stencilBits;
   1.337 +  bool doubleBuffer;
   1.338 +  int  auxBuffers;
   1.339 +
   1.340 +  int xcfg;
   1.341 +};
   1.342 +
   1.343 +static int fbCalcContrib(int desired, int current)
   1.344 +{
   1.345 +    int diff = desired - current;
   1.346 +    if (current != -1) { return diff * diff; }
   1.347 +    else               { return 0; }
   1.348 +}
   1.349 +
   1.350 +// Choose frame buffer configuration and return fbConfigID.
   1.351 +int SDKWindow::chooseFBConfigID(struct _XDisplay* display, int xscreen)
   1.352 +{
   1.353 +    int nativeCount = 0;
   1.354 +    GLXFBConfig* nativeConfigs =
   1.355 +        glXGetFBConfigs(display, xscreen, &nativeCount);
   1.356 +    if (!nativeCount)
   1.357 +    {
   1.358 +        OVR::LogError("[SDKWindow] No valid frame buffer configurations found.");
   1.359 +        return 0;
   1.360 +    }
   1.361 +
   1.362 +    FBConfig* usables = static_cast<FBConfig*>(calloc(nativeCount, sizeof(FBConfig)));
   1.363 +    int numUsables = 0;
   1.364 +
   1.365 +    for (int i = 0; i < nativeCount; ++i)
   1.366 +    {
   1.367 +        GLXFBConfig native = nativeConfigs[i];
   1.368 +        FBConfig* usable   = &usables[numUsables];
   1.369 +        int v              = 0;
   1.370 +
   1.371 +        // Only frame buffer configcs with attached visuals.
   1.372 +        glXGetFBConfigAttrib(display, native, GLX_VISUAL_ID, &v);
   1.373 +        if (!v) { continue; }
   1.374 +
   1.375 +        // Only RGBA frame buffers.
   1.376 +        glXGetFBConfigAttrib(display, native, GLX_RENDER_TYPE, &v);
   1.377 +        if (!(v & GLX_RGBA_BIT)) { continue; }
   1.378 +
   1.379 +        glXGetFBConfigAttrib(display, native, GLX_DRAWABLE_TYPE, &v);
   1.380 +        if (!(v & GLX_WINDOW_BIT)) { continue; }
   1.381 +
   1.382 +        glXGetFBConfigAttrib(display, native, GLX_DEPTH_SIZE,   &usable->depthBits);
   1.383 +        glXGetFBConfigAttrib(display, native, GLX_STENCIL_SIZE, &usable->stencilBits);
   1.384 +
   1.385 +        glXGetFBConfigAttrib(display, native, GLX_RED_SIZE,     &usable->redBits);
   1.386 +        glXGetFBConfigAttrib(display, native, GLX_GREEN_SIZE,   &usable->greenBits);
   1.387 +        glXGetFBConfigAttrib(display, native, GLX_BLUE_SIZE,    &usable->blueBits);
   1.388 +        glXGetFBConfigAttrib(display, native, GLX_ALPHA_SIZE,   &usable->alphaBits);
   1.389 +
   1.390 +        glXGetFBConfigAttrib(display, native, GLX_ALPHA_SIZE,   &usable->auxBuffers);
   1.391 +
   1.392 +        glXGetFBConfigAttrib(display, native, GLX_DOUBLEBUFFER, &v);
   1.393 +        usable->doubleBuffer = v ? true : false;
   1.394 +
   1.395 +        glXGetFBConfigAttrib(display, native, GLX_FBCONFIG_ID, &usable->xcfg);
   1.396 +
   1.397 +        ++numUsables;
   1.398 +    }
   1.399 +
   1.400 +    // We really want std::numeric_limits<int>::max() instead of hardcoded vals.
   1.401 +    const int MostMissing = 100;
   1.402 +    int leastMissing      = MostMissing;
   1.403 +    int leastBias         = MostMissing;
   1.404 +
   1.405 +    const FBConfig* closest = NULL;
   1.406 +    
   1.407 +    // Desired is currently the default config built by constructor.
   1.408 +    FBConfig desired;
   1.409 +
   1.410 +    for (int i = 0; i < numUsables; ++i)
   1.411 +    {
   1.412 +        const FBConfig* cur = &usables[i];
   1.413 +
   1.414 +        if (desired.doubleBuffer != cur->doubleBuffer) { continue; }
   1.415 +
   1.416 +        int missing = 0;
   1.417 +        if (desired.alphaBits > 0 && cur->alphaBits == 0) { ++missing; }
   1.418 +        if (desired.depthBits > 0 && cur->depthBits == 0) { ++missing; }
   1.419 +        if (desired.stencilBits > 0 && cur->stencilBits == 0) { ++missing; }
   1.420 +        if (desired.redBits > 0 && desired.redBits != cur->redBits) { ++missing; }
   1.421 +        if (desired.greenBits > 0 && desired.greenBits != cur->greenBits) { ++missing; }
   1.422 +        if (desired.blueBits > 0 && desired.blueBits != cur->blueBits) { ++missing; }
   1.423 +
   1.424 +        int bias = fbCalcContrib(desired.redBits,     cur->redBits)
   1.425 +                 + fbCalcContrib(desired.greenBits,   cur->greenBits)
   1.426 +                 + fbCalcContrib(desired.blueBits,    cur->blueBits)
   1.427 +                 + fbCalcContrib(desired.alphaBits,   cur->alphaBits)
   1.428 +                 + fbCalcContrib(desired.depthBits,   cur->depthBits)
   1.429 +                 + fbCalcContrib(desired.stencilBits, cur->stencilBits);
   1.430 +
   1.431 +        if (missing < leastMissing)
   1.432 +        {
   1.433 +            closest = cur;
   1.434 +        }
   1.435 +        else if (missing == leastMissing)
   1.436 +        {
   1.437 +            // Now select against squared differences.
   1.438 +            if (bias < leastBias)
   1.439 +            {
   1.440 +                closest = cur;
   1.441 +            }
   1.442 +        }
   1.443 +
   1.444 +        if (closest == cur)
   1.445 +        {
   1.446 +            leastMissing = missing;
   1.447 +            leastBias    = bias;
   1.448 +        }
   1.449 +    }
   1.450 +
   1.451 +    if (closest == NULL)
   1.452 +    {
   1.453 +        OVR::LogError("[SDKWindow] Failed to select appropriate frame buffer.");
   1.454 +        XFree(nativeConfigs);
   1.455 +        free(usables);
   1.456 +        return 0;
   1.457 +    }
   1.458 +
   1.459 +    int retVal = closest->xcfg;
   1.460 +
   1.461 +    XFree(nativeConfigs);
   1.462 +    free(usables);
   1.463 +
   1.464 +    return retVal;
   1.465 +}
   1.466 +
   1.467 +// Obtain visual from frame buffer configuration ID.
   1.468 +XVisualInfo* SDKWindow::getVisual(struct _XDisplay* display,
   1.469 +                                  int fbConfigID, int xscreen)
   1.470 +{
   1.471 +    GLXFBConfig* cfg = getGLXFBConfig(display, fbConfigID, xscreen);
   1.472 +    XVisualInfo* viOut = NULL;
   1.473 +    if (cfg != NULL)
   1.474 +    {
   1.475 +        viOut = glXGetVisualFromFBConfig(display, *cfg);
   1.476 +        XFree(cfg);
   1.477 +        cfg = NULL;
   1.478 +    }
   1.479 +    else
   1.480 +    {
   1.481 +        OVR::LogError("Unable to find fb config ID.");
   1.482 +    }
   1.483 +    return viOut;
   1.484 +}
   1.485 +
   1.486 +// GLXFBConfig pointer from frame buffer configuration ID. You must call
   1.487 +// XFree on the GLXFBConfig pointer.
   1.488 +GLXFBConfig* SDKWindow::getGLXFBConfig(struct _XDisplay* display,
   1.489 +                                       int fbConfigID, int xscreen)
   1.490 +{
   1.491 +    const int attribs[] = {GLX_FBCONFIG_ID, (int)fbConfigID, None};
   1.492 +    int numElems;
   1.493 +
   1.494 +    GLXFBConfig* config = glXChooseFBConfig(display, xscreen, attribs, &numElems);
   1.495 +    if (numElems > 0)
   1.496 +    {
   1.497 +        return config;
   1.498 +    }
   1.499 +    else
   1.500 +    {
   1.501 +        return NULL;
   1.502 +    }
   1.503 +}
   1.504 +
   1.505 +
   1.506 +static int gXLastError = -1;
   1.507 +static int handleXError(struct _XDisplay* display, XErrorEvent* event)
   1.508 +{
   1.509 +  OVR_UNUSED(display);
   1.510 +  gXLastError = event->error_code;
   1.511 +  return 0;
   1.512 +}
   1.513 +
   1.514 +static void obtainXErrorHandler()
   1.515 +{
   1.516 +  gXLastError = Success;
   1.517 +  XSetErrorHandler(handleXError);
   1.518 +}
   1.519 +
   1.520 +static void releaseXErrorHandler(struct _XDisplay* display)
   1.521 +{
   1.522 +  XSync(display, False);
   1.523 +  XSetErrorHandler(NULL);
   1.524 +}
   1.525 +
   1.526 +// Returns 0 on error, otherwise a valid X window is returned.
   1.527 +static Window constructWindow(struct _XDisplay* xDisp, int xScreen,
   1.528 +                              XVisualInfo* xVisual,
   1.529 +                              const LinuxDeviceScreen& devScreen)
   1.530 +{
   1.531 +    XSetWindowAttributes wa;
   1.532 +
   1.533 +    Window root       = XRootWindow(xDisp, xScreen);
   1.534 +    Window xWindowOut = 0;
   1.535 +
   1.536 +    // Create Window
   1.537 +    {
   1.538 +        Colormap xWinColorMapOut = XCreateColormap(
   1.539 +            xDisp, root, xVisual->visual, AllocNone);
   1.540 +        unsigned long wamask = CWBorderPixel | CWColormap | CWEventMask;
   1.541 +
   1.542 +        wa.colormap = xWinColorMapOut;
   1.543 +        wa.border_pixel = 0;
   1.544 +        wa.event_mask = StructureNotifyMask  | ExposureMask    | FocusChangeMask
   1.545 +                      | VisibilityChangeMask | EnterWindowMask | LeaveWindowMask
   1.546 +                      | PropertyChangeMask;
   1.547 +
   1.548 +        obtainXErrorHandler();
   1.549 +
   1.550 +        xWindowOut = XCreateWindow(xDisp, root,
   1.551 +                                   0, 0,
   1.552 +                                   devScreen.width, devScreen.height,
   1.553 +                                   0,
   1.554 +                                   xVisual->depth,
   1.555 +                                   InputOutput,
   1.556 +                                   xVisual->visual,
   1.557 +                                   wamask,
   1.558 +                                   &wa);
   1.559 +
   1.560 +        releaseXErrorHandler(xDisp);
   1.561 +
   1.562 +        if (!xWindowOut)
   1.563 +        {
   1.564 +            OVR::LogError("[SDKWindow] Failed to create SDK window.");
   1.565 +            return 0;
   1.566 +        }
   1.567 +
   1.568 +        XFreeColormap(xDisp, xWinColorMapOut);
   1.569 +    }
   1.570 +
   1.571 +    // OVERRIDE REDIRECT.
   1.572 +    XSetWindowAttributes attributes;
   1.573 +    attributes.override_redirect = True;
   1.574 +    XChangeWindowAttributes(xDisp, xWindowOut,
   1.575 +                            CWOverrideRedirect, &attributes);
   1.576 +
   1.577 +    // Show the window (do this in full screen or windowed).
   1.578 +    XMapRaised(xDisp, xWindowOut);
   1.579 +    XFlush(xDisp);
   1.580 +
   1.581 +    // Position ourselves manually since there should be no WM managing us.
   1.582 +    XRaiseWindow(xDisp, xWindowOut);
   1.583 +    XMoveWindow(xDisp, xWindowOut, devScreen.offsetX, devScreen.offsetY);
   1.584 +    XResizeWindow(xDisp, xWindowOut, devScreen.width, devScreen.height);
   1.585 +
   1.586 +    XFlush(xDisp);
   1.587 +
   1.588 +    // WM Backup in case there still exists a WM managing us...
   1.589 +    Atom NET_WM_BYPASS_COMPOSITOR = 
   1.590 +        XInternAtom(xDisp, "_NET_WM_BYPASS_COMPOSITOR", False);
   1.591 +    Atom NET_WM_STATE =
   1.592 +        XInternAtom(xDisp, "_NET_WM_STATE", False);
   1.593 +    Atom NET_WM_STATE_FULLSCREEN =
   1.594 +        XInternAtom(xDisp, "_NET_WM_STATE_FULLSCREEN", False);
   1.595 +    Atom NET_ACTIVE_WINDOW =
   1.596 +        XInternAtom(xDisp, "_NET_ACTIVE_WINDOW", False);
   1.597 +
   1.598 +    // Bypass compositor if we are under a compositing WM.
   1.599 +    // Just in case a WM ignores our override_redirect.
   1.600 +    if (NET_WM_BYPASS_COMPOSITOR)
   1.601 +    {
   1.602 +        const unsigned long bypass = 1;
   1.603 +        XChangeProperty(xDisp, xWindowOut,
   1.604 +                        NET_WM_BYPASS_COMPOSITOR,
   1.605 +                        XA_CARDINAL, 32, PropModeReplace,
   1.606 +                        (unsigned char*)&bypass, 1);
   1.607 +    }
   1.608 +
   1.609 +    if (NET_WM_STATE && NET_WM_STATE_FULLSCREEN)
   1.610 +    {
   1.611 +        // BACKUP: If we are still managed by a WM we want fullscreen.
   1.612 +        const int EWMH_STATE_ADD    = 1;
   1.613 +
   1.614 +        if (NET_ACTIVE_WINDOW)
   1.615 +        {
   1.616 +            XEvent event;
   1.617 +            memset(&event, 0, sizeof(event));
   1.618 +
   1.619 +            event.type = ClientMessage;
   1.620 +            event.xclient.window = xWindowOut;
   1.621 +            event.xclient.format = 32;
   1.622 +            event.xclient.message_type = NET_ACTIVE_WINDOW;
   1.623 +            event.xclient.data.l[0] = 1;
   1.624 +            event.xclient.data.l[1] = 0;
   1.625 +
   1.626 +            XSendEvent(xDisp, root, False,
   1.627 +                       SubstructureNotifyMask | SubstructureRedirectMask,
   1.628 +                       &event);
   1.629 +        }
   1.630 +
   1.631 +        XEvent event;
   1.632 +        memset(&event, 0, sizeof(event));
   1.633 +
   1.634 +        event.type = ClientMessage;
   1.635 +        event.xclient.window = xWindowOut;
   1.636 +        event.xclient.format = 32;
   1.637 +        event.xclient.message_type = NET_WM_STATE;
   1.638 +        event.xclient.data.l[0] = EWMH_STATE_ADD;
   1.639 +        event.xclient.data.l[1] = NET_WM_STATE_FULLSCREEN;
   1.640 +        event.xclient.data.l[2] = 0;
   1.641 +        event.xclient.data.l[3] = 1;
   1.642 +
   1.643 +        XSendEvent(xDisp, root, False,
   1.644 +                   SubstructureNotifyMask | SubstructureRedirectMask,
   1.645 +                   &event);
   1.646 +    }
   1.647 +
   1.648 +    return xWindowOut;
   1.649 +}
   1.650 +
   1.651 +} // namespace OVR
   1.652 +