aboutsummaryrefslogtreecommitdiffstats
path: root/Samples/CommonSrc
diff options
context:
space:
mode:
Diffstat (limited to 'Samples/CommonSrc')
-rw-r--r--Samples/CommonSrc/Platform/Gamepad.h2
-rw-r--r--Samples/CommonSrc/Platform/Linux_Gamepad.cpp451
-rw-r--r--Samples/CommonSrc/Platform/Linux_Gamepad.h83
-rw-r--r--Samples/CommonSrc/Platform/Linux_Platform.cpp1045
-rw-r--r--Samples/CommonSrc/Platform/Linux_Platform.h149
-rw-r--r--Samples/CommonSrc/Platform/OSX_Platform.mm1661
-rw-r--r--Samples/CommonSrc/Platform/Platform.cpp2
-rw-r--r--Samples/CommonSrc/Platform/Platform.h2
-rw-r--r--Samples/CommonSrc/Platform/Platform_Default.h2
-rw-r--r--Samples/CommonSrc/Platform/Win32_Gamepad.cpp68
-rw-r--r--Samples/CommonSrc/Platform/Win32_Gamepad.h5
-rw-r--r--Samples/CommonSrc/Platform/Win32_Platform.cpp35
-rw-r--r--Samples/CommonSrc/Platform/Win32_Platform.h2
-rw-r--r--Samples/CommonSrc/Render/Render_D3D10_Device.cpp2
-rw-r--r--Samples/CommonSrc/Render/Render_D3D10_Device.h2
-rw-r--r--Samples/CommonSrc/Render/Render_D3D11_Device.cpp2
-rw-r--r--Samples/CommonSrc/Render/Render_D3D11_Device.h2
-rw-r--r--Samples/CommonSrc/Render/Render_D3D1X_Device.cpp166
-rw-r--r--Samples/CommonSrc/Render/Render_D3D1X_Device.h30
-rw-r--r--Samples/CommonSrc/Render/Render_Device.cpp16
-rw-r--r--Samples/CommonSrc/Render/Render_Device.h12
-rw-r--r--Samples/CommonSrc/Render/Render_Font.h2
-rw-r--r--Samples/CommonSrc/Render/Render_GL_Device.cpp801
-rw-r--r--Samples/CommonSrc/Render/Render_GL_Device.h234
-rw-r--r--Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp8
-rw-r--r--Samples/CommonSrc/Render/Render_GL_Win32_Device.h2
-rw-r--r--Samples/CommonSrc/Render/Render_LoadTextureDDS.cpp2
-rw-r--r--Samples/CommonSrc/Render/Render_LoadTextureTGA.cpp2
-rw-r--r--Samples/CommonSrc/Render/Render_XmlSceneLoader.cpp97
-rw-r--r--Samples/CommonSrc/Render/Render_XmlSceneLoader.h2
-rw-r--r--Samples/CommonSrc/Util/OptionMenu.cpp19
-rw-r--r--Samples/CommonSrc/Util/OptionMenu.h2
-rw-r--r--Samples/CommonSrc/Util/RenderProfiler.cpp13
-rw-r--r--Samples/CommonSrc/Util/RenderProfiler.h8
34 files changed, 4024 insertions, 907 deletions
diff --git a/Samples/CommonSrc/Platform/Gamepad.h b/Samples/CommonSrc/Platform/Gamepad.h
index d078bdb..e6295ca 100644
--- a/Samples/CommonSrc/Platform/Gamepad.h
+++ b/Samples/CommonSrc/Platform/Gamepad.h
@@ -5,7 +5,7 @@ Content : Cross platform Gamepad interface.
Created : May 6, 2013
Authors : Lee Cooper
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/Samples/CommonSrc/Platform/Linux_Gamepad.cpp b/Samples/CommonSrc/Platform/Linux_Gamepad.cpp
new file mode 100644
index 0000000..c333efa
--- /dev/null
+++ b/Samples/CommonSrc/Platform/Linux_Gamepad.cpp
@@ -0,0 +1,451 @@
+/************************************************************************************
+
+Filename : Linux_Gamepad.cpp
+Content : Linux implementation of Platform app infrastructure
+Created : May 6, 2013
+Authors : Lee Cooper, Simon Hallam
+
+Copyright : Copyright 2012 Oculus VR, LLC. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <glob.h>
+#include <linux/joystick.h>
+#include "Linux_Gamepad.h"
+
+
+namespace OVR { namespace OvrPlatform { namespace Linux {
+
+const char* pNameXbox360Wireless = "Xbox 360";
+const char* pNameXbox360Wired = "Microsoft X-Box 360";
+
+
+GamepadManager::GamepadManager() :
+ pDevice(NULL)
+{
+ if (!pDevice)
+ {
+ // get a list of paths to all the connected joystick devices
+ glob_t joystickGlobBuffer;
+ glob("/dev/input/js*", 0, NULL, &joystickGlobBuffer);
+
+ // open each joystick device, until we find one that will work for our needs
+ for (UInt32 i = 0; i < joystickGlobBuffer.gl_pathc; i++)
+ {
+ pDevice = new Gamepad();
+ if (pDevice->Open(joystickGlobBuffer.gl_pathv[i]))
+ {
+
+ if (pDevice->IsSupportedType())
+ {
+ break;
+ }
+ }
+
+ // we don't know why the device was not useable, make sure it gets closed cleanly
+ pDevice->Close();
+ pDevice = NULL;
+ }
+ }
+}
+
+GamepadManager::~GamepadManager()
+{
+ // if we have an open device, close it
+ if (pDevice)
+ {
+ pDevice->Close();
+ pDevice = NULL;
+ }
+}
+
+UInt32 GamepadManager::GetGamepadCount()
+{
+ return 1;
+}
+
+bool GamepadManager::GetGamepadState(UInt32 index, GamepadState *pState)
+{
+ if (pDevice)
+ {
+ // we have a device, so update it
+ pDevice->UpdateState();
+
+ // copy the device state into the struct param
+ memcpy(pState, pDevice->GetState(), sizeof(GamepadState));
+
+ // TODO: is the device still active/connected? if not, we should close it
+ // and clear pDevice, so that another device can take over
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+Gamepad::Gamepad() :
+ IsInitialized(false),
+ Name(String("Undefined")),
+ Type(UNDEFINED)
+{
+}
+
+Gamepad::~Gamepad()
+{
+ this->Close();
+}
+
+bool Gamepad::Open(const String& devicePathName)
+{
+ Name = "Undefined";
+ Type = UNDEFINED;
+
+ FileDescriptor = ::open(devicePathName.ToCStr(), O_RDONLY | O_NONBLOCK);
+ if (FileDescriptor == -1)
+ {
+ return false;
+ }
+
+ // get the device name
+ char name[128];
+ if (ioctl(FileDescriptor, JSIOCGNAME(sizeof(name)), name) < 0)
+ {
+ return false;
+ }
+
+ Name = name;
+
+ // see if device name matches one of our supported devices
+ static const UInt32 Wireless360Len = String(pNameXbox360Wireless).GetLength();
+ static const UInt32 Wired360Len = String(pNameXbox360Wired).GetLength();
+ if (Name.Substring(0, Wireless360Len) == pNameXbox360Wireless)
+ {
+ Type = XBOX360GAMEPADWIRELESS;
+ return true;
+ }
+ else if(Name.Substring(0, Wired360Len) == pNameXbox360Wired)
+ {
+ Type = XBOX360GAMEPADWIRED;
+ return true;
+ }
+
+ return false;
+}
+
+bool Gamepad::Close()
+{
+ IsInitialized = false;
+ Name = "Undefined";
+ Type = UNDEFINED;
+ return !::close(FileDescriptor);
+}
+
+void Gamepad::UpdateState()
+{
+ GamepadState *pState = &State;
+ js_event gamepadEvent;
+
+ // read the latest batch of events
+ while (read(FileDescriptor, &gamepadEvent, sizeof(struct js_event)) != -1)
+ {
+ switch (gamepadEvent.type)
+ {
+ case JS_EVENT_BUTTON:
+ IsInitialized = true;
+ SetStateButton(pState, gamepadEvent.number, gamepadEvent.value);
+ break;
+
+ case JS_EVENT_AXIS:
+ IsInitialized = true;
+ SetStateAxis(pState, gamepadEvent.number, gamepadEvent.value);
+ break;
+
+ case JS_EVENT_BUTTON | JS_EVENT_INIT:
+ if (IsInitialized) // skip the fake values during device event initialization
+ {
+ SetStateButton(pState, gamepadEvent.number, gamepadEvent.value);
+ }
+ break;
+
+ case JS_EVENT_AXIS | JS_EVENT_INIT:
+ if (IsInitialized) // skip the fake values during device event initialization
+ {
+ SetStateAxis(pState, gamepadEvent.number, gamepadEvent.value);
+ }
+ break;
+
+ default:
+ LogText("OVR::Linux::UpdateState unknown event type\n");
+ }
+ }
+}
+
+const GamepadState* Gamepad::GetState()
+{
+ return &State;
+}
+
+
+bool Gamepad::IsSupportedType()
+{
+ return Type != UNDEFINED;
+}
+
+const String& Gamepad::GetIdentifier()
+{
+ return Name;
+}
+
+static inline float NormalizeGamepadStickXbox360(SInt32 in)
+{
+ float v;
+ if (abs(in) < 9000) return 0;
+ else if (in > 9000) v = (float)in - 9000;
+ else v = (float)in + 9000;
+ return v / (32767 - 9000);
+}
+
+static inline float NormalizeGamepadTriggerXbox360(SInt32 in,
+ SInt32 offset,
+ SInt32 deadBand,
+ float divisor)
+{
+ in += offset;
+
+ if (in < deadBand)
+ {
+ return 0;
+ }
+ else
+ {
+ return float(in - deadBand) / divisor;
+ }
+}
+
+static inline void UpdateButtonMaskAndBitfield(GamepadState *pState,
+ SInt32 value,
+ UInt32 buttonBitfield)
+{
+ if (value)
+ {
+ pState->Buttons |= buttonBitfield;
+ }
+ else
+ {
+ pState->Buttons = pState->Buttons & (0xFFFFFFFF ^ buttonBitfield);
+ }
+}
+
+void Gamepad::SetStateAxis(GamepadState *pState, UInt32 axis, SInt32 value)
+{
+ // some pads/sticks have lots in common with one another,
+ // handle those shared cases first
+ switch (Type)
+ {
+ case XBOX360GAMEPADWIRELESS:
+ case XBOX360GAMEPADWIRED:
+ switch (axis)
+ {
+ case 0:
+ pState->LX = NormalizeGamepadStickXbox360(value);
+ break;
+
+ case 1:
+ pState->LY = -NormalizeGamepadStickXbox360(value);
+ break;
+
+ case 3:
+ pState->RX = NormalizeGamepadStickXbox360(value);
+ break;
+
+ case 4:
+ pState->RY = -NormalizeGamepadStickXbox360(value);
+ break;
+ }
+ break;
+
+ case UNDEFINED:
+ default:
+ break;
+ }
+
+ // handle the special cases, or pads/sticks which are unique
+ switch (Type)
+ {
+ case XBOX360GAMEPADWIRELESS:
+ switch (axis)
+ {
+ case 2:
+ pState->LT = NormalizeGamepadTriggerXbox360(value, 0, 500, 32267);
+ break;
+
+ case 5:
+ pState->RT = NormalizeGamepadTriggerXbox360(value, 0, 500, 32267);
+ break;
+ }
+ break;
+
+ case XBOX360GAMEPADWIRED:
+ switch (axis)
+ {
+ case 2:
+ pState->LT = NormalizeGamepadTriggerXbox360(value, 32767, 1000, 64535);
+ break;
+
+ case 5:
+ pState->RT = NormalizeGamepadTriggerXbox360(value, 32767, 1000, 64535);
+ break;
+
+ case 6:
+ if (value == 0)
+ {
+ UpdateButtonMaskAndBitfield(pState, 0, Gamepad_Left);
+ UpdateButtonMaskAndBitfield(pState, 0, Gamepad_Right);
+ }
+ else if (value < 0)
+ {
+ UpdateButtonMaskAndBitfield(pState, 1, Gamepad_Left);
+ }
+ else if (value > 0)
+ {
+ UpdateButtonMaskAndBitfield(pState, 1, Gamepad_Right);
+ }
+ break;
+
+ case 7:
+ if (value == 0)
+ {
+ UpdateButtonMaskAndBitfield(pState, 0, Gamepad_Up);
+ UpdateButtonMaskAndBitfield(pState, 0, Gamepad_Down);
+ }
+ else if (value < 0)
+ {
+ UpdateButtonMaskAndBitfield(pState, 1, Gamepad_Up);
+ }
+ else if (value > 0)
+ {
+ UpdateButtonMaskAndBitfield(pState, 1, Gamepad_Down);
+ }
+ break;
+ }
+ break;
+
+ case UNDEFINED:
+ default:
+ break;
+ }
+}
+
+void Gamepad::SetStateButton(GamepadState *pState, UInt32 button, SInt32 value)
+{
+ // some pads/sticks have lots in common with one another,
+ // handle those shared cases first
+ switch (Type)
+ {
+ case XBOX360GAMEPADWIRELESS:
+ case XBOX360GAMEPADWIRED:
+ switch (button)
+ {
+ case 0:
+ UpdateButtonMaskAndBitfield(pState, value, Gamepad_A);
+ break;
+
+ case 1:
+ UpdateButtonMaskAndBitfield(pState, value, Gamepad_B);
+ break;
+
+ case 2:
+ UpdateButtonMaskAndBitfield(pState, value, Gamepad_X);
+ break;
+
+ case 3:
+ UpdateButtonMaskAndBitfield(pState, value, Gamepad_Y);
+ break;
+
+ case 4:
+ UpdateButtonMaskAndBitfield(pState, value, Gamepad_L1);
+ break;
+
+ case 5:
+ UpdateButtonMaskAndBitfield(pState, value, Gamepad_R1);
+ break;
+
+ case 6:
+ UpdateButtonMaskAndBitfield(pState, value, Gamepad_Back);
+ break;
+
+ case 7:
+ UpdateButtonMaskAndBitfield(pState, value, Gamepad_Start);
+ break;
+
+ case 8:
+ // we have no value defined for the Xbox/power button
+ break;
+
+ case 9:
+ UpdateButtonMaskAndBitfield(pState, value, Gamepad_LStick);
+ break;
+
+ case 10:
+ UpdateButtonMaskAndBitfield(pState, value, Gamepad_RStick);
+ break;
+ }
+ break;
+
+ case UNDEFINED:
+ default:
+ break;
+ }
+
+ // handle the special cases, or pads/sticks which are unique
+ switch (Type)
+ {
+ case XBOX360GAMEPADWIRELESS:
+ switch (button)
+ {
+ case 11:
+ UpdateButtonMaskAndBitfield(pState, value, Gamepad_Left);
+ break;
+
+ case 12:
+ UpdateButtonMaskAndBitfield(pState, value, Gamepad_Right);
+ break;
+
+ case 13:
+ UpdateButtonMaskAndBitfield(pState, value, Gamepad_Up);
+ break;
+
+ case 14:
+ UpdateButtonMaskAndBitfield(pState, value, Gamepad_Down);
+ break;
+ }
+
+ case XBOX360GAMEPADWIRED:
+ break;
+
+ case UNDEFINED:
+ default:
+ break;
+ }
+}
+
+}}} // OVR::OvrPlatform::Linux
+
diff --git a/Samples/CommonSrc/Platform/Linux_Gamepad.h b/Samples/CommonSrc/Platform/Linux_Gamepad.h
new file mode 100644
index 0000000..e35e559
--- /dev/null
+++ b/Samples/CommonSrc/Platform/Linux_Gamepad.h
@@ -0,0 +1,83 @@
+/************************************************************************************
+
+Filename : Linux_Gamepad.h
+Content : Linux implementation of Gamepad functionality.
+Created : May 6, 2013
+Authors : Lee Cooper, Simon Hallam
+
+Copyright : Copyright 2012 Oculus VR, LLC. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_Linux_Gamepad_h
+#define OVR_Linux_Gamepad_h
+
+#include "Gamepad.h"
+
+namespace OVR { namespace OvrPlatform { namespace Linux {
+
+class Gamepad; // forward declaration for readability
+
+class GamepadManager : public OvrPlatform::GamepadManager
+{
+public:
+
+ GamepadManager();
+ ~GamepadManager();
+
+ virtual UInt32 GetGamepadCount();
+ virtual bool GetGamepadState(UInt32 index, GamepadState *pState);
+
+private:
+
+ Gamepad *pDevice;
+};
+
+class Gamepad
+{
+public:
+
+ Gamepad();
+ virtual ~Gamepad();
+
+ bool Open(const String& devicePathName);
+ bool Close();
+ bool IsSupportedType();
+ const String& GetIdentifier();
+ void UpdateState();
+ const GamepadState* GetState();
+
+private:
+
+ void SetStateAxis(GamepadState *pState, UInt32 axis, SInt32 value);
+ void SetStateButton(GamepadState *pState, UInt32 button, SInt32 value);
+
+ enum GamepadType
+ {
+ UNDEFINED,
+ XBOX360GAMEPADWIRELESS,
+ XBOX360GAMEPADWIRED
+ };
+
+ UInt32 FileDescriptor;
+ bool IsInitialized;
+ String Name;
+ GamepadType Type;
+ GamepadState State;
+};
+
+}}}
+
+#endif // OVR_Linux_Gamepad_h
diff --git a/Samples/CommonSrc/Platform/Linux_Platform.cpp b/Samples/CommonSrc/Platform/Linux_Platform.cpp
new file mode 100644
index 0000000..c41ba3b
--- /dev/null
+++ b/Samples/CommonSrc/Platform/Linux_Platform.cpp
@@ -0,0 +1,1045 @@
+/************************************************************************************
+
+Filename : Platform_Linux.cpp
+Content : Linux (X11) implementation of Platform app infrastructure
+Created : September 6, 2012
+Authors : Andrew Reisse
+
+Copyright : Copyright 2012 Oculus VR, LLC. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "Kernel/OVR_System.h"
+#include "Kernel/OVR_Array.h"
+#include "Kernel/OVR_String.h"
+#include "Kernel/OVR_Timer.h"
+#include "Kernel/OVR_Threads.h"
+
+#include "Displays/OVR_Linux_SDKWindow.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xmd.h>
+#include <signal.h>
+
+//#include <CAPI/GL/CAPI_GLE.h>
+#include <GL/glx.h> // To be replaced with the above #include.
+
+#include "OVR_CAPI_GL.h"
+
+#include "Linux_Platform.h"
+#include "Linux_Gamepad.h"
+
+#include "../../3rdParty/EDID/edid.h"
+#include <X11/extensions/Xrandr.h>
+
+
+namespace OVR { namespace OvrPlatform { namespace Linux {
+
+struct XDisplayInfo
+{
+ XDisplayInfo() :
+ valid(false),
+ output(0),
+ crtc(0)
+ {}
+
+ bool valid;
+ RROutput output;
+ RRCrtc crtc;
+ int product;
+};
+
+static const char *AtomNames[] = {"WM_PROTOCOLS", "WM_DELETE_WINDOW"};
+
+PlatformCore::PlatformCore(Application* app)
+ : OvrPlatform::PlatformCore(app),
+ StartVP(0, 0, 0, 0),
+ HasWM(false), Disp(NULL), Vis(NULL), Win(0), Quit(0), ExitCode(0),
+ Width(0), Height(0), MMode(Mouse_Normal), InvisibleCursor(), Atoms()
+{
+ pGamepadManager = *new Linux::GamepadManager();
+}
+
+PlatformCore::~PlatformCore()
+{
+ XFreeCursor(Disp, InvisibleCursor);
+
+ if (Disp)
+ {
+ XCloseDisplay(Disp);
+ Disp = NULL;
+ }
+}
+
+// Setup an X11 window in windowed mode.
+void* PlatformCore::SetupWindow(int w, int h)
+{
+ if (!Disp)
+ {
+ XInitThreads();
+
+ Disp = XOpenDisplay(NULL);
+ if (!Disp)
+ {
+ OVR_DEBUG_LOG(("XOpenDisplay failed."));
+ return NULL;
+ }
+
+ XInternAtoms(Disp, const_cast<char**>(AtomNames), NumAtoms, false, Atoms);
+ }
+
+ int screenNumber = DefaultScreen(Disp);
+
+ // Determine if we are running under a WM. Window managers will set the
+ // substructure redirect mask on the root window.
+ XWindowAttributes rootWA;
+ XGetWindowAttributes(Disp, RootWindow(Disp, screenNumber), &rootWA);
+ HasWM = (rootWA.all_event_masks & SubstructureRedirectMask);
+
+ XSetWindowAttributes winattr;
+ unsigned attrmask = CWEventMask | CWBorderPixel;
+
+ winattr.event_mask =
+ ButtonPressMask|ButtonReleaseMask|KeyPressMask|KeyReleaseMask|
+ ButtonMotionMask|PointerMotionMask|StructureNotifyMask|
+ SubstructureNotifyMask;
+ winattr.border_pixel = 0;
+
+ if (!Vis)
+ {
+ int attr[16];
+ int nattr = 2;
+
+ attr[0] = GLX_RGBA;
+ attr[1] = GLX_DOUBLEBUFFER;
+ attr[nattr++] = GLX_DEPTH_SIZE;
+ attr[nattr++] = 24;
+ attr[nattr] = 0;
+
+ Vis = glXChooseVisual(Disp, screenNumber, attr);
+
+ if (!Vis)
+ {
+ OVR_DEBUG_LOG(("glXChooseVisual failed."));
+ return NULL;
+ }
+ }
+
+ Window rootWindow = XRootWindow(Disp, Vis->screen);
+
+ winattr.colormap = XCreateColormap(Disp, rootWindow, Vis->visual, AllocNone);
+ attrmask |= CWColormap;
+
+ Win = XCreateWindow(Disp, rootWindow, 0, 0, w, h, 0, Vis->depth,
+ InputOutput, Vis->visual, attrmask, &winattr);
+
+ if (!Win)
+ {
+ OVR_DEBUG_LOG(("XCreateWindow failed."));
+ return NULL;
+ }
+
+ XStoreName(Disp, Win, "OVR App");
+ XSetWMProtocols(Disp, Win, &Atoms[WM_DELETE_WINDOW], 1);
+
+ // Intialize empty cursor for show/hide.
+ XColor black;
+ static char noData[] = { 0,0,0,0,0,0,0,0 };
+ black.red = black.green = black.blue = 0;
+
+ Pixmap bitmapNoData = XCreateBitmapFromData(Disp, Win, noData, 8, 8);
+ InvisibleCursor = XCreatePixmapCursor(Disp, bitmapNoData, bitmapNoData,
+ &black, &black, 0, 0);
+ XDefineCursor(Disp, Win, InvisibleCursor);
+
+ Width = w;
+ Height = h;
+
+ return (void*)&Win;
+}
+
+void PlatformCore::SetMouseMode(MouseMode mm)
+{
+ if (mm == MMode)
+ return;
+
+ if (Win)
+ {
+ if (mm == Mouse_Relative)
+ {
+ XWarpPointer(Disp, Win, Win, 0,0,Width,Height, Width/2, Height/2);
+ }
+ else
+ {
+ //if (MMode == Mouse_Relative)
+ // ShowCursor(TRUE);
+ }
+ }
+ MMode = mm;
+}
+
+void PlatformCore::GetWindowSize(int* w, int* h) const
+{
+ *w = Width;
+ *h = Height;
+}
+
+void PlatformCore::SetWindowTitle(const char* title)
+{
+ XStoreName(Disp, Win, title);
+}
+
+void PlatformCore::ShowWindow(bool show)
+{
+ if (show)
+ {
+ XRaiseWindow(Disp, Win);
+ }
+ else
+ {
+ XIconifyWindow(Disp, Win, 0);
+ }
+}
+
+void PlatformCore::DestroyWindow()
+{
+ if (Win)
+ {
+ XDestroyWindow(Disp, Win);
+ }
+ Win = 0;
+}
+
+
+static int KeyMap[][2] =
+{
+ { XK_BackSpace, Key_Backspace },
+ { XK_Tab, Key_Tab },
+ { XK_Clear, Key_Clear },
+ { XK_Return, Key_Return },
+ { XK_Shift_L, Key_Shift },
+ { XK_Control_L, Key_Control },
+ { XK_Alt_L, Key_Alt },
+ { XK_Shift_R, Key_Shift },
+ { XK_Control_R, Key_Control },
+ { XK_Alt_R, Key_Alt },
+ { XK_Pause, Key_Pause },
+ { XK_Caps_Lock, Key_CapsLock },
+ { XK_Escape, Key_Escape },
+ { XK_space, Key_Space },
+ { XK_Page_Up, Key_PageUp },
+ { XK_Page_Down, Key_PageDown },
+ { XK_Prior, Key_PageUp },
+ { XK_Next, Key_PageDown },
+ { XK_End, Key_End },
+ { XK_Home, Key_Home },
+ { XK_Left, Key_Left },
+ { XK_Up, Key_Up },
+ { XK_Right, Key_Right },
+ { XK_Down, Key_Down },
+ { XK_Insert, Key_Insert },
+ { XK_Delete, Key_Delete },
+ { XK_Help, Key_Help },
+ { XK_Num_Lock, Key_NumLock },
+ { XK_Scroll_Lock, Key_ScrollLock },
+};
+
+
+static KeyCode MapXKToKeyCode(unsigned vk)
+{
+ unsigned key = Key_None;
+
+ if ((vk >= 'a') && (vk <= 'z'))
+ {
+ key = vk - 'a' + Key_A;
+ }
+ else if ((vk >= ' ') && (vk <= '~'))
+ {
+ key = vk;
+ }
+ else if ((vk >= XK_KP_0) && (vk <= XK_KP_9))
+ {
+ key = vk - XK_KP_0 + Key_KP_0;
+ }
+ else if ((vk >= XK_F1) && (vk <= XK_F15))
+ {
+ key = vk - XK_F1 + Key_F1;
+ }
+ else
+ {
+ for (unsigned i = 0; i< (sizeof(KeyMap) / sizeof(KeyMap[1])); i++)
+ {
+ if (vk == KeyMap[i][0])
+ {
+ key = KeyMap[i][1];
+ break;
+ }
+ }
+ }
+
+ return (KeyCode)key;
+}
+
+static int MapModifiers(int xmod)
+{
+ int mod = 0;
+ if (xmod & ShiftMask)
+ mod |= Mod_Shift;
+ if (xmod & ControlMask)
+ mod |= Mod_Control;
+ if (xmod & Mod1Mask)
+ mod |= Mod_Alt;
+ if (xmod & Mod4Mask)
+ mod |= Mod_Meta;
+ return mod;
+}
+
+void PlatformCore::processEvent(XEvent& event)
+{
+ switch (event.xany.type)
+ {
+ case ConfigureNotify:
+ if (event.xconfigure.width != Width || event.xconfigure.height != Height)
+ {
+ Width = event.xconfigure.width;
+ Height = event.xconfigure.height;
+ pApp->OnResize(Width, Height);
+
+ if (pRender)
+ pRender->SetWindowSize(Width, Height);
+ }
+ break;
+
+ case KeyPress:
+ case KeyRelease:
+ {
+ char chars[8] = {0};
+ KeySym xk;
+ XComposeStatus comp;
+ XLookupString(&event.xkey, chars, sizeof(chars), &xk, &comp);
+ if (xk != XK_VoidSymbol)
+ pApp->OnKey(MapXKToKeyCode((unsigned)xk), chars[0], event.xany.type == KeyPress, MapModifiers(event.xkey.state));
+ if (xk == XK_Escape && MMode == Mouse_Relative)
+ {
+ //ungrab
+ MMode = Mouse_RelativeEscaped;
+ showCursor(true);
+ }
+ }
+ break;
+
+ case MotionNotify:
+ if (MMode == Mouse_Relative)
+ {
+ int dx = event.xmotion.x - Width/2;
+ int dy = event.xmotion.y - Height/2;
+
+ // do not remove this check, WarpPointer generates events too.
+ if (dx == 0 && dy == 0)
+ break;
+
+ XWarpPointer(Disp, Win, Win, 0,0,Width,Height, Width/2, Height/2);
+ pApp->OnMouseMove(dx, dy, Mod_MouseRelative|MapModifiers(event.xmotion.state));
+ }
+ else
+ {
+ pApp->OnMouseMove(event.xmotion.x, event.xmotion.y, MapModifiers(event.xmotion.state));
+ }
+ break;
+
+ case MapNotify:
+ if (MMode == Mouse_Relative)
+ {
+ XWarpPointer(Disp, Win, Win, 0,0,Width,Height, Width/2, Height/2);
+ showCursor(false);
+ }
+ break;
+
+ case ButtonPress:
+ if (event.xbutton.button == 1)
+ {
+ //grab
+
+ if (MMode == Mouse_RelativeEscaped)
+ {
+ XWarpPointer(Disp, Win, Win, 0,0,Width,Height, Width/2, Height/2);
+ showCursor(false);
+ MMode = Mouse_Relative;
+ }
+ }
+ break;
+
+ case FocusOut:
+ if (MMode == Mouse_Relative)
+ {
+ MMode = Mouse_RelativeEscaped;
+ showCursor(true);
+ }
+ break;
+
+ case ClientMessage:
+ if (event.xclient.message_type == Atoms[WM_PROTOCOLS] &&
+ Atom(event.xclient.data.l[0]) == Atoms[WM_DELETE_WINDOW])
+ pApp->OnQuitRequest();
+ break;
+ }
+}
+
+int PlatformCore::Run()
+{
+ while (!Quit)
+ {
+ if (XPending(Disp))
+ {
+ XEvent event;
+ XNextEvent(Disp, &event);
+
+ if (pApp && event.xany.window == Win)
+ processEvent(event);
+ }
+ else
+ {
+ pApp->OnIdle();
+ }
+ }
+
+ return ExitCode;
+}
+
+bool PlatformCore::determineScreenOffset(int screenId, int* screenOffsetX, int* screenOffsetY)
+{
+ bool foundScreen = false;
+
+ RROutput primaryOutput = XRRGetOutputPrimary(Disp, DefaultRootWindow(Disp));
+ XRRScreenResources* screen = XRRGetScreenResources(Disp, Win);
+
+ int screenIndex = 0;
+ for (int i = 0; i < screen->ncrtc; ++i)
+ {
+ XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(Disp, screen, screen->crtcs[i]);
+
+ if (0 == crtcInfo->noutput)
+ {
+ XRRFreeCrtcInfo(crtcInfo);
+ // We intentionally do not increment screenIndex. We do not
+ // consider this a valid display.
+ continue;
+ }
+
+ RROutput output = crtcInfo->outputs[0];
+ for (int ii = 0; ii < crtcInfo->noutput; ++ii)
+ {
+ if (primaryOutput == crtcInfo->outputs[ii])
+ {
+ output = primaryOutput;
+ break;
+ }
+ }
+
+ XRROutputInfo* outputInfo = XRRGetOutputInfo(Disp, screen, output);
+ if (RR_Connected != outputInfo->connection)
+ {
+ XRRFreeOutputInfo(outputInfo);
+ XRRFreeCrtcInfo(crtcInfo);
+ continue;
+ }
+
+ if (screenId == screenIndex)
+ {
+ *screenOffsetX = crtcInfo->x;
+ *screenOffsetY = crtcInfo->y;
+ foundScreen = true;
+ break;
+ }
+
+ XRRFreeOutputInfo(outputInfo);
+ XRRFreeCrtcInfo(crtcInfo);
+
+ ++screenIndex;
+ }
+ XRRFreeScreenResources(screen);
+
+ return foundScreen;
+}
+
+void PlatformCore::showWindowDecorations(bool show)
+{
+ // Declaration of 'MOTIF_WM_HINTS' struct and flags can be found at:
+ // https://people.gnome.org/~tthurman/docs/metacity/xprops_8h-source.html
+ typedef struct WMHints
+ {
+ unsigned long flags;
+ unsigned long functions;
+ unsigned long decorations;
+ long inputMode;
+ unsigned long status;
+ } Hints;
+
+ #define MWM_DECOR_ALL (1L << 0)
+ #define MWM_DECOR_BORDER (1L << 1)
+ #define MWM_DECOR_RESIZEH (1L << 2)
+ #define MWM_DECOR_TITLE (1L << 3)
+ #define MWM_DECOR_MENU (1L << 4)
+ #define MWM_DECOR_MINIMIZE (1L << 5)
+ #define MWM_DECOR_MAXIMIZE (1L << 6)
+
+ Atom property = XInternAtom(Disp, "_MOTIF_WM_HINTS", true);
+
+ Hints hints;
+ hints.flags = 2; // We only want to specify decoration.
+
+ if (show)
+ {
+ hints.decorations = MWM_DECOR_BORDER | MWM_DECOR_TITLE | MWM_DECOR_MENU | MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE;
+ }
+ else
+ {
+ // Remove all window border items.
+ hints.decorations = 0;
+ }
+
+ XChangeProperty(Disp,Win,property,property,32,PropModeReplace,(unsigned char *)&hints,5);
+}
+
+int PlatformCore::IndexOf(Render::DisplayId id)
+{
+ int numScreens = GetDisplayCount();
+ for (int i = 0; i < numScreens; i++)
+ {
+ if (GetDisplay(i).MonitorName == id.MonitorName)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+bool PlatformCore::SetFullscreen(const Render::RendererParams& rp, int fullscreen)
+{
+ if (fullscreen == pRender->GetParams().Fullscreen)
+ return false;
+
+ // Consume any X Configure Notify event. We will wait for a configure
+ // notify event after modifying our window.
+ XEvent report;
+ long eventMask = StructureNotifyMask | SubstructureNotifyMask;
+ while (XCheckWindowEvent(Disp, Win, eventMask, &report));
+
+ int displayIndex = IndexOf(rp.Display);
+ if (pRender->GetParams().Fullscreen == Render::Display_Window)
+ {
+ // Save the original window size and position so we can restore later.
+
+ XWindowAttributes xwa;
+ XGetWindowAttributes(Disp, Win, &xwa);
+ int x, y;
+ Window unused;
+ XTranslateCoordinates(Disp, Win, DefaultRootWindow(Disp), xwa.x, xwa.y, &x, &y, &unused);
+
+ StartVP.w = xwa.width;//Width;
+ StartVP.h = xwa.height;//Height;
+ StartVP.x = x;
+ StartVP.y = y;
+ }
+ else if (pRender->GetParams().Fullscreen == Render::Display_Fullscreen)
+ {
+ {
+ XEvent xev;
+ memset(&xev, 0, sizeof(xev));
+
+ xev.type = ClientMessage;
+ xev.xclient.window = Win;
+ xev.xclient.message_type = XInternAtom( Disp, "_NET_WM_STATE", False);
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = 0;
+ xev.xclient.data.l[1] = XInternAtom( Disp, "_NET_WM_STATE_FULLSCREEN", False);
+ xev.xclient.data.l[2] = 0;
+
+ XSendEvent( Disp, DefaultRootWindow( Disp ), False, SubstructureNotifyMask, &xev);
+ }
+
+ XWindowChanges wc;
+ wc.width = StartVP.w;
+ wc.height = StartVP.h;
+ wc.x = StartVP.x;
+ wc.y = StartVP.y;
+
+ XConfigureWindow(Disp, Win, CWWidth | CWHeight | CWX | CWY, &wc);
+
+ showWindowDecorations(false);
+ }
+
+ if (fullscreen == Render::Display_FakeFullscreen)
+ {
+ // Transitioning from windowed to fake fullscreen.
+ int xOffset;
+ int yOffset;
+
+ if (!determineScreenOffset(displayIndex, &xOffset, &yOffset))
+ {
+ return false;
+ }
+
+ showWindowDecorations(false);
+
+ XMoveWindow(Disp, Win, xOffset, yOffset);
+ XMapRaised(Disp, Win);
+ }
+ else if (fullscreen == Render::Display_Window)
+ {
+ // Transitioning from fake fullscreen to windowed.
+ showWindowDecorations(true);
+
+ XMoveWindow(Disp, Win, StartVP.x, StartVP.y);
+ XMapRaised(Disp, Win);
+ }
+ else if (fullscreen == Render::Display_Fullscreen)
+ {
+ // Obtain display information so that we can make and informed
+ // decision about display modes.
+ XDisplayInfo displayInfo = getXDisplayInfo(rp.Display);
+
+ XRRScreenResources* screen = XRRGetScreenResources(Disp, DefaultRootWindow(Disp));
+ XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(Disp, screen, displayInfo.crtc);
+ XRROutputInfo* outputInfo = XRRGetOutputInfo(Disp, screen, displayInfo.output);
+
+ int xOffset;
+ int yOffset;
+
+ if (!determineScreenOffset(displayIndex, &xOffset, &yOffset))
+ return false;
+
+ // We should probably always be fullscreen if we don't have a WM.
+ if (!HasWM)
+ {
+ // Determine if we are entering fullscreen on a rift device.
+ char deviceID[32];
+ OVR_sprintf(deviceID, 32, "OVR%04d-%d",
+ displayInfo.product, displayInfo.crtc);
+
+ LinuxDeviceScreen devScreen = SDKWindow::findDevScreenForDevID(deviceID);
+ if (devScreen.isValid())
+ {
+ XMoveResizeWindow(Disp, Win,
+ devScreen.offsetX, devScreen.offsetY,
+ devScreen.width, devScreen.height);
+ }
+ }
+
+ showWindowDecorations(false);
+
+ XWindowChanges wc;
+ wc.x = xOffset;
+ wc.y = yOffset;
+ wc.stack_mode = 0;
+
+ XConfigureWindow(Disp, Win, CWX | CWY | CWStackMode, &wc);
+
+ // Make the window fullscreen in the window manager.
+ // If we are using override redirect, or are on a separate screen
+ // with no WM, the following code will have no effect.
+ {
+ XEvent xev;
+ memset(&xev, 0, sizeof(xev));
+
+ xev.type = ClientMessage;
+ xev.xclient.window = Win;
+ xev.xclient.message_type = XInternAtom( Disp, "_NET_WM_STATE", False);
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = 1;
+ xev.xclient.data.l[1] = XInternAtom( Disp, "_NET_WM_STATE_FULLSCREEN", False);
+ xev.xclient.data.l[2] = 0;
+
+ XSendEvent( Disp, DefaultRootWindow( Disp ), False, SubstructureNotifyMask, &xev);
+ }
+ }
+
+ XMapRaised(Disp, Win);
+ XFlush(Disp);
+
+ OvrPlatform::PlatformCore::SetFullscreen(rp, fullscreen);
+
+ // Wait until we receive a configure notify event. If the WM redirected our
+ // structure, then WM should synthesize a configure notify event even
+ // if there was no change in the window layout.
+ XWindowEvent(Disp, Win, eventMask, &report);
+
+ // Process the resize event.
+ processEvent(report);
+
+ return true;
+}
+
+int PlatformCore::GetDisplayCount()
+{
+ XRRScreenResources* screen = XRRGetScreenResources(Disp, Win);
+ RROutput primaryOutput = XRRGetOutputPrimary(Disp, DefaultRootWindow(Disp));
+
+ // Iterate through displays and ensure that they have valid outputs.
+ int numDisplays = 0;
+ for (int i = 0; i < screen->ncrtc; ++i)
+ {
+ XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(Disp, screen, screen->crtcs[i]);
+ if (0 == crtcInfo->noutput)
+ {
+ XRRFreeCrtcInfo(crtcInfo);
+ continue;
+ }
+
+ RROutput output = crtcInfo->outputs[0];
+ for (int ii = 0; ii < crtcInfo->noutput; ++ii)
+ {
+ if (primaryOutput == crtcInfo->outputs[ii])
+ {
+ output = primaryOutput;
+ break;
+ }
+ }
+
+ XRROutputInfo* outputInfo = XRRGetOutputInfo(Disp, screen, output);
+ if (RR_Connected != outputInfo->connection)
+ {
+ XRRFreeOutputInfo(outputInfo);
+ XRRFreeCrtcInfo(crtcInfo);
+ continue;
+ }
+
+ if (RR_Connected == outputInfo->connection)
+ {
+ ++numDisplays;
+ }
+
+ XRRFreeOutputInfo(outputInfo);
+ XRRFreeCrtcInfo(crtcInfo);
+ }
+
+ XRRFreeScreenResources(screen);
+ return numDisplays;
+}
+
+Render::DisplayId PlatformCore::GetDisplay(int screenId)
+{
+ char device_id[32] = "";
+
+ RROutput primaryOutput = XRRGetOutputPrimary(Disp, DefaultRootWindow(Disp));
+ XRRScreenResources* screen = XRRGetScreenResources(Disp, Win);
+
+ int screenIndex = 0;
+ for (int i = 0; i < screen->ncrtc; ++i)
+ {
+ XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(Disp, screen, screen->crtcs[i]);
+
+ if (0 == crtcInfo->noutput)
+ {
+ XRRFreeCrtcInfo(crtcInfo);
+ // We intentionally do not increment screenIndex. We do not
+ // consider this a valid display.
+ continue;
+ }
+
+ RROutput output = crtcInfo->outputs[0];
+ for (int ii = 0; ii < crtcInfo->noutput; ++ii)
+ {
+ if (primaryOutput == crtcInfo->outputs[ii])
+ {
+ output = primaryOutput;
+ break;
+ }
+ }
+
+ XRROutputInfo* outputInfo = XRRGetOutputInfo(Disp, screen, output);
+ if (RR_Connected != outputInfo->connection)
+ {
+ XRRFreeOutputInfo(outputInfo);
+ XRRFreeCrtcInfo(crtcInfo);
+ continue;
+ }
+
+ MonitorInfo * mi = read_edid_data(Disp, output);
+ if (mi == NULL)
+ {
+ ++screenIndex;
+ XRRFreeOutputInfo(outputInfo);
+ XRRFreeCrtcInfo(crtcInfo);
+ continue;
+ }
+
+ if (screenIndex == screenId)
+ {
+ OVR_sprintf(device_id, 32, "%s%04d-%d",
+ mi->manufacturer_code, mi->product_code,
+ screen->crtcs[i]);
+
+ XRRFreeOutputInfo(outputInfo);
+ XRRFreeCrtcInfo(crtcInfo);
+
+ delete mi;
+ break;
+ }
+
+ XRRFreeOutputInfo(outputInfo);
+ XRRFreeCrtcInfo(crtcInfo);
+
+ delete mi;
+ ++screenIndex;
+ }
+ XRRFreeScreenResources(screen);
+
+ return Render::DisplayId(device_id);
+}
+
+XDisplayInfo PlatformCore::getXDisplayInfo(Render::DisplayId id)
+{
+ int screenId = IndexOf(id);
+
+ // Locate and return XDisplayInfo
+ RROutput primaryOutput = XRRGetOutputPrimary(Disp, DefaultRootWindow(Disp));
+ XRRScreenResources* screen = XRRGetScreenResources(Disp, Win);
+
+ int screenIndex = 0;
+ for (int i = 0; i < screen->ncrtc; ++i)
+ {
+ XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(Disp, screen, screen->crtcs[i]);
+
+ if (0 == crtcInfo->noutput)
+ {
+ XRRFreeCrtcInfo(crtcInfo);
+ // We intentionally do not increment screenIndex. We do not
+ // consider this a valid display.
+ continue;
+ }
+
+ RROutput output = crtcInfo->outputs[0];
+ for (int ii = 0; ii < crtcInfo->noutput; ++ii)
+ {
+ if (primaryOutput == crtcInfo->outputs[ii])
+ {
+ output = primaryOutput;
+ break;
+ }
+ }
+
+ XRROutputInfo* outputInfo = XRRGetOutputInfo(Disp, screen, output);
+ if (RR_Connected != outputInfo->connection)
+ {
+ XRRFreeOutputInfo(outputInfo);
+ XRRFreeCrtcInfo(crtcInfo);
+ continue;
+ }
+
+ MonitorInfo * mi = read_edid_data(Disp, output);
+ if (mi == NULL)
+ {
+ ++screenIndex;
+ XRRFreeOutputInfo(outputInfo);
+ XRRFreeCrtcInfo(crtcInfo);
+ continue;
+ }
+
+ if (screenIndex == screenId)
+ {
+ XDisplayInfo dinfo;
+ dinfo.valid = true;
+ dinfo.output = output;
+ dinfo.crtc = outputInfo->crtc;
+ dinfo.product= mi->product_code;
+
+ XRRFreeOutputInfo(outputInfo);
+ XRRFreeCrtcInfo(crtcInfo);
+
+ return dinfo;
+ }
+
+ XRRFreeOutputInfo(outputInfo);
+ XRRFreeCrtcInfo(crtcInfo);
+
+ delete mi;
+ ++screenIndex;
+ }
+ XRRFreeScreenResources(screen);
+
+ return XDisplayInfo();
+}
+
+RenderDevice* PlatformCore::SetupGraphics(const SetupGraphicsDeviceSet& setupGraphicsDesc,
+ const char* type, const Render::RendererParams& rp)
+{
+ const SetupGraphicsDeviceSet* setupDesc = setupGraphicsDesc.PickSetupDevice(type);
+ OVR_ASSERT(setupDesc);
+
+ pRender = *setupDesc->pCreateDevice(rp, this);
+ if (pRender)
+ pRender->SetWindowSize(Width, Height);
+
+ return pRender.GetPtr();
+}
+
+void PlatformCore::showCursor(bool show)
+{
+ if (show)
+ {
+ XUndefineCursor(Disp, Win);
+ }
+ else
+ {
+ XDefineCursor(Disp, Win, InvisibleCursor);
+ }
+}
+
+}}
+
+// GL
+namespace Render { namespace GL { namespace Linux {
+
+
+// To do: We can do away with this function by using our GLEContext class, which already tracks extensions.
+static bool IsGLXExtensionSupported(const char* extension, _XDisplay* pDisplay, int screen = 0)
+{
+ // const char* extensionList = glXQueryExtensionsString(pDisplay, screen);
+ const char* extensionList = glXGetClientString(pDisplay, GLX_EXTENSIONS); // This is returning more extensions than glXQueryExtensionsString does.
+
+ if(extensionList)
+ {
+ const char* start = extensionList;
+ const char* where;
+
+ static bool printed = false;
+ if(!printed)
+ {
+ OVR_DEBUG_LOG(("glX extensions: %s", extensionList));
+ printed = true;
+ }
+
+ while((where = (char*)strstr(start, extension)) != NULL)
+ {
+ if (where)
+ {
+ const char* term = (where + strlen(extension));
+
+ if ((where == start) || (where[-1] == ' '))
+ {
+ if ((term[0] == ' ') || (term[0] == '\0'))
+ return true;
+ }
+
+ start = term;
+ }
+ }
+ }
+
+ return false;
+}
+
+ovrRenderAPIConfig RenderDevice::Get_ovrRenderAPIConfig() const
+{
+ static ovrGLConfig cfg;
+ cfg.OGL.Header.API = ovrRenderAPI_OpenGL;
+ cfg.OGL.Header.RTSize = Sizei(WindowWidth, WindowHeight);
+ cfg.OGL.Header.Multisample = Params.Multisample;
+ cfg.OGL.Win = Win;
+ cfg.OGL.Disp = Disp;
+ return cfg.Config;
+}
+
+Render::RenderDevice* RenderDevice::CreateDevice(const RendererParams& rp, void* oswnd)
+{
+ OvrPlatform::Linux::PlatformCore* PC = (OvrPlatform::Linux::PlatformCore*)oswnd;
+
+ GLXContext context = glXCreateContext(PC->Disp, PC->Vis, 0, GL_TRUE);
+
+ if (!context)
+ return NULL;
+
+ if (!glXMakeCurrent(PC->Disp, PC->Win, context))
+ {
+ glXDestroyContext(PC->Disp, context);
+ return NULL;
+ }
+
+ XMapRaised(PC->Disp, PC->Win);
+
+ InitGLExtensions();
+
+ XSync(PC->Disp, 0);
+
+ for (XWindowAttributes attribute; attribute.map_state != IsViewable; )
+ XGetWindowAttributes(PC->Disp,PC->Win,&attribute);
+
+ XSetInputFocus(PC->Disp, PC->Win, RevertToParent, CurrentTime);
+
+ return new Render::GL::Linux::RenderDevice(rp, PC->Disp, PC->Win, context);
+}
+
+void RenderDevice::Present(bool withVsync)
+{
+ unsigned swapInterval = (withVsync) ? 1 : 0;
+ GLuint currentSwapInterval = 0;
+ glXQueryDrawable(Disp, Win, GLX_SWAP_INTERVAL_EXT, &currentSwapInterval);
+ if (currentSwapInterval != swapInterval)
+ glXSwapIntervalEXT(Disp, Win, swapInterval);
+
+ glXSwapBuffers(Disp, Win);
+}
+
+void RenderDevice::Shutdown()
+{
+ if (Context)
+ {
+ glXMakeCurrent(Disp, 0, NULL);
+ glXDestroyContext(Disp, Context);
+ Context = NULL;
+ Win = 0;
+ }
+}
+
+}}}}
+
+OVR::OvrPlatform::Linux::PlatformCore* gPlatform;
+
+static void handleSigInt(int sig)
+{
+ signal(SIGINT, SIG_IGN);
+ gPlatform->Exit(0);
+}
+
+int main(int argc, const char* argv[])
+{
+ using namespace OVR;
+ using namespace OVR::OvrPlatform;
+
+ // SigInt for capturing Ctrl-c.
+ if (signal(SIGINT, handleSigInt) == SIG_ERR)
+ {
+ fprintf(stderr, "Failed setting SIGINT handler\n");
+ return EXIT_FAILURE;
+ }
+
+ // CreateApplication must be the first call since it does OVR::System::Initialize.
+ Application* app = Application::CreateApplication();
+ gPlatform = new Linux::PlatformCore(app);
+ // The platform attached to an app will be deleted by DestroyApplication.
+ app->SetPlatformCore(gPlatform);
+
+ int exitCode = app->OnStartup(argc, argv);
+ if (!exitCode)
+ exitCode = gPlatform->Run();
+
+ // No OVR functions involving memory are allowed after this.
+ Application::DestroyApplication(app);
+ app = 0;
+
+ return exitCode;
+}
diff --git a/Samples/CommonSrc/Platform/Linux_Platform.h b/Samples/CommonSrc/Platform/Linux_Platform.h
new file mode 100644
index 0000000..b8c5ca3
--- /dev/null
+++ b/Samples/CommonSrc/Platform/Linux_Platform.h
@@ -0,0 +1,149 @@
+/************************************************************************************
+
+Filename : Platform_Linux.h
+Content : Linux (X11) implementation of Platform app infrastructure
+Created : September 6, 2012
+Authors : Andrew Reisse
+
+Copyright : Copyright 2012 Oculus VR, LLC. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_Platform_Linux_h
+#define OVR_Platform_Linux_h
+
+#include "Platform.h"
+#include "../Render/Render_GL_Device.h"
+
+#include <GL/glx.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+namespace OVR { namespace Render {
+ class RenderDevice;
+}}
+
+namespace OVR { namespace OvrPlatform { namespace Linux {
+
+struct XDisplayInfo;
+
+class PlatformCore : public OvrPlatform::PlatformCore
+{
+ Recti StartVP;
+ bool HasWM;
+
+ int IndexOf(Render::DisplayId id);
+ XDisplayInfo getXDisplayInfo(Render::DisplayId id);
+
+public:
+ _XDisplay* Disp;
+ XVisualInfo* Vis;
+ Window Win;
+
+ bool Quit;
+ int ExitCode;
+ int Width, Height;
+
+ MouseMode MMode;
+ Cursor InvisibleCursor;
+
+ enum
+ {
+ WM_PROTOCOLS,
+ WM_DELETE_WINDOW,
+ NumAtoms
+ };
+ Atom Atoms[NumAtoms];
+
+ void processEvent(XEvent& event);
+
+ Render::RenderDevice* SetupGraphics_GL(const Render::RendererParams& rp);
+
+ void showCursor(bool show);
+ bool determineScreenOffset(int screenId, int* screenOffsetX, int* screenOffsetY);
+ void showWindowDecorations(bool show);
+
+public:
+ PlatformCore(Application* app);
+ ~PlatformCore();
+
+ void* SetupWindow(int w, int h);
+ void Exit(int exitcode) { Quit = 1; ExitCode = exitcode; }
+
+ RenderDevice* SetupGraphics(const SetupGraphicsDeviceSet& setupGraphicsDesc,
+ const char* gtype, const Render::RendererParams& rp);
+
+ void SetMouseMode(MouseMode mm);
+ void GetWindowSize(int* w, int* h) const;
+
+ void SetWindowTitle(const char*title);
+
+ void ShowWindow(bool show);
+ void DestroyWindow();
+ bool SetFullscreen(const Render::RendererParams& rp, int fullscreen);
+ int GetDisplayCount();
+ Render::DisplayId GetDisplay(int screen);
+
+ int Run();
+};
+
+}}
+namespace Render { namespace GL { namespace Linux {
+
+class RenderDevice : public Render::GL::RenderDevice
+{
+ _XDisplay* Disp;
+ Window Win;
+ GLXContext Context;
+
+public:
+ RenderDevice(const Render::RendererParams& p, _XDisplay* disp, Window w, GLXContext gl)
+ : GL::RenderDevice(p), Disp(disp), Win(w), Context(gl) {}
+
+ virtual void Shutdown();
+ virtual void Present(bool withVsync);
+ virtual ovrRenderAPIConfig Get_ovrRenderAPIConfig() const;
+
+ // oswnd = Linux::PlatformCore*
+ static Render::RenderDevice* CreateDevice(const RendererParams& rp, void* oswnd);
+};
+
+}}}}
+
+
+// OVR_PLATFORM_APP_ARGS specifies the Application class to use for startup,
+// providing it with startup arguments.
+#define OVR_PLATFORM_APP_ARGS(AppClass, args) \
+ OVR::OvrPlatform::Application* OVR::OvrPlatform::Application::CreateApplication() \
+ { OVR::System::Init(OVR::Log::ConfigureDefaultLog(OVR::LogMask_All)); \
+ return new AppClass args; } \
+ void OVR::OvrPlatform::Application::DestroyApplication(OVR::OvrPlatform::Application* app) \
+ { OVR::OvrPlatform::PlatformCore* platform = app->pPlatform; \
+ delete app; delete platform; OVR::System::Destroy(); };
+
+// OVR_PLATFORM_APP_ARGS specifies the Application startup class with no args.
+#define OVR_PLATFORM_APP(AppClass) OVR_PLATFORM_APP_ARGS(AppClass, ())
+
+#define OVR_PLATFORM_APP_ARGS_WITH_LOG(AppClass, LogClass, args) \
+ OVR::OvrPlatform::Application* OVR::OvrPlatform::Application::CreateApplication() \
+ { static LogClass log; OVR::System::Init(&log); \
+ return new AppClass args; } \
+ void OVR::OvrPlatform::Application::DestroyApplication(OVR::OvrPlatform::Application* app) \
+ { OVR::OvrPlatform::PlatformCore* platform = app->pPlatform; \
+ delete app; delete platform; OVR::System::Destroy(); };
+
+#define OVR_PLATFORM_APP_WITH_LOG(AppClass,LogClass) OVR_PLATFORM_APP_ARGS_WITH_LOG(AppClass,LogClass, ())
+
+#endif
diff --git a/Samples/CommonSrc/Platform/OSX_Platform.mm b/Samples/CommonSrc/Platform/OSX_Platform.mm
index dfc29f8..4955337 100644
--- a/Samples/CommonSrc/Platform/OSX_Platform.mm
+++ b/Samples/CommonSrc/Platform/OSX_Platform.mm
@@ -1,553 +1,1108 @@
-/************************************************************************************
-
-Filename : OSX_Platform.mm
-Content :
-Created :
-Authors :
-
-Copyright : Copyright 2012 Oculus, Inc. All Rights reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-************************************************************************************/
-
-#import "../Platform/OSX_PlatformObjc.h"
-
-using namespace OVR;
-using namespace OVR::OvrPlatform;
-
-@implementation OVRApp
-
-- (void)dealloc
-{
- [super dealloc];
-}
-
-- (void)run
-{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- _running = YES;
- OVR::OvrPlatform::Application* app;
- {
- using namespace OVR;
- using namespace OVR::OvrPlatform;
-
- // CreateApplication must be the first call since it does OVR::System::Initialize.
- app = Application::CreateApplication();
- OSX::PlatformCore* platform = new OSX::PlatformCore(app, self);
- // The platform attached to an app will be deleted by DestroyApplication.
- app->SetPlatformCore(platform);
-
- [self setApp:app];
- [self setPlatform:platform];
-
- const char* argv[] = {"OVRApp"};
- int exitCode = app->OnStartup(1, argv);
- if (exitCode)
- {
- Application::DestroyApplication(app);
- exit(exitCode);
- }
- }
- [self finishLaunching];
- [pool drain];
-
- while ([self isRunning])
- {
- pool = [[NSAutoreleasePool alloc] init];
- NSEvent* event = [self nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES];
- if (event)
- {
- [self sendEvent:event];
- }
- _App->OnIdle();
- [pool drain];
- }
- OVR::OvrPlatform::Application::DestroyApplication(app);
-}
-
-@end
-
-static int KeyMap[][2] =
-{
- { NSDeleteFunctionKey, OVR::Key_Delete },
- { '\t', OVR::Key_Tab },
- { '\n', OVR::Key_Return },
- { NSPauseFunctionKey, OVR::Key_Pause },
- { 27, OVR::Key_Escape },
- { 127, OVR::Key_Backspace },
- { ' ', OVR::Key_Space },
- { NSPageUpFunctionKey, OVR::Key_PageUp },
- { NSPageDownFunctionKey, OVR::Key_PageDown },
- { NSNextFunctionKey, OVR::Key_PageDown },
- { NSEndFunctionKey, OVR::Key_End },
- { NSHomeFunctionKey, OVR::Key_Home },
- { NSLeftArrowFunctionKey, OVR::Key_Left },
- { NSUpArrowFunctionKey, OVR::Key_Up },
- { NSRightArrowFunctionKey, OVR::Key_Right },
- { NSDownArrowFunctionKey, OVR::Key_Down },
- { NSInsertFunctionKey, OVR::Key_Insert },
- { NSDeleteFunctionKey, OVR::Key_Delete },
- { NSHelpFunctionKey, OVR::Key_Insert },
-};
-
-
-static KeyCode MapToKeyCode(wchar_t vk)
-{
- unsigned key = Key_None;
-
- if ((vk >= 'a') && (vk <= 'z'))
- {
- key = vk - 'a' + Key_A;
- }
- else if ((vk >= ' ') && (vk <= '~'))
- {
- key = vk;
- }
- else if ((vk >= '0') && (vk <= '9'))
- {
- key = vk - '0' + Key_Num0;
- }
- else if ((vk >= NSF1FunctionKey) && (vk <= NSF15FunctionKey))
- {
- key = vk - NSF1FunctionKey + Key_F1;
- }
- else
- {
- for (unsigned i = 0; i< (sizeof(KeyMap) / sizeof(KeyMap[1])); i++)
- {
- if (vk == KeyMap[i][0])
- {
- key = KeyMap[i][1];
- break;
- }
- }
- }
-
- return (KeyCode)key;
-}
-
-static int MapModifiers(unsigned long xmod)
-{
- int mod = 0;
- if (xmod & NSShiftKeyMask)
- mod |= OVR::OvrPlatform::Mod_Shift;
- if (xmod & NSCommandKeyMask)
- mod |= OVR::OvrPlatform::Mod_Control;
- if (xmod & NSAlternateKeyMask)
- mod |= OVR::OvrPlatform::Mod_Alt;
- if (xmod & NSControlKeyMask)
- mod |= OVR::OvrPlatform::Mod_Meta;
- return mod;
-}
-
-@implementation OVRView
-
--(BOOL) acceptsFirstResponder
-{
- return YES;
-}
--(BOOL) acceptsFirstMouse:(NSEvent *)ev
-{
- return YES;
-}
-
-+(CGDirectDisplayID) displayFromScreen:(NSScreen *)s
-{
- NSNumber* didref = (NSNumber*)[[s deviceDescription] objectForKey:@"NSScreenNumber"];
- CGDirectDisplayID disp = (CGDirectDisplayID)[didref longValue];
- return disp;
-}
-
--(void) warpMouseToCenter
-{
- NSPoint w;
- w.x = _Platform->Width/2.0f;
- w.y = _Platform->Height/2.0f;
- w = [[self window] convertBaseToScreen:w];
- CGDirectDisplayID disp = [OVRView displayFromScreen:[[self window] screen]];
- CGPoint p = {w.x, CGDisplayPixelsHigh(disp)-w.y};
- CGDisplayMoveCursorToPoint(disp, p);
-}
-
-static bool LookupKey(NSEvent* ev, wchar_t& ch, OVR::KeyCode& key, unsigned& mods)
-{
- NSString* chars = [ev charactersIgnoringModifiers];
- if ([chars length] == 0)
- return false;
- ch = [chars characterAtIndex:0];
- mods = MapModifiers([ev modifierFlags]);
-
- // check for Cmd+Latin Letter
- NSString* modchars = [ev characters];
- if ([modchars length])
- {
- wchar_t modch = [modchars characterAtIndex:0];
- if (modch >= 'a' && modch <= 'z')
- ch = modch;
- }
- key = MapToKeyCode(ch);
- return true;
-}
-
--(void) keyDown:(NSEvent*)ev
-{
- OVR::KeyCode key;
- unsigned mods;
- wchar_t ch;
- if (!LookupKey(ev, ch, key, mods))
- return;
- if (key == Key_Escape && _Platform->MMode == Mouse_Relative)
- {
- [self warpMouseToCenter];
- CGAssociateMouseAndMouseCursorPosition(true);
- [NSCursor unhide];
- _Platform->MMode = Mouse_RelativeEscaped;
- }
- _App->OnKey(key, ch, true, mods);
-}
--(void) keyUp:(NSEvent*)ev
-{
- OVR::KeyCode key;
- unsigned mods;
- wchar_t ch;
- if (LookupKey(ev, ch, key, mods))
- _App->OnKey(key, ch, false, mods);
-}
-
-static const OVR::KeyCode ModifierKeys[] = {OVR::Key_None, OVR::Key_Shift, OVR::Key_Control, OVR::Key_Alt, OVR::Key_Meta};
-
--(void)flagsChanged:(NSEvent *)ev
-{
- unsigned long cmods = [ev modifierFlags];
- if ((cmods & 0xffff0000) != _Modifiers)
- {
- uint32_t mods = MapModifiers(cmods);
- for (int i = 1; i <= 4; i++)
- {
- unsigned long m = (1 << (16+i));
- if ((cmods & m) != (_Modifiers & m))
- {
- if (cmods & m)
- _App->OnKey(ModifierKeys[i], 0, true, mods);
- else
- _App->OnKey(ModifierKeys[i], 0, false, mods);
- }
- }
- _Modifiers = cmods & 0xffff0000;
- }
-}
-
--(void)ProcessMouse:(NSEvent*)ev
-{
- switch ([ev type])
- {
- case NSLeftMouseDragged:
- case NSRightMouseDragged:
- case NSOtherMouseDragged:
- case NSMouseMoved:
- {
- if (_Platform->MMode == OVR::OvrPlatform::Mouse_Relative)
- {
- int dx = [ev deltaX];
- int dy = [ev deltaY];
-
- if (dx != 0 || dy != 0)
- {
- _App->OnMouseMove(dx, dy, Mod_MouseRelative|MapModifiers([ev modifierFlags]));
- [self warpMouseToCenter];
- }
- }
- else
- {
- NSPoint p = [ev locationInWindow];
- _App->OnMouseMove(p.x, p.y, MapModifiers([ev modifierFlags]));
- }
- }
- break;
- case NSLeftMouseDown:
- case NSRightMouseDown:
- case NSOtherMouseDown:
- break;
- }
-}
-
--(void) mouseMoved:(NSEvent*)ev
-{
- [self ProcessMouse:ev];
-}
--(void) mouseDragged:(NSEvent*)ev
-{
- [self ProcessMouse:ev];
-}
--(void) mouseDown:(NSEvent*)ev
-{
- if (_Platform->MMode == Mouse_RelativeEscaped)
- {
- [self warpMouseToCenter];
- CGAssociateMouseAndMouseCursorPosition(false);
- [NSCursor hide];
- _Platform->MMode = Mouse_Relative;
- }
-}
-
-//-(void)
-
--(id) initWithFrame:(NSRect)frameRect
-{
- NSOpenGLPixelFormatAttribute attr[] =
- {
-// NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
-// NSOpenGLPFAWindow,
- NSOpenGLPFADoubleBuffer,
- NSOpenGLPFADepthSize, 24,
- nil
- };
-
- NSOpenGLPixelFormat *pf = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attr] autorelease];
-
- self = [super initWithFrame:frameRect pixelFormat:pf];
- GLint swap = 0;
- [[self openGLContext] setValues:&swap forParameter:NSOpenGLCPSwapInterval];
- //[self setWantsBestResolutionOpenGLSurface:YES];
- return self;
-}
-
--(void) reshape
-{
- NSRect bounds = [self bounds];
- _App->OnResize(bounds.size.width, bounds.size.height);
-
- _Platform->Width = bounds.size.width;
- _Platform->Height = bounds.size.height;
-
- if (_Platform->GetRenderer())
- _Platform->GetRenderer()->SetWindowSize(bounds.size.width, bounds.size.height);
-}
-
--(BOOL)windowShouldClose:(id)sender
-{
- if (_Platform)
- _Platform->Exit(0);
- else
- exit(0);
- return 1;
-}
-
-@end
-
-namespace OVR { namespace OvrPlatform { namespace OSX {
-
-PlatformCore::PlatformCore(Application* app, void* nsapp)
- : OvrPlatform::PlatformCore(app), NsApp(nsapp), Win(NULL), View(NULL), Quit(0), MMode(Mouse_Normal)
-{
- pGamepadManager = *new OSX::GamepadManager();
-}
-PlatformCore::~PlatformCore()
-{
-}
-
-void PlatformCore::Exit(int exitcode)
-{
- OVRApp* nsApp = (OVRApp*)NsApp;
- [nsApp stop:nil];
-}
-
-String PlatformCore::GetContentDirectory() const
-{
- NSBundle* bundle = [NSBundle mainBundle];
- if (bundle)
- return String([[bundle bundlePath] UTF8String]) + "/Contents/Resources";
- else
- return ".";
-}
-
-
-void PlatformCore::SetMouseMode(MouseMode mm)
-{
- if (mm == MMode)
- return;
-
- if (Win)
- {
- if (mm == Mouse_Relative)
- {
- [NSCursor hide];
- [(OVRView*)View warpMouseToCenter];
- CGAssociateMouseAndMouseCursorPosition(false);
- }
- else
- {
- if (MMode == Mouse_Relative)
- {
- CGAssociateMouseAndMouseCursorPosition(true);
- [NSCursor unhide];
- [(OVRView*)View warpMouseToCenter];
- }
- }
- }
- MMode = mm;
-}
-
-
-void PlatformCore::GetWindowSize(int* w, int* h) const
-{
- *w = Width;
- *h = Height;
-}
-
-void* PlatformCore::SetupWindow(int w, int h)
-{
- NSRect winrect;
- winrect.origin.x = 0;
- winrect.origin.y = 1000;
- winrect.size.width = w;
- winrect.size.height = h;
- NSWindow* win = [[NSWindow alloc] initWithContentRect:winrect styleMask:NSTitledWindowMask|NSClosableWindowMask backing:NSBackingStoreBuffered defer:NO];
-
- OVRView* view = [[OVRView alloc] initWithFrame:winrect];
- [view setPlatform:this];
- [win setContentView:view];
- [win setAcceptsMouseMovedEvents:YES];
- [win setDelegate:view];
- [view setApp:pApp];
- Win = win;
- View = view;
- return (void*)[win windowNumber];
-}
-
-void PlatformCore::SetWindowTitle(const char* title)
-{
- [((NSWindow*)Win) setTitle:[[NSString alloc] initWithBytes:title length:strlen(title) encoding:NSUTF8StringEncoding]];
-}
-
-void PlatformCore::ShowWindow(bool show)
-{
- if (show)
- [((NSWindow*)Win) makeKeyAndOrderFront:nil];
- else
- [((NSWindow*)Win) orderOut:nil];
-}
-
-void PlatformCore::DestroyWindow()
-{
- [((NSWindow*)Win) close];
- Win = NULL;
-}
-
-RenderDevice* PlatformCore::SetupGraphics(const SetupGraphicsDeviceSet& setupGraphicsDesc,
- const char* type, const Render::RendererParams& rp)
-{
- const SetupGraphicsDeviceSet* setupDesc = setupGraphicsDesc.PickSetupDevice(type);
- OVR_ASSERT(setupDesc);
-
- pRender = *setupDesc->pCreateDevice(rp, this);
- if (pRender)
- pRender->SetWindowSize(Width, Height);
-
- return pRender.GetPtr();
-}
-
-int PlatformCore::GetDisplayCount()
-{
- return (int)[[NSScreen screens] count];
-}
-
-Render::DisplayId PlatformCore::GetDisplay(int i)
-{
- NSScreen* s = (NSScreen*)[[NSScreen screens] objectAtIndex:i];
- return Render::DisplayId([OVRView displayFromScreen:s]);
-}
-
-bool PlatformCore::SetFullscreen(const Render::RendererParams& rp, int fullscreen)
-{
- if (fullscreen == Render::Display_Window)
- [(OVRView*)View exitFullScreenModeWithOptions:nil];
- else
- {
- NSScreen* usescreen = [NSScreen mainScreen];
- NSArray* screens = [NSScreen screens];
- for (int i = 0; i < [screens count]; i++)
- {
- NSScreen* s = (NSScreen*)[screens objectAtIndex:i];
- CGDirectDisplayID disp = [OVRView displayFromScreen:s];
-
- if (disp == rp.Display.CgDisplayId)
- usescreen = s;
- }
-
- [(OVRView*)View enterFullScreenMode:usescreen withOptions:nil];
- [(NSWindow*)Win setInitialFirstResponder:(OVRView*)View];
- [(NSWindow*)Win makeFirstResponder:(OVRView*)View];
- }
-
- if (pRender)
- pRender->SetFullscreen((Render::DisplayMode)fullscreen);
- return 1;
-}
-
-}}
-// GL
-namespace Render { namespace GL { namespace OSX {
-
-ovrRenderAPIConfig RenderDevice::Get_ovrRenderAPIConfig() const
-{
- ovrRenderAPIConfig result = ovrRenderAPIConfig();
- result.Header.API = ovrRenderAPI_OpenGL;
- result.Header.RTSize = Sizei(WindowWidth, WindowHeight);
- result.Header.Multisample = Params.Multisample;
- return result;
-}
-
-Render::RenderDevice* RenderDevice::CreateDevice(const RendererParams& rp, void* oswnd)
-{
- OvrPlatform::OSX::PlatformCore* PC = (OvrPlatform::OSX::PlatformCore*)oswnd;
-
- OVRView* view = (OVRView*)PC->View;
- NSOpenGLContext *context = [view openGLContext];
- if (!context)
- return NULL;
-
- [context makeCurrentContext];
- [((NSWindow*)PC->Win) makeKeyAndOrderFront:nil];
-
- return new Render::GL::OSX::RenderDevice(rp, context);
-}
-
-void RenderDevice::Present(bool useVsync)
-{
- NSOpenGLContext *context = (NSOpenGLContext*)Context;
- [context flushBuffer];
-}
-
-void RenderDevice::Shutdown()
-{
- Context = NULL;
-}
-
-bool RenderDevice::SetFullscreen(DisplayMode fullscreen)
-{
- Params.Fullscreen = fullscreen;
- return 1;
-}
-
-}}}}
-
-
-int main(int argc, char *argv[])
-{
- NSApplication* nsapp = [OVRApp sharedApplication];
- [nsapp run];
- return 0;
-}
-
+/************************************************************************************
+
+
+
+Filename : OSX_Platform.mm
+
+Content :
+
+Created :
+
+Authors :
+
+
+
+Copyright : Copyright 2012 Oculus, Inc. All Rights reserved.
+
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+
+
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+
+
+Unless required by applicable law or agreed to in writing, software
+
+distributed under the License is distributed on an "AS IS" BASIS,
+
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+
+limitations under the License.
+
+
+
+************************************************************************************/
+
+
+
+#import "../Platform/OSX_PlatformObjc.h"
+
+
+
+using namespace OVR;
+
+using namespace OVR::OvrPlatform;
+
+
+
+@implementation OVRApp
+
+
+
+- (void)dealloc
+
+{
+
+ [super dealloc];
+
+}
+
+
+
+- (void)run
+
+{
+
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ _running = YES;
+
+ OVR::OvrPlatform::Application* app;
+
+ {
+
+ using namespace OVR;
+
+ using namespace OVR::OvrPlatform;
+
+
+
+ // CreateApplication must be the first call since it does OVR::System::Initialize.
+
+ app = Application::CreateApplication();
+
+ OSX::PlatformCore* platform = new OSX::PlatformCore(app, self);
+
+ // The platform attached to an app will be deleted by DestroyApplication.
+
+ app->SetPlatformCore(platform);
+
+
+
+ [self setApp:app];
+
+ [self setPlatform:platform];
+
+
+
+ const char* argv[] = {"OVRApp"};
+
+ int exitCode = app->OnStartup(1, argv);
+
+ if (exitCode)
+
+ {
+
+ Application::DestroyApplication(app);
+
+ exit(exitCode);
+
+ }
+
+ }
+
+ [self finishLaunching];
+
+ [pool drain];
+
+
+
+ while ([self isRunning])
+
+ {
+
+ pool = [[NSAutoreleasePool alloc] init];
+
+ NSEvent* event = [self nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES];
+
+ if (event)
+
+ {
+
+ [self sendEvent:event];
+
+ }
+
+ _App->OnIdle();
+
+ [pool drain];
+
+ }
+
+ OVR::OvrPlatform::Application::DestroyApplication(app);
+
+}
+
+
+
+@end
+
+
+
+static int KeyMap[][2] =
+
+{
+
+ { NSDeleteFunctionKey, OVR::Key_Delete },
+
+ { '\t', OVR::Key_Tab },
+
+ { '\n', OVR::Key_Return },
+
+ { NSPauseFunctionKey, OVR::Key_Pause },
+
+ { 27, OVR::Key_Escape },
+
+ { 127, OVR::Key_Backspace },
+
+ { ' ', OVR::Key_Space },
+
+ { NSPageUpFunctionKey, OVR::Key_PageUp },
+
+ { NSPageDownFunctionKey, OVR::Key_PageDown },
+
+ { NSNextFunctionKey, OVR::Key_PageDown },
+
+ { NSEndFunctionKey, OVR::Key_End },
+
+ { NSHomeFunctionKey, OVR::Key_Home },
+
+ { NSLeftArrowFunctionKey, OVR::Key_Left },
+
+ { NSUpArrowFunctionKey, OVR::Key_Up },
+
+ { NSRightArrowFunctionKey, OVR::Key_Right },
+
+ { NSDownArrowFunctionKey, OVR::Key_Down },
+
+ { NSInsertFunctionKey, OVR::Key_Insert },
+
+ { NSDeleteFunctionKey, OVR::Key_Delete },
+
+ { NSHelpFunctionKey, OVR::Key_Insert },
+
+};
+
+
+
+
+
+static KeyCode MapToKeyCode(wchar_t vk)
+
+{
+
+ unsigned key = Key_None;
+
+
+
+ if ((vk >= 'a') && (vk <= 'z'))
+
+ {
+
+ key = vk - 'a' + Key_A;
+
+ }
+
+ else if ((vk >= ' ') && (vk <= '~'))
+
+ {
+
+ key = vk;
+
+ }
+
+ else if ((vk >= '0') && (vk <= '9'))
+
+ {
+
+ key = vk - '0' + Key_Num0;
+
+ }
+
+ else if ((vk >= NSF1FunctionKey) && (vk <= NSF15FunctionKey))
+
+ {
+
+ key = vk - NSF1FunctionKey + Key_F1;
+
+ }
+
+ else
+
+ {
+
+ for (unsigned i = 0; i< (sizeof(KeyMap) / sizeof(KeyMap[1])); i++)
+
+ {
+
+ if (vk == KeyMap[i][0])
+
+ {
+
+ key = KeyMap[i][1];
+
+ break;
+
+ }
+
+ }
+
+ }
+
+
+
+ return (KeyCode)key;
+
+}
+
+
+
+static int MapModifiers(unsigned long xmod)
+
+{
+
+ int mod = 0;
+
+ if (xmod & NSShiftKeyMask)
+
+ mod |= OVR::OvrPlatform::Mod_Shift;
+
+ if (xmod & NSCommandKeyMask)
+
+ mod |= OVR::OvrPlatform::Mod_Control;
+
+ if (xmod & NSAlternateKeyMask)
+
+ mod |= OVR::OvrPlatform::Mod_Alt;
+
+ if (xmod & NSControlKeyMask)
+
+ mod |= OVR::OvrPlatform::Mod_Meta;
+
+ return mod;
+
+}
+
+
+
+@implementation OVRView
+
+
+
+-(BOOL) acceptsFirstResponder
+
+{
+
+ return YES;
+
+}
+
+-(BOOL) acceptsFirstMouse:(NSEvent *)ev
+
+{
+
+ return YES;
+
+}
+
+
+
++(CGDirectDisplayID) displayFromScreen:(NSScreen *)s
+
+{
+
+ NSNumber* didref = (NSNumber*)[[s deviceDescription] objectForKey:@"NSScreenNumber"];
+
+ CGDirectDisplayID disp = (CGDirectDisplayID)[didref longValue];
+
+ return disp;
+
+}
+
+
+
+-(void) warpMouseToCenter
+
+{
+
+ NSPoint w;
+
+ w.x = _Platform->Width/2.0f;
+
+ w.y = _Platform->Height/2.0f;
+
+ w = [[self window] convertBaseToScreen:w];
+
+ CGDirectDisplayID disp = [OVRView displayFromScreen:[[self window] screen]];
+
+ CGPoint p = {w.x, CGDisplayPixelsHigh(disp)-w.y};
+
+ CGDisplayMoveCursorToPoint(disp, p);
+
+}
+
+
+
+static bool LookupKey(NSEvent* ev, wchar_t& ch, OVR::KeyCode& key, unsigned& mods)
+
+{
+
+ NSString* chars = [ev charactersIgnoringModifiers];
+
+ if ([chars length] == 0)
+
+ return false;
+
+ ch = [chars characterAtIndex:0];
+
+ mods = MapModifiers([ev modifierFlags]);
+
+
+
+ // check for Cmd+Latin Letter
+
+ NSString* modchars = [ev characters];
+
+ if ([modchars length])
+
+ {
+
+ wchar_t modch = [modchars characterAtIndex:0];
+
+ if (modch >= 'a' && modch <= 'z')
+
+ ch = modch;
+
+ }
+
+ key = MapToKeyCode(ch);
+
+ return true;
+
+}
+
+
+
+-(void) keyDown:(NSEvent*)ev
+
+{
+
+ OVR::KeyCode key;
+
+ unsigned mods;
+
+ wchar_t ch;
+
+ if (!LookupKey(ev, ch, key, mods))
+
+ return;
+
+ if (key == Key_Escape && _Platform->MMode == Mouse_Relative)
+
+ {
+
+ [self warpMouseToCenter];
+
+ CGAssociateMouseAndMouseCursorPosition(true);
+
+ [NSCursor unhide];
+
+ _Platform->MMode = Mouse_RelativeEscaped;
+
+ }
+
+ _App->OnKey(key, ch, true, mods);
+
+}
+
+-(void) keyUp:(NSEvent*)ev
+
+{
+
+ OVR::KeyCode key;
+
+ unsigned mods;
+
+ wchar_t ch;
+
+ if (LookupKey(ev, ch, key, mods))
+
+ _App->OnKey(key, ch, false, mods);
+
+}
+
+
+
+static const OVR::KeyCode ModifierKeys[] = {OVR::Key_None, OVR::Key_Shift, OVR::Key_Control, OVR::Key_Alt, OVR::Key_Meta};
+
+
+
+-(void)flagsChanged:(NSEvent *)ev
+
+{
+
+ unsigned long cmods = [ev modifierFlags];
+
+ if ((cmods & 0xffff0000) != _Modifiers)
+
+ {
+
+ uint32_t mods = MapModifiers(cmods);
+
+ for (int i = 1; i <= 4; i++)
+
+ {
+
+ unsigned long m = (1 << (16+i));
+
+ if ((cmods & m) != (_Modifiers & m))
+
+ {
+
+ if (cmods & m)
+
+ _App->OnKey(ModifierKeys[i], 0, true, mods);
+
+ else
+
+ _App->OnKey(ModifierKeys[i], 0, false, mods);
+
+ }
+
+ }
+
+ _Modifiers = cmods & 0xffff0000;
+
+ }
+
+}
+
+
+
+-(void)ProcessMouse:(NSEvent*)ev
+
+{
+
+ switch ([ev type])
+
+ {
+
+ case NSLeftMouseDragged:
+
+ case NSRightMouseDragged:
+
+ case NSOtherMouseDragged:
+
+ case NSMouseMoved:
+
+ {
+
+ if (_Platform->MMode == OVR::OvrPlatform::Mouse_Relative)
+
+ {
+
+ int dx = [ev deltaX];
+
+ int dy = [ev deltaY];
+
+
+
+ if (dx != 0 || dy != 0)
+
+ {
+
+ _App->OnMouseMove(dx, dy, Mod_MouseRelative|MapModifiers([ev modifierFlags]));
+
+ [self warpMouseToCenter];
+
+ }
+
+ }
+
+ else
+
+ {
+
+ NSPoint p = [ev locationInWindow];
+
+ _App->OnMouseMove(p.x, p.y, MapModifiers([ev modifierFlags]));
+
+ }
+
+ }
+
+ break;
+
+ case NSLeftMouseDown:
+
+ case NSRightMouseDown:
+
+ case NSOtherMouseDown:
+
+ break;
+
+ }
+
+}
+
+
+
+-(void) mouseMoved:(NSEvent*)ev
+
+{
+
+ [self ProcessMouse:ev];
+
+}
+
+-(void) mouseDragged:(NSEvent*)ev
+
+{
+
+ [self ProcessMouse:ev];
+
+}
+
+-(void) mouseDown:(NSEvent*)ev
+
+{
+
+ if (_Platform->MMode == Mouse_RelativeEscaped)
+
+ {
+
+ [self warpMouseToCenter];
+
+ CGAssociateMouseAndMouseCursorPosition(false);
+
+ [NSCursor hide];
+
+ _Platform->MMode = Mouse_Relative;
+
+ }
+
+}
+
+
+
+//-(void)
+
+
+
+-(id) initWithFrame:(NSRect)frameRect
+
+{
+
+ NSOpenGLPixelFormatAttribute attr[] =
+
+ {
+
+// NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
+
+// NSOpenGLPFAWindow,
+
+ NSOpenGLPFADoubleBuffer,
+
+ NSOpenGLPFADepthSize, 24,
+
+ 0
+
+ };
+
+
+
+ NSOpenGLPixelFormat *pf = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attr] autorelease];
+
+
+
+ self = [super initWithFrame:frameRect pixelFormat:pf];
+
+ GLint swap = 0;
+
+ [[self openGLContext] setValues:&swap forParameter:NSOpenGLCPSwapInterval];
+
+ //[self setWantsBestResolutionOpenGLSurface:YES];
+
+ return self;
+
+}
+
+
+
+-(void) reshape
+
+{
+
+ NSRect bounds = [self bounds];
+
+ _App->OnResize(bounds.size.width, bounds.size.height);
+
+
+
+ _Platform->Width = bounds.size.width;
+
+ _Platform->Height = bounds.size.height;
+
+
+
+ if (_Platform->GetRenderer())
+
+ _Platform->GetRenderer()->SetWindowSize(bounds.size.width, bounds.size.height);
+
+}
+
+
+
+-(BOOL)windowShouldClose:(id)sender
+
+{
+
+ if (_Platform)
+
+ _Platform->Exit(0);
+
+ else
+
+ exit(0);
+
+ return 1;
+
+}
+
+
+
+@end
+
+
+
+namespace OVR { namespace OvrPlatform { namespace OSX {
+
+
+
+PlatformCore::PlatformCore(Application* app, void* nsapp)
+
+ : OvrPlatform::PlatformCore(app), NsApp(nsapp), Win(NULL), View(NULL), Quit(0), MMode(Mouse_Normal)
+
+{
+
+ pGamepadManager = *new OSX::GamepadManager();
+
+}
+
+PlatformCore::~PlatformCore()
+
+{
+
+}
+
+
+
+void PlatformCore::Exit(int exitcode)
+
+{
+
+ OVRApp* nsApp = (OVRApp*)NsApp;
+
+ [nsApp stop:nil];
+
+}
+
+
+
+String PlatformCore::GetContentDirectory() const
+
+{
+
+ NSBundle* bundle = [NSBundle mainBundle];
+
+ if (bundle)
+
+ return String([[bundle bundlePath] UTF8String]) + "/Contents/Resources";
+
+ else
+
+ return ".";
+
+}
+
+
+
+
+
+void PlatformCore::SetMouseMode(MouseMode mm)
+
+{
+
+ if (mm == MMode)
+
+ return;
+
+
+
+ if (Win)
+
+ {
+
+ if (mm == Mouse_Relative)
+
+ {
+
+ [NSCursor hide];
+
+ [(OVRView*)View warpMouseToCenter];
+
+ CGAssociateMouseAndMouseCursorPosition(false);
+
+ }
+
+ else
+
+ {
+
+ if (MMode == Mouse_Relative)
+
+ {
+
+ CGAssociateMouseAndMouseCursorPosition(true);
+
+ [NSCursor unhide];
+
+ [(OVRView*)View warpMouseToCenter];
+
+ }
+
+ }
+
+ }
+
+ MMode = mm;
+
+}
+
+
+
+
+
+void PlatformCore::GetWindowSize(int* w, int* h) const
+
+{
+
+ *w = Width;
+
+ *h = Height;
+
+}
+
+
+
+void* PlatformCore::SetupWindow(int w, int h)
+
+{
+
+ NSRect winrect;
+
+ winrect.origin.x = 0;
+
+ winrect.origin.y = 1000;
+
+ winrect.size.width = w;
+
+ winrect.size.height = h;
+
+ NSWindow* win = [[NSWindow alloc] initWithContentRect:winrect styleMask:NSTitledWindowMask|NSClosableWindowMask backing:NSBackingStoreBuffered defer:NO];
+
+
+
+ OVRView* view = [[OVRView alloc] initWithFrame:winrect];
+
+ [view setPlatform:this];
+
+ [win setContentView:view];
+
+ [win setAcceptsMouseMovedEvents:YES];
+
+ [win setDelegate:view];
+
+ [view setApp:pApp];
+
+ Win = win;
+
+ View = view;
+
+ return (void*)[win windowNumber];
+
+}
+
+
+
+void PlatformCore::SetWindowTitle(const char* title)
+
+{
+
+ NSString* nsTitle = [[[NSString alloc] initWithBytes:title length:strlen(title) encoding:NSUTF8StringEncoding] autorelease];
+
+ [((NSWindow*)Win) setTitle:nsTitle];
+
+}
+
+
+
+void PlatformCore::ShowWindow(bool show)
+
+{
+
+ if (show)
+
+ [((NSWindow*)Win) makeKeyAndOrderFront:nil];
+
+ else
+
+ [((NSWindow*)Win) orderOut:nil];
+
+}
+
+
+
+void PlatformCore::DestroyWindow()
+
+{
+
+ [((NSWindow*)Win) close];
+
+ Win = NULL;
+
+}
+
+
+
+RenderDevice* PlatformCore::SetupGraphics(const SetupGraphicsDeviceSet& setupGraphicsDesc,
+
+ const char* type, const Render::RendererParams& rp)
+
+{
+
+ const SetupGraphicsDeviceSet* setupDesc = setupGraphicsDesc.PickSetupDevice(type);
+
+ OVR_ASSERT(setupDesc && setupDesc->pCreateDevice);
+
+
+
+ pRender = *setupDesc->pCreateDevice(rp, this);
+
+ if (pRender)
+
+ pRender->SetWindowSize(Width, Height);
+
+
+
+ return pRender.GetPtr();
+
+}
+
+
+
+int PlatformCore::GetDisplayCount()
+
+{
+
+ return (int)[[NSScreen screens] count];
+
+}
+
+
+
+Render::DisplayId PlatformCore::GetDisplay(int i)
+
+{
+
+ NSScreen* s = (NSScreen*)[[NSScreen screens] objectAtIndex:i];
+
+ return Render::DisplayId([OVRView displayFromScreen:s]);
+
+}
+
+
+
+bool PlatformCore::SetFullscreen(const Render::RendererParams& rp, int fullscreen)
+
+{
+
+ if (fullscreen == Render::Display_Window)
+
+ [(OVRView*)View exitFullScreenModeWithOptions:nil];
+
+ else
+
+ {
+
+ NSScreen* usescreen = [NSScreen mainScreen];
+
+ NSArray* screens = [NSScreen screens];
+
+ for (int i = 0; i < [screens count]; i++)
+
+ {
+
+ NSScreen* s = (NSScreen*)[screens objectAtIndex:i];
+
+ CGDirectDisplayID disp = [OVRView displayFromScreen:s];
+
+
+
+ if (disp == rp.Display.CgDisplayId)
+
+ usescreen = s;
+
+ }
+
+
+
+ [(OVRView*)View enterFullScreenMode:usescreen withOptions:nil];
+
+ [(NSWindow*)Win setInitialFirstResponder:(OVRView*)View];
+
+ [(NSWindow*)Win makeFirstResponder:(OVRView*)View];
+
+ }
+
+
+
+ if (pRender)
+
+ pRender->SetFullscreen((Render::DisplayMode)fullscreen);
+
+ return 1;
+
+}
+
+
+
+}}
+
+// GL
+
+namespace Render { namespace GL { namespace OSX {
+
+
+
+ovrRenderAPIConfig RenderDevice::Get_ovrRenderAPIConfig() const
+
+{
+
+ ovrRenderAPIConfig result = ovrRenderAPIConfig();
+
+ result.Header.API = ovrRenderAPI_OpenGL;
+
+ result.Header.RTSize = Sizei(WindowWidth, WindowHeight);
+
+ result.Header.Multisample = Params.Multisample;
+
+ return result;
+
+}
+
+
+
+Render::RenderDevice* RenderDevice::CreateDevice(const RendererParams& rp, void* oswnd)
+
+{
+
+ OvrPlatform::OSX::PlatformCore* PC = (OvrPlatform::OSX::PlatformCore*)oswnd;
+
+
+
+ OVRView* view = (OVRView*)PC->View;
+
+ NSOpenGLContext *context = [view openGLContext];
+
+ if (!context)
+
+ return NULL;
+
+
+
+ [context makeCurrentContext];
+
+ [((NSWindow*)PC->Win) makeKeyAndOrderFront:nil];
+
+
+
+ return new Render::GL::OSX::RenderDevice(rp, context);
+
+}
+
+
+
+void RenderDevice::Present(bool useVsync)
+
+{
+
+ NSOpenGLContext *context = (NSOpenGLContext*)Context;
+
+ [context flushBuffer];
+
+}
+
+
+
+void RenderDevice::Shutdown()
+
+{
+
+ Context = NULL;
+
+}
+
+
+
+bool RenderDevice::SetFullscreen(DisplayMode fullscreen)
+
+{
+
+ Params.Fullscreen = fullscreen;
+
+ return 1;
+
+}
+
+
+
+}}}}
+
+
+
+
+
+int main(int argc, char *argv[])
+
+{
+
+ NSApplication* nsapp = [OVRApp sharedApplication];
+
+ [nsapp run];
+
+ return 0;
+
+}
+
+
+
diff --git a/Samples/CommonSrc/Platform/Platform.cpp b/Samples/CommonSrc/Platform/Platform.cpp
index 40d7842..3b4f206 100644
--- a/Samples/CommonSrc/Platform/Platform.cpp
+++ b/Samples/CommonSrc/Platform/Platform.cpp
@@ -5,7 +5,7 @@ Content : Platform-independent app framework for Oculus samples
Created : September 6, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/Samples/CommonSrc/Platform/Platform.h b/Samples/CommonSrc/Platform/Platform.h
index e9325a7..2eeb4df 100644
--- a/Samples/CommonSrc/Platform/Platform.h
+++ b/Samples/CommonSrc/Platform/Platform.h
@@ -5,7 +5,7 @@ Content : Platform-independent app and rendering framework for Oculus samp
Created : September 6, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/Samples/CommonSrc/Platform/Platform_Default.h b/Samples/CommonSrc/Platform/Platform_Default.h
index 420b088..0ce02ad 100644
--- a/Samples/CommonSrc/Platform/Platform_Default.h
+++ b/Samples/CommonSrc/Platform/Platform_Default.h
@@ -5,7 +5,7 @@ Content : Default Platform class and RenderDevice selection file
Created : October 4, 2012
Authors :
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/Samples/CommonSrc/Platform/Win32_Gamepad.cpp b/Samples/CommonSrc/Platform/Win32_Gamepad.cpp
index 5186773..d10c4b1 100644
--- a/Samples/CommonSrc/Platform/Win32_Gamepad.cpp
+++ b/Samples/CommonSrc/Platform/Win32_Gamepad.cpp
@@ -5,7 +5,7 @@ Content : Win32 implementation of Platform app infrastructure
Created : May 6, 2013
Authors : Lee Cooper
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -23,9 +23,17 @@ limitations under the License.
#include "Win32_Gamepad.h"
+
+OVR_DISABLE_MSVC_WARNING(28159) // C28159: GetTickCount: consider using another function instead.
+
+
namespace OVR { namespace OvrPlatform { namespace Win32 {
-GamepadManager::GamepadManager()
+GamepadManager::GamepadManager() :
+ //hXInputModule(NULL),
+ pXInputGetState(NULL),
+ LastPadPacketNo(0xffffffff),
+ NextTryTime(0)
{
hXInputModule = ::LoadLibraryA("Xinput9_1_0.dll");
if (hXInputModule)
@@ -73,29 +81,45 @@ bool GamepadManager::GetGamepadState(uint32_t index, GamepadState* pState)
if (pXInputGetState)
{
- XINPUT_STATE xis;
-
- if (pXInputGetState(0, &xis))
- return false;
-
- if (xis.dwPacketNumber == LastPadPacketNo)
- return false;
-
- // State changed.
- pState->Buttons = xis.Gamepad.wButtons; // Currently matches Xinput
- pState->LT = GamepadTrigger(xis.Gamepad.bLeftTrigger);
- pState->RT = GamepadTrigger(xis.Gamepad.bRightTrigger);
- pState->LX = GamepadStick(xis.Gamepad.sThumbLX);
- pState->LY = GamepadStick(xis.Gamepad.sThumbLY);
- pState->RX = GamepadStick(xis.Gamepad.sThumbRX);
- pState->RY = GamepadStick(xis.Gamepad.sThumbRY);
-
- LastPadPacketNo = xis.dwPacketNumber;
-
- return true;
+ if((NextTryTime == 0) || (GetTickCount() >= NextTryTime)) // If the device is known to be present or if it's time to try testing for it again...
+ {
+ XINPUT_STATE xis;
+ DWORD dwResult = pXInputGetState(0, &xis); // This function is expensive, including if there is no connected device.
+
+ if(dwResult == ERROR_SUCCESS)
+ {
+ if (xis.dwPacketNumber != LastPadPacketNo)
+ {
+ // State changed.
+ pState->Buttons = xis.Gamepad.wButtons; // Currently matches Xinput
+ pState->LT = GamepadTrigger(xis.Gamepad.bLeftTrigger);
+ pState->RT = GamepadTrigger(xis.Gamepad.bRightTrigger);
+ pState->LX = GamepadStick(xis.Gamepad.sThumbLX);
+ pState->LY = GamepadStick(xis.Gamepad.sThumbLY);
+ pState->RX = GamepadStick(xis.Gamepad.sThumbRX);
+ pState->RY = GamepadStick(xis.Gamepad.sThumbRY);
+
+ LastPadPacketNo = xis.dwPacketNumber;
+ NextTryTime = 0;
+
+ return true;
+ }
+ }
+ else if(dwResult == ERROR_DEVICE_NOT_CONNECTED)
+ {
+ // Don't bother wasting time on XInputGetState if one isn't connected, as it's very slow when one isn't connected.
+ // GetTickCount64 is available with Windows Vista+ and doesn't wrap around.
+ // GetTickCount wraps around every 49.7 days since the system started, but we don't need absolute time and it's OK
+ // if we have a false positive which would occur if NextTryTime is set to a value that has wrapped around to zero.
+ NextTryTime = GetTickCount() + 5000;
+ }
+ }
}
return false;
}
}}} // OVR::OvrPlatform::Win32
+
+OVR_RESTORE_MSVC_WARNING()
+
diff --git a/Samples/CommonSrc/Platform/Win32_Gamepad.h b/Samples/CommonSrc/Platform/Win32_Gamepad.h
index 6c80350..fc91413 100644
--- a/Samples/CommonSrc/Platform/Win32_Gamepad.h
+++ b/Samples/CommonSrc/Platform/Win32_Gamepad.h
@@ -5,7 +5,7 @@ Content : Win32 implementation of Gamepad functionality.
Created : May 6, 2013
Authors : Lee Cooper
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -49,7 +49,8 @@ private:
typedef DWORD (WINAPI *PFn_XInputGetState)(DWORD dwUserIndex, XINPUT_STATE* pState);
PFn_XInputGetState pXInputGetState;
- uint32_t LastPadPacketNo;
+ uint32_t LastPadPacketNo; // Used to prevent reading the same packet twice.
+ uint32_t NextTryTime; // If no device was found then we don't try to access it again until some later time.
};
}}}
diff --git a/Samples/CommonSrc/Platform/Win32_Platform.cpp b/Samples/CommonSrc/Platform/Win32_Platform.cpp
index a3e491d..6efd6aa 100644
--- a/Samples/CommonSrc/Platform/Win32_Platform.cpp
+++ b/Samples/CommonSrc/Platform/Win32_Platform.cpp
@@ -5,7 +5,7 @@ Content : Win32 implementation of Platform app infrastructure
Created : September 6, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -39,9 +39,11 @@ namespace OVR { namespace OvrPlatform { namespace Win32 {
PlatformCore::PlatformCore(Application* app, HINSTANCE hinst)
- : OvrPlatform::PlatformCore(app), hWnd(NULL), hInstance(hinst), Quit(0), MMode(Mouse_Normal),
- Cursor(0), Modifiers(0), WindowTitle("App")
+ : OvrPlatform::PlatformCore(app), hWnd(NULL), hInstance(hinst), Quit(false), ExitCode(0), Width(0), Height(0), MMode(Mouse_Normal),
+ /*WindowCenter,*/ Cursor(NULL), Modifiers(0), WindowTitle("App")
{
+ WindowCenter.x = 0;
+ WindowCenter.y = 0;
pGamepadManager = *new Win32::GamepadManager();
}
@@ -49,17 +51,24 @@ PlatformCore::~PlatformCore()
{
}
+static LPCWSTR WindowClassName = L"OVRPlatAppWindow";
+
void* PlatformCore::SetupWindow(int w, int h)
{
- WNDCLASS wc;
+ WNDCLASSW wc;
memset(&wc, 0, sizeof(wc));
- wc.lpszClassName = L"OVRAppWindow";
+ wc.lpszClassName = WindowClassName;
wc.style = CS_OWNDC;
wc.lpfnWndProc = systemWindowProc;
wc.cbWndExtra = sizeof(PlatformCore*);
wc.hbrBackground = (HBRUSH)::GetStockObject(BLACK_BRUSH);
- RegisterClass(&wc);
+ RegisterClassW(&wc);
+
+ Array<wchar_t> buffer;
+ intptr_t textLength = UTF8Util::GetLength(WindowTitle);
+ buffer.Resize(textLength + 1);
+ UTF8Util::DecodeString(&buffer[0], WindowTitle);
Width = w;
Height = h;
@@ -69,7 +78,7 @@ void* PlatformCore::SetupWindow(int w, int h)
winSize.bottom = Height;
AdjustWindowRect(&winSize, WS_OVERLAPPEDWINDOW, false);
// WS_CLIPCHILDREN is needed to support NotificationOverlay.
- hWnd = CreateWindowA("OVRAppWindow", WindowTitle.ToCStr(), WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN,
+ hWnd = CreateWindowW(WindowClassName, &buffer[0], WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
// 1950, 10,
winSize.right-winSize.left, winSize.bottom-winSize.top,
@@ -103,7 +112,7 @@ void PlatformCore::DestroyWindow()
// Release window resources.
::DestroyWindow(hWnd);
- UnregisterClass(L"OVRAppWindow", hInstance);
+ UnregisterClassW(WindowClassName, hInstance);
hWnd = 0;
Width = Height = 0;
@@ -477,7 +486,7 @@ struct MonitorSet
BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData)
{
MonitorSet* monitorSet = (MonitorSet*)dwData;
- if (monitorSet->MonitorCount > MonitorSet::MaxMonitors)
+ if (monitorSet->MonitorCount >= MonitorSet::MaxMonitors)
return FALSE;
monitorSet->Monitors[monitorSet->MonitorCount] = hMonitor;
@@ -594,19 +603,19 @@ NotificationOverlay::NotificationOverlay(PlatformCore* core, int fontHeightPixel
// Create a static, centered TextField of specified font size.
- hFont= CreateFont(fontHeightPixels, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET,
+ hFont= CreateFontA(fontHeightPixels, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
- DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, L"Arial");
+ DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial");
HDC dc = ::CreateCompatibleDC(0);
::SelectObject(dc, hFont);
TextSize.cx = TextSize.cy = 0;
- ::GetTextExtentPoint32(dc, &buffer[0], (int)textLength, &TextSize);
+ ::GetTextExtentPoint32W(dc, &buffer[0], (int)textLength, &TextSize);
::DeleteDC(dc);
int vpos = (YOffest > 0) ? YOffest : (pCore->Height + YOffest - (TextSize.cy + 7));
- hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("STATIC"),
+ hWnd = CreateWindowExW(WS_EX_CLIENTEDGE, L"STATIC",
&buffer[0], WS_CHILD|WS_VISIBLE|SS_CENTER|WS_CLIPSIBLINGS,
(core->Width-TextSize.cx+20)/2, vpos,
TextSize.cx+20, TextSize.cy + 7,
diff --git a/Samples/CommonSrc/Platform/Win32_Platform.h b/Samples/CommonSrc/Platform/Win32_Platform.h
index b21bd0d..03d8e4a 100644
--- a/Samples/CommonSrc/Platform/Win32_Platform.h
+++ b/Samples/CommonSrc/Platform/Win32_Platform.h
@@ -5,7 +5,7 @@ Content : Win32 implementation of Platform app infrastructure
Created : September 6, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/Samples/CommonSrc/Render/Render_D3D10_Device.cpp b/Samples/CommonSrc/Render/Render_D3D10_Device.cpp
index b5c0ca6..7bcac94 100644
--- a/Samples/CommonSrc/Render/Render_D3D10_Device.cpp
+++ b/Samples/CommonSrc/Render/Render_D3D10_Device.cpp
@@ -5,7 +5,7 @@ Content : Builds D3D10 renderer versions (to avoid duplication).
Created : September 10, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/Samples/CommonSrc/Render/Render_D3D10_Device.h b/Samples/CommonSrc/Render/Render_D3D10_Device.h
index ec06e51..fe74ed6 100644
--- a/Samples/CommonSrc/Render/Render_D3D10_Device.h
+++ b/Samples/CommonSrc/Render/Render_D3D10_Device.h
@@ -5,7 +5,7 @@ Content : Builds D3D10 renderer versions (to avoid duplication).
Created : September 10, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/Samples/CommonSrc/Render/Render_D3D11_Device.cpp b/Samples/CommonSrc/Render/Render_D3D11_Device.cpp
index 6ec7ed4..f25884f 100644
--- a/Samples/CommonSrc/Render/Render_D3D11_Device.cpp
+++ b/Samples/CommonSrc/Render/Render_D3D11_Device.cpp
@@ -5,7 +5,7 @@ Content : Builds D3D11 renderer versions (to avoid duplication).
Created : September 10, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/Samples/CommonSrc/Render/Render_D3D11_Device.h b/Samples/CommonSrc/Render/Render_D3D11_Device.h
index a243b16..89be286 100644
--- a/Samples/CommonSrc/Render/Render_D3D11_Device.h
+++ b/Samples/CommonSrc/Render/Render_D3D11_Device.h
@@ -5,7 +5,7 @@ Content : Builds D3D11 renderer versions (to avoid duplication).
Created : September 10, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/Samples/CommonSrc/Render/Render_D3D1X_Device.cpp b/Samples/CommonSrc/Render/Render_D3D1X_Device.cpp
index a904ee5..c40edf2 100644
--- a/Samples/CommonSrc/Render/Render_D3D1X_Device.cpp
+++ b/Samples/CommonSrc/Render/Render_D3D1X_Device.cpp
@@ -5,7 +5,7 @@ Content : RenderDevice implementation for D3DX10/11.
Created : September 10, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ limitations under the License.
#include "Render_D3D1X_Device.h"
#include "Util/Util_ImageWindow.h"
+#include "Kernel/OVR_Log.h"
#include "OVR_CAPI_D3D.h"
@@ -711,6 +712,7 @@ static void ReportCOMError(HRESULT hr, const char* file, int line)
}
else
{
+#ifdef _UNICODE
size_t len = wcslen(errMsg);
char* data = new char[len + 1];
size_t count = len;
@@ -720,8 +722,13 @@ static void ReportCOMError(HRESULT hr, const char* file, int line)
len = count;
}
data[len] = '\0';
+#else
+ const char* data = errMsg;
+#endif
LogError("{ERR-018w} [D3D] Error in %s on line %d : %s", file, line, data);
+#ifdef _UNICODE
delete[] data;
+#endif
}
OVR_ASSERT(false);
@@ -737,15 +744,55 @@ static void ReportCOMError(HRESULT hr, const char* file, int line)
#endif
-RenderDevice::RenderDevice(const RendererParams& p, HWND window)
-{
+
+RenderDevice::RenderDevice(const RendererParams& p, HWND window) :
+ DXGIFactory(),
+ Window(window),
+ Device(),
+ Context(),
+ SwapChain(),
+ Adapter(),
+ FullscreenOutput(),
+ FSDesktopX(-1),
+ FSDesktopY(-1),
+ PreFullscreenX(0),
+ PreFullscreenY(0),
+ PreFullscreenW(0),
+ PreFullscreenH(0),
+ BackBuffer(),
+ BackBufferRT(),
+ CurRenderTarget(),
+ CurDepthBuffer(),
+ Rasterizer(),
+ BlendState(),
+ //DepthStates[]
+ CurDepthState(),
+ ModelVertexIL(),
+ DistortionVertexIL(),
+ HeightmapVertexIL(),
+ //SamplerStates[]
+ StdUniforms(),
+ //UniformBuffers[];
+ //MaxTextureSet[];
+ //VertexShaders[];
+ //PixelShaders[];
+ //pStereoShaders[];
+ //CommonUniforms[];
+ ExtraShaders(),
+ DefaultFill(),
+ QuadVertexBuffer(),
+ DepthBuffers()
+{
+ memset(&D3DViewport, 0, sizeof(D3DViewport));
+ memset(MaxTextureSet, 0, sizeof(MaxTextureSet));
+
HRESULT hr;
RECT rc;
if (p.Resolution == Sizei(0))
{
GetClientRect(window, &rc);
- UINT width = rc.right - rc.left;
+ UINT width = rc.right - rc.left;
UINT height = rc.bottom - rc.top;
::OVR::Render::RenderDevice::SetWindowSize(width, height);
}
@@ -755,8 +802,6 @@ RenderDevice::RenderDevice(const RendererParams& p, HWND window)
::OVR::Render::RenderDevice::SetWindowSize(p.Resolution.w, p.Resolution.h);
}
- Window = window;
-
Params = p;
DXGIFactory = NULL;
hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&DXGIFactory.GetRawRef()));
@@ -820,7 +865,7 @@ RenderDevice::RenderDevice(const RendererParams& p, HWND window)
Context = NULL;
D3D_FEATURE_LEVEL featureLevel; // TODO: Limit certain features based on D3D feature level
hr = D3D11CreateDevice(Adapter, Adapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE,
- NULL, flags, NULL, 0, D3D1x_(SDK_VERSION),
+ NULL, flags /*| D3D11_CREATE_DEVICE_DEBUG*/, NULL, 0, D3D1x_(SDK_VERSION),
&Device.GetRawRef(), &featureLevel, &Context.GetRawRef());
#endif
if (FAILED(hr))
@@ -1126,7 +1171,7 @@ bool RenderDevice::RecreateSwapChain()
scDesc.BufferCount = 1;
scDesc.BufferDesc.Width = WindowWidth;
scDesc.BufferDesc.Height = WindowHeight;
- scDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ scDesc.BufferDesc.Format = Params.SrgbBackBuffer ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
// Use default refresh rate; switching rate on CC prototype can cause screen lockup.
scDesc.BufferDesc.RefreshRate.Numerator = 0;
scDesc.BufferDesc.RefreshRate.Denominator = 1;
@@ -1526,7 +1571,7 @@ void* Buffer::Map(size_t start, size_t size, int flags)
#endif
}
-bool Buffer::Unmap(void *m)
+bool Buffer::Unmap(void* m)
{
OVR_UNUSED(m);
@@ -1661,27 +1706,35 @@ ID3D10Blob* RenderDevice::CompileShader(const char* profile, const char* src, co
}
-ShaderBase::ShaderBase(RenderDevice* r, ShaderStage stage)
- : Render::Shader(stage), Ren(r), UniformData(0)
+ShaderBase::ShaderBase(RenderDevice* r, ShaderStage stage) :
+ Render::Shader(stage),
+ Ren(r),
+ UniformData(NULL),
+ UniformsSize(-1)
{
}
+
ShaderBase::~ShaderBase()
{
if (UniformData)
{
OVR_FREE(UniformData);
+ UniformData = NULL;
}
}
bool ShaderBase::SetUniform(const char* name, int n, const float* v)
{
- for(unsigned i = 0; i < UniformInfo.GetSize(); i++)
- if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
+ for (int i = 0; i < UniformInfo.GetSizeI(); i++)
+ {
+ if (UniformInfo[i].Name == name)
{
memcpy(UniformData + UniformInfo[i].Offset, v, n * sizeof(float));
- return 1;
+ return true;
}
- return 0;
+ }
+
+ return false;
}
void ShaderBase::InitUniforms(ID3D10Blob* s)
@@ -1887,9 +1940,19 @@ ID3D1xSamplerState* RenderDevice::GetSamplerState(int sm)
return SamplerStates[sm];
}
-Texture::Texture(RenderDevice* ren, int fmt, int w, int h) : Ren(ren), Tex(NULL), TexSv(NULL), TexRtv(NULL), TexDsv(NULL), Width(w), Height(h)
+Texture::Texture(RenderDevice* ren, int fmt, int w, int h) :
+ Ren(ren),
+ Tex(NULL),
+ TexSv(NULL),
+ TexRtv(NULL),
+ TexDsv(NULL),
+ TexStaging(NULL),
+ Sampler(NULL),
+ Format(fmt),
+ Width(w),
+ Height(h),
+ Samples(0)
{
- OVR_UNUSED(fmt);
Sampler = Ren->GetSamplerState(0);
}
@@ -1956,21 +2019,23 @@ void RenderDevice::GenerateSubresourceData(
unsigned subresHeight = imageHeight;
unsigned numMips = effectiveMipCount;
+ unsigned bytesPerBlock = 0;
+ switch(format)
+ {
+ case DXGI_FORMAT_BC1_UNORM_SRGB: // fall thru
+ case DXGI_FORMAT_BC1_UNORM: bytesPerBlock = 8; break;
+
+ case DXGI_FORMAT_BC2_UNORM_SRGB: // fall thru
+ case DXGI_FORMAT_BC2_UNORM: bytesPerBlock = 16; break;
+
+ case DXGI_FORMAT_BC3_UNORM_SRGB: // fall thru
+ case DXGI_FORMAT_BC3_UNORM: bytesPerBlock = 16; break;
+
+ default: OVR_ASSERT(false);
+ }
+
for(unsigned i = 0; i < numMips; i++)
{
- unsigned bytesPerBlock = 0;
- if (format == DXGI_FORMAT_BC1_UNORM)
- {
- bytesPerBlock = 8;
- }
- else if (format == DXGI_FORMAT_BC2_UNORM)
- {
- bytesPerBlock = 16;
- }
- else if (format == DXGI_FORMAT_BC3_UNORM)
- {
- bytesPerBlock = 16;
- }
unsigned blockWidth = 0;
blockWidth = (subresWidth + 3) / 4;
@@ -2067,21 +2132,28 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo
imageDimUpperLimit = 1024;
}
- if (format == Texture_DXT1 || format == Texture_DXT3 || format == Texture_DXT5)
+ if ((format & Texture_TypeMask) == Texture_DXT1 ||
+ (format & Texture_TypeMask) == Texture_DXT3 ||
+ (format & Texture_TypeMask) == Texture_DXT5)
{
int convertedFormat;
- switch (format) {
- case Texture_DXT1:
- convertedFormat = DXGI_FORMAT_BC1_UNORM;
- break;
- case Texture_DXT3:
- convertedFormat = DXGI_FORMAT_BC2_UNORM;
- break;
- case Texture_DXT5:
- default:
- convertedFormat = DXGI_FORMAT_BC3_UNORM;
- break;
- }
+ if((format & Texture_TypeMask) == Texture_DXT1)
+ {
+ convertedFormat = (format & Texture_SRGB) ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
+ }
+ else if((format & Texture_TypeMask) == Texture_DXT3)
+ {
+ convertedFormat = (format & Texture_SRGB) ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
+ }
+ else if((format & Texture_TypeMask) == Texture_DXT5)
+ {
+ convertedFormat = (format & Texture_SRGB) ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
+ }
+ else
+ {
+ OVR_ASSERT(false); return NULL;
+ }
+
unsigned largestMipWidth = 0;
unsigned largestMipHeight = 0;
unsigned effectiveMipCount = mipcount;
@@ -2181,6 +2253,7 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo
d3dformat = createDepthSrv ? DXGI_FORMAT_R32_TYPELESS : DXGI_FORMAT_D32_FLOAT;
break;
default:
+ OVR_ASSERT(false);
return NULL;
}
@@ -2320,6 +2393,13 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo
// Rendering
+void RenderDevice::ResolveMsaa(OVR::Render::Texture* msaaTex, OVR::Render::Texture* outputTex)
+{
+ int isSrgb = ((Texture*)msaaTex)->Format & Texture_SRGB;
+
+ Context->ResolveSubresource(((Texture*)outputTex)->Tex, 0, ((Texture*)msaaTex)->Tex, 0, isSrgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM);
+}
+
void RenderDevice::BeginRendering()
{
Context->RSSetState(Rasterizer);
diff --git a/Samples/CommonSrc/Render/Render_D3D1X_Device.h b/Samples/CommonSrc/Render/Render_D3D1X_Device.h
index cac104e..63e8e67 100644
--- a/Samples/CommonSrc/Render/Render_D3D1X_Device.h
+++ b/Samples/CommonSrc/Render/Render_D3D1X_Device.h
@@ -5,7 +5,7 @@ Content : RenderDevice implementation header for D3DX10/11.
Created : September 10, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -117,6 +117,7 @@ typedef D3D11_QUERY_DESC D3D1x_QUERY_DESC;
class Buffer;
+
class ShaderBase : public Render::Shader
{
public:
@@ -127,7 +128,8 @@ public:
struct Uniform
{
String Name;
- int Offset, Size;
+ int Offset;
+ int Size;
};
Array<Uniform> UniformInfo;
@@ -141,6 +143,7 @@ public:
void UpdateBuffer(Buffer* b);
};
+
template<Render::ShaderStage SStage, class D3DShaderType>
class Shader : public ShaderBase
{
@@ -186,7 +189,13 @@ public:
bool Dynamic;
public:
- Buffer(RenderDevice* r) : Ren(r), Size(0), Use(0) {}
+ Buffer(RenderDevice* r) :
+ Ren(r),
+ Size(0),
+ Use(0),
+ Dynamic(false)
+ {
+ }
~Buffer();
ID3D1xBuffer* GetBuffer()
@@ -199,10 +208,11 @@ public:
return Size;
}
virtual void* Map(size_t start, size_t size, int flags = 0);
- virtual bool Unmap(void *m);
+ virtual bool Unmap(void* m);
virtual bool Data(int use, const void* buffer, size_t size);
};
+
class Texture : public Render::Texture
{
public:
@@ -215,6 +225,7 @@ public:
mutable Ptr<ID3D1xSamplerState> Sampler;
int Width, Height;
int Samples;
+ int Format;
Texture(RenderDevice* r, int fmt, int w, int h);
~Texture();
@@ -239,9 +250,9 @@ public:
virtual ovrTexture Get_ovrTexture();
virtual void* GetInternalImplementation();
-
};
+
class RenderDevice : public Render::RenderDevice
{
public:
@@ -302,7 +313,7 @@ public:
// to get the latest info about monitors (including just connected/
// disconnected ones). Note, SwapChain will be released in this case
// and it should be recreated.
- void UpdateMonitorOutputs(bool needRecreate = false);
+ void UpdateMonitorOutputs(bool needRecreate = false);
virtual void SetViewport(const Recti& vp);
virtual void SetWindowSize(int w, int h);
@@ -337,6 +348,8 @@ public:
Texture* GetDepthBuffer(int w, int h, int ms);
+ virtual void ResolveMsaa(OVR::Render::Texture* msaaTex, OVR::Render::Texture* outputTex) OVR_OVERRIDE;
+
virtual void BeginRendering();
virtual void SetRenderTarget(Render::Texture* color,
Render::Texture* depth = NULL, Render::Texture* stencil = NULL);
@@ -348,7 +361,7 @@ public:
ExtraShaders = s;
}
- // Overrident to apply proper blend state.
+ // Overridden to apply proper blend state.
virtual void FillRect(float left, float top, float right, float bottom, Color c, const Matrix4f* view=NULL);
virtual void FillGradientRect(float left, float top, float right, float bottom, Color col_top, Color col_btm, const Matrix4f* view);
virtual void RenderText(const struct Font* font, const char* str, float x, float y, float size, Color c, const Matrix4f* view=NULL);
@@ -377,6 +390,7 @@ public:
virtual void EndGpuEvent();
};
-}}}
+
+}}} // namespace OVR::Render::D3D1?
#endif
diff --git a/Samples/CommonSrc/Render/Render_Device.cpp b/Samples/CommonSrc/Render/Render_Device.cpp
index 94ff680..7b95713 100644
--- a/Samples/CommonSrc/Render/Render_Device.cpp
+++ b/Samples/CommonSrc/Render/Render_Device.cpp
@@ -5,7 +5,7 @@ Content : Platform renderer for simple scene graph - implementation
Created : September 6, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -1033,7 +1033,7 @@ namespace OVR { namespace Render {
pCurVert->TexG = pCurRawVert->TanEyeAnglesG;
pCurVert->TexB = pCurRawVert->TanEyeAnglesB;
// Convert [0.0f,1.0f] to [0,255]
- pCurVert->Col.R = (uint8_t)( floorf ( pCurRawVert->Shade * 255.999f ) );
+ pCurVert->Col.R = (uint8_t)( floorf ( Alg::Max ( pCurRawVert->Shade, 0.0f ) * 255.999f ) );
pCurVert->Col.G = pCurVert->Col.R;
pCurVert->Col.B = pCurVert->Col.R;
pCurVert->Col.A = (uint8_t)( floorf ( pCurRawVert->TimewarpLerp * 255.999f ) );
@@ -1171,8 +1171,8 @@ namespace OVR { namespace Render {
Matrix4f const &matRenderFromWorld = ( eyeNum == 0 ) ? matRenderFromWorldLeft : matRenderFromWorldRight;
const StereoEyeParams &stereoParams = ( eyeNum == 0 ) ? stereoParamsLeft : stereoParamsRight;
- Matrix4f matRenderFromNowStart = TimewarpComputePoseDelta ( matRenderFromWorld, matNowFromWorldStart, stereoParams.ViewAdjust );
- Matrix4f matRenderFromNowEnd = TimewarpComputePoseDelta ( matRenderFromWorld, matNowFromWorldEnd, stereoParams.ViewAdjust );
+ Matrix4f matRenderFromNowStart = TimewarpComputePoseDelta ( matRenderFromWorld, matNowFromWorldStart, stereoParams.HmdToEyeViewOffset );
+ Matrix4f matRenderFromNowEnd = TimewarpComputePoseDelta ( matRenderFromWorld, matNowFromWorldEnd, stereoParams.HmdToEyeViewOffset );
pPostProcessShader->SetUniform2f("EyeToSourceUVScale", stereoParams.EyeToSourceUV.Scale.x, stereoParams.EyeToSourceUV.Scale.y );
pPostProcessShader->SetUniform2f("EyeToSourceUVOffset", stereoParams.EyeToSourceUV.Offset.x, stereoParams.EyeToSourceUV.Offset.y );
@@ -1209,8 +1209,8 @@ namespace OVR { namespace Render {
Matrix4f const &matRenderFromWorld = ( eyeNum == 0 ) ? matRenderFromWorldLeft : matRenderFromWorldRight;
const StereoEyeParams &stereoParams = ( eyeNum == 0 ) ? stereoParamsLeft : stereoParamsRight;
- Matrix4f matRenderFromNowStart = TimewarpComputePoseDelta ( matRenderFromWorld, matNowFromWorldStart, stereoParams.ViewAdjust );
- Matrix4f matRenderFromNowEnd = TimewarpComputePoseDelta ( matRenderFromWorld, matNowFromWorldEnd, stereoParams.ViewAdjust );
+ Matrix4f matRenderFromNowStart = TimewarpComputePoseDelta ( matRenderFromWorld, matNowFromWorldStart, stereoParams.HmdToEyeViewOffset );
+ Matrix4f matRenderFromNowEnd = TimewarpComputePoseDelta ( matRenderFromWorld, matNowFromWorldEnd, stereoParams.HmdToEyeViewOffset );
pPostProcessShader->SetUniform2f("EyeToSourceUVScale", stereoParams.EyeToSourceUV.Scale.x, stereoParams.EyeToSourceUV.Scale.y );
pPostProcessShader->SetUniform2f("EyeToSourceUVOffset", stereoParams.EyeToSourceUV.Offset.x, stereoParams.EyeToSourceUV.Offset.y );
@@ -1313,8 +1313,8 @@ namespace OVR { namespace Render {
Matrix4f const &matRenderFromWorld = ( eyeNum == 0 ) ? matRenderFromWorldLeft : matRenderFromWorldRight;
- Matrix4f matRenderFromNowStart = TimewarpComputePoseDeltaPosition ( matRenderFromWorld, matNowFromWorldStart, stereoParams.ViewAdjust );
- Matrix4f matRenderFromNowEnd = TimewarpComputePoseDeltaPosition ( matRenderFromWorld, matNowFromWorldEnd, stereoParams.ViewAdjust );
+ Matrix4f matRenderFromNowStart = TimewarpComputePoseDeltaPosition ( matRenderFromWorld, matNowFromWorldStart, stereoParams.HmdToEyeViewOffset );
+ Matrix4f matRenderFromNowEnd = TimewarpComputePoseDeltaPosition ( matRenderFromWorld, matNowFromWorldEnd, stereoParams.HmdToEyeViewOffset );
pPostProcessHeightmapShader->SetUniform2f("EyeToSourceUVScale", stereoParams.EyeToSourceUV.Scale.x, stereoParams.EyeToSourceUV.Scale.y );
pPostProcessHeightmapShader->SetUniform2f("EyeToSourceUVOffset", stereoParams.EyeToSourceUV.Offset.x, stereoParams.EyeToSourceUV.Offset.y );
diff --git a/Samples/CommonSrc/Render/Render_Device.h b/Samples/CommonSrc/Render/Render_Device.h
index 1da49fe..5e9d270 100644
--- a/Samples/CommonSrc/Render/Render_Device.h
+++ b/Samples/CommonSrc/Render/Render_Device.h
@@ -5,7 +5,7 @@ Content : Platform renderer for simple scene graph
Created : September 6, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -517,7 +517,7 @@ public:
Ptr<Buffer> VertexBuffer;
Ptr<Buffer> IndexBuffer;
- Model(PrimitiveType t = Prim_Triangles) : Type(t), Fill(NULL), Visible(true) { }
+ Model(PrimitiveType t = Prim_Triangles) : Type(t), Fill(NULL), Visible(true), IsCollisionModel(false) { }
~Model() { }
virtual NodeType GetType() const { return Node_Model; }
@@ -753,13 +753,14 @@ struct DisplayId
struct RendererParams
{
int Multisample;
+ bool SrgbBackBuffer;
int Fullscreen;
DisplayId Display;
// Resolution of the rendering buffer used during creation.
// Allows buffer of different size then the widow if not zero.
Sizei Resolution;
- RendererParams(int ms = 1) : Multisample(ms), Fullscreen(0), Resolution(0) {}
+ RendererParams(int ms = 1) : Multisample(ms), SrgbBackBuffer(false), Fullscreen(0), Resolution(0) {}
bool IsDisplaySet() const
{
@@ -913,6 +914,9 @@ public:
// Finish scene.
virtual void FinishScene();
+ virtual void ResolveMsaa(Texture* msaaTex, Texture* outputTex)
+ { OVR_UNUSED2(msaaTex, outputTex); };
+
// Texture must have been created with Texture_RenderTarget. Use NULL for the default render target.
// NULL depth buffer means use an internal, temporary one.
virtual void SetRenderTarget(Texture* color, Texture* depth = NULL, Texture* stencil = NULL)
@@ -946,7 +950,7 @@ public:
// Returns width of text in same units as drawing. If strsize is not null, stores width and height.
// Can optionally return char-range selection rectangle.
- float MeasureText(const Font* font, const char* str, float size, float strsize[2] = NULL,
+ static float MeasureText(const Font* font, const char* str, float size, float strsize[2] = NULL,
const size_t charRange[2] = 0, Vector2f charRangeRect[2] = 0);
virtual void RenderText(const Font* font, const char* str, float x, float y, float size, Color c, const Matrix4f* view = NULL);
diff --git a/Samples/CommonSrc/Render/Render_Font.h b/Samples/CommonSrc/Render/Render_Font.h
index 3201b68..2e44e5d 100644
--- a/Samples/CommonSrc/Render/Render_Font.h
+++ b/Samples/CommonSrc/Render/Render_Font.h
@@ -5,7 +5,7 @@ Content : Font data structure used by renderer
Created : September, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/Samples/CommonSrc/Render/Render_GL_Device.cpp b/Samples/CommonSrc/Render/Render_GL_Device.cpp
index 54a2b9b..64da492 100644
--- a/Samples/CommonSrc/Render/Render_GL_Device.cpp
+++ b/Samples/CommonSrc/Render/Render_GL_Device.cpp
@@ -5,7 +5,7 @@ Content : RenderDevice implementation for OpenGL
Created : September 10, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -54,6 +54,7 @@ void (*GetFunction(const char *functionName))( void )
#endif
+PFNGLGETSTRINGIPROC glGetStringi;
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
PFNGLDELETESHADERPROC glDeleteShader;
@@ -95,6 +96,7 @@ PFNGLUNIFORM3FVPROC glUniform3fv;
PFNGLUNIFORM2FVPROC glUniform2fv;
PFNGLUNIFORM1FVPROC glUniform1fv;
PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D;
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
@@ -102,6 +104,7 @@ PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
+PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebuffer;
void InitGLExtensions()
{
@@ -115,6 +118,7 @@ void InitGLExtensions()
glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) GetFunction("glXSwapIntervalEXT");
#endif
+ glGetStringi = (PFNGLGETSTRINGIPROC) GetFunction("glGetStringi");
glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) GetFunction("glGenFramebuffersEXT");
glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) GetFunction("glDeleteFramebuffersEXT");
glDeleteShader = (PFNGLDELETESHADERPROC) GetFunction("glDeleteShader");
@@ -156,6 +160,7 @@ void InitGLExtensions()
glUniform2fv = (PFNGLUNIFORM2FVPROC) GetFunction("glUniform2fv");
glUniform1fv = (PFNGLUNIFORM1FVPROC) GetFunction("glUniform1fv");
glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) GetFunction("glCompressedTexImage2D");
+ glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) GetFunction("glTexImage2DMultisample");
glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) GetFunction("glRenderbufferStorageEXT");
glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) GetFunction("glBindRenderbufferEXT");
glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) GetFunction("glGenRenderbuffersEXT");
@@ -163,13 +168,14 @@ void InitGLExtensions()
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) GetFunction("glGenVertexArrays");
glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) GetFunction("glDeleteVertexArrays");
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) GetFunction("glBindVertexArray");
+ glBlitFramebuffer = (PFNGLBLITFRAMEBUFFEREXTPROC) GetFunction("glBlitFramebufferEXT");
}
#endif
static const char* StdVertexShaderSrc =
- "#version 110\n"
-
+"#version 110\n"
+
"uniform mat4 Proj;\n"
"uniform mat4 View;\n"
@@ -252,28 +258,28 @@ static const char* TextureFragShaderSrc =
" discard;\n"
"}\n";
-#define LIGHTING_COMMON \
+#define LIGHTING_COMMON \
"#version 110\n" \
- "uniform vec3 Ambient;\n" \
- "uniform vec4 LightPos[8];\n" \
- "uniform vec4 LightColor[8];\n" \
- "uniform float LightCount;\n" \
+ "uniform vec3 Ambient;\n" \
+ "uniform vec4 LightPos[8];\n" \
+ "uniform vec4 LightColor[8];\n" \
+ "uniform float LightCount;\n" \
"varying vec4 oColor;\n" \
"varying vec2 oTexCoord;\n" \
"varying vec3 oNormal;\n" \
"varying vec3 oVPos;\n" \
- "vec4 DoLight()\n" \
- "{\n" \
- " vec3 norm = normalize(oNormal);\n" \
- " vec3 light = Ambient;\n" \
- " for (int i = 0; i < int(LightCount); i++)\n" \
- " {\n" \
- " vec3 ltp = (LightPos[i].xyz - oVPos);\n" \
- " float ldist = length(ltp);\n" \
- " ltp = normalize(ltp);\n" \
+ "vec4 DoLight()\n" \
+ "{\n" \
+ " vec3 norm = normalize(oNormal);\n" \
+ " vec3 light = Ambient;\n" \
+ " for (int i = 0; i < int(LightCount); i++)\n" \
+ " {\n" \
+ " vec3 ltp = (LightPos[i].xyz - oVPos);\n" \
+ " float ldist = length(ltp);\n" \
+ " ltp = normalize(ltp);\n" \
" light += clamp(LightColor[i].rgb * oColor.rgb * (dot(norm, ltp) / ldist), 0.0,1.0);\n" \
- " }\n" \
- " return vec4(light, oColor.a);\n" \
+ " }\n" \
+ " return vec4(light, oColor.a);\n" \
"}\n"
static const char* LitSolidFragShaderSrc =
@@ -308,21 +314,21 @@ static const char* AlphaTextureFragShaderSrc =
"}\n";
static const char* AlphaBlendedTextureFragShaderSrc =
- "#version 110\n"
-
- "uniform sampler2D Texture0;\n"
+ "#version 110\n"
- "varying vec4 oColor;\n"
- "varying vec2 oTexCoord;\n"
+ "uniform sampler2D Texture0;\n"
- "void main()\n"
- "{\n"
+ "varying vec4 oColor;\n"
+ "varying vec2 oTexCoord;\n"
+
+ "void main()\n"
+ "{\n"
" vec4 finalColor = oColor;\n"
" finalColor *= texture2D(Texture0, oTexCoord);\n"
// Blend state expects premultiplied alpha
" finalColor.rgb *= finalColor.a;\n"
- " gl_FragColor = finalColor;\n"
- "}\n";
+ " gl_FragColor = finalColor;\n"
+ "}\n";
static const char* MultiTextureFragShaderSrc =
"#version 110\n"
@@ -336,15 +342,15 @@ static const char* MultiTextureFragShaderSrc =
"void main()\n"
"{\n"
- " vec4 color = texture2D(Texture0, oTexCoord);\n"
+ " vec4 color = texture2D(Texture0, oTexCoord);\n"
- " gl_FragColor = texture2D(Texture1, oTexCoord1);\n"
- " gl_FragColor.rgb = gl_FragColor.rgb * mix(1.9, 1.2, clamp(length(gl_FragColor.rgb),0.0,1.0));\n"
+ " gl_FragColor = texture2D(Texture1, oTexCoord1);\n"
+ " gl_FragColor.rgb = gl_FragColor.rgb * mix(1.9, 1.2, clamp(length(gl_FragColor.rgb),0.0,1.0));\n"
- " gl_FragColor = color * gl_FragColor;\n"
+ " gl_FragColor = color * gl_FragColor;\n"
- " if (gl_FragColor.a <= 0.6)\n"
- " discard;\n"
+ " if (gl_FragColor.a <= 0.6)\n"
+ " discard;\n"
"}\n";
static const char* PostProcessMeshFragShaderSrc =
@@ -455,12 +461,12 @@ static const char* PostProcessMeshTimewarpVertexShaderSrc =
// Accurate time warp lerp vs. faster
#if 0
// Apply the two 3x3 timewarp rotations to these vectors.
- " vec3 TransformedRStart = (EyeRotationStart * vec4(TanEyeAngleR, 0)).xyz;\n"
- " vec3 TransformedGStart = (EyeRotationStart * vec4(TanEyeAngleG, 0)).xyz;\n"
- " vec3 TransformedBStart = (EyeRotationStart * vec4(TanEyeAngleB, 0)).xyz;\n"
- " vec3 TransformedREnd = (EyeRotationEnd * vec4(TanEyeAngleR, 0)).xyz;\n"
- " vec3 TransformedGEnd = (EyeRotationEnd * vec4(TanEyeAngleG, 0)).xyz;\n"
- " vec3 TransformedBEnd = (EyeRotationEnd * vec4(TanEyeAngleB, 0)).xyz;\n"
+ " vec3 TransformedRStart = (EyeRotationStart * vec4(TanEyeAngleR, 0)).xyz;\n"
+ " vec3 TransformedGStart = (EyeRotationStart * vec4(TanEyeAngleG, 0)).xyz;\n"
+ " vec3 TransformedBStart = (EyeRotationStart * vec4(TanEyeAngleB, 0)).xyz;\n"
+ " vec3 TransformedREnd = (EyeRotationEnd * vec4(TanEyeAngleR, 0)).xyz;\n"
+ " vec3 TransformedGEnd = (EyeRotationEnd * vec4(TanEyeAngleG, 0)).xyz;\n"
+ " vec3 TransformedBEnd = (EyeRotationEnd * vec4(TanEyeAngleB, 0)).xyz;\n"
// And blend between them.
" vec3 TransformedR = mix ( TransformedRStart, TransformedREnd, Color.a );\n"
" vec3 TransformedG = mix ( TransformedGStart, TransformedGEnd, Color.a );\n"
@@ -526,7 +532,7 @@ PostProcessMeshTimewarpVertexShaderSrc;
"{\n"
" vec2 eyeToSourceTexCoord = inTexCoord * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
" eyeToSourceTexCoord.y = 1.0 - eyeToSourceTexCoord.y;\n"
- " float depth = texelFetch(Texture0, ivec2(eyeToSourceTexCoord * DepthDimSize), 0).x;\n" //FIXME: Use Texture2DLod for #version 110 support.
+ " float depth = texelFetch(Texture0, ivec2(eyeToSourceTexCoord * DepthDimSize), 0).x;\n" //FIXME: Use Texture2DLod for #version 110 support.
" float linearDepth = DepthProjector.y / (depth - DepthProjector.x);\n"
" vec4 retVal = vec4(inTexCoord, 1, 1);\n"
" retVal.xyz *= linearDepth;\n"
@@ -616,7 +622,7 @@ PostProcessMeshTimewarpVertexShaderSrc;
" lerpedEyeRot[1] = mix(EyeXformStart[1], EyeXformEnd[1], timewarpLerpFactor);\n"
" lerpedEyeRot[2] = mix(EyeXformStart[2], EyeXformEnd[2], timewarpLerpFactor);\n"
" lerpedEyeRot[3] = mix(EyeXformStart[3], EyeXformEnd[3], timewarpLerpFactor);\n"
- //" float4x4 lerpedEyeRot = EyeXformStart;\n"
+ //" float4x4 lerpedEyeRot = EyeXformStart;\n"
// warped positions are a bit more involved, hence a separate function
" gl_Position = TimewarpPos(Position.xy, oTexCoord0, lerpedEyeRot);\n"
@@ -641,8 +647,8 @@ static const char* PostProcessFragShaderWithChromAbSrc =
"varying vec4 oPosition;\n"
"varying vec2 oTexCoord;\n"
-
- "void main()\n"
+
+ "void main()\n"
"{\n"
// Input oTexCoord is [-1,1] across the half of the screen used for a single eye.
" vec2 TanEyeAngleDistorted = oTexCoord * TanEyeAngleScale + TanEyeAngleOffset;\n" // Scales to tan(thetaX),tan(thetaY), but still distorted (i.e. only the center is correct)
@@ -661,15 +667,15 @@ static const char* PostProcessFragShaderWithChromAbSrc =
// Scale them into ([0,0.5],[0,1]) or ([0.5,0],[0,1]) UV lookup space (depending on eye)
" vec2 SourceCoordR = TanEyeAngleR * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
- " SourceCoordR.y = 1.0 - SourceCoordR.y;\n"
+ " SourceCoordR.y = 1.0 - SourceCoordR.y;\n"
" vec2 SourceCoordG = TanEyeAngleG * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
- " SourceCoordG.y = 1.0 - SourceCoordG.y;\n"
+ " SourceCoordG.y = 1.0 - SourceCoordG.y;\n"
" vec2 SourceCoordB = TanEyeAngleB * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
- " SourceCoordB.y = 1.0 - SourceCoordB.y;\n"
+ " SourceCoordB.y = 1.0 - SourceCoordB.y;\n"
// Find the distance to the nearest edge.
" vec2 NDCCoord = TanEyeAngleG * EyeToSourceNDCScale + EyeToSourceNDCOffset;\n"
- " float EdgeFadeIn = clamp ( EdgeFadeScale, 0.0, 1e5 ) * ( 1.0 - max ( abs ( NDCCoord.x ), abs ( NDCCoord.y ) ) );\n"
+ " float EdgeFadeIn = clamp ( EdgeFadeScale, 0.0, 1e5 ) * ( 1.0 - max ( abs ( NDCCoord.x ), abs ( NDCCoord.y ) ) );\n"
" if ( EdgeFadeIn < 0.0 )\n"
" {\n"
" gl_FragColor = vec4(DistortionClearColor.r, DistortionClearColor.g, DistortionClearColor.b, 1.0);\n"
@@ -692,7 +698,7 @@ static const char* VShaderSrcs[VShader_Count] =
DirectVertexShaderSrc,
StdVertexShaderSrc,
PostProcessVertexShaderSrc,
- PostProcessMeshVertexShaderSrc,
+ PostProcessMeshVertexShaderSrc,
PostProcessMeshTimewarpVertexShaderSrc,
PostProcessMeshPositionalTimewarpVertexShaderSrc,
PostProcessHeightmapTimewarpVertexShaderSrc,
@@ -703,7 +709,7 @@ static const char* FShaderSrcs[FShader_Count] =
GouraudFragShaderSrc,
TextureFragShaderSrc,
AlphaTextureFragShaderSrc,
- AlphaBlendedTextureFragShaderSrc,
+ AlphaBlendedTextureFragShaderSrc,
PostProcessFragShaderWithChromAbSrc,
LitSolidFragShaderSrc,
LitTextureFragShaderSrc,
@@ -716,11 +722,25 @@ static const char* FShaderSrcs[FShader_Count] =
RenderDevice::RenderDevice(const RendererParams&)
+ : VertexShaders(),
+ FragShaders(),
+ DefaultFill(),
+ Proj(),
+ Vao(0),
+ CurRenderTarget(),
+ DepthBuffers(),
+ CurrentFbo(0),
+ MsaaFbo(0),
+ GLVersionInfo(),
+ DebugCallbackControl(),
+ Lighting(NULL)
{
+ DebugCallbackControl.Initialize();
+
GetGLVersionAndExtensions(GLVersionInfo);
OVR_ASSERT(GLVersionInfo.MajorVersion >= 2);
-
+
for (int i = 0; i < VShader_Count; i++)
{
OVR_ASSERT ( VShaderSrcs[i] != NULL ); // You forgot a shader!
@@ -732,13 +752,14 @@ RenderDevice::RenderDevice(const RendererParams&)
OVR_ASSERT ( FShaderSrcs[i] != NULL ); // You forgot a shader!
FragShaders[i] = *new Shader(this, Shader_Fragment, FShaderSrcs[i]);
}
-
+
Ptr<ShaderSet> gouraudShaders = *new ShaderSet();
gouraudShaders->SetShader(VertexShaders[VShader_MVP]);
gouraudShaders->SetShader(FragShaders[FShader_Gouraud]);
DefaultFill = *new ShaderFill(gouraudShaders);
glGenFramebuffers(1, &CurrentFbo);
+ glGenFramebuffers(1, &MsaaFbo);
if (GLVersionInfo.SupportsVAO)
{
@@ -758,7 +779,8 @@ void RenderDevice::Shutdown()
// This runs before the subclass's Shutdown(), where the context, etc, may be deleted.
- glDeleteFramebuffers(1, &CurrentFbo);
+ glDeleteFramebuffers(1, &CurrentFbo);
+ glDeleteFramebuffers(1, &MsaaFbo);
if (GLVersionInfo.SupportsVAO)
{
@@ -777,12 +799,14 @@ void RenderDevice::Shutdown()
DefaultFill.Clear();
DepthBuffers.Clear();
+
+ DebugCallbackControl.Shutdown();
}
void RenderDevice::FillTexturedRect(float left, float top, float right, float bottom, float ul, float vt, float ur, float vb, Color c, Ptr<OVR::Render::Texture> tex)
{
- Render::RenderDevice::FillTexturedRect(left, top, right, bottom, ul, vb, ur, vt, c, tex);
+ Render::RenderDevice::FillTexturedRect(left, top, right, bottom, ul, vt, ur, vb, c, tex);
}
@@ -829,12 +853,7 @@ void RenderDevice::SetDepthMode(bool enable, bool write, CompareFunc func)
void RenderDevice::SetViewport(const Recti& vp)
{
- int wh;
- if (CurRenderTarget)
- wh = CurRenderTarget->Height;
- else
- wh = WindowHeight;
- glViewport(vp.x, wh - vp.y - vp.h, vp.w, vp.h);
+ glViewport(vp.x, vp.y, vp.w, vp.h);
}
void RenderDevice::Flush()
@@ -844,14 +863,14 @@ void RenderDevice::Flush()
void RenderDevice::WaitUntilGpuIdle()
{
- glFlush();
- glFinish();
+ glFlush();
+ glFinish();
}
void RenderDevice::Clear(float r, float g, float b, float a, float depth, bool clearColor /*= true*/, bool clearDepth /*= true*/)
{
- glClearColor(r,g,b,a);
- glClearDepth(depth);
+ glClearColor(r,g,b,a);
+ glClearDepth(depth);
glClear(
( clearColor ? ( GL_COLOR_BUFFER_BIT ) : 0 ) |
( clearDepth ? ( GL_DEPTH_BUFFER_BIT ) : 0 )
@@ -869,6 +888,31 @@ Texture* RenderDevice::GetDepthBuffer(int w, int h, int ms)
return newDepth.GetPtr();
}
+void RenderDevice::ResolveMsaa(OVR::Render::Texture* msaaTex, OVR::Render::Texture* outputTex)
+{
+ bool isMsaaTarget = msaaTex->GetSamples() > 1;
+ glBindFramebuffer( GL_READ_FRAMEBUFFER, MsaaFbo );
+ glFramebufferTexture2D( GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ isMsaaTarget ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D,
+ ((Texture*)msaaTex)->TexId, 0);
+ glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
+ OVR_ASSERT(glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+
+ glBindFramebuffer( GL_DRAW_FRAMEBUFFER, CurrentFbo );
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ((Texture*)outputTex)->TexId, 0);
+ glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
+
+ OVR_ASSERT(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+
+ //glReadBuffer(GL_TEXTURE_2D_MULTISAMPLE);
+ //glDrawBuffer(GL_COLOR_ATTACHMENT0);
+ glBlitFramebuffer( 0, 0, msaaTex->GetWidth(), msaaTex->GetHeight(),
+ 0, 0, outputTex->GetWidth(), outputTex->GetHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST );
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ GLint err = glGetError();
+ OVR_ASSERT(!err); OVR_UNUSED(err);
+}
+
void RenderDevice::SetRenderTarget(Render::Texture* color, Render::Texture* depth, Render::Texture* stencil)
{
OVR_UNUSED(stencil);
@@ -879,14 +923,19 @@ void RenderDevice::SetRenderTarget(Render::Texture* color, Render::Texture* dept
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return;
}
-
- if (depth == NULL)
- depth = GetDepthBuffer(color->GetWidth(), color->GetHeight(), CurRenderTarget->GetSamples());
+
+ int sampleCount = CurRenderTarget->GetSamples();
+
+ if (depth == NULL)
+ depth = GetDepthBuffer(color->GetWidth(), color->GetHeight(), sampleCount);
glBindFramebuffer(GL_FRAMEBUFFER, CurrentFbo);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ((Texture*)color)->TexId, 0);
+
+ GLenum texTarget = (sampleCount > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texTarget, ((Texture*)color)->TexId, 0);
if (depth)
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, ((Texture*)depth)->TexId, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texTarget, ((Texture*)depth)->TexId, 0);
else
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
@@ -904,7 +953,7 @@ void RenderDevice::SetWorldUniforms(const Matrix4f& proj)
void RenderDevice::SetTexture(Render::ShaderStage, int slot, const Texture* t)
{
glActiveTexture(GL_TEXTURE0 + slot);
- glBindTexture(GL_TEXTURE_2D, ((Texture*)t)->TexId);
+ glBindTexture((t->GetSamples() > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, ((Texture*)t)->TexId);
}
Buffer* RenderDevice::CreateBuffer()
@@ -979,11 +1028,11 @@ void RenderDevice::Render(const Fill* fill, Render::Buffer* vertices, Render::Bu
Lighting->Set(shaders);
}
- glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer);
- for (int i = 0; i < 5; i++)
- glEnableVertexAttribArray(i);
+ glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer);
+ for (int i = 0; i < 5; i++)
+ glEnableVertexAttribArray(i);
- switch (meshType)
+ switch (meshType)
{
case Mesh_Distortion:
glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset) + offsetof(DistortionVertex, Pos));
@@ -1016,8 +1065,8 @@ void RenderDevice::Render(const Fill* fill, Render::Buffer* vertices, Render::Bu
glDrawArrays(prim, 0, count);
}
- for (int i = 0; i < 5; i++)
- glDisableVertexAttribArray(i);
+ for (int i = 0; i < 5; i++)
+ glDisableVertexAttribArray(i);
}
void RenderDevice::RenderWithAlpha(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices,
@@ -1104,8 +1153,16 @@ bool Shader::Compile(const char* src)
return 1;
}
-ShaderSet::ShaderSet()
+ShaderSet::ShaderSet() :
+ //Prog(0),
+ UniformInfo(),
+ ProjLoc(0),
+ ViewLoc(0),
+ //TexLoc[8];
+ UsesLighting(false),
+ LightingVer(0)
{
+ memset(TexLoc, 0, sizeof(TexLoc));
Prog = glCreateProgram();
}
ShaderSet::~ShaderSet()
@@ -1155,9 +1212,9 @@ bool ShaderSet::Link()
LightingVer = 0;
UsesLighting = 0;
- GLint uniformCount = 0;
- glGetProgramiv(Prog, GL_ACTIVE_UNIFORMS, &uniformCount);
- OVR_ASSERT(uniformCount >= 0);
+ GLint uniformCount = 0;
+ glGetProgramiv(Prog, GL_ACTIVE_UNIFORMS, &uniformCount);
+ OVR_ASSERT(uniformCount >= 0);
for(GLuint i = 0; i < (GLuint)uniformCount; i++)
{
@@ -1260,7 +1317,7 @@ bool ShaderSet::SetUniform4x4f(const char* name, const Matrix4f& m)
return 0;
}
-Texture::Texture(RenderDevice* r, int w, int h) : Ren(r), Width(w), Height(h)
+Texture::Texture(RenderDevice* r, int w, int h, int samples) : Ren(r), Width(w), Height(h), Samples(samples)
{
glGenTextures(1, &TexId);
}
@@ -1278,7 +1335,7 @@ void Texture::Set(int slot, Render::ShaderStage stage) const
void Texture::SetSampleMode(int sm)
{
- glBindTexture(GL_TEXTURE_2D, TexId);
+ glBindTexture((GetSamples() > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, TexId);
switch (sm & Sample_FilterMask)
{
case Sample_Linear:
@@ -1294,7 +1351,7 @@ void Texture::SetSampleMode(int sm)
break;
case Sample_Nearest:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
break;
@@ -1321,8 +1378,8 @@ void Texture::SetSampleMode(int sm)
ovrTexture Texture::Get_ovrTexture()
{
- ovrTexture tex;
- OVR::Sizei newRTSize(Width, Height);
+ ovrTexture tex;
+ OVR::Sizei newRTSize(Width, Height);
ovrGLTextureData* texData = (ovrGLTextureData*)&tex;
texData->Header.API = ovrRenderAPI_OpenGL;
@@ -1330,7 +1387,7 @@ ovrTexture Texture::Get_ovrTexture()
texData->Header.RenderViewport = Recti(newRTSize);
texData->TexId = TexId;
- return tex;
+ return tex;
}
Texture* RenderDevice::CreateTexture(int format, int width, int height, const void* data, int mipcount)
@@ -1340,23 +1397,34 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo
{
case Texture_RGBA: glformat = GL_RGBA; break;
case Texture_R: glformat = GL_RED; break;
- case Texture_Depth: glformat = GL_DEPTH_COMPONENT; gltype = GL_FLOAT; break;
+ case Texture_Depth: glformat = GL_DEPTH_COMPONENT; gltype = GL_FLOAT; break;
case Texture_DXT1: glformat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
case Texture_DXT3: glformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
case Texture_DXT5: glformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
default:
return NULL;
}
- Texture* NewTex = new Texture(this, width, height);
- glBindTexture(GL_TEXTURE_2D, NewTex->TexId);
- GLint err = glGetError();
+ int samples = format & Texture_SamplesMask;
+ if(samples < 1 ||
+ GLVersionInfo.WholeVersion < 302) // disallow MSAA for low GL context versions
+ {
+ samples = 1;
+ }
+
+ GLenum textureTarget = (samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
+
+ Texture* NewTex = new Texture(this, width, height, samples);
+ glBindTexture(textureTarget, NewTex->TexId);
+ GLint err = glGetError();
+ #if ! defined(OVR_OS_MAC)
OVR_ASSERT(!err);
+ #endif
- if( err )
- {
- printf("%d\n", err);
- }
+ if( err )
+ {
+ printf("RenderDevice::CreateTexture glGetError result: %d\n", err);
+ }
if (format & Texture_Compressed)
{
@@ -1374,14 +1442,17 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo
if (h < 1) h = 1;
}
}
- else
- {
- bool isSRGB = ((format & Texture_TypeMask) == Texture_RGBA && (format & Texture_SRGB) != 0);
- bool isDepth = ((format & Texture_Depth) != 0);
- GLenum internalFormat = (isSRGB) ? GL_SRGB_ALPHA : (isDepth) ? GL_DEPTH_COMPONENT32F : glformat;
+ else
+ {
+ bool isSRGB = ((format & Texture_TypeMask) == Texture_RGBA && (format & Texture_SRGB) != 0);
+ bool isDepth = ((format & Texture_Depth) != 0);
+ GLenum internalFormat = (isSRGB) ? GL_SRGB8_ALPHA8 : (isDepth) ? GL_DEPTH_COMPONENT32F : glformat;
- glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, glformat, gltype, data);
- }
+ if (samples > 1)
+ glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalFormat, width, height, false);
+ else
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, glformat, gltype, data);
+ }
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
@@ -1435,9 +1506,397 @@ RBuffer::~RBuffer()
}
-//// GLVersion
-static void ParseGLVersion(GLVersionAndExtensions& versionInfo)
+
+
+
+DebugCallback::DebugCallback()
+ : Initialized(false),
+ MinLogSeverity(SeverityHigh),
+ MinAssertSeverity(SeverityHigh),
+ glDebugMessageCallback(NULL),
+ glDebugMessageControl(NULL),
+ glDebugMessageCallbackARB(NULL),
+ glDebugMessageControlARB(NULL),
+ glDebugMessageCallbackAMD(NULL),
+ glDebugMessageControlAMD(NULL)
+{
+}
+
+
+DebugCallback::~DebugCallback()
+{
+ Shutdown();
+}
+
+
+bool DebugCallback::GetGLDebugCallback(PFNGLDEBUGMESSAGECALLBACKPROC* debugCallback, const void** userParam) const
+{
+ // Curiously, the KHR and ARB callbacks use the same glGetPointerv defines, which means you can only have
+ // one of them active concurrently. This also implies that an OpenGL implementation which implements both
+ // KHR and ARB implements the latter as simply a passthrough (or alias) of the former.
+ #if defined(GL_ARB_debug_output) || defined(GL_KHR_debug)
+ // glGetPointerv requires at least OpenGL 4.3 headers and implementation,
+ // but will be present in the headers if GL_ARB_debug_output or GL_KHR_debug are.
+ if(glDebugMessageCallback || glDebugMessageCallbackARB)
+ {
+ glGetPointerv(GL_DEBUG_CALLBACK_FUNCTION, reinterpret_cast<GLvoid**>(debugCallback));
+ glGetPointerv(GL_DEBUG_CALLBACK_USER_PARAM, const_cast<GLvoid**>(userParam));
+ return true;
+ }
+ #endif
+
+ // AMD_debug_output doesn't provide an option to get the debug callback.
+ debugCallback = NULL;
+ userParam = NULL;
+ return false;
+}
+
+
+void DebugCallback::DebugCallbackInternal(Severity s, const char* pSource, const char* pType, GLuint id, const char* pSeverity, const char* message)
+{
+ if(s >= MinLogSeverity)
+ {
+ OVR::LogError("{ERR-xxxx} [GL Error] %s %s %#x %s: %s", pSource, pType, id, pSeverity, message);
+ }
+
+ if(s >= MinAssertSeverity)
+ {
+ OVR_ASSERT(s < MinAssertSeverity); // Unilateral fail.
+ }
+}
+
+
+void DebugCallback::Initialize()
+{
+ if(!Initialized)
+ {
+ Initialized = true;
+
+ int err = glGetError();
+ OVR_UNUSED(err);
+
+ // Used to see if a callback was already registered.
+ PFNGLDEBUGMESSAGECALLBACKPROC debugCallbackPrev = NULL;
+ const void* userParamPrev = NULL;
+
+ // Try getting the KHR interface.
+ #if defined(OVR_OS_MAC) // With Mac OpenGL, functions aren't dynamically linked. They are only directly called.
+ //glDebugMessageCallback = ::glDebugMessageCallback; // We can enable this some day when Apple includes support
+ //glDebugMessageControl = ::glDebugMessageControl; // for glDebugMessageCallback in their headers and SDK.
+ #else
+ glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC) GetFunction("glDebugMessageCallback");
+ glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC) GetFunction("glDebugMessageControl");
+ #endif
+
+ if(glDebugMessageCallback)
+ {
+ GetGLDebugCallback(&debugCallbackPrev, &userParamPrev);
+
+ if(!debugCallbackPrev) // If a callback isn't already registered...
+ {
+ glDebugMessageCallback(GLDEBUGPROC(DebugMessageCallback), this);
+ err = glGetError();
+ if(err)
+ {
+ glDebugMessageCallback = NULL;
+ glDebugMessageControl = NULL;
+ OVR_DEBUG_LOG(("glDebugMessageCallback error: %x (%d)\n", err, err));
+ }
+
+ glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ err = glGetError();
+ if(err)
+ {
+ OVR_DEBUG_LOG(("GL_DEBUG_OUTPUT_SYNCHRONOUS error: %x (%d)\n", err, err));
+ }
+
+ // To consider: disable marker/push/pop
+ // glDebugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, GL_DONT_CARE, 0, NULL, GL_FALSE);
+ // glDebugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP, GL_DONT_CARE, 0, NULL, GL_FALSE);
+ // glDebugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP, GL_DONT_CARE, 0, NULL, GL_FALSE);
+ }
+ }
+
+ if(!glDebugMessageCallback) // If KHR_debug wasn't found, try ARB_debug_output.
+ {
+ #if !defined(OVR_OS_MAC)
+ glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC) GetFunction("glDebugMessageCallbackARB");
+ glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) GetFunction("glDebugMessageControlARB");
+ #endif
+
+ if(glDebugMessageCallbackARB)
+ {
+ GetGLDebugCallback(&debugCallbackPrev, &userParamPrev);
+
+ if(!debugCallbackPrev) // If a callback isn't already registered...
+ {
+ glDebugMessageCallbackARB(GLDEBUGPROCARB(DebugMessageCallback), this);
+ err = glGetError();
+ if(err)
+ {
+ glDebugMessageCallbackARB = NULL;
+ glDebugMessageControlARB = NULL;
+ OVR_DEBUG_LOG(("glDebugMessageCallbackARB error: %x (%d)\n", err, err));
+ }
+
+ glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ err = glGetError();
+ if(err)
+ {
+ OVR_DEBUG_LOG(("GL_DEBUG_OUTPUT_SYNCHRONOUS error: %x (%d)\n", err, err));
+ }
+
+ // To consider: disable marker/push/pop
+ // glDebugMessageControlARB(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, GL_DONT_CARE, 0, NULL, GL_FALSE);
+ // glDebugMessageControlARB(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP, GL_DONT_CARE, 0, NULL, GL_FALSE);
+ // glDebugMessageControlARB(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP, GL_DONT_CARE, 0, NULL, GL_FALSE);
+ }
+ }
+ }
+
+ if(!glDebugMessageCallback && !glDebugMessageCallbackARB)// If ARB_debug_output also wasn't found, try AMD_debug_output.
+ {
+ #if !defined(OVR_OS_MAC)
+ glDebugMessageCallbackAMD = (PFNGLDEBUGMESSAGECALLBACKAMDPROC) GetFunction("glDebugMessageCallbackAMD");
+ glDebugMessageControlAMD = (PFNGLDEBUGMESSAGEENABLEAMDPROC) GetFunction("glDebugMessageControlAMD");
+ #endif
+
+ if(glDebugMessageCallbackAMD)
+ {
+ if(!debugCallbackPrev) // If a callback isn't already registered...
+ {
+ glDebugMessageCallbackAMD(GLDEBUGPROCAMD(DebugMessageCallbackAMD), this);
+ err = glGetError();
+ if(err)
+ {
+ glDebugMessageCallbackAMD = NULL;
+ glDebugMessageControlAMD = NULL;
+ OVR_DEBUG_LOG(("glDebugMessageCallbackAMD error: %x (%d)\n", err, err));
+ }
+ // There is no control for synchronous/asynchronous with AMD_debug_output.
+ }
+ }
+ }
+ }
+}
+
+
+void DebugCallback::Shutdown()
+{
+ if(Initialized)
+ {
+ if(glDebugMessageCallbackAMD)
+ {
+ glDebugMessageCallbackAMD(NULL, NULL);
+ glDebugMessageCallbackAMD = NULL;
+ }
+
+ if(glDebugMessageCallbackARB)
+ {
+ glDebugMessageCallbackARB(NULL, NULL);
+ glDebugMessageCallbackARB = NULL;
+ }
+
+ if(glDebugMessageCallback)
+ {
+ glDebugMessageCallback(NULL, NULL);
+ glDebugMessageCallback = NULL;
+ }
+
+ Initialized = false;
+ }
+}
+
+
+void DebugCallback::SetMinSeverity(Severity minLogSeverity, Severity minAssertSeverity)
+{
+ MinLogSeverity = minLogSeverity;
+ MinAssertSeverity = minAssertSeverity;
+}
+
+
+DebugCallback::Implementation DebugCallback::GetImplementation() const
+{
+ if(glDebugMessageCallbackAMD)
+ return ImplementationAMD;
+
+ if(glDebugMessageCallbackARB)
+ return ImplementationARB;
+
+ if(glDebugMessageCallback)
+ return ImplementationKHR;
+
+ return ImplementationNone;
+}
+
+
+void DebugCallback::DebugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei /*length*/, const GLchar* message, GLvoid* userParam)
+{
+ const char* pSource = GetSource(source);
+ const char* pType = GetType(type);
+ const char* pSeverity = GetSeverity(severity);
+ Severity s;
+
+ switch(severity)
+ {
+ default:
+ case GL_DEBUG_SEVERITY_NOTIFICATION:
+ s = SeverityNotification;
+ break;
+ case GL_DEBUG_SEVERITY_LOW:
+ s = SeverityLow;
+ break;
+ case GL_DEBUG_SEVERITY_MEDIUM:
+ s = SeverityMedium;
+ break;
+ case GL_DEBUG_SEVERITY_HIGH:
+ s = SeverityHigh;
+ break;
+ }
+
+ DebugCallback* pThis = reinterpret_cast<DebugCallback*>(userParam);
+ pThis->DebugCallbackInternal(s, pSource, pType, id, pSeverity, message);
+}
+
+
+const char* DebugCallback::GetSource(GLenum Source)
+{
+ // There is one contiguous section of GL_DEBUG_SOURCE values.
+ static_assert((GL_DEBUG_SOURCE_OTHER - GL_DEBUG_SOURCE_API) == 5, "GL_DEBUG_SOURCE constants are not contiguous.");
+
+ static const char* GL_SourceStrings[] =
+ {
+ "API", // GL_DEBUG_SOURCE_API
+ "System", // GL_DEBUG_SOURCE_WINDOW_SYSTEM
+ "ShaderCompiler", // GL_DEBUG_SOURCE_SHADER_COMPILER
+ "ThirdParty", // GL_DEBUG_SOURCE_THIRD_PARTY
+ "Application", // GL_DEBUG_SOURCE_APPLICATION
+ "Other" // GL_DEBUG_SOURCE_OTHER
+ };
+
+ if ((Source >= GL_DEBUG_SOURCE_API) && (Source <= GL_DEBUG_SOURCE_OTHER))
+ return GL_SourceStrings[Source - GL_DEBUG_SOURCE_API];
+
+ return "Unknown";
+}
+
+
+
+const char* DebugCallback::GetType(GLenum Type)
+{
+ // There are two contiguous sections of GL_DEBUG_TYPE values.
+ static_assert((GL_DEBUG_TYPE_OTHER - GL_DEBUG_TYPE_ERROR) == 5, "GL_DEBUG_TYPE constants are not contiguous.");
+ static const char* TypeStrings[] =
+ {
+ "Error", // GL_DEBUG_TYPE_ERROR
+ "Deprecated", // GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR
+ "UndefinedBehavior", // GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR
+ "Portability", // GL_DEBUG_TYPE_PORTABILITY
+ "Performance", // GL_DEBUG_TYPE_PERFORMANCE
+ "Other" // GL_DEBUG_TYPE_OTHER
+ };
+
+ if ((Type >= GL_DEBUG_TYPE_ERROR) && (Type <= GL_DEBUG_TYPE_OTHER))
+ return TypeStrings[Type - GL_DEBUG_TYPE_ERROR];
+
+ // KHR_debug marker/push/pop functionality.
+ static_assert((GL_DEBUG_TYPE_POP_GROUP - GL_DEBUG_TYPE_MARKER) == 2, "GL_DEBUG_TYPE constants are not contiguous.");
+ static const char* TypeStrings2[] =
+ {
+ "Marker", // GL_DEBUG_TYPE_MARKER
+ "PushGroup", // GL_DEBUG_TYPE_PUSH_GROUP
+ "PopGroup", // GL_DEBUG_TYPE_POP_GROUP
+ };
+
+ if ((Type >= GL_DEBUG_TYPE_MARKER) && (Type <= GL_DEBUG_TYPE_POP_GROUP))
+ return TypeStrings2[Type - GL_DEBUG_TYPE_MARKER];
+
+ return "Unknown";
+}
+
+
+const char* DebugCallback::GetSeverity(GLenum Severity)
+{
+ // There are two sections of GL_DEBUG_SEVERITY.
+ static_assert((GL_DEBUG_SEVERITY_LOW - GL_DEBUG_SEVERITY_HIGH) == 2, "GL_DEBUG_SEVERITY constants are not contiguous.");
+ static const char* SeverityStrings[] =
+ {
+ "High",
+ "Medium",
+ "Low"
+ };
+
+ if ((Severity >= GL_DEBUG_SEVERITY_HIGH) && (Severity <= GL_DEBUG_SEVERITY_LOW))
+ return SeverityStrings[Severity - GL_DEBUG_SEVERITY_HIGH];
+
+ // There is just one value in this second section.
+ if(Severity == GL_DEBUG_SEVERITY_NOTIFICATION)
+ return "Notification";
+
+ return "Unknown";
+}
+
+
+void DebugCallback::DebugMessageCallbackAMD(GLuint id, GLenum category, GLenum severity, GLsizei /*length*/, const GLchar *message, GLvoid *userParam)
+{
+ static_assert(GL_DEBUG_SEVERITY_LOW_AMD == GL_DEBUG_SEVERITY_LOW, "Severity mismatch"); // Verify that AMD_debug_output severity constants are identical to KHR_debug severity contstants.
+
+ const char* pSource = GetCategoryAMD(category);
+ const char* pSeverity = GetSeverity(severity);
+ Severity s;
+
+ switch(severity)
+ {
+ default:
+ case GL_DEBUG_SEVERITY_NOTIFICATION:
+ s = SeverityNotification;
+ break;
+ case GL_DEBUG_SEVERITY_LOW:
+ s = SeverityLow;
+ break;
+ case GL_DEBUG_SEVERITY_MEDIUM:
+ s = SeverityMedium;
+ break;
+ case GL_DEBUG_SEVERITY_HIGH:
+ s = SeverityHigh;
+ break;
+ }
+
+ DebugCallback* pThis = reinterpret_cast<DebugCallback*>(userParam);
+ pThis->DebugCallbackInternal(s, pSource, "Other", id, pSeverity, message);
+}
+
+
+const char* DebugCallback::GetCategoryAMD(GLenum Category)
+{
+ static_assert((GL_DEBUG_CATEGORY_OTHER_AMD - GL_DEBUG_CATEGORY_API_ERROR_AMD) == 7, "GL_DEBUG_CATEGORY constants are not contiguous.");
+ static const char* CategoryStrings[] =
+ {
+ "API", // GL_DEBUG_CATEGORY_API_ERROR_AMD
+ "System", // GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD
+ "Deprecation", // GL_DEBUG_CATEGORY_DEPRECATION_AMD
+ "UndefinedBehavior", // GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD
+ "Performance", // GL_DEBUG_CATEGORY_PERFORMANCE_AMD
+ "ShaderCompiler", // GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD
+ "Application", // GL_DEBUG_CATEGORY_APPLICATION_AMD
+ "Other" // GL_DEBUG_CATEGORY_OTHER_AMD
+ };
+
+ if((Category >= GL_DEBUG_CATEGORY_API_ERROR_AMD) && (Category <= GL_DEBUG_CATEGORY_OTHER_AMD))
+ return CategoryStrings[Category - GL_DEBUG_CATEGORY_API_ERROR_AMD];
+
+ return "Unknown";
+}
+
+
+
+
+
+
+
+
+void GLVersionAndExtensions::ParseGLVersion()
{
const char* version = (const char*)glGetString(GL_VERSION);
int fields = 0, major = 0, minor = 0;
@@ -1448,23 +1907,14 @@ static void ParseGLVersion(GLVersionAndExtensions& versionInfo)
{
OVR_DEBUG_LOG(("GL_VERSION: %s", (const char*)version));
-#ifdef OVR_CC_MSVC
- // Hack: This is using sscanf_s on MSVC to kill the security warning.
- // Normally the two functions are not interchangeable because the string format
- // is different for %s types, however we only use %d so it's fine.
-#define TEMP_OVR_SSCANF sscanf_s
-#else
-#define TEMP_OVR_SSCANF sscanf
-#endif
-
// Skip all leading non-digits before reading %d.
// Example GL_VERSION strings:
// "1.5 ATI-1.4.18"
// "OpenGL ES-CM 3.2"
- fields = TEMP_OVR_SSCANF(version, isdigit(*version) ? "%d.%d" : "%*[^0-9]%d.%d", &major, &minor);
+ OVR_DISABLE_MSVC_WARNING(4996) // "scanf may be unsafe"
+ fields = sscanf(version, isdigit(*version) ? "%d.%d" : "%*[^0-9]%d.%d", &major, &minor);
isGLES = (strstr(version, "OpenGL ES") != NULL);
-
-#undef TEMP_OVR_SSCANF
+ OVR_RESTORE_MSVC_WARNING()
}
else
{
@@ -1481,81 +1931,122 @@ static void ParseGLVersion(GLVersionAndExtensions& versionInfo)
}
// Write version data
- versionInfo.MajorVersion = major;
- versionInfo.MinorVersion = minor;
- versionInfo.IsGLES = isGLES;
+ MajorVersion = major;
+ MinorVersion = minor;
+ WholeVersion = (major * 100) + minor;
+ IsGLES = isGLES;
+ IsCoreProfile = (MajorVersion >= 3); // Until we get a better way to detect core profiles, we err on the conservative side and set to true if the version is >= 3.
}
-static bool HasGLExtension(const char* extensions, const char* searchKey)
-{
- const int searchKeyLen = (int)strlen(searchKey);
- const char* p = extensions;
- for (;;)
+bool GLVersionAndExtensions::HasGLExtension(const char* searchKey) const
+{
+ if (Extensions && Extensions[0]) // If we have an extension string to search for individual extensions...
{
- p = strstr(p, searchKey);
+ const int searchKeyLen = (int)strlen(searchKey);
+ const char* p = Extensions;
- // If not found,
- if (p == NULL)
+ for (;;)
{
- break;
- }
+ p = strstr(p, searchKey);
- // Only match full string
- if ((p == extensions || p[-1] == ' ') &&
- (p[searchKeyLen] == '\0' || p[searchKeyLen] == ' '))
- {
- return true;
+ // If not found,
+ if (p == NULL)
+ {
+ break;
+ }
+
+ // Only match full string
+ if ((p == Extensions || p[-1] == ' ') &&
+ (p[searchKeyLen] == '\0' || p[searchKeyLen] == ' '))
+ {
+ return true;
+ }
+
+ // Skip ahead
+ p += searchKeyLen;
}
+ }
+ else
+ {
+ if (MajorVersion >= 3) // If glGetIntegerv(GL_NUM_EXTENSIONS, ...) is supported...
+ {
+ GLint extensionCount = 0;
+ glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
+ GLenum err = glGetError();
- // Skip ahead
- p += searchKeyLen;
+ if (err == 0)
+ {
+ for (GLint i = 0; i != extensionCount; ++i)
+ {
+ const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, (GLuint)i);
+
+ if (extension) // glGetStringi returns NULL upon error.
+ {
+ if (strcmp(extension, searchKey) == 0)
+ return true;
+ }
+ else
+ break;
+ }
+ }
+ }
}
return false;
}
-static void ParseGLExtensions(GLVersionAndExtensions& versionInfo)
+void GLVersionAndExtensions::ParseGLExtensions()
{
- const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
-
- OVR_ASSERT(extensions);
- if (!extensions)
+ if (MajorVersion >= 3)
{
- extensions = ""; // Note: glGetString() can return null
- LogText("Warning: GL_EXTENSIONS was NULL\n");
+ // Set to empty because we need to use glGetStringi to read extensions on recent OpenGL.
+ Extensions = "";
}
else
{
- // Cannot print this to debug log: It's too long!
- //OVR_DEBUG_LOG(("GL_EXTENSIONS: %s", (const char*)extensions));
+ const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
+
+ OVR_ASSERT(extensions);
+ if (!extensions)
+ {
+ extensions = ""; // Note: glGetString() can return null
+ LogText("Warning: GL_EXTENSIONS was NULL\n");
+ }
+ else
+ {
+ // Cannot print this to debug log: It's too long!
+ //OVR_DEBUG_LOG(("GL_EXTENSIONS: %s", (const char*)extensions));
+ }
+
+ Extensions = extensions;
}
- versionInfo.Extensions = extensions;
+ // To do: revise the code below to loop through calls to glGetStringi(GL_EXTENSIONS, ...) so that all extensions below
+ // can be searched with a single pass over the extensions instead of a full loop per HasGLExtensionCall.
- if (versionInfo.MajorVersion >= 3)
+ if (MajorVersion >= 3)
{
- versionInfo.SupportsVAO = true;
+ SupportsVAO = true;
}
else
{
- versionInfo.SupportsVAO =
- HasGLExtension(extensions, "GL_ARB_vertex_array_object") ||
- HasGLExtension(extensions, "GL_APPLE_vertex_array_object");
+ SupportsVAO =
+ HasGLExtension("GL_ARB_vertex_array_object") ||
+ HasGLExtension("GL_APPLE_vertex_array_object");
}
- versionInfo.SupportsDrawBuffers = HasGLExtension(extensions, "GL_EXT_draw_buffers2");
+ SupportsDrawBuffers = HasGLExtension("GL_EXT_draw_buffers2");
// Add more extension checks here...
}
void GetGLVersionAndExtensions(GLVersionAndExtensions& versionInfo)
{
- ParseGLVersion(versionInfo);
-
+ versionInfo.ParseGLVersion();
// GL Version must be parsed before parsing extensions:
-
- ParseGLExtensions(versionInfo);
+ versionInfo.ParseGLExtensions();
+ // To consider: Call to glGetStringi(GL_SHADING_LANGUAGE_VERSION, ...) check/validate the GLSL support.
}
diff --git a/Samples/CommonSrc/Render/Render_GL_Device.h b/Samples/CommonSrc/Render/Render_GL_Device.h
index 0e24517..620d1bb 100644
--- a/Samples/CommonSrc/Render/Render_GL_Device.h
+++ b/Samples/CommonSrc/Render/Render_GL_Device.h
@@ -5,7 +5,7 @@ Content : RenderDevice implementation header for OpenGL
Created : September 10, 2012
Authors : Andrew Reisse, David Borel
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -62,6 +62,7 @@ extern PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT;
#endif
+extern PFNGLGETSTRINGIPROC glGetStringi;
extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
extern PFNGLDELETESHADERPROC glDeleteShader;
@@ -102,6 +103,7 @@ extern PFNGLUNIFORM3FVPROC glUniform3fv;
extern PFNGLUNIFORM2FVPROC glUniform2fv;
extern PFNGLUNIFORM1FVPROC glUniform1fv;
extern PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D;
+extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
@@ -109,6 +111,7 @@ extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
+extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebuffer;
extern void InitGLExtensions();
@@ -116,22 +119,26 @@ extern void InitGLExtensions();
-//// GLVersion
-
-/*
- FIXME: CODE DUPLICATION WARNING
-
- Right now we have this same code in CommonSrc and in CAPI::GL.
- At some point we need to consolidate these, in Kernel or Util.
- Be sure to update both locations for now!
-*/
-
-struct GLVersionAndExtensions
+//// GLVersionAndExtensions
+//
+// FIXME: CODE DUPLICATION WARNING
+// Right now we have this same code in CommonSrc and in CAPI::GL.
+// At some point we need to consolidate these, in Kernel or Util.
+// Be sure to update both locations for now!
+//
+// This class needs to be initialized at runtime with GetGLVersionAndExtensions,
+// after an OpenGL context has been created. It must be re-initialized any time
+// a new OpenGL context is created, as the new context may differ in version or
+// supported functionality.
+class GLVersionAndExtensions
{
+public:
// Version information
int MajorVersion; // Best guess at major version
int MinorVersion; // Best guess at minor version
+ int WholeVersion; // Equals ((MajorVersion * 100) + MinorVersion). Example usage: if(glv.WholeVersion >= 302) // If OpenGL v3.02+ ...
bool IsGLES; // Open GL ES?
+ bool IsCoreProfile; // Is the current OpenGL context a core profile context? Its trueness may be a false positive but will never be a false negative.
// Extension information
bool SupportsVAO; // Supports Vertex Array Objects?
@@ -139,19 +146,185 @@ struct GLVersionAndExtensions
const char* Extensions; // Other extensions string (will not be null)
GLVersionAndExtensions()
+ : MajorVersion(0),
+ MinorVersion(0),
+ WholeVersion(0),
+ IsGLES(false),
+ IsCoreProfile(false),
+ SupportsDrawBuffers(false),
+ SupportsVAO(false),
+ Extensions("")
{
- IsGLES = false;
- MajorVersion = 0;
- MinorVersion = 0;
- SupportsDrawBuffers = false;
- SupportsVAO = false;
- Extensions = "";
}
+
+ bool HasGLExtension(const char* searchKey) const;
+
+protected:
+ friend void GetGLVersionAndExtensions(GLVersionAndExtensions& versionInfo);
+
+ void ParseGLVersion();
+ void ParseGLExtensions();
};
void GetGLVersionAndExtensions(GLVersionAndExtensions& versionInfo);
+
+//// DebugCallback
+//
+// Used for high level usage and control of the various OpenGL debug output extensions. This is useful for
+// intercepting all OpenGL errors in a single place.
+// This functionality is specific to OpenGL and no analog exists in DirectX, as DirectX doesn't support
+// debug callbacks.
+//
+// Example basic usage:
+// DebugCallback glDebug;
+//
+// <initialize OpenGL context>
+// glDebug.Initialize();
+// glDebug.SetMinSeverity(SeverityMedium, SeverityHigh);
+// <use OpenGL. Debug output will be logged by default.>
+// glDebug.Shutdown();
+// <destroy OpenGL context>
+//
+// There are three OpenGL API debug interfaces, each being an evolution of its predecessor:
+// AMD_debug_output - https://www.opengl.org/registry/specs/AMD/debug_output.txt
+// ARB_debug_output - https://www.opengl.org/registry/specs/ARB/debug_output.txt
+// KHR_debug - https://www.opengl.org/registry/specs/KHR/debug.txt
+//
+// If the AMD_debug_output functionality is present in the OpenGL headers, GL_AMD_debug_output will be defined by glext.h.
+// If the ARB_debug_output functionality is present in the OpenGL headers, GL_ARB_debug_output will be defined by glext.h.
+// If the KHR_debug functionality is present in the OpenGL headers, GL_KHR_debug will be defined.
+//
+// As of at least XCode 5.1, debug functionality isn't yet supported by Macintosh OS X.
+// KHR_debug is part of the OpenGL 4.3 core profile. It uses the same interface as the ARB extension along with some additions.
+// The KHR_debug functionality doesn't include an API suffix (e.g. you would call glDebugMessageCallback).
+// OpenGL ES supports KHR debug callbacks as of v3.1. However, for OpenGL ES entry points use the "KHR" suffix (e.g. glDebugMessageCallbackKHR).
+// With the KHR version you can control debug messages at runtime with glEnable/glDisable(DEBUG_OUTPUT).
+// The KHR_debug functionality requires that the OpenGL context be created with the CONTEXT_FLAG_DEBUG_BIT.
+// Windows wglCreateContextAttribsARB should be done with WGL_CONTEXT_DEBUG_BIT_ARB with in WGL_CONTEXT_FLAGS.
+// Linux glXCreateContext should be done with GLX_CONTEXT_DEBUG_BIT_ARB set in GLX_CONTEXT_FLAGS.
+
+// We manually declare types and define values that aren't already declared and defined. This is because this functionality
+// is fairly recent (2010 through 2014) and isn't present in all OpenGL headers and implementations.
+#ifndef GL_AMD_debug_output
+ typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam);
+ typedef void (APIENTRYP PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+ typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKAMDPROC)(GLDEBUGPROCAMD callback, GLvoid *userParam);
+
+ #define GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149
+ #define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150
+ #define GL_DEBUG_SEVERITY_LOW_AMD 0x9148
+#endif
+
+#ifndef GL_ARB_debug_output
+ typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam);
+ typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+ typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKARBPROC)(GLDEBUGPROCARB callback, const void *userParam);
+
+ // We don't define anything here because the defines are the same as the KHR defines below (aside from the _ARB suffix).
+#endif
+
+#ifndef GL_KHR_debug // The following defines were added to OpenGL 4.3+ headers.
+ typedef void (APIENTRY *GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam);
+ typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+ typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC)(GLDEBUGPROC callback, const void *userParam);
+
+ #define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+ #define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+ #define GL_DEBUG_TYPE_MARKER 0x8268
+ #define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+ #define GL_DEBUG_TYPE_POP_GROUP 0x826A
+ #define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+ #define GL_DEBUG_SEVERITY_NOTIFICATION 0x826b
+ #define GL_DEBUG_SEVERITY_LOW 0x9148
+ #define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+ #define GL_DEBUG_SEVERITY_HIGH 0x9146
+ #define GL_DEBUG_SOURCE_APPLICATION 0x824A
+ #define GL_DEBUG_SOURCE_OTHER 0x824b
+ #define GL_DEBUG_SOURCE_API 0x8246
+ #define GL_DEBUG_TYPE_ERROR 0x824C
+ #define GL_DEBUG_TYPE_OTHER 0x8251
+ #define GL_DEBUG_OUTPUT 0x92E0
+#endif
+
+
+class DebugCallback
+{
+public:
+ DebugCallback();
+ ~DebugCallback();
+
+ // Initialize must be called after the OpenGL context is created.
+ void Initialize();
+
+ // Shutdown must be called before the OpenGL context is destroyed.
+ void Shutdown();
+
+ enum Implementation
+ {
+ ImplementationNone,
+ ImplementationAMD, // Oldest version, deprecated by later versions.
+ ImplementationARB, // ARB version, deprecated by KHR version.
+ ImplementationKHR // OpenGL 4.3+ core profile version.
+ };
+
+ // Will return ImplementationNone until Initialize has been called, at which point it will return the version used.
+ Implementation GetImplementation() const;
+
+ // Maps to glEnable(GL_DEBUG_OUTPUT) when it is available, else does nothing. This controls debug output at the driver
+ // level and can be used, for example, to temporarily disable debug output that some other application entity enabled
+ // via glDebugMessageCallback. In practice this is available only when KHR_debug is available
+ void EnableGLDebug(bool enabled);
+
+ enum Severity // These are a mirror of the OpenGL types.
+ {
+ SeverityNone = 0,
+ SeverityNotification,
+ SeverityLow,
+ SeverityMedium,
+ SeverityHigh,
+ SeverityDisabled // When min severity is set to this level, it is never logged or assertion-failed.
+ };
+
+ // Set the severity required before we log or assert on a debug message. Default is SeverityHigh/SeverityHigh.
+ void SetMinSeverity(Severity minLogSeverity, Severity minAssertSeverity);
+
+ // Returns the debug callback currently used by OpenGL.
+ // This works for both ARB and KHR implementations. The same debug callback is used by OpenGL implementations for both.
+ // However, you can call GetImplementation to see which of the two we are using. This functionality is not available
+ // with the AMD implementation. Returns false and sets debugCallback and userParam to NULL if there is no existing callback.
+ bool GetGLDebugCallback(PFNGLDEBUGMESSAGECALLBACKPROC* debugCallback, const void** userParam) const;
+
+protected:
+ void DebugCallbackInternal(Severity s, const char* pSource, const char* pType, GLuint id, const char* pSeverity, const char* message);
+
+ // ARB and KHR debug handler
+ static void APIENTRY DebugMessageCallback(GLenum Source, GLenum Type, GLuint Id, GLenum Severity, GLsizei Length, const GLchar* Message, GLvoid* UserParam);
+ static const char* GetSource(GLenum Source);
+ static const char* GetType(GLenum Type);
+ static const char* GetSeverity(GLenum Severity);
+
+ // AMD handler
+ static void APIENTRY DebugMessageCallbackAMD(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam);
+ static const char* GetCategoryAMD(GLenum Category);
+
+protected:
+ bool Initialized;
+ int MinLogSeverity; // Minimum severity for us to log the event.
+ int MinAssertSeverity; // Minimum severity for us to assertion-fail the event.
+ PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback;
+ PFNGLDEBUGMESSAGECONTROLPROC glDebugMessageControl;
+ PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB; // glDebugMessageCallbackARB is the same as glDebugMessageCallback and may not need to be a separate variable.
+ PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB;
+ PFNGLDEBUGMESSAGECALLBACKAMDPROC glDebugMessageCallbackAMD;
+ PFNGLDEBUGMESSAGEENABLEAMDPROC glDebugMessageControlAMD;
+};
+
+
+
+
+
class RenderDevice;
class Buffer : public Render::Buffer
@@ -179,16 +352,17 @@ class Texture : public Render::Texture
public:
RenderDevice* Ren;
GLuint TexId;
- int Width, Height;
+ int Width, Height, Samples;
- Texture(RenderDevice* r, int w, int h);
+ Texture(RenderDevice* r, int w, int h, int samples);
~Texture();
virtual int GetWidth() const { return Width; }
virtual int GetHeight() const { return Height; }
+ virtual int GetSamples() const { return Samples; }
virtual void SetSampleMode(int);
- virtual ovrTexture Get_ovrTexture();
+ virtual ovrTexture Get_ovrTexture();
virtual void Set(int slot, ShaderStage stage = Shader_Fragment) const;
};
@@ -204,7 +378,7 @@ public:
Compile(src);
}
- ~Shader();
+ ~Shader();
bool Compile(const char* src);
GLenum GLStage() const
@@ -231,6 +405,8 @@ public:
String Name;
int Location, Size;
int Type; // currently number of floats in vector
+
+ Uniform() : Name(), Location(0), Size(0), Type(0){}
};
Array<Uniform> UniformInfo;
@@ -243,7 +419,7 @@ public:
~ShaderSet();
virtual void SetShader(Render::Shader *s);
- virtual void UnsetShader(int stage);
+ virtual void UnsetShader(int stage);
virtual void Set(PrimitiveType prim) const;
@@ -275,14 +451,15 @@ class RenderDevice : public Render::RenderDevice
Matrix4f Proj;
- GLuint Vao;
+ GLuint Vao;
protected:
Ptr<Texture> CurRenderTarget;
Array<Ptr<Texture> > DepthBuffers;
GLuint CurrentFbo;
+ GLuint MsaaFbo;
GLVersionAndExtensions GLVersionInfo;
-
+ DebugCallback DebugCallbackControl;
const LightingParams* Lighting;
public:
@@ -290,11 +467,11 @@ public:
virtual ~RenderDevice();
virtual void Shutdown();
-
+
virtual void FillTexturedRect(float left, float top, float right, float bottom, float ul, float vt, float ur, float vb, Color c, Ptr<OVR::Render::Texture> tex);
virtual void SetViewport(const Recti& vp);
-
+
virtual void WaitUntilGpuIdle();
virtual void Flush();
@@ -308,6 +485,8 @@ public:
Texture* GetDepthBuffer(int w, int h, int ms);
+ virtual void ResolveMsaa(OVR::Render::Texture* msaaTex, OVR::Render::Texture* outputTex) OVR_OVERRIDE;
+
virtual void Present (bool withVsync){OVR_UNUSED(withVsync);};
virtual void SetRenderTarget(Render::Texture* color,
Render::Texture* depth = NULL, Render::Texture* stencil = NULL);
@@ -332,6 +511,7 @@ public:
};
+
}}}
#endif
diff --git a/Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp b/Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp
index b2e2e10..465d16e 100644
--- a/Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp
+++ b/Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp
@@ -5,7 +5,7 @@ Content : Win32 OpenGL Device implementation
Created : September 10, 2012
Authors : Andrew Reisse, Michael Antonov, David Borel
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -55,12 +55,16 @@ Render::RenderDevice* RenderDevice::CreateDevice(const RendererParams& rp, void*
if (!DwmEnableComposition)
{
- HINSTANCE hInst = LoadLibrary( L"dwmapi.dll" );
+ HINSTANCE hInst = LoadLibraryA( "dwmapi.dll" );
OVR_ASSERT(hInst);
DwmEnableComposition = (PFNDWMENABLECOMPOSITIONPROC)GetProcAddress( hInst, "DwmEnableComposition" );
OVR_ASSERT(DwmEnableComposition);
}
+ // Why do we need to disable composition for OpenGL rendering?
+ // "Enabling DWM in extended mode causes 60Hz judder on NVIDIA cards unless the Rift is the main display. "
+ // "Maybe the confusion is that GL goes through the same compositional pipeline as DX. To the kernel and DWM there is no difference between the two."
+ // "The judder does not occur with DX. My understanding is that for DWM, GL actually requires an additional blt whose timing is dependent on the main monitor."
DwmEnableComposition(DWM_EC_DISABLECOMPOSITION);
{
PIXELFORMATDESCRIPTOR pfd;
diff --git a/Samples/CommonSrc/Render/Render_GL_Win32_Device.h b/Samples/CommonSrc/Render/Render_GL_Win32_Device.h
index 14d0b65..48046bd 100644
--- a/Samples/CommonSrc/Render/Render_GL_Win32_Device.h
+++ b/Samples/CommonSrc/Render/Render_GL_Win32_Device.h
@@ -5,7 +5,7 @@ Content : Win32 OpenGL Device implementation header
Created : September 10, 2012
Authors : Andrew Reisse, Michael Antonov, David Borel
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/Samples/CommonSrc/Render/Render_LoadTextureDDS.cpp b/Samples/CommonSrc/Render/Render_LoadTextureDDS.cpp
index 08dda43..136a1d2 100644
--- a/Samples/CommonSrc/Render/Render_LoadTextureDDS.cpp
+++ b/Samples/CommonSrc/Render/Render_LoadTextureDDS.cpp
@@ -5,7 +5,7 @@ Content : A DDS file loader for cross-platform compressed texture support.
Created : March 5, 2013
Authors : Peter Hoff, Dan Goodman, Bryan Croteau
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/Samples/CommonSrc/Render/Render_LoadTextureTGA.cpp b/Samples/CommonSrc/Render/Render_LoadTextureTGA.cpp
index 7c80c88..bdb5804 100644
--- a/Samples/CommonSrc/Render/Render_LoadTextureTGA.cpp
+++ b/Samples/CommonSrc/Render/Render_LoadTextureTGA.cpp
@@ -5,7 +5,7 @@ Content : Loading of TGA implementation
Created : October, 2012
Authors : Andrew Reisse
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/Samples/CommonSrc/Render/Render_XmlSceneLoader.cpp b/Samples/CommonSrc/Render/Render_XmlSceneLoader.cpp
index 0eea8eb..d011ee9 100644
--- a/Samples/CommonSrc/Render/Render_XmlSceneLoader.cpp
+++ b/Samples/CommonSrc/Render/Render_XmlSceneLoader.cpp
@@ -5,7 +5,7 @@ Content : Imports and exports XML files - implementation
Created : January 21, 2013
Authors : Robotic Arm Software - Peter Hoff, Dan Goodman, Bryan Croteau
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -26,7 +26,12 @@ limitations under the License.
namespace OVR { namespace Render {
-XmlHandler::XmlHandler() : pXmlDocument(NULL)
+XmlHandler::XmlHandler() :
+ pXmlDocument(NULL),
+ textureCount(0),
+ modelCount(0),
+ collisionModelCount(0),
+ groundCollisionModelCount(0)
{
pXmlDocument = new tinyxml2::XMLDocument();
}
@@ -63,6 +68,7 @@ bool XmlHandler::ReadFile(const char* fileName, OVR::Render::RenderDevice* pRend
// Load the textures
OVR_DEBUG_LOG_TEXT(("Loading textures..."));
XMLElement* pXmlTexture = pXmlDocument->FirstChildElement("scene")->FirstChildElement("textures");
+ OVR_ASSERT(pXmlTexture);
if (pXmlTexture)
{
pXmlTexture->QueryIntAttribute("count", &textureCount);
@@ -299,61 +305,68 @@ bool XmlHandler::ReadFile(const char* fileName, OVR::Render::RenderDevice* pRend
{
Ptr<CollisionModel> cm = *new CollisionModel();
int planeCount = 0;
- pXmlCollisionModel->QueryIntAttribute("planeCount", &planeCount);
-
- pXmlPlane = pXmlCollisionModel->FirstChildElement("plane");
- for(int j = 0; j < planeCount; ++j)
+
+ OVR_ASSERT(pXmlCollisionModel != NULL); // collisionModelCount should guarantee this.
+ if (pXmlCollisionModel)
{
- Vector3f norm;
- pXmlPlane->QueryFloatAttribute("nx", &norm.x);
- pXmlPlane->QueryFloatAttribute("ny", &norm.y);
- pXmlPlane->QueryFloatAttribute("nz", &norm.z);
- float D;
- pXmlPlane->QueryFloatAttribute("d", &D);
- D -= 0.5f;
- if (i == 26)
- D += 0.5f; // tighten the terrace collision so player can move right up to rail
- Planef p(norm.z, norm.y, norm.x * -1.0f, D);
- cm->Add(p);
- pXmlPlane = pXmlPlane->NextSiblingElement("plane");
- }
+ pXmlCollisionModel->QueryIntAttribute("planeCount", &planeCount);
+
+ pXmlPlane = pXmlCollisionModel->FirstChildElement("plane");
+ for(int j = 0; j < planeCount; ++j)
+ {
+ Vector3f norm;
+ pXmlPlane->QueryFloatAttribute("nx", &norm.x);
+ pXmlPlane->QueryFloatAttribute("ny", &norm.y);
+ pXmlPlane->QueryFloatAttribute("nz", &norm.z);
+ float D;
+ pXmlPlane->QueryFloatAttribute("d", &D);
+ D -= 0.5f;
+ if (i == 26)
+ D += 0.5f; // tighten the terrace collision so player can move right up to rail
+ Planef p(norm.z, norm.y, norm.x * -1.0f, D);
+ cm->Add(p);
+ pXmlPlane = pXmlPlane->NextSiblingElement("plane");
+ }
- pCollisions->PushBack(cm);
- pXmlCollisionModel = pXmlCollisionModel->NextSiblingElement("collisionModel");
+ pCollisions->PushBack(cm);
+ pXmlCollisionModel = pXmlCollisionModel->NextSiblingElement("collisionModel");
+ }
}
OVR_DEBUG_LOG(("done."));
//load the ground collision models
OVR_DEBUG_LOG(("Loading ground collision models..."));
pXmlCollisionModel = pXmlDocument->FirstChildElement("scene")->FirstChildElement("groundCollisionModels");
+ OVR_ASSERT(pXmlCollisionModel);
if (pXmlCollisionModel)
{
pXmlCollisionModel->QueryIntAttribute("count", &groundCollisionModelCount);
pXmlCollisionModel = pXmlCollisionModel->FirstChildElement("collisionModel");
- }
- pXmlPlane = NULL;
- for(int i = 0; i < groundCollisionModelCount; ++i)
- {
- Ptr<CollisionModel> cm = *new CollisionModel();
- int planeCount = 0;
- pXmlCollisionModel->QueryIntAttribute("planeCount", &planeCount);
- pXmlPlane = pXmlCollisionModel->FirstChildElement("plane");
- for(int j = 0; j < planeCount; ++j)
+ pXmlPlane = NULL;
+ for (int i = 0; i < groundCollisionModelCount; ++i)
{
- Vector3f norm;
- pXmlPlane->QueryFloatAttribute("nx", &norm.x);
- pXmlPlane->QueryFloatAttribute("ny", &norm.y);
- pXmlPlane->QueryFloatAttribute("nz", &norm.z);
- float D;
- pXmlPlane->QueryFloatAttribute("d", &D);
- Planef p(norm.z, norm.y, norm.x * -1.0f, D);
- cm->Add(p);
- pXmlPlane = pXmlPlane->NextSiblingElement("plane");
- }
+ Ptr<CollisionModel> cm = *new CollisionModel();
+ int planeCount = 0;
+ pXmlCollisionModel->QueryIntAttribute("planeCount", &planeCount);
- pGroundCollisions->PushBack(cm);
- pXmlCollisionModel = pXmlCollisionModel->NextSiblingElement("collisionModel");
+ pXmlPlane = pXmlCollisionModel->FirstChildElement("plane");
+ for (int j = 0; j < planeCount; ++j)
+ {
+ Vector3f norm;
+ pXmlPlane->QueryFloatAttribute("nx", &norm.x);
+ pXmlPlane->QueryFloatAttribute("ny", &norm.y);
+ pXmlPlane->QueryFloatAttribute("nz", &norm.z);
+ float D = 0.f;
+ pXmlPlane->QueryFloatAttribute("d", &D);
+ Planef p(norm.z, norm.y, norm.x * -1.0f, D);
+ cm->Add(p);
+ pXmlPlane = pXmlPlane->NextSiblingElement("plane");
+ }
+
+ pGroundCollisions->PushBack(cm);
+ pXmlCollisionModel = pXmlCollisionModel->NextSiblingElement("collisionModel");
+ }
}
OVR_DEBUG_LOG(("done."));
return true;
diff --git a/Samples/CommonSrc/Render/Render_XmlSceneLoader.h b/Samples/CommonSrc/Render/Render_XmlSceneLoader.h
index 22c9ccd..94a2219 100644
--- a/Samples/CommonSrc/Render/Render_XmlSceneLoader.h
+++ b/Samples/CommonSrc/Render/Render_XmlSceneLoader.h
@@ -5,7 +5,7 @@ Content : Imports and exports XML files
Created : January 21, 2013
Authors : Robotic Arm Software - Peter Hoff, Dan Goodman, Bryan Croteau
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/Samples/CommonSrc/Util/OptionMenu.cpp b/Samples/CommonSrc/Util/OptionMenu.cpp
index 2d3c3d0..b2cc0c9 100644
--- a/Samples/CommonSrc/Util/OptionMenu.cpp
+++ b/Samples/CommonSrc/Util/OptionMenu.cpp
@@ -5,7 +5,7 @@ Content : Option selection and editing for OculusWorldDemo
Created : March 7, 2014
Authors : Michael Antonov, Caleb Leak
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -150,6 +150,7 @@ OptionVar::OptionVar(const char* name, void* pvar, VarType type,
ShortcutDown.pNotify = new FunctionNotifyContext<OptionVar, bool>(this, &OptionVar::PrevValue);
}
+
OptionVar::OptionVar(const char* name, int32_t* pvar,
int32_t min, int32_t max, int32_t stepSize,
const char* formatString,
@@ -164,6 +165,11 @@ OptionVar::OptionVar(const char* name, int32_t* pvar,
pNotify = 0;
FormatString= formatString;
+ MaxFloat = MATH_FLOAT_MAXVALUE;
+ MinFloat = -MATH_FLOAT_MAXVALUE;
+ StepFloat = 1.0f;
+ FormatScale = 1.0f;
+
MinInt = min;
MaxInt = max;
StepInt = stepSize;
@@ -194,6 +200,10 @@ OptionVar::OptionVar(const char* name, float* pvar,
StepFloat = stepSize;
FormatScale = formatScale;
+ MaxInt = 0x7FFFFFFF;
+ MinInt = -(MaxInt) - 1;
+ StepInt = 1;
+
SelectedIndex = 0;
ShortcutUp.pNotify = new FunctionNotifyContext<OptionVar, bool>(this, &OptionVar::NextValue);
@@ -243,9 +253,12 @@ void OptionVar::PrevValue(bool* pFastStep)
switch (Type)
{
case Type_Enum:
- *AsInt() = ((GetEnumIndex() + (uint32_t)EnumValues.GetSize() - 1) % EnumValues.GetSize());
+ {
+ uint32_t size = (uint32_t)(EnumValues.GetSize() ? EnumValues.GetSize() : 1);
+ *AsInt() = ((GetEnumIndex() + (size - 1)) % size);
break;
-
+ }
+
case Type_Int:
*AsInt() = Alg::Max<int32_t>(*AsInt() - StepInt * (fastStep ? 5 : 1), MinInt);
break;
diff --git a/Samples/CommonSrc/Util/OptionMenu.h b/Samples/CommonSrc/Util/OptionMenu.h
index 5eea9bd..0c3c289 100644
--- a/Samples/CommonSrc/Util/OptionMenu.h
+++ b/Samples/CommonSrc/Util/OptionMenu.h
@@ -5,7 +5,7 @@ Content : Option selection and editing for OculusWorldDemo
Created : March 7, 2014
Authors : Michael Antonov, Caleb Leak
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/Samples/CommonSrc/Util/RenderProfiler.cpp b/Samples/CommonSrc/Util/RenderProfiler.cpp
index 00bbdd9..cc617ff 100644
--- a/Samples/CommonSrc/Util/RenderProfiler.cpp
+++ b/Samples/CommonSrc/Util/RenderProfiler.cpp
@@ -5,7 +5,7 @@ Content : Profiling for render.
Created : March 10, 2014
Authors : Caleb Leak
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -76,18 +76,19 @@ void RenderProfiler::DrawOverlay(RenderDevice* prender)
const double* averages = GetAverages();
const double* lastSampleSet = GetLastSampleSet();
- for ( int timerNum = 1; timerNum < Sample_LAST; timerNum++ )
+ static_assert((Sample_FrameStart == 0) && (Sample_AfterGameProcessing == 1) && (Sample_AfterPresent + 1 == Sample_LAST), "The following code depends on SampleType enum values.");
+
+ for ( int timerNum = Sample_AfterGameProcessing; timerNum < Sample_LAST; timerNum++ )
{
char const *pName = "";
switch ( timerNum )
{
case Sample_AfterGameProcessing: pName = "AfterGameProcessing"; break;
case Sample_AfterEyeRender : pName = "AfterEyeRender "; break;
-// case Sample_BeforeDistortion : pName = "BeforeDistortion "; break;
-// case Sample_AfterDistortion : pName = "AfterDistortion "; break;
+ //case Sample_BeforeDistortion : pName = "BeforeDistortion "; break; This enumerant is currently disabled in the enumeration declaration.
+ //case Sample_AfterDistortion : pName = "AfterDistortion "; break;
case Sample_AfterPresent : pName = "AfterPresent "; break;
-// case Sample_AfterFlush : pName = "AfterFlush "; break;
- default: OVR_ASSERT ( false );
+ //case Sample_AfterFlush : pName = "AfterFlush "; break;
}
char bufTemp[256];
OVR_sprintf ( bufTemp, sizeof(bufTemp), "\nRaw: %.2lfms\t400Ave: %.2lfms\t800%s",
diff --git a/Samples/CommonSrc/Util/RenderProfiler.h b/Samples/CommonSrc/Util/RenderProfiler.h
index 7494034..84e5013 100644
--- a/Samples/CommonSrc/Util/RenderProfiler.h
+++ b/Samples/CommonSrc/Util/RenderProfiler.h
@@ -5,7 +5,7 @@ Content : Profiling for render.
Created : March 10, 2014
Authors : Caleb Leak
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2012 Oculus VR, LLC All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -43,10 +43,10 @@ public:
Sample_FrameStart ,
Sample_AfterGameProcessing ,
Sample_AfterEyeRender ,
- // Sample_BeforeDistortion ,
- // Sample_AfterDistortion ,
+ //Sample_BeforeDistortion ,
+ //Sample_AfterDistortion ,
Sample_AfterPresent ,
- // Sample_AfterFlush ,
+ //Sample_AfterFlush ,
Sample_LAST
};