* Copyright (c) 2025 Huawei Device Co., Ltd.
* 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 "ge_sdf_shader_shape.h"
#include "draw/surface.h"
#include "ge_sdf_pixelmap_shader_shape.h"
#include "ge_sdf_rrect_shader_shape.h"
#include "ge_sdf_sub_op_shader_shape.h"
#include "ge_sdf_transform_shader_shape.h"
#include "ge_sdf_union_op_shader_shape.h"
#include "ge_shader_diagnostics.h"
#include "ge_log.h"
namespace OHOS {
namespace Rosen {
namespace Drawing {
namespace {
static constexpr char SHAPE_SDF_PROG[] = R"(
uniform shader sdfNormalImg;
vec4 main(vec2 fragCoord)
{
vec4 c1 = sdfNormalImg.eval(fragCoord).rgba;
return c1;
}
)";
thread_local static std::shared_ptr<Drawing::RuntimeEffect> g_shapeSDFShaderEffect = nullptr;
}
std::shared_ptr<ShaderEffect> GESDFShaderShape::GenerateDrawingShader(float width, float height) const
{
return nullptr;
}
std::shared_ptr<ShaderEffect> GESDFShaderShape::GenerateDrawingShaderHasNormal(float width, float height) const
{
return nullptr;
}
std::shared_ptr<ShaderEffect> GESDFShaderShape::GenerateDrawingShader(Canvas& canvas, float width, float height)
{
Preprocess(canvas, Rect(0.0, 0.0, width, height), false);
return GenerateDrawingShader(width, height);
}
std::shared_ptr<ShaderEffect> GESDFShaderShape::GenerateDrawingShaderHasNormal(Canvas& canvas,
float width, float height)
{
Preprocess(canvas, Rect(0.0, 0.0, width, height), true);
return GenerateDrawingShaderHasNormal(width, height);
}
void GESDFShaderShape::CopyState(const GESDFShaderShape& shape)
{
if (GetSDFShapeType() != shape.GetSDFShapeType()) {
LOGE("GESDFShaderShape::CopyState, forbid to copy state from different type shape!");
return;
}
if (GetSDFShapeType() == GESDFShapeType::RRECT) {
const auto* rectShape = static_cast<const GESDFRRectShaderShape*>(&shape);
auto* thisRect = static_cast<GESDFRRectShaderShape*>(this);
thisRect->CopyState(*rectShape);
} else if (GetSDFShapeType() == GESDFShapeType::UNION_OP) {
const auto* unionShape = static_cast<const GESDFUnionOpShaderShape*>(&shape);
auto* thisUnion = static_cast<GESDFUnionOpShaderShape*>(this);
thisUnion->CopyState(*unionShape);
} else if (GetSDFShapeType() == GESDFShapeType::SUB_OP) {
const auto* subOpShape = static_cast<const GESDFSubOpShaderShape*>(&shape);
auto* thisSubOp = static_cast<GESDFSubOpShaderShape*>(this);
thisSubOp->CopyState(*subOpShape);
} else if (GetSDFShapeType() == GESDFShapeType::SMOOTH_SUB_OP) {
const auto* smoothSubOpShape = static_cast<const GESDFSmoothSubOpShaderShape*>(&shape);
auto* thisSmoothSubOp = static_cast<GESDFSmoothSubOpShaderShape*>(this);
thisSmoothSubOp->CopyState(*smoothSubOpShape);
} else if (GetSDFShapeType() == GESDFShapeType::TRANSFORM) {
const auto* transformShape = static_cast<const GESDFTransformShaderShape*>(&shape);
auto* thisTransform = static_cast<GESDFTransformShaderShape*>(this);
thisTransform->CopyState(*transformShape);
} else if (GetSDFShapeType() == GESDFShapeType::PIXELMAP) {
const auto* pixelmapShape = static_cast<const GESDFPixelmapShaderShape*>(&shape);
auto* thisPixelmap = static_cast<GESDFPixelmapShaderShape*>(this);
thisPixelmap->CopyState(*pixelmapShape);
}
}
bool GESDFShaderShape::TryGetCenterAndHalfSize(float& outX, float& outY, Vector2f& shapeHalfSize) const
{
LOGE("GESDFShaderShape::TryGetCenterAndHalfSize error");
return false;
}
std::shared_ptr<Drawing::Image> GESDFShaderShape::MakeSDFImage(Canvas& canvas,
float width, float height, bool hasNormal)
{
if (g_shapeSDFShaderEffect == nullptr) {
Drawing::RuntimeEffectOptions reo{};
reo.needDrawingslToSksl = false;
reo.useHighpLocalCoords = true;
g_shapeSDFShaderEffect = GECreateRuntimeEffectForShader(SHAPE_SDF_PROG, reo);
}
if (g_shapeSDFShaderEffect == nullptr) {
GE_LOGE("GESDFShaderShape::MakeSDFImage create runtime error");
return nullptr;
}
auto shader = hasNormal ? GenerateDrawingShaderHasNormal(canvas, width, height) :
GenerateDrawingShader(canvas, width, height);
if (shader == nullptr) {
GE_LOGE("GESDFShaderShape::MakeSDFImage create shader error");
return nullptr;
}
auto builder = std::make_shared<Drawing::RuntimeShaderBuilder>(g_shapeSDFShaderEffect);
builder->SetChild("sdfNormalImg", shader);
auto canvasSurface = canvas.GetSurface();
std::shared_ptr<Drawing::ColorSpace> colorSpace = canvasSurface ?
canvasSurface->GetImageInfo().GetColorSpace() : nullptr;
Drawing::Matrix makeMatrix;
Drawing::ImageInfo imageInfo(width, height, Drawing::ColorType::COLORTYPE_RGBA_F16,
Drawing::AlphaType::ALPHATYPE_OPAQUE, colorSpace);
auto context = canvas.GetGPUContext().get();
return context ? builder->MakeImage(context, &(makeMatrix), imageInfo, false) : nullptr;
}
}
}
}