From d94ad5823b7da7f115e997d12828314e290981f6 Mon Sep 17 00:00:00 2001 From: liyuqian Date: Tue, 7 Jun 2016 14:22:37 -0700 Subject: [PATCH] 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 --- .../java/org/skia/viewer/StateAdapter.java | 17 +++++ .../java/org/skia/viewer/ViewerActivity.java | 8 +-- tools/viewer/Viewer.cpp | 3 +- tools/viewer/sk_app/RasterWindowContext.h | 29 ++++++++ tools/viewer/sk_app/Window.h | 3 +- .../android/RasterWindowContext_android.cpp | 69 +++++++++++++++++++ .../android/RasterWindowContext_android.h | 43 ++++++++++++ .../viewer/sk_app/android/Window_android.cpp | 13 ++-- tools/viewer/sk_app/android/Window_android.h | 3 - 9 files changed, 170 insertions(+), 18 deletions(-) create mode 100644 tools/viewer/sk_app/RasterWindowContext.h create mode 100644 tools/viewer/sk_app/android/RasterWindowContext_android.cpp create mode 100644 tools/viewer/sk_app/android/RasterWindowContext_android.h 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 d546c7bb3e..5ee68efc3c 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 @@ public class StateAdapter extends BaseAdapter implements AdapterView.OnItemSelec 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 @@ public class StateAdapter extends BaseAdapter implements AdapterView.OnItemSelec 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 ce5bb0deda..0291f5e291 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 @@ public class ViewerActivity private ListView mDrawerList; private StateAdapter mStateAdapter; - private SurfaceView mView; private ViewerApplication mApplication; private native void onSurfaceCreated(long handle, Surface surface); @@ -74,10 +73,9 @@ public class ViewerActivity 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 de4c4cce30..7015dad458 100644 --- a/tools/viewer/Viewer.cpp +++ b/tools/viewer/Viewer.cpp @@ -57,7 +57,8 @@ DEFINE_bool(vulkan, true, "Run with Vulkan."); 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 0000000000..f116b8eb15 --- /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 29c85b9e78..8b1378a80f 100644 --- a/tools/viewer/sk_app/Window.h +++ b/tools/viewer/sk_app/Window.h @@ -42,8 +42,9 @@ public: 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 0000000000..306f291de8 --- /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(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 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 0000000000..913b06c9dd --- /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 + +#include "../RasterWindowContext.h" + +namespace sk_app { + +class RasterWindowContext_android : public RasterWindowContext { +public: + friend RasterWindowContext* RasterWindowContext::Create( + void* platformData, const DisplayParams&); + + sk_sp 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 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 926c7cd17d..94ba9b00df 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 @@ bool Window_android::attach(BackendType attachType, const DisplayParams& params) 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 @@ bool Window_android::attach(BackendType attachType, const DisplayParams& params) 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::initDisplay(ANativeWindow* window) { 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 2a7ff4730a..10c35d0122 100644 --- a/tools/viewer/sk_app/android/Window_android.h +++ b/tools/viewer/sk_app/android/Window_android.h @@ -44,9 +44,6 @@ public: 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;