Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LayerStyle supports deferred rendering. #2607

Merged
merged 16 commits into from
Dec 11, 2024
Merged
6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 1 addition & 7 deletions src/rendering/caches/RenderCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,12 +568,6 @@ void RenderCache::clearSequenceCache(ID uniqueID) {

//===================================== filter caches =====================================

LayerFilter* RenderCache::getFilterCache(LayerStyle* layerStyle) {
return getLayerFilterCache(layerStyle->uniqueID, [=]() -> LayerFilter* {
return LayerFilter::Make(layerStyle).release();
});
}

LayerFilter* RenderCache::getFilterCache(Effect* effect) {
return getLayerFilterCache(effect->uniqueID,
[=]() -> LayerFilter* { return LayerFilter::Make(effect).release(); });
Expand Down Expand Up @@ -620,7 +614,7 @@ LayerStylesFilter* RenderCache::getLayerStylesFilter(Layer* layer) {
LayerStylesFilter* filter = nullptr;
auto result = filterCaches.find(layer->uniqueID);
if (result == filterCaches.end()) {
filter = new LayerStylesFilter(this);
filter = new LayerStylesFilter();
if (initFilter(filter)) {
filterCaches.insert(std::make_pair(layer->uniqueID, filter));
} else {
Expand Down
2 changes: 0 additions & 2 deletions src/rendering/caches/RenderCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,6 @@ class RenderCache : public Performance {
std::shared_ptr<tgfx::Image> getSequenceImage(std::shared_ptr<SequenceInfo> sequence,
Frame targetFrame);

LayerFilter* getFilterCache(LayerStyle* layerStyle);

LayerFilter* getFilterCache(Effect* effect);

MotionBlurFilter* getMotionBlurFilter();
Expand Down
7 changes: 7 additions & 0 deletions src/rendering/filters/Filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#pragma once

#include <tgfx/gpu/ImageOrigin.h>
#include <array>
#include "tgfx/core/Matrix.h"
#include "tgfx/gpu/Backend.h"
Expand Down Expand Up @@ -48,12 +49,18 @@ struct FilterSource {
*/
tgfx::Point scale = {};

/**
* The origin of the source image.
*/
tgfx::ImageOrigin origin = tgfx::ImageOrigin::TopLeft;

/**
* The 3x3 texture coordinate transform matrix. This transform matrix maps 2D texture coordinates
* of the form (s, t, 0, 1) with s and t in the inclusive range [0, 1] to the texture coordinate
* that should be used to sample that location from the texture. Sampling the texture outside of
* the range of this transform is undefined. The matrix is stored in column-major order so that it
* may be passed directly to OpenGL ES via the glLoadMatrixf or glUniformMatrix4fv functions.
* note:The texture matrix is the data after applying the ImageOrigin.
*/
std::array<float, 9> textureMatrix = {};
};
Expand Down
24 changes: 0 additions & 24 deletions src/rendering/filters/LayerFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include "BulgeFilter.h"
#include "CornerPinFilter.h"
#include "DisplacementMapFilter.h"
#include "GradientOverlayFilter.h"
#include "HueSaturationFilter.h"
#include "LevelsIndividualFilter.h"
#include "MosaicFilter.h"
Expand All @@ -30,8 +29,6 @@
#include "rendering/filters/gaussianblur/GaussianBlurFilter.h"
#include "rendering/filters/glow/GlowFilter.h"
#include "rendering/filters/layerstyle/DropShadowFilter.h"
#include "rendering/filters/layerstyle/OuterGlowFilter.h"
#include "rendering/filters/layerstyle/StrokeFilter.h"
#include "rendering/filters/utils/FilterHelper.h"

namespace pag {
Expand Down Expand Up @@ -116,27 +113,6 @@ void FilterProgram::onReleaseGPU() {
}
}

std::unique_ptr<LayerFilter> LayerFilter::Make(LayerStyle* layerStyle) {
LayerFilter* filter = nullptr;
switch (layerStyle->type()) {
case LayerStyleType::DropShadow:
filter = new DropShadowFilter(reinterpret_cast<DropShadowStyle*>(layerStyle));
break;
case LayerStyleType::OuterGlow:
filter = new OuterGlowFilter(reinterpret_cast<OuterGlowStyle*>(layerStyle));
break;
case LayerStyleType::Stroke:
filter = new StrokeFilter(reinterpret_cast<StrokeStyle*>(layerStyle));
break;
case LayerStyleType::GradientOverlay:
filter = new GradientOverlayFilter(reinterpret_cast<GradientOverlayStyle*>(layerStyle));
break;
default:
break;
}
return std::unique_ptr<LayerFilter>(filter);
}

std::unique_ptr<LayerFilter> LayerFilter::Make(Effect* effect) {
LayerFilter* filter = nullptr;
switch (effect->type()) {
Expand Down
2 changes: 0 additions & 2 deletions src/rendering/filters/LayerFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ class FilterProgram : public tgfx::GLResource {

class LayerFilter : public Filter {
public:
static std::unique_ptr<LayerFilter> Make(LayerStyle* layerStyle);

static std::unique_ptr<LayerFilter> Make(Effect* effect);

bool initialize(tgfx::Context* context) override;
Expand Down
53 changes: 31 additions & 22 deletions src/rendering/filters/LayerStylesFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
/////////////////////////////////////////////////////////////////////////////////////////////////

#include "LayerStylesFilter.h"
#include <tgfx/core/Surface.h>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不用尖括号

#include "layerstyle/LayerStyleFilter.h"
#include "rendering/caches/RenderCache.h"
#include "rendering/renderers/FilterRenderer.h"

Expand All @@ -31,34 +33,39 @@ void LayerStylesFilter::TransformBounds(tgfx::Rect* bounds, const FilterList* fi
}
}

LayerStylesFilter::LayerStylesFilter(RenderCache* renderCache) : renderCache(renderCache) {
drawFilter = new LayerFilter();
bool LayerStylesFilter::initialize(tgfx::Context*) {
return true;
}

LayerStylesFilter::~LayerStylesFilter() {
delete drawFilter;
}

bool LayerStylesFilter::initialize(tgfx::Context* context) {
return drawFilter->initialize(context);
}

void LayerStylesFilter::update(const FilterList* list, const tgfx::Rect& inputBounds,
const tgfx::Rect& outputBounds, const tgfx::Point& extraScale) {
void LayerStylesFilter::update(const FilterList* list, const tgfx::Point& extraScale) {
filterList = list;
contentBounds = inputBounds;
transformedBounds = outputBounds;
filterScale = extraScale;
}

void LayerStylesFilter::draw(tgfx::Context* context, const FilterSource* source,
const FilterTarget* target) {
tgfx::BackendTexture backendTexture = {source->sampler, source->width, source->height};
auto sourceImage = tgfx::Image::MakeFrom(context, backendTexture, source->origin);
if (sourceImage == nullptr) {
return;
}

tgfx::BackendRenderTarget renderTarget = {target->frameBuffer, target->width, target->height};
auto surface = tgfx::Surface::MakeFrom(context, renderTarget, tgfx::ImageOrigin::TopLeft);
if (surface == nullptr) {
return;
}
auto canvas = surface->getCanvas();
canvas->concat(ToMatrix(target));
auto totalScale = filterScale;
totalScale.x *= source->scale.x;
totalScale.y *= source->scale.y;
for (auto& layerStyle : filterList->layerStyles) {
if (layerStyle->drawPosition() == LayerStylePosition::Blow) {
auto filter = renderCache->getFilterCache(layerStyle);
auto filter = LayerStyleFilter::Make(layerStyle);
if (filter) {
filter->update(filterList->layerFrame, contentBounds, transformedBounds, filterScale);
filter->draw(context, source, target);
filter->update(filterList->layerFrame, totalScale);
filter->draw(canvas, sourceImage);
}
}
}
Expand All @@ -68,18 +75,20 @@ void LayerStylesFilter::draw(tgfx::Context* context, const FilterSource* source,
bool drawSource = true;
for (auto& layerStyle : filterList->layerStyles) {
if (layerStyle->drawPosition() == LayerStylePosition::Above) {
auto filter = renderCache->getFilterCache(layerStyle);
auto filter = LayerStyleFilter::Make(layerStyle);
if (filter) {
filter->update(filterList->layerFrame, contentBounds, transformedBounds, filterScale);
filter->draw(context, source, target);
// GradientOverlayFilter is scale-invariant for the source image, so we can use the filter
// scale directly.
filter->update(filterList->layerFrame, filterScale);
filter->draw(canvas, sourceImage);
drawSource = false;
}
}
}

if (drawSource) {
drawFilter->update(filterList->layerFrame, contentBounds, contentBounds, filterScale);
drawFilter->draw(context, source, target);
canvas->drawImage(sourceImage);
}
context->flush();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里删掉

}
} // namespace pag
13 changes: 1 addition & 12 deletions src/rendering/filters/LayerStylesFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,21 @@
#include "rendering/filters/LayerFilter.h"

namespace pag {
class RenderCache;

struct FilterList;

class LayerStylesFilter : public Filter {
public:
static void TransformBounds(tgfx::Rect* bounds, const FilterList* filterList);

explicit LayerStylesFilter(RenderCache* renderCache);

~LayerStylesFilter() override;

bool initialize(tgfx::Context* context) override;

void update(const FilterList* filterList, const tgfx::Rect& contentBounds,
const tgfx::Rect& transformedBounds, const tgfx::Point& filterScale);
void update(const FilterList* filterList, const tgfx::Point& filterScale);

void draw(tgfx::Context* context, const FilterSource* source,
const FilterTarget* target) override;

private:
const FilterList* filterList = nullptr;
RenderCache* renderCache = nullptr;
LayerFilter* drawFilter = nullptr;
tgfx::Rect contentBounds = {};
tgfx::Rect transformedBounds = {};
tgfx::Point filterScale = {};
};
} // namespace pag
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
//
/////////////////////////////////////////////////////////////////////////////////////////////////

#include "AlphaEdgeDetectFilter.h"
#include "AlphaEdgeDetectEffect.h"

namespace pag {
static const char FRAGMENT_SHADER[] = R"(
Expand Down Expand Up @@ -44,23 +44,22 @@ static const char FRAGMENT_SHADER[] = R"(
}
)";

AlphaEdgeDetectFilter::AlphaEdgeDetectFilter() {
}

std::string AlphaEdgeDetectFilter::onBuildFragmentShader() {
std::string AlphaEdgeDetectLayerEffect::onBuildFragmentShader() const {
return FRAGMENT_SHADER;
}

void AlphaEdgeDetectFilter::onPrepareProgram(tgfx::Context* context, unsigned int program) {
auto gl = tgfx::GLFunctions::Get(context);
horizontalStepHandle = gl->getUniformLocation(program, "mHorizontalStep");
verticalStepHandle = gl->getUniformLocation(program, "mVerticalStep");
std::unique_ptr<Uniforms> AlphaEdgeDetectLayerEffect::onPrepareProgram(tgfx::Context* context,
unsigned program) const {
return std::make_unique<AlphaEdgeDetectEffectUniforms>(context, program);
}

void AlphaEdgeDetectFilter::onUpdateParams(tgfx::Context* context, const tgfx::Rect& contentBounds,
const tgfx::Point&) {
void AlphaEdgeDetectLayerEffect::onUpdateParams(
tgfx::Context* context, const EffectProgram* program,
const std::vector<tgfx::BackendTexture>& sources) const {
auto uniforms = static_cast<AlphaEdgeDetectEffectUniforms*>(program->uniforms.get());
auto gl = tgfx::GLFunctions::Get(context);
gl->uniform1f(horizontalStepHandle, 1.0f / contentBounds.width());
gl->uniform1f(verticalStepHandle, 1.0f / contentBounds.height());
gl->uniform1f(uniforms->horizontalStepHandle, 1.0f / sources[0].width());
gl->uniform1f(uniforms->verticalStepHandle, 1.0f / sources[0].height());
}

} // namespace pag
53 changes: 53 additions & 0 deletions src/rendering/filters/effects/AlphaEdgeDetectEffect.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Tencent is pleased to support the open source community by making libpag available.
//
// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
//
// 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.
//
/////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#include "FilterEffect.h"
#include "rendering/filters/LayerFilter.h"

namespace pag {

class AlphaEdgeDetectEffectUniforms : public Uniforms {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

都改名为Filter,避免和PAG的Effect概念冲突。

public:
AlphaEdgeDetectEffectUniforms(tgfx::Context* context, unsigned program)
: Uniforms(context, program) {
auto gl = tgfx::GLFunctions::Get(context);
horizontalStepHandle = gl->getUniformLocation(program, "mHorizontalStep");
verticalStepHandle = gl->getUniformLocation(program, "mVerticalStep");
}
int horizontalStepHandle = -1;
int verticalStepHandle = -1;
};

class AlphaEdgeDetectLayerEffect : public FilterEffect {
public:
DEFINE_RUNTIME_EFFECT_TYPE;
explicit AlphaEdgeDetectLayerEffect() : FilterEffect(Type()) {
}

std::string onBuildFragmentShader() const override;

std::unique_ptr<Uniforms> onPrepareProgram(tgfx::Context* context,
unsigned program) const override;

void onUpdateParams(tgfx::Context* context, const EffectProgram* program,
const std::vector<tgfx::BackendTexture>& sources) const override;
};

} // namespace pag
Loading
Loading