From: rmistry Date: Fri, 24 Jun 2016 12:24:16 +0000 (-0700) Subject: Revert of Remove Android SampleApp (patchset #5 id:80001 of https://codereview.chromi... X-Git-Tag: accepted/tizen/5.0/unified/20181102.025319~129^2~73 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7bde5659d354b4ef227c487a4e9fa8de12573c31;p=platform%2Fupstream%2FlibSkiaSharp.git Revert of Remove Android SampleApp (patchset #5 id:80001 of https://codereview.chromium.org/2096683002/ ) Reason for revert: Testing to see if this CL caused the failures in Build-Mac-Clang-Arm7-Debug-Android Original issue's description: > Remove Android SampleApp > > BUG=skia: > GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2096683002 > > Committed: https://skia.googlesource.com/skia/+/41bb5b40e71411ee39538399ea125986ec760a90 TBR=djsollen@google.com,liyuqian@google.com # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=skia: Review-Url: https://codereview.chromium.org/2099693002 --- diff --git a/gyp/SampleApp.gyp b/gyp/SampleApp.gyp index beaaeca..347af56 100644 --- a/gyp/SampleApp.gyp +++ b/gyp/SampleApp.gyp @@ -114,6 +114,23 @@ '../experimental/iOSSampleApp/iPhone/MainWindow_iPhone.xib', ], }], + [ 'skia_os == "android"', { + 'conditions': [ + ['skia_android_framework == 0', { + 'dependencies': [ + 'android_deps.gyp:Android_EntryPoint', + 'skia_launcher.gyp:skia_launcher', + ], + }], + ], + 'dependencies!': [ + 'experimental.gyp:experimental', + ], + 'dependencies': [ + 'android_output.gyp:android_output', + 'android_deps.gyp:Android_SampleApp', + ], + }], [ 'skia_gpu == 1', { 'dependencies': [ 'gputest.gyp:skgputest', diff --git a/gyp/everything.gyp b/gyp/everything.gyp index beda91f..02a5474 100644 --- a/gyp/everything.gyp +++ b/gyp/everything.gyp @@ -31,7 +31,7 @@ }], ['skia_os == "android"', { 'dependencies': [ - 'android_system.gyp:Viewer_APK', + 'android_system.gyp:SampleApp_APK', ], }], ], diff --git a/gyp/most.gyp b/gyp/most.gyp index 7070512..eb9f6c0 100644 --- a/gyp/most.gyp +++ b/gyp/most.gyp @@ -39,13 +39,10 @@ 'example.gyp:HelloWorld', ], }], - ['skia_os == "android"', { + ['skia_os == "android" and skia_vulkan == 1', { 'dependencies': [ 'android_system.gyp:Viewer_APK', ], - 'dependencies!': [ - 'SampleApp.gyp:SampleApp', - ], }], ['skia_os == "ios"', { 'dependencies!': [ diff --git a/gyp/tools.gyp b/gyp/tools.gyp index 68af294..ab8b4c6 100644 --- a/gyp/tools.gyp +++ b/gyp/tools.gyp @@ -496,6 +496,7 @@ '<(skia_include_path)/utils/win', '<(skia_include_path)/utils/SkDebugUtils.h', '<(skia_include_path)/utils/SkJSONCPP.h', + '<(skia_include_path)/views/SkOSWindow_Android.h', '<(skia_include_path)/views/SkOSWindow_iOS.h', '<(skia_include_path)/views/SkOSWindow_Mac.h', '<(skia_include_path)/views/SkOSWindow_SDL.h', diff --git a/include/views/SkOSWindow_Android.h b/include/views/SkOSWindow_Android.h new file mode 100644 index 0000000..234e65c --- /dev/null +++ b/include/views/SkOSWindow_Android.h @@ -0,0 +1,53 @@ +/* + * Copyright 2011 Skia + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkOSWindow_Android_DEFINED +#define SkOSWindow_Android_DEFINED + +#include "SkWindow.h" + +#include + +struct SkAndroidWindow { + EGLDisplay fDisplay; + EGLSurface fSurface; + EGLContext fContext; +}; + +class SkOSWindow : public SkWindow { +public: + SkOSWindow(void*); + ~SkOSWindow(); + + enum SkBackEndTypes { + kNone_BackEndType, + kNativeGL_BackEndType, + }; + + bool attach(SkBackEndTypes attachType, int msaaSampleCount, bool deepColor, + AttachmentInfo* info); + void release(); + void present(); + bool makeFullscreen() { return true; } + void closeWindow(); + void setVsync(bool); + bool destroyRequested() { return fDestroyRequested; } + +protected: + // overrides from SkWindow + virtual void onHandleInval(const SkIRect&); + virtual void onSetTitle(const char title[]); + +private: + SkAndroidWindow fWindow; + ANativeWindow* fNativeWindow; + bool fDestroyRequested; + + typedef SkWindow INHERITED; +}; + +#endif diff --git a/include/views/SkWindow.h b/include/views/SkWindow.h index f81ec5d..5077484 100644 --- a/include/views/SkWindow.h +++ b/include/views/SkWindow.h @@ -129,7 +129,7 @@ private: #elif defined(SK_BUILD_FOR_WIN) #include "SkOSWindow_Win.h" #elif defined(SK_BUILD_FOR_ANDROID) - #error Android does not support SkOSWindow and SampleApp. Please use Viewer instead. + #include "SkOSWindow_Android.h" #elif defined(SK_BUILD_FOR_UNIX) #include "SkOSWindow_Unix.h" #elif defined(SK_BUILD_FOR_IOS) diff --git a/platform_tools/android/apps/sample_app/build.gradle b/platform_tools/android/apps/sample_app/build.gradle new file mode 100644 index 0000000..4678980 --- /dev/null +++ b/platform_tools/android/apps/sample_app/build.gradle @@ -0,0 +1,30 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 19 + buildToolsVersion "22.0.1" + + defaultConfig { + applicationId "com.skia.sample_app" + minSdkVersion 9 + targetSdkVersion 19 + versionCode 1 + versionName "1.0" + signingConfig signingConfigs.debug + } + + sourceSets.main.jni.srcDirs = [] //disable automatic ndk-build call + sourceSets.main.jniLibs.srcDir "src/main/libs" + + productFlavors { + arm {} + arm64 {} + x86 {} + x86_64 {} + mips {} + mips64 {} + } + + // make sure that app is built and shared libraries are copied to correct directories + setupSkiaLibraryBuild(project, applicationVariants, "CopySampleAppDeps") +} \ No newline at end of file diff --git a/platform_tools/android/apps/sample_app/src/main/AndroidManifest.xml b/platform_tools/android/apps/sample_app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..edb0424 --- /dev/null +++ b/platform_tools/android/apps/sample_app/src/main/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/platform_tools/android/apps/sample_app/src/main/java/com/skia/SkiaSampleActivity.java b/platform_tools/android/apps/sample_app/src/main/java/com/skia/SkiaSampleActivity.java new file mode 100644 index 0000000..6e30696 --- /dev/null +++ b/platform_tools/android/apps/sample_app/src/main/java/com/skia/SkiaSampleActivity.java @@ -0,0 +1,251 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +package com.skia; + +import android.app.ActionBar; +import android.app.Activity; +import android.app.DownloadManager; +import android.content.Intent; +import android.content.Context; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.LinearLayout; +import android.widget.TextView; + +import java.io.File; + +public class SkiaSampleActivity extends Activity +{ + private TextView mTitle; + private SkiaSampleView mSampleView; + + private ArrayAdapter mSlideList; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.layout); + mTitle = (TextView) findViewById(R.id.title_view); + mSlideList = new ArrayAdapter(this, android.R.layout.simple_expandable_list_item_1); + + try { + System.loadLibrary("skia_android"); + } catch (UnsatisfiedLinkError e) { + // This might be because skia was linked to SampleApp statically. + } + + try { + System.loadLibrary("SampleApp"); + + createSampleView(false, 0); + + setupActionBar(); + } catch (UnsatisfiedLinkError e) { + mTitle.setText("ERROR: native library could not be loaded"); + } + } + + private void createSampleView(boolean useOpenGLAPI, int msaaSampleCount) { + if (mSampleView != null) { + ViewGroup viewGroup = (ViewGroup) mSampleView.getParent(); + viewGroup.removeView(mSampleView); + mSampleView.terminate(); + } + + // intent get intent extras if triggered from the command line + Intent intent = this.getIntent(); + String flags = intent.getStringExtra("cmdLineFlags"); + + if (flags == null || flags.isEmpty()) { + flags = "--pictureDir /data/local/tmp/skia_skp "; + flags += "--resourcePath /data/local/tmp/skia_resources "; + } + + mSampleView = new SkiaSampleView(this, flags, useOpenGLAPI, msaaSampleCount); + LinearLayout holder = (LinearLayout) findViewById(R.id.holder); + holder.addView(mSampleView, new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + } + + private void setupActionBar() { + ActionBar.OnNavigationListener navigationCallback = new ActionBar.OnNavigationListener() { + @Override + public boolean onNavigationItemSelected(int position, long itemId) { + mSampleView.goToSample(position); + return true; + } + }; + + ActionBar actionBar = getActionBar(); + actionBar.setDisplayShowHomeEnabled(false); + actionBar.setDisplayShowTitleEnabled(false); + actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); + actionBar.setListNavigationCallbacks(mSlideList, navigationCallback); + } + + @Override + protected void onResume () { + super.onResume(); + if (mSampleView != null && mSampleView.getWidth() > 0 && mSampleView.getHeight() > 0) { + //TODO try mSampleView.requestRender() instead + mSampleView.inval(); + } + } + + @Override + public void onDestroy() { + if (mSampleView != null) { + mSampleView.terminate(); + } + super.onDestroy(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.action_bar, menu); + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + if (mSampleView != null) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { + ((MenuItem) menu.findItem(R.id.glcontext_menu)) + .setEnabled(false); + + } else { + boolean usesOpenGLAPI = mSampleView.getUsesOpenGLAPI(); + boolean isMSAA4 = mSampleView.getMSAASampleCount() == 4; + + ((MenuItem) menu.findItem(R.id.glcontext_opengles)) + .setChecked(!usesOpenGLAPI && !isMSAA4); + + ((MenuItem) menu.findItem(R.id.glcontext_msaa4_opengles)) + .setChecked(!usesOpenGLAPI && isMSAA4); + + ((MenuItem) menu.findItem(R.id.glcontext_opengl)) + .setChecked(usesOpenGLAPI && !isMSAA4); + + ((MenuItem) menu.findItem(R.id.glcontext_msaa4_opengl)) + .setChecked(usesOpenGLAPI && isMSAA4); + } + } + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (mSampleView == null) { + return false; + } + + switch (item.getItemId()) { + case R.id.overview: + mSampleView.showOverview(); + return true; + case R.id.prev: + mSampleView.previousSample(); + return true; + case R.id.next: + mSampleView.nextSample(); + return true; + case R.id.toggle_rendering: + mSampleView.toggleRenderingMode(); + return true; + case R.id.slideshow: + mSampleView.toggleSlideshow(); + return true; + case R.id.fps: + mSampleView.toggleFPS(); + return true; + case R.id.tiling: + mSampleView.toggleTiling(); + return true; + case R.id.bbox: + mSampleView.toggleBBox(); + return true; + case R.id.save_to_pdf: + mSampleView.saveToPDF(); + return true; + case R.id.glcontext_opengles: + return setOpenGLContextSettings(false, 0); + case R.id.glcontext_msaa4_opengles: + return setOpenGLContextSettings(false, 4); + case R.id.glcontext_opengl: + return setOpenGLContextSettings(true, 0); + case R.id.glcontext_msaa4_opengl: + return setOpenGLContextSettings(true, 4); + default: + return false; + } + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + final int keycode = event.getKeyCode(); + if (keycode == KeyEvent.KEYCODE_BACK) { + if (event.getAction() == KeyEvent.ACTION_UP) { + finish(); + } + return true; + } + return false; + } + + private static final int SET_TITLE = 1; + private static final int SET_SLIDES = 2; + + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case SET_TITLE: + mTitle.setText((String) msg.obj); + SkiaSampleActivity.this.getActionBar().setSubtitle((String) msg.obj); + break; + case SET_SLIDES: + mSlideList.addAll((String[]) msg.obj); + break; + default: + break; + } + } + }; + + // Called by JNI + @Override + public void setTitle(CharSequence title) { + mHandler.obtainMessage(SET_TITLE, title).sendToTarget(); + } + + // Called by JNI + public void setSlideList(String[] slideList) { + mHandler.obtainMessage(SET_SLIDES, slideList).sendToTarget(); + } + + private boolean setOpenGLContextSettings(boolean requestedOpenGLAPI, int requestedSampleCount) { + if (mSampleView != null && + mSampleView.getMSAASampleCount() == requestedSampleCount && + mSampleView.getUsesOpenGLAPI() == requestedOpenGLAPI) { + return true; + } + + createSampleView(requestedOpenGLAPI, requestedSampleCount); + + return true; + } +} diff --git a/platform_tools/android/apps/sample_app/src/main/java/com/skia/SkiaSampleRenderer.java b/platform_tools/android/apps/sample_app/src/main/java/com/skia/SkiaSampleRenderer.java new file mode 100644 index 0000000..5525709 --- /dev/null +++ b/platform_tools/android/apps/sample_app/src/main/java/com/skia/SkiaSampleRenderer.java @@ -0,0 +1,113 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +package com.skia; + +import android.opengl.GLSurfaceView; +import android.os.Handler; +import android.util.Log; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; +import javax.microedition.khronos.opengles.GL11; + +public class SkiaSampleRenderer implements GLSurfaceView.Renderer { + + private final SkiaSampleView mSampleView; + private Handler mHandler = new Handler(); + private int mMSAASampleCount; + private String mCmdLineFlags; + + SkiaSampleRenderer(SkiaSampleView view, String cmdLineFlags) { + mSampleView = view; + mCmdLineFlags = cmdLineFlags; + } + + @Override + public void onDrawFrame(GL10 gl) { + draw(); + } + + @Override + public void onSurfaceChanged(GL10 gl, int width, int height) { + updateSize(width, height); + } + + @Override + public void onSurfaceCreated(GL10 gl, EGLConfig config) { + if (gl instanceof GL11) { + int value[] = new int[1]; + ((GL11) gl).glGetIntegerv(GL11.GL_SAMPLES, value, 0); + if (value[0] == 1) { + mMSAASampleCount = 0; + } else { + mMSAASampleCount = value[0]; + } + } + + gl.glClearStencil(0); + gl.glClear(GL10.GL_STENCIL_BUFFER_BIT); + + init((SkiaSampleActivity)mSampleView.getContext(), mCmdLineFlags, mMSAASampleCount); + } + + // Called by JNI and the view. + synchronized public int getMSAASampleCount() { + return mMSAASampleCount; + } + + // Called by JNI + 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() { + mSampleView.queueEvent(new Runnable() { + @Override + public void run() { + serviceQueueTimer(); + } + }); + } + }, ms); + } + + // Called by JNI + private void queueSkEvent() { + mSampleView.queueEvent(new Runnable() { + @Override + public void run() { + processSkEvent(); + } + }); + } + + // Called by JNI + private void requestRender() { + mSampleView.requestRender(); + } + + native void init(SkiaSampleActivity activity, String flags, int msaaSampleCount); + native void term(); + native void draw(); + native void updateSize(int w, int h); + native void handleClick(int owner, float x, float y, int state); + native void showOverview(); + native void nextSample(); + native void previousSample(); + native void goToSample(int position); + native void toggleRenderingMode(); + native void toggleSlideshow(); + native void toggleFPS(); + native void toggleTiling(); + native void toggleBBox(); + native void processSkEvent(); + native void serviceQueueTimer(); + native void saveToPDF(); + native void postInval(); +} \ No newline at end of file diff --git a/platform_tools/android/apps/sample_app/src/main/java/com/skia/SkiaSampleView.java b/platform_tools/android/apps/sample_app/src/main/java/com/skia/SkiaSampleView.java new file mode 100644 index 0000000..6213a6f --- /dev/null +++ b/platform_tools/android/apps/sample_app/src/main/java/com/skia/SkiaSampleView.java @@ -0,0 +1,310 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +package com.skia; + +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLDisplay; +import javax.microedition.khronos.opengles.GL10; + +import android.content.Context; +import android.opengl.EGL14; +import android.opengl.GLSurfaceView; +import android.os.Build; +import android.util.Log; +import android.view.MotionEvent; +import android.widget.Toast; + +public class SkiaSampleView extends GLSurfaceView { + + private final SkiaSampleRenderer mSampleRenderer; + private boolean mRequestedOpenGLAPI; // true == use (desktop) OpenGL. false == use OpenGL ES. + private int mRequestedMSAASampleCount; + + public SkiaSampleView(Context ctx, String cmdLineFlags, boolean useOpenGL, int msaaSampleCount) { + super(ctx); + + mSampleRenderer = new SkiaSampleRenderer(this, cmdLineFlags); + mRequestedMSAASampleCount = msaaSampleCount; + + setEGLContextClientVersion(2); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { + setEGLConfigChooser(8, 8, 8, 8, 0, 8); + } else { + mRequestedOpenGLAPI = useOpenGL; + setEGLConfigChooser(new SampleViewEGLConfigChooser()); + } + setRenderer(mSampleRenderer); + setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + int count = event.getPointerCount(); + for (int i = 0; i < count; i++) { + final float x = event.getX(i); + final float y = event.getY(i); + final int owner = event.getPointerId(i); + int action = event.getAction() & MotionEvent.ACTION_MASK; + switch (action) { + case MotionEvent.ACTION_POINTER_UP: + action = MotionEvent.ACTION_UP; + break; + case MotionEvent.ACTION_POINTER_DOWN: + action = MotionEvent.ACTION_DOWN; + break; + default: + break; + } + final int finalAction = action; + queueEvent(new Runnable() { + @Override + public void run() { + mSampleRenderer.handleClick(owner, x, y, finalAction); + } + }); + } + return true; + } + + public void inval() { + queueEvent(new Runnable() { + @Override + public void run() { + mSampleRenderer.postInval(); + } + }); + } + + public void terminate() { + queueEvent(new Runnable() { + @Override + public void run() { + mSampleRenderer.term(); + } + }); + } + + public void showOverview() { + queueEvent(new Runnable() { + @Override + public void run() { + mSampleRenderer.showOverview(); + } + }); + } + + public void nextSample() { + queueEvent(new Runnable() { + @Override + public void run() { + mSampleRenderer.nextSample(); + } + }); + } + + public void previousSample() { + queueEvent(new Runnable() { + @Override + public void run() { + mSampleRenderer.previousSample(); + } + }); + } + + public void goToSample(final int position) { + queueEvent(new Runnable() { + @Override + public void run() { + mSampleRenderer.goToSample(position); + } + }); + } + + public void toggleRenderingMode() { + queueEvent(new Runnable() { + @Override + public void run() { + mSampleRenderer.toggleRenderingMode(); + } + }); + } + + public void toggleSlideshow() { + queueEvent(new Runnable() { + @Override + public void run() { + mSampleRenderer.toggleSlideshow(); + } + }); + } + + public void toggleFPS() { + queueEvent(new Runnable() { + @Override + public void run() { + mSampleRenderer.toggleFPS(); + } + }); + } + + public void toggleTiling() { + queueEvent(new Runnable() { + @Override + public void run() { + mSampleRenderer.toggleTiling(); + } + }); + } + + public void toggleBBox() { + queueEvent(new Runnable() { + @Override + public void run() { + mSampleRenderer.toggleBBox(); + } + }); + } + + public void saveToPDF() { + queueEvent(new Runnable() { + @Override + public void run() { + mSampleRenderer.saveToPDF(); + } + }); + + String msg = getContext().getString(R.string.pdf_save_info); + Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show(); + } + + public boolean getUsesOpenGLAPI() { + return mRequestedOpenGLAPI; + } + + public int getMSAASampleCount() { + return mSampleRenderer.getMSAASampleCount(); + } + + private class SampleViewEGLConfigChooser implements GLSurfaceView.EGLConfigChooser { + + @Override + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { + int numConfigs = 0; + int[] configSpec = null; + int[] value = new int[1]; + + int[] validAPIs = new int[] { + EGL14.EGL_OPENGL_API, + EGL14.EGL_OPENGL_ES_API + }; + int initialAPI = mRequestedOpenGLAPI ? 0 : 1; + + for (int i = initialAPI; i < validAPIs.length && numConfigs == 0; i++) { + int currentAPI = validAPIs[i]; + EGL14.eglBindAPI(currentAPI); + + // setup the renderableType which will only be included in the + // spec if we are attempting to get access to the OpenGL APIs. + int renderableType = EGL14.EGL_OPENGL_BIT; + if (currentAPI == EGL14.EGL_OPENGL_API) { + renderableType = EGL14.EGL_OPENGL_ES2_BIT; + } + + if (mRequestedMSAASampleCount > 0) { + configSpec = new int[] { + EGL10.EGL_RED_SIZE, 8, + EGL10.EGL_GREEN_SIZE, 8, + EGL10.EGL_BLUE_SIZE, 8, + EGL10.EGL_ALPHA_SIZE, 8, + EGL10.EGL_DEPTH_SIZE, 0, + EGL10.EGL_STENCIL_SIZE, 8, + EGL10.EGL_SAMPLE_BUFFERS, 1, + EGL10.EGL_SAMPLES, mRequestedMSAASampleCount, + EGL10.EGL_RENDERABLE_TYPE, renderableType, + EGL10.EGL_NONE + }; + + // EGL_RENDERABLE_TYPE is only needed when attempting to use + // the OpenGL API (not ES) and causes many EGL drivers to fail + // with a BAD_ATTRIBUTE error. + if (!mRequestedOpenGLAPI) { + configSpec[16] = EGL10.EGL_NONE; + Log.i("Skia", "spec: " + configSpec); + } + + if (!egl.eglChooseConfig(display, configSpec, null, 0, value)) { + Log.i("Skia", "Could not get MSAA context count: " + mRequestedMSAASampleCount); + } + + numConfigs = value[0]; + } + + if (numConfigs <= 0) { + // Try without multisampling. + configSpec = new int[] { + EGL10.EGL_RED_SIZE, 8, + EGL10.EGL_GREEN_SIZE, 8, + EGL10.EGL_BLUE_SIZE, 8, + EGL10.EGL_ALPHA_SIZE, 8, + EGL10.EGL_DEPTH_SIZE, 0, + EGL10.EGL_STENCIL_SIZE, 8, + EGL10.EGL_RENDERABLE_TYPE, renderableType, + EGL10.EGL_NONE + }; + + // EGL_RENDERABLE_TYPE is only needed when attempting to use + // the OpenGL API (not ES) and causes many EGL drivers to fail + // with a BAD_ATTRIBUTE error. + if (!mRequestedOpenGLAPI) { + configSpec[12] = EGL10.EGL_NONE; + Log.i("Skia", "spec: " + configSpec); + } + + if (!egl.eglChooseConfig(display, configSpec, null, 0, value)) { + Log.i("Skia", "Could not get non-MSAA context count"); + } + numConfigs = value[0]; + } + } + + if (numConfigs <= 0) { + throw new IllegalArgumentException("No configs match configSpec"); + } + + // Get all matching configurations. + EGLConfig[] configs = new EGLConfig[numConfigs]; + if (!egl.eglChooseConfig(display, configSpec, configs, numConfigs, value)) { + throw new IllegalArgumentException("Could not get config data"); + } + + for (int i = 0; i < configs.length; ++i) { + EGLConfig config = configs[i]; + if (findConfigAttrib(egl, display, config , EGL10.EGL_RED_SIZE, 0) == 8 && + findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0) == 8 && + findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0) == 8 && + findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0) == 8 && + findConfigAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0) == 8) { + return config; + } + } + + throw new IllegalArgumentException("Could not find suitable EGL config"); + } + + private int findConfigAttrib(EGL10 egl, EGLDisplay display, + EGLConfig config, int attribute, int defaultValue) { + int[] value = new int[1]; + if (egl.eglGetConfigAttrib(display, config, attribute, value)) { + return value[0]; + } + return defaultValue; + } + + } +} diff --git a/platform_tools/android/apps/sample_app/src/main/jni/AndroidKeyToSkKey.h b/platform_tools/android/apps/sample_app/src/main/jni/AndroidKeyToSkKey.h new file mode 100644 index 0000000..00fd5d0 --- /dev/null +++ b/platform_tools/android/apps/sample_app/src/main/jni/AndroidKeyToSkKey.h @@ -0,0 +1,34 @@ +/* + * Copyright 2011 Skia + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#ifndef _ANDROID_TO_SKIA_KEYCODES_H +#define _ANDROID_TO_SKIA_KEYCODES_H + +#include "android/keycodes.h" +#include "SkKey.h" + +// Convert an Android keycode to an SkKey. This is an incomplete list, only +// including keys used by the sample app. +SkKey AndroidKeycodeToSkKey(int keycode) { + switch (keycode) { + case AKEYCODE_DPAD_LEFT: + return kLeft_SkKey; + case AKEYCODE_DPAD_RIGHT: + return kRight_SkKey; + case AKEYCODE_DPAD_UP: + return kUp_SkKey; + case AKEYCODE_DPAD_DOWN: + return kDown_SkKey; + case AKEYCODE_BACK: + return kBack_SkKey; + default: + return kNONE_SkKey; + } +} + +#endif diff --git a/platform_tools/android/apps/sample_app/src/main/jni/com_skia_SkiaSampleRenderer.cpp b/platform_tools/android/apps/sample_app/src/main/jni/com_skia_SkiaSampleRenderer.cpp new file mode 100644 index 0000000..f233a2f --- /dev/null +++ b/platform_tools/android/apps/sample_app/src/main/jni/com_skia_SkiaSampleRenderer.cpp @@ -0,0 +1,356 @@ +/* + * Copyright 2011 Skia + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "com_skia_SkiaSampleRenderer.h" + +#include "SampleApp.h" +#include "SkApplication.h" +#include "SkCanvas.h" +#include "SkDevice.h" +#include "SkEvent.h" +#include "SkWindow.h" + +#include +#include "AndroidKeyToSkKey.h" + + +/////////////////////////////////////////// +///////////////// Globals ///////////////// +/////////////////////////////////////////// + +struct ActivityGlue { + JNIEnv* m_env; + jweak m_obj; + jmethodID m_setTitle; + jmethodID m_setSlideList; + ActivityGlue() { + m_env = nullptr; + m_obj = nullptr; + m_setTitle = nullptr; + m_setSlideList = nullptr; + } +} gActivityGlue; + +struct WindowGlue { + jweak m_obj; + jmethodID m_inval; + jmethodID m_queueSkEvent; + jmethodID m_startTimer; + jmethodID m_getMSAASampleCount; + WindowGlue() { + m_obj = nullptr; + m_inval = nullptr; + m_queueSkEvent = nullptr; + m_startTimer = nullptr; + m_getMSAASampleCount = nullptr; + } +} gWindowGlue; + +SampleWindow* gWindow; + +/////////////////////////////////////////// +///////////// SkOSWindow impl ///////////// +/////////////////////////////////////////// + +SkOSWindow::SkOSWindow(void*) : fDestroyRequested(false) { +} + +SkOSWindow::~SkOSWindow() { +} + +bool SkOSWindow::attach(SkBackEndTypes /* attachType */, int /*msaaSampleCount*/, + bool /*deepColor*/, AttachmentInfo* info) +{ + JNIEnv* env = gActivityGlue.m_env; + if (!env || !gWindowGlue.m_getMSAASampleCount || !gWindowGlue.m_obj) { + return false; + } + if (env->IsSameObject(gWindowGlue.m_obj, nullptr)) { + SkDebugf("ERROR: The JNI WeakRef to the Window is invalid"); + return false; + } + info->fSampleCount = env->CallIntMethod(gWindowGlue.m_obj, gWindowGlue.m_getMSAASampleCount); + + // This is the value requested in SkiaSampleView.java. + info->fStencilBits = 8; + return true; +} + +void SkOSWindow::release() { +} + +void SkOSWindow::present() { +} + +void SkOSWindow::closeWindow() { +} + +void SkOSWindow::setVsync(bool) { +} + +void SkOSWindow::onSetTitle(const char title[]) +{ + JNIEnv* env = gActivityGlue.m_env; + if (!env) { + return; + } + if (env->IsSameObject(gActivityGlue.m_obj, nullptr)) { + SkDebugf("ERROR: The JNI WeakRef to the Activity is invalid"); + return; + } + + jstring string = env->NewStringUTF(title); + env->CallVoidMethod(gActivityGlue.m_obj, gActivityGlue.m_setTitle, string); + env->DeleteLocalRef(string); +} + +void SkOSWindow::onHandleInval(const SkIRect& rect) +{ + JNIEnv* env = gActivityGlue.m_env; + if (!env || !gWindowGlue.m_inval || !gWindowGlue.m_obj) { + return; + } + if (env->IsSameObject(gWindowGlue.m_obj, nullptr)) { + SkDebugf("ERROR: The JNI WeakRef to the Window is invalid"); + return; + } + env->CallVoidMethod(gWindowGlue.m_obj, gWindowGlue.m_inval); +} + +/////////////////////////////////////////// +/////////////// SkEvent impl ////////////// +/////////////////////////////////////////// + +void SkEvent::SignalQueueTimer(SkMSec ms) +{ + JNIEnv* env = gActivityGlue.m_env; + if (!env || !gWindowGlue.m_startTimer || !gWindowGlue.m_obj || !ms) { + return; + } + if (env->IsSameObject(gWindowGlue.m_obj, nullptr)) { + SkDebugf("ERROR: The JNI WeakRef to the Window is invalid"); + return; + } + env->CallVoidMethod(gWindowGlue.m_obj, + gWindowGlue.m_startTimer, ms); +} + +void SkEvent::SignalNonEmptyQueue() +{ + JNIEnv* env = gActivityGlue.m_env; + if (!env || !gWindowGlue.m_queueSkEvent || !gWindowGlue.m_obj) { + return; + } + if (env->IsSameObject(gWindowGlue.m_obj, nullptr)) { + SkDebugf("ERROR: The JNI WeakRef to the Window is invalid"); + return; + } + env->CallVoidMethod(gWindowGlue.m_obj, gWindowGlue.m_queueSkEvent); +} + +/////////////////////////////////////////// +////////////////// JNI //////////////////// +/////////////////////////////////////////// + +static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], + const char signature[]) +{ + jmethodID m = env->GetMethodID(clazz, name, signature); + if (!m) SkDebugf("Could not find Java method %s\n", name); + return m; +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_init(JNIEnv* env, + jobject thiz, jobject jsampleActivity, jstring cmdLineFlags, jint msaaSampleCount) +{ + // setup jni hooks to the java activity + gActivityGlue.m_env = env; + jclass clazz = env->FindClass("com/skia/SkiaSampleActivity"); + gActivityGlue.m_obj = env->NewWeakGlobalRef(jsampleActivity); + gActivityGlue.m_setTitle = GetJMethod(env, clazz, "setTitle", "(Ljava/lang/CharSequence;)V"); + gActivityGlue.m_setSlideList = GetJMethod(env, clazz, "setSlideList", "([Ljava/lang/String;)V"); + env->DeleteLocalRef(clazz); + + // setup jni hooks to the java renderer + clazz = env->FindClass("com/skia/SkiaSampleRenderer"); + gWindowGlue.m_obj = env->NewWeakGlobalRef(thiz); + gWindowGlue.m_inval = GetJMethod(env, clazz, "requestRender", "()V"); + gWindowGlue.m_queueSkEvent = GetJMethod(env, clazz, "queueSkEvent", "()V"); + gWindowGlue.m_startTimer = GetJMethod(env, clazz, "startTimer", "(I)V"); + gWindowGlue.m_getMSAASampleCount = GetJMethod(env, clazz, "getMSAASampleCount", "()I"); + env->DeleteLocalRef(clazz); + + application_init(); + + const char* flags = env->GetStringUTFChars(cmdLineFlags, JNI_FALSE); + SkTArray flagEntries; + SkStrSplit(flags, " ", &flagEntries); + + SkTArray args; + args.push_back("SampleApp"); + for (int i = 0; i < flagEntries.count(); i++) { + SkDebugf(flagEntries[i].c_str()); + args.push_back(flagEntries[i].c_str()); + } + + SkString msaaSampleCountString; + if (msaaSampleCount > 0) { + args.push_back("--msaa"); + msaaSampleCountString.appendS32(static_cast(msaaSampleCount)); + args.push_back(msaaSampleCountString.c_str()); + } + + if (gWindow) { + SkDebugf("The sample window already exists."); + } else { + gWindow = new SampleWindow(nullptr, args.count(), const_cast(args.begin()), nullptr); + } + + // cleanup the command line flags + env->ReleaseStringUTFChars(cmdLineFlags, flags); + + // send the list of slides up to the activity + const int slideCount = gWindow->sampleCount(); + jobjectArray slideList = env->NewObjectArray(slideCount, env->FindClass("java/lang/String"), env->NewStringUTF("")); + for (int i = 0; i < slideCount; i++) { + jstring slideTitle = env->NewStringUTF(gWindow->getSampleTitle(i).c_str()); + env->SetObjectArrayElement(slideList, i, slideTitle); + env->DeleteLocalRef(slideTitle); + } + env->CallVoidMethod(gActivityGlue.m_obj, gActivityGlue.m_setSlideList, slideList); + env->DeleteLocalRef(slideList); +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_term(JNIEnv* env, + jobject thiz) +{ + delete gWindow; + gWindow = nullptr; + application_term(); + if (gWindowGlue.m_obj) { + env->DeleteWeakGlobalRef(gWindowGlue.m_obj); + gWindowGlue.m_obj = nullptr; + } + if (gActivityGlue.m_obj) { + env->DeleteWeakGlobalRef(gActivityGlue.m_obj); + gActivityGlue.m_obj = nullptr; + } +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_draw( + JNIEnv* env, jobject thiz) +{ + if (!gWindow) return; + gWindow->update(nullptr); +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_updateSize(JNIEnv* env, + jobject thiz, jint w, jint h) +{ + gWindow->resize(w, h); +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_handleClick(JNIEnv* env, + jobject thiz, jint owner, jfloat x, jfloat y, jint jstate) +{ + SkView::Click::State state; + switch(jstate) { + case 0: // MotionEvent.ACTION_DOWN + state = SkView::Click::kDown_State; + break; + case 1: // MotionEvent.ACTION_UP + case 3: // MotionEvent.ACTION_CANCEL + state = SkView::Click::kUp_State; + break; + case 2: // MotionEvent.ACTION_MOVE + state = SkView::Click::kMoved_State; + break; + default: + SkDebugf("motion event ignored\n"); + return; + } + gWindow->handleClick(x, y, state, reinterpret_cast(owner)); +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_nextSample( + JNIEnv* env, jobject thiz) +{ + gWindow->nextSample(); +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_previousSample( + JNIEnv* env, jobject thiz) +{ + gWindow->previousSample(); +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_goToSample( + JNIEnv* env, jobject thiz, jint position) +{ + gWindow->goToSample(position); +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleRenderingMode( + JNIEnv* env, jobject thiz) +{ + gWindow->toggleRendering(); +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_showOverview( + JNIEnv* env, jobject thiz) +{ + gWindow->showOverview(); +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleSlideshow( + JNIEnv* env, jobject thiz) +{ + gWindow->toggleSlideshow(); +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleFPS( + JNIEnv* env, jobject thiz) +{ + gWindow->toggleFPS(); +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleTiling( + JNIEnv* env, jobject thiz) +{ + gWindow->handleChar('t'); +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleBBox( + JNIEnv* env, jobject thiz) +{ + gWindow->handleChar('b'); +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_processSkEvent( + JNIEnv* env, jobject thiz) +{ + if (SkEvent::ProcessEvent()) { + SkEvent::SignalNonEmptyQueue(); + } +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_serviceQueueTimer( + JNIEnv* env, jobject thiz) +{ + SkEvent::ServiceQueueTimer(); +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_saveToPDF( + JNIEnv* env, jobject thiz) +{ + gWindow->saveToPdf(); +} + +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_postInval( + JNIEnv* env, jobject thiz) +{ + gWindow->postInvalDelay(); +} diff --git a/platform_tools/android/apps/sample_app/src/main/jni/com_skia_SkiaSampleRenderer.h b/platform_tools/android/apps/sample_app/src/main/jni/com_skia_SkiaSampleRenderer.h new file mode 100644 index 0000000..8883a3a --- /dev/null +++ b/platform_tools/android/apps/sample_app/src/main/jni/com_skia_SkiaSampleRenderer.h @@ -0,0 +1,164 @@ +/* + * Copyright 2015 Skia + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_skia_SkiaSampleRenderer */ + +#ifndef _Included_com_skia_SkiaSampleRenderer +#define _Included_com_skia_SkiaSampleRenderer +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_skia_SkiaSampleRenderer + * Method: init + * Signature: (Lcom/skia/SkiaSampleActivity;Ljava/lang/String;I)V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_init + (JNIEnv *, jobject, jobject, jstring, jint); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: term + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_term + (JNIEnv *, jobject); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: draw + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_draw + (JNIEnv *, jobject); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: updateSize + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_updateSize + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: handleClick + * Signature: (IFFI)V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_handleClick + (JNIEnv *, jobject, jint, jfloat, jfloat, jint); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: showOverview + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_showOverview + (JNIEnv *, jobject); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: nextSample + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_nextSample + (JNIEnv *, jobject); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: previousSample + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_previousSample + (JNIEnv *, jobject); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: goToSample + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_goToSample + (JNIEnv *, jobject, jint); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: toggleRenderingMode + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleRenderingMode + (JNIEnv *, jobject); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: toggleSlideshow + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleSlideshow + (JNIEnv *, jobject); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: toggleFPS + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleFPS + (JNIEnv *, jobject); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: toggleTiling + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleTiling + (JNIEnv *, jobject); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: toggleBBox + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleBBox + (JNIEnv *, jobject); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: processSkEvent + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_processSkEvent + (JNIEnv *, jobject); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: serviceQueueTimer + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_serviceQueueTimer + (JNIEnv *, jobject); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: saveToPdf + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_saveToPDF + (JNIEnv *, jobject); + +/* + * Class: com_skia_SkiaSampleRenderer + * Method: postInval + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_postInval + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/platform_tools/android/apps/sample_app/src/main/res/drawable-hdpi/ic_btn_find_next.png b/platform_tools/android/apps/sample_app/src/main/res/drawable-hdpi/ic_btn_find_next.png new file mode 100644 index 0000000..b696a6b Binary files /dev/null and b/platform_tools/android/apps/sample_app/src/main/res/drawable-hdpi/ic_btn_find_next.png differ diff --git a/platform_tools/android/apps/sample_app/src/main/res/drawable-hdpi/ic_btn_find_prev.png b/platform_tools/android/apps/sample_app/src/main/res/drawable-hdpi/ic_btn_find_prev.png new file mode 100644 index 0000000..5550c5a Binary files /dev/null and b/platform_tools/android/apps/sample_app/src/main/res/drawable-hdpi/ic_btn_find_prev.png differ diff --git a/platform_tools/android/apps/sample_app/src/main/res/layout/layout.xml b/platform_tools/android/apps/sample_app/src/main/res/layout/layout.xml new file mode 100644 index 0000000..cdb90e9 --- /dev/null +++ b/platform_tools/android/apps/sample_app/src/main/res/layout/layout.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/platform_tools/android/apps/sample_app/src/main/res/menu/action_bar.xml b/platform_tools/android/apps/sample_app/src/main/res/menu/action_bar.xml new file mode 100644 index 0000000..72e135e --- /dev/null +++ b/platform_tools/android/apps/sample_app/src/main/res/menu/action_bar.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/platform_tools/android/apps/sample_app/src/main/res/values/strings.xml b/platform_tools/android/apps/sample_app/src/main/res/values/strings.xml new file mode 100644 index 0000000..f9ec6a0 --- /dev/null +++ b/platform_tools/android/apps/sample_app/src/main/res/values/strings.xml @@ -0,0 +1,17 @@ + + + Skia Samples + Overview + Toggle Rendering + Slideshow + FPS + Toggle Tiling + Toggle SKP BBox + Save to PDF + View saved as PDF to directory \"/sdcard\" + Set OpenGL Context Type + OpenGL ES + OpenGL ES, MSAA4 + OpenGL + OpenGL, MSAA4 + diff --git a/platform_tools/android/apps/settings.gradle b/platform_tools/android/apps/settings.gradle index faa3934..9d23bff 100644 --- a/platform_tools/android/apps/settings.gradle +++ b/platform_tools/android/apps/settings.gradle @@ -1,2 +1,3 @@ +include ':sample_app' include ':canvasproof' include ':viewer' diff --git a/platform_tools/android/gyp/dependencies.gypi b/platform_tools/android/gyp/dependencies.gypi index 55f9576..14f73bf 100644 --- a/platform_tools/android/gyp/dependencies.gypi +++ b/platform_tools/android/gyp/dependencies.gypi @@ -89,5 +89,37 @@ ], }, }, + { + # This target is a dependency for Skia Sample application which runs on + # Android. Since Android requires us to load native code in shared + # libraries, we need a common entry point to wrap around main(). Here + # we also change the type of all would-be executables to be shared + # libraries. The alternative would be to introduce a condition in every + # executable target which changes to a shared library if the target OS is + # Android. This is nicer because the switch is in one place. + 'target_name': 'Android_SampleApp', + 'type': 'static_library', + 'direct_dependent_settings': { + 'target_conditions': [ + # '_type' is an 'automatic variable' which is defined for any + # target which defines a key-value pair with 'type' as the key (so, + # all of them). Conditionals inside 'target_conditions' are evaluated + # *after* all other definitions and conditionals are evaluated, so + # we're guaranteed that '_type' will be defined when we get here. + # For more info, see: + # - http://code.google.com/p/gyp/wiki/InputFormatReference#Variables + # - http://codereview.appspot.com/6353065/ + ['_type == "executable"', { + 'type': 'shared_library', + }], + ], + 'cflags': [ + '-Wno-unused-private-field', + ], + 'sources': [ + '../apps/sample_app/src/main/jni/com_skia_SkiaSampleRenderer.cpp', + ], + }, + }, ] } diff --git a/platform_tools/android/gyp/skia_android.gypi b/platform_tools/android/gyp/skia_android.gypi index 87c4714..fe535b3 100644 --- a/platform_tools/android/gyp/skia_android.gypi +++ b/platform_tools/android/gyp/skia_android.gypi @@ -51,4 +51,72 @@ 'canvasproof.gypi', 'viewer.gypi', ], + 'targets': [ + { + 'target_name': 'CopySampleAppDeps', + 'type': 'none', + 'dependencies': [ + 'skia_lib.gyp:skia_lib', + 'SampleApp.gyp:SampleApp', + ], + 'copies': [ + # Copy all shared libraries into the Android app's libs folder. Note + # that this copy requires us to build SkiaAndroidApp after those + # libraries, so that they exist by the time it occurs. If there are no + # libraries to copy, this will cause an error in Make, but the app will + # still build. + { + 'destination': '<(android_base)/apps/sample_app/src/main/libs/<(android_arch)', + 'conditions': [ + [ 'skia_shared_lib', { + 'files': [ + '<(SHARED_LIB_DIR)/libSampleApp.so', + '<(SHARED_LIB_DIR)/libskia_android.so', + ]}, { + 'files': [ + '<(SHARED_LIB_DIR)/libSampleApp.so', + ]} + ], + ], + }, + ], + }, + { + 'target_name': 'SampleApp_APK', + 'type': 'none', + 'dependencies': [ + 'CopySampleAppDeps', + ], + 'actions': [ + { + 'action_name': 'SampleApp_apk', + 'inputs': [ + '<(android_base)/apps/sample_app/src/main/AndroidManifest.xml', + '<(android_base)/apps/sample_app/src/main/jni/com_skia_SkiaSampleRenderer.h', + '<(android_base)/apps/sample_app/src/main/jni/com_skia_SkiaSampleRenderer.cpp', + '<(android_base)/apps/sample_app/src/main/java/com/skia/SkiaSampleActivity.java', + '<(android_base)/apps/sample_app/src/main/java/com/skia/SkiaSampleRenderer.java', + '<(android_base)/apps/sample_app/src/main/java/com/skia/SkiaSampleView.java', + '<(android_base)/apps/sample_app/src/main/libs/<(android_arch)/libSampleApp.so', + ], + 'conditions': [ + [ 'skia_shared_lib', { + 'inputs': [ + '<(android_base)/apps/sample_app/src/main/libs/<(android_arch)/libskia_android.so', + ], + }], + ], + 'outputs': [ + '<(android_base)/apps/sample_app/build/outputs/apk/sample_app-<(android_variant)-<(android_apk_suffix)', + ], + 'action': [ + '<(android_base)/apps/gradlew', + ':sample_app:assemble<(android_variant)<(android_buildtype)', + '-p<(android_base)/apps/sample_app', + '-PsuppressNativeBuild', + ], + }, + ], + }, + ], }