Android WIP: support OpenGL ES 3.2 and implement Android backend library

This commit is contained in:
Nikita Lisitsa 2023-07-18 15:43:14 +03:00
parent 93d5c55c68
commit 54b78e6c66
28 changed files with 3666 additions and 66 deletions

View file

@ -31,21 +31,37 @@ if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
list(APPEND PSEMEK_CXX_FLAGS -Wno-dtor-name) list(APPEND PSEMEK_CXX_FLAGS -Wno-dtor-name)
endif() endif()
set(PSEMEK_BACKEND "SDL2" CACHE STRING "Application backend (OFF/SDL2)") set(PSEMEK_BACKEND "SDL2" CACHE STRING "Application backend (OFF/SDL2/ANDROID)")
option(PSEMEK_LEGACY_UI "Use legacy UI library" OFF) option(PSEMEK_LEGACY_UI "Use legacy UI library" OFF)
message(STATUS "Using backend ${PSEMEK_BACKEND}") message(STATUS "Using backend ${PSEMEK_BACKEND}")
if(PSEMEK_BACKEND STREQUAL "ANDROID")
set(PSEMEK_GL_API gles32)
set(PSEMEK_GL_LIBRARIES GLESv3 EGL)
set(PSEMEK_PACKAGE_AS_LIBRARY ON CACHE INTERNAL "Build applications as shared libraries")
list(APPEND PSEMEK_CXX_FLAGS -fPIC)
else()
find_package(Threads REQUIRED)
set(OpenGL_GL_PREFERENCE LEGACY)
find_package(OpenGL REQUIRED)
set(PSEMEK_GL_API gl33)
set(PSEMEK_GL_LIBRARIES OpenGL::GL)
set(PSEMEK_PACKAGE_AS_LIBRARY OFF CACHE INTERNAL "Build applications as shared libraries")
endif()
add_subdirectory(3rdparty) add_subdirectory(3rdparty)
get_directory_property(PSEMEK_PARENT_DIRECTORY PARENT_DIRECTORY) get_directory_property(PSEMEK_PARENT_DIRECTORY PARENT_DIRECTORY)
add_subdirectory(package) add_subdirectory(package)
if(PSEMEK_PACKAGE_MODE) if(PSEMEK_PACKAGE_MODE AND PSEMEK_PACKAGE_TARGET AND NOT PSEMEK_PACKAGE_AS_LIBRARY)
set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_LIBS ON)
endif() endif()
find_package(PNG REQUIRED)
add_subdirectory(tools) add_subdirectory(tools)
add_subdirectory(libs) add_subdirectory(libs)
@ -58,9 +74,6 @@ psemek_add_library(psemek EXCLUDE_FROM_ALL ${PSEMEK_SOURCES})
target_link_libraries(psemek INTERFACE ${PSEMEK_LIBRARIES}) target_link_libraries(psemek INTERFACE ${PSEMEK_LIBRARIES})
set_target_properties(psemek PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(psemek PROPERTIES LINKER_LANGUAGE CXX)
psemek_add_library(psemek-backend EXCLUDE_FROM_ALL)
target_link_libraries(psemek-backend INTERFACE psemek ${PSEMEK_BACKEND_LIBRARY})
option(PSEMEK_EXAMPLES "Build example apps" ON) option(PSEMEK_EXAMPLES "Build example apps" ON)
if(PSEMEK_EXAMPLES) if(PSEMEK_EXAMPLES)

View file

@ -7,10 +7,12 @@ else()
list(REMOVE_ITEM PSEMEK_LIB_DIRS "ui_legacy") list(REMOVE_ITEM PSEMEK_LIB_DIRS "ui_legacy")
endif() endif()
list(REMOVE_ITEM PSEMEK_LIB_DIRS "sdl2") list(REMOVE_ITEM PSEMEK_LIB_DIRS sdl2 android)
set(PSEMEK_BACKEND_LIB_DIR) set(PSEMEK_BACKEND_LIB_DIR)
if(PSEMEK_BACKEND STREQUAL "SDL2") if(PSEMEK_BACKEND STREQUAL "SDL2")
set(PSEMEK_BACKEND_LIB_DIR "sdl2") set(PSEMEK_BACKEND_LIB_DIR "sdl2")
elseif(PSEMEK_BACKEND STREQUAL "ANDROID")
set(PSEMEK_BACKEND_LIB_DIR "android")
endif() endif()
set(PSEMEK_LIBRARIES) set(PSEMEK_LIBRARIES)
@ -29,4 +31,4 @@ foreach(lib ${PSEMEK_LIB_DIRS} ${PSEMEK_BACKEND_LIB_DIR})
endforeach() endforeach()
set(PSEMEK_LIBRARIES ${PSEMEK_LIBRARIES} PARENT_SCOPE) set(PSEMEK_LIBRARIES ${PSEMEK_LIBRARIES} PARENT_SCOPE)
set(PSEMEK_BACKEND_LIBRARY ${PSEMEK_BACKEND_LIBRARY} PARENT_SCOPE) set(PSEMEK_BACKEND_LIBRARY ${PSEMEK_BACKEND_LIBRARY} CACHE INTERNAL "Application backend library target")

View file

@ -0,0 +1,6 @@
file(GLOB_RECURSE PSEMEK_ANDROID_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp")
file(GLOB_RECURSE PSEMEK_ANDROID_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp")
psemek_add_library(psemek-android ${PSEMEK_ANDROID_HEADERS} ${PSEMEK_ANDROID_SOURCES})
target_include_directories(psemek-android PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(psemek-android PUBLIC psemek-log psemek-util psemek-gfx psemek-audio psemek-app android log)

View file

@ -0,0 +1,57 @@
#include <psemek/audio/engine.hpp>
#include <psemek/audio/constants.hpp>
#include <psemek/log/log.hpp>
#include <psemek/prof/profiler.hpp>
#include <psemek/util/at_scope_exit.hpp>
#include <psemek/util/to_string.hpp>
#include <jni.h>
namespace psemek::android
{
namespace
{
audio::channel_ptr output_channel = std::make_shared<audio::channel>();
struct audio_engine_impl
: audio::engine
{
audio::channel_ptr output() override
{
return output_channel;
}
};
}
}
namespace psemek::audio
{
std::unique_ptr<engine> make_engine()
{
return std::make_unique<android::audio_engine_impl>();
}
}
extern "C" int Java_psemek_app_PsemekApplication_audioFrequencyNative(JNIEnv *, jclass)
{
return psemek::audio::frequency;
}
extern "C" int Java_psemek_app_PsemekApplication_audioGetSamples(JNIEnv * env, jclass, jfloatArray buffer, jint sampleOffset, jint sampleCount)
{
jfloat * data = env->GetFloatArrayElements(buffer, nullptr);
int result = 0;
if (auto stream = psemek::android::output_channel->stream())
result = stream->read({data + sampleOffset, sampleCount});
std::fill(data + sampleOffset + result, data + sampleOffset + sampleCount, 0.f);
return sampleCount;
}

View file

@ -0,0 +1,117 @@
#include <jni.h>
#include <android/log.h>
#include <psemek/app/application.hpp>
#include <psemek/gfx/init.hpp>
#include <psemek/log/log.hpp>
namespace
{
using namespace psemek;
android_LogPriority log_priority(log::level level)
{
switch (level)
{
case log::level::debug:
return ANDROID_LOG_DEBUG;
case log::level::info:
return ANDROID_LOG_INFO;
case log::level::warning:
return ANDROID_LOG_WARN;
case log::level::error:
return ANDROID_LOG_ERROR;
default:
return ANDROID_LOG_UNKNOWN;
}
}
struct sink_impl
: log::sink
{
void put_message(log::message const & msg) override
{
__android_log_write(log_priority(msg.level), "psemek", msg.message.data());
}
void flush() override
{}
};
}
extern "C" void Java_psemek_app_PsemekApplication_setupLogging(JNIEnv *, jclass)
{
psemek::log::add_sink(std::make_unique<sink_impl>());
}
extern "C" jlong Java_psemek_app_PsemekApplication_createNativeApp(JNIEnv * env, jclass) try
{
auto factory = psemek::app::make_application_factory();
psemek::gfx::init();
psemek::app::application::context context;
auto app = factory->create(factory->options(), context).release();
return reinterpret_cast<jlong>(app);
}
catch (std::exception const & e)
{
env->ThrowNew(env->FindClass("java/lang/Exception"), e.what());
return 0;
}
catch (...)
{
env->ThrowNew(env->FindClass("java/lang/Exception"), "Unknown exception");
return 0;
}
extern "C" void Java_psemek_app_PsemekApplication_destroyNativeApp(JNIEnv *, jclass, jlong ptr)
{
delete reinterpret_cast<psemek::app::application *>(ptr);
}
extern "C" void Java_psemek_app_PsemekApplication_resizeNative(JNIEnv * env, jclass, jlong ptr, jint width, jint height) try
{
auto app = reinterpret_cast<psemek::app::application *>(ptr);
app->on_event(psemek::app::resize_event{{width, height}});
}
catch (std::exception const & e)
{
env->ThrowNew(env->FindClass("java/lang/Exception"), e.what());
}
catch (...)
{
env->ThrowNew(env->FindClass("java/lang/Exception"), "Unknown exception");
}
extern "C" void Java_psemek_app_PsemekApplication_touchNative(JNIEnv * env, jclass, jlong ptr, jint x, jint y) try
{
auto app = reinterpret_cast<psemek::app::application *>(ptr);
app->on_event(psemek::app::touch_event{{x, y}});
}
catch (std::exception const & e)
{
env->ThrowNew(env->FindClass("java/lang/Exception"), e.what());
}
catch (...)
{
env->ThrowNew(env->FindClass("java/lang/Exception"), "Unknown exception");
}
extern "C" void Java_psemek_app_PsemekApplication_drawFrameNative(JNIEnv * env, jclass, jlong ptr) try
{
auto app = reinterpret_cast<psemek::app::application *>(ptr);
app->update();
app->present();
}
catch (std::exception const & e)
{
env->ThrowNew(env->FindClass("java/lang/Exception"), e.what());
}
catch (...)
{
env->ThrowNew(env->FindClass("java/lang/Exception"), "Unknown exception");
}

View file

@ -0,0 +1,59 @@
#include <psemek/app/resource.hpp>
#include <psemek/log/log.hpp>
#include <psemek/util/to_string.hpp>
#include <android/asset_manager_jni.h>
namespace
{
jobject assetManagerRef;
AAssetManager * assetManager;
struct stream_impl
: psemek::io::istream
{
stream_impl(AAsset * asset)
: asset_(asset)
{}
~stream_impl()
{
AAsset_close(asset_);
}
std::size_t read(char * p, std::size_t size) override
{
int result = AAsset_read(asset_, p, size);
if (result < 0)
throw std::runtime_error("Failed to read from resource");
return result;
}
private:
AAsset * asset_;
};
}
namespace psemek::app
{
std::unique_ptr<io::istream> open_resource(std::filesystem::path const & relative_path)
{
log::error() << "Opening resource " << relative_path;
auto asset = AAssetManager_open(assetManager, relative_path.c_str(), AASSET_MODE_STREAMING);
if (!asset)
throw std::runtime_error(util::to_string("Failed to open resource ", relative_path));
return std::make_unique<stream_impl>(asset);
}
}
extern "C" void Java_psemek_app_PsemekApplication_setAssetManager(JNIEnv * env, jclass, jobject manager)
{
assetManagerRef = env->NewLocalRef(manager);
assetManager = AAssetManager_fromJava(env, manager);
}

View file

@ -1,15 +1,11 @@
set(OpenGL_GL_PREFERENCE LEGACY)
find_package(OpenGL REQUIRED)
find_package(PNG REQUIRED)
find_file(KHR_PLATFORM_FILE KHR/khrplatform.h) find_file(KHR_PLATFORM_FILE KHR/khrplatform.h)
file(GLOB_RECURSE PSEMEK_GFX_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp") file(GLOB_RECURSE PSEMEK_GFX_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp")
file(GLOB_RECURSE PSEMEK_GFX_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp") file(GLOB_RECURSE PSEMEK_GFX_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp")
psemek_add_library(psemek-gfx ${PSEMEK_GFX_HEADERS} ${PSEMEK_GFX_SOURCES}) psemek_add_library(psemek-gfx ${PSEMEK_GFX_HEADERS} ${PSEMEK_GFX_SOURCES} "${CMAKE_CURRENT_SOURCE_DIR}/api/${PSEMEK_GL_API}/source/gl.cpp")
target_include_directories(psemek-gfx PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") target_include_directories(psemek-gfx PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/api/${PSEMEK_GL_API}/include")
target_link_libraries(psemek-gfx PUBLIC psemek-util psemek-geom psemek-cg psemek-random psemek-io psemek-log OpenGL::GL PNG::PNG rapidjson) target_link_libraries(psemek-gfx PUBLIC psemek-util psemek-geom psemek-cg psemek-random psemek-io psemek-log ${PSEMEK_GL_LIBRARIES} PNG::PNG rapidjson)
if(NOT KHR_PLATFORM_FILE) if(NOT KHR_PLATFORM_FILE)
message(STATUS "KHR/khrplatform.h not found, using a substitute header") message(STATUS "KHR/khrplatform.h not found, using a substitute header")
target_include_directories(psemek-gfx PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/extra/khr/include") target_include_directories(psemek-gfx PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/extra/khr/include")

View file

@ -1871,6 +1871,8 @@ namespace gl
bool ext_ARB_shader_image_load_store(); bool ext_ARB_shader_image_load_store();
bool ext_ARB_texture_filter_anisotropic(); bool ext_ARB_texture_filter_anisotropic();
const char * shader_prefix();
} // namespace sys } // namespace sys
} // namespace gl } // namespace gl

View file

@ -1276,6 +1276,13 @@ namespace gl
bool ext_ARB_shader_image_load_store(){ return ext_GL_ARB_shader_image_load_store_loaded; } bool ext_ARB_shader_image_load_store(){ return ext_GL_ARB_shader_image_load_store_loaded; }
bool ext_ARB_texture_filter_anisotropic(){ return ext_GL_ARB_texture_filter_anisotropic_loaded; } bool ext_ARB_texture_filter_anisotropic(){ return ext_GL_ARB_texture_filter_anisotropic_loaded; }
const char * shader_prefix()
{
return R"(#version 330 core
)";
}
} // namespace sys } // namespace sys
} // namespace gl } // namespace gl

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,21 @@
{
"spec_file": "gl.xml",
"api": "gles2",
"version": "3.2",
"profile": "core",
"extensions": [
"ARB_texture_filter_anisotropic",
"ARB_compute_shader",
"ARB_shader_image_load_store"
],
"indent": "\t",
"namespace": "gl",
"loader_namespace": "sys",
"internal_namespace": "internal",
"internal_prefix": "",
"undef": 4,
"strip": true,
"out_header": "gl.hpp",
"out_source": "gl.cpp",
"include": "<psemek/gfx/gl.hpp>"
}

View file

@ -171,6 +171,7 @@ namespace psemek::gfx
static constexpr GLboolean normalized = gl::FALSE; static constexpr GLboolean normalized = gl::FALSE;
}; };
#ifndef PSEMEK_GLES
template <> template <>
struct attrib_traits<double> struct attrib_traits<double>
{ {
@ -181,6 +182,7 @@ namespace psemek::gfx
static constexpr bool integer = false; static constexpr bool integer = false;
static constexpr GLboolean normalized = gl::FALSE; static constexpr GLboolean normalized = gl::FALSE;
}; };
#endif
template <typename T, std::size_t N> template <typename T, std::size_t N>
struct attrib_traits<std::array<T, N>> struct attrib_traits<std::array<T, N>>

View file

@ -160,7 +160,7 @@ namespace psemek::gfx
return std::static_pointer_cast<T[]>(p); return std::static_pointer_cast<T[]>(p);
bind(); bind();
std::shared_ptr<T[]> p(reinterpret_cast<T *>(gl::MapBuffer(Target, gl::WRITE_ONLY)), [this](T *){ std::shared_ptr<T[]> p(reinterpret_cast<T *>(gl::MapBufferRange(Target, 0, size_, gl::WRITE_ONLY)), [this](T *){
bind(); bind();
gl::UnmapBuffer(Target); gl::UnmapBuffer(Target);
}); });

View file

@ -32,27 +32,30 @@ namespace psemek::gfx
void reset(); void reset();
void color(texture_1d const & tex, int attachment = 0);
void color(texture_2d const & tex, int attachment = 0); void color(texture_2d const & tex, int attachment = 0);
void color(texture_2d_multisample const & tex, int attachment = 0);
void color(texture_3d const & tex, int layer, int attachment = 0);
void color(texture_2d_array const & tex, int layer, int attachment = 0); void color(texture_2d_array const & tex, int layer, int attachment = 0);
void color(texture_cubemap const & tex, int attachment = 0); void color(texture_cubemap const & tex, int attachment = 0);
void color(texture_cubemap const & tex, int face, int attachment = 0); void color(texture_cubemap const & tex, int face, int attachment = 0);
void color(renderbuffer const & rb, int attachment = 0); void color(renderbuffer const & rb, int attachment = 0);
void depth(texture_2d const & tex); void depth(texture_2d const & tex);
void depth(texture_2d_multisample const & tex);
void depth(texture_2d_array const & tex, int layer); void depth(texture_2d_array const & tex, int layer);
void depth(texture_cubemap const & tex); void depth(texture_cubemap const & tex);
void depth(texture_cubemap const & tex, int face); void depth(texture_cubemap const & tex, int face);
void depth(renderbuffer const & rb); void depth(renderbuffer const & rb);
void depth_stencil(texture_2d const & tex); void depth_stencil(texture_2d const & tex);
void depth_stencil(texture_2d_multisample const & tex);
void depth_stencil(texture_2d_array const & tex, int layer); void depth_stencil(texture_2d_array const & tex, int layer);
void depth_stencil(texture_cubemap const & tex); void depth_stencil(texture_cubemap const & tex);
void depth_stencil(texture_cubemap const & tex, int face); void depth_stencil(texture_cubemap const & tex, int face);
void depth_stencil(renderbuffer const & rb); void depth_stencil(renderbuffer const & rb);
#ifndef PSEMEK_GLES
void color(texture_1d const & tex, int attachment = 0);
void color(texture_2d_multisample const & tex, int attachment = 0);
void color(texture_3d const & tex, int layer, int attachment = 0);
void depth(texture_2d_multisample const & tex);
void depth_stencil(texture_2d_multisample const & tex);
#endif
GLenum status() const; GLenum status() const;
bool complete() const; bool complete() const;
void assert_complete(std::string_view name = {}) const; void assert_complete(std::string_view name = {}) const;

View file

@ -93,6 +93,7 @@ namespace psemek::gfx
// Normalized 10-bit // Normalized 10-bit
#ifndef PSEMEK_GLES
template <> template <>
struct pixel_traits<geom::vector<uint10, 3>> struct pixel_traits<geom::vector<uint10, 3>>
{ {
@ -153,6 +154,8 @@ namespace psemek::gfx
static constexpr GLenum type = gl::UNSIGNED_SHORT; static constexpr GLenum type = gl::UNSIGNED_SHORT;
}; };
#endif
// Normalized 10-10-10-2 // Normalized 10-10-10-2
template <> template <>
@ -442,7 +445,7 @@ namespace psemek::gfx
{ {
static constexpr GLenum internal_format = gl::DEPTH_COMPONENT24; static constexpr GLenum internal_format = gl::DEPTH_COMPONENT24;
static constexpr GLenum format = gl::DEPTH_COMPONENT; static constexpr GLenum format = gl::DEPTH_COMPONENT;
static constexpr GLenum type = gl::UNSIGNED_BYTE; static constexpr GLenum type = gl::UNSIGNED_INT;
}; };
template <> template <>
@ -450,7 +453,7 @@ namespace psemek::gfx
{ {
static constexpr GLenum internal_format = gl::DEPTH24_STENCIL8; static constexpr GLenum internal_format = gl::DEPTH24_STENCIL8;
static constexpr GLenum format = gl::DEPTH_STENCIL; static constexpr GLenum format = gl::DEPTH_STENCIL;
static constexpr GLenum type = gl::UNSIGNED_BYTE; static constexpr GLenum type = gl::UNSIGNED_INT_24_8;
}; };
std::size_t pixel_size(GLint internal_format); std::size_t pixel_size(GLint internal_format);

View file

@ -15,6 +15,7 @@
namespace psemek::gfx namespace psemek::gfx
{ {
#ifndef PSEMEK_GLES
struct deferred_renderer struct deferred_renderer
{ {
deferred_renderer(); deferred_renderer();
@ -134,5 +135,6 @@ namespace psemek::gfx
private: private:
psemek_declare_pimpl psemek_declare_pimpl
}; };
#endif
} }

View file

@ -59,6 +59,7 @@ namespace psemek::gfx
template <typename Pixel> template <typename Pixel>
void load_srgb(util::array<Pixel, D> const & p); void load_srgb(util::array<Pixel, D> const & p);
#ifndef PSEMEK_GLES
void pixels(GLenum format, GLenum type, void * data, int layer = 0) const; void pixels(GLenum format, GLenum type, void * data, int layer = 0) const;
template <typename Pixmap> template <typename Pixmap>
@ -66,6 +67,7 @@ namespace psemek::gfx
template <typename Pixmap> template <typename Pixmap>
Pixmap pixels(int layer = 0) const; Pixmap pixels(int layer = 0) const;
#endif
static basic_texture from_data(GLint internal_format, geom::vector<std::size_t, D> const & size, GLenum format, GLenum type, const void * data); static basic_texture from_data(GLint internal_format, geom::vector<std::size_t, D> const & size, GLenum format, GLenum type, const void * data);
@ -93,20 +95,23 @@ namespace psemek::gfx
explicit basic_texture(std::nullptr_t); explicit basic_texture(std::nullptr_t);
}; };
using texture_1d = basic_texture<1, gl::TEXTURE_1D>;
using texture_1d_array = basic_texture<2, gl::TEXTURE_1D_ARRAY>;
using texture_2d = basic_texture<2, gl::TEXTURE_2D>; using texture_2d = basic_texture<2, gl::TEXTURE_2D>;
using texture_2d_array = basic_texture<3, gl::TEXTURE_2D_ARRAY>; using texture_2d_array = basic_texture<3, gl::TEXTURE_2D_ARRAY>;
using texture_3d = basic_texture<3, gl::TEXTURE_3D>; using texture_3d = basic_texture<3, gl::TEXTURE_3D>;
extern template struct basic_texture<1, gl::TEXTURE_1D>;
extern template struct basic_texture<2, gl::TEXTURE_1D_ARRAY>;
extern template struct basic_texture<2, gl::TEXTURE_2D>; extern template struct basic_texture<2, gl::TEXTURE_2D>;
extern template struct basic_texture<3, gl::TEXTURE_2D_ARRAY>; extern template struct basic_texture<3, gl::TEXTURE_2D_ARRAY>;
extern template struct basic_texture<3, gl::TEXTURE_3D>; extern template struct basic_texture<3, gl::TEXTURE_3D>;
extern template struct basic_texture<2, gl::TEXTURE_CUBE_MAP>; extern template struct basic_texture<2, gl::TEXTURE_CUBE_MAP>;
#ifndef PSEMEK_GLES
using texture_1d = basic_texture<1, gl::TEXTURE_1D>;
using texture_1d_array = basic_texture<2, gl::TEXTURE_1D_ARRAY>;
extern template struct basic_texture<1, gl::TEXTURE_1D>;
extern template struct basic_texture<2, gl::TEXTURE_1D_ARRAY>;
#endif
struct texture_cubemap struct texture_cubemap
: basic_texture<2, gl::TEXTURE_CUBE_MAP> : basic_texture<2, gl::TEXTURE_CUBE_MAP>
{ {
@ -165,6 +170,7 @@ namespace psemek::gfx
{} {}
}; };
#ifndef PSEMEK_GLES
struct texture_2d_multisample struct texture_2d_multisample
{ {
texture_2d_multisample(); texture_2d_multisample();
@ -207,6 +213,7 @@ namespace psemek::gfx
explicit texture_2d_multisample(std::nullptr_t); explicit texture_2d_multisample(std::nullptr_t);
}; };
#endif
struct buffer_texture struct buffer_texture
{ {
@ -350,7 +357,9 @@ namespace psemek::gfx
if constexpr (D == 1) if constexpr (D == 1)
{ {
#ifndef PSEMEK_GLES
gl::TexImage1D(Target, 0, internal_format, size[0], 0, format, type, data); gl::TexImage1D(Target, 0, internal_format, size[0], 0, format, type, data);
#endif
} }
else if (D == 2) else if (D == 2)
{ {
@ -399,6 +408,7 @@ namespace psemek::gfx
load_srgb(size, p.data()); load_srgb(size, p.data());
} }
#ifndef PSEMEK_GLES
template <std::size_t D, GLenum Target> template <std::size_t D, GLenum Target>
void basic_texture<D, Target>::pixels(GLenum format, GLenum type, void * data, int layer) const void basic_texture<D, Target>::pixels(GLenum format, GLenum type, void * data, int layer) const
{ {
@ -426,6 +436,7 @@ namespace psemek::gfx
pixels(pixmap, layer); pixels(pixmap, layer);
return pixmap; return pixmap;
} }
#endif
template <std::size_t D, GLenum Target> template <std::size_t D, GLenum Target>
basic_texture<D, Target> basic_texture<D, Target>::from_data(GLint internal_format, geom::vector<std::size_t, D> const & size, GLenum format, GLenum type, const void * data) basic_texture<D, Target> basic_texture<D, Target>::from_data(GLint internal_format, geom::vector<std::size_t, D> const & size, GLenum format, GLenum type, const void * data)
@ -524,11 +535,13 @@ namespace psemek::gfx
basic_texture<D, Target>::basic_texture(std::nullptr_t) basic_texture<D, Target>::basic_texture(std::nullptr_t)
{} {}
#ifndef PSEMEK_GLES
template <typename Pixel> template <typename Pixel>
void texture_2d_multisample::load(geom::vector<std::size_t, 2> const & size, int samples, bool fixed_sample_locations) void texture_2d_multisample::load(geom::vector<std::size_t, 2> const & size, int samples, bool fixed_sample_locations)
{ {
load(pixel_traits<Pixel>::internal_format, size, samples, fixed_sample_locations); load(pixel_traits<Pixel>::internal_format, size, samples, fixed_sample_locations);
} }
#endif
inline buffer_texture::buffer_texture() inline buffer_texture::buffer_texture()
{ {
@ -625,10 +638,12 @@ namespace psemek::gfx
{ {
switch (Target) switch (Target)
{ {
#ifndef PSEMEK_GLES
case gl::TEXTURE_1D: case gl::TEXTURE_1D:
case gl::TEXTURE_1D_ARRAY: case gl::TEXTURE_1D_ARRAY:
mipmap_factor = 2.f; mipmap_factor = 2.f;
break; break;
#endif
case gl::TEXTURE_2D: case gl::TEXTURE_2D:
case gl::TEXTURE_2D_ARRAY: case gl::TEXTURE_2D_ARRAY:
mipmap_factor = 4.f / 3.f; mipmap_factor = 4.f / 3.f;

View file

@ -67,11 +67,13 @@ namespace psemek::gfx
id_ = 0; id_ = 0;
} }
#ifndef PSEMEK_GLES
void framebuffer::color(texture_1d const & tex, int attachment) void framebuffer::color(texture_1d const & tex, int attachment)
{ {
bind(); bind();
gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + attachment, tex.target, tex.id(), 0); gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + attachment, tex.target, tex.id(), 0);
} }
#endif
void framebuffer::color(texture_2d const & tex, int attachment) void framebuffer::color(texture_2d const & tex, int attachment)
{ {
@ -79,6 +81,7 @@ namespace psemek::gfx
gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + attachment, tex.target, tex.id(), 0); gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + attachment, tex.target, tex.id(), 0);
} }
#ifndef PSEMEK_GLES
void framebuffer::color(texture_2d_multisample const & tex, int attachment) void framebuffer::color(texture_2d_multisample const & tex, int attachment)
{ {
bind(); bind();
@ -90,6 +93,7 @@ namespace psemek::gfx
bind(); bind();
gl::FramebufferTexture3D(gl::DRAW_FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + attachment, tex.target, tex.id(), 0, layer); gl::FramebufferTexture3D(gl::DRAW_FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + attachment, tex.target, tex.id(), 0, layer);
} }
#endif
void framebuffer::color(texture_2d_array const & tex, int layer, int attachment) void framebuffer::color(texture_2d_array const & tex, int layer, int attachment)
{ {
@ -121,11 +125,13 @@ namespace psemek::gfx
gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::DEPTH_ATTACHMENT, tex.target, tex.id(), 0); gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::DEPTH_ATTACHMENT, tex.target, tex.id(), 0);
} }
#ifndef PSEMEK_GLES
void framebuffer::depth(texture_2d_multisample const & tex) void framebuffer::depth(texture_2d_multisample const & tex)
{ {
bind(); bind();
gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::DEPTH_ATTACHMENT, tex.target, tex.id(), 0); gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::DEPTH_ATTACHMENT, tex.target, tex.id(), 0);
} }
#endif
void framebuffer::depth(texture_2d_array const & tex, int layer) void framebuffer::depth(texture_2d_array const & tex, int layer)
{ {
@ -157,11 +163,13 @@ namespace psemek::gfx
gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::DEPTH_STENCIL_ATTACHMENT, tex.target, tex.id(), 0); gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::DEPTH_STENCIL_ATTACHMENT, tex.target, tex.id(), 0);
} }
#ifndef PSEMEK_GLES
void framebuffer::depth_stencil(texture_2d_multisample const & tex) void framebuffer::depth_stencil(texture_2d_multisample const & tex)
{ {
bind(); bind();
gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::DEPTH_STENCIL_ATTACHMENT, tex.target, tex.id(), 0); gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::DEPTH_STENCIL_ATTACHMENT, tex.target, tex.id(), 0);
} }
#endif
void framebuffer::depth_stencil(texture_2d_array const & tex, int layer) void framebuffer::depth_stencil(texture_2d_array const & tex, int layer)
{ {

View file

@ -7,8 +7,7 @@
#include <psemek/io/memory_stream.hpp> #include <psemek/io/memory_stream.hpp>
static const char vertex_source[] = static const char vertex_source[] =
R"(#version 330 R"(
uniform mat4 u_transform; uniform mat4 u_transform;
layout (location = 0) in vec4 in_position; layout (location = 0) in vec4 in_position;
@ -24,8 +23,7 @@ void main()
)"; )";
static const char fragment_source[] = static const char fragment_source[] =
R"(#version 330 R"(
in vec4 color; in vec4 color;
out vec4 out_color; out vec4 out_color;
@ -37,8 +35,7 @@ void main()
)"; )";
static const char text_vertex_source[] = static const char text_vertex_source[] =
R"(#version 330 R"(
uniform mat4 u_transform; uniform mat4 u_transform;
uniform uvec2 u_texture_size; uniform uvec2 u_texture_size;
@ -58,8 +55,7 @@ void main()
)"; )";
static const char text_fragment_source[] = static const char text_fragment_source[] =
R"(#version 330 R"(
uniform sampler2D u_texture; uniform sampler2D u_texture;
in vec4 color; in vec4 color;
@ -74,8 +70,7 @@ void main()
)"; )";
static const char texture_vertex_source[] = static const char texture_vertex_source[] =
R"(#version 330 R"(
uniform mat4 u_transform; uniform mat4 u_transform;
layout (location = 0) in vec4 in_position; layout (location = 0) in vec4 in_position;
@ -91,8 +86,7 @@ void main()
)"; )";
static const char texture_fragment_source[] = static const char texture_fragment_source[] =
R"(#version 330 R"(
uniform sampler2D u_texture; uniform sampler2D u_texture;
uniform vec4 u_color; uniform vec4 u_color;
@ -111,6 +105,8 @@ void main()
namespace psemek::gfx namespace psemek::gfx
{ {
static std::string shader_prefix = gl::sys::shader_prefix();
struct painter::impl struct painter::impl
{ {
struct vertex struct vertex
@ -132,9 +128,9 @@ namespace psemek::gfx
geom::point<std::uint16_t, 2> texcoord; geom::point<std::uint16_t, 2> texcoord;
}; };
gfx::program program{vertex_source, fragment_source}; gfx::program program{shader_prefix + vertex_source, shader_prefix + fragment_source};
gfx::program text_program{text_vertex_source, text_fragment_source}; gfx::program text_program{shader_prefix + text_vertex_source, shader_prefix + text_fragment_source};
gfx::program texture_program{texture_vertex_source, texture_fragment_source}; gfx::program texture_program{shader_prefix + texture_vertex_source, shader_prefix + texture_fragment_source};
gfx::mesh mesh; gfx::mesh mesh;
gfx::mesh text_mesh; gfx::mesh text_mesh;
gfx::mesh texture_mesh; gfx::mesh texture_mesh;

View file

@ -13,7 +13,9 @@ namespace psemek::gfx
case gl::RGBA32F: return 16; case gl::RGBA32F: return 16;
case gl::RGBA32I: return 16; case gl::RGBA32I: return 16;
case gl::RGBA32UI: return 16; case gl::RGBA32UI: return 16;
#ifndef PSEMEK_GLES
case gl::RGBA16: return 8; case gl::RGBA16: return 8;
#endif
case gl::RGBA16F: return 8; case gl::RGBA16F: return 8;
case gl::RGBA16I: return 8; case gl::RGBA16I: return 8;
case gl::RGBA16UI: return 8; case gl::RGBA16UI: return 8;
@ -26,7 +28,9 @@ namespace psemek::gfx
case gl::RG32F: return 8; case gl::RG32F: return 8;
case gl::RG32I: return 8; case gl::RG32I: return 8;
case gl::RG32UI: return 8; case gl::RG32UI: return 8;
#ifndef PSEMEK_GLES
case gl::RG16: return 4; case gl::RG16: return 4;
#endif
case gl::RG16F: return 4; case gl::RG16F: return 4;
case gl::RGB16I: return 4; case gl::RGB16I: return 4;
case gl::RGB16UI: return 4; case gl::RGB16UI: return 4;
@ -42,23 +46,33 @@ namespace psemek::gfx
case gl::R8: return 1; case gl::R8: return 1;
case gl::R8I: return 1; case gl::R8I: return 1;
case gl::R8UI: return 1; case gl::R8UI: return 1;
#ifndef PSEMEK_GLES
case gl::RGBA16_SNORM: return 8; case gl::RGBA16_SNORM: return 8;
#endif
case gl::RGBA8_SNORM: return 4; case gl::RGBA8_SNORM: return 4;
case gl::RGB32F: return 12; case gl::RGB32F: return 12;
case gl::RGB32I: return 12; case gl::RGB32I: return 12;
case gl::RGB32UI: return 12; case gl::RGB32UI: return 12;
#ifndef PSEMEK_GLES
case gl::RGB16_SNORM: return 6; case gl::RGB16_SNORM: return 6;
#endif
case gl::RGB16F: return 6; case gl::RGB16F: return 6;
#ifndef PSEMEK_GLES
case gl::RGB16: return 6; case gl::RGB16: return 6;
#endif
case gl::RGB8_SNORM: return 3; case gl::RGB8_SNORM: return 3;
case gl::RGB8: return 3; case gl::RGB8: return 3;
case gl::RGB8I: return 3; case gl::RGB8I: return 3;
case gl::RGB8UI: return 3; case gl::RGB8UI: return 3;
case gl::SRGB8: return 3; case gl::SRGB8: return 3;
case gl::RGB9_E5: return 4; case gl::RGB9_E5: return 4;
#ifndef PSEMEK_GLES
case gl::RG16_SNORM: return 4; case gl::RG16_SNORM: return 4;
#endif
case gl::RG8_SNORM: return 2; case gl::RG8_SNORM: return 2;
#ifndef PSEMEK_GLES
case gl::R16_SNORM: return 2; case gl::R16_SNORM: return 2;
#endif
case gl::R8_SNORM: return 1; case gl::R8_SNORM: return 1;
case gl::DEPTH_COMPONENT32F: return 4; case gl::DEPTH_COMPONENT32F: return 4;
case gl::DEPTH_COMPONENT24: return 3; case gl::DEPTH_COMPONENT24: return 3;
@ -66,10 +80,12 @@ namespace psemek::gfx
case gl::DEPTH32F_STENCIL8: return 5; case gl::DEPTH32F_STENCIL8: return 5;
case gl::DEPTH24_STENCIL8: return 4; case gl::DEPTH24_STENCIL8: return 4;
// Assume uncompressed size as an upper bound // Assume uncompressed size as an upper bound
#ifndef PSEMEK_GLES
case gl::COMPRESSED_RG_RGTC2: return 2; case gl::COMPRESSED_RG_RGTC2: return 2;
case gl::COMPRESSED_SIGNED_RG_RGTC2: return 2; case gl::COMPRESSED_SIGNED_RG_RGTC2: return 2;
case gl::COMPRESSED_RED_RGTC1: return 1; case gl::COMPRESSED_RED_RGTC1: return 1;
case gl::COMPRESSED_SIGNED_RED_RGTC1: return 1; case gl::COMPRESSED_SIGNED_RED_RGTC1: return 1;
#endif
}; };
log::warning() << "Unknown pixel format: 0x" << std::hex << internal_format; log::warning() << "Unknown pixel format: 0x" << std::hex << internal_format;

View file

@ -39,11 +39,11 @@ namespace psemek::gfx
{ {
if (!callbacks_[i]) continue; if (!callbacks_[i]) continue;
GLint result; GLuint result;
gl::GetQueryObjectiv(ids_[i], gl::QUERY_RESULT_AVAILABLE, &result); gl::GetQueryObjectuiv(ids_[i], gl::QUERY_RESULT_AVAILABLE, &result);
if (result == gl::TRUE) if (result == gl::TRUE)
{ {
gl::GetQueryObjectiv(ids_[i], gl::QUERY_RESULT, &result); gl::GetQueryObjectuiv(ids_[i], gl::QUERY_RESULT, &result);
callbacks_[i](result); callbacks_[i](result);
callbacks_[i].reset(); callbacks_[i].reset();
} }

View file

@ -1,5 +1,7 @@
#include <psemek/gfx/renderer/deferred.hpp> #include <psemek/gfx/renderer/deferred.hpp>
#ifndef PSEMEK_GLES
#include <psemek/gfx/program.hpp> #include <psemek/gfx/program.hpp>
#include <psemek/gfx/framebuffer.hpp> #include <psemek/gfx/framebuffer.hpp>
#include <psemek/gfx/texture.hpp> #include <psemek/gfx/texture.hpp>
@ -1972,3 +1974,5 @@ void main(){}
} }
} }
#endif

View file

@ -4,8 +4,10 @@
namespace psemek::gfx namespace psemek::gfx
{ {
#ifndef PSEMEK_GLES
template struct basic_texture<1, gl::TEXTURE_1D>; template struct basic_texture<1, gl::TEXTURE_1D>;
template struct basic_texture<2, gl::TEXTURE_1D_ARRAY>; template struct basic_texture<2, gl::TEXTURE_1D_ARRAY>;
#endif
template struct basic_texture<2, gl::TEXTURE_2D>; template struct basic_texture<2, gl::TEXTURE_2D>;
template struct basic_texture<3, gl::TEXTURE_2D_ARRAY>; template struct basic_texture<3, gl::TEXTURE_2D_ARRAY>;
template struct basic_texture<3, gl::TEXTURE_3D>; template struct basic_texture<3, gl::TEXTURE_3D>;
@ -41,17 +43,21 @@ namespace psemek::gfx
size_ = size; size_ = size;
} }
#ifndef PSEMEK_GLES
void texture_cubemap::pixels(int f, GLenum format, GLenum type, void * data) const void texture_cubemap::pixels(int f, GLenum format, GLenum type, void * data) const
{ {
bind(); bind();
gl::GetTexImage(face_to_gl(f), 0, format, type, data); gl::GetTexImage(face_to_gl(f), 0, format, type, data);
} }
#endif
GLenum texture_cubemap::face_to_gl(int f) GLenum texture_cubemap::face_to_gl(int f)
{ {
return gl::TEXTURE_CUBE_MAP_POSITIVE_X + f; return gl::TEXTURE_CUBE_MAP_POSITIVE_X + f;
} }
#ifndef PSEMEK_GLES
texture_2d_multisample::texture_2d_multisample() texture_2d_multisample::texture_2d_multisample()
{ {
gl::GenTextures(1, &id_); gl::GenTextures(1, &id_);
@ -120,4 +126,6 @@ namespace psemek::gfx
texture_2d_multisample::texture_2d_multisample(std::nullptr_t) texture_2d_multisample::texture_2d_multisample(std::nullptr_t)
{} {}
#endif
} }

View file

@ -1,5 +1,3 @@
find_package(Threads REQUIRED)
file(GLOB_RECURSE PSEMEK_LOG_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp") file(GLOB_RECURSE PSEMEK_LOG_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp")
file(GLOB_RECURSE PSEMEK_LOG_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp") file(GLOB_RECURSE PSEMEK_LOG_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp")

View file

@ -1,4 +1,3 @@
find_package(Threads REQUIRED)
find_package(Boost REQUIRED) find_package(Boost REQUIRED)
file(GLOB_RECURSE PSEMEK_UTIL_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp") file(GLOB_RECURSE PSEMEK_UTIL_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp")

View file

@ -5,10 +5,12 @@ set(PSEMEK_PACKAGE_VERSION_SUFFIX "" CACHE STRING "Packaging version suffix")
if(PSEMEK_PACKAGE_MODE) if(PSEMEK_PACKAGE_MODE)
if(WIN32) if(WIN32)
set(PSEMEK_PACKAGE_SUFFIX_RAW win) set(PSEMEK_PACKAGE_SUFFIX_RAW win)
elseif(UNIX AND (NOT APPLE)) elseif(APPLE)
set(PSEMEK_PACKAGE_SUFFIX_RAW linux)
elseif(UNIX AND APPLE)
set(PSEMEK_PACKAGE_SUFFIX_RAW mac) set(PSEMEK_PACKAGE_SUFFIX_RAW mac)
elseif(ANDROID)
set(PSEMEK_PACKAGE_SUFFIX_RAW android)
elseif(UNIX)
set(PSEMEK_PACKAGE_SUFFIX_RAW linux)
else() else()
message(FATAL "Uknown system for packaging") message(FATAL "Uknown system for packaging")
endif() endif()
@ -31,15 +33,23 @@ function(psemek_package_output_path target outvar)
set(${outvar} "${CMAKE_CURRENT_LIST_DIR}/${PSEMEK_PACKAGE_OUTPUT_PATH}/${target}${PSEMEK_PACKAGE_VERSION_SUFFIX}-${PSEMEK_PACKAGE_SUFFIX}.zip" PARENT_SCOPE) set(${outvar} "${CMAKE_CURRENT_LIST_DIR}/${PSEMEK_PACKAGE_OUTPUT_PATH}/${target}${PSEMEK_PACKAGE_VERSION_SUFFIX}-${PSEMEK_PACKAGE_SUFFIX}.zip" PARENT_SCOPE)
endfunction() endfunction()
function(psemek_add_executable_impl target link_backend) function(psemek_add_executable_impl target is_application)
if((NOT PSEMEK_PACKAGE_MODE) OR PSEMEK_PACKAGE_TARGET) if((NOT PSEMEK_PACKAGE_MODE) OR PSEMEK_PACKAGE_TARGET)
add_executable(${target} ${ARGN}) if(${PSEMEK_PACKAGE_AS_LIBRARY} AND ${is_application})
add_library(${target} SHARED ${ARGN})
else()
add_executable(${target} ${ARGN})
endif()
target_link_libraries(${target} PUBLIC psemek) target_link_libraries(${target} PUBLIC psemek)
if(${link_backend}) if(${is_application})
target_link_libraries(${target} PUBLIC psemek-backend) target_link_libraries(${target} PUBLIC
"-Wl,--whole-archive $<TARGET_FILE:${PSEMEK_BACKEND_LIBRARY}> -Wl,--no-whole-archive"
${PSEMEK_BACKEND_LIBRARY})
endif() endif()
install(TARGETS ${target})
if(PSEMEK_PACKAGE_MODE) if(PSEMEK_PACKAGE_MODE)
target_link_options(${target} PUBLIC ${PSEMEK_PACKAGE_LINK_FLAGS}) target_link_options(${target} PUBLIC ${PSEMEK_PACKAGE_LINK_FLAGS})
@ -55,18 +65,20 @@ function(psemek_add_executable_impl target link_backend)
COMMAND ${CMAKE_STRIP} $<TARGET_FILE:${target}> COMMAND ${CMAKE_STRIP} $<TARGET_FILE:${target}>
) )
if(UNIX AND (NOT APPLE)) if(UNIX AND (NOT APPLE) AND (NOT ANDROID))
add_custom_command(TARGET ${target} POST_BUILD add_custom_command(TARGET ${target} POST_BUILD
COMMAND chrpath -r . $<TARGET_FILE:${target}> COMMAND chrpath -r . $<TARGET_FILE:${target}>
) )
endif() endif()
psemek_package_output_path(${target} _OUTPUT_PATH) if(NOT ANDROID)
psemek_package_output_path(${target} _OUTPUT_PATH)
add_custom_command(TARGET ${target} POST_BUILD add_custom_command(TARGET ${target} POST_BUILD
COMMAND echo Packaging target ${target} into ${_OUTPUT_PATH} COMMAND echo Packaging target ${target} into ${_OUTPUT_PATH}
COMMAND zip -v "${_OUTPUT_PATH}" -j $<TARGET_FILE:${target}> ${PSEMEK_PACKAGE_COPY_FILES} COMMAND zip -v "${_OUTPUT_PATH}" -j $<TARGET_FILE:${target}> ${PSEMEK_PACKAGE_COPY_FILES}
) )
endif()
endif() endif()
endif() endif()
endfunction() endfunction()
@ -96,7 +108,7 @@ function(psemek_add_build_tool target link_psemek)
find_file(_LOCATION ${target} PATHS "${PSEMEK_PACKAGE_TOOLS_PATH}/bin") find_file(_LOCATION ${target} PATHS "${PSEMEK_PACKAGE_TOOLS_PATH}/bin")
message(STATUS "Found ${target}: ${_LOCATION}") message(STATUS "Found ${target}: ${_LOCATION}")
if(NOT _LOCATION) if(NOT _LOCATION)
message(FATAL "Could not locate ${target} build tool in ${PSEMEK_PACKAGE_TOOLS_PATH}") message(FATAL_ERROR "Could not locate ${target} build tool in ${PSEMEK_PACKAGE_TOOLS_PATH}")
endif() endif()
add_executable(${target} IMPORTED GLOBAL) add_executable(${target} IMPORTED GLOBAL)
set_target_properties(${target} PROPERTIES IMPORTED_LOCATION ${_LOCATION}) set_target_properties(${target} PROPERTIES IMPORTED_LOCATION ${_LOCATION})
@ -138,12 +150,16 @@ endfunction()
function(psemek_package_files target) function(psemek_package_files target)
if(PSEMEK_PACKAGE_MODE) if(PSEMEK_PACKAGE_MODE)
if(PSEMEK_PACKAGE_TARGET) if(PSEMEK_PACKAGE_TARGET)
psemek_package_output_path(${target} _OUTPUT_PATH) if(ANDROID)
add_custom_command(TARGET ${target} POST_BUILD else()
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} psemek_package_output_path(${target} _OUTPUT_PATH)
COMMAND zip -v "${_OUTPUT_PATH}" -r ${ARGN}
) add_custom_command(TARGET ${target} POST_BUILD
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
COMMAND zip -v "${_OUTPUT_PATH}" -r ${ARGN}
)
endif()
endif() endif()
else() else()
foreach(_FILE ${ARGN}) foreach(_FILE ${ARGN})