add webgl support

This commit is contained in:
2019-10-05 21:08:40 +02:00
parent a1c0dcb007
commit f2a73a905d
19 changed files with 370 additions and 11 deletions

3
.gitignore vendored
View File

@@ -50,3 +50,6 @@ linux/CMakeFiles/
linux/cmake_install.cmake
linux/CMakeCache.txt
linux/Makefile
webgl/build
webgl/.vscode

View File

@@ -23,7 +23,6 @@
</border>
<border width="100%" height="100" color="0 0 0 .9" pad="10" dir="row" grow="1">
<scroll id="files-list" dir="row" wrap="1" flood-events="1" grow="1" height="100%" margin="0 0 0 0" pad="0 20 0 0" color=".2 .2 .2 1">
<ref id="dialog-brush-download-item"/>
</scroll>
</border>
<node id="footer" height="50" dir="row" align="flex-end" justify="flex-end" pad="10">

View File

@@ -250,6 +250,7 @@ void App::initLog()
LOG("load preferences failed");
}
#if WITH_CURL
int progress_callback_download(void *clientp, curl_off_t dltotal,
curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
@@ -265,9 +266,11 @@ int progress_callback_upload(void *clientp, curl_off_t dltotal,
progress((float)ulnow / (float)ultotal);
return 0;
}
#endif //CURL
void App::download(std::string url, std::string dest_filepath, std::function<void(float)> progress)
{
#if WITH_CURL
CURL *curl = curl_easy_init();
if (curl)
{
@@ -289,12 +292,14 @@ void App::download(std::string url, std::string dest_filepath, std::function<voi
curl_easy_cleanup(curl);
fclose(fp);
}
#endif //CURL
}
bool App::check_license()
{
return true; // TODO: for distribuiton only
#if WITH_CURL
CURL *curl = curl_easy_init();
if (curl)
{
@@ -321,11 +326,13 @@ bool App::check_license()
if (err == CURLcode::CURLE_OK && ret == "success")
return true;
}
#endif //CURL
return false;
}
void App::upload(std::string filename, std::string name, std::function<void(float)> progress)
{
#if WITH_CURL
CURL *curl;
struct curl_httppost *formpost = NULL;
@@ -362,6 +369,7 @@ void App::upload(std::string filename, std::string name, std::function<void(floa
std::cout << "\n\nUPLOAD RESULT\n" << res << "\n\n\n";
curl_easy_cleanup(curl);
}
#endif //CURL
}
#ifdef _WIN32
@@ -413,6 +421,7 @@ void App::init()
LOG("GL version: %s", glGetString(GL_VERSION));
LOG("GL vendor: %s", glGetString(GL_VENDOR));
LOG("GL renderer: %s", glGetString(GL_RENDERER));
LOG("GLSL version: %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
//GLint n_exts;
//glGetIntegerv(GL_NUM_EXTENSIONS, &n_exts);
@@ -465,7 +474,7 @@ void App::async_start()
#elif _WIN32
async_lock();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#elif __LINUX__
#elif __LINUX__ || __WEB__
glfwMakeContextCurrent(glfw_window);
#endif
}
@@ -499,7 +508,7 @@ void App::async_swap()
android_async_swap();
#elif _WIN32
win32_async_swap();
#elif __LINUX__
#elif __LINUX__ || __WEB__
glfwSwapBuffers(glfw_window);
#endif
}
@@ -833,6 +842,37 @@ void App::rec_loop()
}
}
void App::render_thread_tick()
{
static uint32_t count = 0;
render_thread_id = std::this_thread::get_id();
render_running = true;
std::deque<AppTask> working_list;
// move the task list locally to free the queue for other threads
{
std::unique_lock<std::mutex> lock(render_task_mutex);
if (render_tasklist.empty())
return;
working_list = std::move(render_tasklist);
}
// execute the tasks
if (!working_list.empty())
{
async_start();
while (!working_list.empty())
{
//LOG("render task %d", count);
//LOG("task %s", working_list.front().name.c_str());
count++;
working_list.front()();
working_list.pop_front();
}
async_end();
}
}
void App::render_thread_main()
{
BT_SetTerminate();
@@ -868,6 +908,45 @@ void App::render_thread_main()
}
}
void App::ui_thread_tick()
{
ui_thread_id = std::this_thread::get_id();
ui_running = true;
std::deque<AppTask> working_list;
// move the task list locally to free the queue for other threads
{
std::unique_lock<std::mutex> lock(ui_task_mutex);
working_list = std::move(ui_tasklist);
}
// execute the tasks
if (!working_list.empty())
{
while (!working_list.empty())
{
//LOG("ui task %d", count);
working_list.front()();
working_list.pop_front();
}
}
tick(0);
if (redraw)
{
update(0);
render_task([this]
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
clear();
draw(0);
async_swap();
});
}
}
void App::ui_thread_main()
{
BT_SetTerminate();

View File

@@ -155,7 +155,7 @@ public:
#elif defined(__OSX__) && defined(__OBJC__)
View* osx_view;
AppOSX* osx_app;
#elif __LINUX__
#elif __LINUX__ || __WEB__
GLFWwindow* glfw_window;
#endif
@@ -294,6 +294,7 @@ public:
static std::thread render_thread;
static std::thread::id render_thread_id;
static bool render_running;
void render_thread_tick();
void render_thread_main();
void render_thread_start();
void render_thread_stop();
@@ -365,6 +366,7 @@ public:
static std::thread ui_thread;
static std::thread::id ui_thread_id;
static bool ui_running;
void ui_thread_tick();
void ui_thread_main();
void ui_thread_start();
void ui_thread_stop();

View File

@@ -193,7 +193,7 @@ void App::pick_file(std::vector<std::string> types, std::function<void (std::str
std::string path = win32_open_file(filter.c_str());
if (!path.empty())
callback(path);
#else
#elif __LINUX__
if (auto p = tinyfd_openFileDialog("Open File", "", 0, nullptr, nullptr, false))
callback(p);
#endif

View File

@@ -17,7 +17,7 @@ void App::initShaders()
std::string ext = (const char*)glGetStringi(GL_EXTENSIONS, i);
if (ext.find("shader_framebuffer_fetch") != std::string::npos)
ShaderManager::ext_framebuffer_fetch = true;
#if __GLES__
#if __GLES__ && !__WEB__
if (ext.find("texture_float") != std::string::npos)
ShaderManager::ext_float32 = true;
if (ext.find("texture_float_linear") != std::string::npos)

View File

@@ -145,6 +145,8 @@ bool Asset::create_dir(const std::string& path)
return android_create_dir(path);
#elif __IOS__ || __OSX__
return apple_create_dir(path);
else
return false;
#endif
}
@@ -155,6 +157,7 @@ static size_t curl_data_handler_asset(void* contents, size_t size, size_t nmemb,
return size * nmemb;
}
#if WITH_CURL
static int progress_callback_asset_download(void* clientp, curl_off_t dltotal,
curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
@@ -168,9 +171,11 @@ static int progress_callback_asset_download(void* clientp, curl_off_t dltotal,
bool cont = ass->on_progress(p);
return cont ? 0 : 1;
}
#endif //CURL
bool Asset::open_url(const std::string& url, std::function<bool(float)> progress /*= nullptr*/)
{
#if WITH_CURL
CURL* curl = curl_easy_init();
if (curl)
{
@@ -204,6 +209,7 @@ bool Asset::open_url(const std::string& url, std::function<bool(float)> progress
return true;
}
}
#endif // CURL
return false;
}

View File

@@ -1577,7 +1577,7 @@ bool Canvas::create(int width, int height)
m_tex[i].create(width, height, GL_RGBA8);
m_tex2[i].create(width, height, GL_RGBA8);
}
#if defined(__IOS__) || defined(__ANDROID__)
#if defined(__GLES__)
m_sampler_brush.create();
#else
m_sampler_brush.create(GL_LINEAR, GL_CLAMP_TO_BORDER);

View File

@@ -9,7 +9,11 @@
#include "canvas_modes.h"
#include <stack>
#if __WEB__
#define CANVAS_RES 512
#else
#define CANVAS_RES 1536
#endif
struct PPIThumb
{

View File

@@ -6,6 +6,7 @@ LogRemote LogRemote::I;
void LogRemote::start()
{
#if WITH_CURL
if (m_running || m_error)
return; // already running
@@ -27,6 +28,7 @@ void LogRemote::start()
net_close();
LOG("NET thread loop exit");
});
#endif //CURL
}
void LogRemote::stop()
@@ -39,6 +41,7 @@ void LogRemote::stop()
void LogRemote::net_init()
{
#if WITH_CURL
if (!(curl = curl_easy_init()))
return;
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &this->readBuffer);
@@ -48,10 +51,12 @@ void LogRemote::net_init()
#ifdef __ANDROID__
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
#endif
#endif //CURL
}
std::string LogRemote::net_request(std::string cmd, std::string data /*= ""*/)
{
readBuffer.clear();
#if WITH_CURL
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
auto url = m_url + cmd;
@@ -63,13 +68,16 @@ std::string LogRemote::net_request(std::string cmd, std::string data /*= ""*/)
m_running = false;
m_error = true;
}
#endif //CURL
return readBuffer;
}
void LogRemote::net_close()
{
#if WITH_CURL
if (curl)
curl_easy_cleanup(curl);
curl = nullptr;
#endif //CURL
m_running = false;
}
void LogRemote::file_init()

View File

@@ -23,8 +23,10 @@ public:
BlockingQueue<std::string> m_mq;
// Store messages until the file is open
std::vector<std::string> m_tmp;
#if WITH_CURL
CURL *curl = nullptr;
CURLcode res;
#endif
std::string readBuffer;
std::string m_url = "http://omigamedev.ddns.net:8083";
int m_session;

View File

@@ -1322,7 +1322,7 @@ void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
void Node::load_internal(const tinyxml2::XMLElement* x_node)
{
m_name = x_node->Name();
//LOG("node %s", m_name.c_str());
//LOG("load_internal node %s", m_name.c_str());
init();

View File

@@ -48,6 +48,7 @@ void NodeDialogCloud::removed(Node* parent)
void NodeDialogCloud::load_thumbs_thread()
{
#if WITH_CURL
BT_SetTerminate();
CURL *curl = curl_easy_init();
std::string res;
@@ -144,6 +145,7 @@ void NodeDialogCloud::load_thumbs_thread()
}
curl_easy_cleanup(curl);
}
#endif //CURL
}
//////////////////////////////////////////////////////////////////

View File

@@ -147,7 +147,7 @@ void NodePanelGrid::init_controls()
if (texres == m_texture.size().x)
return;
#if defined(__IOS__) || defined(__ANDROID__)
#if defined(__GLES__)
m_texture.create(texres, texres);
m_texture.create_mipmaps();
#else

View File

@@ -177,8 +177,12 @@ void NodePanelQuick::init_controls()
NodeButtonCustom* NodePanelQuick::init_button_brush(const std::string& name, bool szp, bool flp)
{
LOG("init_button_brush %s", name.c_str());
auto button = find<NodeButtonCustom>(name.c_str());
if (!button)
LOG("couldn't find button %s", name.c_str());
button->on_click = std::bind(&this_class::handle_button_brush_click, this, std::placeholders::_1);
LOG("button has %d children", button->m_children.size());
auto pr = static_cast<NodeStrokePreview*>(button->m_children[0].get());
pr->m_brush = std::make_shared<Brush>();
pr->m_brush->m_tip_size_pressure = szp;

View File

@@ -103,6 +103,24 @@
#define __block
#define BT_SetTerminate void
#elif defined(EMSCRIPTEN)
#define GLFW_INCLUDE_ES3
#include <GLFW/glfw3.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#define __WEB__ 1
#define SHADER_VERSION "#version 300 es\n"
#define PP_OS "web"
#define __GLES__ 1
#define __WEBGL__ 1
#define __block
#define BT_SetTerminate void
//#define GL_RGBA8 GL_RGBA
#endif
#define SIXPLETTE(I) {I, I, I, I, I, I}
@@ -155,5 +173,8 @@
#include <stb/stb_truetype.h>
#include <stb/stb_image.h>
#include <stb/stb_image_write.h>
#include <curl/curl.h>
#include <sqlite3.h>
#ifndef EMSCRIPTEN
#include <curl/curl.h>
#endif

View File

@@ -299,7 +299,7 @@ void Sampler::set_border(glm::vec4 rgba)
{
App::I->render_task([this, rgba]
{
#if USE_SAMPLER && !defined(__IOS__) && !defined(__ANDROID__)
#if USE_SAMPLER && !defined(__GLES__)
glSamplerParameterfv(id, GL_TEXTURE_BORDER_COLOR, glm::value_ptr(rgba));
#endif // USE_SAMPLER
});

136
webgl/CMakeLists.txt Normal file
View File

@@ -0,0 +1,136 @@
cmake_minimum_required(VERSION 3.4.1)
project(panopainter)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \
-std=c++14 -O2 \
-s USE_GLFW=3 \
-s USE_WEBGL2=1 \
-s FULL_ES3=1 \
-s USE_PTHREADS=1 \
-s ASSERTIONS=2 \
-s TOTAL_MEMORY=64Mb \
-s ALLOW_MEMORY_GROWTH=1 \
-s WASM_MEM_MAX=512MB \
")
add_executable(panopainter
src/main.cpp
../libs/yoga/yoga/log.cpp
../libs/yoga/yoga/Utils.cpp
../libs/yoga/yoga/YGConfig.cpp
../libs/yoga/yoga/YGEnums.cpp
../libs/yoga/yoga/YGLayout.cpp
../libs/yoga/yoga/YGMarker.cpp
../libs/yoga/yoga/YGNode.cpp
../libs/yoga/yoga/YGNodePrint.cpp
../libs/yoga/yoga/YGStyle.cpp
../libs/yoga/yoga/YGValue.cpp
../libs/yoga/yoga/Yoga.cpp
../libs/tinyxml2/tinyxml2.cpp
../libs/jpeg/jpgd.cpp
../libs/jpeg/jpge.cpp
../libs/poly2tri/poly2tri/common/shapes.cc
../libs/poly2tri/poly2tri/sweep/advancing_front.cc
../libs/poly2tri/poly2tri/sweep/cdt.cc
../libs/poly2tri/poly2tri/sweep/sweep_context.cc
../libs/poly2tri/poly2tri/sweep/sweep.cc
../libs/fmt/src/format.cc
../src/pch.cpp
../src/util.cpp
../src/rtt.cpp
../src/bezier.cpp
../src/asset.cpp
../src/image.cpp
../src/texture.cpp
../src/font.cpp
../src/shader.cpp
../src/shape.cpp
../src/app.cpp
../src/app_cloud.cpp
../src/app_dialogs.cpp
../src/app_events.cpp
../src/app_layout.cpp
../src/app_shaders.cpp
../src/app_vr.cpp
../src/brush.cpp
../src/canvas.cpp
../src/canvas_layer.cpp
../src/canvas_actions.cpp
../src/canvas_modes.cpp
../src/log.cpp
../src/action.cpp
../src/layout.cpp
../src/version.cpp
../src/node.cpp
../src/node_about.cpp
../src/node_border.cpp
../src/node_button.cpp
../src/node_button_custom.cpp
../src/node_canvas.cpp
../src/node_checkbox.cpp
../src/node_color_quad.cpp
../src/node_colorwheel.cpp
../src/node_combobox.cpp
../src/node_changelog.cpp
../src/node_dialog_browse.cpp
../src/node_dialog_cloud.cpp
../src/node_dialog_open.cpp
../src/node_dialog_picker.cpp
../src/node_dialog_layer_rename.cpp
../src/node_dialog_resize.cpp
../src/node_icon.cpp
../src/node_image.cpp
../src/node_image_texture.cpp
../src/node_message_box.cpp
../src/node_panel_brush.cpp
../src/node_panel_color.cpp
../src/node_panel_grid.cpp
../src/node_panel_floating.cpp
../src/node_panel_layer.cpp
../src/node_panel_stroke.cpp
../src/node_panel_quick.cpp
../src/node_popup_menu.cpp
../src/node_progress_bar.cpp
../src/node_settings.cpp
../src/node_slider.cpp
../src/node_stroke_preview.cpp
../src/node_text.cpp
../src/node_text_input.cpp
../src/node_tool_bucket.cpp
../src/node_usermanual.cpp
../src/node_viewport.cpp
../src/node_scroll.cpp
../src/abr.cpp
../src/binary_stream.cpp
../src/serializer.cpp
../src/settings.cpp
../src/node_input_box.cpp
../src/node_dialog_export_ppbr.cpp
)
set_target_properties(panopainter PROPERTIES SUFFIX ".html")
set_target_properties(panopainter PROPERTIES LINK_FLAGS "\
--embed-file data \
-s USE_GLFW=3 \
-s USE_WEBGL2=1 \
-s FULL_ES3=1 \
-s USE_PTHREADS=1 \
-s ASSERTIONS=2 \
-s TOTAL_MEMORY=64Mb \
-s ALLOW_MEMORY_GROWTH=1 \
-s WASM_MEM_MAX=512MB \
")
target_include_directories(panopainter PRIVATE
src
../src
../libs/glm
../libs/tinyxml2
../libs/yoga
../libs/stb
../libs/jpeg
../libs/poly2tri/poly2tri
../libs/base64
../libs/sqlite3
../libs/nanort
../libs/hash-library
../libs/fmt/include
../libs/glad/include
../libs/tinyfiledialogs
)

93
webgl/src/main.cpp Normal file
View File

@@ -0,0 +1,93 @@
#include <pch.h>
#include <stdio.h>
#include <emscripten.h>
#include <thread>
#include <chrono>
#include <app.h>
#include <fstream>
App app;
GLFWwindow* wnd;
float theta = 0;
glm::vec2 g_cursor_pos;
void main_loop()
{
app.render_thread_tick();
app.ui_thread_tick();
// theta += 0.1f;
// float r = sinf(theta);
// glClearColor(r, 0.9f, 0.9f, 1.0f);
// glClear(GL_COLOR_BUFFER_BIT);
// app.tick(0);
// app.update(0);
// app.draw(0);
// SDL_GL_SwapWindow(wnd);
}
int main()
{
if (glfwInit() != GL_TRUE)
printf("Failed to init GLFW");
wnd = glfwCreateWindow(800, 600, "hello", nullptr, nullptr);
glfwMakeContextCurrent(wnd);
glfwSetCursorPosCallback(wnd, [](GLFWwindow* wnd, double x, double y){
g_cursor_pos = glm::vec2(x, y);
app.ui_task_async([=]{
app.mouse_move(x, y, 1.f, kEventSource::Mouse, false);
});
});
glfwSetMouseButtonCallback(wnd, [](GLFWwindow* wnd, int button, int action, int mods){
app.ui_task_async([=]{
if (action == GLFW_PRESS)
app.mouse_down(button, g_cursor_pos.x, g_cursor_pos.y, 1.f, kEventSource::Mouse, false);
else if (action == GLFW_RELEASE)
app.mouse_up(button, g_cursor_pos.x, g_cursor_pos.y, kEventSource::Mouse, false);
});
});
glfwSetWindowSizeCallback(wnd, [](GLFWwindow* wnd, int width, int height){
app.ui_task_async([=]{
app.resize(width, height);
});
});
glfwSetWindowCloseCallback(wnd, [](GLFWwindow* wnd){
app.ui_task([] {
if (!app.request_close())
glfwSetWindowShouldClose(app.glfw_window, GLFW_FALSE);
});
});
glfwSetWindowRefreshCallback(wnd, [](GLFWwindow* wnd){
app.ui_task_async([=]{
app.redraw = true;
}, true);
});
printf("GL version: %s\n", glGetString(GL_VERSION));
printf("GL vendor: %s\n", glGetString(GL_VENDOR));
printf("GL renderer: %s\n", glGetString(GL_RENDERER));
printf("GLSL version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
App::I = &app;
app.initLog();
app.create();
app.width = 800;
app.height = 600;
app.glfw_window = wnd;
// app.render_thread_tick();
// app.ui_thread_tick();
app.ui_task_async([]{
app.init();
});
LOG("start threads");
//app.render_thread_start();
// app.ui_thread_start();
emscripten_set_main_loop(main_loop, 0, true);
printf("hello world 003\n");
return 0;
}