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