mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 19:55:07 +02:00
Merge pull request #8164 from SamGondelman/macHMDPreview
Added Mac preview image if VSync is enabled
This commit is contained in:
commit
abcd1e0062
7 changed files with 152 additions and 36 deletions
BIN
interface/resources/images/preview.png
Normal file
BIN
interface/resources/images/preview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 110 KiB |
|
@ -16,6 +16,9 @@
|
|||
#include <QtOpenGL/QGLWidget>
|
||||
#include <QtGui/QImage>
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
#include <OpenGL/CGLCurrent.h>
|
||||
#endif
|
||||
#include <gl/QOpenGLContextWrapper.h>
|
||||
#include <gpu/Texture.h>
|
||||
#include <gl/GLWidget.h>
|
||||
|
@ -612,8 +615,14 @@ void OpenGLDisplayPlugin::enableVsync(bool enable) {
|
|||
if (!_vsyncSupported) {
|
||||
return;
|
||||
}
|
||||
#ifdef Q_OS_WIN
|
||||
#if defined(Q_OS_WIN)
|
||||
wglSwapIntervalEXT(enable ? 1 : 0);
|
||||
#elif defined(Q_OS_MAC)
|
||||
GLint interval = enable ? 1 : 0;
|
||||
CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &interval);
|
||||
#else
|
||||
// TODO: Fill in for linux
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -621,9 +630,14 @@ bool OpenGLDisplayPlugin::isVsyncEnabled() {
|
|||
if (!_vsyncSupported) {
|
||||
return true;
|
||||
}
|
||||
#ifdef Q_OS_WIN
|
||||
#if defined(Q_OS_WIN)
|
||||
return wglGetSwapIntervalEXT() != 0;
|
||||
#elif defined(Q_OS_MAC)
|
||||
GLint interval;
|
||||
CGLGetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &interval);
|
||||
return interval != 0;
|
||||
#else
|
||||
// TODO: Fill in for linux
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -21,6 +21,11 @@
|
|||
#include <gl/GLWidget.h>
|
||||
#include <shared/NsightHelpers.h>
|
||||
|
||||
#include <gpu/DrawUnitQuadTexcoord_vert.h>
|
||||
#include <gpu/DrawTexture_frag.h>
|
||||
|
||||
#include <PathUtils.h>
|
||||
|
||||
#include "../Logging.h"
|
||||
#include "../CompositorHelper.h"
|
||||
|
||||
|
@ -58,9 +63,33 @@ bool HmdDisplayPlugin::internalActivate() {
|
|||
_eyeInverseProjections[eye] = glm::inverse(_eyeProjections[eye]);
|
||||
});
|
||||
|
||||
if (_previewTextureID == 0) {
|
||||
QImage previewTexture(PathUtils::resourcesPath() + "images/preview.png");
|
||||
if (!previewTexture.isNull()) {
|
||||
glGenTextures(1, &_previewTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _previewTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, previewTexture.width(), previewTexture.height(), 0,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE, previewTexture.mirrored(false, true).bits());
|
||||
using namespace oglplus;
|
||||
Texture::MinFilter(TextureTarget::_2D, TextureMinFilter::Linear);
|
||||
Texture::MagFilter(TextureTarget::_2D, TextureMagFilter::Linear);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
_previewAspect = ((float)previewTexture.width())/((float)previewTexture.height());
|
||||
_firstPreview = true;
|
||||
}
|
||||
}
|
||||
|
||||
return Parent::internalActivate();
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::internalDeactivate() {
|
||||
if (_previewTextureID != 0) {
|
||||
glDeleteTextures(1, &_previewTextureID);
|
||||
_previewTextureID = 0;
|
||||
}
|
||||
Parent::internalDeactivate();
|
||||
}
|
||||
|
||||
|
||||
static const char * REPROJECTION_VS = R"VS(#version 410 core
|
||||
in vec3 Position;
|
||||
|
@ -196,6 +225,7 @@ static ProgramPtr getReprojectionProgram() {
|
|||
}
|
||||
#endif
|
||||
|
||||
static GLint PREVIEW_TEXTURE_LOCATION = -1;
|
||||
|
||||
static const char * LASER_VS = R"VS(#version 410 core
|
||||
uniform mat4 mvp = mat4(1);
|
||||
|
@ -227,14 +257,24 @@ void main() {
|
|||
void HmdDisplayPlugin::customizeContext() {
|
||||
Parent::customizeContext();
|
||||
// Only enable mirroring if we know vsync is disabled
|
||||
// On Mac, this won't work due to how the contexts are handled, so don't try
|
||||
#if !defined(Q_OS_MAC)
|
||||
enableVsync(false);
|
||||
#endif
|
||||
_enablePreview = !isVsyncEnabled();
|
||||
_sphereSection = loadSphereSection(_program, CompositorHelper::VIRTUAL_UI_TARGET_FOV.y, CompositorHelper::VIRTUAL_UI_ASPECT_RATIO);
|
||||
compileProgram(_laserProgram, LASER_VS, LASER_FS);
|
||||
_laserGeometry = loadLaser(_laserProgram);
|
||||
compileProgram(_reprojectionProgram, REPROJECTION_VS, REPROJECTION_FS);
|
||||
|
||||
using namespace oglplus;
|
||||
if (!_enablePreview) {
|
||||
const std::string version("#version 410 core\n");
|
||||
compileProgram(_previewProgram, version + DrawUnitQuadTexcoord_vert, version + DrawTexture_frag);
|
||||
PREVIEW_TEXTURE_LOCATION = Uniform<int>(*_previewProgram, "colorMap").Location();
|
||||
}
|
||||
|
||||
compileProgram(_laserProgram, LASER_VS, LASER_FS);
|
||||
_laserGeometry = loadLaser(_laserProgram);
|
||||
|
||||
compileProgram(_reprojectionProgram, REPROJECTION_VS, REPROJECTION_FS);
|
||||
REPROJECTION_MATRIX_LOCATION = Uniform<glm::mat3>(*_reprojectionProgram, "reprojection").Location();
|
||||
INVERSE_PROJECTION_MATRIX_LOCATION = Uniform<glm::mat4>(*_reprojectionProgram, "inverseProjections").Location();
|
||||
PROJECTION_MATRIX_LOCATION = Uniform<glm::mat4>(*_reprojectionProgram, "projections").Location();
|
||||
|
@ -243,6 +283,7 @@ void HmdDisplayPlugin::customizeContext() {
|
|||
void HmdDisplayPlugin::uncustomizeContext() {
|
||||
_sphereSection.reset();
|
||||
_compositeFramebuffer.reset();
|
||||
_previewProgram.reset();
|
||||
_reprojectionProgram.reset();
|
||||
_laserProgram.reset();
|
||||
_laserGeometry.reset();
|
||||
|
@ -335,30 +376,32 @@ void HmdDisplayPlugin::internalPresent() {
|
|||
hmdPresent();
|
||||
|
||||
// screen preview mirroring
|
||||
auto window = _container->getPrimaryWidget();
|
||||
auto devicePixelRatio = window->devicePixelRatio();
|
||||
auto windowSize = toGlm(window->size());
|
||||
windowSize *= devicePixelRatio;
|
||||
float windowAspect = aspect(windowSize);
|
||||
float sceneAspect = _enablePreview ? aspect(_renderTargetSize) : _previewAspect;
|
||||
if (_enablePreview && _monoPreview) {
|
||||
sceneAspect /= 2.0f;
|
||||
}
|
||||
float aspectRatio = sceneAspect / windowAspect;
|
||||
|
||||
uvec2 targetViewportSize = windowSize;
|
||||
if (aspectRatio < 1.0f) {
|
||||
targetViewportSize.x *= aspectRatio;
|
||||
} else {
|
||||
targetViewportSize.y /= aspectRatio;
|
||||
}
|
||||
|
||||
uvec2 targetViewportPosition;
|
||||
if (targetViewportSize.x < windowSize.x) {
|
||||
targetViewportPosition.x = (windowSize.x - targetViewportSize.x) / 2;
|
||||
} else if (targetViewportSize.y < windowSize.y) {
|
||||
targetViewportPosition.y = (windowSize.y - targetViewportSize.y) / 2;
|
||||
}
|
||||
|
||||
if (_enablePreview) {
|
||||
auto window = _container->getPrimaryWidget();
|
||||
auto windowSize = toGlm(window->size());
|
||||
float windowAspect = aspect(windowSize);
|
||||
float sceneAspect = aspect(_renderTargetSize);
|
||||
if (_monoPreview) {
|
||||
sceneAspect /= 2.0f;
|
||||
}
|
||||
float aspectRatio = sceneAspect / windowAspect;
|
||||
|
||||
uvec2 targetViewportSize = windowSize;
|
||||
if (aspectRatio < 1.0f) {
|
||||
targetViewportSize.x *= aspectRatio;
|
||||
} else {
|
||||
targetViewportSize.y /= aspectRatio;
|
||||
}
|
||||
|
||||
uvec2 targetViewportPosition;
|
||||
if (targetViewportSize.x < windowSize.x) {
|
||||
targetViewportPosition.x = (windowSize.x - targetViewportSize.x) / 2;
|
||||
} else if (targetViewportSize.y < windowSize.y) {
|
||||
targetViewportPosition.y = (windowSize.y - targetViewportSize.y) / 2;
|
||||
}
|
||||
|
||||
using namespace oglplus;
|
||||
Context::Clear().ColorBuffer();
|
||||
auto sourceSize = _compositeFramebuffer->size;
|
||||
|
@ -373,6 +416,21 @@ void HmdDisplayPlugin::internalPresent() {
|
|||
BufferSelectBit::ColorBuffer, BlitFilter::Nearest);
|
||||
});
|
||||
swapBuffers();
|
||||
} else if (_firstPreview || windowSize != _prevWindowSize || devicePixelRatio != _prevDevicePixelRatio) {
|
||||
useProgram(_previewProgram);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glViewport(targetViewportPosition.x, targetViewportPosition.y, targetViewportSize.x, targetViewportSize.y);
|
||||
glUniform1i(PREVIEW_TEXTURE_LOCATION, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, _previewTextureID);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
swapBuffers();
|
||||
_firstPreview = false;
|
||||
_prevWindowSize = windowSize;
|
||||
_prevDevicePixelRatio = devicePixelRatio;
|
||||
}
|
||||
|
||||
postPreview();
|
||||
|
|
|
@ -40,6 +40,7 @@ protected:
|
|||
virtual void updatePresentPose();
|
||||
|
||||
bool internalActivate() override;
|
||||
void internalDeactivate() override;
|
||||
void compositeScene() override;
|
||||
void compositeOverlay() override;
|
||||
void compositePointer() override;
|
||||
|
@ -89,8 +90,17 @@ private:
|
|||
bool _enablePreview { false };
|
||||
bool _monoPreview { true };
|
||||
bool _enableReprojection { true };
|
||||
ShapeWrapperPtr _sphereSection;
|
||||
bool _firstPreview { true };
|
||||
|
||||
ProgramPtr _previewProgram;
|
||||
float _previewAspect { 0 };
|
||||
GLuint _previewTextureID { 0 };
|
||||
glm::uvec2 _prevWindowSize { 0, 0 };
|
||||
qreal _prevDevicePixelRatio { 0 };
|
||||
|
||||
ProgramPtr _reprojectionProgram;
|
||||
ShapeWrapperPtr _sphereSection;
|
||||
|
||||
ProgramPtr _laserProgram;
|
||||
ShapeWrapperPtr _laserGeometry;
|
||||
};
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glext.h>
|
||||
#include <OpenGL/OpenGL.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -47,13 +47,16 @@ void GLWidget::initializeGL() {
|
|||
// Note, we *DO NOT* want Qt to automatically swap buffers for us. This results in the "ringing" bug mentioned in WL#19514 when we're throttling the framerate.
|
||||
setAutoBufferSwap(false);
|
||||
|
||||
// TODO: write the proper code for linux
|
||||
makeCurrent();
|
||||
#if defined(Q_OS_WIN)
|
||||
if (isValid() && context() && context()->contextHandle()) {
|
||||
_vsyncSupported = context()->contextHandle()->hasExtension("WGL_EXT_swap_control");;
|
||||
}
|
||||
#if defined(Q_OS_WIN)
|
||||
_vsyncSupported = context()->contextHandle()->hasExtension("WGL_EXT_swap_control");
|
||||
#elif defined(Q_OS_MAC)
|
||||
_vsyncSupported = true;
|
||||
#else
|
||||
// TODO: write the proper code for linux
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void GLWidget::paintEvent(QPaintEvent* event) {
|
||||
|
|
|
@ -68,18 +68,48 @@ bool OculusLegacyDisplayPlugin::isSupported() const {
|
|||
}
|
||||
|
||||
auto hmd = ovrHmd_Create(0);
|
||||
|
||||
// The Oculus SDK seems to have trouble finding the right screen sometimes, so we have to guess
|
||||
// Guesses, in order of best match:
|
||||
// - resolution and position match
|
||||
// - resolution and one component of position match
|
||||
// - resolution matches
|
||||
// - position matches
|
||||
// If it still picks the wrong screen, you'll have to mess with your monitor configuration
|
||||
QList<int> matches({ -1, -1, -1, -1 });
|
||||
if (hmd) {
|
||||
QPoint targetPosition{ hmd->WindowsPos.x, hmd->WindowsPos.y };
|
||||
QSize targetResolution{ hmd->Resolution.w, hmd->Resolution.h };
|
||||
auto screens = qApp->screens();
|
||||
for(int i = 0; i < screens.size(); ++i) {
|
||||
auto screen = screens[i];
|
||||
QPoint position = screen->geometry().topLeft();
|
||||
if (position == targetPosition) {
|
||||
_hmdScreen = i;
|
||||
break;
|
||||
QSize resolution = screen->geometry().size();
|
||||
|
||||
if (position == targetPosition && resolution == targetResolution) {
|
||||
matches[0] = i;
|
||||
} else if ((position.x() == targetPosition.x() || position.y() == targetPosition.y()) &&
|
||||
resolution == targetResolution) {
|
||||
matches[1] = i;
|
||||
} else if (resolution == targetResolution) {
|
||||
matches[2] = i;
|
||||
} else if (position == targetPosition) {
|
||||
matches[3] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int screen : matches) {
|
||||
if (screen != -1) {
|
||||
_hmdScreen = screen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_hmdScreen == -1) {
|
||||
qDebug() << "Could not find Rift screen";
|
||||
result = false;
|
||||
}
|
||||
|
||||
ovr_Shutdown();
|
||||
return result;
|
||||
|
|
Loading…
Reference in a new issue