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

Commit 95e7c023 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Continue to isolate graphics classes by introducing C API"

parents 5061178c c287a77d
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -386,10 +386,12 @@ cc_library_static {
    local_include_dirs: [
        "include",  // NEEDED FOR ANDROID RUNTIME
        "android/graphics",
        "android/graphics/apex/include",
    ],

    export_include_dirs: [
        ".",
        "android/graphics/apex/include",
    ],

    include_dirs: [
@@ -417,6 +419,8 @@ cc_library_static {
    target: {
        android: {
            srcs: [ // sources that depend on android only libraries
                "android/graphics/apex/android_canvas.cpp",

                "android_view_TextureLayer.cpp",
                "android_view_ThreadedRenderer.cpp",
                "android/graphics/BitmapRegionDecoder.cpp",
+70 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "android/graphics/canvas.h"

#include "GraphicsJNI.h"

#include <hwui/Canvas.h>
#include <utils/Color.h>

#include <SkBitmap.h>

using namespace android;

static inline Canvas* toCanvas(ACanvas* aCanvas) {
    return reinterpret_cast<Canvas*>(aCanvas);
}

static inline ACanvas* toACanvas(Canvas* canvas) {
    return reinterpret_cast<ACanvas*>(canvas);
}

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 toACanvas(GraphicsJNI::getNativeCanvas(env, canvasObj));
}

void ACanvas_setBuffer(ACanvas* canvas, 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);
    }

    toCanvas(canvas)->setBitmap(bitmap);
}

void ACanvas_clipRect(ACanvas* canvas, const ARect& clipRect, bool /*doAA*/) {
    //TODO update Canvas to take antialias param
    toCanvas(canvas)->clipRect(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom,
                               SkClipOp::kIntersect);
}

void ACanvas_clipOutRect(ACanvas* canvas, const ARect& clipRect, bool /*doAA*/) {
    //TODO update Canvas to take antialias param
    toCanvas(canvas)->clipRect(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom,
                               SkClipOp::kDifference);
}
+66 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef ANDROID_GRAPHICS_CANVAS_H
#define ANDROID_GRAPHICS_CANVAS_H

#include <android/native_window.h>
#include <android/rect.h>
#include <jni.h>

__BEGIN_DECLS

/**
* Opaque handle for a native graphics canvas.
*/
typedef struct ACanvas ACanvas;

//  One of AHardwareBuffer_Format.
bool ACanvas_isSupportedPixelFormat(int32_t bufferFormat);

/**
 * Returns a native handle to a Java android.graphics.Canvas
 *
 * @param env
 * @param canvas
 * @return ACanvas* that is only valid for the life of the jobject.
 */
ACanvas* ACanvas_getNativeHandleFromJava(JNIEnv* env, jobject canvas);

/**
 * Updates the canvas to render into the pixels in the provided buffer
 *
 * @param canvas
 * @param buffer The buffer that will provide the backing store for this canvas.  The buffer must
 *               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.
 * @param dataspace
 */
void ACanvas_setBuffer(ACanvas* canvas, const ANativeWindow_Buffer* buffer,
                       int32_t /*android_dataspace_t*/ dataspace);

/**
 * Clips operations on the canvas to the intersection of the current clip and the provided clipRect.
 */
void ACanvas_clipRect(ACanvas* canvas, const ARect& clipRect, bool doAntiAlias = false);

/**
 * Clips operations on the canvas to the difference of the current clip and the provided clipRect.
 */
void ACanvas_clipOutRect(ACanvas* canvas, const ARect& clipRect, bool doAntiAlias = false);

__END_DECLS
#endif // ANDROID_GRAPHICS_CANVAS_H
 No newline at end of file
+18 −46
Original line number Diff line number Diff line
@@ -21,11 +21,6 @@
#include <inttypes.h>

#include "android_os_Parcel.h"
#include "android/graphics/GraphicsJNI.h"

#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_graphics_GraphicBuffer.h>

#include <binder/Parcel.h>

#include <log/log.h>
@@ -33,10 +28,10 @@
#include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h>

#include <hwui/Bitmap.h>

#include <SkCanvas.h>
#include <SkBitmap.h>
#include <android/native_window.h>
#include <android/graphics/canvas.h>
#include <android_runtime/android_graphics_GraphicBuffer.h>
#include <private/android/AHardwareBufferHelpers.h>

#include <private/gui/ComposerService.h>

@@ -146,23 +141,8 @@ static void android_graphics_GraphicBuffer_destroy(JNIEnv* env, jobject clazz,
// Canvas management
// ----------------------------------------------------------------------------

static inline SkColorType convertPixelFormat(int32_t format) {
    switch (format) {
        case PIXEL_FORMAT_RGBA_8888:
            return kN32_SkColorType;
        case PIXEL_FORMAT_RGBX_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 jboolean android_graphics_GraphicBuffer_lockCanvas(JNIEnv* env, jobject,
        jlong wrapperHandle, jobject canvas, jobject dirtyRect) {
        jlong wrapperHandle, jobject canvasObj, jobject dirtyRect) {

    GraphicBufferWrapper* wrapper =
                reinterpret_cast<GraphicBufferWrapper*>(wrapperHandle);
@@ -191,24 +171,16 @@ static jboolean android_graphics_GraphicBuffer_lockCanvas(JNIEnv* env, jobject,
        return JNI_FALSE;
    }

    ssize_t bytesCount = buffer->getStride() * bytesPerPixel(buffer->getPixelFormat());

    SkBitmap bitmap;
    bitmap.setInfo(SkImageInfo::Make(buffer->getWidth(), buffer->getHeight(),
                                     convertPixelFormat(buffer->getPixelFormat()),
                                     kPremul_SkAlphaType),
                   bytesCount);

    if (buffer->getWidth() > 0 && buffer->getHeight() > 0) {
        bitmap.setPixels(bits);
    } else {
        bitmap.setPixels(NULL);
    }
    ANativeWindow_Buffer nativeBuffer;
    nativeBuffer.width = buffer->getWidth();
    nativeBuffer.height = buffer->getHeight();
    nativeBuffer.stride = buffer->getStride();
    nativeBuffer.format = AHardwareBuffer_convertFromPixelFormat(buffer->getPixelFormat());
    nativeBuffer.bits = bits;

    Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas);
    nativeCanvas->setBitmap(bitmap);
    nativeCanvas->clipRect(rect.left, rect.top, rect.right, rect.bottom,
            SkClipOp::kIntersect);
    ACanvas* canvas = ACanvas_getNativeHandleFromJava(env, canvasObj);
    ACanvas_setBuffer(canvas, &nativeBuffer, ADATASPACE_UNKNOWN);
    ACanvas_clipRect(canvas, {rect.left, rect.top, rect.right, rect.bottom});

    if (dirtyRect) {
        INVOKEV(dirtyRect, gRectClassInfo.set,
@@ -219,13 +191,13 @@ static jboolean android_graphics_GraphicBuffer_lockCanvas(JNIEnv* env, jobject,
}

static jboolean android_graphics_GraphicBuffer_unlockCanvasAndPost(JNIEnv* env, jobject,
        jlong wrapperHandle, jobject canvas) {
        jlong wrapperHandle, jobject canvasObj) {
    // release the buffer from the canvas
    ACanvas* canvas = ACanvas_getNativeHandleFromJava(env, canvasObj);
    ACanvas_setBuffer(canvas, nullptr, ADATASPACE_UNKNOWN);

    GraphicBufferWrapper* wrapper =
                reinterpret_cast<GraphicBufferWrapper*>(wrapperHandle);
    Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas);
    nativeCanvas->setBitmap(SkBitmap());

    if (wrapper) {
        status_t status = wrapper->get()->unlock();
        return status == 0 ? JNI_TRUE : JNI_FALSE;
+13 −33
Original line number Diff line number Diff line
@@ -20,15 +20,16 @@

#include "jni.h"
#include <nativehelper/JNIHelp.h>
#include "android_os_Parcel.h"
#include "android/graphics/GraphicsJNI.h"

#include "core_jni_helpers.h"

#include <android/graphics/canvas.h>
#include <android_runtime/android_graphics_GraphicBuffer.h>
#include <android_runtime/android_graphics_SurfaceTexture.h>
#include <android_runtime/android_view_Surface.h>
#include <android_runtime/Log.h>
#include <private/android/AHardwareBufferHelpers.h>

#include "android_os_Parcel.h"
#include <binder/Parcel.h>

#include <gui/Surface.h>
@@ -39,11 +40,6 @@
#include <ui/Rect.h>
#include <ui/Region.h>

#include <SkCanvas.h>
#include <SkBitmap.h>
#include <SkImage.h>
#include <SkRegion.h>

#include <utils/misc.h>
#include <utils/Log.h>

@@ -232,37 +228,21 @@ static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
        dirtyRectPtr = &dirtyRect;
    }

    ANativeWindow_Buffer outBuffer;
    status_t err = surface->lock(&outBuffer, dirtyRectPtr);
    ANativeWindow_Buffer buffer;
    status_t err = surface->lock(&buffer, dirtyRectPtr);
    if (err < 0) {
        const char* const exception = (err == NO_MEMORY) ?
                OutOfResourcesException :
                "java/lang/IllegalArgumentException";
                OutOfResourcesException : IllegalArgumentException;
        jniThrowException(env, exception, NULL);
        return 0;
    }

    SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
                                         convertPixelFormat(outBuffer.format),
                                         outBuffer.format == PIXEL_FORMAT_RGBX_8888
                                                 ? kOpaque_SkAlphaType : kPremul_SkAlphaType);

    SkBitmap bitmap;
    ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
    bitmap.setInfo(info, bpr);
    if (outBuffer.width > 0 && outBuffer.height > 0) {
        bitmap.setPixels(outBuffer.bits);
    } else {
        // be safe with an empty bitmap.
        bitmap.setPixels(NULL);
    }

    Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
    nativeCanvas->setBitmap(bitmap);
    ACanvas* canvas = ACanvas_getNativeHandleFromJava(env, canvasObj);
    ACanvas_setBuffer(canvas, &buffer, static_cast<int32_t>(surface->getBuffersDataSpace()));

    if (dirtyRectPtr) {
        nativeCanvas->clipRect(dirtyRect.left, dirtyRect.top,
                dirtyRect.right, dirtyRect.bottom, SkClipOp::kIntersect);
        ACanvas_clipRect(canvas, {dirtyRect.left, dirtyRect.top,
                                  dirtyRect.right, dirtyRect.bottom});
    }

    if (dirtyRectObj) {
@@ -288,8 +268,8 @@ static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
    }

    // detach the canvas from the surface
    Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
    nativeCanvas->setBitmap(SkBitmap());
    ACanvas* canvas = ACanvas_getNativeHandleFromJava(env, canvasObj);
    ACanvas_setBuffer(canvas, nullptr, ADATASPACE_UNKNOWN);

    // unlock surface
    status_t err = surface->unlockAndPost();
Loading