Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4076789 authored by Greg Daniel's avatar Greg Daniel Committed by Stan Iliev
Browse files

Add support for preTransform in Vulkan swapchain.

Test: manual building and running of apps.
Bug: 110985606
Bug: 122662274
Change-Id: Id53aa1ce028b448b1f12558eec78a60e09512166
parent 793f1a79
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -100,7 +100,8 @@ bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, con
            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
+11 −7
Original line number Diff line number Diff line
@@ -312,7 +312,8 @@ void SkiaPipeline::endCapture(SkSurface* surface) {

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 @@ void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& cli
    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 @@ static Rect nodeBounds(RenderNode& node) {

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 @@ static const uint32_t kOverdrawColors[2][6] = {

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 @@ void SkiaPipeline::renderOverdraw(const LayerUpdateQueue& layers, const SkRect&
    // 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.
+5 −3
Original line number Diff line number Diff line
@@ -53,7 +53,8 @@ public:

    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 @@ protected:
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 @@ private:
     */
    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.
+4 −2
Original line number Diff line number Diff line
@@ -58,7 +58,8 @@ Frame SkiaVulkanPipeline::getFrame() {
        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 @@ bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, con
        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();

+58 −5
Original line number Diff line number Diff line
@@ -480,6 +480,32 @@ VulkanSurface::BackbufferInfo* VulkanManager::getAvailableBackbuffer(VulkanSurfa
    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 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) {
        // 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 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) {
    }
    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 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
        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 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
        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 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
                                   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 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
    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 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
        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 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
        return false;
    }

    surface->mTransform = transform;

    // destroy the old swapchain
    if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) {
        mDeviceWaitIdle(mDevice);
@@ -857,7 +910,7 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
        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
Loading