Add support for preTransform in Vulkan swapchain.
Test: manual building and running of apps.
Bug: 110985606
Bug: 122662274
Change-Id: Id53aa1ce028b448b1f12558eec78a60e09512166
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index e6e6b0e..cfbb995 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -100,7 +100,8 @@
mSurfaceColorSpace, &props));
SkiaPipeline::updateLighting(lightGeometry, lightInfo);
- renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
+ renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
+ SkMatrix::I());
layerUpdateQueue->clear();
// Draw visual debugging features
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index d7faaf7..df82243 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -312,7 +312,8 @@
void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
const std::vector<sp<RenderNode>>& nodes, bool opaque,
- const Rect& contentDrawBounds, sk_sp<SkSurface> surface) {
+ const Rect& contentDrawBounds, sk_sp<SkSurface> surface,
+ const SkMatrix& preTransform) {
renderVectorDrawableCache();
// draw all layers up front
@@ -323,12 +324,12 @@
std::unique_ptr<SkPictureRecorder> recorder;
SkCanvas* canvas = tryCapture(surface.get());
- renderFrameImpl(layers, clip, nodes, opaque, contentDrawBounds, canvas);
+ renderFrameImpl(layers, clip, nodes, opaque, contentDrawBounds, canvas, preTransform);
endCapture(surface.get());
if (CC_UNLIKELY(Properties::debugOverdraw)) {
- renderOverdraw(layers, clip, nodes, contentDrawBounds, surface);
+ renderOverdraw(layers, clip, nodes, contentDrawBounds, surface, preTransform);
}
ATRACE_NAME("flush commands");
@@ -344,9 +345,11 @@
void SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip,
const std::vector<sp<RenderNode>>& nodes, bool opaque,
- const Rect& contentDrawBounds, SkCanvas* canvas) {
+ const Rect& contentDrawBounds, SkCanvas* canvas,
+ const SkMatrix& preTransform) {
SkAutoCanvasRestore saver(canvas, true);
- canvas->androidFramework_setDeviceClipRestriction(clip.roundOut());
+ canvas->androidFramework_setDeviceClipRestriction(preTransform.mapRect(clip).roundOut());
+ canvas->concat(preTransform);
// STOPSHIP: Revert, temporary workaround to clear always F16 frame buffer for b/74976293
if (!opaque || getSurfaceColorType() == kRGBA_F16_SkColorType) {
@@ -486,7 +489,8 @@
void SkiaPipeline::renderOverdraw(const LayerUpdateQueue& layers, const SkRect& clip,
const std::vector<sp<RenderNode>>& nodes,
- const Rect& contentDrawBounds, sk_sp<SkSurface> surface) {
+ const Rect& contentDrawBounds, sk_sp<SkSurface> surface,
+ const SkMatrix& preTransform) {
// Set up the overdraw canvas.
SkImageInfo offscreenInfo = SkImageInfo::MakeA8(surface->width(), surface->height());
sk_sp<SkSurface> offscreen = surface->makeSurface(offscreenInfo);
@@ -496,7 +500,7 @@
// each time a pixel would have been drawn.
// Pass true for opaque so we skip the clear - the overdrawCanvas is already zero
// initialized.
- renderFrameImpl(layers, clip, nodes, true, contentDrawBounds, &overdrawCanvas);
+ renderFrameImpl(layers, clip, nodes, true, contentDrawBounds, &overdrawCanvas, preTransform);
sk_sp<SkImage> counts = offscreen->makeImageSnapshot();
// Draw overdraw colors to the canvas. The color filter will convert counts to colors.
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index 94a699b..cf6f5b2 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -53,7 +53,8 @@
void renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
const std::vector<sp<RenderNode>>& nodes, bool opaque,
- const Rect& contentDrawBounds, sk_sp<SkSurface> surface);
+ const Rect& contentDrawBounds, sk_sp<SkSurface> surface,
+ const SkMatrix& preTransform);
std::vector<VectorDrawableRoot*>* getVectorDrawables() { return &mVectorDrawables; }
@@ -116,7 +117,8 @@
private:
void renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip,
const std::vector<sp<RenderNode>>& nodes, bool opaque,
- const Rect& contentDrawBounds, SkCanvas* canvas);
+ const Rect& contentDrawBounds, SkCanvas* canvas,
+ const SkMatrix& preTransform);
/**
* Debugging feature. Draws a semi-transparent overlay on each pixel, indicating
@@ -124,7 +126,7 @@
*/
void renderOverdraw(const LayerUpdateQueue& layers, const SkRect& clip,
const std::vector<sp<RenderNode>>& nodes, const Rect& contentDrawBounds,
- sk_sp<SkSurface>);
+ sk_sp<SkSurface> surface, const SkMatrix& preTransform);
/**
* Render mVectorDrawables into offscreen buffers.
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index b9aae98..53495a7 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -58,7 +58,8 @@
return Frame(-1, -1, 0);
}
- Frame frame(backBuffer->width(), backBuffer->height(), mVkManager.getAge(mVkSurface));
+ Frame frame(mVkSurface->windowWidth(), mVkSurface->windowHeight(),
+ mVkManager.getAge(mVkSurface));
return frame;
}
@@ -73,7 +74,8 @@
return false;
}
SkiaPipeline::updateLighting(lightGeometry, lightInfo);
- renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer);
+ renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds,
+ backBuffer, mVkSurface->preTransform());
ShaderCache::get().onVkFrameFlushed(mRenderThread.getGrContext());
layerUpdateQueue->clear();
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 6c540f6..5c6cb9a 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -480,6 +480,32 @@
return backbuffer;
}
+static SkMatrix getPreTransformMatrix(int width, int height,
+ VkSurfaceTransformFlagBitsKHR transform) {
+ switch (transform) {
+ case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
+ return SkMatrix::I();
+ case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
+ return SkMatrix::MakeAll(0, -1, height, 1, 0, 0, 0, 0, 1);
+ case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
+ return SkMatrix::MakeAll(-1, 0, width, 0, -1, height, 0, 0, 1);
+ case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
+ return SkMatrix::MakeAll(0, 1, 0, -1, 0, width, 0, 0, 1);
+ case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
+ return SkMatrix::MakeAll(-1, 0, width, 0, 1, 0, 0, 0, 1);
+ case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
+ return SkMatrix::MakeAll(0, -1, height, -1, 0, width, 0, 0, 1);
+ case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
+ return SkMatrix::MakeAll(1, 0, 0, 0, -1, height, 0, 0, 1);
+ case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
+ return SkMatrix::MakeAll(0, 1, 0, 1, 0, 0, 0, 0, 1);
+ default:
+ LOG_ALWAYS_FATAL("Unsupported pre transform of swapchain.");
+ }
+ return SkMatrix::I();
+}
+
+
SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) {
// Recreate VulkanSurface, if ANativeWindow has been resized.
VulkanSurface* surface = *surfaceOut;
@@ -516,7 +542,7 @@
// maybe use attach somehow? but need a Window
return nullptr;
}
- if (VK_ERROR_OUT_OF_DATE_KHR == res) {
+ if (VK_ERROR_OUT_OF_DATE_KHR == res || VK_SUBOPTIMAL_KHR == res) {
// tear swapchain down and try again
if (!createSwapchain(surface)) {
return nullptr;
@@ -595,6 +621,10 @@
}
backendRT.setVkImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ surface->mPreTransform = getPreTransformMatrix(surface->windowWidth(),
+ surface->windowHeight(),
+ surface->mTransform);
+
surface->mBackbuffer = std::move(skSurface);
return surface->mBackbuffer.get();
}
@@ -749,6 +779,17 @@
return false;
}
+ if (!SkToBool(caps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)) {
+ return false;
+ }
+ VkSurfaceTransformFlagBitsKHR transform;
+ if (SkToBool(caps.supportedTransforms & caps.currentTransform) &&
+ !SkToBool(caps.currentTransform & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR)) {
+ transform = caps.currentTransform;
+ } else {
+ transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+ }
+
VkExtent2D extent = caps.currentExtent;
// clamp width; to handle currentExtent of -1 and protect us from broken hints
if (extent.width < caps.minImageExtent.width) {
@@ -760,6 +801,16 @@
extent.height = caps.minImageExtent.height;
}
SkASSERT(extent.height <= caps.maxImageExtent.height);
+
+ VkExtent2D swapExtent = extent;
+ if (transform == VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR ||
+ transform == VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR ||
+ transform == VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR ||
+ transform == VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) {
+ swapExtent.width = extent.height;
+ swapExtent.height = extent.width;
+ }
+
surface->mWindowWidth = extent.width;
surface->mWindowHeight = extent.height;
@@ -775,7 +826,7 @@
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
SkASSERT((caps.supportedUsageFlags & usageFlags) == usageFlags);
- SkASSERT(caps.supportedTransforms & caps.currentTransform);
+
SkASSERT(caps.supportedCompositeAlpha &
(VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR));
VkCompositeAlphaFlagBitsKHR composite_alpha =
@@ -822,7 +873,7 @@
swapchainCreateInfo.minImageCount = imageCount;
swapchainCreateInfo.imageFormat = surfaceFormat;
swapchainCreateInfo.imageColorSpace = colorSpace;
- swapchainCreateInfo.imageExtent = extent;
+ swapchainCreateInfo.imageExtent = swapExtent;
swapchainCreateInfo.imageArrayLayers = 1;
swapchainCreateInfo.imageUsage = usageFlags;
@@ -837,7 +888,7 @@
swapchainCreateInfo.pQueueFamilyIndices = nullptr;
}
- swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+ swapchainCreateInfo.preTransform = transform;
swapchainCreateInfo.compositeAlpha = composite_alpha;
swapchainCreateInfo.presentMode = mode;
swapchainCreateInfo.clipped = true;
@@ -848,6 +899,8 @@
return false;
}
+ surface->mTransform = transform;
+
// destroy the old swapchain
if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) {
mDeviceWaitIdle(mDevice);
@@ -857,7 +910,7 @@
mDestroySwapchainKHR(mDevice, swapchainCreateInfo.oldSwapchain, nullptr);
}
- createBuffers(surface, surfaceFormat, extent);
+ createBuffers(surface, surfaceFormat, swapExtent);
// The window content is not updated (frozen) until a buffer of the window size is received.
// This prevents temporary stretching of the window after it is resized, but before the first
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 105ee09..b06eb82 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -45,6 +45,14 @@
sk_sp<SkSurface> getBackBufferSurface() { return mBackbuffer; }
+ // The width and height are are the logical width and height for when submitting draws to the
+ // surface. In reality if the window is rotated the underlying VkImage may have the width and
+ // height swapped.
+ int windowWidth() const { return mWindowWidth; }
+ int windowHeight() const { return mWindowHeight; }
+
+ SkMatrix& preTransform() { return mPreTransform; }
+
private:
friend class VulkanManager;
struct BackbufferInfo {
@@ -84,6 +92,8 @@
sk_sp<SkColorSpace> mColorSpace;
SkColorSpace::Gamut mColorGamut;
SkColorType mColorType;
+ VkSurfaceTransformFlagBitsKHR mTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+ SkMatrix mPreTransform;
};
// This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue,
diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
index 3c06dab..e86cf42 100644
--- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp
+++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
@@ -51,7 +51,8 @@
auto surface = SkSurface::MakeRasterN32Premul(1, 1);
surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
+ SkMatrix::I());
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
}
@@ -83,7 +84,8 @@
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
// drawFrame will crash if "SkiaPipeline::onPrepareTree" did not clean invalid VD pointer
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
+ SkMatrix::I());
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
}
@@ -104,10 +106,12 @@
auto surface = SkSurface::MakeRasterN32Premul(2, 2);
surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface,
+ SkMatrix::I());
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, false, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, false, contentDrawBounds, surface,
+ SkMatrix::I());
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned int)SK_ColorTRANSPARENT);
ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
}
@@ -126,7 +130,8 @@
auto surface = SkSurface::MakeRasterN32Premul(2, 2);
surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface,
+ SkMatrix::I());
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
ASSERT_EQ(TestUtils::getColor(surface, 1, 0), SK_ColorBLUE);
ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorRED);
@@ -198,32 +203,38 @@
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
// Single draw, should be white.
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
+ SkMatrix::I());
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);
// 1 Overdraw, should be blue blended onto white.
renderNodes.push_back(whiteNode);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
+ SkMatrix::I());
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0d0ff);
// 2 Overdraw, should be green blended onto white
renderNodes.push_back(whiteNode);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
+ SkMatrix::I());
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0ffd0);
// 3 Overdraw, should be pink blended onto white.
renderNodes.push_back(whiteNode);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
+ SkMatrix::I());
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffffc0c0);
// 4 Overdraw, should be red blended onto white.
renderNodes.push_back(whiteNode);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
+ SkMatrix::I());
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080);
// 5 Overdraw, should be red blended onto white.
renderNodes.push_back(whiteNode);
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
+ SkMatrix::I());
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080);
}
@@ -308,7 +319,8 @@
SkRect dirty = SkRect::MakeWH(800, 600);
auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
sk_sp<DeferLayer<DeferTestCanvas>> surface(new DeferLayer<DeferTestCanvas>());
- pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, contentDrawBounds, surface);
+ pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, contentDrawBounds, surface,
+ SkMatrix::I());
EXPECT_EQ(4, surface->canvas()->mDrawCounter);
}
@@ -339,7 +351,43 @@
auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
sk_sp<DeferLayer<ClippedTestCanvas>> surface(new DeferLayer<ClippedTestCanvas>());
pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
- SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
+ SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface, SkMatrix::I());
+ EXPECT_EQ(1, surface->canvas()->mDrawCounter);
+}
+
+// Test renderFrame with a dirty clip and a pre-transform matrix.
+RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clipped_rotated) {
+ static const int CANVAS_WIDTH = 200;
+ static const int CANVAS_HEIGHT = 100;
+ static const SkMatrix rotateMatrix = SkMatrix::MakeAll(0, -1, CANVAS_HEIGHT, 1, 0, 0, 0, 0, 1);
+ static const SkRect dirty = SkRect::MakeLTRB(10, 20, 20, 40);
+ class ClippedTestCanvas : public SkCanvas {
+ public:
+ ClippedTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {}
+ void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*) override {
+ EXPECT_EQ(0, mDrawCounter++);
+ // Expect clip to be rotated.
+ EXPECT_EQ(SkRect::MakeLTRB(CANVAS_HEIGHT - dirty.fTop - dirty.height(), dirty.fLeft,
+ CANVAS_HEIGHT - dirty.fTop, dirty.fLeft + dirty.width()),
+ TestUtils::getClipBounds(this));
+ EXPECT_EQ(rotateMatrix, getTotalMatrix());
+ }
+ int mDrawCounter = 0;
+ };
+
+ std::vector<sp<RenderNode>> nodes;
+ nodes.push_back(TestUtils::createSkiaNode(
+ 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ sk_sp<Bitmap> bitmap(TestUtils::createBitmap(CANVAS_WIDTH, CANVAS_HEIGHT));
+ canvas.drawBitmap(*bitmap, 0, 0, nullptr);
+ }));
+
+ LayerUpdateQueue layerUpdateQueue;
+ auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
+ sk_sp<DeferLayer<ClippedTestCanvas>> surface(new DeferLayer<ClippedTestCanvas>());
+ pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
+ SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface, rotateMatrix);
EXPECT_EQ(1, surface->canvas()->mDrawCounter);
}
@@ -369,7 +417,7 @@
auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
sk_sp<DeferLayer<ClipReplaceTestCanvas>> surface(new DeferLayer<ClipReplaceTestCanvas>());
pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
- SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
+ SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface, SkMatrix::I());
EXPECT_EQ(1, surface->canvas()->mDrawCounter);
}