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
This commit is contained in:
liyuqian 2016-06-07 14:22:37 -07:00 committed by Commit bot
parent 93e3fff79e
commit d94ad5823b
9 changed files with 170 additions and 18 deletions

View File

@ -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

View File

@ -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,

View File

@ -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";

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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() {

View File

@ -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;