mirror of
https://gitee.com/bianbu-linux/k1x-gpu-test
synced 2025-04-18 19:25:05 -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
Reference in a new issue