Implement Raster Backend on Android Viewer App
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2041193004
Review-Url: https://codereview.chromium.org/2041193004
diff --git a/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/StateAdapter.java b/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/StateAdapter.java
index d546c7b..5ee68ef 100644
--- a/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/StateAdapter.java
+++ b/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/StateAdapter.java
@@ -1,6 +1,7 @@
package org.skia.viewer;
import android.view.LayoutInflater;
+import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -30,6 +31,7 @@
static final String NAME = "name";
static final String VALUE = "value";
static final String OPTIONS = "options";
+ private static final String BACKEND_STATE_NAME = "Backend";
ViewerActivity mViewerActivity;
LinearLayout mLayout;
@@ -146,6 +148,21 @@
stateItem.setTag(null); // Reset the tag to let updateDrawer update this item view.
mViewerActivity.onStateChanged(stateName, stateValue);
}
+
+ // Due to the current Android limitation, we're required to recreate the SurfaceView for
+ // switching to/from the Raster backend.
+ // (Although we can switch between GPU backend without recreating the SurfaceView.)
+ final Object oldValue = stateItem.getTag(R.integer.value_tag_key);
+ if (stateName.equals(BACKEND_STATE_NAME)
+ && oldValue != null && !stateValue.equals(oldValue)) {
+ LinearLayout mainLayout = (LinearLayout) mViewerActivity.findViewById(R.id.mainLayout);
+ mainLayout.removeAllViews();
+ SurfaceView surfaceView = new SurfaceView(mViewerActivity);
+ surfaceView.setId(R.id.surfaceView);
+ surfaceView.getHolder().addCallback(mViewerActivity);
+ surfaceView.setOnTouchListener(mViewerActivity);
+ mainLayout.addView(surfaceView);
+ }
}
@Override
diff --git a/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerActivity.java b/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerActivity.java
index ce5bb0d..0291f5e 100644
--- a/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerActivity.java
+++ b/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerActivity.java
@@ -32,7 +32,6 @@
private ListView mDrawerList;
private StateAdapter mStateAdapter;
- private SurfaceView mView;
private ViewerApplication mApplication;
private native void onSurfaceCreated(long handle, Surface surface);
@@ -74,10 +73,9 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- mView = (SurfaceView) findViewById(R.id.surfaceView);
- mView.getHolder().addCallback(this);
-
- mView.setOnTouchListener(this);
+ SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
+ surfaceView.getHolder().addCallback(this);
+ surfaceView.setOnTouchListener(this);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp
index de4c4cc..7015dad 100644
--- a/tools/viewer/Viewer.cpp
+++ b/tools/viewer/Viewer.cpp
@@ -57,7 +57,8 @@
const char *kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = {
" [OpenGL]",
- " [Vulkan]"
+ " [Vulkan]",
+ " [Raster]"
};
const char* kName = "name";
diff --git a/tools/viewer/sk_app/RasterWindowContext.h b/tools/viewer/sk_app/RasterWindowContext.h
new file mode 100644
index 0000000..f116b8e
--- /dev/null
+++ b/tools/viewer/sk_app/RasterWindowContext.h
@@ -0,0 +1,29 @@
+
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef RasterWindowContext_DEFINED
+#define RasterWindowContext_DEFINED
+
+#include "WindowContext.h"
+
+namespace sk_app {
+
+class RasterWindowContext : public WindowContext {
+public:
+ // This is defined in the platform .cpp file
+ static RasterWindowContext* Create(void* platformData, const DisplayParams& params);
+
+ // Explicitly convert nullptr to GrBackendContext is needed for compiling
+ GrBackendContext getBackendContext() override { return (GrBackendContext) nullptr; }
+
+protected:
+ bool isGpuContext() override { return false; }
+};
+
+} // namespace sk_app
+
+#endif
diff --git a/tools/viewer/sk_app/Window.h b/tools/viewer/sk_app/Window.h
index 29c85b9..8b1378a 100644
--- a/tools/viewer/sk_app/Window.h
+++ b/tools/viewer/sk_app/Window.h
@@ -42,8 +42,9 @@
enum BackendType {
kNativeGL_BackendType,
kVulkan_BackendType,
+ kRaster_BackendType,
- kLast_BackendType = kVulkan_BackendType
+ kLast_BackendType = kRaster_BackendType
};
enum {
kBackendTypeCount = kLast_BackendType + 1
diff --git a/tools/viewer/sk_app/android/RasterWindowContext_android.cpp b/tools/viewer/sk_app/android/RasterWindowContext_android.cpp
new file mode 100644
index 0000000..306f291
--- /dev/null
+++ b/tools/viewer/sk_app/android/RasterWindowContext_android.cpp
@@ -0,0 +1,69 @@
+
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "RasterWindowContext_android.h"
+
+#include "SkSurface.h"
+#include "SkTypes.h"
+
+#include "Window_android.h"
+
+namespace sk_app {
+
+RasterWindowContext* RasterWindowContext::Create(void* platformData, const DisplayParams& params) {
+ RasterWindowContext* ctx = new RasterWindowContext_android(platformData, params);
+ if (!ctx->isValid()) {
+ delete ctx;
+ ctx = nullptr;
+ }
+ return ctx;
+}
+
+RasterWindowContext_android::RasterWindowContext_android(
+ void* platformData, const DisplayParams& params) {
+ fDisplayParams = params;
+ ContextPlatformData_android* androidPlatformData =
+ reinterpret_cast<ContextPlatformData_android*>(platformData);
+ fNativeWindow = androidPlatformData->fNativeWindow;
+ fWidth = ANativeWindow_getWidth(fNativeWindow);
+ fHeight = ANativeWindow_getHeight(fNativeWindow);
+ int32_t format;
+ switch(params.fColorType) {
+ case kRGBA_8888_SkColorType:
+ format = WINDOW_FORMAT_RGBA_8888;
+ break;
+ case kRGB_565_SkColorType:
+ format = WINDOW_FORMAT_RGB_565;
+ break;
+ default:
+ SkDEBUGFAIL("Unsupported Android color type");
+ }
+ ANativeWindow_setBuffersGeometry(fNativeWindow, fWidth, fHeight, format);
+}
+
+sk_sp<SkSurface> RasterWindowContext_android::getBackbufferSurface() {
+ if (nullptr == fBackbufferSurface) {
+ ANativeWindow_lock(fNativeWindow, &fBuffer, &fBounds);
+ const int bytePerPixel = fBuffer.format == WINDOW_FORMAT_RGB_565 ? 2 : 4;
+ SkImageInfo info = SkImageInfo::Make(fWidth, fHeight,
+ fDisplayParams.fColorType,
+ kOpaque_SkAlphaType,
+ fDisplayParams.fProfileType);
+ fBackbufferSurface = SkSurface::MakeRasterDirect(
+ info, fBuffer.bits, fBuffer.stride * bytePerPixel, nullptr);
+ }
+ return fBackbufferSurface;
+}
+
+
+void RasterWindowContext_android::swapBuffers() {
+ ANativeWindow_unlockAndPost(fNativeWindow);
+ fBackbufferSurface.reset(nullptr);
+}
+
+} // namespace sk_app
diff --git a/tools/viewer/sk_app/android/RasterWindowContext_android.h b/tools/viewer/sk_app/android/RasterWindowContext_android.h
new file mode 100644
index 0000000..913b06c
--- /dev/null
+++ b/tools/viewer/sk_app/android/RasterWindowContext_android.h
@@ -0,0 +1,43 @@
+
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef RasterWindowContext_android_DEFINED
+#define RasterWindowContext_android_DEFINED
+
+#include <android/native_window_jni.h>
+
+#include "../RasterWindowContext.h"
+
+namespace sk_app {
+
+class RasterWindowContext_android : public RasterWindowContext {
+public:
+ friend RasterWindowContext* RasterWindowContext::Create(
+ void* platformData, const DisplayParams&);
+
+ sk_sp<SkSurface> getBackbufferSurface() override;
+ void swapBuffers() override;
+
+ bool isValid() override { return SkToBool(fNativeWindow); }
+ void resize(uint32_t w, uint32_t h) override {
+ SkDEBUGFAIL("Resize is currently unsupported.");
+ }
+ void setDisplayParams(const DisplayParams& params) override {
+ SkDEBUGFAIL("setDisplayParams is currently unsupported.");
+ }
+
+private:
+ RasterWindowContext_android(void* platformData, const DisplayParams& params);
+ sk_sp<SkSurface> fBackbufferSurface = nullptr;
+ ANativeWindow* fNativeWindow = nullptr;
+ ANativeWindow_Buffer fBuffer;
+ ARect fBounds;
+};
+
+} // namespace sk_app
+
+#endif
diff --git a/tools/viewer/sk_app/android/Window_android.cpp b/tools/viewer/sk_app/android/Window_android.cpp
index 926c7cd..94ba9b0 100644
--- a/tools/viewer/sk_app/android/Window_android.cpp
+++ b/tools/viewer/sk_app/android/Window_android.cpp
@@ -8,6 +8,7 @@
#include "Window_android.h"
#include "../GLWindowContext.h"
#include "../VulkanWindowContext.h"
+#include "../RasterWindowContext.h"
namespace sk_app {
@@ -49,11 +50,7 @@
fBackendType = attachType;
fDisplayParams = params;
- if (fNativeWindow) {
- this->initDisplay(fNativeWindow);
- }
- // If fNativeWindow is not set,
- // we delay the creation of fWindowContext until Android informs us that
+ // We delay the creation of fWindowContext until Android informs us that
// the native window is ready to use.
// The creation will be done in initDisplay, which is initiated by kSurfaceCreated event.
return true;
@@ -61,14 +58,15 @@
void Window_android::initDisplay(ANativeWindow* window) {
SkASSERT(window);
- fNativeWindow = window;
ContextPlatformData_android platformData;
platformData.fNativeWindow = window;
switch (fBackendType) {
case kNativeGL_BackendType:
fWindowContext = GLWindowContext::Create((void*)&platformData, fDisplayParams);
break;
-
+ case kRaster_BackendType:
+ fWindowContext = RasterWindowContext::Create((void*)&platformData, fDisplayParams);
+ break;
case kVulkan_BackendType:
default:
fWindowContext = VulkanWindowContext::Create((void*)&platformData, fDisplayParams);
@@ -78,7 +76,6 @@
void Window_android::onDisplayDestroyed() {
detach();
- fNativeWindow = nullptr;
}
void Window_android::onInval() {
diff --git a/tools/viewer/sk_app/android/Window_android.h b/tools/viewer/sk_app/android/Window_android.h
index 2a7ff47..10c35d0 100644
--- a/tools/viewer/sk_app/android/Window_android.h
+++ b/tools/viewer/sk_app/android/Window_android.h
@@ -44,9 +44,6 @@
void setContentRect(int l, int t, int r, int b) { fContentRect.set(l,t,r,b); }
private:
- // We need fNativeWindow for attaching with another backend.
- // (in that case, attach is called without initDisplay being called later)
- ANativeWindow* fNativeWindow = nullptr;
SkiaAndroidApp* fSkiaAndroidApp = nullptr;
SkRect fContentRect;
DisplayParams fDisplayParams;