Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4aa30d07 authored by Derek Sollenberger's avatar Derek Sollenberger
Browse files

Remove native calls to HWUI from Surface and use the public API instead

Test: CtsGraphicsTestCases and CtsWindowManagerDeviceTestCases
Bug: 137655431
Change-Id: I8427f96e4f33905e8cabb6d48a0cc29443b9ed63
parent 65677969
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -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);
}
+41 −21
Original line number Diff line number Diff line
@@ -23,46 +23,66 @@
#include <utils/Color.h>

#include <SkBitmap.h>
#include <SkSurface.h>

using namespace android;

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

ACanvas* ACanvas_getNativeHandleFromJava(JNIEnv* env, jobject canvasObj) {
    return TypeCast::toACanvas(GraphicsJNI::getNativeCanvas(env, canvasObj));
/*
 * 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;
    }

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);
    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 bitmap;
        return true;
    }
    return false;
}

bool ACanvas_isSupportedPixelFormat(int32_t bufferFormat) {
    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));
}

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*/) {
+7 −4
Original line number Diff line number Diff line
@@ -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) {
+1 −81
Original line number Diff line number Diff line
@@ -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)
+5 −2
Original line number Diff line number Diff line
@@ -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 },
Loading