• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "include/core/SkBitmap.h"
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkSurface.h"
13 #include "include/core/SkTime.h"
14 #include <jni.h>
15 #include <math.h>
16 #include <string>
17 #include <utility>
18 
19 #include "include/gpu/GrBackendSurface.h"
20 #include "include/gpu/GrContextOptions.h"
21 #include "include/gpu/GrDirectContext.h"
22 #include "include/gpu/gl/GrGLInterface.h"
23 #include "include/gpu/gl/GrGLTypes.h"
24 
25 #include "modules/skottie/include/Skottie.h"
26 #include "modules/sksg/include/SkSGInvalidationController.h"
27 
28 #include <GLES2/gl2.h>
29 #include <GLES2/gl2ext.h>
30 
31 #include <GLES3/gl3.h>
32 
33 #define STENCIL_BUFFER_SIZE 8
34 
35 /*#define ATRACE_NAME(name) ScopedTrace ___tracer(name)
36 
37 // ATRACE_CALL is an ATRACE_NAME that uses the current function name.
38 #define ATRACE_CALL() ATRACE_NAME(__FUNCTION__)
39 namespace {
40     class ScopedTrace {
41     public:
42         inline ScopedTrace(const char *name) {
43             ATrace_beginSection(name);
44         }
45 
46         inline ~ScopedTrace() {
47             ATrace_endSection();
48         }
49     };
50 
51 }*/
52 
53 //disable atrace
54 #define ATRACE_NAME(name)
55 #define ATRACE_CALL()
56 
57 struct SkottieRunner {
58     sk_sp<GrDirectContext> mDContext;
59 };
60 
61 static JavaVM* sJVM = nullptr;
62 
release_global_jni_ref(const void *,void * context)63 static void release_global_jni_ref(const void* /*data*/, void* context) {
64     JNIEnv* env;
65     if (sJVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
66         SK_ABORT("Attempting to release a JNI ref on a thread without a JVM attached.");
67     }
68     jobject obj = reinterpret_cast<jobject>(context);
69     env->DeleteGlobalRef(obj);
70 }
71 
72 extern "C" JNIEXPORT jlong
73 JNICALL
Java_org_skia_skottie_SkottieRunner_nCreateProxy(JNIEnv * env,jclass clazz)74 Java_org_skia_skottie_SkottieRunner_nCreateProxy(JNIEnv *env, jclass clazz) {
75     sk_sp<const GrGLInterface> glInterface = GrGLMakeNativeInterface();
76     if (!glInterface.get()) {
77         return 0;
78     }
79 
80     GrContextOptions options;
81     options.fDisableDistanceFieldPaths = true;
82     sk_sp<GrDirectContext> dContext = GrDirectContext::MakeGL(std::move(glInterface), options);
83     if (!dContext.get()) {
84         return 0;
85     }
86 
87     SkottieRunner* skottie = new SkottieRunner();
88     skottie->mDContext = std::move(dContext);
89 
90     return (jlong) skottie;
91 }
92 
93 extern "C" JNIEXPORT void
94 JNICALL
Java_org_skia_skottie_SkottieRunner_nDeleteProxy(JNIEnv * env,jclass clazz,jlong nativeProxy)95 Java_org_skia_skottie_SkottieRunner_nDeleteProxy(JNIEnv *env, jclass clazz, jlong nativeProxy) {
96     if (!nativeProxy) {
97         return;
98     }
99     SkottieRunner* skottie = reinterpret_cast<SkottieRunner*>(nativeProxy);
100     if (skottie->mDContext) {
101         skottie->mDContext->releaseResourcesAndAbandonContext();
102         skottie->mDContext.reset();
103     }
104     delete skottie;
105 }
106 
107 struct SkottieAnimation {
108     SkottieRunner *mRunner;
109     std::unique_ptr<SkStream> mStream;
110     sk_sp<skottie::Animation> mAnimation;
111     long                      mTimeBase;
112     float                     mDuration; //in milliseconds
113 };
114 
115 extern "C" JNIEXPORT jlong
116 JNICALL
Java_org_skia_skottie_SkottieAnimation_nCreateProxy(JNIEnv * env,jobject clazz,jlong runner,jobject bufferObj)117 Java_org_skia_skottie_SkottieAnimation_nCreateProxy(JNIEnv *env,
118                                                     jobject clazz,
119                                                     jlong runner,
120                                                     jobject bufferObj) {
121 
122     if (!runner) {
123         return 0;
124     }
125     SkottieRunner *skottieRunner = reinterpret_cast<SkottieRunner*>(runner);
126 
127     const void* buffer = env->GetDirectBufferAddress(bufferObj);
128     jlong bufferSize = env->GetDirectBufferCapacity(bufferObj);
129     if (buffer == nullptr || bufferSize <= 0) {
130         return 0;
131     }
132 
133     env->GetJavaVM(&sJVM);
134     jobject bufferRef = env->NewGlobalRef(bufferObj);
135     if (bufferRef == nullptr) {
136         return 0;
137     }
138 
139     sk_sp<SkData> data(SkData::MakeWithProc(buffer, bufferSize, release_global_jni_ref,
140                                             reinterpret_cast<void*>(bufferRef)));
141     std::unique_ptr<SkStream> stream = SkMemoryStream::Make(data);
142     if (!stream.get()) {
143         // Cannot create a stream
144         return 0;
145     }
146 
147     SkottieAnimation* skottieAnimation = new SkottieAnimation();
148     skottieAnimation->mRunner = skottieRunner;
149     skottieAnimation->mStream = std::move(stream);
150 
151     skottieAnimation->mAnimation = skottie::Animation::Make(skottieAnimation->mStream.get());
152     skottieAnimation->mTimeBase  = 0.0f; // force a time reset
153     skottieAnimation->mDuration = 1000 * skottieAnimation->mAnimation->duration();
154 
155     if (!skottieAnimation->mAnimation) {
156         //failed to load Bodymovin animation
157         delete skottieAnimation;
158         return 0;
159     }
160 
161     return (jlong) skottieAnimation;
162 }
163 
164 extern "C" JNIEXPORT void
165 JNICALL
Java_org_skia_skottie_SkottieAnimation_nDeleteProxy(JNIEnv * env,jclass clazz,jlong nativeProxy)166 Java_org_skia_skottie_SkottieAnimation_nDeleteProxy(JNIEnv *env, jclass clazz,
167                                                     jlong nativeProxy) {
168     if (!nativeProxy) {
169         return;
170     }
171     SkottieAnimation* skottieAnimation = reinterpret_cast<SkottieAnimation*>(nativeProxy);
172     delete skottieAnimation;
173 }
174 
175 extern "C" JNIEXPORT bool
176 JNICALL
Java_org_skia_skottie_SkottieAnimation_nDrawFrame(JNIEnv * env,jclass clazz,jlong nativeProxy,jint width,jint height,jboolean wideColorGamut,jfloat progress,jint backgroundColor,jboolean forceDraw)177 Java_org_skia_skottie_SkottieAnimation_nDrawFrame(JNIEnv *env, jclass clazz,
178                                                   jlong nativeProxy, jint width,
179                                                   jint height,
180                                                   jboolean wideColorGamut,
181                                                   jfloat progress,
182                                                   jint backgroundColor,
183                                                   jboolean forceDraw) {
184     ATRACE_NAME("SkottieDrawFrame");
185     if (!nativeProxy) {
186         return false;
187     }
188     SkottieAnimation* skottieAnimation = reinterpret_cast<SkottieAnimation*>(nativeProxy);
189 
190     auto dContext = skottieAnimation->mRunner->mDContext.get();
191 
192     if (!dContext) {
193         return false;
194     }
195 
196     sksg::InvalidationController ic;
197 
198     if (skottieAnimation->mAnimation) {
199         skottieAnimation->mAnimation->seek(progress, &ic);
200         if (!forceDraw && ic.bounds().isEmpty()) {
201             return false;
202         }
203     }
204 
205     SkColorType colorType;
206     // setup surface for fbo0
207     GrGLFramebufferInfo fboInfo;
208     fboInfo.fFBOID = 0;
209     if (wideColorGamut) {
210         fboInfo.fFormat = GL_RGBA16F;
211         colorType = kRGBA_F16_SkColorType;
212     } else {
213         fboInfo.fFormat = GL_RGBA8;
214         colorType = kN32_SkColorType;
215     }
216     GrBackendRenderTarget backendRT(width, height, 0, STENCIL_BUFFER_SIZE, fboInfo);
217 
218     SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
219 
220     sk_sp<SkSurface> renderTarget(SkSurface::MakeFromBackendRenderTarget(
221             dContext, backendRT, kBottomLeft_GrSurfaceOrigin, colorType,
222             nullptr, &props));
223 
224     auto canvas = renderTarget->getCanvas();
225     canvas->clear(backgroundColor);
226 
227     SkAutoCanvasRestore acr(canvas, true);
228     SkRect bounds = SkRect::MakeWH(width, height);
229     skottieAnimation->mAnimation->render(canvas, &bounds);
230 
231     canvas->flush();
232     return true;
233 }
234 
235 extern "C" JNIEXPORT jlong
236 JNICALL
Java_org_skia_skottie_SkottieAnimation_nGetDuration(JNIEnv * env,jclass clazz,jlong nativeProxy)237 Java_org_skia_skottie_SkottieAnimation_nGetDuration(JNIEnv *env,
238                                                     jclass clazz,
239                                                     jlong nativeProxy) {
240     if (!nativeProxy) {
241         return 0;
242     }
243     SkottieAnimation* skottieAnimation = reinterpret_cast<SkottieAnimation*>(nativeProxy);
244     return (jlong) skottieAnimation->mDuration;
245 }
246