diff options
Diffstat (limited to 'platform_tools/android/apps/visualbench')
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; + } + } +} |