Support wasm components installation (#55)

* Support for WebAssembler

- Qt 5.12 provide tech preview for wasm, and 5.13 and later it supports.

Signed-off-by: Hiroshi Miura <miurahr@linux.com>
This commit is contained in:
Hiroshi Miura
2019-11-16 23:44:50 +09:00
committed by GitHub
parent dbb8bd1d5d
commit 73ba2b67de
13 changed files with 549 additions and 60 deletions

View File

@@ -26,5 +26,6 @@ recursive-include tests *.qml
recursive-include tests *.qrc recursive-include tests *.qrc
recursive-include tests *.svg recursive-include tests *.svg
recursive-include tests *.h recursive-include tests *.h
recursive-include tests *.pri
recursive-include tests *.png recursive-include tests *.png
recursive-include tests *.qdoc recursive-include tests *.qdoc

View File

@@ -62,6 +62,7 @@ class QtArchives:
self.target = target self.target = target
self.arch = arch self.arch = arch
self.mirror = mirror self.mirror = mirror
self.os_name = os_name
if mirror is not None: if mirror is not None:
self.has_mirror = True self.has_mirror = True
self.base = mirror + '/online/qtsdkrepository/' self.base = mirror + '/online/qtsdkrepository/'
@@ -75,15 +76,16 @@ class QtArchives:
for m in modules if modules is not None else []: for m in modules if modules is not None else []:
fqmn = "qt.qt5.{}.{}.{}".format(self.qt_ver_num, m, arch) fqmn = "qt.qt5.{}.{}.{}".format(self.qt_ver_num, m, arch)
self.mod_list.append(fqmn) self.mod_list.append(fqmn)
self._get_archives(os_name) self._get_archives()
def _get_archives(self, os_name): def _get_archives(self):
if os_name == 'windows': qt_ver_num = self.version.replace(".", "")
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 + '/'
# Get packages index # 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) update_xml_url = "{0}Updates.xml".format(archive_url)
try: try:
r = requests.get(update_xml_url) r = requests.get(update_xml_url)
@@ -91,31 +93,27 @@ class QtArchives:
self.logger.error('Download error: %s\n' % e.args, exc_info=True) self.logger.error('Download error: %s\n' % e.args, exc_info=True)
raise e raise e
else: 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) self.update_xml = ElementTree.fromstring(r.text)
for packageupdate in self.update_xml.iter("PackageUpdate"): for packageupdate in self.update_xml.iter("PackageUpdate"):
name = packageupdate.find("Name").text 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: if packageupdate.find("DownloadableArchives").text is None:
continue continue
if name == "qt.qt5.{}.{}".format(self.qt_ver_num, self.arch): if name in target_packages:
pass downloadable_archives = packageupdate.find("DownloadableArchives").text.split(", ")
elif name == "qt.{}.{}".format(self.qt_ver_num, self.arch): full_version = packageupdate.find("Version").text
pass package_desc = packageupdate.find("Description").text
elif name in self.mod_list: for archive in downloadable_archives:
pass package_url = archive_url + name + "/" + full_version + archive
else: self.archives.append(QtPackage(name, package_url, archive, package_desc,
continue has_mirror=self.has_mirror))
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: if len(self.archives) == 0:
print("Error while parsing package information!") print("Error while parsing package information!")
exit(1) exit(1)
@@ -137,13 +135,14 @@ class ToolArchives(QtArchives):
def __init__(self, os_name, tool_name, version, arch, mirror=None, logging=None): def __init__(self, os_name, tool_name, version, arch, mirror=None, logging=None):
self.tool_name = tool_name self.tool_name = tool_name
self.os_name = os_name
super(ToolArchives, self).__init__(os_name, 'desktop', version, arch, mirror=mirror, logging=logging) super(ToolArchives, self).__init__(os_name, 'desktop', version, arch, mirror=mirror, logging=logging)
def _get_archives(self, os_name): def _get_archives(self):
if os_name == 'windows': if self.os_name == 'windows':
archive_url = self.base + os_name + '_x86/' + self.target + '/' archive_url = self.base + self.os_name + '_x86/' + self.target + '/'
else: 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) update_xml_url = "{0}{1}/Updates.xml".format(archive_url, self.tool_name)
try: try:
r = requests.get(update_xml_url) r = requests.get(update_xml_url)

View File

@@ -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("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('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('target', choices=['desktop', 'winrt', 'android', 'ios'], help="target sdk")
install_parser.add_argument('arch', nargs='?', help="\ntarget linux/desktop: gcc_64" install_parser.add_argument('arch', nargs='?', help="\ntarget linux/desktop: gcc_64, wasm_32"
"\ntarget mac/desktop: clang_64" "\ntarget mac/desktop: clang_64, wasm_32"
"\ntarget mac/ios: ios" "\ntarget mac/ios: ios"
"\nwindows/desktop: win64_msvc2017_64, win64_msvc2015_64" "\nwindows/desktop: win64_msvc2017_64, win64_msvc2015_64"
"\n win32_msvc2015, win32_mingw53" "\n win32_msvc2015, win32_mingw53"
"\n win64_mingw73, win32_mingw73" "\n win64_mingw73, win32_mingw73"
"\n wasm_32"
"\nwindows/winrt: win64_msvc2017_winrt_x64, win64_msvc2017_winrt_x86" "\nwindows/winrt: win64_msvc2017_winrt_x64, win64_msvc2017_winrt_x86"
"\n win64_msvc2017_winrt_armv7" "\n win64_msvc2017_winrt_armv7"
"\nandroid: android_x86, android_armv7") "\nandroid: android_x86, android_armv7")

View File

@@ -1,8 +1,10 @@
[{"qt": [ [{"qt": [
{"os_name": "linux", "target": "desktop", "arch": "gcc_64"}, {"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_x86"},
{"os_name": "linux", "target": "android", "arch": "android_armv7"}, {"os_name": "linux", "target": "android", "arch": "android_armv7"},
{"os_name": "mac", "target": "desktop", "arch": "clang_64"}, {"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": "mac", "target": "ios", "arch": "ios"},
{"os_name": "windows", "target": "desktop", "arch": "win64_msvc2017_64"}, {"os_name": "windows", "target": "desktop", "arch": "win64_msvc2017_64"},
{"os_name": "windows", "target": "desktop", "arch": "win32_msvc2017"}, {"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_x64"},
{"os_name": "windows", "target": "winrt", "arch": "win64_msvc2017_winrt_x86"}, {"os_name": "windows", "target": "winrt", "arch": "win64_msvc2017_winrt_x86"},
{"os_name": "windows", "target": "winrt", "arch": "win64_msvc2017_winrt_armv7"}, {"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_x86"},
{"os_name": "windows", "target": "android", "arch": "android_armv7"} {"os_name": "windows", "target": "android", "arch": "android_armv7"}
], "tools": [ ], "tools": [

View File

@@ -27,8 +27,8 @@ python_versions = [
] ]
qt_versions = [ qt_versions = [
'5.12.5', '5.12.6',
'5.13.1', '5.13.2',
'5.14.0' '5.14.0'
] ]
@@ -43,14 +43,17 @@ all_platform_build_jobs = [
] ]
# Linux Desktop # Linux Desktop
for qt_version in qt_versions: for qt_version in qt_versions:
linux_build_jobs.append( linux_build_jobs.append(
BuildJob(qt_version, 'linux', 'desktop', 'gcc_64', 'gcc_64') 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: for qt_version in qt_versions:
mac_build_jobs.append( mac_build_jobs.append(
BuildJob(qt_version, 'mac', 'desktop', 'clang_64', "clang_64") BuildJob(qt_version, 'mac', 'desktop', 'clang_64', "clang_64")
@@ -58,7 +61,12 @@ for qt_version in qt_versions:
# Mac iOS # Mac iOS
mac_build_jobs.append( 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 # 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( windows_build_jobs.extend(
[ [
BuildJob('5.13.1', 'windows', 'desktop', 'win64_msvc2017_64', 'msvc2017_64'), BuildJob('5.13.1', 'windows', 'desktop', 'win64_msvc2017_64', 'msvc2017_64'),

View File

@@ -1,4 +1,5 @@
steps: steps:
# Install aqtinstall
- task: UsePythonVersion@0 - task: UsePythonVersion@0
inputs: inputs:
versionSpec: $(PYTHON_VERSION) versionSpec: $(PYTHON_VERSION)
@@ -14,12 +15,13 @@ steps:
arguments: sdist bdist_wheel arguments: sdist bdist_wheel
workingDirectory: $(Build.SourcesDirectory) workingDirectory: $(Build.SourcesDirectory)
displayName: build package displayName: build package
#
# Install aqtinstall
- powershell: | - powershell: |
$aqtVersion = & python $(Build.SourcesDirectory)/setup.py --version | Out-String -Stream $aqtVersion = & python $(Build.SourcesDirectory)/setup.py --version | Out-String -Stream
pip install $(Build.SourcesDirectory)/dist/aqtinstall-$aqtVersion-py2.py3-none-any.whl pip install $(Build.SourcesDirectory)/dist/aqtinstall-$aqtVersion-py2.py3-none-any.whl
displayName: install package displayName: install package
# Run Aqt
##----------------------------------------------------
- task: PythonScript@0 - task: PythonScript@0
inputs: inputs:
scriptSource: filePath scriptSource: filePath
@@ -44,8 +46,9 @@ steps:
workingDirectory: $(Build.BinariesDirectory) workingDirectory: $(Build.BinariesDirectory)
condition: and(not(variables['TOOL_NAME']), ne(variables['MODULE'], '')) condition: and(not(variables['TOOL_NAME']), ne(variables['MODULE'], ''))
displayName: Run Aqt (With modules) displayName: Run Aqt (With modules)
#
# Test installation results # Test installation environments
##----------------------------------------------------
# for Android on linux # for Android on linux
- script: | - script: |
wget https://dl.google.com/android/repository/android-ndk-r19c-linux-x86_64.zip 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 $(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'))) 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 displayName: Build accelbubble example application to test for android
# for desktop application
##----------------------------------------------------
# Test build on Windows/Linux and Mac
# determine Windows build system
- powershell: | - powershell: |
Install-PackageProvider NuGet -Force Install-PackageProvider NuGet -Force
Import-PackageProvider NuGet -Force Import-PackageProvider NuGet -Force
@@ -87,42 +93,45 @@ steps:
echo '##vso[task.setvariable variable=VSVER]2015' echo '##vso[task.setvariable variable=VSVER]2015'
} }
condition: eq( variables['Agent.OS'], 'Windows_NT') 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 # no modules
- powershell: | - powershell: |
Import-VisualStudioVars -VisualStudioVersion $(VSVER) -Architecture $(ARCHITECTURE) 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 nmake
condition: and(eq( variables['Agent.OS'], 'Windows_NT'), eq(variables['TOOLCHAIN'], 'MSVC'), eq(variables['MODULE'], '')) 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: | - script: |
sudo apt-get install libgl1-mesa-dev $(Build.BinariesDirectory)/Qt/$(QT_VERSION)/$(ARCHDIR)/bin/qmake $(Build.SourcesDirectory)/tests/helloworld
$(Build.BinariesDirectory)/Qt/$(QT_VERSION)/$(ARCHDIR)/bin/qmake $(Build.SourcesDirectory)/tests
make make
condition: and(eq( variables['TARGET'], 'desktop' ), or(eq(variables['Agent.OS'], 'Linux'), eq(variables['Agent.OS'], 'Darwin')), eq(variables['MODULE'], '')) 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 displayName: Build test with qmake for Linux and macOS w/o extra module
# modules # modules
- powershell: | - powershell: |
Import-VisualStudioVars -VisualStudioVersion $(VSVER) -Architecture $(ARCHITECTURE) Import-VisualStudioVars -VisualStudioVersion $(VSVER) -Architecture $(ARCHITECTURE)
$(Build.BinariesDirectory)/Qt/$(QT_VERSION)/$(ARCHDIR)/bin/qmake $(Build.SourcesDirectory)/tests/redditclient $(Build.BinariesDirectory)/Qt/$(QT_VERSION)/$(ARCHDIR)/bin/qmake $(Build.SourcesDirectory)/tests/redditclient
nmake nmake
condition: and(eq( variables['Agent.OS'], 'Windows_NT'), eq(variables['TOOLCHAIN'], 'MSVC'), ne(variables['MODULE'], '')) 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: | - script: |
sudo apt-get install libgl1-mesa-dev
$(Build.BinariesDirectory)/Qt/$(QT_VERSION)/$(ARCHDIR)/bin/qmake $(Build.SourcesDirectory)/tests/redditclient $(Build.BinariesDirectory)/Qt/$(QT_VERSION)/$(ARCHDIR)/bin/qmake $(Build.SourcesDirectory)/tests/redditclient
make make
condition: and(eq( variables['TARGET'], 'desktop' ), or(eq(variables['Agent.OS'], 'Linux'), eq(variables['Agent.OS'], 'Darwin')), ne(variables['MODULE'], '')) 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 # for ios
- script: echo Currently not implemented. - script: echo Currently not implemented.
condition: and(eq(variables['TARGET'], 'ios'), eq(variables['Agent.OS'], 'Darwin')) condition: and(eq(variables['TARGET'], 'ios'), eq(variables['Agent.OS'], 'Darwin'))
displayName: Build test with qmake for ios displayName: Build test with qmake for ios
#
# Install aqtinstall ##----------------------------------------------------
- powershell: | # Tools Support
$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
- task: PythonScript@0 - task: PythonScript@0
inputs: inputs:
scriptSource: filePath scriptSource: filePath
@@ -131,10 +140,26 @@ steps:
workingDirectory: $(Build.BinariesDirectory) workingDirectory: $(Build.BinariesDirectory)
condition: variables['TOOL_NAME'] condition: variables['TOOL_NAME']
displayName: Run Aqt (Tool) displayName: Run Aqt (Tool)
#
# Test installation results # Test installation results
# for OpenSSL on linux
- script: | - script: |
$(Build.BinariesDirectory)/Qt/Tools/$(TEST_EXECUTABLE) $(TEST_COMMAND) $(Build.BinariesDirectory)/Qt/Tools/$(TEST_EXECUTABLE) $(TEST_COMMAND)
condition: variables['TOOL_NAME'] condition: variables['TOOL_NAME']
displayName: Tool test 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'

180
tests/openglwindow/main.cpp Normal file
View File

@@ -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 <QtGui/QGuiApplication>
#include <QtGui/QMatrix4x4>
#include <QtGui/QOpenGLShaderProgram>
#include <QtGui/QScreen>
#include <QtCore/qmath.h>
//! [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]

View File

@@ -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 <QtCore/QCoreApplication>
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLPaintDevice>
#include <QtGui/QPainter>
//! [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]

View File

@@ -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 <QtGui/QWindow>
#include <QtGui/QOpenGLFunctions>
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]

View File

@@ -0,0 +1,3 @@
INCLUDEPATH += $$PWD
SOURCES += $$PWD/openglwindow.cpp
HEADERS += $$PWD/openglwindow.h

View File

@@ -0,0 +1,7 @@
include(openglwindow.pri)
SOURCES += \
main.cpp
target.path = $$[QT_INSTALL_EXAMPLES]/gui/openglwindow
INSTALLS += target