unplugged-vendor/frameworks/native/libs/renderengine/mediatek/SkiaDitherEffect.cpp

182 lines
6.8 KiB
C++

/* Copyright Statement:
*
* This software/firmware and related documentation ("MediaTek Software") are
* protected under relevant copyright laws. The information contained herein is
* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
* the prior written permission of MediaTek inc. and/or its licensors, any
* reproduction, modification, use or disclosure of MediaTek Software, and
* information contained herein, in whole or in part, shall be strictly
* prohibited.
*
* MediaTek Inc. (C) 2021. All rights reserved.
*
* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
*
* The following software/firmware and/or related documentation ("MediaTek
* Software") have been modified by MediaTek Inc. All revisions are subject to
* any receiver's applicable license agreements with MediaTek Inc.
*/
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include "SkiaDitherEffect.h"
#include <SkCanvas.h>
#include <SkData.h>
#include <SkPaint.h>
#include <SkRRect.h>
#include <SkRuntimeEffect.h>
#include <SkSize.h>
#include <SkString.h>
#include <SkSurface.h>
#include <log/log.h>
#include <utils/Trace.h>
using namespace android;
using android::hardware::graphics::common::V1_1::BufferUsage;
namespace android {
namespace renderengine {
namespace skia {
/* MTK_SKIA_DITHER_EFFECT_DEBUG
Once defined, the dither shader string could be override for debugging.
*/
// #define MTK_SKIA_DITHER_EFFECT_DEBUG
/* MTK_SKIA_DITHER_BLUE_NOISE_TABLE
Once define, blue noise will be used (64x64 bytes).
/system/etc/HBMNoiseTable is required.
If this option is not defined,
the dither table is from skia dither (8x8 bytes).
*/
// #define MTK_SKIA_DITHER_BLUE_NOISE_TABLE
#ifdef MTK_IN_DISPLAY_FINGERPRINT
bool SkiaDitherEffect::isInitOK() {
return mInitOK;
}
SkiaDitherEffect::~SkiaDitherEffect(){
}
SkiaDitherEffect::SkiaDitherEffect() {
bool initOK = true;
#ifdef MTK_SKIA_DITHER_BLUE_NOISE_TABLE
static unsigned char ditherTable[64 * 64] = {0};
FILE* fp = fopen("/system/etc/HBMNoiseTable","rb");
if (fp) {
size_t result = fread(ditherTable, 1, sizeof(ditherTable), fp);
if (result != sizeof(ditherTable)) {
ALOGE("HBMNoiseTable size is not correct (%zu)", result);
initOK = false;
}
int ret = fclose(fp);
if (CC_UNLIKELY(ret != 0)) {
ALOGE("%s(), fclose fail", __FUNCTION__);
initOK = false;
}
} else {
ALOGE("open file /system/etc/HBMNoiseTable failed (%s)", strerror(errno));
initOK = false;
}
mDitherBmp.setInfo(SkImageInfo::MakeA8(64, 64));
mDitherBmp.setPixels(const_cast<uint8_t*>(ditherTable));
mDitherBmp.setImmutable();
#else
static unsigned char ditherTable[8*8] = {0};
// following dither table is from Skia dither
for (int x = 0; x < 8; ++x) {
for (int y = 0; y < 8; ++y) {
unsigned int m = (y & 1) << 5 | (x & 1) << 4 |
(y & 2) << 2 | (x & 2) << 1 |
(y & 4) >> 1 | (x & 4) >> 2;
float value = float(m) * 1.0 / 64.0 - 63.0 / 128.0;
ditherTable[y * 8 + x] = (uint8_t)((value + 0.5) * 255.f + 0.5f);
}
}
mDitherBmp.setInfo(SkImageInfo::MakeA8(8, 8));
mDitherBmp.setPixels(const_cast<uint8_t*>(ditherTable));
mDitherBmp.setImmutable();
#endif
mInitOK = initOK;
}
sk_sp<SkImage> SkiaDitherEffect::makeImage(GrDirectContext* context){
static GrDirectContext* current_context = nullptr;
if (current_context != context) {
mDitherImage = SkImage::MakeFromBitmap(mDitherBmp)->makeTextureImage(context);
current_context = context;
}
return mDitherImage;
}
sk_sp<SkShader> SkiaDitherEffect::createDitherShader(GrDirectContext* grContext, sk_sp<SkShader> input, const float ditherAlpha) {
sk_sp<SkImage> ditherImage = makeImage(grContext);
if (ditherImage == nullptr){
ALOGE("%s(), makeImage fail", __FUNCTION__);
}
SkString ditherString(R"(
uniform shader input;
uniform shader table;
uniform float ditherAlpha;
half4 main(float2 xy) {
float4 c = float4(sample(input, xy));
float dither = ((sample(table, xy).a) - 0.5)/256.0;
return float4(clamp(c.rgb*ditherAlpha+dither,0.0,1.0), c.a);
}
)");
#ifdef MTK_SKIA_DITHER_EFFECT_DEBUG
char ditherStringDbg[1024] = {0};
FILE* fp = fopen("/data/ditherStringDbg","rb");
if (fp) {
fread(ditherStringDbg, 1, sizeof(ditherStringDbg), fp);
int ret = fclose(fp);
if (CC_UNLIKELY(ret != 0)) {
ALOGE("%s(), fclose fail", __FUNCTION__);
}
} else {
ALOGE("open file /data/ditherStringDbg failed");
}
ALOGI("open file /data/ditherStringDbg");
ditherString = ditherStringDbg;
#endif
auto [ditherEffect, error] = SkRuntimeEffect::MakeForShader(ditherString);
if (!ditherEffect) {
ALOGE("%s(), RuntimeShader error: %s", __FUNCTION__, error.c_str());
return nullptr;
}
mDitherEffect = std::move(ditherEffect);
SkRuntimeShaderBuilder ditherBuilder(mDitherEffect);
ditherBuilder.child("input") = input;
ditherBuilder.child("table") =
ditherImage->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
SkSamplingOptions({SkFilterMode::kNearest, SkMipmapMode::kNone}));
ditherBuilder.uniform("ditherAlpha") = ditherAlpha;
return ditherBuilder.makeShader(nullptr, false);
}
#endif
} // namespace skia
} // namespace renderengine
} // namespace android