diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d170ed4c..e4da7f34 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -284,7 +284,7 @@ jobs: - name: Build Linux run: | - node build_tgfx -DTGFX_USE_SWIFTSHADER=ON + node build_tgfx -s ./linux Hello2D -o ./out/release/linux -a x64 - name: Save Third-Party Cache if: ${{ (github.event_name == 'push') && (steps.third-party-cache.outputs.cache-hit != 'true') }} diff --git a/.idea/misc.xml b/.idea/misc.xml index 5fe263c2..e20dc0fc 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -15,7 +15,6 @@ - \ No newline at end of file diff --git a/README.md b/README.md index f04515bb..79e424f4 100644 --- a/README.md +++ b/README.md @@ -268,6 +268,27 @@ pack the generated `.wasm` file into the final web program. This is because comm usually ignore the `.wasm` file. Moreover, remember to upload the `.wasm` file to a server, enabling users to access it from the network. +### Linux + +When running Linux, the system usually lacks GPU hardware support. Therefore, we utilize the +[**SwiftShader**](https://github.com/google/swiftshader) library to emulate the GPU rendering +environment. Since SwiftShader relies on certain X11 header files, it is necessary to install the +following packages before building the demo project: + +``` +yum install libX11-devel --nogpg +``` + +Next, execute the following commands in the linux/ directory: + +``` +cmake -B ./build -DCMAKE_BUILD_TYPE=Release +cmake --build ./build -- -j 12 +``` + +You will get the demo executable file in the build directory. You also have the option of opening +the `linux/` directory in CLion and building the demo project directly in the IDE. + ### Windows To start, open the `win/` directory in CLion. Next, open the `File->Setting` panel and navigate to diff --git a/codeformat.sh b/codeformat.sh index 4f0c683d..65eb25d2 100755 --- a/codeformat.sh +++ b/codeformat.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash +cd $(dirname $0) + if [[ $(uname) == 'Darwin' ]]; then MAC_REQUIRED_TOOLS="python3" for TOOL in ${MAC_REQUIRED_TOOLS[@]}; do @@ -26,24 +28,24 @@ echo "----begin to scan code format----" find include -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i find src -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i find drawers -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i -find test -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i -find qt -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i -find ios -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i -find mac -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i -find linux -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i -find win -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i -find web -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i -find android -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i +find test/src -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i +find qt/src -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i +find ios/Hello2D -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i +find mac/Hello2D -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i +find linux/src -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i +find win/src -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i +find web/demo/src -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i +find android/app/src -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i git diff result=`git diff` if [[ $result =~ "diff" ]] then - echo "----Failed to pass coding specification----" + echo "----Failed to pass the code format check----" exit 1 else - echo "----Pass coding specification----" + echo "----Complete the code format check-----" fi -echo "----Complete the scan code format-----" + diff --git a/linux/.idea/fileTemplates/includes/TGFX File Header.h b/linux/.idea/fileTemplates/includes/TGFX File Header.h new file mode 100644 index 00000000..9a045aca --- /dev/null +++ b/linux/.idea/fileTemplates/includes/TGFX File Header.h @@ -0,0 +1,17 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making tgfx available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/linux/.idea/fileTemplates/internal/C Header File.h b/linux/.idea/fileTemplates/internal/C Header File.h new file mode 100644 index 00000000..d7f0678b --- /dev/null +++ b/linux/.idea/fileTemplates/internal/C Header File.h @@ -0,0 +1,7 @@ +#parse("TGFX File Header.h") + +#pragma once + +namespace tgfx { + +} // namespace tgfx diff --git a/linux/.idea/fileTemplates/internal/C Source File.c b/linux/.idea/fileTemplates/internal/C Source File.c new file mode 100644 index 00000000..1df3e1b3 --- /dev/null +++ b/linux/.idea/fileTemplates/internal/C Source File.c @@ -0,0 +1,8 @@ +#parse("TGFX File Header.h") +#if (${HEADER_FILENAME}) +#[[#include]]# "${HEADER_FILENAME}" +#end + +namespace tgfx { + +} // namespace tgfx \ No newline at end of file diff --git a/linux/.idea/fileTemplates/internal/C++ Class Header.h b/linux/.idea/fileTemplates/internal/C++ Class Header.h new file mode 100644 index 00000000..e1c28ff0 --- /dev/null +++ b/linux/.idea/fileTemplates/internal/C++ Class Header.h @@ -0,0 +1,9 @@ +#parse("TGFX File Header.h") + +#pragma once + +namespace tgfx { +class ${NAME} { + public: +}; +} // namespace tgfx diff --git a/linux/.idea/fileTemplates/internal/C++ Class.cc b/linux/.idea/fileTemplates/internal/C++ Class.cc new file mode 100644 index 00000000..6df4f00d --- /dev/null +++ b/linux/.idea/fileTemplates/internal/C++ Class.cc @@ -0,0 +1,7 @@ +#parse("TGFX File Header.h") + +#[[#include]]# "${HEADER_FILENAME}" + +namespace tgfx { + +} // namespace tgfx diff --git a/linux/.idea/misc.xml b/linux/.idea/misc.xml new file mode 100644 index 00000000..79b3c948 --- /dev/null +++ b/linux/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt new file mode 100644 index 00000000..87cf48d2 --- /dev/null +++ b/linux/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.13) +project(Hello2D) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release") +endif () + +if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR $CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64") + set(ARCH x64) +elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") + set(ARCH arm64) +else () + set(ARCH x86) +endif () + +file(GLOB SWIFTSHADER_LIBS ../vendor/swiftshader/mac/${ARCH}/*.${CMAKE_SHARED_LIBRARY_SUFFIX}) +list(APPEND HELLO_2D_LIBS ${SWIFTSHADER_LIBS}) +list(APPEND HELLO_2D_INCLUDES ../vendor/swiftshader/include) + +if (APPLE) + find_library(APPLICATION_SERVICES_FRAMEWORK ApplicationServices REQUIRED) + list(APPEND HELLO_2D_LIBS ${APPLICATION_SERVICES_FRAMEWORK}) + find_library(QUARTZ_CORE QuartzCore REQUIRED) + list(APPEND HELLO_2D_LIBS ${QUARTZ_CORE}) + find_library(COCOA Cocoa REQUIRED) + list(APPEND HELLO_2D_LIBS ${COCOA}) + find_library(FOUNDATION Foundation REQUIRED) + list(APPEND HELLO_2D_LIBS ${FOUNDATION}) + find_library(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2 c) + list(APPEND HELLO_2D_LIBS ${ICONV_LIBRARIES}) + find_library(CORE_MEDIA CoreMedia) + list(APPEND HELLO_2D_LIBS ${CORE_MEDIA}) +else () + find_package(Threads) + list(APPEND HELLO_2D_LIBS ${CMAKE_THREAD_LIBS_INIT}) + list(APPEND HELLO_2D_LIBS dl) + list(APPEND HELLO_2D_COMPILE_OPTIONS -fPIC -pthread) +endif () + +set(TGFX_BUILD_DRAWERS ON) +set(TGFX_USE_SWIFTSHADER ON) +set(TGFX_USE_FREETYPE ON) + +set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../ ./tgfx) + +file(GLOB_RECURSE HELLO_2D_SOURCE_FILES src/*.*) +add_executable(Hello2D ${HELLO_2D_SOURCE_FILES}) +target_include_directories(Hello2D PRIVATE ${HELLO_2D_INCLUDES} src) +target_link_libraries(Hello2D tgfx-drawers tgfx ${HELLO_2D_LIBS}) + diff --git a/linux/src/main.cpp b/linux/src/main.cpp new file mode 100644 index 00000000..1627db9c --- /dev/null +++ b/linux/src/main.cpp @@ -0,0 +1,87 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making tgfx available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "drawers/Drawer.h" +#include "tgfx/gpu/Surface.h" +#include "tgfx/opengl/GLDevice.h" +#include "tgfx/platform/Print.h" + +static std::string GetRootPath() { + std::filesystem::path filePath = __FILE__; + auto dir = filePath.parent_path().string(); + return std::filesystem::path(dir + "/../..").lexically_normal(); +} + +static void SaveFile(std::shared_ptr data, const std::string& output) { + std::filesystem::path path = output; + std::filesystem::create_directories(path.parent_path()); + std::ofstream out(path); + out.write(reinterpret_cast(data->data()), + static_cast(data->size())); + out.close(); +} + +int main() { + auto rootPath = GetRootPath(); + drawers::AppHost appHost(720, 720, 2.0f); + auto image = tgfx::Image::MakeFromFile(rootPath + "resources/assets/bridge.jpg"); + appHost.addImage("bridge", std::move(image)); + auto typeface = tgfx::Typeface::MakeFromPath(rootPath + "resources/font/NotoSansSC-Regular.otf"); + appHost.addTypeface("default", std::move(typeface)); + typeface = tgfx::Typeface::MakeFromPath(rootPath + "resources/font/NotoColorEmoji.ttf"); + appHost.addTypeface("emoji", std::move(typeface)); + + auto device = tgfx::GLDevice::Make(); + if (device == nullptr) { + tgfx::PrintError("Failed to create the Device!"); + return -1; + } + auto context = device->lockContext(); + if (context == nullptr) { + tgfx::PrintError("Failed to lock the Context!"); + return -1; + } + auto surface = tgfx::Surface::Make(context, appHost.width(), appHost.height()); + auto canvas = surface->getCanvas(); + auto drawerNames = drawers::Drawer::Names(); + for (auto& name : drawerNames) { + auto drawer = drawers::Drawer::GetByName(name); + canvas->clear(); + drawer->draw(canvas, &appHost); + tgfx::Bitmap bitmap = {}; + bitmap.allocPixels(surface->width(), surface->height()); + auto pixels = bitmap.lockPixels(); + auto success = surface->readPixels(bitmap.info(), pixels); + bitmap.unlockPixels(); + if (!success) { + tgfx::PrintError("Failed to readPixels!"); + return -1; + } + auto data = bitmap.encode(); + if (data == nullptr) { + tgfx::PrintError("Failed to encode bitmap!"); + return -1; + } + SaveFile(data, "out/" + name + ".png"); + } + device->unlock(); + tgfx::PrintLog("All images have been saved to the 'out/' directory"); + return 0; +}