mirror of
https://gitee.com/bianbu-linux/k1x-gpu-test
synced 2025-06-28 09:44:19 -04:00
initial commit
This commit is contained in:
commit
1018ee28cf
30 changed files with 16611 additions and 0 deletions
36
.bianbu-ci.yml
Normal file
36
.bianbu-ci.yml
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
image: harbor.bianbu.xyz/gitlab/ci-pack
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- pack
|
||||||
|
|
||||||
|
pack-job:
|
||||||
|
stage: pack
|
||||||
|
script:
|
||||||
|
- echo "Building for tag $CI_COMMIT_TAG"
|
||||||
|
- eval $(ssh-agent -s)
|
||||||
|
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
|
||||||
|
- mkdir -p ~/.ssh
|
||||||
|
- chmod 700 ~/.ssh
|
||||||
|
- ssh-keyscan gitlab.dc.com >> ~/.ssh/known_hosts
|
||||||
|
- chmod 644 ~/.ssh/known_hosts
|
||||||
|
- git config --global user.email "bianbu-ci@spacemit.com"
|
||||||
|
- git config --global user.name "bianbu-ci"
|
||||||
|
# 准备打包脚本
|
||||||
|
- cd ..
|
||||||
|
- git clone git@gitlab.dc.com:bianbu/bianbu-devscripts.git
|
||||||
|
- export PATH=$CI_PROJECT_DIR/../bianbu-devscripts:$PATH
|
||||||
|
# 准备打包所需的源码,从detach切换到分支
|
||||||
|
- cd $CI_PROJECT_DIR
|
||||||
|
- git checkout ${CI_COMMIT_TAG%%/*}
|
||||||
|
- bianbu-dev set-default-dist ${CI_COMMIT_TAG%%/*}
|
||||||
|
- bianbu-pkg -u local -w . -t $CI_COMMIT_TAG
|
||||||
|
- changes_file=$(find ../ -maxdepth 1 -type f -name "*.changes" | head -n 1)
|
||||||
|
# 上传结果
|
||||||
|
- ssh-keyscan reprepro-headless-service.buildsystem.svc.cluster.local >> ~/.ssh/known_hosts
|
||||||
|
- bianbu-dev upload --sync $changes_file
|
||||||
|
# 修改为ssh协议
|
||||||
|
- git remote set-url origin git@gitlab.dc.com:$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME.git
|
||||||
|
- git push origin --all
|
||||||
|
|
||||||
|
only:
|
||||||
|
- tags
|
9
CMakeLists.txt
Normal file
9
CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
project(k1x-gpu-test VERSION 1.0.2 LANGUAGES C)
|
||||||
|
|
||||||
|
# set(CMAKE_INSTALL_RPATH /usr/lib)
|
||||||
|
# set(CMAKE_BUILD_RPATH /usr/lib)
|
||||||
|
|
||||||
|
add_subdirectory(openGLDemo)
|
||||||
|
add_subdirectory(openCLDemo)
|
8
debian/README.Debian
vendored
Normal file
8
debian/README.Debian
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
k1x-gpu-test for Debian
|
||||||
|
|
||||||
|
Please edit this to provide information specific to
|
||||||
|
this k1x-gpu-test Debian package.
|
||||||
|
|
||||||
|
(Automatically generated by debmake Version 4.4.0)
|
||||||
|
|
||||||
|
-- root <> Tue, 20 Aug 2024 09:55:38 +0800
|
4
debian/bianbu.conf
vendored
Normal file
4
debian/bianbu.conf
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[package]
|
||||||
|
upstream = False
|
||||||
|
targetsuite = noble-porting
|
||||||
|
|
5
debian/changelog
vendored
Normal file
5
debian/changelog
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
k1x-gpu-test (0.0.1) mantic-porting; urgency=medium
|
||||||
|
|
||||||
|
* Initial for bianbu-23.10
|
||||||
|
|
||||||
|
-- root <root@localhost> Tue, 20 Aug 2024 09:55:42 +0800
|
16
debian/control
vendored
Normal file
16
debian/control
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
Source: k1x-gpu-test
|
||||||
|
Section: graphics
|
||||||
|
Priority: optional
|
||||||
|
Maintainer: baihui-spacemit <>
|
||||||
|
Build-Depends: cmake, debhelper-compat (= 12), libegl1-mesa-dev, libgles2-mesa-dev, libwayland-dev, libwayland-egl1-mesa, libwayland-cursor0, libc6-dev, ocl-icd-opencl-dev, img-gpu-powervr, libgbm-dev, libdrm-dev
|
||||||
|
Standards-Version: 1.0.2
|
||||||
|
|
||||||
|
Package: k1x-gpu-test
|
||||||
|
Architecture: any
|
||||||
|
Multi-Arch: foreign
|
||||||
|
Depends: ${misc:Depends}, ${shlibs:Depends}, img-gpu-powervr, libgbm-dev
|
||||||
|
Description: A simple OpenGL/OpenCL test application
|
||||||
|
.
|
||||||
|
This package contains a simple test application that demonstrates basic
|
||||||
|
functionality of OpenGL ES & OpenCL on the RISC-V architecture.
|
||||||
|
|
141
debian/copyright
vendored
Normal file
141
debian/copyright
vendored
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: k1x-gpu-test
|
||||||
|
Upstream-Contact: <preferred name and address to reach the upstream project>
|
||||||
|
Source: <url://example.com>
|
||||||
|
#
|
||||||
|
# Please double check copyright with the licensecheck(1) command.
|
||||||
|
|
||||||
|
Files: CMakeLists.txt
|
||||||
|
common/include/utils_opengles.h
|
||||||
|
common/source/utils_opengles.c
|
||||||
|
cube_demo.c
|
||||||
|
data/bianbu.png
|
||||||
|
square_demo.c
|
||||||
|
texture_square_rotation_demo.c
|
||||||
|
triangle_demo.c
|
||||||
|
Copyright: __NO_COPYRIGHT_NOR_LICENSE__
|
||||||
|
License: __NO_COPYRIGHT_NOR_LICENSE__
|
||||||
|
|
||||||
|
Files: common/include/xdg-shell-client-protocol.h
|
||||||
|
Copyright: 2008-2013 Kristian Høgsberg
|
||||||
|
2010-2013 Intel Corporation
|
||||||
|
2013 Jasper St. Pierre
|
||||||
|
2013 Rafael Antognolli
|
||||||
|
2015-2017 Red Hat Inc.
|
||||||
|
2015-2017 Samsung Electronics Co., Ltd
|
||||||
|
License: MIT
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
.
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
Files: common/source/xdg-shell-protocol.c
|
||||||
|
Copyright: 2008-2013 Kristian Høgsberg
|
||||||
|
2010-2013 Intel Corporation
|
||||||
|
2013 Jasper St. Pierre
|
||||||
|
2013 Rafael Antognolli
|
||||||
|
2015-2017 Red Hat Inc.
|
||||||
|
2015-2017 Samsung Electronics Co., Ltd
|
||||||
|
License: MIT
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
.
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Files: common/include/stb_image.h
|
||||||
|
Copyright: 2017 Sean Barrett
|
||||||
|
License: __UNKNOWN__
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
__MANY_TOTAL_LINES__(7954lines) truncating at: this software and associated documentation files (the "Software"
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
__MANY_TOTAL_LINES__(7955lines) truncating at: the Software without restriction, including without limitation t
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
__MANY_TOTAL_LINES__(7956lines) truncating at: use, copy, modify, merge, publish, distribute, sublicense, and/o
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
__MANY_TOTAL_LINES__(7957lines) truncating at: of the Software, and to permit persons to whom the Software is f
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
__MANY_TOTAL_LINES__(7958lines) truncating at: so, subject to the following conditions:
|
||||||
|
so, subject to the following conditions:
|
||||||
|
__MANY_TOTAL_LINES__(7959lines) truncating at: The above copyright notice and this permission notice shall be i
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
__MANY_TOTAL_LINES__(7960lines) truncating at: copies or substantial portions of the Software.
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
__MANY_TOTAL_LINES__(7961lines) truncating at: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
__MANY_TOTAL_LINES__(7962lines) truncating at: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANT
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
__MANY_TOTAL_LINES__(7963lines) truncating at: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVEN
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
__MANY_TOTAL_LINES__(7964lines) truncating at: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
__MANY_TOTAL_LINES__(7965lines) truncating at: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
__MANY_TOTAL_LINES__(7966lines) truncating at: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DE
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
__MANY_TOTAL_LINES__(7967lines) truncating at: SOFTWARE.
|
||||||
|
SOFTWARE.
|
||||||
|
__MANY_TOTAL_LINES__(7968lines) truncating at: ----------------------------------------------------------------
|
||||||
|
|
||||||
|
Files: README.md
|
||||||
|
Copyright: 2024 SpacemiT
|
||||||
|
License: BSD-3-Clause
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
.
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
.
|
||||||
|
2. 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.
|
||||||
|
.
|
||||||
|
3. Neither the name of the copyright holder 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 HOLDER 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.
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the BSD 3-clause "New" or "Revised"
|
||||||
|
License can be found in `/usr/share/common-licenses/BSD'.
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------
|
||||||
|
# Files marked as NO_LICENSE_TEXT_FOUND may be covered by the following
|
||||||
|
# license/copyright files.
|
17
debian/rules
vendored
Executable file
17
debian/rules
vendored
Executable file
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/make -f
|
||||||
|
|
||||||
|
include /usr/share/dpkg/pkg-info.mk
|
||||||
|
SUPPORT = https://www.debian.org/support
|
||||||
|
|
||||||
|
export DEB_BUILD_OPTIONS = noopt
|
||||||
|
|
||||||
|
# Include common rules from debhelper
|
||||||
|
%:
|
||||||
|
dh $@
|
||||||
|
|
||||||
|
override_dh_auto_clean:
|
||||||
|
@echo "Cleaning up..."
|
||||||
|
rm -rf build
|
||||||
|
|
||||||
|
override_dh_shlibdeps:
|
||||||
|
dh_shlibdeps --dpkg-shlibdeps-params="--ignore-missing-info"
|
10
debian/salsa-ci.yml
vendored
Normal file
10
debian/salsa-ci.yml
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# For more information on what jobs are run see:
|
||||||
|
# https://salsa.debian.org/salsa-ci-team/pipeline
|
||||||
|
#
|
||||||
|
# To enable the jobs, go to your repository (at salsa.debian.org)
|
||||||
|
# and click over Settings > CI/CD > Expand (in General pipelines).
|
||||||
|
# In "CI/CD configuration file" write debian/salsa-ci.yml and click
|
||||||
|
# in "Save Changes". The CI tests will run after the next commit.
|
||||||
|
---
|
||||||
|
include:
|
||||||
|
- https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml
|
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
3.0 (native)
|
9
debian/tests/control
vendored
Normal file
9
debian/tests/control
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#
|
||||||
|
# DEP-8: autopkgtest - automatic as-installed package testing
|
||||||
|
# Please check * https://dep-team.pages.debian.net/deps/dep8/
|
||||||
|
# * /usr/share/doc/autopkgtest
|
||||||
|
#
|
||||||
|
# !!! Please make sure to edit this to a valid test, otherwise build will fails
|
||||||
|
#
|
||||||
|
#Tests: testcode.sh
|
||||||
|
#Restrictions: allow-stderr, breaks-testbed, needs-internet, needs-root
|
16
debian/upstream/metadata
vendored
Normal file
16
debian/upstream/metadata
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#
|
||||||
|
# DEP-12: Per-package machine-readable metadata about Upstream
|
||||||
|
# Please check * https://dep-team.pages.debian.net/deps/dep12/
|
||||||
|
# * https://wiki.debian.org/UpstreamMetadata
|
||||||
|
Reference:
|
||||||
|
Author: <please use full names and separate multiple author by the keyword "and">
|
||||||
|
Title:
|
||||||
|
Journal:
|
||||||
|
Year:
|
||||||
|
Volume:
|
||||||
|
Number:
|
||||||
|
Pages:
|
||||||
|
DOI:
|
||||||
|
PMID:
|
||||||
|
URL:
|
||||||
|
eprint:
|
2
debian/watch
vendored
Normal file
2
debian/watch
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# You must remove unused comment lines for the released package.
|
||||||
|
version=3
|
16
openCLDemo/CMakeLists.txt
Normal file
16
openCLDemo/CMakeLists.txt
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# Define the OpenCL version
|
||||||
|
add_definitions(-DCL_TARGET_OPENCL_VERSION=300) # For OpenCL 3.0
|
||||||
|
|
||||||
|
# Add Link Library
|
||||||
|
set(LINK_LIBRARIES
|
||||||
|
PVROCL
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(gpu-addDemo ${CMAKE_CURRENT_SOURCE_DIR}/add_demo.c)
|
||||||
|
|
||||||
|
target_link_libraries(gpu-addDemo ${LINK_LIBRARIES})
|
||||||
|
|
||||||
|
install(
|
||||||
|
TARGETS
|
||||||
|
gpu-addDemo
|
||||||
|
DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
|
50
openCLDemo/ReadMe.md
Normal file
50
openCLDemo/ReadMe.md
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# openGL Demo
|
||||||
|
|
||||||
|
## 1.简介
|
||||||
|
|
||||||
|
OpenCL(Open Computing Language),即开放计算语言,最初由苹果公司(Apple)提出,后交由非盈利组织Khronos维护。使用OpenCL可以让程序内部并发地执行。
|
||||||
|
|
||||||
|
## 2.使用指南
|
||||||
|
|
||||||
|
### 2.1克隆仓库
|
||||||
|
|
||||||
|
```git
|
||||||
|
git clone git@gitlab.dc.com:bianbu/graphics/k1x-gpu-test.git
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2进到源码目录使用cmake进行编译
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd k1x-gpu-test/openGLDemo
|
||||||
|
cmake .
|
||||||
|
make -j
|
||||||
|
```
|
||||||
|
|
||||||
|
编译完成后会在当前目录下生成 gpu-addDemo 文件,直接运行即可:./gpu-addDemo。如需安装,可在当前目录(即源码目录)下执行 make install 命令,会自动将可执行文件安装到 /usr/local/bin/ 目录下,安装完成后可直接运行:gpu-addDemo。
|
||||||
|
|
||||||
|
### 2.3添加Demo
|
||||||
|
|
||||||
|
如果增加一个名为 testDemo.c 的文件,并希望编译得到名为 testDemo 的可执行文件,可按以下示例修改CMakeLists.txt
|
||||||
|
|
||||||
|
```CMake
|
||||||
|
# 定义 OpenCL 版本为 300
|
||||||
|
add_definitions(-DCL_TARGET_OPENCL_VERSION=300)
|
||||||
|
|
||||||
|
# 添加链接库
|
||||||
|
set(LINK_LIBRARIES PVROCL) //设置链接库变量,指定链接库名称
|
||||||
|
|
||||||
|
add_executable(gpu-addDemo ${CMAKE_CURRENT_SOURCE_DIR}/add_demo.c)
|
||||||
|
add_executable(testDemo ${CMAKE_CURRENT_SOURCE_DIR}/testDemo.c) # 创建新的可执行文件
|
||||||
|
|
||||||
|
# 链接库,将指定的链接库与可执行文件链接
|
||||||
|
target_link_libraries(gpu-addDemo ${LINK_LIBRARIES})
|
||||||
|
target_link_libraries(testDemo ${LINK_LIBRARIES})
|
||||||
|
|
||||||
|
# 安装, 将可执行文件安装到指定目录
|
||||||
|
install(TARGETS
|
||||||
|
gpu-addDemo
|
||||||
|
testDemo #安装新的可执行文件
|
||||||
|
DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
|
||||||
|
```
|
||||||
|
|
||||||
|
然后再次执行 make -j 即可。
|
299
openCLDemo/add_demo.c
Normal file
299
openCLDemo/add_demo.c
Normal file
|
@ -0,0 +1,299 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <CL/cl.h>
|
||||||
|
|
||||||
|
// OpenCL kernel to perform an element-wise addition
|
||||||
|
#if 1
|
||||||
|
const char *programSource =
|
||||||
|
"__kernel \n"
|
||||||
|
"void vec_add(__global float *A, \n"
|
||||||
|
" __global float *B, \n"
|
||||||
|
" __global float *C) \n"
|
||||||
|
"{ \n"
|
||||||
|
" // Get the work-item's unique ID \n"
|
||||||
|
" int idx = (get_global_id(0) << 2) & (16384 - 1); \n"
|
||||||
|
" float4 vector_a = vload4(0, A + idx); \n"
|
||||||
|
" float4 vector_b = vload4(0, B + idx); \n"
|
||||||
|
" float4 vector_c = vector_a + vector_b; \n"
|
||||||
|
" \n"
|
||||||
|
" // Add the corresponding locations of \n"
|
||||||
|
" // 'A' and 'B', and store the reasult in 'C' \n"
|
||||||
|
" vstore4(vector_c, 0, C + idx); \n"
|
||||||
|
"} \n";
|
||||||
|
#else
|
||||||
|
// OpenCL kernel to perform an element-wise addition
|
||||||
|
const char *programSource =
|
||||||
|
"__kernel \n"
|
||||||
|
"void vec_add(__global float *A, \n"
|
||||||
|
" __global float *B, \n"
|
||||||
|
" __global float *C) \n"
|
||||||
|
"{ \n"
|
||||||
|
" // Get the work-item's unique ID \n"
|
||||||
|
" int idx = get_global_id(0); \n"
|
||||||
|
" \n"
|
||||||
|
" // Add the corresponding locations of \n"
|
||||||
|
" // 'A' and 'B', and store the reasult in 'C' \n"
|
||||||
|
" C[idx] = A[idx] + B[idx]; \n"
|
||||||
|
"} \n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Choose OpenCL platform and create a context
|
||||||
|
cl_context CreateContext()
|
||||||
|
{
|
||||||
|
/* 1. get platform information */
|
||||||
|
cl_uint num_platforms;
|
||||||
|
cl_platform_id first_platform_id;
|
||||||
|
cl_int err_num;
|
||||||
|
|
||||||
|
// get num_platforms and platforms ID
|
||||||
|
err_num = clGetPlatformIDs(1, &first_platform_id, &num_platforms);
|
||||||
|
if (err_num != CL_SUCCESS || num_platforms <= 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to get number of platforms: %d\n", err_num);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2. create context */
|
||||||
|
cl_context context = NULL;
|
||||||
|
cl_context_properties context_prop[] = {
|
||||||
|
CL_CONTEXT_PLATFORM,
|
||||||
|
(cl_context_properties)first_platform_id,
|
||||||
|
0};
|
||||||
|
|
||||||
|
context = clCreateContextFromType(context_prop, CL_DEVICE_TYPE_ALL, NULL, NULL, &err_num);
|
||||||
|
|
||||||
|
if (err_num != CL_SUCCESS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to create context: %d\n", err_num);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create command queue */
|
||||||
|
cl_command_queue CreateCommandQueue(cl_context context, cl_device_id *device)
|
||||||
|
{
|
||||||
|
cl_int err_num;
|
||||||
|
cl_device_id *devices_arr;
|
||||||
|
cl_command_queue command_queue = NULL;
|
||||||
|
size_t deviceBufferSize = -1;
|
||||||
|
|
||||||
|
// Get device buffer size
|
||||||
|
err_num = clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &deviceBufferSize);
|
||||||
|
|
||||||
|
if (deviceBufferSize <= 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "No devices available: %d\n", err_num);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate cache space for devices
|
||||||
|
devices_arr = malloc(deviceBufferSize / sizeof(cl_device_id));
|
||||||
|
err_num = clGetContextInfo(context, CL_CONTEXT_DEVICES, deviceBufferSize, devices_arr, NULL);
|
||||||
|
|
||||||
|
// Select the first available device
|
||||||
|
command_queue = clCreateCommandQueueWithProperties(context, devices_arr[0], 0, NULL);
|
||||||
|
|
||||||
|
*device = devices_arr[0];
|
||||||
|
free(devices_arr);
|
||||||
|
return command_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and build program objects
|
||||||
|
cl_program CreateProgram(cl_context context, cl_device_id device, const char *srcStr)
|
||||||
|
{
|
||||||
|
cl_int err_num;
|
||||||
|
cl_program program;
|
||||||
|
|
||||||
|
program = clCreateProgramWithSource(context, 1, (const char **)&srcStr, NULL, &err_num);
|
||||||
|
|
||||||
|
if (err_num != CL_SUCCESS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to create program: %d\n", err_num);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// err_num = clBuildProgram(program, 1, &device, NULL, NULL, NULL);
|
||||||
|
err_num = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
|
||||||
|
if (err_num != CL_SUCCESS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to build program: %d\n", err_num);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create memory object
|
||||||
|
bool CreateMemObjects(cl_context context, cl_mem mem_objects[3], float *a, float *b, size_t datasize)
|
||||||
|
{
|
||||||
|
mem_objects[0] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
|
||||||
|
datasize, a, NULL);
|
||||||
|
mem_objects[1] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
|
||||||
|
datasize, b, NULL);
|
||||||
|
mem_objects[2] = clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||||
|
datasize, NULL, NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
void Cleanup(cl_context context, cl_command_queue command_queue,
|
||||||
|
cl_program program, cl_kernel kernel, cl_mem mem_objects[3])
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (mem_objects[i] != 0)
|
||||||
|
clReleaseMemObject(mem_objects[i]);
|
||||||
|
}
|
||||||
|
if (command_queue != 0)
|
||||||
|
clReleaseCommandQueue(command_queue);
|
||||||
|
|
||||||
|
if (kernel != 0)
|
||||||
|
clReleaseKernel(kernel);
|
||||||
|
|
||||||
|
if (program != 0)
|
||||||
|
clReleaseProgram(program);
|
||||||
|
|
||||||
|
if (context != 0)
|
||||||
|
clReleaseContext(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
struct timeval tv_start, tv_end;
|
||||||
|
uint64_t time_start, time_end;
|
||||||
|
|
||||||
|
cl_int err_num = 0;
|
||||||
|
cl_context context = 0;
|
||||||
|
cl_command_queue command_queue = 0;
|
||||||
|
cl_program program = 0;
|
||||||
|
cl_device_id device = 0;
|
||||||
|
cl_kernel kernel = 0;
|
||||||
|
cl_mem mem_objects[3] = {0, 0, 0};
|
||||||
|
|
||||||
|
/* 1. Choose OpenCL platform and create a context */
|
||||||
|
context = CreateContext();
|
||||||
|
fprintf(stderr, "Create context success.\n");
|
||||||
|
/* 2. Create command queue */
|
||||||
|
command_queue = CreateCommandQueue(context, &device);
|
||||||
|
fprintf(stderr, "Create command queue success.\n");
|
||||||
|
/* 3. Create and build program objects */
|
||||||
|
program = CreateProgram(context, device, programSource);
|
||||||
|
fprintf(stderr, "Create program success.\n");
|
||||||
|
|
||||||
|
/* 4. create kernel */
|
||||||
|
kernel = clCreateKernel(program, "vec_add", &err_num);
|
||||||
|
if (err_num != CL_SUCCESS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to create kernel: %d\n", err_num);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 5. set input data && create memory object */
|
||||||
|
|
||||||
|
// Elements in each array
|
||||||
|
const int elements = 102400000;
|
||||||
|
// Compute the size of the data
|
||||||
|
size_t datasize = sizeof(float) * (16384);
|
||||||
|
// Allocate space for input/output host data
|
||||||
|
float *A = (float *)malloc(datasize); // Input array
|
||||||
|
float *B = (float *)malloc(datasize); // Input array
|
||||||
|
float *C = (float *)malloc(datasize); // Output array
|
||||||
|
// Initialize the input data
|
||||||
|
for (int i = 0; i < (16384); i++)
|
||||||
|
{
|
||||||
|
A[i] = (float)i;
|
||||||
|
B[i] = 3.0 * (float)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create MemObjects
|
||||||
|
if (!CreateMemObjects(context, mem_objects, A, B, datasize))
|
||||||
|
{
|
||||||
|
Cleanup(context, command_queue, program, kernel, mem_objects);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write data from the input arrays to the buffers
|
||||||
|
err_num = clEnqueueWriteBuffer(command_queue, mem_objects[0], CL_FALSE, 0, datasize, A, 0, NULL, NULL);
|
||||||
|
err_num = clEnqueueWriteBuffer(command_queue, mem_objects[1], CL_FALSE, 0, datasize, B, 0, NULL, NULL);
|
||||||
|
|
||||||
|
/* 6. set kernel argument */
|
||||||
|
err_num = clSetKernelArg(kernel, 0, sizeof(cl_mem), &mem_objects[0]);
|
||||||
|
if (err_num != CL_SUCCESS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to set kernel argument 0: %d\n", err_num);
|
||||||
|
Cleanup(context, command_queue, program, kernel, mem_objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
err_num = clSetKernelArg(kernel, 1, sizeof(cl_mem), &mem_objects[1]);
|
||||||
|
if (err_num != CL_SUCCESS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to set kernel argument 1: %d\n", err_num);
|
||||||
|
Cleanup(context, command_queue, program, kernel, mem_objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
err_num = clSetKernelArg(kernel, 2, sizeof(cl_mem), &mem_objects[2]);
|
||||||
|
if (err_num != CL_SUCCESS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to set kernel argument 2: %d\n", err_num);
|
||||||
|
Cleanup(context, command_queue, program, kernel, mem_objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
gettimeofday(&tv_start, NULL);
|
||||||
|
/* 7. send kernel to execute */
|
||||||
|
size_t globalWorkSize[] = {elements / 4, 1, 1};
|
||||||
|
size_t localWorkSize[] = {32, 1, 1};
|
||||||
|
int num_loops = 1;
|
||||||
|
for (int batch = 0; batch < num_loops; batch += 1)
|
||||||
|
{
|
||||||
|
err_num = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, globalWorkSize,
|
||||||
|
localWorkSize, 0, NULL, NULL);
|
||||||
|
if (err_num != CL_SUCCESS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to enqueue kernel: %d\n", err_num);
|
||||||
|
Cleanup(context, command_queue, program, kernel, mem_objects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
/* 8. read data from output */
|
||||||
|
err_num = clEnqueueReadBuffer(command_queue, mem_objects[2], CL_TRUE, 0, datasize, C, 0, NULL, NULL);
|
||||||
|
if (err_num != CL_SUCCESS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to read buffer: %d\n", err_num);
|
||||||
|
Cleanup(context, command_queue, program, kernel, mem_objects);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
clFinish(command_queue);
|
||||||
|
gettimeofday(&tv_end, NULL);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
for (int i = 0; i < 16384; i++)
|
||||||
|
{
|
||||||
|
printf("%f ", C[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
long int start_time_us = tv_start.tv_sec * 1000000L + tv_start.tv_usec;
|
||||||
|
long int end_time_us = tv_end.tv_sec * 1000000L + tv_end.tv_usec;
|
||||||
|
|
||||||
|
long int diff_time_us = end_time_us - start_time_us;
|
||||||
|
|
||||||
|
printf("Start time: %ld sec, %ld usec\n", tv_start.tv_sec, tv_start.tv_usec);
|
||||||
|
printf("End time: %ld sec, %ld usec\n", tv_end.tv_sec, tv_end.tv_usec);
|
||||||
|
printf("Calculate time for %d addition operations: %ld us\n", elements * num_loops, diff_time_us);
|
||||||
|
|
||||||
|
/* 9. clean up */
|
||||||
|
free(A);
|
||||||
|
free(B);
|
||||||
|
free(C);
|
||||||
|
Cleanup(context, command_queue, program, kernel, mem_objects);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
56
openGLDemo/CMakeLists.txt
Normal file
56
openGLDemo/CMakeLists.txt
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
add_definitions(-DSTB_IMAGE_IMPLEMENTATION)
|
||||||
|
add_definitions(-DNDEBUG)
|
||||||
|
|
||||||
|
# Define a public source file list
|
||||||
|
set(COMMON_SOURCE_FILES
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/common/source/xdg-shell-protocol.c
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/common/source/utils_opengles.c
|
||||||
|
)
|
||||||
|
|
||||||
|
# set(CMAKE_BUILD_TYPE Debug)
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/common/include/
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add Link Library
|
||||||
|
set(LINK_LIBRARIES
|
||||||
|
EGL
|
||||||
|
GLESv2
|
||||||
|
wayland-client
|
||||||
|
wayland-server
|
||||||
|
wayland-egl
|
||||||
|
m
|
||||||
|
wayland-cursor
|
||||||
|
gbm
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(gpu-cubeDemo ${CMAKE_CURRENT_SOURCE_DIR}/cube_demo.c ${COMMON_SOURCE_FILES})
|
||||||
|
add_executable(gpu-textureDemo ${CMAKE_CURRENT_SOURCE_DIR}/texture_square_rotation_demo.c ${COMMON_SOURCE_FILES})
|
||||||
|
add_executable(gpu-squareDemo ${CMAKE_CURRENT_SOURCE_DIR}/square_demo.c ${COMMON_SOURCE_FILES})
|
||||||
|
add_executable(gpu-triangleDemo ${CMAKE_CURRENT_SOURCE_DIR}/triangle_demo.c ${COMMON_SOURCE_FILES})
|
||||||
|
add_executable(gpu-cubeTextureDemo ${CMAKE_CURRENT_SOURCE_DIR}/cube_texture_demo.c ${COMMON_SOURCE_FILES})
|
||||||
|
add_executable(gpu-externalTextureDemo ${CMAKE_CURRENT_SOURCE_DIR}/cube_externalTexture_demo.c ${COMMON_SOURCE_FILES})
|
||||||
|
|
||||||
|
target_link_libraries(gpu-cubeDemo ${LINK_LIBRARIES})
|
||||||
|
target_link_libraries(gpu-textureDemo ${LINK_LIBRARIES})
|
||||||
|
target_link_libraries(gpu-squareDemo ${LINK_LIBRARIES})
|
||||||
|
target_link_libraries(gpu-triangleDemo ${LINK_LIBRARIES})
|
||||||
|
target_link_libraries(gpu-cubeTextureDemo ${LINK_LIBRARIES})
|
||||||
|
target_link_libraries(gpu-externalTextureDemo ${LINK_LIBRARIES})
|
||||||
|
|
||||||
|
install(
|
||||||
|
TARGETS
|
||||||
|
gpu-cubeDemo
|
||||||
|
gpu-textureDemo
|
||||||
|
gpu-squareDemo
|
||||||
|
gpu-triangleDemo
|
||||||
|
gpu-cubeTextureDemo
|
||||||
|
gpu-externalTextureDemo
|
||||||
|
DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
|
||||||
|
|
||||||
|
file(GLOB IMAGE_FILES "data/*.png")
|
||||||
|
install(
|
||||||
|
FILES ${IMAGE_FILES}
|
||||||
|
DESTINATION "${CMAKE_INSTALL_PREFIX}/data")
|
9333
openGLDemo/common/include/stb_image.h
Normal file
9333
openGLDemo/common/include/stb_image.h
Normal file
File diff suppressed because it is too large
Load diff
359
openGLDemo/common/include/utils_opengles.h
Normal file
359
openGLDemo/common/include/utils_opengles.h
Normal file
|
@ -0,0 +1,359 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2011 Benjamin Franzke
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UTILS_OPENGLES_H
|
||||||
|
#define UTILS_OPENGLES_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include <GLES3/gl3.h>
|
||||||
|
#include <GLES3/gl3ext.h>
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <EGL/eglext.h>
|
||||||
|
|
||||||
|
#include "xdg-shell-client-protocol.h"
|
||||||
|
|
||||||
|
#ifndef EGL_WL_bind_wayland_display
|
||||||
|
#define EGL_WL_bind_wayland_display 1
|
||||||
|
|
||||||
|
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||||
|
EGLAPI EGLBoolean EGLAPIENTRY eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display);
|
||||||
|
EGLAPI EGLBoolean EGLAPIENTRY eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display);
|
||||||
|
#endif
|
||||||
|
typedef EGLBoolean(EGLAPIENTRYP PFNEGLBINDWAYLANDDISPLAYWL)(EGLDisplay dpy, struct wl_display *display);
|
||||||
|
typedef EGLBoolean(EGLAPIENTRYP PFNEGLUNBINDWAYLANDDISPLAYWL)(EGLDisplay dpy, struct wl_display *display);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a little different to the tests shipped with EGL implementations,
|
||||||
|
* which wrap the entire thing in #ifndef EGL_WL_bind_wayland_display, then go
|
||||||
|
* on to define both BindWaylandDisplay and QueryWaylandBuffer.
|
||||||
|
*
|
||||||
|
* Unfortunately, some implementations (particularly the version of Mesa shipped
|
||||||
|
* in Ubuntu 12.04) define EGL_WL_bind_wayland_display, but then only provide
|
||||||
|
* prototypes for (Un)BindWaylandDisplay, completely omitting
|
||||||
|
* QueryWaylandBuffer.
|
||||||
|
*
|
||||||
|
* Detect this, and provide our own definitions if necessary.
|
||||||
|
*/
|
||||||
|
#ifndef EGL_WAYLAND_BUFFER_WL
|
||||||
|
#define EGL_WAYLAND_BUFFER_WL 0x31D5 /* eglCreateImageKHR target */
|
||||||
|
#define EGL_WAYLAND_PLANE_WL 0x31D6 /* eglCreateImageKHR target */
|
||||||
|
|
||||||
|
#define EGL_TEXTURE_Y_U_V_WL 0x31D7
|
||||||
|
#define EGL_TEXTURE_Y_UV_WL 0x31D8
|
||||||
|
#define EGL_TEXTURE_Y_XUXV_WL 0x31D9
|
||||||
|
#define EGL_TEXTURE_EXTERNAL_WL 0x31DA
|
||||||
|
|
||||||
|
struct wl_resource;
|
||||||
|
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||||
|
EGLAPI EGLBoolean EGLAPIENTRY eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value);
|
||||||
|
#endif
|
||||||
|
typedef EGLBoolean(EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL)(EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EGL_WL_create_wayland_buffer_from_image
|
||||||
|
#define EGL_WL_create_wayland_buffer_from_image 1
|
||||||
|
|
||||||
|
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||||
|
EGLAPI struct wl_buffer *EGLAPIENTRY eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImageKHR image);
|
||||||
|
#endif
|
||||||
|
typedef struct wl_buffer *(EGLAPIENTRYP PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL)(EGLDisplay dpy, EGLImageKHR image);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EGL_TEXTURE_EXTERNAL_WL
|
||||||
|
#define EGL_TEXTURE_EXTERNAL_WL 0x31DA
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EGL_BUFFER_AGE_EXT
|
||||||
|
#define EGL_BUFFER_AGE_EXT 0x313D
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EGL_WAYLAND_Y_INVERTED_WL
|
||||||
|
#define EGL_WAYLAND_Y_INVERTED_WL 0x31DB /* eglQueryWaylandBufferWL attribute */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_EXT_unpack_subimage
|
||||||
|
#define GL_EXT_unpack_subimage 1
|
||||||
|
#define GL_UNPACK_ROW_LENGTH_EXT 0x0CF2
|
||||||
|
#define GL_UNPACK_SKIP_ROWS_EXT 0x0CF3
|
||||||
|
#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4
|
||||||
|
#endif /* GL_EXT_unpack_subimage */
|
||||||
|
|
||||||
|
/* Mesas gl2ext.h and probably Khronos upstream defined
|
||||||
|
* GL_EXT_unpack_subimage with non _EXT suffixed GL_UNPACK_* tokens.
|
||||||
|
* In case we're using that mess, manually define the _EXT versions
|
||||||
|
* of the tokens here.*/
|
||||||
|
#if defined(GL_EXT_unpack_subimage) && !defined(GL_UNPACK_ROW_LENGTH_EXT)
|
||||||
|
#define GL_UNPACK_ROW_LENGTH_EXT 0x0CF2
|
||||||
|
#define GL_UNPACK_SKIP_ROWS_EXT 0x0CF3
|
||||||
|
#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define needed tokens from EGL_EXT_image_dma_buf_import extension
|
||||||
|
* here to avoid having to add ifdefs everywhere.*/
|
||||||
|
#ifndef EGL_EXT_image_dma_buf_import
|
||||||
|
#define EGL_LINUX_DMA_BUF_EXT 0x3270
|
||||||
|
#define EGL_LINUX_DRM_FOURCC_EXT 0x3271
|
||||||
|
#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272
|
||||||
|
#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273
|
||||||
|
#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274
|
||||||
|
#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275
|
||||||
|
#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276
|
||||||
|
#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277
|
||||||
|
#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278
|
||||||
|
#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279
|
||||||
|
#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define tokens from EGL_EXT_image_dma_buf_import_modifiers */
|
||||||
|
#ifndef EGL_EXT_image_dma_buf_import_modifiers
|
||||||
|
#define EGL_EXT_image_dma_buf_import_modifiers 1
|
||||||
|
#define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440
|
||||||
|
#define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441
|
||||||
|
#define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442
|
||||||
|
#define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443
|
||||||
|
#define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444
|
||||||
|
#define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445
|
||||||
|
#define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446
|
||||||
|
#define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447
|
||||||
|
#define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448
|
||||||
|
#define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449
|
||||||
|
#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A
|
||||||
|
typedef EGLBoolean(EGLAPIENTRYP PFNEGLQUERYDMABUFFORMATSEXTPROC)(EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats);
|
||||||
|
typedef EGLBoolean(EGLAPIENTRYP PFNEGLQUERYDMABUFMODIFIERSEXTPROC)(EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define tokens from EGL_EXT_device_base */
|
||||||
|
#ifndef EGL_EXT_device_base
|
||||||
|
#define EGL_EXT_device_base 1
|
||||||
|
typedef void *EGLDeviceEXT;
|
||||||
|
#define EGL_NO_DEVICE_EXT EGL_CAST(EGLDeviceEXT, 0)
|
||||||
|
#define EGL_BAD_DEVICE_EXT 0x322B
|
||||||
|
#define EGL_DEVICE_EXT 0x322C
|
||||||
|
typedef EGLBoolean(EGLAPIENTRYP PFNEGLQUERYDEVICEATTRIBEXTPROC)(EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
|
||||||
|
typedef const char *(EGLAPIENTRYP PFNEGLQUERYDEVICESTRINGEXTPROC)(EGLDeviceEXT device, EGLint name);
|
||||||
|
typedef EGLBoolean(EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC)(EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
|
||||||
|
typedef EGLBoolean(EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBEXTPROC)(EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
|
||||||
|
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||||
|
EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
|
||||||
|
EGLAPI const char *EGLAPIENTRY eglQueryDeviceStringEXT(EGLDeviceEXT device, EGLint name);
|
||||||
|
EGLAPI EGLBoolean EGLAPIENTRY eglQueryDevicesEXT(EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
|
||||||
|
EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
|
||||||
|
#endif
|
||||||
|
#endif /* EGL_EXT_device_base */
|
||||||
|
|
||||||
|
/* Define tokens from EGL_EXT_device_drm */
|
||||||
|
#ifndef EGL_EXT_device_drm
|
||||||
|
#define EGL_EXT_device_drm 1
|
||||||
|
#define EGL_DRM_DEVICE_FILE_EXT 0x3233
|
||||||
|
#define EGL_DRM_MASTER_FD_EXT 0x333C
|
||||||
|
#endif /* EGL_EXT_device_drm */
|
||||||
|
|
||||||
|
/* Define tokens from EGL_EXT_device_drm_render_node */
|
||||||
|
#ifndef EGL_EXT_device_drm_render_node
|
||||||
|
#define EGL_EXT_device_drm_render_node 1
|
||||||
|
#define EGL_DRM_RENDER_NODE_FILE_EXT 0x3377
|
||||||
|
#endif /* EGL_EXT_device_drm_render_node */
|
||||||
|
|
||||||
|
#ifndef EGL_EXT_swap_buffers_with_damage
|
||||||
|
#define EGL_EXT_swap_buffers_with_damage 1
|
||||||
|
typedef EGLBoolean(EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC)(EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
|
||||||
|
#endif /* EGL_EXT_swap_buffers_with_damage */
|
||||||
|
|
||||||
|
#ifndef EGL_MESA_configless_context
|
||||||
|
#define EGL_MESA_configless_context 1
|
||||||
|
#define EGL_NO_CONFIG_MESA ((EGLConfig)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EGL_NO_CONFIG_KHR
|
||||||
|
#define EGL_NO_CONFIG_KHR ((EGLConfig)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EGL_EXT_platform_base
|
||||||
|
#define EGL_EXT_platform_base 1
|
||||||
|
typedef EGLDisplay(EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum platform, void *native_display, const EGLint *attrib_list);
|
||||||
|
typedef EGLSurface(EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
|
||||||
|
typedef EGLSurface(EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC)(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
|
||||||
|
#endif /* EGL_EXT_platform_base */
|
||||||
|
|
||||||
|
#ifndef EGL_PLATFORM_GBM_KHR
|
||||||
|
#define EGL_PLATFORM_GBM_KHR 0x31D7
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EGL_PLATFORM_WAYLAND_KHR
|
||||||
|
#define EGL_PLATFORM_WAYLAND_KHR 0x31D8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EGL_PLATFORM_X11_KHR
|
||||||
|
#define EGL_PLATFORM_X11_KHR 0x31D5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EGL_PLATFORM_SURFACELESS_MESA
|
||||||
|
#define EGL_PLATFORM_SURFACELESS_MESA 0x31DD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EGL_KHR_cl_event2
|
||||||
|
#define EGL_KHR_cl_event2 1
|
||||||
|
typedef void *EGLSyncKHR;
|
||||||
|
#endif /* EGL_KHR_cl_event2 */
|
||||||
|
|
||||||
|
#ifndef EGL_NO_SYNC_KHR
|
||||||
|
#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EGL_KHR_fence_sync
|
||||||
|
#define EGL_KHR_fence_sync 1
|
||||||
|
typedef EGLSyncKHR(EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC)(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
|
||||||
|
typedef EGLBoolean(EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC)(EGLDisplay dpy, EGLSyncKHR sync);
|
||||||
|
#endif /* EGL_KHR_fence_sync */
|
||||||
|
|
||||||
|
#ifndef EGL_ANDROID_native_fence_sync
|
||||||
|
#define EGL_ANDROID_native_fence_sync 1
|
||||||
|
typedef EGLint(EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC)(EGLDisplay dpy, EGLSyncKHR sync);
|
||||||
|
#endif /* EGL_ANDROID_native_fence_sync */
|
||||||
|
|
||||||
|
#ifndef EGL_SYNC_NATIVE_FENCE_ANDROID
|
||||||
|
#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EGL_NO_NATIVE_FENCE_FD_ANDROID
|
||||||
|
#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PI 3.1415926535897932384626433832795f
|
||||||
|
|
||||||
|
struct Display
|
||||||
|
{
|
||||||
|
struct wl_display *display;
|
||||||
|
struct wl_registry *registry;
|
||||||
|
struct wl_compositor *compositor;
|
||||||
|
struct xdg_wm_base *wm_base;
|
||||||
|
struct wl_seat *seat;
|
||||||
|
struct wl_pointer *pointer;
|
||||||
|
struct wl_touch *touch;
|
||||||
|
struct wl_keyboard *keyboard;
|
||||||
|
struct wl_shm *shm;
|
||||||
|
struct wl_cursor_theme *cursor_theme;
|
||||||
|
struct wl_cursor *default_cursor;
|
||||||
|
struct wl_surface *cursor_surface;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
EGLDisplay dpy;
|
||||||
|
EGLContext ctx;
|
||||||
|
EGLConfig conf;
|
||||||
|
// for external texture
|
||||||
|
bool has_dma_buf_import_modifiers;
|
||||||
|
bool has_no_config_context;
|
||||||
|
} egl;
|
||||||
|
// for external texture
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int drm_fd;
|
||||||
|
struct gbm_device *device;
|
||||||
|
} gbm;
|
||||||
|
struct Window *window;
|
||||||
|
|
||||||
|
PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct geometry
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Window
|
||||||
|
{
|
||||||
|
struct Display *display;
|
||||||
|
struct geometry geometry, window_size;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
GLuint rotation_uniform;
|
||||||
|
GLuint pos;
|
||||||
|
GLuint col;
|
||||||
|
} gl;
|
||||||
|
|
||||||
|
uint32_t benchmark_time, frames;
|
||||||
|
struct wl_egl_window *native;
|
||||||
|
struct wl_surface *surface;
|
||||||
|
struct xdg_surface *xdg_surface;
|
||||||
|
struct xdg_toplevel *xdg_toplevel;
|
||||||
|
EGLSurface egl_surface;
|
||||||
|
struct wl_callback *callback;
|
||||||
|
int fullscreen, maximized, opaque, buffer_size, frame_sync, delay;
|
||||||
|
bool wait_for_configure;
|
||||||
|
void *userData;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int running;
|
||||||
|
} RunningState;
|
||||||
|
|
||||||
|
extern RunningState global_state;
|
||||||
|
|
||||||
|
void log_error(const char *message);
|
||||||
|
|
||||||
|
void init_egl(struct Display *display, struct Window *window);
|
||||||
|
void init_gl(struct Window *window);
|
||||||
|
void create_surface(struct Window *window);
|
||||||
|
void destroy_surface(struct Window *window);
|
||||||
|
void registry_handle_global(void *data, struct wl_registry *registry,
|
||||||
|
uint32_t name, const char *interface, uint32_t version);
|
||||||
|
void registry_handle_global_remove(void *data, struct wl_registry *registry,
|
||||||
|
uint32_t name);
|
||||||
|
void usage(int error_code);
|
||||||
|
|
||||||
|
int create_window(struct Window *window, struct Display *display, int ret);
|
||||||
|
void destroy_window(struct Window *window, struct Display *display);
|
||||||
|
|
||||||
|
GLuint load_shader(const char *source, GLenum shader_type);
|
||||||
|
GLint load_program(const char *vertShaderSrc, const char *fragShaderSrc);
|
||||||
|
GLuint loadTexture(const char *filename);
|
||||||
|
|
||||||
|
unsigned char *load_imageData(const char *filename, int *width, int *height, int *channels, int req_comp);
|
||||||
|
void free_imageData(unsigned char *data);
|
||||||
|
|
||||||
|
void checkProgramLinking(GLuint program);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GLfloat m[4][4];
|
||||||
|
} ESMatrix;
|
||||||
|
|
||||||
|
void esScale(ESMatrix *result, GLfloat sx, GLfloat sy, GLfloat sz);
|
||||||
|
void esTranslate(ESMatrix *result, GLfloat tx, GLfloat ty, GLfloat tz);
|
||||||
|
void esRotate(ESMatrix *result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
|
||||||
|
void esFrustum(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ);
|
||||||
|
void esPerspective(ESMatrix *result, float fovy, float aspect, float nearZ, float farZ);
|
||||||
|
void esOrtho(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ);
|
||||||
|
void esMatrixMultiply(ESMatrix *result, ESMatrix *srcA, ESMatrix *srcB);
|
||||||
|
void esMatrixLoadIdentity(ESMatrix *result);
|
||||||
|
void esMatrixLookAt(ESMatrix *result,
|
||||||
|
float posX, float posY, float posZ,
|
||||||
|
float lookAtX, float lookAtY, float lookAtZ,
|
||||||
|
float upX, float upY, float upZ);
|
||||||
|
|
||||||
|
#endif
|
2280
openGLDemo/common/include/xdg-shell-client-protocol.h
Normal file
2280
openGLDemo/common/include/xdg-shell-client-protocol.h
Normal file
File diff suppressed because it is too large
Load diff
1252
openGLDemo/common/source/utils_opengles.c
Normal file
1252
openGLDemo/common/source/utils_opengles.c
Normal file
File diff suppressed because it is too large
Load diff
183
openGLDemo/common/source/xdg-shell-protocol.c
Normal file
183
openGLDemo/common/source/xdg-shell-protocol.c
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
/* Generated by wayland-scanner 1.21.0 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright © 2008-2013 Kristian Høgsberg
|
||||||
|
* Copyright © 2013 Rafael Antognolli
|
||||||
|
* Copyright © 2013 Jasper St. Pierre
|
||||||
|
* Copyright © 2010-2013 Intel Corporation
|
||||||
|
* Copyright © 2015-2017 Samsung Electronics Co., Ltd
|
||||||
|
* Copyright © 2015-2017 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "wayland-util.h"
|
||||||
|
|
||||||
|
#ifndef __has_attribute
|
||||||
|
# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
|
||||||
|
#define WL_PRIVATE __attribute__ ((visibility("hidden")))
|
||||||
|
#else
|
||||||
|
#define WL_PRIVATE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern const struct wl_interface wl_output_interface;
|
||||||
|
extern const struct wl_interface wl_seat_interface;
|
||||||
|
extern const struct wl_interface wl_surface_interface;
|
||||||
|
extern const struct wl_interface xdg_popup_interface;
|
||||||
|
extern const struct wl_interface xdg_positioner_interface;
|
||||||
|
extern const struct wl_interface xdg_surface_interface;
|
||||||
|
extern const struct wl_interface xdg_toplevel_interface;
|
||||||
|
|
||||||
|
static const struct wl_interface *xdg_shell_types[] = {
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&xdg_positioner_interface,
|
||||||
|
&xdg_surface_interface,
|
||||||
|
&wl_surface_interface,
|
||||||
|
&xdg_toplevel_interface,
|
||||||
|
&xdg_popup_interface,
|
||||||
|
&xdg_surface_interface,
|
||||||
|
&xdg_positioner_interface,
|
||||||
|
&xdg_toplevel_interface,
|
||||||
|
&wl_seat_interface,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&wl_seat_interface,
|
||||||
|
NULL,
|
||||||
|
&wl_seat_interface,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&wl_output_interface,
|
||||||
|
&wl_seat_interface,
|
||||||
|
NULL,
|
||||||
|
&xdg_positioner_interface,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wl_message xdg_wm_base_requests[] = {
|
||||||
|
{ "destroy", "", xdg_shell_types + 0 },
|
||||||
|
{ "create_positioner", "n", xdg_shell_types + 4 },
|
||||||
|
{ "get_xdg_surface", "no", xdg_shell_types + 5 },
|
||||||
|
{ "pong", "u", xdg_shell_types + 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wl_message xdg_wm_base_events[] = {
|
||||||
|
{ "ping", "u", xdg_shell_types + 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
WL_PRIVATE const struct wl_interface xdg_wm_base_interface = {
|
||||||
|
"xdg_wm_base", 5,
|
||||||
|
4, xdg_wm_base_requests,
|
||||||
|
1, xdg_wm_base_events,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wl_message xdg_positioner_requests[] = {
|
||||||
|
{ "destroy", "", xdg_shell_types + 0 },
|
||||||
|
{ "set_size", "ii", xdg_shell_types + 0 },
|
||||||
|
{ "set_anchor_rect", "iiii", xdg_shell_types + 0 },
|
||||||
|
{ "set_anchor", "u", xdg_shell_types + 0 },
|
||||||
|
{ "set_gravity", "u", xdg_shell_types + 0 },
|
||||||
|
{ "set_constraint_adjustment", "u", xdg_shell_types + 0 },
|
||||||
|
{ "set_offset", "ii", xdg_shell_types + 0 },
|
||||||
|
{ "set_reactive", "3", xdg_shell_types + 0 },
|
||||||
|
{ "set_parent_size", "3ii", xdg_shell_types + 0 },
|
||||||
|
{ "set_parent_configure", "3u", xdg_shell_types + 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
WL_PRIVATE const struct wl_interface xdg_positioner_interface = {
|
||||||
|
"xdg_positioner", 5,
|
||||||
|
10, xdg_positioner_requests,
|
||||||
|
0, NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wl_message xdg_surface_requests[] = {
|
||||||
|
{ "destroy", "", xdg_shell_types + 0 },
|
||||||
|
{ "get_toplevel", "n", xdg_shell_types + 7 },
|
||||||
|
{ "get_popup", "n?oo", xdg_shell_types + 8 },
|
||||||
|
{ "set_window_geometry", "iiii", xdg_shell_types + 0 },
|
||||||
|
{ "ack_configure", "u", xdg_shell_types + 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wl_message xdg_surface_events[] = {
|
||||||
|
{ "configure", "u", xdg_shell_types + 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
WL_PRIVATE const struct wl_interface xdg_surface_interface = {
|
||||||
|
"xdg_surface", 5,
|
||||||
|
5, xdg_surface_requests,
|
||||||
|
1, xdg_surface_events,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wl_message xdg_toplevel_requests[] = {
|
||||||
|
{ "destroy", "", xdg_shell_types + 0 },
|
||||||
|
{ "set_parent", "?o", xdg_shell_types + 11 },
|
||||||
|
{ "set_title", "s", xdg_shell_types + 0 },
|
||||||
|
{ "set_app_id", "s", xdg_shell_types + 0 },
|
||||||
|
{ "show_window_menu", "ouii", xdg_shell_types + 12 },
|
||||||
|
{ "move", "ou", xdg_shell_types + 16 },
|
||||||
|
{ "resize", "ouu", xdg_shell_types + 18 },
|
||||||
|
{ "set_max_size", "ii", xdg_shell_types + 0 },
|
||||||
|
{ "set_min_size", "ii", xdg_shell_types + 0 },
|
||||||
|
{ "set_maximized", "", xdg_shell_types + 0 },
|
||||||
|
{ "unset_maximized", "", xdg_shell_types + 0 },
|
||||||
|
{ "set_fullscreen", "?o", xdg_shell_types + 21 },
|
||||||
|
{ "unset_fullscreen", "", xdg_shell_types + 0 },
|
||||||
|
{ "set_minimized", "", xdg_shell_types + 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wl_message xdg_toplevel_events[] = {
|
||||||
|
{ "configure", "iia", xdg_shell_types + 0 },
|
||||||
|
{ "close", "", xdg_shell_types + 0 },
|
||||||
|
{ "configure_bounds", "4ii", xdg_shell_types + 0 },
|
||||||
|
{ "wm_capabilities", "5a", xdg_shell_types + 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
WL_PRIVATE const struct wl_interface xdg_toplevel_interface = {
|
||||||
|
"xdg_toplevel", 5,
|
||||||
|
14, xdg_toplevel_requests,
|
||||||
|
4, xdg_toplevel_events,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wl_message xdg_popup_requests[] = {
|
||||||
|
{ "destroy", "", xdg_shell_types + 0 },
|
||||||
|
{ "grab", "ou", xdg_shell_types + 22 },
|
||||||
|
{ "reposition", "3ou", xdg_shell_types + 24 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wl_message xdg_popup_events[] = {
|
||||||
|
{ "configure", "iiii", xdg_shell_types + 0 },
|
||||||
|
{ "popup_done", "", xdg_shell_types + 0 },
|
||||||
|
{ "repositioned", "3u", xdg_shell_types + 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
WL_PRIVATE const struct wl_interface xdg_popup_interface = {
|
||||||
|
"xdg_popup", 5,
|
||||||
|
3, xdg_popup_requests,
|
||||||
|
3, xdg_popup_events,
|
||||||
|
};
|
||||||
|
|
383
openGLDemo/cube_demo.c
Executable file
383
openGLDemo/cube_demo.c
Executable file
|
@ -0,0 +1,383 @@
|
||||||
|
/*
|
||||||
|
* GPU test for Spacemit
|
||||||
|
* Copyright (C) 2024 Spacemit Co., Ltd.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <utils_opengles.h>
|
||||||
|
|
||||||
|
static void signal_int(int signum)
|
||||||
|
{
|
||||||
|
global_state.running = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// Handle to a program object
|
||||||
|
GLuint programObject;
|
||||||
|
// Uniform locations
|
||||||
|
GLint mvpLoc;
|
||||||
|
// Vertex data
|
||||||
|
GLfloat *vertices;
|
||||||
|
GLuint *indices;
|
||||||
|
int num_indices[2];
|
||||||
|
// Rotation angle
|
||||||
|
GLfloat angle;
|
||||||
|
uint32_t rotate_benchmark_time;
|
||||||
|
// MVP matrix
|
||||||
|
ESMatrix mvpMatrix;
|
||||||
|
ESMatrix perspective;
|
||||||
|
ESMatrix modelview;
|
||||||
|
// vertex array, buffer
|
||||||
|
GLuint vao, vbo, ebo, lineEbo;
|
||||||
|
|
||||||
|
} UserData;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize the shader and program object
|
||||||
|
//
|
||||||
|
int Init(struct Window *window)
|
||||||
|
{
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
|
||||||
|
char vertShaderSrc[] = {
|
||||||
|
"#version 300 es\n"
|
||||||
|
"layout(location = 0) in vec4 vPosition;\n"
|
||||||
|
"layout(location = 1) in vec4 aColor;\n"
|
||||||
|
"out vec4 vColor;\n"
|
||||||
|
"uniform mat4 u_mvpMatrix;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = u_mvpMatrix * vPosition;\n"
|
||||||
|
" vColor = aColor;\n"
|
||||||
|
"}\n"};
|
||||||
|
|
||||||
|
char fragShaderSrc[] = {
|
||||||
|
"#version 300 es\n"
|
||||||
|
"precision mediump float;\n"
|
||||||
|
"in vec4 vColor;\n"
|
||||||
|
"out vec4 outColor;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" outColor = vColor;\n"
|
||||||
|
"}\n"};
|
||||||
|
|
||||||
|
userData->programObject = load_program(vertShaderSrc, fragShaderSrc);
|
||||||
|
|
||||||
|
// Define the vertex positions of the cube
|
||||||
|
GLfloat vertices[] = {
|
||||||
|
0.5f, -0.5f, 0.5f, // point 1
|
||||||
|
-0.5f, -0.5f, 0.5f, // point 2
|
||||||
|
-0.5f, 0.5f, 0.5f, // point 3
|
||||||
|
0.5f, 0.5f, 0.5f, // point 4
|
||||||
|
0.5f, -0.5f, -0.5f, // point 5
|
||||||
|
-0.5f, -0.5f, -0.5f, // point 6
|
||||||
|
-0.5f, 0.5f, -0.5f, // point 7
|
||||||
|
0.5f, 0.5f, -0.5f // point 8
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define the vertex index of a cube for drawing solid faces
|
||||||
|
GLuint indices[] = {
|
||||||
|
0, 1, 2, 2, 3, 0, // front
|
||||||
|
4, 5, 6, 6, 7, 4, // back
|
||||||
|
0, 4, 5, 5, 1, 0, // bottom
|
||||||
|
1, 5, 6, 6, 2, 1, // left
|
||||||
|
3, 2, 6, 6, 7, 3, // top
|
||||||
|
0, 4, 7, 7, 3, 0 // right
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define the wireframe index of the cube
|
||||||
|
const GLushort lineIndices[] = {
|
||||||
|
0, 1, 1, 2, 2, 3, 3, 0, // front
|
||||||
|
4, 5, 5, 6, 6, 7, 7, 4, // back
|
||||||
|
0, 4, 1, 5, 2, 6, 3, 7, // sides
|
||||||
|
};
|
||||||
|
|
||||||
|
userData->vertices = (GLfloat *)malloc(sizeof(vertices));
|
||||||
|
memcpy(userData->vertices, vertices, sizeof(vertices));
|
||||||
|
|
||||||
|
userData->num_indices[0] = sizeof(indices) / sizeof(indices[0]);
|
||||||
|
userData->num_indices[1] = sizeof(lineIndices) / sizeof(lineIndices[0]);
|
||||||
|
|
||||||
|
// Bind Vertex Array Object (VAO) and Vertex Buffer Object (VBO), and send vertex data to GPU
|
||||||
|
glGenVertexArrays(1, &userData->vao);
|
||||||
|
glBindVertexArray(userData->vao);
|
||||||
|
|
||||||
|
glGenBuffers(1, &userData->vbo);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, userData->vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), userData->vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// Copy the index array into an index buffer for OpenGL to use
|
||||||
|
glGenBuffers(1, &userData->ebo);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->ebo);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
// Create wireframe EBO
|
||||||
|
glGenBuffers(1, &userData->lineEbo);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->lineEbo);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(lineIndices), lineIndices, GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
// Set vertex attribute pointer
|
||||||
|
GLuint positionAttrib = glGetAttribLocation(userData->programObject, "vPosition");
|
||||||
|
glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void *)0);
|
||||||
|
glEnableVertexAttribArray(positionAttrib);
|
||||||
|
|
||||||
|
// Compute the window aspect ratio
|
||||||
|
float aspect;
|
||||||
|
aspect = (GLfloat)window->geometry.width / (GLfloat)window->geometry.height;
|
||||||
|
// Generate a perspective matrix with a 60 degree FOV
|
||||||
|
esMatrixLoadIdentity(&userData->perspective);
|
||||||
|
esPerspective(&userData->perspective, 60.0f, aspect, 1.0f, 15.0f);
|
||||||
|
|
||||||
|
// Generate a model view matrix to rotate/translate the cube
|
||||||
|
esMatrixLoadIdentity(&userData->modelview);
|
||||||
|
|
||||||
|
// Translate away from the viewer
|
||||||
|
esTranslate(&userData->modelview, 0.0, 0.0, -2.0);
|
||||||
|
|
||||||
|
// Starting rotation angle for the cube
|
||||||
|
userData->angle = 0.0f;
|
||||||
|
// rotate the matrix
|
||||||
|
esRotate(&userData->modelview, userData->angle, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
// Generate a mvp matrix
|
||||||
|
esMatrixMultiply(&userData->mvpMatrix, &userData->modelview, &userData->perspective);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update(struct Window *window)
|
||||||
|
{
|
||||||
|
struct Display *display = window->display;
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
// Rotation angle update interval
|
||||||
|
static uint8_t update_interval;
|
||||||
|
static const uint8_t initial_update_interval = 1.5;
|
||||||
|
static const uint8_t subsequent_update_interval = 3;
|
||||||
|
static uint8_t call_count = 0;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
if (gettimeofday(&tv, NULL) == -1)
|
||||||
|
{
|
||||||
|
printf("get time of day faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
|
// Init rotate_benchmark_time and update_interval
|
||||||
|
if (call_count == 0)
|
||||||
|
{
|
||||||
|
userData->rotate_benchmark_time = time;
|
||||||
|
update_interval = initial_update_interval;
|
||||||
|
}
|
||||||
|
// Update rotate_benchmark_time and angle
|
||||||
|
if (time - userData->rotate_benchmark_time > (update_interval * 1000))
|
||||||
|
{
|
||||||
|
update_interval = subsequent_update_interval;
|
||||||
|
userData->rotate_benchmark_time = time;
|
||||||
|
userData->angle += 3.0f;
|
||||||
|
if (userData->angle > 6.0f)
|
||||||
|
{
|
||||||
|
userData->angle = 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the model view projection matrix
|
||||||
|
esRotate(&userData->modelview, userData->angle, 0.0, 1.0, 0.0);
|
||||||
|
esMatrixMultiply(&userData->mvpMatrix, &userData->modelview, &userData->perspective);
|
||||||
|
|
||||||
|
call_count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Draw(struct Window *window, struct wl_callback *callback, uint32_t time)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Display *display = window->display;
|
||||||
|
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
|
||||||
|
static const uint32_t benchmark_interval = 5;
|
||||||
|
struct wl_region *region;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
if (window->callback != callback)
|
||||||
|
{
|
||||||
|
log_error("window->callback != callback");
|
||||||
|
}
|
||||||
|
window->callback = NULL;
|
||||||
|
|
||||||
|
if (callback)
|
||||||
|
wl_callback_destroy(callback);
|
||||||
|
|
||||||
|
if (gettimeofday(&tv, NULL) == -1)
|
||||||
|
{
|
||||||
|
printf("get time of day faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
|
if (window->frames == 0)
|
||||||
|
window->benchmark_time = time;
|
||||||
|
if (time - window->benchmark_time > (benchmark_interval * 1000))
|
||||||
|
{
|
||||||
|
printf("%d frames in %d seconds: %f fps\n",
|
||||||
|
window->frames,
|
||||||
|
benchmark_interval,
|
||||||
|
(float)window->frames / benchmark_interval);
|
||||||
|
window->benchmark_time = time;
|
||||||
|
window->frames = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the model view projection matrix
|
||||||
|
Update(window);
|
||||||
|
|
||||||
|
// Set the viewport
|
||||||
|
glViewport(0, 0, window->geometry.width, window->geometry.height);
|
||||||
|
// Clear the color buffer
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
// Use the program object
|
||||||
|
glUseProgram(userData->programObject);
|
||||||
|
|
||||||
|
// Load the MVP matrix
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(userData->programObject, "u_mvpMatrix"), 1, GL_FALSE, (GLfloat *)&userData->mvpMatrix.m[0][0]);
|
||||||
|
|
||||||
|
glBindVertexArray(userData->vao);
|
||||||
|
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
// glDepthFunc(GL_LESS);
|
||||||
|
// glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
// Rendering Cube
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->ebo);
|
||||||
|
// Set color
|
||||||
|
const GLfloat frameColor[] = {0.0f, 1.0f, 0.0f, 1.0f};
|
||||||
|
glVertexAttrib4fv(1, frameColor);
|
||||||
|
glDrawElements(GL_TRIANGLES, userData->num_indices[0], GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
|
// Rendering wireframe
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->lineEbo);
|
||||||
|
// Set color
|
||||||
|
const GLfloat wireframeColor[] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
|
glVertexAttrib4fv(1, wireframeColor);
|
||||||
|
glDrawElements(GL_LINES, userData->num_indices[1], GL_UNSIGNED_SHORT, 0);
|
||||||
|
|
||||||
|
// Swap buffer
|
||||||
|
eglSwapBuffers(display->egl.dpy, window->egl_surface);
|
||||||
|
|
||||||
|
window->frames++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
void Shutdown(void *data)
|
||||||
|
{
|
||||||
|
struct Window *window = data;
|
||||||
|
UserData *userData = window->userData;
|
||||||
|
|
||||||
|
if (userData->vbo != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->vbo);
|
||||||
|
userData->vbo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->vao != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->vao);
|
||||||
|
userData->vao = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->ebo != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->ebo);
|
||||||
|
userData->ebo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->vertices != NULL)
|
||||||
|
{
|
||||||
|
free(userData->vertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->indices != NULL)
|
||||||
|
{
|
||||||
|
free(userData->indices);
|
||||||
|
}
|
||||||
|
// Delete program object
|
||||||
|
glDeleteProgram(userData->programObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sigaction sigint;
|
||||||
|
struct Display display = {0};
|
||||||
|
struct Window window = {0};
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
window.display = &display;
|
||||||
|
display.window = &window;
|
||||||
|
window.geometry.width = 512;
|
||||||
|
window.geometry.height = 512;
|
||||||
|
window.window_size = window.geometry;
|
||||||
|
window.buffer_size = 0;
|
||||||
|
window.frame_sync = 1;
|
||||||
|
window.delay = 0;
|
||||||
|
|
||||||
|
window.userData = malloc(sizeof(UserData));
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (strcmp("-d", argv[i]) == 0 && i + 1 < argc)
|
||||||
|
window.delay = atoi(argv[++i]);
|
||||||
|
else if (strcmp("-f", argv[i]) == 0)
|
||||||
|
// Set full screen display
|
||||||
|
window.fullscreen = 1;
|
||||||
|
else if (strcmp("-m", argv[i]) == 0)
|
||||||
|
// Maximization mode
|
||||||
|
window.maximized = 1;
|
||||||
|
else if (strcmp("-o", argv[i]) == 0)
|
||||||
|
// Create an opaque surface
|
||||||
|
window.opaque = 1;
|
||||||
|
else if (strcmp("-s", argv[i]) == 0)
|
||||||
|
// EGL configuration using 16bpp (16 bit color mode)
|
||||||
|
window.buffer_size = 16;
|
||||||
|
else if (strcmp("-b", argv[i]) == 0)
|
||||||
|
window.frame_sync = 0;
|
||||||
|
else if (strcmp("-h", argv[i]) == 0)
|
||||||
|
usage(EXIT_SUCCESS);
|
||||||
|
else
|
||||||
|
usage(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (create_window(&window, &display, ret) == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Create window faild!");
|
||||||
|
destroy_window(&window, &display);
|
||||||
|
Shutdown(&window);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Create window success.\n");
|
||||||
|
|
||||||
|
if (!Init(&window))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Init openGL faild!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Init openGL success.\n");
|
||||||
|
|
||||||
|
// Handling SIGINT signals (usually interrupt signals triggered by pressing Ctrl+C)
|
||||||
|
sigint.sa_handler = signal_int;
|
||||||
|
sigemptyset(&sigint.sa_mask);
|
||||||
|
sigint.sa_flags = SA_RESETHAND;
|
||||||
|
sigaction(SIGINT, &sigint, NULL);
|
||||||
|
|
||||||
|
while (global_state.running && ret != -1)
|
||||||
|
{
|
||||||
|
ret = wl_display_dispatch_pending(display.display);
|
||||||
|
Draw(&window, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Simple-egl exiting\n");
|
||||||
|
destroy_window(&window, &display);
|
||||||
|
Shutdown(&window);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
828
openGLDemo/cube_externalTexture_demo.c
Executable file
828
openGLDemo/cube_externalTexture_demo.c
Executable file
|
@ -0,0 +1,828 @@
|
||||||
|
/*
|
||||||
|
* GPU test for Spacemit
|
||||||
|
* Copyright (C) 2024 Spacemit Co., Ltd.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <utils_opengles.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <gbm.h>
|
||||||
|
#include <libdrm/drm_fourcc.h>
|
||||||
|
#include <GLES2/gl2ext.h>
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/dma-heap.h>
|
||||||
|
#include <drm/drm_fourcc.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
bool ready_to_render = false;
|
||||||
|
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
|
||||||
|
|
||||||
|
#define USE_GBM_BUF 1
|
||||||
|
#define USE_DMA_BUF 0
|
||||||
|
|
||||||
|
static void signal_int(int signum)
|
||||||
|
{
|
||||||
|
global_state.running = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// Handle to a program object
|
||||||
|
GLuint programObject;
|
||||||
|
// Uniform locations
|
||||||
|
GLint mvpLoc;
|
||||||
|
// Vertex data
|
||||||
|
GLfloat *vertices;
|
||||||
|
GLuint *indices;
|
||||||
|
int num_indices[2];
|
||||||
|
// Rotation angle
|
||||||
|
GLfloat angle;
|
||||||
|
uint32_t rotate_benchmark_time;
|
||||||
|
// MVP matrix
|
||||||
|
ESMatrix mvpMatrix;
|
||||||
|
ESMatrix perspective;
|
||||||
|
ESMatrix modelview;
|
||||||
|
// vertex array, buffer
|
||||||
|
GLuint vao, vbo, ebo, lineEbo;
|
||||||
|
GLuint textureID;
|
||||||
|
|
||||||
|
GLuint *textures;
|
||||||
|
int current_texture_index;
|
||||||
|
|
||||||
|
} UserData;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize the shader and program object
|
||||||
|
//
|
||||||
|
int Init(struct Window *window)
|
||||||
|
{
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
|
||||||
|
char vertShaderSrc[] = {
|
||||||
|
"#version 300 es\n"
|
||||||
|
"layout(location = 0) in vec3 vPosition;\n"
|
||||||
|
"layout(location = 1) in vec2 aTexCoord;\n"
|
||||||
|
"layout(location = 2) in vec4 aColor;\n"
|
||||||
|
"out vec2 vTextureCoord;\n"
|
||||||
|
"out vec4 vColor;\n"
|
||||||
|
"uniform mat4 u_mvpMatrix;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = u_mvpMatrix * vec4(vPosition, 1.0f);\n"
|
||||||
|
" vTextureCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y);\n"
|
||||||
|
" vColor = aColor.argb;\n"
|
||||||
|
"}\n"};
|
||||||
|
|
||||||
|
char fragShaderSrc[] = {
|
||||||
|
"#version 300 es\n"
|
||||||
|
"precision mediump float;\n"
|
||||||
|
"uniform sampler2D uSampler;\n"
|
||||||
|
"uniform bool useTexture;\n"
|
||||||
|
"in vec2 vTextureCoord;\n"
|
||||||
|
"in vec4 vColor;\n"
|
||||||
|
"out vec4 outColor;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" if(useTexture){\n"
|
||||||
|
" outColor = texture(uSampler, vTextureCoord).bgra;\n"
|
||||||
|
" } else{\n"
|
||||||
|
" outColor = vColor;\n"
|
||||||
|
" }"
|
||||||
|
"}\n"};
|
||||||
|
|
||||||
|
userData->programObject = load_program(vertShaderSrc, fragShaderSrc);
|
||||||
|
|
||||||
|
// Define the vertex positions of the cube
|
||||||
|
GLfloat vertices[] = {
|
||||||
|
// vertex // texture
|
||||||
|
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, // point 0
|
||||||
|
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // point 1
|
||||||
|
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, // point 2
|
||||||
|
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // point 3
|
||||||
|
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // point 4
|
||||||
|
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, // point 5
|
||||||
|
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // point 6
|
||||||
|
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, // point 7
|
||||||
|
|
||||||
|
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, // point 0->8
|
||||||
|
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, // point 1->9
|
||||||
|
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, // point 2->10
|
||||||
|
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // point 3->11
|
||||||
|
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, // point 4->12
|
||||||
|
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // point 5->13
|
||||||
|
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, // point 6->14
|
||||||
|
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // point 7->15
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define the vertex index of a cube for drawing solid faces
|
||||||
|
GLuint indices[] = {
|
||||||
|
0, 1, 2, 2, 3, 0, // front
|
||||||
|
1, 5, 6, 6, 2, 1, // left
|
||||||
|
4, 5, 6, 6, 7, 4, // back
|
||||||
|
0, 4, 7, 7, 3, 0, // right
|
||||||
|
|
||||||
|
8, 12, 13, 13, 9, 8, // bottom
|
||||||
|
11, 10, 15, 15, 14, 10, // top
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define the wireframe index of the cube
|
||||||
|
GLuint lineIndices[] = {
|
||||||
|
0, 1, 1, 2, 2, 3, 3, 0, // front
|
||||||
|
4, 5, 5, 6, 6, 7, 7, 4, // back
|
||||||
|
0, 4, 1, 5, 2, 6, 3, 7, // sides
|
||||||
|
};
|
||||||
|
|
||||||
|
userData->vertices = (GLfloat *)malloc(sizeof(vertices));
|
||||||
|
memcpy(userData->vertices, vertices, sizeof(vertices));
|
||||||
|
|
||||||
|
userData->num_indices[0] = sizeof(indices) / sizeof(indices[0]);
|
||||||
|
userData->num_indices[1] = sizeof(lineIndices) / sizeof(lineIndices[0]);
|
||||||
|
|
||||||
|
// Bind Vertex Array Object (VAO) and Vertex Buffer Object (VBO), and send vertex data to GPU
|
||||||
|
glGenVertexArrays(1, &userData->vao);
|
||||||
|
glBindVertexArray(userData->vao);
|
||||||
|
|
||||||
|
glGenBuffers(1, &userData->vbo);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, userData->vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), userData->vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// Copy the index array into an index buffer for OpenGL to use
|
||||||
|
glGenBuffers(1, &userData->ebo);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->ebo);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
// Create wireframe EBO
|
||||||
|
glGenBuffers(1, &userData->lineEbo);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->lineEbo);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(lineIndices), lineIndices, GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
// Set vertex pointer attribute
|
||||||
|
GLuint positionAttrib = glGetAttribLocation(userData->programObject, "vPosition");
|
||||||
|
glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void *)0);
|
||||||
|
glEnableVertexAttribArray(positionAttrib);
|
||||||
|
|
||||||
|
// Texture position attribute
|
||||||
|
GLuint textureAttrib = glGetAttribLocation(userData->programObject, "aTexCoord");
|
||||||
|
glVertexAttribPointer(textureAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void *)(3 * sizeof(GLfloat)));
|
||||||
|
glEnableVertexAttribArray(textureAttrib);
|
||||||
|
|
||||||
|
// Compute the window aspect ratio
|
||||||
|
float aspect;
|
||||||
|
aspect = (GLfloat)window->geometry.width / (GLfloat)window->geometry.height;
|
||||||
|
// Generate a perspective matrix with a 60 degree FOV
|
||||||
|
esMatrixLoadIdentity(&userData->perspective);
|
||||||
|
esPerspective(&userData->perspective, 60.0f, aspect, 1.0f, 15.0f);
|
||||||
|
|
||||||
|
// Generate a model view matrix to rotate/translate the cube
|
||||||
|
esMatrixLoadIdentity(&userData->modelview);
|
||||||
|
|
||||||
|
// Translate away from the viewer
|
||||||
|
esTranslate(&userData->modelview, 0.0, 0.0, -2.0);
|
||||||
|
|
||||||
|
// Starting rotation angle for the cube
|
||||||
|
userData->angle = 0.0f;
|
||||||
|
// rotate the matrix
|
||||||
|
esRotate(&userData->modelview, userData->angle, 0.5, 1.0, 0.0);
|
||||||
|
|
||||||
|
// Generate a mvp matrix
|
||||||
|
esMatrixMultiply(&userData->mvpMatrix, &userData->modelview, &userData->perspective);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update(struct Window *window)
|
||||||
|
{
|
||||||
|
struct Display *display = window->display;
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
// Rotation angle update interval
|
||||||
|
static uint8_t update_interval;
|
||||||
|
static const uint8_t initial_update_interval = 3;
|
||||||
|
static const uint8_t subsequent_update_interval = 3;
|
||||||
|
static uint8_t call_count = 0;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
if (gettimeofday(&tv, NULL) == -1)
|
||||||
|
{
|
||||||
|
printf("get time of day faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
|
// Init rotate_benchmark_time and update_interval
|
||||||
|
if (call_count == 0)
|
||||||
|
{
|
||||||
|
userData->rotate_benchmark_time = time;
|
||||||
|
update_interval = initial_update_interval;
|
||||||
|
}
|
||||||
|
// Update rotate_benchmark_time and angle
|
||||||
|
if (time - userData->rotate_benchmark_time > (update_interval * 1000))
|
||||||
|
{
|
||||||
|
update_interval = subsequent_update_interval;
|
||||||
|
userData->rotate_benchmark_time = time;
|
||||||
|
userData->angle += 3.0f;
|
||||||
|
if (userData->angle > 6.0f)
|
||||||
|
{
|
||||||
|
userData->angle = 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the model view projection matrix
|
||||||
|
esRotate(&userData->modelview, userData->angle, 0.5, 1.0, 0.0);
|
||||||
|
esMatrixMultiply(&userData->mvpMatrix, &userData->modelview, &userData->perspective);
|
||||||
|
|
||||||
|
call_count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Draw(struct Window *window, struct wl_callback *callback, uint32_t time)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Display *display = window->display;
|
||||||
|
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
|
||||||
|
static const uint32_t benchmark_interval = 5;
|
||||||
|
struct wl_region *region;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
if (window->callback != callback)
|
||||||
|
{
|
||||||
|
log_error("window->callback != callback");
|
||||||
|
}
|
||||||
|
window->callback = NULL;
|
||||||
|
|
||||||
|
if (callback)
|
||||||
|
wl_callback_destroy(callback);
|
||||||
|
|
||||||
|
if (gettimeofday(&tv, NULL) == -1)
|
||||||
|
{
|
||||||
|
printf("get time of day faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
|
if (window->frames == 0)
|
||||||
|
window->benchmark_time = time;
|
||||||
|
if (time - window->benchmark_time > (benchmark_interval * 1000))
|
||||||
|
{
|
||||||
|
printf("%d frames in %d seconds: %f fps\n",
|
||||||
|
window->frames,
|
||||||
|
benchmark_interval,
|
||||||
|
(float)window->frames / benchmark_interval);
|
||||||
|
window->benchmark_time = time;
|
||||||
|
window->frames = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the model view projection matrix
|
||||||
|
Update(window);
|
||||||
|
|
||||||
|
// Set the viewport
|
||||||
|
glViewport(0, 0, window->geometry.width, window->geometry.height);
|
||||||
|
// Clear the color buffer
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthFunc(GL_LESS);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
// Use the program object
|
||||||
|
glUseProgram(userData->programObject);
|
||||||
|
|
||||||
|
// Load the MVP matrix
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(userData->programObject, "u_mvpMatrix"), 1, GL_FALSE, (GLfloat *)&userData->mvpMatrix.m[0][0]);
|
||||||
|
|
||||||
|
glBindVertexArray(userData->vao);
|
||||||
|
|
||||||
|
GLenum error = glGetError();
|
||||||
|
if (error != GL_NO_ERROR)
|
||||||
|
{
|
||||||
|
printf("OpenGL Error: %d\n", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rendering Cube
|
||||||
|
glUniform1i(glGetUniformLocation(userData->programObject, "useTexture"), GL_TRUE);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, userData->textures[userData->current_texture_index]); // Bind the correct texture
|
||||||
|
glUniform1i(glGetUniformLocation(userData->programObject, "uSampler"), 0);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->ebo);
|
||||||
|
glDrawElements(GL_TRIANGLES, userData->num_indices[0], GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
|
// Rendering wireframe
|
||||||
|
glUniform1i(glGetUniformLocation(userData->programObject, "useTexture"), GL_FALSE);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->lineEbo);
|
||||||
|
glLineWidth(5.0f); // Set line width
|
||||||
|
const GLfloat wireframeColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
|
glVertexAttrib4fv(2, wireframeColor); // Set color
|
||||||
|
glDrawElements(GL_LINES, userData->num_indices[1], GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
|
// Swap buffer
|
||||||
|
eglSwapBuffers(display->egl.dpy, window->egl_surface);
|
||||||
|
|
||||||
|
window->frames++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
void Shutdown(void *data)
|
||||||
|
{
|
||||||
|
struct Window *window = data;
|
||||||
|
UserData *userData = window->userData;
|
||||||
|
|
||||||
|
if (userData->vbo != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->vbo);
|
||||||
|
userData->vbo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->vao != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->vao);
|
||||||
|
userData->vao = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->ebo != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->ebo);
|
||||||
|
userData->ebo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->vertices != NULL)
|
||||||
|
{
|
||||||
|
free(userData->vertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->indices != NULL)
|
||||||
|
{
|
||||||
|
free(userData->indices);
|
||||||
|
}
|
||||||
|
// Delete program object
|
||||||
|
glDeleteProgram(userData->programObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USE_GBM_BUF
|
||||||
|
#define MAX_BUFFER_PLANES 4
|
||||||
|
struct Buffer
|
||||||
|
{
|
||||||
|
struct Display *display;
|
||||||
|
struct wl_buffer *buffer;
|
||||||
|
int busy;
|
||||||
|
|
||||||
|
struct gbm_bo *bo;
|
||||||
|
void *map;
|
||||||
|
void *map_data;
|
||||||
|
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int format;
|
||||||
|
uint64_t modifier;
|
||||||
|
int plane_count;
|
||||||
|
int dmabuf_fds[MAX_BUFFER_PLANES];
|
||||||
|
uint32_t strides[MAX_BUFFER_PLANES];
|
||||||
|
uint32_t offsets[MAX_BUFFER_PLANES];
|
||||||
|
|
||||||
|
EGLImageKHR egl_image;
|
||||||
|
GLuint gl_texture;
|
||||||
|
GLuint gl_fbo;
|
||||||
|
|
||||||
|
struct zwp_linux_buffer_release_v1 *buffer_release;
|
||||||
|
/* The buffer owns the release_fence_fd, until it passes ownership
|
||||||
|
* to it to EGL (see wait_for_buffer_release_fence). */
|
||||||
|
int release_fence_fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool display_set_up_gbm(struct Display *display, const char *drm_render_node)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "display_set_up_gbm...\n");
|
||||||
|
display->gbm.drm_fd = open(drm_render_node, O_RDWR);
|
||||||
|
if (display->gbm.drm_fd < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to open drm render node %s\n",
|
||||||
|
drm_render_node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
display->gbm.device = gbm_create_device(display->gbm.drm_fd);
|
||||||
|
if (display->gbm.device == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to create gbm device\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create GBM buffer
|
||||||
|
bool create_gbm_buffer(struct Display *display, struct Buffer *buffer, int width, int height)
|
||||||
|
{
|
||||||
|
buffer->format = GBM_FORMAT_ARGB8888;
|
||||||
|
// fprintf(stdout, "buffer format: %x\n", buffer->format);
|
||||||
|
buffer->bo = gbm_bo_create(display->gbm.device, width, height, buffer->format, GBM_BO_USE_RENDERING);
|
||||||
|
if (!buffer->bo)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to create GBM buffer\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specify the area to be mapped
|
||||||
|
uint32_t x = 0;
|
||||||
|
uint32_t y = 0;
|
||||||
|
uint32_t flags = GBM_BO_TRANSFER_WRITE;
|
||||||
|
uint32_t stride;
|
||||||
|
|
||||||
|
void *map;
|
||||||
|
void *map_data;
|
||||||
|
map = gbm_bo_map(buffer->bo, x, y, width, height, flags, &stride, &map_data);
|
||||||
|
if (!map)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to map GBM buffer\n");
|
||||||
|
gbm_bo_destroy(buffer->bo);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Save the mapped pointer to gbm_buf ->map
|
||||||
|
buffer->map = map;
|
||||||
|
buffer->strides[0] = stride;
|
||||||
|
buffer->offsets[0] = 0;
|
||||||
|
buffer->dmabuf_fds[0] = gbm_bo_get_fd(buffer->bo);
|
||||||
|
buffer->width = width;
|
||||||
|
buffer->height = height;
|
||||||
|
buffer->map_data = map_data;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool save_buffer_to_bin(struct Buffer *buffer, const char *filename, int total_size)
|
||||||
|
{
|
||||||
|
FILE *file = fopen(filename, "wb"); // Open file in binary write mode
|
||||||
|
if (!file)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to open file '%s' for writing: %s\n", filename, strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bytes_written = fwrite(buffer->map, 1, total_size, file); // Write data
|
||||||
|
|
||||||
|
if (bytes_written != total_size)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to write all data to file '%s'\n", filename);
|
||||||
|
fclose(file);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint create_texture_gbm(struct Display *display, const char *drm_render_node, struct Buffer *buffer, const char *filename)
|
||||||
|
{
|
||||||
|
if (!display_set_up_gbm(display, drm_render_node))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "init gbm faild!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width, height, nrChannels, total_size;
|
||||||
|
unsigned char *image_data = load_imageData(filename, &width, &height, &nrChannels, 0);
|
||||||
|
if (!image_data)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to load image\n");
|
||||||
|
free_imageData(image_data);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
total_size = width * height * nrChannels;
|
||||||
|
|
||||||
|
create_gbm_buffer(display, buffer, width, height);
|
||||||
|
|
||||||
|
memcpy(buffer->map, image_data, total_size);
|
||||||
|
free_imageData(image_data);
|
||||||
|
|
||||||
|
EGLint attribs[] = {
|
||||||
|
EGL_WIDTH, buffer->width,
|
||||||
|
EGL_HEIGHT, buffer->height,
|
||||||
|
EGL_LINUX_DRM_FOURCC_EXT, buffer->format,
|
||||||
|
EGL_DMA_BUF_PLANE0_FD_EXT, buffer->dmabuf_fds[0],
|
||||||
|
EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
|
||||||
|
EGL_DMA_BUF_PLANE0_PITCH_EXT, gbm_bo_get_stride(buffer->bo),
|
||||||
|
EGL_NONE};
|
||||||
|
|
||||||
|
fprintf(stdout, "GBM-BUF data, width: %d, height: %d, format: %x, dmabuf_fds: %d,\n",
|
||||||
|
buffer->width, buffer->height, buffer->format, buffer->dmabuf_fds[0]);
|
||||||
|
|
||||||
|
PFNEGLCREATEIMAGEKHRPROC create_image;
|
||||||
|
create_image = (void *)eglGetProcAddress("eglCreateImageKHR");
|
||||||
|
buffer->egl_image = create_image(display->egl.dpy, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
|
||||||
|
NULL, attribs);
|
||||||
|
|
||||||
|
if (buffer->egl_image == EGL_NO_IMAGE_KHR)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "EGLImageKHR creation failed, eglGetError():0x%x\n", eglGetError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint ex_texture;
|
||||||
|
glGenTextures(1, &ex_texture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, ex_texture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d; // require openGL ES2.0
|
||||||
|
image_target_texture_2d = (void *)eglGetProcAddress("glEGLImageTargetTexture2DOES");
|
||||||
|
image_target_texture_2d(GL_TEXTURE_2D, buffer->egl_image);
|
||||||
|
// fprintf(stdout, "debug:image_target_texture_2d: glGetError(): %d\n", glGetError());
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
return ex_texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a structure to store image data
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned char *data;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int nrChannels;
|
||||||
|
size_t size;
|
||||||
|
} ImageData;
|
||||||
|
|
||||||
|
// Dma buf updates thread function
|
||||||
|
void *dmabuf_update_thread(void *arg)
|
||||||
|
{
|
||||||
|
struct Buffer *buffer = (struct Buffer *)arg;
|
||||||
|
char *file_names[] = {"/usr/data/bianbu2.png", "/usr/data/bianbu.png"};
|
||||||
|
int num_imgs = sizeof(file_names) / sizeof(file_names[0]);
|
||||||
|
ImageData images[num_imgs];
|
||||||
|
for (int i = 0; i < num_imgs; ++i)
|
||||||
|
{
|
||||||
|
images[i].data = load_imageData(file_names[i], &images[i].width, &images[i].height, &images[i].nrChannels, 0);
|
||||||
|
if (images[i].data == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to load image %d.\n", i);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
images[i].size = images[i].width * images[i].height * images[i].nrChannels;
|
||||||
|
}
|
||||||
|
|
||||||
|
int current_image_index = 0;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
current_image_index = (current_image_index + 1) % num_imgs;
|
||||||
|
// Update buffer ->map content
|
||||||
|
if (images[current_image_index].data != NULL)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&mtx);
|
||||||
|
memcpy(buffer->map, images[current_image_index].data, images[current_image_index].size);
|
||||||
|
ready_to_render = 1;
|
||||||
|
pthread_cond_signal(&cv);
|
||||||
|
pthread_mutex_unlock(&mtx);
|
||||||
|
}
|
||||||
|
sleep(3);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USE_DMA_BUF
|
||||||
|
GLuint create_texture_dma(struct Display *display, const char *filename)
|
||||||
|
{
|
||||||
|
int width, height, nrChannels;
|
||||||
|
|
||||||
|
// Load image data
|
||||||
|
unsigned char *image_data = load_imageData(filename, &width, &height, &nrChannels, 0);
|
||||||
|
if (!image_data)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to load image\n");
|
||||||
|
free_imageData(image_data);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
// printf("Image loaded with dimensions %dx%d and %d channels.\n", width, height, nrChannels);
|
||||||
|
|
||||||
|
int img_size = width * height * nrChannels;
|
||||||
|
// 1. Allocate DMA-BUF through dma-heap
|
||||||
|
int dma_heap_fd = open("/dev/dma_heap/system", O_RDWR | O_CLOEXEC);
|
||||||
|
if (dma_heap_fd < 0)
|
||||||
|
{
|
||||||
|
perror("Failed to open dma_heap");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dma_heap_allocation_data alloc_data = {
|
||||||
|
.len = img_size,
|
||||||
|
.fd_flags = O_RDWR | O_CLOEXEC,
|
||||||
|
.heap_flags = 0};
|
||||||
|
|
||||||
|
if (ioctl(dma_heap_fd, DMA_HEAP_IOCTL_ALLOC, &alloc_data) < 0)
|
||||||
|
{
|
||||||
|
perror("Failed to allocate DMA-BUF");
|
||||||
|
close(dma_heap_fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "DMA-BUF data, len: %zu, fd: %d, fd_flags: %d, heap_flags: %u\n",
|
||||||
|
alloc_data.len, alloc_data.fd, alloc_data.fd_flags, alloc_data.heap_flags);
|
||||||
|
|
||||||
|
int dma_buf_fd = alloc_data.fd;
|
||||||
|
close(dma_heap_fd); // No longer need dma-heap file descriptor
|
||||||
|
|
||||||
|
// 2. Map DMA-BUF to user space
|
||||||
|
void *buffer = mmap(NULL, img_size, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf_fd, 0);
|
||||||
|
if (buffer == MAP_FAILED)
|
||||||
|
{
|
||||||
|
perror("Failed to mmap DMA-BUF");
|
||||||
|
close(dma_buf_fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Write data to buffer
|
||||||
|
// memset(buffer, 0xF0, img_size); // Fill in 0xF0 (ARGB8888 format)
|
||||||
|
memcpy(buffer, image_data, img_size);
|
||||||
|
|
||||||
|
// 4. Cancel mapping
|
||||||
|
munmap(buffer, img_size);
|
||||||
|
|
||||||
|
EGLint attribs[] = {
|
||||||
|
EGL_WIDTH, width,
|
||||||
|
EGL_HEIGHT, height,
|
||||||
|
EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888,
|
||||||
|
EGL_DMA_BUF_PLANE0_FD_EXT, dma_buf_fd,
|
||||||
|
EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
|
||||||
|
EGL_DMA_BUF_PLANE0_PITCH_EXT, width * 4,
|
||||||
|
EGL_NONE};
|
||||||
|
|
||||||
|
PFNEGLCREATEIMAGEKHRPROC create_image;
|
||||||
|
create_image = (void *)eglGetProcAddress("eglCreateImageKHR");
|
||||||
|
EGLImageKHR egl_image = create_image(display->egl.dpy, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
|
||||||
|
NULL, attribs);
|
||||||
|
|
||||||
|
if (egl_image == EGL_NO_IMAGE_KHR)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "EGLImageKHR creation failed, eglGetError():0x%x\n", eglGetError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint ex_texture;
|
||||||
|
glGenTextures(1, &ex_texture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, ex_texture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d; // for openGL ES2.0
|
||||||
|
image_target_texture_2d = (void *)eglGetProcAddress("glEGLImageTargetTexture2DOES");
|
||||||
|
image_target_texture_2d(GL_TEXTURE_2D, egl_image);
|
||||||
|
// fprintf(stdout, "debug:image_target_texture_2d: glGetError(): %d\n", glGetError());
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
return ex_texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Texture update thread function
|
||||||
|
void *texture_update_thread(void *arg))
|
||||||
|
{
|
||||||
|
UserData *userData = (UserData *)arg while (1)
|
||||||
|
{
|
||||||
|
// Protecting critical areas
|
||||||
|
pthread_mutex_lock(&mtx);
|
||||||
|
userData->current_texture_index = (userData->current_texture_index + 1) % 2;
|
||||||
|
pthread_cond_signal(&cv); // Notify rendering thread
|
||||||
|
pthread_mutex_unlock(&mtx);
|
||||||
|
ready_to_render = 1;
|
||||||
|
// Pause for a period of time to observe the effect
|
||||||
|
sleep(3);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sigaction sigint;
|
||||||
|
struct Display display = {0};
|
||||||
|
struct Window window = {0};
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
window.display = &display;
|
||||||
|
display.window = &window;
|
||||||
|
window.geometry.width = 512;
|
||||||
|
window.geometry.height = 512;
|
||||||
|
window.window_size = window.geometry;
|
||||||
|
window.buffer_size = 0;
|
||||||
|
window.frame_sync = 1;
|
||||||
|
window.delay = 0;
|
||||||
|
|
||||||
|
window.userData = malloc(sizeof(UserData));
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (strcmp("-d", argv[i]) == 0 && i + 1 < argc)
|
||||||
|
window.delay = atoi(argv[++i]);
|
||||||
|
else if (strcmp("-f", argv[i]) == 0)
|
||||||
|
// Set full screen display
|
||||||
|
window.fullscreen = 1;
|
||||||
|
else if (strcmp("-m", argv[i]) == 0)
|
||||||
|
// Maximization mode
|
||||||
|
window.maximized = 1;
|
||||||
|
else if (strcmp("-o", argv[i]) == 0)
|
||||||
|
// Create an opaque surface
|
||||||
|
window.opaque = 1;
|
||||||
|
else if (strcmp("-s", argv[i]) == 0)
|
||||||
|
// EGL configuration using 16bpp (16 bit color mode)
|
||||||
|
window.buffer_size = 16;
|
||||||
|
else if (strcmp("-b", argv[i]) == 0)
|
||||||
|
window.frame_sync = 0;
|
||||||
|
else if (strcmp("-h", argv[i]) == 0)
|
||||||
|
usage(EXIT_SUCCESS);
|
||||||
|
else
|
||||||
|
usage(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (create_window(&window, &display, ret) == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "create window faild!");
|
||||||
|
destroy_window(&window, &display);
|
||||||
|
Shutdown(&window);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "create window success.\n");
|
||||||
|
|
||||||
|
if (!Init(&window))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "init openGL faild!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "init openGL success.\n");
|
||||||
|
// Handling SIGINT signals (usually interrupt signals triggered by pressing Ctrl+C)
|
||||||
|
sigint.sa_handler = signal_int;
|
||||||
|
sigemptyset(&sigint.sa_mask);
|
||||||
|
sigint.sa_flags = SA_RESETHAND;
|
||||||
|
sigaction(SIGINT, &sigint, NULL);
|
||||||
|
|
||||||
|
char *file_names[2] = {"/usr/data/bianbu.png", "/usr/data/bianbu2.png"};
|
||||||
|
UserData *userData = window.userData;
|
||||||
|
userData->textures = malloc(2 * sizeof(GLuint)); // Allocate space for 2 textures
|
||||||
|
userData->current_texture_index = 0;
|
||||||
|
|
||||||
|
pthread_t buf_tid;
|
||||||
|
fprintf(stdout, "create_texture via %s...\n", USE_GBM_BUF ? "GBM BUF" : "DMA BUF");
|
||||||
|
|
||||||
|
#if USE_GBM_BUF
|
||||||
|
struct Buffer *buffer = malloc(sizeof(struct Buffer));
|
||||||
|
buffer->display = &display;
|
||||||
|
userData->textures[0] = create_texture_gbm(&display, "/dev/dri/card1", buffer, file_names[0]);
|
||||||
|
// save_buffer_to_bin(buffer, "./test-buffer.bin", total_size);
|
||||||
|
|
||||||
|
// Create dma buf update thread
|
||||||
|
if (pthread_create(&buf_tid, NULL, &dmabuf_update_thread, buffer) != 0)
|
||||||
|
{
|
||||||
|
perror("Failed to create texture update thread");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USE_DMA_BUF
|
||||||
|
// Create texture update thread
|
||||||
|
if (pthread_create(&buf_tid, NULL, &texture_update_thread, userData) != 0)
|
||||||
|
{
|
||||||
|
perror("Failed to create texture update thread");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
userData->textures[0] = create_texture_dma(&display, file_names[0]);
|
||||||
|
userData->textures[1] = create_texture_dma(&display, file_names[1]);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (global_state.running && ret != -1)
|
||||||
|
{
|
||||||
|
ret = wl_display_dispatch_pending(display.display);
|
||||||
|
Draw(&window, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_join(buf_tid, NULL) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to join texture update thread");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "simple-egl exiting\n");
|
||||||
|
|
||||||
|
#if USE_GBM_BUF
|
||||||
|
free(buffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pthread_mutex_destroy(&mtx);
|
||||||
|
pthread_cond_destroy(&cv);
|
||||||
|
destroy_window(&window, &display);
|
||||||
|
Shutdown(&window);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
432
openGLDemo/cube_texture_demo.c
Executable file
432
openGLDemo/cube_texture_demo.c
Executable file
|
@ -0,0 +1,432 @@
|
||||||
|
/*
|
||||||
|
* GPU test for Spacemit
|
||||||
|
* Copyright (C) 2024 Spacemit Co., Ltd.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <utils_opengles.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
bool ready_to_render = false;
|
||||||
|
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
|
||||||
|
|
||||||
|
static void signal_int(int signum)
|
||||||
|
{
|
||||||
|
global_state.running = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// Handle to a program object
|
||||||
|
GLuint programObject;
|
||||||
|
// Uniform locations
|
||||||
|
GLint mvpLoc;
|
||||||
|
// Vertex data
|
||||||
|
GLfloat *vertices;
|
||||||
|
GLuint *indices;
|
||||||
|
int num_indices[2];
|
||||||
|
// Rotation angle
|
||||||
|
GLfloat angle;
|
||||||
|
uint32_t rotate_benchmark_time;
|
||||||
|
// MVP matrix
|
||||||
|
ESMatrix mvpMatrix;
|
||||||
|
ESMatrix perspective;
|
||||||
|
ESMatrix modelview;
|
||||||
|
// vertex array, buffer
|
||||||
|
GLuint vao, vbo, ebo, lineEbo;
|
||||||
|
GLuint textureID;
|
||||||
|
|
||||||
|
} UserData;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize the shader and program object
|
||||||
|
//
|
||||||
|
int Init(struct Window *window)
|
||||||
|
{
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
|
||||||
|
char vertShaderSrc[] = {
|
||||||
|
"#version 300 es\n"
|
||||||
|
"layout(location = 0) in vec3 vPosition;\n"
|
||||||
|
"layout(location = 1) in vec2 aTexCoord;\n"
|
||||||
|
"layout(location = 2) in vec4 aColor;\n"
|
||||||
|
"out vec2 vTextureCoord;\n"
|
||||||
|
"out vec4 vColor;\n"
|
||||||
|
"uniform mat4 u_mvpMatrix;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = u_mvpMatrix * vec4(vPosition, 1.0f);\n"
|
||||||
|
" vTextureCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y);\n"
|
||||||
|
" vColor = aColor;\n"
|
||||||
|
"}\n"};
|
||||||
|
|
||||||
|
char fragShaderSrc[] = {
|
||||||
|
"#version 300 es\n"
|
||||||
|
"precision mediump float;\n"
|
||||||
|
"uniform sampler2D uSampler;\n"
|
||||||
|
"uniform bool useTexture;\n"
|
||||||
|
"in vec2 vTextureCoord;\n"
|
||||||
|
"in vec4 vColor;\n"
|
||||||
|
"out vec4 outColor;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" if(useTexture){\n"
|
||||||
|
" outColor = texture(uSampler, vTextureCoord);\n"
|
||||||
|
" } else{\n"
|
||||||
|
" outColor = vColor;\n"
|
||||||
|
" }"
|
||||||
|
"}\n"};
|
||||||
|
|
||||||
|
userData->programObject = load_program(vertShaderSrc, fragShaderSrc);
|
||||||
|
|
||||||
|
// Define the vertex positions of the cube
|
||||||
|
GLfloat vertices[] = {
|
||||||
|
// vertex // texture
|
||||||
|
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, // point 0
|
||||||
|
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // point 1
|
||||||
|
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, // point 2
|
||||||
|
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // point 3
|
||||||
|
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // point 4
|
||||||
|
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, // point 5
|
||||||
|
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // point 6
|
||||||
|
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, // point 7
|
||||||
|
|
||||||
|
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, // point 0->8
|
||||||
|
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, // point 1->9
|
||||||
|
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, // point 2->10
|
||||||
|
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // point 3->11
|
||||||
|
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, // point 4->12
|
||||||
|
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // point 5->13
|
||||||
|
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, // point 6->14
|
||||||
|
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // point 7->15
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define the vertex index of a cube for drawing solid faces
|
||||||
|
GLuint indices[] = {
|
||||||
|
0, 1, 2, 2, 3, 0, // front
|
||||||
|
1, 5, 6, 6, 2, 1, // left
|
||||||
|
4, 5, 6, 6, 7, 4, // back
|
||||||
|
0, 4, 7, 7, 3, 0, // right
|
||||||
|
|
||||||
|
8, 12, 13, 13, 9, 8, // bottom
|
||||||
|
11, 10, 15, 15, 14, 10, // top
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define the wireframe index of the cube
|
||||||
|
GLuint lineIndices[] = {
|
||||||
|
0, 1, 1, 2, 2, 3, 3, 0, // front
|
||||||
|
4, 5, 5, 6, 6, 7, 7, 4, // back
|
||||||
|
0, 4, 1, 5, 2, 6, 3, 7, // sides
|
||||||
|
};
|
||||||
|
|
||||||
|
userData->vertices = (GLfloat *)malloc(sizeof(vertices));
|
||||||
|
memcpy(userData->vertices, vertices, sizeof(vertices));
|
||||||
|
|
||||||
|
userData->num_indices[0] = sizeof(indices) / sizeof(indices[0]);
|
||||||
|
userData->num_indices[1] = sizeof(lineIndices) / sizeof(lineIndices[0]);
|
||||||
|
|
||||||
|
// Bind Vertex Array Object (VAO) and Vertex Buffer Object (VBO), and send vertex data to GPU
|
||||||
|
glGenVertexArrays(1, &userData->vao);
|
||||||
|
glBindVertexArray(userData->vao);
|
||||||
|
|
||||||
|
glGenBuffers(1, &userData->vbo);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, userData->vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), userData->vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// Copy the index array into an index buffer for OpenGL to use
|
||||||
|
glGenBuffers(1, &userData->ebo);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->ebo);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
// Create wireframe EBO
|
||||||
|
glGenBuffers(1, &userData->lineEbo);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->lineEbo);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(lineIndices), lineIndices, GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
// Set vertex pointer attribute
|
||||||
|
GLuint positionAttrib = glGetAttribLocation(userData->programObject, "vPosition");
|
||||||
|
glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void *)0);
|
||||||
|
glEnableVertexAttribArray(positionAttrib);
|
||||||
|
|
||||||
|
// Texture position attribute
|
||||||
|
GLuint textureAttrib = glGetAttribLocation(userData->programObject, "aTexCoord");
|
||||||
|
glVertexAttribPointer(textureAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void *)(3 * sizeof(GLfloat)));
|
||||||
|
glEnableVertexAttribArray(textureAttrib);
|
||||||
|
|
||||||
|
// Load texture
|
||||||
|
GLuint textureID = loadTexture("/usr/data/bianbu2.png");
|
||||||
|
userData->textureID = textureID;
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||||
|
|
||||||
|
// Compute the window aspect ratio
|
||||||
|
float aspect;
|
||||||
|
aspect = (GLfloat)window->geometry.width / (GLfloat)window->geometry.height;
|
||||||
|
// Generate a perspective matrix with a 60 degree FOV
|
||||||
|
esMatrixLoadIdentity(&userData->perspective);
|
||||||
|
esPerspective(&userData->perspective, 60.0f, aspect, 1.0f, 15.0f);
|
||||||
|
|
||||||
|
// Generate a model view matrix to rotate/translate the cube
|
||||||
|
esMatrixLoadIdentity(&userData->modelview);
|
||||||
|
|
||||||
|
// Translate away from the viewer
|
||||||
|
esTranslate(&userData->modelview, 0.0, 0.0, -2.0);
|
||||||
|
|
||||||
|
// Starting rotation angle for the cube
|
||||||
|
userData->angle = 0.0f;
|
||||||
|
// rotate the matrix
|
||||||
|
esRotate(&userData->modelview, userData->angle, 0.5, 1.0, 0.0);
|
||||||
|
|
||||||
|
// Generate a mvp matrix
|
||||||
|
esMatrixMultiply(&userData->mvpMatrix, &userData->modelview, &userData->perspective);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update(struct Window *window)
|
||||||
|
{
|
||||||
|
struct Display *display = window->display;
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
// Rotation angle update interval
|
||||||
|
static uint8_t update_interval;
|
||||||
|
static const uint8_t initial_update_interval = 1.5;
|
||||||
|
static const uint8_t subsequent_update_interval = 3;
|
||||||
|
static uint8_t call_count = 0;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
if (gettimeofday(&tv, NULL) == -1)
|
||||||
|
{
|
||||||
|
printf("get time of day faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
|
// Init rotate_benchmark_time and update_interval
|
||||||
|
if (call_count == 0)
|
||||||
|
{
|
||||||
|
userData->rotate_benchmark_time = time;
|
||||||
|
update_interval = initial_update_interval;
|
||||||
|
}
|
||||||
|
// Update rotate_benchmark_time and angle
|
||||||
|
if (time - userData->rotate_benchmark_time > (update_interval * 1000))
|
||||||
|
{
|
||||||
|
update_interval = subsequent_update_interval;
|
||||||
|
userData->rotate_benchmark_time = time;
|
||||||
|
userData->angle += 3.0f;
|
||||||
|
if (userData->angle > 6.0f)
|
||||||
|
{
|
||||||
|
userData->angle = 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the model view projection matrix
|
||||||
|
esRotate(&userData->modelview, userData->angle, 0.5, 1.0, 0.0);
|
||||||
|
esMatrixMultiply(&userData->mvpMatrix, &userData->modelview, &userData->perspective);
|
||||||
|
|
||||||
|
call_count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Draw(struct Window *window, struct wl_callback *callback, uint32_t time)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Display *display = window->display;
|
||||||
|
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
|
||||||
|
static const uint32_t benchmark_interval = 5;
|
||||||
|
struct wl_region *region;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
if (window->callback != callback)
|
||||||
|
{
|
||||||
|
log_error("window->callback != callback");
|
||||||
|
}
|
||||||
|
window->callback = NULL;
|
||||||
|
|
||||||
|
if (callback)
|
||||||
|
wl_callback_destroy(callback);
|
||||||
|
|
||||||
|
if (gettimeofday(&tv, NULL) == -1)
|
||||||
|
{
|
||||||
|
printf("get time of day faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
|
if (window->frames == 0)
|
||||||
|
window->benchmark_time = time;
|
||||||
|
if (time - window->benchmark_time > (benchmark_interval * 1000))
|
||||||
|
{
|
||||||
|
printf("%d frames in %d seconds: %f fps\n",
|
||||||
|
window->frames,
|
||||||
|
benchmark_interval,
|
||||||
|
(float)window->frames / benchmark_interval);
|
||||||
|
window->benchmark_time = time;
|
||||||
|
window->frames = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the model view projection matrix
|
||||||
|
Update(window);
|
||||||
|
|
||||||
|
// Set the viewport
|
||||||
|
glViewport(0, 0, window->geometry.width, window->geometry.height);
|
||||||
|
// Clear the color buffer
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthFunc(GL_LESS);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
// Use the program object
|
||||||
|
glUseProgram(userData->programObject);
|
||||||
|
|
||||||
|
// Load the MVP matrix
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(userData->programObject, "u_mvpMatrix"), 1, GL_FALSE, (GLfloat *)&userData->mvpMatrix.m[0][0]);
|
||||||
|
|
||||||
|
glBindVertexArray(userData->vao);
|
||||||
|
|
||||||
|
GLenum error = glGetError();
|
||||||
|
if (error != GL_NO_ERROR)
|
||||||
|
{
|
||||||
|
printf("OpenGL Error: %d\n", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rendering Cube
|
||||||
|
glUniform1i(glGetUniformLocation(userData->programObject, "useTexture"), GL_TRUE);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, userData->textureID);
|
||||||
|
glUniform1i(glGetUniformLocation(userData->programObject, "uSampler"), 0);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->ebo);
|
||||||
|
glDrawElements(GL_TRIANGLES, userData->num_indices[0], GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
|
// Rendering wireframe
|
||||||
|
glUniform1i(glGetUniformLocation(userData->programObject, "useTexture"), GL_FALSE);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->lineEbo);
|
||||||
|
glLineWidth(5.0f); // Set line width
|
||||||
|
const GLfloat wireframeColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
|
glVertexAttrib4fv(2, wireframeColor); // Set color
|
||||||
|
glDrawElements(GL_LINES, userData->num_indices[1], GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
|
// Swap buffer
|
||||||
|
eglSwapBuffers(display->egl.dpy, window->egl_surface);
|
||||||
|
|
||||||
|
window->frames++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
void Shutdown(void *data)
|
||||||
|
{
|
||||||
|
struct Window *window = data;
|
||||||
|
UserData *userData = window->userData;
|
||||||
|
|
||||||
|
if (userData->vbo != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->vbo);
|
||||||
|
userData->vbo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->vao != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->vao);
|
||||||
|
userData->vao = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->ebo != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->ebo);
|
||||||
|
userData->ebo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->vertices != NULL)
|
||||||
|
{
|
||||||
|
free(userData->vertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->indices != NULL)
|
||||||
|
{
|
||||||
|
free(userData->indices);
|
||||||
|
}
|
||||||
|
// Delete program object
|
||||||
|
glDeleteProgram(userData->programObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sigaction sigint;
|
||||||
|
struct Display display = {0};
|
||||||
|
struct Window window = {0};
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
window.display = &display;
|
||||||
|
display.window = &window;
|
||||||
|
window.geometry.width = 512;
|
||||||
|
window.geometry.height = 512;
|
||||||
|
window.window_size = window.geometry;
|
||||||
|
window.buffer_size = 0;
|
||||||
|
window.frame_sync = 1;
|
||||||
|
window.delay = 0;
|
||||||
|
|
||||||
|
window.userData = malloc(sizeof(UserData));
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (strcmp("-d", argv[i]) == 0 && i + 1 < argc)
|
||||||
|
window.delay = atoi(argv[++i]);
|
||||||
|
else if (strcmp("-f", argv[i]) == 0)
|
||||||
|
// Set full screen display
|
||||||
|
window.fullscreen = 1;
|
||||||
|
else if (strcmp("-m", argv[i]) == 0)
|
||||||
|
// Maximization mode
|
||||||
|
window.maximized = 1;
|
||||||
|
else if (strcmp("-o", argv[i]) == 0)
|
||||||
|
// Create an opaque surface
|
||||||
|
window.opaque = 1;
|
||||||
|
else if (strcmp("-s", argv[i]) == 0)
|
||||||
|
// EGL configuration using 16bpp (16 bit color mode)
|
||||||
|
window.buffer_size = 16;
|
||||||
|
else if (strcmp("-b", argv[i]) == 0)
|
||||||
|
window.frame_sync = 0;
|
||||||
|
else if (strcmp("-h", argv[i]) == 0)
|
||||||
|
usage(EXIT_SUCCESS);
|
||||||
|
else
|
||||||
|
usage(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (create_window(&window, &display, ret) == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "create window faild!");
|
||||||
|
destroy_window(&window, &display);
|
||||||
|
Shutdown(&window);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Create window success.\n");
|
||||||
|
|
||||||
|
if (!Init(&window))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Init openGL faild!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Init openGL success.\n");
|
||||||
|
|
||||||
|
// Handling SIGINT signals (usually interrupt signals triggered by pressing Ctrl+C)
|
||||||
|
sigint.sa_handler = signal_int;
|
||||||
|
sigemptyset(&sigint.sa_mask);
|
||||||
|
sigint.sa_flags = SA_RESETHAND;
|
||||||
|
sigaction(SIGINT, &sigint, NULL);
|
||||||
|
|
||||||
|
while (global_state.running && ret != -1)
|
||||||
|
{
|
||||||
|
ret = wl_display_dispatch_pending(display.display);
|
||||||
|
Draw(&window, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Simple-egl exiting\n");
|
||||||
|
destroy_window(&window, &display);
|
||||||
|
Shutdown(&window);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
openGLDemo/data/bianbu.png
Normal file
BIN
openGLDemo/data/bianbu.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
BIN
openGLDemo/data/bianbu2.png
Normal file
BIN
openGLDemo/data/bianbu2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 256 KiB |
263
openGLDemo/square_demo.c
Executable file
263
openGLDemo/square_demo.c
Executable file
|
@ -0,0 +1,263 @@
|
||||||
|
/*
|
||||||
|
* GPU test for Spacemit
|
||||||
|
* Copyright (C) 2024 Spacemit Co., Ltd.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <utils_opengles.h>
|
||||||
|
|
||||||
|
static void signal_int(int signum)
|
||||||
|
{
|
||||||
|
global_state.running = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// Handle to a program object
|
||||||
|
GLuint programObject;
|
||||||
|
// Uniform locations
|
||||||
|
GLint mvpLoc;
|
||||||
|
// Vertex data
|
||||||
|
GLfloat *vertices;
|
||||||
|
GLuint *indices;
|
||||||
|
int num_indices;
|
||||||
|
// Rotation angle
|
||||||
|
GLfloat angle;
|
||||||
|
uint32_t rotate_benchmark_time;
|
||||||
|
// MVP matrix
|
||||||
|
ESMatrix mvpMatrix;
|
||||||
|
ESMatrix perspective;
|
||||||
|
ESMatrix modelview;
|
||||||
|
// vertex array, buffer
|
||||||
|
GLuint vao, vbo, ebo;
|
||||||
|
|
||||||
|
} UserData;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize the shader and program object
|
||||||
|
//
|
||||||
|
int Init(struct Window *window)
|
||||||
|
{
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
|
||||||
|
char vertShaderSrc[] = {
|
||||||
|
"#version 300 es\n"
|
||||||
|
"layout(location = 0) in vec4 vPosition;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = vPosition;\n"
|
||||||
|
"}\n"};
|
||||||
|
|
||||||
|
char fragShaderSrc[] = {
|
||||||
|
"#version 300 es\n"
|
||||||
|
"precision mediump float;\n"
|
||||||
|
"out vec4 outColor;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" outColor = vec4 (0.0, 1.0, 0.0, 1.0);\n"
|
||||||
|
"}\n"};
|
||||||
|
|
||||||
|
userData->programObject = load_program(vertShaderSrc, fragShaderSrc);
|
||||||
|
|
||||||
|
// Vertex data matrix
|
||||||
|
float vertices[] = {
|
||||||
|
0.5f, 0.5f, 0.0f, // point 1
|
||||||
|
0.5f, -0.5f, 0.0f, // point 2
|
||||||
|
-0.5f, -0.5f, 0.0f, // point 3
|
||||||
|
-0.5f, 0.5f, 0.0f, // point 4
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int indices[] = {
|
||||||
|
0, 1, 3, // The first triangle
|
||||||
|
1, 2, 3, // The second triangle
|
||||||
|
};
|
||||||
|
|
||||||
|
userData->vertices = (GLfloat *)malloc(sizeof(vertices));
|
||||||
|
memcpy(userData->vertices, vertices, sizeof(vertices));
|
||||||
|
|
||||||
|
userData->num_indices = sizeof(indices) / sizeof(indices[0]);
|
||||||
|
|
||||||
|
// Bind Vertex Array Object (VAO) and Vertex Buffer Object (VBO), and send vertex data to GPU
|
||||||
|
glGenVertexArrays(1, &userData->vao);
|
||||||
|
glBindVertexArray(userData->vao);
|
||||||
|
|
||||||
|
glGenBuffers(1, &userData->vbo);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, userData->vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), userData->vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glGenBuffers(1, &userData->ebo);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->ebo);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void *)0);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Draw(struct Window *window, struct wl_callback *callback, uint32_t time)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Display *display = window->display;
|
||||||
|
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
|
||||||
|
static const uint32_t benchmark_interval = 5;
|
||||||
|
struct wl_region *region;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
if (window->callback != callback)
|
||||||
|
{
|
||||||
|
log_error("window->callback != callback");
|
||||||
|
}
|
||||||
|
window->callback = NULL;
|
||||||
|
|
||||||
|
if (callback)
|
||||||
|
wl_callback_destroy(callback);
|
||||||
|
|
||||||
|
if (gettimeofday(&tv, NULL) == -1)
|
||||||
|
{
|
||||||
|
printf("get time of day faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
|
if (window->frames == 0)
|
||||||
|
window->benchmark_time = time;
|
||||||
|
if (time - window->benchmark_time > (benchmark_interval * 1000))
|
||||||
|
{
|
||||||
|
printf("%d frames in %d seconds: %f fps\n",
|
||||||
|
window->frames,
|
||||||
|
benchmark_interval,
|
||||||
|
(float)window->frames / benchmark_interval);
|
||||||
|
window->benchmark_time = time;
|
||||||
|
window->frames = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the viewport
|
||||||
|
glViewport(0, 0, window->geometry.width, window->geometry.height);
|
||||||
|
// Clear the color buffer
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
// Use the program object
|
||||||
|
glUseProgram(userData->programObject);
|
||||||
|
glBindVertexArray(userData->vao);
|
||||||
|
glDrawElements(GL_TRIANGLES, userData->num_indices, GL_UNSIGNED_INT, 0);
|
||||||
|
eglSwapBuffers(display->egl.dpy, window->egl_surface);
|
||||||
|
|
||||||
|
window->frames++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
void Shutdown(void *data)
|
||||||
|
{
|
||||||
|
struct Window *window = data;
|
||||||
|
UserData *userData = window->userData;
|
||||||
|
|
||||||
|
if (userData->vbo != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->vbo);
|
||||||
|
userData->vbo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->vao != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->vao);
|
||||||
|
userData->vao = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->ebo != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->ebo);
|
||||||
|
userData->ebo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->vertices != NULL)
|
||||||
|
{
|
||||||
|
free(userData->vertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->indices != NULL)
|
||||||
|
{
|
||||||
|
free(userData->indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete program object
|
||||||
|
glDeleteProgram(userData->programObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sigaction sigint;
|
||||||
|
struct Display display = {0};
|
||||||
|
struct Window window = {0};
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
window.display = &display;
|
||||||
|
display.window = &window;
|
||||||
|
window.geometry.width = 512;
|
||||||
|
window.geometry.height = 512;
|
||||||
|
window.window_size = window.geometry;
|
||||||
|
window.buffer_size = 0;
|
||||||
|
window.frame_sync = 1;
|
||||||
|
window.delay = 0;
|
||||||
|
|
||||||
|
window.userData = malloc(sizeof(UserData));
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (strcmp("-d", argv[i]) == 0 && i + 1 < argc)
|
||||||
|
window.delay = atoi(argv[++i]);
|
||||||
|
else if (strcmp("-f", argv[i]) == 0)
|
||||||
|
// Set full screen display
|
||||||
|
window.fullscreen = 1;
|
||||||
|
else if (strcmp("-m", argv[i]) == 0)
|
||||||
|
// Maximization mode
|
||||||
|
window.maximized = 1;
|
||||||
|
else if (strcmp("-o", argv[i]) == 0)
|
||||||
|
// Create an opaque surface
|
||||||
|
window.opaque = 1;
|
||||||
|
else if (strcmp("-s", argv[i]) == 0)
|
||||||
|
// EGL configuration using 16bpp (16 bit color mode)
|
||||||
|
window.buffer_size = 16;
|
||||||
|
else if (strcmp("-b", argv[i]) == 0)
|
||||||
|
window.frame_sync = 0;
|
||||||
|
else if (strcmp("-h", argv[i]) == 0)
|
||||||
|
usage(EXIT_SUCCESS);
|
||||||
|
else
|
||||||
|
usage(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (create_window(&window, &display, ret) == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Create window faild!");
|
||||||
|
destroy_window(&window, &display);
|
||||||
|
Shutdown(&window);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Create window success.\n");
|
||||||
|
|
||||||
|
if (!Init(&window))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Init openGL faild!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Init openGL success.\n");
|
||||||
|
|
||||||
|
// Handling SIGINT signals (usually interrupt signals triggered by pressing Ctrl+C)
|
||||||
|
sigint.sa_handler = signal_int;
|
||||||
|
sigemptyset(&sigint.sa_mask);
|
||||||
|
sigint.sa_flags = SA_RESETHAND;
|
||||||
|
sigaction(SIGINT, &sigint, NULL);
|
||||||
|
|
||||||
|
while (global_state.running && ret != -1)
|
||||||
|
{
|
||||||
|
ret = wl_display_dispatch_pending(display.display);
|
||||||
|
Draw(&window, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Simple-egl exiting\n");
|
||||||
|
destroy_window(&window, &display);
|
||||||
|
Shutdown(&window);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
348
openGLDemo/texture_square_rotation_demo.c
Executable file
348
openGLDemo/texture_square_rotation_demo.c
Executable file
|
@ -0,0 +1,348 @@
|
||||||
|
/*
|
||||||
|
* GPU test for Spacemit
|
||||||
|
* Copyright (C) 2024 Spacemit Co., Ltd.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <utils_opengles.h>
|
||||||
|
|
||||||
|
static void signal_int(int signum)
|
||||||
|
{
|
||||||
|
global_state.running = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// Handle to a program object
|
||||||
|
GLuint programObject;
|
||||||
|
// Uniform locations
|
||||||
|
GLint mvpLoc;
|
||||||
|
// Vertex data
|
||||||
|
GLfloat *vertices;
|
||||||
|
GLuint *indices;
|
||||||
|
int num_indices;
|
||||||
|
// Rotation angle
|
||||||
|
GLfloat angle;
|
||||||
|
uint32_t rotate_benchmark_time;
|
||||||
|
// MVP matrix
|
||||||
|
ESMatrix mvpMatrix;
|
||||||
|
ESMatrix perspective;
|
||||||
|
ESMatrix modelview;
|
||||||
|
// vertex array, buffer
|
||||||
|
GLuint vao, vbo, ebo;
|
||||||
|
|
||||||
|
} UserData;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize the shader and program object
|
||||||
|
//
|
||||||
|
int Init(struct Window *window)
|
||||||
|
{
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
|
||||||
|
char vertShaderSrc[] = {
|
||||||
|
"#version 300 es\n"
|
||||||
|
"layout(location = 0) in vec4 vPosition;\n"
|
||||||
|
"layout(location = 1) in vec2 aTextureCoord;\n"
|
||||||
|
"uniform mat4 u_mvpMatrix;\n"
|
||||||
|
"out vec2 vTextureCoord;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = u_mvpMatrix * vPosition;\n"
|
||||||
|
" vTextureCoord = aTextureCoord;\n"
|
||||||
|
"}\n"};
|
||||||
|
|
||||||
|
char fragShaderSrc[] = {
|
||||||
|
"#version 300 es\n"
|
||||||
|
"precision mediump float;\n"
|
||||||
|
"uniform sampler2D uSampler;\n"
|
||||||
|
"in vec2 vTextureCoord;\n"
|
||||||
|
"out vec4 outColor;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" outColor = texture(uSampler, vTextureCoord);\n"
|
||||||
|
"}\n"};
|
||||||
|
|
||||||
|
userData->programObject = load_program(vertShaderSrc, fragShaderSrc);
|
||||||
|
|
||||||
|
// Get the uniform locations
|
||||||
|
userData->mvpLoc = glGetUniformLocation(userData->programObject, "u_mvpMatrix");
|
||||||
|
|
||||||
|
float vertices[] = {
|
||||||
|
// Vertex // texture
|
||||||
|
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // point 1
|
||||||
|
0.5f, -0.5f, 0.0f, 1.0f, 1.0f, // point 2
|
||||||
|
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // point 3
|
||||||
|
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f // point 4
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int indices[] = {
|
||||||
|
0, 1, 3,
|
||||||
|
1, 2, 3};
|
||||||
|
|
||||||
|
userData->vertices = (GLfloat *)malloc(sizeof(vertices));
|
||||||
|
memcpy(userData->vertices, vertices, sizeof(vertices));
|
||||||
|
|
||||||
|
userData->num_indices = sizeof(indices) / sizeof(indices[0]);
|
||||||
|
|
||||||
|
// Load texture
|
||||||
|
GLuint textureID = loadTexture("/usr/data/bianbu.png");
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||||
|
|
||||||
|
// Bind Vertex Array Object (VAO) and Vertex Buffer Object (VBO), and send vertex data to GPU
|
||||||
|
glGenVertexArrays(1, &userData->vao);
|
||||||
|
glBindVertexArray(userData->vao);
|
||||||
|
|
||||||
|
glGenBuffers(1, &userData->vbo);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, userData->vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), userData->vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glGenBuffers(1, &userData->ebo);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->ebo);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// Vertex position attribute
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void *)0);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
// Texture position attribute
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void *)(3 * sizeof(GLfloat)));
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
|
// Compute the window aspect ratio
|
||||||
|
float aspect;
|
||||||
|
aspect = (GLfloat)window->geometry.width / (GLfloat)window->geometry.height;
|
||||||
|
// Generate a perspective matrix with a 60 degree FOV
|
||||||
|
esMatrixLoadIdentity(&userData->perspective);
|
||||||
|
esPerspective(&userData->perspective, 60.0f, aspect, 1.0f, 15.0f);
|
||||||
|
|
||||||
|
// Generate a model view matrix to rotate/translate the cube
|
||||||
|
esMatrixLoadIdentity(&userData->modelview);
|
||||||
|
|
||||||
|
// Translate away from the viewer
|
||||||
|
esTranslate(&userData->modelview, 0.0, 0.0, -2.0);
|
||||||
|
|
||||||
|
// Starting rotation angle for the cube
|
||||||
|
userData->angle = 0.0f;
|
||||||
|
// rotate the matrix
|
||||||
|
esRotate(&userData->modelview, userData->angle, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
// Generate a mvp matrix
|
||||||
|
esMatrixMultiply(&userData->mvpMatrix, &userData->modelview, &userData->perspective);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update(struct Window *window)
|
||||||
|
{
|
||||||
|
struct Display *display = window->display;
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
// Rotation angle update interval
|
||||||
|
static uint8_t update_interval;
|
||||||
|
static const uint8_t initial_update_interval = 1.5;
|
||||||
|
static const uint8_t subsequent_update_interval = 3;
|
||||||
|
static uint8_t call_count = 0;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
if (gettimeofday(&tv, NULL) == -1)
|
||||||
|
{
|
||||||
|
printf("get time of day faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
|
// Init rotate_benchmark_time and update_interval
|
||||||
|
if (call_count == 0)
|
||||||
|
{
|
||||||
|
userData->rotate_benchmark_time = time;
|
||||||
|
update_interval = initial_update_interval;
|
||||||
|
}
|
||||||
|
// Update rotate_benchmark_time and angle
|
||||||
|
if (time - userData->rotate_benchmark_time > (update_interval * 1000))
|
||||||
|
{
|
||||||
|
update_interval = subsequent_update_interval;
|
||||||
|
userData->rotate_benchmark_time = time;
|
||||||
|
userData->angle += 5.0f;
|
||||||
|
if (userData->angle > 12.0f)
|
||||||
|
{
|
||||||
|
userData->angle = 2.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Update the model view projection matrix
|
||||||
|
esRotate(&userData->modelview, userData->angle, 0.0, 1.0, 0.0);
|
||||||
|
esMatrixMultiply(&userData->mvpMatrix, &userData->modelview, &userData->perspective);
|
||||||
|
|
||||||
|
call_count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Draw(struct Window *window, struct wl_callback *callback, uint32_t time)
|
||||||
|
{
|
||||||
|
struct Display *display = window->display;
|
||||||
|
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
|
||||||
|
static const uint32_t benchmark_interval = 5;
|
||||||
|
struct wl_region *region;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
if (window->callback != callback)
|
||||||
|
{
|
||||||
|
log_error("window->callback != callback");
|
||||||
|
}
|
||||||
|
window->callback = NULL;
|
||||||
|
|
||||||
|
if (callback)
|
||||||
|
wl_callback_destroy(callback);
|
||||||
|
|
||||||
|
if (gettimeofday(&tv, NULL) == -1)
|
||||||
|
{
|
||||||
|
printf("get time of day faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
|
if (window->frames == 0)
|
||||||
|
window->benchmark_time = time;
|
||||||
|
if (time - window->benchmark_time > (benchmark_interval * 1000))
|
||||||
|
{
|
||||||
|
printf("%d frames in %d seconds: %f fps\n",
|
||||||
|
window->frames,
|
||||||
|
benchmark_interval,
|
||||||
|
(float)window->frames / benchmark_interval);
|
||||||
|
window->benchmark_time = time;
|
||||||
|
window->frames = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the model view projection matrix
|
||||||
|
Update(window);
|
||||||
|
// Set the viewport
|
||||||
|
glViewport(0, 0, window->geometry.width, window->geometry.height);
|
||||||
|
// Clear the color buffer
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
// Use the program object
|
||||||
|
glUseProgram(userData->programObject);
|
||||||
|
// Load the MVP matrix
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(userData->programObject, "u_mvpMatrix"), 1, GL_FALSE, (GLfloat *)&userData->mvpMatrix.m[0][0]);
|
||||||
|
// printf("mvpMatrix: %f\n", userData->mvpMatrix[0]);
|
||||||
|
glBindVertexArray(userData->vao);
|
||||||
|
glDrawElements(GL_TRIANGLES, userData->num_indices, GL_UNSIGNED_INT, 0);
|
||||||
|
// Swap buffer
|
||||||
|
eglSwapBuffers(display->egl.dpy, window->egl_surface);
|
||||||
|
|
||||||
|
window->frames++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
void Shutdown(void *data)
|
||||||
|
{
|
||||||
|
struct Window *window = data;
|
||||||
|
UserData *userData = window->userData;
|
||||||
|
|
||||||
|
if (userData->vbo != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->vbo);
|
||||||
|
userData->vbo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->vao != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->vao);
|
||||||
|
userData->vao = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->ebo != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->ebo);
|
||||||
|
userData->ebo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->vertices != NULL)
|
||||||
|
{
|
||||||
|
free(userData->vertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->indices != NULL)
|
||||||
|
{
|
||||||
|
free(userData->indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete program object
|
||||||
|
glDeleteProgram(userData->programObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sigaction sigint;
|
||||||
|
struct Display display = {0};
|
||||||
|
struct Window window = {0};
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
window.display = &display;
|
||||||
|
display.window = &window;
|
||||||
|
window.geometry.width = 512;
|
||||||
|
window.geometry.height = 512;
|
||||||
|
window.window_size = window.geometry;
|
||||||
|
window.buffer_size = 0;
|
||||||
|
window.frame_sync = 1;
|
||||||
|
window.delay = 0;
|
||||||
|
|
||||||
|
window.userData = malloc(sizeof(UserData));
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (strcmp("-d", argv[i]) == 0 && i + 1 < argc)
|
||||||
|
window.delay = atoi(argv[++i]);
|
||||||
|
else if (strcmp("-f", argv[i]) == 0)
|
||||||
|
// Set full screen display
|
||||||
|
window.fullscreen = 1;
|
||||||
|
else if (strcmp("-m", argv[i]) == 0)
|
||||||
|
// Maximization mode
|
||||||
|
window.maximized = 1;
|
||||||
|
else if (strcmp("-o", argv[i]) == 0)
|
||||||
|
// Create an opaque surface
|
||||||
|
window.opaque = 1;
|
||||||
|
else if (strcmp("-s", argv[i]) == 0)
|
||||||
|
// EGL configuration using 16bpp (16 bit color mode)
|
||||||
|
window.buffer_size = 16;
|
||||||
|
else if (strcmp("-b", argv[i]) == 0)
|
||||||
|
window.frame_sync = 0;
|
||||||
|
else if (strcmp("-h", argv[i]) == 0)
|
||||||
|
usage(EXIT_SUCCESS);
|
||||||
|
else
|
||||||
|
usage(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (create_window(&window, &display, ret) == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Create window faild!");
|
||||||
|
destroy_window(&window, &display);
|
||||||
|
Shutdown(&window);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Create window success.\n");
|
||||||
|
|
||||||
|
if (!Init(&window))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Init openGL faild!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Init openGL success.\n");
|
||||||
|
|
||||||
|
// Handling SIGINT signals (usually interrupt signals triggered by pressing Ctrl+C)
|
||||||
|
sigint.sa_handler = signal_int;
|
||||||
|
sigemptyset(&sigint.sa_mask);
|
||||||
|
sigint.sa_flags = SA_RESETHAND;
|
||||||
|
sigaction(SIGINT, &sigint, NULL);
|
||||||
|
|
||||||
|
while (global_state.running && ret != -1)
|
||||||
|
{
|
||||||
|
ret = wl_display_dispatch_pending(display.display);
|
||||||
|
Draw(&window, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Simple-egl exiting\n");
|
||||||
|
|
||||||
|
destroy_window(&window, &display);
|
||||||
|
Shutdown(&window);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
255
openGLDemo/triangle_demo.c
Executable file
255
openGLDemo/triangle_demo.c
Executable file
|
@ -0,0 +1,255 @@
|
||||||
|
/*
|
||||||
|
* GPU test for Spacemit
|
||||||
|
* Copyright (C) 2024 Spacemit Co., Ltd.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <utils_opengles.h>
|
||||||
|
|
||||||
|
static void signal_int(int signum)
|
||||||
|
{
|
||||||
|
global_state.running = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// Handle to a program object
|
||||||
|
GLuint programObject;
|
||||||
|
// Vertex data
|
||||||
|
GLfloat *vertices;
|
||||||
|
GLuint *indices;
|
||||||
|
// vertex array, buffer
|
||||||
|
GLuint vao, vbo;
|
||||||
|
|
||||||
|
} UserData;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize the shader and program object
|
||||||
|
//
|
||||||
|
int Init(struct Window *window)
|
||||||
|
{
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
|
||||||
|
char vertShaderSrc[] = {
|
||||||
|
"#version 300 es\n"
|
||||||
|
"layout(location = 0) in vec4 vPosition;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = vPosition;\n"
|
||||||
|
"}"};
|
||||||
|
|
||||||
|
char fragShaderSrc[] = {
|
||||||
|
"#version 300 es\n"
|
||||||
|
"precision mediump float;\n"
|
||||||
|
"out vec4 outColor;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" outColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
|
||||||
|
"}"};
|
||||||
|
|
||||||
|
char *pszVertShader = (char *)vertShaderSrc;
|
||||||
|
char *pszFragShader = (char *)fragShaderSrc;
|
||||||
|
|
||||||
|
GLuint textureVertShader = 0; // Handle used to store Vertex and Fragment shader
|
||||||
|
GLuint textureFragShader = 0;
|
||||||
|
GLuint textureProgramObject = 0; // Used to store the handle of the created program
|
||||||
|
|
||||||
|
// Create Vertex Shader
|
||||||
|
textureVertShader = load_shader(pszVertShader, GL_VERTEX_SHADER);
|
||||||
|
// Create Fragment Shader
|
||||||
|
textureFragShader = load_shader(pszFragShader, GL_FRAGMENT_SHADER);
|
||||||
|
// Create rogramObject
|
||||||
|
textureProgramObject = glCreateProgram();
|
||||||
|
// Bind Vertex and Fragment Shader
|
||||||
|
glAttachShader(textureProgramObject, textureVertShader);
|
||||||
|
glAttachShader(textureProgramObject, textureFragShader);
|
||||||
|
// Link program
|
||||||
|
glLinkProgram(textureProgramObject);
|
||||||
|
checkProgramLinking(textureProgramObject);
|
||||||
|
userData->programObject = textureProgramObject;
|
||||||
|
|
||||||
|
// data
|
||||||
|
float vertices[] =
|
||||||
|
{
|
||||||
|
-0.5f, -0.5f, 0.0f, // point 1
|
||||||
|
0.5f, -0.5f, 0.0f, // point 2
|
||||||
|
0.0f, 0.5f, 0.0f, // point 3
|
||||||
|
};
|
||||||
|
|
||||||
|
userData->vertices = (GLfloat *)malloc(sizeof(vertices));
|
||||||
|
memcpy(userData->vertices, vertices, sizeof(vertices));
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &userData->vao);
|
||||||
|
glBindVertexArray(userData->vao);
|
||||||
|
|
||||||
|
glGenBuffers(1, &userData->vbo);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, userData->vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), userData->vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void *)0);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Draw(struct Window *window, struct wl_callback *callback, uint32_t time)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Display *display = window->display;
|
||||||
|
|
||||||
|
UserData *userData = (UserData *)window->userData;
|
||||||
|
|
||||||
|
static const uint32_t benchmark_interval = 5;
|
||||||
|
struct wl_region *region;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
if (window->callback != callback)
|
||||||
|
{
|
||||||
|
log_error("window->callback != callback");
|
||||||
|
}
|
||||||
|
window->callback = NULL;
|
||||||
|
|
||||||
|
if (callback)
|
||||||
|
wl_callback_destroy(callback);
|
||||||
|
|
||||||
|
if (gettimeofday(&tv, NULL) == -1)
|
||||||
|
{
|
||||||
|
printf("get time of day faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
|
|
||||||
|
if (window->frames == 0)
|
||||||
|
window->benchmark_time = time;
|
||||||
|
if (time - window->benchmark_time > (benchmark_interval * 1000))
|
||||||
|
{
|
||||||
|
printf("%d frames in %d seconds: %f fps\n",
|
||||||
|
window->frames,
|
||||||
|
benchmark_interval,
|
||||||
|
(float)window->frames / benchmark_interval);
|
||||||
|
window->benchmark_time = time;
|
||||||
|
window->frames = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the viewport
|
||||||
|
glViewport(0, 0, window->geometry.width, window->geometry.height);
|
||||||
|
// Clear the color buffer
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
// Bind program object
|
||||||
|
glUseProgram(userData->programObject);
|
||||||
|
// Bind vao
|
||||||
|
glBindVertexArray(userData->vao);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
// Swap buffer
|
||||||
|
eglSwapBuffers(display->egl.dpy, window->egl_surface);
|
||||||
|
|
||||||
|
window->frames++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
void Shutdown(void *data)
|
||||||
|
{
|
||||||
|
struct Window *window = data;
|
||||||
|
UserData *userData = window->userData;
|
||||||
|
|
||||||
|
if (userData->vbo != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->vbo);
|
||||||
|
userData->vbo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->vao != 0)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &userData->vao);
|
||||||
|
userData->vao = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->vertices != NULL)
|
||||||
|
{
|
||||||
|
free(userData->vertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData->indices != NULL)
|
||||||
|
{
|
||||||
|
free(userData->indices);
|
||||||
|
}
|
||||||
|
// Delete program object
|
||||||
|
glDeleteProgram(userData->programObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sigaction sigint;
|
||||||
|
struct Display display = {0};
|
||||||
|
struct Window window = {0};
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
window.display = &display;
|
||||||
|
display.window = &window;
|
||||||
|
window.geometry.width = 512;
|
||||||
|
window.geometry.height = 512;
|
||||||
|
window.window_size = window.geometry;
|
||||||
|
window.buffer_size = 0;
|
||||||
|
window.frame_sync = 1;
|
||||||
|
window.delay = 0;
|
||||||
|
|
||||||
|
window.userData = malloc(sizeof(UserData));
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (strcmp("-d", argv[i]) == 0 && i + 1 < argc)
|
||||||
|
window.delay = atoi(argv[++i]);
|
||||||
|
else if (strcmp("-f", argv[i]) == 0)
|
||||||
|
// Set full screen display
|
||||||
|
window.fullscreen = 1;
|
||||||
|
else if (strcmp("-m", argv[i]) == 0)
|
||||||
|
// Maximization mode
|
||||||
|
window.maximized = 1;
|
||||||
|
else if (strcmp("-o", argv[i]) == 0)
|
||||||
|
// Create an opaque surface
|
||||||
|
window.opaque = 1;
|
||||||
|
else if (strcmp("-s", argv[i]) == 0)
|
||||||
|
// EGL configuration using 16bpp (16 bit color mode)
|
||||||
|
window.buffer_size = 16;
|
||||||
|
else if (strcmp("-b", argv[i]) == 0)
|
||||||
|
window.frame_sync = 0;
|
||||||
|
else if (strcmp("-h", argv[i]) == 0)
|
||||||
|
usage(EXIT_SUCCESS);
|
||||||
|
else
|
||||||
|
usage(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (create_window(&window, &display, ret) == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Create window faild!");
|
||||||
|
destroy_window(&window, &display);
|
||||||
|
Shutdown(&window);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Create window success.\n");
|
||||||
|
|
||||||
|
if (!Init(&window))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Init openGL faild!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Init openGL success.\n");
|
||||||
|
|
||||||
|
sigint.sa_handler = signal_int;
|
||||||
|
sigemptyset(&sigint.sa_mask);
|
||||||
|
sigint.sa_flags = SA_RESETHAND;
|
||||||
|
sigaction(SIGINT, &sigint, NULL);
|
||||||
|
|
||||||
|
while (global_state.running && ret != -1)
|
||||||
|
{
|
||||||
|
ret = wl_display_dispatch_pending(display.display);
|
||||||
|
Draw(&window, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Simple-egl exiting\n");
|
||||||
|
destroy_window(&window, &display);
|
||||||
|
Shutdown(&window);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue