From 2c8208f3a444098aee562f5a1ef620142807eda2 Mon Sep 17 00:00:00 2001 From: Scroggo Date: Wed, 15 Jun 2011 16:49:08 +0000 Subject: Improvements to the SampleApp (primarily Android). Reviewed at http://codereview.appspot.com/4587042/ Android - Added buttons for interaction without a keyboard. - Added the ability to zoom in to a specific point (roughly). - Added event handling (for showing a slideshow, for example). - Allow changing screen orientation - Updated README file, explaining how to build Multiplatform changes - Added SampleApp header file - Remove FPS when turning off measure FPS mode git-svn-id: http://skia.googlecode.com/svn/trunk@1596 2bbb7eff-a529-9590-31e7-b0007b416f81 --- android_sample/SampleApp/Android.mk | 3 + android_sample/SampleApp/AndroidManifest.xml | 3 +- android_sample/SampleApp/README.txt | 23 +--- android_sample/SampleApp/jni/sample-jni.cpp | 117 ++++++++++++++++++--- android_sample/SampleApp/res/menu/sample.xml | 19 ++++ android_sample/SampleApp/res/values/strings.xml | 4 + .../src/com/skia/sampleapp/SampleApp.java | 69 ++++++++++-- .../src/com/skia/sampleapp/SampleView.java | 36 +++++-- 8 files changed, 222 insertions(+), 52 deletions(-) (limited to 'android_sample') diff --git a/android_sample/SampleApp/Android.mk b/android_sample/SampleApp/Android.mk index 59f69936b0..f2fd860684 100644 --- a/android_sample/SampleApp/Android.mk +++ b/android_sample/SampleApp/Android.mk @@ -14,6 +14,8 @@ LOCAL_PACKAGE_NAME := SampleApp LOCAL_JNI_SHARED_LIBRARIES := libskia-sample +LOCAL_PROGUARD_ENABLED := disabled + include $(BUILD_PACKAGE) ###################################### @@ -37,6 +39,7 @@ LOCAL_C_INCLUDES += \ external/skia/include/gpu \ external/skia/src/core \ external/skia/gpu/include \ + frameworks/base/opengl/include/GLES2 \ $(LOCAL_PATH)/jni LOCAL_SHARED_LIBRARIES := \ diff --git a/android_sample/SampleApp/AndroidManifest.xml b/android_sample/SampleApp/AndroidManifest.xml index 071ae03390..5980d298d0 100644 --- a/android_sample/SampleApp/AndroidManifest.xml +++ b/android_sample/SampleApp/AndroidManifest.xml @@ -22,6 +22,7 @@ android:debuggable="true"> @@ -29,4 +30,4 @@ - + diff --git a/android_sample/SampleApp/README.txt b/android_sample/SampleApp/README.txt index a7d8e54d2e..31e649291b 100644 --- a/android_sample/SampleApp/README.txt +++ b/android_sample/SampleApp/README.txt @@ -1,25 +1,6 @@ Building the sample app for Android using an Android tree: -Copy this folder into an Android tree in packages/apps. In addition to jni, -res, and src, there needs to be a fourth folder named "skia_extra". This -will include the skia files which are not part of an Android checkout. It -should have three folders: include, samplecode, and src. - -skia/trunk/include/views -> skia_extra/include/views -skia/trunk/include/xml -> skia_extra/include/xml - -skia/trunk/samplecode -> skia_extra/samplecode - -skia/trunk/src/views -> skia_extra/src/views -skia/trunk/src/ports/SkXMLParser_empty.cpp -> skia_extra/src/ports/ -skia/trunk/src/xml -> skia_extra/src/xml - -skia/trunk/include/utils/android/AndroidKeyToSkKey.h -> jni/ - -From packages/apps/SampleApp, type "mm" to build, and install the -resulting apk. - -(It may be necessary to remove samples that do not build from -skia_extra/samplecode/samplecode_files.mk) +cd into external/skia/android_sample/SampleApp. +Type "mm" to build, and install the resulting apk. TODO: Instructions for building from SDK/NDK diff --git a/android_sample/SampleApp/jni/sample-jni.cpp b/android_sample/SampleApp/jni/sample-jni.cpp index 86d07a85b8..be4e4d4a68 100644 --- a/android_sample/SampleApp/jni/sample-jni.cpp +++ b/android_sample/SampleApp/jni/sample-jni.cpp @@ -15,17 +15,18 @@ * */ -#include - +#include "GrContext.h" +#include "SampleApp.h" +#include "SkApplication.h" #include "SkCanvas.h" +#include "SkDevice.h" #include "SkEvent.h" +#include "SkGpuCanvas.h" #include "SkWindow.h" -#include "SkApplication.h" + +#include #include "utils/android/AndroidKeyToSkKey.h" -#include "SkDevice.h" -#include "SkGpuCanvas.h" -#include "GrContext.h" /////////////////////////////////////////// ///////////////// Globals ///////////////// @@ -35,23 +36,27 @@ struct ActivityGlue { JNIEnv* m_env; jweak m_obj; jmethodID m_setTitle; + jmethodID m_startTimer; ActivityGlue() { m_env = NULL; m_obj = NULL; m_setTitle = NULL; + m_startTimer = NULL; } } gActivityGlue; struct WindowGlue { jweak m_obj; jmethodID m_inval; + jmethodID m_queueSkEvent; WindowGlue() { m_obj = NULL; m_inval = NULL; + m_queueSkEvent = NULL; } } gWindowGlue; -SkOSWindow* gWindow; +SampleWindow* gWindow; /////////////////////////////////////////// ///////////// SkOSWindow impl ///////////// @@ -80,9 +85,25 @@ void SkOSWindow::onHandleInval(const SkIRect& rect) /////////////// SkEvent impl ////////////// /////////////////////////////////////////// -void SkEvent::SignalQueueTimer(SkMSec) {} +void SkEvent::SignalQueueTimer(SkMSec ms) +{ + if (!gActivityGlue.m_env || !gActivityGlue.m_startTimer + || !gActivityGlue.m_obj || !ms) { + return; + } + gActivityGlue.m_env->CallVoidMethod(gActivityGlue.m_obj, + gActivityGlue.m_startTimer, ms); +} -void SkEvent::SignalNonEmptyQueue() {} +void SkEvent::SignalNonEmptyQueue() +{ + if (!gActivityGlue.m_env || !gWindowGlue.m_queueSkEvent + || !gWindowGlue.m_obj) { + return; + } + gActivityGlue.m_env->CallVoidMethod(gWindowGlue.m_obj, + gWindowGlue.m_queueSkEvent); +} /////////////////////////////////////////// ////////////////// JNI //////////////////// @@ -113,8 +134,22 @@ JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_handleClick( JNIEnv* env, jobject thiz, jint x, jint y, jint state); JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_createOSWindow( JNIEnv* env, jobject thiz, jobject jsampleView); +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_setZoomCenter( + JNIEnv* env, jobject thiz, jfloat x, jfloat y); JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_zoom( JNIEnv* env, jobject thiz, jfloat factor); +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_nextSample( + JNIEnv* env, jobject thiz, jboolean fprevious); +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_toggleRendering( + JNIEnv* env, jobject thiz); +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_toggleSlideshow( + JNIEnv* env, jobject thiz); +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_toggleFps( + JNIEnv* env, jobject thiz); +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_processSkEvent( + JNIEnv* env, jobject thiz); +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_serviceQueueTimer( + JNIEnv* env, jobject thiz); }; JNIEXPORT bool JNICALL Java_com_skia_sampleapp_SampleApp_handleKeyDown( @@ -162,12 +197,14 @@ JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_updateSize(JNIEnv* env, JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_createOSWindow( JNIEnv* env, jobject thiz, jobject jsampleView) { - gWindow = create_sk_window(NULL); - // Only using a method on View. - jclass clazz = gActivityGlue.m_env->FindClass("android/opengl/GLSurfaceView"); + gWindow = new SampleWindow(NULL); + jclass clazz = gActivityGlue.m_env->FindClass( + "com/skia/sampleapp/SampleView"); gWindowGlue.m_obj = gActivityGlue.m_env->NewWeakGlobalRef(jsampleView); - gWindowGlue.m_inval = GetJMethod(gActivityGlue.m_env, clazz, "requestRender", - "()V"); + gWindowGlue.m_inval = GetJMethod(gActivityGlue.m_env, clazz, + "requestRender", "()V"); + gWindowGlue.m_queueSkEvent = GetJMethod(gActivityGlue.m_env, clazz, + "queueSkEvent", "()V"); gActivityGlue.m_env->DeleteLocalRef(clazz); } @@ -175,11 +212,12 @@ JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_init(JNIEnv* env, jobject thiz) { gActivityGlue.m_env = env; - // Only using a method on Activity. - jclass clazz = env->FindClass("android/app/Activity"); + jclass clazz = env->FindClass("com/skia/sampleapp/SampleApp"); gActivityGlue.m_obj = env->NewWeakGlobalRef(thiz); gActivityGlue.m_setTitle = GetJMethod(env, clazz, "setTitle", "(Ljava/lang/CharSequence;)V"); + gActivityGlue.m_startTimer = GetJMethod(gActivityGlue.m_env, clazz, + "startTimer", "(I)V"); env->DeleteLocalRef(clazz); application_init(); @@ -235,9 +273,56 @@ JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_draw( } } +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_setZoomCenter( + JNIEnv* env, jobject thiz, jfloat x, jfloat y) +{ + gWindow->setZoomCenter(x, y); +} + JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_zoom( JNIEnv* env, jobject thiz, jfloat factor) { gWindow->changeZoomLevel(factor); } +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_nextSample( + JNIEnv* env, jobject thiz, jboolean fprevious) +{ + if (fprevious) { + gWindow->previousSample(); + } else { + gWindow->nextSample(); + } +} + +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_toggleRendering( + JNIEnv* env, jobject thiz) +{ + gWindow->toggleRendering(); +} + +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_toggleSlideshow( + JNIEnv* env, jobject thiz) +{ + gWindow->toggleSlideshow(); +} + +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_toggleFps( + JNIEnv* env, jobject thiz) +{ + gWindow->toggleFPS(); +} + +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_processSkEvent( + JNIEnv* env, jobject thiz) +{ + if (SkEvent::ProcessEvent()) { + SkEvent::SignalNonEmptyQueue(); + } +} + +JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_serviceQueueTimer( + JNIEnv* env, jobject thiz) +{ + SkEvent::ServiceQueueTimer(); +} diff --git a/android_sample/SampleApp/res/menu/sample.xml b/android_sample/SampleApp/res/menu/sample.xml index 49f7ebb091..193f277762 100644 --- a/android_sample/SampleApp/res/menu/sample.xml +++ b/android_sample/SampleApp/res/menu/sample.xml @@ -15,6 +15,21 @@ --> + + + + diff --git a/android_sample/SampleApp/res/values/strings.xml b/android_sample/SampleApp/res/values/strings.xml index 72d3bc8596..810ff41386 100644 --- a/android_sample/SampleApp/res/values/strings.xml +++ b/android_sample/SampleApp/res/values/strings.xml @@ -15,4 +15,8 @@ --> SampleApp + Overview + Toggle rendering + Slideshow + FPS diff --git a/android_sample/SampleApp/src/com/skia/sampleapp/SampleApp.java b/android_sample/SampleApp/src/com/skia/sampleapp/SampleApp.java index fe733603eb..b1160104aa 100644 --- a/android_sample/SampleApp/src/com/skia/sampleapp/SampleApp.java +++ b/android_sample/SampleApp/src/com/skia/sampleapp/SampleApp.java @@ -53,10 +53,9 @@ public class SampleApp extends Activity holder.addView(mView, new LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - + mTitle.setVisibility(View.GONE); getActionBar().setDisplayShowHomeEnabled(false); - } @Override @@ -87,11 +86,43 @@ public class SampleApp extends Activity } }); return true; + case R.id.prev: + mView.queueEvent(new Runnable() { + @Override + public void run() { + nextSample(true); + } + }); + return true; case R.id.next: mView.queueEvent(new Runnable() { @Override public void run() { - handleKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, 0); + nextSample(false); + } + }); + return true; + case R.id.toggle_rendering: + mView.queueEvent(new Runnable() { + @Override + public void run() { + toggleRendering(); + } + }); + return true; + case R.id.slideshow: + mView.queueEvent(new Runnable() { + @Override + public void run() { + toggleSlideshow(); + } + }); + return true; + case R.id.fps: + mView.queueEvent(new Runnable() { + @Override + public void run() { + toggleFps(); } }); return true; @@ -118,7 +149,6 @@ public class SampleApp extends Activity handleKeyDown(keycode, uni); } }); - return true; case KeyEvent.ACTION_UP: mView.queueEvent(new Runnable() { @@ -134,7 +164,7 @@ public class SampleApp extends Activity } private static final int SET_TITLE = 1; - + private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -148,22 +178,47 @@ public class SampleApp extends Activity } } }; - + @Override public void setTitle(CharSequence title) { mHandler.obtainMessage(SET_TITLE, title).sendToTarget(); } + // Called by JNI + @SuppressWarnings("unused") + private void startTimer(int ms) { + // After the delay, queue an event to the Renderer's thread + // to handle the event on the timer queue + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + mView.queueEvent(new Runnable() { + @Override + public void run() { + serviceQueueTimer(); + } + }); + } + }, ms); + } + native void draw(); native void init(); native void term(); // Currently depends on init having already been called. - native void createOSWindow(GLSurfaceView view); + native void createOSWindow(SampleView view); native void updateSize(int w, int h); native void handleClick(int x, int y, int state); native boolean handleKeyDown(int key, int uni); native boolean handleKeyUp(int key); native void zoom(float factor); + native void setZoomCenter(float x, float y); + native void nextSample(boolean previous); + native void toggleRendering(); + native void toggleSlideshow(); + native void toggleFps(); + native void processSkEvent(); + native void serviceQueueTimer(); static { System.loadLibrary("skia-sample"); diff --git a/android_sample/SampleApp/src/com/skia/sampleapp/SampleView.java b/android_sample/SampleApp/src/com/skia/sampleapp/SampleView.java index 0d76dcea93..5ea36a864d 100644 --- a/android_sample/SampleApp/src/com/skia/sampleapp/SampleView.java +++ b/android_sample/SampleApp/src/com/skia/sampleapp/SampleView.java @@ -33,9 +33,10 @@ import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; public class SampleView extends GLSurfaceView implements OnScaleGestureListener { - + private final SampleApp mApp; private ScaleGestureDetector mDetector; + public SampleView(SampleApp app) { super(app); mApp = app; @@ -46,6 +47,17 @@ public class SampleView extends GLSurfaceView implements OnScaleGestureListener mDetector = new ScaleGestureDetector(app, this); } + // Called by JNI + @SuppressWarnings("unused") + private void queueSkEvent() { + queueEvent(new Runnable() { + @Override + public void run() { + mApp.processSkEvent(); + } + }); + } + @Override public boolean onTouchEvent(MotionEvent event) { mDetector.onTouchEvent(event); @@ -62,23 +74,33 @@ public class SampleView extends GLSurfaceView implements OnScaleGestureListener mApp.handleClick(x, y, action); } }); - + return true; } + // ScaleGestureDetector.OnScaleGestureListener implementation @Override public boolean onScaleBegin(ScaleGestureDetector detector) { + final float x = detector.getFocusX(); + final float y = detector.getFocusY(); + queueEvent(new Runnable() { + @Override + public void run() { + mApp.setZoomCenter(x, y); + } + }); return true; } @Override public boolean onScale(ScaleGestureDetector detector) { if (detector.getScaleFactor() != 1) { - final float difference = detector.getCurrentSpan() - detector.getPreviousSpan(); + final float difference = detector.getCurrentSpan() + - detector.getPreviousSpan(); queueEvent(new Runnable() { @Override public void run() { - mApp.zoom(difference * .03f); + mApp.zoom(difference * .01f); } }); @@ -96,11 +118,11 @@ public class SampleView extends GLSurfaceView implements OnScaleGestureListener public void onDrawFrame(GL10 gl) { mApp.draw(); } - + public void onSurfaceChanged(GL10 gl, int width, int height) { mApp.updateSize(width, height); } - + public void onSurfaceCreated(GL10 gl, EGLConfig config) { gl.glClearStencil(0); gl.glClear(gl.GL_STENCIL_BUFFER_BIT); @@ -108,4 +130,4 @@ public class SampleView extends GLSurfaceView implements OnScaleGestureListener mApp.createOSWindow(SampleView.this); } } -} \ No newline at end of file +} -- cgit v1.2.3