summaryrefslogtreecommitdiffstats
path: root/src/Authoring/Qt3DStudio/Render/WGLRenderContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Authoring/Qt3DStudio/Render/WGLRenderContext.cpp')
-rw-r--r--src/Authoring/Qt3DStudio/Render/WGLRenderContext.cpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/Authoring/Qt3DStudio/Render/WGLRenderContext.cpp b/src/Authoring/Qt3DStudio/Render/WGLRenderContext.cpp
new file mode 100644
index 00000000..57428631
--- /dev/null
+++ b/src/Authoring/Qt3DStudio/Render/WGLRenderContext.cpp
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSCommonPrecompile.h"
+
+#include "WGLRenderContext.h"
+#include "foundation/TrackingAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "render/Qt3DSRenderContext.h"
+#include "EASTL/string.h"
+#include "foundation/Qt3DSLogging.h"
+
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QSurfaceFormat>
+#include <QtWidgets/qopenglwidget.h>
+
+//QT3DS_DEFINE_THISFILE;
+
+//=============================================================================
+/**
+ * Constructor: Creates the object
+ */
+CWGLRenderContext::CWGLRenderContext(Qt3DSWindow inWindow)
+ : m_qtContext(0)
+ , m_Foundation(Q3DStudio::Foundation::SStudioFoundation::Create())
+{
+ Open(inWindow);
+}
+
+//=============================================================================
+/**
+ * Destructor: Destroys the object.
+ */
+CWGLRenderContext::~CWGLRenderContext()
+{
+ Close();
+}
+
+//=============================================================================
+/**
+ * Open the render context.
+ * @param inRenderWindow window handle
+ * @param inWindowSize window size
+ */
+void CWGLRenderContext::Open(Qt3DSWindow inRenderWindow)
+{
+ // needed because NVidia cards will fail all the system functions below if there is no window.
+ // note: the only time inRenderWindow is nullptr is when CThumbnailGenerator is used. Bug3075.
+ if (!inRenderWindow)
+ return;
+
+ QObject* qObject = static_cast<QObject*>(inRenderWindow);
+ QOpenGLWidget* qRenderWidget = qobject_cast<QOpenGLWidget*>(qObject);
+ Q_ASSERT(qRenderWidget);
+
+ OpenNormalContext(qRenderWidget);
+}
+
+static bool compareContextVersion(QSurfaceFormat a, QSurfaceFormat b)
+{
+ if (a.renderableType() != b.renderableType())
+ return false;
+ if (a.majorVersion() != b.majorVersion())
+ return false;
+ if (a.minorVersion() > b.minorVersion())
+ return false;
+ return true;
+}
+
+QSurfaceFormat CWGLRenderContext::selectSurfaceFormat(QOpenGLWidget *window)
+{
+#if defined(Q_OS_MACOS)
+ Q_UNUSED(window)
+ QSurfaceFormat openGL33Format;
+ openGL33Format.setRenderableType(QSurfaceFormat::OpenGL);
+ openGL33Format.setProfile(QSurfaceFormat::CoreProfile);
+ openGL33Format.setMajorVersion(3);
+ openGL33Format.setMinorVersion(3);
+ openGL33Format.setStencilBufferSize(8);
+ QSurfaceFormat::setDefaultFormat(openGL33Format);
+ return openGL33Format;
+#else
+ struct ContextVersion {
+ int major;
+ int minor;
+ qt3ds::render::NVRenderContextType contextType;
+ };
+
+ ContextVersion versions[] = {
+ {4, 5, qt3ds::render::NVRenderContextValues::GL4},
+ {4, 4, qt3ds::render::NVRenderContextValues::GL4},
+ {4, 3, qt3ds::render::NVRenderContextValues::GL4},
+ {4, 2, qt3ds::render::NVRenderContextValues::GL4},
+ {4, 1, qt3ds::render::NVRenderContextValues::GL4},
+ {3, 3, qt3ds::render::NVRenderContextValues::GL3},
+ {2, 1, qt3ds::render::NVRenderContextValues::GL2},
+ {2, 0, qt3ds::render::NVRenderContextValues::GLES2},
+ {0, 0, qt3ds::render::NVRenderContextValues::NullContext}
+ };
+
+ QSurfaceFormat result = window->format();
+ bool valid = false;
+
+ for (const auto& ver : versions) {
+ if (ver.contextType == qt3ds::render::NVRenderContextValues::NullContext)
+ break;
+
+ // make an offscreen surface + context to query version
+ QScopedPointer<QOffscreenSurface> offscreenSurface(new QOffscreenSurface);
+
+ QSurfaceFormat format = window->format();
+ if (ver.contextType == qt3ds::render::NVRenderContextValues::GLES2) {
+ format.setRenderableType(QSurfaceFormat::OpenGLES);
+ } else {
+ format.setRenderableType(QSurfaceFormat::OpenGL);
+ if (ver.major >= 2)
+ format.setProfile(QSurfaceFormat::CoreProfile);
+ }
+ format.setMajorVersion(ver.major);
+ format.setMinorVersion(ver.minor);
+ format.setDepthBufferSize(24);
+ format.setStencilBufferSize(8);
+
+ offscreenSurface->setFormat(format);
+ offscreenSurface->create();
+ Q_ASSERT(offscreenSurface->isValid());
+
+ QScopedPointer<QOpenGLContext> queryContext(new QOpenGLContext);
+ queryContext->setFormat(format);
+ if (queryContext->create() && compareContextVersion(format, queryContext->format())) {
+ valid = true;
+ result = format;
+ break;
+ }
+ } // of version test iteration
+
+ if (!valid) {
+ qFatal("Unable to select suitable OpenGL context");
+ }
+
+ qDebug() << Q_FUNC_INFO << "selected surface format:" << result;
+ QSurfaceFormat::setDefaultFormat(result);
+ return result;
+#endif
+}
+
+//=============================================================================
+/**
+ * Open a non-multisample render context.
+ * @param inRenderWindow window handle
+ * @param inWindowSize window size
+ * @param inPixelDesc the pixel descriptor struct
+ */
+void CWGLRenderContext::OpenNormalContext(QOpenGLWidget* inRenderWindow)
+{
+ // Close before trying to open
+ Close();
+
+ // Save off the window
+ m_Window = inRenderWindow;
+ m_qtContext = m_Window->context();
+ Q_ASSERT(m_qtContext);
+
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::foundation::IStringTable> theStringTable =
+ qt3ds::foundation::IStringTable::CreateStringTable(*m_Foundation.m_AllocatorCallback);
+ QSurfaceFormat contextFormat = m_qtContext->format();
+ m_RenderContext = NVScopedRefCounted<NVRenderContext>(
+ NVRenderContext::CreateGL(*m_Foundation.m_Foundation, *theStringTable,
+ contextFormat));
+ if (m_RenderContext) {
+ m_RenderContext->SetDefaultDepthBufferBitCount(contextFormat.depthBufferSize());
+ m_RenderContext->SetDefaultRenderTarget(inRenderWindow->defaultFramebufferObject());
+ }
+}
+
+//=============================================================================
+/**
+ * Close the render context.
+ */
+void CWGLRenderContext::Close()
+{
+ m_qtContext = 0;
+}
+
+//=============================================================================
+/**
+ * Prepare the render context to begin rendering.
+ */
+void CWGLRenderContext::BeginRender()
+{
+ m_Window->makeCurrent();
+ if (m_lastWidgetFBO != m_Window->defaultFramebufferObject()) {
+ m_lastWidgetFBO = m_Window->defaultFramebufferObject();
+ m_RenderContext->SetDefaultRenderTarget(m_lastWidgetFBO);
+ }
+}
+
+//=============================================================================
+/**
+ * Finalize the rendering of this frame, and present the result.
+ */
+void CWGLRenderContext::EndRender()
+{
+ m_Window->doneCurrent();
+}
+
+void CWGLRenderContext::resized()
+{
+ if (m_RenderContext) {
+ m_RenderContext->SetDefaultRenderTarget(m_Window->defaultFramebufferObject());
+ }
+}
+
+void CWGLRenderContext::requestRender()
+{
+ m_Window->update();
+}