Home | History | Annotate | Download | only in cpp
      1 
      2 /*
      3  * Copyright 2018 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include <jni.h>
     10 #include <math.h>
     11 #include <string>
     12 #include <utility>
     13 #include <SkColor.h>
     14 #include <SkCanvas.h>
     15 #include <SkBitmap.h>
     16 #include <SkSurface.h>
     17 #include <SkTime.h>
     18 
     19 #include <GrContextOptions.h>
     20 #include <GrContext.h>
     21 #include <gl/GrGLInterface.h>
     22 #include <GrBackendSurface.h>
     23 #include <gl/GrGLTypes.h>
     24 
     25 #include <Skottie.h>
     26 
     27 #include <GLES2/gl2.h>
     28 #include <GLES2/gl2ext.h>
     29 
     30 #include <GLES3/gl3.h>
     31 #include <android/trace.h>
     32 #include "JavaInputStreamAdaptor.h"
     33 
     34 #define STENCIL_BUFFER_SIZE 8
     35 
     36 /*#define ATRACE_NAME(name) ScopedTrace ___tracer(name)
     37 
     38 // ATRACE_CALL is an ATRACE_NAME that uses the current function name.
     39 #define ATRACE_CALL() ATRACE_NAME(__FUNCTION__)
     40 namespace {
     41     class ScopedTrace {
     42     public:
     43         inline ScopedTrace(const char *name) {
     44             ATrace_beginSection(name);
     45         }
     46 
     47         inline ~ScopedTrace() {
     48             ATrace_endSection();
     49         }
     50     };
     51 
     52 }*/
     53 
     54 //disable atrace
     55 #define ATRACE_NAME(name)
     56 #define ATRACE_CALL()
     57 
     58 struct SkottieRunner {
     59     sk_sp<GrContext> mGrContext;
     60 };
     61 
     62 extern "C" JNIEXPORT jlong
     63 JNICALL
     64 Java_org_skia_skottie_SkottieRunner_nCreateProxy(JNIEnv *env, jclass clazz) {
     65     sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
     66     if (!glInterface.get()) {
     67         return 0;
     68     }
     69 
     70     GrContextOptions options;
     71     options.fDisableDistanceFieldPaths = true;
     72     options.fDisableCoverageCountingPaths = true;
     73     sk_sp<GrContext> grContext = GrContext::MakeGL(std::move(glInterface), options);
     74     if (!grContext.get()) {
     75         return 0;
     76     }
     77 
     78     SkottieRunner* skottie = new SkottieRunner();
     79     skottie->mGrContext = grContext;
     80 
     81     return (jlong) skottie;
     82 }
     83 
     84 extern "C" JNIEXPORT void
     85 JNICALL
     86 Java_org_skia_skottie_SkottieRunner_nDeleteProxy(JNIEnv *env, jclass clazz, jlong nativeProxy) {
     87     if (!nativeProxy) {
     88         return;
     89     }
     90     SkottieRunner* skottie = reinterpret_cast<SkottieRunner*>(nativeProxy);
     91     if (skottie->mGrContext) {
     92         skottie->mGrContext->releaseResourcesAndAbandonContext();
     93         skottie->mGrContext.reset();
     94     }
     95     delete skottie;
     96 }
     97 
     98 struct SkottieAnimation {
     99     SkottieRunner *mRunner;
    100     std::unique_ptr<SkStream> mStream;
    101     sk_sp<skottie::Animation> mAnimation;
    102     long                      mTimeBase;
    103     float                     mDuration; //in milliseconds
    104 };
    105 
    106 extern "C" JNIEXPORT jlong
    107 JNICALL
    108 Java_org_skia_skottie_SkottieRunner_00024SkottieAnimationImpl_nCreateProxy(JNIEnv *env, jobject clazz,
    109                                                                        jlong runner, jobject is,
    110                                                                        jbyteArray storage) {
    111 
    112     if (!runner) {
    113         return 0;
    114     }
    115     SkottieRunner *skottieRunner = reinterpret_cast<SkottieRunner*>(runner);
    116     std::unique_ptr<SkStream> stream(CopyJavaInputStream(env, is, storage));
    117     if (!stream.get()) {
    118         // Cannot create a stream
    119         return 0;
    120     }
    121 
    122     SkottieAnimation* skottieAnimation = new SkottieAnimation();
    123     skottieAnimation->mRunner = skottieRunner;
    124     skottieAnimation->mStream = std::move(stream);
    125 
    126     skottieAnimation->mAnimation = skottie::Animation::Make(skottieAnimation->mStream.get());
    127     skottieAnimation->mTimeBase  = 0.0f; // force a time reset
    128     skottieAnimation->mDuration = 1000 * skottieAnimation->mAnimation->duration();
    129 
    130     if (!skottieAnimation->mAnimation) {
    131         //failed to load Bodymovin animation
    132         delete skottieAnimation;
    133         return 0;
    134     }
    135 
    136     return (jlong) skottieAnimation;
    137 }
    138 
    139 extern "C" JNIEXPORT void
    140 JNICALL
    141 Java_org_skia_skottie_SkottieRunner_00024SkottieAnimationImpl_nDeleteProxy(JNIEnv *env, jclass clazz,
    142                                                                        jlong nativeProxy) {
    143     if (!nativeProxy) {
    144         return;
    145     }
    146     SkottieAnimation* skottieAnimation = reinterpret_cast<SkottieAnimation*>(nativeProxy);
    147     delete skottieAnimation;
    148 }
    149 
    150 extern "C" JNIEXPORT void
    151 JNICALL
    152 Java_org_skia_skottie_SkottieRunner_00024SkottieAnimationImpl_nDrawFrame(JNIEnv *env, jclass clazz,
    153                                                                      jlong nativeProxy, jint width,
    154                                                                      jint height,
    155                                                                      jboolean wideColorGamut,
    156                                                                      jfloat progress) {
    157     ATRACE_NAME("SkottieDrawFrame");
    158     if (!nativeProxy) {
    159         return;
    160     }
    161     SkottieAnimation* skottieAnimation = reinterpret_cast<SkottieAnimation*>(nativeProxy);
    162 
    163     auto grContext = skottieAnimation->mRunner->mGrContext;
    164 
    165     if (!grContext) {
    166         return;
    167     }
    168 
    169     SkColorType colorType;
    170     // setup surface for fbo0
    171     GrGLFramebufferInfo fboInfo;
    172     fboInfo.fFBOID = 0;
    173     if (wideColorGamut) {
    174         fboInfo.fFormat = GL_RGBA16F;
    175         colorType = kRGBA_F16_SkColorType;
    176     } else {
    177         fboInfo.fFormat = GL_RGBA8;
    178         colorType = kN32_SkColorType;
    179     }
    180     GrBackendRenderTarget backendRT(width, height, 0, STENCIL_BUFFER_SIZE, fboInfo);
    181 
    182     SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
    183 
    184     sk_sp<SkSurface> renderTarget(SkSurface::MakeFromBackendRenderTarget(
    185             grContext.get(), backendRT, kBottomLeft_GrSurfaceOrigin, colorType,
    186             nullptr, &props));
    187 
    188     auto canvas = renderTarget->getCanvas();
    189     canvas->clear(SK_ColorTRANSPARENT);
    190     if (skottieAnimation->mAnimation) {
    191         skottieAnimation->mAnimation->seek(progress);
    192 
    193         SkAutoCanvasRestore acr(canvas, true);
    194         SkRect bounds = SkRect::MakeWH(width, height);
    195         skottieAnimation->mAnimation->render(canvas, &bounds);
    196     }
    197 
    198     canvas->flush();
    199 }
    200 
    201 extern "C" JNIEXPORT jlong
    202 JNICALL
    203 Java_org_skia_skottie_SkottieRunner_00024SkottieAnimationImpl_nGetDuration(JNIEnv *env,
    204                                                                            jclass clazz,
    205                                                                            jlong nativeProxy) {
    206     if (!nativeProxy) {
    207         return 0;
    208     }
    209     SkottieAnimation* skottieAnimation = reinterpret_cast<SkottieAnimation*>(nativeProxy);
    210     return (jlong) skottieAnimation->mDuration;
    211 }
    212