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

Commit 36cf8b2c authored by Derek Sollenberger's avatar Derek Sollenberger Committed by Android (Google) Code Review
Browse files

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

parents b298aeb3 4aa30d07
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