Add drawDrawable support to GrRenderTargetContext.
This also includes adding drawable Op and plumbing it through to the GPU. BUG=skia: Change-Id: I0b2464c5a458c2fbf05b9528e47b9e6e3ac27d57 Reviewed-on: https://skia-review.googlesource.com/c/9645 Commit-Queue: Greg Daniel <egdaniel@google.com> Reviewed-by: Jim Van Verth <jvanverth@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
6064e1c5d6
commit
64cc9aaaf1
@ -249,10 +249,13 @@ skia_gpu_sources = [
|
||||
"$_src/gpu/ops/GrDashLinePathRenderer.h",
|
||||
"$_src/gpu/ops/GrDashOp.cpp",
|
||||
"$_src/gpu/ops/GrDashOp.h",
|
||||
"$_src/gpu/ops/GrDebugMarkerOp.h",
|
||||
"$_src/gpu/ops/GrDefaultPathRenderer.cpp",
|
||||
"$_src/gpu/ops/GrDefaultPathRenderer.h",
|
||||
"$_src/gpu/ops/GrDebugMarkerOp.cpp",
|
||||
"$_src/gpu/ops/GrDebugMarkerOp.h",
|
||||
"$_src/gpu/ops/GrDrawableOp.cpp",
|
||||
"$_src/gpu/ops/GrDrawableOp.h",
|
||||
"$_src/gpu/ops/GrDrawAtlasOp.cpp",
|
||||
"$_src/gpu/ops/GrDrawAtlasOp.h",
|
||||
"$_src/gpu/ops/GrDrawOp.h",
|
||||
|
@ -283,6 +283,7 @@ tests_sources = [
|
||||
"$_tests/UtilsTest.cpp",
|
||||
"$_tests/VerticesTest.cpp",
|
||||
"$_tests/VkBackendSurfaceTest.cpp",
|
||||
"$_tests/VkDrawableTest.cpp",
|
||||
"$_tests/VkMakeCopyPipelineTest.cpp",
|
||||
"$_tests/VkWrapTests.cpp",
|
||||
"$_tests/VptrTest.cpp",
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "GrColor.h"
|
||||
#include "GrPipeline.h"
|
||||
#include "SkDrawable.h"
|
||||
#include "ops/GrDrawOp.h"
|
||||
|
||||
class GrOpFlushState;
|
||||
@ -19,6 +20,7 @@ class GrMesh;
|
||||
class GrPipeline;
|
||||
class GrPrimitiveProcessor;
|
||||
class GrRenderTarget;
|
||||
class GrSemaphore;
|
||||
struct SkIRect;
|
||||
struct SkRect;
|
||||
|
||||
@ -117,6 +119,11 @@ public:
|
||||
// TODO: This should be removed in the future to favor using the load and store ops for discard
|
||||
virtual void discard() = 0;
|
||||
|
||||
/**
|
||||
* Executes the SkDrawable object for the underlying backend.
|
||||
*/
|
||||
virtual void executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) {}
|
||||
|
||||
protected:
|
||||
GrGpuRTCommandBuffer() : fOrigin(kTopLeft_GrSurfaceOrigin), fRenderTarget(nullptr) {}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "GrStencilAttachment.h"
|
||||
#include "GrStyle.h"
|
||||
#include "GrTracing.h"
|
||||
#include "SkDrawable.h"
|
||||
#include "SkDrawShadowInfo.h"
|
||||
#include "SkGlyphRunPainter.h"
|
||||
#include "SkGr.h"
|
||||
@ -39,6 +40,7 @@
|
||||
#include "ops/GrClearOp.h"
|
||||
#include "ops/GrClearStencilClipOp.h"
|
||||
#include "ops/GrDebugMarkerOp.h"
|
||||
#include "ops/GrDrawableOp.h"
|
||||
#include "ops/GrDrawAtlasOp.h"
|
||||
#include "ops/GrDrawOp.h"
|
||||
#include "ops/GrDrawVerticesOp.h"
|
||||
@ -1442,6 +1444,13 @@ void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
|
||||
this->addDrawOp(clip, std::move(op));
|
||||
}
|
||||
|
||||
void GrRenderTargetContext::drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
|
||||
const SkRect& bounds) {
|
||||
std::unique_ptr<GrOp> op(GrDrawableOp::Make(fContext, std::move(drawable), bounds));
|
||||
SkASSERT(op);
|
||||
this->getRTOpList()->addOp(std::move(op), *this->caps());
|
||||
}
|
||||
|
||||
GrSemaphoresSubmitted GrRenderTargetContext::prepareForExternalIO(
|
||||
int numSemaphores, GrBackendSemaphore backendSemaphores[]) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "GrTypesPriv.h"
|
||||
#include "GrXferProcessor.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkDrawable.h"
|
||||
#include "SkRefCnt.h"
|
||||
#include "SkSurfaceProps.h"
|
||||
#include "text/GrTextTarget.h"
|
||||
@ -338,6 +339,12 @@ public:
|
||||
std::unique_ptr<SkLatticeIter>,
|
||||
const SkRect& dst);
|
||||
|
||||
/**
|
||||
* Adds the necessary signal and wait semaphores and adds the passed in SkDrawable to the
|
||||
* command stream.
|
||||
*/
|
||||
void drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>, const SkRect& bounds);
|
||||
|
||||
/**
|
||||
* After this returns any pending surface IO will be issued to the backend 3D API and
|
||||
* if the surface has MSAA it will be resolved.
|
||||
|
@ -1696,13 +1696,14 @@ void SkGpuDevice::drawDrawable(SkDrawable* drawable, const SkMatrix* matrix, SkC
|
||||
std::unique_ptr<SkDrawable::GpuDrawHandler> gpuDraw =
|
||||
drawable->snapGpuDrawHandler(api, combinedMatrix);
|
||||
if (gpuDraw) {
|
||||
// TODO: send the gpuDraw to the renderTargetContext and make an Op out of it
|
||||
// return;
|
||||
fRenderTargetContext->drawDrawable(std::move(gpuDraw), drawable->getBounds());
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->INHERITED::drawDrawable(drawable, matrix, canvas);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkGpuDevice::flush() {
|
||||
|
35
src/gpu/ops/GrDrawableOp.cpp
Normal file
35
src/gpu/ops/GrDrawableOp.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrDrawableOp.h"
|
||||
|
||||
#include "GrContext.h"
|
||||
#include "GrContextPriv.h"
|
||||
#include "GrGpuCommandBuffer.h"
|
||||
#include "GrMemoryPool.h"
|
||||
#include "GrOpFlushState.h"
|
||||
#include "SkDrawable.h"
|
||||
|
||||
std::unique_ptr<GrDrawableOp> GrDrawableOp::Make(
|
||||
GrContext* context, std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
|
||||
const SkRect& bounds) {
|
||||
GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
|
||||
return pool->allocate<GrDrawableOp>(std::move(drawable), bounds);
|
||||
}
|
||||
|
||||
GrDrawableOp::GrDrawableOp(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
|
||||
const SkRect& bounds)
|
||||
: INHERITED(ClassID())
|
||||
, fDrawable(std::move(drawable)) {
|
||||
this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
|
||||
}
|
||||
|
||||
void GrDrawableOp::onExecute(GrOpFlushState* state) {
|
||||
SkASSERT(state->commandBuffer());
|
||||
state->rtCommandBuffer()->executeDrawable(std::move(fDrawable));
|
||||
}
|
||||
|
49
src/gpu/ops/GrDrawableOp.h
Normal file
49
src/gpu/ops/GrDrawableOp.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrDrawableOp_DEFINED
|
||||
#define GrDrawableOp_DEFINED
|
||||
|
||||
#include "GrOp.h"
|
||||
|
||||
#include "GrSemaphore.h"
|
||||
#include "SkDrawable.h"
|
||||
#include "SkMatrix.h"
|
||||
|
||||
class GrDrawableOp final : public GrOp {
|
||||
public:
|
||||
DEFINE_OP_CLASS_ID
|
||||
|
||||
static std::unique_ptr<GrDrawableOp> Make(GrContext*,
|
||||
std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
|
||||
const SkRect& bounds);
|
||||
|
||||
const char* name() const override { return "Drawable"; }
|
||||
|
||||
SkString dumpInfo() const override {
|
||||
return INHERITED::dumpInfo();
|
||||
}
|
||||
|
||||
private:
|
||||
friend class GrOpMemoryPool; // for ctor
|
||||
|
||||
GrDrawableOp(std::unique_ptr<SkDrawable::GpuDrawHandler>, const SkRect& bounds);
|
||||
|
||||
CombineResult onCombineIfPossible(GrOp* that, const GrCaps& caps) override {
|
||||
return CombineResult::kCannotCombine;
|
||||
}
|
||||
void onPrepare(GrOpFlushState*) override {}
|
||||
|
||||
void onExecute(GrOpFlushState* state) override;
|
||||
|
||||
std::unique_ptr<SkDrawable::GpuDrawHandler> fDrawable;
|
||||
|
||||
typedef GrOp INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -311,6 +311,8 @@ public:
|
||||
const GrVkRenderPass* compatibleRenderPass);
|
||||
void end(const GrVkGpu* gpu);
|
||||
|
||||
VkCommandBuffer vkCommandBuffer() { return fCmdBuffer; }
|
||||
|
||||
#ifdef SK_TRACE_VK_RESOURCES
|
||||
void dumpInfo() const override {
|
||||
SkDebugf("GrVkSecondaryCommandBuffer: %d (%d refs)\n", fCmdBuffer, this->getRefCnt());
|
||||
|
@ -307,6 +307,9 @@ void GrVkGpu::submitCommandBuffer(SyncQueue sync) {
|
||||
|
||||
fCurrentCmdBuffer->submitToQueue(this, fQueue, sync, fSemaphoresToSignal, fSemaphoresToWaitOn);
|
||||
|
||||
// We must delete and drawables that have been waitint till submit for us to destroy.
|
||||
fDrawables.reset();
|
||||
|
||||
for (int i = 0; i < fSemaphoresToWaitOn.count(); ++i) {
|
||||
fSemaphoresToWaitOn[i]->unref(this);
|
||||
}
|
||||
@ -2153,3 +2156,7 @@ sk_sp<GrSemaphore> GrVkGpu::prepareTextureForCrossContextUsage(GrTexture* textur
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GrVkGpu::addDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable) {
|
||||
fDrawables.emplace_back(std::move(drawable));
|
||||
}
|
||||
|
||||
|
@ -141,6 +141,14 @@ public:
|
||||
void insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) override;
|
||||
void waitSemaphore(sk_sp<GrSemaphore> semaphore) override;
|
||||
|
||||
// These match the definitions in SkDrawable, from whence they came
|
||||
typedef void* SubmitContext;
|
||||
typedef void (*SubmitProc)(SubmitContext submitContext);
|
||||
|
||||
// Adds an SkDrawable::GpuDrawHandler that we will delete the next time we submit the primary
|
||||
// command buffer to the gpu.
|
||||
void addDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable);
|
||||
|
||||
sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override;
|
||||
|
||||
void copyBuffer(GrVkBuffer* srcBuffer, GrVkBuffer* dstBuffer, VkDeviceSize srcOffset,
|
||||
@ -227,40 +235,42 @@ private:
|
||||
size_t srcRowBytes, GrVkImageInfo* info);
|
||||
#endif
|
||||
|
||||
sk_sp<const GrVkInterface> fInterface;
|
||||
sk_sp<GrVkMemoryAllocator> fMemoryAllocator;
|
||||
sk_sp<GrVkCaps> fVkCaps;
|
||||
sk_sp<const GrVkInterface> fInterface;
|
||||
sk_sp<GrVkMemoryAllocator> fMemoryAllocator;
|
||||
sk_sp<GrVkCaps> fVkCaps;
|
||||
|
||||
VkInstance fInstance;
|
||||
VkPhysicalDevice fPhysicalDevice;
|
||||
VkDevice fDevice;
|
||||
VkQueue fQueue; // Must be Graphics queue
|
||||
uint32_t fQueueIndex;
|
||||
VkInstance fInstance;
|
||||
VkPhysicalDevice fPhysicalDevice;
|
||||
VkDevice fDevice;
|
||||
VkQueue fQueue; // Must be Graphics queue
|
||||
uint32_t fQueueIndex;
|
||||
|
||||
// Created by GrVkGpu
|
||||
GrVkResourceProvider fResourceProvider;
|
||||
VkCommandPool fCmdPool;
|
||||
GrVkResourceProvider fResourceProvider;
|
||||
VkCommandPool fCmdPool;
|
||||
|
||||
GrVkPrimaryCommandBuffer* fCurrentCmdBuffer;
|
||||
GrVkPrimaryCommandBuffer* fCurrentCmdBuffer;
|
||||
|
||||
SkSTArray<1, GrVkSemaphore::Resource*> fSemaphoresToWaitOn;
|
||||
SkSTArray<1, GrVkSemaphore::Resource*> fSemaphoresToSignal;
|
||||
SkSTArray<1, GrVkSemaphore::Resource*> fSemaphoresToWaitOn;
|
||||
SkSTArray<1, GrVkSemaphore::Resource*> fSemaphoresToSignal;
|
||||
|
||||
VkPhysicalDeviceProperties fPhysDevProps;
|
||||
VkPhysicalDeviceMemoryProperties fPhysDevMemProps;
|
||||
SkTArray<std::unique_ptr<SkDrawable::GpuDrawHandler>> fDrawables;
|
||||
|
||||
GrVkCopyManager fCopyManager;
|
||||
VkPhysicalDeviceProperties fPhysDevProps;
|
||||
VkPhysicalDeviceMemoryProperties fPhysDevMemProps;
|
||||
|
||||
GrVkCopyManager fCopyManager;
|
||||
|
||||
// compiler used for compiling sksl into spirv. We only want to create the compiler once since
|
||||
// there is significant overhead to the first compile of any compiler.
|
||||
SkSL::Compiler* fCompiler;
|
||||
SkSL::Compiler* fCompiler;
|
||||
|
||||
// We need a bool to track whether or not we've already disconnected all the gpu resources from
|
||||
// vulkan context.
|
||||
bool fDisconnected;
|
||||
bool fDisconnected;
|
||||
|
||||
std::unique_ptr<GrVkGpuRTCommandBuffer> fCachedRTCommandBuffer;
|
||||
std::unique_ptr<GrVkGpuTextureCommandBuffer> fCachedTexCommandBuffer;
|
||||
std::unique_ptr<GrVkGpuRTCommandBuffer> fCachedRTCommandBuffer;
|
||||
std::unique_ptr<GrVkGpuTextureCommandBuffer> fCachedTexCommandBuffer;
|
||||
|
||||
typedef GrGpu INHERITED;
|
||||
};
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "GrVkGpuCommandBuffer.h"
|
||||
|
||||
#include "GrBackendDrawableInfo.h"
|
||||
#include "GrFixedClip.h"
|
||||
#include "GrMesh.h"
|
||||
#include "GrOpFlushState.h"
|
||||
@ -19,7 +20,9 @@
|
||||
#include "GrVkRenderPass.h"
|
||||
#include "GrVkRenderTarget.h"
|
||||
#include "GrVkResourceProvider.h"
|
||||
#include "GrVkSemaphore.h"
|
||||
#include "GrVkTexture.h"
|
||||
#include "SkDrawable.h"
|
||||
#include "SkRect.h"
|
||||
|
||||
void GrVkGpuTextureCommandBuffer::copy(GrSurface* src, GrSurfaceOrigin srcOrigin,
|
||||
@ -267,6 +270,8 @@ void GrVkGpuRTCommandBuffer::reset() {
|
||||
fRenderTarget = nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrVkGpuRTCommandBuffer::discard() {
|
||||
GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(fRenderTarget);
|
||||
|
||||
@ -777,3 +782,36 @@ void GrVkGpuRTCommandBuffer::sendIndexedInstancedMeshToGpu(GrPrimitiveType,
|
||||
baseIndex, baseVertex, baseInstance);
|
||||
fGpu->stats()->incNumDraws();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrVkGpuRTCommandBuffer::executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable) {
|
||||
GrVkRenderTarget* target = static_cast<GrVkRenderTarget*>(fRenderTarget);
|
||||
|
||||
GrVkImage* targetImage = target->msaaImage() ? target->msaaImage() : target;
|
||||
|
||||
CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
|
||||
VkRect2D bounds;
|
||||
bounds.offset = { 0, 0 };
|
||||
bounds.extent = { 0, 0 };
|
||||
|
||||
GrVkDrawableInfo vkInfo;
|
||||
vkInfo.fSecondaryCommandBuffer = cbInfo.currentCmdBuf()->vkCommandBuffer();
|
||||
vkInfo.fCompatibleRenderPass = cbInfo.fRenderPass->vkRenderPass();
|
||||
SkAssertResult(cbInfo.fRenderPass->colorAttachmentIndex(&vkInfo.fImageAttachmentIndex));
|
||||
vkInfo.fFormat = targetImage->imageFormat();
|
||||
vkInfo.fDrawBounds = &bounds;
|
||||
|
||||
GrBackendDrawableInfo info(vkInfo);
|
||||
|
||||
drawable->draw(info);
|
||||
fGpu->addDrawable(std::move(drawable));
|
||||
|
||||
if (bounds.extent.width == 0 || bounds.extent.height == 0) {
|
||||
cbInfo.fBounds.join(target->getBoundsRect());
|
||||
} else {
|
||||
cbInfo.fBounds.join(SkRect::MakeXYWH(bounds.offset.x, bounds.offset.y,
|
||||
bounds.extent.width, bounds.extent.height));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,8 @@ public:
|
||||
void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) override;
|
||||
|
||||
void executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) override;
|
||||
|
||||
void set(GrRenderTarget*, GrSurfaceOrigin,
|
||||
const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
|
||||
const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&);
|
||||
|
164
tests/VkDrawableTest.cpp
Normal file
164
tests/VkDrawableTest.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
// This is a GPU-backend specific test. It relies on static intializers to work
|
||||
|
||||
#include "SkTypes.h"
|
||||
|
||||
#if SK_SUPPORT_GPU && defined(SK_VULKAN)
|
||||
|
||||
#include "GrBackendDrawableInfo.h"
|
||||
#include "GrContextFactory.h"
|
||||
#include "GrContextPriv.h"
|
||||
#include "SkDrawable.h"
|
||||
#include "SkSurface.h"
|
||||
#include "Test.h"
|
||||
#include "vk/GrVkGpu.h"
|
||||
#include "vk/GrVkInterface.h"
|
||||
#include "vk/GrVkMemory.h"
|
||||
#include "vk/GrVkUtil.h"
|
||||
|
||||
using sk_gpu_test::GrContextFactory;
|
||||
|
||||
static const int DEV_W = 16, DEV_H = 16;
|
||||
|
||||
class TestDrawable : public SkDrawable {
|
||||
public:
|
||||
TestDrawable(const GrVkInterface* interface, int32_t width, int32_t height)
|
||||
: INHERITED()
|
||||
, fInterface(interface)
|
||||
, fWidth(width)
|
||||
, fHeight(height) {}
|
||||
|
||||
~TestDrawable() override {}
|
||||
|
||||
class DrawHandler : public GpuDrawHandler {
|
||||
public:
|
||||
DrawHandler(const GrVkInterface* interface, int32_t width, int32_t height)
|
||||
: INHERITED()
|
||||
, fInterface(interface)
|
||||
, fWidth(width)
|
||||
, fHeight(height) {}
|
||||
~DrawHandler() override {}
|
||||
|
||||
void draw(const GrBackendDrawableInfo& info) override {
|
||||
GrVkDrawableInfo vkInfo;
|
||||
SkAssertResult(info.getVkDrawableInfo(&vkInfo));
|
||||
|
||||
// Clear to Red
|
||||
VkClearColorValue vkColor;
|
||||
vkColor.float32[0] = 1.0f; // r
|
||||
vkColor.float32[1] = 0.0f; // g
|
||||
vkColor.float32[2] = 0.0f; // b
|
||||
vkColor.float32[3] = 1.0f; // a
|
||||
|
||||
// Clear right half of render target
|
||||
VkClearRect clearRect;
|
||||
clearRect.rect.offset = { fWidth / 2, 0 };
|
||||
clearRect.rect.extent = { (uint32_t)fWidth / 2, (uint32_t)fHeight };
|
||||
clearRect.baseArrayLayer = 0;
|
||||
clearRect.layerCount = 1;
|
||||
|
||||
VkClearAttachment attachment;
|
||||
attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
attachment.colorAttachment = vkInfo.fImageAttachmentIndex;
|
||||
attachment.clearValue.color = vkColor;
|
||||
|
||||
GR_VK_CALL(fInterface, CmdClearAttachments(vkInfo.fSecondaryCommandBuffer,
|
||||
1,
|
||||
&attachment,
|
||||
1,
|
||||
&clearRect));
|
||||
vkInfo.fDrawBounds->offset = { fWidth / 2, 0 };
|
||||
vkInfo.fDrawBounds->extent = { (uint32_t)fWidth / 2, (uint32_t)fHeight };
|
||||
}
|
||||
private:
|
||||
const GrVkInterface* fInterface;
|
||||
int32_t fWidth;
|
||||
int32_t fHeight;
|
||||
|
||||
typedef GpuDrawHandler INHERITED;
|
||||
};
|
||||
|
||||
std::unique_ptr<GpuDrawHandler> onSnapGpuDrawHandler(GrBackendApi backendApi,
|
||||
const SkMatrix& matrix) override {
|
||||
if (backendApi != GrBackendApi::kVulkan) {
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<DrawHandler> draw(new DrawHandler(fInterface, fWidth, fHeight));
|
||||
return std::move(draw);
|
||||
}
|
||||
|
||||
SkRect onGetBounds() override {
|
||||
return SkRect::MakeLTRB(fWidth / 2, 0, fWidth, fHeight);
|
||||
}
|
||||
|
||||
void onDraw(SkCanvas*) override {
|
||||
SkASSERT(false);
|
||||
}
|
||||
|
||||
private:
|
||||
const GrVkInterface* fInterface;
|
||||
int32_t fWidth;
|
||||
int32_t fHeight;
|
||||
|
||||
typedef SkDrawable INHERITED;
|
||||
};
|
||||
|
||||
void draw_drawable_test(skiatest::Reporter* reporter, GrContext* context) {
|
||||
GrVkGpu* gpu = static_cast<GrVkGpu*>(context->contextPriv().getGpu());
|
||||
|
||||
const SkImageInfo ii = SkImageInfo::Make(DEV_W, DEV_H, kRGBA_8888_SkColorType,
|
||||
kPremul_SkAlphaType);
|
||||
sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo,
|
||||
ii, 0, kTopLeft_GrSurfaceOrigin, nullptr));
|
||||
SkCanvas* canvas = surface->getCanvas();
|
||||
canvas->clear(SK_ColorBLUE);
|
||||
|
||||
sk_sp<TestDrawable> drawable(new TestDrawable(gpu->vkInterface(), DEV_W, DEV_H));
|
||||
canvas->drawDrawable(drawable.get());
|
||||
|
||||
SkPaint paint;
|
||||
paint.setColor(SK_ColorGREEN);
|
||||
SkIRect rect = SkIRect::MakeLTRB(0, DEV_H/2, DEV_W, DEV_H);
|
||||
canvas->drawIRect(rect, paint);
|
||||
|
||||
// read pixels
|
||||
SkBitmap bitmap;
|
||||
bitmap.allocPixels(ii);
|
||||
canvas->readPixels(bitmap, 0, 0);
|
||||
|
||||
const uint32_t* canvasPixels = static_cast<const uint32_t*>(bitmap.getPixels());
|
||||
bool failureFound = false;
|
||||
SkPMColor expectedPixel;
|
||||
for (int cy = 0; cy < DEV_H || failureFound; ++cy) {
|
||||
for (int cx = 0; cx < DEV_W || failureFound; ++cx) {
|
||||
SkPMColor canvasPixel = canvasPixels[cy * DEV_W + cx];
|
||||
if (cy < DEV_H / 2) {
|
||||
if (cx < DEV_W / 2) {
|
||||
expectedPixel = 0xFFFF0000; // Blue
|
||||
} else {
|
||||
expectedPixel = 0xFF0000FF; // Red
|
||||
}
|
||||
} else {
|
||||
expectedPixel = 0xFF00FF00; // Green
|
||||
}
|
||||
if (expectedPixel != canvasPixel) {
|
||||
failureFound = true;
|
||||
ERRORF(reporter, "Wrong color at %d, %d. Got 0x%08x when we expected 0x%08x",
|
||||
cx, cy, canvasPixel, expectedPixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkDrawableTest, reporter, ctxInfo) {
|
||||
draw_drawable_test(reporter, ctxInfo.grContext());
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user