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

Commit f0ea9e19 authored by Nader Jawad's avatar Nader Jawad
Browse files

Update ColorFilter API to be backed by mutable native objects

Move the native ColorFilter implementation off of Skia's
SkColorFilter and instead have a mutable intermediate object
that can be inspected.

Bug: 264559422
Test: re-ran CtsUiRenderingTestCases
Change-Id: I9ec056084f00e72632c86bdf88376b1307e8ef74
parent de6f2499
Loading
Loading
Loading
Loading
+1 −12
Original line number Diff line number Diff line
@@ -41,21 +41,11 @@ public class ColorFilter {
     * Current native SkColorFilter instance.
     */
    private long mNativeInstance;
    // Runnable to do immediate destruction
    private Runnable mCleaner;

    long createNativeInstance() {
        return 0;
    }

    synchronized final void discardNativeInstance() {
        if (mNativeInstance != 0) {
            mCleaner.run();
            mCleaner = null;
            mNativeInstance = 0;
        }
    }

    /** @hide */
    public synchronized final long getNativeInstance() {
        if (mNativeInstance == 0) {
@@ -65,8 +55,7 @@ public class ColorFilter {
                // Note: we must check for null here, since it's possible for createNativeInstance()
                // to return nullptr if the native SkColorFilter would be a no-op at draw time.
                // See native implementations of subclass create methods for more info.
                mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
                        this, mNativeInstance);
                NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeInstance);
            }
        }
        return mNativeInstance;
+4 −2
Original line number Diff line number Diff line
@@ -81,12 +81,12 @@ public class ColorMatrixColorFilter extends ColorFilter {
     */
    @UnsupportedAppUsage
    public void setColorMatrix(@Nullable ColorMatrix matrix) {
        discardNativeInstance();
        if (matrix == null) {
            mMatrix.reset();
        } else {
            mMatrix.set(matrix);
        }
        nativeSetColorMatrix(getNativeInstance(), mMatrix.getArray());
    }

    /**
@@ -111,7 +111,6 @@ public class ColorMatrixColorFilter extends ColorFilter {
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public void setColorMatrixArray(@Nullable float[] array) {
        // called '...Array' so that passing null isn't ambiguous
        discardNativeInstance();
        if (array == null) {
            mMatrix.reset();
        } else {
@@ -120,6 +119,7 @@ public class ColorMatrixColorFilter extends ColorFilter {
            }
            mMatrix.set(array);
        }
        nativeSetColorMatrix(getNativeInstance(), mMatrix.getArray());
    }

    @Override
@@ -128,4 +128,6 @@ public class ColorMatrixColorFilter extends ColorFilter {
    }

    private static native long nativeColorMatrixFilter(float[] array);

    private static native void nativeSetColorMatrix(long colorMatrixColorFilter, float[] array);
}
+6 −2
Original line number Diff line number Diff line
@@ -78,7 +78,7 @@ public class LightingColorFilter extends ColorFilter {
    public void setColorMultiply(@ColorInt int mul) {
        if (mMul != mul) {
            mMul = mul;
            discardNativeInstance();
            native_SetLightingFilterMul(getNativeInstance(), mul);
        }
    }

@@ -104,7 +104,7 @@ public class LightingColorFilter extends ColorFilter {
    public void setColorAdd(@ColorInt int add) {
        if (mAdd != add) {
            mAdd = add;
            discardNativeInstance();
            native_SetLightingFilterAdd(getNativeInstance(), add);
        }
    }

@@ -114,4 +114,8 @@ public class LightingColorFilter extends ColorFilter {
    }

    private static native long native_CreateLightingFilter(int mul, int add);

    private static native void native_SetLightingFilterAdd(long lightingFilter, int add);

    private static native void native_SetLightingFilterMul(long lightingFilter, int mul);
}
+94 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 COLORFILTER_H_
#define COLORFILTER_H_

#include <stdint.h>

#include <memory>

#include "GraphicsJNI.h"
#include "SkColorFilter.h"
#include "SkiaWrapper.h"

namespace android {
namespace uirenderer {

class ColorFilter : public SkiaWrapper<SkColorFilter> {
public:
    static ColorFilter* fromJava(jlong handle) { return reinterpret_cast<ColorFilter*>(handle); }

protected:
    ColorFilter() = default;
};

class BlendModeColorFilter : public ColorFilter {
public:
    BlendModeColorFilter(SkColor color, SkBlendMode mode) : mColor(color), mMode(mode) {}

private:
    sk_sp<SkColorFilter> createInstance() override { return SkColorFilters::Blend(mColor, mMode); }

private:
    const SkColor mColor;
    const SkBlendMode mMode;
};

class LightingFilter : public ColorFilter {
public:
    LightingFilter(SkColor mul, SkColor add) : mMul(mul), mAdd(add) {}

    void setMul(SkColor mul) {
        mMul = mul;
        discardInstance();
    }

    void setAdd(SkColor add) {
        mAdd = add;
        discardInstance();
    }

private:
    sk_sp<SkColorFilter> createInstance() override { return SkColorFilters::Lighting(mMul, mAdd); }

private:
    SkColor mMul;
    SkColor mAdd;
};

class ColorMatrixColorFilter : public ColorFilter {
public:
    ColorMatrixColorFilter(std::vector<float>&& matrix) : mMatrix(std::move(matrix)) {}

    void setMatrix(std::vector<float>&& matrix) {
        mMatrix = std::move(matrix);
        discardInstance();
    }

private:
    sk_sp<SkColorFilter> createInstance() override {
        return SkColorFilters::Matrix(mMatrix.data());
    }

private:
    std::vector<float> mMatrix;
};

}  // namespace uirenderer
}  // namespace android

#endif  // COLORFILTER_H_
+56 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 SKIA_WRAPPER_H_
#define SKIA_WRAPPER_H_

#include <SkRefCnt.h>
#include <utils/RefBase.h>

namespace android::uirenderer {

template <typename T>
class SkiaWrapper : public VirtualLightRefBase {
public:
    sk_sp<T> getInstance() {
        if (mInstance != nullptr && shouldDiscardInstance()) {
            mInstance = nullptr;
        }

        if (mInstance == nullptr) {
            mInstance = createInstance();
            mGenerationId++;
        }
        return mInstance;
    }

    virtual bool shouldDiscardInstance() const { return false; }

    void discardInstance() { mInstance = nullptr; }

    [[nodiscard]] int32_t getGenerationId() const { return mGenerationId; }

protected:
    virtual sk_sp<T> createInstance() = 0;

private:
    sk_sp<T> mInstance = nullptr;
    int32_t mGenerationId = 0;
};

}  // namespace android::uirenderer

#endif  // SKIA_WRAPPER_H_
Loading