diff options
| author | 2019-11-08 13:40:22 +0000 | |
|---|---|---|
| committer | 2019-11-08 13:40:22 +0000 | |
| commit | 36cf8b2c1290670b5eda56c10ecbd344bf869534 (patch) | |
| tree | 3756913512b3cc5bc4e6828334b2da2c87d09117 | |
| parent | b298aeb3db215441cf46580ef1f686f8e25bc074 (diff) | |
| parent | 4aa30d07c542cec423ec36db7c294825e757a157 (diff) | |
Merge "Remove native calls to HWUI from Surface and use the public API instead"
| -rw-r--r-- | core/java/android/view/Surface.java | 28 | ||||
| -rw-r--r-- | core/jni/android/graphics/apex/android_canvas.cpp | 62 | ||||
| -rw-r--r-- | core/jni/android/graphics/apex/include/android/graphics/canvas.h | 11 | ||||
| -rw-r--r-- | core/jni/android_view_Surface.cpp | 82 | ||||
| -rw-r--r-- | core/jni/android_view_ThreadedRenderer.cpp | 7 | ||||
| -rw-r--r-- | graphics/java/android/graphics/HardwareRenderer.java | 18 |
6 files changed, 84 insertions, 124 deletions
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 17f07b5a2ad4..dac62821fe90 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -23,6 +23,7 @@ import android.content.res.CompatibilityInfo.Translator; import android.graphics.Canvas; import android.graphics.ColorSpace; import android.graphics.GraphicBuffer; +import android.graphics.HardwareRenderer; import android.graphics.Matrix; import android.graphics.RecordingCanvas; import android.graphics.Rect; @@ -925,7 +926,7 @@ public class Surface implements Parcelable { private final class HwuiContext { private final RenderNode mRenderNode; - private long mHwuiRenderer; + private HardwareRenderer mHardwareRenderer; private RecordingCanvas mCanvas; private final boolean mIsWideColorGamut; @@ -934,8 +935,13 @@ public class Surface implements Parcelable { mRenderNode.setClipToBounds(false); mRenderNode.setForceDarkAllowed(false); mIsWideColorGamut = isWideColorGamut; - mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject, - isWideColorGamut); + + mHardwareRenderer = new HardwareRenderer(); + mHardwareRenderer.setContentRoot(mRenderNode); + mHardwareRenderer.setSurface(Surface.this, true); + mHardwareRenderer.setWideGamut(isWideColorGamut); + mHardwareRenderer.setLightSourceAlpha(0.0f, 0.0f); + mHardwareRenderer.setLightSourceGeometry(0.0f, 0.0f, 0.0f, 0.0f); } Canvas lockCanvas(int width, int height) { @@ -953,27 +959,21 @@ public class Surface implements Parcelable { } mRenderNode.endRecording(); mCanvas = null; - nHwuiDraw(mHwuiRenderer); + mHardwareRenderer.createRenderRequest() + .setVsyncTime(System.nanoTime()) + .syncAndDraw(); } void updateSurface() { - nHwuiSetSurface(mHwuiRenderer, mNativeObject); + mHardwareRenderer.setSurface(Surface.this, true); } void destroy() { - if (mHwuiRenderer != 0) { - nHwuiDestroy(mHwuiRenderer); - mHwuiRenderer = 0; - } + mHardwareRenderer.destroy(); } boolean isWideColorGamut() { return mIsWideColorGamut; } } - - private static native long nHwuiCreate(long rootNode, long surface, boolean isWideColorGamut); - private static native void nHwuiSetSurface(long renderer, long surface); - private static native void nHwuiDraw(long renderer); - private static native void nHwuiDestroy(long renderer); } diff --git a/core/jni/android/graphics/apex/android_canvas.cpp b/core/jni/android/graphics/apex/android_canvas.cpp index 527a745426e3..2a939efed9bb 100644 --- a/core/jni/android/graphics/apex/android_canvas.cpp +++ b/core/jni/android/graphics/apex/android_canvas.cpp @@ -23,46 +23,66 @@ #include <utils/Color.h> #include <SkBitmap.h> +#include <SkSurface.h> using namespace android; +/* + * Converts a buffer and dataspace into an SkBitmap only if the resulting bitmap can be treated as a + * rendering destination for a Canvas. If the buffer is null or the format is one that we cannot + * render into with a Canvas then false is returned and the outBitmap param is unmodified. + */ +static bool convert(const ANativeWindow_Buffer* buffer, + int32_t /*android_dataspace_t*/ dataspace, + SkBitmap* outBitmap) { + if (buffer == nullptr) { + return false; + } + + sk_sp<SkColorSpace> cs(uirenderer::DataSpaceToColorSpace((android_dataspace)dataspace)); + SkImageInfo imageInfo = uirenderer::ANativeWindowToImageInfo(*buffer, cs); + size_t rowBytes = buffer->stride * imageInfo.bytesPerPixel(); + + // If SkSurface::MakeRasterDirect fails then we should as well as we will not be able to + // draw into the canvas. + sk_sp<SkSurface> surface = SkSurface::MakeRasterDirect(imageInfo, buffer->bits, rowBytes); + if (surface.get() != nullptr) { + if (outBitmap) { + outBitmap->setInfo(imageInfo, rowBytes); + outBitmap->setPixels(buffer->bits); + } + return true; + } + return false; +} + bool ACanvas_isSupportedPixelFormat(int32_t bufferFormat) { - ANativeWindow_Buffer buffer { 0, 0, 0, bufferFormat, nullptr, {0} }; - const SkColorType colorType = uirenderer::ANativeWindowToImageInfo(buffer, nullptr).colorType(); - return kUnknown_SkColorType != colorType; + char pixels[8]; + ANativeWindow_Buffer buffer { 1, 1, 1, bufferFormat, pixels, {0} }; + return convert(&buffer, HAL_DATASPACE_UNKNOWN, nullptr); } ACanvas* ACanvas_getNativeHandleFromJava(JNIEnv* env, jobject canvasObj) { return TypeCast::toACanvas(GraphicsJNI::getNativeCanvas(env, canvasObj)); } -static SkBitmap convert(const ANativeWindow_Buffer* buffer, - int32_t /*android_dataspace_t*/ dataspace) { - SkBitmap bitmap; - if (buffer != nullptr && buffer->width > 0 && buffer->height > 0) { - sk_sp<SkColorSpace> cs(uirenderer::DataSpaceToColorSpace((android_dataspace)dataspace)); - SkImageInfo imageInfo = uirenderer::ANativeWindowToImageInfo(*buffer, cs); - ssize_t rowBytes = buffer->stride * imageInfo.bytesPerPixel(); - bitmap.setInfo(imageInfo, rowBytes); - bitmap.setPixels(buffer->bits); - } - return bitmap; -} - ACanvas* ACanvas_createCanvas(const ANativeWindow_Buffer* buffer, int32_t /*android_dataspace_t*/ dataspace) { - return TypeCast::toACanvas(Canvas::create_canvas(convert(buffer, dataspace))); + SkBitmap bitmap; + bool isValidBuffer = convert(buffer, dataspace, &bitmap); + return isValidBuffer ? TypeCast::toACanvas(Canvas::create_canvas(bitmap)) : nullptr; } void ACanvas_destroyCanvas(ACanvas* canvas) { delete TypeCast::toCanvas(canvas); } -void ACanvas_setBuffer(ACanvas* canvas, const ANativeWindow_Buffer* buffer, +bool ACanvas_setBuffer(ACanvas* canvas, const ANativeWindow_Buffer* buffer, int32_t /*android_dataspace_t*/ dataspace) { - - - TypeCast::toCanvas(canvas)->setBitmap(convert(buffer, dataspace)); + SkBitmap bitmap; + bool isValidBuffer = (buffer == nullptr) ? false : convert(buffer, dataspace, &bitmap); + TypeCast::toCanvas(canvas)->setBitmap(bitmap); + return isValidBuffer; } void ACanvas_clipRect(ACanvas* canvas, const ARect* clipRect, bool /*doAA*/) { diff --git a/core/jni/android/graphics/apex/include/android/graphics/canvas.h b/core/jni/android/graphics/apex/include/android/graphics/canvas.h index 190aba4565f8..6fd6b0693b37 100644 --- a/core/jni/android/graphics/apex/include/android/graphics/canvas.h +++ b/core/jni/android/graphics/apex/include/android/graphics/canvas.h @@ -42,7 +42,7 @@ ACanvas* ACanvas_getNativeHandleFromJava(JNIEnv* env, jobject canvas); /** * Creates a canvas that wraps the buffer * - * @param buffer required + * @param buffer is a required param. If no buffer is provided a nullptr will be returned. */ ACanvas* ACanvas_createCanvas(const ANativeWindow_Buffer* buffer, int32_t /*android_dataspace_t*/ dataspace); @@ -56,8 +56,11 @@ void ACanvas_destroyCanvas(ACanvas* canvas); * remain valid until the this method is called again with either another active * buffer or nullptr. If nullptr is given the canvas will release the previous buffer * and set an empty backing store. + * @return A boolean value indicating whether or not the buffer was successfully set. If false the + * method will behave as if nullptr were passed as the input buffer and the previous buffer + * will still be released. */ -void ACanvas_setBuffer(ACanvas* canvas, const ANativeWindow_Buffer* buffer, +bool ACanvas_setBuffer(ACanvas* canvas, const ANativeWindow_Buffer* buffer, int32_t /*android_dataspace_t*/ dataspace); /** @@ -110,9 +113,9 @@ namespace graphics { } } - void setBuffer(const ANativeWindow_Buffer* buffer, + bool setBuffer(const ANativeWindow_Buffer* buffer, int32_t /*android_dataspace_t*/ dataspace) { - ACanvas_setBuffer(mCanvas, buffer, dataspace); + return ACanvas_setBuffer(mCanvas, buffer, dataspace); } void clipRect(const ARect& clipRect, bool doAntiAlias = false) { diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 058a4c8ee2f9..01b5920755fa 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -45,11 +45,6 @@ #include <nativehelper/ScopedUtfChars.h> -#include <AnimationContext.h> -#include <FrameInfo.h> -#include <RenderNode.h> -#include <renderthread/RenderProxy.h> - // ---------------------------------------------------------------------------- namespace android { @@ -189,21 +184,6 @@ static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jclass clazz, jlong n return value; } -static inline SkColorType convertPixelFormat(PixelFormat format) { - /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then - we can map to kN32_SkColorType, and optionally call - bitmap.setAlphaType(kOpaque_SkAlphaType) on the resulting SkBitmap - (as an accelerator) - */ - switch (format) { - case PIXEL_FORMAT_RGBX_8888: return kN32_SkColorType; - case PIXEL_FORMAT_RGBA_8888: return kN32_SkColorType; - case PIXEL_FORMAT_RGBA_FP16: return kRGBA_F16_SkColorType; - case PIXEL_FORMAT_RGB_565: return kRGB_565_SkColorType; - default: return kUnknown_SkColorType; - } -} - static jlong nativeLockCanvas(JNIEnv* env, jclass clazz, jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) { sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject)); @@ -213,7 +193,7 @@ static jlong nativeLockCanvas(JNIEnv* env, jclass clazz, return 0; } - if (convertPixelFormat(ANativeWindow_getFormat(surface.get())) == kUnknown_SkColorType) { + if (!ACanvas_isSupportedPixelFormat(ANativeWindow_getFormat(surface.get()))) { native_window_set_buffers_format(surface.get(), PIXEL_FORMAT_RGBA_8888); } @@ -433,62 +413,8 @@ static jint nativeSetAutoRefreshEnabled(JNIEnv* env, jclass clazz, jlong nativeO return anw->perform(surface, NATIVE_WINDOW_SET_AUTO_REFRESH, int(enabled)); } -namespace uirenderer { - -using namespace android::uirenderer::renderthread; - -class ContextFactory : public IContextFactory { -public: - virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) { - return new AnimationContext(clock); - } -}; - -static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfacePtr, - jboolean isWideColorGamut) { - RenderNode* rootNode = reinterpret_cast<RenderNode*>(rootNodePtr); - sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr)); - ContextFactory factory; - RenderProxy* proxy = new RenderProxy(false, rootNode, &factory); - proxy->loadSystemProperties(); - if (isWideColorGamut) { - proxy->setWideGamut(true); - } - proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer); - proxy->setSurface(surface); - // Shadows can't be used via this interface, so just set the light source - // to all 0s. - proxy->setLightAlpha(0, 0); - proxy->setLightGeometry((Vector3){0, 0, 0}, 0); - return (jlong) proxy; -} - -static void setSurface(JNIEnv* env, jclass clazz, jlong rendererPtr, jlong surfacePtr) { - RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr); - sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr)); - proxy->setSurface(surface); -} - -static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) { - RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr); - nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC); - UiFrameInfoBuilder(proxy->frameInfo()) - .setVsync(vsync, vsync) - .addFlag(FrameInfoFlags::SurfaceCanvas); - proxy->syncAndDrawFrame(); -} - -static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) { - RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr); - delete proxy; -} - -} // uirenderer - // ---------------------------------------------------------------------------- -namespace hwui = android::uirenderer; - static const JNINativeMethod gSurfaceMethods[] = { {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J", (void*)nativeCreateFromSurfaceTexture }, @@ -521,12 +447,6 @@ static const JNINativeMethod gSurfaceMethods[] = { (void*)nativeAttachAndQueueBufferWithColorSpace}, {"nativeSetSharedBufferModeEnabled", "(JZ)I", (void*)nativeSetSharedBufferModeEnabled}, {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled}, - - // HWUI context - {"nHwuiCreate", "(JJZ)J", (void*) hwui::create }, - {"nHwuiSetSurface", "(JJ)V", (void*) hwui::setSurface }, - {"nHwuiDraw", "(J)V", (void*) hwui::draw }, - {"nHwuiDestroy", "(J)V", (void*) hwui::destroy }, }; int register_android_view_Surface(JNIEnv* env) diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index dd3a4d0c5699..7350396537ee 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -174,12 +174,15 @@ static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz, } static void android_view_ThreadedRenderer_setSurface(JNIEnv* env, jobject clazz, - jlong proxyPtr, jobject jsurface) { + jlong proxyPtr, jobject jsurface, jboolean discardBuffer) { RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); sp<Surface> surface; if (jsurface) { surface = android_view_Surface_getSurface(env, jsurface); } + if (discardBuffer) { + proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer); + } proxy->setSurface(surface); } @@ -632,7 +635,7 @@ static const JNINativeMethod gMethods[] = { { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy }, { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties }, { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName }, - { "nSetSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_setSurface }, + { "nSetSurface", "(JLandroid/view/Surface;Z)V", (void*) android_view_ThreadedRenderer_setSurface }, { "nPause", "(J)Z", (void*) android_view_ThreadedRenderer_pause }, { "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped }, { "nSetLightAlpha", "(JFF)V", (void*) android_view_ThreadedRenderer_setLightAlpha }, diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java index b6b2d4e1c46a..3f3ad578e8d7 100644 --- a/graphics/java/android/graphics/HardwareRenderer.java +++ b/graphics/java/android/graphics/HardwareRenderer.java @@ -286,10 +286,24 @@ public class HardwareRenderer { * non-null then {@link Surface#isValid()} must be true. */ public void setSurface(@Nullable Surface surface) { + setSurface(surface, false); + } + + /** + * See {@link #setSurface(Surface)} + * + * @hide + * @param discardBuffer determines whether the surface will attempt to preserve its contents + * between frames. If set to true the renderer will attempt to preserve + * the contents of the buffer between frames if the implementation allows + * it. If set to false no attempt will be made to preserve the buffer's + * contents between frames. + */ + public void setSurface(@Nullable Surface surface, boolean discardBuffer) { if (surface != null && !surface.isValid()) { throw new IllegalArgumentException("Surface is invalid. surface.isValid() == false."); } - nSetSurface(mNativeProxy, surface); + nSetSurface(mNativeProxy, surface, discardBuffer); } /** @@ -1084,7 +1098,7 @@ public class HardwareRenderer { private static native void nSetName(long nativeProxy, String name); - private static native void nSetSurface(long nativeProxy, Surface window); + private static native void nSetSurface(long nativeProxy, Surface window, boolean discardBuffer); private static native boolean nPause(long nativeProxy); |