1/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "org_skia_canvasproof_GaneshPictureRenderer.h"
9
10#include "GrContext.h"
11#include "JavaInputStream.h"
12#include "SkCanvas.h"
13#include "SkMatrix.h"
14#include "SkPicture.h"
15#include "SkRect.h"
16#include "SkStream.h"
17#include "SkSurface.h"
18
19#define TAG "GaneshPictureRenderer.cpp: "
20
21static void render_picture(GrContext* grContext,
22                           int width,
23                           int height,
24                           const SkPicture* picture,
25                           const SkMatrix& matrix) {
26    SkASSERT(grContext);
27    if (!picture) {
28        SkDebugf(TAG "!picture\n");
29        return;
30    }
31    // Render to the default framebuffer render target.
32    GrBackendRenderTargetDesc desc;
33    desc.fWidth = width;
34    desc.fHeight = height;
35    desc.fConfig = kSkia8888_GrPixelConfig;
36    desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
37    SkSurfaceProps surfaceProps(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
38                                kUnknown_SkPixelGeometry);
39    // TODO:  Check to see if we can keep the surface between draw calls.
40    SkAutoTUnref<SkSurface> surface(
41            SkSurface::NewFromBackendRenderTarget(
42                    grContext, desc, &surfaceProps));
43    if (surface) {
44        SkCanvas* canvas = surface->getCanvas();
45        SkASSERT(canvas);
46        canvas->clear(SK_ColorGRAY);
47        canvas->concat(matrix);
48        SkRect cullRect = picture->cullRect();
49        canvas->clipRect(cullRect);
50        picture->playback(canvas);
51        canvas->flush();
52    }
53}
54
55namespace {
56struct GaneshPictureRendererImpl {
57    SkAutoTUnref<GrContext> fGrContext;
58    void render(int w, int h, const SkPicture* p, const SkMatrix& m) {
59        if (!fGrContext) {
60            // Cache the rendering context between frames.
61            fGrContext.reset(GrContext::Create(kOpenGL_GrBackend, 0));
62            if (!fGrContext) {
63                SkDebugf(TAG "GrContext::Create - failed\n");
64                return;
65            }
66        }
67        render_picture(fGrContext, w, h, p, m);
68    }
69};
70}  // namespace
71
72/*
73 * Class:     org_skia_canvasproof_GaneshPictureRenderer
74 * Method:    DrawThisFrame
75 * Signature: (IIFJ)V
76 */
77JNIEXPORT void JNICALL Java_org_skia_canvasproof_GaneshPictureRenderer_DrawThisFrame(
78        JNIEnv*, jclass, jint width, jint height, jfloat scale, jlong ptr, jlong pic) {
79    if (!ptr) { return; }
80    SkMatrix matrix = SkMatrix::MakeScale((SkScalar)scale);
81    GaneshPictureRendererImpl* impl =
82        reinterpret_cast<GaneshPictureRendererImpl*>(ptr);
83    SkPicture* picture = reinterpret_cast<SkPicture*>(pic);
84    impl->render((int)width, (int)height, picture, matrix);
85}
86
87/*
88 * Class:     org_skia_canvasproof_GaneshPictureRenderer
89 * Method:    Ctor
90 * Signature: ()J
91 */
92JNIEXPORT jlong JNICALL Java_org_skia_canvasproof_GaneshPictureRenderer_Ctor
93  (JNIEnv *, jclass) {
94    return reinterpret_cast<jlong>(new GaneshPictureRendererImpl);
95}
96
97/*
98 * Class:     org_skia_canvasproof_GaneshPictureRenderer
99 * Method:    CleanUp
100 * Signature: (J)V
101 */
102JNIEXPORT void JNICALL Java_org_skia_canvasproof_GaneshPictureRenderer_CleanUp
103  (JNIEnv *, jclass, jlong ptr) {
104    delete reinterpret_cast<GaneshPictureRendererImpl*>(ptr);
105}
106
107namespace {
108struct AndroidRectHelper {
109    jfieldID fLeft, fTop, fRight, fBottom;
110    AndroidRectHelper()
111        : fLeft(nullptr), fTop(nullptr), fRight(nullptr), fBottom(nullptr) {}
112    void config(JNIEnv *env) {
113        if (!fLeft) {
114            jclass rectClass = env->FindClass("android/graphics/Rect");
115            SkASSERT(rectClass);
116            fLeft = env->GetFieldID(rectClass, "left", "I");
117            fTop = env->GetFieldID(rectClass, "top", "I");
118            fRight = env->GetFieldID(rectClass, "right", "I");
119            fBottom = env->GetFieldID(rectClass, "bottom", "I");
120        }
121    }
122};
123} // namespace
124
125/*
126 * Class:     org_skia_canvasproof_GaneshPictureRenderer
127 * Method:    GetCullRect
128 * Signature: (Landroid/graphics/Rect;J)V
129 */
130JNIEXPORT void JNICALL Java_org_skia_canvasproof_GaneshPictureRenderer_GetCullRect
131  (JNIEnv *env, jclass, jobject androidGraphicsRect, jlong picturePtr) {
132    SkASSERT(androidGraphicsRect);
133    const SkPicture* picture = reinterpret_cast<SkPicture*>(picturePtr);
134    SkRect rect = SkRect::MakeEmpty();
135    if (picture) {
136        rect = picture->cullRect();
137    }
138    SkIRect iRect;
139    rect.roundOut(&iRect);
140    static AndroidRectHelper help;
141    help.config(env);
142    env->SetIntField(androidGraphicsRect, help.fLeft, (jint)(iRect.left()));
143    env->SetIntField(androidGraphicsRect, help.fTop, (jint)(iRect.top()));
144    env->SetIntField(androidGraphicsRect, help.fRight, (jint)(iRect.right()));
145    env->SetIntField(androidGraphicsRect, help.fBottom, (jint)(iRect.bottom()));
146}
147