Merge "Make stopped state a first-class thing" into nyc-dev
am: c724dcf
* commit 'c724dcf23c5e2ebd22c042a8a6f2424b7e9d5029':
Make stopped state a first-class thing
Change-Id: Idfa3cc5d8fa5b07c742c2700b38441ff7d692f42
This commit is contained in:
@@ -485,14 +485,24 @@ public final class ThreadedRenderer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops any rendering into the surface. Use this if it is unclear whether
|
||||
* Halts any current rendering into the surface. Use this if it is unclear whether
|
||||
* or not the surface used by the HardwareRenderer will be changing. It
|
||||
* Suspends any rendering into the surface, but will not do any destruction
|
||||
* Suspends any rendering into the surface, but will not do any destruction.
|
||||
*
|
||||
* Any subsequent draws will override the pause, resuming normal operation.
|
||||
*/
|
||||
boolean pauseSurface(Surface surface) {
|
||||
return nPauseSurface(mNativeProxy, surface);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hard stops or resumes rendering into the surface. This flag is used to
|
||||
* determine whether or not it is safe to use the given surface *at all*
|
||||
*/
|
||||
void setStopped(boolean stopped) {
|
||||
nSetStopped(mNativeProxy, stopped);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys all hardware rendering resources associated with the specified
|
||||
* view hierarchy.
|
||||
@@ -988,6 +998,7 @@ public final class ThreadedRenderer {
|
||||
private static native void nInitialize(long nativeProxy, Surface window);
|
||||
private static native void nUpdateSurface(long nativeProxy, Surface window);
|
||||
private static native boolean nPauseSurface(long nativeProxy, Surface window);
|
||||
private static native void nSetStopped(long nativeProxy, boolean stopped);
|
||||
private static native void nSetup(long nativeProxy, int width, int height,
|
||||
float lightRadius, int ambientShadowAlpha, int spotShadowAlpha);
|
||||
private static native void nSetLightCenter(long nativeProxy,
|
||||
|
||||
@@ -1079,13 +1079,16 @@ public final class ViewRootImpl implements ViewParent,
|
||||
void setWindowStopped(boolean stopped) {
|
||||
if (mStopped != stopped) {
|
||||
mStopped = stopped;
|
||||
final ThreadedRenderer renderer = mAttachInfo.mHardwareRenderer;
|
||||
if (renderer != null) {
|
||||
if (DEBUG_DRAW) Log.d(mTag, "WindowStopped on " + getTitle() + " set to " + mStopped);
|
||||
renderer.setStopped(mStopped);
|
||||
}
|
||||
if (!mStopped) {
|
||||
scheduleTraversals();
|
||||
} else {
|
||||
if (mAttachInfo.mHardwareRenderer != null) {
|
||||
if (DEBUG_DRAW) Log.d(mTag, "WindowStopped on " + getTitle());
|
||||
mAttachInfo.mHardwareRenderer.updateSurface(null);
|
||||
mAttachInfo.mHardwareRenderer.destroyHardwareResources(mView);
|
||||
if (renderer != null) {
|
||||
renderer.destroyHardwareResources(mView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,6 +478,12 @@ static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject
|
||||
return proxy->pauseSurface(surface);
|
||||
}
|
||||
|
||||
static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz,
|
||||
jlong proxyPtr, jboolean stopped) {
|
||||
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
|
||||
proxy->setStopped(stopped);
|
||||
}
|
||||
|
||||
static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
|
||||
jint width, jint height, jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) {
|
||||
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
|
||||
@@ -731,6 +737,7 @@ static const JNINativeMethod gMethods[] = {
|
||||
{ "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize },
|
||||
{ "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
|
||||
{ "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
|
||||
{ "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped },
|
||||
{ "nSetup", "(JIIFII)V", (void*) android_view_ThreadedRenderer_setup },
|
||||
{ "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
|
||||
{ "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
|
||||
|
||||
@@ -113,18 +113,11 @@ void CanvasContext::setSurface(Surface* surface) {
|
||||
mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
|
||||
mHaveNewSurface = true;
|
||||
mSwapHistory.clear();
|
||||
makeCurrent();
|
||||
} else {
|
||||
mRenderThread.removeFrameCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasContext::requireSurface() {
|
||||
LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
|
||||
"requireSurface() called but no surface set!");
|
||||
makeCurrent();
|
||||
}
|
||||
|
||||
void CanvasContext::setSwapBehavior(SwapBehavior swapBehavior) {
|
||||
mSwapBehavior = swapBehavior;
|
||||
}
|
||||
@@ -146,6 +139,18 @@ bool CanvasContext::pauseSurface(Surface* surface) {
|
||||
return mRenderThread.removeFrameCallback(this);
|
||||
}
|
||||
|
||||
void CanvasContext::setStopped(bool stopped) {
|
||||
if (mStopped != stopped) {
|
||||
mStopped = stopped;
|
||||
if (mStopped) {
|
||||
mRenderThread.removeFrameCallback(this);
|
||||
if (mEglManager.isCurrent(mEglSurface)) {
|
||||
mEglManager.makeCurrent(EGL_NO_SURFACE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: don't pass viewport size, it's automatic via EGL
|
||||
void CanvasContext::setup(int width, int height, float lightRadius,
|
||||
uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
|
||||
@@ -172,7 +177,9 @@ void CanvasContext::setOpaque(bool opaque) {
|
||||
mOpaque = opaque;
|
||||
}
|
||||
|
||||
void CanvasContext::makeCurrent() {
|
||||
bool CanvasContext::makeCurrent() {
|
||||
if (mStopped) return false;
|
||||
|
||||
// TODO: Figure out why this workaround is needed, see b/13913604
|
||||
// In the meantime this matches the behavior of GLRenderer, so it is not a regression
|
||||
EGLint error = 0;
|
||||
@@ -180,6 +187,7 @@ void CanvasContext::makeCurrent() {
|
||||
if (error) {
|
||||
setSurface(nullptr);
|
||||
}
|
||||
return !error;
|
||||
}
|
||||
|
||||
static bool wasSkipped(FrameInfo* info) {
|
||||
@@ -671,7 +679,7 @@ void CanvasContext::runWithGlContext(RenderTask* task) {
|
||||
}
|
||||
|
||||
Layer* CanvasContext::createTextureLayer() {
|
||||
requireSurface();
|
||||
mEglManager.initialize();
|
||||
return LayerRenderer::createTextureLayer(mRenderThread.renderState());
|
||||
}
|
||||
|
||||
|
||||
@@ -82,13 +82,14 @@ public:
|
||||
void initialize(Surface* surface);
|
||||
void updateSurface(Surface* surface);
|
||||
bool pauseSurface(Surface* surface);
|
||||
void setStopped(bool stopped);
|
||||
bool hasSurface() { return mNativeSurface.get(); }
|
||||
|
||||
void setup(int width, int height, float lightRadius,
|
||||
uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
|
||||
void setLightCenter(const Vector3& lightCenter);
|
||||
void setOpaque(bool opaque);
|
||||
void makeCurrent();
|
||||
bool makeCurrent();
|
||||
void prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
|
||||
int64_t syncQueued, RenderNode* target);
|
||||
void draw();
|
||||
@@ -172,7 +173,6 @@ private:
|
||||
friend class android::uirenderer::RenderState;
|
||||
|
||||
void setSurface(Surface* window);
|
||||
void requireSurface();
|
||||
|
||||
void freePrefetchedLayers(TreeObserver* observer);
|
||||
|
||||
@@ -185,6 +185,7 @@ private:
|
||||
EglManager& mEglManager;
|
||||
sp<Surface> mNativeSurface;
|
||||
EGLSurface mEglSurface = EGL_NO_SURFACE;
|
||||
bool mStopped = false;
|
||||
bool mBufferPreserved = false;
|
||||
SwapBehavior mSwapBehavior = kSwap_default;
|
||||
struct SwapHistory {
|
||||
|
||||
@@ -115,7 +115,7 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) {
|
||||
ATRACE_CALL();
|
||||
int64_t vsync = mFrameInfo[static_cast<int>(FrameInfoIndex::Vsync)];
|
||||
mRenderThread->timeLord().vsyncReceived(vsync);
|
||||
mContext->makeCurrent();
|
||||
bool canDraw = mContext->makeCurrent();
|
||||
Caches::getInstance().textureCache.resetMarkInUse(mContext);
|
||||
|
||||
for (size_t i = 0; i < mLayers.size(); i++) {
|
||||
@@ -126,8 +126,9 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) {
|
||||
|
||||
// This is after the prepareTree so that any pending operations
|
||||
// (RenderNode tree state, prefetched layers, etc...) will be flushed.
|
||||
if (CC_UNLIKELY(!mContext->hasSurface())) {
|
||||
if (CC_UNLIKELY(!mContext->hasSurface() || !canDraw)) {
|
||||
mSyncResult |= kSync_LostSurfaceRewardIfFound;
|
||||
info.out.canDrawThisFrame = false;
|
||||
}
|
||||
|
||||
if (info.out.hasAnimations) {
|
||||
|
||||
@@ -270,12 +270,6 @@ bool EglManager::makeCurrent(EGLSurface surface, EGLint* errOut) {
|
||||
// Ensure we always have a valid surface & context
|
||||
surface = mPBufferSurface;
|
||||
}
|
||||
// TODO: Temporary to help diagnose b/27286867
|
||||
if (mCurrentSurface == mPBufferSurface || surface == mPBufferSurface) {
|
||||
ALOGD("Switching from surface %p%s to %p%s", mCurrentSurface,
|
||||
mCurrentSurface == mPBufferSurface ? " (pbuffer)" : "",
|
||||
surface, surface == mPBufferSurface ? " (pbuffer)" : "");
|
||||
}
|
||||
if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
|
||||
if (errOut) {
|
||||
*errOut = eglGetError();
|
||||
|
||||
@@ -167,6 +167,18 @@ bool RenderProxy::pauseSurface(const sp<Surface>& surface) {
|
||||
return (bool) postAndWait(task);
|
||||
}
|
||||
|
||||
CREATE_BRIDGE2(setStopped, CanvasContext* context, bool stopped) {
|
||||
args->context->setStopped(args->stopped);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RenderProxy::setStopped(bool stopped) {
|
||||
SETUP_TASK(setStopped);
|
||||
args->context = mContext;
|
||||
args->stopped = stopped;
|
||||
postAndWait(task);
|
||||
}
|
||||
|
||||
CREATE_BRIDGE6(setup, CanvasContext* context, int width, int height,
|
||||
float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
|
||||
args->context->setup(args->width, args->height, args->lightRadius,
|
||||
|
||||
@@ -79,6 +79,7 @@ public:
|
||||
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 setStopped(bool stopped);
|
||||
ANDROID_API void setup(int width, int height, float lightRadius,
|
||||
uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
|
||||
ANDROID_API void setLightCenter(const Vector3& lightCenter);
|
||||
|
||||
Reference in New Issue
Block a user