diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 6632f39d0c42d..5e5825049ed2b 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -260,7 +260,7 @@ public abstract class HardwareRenderer { /** * Gets the current width of the surface. This is the width that the surface - * was last set to in a call to {@link #setup(int, int, Rect)}. + * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}. * * @return the current width of the surface */ @@ -268,7 +268,7 @@ public abstract class HardwareRenderer { /** * Gets the current height of the surface. This is the height that the surface - * was last set to in a call to {@link #setup(int, int, Rect)}. + * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}. * * @return the current width of the surface */ @@ -373,19 +373,20 @@ public abstract class HardwareRenderer { * * @param width The width of the drawing surface. * @param height The height of the drawing surface. + * @param attachInfo Information about the window. * @param surface The surface to hardware accelerate * @param surfaceInsets The drawing surface insets to apply * * @return true if the surface was initialized, false otherwise. Returning * false might mean that the surface was already initialized. */ - boolean initializeIfNeeded(int width, int height, Surface surface, Rect surfaceInsets) - throws OutOfResourcesException { + boolean initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, + Surface surface, Rect surfaceInsets) throws OutOfResourcesException { if (isRequested()) { // We lost the gl context, so recreate it. if (!isEnabled()) { if (initialize(surface)) { - setup(width, height, surfaceInsets); + setup(width, height, attachInfo, surfaceInsets); return true; } } @@ -398,9 +399,17 @@ public abstract class HardwareRenderer { * * @param width The width of the drawing surface. * @param height The height of the drawing surface. + * @param attachInfo Information about the window. * @param surfaceInsets The drawing surface insets to apply */ - abstract void setup(int width, int height, Rect surfaceInsets); + abstract void setup(int width, int height, View.AttachInfo attachInfo, Rect surfaceInsets); + + /** + * Updates the light position based on the position of the window. + * + * @param attachInfo Information about the window. + */ + abstract void setLightCenter(View.AttachInfo attachInfo); /** * Optional, sets the name of the renderer. Useful for debugging purposes. diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 1fd7109736b2f..7f243d3425d88 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -19,11 +19,10 @@ package android.view; import android.annotation.IntDef; import android.annotation.NonNull; import android.content.Context; -import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; +import android.graphics.Point; import android.graphics.Rect; -import android.graphics.drawable.Drawable; import android.os.Binder; import android.os.IBinder; import android.os.ParcelFileDescriptor; @@ -31,7 +30,6 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.Trace; import android.util.Log; -import android.util.LongSparseArray; import android.view.Surface.OutOfResourcesException; import android.view.View.AttachInfo; @@ -41,8 +39,6 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.HashSet; /** * Hardware renderer that proxies the rendering to a render thread. Most calls @@ -197,10 +193,10 @@ public class ThreadedRenderer extends HardwareRenderer { } @Override - void setup(int width, int height, Rect surfaceInsets) { - final float lightX = width / 2.0f; + void setup(int width, int height, AttachInfo attachInfo, Rect surfaceInsets) { mWidth = width; mHeight = height; + if (surfaceInsets != null && (surfaceInsets.left != 0 || surfaceInsets.right != 0 || surfaceInsets.top != 0 || surfaceInsets.bottom != 0)) { mHasInsets = true; @@ -218,10 +214,23 @@ public class ThreadedRenderer extends HardwareRenderer { mSurfaceWidth = width; mSurfaceHeight = height; } + mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight); - nSetup(mNativeProxy, mSurfaceWidth, mSurfaceHeight, - lightX, mLightY, mLightZ, mLightRadius, + nSetup(mNativeProxy, mSurfaceWidth, mSurfaceHeight, mLightRadius, mAmbientShadowAlpha, mSpotShadowAlpha); + + setLightCenter(attachInfo); + } + + @Override + void setLightCenter(AttachInfo attachInfo) { + // Adjust light position for window offsets. + final Point displaySize = attachInfo.mPoint; + attachInfo.mDisplay.getRealSize(displaySize); + final float lightX = displaySize.x / 2f - attachInfo.mWindowLeft; + final float lightY = mLightY - attachInfo.mWindowTop; + + nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ); } @Override @@ -500,8 +509,9 @@ public class ThreadedRenderer extends HardwareRenderer { private static native void nUpdateSurface(long nativeProxy, Surface window); private static native boolean nPauseSurface(long nativeProxy, Surface window); private static native void nSetup(long nativeProxy, int width, int height, - float lightX, float lightY, float lightZ, float lightRadius, - int ambientShadowAlpha, int spotShadowAlpha); + float lightRadius, int ambientShadowAlpha, int spotShadowAlpha); + private static native void nSetLightCenter(long nativeProxy, + float lightX, float lightY, float lightZ); private static native void nSetOpaque(long nativeProxy, boolean opaque); private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size); private static native void nDestroy(long nativeProxy); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 4f2a3fabbbaae..06dddfb2af919 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1813,15 +1813,15 @@ public final class ViewRootImpl implements ViewParent, } } - if (mAttachInfo.mHardwareRenderer != null && - mAttachInfo.mHardwareRenderer.isEnabled()) { - if (hwInitialized || - mWidth != mAttachInfo.mHardwareRenderer.getWidth() || - mHeight != mAttachInfo.mHardwareRenderer.getHeight()) { - mAttachInfo.mHardwareRenderer.setup( - mWidth, mHeight, mWindowAttributes.surfaceInsets); + final HardwareRenderer hardwareRenderer = mAttachInfo.mHardwareRenderer; + if (hardwareRenderer != null && hardwareRenderer.isEnabled()) { + if (hwInitialized + || mWidth != hardwareRenderer.getWidth() + || mHeight != hardwareRenderer.getHeight()) { + hardwareRenderer.setup(mWidth, mHeight, mAttachInfo, + mWindowAttributes.surfaceInsets); if (!hwInitialized) { - mAttachInfo.mHardwareRenderer.invalidate(mSurface); + hardwareRenderer.invalidate(mSurface); mFullRedrawNeeded = true; } } @@ -1897,6 +1897,11 @@ public final class ViewRootImpl implements ViewParent, } mAttachInfo.mWindowLeft = frame.left; mAttachInfo.mWindowTop = frame.top; + + // Update the light position for the new window offsets. + if (mAttachInfo.mHardwareRenderer != null) { + mAttachInfo.mHardwareRenderer.setLightCenter(mAttachInfo); + } } } @@ -2605,7 +2610,7 @@ public final class ViewRootImpl implements ViewParent, try { mAttachInfo.mHardwareRenderer.initializeIfNeeded( - mWidth, mHeight, mSurface, surfaceInsets); + mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets); } catch (OutOfResourcesException e) { handleOutOfResourcesException(e); return; @@ -3300,7 +3305,7 @@ public final class ViewRootImpl implements ViewParent, final WindowManager.LayoutParams lp = mWindowAttributes; final Rect surfaceInsets = lp != null ? lp.surfaceInsets : null; mAttachInfo.mHardwareRenderer.initializeIfNeeded( - mWidth, mHeight, mSurface, surfaceInsets); + mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets); } catch (OutOfResourcesException e) { Log.e(TAG, "OutOfResourcesException locking surface", e); try { diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index c4cd7ff1f0f21..3fa92a870ca76 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -483,7 +483,8 @@ static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfaceP proxy->initialize(surface); // Shadows can't be used via this interface, so just set the light source // to all 0s. (and width & height are unused, TODO remove them) - proxy->setup(0, 0, (Vector3){0, 0, 0}, 0, 0, 0); + proxy->setup(0, 0, 0, 0, 0); + proxy->setLightCenter((Vector3){0, 0, 0}); return (jlong) proxy; } diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index 5d5465bf75337..47132f40be21b 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -290,12 +290,15 @@ static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject } static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr, - jint width, jint height, - jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius, - jint ambientShadowAlpha, jint spotShadowAlpha, jfloat density) { + jint width, jint height, jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) { RenderProxy* proxy = reinterpret_cast(proxyPtr); - proxy->setup(width, height, (Vector3){lightX, lightY, lightZ}, lightRadius, - ambientShadowAlpha, spotShadowAlpha); + proxy->setup(width, height, lightRadius, ambientShadowAlpha, spotShadowAlpha); +} + +static void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz, + jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) { + RenderProxy* proxy = reinterpret_cast(proxyPtr); + proxy->setLightCenter((Vector3){lightX, lightY, lightZ}); } static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz, @@ -461,7 +464,8 @@ static JNINativeMethod gMethods[] = { { "nInitialize", "(JLandroid/view/Surface;)Z", (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 }, - { "nSetup", "(JIIFFFFII)V", (void*) android_view_ThreadedRenderer_setup }, + { "nSetup", "(JIIFII)V", (void*) android_view_ThreadedRenderer_setup }, + { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter }, { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque }, { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame }, { "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy }, diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index 458f35b6b49b5..e16865ede1600 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -90,8 +90,10 @@ void Layer::updateLightPosFromRenderer(const OpenGLRenderer& rootRenderer) { // re-init renderer's light position, based upon last cached location in window Vector3 lightPos = rootRenderer.getLightCenter(); cachedInvTransformInWindow.mapPoint3d(lightPos); - renderer->initLight(lightPos, rootRenderer.getLightRadius(), - rootRenderer.getAmbientShadowAlpha(), rootRenderer.getSpotShadowAlpha()); + renderer->initLight(rootRenderer.getLightRadius(), + rootRenderer.getAmbientShadowAlpha(), + rootRenderer.getSpotShadowAlpha()); + renderer->setLightCenter(lightPos); rendererLightPosDirty = false; } } diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 09674f73ca602..54bcd7e43d1d5 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -94,14 +94,17 @@ void OpenGLRenderer::initProperties() { } } -void OpenGLRenderer::initLight(const Vector3& lightCenter, float lightRadius, - uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { - mLightCenter = lightCenter; +void OpenGLRenderer::initLight(float lightRadius, uint8_t ambientShadowAlpha, + uint8_t spotShadowAlpha) { mLightRadius = lightRadius; mAmbientShadowAlpha = ambientShadowAlpha; mSpotShadowAlpha = spotShadowAlpha; } +void OpenGLRenderer::setLightCenter(const Vector3& lightCenter) { + mLightCenter = lightCenter; +} + /////////////////////////////////////////////////////////////////////////////// // Setup /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index c34eb2c61f015..218818d8e41df 100755 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -127,8 +127,9 @@ public: void setViewport(int width, int height) { mState.setViewport(width, height); } void initProperties(); - void initLight(const Vector3& lightCenter, float lightRadius, - uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha); + void initLight(float lightRadius, uint8_t ambientShadowAlpha, + uint8_t spotShadowAlpha); + void setLightCenter(const Vector3& lightCenter); /* * Prepares the renderer to draw a frame. This method must be invoked diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 6d7dcf1e1bd35..8329cd49101d0 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -127,10 +127,15 @@ bool CanvasContext::pauseSurface(ANativeWindow* window) { } // TODO: don't pass viewport size, it's automatic via EGL -void CanvasContext::setup(int width, int height, const Vector3& lightCenter, float lightRadius, +void CanvasContext::setup(int width, int height, float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { if (!mCanvas) return; - mCanvas->initLight(lightCenter, lightRadius, ambientShadowAlpha, spotShadowAlpha); + mCanvas->initLight(lightRadius, ambientShadowAlpha, spotShadowAlpha); +} + +void CanvasContext::setLightCenter(const Vector3& lightCenter) { + if (!mCanvas) return; + mCanvas->setLightCenter(lightCenter); } void CanvasContext::setOpaque(bool opaque) { diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 8d543044234b6..17917af9d373e 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -72,8 +72,9 @@ public: bool pauseSurface(ANativeWindow* window); bool hasSurface() { return mNativeWindow.get(); } - void setup(int width, int height, const Vector3& lightCenter, float lightRadius, + 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(); void processLayerUpdate(DeferredLayerUpdater* layerUpdater); diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 17e47b9b771f0..d8a9921c08541 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -172,27 +172,37 @@ bool RenderProxy::pauseSurface(const sp& window) { return (bool) postAndWait(task); } -CREATE_BRIDGE7(setup, CanvasContext* context, int width, int height, - Vector3 lightCenter, float lightRadius, - uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { - args->context->setup(args->width, args->height, args->lightCenter, args->lightRadius, +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, args->ambientShadowAlpha, args->spotShadowAlpha); return nullptr; } -void RenderProxy::setup(int width, int height, const Vector3& lightCenter, float lightRadius, +void RenderProxy::setup(int width, int height, float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { SETUP_TASK(setup); args->context = mContext; args->width = width; args->height = height; - args->lightCenter = lightCenter; args->lightRadius = lightRadius; args->ambientShadowAlpha = ambientShadowAlpha; args->spotShadowAlpha = spotShadowAlpha; post(task); } +CREATE_BRIDGE2(setLightCenter, CanvasContext* context, Vector3 lightCenter) { + args->context->setLightCenter(args->lightCenter); + return nullptr; +} + +void RenderProxy::setLightCenter(const Vector3& lightCenter) { + SETUP_TASK(setLightCenter); + args->context = mContext; + args->lightCenter = lightCenter; + post(task); +} + CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) { args->context->setOpaque(args->opaque); return nullptr; diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index 31456cdd076cf..5febbe0ab26c5 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -70,8 +70,9 @@ public: ANDROID_API bool initialize(const sp& window); ANDROID_API void updateSurface(const sp& window); ANDROID_API bool pauseSurface(const sp& window); - ANDROID_API void setup(int width, int height, const Vector3& lightCenter, float lightRadius, + ANDROID_API void setup(int width, int height, float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha); + ANDROID_API void setLightCenter(const Vector3& lightCenter); ANDROID_API void setOpaque(bool opaque); ANDROID_API int64_t* frameInfo(); ANDROID_API int syncAndDrawFrame(); diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp index 2f79c5875e374..ceee953ef7c26 100644 --- a/libs/hwui/tests/main.cpp +++ b/libs/hwui/tests/main.cpp @@ -92,8 +92,8 @@ public: proxy->loadSystemProperties(); proxy->initialize(surface); float lightX = width / 2.0; - proxy->setup(width, height, (Vector3){lightX, dp(-200.0f), dp(800.0f)}, - dp(800.0f), 255 * 0.075, 255 * 0.15); + proxy->setup(width, height, dp(800.0f), 255 * 0.075, 255 * 0.15); + proxy->setLightCenter((Vector3){lightX, dp(-200.0f), dp(800.0f)}); android::uirenderer::Rect DUMMY;