Skip to content

Commit

Permalink
Remove the makeContentSurface() and hasComplexPaint() methods from Ca…
Browse files Browse the repository at this point in the history
…nvas.
  • Loading branch information
domchen committed Feb 13, 2022
1 parent 9518578 commit 277eb30
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 95 deletions.
3 changes: 2 additions & 1 deletion src/rendering/graphics/Modifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "base/utils/UniqueID.h"
#include "core/Blend.h"
#include "gpu/Surface.h"
#include "rendering/utils/SurfaceUtil.h"

namespace pag {
static constexpr std::pair<Enum, Blend> kBlendModeMap[] = {
Expand Down Expand Up @@ -286,7 +287,7 @@ void MaskModifier::applyToGraphic(Canvas* canvas, RenderCache* cache,
// 与遮罩不相交,直接跳过绘制。
return;
}
auto contentSurface = canvas->makeContentSurface(bounds, FLT_MAX);
auto contentSurface = SurfaceUtil::MakeContentSurface(canvas, bounds, FLT_MAX);
if (contentSurface == nullptr) {
return;
}
Expand Down
34 changes: 28 additions & 6 deletions src/rendering/renderers/FilterRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "rendering/filters/MotionBlurFilter.h"
#include "rendering/filters/utils/FilterBuffer.h"
#include "rendering/filters/utils/FilterHelper.h"
#include "rendering/utils/SurfaceUtil.h"

namespace pag {
#define FAST_BLUR_MAX_SCALE_FACTOR 0.1f
Expand Down Expand Up @@ -160,7 +161,7 @@ void FilterRenderer::MeasureFilterBounds(Rect* bounds, const FilterModifier* mod
}

Rect GetClipBounds(Canvas* canvas, const FilterList* filterList) {
auto clip = canvas->getGlobalClip();
auto clip = canvas->getTotalClip();
auto matrix = canvas->getMatrix();
if (filterList->useParentSizeInput) {
Matrix inverted = Matrix::I();
Expand Down Expand Up @@ -345,6 +346,27 @@ void ApplyFilters(Context* context, std::vector<FilterNode> filterNodes, const R
}
}

static bool HasComplexPaint(Canvas* parentCanvas, const Rect& drawingBounds) {
if (parentCanvas->getAlpha() != Opaque) {
return true;
}
if (parentCanvas->getBlendMode() != Blend::SrcOver) {
return true;
}
auto bounds = drawingBounds;
auto matrix = parentCanvas->getMatrix();
matrix.mapRect(&bounds);
auto surface = parentCanvas->getSurface();
auto surfaceBounds =
Rect::MakeWH(static_cast<float>(surface->width()), static_cast<float>(surface->height()));
bounds.intersect(surfaceBounds);
auto clip = parentCanvas->getTotalClip();
if (!clip.contains(bounds)) {
return true;
}
return false;
}

std::unique_ptr<FilterTarget> GetDirectFilterTarget(Canvas* parentCanvas,
const FilterList* filterList,
const std::vector<FilterNode>& filterNodes,
Expand All @@ -361,7 +383,7 @@ std::unique_ptr<FilterTarget> GetDirectFilterTarget(Canvas* parentCanvas,
// 因为计算filter的顶点位置的bounds都是没有经过裁切的
auto transformBounds = contentBounds;
TransformFilterBounds(&transformBounds, filterList);
if (parentCanvas->hasComplexPaint(transformBounds) != PaintKind::None) {
if (HasComplexPaint(parentCanvas, transformBounds)) {
return nullptr;
}
auto surface = parentCanvas->getSurface();
Expand Down Expand Up @@ -431,7 +453,7 @@ void FilterRenderer::DrawWithFilter(Canvas* parentCanvas, RenderCache* cache,
}
ProcessFastBlur(filterList.get());
auto contentSurface =
parentCanvas->makeContentSurface(contentBounds, filterList->scaleFactorLimit);
SurfaceUtil::MakeContentSurface(parentCanvas, contentBounds, filterList->scaleFactorLimit);
if (contentSurface == nullptr) {
return;
}
Expand All @@ -446,9 +468,9 @@ void FilterRenderer::DrawWithFilter(Canvas* parentCanvas, RenderCache* cache,
parentCanvas, filterList.get(), filterNodes, contentBounds, filterSource->scale);
if (filterTarget == nullptr) {
// 需要离屏绘制
targetSurface =
parentCanvas->makeContentSurface(filterNodes.back().bounds, filterList->scaleFactorLimit,
filterNodes.back().filter->needsMSAA());
targetSurface = SurfaceUtil::MakeContentSurface(parentCanvas, filterNodes.back().bounds,
filterList->scaleFactorLimit,
filterNodes.back().filter->needsMSAA());
if (targetSurface == nullptr) {
return;
}
Expand Down
49 changes: 49 additions & 0 deletions src/rendering/utils/SurfaceUtil.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Tencent is pleased to support the open source community by making libpag available.
//
// Copyright (C) 2021 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.
//
/////////////////////////////////////////////////////////////////////////////////////////////////

#include "SurfaceUtil.h"
#include "base/utils/MatrixUtil.h"

namespace pag {
// 1/20 is the minimum precision for rendering pixels on most platforms.
#define CONTENT_SCALE_STEP 20.0f

std::shared_ptr<Surface> SurfaceUtil::MakeContentSurface(Canvas* parentCanvas, const Rect& bounds,
float scaleFactorLimit, bool usesMSAA) {
auto maxScale = GetMaxScaleFactor(parentCanvas->getMatrix());
if (maxScale > scaleFactorLimit) {
maxScale = scaleFactorLimit;
} else {
// Snap the scale value to 1/20 to prevent edge shaking when rendering zoom-in animations.
maxScale = ceilf(maxScale * CONTENT_SCALE_STEP) / CONTENT_SCALE_STEP;
}
auto width = static_cast<int>(ceilf(bounds.width() * maxScale));
auto height = static_cast<int>(ceil(bounds.height() * maxScale));
// LOGE("makeContentSurface: (width = %d, height = %d)", width, height);
auto sampleCount = usesMSAA ? 4 : 1;
auto newSurface = Surface::Make(parentCanvas->getContext(), width, height, false, sampleCount);
if (newSurface == nullptr) {
return nullptr;
}
auto newCanvas = newSurface->getCanvas();
auto matrix = Matrix::MakeScale(maxScale);
matrix.preTranslate(-bounds.x(), -bounds.y());
newCanvas->setMatrix(matrix);
return newSurface;
}
} // namespace pag
30 changes: 30 additions & 0 deletions src/rendering/utils/SurfaceUtil.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Tencent is pleased to support the open source community by making libpag available.
//
// Copyright (C) 2021 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 "gpu/Surface.h"

namespace pag {
class SurfaceUtil {
public:
static std::shared_ptr<Surface> MakeContentSurface(Canvas* parentCanvas, const Rect& bounds,
float scaleFactorLimit = FLT_MAX,
bool usesMSAA = false);
};
} // namespace pag
55 changes: 19 additions & 36 deletions tgfx/include/gpu/Canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,6 @@ class Surface;

class SurfaceOptions;

struct PaintKind {
public:
static const Enum None = 0;
static const Enum Alpha = 1 << 0;
static const Enum Blend = 1 << 1;
static const Enum Clip = 1 << 2;
};

struct CanvasPaint {
Opacity alpha = Opaque;
Blend blendMode = Blend::SrcOver;
Expand All @@ -57,6 +49,21 @@ class Canvas {

virtual ~Canvas() = default;

/**
* Retrieves the context associated with this Surface.
*/
Context* getContext() const;

/**
* Returns the Surface this canvas draws into.
*/
Surface* getSurface() const;

/**
* Returns SurfaceOptions associated with this canvas.
*/
const SurfaceOptions* surfaceOptions() const;

/**
* Saves alpha, blend mode, matrix and clip. Calling restore() discards changes to them, restoring
* them to their state when save() was called. Saved Canvas state is put on a stack, multiple
Expand Down Expand Up @@ -117,7 +124,7 @@ class Canvas {
/**
* Returns the current total clip.
*/
Path getGlobalClip() const;
Path getTotalClip() const;

/**
* Replaces clip with the intersection of clip and path. The path is transformed by Matrix before
Expand All @@ -131,7 +138,8 @@ class Canvas {
virtual void clear() = 0;

/**
* Draws a rectangle using current clip, matrix, and specified paint.
* Draws a rectangle with specified paint, using current current alpha, blend mode, clip and
* matrix.
*/
void drawRect(const Rect& rect, const Paint& paint);

Expand All @@ -143,7 +151,7 @@ class Canvas {

/**
* Draws a RGBAAA layout Texture, with its top-left corner at (0, 0), using current alpha, blend
* mode, clip and Matrix.
* mode, clip and matrix.
*/
virtual void drawTexture(const Texture* texture, const RGBAAALayout* layout) = 0;

Expand Down Expand Up @@ -176,31 +184,6 @@ class Canvas {
virtual void flush() {
}

/**
* Returns the paint kinds of this canvas for specified area.
*/
virtual Enum hasComplexPaint(const Rect& drawingBounds) const = 0;

/**
* Retrieves the context associated with this Surface.
*/
Context* getContext() const;

/**
* Returns the Surface this canvas draws into.
*/
Surface* getSurface() const {
return surface;
}

/**
* Returns SurfaceOptions associated with this canvas.
*/
const SurfaceOptions* surfaceOptions() const;

std::shared_ptr<Surface> makeContentSurface(const Rect& bounds, float scaleFactorLimit = FLT_MAX,
bool usesMSAA = false) const;

protected:
Surface* surface = nullptr;
CanvasPaint globalPaint = {};
Expand Down
37 changes: 5 additions & 32 deletions tgfx/src/gpu/Canvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,9 @@
/////////////////////////////////////////////////////////////////////////////////////////////////

#include "gpu/Canvas.h"
#include "base/utils/MatrixUtil.h"
#include "gpu/Surface.h"

namespace pag {
#define CONTENT_SCALE_STEP 20.0f

Canvas::Canvas(Surface* surface) : surface(surface) {
globalPaint.clip.addRect(0, 0, static_cast<float>(surface->width()),
static_cast<float>(surface->height()));
Expand Down Expand Up @@ -77,7 +74,7 @@ void Canvas::setBlendMode(Blend blendMode) {
globalPaint.blendMode = blendMode;
}

Path Canvas::getGlobalClip() const {
Path Canvas::getTotalClip() const {
return globalPaint.clip;
}

Expand Down Expand Up @@ -109,35 +106,11 @@ Context* Canvas::getContext() const {
return surface->getContext();
}

const SurfaceOptions* Canvas::surfaceOptions() const {
return surface->options();
Surface* Canvas::getSurface() const {
return surface;
}

std::shared_ptr<Surface> Canvas::makeContentSurface(const Rect& bounds, float scaleFactorLimit,
bool usesMSAA) const {
auto totalMatrix = getMatrix();
auto maxScale = GetMaxScaleFactor(totalMatrix);
if (maxScale > scaleFactorLimit) {
maxScale = scaleFactorLimit;
} else {
// Corrected the zoom value to snap to 1/20th the accuracy of pixels to prevent edge jitter
// during gradual zoom-in.
// 1/20 is the minimum pixel accuracy for most platforms, and there is no jitter when drawing
// on the screen.
maxScale = ceilf(maxScale * CONTENT_SCALE_STEP) / CONTENT_SCALE_STEP;
}
auto width = static_cast<int>(ceilf(bounds.width() * maxScale));
auto height = static_cast<int>(ceil(bounds.height() * maxScale));
// LOGE("makeContentSurface: (width = %d, height = %d)", width, height);
auto sampleCount = usesMSAA ? 4 : 1;
auto newSurface = Surface::Make(getContext(), width, height, false, sampleCount);
if (newSurface == nullptr) {
return nullptr;
}
auto newCanvas = newSurface->getCanvas();
auto matrix = Matrix::MakeScale(maxScale);
matrix.preTranslate(-bounds.x(), -bounds.y());
newCanvas->setMatrix(matrix);
return newSurface;
const SurfaceOptions* Canvas::surfaceOptions() const {
return surface->options();
}
} // namespace pag
19 changes: 0 additions & 19 deletions tgfx/src/gpu/opengl/GLCanvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,25 +302,6 @@ void GLCanvas::drawMaskGlyphs(TextBlob* textBlob, const Paint& paint) {
drawMask(clippedDeviceQuad, texture.get(), shader.get());
}

Enum GLCanvas::hasComplexPaint(const Rect& drawingBounds) const {
auto bounds = drawingBounds;
globalPaint.matrix.mapRect(&bounds);
auto result = PaintKind::None;
if (globalPaint.alpha != Opaque) {
result |= PaintKind::Alpha;
}
if (globalPaint.blendMode != Blend::SrcOver) {
result |= PaintKind::Blend;
}
auto surfaceBounds =
Rect::MakeWH(static_cast<float>(surface->width()), static_cast<float>(surface->height()));
bounds.intersect(surfaceBounds);
if (!globalPaint.clip.contains(bounds)) {
result |= PaintKind::Clip;
}
return result;
}

GLDrawer* GLCanvas::getDrawer() {
if (_drawer == nullptr) {
_drawer = GLDrawer::Make(getContext());
Expand Down
1 change: 0 additions & 1 deletion tgfx/src/gpu/opengl/GLCanvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ class GLCanvas : public Canvas {
void drawPath(const Path& path, const Paint& paint) override;
void drawGlyphs(const GlyphID glyphIDs[], const Point positions[], size_t glyphCount,
const Font& font, const Paint& paint) override;
Enum hasComplexPaint(const Rect& drawingBounds) const override;

protected:
void onSave() override {
Expand Down

0 comments on commit 277eb30

Please sign in to comment.