aboutsummaryrefslogtreecommitdiffhomepage
path: root/platform_tools/android/apps/visualbench
diff options
context:
space:
mode:
Diffstat (limited to 'platform_tools/android/apps/visualbench')
-rw-r--r--platform_tools/android/apps/visualbench/build.gradle46
-rw-r--r--platform_tools/android/apps/visualbench/src/main/AndroidManifest.xml29
-rw-r--r--platform_tools/android/apps/visualbench/src/main/java/com/skia/VisualBenchActivity.java49
-rw-r--r--platform_tools/android/apps/visualbench/src/main/jni/SkOSWindow_AndroidNative.cpp187
-rw-r--r--platform_tools/android/apps/visualbench/src/main/jni/main.cpp134
5 files changed, 445 insertions, 0 deletions
diff --git a/platform_tools/android/apps/visualbench/build.gradle b/platform_tools/android/apps/visualbench/build.gradle
new file mode 100644
index 0000000000..81322b026e
--- /dev/null
+++ b/platform_tools/android/apps/visualbench/build.gradle
@@ -0,0 +1,46 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 19
+ buildToolsVersion "22.0.1"
+
+ defaultConfig {
+ applicationId "com.skia.visualbench"
+ minSdkVersion 9
+ targetSdkVersion 19
+ versionCode 1
+ versionName "1.0"
+ }
+
+ 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
+ applicationVariants.all{ variant ->
+
+ def buildNativeLib = task("${variant.name}_NativeLib", type:Exec) {
+ workingDir '../../../..' // top-level skia directory
+ commandLine constructBuildCommand(variant, "CopyVisualBenchDeps").split()
+ environment PATH: getPathWithDepotTools()
+ environment ANDROID_SDK_ROOT: getSDKPath()
+ }
+
+ if (!hasProperty("suppressNativeBuild")) {
+ TaskCollection<Task> assembleTask
+ assembleTask = project.tasks.matching {
+ it.name.contains("assemble") &&
+ it.name.toLowerCase().endsWith(variant.name.toLowerCase())
+ }
+ assembleTask.getAt(0).dependsOn buildNativeLib
+ }
+ }
+} \ No newline at end of file
diff --git a/platform_tools/android/apps/visualbench/src/main/AndroidManifest.xml b/platform_tools/android/apps/visualbench/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..c15dee6e16
--- /dev/null
+++ b/platform_tools/android/apps/visualbench/src/main/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- BEGIN_INCLUDE(manifest) -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.skia"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <!-- This is the platform API where NativeActivity was introduced. -->
+ <uses-sdk android:minSdkVersion="9" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.ACCESS_ALL_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+ <application android:label="VisualBenchActivity">
+ <activity android:name=".VisualBenchActivity"
+ android:label="VisualBenchActivity"
+ android:configChanges="orientation|keyboardHidden"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
+ <meta-data android:name="android.app.lib_name"
+ android:value="visualbench" />
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
+<!-- END_INCLUDE(manifest) -->
diff --git a/platform_tools/android/apps/visualbench/src/main/java/com/skia/VisualBenchActivity.java b/platform_tools/android/apps/visualbench/src/main/java/com/skia/VisualBenchActivity.java
new file mode 100644
index 0000000000..90f70bfe0a
--- /dev/null
+++ b/platform_tools/android/apps/visualbench/src/main/java/com/skia/VisualBenchActivity.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2015 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.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.View;
+import android.view.WindowManager;
+
+public class VisualBenchActivity extends android.app.NativeActivity {
+ static {
+ System.loadLibrary("skia_android");
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ // Setup a bunch of window parameters. We have to do this here to prevent our backend from
+ // getting spurious term / init messages when we relayout
+
+ // Layout fullscreen and keep screen on
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
+ WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+ getWindow().getDecorView().setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar
+ View.SYSTEM_UI_FLAG_FULLSCREEN |// hide status bar
+ View.SYSTEM_UI_FLAG_IMMERSIVE);
+
+ // Disable backlight to keep the system as cool as possible
+ // TODO make this configurable
+ Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE,
+ Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+
+ WindowManager.LayoutParams lp = getWindow().getAttributes();
+ lp.screenBrightness = 0; // 0f - no backlight
+ getWindow().setAttributes(lp);
+ }
+}
diff --git a/platform_tools/android/apps/visualbench/src/main/jni/SkOSWindow_AndroidNative.cpp b/platform_tools/android/apps/visualbench/src/main/jni/SkOSWindow_AndroidNative.cpp
new file mode 100644
index 0000000000..e2bc99610f
--- /dev/null
+++ b/platform_tools/android/apps/visualbench/src/main/jni/SkOSWindow_AndroidNative.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkOSWindow_Android.h"
+
+#include <GLES/gl.h>
+
+SkOSWindow::SkOSWindow(void* hwnd) {
+ fWindow.fDisplay = EGL_NO_DISPLAY;
+ fWindow.fContext = EGL_NO_CONTEXT;
+ fWindow.fSurface = EGL_NO_SURFACE;
+ fNativeWindow = (ANativeWindow*)hwnd;
+ fDestroyRequested = false;
+}
+
+SkOSWindow::~SkOSWindow() {
+ if (fWindow.fDisplay != EGL_NO_DISPLAY) {
+ eglMakeCurrent(fWindow.fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (fWindow.fContext != EGL_NO_CONTEXT) {
+ eglDestroyContext(fWindow.fDisplay, fWindow.fContext);
+ }
+ if (fWindow.fSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(fWindow.fDisplay, fWindow.fSurface);
+ }
+ eglTerminate(fWindow.fDisplay);
+ }
+ fWindow.fDisplay = EGL_NO_DISPLAY;
+ fWindow.fContext = EGL_NO_CONTEXT;
+ fWindow.fSurface = EGL_NO_SURFACE;
+}
+
+bool SkOSWindow::attach(SkBackEndTypes attachType,
+ int /*msaaSampleCount*/,
+ AttachmentInfo* info) {
+ static const EGLint kEGLContextAttribsForOpenGL[] = {
+ EGL_NONE
+ };
+
+ static const EGLint kEGLContextAttribsForOpenGLES[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ static const struct {
+ const EGLint* fContextAttribs;
+ EGLenum fAPI;
+ EGLint fRenderableTypeBit;
+ } kAPIs[] = {
+ { // OpenGL
+ kEGLContextAttribsForOpenGL,
+ EGL_OPENGL_API,
+ EGL_OPENGL_BIT,
+ },
+ { // OpenGL ES. This seems to work for both ES2 and 3 (when available).
+ kEGLContextAttribsForOpenGLES,
+ EGL_OPENGL_ES_API,
+ EGL_OPENGL_ES2_BIT,
+ },
+ };
+
+ size_t apiLimit = SK_ARRAY_COUNT(kAPIs);
+
+ for (size_t api = 0; api < apiLimit; ++api) {
+ EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+
+ EGLint majorVersion;
+ EGLint minorVersion;
+ eglInitialize(display, &majorVersion, &minorVersion);
+
+#if 0
+ SkDebugf("VENDOR: %s\n", eglQueryString(fDisplay, EGL_VENDOR));
+ SkDebugf("APIS: %s\n", eglQueryString(fDisplay, EGL_CLIENT_APIS));
+ SkDebugf("VERSION: %s\n", eglQueryString(fDisplay, EGL_VERSION));
+ SkDebugf("EXTENSIONS %s\n", eglQueryString(fDisplay, EGL_EXTENSIONS));
+#endif
+
+ if (!eglBindAPI(kAPIs[api].fAPI)) {
+ continue;
+ }
+
+ const EGLint configAttribs[] = {
+ EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+ EGL_RENDERABLE_TYPE, kAPIs[api].fRenderableTypeBit,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_NONE
+ };
+
+ EGLint format;
+ EGLint numConfigs;
+ EGLConfig config;
+ EGLSurface surface;
+ EGLContext context;
+
+ /* Here, the application chooses the configuration it desires. In this
+ * sample, we have a very simplified selection process, where we pick
+ * the first EGLConfig that matches our criteria */
+ eglChooseConfig(display, configAttribs, &config, 1, &numConfigs);
+
+ /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
+ * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
+ * As soon as we picked a EGLConfig, we can safely reconfigure the
+ * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
+ eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
+
+ ANativeWindow_setBuffersGeometry(fNativeWindow, 0, 0, format);
+
+ surface = eglCreateWindowSurface(display, config, fNativeWindow, NULL);
+ context = eglCreateContext(display, config, NULL, kAPIs[api].fContextAttribs);
+ if (EGL_NO_CONTEXT == context) {
+ SkDebugf("eglCreateContext failed. EGL Error: 0x%08x\n", eglGetError());
+ continue;
+ }
+
+ if (!eglMakeCurrent(display, surface, surface, context)) {
+ SkDebugf("eglMakeCurrent failed. EGL Error: 0x%08x\n", eglGetError());
+ continue;
+ }
+
+ fWindow.fDisplay = display;
+ fWindow.fContext = context;
+ fWindow.fSurface = surface;
+ }
+
+ if (fWindow.fDisplay && fWindow.fContext && fWindow.fSurface) {
+ EGLint w, h;
+ eglQuerySurface(fWindow.fDisplay, fWindow.fSurface, EGL_WIDTH, &w);
+ eglQuerySurface(fWindow.fDisplay, fWindow.fSurface, EGL_HEIGHT, &h);
+
+ glViewport(0, 0, w, h);
+ glClearColor(0.0, 0, 0, 0.0);
+ glClearStencil(0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ // We retrieve the fullscreen width and height
+ this->setSize((SkScalar)w, (SkScalar)h);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void SkOSWindow::detach() {
+ fDestroyRequested = true;
+}
+
+void SkOSWindow::present() {
+ if (fWindow.fDisplay != EGL_NO_DISPLAY && fWindow.fContext != EGL_NO_CONTEXT) {
+ eglSwapBuffers(fWindow.fDisplay, fWindow.fSurface);
+ }
+}
+
+void SkOSWindow::closeWindow() {
+ fDestroyRequested = true;
+}
+
+void SkOSWindow::setVsync(bool vsync) {
+ if (fWindow.fDisplay != EGL_NO_DISPLAY) {
+ int swapInterval = vsync ? 1 : 0;
+ eglSwapInterval(fWindow.fDisplay, swapInterval);
+ }
+}
+
+void SkOSWindow::onSetTitle(const char title[]) {
+}
+
+void SkOSWindow::onHandleInval(const SkIRect& rect) {
+}
+
+void SkOSWindow::onPDFSaved(const char title[], const char desc[], const char path[]) {
+}
+
+///////////////////////////////////////////
+/////////////// SkEvent impl //////////////
+///////////////////////////////////////////
+
+void SkEvent::SignalQueueTimer(SkMSec ms) {
+}
+
+void SkEvent::SignalNonEmptyQueue() {
+}
diff --git a/platform_tools/android/apps/visualbench/src/main/jni/main.cpp b/platform_tools/android/apps/visualbench/src/main/jni/main.cpp
new file mode 100644
index 0000000000..2ea6b76b39
--- /dev/null
+++ b/platform_tools/android/apps/visualbench/src/main/jni/main.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+#include <android_native_app_glue.h>
+
+#include "SkApplication.h"
+#include "VisualBench.h"
+
+/**
+ * Shared state for our app.
+ */
+enum State {
+ kInit_State,
+ kAnimate_State,
+ kDestroyRequested_State,
+ kFinished_State,
+};
+
+struct VisualBenchState {
+ VisualBenchState() : fApp(NULL), fWindow(NULL), fState(kInit_State) {}
+ struct android_app* fApp;
+ SkOSWindow* fWindow;
+ SkTArray<SkString> fFlags;
+ State fState;
+};
+
+static void handle_cmd(struct android_app* app, int32_t cmd) {
+ struct VisualBenchState* state = (struct VisualBenchState*)app->userData;
+ switch (cmd) {
+ case APP_CMD_INIT_WINDOW:
+ // The window is being shown, get it ready.
+ if (state->fApp->window != NULL && kInit_State == state->fState) {
+ // drain any events that occurred before |window| was assigned.
+ while (SkEvent::ProcessEvent());
+
+ // Start normal Skia sequence
+ application_init();
+
+ SkTArray<const char*> args;
+ args.push_back("VisualBench");
+ for (int i = 0; i < state->fFlags.count(); i++) {
+ SkDebugf(state->fFlags[i].c_str());
+ args.push_back(state->fFlags[i].c_str());
+ }
+
+ state->fWindow = create_sk_window((void*)state->fApp->window,
+ args.count(),
+ const_cast<char**>(args.begin()));
+ state->fWindow->forceInvalAll();
+ state->fState = kAnimate_State;
+ }
+ break;
+ case APP_CMD_TERM_WINDOW:
+ state->fState = kDestroyRequested_State;
+ break;
+ }
+}
+
+void android_main(struct android_app* state) {
+ struct VisualBenchState visualBenchState;
+
+ // Make sure glue isn't stripped.
+ app_dummy();
+
+ state->userData = &visualBenchState;
+ state->onAppCmd = handle_cmd;
+ visualBenchState.fApp = state;
+
+ // Get command line arguments
+ JavaVM* jvm = state->activity->vm;
+ JNIEnv *env;
+ jvm->AttachCurrentThread(&env, 0);
+
+ jobject me = state->activity->clazz;
+
+ jclass acl = env->GetObjectClass(me); //class pointer of NativeActivity
+ jmethodID giid = env->GetMethodID(acl, "getIntent", "()Landroid/content/Intent;");
+ jobject intent = env->CallObjectMethod(me, giid); //Got our intent
+
+ jclass icl = env->GetObjectClass(intent); //class pointer of Intent
+ jmethodID gseid = env->GetMethodID(icl, "getStringExtra",
+ "(Ljava/lang/String;)Ljava/lang/String;");
+
+ jstring jsParam1 = (jstring)env->CallObjectMethod(intent, gseid,
+ env->NewStringUTF("cmdLineFlags"));
+ if (jsParam1) {
+ const char* flags = env->GetStringUTFChars(jsParam1, 0);
+ SkStrSplit(flags, " ", &visualBenchState.fFlags);
+ env->ReleaseStringUTFChars(jsParam1, flags);
+ }
+ jvm->DetachCurrentThread();
+
+ while (1) {
+ // Read all pending events.
+ int ident;
+ int events;
+ struct android_poll_source* source;
+
+ // We loop until all events are read, then continue to draw the next frame of animation.
+ while ((ident=ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0) {
+ // Process this event.
+ if (source != NULL) {
+ source->process(state, source);
+ }
+
+ // Check if we are exiting.
+ if (state->destroyRequested != 0) {
+ return;
+ }
+
+ }
+
+ if (visualBenchState.fWindow) {
+ if (visualBenchState.fWindow->destroyRequested()) {
+ visualBenchState.fState = kDestroyRequested_State;
+ } else {
+ visualBenchState.fWindow->update(NULL);
+ }
+ }
+
+ if (kDestroyRequested_State == visualBenchState.fState) {
+ SkDELETE(visualBenchState.fWindow);
+ visualBenchState.fWindow = NULL;
+ application_term();
+ ANativeActivity_finish(state->activity);
+ visualBenchState.fState = kFinished_State;
+ }
+ }
+}