Revert "Tests: updated viewer"
authorTaehyub Kim <taehyub.kim@samsung.com>
Fri, 11 Nov 2022 07:20:12 +0000 (16:20 +0900)
committerTaehyub Kim <taehyub.kim@samsung.com>
Fri, 11 Nov 2022 07:20:12 +0000 (16:20 +0900)
This reverts commit 2a94a255decc348213dd2dab701c43df238a10ea.

viewer/buggy.riv [deleted file]
viewer/meson.build
viewer/viewer_cpu.cpp
viewer/viewer_gpu.cpp [new file with mode: 0644]

diff --git a/viewer/buggy.riv b/viewer/buggy.riv
deleted file mode 100644 (file)
index 3a4227b..0000000
Binary files a/viewer/buggy.riv and /dev/null differ
index 7e958e235c4e38306232bb0adb8e43a7cbaeb4a5..2057702539d81e06834822bb7b6697c4742bdae0 100644 (file)
@@ -1,15 +1,60 @@
 project('rive-tizen-viewer',
         'cpp',
         default_options : ['cpp_std=c++17'],
-        version : '0.2.1',
+        version : '0.2.0',
         license : 'MIT')
 
 cc = meson.get_compiler('cpp')
-rive_tizen_dep = [dependency('rive_tizen', required: true)]
 
-message('Building CPU Viewer')
-elementary_dep = dependency('elementary', required : true)
-viewer_dep = [elementary_dep, rive_tizen_dep]
+headers = [include_directories('../inc'), include_directories('../src')]
+rive_headers = [include_directories('../submodule/rive-cpp/include')]
 
-executable('viewer_cpu', 'viewer_cpu.cpp',
-    dependencies : viewer_dep)
\ No newline at end of file
+skia_inc = include_directories('../submodule/skia')
+skia_inc_core = include_directories('../submodule/skia/include/core')
+skia_inc_effects = include_directories('../submodule/skia/include/effects')
+skia_inc_dirs = [skia_inc, skia_inc_core, skia_inc_effects]
+
+skia_inc_gpu = include_directories('../submodule/skia/include/gpu')
+
+dir_base = meson.current_source_dir()
+skia_dir = join_paths(dir_base, '../submodule/skia/out/static')
+rivetizen_dir = join_paths(dir_base, '../build/src')
+
+skia_lib = cc.find_library('libskia', dirs : skia_dir, static: false, header_include_directories: skia_inc_dirs)
+rive_tizen_lib = cc.find_library('librive-tizen', dirs: rivetizen_dir, static: true)
+
+skia_dep = declare_dependency(
+       include_directories: [skia_inc, skia_inc_core, skia_inc_effects],
+       dependencies: skia_lib,
+)
+
+rive_tizen_dep = declare_dependency(
+    include_directories: headers,
+    dependencies: rive_tizen_lib
+)
+
+if get_option('use_gl') == true
+    message('Building GPU Viewer')
+
+    glfw3_dep = dependency('glfw3', required : true)
+    threads_dep = dependency('threads', required: true)
+    glx_dep = dependency('glx', required: true)
+
+    viewer_dep = [glfw3_dep, threads_dep, glx_dep, skia_dep]
+
+    viewer_headers = [headers, skia_inc_gpu]
+
+    executable('viewer_gpu', 'viewer_gpu.cpp',
+        include_directories : viewer_headers,
+        link_with : rive_tizen_lib,
+        dependencies : viewer_dep)
+else
+    message('Building CPU Viewer')
+
+    elementary_dep = dependency('elementary', required : true)
+    viewer_dep = [elementary_dep, skia_dep, rive_tizen_dep]
+
+    executable('viewer_cpu', 'viewer_cpu.cpp',
+        include_directories : [headers, rive_headers],
+        dependencies : viewer_dep)
+endif
index f224e472962ece6c70b00b8561683640e5777802..bc650a8d5e51eee8ecfa0a82f25a0ff9337fb375 100644 (file)
@@ -3,17 +3,52 @@
 #include <Elementary.h>
 #include <time.h>
 
-#include <rive_tizen.hpp>
+#include "SkCanvas.h"
+#include "SkColorSpace.h"
+#include "SkSurface.h"
+#include "SkTypes.h"
+
+#include "rive/animation/linear_animation_instance.hpp"
+#include "rive/animation/state_machine_instance.hpp"
+#include "rive/animation/state_machine_input_instance.hpp"
+#include "rive/animation/state_machine_number.hpp"
+#include "rive/animation/state_machine_bool.hpp"
+#include "rive/animation/state_machine_trigger.hpp"
+#include "rive/artboard.hpp"
+#include "rive/file.hpp"
+#include "rive/layout.hpp"
+#include "rive/math/aabb.hpp"
+#include "skia_factory.hpp"
+#include "skia_renderer.hpp"
 
 #define WIDTH 1280
 #define HEIGHT 720
 
 Evas_Object *view = nullptr;
+
 void* pixels;
+sk_sp<SkSurface> surface;
+SkCanvas* canvas = nullptr;
+
+std::vector<uint8_t> fileBytes;
+int animationIndex = 0;
+int stateMachineIndex = -1;
+
+rive::SkiaFactory skiaFactory;
 
-RiveTizen *mRiveTizenAdapter;
-rive::Artboard *mArtboard;
-std::vector<rive::LinearAnimationInstance*> mAnimations;
+std::unique_ptr<rive::File> currentFile;
+std::unique_ptr<rive::ArtboardInstance> artboardInstance;
+std::unique_ptr<rive::Scene> currentScene;
+
+std::vector<std::string> animationNames;
+std::vector<std::string> stateMachineNames;
+
+static Ecore_Animator *anim;
+
+static Eina_Bool _do_animation(void *data, double pos)
+{
+    return ECORE_CALLBACK_RENEW;
+}
 
 static void createCanvas(unsigned int width, unsigned int height) {
     static constexpr auto BPP = 4;
@@ -21,34 +56,74 @@ static void createCanvas(unsigned int width, unsigned int height) {
     if (pixels) free(pixels);
     pixels = (void*) malloc (width * height * BPP);
 
-    mRiveTizenAdapter->createCanvas((unsigned char *)pixels, width, height, width);
+    static constexpr SkAlphaType at = kPremul_SkAlphaType;
+    const SkImageInfo info = SkImageInfo::MakeN32(width, height, at);
+
+    surface = SkSurface::MakeRasterDirect(info, pixels, width * BPP);
+    if (!surface) {
+        fprintf(stderr, "Failed to create Skia surface\n");
+    }
+
+    canvas = surface->getCanvas();
+}
+
+static void loadNames(const rive::Artboard* ab) {
+    animationNames.clear();
+    stateMachineNames.clear();
+    if (ab) {
+        for (size_t i = 0; i < ab->animationCount(); ++i) {
+            animationNames.push_back(ab->animationNameAt(i));
+        }
+        for (size_t i = 0; i < ab->stateMachineCount(); ++i) {
+            stateMachineNames.push_back(ab->stateMachineNameAt(i));
+        }
+    }
+}
+
+static void initAnimation(int index) {
+    animationIndex = index;
+    stateMachineIndex = -1;
+    assert(fileBytes.size() != 0);
+    auto file = rive::File::import(rive::toSpan(fileBytes), &skiaFactory);
+    if (!file) {
+        fileBytes.clear();
+        fprintf(stderr, "failed to import file\n");
+        return;
+    }
+    currentScene = nullptr;
+    artboardInstance = nullptr;
+
+    currentFile = std::move(file);
+    artboardInstance = currentFile->artboardDefault();
+    artboardInstance->advance(0.0f);
+    loadNames(artboardInstance.get());
+
+    if (index >= 0 && index < artboardInstance->animationCount()) {
+        currentScene = artboardInstance->animationAt(index);
+        currentScene->inputCount();
+    }
+
+    evas_object_image_pixels_dirty_set(view, EINA_TRUE);
+    evas_render(view);
 }
 
 static void loadRivFile(const char* filename) {
     FILE* fp = fopen(filename, "rb");
     if (!fp) {
-        fprintf(stderr, "[%s:%d][%s]:ERROR file %s opening failure\n", __FILE__, __LINE__, __func__, filename);
+        fprintf(stderr, "file %s opening failure.\n", filename);
         return;
     }
     fseek(fp, 0, SEEK_END);
     size_t size = ftell(fp);
     fseek(fp, 0, SEEK_SET);
-
-    std::vector<uint8_t> bytes;
-    bytes.resize(size);
-    if (fread(bytes.data(), 1, size, fp) != size) {
-        bytes.clear();
-        fprintf(stderr, "[%s:%d][%s]:ERROR failed to read all of %s\n", __FILE__, __LINE__, __func__, filename);
+    fileBytes.resize(size);
+    if (fread(fileBytes.data(), 1, size, fp) != size) {
+        fileBytes.clear();
+        fprintf(stderr, "failed to read all of %s\n", filename);
         return;
     }
-
-    mRiveTizenAdapter->loadRiveResource(&bytes[0], bytes.size());
-
-    mArtboard = mRiveTizenAdapter->getArtboard();
-
-    for (unsigned int i = 0; i < mArtboard->animationCount(); i++) {
-        mAnimations.emplace_back(mRiveTizenAdapter->createLinearAnimationInstance(i));
-    }
+    printf("Loaded %s file succesfully.\n", filename);
+    initAnimation(0);
 }
 
 static float getElapsedTime() {
@@ -58,34 +133,42 @@ static float getElapsedTime() {
     float elapsed = (float)(t - staticClock)/CLOCKS_PER_SEC;
     staticClock = t;
     return elapsed;
-}
+} 
 
 void initSwView() {
-    printf("[%s:%d][%s]\n", __FILE__, __LINE__, __func__);
-    loadRivFile("buggy.riv");
+    printf("[mszczeci][%s:%d][%s]\n",__FILE__, __LINE__, __func__);
+    SkPaint paint;
+    paint.setColor(SK_ColorGRAY);
+    canvas->drawPaint(paint);
+
+    loadRivFile("file.riv");
 }
 
 void drawSwView(void* data, Eo* obj) {
-    const float elapsed = getElapsedTime();
-    int i = 0;
-    for(auto& animation : mAnimations) {
-        //const std::string& name      = animation->name();
-        if (i == 1 || i == 3) {
-            mRiveTizenAdapter->animationAdvanceApply(animation, elapsed);
-        }
-        ++i;
-    }
+    if (currentScene) {
+        const float elapsed = getElapsedTime();
+        bool ret = currentScene->advanceAndApply(elapsed);
 
-    clock_t begin = clock();
+        clock_t t = clock();
 
-    if (!mRiveTizenAdapter->render(elapsed, WIDTH, HEIGHT)) {
-        printf("[%s:%d][%s] ERROR\n", __FILE__, __LINE__, __func__);
-        return;
-    }
+        rive::SkiaRenderer renderer(canvas);
+        renderer.save();
+
+        const unsigned int width = WIDTH, height = HEIGHT;
 
-    clock_t end = clock();
-    double time_spent = (double)(end - begin) / CLOCKS_PER_SEC * 1e3;
-    printf("Rendering time %0.3f ms\n", time_spent);
+        auto viewTransform = rive::computeAlignment(rive::Fit::contain,
+                                                    rive::Alignment::center,
+                                                    rive::AABB(0, 0, width, height),
+                                                    currentScene->bounds());
+        renderer.transform(viewTransform);
+
+        currentScene->draw(&renderer);
+        renderer.restore();
+
+        t = clock() - t;
+        double time_taken = ((double)t)/CLOCKS_PER_SEC;
+        printf("Frame rendering time %f sec\n", time_taken);
+    }
 }
 
 void transitSwCallback(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) {
@@ -95,8 +178,7 @@ void transitSwCallback(Elm_Transit_Effect *effect, Elm_Transit* transit, double
 }
 
 void win_del(void *data, Evas_Object *o, void *ev) {
-    delete mRiveTizenAdapter;
-    elm_exit();
+   elm_exit();
 }
 
 int main(int argc, char **argv) {
@@ -127,12 +209,10 @@ int main(int argc, char **argv) {
     elm_transit_auto_reverse_set(transit, EINA_TRUE);
     elm_transit_go(transit);
 
-    mRiveTizenAdapter = new RiveTizen();
-
     initSwView();
 
     elm_run();
     elm_shutdown();
 
     return 0;
-}
+}
\ No newline at end of file
diff --git a/viewer/viewer_gpu.cpp b/viewer/viewer_gpu.cpp
new file mode 100644 (file)
index 0000000..f78e62f
--- /dev/null
@@ -0,0 +1,260 @@
+#include <cstdio>
+#include <cmath>
+
+#define SK_GL
+#include <GLFW/glfw3.h>
+
+#include "GrBackendSurface.h"
+#include "GrDirectContext.h"
+#include "SkCanvas.h"
+#include "SkColorSpace.h"
+#include "SkSurface.h"
+#include "SkTypes.h"
+#include "gl/GrGLInterface.h"
+
+#include "rive/animation/linear_animation_instance.hpp"
+#include "rive/animation/state_machine_instance.hpp"
+#include "rive/animation/state_machine_input_instance.hpp"
+#include "rive/animation/state_machine_number.hpp"
+#include "rive/animation/state_machine_bool.hpp"
+#include "rive/animation/state_machine_trigger.hpp"
+#include "rive/artboard.hpp"
+#include "rive/file.hpp"
+#include "rive/layout.hpp"
+#include "rive/math/aabb.hpp"
+#include "skia_factory.hpp"
+#include "skia_renderer.hpp"
+
+#define WIDTH 1280
+#define HEIGHT 720
+
+rive::SkiaFactory skiaFactory;
+
+std::string filename;
+std::unique_ptr<rive::File> currentFile;
+std::unique_ptr<rive::ArtboardInstance> artboardInstance;
+std::unique_ptr<rive::Scene> currentScene;
+
+std::vector<std::string> animationNames;
+std::vector<std::string> stateMachineNames;
+
+#include <time.h>
+double GetSecondsToday() {
+    time_t m_time;
+    time(&m_time);
+    struct tm tstruct;
+    gmtime_r(&m_time, &tstruct);
+
+    int hours = tstruct.tm_hour - 4;
+    if (hours < 0) {
+        hours += 12;
+    } else if (hours >= 12) {
+        hours -= 12;
+    }
+
+    auto secs = (double)hours * 60 * 60 +
+                (double)tstruct.tm_min * 60 +
+                (double)tstruct.tm_sec;
+//    printf("%d %d %d\n", tstruct.tm_sec, tstruct.tm_min, hours);
+//    printf("%g %g %g\n", secs, secs/60, secs/60/60);
+    return secs;
+}
+
+std::vector<uint8_t> fileBytes;
+
+int animationIndex = 0;
+int stateMachineIndex = -1;
+
+static void loadNames(const rive::Artboard* ab) {
+    animationNames.clear();
+    stateMachineNames.clear();
+    if (ab) {
+        for (size_t i = 0; i < ab->animationCount(); ++i) {
+            animationNames.push_back(ab->animationNameAt(i));
+        }
+        for (size_t i = 0; i < ab->stateMachineCount(); ++i) {
+            stateMachineNames.push_back(ab->stateMachineNameAt(i));
+        }
+    }
+}
+
+static void initAnimation(int index) {
+    animationIndex = index;
+    stateMachineIndex = -1;
+    assert(fileBytes.size() != 0);
+    auto file = rive::File::import(rive::toSpan(fileBytes), &skiaFactory);
+    if (!file) {
+        fileBytes.clear();
+        fprintf(stderr, "failed to import file\n");
+        return;
+    }
+    currentScene = nullptr;
+    artboardInstance = nullptr;
+
+    currentFile = std::move(file);
+    artboardInstance = currentFile->artboardDefault();
+    artboardInstance->advance(0.0f);
+    loadNames(artboardInstance.get());
+
+    if (index >= 0 && index < artboardInstance->animationCount()) {
+        currentScene = artboardInstance->animationAt(index);
+        currentScene->inputCount();
+    }
+}
+
+
+rive::Mat2D gInverseViewTransform;
+rive::Vec2D lastWorldMouse;
+static void glfwCursorPosCallback(GLFWwindow* window, double x, double y) {
+    float xscale, yscale;
+    glfwGetWindowContentScale(window, &xscale, &yscale);
+    lastWorldMouse = gInverseViewTransform * rive::Vec2D(x * xscale, y * yscale);
+    if (currentScene) {
+        currentScene->pointerMove(lastWorldMouse);
+    }
+}
+static void glfwMouseButtonCallback(GLFWwindow* window, int button, int action, int mods) {
+    if (currentScene) {
+        switch (action) {
+            case GLFW_PRESS:
+                currentScene->pointerDown(lastWorldMouse);
+                break;
+            case GLFW_RELEASE:
+                currentScene->pointerUp(lastWorldMouse);
+                break;
+        }
+    }
+}
+
+static void glfwErrorCallback(int error, const char* description) {
+    puts(description);
+}
+
+static void glfwDropCallback(GLFWwindow* window, int count, const char** paths) {
+    filename = paths[0];
+    FILE* fp = fopen(filename.c_str(), "rb");
+    fseek(fp, 0, SEEK_END);
+    size_t size = ftell(fp);
+    fseek(fp, 0, SEEK_SET);
+    fileBytes.resize(size);
+    if (fread(fileBytes.data(), 1, size, fp) != size) {
+        fileBytes.clear();
+        fprintf(stderr, "failed to read all of %s\n", filename.c_str());
+        return;
+    }
+    printf("Loaded %s file succesfully.\n", filename.c_str());
+    initAnimation(0);
+}
+
+int main() {
+    if (!glfwInit()) {
+        fprintf(stderr, "Failed to initialize glfw.\n");
+        return 1;
+    }
+    glfwSetErrorCallback(glfwErrorCallback);
+
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
+    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Rive-skia GPU Viewer", NULL, NULL);
+    if (window == nullptr) {
+        fprintf(stderr, "Failed to make window or GL.\n");
+        glfwTerminate();
+        return 1;
+    }
+
+    glfwSetDropCallback(window, glfwDropCallback);
+    glfwSetCursorPosCallback(window, glfwCursorPosCallback);
+    glfwSetMouseButtonCallback(window, glfwMouseButtonCallback);
+    glfwMakeContextCurrent(window);
+
+    // Enable VSYNC.
+    glfwSwapInterval(1);
+
+    // Setup Skia
+    GrContextOptions options;
+    sk_sp<GrDirectContext> context = GrDirectContext::MakeGL(nullptr, options);
+    GrGLFramebufferInfo framebufferInfo;
+    framebufferInfo.fFBOID = 0;
+    framebufferInfo.fFormat = GL_RGBA8;
+
+    sk_sp<SkSurface> surface;
+    SkCanvas* canvas = nullptr;
+    
+    int width = 0, height = 0;
+    int lastScreenWidth = 0, lastScreenHeight = 0;
+
+    double lastTime = glfwGetTime();
+
+    static constexpr SkAlphaType at = kPremul_SkAlphaType;
+    const SkImageInfo info = SkImageInfo::MakeN32(WIDTH, HEIGHT, at);
+
+    printf("Viewer loaded. Drag and drop .riv file to load.\n");
+
+    while (!glfwWindowShouldClose(window)) {
+        glfwGetFramebufferSize(window, &width, &height);
+
+        if (!surface || width != lastScreenWidth || height != lastScreenHeight) {
+            lastScreenWidth = width;
+            lastScreenHeight = height;
+
+            SkColorType colorType = kRGBA_8888_SkColorType;
+
+            GrBackendRenderTarget backendRenderTarget(width,
+                                                      height,
+                                                      0, // sample count
+                                                      0, // stencil bits
+                                                      framebufferInfo);
+
+            surface = SkSurface::MakeFromBackendRenderTarget(context.get(),
+                                                             backendRenderTarget,
+                                                             kBottomLeft_GrSurfaceOrigin,
+                                                             colorType,
+                                                             nullptr,
+                                                             nullptr);
+
+            if (!surface) {
+                fprintf(stderr, "Failed to create Skia surface\n");
+                return 1;
+            }
+
+            canvas = surface->getCanvas();
+        }
+
+        double time = glfwGetTime();
+        float elapsed = (float)(time - lastTime);
+        lastTime = time;
+
+        SkPaint paint;
+        paint.setColor(SK_ColorGRAY);
+        canvas->drawPaint(paint);
+
+        if (currentScene) {
+            if (auto num = currentScene->getNumber("isTime")) {
+                num->value(GetSecondsToday()/60/60);
+            }
+
+            currentScene->advanceAndApply(elapsed);
+
+            rive::SkiaRenderer renderer(canvas);
+            renderer.save();
+
+            auto viewTransform = rive::computeAlignment(rive::Fit::contain,
+                                                        rive::Alignment::center,
+                                                        rive::AABB(0, 0, width, height),
+                                                        currentScene->bounds());
+            renderer.transform(viewTransform);
+            gInverseViewTransform = viewTransform.invertOrIdentity();
+
+            currentScene->draw(&renderer);
+            renderer.restore();
+        }
+        context->flush();
+
+        glfwSwapBuffers(window);
+        glfwPollEvents();
+    }
+
+    glfwDestroyWindow(window);
+    glfwTerminate();
+    exit(EXIT_SUCCESS);
+}
\ No newline at end of file