Home | History | Annotate | Download | only in jni
      1 
      2 /*
      3  * Copyright 2011 Skia
      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 #include "com_skia_SkiaSampleRenderer.h"
      9 
     10 #include "SampleApp.h"
     11 #include "SkApplication.h"
     12 #include "SkCanvas.h"
     13 #include "SkDevice.h"
     14 #include "SkEvent.h"
     15 #include "SkWindow.h"
     16 
     17 #include <jni.h>
     18 #include "android/AndroidKeyToSkKey.h"
     19 
     20 
     21 ///////////////////////////////////////////
     22 ///////////////// Globals /////////////////
     23 ///////////////////////////////////////////
     24 
     25 struct ActivityGlue {
     26     JNIEnv* m_env;
     27     jweak m_obj;
     28     jmethodID m_setTitle;
     29     jmethodID m_setSlideList;
     30     jmethodID m_addToDownloads;
     31     ActivityGlue() {
     32         m_env = NULL;
     33         m_obj = NULL;
     34         m_setTitle = NULL;
     35         m_setSlideList = NULL;
     36         m_addToDownloads = NULL;
     37     }
     38 } gActivityGlue;
     39 
     40 struct WindowGlue {
     41     jweak m_obj;
     42     jmethodID m_inval;
     43     jmethodID m_queueSkEvent;
     44     jmethodID m_startTimer;
     45     jmethodID m_getMSAASampleCount;
     46     WindowGlue() {
     47         m_obj = NULL;
     48         m_inval = NULL;
     49         m_queueSkEvent = NULL;
     50         m_startTimer = NULL;
     51         m_getMSAASampleCount = NULL;
     52     }
     53 } gWindowGlue;
     54 
     55 SampleWindow* gWindow;
     56 
     57 ///////////////////////////////////////////
     58 ///////////// SkOSWindow impl /////////////
     59 ///////////////////////////////////////////
     60 
     61 bool SkOSWindow::attach(SkBackEndTypes /* attachType */, int /*msaaSampleCount*/, AttachmentInfo* info)
     62 {
     63     JNIEnv* env = gActivityGlue.m_env;
     64     if (!env || !gWindowGlue.m_getMSAASampleCount || !gWindowGlue.m_obj) {
     65         return false;
     66     }
     67     if (env->IsSameObject(gWindowGlue.m_obj, NULL)) {
     68         SkDebugf("ERROR: The JNI WeakRef to the Window is invalid");
     69         return false;
     70     }
     71     info->fSampleCount = env->CallIntMethod(gWindowGlue.m_obj, gWindowGlue.m_getMSAASampleCount);
     72 
     73     // This is the value requested in SkiaSampleView.java.
     74     info->fStencilBits = 8;
     75     return true;
     76 }
     77 
     78 void SkOSWindow::onSetTitle(const char title[])
     79 {
     80     JNIEnv* env = gActivityGlue.m_env;
     81     if (!env) {
     82         return;
     83     }
     84     if (env->IsSameObject(gActivityGlue.m_obj, NULL)) {
     85         SkDebugf("ERROR: The JNI WeakRef to the Activity is invalid");
     86         return;
     87     }
     88 
     89     jstring string = env->NewStringUTF(title);
     90     env->CallVoidMethod(gActivityGlue.m_obj, gActivityGlue.m_setTitle, string);
     91     env->DeleteLocalRef(string);
     92 }
     93 
     94 void SkOSWindow::onHandleInval(const SkIRect& rect)
     95 {
     96     JNIEnv* env = gActivityGlue.m_env;
     97     if (!env || !gWindowGlue.m_inval || !gWindowGlue.m_obj) {
     98         return;
     99     }
    100     if (env->IsSameObject(gWindowGlue.m_obj, NULL)) {
    101         SkDebugf("ERROR: The JNI WeakRef to the Window is invalid");
    102         return;
    103     }
    104     env->CallVoidMethod(gWindowGlue.m_obj, gWindowGlue.m_inval);
    105 }
    106 
    107 void SkOSWindow::onPDFSaved(const char title[], const char desc[],
    108         const char path[])
    109 {
    110     JNIEnv* env = gActivityGlue.m_env;
    111     if (!env || !gActivityGlue.m_addToDownloads || !gActivityGlue.m_obj) {
    112         return;
    113     }
    114     if (env->IsSameObject(gActivityGlue.m_obj, NULL)) {
    115         SkDebugf("ERROR: The JNI WeakRef to the Activity is invalid");
    116         return;
    117     }
    118 
    119     jstring jtitle = env->NewStringUTF(title);
    120     jstring jdesc = env->NewStringUTF(desc);
    121     jstring jpath = env->NewStringUTF(path);
    122 
    123     env->CallVoidMethod(gActivityGlue.m_obj, gActivityGlue.m_addToDownloads,
    124             jtitle, jdesc, jpath);
    125 
    126     env->DeleteLocalRef(jtitle);
    127     env->DeleteLocalRef(jdesc);
    128     env->DeleteLocalRef(jpath);
    129 }
    130 
    131 ///////////////////////////////////////////
    132 /////////////// SkEvent impl //////////////
    133 ///////////////////////////////////////////
    134 
    135 void SkEvent::SignalQueueTimer(SkMSec ms)
    136 {
    137     JNIEnv* env = gActivityGlue.m_env;
    138     if (!env || !gWindowGlue.m_startTimer || !gWindowGlue.m_obj || !ms) {
    139         return;
    140     }
    141     if (env->IsSameObject(gWindowGlue.m_obj, NULL)) {
    142         SkDebugf("ERROR: The JNI WeakRef to the Window is invalid");
    143         return;
    144     }
    145     env->CallVoidMethod(gWindowGlue.m_obj,
    146             gWindowGlue.m_startTimer, ms);
    147 }
    148 
    149 void SkEvent::SignalNonEmptyQueue()
    150 {
    151     JNIEnv* env = gActivityGlue.m_env;
    152     if (!env || !gWindowGlue.m_queueSkEvent || !gWindowGlue.m_obj) {
    153         return;
    154     }
    155     if (env->IsSameObject(gWindowGlue.m_obj, NULL)) {
    156         SkDebugf("ERROR: The JNI WeakRef to the Window is invalid");
    157         return;
    158     }
    159     env->CallVoidMethod(gWindowGlue.m_obj, gWindowGlue.m_queueSkEvent);
    160 }
    161 
    162 ///////////////////////////////////////////
    163 ////////////////// JNI ////////////////////
    164 ///////////////////////////////////////////
    165 
    166 static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[],
    167         const char signature[])
    168 {
    169     jmethodID m = env->GetMethodID(clazz, name, signature);
    170     if (!m) SkDebugf("Could not find Java method %s\n", name);
    171     return m;
    172 }
    173 
    174 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_init(JNIEnv* env,
    175         jobject thiz, jobject jsampleActivity, jint msaaSampleCount)
    176 {
    177     // setup jni hooks to the java activity
    178     gActivityGlue.m_env = env;
    179     jclass clazz = env->FindClass("com/skia/SkiaSampleActivity");
    180     gActivityGlue.m_obj = env->NewWeakGlobalRef(jsampleActivity);
    181     gActivityGlue.m_setTitle = GetJMethod(env, clazz, "setTitle", "(Ljava/lang/CharSequence;)V");
    182     gActivityGlue.m_setSlideList = GetJMethod(env, clazz, "setSlideList", "([Ljava/lang/String;)V");
    183     gActivityGlue.m_addToDownloads = GetJMethod(env, clazz, "addToDownloads",
    184             "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
    185     env->DeleteLocalRef(clazz);
    186 
    187     // setup jni hooks to the java renderer
    188     clazz = env->FindClass("com/skia/SkiaSampleRenderer");
    189     gWindowGlue.m_obj = env->NewWeakGlobalRef(thiz);
    190     gWindowGlue.m_inval = GetJMethod(env, clazz, "requestRender", "()V");
    191     gWindowGlue.m_queueSkEvent = GetJMethod(env, clazz, "queueSkEvent", "()V");
    192     gWindowGlue.m_startTimer = GetJMethod(env, clazz, "startTimer", "(I)V");
    193     gWindowGlue.m_getMSAASampleCount = GetJMethod(env, clazz, "getMSAASampleCount", "()I");
    194     env->DeleteLocalRef(clazz);
    195 
    196     application_init();
    197     SkTArray<const char*> args;
    198 
    199     args.push_back("SampleApp");
    200     // TODO: push ability to select skp dir into the UI
    201     args.push_back("--pictureDir");
    202     args.push_back("/sdcard/skiabot/skia_skp");
    203 
    204     SkString msaaSampleCountString;
    205     if (msaaSampleCount > 0) {
    206         args.push_back("--msaa");
    207         msaaSampleCountString.appendS32(static_cast<uint32_t>(msaaSampleCount));
    208         args.push_back(msaaSampleCountString.c_str());
    209     }
    210 
    211     gWindow = new SampleWindow(NULL, args.count(), const_cast<char**>(args.begin()), NULL);
    212 
    213     // send the list of slides up to the activity
    214     const int slideCount = gWindow->sampleCount();
    215     jobjectArray slideList = env->NewObjectArray(slideCount, env->FindClass("java/lang/String"), env->NewStringUTF(""));
    216     for (int i = 0; i < slideCount; i++) {
    217         jstring slideTitle = env->NewStringUTF(gWindow->getSampleTitle(i).c_str());
    218         env->SetObjectArrayElement(slideList, i, slideTitle);
    219         env->DeleteLocalRef(slideTitle);
    220     }
    221     env->CallVoidMethod(gActivityGlue.m_obj, gActivityGlue.m_setSlideList, slideList);
    222     env->DeleteLocalRef(slideList);
    223 }
    224 
    225 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_term(JNIEnv* env,
    226         jobject thiz)
    227 {
    228     delete gWindow;
    229     gWindow = NULL;
    230     application_term();
    231     if (gWindowGlue.m_obj) {
    232         env->DeleteWeakGlobalRef(gWindowGlue.m_obj);
    233         gWindowGlue.m_obj = NULL;
    234     }
    235     if (gActivityGlue.m_obj) {
    236         env->DeleteWeakGlobalRef(gActivityGlue.m_obj);
    237         gActivityGlue.m_obj = NULL;
    238     }
    239 }
    240 
    241 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_draw(
    242         JNIEnv* env, jobject thiz)
    243 {
    244     if (!gWindow) return;
    245     gWindow->update(NULL);
    246 }
    247 
    248 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_updateSize(JNIEnv* env,
    249         jobject thiz, jint w, jint h)
    250 {
    251     gWindow->resize(w, h);
    252 }
    253 
    254 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_handleClick(JNIEnv* env,
    255         jobject thiz, jint owner, jfloat x, jfloat y, jint jstate)
    256 {
    257     SkView::Click::State state;
    258     switch(jstate) {
    259         case 0:     // MotionEvent.ACTION_DOWN
    260             state = SkView::Click::kDown_State;
    261             break;
    262         case 1:     // MotionEvent.ACTION_UP
    263         case 3:     // MotionEvent.ACTION_CANCEL
    264             state = SkView::Click::kUp_State;
    265             break;
    266         case 2:     // MotionEvent.ACTION_MOVE
    267             state = SkView::Click::kMoved_State;
    268             break;
    269         default:
    270             SkDebugf("motion event ignored\n");
    271             return;
    272     }
    273     gWindow->handleClick(x, y, state, reinterpret_cast<void*>(owner));
    274 }
    275 
    276 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_nextSample(
    277         JNIEnv* env, jobject thiz)
    278 {
    279     gWindow->nextSample();
    280 }
    281 
    282 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_previousSample(
    283         JNIEnv* env, jobject thiz)
    284 {
    285     gWindow->previousSample();
    286 }
    287 
    288 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_goToSample(
    289         JNIEnv* env, jobject thiz, jint position)
    290 {
    291     gWindow->goToSample(position);
    292 }
    293 
    294 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleRenderingMode(
    295         JNIEnv* env, jobject thiz)
    296 {
    297     gWindow->toggleRendering();
    298 }
    299 
    300 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_showOverview(
    301         JNIEnv* env, jobject thiz)
    302 {
    303     gWindow->showOverview();
    304 }
    305 
    306 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleSlideshow(
    307         JNIEnv* env, jobject thiz)
    308 {
    309     gWindow->toggleSlideshow();
    310 }
    311 
    312 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleFPS(
    313         JNIEnv* env, jobject thiz)
    314 {
    315     gWindow->toggleFPS();
    316 }
    317 
    318 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleTiling(
    319         JNIEnv* env, jobject thiz)
    320 {
    321     gWindow->handleChar('t');
    322 }
    323 
    324 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleBBox(
    325         JNIEnv* env, jobject thiz)
    326 {
    327     gWindow->handleChar('b');
    328 }
    329 
    330 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_processSkEvent(
    331         JNIEnv* env, jobject thiz)
    332 {
    333     if (SkEvent::ProcessEvent()) {
    334         SkEvent::SignalNonEmptyQueue();
    335     }
    336 }
    337 
    338 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_serviceQueueTimer(
    339         JNIEnv* env, jobject thiz)
    340 {
    341     SkEvent::ServiceQueueTimer();
    342 }
    343 
    344 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_saveToPDF(
    345         JNIEnv* env, jobject thiz)
    346 {
    347     gWindow->saveToPdf();
    348 }
    349 
    350 JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_postInval(
    351         JNIEnv* env, jobject thiz)
    352 {
    353     gWindow->postInvalDelay();
    354 }
    355