Have RT drive window positioning
Bug: 22802885 Change-Id: I6beed5474d3a943b16e9097f7bd61ce3cbd37505
This commit is contained in:
@@ -135,6 +135,9 @@ public class RenderNode {
|
||||
private RenderNode(String name, View owningView) {
|
||||
mNativeRenderNode = nCreate(name);
|
||||
mOwningView = owningView;
|
||||
if (mOwningView instanceof SurfaceView) {
|
||||
nRequestPositionUpdates(mNativeRenderNode, (SurfaceView) mOwningView);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -854,6 +857,8 @@ public class RenderNode {
|
||||
private static native void nOutput(long renderNode);
|
||||
private static native int nGetDebugSize(long renderNode);
|
||||
|
||||
private static native void nRequestPositionUpdates(long renderNode, SurfaceView callback);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Animations
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -135,7 +135,7 @@ public class SurfaceView extends View {
|
||||
}
|
||||
};
|
||||
|
||||
final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener
|
||||
private final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener
|
||||
= new ViewTreeObserver.OnScrollChangedListener() {
|
||||
@Override
|
||||
public void onScrollChanged() {
|
||||
@@ -143,6 +143,17 @@ public class SurfaceView extends View {
|
||||
}
|
||||
};
|
||||
|
||||
private final ViewTreeObserver.OnPreDrawListener mDrawListener =
|
||||
new ViewTreeObserver.OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
// reposition ourselves where the surface is
|
||||
mHaveFrame = getWidth() > 0 && getHeight() > 0;
|
||||
updateWindow(false, false);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
boolean mRequestedVisible = false;
|
||||
boolean mWindowVisibility = false;
|
||||
boolean mViewVisibility = false;
|
||||
@@ -168,17 +179,9 @@ public class SurfaceView extends View {
|
||||
boolean mUpdateWindowNeeded;
|
||||
boolean mReportDrawNeeded;
|
||||
private Translator mTranslator;
|
||||
private int mWindowInsetLeft;
|
||||
private int mWindowInsetTop;
|
||||
|
||||
private final ViewTreeObserver.OnPreDrawListener mDrawListener =
|
||||
new ViewTreeObserver.OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
// reposition ourselves where the surface is
|
||||
mHaveFrame = getWidth() > 0 && getHeight() > 0;
|
||||
updateWindow(false, false);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
private boolean mGlobalListenersAdded;
|
||||
|
||||
public SurfaceView(Context context) {
|
||||
@@ -443,17 +446,17 @@ public class SurfaceView extends View {
|
||||
int myHeight = mRequestedHeight;
|
||||
if (myHeight <= 0) myHeight = getHeight();
|
||||
|
||||
getLocationInWindow(mLocation);
|
||||
final boolean creating = mWindow == null;
|
||||
final boolean formatChanged = mFormat != mRequestedFormat;
|
||||
final boolean sizeChanged = mWindowSpaceWidth != myWidth || mWindowSpaceHeight != myHeight;
|
||||
final boolean visibleChanged = mVisible != mRequestedVisible;
|
||||
final boolean layoutSizeChanged = getWidth() != mLayout.width
|
||||
|| getHeight() != mLayout.height;
|
||||
final boolean positionChanged = mWindowSpaceLeft != mLocation[0] || mWindowSpaceTop != mLocation[1];
|
||||
|
||||
if (force || creating || formatChanged || sizeChanged || visibleChanged
|
||||
|| mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) {
|
||||
getLocationInWindow(mLocation);
|
||||
|
||||
if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
|
||||
+ " format=" + formatChanged + " size=" + sizeChanged
|
||||
+ " visible=" + visibleChanged
|
||||
@@ -643,27 +646,69 @@ public class SurfaceView extends View {
|
||||
TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
|
||||
" w=" + mLayout.width + " h=" + mLayout.height +
|
||||
", frame=" + mSurfaceFrame);
|
||||
} else if (positionChanged || layoutSizeChanged) { // Only the position has changed
|
||||
mWindowSpaceLeft = mLocation[0];
|
||||
mWindowSpaceTop = mLocation[1];
|
||||
// For our size changed check, we keep mLayout.width and mLayout.height
|
||||
// in view local space.
|
||||
mLocation[0] = mLayout.width = getWidth();
|
||||
mLocation[1] = mLayout.height = getHeight();
|
||||
} else if (!isHardwareAccelerated()) {
|
||||
getLocationInWindow(mLocation);
|
||||
final boolean positionChanged = mWindowSpaceLeft != mLocation[0]
|
||||
|| mWindowSpaceTop != mLocation[1];
|
||||
if (positionChanged || layoutSizeChanged) { // Only the position has changed
|
||||
mWindowSpaceLeft = mLocation[0];
|
||||
mWindowSpaceTop = mLocation[1];
|
||||
// For our size changed check, we keep mLayout.width and mLayout.height
|
||||
// in view local space.
|
||||
mLocation[0] = mLayout.width = getWidth();
|
||||
mLocation[1] = mLayout.height = getHeight();
|
||||
|
||||
transformFromViewToWindowSpace(mLocation);
|
||||
transformFromViewToWindowSpace(mLocation);
|
||||
|
||||
try {
|
||||
mSession.repositionChild(mWindow, mWindowSpaceLeft, mWindowSpaceTop,
|
||||
mLocation[0], mLocation[1],
|
||||
viewRoot != null ? viewRoot.getNextFrameNumber() : -1,
|
||||
mWinFrame);
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Exception from relayout", ex);
|
||||
try {
|
||||
Log.d(TAG, String.format("updateWindowPosition UI, " +
|
||||
"postion = [%d, %d, %d, %d]", mWindowSpaceLeft, mWindowSpaceTop,
|
||||
mLocation[0], mLocation[1]));
|
||||
mSession.repositionChild(mWindow, mWindowSpaceLeft, mWindowSpaceTop,
|
||||
mLocation[0], mLocation[1], -1, mWinFrame);
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Exception from relayout", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Rect mRTLastReportedPosition = new Rect();
|
||||
|
||||
/**
|
||||
* Called by native on RenderThread to update the window position
|
||||
* @hide
|
||||
*/
|
||||
public final void updateWindowPositionRT(long frameNumber,
|
||||
int left, int top, int right, int bottom) {
|
||||
IWindowSession session = mSession;
|
||||
MyWindow window = mWindow;
|
||||
if (session == null || window == null) {
|
||||
// Guess we got detached, that sucks
|
||||
return;
|
||||
}
|
||||
if (mRTLastReportedPosition.left == left
|
||||
&& mRTLastReportedPosition.top == top
|
||||
&& mRTLastReportedPosition.right == right
|
||||
&& mRTLastReportedPosition.bottom == bottom) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, String.format("updateWindowPosition RT, frameNr = %d, " +
|
||||
"postion = [%d, %d, %d, %d]", frameNumber, left, top,
|
||||
right, bottom));
|
||||
}
|
||||
// Just using mRTLastReportedPosition as a dummy rect here
|
||||
session.repositionChild(window, left, top, right, bottom, frameNumber,
|
||||
mRTLastReportedPosition);
|
||||
// Now overwrite mRTLastReportedPosition with our values
|
||||
mRTLastReportedPosition.set(left, top, right, bottom);
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Exception from repositionChild", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private SurfaceHolder.Callback[] getSurfaceCallbacks() {
|
||||
SurfaceHolder.Callback callbacks[];
|
||||
synchronized (mCallbacks) {
|
||||
|
||||
@@ -6815,20 +6815,6 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
}
|
||||
|
||||
long getNextFrameNumber() {
|
||||
long frameNumber = -1;
|
||||
if (mSurfaceHolder != null) {
|
||||
mSurfaceHolder.mSurfaceLock.lock();
|
||||
}
|
||||
if (mSurface.isValid()) {
|
||||
frameNumber = mSurface.getNextFrameNumber();
|
||||
}
|
||||
if (mSurfaceHolder != null) {
|
||||
mSurfaceHolder.mSurfaceLock.unlock();
|
||||
}
|
||||
return frameNumber;
|
||||
}
|
||||
|
||||
class TakenSurfaceHolder extends BaseSurfaceHolder {
|
||||
@Override
|
||||
public boolean onAllowLockCanvas() {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#define LOG_TAG "OpenGLRenderer"
|
||||
#define ATRACE_TAG ATRACE_TAG_VIEW
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
@@ -24,7 +25,10 @@
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
|
||||
#include <Animator.h>
|
||||
#include <DamageAccumulator.h>
|
||||
#include <Matrix.h>
|
||||
#include <RenderNode.h>
|
||||
#include <TreeInfo.h>
|
||||
#include <Paint.h>
|
||||
|
||||
#include "core_jni_helpers.h"
|
||||
@@ -461,6 +465,69 @@ static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
|
||||
renderNode->animators().endAllStagingAnimators();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// SurfaceView position callback
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
jmethodID gSurfaceViewPositionUpdateMethod;
|
||||
|
||||
static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
|
||||
jlong renderNodePtr, jobject surfaceview) {
|
||||
class SurfaceViewPositionUpdater : public RenderNode::PositionListener {
|
||||
public:
|
||||
SurfaceViewPositionUpdater(JNIEnv* env, jobject surfaceview) {
|
||||
env->GetJavaVM(&mVm);
|
||||
mWeakRef = env->NewWeakGlobalRef(surfaceview);
|
||||
}
|
||||
|
||||
virtual ~SurfaceViewPositionUpdater() {
|
||||
jnienv()->DeleteWeakGlobalRef(mWeakRef);
|
||||
mWeakRef = nullptr;
|
||||
}
|
||||
|
||||
virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override {
|
||||
if (CC_UNLIKELY(!mWeakRef || !info.updateWindowPositions)) return;
|
||||
ATRACE_NAME("Update SurfaceView position");
|
||||
|
||||
JNIEnv* env = jnienv();
|
||||
jobject localref = env->NewLocalRef(mWeakRef);
|
||||
if (CC_UNLIKELY(!localref)) {
|
||||
jnienv()->DeleteWeakGlobalRef(mWeakRef);
|
||||
mWeakRef = nullptr;
|
||||
return;
|
||||
}
|
||||
Matrix4 transform;
|
||||
info.damageAccumulator->computeCurrentTransform(&transform);
|
||||
const RenderProperties& props = node.properties();
|
||||
uirenderer::Rect bounds(props.getWidth(), props.getHeight());
|
||||
transform.mapRect(bounds);
|
||||
bounds.left -= info.windowInsetLeft;
|
||||
bounds.right -= info.windowInsetLeft;
|
||||
bounds.top -= info.windowInsetTop;
|
||||
bounds.bottom -= info.windowInsetTop;
|
||||
env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
|
||||
(jlong) info.frameNumber, (jint) bounds.left, (jint) bounds.top,
|
||||
(jint) bounds.right, (jint) bounds.bottom);
|
||||
env->DeleteLocalRef(localref);
|
||||
}
|
||||
|
||||
private:
|
||||
JNIEnv* jnienv() {
|
||||
JNIEnv* env;
|
||||
if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
|
||||
LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm);
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
JavaVM* mVm;
|
||||
jobject mWeakRef;
|
||||
};
|
||||
|
||||
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
|
||||
renderNode->setPositionListener(new SurfaceViewPositionUpdater(env, surfaceview));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// JNI Glue
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -539,9 +606,14 @@ static const JNINativeMethod gMethods[] = {
|
||||
|
||||
{ "nAddAnimator", "(JJ)V", (void*) android_view_RenderNode_addAnimator },
|
||||
{ "nEndAllAnimators", "(J)V", (void*) android_view_RenderNode_endAllAnimators },
|
||||
|
||||
{ "nRequestPositionUpdates", "(JLandroid/view/SurfaceView;)V", (void*) android_view_RenderNode_requestPositionUpdates },
|
||||
};
|
||||
|
||||
int register_android_view_RenderNode(JNIEnv* env) {
|
||||
jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
|
||||
gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
|
||||
"updateWindowPositionRT", "(JIIII)V");
|
||||
return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
|
||||
}
|
||||
|
||||
|
||||
@@ -133,7 +133,14 @@ public:
|
||||
|
||||
virtual void prepareTree(TreeInfo& info) {
|
||||
info.errorHandler = this;
|
||||
// TODO: This is hacky
|
||||
info.windowInsetLeft = -stagingProperties().getLeft();
|
||||
info.windowInsetTop = -stagingProperties().getTop();
|
||||
info.updateWindowPositions = true;
|
||||
RenderNode::prepareTree(info);
|
||||
info.updateWindowPositions = false;
|
||||
info.windowInsetLeft = 0;
|
||||
info.windowInsetTop = 0;
|
||||
info.errorHandler = NULL;
|
||||
}
|
||||
|
||||
@@ -368,28 +375,28 @@ static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz,
|
||||
static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
|
||||
jlong proxyPtr, jobject jsurface) {
|
||||
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
|
||||
sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface);
|
||||
proxy->initialize(window);
|
||||
sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
|
||||
proxy->initialize(surface);
|
||||
}
|
||||
|
||||
static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
|
||||
jlong proxyPtr, jobject jsurface) {
|
||||
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
|
||||
sp<ANativeWindow> window;
|
||||
sp<Surface> surface;
|
||||
if (jsurface) {
|
||||
window = android_view_Surface_getNativeWindow(env, jsurface);
|
||||
surface = android_view_Surface_getSurface(env, jsurface);
|
||||
}
|
||||
proxy->updateSurface(window);
|
||||
proxy->updateSurface(surface);
|
||||
}
|
||||
|
||||
static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
|
||||
jlong proxyPtr, jobject jsurface) {
|
||||
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
|
||||
sp<ANativeWindow> window;
|
||||
sp<Surface> surface;
|
||||
if (jsurface) {
|
||||
window = android_view_Surface_getNativeWindow(env, jsurface);
|
||||
surface = android_view_Surface_getSurface(env, jsurface);
|
||||
}
|
||||
return proxy->pauseSurface(window);
|
||||
return proxy->pauseSurface(surface);
|
||||
}
|
||||
|
||||
static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
// Returns the current dirty area, *NOT* transformed by pushed transforms
|
||||
void peekAtDirty(SkRect* dest) const;
|
||||
|
||||
void computeCurrentTransform(Matrix4* outMatrix) const;
|
||||
ANDROID_API void computeCurrentTransform(Matrix4* outMatrix) const;
|
||||
|
||||
void finish(SkRect* totalDirty);
|
||||
|
||||
|
||||
@@ -381,6 +381,10 @@ void RenderNode::prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer) {
|
||||
bool childFunctorsNeedLayer = mProperties.prepareForFunctorPresence(
|
||||
willHaveFunctor, functorsNeedLayer);
|
||||
|
||||
if (CC_UNLIKELY(mPositionListener.get())) {
|
||||
mPositionListener->onPositionUpdated(*this, info);
|
||||
}
|
||||
|
||||
prepareLayer(info, animatorDirtyMask);
|
||||
if (info.mode == TreeInfo::MODE_FULL) {
|
||||
pushStagingDisplayListChanges(info);
|
||||
|
||||
@@ -209,6 +209,19 @@ public:
|
||||
OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh...
|
||||
#endif
|
||||
|
||||
class ANDROID_API PositionListener {
|
||||
public:
|
||||
virtual ~PositionListener() {}
|
||||
virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) = 0;
|
||||
};
|
||||
|
||||
// Note this is not thread safe, this needs to be called
|
||||
// before the RenderNode is used for drawing.
|
||||
// RenderNode takes ownership of the pointer
|
||||
ANDROID_API void setPositionListener(PositionListener* listener) {
|
||||
mPositionListener.reset(listener);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef key_value_pair_t<float, DrawRenderNodeOp*> ZDrawRenderNodeOpPair;
|
||||
|
||||
@@ -317,6 +330,8 @@ private:
|
||||
// This is *NOT* thread-safe, and should therefore only be tracking
|
||||
// mDisplayList, not mStagingDisplayList.
|
||||
uint32_t mParentCount;
|
||||
|
||||
std::unique_ptr<PositionListener> mPositionListener;
|
||||
}; // class RenderNode
|
||||
|
||||
} /* namespace uirenderer */
|
||||
|
||||
@@ -86,6 +86,12 @@ public:
|
||||
#endif
|
||||
ErrorHandler* errorHandler = nullptr;
|
||||
|
||||
// Frame number for use with synchronized surfaceview position updating
|
||||
int64_t frameNumber = -1;
|
||||
int32_t windowInsetLeft = 0;
|
||||
int32_t windowInsetTop = 0;
|
||||
bool updateWindowPositions = false;
|
||||
|
||||
struct Out {
|
||||
bool hasFunctors = false;
|
||||
// This is only updated if evaluateAnimations is true
|
||||
|
||||
@@ -96,18 +96,18 @@ void CanvasContext::destroy() {
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasContext::setSurface(ANativeWindow* window) {
|
||||
void CanvasContext::setSurface(Surface* surface) {
|
||||
ATRACE_CALL();
|
||||
|
||||
mNativeWindow = window;
|
||||
mNativeSurface = surface;
|
||||
|
||||
if (mEglSurface != EGL_NO_SURFACE) {
|
||||
mEglManager.destroySurface(mEglSurface);
|
||||
mEglSurface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
if (window) {
|
||||
mEglSurface = mEglManager.createSurface(window);
|
||||
if (surface) {
|
||||
mEglSurface = mEglManager.createSurface(surface);
|
||||
}
|
||||
|
||||
if (mEglSurface != EGL_NO_SURFACE) {
|
||||
@@ -131,8 +131,8 @@ void CanvasContext::setSwapBehavior(SwapBehavior swapBehavior) {
|
||||
mSwapBehavior = swapBehavior;
|
||||
}
|
||||
|
||||
void CanvasContext::initialize(ANativeWindow* window) {
|
||||
setSurface(window);
|
||||
void CanvasContext::initialize(Surface* surface) {
|
||||
setSurface(surface);
|
||||
#if !HWUI_NEW_OPS
|
||||
if (mCanvas) return;
|
||||
mCanvas = new OpenGLRenderer(mRenderThread.renderState());
|
||||
@@ -140,11 +140,11 @@ void CanvasContext::initialize(ANativeWindow* window) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void CanvasContext::updateSurface(ANativeWindow* window) {
|
||||
setSurface(window);
|
||||
void CanvasContext::updateSurface(Surface* surface) {
|
||||
setSurface(surface);
|
||||
}
|
||||
|
||||
bool CanvasContext::pauseSurface(ANativeWindow* window) {
|
||||
bool CanvasContext::pauseSurface(Surface* surface) {
|
||||
return mRenderThread.removeFrameCallback(this);
|
||||
}
|
||||
|
||||
@@ -208,6 +208,10 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
|
||||
info.renderer = mCanvas;
|
||||
#endif
|
||||
|
||||
if (CC_LIKELY(mNativeSurface.get())) {
|
||||
info.frameNumber = static_cast<int64_t>(mNativeSurface->getNextFrameNumber());
|
||||
}
|
||||
|
||||
mAnimationContext->startFrame(info.mode);
|
||||
for (const sp<RenderNode>& node : mRenderNodes) {
|
||||
// Only the primary target node will be drawn full - all other nodes would get drawn in
|
||||
@@ -223,7 +227,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
|
||||
freePrefetechedLayers();
|
||||
GL_CHECKPOINT(MODERATE);
|
||||
|
||||
if (CC_UNLIKELY(!mNativeWindow.get())) {
|
||||
if (CC_UNLIKELY(!mNativeSurface.get())) {
|
||||
mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
|
||||
info.out.canDrawThisFrame = false;
|
||||
return;
|
||||
@@ -246,8 +250,9 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
|
||||
} else {
|
||||
// We're maybe behind? Find out for sure
|
||||
int runningBehind = 0;
|
||||
mNativeWindow->query(mNativeWindow.get(),
|
||||
NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &runningBehind);
|
||||
// TODO: Have this method be on Surface, too, not just ANativeWindow...
|
||||
ANativeWindow* window = mNativeSurface.get();
|
||||
window->query(window, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &runningBehind);
|
||||
info.out.canDrawThisFrame = !runningBehind;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <SkBitmap.h>
|
||||
#include <SkRect.h>
|
||||
#include <utils/Functor.h>
|
||||
#include <gui/Surface.h>
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
@@ -74,10 +75,10 @@ public:
|
||||
// Won't take effect until next EGLSurface creation
|
||||
void setSwapBehavior(SwapBehavior swapBehavior);
|
||||
|
||||
void initialize(ANativeWindow* window);
|
||||
void updateSurface(ANativeWindow* window);
|
||||
bool pauseSurface(ANativeWindow* window);
|
||||
bool hasSurface() { return mNativeWindow.get(); }
|
||||
void initialize(Surface* surface);
|
||||
void updateSurface(Surface* surface);
|
||||
bool pauseSurface(Surface* surface);
|
||||
bool hasSurface() { return mNativeSurface.get(); }
|
||||
|
||||
void setup(int width, int height, float lightRadius,
|
||||
uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
|
||||
@@ -171,7 +172,7 @@ private:
|
||||
// lifecycle tracking
|
||||
friend class android::uirenderer::RenderState;
|
||||
|
||||
void setSurface(ANativeWindow* window);
|
||||
void setSurface(Surface* window);
|
||||
void requireSurface();
|
||||
|
||||
void freePrefetechedLayers();
|
||||
@@ -181,7 +182,7 @@ private:
|
||||
|
||||
RenderThread& mRenderThread;
|
||||
EglManager& mEglManager;
|
||||
sp<ANativeWindow> mNativeWindow;
|
||||
sp<Surface> mNativeSurface;
|
||||
EGLSurface mEglSurface = EGL_NO_SURFACE;
|
||||
bool mBufferPreserved = false;
|
||||
SwapBehavior mSwapBehavior = kSwap_default;
|
||||
|
||||
@@ -139,38 +139,38 @@ void RenderProxy::setName(const char* name) {
|
||||
postAndWait(task); // block since name/value pointers owned by caller
|
||||
}
|
||||
|
||||
CREATE_BRIDGE2(initialize, CanvasContext* context, ANativeWindow* window) {
|
||||
args->context->initialize(args->window);
|
||||
CREATE_BRIDGE2(initialize, CanvasContext* context, Surface* surface) {
|
||||
args->context->initialize(args->surface);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RenderProxy::initialize(const sp<ANativeWindow>& window) {
|
||||
void RenderProxy::initialize(const sp<Surface>& surface) {
|
||||
SETUP_TASK(initialize);
|
||||
args->context = mContext;
|
||||
args->window = window.get();
|
||||
args->surface = surface.get();
|
||||
post(task);
|
||||
}
|
||||
|
||||
CREATE_BRIDGE2(updateSurface, CanvasContext* context, ANativeWindow* window) {
|
||||
args->context->updateSurface(args->window);
|
||||
CREATE_BRIDGE2(updateSurface, CanvasContext* context, Surface* surface) {
|
||||
args->context->updateSurface(args->surface);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RenderProxy::updateSurface(const sp<ANativeWindow>& window) {
|
||||
void RenderProxy::updateSurface(const sp<Surface>& surface) {
|
||||
SETUP_TASK(updateSurface);
|
||||
args->context = mContext;
|
||||
args->window = window.get();
|
||||
args->surface = surface.get();
|
||||
postAndWait(task);
|
||||
}
|
||||
|
||||
CREATE_BRIDGE2(pauseSurface, CanvasContext* context, ANativeWindow* window) {
|
||||
return (void*) args->context->pauseSurface(args->window);
|
||||
CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) {
|
||||
return (void*) args->context->pauseSurface(args->surface);
|
||||
}
|
||||
|
||||
bool RenderProxy::pauseSurface(const sp<ANativeWindow>& window) {
|
||||
bool RenderProxy::pauseSurface(const sp<Surface>& surface) {
|
||||
SETUP_TASK(pauseSurface);
|
||||
args->context = mContext;
|
||||
args->window = window.get();
|
||||
args->surface = surface.get();
|
||||
return (bool) postAndWait(task);
|
||||
}
|
||||
|
||||
|
||||
@@ -67,9 +67,9 @@ public:
|
||||
ANDROID_API bool loadSystemProperties();
|
||||
ANDROID_API void setName(const char* name);
|
||||
|
||||
ANDROID_API void initialize(const sp<ANativeWindow>& window);
|
||||
ANDROID_API void updateSurface(const sp<ANativeWindow>& window);
|
||||
ANDROID_API bool pauseSurface(const sp<ANativeWindow>& window);
|
||||
ANDROID_API void initialize(const sp<Surface>& surface);
|
||||
ANDROID_API void updateSurface(const sp<Surface>& surface);
|
||||
ANDROID_API bool pauseSurface(const sp<Surface>& surface);
|
||||
ANDROID_API void setup(int width, int height, float lightRadius,
|
||||
uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
|
||||
ANDROID_API void setLightCenter(const Vector3& lightCenter);
|
||||
|
||||
@@ -355,6 +355,15 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="MovingSurfaceViewActivity"
|
||||
android:label="SurfaceView/Animated Movement">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="com.android.test.hwui.TEST" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="GLTextureViewActivity"
|
||||
android:label="TextureView/OpenGL">
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.test.hwui;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceHolder.Callback;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
public class MovingSurfaceViewActivity extends Activity implements Callback {
|
||||
static final String TAG = "MovingSurfaceView";
|
||||
SurfaceView mSurfaceView;
|
||||
ObjectAnimator mAnimator;
|
||||
|
||||
class MySurfaceView extends SurfaceView {
|
||||
boolean mSlowToggled;
|
||||
|
||||
public MySurfaceView(Context context) {
|
||||
super(context);
|
||||
setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mSlowToggled = !mSlowToggled;
|
||||
Log.d(TAG, "SLOW MODE: " + mSlowToggled);
|
||||
invalidate();
|
||||
}
|
||||
});
|
||||
setWillNotDraw(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
super.draw(canvas);
|
||||
if (mSlowToggled) {
|
||||
try {
|
||||
Thread.sleep(16);
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
}
|
||||
|
||||
public void setMyTranslationY(float ty) {
|
||||
setTranslationY(ty);
|
||||
if (mSlowToggled) {
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public float getMyTranslationY() {
|
||||
return getTranslationY();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
FrameLayout content = new FrameLayout(this);
|
||||
|
||||
mSurfaceView = new MySurfaceView(this);
|
||||
mSurfaceView.getHolder().addCallback(this);
|
||||
|
||||
final float density = getResources().getDisplayMetrics().density;
|
||||
int size = (int) (200 * density);
|
||||
|
||||
content.addView(mSurfaceView, new FrameLayout.LayoutParams(
|
||||
size, size, Gravity.CENTER));
|
||||
mAnimator = ObjectAnimator.ofFloat(mSurfaceView, "myTranslationY",
|
||||
0, size);
|
||||
mAnimator.setRepeatMode(ObjectAnimator.REVERSE);
|
||||
mAnimator.setRepeatCount(ObjectAnimator.INFINITE);
|
||||
mAnimator.setDuration(200);
|
||||
mAnimator.setInterpolator(new LinearInterpolator());
|
||||
setContentView(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
Canvas canvas = holder.lockCanvas();
|
||||
canvas.drawARGB(0xFF, 0x00, 0xFF, 0x00);
|
||||
holder.unlockCanvasAndPost(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mAnimator.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
mAnimator.pause();
|
||||
super.onPause();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user