diff --git a/MANIFEST.in b/MANIFEST.in index 5aee9a9..11cb77b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -24,7 +24,8 @@ recursive-include tests *.cpp recursive-include tests *.pro recursive-include tests *.qml recursive-include tests *.qrc -recursive-include tests *.svg +recursive-include tests *.svg recursive-include tests *.h +recursive-include tests *.pri recursive-include tests *.png recursive-include tests *.qdoc diff --git a/aqt/archives.py b/aqt/archives.py index db310e2..001bc29 100644 --- a/aqt/archives.py +++ b/aqt/archives.py @@ -62,6 +62,7 @@ class QtArchives: self.target = target self.arch = arch self.mirror = mirror + self.os_name = os_name if mirror is not None: self.has_mirror = True self.base = mirror + '/online/qtsdkrepository/' @@ -75,15 +76,16 @@ class QtArchives: for m in modules if modules is not None else []: fqmn = "qt.qt5.{}.{}.{}".format(self.qt_ver_num, m, arch) self.mod_list.append(fqmn) - self._get_archives(os_name) + self._get_archives() - def _get_archives(self, os_name): - if os_name == 'windows': - archive_url = self.base + os_name + '_x86/' + self.target + '/' + 'qt5_' + self.qt_ver_num + '/' - else: - archive_url = self.base + os_name + '_x64/' + self.target + '/' + 'qt5_' + self.qt_ver_num + '/' + def _get_archives(self): + qt_ver_num = self.version.replace(".", "") # Get packages index + archive_url = "{0}{1}{2}{3}/qt5_{4}{5}".format(self.base, self.os_name, + '_x86/' if self.os_name == 'windows' else '_x64/', + self.target, qt_ver_num, + '_wasm/' if self.arch == 'wasm_32' else '/') update_xml_url = "{0}Updates.xml".format(archive_url) try: r = requests.get(update_xml_url) @@ -91,31 +93,27 @@ class QtArchives: self.logger.error('Download error: %s\n' % e.args, exc_info=True) raise e else: + target_packages = [] + target_packages.append("qt.qt5.{}.{}".format(qt_ver_num, self.arch)) + target_packages.append("qt.{}.{}".format(qt_ver_num, self.arch)) + if self.arch == 'wasm_32': + for m in ('qtcharts', 'qtdatavis3d', 'qtlottie', 'qtnetworkauth', 'qtpurchasing', 'qtquicktimeline', + 'qtscript', 'qtvirtualkeyboard', 'qtwebglplugin'): + target_packages.append("qt.qt5.{}.{}.{}".format(qt_ver_num, m, self.arch)) + target_packages.extend(self.mod_list) self.update_xml = ElementTree.fromstring(r.text) for packageupdate in self.update_xml.iter("PackageUpdate"): name = packageupdate.find("Name").text - if name.split(".")[-1] != self.arch: - continue - if name.split(".")[-2] == "debug_info": - continue if packageupdate.find("DownloadableArchives").text is None: continue - if name == "qt.qt5.{}.{}".format(self.qt_ver_num, self.arch): - pass - elif name == "qt.{}.{}".format(self.qt_ver_num, self.arch): - pass - elif name in self.mod_list: - pass - else: - continue - downloadable_archives = packageupdate.find("DownloadableArchives").text.split(", ") - full_version = packageupdate.find("Version").text - package_desc = packageupdate.find("Description").text - for archive in downloadable_archives: - package_url = archive_url + name + "/" + full_version + archive - self.archives.append(QtPackage(name, package_url, archive, package_desc, - has_mirror=self.has_mirror)) - + if name in target_packages: + downloadable_archives = packageupdate.find("DownloadableArchives").text.split(", ") + full_version = packageupdate.find("Version").text + package_desc = packageupdate.find("Description").text + for archive in downloadable_archives: + package_url = archive_url + name + "/" + full_version + archive + self.archives.append(QtPackage(name, package_url, archive, package_desc, + has_mirror=self.has_mirror)) if len(self.archives) == 0: print("Error while parsing package information!") exit(1) @@ -137,13 +135,14 @@ class ToolArchives(QtArchives): def __init__(self, os_name, tool_name, version, arch, mirror=None, logging=None): self.tool_name = tool_name + self.os_name = os_name super(ToolArchives, self).__init__(os_name, 'desktop', version, arch, mirror=mirror, logging=logging) - def _get_archives(self, os_name): - if os_name == 'windows': - archive_url = self.base + os_name + '_x86/' + self.target + '/' + def _get_archives(self): + if self.os_name == 'windows': + archive_url = self.base + self.os_name + '_x86/' + self.target + '/' else: - archive_url = self.base + os_name + '_x64/' + self.target + '/' + archive_url = self.base + self.os_name + '_x64/' + self.target + '/' update_xml_url = "{0}{1}/Updates.xml".format(archive_url, self.tool_name) try: r = requests.get(update_xml_url) diff --git a/aqt/cli.py b/aqt/cli.py index 2a1cbec..ecf7ebd 100644 --- a/aqt/cli.py +++ b/aqt/cli.py @@ -149,12 +149,13 @@ class Cli(): install_parser.add_argument("qt_version", help="Qt version in the format of \"5.X.Y\"") install_parser.add_argument('host', choices=['linux', 'mac', 'windows'], help="host os name") install_parser.add_argument('target', choices=['desktop', 'winrt', 'android', 'ios'], help="target sdk") - install_parser.add_argument('arch', nargs='?', help="\ntarget linux/desktop: gcc_64" - "\ntarget mac/desktop: clang_64" + install_parser.add_argument('arch', nargs='?', help="\ntarget linux/desktop: gcc_64, wasm_32" + "\ntarget mac/desktop: clang_64, wasm_32" "\ntarget mac/ios: ios" "\nwindows/desktop: win64_msvc2017_64, win64_msvc2015_64" "\n win32_msvc2015, win32_mingw53" "\n win64_mingw73, win32_mingw73" + "\n wasm_32" "\nwindows/winrt: win64_msvc2017_winrt_x64, win64_msvc2017_winrt_x86" "\n win64_msvc2017_winrt_armv7" "\nandroid: android_x86, android_armv7") diff --git a/aqt/combinations.json b/aqt/combinations.json index f921eb9..47930bd 100644 --- a/aqt/combinations.json +++ b/aqt/combinations.json @@ -1,8 +1,10 @@ [{"qt": [ {"os_name": "linux", "target": "desktop", "arch": "gcc_64"}, + {"os_name": "linux", "target": "desktop", "arch": "wasm_32"}, {"os_name": "linux", "target": "android", "arch": "android_x86"}, {"os_name": "linux", "target": "android", "arch": "android_armv7"}, {"os_name": "mac", "target": "desktop", "arch": "clang_64"}, + {"os_name": "mac", "target": "desktop", "arch": "wasm_32"}, {"os_name": "mac", "target": "ios", "arch": "ios"}, {"os_name": "windows", "target": "desktop", "arch": "win64_msvc2017_64"}, {"os_name": "windows", "target": "desktop", "arch": "win32_msvc2017"}, @@ -15,6 +17,7 @@ {"os_name": "windows", "target": "winrt", "arch": "win64_msvc2017_winrt_x64"}, {"os_name": "windows", "target": "winrt", "arch": "win64_msvc2017_winrt_x86"}, {"os_name": "windows", "target": "winrt", "arch": "win64_msvc2017_winrt_armv7"}, + {"os_name": "windows", "target": "desktop", "arch": "wasm_32"}, {"os_name": "windows", "target": "android", "arch": "android_x86"}, {"os_name": "windows", "target": "android", "arch": "android_armv7"} ], "tools": [ diff --git a/ci/generate_azure_pipelines_matrices.py b/ci/generate_azure_pipelines_matrices.py index 8a0a84d..efdee2d 100644 --- a/ci/generate_azure_pipelines_matrices.py +++ b/ci/generate_azure_pipelines_matrices.py @@ -27,8 +27,8 @@ python_versions = [ ] qt_versions = [ - '5.12.5', - '5.13.1', + '5.12.6', + '5.13.2', '5.14.0' ] @@ -43,14 +43,17 @@ all_platform_build_jobs = [ ] # Linux Desktop - for qt_version in qt_versions: linux_build_jobs.append( BuildJob(qt_version, 'linux', 'desktop', 'gcc_64', 'gcc_64') ) -# Mac Desktop +# WASM +linux_build_jobs.append( + BuildJob('5.13.2', 'linux', 'desktop', 'wasm_32', "wasm_32") +) +# Mac Desktop for qt_version in qt_versions: mac_build_jobs.append( BuildJob(qt_version, 'mac', 'desktop', 'clang_64', "clang_64") @@ -58,7 +61,12 @@ for qt_version in qt_versions: # Mac iOS mac_build_jobs.append( - BuildJob('5.13.0', 'mac', 'ios', 'ios', 'ios') + BuildJob('5.13.2', 'mac', 'ios', 'ios', 'ios') +) + +# WASM +mac_build_jobs.append( + BuildJob('5.13.2', 'mac', 'desktop', 'wasm_32', "wasm_32") ) # Windows Desktop @@ -69,6 +77,11 @@ windows_build_jobs.extend( ] ) +# WASM +windows_build_jobs.append( + BuildJob('5.13.2', 'windows', 'desktop', 'wasm_32', "wasm_32") +) + windows_build_jobs.extend( [ BuildJob('5.13.1', 'windows', 'desktop', 'win64_msvc2017_64', 'msvc2017_64'), diff --git a/ci/steps.yml b/ci/steps.yml index a958952..2f7e187 100644 --- a/ci/steps.yml +++ b/ci/steps.yml @@ -1,4 +1,5 @@ steps: + # Install aqtinstall - task: UsePythonVersion@0 inputs: versionSpec: $(PYTHON_VERSION) @@ -14,12 +15,13 @@ steps: arguments: sdist bdist_wheel workingDirectory: $(Build.SourcesDirectory) displayName: build package - # - # Install aqtinstall - powershell: | $aqtVersion = & python $(Build.SourcesDirectory)/setup.py --version | Out-String -Stream pip install $(Build.SourcesDirectory)/dist/aqtinstall-$aqtVersion-py2.py3-none-any.whl displayName: install package + + # Run Aqt + ##---------------------------------------------------- - task: PythonScript@0 inputs: scriptSource: filePath @@ -44,8 +46,9 @@ steps: workingDirectory: $(Build.BinariesDirectory) condition: and(not(variables['TOOL_NAME']), ne(variables['MODULE'], '')) displayName: Run Aqt (With modules) - # - # Test installation results + + # Test installation environments + ##---------------------------------------------------- # for Android on linux - script: | wget https://dl.google.com/android/repository/android-ndk-r19c-linux-x86_64.zip @@ -63,7 +66,10 @@ steps: $(Build.BinariesDirectory)/Qt/$(QT_VERSION)/$(ARCHDIR)/bin/qmake $(Build.SourcesDirectory)/tests/accelbubble/ && make condition: and(eq(variables['TARGET'], 'android'), or(eq(variables['Agent.OS'], 'Linux'), eq(variables['Agent.OS'], 'Darwin'))) displayName: Build accelbubble example application to test for android - # for desktop application + + ##---------------------------------------------------- + # Test build on Windows/Linux and Mac + # determine Windows build system - powershell: | Install-PackageProvider NuGet -Force Import-PackageProvider NuGet -Force @@ -87,42 +93,45 @@ steps: echo '##vso[task.setvariable variable=VSVER]2015' } condition: eq( variables['Agent.OS'], 'Windows_NT') + displayName: detect toolchain for Windows + - script: | + sudo apt-get install libgl1-mesa-dev + condition: and(eq( variables['TARGET'], 'desktop' ), eq(variables['Agent.OS'], 'Linux')) + displayName: install test dependency for Linux + # no modules - powershell: | Import-VisualStudioVars -VisualStudioVersion $(VSVER) -Architecture $(ARCHITECTURE) - $(Build.BinariesDirectory)/Qt/$(QT_VERSION)/$(ARCHDIR)/bin/qmake $(Build.SourcesDirectory)/tests + $(Build.BinariesDirectory)/Qt/$(QT_VERSION)/$(ARCHDIR)/bin/qmake $(Build.SourcesDirectory)/tests/helloworld nmake condition: and(eq( variables['Agent.OS'], 'Windows_NT'), eq(variables['TOOLCHAIN'], 'MSVC'), eq(variables['MODULE'], '')) - displayName: build test with qmake with MSVC + displayName: build test with qmake with MSVC w/o extra module - script: | - sudo apt-get install libgl1-mesa-dev - $(Build.BinariesDirectory)/Qt/$(QT_VERSION)/$(ARCHDIR)/bin/qmake $(Build.SourcesDirectory)/tests + $(Build.BinariesDirectory)/Qt/$(QT_VERSION)/$(ARCHDIR)/bin/qmake $(Build.SourcesDirectory)/tests/helloworld make - condition: and(eq( variables['TARGET'], 'desktop' ), or(eq(variables['Agent.OS'], 'Linux'), eq(variables['Agent.OS'], 'Darwin')), eq(variables['MODULE'], '')) - displayName: Build test with qmake for Linux and macOS + condition: and(eq( variables['TARGET'], 'desktop' ), ne( variables['ARCH'], 'wasm_32' ), or(eq(variables['Agent.OS'], 'Linux'), eq(variables['Agent.OS'], 'Darwin')), eq(variables['MODULE'], '')) + displayName: Build test with qmake for Linux and macOS w/o extra module # modules - powershell: | Import-VisualStudioVars -VisualStudioVersion $(VSVER) -Architecture $(ARCHITECTURE) $(Build.BinariesDirectory)/Qt/$(QT_VERSION)/$(ARCHDIR)/bin/qmake $(Build.SourcesDirectory)/tests/redditclient nmake condition: and(eq( variables['Agent.OS'], 'Windows_NT'), eq(variables['TOOLCHAIN'], 'MSVC'), ne(variables['MODULE'], '')) - displayName: build test with qmake with MSVC + displayName: build test with qmake with MSVC with extra module - script: | - sudo apt-get install libgl1-mesa-dev $(Build.BinariesDirectory)/Qt/$(QT_VERSION)/$(ARCHDIR)/bin/qmake $(Build.SourcesDirectory)/tests/redditclient make condition: and(eq( variables['TARGET'], 'desktop' ), or(eq(variables['Agent.OS'], 'Linux'), eq(variables['Agent.OS'], 'Darwin')), ne(variables['MODULE'], '')) - displayName: Build test with qmake for Linux and macOS + displayName: Build test with qmake for Linux and macOS with extra module + + ##---------------------------------------------------- # for ios - script: echo Currently not implemented. condition: and(eq(variables['TARGET'], 'ios'), eq(variables['Agent.OS'], 'Darwin')) displayName: Build test with qmake for ios - # - # Install aqtinstall - - powershell: | - $aqtVersion = & python $(Build.SourcesDirectory)/setup.py --version | Out-String -Stream - pip install $(Build.SourcesDirectory)/dist/aqtinstall-$aqtVersion-py2.py3-none-any.whl - displayName: install package + + ##---------------------------------------------------- + # Tools Support - task: PythonScript@0 inputs: scriptSource: filePath @@ -131,10 +140,26 @@ steps: workingDirectory: $(Build.BinariesDirectory) condition: variables['TOOL_NAME'] displayName: Run Aqt (Tool) - # # Test installation results - # for OpenSSL on linux - script: | $(Build.BinariesDirectory)/Qt/Tools/$(TEST_EXECUTABLE) $(TEST_COMMAND) condition: variables['TOOL_NAME'] displayName: Tool test + ##---------------------------------------------------- + + ##---------------------------------------------------- + # wasm_32 on linux and mac + - script: | + git clone https://github.com/emscripten-core/emsdk.git + cd emsdk + ./emsdk install sdk-1.38.27-64bit + ./emsdk activate --embedded sdk-1.38.27-64bit + workingDirectory: $(Build.BinariesDirectory) + condition: and(eq( variables['ARCH'], 'wasm_32' ), or(eq(variables['Agent.OS'], 'Linux'), eq(variables['Agent.OS'], 'Darwin'))) + displayName: 'Install Emscripten SDK' + - script: | + source $(Build.BinariesDirectory)/emsdk/emsdk_env.sh + $(Build.BinariesDirectory)/Qt/$(QT_VERSION)/$(ARCHDIR)/bin/qmake $(Build.SourcesDirectory)/tests/openglwindow && make + workingDirectory: $(Build.BinariesDirectory) + condition: and(eq( variables['ARCH'], 'wasm_32' ), or(eq(variables['Agent.OS'], 'Linux'), eq(variables['Agent.OS'], 'Darwin'))) + displayName: 'Build WebAssembler sample project' diff --git a/tests/hello.pro b/tests/helloworld/hello.pro similarity index 100% rename from tests/hello.pro rename to tests/helloworld/hello.pro diff --git a/tests/main.cpp b/tests/helloworld/main.cpp similarity index 100% rename from tests/main.cpp rename to tests/helloworld/main.cpp diff --git a/tests/openglwindow/main.cpp b/tests/openglwindow/main.cpp new file mode 100644 index 0000000..90c93f0 --- /dev/null +++ b/tests/openglwindow/main.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "openglwindow.h" + +#include +#include +#include +#include + +#include + +//! [1] +class TriangleWindow : public OpenGLWindow +{ +public: + TriangleWindow(); + + void initialize() override; + void render() override; + +private: + GLuint m_posAttr; + GLuint m_colAttr; + GLuint m_matrixUniform; + + QOpenGLShaderProgram *m_program; + int m_frame; +}; + +TriangleWindow::TriangleWindow() + : m_program(0) + , m_frame(0) +{ +} +//! [1] + +//! [2] +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + + QSurfaceFormat format; + format.setSamples(16); + + TriangleWindow window; + window.setFormat(format); + window.resize(640, 480); + window.show(); + + window.setAnimating(true); + + return app.exec(); +} +//! [2] + + +//! [3] +static const char *vertexShaderSource = + "attribute highp vec4 posAttr;\n" + "attribute lowp vec4 colAttr;\n" + "varying lowp vec4 col;\n" + "uniform highp mat4 matrix;\n" + "void main() {\n" + " col = colAttr;\n" + " gl_Position = matrix * posAttr;\n" + "}\n"; + +static const char *fragmentShaderSource = + "varying lowp vec4 col;\n" + "void main() {\n" + " gl_FragColor = col;\n" + "}\n"; +//! [3] + +//! [4] +void TriangleWindow::initialize() +{ + m_program = new QOpenGLShaderProgram(this); + m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource); + m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource); + m_program->link(); + m_posAttr = m_program->attributeLocation("posAttr"); + m_colAttr = m_program->attributeLocation("colAttr"); + m_matrixUniform = m_program->uniformLocation("matrix"); +} +//! [4] + +//! [5] +void TriangleWindow::render() +{ + const qreal retinaScale = devicePixelRatio(); + glViewport(0, 0, width() * retinaScale, height() * retinaScale); + + glClear(GL_COLOR_BUFFER_BIT); + + m_program->bind(); + + QMatrix4x4 matrix; + matrix.perspective(60.0f, 4.0f/3.0f, 0.1f, 100.0f); + matrix.translate(0, 0, -2); + matrix.rotate(100.0f * m_frame / screen()->refreshRate(), 0, 1, 0); + + m_program->setUniformValue(m_matrixUniform, matrix); + + GLfloat vertices[] = { + 0.0f, 0.707f, + -0.5f, -0.5f, + 0.5f, -0.5f + }; + + GLfloat colors[] = { + 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f + }; + + glVertexAttribPointer(m_posAttr, 2, GL_FLOAT, GL_FALSE, 0, vertices); + glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors); + + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + + glDrawArrays(GL_TRIANGLES, 0, 3); + + glDisableVertexAttribArray(1); + glDisableVertexAttribArray(0); + + m_program->release(); + + ++m_frame; +} +//! [5] diff --git a/tests/openglwindow/openglwindow.cpp b/tests/openglwindow/openglwindow.cpp new file mode 100644 index 0000000..a0c8500 --- /dev/null +++ b/tests/openglwindow/openglwindow.cpp @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "openglwindow.h" + +#include + +#include +#include +#include + +//! [1] +OpenGLWindow::OpenGLWindow(QWindow *parent) + : QWindow(parent) + , m_animating(false) + , m_context(0) + , m_device(0) +{ + setSurfaceType(QWindow::OpenGLSurface); +} +//! [1] + +OpenGLWindow::~OpenGLWindow() +{ + delete m_device; +} +//! [2] +void OpenGLWindow::render(QPainter *painter) +{ + Q_UNUSED(painter); +} + +void OpenGLWindow::initialize() +{ +} + +void OpenGLWindow::render() +{ + if (!m_device) + m_device = new QOpenGLPaintDevice; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + m_device->setSize(size() * devicePixelRatio()); + m_device->setDevicePixelRatio(devicePixelRatio()); + + QPainter painter(m_device); + render(&painter); +} +//! [2] + +//! [3] +void OpenGLWindow::renderLater() +{ + requestUpdate(); +} + +bool OpenGLWindow::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::UpdateRequest: + renderNow(); + return true; + default: + return QWindow::event(event); + } +} + +void OpenGLWindow::exposeEvent(QExposeEvent *event) +{ + Q_UNUSED(event); + + if (isExposed()) + renderNow(); +} +//! [3] + +//! [4] +void OpenGLWindow::renderNow() +{ + if (!isExposed()) + return; + + bool needsInitialize = false; + + if (!m_context) { + m_context = new QOpenGLContext(this); + m_context->setFormat(requestedFormat()); + m_context->create(); + + needsInitialize = true; + } + + m_context->makeCurrent(this); + + if (needsInitialize) { + initializeOpenGLFunctions(); + initialize(); + } + + render(); + + m_context->swapBuffers(this); + + if (m_animating) + renderLater(); +} +//! [4] + +//! [5] +void OpenGLWindow::setAnimating(bool animating) +{ + m_animating = animating; + + if (animating) + renderLater(); +} +//! [5] + diff --git a/tests/openglwindow/openglwindow.h b/tests/openglwindow/openglwindow.h new file mode 100644 index 0000000..6e6c1d7 --- /dev/null +++ b/tests/openglwindow/openglwindow.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +QT_BEGIN_NAMESPACE +class QPainter; +class QOpenGLContext; +class QOpenGLPaintDevice; +QT_END_NAMESPACE + +//! [1] +class OpenGLWindow : public QWindow, protected QOpenGLFunctions +{ + Q_OBJECT +public: + explicit OpenGLWindow(QWindow *parent = 0); + ~OpenGLWindow(); + + virtual void render(QPainter *painter); + virtual void render(); + + virtual void initialize(); + + void setAnimating(bool animating); + +public slots: + void renderLater(); + void renderNow(); + +protected: + bool event(QEvent *event) override; + + void exposeEvent(QExposeEvent *event) override; + +private: + bool m_animating; + + QOpenGLContext *m_context; + QOpenGLPaintDevice *m_device; +}; +//! [1] + diff --git a/tests/openglwindow/openglwindow.pri b/tests/openglwindow/openglwindow.pri new file mode 100644 index 0000000..45b0b0c --- /dev/null +++ b/tests/openglwindow/openglwindow.pri @@ -0,0 +1,3 @@ +INCLUDEPATH += $$PWD +SOURCES += $$PWD/openglwindow.cpp +HEADERS += $$PWD/openglwindow.h diff --git a/tests/openglwindow/openglwindow.pro b/tests/openglwindow/openglwindow.pro new file mode 100644 index 0000000..93f18f3 --- /dev/null +++ b/tests/openglwindow/openglwindow.pro @@ -0,0 +1,7 @@ +include(openglwindow.pri) + +SOURCES += \ + main.cpp + +target.path = $$[QT_INSTALL_EXAMPLES]/gui/openglwindow +INSTALLS += target