182 lines
6.8 KiB
C++
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
|