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

Commit 7cc5a53c authored by Marius Renn's avatar Marius Renn Committed by Android (Google) Code Review
Browse files

Merge "Add HardwareBuffer support to Bitmaps"

parents fb301a47 b2e9f524
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -13262,6 +13262,7 @@ package android.graphics {
    method public void setPixels(int[], int, int, int, int, int, int);
    method public void setPixels(int[], int, int, int, int, int, int);
    method public void setPremultiplied(boolean);
    method public void setPremultiplied(boolean);
    method public void setWidth(int);
    method public void setWidth(int);
    method public static android.graphics.Bitmap wrapHardwareBuffer(android.hardware.HardwareBuffer, android.graphics.ColorSpace);
    method public void writeToParcel(android.os.Parcel, int);
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.graphics.Bitmap> CREATOR;
    field public static final android.os.Parcelable.Creator<android.graphics.Bitmap> CREATOR;
    field public static final int DENSITY_NONE = 0; // 0x0
    field public static final int DENSITY_NONE = 0; // 0x0
+23 −2
Original line number Original line Diff line number Diff line
@@ -21,6 +21,10 @@
#include <hwui/Bitmap.h>
#include <hwui/Bitmap.h>
#include <renderthread/RenderProxy.h>
#include <renderthread/RenderProxy.h>


#include <android_runtime/android_hardware_HardwareBuffer.h>

#include <private/android/AHardwareBufferHelpers.h>

#include "core_jni_helpers.h"
#include "core_jni_helpers.h"


#include <jni.h>
#include <jni.h>
@@ -1104,8 +1108,7 @@ static jobject Bitmap_copyPreserveInternalConfig(JNIEnv* env, jobject, jlong bit


static jobject Bitmap_createHardwareBitmap(JNIEnv* env, jobject, jobject graphicBuffer) {
static jobject Bitmap_createHardwareBitmap(JNIEnv* env, jobject, jobject graphicBuffer) {
    sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
    sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
    // Bitmap::createFrom currently can only attach to a GraphicBuffer with PIXEL_FORMAT_RGBA_8888
    // Bitmap::createFrom currently assumes SRGB color space for RGBA images.
    // format and SRGB color space.
    // To support any color space, we need to pass an additional ColorSpace argument to
    // To support any color space, we need to pass an additional ColorSpace argument to
    // java Bitmap.createHardwareBitmap.
    // java Bitmap.createHardwareBitmap.
    sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
    sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
@@ -1116,6 +1119,22 @@ static jobject Bitmap_createHardwareBitmap(JNIEnv* env, jobject, jobject graphic
    return bitmap::createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
    return bitmap::createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
}
}


static jobject Bitmap_wrapHardwareBufferBitmap(JNIEnv* env, jobject, jobject hardwareBuffer,
                                               jfloatArray xyzD50, jobject transferParameters) {
    SkColorSpaceTransferFn p = GraphicsJNI::getNativeTransferParameters(env, transferParameters);
    SkMatrix44 xyzMatrix = GraphicsJNI::getNativeXYZMatrix(env, xyzD50);
    sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeRGB(p, xyzMatrix);
    AHardwareBuffer* hwBuf = android_hardware_HardwareBuffer_getNativeHardwareBuffer(env,
        hardwareBuffer);
    sp<GraphicBuffer> buffer(AHardwareBuffer_to_GraphicBuffer(hwBuf));
    sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer, colorSpace);
    if (!bitmap.get()) {
        ALOGW("failed to create hardware bitmap from hardware buffer");
        return NULL;
    }
    return bitmap::createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
}

static jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitmapPtr) {
static jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitmapPtr) {
    LocalScopedBitmap bitmapHandle(bitmapPtr);
    LocalScopedBitmap bitmapHandle(bitmapPtr);
    LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
    LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
@@ -1195,6 +1214,8 @@ static const JNINativeMethod gBitmapMethods[] = {
        (void*)Bitmap_copyPreserveInternalConfig },
        (void*)Bitmap_copyPreserveInternalConfig },
    {   "nativeCreateHardwareBitmap", "(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;",
    {   "nativeCreateHardwareBitmap", "(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;",
        (void*) Bitmap_createHardwareBitmap },
        (void*) Bitmap_createHardwareBitmap },
    {   "nativeWrapHardwareBufferBitmap", "(Landroid/hardware/HardwareBuffer;[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/Bitmap;",
        (void*) Bitmap_wrapHardwareBufferBitmap },
    {   "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
    {   "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
        (void*) Bitmap_createGraphicBufferHandle },
        (void*) Bitmap_createGraphicBufferHandle },
    {   "nativeGetColorSpace",      "(J[F[F)Z", (void*)Bitmap_getColorSpace },
    {   "nativeGetColorSpace",      "(J[F[F)Z", (void*)Bitmap_getColorSpace },
+46 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import android.annotation.Size;
import android.annotation.UnsupportedAppUsage;
import android.annotation.UnsupportedAppUsage;
import android.annotation.WorkerThread;
import android.annotation.WorkerThread;
import android.content.res.ResourcesImpl;
import android.content.res.ResourcesImpl;
import android.hardware.HardwareBuffer;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;
import android.os.StrictMode;
import android.os.StrictMode;
@@ -723,6 +724,48 @@ public final class Bitmap implements Parcelable {
        return nativeCreateHardwareBitmap(graphicBuffer);
        return nativeCreateHardwareBitmap(graphicBuffer);
    }
    }


    /**
     * Create a hardware bitmap backed by a {@link HardwareBuffer}.
     *
     * <p>The passed HardwareBuffer's usage flags must contain
     * {@link HardwareBuffer#USAGE_GPU_SAMPLED_IMAGE}.
     *
     * <p>The bitmap will keep a reference to the buffer so that callers can safely close the
     * HardwareBuffer without affecting the Bitmap. However the HardwareBuffer must not be
     * modified while a wrapped Bitmap is accessing it. Doing so will result in undefined behavior.
     *
     * @param hardwareBuffer The HardwareBuffer to wrap.
     * @param colorSpace The color space of the bitmap. Must be a {@link ColorSpace.Rgb} colorspace.
     *                   If null, SRGB is assumed.
     * @return A bitmap wrapping the buffer, or null if there was a problem creating the bitmap.
     * @throws IllegalArgumentException if the HardwareBuffer has an invalid usage, or an invalid
     *                                  colorspace is given.
     */
    @Nullable
    public static Bitmap wrapHardwareBuffer(@NonNull HardwareBuffer hardwareBuffer,
            @Nullable ColorSpace colorSpace) {
        if ((hardwareBuffer.getUsage() & HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE) == 0) {
            throw new IllegalArgumentException("usage flags must contain USAGE_GPU_SAMPLED_IMAGE.");
        }
        int format = hardwareBuffer.getFormat();
        ColorSpace.Rgb rgb = null;
        if (colorSpace != null) {
            if (!(colorSpace instanceof ColorSpace.Rgb)) {
                throw new IllegalArgumentException("colorSpace must be an RGB color space");
            }
            rgb = (ColorSpace.Rgb) colorSpace;
        } else {
            rgb = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB);
        }
        ColorSpace.Rgb.TransferParameters parameters = rgb.getTransferParameters();
        if (parameters == null) {
            throw new IllegalArgumentException("colorSpace must use an ICC "
                    + "parametric transfer function");
        }
        ColorSpace.Rgb d50 = (ColorSpace.Rgb) ColorSpace.adapt(rgb, ColorSpace.ILLUMINANT_D50);
        return nativeWrapHardwareBufferBitmap(hardwareBuffer, d50.getTransform(), parameters);
    }

    /**
    /**
     * Creates a new bitmap, scaled from an existing bitmap, when possible. If the
     * Creates a new bitmap, scaled from an existing bitmap, when possible. If the
     * specified width and height are the same as the current width and height of
     * specified width and height are the same as the current width and height of
@@ -2118,6 +2161,9 @@ public final class Bitmap implements Parcelable {
    private static native int nativeGetAllocationByteCount(long nativeBitmap);
    private static native int nativeGetAllocationByteCount(long nativeBitmap);
    private static native Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap);
    private static native Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap);
    private static native Bitmap nativeCreateHardwareBitmap(GraphicBuffer buffer);
    private static native Bitmap nativeCreateHardwareBitmap(GraphicBuffer buffer);
    private static native Bitmap nativeWrapHardwareBufferBitmap(HardwareBuffer buffer,
                                                              @Size(9) float[] xyzD50,
                                                              ColorSpace.Rgb.TransferParameters p);
    private static native GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap);
    private static native GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap);
    private static native boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params);
    private static native boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params);
    private static native boolean nativeIsSRGB(long nativePtr);
    private static native boolean nativeIsSRGB(long nativePtr);
+7 −6
Original line number Original line Diff line number Diff line
@@ -134,14 +134,15 @@ sk_sp<Bitmap> Bitmap::createFrom(const SkImageInfo& info, SkPixelRef& pixelRef)
}
}


sk_sp<Bitmap> Bitmap::createFrom(sp<GraphicBuffer> graphicBuffer) {
sk_sp<Bitmap> Bitmap::createFrom(sp<GraphicBuffer> graphicBuffer) {
    PixelFormat format = graphicBuffer->getPixelFormat();
    return createFrom(graphicBuffer, SkColorSpace::MakeSRGB());
    if (!graphicBuffer.get() ||
        (format != PIXEL_FORMAT_RGBA_8888 && format != PIXEL_FORMAT_RGBA_FP16)) {
        return nullptr;
}
}

sk_sp<Bitmap> Bitmap::createFrom(sp<GraphicBuffer> graphicBuffer, sk_sp<SkColorSpace> colorSpace) {
    // As we will be effectively texture-sampling the buffer (using either EGL or Vulkan), we can
    // view the colorspace as RGBA8888.
    SkImageInfo info = SkImageInfo::Make(graphicBuffer->getWidth(), graphicBuffer->getHeight(),
    SkImageInfo info = SkImageInfo::Make(graphicBuffer->getWidth(), graphicBuffer->getHeight(),
                                         kRGBA_8888_SkColorType, kPremul_SkAlphaType,
                                         kRGBA_8888_SkColorType, kPremul_SkAlphaType,
                                         SkColorSpace::MakeSRGB());
                                         colorSpace);
    return sk_sp<Bitmap>(new Bitmap(graphicBuffer.get(), info));
    return sk_sp<Bitmap>(new Bitmap(graphicBuffer.get(), info));
}
}


+2 −0
Original line number Original line Diff line number Diff line
@@ -64,6 +64,8 @@ public:
                                              size_t rowBytes);
                                              size_t rowBytes);


    static sk_sp<Bitmap> createFrom(sp<GraphicBuffer> graphicBuffer);
    static sk_sp<Bitmap> createFrom(sp<GraphicBuffer> graphicBuffer);
    static sk_sp<Bitmap> createFrom(sp<GraphicBuffer> graphicBuffer,
                                    sk_sp<SkColorSpace> colorSpace);


    static sk_sp<Bitmap> createFrom(const SkImageInfo&, SkPixelRef&);
    static sk_sp<Bitmap> createFrom(const SkImageInfo&, SkPixelRef&);