RESTRICT AUTOMERGE pixel-snap on HWUI side

Bug: 254771190
Test: android.uirendering.cts.testclasses.ExactCanvasTests#testDrawLine
Change-Id: Idfb5027fe3230f2c2b0cad224f2c7640e147ce4a
This commit is contained in:
John Reck
2023-03-21 12:29:21 -04:00
parent 8df7edf0e3
commit 38323c18fe
9 changed files with 56 additions and 1 deletions

View File

@@ -39,6 +39,9 @@
#include "VectorDrawable.h"
#include "pipeline/skia/AnimatedDrawables.h"
#include "pipeline/skia/FunctorDrawable.h"
#ifdef __ANDROID__
#include "renderthread/CanvasContext.h"
#endif
namespace android {
namespace uirenderer {
@@ -434,7 +437,19 @@ struct DrawPoints final : Op {
size_t count;
SkPaint paint;
void draw(SkCanvas* c, const SkMatrix&) const {
c->drawPoints(mode, count, pod<SkPoint>(this), paint);
if (paint.isAntiAlias()) {
c->drawPoints(mode, count, pod<SkPoint>(this), paint);
} else {
c->save();
#ifdef __ANDROID__
auto pixelSnap = renderthread::CanvasContext::getActiveContext()->getPixelSnapMatrix();
auto transform = c->getLocalToDevice();
transform.postConcat(pixelSnap);
c->setMatrix(transform);
#endif
c->drawPoints(mode, count, pod<SkPoint>(this), paint);
c->restore();
}
}
};
struct DrawVertices final : Op {

View File

@@ -53,6 +53,14 @@ public:
bool isSurfaceReady() override;
bool isContextReady() override;
const SkM44& getPixelSnapMatrix() const override {
// Small (~1/16th) nudge to ensure that pixel-aligned non-AA'd draws fill the
// desired fragment
static const SkScalar kOffset = 0.063f;
static const SkM44 sSnapMatrix = SkM44::Translate(kOffset, kOffset);
return sSnapMatrix;
}
static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
protected:

View File

@@ -180,6 +180,10 @@ void SkiaVulkanPipeline::onContextDestroyed() {
}
}
const SkM44& SkiaVulkanPipeline::getPixelSnapMatrix() const {
return mVkSurface->getPixelSnapMatrix();
}
} /* namespace skiapipeline */
} /* namespace uirenderer */
} /* namespace android */

View File

@@ -49,6 +49,7 @@ public:
void onStop() override;
bool isSurfaceReady() override;
bool isContextReady() override;
const SkM44& getPixelSnapMatrix() const override;
static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
static sk_sp<Bitmap> allocateHardwareBitmap(renderthread::RenderThread& thread,

View File

@@ -793,6 +793,10 @@ SkISize CanvasContext::getNextFrameSize() const {
return size;
}
const SkM44& CanvasContext::getPixelSnapMatrix() const {
return mRenderPipeline->getPixelSnapMatrix();
}
void CanvasContext::prepareAndDraw(RenderNode* node) {
ATRACE_CALL();

View File

@@ -195,6 +195,9 @@ public:
SkISize getNextFrameSize() const;
// Returns the matrix to use to nudge non-AA'd points/lines towards the fragment center
const SkM44& getPixelSnapMatrix() const;
// Called when SurfaceStats are available.
static void onSurfaceStatsAvailable(void* context, int32_t surfaceControlId,
ASurfaceControlStats* stats);

View File

@@ -88,6 +88,8 @@ public:
virtual void setPictureCapturedCallback(
const std::function<void(sk_sp<SkPicture>&&)>& callback) = 0;
virtual const SkM44& getPixelSnapMatrix() const = 0;
virtual ~IRenderPipeline() {}
};

View File

@@ -63,6 +63,18 @@ static SkMatrix GetPreTransformMatrix(SkISize windowSize, int transform) {
return SkMatrix::I();
}
static SkM44 GetPixelSnapMatrix(SkISize windowSize, int transform) {
// Small (~1/16th) nudge to ensure that pixel-aligned non-AA'd draws fill the
// desired fragment
static const SkScalar kOffset = 0.063f;
SkMatrix preRotation = GetPreTransformMatrix(windowSize, transform);
SkMatrix invert;
LOG_ALWAYS_FATAL_IF(!preRotation.invert(&invert));
return SkM44::Translate(kOffset, kOffset)
.postConcat(SkM44(preRotation))
.preConcat(SkM44(invert));
}
static bool ConnectAndSetWindowDefaults(ANativeWindow* window) {
ATRACE_CALL();
@@ -178,6 +190,8 @@ bool VulkanSurface::InitializeWindowInfoStruct(ANativeWindow* window, ColorMode
outWindowInfo->preTransform =
GetPreTransformMatrix(outWindowInfo->size, outWindowInfo->transform);
outWindowInfo->pixelSnapMatrix =
GetPixelSnapMatrix(outWindowInfo->size, outWindowInfo->transform);
err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value);
if (err != 0 || query_value < 0) {
@@ -406,6 +420,7 @@ VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() {
}
mWindowInfo.preTransform = GetPreTransformMatrix(mWindowInfo.size, mWindowInfo.transform);
mWindowInfo.pixelSnapMatrix = GetPixelSnapMatrix(mWindowInfo.size, mWindowInfo.transform);
}
uint32_t idx;

View File

@@ -45,6 +45,8 @@ public:
}
const SkMatrix& getCurrentPreTransform() { return mWindowInfo.preTransform; }
const SkM44& getPixelSnapMatrix() const { return mWindowInfo.pixelSnapMatrix; }
private:
/*
* All structs/methods in this private section are specifically for use by the VulkanManager
@@ -101,6 +103,7 @@ private:
SkISize actualSize;
// transform to be applied to the SkSurface to map the coordinates to the provided transform
SkMatrix preTransform;
SkM44 pixelSnapMatrix;
};
VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo, GrDirectContext* grContext);