diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/third_party/skia/src/gpu | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/skia/src/gpu')
401 files changed, 13561 insertions, 8642 deletions
diff --git a/chromium/third_party/skia/src/gpu/GrAHardwareBufferUtils.cpp b/chromium/third_party/skia/src/gpu/GrAHardwareBufferUtils.cpp index b701dafb3bf..badb8eee5a6 100644 --- a/chromium/third_party/skia/src/gpu/GrAHardwareBufferUtils.cpp +++ b/chromium/third_party/skia/src/gpu/GrAHardwareBufferUtils.cpp @@ -486,6 +486,7 @@ static GrBackendTexture make_vk_backend_texture( // "foreign" device we can leave them as external. imageInfo.fCurrentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL; imageInfo.fYcbcrConversionInfo = *ycbcrConversion; + imageInfo.fSharingMode = imageCreateInfo.sharingMode; *deleteProc = delete_vk_image; *updateProc = update_vk_image; diff --git a/chromium/third_party/skia/src/gpu/GrAppliedClip.h b/chromium/third_party/skia/src/gpu/GrAppliedClip.h index 594a627987d..75e614a659a 100644 --- a/chromium/third_party/skia/src/gpu/GrAppliedClip.h +++ b/chromium/third_party/skia/src/gpu/GrAppliedClip.h @@ -22,11 +22,19 @@ class GrAppliedHardClip { public: static const GrAppliedHardClip& Disabled() { - static GrAppliedHardClip kDisabled; + // The size doesn't really matter here since it's returned as const& so an actual scissor + // will never be set on it, and applied clips are not used to query or bounds test like + // the GrClip is. + static const GrAppliedHardClip kDisabled({1 << 29, 1 << 29}); return kDisabled; } - GrAppliedHardClip() = default; + GrAppliedHardClip(const SkISize& rtDims) : fScissorState(rtDims) {} + GrAppliedHardClip(const SkISize& logicalRTDims, const SkISize& backingStoreDims) + : fScissorState(backingStoreDims) { + fScissorState.set(SkIRect::MakeSize(logicalRTDims)); + } + GrAppliedHardClip(GrAppliedHardClip&& that) = default; GrAppliedHardClip(const GrAppliedHardClip&) = delete; @@ -81,7 +89,14 @@ private: */ class GrAppliedClip { public: - GrAppliedClip() = default; + static GrAppliedClip Disabled() { + return GrAppliedClip({1 << 29, 1 << 29}); + } + + GrAppliedClip(const SkISize& rtDims) : fHardClip(rtDims) {} + GrAppliedClip(const SkISize& logicalRTDims, const SkISize& backingStoreDims) + : fHardClip(logicalRTDims, backingStoreDims) {} + GrAppliedClip(GrAppliedClip&& that) = default; GrAppliedClip(const GrAppliedClip&) = delete; diff --git a/chromium/third_party/skia/src/gpu/GrBackendSurface.cpp b/chromium/third_party/skia/src/gpu/GrBackendSurface.cpp index 8f07bb1ee22..a1e0203ff46 100644 --- a/chromium/third_party/skia/src/gpu/GrBackendSurface.cpp +++ b/chromium/third_party/skia/src/gpu/GrBackendSurface.cpp @@ -7,6 +7,7 @@ #include "include/gpu/GrBackendSurface.h" +#include "src/gpu/GrBackendSurfaceMutableStateImpl.h" #include "src/gpu/gl/GrGLUtil.h" #ifdef SK_DAWN @@ -386,6 +387,8 @@ SkString GrBackendFormat::toStr() const { #endif /////////////////////////////////////////////////////////////////////////////////////////////////// +GrBackendTexture::GrBackendTexture() : fIsValid(false) {} + #ifdef SK_DAWN GrBackendTexture::GrBackendTexture(int width, int height, @@ -398,12 +401,24 @@ GrBackendTexture::GrBackendTexture(int width, , fDawnInfo(dawnInfo) {} #endif -GrBackendTexture::GrBackendTexture(int width, int height, const GrVkImageInfo& vkInfo) #ifdef SK_VULKAN +GrBackendTexture::GrBackendTexture(int width, int height, const GrVkImageInfo& vkInfo) : GrBackendTexture(width, height, vkInfo, - sk_sp<GrVkImageLayout>(new GrVkImageLayout(vkInfo.fImageLayout))) {} -#else - : fIsValid(false) {} + sk_sp<GrBackendSurfaceMutableStateImpl>( + new GrBackendSurfaceMutableStateImpl( + vkInfo.fImageLayout, vkInfo.fCurrentQueueFamily))) {} + +GrBackendTexture::GrBackendTexture(int width, + int height, + const GrVkImageInfo& vkInfo, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState) + : fIsValid(true) + , fWidth(width) + , fHeight(height) + , fMipMapped(GrMipMapped(vkInfo.fLevelCount > 1)) + , fBackend(GrBackendApi::kVulkan) + , fVkInfo(vkInfo) + , fMutableState(std::move(mutableState)) {} #endif #ifdef SK_GL @@ -427,19 +442,6 @@ sk_sp<GrGLTextureParameters> GrBackendTexture::getGLTextureParams() const { } #endif -#ifdef SK_VULKAN -GrBackendTexture::GrBackendTexture(int width, - int height, - const GrVkImageInfo& vkInfo, - sk_sp<GrVkImageLayout> layout) - : fIsValid(true) - , fWidth(width) - , fHeight(height) - , fMipMapped(GrMipMapped(vkInfo.fLevelCount > 1)) - , fBackend(GrBackendApi::kVulkan) - , fVkInfo(vkInfo, layout.release()) {} -#endif - #ifdef SK_METAL GrBackendTexture::GrBackendTexture(int width, int height, @@ -566,10 +568,15 @@ GrBackendTexture& GrBackendTexture::operator=(const GrBackendTexture& that) { default: SK_ABORT("Unknown GrBackend"); } + fMutableState = that.fMutableState; fIsValid = true; return *this; } +sk_sp<GrBackendSurfaceMutableStateImpl> GrBackendTexture::getMutableState() const { + return fMutableState; +} + #ifdef SK_DAWN bool GrBackendTexture::getDawnTextureInfo(GrDawnTextureInfo* outInfo) const { if (this->isValid() && GrBackendApi::kDawn == fBackend) { @@ -583,7 +590,7 @@ bool GrBackendTexture::getDawnTextureInfo(GrDawnTextureInfo* outInfo) const { bool GrBackendTexture::getVkImageInfo(GrVkImageInfo* outInfo) const { #ifdef SK_VULKAN if (this->isValid() && GrBackendApi::kVulkan == fBackend) { - *outInfo = fVkInfo.snapImageInfo(); + *outInfo = fVkInfo.snapImageInfo(fMutableState.get()); return true; } #endif @@ -593,20 +600,11 @@ bool GrBackendTexture::getVkImageInfo(GrVkImageInfo* outInfo) const { void GrBackendTexture::setVkImageLayout(VkImageLayout layout) { #ifdef SK_VULKAN if (this->isValid() && GrBackendApi::kVulkan == fBackend) { - fVkInfo.setImageLayout(layout); + fMutableState->setImageLayout(layout); } #endif } -#ifdef SK_VULKAN -sk_sp<GrVkImageLayout> GrBackendTexture::getGrVkImageLayout() const { - if (this->isValid() && GrBackendApi::kVulkan == fBackend) { - return fVkInfo.getGrVkImageLayout(); - } - return nullptr; -} -#endif - #ifdef SK_METAL bool GrBackendTexture::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const { if (this->isValid() && GrBackendApi::kMetal == fBackend) { @@ -674,6 +672,10 @@ bool GrBackendTexture::getMockTextureInfo(GrMockTextureInfo* outInfo) const { return false; } +void GrBackendTexture::setMutableState(const GrBackendSurfaceMutableState& state) { + fMutableState->set(state); +} + bool GrBackendTexture::isProtected() const { if (!this->isValid() || this->backend() != GrBackendApi::kVulkan) { return false; @@ -695,7 +697,8 @@ bool GrBackendTexture::isSameTexture(const GrBackendTexture& that) { #endif #ifdef SK_VULKAN case GrBackendApi::kVulkan: - return fVkInfo.snapImageInfo().fImage == that.fVkInfo.snapImageInfo().fImage; + return fVkInfo.snapImageInfo(fMutableState.get()).fImage == + that.fVkInfo.snapImageInfo(that.fMutableState.get()).fImage; #endif #ifdef SK_METAL case GrBackendApi::kMetal: @@ -703,7 +706,13 @@ bool GrBackendTexture::isSameTexture(const GrBackendTexture& that) { #endif #ifdef SK_DIRECT3D case GrBackendApi::kDirect3D: - return false; //TODO + return fD3DInfo.snapTextureResourceInfo().fResource == + that.fD3DInfo.snapTextureResourceInfo().fResource; +#endif +#ifdef SK_DAWN + case GrBackendApi::kDawn: { + return this->fDawnInfo.fTexture.Get() == that.fDawnInfo.fTexture.Get(); + } #endif case GrBackendApi::kMock: return fMockInfo.id() == that.fMockInfo.id(); @@ -723,7 +732,7 @@ GrBackendFormat GrBackendTexture::getBackendFormat() const { #endif #ifdef SK_VULKAN case GrBackendApi::kVulkan: { - auto info = fVkInfo.snapImageInfo(); + auto info = fVkInfo.snapImageInfo(fMutableState.get()); if (info.fYcbcrConversionInfo.isValid()) { SkASSERT(info.fFormat == info.fYcbcrConversionInfo.fFormat); return GrBackendFormat::MakeVk(info.fYcbcrConversionInfo); @@ -769,6 +778,12 @@ bool GrBackendTexture::TestingOnly_Equals(const GrBackendTexture& t0, const GrBa return false; } + // For our tests when checking equality we are assuming the both backendTexture objects will + // be using the same mutable state object. + if (t0.fMutableState != t1.fMutableState) { + return false; + } + switch (t0.fBackend) { #ifdef SK_GL case GrBackendApi::kOpenGL: @@ -800,6 +815,9 @@ bool GrBackendTexture::TestingOnly_Equals(const GrBackendTexture& t0, const GrBa //////////////////////////////////////////////////////////////////////////////////////////////////// +GrBackendRenderTarget::GrBackendRenderTarget() : fIsValid(false) {} + + #ifdef SK_DAWN GrBackendRenderTarget::GrBackendRenderTarget(int width, int height, @@ -816,6 +834,7 @@ GrBackendRenderTarget::GrBackendRenderTarget(int width, , fDawnInfo(dawnInfo) {} #endif +#ifdef SK_VULKAN GrBackendRenderTarget::GrBackendRenderTarget(int width, int height, int sampleCnt, @@ -830,26 +849,24 @@ GrBackendRenderTarget::GrBackendRenderTarget(int width, int height, int sampleCnt, const GrVkImageInfo& vkInfo) -#ifdef SK_VULKAN : GrBackendRenderTarget(width, height, sampleCnt, vkInfo, - sk_sp<GrVkImageLayout>(new GrVkImageLayout(vkInfo.fImageLayout))) {} -#else - : fIsValid(false) {} -#endif + sk_sp<GrBackendSurfaceMutableStateImpl>( + new GrBackendSurfaceMutableStateImpl( + vkInfo.fImageLayout, vkInfo.fCurrentQueueFamily))) {} -#ifdef SK_VULKAN GrBackendRenderTarget::GrBackendRenderTarget(int width, int height, int sampleCnt, const GrVkImageInfo& vkInfo, - sk_sp<GrVkImageLayout> layout) + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState) : fIsValid(true) , fWidth(width) , fHeight(height) , fSampleCnt(std::max(1, sampleCnt)) , fStencilBits(0) // We always create stencil buffers internally for vulkan , fBackend(GrBackendApi::kVulkan) - , fVkInfo(vkInfo, layout.release()) {} + , fVkInfo(vkInfo) + , fMutableState(mutableState) {} #endif #ifdef SK_METAL @@ -926,6 +943,11 @@ void GrBackendRenderTarget::cleanup() { fVkInfo.cleanup(); } #endif +#ifdef SK_DIRECT3D + if (this->isValid() && GrBackendApi::kDirect3D == fBackend) { + fD3DInfo.cleanup(); + } +#endif } GrBackendRenderTarget::GrBackendRenderTarget(const GrBackendRenderTarget& that) : fIsValid(false) { @@ -979,10 +1001,15 @@ GrBackendRenderTarget& GrBackendRenderTarget::operator=(const GrBackendRenderTar default: SK_ABORT("Unknown GrBackend"); } + fMutableState = that.fMutableState; fIsValid = that.fIsValid; return *this; } +sk_sp<GrBackendSurfaceMutableStateImpl> GrBackendRenderTarget::getMutableState() const { + return fMutableState; +} + #ifdef SK_DAWN bool GrBackendRenderTarget::getDawnRenderTargetInfo(GrDawnRenderTargetInfo* outInfo) const { if (this->isValid() && GrBackendApi::kDawn == fBackend) { @@ -996,7 +1023,7 @@ bool GrBackendRenderTarget::getDawnRenderTargetInfo(GrDawnRenderTargetInfo* outI bool GrBackendRenderTarget::getVkImageInfo(GrVkImageInfo* outInfo) const { #ifdef SK_VULKAN if (this->isValid() && GrBackendApi::kVulkan == fBackend) { - *outInfo = fVkInfo.snapImageInfo(); + *outInfo = fVkInfo.snapImageInfo(fMutableState.get()); return true; } #endif @@ -1006,20 +1033,11 @@ bool GrBackendRenderTarget::getVkImageInfo(GrVkImageInfo* outInfo) const { void GrBackendRenderTarget::setVkImageLayout(VkImageLayout layout) { #ifdef SK_VULKAN if (this->isValid() && GrBackendApi::kVulkan == fBackend) { - fVkInfo.setImageLayout(layout); + fMutableState->setImageLayout(layout); } #endif } -#ifdef SK_VULKAN -sk_sp<GrVkImageLayout> GrBackendRenderTarget::getGrVkImageLayout() const { - if (this->isValid() && GrBackendApi::kVulkan == fBackend) { - return fVkInfo.getGrVkImageLayout(); - } - return nullptr; -} -#endif - #ifdef SK_METAL bool GrBackendRenderTarget::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const { if (this->isValid() && GrBackendApi::kMetal == fBackend) { @@ -1074,7 +1092,7 @@ GrBackendFormat GrBackendRenderTarget::getBackendFormat() const { #endif #ifdef SK_VULKAN case GrBackendApi::kVulkan: { - auto info = fVkInfo.snapImageInfo(); + auto info = fVkInfo.snapImageInfo(fMutableState.get()); if (info.fYcbcrConversionInfo.isValid()) { SkASSERT(info.fFormat == info.fYcbcrConversionInfo.fFormat); return GrBackendFormat::MakeVk(info.fYcbcrConversionInfo); @@ -1117,6 +1135,10 @@ bool GrBackendRenderTarget::getMockRenderTargetInfo(GrMockRenderTargetInfo* outI return false; } +void GrBackendRenderTarget::setMutableState(const GrBackendSurfaceMutableState& state) { + fMutableState->set(state); +} + bool GrBackendRenderTarget::isProtected() const { if (!this->isValid() || this->backend() != GrBackendApi::kVulkan) { return false; diff --git a/chromium/third_party/skia/src/gpu/GrBackendSurfaceMutableStateImpl.h b/chromium/third_party/skia/src/gpu/GrBackendSurfaceMutableStateImpl.h new file mode 100644 index 00000000000..3e3bc92f4e4 --- /dev/null +++ b/chromium/third_party/skia/src/gpu/GrBackendSurfaceMutableStateImpl.h @@ -0,0 +1,58 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrBackendSurfaceMutableStateImpl_DEFINED +#define GrBackendSurfaceMutableStateImpl_DEFINED + +#include "include/core/SkRefCnt.h" +#include "include/gpu/GrBackendSurfaceMutableState.h" + +class GrBackendSurfaceMutableStateImpl : public SkRefCnt { +public: +#ifdef SK_VULKAN + GrBackendSurfaceMutableStateImpl(VkImageLayout layout, uint32_t queueFamilyIndex) + : fState(layout, queueFamilyIndex) {} + + GrBackendSurfaceMutableStateImpl(GrVkSharedImageInfo sharedInfo) + : fState(sharedInfo.getImageLayout(), sharedInfo.getQueueFamilyIndex()) {} +#endif + + void set(const GrBackendSurfaceMutableState& state) { fState = state; } + +#ifdef SK_VULKAN + VkImageLayout getImageLayout() const { + SkASSERT(fState.fBackend == GrBackend::kVulkan); + return fState.fVkState.getImageLayout(); + } + + void setImageLayout(VkImageLayout layout) { + SkASSERT(fState.fBackend == GrBackend::kVulkan); + fState.fVkState.setImageLayout(layout); + } + + uint32_t getQueueFamilyIndex() const { + SkASSERT(fState.fBackend == GrBackend::kVulkan); + return fState.fVkState.getQueueFamilyIndex(); + } + + void setQueueFamilyIndex(uint32_t queueFamilyIndex) { + SkASSERT(fState.fBackend == GrBackend::kVulkan); + fState.fVkState.setQueueFamilyIndex(queueFamilyIndex); + } + + const GrVkSharedImageInfo& getVkSharedImageInfo() { + SkASSERT(fState.fBackend == GrBackend::kVulkan); + return fState.fVkState; + } +#endif + + +private: + GrBackendSurfaceMutableState fState; +}; + +#endif diff --git a/chromium/third_party/skia/src/gpu/GrBackendUtils.h b/chromium/third_party/skia/src/gpu/GrBackendUtils.h new file mode 100644 index 00000000000..cfbcb0ea302 --- /dev/null +++ b/chromium/third_party/skia/src/gpu/GrBackendUtils.h @@ -0,0 +1,85 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrBackendUtils_DEFINED +#define GrBackendUtils_DEFINED + +#include "include/core/SkImage.h" + +#include "include/gpu/GrBackendSurface.h" + +#ifdef SK_METAL +#include "src/gpu/mtl/GrMtlCppUtil.h" +#endif + +static SkImage::CompressionType GrBackendFormatToCompressionType(const GrBackendFormat& format) { + switch (format.backend()) { + case GrBackendApi::kOpenGL: { +#ifdef SK_GL + GrGLFormat glFormat = format.asGLFormat(); + switch (glFormat) { + case GrGLFormat::kCOMPRESSED_ETC1_RGB8: + case GrGLFormat::kCOMPRESSED_RGB8_ETC2: + return SkImage::CompressionType::kETC2_RGB8_UNORM; + case GrGLFormat::kCOMPRESSED_RGB8_BC1: + return SkImage::CompressionType::kBC1_RGB8_UNORM; + case GrGLFormat::kCOMPRESSED_RGBA8_BC1: + return SkImage::CompressionType::kBC1_RGBA8_UNORM; + default: + return SkImage::CompressionType::kNone; + } +#endif + break; + } + case GrBackendApi::kVulkan: { +#ifdef SK_VULKAN + VkFormat vkFormat; + SkAssertResult(format.asVkFormat(&vkFormat)); + switch (vkFormat) { + case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: + return SkImage::CompressionType::kETC2_RGB8_UNORM; + case VK_FORMAT_BC1_RGB_UNORM_BLOCK: + return SkImage::CompressionType::kBC1_RGB8_UNORM; + case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: + return SkImage::CompressionType::kBC1_RGBA8_UNORM; + default: + return SkImage::CompressionType::kNone; + } +#endif + break; + } + case GrBackendApi::kMetal: { +#ifdef SK_METAL + return GrMtlBackendFormatToCompressionType(format); +#endif + break; + } + case GrBackendApi::kDirect3D: { +#ifdef SK_DIRECT3D + DXGI_FORMAT dxgiFormat; + SkAssertResult(format.asDxgiFormat(&dxgiFormat)); + switch (dxgiFormat) { + case DXGI_FORMAT_BC1_UNORM: + return SkImage::CompressionType::kBC1_RGBA8_UNORM; + default: + return SkImage::CompressionType::kNone; + } +#endif + break; + } + case GrBackendApi::kDawn: { + return SkImage::CompressionType::kNone; + } + case GrBackendApi::kMock: { + return format.asMockCompressionType(); + } + } + return SkImage::CompressionType::kNone; +} + +#endif + diff --git a/chromium/third_party/skia/src/gpu/GrBlockAllocator.h b/chromium/third_party/skia/src/gpu/GrBlockAllocator.h index fae9dabbf20..b683d7825eb 100644 --- a/chromium/third_party/skia/src/gpu/GrBlockAllocator.h +++ b/chromium/third_party/skia/src/gpu/GrBlockAllocator.h @@ -436,7 +436,7 @@ GrBlockAllocator::ByteRange GrBlockAllocator::allocate(size_t size) { <= std::numeric_limits<int32_t>::max()); if (size > kMaxAllocationSize) { - SK_ABORT("Allocation too large"); + SK_ABORT("Allocation too large (%zu bytes requested)", size); } int iSize = (int) size; diff --git a/chromium/third_party/skia/src/gpu/GrBlurUtils.cpp b/chromium/third_party/skia/src/gpu/GrBlurUtils.cpp index 66c145da008..084e8ef8b98 100644 --- a/chromium/third_party/skia/src/gpu/GrBlurUtils.cpp +++ b/chromium/third_party/skia/src/gpu/GrBlurUtils.cpp @@ -43,7 +43,7 @@ static GrSurfaceProxyView find_filtered_mask(GrProxyProvider* provider, const Gr // is already burnt into the mask this boils down to a rect draw. // Return true if the mask was successfully drawn. static bool draw_mask(GrRenderTargetContext* renderTargetContext, - const GrClip& clip, + const GrClip* clip, const SkMatrix& viewMatrix, const SkIRect& maskRect, GrPaint&& paint, @@ -53,7 +53,7 @@ static bool draw_mask(GrRenderTargetContext* renderTargetContext, return false; } - SkMatrix matrix = SkMatrix::MakeTrans(-SkIntToScalar(maskRect.fLeft), + SkMatrix matrix = SkMatrix::Translate(-SkIntToScalar(maskRect.fLeft), -SkIntToScalar(maskRect.fTop)); matrix.preConcat(viewMatrix); paint.addCoverageFragmentProcessor( @@ -70,7 +70,7 @@ static void mask_release_proc(void* addr, void* /*context*/) { static bool sw_draw_with_mask_filter(GrRecordingContext* context, GrRenderTargetContext* renderTargetContext, - const GrClip& clipData, + const GrClip* clipData, const SkMatrix& viewMatrix, const GrStyledShape& shape, const SkMaskFilter* filter, @@ -200,14 +200,13 @@ static std::unique_ptr<GrRenderTargetContext> create_mask_GPU(GrRecordingContext maskPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op); // setup new clip - const SkIRect clipRect = SkIRect::MakeWH(maskRect.width(), maskRect.height()); - GrFixedClip clip(clipRect); + GrFixedClip clip(rtContext->dimensions(), SkIRect::MakeWH(maskRect.width(), maskRect.height())); // Draw the mask into maskTexture with the path's integerized top-left at the origin using // maskPaint. SkMatrix viewMatrix = origViewMatrix; viewMatrix.postTranslate(-SkIntToScalar(maskRect.fLeft), -SkIntToScalar(maskRect.fTop)); - rtContext->drawShape(clip, std::move(maskPaint), GrAA::kYes, viewMatrix, shape); + rtContext->drawShape(&clip, std::move(maskPaint), GrAA::kYes, viewMatrix, shape); return rtContext; } @@ -239,14 +238,15 @@ static bool get_unclipped_shape_dev_bounds(const GrStyledShape& shape, const SkM // Gets the shape bounds, the clip bounds, and the intersection (if any). Returns false if there // is no intersection. static bool get_shape_and_clip_bounds(GrRenderTargetContext* renderTargetContext, - const GrClip& clip, + const GrClip* clip, const GrStyledShape& shape, const SkMatrix& matrix, SkIRect* unclippedDevShapeBounds, SkIRect* devClipBounds) { // compute bounds as intersection of rt size, clip, and path - *devClipBounds = clip.getConservativeBounds(renderTargetContext->width(), - renderTargetContext->height()); + *devClipBounds = clip ? clip->getConservativeBounds() + : SkIRect::MakeWH(renderTargetContext->width(), + renderTargetContext->height()); if (!get_unclipped_shape_dev_bounds(shape, matrix, unclippedDevShapeBounds)) { *unclippedDevShapeBounds = SkIRect::MakeEmpty(); @@ -258,7 +258,7 @@ static bool get_shape_and_clip_bounds(GrRenderTargetContext* renderTargetContext static void draw_shape_with_mask_filter(GrRecordingContext* context, GrRenderTargetContext* renderTargetContext, - const GrClip& clip, + const GrClip* clip, GrPaint&& paint, const SkMatrix& viewMatrix, const SkMaskFilterBase* maskFilter, @@ -282,12 +282,8 @@ static void draw_shape_with_mask_filter(GrRecordingContext* context, shape = tmpShape.get(); } - if (maskFilter->directFilterMaskGPU(context, - renderTargetContext, - std::move(paint), - clip, - viewMatrix, - *shape)) { + if (maskFilter->directFilterMaskGPU(context, renderTargetContext, std::move(paint), clip, + viewMatrix, *shape)) { // the mask filter was able to draw itself directly, so there's nothing // left to do. return; @@ -301,8 +297,7 @@ static void draw_shape_with_mask_filter(GrRecordingContext* context, SkIRect unclippedDevShapeBounds, devClipBounds; if (!get_shape_and_clip_bounds(renderTargetContext, clip, *shape, viewMatrix, - &unclippedDevShapeBounds, - &devClipBounds)) { + &unclippedDevShapeBounds, &devClipBounds)) { // TODO: just cons up an opaque mask here if (!inverseFilled) { return; @@ -439,7 +434,7 @@ static void draw_shape_with_mask_filter(GrRecordingContext* context, void GrBlurUtils::drawShapeWithMaskFilter(GrRecordingContext* context, GrRenderTargetContext* renderTargetContext, - const GrClip& clip, + const GrClip* clip, const GrStyledShape& shape, GrPaint&& paint, const SkMatrix& viewMatrix, @@ -450,7 +445,7 @@ void GrBlurUtils::drawShapeWithMaskFilter(GrRecordingContext* context, void GrBlurUtils::drawShapeWithMaskFilter(GrRecordingContext* context, GrRenderTargetContext* renderTargetContext, - const GrClip& clip, + const GrClip* clip, const SkPaint& paint, const SkMatrixProvider& matrixProvider, const GrStyledShape& shape) { diff --git a/chromium/third_party/skia/src/gpu/GrBlurUtils.h b/chromium/third_party/skia/src/gpu/GrBlurUtils.h index 45ce4efec6f..fa0be4ef52c 100644 --- a/chromium/third_party/skia/src/gpu/GrBlurUtils.h +++ b/chromium/third_party/skia/src/gpu/GrBlurUtils.h @@ -36,7 +36,7 @@ namespace GrBlurUtils { */ void drawShapeWithMaskFilter(GrRecordingContext*, GrRenderTargetContext*, - const GrClip&, + const GrClip*, const SkPaint&, const SkMatrixProvider&, const GrStyledShape&); @@ -47,7 +47,7 @@ namespace GrBlurUtils { */ void drawShapeWithMaskFilter(GrRecordingContext*, GrRenderTargetContext*, - const GrClip&, + const GrClip*, const GrStyledShape&, GrPaint&&, const SkMatrix& viewMatrix, diff --git a/chromium/third_party/skia/src/gpu/GrCaps.cpp b/chromium/third_party/skia/src/gpu/GrCaps.cpp index 43b8996170e..9cd3ea381c1 100644 --- a/chromium/third_party/skia/src/gpu/GrCaps.cpp +++ b/chromium/third_party/skia/src/gpu/GrCaps.cpp @@ -8,6 +8,7 @@ #include "include/gpu/GrBackendSurface.h" #include "include/gpu/GrContextOptions.h" #include "include/private/GrTypesPriv.h" +#include "src/gpu/GrBackendUtils.h" #include "src/gpu/GrCaps.h" #include "src/gpu/GrSurface.h" #include "src/gpu/GrSurfaceProxy.h" @@ -358,9 +359,11 @@ GrCaps::SupportedRead GrCaps::supportedReadPixelsColorType(GrColorType srcColorT // offset alignment is a multiple of 2 but not 4. case 2: read.fOffsetAlignmentForTransferBuffer *= 2; + break; // offset alignment is not a multiple of 2. default: read.fOffsetAlignmentForTransferBuffer *= 4; + break; } } return read; @@ -388,3 +391,37 @@ GrBackendFormat GrCaps::getDefaultBackendFormat(GrColorType colorType, } return format; } + +bool GrCaps::areColorTypeAndFormatCompatible(GrColorType grCT, + const GrBackendFormat& format) const { + if (GrColorType::kUnknown == grCT) { + return false; + } + + SkImage::CompressionType compression = GrBackendFormatToCompressionType(format); + if (compression != SkImage::CompressionType::kNone) { + return grCT == (SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x + : GrColorType::kRGBA_8888); + } + + return this->onAreColorTypeAndFormatCompatible(grCT, format); +} + +GrSwizzle GrCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const { + SkImage::CompressionType compression = GrBackendFormatToCompressionType(format); + if (compression != SkImage::CompressionType::kNone) { + if (colorType == GrColorType::kRGB_888x || colorType == GrColorType::kRGBA_8888) { + return GrSwizzle::RGBA(); + } + SkDEBUGFAILF("Illegal color type (%d) and compressed format (%d) combination.", colorType, + compression); + return {}; + } + + return this->onGetReadSwizzle(format, colorType); +} + +bool GrCaps::isFormatCompressed(const GrBackendFormat& format) const { + return GrBackendFormatToCompressionType(format) != SkImage::CompressionType::kNone; +} + diff --git a/chromium/third_party/skia/src/gpu/GrCaps.h b/chromium/third_party/skia/src/gpu/GrCaps.h index 3ef0c61812a..f81ec565e53 100644 --- a/chromium/third_party/skia/src/gpu/GrCaps.h +++ b/chromium/third_party/skia/src/gpu/GrCaps.h @@ -13,6 +13,7 @@ #include "include/core/SkString.h" #include "include/gpu/GrDriverBugWorkarounds.h" #include "include/private/GrTypesPriv.h" +#include "src/core/SkCompressedDataUtils.h" #include "src/gpu/GrBlend.h" #include "src/gpu/GrSamplerState.h" #include "src/gpu/GrShaderCaps.h" @@ -191,12 +192,7 @@ public: virtual bool isFormatSRGB(const GrBackendFormat&) const = 0; - // This will return SkImage::CompressionType::kNone if the backend format is not compressed. - virtual SkImage::CompressionType compressionType(const GrBackendFormat&) const = 0; - - bool isFormatCompressed(const GrBackendFormat& format) const { - return this->compressionType(format) != SkImage::CompressionType::kNone; - } + bool isFormatCompressed(const GrBackendFormat& format) const; // Can a texture be made with the GrBackendFormat, and then be bound and sampled in a shader. virtual bool isFormatTexturable(const GrBackendFormat&) const = 0; @@ -396,14 +392,7 @@ public: bool validateSurfaceParams(const SkISize&, const GrBackendFormat&, GrRenderable renderable, int renderTargetSampleCnt, GrMipMapped) const; - bool areColorTypeAndFormatCompatible(GrColorType grCT, - const GrBackendFormat& format) const { - if (GrColorType::kUnknown == grCT) { - return false; - } - - return this->onAreColorTypeAndFormatCompatible(grCT, format); - } + bool areColorTypeAndFormatCompatible(GrColorType grCT, const GrBackendFormat& format) const; /** These are used when creating a new texture internally. */ GrBackendFormat getDefaultBackendFormat(GrColorType, GrRenderable) const; @@ -420,7 +409,7 @@ public: * Returns the GrSwizzle to use when sampling or reading back from a texture with the passed in * GrBackendFormat and GrColorType. */ - virtual GrSwizzle getReadSwizzle(const GrBackendFormat&, GrColorType) const = 0; + GrSwizzle getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const; /** * Returns the GrSwizzle to use when writing colors to a surface with the passed in @@ -557,6 +546,9 @@ private: const GrBackendFormat& srcFormat, GrColorType dstColorType) const = 0; + virtual GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const = 0; + + bool fSuppressPrints : 1; bool fWireframeMode : 1; diff --git a/chromium/third_party/skia/src/gpu/GrClip.h b/chromium/third_party/skia/src/gpu/GrClip.h index d85338b3756..ee6935d1d28 100644 --- a/chromium/third_party/skia/src/gpu/GrClip.h +++ b/chromium/third_party/skia/src/gpu/GrClip.h @@ -21,6 +21,8 @@ class GrContext; */ class GrClip { public: + virtual ~GrClip() {} + virtual bool quickContains(const SkRect&) const = 0; virtual bool quickContains(const SkRRect& rrect) const { return this->quickContains(rrect.getBounds()); @@ -30,9 +32,7 @@ public: * The returned bounds represent the limits of pixels that can be drawn; anything outside of the * bounds will be entirely clipped out. */ - virtual SkIRect getConservativeBounds(int width, int height) const { - return SkIRect::MakeWH(width, height); - } + virtual SkIRect getConservativeBounds() const = 0; /** * This computes a GrAppliedClip from the clip which in turn can be used to build a GrPipeline. @@ -45,22 +45,18 @@ public: virtual bool apply(GrRecordingContext*, GrRenderTargetContext*, bool useHWAA, bool hasUserStencilSettings, GrAppliedClip*, SkRect* bounds) const = 0; - virtual ~GrClip() {} - /** * This method quickly and conservatively determines whether the entire clip is equivalent to - * intersection with a rrect. This will only return true if the rrect does not fully contain - * the render target bounds. Moreover, the returned rrect need not be contained by the render + * intersection with a rrect. Moreover, the returned rrect need not be contained by the render * target bounds. We assume all draws will be implicitly clipped by the render target bounds. * - * @param rtBounds The bounds of the render target that the clip will be applied to. * @param rrect If return is true rrect will contain the rrect equivalent to the clip within * rtBounds. * @param aa If return is true aa will indicate whether the rrect clip is antialiased. * @return true if the clip is equivalent to a single rrect, false otherwise. * */ - virtual bool isRRect(const SkRect& rtBounds, SkRRect* rrect, GrAA* aa) const = 0; + virtual bool isRRect(SkRRect* rrect, GrAA* aa) const = 0; /** * This is the maximum distance that a draw may extend beyond a clip's boundary and still count @@ -151,24 +147,13 @@ public: * return 'bounds' has been intersected with a conservative bounds of the clip. A return value * of false indicates that the draw can be skipped as it is fully clipped out. */ - virtual bool apply(int rtWidth, int rtHeight, GrAppliedHardClip* out, SkRect* bounds) const = 0; + virtual bool apply(GrAppliedHardClip* out, SkRect* bounds) const = 0; private: bool apply(GrRecordingContext*, GrRenderTargetContext* rtc, bool useHWAA, bool hasUserStencilSettings, GrAppliedClip* out, SkRect* bounds) const final { - return this->apply(rtc->width(), rtc->height(), &out->hardClip(), bounds); + return this->apply(&out->hardClip(), bounds); } }; -/** - * Specialized implementation for no clip. - */ -class GrNoClip final : public GrHardClip { -private: - bool quickContains(const SkRect&) const final { return true; } - bool quickContains(const SkRRect&) const final { return true; } - bool apply(int rtWidth, int rtHeight, GrAppliedHardClip*, SkRect*) const final { return true; } - bool isRRect(const SkRect&, SkRRect*, GrAA*) const override { return false; } -}; - #endif diff --git a/chromium/third_party/skia/src/gpu/GrClipStackClip.cpp b/chromium/third_party/skia/src/gpu/GrClipStackClip.cpp index 37121fd858b..65532389342 100644 --- a/chromium/third_party/skia/src/gpu/GrClipStackClip.cpp +++ b/chromium/third_party/skia/src/gpu/GrClipStackClip.cpp @@ -15,7 +15,6 @@ #include "src/gpu/GrContextPriv.h" #include "src/gpu/GrDeferredProxyUploader.h" #include "src/gpu/GrDrawingManager.h" -#include "src/gpu/GrFixedClip.h" #include "src/gpu/GrGpuResourcePriv.h" #include "src/gpu/GrProxyProvider.h" #include "src/gpu/GrRecordingContextPriv.h" @@ -24,7 +23,6 @@ #include "src/gpu/GrStencilAttachment.h" #include "src/gpu/GrStyle.h" #include "src/gpu/GrTextureProxy.h" -#include "src/gpu/effects/GrConvexPolyEffect.h" #include "src/gpu/effects/GrRRectEffect.h" #include "src/gpu/effects/generated/GrDeviceSpaceEffect.h" #include "src/gpu/geometry/GrStyledShape.h" @@ -49,26 +47,27 @@ bool GrClipStackClip::quickContains(const SkRRect& rrect) const { return fStack->quickContains(rrect); } -bool GrClipStackClip::isRRect(const SkRect& origRTBounds, SkRRect* rr, GrAA* aa) const { +bool GrClipStackClip::isRRect(SkRRect* rr, GrAA* aa) const { if (!fStack) { return false; } - const SkRect* rtBounds = &origRTBounds; + + SkRect rtBounds = SkRect::MakeIWH(fDeviceSize.fWidth, fDeviceSize.fHeight); bool isAA; - if (fStack->isRRect(*rtBounds, rr, &isAA)) { + if (fStack->isRRect(rtBounds, rr, &isAA)) { *aa = GrAA(isAA); return true; } return false; } -SkIRect GrClipStackClip::getConservativeBounds(int width, int height) const { +SkIRect GrClipStackClip::getConservativeBounds() const { if (fStack) { SkRect devBounds; - fStack->getConservativeBounds(0, 0, width, height, &devBounds); + fStack->getConservativeBounds(0, 0, fDeviceSize.fWidth, fDeviceSize.fHeight, &devBounds); return devBounds.roundOut(); } else { - return this->GrClip::getConservativeBounds(width, height); + return SkIRect::MakeSize(fDeviceSize); } } @@ -79,7 +78,7 @@ static std::unique_ptr<GrFragmentProcessor> create_fp_for_mask(GrSurfaceProxyVie const GrCaps& caps) { GrSamplerState samplerState(GrSamplerState::WrapMode::kClampToBorder, GrSamplerState::Filter::kNearest); - auto m = SkMatrix::MakeTrans(-devBound.fLeft, -devBound.fTop); + auto m = SkMatrix::Translate(-devBound.fLeft, -devBound.fTop); auto subset = SkRect::Make(devBound.size()); // We scissor to devBounds. The mask's texel centers are aligned to device space // pixel centers. Hence this domain of texture coordinates. @@ -200,7 +199,9 @@ bool GrClipStackClip::UseSWOnlyPath(GrRecordingContext* context, bool GrClipStackClip::apply(GrRecordingContext* context, GrRenderTargetContext* renderTargetContext, bool useHWAA, bool hasUserStencilSettings, GrAppliedClip* out, SkRect* bounds) const { - SkRect devBounds = SkRect::MakeIWH(renderTargetContext->width(), renderTargetContext->height()); + SkASSERT(renderTargetContext->width() == fDeviceSize.fWidth && + renderTargetContext->height() == fDeviceSize.fHeight); + SkRect devBounds = SkRect::MakeIWH(fDeviceSize.fWidth, fDeviceSize.fHeight); if (!devBounds.intersect(*bounds)) { return false; } @@ -253,7 +254,8 @@ bool GrClipStackClip::apply(GrRecordingContext* context, GrRenderTargetContext* // The opsTask ID must not be looked up until AFTER producing the clip mask (if any). That step // can cause a flush or otherwise change which opstask our draw is going into. uint32_t opsTaskID = renderTargetContext->getOpsTask()->uniqueID(); - if (auto clipFPs = reducedClip.finishAndDetachAnalyticFPs(ccpr, opsTaskID)) { + if (auto clipFPs = reducedClip.finishAndDetachAnalyticFPs(context, *fMatrixProvider, ccpr, + opsTaskID)) { out->addCoverageFP(std::move(clipFPs)); } diff --git a/chromium/third_party/skia/src/gpu/GrClipStackClip.h b/chromium/third_party/skia/src/gpu/GrClipStackClip.h index 90ca8676fc8..ffbd0017cc3 100644 --- a/chromium/third_party/skia/src/gpu/GrClipStackClip.h +++ b/chromium/third_party/skia/src/gpu/GrClipStackClip.h @@ -20,17 +20,20 @@ class GrTextureProxy; */ class GrClipStackClip final : public GrClip { public: - GrClipStackClip(const SkClipStack* stack = nullptr) { this->reset(stack); } - - void reset(const SkClipStack* stack) { fStack = stack; } + GrClipStackClip(const SkISize& dimensions, + const SkClipStack* stack = nullptr, + const SkMatrixProvider* matrixProvider = nullptr) + : fDeviceSize(dimensions) + , fStack(stack) + , fMatrixProvider(matrixProvider) {} bool quickContains(const SkRect&) const final; bool quickContains(const SkRRect&) const final; - SkIRect getConservativeBounds(int width, int height) const final; + SkIRect getConservativeBounds() const final; bool apply(GrRecordingContext*, GrRenderTargetContext*, bool useHWAA, bool hasUserStencilSettings, GrAppliedClip* out, SkRect* bounds) const final; - bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA* aa) const override; + bool isRRect(SkRRect* rr, GrAA* aa) const override; sk_sp<GrTextureProxy> testingOnly_createClipMask(GrContext*) const; static const char kMaskTestTag[]; @@ -61,7 +64,11 @@ private: const GrRenderTargetContext*, const GrReducedClip&); - const SkClipStack* fStack; + // SkClipStack does not track device bounds explicitly, but it will refine these device bounds + // as clip elements are added to the stack. + SkISize fDeviceSize; + const SkClipStack* fStack; + const SkMatrixProvider* fMatrixProvider; // for applying clip shaders }; #endif // GrClipStackClip_DEFINED diff --git a/chromium/third_party/skia/src/gpu/GrColorInfo.cpp b/chromium/third_party/skia/src/gpu/GrColorInfo.cpp index ada27da5a64..22bdc98678c 100644 --- a/chromium/third_party/skia/src/gpu/GrColorInfo.cpp +++ b/chromium/third_party/skia/src/gpu/GrColorInfo.cpp @@ -11,7 +11,11 @@ GrColorInfo::GrColorInfo( GrColorType colorType, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace) - : fColorSpace(std::move(colorSpace)), fColorType(colorType), fAlphaType(alphaType) {} + : fColorSpace(std::move(colorSpace)), fColorType(colorType), fAlphaType(alphaType) { + // sRGB sources are very common (SkColor, etc...), so we cache that transformation + fColorXformFromSRGB = GrColorSpaceXform::Make(sk_srgb_singleton(), kUnpremul_SkAlphaType, + fColorSpace.get(), kUnpremul_SkAlphaType); +} GrColorInfo::GrColorInfo(const SkColorInfo& ci) : GrColorInfo(SkColorTypeToGrColorType(ci.colorType()), @@ -20,16 +24,3 @@ GrColorInfo::GrColorInfo(const SkColorInfo& ci) GrColorInfo::GrColorInfo(const GrColorInfo&) = default; GrColorInfo& GrColorInfo::operator=(const GrColorInfo&) = default; - -GrColorSpaceXform* GrColorInfo::colorSpaceXformFromSRGB() const { - // TODO: Make this atomic if we start accessing this on multiple threads. - if (!fInitializedColorSpaceXformFromSRGB) { - // sRGB sources are very common (SkColor, etc...), so we cache that transformation - fColorXformFromSRGB = GrColorSpaceXform::Make(sk_srgb_singleton(), kUnpremul_SkAlphaType, - fColorSpace.get(), kUnpremul_SkAlphaType); - fInitializedColorSpaceXformFromSRGB = true; - } - // You can't be color-space aware in legacy mode - SkASSERT(fColorSpace || !fColorXformFromSRGB); - return fColorXformFromSRGB.get(); -} diff --git a/chromium/third_party/skia/src/gpu/GrColorInfo.h b/chromium/third_party/skia/src/gpu/GrColorInfo.h index 578575a5d6c..0af549a8ee5 100644 --- a/chromium/third_party/skia/src/gpu/GrColorInfo.h +++ b/chromium/third_party/skia/src/gpu/GrColorInfo.h @@ -29,10 +29,8 @@ public: SkColorSpace* colorSpace() const { return fColorSpace.get(); } sk_sp<SkColorSpace> refColorSpace() const { return fColorSpace; } - GrColorSpaceXform* colorSpaceXformFromSRGB() const; - sk_sp<GrColorSpaceXform> refColorSpaceXformFromSRGB() const { - return sk_ref_sp(this->colorSpaceXformFromSRGB()); - } + GrColorSpaceXform* colorSpaceXformFromSRGB() const { return fColorXformFromSRGB.get(); } + sk_sp<GrColorSpaceXform> refColorSpaceXformFromSRGB() const { return fColorXformFromSRGB; } GrColorType colorType() const { return fColorType; } SkAlphaType alphaType() const { return fAlphaType; } @@ -43,10 +41,9 @@ public: private: sk_sp<SkColorSpace> fColorSpace; - mutable sk_sp<GrColorSpaceXform> fColorXformFromSRGB; + sk_sp<GrColorSpaceXform> fColorXformFromSRGB; GrColorType fColorType = GrColorType::kUnknown; SkAlphaType fAlphaType = kUnknown_SkAlphaType; - mutable bool fInitializedColorSpaceXformFromSRGB = false; }; #endif diff --git a/chromium/third_party/skia/src/gpu/GrColorSpaceXform.cpp b/chromium/third_party/skia/src/gpu/GrColorSpaceXform.cpp index 0f97d21f9ef..b602b32ea4b 100644 --- a/chromium/third_party/skia/src/gpu/GrColorSpaceXform.cpp +++ b/chromium/third_party/skia/src/gpu/GrColorSpaceXform.cpp @@ -97,7 +97,7 @@ GrColorSpaceXformEffect::GrColorSpaceXformEffect(std::unique_ptr<GrFragmentProce : INHERITED(kGrColorSpaceXformEffect_ClassID, OptFlags(child.get())) , fColorXform(std::move(colorXform)) { if (child) { - this->registerChildProcessor(std::move(child)); + this->registerChild(std::move(child)); } } diff --git a/chromium/third_party/skia/src/gpu/GrContext.cpp b/chromium/third_party/skia/src/gpu/GrContext.cpp index 291c4348e7a..cc951f52643 100644 --- a/chromium/third_party/skia/src/gpu/GrContext.cpp +++ b/chromium/third_party/skia/src/gpu/GrContext.cpp @@ -30,9 +30,9 @@ #include "src/gpu/SkGr.h" #include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h" #include "src/gpu/effects/GrSkSLFP.h" +#include "src/gpu/text/GrSDFTOptions.h" #include "src/gpu/text/GrStrikeCache.h" #include "src/gpu/text/GrTextBlobCache.h" -#include "src/gpu/text/GrTextContext.h" #include "src/image/SkImage_GpuBase.h" #include "src/image/SkSurface_Gpu.h" #include <atomic> @@ -41,16 +41,14 @@ SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == this) #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this) -#define ASSERT_SINGLE_OWNER \ - SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());) +#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(this->singleOwner()) #define RETURN_IF_ABANDONED if (this->abandoned()) { return; } #define RETURN_FALSE_IF_ABANDONED if (this->abandoned()) { return false; } #define RETURN_NULL_IF_ABANDONED if (this->abandoned()) { return nullptr; } //////////////////////////////////////////////////////////////////////////////// -GrContext::GrContext(GrBackendApi backend, const GrContextOptions& options, int32_t contextID) - : INHERITED(backend, options, contextID) { +GrContext::GrContext(sk_sp<GrContextThreadSafeProxy> proxy) : INHERITED(std::move(proxy)) { fResourceCache = nullptr; fResourceProvider = nullptr; } @@ -61,20 +59,19 @@ GrContext::~GrContext() { if (this->drawingManager()) { this->drawingManager()->cleanup(); } + fMappedBufferManager.reset(); delete fResourceProvider; delete fResourceCache; } -bool GrContext::init(sk_sp<const GrCaps> caps) { +bool GrContext::init() { ASSERT_SINGLE_OWNER - SkASSERT(fThreadSafeProxy); // needs to have been initialized by derived classes SkASSERT(this->proxyProvider()); - if (!INHERITED::init(std::move(caps))) { + if (!INHERITED::init()) { return false; } - SkASSERT(this->caps()); SkASSERT(this->getTextBlobCache()); if (fGpu) { @@ -106,7 +103,7 @@ bool GrContext::init(sk_sp<const GrCaps> caps) { } sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() { - return fThreadSafeProxy; + return INHERITED::threadSafeProxy(); } ////////////////////////////////////////////////////////////////////////////// @@ -170,6 +167,8 @@ bool GrContext::abandoned() { return false; } +bool GrContext::oomed() { return fGpu ? fGpu->checkAndResetOOMed() : false; } + void GrContext::resetGLTextureBindings() { if (this->abandoned() || this->backend() != GrBackendApi::kOpenGL) { return; @@ -305,35 +304,49 @@ bool GrContext::wait(int numSemaphores, const GrBackendSemaphore waitSemaphores[ std::unique_ptr<GrSemaphore> sema = fResourceProvider->wrapBackendSemaphore( waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait, kAdopt_GrWrapOwnership); - fGpu->waitSemaphore(sema.get()); + // If we failed to wrap the semaphore it means the client didn't give us a valid semaphore + // to begin with. Therefore, it is fine to not wait on it. + if (sema) { + fGpu->waitSemaphore(sema.get()); + } } return true; } //////////////////////////////////////////////////////////////////////////////// -GrSemaphoresSubmitted GrContext::flush(const GrFlushInfo& info, - const GrPrepareForExternalIORequests& externalRequests) { +GrSemaphoresSubmitted GrContext::flush(const GrFlushInfo& info) { ASSERT_SINGLE_OWNER if (this->abandoned()) { + if (info.fFinishedProc) { + info.fFinishedProc(info.fFinishedContext); + } + if (info.fSubmittedProc) { + info.fSubmittedProc(info.fSubmittedContext, false); + } return GrSemaphoresSubmitted::kNo; } - bool submitted = false; - if (this->drawingManager()->flush(nullptr, 0, SkSurface::BackendSurfaceAccess::kNoAccess, - info, externalRequests)) { - bool forceSync = SkToBool(info.fFlags & kSyncCpu_GrFlushFlag); - submitted = this->drawingManager()->submitToGpu(forceSync); - } + bool flushed = this->drawingManager()->flush( + nullptr, 0, SkSurface::BackendSurfaceAccess::kNoAccess, info, nullptr); - if (!submitted || (!this->priv().caps()->semaphoreSupport() && info.fNumSemaphores)) { + if (!flushed || (!this->priv().caps()->semaphoreSupport() && info.fNumSemaphores)) { return GrSemaphoresSubmitted::kNo; } return GrSemaphoresSubmitted::kYes; } -bool GrContext::submit(bool syncToCpu) { - return true; +bool GrContext::submit(bool syncCpu) { + ASSERT_SINGLE_OWNER + if (this->abandoned()) { + return false; + } + + if (!fGpu) { + return false; + } + + return fGpu->submitToGpu(syncCpu); } //////////////////////////////////////////////////////////////////////////////// @@ -461,71 +474,71 @@ GrBackendTexture GrContext::createBackendTexture(const SkSurfaceCharacterization return result; } +static GrBackendTexture create_and_update_backend_texture( + GrContext* context, + SkISize dimensions, + const GrBackendFormat& backendFormat, + GrMipMapped mipMapped, + GrRenderable renderable, + GrProtected isProtected, + sk_sp<GrRefCntedCallback> finishedCallback, + const GrGpu::BackendTextureData* data) { + GrGpu* gpu = context->priv().getGpu(); + + GrBackendTexture beTex = gpu->createBackendTexture(dimensions, backendFormat, renderable, + mipMapped, isProtected); + if (!beTex.isValid()) { + return {}; + } + + if (!context->priv().getGpu()->updateBackendTexture(beTex, std::move(finishedCallback), data)) { + context->deleteBackendTexture(beTex); + return {}; + } + return beTex; +} + + GrBackendTexture GrContext::createBackendTexture(const SkSurfaceCharacterization& c, const SkColor4f& color, GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) { + sk_sp<GrRefCntedCallback> finishedCallback; + if (finishedProc) { + finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext)); + } + if (!this->asDirectContext() || !c.isValid()) { - finishedProc(finishedContext); return {}; } if (this->abandoned()) { - finishedProc(finishedContext); return {}; } if (c.usesGLFBO0()) { - finishedProc(finishedContext); // If we are making the surface we will never use FBO0. return {}; } if (c.vulkanSecondaryCBCompatible()) { - finishedProc(finishedContext); return {}; } const GrBackendFormat format = this->defaultBackendFormat(c.colorType(), GrRenderable::kYes); if (!format.isValid()) { - finishedProc(finishedContext); return {}; } - GrBackendTexture result = this->createBackendTexture(c.width(), c.height(), format, color, - GrMipMapped(c.isMipMapped()), - GrRenderable::kYes, - c.isProtected(), finishedProc, - finishedContext); + GrGpu::BackendTextureData data(color); + GrBackendTexture result = create_and_update_backend_texture( + this, {c.width(), c.height()}, format, GrMipMapped(c.isMipMapped()), GrRenderable::kYes, + c.isProtected(), std::move(finishedCallback), &data); + SkASSERT(c.isCompatible(result)); return result; } -static GrBackendTexture create_and_update_backend_texture(GrContext* context, - SkISize dimensions, - const GrBackendFormat& backendFormat, - GrMipMapped mipMapped, - GrRenderable renderable, - GrProtected isProtected, - GrGpuFinishedProc finishedProc, - GrGpuFinishedContext finishedContext, - const GrGpu::BackendTextureData* data) { - GrGpu* gpu = context->priv().getGpu(); - - GrBackendTexture beTex = gpu->createBackendTexture(dimensions, backendFormat, renderable, - mipMapped, isProtected); - if (!beTex.isValid()) { - return {}; - } - - if (!context->priv().getGpu()->updateBackendTexture(beTex, finishedProc, finishedContext, - data)) { - context->deleteBackendTexture(beTex); - return {}; - } - return beTex; -} - GrBackendTexture GrContext::createBackendTexture(int width, int height, const GrBackendFormat& backendFormat, const SkColor4f& color, @@ -534,20 +547,23 @@ GrBackendTexture GrContext::createBackendTexture(int width, int height, GrProtected isProtected, GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) { + sk_sp<GrRefCntedCallback> finishedCallback; + if (finishedProc) { + finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext)); + } + TRACE_EVENT0("skia.gpu", TRACE_FUNC); if (!this->asDirectContext()) { - finishedProc(finishedContext); return {}; } if (this->abandoned()) { - finishedProc(finishedContext); return {}; } GrGpu::BackendTextureData data(color); return create_and_update_backend_texture(this, {width, height}, backendFormat, mipMapped, - renderable, isProtected, finishedProc, finishedContext, + renderable, isProtected, std::move(finishedCallback), &data); } @@ -559,27 +575,31 @@ GrBackendTexture GrContext::createBackendTexture(int width, int height, GrProtected isProtected, GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) { + sk_sp<GrRefCntedCallback> finishedCallback; + if (finishedProc) { + finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext)); + } + if (!this->asDirectContext()) { - finishedProc(finishedContext); return {}; } if (this->abandoned()) { - finishedProc(finishedContext); return {}; } GrBackendFormat format = this->defaultBackendFormat(skColorType, renderable); if (!format.isValid()) { - finishedProc(finishedContext); return {}; } GrColorType grColorType = SkColorTypeToGrColorType(skColorType); SkColor4f swizzledColor = this->caps()->getWriteSwizzle(format, grColorType).applyTo(color); - return this->createBackendTexture(width, height, format, swizzledColor, mipMapped, renderable, - isProtected, finishedProc, finishedContext); + GrGpu::BackendTextureData data(swizzledColor); + return create_and_update_backend_texture(this, {width, height}, format, mipMapped, + renderable, isProtected, std::move(finishedCallback), + &data); } GrBackendTexture GrContext::createBackendTexture(const SkPixmap srcData[], int numProvidedLevels, @@ -588,18 +608,20 @@ GrBackendTexture GrContext::createBackendTexture(const SkPixmap srcData[], int n GrGpuFinishedContext finishedContext) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); + sk_sp<GrRefCntedCallback> finishedCallback; + if (finishedProc) { + finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext)); + } + if (!this->asDirectContext()) { - finishedProc(finishedContext); return {}; } if (this->abandoned()) { - finishedProc(finishedContext); return {}; } if (!srcData || numProvidedLevels <= 0) { - finishedProc(finishedContext); return {}; } @@ -615,7 +637,6 @@ GrBackendTexture GrContext::createBackendTexture(const SkPixmap srcData[], int n } if (numProvidedLevels != numExpectedLevels) { - finishedProc(finishedContext); return {}; } @@ -623,26 +644,29 @@ GrBackendTexture GrContext::createBackendTexture(const SkPixmap srcData[], int n GrGpu::BackendTextureData data(srcData); return create_and_update_backend_texture(this, {baseWidth, baseHeight}, backendFormat, - mipMapped, renderable, isProtected, finishedProc, - finishedContext, &data); + mipMapped, renderable, isProtected, + std::move(finishedCallback), &data); } bool GrContext::updateBackendTexture(const GrBackendTexture& backendTexture, const SkColor4f& color, GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) { + sk_sp<GrRefCntedCallback> finishedCallback; + if (finishedProc) { + finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext)); + } + if (!this->asDirectContext()) { - finishedProc(finishedContext); return false; } if (this->abandoned()) { - finishedProc(finishedContext); return false; } GrGpu::BackendTextureData data(color); - return fGpu->updateBackendTexture(backendTexture, finishedProc, finishedContext, &data); + return fGpu->updateBackendTexture(backendTexture, std::move(finishedCallback), &data); } bool GrContext::updateBackendTexture(const GrBackendTexture& backendTexture, @@ -650,18 +674,20 @@ bool GrContext::updateBackendTexture(const GrBackendTexture& backendTexture, int numLevels, GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) { + sk_sp<GrRefCntedCallback> finishedCallback; + if (finishedProc) { + finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext)); + } + if (!this->asDirectContext()) { - finishedProc(finishedContext); return false; } if (this->abandoned()) { - finishedProc(finishedContext); return false; } if (!srcData || numLevels <= 0) { - finishedProc(finishedContext); return false; } @@ -671,12 +697,11 @@ bool GrContext::updateBackendTexture(const GrBackendTexture& backendTexture, backendTexture.height()) + 1; } if (numLevels != numExpectedLevels) { - finishedProc(finishedContext); return false; } GrGpu::BackendTextureData data(srcData); - return fGpu->updateBackendTexture(backendTexture, finishedProc, finishedContext, &data); + return fGpu->updateBackendTexture(backendTexture, std::move(finishedCallback), &data); } ////////////////////////////////////////////////////////////////////////////// @@ -689,20 +714,23 @@ GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); + sk_sp<GrRefCntedCallback> finishedCallback; + if (finishedProc) { + finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext)); + } + if (!this->asDirectContext()) { - finishedProc(finishedContext); return {}; } if (this->abandoned()) { - finishedProc(finishedContext); return {}; } GrGpu::BackendTextureData data(color); return fGpu->createCompressedBackendTexture({width, height}, backendFormat, - mipMapped, isProtected, finishedProc, - finishedContext, &data); + mipMapped, isProtected, std::move(finishedCallback), + &data); } GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height, @@ -713,16 +741,6 @@ GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); - if (!this->asDirectContext()) { - finishedProc(finishedContext); - return {}; - } - - if (this->abandoned()) { - finishedProc(finishedContext); - return {}; - } - GrBackendFormat format = this->compressedBackendFormat(compression); return this->createCompressedBackendTexture(width, height, format, color, mipMapped, isProtected, finishedProc, @@ -738,20 +756,23 @@ GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); + sk_sp<GrRefCntedCallback> finishedCallback; + if (finishedProc) { + finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext)); + } + if (!this->asDirectContext()) { - finishedProc(finishedContext); return {}; } if (this->abandoned()) { - finishedProc(finishedContext); return {}; } GrGpu::BackendTextureData data(compressedData, dataSize); return fGpu->createCompressedBackendTexture({width, height}, backendFormat, - mipMapped, isProtected, finishedProc, - finishedContext, &data); + mipMapped, isProtected, std::move(finishedCallback), + &data); } GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height, @@ -762,20 +783,49 @@ GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); + GrBackendFormat format = this->compressedBackendFormat(compression); + return this->createCompressedBackendTexture(width, height, format, data, dataSize, mipMapped, + isProtected, finishedProc, finishedContext); +} + +bool GrContext::setBackendTextureState(const GrBackendTexture& backendTexture, + const GrBackendSurfaceMutableState& state, + GrGpuFinishedProc finishedProc, + GrGpuFinishedContext finishedContext) { + sk_sp<GrRefCntedCallback> callback; + if (finishedProc) { + callback.reset(new GrRefCntedCallback(finishedProc, finishedContext)); + } + if (!this->asDirectContext()) { - finishedProc(finishedContext); - return {}; + return false; } if (this->abandoned()) { - finishedProc(finishedContext); - return {}; + return false; } - GrBackendFormat format = this->compressedBackendFormat(compression); - return this->createCompressedBackendTexture(width, height, format, data, dataSize, - mipMapped, isProtected, finishedProc, - finishedContext); + return fGpu->setBackendTextureState(backendTexture, state, std::move(callback)); +} + +bool GrContext::setBackendRenderTargetState(const GrBackendRenderTarget& backendRenderTarget, + const GrBackendSurfaceMutableState& state, + GrGpuFinishedProc finishedProc, + GrGpuFinishedContext finishedContext) { + sk_sp<GrRefCntedCallback> callback; + if (finishedProc) { + callback.reset(new GrRefCntedCallback(finishedProc, finishedContext)); + } + + if (!this->asDirectContext()) { + return false; + } + + if (this->abandoned()) { + return false; + } + + return fGpu->setBackendRenderTargetState(backendRenderTarget, state, std::move(callback)); } void GrContext::deleteBackendTexture(GrBackendTexture backendTex) { @@ -789,6 +839,8 @@ void GrContext::deleteBackendTexture(GrBackendTexture backendTex) { fGpu->deleteBackendTexture(backendTex); } +////////////////////////////////////////////////////////////////////////////// + bool GrContext::precompileShader(const SkData& key, const SkData& data) { return fGpu->precompileShader(key, data); } diff --git a/chromium/third_party/skia/src/gpu/GrContextPriv.cpp b/chromium/third_party/skia/src/gpu/GrContextPriv.cpp index 702d82dbd94..3c014b13500 100644 --- a/chromium/third_party/skia/src/gpu/GrContextPriv.cpp +++ b/chromium/third_party/skia/src/gpu/GrContextPriv.cpp @@ -28,8 +28,7 @@ #define ASSERT_OWNED_PROXY(P) \ SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == fContext) -#define ASSERT_SINGLE_OWNER \ - SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->singleOwner());) +#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fContext->singleOwner()) #define RETURN_VALUE_IF_ABANDONED(value) if (fContext->abandoned()) { return (value); } #define RETURN_IF_ABANDONED RETURN_VALUE_IF_ABANDONED(void) @@ -53,7 +52,7 @@ GrSemaphoresSubmitted GrContextPriv::flushSurfaces(GrSurfaceProxy* proxies[], in ASSERT_OWNED_PROXY(proxies[i]); } return fContext->drawingManager()->flushSurfaces( - proxies, numProxies, SkSurface::BackendSurfaceAccess::kNoAccess, info); + proxies, numProxies, SkSurface::BackendSurfaceAccess::kNoAccess, info, nullptr); } void GrContextPriv::flushSurface(GrSurfaceProxy* proxy) { @@ -182,7 +181,7 @@ void GrContextPriv::testingOnly_purgeAllUnlockedResources() { } void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) { - fContext->flush(); + fContext->flushAndSubmit(); fContext->drawingManager()->testingOnly_removeOnFlushCallbackObject(cb); } #endif diff --git a/chromium/third_party/skia/src/gpu/GrContextPriv.h b/chromium/third_party/skia/src/gpu/GrContextPriv.h index d97f7adca6d..c5d3f72021e 100644 --- a/chromium/third_party/skia/src/gpu/GrContextPriv.h +++ b/chromium/third_party/skia/src/gpu/GrContextPriv.h @@ -74,7 +74,7 @@ public: /** * Create a GrContext without a resource cache */ - static sk_sp<GrContext> MakeDDL(const sk_sp<GrContextThreadSafeProxy>&); + static sk_sp<GrContext> MakeDDL(sk_sp<GrContextThreadSafeProxy>); /** * Finalizes all pending reads and writes to the surfaces and also performs an MSAA resolves diff --git a/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxy.cpp b/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxy.cpp index fb27ba1822c..6fd86bd1a9f 100644 --- a/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxy.cpp +++ b/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxy.cpp @@ -19,16 +19,24 @@ #include "src/gpu/vk/GrVkCaps.h" #endif +static int32_t next_id() { + static std::atomic<int32_t> nextID{1}; + int32_t id; + do { + id = nextID++; + } while (id == SK_InvalidGenID); + return id; +} + GrContextThreadSafeProxy::GrContextThreadSafeProxy(GrBackendApi backend, - const GrContextOptions& options, - uint32_t contextID) - : INHERITED(backend, options, contextID) { + const GrContextOptions& options) + : fBackend(backend), fOptions(options), fContextID(next_id()) { } GrContextThreadSafeProxy::~GrContextThreadSafeProxy() = default; -bool GrContextThreadSafeProxy::init(sk_sp<const GrCaps> caps) { - return INHERITED::init(std::move(caps)); +void GrContextThreadSafeProxy::init(sk_sp<const GrCaps> caps) { + fCaps = std::move(caps); } SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization( @@ -38,6 +46,7 @@ SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization( const SkSurfaceProps& surfaceProps, bool isMipMapped, bool willUseGLFBO0, bool isTextureable, GrProtected isProtected) { + SkASSERT(fCaps); if (!backendFormat.isValid()) { return SkSurfaceCharacterization(); // return an invalid characterization } @@ -49,39 +58,39 @@ SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization( return SkSurfaceCharacterization(); // return an invalid characterization } - if (!this->caps()->mipMapSupport()) { + if (!fCaps->mipMapSupport()) { isMipMapped = false; } GrColorType grColorType = SkColorTypeToGrColorType(ii.colorType()); - if (!this->caps()->areColorTypeAndFormatCompatible(grColorType, backendFormat)) { + if (!fCaps->areColorTypeAndFormatCompatible(grColorType, backendFormat)) { return SkSurfaceCharacterization(); // return an invalid characterization } - if (!this->caps()->isFormatAsColorTypeRenderable(grColorType, backendFormat, sampleCnt)) { + if (!fCaps->isFormatAsColorTypeRenderable(grColorType, backendFormat, sampleCnt)) { return SkSurfaceCharacterization(); // return an invalid characterization } - sampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, backendFormat); + sampleCnt = fCaps->getRenderTargetSampleCount(sampleCnt, backendFormat); SkASSERT(sampleCnt); if (willUseGLFBO0 && isTextureable) { return SkSurfaceCharacterization(); // return an invalid characterization } - if (isTextureable && !this->caps()->isFormatTexturable(backendFormat)) { + if (isTextureable && !fCaps->isFormatTexturable(backendFormat)) { // Skia doesn't agree that this is textureable. return SkSurfaceCharacterization(); // return an invalid characterization } if (GrBackendApi::kVulkan == backendFormat.backend()) { - if (GrBackendApi::kVulkan != this->backend()) { + if (GrBackendApi::kVulkan != fBackend) { return SkSurfaceCharacterization(); // return an invalid characterization } #ifdef SK_VULKAN - const GrVkCaps* vkCaps = (const GrVkCaps*) this->caps(); + const GrVkCaps* vkCaps = (const GrVkCaps*) fCaps.get(); // The protection status of the characterization and the context need to match if (isProtected != GrProtected(vkCaps->supportsProtectedMemory())) { @@ -101,18 +110,34 @@ SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization( surfaceProps); } +GrBackendFormat GrContextThreadSafeProxy::defaultBackendFormat(SkColorType skColorType, + GrRenderable renderable) const { + SkASSERT(fCaps); + GrColorType grColorType = SkColorTypeToGrColorType(skColorType); + + GrBackendFormat format = fCaps->getDefaultBackendFormat(grColorType, renderable); + if (!format.isValid()) { + return GrBackendFormat(); + } + + SkASSERT(renderable == GrRenderable::kNo || + fCaps->isFormatAsColorTypeRenderable(grColorType, format)); + + return format; +} + +void GrContextThreadSafeProxy::abandonContext() { + fAbandoned.store(true, std::memory_order_relaxed); +} + +bool GrContextThreadSafeProxy::abandoned() const { + return fAbandoned.load(std::memory_order_relaxed); +} + //////////////////////////////////////////////////////////////////////////////// sk_sp<GrContextThreadSafeProxy> GrContextThreadSafeProxyPriv::Make( GrBackendApi backend, - const GrContextOptions& options, - uint32_t contextID, - sk_sp<const GrCaps> caps) { - sk_sp<GrContextThreadSafeProxy> proxy(new GrContextThreadSafeProxy(backend, options, - contextID)); - - if (!proxy->init(std::move(caps))) { - return nullptr; - } - return proxy; + const GrContextOptions& options) { + return sk_sp<GrContextThreadSafeProxy>(new GrContextThreadSafeProxy(backend, options)); } diff --git a/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxyPriv.h b/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxyPriv.h index 0efb995a357..c4873bb9847 100644 --- a/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxyPriv.h +++ b/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxyPriv.h @@ -9,6 +9,7 @@ #define GrContextThreadSafeProxyPriv_DEFINED #include "include/gpu/GrContextThreadSafeProxy.h" +#include "include/private/GrContext_Base.h" #include "src/gpu/GrCaps.h" @@ -19,21 +20,24 @@ */ class GrContextThreadSafeProxyPriv { public: - // from GrContext_Base - uint32_t contextID() const { return fProxy->contextID(); } + void init(sk_sp<const GrCaps> caps) const { fProxy->init(std::move(caps)); } - bool matches(GrContext_Base* candidate) const { return fProxy->matches(candidate); } + bool matches(GrContext_Base* candidate) const { + return fProxy == candidate->threadSafeProxy().get(); + } - const GrContextOptions& options() const { return fProxy->options(); } + GrBackend backend() const { return fProxy->fBackend; } + const GrContextOptions& options() const { return fProxy->fOptions; } + uint32_t contextID() const { return fProxy->fContextID; } - const GrCaps* caps() const { return fProxy->caps(); } - sk_sp<const GrCaps> refCaps() const { return fProxy->refCaps(); } + const GrCaps* caps() const { return fProxy->fCaps.get(); } + sk_sp<const GrCaps> refCaps() const { return fProxy->fCaps; } + + void abandonContext() { fProxy->abandonContext(); } + bool abandoned() const { return fProxy->abandoned(); } // GrContextThreadSafeProxyPriv - static sk_sp<GrContextThreadSafeProxy> Make(GrBackendApi, - const GrContextOptions&, - uint32_t contextID, - sk_sp<const GrCaps>); + static sk_sp<GrContextThreadSafeProxy> Make(GrBackendApi, const GrContextOptions&); private: explicit GrContextThreadSafeProxyPriv(GrContextThreadSafeProxy* proxy) : fProxy(proxy) {} diff --git a/chromium/third_party/skia/src/gpu/GrContext_Base.cpp b/chromium/third_party/skia/src/gpu/GrContext_Base.cpp index 034d0234875..34262997f02 100644 --- a/chromium/third_party/skia/src/gpu/GrContext_Base.cpp +++ b/chromium/third_party/skia/src/gpu/GrContext_Base.cpp @@ -9,53 +9,35 @@ #include "src/gpu/GrBaseContextPriv.h" #include "src/gpu/GrCaps.h" +#include "src/gpu/GrContextThreadSafeProxyPriv.h" #include "src/gpu/GrShaderUtils.h" #include "src/gpu/effects/GrSkSLFP.h" -static int32_t next_id() { - static std::atomic<int32_t> nextID{1}; - int32_t id; - do { - id = nextID++; - } while (id == SK_InvalidGenID); - return id; -} - -GrContext_Base::GrContext_Base(GrBackendApi backend, - const GrContextOptions& options, - uint32_t contextID) - : fBackend(backend) - , fOptions(options) - , fContextID(SK_InvalidGenID == contextID ? next_id() : contextID) { +GrContext_Base::GrContext_Base(sk_sp<GrContextThreadSafeProxy> proxy) + : fThreadSafeProxy(std::move(proxy)) { } GrContext_Base::~GrContext_Base() { } -bool GrContext_Base::init(sk_sp<const GrCaps> caps) { - SkASSERT(caps); +bool GrContext_Base::init() { + SkASSERT(fThreadSafeProxy->isValid()); - fCaps = caps; return true; } -const GrCaps* GrContext_Base::caps() const { return fCaps.get(); } -sk_sp<const GrCaps> GrContext_Base::refCaps() const { return fCaps; } - -GrBackendFormat GrContext_Base::defaultBackendFormat(SkColorType skColorType, - GrRenderable renderable) const { - const GrCaps* caps = this->caps(); - - GrColorType grColorType = SkColorTypeToGrColorType(skColorType); +uint32_t GrContext_Base::contextID() const { return fThreadSafeProxy->priv().contextID(); } +GrBackendApi GrContext_Base::backend() const { return fThreadSafeProxy->priv().backend(); } - GrBackendFormat format = caps->getDefaultBackendFormat(grColorType, renderable); - if (!format.isValid()) { - return GrBackendFormat(); - } +const GrContextOptions& GrContext_Base::options() const { + return fThreadSafeProxy->priv().options(); +} - SkASSERT(renderable == GrRenderable::kNo || - caps->isFormatAsColorTypeRenderable(grColorType, format)); +const GrCaps* GrContext_Base::caps() const { return fThreadSafeProxy->priv().caps(); } +sk_sp<const GrCaps> GrContext_Base::refCaps() const { return fThreadSafeProxy->priv().refCaps(); } - return format; +GrBackendFormat GrContext_Base::defaultBackendFormat(SkColorType skColorType, + GrRenderable renderable) const { + return fThreadSafeProxy->defaultBackendFormat(skColorType, renderable); } GrBackendFormat GrContext_Base::compressedBackendFormat(SkImage::CompressionType c) const { @@ -67,6 +49,8 @@ GrBackendFormat GrContext_Base::compressedBackendFormat(SkImage::CompressionType return format; } +sk_sp<GrContextThreadSafeProxy> GrContext_Base::threadSafeProxy() { return fThreadSafeProxy; } + /////////////////////////////////////////////////////////////////////////////////////////////////// sk_sp<const GrCaps> GrBaseContextPriv::refCaps() const { return fContext->refCaps(); diff --git a/chromium/third_party/skia/src/gpu/GrCopyRenderTask.cpp b/chromium/third_party/skia/src/gpu/GrCopyRenderTask.cpp index 0f46e69efcb..a578451b1a7 100644 --- a/chromium/third_party/skia/src/gpu/GrCopyRenderTask.cpp +++ b/chromium/third_party/skia/src/gpu/GrCopyRenderTask.cpp @@ -11,7 +11,8 @@ #include "src/gpu/GrOpFlushState.h" #include "src/gpu/GrResourceAllocator.h" -sk_sp<GrRenderTask> GrCopyRenderTask::Make(GrSurfaceProxyView srcView, +sk_sp<GrRenderTask> GrCopyRenderTask::Make(GrDrawingManager* drawingMgr, + GrSurfaceProxyView srcView, const SkIRect& srcRect, GrSurfaceProxyView dstView, const SkIPoint& dstPoint, @@ -41,34 +42,35 @@ sk_sp<GrRenderTask> GrCopyRenderTask::Make(GrSurfaceProxyView srcView, } sk_sp<GrCopyRenderTask> task(new GrCopyRenderTask( - std::move(srcView), clippedSrcRect, std::move(dstView), clippedDstPoint)); + drawingMgr, std::move(srcView), clippedSrcRect, std::move(dstView), clippedDstPoint)); return std::move(task); } -GrCopyRenderTask::GrCopyRenderTask(GrSurfaceProxyView srcView, +GrCopyRenderTask::GrCopyRenderTask(GrDrawingManager* drawingMgr, + GrSurfaceProxyView srcView, const SkIRect& srcRect, GrSurfaceProxyView dstView, const SkIPoint& dstPoint) - : GrRenderTask(std::move(dstView)) + : GrRenderTask() , fSrcView(std::move(srcView)) , fSrcRect(srcRect) , fDstPoint(dstPoint) { - fTargetView.proxy()->setLastRenderTask(this); + this->addTarget(drawingMgr, dstView); } void GrCopyRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const { // This renderTask doesn't have "normal" ops. In this case we still need to add an interval (so // fEndOfOpsTaskOpIndices will remain in sync), so we create a fake op# to capture the fact that - // we read fSrcView and copy to fTargetView. + // we read fSrcView and copy to target view. alloc->addInterval(fSrcView.proxy(), alloc->curOp(), alloc->curOp(), GrResourceAllocator::ActualUse::kYes); - alloc->addInterval(fTargetView.proxy(), alloc->curOp(), alloc->curOp(), + alloc->addInterval(this->target(0).proxy(), alloc->curOp(), alloc->curOp(), GrResourceAllocator::ActualUse::kYes); alloc->incOps(); } bool GrCopyRenderTask::onExecute(GrOpFlushState* flushState) { - GrSurfaceProxy* dstProxy = fTargetView.proxy(); + GrSurfaceProxy* dstProxy = this->target(0).proxy(); GrSurfaceProxy* srcProxy = fSrcView.proxy(); if (!srcProxy->isInstantiated() || !dstProxy->isInstantiated()) { return false; diff --git a/chromium/third_party/skia/src/gpu/GrCopyRenderTask.h b/chromium/third_party/skia/src/gpu/GrCopyRenderTask.h index a9c79ea43c7..4ecd3c7f1dc 100644 --- a/chromium/third_party/skia/src/gpu/GrCopyRenderTask.h +++ b/chromium/third_party/skia/src/gpu/GrCopyRenderTask.h @@ -12,21 +12,21 @@ class GrCopyRenderTask final : public GrRenderTask { public: - static sk_sp<GrRenderTask> Make(GrSurfaceProxyView srcView, + static sk_sp<GrRenderTask> Make(GrDrawingManager*, + GrSurfaceProxyView srcView, const SkIRect& srcRect, GrSurfaceProxyView dstView, const SkIPoint& dstPoint, const GrCaps*); private: - GrCopyRenderTask(GrSurfaceProxyView srcView, + GrCopyRenderTask(GrDrawingManager*, + GrSurfaceProxyView srcView, const SkIRect& srcRect, GrSurfaceProxyView dstView, const SkIPoint& dstPoint); bool onIsUsed(GrSurfaceProxy* proxy) const override { - // This case should be handled by GrRenderTask. - SkASSERT(proxy != fTargetView.proxy()); return proxy == fSrcView.proxy(); } // If instantiation failed, at flush time we simply will skip doing the copy. diff --git a/chromium/third_party/skia/src/gpu/GrDDLContext.cpp b/chromium/third_party/skia/src/gpu/GrDDLContext.cpp index 1f77417a208..ee77eaf8044 100644 --- a/chromium/third_party/skia/src/gpu/GrDDLContext.cpp +++ b/chromium/third_party/skia/src/gpu/GrDDLContext.cpp @@ -21,8 +21,7 @@ class GrDDLContext final : public GrContext { public: GrDDLContext(sk_sp<GrContextThreadSafeProxy> proxy) - : INHERITED(proxy->backend(), proxy->priv().options(), proxy->priv().contextID()) { - fThreadSafeProxy = std::move(proxy); + : INHERITED(std::move(proxy)) { } ~GrDDLContext() override {} @@ -38,8 +37,8 @@ public: } void freeGpuResources() override { - SkASSERT(0); // freeing resources in a DDL Recorder doesn't make a whole lot of sense - INHERITED::freeGpuResources(); + // freeing resources in a DDL Recorder doesn't make a whole lot of sense but some of + // our tests do it anyways } private: @@ -47,11 +46,8 @@ private: // GrRecordingContext! GrContext* asDirectContext() override { return nullptr; } - bool init(sk_sp<const GrCaps> caps) override { - SkASSERT(caps); - SkASSERT(fThreadSafeProxy); // should've been set in the ctor - - if (!INHERITED::init(std::move(caps))) { + bool init() override { + if (!INHERITED::init()) { return false; } @@ -59,8 +55,6 @@ private: // splitting. this->setupDrawingManager(true, true); - SkASSERT(this->caps()); - return true; } @@ -79,8 +73,9 @@ private: if (this->backend() == GrBackendApi::kVulkan || this->backend() == GrBackendApi::kMetal || + this->backend() == GrBackendApi::kDirect3D || this->backend() == GrBackendApi::kDawn) { - // Currently, Vulkan, Metal and Dawn require a live renderTarget to + // Currently Vulkan, Metal, Direct3D, and Dawn require a live renderTarget to // compute the key return; } @@ -153,10 +148,10 @@ private: typedef GrContext INHERITED; }; -sk_sp<GrContext> GrContextPriv::MakeDDL(const sk_sp<GrContextThreadSafeProxy>& proxy) { - sk_sp<GrContext> context(new GrDDLContext(proxy)); +sk_sp<GrContext> GrContextPriv::MakeDDL(sk_sp<GrContextThreadSafeProxy> proxy) { + sk_sp<GrContext> context(new GrDDLContext(std::move(proxy))); - if (!context->init(proxy->priv().refCaps())) { + if (!context->init()) { return nullptr; } return context; diff --git a/chromium/third_party/skia/src/gpu/GrDataUtils.cpp b/chromium/third_party/skia/src/gpu/GrDataUtils.cpp index a6102fd24ca..7e6a6c734eb 100644 --- a/chromium/third_party/skia/src/gpu/GrDataUtils.cpp +++ b/chromium/third_party/skia/src/gpu/GrDataUtils.cpp @@ -7,6 +7,7 @@ #include "src/gpu/GrDataUtils.h" +#include "include/third_party/skcms/skcms.h" #include "src/core/SkColorSpaceXformSteps.h" #include "src/core/SkCompressedDataUtils.h" #include "src/core/SkConvertPixels.h" @@ -595,10 +596,10 @@ bool GrConvertPixels(const GrImageInfo& dstInfo, void* dst, size_t dstRB, if (hasConversion) { loadSwizzle.apply(&pipeline); if (srcIsSRGB) { - pipeline.append(SkRasterPipeline::from_srgb); + pipeline.append_transfer_function(*skcms_sRGB_TransferFunction()); } if (alphaOrCSConversion) { - steps->apply(&pipeline, srcIsNormalized); + steps->apply(&pipeline); } if (clampGamut) { append_clamp_gamut(&pipeline); @@ -606,14 +607,14 @@ bool GrConvertPixels(const GrImageInfo& dstInfo, void* dst, size_t dstRB, if (doLumToAlpha) { pipeline.append(SkRasterPipeline::StockStage::bt709_luminance_or_luma_to_alpha); // If we ever needed to convert from linear-encoded gray to sRGB-encoded - // gray we'd have a problem here because the subsequent to_srgb stage + // gray we'd have a problem here because the subsequent transfer function stage // ignores the alpha channel (where we just stashed the gray). There are // several ways that could be fixed but given our current set of color types // this should never happen. SkASSERT(!dstIsSRGB); } if (dstIsSRGB) { - pipeline.append(SkRasterPipeline::to_srgb); + pipeline.append_transfer_function(*skcms_sRGB_Inverse_TransferFunction()); } storeSwizzle.apply(&pipeline); } else { @@ -664,14 +665,14 @@ bool GrClearImage(const GrImageInfo& dstInfo, void* dst, size_t dstRB, SkColor4f if (doLumToAlpha) { pipeline.append(SkRasterPipeline::StockStage::bt709_luminance_or_luma_to_alpha); // If we ever needed to convert from linear-encoded gray to sRGB-encoded - // gray we'd have a problem here because the subsequent to_srgb stage + // gray we'd have a problem here because the subsequent transfer function stage // ignores the alpha channel (where we just stashed the gray). There are // several ways that could be fixed but given our current set of color types // this should never happen. SkASSERT(!dstIsSRGB); } if (dstIsSRGB) { - pipeline.append(SkRasterPipeline::to_srgb); + pipeline.append_transfer_function(*skcms_sRGB_Inverse_TransferFunction()); } storeSwizzle.apply(&pipeline); SkRasterPipeline_MemoryCtx dstCtx{dst, SkToInt(dstRB/dstInfo.bpp())}; diff --git a/chromium/third_party/skia/src/gpu/GrDefaultGeoProcFactory.cpp b/chromium/third_party/skia/src/gpu/GrDefaultGeoProcFactory.cpp index 4f93238d1ae..94ba1846cbd 100644 --- a/chromium/third_party/skia/src/gpu/GrDefaultGeoProcFactory.cpp +++ b/chromium/third_party/skia/src/gpu/GrDefaultGeoProcFactory.cpp @@ -57,6 +57,7 @@ public: public: GLSLProcessor() : fViewMatrix(SkMatrix::InvalidMatrix()) + , fLocalMatrix(SkMatrix::InvalidMatrix()) , fColor(SK_PMColor4fILLEGAL) , fCoverage(0xff) {} @@ -111,14 +112,14 @@ public: &fViewMatrixUniform); // emit transforms using either explicit local coords or positions - const auto& coordsAttr = gp.fInLocalCoords.isInitialized() ? gp.fInLocalCoords - : gp.fInPosition; - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - coordsAttr.asShaderVar(), - gp.localMatrix(), - args.fFPCoordTransformHandler); + if (gp.fInLocalCoords.isInitialized()) { + SkASSERT(gp.localMatrix().isIdentity()); + gpArgs->fLocalCoordVar = gp.fInLocalCoords.asShaderVar(); + } else if (gp.fLocalCoordsWillBeRead) { + this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, + gp.fInPosition.asShaderVar(), gp.localMatrix(), + &fLocalMatrixUniform); + } // Setup coverage as pass through if (gp.hasVertexCoverage() && !tweakAlpha) { @@ -144,8 +145,12 @@ public: const DefaultGeoProc& def = gp.cast<DefaultGeoProc>(); uint32_t key = def.fFlags; key |= (def.coverage() == 0xff) ? 0x80 : 0; - key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x100 : 0; - key |= ComputePosKey(def.viewMatrix()) << 20; + key |= def.localCoordsWillBeRead() ? 0x100 : 0; + + bool usesLocalMatrix = def.localCoordsWillBeRead() && + !def.fInLocalCoords.isInitialized(); + key = AddMatrixKeys(key, def.viewMatrix(), + usesLocalMatrix ? def.localMatrix() : SkMatrix::I()); b->add32(key); } @@ -154,12 +159,9 @@ public: const CoordTransformRange& transformRange) override { const DefaultGeoProc& dgp = gp.cast<DefaultGeoProc>(); - if (!dgp.viewMatrix().isIdentity() && - !SkMatrixPriv::CheapEqual(fViewMatrix, dgp.viewMatrix())) - { - fViewMatrix = dgp.viewMatrix(); - pdman.setSkMatrix(fViewMatrixUniform, fViewMatrix); - } + this->setTransform(pdman, fViewMatrixUniform, dgp.viewMatrix(), &fViewMatrix); + this->setTransform(pdman, fLocalMatrixUniform, dgp.localMatrix(), &fLocalMatrix); + this->setTransformDataHelper(pdman, transformRange); if (!dgp.hasVertexColor() && dgp.color() != fColor) { pdman.set4fv(fColorUniform, 1, dgp.color().vec()); @@ -170,14 +172,15 @@ public: pdman.set1f(fCoverageUniform, GrNormalizeByteToFloat(dgp.coverage())); fCoverage = dgp.coverage(); } - this->setTransformDataHelper(dgp.fLocalMatrix, pdman, transformRange); } private: SkMatrix fViewMatrix; + SkMatrix fLocalMatrix; SkPMColor4f fColor; uint8_t fCoverage; UniformHandle fViewMatrixUniform; + UniformHandle fLocalMatrixUniform; UniformHandle fColorUniform; UniformHandle fCoverageUniform; diff --git a/chromium/third_party/skia/src/gpu/GrDrawingManager.cpp b/chromium/third_party/skia/src/gpu/GrDrawingManager.cpp index 83af6b41c7d..5ae2684c582 100644 --- a/chromium/third_party/skia/src/gpu/GrDrawingManager.cpp +++ b/chromium/third_party/skia/src/gpu/GrDrawingManager.cpp @@ -10,6 +10,7 @@ #include "include/core/SkDeferredDisplayList.h" #include "include/gpu/GrBackendSemaphore.h" #include "include/private/GrRecordingContext.h" +#include "src/core/SkDeferredDisplayListPriv.h" #include "src/core/SkTTopoSort.h" #include "src/gpu/GrAuditTrail.h" #include "src/gpu/GrClientMappedBufferManager.h" @@ -36,7 +37,7 @@ #include "src/gpu/GrTransferFromRenderTask.h" #include "src/gpu/GrWaitRenderTask.h" #include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h" -#include "src/gpu/text/GrTextContext.h" +#include "src/gpu/text/GrSDFTOptions.h" #include "src/image/SkSurface_Gpu.h" GrDrawingManager::RenderTaskDAG::RenderTaskDAG(bool sortRenderTasks) @@ -57,27 +58,15 @@ void GrDrawingManager::RenderTaskDAG::reset() { fRenderTasks.reset(); } -void GrDrawingManager::RenderTaskDAG::removeRenderTask(int index) { - if (!fRenderTasks[index]->unique()) { - // TODO: Eventually this should be guaranteed unique: http://skbug.com/7111 - fRenderTasks[index]->endFlush(); - } - - fRenderTasks[index] = nullptr; -} - void GrDrawingManager::RenderTaskDAG::removeRenderTasks(int startIndex, int stopIndex) { for (int i = startIndex; i < stopIndex; ++i) { - if (!fRenderTasks[i]) { - continue; - } - this->removeRenderTask(i); + fRenderTasks[i] = nullptr; } } bool GrDrawingManager::RenderTaskDAG::isUsed(GrSurfaceProxy* proxy) const { - for (int i = 0; i < fRenderTasks.count(); ++i) { - if (fRenderTasks[i] && fRenderTasks[i]->isUsed(proxy)) { + for (const auto& task : fRenderTasks) { + if (task && task->isUsed(proxy)) { return true; } } @@ -134,7 +123,7 @@ void GrDrawingManager::RenderTaskDAG::prepForFlush() { GrOpsTask* curOpsTask = fRenderTasks[i]->asOpsTask(); if (prevOpsTask && curOpsTask) { - SkASSERT(prevOpsTask->fTargetView != curOpsTask->fTargetView); + SkASSERT(prevOpsTask->target(0).proxy() != curOpsTask->target(0).proxy()); } prevOpsTask = curOpsTask; @@ -151,7 +140,7 @@ void GrDrawingManager::RenderTaskDAG::closeAll(const GrCaps* caps) { } } -void GrDrawingManager::RenderTaskDAG::cleanup(const GrCaps* caps) { +void GrDrawingManager::RenderTaskDAG::cleanup(GrDrawingManager* drawingMgr, const GrCaps* caps) { for (int i = 0; i < fRenderTasks.count(); ++i) { if (!fRenderTasks[i]) { continue; @@ -160,13 +149,15 @@ void GrDrawingManager::RenderTaskDAG::cleanup(const GrCaps* caps) { // no renderTask should receive a dependency fRenderTasks[i]->makeClosed(*caps); + fRenderTasks[i]->disown(drawingMgr); + // We shouldn't need to do this, but it turns out some clients still hold onto opsTasks // after a cleanup. // MDB TODO: is this still true? if (!fRenderTasks[i]->unique()) { // TODO: Eventually this should be guaranteed unique. // https://bugs.chromium.org/p/skia/issues/detail?id=7111 - fRenderTasks[i]->endFlush(); + fRenderTasks[i]->endFlush(drawingMgr); } } @@ -176,22 +167,18 @@ void GrDrawingManager::RenderTaskDAG::cleanup(const GrCaps* caps) { /////////////////////////////////////////////////////////////////////////////////////////////////// GrDrawingManager::GrDrawingManager(GrRecordingContext* context, const GrPathRendererChain::Options& optionsForPathRendererChain, - const GrTextContext::Options& optionsForTextContext, bool sortRenderTasks, bool reduceOpsTaskSplitting) : fContext(context) , fOptionsForPathRendererChain(optionsForPathRendererChain) - , fOptionsForTextContext(optionsForTextContext) , fDAG(sortRenderTasks) - , fTextContext(nullptr) , fPathRendererChain(nullptr) , fSoftwarePathRenderer(nullptr) , fFlushing(false) - , fReduceOpsTaskSplitting(reduceOpsTaskSplitting) { -} + , fReduceOpsTaskSplitting(reduceOpsTaskSplitting) { } void GrDrawingManager::cleanup() { - fDAG.cleanup(fContext->priv().caps()); + fDAG.cleanup(this, fContext->priv().caps()); fPathRendererChain = nullptr; fSoftwarePathRenderer = nullptr; @@ -221,14 +208,20 @@ void GrDrawingManager::freeGpuResources() { } // MDB TODO: make use of the 'proxy' parameter. -bool GrDrawingManager::flush(GrSurfaceProxy* proxies[], int numProxies, - SkSurface::BackendSurfaceAccess access, const GrFlushInfo& info, - const GrPrepareForExternalIORequests& externalRequests) { +bool GrDrawingManager::flush( + GrSurfaceProxy* proxies[], + int numProxies, + SkSurface::BackendSurfaceAccess access, + const GrFlushInfo& info, + const GrBackendSurfaceMutableState* newState) { SkASSERT(numProxies >= 0); SkASSERT(!numProxies || proxies); GR_CREATE_TRACE_MARKER_CONTEXT("GrDrawingManager", "flush", fContext); if (fFlushing || this->wasAbandoned()) { + if (info.fSubmittedProc) { + info.fSubmittedProc(info.fSubmittedContext, false); + } if (info.fFinishedProc) { info.fFinishedProc(info.fFinishedContext); } @@ -238,18 +231,24 @@ bool GrDrawingManager::flush(GrSurfaceProxy* proxies[], int numProxies, SkDEBUGCODE(this->validate()); if (kNone_GrFlushFlags == info.fFlags && !info.fNumSemaphores && !info.fFinishedProc && - !externalRequests.hasRequests()) { + access == SkSurface::BackendSurfaceAccess::kNoAccess && !newState) { bool canSkip = numProxies > 0; for (int i = 0; i < numProxies && canSkip; ++i) { canSkip = !fDAG.isUsed(proxies[i]) && !this->isDDLTarget(proxies[i]); } if (canSkip) { + if (info.fSubmittedProc) { + info.fSubmittedProc(info.fSubmittedContext, true); + } return false; } } auto direct = fContext->priv().asDirectContext(); if (!direct) { + if (info.fSubmittedProc) { + info.fSubmittedProc(info.fSubmittedContext, false); + } if (info.fFinishedProc) { info.fFinishedProc(info.fFinishedContext); } @@ -258,12 +257,8 @@ bool GrDrawingManager::flush(GrSurfaceProxy* proxies[], int numProxies, direct->priv().clientMappedBufferManager()->process(); GrGpu* gpu = direct->priv().getGpu(); - if (!gpu) { - if (info.fFinishedProc) { - info.fFinishedProc(info.fFinishedContext); - } - return false; // Can't flush while DDL recording - } + // We have a non abandoned and direct GrContext. It must have a GrGpu. + SkASSERT(gpu); fFlushing = true; @@ -382,6 +377,7 @@ bool GrDrawingManager::flush(GrSurfaceProxy* proxies[], int numProxies, SkASSERT(!fDAG.renderTask(i) || fDAG.renderTask(i)->unique()); } #endif + fLastRenderTasks.reset(); fDAG.reset(); this->clearDDLTargets(); @@ -394,7 +390,7 @@ bool GrDrawingManager::flush(GrSurfaceProxy* proxies[], int numProxies, opMemoryPool->isEmpty(); #endif - gpu->executeFlushInfo(proxies, numProxies, access, info, externalRequests); + gpu->executeFlushInfo(proxies, numProxies, access, info, newState); // Give the cache a chance to purge resources that become purgeable due to flushing. if (flushed) { @@ -471,6 +467,7 @@ bool GrDrawingManager::executeRenderTasks(int startIndex, int stopIndex, GrOpFlu SkDebugf("WARNING: onFlushRenderTask failed to execute.\n"); } SkASSERT(onFlushRenderTask->unique()); + onFlushRenderTask->disown(this); onFlushRenderTask = nullptr; (*numRenderTasksExecuted)++; if (*numRenderTasksExecuted >= kMaxRenderTasksBeforeFlush) { @@ -505,15 +502,70 @@ bool GrDrawingManager::executeRenderTasks(int startIndex, int stopIndex, GrOpFlu // resources are the last to be purged by the resource cache. flushState->reset(); - fDAG.removeRenderTasks(startIndex, stopIndex); + this->removeRenderTasks(startIndex, stopIndex); return anyRenderTasksExecuted; } -GrSemaphoresSubmitted GrDrawingManager::flushSurfaces(GrSurfaceProxy* proxies[], int numProxies, - SkSurface::BackendSurfaceAccess access, - const GrFlushInfo& info) { +void GrDrawingManager::removeRenderTasks(int startIndex, int stopIndex) { + for (int i = startIndex; i < stopIndex; ++i) { + GrRenderTask* task = fDAG.renderTask(i); + if (!task) { + continue; + } + if (!task->unique()) { + // TODO: Eventually this should be guaranteed unique: http://skbug.com/7111 + task->endFlush(this); + } + task->disown(this); + } + fDAG.removeRenderTasks(startIndex, stopIndex); +} + +static void resolve_and_mipmap(GrGpu* gpu, GrSurfaceProxy* proxy) { + if (!proxy->isInstantiated()) { + return; + } + + // In the flushSurfaces case, we need to resolve MSAA immediately after flush. This is + // because clients expect the flushed surface's backing texture to be fully resolved + // upon return. + if (proxy->requiresManualMSAAResolve()) { + auto* rtProxy = proxy->asRenderTargetProxy(); + SkASSERT(rtProxy); + if (rtProxy->isMSAADirty()) { + SkASSERT(rtProxy->peekRenderTarget()); + gpu->resolveRenderTarget(rtProxy->peekRenderTarget(), rtProxy->msaaDirtyRect(), + GrGpu::ForExternalIO::kYes); + rtProxy->markMSAAResolved(); + } + } + // If, after a flush, any of the proxies of interest have dirty mipmaps, regenerate them in + // case their backend textures are being stolen. + // (This special case is exercised by the ReimportImageTextureWithMipLevels test.) + // FIXME: It may be more ideal to plumb down a "we're going to steal the backends" flag. + if (auto* textureProxy = proxy->asTextureProxy()) { + if (textureProxy->mipMapsAreDirty()) { + SkASSERT(textureProxy->peekTexture()); + gpu->regenerateMipMapLevels(textureProxy->peekTexture()); + textureProxy->markMipMapsClean(); + } + } +} + +GrSemaphoresSubmitted GrDrawingManager::flushSurfaces( + GrSurfaceProxy* proxies[], + int numProxies, + SkSurface::BackendSurfaceAccess access, + const GrFlushInfo& info, + const GrBackendSurfaceMutableState* newState) { if (this->wasAbandoned()) { + if (info.fSubmittedProc) { + info.fSubmittedProc(info.fSubmittedContext, false); + } + if (info.fFinishedProc) { + info.fFinishedProc(info.fFinishedContext); + } return GrSemaphoresSubmitted::kNo; } SkDEBUGCODE(this->validate()); @@ -522,59 +574,30 @@ GrSemaphoresSubmitted GrDrawingManager::flushSurfaces(GrSurfaceProxy* proxies[], auto direct = fContext->priv().asDirectContext(); if (!direct) { + if (info.fSubmittedProc) { + info.fSubmittedProc(info.fSubmittedContext, false); + } + if (info.fFinishedProc) { + info.fFinishedProc(info.fFinishedContext); + } return GrSemaphoresSubmitted::kNo; // Can't flush while DDL recording } GrGpu* gpu = direct->priv().getGpu(); - if (!gpu) { - return GrSemaphoresSubmitted::kNo; // Can't flush while DDL recording - } + // We have a non abandoned and direct GrContext. It must have a GrGpu. + SkASSERT(gpu); // TODO: It is important to upgrade the drawingmanager to just flushing the // portion of the DAG required by 'proxies' in order to restore some of the // semantics of this method. - bool didFlush = this->flush(proxies, numProxies, access, info, - GrPrepareForExternalIORequests()); + bool didFlush = this->flush(proxies, numProxies, access, info, newState); for (int i = 0; i < numProxies; ++i) { - GrSurfaceProxy* proxy = proxies[i]; - if (!proxy->isInstantiated()) { - continue; - } - // In the flushSurfaces case, we need to resolve MSAA immediately after flush. This is - // because the client will call through to this method when drawing into a target created by - // wrapBackendTextureAsRenderTarget, and will expect the original texture to be fully - // resolved upon return. - if (proxy->requiresManualMSAAResolve()) { - auto* rtProxy = proxy->asRenderTargetProxy(); - SkASSERT(rtProxy); - if (rtProxy->isMSAADirty()) { - SkASSERT(rtProxy->peekRenderTarget()); - gpu->resolveRenderTarget(rtProxy->peekRenderTarget(), rtProxy->msaaDirtyRect(), - GrGpu::ForExternalIO::kYes); - rtProxy->markMSAAResolved(); - } - } - // If, after a flush, any of the proxies of interest have dirty mipmaps, regenerate them in - // case their backend textures are being stolen. - // (This special case is exercised by the ReimportImageTextureWithMipLevels test.) - // FIXME: It may be more ideal to plumb down a "we're going to steal the backends" flag. - if (auto* textureProxy = proxy->asTextureProxy()) { - if (textureProxy->mipMapsAreDirty()) { - SkASSERT(textureProxy->peekTexture()); - gpu->regenerateMipMapLevels(textureProxy->peekTexture()); - textureProxy->markMipMapsClean(); - } - } + resolve_and_mipmap(gpu, proxies[i]); } SkDEBUGCODE(this->validate()); - bool submitted = false; - if (didFlush) { - submitted = this->submitToGpu(SkToBool(info.fFlags & kSyncCpu_GrFlushFlag)); - } - - if (!submitted || (!direct->priv().caps()->semaphoreSupport() && info.fNumSemaphores)) { + if (!didFlush || (!direct->priv().caps()->semaphoreSupport() && info.fNumSemaphores)) { return GrSemaphoresSubmitted::kNo; } return GrSemaphoresSubmitted::kYes; @@ -593,6 +616,31 @@ void GrDrawingManager::testingOnly_removeOnFlushCallbackObject(GrOnFlushCallback } #endif +void GrDrawingManager::setLastRenderTask(const GrSurfaceProxy* proxy, GrRenderTask* task) { +#ifdef SK_DEBUG + if (GrRenderTask* prior = this->getLastRenderTask(proxy)) { + SkASSERT(prior->isClosed()); + } +#endif + uint32_t key = proxy->uniqueID().asUInt(); + if (task) { + fLastRenderTasks.set(key, task); + } else if (fLastRenderTasks.find(key)) { + fLastRenderTasks.remove(key); + } +} + +GrRenderTask* GrDrawingManager::getLastRenderTask(const GrSurfaceProxy* proxy) const { + auto entry = fLastRenderTasks.find(proxy->uniqueID().asUInt()); + return entry ? *entry : nullptr; +} + +GrOpsTask* GrDrawingManager::getLastOpsTask(const GrSurfaceProxy* proxy) const { + GrRenderTask* task = this->getLastRenderTask(proxy); + return task ? task->asOpsTask() : nullptr; +} + + void GrDrawingManager::moveRenderTasksToDDL(SkDeferredDisplayList* ddl) { SkDEBUGCODE(this->validate()); @@ -604,6 +652,7 @@ void GrDrawingManager::moveRenderTasksToDDL(SkDeferredDisplayList* ddl) { SkASSERT(!fDAG.numRenderTasks()); for (auto& renderTask : ddl->fRenderTasks) { + renderTask->disown(this); renderTask->prePrepare(fContext); } @@ -633,7 +682,17 @@ void GrDrawingManager::copyRenderTasksFromDDL(const SkDeferredDisplayList* ddl, fActiveOpsTask = nullptr; } - this->addDDLTarget(newDest); + // Propagate the DDL proxy's state information to the replaying DDL. + if (ddl->priv().targetProxy()->isMSAADirty()) { + newDest->markMSAADirty(ddl->priv().targetProxy()->msaaDirtyRect(), + ddl->characterization().origin()); + } + GrTextureProxy* newTextureProxy = newDest->asTextureProxy(); + if (newTextureProxy && GrMipMapped::kYes == newTextureProxy->mipMapped()) { + newTextureProxy->markMipMapsDirty(); + } + + this->addDDLTarget(newDest, ddl->priv().targetProxy()); // Here we jam the proxy that backs the current replay SkSurface into the LazyProxyData. // The lazy proxy that references it (in the copied opsTasks) will steal its GrTexture. @@ -685,7 +744,7 @@ void GrDrawingManager::closeRenderTasksForNewRenderTask(GrSurfaceProxy* target) // split in case they use both the old and new content. (This is a bit of an overkill: they // really only need to be split if they ever reference proxy's contents again but that is // hard to predict/handle). - if (GrRenderTask* lastRenderTask = target->getLastRenderTask()) { + if (GrRenderTask* lastRenderTask = this->getLastRenderTask(target)) { lastRenderTask->closeThoseWhoDependOnMe(*fContext->priv().caps()); } } else if (fActiveOpsTask) { @@ -706,10 +765,10 @@ sk_sp<GrOpsTask> GrDrawingManager::newOpsTask(GrSurfaceProxyView surfaceView, GrSurfaceProxy* proxy = surfaceView.proxy(); this->closeRenderTasksForNewRenderTask(proxy); - sk_sp<GrOpsTask> opsTask(new GrOpsTask(fContext->priv().arenas(), + sk_sp<GrOpsTask> opsTask(new GrOpsTask(this, fContext->priv().arenas(), std::move(surfaceView), fContext->priv().auditTrail())); - SkASSERT(proxy->getLastRenderTask() == opsTask.get()); + SkASSERT(this->getLastRenderTask(proxy) == opsTask.get()); if (managedOpsTask) { fDAG.add(opsTask); @@ -749,7 +808,7 @@ void GrDrawingManager::newWaitRenderTask(sk_sp<GrSurfaceProxy> proxy, std::move(semaphores), numSemaphores); if (fReduceOpsTaskSplitting) { - GrRenderTask* lastTask = proxy->getLastRenderTask(); + GrRenderTask* lastTask = this->getLastRenderTask(proxy.get()); if (lastTask && !lastTask->isClosed()) { // We directly make the currently open renderTask depend on waitTask instead of using // the proxy version of addDependency. The waitTask will never need to trigger any @@ -773,12 +832,12 @@ void GrDrawingManager::newWaitRenderTask(sk_sp<GrSurfaceProxy> proxy, if (lastTask) { waitTask->addDependency(lastTask); } - proxy->setLastRenderTask(waitTask.get()); + this->setLastRenderTask(proxy.get(), waitTask.get()); } fDAG.add(waitTask); } else { - if (fActiveOpsTask && (fActiveOpsTask->fTargetView.proxy() == proxy.get())) { - SkASSERT(proxy->getLastRenderTask() == fActiveOpsTask); + if (fActiveOpsTask && (fActiveOpsTask->target(0).proxy() == proxy.get())) { + SkASSERT(this->getLastRenderTask(proxy.get()) == fActiveOpsTask); fDAG.addBeforeLast(waitTask); // In this case we keep the current renderTask open but just insert the new waitTask // before it in the list. The waitTask will never need to trigger any resolves or mip @@ -800,10 +859,10 @@ void GrDrawingManager::newWaitRenderTask(sk_sp<GrSurfaceProxy> proxy, // there is a lastTask on the proxy we make waitTask depend on that task. This // dependency isn't strictly needed but it does keep the DAG from reordering the // waitTask earlier and blocking more tasks. - if (GrRenderTask* lastTask = proxy->getLastRenderTask()) { + if (GrRenderTask* lastTask = this->getLastRenderTask(proxy.get())) { waitTask->addDependency(lastTask); } - proxy->setLastRenderTask(waitTask.get()); + this->setLastRenderTask(proxy.get(), waitTask.get()); this->closeRenderTasksForNewRenderTask(proxy.get()); fDAG.add(waitTask); } @@ -825,13 +884,15 @@ void GrDrawingManager::newTransferFromRenderTask(sk_sp<GrSurfaceProxy> srcProxy, this->closeRenderTasksForNewRenderTask(nullptr); GrRenderTask* task = fDAG.add(sk_make_sp<GrTransferFromRenderTask>( - srcProxy, srcRect, surfaceColorType, dstColorType, std::move(dstBuffer), dstOffset)); + srcProxy, srcRect, surfaceColorType, dstColorType, + std::move(dstBuffer), dstOffset)); const GrCaps& caps = *fContext->priv().caps(); // We always say GrMipMapped::kNo here since we are always just copying from the base layer. We // don't need to make sure the whole mip map chain is valid. - task->addDependency(srcProxy.get(), GrMipMapped::kNo, GrTextureResolveManager(this), caps); + task->addDependency(this, srcProxy.get(), GrMipMapped::kNo, + GrTextureResolveManager(this), caps); task->makeClosed(caps); // We have closed the previous active oplist but since a new oplist isn't being added there @@ -853,7 +914,7 @@ bool GrDrawingManager::newCopyRenderTask(GrSurfaceProxyView srcView, GrSurfaceProxy* srcProxy = srcView.proxy(); GrRenderTask* task = - fDAG.add(GrCopyRenderTask::Make(std::move(srcView), srcRect, std::move(dstView), + fDAG.add(GrCopyRenderTask::Make(this, std::move(srcView), srcRect, std::move(dstView), dstPoint, &caps)); if (!task) { return false; @@ -861,7 +922,7 @@ bool GrDrawingManager::newCopyRenderTask(GrSurfaceProxyView srcView, // We always say GrMipMapped::kNo here since we are always just copying from the base layer to // another base layer. We don't need to make sure the whole mip map chain is valid. - task->addDependency(srcProxy, GrMipMapped::kNo, GrTextureResolveManager(this), caps); + task->addDependency(this, srcProxy, GrMipMapped::kNo, GrTextureResolveManager(this), caps); task->makeClosed(caps); // We have closed the previous active oplist but since a new oplist isn't being added there @@ -871,14 +932,6 @@ bool GrDrawingManager::newCopyRenderTask(GrSurfaceProxyView srcView, return true; } -GrTextContext* GrDrawingManager::getTextContext() { - if (!fTextContext) { - fTextContext = GrTextContext::Make(fOptionsForTextContext); - } - - return fTextContext.get(); -} - /* * This method finds a path renderer that can draw the specified path on * the provided target. @@ -936,7 +989,7 @@ void GrDrawingManager::flushIfNecessary() { auto resourceCache = direct->priv().getResourceCache(); if (resourceCache && resourceCache->requestsFlush()) { if (this->flush(nullptr, 0, SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo(), - GrPrepareForExternalIORequests())) { + nullptr)) { this->submitToGpu(false); } resourceCache->purgeAsNeeded(); diff --git a/chromium/third_party/skia/src/gpu/GrDrawingManager.h b/chromium/third_party/skia/src/gpu/GrDrawingManager.h index fcb5466e18f..77c1dd95ce5 100644 --- a/chromium/third_party/skia/src/gpu/GrDrawingManager.h +++ b/chromium/third_party/skia/src/gpu/GrDrawingManager.h @@ -8,26 +8,30 @@ #ifndef GrDrawingManager_DEFINED #define GrDrawingManager_DEFINED -#include <set> #include "include/core/SkSurface.h" #include "include/private/SkTArray.h" +#include "include/private/SkTHash.h" #include "src/gpu/GrBufferAllocPool.h" #include "src/gpu/GrDeferredUpload.h" +#include "src/gpu/GrHashMapWithCache.h" #include "src/gpu/GrPathRenderer.h" #include "src/gpu/GrPathRendererChain.h" #include "src/gpu/GrResourceCache.h" -#include "src/gpu/text/GrTextContext.h" +#include "src/gpu/GrSurfaceProxy.h" // Enabling this will print out which path renderers are being chosen #define GR_PATH_RENDERER_SPEW 0 class GrCoverageCountingPathRenderer; +class GrGpuBuffer; class GrOnFlushCallbackObject; class GrOpFlushState; class GrOpsTask; class GrRecordingContext; class GrRenderTargetContext; class GrRenderTargetProxy; +class GrRenderTask; +class GrSemaphore; class GrSoftwarePathRenderer; class GrSurfaceContext; class GrSurfaceProxyView; @@ -78,8 +82,6 @@ public: GrRecordingContext* getContext() { return fContext; } - GrTextContext* getTextContext(); - GrPathRenderer* getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args, bool allowSW, GrPathRendererChain::DrawType drawType, @@ -98,11 +100,13 @@ public: GrSemaphoresSubmitted flushSurfaces(GrSurfaceProxy* proxies[], int cnt, SkSurface::BackendSurfaceAccess access, - const GrFlushInfo& info); + const GrFlushInfo& info, + const GrBackendSurfaceMutableState* newState); GrSemaphoresSubmitted flushSurface(GrSurfaceProxy* proxy, SkSurface::BackendSurfaceAccess access, - const GrFlushInfo& info) { - return this->flushSurfaces(&proxy, 1, access, info); + const GrFlushInfo& info, + const GrBackendSurfaceMutableState* newState) { + return this->flushSurfaces(&proxy, 1, access, info, newState); } void addOnFlushCallbackObject(GrOnFlushCallbackObject*); @@ -111,6 +115,10 @@ public: void testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject*); #endif + GrRenderTask* getLastRenderTask(const GrSurfaceProxy*) const; + GrOpsTask* getLastOpsTask(const GrSurfaceProxy*) const; + void setLastRenderTask(const GrSurfaceProxy*, GrRenderTask*); + void moveRenderTasksToDDL(SkDeferredDisplayList* ddl); void copyRenderTasksFromDDL(const SkDeferredDisplayList*, GrRenderTargetProxy* newDest); @@ -130,7 +138,7 @@ private: void closeAll(const GrCaps* caps); // A yucky combination of closeAll and reset - void cleanup(const GrCaps* caps); + void cleanup(GrDrawingManager*, const GrCaps* caps); void gatherIDs(SkSTArray<8, uint32_t, true>* idArray) const; @@ -167,8 +175,8 @@ private: bool fSortRenderTasks; }; - GrDrawingManager(GrRecordingContext*, const GrPathRendererChain::Options&, - const GrTextContext::Options&, + GrDrawingManager(GrRecordingContext*, + const GrPathRendererChain::Options&, bool sortRenderTasks, bool reduceOpsTaskSplitting); @@ -185,11 +193,13 @@ private: bool executeRenderTasks(int startIndex, int stopIndex, GrOpFlushState*, int* numRenderTasksExecuted); + void removeRenderTasks(int startIndex, int stopIndex); + bool flush(GrSurfaceProxy* proxies[], int numProxies, SkSurface::BackendSurfaceAccess access, const GrFlushInfo&, - const GrPrepareForExternalIORequests&); + const GrBackendSurfaceMutableState* newState); bool submitToGpu(bool syncToCpu); @@ -206,7 +216,7 @@ private: GrRecordingContext* fContext; GrPathRendererChain::Options fOptionsForPathRendererChain; - GrTextContext::Options fOptionsForTextContext; + // This cache is used by both the vertex and index pools. It reuses memory across multiple // flushes. sk_sp<GrBufferAllocPool::CpuBufferCache> fCpuBufferCache; @@ -218,8 +228,6 @@ private: // These are the new renderTasks generated by the onFlush CBs SkSTArray<4, sk_sp<GrRenderTask>> fOnFlushRenderTasks; - std::unique_ptr<GrTextContext> fTextContext; - std::unique_ptr<GrPathRendererChain> fPathRendererChain; sk_sp<GrSoftwarePathRenderer> fSoftwarePathRenderer; @@ -229,15 +237,31 @@ private: SkTArray<GrOnFlushCallbackObject*> fOnFlushCBObjects; - void addDDLTarget(GrSurfaceProxy* proxy) { fDDLTargets.insert(proxy); } - bool isDDLTarget(GrSurfaceProxy* proxy) { return fDDLTargets.find(proxy) != fDDLTargets.end(); } - void clearDDLTargets() { fDDLTargets.clear(); } + void addDDLTarget(GrSurfaceProxy* newTarget, GrRenderTargetProxy* ddlTarget) { + fDDLTargets.set(newTarget->uniqueID().asUInt(), ddlTarget); + } + bool isDDLTarget(GrSurfaceProxy* newTarget) { + return SkToBool(fDDLTargets.find(newTarget->uniqueID().asUInt())); + } + GrRenderTargetProxy* getDDLTarget(GrSurfaceProxy* newTarget) { + auto entry = fDDLTargets.find(newTarget->uniqueID().asUInt()); + return entry ? *entry : nullptr; + } + void clearDDLTargets() { fDDLTargets.reset(); } // We play a trick with lazy proxies to retarget the base target of a DDL to the SkSurface - // it is replayed on. Because of this remapping we need to explicitly store the targets of - // DDL replaying. + // it is replayed on. 'fDDLTargets' stores this mapping from SkSurface unique proxy ID + // to the DDL's lazy proxy. // Note: we do not expect a whole lot of these per flush - std::set<GrSurfaceProxy*> fDDLTargets; + SkTHashMap<uint32_t, GrRenderTargetProxy*> fDDLTargets; + + struct SurfaceIDKeyTraits { + static uint32_t GetInvalidKey() { + return GrSurfaceProxy::UniqueID::InvalidID().asUInt(); + } + }; + + GrHashMapWithCache<uint32_t, GrRenderTask*, SurfaceIDKeyTraits, GrCheapHash> fLastRenderTasks; }; #endif diff --git a/chromium/third_party/skia/src/gpu/GrDynamicAtlas.cpp b/chromium/third_party/skia/src/gpu/GrDynamicAtlas.cpp index 00d0947728d..2bc309b7736 100644 --- a/chromium/third_party/skia/src/gpu/GrDynamicAtlas.cpp +++ b/chromium/third_party/skia/src/gpu/GrDynamicAtlas.cpp @@ -7,31 +7,33 @@ #include "src/gpu/GrDynamicAtlas.h" +#include "src/core/SkIPoint16.h" #include "src/gpu/GrOnFlushResourceProvider.h" #include "src/gpu/GrProxyProvider.h" +#include "src/gpu/GrRectanizerPow2.h" #include "src/gpu/GrRectanizerSkyline.h" #include "src/gpu/GrRenderTarget.h" -#include "src/gpu/GrRenderTargetContext.h" +#include "src/gpu/GrRenderTargetContextPriv.h" // Each Node covers a sub-rectangle of the final atlas. When a GrDynamicAtlas runs out of room, we // create a new Node the same size as all combined nodes in the atlas as-is, and then place the new // Node immediately below or beside the others (thereby doubling the size of the GyDynamicAtlas). class GrDynamicAtlas::Node { public: - Node(std::unique_ptr<Node> previous, int l, int t, int r, int b) - : fPrevious(std::move(previous)), fX(l), fY(t), fRectanizer(r - l, b - t) {} + Node(Node* previous, GrRectanizer* rectanizer, int x, int y) + : fPrevious(previous), fRectanizer(rectanizer), fX(x), fY(y) {} - Node* previous() const { return fPrevious.get(); } + Node* previous() const { return fPrevious; } bool addRect(int w, int h, SkIPoint16* loc) { // Pad all paths except those that are expected to take up an entire physical texture. - if (w < fRectanizer.width()) { - w = std::min(w + kPadding, fRectanizer.width()); + if (w < fRectanizer->width()) { + w = std::min(w + kPadding, fRectanizer->width()); } - if (h < fRectanizer.height()) { - h = std::min(h + kPadding, fRectanizer.height()); + if (h < fRectanizer->height()) { + h = std::min(h + kPadding, fRectanizer->height()); } - if (!fRectanizer.addRect(w, h, loc)) { + if (!fRectanizer->addRect(w, h, loc)) { return false; } loc->fX += fX; @@ -40,9 +42,9 @@ public: } private: - const std::unique_ptr<Node> fPrevious; + Node* const fPrevious; + GrRectanizer* const fRectanizer; const int fX, fY; - GrRectanizerSkyline fRectanizer; }; sk_sp<GrTextureProxy> GrDynamicAtlas::MakeLazyAtlasProxy( @@ -66,10 +68,12 @@ sk_sp<GrTextureProxy> GrDynamicAtlas::MakeLazyAtlasProxy( } GrDynamicAtlas::GrDynamicAtlas(GrColorType colorType, InternalMultisample internalMultisample, - SkISize initialSize, int maxAtlasSize, const GrCaps& caps) + SkISize initialSize, int maxAtlasSize, const GrCaps& caps, + RectanizerAlgorithm algorithm) : fColorType(colorType) , fInternalMultisample(internalMultisample) - , fMaxAtlasSize(maxAtlasSize) { + , fMaxAtlasSize(maxAtlasSize) + , fRectanizerAlgorithm(algorithm) { SkASSERT(fMaxAtlasSize <= caps.maxTextureSize()); this->reset(initialSize, caps); } @@ -78,6 +82,7 @@ GrDynamicAtlas::~GrDynamicAtlas() { } void GrDynamicAtlas::reset(SkISize initialSize, const GrCaps& caps) { + fNodeAllocator.reset(); fWidth = std::min(SkNextPow2(initialSize.width()), fMaxAtlasSize); fHeight = std::min(SkNextPow2(initialSize.height()), fMaxAtlasSize); fTopNode = nullptr; @@ -95,18 +100,25 @@ void GrDynamicAtlas::reset(SkISize initialSize, const GrCaps& caps) { fBackingTexture = nullptr; } -bool GrDynamicAtlas::addRect(const SkIRect& devIBounds, SkIVector* offset) { +GrDynamicAtlas::Node* GrDynamicAtlas::makeNode(Node* previous, int l, int t, int r, int b) { + int width = r - l; + int height = b - t; + GrRectanizer* rectanizer = (fRectanizerAlgorithm == RectanizerAlgorithm::kSkyline) + ? (GrRectanizer*)fNodeAllocator.make<GrRectanizerSkyline>(width, height) + : fNodeAllocator.make<GrRectanizerPow2>(width, height); + return fNodeAllocator.make<Node>(previous, rectanizer, l, t); +} + +bool GrDynamicAtlas::addRect(int width, int height, SkIPoint16* location) { // This can't be called anymore once instantiate() has been called. SkASSERT(!this->isInstantiated()); - SkIPoint16 location; - if (!this->internalPlaceRect(devIBounds.width(), devIBounds.height(), &location)) { + if (!this->internalPlaceRect(width, height, location)) { return false; } - offset->set(location.x() - devIBounds.left(), location.y() - devIBounds.top()); - fDrawBounds.fWidth = std::max(fDrawBounds.width(), location.x() + devIBounds.width()); - fDrawBounds.fHeight = std::max(fDrawBounds.height(), location.y() + devIBounds.height()); + fDrawBounds.fWidth = std::max(fDrawBounds.width(), location->x() + width); + fDrawBounds.fHeight = std::max(fDrawBounds.height(), location->y() + height); return true; } @@ -126,10 +138,10 @@ bool GrDynamicAtlas::internalPlaceRect(int w, int h, SkIPoint16* loc) { if (h > fHeight) { fHeight = std::min(SkNextPow2(h), fMaxAtlasSize); } - fTopNode = std::make_unique<Node>(nullptr, 0, 0, fWidth, fHeight); + fTopNode = this->makeNode(nullptr, 0, 0, fWidth, fHeight); } - for (Node* node = fTopNode.get(); node; node = node->previous()) { + for (Node* node = fTopNode; node; node = node->previous()) { if (node->addRect(w, h, loc)) { return true; } @@ -143,11 +155,11 @@ bool GrDynamicAtlas::internalPlaceRect(int w, int h, SkIPoint16* loc) { if (fHeight <= fWidth) { int top = fHeight; fHeight = std::min(fHeight * 2, fMaxAtlasSize); - fTopNode = std::make_unique<Node>(std::move(fTopNode), 0, top, fWidth, fHeight); + fTopNode = this->makeNode(fTopNode, 0, top, fWidth, fHeight); } else { int left = fWidth; fWidth = std::min(fWidth * 2, fMaxAtlasSize); - fTopNode = std::make_unique<Node>(std::move(fTopNode), left, 0, fWidth, fHeight); + fTopNode = this->makeNode(fTopNode, left, 0, fWidth, fHeight); } } while (!fTopNode->addRect(w, h, loc)); @@ -187,7 +199,6 @@ std::unique_ptr<GrRenderTargetContext> GrDynamicAtlas::instantiate( } SkIRect clearRect = SkIRect::MakeSize(fDrawBounds); - rtc->clear(&clearRect, SK_PMColor4fTRANSPARENT, - GrRenderTargetContext::CanClearFullscreen::kYes); + rtc->priv().clearAtLeast(clearRect, SK_PMColor4fTRANSPARENT); return rtc; } diff --git a/chromium/third_party/skia/src/gpu/GrDynamicAtlas.h b/chromium/third_party/skia/src/gpu/GrDynamicAtlas.h index 7a7780cc8c8..e96ffe8f590 100644 --- a/chromium/third_party/skia/src/gpu/GrDynamicAtlas.h +++ b/chromium/third_party/skia/src/gpu/GrDynamicAtlas.h @@ -8,6 +8,7 @@ #ifndef GrDynamicAtlas_DEFINED #define GrDynamicAtlas_DEFINED +#include "src/core/SkArenaAlloc.h" #include "src/gpu/GrTextureProxy.h" class GrOnFlushResourceProvider; @@ -41,20 +42,27 @@ public: const GrCaps&, GrSurfaceProxy::UseAllocator); + enum class RectanizerAlgorithm { + kSkyline, + kPow2 + }; + GrDynamicAtlas(GrColorType colorType, InternalMultisample, SkISize initialSize, - int maxAtlasSize, const GrCaps&); + int maxAtlasSize, const GrCaps&, + RectanizerAlgorithm = RectanizerAlgorithm::kSkyline); virtual ~GrDynamicAtlas(); void reset(SkISize initialSize, const GrCaps& desc); + int maxAtlasSize() const { return fMaxAtlasSize; } GrTextureProxy* textureProxy() const { return fTextureProxy.get(); } bool isInstantiated() const { return fTextureProxy->isInstantiated(); } int currentWidth() const { return fWidth; } int currentHeight() const { return fHeight; } - // Attempts to add a rect to the atlas. If successful, returns the integer offset from - // device-space pixels where the path will be drawn, to atlas pixels where its mask resides. - bool addRect(const SkIRect& devIBounds, SkIVector* atlasOffset); + // Attempts to add a rect to the atlas. Returns true if successful, along with the rect's + // top-left location in the atlas. + bool addRect(int width, int height, SkIPoint16* location); const SkISize& drawBounds() { return fDrawBounds; } // Instantiates our texture proxy for the atlas and returns a pre-cleared GrRenderTargetContext @@ -70,16 +78,20 @@ public: private: class Node; + Node* makeNode(Node* previous, int l, int t, int r, int b); bool internalPlaceRect(int w, int h, SkIPoint16* loc); const GrColorType fColorType; const InternalMultisample fInternalMultisample; const int fMaxAtlasSize; + const RectanizerAlgorithm fRectanizerAlgorithm; int fWidth; int fHeight; - std::unique_ptr<Node> fTopNode; SkISize fDrawBounds; + SkSTArenaAlloc<512> fNodeAllocator; + Node* fTopNode = nullptr; + sk_sp<GrTextureProxy> fTextureProxy; sk_sp<GrTexture> fBackingTexture; }; diff --git a/chromium/third_party/skia/src/gpu/GrFPArgs.h b/chromium/third_party/skia/src/gpu/GrFPArgs.h index 3058f8681de..6b21e32602c 100644 --- a/chromium/third_party/skia/src/gpu/GrFPArgs.h +++ b/chromium/third_party/skia/src/gpu/GrFPArgs.h @@ -28,7 +28,13 @@ struct GrFPArgs { } class WithPreLocalMatrix; - class WithPostLocalMatrix; + + GrFPArgs withNewMatrixProvider(const SkMatrixProvider& provider) const { + GrFPArgs newArgs(fContext, provider, fFilterQuality, fDstColorInfo); + newArgs.fInputColorIsOpaque = fInputColorIsOpaque; + newArgs.fPreLocalMatrix = fPreLocalMatrix; + return newArgs; + } GrRecordingContext* fContext; const SkMatrixProvider& fMatrixProvider; @@ -65,4 +71,3 @@ private: }; #endif - diff --git a/chromium/third_party/skia/src/gpu/GrFixedClip.cpp b/chromium/third_party/skia/src/gpu/GrFixedClip.cpp index 51f2f9d7bda..2f75bc9a4bf 100644 --- a/chromium/third_party/skia/src/gpu/GrFixedClip.cpp +++ b/chromium/third_party/skia/src/gpu/GrFixedClip.cpp @@ -14,47 +14,33 @@ bool GrFixedClip::quickContains(const SkRect& rect) const { if (fWindowRectsState.enabled()) { return false; } + return !fScissorState.enabled() || GrClip::IsInsideClip(fScissorState.rect(), rect); } -SkIRect GrFixedClip::getConservativeBounds(int w, int h) const { - SkIRect devResult = this->GrClip::getConservativeBounds(w, h); - if (fScissorState.enabled()) { - if (!devResult.intersect(fScissorState.rect())) { - devResult.setEmpty(); - } - } - return devResult; +SkIRect GrFixedClip::getConservativeBounds() const { + return fScissorState.rect(); } -bool GrFixedClip::isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA* aa) const { +bool GrFixedClip::isRRect(SkRRect* rr, GrAA* aa) const { if (fWindowRectsState.enabled()) { return false; } - if (fScissorState.enabled()) { - SkRect rect = SkRect::Make(fScissorState.rect()); - if (!rect.intersects(rtBounds)) { - return false; - } - rr->setRect(rect); - *aa = GrAA::kNo; - return true; - } - return false; + // Whether or not the scissor test is enabled, the remaining clip is a rectangle described + // by scissorState.rect() (either the scissor or the rt bounds). + rr->setRect(SkRect::Make(fScissorState.rect())); + *aa = GrAA::kNo; + return true; }; -bool GrFixedClip::apply(int rtWidth, int rtHeight, GrAppliedHardClip* out, SkRect* bounds) const { - if (fScissorState.enabled()) { - SkIRect tightScissor = SkIRect::MakeWH(rtWidth, rtHeight); - if (!tightScissor.intersect(fScissorState.rect())) { - return false; - } - if (IsOutsideClip(tightScissor, *bounds)) { - return false; - } - if (!IsInsideClip(fScissorState.rect(), *bounds)) { - out->addScissor(tightScissor, bounds); - } +bool GrFixedClip::apply(GrAppliedHardClip* out, SkRect* bounds) const { + if (IsOutsideClip(fScissorState.rect(), *bounds)) { + return false; + } + if (!IsInsideClip(fScissorState.rect(), *bounds)) { + SkIRect tightScissor = bounds->roundOut(); + SkAssertResult(tightScissor.intersect(fScissorState.rect())); + out->addScissor(tightScissor, bounds); } if (fWindowRectsState.enabled()) { @@ -63,8 +49,3 @@ bool GrFixedClip::apply(int rtWidth, int rtHeight, GrAppliedHardClip* out, SkRec return true; } - -const GrFixedClip& GrFixedClip::Disabled() { - static const GrFixedClip disabled = GrFixedClip(); - return disabled; -} diff --git a/chromium/third_party/skia/src/gpu/GrFixedClip.h b/chromium/third_party/skia/src/gpu/GrFixedClip.h index 1f175f83bee..5abc3102c2f 100644 --- a/chromium/third_party/skia/src/gpu/GrFixedClip.h +++ b/chromium/third_party/skia/src/gpu/GrFixedClip.h @@ -17,17 +17,21 @@ */ class GrFixedClip final : public GrHardClip { public: - GrFixedClip() = default; - explicit GrFixedClip(const SkIRect& scissorRect) : fScissorState(scissorRect) {} + explicit GrFixedClip(const SkISize& rtDims) : fScissorState(rtDims) {} + GrFixedClip(const SkISize& rtDims, const SkIRect& scissorRect) + : GrFixedClip(rtDims) { + SkAssertResult(fScissorState.set(scissorRect)); + } const GrScissorState& scissorState() const { return fScissorState; } bool scissorEnabled() const { return fScissorState.enabled(); } - const SkIRect& scissorRect() const { SkASSERT(scissorEnabled()); return fScissorState.rect(); } + // Returns the scissor rect or rt bounds if the scissor test is not enabled. + const SkIRect& scissorRect() const { return fScissorState.rect(); } void disableScissor() { fScissorState.setDisabled(); } - void setScissor(const SkIRect& irect) { - fScissorState.set(irect); + bool SK_WARN_UNUSED_RESULT setScissor(const SkIRect& irect) { + return fScissorState.set(irect); } bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& irect) { return fScissorState.intersect(irect); @@ -43,11 +47,9 @@ public: } bool quickContains(const SkRect&) const override; - SkIRect getConservativeBounds(int w, int h) const override; - bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const override; - bool apply(int rtWidth, int rtHeight, GrAppliedHardClip*, SkRect*) const override; - - static const GrFixedClip& Disabled(); + SkIRect getConservativeBounds() const override; + bool isRRect(SkRRect* rr, GrAA*) const override; + bool apply(GrAppliedHardClip*, SkRect*) const override; private: GrScissorState fScissorState; diff --git a/chromium/third_party/skia/src/gpu/GrFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/GrFragmentProcessor.cpp index e4b18c89fcf..9c668d3aed4 100644 --- a/chromium/third_party/skia/src/gpu/GrFragmentProcessor.cpp +++ b/chromium/third_party/skia/src/gpu/GrFragmentProcessor.cpp @@ -13,7 +13,6 @@ #include "src/gpu/effects/generated/GrClampFragmentProcessor.h" #include "src/gpu/effects/generated/GrConstColorProcessor.h" #include "src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h" -#include "src/gpu/effects/generated/GrPremulInputFragmentProcessor.h" #include "src/gpu/glsl/GrGLSLFragmentProcessor.h" #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" #include "src/gpu/glsl/GrGLSLProgramDataManager.h" @@ -74,25 +73,47 @@ void GrFragmentProcessor::addCoordTransform(GrCoordTransform* transform) { fFlags |= kHasCoordTransforms_Flag; } -void GrFragmentProcessor::setSampleMatrix(SkSL::SampleMatrix matrix) { - if (matrix == fMatrix) { +void GrFragmentProcessor::setSampleMatrix(SkSL::SampleMatrix newMatrix) { + if (newMatrix == fMatrix) { return; } + SkASSERT(newMatrix.fKind != SkSL::SampleMatrix::Kind::kNone); SkASSERT(fMatrix.fKind != SkSL::SampleMatrix::Kind::kVariable); + if (this->numCoordTransforms() == 0 && + (newMatrix.fKind == SkSL::SampleMatrix::Kind::kConstantOrUniform || + newMatrix.fKind == SkSL::SampleMatrix::Kind::kMixed)) { + // as things stand, matrices only work when there's a coord transform, so we need to add + // an identity transform to keep the downstream code happy + static GrCoordTransform identity; + this->addCoordTransform(&identity); + } if (fMatrix.fKind == SkSL::SampleMatrix::Kind::kConstantOrUniform) { - SkASSERT(matrix.fKind == SkSL::SampleMatrix::Kind::kVariable || - (matrix.fKind == SkSL::SampleMatrix::Kind::kMixed && - matrix.fExpression == fMatrix.fExpression)); - fMatrix = SkSL::SampleMatrix(SkSL::SampleMatrix::Kind::kMixed, fMatrix.fOwner, - fMatrix.fExpression); + if (newMatrix.fKind == SkSL::SampleMatrix::Kind::kConstantOrUniform) { + // need to base this transform on the one that happened in our parent + // If we're already based on something, then we have to assume that parent is now + // based on yet another transform, so don't update our base pointer (or we'll skip + // the intermediate transform). + if (!fMatrix.fBase) { + fMatrix.fBase = newMatrix.fOwner; + } + } else { + SkASSERT(newMatrix.fKind == SkSL::SampleMatrix::Kind::kVariable); + fMatrix.fKind = SkSL::SampleMatrix::Kind::kMixed; + fMatrix.fBase = nullptr; + } } else { SkASSERT(fMatrix.fKind == SkSL::SampleMatrix::Kind::kNone); - fMatrix = matrix; + fMatrix = newMatrix; } - if (matrix.fKind == SkSL::SampleMatrix::Kind::kVariable) { - for (auto& child : fChildProcessors) { - child->setSampleMatrix(matrix); - } + for (auto& child : fChildProcessors) { + child->setSampleMatrix(newMatrix); + } +} + +void GrFragmentProcessor::setSampledWithExplicitCoords() { + fFlags |= kSampledWithExplicitCoords; + for (auto& child : fChildProcessors) { + child->setSampledWithExplicitCoords(); } } @@ -114,7 +135,26 @@ bool GrFragmentProcessor::isInstantiated() const { } #endif -int GrFragmentProcessor::registerChildProcessor(std::unique_ptr<GrFragmentProcessor> child) { +int GrFragmentProcessor::registerChild(std::unique_ptr<GrFragmentProcessor> child, + SkSL::SampleMatrix sampleMatrix, + bool explicitlySampled) { + // Configure child's sampling state first + if (explicitlySampled) { + child->setSampledWithExplicitCoords(); + } + if (sampleMatrix.fKind != SkSL::SampleMatrix::Kind::kNone) { + // FIXME(michaelludwig) - Temporary hack. Owner tracking will be moved off of SampleMatrix + // and into FP. Currently, coord transform compilation fails on sample_matrix GMs if the + // child isn't the owner. But the matrix effect (and expected behavior) require the owner + // to be 'this' FP. + if (this->classID() == kGrMatrixEffect_ClassID) { + sampleMatrix.fOwner = this; + } else { + sampleMatrix.fOwner = child.get(); + } + child->setSampleMatrix(sampleMatrix); + } + if (child->fFlags & kHasCoordTransforms_Flag) { fFlags |= kHasCoordTransforms_Flag; } @@ -127,6 +167,18 @@ int GrFragmentProcessor::registerChildProcessor(std::unique_ptr<GrFragmentProces return index; } +int GrFragmentProcessor::cloneAndRegisterChildProcessor(const GrFragmentProcessor& fp) { + std::unique_ptr<GrFragmentProcessor> clone = fp.clone(); + return this->registerChild(std::move(clone), fp.sampleMatrix(), + fp.isSampledWithExplicitCoords()); +} + +void GrFragmentProcessor::cloneAndRegisterAllChildProcessors(const GrFragmentProcessor& src) { + for (int i = 0; i < src.numChildProcessors(); ++i) { + this->cloneAndRegisterChildProcessor(src.childProcessor(i)); + } +} + bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const { if (this->numCoordTransforms() != that.numCoordTransforms()) { return false; @@ -156,56 +208,50 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MulInputByChildAlpha( return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp), SkBlendMode::kSrcIn); } -std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::PremulInput( - std::unique_ptr<GrFragmentProcessor> fp) { - if (!fp) { - return nullptr; - } - std::unique_ptr<GrFragmentProcessor> fpPipeline[] = { GrPremulInputFragmentProcessor::Make(), - std::move(fp) }; - return GrFragmentProcessor::RunInSeries(fpPipeline, 2); -} - std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::ClampPremulOutput( std::unique_ptr<GrFragmentProcessor> fp) { if (!fp) { return nullptr; } - std::unique_ptr<GrFragmentProcessor> fpPipeline[] = { - std::move(fp), - GrClampFragmentProcessor::Make(true) - }; - return GrFragmentProcessor::RunInSeries(fpPipeline, 2); + return GrClampFragmentProcessor::Make(std::move(fp), /*clampToPremul=*/true); } std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::SwizzleOutput( std::unique_ptr<GrFragmentProcessor> fp, const GrSwizzle& swizzle) { class SwizzleFragmentProcessor : public GrFragmentProcessor { public: - static std::unique_ptr<GrFragmentProcessor> Make(const GrSwizzle& swizzle) { - return std::unique_ptr<GrFragmentProcessor>(new SwizzleFragmentProcessor(swizzle)); + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp, + const GrSwizzle& swizzle) { + return std::unique_ptr<GrFragmentProcessor>( + new SwizzleFragmentProcessor(std::move(fp), swizzle)); } const char* name() const override { return "Swizzle"; } const GrSwizzle& swizzle() const { return fSwizzle; } - std::unique_ptr<GrFragmentProcessor> clone() const override { return Make(fSwizzle); } + std::unique_ptr<GrFragmentProcessor> clone() const override { + return Make(this->childProcessor(0).clone(), fSwizzle); + } private: - SwizzleFragmentProcessor(const GrSwizzle& swizzle) - : INHERITED(kSwizzleFragmentProcessor_ClassID, kAll_OptimizationFlags) - , fSwizzle(swizzle) {} + SwizzleFragmentProcessor(std::unique_ptr<GrFragmentProcessor> fp, const GrSwizzle& swizzle) + : INHERITED(kSwizzleFragmentProcessor_ClassID, ProcessorOptimizationFlags(fp.get())) + , fSwizzle(swizzle) { + this->registerChild(std::move(fp)); + } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { class GLFP : public GrGLSLFragmentProcessor { public: void emitCode(EmitArgs& args) override { + SkString childColor = this->invokeChild(0, args.fInputColor, args); + const SwizzleFragmentProcessor& sfp = args.fFp.cast<SwizzleFragmentProcessor>(); const GrSwizzle& swizzle = sfp.swizzle(); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; fragBuilder->codeAppendf("%s = %s.%s;", - args.fOutputColor, args.fInputColor, swizzle.asString().c_str()); + args.fOutputColor, childColor.c_str(), swizzle.asString().c_str()); } }; return new GLFP; @@ -235,9 +281,7 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::SwizzleOutput( if (GrSwizzle::RGBA() == swizzle) { return fp; } - std::unique_ptr<GrFragmentProcessor> fpPipeline[] = { std::move(fp), - SwizzleFragmentProcessor::Make(swizzle) }; - return GrFragmentProcessor::RunInSeries(fpPipeline, 2); + return SwizzleFragmentProcessor::Make(std::move(fp), swizzle); } std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulByOutput( @@ -259,7 +303,7 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulB private: PremulFragmentProcessor(std::unique_ptr<GrFragmentProcessor> processor) : INHERITED(kPremulFragmentProcessor_ClassID, OptFlags(processor.get())) { - this->registerChildProcessor(std::move(processor)); + this->registerChild(std::move(processor)); } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { @@ -359,7 +403,7 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::RunInSeries( : INHERITED(kSeriesFragmentProcessor_ClassID, OptFlags(children, cnt)) { SkASSERT(cnt > 1); for (int i = 0; i < cnt; ++i) { - this->registerChildProcessor(std::move(children[i])); + this->registerChild(std::move(children[i])); } } @@ -400,8 +444,8 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::RunInSeries( SkPMColor4f knownColor; int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor); if (leadingFPsToEliminate) { - std::unique_ptr<GrFragmentProcessor> colorFP( - GrConstColorProcessor::Make(knownColor, GrConstColorProcessor::InputMode::kIgnore)); + std::unique_ptr<GrFragmentProcessor> colorFP = GrConstColorProcessor::Make( + /*inputFP=*/nullptr, knownColor, GrConstColorProcessor::InputMode::kIgnore); if (leadingFPsToEliminate == cnt) { return colorFP; } diff --git a/chromium/third_party/skia/src/gpu/GrFragmentProcessor.h b/chromium/third_party/skia/src/gpu/GrFragmentProcessor.h index efc4c9ac78b..a0f540eea0e 100644 --- a/chromium/third_party/skia/src/gpu/GrFragmentProcessor.h +++ b/chromium/third_party/skia/src/gpu/GrFragmentProcessor.h @@ -8,6 +8,8 @@ #ifndef GrFragmentProcessor_DEFINED #define GrFragmentProcessor_DEFINED +#include <tuple> + #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrProcessor.h" #include "src/gpu/ops/GrOp.h" @@ -146,19 +148,10 @@ public: return SkToBool(fFlags & kSampledWithExplicitCoords); } - void setSampledWithExplicitCoords() { - fFlags |= kSampledWithExplicitCoords; - for (auto& child : fChildProcessors) { - child->setSampledWithExplicitCoords(); - } - } - SkSL::SampleMatrix sampleMatrix() const { return fMatrix; } - void setSampleMatrix(SkSL::SampleMatrix matrix); - /** * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color * output under the following scenario: @@ -316,6 +309,13 @@ public: // Sentinel type for range-for using FPItemIter. class FPItemEndIter {}; + // FIXME This should be private, but SkGr needs to mark the dither effect as sampled explicitly + // even though it's not added to another FP. Once varying generation doesn't add a redundant + // varying for it, this can be fully private. + void temporary_SetExplicitlySampled() { + this->setSampledWithExplicitCoords(); + } + protected: enum OptimizationFlags : uint32_t { kNone_OptimizationFlags, @@ -408,8 +408,37 @@ protected: * colors will be combined somehow to produce its output color. Registering these child * processors will allow the ProgramBuilder to automatically handle their transformed coords and * texture accesses and mangle their uniform and output color names. + * + * Depending on the 2nd and 3rd parameters, this corresponds to the following SkSL sample calls: + * - sample(child): Keep default arguments + * - sample(child, matrix): Provide approprate SampleMatrix matching SkSL + * - sample(child, float2): SampleMatrix() and 'true', or use 'registerExplicitlySampledChild' + * - sample(child, matrix)+sample(child, float2): Appropriate SampleMatrix and 'true' */ - int registerChildProcessor(std::unique_ptr<GrFragmentProcessor> child); + int registerChild(std::unique_ptr<GrFragmentProcessor> child, + SkSL::SampleMatrix sampleMatrix = SkSL::SampleMatrix(), + bool explicitlySampled = false); + + /** + * A helper for use when the child is only invoked with sample(float2), and not sample() + * or sample(matrix). + */ + int registerExplicitlySampledChild(std::unique_ptr<GrFragmentProcessor> child) { + return this->registerChild(std::move(child), SkSL::SampleMatrix(), true); + } + + /** + * This method takes an existing fragment processor, clones it, registers it as a child of this + * fragment processor, and returns its child index. It also takes care of any boilerplate in the + * cloning process. + */ + int cloneAndRegisterChildProcessor(const GrFragmentProcessor& fp); + + /** + * This method takes an existing fragment processor, clones all of its children, and registers + * the clones as children of this fragment processor. + */ + void cloneAndRegisterAllChildProcessors(const GrFragmentProcessor& src); void setTextureSamplerCnt(int cnt) { SkASSERT(cnt >= 0); @@ -455,6 +484,10 @@ private: bool hasSameTransforms(const GrFragmentProcessor&) const; + void setSampledWithExplicitCoords(); + + void setSampleMatrix(SkSL::SampleMatrix matrix); + enum PrivateFlags { kFirstPrivateFlag = kAll_OptimizationFlags + 1, kHasCoordTransforms_Flag = kFirstPrivateFlag, @@ -658,4 +691,18 @@ private: Src& fSrc; }; +/** + * Some fragment-processor creation methods have preconditions that might not be satisfied by the + * calling code. Those methods can return a `GrFPResult` from their factory methods. If creation + * succeeds, the new fragment processor is created and `success` is true. If a precondition is not + * met, `success` is set to false and the input FP is returned unchanged. + */ +using GrFPResult = std::tuple<bool /*success*/, std::unique_ptr<GrFragmentProcessor>>; +static inline GrFPResult GrFPFailure(std::unique_ptr<GrFragmentProcessor> fp) { + return {false, std::move(fp)}; +} +static inline GrFPResult GrFPSuccess(std::unique_ptr<GrFragmentProcessor> fp) { + return {true, std::move(fp)}; +} + #endif diff --git a/chromium/third_party/skia/src/gpu/GrGpu.cpp b/chromium/third_party/skia/src/gpu/GrGpu.cpp index 5bc99f00354..195d22e03c0 100644 --- a/chromium/third_party/skia/src/gpu/GrGpu.cpp +++ b/chromium/third_party/skia/src/gpu/GrGpu.cpp @@ -15,6 +15,7 @@ #include "src/core/SkMathPriv.h" #include "src/core/SkMipMap.h" #include "src/gpu/GrAuditTrail.h" +#include "src/gpu/GrBackendUtils.h" #include "src/gpu/GrCaps.h" #include "src/gpu/GrContextPriv.h" #include "src/gpu/GrDataUtils.h" @@ -42,6 +43,7 @@ static const size_t kMinStagingBufferSize = 32 * 1024; GrGpu::GrGpu(GrContext* context) : fResetBits(kAll_GrBackendState), fContext(context) {} GrGpu::~GrGpu() { + this->callSubmittedProcs(false); SkASSERT(fBusyStagingBuffers.isEmpty()); } @@ -261,7 +263,7 @@ sk_sp<GrTexture> GrGpu::createCompressedTexture(SkISize dimensions, } // TODO: expand CompressedDataIsCorrect to work here too - SkImage::CompressionType compressionType = this->caps()->compressionType(format); + SkImage::CompressionType compressionType = GrBackendFormatToCompressionType(format); if (dataSize < SkCompressedDataSize(compressionType, dimensions, nullptr, mipMapped == GrMipMapped::kYes)) { @@ -657,7 +659,7 @@ void GrGpu::executeFlushInfo(GrSurfaceProxy* proxies[], int numProxies, SkSurface::BackendSurfaceAccess access, const GrFlushInfo& info, - const GrPrepareForExternalIORequests& externalRequests) { + const GrBackendSurfaceMutableState* newState) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); GrResourceProvider* resourceProvider = fContext->priv().resourceProvider(); @@ -671,7 +673,11 @@ void GrGpu::executeFlushInfo(GrSurfaceProxy* proxies[], info.fSignalSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillSignal, kBorrow_GrWrapOwnership); - this->insertSemaphore(semaphores[i].get()); + // If we failed to wrap the semaphore it means the client didn't give us a valid + // semaphore to begin with. Therefore, it is fine to not signal it. + if (semaphores[i]) { + this->insertSemaphore(semaphores[i].get()); + } } else { semaphores[i] = resourceProvider->makeSemaphore(false); if (semaphores[i]) { @@ -685,8 +691,17 @@ void GrGpu::executeFlushInfo(GrSurfaceProxy* proxies[], if (info.fFinishedProc) { this->addFinishedProc(info.fFinishedProc, info.fFinishedContext); } - this->prepareSurfacesForBackendAccessAndExternalIO(proxies, numProxies, access, - externalRequests); + + if (info.fSubmittedProc) { + fSubmittedProcs.emplace_back(info.fSubmittedProc, info.fSubmittedContext); + } + + // We currently don't support passing in new surface state for multiple proxies here. The only + // time we have multiple proxies is if we are flushing a yuv SkImage which won't have state + // updates anyways. + SkASSERT(!newState || numProxies == 1); + SkASSERT(!newState || access == SkSurface::BackendSurfaceAccess::kNoAccess); + this->prepareSurfacesForBackendAccessAndStateUpdates(proxies, numProxies, access, newState); } bool GrGpu::submitToGpu(bool syncCpu) { @@ -699,9 +714,26 @@ bool GrGpu::submitToGpu(bool syncCpu) { bool submitted = this->onSubmitToGpu(syncCpu); + this->callSubmittedProcs(submitted); + return submitted; } +bool GrGpu::checkAndResetOOMed() { + if (fOOMed) { + fOOMed = false; + return true; + } + return false; +} + +void GrGpu::callSubmittedProcs(bool success) { + for (int i = 0; i < fSubmittedProcs.count(); ++i) { + fSubmittedProcs[i].fProc(fSubmittedProcs[i].fContext, success); + } + fSubmittedProcs.reset(); +} + #ifdef SK_ENABLE_DUMP_GPU void GrGpu::dumpJSON(SkJSONWriter* writer) const { writer->beginObject(); @@ -870,17 +902,11 @@ GrBackendTexture GrGpu::createBackendTexture(SkISize dimensions, } bool GrGpu::updateBackendTexture(const GrBackendTexture& backendTexture, - GrGpuFinishedProc finishedProc, - GrGpuFinishedContext finishedContext, + sk_sp<GrRefCntedCallback> finishedCallback, const BackendTextureData* data) { SkASSERT(data); const GrCaps* caps = this->caps(); - sk_sp<GrRefCntedCallback> callback; - if (finishedProc) { - callback.reset(new GrRefCntedCallback(finishedProc, finishedContext)); - } - if (!backendTexture.isValid()) { return false; } @@ -901,28 +927,22 @@ bool GrGpu::updateBackendTexture(const GrBackendTexture& backendTexture, return false; } - return this->onUpdateBackendTexture(backendTexture, std::move(callback), data); + return this->onUpdateBackendTexture(backendTexture, std::move(finishedCallback), data); } GrBackendTexture GrGpu::createCompressedBackendTexture(SkISize dimensions, const GrBackendFormat& format, GrMipMapped mipMapped, GrProtected isProtected, - GrGpuFinishedProc finishedProc, - GrGpuFinishedContext finishedContext, + sk_sp<GrRefCntedCallback> finishedCallback, const BackendTextureData* data) { - sk_sp<GrRefCntedCallback> callback; - if (finishedProc) { - callback.reset(new GrRefCntedCallback(finishedProc, finishedContext)); - } - const GrCaps* caps = this->caps(); if (!format.isValid()) { return {}; } - SkImage::CompressionType compressionType = caps->compressionType(format); + SkImage::CompressionType compressionType = GrBackendFormatToCompressionType(format); if (compressionType == SkImage::CompressionType::kNone) { // Uncompressed formats must go through the createBackendTexture API return {}; @@ -943,7 +963,7 @@ GrBackendTexture GrGpu::createCompressedBackendTexture(SkISize dimensions, } return this->onCreateCompressedBackendTexture(dimensions, format, mipMapped, - isProtected, std::move(callback), data); + isProtected, std::move(finishedCallback), data); } GrStagingBuffer* GrGpu::findStagingBuffer(size_t size) { diff --git a/chromium/third_party/skia/src/gpu/GrGpu.h b/chromium/third_party/skia/src/gpu/GrGpu.h index 58723df5a05..d93c47fcfc4 100644 --- a/chromium/third_party/skia/src/gpu/GrGpu.h +++ b/chromium/third_party/skia/src/gpu/GrGpu.h @@ -350,8 +350,14 @@ public: // Returns a GrOpsRenderPass which GrOpsTasks send draw commands to instead of directly // to the Gpu object. The 'bounds' rect is the content rect of the renderTarget. + // If a 'stencil' is provided it will be the one bound to 'renderTarget'. If one is not + // provided but 'renderTarget' has a stencil buffer then that is a signal that the + // render target's stencil buffer should be ignored. virtual GrOpsRenderPass* getOpsRenderPass( - GrRenderTarget* renderTarget, GrSurfaceOrigin, const SkIRect& bounds, + GrRenderTarget* renderTarget, + GrStencilAttachment* stencil, + GrSurfaceOrigin, + const SkIRect& bounds, const GrOpsRenderPass::LoadAndStoreInfo&, const GrOpsRenderPass::StencilLoadAndStoreInfo&, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) = 0; @@ -361,8 +367,9 @@ public: // insert any numSemaphore semaphores on the gpu and set the backendSemaphores to match the // inserted semaphores. void executeFlushInfo(GrSurfaceProxy*[], int numProxies, - SkSurface::BackendSurfaceAccess access, const GrFlushInfo&, - const GrPrepareForExternalIORequests&); + SkSurface::BackendSurfaceAccess access, + const GrFlushInfo&, + const GrBackendSurfaceMutableState* newState); bool submitToGpu(bool syncCpu); @@ -382,6 +389,12 @@ public: virtual void checkFinishProcs() = 0; /** + * Checks if we detected an OOM from the underlying 3D API and if so returns true and resets + * the internal OOM state to false. Otherwise, returns false. + */ + bool checkAndResetOOMed(); + + /** * Put this texture in a safe and known state for use across multiple GrContexts. Depending on * the backend, this may return a GrSemaphore. If so, other contexts should wait on that * semaphore before using this texture. @@ -600,8 +613,7 @@ public: GrProtected); bool updateBackendTexture(const GrBackendTexture&, - GrGpuFinishedProc finishedProc, - GrGpuFinishedContext finishedContext, + sk_sp<GrRefCntedCallback> finishedCallback, const BackendTextureData*); /** @@ -612,10 +624,21 @@ public: const GrBackendFormat&, GrMipMapped, GrProtected, - GrGpuFinishedProc finishedProc, - GrGpuFinishedContext finishedContext, + sk_sp<GrRefCntedCallback> finishedCallback, const BackendTextureData*); + virtual bool setBackendTextureState(const GrBackendTexture&, + const GrBackendSurfaceMutableState&, + sk_sp<GrRefCntedCallback> finishedCallback) { + return false; + } + + virtual bool setBackendRenderTargetState(const GrBackendRenderTarget&, + const GrBackendSurfaceMutableState&, + sk_sp<GrRefCntedCallback> finishedCallback) { + return false; + } + /** * Frees a texture created by createBackendTexture(). If ownership of the backend * texture has been transferred to a GrContext using adopt semantics this should not be called. @@ -704,6 +727,8 @@ protected: void didWriteToSurface(GrSurface* surface, GrSurfaceOrigin origin, const SkIRect* bounds, uint32_t mipLevels = 1) const; + void setOOMed() { fOOMed = true; } + typedef SkTInternalLList<GrStagingBuffer> StagingBufferList; const StagingBufferList& availableStagingBuffers() { return fAvailableStagingBuffers; } const StagingBufferList& activeStagingBuffers() { return fActiveStagingBuffers; } @@ -815,9 +840,11 @@ private: virtual void addFinishedProc(GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) = 0; - virtual void prepareSurfacesForBackendAccessAndExternalIO( - GrSurfaceProxy* proxies[], int numProxies, SkSurface::BackendSurfaceAccess access, - const GrPrepareForExternalIORequests& externalRequests) {} + virtual void prepareSurfacesForBackendAccessAndStateUpdates( + GrSurfaceProxy* proxies[], + int numProxies, + SkSurface::BackendSurfaceAccess access, + const GrBackendSurfaceMutableState* newState) {} virtual bool onSubmitToGpu(bool syncCpu) = 0; @@ -843,6 +870,8 @@ private: void validateStagingBuffers() const; #endif + void callSubmittedProcs(bool success); + uint32_t fResetBits; // The context owns us, not vice-versa, so this ptr is not ref'ed by Gpu. GrContext* fContext; @@ -854,6 +883,17 @@ private: StagingBufferList fActiveStagingBuffers; StagingBufferList fBusyStagingBuffers; + struct SubmittedProc { + SubmittedProc(GrGpuSubmittedProc proc, GrGpuSubmittedContext context) + : fProc(proc), fContext(context) {} + + GrGpuSubmittedProc fProc; + GrGpuSubmittedContext fContext; + }; + SkSTArray<4, SubmittedProc> fSubmittedProcs; + + bool fOOMed = false; + friend class GrPathRendering; typedef SkRefCnt INHERITED; }; diff --git a/chromium/third_party/skia/src/gpu/GrHashMapWithCache.h b/chromium/third_party/skia/src/gpu/GrHashMapWithCache.h new file mode 100644 index 00000000000..8a24ecc525c --- /dev/null +++ b/chromium/third_party/skia/src/gpu/GrHashMapWithCache.h @@ -0,0 +1,84 @@ +/* + * Copyright 2020 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrHashMapWithCache_DEFINED +#define GrHashMapWithCache_DEFINED + +#include "include/private/SkChecksum.h" +#include "include/private/SkNoncopyable.h" +#include "include/private/SkTHash.h" + +// Cheaper than SkGoodHash and good enough for UniqueID tables. +struct GrCheapHash { + uint32_t operator()(uint32_t val) { + return SkChecksum::CheapMix(val); + } +}; + +/** A hash map that caches the most recently accessed entry. + The API is a subset of SkHashMap, and you must provide a + sentinel key that will never be present, such as SK_InvalidUniqueID. + + KeyTraits must have: + - static K GetInvalidKey() +*/ +template <typename K, typename V, typename KeyTraits, typename HashT = SkGoodHash> +class GrHashMapWithCache : public SkNoncopyable { +public: + // How many key/value pairs are in the table? + int count() const { return fMap.count(); } + + // Approximately how many bytes of memory do we use beyond sizeof(*this)? + size_t approxBytesUsed() const { return fMap.approxBytesUsed(); } + + // N.B. The pointers returned by set() and find() are valid only until the next call to set(). + + // If there is key/value entry in the table with this key, return a pointer to the value. + // If not, return null. + const V* find(const K& key) const { + if (key != fLastKey) { + fLastKey = key; + fLastValue = fMap.find(key); + } + return fLastValue; + } + + // Set key to val in the map, replacing any previous value with the same key. + // We copy both key and val, and return a pointer to the value copy now in the map. + const V* set(K key, V val) { + if (fLastValue && key == fLastKey) { + *fLastValue = std::move(val); + } else { + fLastKey = key; + fLastValue = fMap.set(std::move(key), std::move(val)); + } + return fLastValue; + } + + // Remove the key/value entry in the table with this key. + void remove(K key) { + // Match SkTHashMap requirement. The caller can find() if they're unsure. + SkASSERT(fMap.find(fLastKey)); + fLastKey = std::move(key); + fLastValue = nullptr; + fMap.remove(fLastKey); + } + + // Clear the map. + void reset() { + fLastKey = KeyTraits::GetInvalidKey(); + fLastValue = nullptr; + fMap.reset(); + } + +private: + SkTHashMap<K, V, HashT> fMap; + mutable K fLastKey = KeyTraits::GetInvalidKey(); + mutable V* fLastValue = nullptr; +}; + +#endif diff --git a/chromium/third_party/skia/src/gpu/GrImageContext.cpp b/chromium/third_party/skia/src/gpu/GrImageContext.cpp index 3f22c1e3ce7..8993a3831bd 100644 --- a/chromium/third_party/skia/src/gpu/GrImageContext.cpp +++ b/chromium/third_party/skia/src/gpu/GrImageContext.cpp @@ -8,33 +8,25 @@ #include "include/private/GrImageContext.h" #include "src/gpu/GrCaps.h" +#include "src/gpu/GrContextThreadSafeProxyPriv.h" #include "src/gpu/GrImageContextPriv.h" #include "src/gpu/GrProxyProvider.h" #include "src/gpu/effects/GrSkSLFP.h" -#define ASSERT_SINGLE_OWNER \ - SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());) - /////////////////////////////////////////////////////////////////////////////////////////////////// -GrImageContext::GrImageContext(GrBackendApi backend, - const GrContextOptions& options, - uint32_t contextID) - : INHERITED(backend, options, contextID) { +GrImageContext::GrImageContext(sk_sp<GrContextThreadSafeProxy> proxy) + : INHERITED(std::move(proxy)) { fProxyProvider.reset(new GrProxyProvider(this)); } GrImageContext::~GrImageContext() {} void GrImageContext::abandonContext() { - ASSERT_SINGLE_OWNER - - fAbandoned = true; + fThreadSafeProxy->priv().abandonContext(); } bool GrImageContext::abandoned() { - ASSERT_SINGLE_OWNER - - return fAbandoned; + return fThreadSafeProxy->priv().abandoned(); } /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/chromium/third_party/skia/src/gpu/GrLegacyDirectContext.cpp b/chromium/third_party/skia/src/gpu/GrLegacyDirectContext.cpp index f7cae12c15a..4b027eaf3fe 100644 --- a/chromium/third_party/skia/src/gpu/GrLegacyDirectContext.cpp +++ b/chromium/third_party/skia/src/gpu/GrLegacyDirectContext.cpp @@ -31,6 +31,13 @@ #include "src/gpu/dawn/GrDawnGpu.h" #endif +#if GR_TEST_UTILS +# include "include/utils/SkRandom.h" +# if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS) +# include <sanitizer/lsan_interface.h> +# endif +#endif + #ifdef SK_DISABLE_REDUCE_OPLIST_SPLITTING static const bool kDefaultReduceOpsTaskSplitting = false; #else @@ -40,7 +47,7 @@ static const bool kDefaultReduceOpsTaskSplitting = false; class GrLegacyDirectContext : public GrContext { public: GrLegacyDirectContext(GrBackendApi backend, const GrContextOptions& options) - : INHERITED(backend, options) + : INHERITED(GrContextThreadSafeProxyPriv::Make(backend, options)) , fAtlasManager(nullptr) { } @@ -48,7 +55,7 @@ public: // this if-test protects against the case where the context is being destroyed // before having been fully created if (this->priv().getGpu()) { - this->flush(); + this->flushAndSubmit(); } delete fAtlasManager; @@ -65,23 +72,21 @@ public: } void freeGpuResources() override { - this->flush(); + this->flushAndSubmit(); fAtlasManager->freeAll(); INHERITED::freeGpuResources(); } protected: - bool init(sk_sp<const GrCaps> caps) override { - SkASSERT(caps); - SkASSERT(!fThreadSafeProxy); - - fThreadSafeProxy = GrContextThreadSafeProxyPriv::Make(this->backend(), - this->options(), - this->contextID(), - caps); + bool init() override { + const GrGpu* gpu = this->priv().getGpu(); + if (!gpu) { + return false; + } - if (!INHERITED::init(std::move(caps))) { + fThreadSafeProxy->priv().init(gpu->refCaps()); + if (!INHERITED::init()) { return false; } @@ -94,8 +99,6 @@ protected: this->setupDrawingManager(true, reduceOpsTaskSplitting); - SkASSERT(this->caps()); - GrDrawOpAtlas::AllowMultitexturing allowMultitexturing; if (GrContextOptions::Enable::kNo == this->options().fAllowMultipleGlyphCacheTextures || // multitexturing supported only if range can represent the index + texcoords fully @@ -139,16 +142,52 @@ sk_sp<GrContext> GrContext::MakeGL() { return MakeGL(nullptr, defaultOptions); } +#if GR_TEST_UTILS +GrGLFunction<GrGLGetErrorFn> make_get_error_with_random_oom(GrGLFunction<GrGLGetErrorFn> original) { + // A SkRandom and a GrGLFunction<GrGLGetErrorFn> are too big to be captured by a + // GrGLFunction<GrGLGetError> (surprise, surprise). So we make a context object and + // capture that by pointer. However, GrGLFunction doesn't support calling a destructor + // on the thing it captures. So we leak the context. + struct GetErrorContext { + SkRandom fRandom; + GrGLFunction<GrGLGetErrorFn> fGetError; + }; + + auto errorContext = new GetErrorContext; + +#if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS) + __lsan_ignore_object(errorContext); +#endif + + errorContext->fGetError = original; + + return GrGLFunction<GrGLGetErrorFn>([errorContext]() { + GrGLenum error = errorContext->fGetError(); + if (error == GR_GL_NO_ERROR && (errorContext->fRandom.nextU() % 300) == 0) { + error = GR_GL_OUT_OF_MEMORY; + } + return error; + }); +} +#endif + sk_sp<GrContext> GrContext::MakeGL(sk_sp<const GrGLInterface> glInterface, const GrContextOptions& options) { sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kOpenGL, options)); - - context->fGpu = GrGLGpu::Make(std::move(glInterface), options, context.get()); - if (!context->fGpu) { - return nullptr; +#if GR_TEST_UTILS + if (options.fRandomGLOOM) { + auto copy = sk_make_sp<GrGLInterface>(*glInterface); + copy->fFunctions.fGetError = + make_get_error_with_random_oom(glInterface->fFunctions.fGetError); +#if GR_GL_CHECK_ERROR + // Suppress logging GL errors since we'll be synthetically generating them. + copy->suppressErrorLogging(); +#endif + glInterface = std::move(copy); } - - if (!context->init(context->fGpu->refCaps())) { +#endif + context->fGpu = GrGLGpu::Make(std::move(glInterface), options, context.get()); + if (!context->init()) { return nullptr; } return context; @@ -165,11 +204,7 @@ sk_sp<GrContext> GrContext::MakeMock(const GrMockOptions* mockOptions, sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kMock, options)); context->fGpu = GrMockGpu::Make(mockOptions, options, context.get()); - if (!context->fGpu) { - return nullptr; - } - - if (!context->init(context->fGpu->refCaps())) { + if (!context->init()) { return nullptr; } @@ -191,13 +226,10 @@ sk_sp<GrContext> GrContext::MakeVulkan(const GrVkBackendContext& backendContext, sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kVulkan, options)); context->fGpu = GrVkGpu::Make(backendContext, options, context.get()); - if (!context->fGpu) { + if (!context->init()) { return nullptr; } - if (!context->init(context->fGpu->refCaps())) { - return nullptr; - } return context; #else return nullptr; @@ -214,13 +246,10 @@ sk_sp<GrContext> GrContext::MakeMetal(void* device, void* queue, const GrContext sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kMetal, options)); context->fGpu = GrMtlTrampoline::MakeGpu(context.get(), options, device, queue); - if (!context->fGpu) { + if (!context->init()) { return nullptr; } - if (!context->init(context->fGpu->refCaps())) { - return nullptr; - } return context; } #endif @@ -236,13 +265,10 @@ sk_sp<GrContext> GrContext::MakeDirect3D(const GrD3DBackendContext& backendConte sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kDirect3D, options)); context->fGpu = GrD3DGpu::Make(backendContext, options, context.get()); - if (!context->fGpu) { + if (!context->init()) { return nullptr; } - if (!context->init(context->fGpu->refCaps())) { - return nullptr; - } return context; } #endif @@ -257,13 +283,10 @@ sk_sp<GrContext> GrContext::MakeDawn(const wgpu::Device& device, const GrContext sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kDawn, options)); context->fGpu = GrDawnGpu::Make(device, options, context.get()); - if (!context->fGpu) { + if (!context->init()) { return nullptr; } - if (!context->init(context->fGpu->refCaps())) { - return nullptr; - } return context; } #endif diff --git a/chromium/third_party/skia/src/gpu/GrOnFlushResourceProvider.cpp b/chromium/third_party/skia/src/gpu/GrOnFlushResourceProvider.cpp index 0ca9f13ef47..93bf9dbe0df 100644 --- a/chromium/third_party/skia/src/gpu/GrOnFlushResourceProvider.cpp +++ b/chromium/third_party/skia/src/gpu/GrOnFlushResourceProvider.cpp @@ -52,12 +52,12 @@ void GrOnFlushResourceProvider::addTextureResolveTask(sk_sp<GrTextureProxy> text // Since we are bypassing normal DAG operation, we need to ensure the textureProxy's last render // task gets closed before making a texture resolve task. makeClosed is what will mark msaa and // mipmaps dirty. - if (GrRenderTask* renderTask = textureProxy->getLastRenderTask()) { + if (GrRenderTask* renderTask = fDrawingMgr->getLastRenderTask(textureProxy.get())) { renderTask->makeClosed(*this->caps()); } auto task = static_cast<GrTextureResolveRenderTask*>(fDrawingMgr->fOnFlushRenderTasks.push_back( sk_make_sp<GrTextureResolveRenderTask>()).get()); - task->addProxy(std::move(textureProxy), resolveFlags, *this->caps()); + task->addProxy(fDrawingMgr, std::move(textureProxy), resolveFlags, *this->caps()); task->makeClosed(*this->caps()); } diff --git a/chromium/third_party/skia/src/gpu/GrOpFlushState.cpp b/chromium/third_party/skia/src/gpu/GrOpFlushState.cpp index dfaa9d6e73c..8bc88f0d091 100644 --- a/chromium/third_party/skia/src/gpu/GrOpFlushState.cpp +++ b/chromium/third_party/skia/src/gpu/GrOpFlushState.cpp @@ -194,7 +194,7 @@ void GrOpFlushState::putBackVertices(int vertices, size_t vertexStride) { } GrAppliedClip GrOpFlushState::detachAppliedClip() { - return fOpArgs->appliedClip() ? std::move(*fOpArgs->appliedClip()) : GrAppliedClip(); + return fOpArgs->appliedClip() ? std::move(*fOpArgs->appliedClip()) : GrAppliedClip::Disabled(); } GrStrikeCache* GrOpFlushState::strikeCache() const { diff --git a/chromium/third_party/skia/src/gpu/GrOpsRenderPass.cpp b/chromium/third_party/skia/src/gpu/GrOpsRenderPass.cpp index 66e346b82fe..07b4eeebe3a 100644 --- a/chromium/third_party/skia/src/gpu/GrOpsRenderPass.cpp +++ b/chromium/third_party/skia/src/gpu/GrOpsRenderPass.cpp @@ -11,12 +11,13 @@ #include "include/gpu/GrContext.h" #include "src/gpu/GrCaps.h" #include "src/gpu/GrContextPriv.h" -#include "src/gpu/GrFixedClip.h" +#include "src/gpu/GrCpuBuffer.h" #include "src/gpu/GrGpu.h" #include "src/gpu/GrPrimitiveProcessor.h" #include "src/gpu/GrProgramInfo.h" #include "src/gpu/GrRenderTarget.h" #include "src/gpu/GrRenderTargetPriv.h" +#include "src/gpu/GrScissorState.h" #include "src/gpu/GrSimpleMesh.h" #include "src/gpu/GrTexturePriv.h" @@ -37,21 +38,22 @@ void GrOpsRenderPass::end() { this->resetActiveBuffers(); } -void GrOpsRenderPass::clear(const GrFixedClip& clip, const SkPMColor4f& color) { +void GrOpsRenderPass::clear(const GrScissorState& scissor, const SkPMColor4f& color) { SkASSERT(fRenderTarget); // A clear at this level will always be a true clear, so make sure clears were not supposed to // be redirected to draws instead SkASSERT(!this->gpu()->caps()->performColorClearsAsDraws()); - SkASSERT(!clip.scissorEnabled() || !this->gpu()->caps()->performPartialClearsAsDraws()); + SkASSERT(!scissor.enabled() || !this->gpu()->caps()->performPartialClearsAsDraws()); fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured; - this->onClear(clip, color); + this->onClear(scissor, color); } -void GrOpsRenderPass::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) { +void GrOpsRenderPass::clearStencilClip(const GrScissorState& scissor, bool insideStencilMask) { // As above, make sure the stencil clear wasn't supposed to be a draw rect with stencil settings SkASSERT(!this->gpu()->caps()->performStencilClearsAsDraws()); + SkASSERT(!scissor.enabled() || !this->gpu()->caps()->performPartialClearsAsDraws()); fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured; - this->onClearStencilClip(clip, insideStencilMask); + this->onClearStencilClip(scissor, insideStencilMask); } void GrOpsRenderPass::executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable) { diff --git a/chromium/third_party/skia/src/gpu/GrOpsRenderPass.h b/chromium/third_party/skia/src/gpu/GrOpsRenderPass.h index 959d1a222f6..ec7960f366c 100644 --- a/chromium/third_party/skia/src/gpu/GrOpsRenderPass.h +++ b/chromium/third_party/skia/src/gpu/GrOpsRenderPass.h @@ -13,12 +13,12 @@ #include "src/gpu/ops/GrDrawOp.h" class GrOpFlushState; -class GrFixedClip; class GrGpu; class GrPipeline; class GrPrimitiveProcessor; class GrProgramInfo; class GrRenderTarget; +class GrScissorState; class GrSemaphore; struct SkIRect; struct SkRect; @@ -120,11 +120,17 @@ public: virtual void inlineUpload(GrOpFlushState*, GrDeferredTextureUploadFn&) = 0; /** - * Clear the owned render target. Ignores the draw state and clip. + * Clear the owned render target. Clears the full target if 'scissor' is disabled, otherwise it + * is restricted to 'scissor'. Must check caps.performPartialClearsAsDraws() before using an + * enabled scissor test; must check caps.performColorClearsAsDraws() before using this at all. */ - void clear(const GrFixedClip&, const SkPMColor4f&); + void clear(const GrScissorState& scissor, const SkPMColor4f&); - void clearStencilClip(const GrFixedClip&, bool insideStencilMask); + /** + * Same as clear() but modifies the stencil; check caps.performStencilClearsAsDraws() and + * caps.performPartialClearsAsDraws(). + */ + void clearStencilClip(const GrScissorState& scissor, bool insideStencilMask); /** * Executes the SkDrawable object for the underlying backend. @@ -189,8 +195,8 @@ private: virtual void onDrawIndexedIndirect(const GrBuffer*, size_t offset, int drawCount) { SK_ABORT("Not implemented."); // Only called if caps.nativeDrawIndirectSupport(). } - virtual void onClear(const GrFixedClip&, const SkPMColor4f&) = 0; - virtual void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) = 0; + virtual void onClear(const GrScissorState&, const SkPMColor4f&) = 0; + virtual void onClearStencilClip(const GrScissorState&, bool insideStencilMask) = 0; virtual void onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) {} enum class DrawPipelineStatus { diff --git a/chromium/third_party/skia/src/gpu/GrOpsTask.cpp b/chromium/third_party/skia/src/gpu/GrOpsTask.cpp index c811883d774..1f0a55f747d 100644 --- a/chromium/third_party/skia/src/gpu/GrOpsTask.cpp +++ b/chromium/third_party/skia/src/gpu/GrOpsTask.cpp @@ -357,14 +357,14 @@ inline void GrOpsTask::OpChain::validate() const { //////////////////////////////////////////////////////////////////////////////// -GrOpsTask::GrOpsTask(GrRecordingContext::Arenas arenas, +GrOpsTask::GrOpsTask(GrDrawingManager* drawingMgr, GrRecordingContext::Arenas arenas, GrSurfaceProxyView view, GrAuditTrail* auditTrail) - : GrRenderTask(std::move(view)) + : GrRenderTask() , fArenas(arenas) , fAuditTrail(auditTrail) SkDEBUGCODE(, fNumClips(0)) { - fTargetView.proxy()->setLastRenderTask(this); + this->addTarget(drawingMgr, std::move(view)); } void GrOpsTask::deleteOps() { @@ -388,20 +388,16 @@ void GrOpsTask::removeClosedObserver(GrOpsTaskClosedObserver* observer) { } } -void GrOpsTask::endFlush() { +void GrOpsTask::endFlush(GrDrawingManager* drawingMgr) { fLastClipStackGenID = SK_InvalidUniqueID; this->deleteOps(); fClipAllocator.reset(); - GrSurfaceProxy* proxy = fTargetView.proxy(); - if (proxy && this == proxy->getLastRenderTask()) { - proxy->setLastRenderTask(nullptr); - } - - fTargetView.reset(); fDeferredProxies.reset(); fSampledProxies.reset(); fAuditTrail = nullptr; + + GrRenderTask::endFlush(drawingMgr); } void GrOpsTask::onPrePrepare(GrRecordingContext* context) { @@ -420,7 +416,7 @@ void GrOpsTask::onPrePrepare(GrRecordingContext* context) { for (const auto& chain : fOpChains) { if (chain.shouldExecute()) { chain.head()->prePrepare(context, - &fTargetView, + &fTargets[0], chain.appliedClip(), chain.dstProxyView()); } @@ -428,7 +424,7 @@ void GrOpsTask::onPrePrepare(GrRecordingContext* context) { } void GrOpsTask::onPrepare(GrOpFlushState* flushState) { - SkASSERT(fTargetView.proxy()->peekRenderTarget()); + SkASSERT(this->target(0).proxy()->peekRenderTarget()); SkASSERT(this->isClosed()); #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK TRACE_EVENT0("skia.gpu", TRACE_FUNC); @@ -449,7 +445,7 @@ void GrOpsTask::onPrepare(GrOpFlushState* flushState) { TRACE_EVENT0("skia.gpu", chain.head()->name()); #endif GrOpFlushState::OpArgs opArgs(chain.head(), - &fTargetView, + &fTargets[0], chain.appliedClip(), chain.dstProxyView()); @@ -457,7 +453,7 @@ void GrOpsTask::onPrepare(GrOpFlushState* flushState) { // Temporary debugging helper: for debugging prePrepare w/o going through DDLs // Delete once most of the GrOps have an onPrePrepare. - // chain.head()->prePrepare(flushState->gpu()->getContext(), &fTargetView, + // chain.head()->prePrepare(flushState->gpu()->getContext(), &this->target(0), // chain.appliedClip()); // GrOp::prePrepare may or may not have been called at this point @@ -469,9 +465,10 @@ void GrOpsTask::onPrepare(GrOpFlushState* flushState) { } static GrOpsRenderPass* create_render_pass( - GrGpu* gpu, GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds, - GrLoadOp colorLoadOp, const SkPMColor4f& loadClearColor, GrLoadOp stencilLoadOp, - GrStoreOp stencilStoreOp, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) { + GrGpu* gpu, GrRenderTarget* rt, GrStencilAttachment* stencil, GrSurfaceOrigin origin, + const SkIRect& bounds, GrLoadOp colorLoadOp, const SkPMColor4f& loadClearColor, + GrLoadOp stencilLoadOp, GrStoreOp stencilStoreOp, + const SkTArray<GrSurfaceProxy*, true>& sampledProxies) { const GrOpsRenderPass::LoadAndStoreInfo kColorLoadStoreInfo { colorLoadOp, GrStoreOp::kStore, @@ -488,8 +485,8 @@ static GrOpsRenderPass* create_render_pass( stencilStoreOp, }; - return gpu->getOpsRenderPass(rt, origin, bounds, kColorLoadStoreInfo, stencilLoadAndStoreInfo, - sampledProxies); + return gpu->getOpsRenderPass(rt, stencil, origin, bounds, + kColorLoadStoreInfo, stencilLoadAndStoreInfo, sampledProxies); } // TODO: this is where GrOp::renderTarget is used (which is fine since it @@ -504,8 +501,8 @@ bool GrOpsTask::onExecute(GrOpFlushState* flushState) { return false; } - SkASSERT(fTargetView.proxy()); - GrRenderTargetProxy* proxy = fTargetView.proxy()->asRenderTargetProxy(); + SkASSERT(this->numTargets() == 1); + GrRenderTargetProxy* proxy = this->target(0).proxy()->asRenderTargetProxy(); SkASSERT(proxy); TRACE_EVENT0("skia.gpu", TRACE_FUNC); @@ -553,6 +550,7 @@ bool GrOpsTask::onExecute(GrOpFlushState* flushState) { // once finished, meaning the stencil values will always remain cleared after the // initial clear. Just fall through to reloading the existing (cleared) stencil values // from memory. + [[fallthrough]]; case StencilContent::kPreserved: SkASSERT(stencil); stencilLoadOp = GrLoadOp::kLoad; @@ -571,7 +569,7 @@ bool GrOpsTask::onExecute(GrOpFlushState* flushState) { : GrStoreOp::kStore; GrOpsRenderPass* renderPass = create_render_pass( - flushState->gpu(), proxy->peekRenderTarget(), fTargetView.origin(), + flushState->gpu(), proxy->peekRenderTarget(), stencil, this->target(0).origin(), fClippedContentBounds, fColorLoadOp, fLoadClearColor, stencilLoadOp, stencilStoreOp, fSampledProxies); if (!renderPass) { @@ -590,7 +588,7 @@ bool GrOpsTask::onExecute(GrOpFlushState* flushState) { #endif GrOpFlushState::OpArgs opArgs(chain.head(), - &fTargetView, + &fTargets[0], chain.appliedClip(), chain.dstProxyView()); @@ -610,9 +608,9 @@ void GrOpsTask::setColorLoadOp(GrLoadOp op, const SkPMColor4f& color) { fColorLoadOp = op; fLoadClearColor = color; if (GrLoadOp::kClear == fColorLoadOp) { - GrSurfaceProxy* proxy = fTargetView.proxy(); + GrSurfaceProxy* proxy = this->target(0).proxy(); SkASSERT(proxy); - fTotalBounds = proxy->getBoundsRect(); + fTotalBounds = proxy->backingStoreBoundsRect(); } } @@ -631,7 +629,7 @@ bool GrOpsTask::resetForFullscreenClear(CanDiscardPreviousOps canDiscardPrevious // If the opsTask is using a render target which wraps a vulkan command buffer, we can't do // a clear load since we cannot change the render pass that we are using. Thus we fall back // to making a clear op in this case. - return !fTargetView.asRenderTargetProxy()->wrapsVkSecondaryCB(); + return !this->target(0).asRenderTargetProxy()->wrapsVkSecondaryCB(); } // Could not empty the task, so an op must be added to handle the clear @@ -757,7 +755,7 @@ void GrOpsTask::gatherProxyIntervals(GrResourceAllocator* alloc) const { alloc->addInterval(fDeferredProxies[i], 0, 0, GrResourceAllocator::ActualUse::kNo); } - GrSurfaceProxy* targetProxy = fTargetView.proxy(); + GrSurfaceProxy* targetProxy = this->target(0).proxy(); // Add the interval for all the writes to this GrOpsTasks's target if (fOpChains.count()) { @@ -776,7 +774,7 @@ void GrOpsTask::gatherProxyIntervals(GrResourceAllocator* alloc) const { auto gather = [ alloc SkDEBUGCODE(, this) ] (GrSurfaceProxy* p, GrMipMapped) { alloc->addInterval(p, alloc->curOp(), alloc->curOp(), GrResourceAllocator::ActualUse::kYes - SkDEBUGCODE(, fTargetView.proxy() == p)); + SkDEBUGCODE(, this->target(0).proxy() == p)); }; for (const OpChain& recordedOp : fOpChains) { recordedOp.visitProxies(gather); @@ -792,7 +790,7 @@ void GrOpsTask::recordOp( const DstProxyView* dstProxyView, const GrCaps& caps) { SkDEBUGCODE(op->validate();) SkASSERT(processorAnalysis.requiresDstTexture() == (dstProxyView && dstProxyView->proxy())); - GrSurfaceProxy* proxy = fTargetView.proxy(); + GrSurfaceProxy* proxy = this->target(0).proxy(); SkASSERT(proxy); // A closed GrOpsTask should never receive new/more ops @@ -892,9 +890,11 @@ GrRenderTask::ExpectedOutcome GrOpsTask::onMakeClosed( fClosedObservers.reset(); }); if (!this->isNoOp()) { - GrSurfaceProxy* proxy = fTargetView.proxy(); - SkRect clippedContentBounds = proxy->getBoundsRect(); - // TODO: If we can fix up GLPrograms test to always intersect the fTargetView proxy bounds + GrSurfaceProxy* proxy = this->target(0).proxy(); + // Use the entire backing store bounds since the GPU doesn't clip automatically to the + // logical dimensions. + SkRect clippedContentBounds = proxy->backingStoreBoundsRect(); + // TODO: If we can fix up GLPrograms test to always intersect the target proxy bounds // then we can simply assert here that the bounds intersect. if (clippedContentBounds.intersect(fTotalBounds)) { clippedContentBounds.roundOut(&fClippedContentBounds); diff --git a/chromium/third_party/skia/src/gpu/GrOpsTask.h b/chromium/third_party/skia/src/gpu/GrOpsTask.h index 0baf847e282..a40a51a9edd 100644 --- a/chromium/third_party/skia/src/gpu/GrOpsTask.h +++ b/chromium/third_party/skia/src/gpu/GrOpsTask.h @@ -51,7 +51,7 @@ private: public: // The Arenas must outlive the GrOpsTask, either by preserving the context that owns // the pool, or by moving the pool to the DDL that takes over the GrOpsTask. - GrOpsTask(GrRecordingContext::Arenas, GrSurfaceProxyView, GrAuditTrail*); + GrOpsTask(GrDrawingManager*, GrRecordingContext::Arenas, GrSurfaceProxyView, GrAuditTrail*); ~GrOpsTask() override; GrOpsTask* asOpsTask() override { return this; } @@ -68,7 +68,7 @@ public: /** * Empties the draw buffer of any queued up draws. */ - void endFlush() override; + void endFlush(GrDrawingManager*) override; void onPrePrepare(GrRecordingContext*) override; /** @@ -88,11 +88,11 @@ public: fSampledProxies.push_back(proxy); } - void addOp(std::unique_ptr<GrOp> op, GrTextureResolveManager textureResolveManager, - const GrCaps& caps) { - auto addDependency = [ textureResolveManager, &caps, this ] ( + void addOp(GrDrawingManager* drawingMgr, std::unique_ptr<GrOp> op, + GrTextureResolveManager textureResolveManager, const GrCaps& caps) { + auto addDependency = [ drawingMgr, textureResolveManager, &caps, this ] ( GrSurfaceProxy* p, GrMipMapped mipmapped) { - this->addDependency(p, mipmapped, textureResolveManager, caps); + this->addDependency(drawingMgr, p, mipmapped, textureResolveManager, caps); }; op->visitProxies(addDependency); @@ -100,19 +100,20 @@ public: this->recordOp(std::move(op), GrProcessorSet::EmptySetAnalysis(), nullptr, nullptr, caps); } - void addWaitOp(std::unique_ptr<GrOp> op, GrTextureResolveManager textureResolveManager, - const GrCaps& caps) { + void addWaitOp(GrDrawingManager* drawingMgr, std::unique_ptr<GrOp> op, + GrTextureResolveManager textureResolveManager, const GrCaps& caps) { fHasWaitOp = true; - this->addOp(std::move(op), textureResolveManager, caps); + this->addOp(drawingMgr, std::move(op), textureResolveManager, caps); } - void addDrawOp(std::unique_ptr<GrDrawOp> op, const GrProcessorSet::Analysis& processorAnalysis, + void addDrawOp(GrDrawingManager* drawingMgr, std::unique_ptr<GrDrawOp> op, + const GrProcessorSet::Analysis& processorAnalysis, GrAppliedClip&& clip, const DstProxyView& dstProxyView, GrTextureResolveManager textureResolveManager, const GrCaps& caps) { - auto addDependency = [ textureResolveManager, &caps, this ] ( + auto addDependency = [ drawingMgr, textureResolveManager, &caps, this ] ( GrSurfaceProxy* p, GrMipMapped mipmapped) { this->addSampledTexture(p); - this->addDependency(p, mipmapped, textureResolveManager, caps); + this->addDependency(drawingMgr, p, mipmapped, textureResolveManager, caps); }; op->visitProxies(addDependency); diff --git a/chromium/third_party/skia/src/gpu/GrPathRenderer.h b/chromium/third_party/skia/src/gpu/GrPathRenderer.h index 47e65362c11..0866e0106c4 100644 --- a/chromium/third_party/skia/src/gpu/GrPathRenderer.h +++ b/chromium/third_party/skia/src/gpu/GrPathRenderer.h @@ -14,7 +14,6 @@ class GrCaps; class GrClip; -class GrFixedClip; class GrHardClip; class GrPaint; class GrRecordingContext; @@ -127,7 +126,6 @@ public: SkASSERT(fContext); SkASSERT(fUserStencilSettings); SkASSERT(fRenderTargetContext); - SkASSERT(fClip); SkASSERT(fClipConservativeBounds); SkASSERT(fViewMatrix); SkASSERT(fShape); diff --git a/chromium/third_party/skia/src/gpu/GrPathRendererChain.cpp b/chromium/third_party/skia/src/gpu/GrPathRendererChain.cpp index ca2d7e4c867..cf7e271f306 100644 --- a/chromium/third_party/skia/src/gpu/GrPathRendererChain.cpp +++ b/chromium/third_party/skia/src/gpu/GrPathRendererChain.cpp @@ -32,7 +32,7 @@ GrPathRendererChain::GrPathRendererChain(GrRecordingContext* context, const Opti fChain.push_back(sk_make_sp<GrDashLinePathRenderer>()); } if (options.fGpuPathRenderers & GpuPathRenderers::kTessellation) { - if (caps.shaderCaps()->tessellationSupport() && caps.drawInstancedSupport()) { + if (caps.drawInstancedSupport()) { auto tess = sk_make_sp<GrTessellationPathRenderer>(caps); context->priv().addOnFlushCallbackObject(tess.get()); fChain.push_back(std::move(tess)); diff --git a/chromium/third_party/skia/src/gpu/GrPersistentCacheUtils.h b/chromium/third_party/skia/src/gpu/GrPersistentCacheUtils.h index fe932c26194..d6a15e73280 100644 --- a/chromium/third_party/skia/src/gpu/GrPersistentCacheUtils.h +++ b/chromium/third_party/skia/src/gpu/GrPersistentCacheUtils.h @@ -10,8 +10,8 @@ #include "include/core/SkData.h" #include "include/private/GrTypesPriv.h" -#include "src/core/SkReader32.h" -#include "src/core/SkWriter32.h" +#include "src/core/SkReadBuffer.h" +#include "src/core/SkWriteBuffer.h" #include "src/sksl/SkSLString.h" #include "src/sksl/ir/SkSLProgram.h" @@ -28,7 +28,7 @@ struct ShaderMetadata { }; // Increment this whenever the serialization format of cached shaders changes -static constexpr int kCurrentVersion = 1; +static constexpr int kCurrentVersion = 2; static inline sk_sp<SkData> PackCachedShaders(SkFourByteTag shaderType, const SkSL::String shaders[], @@ -39,12 +39,12 @@ static inline sk_sp<SkData> PackCachedShaders(SkFourByteTag shaderType, // kGrShaderTypeCount inputs. If the backend gives us fewer, we just replicate the last one. SkASSERT(numInputs >= 1 && numInputs <= kGrShaderTypeCount); - SkWriter32 writer; - writer.write32(kCurrentVersion); - writer.write32(shaderType); + SkBinaryWriteBuffer writer; + writer.writeInt(kCurrentVersion); + writer.writeUInt(shaderType); for (int i = 0; i < kGrShaderTypeCount; ++i) { - writer.writeString(shaders[i].c_str(), shaders[i].size()); - writer.writePad(&inputs[std::min(i, numInputs - 1)], sizeof(SkSL::Program::Inputs)); + writer.writeByteArray(shaders[i].c_str(), shaders[i].size()); + writer.writePad32(&inputs[std::min(i, numInputs - 1)], sizeof(SkSL::Program::Inputs)); } writer.writeBool(SkToBool(meta)); if (meta) { @@ -57,7 +57,7 @@ static inline sk_sp<SkData> PackCachedShaders(SkFourByteTag shaderType, writer.writeInt(meta->fAttributeNames.count()); for (const auto& attr : meta->fAttributeNames) { - writer.writeString(attr.c_str(), attr.size()); + writer.writeByteArray(attr.c_str(), attr.size()); } writer.writeBool(meta->fHasCustomColorOutput); @@ -66,30 +66,28 @@ static inline sk_sp<SkData> PackCachedShaders(SkFourByteTag shaderType, return writer.snapshotAsData(); } -static SkFourByteTag GetType(SkReader32* reader) { +static SkFourByteTag GetType(SkReadBuffer* reader) { constexpr SkFourByteTag kInvalidTag = ~0; - if (!reader->isAvailable(2 * sizeof(int))) { - return kInvalidTag; - } - if (reader->readInt() != kCurrentVersion) { - return kInvalidTag; - } - return reader->readU32(); + int version = reader->readInt(); + SkFourByteTag typeTag = reader->readUInt(); + return reader->validate(version == kCurrentVersion) ? typeTag : kInvalidTag; } -static inline void UnpackCachedShaders(SkReader32* reader, +static inline bool UnpackCachedShaders(SkReadBuffer* reader, SkSL::String shaders[], SkSL::Program::Inputs inputs[], int numInputs, ShaderMetadata* meta = nullptr) { for (int i = 0; i < kGrShaderTypeCount; ++i) { - size_t stringLen = 0; - const char* string = reader->readString(&stringLen); - shaders[i] = SkSL::String(string, stringLen); + size_t shaderLen = 0; + const char* shaderBuf = static_cast<const char*>(reader->skipByteArray(&shaderLen)); + if (shaderBuf) { + shaders[i].assign(shaderBuf, shaderLen); + } // GL, for example, only wants one set of Inputs if (i < numInputs) { - reader->read(&inputs[i], sizeof(inputs[i])); + reader->readPad32(&inputs[i], sizeof(inputs[i])); } else { reader->skip(sizeof(SkSL::Program::Inputs)); } @@ -104,15 +102,24 @@ static inline void UnpackCachedShaders(SkReader32* reader, } meta->fAttributeNames.resize(reader->readInt()); - for (int i = 0; i < meta->fAttributeNames.count(); ++i) { - size_t stringLen = 0; - const char* string = reader->readString(&stringLen); - meta->fAttributeNames[i] = SkSL::String(string, stringLen); + for (auto& attr : meta->fAttributeNames) { + size_t attrLen = 0; + const char* attrName = static_cast<const char*>(reader->skipByteArray(&attrLen)); + if (attrName) { + attr.assign(attrName, attrLen); + } } meta->fHasCustomColorOutput = reader->readBool(); meta->fHasSecondaryColorOutput = reader->readBool(); } + + if (!reader->isValid()) { + for (int i = 0; i < kGrShaderTypeCount; ++i) { + shaders[i].clear(); + } + } + return reader->isValid(); } } diff --git a/chromium/third_party/skia/src/gpu/GrPrimitiveProcessor.h b/chromium/third_party/skia/src/gpu/GrPrimitiveProcessor.h index 40d4c93d586..c7741833f55 100644 --- a/chromium/third_party/skia/src/gpu/GrPrimitiveProcessor.h +++ b/chromium/third_party/skia/src/gpu/GrPrimitiveProcessor.h @@ -36,6 +36,7 @@ class GrCoordTransform; */ class GrGLSLPrimitiveProcessor; +class GrGLSLUniformHandler; /** * GrPrimitiveProcessor defines an interface which all subclasses must implement. All @@ -56,12 +57,14 @@ public: constexpr Attribute(const char* name, GrVertexAttribType cpuType, GrSLType gpuType) - : fName(name), fCPUType(cpuType), fGPUType(gpuType) {} + : fName(name), fCPUType(cpuType), fGPUType(gpuType) { + SkASSERT(name && gpuType != kVoid_GrSLType); + } constexpr Attribute(const Attribute&) = default; Attribute& operator=(const Attribute&) = default; - constexpr bool isInitialized() const { return SkToBool(fName); } + constexpr bool isInitialized() const { return fGPUType != kVoid_GrSLType; } constexpr const char* name() const { return fName; } constexpr GrVertexAttribType cpuType() const { return fCPUType; } @@ -77,7 +80,7 @@ public: private: const char* fName = nullptr; GrVertexAttribType fCPUType = kFloat_GrVertexAttribType; - GrSLType fGPUType = kFloat_GrSLType; + GrSLType fGPUType = kVoid_GrSLType; }; class Iter { @@ -213,11 +216,15 @@ public: // We use these methods as a temporary back door to inject OpenGL tessellation code. Once // tessellation is supported by SkSL we can remove these. - virtual SkString getTessControlShaderGLSL(const char* versionAndExtensionDecls, + virtual SkString getTessControlShaderGLSL(const GrGLSLPrimitiveProcessor*, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, const GrShaderCaps&) const { SK_ABORT("Not implemented."); } - virtual SkString getTessEvaluationShaderGLSL(const char* versionAndExtensionDecls, + virtual SkString getTessEvaluationShaderGLSL(const GrGLSLPrimitiveProcessor*, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, const GrShaderCaps&) const { SK_ABORT("Not implemented."); } diff --git a/chromium/third_party/skia/src/gpu/GrProcessor.h b/chromium/third_party/skia/src/gpu/GrProcessor.h index cb4711c6960..80ec7e390a1 100644 --- a/chromium/third_party/skia/src/gpu/GrProcessor.h +++ b/chromium/third_party/skia/src/gpu/GrProcessor.h @@ -125,7 +125,6 @@ public: kGrPathProcessor_ClassID, kGrPerlinNoise2Effect_ClassID, kGrPipelineDynamicStateTestProcessor_ClassID, - kGrPremulInputFragmentProcessor_ClassID, kGrQuadEffect_ClassID, kGrRadialGradientLayout_ClassID, kGrRectBlurEffect_ClassID, @@ -162,9 +161,10 @@ public: kTessellate_GrFillBoundingBoxShader_ClassID, kTessellate_GrFillCubicHullShader_ClassID, kTessellate_GrFillTriangleShader_ClassID, - kTessellate_GrStencilCubicShader_ClassID, + kTessellate_GrMiddleOutCubicShader_ClassID, kTessellate_GrStencilTriangleShader_ClassID, - kTessellate_GrStencilWedgeShader_ClassID, + kTessellate_GrTessellateCubicShader_ClassID, + kTessellate_GrTessellateWedgeShader_ClassID, kTestFP_ClassID, kTestRectOp_ClassID, kFlatNormalsFP_ClassID, diff --git a/chromium/third_party/skia/src/gpu/GrProcessorSet.cpp b/chromium/third_party/skia/src/gpu/GrProcessorSet.cpp index fe64cb9233d..b8a0aef92cc 100644 --- a/chromium/third_party/skia/src/gpu/GrProcessorSet.cpp +++ b/chromium/third_party/skia/src/gpu/GrProcessorSet.cpp @@ -69,8 +69,9 @@ GrProcessorSet::GrProcessorSet(GrProcessorSet&& that) fFragmentProcessors[i] = std::move(that.fFragmentProcessors[i + that.fFragmentProcessorOffset]); } - that.fColorFragmentProcessorCnt = 0; that.fFragmentProcessors.reset(0); + that.fColorFragmentProcessorCnt = 0; + that.fFragmentProcessorOffset = 0; } GrProcessorSet::~GrProcessorSet() { diff --git a/chromium/third_party/skia/src/gpu/GrProgramInfo.h b/chromium/third_party/skia/src/gpu/GrProgramInfo.h index 373b3bbafdb..f8ce3fc7011 100644 --- a/chromium/third_party/skia/src/gpu/GrProgramInfo.h +++ b/chromium/third_party/skia/src/gpu/GrProgramInfo.h @@ -49,6 +49,7 @@ public: int numSamples() const { return fNumSamples; } int numStencilSamples() const { return fNumStencilSamples; } + bool isStencilEnabled() const { return fPipeline->isStencilEnabled(); } int numRasterSamples() const { return fPipeline->isStencilEnabled() ? fNumStencilSamples : fNumSamples; diff --git a/chromium/third_party/skia/src/gpu/GrProxyProvider.cpp b/chromium/third_party/skia/src/gpu/GrProxyProvider.cpp index cf20dd1d715..e2bfd767ff0 100644 --- a/chromium/third_party/skia/src/gpu/GrProxyProvider.cpp +++ b/chromium/third_party/skia/src/gpu/GrProxyProvider.cpp @@ -33,8 +33,7 @@ #include "src/gpu/SkGr.h" #include "src/image/SkImage_Base.h" -#define ASSERT_SINGLE_OWNER \ - SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fImageContext->priv().singleOwner());) +#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fImageContext->priv().singleOwner()) GrProxyProvider::GrProxyProvider(GrImageContext* imageContext) : fImageContext(imageContext) {} @@ -54,6 +53,9 @@ bool GrProxyProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTexturePr return false; } + // Only the proxyProvider that created a proxy should be assigning unique keys to it. + SkASSERT(this->isDDLProvider() == proxy->creatingProvider()); + #ifdef SK_DEBUG { GrContext* direct = fImageContext->priv().asDirectContext(); @@ -189,9 +191,11 @@ sk_sp<GrTextureProxy> GrProxyProvider::createWrapped(sk_sp<GrTexture> tex, #endif if (tex->asRenderTarget()) { - return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), useAllocator)); + return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), useAllocator, + this->isDDLProvider())); } else { - return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), useAllocator)); + return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), useAllocator, + this->isDDLProvider())); } } @@ -424,19 +428,18 @@ sk_sp<GrTextureProxy> GrProxyProvider::createProxy(const GrBackendFormat& format ? GrMipMapsStatus::kDirty : GrMipMapsStatus::kNotAllocated; if (renderable == GrRenderable::kYes) { - renderTargetSampleCnt = - caps->getRenderTargetSampleCount(renderTargetSampleCnt, format); + renderTargetSampleCnt = caps->getRenderTargetSampleCount(renderTargetSampleCnt, format); SkASSERT(renderTargetSampleCnt); // We know anything we instantiate later from this deferred path will be // both texturable and renderable return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy( *caps, format, dimensions, renderTargetSampleCnt, mipMapped, mipMapsStatus, fit, - budgeted, isProtected, surfaceFlags, useAllocator)); + budgeted, isProtected, surfaceFlags, useAllocator, this->isDDLProvider())); } return sk_sp<GrTextureProxy>(new GrTextureProxy(format, dimensions, mipMapped, mipMapsStatus, fit, budgeted, isProtected, surfaceFlags, - useAllocator)); + useAllocator, this->isDDLProvider())); } sk_sp<GrTextureProxy> GrProxyProvider::createCompressedTextureProxy( @@ -487,9 +490,9 @@ sk_sp<GrTextureProxy> GrProxyProvider::wrapBackendTexture(const GrBackendTexture GrWrapOwnership ownership, GrWrapCacheable cacheable, GrIOType ioType, - ReleaseProc releaseProc, - ReleaseContext releaseCtx) { + sk_sp<GrRefCntedCallback> releaseHelper) { SkASSERT(ioType != kWrite_GrIOType); + if (this->isAbandoned()) { return nullptr; } @@ -508,22 +511,23 @@ sk_sp<GrTextureProxy> GrProxyProvider::wrapBackendTexture(const GrBackendTexture return nullptr; } - if (releaseProc) { - tex->setRelease(releaseProc, releaseCtx); + if (releaseHelper) { + tex->setRelease(std::move(releaseHelper)); } SkASSERT(!tex->asRenderTarget()); // Strictly a GrTexture // Make sure we match how we created the proxy with SkBudgeted::kNo SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType()); - return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), UseAllocator::kNo)); + return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), UseAllocator::kNo, + this->isDDLProvider())); } -sk_sp<GrTextureProxy> GrProxyProvider::wrapCompressedBackendTexture(const GrBackendTexture& beTex, - GrWrapOwnership ownership, - GrWrapCacheable cacheable, - ReleaseProc releaseProc, - ReleaseContext releaseCtx) { +sk_sp<GrTextureProxy> GrProxyProvider::wrapCompressedBackendTexture( + const GrBackendTexture& beTex, + GrWrapOwnership ownership, + GrWrapCacheable cacheable, + sk_sp<GrRefCntedCallback> releaseHelper) { if (this->isAbandoned()) { return nullptr; } @@ -542,15 +546,16 @@ sk_sp<GrTextureProxy> GrProxyProvider::wrapCompressedBackendTexture(const GrBack return nullptr; } - if (releaseProc) { - tex->setRelease(releaseProc, releaseCtx); + if (releaseHelper) { + tex->setRelease(std::move(releaseHelper)); } SkASSERT(!tex->asRenderTarget()); // Strictly a GrTexture // Make sure we match how we created the proxy with SkBudgeted::kNo SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType()); - return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), UseAllocator::kNo)); + return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), UseAllocator::kNo, + this->isDDLProvider())); } sk_sp<GrTextureProxy> GrProxyProvider::wrapRenderableBackendTexture( @@ -558,8 +563,7 @@ sk_sp<GrTextureProxy> GrProxyProvider::wrapRenderableBackendTexture( int sampleCnt, GrWrapOwnership ownership, GrWrapCacheable cacheable, - ReleaseProc releaseProc, - ReleaseContext releaseCtx) { + sk_sp<GrRefCntedCallback> releaseHelper) { if (this->isAbandoned()) { return nullptr; } @@ -583,21 +587,21 @@ sk_sp<GrTextureProxy> GrProxyProvider::wrapRenderableBackendTexture( return nullptr; } - if (releaseProc) { - tex->setRelease(releaseProc, releaseCtx); + if (releaseHelper) { + tex->setRelease(std::move(releaseHelper)); } SkASSERT(tex->asRenderTarget()); // A GrTextureRenderTarget // Make sure we match how we created the proxy with SkBudgeted::kNo SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType()); - return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), UseAllocator::kNo)); + return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), UseAllocator::kNo, + this->isDDLProvider())); } sk_sp<GrSurfaceProxy> GrProxyProvider::wrapBackendRenderTarget( const GrBackendRenderTarget& backendRT, - ReleaseProc releaseProc, - ReleaseContext releaseCtx) { + sk_sp<GrRefCntedCallback> releaseHelper) { if (this->isAbandoned()) { return nullptr; } @@ -615,8 +619,8 @@ sk_sp<GrSurfaceProxy> GrProxyProvider::wrapBackendRenderTarget( return nullptr; } - if (releaseProc) { - rt->setRelease(releaseProc, releaseCtx); + if (releaseHelper) { + rt->setRelease(std::move(releaseHelper)); } SkASSERT(!rt->asTexture()); // A GrRenderTarget that's not textureable @@ -730,7 +734,8 @@ sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& budgeted, isProtected, surfaceFlags, - useAllocator)); + useAllocator, + this->isDDLProvider())); } else { return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(callback), format, @@ -741,7 +746,8 @@ sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& budgeted, isProtected, surfaceFlags, - useAllocator)); + useAllocator, + this->isDDLProvider())); } } @@ -777,7 +783,7 @@ sk_sp<GrRenderTargetProxy> GrProxyProvider::createLazyRenderTargetProxy( return sk_sp<GrRenderTargetProxy>(new GrTextureRenderTargetProxy( *this->caps(), std::move(callback), format, dimensions, sampleCnt, textureInfo->fMipMapped, mipMapsStatus, fit, budgeted, isProtected, surfaceFlags, - useAllocator)); + useAllocator, this->isDDLProvider())); } GrRenderTargetProxy::WrapsVkSecondaryCB vkSCB = @@ -803,17 +809,20 @@ sk_sp<GrTextureProxy> GrProxyProvider::MakeFullyLazyProxy(LazyInstantiateCallbac SkASSERT(renderTargetSampleCnt == 1 || renderable == GrRenderable::kYes); GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone; + // MakeFullyLazyProxy is only called at flush time so we know these texture proxies are + // not being created by a DDL provider. static constexpr SkISize kLazyDims = {-1, -1}; if (GrRenderable::kYes == renderable) { return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy( caps, std::move(callback), format, kLazyDims, renderTargetSampleCnt, GrMipMapped::kNo, GrMipMapsStatus::kNotAllocated, SkBackingFit::kApprox, - SkBudgeted::kYes, isProtected, surfaceFlags, useAllocator)); + SkBudgeted::kYes, isProtected, surfaceFlags, useAllocator, GrDDLProvider::kNo)); } else { return sk_sp<GrTextureProxy>( new GrTextureProxy(std::move(callback), format, kLazyDims, GrMipMapped::kNo, GrMipMapsStatus::kNotAllocated, SkBackingFit::kApprox, - SkBudgeted::kYes, isProtected, surfaceFlags, useAllocator)); + SkBudgeted::kYes, isProtected, surfaceFlags, useAllocator, + GrDDLProvider::kNo)); } } @@ -858,6 +867,10 @@ void GrProxyProvider::processInvalidUniqueKeyImpl(const GrUniqueKey& key, GrText } } +GrDDLProvider GrProxyProvider::isDDLProvider() const { + return fImageContext->priv().asDirectContext() ? GrDDLProvider::kNo : GrDDLProvider::kYes; +} + uint32_t GrProxyProvider::contextID() const { return fImageContext->priv().contextID(); } diff --git a/chromium/third_party/skia/src/gpu/GrProxyProvider.h b/chromium/third_party/skia/src/gpu/GrProxyProvider.h index a275f297940..e1f681f04b6 100644 --- a/chromium/third_party/skia/src/gpu/GrProxyProvider.h +++ b/chromium/third_party/skia/src/gpu/GrProxyProvider.h @@ -115,12 +115,12 @@ public: GrWrapOwnership, GrWrapCacheable, GrIOType, - ReleaseProc = nullptr, - ReleaseContext = nullptr); + sk_sp<GrRefCntedCallback> = nullptr); - sk_sp<GrTextureProxy> wrapCompressedBackendTexture(const GrBackendTexture&, GrWrapOwnership, - GrWrapCacheable, ReleaseProc = nullptr, - ReleaseContext = nullptr); + sk_sp<GrTextureProxy> wrapCompressedBackendTexture(const GrBackendTexture&, + GrWrapOwnership, + GrWrapCacheable, + sk_sp<GrRefCntedCallback> releaseHelper); /* * Create a texture proxy that wraps a backend texture and is both texture-able and renderable @@ -129,15 +129,13 @@ public: int sampleCnt, GrWrapOwnership, GrWrapCacheable, - ReleaseProc = nullptr, - ReleaseContext = nullptr); + sk_sp<GrRefCntedCallback> releaseHelper); /* * Create a render target proxy that wraps a backend render target */ sk_sp<GrSurfaceProxy> wrapBackendRenderTarget(const GrBackendRenderTarget&, - ReleaseProc = nullptr, - ReleaseContext = nullptr); + sk_sp<GrRefCntedCallback> releaseHelper); /* * Create a render target proxy that wraps a backend texture @@ -223,6 +221,8 @@ public: */ void processInvalidUniqueKey(const GrUniqueKey&, GrTextureProxy*, InvalidateGPUResource); + GrDDLProvider isDDLProvider() const; + // TODO: remove these entry points - it is a bit sloppy to be getting context info from here uint32_t contextID() const; const GrCaps* caps() const; diff --git a/chromium/third_party/skia/src/gpu/GrRecordingContext.cpp b/chromium/third_party/skia/src/gpu/GrRecordingContext.cpp index 2c7c64d5730..9173931e4f1 100644 --- a/chromium/third_party/skia/src/gpu/GrRecordingContext.cpp +++ b/chromium/third_party/skia/src/gpu/GrRecordingContext.cpp @@ -8,6 +8,7 @@ #include "include/private/GrRecordingContext.h" #include "include/gpu/GrContext.h" +#include "include/gpu/GrContextThreadSafeProxy.h" #include "src/core/SkArenaAlloc.h" #include "src/gpu/GrAuditTrail.h" #include "src/gpu/GrCaps.h" @@ -22,9 +23,6 @@ #include "src/gpu/effects/GrSkSLFP.h" #include "src/gpu/text/GrTextBlobCache.h" -#define ASSERT_SINGLE_OWNER_PRIV \ - SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());) - GrRecordingContext::ProgramData::ProgramData(std::unique_ptr<const GrProgramDesc> desc, const GrProgramInfo* info) : fDesc(std::move(desc)) @@ -36,44 +34,34 @@ GrRecordingContext::ProgramData::ProgramData(ProgramData&& other) , fInfo(other.fInfo) { } -GrRecordingContext::ProgramData::~ProgramData() {} +GrRecordingContext::ProgramData::~ProgramData() = default; -GrRecordingContext::GrRecordingContext(GrBackendApi backend, - const GrContextOptions& options, - uint32_t contextID) - : INHERITED(backend, options, contextID) +GrRecordingContext::GrRecordingContext(sk_sp<GrContextThreadSafeProxy> proxy) + : INHERITED(std::move(proxy)) , fAuditTrail(new GrAuditTrail()) { } -GrRecordingContext::~GrRecordingContext() { } +GrRecordingContext::~GrRecordingContext() = default; -/** - * TODO: move textblob draw calls below context (see comment below) - */ -static void textblobcache_overbudget_CB(void* data) { - SkASSERT(data); - GrRecordingContext* context = reinterpret_cast<GrRecordingContext*>(data); +bool GrRecordingContext::init() { - GrContext* direct = context->priv().asDirectContext(); - if (!direct) { - return; + if (!INHERITED::init()) { + return false; } - // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on - // GrRenderTargetContext to perform a necessary flush. The solution is to move drawText calls - // to below the GrContext level, but this is not trivial because they call drawPath on - // SkGpuDevice. - direct->flush(); -} - -bool GrRecordingContext::init(sk_sp<const GrCaps> caps) { + auto overBudget = [this]() { + if (GrContext* direct = this->priv().asDirectContext(); direct != nullptr) { - if (!INHERITED::init(std::move(caps))) { - return false; - } + // TODO: move text blob draw calls below context + // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on + // GrRenderTargetContext to perform a necessary flush. The solution is to move drawText + // calls to below the GrContext level, but this is not trivial because they call + // drawPath on SkGpuDevice. + direct->flushAndSubmit(); + } + }; - fTextBlobCache.reset(new GrTextBlobCache(textblobcache_overbudget_CB, this, - this->contextID())); + fTextBlobCache.reset(new GrTextBlobCache(overBudget, this->contextID())); return true; } @@ -99,19 +87,8 @@ void GrRecordingContext::setupDrawingManager(bool sortOpsTasks, bool reduceOpsTa prcOptions.fGpuPathRenderers &= ~GpuPathRenderers::kSmall; } - GrTextContext::Options textContextOptions; - textContextOptions.fMaxDistanceFieldFontSize = this->options().fGlyphsAsPathsFontSize; - textContextOptions.fMinDistanceFieldFontSize = this->options().fMinDistanceFieldFontSize; - textContextOptions.fDistanceFieldVerticesAlwaysHaveW = false; -#if SK_SUPPORT_ATLAS_TEXT - if (GrContextOptions::Enable::kYes == this->options().fDistanceFieldGlyphVerticesAlwaysHaveW) { - textContextOptions.fDistanceFieldVerticesAlwaysHaveW = true; - } -#endif - fDrawingManager.reset(new GrDrawingManager(this, prcOptions, - textContextOptions, sortOpsTasks, reduceOpsTaskSplitting)); } diff --git a/chromium/third_party/skia/src/gpu/GrRecordingContextPriv.h b/chromium/third_party/skia/src/gpu/GrRecordingContextPriv.h index 4337d3f3c4b..4e3e9a7a3da 100644 --- a/chromium/third_party/skia/src/gpu/GrRecordingContextPriv.h +++ b/chromium/third_party/skia/src/gpu/GrRecordingContextPriv.h @@ -9,6 +9,7 @@ #define GrRecordingContextPriv_DEFINED #include "include/private/GrRecordingContext.h" +#include "src/gpu/text/GrSDFTOptions.h" /** Class that exposes methods to GrRecordingContext that are only intended for use internal to Skia. This class is purely a privileged window into GrRecordingContext. It should never have @@ -102,6 +103,10 @@ public: return &fContext->fStats; } + GrSDFTOptions SDFTOptions() const { + return {this->options().fMinDistanceFieldFontSize, this->options().fGlyphsAsPathsFontSize}; + } + private: explicit GrRecordingContextPriv(GrRecordingContext* context) : fContext(context) {} GrRecordingContextPriv(const GrRecordingContextPriv&); // unimpl diff --git a/chromium/third_party/skia/src/gpu/GrRectanizer.h b/chromium/third_party/skia/src/gpu/GrRectanizer.h new file mode 100644 index 00000000000..0b1fff53348 --- /dev/null +++ b/chromium/third_party/skia/src/gpu/GrRectanizer.h @@ -0,0 +1,44 @@ +/* + * Copyright 2010 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrRectanizer_DEFINED +#define GrRectanizer_DEFINED + +#include "include/gpu/GrTypes.h" + +struct SkIPoint16; + +class GrRectanizer { +public: + GrRectanizer(int width, int height) : fWidth(width), fHeight(height) { + SkASSERT(width >= 0); + SkASSERT(height >= 0); + } + + virtual ~GrRectanizer() {} + + virtual void reset() = 0; + + int width() const { return fWidth; } + int height() const { return fHeight; } + + // Attempt to add a rect. Return true on success; false on failure. If + // successful the position in the atlas is returned in 'loc'. + virtual bool addRect(int width, int height, SkIPoint16* loc) = 0; + virtual float percentFull() const = 0; + + /** + * Our factory, which returns the subclass du jour + */ + static GrRectanizer* Factory(int width, int height); + +private: + const int fWidth; + const int fHeight; +}; + +#endif diff --git a/chromium/third_party/skia/src/gpu/GrRectanizerPow2.cpp b/chromium/third_party/skia/src/gpu/GrRectanizerPow2.cpp new file mode 100644 index 00000000000..9a35bf298d2 --- /dev/null +++ b/chromium/third_party/skia/src/gpu/GrRectanizerPow2.cpp @@ -0,0 +1,59 @@ +/* + * Copyright 2010 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "src/gpu/GrRectanizerPow2.h" + +bool GrRectanizerPow2::addRect(int width, int height, SkIPoint16* loc) { + if ((unsigned)width > (unsigned)this->width() || + (unsigned)height > (unsigned)this->height()) { + return false; + } + + int32_t area = width * height; // computed here since height will be modified + + height = GrNextPow2(height); + if (height < kMIN_HEIGHT_POW2) { + height = kMIN_HEIGHT_POW2; + } + + Row* row = &fRows[HeightToRowIndex(height)]; + SkASSERT(row->fRowHeight == 0 || row->fRowHeight == height); + + if (0 == row->fRowHeight) { + if (!this->canAddStrip(height)) { + return false; + } + this->initRow(row, height); + } else { + if (!row->canAddWidth(width, this->width())) { + if (!this->canAddStrip(height)) { + return false; + } + // that row is now "full", so retarget our Row record for + // another one + this->initRow(row, height); + } + } + + SkASSERT(row->fRowHeight == height); + SkASSERT(row->canAddWidth(width, this->width())); + *loc = row->fLoc; + row->fLoc.fX += width; + + SkASSERT(row->fLoc.fX <= this->width()); + SkASSERT(row->fLoc.fY <= this->height()); + SkASSERT(fNextStripY <= this->height()); + fAreaSoFar += area; + return true; +} + +/////////////////////////////////////////////////////////////////////////////// + +// factory is now in GrRectanizer_skyline.cpp +//GrRectanizer* GrRectanizer::Factory(int width, int height) { +// return new GrRectanizerPow2 (width, height); +//} diff --git a/chromium/third_party/skia/src/gpu/GrRectanizerPow2.h b/chromium/third_party/skia/src/gpu/GrRectanizerPow2.h new file mode 100644 index 00000000000..c96c9725b16 --- /dev/null +++ b/chromium/third_party/skia/src/gpu/GrRectanizerPow2.h @@ -0,0 +1,83 @@ +/* +* Copyright 2014 Google Inc. +* +* Use of this source code is governed by a BSD-style license that can be +* found in the LICENSE file. +*/ + +#ifndef GrRectanizerPow2_DEFINED +#define GrRectanizerPow2_DEFINED + +#include "include/private/SkMalloc.h" +#include "src/core/SkIPoint16.h" +#include "src/core/SkMathPriv.h" +#include "src/gpu/GrRectanizer.h" + +// This Rectanizer quantizes the incoming rects to powers of 2. Each power +// of two can have, at most, one active row/shelf. Once a row/shelf for +// a particular power of two gets full its fRows entry is recycled to point +// to a new row. +// The skyline algorithm almost always provides a better packing. +// +// Mark this class final in an effort to avoid the vtable when this subclass is used explicitly. +class GrRectanizerPow2 final : public GrRectanizer { +public: + GrRectanizerPow2(int w, int h) : INHERITED(w, h) { + this->reset(); + } + + ~GrRectanizerPow2() final {} + + void reset() final { + fNextStripY = 0; + fAreaSoFar = 0; + sk_bzero(fRows, sizeof(fRows)); + } + + bool addRect(int w, int h, SkIPoint16* loc) final; + + float percentFull() const final { + return fAreaSoFar / ((float)this->width() * this->height()); + } + +private: + static const int kMIN_HEIGHT_POW2 = 2; + static const int kMaxExponent = 16; + + struct Row { + SkIPoint16 fLoc; + // fRowHeight is actually known by this struct's position in fRows + // but it is used to signal if there exists an open row of this height + int fRowHeight; + + bool canAddWidth(int width, int containerWidth) const { + return fLoc.fX + width <= containerWidth; + } + }; + + Row fRows[kMaxExponent]; // 0-th entry will be unused + + int fNextStripY; + int32_t fAreaSoFar; + + static int HeightToRowIndex(int height) { + SkASSERT(height >= kMIN_HEIGHT_POW2); + int index = 32 - SkCLZ(height - 1); + SkASSERT(index < kMaxExponent); + return index; + } + + bool canAddStrip(int height) const { + return fNextStripY + height <= this->height(); + } + + void initRow(Row* row, int rowHeight) { + row->fLoc.set(0, fNextStripY); + row->fRowHeight = rowHeight; + fNextStripY += rowHeight; + } + + typedef GrRectanizer INHERITED; +}; + +#endif diff --git a/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.cpp b/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.cpp index 42aff7a657f..f36b733d1dc 100644 --- a/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.cpp +++ b/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.cpp @@ -116,3 +116,8 @@ void GrRectanizerSkyline::addSkylineLevel(int skylineIndex, int x, int y, int wi } } +/////////////////////////////////////////////////////////////////////////////// + +GrRectanizer* GrRectanizer::Factory(int width, int height) { + return new GrRectanizerSkyline(width, height); +} diff --git a/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.h b/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.h index 36af34db618..40e5c1cc163 100644 --- a/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.h +++ b/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.h @@ -9,17 +9,21 @@ #define GrRectanizerSkyline_DEFINED #include "include/private/SkTDArray.h" -#include "src/core/SkIPoint16.h" +#include "src/gpu/GrRectanizer.h" // Pack rectangles and track the current silhouette // Based, in part, on Jukka Jylanki's work at http://clb.demon.fi -class GrRectanizerSkyline { +// +// Mark this class final in an effort to avoid the vtable when this subclass is used explicitly. +class GrRectanizerSkyline final : public GrRectanizer { public: - GrRectanizerSkyline(int w, int h) : fWidth{w}, fHeight{h} { + GrRectanizerSkyline(int w, int h) : INHERITED(w, h) { this->reset(); } - void reset() { + ~GrRectanizerSkyline() final { } + + void reset() final { fAreaSoFar = 0; fSkyline.reset(); SkylineSegment* seg = fSkyline.append(1); @@ -28,10 +32,11 @@ public: seg->fWidth = this->width(); } - bool addRect(int w, int h, SkIPoint16* loc); + bool addRect(int w, int h, SkIPoint16* loc) final; - int width() const { return fWidth; } - int height() const { return fHeight; } + float percentFull() const final { + return fAreaSoFar / ((float)this->width() * this->height()); + } private: struct SkylineSegment { @@ -40,6 +45,10 @@ private: int fWidth; }; + SkTDArray<SkylineSegment> fSkyline; + + int32_t fAreaSoFar; + // Can a width x height rectangle fit in the free space represented by // the skyline segments >= 'skylineIndex'? If so, return true and fill in // 'y' with the y-location at which it fits (the x location is pulled from @@ -49,10 +58,7 @@ private: // at x,y. void addSkylineLevel(int skylineIndex, int x, int y, int width, int height); - const int fWidth; - const int fHeight; - SkTDArray<SkylineSegment> fSkyline; - int32_t fAreaSoFar; + typedef GrRectanizer INHERITED; }; -#endif // GrRectanizerSkyline_DEFINED +#endif diff --git a/chromium/third_party/skia/src/gpu/GrReducedClip.cpp b/chromium/third_party/skia/src/gpu/GrReducedClip.cpp index 469b7f94e48..533132edc7c 100644 --- a/chromium/third_party/skia/src/gpu/GrReducedClip.cpp +++ b/chromium/third_party/skia/src/gpu/GrReducedClip.cpp @@ -25,7 +25,9 @@ #include "src/gpu/effects/GrConvexPolyEffect.h" #include "src/gpu/effects/GrRRectEffect.h" #include "src/gpu/effects/generated/GrAARectEffect.h" +#include "src/gpu/effects/generated/GrDeviceSpaceEffect.h" #include "src/gpu/geometry/GrStyledShape.h" +#include "src/shaders/SkShaderBase.h" /** * There are plenty of optimizations that could be added here. Maybe flips could be folded into @@ -115,6 +117,13 @@ GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds // Now that we have determined the bounds to use and filtered out the trivial cases, call // the helper that actually walks the stack. this->walkStack(stack, tighterQuery); + + if (fInitialState == InitialState::kAllOut && fMaskElements.isEmpty()) { + // The clip starts with no coverage and there are no elements to add coverage with + // expanding ops. We ignore the AAClipRectGenID since it is an implied intersection. + this->makeEmpty(); + return; + } } if (SK_InvalidGenID != fAAClipRectGenID && // Is there an AA clip rect? @@ -173,6 +182,18 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound break; } + if (element->getDeviceSpaceType() == Element::DeviceSpaceType::kShader) { + if (fShader) { + // Combine multiple shaders together with src-in blending. This works because all + // shaders are effectively intersections (difference ops have been modified to be + // 1 - alpha already). + fShader = SkShaders::Blend(SkBlendMode::kSrcIn, element->refShader(), fShader); + } else { + fShader = element->refShader(); + } + continue; + } + bool skippable = false; bool isFlip = false; // does this op just flip the in/out state of every point in the bounds @@ -480,6 +501,8 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound } GrReducedClip::ClipResult GrReducedClip::clipInsideElement(const Element* element) { + SkASSERT(element->getDeviceSpaceType() != Element::DeviceSpaceType::kShader); + SkIRect elementIBounds; if (!element->isAA()) { element->getBounds().round(&elementIBounds); @@ -523,12 +546,17 @@ GrReducedClip::ClipResult GrReducedClip::clipInsideElement(const Element* elemen case Element::DeviceSpaceType::kPath: return this->addAnalyticFP(element->getDeviceSpacePath(), Invert(element->isInverseFilled()), GrAA(element->isAA())); + + case Element::DeviceSpaceType::kShader: + SkUNREACHABLE; } SK_ABORT("Unexpected DeviceSpaceType"); } GrReducedClip::ClipResult GrReducedClip::clipOutsideElement(const Element* element) { + SkASSERT(element->getDeviceSpaceType() != Element::DeviceSpaceType::kShader); + switch (element->getDeviceSpaceType()) { case Element::DeviceSpaceType::kEmpty: return ClipResult::kMadeEmpty; @@ -589,6 +617,9 @@ GrReducedClip::ClipResult GrReducedClip::clipOutsideElement(const Element* eleme case Element::DeviceSpaceType::kPath: return this->addAnalyticFP(element->getDeviceSpacePath(), Invert(!element->isInverseFilled()), GrAA(element->isAA())); + + case Element::DeviceSpaceType::kShader: + SkUNREACHABLE; } SK_ABORT("Unexpected DeviceSpaceType"); @@ -620,9 +651,10 @@ GrReducedClip::ClipResult GrReducedClip::addAnalyticFP(const SkRect& deviceSpace return ClipResult::kNotClipped; } - fAnalyticFPs.push_back(GrAARectEffect::Make(GetClipEdgeType(invert, aa), deviceSpaceRect)); - SkASSERT(fAnalyticFPs.back()); + fAnalyticFP = GrAARectEffect::Make(std::move(fAnalyticFP), GetClipEdgeType(invert, aa), + deviceSpaceRect); + SkASSERT(fAnalyticFP != nullptr); return ClipResult::kClipped; } @@ -632,9 +664,12 @@ GrReducedClip::ClipResult GrReducedClip::addAnalyticFP(const SkRRect& deviceSpac return ClipResult::kNotClipped; } - if (auto fp = GrRRectEffect::Make(GetClipEdgeType(invert, aa), deviceSpaceRRect, - *fCaps->shaderCaps())) { - fAnalyticFPs.push_back(std::move(fp)); + // Combine this analytic effect with the previous effect in the stack. + bool success; + std::tie(success, fAnalyticFP) = GrRRectEffect::Make(std::move(fAnalyticFP), + GetClipEdgeType(invert, aa), + deviceSpaceRRect, *fCaps->shaderCaps()); + if (success) { return ClipResult::kClipped; } @@ -650,8 +685,12 @@ GrReducedClip::ClipResult GrReducedClip::addAnalyticFP(const SkPath& deviceSpace return ClipResult::kNotClipped; } - if (auto fp = GrConvexPolyEffect::Make(GetClipEdgeType(invert, aa), deviceSpacePath)) { - fAnalyticFPs.push_back(std::move(fp)); + // Combine this analytic effect with the previous effect in the stack. + bool success; + std::tie(success, fAnalyticFP) = GrConvexPolyEffect::Make(std::move(fAnalyticFP), + GetClipEdgeType(invert, aa), + deviceSpacePath); + if (success) { return ClipResult::kClipped; } @@ -673,6 +712,7 @@ void GrReducedClip::makeEmpty() { fAAClipRectGenID = SK_InvalidGenID; fWindowRects.reset(); fMaskElements.reset(); + fShader.reset(); fInitialState = InitialState::kAllOut; } @@ -693,7 +733,7 @@ static bool stencil_element(GrRenderTargetContext* rtc, GrPaint paint; paint.setCoverageSetOpXPFactory((SkRegion::Op)element->getOp(), element->isInverseFilled()); - rtc->priv().stencilRect(clip, ss, std::move(paint), aa, viewMatrix, + rtc->priv().stencilRect(&clip, ss, std::move(paint), aa, viewMatrix, element->getDeviceSpaceRect()); return true; } @@ -704,7 +744,7 @@ static bool stencil_element(GrRenderTargetContext* rtc, path.toggleInverseFillType(); } - return rtc->priv().drawAndStencilPath(clip, ss, (SkRegion::Op)element->getOp(), + return rtc->priv().drawAndStencilPath(&clip, ss, (SkRegion::Op)element->getOp(), element->isInverseFilled(), aa, viewMatrix, path); } } @@ -724,7 +764,7 @@ static void draw_element(GrRenderTargetContext* rtc, SkDEBUGFAIL("Should never get here with an empty element."); break; case SkClipStack::Element::DeviceSpaceType::kRect: - rtc->drawRect(clip, std::move(paint), aa, viewMatrix, element->getDeviceSpaceRect()); + rtc->drawRect(&clip, std::move(paint), aa, viewMatrix, element->getDeviceSpaceRect()); break; default: { SkPath path; @@ -733,7 +773,7 @@ static void draw_element(GrRenderTargetContext* rtc, path.toggleInverseFillType(); } - rtc->drawPath(clip, std::move(paint), aa, viewMatrix, path, GrStyle::SimpleFill()); + rtc->drawPath(&clip, std::move(paint), aa, viewMatrix, path, GrStyle::SimpleFill()); break; } } @@ -742,7 +782,7 @@ static void draw_element(GrRenderTargetContext* rtc, bool GrReducedClip::drawAlphaClipMask(GrRenderTargetContext* rtc) const { // The texture may be larger than necessary, this rect represents the part of the texture // we populate with a rasterization of the clip. - GrFixedClip clip(SkIRect::MakeWH(fScissor.width(), fScissor.height())); + GrFixedClip clip(rtc->dimensions(), SkIRect::MakeWH(fScissor.width(), fScissor.height())); if (!fWindowRects.empty()) { clip.setWindowRectangles(fWindowRects.makeOffset(-fScissor.left(), -fScissor.top()), @@ -753,7 +793,15 @@ bool GrReducedClip::drawAlphaClipMask(GrRenderTargetContext* rtc) const { // clear the part that we care about. SkPMColor4f initialCoverage = InitialState::kAllIn == this->initialState() ? SK_PMColor4fWHITE : SK_PMColor4fTRANSPARENT; - rtc->priv().clear(clip, initialCoverage, GrRenderTargetContext::CanClearFullscreen::kYes); + if (clip.hasWindowRectangles()) { + GrPaint paint; + paint.setColor4f(initialCoverage); + paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + rtc->drawRect(&clip, std::move(paint), GrAA::kNo, SkMatrix::I(), + SkRect::Make(clip.scissorRect())); + } else { + rtc->priv().clearAtLeast(clip.scissorRect(), initialCoverage); + } // Set the matrix so that rendered clip elements are transformed to mask space from clip space. SkMatrix translate; @@ -794,7 +842,7 @@ bool GrReducedClip::drawAlphaClipMask(GrRenderTargetContext* rtc) const { GrPaint paint; paint.setCoverageSetOpXPFactory(op, !invert); - rtc->priv().stencilRect(clip, &kDrawOutsideElement, std::move(paint), GrAA::kNo, + rtc->priv().stencilRect(&clip, &kDrawOutsideElement, std::move(paint), GrAA::kNo, translate, SkRect::Make(fScissor)); } else { // all the remaining ops can just be directly draw into the accumulation buffer @@ -842,21 +890,59 @@ bool GrReducedClip::drawStencilClipMask(GrRecordingContext* context, return true; } +static int count_fp_recursive(GrFragmentProcessor* fp) { + int count = 0; + if (fp != nullptr) { + count += 1; // count self + for (int index=0; index < fp->numChildProcessors(); ++index) { + count += count_fp_recursive(&fp->childProcessor(index)); // count children + } + } + return count; +} + +int GrReducedClip::numAnalyticFPs() const { + return fCCPRClipPaths.size() + count_fp_recursive(fAnalyticFP.get()); +} + std::unique_ptr<GrFragmentProcessor> GrReducedClip::finishAndDetachAnalyticFPs( + GrRecordingContext* context, const SkMatrixProvider& matrixProvider, GrCoverageCountingPathRenderer* ccpr, uint32_t opsTaskID) { - // Make sure finishAndDetachAnalyticFPs hasn't been called already. - SkDEBUGCODE(for (const auto& fp : fAnalyticFPs) { SkASSERT(fp); }) - - if (!fCCPRClipPaths.empty()) { - fAnalyticFPs.reserve(fAnalyticFPs.count() + fCCPRClipPaths.count()); - for (const SkPath& ccprClipPath : fCCPRClipPaths) { - SkASSERT(ccpr); - SkASSERT(fHasScissor); - auto fp = ccpr->makeClipProcessor(opsTaskID, ccprClipPath, fScissor, *fCaps); - fAnalyticFPs.push_back(std::move(fp)); + // Combine the analytic FP with any CCPR clip processors. + std::unique_ptr<GrFragmentProcessor> clipFP = std::move(fAnalyticFP); + + for (const SkPath& ccprClipPath : fCCPRClipPaths) { + SkASSERT(ccpr); + SkASSERT(fHasScissor); + clipFP = ccpr->makeClipProcessor(std::move(clipFP), opsTaskID, ccprClipPath, + fScissor, *fCaps); + } + fCCPRClipPaths.reset(); + + // Create the shader. + std::unique_ptr<GrFragmentProcessor> shaderFP; + if (fShader != nullptr) { + static const GrColorInfo kCoverageColorInfo{GrColorType::kUnknown, kPremul_SkAlphaType, + nullptr}; + GrFPArgs args(context, matrixProvider, kNone_SkFilterQuality, &kCoverageColorInfo); + shaderFP = as_SB(fShader)->asFragmentProcessor(args); + if (shaderFP != nullptr) { + shaderFP = GrFragmentProcessor::SwizzleOutput(std::move(shaderFP), GrSwizzle::AAAA()); } - fCCPRClipPaths.reset(); } - return GrFragmentProcessor::RunInSeries(fAnalyticFPs.begin(), fAnalyticFPs.count()); + // Combine the clip and shader FPs using RunInSeries. (RunInSeries will automatically return the + // input as-is if we only have one.) + SkSTArray<2, std::unique_ptr<GrFragmentProcessor>> seriesFPs; + if (clipFP != nullptr) { + seriesFPs.push_back(std::move(clipFP)); + } + if (shaderFP != nullptr) { + seriesFPs.push_back(std::move(shaderFP)); + } + + return seriesFPs.empty() + ? nullptr + : GrFragmentProcessor::RunInSeries(&seriesFPs.front(), seriesFPs.size()); } + diff --git a/chromium/third_party/skia/src/gpu/GrReducedClip.h b/chromium/third_party/skia/src/gpu/GrReducedClip.h index ca95bd09949..bcc45a0702e 100644 --- a/chromium/third_party/skia/src/gpu/GrReducedClip.h +++ b/chromium/third_party/skia/src/gpu/GrReducedClip.h @@ -53,6 +53,13 @@ public: bool hasScissor() const { return fHasScissor; } /** + * Indicates if there is a clip shader, representing the merge of all shader elements of the + * original stack. + */ + bool hasShader() const { return SkToBool(fShader); } + sk_sp<SkShader> shader() const { SkASSERT(fShader); return fShader; } + + /** * If nonempty, the clip mask is not valid inside these windows and the caller must clip them * out using the window rectangles GPU extension. */ @@ -85,7 +92,7 @@ public: bool drawAlphaClipMask(GrRenderTargetContext*) const; bool drawStencilClipMask(GrRecordingContext*, GrRenderTargetContext*) const; - int numAnalyticFPs() const { return fAnalyticFPs.count() + fCCPRClipPaths.count(); } + int numAnalyticFPs() const; /** * Called once the client knows the ID of the opsTask that the clip FPs will operate in. This @@ -97,6 +104,7 @@ public: * may cause flushes or otherwise change which opsTask the actual draw is going into. */ std::unique_ptr<GrFragmentProcessor> finishAndDetachAnalyticFPs( + GrRecordingContext*, const SkMatrixProvider& matrixProvider, GrCoverageCountingPathRenderer*, uint32_t opsTaskID); private: @@ -144,8 +152,11 @@ private: ElementList fMaskElements; uint32_t fMaskGenID; bool fMaskRequiresAA; - SkSTArray<4, std::unique_ptr<GrFragmentProcessor>> fAnalyticFPs; + std::unique_ptr<GrFragmentProcessor> fAnalyticFP; SkSTArray<4, SkPath> fCCPRClipPaths; // Will convert to FPs once we have an opsTask ID for CCPR. + // Will be the combination of all kShader elements or null if there's no clip shader. + // Does not count against the analytic FP limit. + sk_sp<SkShader> fShader; }; #endif diff --git a/chromium/third_party/skia/src/gpu/GrRenderTargetContext.cpp b/chromium/third_party/skia/src/gpu/GrRenderTargetContext.cpp index 7a53e76afb4..b4617c8ba3d 100644 --- a/chromium/third_party/skia/src/gpu/GrRenderTargetContext.cpp +++ b/chromium/third_party/skia/src/gpu/GrRenderTargetContext.cpp @@ -20,6 +20,7 @@ #include "src/core/SkGlyphRunPainter.h" #include "src/core/SkLatticeIter.h" #include "src/core/SkMatrixPriv.h" +#include "src/core/SkMatrixProvider.h" #include "src/core/SkRRectPriv.h" #include "src/core/SkSurfacePriv.h" #include "src/core/SkYUVMath.h" @@ -28,11 +29,11 @@ #include "src/gpu/GrBlurUtils.h" #include "src/gpu/GrCaps.h" #include "src/gpu/GrClientMappedBufferManager.h" +#include "src/gpu/GrClip.h" #include "src/gpu/GrColor.h" #include "src/gpu/GrContextPriv.h" #include "src/gpu/GrDataUtils.h" #include "src/gpu/GrDrawingManager.h" -#include "src/gpu/GrFixedClip.h" #include "src/gpu/GrGpuResourcePriv.h" #include "src/gpu/GrImageContextPriv.h" #include "src/gpu/GrImageInfo.h" @@ -55,7 +56,6 @@ #include "src/gpu/geometry/GrStyledShape.h" #include "src/gpu/ops/GrAtlasTextOp.h" #include "src/gpu/ops/GrClearOp.h" -#include "src/gpu/ops/GrClearStencilClipOp.h" #include "src/gpu/ops/GrDrawAtlasOp.h" #include "src/gpu/ops/GrDrawOp.h" #include "src/gpu/ops/GrDrawVerticesOp.h" @@ -70,7 +70,8 @@ #include "src/gpu/ops/GrStencilPathOp.h" #include "src/gpu/ops/GrStrokeRectOp.h" #include "src/gpu/ops/GrTextureOp.h" -#include "src/gpu/text/GrTextContext.h" +#include "src/gpu/text/GrSDFTOptions.h" +#include "src/gpu/text/GrTextBlobCache.h" #include "src/gpu/text/GrTextTarget.h" class GrRenderTargetContext::TextTarget : public GrTextTarget { @@ -78,14 +79,13 @@ public: TextTarget(GrRenderTargetContext* renderTargetContext) : GrTextTarget(renderTargetContext->width(), renderTargetContext->height(), renderTargetContext->colorInfo()) - , fRenderTargetContext(renderTargetContext) - , fGlyphPainter{*renderTargetContext} {} + , fRenderTargetContext(renderTargetContext) {} - void addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) override { + void addDrawOp(const GrClip* clip, std::unique_ptr<GrAtlasTextOp> op) override { fRenderTargetContext->addDrawOp(clip, std::move(op)); } - void drawShape(const GrClip& clip, + void drawShape(const GrClip* clip, const SkPaint& paint, const SkMatrixProvider& matrixProvider, const GrStyledShape& shape) override { @@ -112,20 +112,16 @@ public: } SkGlyphRunListPainter* glyphPainter() override { - return &fGlyphPainter; + return fRenderTargetContext->glyphPainter(); } private: GrRenderTargetContext* fRenderTargetContext; - SkGlyphRunListPainter fGlyphPainter; - }; #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext()) -#define ASSERT_SINGLE_OWNER \ - SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());) -#define ASSERT_SINGLE_OWNER_PRIV \ - SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());) +#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(this->singleOwner()) +#define ASSERT_SINGLE_OWNER_PRIV GR_ASSERT_SINGLE_OWNER(fRenderTargetContext->singleOwner()) #define RETURN_IF_ABANDONED if (fContext->priv().abandoned()) { return; } #define RETURN_IF_ABANDONED_PRIV if (fRenderTargetContext->fContext->priv().abandoned()) { return; } #define RETURN_FALSE_IF_ABANDONED if (fContext->priv().abandoned()) { return false; } @@ -296,12 +292,11 @@ std::unique_ptr<GrRenderTargetContext> GrRenderTargetContext::MakeFromBackendTex int sampleCnt, GrSurfaceOrigin origin, const SkSurfaceProps* surfaceProps, - ReleaseProc releaseProc, - ReleaseContext releaseCtx) { + sk_sp<GrRefCntedCallback> releaseHelper) { SkASSERT(sampleCnt > 0); sk_sp<GrTextureProxy> proxy(context->priv().proxyProvider()->wrapRenderableBackendTexture( - tex, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, releaseProc, - releaseCtx)); + tex, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, + std::move(releaseHelper))); if (!proxy) { return nullptr; } @@ -338,8 +333,13 @@ std::unique_ptr<GrRenderTargetContext> GrRenderTargetContext::MakeFromBackendRen const SkSurfaceProps* surfaceProps, ReleaseProc releaseProc, ReleaseContext releaseCtx) { + sk_sp<GrRefCntedCallback> releaseHelper; + if (releaseProc) { + releaseHelper.reset(new GrRefCntedCallback(releaseProc, releaseCtx)); + } + sk_sp<GrSurfaceProxy> proxy( - context->priv().proxyProvider()->wrapBackendRenderTarget(rt, releaseProc, releaseCtx)); + context->priv().proxyProvider()->wrapBackendRenderTarget(rt, std::move(releaseHelper))); if (!proxy) { return nullptr; } @@ -379,9 +379,10 @@ GrRenderTargetContext::GrRenderTargetContext(GrRecordingContext* context, : GrSurfaceContext(context, std::move(readView), colorType, kPremul_SkAlphaType, std::move(colorSpace)) , fWriteView(std::move(writeView)) - , fOpsTask(sk_ref_sp(this->asSurfaceProxy()->getLastOpsTask())) , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps)) - , fManagedOpsTask(managedOpsTask) { + , fManagedOpsTask(managedOpsTask) + , fGlyphPainter(*this) { + fOpsTask = sk_ref_sp(context->priv().drawingManager()->getLastOpsTask(this->asSurfaceProxy())); if (fOpsTask) { fOpsTask->addClosedObserver(this); } @@ -395,7 +396,7 @@ GrRenderTargetContext::GrRenderTargetContext(GrRecordingContext* context, #ifdef SK_DEBUG void GrRenderTargetContext::onValidate() const { if (fOpsTask && !fOpsTask->isClosed()) { - SkASSERT(fWriteView.proxy()->getLastRenderTask() == fOpsTask.get()); + SkASSERT(this->drawingManager()->getLastRenderTask(fWriteView.proxy()) == fOpsTask.get()); } } #endif @@ -448,9 +449,34 @@ GrOpsTask* GrRenderTargetContext::getOpsTask() { return fOpsTask.get(); } -void GrRenderTargetContext::drawGlyphRunList(const GrClip& clip, +static SkColor compute_canonical_color(const SkPaint& paint, bool lcd) { + SkColor canonicalColor = SkPaintPriv::ComputeLuminanceColor(paint); + if (lcd) { + // This is the correct computation for canonicalColor, but there are tons of cases where LCD + // can be modified. For now we just regenerate if any run in a textblob has LCD. + // TODO figure out where all of these modifications are and see if we can incorporate that + // logic at a higher level *OR* use sRGB + //canonicalColor = SkMaskGamma::CanonicalColor(canonicalColor); + + // TODO we want to figure out a way to be able to use the canonical color on LCD text, + // see the note above. We pick a dummy value for LCD text to ensure we always match the + // same key + return SK_ColorTRANSPARENT; + } else { + // A8, though can have mixed BMP text but it shouldn't matter because BMP text won't have + // gamma corrected masks anyways, nor color + U8CPU lum = SkComputeLuminance(SkColorGetR(canonicalColor), + SkColorGetG(canonicalColor), + SkColorGetB(canonicalColor)); + // reduce to our finite number of bits + canonicalColor = SkMaskGamma::CanonicalColor(SkColorSetRGB(lum, lum, lum)); + } + return canonicalColor; +} + +void GrRenderTargetContext::drawGlyphRunList(const GrClip* clip, const SkMatrixProvider& matrixProvider, - const SkGlyphRunList& blob) { + const SkGlyphRunList& glyphRunList) { ASSERT_SINGLE_OWNER RETURN_IF_ABANDONED SkDEBUGCODE(this->validate();) @@ -463,46 +489,83 @@ void GrRenderTargetContext::drawGlyphRunList(const GrClip& clip, return; } - GrTextContext* atlasTextContext = this->drawingManager()->getTextContext(); - atlasTextContext->drawGlyphRunList(fContext, fTextTarget.get(), clip, matrixProvider, - fSurfaceProps, blob); -} + GrSDFTOptions options = fContext->priv().SDFTOptions(); + GrTextBlobCache* textBlobCache = fContext->priv().getTextBlobCache(); -void GrRenderTargetContext::discard() { - ASSERT_SINGLE_OWNER - RETURN_IF_ABANDONED - SkDEBUGCODE(this->validate();) - GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "discard", fContext); + // Get the first paint to use as the key paint. + const SkPaint& blobPaint = glyphRunList.paint(); - AutoCheckFlush acf(this->drawingManager()); + SkPoint drawOrigin = glyphRunList.origin(); - this->getOpsTask()->discard(); + SkMaskFilterBase::BlurRec blurRec; + // It might be worth caching these things, but its not clear at this time + // TODO for animated mask filters, this will fill up our cache. We need a safeguard here + const SkMaskFilter* mf = blobPaint.getMaskFilter(); + bool canCache = glyphRunList.canCache() && + !(blobPaint.getPathEffect() || (mf && !as_MFB(mf)->asABlur(&blurRec))); + + // If we're doing linear blending, then we can disable the gamma hacks. + // Otherwise, leave them on. In either case, we still want the contrast boost: + // TODO: Can we be even smarter about mask gamma based on the dest transfer function? + SkScalerContextFlags scalerContextFlags = this->colorInfo().isLinearlyBlended() + ? SkScalerContextFlags::kBoostContrast + : SkScalerContextFlags::kFakeGammaAndBoostContrast; + + sk_sp<GrTextBlob> blob; + GrTextBlob::Key key; + if (canCache) { + bool hasLCD = glyphRunList.anyRunsLCD(); + + // We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry + SkPixelGeometry pixelGeometry = + hasLCD ? fSurfaceProps.pixelGeometry() : kUnknown_SkPixelGeometry; + + GrColor canonicalColor = compute_canonical_color(blobPaint, hasLCD); + + key.fPixelGeometry = pixelGeometry; + key.fUniqueID = glyphRunList.uniqueID(); + key.fStyle = blobPaint.getStyle(); + key.fHasBlur = SkToBool(mf); + key.fCanonicalColor = canonicalColor; + key.fScalerContextFlags = scalerContextFlags; + blob = textBlobCache->find(key); + } + + const SkMatrix& drawMatrix(matrixProvider.localToDevice()); + if (blob != nullptr && blob->canReuse(blobPaint, blurRec, drawMatrix, drawOrigin)) { + // Reusing the blob. Move it to the front of LRU cache. + textBlobCache->makeMRU(blob.get()); + } else { + // Build or Rebuild the GrTextBlob + if (blob != nullptr) { + // We have to remake the blob because changes may invalidate our masks. + // TODO we could probably get away with reuse most of the time if the pointer is unique, + // but we'd have to clear the SubRun information + textBlobCache->remove(blob.get()); + } + if (canCache) { + blob = textBlobCache->makeCachedBlob(glyphRunList, key, blurRec, drawMatrix); + } else { + blob = GrTextBlob::Make(glyphRunList, drawMatrix); + } + bool supportsSDFT = fContext->priv().caps()->shaderCaps()->supportsDistanceFieldText(); + fGlyphPainter.processGlyphRunList( + glyphRunList, drawMatrix, fSurfaceProps, supportsSDFT, options, blob.get()); + } + + blob->insertOpsIntoTarget( + fTextTarget.get(), fSurfaceProps, blobPaint, clip, matrixProvider, drawOrigin); } -void GrRenderTargetContext::clear(const SkIRect* rect, - const SkPMColor4f& color, - CanClearFullscreen canClearFullscreen) { +void GrRenderTargetContext::discard() { ASSERT_SINGLE_OWNER RETURN_IF_ABANDONED SkDEBUGCODE(this->validate();) - GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "clear", fContext); + GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "discard", fContext); AutoCheckFlush acf(this->drawingManager()); - this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color, - canClearFullscreen); -} -void GrRenderTargetContextPriv::clear(const GrFixedClip& clip, - const SkPMColor4f& color, - CanClearFullscreen canClearFullscreen) { - ASSERT_SINGLE_OWNER_PRIV - RETURN_IF_ABANDONED_PRIV - SkDEBUGCODE(fRenderTargetContext->validate();) - GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clear", - fRenderTargetContext->fContext); - - AutoCheckFlush acf(fRenderTargetContext->drawingManager()); - fRenderTargetContext->internalClear(clip, color, canClearFullscreen); + this->getOpsTask()->discard(); } static void clear_to_grpaint(const SkPMColor4f& color, GrPaint* paint) { @@ -517,21 +580,46 @@ static void clear_to_grpaint(const SkPMColor4f& color, GrPaint* paint) { } } -void GrRenderTargetContext::internalClear(const GrFixedClip& clip, +// NOTE: We currently pass the premul color unmodified to the gpu, since we assume the GrRTC has a +// premul alpha type. If we ever support different alpha type render targets, this function should +// transform the color as appropriate. +void GrRenderTargetContext::internalClear(const SkIRect* scissor, const SkPMColor4f& color, - CanClearFullscreen canClearFullscreen) { - bool isFull = false; - if (!clip.hasWindowRectangles()) { - // TODO: wrt the shouldInitializeTextures path, it would be more performant to - // only clear the entire target if we knew it had not been cleared before. As - // is this could end up doing a lot of redundant clears. - isFull = !clip.scissorEnabled() || - (CanClearFullscreen::kYes == canClearFullscreen && - (this->caps()->preferFullscreenClears() || this->caps()->shouldInitializeTextures())) || - clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height())); - } - - if (isFull) { + bool upgradePartialToFull) { + ASSERT_SINGLE_OWNER + RETURN_IF_ABANDONED + SkDEBUGCODE(this->validate();) + GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "clear", fContext); + + // There are three ways clears are handled: load ops, native clears, and draws. Load ops are + // only for fullscreen clears; native clears can be fullscreen or with scissors if the backend + // supports then. Drawing an axis-aligned rect is the fallback path. + GrScissorState scissorState(this->asSurfaceProxy()->backingStoreDimensions()); + if (scissor && !scissorState.set(*scissor)) { + // The clear is offscreen, so skip it (normally this would be handled by addDrawOp, + // except clear ops are not draw ops). + return; + } + + // If we have a scissor but it's okay to clear beyond it for performance reasons, then disable + // the test. We only do this when the clear would be handled by a load op or natively. + if (scissorState.enabled() && !this->caps()->performColorClearsAsDraws()) { + if (upgradePartialToFull && (this->caps()->preferFullscreenClears() || + this->caps()->shouldInitializeTextures())) { + // TODO: wrt the shouldInitializeTextures path, it would be more performant to + // only clear the entire target if we knew it had not been cleared before. As + // is this could end up doing a lot of redundant clears. + scissorState.setDisabled(); + } else { + // Unlike with stencil clears, we also allow clears up to the logical dimensions of the + // render target to overflow into any approx-fit padding of the backing store dimensions + scissorState.relaxTest(this->dimensions()); + } + } + + if (!scissorState.enabled()) { + // This is a fullscreen clear, so could be handled as a load op. Regardless, we can also + // discard all prior ops in the current task since the color buffer will be overwritten. GrOpsTask* opsTask = this->getOpsTask(); if (opsTask->resetForFullscreenClear(this->canDiscardPreviousOpsOnFullClear()) && !this->caps()->performColorClearsAsDraws()) { @@ -543,43 +631,24 @@ void GrRenderTargetContext::internalClear(const GrFixedClip& clip, // blow away the color buffer contents opsTask->setColorLoadOp(GrLoadOp::kDiscard); } + } - // Must add an op to the list (either because we couldn't use a load op, or because the - // clear load op isn't supported) - if (this->caps()->performColorClearsAsDraws()) { - SkRect rtRect = SkRect::MakeWH(this->width(), this->height()); - GrPaint paint; - clear_to_grpaint(color, &paint); - this->addDrawOp(GrFixedClip::Disabled(), - GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(), - rtRect)); - } else { - this->addOp(GrClearOp::Make( - fContext, SkIRect::MakeEmpty(), color, /* fullscreen */ true)); - } + // At this point we are either a partial clear or a fullscreen clear that couldn't be applied + // as a load op. + bool clearAsDraw = this->caps()->performColorClearsAsDraws() || + (scissorState.enabled() && this->caps()->performPartialClearsAsDraws()); + if (clearAsDraw) { + GrPaint paint; + clear_to_grpaint(color, &paint); + this->addDrawOp(nullptr, + GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(), + SkRect::Make(scissorState.rect()))); } else { - if (this->caps()->performPartialClearsAsDraws()) { - // performPartialClearsAsDraws() also returns true if any clear has to be a draw. - GrPaint paint; - clear_to_grpaint(color, &paint); - - this->addDrawOp(clip, - GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(), - SkRect::Make(clip.scissorRect()))); - } else { - std::unique_ptr<GrOp> op(GrClearOp::Make(fContext, clip, color, - this->asSurfaceProxy())); - // This version of the clear op factory can return null if the clip doesn't intersect - // with the surface proxy's boundary - if (!op) { - return; - } - this->addOp(std::move(op)); - } + this->addOp(GrClearOp::MakeColor(fContext, scissorState, color)); } } -void GrRenderTargetContext::drawPaint(const GrClip& clip, +void GrRenderTargetContext::drawPaint(const GrClip* clip, GrPaint&& paint, const SkMatrix& viewMatrix) { // Start with the render target, since that is the maximum content we could possibly fill. @@ -630,8 +699,12 @@ static bool make_vertex_finite(float* value) { return true; } +static SkIRect get_clip_bounds(const GrRenderTargetContext* rtc, const GrClip* clip) { + return clip ? clip->getConservativeBounds() : SkIRect::MakeWH(rtc->width(), rtc->height()); +} + GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimization( - const GrClip& clip, const SkPMColor4f* constColor, + const GrClip* clip, const SkPMColor4f* constColor, const GrUserStencilSettings* stencilSettings, GrAA* aa, DrawQuad* quad) { // Optimization requirements: // 1. kDiscard applies when clip bounds and quad bounds do not intersect @@ -645,16 +718,9 @@ GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimi // better to just keep the old flags instead of introducing mixed edge flags. GrQuadAAFlags oldFlags = quad->fEdgeFlags; - SkRect rtRect; - if (stencilSettings) { - // Must use size at which the rendertarget will ultimately be allocated so that stencil - // buffer updates on approximately sized render targets don't get corrupted. - rtRect = this->asSurfaceProxy()->backingStoreBoundsRect(); - } else { - // Use the logical size of the render target, which allows for "fullscreen" clears even if - // the render target has an approximate backing fit - rtRect = SkRect::MakeWH(this->width(), this->height()); - } + // Use the logical size of the render target, which allows for "fullscreen" clears even if + // the render target has an approximate backing fit + SkRect rtRect = this->asSurfaceProxy()->getBoundsRect(); SkRect drawBounds = quad->fDevice.bounds(); if (constColor) { @@ -692,8 +758,8 @@ GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimi // regular draws so that if we fully cover the render target, that can stop being anti-aliased. GrAA clipAA = stencilSettings ? *aa : GrAA::kNo; bool axisAlignedClip = true; - if (!clip.quickContains(rtRect)) { - if (!clip.isRRect(rtRect, &clipRRect, &clipAA)) { + if (clip && !clip->quickContains(rtRect)) { + if (!clip->isRRect(&clipRRect, &clipAA)) { axisAlignedClip = false; } } @@ -717,14 +783,14 @@ GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimi drawBounds = quad->fDevice.bounds(); if (drawBounds.contains(rtRect)) { // Fullscreen clear - this->clear(nullptr, *constColor, CanClearFullscreen::kYes); + this->clear(*constColor); return QuadOptimization::kSubmitted; } else if (GrClip::IsPixelAligned(drawBounds) && drawBounds.width() > 256 && drawBounds.height() > 256) { // Scissor + clear (round shouldn't do anything since we are pixel aligned) SkIRect scissorRect; drawBounds.round(&scissorRect); - this->clear(&scissorRect, *constColor, CanClearFullscreen::kNo); + this->clear(scissorRect, *constColor); return QuadOptimization::kSubmitted; } } @@ -759,7 +825,7 @@ GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimi // we can draw the rrect directly and ignore the edge flags GrPaint paint; clear_to_grpaint(*constColor, &paint); - this->drawRRect(GrFixedClip::Disabled(), std::move(paint), clipAA, SkMatrix::I(), + this->drawRRect(nullptr, std::move(paint), clipAA, SkMatrix::I(), clipRRect, GrStyle::SimpleFill()); return QuadOptimization::kSubmitted; } else { @@ -771,7 +837,7 @@ GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimi } // Crop the quad to the conservative bounds of the clip. - SkRect clipBounds = SkRect::Make(clip.getConservativeBounds(rtRect.width(), rtRect.height())); + SkRect clipBounds = SkRect::Make(get_clip_bounds(this, clip)); // One final check for discarding, since we may have gone here directly due to a complex clip if (!clipBounds.intersects(drawBounds)) { @@ -786,7 +852,7 @@ GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimi return QuadOptimization::kCropped; } -void GrRenderTargetContext::drawFilledQuad(const GrClip& clip, +void GrRenderTargetContext::drawFilledQuad(const GrClip* clip, GrPaint&& paint, GrAA aa, DrawQuad* quad, @@ -809,8 +875,7 @@ void GrRenderTargetContext::drawFilledQuad(const GrClip& clip, QuadOptimization opt = this->attemptQuadOptimization(clip, constColor, ss, &aa, quad); if (opt >= QuadOptimization::kClipApplied) { // These optimizations require caller to add an op themselves - const GrClip& finalClip = opt == QuadOptimization::kClipApplied ? GrFixedClip::Disabled() - : clip; + const GrClip* finalClip = opt == QuadOptimization::kClipApplied ? nullptr : clip; GrAAType aaType = ss ? (aa == GrAA::kYes ? GrAAType::kMSAA : GrAAType::kNone) : this->chooseAAType(aa); this->addDrawOp(finalClip, GrFillRectOp::Make(fContext, std::move(paint), aaType, @@ -819,7 +884,7 @@ void GrRenderTargetContext::drawFilledQuad(const GrClip& clip, // All other optimization levels were completely handled inside attempt(), so no extra op needed } -void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip, +void GrRenderTargetContext::drawTexturedQuad(const GrClip* clip, GrSurfaceProxyView proxyView, SkAlphaType srcAlphaType, sk_sp<GrColorSpaceXform> textureXform, @@ -844,8 +909,7 @@ void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip, SkASSERT(opt != QuadOptimization::kSubmitted); if (opt != QuadOptimization::kDiscarded) { // And the texture op if not discarded - const GrClip& finalClip = opt == QuadOptimization::kClipApplied ? GrFixedClip::Disabled() - : clip; + const GrClip* finalClip = opt == QuadOptimization::kClipApplied ? nullptr : clip; GrAAType aaType = this->chooseAAType(aa); auto clampType = GrColorTypeClampType(this->colorInfo().colorType()); auto saturate = clampType == GrClampType::kManual ? GrTextureOp::Saturate::kYes @@ -859,7 +923,7 @@ void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip, } } -void GrRenderTargetContext::drawRect(const GrClip& clip, +void GrRenderTargetContext::drawRect(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, @@ -904,7 +968,7 @@ void GrRenderTargetContext::drawRect(const GrClip& clip, GrStyledShape(rect, *style)); } -void GrRenderTargetContext::drawQuadSet(const GrClip& clip, GrPaint&& paint, GrAA aa, +void GrRenderTargetContext::drawQuadSet(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, const QuadSetEntry quads[], int cnt) { GrAAType aaType = this->chooseAAType(aa); @@ -956,7 +1020,7 @@ void GrRenderTargetContext::setNeedsStencil(bool useMixedSamplesIfNotMSAA) { if (this->caps()->performStencilClearsAsDraws()) { // There is a driver bug with clearing stencil. We must use an op to manually clear the // stencil buffer before the op that required 'setNeedsStencil'. - this->internalStencilClear(GrFixedClip::Disabled(), /* inside mask */ false); + this->internalStencilClear(nullptr, /* inside mask */ false); } else { this->getOpsTask()->setInitialStencilContent( GrOpsTask::StencilContent::kUserBitsCleared); @@ -964,41 +1028,32 @@ void GrRenderTargetContext::setNeedsStencil(bool useMixedSamplesIfNotMSAA) { } } -void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) { - ASSERT_SINGLE_OWNER_PRIV - RETURN_IF_ABANDONED_PRIV - SkDEBUGCODE(fRenderTargetContext->validate();) - GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clearStencilClip", - fRenderTargetContext->fContext); - - AutoCheckFlush acf(fRenderTargetContext->drawingManager()); - - fRenderTargetContext->internalStencilClear(clip, insideStencilMask); -} - -void GrRenderTargetContext::internalStencilClear(const GrFixedClip& clip, bool insideStencilMask) { +void GrRenderTargetContext::internalStencilClear(const SkIRect* scissor, bool insideStencilMask) { this->setNeedsStencil(/* useMixedSamplesIfNotMSAA = */ false); - if (this->caps()->performStencilClearsAsDraws()) { + GrScissorState scissorState(this->asSurfaceProxy()->backingStoreDimensions()); + if (scissor && !scissorState.set(*scissor)) { + // The requested clear region is off screen, so nothing to do. + return; + } + + bool clearWithDraw = this->caps()->performStencilClearsAsDraws() || + (scissorState.enabled() && this->caps()->performPartialClearsAsDraws()); + if (clearWithDraw) { const GrUserStencilSettings* ss = GrStencilSettings::SetClipBitSettings(insideStencilMask); - SkRect rtRect = SkRect::MakeWH(this->width(), this->height()); // Configure the paint to have no impact on the color buffer GrPaint paint; paint.setXPFactory(GrDisableColorXPFactory::Get()); - this->addDrawOp(clip, GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(), - rtRect, ss)); + this->addDrawOp(nullptr, + GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(), + SkRect::Make(scissorState.rect()), ss)); } else { - std::unique_ptr<GrOp> op(GrClearStencilClipOp::Make(fContext, clip, insideStencilMask, - this->asRenderTargetProxy())); - if (!op) { - return; - } - this->addOp(std::move(op)); + this->addOp(GrClearOp::MakeStencilClip(fContext, scissorState, insideStencilMask)); } } -void GrRenderTargetContextPriv::stencilPath(const GrHardClip& clip, +void GrRenderTargetContextPriv::stencilPath(const GrHardClip* clip, GrAA doStencilMSAA, const SkMatrix& viewMatrix, sk_sp<const GrPath> path) { @@ -1016,12 +1071,18 @@ void GrRenderTargetContextPriv::stencilPath(const GrHardClip& clip, // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved. SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height()); - // Setup clip - GrAppliedHardClip appliedClip; - if (!clip.apply(fRenderTargetContext->width(), fRenderTargetContext->height(), &appliedClip, - &bounds)) { + // Setup clip and reject offscreen paths; we do this explicitly instead of relying on addDrawOp + // because GrStencilPathOp is not a draw op as its state depends directly on the choices made + // during this clip application. + GrAppliedHardClip appliedClip(fRenderTargetContext->dimensions(), + fRenderTargetContext->asSurfaceProxy()->backingStoreDimensions()); + + if (clip && !clip->apply(&appliedClip, &bounds)) { return; } + // else see FIXME above; we'd normally want to check path bounds with render target bounds, + // but as it is, we're just using the full render target so intersecting the two bounds would + // do nothing. std::unique_ptr<GrOp> op = GrStencilPathOp::Make(fRenderTargetContext->fContext, viewMatrix, @@ -1038,7 +1099,7 @@ void GrRenderTargetContextPriv::stencilPath(const GrHardClip& clip, fRenderTargetContext->addOp(std::move(op)); } -void GrRenderTargetContext::drawTextureSet(const GrClip& clip, TextureSetEntry set[], +void GrRenderTargetContext::drawTextureSet(const GrClip* clip, TextureSetEntry set[], int cnt, int proxyRunCnt, GrSamplerState::Filter filter, SkBlendMode mode, GrAA aa, SkCanvas::SrcRectConstraint constraint, @@ -1060,7 +1121,7 @@ void GrRenderTargetContext::drawTextureSet(const GrClip& clip, TextureSetEntry s mode, aaType, constraint, viewMatrix, std::move(texXform)); } -void GrRenderTargetContext::drawVertices(const GrClip& clip, +void GrRenderTargetContext::drawVertices(const GrClip* clip, GrPaint&& paint, const SkMatrixProvider& matrixProvider, sk_sp<SkVertices> vertices, @@ -1084,7 +1145,7 @@ void GrRenderTargetContext::drawVertices(const GrClip& clip, /////////////////////////////////////////////////////////////////////////////// -void GrRenderTargetContext::drawAtlas(const GrClip& clip, +void GrRenderTargetContext::drawAtlas(const GrClip* clip, GrPaint&& paint, const SkMatrix& viewMatrix, int spriteCount, @@ -1106,7 +1167,7 @@ void GrRenderTargetContext::drawAtlas(const GrClip& clip, /////////////////////////////////////////////////////////////////////////////// -void GrRenderTargetContext::drawRRect(const GrClip& origClip, +void GrRenderTargetContext::drawRRect(const GrClip* origClip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, @@ -1122,8 +1183,7 @@ void GrRenderTargetContext::drawRRect(const GrClip& origClip, return; } - GrNoClip noclip; - const GrClip* clip = &origClip; + const GrClip* clip = origClip; #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK // The Android framework frequently clips rrects to themselves where the clip is non-aa and the // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it @@ -1132,9 +1192,9 @@ void GrRenderTargetContext::drawRRect(const GrClip& origClip, // can be ignored. We'd prefer to fix this in the framework by removing the clips calls. This // only works for filled rrects since the stroke width outsets beyond the rrect itself. SkRRect devRRect; - if (stroke.getStyle() == SkStrokeRec::kFill_Style && rrect.transform(viewMatrix, &devRRect) && - clip->quickContains(devRRect)) { - clip = &noclip; + if (clip && stroke.getStyle() == SkStrokeRec::kFill_Style && + rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) { + clip = nullptr; } #endif SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice @@ -1163,12 +1223,12 @@ void GrRenderTargetContext::drawRRect(const GrClip& origClip, fContext, std::move(paint), viewMatrix, rrect, stroke, this->caps()->shaderCaps()); } if (op) { - this->addDrawOp(*clip, std::move(op)); + this->addDrawOp(clip, std::move(op)); return; } assert_alive(paint); - this->drawShapeUsingPathRenderer(*clip, std::move(paint), aa, viewMatrix, + this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrStyledShape(rrect, style)); } @@ -1181,7 +1241,7 @@ static SkPoint3 map(const SkMatrix& m, const SkPoint3& pt) { return result; } -bool GrRenderTargetContext::drawFastShadow(const GrClip& clip, +bool GrRenderTargetContext::drawFastShadow(const GrClip* clip, const SkMatrix& viewMatrix, const SkPath& path, const SkDrawShadowRec& rec) { @@ -1376,7 +1436,7 @@ bool GrRenderTargetContext::drawFastShadow(const GrClip& clip, /////////////////////////////////////////////////////////////////////////////// -bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip, +bool GrRenderTargetContext::drawFilledDRRect(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, @@ -1442,18 +1502,17 @@ bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip, const auto& caps = *this->caps()->shaderCaps(); // TODO these need to be a geometry processors - auto innerEffect = GrRRectEffect::Make(innerEdgeType, *inner, caps); - if (!innerEffect) { + auto [success, fp] = GrRRectEffect::Make(/*inputFP=*/nullptr, innerEdgeType, *inner, caps); + if (!success) { return false; } - auto outerEffect = GrRRectEffect::Make(outerEdgeType, *outer, caps); - if (!outerEffect) { + std::tie(success, fp) = GrRRectEffect::Make(std::move(fp), outerEdgeType, *outer, caps); + if (!success) { return false; } - paint.addCoverageFragmentProcessor(std::move(innerEffect)); - paint.addCoverageFragmentProcessor(std::move(outerEffect)); + paint.addCoverageFragmentProcessor(std::move(fp)); SkRect bounds = outer->getBounds(); if (GrAAType::kCoverage == aaType) { @@ -1465,7 +1524,7 @@ bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip, return true; } -void GrRenderTargetContext::drawDRRect(const GrClip& clip, +void GrRenderTargetContext::drawDRRect(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, @@ -1496,7 +1555,7 @@ void GrRenderTargetContext::drawDRRect(const GrClip& clip, /////////////////////////////////////////////////////////////////////////////// -void GrRenderTargetContext::drawRegion(const GrClip& clip, +void GrRenderTargetContext::drawRegion(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, @@ -1532,7 +1591,7 @@ void GrRenderTargetContext::drawRegion(const GrClip& clip, this->addDrawOp(clip, std::move(op)); } -void GrRenderTargetContext::drawOval(const GrClip& clip, +void GrRenderTargetContext::drawOval(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, @@ -1593,7 +1652,7 @@ void GrRenderTargetContext::drawOval(const GrClip& clip, GrStyledShape(SkRRect::MakeOval(oval), SkPathDirection::kCW, 2, false, style)); } -void GrRenderTargetContext::drawArc(const GrClip& clip, +void GrRenderTargetContext::drawArc(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, @@ -1632,7 +1691,7 @@ void GrRenderTargetContext::drawArc(const GrClip& clip, GrStyledShape::MakeArc(oval, startAngle, sweepAngle, useCenter, style)); } -void GrRenderTargetContext::drawImageLattice(const GrClip& clip, +void GrRenderTargetContext::drawImageLattice(const GrClip* clip, GrPaint&& paint, const SkMatrix& viewMatrix, GrSurfaceProxyView view, @@ -1711,7 +1770,8 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels( int x = srcRect.fLeft; int y = srcRect.fTop; if (needsRescale) { - tempRTC = this->rescale(info, srcRect, rescaleGamma, rescaleQuality); + tempRTC = this->rescale(info, kTopLeft_GrSurfaceOrigin, srcRect, rescaleGamma, + rescaleQuality); if (!tempRTC) { callback(context, nullptr); return; @@ -1754,7 +1814,7 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels( callback(context, nullptr); return; } - tempRTC->drawTexture(GrNoClip(), std::move(texProxyView), this->colorInfo().alphaType(), + tempRTC->drawTexture(nullptr, std::move(texProxyView), this->colorInfo().alphaType(), GrSamplerState::Filter::kNearest, SkBlendMode::kSrc, SK_PMColor4fWHITE, srcRectToDraw, SkRect::MakeWH(srcRect.width(), srcRect.height()), GrAA::kNo, @@ -1899,7 +1959,7 @@ void GrRenderTargetContext::asyncReadPixels(const SkIRect& rect, SkColorType col GrFlushInfo flushInfo; flushInfo.fFinishedContext = finishContext; flushInfo.fFinishedProc = finishCallback; - this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo); + this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo, nullptr); } void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, @@ -1941,7 +2001,8 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC auto info = SkImageInfo::Make(dstSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType, dstColorSpace); // TODO: Incorporate the YUV conversion into last pass of rescaling. - auto tempRTC = this->rescale(info, srcRect, rescaleGamma, rescaleQuality); + auto tempRTC = this->rescale(info, kTopLeft_GrSurfaceOrigin, srcRect, rescaleGamma, + rescaleQuality); if (!tempRTC) { callback(context, nullptr); return; @@ -1976,7 +2037,7 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC callback(context, nullptr); return; } - tempRTC->drawTexture(GrNoClip(), std::move(srcView), this->colorInfo().alphaType(), + tempRTC->drawTexture(nullptr, std::move(srcView), this->colorInfo().alphaType(), GrSamplerState::Filter::kNearest, SkBlendMode::kSrc, SK_PMColor4fWHITE, srcRectToDraw, SkRect::Make(srcRect.size()), GrAA::kNo, GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint, @@ -2008,7 +2069,7 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC // TODO: Use one transfer buffer for all three planes to reduce map/unmap cost? - auto texMatrix = SkMatrix::MakeTrans(x, y); + auto texMatrix = SkMatrix::Translate(x, y); SkRect dstRectY = SkRect::Make(dstSize); SkRect dstRectUV = SkRect::MakeWH(halfW, halfH); @@ -2021,12 +2082,14 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC std::fill_n(yM, 15, 0.f); std::copy_n(baseM + 0, 5, yM + 15); GrPaint yPaint; - yPaint.addColorFragmentProcessor( - GrTextureEffect::Make(srcView, this->colorInfo().alphaType(), texMatrix)); - auto yFP = GrColorMatrixFragmentProcessor::Make(yM, false, true, false); - yPaint.addColorFragmentProcessor(std::move(yFP)); + auto yTexFP = GrTextureEffect::Make(srcView, this->colorInfo().alphaType(), texMatrix); + auto yColFP = GrColorMatrixFragmentProcessor::Make(std::move(yTexFP), yM, + /*unpremulInput=*/false, + /*clampRGBOutput=*/true, + /*premulOutput=*/false); + yPaint.addColorFragmentProcessor(std::move(yColFP)); yPaint.setPorterDuffXPFactory(SkBlendMode::kSrc); - yRTC->fillRectToRect(GrNoClip(), std::move(yPaint), GrAA::kNo, SkMatrix::I(), + yRTC->fillRectToRect(nullptr, std::move(yPaint), GrAA::kNo, SkMatrix::I(), dstRectY, dstRectY); if (!doSynchronousRead) { yTransfer = yRTC->transferPixels(GrColorType::kAlpha_8, @@ -2043,12 +2106,15 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC std::fill_n(uM, 15, 0.f); std::copy_n(baseM + 5, 5, uM + 15); GrPaint uPaint; - uPaint.addColorFragmentProcessor(GrTextureEffect::Make( - srcView, this->colorInfo().alphaType(), texMatrix, GrSamplerState::Filter::kBilerp)); - auto uFP = GrColorMatrixFragmentProcessor::Make(uM, false, true, false); - uPaint.addColorFragmentProcessor(std::move(uFP)); + auto uTexFP = GrTextureEffect::Make(srcView, this->colorInfo().alphaType(), texMatrix, + GrSamplerState::Filter::kBilerp); + auto uColFP = GrColorMatrixFragmentProcessor::Make(std::move(uTexFP), uM, + /*unpremulInput=*/false, + /*clampRGBOutput=*/true, + /*premulOutput=*/false); + uPaint.addColorFragmentProcessor(std::move(uColFP)); uPaint.setPorterDuffXPFactory(SkBlendMode::kSrc); - uRTC->fillRectToRect(GrNoClip(), std::move(uPaint), GrAA::kNo, SkMatrix::I(), + uRTC->fillRectToRect(nullptr, std::move(uPaint), GrAA::kNo, SkMatrix::I(), dstRectUV, dstRectUV); if (!doSynchronousRead) { uTransfer = uRTC->transferPixels(GrColorType::kAlpha_8, @@ -2064,13 +2130,15 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC std::fill_n(vM, 15, 0.f); std::copy_n(baseM + 10, 5, vM + 15); GrPaint vPaint; - vPaint.addColorFragmentProcessor(GrTextureEffect::Make(std::move(srcView), - this->colorInfo().alphaType(), texMatrix, - GrSamplerState::Filter::kBilerp)); - auto vFP = GrColorMatrixFragmentProcessor::Make(vM, false, true, false); - vPaint.addColorFragmentProcessor(std::move(vFP)); + auto vTexFP = GrTextureEffect::Make(std::move(srcView), this->colorInfo().alphaType(), + texMatrix, GrSamplerState::Filter::kBilerp); + auto vColFP = GrColorMatrixFragmentProcessor::Make(std::move(vTexFP), vM, + /*unpremulInput=*/false, + /*clampRGBOutput=*/true, + /*premulOutput=*/false); + vPaint.addColorFragmentProcessor(std::move(vColFP)); vPaint.setPorterDuffXPFactory(SkBlendMode::kSrc); - vRTC->fillRectToRect(GrNoClip(), std::move(vPaint), GrAA::kNo, SkMatrix::I(), + vRTC->fillRectToRect(nullptr, std::move(vPaint), GrAA::kNo, SkMatrix::I(), dstRectUV, dstRectUV); if (!doSynchronousRead) { vTransfer = vRTC->transferPixels(GrColorType::kAlpha_8, @@ -2150,19 +2218,26 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC GrFlushInfo flushInfo; flushInfo.fFinishedContext = finishContext; flushInfo.fFinishedProc = finishCallback; - this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo); + this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo, nullptr); } GrSemaphoresSubmitted GrRenderTargetContext::flush(SkSurface::BackendSurfaceAccess access, - const GrFlushInfo& info) { + const GrFlushInfo& info, + const GrBackendSurfaceMutableState* newState) { ASSERT_SINGLE_OWNER if (fContext->priv().abandoned()) { + if (info.fSubmittedProc) { + info.fSubmittedProc(info.fSubmittedContext, false); + } + if (info.fFinishedProc) { + info.fFinishedProc(info.fFinishedContext); + } return GrSemaphoresSubmitted::kNo; } SkDEBUGCODE(this->validate();) GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "flush", fContext); - return this->drawingManager()->flushSurface(this->asSurfaceProxy(), access, info); + return this->drawingManager()->flushSurface(this->asSurfaceProxy(), access, info, newState); } bool GrRenderTargetContext::waitOnSemaphores(int numSemaphores, @@ -2197,7 +2272,7 @@ bool GrRenderTargetContext::waitOnSemaphores(int numSemaphores, return true; } -void GrRenderTargetContext::drawPath(const GrClip& clip, +void GrRenderTargetContext::drawPath(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, @@ -2213,7 +2288,7 @@ void GrRenderTargetContext::drawPath(const GrClip& clip, this->drawShape(clip, std::move(paint), aa, viewMatrix, shape); } -void GrRenderTargetContext::drawShape(const GrClip& clip, +void GrRenderTargetContext::drawShape(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, @@ -2271,7 +2346,7 @@ void GrRenderTargetContext::drawShape(const GrClip& clip, /* attempt fallback */ false); } -bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip, +bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip* clip, const GrUserStencilSettings* ss, SkRegion::Op op, bool invert, @@ -2302,8 +2377,7 @@ bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip, GrAAType aaType = fRenderTargetContext->chooseAAType(aa); bool hasUserStencilSettings = !ss->isUnused(); - SkIRect clipConservativeBounds = clip.getConservativeBounds(fRenderTargetContext->width(), - fRenderTargetContext->height()); + SkIRect clipConservativeBounds = get_clip_bounds(fRenderTargetContext, clip); GrPaint paint; paint.setCoverageSetOpXPFactory(op, invert); @@ -2332,7 +2406,7 @@ bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip, std::move(paint), ss, fRenderTargetContext, - &clip, + clip, &clipConservativeBounds, &viewMatrix, &shape, @@ -2354,7 +2428,7 @@ SkBudgeted GrRenderTargetContextPriv::isBudgeted() const { return fRenderTargetContext->asSurfaceProxy()->isBudgeted(); } -void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip& clip, +void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, @@ -2376,7 +2450,7 @@ void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip& clip, return; } - SkIRect clipConservativeBounds = clip.getConservativeBounds(this->width(), this->height()); + SkIRect clipConservativeBounds = get_clip_bounds(this, clip); GrStyledShape tempShape; GrAAType aaType = this->chooseAAType(aa); @@ -2441,7 +2515,7 @@ void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip& clip, std::move(paint), &GrUserStencilSettings::kUnused, this, - &clip, + clip, &clipConservativeBounds, &viewMatrix, canDrawArgs.fShape, @@ -2477,11 +2551,12 @@ static void op_bounds(SkRect* bounds, const GrOp* op) { } void GrRenderTargetContext::addOp(std::unique_ptr<GrOp> op) { - this->getOpsTask()->addOp( - std::move(op), GrTextureResolveManager(this->drawingManager()), *this->caps()); + GrDrawingManager* drawingMgr = this->drawingManager(); + this->getOpsTask()->addOp(drawingMgr, + std::move(op), GrTextureResolveManager(drawingMgr), *this->caps()); } -void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op, +void GrRenderTargetContext::addDrawOp(const GrClip* clip, std::unique_ptr<GrDrawOp> op, const std::function<WillAddOpFn>& willAddFn) { ASSERT_SINGLE_OWNER if (fContext->priv().abandoned()) { @@ -2495,7 +2570,7 @@ void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDraw // Setup clip SkRect bounds; op_bounds(&bounds, op.get()); - GrAppliedClip appliedClip; + GrAppliedClip appliedClip(this->dimensions(), this->asSurfaceProxy()->backingStoreDimensions()); GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags(); bool usesHWAA = fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA; bool usesUserStencilBits = fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil; @@ -2504,7 +2579,20 @@ void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDraw this->setNeedsStencil(usesHWAA); } - if (!clip.apply(fContext, this, usesHWAA, usesUserStencilBits, &appliedClip, &bounds)) { + bool skipDraw = false; + if (clip) { + // Have a complex clip, so defer to its early clip culling + if (!clip->apply(fContext, this, usesHWAA, usesUserStencilBits, &appliedClip, &bounds)) { + skipDraw = true; + } + } else { + // No clipping, so just clip the bounds against the logical render target dimensions + if (!bounds.intersect(this->asSurfaceProxy()->getBoundsRect())) { + skipDraw = true; + } + } + + if (skipDraw) { fContext->priv().opMemoryPool()->release(std::move(op)); return; } @@ -2524,24 +2612,26 @@ void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDraw GrProcessorSet::Analysis analysis = op->finalize( *this->caps(), &appliedClip, hasMixedSampledCoverage, clampType); + // Must be called before setDstProxyView so that it sees the final bounds of the op. + op->setClippedBounds(bounds); + GrXferProcessor::DstProxyView dstProxyView; if (analysis.requiresDstTexture()) { - if (!this->setupDstProxyView(clip, *op, &dstProxyView)) { + if (!this->setupDstProxyView(*op, &dstProxyView)) { fContext->priv().opMemoryPool()->release(std::move(op)); return; } } - op->setClippedBounds(bounds); auto opsTask = this->getOpsTask(); if (willAddFn) { willAddFn(op.get(), opsTask->uniqueID()); } - opsTask->addDrawOp(std::move(op), analysis, std::move(appliedClip), dstProxyView, - GrTextureResolveManager(this->drawingManager()), *this->caps()); + opsTask->addDrawOp(this->drawingManager(), std::move(op), analysis, std::move(appliedClip), + dstProxyView,GrTextureResolveManager(this->drawingManager()), *this->caps()); } -bool GrRenderTargetContext::setupDstProxyView(const GrClip& clip, const GrOp& op, +bool GrRenderTargetContext::setupDstProxyView(const GrOp& op, GrXferProcessor::DstProxyView* dstProxyView) { // If we are wrapping a vulkan secondary command buffer, we can't make a dst copy because we // don't actually have a VkImage to make a copy of. Additionally we don't have the power to @@ -2561,37 +2651,20 @@ bool GrRenderTargetContext::setupDstProxyView(const GrClip& clip, const GrOp& op } } - SkIRect copyRect = SkIRect::MakeSize(this->asSurfaceProxy()->dimensions()); - - SkIRect clippedRect = clip.getConservativeBounds(this->width(), this->height()); - SkRect opBounds = op.bounds(); - // If the op has aa bloating or is a infinitely thin geometry (hairline) outset the bounds by - // 0.5 pixels. - if (op.hasAABloat() || op.hasZeroArea()) { - opBounds.outset(0.5f, 0.5f); - // An antialiased/hairline draw can sometimes bleed outside of the clips bounds. For - // performance we may ignore the clip when the draw is entirely inside the clip is float - // space but will hit pixels just outside the clip when actually rasterizing. - clippedRect.outset(1, 1); - clippedRect.intersect(SkIRect::MakeSize(this->asSurfaceProxy()->dimensions())); - } - SkIRect opIBounds; - opBounds.roundOut(&opIBounds); - if (!clippedRect.intersect(opIBounds)) { -#ifdef SK_DEBUG - GrCapsDebugf(this->caps(), "setupDstTexture: Missed an early reject bailing on draw."); -#endif - return false; - } - GrColorType colorType = this->colorInfo().colorType(); // MSAA consideration: When there is support for reading MSAA samples in the shader we could // have per-sample dst values by making the copy multisampled. GrCaps::DstCopyRestrictions restrictions = this->caps()->getDstCopyRestrictions( this->asRenderTargetProxy(), colorType); + SkIRect copyRect = SkIRect::MakeSize(this->asSurfaceProxy()->backingStoreDimensions()); if (!restrictions.fMustCopyWholeSrc) { - copyRect = clippedRect; + // If we don't need the whole source, restrict to the op's bounds. We add an extra pixel + // of padding to account for AA bloat and the unpredictable rounding of coords near pixel + // centers during rasterization. + SkIRect conservativeDrawBounds = op.bounds().roundOut(); + conservativeDrawBounds.outset(1, 1); + SkAssertResult(copyRect.intersect(conservativeDrawBounds)); } SkIPoint dstOffset; @@ -2633,7 +2706,7 @@ bool GrRenderTargetContext::blitTexture(GrSurfaceProxyView view, const SkIRect& paint.addColorFragmentProcessor(std::move(fp)); this->fillRectToRect( - GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), + nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(), SkRect::MakeXYWH(clippedDstPoint.fX, clippedDstPoint.fY, clippedSrcRect.width(), clippedSrcRect.height()), SkRect::Make(clippedSrcRect)); diff --git a/chromium/third_party/skia/src/gpu/GrRenderTargetContext.h b/chromium/third_party/skia/src/gpu/GrRenderTargetContext.h index ca0ac266de0..350461b081a 100644 --- a/chromium/third_party/skia/src/gpu/GrRenderTargetContext.h +++ b/chromium/third_party/skia/src/gpu/GrRenderTargetContext.h @@ -14,6 +14,7 @@ #include "include/core/SkSurface.h" #include "include/core/SkSurfaceProps.h" #include "include/private/GrTypesPriv.h" +#include "src/core/SkGlyphRunPainter.h" #include "src/gpu/GrOpsTask.h" #include "src/gpu/GrPaint.h" #include "src/gpu/GrRenderTargetProxy.h" @@ -28,7 +29,6 @@ class GrClip; class GrColorSpaceXform; class GrCoverageCountingPathRenderer; class GrDrawOp; -class GrFixedClip; class GrOp; class GrRenderTarget; class GrRenderTargetContextPriv; @@ -118,8 +118,8 @@ public: // Creates a GrRenderTargetContext that wraps the passed in GrBackendTexture. static std::unique_ptr<GrRenderTargetContext> MakeFromBackendTexture( GrRecordingContext*, GrColorType, sk_sp<SkColorSpace>, const GrBackendTexture&, - int sampleCnt, GrSurfaceOrigin, const SkSurfaceProps*, ReleaseProc releaseProc, - ReleaseContext releaseCtx); + int sampleCnt, GrSurfaceOrigin, const SkSurfaceProps*, + sk_sp<GrRefCntedCallback> releaseHelper); static std::unique_ptr<GrRenderTargetContext> MakeFromBackendTextureAsRenderTarget( GrRecordingContext*, GrColorType, sk_sp<SkColorSpace>, const GrBackendTexture&, @@ -140,7 +140,7 @@ public: ~GrRenderTargetContext() override; - virtual void drawGlyphRunList(const GrClip&, const SkMatrixProvider&, const SkGlyphRunList&); + virtual void drawGlyphRunList(const GrClip*, const SkMatrixProvider&, const SkGlyphRunList&); /** * Provides a perfomance hint that the render target's contents are allowed @@ -148,28 +148,23 @@ public: */ void discard(); - enum class CanClearFullscreen : bool { - kNo = false, - kYes = true - }; - /** - * Clear the entire or rect of the render target, ignoring any clips. - * @param rect the rect to clear or the whole thing if rect is NULL. + * Clear the rect of the render target to the given color. + * @param rect the rect to clear to * @param color the color to clear to. - * @param CanClearFullscreen allows partial clears to be converted to fullscreen clears on - * tiling platforms where that is an optimization. */ - void clear(const SkIRect* rect, const SkPMColor4f& color, CanClearFullscreen); - + void clear(const SkIRect& rect, const SkPMColor4f& color) { + this->internalClear(&rect, color); + } + // Clears the entire render target to the color. void clear(const SkPMColor4f& color) { - return this->clear(nullptr, color, CanClearFullscreen::kYes); + this->internalClear(nullptr, color); } /** * Draw everywhere (respecting the clip) with the paint. */ - void drawPaint(const GrClip&, GrPaint&&, const SkMatrix& viewMatrix); + void drawPaint(const GrClip*, GrPaint&&, const SkMatrix& viewMatrix); /** * Draw the rect using a paint. @@ -180,7 +175,7 @@ public: * allowed. * The rects coords are used to access the paint (through texture matrix) */ - void drawRect(const GrClip&, + void drawRect(const GrClip*, GrPaint&& paint, GrAA, const SkMatrix& viewMatrix, @@ -196,7 +191,7 @@ public: * @param rectToDraw the rectangle to draw * @param localRect the rectangle of shader coordinates applied to rectToDraw */ - void fillRectToRect(const GrClip& clip, + void fillRectToRect(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, @@ -210,7 +205,7 @@ public: /** * Fills a rect with a paint and a localMatrix. */ - void fillRectWithLocalMatrix(const GrClip& clip, + void fillRectWithLocalMatrix(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, @@ -228,7 +223,7 @@ public: * This is a specialized version of fillQuadWithEdgeAA, but is kept separate since knowing * the geometry is a rectangle affords more optimizations. */ - void fillRectWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrAA aa, GrQuadAAFlags edgeAA, + void fillRectWithEdgeAA(const GrClip* clip, GrPaint&& paint, GrAA aa, GrQuadAAFlags edgeAA, const SkMatrix& viewMatrix, const SkRect& rect, const SkRect* optionalLocalRect = nullptr) { const SkRect& localRect = optionalLocalRect ? *optionalLocalRect : rect; @@ -248,7 +243,7 @@ public: * The last argument, 'optionalLocalQuad', can be null if no separate local coordinates are * necessary. */ - void fillQuadWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrAA aa, GrQuadAAFlags edgeAA, + void fillQuadWithEdgeAA(const GrClip* clip, GrPaint&& paint, GrAA aa, GrQuadAAFlags edgeAA, const SkMatrix& viewMatrix, const SkPoint points[4], const SkPoint optionalLocalPoints[4]) { const SkPoint* localPoints = optionalLocalPoints ? optionalLocalPoints : points; @@ -266,7 +261,7 @@ public: }; // TODO(michaelludwig) - remove if the bulk API is not useful for SkiaRenderer - void drawQuadSet(const GrClip& clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, + void drawQuadSet(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, const QuadSetEntry[], int cnt); /** @@ -275,7 +270,7 @@ public: * specifies the rectangle to draw in local coords which will be transformed by 'viewMatrix' to * device space. */ - void drawTexture(const GrClip& clip, GrSurfaceProxyView view, SkAlphaType srcAlphaType, + void drawTexture(const GrClip* clip, GrSurfaceProxyView view, SkAlphaType srcAlphaType, GrSamplerState::Filter filter, SkBlendMode mode, const SkPMColor4f& color, const SkRect& srcRect, const SkRect& dstRect, GrAA aa, GrQuadAAFlags edgeAA, SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix, @@ -294,7 +289,7 @@ public: * 'subset' is null, it's equivalent to using the fast src rect constraint. If 'subset' is * provided, the strict src rect constraint is applied using 'subset'. */ - void drawTextureQuad(const GrClip& clip, GrSurfaceProxyView view, GrColorType srcColorType, + void drawTextureQuad(const GrClip* clip, GrSurfaceProxyView view, GrColorType srcColorType, SkAlphaType srcAlphaType, GrSamplerState::Filter filter, SkBlendMode mode, const SkPMColor4f& color, const SkPoint srcQuad[4], const SkPoint dstQuad[4], GrAA aa, GrQuadAAFlags edgeAA, @@ -314,7 +309,7 @@ public: SkRect fDstRect; const SkPoint* fDstClipQuad; // Must be null, or point to an array of 4 points const SkMatrix* fPreViewMatrix; // If not null, entry's CTM is 'viewMatrix' * fPreViewMatrix - float fAlpha; + SkPMColor4f fColor; // {a,a,a,a} for rgb textures, {r,g,b,a} for alpha-only textures GrQuadAAFlags fAAFlags; }; /** @@ -328,7 +323,7 @@ public: * can be inferred from the array within this function, but the information is already known * by SkGpuDevice, so no need to incur another iteration over the array. */ - void drawTextureSet(const GrClip&, TextureSetEntry[], int cnt, int proxyRunCnt, + void drawTextureSet(const GrClip*, TextureSetEntry[], int cnt, int proxyRunCnt, GrSamplerState::Filter, SkBlendMode mode, GrAA aa, SkCanvas::SrcRectConstraint, const SkMatrix& viewMatrix, sk_sp<GrColorSpaceXform> texXform); @@ -342,7 +337,7 @@ public: * @param rrect the roundrect to draw * @param style style to apply to the rrect. Currently path effects are not allowed. */ - void drawRRect(const GrClip&, + void drawRRect(const GrClip*, GrPaint&&, GrAA, const SkMatrix& viewMatrix, @@ -357,7 +352,7 @@ public: * @param path the path to shadow * @param rec parameters for shadow rendering */ - bool drawFastShadow(const GrClip&, + bool drawFastShadow(const GrClip*, const SkMatrix& viewMatrix, const SkPath& path, const SkDrawShadowRec& rec); @@ -372,7 +367,7 @@ public: * @param outer the outer roundrect * @param inner the inner roundrect */ - void drawDRRect(const GrClip&, + void drawDRRect(const GrClip*, GrPaint&&, GrAA, const SkMatrix& viewMatrix, @@ -388,7 +383,7 @@ public: * @param path the path to draw * @param style style to apply to the path. */ - void drawPath(const GrClip&, + void drawPath(const GrClip*, GrPaint&&, GrAA, const SkMatrix& viewMatrix, @@ -403,7 +398,7 @@ public: * @param viewMatrix transformation matrix * @param shape the shape to draw */ - void drawShape(const GrClip&, + void drawShape(const GrClip*, GrPaint&&, GrAA, const SkMatrix& viewMatrix, @@ -419,7 +414,7 @@ public: * @param overridePrimType primitive type to draw. If NULL, derive prim type from vertices. * @param effect runtime effect that will handle custom vertex attributes. */ - void drawVertices(const GrClip&, + void drawVertices(const GrClip*, GrPaint&& paint, const SkMatrixProvider& matrixProvider, sk_sp<SkVertices> vertices, @@ -438,7 +433,7 @@ public: * @param colors optional array of per-sprite colors, supercedes * the paint's color field. */ - void drawAtlas(const GrClip&, + void drawAtlas(const GrClip*, GrPaint&& paint, const SkMatrix& viewMatrix, int spriteCount, @@ -455,7 +450,7 @@ public: * @param region the region to be drawn * @param style style to apply to the region */ - void drawRegion(const GrClip&, + void drawRegion(const GrClip*, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix, @@ -472,7 +467,7 @@ public: * @param oval the bounding rect of the oval. * @param style style to apply to the oval. Currently path effects are not allowed. */ - void drawOval(const GrClip&, + void drawOval(const GrClip*, GrPaint&& paint, GrAA, const SkMatrix& viewMatrix, @@ -493,7 +488,7 @@ public: * omitted. * @param style style to apply to the oval. */ - void drawArc(const GrClip&, + void drawArc(const GrClip*, GrPaint&& paint, GrAA, const SkMatrix& viewMatrix, @@ -506,7 +501,7 @@ public: /** * Draw the image as a set of rects, specified by |iter|. */ - void drawImageLattice(const GrClip&, + void drawImageLattice(const GrClip*, GrPaint&&, const SkMatrix& viewMatrix, GrSurfaceProxyView, @@ -551,7 +546,8 @@ public: * 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. */ - GrSemaphoresSubmitted flush(SkSurface::BackendSurfaceAccess access, const GrFlushInfo&); + GrSemaphoresSubmitted flush(SkSurface::BackendSurfaceAccess access, const GrFlushInfo&, + const GrBackendSurfaceMutableState*); /** * The next time this GrRenderTargetContext is flushed, the gpu will wait on the passed in @@ -594,13 +590,12 @@ private: GrAAType chooseAAType(GrAA); - friend class GrAtlasTextBlob; // for access to add[Mesh]DrawOp friend class GrClipStackClip; // for access to getOpsTask friend class GrOnFlushResourceProvider; // for access to getOpsTask (http://skbug.com/9357) friend class GrRenderTargetContextPriv; - // All the path renderers currently make their own ops + // All the path and text renderers/ops currently make their own ops friend class GrSoftwarePathRenderer; // for access to add[Mesh]DrawOp friend class GrAAConvexPathRenderer; // for access to add[Mesh]DrawOp friend class GrDashLinePathRenderer; // for access to add[Mesh]DrawOp @@ -615,6 +610,7 @@ private: friend class GrFillRectOp; // for access to addDrawOp friend class GrTessellationPathRenderer; // for access to addDrawOp friend class GrTextureOp; // for access to addDrawOp + friend class GrAtlasTextOp; // for access to addDrawOp SkDEBUGCODE(void onValidate() const override;) @@ -622,11 +618,12 @@ private: GrOpsTask::CanDiscardPreviousOps canDiscardPreviousOpsOnFullClear() const; void setNeedsStencil(bool useMixedSamplesIfNotMSAA); - void internalClear(const GrFixedClip&, const SkPMColor4f&, CanClearFullscreen); - void internalStencilClear(const GrFixedClip&, bool insideStencilMask); + void internalClear(const SkIRect* scissor, const SkPMColor4f&, + bool upgradePartialToFull = false); + void internalStencilClear(const SkIRect* scissor, bool insideStencilMask); // Only consumes the GrPaint if successful. - bool drawFilledDRRect(const GrClip& clip, + bool drawFilledDRRect(const GrClip* clip, GrPaint&& paint, GrAA, const SkMatrix& viewMatrix, @@ -642,7 +639,7 @@ private: // // 'stencilSettings' are provided merely for decision making purposes; When non-null, // optimization strategies that submit special ops are avoided. - QuadOptimization attemptQuadOptimization(const GrClip& clip, + QuadOptimization attemptQuadOptimization(const GrClip* clip, const SkPMColor4f* constColor, const GrUserStencilSettings* stencilSettings, GrAA* aa, @@ -652,7 +649,7 @@ private: // can choose between coverage, MSAA as per chooseAAType(). This will always attempt to apply // quad optimizations, so all quad/rect public APIs should rely on this function for consistent // clipping behavior. 'quad' will be modified in place to reflect final rendered geometry. - void drawFilledQuad(const GrClip& clip, + void drawFilledQuad(const GrClip* clip, GrPaint&& paint, GrAA aa, DrawQuad* quad, @@ -660,7 +657,7 @@ private: // Like drawFilledQuad but does not require using a GrPaint or FP for texturing. // 'quad' may be modified in place to reflect final geometry. - void drawTexturedQuad(const GrClip& clip, + void drawTexturedQuad(const GrClip* clip, GrSurfaceProxyView proxyView, SkAlphaType alphaType, sk_sp<GrColorSpaceXform> textureXform, @@ -673,7 +670,7 @@ private: // If 'attemptShapeFallback' is true, and the original shape had been simplfied, this // will re-route through drawShape() to see if we can avoid path rendering one more time. - void drawShapeUsingPathRenderer(const GrClip&, GrPaint&&, GrAA, const SkMatrix&, + void drawShapeUsingPathRenderer(const GrClip*, GrPaint&&, GrAA, const SkMatrix&, const GrStyledShape&, bool attemptShapeFallback = true); void addOp(std::unique_ptr<GrOp>); @@ -684,13 +681,17 @@ private: // op list. Before adding the op to an op list the WillAddOpFn is called. Note that it // will not be called in the event that the op is discarded. Moreover, the op may merge into // another op after the function is called (either before addDrawOp returns or some time later). - void addDrawOp(const GrClip&, std::unique_ptr<GrDrawOp>, + // + // If the clip pointer is null, no clipping will be performed. + void addDrawOp(const GrClip*, std::unique_ptr<GrDrawOp>, const std::function<WillAddOpFn>& = std::function<WillAddOpFn>()); // Makes a copy of the proxy if it is necessary for the draw and places the texture that should // be used by GrXferProcessor to access the destination color in 'result'. If the return // value is false then a texture copy could not be made. - bool SK_WARN_UNUSED_RESULT setupDstProxyView(const GrClip&, const GrOp& op, + // + // The op should have already had setClippedBounds called on it. + bool SK_WARN_UNUSED_RESULT setupDstProxyView(const GrOp& op, GrXferProcessor::DstProxyView* result); class AsyncReadResult; @@ -701,6 +702,8 @@ private: GrOpsTask* getOpsTask(); + SkGlyphRunListPainter* glyphPainter() { return &fGlyphPainter; } + std::unique_ptr<GrTextTarget> fTextTarget; GrSurfaceProxyView fWriteView; @@ -716,7 +719,7 @@ private: #if GR_TEST_UTILS bool fPreserveOpsOnFullClear_TestingOnly = false; #endif - + SkGlyphRunListPainter fGlyphPainter; typedef GrSurfaceContext INHERITED; }; diff --git a/chromium/third_party/skia/src/gpu/GrRenderTargetContextPriv.h b/chromium/third_party/skia/src/gpu/GrRenderTargetContextPriv.h index 188d251002d..4e1e227fbc9 100644 --- a/chromium/third_party/skia/src/gpu/GrRenderTargetContextPriv.h +++ b/chromium/third_party/skia/src/gpu/GrRenderTargetContextPriv.h @@ -12,7 +12,6 @@ #include "src/gpu/GrPathRendering.h" #include "src/gpu/GrRenderTargetContext.h" -class GrFixedClip; class GrHardClip; class GrPath; class GrRenderTargetPriv; @@ -43,17 +42,21 @@ public: opsTask->fLastClipNumAnalyticFPs != numClipAnalyticFPs; } - using CanClearFullscreen = GrRenderTargetContext::CanClearFullscreen; - - void clear(const GrFixedClip&, const SkPMColor4f&, CanClearFullscreen); + // Clear at minimum the pixels within 'scissor', but is allowed to clear the full render target + // if that is the more performant option. + void clearAtLeast(const SkIRect& scissor, const SkPMColor4f& color) { + fRenderTargetContext->internalClear(&scissor, color, /* upgrade to full */ true); + } - void clearStencilClip(const GrFixedClip&, bool insideStencilMask); + void clearStencilClip(const SkIRect& scissor, bool insideStencilMask) { + fRenderTargetContext->internalStencilClear(&scissor, insideStencilMask); + } // While this can take a general clip, since GrReducedClip relies on this function, it must take // care to only provide hard clips or we could get stuck in a loop. The general clip is needed // so that path renderers can use this function. void stencilRect( - const GrClip& clip, const GrUserStencilSettings* ss, GrPaint&& paint, + const GrClip* clip, const GrUserStencilSettings* ss, GrPaint&& paint, GrAA doStencilMSAA, const SkMatrix& viewMatrix, const SkRect& rect, const SkMatrix* localMatrix = nullptr) { // Since this provides stencil settings to drawFilledQuad, it performs a different AA type @@ -65,13 +68,13 @@ public: } void stencilPath( - const GrHardClip&, GrAA doStencilMSAA, const SkMatrix& viewMatrix, sk_sp<const GrPath>); + const GrHardClip*, GrAA doStencilMSAA, const SkMatrix& viewMatrix, sk_sp<const GrPath>); /** * Draws a path, either AA or not, and touches the stencil buffer with the user stencil settings * for each color sample written. */ - bool drawAndStencilPath(const GrHardClip&, + bool drawAndStencilPath(const GrHardClip*, const GrUserStencilSettings*, SkRegion::Op op, bool invert, @@ -95,7 +98,7 @@ public: using WillAddOpFn = GrRenderTargetContext::WillAddOpFn; void testingOnly_addDrawOp(std::unique_ptr<GrDrawOp>); - void testingOnly_addDrawOp(const GrClip&, std::unique_ptr<GrDrawOp>, + void testingOnly_addDrawOp(const GrClip*, std::unique_ptr<GrDrawOp>, const std::function<WillAddOpFn>& = std::function<WillAddOpFn>()); bool refsWrappedObjects() const { diff --git a/chromium/third_party/skia/src/gpu/GrRenderTargetProxy.h b/chromium/third_party/skia/src/gpu/GrRenderTargetProxy.h index de21acc23cb..31193ae184b 100644 --- a/chromium/third_party/skia/src/gpu/GrRenderTargetProxy.h +++ b/chromium/third_party/skia/src/gpu/GrRenderTargetProxy.h @@ -60,7 +60,7 @@ public: bool wrapsVkSecondaryCB() const { return fWrapsVkSecondaryCB == WrapsVkSecondaryCB::kYes; } void markMSAADirty(const SkIRect& dirtyRect, GrSurfaceOrigin origin) { - SkASSERT(SkIRect::MakeSize(this->dimensions()).contains(dirtyRect)); + SkASSERT(SkIRect::MakeSize(this->backingStoreDimensions()).contains(dirtyRect)); SkASSERT(this->requiresManualMSAAResolve()); auto nativeRect = GrNativeRect::MakeRelativeTo( origin, this->backingStoreDimensions().height(), dirtyRect); diff --git a/chromium/third_party/skia/src/gpu/GrRenderTask.cpp b/chromium/third_party/skia/src/gpu/GrRenderTask.cpp index 7dc434b8276..fece63f45b2 100644 --- a/chromium/third_party/skia/src/gpu/GrRenderTask.cpp +++ b/chromium/third_party/skia/src/gpu/GrRenderTask.cpp @@ -26,21 +26,24 @@ GrRenderTask::GrRenderTask() , fFlags(0) { } -GrRenderTask::GrRenderTask(GrSurfaceProxyView targetView) - : fTargetView(std::move(targetView)) - , fUniqueID(CreateUniqueID()) - , fFlags(0) { -} +void GrRenderTask::disown(GrDrawingManager* drawingMgr) { + if (this->isSetFlag(kDisowned_Flag)) { + return; + } + this->setFlag(kDisowned_Flag); -GrRenderTask::~GrRenderTask() { - GrSurfaceProxy* proxy = fTargetView.proxy(); - if (proxy && this == proxy->getLastRenderTask()) { - // Ensure the target proxy doesn't keep hold of a dangling back pointer. - proxy->setLastRenderTask(nullptr); + for (const GrSurfaceProxyView& target : fTargets) { + if (this == drawingMgr->getLastRenderTask(target.proxy())) { + drawingMgr->setLastRenderTask(target.proxy(), nullptr); + } } } #ifdef SK_DEBUG +GrRenderTask::~GrRenderTask() { + SkASSERT(this->isSetFlag(kDisowned_Flag)); +} + bool GrRenderTask::deferredProxiesAreInstantiated() const { for (int i = 0; i < fDeferredProxies.count(); ++i) { if (!fDeferredProxies[i]->isInstantiated()) { @@ -59,13 +62,13 @@ void GrRenderTask::makeClosed(const GrCaps& caps) { SkIRect targetUpdateBounds; if (ExpectedOutcome::kTargetDirty == this->onMakeClosed(caps, &targetUpdateBounds)) { - GrSurfaceProxy* proxy = fTargetView.proxy(); + GrSurfaceProxy* proxy = this->target(0).proxy(); if (proxy->requiresManualMSAAResolve()) { - SkASSERT(fTargetView.asRenderTargetProxy()); - fTargetView.asRenderTargetProxy()->markMSAADirty(targetUpdateBounds, - fTargetView.origin()); + SkASSERT(this->target(0).asRenderTargetProxy()); + this->target(0).asRenderTargetProxy()->markMSAADirty(targetUpdateBounds, + this->target(0).origin()); } - GrTextureProxy* textureProxy = fTargetView.asTextureProxy(); + GrTextureProxy* textureProxy = this->target(0).asTextureProxy(); if (textureProxy && GrMipMapped::kYes == textureProxy->mipMapped()) { textureProxy->markMipMapsDirty(); } @@ -111,13 +114,14 @@ void GrRenderTask::addDependenciesFromOtherTask(GrRenderTask* otherTask) { } // Convert from a GrSurface-based dependency to a GrRenderTask one -void GrRenderTask::addDependency(GrSurfaceProxy* dependedOn, GrMipMapped mipMapped, +void GrRenderTask::addDependency(GrDrawingManager* drawingMgr, GrSurfaceProxy* dependedOn, + GrMipMapped mipMapped, GrTextureResolveManager textureResolveManager, const GrCaps& caps) { // If it is still receiving dependencies, this GrRenderTask shouldn't be closed SkASSERT(!this->isClosed()); - GrRenderTask* dependedOnTask = dependedOn->getLastRenderTask(); + GrRenderTask* dependedOnTask = drawingMgr->getLastRenderTask(dependedOn); if (dependedOnTask == this) { // self-read - presumably for dst reads. We don't need to do anything in this case. The @@ -168,11 +172,11 @@ void GrRenderTask::addDependency(GrSurfaceProxy* dependedOn, GrMipMapped mipMapp if (!fTextureResolveTask) { fTextureResolveTask = textureResolveManager.newTextureResolveRenderTask(caps); } - fTextureResolveTask->addProxy(sk_ref_sp(dependedOn), resolveFlags, caps); + fTextureResolveTask->addProxy(drawingMgr, sk_ref_sp(dependedOn), resolveFlags, caps); // addProxy() should have closed the texture proxy's previous task. SkASSERT(!dependedOnTask || dependedOnTask->isClosed()); - SkASSERT(dependedOn->getLastRenderTask() == fTextureResolveTask); + SkASSERT(drawingMgr->getLastRenderTask(dependedOn) == fTextureResolveTask); #ifdef SK_DEBUG // addProxy() should have called addDependency (in this instance, recursively) on @@ -192,7 +196,7 @@ void GrRenderTask::addDependency(GrSurfaceProxy* dependedOn, GrMipMapped mipMapp if (textureProxy) { SkASSERT(!textureProxy->mipMapsAreDirty()); } - SkASSERT(dependedOn->getLastRenderTask() == fTextureResolveTask); + SkASSERT(drawingMgr->getLastRenderTask(dependedOn) == fTextureResolveTask); #endif return; } @@ -250,11 +254,11 @@ void GrRenderTask::closeThoseWhoDependOnMe(const GrCaps& caps) { } bool GrRenderTask::isInstantiated() const { - // Some renderTasks (e.g. GrTransferFromRenderTask) don't have a target. - GrSurfaceProxy* proxy = fTargetView.proxy(); - if (!proxy) { + // Some renderTasks (e.g. GrTransferFromRenderTask) don't have any targets. + if (0 == this->numTargets()) { return true; } + GrSurfaceProxy* proxy = this->target(0).proxy(); if (!proxy->isInstantiated()) { return false; @@ -268,16 +272,29 @@ bool GrRenderTask::isInstantiated() const { return true; } +void GrRenderTask::addTarget(GrDrawingManager* drawingMgr, GrSurfaceProxyView view) { + SkASSERT(view); + drawingMgr->setLastRenderTask(view.proxy(), this); + fTargets.push_back(std::move(view)); +} + #ifdef SK_DEBUG void GrRenderTask::dump(bool printDependencies) const { SkDebugf("--------------------------------------------------------------\n"); - GrSurfaceProxy* proxy = fTargetView.proxy(); - SkDebugf("%s - renderTaskID: %d - proxyID: %d - surfaceID: %d\n", - this->name(), fUniqueID, - proxy ? proxy->uniqueID().asUInt() : -1, - proxy && proxy->peekSurface() - ? proxy->peekSurface()->uniqueID().asUInt() - : -1); + SkDebugf("%s - renderTaskID: %d\n", this->name(), fUniqueID); + + if (!fTargets.empty()) { + SkDebugf("Targets: \n"); + for (int i = 0; i < fTargets.count(); ++i) { + GrSurfaceProxy* proxy = fTargets[i].proxy(); + SkDebugf("[%d]: proxyID: %d - surfaceID: %d\n", + i, + proxy ? proxy->uniqueID().asUInt() : -1, + proxy && proxy->peekSurface() + ? proxy->peekSurface()->uniqueID().asUInt() + : -1); + } + } if (printDependencies) { SkDebugf("I rely On (%d): ", fDependencies.count()); diff --git a/chromium/third_party/skia/src/gpu/GrRenderTask.h b/chromium/third_party/skia/src/gpu/GrRenderTask.h index 83f17d90243..64431a18fea 100644 --- a/chromium/third_party/skia/src/gpu/GrRenderTask.h +++ b/chromium/third_party/skia/src/gpu/GrRenderTask.h @@ -14,6 +14,7 @@ #include "src/gpu/GrSurfaceProxyView.h" #include "src/gpu/GrTextureProxy.h" #include "src/gpu/GrTextureResolveManager.h" +#include "src/gpu/ops/GrOp.h" class GrOpFlushState; class GrOpsTask; @@ -26,8 +27,7 @@ class GrTextureResolveRenderTask; class GrRenderTask : public SkRefCnt { public: GrRenderTask(); - GrRenderTask(GrSurfaceProxyView); - ~GrRenderTask() override; + SkDEBUGCODE(~GrRenderTask() override); void makeClosed(const GrCaps&); @@ -40,15 +40,20 @@ public: // Called when this class will survive a flush and needs to truncate its ops and start over. // TODO: ultimately it should be invalid for an op list to survive a flush. // https://bugs.chromium.org/p/skia/issues/detail?id=7111 - virtual void endFlush() {} + virtual void endFlush(GrDrawingManager*) {} + + // This method "disowns" all the GrSurfaceProxies this RenderTask modifies. In + // practice this just means telling the drawingManager to forget the relevant + // mappings from surface proxy to last modifying rendertask. + virtual void disown(GrDrawingManager*); bool isClosed() const { return this->isSetFlag(kClosed_Flag); } /* * Notify this GrRenderTask that it relies on the contents of 'dependedOn' */ - void addDependency(GrSurfaceProxy* dependedOn, GrMipMapped, GrTextureResolveManager, - const GrCaps& caps); + void addDependency(GrDrawingManager*, GrSurfaceProxy* dependedOn, GrMipMapped, + GrTextureResolveManager, const GrCaps& caps); /* * Notify this GrRenderTask that it relies on the contents of all GrRenderTasks which otherTask @@ -62,6 +67,8 @@ public: bool dependsOn(const GrRenderTask* dependedOn) const; uint32_t uniqueID() const { return fUniqueID; } + int numTargets() const { return fTargets.count(); } + const GrSurfaceProxyView& target(int i) const { return fTargets[i]; } /* * Safely cast this GrRenderTask to a GrOpsTask (if possible). @@ -81,8 +88,8 @@ public: void visitTargetAndSrcProxies_debugOnly(const GrOp::VisitProxyFunc& fn) const { this->visitProxies_debugOnly(fn); - if (fTargetView.proxy()) { - fn(fTargetView.proxy(), GrMipMapped::kNo); + for (int i = 0; i < this->numTargets(); ++i) { + fn(this->target(i).proxy(), GrMipMapped::kNo); } } #endif @@ -94,6 +101,10 @@ protected: SkDEBUGCODE(bool deferredProxiesAreInstantiated() const;) + // Add a target surface proxy to the list of targets for this task. + // This also informs the drawing manager to update the lastRenderTask association. + void addTarget(GrDrawingManager*, GrSurfaceProxyView); + enum class ExpectedOutcome : bool { kTargetUnchanged, kTargetDirty, @@ -106,7 +117,7 @@ protected: // targetUpdateBounds must not extend beyond the proxy bounds. virtual ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect* targetUpdateBounds) = 0; - GrSurfaceProxyView fTargetView; + SkSTArray<1, GrSurfaceProxyView> fTargets; // List of texture proxies whose contents are being prepared on a worker thread // TODO: this list exists so we can fire off the proper upload when an renderTask begins @@ -118,15 +129,19 @@ private: friend class GrDrawingManager; // Drops any pending operations that reference proxies that are not instantiated. - // NOTE: Derived classes don't need to check fTargetView. That is handled when the + // NOTE: Derived classes don't need to check targets. That is handled when the // drawingManager calls isInstantiated. virtual void handleInternalAllocationFailure() = 0; + // Derived classes can override to indicate usage of proxies _other than target proxies_. + // GrRenderTask itself will handle checking the target proxies. virtual bool onIsUsed(GrSurfaceProxy*) const = 0; bool isUsed(GrSurfaceProxy* proxy) const { - if (proxy == fTargetView.proxy()) { - return true; + for (const GrSurfaceProxyView& target : fTargets) { + if (target.proxy() == proxy) { + return true; + } } return this->onIsUsed(proxy); @@ -144,10 +159,11 @@ private: static uint32_t CreateUniqueID(); enum Flags { - kClosed_Flag = 0x01, //!< This GrRenderTask can't accept any more dependencies. + kClosed_Flag = 0x01, //!< This task can't accept any more dependencies. + kDisowned_Flag = 0x02, //!< This task is disowned by its creating GrDrawingManager. - kWasOutput_Flag = 0x02, //!< Flag for topological sorting - kTempMark_Flag = 0x04, //!< Flag for topological sorting + kWasOutput_Flag = 0x04, //!< Flag for topological sorting + kTempMark_Flag = 0x08, //!< Flag for topological sorting }; void setFlag(uint32_t flag) { diff --git a/chromium/third_party/skia/src/gpu/GrResourceCache.cpp b/chromium/third_party/skia/src/gpu/GrResourceCache.cpp index cdc0e21f24b..b3166acf1a6 100644 --- a/chromium/third_party/skia/src/gpu/GrResourceCache.cpp +++ b/chromium/third_party/skia/src/gpu/GrResourceCache.cpp @@ -28,8 +28,7 @@ DECLARE_SKMESSAGEBUS_MESSAGE(GrUniqueKeyInvalidatedMessage); DECLARE_SKMESSAGEBUS_MESSAGE(GrTextureFreedMessage); -#define ASSERT_SINGLE_OWNER \ - SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);) +#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fSingleOwner) ////////////////////////////////////////////////////////////////////////////// diff --git a/chromium/third_party/skia/src/gpu/GrResourceCache.h b/chromium/third_party/skia/src/gpu/GrResourceCache.h index 4db77e21867..23639dc3890 100644 --- a/chromium/third_party/skia/src/gpu/GrResourceCache.h +++ b/chromium/third_party/skia/src/gpu/GrResourceCache.h @@ -61,7 +61,7 @@ public: ~GrResourceCache(); // Default maximum number of bytes of gpu memory of budgeted resources in the cache. - static const size_t kDefaultMaxSize = 96 * (1 << 20); + static const size_t kDefaultMaxSize = 256 * (1 << 20); /** Used to access functionality needed by GrGpuResource for lifetime management. */ class ResourceAccess; diff --git a/chromium/third_party/skia/src/gpu/GrResourceProvider.cpp b/chromium/third_party/skia/src/gpu/GrResourceProvider.cpp index f079c7d9df2..2c9d9b145bb 100644 --- a/chromium/third_party/skia/src/gpu/GrResourceProvider.cpp +++ b/chromium/third_party/skia/src/gpu/GrResourceProvider.cpp @@ -31,8 +31,7 @@ const int GrResourceProvider::kMinScratchTextureSize = 16; -#define ASSERT_SINGLE_OWNER \ - SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);) +#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fSingleOwner) GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* owner) : fCache(cache) diff --git a/chromium/third_party/skia/src/gpu/GrRingBuffer.cpp b/chromium/third_party/skia/src/gpu/GrRingBuffer.cpp new file mode 100644 index 00000000000..145c88a72df --- /dev/null +++ b/chromium/third_party/skia/src/gpu/GrRingBuffer.cpp @@ -0,0 +1,91 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "src/gpu/GrRingBuffer.h" + +// Get offset into buffer that has enough space for size +// Returns fTotalSize if no space +size_t GrRingBuffer::getAllocationOffset(size_t size) { + // capture current state locally (because fTail could be overwritten by the completion handler) + size_t head, tail; + SkAutoSpinlock lock(fMutex); + head = fHead; + tail = fTail; + + // The head and tail indices increment without bound, wrapping with overflow, + // so we need to mod them down to the actual bounds of the allocation to determine + // which blocks are available. + size_t modHead = head & (fTotalSize - 1); + size_t modTail = tail & (fTotalSize - 1); + + bool full = (head != tail && modHead == modTail); + + if (full) { + return fTotalSize; + } + + // case 1: free space lies at the beginning and/or the end of the buffer + if (modHead >= modTail) { + // check for room at the end + if (fTotalSize - modHead < size) { + // no room at the end, check the beginning + if (modTail < size) { + // no room at the beginning + return fTotalSize; + } + // we are going to allocate from the beginning, adjust head to '0' position + head += fTotalSize - modHead; + modHead = 0; + } + // case 2: free space lies in the middle of the buffer, check for room there + } else if (modTail - modHead < size) { + // no room in the middle + return fTotalSize; + } + + fHead = GrAlignTo(head + size, fAlignment); + return modHead; +} + +GrRingBuffer::Slice GrRingBuffer::suballocate(size_t size) { + size_t offset = this->getAllocationOffset(size); + if (offset < fTotalSize) { + return { fBuffer, offset }; + } + + // Try to grow allocation (old allocation will age out). + fTotalSize *= 2; + fBuffer = this->createBuffer(fTotalSize); + SkASSERT(fBuffer); + { + SkAutoSpinlock lock(fMutex); + fHead = 0; + fTail = 0; + fGenID++; + } + offset = this->getAllocationOffset(size); + SkASSERT(offset < fTotalSize); + return { fBuffer, offset }; +} + +// used when current command buffer/command list is submitted +GrRingBuffer::SubmitData GrRingBuffer::startSubmit() { + SubmitData submitData; + SkAutoSpinlock lock(fMutex); + submitData.fBuffer = fBuffer; + submitData.fLastHead = fHead; + submitData.fGenID = fGenID; + return submitData; +} + +// used when current command buffer/command list is completed +void GrRingBuffer::finishSubmit(const GrRingBuffer::SubmitData& submitData) { + SkAutoSpinlock lock(fMutex); + if (submitData.fGenID == fGenID) { + fTail = submitData.fLastHead; + } +} diff --git a/chromium/third_party/skia/src/gpu/GrRingBuffer.h b/chromium/third_party/skia/src/gpu/GrRingBuffer.h new file mode 100644 index 00000000000..2498c0d9cfb --- /dev/null +++ b/chromium/third_party/skia/src/gpu/GrRingBuffer.h @@ -0,0 +1,72 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrRingBuffer_DEFINED +#define GrRingBuffer_DEFINED + +#include "src/gpu/GrGpuBuffer.h" + +#include "include/private/SkSpinlock.h" + +/** + * A wrapper for a GPU buffer that allocates slices in a continuous ring. + * + * It's assumed that suballocate and startSubmit are always called in the same thread, + * and that finishSubmit could be called in a separate thread. + */ +class GrRingBuffer : public SkRefCnt { +public: + GrRingBuffer(sk_sp<GrGpuBuffer> buffer, size_t size, size_t alignment) + : fBuffer(std::move(buffer)) + , fTotalSize(size) + , fAlignment(alignment) + , fHead(0) + , fTail(0) + , fGenID(0) { + // We increment fHead and fTail without bound and let overflow handle any wrapping. + // Because of this, size needs to be a power of two. + SkASSERT(SkIsPow2(size)); + } + virtual ~GrRingBuffer() = default; + + struct Slice { + sk_sp<GrGpuBuffer> fBuffer; + size_t fOffset; + }; + + Slice suballocate(size_t size); + + class SubmitData { + public: + GrGpuBuffer* buffer() const { return fBuffer.get(); } + private: + friend class GrRingBuffer; + sk_sp<GrGpuBuffer> fBuffer; + size_t fLastHead; + size_t fGenID; + }; + // Backends should call startSubmit() at submit time, and finishSubmit() when the + // command buffer/list finishes. + SubmitData startSubmit(); + void finishSubmit(const SubmitData&); + + size_t size() const { return fTotalSize; } + +private: + virtual sk_sp<GrGpuBuffer> createBuffer(size_t size) = 0; + size_t getAllocationOffset(size_t size); + + sk_sp<GrGpuBuffer> fBuffer; + size_t fTotalSize; + size_t fAlignment; + size_t fHead SK_GUARDED_BY(fMutex); // where we start allocating + size_t fTail SK_GUARDED_BY(fMutex); // where we start deallocating + uint64_t fGenID SK_GUARDED_BY(fMutex); // incremented when createBuffer is called + SkSpinlock fMutex; +}; + +#endif diff --git a/chromium/third_party/skia/src/gpu/GrSWMaskHelper.h b/chromium/third_party/skia/src/gpu/GrSWMaskHelper.h index 5ca23f70d61..5982bcffb35 100644 --- a/chromium/third_party/skia/src/gpu/GrSWMaskHelper.h +++ b/chromium/third_party/skia/src/gpu/GrSWMaskHelper.h @@ -15,6 +15,7 @@ #include "src/core/SkAutoPixmapStorage.h" #include "src/core/SkDraw.h" #include "src/core/SkRasterClip.h" +#include "src/gpu/GrSurfaceProxyView.h" class GrShape; class GrStyledShape; diff --git a/chromium/third_party/skia/src/gpu/GrScissorState.h b/chromium/third_party/skia/src/gpu/GrScissorState.h index dac735b023d..cc1cea25781 100644 --- a/chromium/third_party/skia/src/gpu/GrScissorState.h +++ b/chromium/third_party/skia/src/gpu/GrScissorState.h @@ -10,33 +10,74 @@ #include "include/core/SkRect.h" +/** + * The scissor state is stored as the scissor rectangle and the backing store bounds of the render + * target that the scissor will apply to. If the render target is approximate fit and the padded + * content should not be modified, the clip should apply the render target context's logical bounds + * as part of the scissor (e.g. when stenciling). This puts the onus on the render target context + * to intentionally discard the scissor at its logical bounds when drawing into the padded content + * is acceptable (e.g. color-only updates). + */ class GrScissorState { public: - GrScissorState() : fEnabled(false) {} - GrScissorState(const SkIRect& rect) : fEnabled(true), fRect(rect) {} - void setDisabled() { fEnabled = false; } - void set(const SkIRect& rect) { fRect = rect; fEnabled = true; } + // The disabled scissor state for a render target of the given size. + explicit GrScissorState(const SkISize& rtDims) + : fRTSize(rtDims) + , fRect(SkIRect::MakeSize(rtDims)) {} + + void setDisabled() { fRect = SkIRect::MakeSize(fRTSize); } + bool set(const SkIRect& rect) { + this->setDisabled(); + return this->intersect(rect); + } + bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& rect) { - if (!fEnabled) { - this->set(rect); + if (!fRect.intersect(rect)) { + fRect.setEmpty(); + return false; + } else { return true; } - return fRect.intersect(rect); } + + // If the scissor was configured for the backing store dimensions and it's acceptable to + // draw outside the logical dimensions of the target, this will discard the scissor test if + // the test wouldn't modify the logical dimensions. + bool relaxTest(const SkISize& logicalDimensions) { + SkASSERT(logicalDimensions.fWidth <= fRTSize.fWidth && + logicalDimensions.fHeight <= fRTSize.fHeight); + if (fRect.fLeft == 0 && fRect.fTop == 0 && fRect.fRight >= logicalDimensions.fWidth && + fRect.fBottom >= logicalDimensions.fHeight) { + this->setDisabled(); + return true; + } else { + return false; + } + } + bool operator==(const GrScissorState& other) const { - return fEnabled == other.fEnabled && - (false == fEnabled || fRect == other.fRect); + return fRTSize == other.fRTSize && fRect == other.fRect; } bool operator!=(const GrScissorState& other) const { return !(*this == other); } - bool enabled() const { return fEnabled; } + bool enabled() const { + SkASSERT(fRect.isEmpty() || SkIRect::MakeSize(fRTSize).contains(fRect)); + // This is equivalent to a strict contains check on SkIRect::MakeSize(rtSize) w/o creating + // the render target bounding rectangle. + return fRect.fLeft > 0 || fRect.fTop > 0 || + fRect.fRight < fRTSize.fWidth || fRect.fBottom < fRTSize.fHeight; + } + + // Will always be equal to or contained in the rt bounds, or empty if scissor rectangles were + // added that did not intersect with the render target or prior scissor. const SkIRect& rect() const { - SkASSERT(fEnabled); + SkASSERT(fRect.isEmpty() || SkIRect::MakeSize(fRTSize).contains(fRect)); return fRect; } private: - bool fEnabled; + // The scissor is considered enabled if the rectangle does not cover the render target + SkISize fRTSize; SkIRect fRect; }; diff --git a/chromium/third_party/skia/src/gpu/GrShaderCaps.cpp b/chromium/third_party/skia/src/gpu/GrShaderCaps.cpp index faafc94c79b..a629085a099 100644 --- a/chromium/third_party/skia/src/gpu/GrShaderCaps.cpp +++ b/chromium/third_party/skia/src/gpu/GrShaderCaps.cpp @@ -49,7 +49,6 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) { fPreferFlatInterpolation = false; fNoPerspectiveInterpolationSupport = false; fSampleMaskSupport = false; - fTessellationSupport = false; fExternalTextureSupport = false; fVertexIDSupport = false; fFPManipulationSupport = false; @@ -61,6 +60,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) { // GL_ARB_texture_swizzle). fTextureSwizzleAppliedInShader = true; fBuiltinFMASupport = false; + fCanUseDoLoops = true; fVersionDeclString = nullptr; fShaderDerivativeExtensionString = nullptr; @@ -76,6 +76,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) { fFBFetchColorName = nullptr; fFBFetchExtensionString = nullptr; fMaxFragmentSamplers = 0; + fMaxTessellationSegments = 0; fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction; } @@ -132,7 +133,6 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const { writer->appendBool("Prefer flat interpolation", fPreferFlatInterpolation); writer->appendBool("No perspective interpolation support", fNoPerspectiveInterpolationSupport); writer->appendBool("Sample mask support", fSampleMaskSupport); - writer->appendBool("Tessellation Support", fTessellationSupport); writer->appendBool("External texture support", fExternalTextureSupport); writer->appendBool("sk_VertexID support", fVertexIDSupport); writer->appendBool("Floating point manipulation support", fFPManipulationSupport); @@ -142,8 +142,10 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const { writer->appendBool("Color space math needs float", fColorSpaceMathNeedsFloat); writer->appendBool("Texture swizzle applied in shader", fTextureSwizzleAppliedInShader); writer->appendBool("Builtin fma() support", fBuiltinFMASupport); + writer->appendBool("Can use do-while loops", fCanUseDoLoops); writer->appendS32("Max FS Samplers", fMaxFragmentSamplers); + writer->appendS32("Max Tessellation Segments", fMaxTessellationSegments); writer->appendString("Advanced blend equation interaction", kAdvBlendEqInteractionStr[fAdvBlendEqInteraction]); @@ -183,7 +185,7 @@ void GrShaderCaps::applyOptionsOverrides(const GrContextOptions& options) { fGeometryShaderSupport = false; } if (options.fSuppressTessellationShaders) { - fTessellationSupport = false; + fMaxTessellationSegments = 0; } #endif } diff --git a/chromium/third_party/skia/src/gpu/GrShaderCaps.h b/chromium/third_party/skia/src/gpu/GrShaderCaps.h index b6a3cc023c1..3b3e1bf9b5f 100644 --- a/chromium/third_party/skia/src/gpu/GrShaderCaps.h +++ b/chromium/third_party/skia/src/gpu/GrShaderCaps.h @@ -72,8 +72,6 @@ public: bool sampleMaskSupport() const { return fSampleMaskSupport; } - bool tessellationSupport() const { return fTessellationSupport; } - bool externalTextureSupport() const { return fExternalTextureSupport; } bool vertexIDSupport() const { return fVertexIDSupport; } @@ -175,6 +173,10 @@ public: // http://skbug.com/8921 bool canOnlyUseSampleMaskWithStencil() const { return fCanOnlyUseSampleMaskWithStencil; } + // ANGLE disallows do loops altogether, and we're seeing crashes on Tegra3 with do loops in at + // least some cases. + bool canUseDoLoops() const { return fCanUseDoLoops; } + // Returns the string of an extension that must be enabled in the shader to support // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling // this function, the caller should check that shaderDerivativeSupport exists. @@ -244,6 +246,11 @@ public: int maxFragmentSamplers() const { return fMaxFragmentSamplers; } + // Maximum number of segments a tessellation edge can be divided into. + int maxTessellationSegments() const { return fMaxTessellationSegments; } + + bool tessellationSupport() const { return SkToBool(fMaxTessellationSegments);} + bool textureSwizzleAppliedInShader() const { return fTextureSwizzleAppliedInShader; } GrGLSLGeneration generation() const { return fGLSLGeneration; } @@ -267,7 +274,6 @@ private: bool fPreferFlatInterpolation : 1; bool fNoPerspectiveInterpolationSupport : 1; bool fSampleMaskSupport : 1; - bool fTessellationSupport : 1; bool fExternalTextureSupport : 1; bool fVertexIDSupport : 1; bool fFPManipulationSupport : 1; @@ -301,6 +307,7 @@ private: bool fNoDefaultPrecisionForExternalSamplers : 1; bool fCanOnlyUseSampleMaskWithStencil : 1; bool fColorSpaceMathNeedsFloat : 1; + bool fCanUseDoLoops : 1; const char* fVersionDeclString; @@ -319,6 +326,7 @@ private: const char* fFBFetchExtensionString; int fMaxFragmentSamplers; + int fMaxTessellationSegments; AdvBlendEqInteraction fAdvBlendEqInteraction; diff --git a/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp b/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp index 6646caeadb9..95ab059800f 100644 --- a/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp +++ b/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp @@ -68,15 +68,16 @@ static bool get_unclipped_shape_dev_bounds(const GrStyledShape& shape, const SkM // Gets the shape bounds, the clip bounds, and the intersection (if any). Returns false if there // is no intersection. bool GrSoftwarePathRenderer::GetShapeAndClipBounds(GrRenderTargetContext* renderTargetContext, - const GrClip& clip, + const GrClip* clip, const GrStyledShape& shape, const SkMatrix& matrix, SkIRect* unclippedDevShapeBounds, SkIRect* clippedDevShapeBounds, SkIRect* devClipBounds) { // compute bounds as intersection of rt size, clip, and path - *devClipBounds = clip.getConservativeBounds(renderTargetContext->width(), - renderTargetContext->height()); + *devClipBounds = clip ? clip->getConservativeBounds() + : SkIRect::MakeWH(renderTargetContext->width(), + renderTargetContext->height()); if (!get_unclipped_shape_dev_bounds(shape, matrix, unclippedDevShapeBounds)) { *unclippedDevShapeBounds = SkIRect::MakeEmpty(); @@ -95,7 +96,7 @@ bool GrSoftwarePathRenderer::GetShapeAndClipBounds(GrRenderTargetContext* render void GrSoftwarePathRenderer::DrawNonAARect(GrRenderTargetContext* renderTargetContext, GrPaint&& paint, const GrUserStencilSettings& userStencilSettings, - const GrClip& clip, + const GrClip* clip, const SkMatrix& viewMatrix, const SkRect& rect, const SkMatrix& localMatrix) { @@ -106,7 +107,7 @@ void GrSoftwarePathRenderer::DrawNonAARect(GrRenderTargetContext* renderTargetCo void GrSoftwarePathRenderer::DrawAroundInvPath(GrRenderTargetContext* renderTargetContext, GrPaint&& paint, const GrUserStencilSettings& userStencilSettings, - const GrClip& clip, + const GrClip* clip, const SkMatrix& viewMatrix, const SkIRect& devClipBounds, const SkIRect& devPathBounds) { @@ -147,7 +148,7 @@ void GrSoftwarePathRenderer::DrawToTargetWithShapeMask( GrRenderTargetContext* renderTargetContext, GrPaint&& paint, const GrUserStencilSettings& userStencilSettings, - const GrClip& clip, + const GrClip* clip, const SkMatrix& viewMatrix, const SkIPoint& textureOriginInDeviceSpace, const SkIRect& deviceSpaceRectToDraw) { @@ -161,7 +162,7 @@ void GrSoftwarePathRenderer::DrawToTargetWithShapeMask( // We use device coords to compute the texture coordinates. We take the device coords and apply // a translation so that the top-left of the device bounds maps to 0,0, and then a scaling // matrix to normalized coords. - SkMatrix maskMatrix = SkMatrix::MakeTrans(SkIntToScalar(-textureOriginInDeviceSpace.fX), + SkMatrix maskMatrix = SkMatrix::Translate(SkIntToScalar(-textureOriginInDeviceSpace.fX), SkIntToScalar(-textureOriginInDeviceSpace.fY)); maskMatrix.preConcat(viewMatrix); @@ -241,13 +242,13 @@ bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) { args.fShape->hasUnstyledKey() && (GrAAType::kCoverage == args.fAAType); if (!GetShapeAndClipBounds(args.fRenderTargetContext, - *args.fClip, *args.fShape, + args.fClip, *args.fShape, *args.fViewMatrix, &unclippedDevShapeBounds, &clippedDevShapeBounds, &devClipBounds)) { if (inverseFilled) { DrawAroundInvPath(args.fRenderTargetContext, std::move(args.fPaint), - *args.fUserStencilSettings, *args.fClip, *args.fViewMatrix, + *args.fUserStencilSettings, args.fClip, *args.fViewMatrix, devClipBounds, unclippedDevShapeBounds); } return true; @@ -382,11 +383,11 @@ bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) { SkASSERT(view); if (inverseFilled) { DrawAroundInvPath(args.fRenderTargetContext, GrPaint::Clone(args.fPaint), - *args.fUserStencilSettings, *args.fClip, *args.fViewMatrix, devClipBounds, + *args.fUserStencilSettings, args.fClip, *args.fViewMatrix, devClipBounds, unclippedDevShapeBounds); } DrawToTargetWithShapeMask(std::move(view), args.fRenderTargetContext, std::move(args.fPaint), - *args.fUserStencilSettings, *args.fClip, *args.fViewMatrix, + *args.fUserStencilSettings, args.fClip, *args.fViewMatrix, SkIPoint{boundsForMask->fLeft, boundsForMask->fTop}, *boundsForMask); return true; diff --git a/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.h b/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.h index d24d48adbe4..7b931662240 100644 --- a/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.h +++ b/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.h @@ -27,7 +27,7 @@ public: } static bool GetShapeAndClipBounds(GrRenderTargetContext*, - const GrClip& clip, + const GrClip* clip, const GrStyledShape& shape, const SkMatrix& matrix, SkIRect* unclippedDevShapeBounds, @@ -38,14 +38,14 @@ private: static void DrawNonAARect(GrRenderTargetContext* renderTargetContext, GrPaint&& paint, const GrUserStencilSettings& userStencilSettings, - const GrClip& clip, + const GrClip* clip, const SkMatrix& viewMatrix, const SkRect& rect, const SkMatrix& localMatrix); static void DrawAroundInvPath(GrRenderTargetContext* renderTargetContext, GrPaint&& paint, const GrUserStencilSettings& userStencilSettings, - const GrClip& clip, + const GrClip* clip, const SkMatrix& viewMatrix, const SkIRect& devClipBounds, const SkIRect& devPathBounds); @@ -57,7 +57,7 @@ private: GrRenderTargetContext* renderTargetContext, GrPaint&& paint, const GrUserStencilSettings& userStencilSettings, - const GrClip& clip, + const GrClip* clip, const SkMatrix& viewMatrix, const SkIPoint& textureOriginInDeviceSpace, const SkIRect& deviceSpaceRectToDraw); diff --git a/chromium/third_party/skia/src/gpu/GrStencilClip.h b/chromium/third_party/skia/src/gpu/GrStencilClip.h index 854ba1ce510..4ab8a82e080 100644 --- a/chromium/third_party/skia/src/gpu/GrStencilClip.h +++ b/chromium/third_party/skia/src/gpu/GrStencilClip.h @@ -16,12 +16,14 @@ */ class GrStencilClip final : public GrHardClip { public: - GrStencilClip(uint32_t stencilStackID = SK_InvalidGenID) : fStencilStackID(stencilStackID) {} + explicit GrStencilClip(const SkISize& rtDims, uint32_t stencilStackID = SK_InvalidGenID) + : fFixedClip(rtDims) + , fStencilStackID(stencilStackID) {} - explicit GrStencilClip(const SkIRect& scissorRect, uint32_t stencilStackID = SK_InvalidGenID) - : fFixedClip(scissorRect) - , fStencilStackID(stencilStackID) { - } + GrStencilClip(const SkISize& rtDims, const SkIRect& scissorRect, + uint32_t stencilStackID = SK_InvalidGenID) + : fFixedClip(rtDims, scissorRect) + , fStencilStackID(stencilStackID) {} const GrFixedClip& fixedClip() const { return fFixedClip; } GrFixedClip& fixedClip() { return fFixedClip; } @@ -33,14 +35,14 @@ public: bool quickContains(const SkRect& rect) const override { return !this->hasStencilClip() && fFixedClip.quickContains(rect); } - SkIRect getConservativeBounds(int width, int height) const override { - return fFixedClip.getConservativeBounds(width, height); + SkIRect getConservativeBounds() const override { + return fFixedClip.getConservativeBounds(); } - bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA* aa) const override { - return !this->hasStencilClip() && fFixedClip.isRRect(rtBounds, rr, aa); + bool isRRect(SkRRect* rr, GrAA* aa) const override { + return !this->hasStencilClip() && fFixedClip.isRRect(rr, aa); } - bool apply(int rtWidth, int rtHeight, GrAppliedHardClip* out, SkRect* bounds) const override { - if (!fFixedClip.apply(rtWidth, rtHeight, out, bounds)) { + bool apply(GrAppliedHardClip* out, SkRect* bounds) const override { + if (!fFixedClip.apply(out, bounds)) { return false; } if (this->hasStencilClip()) { diff --git a/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.cpp b/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.cpp index f9870f41af1..f261e265e92 100644 --- a/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.cpp +++ b/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.cpp @@ -278,7 +278,7 @@ static void draw_stencil_rect(GrRenderTargetContext* rtc, const GrHardClip& clip const SkRect& rect, GrAA aa) { GrPaint paint; paint.setXPFactory(GrDisableColorXPFactory::Get()); - rtc->priv().stencilRect(clip, ss, std::move(paint), aa, matrix, rect); + rtc->priv().stencilRect(&clip, ss, std::move(paint), aa, matrix, rect); } static void draw_path(GrRecordingContext* context, GrRenderTargetContext* rtc, @@ -334,7 +334,8 @@ bool GrStencilMaskHelper::init(const SkIRect& bounds, uint32_t genID, } fClip.setStencilClip(genID); - fClip.fixedClip().setScissor(bounds); + // Should have caught bounds not intersecting the render target much earlier in clip application + SkAssertResult(fClip.fixedClip().setScissor(bounds)); if (!windowRects.empty()) { fClip.fixedClip().setWindowRectangles( windowRects, GrWindowRectsState::Mode::kExclusive); @@ -462,7 +463,15 @@ bool GrStencilMaskHelper::drawShape(const GrShape& shape, } void GrStencilMaskHelper::clear(bool insideStencil) { - fRTC->priv().clearStencilClip(fClip.fixedClip(), insideStencil); + if (fClip.fixedClip().hasWindowRectangles()) { + // Use a draw to benefit from window rectangles when resetting the stencil buffer; for + // large buffers with MSAA this can be significant. + draw_stencil_rect(fRTC, fClip.fixedClip(), + GrStencilSettings::SetClipBitSettings(insideStencil), SkMatrix::I(), + SkRect::Make(fClip.fixedClip().scissorRect()), GrAA::kNo); + } else { + fRTC->priv().clearStencilClip(fClip.fixedClip().scissorRect(), insideStencil); + } } void GrStencilMaskHelper::finish() { diff --git a/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.h b/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.h index 547bee2d934..f6cd2b90aa2 100644 --- a/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.h +++ b/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.h @@ -39,7 +39,8 @@ public: // of which must outlive the helper. GrStencilMaskHelper(GrRecordingContext* context, GrRenderTargetContext* rtc) : fContext(context) - , fRTC(rtc) {} + , fRTC(rtc) + , fClip(rtc->dimensions()) {} // Returns true if the stencil mask must be redrawn bool init(const SkIRect& maskBounds, uint32_t genID, diff --git a/chromium/third_party/skia/src/gpu/GrSurface.cpp b/chromium/third_party/skia/src/gpu/GrSurface.cpp index 03f46166116..1aa4444482f 100644 --- a/chromium/third_party/skia/src/gpu/GrSurface.cpp +++ b/chromium/third_party/skia/src/gpu/GrSurface.cpp @@ -7,6 +7,7 @@ #include "include/gpu/GrContext.h" #include "src/core/SkCompressedDataUtils.h" +#include "src/gpu/GrBackendUtils.h" #include "src/gpu/GrRenderTarget.h" #include "src/gpu/GrResourceProvider.h" #include "src/gpu/GrSurface.h" @@ -34,7 +35,7 @@ size_t GrSurface::ComputeSize(const GrCaps& caps, dimensions = GrResourceProvider::MakeApprox(dimensions); } - SkImage::CompressionType compressionType = caps.compressionType(format); + SkImage::CompressionType compressionType = GrBackendFormatToCompressionType(format); if (compressionType != SkImage::CompressionType::kNone) { colorSize = SkCompressedFormatDataSize(compressionType, dimensions, mipMapped == GrMipMapped::kYes); diff --git a/chromium/third_party/skia/src/gpu/GrSurfaceContext.cpp b/chromium/third_party/skia/src/gpu/GrSurfaceContext.cpp index 4e0e5c4b6ba..b7c667f04b9 100644 --- a/chromium/third_party/skia/src/gpu/GrSurfaceContext.cpp +++ b/chromium/third_party/skia/src/gpu/GrSurfaceContext.cpp @@ -10,7 +10,6 @@ #include "include/private/GrRecordingContext.h" #include "src/core/SkAutoPixmapStorage.h" #include "src/gpu/GrAuditTrail.h" -#include "src/gpu/GrClip.h" #include "src/gpu/GrContextPriv.h" #include "src/gpu/GrDataUtils.h" #include "src/gpu/GrDrawingManager.h" @@ -24,8 +23,7 @@ #include "src/gpu/SkGr.h" #include "src/gpu/effects/GrBicubicEffect.h" -#define ASSERT_SINGLE_OWNER \ - SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());) +#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(this->singleOwner()) #define RETURN_FALSE_IF_ABANDONED if (this->fContext->priv().abandoned()) { return false; } std::unique_ptr<GrSurfaceContext> GrSurfaceContext::Make(GrRecordingContext* context, @@ -240,7 +238,7 @@ bool GrSurfaceContext::readPixels(const GrImageInfo& origDstInfo, void* dst, siz paint.addColorFragmentProcessor(std::move(fp)); tempCtx->asRenderTargetContext()->fillRectToRect( - GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), + nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(), SkRect::MakeWH(dstInfo.width(), dstInfo.height()), SkRect::MakeXYWH(pt.fX, pt.fY, dstInfo.width(), dstInfo.height())); @@ -275,7 +273,7 @@ bool GrSurfaceContext::readPixels(const GrImageInfo& origDstInfo, void* dst, siz } direct->priv().flushSurface(srcProxy); - + direct->submit(); if (!direct->priv().getGpu()->readPixels(srcSurface, pt.fX, pt.fY, dstInfo.width(), dstInfo.height(), this->colorInfo().colorType(), supportedRead.fColorType, readDst, readRB)) { @@ -426,7 +424,7 @@ bool GrSurfaceContext::writePixels(const GrImageInfo& origSrcInfo, const void* s paint.setPorterDuffXPFactory(SkBlendMode::kSrc); paint.addColorFragmentProcessor(std::move(fp)); this->asRenderTargetContext()->fillRectToRect( - GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), + nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(), SkRect::MakeXYWH(pt.fX, pt.fY, srcInfo.width(), srcInfo.height()), SkRect::MakeWH(srcInfo.width(), srcInfo.height())); } else { @@ -502,14 +500,11 @@ bool GrSurfaceContext::copy(GrSurfaceProxy* src, const SkIRect& srcRect, const S } std::unique_ptr<GrRenderTargetContext> GrSurfaceContext::rescale( - const SkImageInfo& info, - const SkIRect& srcRect, + const GrImageInfo& info, + GrSurfaceOrigin origin, + SkIRect srcRect, SkSurface::RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality) { - auto direct = fContext->priv().asDirectContext(); - if (!direct) { - return nullptr; - } auto rtProxy = this->asRenderTargetProxy(); if (rtProxy && rtProxy->wrapsVkSecondaryCB()) { return nullptr; @@ -524,12 +519,7 @@ std::unique_ptr<GrRenderTargetContext> GrSurfaceContext::rescale( return nullptr; } - int srcW = srcRect.width(); - int srcH = srcRect.height(); - int srcX = srcRect.fLeft; - int srcY = srcRect.fTop; GrSurfaceProxyView texView = this->readSurfaceView(); - SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint; SkAlphaType srcAlphaType = this->colorInfo().alphaType(); if (!texView.asTextureProxy()) { texView = GrSurfaceProxyView::Copy(fContext, std::move(texView), GrMipMapped::kNo, srcRect, @@ -538,25 +528,8 @@ std::unique_ptr<GrRenderTargetContext> GrSurfaceContext::rescale( return nullptr; } SkASSERT(texView.asTextureProxy()); - srcX = 0; - srcY = 0; - constraint = SkCanvas::kFast_SrcRectConstraint; - } - - float sx = (float)info.width() / srcW; - float sy = (float)info.height() / srcH; - - // How many bilerp/bicubic steps to do in X and Y. + means upscaling, - means downscaling. - int stepsX; - int stepsY; - if (rescaleQuality > kNone_SkFilterQuality) { - stepsX = static_cast<int>((sx > 1.f) ? ceil(log2f(sx)) : floor(log2f(sx))); - stepsY = static_cast<int>((sy > 1.f) ? ceil(log2f(sy)) : floor(log2f(sy))); - } else { - stepsX = sx != 1.f; - stepsY = sy != 1.f; + srcRect = SkIRect::MakeSize(srcRect.size()); } - SkASSERT(stepsX || stepsY); // Within a rescaling pass A is the input (if not null) and B is the output. At the end of the // pass B is moved to A. If 'this' is the input on the first pass then tempA is null. @@ -572,100 +545,95 @@ std::unique_ptr<GrRenderTargetContext> GrSurfaceContext::rescale( kPremul_SkAlphaType); // We'll fall back to kRGBA_8888 if half float not supported. auto linearRTC = GrRenderTargetContext::MakeWithFallback( - fContext, GrColorType::kRGBA_F16, cs, SkBackingFit::kExact, {srcW, srcH}, 1, - GrMipMapped::kNo, GrProtected::kNo, kTopLeft_GrSurfaceOrigin); + fContext, GrColorType::kRGBA_F16, cs, SkBackingFit::kApprox, srcRect.size(), 1, + GrMipMapped::kNo, GrProtected::kNo, origin); if (!linearRTC) { return nullptr; } - linearRTC->drawTexture(GrNoClip(), std::move(texView), srcAlphaType, + // 1-to-1 draw can always be kFast. + linearRTC->drawTexture(nullptr, std::move(texView), srcAlphaType, GrSamplerState::Filter::kNearest, SkBlendMode::kSrc, - SK_PMColor4fWHITE, SkRect::Make(srcRect), SkRect::MakeWH(srcW, srcH), - GrAA::kNo, GrQuadAAFlags::kNone, constraint, SkMatrix::I(), - std::move(xform)); + SK_PMColor4fWHITE, SkRect::Make(srcRect), + SkRect::Make(srcRect.size()), GrAA::kNo, GrQuadAAFlags::kNone, + SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), std::move(xform)); texView = linearRTC->readSurfaceView(); SkASSERT(texView.asTextureProxy()); tempA = std::move(linearRTC); - srcX = 0; - srcY = 0; - constraint = SkCanvas::kFast_SrcRectConstraint; - } - while (stepsX || stepsY) { - int nextW = info.width(); - int nextH = info.height(); - if (stepsX < 0) { - nextW = info.width() << (-stepsX - 1); - stepsX++; - } else if (stepsX != 0) { - if (stepsX > 1) { - nextW = srcW * 2; + srcRect = SkIRect::MakeSize(srcRect.size()); + } + + while (srcRect.size() != info.dimensions()) { + SkISize nextDims = info.dimensions(); + if (rescaleQuality != kNone_SkFilterQuality) { + if (srcRect.width() > info.width()) { + nextDims.fWidth = std::max((srcRect.width() + 1)/2, info.width()); + } else if (srcRect.width() < info.width()) { + nextDims.fWidth = std::min(srcRect.width()*2, info.width()); } - --stepsX; - } - if (stepsY < 0) { - nextH = info.height() << (-stepsY - 1); - stepsY++; - } else if (stepsY != 0) { - if (stepsY > 1) { - nextH = srcH * 2; + if (srcRect.height() > info.height()) { + nextDims.fHeight = std::max((srcRect.height() + 1)/2, info.height()); + } else if (srcRect.height() < info.height()) { + nextDims.fHeight = std::min(srcRect.height()*2, info.height()); } - --stepsY; } auto input = tempA ? tempA.get() : this; GrColorType colorType = input->colorInfo().colorType(); auto cs = input->colorInfo().refColorSpace(); sk_sp<GrColorSpaceXform> xform; auto prevAlphaType = input->colorInfo().alphaType(); - if (!stepsX && !stepsY) { + if (nextDims == info.dimensions()) { // Might as well fold conversion to final info in the last step. cs = info.refColorSpace(); - colorType = SkColorTypeToGrColorType(info.colorType()); xform = GrColorSpaceXform::Make(input->colorInfo().colorSpace(), input->colorInfo().alphaType(), cs.get(), info.alphaType()); } - tempB = GrRenderTargetContext::MakeWithFallback( - fContext, colorType, std::move(cs), SkBackingFit::kExact, {nextW, nextH}, 1, - GrMipMapped::kNo, GrProtected::kNo, kTopLeft_GrSurfaceOrigin); + tempB = GrRenderTargetContext::MakeWithFallback(fContext, colorType, std::move(cs), + SkBackingFit::kApprox, nextDims, 1, + GrMipMapped::kNo, GrProtected::kNo, origin); if (!tempB) { return nullptr; } - auto dstRect = SkRect::MakeWH(nextW, nextH); + auto dstRect = SkRect::Make(nextDims); if (rescaleQuality == kHigh_SkFilterQuality) { SkMatrix matrix; - matrix.setScaleTranslate((float)srcW / nextW, (float)srcH / nextH, srcX, srcY); + matrix.setScaleTranslate((float)srcRect.width()/nextDims.width(), + (float)srcRect.height()/nextDims.height(), + srcRect.x(), + srcRect.y()); std::unique_ptr<GrFragmentProcessor> fp; auto dir = GrBicubicEffect::Direction::kXY; - if (nextW == srcW) { + if (nextDims.width() == srcRect.width()) { dir = GrBicubicEffect::Direction::kY; - } else if (nextH == srcH) { + } else if (nextDims.height() == srcRect.height()) { dir = GrBicubicEffect::Direction::kX; } static constexpr GrSamplerState::WrapMode kWM = GrSamplerState::WrapMode::kClamp; - auto subset = SkRect::MakeXYWH(srcX, srcY, srcW, srcH); fp = GrBicubicEffect::MakeSubset(std::move(texView), prevAlphaType, matrix, kWM, kWM, - subset, dir, *this->caps()); + SkRect::Make(srcRect), dir, *this->caps()); if (xform) { fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(xform)); } GrPaint paint; paint.addColorFragmentProcessor(std::move(fp)); paint.setPorterDuffXPFactory(SkBlendMode::kSrc); - tempB->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect, + tempB->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect, dstRect); } else { auto filter = rescaleQuality == kNone_SkFilterQuality ? GrSamplerState::Filter::kNearest : GrSamplerState::Filter::kBilerp; - auto srcSubset = SkRect::MakeXYWH(srcX, srcY, srcW, srcH); - tempB->drawTexture(GrNoClip(), std::move(texView), srcAlphaType, filter, - SkBlendMode::kSrc, SK_PMColor4fWHITE, srcSubset, dstRect, GrAA::kNo, + // Minimizing draw with integer coord src and dev rects can always be kFast. + auto constraint = SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint; + if (nextDims.width() <= srcRect.width() && nextDims.height() <= srcRect.height()) { + constraint = SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint; + } + tempB->drawTexture(nullptr, std::move(texView), srcAlphaType, filter, SkBlendMode::kSrc, + SK_PMColor4fWHITE, SkRect::Make(srcRect), dstRect, GrAA::kNo, GrQuadAAFlags::kNone, constraint, SkMatrix::I(), std::move(xform)); } texView = tempB->readSurfaceView(); tempA = std::move(tempB); - srcX = srcY = 0; - srcW = nextW; - srcH = nextH; - constraint = SkCanvas::kFast_SrcRectConstraint; + srcRect = SkIRect::MakeSize(nextDims); } SkASSERT(tempA); return tempA; @@ -744,4 +712,3 @@ void GrSurfaceContext::validate() const { this->onValidate(); } #endif - diff --git a/chromium/third_party/skia/src/gpu/GrSurfaceContext.h b/chromium/third_party/skia/src/gpu/GrSurfaceContext.h index 028cc52a94d..8e3394ce1a0 100644 --- a/chromium/third_party/skia/src/gpu/GrSurfaceContext.h +++ b/chromium/third_party/skia/src/gpu/GrSurfaceContext.h @@ -114,6 +114,19 @@ public: virtual GrRenderTargetContext* asRenderTargetContext() { return nullptr; } + /** + * Rescales the contents of srcRect. The gamma in which the rescaling occurs is controlled by + * RescaleGamma. It is always in the original gamut. The result is converted to the color type + * and color space of info after rescaling. Note: this currently requires that the info have a + * different size than srcRect. Though, it could be relaxed to allow non-scaling color + * conversions. + */ + std::unique_ptr<GrRenderTargetContext> rescale(const GrImageInfo& info, + GrSurfaceOrigin, + SkIRect srcRect, + SkSurface::RescaleGamma, + SkFilterQuality); + GrAuditTrail* auditTrail(); // Provides access to functions that aren't part of the public API. @@ -144,11 +157,6 @@ protected: GrSurfaceProxyView fReadView; - // The rescaling step of asyncRescaleAndReadPixels[YUV420](). - std::unique_ptr<GrRenderTargetContext> rescale(const SkImageInfo& info, const SkIRect& srcRect, - SkSurface::RescaleGamma rescaleGamma, - SkFilterQuality rescaleQuality); - // Inserts a transfer, part of the implementation of asyncReadPixels and // asyncRescaleAndReadPixelsYUV420(). struct PixelTransferResult { diff --git a/chromium/third_party/skia/src/gpu/GrSurfaceProxy.cpp b/chromium/third_party/skia/src/gpu/GrSurfaceProxy.cpp index 4df6c3302db..23580b2a5e4 100644 --- a/chromium/third_party/skia/src/gpu/GrSurfaceProxy.cpp +++ b/chromium/third_party/skia/src/gpu/GrSurfaceProxy.cpp @@ -106,9 +106,6 @@ GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface, } GrSurfaceProxy::~GrSurfaceProxy() { - // For this to be deleted the opsTask that held a ref on it (if there was one) must have been - // deleted. Which would have cleared out this back pointer. - SkASSERT(!fLastRenderTask); } sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider, @@ -219,21 +216,6 @@ void GrSurfaceProxy::computeScratchKey(const GrCaps& caps, GrScratchKey* key) co renderable, sampleCount, mipMapped, fIsProtected, key); } -void GrSurfaceProxy::setLastRenderTask(GrRenderTask* renderTask) { -#ifdef SK_DEBUG - if (fLastRenderTask) { - SkASSERT(fLastRenderTask->isClosed()); - } -#endif - - // Un-reffed - fLastRenderTask = renderTask; -} - -GrOpsTask* GrSurfaceProxy::getLastOpsTask() { - return fLastRenderTask ? fLastRenderTask->asOpsTask() : nullptr; -} - SkISize GrSurfaceProxy::backingStoreDimensions() const { SkASSERT(!this->isFullyLazy()); if (fTarget) { @@ -259,7 +241,7 @@ bool GrSurfaceProxy::isFormatCompressed(const GrCaps* caps) const { #ifdef SK_DEBUG void GrSurfaceProxy::validate(GrContext_Base* context) const { if (fTarget) { - SkASSERT(fTarget->getContext() == context); + SkASSERT(fTarget->getContext()->priv().matches(context)); } } #endif diff --git a/chromium/third_party/skia/src/gpu/GrSurfaceProxy.h b/chromium/third_party/skia/src/gpu/GrSurfaceProxy.h index 0bbd936127b..f30e21d10d4 100644 --- a/chromium/third_party/skia/src/gpu/GrSurfaceProxy.h +++ b/chromium/third_party/skia/src/gpu/GrSurfaceProxy.h @@ -268,11 +268,6 @@ public: return fSurfaceFlags & GrInternalSurfaceFlags::kRequiresManualMSAAResolve; } - void setLastRenderTask(GrRenderTask*); - GrRenderTask* getLastRenderTask() { return fLastRenderTask; } - - GrOpsTask* getLastOpsTask(); - /** * Retrieves the amount of GPU memory that will be or currently is used by this resource * in bytes. It is approximate since we aren't aware of additional padding or copies made @@ -436,15 +431,6 @@ private: // If the proxy computes its own answer that answer is checked (in debug mode) in // the instantiation method. mutable size_t fGpuMemorySize; - - // The last GrRenderTask that wrote to or is currently going to write to this surface - // The GrRenderTask can be closed (e.g., no surface context is currently bound - // to this proxy). - // This back-pointer is required so that we can add a dependancy between - // the GrRenderTask used to create the current contents of this surface - // and the GrRenderTask of a destination surface to which this one is being drawn or copied. - // This pointer is unreffed. GrRenderTasks own a ref on their surface proxies. - GrRenderTask* fLastRenderTask = nullptr; }; GR_MAKE_BITFIELD_CLASS_OPS(GrSurfaceProxy::ResolveFlags) diff --git a/chromium/third_party/skia/src/gpu/GrTextureProxy.cpp b/chromium/third_party/skia/src/gpu/GrTextureProxy.cpp index fa7e064fa9a..d955712d209 100644 --- a/chromium/third_party/skia/src/gpu/GrTextureProxy.cpp +++ b/chromium/third_party/skia/src/gpu/GrTextureProxy.cpp @@ -24,10 +24,13 @@ GrTextureProxy::GrTextureProxy(const GrBackendFormat& format, SkBudgeted budgeted, GrProtected isProtected, GrInternalSurfaceFlags surfaceFlags, - UseAllocator useAllocator) + UseAllocator useAllocator, + GrDDLProvider creatingProvider) : INHERITED(format, dimensions, fit, budgeted, isProtected, surfaceFlags, useAllocator) , fMipMapped(mipMapped) - , fMipMapsStatus(mipMapsStatus) SkDEBUGCODE(, fInitialMipMapsStatus(fMipMapsStatus)) + , fMipMapsStatus(mipMapsStatus) + SkDEBUGCODE(, fInitialMipMapsStatus(fMipMapsStatus)) + , fCreatingProvider(creatingProvider) , fProxyProvider(nullptr) , fDeferredUploader(nullptr) { SkASSERT(!(fSurfaceFlags & GrInternalSurfaceFlags::kFramebufferOnly)); @@ -43,22 +46,28 @@ GrTextureProxy::GrTextureProxy(LazyInstantiateCallback&& callback, SkBudgeted budgeted, GrProtected isProtected, GrInternalSurfaceFlags surfaceFlags, - UseAllocator useAllocator) + UseAllocator useAllocator, + GrDDLProvider creatingProvider) : INHERITED(std::move(callback), format, dimensions, fit, budgeted, isProtected, surfaceFlags, useAllocator) , fMipMapped(mipMapped) - , fMipMapsStatus(mipMapsStatus) SkDEBUGCODE(, fInitialMipMapsStatus(fMipMapsStatus)) + , fMipMapsStatus(mipMapsStatus) + SkDEBUGCODE(, fInitialMipMapsStatus(fMipMapsStatus)) + , fCreatingProvider(creatingProvider) , fProxyProvider(nullptr) , fDeferredUploader(nullptr) { SkASSERT(!(fSurfaceFlags & GrInternalSurfaceFlags::kFramebufferOnly)); } // Wrapped version -GrTextureProxy::GrTextureProxy(sk_sp<GrSurface> surf, UseAllocator useAllocator) +GrTextureProxy::GrTextureProxy(sk_sp<GrSurface> surf, + UseAllocator useAllocator, + GrDDLProvider creatingProvider) : INHERITED(std::move(surf), SkBackingFit::kExact, useAllocator) , fMipMapped(fTarget->asTexture()->texturePriv().mipMapped()) , fMipMapsStatus(fTarget->asTexture()->texturePriv().mipMapsStatus()) - SkDEBUGCODE(, fInitialMipMapsStatus(fMipMapsStatus)) + SkDEBUGCODE(, fInitialMipMapsStatus(fMipMapsStatus)) + , fCreatingProvider(creatingProvider) , fProxyProvider(nullptr) , fDeferredUploader(nullptr) { if (fTarget->getUniqueKey().isValid()) { diff --git a/chromium/third_party/skia/src/gpu/GrTextureProxy.h b/chromium/third_party/skia/src/gpu/GrTextureProxy.h index 06afa9a08ce..7781cc2309f 100644 --- a/chromium/third_party/skia/src/gpu/GrTextureProxy.h +++ b/chromium/third_party/skia/src/gpu/GrTextureProxy.h @@ -73,7 +73,8 @@ public: */ const GrUniqueKey& getUniqueKey() const { #ifdef SK_DEBUG - if (this->isInstantiated() && fUniqueKey.isValid() && fSyncTargetKey) { + if (this->isInstantiated() && fUniqueKey.isValid() && fSyncTargetKey && + fCreatingProvider == GrDDLProvider::kNo) { GrSurface* surface = this->peekSurface(); SkASSERT(surface); @@ -100,6 +101,8 @@ public: GrTextureProxyPriv texPriv(); const GrTextureProxyPriv texPriv() const; + SkDEBUGCODE(GrDDLProvider creatingProvider() const { return fCreatingProvider; }) + protected: // DDL TODO: rm the GrSurfaceProxy friending friend class GrSurfaceProxy; // for ctors @@ -116,7 +119,8 @@ protected: SkBudgeted, GrProtected, GrInternalSurfaceFlags, - UseAllocator); + UseAllocator, + GrDDLProvider creatingProvider); // Lazy-callback version // There are two main use cases for lazily-instantiated proxies: @@ -137,15 +141,19 @@ protected: SkBudgeted, GrProtected, GrInternalSurfaceFlags, - UseAllocator); + UseAllocator, + GrDDLProvider creatingProvider); // Wrapped version - GrTextureProxy(sk_sp<GrSurface>, UseAllocator); + GrTextureProxy(sk_sp<GrSurface>, UseAllocator, GrDDLProvider creatingProvider); ~GrTextureProxy() override; sk_sp<GrSurface> createSurface(GrResourceProvider*) const override; + // By default uniqueKeys are propagated from a textureProxy to its backing GrTexture. + // Setting syncTargetKey to false disables this behavior and only keeps the unique key + // on the proxy. void setTargetKeySync(bool sync) { fSyncTargetKey = sync; } private: @@ -173,6 +181,12 @@ private: bool fSyncTargetKey = true; // Should target's unique key be sync'ed with ours. + // For GrTextureProxies created in a DDL recording thread it is possible for the uniqueKey + // to be cleared on the backing GrTexture while the uniqueKey remains on the proxy. + // A fCreatingProvider of DDLProvider::kYes loosens up asserts that the key of an instantiated + // uniquely-keyed textureProxy is also always set on the backing GrTexture. + GrDDLProvider fCreatingProvider = GrDDLProvider::kNo; + GrUniqueKey fUniqueKey; GrProxyProvider* fProxyProvider; // only set when fUniqueKey is valid diff --git a/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.cpp b/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.cpp index e7b6e186691..7dbd304e7dd 100644 --- a/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.cpp +++ b/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.cpp @@ -30,13 +30,14 @@ GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(const GrCaps& caps, SkBudgeted budgeted, GrProtected isProtected, GrInternalSurfaceFlags surfaceFlags, - UseAllocator useAllocator) + UseAllocator useAllocator, + GrDDLProvider creatingProvider) : GrSurfaceProxy(format, dimensions, fit, budgeted, isProtected, surfaceFlags, useAllocator) // for now textures w/ data are always wrapped , GrRenderTargetProxy(caps, format, dimensions, sampleCnt, fit, budgeted, isProtected, surfaceFlags, useAllocator) , GrTextureProxy(format, dimensions, mipMapped, mipMapsStatus, fit, budgeted, isProtected, - surfaceFlags, useAllocator) { + surfaceFlags, useAllocator, creatingProvider) { this->initSurfaceFlags(caps); } @@ -52,7 +53,8 @@ GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(const GrCaps& caps, SkBudgeted budgeted, GrProtected isProtected, GrInternalSurfaceFlags surfaceFlags, - UseAllocator useAllocator) + UseAllocator useAllocator, + GrDDLProvider creatingProvider) : GrSurfaceProxy(std::move(callback), format, dimensions, fit, budgeted, isProtected, surfaceFlags, useAllocator) // Since we have virtual inheritance, we initialize GrSurfaceProxy directly. Send null @@ -61,7 +63,8 @@ GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(const GrCaps& caps, budgeted, isProtected, surfaceFlags, useAllocator, WrapsVkSecondaryCB::kNo) , GrTextureProxy(LazyInstantiateCallback(), format, dimensions, mipMapped, mipMapsStatus, - fit, budgeted, isProtected, surfaceFlags, useAllocator) { + fit, budgeted, isProtected, surfaceFlags, useAllocator, + creatingProvider) { this->initSurfaceFlags(caps); } @@ -69,10 +72,11 @@ GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(const GrCaps& caps, // This class is virtually derived from GrSurfaceProxy (via both GrTextureProxy and // GrRenderTargetProxy) so its constructor must be explicitly called. GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(sk_sp<GrSurface> surf, - UseAllocator useAllocator) + UseAllocator useAllocator, + GrDDLProvider creatingProvider) : GrSurfaceProxy(surf, SkBackingFit::kExact, useAllocator) , GrRenderTargetProxy(surf, useAllocator) - , GrTextureProxy(surf, useAllocator) { + , GrTextureProxy(surf, useAllocator, creatingProvider) { SkASSERT(surf->asTexture()); SkASSERT(surf->asRenderTarget()); SkASSERT(fSurfaceFlags == fTarget->surfacePriv().flags()); diff --git a/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.h b/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.h index 585f60c63d9..4eb81f25f89 100644 --- a/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.h +++ b/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.h @@ -38,7 +38,8 @@ private: SkBudgeted, GrProtected, GrInternalSurfaceFlags, - UseAllocator); + UseAllocator, + GrDDLProvider creatingProvider); // Lazy-callback version GrTextureRenderTargetProxy(const GrCaps&, @@ -52,11 +53,13 @@ private: SkBudgeted, GrProtected, GrInternalSurfaceFlags, - UseAllocator); + UseAllocator, + GrDDLProvider creatingProvider); // Wrapped version GrTextureRenderTargetProxy(sk_sp<GrSurface>, - UseAllocator); + UseAllocator, + GrDDLProvider creatingProvider); void initSurfaceFlags(const GrCaps&); diff --git a/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.cpp b/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.cpp index 8d67c035321..1a915bad9db 100644 --- a/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.cpp +++ b/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.cpp @@ -14,28 +14,24 @@ #include "src/gpu/GrResourceAllocator.h" #include "src/gpu/GrTexturePriv.h" -GrTextureResolveRenderTask::~GrTextureResolveRenderTask() { - for (const auto& resolve : fResolves) { - // Ensure the proxy doesn't keep hold of a dangling back pointer. - resolve.fProxy->setLastRenderTask(nullptr); - } -} - -void GrTextureResolveRenderTask::addProxy( - sk_sp<GrSurfaceProxy> proxyRef, GrSurfaceProxy::ResolveFlags flags, const GrCaps& caps) { - fResolves.emplace_back(std::move(proxyRef), flags); - GrSurfaceProxy* proxy = fResolves.back().fProxy.get(); +void GrTextureResolveRenderTask::addProxy(GrDrawingManager* drawingMgr, + sk_sp<GrSurfaceProxy> proxyRef, + GrSurfaceProxy::ResolveFlags flags, + const GrCaps& caps) { + Resolve& resolve = fResolves.emplace_back(flags); + GrSurfaceProxy* proxy = proxyRef.get(); // Ensure the last render task that operated on the proxy is closed. That's where msaa and // mipmaps should have been marked dirty. - SkASSERT(!proxy->getLastRenderTask() || proxy->getLastRenderTask()->isClosed()); + SkASSERT(!drawingMgr->getLastRenderTask(proxy) + || drawingMgr->getLastRenderTask(proxy)->isClosed()); SkASSERT(GrSurfaceProxy::ResolveFlags::kNone != flags); if (GrSurfaceProxy::ResolveFlags::kMSAA & flags) { GrRenderTargetProxy* renderTargetProxy = proxy->asRenderTargetProxy(); SkASSERT(renderTargetProxy); SkASSERT(renderTargetProxy->isMSAADirty()); - fResolves.back().fMSAAResolveRect = renderTargetProxy->msaaDirtyRect(); + resolve.fMSAAResolveRect = renderTargetProxy->msaaDirtyRect(); renderTargetProxy->markMSAAResolved(); } @@ -48,8 +44,9 @@ void GrTextureResolveRenderTask::addProxy( // Add the proxy as a dependency: We will read the existing contents of this texture while // generating mipmap levels and/or resolving MSAA. - this->addDependency(proxy, GrMipMapped::kNo, GrTextureResolveManager(nullptr), caps); - proxy->setLastRenderTask(this); + this->addDependency(drawingMgr, proxy, GrMipMapped::kNo, + GrTextureResolveManager(nullptr), caps); + this->addTarget(drawingMgr, GrSurfaceProxyView(std::move(proxyRef))); } void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const { @@ -57,8 +54,9 @@ void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc // fEndOfOpsTaskOpIndices will remain in sync. We create fake op#'s to capture the fact that we // manipulate the resolve proxies. auto fakeOp = alloc->curOp(); - for (const auto& resolve : fResolves) { - alloc->addInterval(resolve.fProxy.get(), fakeOp, fakeOp, + SkASSERT(fResolves.count() == this->numTargets()); + for (const GrSurfaceProxyView& target : fTargets) { + alloc->addInterval(target.proxy(), fakeOp, fakeOp, GrResourceAllocator::ActualUse::kYes); } alloc->incOps(); @@ -66,9 +64,11 @@ void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) { // Resolve all msaa back-to-back, before regenerating mipmaps. - for (const auto& resolve : fResolves) { + SkASSERT(fResolves.count() == this->numTargets()); + for (int i = 0; i < fResolves.count(); ++i) { + const Resolve& resolve = fResolves[i]; if (GrSurfaceProxy::ResolveFlags::kMSAA & resolve.fFlags) { - GrSurfaceProxy* proxy = resolve.fProxy.get(); + GrSurfaceProxy* proxy = this->target(i).proxy(); // peekRenderTarget might be null if there was an instantiation error. if (GrRenderTarget* renderTarget = proxy->peekRenderTarget()) { flushState->gpu()->resolveRenderTarget(renderTarget, resolve.fMSAAResolveRect, @@ -77,10 +77,11 @@ bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) { } } // Regenerate all mipmaps back-to-back. - for (const auto& resolve : fResolves) { + for (int i = 0; i < fResolves.count(); ++i) { + const Resolve& resolve = fResolves[i]; if (GrSurfaceProxy::ResolveFlags::kMipMaps & resolve.fFlags) { // peekTexture might be null if there was an instantiation error. - GrTexture* texture = resolve.fProxy->peekTexture(); + GrTexture* texture = this->target(i).proxy()->peekTexture(); if (texture && texture->texturePriv().mipMapsAreDirty()) { flushState->gpu()->regenerateMipMapLevels(texture); SkASSERT(!texture->texturePriv().mipMapsAreDirty()); @@ -92,9 +93,5 @@ bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) { } #ifdef SK_DEBUG -void GrTextureResolveRenderTask::visitProxies_debugOnly(const GrOp::VisitProxyFunc& fn) const { - for (const auto& resolve : fResolves) { - fn(resolve.fProxy.get(), GrMipMapped::kNo); - } -} +void GrTextureResolveRenderTask::visitProxies_debugOnly(const GrOp::VisitProxyFunc& fn) const {} #endif diff --git a/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.h b/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.h index e9ce954ca5c..379aa4b3453 100644 --- a/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.h +++ b/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.h @@ -13,14 +13,12 @@ class GrTextureResolveRenderTask final : public GrRenderTask { public: GrTextureResolveRenderTask() : GrRenderTask() {} - ~GrTextureResolveRenderTask() override; - void addProxy(sk_sp<GrSurfaceProxy> proxy, GrSurfaceProxy::ResolveFlags, const GrCaps&); + void addProxy(GrDrawingManager*, sk_sp<GrSurfaceProxy> proxy, + GrSurfaceProxy::ResolveFlags, const GrCaps&); private: bool onIsUsed(GrSurfaceProxy* proxy) const override { - // This case should be handled by GrRenderTask. - SkASSERT(proxy != fTargetView.proxy()); return false; } void handleInternalAllocationFailure() override { @@ -40,9 +38,7 @@ private: #endif struct Resolve { - Resolve(sk_sp<GrSurfaceProxy> proxy, GrSurfaceProxy::ResolveFlags flags) - : fProxy(std::move(proxy)), fFlags(flags) {} - sk_sp<GrSurfaceProxy> fProxy; + Resolve(GrSurfaceProxy::ResolveFlags flags) : fFlags(flags) {} GrSurfaceProxy::ResolveFlags fFlags; SkIRect fMSAAResolveRect; }; diff --git a/chromium/third_party/skia/src/gpu/GrTransferFromRenderTask.h b/chromium/third_party/skia/src/gpu/GrTransferFromRenderTask.h index 2126ae81a86..93a0f7aad31 100644 --- a/chromium/third_party/skia/src/gpu/GrTransferFromRenderTask.h +++ b/chromium/third_party/skia/src/gpu/GrTransferFromRenderTask.h @@ -28,7 +28,7 @@ public: private: bool onIsUsed(GrSurfaceProxy* proxy) const override { - SkASSERT(!fTargetView.proxy()); + SkASSERT(0 == this->numTargets()); return proxy == fSrcProxy.get(); } // If fSrcProxy is uninstantiated at flush time we simply will skip doing the transfer. diff --git a/chromium/third_party/skia/src/gpu/GrTriangulator.cpp b/chromium/third_party/skia/src/gpu/GrTriangulator.cpp index b2b2af31add..f695d6ee2dc 100644 --- a/chromium/third_party/skia/src/gpu/GrTriangulator.cpp +++ b/chromium/third_party/skia/src/gpu/GrTriangulator.cpp @@ -2400,13 +2400,13 @@ int get_contour_count(const SkPath& path, SkScalar tolerance) { if (!first) { ++contourCnt; } - // fallthru. + [[fallthrough]]; case SkPath::kLine_Verb: case SkPath::kConic_Verb: case SkPath::kQuad_Verb: case SkPath::kCubic_Verb: hasPoints = true; - // fallthru to break. + break; default: break; } diff --git a/chromium/third_party/skia/src/gpu/GrUniformDataManager.cpp b/chromium/third_party/skia/src/gpu/GrUniformDataManager.cpp new file mode 100644 index 00000000000..549057a3d5a --- /dev/null +++ b/chromium/third_party/skia/src/gpu/GrUniformDataManager.cpp @@ -0,0 +1,319 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "src/gpu/GrUniformDataManager.h" + +#include "src/gpu/GrShaderVar.h" + +GrUniformDataManager::GrUniformDataManager(uint32_t uniformCount, uint32_t uniformSize) + : fUniformSize(uniformSize) + , fUniformsDirty(false) { + fUniformData.reset(uniformSize); + fUniforms.push_back_n(uniformCount); + // subclasses fill in the uniforms in their constructor +} + +void* GrUniformDataManager::getBufferPtrAndMarkDirty(const Uniform& uni) const { + fUniformsDirty = true; + return static_cast<char*>(fUniformData.get())+uni.fOffset; +} + +void GrUniformDataManager::set1i(UniformHandle u, int32_t i) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType); + SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); + void* buffer = this->getBufferPtrAndMarkDirty(uni); + memcpy(buffer, &i, sizeof(int32_t)); +} + +void GrUniformDataManager::set1iv(UniformHandle u, + int arrayCount, + const int32_t v[]) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType); + SkASSERT(arrayCount > 0); + SkASSERT(arrayCount <= uni.fArrayCount || + (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); + + void* buffer = this->getBufferPtrAndMarkDirty(uni); + SkASSERT(sizeof(int32_t) == 4); + for (int i = 0; i < arrayCount; ++i) { + const int32_t* curVec = &v[i]; + memcpy(buffer, curVec, sizeof(int32_t)); + buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t); + } +} + +void GrUniformDataManager::set1f(UniformHandle u, float v0) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kFloat_GrSLType || uni.fType == kHalf_GrSLType); + SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); + void* buffer = this->getBufferPtrAndMarkDirty(uni); + SkASSERT(sizeof(float) == 4); + memcpy(buffer, &v0, sizeof(float)); +} + +void GrUniformDataManager::set1fv(UniformHandle u, + int arrayCount, + const float v[]) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kFloat_GrSLType || uni.fType == kHalf_GrSLType); + SkASSERT(arrayCount > 0); + SkASSERT(arrayCount <= uni.fArrayCount || + (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); + + void* buffer = this->getBufferPtrAndMarkDirty(uni); + SkASSERT(sizeof(float) == 4); + for (int i = 0; i < arrayCount; ++i) { + const float* curVec = &v[i]; + memcpy(buffer, curVec, sizeof(float)); + buffer = static_cast<char*>(buffer) + 4*sizeof(float); + } +} + +void GrUniformDataManager::set2i(UniformHandle u, int32_t i0, int32_t i1) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kInt2_GrSLType || uni.fType == kShort2_GrSLType); + SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); + void* buffer = this->getBufferPtrAndMarkDirty(uni); + int32_t v[2] = { i0, i1 }; + memcpy(buffer, v, 2 * sizeof(int32_t)); +} + +void GrUniformDataManager::set2iv(UniformHandle u, + int arrayCount, + const int32_t v[]) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kInt2_GrSLType || uni.fType == kShort2_GrSLType); + SkASSERT(arrayCount > 0); + SkASSERT(arrayCount <= uni.fArrayCount || + (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); + + void* buffer = this->getBufferPtrAndMarkDirty(uni); + SkASSERT(sizeof(int32_t) == 4); + for (int i = 0; i < arrayCount; ++i) { + const int32_t* curVec = &v[2 * i]; + memcpy(buffer, curVec, 2 * sizeof(int32_t)); + buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t); + } +} + +void GrUniformDataManager::set2f(UniformHandle u, float v0, float v1) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType); + SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); + void* buffer = this->getBufferPtrAndMarkDirty(uni); + SkASSERT(sizeof(float) == 4); + float v[2] = { v0, v1 }; + memcpy(buffer, v, 2 * sizeof(float)); +} + +void GrUniformDataManager::set2fv(UniformHandle u, + int arrayCount, + const float v[]) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType); + SkASSERT(arrayCount > 0); + SkASSERT(arrayCount <= uni.fArrayCount || + (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); + + void* buffer = this->getBufferPtrAndMarkDirty(uni); + SkASSERT(sizeof(float) == 4); + for (int i = 0; i < arrayCount; ++i) { + const float* curVec = &v[2 * i]; + memcpy(buffer, curVec, 2 * sizeof(float)); + buffer = static_cast<char*>(buffer) + 4*sizeof(float); + } +} + +void GrUniformDataManager::set3i(UniformHandle u, + int32_t i0, + int32_t i1, + int32_t i2) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kInt3_GrSLType || uni.fType == kShort3_GrSLType); + SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); + void* buffer = this->getBufferPtrAndMarkDirty(uni); + int32_t v[3] = { i0, i1, i2 }; + memcpy(buffer, v, 3 * sizeof(int32_t)); +} + +void GrUniformDataManager::set3iv(UniformHandle u, + int arrayCount, + const int32_t v[]) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kInt3_GrSLType || uni.fType == kShort3_GrSLType); + SkASSERT(arrayCount > 0); + SkASSERT(arrayCount <= uni.fArrayCount || + (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); + + void* buffer = this->getBufferPtrAndMarkDirty(uni); + SkASSERT(sizeof(int32_t) == 4); + for (int i = 0; i < arrayCount; ++i) { + const int32_t* curVec = &v[3 * i]; + memcpy(buffer, curVec, 3 * sizeof(int32_t)); + buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t); + } +} + +void GrUniformDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_GrSLType); + SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); + void* buffer = this->getBufferPtrAndMarkDirty(uni); + SkASSERT(sizeof(float) == 4); + float v[3] = { v0, v1, v2 }; + memcpy(buffer, v, 3 * sizeof(float)); +} + +void GrUniformDataManager::set3fv(UniformHandle u, + int arrayCount, + const float v[]) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_GrSLType); + SkASSERT(arrayCount > 0); + SkASSERT(arrayCount <= uni.fArrayCount || + (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); + + void* buffer = this->getBufferPtrAndMarkDirty(uni); + SkASSERT(sizeof(float) == 4); + for (int i = 0; i < arrayCount; ++i) { + const float* curVec = &v[3 * i]; + memcpy(buffer, curVec, 3 * sizeof(float)); + buffer = static_cast<char*>(buffer) + 4*sizeof(float); + } +} + +void GrUniformDataManager::set4i(UniformHandle u, + int32_t i0, + int32_t i1, + int32_t i2, + int32_t i3) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kInt4_GrSLType || uni.fType == kShort4_GrSLType); + SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); + void* buffer = this->getBufferPtrAndMarkDirty(uni); + int32_t v[4] = { i0, i1, i2, i3 }; + memcpy(buffer, v, 4 * sizeof(int32_t)); +} + +void GrUniformDataManager::set4iv(UniformHandle u, + int arrayCount, + const int32_t v[]) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kInt4_GrSLType || uni.fType == kShort4_GrSLType); + SkASSERT(arrayCount > 0); + SkASSERT(arrayCount <= uni.fArrayCount || + (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); + + void* buffer = this->getBufferPtrAndMarkDirty(uni); + SkASSERT(sizeof(int32_t) == 4); + for (int i = 0; i < arrayCount; ++i) { + const int32_t* curVec = &v[4 * i]; + memcpy(buffer, curVec, 4 * sizeof(int32_t)); + buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t); + } +} + +void GrUniformDataManager::set4f(UniformHandle u, + float v0, + float v1, + float v2, + float v3) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_GrSLType); + SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); + void* buffer = this->getBufferPtrAndMarkDirty(uni); + SkASSERT(sizeof(float) == 4); + float v[4] = { v0, v1, v2, v3 }; + memcpy(buffer, v, 4 * sizeof(float)); +} + +void GrUniformDataManager::set4fv(UniformHandle u, + int arrayCount, + const float v[]) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_GrSLType); + SkASSERT(arrayCount > 0); + SkASSERT(arrayCount <= uni.fArrayCount || + (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); + + void* buffer = this->getBufferPtrAndMarkDirty(uni); + SkASSERT(sizeof(float) == 4); + memcpy(buffer, v, arrayCount * 4 * sizeof(float)); +} + +void GrUniformDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const { + this->setMatrices<2>(u, 1, matrix); +} + +void GrUniformDataManager::setMatrix2fv(UniformHandle u, + int arrayCount, + const float m[]) const { + this->setMatrices<2>(u, arrayCount, m); +} + +void GrUniformDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const { + this->setMatrices<3>(u, 1, matrix); +} + +void GrUniformDataManager::setMatrix3fv(UniformHandle u, + int arrayCount, + const float m[]) const { + this->setMatrices<3>(u, arrayCount, m); +} + +void GrUniformDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const { + this->setMatrices<4>(u, 1, matrix); +} + +void GrUniformDataManager::setMatrix4fv(UniformHandle u, + int arrayCount, + const float m[]) const { + this->setMatrices<4>(u, arrayCount, m); +} + +template<int N> struct set_uniform_matrix; + +template<int N> inline void GrUniformDataManager::setMatrices(UniformHandle u, + int arrayCount, + const float matrices[]) const { + const Uniform& uni = fUniforms[u.toIndex()]; + SkASSERT(uni.fType == kFloat2x2_GrSLType + (N - 2) || + uni.fType == kHalf2x2_GrSLType + (N - 2)); + SkASSERT(arrayCount > 0); + SkASSERT(arrayCount <= uni.fArrayCount || + (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); + + void* buffer = fUniformData.get(); + fUniformsDirty = true; + + set_uniform_matrix<N>::set(buffer, uni.fOffset, arrayCount, matrices); +} + +template<int N> struct set_uniform_matrix { + inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) { + static_assert(sizeof(float) == 4); + buffer = static_cast<char*>(buffer) + uniformOffset; + for (int i = 0; i < count; ++i) { + const float* matrix = &matrices[N * N * i]; + for (int j = 0; j < N; ++j) { + memcpy(buffer, &matrix[j * N], N * sizeof(float)); + buffer = static_cast<char*>(buffer) + 4 * sizeof(float); + } + } + } +}; + +template<> struct set_uniform_matrix<4> { + inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) { + static_assert(sizeof(float) == 4); + buffer = static_cast<char*>(buffer) + uniformOffset; + memcpy(buffer, matrices, count * 16 * sizeof(float)); + } +}; + diff --git a/chromium/third_party/skia/src/gpu/GrUniformDataManager.h b/chromium/third_party/skia/src/gpu/GrUniformDataManager.h new file mode 100644 index 00000000000..dc08bcf0d2b --- /dev/null +++ b/chromium/third_party/skia/src/gpu/GrUniformDataManager.h @@ -0,0 +1,77 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrUniformDataManager_DEFINED +#define GrUniformDataManager_DEFINED + +#include "src/gpu/glsl/GrGLSLProgramDataManager.h" + +#include "include/private/GrTypesPriv.h" +#include "include/private/SkTArray.h" +#include "src/core/SkAutoMalloc.h" + +class GrUniformDataManager : public GrGLSLProgramDataManager { +public: + GrUniformDataManager(uint32_t uniformCount, uint32_t uniformSize); + + void set1i(UniformHandle, int32_t) const override; + void set1iv(UniformHandle, int arrayCount, const int32_t v[]) const override; + void set1f(UniformHandle, float v0) const override; + void set1fv(UniformHandle, int arrayCount, const float v[]) const override; + void set2i(UniformHandle, int32_t, int32_t) const override; + void set2iv(UniformHandle, int arrayCount, const int32_t v[]) const override; + void set2f(UniformHandle, float, float) const override; + void set2fv(UniformHandle, int arrayCount, const float v[]) const override; + void set3i(UniformHandle, int32_t, int32_t, int32_t) const override; + void set3iv(UniformHandle, int arrayCount, const int32_t v[]) const override; + void set3f(UniformHandle, float, float, float) const override; + void set3fv(UniformHandle, int arrayCount, const float v[]) const override; + void set4i(UniformHandle, int32_t, int32_t, int32_t, int32_t) const override; + void set4iv(UniformHandle, int arrayCount, const int32_t v[]) const override; + void set4f(UniformHandle, float, float, float, float) const override; + void set4fv(UniformHandle, int arrayCount, const float v[]) const override; + // matrices are column-major, the first two upload a single matrix, the latter two upload + // arrayCount matrices into a uniform array. + void setMatrix2f(UniformHandle, const float matrix[]) const override; + void setMatrix3f(UniformHandle, const float matrix[]) const override; + void setMatrix4f(UniformHandle, const float matrix[]) const override; + void setMatrix2fv(UniformHandle, int arrayCount, const float matrices[]) const override; + void setMatrix3fv(UniformHandle, int arrayCount, const float matrices[]) const override; + void setMatrix4fv(UniformHandle, int arrayCount, const float matrices[]) const override; + + // for nvpr only + void setPathFragmentInputTransform(VaryingHandle u, int components, + const SkMatrix& matrix) const override { + SK_ABORT("Only supported in NVPR, which is only available in GL"); + } + + // For the uniform data to be dirty so that we will reupload on the next use. + void markDirty() { fUniformsDirty = true; } + +protected: + struct Uniform { + uint32_t fOffset; + SkDEBUGCODE( + GrSLType fType; + int fArrayCount; + ); + }; + + template<int N> inline void setMatrices(UniformHandle, int arrayCount, + const float matrices[]) const; + + void* getBufferPtrAndMarkDirty(const Uniform& uni) const; + + uint32_t fUniformSize; + + SkTArray<Uniform, true> fUniforms; + + mutable SkAutoMalloc fUniformData; + mutable bool fUniformsDirty; +}; + +#endif diff --git a/chromium/third_party/skia/src/gpu/GrWaitRenderTask.cpp b/chromium/third_party/skia/src/gpu/GrWaitRenderTask.cpp index d7b2a7cc081..d9740301760 100644 --- a/chromium/third_party/skia/src/gpu/GrWaitRenderTask.cpp +++ b/chromium/third_party/skia/src/gpu/GrWaitRenderTask.cpp @@ -14,15 +14,22 @@ void GrWaitRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const { // This renderTask doesn't have "normal" ops. In this case we still need to add an interval (so // fEndOfOpsTaskOpIndices will remain in sync), so we create a fake op# to capture the fact that - // we manipulate fTargetView's proxy. - alloc->addInterval(fTargetView.proxy(), alloc->curOp(), alloc->curOp(), + // we manipulate our target's proxy. + SkASSERT(0 == this->numTargets()); + auto fakeOp = alloc->curOp(); + alloc->addInterval(fWaitedOn.proxy(), fakeOp, fakeOp, GrResourceAllocator::ActualUse::kYes); alloc->incOps(); } bool GrWaitRenderTask::onExecute(GrOpFlushState* flushState) { for (int i = 0; i < fNumSemaphores; ++i) { - flushState->gpu()->waitSemaphore(fSemaphores[i].get()); + // If we don't have a semaphore here it means we failed to wrap it. That happens if the + // client didn't give us a valid semaphore to begin with. Therefore, it is fine to not wait + // on it. + if (fSemaphores[i].get()) { + flushState->gpu()->waitSemaphore(fSemaphores[i].get()); + } } return true; } diff --git a/chromium/third_party/skia/src/gpu/GrWaitRenderTask.h b/chromium/third_party/skia/src/gpu/GrWaitRenderTask.h index 18e715755c8..4681f76209f 100644 --- a/chromium/third_party/skia/src/gpu/GrWaitRenderTask.h +++ b/chromium/third_party/skia/src/gpu/GrWaitRenderTask.h @@ -16,15 +16,14 @@ public: GrWaitRenderTask(GrSurfaceProxyView surfaceView, std::unique_ptr<std::unique_ptr<GrSemaphore>[]> semaphores, int numSemaphores) - : GrRenderTask(std::move(surfaceView)) + : GrRenderTask() , fSemaphores(std::move(semaphores)) - , fNumSemaphores(numSemaphores) {} + , fNumSemaphores(numSemaphores) + , fWaitedOn(std::move(surfaceView)) {} private: bool onIsUsed(GrSurfaceProxy* proxy) const override { - // This case should be handled by GrRenderTask. - SkASSERT(proxy != fTargetView.proxy()); - return false; + return proxy == fWaitedOn.proxy(); } void handleInternalAllocationFailure() override {} void gatherProxyIntervals(GrResourceAllocator*) const override; @@ -42,6 +41,11 @@ private: #endif std::unique_ptr<std::unique_ptr<GrSemaphore>[]> fSemaphores; int fNumSemaphores; + + // This field is separate from the main "targets" field on GrRenderTask because this task + // does not actually write to the surface and so should not participate in the normal + // lastRenderTask tracking that written-to targets do. + GrSurfaceProxyView fWaitedOn; }; #endif diff --git a/chromium/third_party/skia/src/gpu/GrYUVProvider.cpp b/chromium/third_party/skia/src/gpu/GrYUVProvider.cpp index 6a25a79562b..3d5668c6f30 100644 --- a/chromium/third_party/skia/src/gpu/GrYUVProvider.cpp +++ b/chromium/third_party/skia/src/gpu/GrYUVProvider.cpp @@ -16,7 +16,6 @@ #include "src/core/SkYUVPlanesCache.h" #include "src/gpu/GrBitmapTextureMaker.h" #include "src/gpu/GrCaps.h" -#include "src/gpu/GrClip.h" #include "src/gpu/GrColorSpaceXform.h" #include "src/gpu/GrProxyProvider.h" #include "src/gpu/GrRecordingContextPriv.h" @@ -191,7 +190,7 @@ GrSurfaceProxyView GrYUVProvider::refAsTextureProxyView(GrRecordingContext* ctx, yuvSizeInfo.fSizes[0].fHeight); SkMatrix m = SkEncodedOriginToMatrix(yuvSizeInfo.fOrigin, r.width(), r.height()); - renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, m, r); + renderTargetContext->drawRect(nullptr, std::move(paint), GrAA::kNo, m, r); SkASSERT(renderTargetContext->asTextureProxy()); return renderTargetContext->readSurfaceView(); diff --git a/chromium/third_party/skia/src/gpu/SkGpuDevice.cpp b/chromium/third_party/skia/src/gpu/SkGpuDevice.cpp index fcd15fa7aad..aa949a3acc3 100644 --- a/chromium/third_party/skia/src/gpu/SkGpuDevice.cpp +++ b/chromium/third_party/skia/src/gpu/SkGpuDevice.cpp @@ -48,8 +48,7 @@ #include "src/image/SkSurface_Gpu.h" #include "src/utils/SkUTF.h" -#define ASSERT_SINGLE_OWNER \ -SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->priv().singleOwner());) +#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fContext->priv().singleOwner()) /////////////////////////////////////////////////////////////////////////////// @@ -125,7 +124,8 @@ SkGpuDevice::SkGpuDevice(GrContext* context, : INHERITED(make_info(renderTargetContext.get(), SkToBool(flags & kIsOpaque_Flag)), renderTargetContext->surfaceProps()) , fContext(SkRef(context)) - , fRenderTargetContext(std::move(renderTargetContext)) { + , fRenderTargetContext(std::move(renderTargetContext)) + , fClip(fRenderTargetContext->dimensions(), &this->cs(), &this->asMatrixProvider()) { if (flags & kNeedClear_Flag) { this->clearAll(); } @@ -209,8 +209,7 @@ void SkGpuDevice::clearAll() { GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "clearAll", fContext.get()); SkIRect rect = SkIRect::MakeWH(this->width(), this->height()); - fRenderTargetContext->clear(&rect, SK_PMColor4fTRANSPARENT, - GrRenderTargetContext::CanClearFullscreen::kYes); + fRenderTargetContext->priv().clearAtLeast(rect, SK_PMColor4fTRANSPARENT); } void SkGpuDevice::replaceRenderTargetContext(std::unique_ptr<GrRenderTargetContext> rtc, @@ -325,13 +324,12 @@ void SkGpuDevice::drawPoints(SkCanvas::PointMode mode, const SkMatrixProvider* matrixProvider = this; #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK - SkTLazy<SkPostConcatMatrixProvider> postConcatMatrixProvider; + SkTLazy<SkPostTranslateMatrixProvider> postTranslateMatrixProvider; // This offsetting in device space matches the expectations of the Android framework for non-AA // points and lines. if (GrIsPrimTypeLines(primitiveType) || GrPrimitiveType::kPoints == primitiveType) { static const SkScalar kOffset = 0.063f; // Just greater than 1/16. - matrixProvider = postConcatMatrixProvider.init(*matrixProvider, - SkMatrix::MakeTrans(kOffset, kOffset)); + matrixProvider = postTranslateMatrixProvider.init(*matrixProvider, kOffset, kOffset); } #endif @@ -630,8 +628,7 @@ void SkGpuDevice::drawPath(const SkPath& origSrcPath, const SkPaint& paint, bool paint, this->asMatrixProvider(), shape); } -void SkGpuDevice::drawSpecial(SkSpecialImage* special, int left, int top, const SkPaint& paint, - SkImage* clipImage, const SkMatrix& clipMatrix) { +void SkGpuDevice::drawSpecial(SkSpecialImage* special, int left, int top, const SkPaint& paint) { SkASSERT(!paint.getMaskFilter()); ASSERT_SINGLE_OWNER @@ -687,55 +684,7 @@ void SkGpuDevice::drawSpecial(SkSpecialImage* special, int left, int top, const const SkIRect& subset = result->subset(); SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(left, top, subset.width(), subset.height())); SkRect srcRect = SkRect::Make(subset); - if (clipImage) { - // Add the image as a simple texture effect applied to coverage. Accessing content outside - // of the clip image should behave as if it were a decal (i.e. zero coverage). However, to - // limit pixels touched and hardware checks, we draw the clip image geometry to get the - // decal effect. - auto filter = paint.getFilterQuality() > kNone_SkFilterQuality - ? GrSamplerState::Filter::kBilerp - : GrSamplerState::Filter::kNearest; - GrSurfaceProxyView clipView = as_IB(clipImage)->refView(this->context(), GrMipMapped::kNo); - // Fold clip matrix into ctm - ctm.preConcat(clipMatrix); - SkMatrix inverseClipMatrix; - - std::unique_ptr<GrFragmentProcessor> cfp; - if (clipView && ctm.invert(&inverseClipMatrix)) { - GrColorType srcColorType = SkColorTypeToGrColorType(clipImage->colorType()); - - cfp = GrTextureEffect::Make(std::move(clipView), clipImage->alphaType(), - inverseClipMatrix, filter); - if (srcColorType != GrColorType::kAlpha_8) { - cfp = GrFragmentProcessor::SwizzleOutput(std::move(cfp), GrSwizzle::AAAA()); - } - } - if (cfp) { - // If the grPaint already has coverage, this adds an additional stage that multiples - // the image's alpha channel with the prior coverage. - grPaint.addCoverageFragmentProcessor(std::move(cfp)); - - // Undo the offset that was needed for shader coord transforms to get the transform for - // the actual drawn geometry. - ctm.postTranslate(SkIntToScalar(left), SkIntToScalar(top)); - inverseClipMatrix.preTranslate(-SkIntToScalar(left), -SkIntToScalar(top)); - SkRect clipGeometry = SkRect::MakeWH(clipImage->width(), clipImage->height()); - if (!clipGeometry.contains(inverseClipMatrix.mapRect(dstRect))) { - // Draw the clip geometry since it is smaller, using dstRect as an extra scissor - SkClipStack clip(this->cs()); - clip.clipDevRect(SkIRect::MakeXYWH(left, top, subset.width(), subset.height()), - SkClipOp::kIntersect); - SkMatrix local = SkMatrix::Concat(SkMatrix::MakeRectToRect( - dstRect, srcRect, SkMatrix::kFill_ScaleToFit), ctm); - fRenderTargetContext->fillRectWithLocalMatrix(GrClipStackClip(&clip), - std::move(grPaint), GrAA(paint.isAntiAlias()), ctm, clipGeometry, local); - return; - } - // Else fall through and draw the subset since that is contained in the clip geometry - } - // Else some issue configuring the coverage FP, so just draw without the clip mask image - } // Draw directly in screen space, possibly with an extra coverage processor fRenderTargetContext->fillRectToRect(this->clip(), std::move(grPaint), GrAA(paint.isAntiAlias()), SkMatrix::I(), dstRect, srcRect); @@ -844,7 +793,7 @@ void SkGpuDevice::drawDevice(SkBaseDevice* device, return; } - this->drawSpecial(srcImg.get(), left, top, paint, nullptr, SkMatrix::I()); + this->drawSpecial(srcImg.get(), left, top, paint); } void SkGpuDevice::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, @@ -941,12 +890,11 @@ static bool init_vertices_paint(GrContext* context, const SkPaint& skPaint, const SkMatrixProvider& matrixProvider, SkBlendMode bmode, - bool hasTexs, bool hasColors, GrPaint* grPaint) { - if (hasTexs && skPaint.getShader()) { + if (skPaint.getShader()) { if (hasColors) { - // When there are texs and colors the shader and colors are combined using bmode. + // When there are colors and a shader, the shader and colors are combined using bmode. return SkPaintToGrPaintWithXfermode(context, colorInfo, skPaint, matrixProvider, bmode, grPaint); } else { @@ -955,12 +903,11 @@ static bool init_vertices_paint(GrContext* context, } } else { if (hasColors) { - // We have colors, but either have no shader or no texture coords (which implies that - // we should ignore the shader). + // We have colors, but no shader. return SkPaintToGrPaintWithPrimitiveColor(context, colorInfo, skPaint, matrixProvider, grPaint); } else { - // No colors and no shaders. Just draw with the paint color. + // No colors and no shader. Just draw with the paint color. return SkPaintToGrPaintNoShader(context, colorInfo, skPaint, matrixProvider, grPaint); } } @@ -976,13 +923,9 @@ void SkGpuDevice::drawVertices(const SkVertices* vertices, SkBlendMode mode, con const SkRuntimeEffect* effect = paint.getShader() ? as_SB(paint.getShader())->asRuntimeEffect() : nullptr; - // Pretend that we have tex coords when using custom per-vertex data. The shader is going to - // use those (rather than local coords), but our paint conversion remains the same. GrPaint grPaint; - bool hasColors = info.hasColors(); - bool hasTexs = info.hasTexCoords() || info.hasCustomData(); if (!init_vertices_paint(fContext.get(), fRenderTargetContext->colorInfo(), paint, - this->asMatrixProvider(), mode, hasTexs, hasColors, &grPaint)) { + this->asMatrixProvider(), mode, info.hasColors(), &grPaint)) { return; } fRenderTargetContext->drawVertices(this->clip(), std::move(grPaint), this->asMatrixProvider(), @@ -1067,14 +1010,16 @@ void SkGpuDevice::drawDrawable(SkDrawable* drawable, const SkMatrix* matrix, SkC /////////////////////////////////////////////////////////////////////////////// void SkGpuDevice::flush() { - this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo()); + this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo(), nullptr); + this->context()->submit(); } GrSemaphoresSubmitted SkGpuDevice::flush(SkSurface::BackendSurfaceAccess access, - const GrFlushInfo& info) { + const GrFlushInfo& info, + const GrBackendSurfaceMutableState* newState) { ASSERT_SINGLE_OWNER - return fRenderTargetContext->flush(access, info); + return fRenderTargetContext->flush(access, info, newState); } bool SkGpuDevice::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) { @@ -1143,7 +1088,6 @@ bool SkGpuDevice::android_utils_clipWithStencil() { } GrPaint grPaint; grPaint.setXPFactory(GrDisableColorXPFactory::Get()); - GrNoClip noClip; static constexpr GrUserStencilSettings kDrawToStencil( GrUserStencilSettings::StaticInit< 0x1, @@ -1153,7 +1097,7 @@ bool SkGpuDevice::android_utils_clipWithStencil() { GrUserStencilOp::kReplace, 0x1>() ); - rtc->drawRegion(noClip, std::move(grPaint), GrAA::kNo, SkMatrix::I(), clipRegion, + rtc->drawRegion(nullptr, std::move(grPaint), GrAA::kNo, SkMatrix::I(), clipRegion, GrStyle::SimpleFill(), &kDrawToStencil); return true; } diff --git a/chromium/third_party/skia/src/gpu/SkGpuDevice.h b/chromium/third_party/skia/src/gpu/SkGpuDevice.h index 664aaf0b5c9..75aa82db57b 100644 --- a/chromium/third_party/skia/src/gpu/SkGpuDevice.h +++ b/chromium/third_party/skia/src/gpu/SkGpuDevice.h @@ -101,8 +101,7 @@ public: void drawDevice(SkBaseDevice*, int x, int y, const SkPaint&) override; - void drawSpecial(SkSpecialImage*, int left, int top, const SkPaint& paint, - SkImage*, const SkMatrix&) override; + void drawSpecial(SkSpecialImage*, int left, int top, const SkPaint&) override; void drawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], SkCanvas::QuadAAFlags aaFlags, const SkColor4f& color, SkBlendMode mode) override; @@ -114,7 +113,8 @@ public: sk_sp<SkSpecialImage> snapSpecial(const SkIRect&, bool = false) override; void flush() override; - GrSemaphoresSubmitted flush(SkSurface::BackendSurfaceAccess access, const GrFlushInfo&); + GrSemaphoresSubmitted flush(SkSurface::BackendSurfaceAccess access, const GrFlushInfo&, + const GrBackendSurfaceMutableState*); bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores); bool onAccessPixels(SkPixmap*) override; @@ -129,6 +129,7 @@ private: // We want these unreffed in RenderTargetContext, GrContext order. sk_sp<GrContext> fContext; std::unique_ptr<GrRenderTargetContext> fRenderTargetContext; + GrClipStackClip fClip; enum Flags { kNeedClear_Flag = 1 << 0, //!< Surface requires an initial clear @@ -148,7 +149,7 @@ private: bool forceConservativeRasterClip() const override { return true; } - GrClipStackClip clip() const { return GrClipStackClip(&this->cs()); } + const GrClip* clip() const { return &fClip; } sk_sp<SkSpecialImage> filterTexture(SkSpecialImage*, int left, int top, diff --git a/chromium/third_party/skia/src/gpu/SkGpuDevice_drawTexture.cpp b/chromium/third_party/skia/src/gpu/SkGpuDevice_drawTexture.cpp index 3534b6cd844..4ef4d653950 100644 --- a/chromium/third_party/skia/src/gpu/SkGpuDevice_drawTexture.cpp +++ b/chromium/third_party/skia/src/gpu/SkGpuDevice_drawTexture.cpp @@ -125,12 +125,13 @@ static int determine_tile_size(const SkIRect& src, int maxTileSize) { // Given a bitmap, an optional src rect, and a context with a clip and matrix determine what // pixels from the bitmap are necessary. static SkIRect determine_clipped_src_rect(int width, int height, - const GrClip& clip, + const GrClip* clip, const SkMatrix& viewMatrix, const SkMatrix& srcToDstRect, const SkISize& imageDimensions, const SkRect* srcRectPtr) { - SkIRect clippedSrcIRect = clip.getConservativeBounds(width, height); + SkIRect clippedSrcIRect = clip ? clip->getConservativeBounds() + : SkIRect::MakeWH(width, height); SkMatrix inv = SkMatrix::Concat(viewMatrix, srcToDstRect); if (!inv.invert(&inv)) { return SkIRect::MakeEmpty(); @@ -154,7 +155,7 @@ static SkIRect determine_clipped_src_rect(int width, int height, // tileSize and clippedSubset are valid if true is returned static bool should_tile_image_id(GrContext* context, SkISize rtSize, - const GrClip& clip, + const GrClip* clip, uint32_t imageID, const SkISize& imageSize, const SkMatrix& ctm, @@ -318,8 +319,19 @@ static bool can_use_draw_texture(const SkPaint& paint) { !paint.getImageFilter() && paint.getFilterQuality() < kMedium_SkFilterQuality); } +static SkPMColor4f texture_color(SkColor4f paintColor, float entryAlpha, GrColorType srcColorType, + const GrColorInfo& dstColorInfo) { + paintColor.fA *= entryAlpha; + if (GrColorTypeIsAlphaOnly(srcColorType)) { + return SkColor4fPrepForDst(paintColor, dstColorInfo).premul(); + } else { + float paintAlpha = SkTPin(paintColor.fA, 0.f, 1.f); + return { paintAlpha, paintAlpha, paintAlpha, paintAlpha }; + } +} + // Assumes srcRect and dstRect have already been optimized to fit the proxy -static void draw_texture(GrRenderTargetContext* rtc, const GrClip& clip, const SkMatrix& ctm, +static void draw_texture(GrRenderTargetContext* rtc, const GrClip* clip, const SkMatrix& ctm, const SkPaint& paint, const SkRect& srcRect, const SkRect& dstRect, const SkPoint dstClip[4], GrAA aa, GrQuadAAFlags aaFlags, SkCanvas::SrcRectConstraint constraint, GrSurfaceProxyView view, @@ -354,14 +366,8 @@ static void draw_texture(GrRenderTargetContext* rtc, const GrClip& clip, const S constraint = SkCanvas::kStrict_SrcRectConstraint; } } - SkPMColor4f color; - if (GrColorTypeIsAlphaOnly(srcColorInfo.colorType())) { - color = SkColor4fPrepForDst(paint.getColor4f(), dstInfo).premul(); - } else { - float paintAlpha = paint.getColor4f().fA; - color = { paintAlpha, paintAlpha, paintAlpha, paintAlpha }; - } + SkPMColor4f color = texture_color(paint.getColor4f(), 1.f, srcColorInfo.colorType(), dstInfo); if (dstClip) { // Get source coords corresponding to dstClip SkPoint srcQuad[4]; @@ -382,7 +388,7 @@ static void draw_texture(GrRenderTargetContext* rtc, const GrClip& clip, const S // Assumes srcRect and dstRect have already been optimized to fit the proxy. static void draw_texture_producer(GrContext* context, GrRenderTargetContext* rtc, - const GrClip& clip, + const GrClip* clip, const SkMatrixProvider& matrixProvider, const SkPaint& paint, GrTextureProducer* producer, @@ -510,7 +516,7 @@ static void draw_texture_producer(GrContext* context, void draw_tiled_bitmap(GrContext* context, GrRenderTargetContext* rtc, - const GrClip& clip, + const GrClip* clip, const SkBitmap& bitmap, int tileSize, const SkMatrixProvider& matrixProvider, @@ -844,7 +850,9 @@ void SkGpuDevice::drawEdgeAAImageSet(const SkCanvas::ImageSetEntry set[], int co textures[i].fDstClipQuad = clip; textures[i].fPreViewMatrix = set[i].fMatrixIndex < 0 ? nullptr : preViewMatrices + set[i].fMatrixIndex; - textures[i].fAlpha = set[i].fAlpha * paint.getAlphaf(); + textures[i].fColor = texture_color(paint.getColor4f(), set[i].fAlpha, + SkColorTypeToGrColorType(image->colorType()), + fRenderTargetContext->colorInfo()); textures[i].fAAFlags = SkToGrQuadAAFlags(set[i].fAAFlags); if (n > 0 && diff --git a/chromium/third_party/skia/src/gpu/SkGr.cpp b/chromium/third_party/skia/src/gpu/SkGr.cpp index 9c66d396ce7..9b77a281fc5 100644 --- a/chromium/third_party/skia/src/gpu/SkGr.cpp +++ b/chromium/third_party/skia/src/gpu/SkGr.cpp @@ -20,6 +20,7 @@ #include "include/private/SkTemplates.h" #include "src/core/SkAutoMalloc.h" #include "src/core/SkBlendModePriv.h" +#include "src/core/SkColorFilterBase.h" #include "src/core/SkColorSpacePriv.h" #include "src/core/SkImagePriv.h" #include "src/core/SkMaskFilterBase.h" @@ -48,38 +49,39 @@ #include "src/shaders/SkShaderBase.h" GR_FP_SRC_STRING SKSL_DITHER_SRC = R"( -// This controls the range of values added to color channels -in int rangeType; +// This controls the range of values added to color channels and is based on the destination color +// type; as such it doesn't really affect our program cache to have a variant per-range. +in half range; -void main(float2 p, inout half4 color) { +void main(inout half4 color) { half value; - half range; - @switch (rangeType) { - case 0: - range = 1.0 / 255.0; - break; - case 1: - range = 1.0 / 63.0; - break; - default: - // Experimentally this looks better than the expected value of 1/15. - range = 1.0 / 15.0; - break; - } - @if (sk_Caps.integerSupport) { + @if (sk_Caps.integerSupport) + { // This ordered-dither code is lifted from the cpu backend. - uint x = uint(p.x); - uint y = uint(p.y); + uint x = uint(sk_FragCoord.x); + uint y = uint(sk_FragCoord.y) ^ x; uint m = (y & 1) << 5 | (x & 1) << 4 | (y & 2) << 2 | (x & 2) << 1 | (y & 4) >> 1 | (x & 4) >> 2; value = half(m) * 1.0 / 64.0 - 63.0 / 128.0; } else { - // Simulate the integer effect used above using step/mod. For speed, simulates a 4x4 - // dither pattern rather than an 8x8 one. - half4 modValues = mod(half4(half(p.x), half(p.y), half(p.x), half(p.y)), half4(2.0, 2.0, 4.0, 4.0)); - half4 stepValues = step(modValues, half4(1.0, 1.0, 2.0, 2.0)); - value = dot(stepValues, half4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0; + // Simulate the integer effect used above using step/mod/abs. For speed, simulates a 4x4 + // dither pattern rather than an 8x8 one. Since it's 4x4, this is effectively computing: + // uint m = (y & 1) << 3 | (x & 1) << 2 | + // (y & 2) << 0 | (x & 2) >> 1; + // where 'y' has already been XOR'ed with 'x' as in the integer-supported case. + + // To get the low bit of p.x and p.y, we compute mod 2.0; for the high bit, we mod 4.0 + half4 bits = mod(half4(sk_FragCoord.yxyx), half4(2.0, 2.0, 4.0, 4.0)); + // Use step to convert the 0-3 value in bits.zw into a 0|1 value. bits.xy is already 0|1. + bits.zw = step(2.0, bits.zw); + // bits was constructed such that the p.x bits were already in the right place for + // interleaving (in bits.yw). We just need to update the other bits from p.y to (p.x ^ p.y). + // These are in bits.xz. Since the values are 0|1, we can simulate ^ as abs(y - x). + bits.xz = abs(bits.xz - bits.yw); + + // Manual binary sum, divide by N^2, and offset + value = dot(bits, half4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0; } // For each color channel, add the random offset to the channel value and then clamp // between 0 and alpha to keep the color premultiplied. @@ -198,39 +200,50 @@ static inline bool blend_requires_shader(const SkBlendMode mode) { } #ifndef SK_IGNORE_GPU_DITHER -static inline int32_t dither_range_type_for_config(GrColorType dstColorType) { +static inline float dither_range_for_config(GrColorType dstColorType) { + // We use 1 / (2^bitdepth-1) as the range since each channel can hold 2^bitdepth values switch (dstColorType) { + // 4 bit + case GrColorType::kABGR_4444: + return 1 / 15.f; + // 6 bit + case GrColorType::kBGR_565: + return 1 / 63.f; + // 8 bit case GrColorType::kUnknown: + case GrColorType::kAlpha_8: + case GrColorType::kAlpha_8xxx: case GrColorType::kGray_8: - case GrColorType::kRGBA_8888: - case GrColorType::kRGB_888x: + case GrColorType::kGray_8xxx: + case GrColorType::kR_8: case GrColorType::kRG_88: - case GrColorType::kBGRA_8888: - case GrColorType::kRG_1616: - case GrColorType::kRGBA_16161616: - case GrColorType::kRG_F16: + case GrColorType::kRGB_888: + case GrColorType::kRGB_888x: + case GrColorType::kRGBA_8888: case GrColorType::kRGBA_8888_SRGB: + case GrColorType::kBGRA_8888: + return 1 / 255.f; + // 10 bit case GrColorType::kRGBA_1010102: case GrColorType::kBGRA_1010102: + return 1 / 1023.f; + // 16 bit + case GrColorType::kAlpha_16: + case GrColorType::kR_16: + case GrColorType::kRG_1616: + case GrColorType::kRGBA_16161616: + return 1 / 32767.f; + // Half case GrColorType::kAlpha_F16: - case GrColorType::kRGBA_F32: + case GrColorType::kGray_F16: + case GrColorType::kR_F16: + case GrColorType::kRG_F16: case GrColorType::kRGBA_F16: case GrColorType::kRGBA_F16_Clamped: - case GrColorType::kAlpha_8: - case GrColorType::kAlpha_8xxx: - case GrColorType::kAlpha_16: + // Float case GrColorType::kAlpha_F32xxx: - case GrColorType::kGray_8xxx: - case GrColorType::kRGB_888: - case GrColorType::kR_8: - case GrColorType::kR_16: - case GrColorType::kR_F16: - case GrColorType::kGray_F16: - return 0; - case GrColorType::kBGR_565: - return 1; - case GrColorType::kABGR_4444: - return 2; + case GrColorType::kRGBA_F32: + return 0.f; // no dithering } SkUNREACHABLE; } @@ -250,15 +263,17 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context, // Setup the initial color considering the shader, the SkPaint color, and the presence or not // of per-vertex colors. - std::unique_ptr<GrFragmentProcessor> shaderFP; + std::unique_ptr<GrFragmentProcessor> paintFP; if (!primColorMode || blend_requires_shader(*primColorMode)) { fpArgs.fInputColorIsOpaque = origColor.isOpaque(); if (shaderProcessor) { - shaderFP = std::move(*shaderProcessor); - } else if (const auto* shader = as_SB(skPaint.getShader())) { - shaderFP = shader->asFragmentProcessor(fpArgs); - if (!shaderFP) { - return false; + paintFP = std::move(*shaderProcessor); + } else { + if (const SkShaderBase* shader = as_SB(skPaint.getShader())) { + paintFP = shader->asFragmentProcessor(fpArgs); + if (paintFP == nullptr) { + return false; + } } } } @@ -267,7 +282,7 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context, // a known constant value. In that case we can simply apply a color filter during this // conversion without converting the color filter to a GrFragmentProcessor. bool applyColorFilterToPaintColor = false; - if (shaderFP) { + if (paintFP) { if (primColorMode) { // There is a blend between the primitive color and the shader color. The shader sees // the opaque paint color. The shader's output is blended using the provided mode by @@ -277,43 +292,33 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context, // the GrPaint color will be ignored. SkPMColor4f shaderInput = origColor.makeOpaque().premul(); - shaderFP = GrFragmentProcessor::OverrideInput(std::move(shaderFP), shaderInput); - shaderFP = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(shaderFP), - *primColorMode); - - // The above may return null if compose results in a pass through of the prim color. - if (shaderFP) { - grPaint->addColorFragmentProcessor(std::move(shaderFP)); - } + paintFP = GrFragmentProcessor::OverrideInput(std::move(paintFP), shaderInput); + paintFP = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(paintFP), + *primColorMode); // We can ignore origColor here - alpha is unchanged by gamma float paintAlpha = skPaint.getColor4f().fA; if (1.0f != paintAlpha) { // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all // color channels. It's value should be treated as the same in ANY color space. - grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make( - { paintAlpha, paintAlpha, paintAlpha, paintAlpha }, - GrConstColorProcessor::InputMode::kModulateRGBA)); + paintFP = GrConstColorProcessor::Make( + std::move(paintFP), { paintAlpha, paintAlpha, paintAlpha, paintAlpha }, + GrConstColorProcessor::InputMode::kModulateRGBA); } } else { // The shader's FP sees the paint *unpremul* color SkPMColor4f origColorAsPM = { origColor.fR, origColor.fG, origColor.fB, origColor.fA }; grPaint->setColor4f(origColorAsPM); - grPaint->addColorFragmentProcessor(std::move(shaderFP)); } } else { if (primColorMode) { // There is a blend between the primitive color and the paint color. The blend considers // the opaque paint color. The paint's alpha is applied to the post-blended color. SkPMColor4f opaqueColor = origColor.makeOpaque().premul(); - auto processor = GrConstColorProcessor::Make(opaqueColor, - GrConstColorProcessor::InputMode::kIgnore); - processor = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(processor), - *primColorMode); - if (processor) { - grPaint->addColorFragmentProcessor(std::move(processor)); - } - + paintFP = GrConstColorProcessor::Make(/*inputFP=*/nullptr, opaqueColor, + GrConstColorProcessor::InputMode::kIgnore); + paintFP = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(paintFP), + *primColorMode); grPaint->setColor4f(opaqueColor); // We can ignore origColor here - alpha is unchanged by gamma @@ -321,9 +326,9 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context, if (1.0f != paintAlpha) { // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all // color channels. It's value should be treated as the same in ANY color space. - grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make( - { paintAlpha, paintAlpha, paintAlpha, paintAlpha }, - GrConstColorProcessor::InputMode::kModulateRGBA)); + paintFP = GrConstColorProcessor::Make( + std::move(paintFP), { paintAlpha, paintAlpha, paintAlpha, paintAlpha }, + GrConstColorProcessor::InputMode::kModulateRGBA); } } else { // No shader, no primitive color. @@ -332,13 +337,17 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context, } } + if (paintFP) { + grPaint->addColorFragmentProcessor(std::move(paintFP)); + } + SkColorFilter* colorFilter = skPaint.getColorFilter(); if (colorFilter) { if (applyColorFilterToPaintColor) { SkColorSpace* dstCS = dstColorInfo.colorSpace(); grPaint->setColor4f(colorFilter->filterColor4f(origColor, dstCS, dstCS).premul()); } else { - auto cfFP = colorFilter->asFragmentProcessor(context, dstColorInfo); + auto cfFP = as_CFB(colorFilter)->asFragmentProcessor(context, dstColorInfo); if (cfFP) { grPaint->addColorFragmentProcessor(std::move(cfFP)); } else { @@ -367,12 +376,15 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context, GrColorType ct = dstColorInfo.colorType(); if (SkPaintPriv::ShouldDither(skPaint, GrColorTypeToSkColorType(ct)) && grPaint->numColorFragmentProcessors() > 0) { - int32_t ditherRange = dither_range_type_for_config(ct); - if (ditherRange >= 0) { + float ditherRange = dither_range_for_config(ct); + if (ditherRange > 0.f) { static auto effect = std::get<0>(SkRuntimeEffect::Make(SkString(SKSL_DITHER_SRC))); auto ditherFP = GrSkSLFP::Make(context, effect, "Dither", SkData::MakeWithCopy(&ditherRange, sizeof(ditherRange))); if (ditherFP) { + // The dither shader doesn't actually use input coordinates, but if we don't set + // this flag, the generated shader includes an extra local coord varying. + ditherFP->temporary_SetExplicitlySampled(); grPaint->addColorFragmentProcessor(std::move(ditherFP)); } } @@ -380,7 +392,8 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context, #endif if (GrColorTypeClampType(dstColorInfo.colorType()) == GrClampType::kManual) { if (grPaint->numColorFragmentProcessors()) { - grPaint->addColorFragmentProcessor(GrClampFragmentProcessor::Make(false)); + grPaint->addColorFragmentProcessor( + GrClampFragmentProcessor::Make(/*inputFP=*/nullptr, /*clampToPremul=*/false)); } else { auto color = grPaint->getColor4f(); grPaint->setColor4f({SkTPin(color.fR, 0.f, 1.f), diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCAtlas.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCCAtlas.cpp index a980f688841..8cf105e6740 100644 --- a/chromium/third_party/skia/src/gpu/ccpr/GrCCAtlas.cpp +++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCAtlas.cpp @@ -7,6 +7,7 @@ #include "src/gpu/ccpr/GrCCAtlas.h" +#include "src/core/SkIPoint16.h" #include "src/gpu/GrOnFlushResourceProvider.h" #include "src/gpu/ccpr/GrCCPathCache.h" @@ -84,13 +85,16 @@ sk_sp<GrCCCachedAtlas> GrCCAtlas::refOrMakeCachedAtlas(GrOnFlushResourceProvider GrCCAtlas* GrCCAtlasStack::addRect(const SkIRect& devIBounds, SkIVector* devToAtlasOffset) { GrCCAtlas* retiredAtlas = nullptr; - if (fAtlases.empty() || !fAtlases.back().addRect(devIBounds, devToAtlasOffset)) { + SkIPoint16 location; + if (fAtlases.empty() || + !fAtlases.back().addRect(devIBounds.width(), devIBounds.height(), &location)) { // The retired atlas is out of room and can't grow any bigger. retiredAtlas = !fAtlases.empty() ? &fAtlases.back() : nullptr; fAtlases.emplace_back(fCoverageType, fSpecs, *fCaps); SkASSERT(devIBounds.width() <= fSpecs.fMinWidth); SkASSERT(devIBounds.height() <= fSpecs.fMinHeight); - SkAssertResult(fAtlases.back().addRect(devIBounds, devToAtlasOffset)); + SkAssertResult(fAtlases.back().addRect(devIBounds.width(), devIBounds.height(), &location)); } + devToAtlasOffset->set(location.x() - devIBounds.left(), location.y() - devIBounds.top()); return retiredAtlas; } diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.cpp index b2a2c07f833..36ba5f8383e 100644 --- a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.cpp +++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.cpp @@ -21,23 +21,19 @@ void GrCCClipPath::init( fAtlasLazyProxy = GrCCAtlas::MakeLazyAtlasProxy( [this](GrResourceProvider* resourceProvider, const GrCCAtlas::LazyAtlasDesc& desc) { SkASSERT(fHasAtlas); - SkASSERT(!fHasAtlasTransform); + SkASSERT(!fHasAtlasTranslate); GrTextureProxy* textureProxy = fAtlas ? fAtlas->textureProxy() : nullptr; if (!textureProxy || !textureProxy->instantiate(resourceProvider)) { - fAtlasScale = fAtlasTranslate = {0, 0}; - SkDEBUGCODE(fHasAtlasTransform = true); + SkDEBUGCODE(fHasAtlasTranslate = true); return GrSurfaceProxy::LazyCallbackResult(); } sk_sp<GrTexture> texture = sk_ref_sp(textureProxy->peekTexture()); SkASSERT(texture); - fAtlasScale = {1.f / texture->width(), 1.f / texture->height()}; - fAtlasTranslate.set(fDevToAtlasOffset.fX * fAtlasScale.x(), - fDevToAtlasOffset.fY * fAtlasScale.y()); - SkDEBUGCODE(fHasAtlasTransform = true); + SkDEBUGCODE(fHasAtlasTranslate = true); // We use LazyInstantiationKeyMode::kUnsynced here because CCPR clip masks are never // cached, and the clip FP proxies need to ignore any unique keys that atlas diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.h b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.h index 0f3fef20583..c0ec06c47b1 100644 --- a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.h +++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.h @@ -62,8 +62,10 @@ public: void accountForOwnPath(GrCCPerFlushResourceSpecs*) const; void renderPathInAtlas(GrCCPerFlushResources*, GrOnFlushResourceProvider*); - const SkVector& atlasScale() const { SkASSERT(fHasAtlasTransform); return fAtlasScale; } - const SkVector& atlasTranslate() const { SkASSERT(fHasAtlasTransform); return fAtlasTranslate; } + const SkIVector& atlasTranslate() const { + SkASSERT(fHasAtlasTranslate); + return fDevToAtlasOffset; + } private: sk_sp<GrTextureProxy> fAtlasLazyProxy; @@ -74,10 +76,7 @@ private: const GrCCAtlas* fAtlas = nullptr; SkIVector fDevToAtlasOffset; // Translation from device space to location in atlas. SkDEBUGCODE(bool fHasAtlas = false;) - - SkVector fAtlasScale; - SkVector fAtlasTranslate; - SkDEBUGCODE(bool fHasAtlasTransform = false;) + SkDEBUGCODE(bool fHasAtlasTranslate = false;) }; #endif diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.cpp index 9eed783219f..718985ac5fb 100644 --- a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.cpp +++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.cpp @@ -7,9 +7,8 @@ #include "src/gpu/ccpr/GrCCClipProcessor.h" -#include "src/gpu/GrTexture.h" -#include "src/gpu/GrTextureProxy.h" #include "src/gpu/ccpr/GrCCClipPath.h" +#include "src/gpu/effects/GrTextureEffect.h" #include "src/gpu/glsl/GrGLSLFragmentProcessor.h" #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" @@ -20,30 +19,34 @@ static GrSurfaceProxyView make_view(const GrCaps& caps, GrSurfaceProxy* proxy, return { sk_ref_sp(proxy), GrCCAtlas::kTextureOrigin, swizzle }; } -GrCCClipProcessor::GrCCClipProcessor(GrSurfaceProxyView view, const GrCCClipPath* clipPath, +GrCCClipProcessor::GrCCClipProcessor(std::unique_ptr<GrFragmentProcessor> inputFP, + const GrCaps& caps, + const GrCCClipPath* clipPath, IsCoverageCount isCoverageCount, MustCheckBounds mustCheckBounds) : INHERITED(kGrCCClipProcessor_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag) , fClipPath(clipPath) , fIsCoverageCount(IsCoverageCount::kYes == isCoverageCount) - , fMustCheckBounds(MustCheckBounds::kYes == mustCheckBounds) - , fAtlasAccess(std::move(view)) { - SkASSERT(fAtlasAccess.view()); - this->setTextureSamplerCnt(1); + , fMustCheckBounds(MustCheckBounds::kYes == mustCheckBounds) { + auto view = make_view(caps, clipPath->atlasLazyProxy(), fIsCoverageCount); + auto texEffect = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType); + this->registerExplicitlySampledChild(std::move(texEffect)); + + if (inputFP != nullptr) { + this->registerChild(std::move(inputFP)); + } } -GrCCClipProcessor::GrCCClipProcessor(const GrCaps& caps, const GrCCClipPath* clipPath, - IsCoverageCount isCoverageCount, - MustCheckBounds mustCheckBounds) - : GrCCClipProcessor(make_view(caps, clipPath->atlasLazyProxy(), - IsCoverageCount::kYes == isCoverageCount), - clipPath, isCoverageCount, mustCheckBounds) { +GrCCClipProcessor::GrCCClipProcessor(const GrCCClipProcessor& that) + : INHERITED(kGrCCClipProcessor_ClassID, that.optimizationFlags()) + , fClipPath(that.fClipPath) + , fIsCoverageCount(that.fIsCoverageCount) + , fMustCheckBounds(that.fMustCheckBounds) { + this->cloneAndRegisterAllChildProcessors(that); } std::unique_ptr<GrFragmentProcessor> GrCCClipProcessor::clone() const { - return std::make_unique<GrCCClipProcessor>( - fAtlasAccess.view(), fClipPath, IsCoverageCount(fIsCoverageCount), - MustCheckBounds(fMustCheckBounds)); + return std::unique_ptr<GrFragmentProcessor>(new GrCCClipProcessor(*this)); } void GrCCClipProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const { @@ -56,15 +59,19 @@ void GrCCClipProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKe bool GrCCClipProcessor::onIsEqual(const GrFragmentProcessor& fp) const { const GrCCClipProcessor& that = fp.cast<GrCCClipProcessor>(); - // Each ClipPath path has a unique atlas proxy, so hasSameSamplersAndAccesses should have - // already weeded out FPs with different ClipPaths. - SkASSERT(that.fClipPath->deviceSpacePath().getGenerationID() == - fClipPath->deviceSpacePath().getGenerationID()); - return that.fClipPath->deviceSpacePath().getFillType() == + return that.fClipPath->deviceSpacePath().getGenerationID() == + fClipPath->deviceSpacePath().getGenerationID() && + that.fClipPath->deviceSpacePath().getFillType() == fClipPath->deviceSpacePath().getFillType() && that.fIsCoverageCount == fIsCoverageCount && that.fMustCheckBounds == fMustCheckBounds; } +bool GrCCClipProcessor::hasInputFP() const { + // We always have a `texEffect`, and this accounts for one child. + // The second child will be the input FP, if we have one. + return this->numChildProcessors() > 1; +} + class GrCCClipProcessor::Impl : public GrGLSLFragmentProcessor { public: void emitCode(EmitArgs& args) override { @@ -72,7 +79,7 @@ public: GrGLSLUniformHandler* uniHandler = args.fUniformHandler; GrGLSLFPFragmentBuilder* f = args.fFragBuilder; - f->codeAppend ("half coverage;"); + f->codeAppend("half coverage;"); if (proc.fMustCheckBounds) { const char* pathIBounds; @@ -84,39 +91,43 @@ public: pathIBounds, pathIBounds); } - const char* atlasTransform; - fAtlasTransformUniform = uniHandler->addUniform(&proc, kFragment_GrShaderFlag, - kFloat4_GrSLType, "atlas_transform", - &atlasTransform); - f->codeAppendf("float2 texcoord = sk_FragCoord.xy * %s.xy + %s.zw;", - atlasTransform, atlasTransform); - - f->codeAppend ("coverage = "); - f->appendTextureLookup(args.fTexSamplers[0], "texcoord"); - f->codeAppend (".a;"); + const char* atlasTranslate; + fAtlasTranslateUniform = uniHandler->addUniform(&proc, kFragment_GrShaderFlag, + kFloat2_GrSLType, "atlas_translate", + &atlasTranslate); + SkString coord; + coord.printf("sk_FragCoord.xy + %s.xy", atlasTranslate); + constexpr int kTexEffectFPIndex = 0; + SkString sample = this->invokeChild(kTexEffectFPIndex, args, coord.c_str()); + f->codeAppendf("coverage = %s.a;", sample.c_str()); if (proc.fIsCoverageCount) { auto fillRule = GrFillRuleForSkPath(proc.fClipPath->deviceSpacePath()); if (GrFillRule::kEvenOdd == fillRule) { - f->codeAppend ("half t = mod(abs(coverage), 2);"); - f->codeAppend ("coverage = 1 - abs(t - 1);"); + f->codeAppend("half t = mod(abs(coverage), 2);"); + f->codeAppend("coverage = 1 - abs(t - 1);"); } else { SkASSERT(GrFillRule::kNonzero == fillRule); - f->codeAppend ("coverage = min(abs(coverage), 1);"); + f->codeAppend("coverage = min(abs(coverage), 1);"); } } if (proc.fMustCheckBounds) { - f->codeAppend ("} else {"); - f->codeAppend ( "coverage = 0;"); - f->codeAppend ("}"); + f->codeAppend("} else {"); + f->codeAppend( "coverage = 0;"); + f->codeAppend("}"); } if (proc.fClipPath->deviceSpacePath().isInverseFillType()) { - f->codeAppend ("coverage = 1 - coverage;"); + f->codeAppend("coverage = 1 - coverage;"); } - f->codeAppendf("%s = %s * coverage;", args.fOutputColor, args.fInputColor); + constexpr int kInputFPIndex = 1; + SkString inputColor = proc.hasInputFP() + ? this->invokeChild(kInputFPIndex, args.fInputColor, args) + : SkString(args.fInputColor); + + f->codeAppendf("%s = %s * coverage;", args.fOutputColor, inputColor.c_str()); } void onSetData(const GrGLSLProgramDataManager& pdman, @@ -127,14 +138,13 @@ public: pdman.set4f(fPathIBoundsUniform, pathIBounds.left(), pathIBounds.top(), pathIBounds.right(), pathIBounds.bottom()); } - const SkVector& scale = proc.fClipPath->atlasScale(); - const SkVector& trans = proc.fClipPath->atlasTranslate(); - pdman.set4f(fAtlasTransformUniform, scale.x(), scale.y(), trans.x(), trans.y()); + const SkIVector& trans = proc.fClipPath->atlasTranslate(); + pdman.set2f(fAtlasTranslateUniform, trans.x(), trans.y()); } private: UniformHandle fPathIBoundsUniform; - UniformHandle fAtlasTransformUniform; + UniformHandle fAtlasTranslateUniform; }; GrGLSLFragmentProcessor* GrCCClipProcessor::onCreateGLSLInstance() const { diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.h b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.h index d7eae5e5bc1..536bb8ed214 100644 --- a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.h +++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.h @@ -24,21 +24,22 @@ public: kYes = true }; - GrCCClipProcessor(GrSurfaceProxyView, const GrCCClipPath*, IsCoverageCount, MustCheckBounds); - GrCCClipProcessor(const GrCaps&, const GrCCClipPath*, IsCoverageCount, MustCheckBounds); + GrCCClipProcessor(std::unique_ptr<GrFragmentProcessor>, const GrCaps&, const GrCCClipPath*, + IsCoverageCount, MustCheckBounds); const char* name() const override { return "GrCCClipProcessor"; } std::unique_ptr<GrFragmentProcessor> clone() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; - const TextureSampler& onTextureSampler(int) const override { return fAtlasAccess; } + bool hasInputFP() const; private: + explicit GrCCClipProcessor(const GrCCClipProcessor&); + const GrCCClipPath* const fClipPath; const bool fIsCoverageCount; const bool fMustCheckBounds; - const TextureSampler fAtlasAccess; class Impl; diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCFiller.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCCFiller.cpp index ee9520f83be..9b30a708cd5 100644 --- a/chromium/third_party/skia/src/gpu/ccpr/GrCCFiller.cpp +++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCFiller.cpp @@ -433,7 +433,7 @@ bool GrCCFiller::prepareToDraw(GrOnFlushResourceProvider* onFlushRP) { SkASSERT(!currFan.empty()); currFan.pop_back(); } - // fallthru. + [[fallthrough]]; case Verb::kEndOpenContour: // endPt != startPt. SkASSERT(!currFanIsTessellated || currFan.empty()); if (!currFanIsTessellated && currFan.count() >= 3) { diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.cpp index d4c1d8be466..e5c99c01a78 100644 --- a/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.cpp +++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.cpp @@ -103,6 +103,10 @@ class GrCCPathProcessor::Impl : public GrGLSLGeometryProcessor { public: void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override; + static void GenKey(const GrCCPathProcessor& cc, GrProcessorKeyBuilder* b) { + b->add32(AddMatrixKeys((uint32_t) cc.fCoverageMode, SkMatrix::I(), cc.fLocalMatrix)); + } + private: void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc, const CoordTransformRange& transformRange) override { @@ -110,14 +114,21 @@ private: pdman.set2f(fAtlasAdjustUniform, 1.0f / proc.fAtlasDimensions.fWidth, 1.0f / proc.fAtlasDimensions.fHeight); - this->setTransformDataHelper(proc.fLocalMatrix, pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); + this->setTransform(pdman, fLocalMatrixUni, proc.fLocalMatrix, &fLocalMatrix); } GrGLSLUniformHandler::UniformHandle fAtlasAdjustUniform; + GrGLSLUniformHandler::UniformHandle fLocalMatrixUni; + SkMatrix fLocalMatrix = SkMatrix::InvalidMatrix(); typedef GrGLSLGeometryProcessor INHERITED; }; +void GrCCPathProcessor::getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const { + GrCCPathProcessor::Impl::GenKey(*this, b); +} + GrGLSLPrimitiveProcessor* GrCCPathProcessor::createGLSLInstance(const GrShaderCaps&) const { return new Impl(); } @@ -218,8 +229,8 @@ void GrCCPathProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { } gpArgs->fPositionVar.set(kFloat2_GrSLType, "octocoord"); - this->emitTransforms(v, varyingHandler, uniHandler, gpArgs->fPositionVar, proc.fLocalMatrix, - args.fFPCoordTransformHandler); + this->writeLocalCoord(v, args.fUniformHandler, gpArgs, gpArgs->fPositionVar, proc.fLocalMatrix, + &fLocalMatrixUni); // Fragment shader. GrGLSLFPFragmentBuilder* f = args.fFragBuilder; diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.h b/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.h index cb5f22770ef..789ac2e3ff6 100644 --- a/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.h +++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.h @@ -64,9 +64,8 @@ public: const SkMatrix& viewMatrixIfUsingLocalCoords = SkMatrix::I()); const char* name() const override { return "GrCCPathProcessor"; } - void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override { - b->add32((uint32_t)fCoverageMode); - } + void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override; + GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override; void drawPaths(GrOpFlushState*, const GrPipeline&, const GrSurfaceProxy& atlasProxy, diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCPerFlushResources.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCCPerFlushResources.cpp index 9101b1d84c4..d13a52a28f6 100644 --- a/chromium/third_party/skia/src/gpu/ccpr/GrCCPerFlushResources.cpp +++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCPerFlushResources.cpp @@ -8,7 +8,6 @@ #include "src/gpu/ccpr/GrCCPerFlushResources.h" #include "include/private/GrRecordingContext.h" -#include "src/gpu/GrClip.h" #include "src/gpu/GrMemoryPool.h" #include "src/gpu/GrOnFlushResourceProvider.h" #include "src/gpu/GrRecordingContextPriv.h" @@ -97,8 +96,10 @@ public: GrCCPathProcessor pathProc(coverageMode, fSrcProxy->peekTexture(), swizzle, GrCCAtlas::kTextureOrigin); - GrPipeline pipeline(GrScissorTest::kDisabled, SkBlendMode::kSrc, - flushState->drawOpArgs().writeSwizzle()); + bool hasScissor = flushState->appliedClip() && + flushState->appliedClip()->scissorState().enabled(); + GrPipeline pipeline(hasScissor ? GrScissorTest::kEnabled : GrScissorTest::kDisabled, + SkBlendMode::kSrc, flushState->drawOpArgs().writeSwizzle()); pathProc.drawPaths(flushState, pipeline, *fSrcProxy, *fResources, fBaseInstance, fEndInstance, this->bounds()); @@ -541,7 +542,7 @@ bool GrCCPerFlushResources::finalize(GrOnFlushResourceProvider* onFlushRP) { auto op = CopyAtlasOp::Make( rtc->surfPriv().getContext(), sk_ref_sp(this), copyRange.fSrcProxy, baseCopyInstance, endCopyInstance, atlas.drawBounds()); - rtc->addDrawOp(GrNoClip(), std::move(op)); + rtc->addDrawOp(nullptr, std::move(op)); } baseCopyInstance = endCopyInstance; } @@ -580,7 +581,7 @@ bool GrCCPerFlushResources::finalize(GrOnFlushResourceProvider* onFlushRP) { rtc->surfPriv().getContext(), sk_ref_sp(this), atlas.getFillBatchID(), atlas.getStrokeBatchID(), atlas.drawBounds()); } - rtc->addDrawOp(GrNoClip(), std::move(op)); + rtc->addDrawOp(nullptr, std::move(op)); if (rtc->asSurfaceProxy()->requiresManualMSAAResolve()) { onFlushRP->addTextureResolveTask(sk_ref_sp(rtc->asTextureProxy()), GrSurfaceProxy::ResolveFlags::kMSAA); diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCStroker.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCCStroker.cpp index 44f3db3362f..bb09fe4c612 100644 --- a/chromium/third_party/skia/src/gpu/ccpr/GrCCStroker.cpp +++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCStroker.cpp @@ -103,7 +103,6 @@ private: void LinearStrokeProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; - GrGLSLUniformHandler* uniHandler = args.fUniformHandler; varyingHandler->emitAttributes(args.fGP.cast<LinearStrokeProcessor>()); @@ -137,8 +136,7 @@ void LinearStrokeProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { edgeDistances.vsOut(), edgeDistances.vsOut(), edgeDistances.vsOut()); gpArgs->fPositionVar.set(kFloat2_GrSLType, "position"); - this->emitTransforms(v, varyingHandler, uniHandler, GrShaderVar("position", kFloat2_GrSLType), - SkMatrix::I(), args.fFPCoordTransformHandler); + // Leave fLocalCoordVar uninitialized; this GP is not combined with frag processors // Use the 4 edge distances to calculate coverage in the fragment shader. GrGLSLFPFragmentBuilder* f = args.fFragBuilder; @@ -194,7 +192,6 @@ private: void CubicStrokeProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; - GrGLSLUniformHandler* uniHandler = args.fUniformHandler; varyingHandler->emitAttributes(args.fGP.cast<CubicStrokeProcessor>()); @@ -259,8 +256,7 @@ void CubicStrokeProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { coverages.vsOut()); gpArgs->fPositionVar.set(kFloat2_GrSLType, "position"); - this->emitTransforms(v, varyingHandler, uniHandler, GrShaderVar("position", kFloat2_GrSLType), - SkMatrix::I(), args.fFPCoordTransformHandler); + // Leave fLocalCoordVar uninitialized; this GP is not combined with frag processors // Use the 2 edge distances and interpolated butt cap AA to calculate fragment coverage. GrGLSLFPFragmentBuilder* f = args.fFragBuilder; @@ -649,10 +645,10 @@ bool GrCCStroker::prepareToDraw(GrOnFlushResourceProvider* onFlushRP) { case Verb::kRoundJoin: case Verb::kInternalRoundJoin: conicWeight = params[paramsIdx++].fConicWeight; - // fallthru + [[fallthrough]]; case Verb::kMiterJoin: miterCapHeightOverWidth = params[paramsIdx++].fMiterCapHeightOverWidth; - // fallthru + [[fallthrough]]; case Verb::kBevelJoin: case Verb::kInternalBevelJoin: builder.appendJoin(verb, pts[ptsIdx], normals[normalsIdx], normals[normalsIdx + 1], diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp index bc56c5de6e4..5f66c6e442e 100644 --- a/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp +++ b/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp @@ -9,8 +9,8 @@ #include "include/pathops/SkPathOps.h" #include "src/gpu/GrCaps.h" -#include "src/gpu/GrClip.h" #include "src/gpu/GrProxyProvider.h" +#include "src/gpu/GrRenderTargetContext.h" #include "src/gpu/ccpr/GrCCClipProcessor.h" #include "src/gpu/ccpr/GrCCDrawPathsOp.h" #include "src/gpu/ccpr/GrCCPathCache.h" @@ -136,7 +136,7 @@ GrPathRenderer::CanDrawPath GrCoverageCountingPathRenderer::onCanDrawPath( // defined relative to device space. return CanDrawPath::kNo; } - // fallthru + [[fallthrough]]; case SkStrokeRec::kHairline_Style: { if (CoverageType::kFP16_CoverageCount != fCoverageType) { // Stroking is not yet supported in MSAA atlas mode. @@ -167,11 +167,8 @@ GrPathRenderer::CanDrawPath GrCoverageCountingPathRenderer::onCanDrawPath( bool GrCoverageCountingPathRenderer::onDrawPath(const DrawPathArgs& args) { SkASSERT(!fFlushing); - GrRenderTargetContext* rtc = args.fRenderTargetContext; - SkIRect clipIBounds = args.fClip->getConservativeBounds(rtc->width(), rtc->height()); - - auto op = GrCCDrawPathsOp::Make(args.fContext, clipIBounds, *args.fViewMatrix, *args.fShape, - std::move(args.fPaint)); + auto op = GrCCDrawPathsOp::Make(args.fContext, *args.fClipConservativeBounds, *args.fViewMatrix, + *args.fShape, std::move(args.fPaint)); this->recordOp(std::move(op), args); return true; } @@ -183,14 +180,14 @@ void GrCoverageCountingPathRenderer::recordOp(std::unique_ptr<GrCCDrawPathsOp> o op->cast<GrCCDrawPathsOp>()->addToOwningPerOpsTaskPaths( sk_ref_sp(this->lookupPendingPaths(opsTaskID))); }; - args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op), + args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op), addToOwningPerOpsTaskPaths); } } std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor( - uint32_t opsTaskID, const SkPath& deviceSpacePath, const SkIRect& accessRect, - const GrCaps& caps) { + std::unique_ptr<GrFragmentProcessor> inputFP, uint32_t opsTaskID, + const SkPath& deviceSpacePath, const SkIRect& accessRect, const GrCaps& caps) { SkASSERT(!fFlushing); uint32_t key = deviceSpacePath.getGenerationID(); @@ -221,7 +218,8 @@ std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipPro CoverageType::kFP16_CoverageCount == fCoverageType); auto mustCheckBounds = GrCCClipProcessor::MustCheckBounds( !clipPath.pathDevIBounds().contains(accessRect)); - return std::make_unique<GrCCClipProcessor>(caps, &clipPath, isCoverageCount, mustCheckBounds); + return std::make_unique<GrCCClipProcessor>( + std::move(inputFP), caps, &clipPath, isCoverageCount, mustCheckBounds); } void GrCoverageCountingPathRenderer::preFlush( diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.h b/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.h index a3107057b44..e5e09472f00 100644 --- a/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.h +++ b/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.h @@ -63,8 +63,8 @@ public: } std::unique_ptr<GrFragmentProcessor> makeClipProcessor( - uint32_t oplistID, const SkPath& deviceSpacePath, const SkIRect& accessRect, - const GrCaps&); + std::unique_ptr<GrFragmentProcessor> inputFP, uint32_t opsTaskID, + const SkPath& deviceSpacePath, const SkIRect& accessRect, const GrCaps& caps); // GrOnFlushCallbackObject overrides. void preFlush(GrOnFlushResourceProvider*, const uint32_t* opsTaskIDs, diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer_none.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer_none.cpp index 1b2a55e0e70..72d443c6949 100644 --- a/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer_none.cpp +++ b/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer_none.cpp @@ -17,7 +17,7 @@ sk_sp<GrCoverageCountingPathRenderer> GrCoverageCountingPathRenderer::CreateIfSu } std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor( - uint32_t opsTaskID, const SkPath& deviceSpacePath, const SkIRect& accessRect, - const GrCaps& caps) { + std::unique_ptr<GrFragmentProcessor> inputFP, uint32_t opsTaskID, + const SkPath& deviceSpacePath, const SkIRect& accessRect, const GrCaps& caps) { return nullptr; } diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrGSCoverageProcessor.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrGSCoverageProcessor.cpp index feaac1a1439..44e2def7264 100644 --- a/chromium/third_party/skia/src/gpu/ccpr/GrGSCoverageProcessor.cpp +++ b/chromium/third_party/skia/src/gpu/ccpr/GrGSCoverageProcessor.cpp @@ -25,7 +25,7 @@ protected: void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&, const CoordTransformRange& transformRange) final { - this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); } void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final { diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrVSCoverageProcessor.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrVSCoverageProcessor.cpp index ee3ce647edb..0270cbf89af 100644 --- a/chromium/third_party/skia/src/gpu/ccpr/GrVSCoverageProcessor.cpp +++ b/chromium/third_party/skia/src/gpu/ccpr/GrVSCoverageProcessor.cpp @@ -20,7 +20,7 @@ public: private: void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&, const CoordTransformRange& transformRange) final { - this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); } void onEmitCode(EmitArgs&, GrGPArgs*) override; diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DAttachmentViewManager.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DAttachmentViewManager.cpp deleted file mode 100644 index 7536f590918..00000000000 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DAttachmentViewManager.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "src/gpu/d3d/GrD3DAttachmentViewManager.h" - -#include "src/gpu/d3d/GrD3DGpu.h" - -GrD3DAttachmentViewManager::GrD3DAttachmentViewManager(GrD3DGpu* gpu) - : fRTVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_RTV) - , fDSVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_DSV) {} - -D3D12_CPU_DESCRIPTOR_HANDLE GrD3DAttachmentViewManager::createRenderTargetView( - GrD3DGpu* gpu, ID3D12Resource* textureResource) { - D3D12_CPU_DESCRIPTOR_HANDLE descriptor = fRTVDescriptorPool.allocateHandle(gpu); - gpu->device()->CreateRenderTargetView(textureResource, nullptr, descriptor); - return descriptor; -} - -void GrD3DAttachmentViewManager::recycleRenderTargetView( - D3D12_CPU_DESCRIPTOR_HANDLE* rtvDescriptor) { - fRTVDescriptorPool.releaseHandle(rtvDescriptor); -} - -D3D12_CPU_DESCRIPTOR_HANDLE GrD3DAttachmentViewManager::createDepthStencilView( - GrD3DGpu* gpu, ID3D12Resource* textureResource) { - D3D12_CPU_DESCRIPTOR_HANDLE descriptor = fDSVDescriptorPool.allocateHandle(gpu); - gpu->device()->CreateDepthStencilView(textureResource, nullptr, descriptor); - return descriptor; -} - -void GrD3DAttachmentViewManager::recycleDepthStencilView( - D3D12_CPU_DESCRIPTOR_HANDLE* dsvDescriptor) { - fDSVDescriptorPool.releaseHandle(dsvDescriptor); -} - -//////////////////////////////////////////////////////////////////////////////////////////////// - -std::unique_ptr<GrD3DAttachmentViewManager::Heap> GrD3DAttachmentViewManager::Heap::Make( - GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, unsigned int numDescriptors) { - std::unique_ptr<GrD3DDescriptorHeap> heap = - GrD3DDescriptorHeap::Make(gpu, type, numDescriptors, D3D12_DESCRIPTOR_HEAP_FLAG_NONE); - if (!heap) { - return nullptr; - } - - return std::unique_ptr<Heap>(new Heap(heap, numDescriptors)); - -} - -D3D12_CPU_DESCRIPTOR_HANDLE GrD3DAttachmentViewManager::Heap::allocateCPUHandle() { - SkBitSet::OptionalIndex freeBlock = fFreeBlocks.findFirst(); - SkASSERT(freeBlock); - fFreeBlocks.reset(*freeBlock); - --fFreeCount; - return fHeap->getCPUHandle(*freeBlock); -} - -bool GrD3DAttachmentViewManager::Heap::freeCPUHandle(D3D12_CPU_DESCRIPTOR_HANDLE* handle) { - size_t index; - if (!fHeap->getIndex(*handle, &index)) { - return false; - } - fFreeBlocks.set(index); - ++fFreeCount; - handle->ptr = 0; - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////// - -GrD3DAttachmentViewManager::HeapPool::HeapPool(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE heapType) - : fMaxAvailableDescriptors(32) - , fHeapType(heapType) { - std::unique_ptr<GrD3DAttachmentViewManager::Heap> heap = - GrD3DAttachmentViewManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors); - fDescriptorHeaps.push_back(std::move(heap)); -} - -D3D12_CPU_DESCRIPTOR_HANDLE GrD3DAttachmentViewManager::HeapPool::allocateHandle(GrD3DGpu* gpu) { - for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) { - if (fDescriptorHeaps[i]->canAllocate()) { - D3D12_CPU_DESCRIPTOR_HANDLE handle = fDescriptorHeaps[i]->allocateCPUHandle(); - return handle; - } - } - - // need to allocate more space - std::unique_ptr<GrD3DAttachmentViewManager::Heap> heap = - GrD3DAttachmentViewManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors); - - fDescriptorHeaps.push_back(std::move(heap)); - fMaxAvailableDescriptors *= 2; - D3D12_CPU_DESCRIPTOR_HANDLE handle = - fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateCPUHandle(); - return handle; -} - -void GrD3DAttachmentViewManager::HeapPool::releaseHandle( - D3D12_CPU_DESCRIPTOR_HANDLE* dsvDescriptor) { - for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) { - if (fDescriptorHeaps[i]->freeCPUHandle(dsvDescriptor)) { - return; - } - } - SkASSERT(false); -} diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DAttachmentViewManager.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DAttachmentViewManager.h deleted file mode 100644 index 3424ba39f94..00000000000 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DAttachmentViewManager.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrD3DAttachmentViewManager_DEFINED -#define GrD3DAttachmentViewManager_DEFINED - -#include "src/gpu/d3d/GrD3DDescriptorHeap.h" - -class GrD3DGpu; - -class GrD3DAttachmentViewManager { -public: - GrD3DAttachmentViewManager(GrD3DGpu*); - - D3D12_CPU_DESCRIPTOR_HANDLE createRenderTargetView(GrD3DGpu*, ID3D12Resource* textureResource); - void recycleRenderTargetView(D3D12_CPU_DESCRIPTOR_HANDLE*); - - D3D12_CPU_DESCRIPTOR_HANDLE createDepthStencilView(GrD3DGpu*, ID3D12Resource* textureResource); - void recycleDepthStencilView(D3D12_CPU_DESCRIPTOR_HANDLE*); - -private: - class Heap { - public: - static std::unique_ptr<Heap> Make(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, - unsigned int numDescriptors); - - D3D12_CPU_DESCRIPTOR_HANDLE allocateCPUHandle(); - bool freeCPUHandle(D3D12_CPU_DESCRIPTOR_HANDLE*); - - bool canAllocate() { return fFreeCount > 0; } - - private: - Heap(std::unique_ptr<GrD3DDescriptorHeap>& heap, unsigned int numDescriptors) - : fHeap(std::move(heap)) - , fFreeBlocks(numDescriptors) - , fFreeCount(numDescriptors) { - for (unsigned int i = 0; i < numDescriptors; ++i) { - fFreeBlocks.set(i); - } - } - - std::unique_ptr<GrD3DDescriptorHeap> fHeap; - SkBitSet fFreeBlocks; - unsigned int fFreeCount; - }; - - class HeapPool { - public: - HeapPool(GrD3DGpu*, D3D12_DESCRIPTOR_HEAP_TYPE); - - D3D12_CPU_DESCRIPTOR_HANDLE allocateHandle(GrD3DGpu*); - void releaseHandle(D3D12_CPU_DESCRIPTOR_HANDLE*); - - private: - std::vector<std::unique_ptr<Heap>> fDescriptorHeaps; - int fMaxAvailableDescriptors; - D3D12_DESCRIPTOR_HEAP_TYPE fHeapType; - }; - - HeapPool fRTVDescriptorPool; - HeapPool fDSVDescriptorPool; -}; - -#endif diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.cpp index 7462feb392d..108e9d11571 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.cpp @@ -24,8 +24,8 @@ sk_sp<GrD3DBuffer::Resource> GrD3DBuffer::Resource::Make(GrD3DGpu* gpu, size_t s SkASSERT(intendedType != GrGpuBufferType::kXferCpuToGpu && intendedType != GrGpuBufferType::kXferGpuToCpu); heapType = D3D12_HEAP_TYPE_DEFAULT; - // Can be transitioned to different states - *resourceState = D3D12_RESOURCE_STATE_COMMON; + // Needs to be transitioned to appropriate state to be read in shader + *resourceState = D3D12_RESOURCE_STATE_COPY_DEST; } else { if (intendedType == GrGpuBufferType::kXferGpuToCpu) { heapType = D3D12_HEAP_TYPE_READBACK; @@ -101,6 +101,26 @@ GrD3DBuffer::GrD3DBuffer(GrD3DGpu* gpu, size_t size, GrGpuBufferType intendedTyp VALIDATE(); } +void GrD3DBuffer::setResourceState(const GrD3DGpu* gpu, + D3D12_RESOURCE_STATES newResourceState) { + if (newResourceState == fResourceState || + // GENERIC_READ encapsulates a lot of different read states + (fResourceState == D3D12_RESOURCE_STATE_GENERIC_READ && + SkToBool(newResourceState | fResourceState))) { + return; + } + + D3D12_RESOURCE_TRANSITION_BARRIER barrier = {}; + barrier.pResource = this->d3dResource(); + barrier.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier.StateBefore = fResourceState; + barrier.StateAfter = newResourceState; + + gpu->addResourceBarriers(this->resource(), 1, &barrier); + + fResourceState = newResourceState; +} + void GrD3DBuffer::onRelease() { if (!this->wasDestroyed()) { VALIDATE(); @@ -169,10 +189,6 @@ void GrD3DBuffer::internalMap(size_t size) { VALIDATE(); if (this->accessPattern() == kStatic_GrAccessPattern) { -#ifdef SK_BUILD_FOR_MAC - // Mac requires 4-byte alignment for copies so we pad this out - sizeInBytes = SkAlign4(sizeInBytes); -#endif // TODO: should use a slice of a previously allocated UPLOAD buffer D3D12_RESOURCE_STATES resourceState; // not used, just to pass to make fMappedResource = Resource::Make(this->getD3DGpu(), size, GrGpuBufferType::kXferCpuToGpu, @@ -215,15 +231,10 @@ void GrD3DBuffer::internalUnmap(size_t size) { range.Begin = 0; range.End = size; fMappedResource->fD3DResource->Unmap(0, &range); - // TODO - // let the D3DGpu make this decision? - //if (size == this->size()) { - // this->getD3DGpu()->copyResource(this->d3dResource(), fMappedResource->fD3DResource); - - //} else { - // this->getD3DGpu()->copyBufferRegion(this->d3dResource(), 0, - // fMappedResource->fD3DResource, 0, size); - //} + this->setResourceState(this->getD3DGpu(), D3D12_RESOURCE_STATE_COPY_DEST); + this->getD3DGpu()->currentCommandList()->copyBufferToBuffer( + fResource, fResource->fD3DResource.get(), 0, + fMappedResource, fMappedResource->fD3DResource.get(), 0, size); } else { D3D12_RANGE range; range.Begin = 0; diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.h index e2d1efc55de..00611728fc6 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.h @@ -37,6 +37,8 @@ public: return fResource; } + void setResourceState(const GrD3DGpu* gpu, D3D12_RESOURCE_STATES newResourceState); + protected: GrD3DBuffer(GrD3DGpu*, size_t size, GrGpuBufferType, GrAccessPattern, const sk_sp<Resource>&, D3D12_RESOURCE_STATES); diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.cpp index df17463d607..e6b00dc73b5 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.cpp @@ -10,6 +10,7 @@ #include "include/gpu/d3d/GrD3DTypes.h" #include "src/core/SkCompressedDataUtils.h" +#include "src/gpu/GrBackendUtils.h" #include "src/gpu/GrProgramDesc.h" #include "src/gpu/GrProgramInfo.h" #include "src/gpu/GrShaderCaps.h" @@ -773,20 +774,6 @@ bool GrD3DCaps::isFormatSRGB(const GrBackendFormat& format) const { } } -SkImage::CompressionType GrD3DCaps::compressionType(const GrBackendFormat& format) const { - DXGI_FORMAT dxgiFormat; - if (!format.asDxgiFormat(&dxgiFormat)) { - return SkImage::CompressionType::kNone; - } - - switch (dxgiFormat) { - case DXGI_FORMAT_BC1_UNORM: return SkImage::CompressionType::kBC1_RGBA8_UNORM; - default: return SkImage::CompressionType::kNone; - } - - SkUNREACHABLE; -} - bool GrD3DCaps::isFormatTexturable(const GrBackendFormat& format) const { DXGI_FORMAT dxgiFormat; if (!format.asDxgiFormat(&dxgiFormat)) { @@ -944,12 +931,6 @@ bool GrD3DCaps::onAreColorTypeAndFormatCompatible(GrColorType ct, return false; } - SkImage::CompressionType compression = GrDxgiFormatToCompressionType(dxgiFormat); - if (compression != SkImage::CompressionType::kNone) { - return ct == (SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x - : GrColorType::kRGBA_8888); - } - const auto& info = this->getFormatInfo(dxgiFormat); for (int i = 0; i < info.fColorTypeInfoCount; ++i) { if (info.fColorTypeInfos[i].fColorType == ct) { @@ -982,7 +963,7 @@ GrBackendFormat GrD3DCaps::getBackendFormatFromCompressionType( SkUNREACHABLE; } -GrSwizzle GrD3DCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const { +GrSwizzle GrD3DCaps::onGetReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const { DXGI_FORMAT dxgiFormat; SkAssertResult(format.asDxgiFormat(&dxgiFormat)); const auto& info = this->getFormatInfo(dxgiFormat); @@ -1025,7 +1006,7 @@ GrCaps::SupportedRead GrD3DCaps::onSupportedReadPixelsColorType( return { GrColorType::kUnknown, 0 }; } - SkImage::CompressionType compression = GrDxgiFormatToCompressionType(dxgiFormat); + SkImage::CompressionType compression = GrBackendFormatToCompressionType(srcBackendFormat); if (compression != SkImage::CompressionType::kNone) { return { SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x : GrColorType::kRGBA_8888, 0 }; diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.h index 1c4fefb52db..2e05f117b52 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.h @@ -29,7 +29,6 @@ public: GrD3DCaps(const GrContextOptions& contextOptions, IDXGIAdapter1*, ID3D12Device*); bool isFormatSRGB(const GrBackendFormat&) const override; - SkImage::CompressionType compressionType(const GrBackendFormat&) const override; bool isFormatTexturable(const GrBackendFormat&) const override; bool isFormatTexturable(DXGI_FORMAT) const; @@ -93,7 +92,6 @@ public: return fColorTypeToFormatTable[idx]; } - GrSwizzle getReadSwizzle(const GrBackendFormat&, GrColorType) const override; GrSwizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override; uint64_t computeFormatKey(const GrBackendFormat&) const override; @@ -139,6 +137,8 @@ private: SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&, GrColorType) const override; + GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override; + // ColorTypeInfo for a specific format struct ColorTypeInfo { GrColorType fColorType = GrColorType::kUnknown; diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.cpp index 1216b93f17b..a422622116d 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.cpp @@ -7,10 +7,13 @@ #include "src/gpu/d3d/GrD3DCommandList.h" +#include "src/gpu/GrScissorState.h" #include "src/gpu/d3d/GrD3DBuffer.h" #include "src/gpu/d3d/GrD3DGpu.h" #include "src/gpu/d3d/GrD3DPipelineState.h" #include "src/gpu/d3d/GrD3DRenderTarget.h" +#include "src/gpu/d3d/GrD3DStencilAttachment.h" +#include "src/gpu/d3d/GrD3DTexture.h" #include "src/gpu/d3d/GrD3DTextureResource.h" GrD3DCommandList::GrD3DCommandList(gr_cp<ID3D12CommandAllocator> allocator, @@ -30,6 +33,7 @@ bool GrD3DCommandList::close() { GrD3DCommandList::SubmitResult GrD3DCommandList::submit(ID3D12CommandQueue* queue) { SkASSERT(fIsActive); if (!this->hasWork()) { + this->callFinishedCallbacks(); return SubmitResult::kNoWork; } @@ -49,6 +53,7 @@ void GrD3DCommandList::reset() { SkASSERT(SUCCEEDED(hr)); SkDEBUGCODE(hr = ) fCommandList->Reset(fAllocator.get(), nullptr); SkASSERT(SUCCEEDED(hr)); + this->onReset(); this->releaseResources(); @@ -73,6 +78,12 @@ void GrD3DCommandList::releaseResources() { fTrackedResources.reset(); fTrackedRecycledResources.reset(); + + this->callFinishedCallbacks(); +} + +void GrD3DCommandList::addFinishedCallback(sk_sp<GrRefCntedCallback> callback) { + fFinishedCallbacks.push_back(std::move(callback)); } //////////////////////////////////////////////////////////////////////////////// @@ -81,7 +92,7 @@ void GrD3DCommandList::releaseResources() { void GrD3DCommandList::resourceBarrier(sk_sp<GrManagedResource> resource, int numBarriers, - D3D12_RESOURCE_TRANSITION_BARRIER* barriers) { + const D3D12_RESOURCE_TRANSITION_BARRIER* barriers) { SkASSERT(fIsActive); SkASSERT(barriers); for (int i = 0; i < numBarriers; ++i) { @@ -108,8 +119,8 @@ void GrD3DCommandList::submitResourceBarriers() { SkASSERT(!fResourceBarriers.count()); } -void GrD3DCommandList::copyBufferToTexture(GrD3DBuffer* srcBuffer, - GrD3DTextureResource* dstTexture, +void GrD3DCommandList::copyBufferToTexture(const GrD3DBuffer* srcBuffer, + const GrD3DTextureResource* dstTexture, uint32_t subresourceCount, D3D12_PLACED_SUBRESOURCE_FOOTPRINT* bufferFootprints, int left, int top) { @@ -148,14 +159,23 @@ void GrD3DCommandList::copyTextureRegion(sk_sp<GrManagedResource> dst, fCommandList->CopyTextureRegion(dstLocation, dstX, dstY, 0, srcLocation, srcBox); } -void GrD3DCommandList::clearRenderTargetView(GrD3DRenderTarget* renderTarget, - const SkPMColor4f& color, - const GrFixedClip& clip) { +void GrD3DCommandList::copyBufferToBuffer(sk_sp<GrManagedResource> dst, + ID3D12Resource* dstBuffer, uint64_t dstOffset, + sk_sp<GrManagedResource> src, + ID3D12Resource* srcBuffer, uint64_t srcOffset, + uint64_t numBytes) { + SkASSERT(fIsActive); + this->addingWork(); - this->addResource(renderTarget->resource()); - fCommandList->ClearRenderTargetView(renderTarget->colorRenderTargetView(), - color.vec(), - 0, NULL); // no cliprects for now + this->addResource(dst); + this->addResource(src); + uint64_t dstSize = dstBuffer->GetDesc().Width; + uint64_t srcSize = srcBuffer->GetDesc().Width; + if (dstSize == srcSize && srcSize == numBytes) { + fCommandList->CopyResource(dstBuffer, srcBuffer); + } else { + fCommandList->CopyBufferRegion(dstBuffer, dstOffset, srcBuffer, srcOffset, numBytes); + } } void GrD3DCommandList::addingWork() { @@ -183,7 +203,31 @@ std::unique_ptr<GrD3DDirectCommandList> GrD3DDirectCommandList::Make(ID3D12Devic GrD3DDirectCommandList::GrD3DDirectCommandList(gr_cp<ID3D12CommandAllocator> allocator, gr_cp<ID3D12GraphicsCommandList> commandList) - : GrD3DCommandList(std::move(allocator), std::move(commandList)) { + : GrD3DCommandList(std::move(allocator), std::move(commandList)) + , fCurrentRootSignature(nullptr) + , fCurrentVertexBuffer(nullptr) + , fCurrentVertexStride(0) + , fCurrentInstanceBuffer(nullptr) + , fCurrentInstanceStride(0) + , fCurrentIndexBuffer(nullptr) + , fCurrentConstantRingBuffer(nullptr) + , fCurrentSRVCRVDescriptorHeap(nullptr) + , fCurrentSamplerDescriptorHeap(nullptr) { +} + +void GrD3DDirectCommandList::onReset() { + fCurrentRootSignature = nullptr; + fCurrentVertexBuffer = nullptr; + fCurrentVertexStride = 0; + fCurrentInstanceBuffer = nullptr; + fCurrentInstanceStride = 0; + fCurrentIndexBuffer = nullptr; + if (fCurrentConstantRingBuffer) { + fCurrentConstantRingBuffer->finishSubmit(fConstantRingBufferSubmitData); + fCurrentConstantRingBuffer = nullptr; + } + fCurrentSRVCRVDescriptorHeap = nullptr; + fCurrentSamplerDescriptorHeap = nullptr; } void GrD3DDirectCommandList::setPipelineState(sk_sp<GrD3DPipelineState> pipelineState) { @@ -192,6 +236,16 @@ void GrD3DDirectCommandList::setPipelineState(sk_sp<GrD3DPipelineState> pipeline this->addResource(std::move(pipelineState)); } +void GrD3DDirectCommandList::setCurrentConstantBuffer( + const sk_sp<GrD3DConstantRingBuffer>& constantBuffer) { + fCurrentConstantRingBuffer = constantBuffer.get(); + if (fCurrentConstantRingBuffer) { + fConstantRingBufferSubmitData = constantBuffer->startSubmit(); + this->addResource( + static_cast<GrD3DBuffer*>(fConstantRingBufferSubmitData.buffer())->resource()); + } +} + void GrD3DDirectCommandList::setStencilRef(unsigned int stencilRef) { SkASSERT(fIsActive); fCommandList->OMSetStencilRef(stencilRef); @@ -218,6 +272,150 @@ void GrD3DDirectCommandList::setViewports(unsigned int numViewports, fCommandList->RSSetViewports(numViewports, viewports); } +void GrD3DDirectCommandList::setGraphicsRootSignature(const sk_sp<GrD3DRootSignature>& rootSig) { + SkASSERT(fIsActive); + if (fCurrentRootSignature != rootSig.get()) { + fCommandList->SetGraphicsRootSignature(rootSig->rootSignature()); + this->addResource(rootSig); + fCurrentRootSignature = rootSig.get(); + } +} + +void GrD3DDirectCommandList::setVertexBuffers(unsigned int startSlot, + const GrD3DBuffer* vertexBuffer, + size_t vertexStride, + const GrD3DBuffer* instanceBuffer, + size_t instanceStride) { + if (fCurrentVertexBuffer != vertexBuffer || fCurrentVertexStride != vertexStride || + fCurrentInstanceBuffer != instanceBuffer || fCurrentInstanceStride != instanceStride) { + this->addResource(vertexBuffer->resource()); + + D3D12_VERTEX_BUFFER_VIEW views[2]; + int numViews = 0; + views[numViews].BufferLocation = vertexBuffer->d3dResource()->GetGPUVirtualAddress(); + views[numViews].SizeInBytes = vertexBuffer->size(); + views[numViews++].StrideInBytes = vertexStride; + if (instanceBuffer) { + this->addResource(instanceBuffer->resource()); + views[numViews].BufferLocation = instanceBuffer->d3dResource()->GetGPUVirtualAddress(); + views[numViews].SizeInBytes = instanceBuffer->size(); + views[numViews++].StrideInBytes = instanceStride; + } + fCommandList->IASetVertexBuffers(startSlot, numViews, views); + + fCurrentVertexBuffer = vertexBuffer; + fCurrentVertexStride = vertexStride; + fCurrentInstanceBuffer = instanceBuffer; + fCurrentInstanceStride = instanceStride; + } +} + +void GrD3DDirectCommandList::setIndexBuffer(const GrD3DBuffer* indexBuffer) { + if (fCurrentIndexBuffer != indexBuffer) { + this->addResource(indexBuffer->resource()); + + D3D12_INDEX_BUFFER_VIEW view = {}; + view.BufferLocation = indexBuffer->d3dResource()->GetGPUVirtualAddress(); + view.SizeInBytes = indexBuffer->size(); + view.Format = DXGI_FORMAT_R16_UINT; + fCommandList->IASetIndexBuffer(&view); + } +} + +void GrD3DDirectCommandList::drawInstanced(unsigned int vertexCount, unsigned int instanceCount, + unsigned int startVertex, unsigned int startInstance) { + SkASSERT(fIsActive); + this->addingWork(); + fCommandList->DrawInstanced(vertexCount, instanceCount, startVertex, startInstance); +} + +void GrD3DDirectCommandList::drawIndexedInstanced(unsigned int indexCount, + unsigned int instanceCount, + unsigned int startIndex, + unsigned int baseVertex, + unsigned int startInstance) { + SkASSERT(fIsActive); + this->addingWork(); + fCommandList->DrawIndexedInstanced(indexCount, instanceCount, startIndex, baseVertex, + startInstance); +} + +void GrD3DDirectCommandList::clearRenderTargetView(const GrD3DRenderTarget* renderTarget, + const SkPMColor4f& color, + const D3D12_RECT* rect) { + this->addingWork(); + this->addResource(renderTarget->resource()); + if (renderTarget->numSamples() > 1) { + this->addResource(renderTarget->msaaTextureResource()->resource()); + } + unsigned int numRects = rect ? 1 : 0; + fCommandList->ClearRenderTargetView(renderTarget->colorRenderTargetView(), + color.vec(), numRects, rect); +} + +void GrD3DDirectCommandList::clearDepthStencilView(const GrD3DStencilAttachment* stencil, + uint8_t stencilClearValue, + const D3D12_RECT* rect) { + this->addingWork(); + this->addResource(stencil->resource()); + unsigned int numRects = rect ? 1 : 0; + fCommandList->ClearDepthStencilView(stencil->view(), D3D12_CLEAR_FLAG_STENCIL, 0, + stencilClearValue, numRects, rect); +} + +void GrD3DDirectCommandList::setRenderTarget(const GrD3DRenderTarget* renderTarget) { + this->addingWork(); + this->addResource(renderTarget->resource()); + if (renderTarget->numSamples() > 1) { + this->addResource(renderTarget->msaaTextureResource()->resource()); + } + D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = renderTarget->colorRenderTargetView(); + + D3D12_CPU_DESCRIPTOR_HANDLE dsDescriptor; + D3D12_CPU_DESCRIPTOR_HANDLE* dsDescriptorPtr = nullptr; + if (auto stencil = renderTarget->renderTargetPriv().getStencilAttachment()) { + GrD3DStencilAttachment* d3dStencil = static_cast<GrD3DStencilAttachment*>(stencil); + this->addResource(d3dStencil->resource()); + dsDescriptor = d3dStencil->view(); + dsDescriptorPtr = &dsDescriptor; + } + + fCommandList->OMSetRenderTargets(1, &rtvDescriptor, false, dsDescriptorPtr); +} + +void GrD3DDirectCommandList::setGraphicsRootConstantBufferView( + unsigned int rootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS bufferLocation) { + fCommandList->SetGraphicsRootConstantBufferView(rootParameterIndex, bufferLocation); +} + +void GrD3DDirectCommandList::setGraphicsRootDescriptorTable( + unsigned int rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor) { + fCommandList->SetGraphicsRootDescriptorTable(rootParameterIndex, baseDescriptor); +} + +void GrD3DDirectCommandList::setDescriptorHeaps(sk_sp<GrRecycledResource> srvCrvHeapResource, + ID3D12DescriptorHeap* srvCrvDescriptorHeap, + sk_sp<GrRecycledResource> samplerHeapResource, + ID3D12DescriptorHeap* samplerDescriptorHeap) { + if (srvCrvDescriptorHeap != fCurrentSRVCRVDescriptorHeap || + samplerDescriptorHeap != fCurrentSamplerDescriptorHeap) { + ID3D12DescriptorHeap* heaps[2] = { + srvCrvDescriptorHeap, + samplerDescriptorHeap + }; + + fCommandList->SetDescriptorHeaps(2, heaps); + this->addRecycledResource(std::move(srvCrvHeapResource)); + this->addRecycledResource(std::move(samplerHeapResource)); + fCurrentSRVCRVDescriptorHeap = srvCrvDescriptorHeap; + fCurrentSamplerDescriptorHeap = samplerDescriptorHeap; + } +} + +void GrD3DDirectCommandList::addSampledTextureRef(GrD3DTexture* texture) { + this->addResource(texture->resource()); +} + //////////////////////////////////////////////////////////////////////////////////////////////////// std::unique_ptr<GrD3DCopyCommandList> GrD3DCopyCommandList::Make(ID3D12Device* device) { diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.h index 781f8f7c52d..4bea28bad1e 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.h @@ -12,20 +12,25 @@ #include "include/gpu/d3d/GrD3DTypes.h" #include "include/private/SkColorData.h" #include "src/gpu/GrManagedResource.h" +#include "src/gpu/d3d/GrD3DConstantRingBuffer.h" #include <memory> class GrD3DGpu; class GrD3DBuffer; +class GrD3DConstantRingBuffer; class GrD3DPipelineState; class GrD3DRenderTarget; +class GrD3DRootSignature; +class GrD3DStencilAttachment; +class GrD3DTexture; class GrD3DTextureResource; -class GrFixedClip; +class GrScissorState; class GrD3DCommandList { public: - ~GrD3DCommandList() { + virtual ~GrD3DCommandList() { this->releaseResources(); } @@ -47,11 +52,11 @@ public: // All barriers should reference subresources of managedResource void resourceBarrier(sk_sp<GrManagedResource> managedResource, int numBarriers, - D3D12_RESOURCE_TRANSITION_BARRIER* barriers); + const D3D12_RESOURCE_TRANSITION_BARRIER* barriers); // Helper method that calls copyTextureRegion multiple times, once for each subresource - void copyBufferToTexture(GrD3DBuffer* srcBuffer, - GrD3DTextureResource* dstTexture, + void copyBufferToTexture(const GrD3DBuffer* srcBuffer, + const GrD3DTextureResource* dstTexture, uint32_t subresourceCount, D3D12_PLACED_SUBRESOURCE_FOOTPRINT* bufferFootprints, int left, int top); @@ -61,9 +66,24 @@ public: sk_sp<GrManagedResource> src, const D3D12_TEXTURE_COPY_LOCATION* srcLocation, const D3D12_BOX* srcBox); + void copyBufferToBuffer(sk_sp<GrManagedResource> dst, + ID3D12Resource* dstBuffer, uint64_t dstOffset, + sk_sp<GrManagedResource> src, + ID3D12Resource* srcBuffer, uint64_t srcOffset, + uint64_t numBytes); - void clearRenderTargetView(GrD3DRenderTarget* renderTarget, const SkPMColor4f& color, - const GrFixedClip& clip); + void releaseResources(); + + bool hasWork() const { return fHasWork; } + + void addFinishedCallback(sk_sp<GrRefCntedCallback> callback); + +private: + static const int kInitialTrackedResourcesCount = 32; + +protected: + GrD3DCommandList(gr_cp<ID3D12CommandAllocator> allocator, + gr_cp<ID3D12GraphicsCommandList> commandList); // Add ref-counted resource that will be tracked and released when this command buffer finishes // execution @@ -80,18 +100,8 @@ public: fTrackedRecycledResources.push_back(std::move(resource)); } - void releaseResources(); - - bool hasWork() const { return fHasWork; } - -private: - static const int kInitialTrackedResourcesCount = 32; - -protected: - GrD3DCommandList(gr_cp<ID3D12CommandAllocator> allocator, - gr_cp<ID3D12GraphicsCommandList> commandList); - void addingWork(); + virtual void onReset() {} void submitResourceBarriers(); @@ -105,26 +115,76 @@ protected: bool fHasWork = false; private: + void callFinishedCallbacks() { fFinishedCallbacks.reset(); } + gr_cp<ID3D12CommandAllocator> fAllocator; SkSTArray<4, D3D12_RESOURCE_BARRIER> fResourceBarriers; + + SkTArray<sk_sp<GrRefCntedCallback>> fFinishedCallbacks; }; class GrD3DDirectCommandList : public GrD3DCommandList { public: static std::unique_ptr<GrD3DDirectCommandList> Make(ID3D12Device* device); + ~GrD3DDirectCommandList() override = default; + void setPipelineState(sk_sp<GrD3DPipelineState> pipelineState); + void setCurrentConstantBuffer(const sk_sp<GrD3DConstantRingBuffer>& constantBuffer); + void setStencilRef(unsigned int stencilRef); void setBlendFactor(const float blendFactor[4]); void setPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY primitiveTopology); void setScissorRects(unsigned int numRects, const D3D12_RECT* rects); void setViewports(unsigned int numViewports, const D3D12_VIEWPORT* viewports); + void setGraphicsRootSignature(const sk_sp<GrD3DRootSignature>& rootSignature); + void setVertexBuffers(unsigned int startSlot, + const GrD3DBuffer* vertexBuffer, size_t vertexStride, + const GrD3DBuffer* instanceBuffer, size_t instanceStride); + void setIndexBuffer(const GrD3DBuffer* indexBuffer); + void drawInstanced(unsigned int vertexCount, unsigned int instanceCount, + unsigned int startVertex, unsigned int startInstance); + void drawIndexedInstanced(unsigned int indexCount, unsigned int instanceCount, + unsigned int startIndex, unsigned int baseVertex, + unsigned int startInstance); + + void clearRenderTargetView(const GrD3DRenderTarget* renderTarget, const SkPMColor4f& color, + const D3D12_RECT* rect); + void clearDepthStencilView(const GrD3DStencilAttachment*, uint8_t stencilClearValue, + const D3D12_RECT* rect); + void setRenderTarget(const GrD3DRenderTarget* renderTarget); + + void setGraphicsRootConstantBufferView(unsigned int rootParameterIndex, + D3D12_GPU_VIRTUAL_ADDRESS bufferLocation); + void setGraphicsRootDescriptorTable(unsigned int rootParameterIndex, + D3D12_GPU_DESCRIPTOR_HANDLE bufferLocation); + void setDescriptorHeaps(sk_sp<GrRecycledResource> srvCrvHeapResource, + ID3D12DescriptorHeap* srvDescriptorHeap, + sk_sp<GrRecycledResource> samplerHeapResource, + ID3D12DescriptorHeap* samplerDescriptorHeap); + + void addSampledTextureRef(GrD3DTexture*); private: GrD3DDirectCommandList(gr_cp<ID3D12CommandAllocator> allocator, gr_cp<ID3D12GraphicsCommandList> commandList); + + void onReset() override; + + const GrD3DRootSignature* fCurrentRootSignature; + const GrD3DBuffer* fCurrentVertexBuffer; + size_t fCurrentVertexStride; + const GrD3DBuffer* fCurrentInstanceBuffer; + size_t fCurrentInstanceStride; + const GrD3DBuffer* fCurrentIndexBuffer; + + GrD3DConstantRingBuffer* fCurrentConstantRingBuffer; + GrD3DConstantRingBuffer::SubmitData fConstantRingBufferSubmitData; + + const ID3D12DescriptorHeap* fCurrentSRVCRVDescriptorHeap; + const ID3D12DescriptorHeap* fCurrentSamplerDescriptorHeap; }; class GrD3DCopyCommandList : public GrD3DCommandList { diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DConstantRingBuffer.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DConstantRingBuffer.cpp new file mode 100644 index 00000000000..cf719c7745b --- /dev/null +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DConstantRingBuffer.cpp @@ -0,0 +1,30 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "src/gpu/d3d/GrD3DConstantRingBuffer.h" + +#include "src/gpu/d3d/GrD3DBuffer.h" +#include "src/gpu/d3d/GrD3DGpu.h" + +sk_sp<GrD3DConstantRingBuffer> GrD3DConstantRingBuffer::Make(GrD3DGpu* gpu, size_t size, + size_t alignment) { + sk_sp<GrGpuBuffer> buffer = GrD3DBuffer::Make(gpu, size, GrGpuBufferType::kVertex, + kDynamic_GrAccessPattern); + if (!buffer) { + return nullptr; + } + + return sk_sp<GrD3DConstantRingBuffer>(new GrD3DConstantRingBuffer(std::move(buffer), size, + alignment, gpu)); +} + +sk_sp<GrGpuBuffer> GrD3DConstantRingBuffer::createBuffer(size_t size) { + // Make sure the old buffer is added to the current command list + fGpu->resourceProvider().prepForSubmit(); + + return GrD3DBuffer::Make(fGpu, size, GrGpuBufferType::kVertex, kDynamic_GrAccessPattern); +} diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DConstantRingBuffer.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DConstantRingBuffer.h new file mode 100644 index 00000000000..0a4bbf60675 --- /dev/null +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DConstantRingBuffer.h @@ -0,0 +1,33 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrD3DConstantRingBuffer_DEFINED + +#define GrD3DConstantRingBuffer_DEFINED + +#include "src/gpu/GrRingBuffer.h" + +class GrD3DGpu; + +class GrD3DConstantRingBuffer : public GrRingBuffer { +public: + static sk_sp<GrD3DConstantRingBuffer> Make(GrD3DGpu* gpu, size_t size, size_t alignment); + +private: + GrD3DConstantRingBuffer(sk_sp<GrGpuBuffer> buffer, size_t size, size_t alignment, GrD3DGpu* gpu) + : INHERITED(std::move(buffer), size, alignment) + , fGpu(gpu) {} + ~GrD3DConstantRingBuffer() override = default; + + sk_sp<GrGpuBuffer> createBuffer(size_t size) override; + + GrD3DGpu* fGpu; + + typedef GrRingBuffer INHERITED; +}; + +#endif diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DCpuDescriptorManager.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DCpuDescriptorManager.cpp new file mode 100644 index 00000000000..3ad33c388ea --- /dev/null +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DCpuDescriptorManager.cpp @@ -0,0 +1,158 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "src/gpu/d3d/GrD3DCpuDescriptorManager.h" + +#include "src/gpu/d3d/GrD3DGpu.h" + +GrD3DCpuDescriptorManager::GrD3DCpuDescriptorManager(GrD3DGpu* gpu) + : fRTVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_RTV) + , fDSVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_DSV) + , fCBVSRVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) + , fSamplerDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) {} + +GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createRenderTargetView( + GrD3DGpu* gpu, ID3D12Resource* textureResource) { + const GrD3DDescriptorHeap::CPUHandle& descriptor = fRTVDescriptorPool.allocateHandle(gpu); + gpu->device()->CreateRenderTargetView(textureResource, nullptr, descriptor.fHandle); + return descriptor; +} + +void GrD3DCpuDescriptorManager::recycleRenderTargetView( + const GrD3DDescriptorHeap::CPUHandle& rtvDescriptor) { + fRTVDescriptorPool.releaseHandle(rtvDescriptor); +} + +GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createDepthStencilView( + GrD3DGpu* gpu, ID3D12Resource* textureResource) { + const GrD3DDescriptorHeap::CPUHandle& descriptor = fDSVDescriptorPool.allocateHandle(gpu); + gpu->device()->CreateDepthStencilView(textureResource, nullptr, descriptor.fHandle); + return descriptor; +} + +void GrD3DCpuDescriptorManager::recycleDepthStencilView( + const GrD3DDescriptorHeap::CPUHandle& dsvDescriptor) { + fDSVDescriptorPool.releaseHandle(dsvDescriptor); +} + +GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createConstantBufferView( + GrD3DGpu* gpu, ID3D12Resource* bufferResource, size_t offset, size_t size) { + const GrD3DDescriptorHeap::CPUHandle& descriptor = fCBVSRVDescriptorPool.allocateHandle(gpu); + D3D12_CONSTANT_BUFFER_VIEW_DESC desc = {}; + desc.BufferLocation = bufferResource->GetGPUVirtualAddress() + offset; + desc.SizeInBytes = size; + gpu->device()->CreateConstantBufferView(&desc, descriptor.fHandle); + return descriptor; +} + +GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createShaderResourceView( + GrD3DGpu* gpu, ID3D12Resource* resource) { + const GrD3DDescriptorHeap::CPUHandle& descriptor = fCBVSRVDescriptorPool.allocateHandle(gpu); + // TODO: for 4:2:0 YUV formats we'll need to map two different views, one for Y and one for UV. + // For now map the entire resource. + gpu->device()->CreateShaderResourceView(resource, nullptr, descriptor.fHandle); + return descriptor; +} + +void GrD3DCpuDescriptorManager::recycleConstantOrShaderView( + const GrD3DDescriptorHeap::CPUHandle& view) { + fCBVSRVDescriptorPool.releaseHandle(view); +} + +GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createSampler( + GrD3DGpu* gpu, D3D12_FILTER filter, D3D12_TEXTURE_ADDRESS_MODE addressModeU, + D3D12_TEXTURE_ADDRESS_MODE addressModeV) { + const GrD3DDescriptorHeap::CPUHandle& descriptor = fSamplerDescriptorPool.allocateHandle(gpu); + D3D12_SAMPLER_DESC desc = {}; + desc.Filter = filter; + desc.AddressU = addressModeU; + desc.AddressV = addressModeV; + desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + desc.MipLODBias = 0; + desc.MaxAnisotropy = 1; + desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; + // desc.BorderColor initialized to { 0, 0, 0, 0 } by default initializer, above. + desc.MinLOD = 0; + desc.MaxLOD = SK_ScalarMax; + + gpu->device()->CreateSampler(&desc, descriptor.fHandle); + return descriptor; +} + +void GrD3DCpuDescriptorManager::recycleSampler( + const GrD3DDescriptorHeap::CPUHandle& samplerDescriptor) { + fSamplerDescriptorPool.releaseHandle(samplerDescriptor); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// + +std::unique_ptr<GrD3DCpuDescriptorManager::Heap> GrD3DCpuDescriptorManager::Heap::Make( + GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, unsigned int numDescriptors) { + std::unique_ptr<GrD3DDescriptorHeap> heap = + GrD3DDescriptorHeap::Make(gpu, type, numDescriptors, D3D12_DESCRIPTOR_HEAP_FLAG_NONE); + if (!heap) { + return nullptr; + } + + return std::unique_ptr<Heap>(new Heap(heap, numDescriptors)); +} + +GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::Heap::allocateCPUHandle() { + SkBitSet::OptionalIndex freeBlock = fFreeBlocks.findFirst(); + SkASSERT(freeBlock); + fFreeBlocks.reset(*freeBlock); + --fFreeCount; + return fHeap->getCPUHandle(*freeBlock); +} + +void GrD3DCpuDescriptorManager::Heap::freeCPUHandle(const GrD3DDescriptorHeap::CPUHandle& handle) { + SkASSERT(this->ownsHandle(handle)); + size_t index = fHeap->getIndex(handle); + fFreeBlocks.set(index); + ++fFreeCount; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// + +GrD3DCpuDescriptorManager::HeapPool::HeapPool(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE heapType) + : fMaxAvailableDescriptors(32) + , fHeapType(heapType) { + std::unique_ptr<GrD3DCpuDescriptorManager::Heap> heap = + GrD3DCpuDescriptorManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors); + fDescriptorHeaps.push_back(std::move(heap)); +} + +GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::HeapPool::allocateHandle( + GrD3DGpu* gpu) { + for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) { + if (fDescriptorHeaps[i]->canAllocate()) { + GrD3DDescriptorHeap::CPUHandle handle = fDescriptorHeaps[i]->allocateCPUHandle(); + return handle; + } + } + + // need to allocate more space + std::unique_ptr<GrD3DCpuDescriptorManager::Heap> heap = + GrD3DCpuDescriptorManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors); + + fDescriptorHeaps.push_back(std::move(heap)); + fMaxAvailableDescriptors *= 2; + GrD3DDescriptorHeap::CPUHandle handle = + fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateCPUHandle(); + return handle; +} + +void GrD3DCpuDescriptorManager::HeapPool::releaseHandle( + const GrD3DDescriptorHeap::CPUHandle& dsvDescriptor) { + for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) { + if (fDescriptorHeaps[i]->ownsHandle(dsvDescriptor)) { + fDescriptorHeaps[i]->freeCPUHandle(dsvDescriptor); + return; + } + } + SkASSERT(false); +} diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DCpuDescriptorManager.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DCpuDescriptorManager.h new file mode 100644 index 00000000000..056c6968738 --- /dev/null +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DCpuDescriptorManager.h @@ -0,0 +1,89 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrD3DCpuDescriptorManager_DEFINED +#define GrD3DCpuDescriptorManager_DEFINED + +#include "src/gpu/d3d/GrD3DDescriptorHeap.h" + +class GrD3DGpu; + +class GrD3DCpuDescriptorManager { +public: + GrD3DCpuDescriptorManager(GrD3DGpu*); + + GrD3DDescriptorHeap::CPUHandle createRenderTargetView(GrD3DGpu*, + ID3D12Resource* textureResource); + void recycleRenderTargetView(const GrD3DDescriptorHeap::CPUHandle&); + + GrD3DDescriptorHeap::CPUHandle createDepthStencilView(GrD3DGpu*, + ID3D12Resource* textureResource); + void recycleDepthStencilView(const GrD3DDescriptorHeap::CPUHandle&); + + GrD3DDescriptorHeap::CPUHandle createConstantBufferView(GrD3DGpu*, + ID3D12Resource* bufferResource, + size_t offset, + size_t size); + GrD3DDescriptorHeap::CPUHandle createShaderResourceView(GrD3DGpu*, + ID3D12Resource* resource); + void recycleConstantOrShaderView(const GrD3DDescriptorHeap::CPUHandle&); + + GrD3DDescriptorHeap::CPUHandle createSampler(GrD3DGpu*, + D3D12_FILTER filter, + D3D12_TEXTURE_ADDRESS_MODE addressModeU, + D3D12_TEXTURE_ADDRESS_MODE addressModeV); + void recycleSampler(const GrD3DDescriptorHeap::CPUHandle&); + +private: + class Heap { + public: + static std::unique_ptr<Heap> Make(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, + unsigned int numDescriptors); + + GrD3DDescriptorHeap::CPUHandle allocateCPUHandle(); + void freeCPUHandle(const GrD3DDescriptorHeap::CPUHandle&); + bool ownsHandle(const GrD3DDescriptorHeap::CPUHandle& handle) { + return handle.fHeapID == fHeap->uniqueID(); + } + + bool canAllocate() { return fFreeCount > 0; } + + private: + Heap(std::unique_ptr<GrD3DDescriptorHeap>& heap, unsigned int numDescriptors) + : fHeap(std::move(heap)) + , fFreeBlocks(numDescriptors) + , fFreeCount(numDescriptors) { + for (unsigned int i = 0; i < numDescriptors; ++i) { + fFreeBlocks.set(i); + } + } + + std::unique_ptr<GrD3DDescriptorHeap> fHeap; + SkBitSet fFreeBlocks; + unsigned int fFreeCount; + }; + + class HeapPool { + public: + HeapPool(GrD3DGpu*, D3D12_DESCRIPTOR_HEAP_TYPE); + + GrD3DDescriptorHeap::CPUHandle allocateHandle(GrD3DGpu*); + void releaseHandle(const GrD3DDescriptorHeap::CPUHandle&); + + private: + std::vector<std::unique_ptr<Heap>> fDescriptorHeaps; + int fMaxAvailableDescriptors; + D3D12_DESCRIPTOR_HEAP_TYPE fHeapType; + }; + + HeapPool fRTVDescriptorPool; + HeapPool fDSVDescriptorPool; + HeapPool fCBVSRVDescriptorPool; + HeapPool fSamplerDescriptorPool; +}; + +#endif diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.cpp index b3ae3cc330e..8d2569783bf 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.cpp @@ -28,25 +28,24 @@ std::unique_ptr<GrD3DDescriptorHeap> GrD3DDescriptorHeap::Make(GrD3DGpu* gpu, GrD3DDescriptorHeap::GrD3DDescriptorHeap(const gr_cp<ID3D12DescriptorHeap>& heap, unsigned int handleIncrementSize) : fHeap(heap) - , fHandleIncrementSize(handleIncrementSize) { + , fHandleIncrementSize(handleIncrementSize) + , fUniqueID(GenID()) { fCPUHeapStart = fHeap->GetCPUDescriptorHandleForHeapStart(); fGPUHeapStart = fHeap->GetGPUDescriptorHandleForHeapStart(); } -D3D12_CPU_DESCRIPTOR_HANDLE GrD3DDescriptorHeap::getCPUHandle(unsigned int index) { - // valid only for non-shader-visible heaps - SkASSERT(!SkToBool(fHeap->GetDesc().Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)); +GrD3DDescriptorHeap::CPUHandle GrD3DDescriptorHeap::getCPUHandle(unsigned int index) { SkASSERT(index < fHeap->GetDesc().NumDescriptors); D3D12_CPU_DESCRIPTOR_HANDLE handle = fCPUHeapStart; handle.ptr += index * fHandleIncrementSize; - return handle; + return {handle, fUniqueID}; } -D3D12_GPU_DESCRIPTOR_HANDLE GrD3DDescriptorHeap::getGPUHandle(unsigned int index) { +GrD3DDescriptorHeap::GPUHandle GrD3DDescriptorHeap::getGPUHandle(unsigned int index) { SkASSERT(index < fHeap->GetDesc().NumDescriptors); D3D12_GPU_DESCRIPTOR_HANDLE handle = fGPUHeapStart; handle.ptr += index * fHandleIncrementSize; - return handle; + return {handle, fUniqueID}; } diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.h index 19e2745011c..30fdc1358eb 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.h @@ -22,42 +22,56 @@ public: ~GrD3DDescriptorHeap() = default; - D3D12_CPU_DESCRIPTOR_HANDLE getCPUHandle(unsigned int index); // only if non-shader-visible - D3D12_GPU_DESCRIPTOR_HANDLE getGPUHandle(unsigned int index); - - bool getIndex(D3D12_CPU_DESCRIPTOR_HANDLE handle, size_t* indexPtr) { - if (handle.ptr < fCPUHeapStart.ptr) { - return false; - } - size_t index = (handle.ptr - fCPUHeapStart.ptr) / fHandleIncrementSize; - if (index >= fHeap->GetDesc().NumDescriptors) { - return false; - } - SkASSERT(handle.ptr == fCPUHeapStart.ptr + index * fHandleIncrementSize); - *indexPtr = index; - return true; + uint32_t uniqueID() const { return fUniqueID; } + + struct CPUHandle { + D3D12_CPU_DESCRIPTOR_HANDLE fHandle; + uint32_t fHeapID; + }; + + struct GPUHandle { + D3D12_GPU_DESCRIPTOR_HANDLE fHandle; + uint32_t fHeapID; + }; + + CPUHandle getCPUHandle(unsigned int index); // write-only if shader-visible + GPUHandle getGPUHandle(unsigned int index); + ID3D12DescriptorHeap* descriptorHeap() const { return fHeap.get(); } + size_t handleIncrementSize() { return fHandleIncrementSize; } + + size_t getIndex(const CPUHandle& handle) { + SkASSERT(handle.fHeapID == fUniqueID); + size_t index = (handle.fHandle.ptr - fCPUHeapStart.ptr) / fHandleIncrementSize; + SkASSERT(index < fHeap->GetDesc().NumDescriptors); + SkASSERT(handle.fHandle.ptr == fCPUHeapStart.ptr + index * fHandleIncrementSize); + return index; } - bool getIndex(D3D12_GPU_DESCRIPTOR_HANDLE handle, size_t* indexPtr) { - if (handle.ptr < fGPUHeapStart.ptr) { - return false; - } - size_t index = (handle.ptr - fGPUHeapStart.ptr) / fHandleIncrementSize; - if (index >= fHeap->GetDesc().NumDescriptors) { - return false; - } - SkASSERT(handle.ptr == fGPUHeapStart.ptr + index * fHandleIncrementSize); - *indexPtr = index; - return true; + size_t getIndex(const GPUHandle& handle) { + SkASSERT(handle.fHeapID == fUniqueID); + size_t index = (handle.fHandle.ptr - fCPUHeapStart.ptr) / fHandleIncrementSize; + SkASSERT(index < fHeap->GetDesc().NumDescriptors); + SkASSERT(handle.fHandle.ptr == fCPUHeapStart.ptr + index * fHandleIncrementSize); + return index; } protected: GrD3DDescriptorHeap(const gr_cp<ID3D12DescriptorHeap>&, unsigned int handleIncrementSize); + static uint32_t GenID() { + static std::atomic<uint32_t> nextID{1}; + uint32_t id; + do { + id = nextID++; + } while (id == SK_InvalidUniqueID); + return id; + } + gr_cp<ID3D12DescriptorHeap> fHeap; size_t fHandleIncrementSize; D3D12_CPU_DESCRIPTOR_HANDLE fCPUHeapStart; D3D12_GPU_DESCRIPTOR_HANDLE fGPUHeapStart; + uint32_t fUniqueID; }; #endif diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorTableManager.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorTableManager.cpp new file mode 100644 index 00000000000..7bbb95f2450 --- /dev/null +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorTableManager.cpp @@ -0,0 +1,150 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "src/gpu/d3d/GrD3DDescriptorTableManager.h" + +#include "src/gpu/d3d/GrD3DGpu.h" + +GrD3DDescriptorTableManager::GrD3DDescriptorTableManager(GrD3DGpu* gpu) + : fCBVSRVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) + , fSamplerDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) {} + +std::unique_ptr<GrD3DDescriptorTable> + GrD3DDescriptorTableManager::createShaderOrConstantResourceTable(GrD3DGpu* gpu, + unsigned int size) { + std::unique_ptr<GrD3DDescriptorTable> table = fCBVSRVDescriptorPool.allocateTable(gpu, size); + this->setHeaps(gpu); + return table; +} + +std::unique_ptr<GrD3DDescriptorTable> GrD3DDescriptorTableManager::createSamplerTable( + GrD3DGpu* gpu, unsigned int size) { + std::unique_ptr<GrD3DDescriptorTable> table = fSamplerDescriptorPool.allocateTable(gpu, size); + this->setHeaps(gpu); + return table; +} + +void GrD3DDescriptorTableManager::setHeaps(GrD3DGpu* gpu) { + sk_sp<Heap>& currentCBVSRVHeap = fCBVSRVDescriptorPool.currentDescriptorHeap(); + sk_sp<Heap>& currentSamplerHeap = fSamplerDescriptorPool.currentDescriptorHeap(); + GrD3DDirectCommandList* commandList = gpu->currentCommandList(); + commandList->setDescriptorHeaps(currentCBVSRVHeap, + currentCBVSRVHeap->d3dDescriptorHeap(), + currentSamplerHeap, + currentSamplerHeap->d3dDescriptorHeap()); +} + +void GrD3DDescriptorTableManager::prepForSubmit(GrD3DGpu* gpu) { + fCBVSRVDescriptorPool.prepForSubmit(gpu); + fSamplerDescriptorPool.prepForSubmit(gpu); +} + +void GrD3DDescriptorTableManager::recycle(Heap* heap) { + // wrap the heap in an sk_sp and take ownership of it + sk_sp<Heap> wrappedHeap(heap); + + SkASSERT(heap); + switch (heap->type()) { + case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV: + fCBVSRVDescriptorPool.recycle(std::move(wrappedHeap)); + break; + case D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER: + fSamplerDescriptorPool.recycle(std::move(wrappedHeap)); + break; + default: + SkUNREACHABLE; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////// + +sk_sp<GrD3DDescriptorTableManager::Heap> GrD3DDescriptorTableManager::Heap::Make( + GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, unsigned int descriptorCount) { + std::unique_ptr<GrD3DDescriptorHeap> heap = + GrD3DDescriptorHeap::Make(gpu, type, descriptorCount, + D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); + if (!heap) { + return nullptr; + } + + return sk_sp< GrD3DDescriptorTableManager::Heap>(new Heap(gpu, heap, type, descriptorCount)); +} + +std::unique_ptr<GrD3DDescriptorTable> GrD3DDescriptorTableManager::Heap::allocateTable( + unsigned int count) { + SkASSERT(fDescriptorCount - fNextAvailable >= count); + unsigned int startIndex = fNextAvailable; + fNextAvailable += count; + return std::unique_ptr<GrD3DDescriptorTable>( + new GrD3DDescriptorTable(fHeap->getCPUHandle(startIndex).fHandle, + fHeap->getGPUHandle(startIndex).fHandle, fType)); +} + +void GrD3DDescriptorTableManager::Heap::onRecycle() const { + fGpu->resourceProvider().descriptorTableMgr()->recycle(const_cast<Heap*>(this)); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// + +GrD3DDescriptorTableManager::HeapPool::HeapPool(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE heapType) + : fHeapType(heapType) + , fCurrentHeapDescriptorCount(kInitialHeapDescriptorCount) { + sk_sp<Heap> heap = Heap::Make(gpu, fHeapType, fCurrentHeapDescriptorCount); + fDescriptorHeaps.push_back(heap); +} + +std::unique_ptr<GrD3DDescriptorTable> GrD3DDescriptorTableManager::HeapPool::allocateTable( + GrD3DGpu* gpu, unsigned int count) { + // In back-to-front order, iterate through heaps until we find one we can allocate from. + // Any heap we can't allocate from gets removed from the list. + // If it was already used, it will have been added to the commandlist, + // and then later recycled back to us. + while (fDescriptorHeaps.size() > 0) { + if (fDescriptorHeaps[fDescriptorHeaps.size() - 1]->canAllocate(count)) { + return fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateTable(count); + } + // No space in current heap, pop off list + fDescriptorHeaps.pop_back(); + } + + // Out of available heaps, need to allocate a new one + fCurrentHeapDescriptorCount = std::min(2*fCurrentHeapDescriptorCount, 2048u); + sk_sp<GrD3DDescriptorTableManager::Heap> heap = + GrD3DDescriptorTableManager::Heap::Make(gpu, fHeapType, fCurrentHeapDescriptorCount); + fDescriptorHeaps.push_back(heap); + return fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateTable(count); +} + +sk_sp<GrD3DDescriptorTableManager::Heap>& + GrD3DDescriptorTableManager::HeapPool::currentDescriptorHeap() { + SkASSERT(fDescriptorHeaps.size() > 0); + return fDescriptorHeaps[fDescriptorHeaps.size() - 1]; +} + +void GrD3DDescriptorTableManager::HeapPool::prepForSubmit(GrD3DGpu* gpu) { + // Pop off the current descriptor heap + if (fDescriptorHeaps[fDescriptorHeaps.size() - 1]->used()) { + fDescriptorHeaps.pop_back(); + } + + if (fDescriptorHeaps.size() == 0) { + fCurrentHeapDescriptorCount = std::min(fCurrentHeapDescriptorCount, 2048u); + sk_sp<GrD3DDescriptorTableManager::Heap> heap = + GrD3DDescriptorTableManager::Heap::Make(gpu, fHeapType, fCurrentHeapDescriptorCount); + fDescriptorHeaps.push_back(heap); + } +} + +void GrD3DDescriptorTableManager::HeapPool::recycle(sk_sp<Heap> heap) { + SkASSERT(heap); + // only add heaps back if they match our current size + // this purges any smaller heaps we no longer need + if (heap->descriptorCount() == fCurrentHeapDescriptorCount) { + heap->reset(); + fDescriptorHeaps.push_back(heap); + } +} diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorTableManager.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorTableManager.h new file mode 100644 index 00000000000..295b8680afc --- /dev/null +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorTableManager.h @@ -0,0 +1,123 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrD3DGpuDescriptorTableManager_DEFINED +#define GrD3DGpuDescriptorTableManager_DEFINED + +#include "src/gpu/d3d/GrD3DDescriptorHeap.h" + +class GrD3DCommandList; +class GrD3DDirectCommandList; +class GrD3DGpu; + +class GrD3DDescriptorTable { +public: + GrD3DDescriptorTable(D3D12_CPU_DESCRIPTOR_HANDLE baseCPU, D3D12_GPU_DESCRIPTOR_HANDLE baseGPU, + D3D12_DESCRIPTOR_HEAP_TYPE type) + : fDescriptorTableCpuStart(baseCPU) + , fDescriptorTableGpuStart(baseGPU) + , fType(type) {} + + const D3D12_CPU_DESCRIPTOR_HANDLE* baseCpuDescriptorPtr() { + return &fDescriptorTableCpuStart; + } + + const D3D12_GPU_DESCRIPTOR_HANDLE baseGpuDescriptor() { + return fDescriptorTableGpuStart; + } + + D3D12_DESCRIPTOR_HEAP_TYPE type() const { return fType; } + +private: + D3D12_CPU_DESCRIPTOR_HANDLE fDescriptorTableCpuStart; + D3D12_GPU_DESCRIPTOR_HANDLE fDescriptorTableGpuStart; + D3D12_DESCRIPTOR_HEAP_TYPE fType; +}; + +class GrD3DDescriptorTableManager { +public: + GrD3DDescriptorTableManager(GrD3DGpu*); + + std::unique_ptr<GrD3DDescriptorTable> createShaderOrConstantResourceTable(GrD3DGpu*, + unsigned int count); + std::unique_ptr<GrD3DDescriptorTable> createSamplerTable(GrD3DGpu*, unsigned int count); + + void prepForSubmit(GrD3DGpu* gpu); + +private: + class Heap : public GrRecycledResource { + public: + static sk_sp<Heap> Make(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, + unsigned int numDescriptors); + + std::unique_ptr<GrD3DDescriptorTable> allocateTable(unsigned int count); + bool canAllocate(unsigned int count) const { + return (fDescriptorCount - fNextAvailable) >= count; + } + ID3D12DescriptorHeap* d3dDescriptorHeap() const { return fHeap->descriptorHeap(); } + D3D12_DESCRIPTOR_HEAP_TYPE type() const { return fType; } + unsigned int descriptorCount() { return fDescriptorCount; } + bool used() { return fNextAvailable > 0; } + + void reset() { + fNextAvailable = 0; + } + + private: + Heap(GrD3DGpu* gpu, std::unique_ptr<GrD3DDescriptorHeap>& heap, + D3D12_DESCRIPTOR_HEAP_TYPE type, unsigned int descriptorCount) + : INHERITED() + , fGpu(gpu) + , fHeap(std::move(heap)) + , fType(type) + , fDescriptorCount(descriptorCount) + , fNextAvailable(0) { + } + + void freeGPUData() const override {} + void onRecycle() const override; + +#ifdef SK_TRACE_MANAGED_RESOURCES + void dumpInfo() const override { + SkDebugf("GrD3DDescriptorTable::Heap: %d (%d refs)\n", fHeap.get(), this->getRefCnt()); + } +#endif + + GrD3DGpu* fGpu; + std::unique_ptr<GrD3DDescriptorHeap> fHeap; + D3D12_DESCRIPTOR_HEAP_TYPE fType; + unsigned int fDescriptorCount; + unsigned int fNextAvailable; + + typedef GrRecycledResource INHERITED; + }; + + class HeapPool { + public: + HeapPool(GrD3DGpu*, D3D12_DESCRIPTOR_HEAP_TYPE); + + std::unique_ptr<GrD3DDescriptorTable> allocateTable(GrD3DGpu*, unsigned int count); + void recycle(sk_sp<Heap>); + sk_sp<Heap>& currentDescriptorHeap(); + void prepForSubmit(GrD3DGpu* gpu); + + private: + static constexpr int kInitialHeapDescriptorCount = 256; + + std::vector<sk_sp<Heap>> fDescriptorHeaps; + D3D12_DESCRIPTOR_HEAP_TYPE fHeapType; + unsigned int fCurrentHeapDescriptorCount; + }; + + void setHeaps(GrD3DGpu*); + void recycle(Heap*); + + HeapPool fCBVSRVDescriptorPool; + HeapPool fSamplerDescriptorPool; +}; + +#endif diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.cpp index fb79434c9e1..fbfc3c741bf 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.cpp @@ -11,6 +11,7 @@ #include "include/gpu/d3d/GrD3DBackendContext.h" #include "src/core/SkConvertPixels.h" #include "src/core/SkMipMap.h" +#include "src/gpu/GrBackendUtils.h" #include "src/gpu/GrDataUtils.h" #include "src/gpu/GrTexturePriv.h" #include "src/gpu/d3d/GrD3DBuffer.h" @@ -84,16 +85,19 @@ void GrD3DGpu::destroyResources() { // We used a placement new for each object in fOutstandingCommandLists, so we're responsible // for calling the destructor on each of them as well. while (!fOutstandingCommandLists.empty()) { - OutstandingCommandList* list = (OutstandingCommandList*)fOutstandingCommandLists.back(); + OutstandingCommandList* list = (OutstandingCommandList*)fOutstandingCommandLists.front(); SkASSERT(list->fFenceValue <= fenceValue); // No reason to recycle the command lists since we are destroying all resources anyways. list->~OutstandingCommandList(); - fOutstandingCommandLists.pop_back(); + fOutstandingCommandLists.pop_front(); } + + fResourceProvider.destroyResources(); } GrOpsRenderPass* GrD3DGpu::getOpsRenderPass( - GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds, + GrRenderTarget* rt, GrStencilAttachment*, + GrSurfaceOrigin origin, const SkIRect& bounds, const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) { @@ -110,16 +114,23 @@ GrOpsRenderPass* GrD3DGpu::getOpsRenderPass( bool GrD3DGpu::submitDirectCommandList(SyncQueue sync) { SkASSERT(fCurrentDirectCommandList); + fResourceProvider.prepForSubmit(); + GrD3DDirectCommandList::SubmitResult result = fCurrentDirectCommandList->submit(fQueue.get()); if (result == GrD3DDirectCommandList::SubmitResult::kFailure) { return false; } else if (result == GrD3DDirectCommandList::SubmitResult::kNoWork) { if (sync == SyncQueue::kForce) { this->waitForQueueCompletion(); + this->checkForFinishedCommandLists(); } return true; } + // We just submitted the command list so make sure all GrD3DPipelineState's mark their cached + // uniform data as dirty. + fResourceProvider.markPipelineStateUniformsDirty(); + new (fOutstandingCommandLists.push_back()) OutstandingCommandList( std::move(fCurrentDirectCommandList), ++fCurrentFenceValue); @@ -180,6 +191,29 @@ void GrD3DGpu::submit(GrOpsRenderPass* renderPass) { fCachedOpsRenderPass.reset(); } +void GrD3DGpu::addFinishedProc(GrGpuFinishedProc finishedProc, + GrGpuFinishedContext finishedContext) { + SkASSERT(finishedProc); + sk_sp<GrRefCntedCallback> finishedCallback( + new GrRefCntedCallback(finishedProc, finishedContext)); + this->addFinishedCallback(std::move(finishedCallback)); +} + +void GrD3DGpu::addFinishedCallback(sk_sp<GrRefCntedCallback> finishedCallback) { + SkASSERT(finishedCallback); + // Besides the current command list, we also add the finishedCallback to the newest outstanding + // command list. Our contract for calling the proc is that all previous submitted command lists + // have finished when we call it. However, if our current command list has no work when it is + // flushed it will drop its ref to the callback immediately. But the previous work may not have + // finished. It is safe to only add the proc to the newest outstanding commandlist cause that + // must finish after all previously submitted command lists. + OutstandingCommandList* back = (OutstandingCommandList*)fOutstandingCommandLists.back(); + if (back) { + back->fCommandList->addFinishedCallback(finishedCallback); + } + fCurrentDirectCommandList->addFinishedCallback(std::move(finishedCallback)); +} + void GrD3DGpu::querySampleLocations(GrRenderTarget* rt, SkTArray<SkPoint>* sampleLocations) { // TODO } @@ -561,14 +595,6 @@ bool GrD3DGpu::uploadToTexture(GrD3DTexture* tex, int left, int top, int width, return true; } -void GrD3DGpu::clear(const GrFixedClip& clip, const SkPMColor4f& color, GrRenderTarget* rt) { - GrD3DRenderTarget* d3dRT = static_cast<GrD3DRenderTarget*>(rt); - - d3dRT->setResourceState(this, D3D12_RESOURCE_STATE_RENDER_TARGET); - - fCurrentDirectCommandList->clearRenderTargetView(d3dRT, color, clip); -} - static bool check_resource_info(const GrD3DTextureResourceInfo& info) { if (!info.fResource.get()) { return false; @@ -884,10 +910,157 @@ GrBackendTexture GrD3DGpu::onCreateBackendTexture(SkISize dimensions, return GrBackendTexture(dimensions.width(), dimensions.height(), info); } +bool copy_src_data(GrD3DGpu* gpu, char* mapPtr, DXGI_FORMAT dxgiFormat, + D3D12_PLACED_SUBRESOURCE_FOOTPRINT* placedFootprints, + const SkPixmap srcData[], int numMipLevels) { + SkASSERT(srcData && numMipLevels); + SkASSERT(!GrDxgiFormatIsCompressed(dxgiFormat)); + SkASSERT(mapPtr); + + size_t bytesPerPixel = gpu->d3dCaps().bytesPerPixel(dxgiFormat); + + for (int currentMipLevel = 0; currentMipLevel < numMipLevels; currentMipLevel++) { + const size_t trimRowBytes = srcData[currentMipLevel].width() * bytesPerPixel; + + // copy data into the buffer, skipping any trailing bytes + char* dst = mapPtr + placedFootprints[currentMipLevel].Offset; + SkRectMemcpy(dst, placedFootprints[currentMipLevel].Footprint.RowPitch, + srcData[currentMipLevel].addr(), srcData[currentMipLevel].rowBytes(), + trimRowBytes, srcData[currentMipLevel].height()); + } + + return true; +} + +// Used to "clear" a backend texture to a constant color by transferring. +static GrColorType dxgi_format_to_backend_tex_clear_colortype(DXGI_FORMAT format) { + switch (format) { + case DXGI_FORMAT_A8_UNORM: return GrColorType::kAlpha_8; + case DXGI_FORMAT_R8_UNORM: return GrColorType::kR_8; + + case DXGI_FORMAT_B5G6R5_UNORM: return GrColorType::kBGR_565; + case DXGI_FORMAT_B4G4R4A4_UNORM: return GrColorType::kABGR_4444; + case DXGI_FORMAT_R8G8B8A8_UNORM: return GrColorType::kRGBA_8888; + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return GrColorType::kRGBA_8888_SRGB; + + case DXGI_FORMAT_R8G8_UNORM: return GrColorType::kRG_88; + case DXGI_FORMAT_B8G8R8A8_UNORM: return GrColorType::kBGRA_8888; + case DXGI_FORMAT_R10G10B10A2_UNORM: return GrColorType::kRGBA_1010102; + case DXGI_FORMAT_R16_FLOAT: return GrColorType::kR_F16; + case DXGI_FORMAT_R16G16B16A16_FLOAT: return GrColorType::kRGBA_F16; + case DXGI_FORMAT_R16_UNORM: return GrColorType::kR_16; + case DXGI_FORMAT_R16G16_UNORM: return GrColorType::kRG_1616; + case DXGI_FORMAT_R16G16B16A16_UNORM: return GrColorType::kRGBA_16161616; + case DXGI_FORMAT_R16G16_FLOAT: return GrColorType::kRG_F16; + default: return GrColorType::kUnknown; + } + + SkUNREACHABLE; +} + + +bool copy_color_data(char* mapPtr, DXGI_FORMAT dxgiFormat, SkISize dimensions, + D3D12_PLACED_SUBRESOURCE_FOOTPRINT* placedFootprints, SkColor4f color) { + auto colorType = dxgi_format_to_backend_tex_clear_colortype(dxgiFormat); + if (colorType == GrColorType::kUnknown) { + return false; + } + GrImageInfo ii(colorType, kUnpremul_SkAlphaType, nullptr, dimensions); + if (!GrClearImage(ii, mapPtr, placedFootprints[0].Footprint.RowPitch, color)) { + return false; + } + + return true; +} + bool GrD3DGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture, sk_sp<GrRefCntedCallback> finishedCallback, const BackendTextureData* data) { - // TODO: handle finishedCallback and data upload + GrD3DTextureResourceInfo info; + SkAssertResult(backendTexture.getD3DTextureResourceInfo(&info)); + + sk_sp<GrD3DResourceState> state = backendTexture.getGrD3DResourceState(); + SkASSERT(state); + sk_sp<GrD3DTexture> texture = + GrD3DTexture::MakeWrappedTexture(this, backendTexture.dimensions(), + GrWrapCacheable::kNo, + kRW_GrIOType, info, std::move(state)); + if (!texture) { + return false; + } + + GrD3DDirectCommandList* cmdList = this->currentCommandList(); + if (!cmdList) { + return false; + } + + texture->setResourceState(this, D3D12_RESOURCE_STATE_COPY_DEST); + + ID3D12Resource* d3dResource = texture->d3dResource(); + SkASSERT(d3dResource); + D3D12_RESOURCE_DESC desc = d3dResource->GetDesc(); + unsigned int mipLevelCount = 1; + if (backendTexture.fMipMapped == GrMipMapped::kYes) { + mipLevelCount = SkMipMap::ComputeLevelCount(backendTexture.dimensions().width(), + backendTexture.dimensions().height()) + 1; + } + SkASSERT(mipLevelCount == info.fLevelCount); + SkAutoTMalloc<D3D12_PLACED_SUBRESOURCE_FOOTPRINT> placedFootprints(mipLevelCount); + UINT64 combinedBufferSize; + fDevice->GetCopyableFootprints(&desc, 0, mipLevelCount, 0, placedFootprints.get(), + nullptr, nullptr, &combinedBufferSize); + SkASSERT(combinedBufferSize); + if (data->type() == BackendTextureData::Type::kColor && + !GrDxgiFormatIsCompressed(info.fFormat) && mipLevelCount > 1) { + // For a single uncompressed color, we reuse the same top-level buffer area for all levels. + combinedBufferSize = + placedFootprints[0].Footprint.RowPitch * placedFootprints[0].Footprint.Height; + for (unsigned int i = 1; i < mipLevelCount; ++i) { + placedFootprints[i].Offset = 0; + placedFootprints[i].Footprint.RowPitch = placedFootprints[0].Footprint.RowPitch; + } + } + + // TODO: do this until we have slices of buttery buffers + sk_sp<GrGpuBuffer> transferBuffer = this->createBuffer(combinedBufferSize, + GrGpuBufferType::kXferCpuToGpu, + kDynamic_GrAccessPattern); + if (!transferBuffer) { + return false; + } + char* bufferData = (char*)transferBuffer->map(); + SkASSERT(bufferData); + + bool result; + if (data->type() == BackendTextureData::Type::kPixmaps) { + result = copy_src_data(this, bufferData, info.fFormat, placedFootprints.get(), + data->pixmaps(), info.fLevelCount); + } else if (data->type() == BackendTextureData::Type::kCompressed) { + memcpy(bufferData, data->compressedData(), data->compressedSize()); + result = true; + } else { + SkASSERT(data->type() == BackendTextureData::Type::kColor); + SkImage::CompressionType compression = + GrBackendFormatToCompressionType(backendTexture.getBackendFormat()); + if (SkImage::CompressionType::kNone == compression) { + result = copy_color_data(bufferData, info.fFormat, backendTexture.dimensions(), + placedFootprints, data->color()); + } else { + GrFillInCompressedData(compression, backendTexture.dimensions(), + backendTexture.fMipMapped, bufferData, data->color()); + result = true; + } + } + transferBuffer->unmap(); + + GrD3DBuffer* d3dBuffer = static_cast<GrD3DBuffer*>(transferBuffer.get()); + cmdList->copyBufferToTexture(d3dBuffer, texture.get(), mipLevelCount, placedFootprints.get(), + 0, 0); + + if (finishedCallback) { + this->addFinishedCallback(std::move(finishedCallback)); + } + return true; } @@ -1006,6 +1179,31 @@ void GrD3DGpu::addResourceBarriers(sk_sp<GrManagedResource> resource, fCurrentDirectCommandList->resourceBarrier(std::move(resource), numBarriers, barriers); } +void GrD3DGpu::prepareSurfacesForBackendAccessAndStateUpdates( + GrSurfaceProxy* proxies[], + int numProxies, + SkSurface::BackendSurfaceAccess access, + const GrBackendSurfaceMutableState* newState) { + SkASSERT(numProxies >= 0); + SkASSERT(!numProxies || proxies); + + // prepare proxies by transitioning to PRESENT renderState + if (numProxies && access == SkSurface::BackendSurfaceAccess::kPresent) { + GrD3DTextureResource* resource; + for (int i = 0; i < numProxies; ++i) { + SkASSERT(proxies[i]->isInstantiated()); + if (GrTexture* tex = proxies[i]->peekTexture()) { + resource = static_cast<GrD3DTexture*>(tex); + } else { + GrRenderTarget* rt = proxies[i]->peekRenderTarget(); + SkASSERT(rt); + resource = static_cast<GrD3DRenderTarget*>(rt); + } + resource->prepareForPresent(this); + } + } +} + bool GrD3DGpu::onSubmitToGpu(bool syncCpu) { if (syncCpu) { return this->submitDirectCommandList(SyncQueue::kForce); diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.h index 3c1c9738a10..ce2488134c4 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.h @@ -64,13 +64,18 @@ public: void testingOnly_startCapture() override; void testingOnly_endCapture() override; + + void resetShaderCacheForTesting() const override { + fResourceProvider.resetShaderCacheForTesting(); + } #endif GrStencilAttachment* createStencilAttachmentForRenderTarget( const GrRenderTarget*, int width, int height, int numStencilSamples) override; GrOpsRenderPass* getOpsRenderPass( - GrRenderTarget*, GrSurfaceOrigin, const SkIRect&, + GrRenderTarget*, GrStencilAttachment*, + GrSurfaceOrigin, const SkIRect&, const GrOpsRenderPass::LoadAndStoreInfo&, const GrOpsRenderPass::StencilLoadAndStoreInfo&, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override; @@ -98,11 +103,9 @@ public: return nullptr; } - void clear(const GrFixedClip& clip, const SkPMColor4f& color, GrRenderTarget*); - void submit(GrOpsRenderPass* renderPass) override; - void checkFinishProcs() override {} + void checkFinishProcs() override { this->checkForFinishedCommandLists(); } SkSL::Compiler* shaderCompiler() const { return fCompiler.get(); @@ -184,11 +187,14 @@ private: void onResolveRenderTarget(GrRenderTarget* target, const SkIRect&, ForExternalIO) override {} void addFinishedProc(GrGpuFinishedProc finishedProc, - GrGpuFinishedContext finishedContext) override { - // TODO: have this actually wait before calling the proc - SkASSERT(finishedProc); - finishedProc(finishedContext); - } + GrGpuFinishedContext finishedContext) override; + void addFinishedCallback(sk_sp<GrRefCntedCallback> finishedCallback); + + void prepareSurfacesForBackendAccessAndStateUpdates( + GrSurfaceProxy* proxies[], + int numProxies, + SkSurface::BackendSurfaceAccess access, + const GrBackendSurfaceMutableState* newState) override; bool onSubmitToGpu(bool syncCpu) override; diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.cpp index bd681f9058f..baac3d222f2 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.cpp @@ -8,13 +8,16 @@ #include "src/gpu/d3d/GrD3DOpsRenderPass.h" #include "src/gpu/GrContextPriv.h" -#include "src/gpu/GrFixedClip.h" +#include "src/gpu/GrOpFlushState.h" #include "src/gpu/GrProgramDesc.h" #include "src/gpu/GrRenderTargetPriv.h" #include "src/gpu/GrStencilSettings.h" +#include "src/gpu/d3d/GrD3DBuffer.h" #include "src/gpu/d3d/GrD3DGpu.h" #include "src/gpu/d3d/GrD3DPipelineState.h" #include "src/gpu/d3d/GrD3DPipelineStateBuilder.h" +#include "src/gpu/d3d/GrD3DRenderTarget.h" +#include "src/gpu/d3d/GrD3DTexture.h" GrD3DOpsRenderPass::GrD3DOpsRenderPass(GrD3DGpu* gpu) : fGpu(gpu) {} @@ -41,11 +44,33 @@ GrD3DOpsRenderPass::~GrD3DOpsRenderPass() {} GrGpu* GrD3DOpsRenderPass::gpu() { return fGpu; } +void GrD3DOpsRenderPass::onBegin() { + GrD3DRenderTarget* d3dRT = static_cast<GrD3DRenderTarget*>(fRenderTarget); + d3dRT->setResourceState(fGpu, D3D12_RESOURCE_STATE_RENDER_TARGET); + fGpu->currentCommandList()->setRenderTarget(d3dRT); + + if (GrLoadOp::kClear == fColorLoadOp) { + // Passing in nullptr for the rect clears the entire d3d RT. Is this correct? Does the load + // op respect the logical bounds of a RT? + fGpu->currentCommandList()->clearRenderTargetView(d3dRT, fClearColor, nullptr); + } + + if (auto stencil = d3dRT->renderTargetPriv().getStencilAttachment()) { + GrD3DStencilAttachment* d3dStencil = static_cast<GrD3DStencilAttachment*>(stencil); + d3dStencil->setResourceState(fGpu, D3D12_RESOURCE_STATE_DEPTH_WRITE); + if (fStencilLoadOp == GrLoadOp::kClear) { + fGpu->currentCommandList()->clearDepthStencilView(d3dStencil, 0, nullptr); + } + } +} + void set_stencil_ref(GrD3DGpu* gpu, const GrProgramInfo& info) { GrStencilSettings stencilSettings = info.nonGLStencilSettings(); if (!stencilSettings.isDisabled()) { unsigned int stencilRef = 0; if (stencilSettings.isTwoSided()) { + SkASSERT(stencilSettings.postOriginCCWFace(info.origin()).fRef == + stencilSettings.postOriginCWFace(info.origin()).fRef); stencilRef = stencilSettings.postOriginCCWFace(info.origin()).fRef; } else { stencilRef = stencilSettings.singleSidedFace().fRef; @@ -97,6 +122,7 @@ void set_primitive_topology(GrD3DGpu* gpu, const GrProgramInfo& info) { default: SkUNREACHABLE; } + gpu->currentCommandList()->setPrimitiveTopology(topology); } void set_scissor_rects(GrD3DGpu* gpu, const GrRenderTarget* renderTarget, GrSurfaceOrigin rtOrigin, @@ -139,13 +165,16 @@ bool GrD3DOpsRenderPass::onBindPipeline(const GrProgramInfo& info, const SkRect& fCurrentPipelineBounds.setEmpty(); } - sk_sp<GrD3DPipelineState> pipelineState = + fCurrentPipelineState = fGpu->resourceProvider().findOrCreateCompatiblePipelineState(fRenderTarget, info); - if (!pipelineState) { + if (!fCurrentPipelineState) { return false; } - fGpu->currentCommandList()->setPipelineState(std::move(pipelineState)); + fGpu->currentCommandList()->setGraphicsRootSignature(fCurrentPipelineState->rootSignature()); + fGpu->currentCommandList()->setPipelineState(fCurrentPipelineState); + + fCurrentPipelineState->setAndBindConstants(fGpu, fRenderTarget, info); set_stencil_ref(fGpu, info); set_blend_factor(fGpu, info); @@ -159,13 +188,128 @@ bool GrD3DOpsRenderPass::onBindPipeline(const GrProgramInfo& info, const SkRect& return true; } -void GrD3DOpsRenderPass::onBegin() { - if (GrLoadOp::kClear == fColorLoadOp) { - GrFixedClip clip; - fGpu->clear(clip, fClearColor, fRenderTarget); +void GrD3DOpsRenderPass::onSetScissorRect(const SkIRect& scissor) { + SkIRect combinedScissorRect; + if (!combinedScissorRect.intersect(fCurrentPipelineBounds, scissor)) { + combinedScissorRect = SkIRect::MakeEmpty(); + } + + set_scissor_rects(fGpu, fRenderTarget, fOrigin, combinedScissorRect); +} + +void update_resource_state(GrTexture* tex, GrRenderTarget* rt, GrD3DGpu* gpu) { + SkASSERT(!tex->isProtected() || (rt->isProtected() && gpu->protectedContext())); + GrD3DTexture* d3dTex = static_cast<GrD3DTexture*>(tex); + SkASSERT(d3dTex); + d3dTex->setResourceState(gpu, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); +} + +bool GrD3DOpsRenderPass::onBindTextures(const GrPrimitiveProcessor& primProc, + const GrSurfaceProxy* const primProcTextures[], + const GrPipeline& pipeline) { + SkASSERT(fCurrentPipelineState); + + // update textures to sampled resource state + for (int i = 0; i < primProc.numTextureSamplers(); ++i) { + update_resource_state(primProcTextures[i]->peekTexture(), fRenderTarget, fGpu); + } + GrFragmentProcessor::PipelineTextureSamplerRange textureSamplerRange(pipeline); + for (auto [sampler, fp] : textureSamplerRange) { + update_resource_state(sampler.peekTexture(), fRenderTarget, fGpu); + } + if (GrTexture* dstTexture = pipeline.peekDstTexture()) { + update_resource_state(dstTexture, fRenderTarget, fGpu); + } + + // TODO: possibly check for success once we start binding properly + fCurrentPipelineState->setAndBindTextures(fGpu, primProc, primProcTextures, pipeline); + + return true; +} + +void GrD3DOpsRenderPass::onBindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer, + const GrBuffer* vertexBuffer, + GrPrimitiveRestart primRestart) { + SkASSERT(GrPrimitiveRestart::kNo == primRestart); + SkASSERT(fCurrentPipelineState); + SkASSERT(!fGpu->caps()->usePrimitiveRestart()); // Ignore primitiveRestart parameter. + + GrD3DDirectCommandList* currCmdList = fGpu->currentCommandList(); + SkASSERT(currCmdList); + + // TODO: do we need a memory barrier here? + + fCurrentPipelineState->bindBuffers(fGpu, indexBuffer, instanceBuffer, vertexBuffer, + currCmdList); +} + +void GrD3DOpsRenderPass::onDrawInstanced(int instanceCount, int baseInstance, int vertexCount, + int baseVertex) { + SkASSERT(fCurrentPipelineState); + fGpu->currentCommandList()->drawInstanced(vertexCount, instanceCount, baseVertex, baseInstance); + fGpu->stats()->incNumDraws(); +} + +void GrD3DOpsRenderPass::onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, + int baseInstance, int baseVertex) { + SkASSERT(fCurrentPipelineState); + fGpu->currentCommandList()->drawIndexedInstanced(indexCount, instanceCount, baseIndex, + baseVertex, baseInstance); + fGpu->stats()->incNumDraws(); +} + +static D3D12_RECT scissor_to_d3d_clear_rect(const GrScissorState& scissor, + const GrSurface* surface, + GrSurfaceOrigin origin) { + D3D12_RECT clearRect; + // Flip rect if necessary + SkIRect d3dRect; + if (!scissor.enabled()) { + d3dRect.setXYWH(0, 0, surface->width(), surface->height()); + } else if (kBottomLeft_GrSurfaceOrigin != origin) { + d3dRect = scissor.rect(); + } else { + d3dRect.setLTRB(scissor.rect().fLeft, surface->height() - scissor.rect().fBottom, + scissor.rect().fRight, surface->height() - scissor.rect().fTop); } + clearRect.left = d3dRect.fLeft; + clearRect.right = d3dRect.fRight; + clearRect.top = d3dRect.fTop; + clearRect.bottom = d3dRect.fBottom; + return clearRect; +} + +void GrD3DOpsRenderPass::onClear(const GrScissorState& scissor, const SkPMColor4f& color) { + D3D12_RECT clearRect = scissor_to_d3d_clear_rect(scissor, fRenderTarget, fOrigin); + auto d3dRT = static_cast<GrD3DRenderTarget*>(fRenderTarget); + SkASSERT(d3dRT->grD3DResourceState()->getResourceState() == D3D12_RESOURCE_STATE_RENDER_TARGET); + fGpu->currentCommandList()->clearRenderTargetView(d3dRT, color, &clearRect); +} + +void GrD3DOpsRenderPass::onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) { + GrStencilAttachment* sb = fRenderTarget->renderTargetPriv().getStencilAttachment(); + // this should only be called internally when we know we have a + // stencil buffer. + SkASSERT(sb); + int stencilBitCount = sb->bits(); + + // The contract with the callers does not guarantee that we preserve all bits in the stencil + // during this clear. Thus we will clear the entire stencil to the desired value. + + uint8_t stencilColor = 0; + if (insideStencilMask) { + stencilColor = (1 << (stencilBitCount - 1)); + } + + D3D12_RECT clearRect = scissor_to_d3d_clear_rect(scissor, fRenderTarget, fOrigin); + + auto d3dStencil = static_cast<GrD3DStencilAttachment*>(sb); + fGpu->currentCommandList()->clearDepthStencilView(d3dStencil, stencilColor, &clearRect); } -void GrD3DOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& color) { - fGpu->clear(clip, color, fRenderTarget); +void GrD3DOpsRenderPass::inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) { + // If we ever start using copy command lists for doing uploads, then we'll need to make sure + // we submit our main command list before doing the copy here and then start a new main command + // list. + state->doUpload(upload); } diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.h index 058d046422d..ed540bd7ed2 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.h @@ -14,6 +14,7 @@ #include "include/private/GrTypesPriv.h" class GrD3DGpu; +class GrD3DPipelineState; class GrD3DOpsRenderPass : public GrOpsRenderPass { public: @@ -21,7 +22,7 @@ public: ~GrD3DOpsRenderPass() override; - void inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) override {} + void inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) override; void onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) override {} @@ -36,31 +37,39 @@ private: void onBegin() override; bool onBindPipeline(const GrProgramInfo&, const SkRect& drawBounds) override; - void onSetScissorRect(const SkIRect&) override {} + void onSetScissorRect(const SkIRect&) override; bool onBindTextures(const GrPrimitiveProcessor&, const GrSurfaceProxy* const primProcTextures[], - const GrPipeline&) override { - return true; - } + const GrPipeline&) override; void onBindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer, - const GrBuffer* vertexBuffer, GrPrimitiveRestart) override {} - void onDraw(int vertexCount, int baseVertex) override {} + const GrBuffer* vertexBuffer, GrPrimitiveRestart) override; + void onDraw(int vertexCount, int baseVertex) override { + this->onDrawInstanced(1, 0, vertexCount, baseVertex); + } void onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue, - uint16_t maxIndexValue, int baseVertex) override {} + uint16_t maxIndexValue, int baseVertex) override { + this->onDrawIndexedInstanced(indexCount, baseIndex, 1, 0, baseVertex); + } void onDrawInstanced(int instanceCount, int baseInstance, int vertexCount, - int baseVertex) override {} + int baseVertex) override; void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance, - int baseVertex) override {} + int baseVertex) override; + void onDrawIndirect(const GrBuffer*, size_t offset, int drawCount) override {} + void onDrawIndexedIndirect(const GrBuffer*, size_t offset, int drawCount) override {} - void onClear(const GrFixedClip&, const SkPMColor4f& color) override; + void onClear(const GrScissorState& scissor, const SkPMColor4f& color) override; - void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) override {} + void onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) override; GrD3DGpu* fGpu; + + sk_sp<GrD3DPipelineState> fCurrentPipelineState; + SkIRect fBounds; SkIRect fCurrentPipelineBounds; GrLoadOp fColorLoadOp; SkPMColor4f fClearColor; + GrLoadOp fStencilLoadOp; typedef GrOpsRenderPass INHERITED; }; diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.cpp index 21351763373..f7e3d6e26a4 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.cpp @@ -10,393 +10,183 @@ #include "include/private/SkTemplates.h" #include "src/gpu/GrProgramInfo.h" #include "src/gpu/GrStencilSettings.h" +#include "src/gpu/d3d/GrD3DBuffer.h" #include "src/gpu/d3d/GrD3DGpu.h" #include "src/gpu/d3d/GrD3DRootSignature.h" - -static DXGI_FORMAT attrib_type_to_format(GrVertexAttribType type) { - switch (type) { - case kFloat_GrVertexAttribType: - return DXGI_FORMAT_R32_FLOAT; - case kFloat2_GrVertexAttribType: - return DXGI_FORMAT_R32G32_FLOAT; - case kFloat3_GrVertexAttribType: - return DXGI_FORMAT_R32G32B32_FLOAT; - case kFloat4_GrVertexAttribType: - return DXGI_FORMAT_R32G32B32A32_FLOAT; - case kHalf_GrVertexAttribType: - return DXGI_FORMAT_R16_FLOAT; - case kHalf2_GrVertexAttribType: - return DXGI_FORMAT_R16G16_FLOAT; - case kHalf4_GrVertexAttribType: - return DXGI_FORMAT_R16G16B16A16_FLOAT; - case kInt2_GrVertexAttribType: - return DXGI_FORMAT_R32G32_SINT; - case kInt3_GrVertexAttribType: - return DXGI_FORMAT_R32G32B32_SINT; - case kInt4_GrVertexAttribType: - return DXGI_FORMAT_R32G32B32A32_SINT; - case kByte_GrVertexAttribType: - return DXGI_FORMAT_R8_SINT; - case kByte2_GrVertexAttribType: - return DXGI_FORMAT_R8G8_SINT; - case kByte4_GrVertexAttribType: - return DXGI_FORMAT_R8G8B8A8_SINT; - case kUByte_GrVertexAttribType: - return DXGI_FORMAT_R8_UINT; - case kUByte2_GrVertexAttribType: - return DXGI_FORMAT_R8G8_UINT; - case kUByte4_GrVertexAttribType: - return DXGI_FORMAT_R8G8B8A8_UINT; - case kUByte_norm_GrVertexAttribType: - return DXGI_FORMAT_R8_UNORM; - case kUByte4_norm_GrVertexAttribType: - return DXGI_FORMAT_R8G8B8A8_UNORM; - case kShort2_GrVertexAttribType: - return DXGI_FORMAT_R16G16_SINT; - case kShort4_GrVertexAttribType: - return DXGI_FORMAT_R16G16B16A16_SINT; - case kUShort2_GrVertexAttribType: - return DXGI_FORMAT_R16G16_UINT; - case kUShort2_norm_GrVertexAttribType: - return DXGI_FORMAT_R16G16_UNORM; - case kInt_GrVertexAttribType: - return DXGI_FORMAT_R32_SINT; - case kUint_GrVertexAttribType: - return DXGI_FORMAT_R32_UINT; - case kUShort_norm_GrVertexAttribType: - return DXGI_FORMAT_R16_UNORM; - case kUShort4_norm_GrVertexAttribType: - return DXGI_FORMAT_R16G16B16A16_UNORM; +#include "src/gpu/d3d/GrD3DTexture.h" +#include "src/gpu/glsl/GrGLSLFragmentProcessor.h" +#include "src/gpu/glsl/GrGLSLGeometryProcessor.h" +#include "src/gpu/glsl/GrGLSLXferProcessor.h" + +GrD3DPipelineState::GrD3DPipelineState( + gr_cp<ID3D12PipelineState> pipelineState, + sk_sp<GrD3DRootSignature> rootSignature, + const GrGLSLBuiltinUniformHandles& builtinUniformHandles, + const UniformInfoArray& uniforms, uint32_t uniformSize, + uint32_t numSamplers, + std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor, + std::unique_ptr<GrGLSLXferProcessor> xferProcessor, + std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors, + int fragmentProcessorCnt, + size_t vertexStride, + size_t instanceStride) + : fPipelineState(std::move(pipelineState)) + , fRootSignature(std::move(rootSignature)) + , fBuiltinUniformHandles(builtinUniformHandles) + , fGeometryProcessor(std::move(geometryProcessor)) + , fXferProcessor(std::move(xferProcessor)) + , fFragmentProcessors(std::move(fragmentProcessors)) + , fFragmentProcessorCnt(fragmentProcessorCnt) + , fDataManager(uniforms, uniformSize) + , fNumSamplers(numSamplers) + , fVertexStride(vertexStride) + , fInstanceStride(instanceStride) {} + +void GrD3DPipelineState::setAndBindConstants(GrD3DGpu* gpu, + const GrRenderTarget* renderTarget, + const GrProgramInfo& programInfo) { + this->setRenderTargetState(renderTarget, programInfo.origin()); + + GrFragmentProcessor::PipelineCoordTransformRange transformRange(programInfo.pipeline()); + fGeometryProcessor->setData(fDataManager, programInfo.primProc(), transformRange); + GrFragmentProcessor::CIter fpIter(programInfo.pipeline()); + GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt); + for (; fpIter && glslIter; ++fpIter, ++glslIter) { + glslIter->setData(fDataManager, *fpIter); } - SK_ABORT("Unknown vertex attrib type"); -} + SkASSERT(!fpIter && !glslIter); -static void setup_vertex_input_layout(const GrPrimitiveProcessor& primProc, - D3D12_INPUT_ELEMENT_DESC* inputElements) { - unsigned int slotNumber = 0; - unsigned int vertexSlot = 0; - unsigned int instanceSlot = 0; - if (primProc.hasVertexAttributes()) { - vertexSlot = slotNumber++; - } - if (primProc.hasInstanceAttributes()) { - instanceSlot = slotNumber++; - } + { + SkIPoint offset; + GrTexture* dstTexture = programInfo.pipeline().peekDstTexture(&offset); - unsigned int currentAttrib = 0; - unsigned int vertexAttributeOffset = 0; - - for (const auto& attrib : primProc.vertexAttributes()) { - // When using SPIRV-Cross it converts the location modifier in SPIRV to be - // TEXCOORD<N> where N is the location value for eveery vertext attribute - inputElements[currentAttrib] = {"TEXCOORD", currentAttrib, - attrib_type_to_format(attrib.cpuType()), - vertexSlot, vertexAttributeOffset, - D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}; - vertexAttributeOffset += attrib.sizeAlign4(); - currentAttrib++; + fXferProcessor->setData(fDataManager, programInfo.pipeline().getXferProcessor(), + dstTexture, offset); } - SkASSERT(vertexAttributeOffset == primProc.vertexStride()); - unsigned int instanceAttributeOffset = 0; - for (const auto& attrib : primProc.instanceAttributes()) { - // When using SPIRV-Cross it converts the location modifier in SPIRV to be - // TEXCOORD<N> where N is the location value for eveery vertext attribute - inputElements[currentAttrib] = {"TEXCOORD", currentAttrib, - attrib_type_to_format(attrib.cpuType()), - instanceSlot, instanceAttributeOffset, - D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}; - instanceAttributeOffset += attrib.sizeAlign4(); - currentAttrib++; - } - SkASSERT(instanceAttributeOffset == primProc.instanceStride()); + D3D12_GPU_VIRTUAL_ADDRESS constantsAddress = fDataManager.uploadConstants(gpu); + gpu->currentCommandList()->setGraphicsRootConstantBufferView( + (unsigned int)(GrD3DRootSignature::ParamIndex::kConstantBufferView), + constantsAddress); } -static D3D12_BLEND blend_coeff_to_d3d_blend(GrBlendCoeff coeff) { - switch (coeff) { - case kZero_GrBlendCoeff: - return D3D12_BLEND_ZERO; - case kOne_GrBlendCoeff: - return D3D12_BLEND_ONE; - case kSC_GrBlendCoeff: - return D3D12_BLEND_SRC_COLOR; - case kISC_GrBlendCoeff: - return D3D12_BLEND_INV_SRC_COLOR; - case kDC_GrBlendCoeff: - return D3D12_BLEND_DEST_COLOR; - case kIDC_GrBlendCoeff: - return D3D12_BLEND_INV_DEST_COLOR; - case kSA_GrBlendCoeff: - return D3D12_BLEND_SRC_ALPHA; - case kISA_GrBlendCoeff: - return D3D12_BLEND_INV_SRC_ALPHA; - case kDA_GrBlendCoeff: - return D3D12_BLEND_DEST_ALPHA; - case kIDA_GrBlendCoeff: - return D3D12_BLEND_INV_DEST_ALPHA; - case kConstC_GrBlendCoeff: - return D3D12_BLEND_BLEND_FACTOR; - case kIConstC_GrBlendCoeff: - return D3D12_BLEND_INV_BLEND_FACTOR; - case kS2C_GrBlendCoeff: - return D3D12_BLEND_SRC1_COLOR; - case kIS2C_GrBlendCoeff: - return D3D12_BLEND_INV_SRC1_COLOR; - case kS2A_GrBlendCoeff: - return D3D12_BLEND_SRC1_ALPHA; - case kIS2A_GrBlendCoeff: - return D3D12_BLEND_INV_SRC1_ALPHA; - case kIllegal_GrBlendCoeff: - return D3D12_BLEND_ZERO; +void GrD3DPipelineState::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin) { + // Load the RT height uniform if it is needed to y-flip gl_FragCoord. + if (fBuiltinUniformHandles.fRTHeightUni.isValid() && + fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) { + fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height())); } - SkUNREACHABLE; -} -static D3D12_BLEND blend_coeff_to_d3d_blend_for_alpha(GrBlendCoeff coeff) { - switch (coeff) { - // Force all srcColor used in alpha slot to alpha version. - case kSC_GrBlendCoeff: - return D3D12_BLEND_SRC_ALPHA; - case kISC_GrBlendCoeff: - return D3D12_BLEND_INV_SRC_ALPHA; - case kDC_GrBlendCoeff: - return D3D12_BLEND_DEST_ALPHA; - case kIDC_GrBlendCoeff: - return D3D12_BLEND_INV_DEST_ALPHA; - case kS2C_GrBlendCoeff: - return D3D12_BLEND_SRC1_ALPHA; - case kIS2C_GrBlendCoeff: - return D3D12_BLEND_INV_SRC1_ALPHA; - - default: - return blend_coeff_to_d3d_blend(coeff); - } -} - - -static D3D12_BLEND_OP blend_equation_to_d3d_op(GrBlendEquation equation) { - switch (equation) { - case kAdd_GrBlendEquation: - return D3D12_BLEND_OP_ADD; - case kSubtract_GrBlendEquation: - return D3D12_BLEND_OP_SUBTRACT; - case kReverseSubtract_GrBlendEquation: - return D3D12_BLEND_OP_REV_SUBTRACT; - default: - SkUNREACHABLE; + // set RT adjustment + SkISize dimensions = rt->dimensions(); + SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid()); + if (fRenderTargetState.fRenderTargetOrigin != origin || + fRenderTargetState.fRenderTargetSize != dimensions) { + fRenderTargetState.fRenderTargetSize = dimensions; + fRenderTargetState.fRenderTargetOrigin = origin; + + float rtAdjustmentVec[4]; + fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec); + fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec); } } -static void fill_in_blend_state(const GrPipeline& pipeline, D3D12_BLEND_DESC* blendDesc) { - blendDesc->AlphaToCoverageEnable = false; - blendDesc->IndependentBlendEnable = false; - - const GrXferProcessor::BlendInfo& blendInfo = pipeline.getXferProcessor().getBlendInfo(); - - GrBlendEquation equation = blendInfo.fEquation; - GrBlendCoeff srcCoeff = blendInfo.fSrcBlend; - GrBlendCoeff dstCoeff = blendInfo.fDstBlend; - bool blendOff = GrBlendShouldDisable(equation, srcCoeff, dstCoeff); - - auto& rtBlend = blendDesc->RenderTarget[0]; - rtBlend.BlendEnable = !blendOff; - if (!blendOff) { - rtBlend.SrcBlend = blend_coeff_to_d3d_blend(srcCoeff); - rtBlend.DestBlend = blend_coeff_to_d3d_blend(dstCoeff); - rtBlend.BlendOp = blend_equation_to_d3d_op(equation); - rtBlend.SrcBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(srcCoeff); - rtBlend.DestBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(dstCoeff); - rtBlend.BlendOpAlpha = blend_equation_to_d3d_op(equation); +void GrD3DPipelineState::setAndBindTextures(GrD3DGpu* gpu, const GrPrimitiveProcessor& primProc, + const GrSurfaceProxy* const primProcTextures[], + const GrPipeline& pipeline) { + SkASSERT(primProcTextures || !primProc.numTextureSamplers()); + + SkAutoSTMalloc<8, D3D12_CPU_DESCRIPTOR_HANDLE> shaderResourceViews(fNumSamplers); + SkAutoSTMalloc<8, D3D12_CPU_DESCRIPTOR_HANDLE> samplers(fNumSamplers); + SkAutoSTMalloc<8, unsigned int> rangeSizes(fNumSamplers); + unsigned int currTextureBinding = 0; + + for (int i = 0; i < primProc.numTextureSamplers(); ++i) { + SkASSERT(primProcTextures[i]->asTextureProxy()); + const auto& sampler = primProc.textureSampler(i); + auto texture = static_cast<GrD3DTexture*>(primProcTextures[i]->peekTexture()); + shaderResourceViews[currTextureBinding] = texture->shaderResourceView(); + samplers[currTextureBinding] = + gpu->resourceProvider().findOrCreateCompatibleSampler(sampler.samplerState()); + gpu->currentCommandList()->addSampledTextureRef(texture); + rangeSizes[currTextureBinding++] = 1; } - if (!blendInfo.fWriteColor) { - rtBlend.RenderTargetWriteMask = 0; - } else { - rtBlend.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + GrFragmentProcessor::CIter fpIter(pipeline); + GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt); + for (; fpIter && glslIter; ++fpIter, ++glslIter) { + for (int i = 0; i < fpIter->numTextureSamplers(); ++i) { + const auto& sampler = fpIter->textureSampler(i); + auto texture = static_cast<GrD3DTexture*>(sampler.peekTexture()); + shaderResourceViews[currTextureBinding] = texture->shaderResourceView(); + samplers[currTextureBinding] = + gpu->resourceProvider().findOrCreateCompatibleSampler(sampler.samplerState()); + gpu->currentCommandList()->addSampledTextureRef(texture); + rangeSizes[currTextureBinding++] = 1; + } } -} - -static void fill_in_rasterizer_state(const GrPipeline& pipeline, const GrCaps* caps, - D3D12_RASTERIZER_DESC* rasterizer) { - rasterizer->FillMode = (caps->wireframeMode() || pipeline.isWireframe()) ? - D3D12_FILL_MODE_WIREFRAME : D3D12_FILL_MODE_SOLID; - rasterizer->CullMode = D3D12_CULL_MODE_NONE; - rasterizer->FrontCounterClockwise = true; - rasterizer->DepthBias = 0; - rasterizer->DepthBiasClamp = 0.0f; - rasterizer->SlopeScaledDepthBias = 0.0f; - rasterizer->DepthClipEnable = false; - rasterizer->MultisampleEnable = pipeline.isHWAntialiasState(); - rasterizer->AntialiasedLineEnable = false; - rasterizer->ForcedSampleCount = 0; - rasterizer->ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; -} - -static D3D12_STENCIL_OP stencil_op_to_d3d_op(GrStencilOp op) { - switch (op) { - case GrStencilOp::kKeep: - return D3D12_STENCIL_OP_KEEP; - case GrStencilOp::kZero: - return D3D12_STENCIL_OP_ZERO; - case GrStencilOp::kReplace: - return D3D12_STENCIL_OP_REPLACE; - case GrStencilOp::kInvert: - return D3D12_STENCIL_OP_INVERT; - case GrStencilOp::kIncWrap: - return D3D12_STENCIL_OP_INCR; - case GrStencilOp::kDecWrap: - return D3D12_STENCIL_OP_DECR; - case GrStencilOp::kIncClamp: - return D3D12_STENCIL_OP_INCR_SAT; - case GrStencilOp::kDecClamp: - return D3D12_STENCIL_OP_DECR_SAT; + SkASSERT(!fpIter && !glslIter); + + if (GrTexture* dstTexture = pipeline.peekDstTexture()) { + auto texture = static_cast<GrD3DTexture*>(dstTexture); + shaderResourceViews[currTextureBinding] = texture->shaderResourceView(); + samplers[currTextureBinding] = gpu->resourceProvider().findOrCreateCompatibleSampler( + GrSamplerState::Filter::kNearest); + gpu->currentCommandList()->addSampledTextureRef(texture); + rangeSizes[currTextureBinding++] = 1; } - SkUNREACHABLE; -} -static D3D12_COMPARISON_FUNC stencil_test_to_d3d_func(GrStencilTest test) { - switch (test) { - case GrStencilTest::kAlways: - return D3D12_COMPARISON_FUNC_ALWAYS; - case GrStencilTest::kNever: - return D3D12_COMPARISON_FUNC_NEVER; - case GrStencilTest::kGreater: - return D3D12_COMPARISON_FUNC_GREATER; - case GrStencilTest::kGEqual: - return D3D12_COMPARISON_FUNC_GREATER_EQUAL; - case GrStencilTest::kLess: - return D3D12_COMPARISON_FUNC_LESS; - case GrStencilTest::kLEqual: - return D3D12_COMPARISON_FUNC_LESS_EQUAL; - case GrStencilTest::kEqual: - return D3D12_COMPARISON_FUNC_EQUAL; - case GrStencilTest::kNotEqual: - return D3D12_COMPARISON_FUNC_NOT_EQUAL; + SkASSERT(fNumSamplers == currTextureBinding); + + // fill in descriptor tables and bind to root signature + if (fNumSamplers > 0) { + // set up and bind shader resource view table + std::unique_ptr<GrD3DDescriptorTable> srvTable = + gpu->resourceProvider().createShaderOrConstantResourceTable(fNumSamplers); + gpu->device()->CopyDescriptors(1, srvTable->baseCpuDescriptorPtr(), &fNumSamplers, + fNumSamplers, shaderResourceViews.get(), rangeSizes.get(), + srvTable->type()); + gpu->currentCommandList()->setGraphicsRootDescriptorTable( + static_cast<unsigned int>(GrD3DRootSignature::ParamIndex::kTextureDescriptorTable), + srvTable->baseGpuDescriptor()); + + // set up and bind sampler table + std::unique_ptr<GrD3DDescriptorTable> samplerTable = + gpu->resourceProvider().createSamplerTable(fNumSamplers); + gpu->device()->CopyDescriptors(1, samplerTable->baseCpuDescriptorPtr(), &fNumSamplers, + fNumSamplers, samplers.get(), rangeSizes.get(), + samplerTable->type()); + gpu->currentCommandList()->setGraphicsRootDescriptorTable( + static_cast<unsigned int>(GrD3DRootSignature::ParamIndex::kSamplerDescriptorTable), + samplerTable->baseGpuDescriptor()); } - SkUNREACHABLE; -} - -static void setup_stencilop_desc(D3D12_DEPTH_STENCILOP_DESC* desc, - const GrStencilSettings::Face& stencilFace) { - desc->StencilFailOp = stencil_op_to_d3d_op(stencilFace.fFailOp); - desc->StencilDepthFailOp = desc->StencilFailOp; - desc->StencilPassOp = stencil_op_to_d3d_op(stencilFace.fPassOp); - desc->StencilFunc = stencil_test_to_d3d_func(stencilFace.fTest); } -static void fill_in_depth_stencil_state(const GrProgramInfo& programInfo, - D3D12_DEPTH_STENCIL_DESC* dsDesc) { - GrStencilSettings stencilSettings = programInfo.nonGLStencilSettings(); - GrSurfaceOrigin origin = programInfo.origin(); - - dsDesc->DepthEnable = false; - dsDesc->DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; - dsDesc->DepthFunc = D3D12_COMPARISON_FUNC_NEVER; - dsDesc->StencilEnable = !stencilSettings.isDisabled(); - if (!stencilSettings.isDisabled()) { - if (stencilSettings.isTwoSided()) { - const auto& frontFace = stencilSettings.postOriginCCWFace(origin); - const auto& backFace = stencilSettings.postOriginCCWFace(origin); - - SkASSERT(frontFace.fTestMask == backFace.fTestMask); - SkASSERT(frontFace.fWriteMask == backFace.fWriteMask); - dsDesc->StencilReadMask = frontFace.fTestMask; - dsDesc->StencilWriteMask = frontFace.fWriteMask; - - setup_stencilop_desc(&dsDesc->FrontFace, frontFace); - setup_stencilop_desc(&dsDesc->BackFace, backFace); - } else { - dsDesc->StencilReadMask = stencilSettings.singleSidedFace().fTestMask; - dsDesc->StencilWriteMask = stencilSettings.singleSidedFace().fTestMask; - setup_stencilop_desc(&dsDesc->FrontFace, stencilSettings.singleSidedFace()); - dsDesc->BackFace = dsDesc->FrontFace; +void GrD3DPipelineState::bindBuffers(GrD3DGpu* gpu, const GrBuffer* indexBuffer, + const GrBuffer* instanceBuffer, const GrBuffer* vertexBuffer, + GrD3DDirectCommandList* commandList) { + // Here our vertex and instance inputs need to match the same 0-based bindings they were + // assigned in the PipelineState. That is, vertex first (if any) followed by instance. + if (auto* d3dVertexBuffer = static_cast<const GrD3DBuffer*>(vertexBuffer)) { + SkASSERT(!d3dVertexBuffer->isCpuBuffer()); + SkASSERT(!d3dVertexBuffer->isMapped()); + const_cast<GrD3DBuffer*>(d3dVertexBuffer)->setResourceState( + gpu, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); + auto* d3dInstanceBuffer = static_cast<const GrD3DBuffer*>(instanceBuffer); + if (d3dInstanceBuffer) { + SkASSERT(!d3dInstanceBuffer->isCpuBuffer()); + SkASSERT(!d3dInstanceBuffer->isMapped()); + const_cast<GrD3DBuffer*>(d3dInstanceBuffer)->setResourceState( + gpu, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); } + commandList->setVertexBuffers(0, d3dVertexBuffer, fVertexStride, + d3dInstanceBuffer, fInstanceStride); } -} - -static D3D12_PRIMITIVE_TOPOLOGY_TYPE gr_primitive_type_to_d3d(GrPrimitiveType primitiveType) { - switch (primitiveType) { - case GrPrimitiveType::kTriangles: - case GrPrimitiveType::kTriangleStrip: //fall through - return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - case GrPrimitiveType::kPoints: - return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; - case GrPrimitiveType::kLines: // fall through - case GrPrimitiveType::kLineStrip: - return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; - case GrPrimitiveType::kPatches: // fall through, unsupported - case GrPrimitiveType::kPath: // fall through, unsupported - default: - SkUNREACHABLE; + if (auto* d3dIndexBuffer = static_cast<const GrD3DBuffer*>(indexBuffer)) { + SkASSERT(!d3dIndexBuffer->isCpuBuffer()); + SkASSERT(!d3dIndexBuffer->isMapped()); + const_cast<GrD3DBuffer*>(d3dIndexBuffer)->setResourceState( + gpu, D3D12_RESOURCE_STATE_INDEX_BUFFER); + commandList->setIndexBuffer(d3dIndexBuffer); } } - -sk_sp<GrD3DPipelineState> GrD3DPipelineState::Make(GrD3DGpu* gpu, - const GrProgramInfo& programInfo, - sk_sp<GrD3DRootSignature> rootSig, - gr_cp<ID3DBlob> vertexShader, - gr_cp<ID3DBlob> geometryShader, - gr_cp<ID3DBlob> pixelShader, - DXGI_FORMAT renderTargetFormat, - DXGI_FORMAT depthStencilFormat, - unsigned int sampleQualityLevel) { - D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; - - psoDesc.pRootSignature = rootSig->rootSignature(); - - psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()), - vertexShader->GetBufferSize() }; - psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()), - pixelShader->GetBufferSize() }; - - if (geometryShader.get()) { - psoDesc.GS = { reinterpret_cast<UINT8*>(geometryShader->GetBufferPointer()), - geometryShader->GetBufferSize() }; - } - - psoDesc.StreamOutput = {nullptr, 0, nullptr, 0, 0}; - - fill_in_blend_state(programInfo.pipeline(), &psoDesc.BlendState); - psoDesc.SampleMask = UINT_MAX; - - fill_in_rasterizer_state(programInfo.pipeline(), gpu->caps(), &psoDesc.RasterizerState); - - fill_in_depth_stencil_state(programInfo, &psoDesc.DepthStencilState); - - unsigned int totalAttributeCnt = programInfo.primProc().numVertexAttributes() + - programInfo.primProc().numInstanceAttributes(); - SkAutoSTArray<4, D3D12_INPUT_ELEMENT_DESC> inputElements(totalAttributeCnt); - setup_vertex_input_layout(programInfo.primProc(), inputElements.get()); - - psoDesc.InputLayout = { inputElements.get(), totalAttributeCnt }; - - psoDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; - - // This is for geometry or hull shader primitives - psoDesc.PrimitiveTopologyType = gr_primitive_type_to_d3d(programInfo.primitiveType()); - - psoDesc.NumRenderTargets = 1; - - psoDesc.RTVFormats[0] = renderTargetFormat; - - psoDesc.DSVFormat = depthStencilFormat; - - unsigned int numRasterSamples = programInfo.numRasterSamples(); - psoDesc.SampleDesc = {numRasterSamples, sampleQualityLevel}; - - // Only used for multi-adapter systems. - psoDesc.NodeMask = 0; - - psoDesc.CachedPSO = {nullptr, 0}; - psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; - - gr_cp<ID3D12PipelineState> pipelineState; - SkDEBUGCODE(HRESULT hr = )gpu->device()->CreateGraphicsPipelineState( - &psoDesc, IID_PPV_ARGS(&pipelineState)); - SkASSERT(SUCCEEDED(hr)); - - return sk_sp<GrD3DPipelineState>(new GrD3DPipelineState(std::move(pipelineState))); -} - -GrD3DPipelineState::GrD3DPipelineState(gr_cp<ID3D12PipelineState> pipelineState) - : fPipelineState(std::move(pipelineState)) {} diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.h index b6eb50a8d24..0925571d950 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.h @@ -12,21 +12,30 @@ #include "include/gpu/GrTypes.h" #include "include/gpu/d3d/GrD3DTypes.h" #include "src/gpu/GrManagedResource.h" +#include "src/gpu/d3d/GrD3DPipelineStateDataManager.h" +#include "src/gpu/glsl/GrGLSLProgramBuilder.h" +class GrD3DDirectCommandList; class GrD3DGpu; class GrD3DRootSignature; class GrProgramInfo; class GrD3DPipelineState : public GrManagedResource { public: - static sk_sp<GrD3DPipelineState> Make(GrD3DGpu* gpu, const GrProgramInfo&, - sk_sp<GrD3DRootSignature> rootSig, - gr_cp<ID3DBlob> vertexShader, - gr_cp<ID3DBlob> geometryShader, - gr_cp<ID3DBlob> pixelShader, - DXGI_FORMAT renderTargetFormat, - DXGI_FORMAT depthStencilFormat, - unsigned int sampleQualityLevel); + using UniformInfoArray = GrD3DPipelineStateDataManager::UniformInfoArray; + + GrD3DPipelineState(gr_cp<ID3D12PipelineState> pipelineState, + sk_sp<GrD3DRootSignature> rootSignature, + const GrGLSLBuiltinUniformHandles& builtinUniformHandles, + const UniformInfoArray& uniforms, + uint32_t uniformSize, + uint32_t numSamplers, + std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor, + std::unique_ptr<GrGLSLXferProcessor> xferProcessor, + std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragProcessors, + int fragmentProcessorCnt, + size_t vertexStride, + size_t instanceStride); #ifdef SK_TRACE_MANAGED_RESOURCES /** Output a human-readable dump of this resource's information @@ -41,12 +50,81 @@ public: void freeGPUData() const override {} ID3D12PipelineState* pipelineState() const { return fPipelineState.get(); } + const sk_sp<GrD3DRootSignature>& rootSignature() const { return fRootSignature; } + + void setAndBindConstants(GrD3DGpu*, const GrRenderTarget*, const GrProgramInfo&); + + void setAndBindTextures(GrD3DGpu*, const GrPrimitiveProcessor& primProc, + const GrSurfaceProxy* const primProcTextures[], + const GrPipeline& pipeline); + + void bindBuffers(GrD3DGpu*, const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer, + const GrBuffer* vertexBuffer, GrD3DDirectCommandList* commandList); + + // We can only cache non dirty uniform values until we submit a command list. After that, the + // next frame will get a completely different uniform buffer and/or offset into the buffer. Thus + // we need a way to mark them all as dirty during submit. + void markUniformsDirty() { fDataManager.markDirty(); } private: - GrD3DPipelineState(gr_cp<ID3D12PipelineState> pipelineState); + /** + * We use the RT's size and origin to adjust from Skia device space to d3d normalized device + * space and to make device space positions have the correct origin for processors that require + * them. + */ + struct RenderTargetState { + SkISize fRenderTargetSize; + GrSurfaceOrigin fRenderTargetOrigin; + + RenderTargetState() { this->invalidate(); } + void invalidate() { + fRenderTargetSize.fWidth = -1; + fRenderTargetSize.fHeight = -1; + fRenderTargetOrigin = (GrSurfaceOrigin)-1; + } + + /** + * Gets a float4 that adjusts the position from Skia device coords to D3D's normalized device + * coords. Assuming the transformed position, pos, is a homogeneous float3, the vec, v, is + * applied as such: + * pos.x = dot(v.xy, pos.xz) + * pos.y = dot(v.zw, pos.yz) + */ + void getRTAdjustmentVec(float* destVec) { + destVec[0] = 2.f / fRenderTargetSize.fWidth; + destVec[1] = -1.f; + // D3D's NDC space is flipped from Vulkan and Metal + if (kTopLeft_GrSurfaceOrigin == fRenderTargetOrigin) { + destVec[2] = -2.f / fRenderTargetSize.fHeight; + destVec[3] = 1.f; + } else { + destVec[2] = 2.f / fRenderTargetSize.fHeight; + destVec[3] = -1.f; + } + } + }; + + // Helper for setData() that sets the view matrix and loads the render target height uniform + void setRenderTargetState(const GrRenderTarget*, GrSurfaceOrigin); gr_cp<ID3D12PipelineState> fPipelineState; + sk_sp<GrD3DRootSignature> fRootSignature; + + // Tracks the current render target uniforms stored in the vertex buffer. + RenderTargetState fRenderTargetState; + GrGLSLBuiltinUniformHandles fBuiltinUniformHandles; + + // Processors in the GrD3DPipelineState + std::unique_ptr<GrGLSLPrimitiveProcessor> fGeometryProcessor; + std::unique_ptr<GrGLSLXferProcessor> fXferProcessor; + std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fFragmentProcessors; + int fFragmentProcessorCnt; + + GrD3DPipelineStateDataManager fDataManager; + unsigned int fNumSamplers; + size_t fVertexStride; + size_t fInstanceStride; }; #endif diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp index f03858ec832..5c2b91f509d 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp @@ -14,6 +14,7 @@ #include "src/core/SkTraceEvent.h" #include "src/gpu/GrAutoLocaleSetter.h" #include "src/gpu/GrContextPriv.h" +#include "src/gpu/GrPersistentCacheUtils.h" #include "src/gpu/GrShaderCaps.h" #include "src/gpu/GrShaderUtils.h" #include "src/gpu/GrStencilSettings.h" @@ -24,8 +25,6 @@ #include <d3dcompiler.h> -typedef size_t shader_size; - sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::MakePipelineState( GrD3DGpu* gpu, GrRenderTarget* renderTarget, @@ -66,27 +65,9 @@ void GrD3DPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outp outputColor.addLayoutQualifier("location = 0, index = 1"); } -void GrD3DPipelineStateBuilder::compileD3DProgram(SkSL::Program::Kind kind, - const SkSL::String& sksl, - const SkSL::Program::Settings& settings, - ID3DBlob** shader, - SkSL::Program::Inputs* outInputs) { - auto errorHandler = fGpu->getContext()->priv().getShaderErrorHandler(); - std::unique_ptr<SkSL::Program> program = fGpu->shaderCompiler()->convertProgram( - kind, sksl, settings); - if (!program) { - errorHandler->compileError(sksl.c_str(), - fGpu->shaderCompiler()->errorText().c_str()); - return; - } - *outInputs = program->fInputs; - SkSL::String outHLSL; - if (!fGpu->shaderCompiler()->toHLSL(*program, &outHLSL)) { - errorHandler->compileError(sksl.c_str(), - fGpu->shaderCompiler()->errorText().c_str()); - return; - } - +static gr_cp<ID3DBlob> GrCompileHLSLShader(GrD3DGpu* gpu, + const SkSL::String& hlsl, + SkSL::Program::Kind kind) { const char* compileTarget = nullptr; switch (kind) { case SkSL::Program::kVertex_Kind: @@ -110,16 +91,452 @@ void GrD3DPipelineStateBuilder::compileD3DProgram(SkSL::Program::Kind kind, // SPRIV-cross does matrix multiplication expecting row major matrices compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR; - // TODO: D3D Static Function + gr_cp<ID3DBlob> shader; gr_cp<ID3DBlob> errors; - HRESULT hr = D3DCompile(outHLSL.c_str(), outHLSL.length(), nullptr, nullptr, nullptr, "main", - compileTarget, compileFlags, 0, shader, &errors); + HRESULT hr = D3DCompile(hlsl.c_str(), hlsl.length(), nullptr, nullptr, nullptr, "main", + compileTarget, compileFlags, 0, &shader, &errors); if (!SUCCEEDED(hr)) { - errorHandler->compileError(outHLSL.c_str(), - reinterpret_cast<char*>(errors->GetBufferPointer())); + gpu->getContext()->priv().getShaderErrorHandler()->compileError( + hlsl.c_str(), reinterpret_cast<char*>(errors->GetBufferPointer())); + } + return shader; +} + +bool GrD3DPipelineStateBuilder::loadHLSLFromCache(SkReadBuffer* reader, gr_cp<ID3DBlob> shaders[]) { + + SkSL::String hlsl[kGrShaderTypeCount]; + SkSL::Program::Inputs inputs[kGrShaderTypeCount]; + + if (!GrPersistentCacheUtils::UnpackCachedShaders(reader, hlsl, inputs, kGrShaderTypeCount)) { + return false; } + + auto compile = [&](SkSL::Program::Kind kind, GrShaderType shaderType) { + if (inputs[shaderType].fRTHeight) { + this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); + } + shaders[shaderType] = GrCompileHLSLShader(fGpu, hlsl[shaderType], kind); + return shaders[shaderType].get(); + }; + + return compile(SkSL::Program::kVertex_Kind, kVertex_GrShaderType) && + compile(SkSL::Program::kFragment_Kind, kFragment_GrShaderType) && + (hlsl[kGeometry_GrShaderType].empty() || + compile(SkSL::Program::kGeometry_Kind, kGeometry_GrShaderType)); } +gr_cp<ID3DBlob> GrD3DPipelineStateBuilder::compileD3DProgram( + SkSL::Program::Kind kind, + const SkSL::String& sksl, + const SkSL::Program::Settings& settings, + SkSL::Program::Inputs* outInputs, + SkSL::String* outHLSL) { + auto errorHandler = fGpu->getContext()->priv().getShaderErrorHandler(); + std::unique_ptr<SkSL::Program> program = fGpu->shaderCompiler()->convertProgram( + kind, sksl, settings); + if (!program) { + errorHandler->compileError(sksl.c_str(), + fGpu->shaderCompiler()->errorText().c_str()); + return gr_cp<ID3DBlob>(); + } + *outInputs = program->fInputs; + if (!fGpu->shaderCompiler()->toHLSL(*program, outHLSL)) { + errorHandler->compileError(sksl.c_str(), + fGpu->shaderCompiler()->errorText().c_str()); + return gr_cp<ID3DBlob>(); + } + + if (program->fInputs.fRTHeight) { + this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); + } + + return GrCompileHLSLShader(fGpu, *outHLSL, kind); +} + +static DXGI_FORMAT attrib_type_to_format(GrVertexAttribType type) { + switch (type) { + case kFloat_GrVertexAttribType: + return DXGI_FORMAT_R32_FLOAT; + case kFloat2_GrVertexAttribType: + return DXGI_FORMAT_R32G32_FLOAT; + case kFloat3_GrVertexAttribType: + return DXGI_FORMAT_R32G32B32_FLOAT; + case kFloat4_GrVertexAttribType: + return DXGI_FORMAT_R32G32B32A32_FLOAT; + case kHalf_GrVertexAttribType: + return DXGI_FORMAT_R16_FLOAT; + case kHalf2_GrVertexAttribType: + return DXGI_FORMAT_R16G16_FLOAT; + case kHalf4_GrVertexAttribType: + return DXGI_FORMAT_R16G16B16A16_FLOAT; + case kInt2_GrVertexAttribType: + return DXGI_FORMAT_R32G32_SINT; + case kInt3_GrVertexAttribType: + return DXGI_FORMAT_R32G32B32_SINT; + case kInt4_GrVertexAttribType: + return DXGI_FORMAT_R32G32B32A32_SINT; + case kByte_GrVertexAttribType: + return DXGI_FORMAT_R8_SINT; + case kByte2_GrVertexAttribType: + return DXGI_FORMAT_R8G8_SINT; + case kByte4_GrVertexAttribType: + return DXGI_FORMAT_R8G8B8A8_SINT; + case kUByte_GrVertexAttribType: + return DXGI_FORMAT_R8_UINT; + case kUByte2_GrVertexAttribType: + return DXGI_FORMAT_R8G8_UINT; + case kUByte4_GrVertexAttribType: + return DXGI_FORMAT_R8G8B8A8_UINT; + case kUByte_norm_GrVertexAttribType: + return DXGI_FORMAT_R8_UNORM; + case kUByte4_norm_GrVertexAttribType: + return DXGI_FORMAT_R8G8B8A8_UNORM; + case kShort2_GrVertexAttribType: + return DXGI_FORMAT_R16G16_SINT; + case kShort4_GrVertexAttribType: + return DXGI_FORMAT_R16G16B16A16_SINT; + case kUShort2_GrVertexAttribType: + return DXGI_FORMAT_R16G16_UINT; + case kUShort2_norm_GrVertexAttribType: + return DXGI_FORMAT_R16G16_UNORM; + case kInt_GrVertexAttribType: + return DXGI_FORMAT_R32_SINT; + case kUint_GrVertexAttribType: + return DXGI_FORMAT_R32_UINT; + case kUShort_norm_GrVertexAttribType: + return DXGI_FORMAT_R16_UNORM; + case kUShort4_norm_GrVertexAttribType: + return DXGI_FORMAT_R16G16B16A16_UNORM; + } + SK_ABORT("Unknown vertex attrib type"); +} + +static void setup_vertex_input_layout(const GrPrimitiveProcessor& primProc, + D3D12_INPUT_ELEMENT_DESC* inputElements) { + unsigned int slotNumber = 0; + unsigned int vertexSlot = 0; + unsigned int instanceSlot = 0; + if (primProc.hasVertexAttributes()) { + vertexSlot = slotNumber++; + } + if (primProc.hasInstanceAttributes()) { + instanceSlot = slotNumber++; + } + + unsigned int currentAttrib = 0; + unsigned int vertexAttributeOffset = 0; + + for (const auto& attrib : primProc.vertexAttributes()) { + // When using SPIRV-Cross it converts the location modifier in SPIRV to be + // TEXCOORD<N> where N is the location value for eveery vertext attribute + inputElements[currentAttrib] = { "TEXCOORD", currentAttrib, + attrib_type_to_format(attrib.cpuType()), + vertexSlot, vertexAttributeOffset, + D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }; + vertexAttributeOffset += attrib.sizeAlign4(); + currentAttrib++; + } + SkASSERT(vertexAttributeOffset == primProc.vertexStride()); + + unsigned int instanceAttributeOffset = 0; + for (const auto& attrib : primProc.instanceAttributes()) { + // When using SPIRV-Cross it converts the location modifier in SPIRV to be + // TEXCOORD<N> where N is the location value for eveery vertext attribute + inputElements[currentAttrib] = { "TEXCOORD", currentAttrib, + attrib_type_to_format(attrib.cpuType()), + instanceSlot, instanceAttributeOffset, + D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 }; + instanceAttributeOffset += attrib.sizeAlign4(); + currentAttrib++; + } + SkASSERT(instanceAttributeOffset == primProc.instanceStride()); +} + +static D3D12_BLEND blend_coeff_to_d3d_blend(GrBlendCoeff coeff) { + switch (coeff) { + case kZero_GrBlendCoeff: + return D3D12_BLEND_ZERO; + case kOne_GrBlendCoeff: + return D3D12_BLEND_ONE; + case kSC_GrBlendCoeff: + return D3D12_BLEND_SRC_COLOR; + case kISC_GrBlendCoeff: + return D3D12_BLEND_INV_SRC_COLOR; + case kDC_GrBlendCoeff: + return D3D12_BLEND_DEST_COLOR; + case kIDC_GrBlendCoeff: + return D3D12_BLEND_INV_DEST_COLOR; + case kSA_GrBlendCoeff: + return D3D12_BLEND_SRC_ALPHA; + case kISA_GrBlendCoeff: + return D3D12_BLEND_INV_SRC_ALPHA; + case kDA_GrBlendCoeff: + return D3D12_BLEND_DEST_ALPHA; + case kIDA_GrBlendCoeff: + return D3D12_BLEND_INV_DEST_ALPHA; + case kConstC_GrBlendCoeff: + return D3D12_BLEND_BLEND_FACTOR; + case kIConstC_GrBlendCoeff: + return D3D12_BLEND_INV_BLEND_FACTOR; + case kS2C_GrBlendCoeff: + return D3D12_BLEND_SRC1_COLOR; + case kIS2C_GrBlendCoeff: + return D3D12_BLEND_INV_SRC1_COLOR; + case kS2A_GrBlendCoeff: + return D3D12_BLEND_SRC1_ALPHA; + case kIS2A_GrBlendCoeff: + return D3D12_BLEND_INV_SRC1_ALPHA; + case kIllegal_GrBlendCoeff: + return D3D12_BLEND_ZERO; + } + SkUNREACHABLE; +} + +static D3D12_BLEND blend_coeff_to_d3d_blend_for_alpha(GrBlendCoeff coeff) { + switch (coeff) { + // Force all srcColor used in alpha slot to alpha version. + case kSC_GrBlendCoeff: + return D3D12_BLEND_SRC_ALPHA; + case kISC_GrBlendCoeff: + return D3D12_BLEND_INV_SRC_ALPHA; + case kDC_GrBlendCoeff: + return D3D12_BLEND_DEST_ALPHA; + case kIDC_GrBlendCoeff: + return D3D12_BLEND_INV_DEST_ALPHA; + case kS2C_GrBlendCoeff: + return D3D12_BLEND_SRC1_ALPHA; + case kIS2C_GrBlendCoeff: + return D3D12_BLEND_INV_SRC1_ALPHA; + + default: + return blend_coeff_to_d3d_blend(coeff); + } +} + + +static D3D12_BLEND_OP blend_equation_to_d3d_op(GrBlendEquation equation) { + switch (equation) { + case kAdd_GrBlendEquation: + return D3D12_BLEND_OP_ADD; + case kSubtract_GrBlendEquation: + return D3D12_BLEND_OP_SUBTRACT; + case kReverseSubtract_GrBlendEquation: + return D3D12_BLEND_OP_REV_SUBTRACT; + default: + SkUNREACHABLE; + } +} + +static void fill_in_blend_state(const GrPipeline& pipeline, D3D12_BLEND_DESC* blendDesc) { + blendDesc->AlphaToCoverageEnable = false; + blendDesc->IndependentBlendEnable = false; + + const GrXferProcessor::BlendInfo& blendInfo = pipeline.getXferProcessor().getBlendInfo(); + + GrBlendEquation equation = blendInfo.fEquation; + GrBlendCoeff srcCoeff = blendInfo.fSrcBlend; + GrBlendCoeff dstCoeff = blendInfo.fDstBlend; + bool blendOff = GrBlendShouldDisable(equation, srcCoeff, dstCoeff); + + auto& rtBlend = blendDesc->RenderTarget[0]; + rtBlend.BlendEnable = !blendOff; + if (!blendOff) { + rtBlend.SrcBlend = blend_coeff_to_d3d_blend(srcCoeff); + rtBlend.DestBlend = blend_coeff_to_d3d_blend(dstCoeff); + rtBlend.BlendOp = blend_equation_to_d3d_op(equation); + rtBlend.SrcBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(srcCoeff); + rtBlend.DestBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(dstCoeff); + rtBlend.BlendOpAlpha = blend_equation_to_d3d_op(equation); + } + + if (!blendInfo.fWriteColor) { + rtBlend.RenderTargetWriteMask = 0; + } else { + rtBlend.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + } +} + +static void fill_in_rasterizer_state(const GrPipeline& pipeline, const GrCaps* caps, + D3D12_RASTERIZER_DESC* rasterizer) { + rasterizer->FillMode = (caps->wireframeMode() || pipeline.isWireframe()) ? + D3D12_FILL_MODE_WIREFRAME : D3D12_FILL_MODE_SOLID; + rasterizer->CullMode = D3D12_CULL_MODE_NONE; + rasterizer->FrontCounterClockwise = true; + rasterizer->DepthBias = 0; + rasterizer->DepthBiasClamp = 0.0f; + rasterizer->SlopeScaledDepthBias = 0.0f; + rasterizer->DepthClipEnable = false; + rasterizer->MultisampleEnable = pipeline.isHWAntialiasState(); + rasterizer->AntialiasedLineEnable = false; + rasterizer->ForcedSampleCount = 0; + rasterizer->ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; +} + +static D3D12_STENCIL_OP stencil_op_to_d3d_op(GrStencilOp op) { + switch (op) { + case GrStencilOp::kKeep: + return D3D12_STENCIL_OP_KEEP; + case GrStencilOp::kZero: + return D3D12_STENCIL_OP_ZERO; + case GrStencilOp::kReplace: + return D3D12_STENCIL_OP_REPLACE; + case GrStencilOp::kInvert: + return D3D12_STENCIL_OP_INVERT; + case GrStencilOp::kIncWrap: + return D3D12_STENCIL_OP_INCR; + case GrStencilOp::kDecWrap: + return D3D12_STENCIL_OP_DECR; + case GrStencilOp::kIncClamp: + return D3D12_STENCIL_OP_INCR_SAT; + case GrStencilOp::kDecClamp: + return D3D12_STENCIL_OP_DECR_SAT; + } + SkUNREACHABLE; +} + +static D3D12_COMPARISON_FUNC stencil_test_to_d3d_func(GrStencilTest test) { + switch (test) { + case GrStencilTest::kAlways: + return D3D12_COMPARISON_FUNC_ALWAYS; + case GrStencilTest::kNever: + return D3D12_COMPARISON_FUNC_NEVER; + case GrStencilTest::kGreater: + return D3D12_COMPARISON_FUNC_GREATER; + case GrStencilTest::kGEqual: + return D3D12_COMPARISON_FUNC_GREATER_EQUAL; + case GrStencilTest::kLess: + return D3D12_COMPARISON_FUNC_LESS; + case GrStencilTest::kLEqual: + return D3D12_COMPARISON_FUNC_LESS_EQUAL; + case GrStencilTest::kEqual: + return D3D12_COMPARISON_FUNC_EQUAL; + case GrStencilTest::kNotEqual: + return D3D12_COMPARISON_FUNC_NOT_EQUAL; + } + SkUNREACHABLE; +} + +static void setup_stencilop_desc(D3D12_DEPTH_STENCILOP_DESC* desc, + const GrStencilSettings::Face& stencilFace) { + desc->StencilFailOp = stencil_op_to_d3d_op(stencilFace.fFailOp); + desc->StencilDepthFailOp = desc->StencilFailOp; + desc->StencilPassOp = stencil_op_to_d3d_op(stencilFace.fPassOp); + desc->StencilFunc = stencil_test_to_d3d_func(stencilFace.fTest); +} + +static void fill_in_depth_stencil_state(const GrProgramInfo& programInfo, + D3D12_DEPTH_STENCIL_DESC* dsDesc) { + GrStencilSettings stencilSettings = programInfo.nonGLStencilSettings(); + GrSurfaceOrigin origin = programInfo.origin(); + + dsDesc->DepthEnable = false; + dsDesc->DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; + dsDesc->DepthFunc = D3D12_COMPARISON_FUNC_NEVER; + dsDesc->StencilEnable = !stencilSettings.isDisabled(); + if (!stencilSettings.isDisabled()) { + if (stencilSettings.isTwoSided()) { + const auto& frontFace = stencilSettings.postOriginCCWFace(origin); + const auto& backFace = stencilSettings.postOriginCWFace(origin); + + SkASSERT(frontFace.fTestMask == backFace.fTestMask); + SkASSERT(frontFace.fWriteMask == backFace.fWriteMask); + dsDesc->StencilReadMask = frontFace.fTestMask; + dsDesc->StencilWriteMask = frontFace.fWriteMask; + + setup_stencilop_desc(&dsDesc->FrontFace, frontFace); + setup_stencilop_desc(&dsDesc->BackFace, backFace); + } else { + dsDesc->StencilReadMask = stencilSettings.singleSidedFace().fTestMask; + dsDesc->StencilWriteMask = stencilSettings.singleSidedFace().fWriteMask; + setup_stencilop_desc(&dsDesc->FrontFace, stencilSettings.singleSidedFace()); + dsDesc->BackFace = dsDesc->FrontFace; + } + } +} + +static D3D12_PRIMITIVE_TOPOLOGY_TYPE gr_primitive_type_to_d3d(GrPrimitiveType primitiveType) { + switch (primitiveType) { + case GrPrimitiveType::kTriangles: + case GrPrimitiveType::kTriangleStrip: //fall through + return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + case GrPrimitiveType::kPoints: + return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; + case GrPrimitiveType::kLines: // fall through + case GrPrimitiveType::kLineStrip: + return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; + case GrPrimitiveType::kPatches: // fall through, unsupported + case GrPrimitiveType::kPath: // fall through, unsupported + default: + SkUNREACHABLE; + } +} + +gr_cp<ID3D12PipelineState> create_pipeline_state( + GrD3DGpu* gpu, const GrProgramInfo& programInfo, const sk_sp<GrD3DRootSignature>& rootSig, + gr_cp<ID3DBlob> vertexShader, gr_cp<ID3DBlob> geometryShader, gr_cp<ID3DBlob> pixelShader, + DXGI_FORMAT renderTargetFormat, DXGI_FORMAT depthStencilFormat, + unsigned int sampleQualityLevel) { + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + + psoDesc.pRootSignature = rootSig->rootSignature(); + + psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()), + vertexShader->GetBufferSize() }; + psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()), + pixelShader->GetBufferSize() }; + + if (geometryShader.get()) { + psoDesc.GS = { reinterpret_cast<UINT8*>(geometryShader->GetBufferPointer()), + geometryShader->GetBufferSize() }; + } + + psoDesc.StreamOutput = { nullptr, 0, nullptr, 0, 0 }; + + fill_in_blend_state(programInfo.pipeline(), &psoDesc.BlendState); + psoDesc.SampleMask = UINT_MAX; + + fill_in_rasterizer_state(programInfo.pipeline(), gpu->caps(), &psoDesc.RasterizerState); + + fill_in_depth_stencil_state(programInfo, &psoDesc.DepthStencilState); + + unsigned int totalAttributeCnt = programInfo.primProc().numVertexAttributes() + + programInfo.primProc().numInstanceAttributes(); + SkAutoSTArray<4, D3D12_INPUT_ELEMENT_DESC> inputElements(totalAttributeCnt); + setup_vertex_input_layout(programInfo.primProc(), inputElements.get()); + + psoDesc.InputLayout = { inputElements.get(), totalAttributeCnt }; + + psoDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; + + // This is for geometry or hull shader primitives + psoDesc.PrimitiveTopologyType = gr_primitive_type_to_d3d(programInfo.primitiveType()); + + psoDesc.NumRenderTargets = 1; + + psoDesc.RTVFormats[0] = renderTargetFormat; + + psoDesc.DSVFormat = depthStencilFormat; + + unsigned int numRasterSamples = programInfo.numRasterSamples(); + psoDesc.SampleDesc = { numRasterSamples, sampleQualityLevel }; + + // Only used for multi-adapter systems. + psoDesc.NodeMask = 0; + + psoDesc.CachedPSO = { nullptr, 0 }; + psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + + gr_cp<ID3D12PipelineState> pipelineState; + SkDEBUGCODE(HRESULT hr = )gpu->device()->CreateGraphicsPipelineState( + &psoDesc, IID_PPV_ARGS(&pipelineState)); + SkASSERT(SUCCEEDED(hr)); + + return pipelineState; +} + +static constexpr SkFourByteTag kHLSL_Tag = SkSetFourByteTag('H', 'L', 'S', 'L'); +static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L'); + sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() { TRACE_EVENT0("skia.gpu", TRACE_FUNC); @@ -135,32 +552,86 @@ sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() { SkSL::Program::Settings settings; settings.fCaps = this->caps()->shaderCaps(); settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin; + settings.fInverseW = true; settings.fSharpenTextures = this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures; settings.fRTHeightOffset = fUniformHandler.getRTHeightOffset(); settings.fRTHeightBinding = 0; settings.fRTHeightSet = 0; - gr_cp<ID3DBlob> vertexShader; - gr_cp<ID3DBlob> geometryShader; - gr_cp<ID3DBlob> pixelShader; - SkSL::Program::Inputs vertInputs, fragInputs, geomInputs; + sk_sp<SkData> cached; + SkReadBuffer reader; + SkFourByteTag shaderType = 0; + auto persistentCache = fGpu->getContext()->priv().getPersistentCache(); + if (persistentCache) { + // Shear off the D3D-specific portion of the Desc to get the persistent key. We only cache + // shader code, not entire pipelines. + sk_sp<SkData> key = + SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().initialKeyLength()); + cached = persistentCache->load(*key); + if (cached) { + reader.setMemory(cached->data(), cached->size()); + shaderType = GrPersistentCacheUtils::GetType(&reader); + } + } - this->compileD3DProgram(SkSL::Program::kVertex_Kind, fVS.fCompilerString, settings, - &vertexShader, &vertInputs); - this->compileD3DProgram(SkSL::Program::kFragment_Kind, fFS.fCompilerString, settings, - &pixelShader, &fragInputs); + const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); + gr_cp<ID3DBlob> shaders[kGrShaderTypeCount]; - if (!vertexShader.get() || !pixelShader.get()) { - return nullptr; - } + if (kHLSL_Tag == shaderType && this->loadHLSLFromCache(&reader, shaders)) { + // We successfully loaded and compiled HLSL + } else { + SkSL::Program::Inputs inputs[kGrShaderTypeCount]; + SkSL::String* sksl[kGrShaderTypeCount] = { + &fVS.fCompilerString, + &fGS.fCompilerString, + &fFS.fCompilerString, + }; + SkSL::String cached_sksl[kGrShaderTypeCount]; + SkSL::String hlsl[kGrShaderTypeCount]; - if (this->primitiveProcessor().willUseGeoShader()) { - this->compileD3DProgram(SkSL::Program::kGeometry_Kind, fGS.fCompilerString, settings, - &geometryShader, &geomInputs); - if (!geometryShader.get()) { + if (kSKSL_Tag == shaderType) { + if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, inputs, + kGrShaderTypeCount)) { + for (int i = 0; i < kGrShaderTypeCount; ++i) { + sksl[i] = &cached_sksl[i]; + } + } + } + + auto compile = [&](SkSL::Program::Kind kind, GrShaderType shaderType) { + shaders[shaderType] = this->compileD3DProgram(kind, *sksl[shaderType], settings, + &inputs[shaderType], &hlsl[shaderType]); + return shaders[shaderType].get(); + }; + + if (!compile(SkSL::Program::kVertex_Kind, kVertex_GrShaderType) || + !compile(SkSL::Program::kFragment_Kind, kFragment_GrShaderType)) { return nullptr; } + + if (primProc.willUseGeoShader()) { + if (!compile(SkSL::Program::kGeometry_Kind, kGeometry_GrShaderType)) { + return nullptr; + } + } + + if (persistentCache && !cached) { + const bool cacheSkSL = fGpu->getContext()->priv().options().fShaderCacheStrategy == + GrContextOptions::ShaderCacheStrategy::kSkSL; + if (cacheSkSL) { + // Replace the HLSL with formatted SkSL to be cached. This looks odd, but this is + // the last time we're going to use these strings, so it's safe. + for (int i = 0; i < kGrShaderTypeCount; ++i) { + hlsl[i] = GrShaderUtils::PrettyPrint(*sksl[i]); + } + } + sk_sp<SkData> key = + SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().initialKeyLength()); + sk_sp<SkData> data = GrPersistentCacheUtils::PackCachedShaders( + cacheSkSL ? kSKSL_Tag : kHLSL_Tag, hlsl, inputs, kGrShaderTypeCount); + persistentCache->store(*key, *data); + } } sk_sp<GrD3DRootSignature> rootSig = @@ -170,8 +641,21 @@ sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() { } const GrD3DRenderTarget* rt = static_cast<const GrD3DRenderTarget*>(fRenderTarget); - return GrD3DPipelineState::Make(fGpu, fProgramInfo, std::move(rootSig), - std::move(vertexShader), std::move(geometryShader), - std::move(pixelShader), rt->dxgiFormat(), - rt->stencilDxgiFormat(), rt->sampleQualityLevel()); + gr_cp<ID3D12PipelineState> pipelineState = create_pipeline_state( + fGpu, fProgramInfo, rootSig, std::move(shaders[kVertex_GrShaderType]), + std::move(shaders[kGeometry_GrShaderType]), std::move(shaders[kFragment_GrShaderType]), + rt->dxgiFormat(), rt->stencilDxgiFormat(), rt->sampleQualityLevel()); + + return sk_sp<GrD3DPipelineState>(new GrD3DPipelineState(std::move(pipelineState), + std::move(rootSig), + fUniformHandles, + fUniformHandler.fUniforms, + fUniformHandler.fCurrentUBOOffset, + fUniformHandler.fSamplers.count(), + std::move(fGeometryProcessor), + std::move(fXferProcessor), + std::move(fFragmentProcessors), + fFragmentProcessorCnt, + primProc.vertexStride(), + primProc.instanceStride())); } diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.h index e5fc4171bbd..357c024b0cd 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.h @@ -18,7 +18,6 @@ class GrProgramDesc; class GrD3DGpu; class GrVkRenderPass; -class SkReader32; class GrD3DPipelineStateBuilder : public GrGLSLProgramBuilder { public: @@ -46,11 +45,13 @@ private: sk_sp<GrD3DPipelineState> finalize(); - void compileD3DProgram(SkSL::Program::Kind kind, - const SkSL::String& sksl, - const SkSL::Program::Settings& settings, - ID3DBlob** shader, - SkSL::Program::Inputs* outInputs); + bool loadHLSLFromCache(SkReadBuffer* reader, gr_cp<ID3DBlob> shaders[]); + + gr_cp<ID3DBlob> compileD3DProgram(SkSL::Program::Kind kind, + const SkSL::String& sksl, + const SkSL::Program::Settings& settings, + SkSL::Program::Inputs* outInputs, + SkSL::String* outHLSL); GrGLSLUniformHandler* uniformHandler() override { return &fUniformHandler; } const GrGLSLUniformHandler* uniformHandler() const override { return &fUniformHandler; } diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateDataManager.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateDataManager.cpp new file mode 100644 index 00000000000..a902bddc9a5 --- /dev/null +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateDataManager.cpp @@ -0,0 +1,41 @@ +/* +* Copyright 2016 Google Inc. +* +* Use of this source code is governed by a BSD-style license that can be +* found in the LICENSE file. +*/ + +#include "src/gpu/d3d/GrD3DPipelineStateDataManager.h" + +#include "src/gpu/d3d/GrD3DGpu.h" +#include "src/gpu/d3d/GrD3DResourceProvider.h" + +GrD3DPipelineStateDataManager::GrD3DPipelineStateDataManager(const UniformInfoArray& uniforms, + uint32_t uniformSize) + : INHERITED(uniforms.count(), uniformSize) { + // We must add uniforms in same order as the UniformInfoArray so that UniformHandles already + // owned by other objects will still match up here. + int i = 0; + for (const auto& uniformInfo : uniforms.items()) { + Uniform& uniform = fUniforms[i]; + SkASSERT(GrShaderVar::kNonArray == uniformInfo.fVariable.getArrayCount() || + uniformInfo.fVariable.getArrayCount() > 0); + SkDEBUGCODE( + uniform.fArrayCount = uniformInfo.fVariable.getArrayCount(); + uniform.fType = uniformInfo.fVariable.getType(); + ) + + uniform.fOffset = uniformInfo.fUBOOffset; + ++i; + } +} + +D3D12_GPU_VIRTUAL_ADDRESS GrD3DPipelineStateDataManager::uploadConstants(GrD3DGpu* gpu) { + if (fUniformsDirty) { + fConstantBufferAddress = gpu->resourceProvider().uploadConstantData(fUniformData.get(), + fUniformSize); + fUniformsDirty = false; + } + + return fConstantBufferAddress; +} diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateDataManager.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateDataManager.h new file mode 100644 index 00000000000..15a41abc42f --- /dev/null +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateDataManager.h @@ -0,0 +1,34 @@ +/* +* Copyright 2020 Google LLC +* +* Use of this source code is governed by a BSD-style license that can be +* found in the LICENSE file. +*/ + +#ifndef GrD3DPipelineStateDataManager_DEFINED +#define GrD3DPipelineStateDataManager_DEFINED + +#include "src/gpu/GrUniformDataManager.h" + +#include "include/gpu/d3d/GrD3DTypes.h" +#include "src/gpu/GrSPIRVUniformHandler.h" + +class GrD3DConstantRingBuffer; +class GrD3DGpu; + +class GrD3DPipelineStateDataManager : public GrUniformDataManager { +public: + typedef GrSPIRVUniformHandler::UniformInfoArray UniformInfoArray; + + GrD3DPipelineStateDataManager(const UniformInfoArray&, + uint32_t uniformSize); + + D3D12_GPU_VIRTUAL_ADDRESS uploadConstants(GrD3DGpu* gpu); + +private: + D3D12_GPU_VIRTUAL_ADDRESS fConstantBufferAddress; + + typedef GrUniformDataManager INHERITED; +}; + +#endif diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.cpp index 4dd2e6092ec..b572a6f5c7b 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.cpp @@ -24,8 +24,8 @@ GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu, sk_sp<GrD3DResourceState> state, const GrD3DTextureResourceInfo& msaaInfo, sk_sp<GrD3DResourceState> msaaState, - const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView, - const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView, + const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView, + const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView, Wrapped) : GrSurface(gpu, dimensions, info.fProtected) , GrD3DTextureResource(info, std::move(state)) @@ -48,8 +48,8 @@ GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu, sk_sp<GrD3DResourceState> state, const GrD3DTextureResourceInfo& msaaInfo, sk_sp<GrD3DResourceState> msaaState, - const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView, - const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView) + const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView, + const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView) : GrSurface(gpu, dimensions, info.fProtected) , GrD3DTextureResource(info, std::move(state)) // for the moment we only support 1:1 color to stencil @@ -67,7 +67,7 @@ GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu, SkISize dimensions, const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state, - const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView, + const GrD3DDescriptorHeap::CPUHandle& renderTargetView, Wrapped) : GrSurface(gpu, dimensions, info.fProtected) , GrD3DTextureResource(info, std::move(state)) @@ -83,7 +83,7 @@ GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu, SkISize dimensions, const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state, - const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView) + const GrD3DDescriptorHeap::CPUHandle& renderTargetView) : GrSurface(gpu, dimensions, info.fProtected) , GrD3DTextureResource(info, std::move(state)) , GrRenderTarget(gpu, dimensions, 1, info.fProtected) @@ -98,7 +98,7 @@ sk_sp<GrD3DRenderTarget> GrD3DRenderTarget::MakeWrappedRenderTarget( SkASSERT(1 == info.fLevelCount); DXGI_FORMAT dxgiFormat = info.fFormat; - D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView = + GrD3DDescriptorHeap::CPUHandle renderTargetView = gpu->resourceProvider().createRenderTargetView(info.fResource.get()); // create msaa surface if necessary @@ -137,7 +137,7 @@ sk_sp<GrD3DRenderTarget> GrD3DRenderTarget::MakeWrappedRenderTarget( msState.reset(new GrD3DResourceState( static_cast<D3D12_RESOURCE_STATES>(msInfo.fResourceState))); - D3D12_CPU_DESCRIPTOR_HANDLE msaaRenderTargetView = + GrD3DDescriptorHeap::CPUHandle msaaRenderTargetView = gpu->resourceProvider().createRenderTargetView(msInfo.fResource.get()); d3dRT = new GrD3DRenderTarget(gpu, dimensions, sampleCnt, info, std::move(state), msInfo, @@ -162,10 +162,10 @@ void GrD3DRenderTarget::releaseInternalObjects() { if (fMSAATextureResource) { fMSAATextureResource->releaseResource(gpu); fMSAATextureResource.reset(); - gpu->resourceProvider().recycleRenderTargetView(&fResolveRenderTargetView); + gpu->resourceProvider().recycleRenderTargetView(fResolveRenderTargetView); } - gpu->resourceProvider().recycleRenderTargetView(&fColorRenderTargetView); + gpu->resourceProvider().recycleRenderTargetView(fColorRenderTargetView); } void GrD3DRenderTarget::onRelease() { diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.h index e2829a444ca..c83cf60020e 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.h @@ -14,6 +14,7 @@ #include "include/gpu/d3d/GrD3DTypes.h" #include "src/gpu/GrGpu.h" +#include "src/gpu/d3d/GrD3DDescriptorHeap.h" #include "src/gpu/d3d/GrD3DResourceProvider.h" class GrD3DGpu; @@ -36,7 +37,7 @@ public: GrBackendFormat backendFormat() const override { return this->getBackendFormat(); } - GrD3DTextureResource* msaaTextureResource() { return fMSAATextureResource.get(); } + GrD3DTextureResource* msaaTextureResource() const { return fMSAATextureResource.get(); } bool canAttemptStencilAttachment() const override { return true; @@ -44,8 +45,8 @@ public: GrBackendRenderTarget getBackendRenderTarget() const override; - D3D12_CPU_DESCRIPTOR_HANDLE colorRenderTargetView() { - return fColorRenderTargetView; + D3D12_CPU_DESCRIPTOR_HANDLE colorRenderTargetView() const { + return fColorRenderTargetView.fHandle; } DXGI_FORMAT stencilDxgiFormat() const; @@ -61,14 +62,14 @@ protected: sk_sp<GrD3DResourceState> state, const GrD3DTextureResourceInfo& msaaInfo, sk_sp<GrD3DResourceState> msaaState, - const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView, - const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView); + const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView, + const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView); GrD3DRenderTarget(GrD3DGpu* gpu, SkISize dimensions, const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state, - const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView); + const GrD3DDescriptorHeap::CPUHandle& renderTargetView); void onAbandon() override; void onRelease() override; @@ -95,15 +96,15 @@ private: sk_sp<GrD3DResourceState> state, const GrD3DTextureResourceInfo& msaaInfo, sk_sp<GrD3DResourceState> msaaState, - const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView, - const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView, + const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView, + const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView, Wrapped); GrD3DRenderTarget(GrD3DGpu* gpu, SkISize dimensions, const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state, - const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView, + const GrD3DDescriptorHeap::CPUHandle& renderTargetView, Wrapped); GrD3DGpu* getD3DGpu() const; @@ -121,8 +122,8 @@ private: std::unique_ptr<GrD3DTextureResource> fMSAATextureResource; - D3D12_CPU_DESCRIPTOR_HANDLE fColorRenderTargetView; - D3D12_CPU_DESCRIPTOR_HANDLE fResolveRenderTargetView; + GrD3DDescriptorHeap::CPUHandle fColorRenderTargetView; + GrD3DDescriptorHeap::CPUHandle fResolveRenderTargetView; }; #endif diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.cpp index f93b36c2687..c933743e358 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.cpp @@ -9,6 +9,7 @@ #include "include/gpu/GrContextOptions.h" #include "src/gpu/GrContextPriv.h" +#include "src/gpu/d3d/GrD3DBuffer.h" #include "src/gpu/d3d/GrD3DCommandList.h" #include "src/gpu/d3d/GrD3DGpu.h" #include "src/gpu/d3d/GrD3DPipelineState.h" @@ -16,8 +17,14 @@ GrD3DResourceProvider::GrD3DResourceProvider(GrD3DGpu* gpu) : fGpu(gpu) - , fAttachmentViewManager(gpu) - , fPipelineStateCache(new PipelineStateCache(gpu)) { + , fCpuDescriptorManager(gpu) + , fDescriptorTableManager(gpu) + , fPipelineStateCache(new PipelineStateCache(gpu)) {} + +void GrD3DResourceProvider::destroyResources() { + fSamplers.reset(); + + fPipelineStateCache->release(); } std::unique_ptr<GrD3DDirectCommandList> GrD3DResourceProvider::findOrCreateDirectCommandList() { @@ -52,22 +59,91 @@ sk_sp<GrD3DRootSignature> GrD3DResourceProvider::findOrCreateRootSignature(int n } -D3D12_CPU_DESCRIPTOR_HANDLE GrD3DResourceProvider::createRenderTargetView( +GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createRenderTargetView( ID3D12Resource* textureResource) { - return fAttachmentViewManager.createRenderTargetView(fGpu, textureResource); + return fCpuDescriptorManager.createRenderTargetView(fGpu, textureResource); } -void GrD3DResourceProvider::recycleRenderTargetView(D3D12_CPU_DESCRIPTOR_HANDLE* rtvDescriptor) { - fAttachmentViewManager.recycleRenderTargetView(rtvDescriptor); +void GrD3DResourceProvider::recycleRenderTargetView( + const GrD3DDescriptorHeap::CPUHandle& rtvDescriptor) { + fCpuDescriptorManager.recycleRenderTargetView(rtvDescriptor); } -D3D12_CPU_DESCRIPTOR_HANDLE GrD3DResourceProvider::createDepthStencilView( +GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createDepthStencilView( ID3D12Resource* textureResource) { - return fAttachmentViewManager.createDepthStencilView(fGpu, textureResource); + return fCpuDescriptorManager.createDepthStencilView(fGpu, textureResource); +} + +void GrD3DResourceProvider::recycleDepthStencilView( + const GrD3DDescriptorHeap::CPUHandle& dsvDescriptor) { + fCpuDescriptorManager.recycleDepthStencilView(dsvDescriptor); +} + +GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createConstantBufferView( + ID3D12Resource* bufferResource, size_t offset, size_t size) { + return fCpuDescriptorManager.createConstantBufferView(fGpu, bufferResource, offset, size); +} + +GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createShaderResourceView( + ID3D12Resource* resource) { + return fCpuDescriptorManager.createShaderResourceView(fGpu, resource); +} + +void GrD3DResourceProvider::recycleConstantOrShaderView( + const GrD3DDescriptorHeap::CPUHandle& view) { + fCpuDescriptorManager.recycleConstantOrShaderView(view); } -void GrD3DResourceProvider::recycleDepthStencilView(D3D12_CPU_DESCRIPTOR_HANDLE* dsvDescriptor) { - fAttachmentViewManager.recycleDepthStencilView(dsvDescriptor); +static D3D12_TEXTURE_ADDRESS_MODE wrap_mode_to_d3d_address_mode(GrSamplerState::WrapMode wrapMode) { + switch (wrapMode) { + case GrSamplerState::WrapMode::kClamp: + return D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + case GrSamplerState::WrapMode::kRepeat: + return D3D12_TEXTURE_ADDRESS_MODE_WRAP; + case GrSamplerState::WrapMode::kMirrorRepeat: + return D3D12_TEXTURE_ADDRESS_MODE_MIRROR; + case GrSamplerState::WrapMode::kClampToBorder: + return D3D12_TEXTURE_ADDRESS_MODE_BORDER; + } + SK_ABORT("Unknown wrap mode."); +} + +D3D12_CPU_DESCRIPTOR_HANDLE GrD3DResourceProvider::findOrCreateCompatibleSampler( + const GrSamplerState& params) { + uint32_t key = GrSamplerState::GenerateKey(params); + D3D12_CPU_DESCRIPTOR_HANDLE* samplerPtr = fSamplers.find(key); + if (samplerPtr) { + return *samplerPtr; + } + + static D3D12_FILTER d3dFilterModes[] = { + D3D12_FILTER_MIN_MAG_MIP_POINT, + D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT, + D3D12_FILTER_MIN_MAG_MIP_LINEAR + }; + + static_assert((int)GrSamplerState::Filter::kNearest == 0); + static_assert((int)GrSamplerState::Filter::kBilerp == 1); + static_assert((int)GrSamplerState::Filter::kMipMap == 2); + + D3D12_FILTER filter = d3dFilterModes[static_cast<int>(params.filter())]; + D3D12_TEXTURE_ADDRESS_MODE addressModeU = wrap_mode_to_d3d_address_mode(params.wrapModeX()); + D3D12_TEXTURE_ADDRESS_MODE addressModeV = wrap_mode_to_d3d_address_mode(params.wrapModeY()); + + D3D12_CPU_DESCRIPTOR_HANDLE sampler = + fCpuDescriptorManager.createSampler( + fGpu, filter, addressModeU, addressModeV).fHandle; + fSamplers.set(key, sampler); + return sampler; +} + +std::unique_ptr<GrD3DDescriptorTable> GrD3DResourceProvider::createShaderOrConstantResourceTable( + unsigned int size) { + return fDescriptorTableManager.createShaderOrConstantResourceTable(fGpu, size); +} + +std::unique_ptr<GrD3DDescriptorTable> GrD3DResourceProvider::createSamplerTable(unsigned int size) { + return fDescriptorTableManager.createSamplerTable(fGpu, size); } sk_sp<GrD3DPipelineState> GrD3DResourceProvider::findOrCreateCompatiblePipelineState( @@ -75,6 +151,34 @@ sk_sp<GrD3DPipelineState> GrD3DResourceProvider::findOrCreateCompatiblePipelineS return fPipelineStateCache->refPipelineState(rt, info); } +D3D12_GPU_VIRTUAL_ADDRESS GrD3DResourceProvider::uploadConstantData(void* data, size_t size) { + // constant size has to be aligned to 256 + constexpr int kConstantAlignment = 256; + + // Due to dependency on the resource cache we can't initialize this in the constructor, so + // we do so it here. + if (!fConstantBuffer) { + fConstantBuffer = GrD3DConstantRingBuffer::Make(fGpu, 128 * 1024, kConstantAlignment); + SkASSERT(fConstantBuffer); + } + + // upload the data + size_t paddedSize = GrAlignTo(size, kConstantAlignment); + GrRingBuffer::Slice slice = fConstantBuffer->suballocate(paddedSize); + char* destPtr = static_cast<char*>(slice.fBuffer->map()) + slice.fOffset; + memcpy(destPtr, data, size); + + // create the associated constant buffer view descriptor + GrD3DBuffer* d3dBuffer = static_cast<GrD3DBuffer*>(slice.fBuffer.get()); + D3D12_GPU_VIRTUAL_ADDRESS gpuAddress = d3dBuffer->d3dResource()->GetGPUVirtualAddress(); + return gpuAddress + slice.fOffset; +} + +void GrD3DResourceProvider::prepForSubmit() { + fGpu->currentCommandList()->setCurrentConstantBuffer(fConstantBuffer); + fDescriptorTableManager.prepForSubmit(fGpu); +} + //////////////////////////////////////////////////////////////////////////////////////////////// #ifdef GR_PIPELINE_STATE_CACHE_STATS @@ -114,6 +218,10 @@ GrD3DResourceProvider::PipelineStateCache::~PipelineStateCache() { #endif } +void GrD3DResourceProvider::PipelineStateCache::release() { + fMap.reset(); +} + sk_sp<GrD3DPipelineState> GrD3DResourceProvider::PipelineStateCache::refPipelineState( GrRenderTarget* renderTarget, const GrProgramInfo& programInfo) { #ifdef GR_PIPELINE_STATE_CACHE_STATS @@ -144,3 +252,10 @@ sk_sp<GrD3DPipelineState> GrD3DResourceProvider::PipelineStateCache::refPipeline } return (*entry)->fPipelineState; } + +void GrD3DResourceProvider::PipelineStateCache::markPipelineStateUniformsDirty() { + fMap.foreach ([](const GrProgramDesc*, std::unique_ptr<Entry>* entry) { + (*entry)->fPipelineState->markUniformsDirty(); + }); +} + diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.h index 4e244cb632f..923342ab79f 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.h @@ -10,9 +10,12 @@ #include "include/gpu/d3d/GrD3DTypes.h" #include "include/private/SkTArray.h" +#include "include/private/SkTHash.h" #include "src/core/SkLRUCache.h" #include "src/gpu/GrProgramDesc.h" -#include "src/gpu/d3d/GrD3DAttachmentViewManager.h" +#include "src/gpu/d3d/GrD3DConstantRingBuffer.h" +#include "src/gpu/d3d/GrD3DCpuDescriptorManager.h" +#include "src/gpu/d3d/GrD3DDescriptorTableManager.h" #include "src/gpu/d3d/GrD3DRootSignature.h" #include <memory> @@ -20,26 +23,53 @@ class GrD3DDirectCommandList; class GrD3DGpu; class GrD3DPipelineState; +class GrSamplerState; class GrD3DResourceProvider { public: GrD3DResourceProvider(GrD3DGpu*); + void destroyResources(); + std::unique_ptr<GrD3DDirectCommandList> findOrCreateDirectCommandList(); void recycleDirectCommandList(std::unique_ptr<GrD3DDirectCommandList>); sk_sp<GrD3DRootSignature> findOrCreateRootSignature(int numTextureSamplers); - D3D12_CPU_DESCRIPTOR_HANDLE createRenderTargetView(ID3D12Resource* textureResource); - void recycleRenderTargetView(D3D12_CPU_DESCRIPTOR_HANDLE*); + GrD3DDescriptorHeap::CPUHandle createRenderTargetView(ID3D12Resource* textureResource); + void recycleRenderTargetView(const GrD3DDescriptorHeap::CPUHandle&); + + GrD3DDescriptorHeap::CPUHandle createDepthStencilView(ID3D12Resource* textureResource); + void recycleDepthStencilView(const GrD3DDescriptorHeap::CPUHandle&); + + GrD3DDescriptorHeap::CPUHandle createConstantBufferView(ID3D12Resource* bufferResource, + size_t offset, + size_t size); + GrD3DDescriptorHeap::CPUHandle createShaderResourceView(ID3D12Resource* resource); + void recycleConstantOrShaderView(const GrD3DDescriptorHeap::CPUHandle&); - D3D12_CPU_DESCRIPTOR_HANDLE createDepthStencilView(ID3D12Resource* textureResource); - void recycleDepthStencilView(D3D12_CPU_DESCRIPTOR_HANDLE*); + D3D12_CPU_DESCRIPTOR_HANDLE findOrCreateCompatibleSampler(const GrSamplerState& params); - sk_sp<GrD3DPipelineState> findOrCreateCompatiblePipelineState(GrRenderTarget*, + + std::unique_ptr<GrD3DDescriptorTable> createShaderOrConstantResourceTable(unsigned int size); + std::unique_ptr<GrD3DDescriptorTable> createSamplerTable(unsigned int size); + GrD3DDescriptorTableManager* descriptorTableMgr() { + return &fDescriptorTableManager; + } + + sk_sp<GrD3DPipelineState> findOrCreateCompatiblePipelineState(GrRenderTarget*, const GrProgramInfo&); + D3D12_GPU_VIRTUAL_ADDRESS uploadConstantData(void* data, size_t size); + void prepForSubmit(); + + void markPipelineStateUniformsDirty() { fPipelineStateCache->markPipelineStateUniformsDirty(); } + +#if GR_TEST_UTILS + void resetShaderCacheForTesting() const { fPipelineStateCache->release(); } +#endif + private: #ifdef SK_DEBUG #define GR_PIPELINE_STATE_CACHE_STATS @@ -50,8 +80,11 @@ private: PipelineStateCache(GrD3DGpu* gpu); ~PipelineStateCache(); + void release(); sk_sp<GrD3DPipelineState> refPipelineState(GrRenderTarget*, const GrProgramInfo&); + void markPipelineStateUniformsDirty(); + private: struct Entry; @@ -76,9 +109,14 @@ private: SkSTArray<4, std::unique_ptr<GrD3DDirectCommandList>> fAvailableDirectCommandLists; SkSTArray<4, sk_sp<GrD3DRootSignature>> fRootSignatures; - GrD3DAttachmentViewManager fAttachmentViewManager; + GrD3DCpuDescriptorManager fCpuDescriptorManager; + GrD3DDescriptorTableManager fDescriptorTableManager; + + sk_sp<GrD3DConstantRingBuffer> fConstantBuffer; std::unique_ptr<PipelineStateCache> fPipelineStateCache; + + SkTHashMap<uint32_t, D3D12_CPU_DESCRIPTOR_HANDLE> fSamplers; }; #endif diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.cpp index b4f2d8ddc04..e64faa2ba0c 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.cpp @@ -15,17 +15,9 @@ sk_sp<GrD3DRootSignature> GrD3DRootSignature::Make(GrD3DGpu* gpu, int numTexture D3D12_ROOT_PARAMETER parameters[3]; // The first will always be our uniforms - D3D12_DESCRIPTOR_RANGE uniformRange{}; - uniformRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; - uniformRange.NumDescriptors = 1; - uniformRange.BaseShaderRegister = 0; - // Spirv-Cross uses the descriptor set as the space in HSLS - uniformRange.RegisterSpace = GrSPIRVUniformHandler::kUniformDescriptorSet; - uniformRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - - parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - parameters[0].DescriptorTable.NumDescriptorRanges = 1; - parameters[0].DescriptorTable.pDescriptorRanges = &uniformRange; + parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + parameters[0].Descriptor.ShaderRegister = 0; + parameters[0].Descriptor.RegisterSpace = GrSPIRVUniformHandler::kUniformDescriptorSet; parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; SkAutoTArray<D3D12_DESCRIPTOR_RANGE> samplerRanges(numTextureSamplers); diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.h index c133e2e5aca..025ac4d2a8e 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.h @@ -17,6 +17,12 @@ class GrD3DRootSignature : public GrManagedResource { public: static sk_sp<GrD3DRootSignature> Make(GrD3DGpu* gpu, int numTextureSamplers); + enum class ParamIndex { + kConstantBufferView = 0, + kSamplerDescriptorTable = 1, + kTextureDescriptorTable = 2 + }; + bool isCompatible(int numTextureSamplers) const; ID3D12RootSignature* rootSignature() const { return fRootSignature.get(); } diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.cpp index e5dd5bcf339..c8925c1d87f 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.cpp @@ -13,10 +13,12 @@ GrD3DStencilAttachment::GrD3DStencilAttachment(GrD3DGpu* gpu, const Format& format, const D3D12_RESOURCE_DESC& desc, const GrD3DTextureResourceInfo& info, - sk_sp<GrD3DResourceState> state) + sk_sp<GrD3DResourceState> state, + const GrD3DDescriptorHeap::CPUHandle& view) : GrStencilAttachment(gpu, desc.Width, desc.Height, format.fStencilBits, desc.SampleDesc.Count) - , GrD3DTextureResource(info, state) { + , GrD3DTextureResource(info, state) + , fView(view) { this->registerWithCache(SkBudgeted::kYes); } @@ -51,9 +53,12 @@ GrD3DStencilAttachment* GrD3DStencilAttachment::Make(GrD3DGpu* gpu, return nullptr; } + GrD3DDescriptorHeap::CPUHandle view = + gpu->resourceProvider().createDepthStencilView(info.fResource.get()); + sk_sp<GrD3DResourceState> state(new GrD3DResourceState(info.fResourceState)); GrD3DStencilAttachment* stencil = new GrD3DStencilAttachment(gpu, format, resourceDesc, - info, std::move(state)); + info, std::move(state), view); return stencil; } diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.h index 096626d9053..927637c9e15 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.h @@ -11,11 +11,11 @@ #include "src/gpu/GrStencilAttachment.h" #include "include/gpu/d3d/GrD3DTypes.h" +#include "src/gpu/d3d/GrD3DDescriptorHeap.h" #include "src/gpu/d3d/GrD3DTextureResource.h" class GrD3DGpu; - class GrD3DStencilAttachment : public GrStencilAttachment, public GrD3DTextureResource { public: struct Format { @@ -28,6 +28,10 @@ public: ~GrD3DStencilAttachment() override {} + D3D12_CPU_DESCRIPTOR_HANDLE view() const { + return fView.fHandle; + } + protected: void onRelease() override; void onAbandon() override; @@ -39,9 +43,12 @@ private: const Format& format, const D3D12_RESOURCE_DESC&, const GrD3DTextureResourceInfo&, - sk_sp<GrD3DResourceState>); + sk_sp<GrD3DResourceState>, + const GrD3DDescriptorHeap::CPUHandle& view); GrD3DGpu* getD3DGpu() const; + + GrD3DDescriptorHeap::CPUHandle fView; }; #endif diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.cpp index 458853a3ad6..b59fb4d5f4d 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.cpp @@ -19,10 +19,12 @@ GrD3DTexture::GrD3DTexture(GrD3DGpu* gpu, SkISize dimensions, const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state, + const GrD3DDescriptorHeap::CPUHandle& shaderResourceView, GrMipMapsStatus mipMapsStatus) : GrSurface(gpu, dimensions, info.fProtected) , GrD3DTextureResource(info, std::move(state)) - , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus) { + , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus) + , fShaderResourceView(shaderResourceView) { SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount)); this->registerWithCache(budgeted); if (GrDxgiFormatIsCompressed(info.fFormat)) { @@ -31,11 +33,14 @@ GrD3DTexture::GrD3DTexture(GrD3DGpu* gpu, } GrD3DTexture::GrD3DTexture(GrD3DGpu* gpu, SkISize dimensions, const GrD3DTextureResourceInfo& info, - sk_sp<GrD3DResourceState> state, GrMipMapsStatus mipMapsStatus, - GrWrapCacheable cacheable, GrIOType ioType) + sk_sp<GrD3DResourceState> state, + const GrD3DDescriptorHeap::CPUHandle& shaderResourceView, + GrMipMapsStatus mipMapsStatus, GrWrapCacheable cacheable, + GrIOType ioType) : GrSurface(gpu, dimensions, info.fProtected) , GrD3DTextureResource(info, std::move(state)) - , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus) { + , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus) + , fShaderResourceView(shaderResourceView) { SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount)); if (ioType == kRead_GrIOType) { this->setReadOnly(); @@ -48,10 +53,12 @@ GrD3DTexture::GrD3DTexture(GrD3DGpu* gpu, SkISize dimensions, const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state, + const GrD3DDescriptorHeap::CPUHandle& shaderResourceView, GrMipMapsStatus mipMapsStatus) : GrSurface(gpu, dimensions, info.fProtected) , GrD3DTextureResource(info, state) - , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus) { + , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus) + , fShaderResourceView(shaderResourceView) { SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount)); } @@ -70,8 +77,11 @@ sk_sp<GrD3DTexture> GrD3DTexture::MakeNewTexture(GrD3DGpu* gpu, SkBudgeted budge sk_sp<GrD3DResourceState> state( new GrD3DResourceState(static_cast<D3D12_RESOURCE_STATES>(info.fResourceState))); + GrD3DDescriptorHeap::CPUHandle shaderResourceView = + gpu->resourceProvider().createShaderResourceView(info.fResource.get()); + GrD3DTexture* tex = new GrD3DTexture(gpu, budgeted, dimensions, info, std::move(state), - mipMapsStatus); + shaderResourceView, mipMapsStatus); return sk_sp<GrD3DTexture>(tex); } @@ -90,8 +100,12 @@ sk_sp<GrD3DTexture> GrD3DTexture::MakeWrappedTexture(GrD3DGpu* gpu, GrMipMapsStatus mipMapsStatus = info.fLevelCount > 1 ? GrMipMapsStatus::kValid : GrMipMapsStatus::kNotAllocated; + GrD3DDescriptorHeap::CPUHandle shaderResourceView = + gpu->resourceProvider().createShaderResourceView(info.fResource.get()); + return sk_sp<GrD3DTexture>(new GrD3DTexture(gpu, dimensions, info, std::move(state), - mipMapsStatus, cacheable, ioType)); + shaderResourceView, mipMapsStatus, cacheable, + ioType)); } void GrD3DTexture::onRelease() { @@ -103,7 +117,9 @@ void GrD3DTexture::onRelease() { this->removeFinishIdleProcs(); } - this->releaseResource(this->getD3DGpu()); + GrD3DGpu* gpu = this->getD3DGpu(); + gpu->resourceProvider().recycleConstantOrShaderView(fShaderResourceView); + this->releaseResource(gpu); INHERITED::onRelease(); } @@ -117,7 +133,9 @@ void GrD3DTexture::onAbandon() { this->removeFinishIdleProcs(); } - this->releaseResource(this->getD3DGpu()); + GrD3DGpu* gpu = this->getD3DGpu(); + gpu->resourceProvider().recycleConstantOrShaderView(fShaderResourceView); + this->releaseResource(gpu); INHERITED::onAbandon(); } diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.h index 704f1b2146d..e6e9b56a42a 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.h @@ -11,6 +11,7 @@ #include "src/core/SkLRUCache.h" #include "src/gpu/GrSamplerState.h" #include "src/gpu/GrTexture.h" +#include "src/gpu/d3d/GrD3DDescriptorHeap.h" #include "src/gpu/d3d/GrD3DTextureResource.h" class GrD3DTexture : public GrTexture, public virtual GrD3DTextureResource { @@ -34,6 +35,7 @@ public: GrBackendTexture getBackendTexture() const override; GrBackendFormat backendFormat() const override { return this->getBackendFormat(); } + D3D12_CPU_DESCRIPTOR_HANDLE shaderResourceView() { return fShaderResourceView.fHandle; } void textureParamsModified() override {} @@ -45,6 +47,7 @@ protected: SkISize dimensions, const GrD3DTextureResourceInfo&, sk_sp<GrD3DResourceState>, + const GrD3DDescriptorHeap::CPUHandle& shaderResourceView, GrMipMapsStatus); GrD3DGpu* getD3DGpu() const; @@ -60,9 +63,13 @@ protected: private: GrD3DTexture(GrD3DGpu*, SkBudgeted, SkISize dimensions, const GrD3DTextureResourceInfo&, - sk_sp<GrD3DResourceState>, GrMipMapsStatus); + sk_sp<GrD3DResourceState>, + const GrD3DDescriptorHeap::CPUHandle& shaderResourceView, + GrMipMapsStatus); GrD3DTexture(GrD3DGpu*, SkISize dimensions, const GrD3DTextureResourceInfo&, - sk_sp<GrD3DResourceState>, GrMipMapsStatus, GrWrapCacheable, GrIOType); + sk_sp<GrD3DResourceState>, + const GrD3DDescriptorHeap::CPUHandle& shaderResourceView, + GrMipMapsStatus, GrWrapCacheable, GrIOType); // In D3D we call the release proc after we are finished with the underlying // GrSurfaceResource::Resource object (which occurs after the GPU has finished all work on it). @@ -79,6 +86,8 @@ private: } }; + GrD3DDescriptorHeap::CPUHandle fShaderResourceView; + typedef GrTexture INHERITED; }; diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.cpp index 1aa178b5f61..f352e8d7954 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.cpp @@ -13,13 +13,14 @@ GrD3DTextureRenderTarget::GrD3DTextureRenderTarget( GrD3DGpu* gpu, SkBudgeted budgeted, SkISize dimensions, int sampleCnt, const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state, + const GrD3DDescriptorHeap::CPUHandle& shaderResourceView, const GrD3DTextureResourceInfo& msaaInfo, sk_sp<GrD3DResourceState> msaaState, - const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView, - const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView, + const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView, + const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView, GrMipMapsStatus mipMapsStatus) : GrSurface(gpu, dimensions, info.fProtected) , GrD3DTextureResource(info, state) - , GrD3DTexture(gpu, dimensions, info, state, mipMapsStatus) + , GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipMapsStatus) , GrD3DRenderTarget(gpu, dimensions, sampleCnt, info, state, msaaInfo, std::move(msaaState), colorRenderTargetView, resolveRenderTargetView) { SkASSERT(info.fProtected == msaaInfo.fProtected); @@ -29,11 +30,12 @@ GrD3DTextureRenderTarget::GrD3DTextureRenderTarget( GrD3DTextureRenderTarget::GrD3DTextureRenderTarget( GrD3DGpu* gpu, SkBudgeted budgeted, SkISize dimensions, const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state, - const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView, + const GrD3DDescriptorHeap::CPUHandle& shaderResourceView, + const GrD3DDescriptorHeap::CPUHandle& renderTargetView, GrMipMapsStatus mipMapsStatus) : GrSurface(gpu, dimensions, info.fProtected) , GrD3DTextureResource(info, state) - , GrD3DTexture(gpu, dimensions, info, state, mipMapsStatus) + , GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipMapsStatus) , GrD3DRenderTarget(gpu, dimensions, info, state, renderTargetView) { this->registerWithCache(budgeted); } @@ -41,14 +43,15 @@ GrD3DTextureRenderTarget::GrD3DTextureRenderTarget( GrD3DTextureRenderTarget::GrD3DTextureRenderTarget( GrD3DGpu* gpu, SkISize dimensions, int sampleCnt, const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state, + const GrD3DDescriptorHeap::CPUHandle& shaderResourceView, const GrD3DTextureResourceInfo& msaaInfo, sk_sp<GrD3DResourceState> msaaState, - const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView, - const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView, + const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView, + const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView, GrMipMapsStatus mipMapsStatus, GrWrapCacheable cacheable) : GrSurface(gpu, dimensions, info.fProtected) , GrD3DTextureResource(info, state) - , GrD3DTexture(gpu, dimensions, info, state, mipMapsStatus) + , GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipMapsStatus) , GrD3DRenderTarget(gpu, dimensions, sampleCnt, info, state, msaaInfo, std::move(msaaState), colorRenderTargetView, resolveRenderTargetView) { SkASSERT(info.fProtected == msaaInfo.fProtected); @@ -58,12 +61,13 @@ GrD3DTextureRenderTarget::GrD3DTextureRenderTarget( GrD3DTextureRenderTarget::GrD3DTextureRenderTarget( GrD3DGpu* gpu, SkISize dimensions, const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state, - const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView, + const GrD3DDescriptorHeap::CPUHandle& shaderResourceView, + const GrD3DDescriptorHeap::CPUHandle& renderTargetView, GrMipMapsStatus mipMapsStatus, GrWrapCacheable cacheable) : GrSurface(gpu, dimensions, info.fProtected) , GrD3DTextureResource(info, state) - , GrD3DTexture(gpu, dimensions, info, state, mipMapsStatus) + , GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipMapsStatus) , GrD3DRenderTarget(gpu, dimensions, info, state, renderTargetView) { this->registerWithCacheWrapped(cacheable); } @@ -134,8 +138,11 @@ sk_sp<GrD3DTextureRenderTarget> GrD3DTextureRenderTarget::MakeNewTextureRenderTa sk_sp<GrD3DResourceState> state(new GrD3DResourceState( static_cast<D3D12_RESOURCE_STATES>(info.fResourceState))); - const D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView = - gpu->resourceProvider().createRenderTargetView(info.fResource.get()); + const GrD3DDescriptorHeap::CPUHandle shaderResourceView = + gpu->resourceProvider().createShaderResourceView(info.fResource.get()); + + const GrD3DDescriptorHeap::CPUHandle renderTargetView = + gpu->resourceProvider().createRenderTargetView(info.fResource.get()); if (sampleCnt > 1) { GrD3DTextureResourceInfo msInfo; @@ -143,16 +150,17 @@ sk_sp<GrD3DTextureRenderTarget> GrD3DTextureRenderTarget::MakeNewTextureRenderTa std::tie(msInfo, msState) = create_msaa_resource(gpu, dimensions, sampleCnt, info); - const D3D12_CPU_DESCRIPTOR_HANDLE msaaRenderTargetView = - gpu->resourceProvider().createRenderTargetView(msInfo.fResource.get()); + const GrD3DDescriptorHeap::CPUHandle msaaRenderTargetView = + gpu->resourceProvider().createRenderTargetView(msInfo.fResource.get()); GrD3DTextureRenderTarget* trt = new GrD3DTextureRenderTarget( - gpu, budgeted, dimensions, sampleCnt, info, std::move(state), + gpu, budgeted, dimensions, sampleCnt, info, std::move(state), shaderResourceView, msInfo, std::move(msState), msaaRenderTargetView, renderTargetView, mipMapsStatus); return sk_sp<GrD3DTextureRenderTarget>(trt); } else { GrD3DTextureRenderTarget* trt = new GrD3DTextureRenderTarget( - gpu, budgeted, dimensions, info, std::move(state), renderTargetView, mipMapsStatus); + gpu, budgeted, dimensions, info, std::move(state), shaderResourceView, + renderTargetView, mipMapsStatus); return sk_sp<GrD3DTextureRenderTarget>(trt); } } @@ -172,25 +180,29 @@ sk_sp<GrD3DTextureRenderTarget> GrD3DTextureRenderTarget::MakeWrappedTextureRend GrMipMapsStatus mipMapsStatus = info.fLevelCount > 1 ? GrMipMapsStatus::kDirty : GrMipMapsStatus::kNotAllocated; - const D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView = - gpu->resourceProvider().createRenderTargetView(info.fResource.get()); + const GrD3DDescriptorHeap::CPUHandle shaderResourceView = + gpu->resourceProvider().createShaderResourceView(info.fResource.get()); + + const GrD3DDescriptorHeap::CPUHandle renderTargetView = + gpu->resourceProvider().createRenderTargetView(info.fResource.get()); if (sampleCnt > 1) { GrD3DTextureResourceInfo msInfo; sk_sp<GrD3DResourceState> msState; std::tie(msInfo, msState) = create_msaa_resource(gpu, dimensions, sampleCnt, info); - const D3D12_CPU_DESCRIPTOR_HANDLE msaaRenderTargetView = + const GrD3DDescriptorHeap::CPUHandle msaaRenderTargetView = gpu->resourceProvider().createRenderTargetView(msInfo.fResource.get()); GrD3DTextureRenderTarget* trt = new GrD3DTextureRenderTarget( - gpu, dimensions, sampleCnt, info, std::move(state), msInfo, std::move(msState), - msaaRenderTargetView, renderTargetView, mipMapsStatus, cacheable); + gpu, dimensions, sampleCnt, info, std::move(state), shaderResourceView, + msInfo, std::move(msState), msaaRenderTargetView, renderTargetView, mipMapsStatus, + cacheable); return sk_sp<GrD3DTextureRenderTarget>(trt); } else { return sk_sp<GrD3DTextureRenderTarget>(new GrD3DTextureRenderTarget( - gpu, dimensions, info, std::move(state), renderTargetView, mipMapsStatus, - cacheable)); + gpu, dimensions, info, std::move(state), shaderResourceView, renderTargetView, + mipMapsStatus, cacheable)); } } diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.h index 75ac076fb07..46d3ca5a3fc 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.h @@ -59,10 +59,11 @@ private: int sampleCnt, const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state, + const GrD3DDescriptorHeap::CPUHandle& shaderResourceView, const GrD3DTextureResourceInfo& msaaInfo, sk_sp<GrD3DResourceState> msaaState, - const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView, - const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView, + const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView, + const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView, GrMipMapsStatus); // non-MSAA, not-wrapped @@ -71,7 +72,8 @@ private: SkISize dimensions, const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state, - const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView, + const GrD3DDescriptorHeap::CPUHandle& shaderResourceView, + const GrD3DDescriptorHeap::CPUHandle& renderTargetView, GrMipMapsStatus); // MSAA, wrapped @@ -80,10 +82,11 @@ private: int sampleCnt, const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state, + const GrD3DDescriptorHeap::CPUHandle& shaderResourceView, const GrD3DTextureResourceInfo& msaaInfo, sk_sp<GrD3DResourceState> msaaState, - const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView, - const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView, + const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView, + const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView, GrMipMapsStatus, GrWrapCacheable); @@ -92,7 +95,8 @@ private: SkISize dimensions, const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state, - const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView, + const GrD3DDescriptorHeap::CPUHandle& shaderResourceView, + const GrD3DDescriptorHeap::CPUHandle& renderTargetView, GrMipMapsStatus, GrWrapCacheable); diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.cpp index a62f2d8554d..a307d110365 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.cpp @@ -16,14 +16,12 @@ void GrD3DTextureResource::setResourceState(const GrD3DGpu* gpu, return; } - SkAutoTMalloc<D3D12_RESOURCE_TRANSITION_BARRIER> barriers(fInfo.fLevelCount); - for (uint32_t mipLevel = 0; mipLevel < fInfo.fLevelCount; ++mipLevel) { - barriers[mipLevel].pResource = this->d3dResource(); - barriers[mipLevel].Subresource = mipLevel; - barriers[mipLevel].StateBefore = currentResourceState; - barriers[mipLevel].StateAfter = newResourceState; - } - gpu->addResourceBarriers(this->resource(), fInfo.fLevelCount, barriers.get()); + D3D12_RESOURCE_TRANSITION_BARRIER barrier; + barrier.pResource = this->d3dResource(); + barrier.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier.StateBefore = currentResourceState; + barrier.StateAfter = newResourceState; + gpu->addResourceBarriers(this->resource(), 1, &barrier); this->updateResourceState(newResourceState); } @@ -78,6 +76,10 @@ GrD3DTextureResource::~GrD3DTextureResource() { SkASSERT(!fResource); } +void GrD3DTextureResource::prepareForPresent(GrD3DGpu* gpu) { + this->setResourceState(gpu, D3D12_RESOURCE_STATE_PRESENT); +} + void GrD3DTextureResource::releaseResource(GrD3DGpu* gpu) { // TODO: do we need to migrate resource state if we change queues? if (fResource) { diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.h index bffb68988f3..6f091ea406b 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.h @@ -55,6 +55,9 @@ public: void setResourceState(const GrD3DGpu* gpu, D3D12_RESOURCE_STATES newResourceState); + // Changes the layout to present + void prepareForPresent(GrD3DGpu* gpu); + unsigned int sampleQualityLevel() const { return fInfo.fSampleQualityLevel; } // This simply updates our tracking of the resourceState and does not actually do any gpu work. diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.cpp index 521fd5d684d..dd66b8355be 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.cpp +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.cpp @@ -21,11 +21,3 @@ bool GrDxgiFormatIsCompressed(DXGI_FORMAT format) { } SkUNREACHABLE; } - -SkImage::CompressionType GrDxgiFormatToCompressionType(DXGI_FORMAT format) { - switch (format) { - case DXGI_FORMAT_BC1_UNORM: return SkImage::CompressionType::kBC1_RGBA8_UNORM; - default: return SkImage::CompressionType::kNone; - } - SkUNREACHABLE; -} diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.h index b17f7a5dae8..c5aa209acf3 100644 --- a/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.h +++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.h @@ -18,11 +18,6 @@ */ bool GrDxgiFormatIsCompressed(DXGI_FORMAT); -/** - * Maps a dxgi format into the CompressionType enum if applicable. - */ -SkImage::CompressionType GrDxgiFormatToCompressionType(DXGI_FORMAT dxgiFormat); - static constexpr uint32_t GrDxgiFormatChannels(DXGI_FORMAT vkFormat) { switch (vkFormat) { case DXGI_FORMAT_R8G8B8A8_UNORM: return kRGBA_SkColorChannelFlags; diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.cpp b/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.cpp index 15c4d8941c7..41b9fd851a4 100644 --- a/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.cpp +++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.cpp @@ -38,10 +38,6 @@ bool GrDawnCaps::isFormatSRGB(const GrBackendFormat& format) const { return false; } -SkImage::CompressionType GrDawnCaps::compressionType(const GrBackendFormat& format) const { - return SkImage::CompressionType::kNone; -} - bool GrDawnCaps::isFormatTexturable(const GrBackendFormat& format) const { // Currently, all the formats in GrDawnFormatToPixelConfig are texturable. wgpu::TextureFormat dawnFormat; @@ -67,6 +63,7 @@ static GrSwizzle get_swizzle(const GrBackendFormat& format, GrColorType colorTyp if (!forOutput) { return GrSwizzle::RGB1(); } + break; default: return GrSwizzle::RGBA(); } @@ -88,6 +85,18 @@ bool GrDawnCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFo return isFormatRenderable(format, sampleCount); } +GrCaps::SurfaceReadPixelsSupport GrDawnCaps::surfaceSupportsReadPixels( + const GrSurface* surface) const { + // We currently support readbacks only from Textures and TextureRenderTargets. + return surface->asTexture() ? SurfaceReadPixelsSupport::kSupported + : SurfaceReadPixelsSupport::kUnsupported; +} + +bool GrDawnCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const { + // We currently support writePixels only to Textures and TextureRenderTargets. + return surface->asTexture() != nullptr; +} + size_t GrDawnCaps::bytesPerPixel(const GrBackendFormat& backendFormat) const { wgpu::TextureFormat dawnFormat; if (!backendFormat.asDawnFormat(&dawnFormat)) { @@ -122,7 +131,7 @@ GrBackendFormat GrDawnCaps::getBackendFormatFromCompressionType(SkImage::Compres return GrBackendFormat(); } -GrSwizzle GrDawnCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const +GrSwizzle GrDawnCaps::onGetReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const { return get_swizzle(format, colorType, false); } diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.h b/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.h index c6922a9855e..fc2f8b52ed2 100644 --- a/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.h +++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.h @@ -18,7 +18,6 @@ public: GrDawnCaps(const GrContextOptions& contextOptions); bool isFormatSRGB(const GrBackendFormat&) const override; - SkImage::CompressionType compressionType(const GrBackendFormat&) const override; bool isFormatRenderable(const GrBackendFormat& format, int sampleCount = 1) const override; @@ -36,9 +35,7 @@ public: return {surfaceColorType, GrColorTypeBytesPerPixel(surfaceColorType)}; } - SurfaceReadPixelsSupport surfaceSupportsReadPixels(const GrSurface*) const override { - return SurfaceReadPixelsSupport::kSupported; - } + SurfaceReadPixelsSupport surfaceSupportsReadPixels(const GrSurface*) const override; size_t bytesPerPixel(const GrBackendFormat&) const override; @@ -49,8 +46,6 @@ public: GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override; - GrSwizzle getReadSwizzle(const GrBackendFormat&, GrColorType) const override; - GrSwizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override; uint64_t computeFormatKey(const GrBackendFormat&) const override; @@ -62,9 +57,7 @@ public: #endif private: - bool onSurfaceSupportsWritePixels(const GrSurface* surface) const override { - return true; - } + bool onSurfaceSupportsWritePixels(const GrSurface* surface) const override; bool onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) const override { return true; @@ -79,6 +72,8 @@ private: return { srcColorType, GrColorTypeBytesPerPixel(srcColorType) }; } + GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override; + typedef GrCaps INHERITED; }; diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.cpp b/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.cpp index cc0f446134c..f35a2e7e630 100644 --- a/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.cpp +++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.cpp @@ -10,6 +10,7 @@ #include "include/gpu/GrBackendSemaphore.h" #include "include/gpu/GrBackendSurface.h" #include "include/gpu/GrContextOptions.h" +#include "src/gpu/GrDataUtils.h" #include "src/gpu/GrGeometryProcessor.h" #include "src/gpu/GrGpuResourceCacheAccess.h" #include "src/gpu/GrPipeline.h" @@ -92,7 +93,6 @@ static wgpu::AddressMode to_dawn_address_mode(GrSamplerState::WrapMode wrapMode) } SkASSERT(!"unsupported address mode"); return wgpu::AddressMode::ClampToEdge; - } sk_sp<GrGpu> GrDawnGpu::Make(const wgpu::Device& device, @@ -124,20 +124,22 @@ GrDawnGpu::~GrDawnGpu() { } } - void GrDawnGpu::disconnect(DisconnectType type) { if (DisconnectType::kCleanup == type) { while (!this->busyStagingBuffers().isEmpty()) { fDevice.Tick(); } } + fQueue = nullptr; + fDevice = nullptr; INHERITED::disconnect(type); } /////////////////////////////////////////////////////////////////////////////// GrOpsRenderPass* GrDawnGpu::getOpsRenderPass( - GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds, + GrRenderTarget* rt, GrStencilAttachment*, + GrSurfaceOrigin origin, const SkIRect& bounds, const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) { @@ -193,7 +195,10 @@ sk_sp<GrTexture> GrDawnGpu::onCreateTexture(SkISize dimensions, GrProtected, int mipLevelCount, uint32_t levelClearMask) { - SkASSERT(!levelClearMask); + if (levelClearMask) { + return nullptr; + } + wgpu::TextureFormat format; if (!backendFormat.asDawnFormat(&format)) { return nullptr; @@ -353,7 +358,13 @@ bool GrDawnGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture, pixels = data->pixmap(0).addr(); } else { pixels = defaultStorage.get(); - memset(defaultStorage.get(), 0, baseLayerSize); + GrColorType colorType; + if (!GrDawnFormatToGrColorType(info.fFormat, &colorType)) { + return false; + } + SkISize size{backendTexture.width(), backendTexture.height()}; + GrImageInfo imageInfo(colorType, kUnpremul_SkAlphaType, nullptr, size); + GrClearImage(imageInfo, defaultStorage.get(), bpp * backendTexture.width(), data->color()); } wgpu::Device device = this->device(); wgpu::CommandEncoder copyEncoder = this->getCopyEncoder(); @@ -530,7 +541,6 @@ bool GrDawnGpu::onReadPixels(GrSurface* surface, int left, int top, int width, i GrColorType surfaceColorType, GrColorType dstColorType, void* buffer, size_t rowBytes) { wgpu::Texture tex = get_dawn_texture_from_surface(surface); - SkASSERT(tex); if (!tex || 0 == rowBytes) { return false; @@ -638,7 +648,6 @@ std::unique_ptr<GrSemaphore> GrDawnGpu::prepareTextureForCrossContextUsage(GrTex sk_sp<GrDawnProgram> GrDawnGpu::getOrCreateRenderPipeline( GrRenderTarget* rt, const GrProgramInfo& programInfo) { - GrProgramDesc desc = this->caps()->makeDesc(rt, programInfo); if (!desc.isValid()) { return nullptr; diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.h b/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.h index ac4f983bb62..fd09f9e5f56 100644 --- a/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.h +++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.h @@ -61,7 +61,8 @@ public: int numStencilSamples) override; GrOpsRenderPass* getOpsRenderPass( - GrRenderTarget*, GrSurfaceOrigin, const SkIRect& bounds, + GrRenderTarget*, GrStencilAttachment*, + GrSurfaceOrigin, const SkIRect& bounds, const GrOpsRenderPass::LoadAndStoreInfo&, const GrOpsRenderPass::StencilLoadAndStoreInfo&, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override; diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.cpp b/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.cpp index 8c23a31d973..ba4c73e77ac 100644 --- a/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.cpp +++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.cpp @@ -7,7 +7,6 @@ #include "src/gpu/dawn/GrDawnOpsRenderPass.h" -#include "src/gpu/GrFixedClip.h" #include "src/gpu/GrOpFlushState.h" #include "src/gpu/GrPipeline.h" #include "src/gpu/GrRenderTargetPriv.h" @@ -94,12 +93,15 @@ void GrDawnOpsRenderPass::submit() { fGpu->appendCommandBuffer(fEncoder.Finish()); } -void GrDawnOpsRenderPass::onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) { +void GrDawnOpsRenderPass::onClearStencilClip(const GrScissorState& scissor, + bool insideStencilMask) { + SkASSERT(!scissor.enabled()); fPassEncoder.EndPass(); fPassEncoder = beginRenderPass(wgpu::LoadOp::Load, wgpu::LoadOp::Clear); } -void GrDawnOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& color) { +void GrDawnOpsRenderPass::onClear(const GrScissorState& scissor, const SkPMColor4f& color) { + SkASSERT(!scissor.enabled()); fPassEncoder.EndPass(); fPassEncoder = beginRenderPass(wgpu::LoadOp::Clear, wgpu::LoadOp::Load); } @@ -108,7 +110,8 @@ void GrDawnOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& co void GrDawnOpsRenderPass::inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) { - SkASSERT(!"unimplemented"); + fGpu->submitToGpu(false); + state->doUpload(upload); } //////////////////////////////////////////////////////////////////////////////// @@ -144,20 +147,22 @@ bool GrDawnOpsRenderPass::onBindPipeline(const GrProgramInfo& programInfo, } void GrDawnOpsRenderPass::onSetScissorRect(const SkIRect& scissor) { - SkIRect rect; - SkIRect currentPipelineBounds = - SkIRect::MakeWH(fRenderTarget->width(), fRenderTarget->height()); - if (!rect.intersect(currentPipelineBounds, scissor)) { - rect = SkIRect::MakeEmpty(); - } - fPassEncoder.SetScissorRect(rect.x(), rect.y(), rect.width(), rect.height()); + // Higher-level GrRenderTargetContext and clips should have already ensured draw bounds are + // restricted to the render target. This is a sanity check. + SkASSERT(SkIRect::MakeSize(fRenderTarget->dimensions()).contains(scissor)); + auto nativeScissorRect = + GrNativeRect::MakeRelativeTo(fOrigin, fRenderTarget->height(), scissor); + fPassEncoder.SetScissorRect(nativeScissorRect.fX, nativeScissorRect.fY, + nativeScissorRect.fWidth, nativeScissorRect.fHeight); } bool GrDawnOpsRenderPass::onBindTextures(const GrPrimitiveProcessor& primProc, const GrSurfaceProxy* const primProcTextures[], const GrPipeline& pipeline) { auto bindGroup = fCurrentProgram->setTextures(fGpu, primProc, pipeline, primProcTextures); - fPassEncoder.SetBindGroup(1, bindGroup, 0, nullptr); + if (bindGroup) { + fPassEncoder.SetBindGroup(1, bindGroup, 0, nullptr); + } return true; } diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.h b/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.h index 8ab0c771445..1f7b70f25ea 100644 --- a/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.h +++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.h @@ -51,9 +51,9 @@ private: void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance, int baseVertex) override; - void onClear(const GrFixedClip&, const SkPMColor4f& color) override; + void onClear(const GrScissorState& scissor, const SkPMColor4f& color) override; - void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) override; + void onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) override; struct InlineUploadInfo { InlineUploadInfo(GrOpFlushState* state, const GrDeferredTextureUploadFn& upload) diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.cpp b/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.cpp index 95d85fb7501..1008eac3d0b 100644 --- a/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.cpp +++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.cpp @@ -325,29 +325,32 @@ sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu, if (0 != uniformBufferSize) { uniformLayoutEntries.push_back({ GrSPIRVUniformHandler::kUniformBinding, wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment, - wgpu::BindingType::UniformBuffer}); + wgpu::BindingType::UniformBuffer }); } wgpu::BindGroupLayoutDescriptor uniformBindGroupLayoutDesc; uniformBindGroupLayoutDesc.entryCount = uniformLayoutEntries.size(); uniformBindGroupLayoutDesc.entries = uniformLayoutEntries.data(); - result->fBindGroupLayouts[0] = - gpu->device().CreateBindGroupLayout(&uniformBindGroupLayoutDesc); + result->fBindGroupLayouts.push_back( + gpu->device().CreateBindGroupLayout(&uniformBindGroupLayoutDesc)); uint32_t binding = 0; std::vector<wgpu::BindGroupLayoutEntry> textureLayoutEntries; - for (int i = 0; i < builder.fUniformHandler.fSamplers.count(); ++i) { - textureLayoutEntries.push_back({ binding++, wgpu::ShaderStage::Fragment, - wgpu::BindingType::Sampler}); - textureLayoutEntries.push_back({ binding++, wgpu::ShaderStage::Fragment, - wgpu::BindingType::SampledTexture}); + int textureCount = builder.fUniformHandler.fSamplers.count(); + if (textureCount > 0) { + for (int i = 0; i < textureCount; ++i) { + textureLayoutEntries.push_back({ binding++, wgpu::ShaderStage::Fragment, + wgpu::BindingType::Sampler }); + textureLayoutEntries.push_back({ binding++, wgpu::ShaderStage::Fragment, + wgpu::BindingType::SampledTexture }); + } + wgpu::BindGroupLayoutDescriptor textureBindGroupLayoutDesc; + textureBindGroupLayoutDesc.entryCount = textureLayoutEntries.size(); + textureBindGroupLayoutDesc.entries = textureLayoutEntries.data(); + result->fBindGroupLayouts.push_back( + gpu->device().CreateBindGroupLayout(&textureBindGroupLayoutDesc)); } - wgpu::BindGroupLayoutDescriptor textureBindGroupLayoutDesc; - textureBindGroupLayoutDesc.entryCount = textureLayoutEntries.size(); - textureBindGroupLayoutDesc.entries = textureLayoutEntries.data(); - result->fBindGroupLayouts[1] = - gpu->device().CreateBindGroupLayout(&textureBindGroupLayoutDesc); wgpu::PipelineLayoutDescriptor pipelineLayoutDesc; - pipelineLayoutDesc.bindGroupLayoutCount = 2; - pipelineLayoutDesc.bindGroupLayouts = &result->fBindGroupLayouts[0]; + pipelineLayoutDesc.bindGroupLayoutCount = result->fBindGroupLayouts.size(); + pipelineLayoutDesc.bindGroupLayouts = result->fBindGroupLayouts.data(); auto pipelineLayout = gpu->device().CreatePipelineLayout(&pipelineLayoutDesc); result->fBuiltinUniformHandles = builder.fUniformHandles; const GrPipeline& pipeline = programInfo.pipeline(); @@ -365,9 +368,9 @@ sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu, std::vector<wgpu::VertexAttributeDescriptor> vertexAttributes; const GrPrimitiveProcessor& primProc = programInfo.primProc(); + int i = 0; if (primProc.numVertexAttributes() > 0) { size_t offset = 0; - int i = 0; for (const auto& attrib : primProc.vertexAttributes()) { wgpu::VertexAttributeDescriptor attribute; attribute.shaderLocation = i; @@ -387,7 +390,6 @@ sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu, std::vector<wgpu::VertexAttributeDescriptor> instanceAttributes; if (primProc.numInstanceAttributes() > 0) { size_t offset = 0; - int i = 0; for (const auto& attrib : primProc.instanceAttributes()) { wgpu::VertexAttributeDescriptor attribute; attribute.shaderLocation = i; @@ -543,6 +545,9 @@ wgpu::BindGroup GrDawnProgram::setTextures(GrDawnGpu* gpu, const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, const GrSurfaceProxy* const primProcTextures[]) { + if (fBindGroupLayouts.size() < 2) { + return nullptr; + } std::vector<wgpu::BindGroupEntry> bindings; int binding = 0; if (primProcTextures) { diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.h b/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.h index b4f75d4e058..af707843b65 100644 --- a/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.h +++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.h @@ -57,7 +57,7 @@ struct GrDawnProgram : public SkRefCnt { std::unique_ptr<GrGLSLXferProcessor> fXferProcessor; std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fFragmentProcessors; int fFragmentProcessorCnt; - wgpu::BindGroupLayout fBindGroupLayouts[2]; + std::vector<wgpu::BindGroupLayout> fBindGroupLayouts; wgpu::RenderPipeline fRenderPipeline; GrDawnProgramDataManager fDataManager; RenderTargetState fRenderTargetState; diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.cpp b/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.cpp index 9f6daec00cc..91b155d8e76 100644 --- a/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.cpp +++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.cpp @@ -45,6 +45,22 @@ bool GrColorTypeToDawnFormat(GrColorType ct, wgpu::TextureFormat* format) { } } +bool GrDawnFormatToGrColorType(wgpu::TextureFormat format, GrColorType* colorType) { + switch (format) { + case wgpu::TextureFormat::RGBA8Unorm: + *colorType = GrColorType::kRGBA_8888; + return true; + case wgpu::TextureFormat::BGRA8Unorm: + *colorType = GrColorType::kBGRA_8888; + return true; + case wgpu::TextureFormat::R8Unorm: + *colorType = GrColorType::kR_8; + return true; + default: + return false; + } +} + size_t GrDawnRoundRowBytes(size_t rowBytes) { // Dawn requires that rowBytes be a multiple of 256. (This is actually imposed by D3D12.) return (rowBytes + 0xFF) & ~0xFF; diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.h b/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.h index 7b5ac6c5715..6f090ffe4a1 100644 --- a/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.h +++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.h @@ -14,6 +14,7 @@ size_t GrDawnBytesPerPixel(wgpu::TextureFormat format); bool GrDawnFormatIsRenderable(wgpu::TextureFormat format); bool GrColorTypeToDawnFormat(GrColorType colorType, wgpu::TextureFormat* format); +bool GrDawnFormatToGrColorType(wgpu::TextureFormat format, GrColorType* colorType); size_t GrDawnRoundRowBytes(size_t rowBytes); #if GR_TEST_UTILS const char* GrDawnFormatToStr(wgpu::TextureFormat format); diff --git a/chromium/third_party/skia/src/gpu/effects/GrAARectEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrAARectEffect.fp index 856b761a0f5..6a66a69d732 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrAARectEffect.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrAARectEffect.fp @@ -5,12 +5,16 @@ * found in the LICENSE file. */ +in fragmentProcessor? inputFP; layout(key) in GrClipEdgeType edgeType; layout(ctype=SkRect) in float4 rect; layout(ctype=SkRect) float4 prevRect = float4(-1); uniform float4 rectUniform; -@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag } +@optimizationFlags { + (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) & + kCompatibleWithCoverageAsAlpha_OptimizationFlag +} void main() { half alpha; @@ -37,7 +41,8 @@ void main() { @if (edgeType == GrClipEdgeType::kInverseFillBW || edgeType == GrClipEdgeType::kInverseFillAA) { alpha = 1.0 - alpha; } - sk_OutColor = sk_InColor * alpha; + half4 inputColor = sample(inputFP, sk_InColor); + sk_OutColor = inputColor * alpha; } @setData(pdman) { @@ -59,7 +64,7 @@ void main() { GrClipEdgeType edgeType = static_cast<GrClipEdgeType>( d->fRandom->nextULessThan(kGrClipEdgeTypeCnt)); - fp = GrAARectEffect::Make(edgeType, rect); + fp = GrAARectEffect::Make(/*inputFP=*/nullptr, edgeType, rect); } while (nullptr == fp); return fp; } diff --git a/chromium/third_party/skia/src/gpu/effects/GrAlphaThresholdFragmentProcessor.fp b/chromium/third_party/skia/src/gpu/effects/GrAlphaThresholdFragmentProcessor.fp index 4eb3a4eeeff..24aaf921c7e 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrAlphaThresholdFragmentProcessor.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrAlphaThresholdFragmentProcessor.fp @@ -5,47 +5,19 @@ * found in the LICENSE file. */ -in uniform sampler2D mask; +in fragmentProcessor? inputFP; +in fragmentProcessor maskFP; in uniform half innerThreshold; in uniform half outerThreshold; -@class { - inline OptimizationFlags optFlags(float outerThreshold); -} - -@constructorParams { - const SkIRect& bounds -} - -@make { - static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView mask, - float innerThreshold, - float outerThreshold, - const SkIRect& bounds) { - return std::unique_ptr<GrFragmentProcessor>(new GrAlphaThresholdFragmentProcessor( - std::move(mask), innerThreshold, outerThreshold, bounds)); - } -} - -@coordTransform(mask) { - SkMatrix::MakeTrans(SkIntToScalar(-bounds.x()), SkIntToScalar(-bounds.y())) -} - -@cpp { - inline GrFragmentProcessor::OptimizationFlags GrAlphaThresholdFragmentProcessor::optFlags( - float outerThreshold) { - if (outerThreshold >= 1.0) { - return kPreservesOpaqueInput_OptimizationFlag | - kCompatibleWithCoverageAsAlpha_OptimizationFlag; - } else { - return kCompatibleWithCoverageAsAlpha_OptimizationFlag; - } - } +@optimizationFlags { + (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) & + ((outerThreshold >= 1.0) ? kPreservesOpaqueInput_OptimizationFlag : kNone_OptimizationFlags) } void main() { - half4 color = sk_InColor; - half4 mask_color = sample(mask, sk_TransformedCoords2D[0]); + half4 color = sample(inputFP, sk_InColor); + half4 mask_color = sample(maskFP); if (mask_color.a < 0.5) { if (color.a > outerThreshold) { half scale = outerThreshold / color.a; @@ -61,18 +33,15 @@ void main() { } @test(testData) { - auto [maskView, ct, at] = testData->randomAlphaOnlyView(); - // Make the inner and outer thresholds be in (0, 1) exclusive and be sorted correctly. - float innerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f; - float outerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f; - const int kMaxWidth = 1000; - const int kMaxHeight = 1000; - uint32_t width = testData->fRandom->nextULessThan(kMaxWidth); - uint32_t height = testData->fRandom->nextULessThan(kMaxHeight); - uint32_t x = testData->fRandom->nextULessThan(kMaxWidth - width); - uint32_t y = testData->fRandom->nextULessThan(kMaxHeight - height); - SkIRect bounds = SkIRect::MakeXYWH(x, y, width, height); + // Make the inner and outer thresholds be in [0, 1]. + float outerThresh = testData->fRandom->nextUScalar1(); + float innerThresh = testData->fRandom->nextUScalar1(); + std::unique_ptr<GrFragmentProcessor> inputChild, maskChild; + if (testData->fRandom->nextBool()) { + inputChild = GrProcessorUnitTest::MakeChildFP(testData); + } + maskChild = GrProcessorUnitTest::MakeChildFP(testData); - return GrAlphaThresholdFragmentProcessor::Make(std::move(maskView), innerThresh, outerThresh, - bounds); + return GrAlphaThresholdFragmentProcessor::Make(std::move(inputChild), std::move(maskChild), + innerThresh, outerThresh); } diff --git a/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.cpp index 2fc715c70f2..e127ab4a0d3 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.cpp @@ -28,12 +28,8 @@ public: const CoordTransformRange& transformRange) override { const GrConicEffect& ce = primProc.cast<GrConicEffect>(); - if (!ce.viewMatrix().isIdentity() && - !SkMatrixPriv::CheapEqual(fViewMatrix, ce.viewMatrix())) - { - fViewMatrix = ce.viewMatrix(); - pdman.setSkMatrix(fViewMatrixUniform, fViewMatrix); - } + this->setTransform(pdman, fViewMatrixUniform, ce.viewMatrix(), &fViewMatrix); + this->setTransform(pdman, fLocalMatrixUniform, ce.localMatrix(), &fLocalMatrix); if (ce.color() != fColor) { pdman.set4fv(fColorUniform, 1, ce.color().vec()); @@ -44,26 +40,27 @@ public: pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(ce.coverageScale())); fCoverageScale = ce.coverageScale(); } - this->setTransformDataHelper(ce.localMatrix(), pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); } private: SkMatrix fViewMatrix; + SkMatrix fLocalMatrix; SkPMColor4f fColor; uint8_t fCoverageScale; - GrClipEdgeType fEdgeType; UniformHandle fColorUniform; UniformHandle fCoverageScaleUniform; UniformHandle fViewMatrixUniform; + UniformHandle fLocalMatrixUniform; typedef GrGLSLGeometryProcessor INHERITED; }; GrGLConicEffect::GrGLConicEffect(const GrGeometryProcessor& processor) - : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(SK_PMColor4fILLEGAL), fCoverageScale(0xff) { - const GrConicEffect& ce = processor.cast<GrConicEffect>(); - fEdgeType = ce.getEdgeType(); -} + : fViewMatrix(SkMatrix::InvalidMatrix()) + , fLocalMatrix(SkMatrix::InvalidMatrix()) + , fColor(SK_PMColor4fILLEGAL) + , fCoverageScale(0xff) {} void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; @@ -89,14 +86,10 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { gp.inPosition().name(), gp.viewMatrix(), &fViewMatrixUniform); - - // emit transforms with position - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - gp.inPosition().asShaderVar(), - gp.localMatrix(), - args.fFPCoordTransformHandler); + if (gp.usesLocalCoords()) { + this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, gp.inPosition().asShaderVar(), + gp.localMatrix(), &fLocalMatrixUniform); + } // TODO: we should check on the number of bits float and half provide and use the smallest one // that suffices. Additionally we should assert that the upstream code only lets us get here if @@ -120,74 +113,31 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { fragBuilder->declAppend(gFM); fragBuilder->declAppend(func); - switch (fEdgeType) { - case GrClipEdgeType::kHairlineAA: { - fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn()); - fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn()); - fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;", - dfdx.c_str(), - v.fsIn(), dklmdx.c_str(), - v.fsIn(), dklmdx.c_str(), - v.fsIn(), dklmdx.c_str()); - fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;", - dfdy.c_str(), - v.fsIn(), dklmdy.c_str(), - v.fsIn(), dklmdy.c_str(), - v.fsIn(), dklmdy.c_str()); - fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(), - dfdy.c_str()); - fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));", - gFM.c_str(), gF.c_str(), gF.c_str()); - fragBuilder->codeAppendf("%s = %s.x*%s.x - %s.y*%s.z;", - func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn()); - fragBuilder->codeAppendf("%s = abs(%s);", func.c_str(), func.c_str()); - fragBuilder->codeAppendf("%s = half(%s / %s);", - edgeAlpha.c_str(), func.c_str(), gFM.c_str()); - fragBuilder->codeAppendf("%s = max(1.0 - %s, 0.0);", - edgeAlpha.c_str(), edgeAlpha.c_str()); - // Add line below for smooth cubic ramp - // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); - break; - } - case GrClipEdgeType::kFillAA: { - fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn()); - fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn()); - fragBuilder->codeAppendf("%s =" - "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;", - dfdx.c_str(), - v.fsIn(), dklmdx.c_str(), - v.fsIn(), dklmdx.c_str(), - v.fsIn(), dklmdx.c_str()); - fragBuilder->codeAppendf("%s =" - "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;", - dfdy.c_str(), - v.fsIn(), dklmdy.c_str(), - v.fsIn(), dklmdy.c_str(), - v.fsIn(), dklmdy.c_str()); - fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(), - dfdy.c_str()); - fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));", - gFM.c_str(), gF.c_str(), gF.c_str()); - fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;", - func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn()); - fragBuilder->codeAppendf("%s = half(%s / %s);", - edgeAlpha.c_str(), func.c_str(), gFM.c_str()); - fragBuilder->codeAppendf("%s = saturate(0.5 - %s);", - edgeAlpha.c_str(), edgeAlpha.c_str()); - // Add line below for smooth cubic ramp - // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); - break; - } - case GrClipEdgeType::kFillBW: { - fragBuilder->codeAppendf("%s = half(%s.x * %s.x - %s.y * %s.z);", - edgeAlpha.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn()); - fragBuilder->codeAppendf("%s = half(%s < 0.0);", - edgeAlpha.c_str(), edgeAlpha.c_str()); - break; - } - default: - SK_ABORT("Shouldn't get here"); - } + fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn()); + fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn()); + fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;", + dfdx.c_str(), + v.fsIn(), dklmdx.c_str(), + v.fsIn(), dklmdx.c_str(), + v.fsIn(), dklmdx.c_str()); + fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;", + dfdy.c_str(), + v.fsIn(), dklmdy.c_str(), + v.fsIn(), dklmdy.c_str(), + v.fsIn(), dklmdy.c_str()); + fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(), + dfdy.c_str()); + fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));", + gFM.c_str(), gF.c_str(), gF.c_str()); + fragBuilder->codeAppendf("%s = %s.x*%s.x - %s.y*%s.z;", + func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn()); + fragBuilder->codeAppendf("%s = abs(%s);", func.c_str(), func.c_str()); + fragBuilder->codeAppendf("%s = half(%s / %s);", + edgeAlpha.c_str(), func.c_str(), gFM.c_str()); + fragBuilder->codeAppendf("%s = max(1.0 - %s, 0.0);", + edgeAlpha.c_str(), edgeAlpha.c_str()); + // Add line below for smooth cubic ramp + // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); // TODO should we really be doing this? if (gp.coverageScale() != 0xff) { @@ -210,8 +160,9 @@ void GrGLConicEffect::GenKey(const GrGeometryProcessor& gp, const GrConicEffect& ce = gp.cast<GrConicEffect>(); uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2; key |= 0xff != ce.coverageScale() ? 0x8 : 0x0; - key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0; - key |= ComputePosKey(ce.viewMatrix()) << 5; + key |= ce.usesLocalCoords() ? 0x10 : 0x0; + key = AddMatrixKeys(key, ce.viewMatrix(), ce.usesLocalCoords() ? ce.localMatrix() + : SkMatrix::I()); b->add32(key); } @@ -231,15 +182,13 @@ GrGLSLPrimitiveProcessor* GrConicEffect::createGLSLInstance(const GrShaderCaps&) } GrConicEffect::GrConicEffect(const SkPMColor4f& color, const SkMatrix& viewMatrix, uint8_t coverage, - GrClipEdgeType edgeType, const SkMatrix& localMatrix, - bool usesLocalCoords) + const SkMatrix& localMatrix, bool usesLocalCoords) : INHERITED(kGrConicEffect_ClassID) , fColor(color) , fViewMatrix(viewMatrix) , fLocalMatrix(viewMatrix) , fUsesLocalCoords(usesLocalCoords) - , fCoverageScale(coverage) - , fEdgeType(edgeType) { + , fCoverageScale(coverage) { this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes)); } @@ -249,17 +198,10 @@ GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrConicEffect); #if GR_TEST_UTILS GrGeometryProcessor* GrConicEffect::TestCreate(GrProcessorTestData* d) { - GrGeometryProcessor* gp; - do { - GrClipEdgeType edgeType = - static_cast<GrClipEdgeType>( - d->fRandom->nextULessThan(kGrClipEdgeTypeCnt)); - gp = GrConicEffect::Make(d->allocator(), - SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)), - GrTest::TestMatrix(d->fRandom), edgeType, *d->caps(), - GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool()); - } while (nullptr == gp); - return gp; + return GrConicEffect::Make(d->allocator(), + SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)), + GrTest::TestMatrix(d->fRandom), *d->caps(), + GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool()); } #endif @@ -281,12 +223,8 @@ public: const CoordTransformRange& transformRange) override { const GrQuadEffect& qe = primProc.cast<GrQuadEffect>(); - if (!qe.viewMatrix().isIdentity() && - !SkMatrixPriv::CheapEqual(fViewMatrix, qe.viewMatrix())) - { - fViewMatrix = qe.viewMatrix(); - pdman.setSkMatrix(fViewMatrixUniform, fViewMatrix); - } + this->setTransform(pdman, fViewMatrixUniform, qe.viewMatrix(), &fViewMatrix); + this->setTransform(pdman, fLocalMatrixUniform, qe.localMatrix(), &fLocalMatrix); if (qe.color() != fColor) { pdman.set4fv(fColorUniform, 1, qe.color().vec()); @@ -297,26 +235,28 @@ public: pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(qe.coverageScale())); fCoverageScale = qe.coverageScale(); } - this->setTransformDataHelper(qe.localMatrix(), pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); } private: SkMatrix fViewMatrix; + SkMatrix fLocalMatrix; SkPMColor4f fColor; uint8_t fCoverageScale; - GrClipEdgeType fEdgeType; + UniformHandle fColorUniform; UniformHandle fCoverageScaleUniform; UniformHandle fViewMatrixUniform; + UniformHandle fLocalMatrixUniform; typedef GrGLSLGeometryProcessor INHERITED; }; GrGLQuadEffect::GrGLQuadEffect(const GrGeometryProcessor& processor) - : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(SK_PMColor4fILLEGAL), fCoverageScale(0xff) { - const GrQuadEffect& ce = processor.cast<GrQuadEffect>(); - fEdgeType = ce.getEdgeType(); -} + : fViewMatrix(SkMatrix::InvalidMatrix()) + , fLocalMatrix(SkMatrix::InvalidMatrix()) + , fColor(SK_PMColor4fILLEGAL) + , fCoverageScale(0xff) {} void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; @@ -342,55 +282,24 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { gp.inPosition().name(), gp.viewMatrix(), &fViewMatrixUniform); - - // emit transforms with position - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - gp.inPosition().asShaderVar(), - gp.localMatrix(), - args.fFPCoordTransformHandler); + if (gp.usesLocalCoords()) { + this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, gp.inPosition().asShaderVar(), + gp.localMatrix(), &fLocalMatrixUniform); + } fragBuilder->codeAppendf("half edgeAlpha;"); - switch (fEdgeType) { - case GrClipEdgeType::kHairlineAA: { - fragBuilder->codeAppendf("half2 duvdx = half2(dFdx(%s.xy));", v.fsIn()); - fragBuilder->codeAppendf("half2 duvdy = half2(dFdy(%s.xy));", v.fsIn()); - fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y," - " 2.0 * %s.x * duvdy.x - duvdy.y);", - v.fsIn(), v.fsIn()); - fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);", - v.fsIn(), v.fsIn(), v.fsIn()); - fragBuilder->codeAppend("edgeAlpha = sqrt(edgeAlpha * edgeAlpha / dot(gF, gF));"); - fragBuilder->codeAppend("edgeAlpha = max(1.0 - edgeAlpha, 0.0);"); - // Add line below for smooth cubic ramp - // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); - break; - } - case GrClipEdgeType::kFillAA: { - fragBuilder->codeAppendf("half2 duvdx = half2(dFdx(%s.xy));", v.fsIn()); - fragBuilder->codeAppendf("half2 duvdy = half2(dFdy(%s.xy));", v.fsIn()); - fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y," - " 2.0 * %s.x * duvdy.x - duvdy.y);", - v.fsIn(), v.fsIn()); - fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);", - v.fsIn(), v.fsIn(), v.fsIn()); - fragBuilder->codeAppend("edgeAlpha = edgeAlpha / sqrt(dot(gF, gF));"); - fragBuilder->codeAppend("edgeAlpha = saturate(0.5 - edgeAlpha);"); - // Add line below for smooth cubic ramp - // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); - break; - } - case GrClipEdgeType::kFillBW: { - fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);", - v.fsIn(), v.fsIn(), v.fsIn()); - fragBuilder->codeAppend("edgeAlpha = half(edgeAlpha < 0.0);"); - break; - } - default: - SK_ABORT("Shouldn't get here"); - } + fragBuilder->codeAppendf("half2 duvdx = half2(dFdx(%s.xy));", v.fsIn()); + fragBuilder->codeAppendf("half2 duvdy = half2(dFdy(%s.xy));", v.fsIn()); + fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y," + " 2.0 * %s.x * duvdy.x - duvdy.y);", + v.fsIn(), v.fsIn()); + fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);", + v.fsIn(), v.fsIn(), v.fsIn()); + fragBuilder->codeAppend("edgeAlpha = sqrt(edgeAlpha * edgeAlpha / dot(gF, gF));"); + fragBuilder->codeAppend("edgeAlpha = max(1.0 - edgeAlpha, 0.0);"); + // Add line below for smooth cubic ramp + // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); if (0xff != gp.coverageScale()) { const char* coverageScale; @@ -412,8 +321,9 @@ void GrGLQuadEffect::GenKey(const GrGeometryProcessor& gp, const GrQuadEffect& ce = gp.cast<GrQuadEffect>(); uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2; key |= ce.coverageScale() != 0xff ? 0x8 : 0x0; - key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0; - key |= ComputePosKey(ce.viewMatrix()) << 5; + key |= ce.usesLocalCoords()? 0x10 : 0x0; + key = AddMatrixKeys(key, ce.viewMatrix(), ce.usesLocalCoords() ? ce.localMatrix() + : SkMatrix::I()); b->add32(key); } @@ -433,15 +343,13 @@ GrGLSLPrimitiveProcessor* GrQuadEffect::createGLSLInstance(const GrShaderCaps&) } GrQuadEffect::GrQuadEffect(const SkPMColor4f& color, const SkMatrix& viewMatrix, uint8_t coverage, - GrClipEdgeType edgeType, const SkMatrix& localMatrix, - bool usesLocalCoords) + const SkMatrix& localMatrix, bool usesLocalCoords) : INHERITED(kGrQuadEffect_ClassID) , fColor(color) , fViewMatrix(viewMatrix) , fLocalMatrix(localMatrix) , fUsesLocalCoords(usesLocalCoords) - , fCoverageScale(coverage) - , fEdgeType(edgeType) { + , fCoverageScale(coverage) { this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes)); } @@ -451,15 +359,9 @@ GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrQuadEffect); #if GR_TEST_UTILS GrGeometryProcessor* GrQuadEffect::TestCreate(GrProcessorTestData* d) { - GrGeometryProcessor* gp; - do { - GrClipEdgeType edgeType = static_cast<GrClipEdgeType>( - d->fRandom->nextULessThan(kGrClipEdgeTypeCnt)); - gp = GrQuadEffect::Make(d->allocator(), - SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)), - GrTest::TestMatrix(d->fRandom), edgeType, *d->caps(), - GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool()); - } while (nullptr == gp); - return gp; + return GrQuadEffect::Make(d->allocator(), + SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)), + GrTest::TestMatrix(d->fRandom), *d->caps(), + GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool()); } #endif diff --git a/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.h b/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.h index c59faebc5b3..87d3721a120 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.h @@ -61,25 +61,15 @@ public: static GrGeometryProcessor* Make(SkArenaAlloc* arena, const SkPMColor4f& color, const SkMatrix& viewMatrix, - const GrClipEdgeType edgeType, const GrCaps& caps, const SkMatrix& localMatrix, bool usesLocalCoords, uint8_t coverage = 0xff) { - switch (edgeType) { - case GrClipEdgeType::kFillAA: // fall through - case GrClipEdgeType::kHairlineAA: - if (!caps.shaderCaps()->shaderDerivativeSupport()) { - return nullptr; - } - break; - case GrClipEdgeType::kFillBW: - break; - default: // kInverseFillBW or kInverseFillAA - return nullptr; + if (!caps.shaderCaps()->shaderDerivativeSupport()) { + return nullptr; } - return arena->make<GrConicEffect>(color, viewMatrix, coverage, edgeType, localMatrix, + return arena->make<GrConicEffect>(color, viewMatrix, coverage, localMatrix, usesLocalCoords); } @@ -89,9 +79,8 @@ public: inline const Attribute& inPosition() const { return kAttributes[0]; } inline const Attribute& inConicCoeffs() const { return kAttributes[1]; } - inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); } - inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); } - inline GrClipEdgeType getEdgeType() const { return fEdgeType; } + inline bool isAntiAliased() const { return true; } + inline bool isFilled() const { return false; } const SkPMColor4f& color() const { return fColor; } const SkMatrix& viewMatrix() const { return fViewMatrix; } const SkMatrix& localMatrix() const { return fLocalMatrix; } @@ -105,7 +94,7 @@ public: private: friend class ::SkArenaAlloc; // for access to ctor - GrConicEffect(const SkPMColor4f&, const SkMatrix& viewMatrix, uint8_t coverage, GrClipEdgeType, + GrConicEffect(const SkPMColor4f&, const SkMatrix& viewMatrix, uint8_t coverage, const SkMatrix& localMatrix, bool usesLocalCoords); SkPMColor4f fColor; @@ -113,7 +102,6 @@ private: SkMatrix fLocalMatrix; bool fUsesLocalCoords; uint8_t fCoverageScale; - GrClipEdgeType fEdgeType; static constexpr Attribute kAttributes[] = { {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType}, {"inConicCoeffs", kFloat4_GrVertexAttribType, kHalf4_GrSLType} @@ -140,26 +128,15 @@ public: static GrGeometryProcessor* Make(SkArenaAlloc* arena, const SkPMColor4f& color, const SkMatrix& viewMatrix, - const GrClipEdgeType edgeType, const GrCaps& caps, const SkMatrix& localMatrix, bool usesLocalCoords, uint8_t coverage = 0xff) { - switch (edgeType) { - case GrClipEdgeType::kFillAA: // fall through - case GrClipEdgeType::kHairlineAA: - if (!caps.shaderCaps()->shaderDerivativeSupport()) { - return nullptr; - } - break; - case GrClipEdgeType::kFillBW: - break; - default: // kInverseFillBW and kInverseFillAA - return nullptr; + if (!caps.shaderCaps()->shaderDerivativeSupport()) { + return nullptr; } - return arena->make<GrQuadEffect>(color, viewMatrix, coverage, edgeType, - localMatrix, usesLocalCoords); + return arena->make<GrQuadEffect>(color, viewMatrix, coverage, localMatrix, usesLocalCoords); } ~GrQuadEffect() override; @@ -168,9 +145,8 @@ public: inline const Attribute& inPosition() const { return kAttributes[0]; } inline const Attribute& inHairQuadEdge() const { return kAttributes[1]; } - inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); } - inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); } - inline GrClipEdgeType getEdgeType() const { return fEdgeType; } + inline bool isAntiAliased() const { return true; } + inline bool isFilled() const { return false; } const SkPMColor4f& color() const { return fColor; } const SkMatrix& viewMatrix() const { return fViewMatrix; } const SkMatrix& localMatrix() const { return fLocalMatrix; } @@ -184,7 +160,7 @@ public: private: friend class ::SkArenaAlloc; // for access to ctor - GrQuadEffect(const SkPMColor4f&, const SkMatrix& viewMatrix, uint8_t coverage, GrClipEdgeType, + GrQuadEffect(const SkPMColor4f&, const SkMatrix& viewMatrix, uint8_t coverage, const SkMatrix& localMatrix, bool usesLocalCoords); SkPMColor4f fColor; @@ -192,7 +168,6 @@ private: SkMatrix fLocalMatrix; bool fUsesLocalCoords; uint8_t fCoverageScale; - GrClipEdgeType fEdgeType; static constexpr Attribute kAttributes[] = { {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType}, diff --git a/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.cpp index ef9560e57e8..d575668ba49 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.cpp @@ -176,9 +176,8 @@ GrBicubicEffect::GrBicubicEffect(std::unique_ptr<GrFragmentProcessor> fp, , fCoordTransform(matrix) , fDirection(direction) , fClamp(clamp) { - fp->setSampledWithExplicitCoords(); this->addCoordTransform(&fCoordTransform); - this->registerChildProcessor(std::move(fp)); + this->registerExplicitlySampledChild(std::move(fp)); } GrBicubicEffect::GrBicubicEffect(const GrBicubicEffect& that) @@ -187,9 +186,7 @@ GrBicubicEffect::GrBicubicEffect(const GrBicubicEffect& that) , fDirection(that.fDirection) , fClamp(that.fClamp) { this->addCoordTransform(&fCoordTransform); - auto child = that.childProcessor(0).clone(); - child->setSampledWithExplicitCoords(); - this->registerChildProcessor(std::move(child)); + this->cloneAndRegisterAllChildProcessors(that); } void GrBicubicEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, diff --git a/chromium/third_party/skia/src/gpu/effects/GrBitmapTextGeoProc.cpp b/chromium/third_party/skia/src/gpu/effects/GrBitmapTextGeoProc.cpp index 87612127b20..4a9f94e52cd 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrBitmapTextGeoProc.cpp +++ b/chromium/third_party/skia/src/gpu/effects/GrBitmapTextGeoProc.cpp @@ -20,7 +20,10 @@ class GrGLBitmapTextGeoProc : public GrGLSLGeometryProcessor { public: - GrGLBitmapTextGeoProc() : fColor(SK_PMColor4fILLEGAL), fAtlasDimensions{0,0} {} + GrGLBitmapTextGeoProc() + : fColor(SK_PMColor4fILLEGAL) + , fAtlasDimensions{0,0} + , fLocalMatrix(SkMatrix::InvalidMatrix()) {} void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { const GrBitmapTextGeoProc& btgp = args.fGP.cast<GrBitmapTextGeoProc>(); @@ -53,14 +56,8 @@ public: // Setup position gpArgs->fPositionVar = btgp.inPosition().asShaderVar(); - - // emit transforms - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - btgp.inPosition().asShaderVar(), - btgp.localMatrix(), - args.fFPCoordTransformHandler); + this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, btgp.inPosition().asShaderVar(), + btgp.localMatrix(), &fLocalMatrixUniform); fragBuilder->codeAppend("half4 texColor;"); append_multitexture_lookup(args, btgp.numTextureSamplers(), @@ -92,7 +89,9 @@ public: 1.0f / atlasDimensions.fHeight); fAtlasDimensions = atlasDimensions; } - this->setTransformDataHelper(btgp.localMatrix(), pdman, transformRange); + + this->setTransform(pdman, fLocalMatrixUniform, btgp.localMatrix(), &fLocalMatrix); + this->setTransformDataHelper(pdman, transformRange); } static inline void GenKey(const GrGeometryProcessor& proc, @@ -102,6 +101,7 @@ public: uint32_t key = 0; key |= btgp.usesW() ? 0x1 : 0x0; key |= btgp.maskFormat() << 1; + key |= ComputeMatrixKey(btgp.localMatrix()) << 2; b->add32(key); b->add32(btgp.numTextureSamplers()); } @@ -113,6 +113,9 @@ private: SkISize fAtlasDimensions; UniformHandle fAtlasDimensionsInvUniform; + SkMatrix fLocalMatrix; + UniformHandle fLocalMatrixUniform; + typedef GrGLSLGeometryProcessor INHERITED; }; diff --git a/chromium/third_party/skia/src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp b/chromium/third_party/skia/src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp index 6126c7d5f6e..f5fde018544 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp @@ -10,10 +10,12 @@ enum class Mode { kSmoothStep = 1 }; +in fragmentProcessor? inputFP; layout(key) in Mode mode; void main() { - half factor = 1.0 - sk_InColor.a; + half inputAlpha = sample(inputFP, sk_InColor).a; + half factor = 1.0 - inputAlpha; @switch (mode) { case Mode::kGaussian: factor = half(exp(-factor * factor * 4.0) - 0.018); diff --git a/chromium/third_party/skia/src/gpu/effects/GrCircleBlurFragmentProcessor.fp b/chromium/third_party/skia/src/gpu/effects/GrCircleBlurFragmentProcessor.fp index 12eaeb6e24a..458431cefc0 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrCircleBlurFragmentProcessor.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrCircleBlurFragmentProcessor.fp @@ -5,10 +5,15 @@ * found in the LICENSE file. */ +in fragmentProcessor? inputFP; in half4 circleRect; -in half textureRadius; in half solidRadius; -in uniform sampler2D blurProfileSampler; +in half textureRadius; +in fragmentProcessor blurProfile; + +@header { + #include "src/gpu/effects/GrTextureEffect.h" +}; // The data is formatted as: // x, y - the center of the circle @@ -17,12 +22,14 @@ in uniform sampler2D blurProfileSampler; uniform half4 circleData; @optimizationFlags { + (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) & kCompatibleWithCoverageAsAlpha_OptimizationFlag } @make { - static std::unique_ptr<GrFragmentProcessor> Make(GrRecordingContext*, - const SkRect& circle, float sigma); + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrRecordingContext*, const SkRect& circle, + float sigma); } @setData(data) { @@ -188,13 +195,14 @@ uniform half4 circleData; profile[profileWidth - 1] = 0; } - static GrSurfaceProxyView create_profile_texture(GrRecordingContext* context, + static std::unique_ptr<GrFragmentProcessor> create_profile_effect(GrRecordingContext* context, const SkRect& circle, float sigma, - float* solidRadius, float* textureRadius) { + float* solidRadius, + float* textureRadius) { float circleR = circle.width() / 2.0f; if (circleR < SK_ScalarNearlyZero) { - return {}; + return nullptr; } // Profile textures are cached by the ratio of sigma to circle radius and by the size of the // profile texture (binned by powers of 2). @@ -224,6 +232,12 @@ uniform half4 circleData; *textureRadius = circleR + 3 * sigma; } + static constexpr int kProfileTextureWidth = 512; + // This would be kProfileTextureWidth/textureRadius if it weren't for the fact that we do + // the calculation of the profile coord in a coord space that has already been scaled by + // 1 / textureRadius. This is done to avoid overflow in length(). + SkMatrix texM = SkMatrix::Scale(kProfileTextureWidth, 1.f); + static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); GrUniqueKey key; GrUniqueKey::Builder builder(&key, kDomain, 1, "1-D Circular Blur"); @@ -234,14 +248,14 @@ uniform half4 circleData; if (sk_sp<GrTextureProxy> blurProfile = proxyProvider->findOrCreateProxyByUniqueKey(key)) { GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(blurProfile->backendFormat(), GrColorType::kAlpha_8); - return {std::move(blurProfile), kTopLeft_GrSurfaceOrigin, swizzle}; + GrSurfaceProxyView profileView{std::move(blurProfile), kTopLeft_GrSurfaceOrigin, + swizzle}; + return GrTextureEffect::Make(std::move(profileView), kPremul_SkAlphaType, texM); } - static constexpr int kProfileTextureWidth = 512; - SkBitmap bm; if (!bm.tryAllocPixels(SkImageInfo::MakeA8(kProfileTextureWidth, 1))) { - return {}; + return nullptr; } if (useHalfPlaneApprox) { @@ -256,40 +270,42 @@ uniform half4 circleData; bm.setImmutable(); GrBitmapTextureMaker maker(context, bm, GrImageTexGenPolicy::kNew_Uncached_Budgeted); - auto blurView = maker.view(GrMipMapped::kNo); - if (!blurView) { - return {}; + auto profileView = maker.view(GrMipMapped::kNo); + if (!profileView) { + return nullptr; } - proxyProvider->assignUniqueKeyToProxy(key, blurView.asTextureProxy()); - return blurView; + proxyProvider->assignUniqueKeyToProxy(key, profileView.asTextureProxy()); + return GrTextureEffect::Make(std::move(profileView), kPremul_SkAlphaType, texM); } std::unique_ptr<GrFragmentProcessor> GrCircleBlurFragmentProcessor::Make( - GrRecordingContext* context, const SkRect& circle, float sigma) { + std::unique_ptr<GrFragmentProcessor> inputFP, GrRecordingContext* context, + const SkRect& circle, float sigma) { float solidRadius; float textureRadius; - GrSurfaceProxyView profile = create_profile_texture(context, circle, sigma, + std::unique_ptr<GrFragmentProcessor> profile = create_profile_effect(context, circle, sigma, &solidRadius, &textureRadius); if (!profile) { return nullptr; } return std::unique_ptr<GrFragmentProcessor>(new GrCircleBlurFragmentProcessor( - circle, textureRadius, solidRadius, std::move(profile))); + std::move(inputFP), circle, solidRadius, textureRadius, std::move(profile))); } } void main() { // We just want to compute "(length(vec) - circleData.z + 0.5) * circleData.w" but need to - // rearrange for precision. - half2 vec = half2(half((sk_FragCoord.x - circleData.x) * circleData.w), - half((sk_FragCoord.y - circleData.y) * circleData.w)); + // rearrange to avoid passing large values to length() that would overflow. + half2 vec = half2((sk_FragCoord.xy - circleData.xy) * circleData.w); half dist = length(vec) + (0.5 - circleData.z) * circleData.w; - sk_OutColor = sk_InColor * sample(blurProfileSampler, half2(dist, 0.5)).a; + half4 inputColor = sample(inputFP, sk_InColor); + sk_OutColor = inputColor * sample(blurProfile, half2(dist, 0.5)).a; } @test(testData) { SkScalar wh = testData->fRandom->nextRangeScalar(100.f, 1000.f); - SkScalar sigma = testData->fRandom->nextRangeF(1.f,10.f); + SkScalar sigma = testData->fRandom->nextRangeF(1.f, 10.f); SkRect circle = SkRect::MakeWH(wh, wh); - return GrCircleBlurFragmentProcessor::Make(testData->context(), circle, sigma); + return GrCircleBlurFragmentProcessor::Make(/*inputFP=*/nullptr, testData->context(), + circle, sigma); } diff --git a/chromium/third_party/skia/src/gpu/effects/GrCircleEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrCircleEffect.fp index ac06c7c47ba..00c6733a713 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrCircleEffect.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrCircleEffect.fp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +in fragmentProcessor? inputFP; layout(key) in GrClipEdgeType edgeType; in float2 center; in float radius; @@ -16,18 +17,22 @@ float prevRadius = -1; uniform float4 circle; @make { - static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, SkPoint center, - float radius) { + static GrFPResult Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, SkPoint center, float radius) { // A radius below half causes the implicit insetting done by this processor to become // inverted. We could handle this case by making the processor code more complicated. if (radius < .5f && GrProcessorEdgeTypeIsInverseFill(edgeType)) { - return nullptr; + return GrFPFailure(std::move(inputFP)); } - return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(edgeType, center, radius)); + return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>( + new GrCircleEffect(std::move(inputFP), edgeType, center, radius))); } } -@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag } +@optimizationFlags { + (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) & + kCompatibleWithCoverageAsAlpha_OptimizationFlag +} @setData(pdman) { if (radius != prevRadius || center != prevCenter) { @@ -57,12 +62,12 @@ void main() { } else { d = half((1.0 - length((circle.xy - sk_FragCoord.xy) * circle.w)) * circle.z); } + half4 inputColor = sample(inputFP, sk_InColor); @if (edgeType == GrClipEdgeType::kFillAA || - edgeType == GrClipEdgeType::kInverseFillAA || - edgeType == GrClipEdgeType::kHairlineAA) { - sk_OutColor = sk_InColor * saturate(d); + edgeType == GrClipEdgeType::kInverseFillAA) { + sk_OutColor = inputColor * saturate(d); } else { - sk_OutColor = d > 0.5 ? sk_InColor : half4(0); + sk_OutColor = d > 0.5 ? inputColor : half4(0); } } @@ -71,9 +76,11 @@ void main() { center.fX = testData->fRandom->nextRangeScalar(0.f, 1000.f); center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f); SkScalar radius = testData->fRandom->nextRangeF(1.f, 1000.f); - GrClipEdgeType et; + bool success; + std::unique_ptr<GrFragmentProcessor> fp; do { - et = (GrClipEdgeType) testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt); - } while (GrClipEdgeType::kHairlineAA == et); - return GrCircleEffect::Make(et, center, radius); + GrClipEdgeType et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt); + std::tie(success, fp) = GrCircleEffect::Make(/*inputFP=*/nullptr, et, center, radius); + } while (!success); + return fp; } diff --git a/chromium/third_party/skia/src/gpu/effects/GrClampFragmentProcessor.fp b/chromium/third_party/skia/src/gpu/effects/GrClampFragmentProcessor.fp index f81fe08de7e..ed6771cbb5d 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrClampFragmentProcessor.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrClampFragmentProcessor.fp @@ -5,24 +5,30 @@ * found in the LICENSE file. */ +in fragmentProcessor? inputFP; layout(key) in bool clampToPremul; @optimizationFlags { - kConstantOutputForConstantInput_OptimizationFlag | - kPreservesOpaqueInput_OptimizationFlag + (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) & + (kConstantOutputForConstantInput_OptimizationFlag | + kPreservesOpaqueInput_OptimizationFlag) } void main() { + half4 inputColor = sample(inputFP, sk_InColor); @if (clampToPremul) { - half alpha = saturate(sk_InColor.a); - sk_OutColor = half4(clamp(sk_InColor.rgb, 0, alpha), alpha); + half alpha = saturate(inputColor.a); + sk_OutColor = half4(clamp(inputColor.rgb, 0, alpha), alpha); } else { - sk_OutColor = saturate(sk_InColor); + sk_OutColor = saturate(inputColor); } } @class { - SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override { + SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override { + SkPMColor4f input = this->numChildProcessors() + ? ConstantOutputForConstantInput(this->childProcessor(0), inColor) + : inColor; float clampedAlpha = SkTPin(input.fA, 0.f, 1.f); float clampVal = clampToPremul ? clampedAlpha : 1.f; return {SkTPin(input.fR, 0.f, clampVal), @@ -33,5 +39,5 @@ void main() { } @test(d) { - return GrClampFragmentProcessor::Make(d->fRandom->nextBool()); + return GrClampFragmentProcessor::Make(/*inputFP=*/nullptr, d->fRandom->nextBool()); } diff --git a/chromium/third_party/skia/src/gpu/effects/GrColorMatrixFragmentProcessor.fp b/chromium/third_party/skia/src/gpu/effects/GrColorMatrixFragmentProcessor.fp index ee73b89f035..5e07a148595 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrColorMatrixFragmentProcessor.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrColorMatrixFragmentProcessor.fp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +in fragmentProcessor? inputFP; layout(ctype=SkM44, tracked) in uniform half4x4 m; layout(ctype=SkV4, tracked) in uniform half4 v; layout(key) in bool unpremulInput; @@ -12,16 +13,14 @@ layout(key) in bool clampRGBOutput; layout(key) in bool premulOutput; @optimizationFlags { + (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) & kConstantOutputForConstantInput_OptimizationFlag } void main() { - half4 inputColor = sk_InColor; + half4 inputColor = sample(inputFP, sk_InColor); @if (unpremulInput) { - // The max() is to guard against 0 / 0 during unpremul when the incoming color is - // transparent black. - half nonZeroAlpha = max(inputColor.a, 0.0001); - inputColor = half4(inputColor.rgb / nonZeroAlpha, inputColor.a); + inputColor = unpremul(inputColor); } sk_OutColor = m * inputColor + v; @if (clampRGBOutput) { @@ -35,7 +34,10 @@ void main() { } @class { - SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override { + SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override { + SkPMColor4f input = this->numChildProcessors() + ? ConstantOutputForConstantInput(this->childProcessor(0), inColor) + : inColor; SkColor4f color; if (unpremulInput) { color = input.unpremul(); @@ -62,7 +64,9 @@ void main() { } @make { - static std::unique_ptr<GrFragmentProcessor> Make(const float matrix[20], bool unpremulInput, bool clampRGBOutput, bool premulOutput) { + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP, + const float matrix[20], bool unpremulInput, + bool clampRGBOutput, bool premulOutput) { SkM44 m44( matrix[ 0], matrix[ 1], matrix[ 2], matrix[ 3], matrix[ 5], matrix[ 6], matrix[ 7], matrix[ 8], @@ -70,7 +74,8 @@ void main() { matrix[15], matrix[16], matrix[17], matrix[18] ); SkV4 v4 = {matrix[4], matrix[9], matrix[14], matrix[19]}; - return std::unique_ptr<GrFragmentProcessor>(new GrColorMatrixFragmentProcessor(m44, v4, unpremulInput, clampRGBOutput, premulOutput)); + return std::unique_ptr<GrFragmentProcessor>(new GrColorMatrixFragmentProcessor( + std::move(inputFP), m44, v4, unpremulInput, clampRGBOutput, premulOutput)); } } @@ -82,5 +87,5 @@ void main() { bool unpremul = d->fRandom->nextBool(); bool clampRGB = d->fRandom->nextBool(); bool premul = d->fRandom->nextBool(); - return Make(m, unpremul, clampRGB, premul); + return Make(/*inputFP=*/nullptr, m, unpremul, clampRGB, premul); } diff --git a/chromium/third_party/skia/src/gpu/effects/GrConfigConversionEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrConfigConversionEffect.fp index 6e08ad3daea..c66f283801b 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrConfigConversionEffect.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrConfigConversionEffect.fp @@ -8,7 +8,6 @@ @header { #include "include/gpu/GrContext.h" #include "src/gpu/GrBitmapTextureMaker.h" - #include "src/gpu/GrClip.h" #include "src/gpu/GrContextPriv.h" #include "src/gpu/GrImageInfo.h" #include "src/gpu/GrRenderTargetContext.h" @@ -84,8 +83,7 @@ paint1.addColorFragmentProcessor(pmToUPM->clone()); paint1.setPorterDuffXPFactory(SkBlendMode::kSrc); - readRTC->fillRectToRect(GrNoClip(), std::move(paint1), GrAA::kNo, SkMatrix::I(), kRect, - kRect); + readRTC->fillRectToRect(nullptr, std::move(paint1), GrAA::kNo, SkMatrix::I(), kRect, kRect); if (!readRTC->readPixels(ii, firstRead, 0, {0, 0})) { return false; } @@ -99,16 +97,14 @@ paint2.addColorFragmentProcessor(std::move(upmToPM)); paint2.setPorterDuffXPFactory(SkBlendMode::kSrc); - tempRTC->fillRectToRect(GrNoClip(), std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect, - kRect); + tempRTC->fillRectToRect(nullptr, std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect, kRect); paint3.addColorFragmentProcessor(GrTextureEffect::Make(tempRTC->readSurfaceView(), kPremul_SkAlphaType)); paint3.addColorFragmentProcessor(std::move(pmToUPM)); paint3.setPorterDuffXPFactory(SkBlendMode::kSrc); - readRTC->fillRectToRect(GrNoClip(), std::move(paint3), GrAA::kNo, SkMatrix::I(), kRect, - kRect); + readRTC->fillRectToRect(nullptr, std::move(paint3), GrAA::kNo, SkMatrix::I(), kRect, kRect); if (!readRTC->readPixels(ii, secondRead, 0, {0, 0})) { return false; diff --git a/chromium/third_party/skia/src/gpu/effects/GrConstColorProcessor.fp b/chromium/third_party/skia/src/gpu/effects/GrConstColorProcessor.fp index 18cc91a4b12..950705c4f0a 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrConstColorProcessor.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrConstColorProcessor.fp @@ -13,51 +13,60 @@ enum class InputMode { kLast = kModulateA }; +in fragmentProcessor? inputFP; layout(ctype=SkPMColor4f, tracked) in uniform half4 color; layout(key) in InputMode mode; @optimizationFlags { - OptFlags(color, mode) + (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) & + (kConstantOutputForConstantInput_OptimizationFlag | + ((mode != InputMode::kIgnore) ? kCompatibleWithCoverageAsAlpha_OptimizationFlag + : kNone_OptimizationFlags) | + ((color.isOpaque()) ? kPreservesOpaqueInput_OptimizationFlag + : kNone_OptimizationFlags)) } void main() { @switch (mode) { - case InputMode::kIgnore: + case InputMode::kIgnore: { sk_OutColor = color; break; - case InputMode::kModulateRGBA: - sk_OutColor = sk_InColor * color; + } + case InputMode::kModulateRGBA: { + half4 inputColor = sample(inputFP, sk_InColor); + sk_OutColor = inputColor * color; break; - case InputMode::kModulateA: - sk_OutColor = sk_InColor.a * color; + } + case InputMode::kModulateA: { + half inputAlpha = sample(inputFP, sk_InColor).a; + sk_OutColor = inputAlpha * color; break; + } } } @class { static const int kInputModeCnt = (int) InputMode::kLast + 1; - static OptimizationFlags OptFlags(const SkPMColor4f& color, InputMode mode) { - OptimizationFlags flags = kConstantOutputForConstantInput_OptimizationFlag; - if (mode != InputMode::kIgnore) { - flags |= kCompatibleWithCoverageAsAlpha_OptimizationFlag; - } - if (color.isOpaque()) { - flags |= kPreservesOpaqueInput_OptimizationFlag; - } - return flags; - } - - SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override { + SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override { switch (mode) { - case InputMode::kIgnore: + case InputMode::kIgnore: { return color; - case InputMode::kModulateA: + } + case InputMode::kModulateA: { + SkPMColor4f input = this->numChildProcessors() + ? ConstantOutputForConstantInput(this->childProcessor(inputFP_index), inColor) + : inColor; return color * input.fA; - case InputMode::kModulateRGBA: + } + case InputMode::kModulateRGBA: { + SkPMColor4f input = this->numChildProcessors() + ? ConstantOutputForConstantInput(this->childProcessor(inputFP_index), inColor) + : inColor; return color * input; + } } - SK_ABORT("Unexpected mode"); + SkUNREACHABLE; } } @@ -82,5 +91,5 @@ void main() { break; } InputMode mode = static_cast<InputMode>(d->fRandom->nextULessThan(kInputModeCnt)); - return GrConstColorProcessor::Make(color, mode); + return GrConstColorProcessor::Make(/*inputFP=*/nullptr, color, mode); } diff --git a/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.cpp index 82de90ec6db..70f2fe443f2 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.cpp @@ -66,7 +66,12 @@ void GrGLConvexPolyEffect::emitCode(EmitArgs& args) { if (GrProcessorEdgeTypeIsInverseFill(cpe.getEdgeType())) { fragBuilder->codeAppend("\talpha = 1.0 - alpha;\n"); } - fragBuilder->codeAppendf("\t%s = %s * alpha;\n", args.fOutputColor, args.fInputColor); + + SkString inputSample = cpe.hasInputFP() + ? this->invokeChild(/*childIndex=*/0, args.fInputColor, args) + : SkString(args.fInputColor); + + fragBuilder->codeAppendf("\t%s = %s * alpha;\n", args.fOutputColor, inputSample.c_str()); } void GrGLConvexPolyEffect::onSetData(const GrGLSLProgramDataManager& pdman, @@ -89,14 +94,10 @@ void GrGLConvexPolyEffect::GenKey(const GrProcessor& processor, const GrShaderCa ////////////////////////////////////////////////////////////////////////////// -std::unique_ptr<GrFragmentProcessor> GrConvexPolyEffect::Make(GrClipEdgeType type, - const SkPath& path) { - if (GrClipEdgeType::kHairlineAA == type) { - return nullptr; - } - if (path.getSegmentMasks() != SkPath::kLine_SegmentMask || - !path.isConvex()) { - return nullptr; +GrFPResult GrConvexPolyEffect::Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType type, const SkPath& path) { + if (path.getSegmentMasks() != SkPath::kLine_SegmentMask || !path.isConvex()) { + return GrFPFailure(std::move(inputFP)); } SkPathPriv::FirstDirection dir; @@ -105,15 +106,17 @@ std::unique_ptr<GrFragmentProcessor> GrConvexPolyEffect::Make(GrClipEdgeType typ // skip the draw or omit the clip element. if (!SkPathPriv::CheapComputeFirstDirection(path, &dir)) { if (GrProcessorEdgeTypeIsInverseFill(type)) { - return GrConstColorProcessor::Make(SK_PMColor4fWHITE, - GrConstColorProcessor::InputMode::kModulateRGBA); + return GrFPSuccess( + GrConstColorProcessor::Make(std::move(inputFP), SK_PMColor4fWHITE, + GrConstColorProcessor::InputMode::kModulateRGBA)); } // This could use kIgnore instead of kModulateRGBA but it would trigger a debug print // about a coverage processor not being compatible with the alpha-as-coverage optimization. // We don't really care about this unlikely case so we just use kModulateRGBA to suppress // the print. - return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT, - GrConstColorProcessor::InputMode::kModulateRGBA); + return GrFPSuccess( + GrConstColorProcessor::Make(std::move(inputFP), SK_PMColor4fTRANSPARENT, + GrConstColorProcessor::InputMode::kModulateRGBA)); } SkScalar edges[3 * kMaxEdges]; @@ -130,11 +133,12 @@ std::unique_ptr<GrFragmentProcessor> GrConvexPolyEffect::Make(GrClipEdgeType typ switch (verb) { case SkPath::kMove_Verb: SkASSERT(n == 0); + break; case SkPath::kClose_Verb: break; case SkPath::kLine_Verb: { if (n >= kMaxEdges) { - return nullptr; + return GrFPFailure(std::move(inputFP)); } if (pts[0] != pts[1]) { SkVector v = pts[1] - pts[0]; @@ -152,22 +156,20 @@ std::unique_ptr<GrFragmentProcessor> GrConvexPolyEffect::Make(GrClipEdgeType typ break; } default: - return nullptr; + return GrFPFailure(std::move(inputFP)); } } if (path.isInverseFillType()) { type = GrInvertProcessorEdgeType(type); } - return Make(type, n, edges); + return GrConvexPolyEffect::Make(std::move(inputFP), type, n, edges); } -std::unique_ptr<GrFragmentProcessor> GrConvexPolyEffect::Make(GrClipEdgeType edgeType, - const SkRect& rect) { - if (GrClipEdgeType::kHairlineAA == edgeType){ - return nullptr; - } - return GrAARectEffect::Make(edgeType, rect); +GrFPResult GrConvexPolyEffect::Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, const SkRect& rect) { + // TODO: Replace calls to this method with calling GrAARectEffect::Make directly + return GrFPSuccess(GrAARectEffect::Make(std::move(inputFP), edgeType, rect)); } GrConvexPolyEffect::~GrConvexPolyEffect() {} @@ -181,7 +183,8 @@ GrGLSLFragmentProcessor* GrConvexPolyEffect::onCreateGLSLInstance() const { return new GrGLConvexPolyEffect; } -GrConvexPolyEffect::GrConvexPolyEffect(GrClipEdgeType edgeType, int n, const SkScalar edges[]) +GrConvexPolyEffect::GrConvexPolyEffect(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, int n, const SkScalar edges[]) : INHERITED(kGrConvexPolyEffect_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag) , fEdgeType(edgeType) , fEdgeCount(n) { @@ -193,12 +196,17 @@ GrConvexPolyEffect::GrConvexPolyEffect(GrClipEdgeType edgeType, int n, const SkS for (int i = 0; i < n; ++i) { fEdges[3 * i + 2] += SK_ScalarHalf; } + + if (inputFP != nullptr) { + this->registerChild(std::move(inputFP)); + } } GrConvexPolyEffect::GrConvexPolyEffect(const GrConvexPolyEffect& that) : INHERITED(kGrConvexPolyEffect_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag) , fEdgeType(that.fEdgeType) , fEdgeCount(that.fEdgeCount) { + this->cloneAndRegisterAllChildProcessors(that); memcpy(fEdges, that.fEdges, 3 * that.fEdgeCount * sizeof(SkScalar)); } @@ -229,7 +237,11 @@ std::unique_ptr<GrFragmentProcessor> GrConvexPolyEffect::TestCreate(GrProcessorT do { GrClipEdgeType edgeType = static_cast<GrClipEdgeType>( d->fRandom->nextULessThan(kGrClipEdgeTypeCnt)); - fp = GrConvexPolyEffect::Make(edgeType, count, edges); + auto [success, convexPolyFP] = GrConvexPolyEffect::Make(/*inputFP=*/nullptr, edgeType, + count, edges); + if (success) { + fp = std::move(convexPolyFP); + } } while (nullptr == fp); return fp; } diff --git a/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.h b/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.h index 2bb33736f81..36fbc73f0e0 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.h @@ -23,9 +23,7 @@ class SkPath; */ class GrConvexPolyEffect : public GrFragmentProcessor { public: - enum { - kMaxEdges = 8, - }; + static constexpr int kMaxEdges = 8; /** * edges is a set of n edge equations where n is limited to kMaxEdges. It contains 3*n values. @@ -38,24 +36,26 @@ public: * have to modify the effect/shaderbuilder interface to make it possible (e.g. give access * to the view matrix or untransformed positions in the fragment shader). */ - static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, int n, - const SkScalar edges[]) { - if (n <= 0 || n > kMaxEdges || GrClipEdgeType::kHairlineAA == edgeType) { - return nullptr; + static GrFPResult Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, int n, const SkScalar edges[]) { + if (n <= 0 || n > kMaxEdges) { + return GrFPFailure(std::move(inputFP)); } - return std::unique_ptr<GrFragmentProcessor>(new GrConvexPolyEffect(edgeType, n, edges)); + + return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>( + new GrConvexPolyEffect(std::move(inputFP), edgeType, n, edges))); } /** * Creates an effect that clips against the path. If the path is not a convex polygon, is - * inverse filled, or has too many edges, this will return nullptr. + * inverse filled, or has too many edges, creation will fail. */ - static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkPath&); + static GrFPResult Make(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType, const SkPath&); /** * Creates an effect that fills inside the rect with AA edges.. */ - static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRect&); + static GrFPResult Make(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType, const SkRect&); ~GrConvexPolyEffect() override; @@ -69,8 +69,12 @@ public: const SkScalar* getEdges() const { return fEdges; } + bool hasInputFP() const { return numChildProcessors() > 0; } + private: - GrConvexPolyEffect(GrClipEdgeType edgeType, int n, const SkScalar edges[]); + GrConvexPolyEffect(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, + int n, const SkScalar edges[]); GrConvexPolyEffect(const GrConvexPolyEffect&); GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; diff --git a/chromium/third_party/skia/src/gpu/effects/GrDeviceSpaceEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrDeviceSpaceEffect.fp index 879c7c4d7c3..8dfb2c4dbda 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrDeviceSpaceEffect.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrDeviceSpaceEffect.fp @@ -7,8 +7,18 @@ in fragmentProcessor fp; +in uniform float3x3 matrix; + void main() { - sk_OutColor = sample(fp, sk_InColor, sk_FragCoord.xy); + float3 p = matrix * (sk_FragCoord.xy1); + sk_OutColor = sample(fp, sk_InColor, p.xy / p.z); +} + +@make{ + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp, + const SkMatrix& matrix = SkMatrix::I()) { + return std::unique_ptr<GrFragmentProcessor>(new GrDeviceSpaceEffect(std::move(fp), matrix)); + } } @test(d) { diff --git a/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldGeoProc.cpp index 3bf74e11fba..19c75f332f3 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldGeoProc.cpp +++ b/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldGeoProc.cpp @@ -57,14 +57,8 @@ public: // Setup position gpArgs->fPositionVar = dfTexEffect.inPosition().asShaderVar(); - - // emit transforms - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - dfTexEffect.inPosition().asShaderVar(), - dfTexEffect.localMatrix(), - args.fFPCoordTransformHandler); + this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, gpArgs->fPositionVar, + dfTexEffect.localMatrix(), &fLocalMatrixUniform); // add varyings GrGLSLVarying uv(kFloat2_GrSLType); @@ -185,7 +179,8 @@ public: 1.0f / atlasDimensions.fHeight); fAtlasDimensions = atlasDimensions; } - this->setTransformDataHelper(dfa8gp.localMatrix(), pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); + this->setTransform(pdman, fLocalMatrixUniform, dfa8gp.localMatrix(), &fLocalMatrix); } static inline void GenKey(const GrGeometryProcessor& gp, @@ -193,6 +188,7 @@ public: GrProcessorKeyBuilder* b) { const GrDistanceFieldA8TextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldA8TextGeoProc>(); uint32_t key = dfTexEffect.getFlags(); + key |= ComputeMatrixKey(dfTexEffect.localMatrix()) << 16; b->add32(key); b->add32(dfTexEffect.numTextureSamplers()); } @@ -202,9 +198,12 @@ private: float fDistanceAdjust = -1.f; UniformHandle fDistanceAdjustUni; #endif - SkISize fAtlasDimensions = {0, 0}; + SkISize fAtlasDimensions = {0, 0}; UniformHandle fAtlasDimensionsInvUniform; + SkMatrix fLocalMatrix = SkMatrix::InvalidMatrix(); + UniformHandle fLocalMatrixUniform; + typedef GrGLSLGeometryProcessor INHERITED; }; @@ -354,31 +353,20 @@ public: varyingHandler->addPassThroughAttribute(dfPathEffect.inColor(), args.fOutputColor); if (dfPathEffect.matrix().hasPerspective()) { - // Setup position + // Setup position (output position is transformed, local coords are pass through) this->writeOutputPosition(vertBuilder, uniformHandler, gpArgs, dfPathEffect.inPosition().name(), dfPathEffect.matrix(), &fMatrixUniform); - - // emit transforms - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - dfPathEffect.inPosition().asShaderVar(), - args.fFPCoordTransformHandler); + gpArgs->fLocalCoordVar = dfPathEffect.inPosition().asShaderVar(); } else { - // Setup position + // Setup position (output position is pass through, local coords are transformed) this->writeOutputPosition(vertBuilder, gpArgs, dfPathEffect.inPosition().name()); - - // emit transforms - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - dfPathEffect.inPosition().asShaderVar(), - dfPathEffect.matrix(), - args.fFPCoordTransformHandler); + this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, + dfPathEffect.inPosition().asShaderVar(), dfPathEffect.matrix(), + &fMatrixUniform); } // Use highp to work around aliasing issues @@ -463,10 +451,9 @@ public: const CoordTransformRange& transformRange) override { const GrDistanceFieldPathGeoProc& dfpgp = proc.cast<GrDistanceFieldPathGeoProc>(); - if (dfpgp.matrix().hasPerspective() && !SkMatrixPriv::CheapEqual(fMatrix, dfpgp.matrix())) { - fMatrix = dfpgp.matrix(); - pdman.setSkMatrix(fMatrixUniform, fMatrix); - } + // We always set the matrix uniform; it's either used to transform from local to device + // for the output position, or from device to local for the local coord variable. + this->setTransform(pdman, fMatrixUniform, dfpgp.matrix(), &fMatrix); const SkISize& atlasDimensions = dfpgp.atlasDimensions(); SkASSERT(SkIsPow2(atlasDimensions.fWidth) && SkIsPow2(atlasDimensions.fHeight)); @@ -477,11 +464,7 @@ public: fAtlasDimensions = atlasDimensions; } - if (dfpgp.matrix().hasPerspective()) { - this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange); - } else { - this->setTransformDataHelper(dfpgp.matrix(), pdman, transformRange); - } + this->setTransformDataHelper(pdman, transformRange); } static inline void GenKey(const GrGeometryProcessor& gp, @@ -490,7 +473,7 @@ public: const GrDistanceFieldPathGeoProc& dfTexEffect = gp.cast<GrDistanceFieldPathGeoProc>(); uint32_t key = dfTexEffect.getFlags(); - key |= ComputePosKey(dfTexEffect.matrix()) << 16; + key |= ComputeMatrixKey(dfTexEffect.matrix()) << 16; b->add32(key); b->add32(dfTexEffect.matrix().hasPerspective()); b->add32(dfTexEffect.numTextureSamplers()); @@ -605,7 +588,9 @@ GrGeometryProcessor* GrDistanceFieldPathGeoProc::TestCreate(GrProcessorTestData* class GrGLDistanceFieldLCDTextGeoProc : public GrGLSLGeometryProcessor { public: - GrGLDistanceFieldLCDTextGeoProc() : fAtlasDimensions({0, 0}) { + GrGLDistanceFieldLCDTextGeoProc() + : fAtlasDimensions({0, 0}) + , fLocalMatrix(SkMatrix::InvalidMatrix()) { fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.0f, 1.0f, 1.0f); } @@ -634,14 +619,9 @@ public: // Setup position gpArgs->fPositionVar = dfTexEffect.inPosition().asShaderVar(); - - // emit transforms - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - dfTexEffect.inPosition().asShaderVar(), - dfTexEffect.localMatrix(), - args.fFPCoordTransformHandler); + this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, + dfTexEffect.inPosition().asShaderVar(), dfTexEffect.localMatrix(), + &fLocalMatrixUniform); // set up varyings GrGLSLVarying uv(kFloat2_GrSLType); @@ -801,7 +781,8 @@ public: 1.0f / atlasDimensions.fHeight); fAtlasDimensions = atlasDimensions; } - this->setTransformDataHelper(dflcd.localMatrix(), pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); + this->setTransform(pdman, fLocalMatrixUniform, dflcd.localMatrix(), &fLocalMatrix); } static inline void GenKey(const GrGeometryProcessor& gp, @@ -809,7 +790,8 @@ public: GrProcessorKeyBuilder* b) { const GrDistanceFieldLCDTextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldLCDTextGeoProc>(); - uint32_t key = dfTexEffect.getFlags(); + uint32_t key = (dfTexEffect.getFlags() << 16) | + ComputeMatrixKey(dfTexEffect.localMatrix()); b->add32(key); b->add32(dfTexEffect.numTextureSamplers()); } @@ -821,6 +803,9 @@ private: SkISize fAtlasDimensions; UniformHandle fAtlasDimensionsInvUniform; + SkMatrix fLocalMatrix; + UniformHandle fLocalMatrixUniform; + typedef GrGLSLGeometryProcessor INHERITED; }; diff --git a/chromium/third_party/skia/src/gpu/effects/GrEllipseEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrEllipseEffect.fp index 8e8c766d0f2..918dcbece1d 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrEllipseEffect.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrEllipseEffect.fp @@ -9,6 +9,7 @@ #include "src/gpu/GrShaderCaps.h" } +in fragmentProcessor? inputFP; layout(key) in GrClipEdgeType edgeType; in float2 center; in float2 radii; @@ -23,25 +24,29 @@ bool medPrecision = !sk_Caps.floatIs32Bits; layout(when=medPrecision) uniform float2 scale; @make { - static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, SkPoint center, - SkPoint radii, const GrShaderCaps& caps) { + static GrFPResult Make(std::unique_ptr<GrFragmentProcessor> inputFP, GrClipEdgeType edgeType, + SkPoint center, SkPoint radii, const GrShaderCaps& caps) { // Small radii produce bad results on devices without full float. if (!caps.floatIs32Bits() && (radii.fX < 0.5f || radii.fY < 0.5f)) { - return nullptr; + return GrFPFailure(std::move(inputFP)); } // Very narrow ellipses produce bad results on devices without full float if (!caps.floatIs32Bits() && (radii.fX > 255*radii.fY || radii.fY > 255*radii.fX)) { - return nullptr; + return GrFPFailure(std::move(inputFP)); } // Very large ellipses produce bad results on devices without full float if (!caps.floatIs32Bits() && (radii.fX > 16384 || radii.fY > 16384)) { - return nullptr; + return GrFPFailure(std::move(inputFP)); } - return std::unique_ptr<GrFragmentProcessor>(new GrEllipseEffect(edgeType, center, radii)); + return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>( + new GrEllipseEffect(std::move(inputFP), edgeType, center, radii))); } } -@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag } +@optimizationFlags { + (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) & + kCompatibleWithCoverageAsAlpha_OptimizationFlag +} @setData(pdman) { if (radii != prevRadii || center != prevCenter) { @@ -114,7 +119,8 @@ void main() { // hairline not supported discard; } - sk_OutColor = sk_InColor * alpha; + half4 inputColor = sample(inputFP, sk_InColor); + sk_OutColor = inputColor * alpha; } @test(testData) { @@ -123,10 +129,13 @@ void main() { center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f); SkScalar rx = testData->fRandom->nextRangeF(0.f, 1000.f); SkScalar ry = testData->fRandom->nextRangeF(0.f, 1000.f); - GrClipEdgeType et; + bool success; + std::unique_ptr<GrFragmentProcessor> fp; do { - et = (GrClipEdgeType) testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt); - } while (GrClipEdgeType::kHairlineAA == et); - return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry), - *testData->caps()->shaderCaps()); + GrClipEdgeType et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt); + std::tie(success, fp) = GrEllipseEffect::Make(/*inputFP=*/nullptr, et, center, + SkPoint::Make(rx, ry), + *testData->caps()->shaderCaps()); + } while (!success); + return fp; } diff --git a/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp index da7d950609a..3c8db3455a8 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp +++ b/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp @@ -140,29 +140,23 @@ std::unique_ptr<GrFragmentProcessor> GrGaussianConvolutionFragmentProcessor::Mak int halfWidth, float gaussianSigma, GrSamplerState::WrapMode wm, - const int bounds[2], + const SkIRect& subset, + const SkIRect* pixelDomain, const GrCaps& caps) { std::unique_ptr<GrFragmentProcessor> child; - GrSamplerState sampler; - switch (dir) { - case Direction::kX: sampler.setWrapModeX(wm); break; - case Direction::kY: sampler.setWrapModeY(wm); break; - } - if (bounds) { - SkASSERT(bounds[0] < bounds[1]); - SkRect subset; + GrSamplerState sampler(wm, GrSamplerState::Filter::kNearest); + if (pixelDomain) { + // Inset because we expect to be invoked at pixel centers. + SkRect domain = SkRect::Make(*pixelDomain).makeInset(0.5, 0.5f); switch (dir) { - case Direction::kX: - subset = SkRect::MakeLTRB(bounds[0], 0, bounds[1], view.height()); - break; - case Direction::kY: - subset = SkRect::MakeLTRB(0, bounds[0], view.width(), bounds[1]); - break; + case Direction::kX: domain.outset(halfWidth, 0); break; + case Direction::kY: domain.outset(0, halfWidth); break; } child = GrTextureEffect::MakeSubset(std::move(view), alphaType, SkMatrix::I(), sampler, - subset, caps); + SkRect::Make(subset), domain, caps); } else { - child = GrTextureEffect::Make(std::move(view), alphaType, SkMatrix::I(), sampler, caps); + child = GrTextureEffect::MakeSubset(std::move(view), alphaType, SkMatrix::I(), sampler, + SkRect::Make(subset), caps); } return std::unique_ptr<GrFragmentProcessor>(new GrGaussianConvolutionFragmentProcessor( std::move(child), dir, halfWidth, gaussianSigma)); @@ -177,8 +171,7 @@ GrGaussianConvolutionFragmentProcessor::GrGaussianConvolutionFragmentProcessor( ProcessorOptimizationFlags(child.get())) , fRadius(radius) , fDirection(direction) { - child->setSampledWithExplicitCoords(); - this->registerChildProcessor(std::move(child)); + this->registerExplicitlySampledChild(std::move(child)); SkASSERT(radius <= kMaxKernelRadius); fill_in_1D_gaussian_kernel(fKernel, gaussianSigma, fRadius); this->addCoordTransform(&fCoordTransform); @@ -189,9 +182,7 @@ GrGaussianConvolutionFragmentProcessor::GrGaussianConvolutionFragmentProcessor( : INHERITED(kGrGaussianConvolutionFragmentProcessor_ClassID, that.optimizationFlags()) , fRadius(that.fRadius) , fDirection(that.fDirection) { - auto child = that.childProcessor(0).clone(); - child->setSampledWithExplicitCoords(); - this->registerChildProcessor(std::move(child)); + this->cloneAndRegisterAllChildProcessors(that); memcpy(fKernel, that.fKernel, radius_to_width(fRadius) * sizeof(float)); this->addCoordTransform(&fCoordTransform); } @@ -220,27 +211,33 @@ std::unique_ptr<GrFragmentProcessor> GrGaussianConvolutionFragmentProcessor::Tes GrProcessorTestData* d) { auto [view, ct, at] = d->randomView(); - Direction dir; - int bounds[2]; - do { - if (d->fRandom->nextBool()) { - dir = Direction::kX; - bounds[0] = d->fRandom->nextRangeU(0, view.width() - 1); - bounds[1] = d->fRandom->nextRangeU(0, view.width() - 1); - } else { - dir = Direction::kY; - bounds[0] = d->fRandom->nextRangeU(0, view.height() - 1); - bounds[1] = d->fRandom->nextRangeU(0, view.height() - 1); - } - } while (bounds[0] == bounds[1]); - std::sort(bounds, bounds + 2); + Direction dir = d->fRandom->nextBool() ? Direction::kY : Direction::kX; + SkIRect subset{ + static_cast<int>(d->fRandom->nextRangeU(0, view.width() - 1)), + static_cast<int>(d->fRandom->nextRangeU(0, view.height() - 1)), + static_cast<int>(d->fRandom->nextRangeU(0, view.width() - 1)), + static_cast<int>(d->fRandom->nextRangeU(0, view.height() - 1)), + }; + subset.sort(); auto wm = static_cast<GrSamplerState::WrapMode>( d->fRandom->nextULessThan(GrSamplerState::kWrapModeCount)); int radius = d->fRandom->nextRangeU(1, kMaxKernelRadius); float sigma = radius / 3.f; + SkIRect temp; + SkIRect* domain = nullptr; + if (d->fRandom->nextBool()) { + temp = { + static_cast<int>(d->fRandom->nextRangeU(0, view.width() - 1)), + static_cast<int>(d->fRandom->nextRangeU(0, view.height() - 1)), + static_cast<int>(d->fRandom->nextRangeU(0, view.width() - 1)), + static_cast<int>(d->fRandom->nextRangeU(0, view.height() - 1)), + }; + temp.sort(); + domain = &temp; + } return GrGaussianConvolutionFragmentProcessor::Make(std::move(view), at, dir, radius, sigma, wm, - bounds, *d->caps()); + subset, domain, *d->caps()); } #endif diff --git a/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h index 70fa89bbdae..61f6e4e3231 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h +++ b/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h @@ -22,17 +22,22 @@ public: /** * Convolve with a Gaussian kernel. Bounds limits the coords sampled by the effect along the - * axis indicated by Direction. The WrapMode is applied to the bounds interval. If bounds is - * nullptr then the full proxy width/height is used. + * axis indicated by Direction. The WrapMode is applied to the subset. If present, the + * pixelDomain indicates the domain of pixels that this effect will be called with. It should + * not account for outsetting due to the filter radius, this effect will handle that. It is + * assumed that the effect is only invoked at pixel centers within the pixelDomain, the + * effect will optimize for that, and may produce incorrect results if it is not the case. If + * pixelDomain is null then the effect will work correctly with any sample coordinates. */ - static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView view, - SkAlphaType alphaType, - Direction dir, + static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView, + SkAlphaType, + Direction, int halfWidth, float gaussianSigma, GrSamplerState::WrapMode, - const int bounds[2], - const GrCaps& caps); + const SkIRect& subset, + const SkIRect* pixelDomain, + const GrCaps&); const char* name() const override { return "GaussianConvolution"; } diff --git a/chromium/third_party/skia/src/gpu/effects/GrHSLToRGBFilterEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrHSLToRGBFilterEffect.fp index 02125f8e709..029f7b2adf7 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrHSLToRGBFilterEffect.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrHSLToRGBFilterEffect.fp @@ -13,19 +13,23 @@ // [2] http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl // [3] http://www.chilliant.com/rgb2hsv.html +in fragmentProcessor? inputFP; + void main() { - half3 hsl = sk_InColor.rgb; + half4 inputColor = sample(inputFP, sk_InColor); + half3 hsl = inputColor.rgb; half C = (1 - abs(2 * hsl.z - 1)) * hsl.y; half3 p = hsl.xxx + half3(0, 2/3.0, 1/3.0); half3 q = saturate(abs(fract(p) * 6 - 3) - 1); half3 rgb = (q - 0.5) * C + hsl.z; - sk_OutColor = saturate(half4(rgb, sk_InColor.a)); + sk_OutColor = saturate(half4(rgb, inputColor.a)); sk_OutColor.rgb *= sk_OutColor.a; } @optimizationFlags { + (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) & (kConstantOutputForConstantInput_OptimizationFlag | kPreservesOpaqueInput_OptimizationFlag) } @@ -33,7 +37,10 @@ void main() { #include "include/private/SkColorData.h" #include "include/private/SkNx.h" - SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& c) const override { + SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override { + SkPMColor4f c = this->numChildProcessors() + ? ConstantOutputForConstantInput(this->childProcessor(0), inColor) + : inColor; const auto H = c[0], S = c[1], L = c[2], diff --git a/chromium/third_party/skia/src/gpu/effects/GrLumaColorFilterEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrLumaColorFilterEffect.fp index 1548b26e0bf..67188459df8 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrLumaColorFilterEffect.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrLumaColorFilterEffect.fp @@ -5,14 +5,20 @@ * found in the LICENSE file. */ +in fragmentProcessor? inputFP; + @optimizationFlags { - kConstantOutputForConstantInput_OptimizationFlag + (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) & + kConstantOutputForConstantInput_OptimizationFlag } @class { #include "include/private/SkColorData.h" - SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override { + SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override { + SkPMColor4f input = this->numChildProcessors() + ? ConstantOutputForConstantInput(this->childProcessor(inputFP_index), inColor) + : inColor; float luma = SK_ITU_BT709_LUM_COEFF_R * input.fR + SK_ITU_BT709_LUM_COEFF_G * input.fG + SK_ITU_BT709_LUM_COEFF_B * input.fB; @@ -21,7 +27,8 @@ } void main() { + half4 inputColor = sample(inputFP, sk_InColor); const half3 SK_ITU_BT709_LUM_COEFF = half3(0.2126, 0.7152, 0.0722); - half luma = saturate(dot(SK_ITU_BT709_LUM_COEFF, sk_InColor.rgb)); + half luma = saturate(dot(SK_ITU_BT709_LUM_COEFF, inputColor.rgb)); sk_OutColor = half4(0, 0, 0, luma); } diff --git a/chromium/third_party/skia/src/gpu/effects/GrMagnifierEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrMagnifierEffect.fp index 582fc4bb298..b4af4c4804b 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrMagnifierEffect.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrMagnifierEffect.fp @@ -5,7 +5,7 @@ * found in the LICENSE file. */ -in uniform sampler2D src; +in fragmentProcessor src; layout(ctype=SkIRect) in int4 bounds; uniform float4 boundsUniform; layout(ctype=SkRect) in float4 srcRect; @@ -16,9 +16,7 @@ in uniform float yInvInset; uniform half2 offset; -@coordTransform(src) { - SkMatrix::I() -} +@coordTransform { SkMatrix::I() } void main() { float2 coord = sk_TransformedCoords2D[0]; @@ -42,36 +40,11 @@ void main() { } @setData(pdman) { - SkScalar invW = 1.0f / src.width(); - SkScalar invH = 1.0f / src.height(); - - { - SkScalar y = srcRect.y() * invH; - if (srcView.origin() != kTopLeft_GrSurfaceOrigin) { - y = 1.0f - (srcRect.height() / bounds.height()) - y; - } - - pdman.set2f(offset, srcRect.x() * invW, y); - } - - { - SkScalar y = bounds.y() * invH; - SkScalar hSign = 1.f; - if (srcView.origin() != kTopLeft_GrSurfaceOrigin) { - y = 1.0f - bounds.y() * invH; - hSign = -1.f; - } - - pdman.set4f(boundsUniform, - bounds.x() * invW, - y, - SkIntToScalar(src.width()) / bounds.width(), - hSign * SkIntToScalar(src.height()) / bounds.height()); - } + pdman.set2f(offset, srcRect.x(), srcRect.y()); + pdman.set4f(boundsUniform, bounds.x(), bounds.y(), 1.f/ bounds.width(), 1.f / bounds.height()); } @test(d) { - auto [view, ct, at] = d->randomView(); const int kMaxWidth = 200; const int kMaxHeight = 200; const SkScalar kMaxInset = 20.0f; @@ -82,7 +55,8 @@ void main() { SkIRect bounds = SkIRect::MakeWH(SkIntToScalar(kMaxWidth), SkIntToScalar(kMaxHeight)); SkRect srcRect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); - auto effect = GrMagnifierEffect::Make(std::move(view), + auto src = GrProcessorUnitTest::MakeChildFP(d); + auto effect = GrMagnifierEffect::Make(std::move(src), bounds, srcRect, srcRect.width() / bounds.width(), diff --git a/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.cpp index 8de8deefce0..04036d03ded 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.cpp @@ -42,9 +42,12 @@ private: typedef GrGLSLFragmentProcessor INHERITED; }; -GrMatrixConvolutionEffect::KernelWrapper GrMatrixConvolutionEffect::KernelWrapper::Make( - GrRecordingContext* context, SkISize size, const GrCaps& caps, const SkScalar* values) { - if (nullptr == context || nullptr == values || size.isEmpty()) { +GrMatrixConvolutionEffect::KernelWrapper::MakeResult +GrMatrixConvolutionEffect::KernelWrapper::Make(GrRecordingContext* context, + SkISize size, + const GrCaps& caps, + const SkScalar* values) { + if (!context || !values || size.isEmpty()) { return {}; } const int length = size.area(); @@ -54,10 +57,10 @@ GrMatrixConvolutionEffect::KernelWrapper GrMatrixConvolutionEffect::KernelWrappe for (int i = 0; i < length; i++) { result.fArray[i] = SkScalarToFloat(values[i]); } - return result; + return {result, nullptr}; } - ScalableSampler& scalableSampler = result.fScalableSampler; + BiasAndGain& scalableSampler = result.fBiasAndGain; bool useA16 = context->defaultBackendFormat(kA16_float_SkColorType, GrRenderable::kNo).isValid(); SkScalar min = values[0]; @@ -108,8 +111,7 @@ GrMatrixConvolutionEffect::KernelWrapper GrMatrixConvolutionEffect::KernelWrappe view = {std::move(cachedKernel), kTopLeft_GrSurfaceOrigin, swizzle}; } else { SkBitmap bm; - auto info = SkImageInfo::Make({(int)GrNextPow2(length), 1}, colorType, - kPremul_SkAlphaType, nullptr); + auto info = SkImageInfo::Make({length, 1}, colorType, kPremul_SkAlphaType, nullptr); if (!bm.tryAllocPixels(info)) { return {}; } @@ -131,23 +133,23 @@ GrMatrixConvolutionEffect::KernelWrapper GrMatrixConvolutionEffect::KernelWrappe proxyProvider->assignUniqueKeyToProxy(key, view.asTextureProxy()); } } - scalableSampler.fSampler = { std::move(view) }; - return result; + auto kernelFP = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType); + return {result, std::move(kernelFP)}; } bool GrMatrixConvolutionEffect::KernelWrapper::operator==(const KernelWrapper& k) const { if (fSize != k.fSize) { return false; } else if (this->isSampled()) { - return fScalableSampler == k.fScalableSampler; + return fBiasAndGain == k.fBiasAndGain; } else { return std::equal(fArray.begin(), fArray.begin() + fSize.area(), k.fArray.begin()); } } -bool GrMatrixConvolutionEffect::KernelWrapper::ScalableSampler::operator==( - const ScalableSampler& k) const { - return fSampler == k.fSampler && fGain == k.fGain && fBias == k.fBias; +bool GrMatrixConvolutionEffect::KernelWrapper::BiasAndGain::operator==( + const BiasAndGain& k) const { + return fGain == k.fGain && fBias == k.fBias; } // For sampled kernels, emit a for loop that does all the kernel accumulation. @@ -162,7 +164,6 @@ void GrGLMatrixConvolutionEffect::emitKernelBlock(EmitArgs& args, SkIPoint loc) int kernelArea = kernelWidth * kernelHeight; if (mce.kernelIsSampled()) { - fragBuilder->codeAppendf("half2 kernelCoord = half2(0, 0);"); fragBuilder->codeAppendf("for (int i = 0; i < %d; ++i)", (int)kernelArea); } @@ -172,13 +173,11 @@ void GrGLMatrixConvolutionEffect::emitKernelBlock(EmitArgs& args, SkIPoint loc) fragBuilder->codeAppend("half2 sourceOffset;"); if (mce.kernelIsSampled()) { const char* kernelBias = uniformHandler->getUniformCStr(fKernelBiasUni); - fragBuilder->codeAppend("k = "); - fragBuilder->appendTextureLookup(args.fTexSamplers[0], "kernelCoord"); - fragBuilder->codeAppendf(".w + %s;", kernelBias); + SkString kernelCoord = SkStringPrintf("float2(float(i) + 0.5, 0.5)"); + SkString kernelSample = this->invokeChild(1, args, kernelCoord.c_str()); + fragBuilder->codeAppendf("k = %s.w + %s;", kernelSample.c_str(), kernelBias); fragBuilder->codeAppendf("sourceOffset.y = floor(i / %d);", kernelWidth); fragBuilder->codeAppendf("sourceOffset.x = i - sourceOffset.y * %d;", kernelWidth); - float kernelStride = 1.0f / (float)GrNextPow2(kernelArea); - fragBuilder->codeAppendf("kernelCoord.x += %f;", kernelStride); } else { fragBuilder->codeAppendf("sourceOffset = half2(%d, %d);", loc.x(), loc.y()); int offset = loc.y() * kernelWidth + loc.x(); @@ -191,7 +190,7 @@ void GrGLMatrixConvolutionEffect::emitKernelBlock(EmitArgs& args, SkIPoint loc) auto sample = this->invokeChild(0, args, "coord + sourceOffset"); fragBuilder->codeAppendf("half4 c = %s;", sample.c_str()); if (!mce.convolveAlpha()) { - fragBuilder->codeAppend("c.rgb /= max(c.a, 0.0001);"); + fragBuilder->codeAppend("c = unpremul(c);"); fragBuilder->codeAppend("c.rgb = saturate(c.rgb);"); } fragBuilder->codeAppend("sum += c * k;"); @@ -282,7 +281,8 @@ void GrGLMatrixConvolutionEffect::onSetData(const GrGLSLProgramDataManager& pdma } GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(std::unique_ptr<GrFragmentProcessor> child, - KernelWrapper kernel, + const KernelWrapper& kernel, + std::unique_ptr<GrFragmentProcessor> kernelFP, SkScalar gain, SkScalar bias, const SkIPoint& kernelOffset, @@ -290,14 +290,13 @@ GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(std::unique_ptr<GrFragmentP // To advertise either the modulation or opaqueness optimizations we'd have to examine the // parameters. : INHERITED(kGrMatrixConvolutionEffect_ClassID, kNone_OptimizationFlags) - , fKernel(std::move(kernel)) + , fKernel(kernel) , fGain(SkScalarToFloat(gain)) , fBias(SkScalarToFloat(bias) / 255.0f) , fConvolveAlpha(convolveAlpha) { - child->setSampledWithExplicitCoords(); - this->registerChildProcessor(std::move(child)); - if (fKernel.isSampled()) { - this->setTextureSamplerCnt(1); + this->registerExplicitlySampledChild(std::move(child)); + if (kernelFP) { + this->registerExplicitlySampledChild(std::move(kernelFP)); } fKernelOffset = {static_cast<float>(kernelOffset.x()), static_cast<float>(kernelOffset.y())}; @@ -311,12 +310,7 @@ GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(const GrMatrixConvolutionEf , fBias(that.fBias) , fKernelOffset(that.fKernelOffset) , fConvolveAlpha(that.fConvolveAlpha) { - auto child = that.childProcessor(0).clone(); - child->setSampledWithExplicitCoords(); - this->registerChildProcessor(std::move(child)); - if (fKernel.isSampled()) { - this->setTextureSamplerCnt(1); - } + this->cloneAndRegisterAllChildProcessors(that); this->addCoordTransform(&fCoordTransform); } @@ -342,11 +336,6 @@ bool GrMatrixConvolutionEffect::onIsEqual(const GrFragmentProcessor& sBase) cons fConvolveAlpha == s.convolveAlpha(); } -const GrFragmentProcessor::TextureSampler& GrMatrixConvolutionEffect::onTextureSampler( - int index) const { - return IthTextureSampler(index, fKernel.scalableSampler().fSampler); -} - static void fill_in_1D_gaussian_kernel_with_stride(float* kernel, int size, int stride, float twoSigmaSqrd) { SkASSERT(!SkScalarNearlyZero(twoSigmaSqrd, SK_ScalarNearlyZero)); @@ -437,15 +426,16 @@ std::unique_ptr<GrFragmentProcessor> GrMatrixConvolutionEffect::Make(GrRecording GrSamplerState::WrapMode wm, bool convolveAlpha, const GrCaps& caps) { - auto kw = KernelWrapper::Make(context, kernelSize, caps, kernel); - if (!kw.isValid()) { + auto [kernelWrapper, kernelFP] = KernelWrapper::Make(context, kernelSize, caps, kernel); + if (!kernelWrapper.isValid()) { return nullptr; } GrSamplerState sampler(wm, GrSamplerState::Filter::kNearest); auto child = GrTextureEffect::MakeSubset(std::move(srcView), kPremul_SkAlphaType, SkMatrix::I(), sampler, SkRect::Make(srcBounds), caps); - return std::unique_ptr<GrFragmentProcessor>(new GrMatrixConvolutionEffect( - std::move(child), std::move(kw), gain, bias, kernelOffset, convolveAlpha)); + return std::unique_ptr<GrFragmentProcessor>( + new GrMatrixConvolutionEffect(std::move(child), kernelWrapper, std::move(kernelFP), + gain, bias, kernelOffset, convolveAlpha)); } std::unique_ptr<GrFragmentProcessor> GrMatrixConvolutionEffect::MakeGaussian( diff --git a/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.h b/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.h index 4a5627bdec3..e28cb957484 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.h @@ -49,8 +49,8 @@ public: const SkV2 kernelOffset() const { return fKernelOffset; } bool kernelIsSampled() const { return fKernel.isSampled(); } const float *kernel() const { return fKernel.array().data(); } - float kernelSampleGain() const { return fKernel.scalableSampler().fGain; } - float kernelSampleBias() const { return fKernel.scalableSampler().fBias; } + float kernelSampleGain() const { return fKernel.biasAndGain().fGain; } + float kernelSampleBias() const { return fKernel.biasAndGain().fBias; } float gain() const { return fGain; } float bias() const { return fBias; } bool convolveAlpha() const { return fConvolveAlpha; } @@ -67,36 +67,24 @@ private: */ class KernelWrapper { public: - struct ScalableSampler { - TextureSampler fSampler; + struct BiasAndGain { // Only used in A8 mode. Applied before any other math. - float fBias = 0.0f; + float fBias; // Only used in A8 mode. Premultiplied in with user gain to save time. - float fGain = 1.0f; - bool operator==(const ScalableSampler&) const; + float fGain; + bool operator==(const BiasAndGain&) const; }; - static KernelWrapper Make(GrRecordingContext*, SkISize, - const GrCaps&, const float* values); + using MakeResult = std::tuple<KernelWrapper, std::unique_ptr<GrFragmentProcessor>>; + static MakeResult Make(GrRecordingContext*, SkISize, const GrCaps&, const float* values); - KernelWrapper(KernelWrapper&& that) : fSize(that.fSize) { - if (that.isSampled()) { - new (&fScalableSampler) ScalableSampler(std::move(that.fScalableSampler)); - } else { - new (&fArray) std::array<float, kMaxUniformSize>(std::move(that.fArray)); - } - } + KernelWrapper() = default; KernelWrapper(const KernelWrapper& that) : fSize(that.fSize) { if (that.isSampled()) { - new (&fScalableSampler) ScalableSampler(that.fScalableSampler); + fBiasAndGain = that.fBiasAndGain; } else { new (&fArray) std::array<float, kMaxUniformSize>(that.fArray); } } - ~KernelWrapper() { - if (this->isSampled()) { - fScalableSampler.~ScalableSampler(); - } - } bool isValid() const { return !fSize.isEmpty(); } SkISize size() const { return fSize; } @@ -105,29 +93,29 @@ private: SkASSERT(!this->isSampled()); return fArray; } - const ScalableSampler& scalableSampler() const { + const BiasAndGain& biasAndGain() const { SkASSERT(this->isSampled()); - return fScalableSampler; + return fBiasAndGain; } bool operator==(const KernelWrapper&) const; private: - KernelWrapper() : fSize({}) {} KernelWrapper(SkISize size) : fSize(size) { if (this->isSampled()) { - new (&fScalableSampler) ScalableSampler; + fBiasAndGain = {0.f , 1.f}; } } - SkISize fSize; + SkISize fSize = {}; union { std::array<float, kMaxUniformSize> fArray; - ScalableSampler fScalableSampler; + BiasAndGain fBiasAndGain; }; }; GrMatrixConvolutionEffect(std::unique_ptr<GrFragmentProcessor> child, - KernelWrapper kernel, + const KernelWrapper& kernel, + std::unique_ptr<GrFragmentProcessor> kernelFP, SkScalar gain, SkScalar bias, const SkIPoint& kernelOffset, @@ -141,8 +129,6 @@ private: bool onIsEqual(const GrFragmentProcessor&) const override; - const GrFragmentProcessor::TextureSampler& onTextureSampler(int index) const override; - // We really just want the unaltered local coords, but the only way to get that right now is // an identity coord transform. GrCoordTransform fCoordTransform = {}; diff --git a/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.cpp new file mode 100644 index 00000000000..aa5cd3cd888 --- /dev/null +++ b/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.cpp @@ -0,0 +1,59 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "src/gpu/effects/GrMatrixEffect.h" + +#include "src/gpu/GrTexture.h" +#include "src/gpu/glsl/GrGLSLFragmentProcessor.h" +#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" +#include "src/gpu/glsl/GrGLSLProgramBuilder.h" +#include "src/sksl/SkSLCPP.h" +#include "src/sksl/SkSLUtil.h" + +class GrGLSLMatrixEffect : public GrGLSLFragmentProcessor { +public: + GrGLSLMatrixEffect() {} + + void emitCode(EmitArgs& args) override { + fMatrixVar = args.fUniformHandler->addUniform(&args.fFp, kFragment_GrShaderFlag, + kFloat3x3_GrSLType, "matrix"); + SkString child = this->invokeChild(0, args.fInputColor, args); + args.fFragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, child.c_str()); + } + +private: + void onSetData(const GrGLSLProgramDataManager& pdman, + const GrFragmentProcessor& proc) override { + const GrMatrixEffect& mtx = proc.cast<GrMatrixEffect>(); + pdman.setSkMatrix(fMatrixVar, mtx.matrix()); + } + + UniformHandle fMatrixVar; +}; + +GrGLSLFragmentProcessor* GrMatrixEffect::onCreateGLSLInstance() const { + return new GrGLSLMatrixEffect(); +} + +void GrMatrixEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, + GrProcessorKeyBuilder* b) const {} + +bool GrMatrixEffect::onIsEqual(const GrFragmentProcessor& other) const { + const GrMatrixEffect& that = other.cast<GrMatrixEffect>(); + if (fMatrix != that.fMatrix) return false; + return true; +} + +GrMatrixEffect::GrMatrixEffect(const GrMatrixEffect& src) + : INHERITED(kGrMatrixEffect_ClassID, src.optimizationFlags()) + , fMatrix(src.fMatrix) { + this->cloneAndRegisterAllChildProcessors(src); +} + +std::unique_ptr<GrFragmentProcessor> GrMatrixEffect::clone() const { + return std::unique_ptr<GrFragmentProcessor>(new GrMatrixEffect(*this)); +} diff --git a/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.fp deleted file mode 100644 index d325c7b73e3..00000000000 --- a/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.fp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -in uniform float3x3 matrix; -in fragmentProcessor child; - -@class { - static std::unique_ptr<GrFragmentProcessor> Apply(const SkMatrix& matrix, - std::unique_ptr<GrFragmentProcessor> processor) { - if (matrix.isIdentity()) { - return processor; - } - SkASSERT(!processor->isSampledWithExplicitCoords()); - SkASSERT(processor->sampleMatrix().fKind == SkSL::SampleMatrix::Kind::kNone); - return Make(matrix, std::move(processor)); - } -} - -void main() { - sk_OutColor = sample(child, sk_InColor, matrix); -} diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrMatrixEffect.h b/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.h index 75a2dbc32ff..69fd1be37e1 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrMatrixEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.h @@ -5,49 +5,48 @@ * found in the LICENSE file. */ -/************************************************************************************************** - *** This file was autogenerated from GrMatrixEffect.fp; do not modify. - **************************************************************************************************/ #ifndef GrMatrixEffect_DEFINED #define GrMatrixEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrMatrixEffect : public GrFragmentProcessor { public: - static std::unique_ptr<GrFragmentProcessor> Apply( - const SkMatrix& matrix, std::unique_ptr<GrFragmentProcessor> processor) { + static std::unique_ptr<GrFragmentProcessor> Make( + const SkMatrix& matrix, std::unique_ptr<GrFragmentProcessor> child) { if (matrix.isIdentity()) { - return processor; + return child; } - SkASSERT(!processor->isSampledWithExplicitCoords()); - SkASSERT(processor->sampleMatrix().fKind == SkSL::SampleMatrix::Kind::kNone); - return Make(matrix, std::move(processor)); - } - static std::unique_ptr<GrFragmentProcessor> Make(SkMatrix matrix, - std::unique_ptr<GrFragmentProcessor> child) { - return std::unique_ptr<GrFragmentProcessor>(new GrMatrixEffect(matrix, std::move(child))); + SkASSERT(!child->isSampledWithExplicitCoords()); + SkASSERT(child->sampleMatrix().fKind == SkSL::SampleMatrix::Kind::kNone); + return std::unique_ptr<GrFragmentProcessor>( + new GrMatrixEffect(matrix, std::move(child))); } - GrMatrixEffect(const GrMatrixEffect& src); + std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "MatrixEffect"; } - SkMatrix matrix; - int child_index = -1; + const SkMatrix& matrix() const { return fMatrix; } private: + GrMatrixEffect(const GrMatrixEffect& src); + GrMatrixEffect(SkMatrix matrix, std::unique_ptr<GrFragmentProcessor> child) - : INHERITED(kGrMatrixEffect_ClassID, kNone_OptimizationFlags), matrix(matrix) { + : INHERITED(kGrMatrixEffect_ClassID, kNone_OptimizationFlags) + , fMatrix(matrix) { SkASSERT(child); - child_index = this->numChildProcessors(); - child->setSampleMatrix( - SkSL::SampleMatrix(SkSL::SampleMatrix::Kind::kConstantOrUniform, this, "matrix")); - this->registerChildProcessor(std::move(child)); + this->registerChild(std::move(child), SkSL::SampleMatrix::MakeConstUniform("matrix")); } + GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; + + SkMatrix fMatrix; + GR_DECLARE_FRAGMENT_PROCESSOR_TEST typedef GrFragmentProcessor INHERITED; }; diff --git a/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.cpp index b7c001cd54b..a84e6c2c737 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.cpp @@ -11,23 +11,20 @@ #include "src/gpu/effects/generated/GrCircleEffect.h" #include "src/gpu/effects/generated/GrEllipseEffect.h" -std::unique_ptr<GrFragmentProcessor> GrOvalEffect::Make(GrClipEdgeType edgeType, const SkRect& oval, - const GrShaderCaps& caps) { - if (GrClipEdgeType::kHairlineAA == edgeType) { - return nullptr; - } +GrFPResult GrOvalEffect::Make(std::unique_ptr<GrFragmentProcessor> inputFP, GrClipEdgeType edgeType, + const SkRect& oval, const GrShaderCaps& caps) { SkScalar w = oval.width(); SkScalar h = oval.height(); if (SkScalarNearlyEqual(w, h)) { w /= 2; - return GrCircleEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + w), - w); + return GrCircleEffect::Make(std::move(inputFP), edgeType, + SkPoint::Make(oval.fLeft + w, oval.fTop + w), w); } else { w /= 2; h /= 2; - return GrEllipseEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h), + return GrEllipseEffect::Make(std::move(inputFP), edgeType, + SkPoint::Make(oval.fLeft + w, oval.fTop + h), SkPoint::Make(w, h), caps); } - - return nullptr; + SkUNREACHABLE; } diff --git a/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.h b/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.h index 8b4c95d71b1..955c1949566 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.h @@ -11,8 +11,8 @@ #include "include/core/SkRefCnt.h" #include "include/gpu/GrTypes.h" #include "include/private/GrTypesPriv.h" +#include "src/gpu/GrFragmentProcessor.h" -class GrFragmentProcessor; class GrShaderCaps; struct SkRect; @@ -21,7 +21,8 @@ namespace GrOvalEffect { /** * Creates an effect that performs clipping against an oval. */ -std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRect&, const GrShaderCaps&); +GrFPResult Make(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType, const SkRect&, + const GrShaderCaps&); }; #endif diff --git a/chromium/third_party/skia/src/gpu/effects/GrPremulInputFragmentProcessor.fp b/chromium/third_party/skia/src/gpu/effects/GrPremulInputFragmentProcessor.fp deleted file mode 100644 index cbba6070740..00000000000 --- a/chromium/third_party/skia/src/gpu/effects/GrPremulInputFragmentProcessor.fp +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2018 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -@optimizationFlags { - kPreservesOpaqueInput_OptimizationFlag | kConstantOutputForConstantInput_OptimizationFlag -} - -void main() { - sk_OutColor = sk_InColor; - sk_OutColor.rgb *= sk_InColor.a; -} - -@class { - SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override { - return SkColor4f { input.fR, input.fG, input.fB, input.fA }.premul(); - } -} diff --git a/chromium/third_party/skia/src/gpu/effects/GrRGBToHSLFilterEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrRGBToHSLFilterEffect.fp index 443fd1ae395..b30d798ebbb 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrRGBToHSLFilterEffect.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrRGBToHSLFilterEffect.fp @@ -25,8 +25,10 @@ // [2] http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl // [3] http://www.chilliant.com/rgb2hsv.html +in fragmentProcessor? inputFP; + void main() { - half4 c = sk_InColor; + half4 c = sample(inputFP, sk_InColor); half4 p = (c.g < c.b) ? half4(c.bg, -1, 2/3.0) : half4(c.gb, 0, -1/3.0); half4 q = (c.r < p.x) ? half4(p.x, c.r, p.yw) @@ -48,13 +50,17 @@ void main() { } @optimizationFlags { + (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) & (kConstantOutputForConstantInput_OptimizationFlag | kPreservesOpaqueInput_OptimizationFlag) } @class { #include "include/private/SkColorData.h" - SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& c) const override { + SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override { + SkPMColor4f c = this->numChildProcessors() + ? ConstantOutputForConstantInput(this->childProcessor(0), inColor) + : inColor; const auto p = (c.fG < c.fB) ? SkPMColor4f{ c.fB, c.fG, -1, 2/3.f } : SkPMColor4f{ c.fG, c.fB, 0, -1/3.f }, q = (c.fR < p[0]) ? SkPMColor4f{ p[0], c.fR, p[1], p[3] } diff --git a/chromium/third_party/skia/src/gpu/effects/GrRRectBlurEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrRRectBlurEffect.fp index 02a8743c166..e8cb928439d 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrRRectBlurEffect.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrRRectBlurEffect.fp @@ -5,10 +5,11 @@ * found in the LICENSE file. */ +in fragmentProcessor? inputFP; in float sigma; layout(ctype=SkRect) in float4 rect; in uniform half cornerRadius; -in uniform sampler2D ninePatchSampler; +in fragmentProcessor ninePatchFP; layout(ctype=SkRect) uniform float4 proxyRect; uniform half blurRadius; @@ -19,19 +20,20 @@ uniform half blurRadius; #include "src/core/SkGpuBlurUtils.h" #include "src/core/SkRRectPriv.h" #include "src/gpu/GrCaps.h" - #include "src/gpu/GrClip.h" #include "src/gpu/GrPaint.h" #include "src/gpu/GrProxyProvider.h" #include "src/gpu/GrRecordingContextPriv.h" #include "src/gpu/GrRenderTargetContext.h" #include "src/gpu/GrStyle.h" + #include "src/gpu/effects/GrTextureEffect.h" } @class { - static GrSurfaceProxyView find_or_create_rrect_blur_mask(GrRecordingContext* context, - const SkRRect& rrectToDraw, - const SkISize& dimensions, - float xformedSigma) { + static std::unique_ptr<GrFragmentProcessor> find_or_create_rrect_blur_mask_fp( + GrRecordingContext* context, + const SkRRect& rrectToDraw, + const SkISize& dimensions, + float xformedSigma) { static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); GrUniqueKey key; GrUniqueKey::Builder builder(&key, kDomain, 9, "RoundRect Blur Mask"); @@ -47,31 +49,37 @@ uniform half blurRadius; } builder.finish(); + // It seems like we could omit this matrix and modify the shader code to not normalize + // the coords used to sample the texture effect. However, the "proxyDims" value in the + // shader is not always the actual the proxy dimensions. This is because 'dimensions' here + // was computed using integer corner radii as determined in + // SkComputeBlurredRRectParams whereas the shader code uses the float radius to compute + // 'proxyDims'. Why it draws correctly with these unequal values is a mystery for the ages. + auto m = SkMatrix::Scale(dimensions.width(), dimensions.height()); static constexpr auto kMaskOrigin = kBottomLeft_GrSurfaceOrigin; GrProxyProvider* proxyProvider = context->priv().proxyProvider(); if (auto view = proxyProvider->findCachedProxyWithColorTypeFallback( key, kMaskOrigin, GrColorType::kAlpha_8, 1)) { - return view; + return GrTextureEffect::Make(std::move(view), kPremul_SkAlphaType, m); } auto rtc = GrRenderTargetContext::MakeWithFallback( context, GrColorType::kAlpha_8, nullptr, SkBackingFit::kExact, dimensions, 1, GrMipMapped::kNo, GrProtected::kNo, kMaskOrigin); if (!rtc) { - return {}; + return nullptr; } GrPaint paint; - rtc->clear(nullptr, SK_PMColor4fTRANSPARENT, - GrRenderTargetContext::CanClearFullscreen::kYes); - rtc->drawRRect(GrNoClip(), std::move(paint), GrAA::kYes, SkMatrix::I(), rrectToDraw, + rtc->clear(SK_PMColor4fTRANSPARENT); + rtc->drawRRect(nullptr, std::move(paint), GrAA::kYes, SkMatrix::I(), rrectToDraw, GrStyle::SimpleFill()); GrSurfaceProxyView srcView = rtc->readSurfaceView(); if (!srcView) { - return {}; + return nullptr; } SkASSERT(srcView.asTextureProxy()); auto rtc2 = SkGpuBlurUtils::GaussianBlur(context, @@ -86,27 +94,28 @@ uniform half blurRadius; SkTileMode::kClamp, SkBackingFit::kExact); if (!rtc2) { - return {}; + return nullptr; } GrSurfaceProxyView mask = rtc2->readSurfaceView(); if (!mask) { - return {}; + return nullptr; } SkASSERT(mask.asTextureProxy()); - SkASSERT(mask.origin() == kBottomLeft_GrSurfaceOrigin); + SkASSERT(mask.origin() == kMaskOrigin); proxyProvider->assignUniqueKeyToProxy(key, mask.asTextureProxy()); - - return mask; + return GrTextureEffect::Make(std::move(mask), kPremul_SkAlphaType, m); } } @optimizationFlags { - kCompatibleWithCoverageAsAlpha_OptimizationFlag + (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) & + kCompatibleWithCoverageAsAlpha_OptimizationFlag } @make { - static std::unique_ptr<GrFragmentProcessor> Make(GrRecordingContext* context, + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrRecordingContext* context, float sigma, float xformedSigma, const SkRRect& srcRRect, @@ -114,11 +123,13 @@ uniform half blurRadius; } @cpp { - std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::Make(GrRecordingContext* context, - float sigma, - float xformedSigma, - const SkRRect& srcRRect, - const SkRRect& devRRect) { + std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::Make( + std::unique_ptr<GrFragmentProcessor> inputFP, + GrRecordingContext* context, + float sigma, + float xformedSigma, + const SkRRect& srcRRect, + const SkRRect& devRRect) { SkASSERT(!SkRRectPriv::IsCircle(devRRect) && !devRRect.isRect()); // Should've been caught up-stream // TODO: loosen this up @@ -147,15 +158,15 @@ uniform half blurRadius; return nullptr; } - GrSurfaceProxyView mask = find_or_create_rrect_blur_mask(context, rrectToDraw, dimensions, - xformedSigma); - if (!mask) { + std::unique_ptr<GrFragmentProcessor> maskFP = find_or_create_rrect_blur_mask_fp( + context, rrectToDraw, dimensions, xformedSigma); + if (!maskFP) { return nullptr; } return std::unique_ptr<GrFragmentProcessor>( - new GrRRectBlurEffect(xformedSigma, devRRect.getBounds(), - SkRRectPriv::GetSimpleRadii(devRRect).fX, std::move(mask))); + new GrRRectBlurEffect(std::move(inputFP), xformedSigma, devRRect.getBounds(), + SkRRectPriv::GetSimpleRadii(devRRect).fX, std::move(maskFP))); } } @@ -166,33 +177,46 @@ uniform half blurRadius; SkScalar sigma = d->fRandom->nextRangeF(1.f,10.f); SkRRect rrect; rrect.setRectXY(SkRect::MakeWH(w, h), r, r); - return GrRRectBlurEffect::Make(d->context(), sigma, sigma, rrect, rrect); + return GrRRectBlurEffect::Make(/*inputFP=*/nullptr, d->context(), sigma, sigma, rrect, rrect); } void main() { - // warp the fragment position to the appropriate part of the 9patch blur texture - - half2 rectCenter = half2((proxyRect.xy + proxyRect.zw) / 2.0); - half2 translatedFragPos = half2(sk_FragCoord.xy - proxyRect.xy); - half threshold = cornerRadius + 2.0 * blurRadius; - half2 middle = half2(proxyRect.zw - proxyRect.xy - 2.0 * threshold); - - if (translatedFragPos.x >= threshold && translatedFragPos.x < (middle.x + threshold)) { - translatedFragPos.x = threshold; - } else if (translatedFragPos.x >= (middle.x + threshold)) { - translatedFragPos.x -= middle.x - 1.0; - } - - if (translatedFragPos.y > threshold && translatedFragPos.y < (middle.y+threshold)) { - translatedFragPos.y = threshold; - } else if (translatedFragPos.y >= (middle.y + threshold)) { - translatedFragPos.y -= middle.y - 1.0; - } - - half2 proxyDims = half2(2.0 * threshold + 1.0); + // Warp the fragment position to the appropriate part of the 9-patch blur texture by snipping + // out the middle section of the proxy rect. + half2 translatedFragPos = half2(sk_FragCoord.xy - proxyRect.LT); + half2 proxyCenter = half2((proxyRect.RB - proxyRect.LT) * 0.5); + half edgeSize = 2.0 * blurRadius + cornerRadius + 0.5; + + // Position the fragment so that (0, 0) marks the center of the proxy rectangle. + // Negative coordinates are on the left/top side and positive numbers are on the right/bottom. + translatedFragPos -= proxyCenter; + + // Temporarily strip off the fragment's sign. x/y are now strictly increasing as we move away + // from the center. + half2 fragDirection = sign(translatedFragPos); + translatedFragPos = abs(translatedFragPos); + + // Our goal is to snip out the "middle section" of the proxy rect (everything but the edge). + // We've repositioned our fragment position so that (0, 0) is the centerpoint and x/y are always + // positive, so we can subtract here and interpret negative results as being within the middle + // section. + translatedFragPos -= proxyCenter - edgeSize; + + // Remove the middle section by clamping to zero. + translatedFragPos = max(translatedFragPos, 0); + + // Reapply the fragment's sign, so that negative coordinates once again mean left/top side and + // positive means bottom/right side. + translatedFragPos *= fragDirection; + + // Offset the fragment so that (0, 0) marks the upper-left again, instead of the center point. + translatedFragPos += half2(edgeSize); + + half2 proxyDims = half2(2.0 * edgeSize); half2 texCoord = translatedFragPos / proxyDims; - sk_OutColor = sk_InColor * sample(ninePatchSampler, texCoord); + half4 inputColor = sample(inputFP, sk_InColor); + sk_OutColor = inputColor * sample(ninePatchFP, texCoord); } @setData(pdman) { diff --git a/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.cpp index f444034e426..a5f8538f86a 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.cpp @@ -45,8 +45,8 @@ public: // The flags are used to indicate which corners are circluar (unflagged corners are assumed to // be square). - static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, - uint32_t circularCornerFlags, const SkRRect&); + static GrFPResult Make(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType, + uint32_t circularCornerFlags, const SkRRect&); ~CircularRRectEffect() override {} @@ -60,8 +60,14 @@ public: GrClipEdgeType getEdgeType() const { return fEdgeType; } + bool hasInputFP() const { + return this->numChildProcessors() > 0; + } + private: - CircularRRectEffect(GrClipEdgeType, uint32_t circularCornerFlags, const SkRRect&); + CircularRRectEffect(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType, uint32_t circularCornerFlags, const SkRRect&); + CircularRRectEffect(const CircularRRectEffect& that); GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; @@ -69,36 +75,50 @@ private: bool onIsEqual(const GrFragmentProcessor& other) const override; - SkRRect fRRect; + SkRRect fRRect; GrClipEdgeType fEdgeType; - uint32_t fCircularCornerFlags; + uint32_t fCircularCornerFlags; GR_DECLARE_FRAGMENT_PROCESSOR_TEST typedef GrFragmentProcessor INHERITED; }; -std::unique_ptr<GrFragmentProcessor> CircularRRectEffect::Make(GrClipEdgeType edgeType, - uint32_t circularCornerFlags, - const SkRRect& rrect) { +GrFPResult CircularRRectEffect::Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, + uint32_t circularCornerFlags, const SkRRect& rrect) { if (GrClipEdgeType::kFillAA != edgeType && GrClipEdgeType::kInverseFillAA != edgeType) { - return nullptr; + return GrFPFailure(std::move(inputFP)); } - return std::unique_ptr<GrFragmentProcessor>( - new CircularRRectEffect(edgeType, circularCornerFlags, rrect)); + return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>( + new CircularRRectEffect(std::move(inputFP), edgeType, circularCornerFlags, rrect))); } -CircularRRectEffect::CircularRRectEffect(GrClipEdgeType edgeType, uint32_t circularCornerFlags, +CircularRRectEffect::CircularRRectEffect(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, uint32_t circularCornerFlags, const SkRRect& rrect) - : INHERITED(kCircularRRectEffect_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag) + : INHERITED( + kCircularRRectEffect_ClassID, + (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) & + kCompatibleWithCoverageAsAlpha_OptimizationFlag) , fRRect(rrect) , fEdgeType(edgeType) , fCircularCornerFlags(circularCornerFlags) { + if (inputFP != nullptr) { + this->registerChild(std::move(inputFP)); + } +} + +CircularRRectEffect::CircularRRectEffect(const CircularRRectEffect& that) + : INHERITED(kCircularRRectEffect_ClassID, that.optimizationFlags()) + , fRRect(that.fRRect) + , fEdgeType(that.fEdgeType) + , fCircularCornerFlags(that.fCircularCornerFlags) { + this->cloneAndRegisterAllChildProcessors(that); } std::unique_ptr<GrFragmentProcessor> CircularRRectEffect::clone() const { - return std::unique_ptr<GrFragmentProcessor>( - new CircularRRectEffect(fEdgeType, fCircularCornerFlags, fRRect)); + return std::unique_ptr<GrFragmentProcessor>(new CircularRRectEffect(*this)); } bool CircularRRectEffect::onIsEqual(const GrFragmentProcessor& other) const { @@ -119,11 +139,13 @@ std::unique_ptr<GrFragmentProcessor> CircularRRectEffect::TestCreate(GrProcessor SkRRect rrect; rrect.setRectXY(SkRect::MakeWH(w, h), r, r); std::unique_ptr<GrFragmentProcessor> fp; + bool success; do { GrClipEdgeType et = (GrClipEdgeType)d->fRandom->nextULessThan(kGrClipEdgeTypeCnt); - fp = GrRRectEffect::Make(et, rrect, *d->caps()->shaderCaps()); - } while (nullptr == fp); + std::tie(success, fp) = GrRRectEffect::Make(/*inputFP=*/nullptr, et, rrect, + *d->caps()->shaderCaps()); + } while (!success); return fp; } #endif @@ -191,85 +213,85 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) { // alphas together. switch (crre.getCircularCornerFlags()) { case CircularRRectEffect::kAll_CornerFlags: - fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); - fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); + fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName); + fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName); fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);"); fragBuilder->codeAppendf("half alpha = half(%s);", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kTopLeft_CornerFlag: - fragBuilder->codeAppendf("float2 dxy = max(%s.xy - sk_FragCoord.xy, 0.0);", + fragBuilder->codeAppendf("float2 dxy = max(%s.LT - sk_FragCoord.xy, 0.0);", rectName); - fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.z - sk_FragCoord.x));", + fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.R - sk_FragCoord.x));", rectName); - fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.w - sk_FragCoord.y));", + fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.B - sk_FragCoord.y));", rectName); fragBuilder->codeAppendf("half alpha = bottomAlpha * rightAlpha * half(%s);", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kTopRight_CornerFlag: - fragBuilder->codeAppendf("float2 dxy = max(float2(sk_FragCoord.x - %s.z, " - "%s.y - sk_FragCoord.y), 0.0);", + fragBuilder->codeAppendf("float2 dxy = max(float2(sk_FragCoord.x - %s.R, " + "%s.T - sk_FragCoord.y), 0.0);", rectName, rectName); - fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.x));", + fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.L));", rectName); - fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.w - sk_FragCoord.y));", + fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.B - sk_FragCoord.y));", rectName); fragBuilder->codeAppendf("half alpha = bottomAlpha * leftAlpha * half(%s);", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kBottomRight_CornerFlag: - fragBuilder->codeAppendf("float2 dxy = max(sk_FragCoord.xy - %s.zw, 0.0);", + fragBuilder->codeAppendf("float2 dxy = max(sk_FragCoord.xy - %s.RB, 0.0);", rectName); - fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.x));", + fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.L));", rectName); - fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.y));", + fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.T));", rectName); fragBuilder->codeAppendf("half alpha = topAlpha * leftAlpha * half(%s);", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kBottomLeft_CornerFlag: - fragBuilder->codeAppendf("float2 dxy = max(float2(%s.x - sk_FragCoord.x, " - "sk_FragCoord.y - %s.w), 0.0);", + fragBuilder->codeAppendf("float2 dxy = max(float2(%s.L - sk_FragCoord.x, " + "sk_FragCoord.y - %s.B), 0.0);", rectName, rectName); - fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.z - sk_FragCoord.x));", + fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.R - sk_FragCoord.x));", rectName); - fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.y));", + fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.T));", rectName); fragBuilder->codeAppendf("half alpha = topAlpha * rightAlpha * half(%s);", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kLeft_CornerFlags: - fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); - fragBuilder->codeAppendf("float dy1 = sk_FragCoord.y - %s.w;", rectName); + fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName); + fragBuilder->codeAppendf("float dy1 = sk_FragCoord.y - %s.B;", rectName); fragBuilder->codeAppend("float2 dxy = max(float2(dxy0.x, max(dxy0.y, dy1)), 0.0);"); - fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.z - sk_FragCoord.x));", + fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.R - sk_FragCoord.x));", rectName); fragBuilder->codeAppendf("half alpha = rightAlpha * half(%s);", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kTop_CornerFlags: - fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); - fragBuilder->codeAppendf("float dx1 = sk_FragCoord.x - %s.z;", rectName); + fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName); + fragBuilder->codeAppendf("float dx1 = sk_FragCoord.x - %s.R;", rectName); fragBuilder->codeAppend("float2 dxy = max(float2(max(dxy0.x, dx1), dxy0.y), 0.0);"); - fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.w - sk_FragCoord.y));", + fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.B - sk_FragCoord.y));", rectName); fragBuilder->codeAppendf("half alpha = bottomAlpha * half(%s);", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kRight_CornerFlags: - fragBuilder->codeAppendf("float dy0 = %s.y - sk_FragCoord.y;", rectName); - fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); + fragBuilder->codeAppendf("float dy0 = %s.T - sk_FragCoord.y;", rectName); + fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName); fragBuilder->codeAppend("float2 dxy = max(float2(dxy1.x, max(dy0, dxy1.y)), 0.0);"); - fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.x));", + fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.L));", rectName); fragBuilder->codeAppendf("half alpha = leftAlpha * half(%s);", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kBottom_CornerFlags: - fragBuilder->codeAppendf("float dx0 = %s.x - sk_FragCoord.x;", rectName); - fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); + fragBuilder->codeAppendf("float dx0 = %s.L - sk_FragCoord.x;", rectName); + fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName); fragBuilder->codeAppend("float2 dxy = max(float2(max(dx0, dxy1.x), dxy1.y), 0.0);"); - fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.y));", + fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.T));", rectName); fragBuilder->codeAppendf("half alpha = topAlpha * half(%s);", clampedCircleDistance.c_str()); @@ -280,7 +302,11 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) { fragBuilder->codeAppend("alpha = 1.0 - alpha;"); } - fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, args.fInputColor); + SkString inputSample = crre.hasInputFP() + ? this->invokeChild(/*childIndex=*/0, args.fInputColor, args) + : SkString(args.fInputColor); + + fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, inputSample.c_str()); } void GLCircularRRectEffect::GenKey(const GrProcessor& processor, const GrShaderCaps&, @@ -385,7 +411,7 @@ GrGLSLFragmentProcessor* CircularRRectEffect::onCreateGLSLInstance() const { class EllipticalRRectEffect : public GrFragmentProcessor { public: - static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRRect&); + static GrFPResult Make(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType, const SkRRect&); ~EllipticalRRectEffect() override {} @@ -397,8 +423,13 @@ public: GrClipEdgeType getEdgeType() const { return fEdgeType; } + bool hasInputFP() const { + return this->numChildProcessors() > 0; + } + private: - EllipticalRRectEffect(GrClipEdgeType, const SkRRect&); + EllipticalRRectEffect(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType, const SkRRect&); + EllipticalRRectEffect(const EllipticalRRectEffect& that); GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; @@ -414,22 +445,37 @@ private: typedef GrFragmentProcessor INHERITED; }; -std::unique_ptr<GrFragmentProcessor> EllipticalRRectEffect::Make(GrClipEdgeType edgeType, - const SkRRect& rrect) { +GrFPResult EllipticalRRectEffect::Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, const SkRRect& rrect) { if (GrClipEdgeType::kFillAA != edgeType && GrClipEdgeType::kInverseFillAA != edgeType) { - return nullptr; + return GrFPFailure(std::move(inputFP)); } - return std::unique_ptr<GrFragmentProcessor>(new EllipticalRRectEffect(edgeType, rrect)); + return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>( + new EllipticalRRectEffect(std::move(inputFP), edgeType, rrect))); } -EllipticalRRectEffect::EllipticalRRectEffect(GrClipEdgeType edgeType, const SkRRect& rrect) - : INHERITED(kEllipticalRRectEffect_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag) +EllipticalRRectEffect::EllipticalRRectEffect(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, const SkRRect& rrect) + : INHERITED( + kEllipticalRRectEffect_ClassID, + (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) & + kCompatibleWithCoverageAsAlpha_OptimizationFlag) , fRRect(rrect) , fEdgeType(edgeType) { + if (inputFP != nullptr) { + this->registerChild(std::move(inputFP)); + } +} + +EllipticalRRectEffect::EllipticalRRectEffect(const EllipticalRRectEffect& that) + : INHERITED(kEllipticalRRectEffect_ClassID, that.optimizationFlags()) + , fRRect(that.fRRect) + , fEdgeType(that.fEdgeType) { + this->cloneAndRegisterAllChildProcessors(that); } std::unique_ptr<GrFragmentProcessor> EllipticalRRectEffect::clone() const { - return std::unique_ptr<GrFragmentProcessor>(new EllipticalRRectEffect(fEdgeType, fRRect)); + return std::unique_ptr<GrFragmentProcessor>(new EllipticalRRectEffect(*this)); } bool EllipticalRRectEffect::onIsEqual(const GrFragmentProcessor& other) const { @@ -470,10 +516,12 @@ std::unique_ptr<GrFragmentProcessor> EllipticalRRectEffect::TestCreate(GrProcess r[SkRRect::kUpperLeft_Corner].fY); } std::unique_ptr<GrFragmentProcessor> fp; + bool success; do { GrClipEdgeType et = (GrClipEdgeType)d->fRandom->nextULessThan(kGrClipEdgeTypeCnt); - fp = GrRRectEffect::Make(et, rrect, *d->caps()->shaderCaps()); - } while (nullptr == fp); + std::tie(success, fp) = GrRRectEffect::Make(/*inputFP=*/nullptr, et, rrect, + *d->caps()->shaderCaps()); + } while (!success); return fp; } #endif @@ -520,8 +568,8 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) { // The code below is a simplified version of the above that performs maxs on the vector // components before computing distances and alpha values so that only one distance computation // need be computed to determine the min alpha. - fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); - fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); + fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName); + fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName); // If we're on a device where float != fp32 then we'll do the distance computation in a space // that is normalized by the largest radius. The scale uniform will be scale, 1/scale. The @@ -589,7 +637,11 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) { fragBuilder->codeAppend("half alpha = clamp(0.5 + approx_dist, 0.0, 1.0);"); } - fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, args.fInputColor); + SkString inputSample = erre.hasInputFP() + ? this->invokeChild(/*childIndex=*/0, args.fInputColor, args) + : SkString(args.fInputColor); + + fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, inputSample.c_str()); } void GLEllipticalRRectEffect::GenKey(const GrProcessor& effect, const GrShaderCaps&, @@ -671,15 +723,15 @@ GrGLSLFragmentProcessor* EllipticalRRectEffect::onCreateGLSLInstance() const { ////////////////////////////////////////////////////////////////////////////// -std::unique_ptr<GrFragmentProcessor> GrRRectEffect::Make(GrClipEdgeType edgeType, - const SkRRect& rrect, - const GrShaderCaps& caps) { +GrFPResult GrRRectEffect::Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, const SkRRect& rrect, + const GrShaderCaps& caps) { if (rrect.isRect()) { - return GrConvexPolyEffect::Make(edgeType, rrect.getBounds()); + return GrConvexPolyEffect::Make(std::move(inputFP), edgeType, rrect.getBounds()); } if (rrect.isOval()) { - return GrOvalEffect::Make(edgeType, rrect.getBounds(), caps); + return GrOvalEffect::Make(std::move(inputFP), edgeType, rrect.getBounds(), caps); } if (rrect.isSimple()) { @@ -687,13 +739,13 @@ std::unique_ptr<GrFragmentProcessor> GrRRectEffect::Make(GrClipEdgeType edgeType SkRRectPriv::GetSimpleRadii(rrect).fY < kRadiusMin) { // In this case the corners are extremely close to rectangular and we collapse the // clip to a rectangular clip. - return GrConvexPolyEffect::Make(edgeType, rrect.getBounds()); + return GrConvexPolyEffect::Make(std::move(inputFP), edgeType, rrect.getBounds()); } if (SkRRectPriv::GetSimpleRadii(rrect).fX == SkRRectPriv::GetSimpleRadii(rrect).fY) { - return CircularRRectEffect::Make(edgeType, CircularRRectEffect::kAll_CornerFlags, - rrect); + return CircularRRectEffect::Make(std::move(inputFP), edgeType, + CircularRRectEffect::kAll_CornerFlags, rrect); } else { - return EllipticalRRectEffect::Make(edgeType, rrect); + return EllipticalRRectEffect::Make(std::move(inputFP), edgeType, rrect); } } @@ -737,6 +789,7 @@ std::unique_ptr<GrFragmentProcessor> GrRRectEffect::Make(GrClipEdgeType edgeType // This rrect should have been caught in the simple case above. Though, it would // be correctly handled in the fallthrough code. SkASSERT(false); + [[fallthrough]]; case CircularRRectEffect::kTopLeft_CornerFlag: case CircularRRectEffect::kTopRight_CornerFlag: case CircularRRectEffect::kBottomRight_CornerFlag: @@ -749,24 +802,24 @@ std::unique_ptr<GrFragmentProcessor> GrRRectEffect::Make(GrClipEdgeType edgeType if (squashedRadii) { rr.writable()->setRectRadii(rrect.getBounds(), radii); } - return CircularRRectEffect::Make(edgeType, cornerFlags, *rr); + return CircularRRectEffect::Make(std::move(inputFP), edgeType, cornerFlags, *rr); + } + case CircularRRectEffect::kNone_CornerFlags: { + return GrConvexPolyEffect::Make(std::move(inputFP), edgeType, rrect.getBounds()); } - case CircularRRectEffect::kNone_CornerFlags: - return GrConvexPolyEffect::Make(edgeType, rrect.getBounds()); default: { if (squashedRadii) { // If we got here then we squashed some but not all the radii to zero. (If all // had been squashed cornerFlags would be 0.) The elliptical effect doesn't // support some rounded and some square corners. - return nullptr; + return GrFPFailure(std::move(inputFP)); } if (rrect.isNinePatch()) { - return EllipticalRRectEffect::Make(edgeType, rrect); + return EllipticalRRectEffect::Make(std::move(inputFP), edgeType, rrect); } - return nullptr; + return GrFPFailure(std::move(inputFP)); } } } - - return nullptr; + return GrFPFailure(std::move(inputFP)); } diff --git a/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.h b/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.h index 426cb8f3c2c..e61246fdd94 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.h @@ -11,8 +11,8 @@ #include "include/core/SkRefCnt.h" #include "include/gpu/GrTypes.h" #include "include/private/GrTypesPriv.h" +#include "src/gpu/GrFragmentProcessor.h" -class GrFragmentProcessor; class GrShaderCaps; class GrProcessor; class SkRRect; @@ -21,9 +21,11 @@ namespace GrRRectEffect { /** * Creates an effect that performs anti-aliased clipping against a SkRRect. It doesn't support - * all varieties of SkRRect so the caller must check for a nullptr return. + * all varieties of SkRRect, so the caller must check `success` in the GrFPResult. */ -std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRRect&, const GrShaderCaps&); +GrFPResult Make(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType, const SkRRect&, + const GrShaderCaps&); + }; #endif diff --git a/chromium/third_party/skia/src/gpu/effects/GrRectBlurEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrRectBlurEffect.fp index ec11611dda9..56cd64fcb7d 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrRectBlurEffect.fp +++ b/chromium/third_party/skia/src/gpu/effects/GrRectBlurEffect.fp @@ -17,8 +17,10 @@ #include "src/gpu/GrProxyProvider.h" #include "src/gpu/GrRecordingContextPriv.h" #include "src/gpu/GrShaderCaps.h" +#include "src/gpu/effects/GrTextureEffect.h" } +in fragmentProcessor? inputFP; in float4 rect; layout(key) bool highp = abs(rect.x) > 16000 || abs(rect.y) > 16000 || @@ -27,17 +29,20 @@ layout(key) bool highp = abs(rect.x) > 16000 || abs(rect.y) > 16000 || layout(when= highp) uniform float4 rectF; layout(when=!highp) uniform half4 rectH; -// Texture that is a LUT for integral of normal distribution. The value at x (where x is a texture -// coord between 0 and 1) is the integral from -inf to (3 * sigma * (-2 * x - 1)). I.e. x is mapped -// 0 3*sigma to -3 sigma. The flip saves a reversal in the shader. -in uniform sampler2D integral; -// Used to produce normalized texture coords for lookups in 'integral' -in uniform half invSixSigma; +// Effect that is a LUT for integral of normal distribution. The value at x:[0,6*sigma] is the +// integral from -inf to (3*sigma - x). I.e. x is mapped from [0, 6*sigma] to [3*sigma to -3*sigma]. +// The flip saves a reversal in the shader. +in fragmentProcessor integral; // There is a fast variant of the effect that does 2 texture lookups and a more general one for // wider blurs relative to rect sizes that does 4. layout(key) in bool isFast; +@optimizationFlags { + (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) & + kCompatibleWithCoverageAsAlpha_OptimizationFlag +} + @constructorParams { GrSamplerState samplerParams } @@ -45,8 +50,10 @@ layout(key) in bool isFast; @samplerParams(integral) { samplerParams } + @class { -static GrSurfaceProxyView CreateIntegralTexture(GrRecordingContext* context, float sixSigma) { +static std::unique_ptr<GrFragmentProcessor> MakeIntegralFP(GrRecordingContext* context, + float sixSigma) { // The texture we're producing represents the integral of a normal distribution over a six-sigma // range centered at zero. We want enough resolution so that the linear interpolation done in // texture lookup doesn't introduce noticeable artifacts. We conservatively choose to have 2 @@ -61,11 +68,15 @@ static GrSurfaceProxyView CreateIntegralTexture(GrRecordingContext* context, flo builder[0] = width; builder.finish(); + SkMatrix m = SkMatrix::Scale(width/sixSigma, 1.f); + GrProxyProvider* proxyProvider = context->priv().proxyProvider(); if (sk_sp<GrTextureProxy> proxy = proxyProvider->findOrCreateProxyByUniqueKey(key)) { GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(proxy->backendFormat(), GrColorType::kAlpha_8); - return {std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle}; + GrSurfaceProxyView view{std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle}; + return GrTextureEffect::Make( + std::move(view), kPremul_SkAlphaType, m, GrSamplerState::Filter::kBilerp); } SkBitmap bitmap; @@ -90,12 +101,14 @@ static GrSurfaceProxyView CreateIntegralTexture(GrRecordingContext* context, flo } SkASSERT(view.origin() == kTopLeft_GrSurfaceOrigin); proxyProvider->assignUniqueKeyToProxy(key, view.asTextureProxy()); - return view; + return GrTextureEffect::Make( + std::move(view), kPremul_SkAlphaType, m, GrSamplerState::Filter::kBilerp); } } @make { - static std::unique_ptr<GrFragmentProcessor> Make(GrRecordingContext* context, + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrRecordingContext* context, const GrShaderCaps& caps, const SkRect& rect, float sigma) { SkASSERT(rect.isSorted()); @@ -110,7 +123,7 @@ static GrSurfaceProxyView CreateIntegralTexture(GrRecordingContext* context, flo } const float sixSigma = 6 * sigma; - GrSurfaceProxyView integral = CreateIntegralTexture(context, sixSigma); + std::unique_ptr<GrFragmentProcessor> integral = MakeIntegralFP(context, sixSigma); if (!integral) { return nullptr; } @@ -130,71 +143,61 @@ static GrSurfaceProxyView CreateIntegralTexture(GrRecordingContext* context, flo // less than 6 sigma wide then things aren't so simple and we have to consider both the // left and right edge of the rectangle (and similar in y). bool isFast = insetRect.isSorted(); - // 1 / (6 * sigma) is the domain of the integral texture. We use the inverse to produce - // normalized texture coords from frag coord distances. - float invSixSigma = 1.f / sixSigma; - return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect(insetRect, - std::move(integral), invSixSigma, isFast, GrSamplerState::Filter::kBilerp)); + return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect( + std::move(inputFP), insetRect, std::move(integral), + isFast, GrSamplerState::Filter::kBilerp)); } } void main() { - half xCoverage, yCoverage; - @if (isFast) { - // Get the smaller of the signed distance from the frag coord to the left and right - // edges and similar for y. - // The integral texture goes "backwards" (from 3*sigma to -3*sigma), So, the below - // computations align the left edge of the integral texture with the inset rect's edge - // extending outward 6 * sigma from the inset rect. - half x, y; - @if (highp) { - x = max(half(rectF.x - sk_FragCoord.x), half(sk_FragCoord.x - rectF.z)); - y = max(half(rectF.y - sk_FragCoord.y), half(sk_FragCoord.y - rectF.w)); - } else { - x = max(half(rectH.x - sk_FragCoord.x), half(sk_FragCoord.x - rectH.z)); - y = max(half(rectH.y - sk_FragCoord.y), half(sk_FragCoord.y - rectH.w)); - } - xCoverage = sample(integral, half2(x * invSixSigma, 0.5)).a; - yCoverage = sample(integral, half2(y * invSixSigma, 0.5)).a; - sk_OutColor = sk_InColor * xCoverage * yCoverage; + half xCoverage, yCoverage; + @if (isFast) { + // Get the smaller of the signed distance from the frag coord to the left and right + // edges and similar for y. + // The integral texture goes "backwards" (from 3*sigma to -3*sigma), So, the below + // computations align the left edge of the integral texture with the inset rect's edge + // extending outward 6 * sigma from the inset rect. + half2 xy; + @if (highp) { + xy = max(half2(rectF.LT - sk_FragCoord.xy), + half2(sk_FragCoord.xy - rectF.RB)); + } else { + xy = max(half2(rectH.LT - sk_FragCoord.xy), + half2(sk_FragCoord.xy - rectH.RB)); + } + xCoverage = sample(integral, half2(xy.x, 0.5)).a; + yCoverage = sample(integral, half2(xy.y, 0.5)).a; + } else { + // We just consider just the x direction here. In practice we compute x and y separately + // and multiply them together. + // We define our coord system so that the point at which we're evaluating a kernel + // defined by the normal distribution (K) at 0. In this coord system let L be left + // edge and R be the right edge of the rectangle. + // We can calculate C by integrating K with the half infinite ranges outside the L to R + // range and subtracting from 1: + // C = 1 - <integral of K from from -inf to L> - <integral of K from R to inf> + // K is symmetric about x=0 so: + // C = 1 - <integral of K from from -inf to L> - <integral of K from -inf to -R> + + // The integral texture goes "backwards" (from 3*sigma to -3*sigma) which is factored + // in to the below calculations. + // Also, our rect uniform was pre-inset by 3 sigma from the actual rect being blurred, + // also factored in. + half4 rect; + @if (highp) { + rect.LT = half2(rectF.LT - sk_FragCoord.xy); + rect.RB = half2(sk_FragCoord.xy - rectF.RB); } else { - // We just consider just the x direction here. In practice we compute x and y separately - // and multiply them together. - // We define our coord system so that the point at which we're evaluating a kernel - // defined by the normal distribution (K) as 0. In this coord system let L be left - // edge and R be the right edge of the rectangle. - // We can calculate C by integrating K with the half infinite ranges outside the L to R - // range and subtracting from 1: - // C = 1 - <integral of K from from -inf to L> - <integral of K from R to inf> - // K is symmetric about x=0 so: - // C = 1 - <integral of K from from -inf to L> - <integral of K from -inf to -R> - - // The integral texture goes "backwards" (from 3*sigma to -3*sigma) which is factored - // in to the below calculations. - // Also, our rect uniform was pre-inset by 3 sigma from the actual rect being blurred, - // also factored in. - half l, r, t, b; - @if (highp) { - l = half(sk_FragCoord.x - rectF.x); - r = half(rectF.z - sk_FragCoord.x); - t = half(sk_FragCoord.y - rectF.y); - b = half(rectF.w - sk_FragCoord.y); - } else { - l = half(sk_FragCoord.x - rectH.x); - r = half(rectH.z - sk_FragCoord.x); - t = half(sk_FragCoord.y - rectH.y); - b = half(rectH.w - sk_FragCoord.y); - } - half il = 1 + l * invSixSigma; - half ir = 1 + r * invSixSigma; - half it = 1 + t * invSixSigma; - half ib = 1 + b * invSixSigma; - xCoverage = 1 - sample(integral, half2(il, 0.5)).a - - sample(integral, half2(ir, 0.5)).a; - yCoverage = 1 - sample(integral, half2(it, 0.5)).a - - sample(integral, half2(ib, 0.5)).a; + rect.LT = half2(rectH.LT - sk_FragCoord.xy); + rect.RB = half2(sk_FragCoord.xy - rectH.RB); } - sk_OutColor = sk_InColor * xCoverage * yCoverage; + xCoverage = 1 - sample(integral, half2(rect.L, 0.5)).a + - sample(integral, half2(rect.R, 0.5)).a; + yCoverage = 1 - sample(integral, half2(rect.T, 0.5)).a + - sample(integral, half2(rect.B, 0.5)).a; + } + half4 inputColor = sample(inputFP, sk_InColor); + sk_OutColor = inputColor * xCoverage * yCoverage; } @setData(pdman) { @@ -202,12 +205,10 @@ void main() { pdman.set4fv(highp ? rectF : rectH, 1, r); } -@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag } - @test(data) { float sigma = data->fRandom->nextRangeF(3,8); float width = data->fRandom->nextRangeF(200,300); float height = data->fRandom->nextRangeF(200,300); - return GrRectBlurEffect::Make(data->context(), *data->caps()->shaderCaps(), + return GrRectBlurEffect::Make(/*inputFP=*/nullptr, data->context(), *data->caps()->shaderCaps(), SkRect::MakeWH(width, height), sigma); } diff --git a/chromium/third_party/skia/src/gpu/effects/GrShadowGeoProc.cpp b/chromium/third_party/skia/src/gpu/effects/GrShadowGeoProc.cpp index de6db266441..d129a7d2ff0 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrShadowGeoProc.cpp +++ b/chromium/third_party/skia/src/gpu/effects/GrShadowGeoProc.cpp @@ -22,7 +22,6 @@ public: const GrRRectShadowGeoProc& rsgp = args.fGP.cast<GrRRectShadowGeoProc>(); GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; - GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; // emit attributes @@ -35,13 +34,7 @@ public: // Setup position this->writeOutputPosition(vertBuilder, gpArgs, rsgp.inPosition().name()); - - // emit transforms - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - rsgp.inPosition().asShaderVar(), - args.fFPCoordTransformHandler); + // No need for local coordinates, this GP does not combine with fragment processors fragBuilder->codeAppend("half d = length(shadowParams.xy);"); fragBuilder->codeAppend("float2 uv = float2(shadowParams.z * (1.0 - d), 0.5);"); @@ -53,7 +46,7 @@ public: void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc, const CoordTransformRange& transformRange) override { - this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); } private: diff --git a/chromium/third_party/skia/src/gpu/effects/GrSkSLFP.cpp b/chromium/third_party/skia/src/gpu/effects/GrSkSLFP.cpp index a2e9b465d64..b2ed34f653c 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrSkSLFP.cpp +++ b/chromium/third_party/skia/src/gpu/effects/GrSkSLFP.cpp @@ -198,8 +198,7 @@ const char* GrSkSLFP::name() const { } void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child) { - child->setSampledWithExplicitCoords(); - this->registerChildProcessor(std::move(child)); + this->registerExplicitlySampledChild(std::move(child)); } GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const { @@ -259,6 +258,7 @@ GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSkSLFP); #include "include/effects/SkArithmeticImageFilter.h" #include "include/effects/SkOverdrawColorFilter.h" #include "include/gpu/GrContext.h" +#include "src/core/SkColorFilterBase.h" #include "src/gpu/effects/generated/GrConstColorProcessor.h" extern const char* SKSL_ARITHMETIC_SRC; @@ -284,7 +284,7 @@ std::unique_ptr<GrFragmentProcessor> GrSkSLFP::TestCreate(GrProcessorTestData* d auto result = GrSkSLFP::Make(d->context(), effect, "Arithmetic", SkData::MakeWithCopy(&inputs, sizeof(inputs))); result->addChild(GrConstColorProcessor::Make( - SK_PMColor4fWHITE, GrConstColorProcessor::InputMode::kIgnore)); + /*inputFP=*/nullptr, SK_PMColor4fWHITE, GrConstColorProcessor::InputMode::kIgnore)); return std::unique_ptr<GrFragmentProcessor>(result.release()); } case 2: { @@ -292,8 +292,8 @@ std::unique_ptr<GrFragmentProcessor> GrSkSLFP::TestCreate(GrProcessorTestData* d for (SkColor& c : colors) { c = d->fRandom->nextU(); } - return SkOverdrawColorFilter::MakeWithSkColors(colors) - ->asFragmentProcessor(d->context(), GrColorInfo{}); + auto filter = SkOverdrawColorFilter::MakeWithSkColors(colors); + return as_CFB(filter)->asFragmentProcessor(d->context(), GrColorInfo{}); } } SK_ABORT("unreachable"); diff --git a/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.cpp index b2ed99eea71..5113cbf8137 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.cpp @@ -9,7 +9,7 @@ #include "src/gpu/GrTexture.h" #include "src/gpu/GrTexturePriv.h" -#include "src/gpu/effects/generated/GrMatrixEffect.h" +#include "src/gpu/effects/GrMatrixEffect.h" #include "src/gpu/glsl/GrGLSLFragmentProcessor.h" #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" #include "src/gpu/glsl/GrGLSLProgramBuilder.h" @@ -110,7 +110,7 @@ GrTextureEffect::Sampling::Sampling(const GrSurfaceProxy& proxy, r.fShaderSubset = r.fShaderClamp = {0, 0}; return r; } - r.fShaderMode = static_cast<ShaderMode>(mode); + r.fShaderMode = GetShaderMode(mode, filter); r.fHWMode = Mode::kClamp; return r; }; @@ -142,8 +142,7 @@ bool GrTextureEffect::Sampling::hasBorderAlpha() const { fHWSampler.wrapModeY() == GrSamplerState::WrapMode::kClampToBorder) { return true; } - if (fShaderModes[0] == ShaderMode::kClampToBorder || - fShaderModes[1] == ShaderMode::kClampToBorder) { + if (ShaderModeIsClampToBorder(fShaderModes[0]) || ShaderModeIsClampToBorder(fShaderModes[1])) { return fBorder[3] < 1.f; } return false; @@ -196,7 +195,7 @@ std::unique_ptr<GrFragmentProcessor> GrTextureEffect::Make(GrSurfaceProxyView vi SkMatrix final; bool lazyProxyNormalization; get_matrix(matrix, view, &final, &lazyProxyNormalization); - return GrMatrixEffect::Apply(final, std::unique_ptr<GrFragmentProcessor>( + return GrMatrixEffect::Make(final, std::unique_ptr<GrFragmentProcessor>( new GrTextureEffect(std::move(view), alphaType, Sampling(filter), @@ -214,7 +213,7 @@ std::unique_ptr<GrFragmentProcessor> GrTextureEffect::Make(GrSurfaceProxyView vi SkMatrix final; bool lazyProxyNormalization; get_matrix(matrix, view, &final, &lazyProxyNormalization); - return GrMatrixEffect::Apply(final, std::unique_ptr<GrFragmentProcessor>( + return GrMatrixEffect::Make(final, std::unique_ptr<GrFragmentProcessor>( new GrTextureEffect(std::move(view), alphaType, sampling, @@ -232,7 +231,7 @@ std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeSubset(GrSurfaceProxyV SkMatrix final; bool lazyProxyNormalization; get_matrix(matrix, view, &final, &lazyProxyNormalization); - return GrMatrixEffect::Apply(final, std::unique_ptr<GrFragmentProcessor>( + return GrMatrixEffect::Make(final, std::unique_ptr<GrFragmentProcessor>( new GrTextureEffect(std::move(view), alphaType, sampling, @@ -251,37 +250,41 @@ std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeSubset(GrSurfaceProxyV SkMatrix final; bool lazyProxyNormalization; get_matrix(matrix, view, &final, &lazyProxyNormalization); - return GrMatrixEffect::Apply(final, std::unique_ptr<GrFragmentProcessor>( + return GrMatrixEffect::Make(final, std::unique_ptr<GrFragmentProcessor>( new GrTextureEffect(std::move(view), alphaType, sampling, lazyProxyNormalization))); } -GrTextureEffect::FilterLogic GrTextureEffect::GetFilterLogic(ShaderMode mode, - GrSamplerState::Filter filter) { +GrTextureEffect::ShaderMode GrTextureEffect::GetShaderMode(GrSamplerState::WrapMode mode, + GrSamplerState::Filter filter) { switch (mode) { - case ShaderMode::kMirrorRepeat: - case ShaderMode::kNone: - case ShaderMode::kClamp: - return FilterLogic::kNone; - case ShaderMode::kRepeat: + case GrSamplerState::WrapMode::kMirrorRepeat: + return ShaderMode::kMirrorRepeat; + case GrSamplerState::WrapMode::kClamp: + return ShaderMode::kClamp; + case GrSamplerState::WrapMode::kRepeat: switch (filter) { case GrSamplerState::Filter::kNearest: - return FilterLogic::kNone; + return ShaderMode::kRepeatNearest; case GrSamplerState::Filter::kBilerp: - return FilterLogic::kRepeatBilerp; + return ShaderMode::kRepeatBilerp; case GrSamplerState::Filter::kMipMap: - return FilterLogic::kRepeatMipMap; + return ShaderMode::kRepeatMipMap; } SkUNREACHABLE; - case ShaderMode::kClampToBorder: - return filter > GrSamplerState::Filter::kNearest ? FilterLogic::kClampToBorderFilter - : FilterLogic::kClampToBorderNearest; + case GrSamplerState::WrapMode::kClampToBorder: + return filter == GrSamplerState::Filter::kNearest ? ShaderMode::kClampToBorderNearest + : ShaderMode::kClampToBorderFilter; } SkUNREACHABLE; } +inline bool GrTextureEffect::ShaderModeIsClampToBorder(ShaderMode m) { + return m == ShaderMode::kClampToBorderNearest || m == ShaderMode::kClampToBorderFilter; +} + GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const { class Impl : public GrGLSLFragmentProcessor { UniformHandle fSubsetUni; @@ -300,10 +303,18 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const { } auto* fb = args.fFragBuilder; if (te.sampleMatrix().fKind == SkSL::SampleMatrix::Kind::kMixed) { + // FIXME this is very similar to the extra logic in + // GrGLSLFragmentShaderBuilder::ensureCoords2D args.fUniformHandler->writeUniformMappings(te.sampleMatrix().fOwner, fb); - coords = SkStringPrintf("(%s * _matrix * float3(%s, 1)).xy", - te.sampleMatrix().fExpression.c_str(), - coords.c_str()); + SkString coords2D; + coords2D.printf("%s_teSample", coords.c_str()); + + fb->codeAppendf("float3 %s_3d = %s * _matrix * %s.xy1;\n", + coords2D.c_str(), te.sampleMatrix().fExpression.c_str(), + coords.c_str()); + fb->codeAppendf("float2 %s = %s_3d.xy / %s_3d.z;\n", + coords2D.c_str(), coords2D.c_str(), coords2D.c_str()); + coords = coords2D; } if (te.fShaderModes[0] == ShaderMode::kNone && te.fShaderModes[1] == ShaderMode::kNone) { @@ -354,24 +365,55 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const { const auto& m = te.fShaderModes; GrTextureType textureType = te.fSampler.proxy()->backendFormat().textureType(); bool normCoords = textureType != GrTextureType::kRectangle; - auto filter = te.fSampler.samplerState().filter(); - FilterLogic filterLogic[2] = {GetFilterLogic(m[0], filter), - GetFilterLogic(m[1], filter)}; const char* borderName = nullptr; - if (te.fShaderModes[0] == ShaderMode::kClampToBorder || - te.fShaderModes[1] == ShaderMode::kClampToBorder) { + if (te.hasClampToBorderShaderMode()) { fBorderUni = args.fUniformHandler->addUniform( &te, kFragment_GrShaderFlag, kHalf4_GrSLType, "border", &borderName); } auto modeUsesSubset = [](ShaderMode m) { - return m == ShaderMode::kRepeat || m == ShaderMode::kMirrorRepeat || - m == ShaderMode::kClampToBorder; + switch (m) { + case ShaderMode::kNone: return false; + case ShaderMode::kClamp: return false; + case ShaderMode::kRepeatNearest: return true; + case ShaderMode::kRepeatBilerp: return true; + case ShaderMode::kRepeatMipMap: return true; + case ShaderMode::kMirrorRepeat: return true; + case ShaderMode::kClampToBorderNearest: return true; + case ShaderMode::kClampToBorderFilter: return true; + } + SkUNREACHABLE; + }; + + auto modeUsesClamp = [](ShaderMode m) { + switch (m) { + case ShaderMode::kNone: return false; + case ShaderMode::kClamp: return true; + case ShaderMode::kRepeatNearest: return true; + case ShaderMode::kRepeatBilerp: return true; + case ShaderMode::kRepeatMipMap: return true; + case ShaderMode::kMirrorRepeat: return true; + case ShaderMode::kClampToBorderNearest: return false; + case ShaderMode::kClampToBorderFilter: return true; + } + SkUNREACHABLE; }; - auto modeUsesClamp = [filter](ShaderMode m) { - return m != ShaderMode::kNone && - (m != ShaderMode::kClampToBorder || filter > Filter::kNearest); + // To keep things a little simpler, when we have filtering logic in the shader we + // operate on unnormalized texture coordinates. We will add a uniform that stores + // {w, h, 1/w, 1/h} in a float4 below. + auto modeRequiresUnormCoords = [](ShaderMode m) { + switch (m) { + case ShaderMode::kNone: return false; + case ShaderMode::kClamp: return false; + case ShaderMode::kRepeatNearest: return false; + case ShaderMode::kRepeatBilerp: return true; + case ShaderMode::kRepeatMipMap: return true; + case ShaderMode::kMirrorRepeat: return false; + case ShaderMode::kClampToBorderNearest: return true; + case ShaderMode::kClampToBorderFilter: return true; + } + SkUNREACHABLE; }; bool useSubset[2] = {modeUsesSubset(m[0]), modeUsesSubset(m[1])}; @@ -389,12 +431,9 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const { &te, kFragment_GrShaderFlag, kFloat4_GrSLType, "clamp", &clampName); } - // To keep things a little simpler, when we have filtering logic in the shader we - // operate on unnormalized texture coordinates. We add a uniform that stores - // {w, h, 1/w, 1/h} in a float4. const char* norm = nullptr; - if (normCoords && (filterLogic[0] != FilterLogic::kNone || - filterLogic[1] != FilterLogic::kNone)) { + if (normCoords && (modeRequiresUnormCoords(m[0]) || + modeRequiresUnormCoords(m[1]))) { // TODO: Detect support for textureSize() or polyfill textureSize() in SkSL and // always use? fNormUni = args.fUniformHandler->addUniform(&te, kFragment_GrShaderFlag, @@ -428,55 +467,56 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const { // These modes either don't use the subset rect or don't need to map the // coords to be within the subset. case ShaderMode::kNone: - case ShaderMode::kClampToBorder: + case ShaderMode::kClampToBorderNearest: + case ShaderMode::kClampToBorderFilter: case ShaderMode::kClamp: fb->codeAppendf("subsetCoord.%s = inCoord.%s;", coordSwizzle, coordSwizzle); break; - case ShaderMode::kRepeat: - if (filter == Filter::kMipMap) { - // The approach here is to generate two sets of texture coords that - // are both "moving" at the same speed (if not direction) as - // inCoords. We accomplish that by using two out of phase mirror - // repeat coords. We will always sample using both coords but the - // read from the upward sloping one is selected using a weight - // that transitions from one set to the other near the reflection - // point. Like the coords, the weight is a saw-tooth function, - // phase-shifted, vertically translated, and then clamped to 0..1. - // TODO: Skip this and use textureGrad() when available. - SkASSERT(extraCoord); - SkASSERT(coordWeight); - fb->codeAppend("{"); - fb->codeAppendf("float w = %s.%s - %s.%s;", subsetName, - subsetStopSwizzle, subsetName, subsetStartSwizzle); - fb->codeAppendf("float w2 = 2 * w;"); - fb->codeAppendf("float d = inCoord.%s - %s.%s;", coordSwizzle, - subsetName, subsetStartSwizzle); - fb->codeAppend("float m = mod(d, w2);"); - fb->codeAppend("float o = mix(m, w2 - m, step(w, m));"); - fb->codeAppendf("subsetCoord.%s = o + %s.%s;", coordSwizzle, - subsetName, subsetStartSwizzle); - fb->codeAppendf("%s = w - o + %s.%s;", extraCoord, subsetName, - subsetStartSwizzle); - // coordWeight is used as the third param of mix() to blend between a - // sample taken using subsetCoord and a sample at extraCoord. - fb->codeAppend("float hw = w/2;"); - fb->codeAppend("float n = mod(d - hw, w2);"); - fb->codeAppendf( - "%s = saturate(half(mix(n, w2 - n, step(w, n)) - hw + " - "0.5));", - coordWeight); - fb->codeAppend("}"); - } else { - fb->codeAppendf( - "subsetCoord.%s = mod(inCoord.%s - %s.%s, %s.%s - %s.%s) + " - "%s.%s;", - coordSwizzle, coordSwizzle, subsetName, subsetStartSwizzle, - subsetName, subsetStopSwizzle, subsetName, - subsetStartSwizzle, subsetName, subsetStartSwizzle); - } + case ShaderMode::kRepeatNearest: + case ShaderMode::kRepeatBilerp: + fb->codeAppendf( + "subsetCoord.%s = mod(inCoord.%s - %s.%s, %s.%s - %s.%s) + " + "%s.%s;", + coordSwizzle, coordSwizzle, subsetName, subsetStartSwizzle, + subsetName, subsetStopSwizzle, subsetName, subsetStartSwizzle, + subsetName, subsetStartSwizzle); + break; + case ShaderMode::kRepeatMipMap: + // The approach here is to generate two sets of texture coords that + // are both "moving" at the same speed (if not direction) as + // inCoords. We accomplish that by using two out of phase mirror + // repeat coords. We will always sample using both coords but the + // read from the upward sloping one is selected using a weight + // that transitions from one set to the other near the reflection + // point. Like the coords, the weight is a saw-tooth function, + // phase-shifted, vertically translated, and then clamped to 0..1. + // TODO: Skip this and use textureGrad() when available. + SkASSERT(extraCoord); + SkASSERT(coordWeight); + fb->codeAppend("{"); + fb->codeAppendf("float w = %s.%s - %s.%s;", subsetName, + subsetStopSwizzle, subsetName, subsetStartSwizzle); + fb->codeAppendf("float w2 = 2 * w;"); + fb->codeAppendf("float d = inCoord.%s - %s.%s;", coordSwizzle, + subsetName, subsetStartSwizzle); + fb->codeAppend("float m = mod(d, w2);"); + fb->codeAppend("float o = mix(m, w2 - m, step(w, m));"); + fb->codeAppendf("subsetCoord.%s = o + %s.%s;", coordSwizzle, subsetName, + subsetStartSwizzle); + fb->codeAppendf("%s = w - o + %s.%s;", extraCoord, subsetName, + subsetStartSwizzle); + // coordWeight is used as the third param of mix() to blend between a + // sample taken using subsetCoord and a sample at extraCoord. + fb->codeAppend("float hw = w/2;"); + fb->codeAppend("float n = mod(d - hw, w2);"); + fb->codeAppendf( + "%s = saturate(half(mix(n, w2 - n, step(w, n)) - hw + " + "0.5));", + coordWeight); + fb->codeAppend("}"); break; - case ShaderMode::kMirrorRepeat: { + case ShaderMode::kMirrorRepeat: fb->codeAppend("{"); fb->codeAppendf("float w = %s.%s - %s.%s;", subsetName, subsetStopSwizzle, subsetName, subsetStartSwizzle); @@ -487,7 +527,6 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const { coordSwizzle, subsetName, subsetStartSwizzle); fb->codeAppend("}"); break; - } } }; @@ -510,12 +549,12 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const { const char* repeatCoordWeightX = nullptr; const char* extraRepeatCoordY = nullptr; const char* repeatCoordWeightY = nullptr; - if (filterLogic[0] == FilterLogic::kRepeatMipMap) { + if (m[0] == ShaderMode::kRepeatMipMap) { fb->codeAppend("float extraRepeatCoordX; half repeatCoordWeightX;"); extraRepeatCoordX = "extraRepeatCoordX"; repeatCoordWeightX = "repeatCoordWeightX"; } - if (filterLogic[1] == FilterLogic::kRepeatMipMap) { + if (m[1] == ShaderMode::kRepeatMipMap) { fb->codeAppend("float extraRepeatCoordY; half repeatCoordWeightY;"); extraRepeatCoordY = "extraRepeatCoordY"; repeatCoordWeightY = "repeatCoordWeightY"; @@ -532,11 +571,11 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const { clampCoord(useClamp[1], "y", "y", "w"); // Additional clamping for the extra coords for kRepeatMipMap. - if (filterLogic[0] == FilterLogic::kRepeatMipMap) { + if (m[0] == ShaderMode::kRepeatMipMap) { fb->codeAppendf("extraRepeatCoordX = clamp(extraRepeatCoordX, %s.x, %s.z);", clampName, clampName); } - if (filterLogic[1] == FilterLogic::kRepeatMipMap) { + if (m[1] == ShaderMode::kRepeatMipMap) { fb->codeAppendf("extraRepeatCoordY = clamp(extraRepeatCoordY, %s.y, %s.w);", clampName, clampName); } @@ -544,8 +583,7 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const { // Do the 2 or 4 texture reads for kRepeatMipMap and then apply the weight(s) // to blend between them. If neither direction is kRepeatMipMap do a single // read at clampedCoord. - if (filterLogic[0] == FilterLogic::kRepeatMipMap && - filterLogic[1] == FilterLogic::kRepeatMipMap) { + if (m[0] == ShaderMode::kRepeatMipMap && m[1] == ShaderMode::kRepeatMipMap) { fb->codeAppendf( "half4 textureColor =" " mix(mix(%s, %s, repeatCoordWeightX)," @@ -556,11 +594,11 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const { read("float2(clampedCoord.x, extraRepeatCoordY)").c_str(), read("float2(extraRepeatCoordX, extraRepeatCoordY)").c_str()); - } else if (filterLogic[0] == FilterLogic::kRepeatMipMap) { + } else if (m[0] == ShaderMode::kRepeatMipMap) { fb->codeAppendf("half4 textureColor = mix(%s, %s, repeatCoordWeightX);", read("clampedCoord").c_str(), read("float2(extraRepeatCoordX, clampedCoord.y)").c_str()); - } else if (filterLogic[1] == FilterLogic::kRepeatMipMap) { + } else if (m[1] == ShaderMode::kRepeatMipMap) { fb->codeAppendf("half4 textureColor = mix(%s, %s, repeatCoordWeightY);", read("clampedCoord").c_str(), read("float2(clampedCoord.x, extraRepeatCoordY)").c_str()); @@ -575,15 +613,13 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const { // Calculate the amount the coord moved for clamping. This will be used // to implement shader-based filtering for kClampToBorder and kRepeat. - if (filterLogic[0] == FilterLogic::kRepeatBilerp || - filterLogic[0] == FilterLogic::kClampToBorderFilter) { + if (m[0] == ShaderMode::kRepeatBilerp || m[0] == ShaderMode::kClampToBorderFilter) { fb->codeAppend("half errX = half(subsetCoord.x - clampedCoord.x);"); fb->codeAppendf("float repeatCoordX = errX > 0 ? %s.x : %s.z;", clampName, clampName); repeatBilerpReadX = read("float2(repeatCoordX, clampedCoord.y)"); } - if (filterLogic[1] == FilterLogic::kRepeatBilerp || - filterLogic[1] == FilterLogic::kClampToBorderFilter) { + if (m[1] == ShaderMode::kRepeatBilerp || m[1] == ShaderMode::kClampToBorderFilter) { fb->codeAppend("half errY = half(subsetCoord.y - clampedCoord.y);"); fb->codeAppendf("float repeatCoordY = errY > 0 ? %s.y : %s.w;", clampName, clampName); @@ -595,8 +631,7 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const { // or a corner. Then blend the multiple reads using the err values calculated // above. const char* ifStr = "if"; - if (filterLogic[0] == FilterLogic::kRepeatBilerp && - filterLogic[1] == FilterLogic::kRepeatBilerp) { + if (m[0] == ShaderMode::kRepeatBilerp && m[1] == ShaderMode::kRepeatBilerp) { auto repeatBilerpReadXY = read("float2(repeatCoordX, repeatCoordY)"); fb->codeAppendf( "if (errX != 0 && errY != 0) {" @@ -609,14 +644,14 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const { repeatBilerpReadXY.c_str()); ifStr = "else if"; } - if (filterLogic[0] == FilterLogic::kRepeatBilerp) { + if (m[0] == ShaderMode::kRepeatBilerp) { fb->codeAppendf( "%s (errX != 0) {" " textureColor = mix(textureColor, %s, abs(errX));" "}", ifStr, repeatBilerpReadX.c_str()); } - if (filterLogic[1] == FilterLogic::kRepeatBilerp) { + if (m[1] == ShaderMode::kRepeatBilerp) { fb->codeAppendf( "%s (errY != 0) {" " textureColor = mix(textureColor, %s, abs(errY));" @@ -626,27 +661,30 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const { // Do soft edge shader filtering against border color for kClampToBorderFilter using // the err values calculated above. - if (filterLogic[0] == FilterLogic::kClampToBorderFilter) { + if (m[0] == ShaderMode::kClampToBorderFilter) { fb->codeAppendf("textureColor = mix(textureColor, %s, min(abs(errX), 1));", borderName); } - if (filterLogic[1] == FilterLogic::kClampToBorderFilter) { + if (m[1] == ShaderMode::kClampToBorderFilter) { fb->codeAppendf("textureColor = mix(textureColor, %s, min(abs(errY), 1));", borderName); } // Do hard-edge shader transition to border color for kClampToBorderNearest at the - // subset boundaries. - if (filterLogic[0] == FilterLogic::kClampToBorderNearest) { + // subset boundaries. Snap the input coordinates to nearest neighbor (with an + // epsilon) before comparing to the subset rect to avoid GPU interpolation errors + if (m[0] == ShaderMode::kClampToBorderNearest) { fb->codeAppendf( - "if (inCoord.x < %s.x || inCoord.x > %s.z) {" + "float snappedX = floor(inCoord.x + 0.001) + 0.5;" + "if (snappedX < %s.x || snappedX > %s.z) {" " textureColor = %s;" "}", subsetName, subsetName, borderName); } - if (filterLogic[1] == FilterLogic::kClampToBorderNearest) { + if (m[1] == ShaderMode::kClampToBorderNearest) { fb->codeAppendf( - "if (inCoord.y < %s.y || inCoord.y > %s.w) {" + "float snappedY = floor(inCoord.y + 0.001) + 0.5;" + "if (snappedY < %s.y || snappedY > %s.w) {" " textureColor = %s;" "}", subsetName, subsetName, borderName); @@ -708,10 +746,7 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const { void GrTextureEffect::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const { auto m0 = static_cast<uint32_t>(fShaderModes[0]); auto m1 = static_cast<uint32_t>(fShaderModes[1]); - auto filter = fSampler.samplerState().filter(); - auto l0 = static_cast<uint32_t>(GetFilterLogic(fShaderModes[0], filter)); - auto l1 = static_cast<uint32_t>(GetFilterLogic(fShaderModes[1], filter)); - b->add32((l0 << 24) | (l1 << 16) | (m0 << 8) | m1); + b->add32((m0 << 16) | m1); } bool GrTextureEffect::onIsEqual(const GrFragmentProcessor& other) const { @@ -722,9 +757,7 @@ bool GrTextureEffect::onIsEqual(const GrFragmentProcessor& other) const { if (fSubset != that.fSubset) { return false; } - if ((fShaderModes[0] == ShaderMode::kClampToBorder || - fShaderModes[1] == ShaderMode::kClampToBorder) && - !std::equal(fBorder, fBorder + 4, that.fBorder)) { + if (this->hasClampToBorderShaderMode() && !std::equal(fBorder, fBorder + 4, that.fBorder)) { return false; } return true; diff --git a/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.h b/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.h index c808bfb3018..47acda81472 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.h @@ -71,28 +71,24 @@ public: const char* name() const override { return "TextureEffect"; } private: - enum class ShaderMode : uint16_t { - kClamp = static_cast<int>(GrSamplerState::WrapMode::kClamp), - kRepeat = static_cast<int>(GrSamplerState::WrapMode::kRepeat), - kMirrorRepeat = static_cast<int>(GrSamplerState::WrapMode::kMirrorRepeat), - kClampToBorder = static_cast<int>(GrSamplerState::WrapMode::kClampToBorder), - kNone, - }; - struct Sampling; /** - * Sometimes the implementation of a ShaderMode depends on which GrSamplerState::Filter is - * used. + * Possible implementation of wrap mode in shader code. Some modes are specialized by + * filter. */ - enum class FilterLogic { - kNone, // The shader isn't specialized for the filter. + enum class ShaderMode : uint16_t { + kNone, // Using HW mode + kClamp, // Shader based clamp, no filter specialization + kRepeatNearest, // Simple repeat for nearest sampling kRepeatBilerp, // Filter across the subset boundary for kRepeat mode kRepeatMipMap, // Logic for LOD selection with kRepeat mode. - kClampToBorderFilter, // Logic for fading to border color when filtering. + kMirrorRepeat, // Mirror repeat (doesn't depend on filter)) kClampToBorderNearest, // Logic for hard transition to border color when not filtering. + kClampToBorderFilter, // Logic for fading to border color when filtering. }; - static FilterLogic GetFilterLogic(ShaderMode mode, GrSamplerState::Filter filter); + static ShaderMode GetShaderMode(GrSamplerState::WrapMode, GrSamplerState::Filter); + static bool ShaderModeIsClampToBorder(ShaderMode); GrCoordTransform fCoordTransform; TextureSampler fSampler; @@ -115,6 +111,11 @@ private: const TextureSampler& onTextureSampler(int) const override; + bool hasClampToBorderShaderMode() const { + return ShaderModeIsClampToBorder(fShaderModes[0]) || + ShaderModeIsClampToBorder(fShaderModes[1]); + } + GR_DECLARE_FRAGMENT_PROCESSOR_TEST typedef GrFragmentProcessor INHERITED; diff --git a/chromium/third_party/skia/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/GrXfermodeFragmentProcessor.cpp index 3d060a69fa9..fe09020845c 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrXfermodeFragmentProcessor.cpp +++ b/chromium/third_party/skia/src/gpu/effects/GrXfermodeFragmentProcessor.cpp @@ -62,8 +62,8 @@ private: SkBlendMode mode) : INHERITED(kComposeTwoFragmentProcessor_ClassID, OptFlags(src.get(), dst.get(), mode)) , fMode(mode) { - SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(std::move(src)); - SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(std::move(dst)); + SkDEBUGCODE(int shaderAChildIndex = )this->registerChild(std::move(src)); + SkDEBUGCODE(int shaderBChildIndex = )this->registerChild(std::move(dst)); SkASSERT(0 == shaderAChildIndex); SkASSERT(1 == shaderBChildIndex); } @@ -245,7 +245,7 @@ std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoPro SkBlendMode mode) { switch (mode) { case SkBlendMode::kClear: - return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT, + return GrConstColorProcessor::Make(/*inputFP=*/nullptr, SK_PMColor4fTRANSPARENT, GrConstColorProcessor::InputMode::kIgnore); case SkBlendMode::kSrc: return src; @@ -413,7 +413,7 @@ private: : INHERITED(kComposeOneFragmentProcessor_ClassID, OptFlags(fp.get(), mode, child)) , fMode(mode) , fChild(child) { - SkDEBUGCODE(int dstIndex =) this->registerChildProcessor(std::move(fp)); + SkDEBUGCODE(int dstIndex =) this->registerChild(std::move(fp)); SkASSERT(0 == dstIndex); } @@ -496,7 +496,7 @@ std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstPro std::unique_ptr<GrFragmentProcessor> dst, SkBlendMode mode) { switch (mode) { case SkBlendMode::kClear: - return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT, + return GrConstColorProcessor::Make(/*inputFP=*/nullptr, SK_PMColor4fTRANSPARENT, GrConstColorProcessor::InputMode::kIgnore); case SkBlendMode::kSrc: return nullptr; @@ -510,7 +510,7 @@ std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcPro std::unique_ptr<GrFragmentProcessor> src, SkBlendMode mode) { switch (mode) { case SkBlendMode::kClear: - return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT, + return GrConstColorProcessor::Make(/*inputFP=*/nullptr, SK_PMColor4fTRANSPARENT, GrConstColorProcessor::InputMode::kIgnore); case SkBlendMode::kDst: return nullptr; diff --git a/chromium/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp index 114f54b2aa6..ad0584a72b3 100644 --- a/chromium/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp @@ -74,7 +74,7 @@ std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(GrSurfaceProxyView v dimensions.height() == yDimensions.height() / 2 + 1) { sy = 0.5f; } - *planeMatrix.writable() = SkMatrix::MakeScale(sx, sy); + *planeMatrix.writable() = SkMatrix::Scale(sx, sy); planeMatrix.writable()->preConcat(localMatrix); planeFilter = subsampledPlaneFilterMode; if (subset) { @@ -112,7 +112,7 @@ GrYUVtoRGBEffect::GrYUVtoRGBEffect(std::unique_ptr<GrFragmentProcessor> planeFPs ModulateForClampedSamplerOptFlags(alpha_type(yuvaIndices))) , fYUVColorSpace(yuvColorSpace) { for (int i = 0; i < numPlanes; ++i) { - this->registerChildProcessor(std::move(planeFPs[i])); + this->registerChild(std::move(planeFPs[i])); } std::copy_n(yuvaIndices, 4, fYUVAIndices); } @@ -251,10 +251,7 @@ bool GrYUVtoRGBEffect::onIsEqual(const GrFragmentProcessor& other) const { GrYUVtoRGBEffect::GrYUVtoRGBEffect(const GrYUVtoRGBEffect& src) : GrFragmentProcessor(kGrYUVtoRGBEffect_ClassID, src.optimizationFlags()) , fYUVColorSpace(src.fYUVColorSpace) { - int numPlanes = src.numChildProcessors(); - for (int i = 0; i < numPlanes; ++i) { - this->registerChildProcessor(this->childProcessor(i).clone()); - } + this->cloneAndRegisterAllChildProcessors(src); std::copy_n(src.fYUVAIndices, this->numChildProcessors(), fYUVAIndices); } diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.cpp index 63f3a67364a..233c42a7d0e 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.cpp @@ -28,34 +28,48 @@ public: auto rect = _outer.rect; (void)rect; prevRect = float4(-1.0); - rectUniformVar = args.fUniformHandler->addUniform( - &_outer, kFragment_GrShaderFlag, kFloat4_GrSLType, "rectUniform"); + rectUniformVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, + kFloat4_GrSLType, "rectUniform"); fragBuilder->codeAppendf( - "float4 prevRect = float4(%f, %f, %f, %f);\nhalf alpha;\n@switch (%d) {\n case " - "0:\n case 2:\n alpha = half(all(greaterThan(float4(sk_FragCoord.xy, " - "%s.zw), float4(%s.xy, sk_FragCoord.xy))) ? 1 : 0);\n break;\n " - "default:\n half xSub, ySub;\n xSub = min(half(sk_FragCoord.x - " - "%s.x), 0.0);\n xSub += min(half(%s.z - sk_FragCoord.x), 0.0);\n " - "ySub = min(half(sk_FragCoord.y - %s.y), 0.0);\n ySub += min(half(%s.w - " - "sk_FragCoord.y), 0.0);\n alpha = (1.0 + ", - prevRect.left(), - prevRect.top(), - prevRect.right(), - prevRect.bottom(), - (int)_outer.edgeType, - args.fUniformHandler->getUniformCStr(rectUniformVar), + R"SkSL(float4 prevRect = float4(%f, %f, %f, %f); +half alpha; +@switch (%d) { + case 0: + case 2: + alpha = half(all(greaterThan(float4(sk_FragCoord.xy, %s.zw), float4(%s.xy, sk_FragCoord.xy))) ? 1 : 0); + break; + default: + half xSub, ySub; + xSub = min(half(sk_FragCoord.x - %s.x), 0.0); + xSub += min(half(%s.z - sk_FragCoord.x), 0.0); + ySub = min(half(sk_FragCoord.y - %s.y), 0.0); + ySub += min(half(%s.w - sk_FragCoord.y), 0.0); + alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0)); +} +@if (%d == 2 || %d == 3) { + alpha = 1.0 - alpha; +})SkSL", + prevRect.left(), prevRect.top(), prevRect.right(), prevRect.bottom(), + (int)_outer.edgeType, args.fUniformHandler->getUniformCStr(rectUniformVar), args.fUniformHandler->getUniformCStr(rectUniformVar), args.fUniformHandler->getUniformCStr(rectUniformVar), args.fUniformHandler->getUniformCStr(rectUniformVar), args.fUniformHandler->getUniformCStr(rectUniformVar), - args.fUniformHandler->getUniformCStr(rectUniformVar)); + args.fUniformHandler->getUniformCStr(rectUniformVar), (int)_outer.edgeType, + (int)_outer.edgeType); + SkString _input1677(args.fInputColor); + SkString _sample1677; + if (_outer.inputFP_index >= 0) { + _sample1677 = this->invokeChild(_outer.inputFP_index, _input1677.c_str(), args); + } else { + _sample1677.swap(_input1677); + } fragBuilder->codeAppendf( - "max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n}\n@if (%d == 2 || %d == 3) {\n " - "alpha = 1.0 - alpha;\n}\n%s = %s * alpha;\n", - (int)_outer.edgeType, - (int)_outer.edgeType, - args.fOutputColor, - args.fInputColor); + R"SkSL( +half4 inputColor = %s; +%s = inputColor * alpha; +)SkSL", + _sample1677.c_str(), args.fOutputColor); } private: @@ -95,7 +109,11 @@ bool GrAARectEffect::onIsEqual(const GrFragmentProcessor& other) const { GrAARectEffect::GrAARectEffect(const GrAARectEffect& src) : INHERITED(kGrAARectEffect_ClassID, src.optimizationFlags()) , edgeType(src.edgeType) - , rect(src.rect) {} + , rect(src.rect) { + if (src.inputFP_index >= 0) { + inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); + } +} std::unique_ptr<GrFragmentProcessor> GrAARectEffect::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrAARectEffect(*this)); } @@ -111,7 +129,7 @@ std::unique_ptr<GrFragmentProcessor> GrAARectEffect::TestCreate(GrProcessorTestD GrClipEdgeType edgeType = static_cast<GrClipEdgeType>(d->fRandom->nextULessThan(kGrClipEdgeTypeCnt)); - fp = GrAARectEffect::Make(edgeType, rect); + fp = GrAARectEffect::Make(/*inputFP=*/nullptr, edgeType, rect); } while (nullptr == fp); return fp; } diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.h index 42324b4c6dc..88891e443b5 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.h @@ -10,28 +10,42 @@ **************************************************************************************************/ #ifndef GrAARectEffect_DEFINED #define GrAARectEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrAARectEffect : public GrFragmentProcessor { public: - static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, SkRect rect) { - return std::unique_ptr<GrFragmentProcessor>(new GrAARectEffect(edgeType, rect)); + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, + SkRect rect) { + return std::unique_ptr<GrFragmentProcessor>( + new GrAARectEffect(std::move(inputFP), edgeType, rect)); } GrAARectEffect(const GrAARectEffect& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "AARectEffect"; } + int inputFP_index = -1; GrClipEdgeType edgeType; SkRect rect; private: - GrAARectEffect(GrClipEdgeType edgeType, SkRect rect) + GrAARectEffect(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, + SkRect rect) : INHERITED(kGrAARectEffect_ClassID, - (OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag) + (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get()) + : kAll_OptimizationFlags) & + kCompatibleWithCoverageAsAlpha_OptimizationFlag) , edgeType(edgeType) - , rect(rect) {} + , rect(rect) { + if (inputFP) { + inputFP_index = this->registerChild(std::move(inputFP)); + } + } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp index 915684f1222..c9f7c7bf634 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp @@ -10,15 +10,6 @@ **************************************************************************************************/ #include "GrAlphaThresholdFragmentProcessor.h" -inline GrFragmentProcessor::OptimizationFlags GrAlphaThresholdFragmentProcessor::optFlags( - float outerThreshold) { - if (outerThreshold >= 1.0) { - return kPreservesOpaqueInput_OptimizationFlag | - kCompatibleWithCoverageAsAlpha_OptimizationFlag; - } else { - return kCompatibleWithCoverageAsAlpha_OptimizationFlag; - } -} #include "src/gpu/GrTexture.h" #include "src/gpu/glsl/GrGLSLFragmentProcessor.h" #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" @@ -41,22 +32,34 @@ public: kHalf_GrSLType, "innerThreshold"); outerThresholdVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf_GrSLType, "outerThreshold"); - SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D( - args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix()); + SkString _input515(args.fInputColor); + SkString _sample515; + if (_outer.inputFP_index >= 0) { + _sample515 = this->invokeChild(_outer.inputFP_index, _input515.c_str(), args); + } else { + _sample515.swap(_input515); + } fragBuilder->codeAppendf( - "half4 color = %s;\nhalf4 mask_color = sample(%s, %s).%s;\nif (mask_color.w < 0.5) " - "{\n if (color.w > %s) {\n half scale = %s / color.w;\n color.xyz " - "*= scale;\n color.w = %s;\n }\n} else if (color.w < %s) {\n half " - "scale = %s / max(0.0010000000474974513, color.w);\n color.xyz *= scale;\n " - "color.w = %s;\n}\n%s = color;\n", - args.fInputColor, - fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]), - sk_TransformedCoords2D_0.c_str(), - fragBuilder->getProgramBuilder() - ->samplerSwizzle(args.fTexSamplers[0]) - .asString() - .c_str(), - args.fUniformHandler->getUniformCStr(outerThresholdVar), + R"SkSL(half4 color = %s;)SkSL", _sample515.c_str()); + SkString _sample567; + _sample567 = this->invokeChild(_outer.maskFP_index, args); + fragBuilder->codeAppendf( + R"SkSL( +half4 mask_color = %s; +if (mask_color.w < 0.5) { + if (color.w > %s) { + half scale = %s / color.w; + color.xyz *= scale; + color.w = %s; + } +} else if (color.w < %s) { + half scale = %s / max(0.0010000000474974513, color.w); + color.xyz *= scale; + color.w = %s; +} +%s = color; +)SkSL", + _sample567.c_str(), args.fUniformHandler->getUniformCStr(outerThresholdVar), args.fUniformHandler->getUniformCStr(outerThresholdVar), args.fUniformHandler->getUniformCStr(outerThresholdVar), args.fUniformHandler->getUniformCStr(innerThresholdVar), @@ -85,7 +88,6 @@ void GrAlphaThresholdFragmentProcessor::onGetGLSLProcessorKey(const GrShaderCaps bool GrAlphaThresholdFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const { const GrAlphaThresholdFragmentProcessor& that = other.cast<GrAlphaThresholdFragmentProcessor>(); (void)that; - if (mask != that.mask) return false; if (innerThreshold != that.innerThreshold) return false; if (outerThreshold != that.outerThreshold) return false; return true; @@ -93,37 +95,30 @@ bool GrAlphaThresholdFragmentProcessor::onIsEqual(const GrFragmentProcessor& oth GrAlphaThresholdFragmentProcessor::GrAlphaThresholdFragmentProcessor( const GrAlphaThresholdFragmentProcessor& src) : INHERITED(kGrAlphaThresholdFragmentProcessor_ClassID, src.optimizationFlags()) - , maskCoordTransform(src.maskCoordTransform) - , mask(src.mask) , innerThreshold(src.innerThreshold) , outerThreshold(src.outerThreshold) { - this->setTextureSamplerCnt(1); - this->addCoordTransform(&maskCoordTransform); + if (src.inputFP_index >= 0) { + inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); + } + { maskFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.maskFP_index)); } } std::unique_ptr<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrAlphaThresholdFragmentProcessor(*this)); } -const GrFragmentProcessor::TextureSampler& GrAlphaThresholdFragmentProcessor::onTextureSampler( - int index) const { - return IthTextureSampler(index, mask); -} GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrAlphaThresholdFragmentProcessor); #if GR_TEST_UTILS std::unique_ptr<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::TestCreate( GrProcessorTestData* testData) { - auto[maskView, ct, at] = testData->randomAlphaOnlyView(); - // Make the inner and outer thresholds be in (0, 1) exclusive and be sorted correctly. - float innerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f; - float outerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f; - const int kMaxWidth = 1000; - const int kMaxHeight = 1000; - uint32_t width = testData->fRandom->nextULessThan(kMaxWidth); - uint32_t height = testData->fRandom->nextULessThan(kMaxHeight); - uint32_t x = testData->fRandom->nextULessThan(kMaxWidth - width); - uint32_t y = testData->fRandom->nextULessThan(kMaxHeight - height); - SkIRect bounds = SkIRect::MakeXYWH(x, y, width, height); + // Make the inner and outer thresholds be in [0, 1]. + float outerThresh = testData->fRandom->nextUScalar1(); + float innerThresh = testData->fRandom->nextUScalar1(); + std::unique_ptr<GrFragmentProcessor> inputChild, maskChild; + if (testData->fRandom->nextBool()) { + inputChild = GrProcessorUnitTest::MakeChildFP(testData); + } + maskChild = GrProcessorUnitTest::MakeChildFP(testData); - return GrAlphaThresholdFragmentProcessor::Make(std::move(maskView), innerThresh, outerThresh, - bounds); + return GrAlphaThresholdFragmentProcessor::Make(std::move(inputChild), std::move(maskChild), + innerThresh, outerThresh); } #endif diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.h index c4de913733f..eeb9e9cfa51 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.h @@ -10,50 +10,51 @@ **************************************************************************************************/ #ifndef GrAlphaThresholdFragmentProcessor_DEFINED #define GrAlphaThresholdFragmentProcessor_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrAlphaThresholdFragmentProcessor : public GrFragmentProcessor { public: - inline OptimizationFlags optFlags(float outerThreshold); - - static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView mask, + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP, + std::unique_ptr<GrFragmentProcessor> maskFP, float innerThreshold, - float outerThreshold, - const SkIRect& bounds) { + float outerThreshold) { return std::unique_ptr<GrFragmentProcessor>(new GrAlphaThresholdFragmentProcessor( - std::move(mask), innerThreshold, outerThreshold, bounds)); + std::move(inputFP), std::move(maskFP), innerThreshold, outerThreshold)); } GrAlphaThresholdFragmentProcessor(const GrAlphaThresholdFragmentProcessor& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "AlphaThresholdFragmentProcessor"; } - GrCoordTransform maskCoordTransform; - TextureSampler mask; + int inputFP_index = -1; + int maskFP_index = -1; float innerThreshold; float outerThreshold; private: - GrAlphaThresholdFragmentProcessor(GrSurfaceProxyView mask, + GrAlphaThresholdFragmentProcessor(std::unique_ptr<GrFragmentProcessor> inputFP, + std::unique_ptr<GrFragmentProcessor> maskFP, float innerThreshold, - float outerThreshold, - const SkIRect& bounds) - : INHERITED(kGrAlphaThresholdFragmentProcessor_ClassID, kNone_OptimizationFlags) - , maskCoordTransform( - SkMatrix::MakeTrans(SkIntToScalar(-bounds.x()), SkIntToScalar(-bounds.y())), - mask.proxy(), - mask.origin()) - , mask(std::move(mask)) + float outerThreshold) + : INHERITED(kGrAlphaThresholdFragmentProcessor_ClassID, + (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get()) + : kAll_OptimizationFlags) & + ((outerThreshold >= 1.0) ? kPreservesOpaqueInput_OptimizationFlag + : kNone_OptimizationFlags)) , innerThreshold(innerThreshold) , outerThreshold(outerThreshold) { - this->setTextureSamplerCnt(1); - this->addCoordTransform(&maskCoordTransform); + if (inputFP) { + inputFP_index = this->registerChild(std::move(inputFP)); + } + SkASSERT(maskFP); + maskFP_index = this->registerChild(std::move(maskFP)); } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; - const TextureSampler& onTextureSampler(int) const override; GR_DECLARE_FRAGMENT_PROCESSOR_TEST typedef GrFragmentProcessor INHERITED; }; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp index 5c6dbc3db6f..3d5b7b12380 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp @@ -26,12 +26,27 @@ public: (void)_outer; auto mode = _outer.mode; (void)mode; + SkString _input308(args.fInputColor); + SkString _sample308; + if (_outer.inputFP_index >= 0) { + _sample308 = this->invokeChild(_outer.inputFP_index, _input308.c_str(), args); + } else { + _sample308.swap(_input308); + } fragBuilder->codeAppendf( - "half factor = 1.0 - %s.w;\n@switch (%d) {\n case 0:\n factor = " - "exp((-factor * factor) * 4.0) - 0.017999999225139618;\n break;\n case " - "1:\n factor = smoothstep(1.0, 0.0, factor);\n break;\n}\n%s = " - "half4(factor);\n", - args.fInputColor, (int)_outer.mode, args.fOutputColor); + R"SkSL(half inputAlpha = %s.w; +half factor = 1.0 - inputAlpha; +@switch (%d) { + case 0: + factor = exp((-factor * factor) * 4.0) - 0.017999999225139618; + break; + case 1: + factor = smoothstep(1.0, 0.0, factor); + break; +} +%s = half4(factor); +)SkSL", + _sample308.c_str(), (int)_outer.mode, args.fOutputColor); } private: @@ -54,7 +69,11 @@ bool GrBlurredEdgeFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) GrBlurredEdgeFragmentProcessor::GrBlurredEdgeFragmentProcessor( const GrBlurredEdgeFragmentProcessor& src) : INHERITED(kGrBlurredEdgeFragmentProcessor_ClassID, src.optimizationFlags()) - , mode(src.mode) {} + , mode(src.mode) { + if (src.inputFP_index >= 0) { + inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); + } +} std::unique_ptr<GrFragmentProcessor> GrBlurredEdgeFragmentProcessor::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrBlurredEdgeFragmentProcessor(*this)); } diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.h index 188280327a9..d9c0c3b5516 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.h @@ -10,26 +10,35 @@ **************************************************************************************************/ #ifndef GrBlurredEdgeFragmentProcessor_DEFINED #define GrBlurredEdgeFragmentProcessor_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrBlurredEdgeFragmentProcessor : public GrFragmentProcessor { public: enum class Mode { kGaussian = 0, kSmoothStep = 1 }; - static std::unique_ptr<GrFragmentProcessor> Make(Mode mode) { - return std::unique_ptr<GrFragmentProcessor>(new GrBlurredEdgeFragmentProcessor(mode)); + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP, + Mode mode) { + return std::unique_ptr<GrFragmentProcessor>( + new GrBlurredEdgeFragmentProcessor(std::move(inputFP), mode)); } GrBlurredEdgeFragmentProcessor(const GrBlurredEdgeFragmentProcessor& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "BlurredEdgeFragmentProcessor"; } + int inputFP_index = -1; Mode mode; private: - GrBlurredEdgeFragmentProcessor(Mode mode) + GrBlurredEdgeFragmentProcessor(std::unique_ptr<GrFragmentProcessor> inputFP, Mode mode) : INHERITED(kGrBlurredEdgeFragmentProcessor_ClassID, kNone_OptimizationFlags) - , mode(mode) {} + , mode(mode) { + if (inputFP) { + inputFP_index = this->registerChild(std::move(inputFP)); + } + } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp index 451dd98d0d4..67449dd8a54 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp @@ -177,14 +177,14 @@ static void create_half_plane_profile(uint8_t* profile, int profileWidth) { profile[profileWidth - 1] = 0; } -static GrSurfaceProxyView create_profile_texture(GrRecordingContext* context, - const SkRect& circle, - float sigma, - float* solidRadius, - float* textureRadius) { +static std::unique_ptr<GrFragmentProcessor> create_profile_effect(GrRecordingContext* context, + const SkRect& circle, + float sigma, + float* solidRadius, + float* textureRadius) { float circleR = circle.width() / 2.0f; if (circleR < SK_ScalarNearlyZero) { - return {}; + return nullptr; } // Profile textures are cached by the ratio of sigma to circle radius and by the size of the // profile texture (binned by powers of 2). @@ -214,6 +214,12 @@ static GrSurfaceProxyView create_profile_texture(GrRecordingContext* context, *textureRadius = circleR + 3 * sigma; } + static constexpr int kProfileTextureWidth = 512; + // This would be kProfileTextureWidth/textureRadius if it weren't for the fact that we do + // the calculation of the profile coord in a coord space that has already been scaled by + // 1 / textureRadius. This is done to avoid overflow in length(). + SkMatrix texM = SkMatrix::Scale(kProfileTextureWidth, 1.f); + static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); GrUniqueKey key; GrUniqueKey::Builder builder(&key, kDomain, 1, "1-D Circular Blur"); @@ -224,14 +230,13 @@ static GrSurfaceProxyView create_profile_texture(GrRecordingContext* context, if (sk_sp<GrTextureProxy> blurProfile = proxyProvider->findOrCreateProxyByUniqueKey(key)) { GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(blurProfile->backendFormat(), GrColorType::kAlpha_8); - return {std::move(blurProfile), kTopLeft_GrSurfaceOrigin, swizzle}; + GrSurfaceProxyView profileView{std::move(blurProfile), kTopLeft_GrSurfaceOrigin, swizzle}; + return GrTextureEffect::Make(std::move(profileView), kPremul_SkAlphaType, texM); } - static constexpr int kProfileTextureWidth = 512; - SkBitmap bm; if (!bm.tryAllocPixels(SkImageInfo::MakeA8(kProfileTextureWidth, 1))) { - return {}; + return nullptr; } if (useHalfPlaneApprox) { @@ -246,25 +251,28 @@ static GrSurfaceProxyView create_profile_texture(GrRecordingContext* context, bm.setImmutable(); GrBitmapTextureMaker maker(context, bm, GrImageTexGenPolicy::kNew_Uncached_Budgeted); - auto blurView = maker.view(GrMipMapped::kNo); - if (!blurView) { - return {}; + auto profileView = maker.view(GrMipMapped::kNo); + if (!profileView) { + return nullptr; } - proxyProvider->assignUniqueKeyToProxy(key, blurView.asTextureProxy()); - return blurView; + proxyProvider->assignUniqueKeyToProxy(key, profileView.asTextureProxy()); + return GrTextureEffect::Make(std::move(profileView), kPremul_SkAlphaType, texM); } std::unique_ptr<GrFragmentProcessor> GrCircleBlurFragmentProcessor::Make( - GrRecordingContext* context, const SkRect& circle, float sigma) { + std::unique_ptr<GrFragmentProcessor> inputFP, + GrRecordingContext* context, + const SkRect& circle, + float sigma) { float solidRadius; float textureRadius; - GrSurfaceProxyView profile = - create_profile_texture(context, circle, sigma, &solidRadius, &textureRadius); + std::unique_ptr<GrFragmentProcessor> profile = + create_profile_effect(context, circle, sigma, &solidRadius, &textureRadius); if (!profile) { return nullptr; } return std::unique_ptr<GrFragmentProcessor>(new GrCircleBlurFragmentProcessor( - circle, textureRadius, solidRadius, std::move(profile))); + std::move(inputFP), circle, solidRadius, textureRadius, std::move(profile))); } #include "src/gpu/GrTexture.h" #include "src/gpu/glsl/GrGLSLFragmentProcessor.h" @@ -282,28 +290,39 @@ public: (void)_outer; auto circleRect = _outer.circleRect; (void)circleRect; - auto textureRadius = _outer.textureRadius; - (void)textureRadius; auto solidRadius = _outer.solidRadius; (void)solidRadius; + auto textureRadius = _outer.textureRadius; + (void)textureRadius; circleDataVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf4_GrSLType, "circleData"); fragBuilder->codeAppendf( - "half2 vec = half2(half((sk_FragCoord.x - float(%s.x)) * float(%s.w)), " - "half((sk_FragCoord.y - float(%s.y)) * float(%s.w)));\nhalf dist = length(vec) + " - "(0.5 - %s.z) * %s.w;\n%s = %s * sample(%s, float2(half2(dist, 0.5))).%s.w;\n", - args.fUniformHandler->getUniformCStr(circleDataVar), - args.fUniformHandler->getUniformCStr(circleDataVar), + R"SkSL(; +half2 vec = half2((sk_FragCoord.xy - float2(%s.xy)) * float(%s.w)); +half dist = length(vec) + (0.5 - %s.z) * %s.w;)SkSL", args.fUniformHandler->getUniformCStr(circleDataVar), args.fUniformHandler->getUniformCStr(circleDataVar), args.fUniformHandler->getUniformCStr(circleDataVar), - args.fUniformHandler->getUniformCStr(circleDataVar), args.fOutputColor, - args.fInputColor, - fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]), - fragBuilder->getProgramBuilder() - ->samplerSwizzle(args.fTexSamplers[0]) - .asString() - .c_str()); + args.fUniformHandler->getUniformCStr(circleDataVar)); + SkString _input13945(args.fInputColor); + SkString _sample13945; + if (_outer.inputFP_index >= 0) { + _sample13945 = this->invokeChild(_outer.inputFP_index, _input13945.c_str(), args); + } else { + _sample13945.swap(_input13945); + } + fragBuilder->codeAppendf( + R"SkSL( +half4 inputColor = %s;)SkSL", + _sample13945.c_str()); + SkString _sample14005; + SkString _coords14005("float2(half2(dist, 0.5))"); + _sample14005 = this->invokeChild(_outer.blurProfile_index, args, _coords14005.c_str()); + fragBuilder->codeAppendf( + R"SkSL( +%s = inputColor * %s.w; +)SkSL", + args.fOutputColor, _sample14005.c_str()); } private: @@ -312,13 +331,10 @@ private: const GrCircleBlurFragmentProcessor& _outer = _proc.cast<GrCircleBlurFragmentProcessor>(); auto circleRect = _outer.circleRect; (void)circleRect; - auto textureRadius = _outer.textureRadius; - (void)textureRadius; auto solidRadius = _outer.solidRadius; (void)solidRadius; - const GrSurfaceProxyView& blurProfileSamplerView = _outer.textureSampler(0).view(); - GrTexture& blurProfileSampler = *blurProfileSamplerView.proxy()->peekTexture(); - (void)blurProfileSampler; + auto textureRadius = _outer.textureRadius; + (void)textureRadius; UniformHandle& circleData = circleDataVar; (void)circleData; @@ -336,27 +352,27 @@ bool GrCircleBlurFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const GrCircleBlurFragmentProcessor& that = other.cast<GrCircleBlurFragmentProcessor>(); (void)that; if (circleRect != that.circleRect) return false; - if (textureRadius != that.textureRadius) return false; if (solidRadius != that.solidRadius) return false; - if (blurProfileSampler != that.blurProfileSampler) return false; + if (textureRadius != that.textureRadius) return false; return true; } GrCircleBlurFragmentProcessor::GrCircleBlurFragmentProcessor( const GrCircleBlurFragmentProcessor& src) : INHERITED(kGrCircleBlurFragmentProcessor_ClassID, src.optimizationFlags()) , circleRect(src.circleRect) - , textureRadius(src.textureRadius) , solidRadius(src.solidRadius) - , blurProfileSampler(src.blurProfileSampler) { - this->setTextureSamplerCnt(1); + , textureRadius(src.textureRadius) { + if (src.inputFP_index >= 0) { + inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); + } + { + blurProfile_index = + this->cloneAndRegisterChildProcessor(src.childProcessor(src.blurProfile_index)); + } } std::unique_ptr<GrFragmentProcessor> GrCircleBlurFragmentProcessor::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrCircleBlurFragmentProcessor(*this)); } -const GrFragmentProcessor::TextureSampler& GrCircleBlurFragmentProcessor::onTextureSampler( - int index) const { - return IthTextureSampler(index, blurProfileSampler); -} GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrCircleBlurFragmentProcessor); #if GR_TEST_UTILS std::unique_ptr<GrFragmentProcessor> GrCircleBlurFragmentProcessor::TestCreate( @@ -364,6 +380,7 @@ std::unique_ptr<GrFragmentProcessor> GrCircleBlurFragmentProcessor::TestCreate( SkScalar wh = testData->fRandom->nextRangeScalar(100.f, 1000.f); SkScalar sigma = testData->fRandom->nextRangeF(1.f, 10.f); SkRect circle = SkRect::MakeWH(wh, wh); - return GrCircleBlurFragmentProcessor::Make(testData->context(), circle, sigma); + return GrCircleBlurFragmentProcessor::Make(/*inputFP=*/nullptr, testData->context(), circle, + sigma); } #endif diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.h index b61315ac533..164ccdd8113 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.h @@ -10,41 +10,52 @@ **************************************************************************************************/ #ifndef GrCircleBlurFragmentProcessor_DEFINED #define GrCircleBlurFragmentProcessor_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" + +#include "src/gpu/effects/GrTextureEffect.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrCircleBlurFragmentProcessor : public GrFragmentProcessor { public: - static std::unique_ptr<GrFragmentProcessor> Make(GrRecordingContext*, + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrRecordingContext*, const SkRect& circle, float sigma); GrCircleBlurFragmentProcessor(const GrCircleBlurFragmentProcessor& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "CircleBlurFragmentProcessor"; } + int inputFP_index = -1; SkRect circleRect; - float textureRadius; float solidRadius; - TextureSampler blurProfileSampler; + float textureRadius; + int blurProfile_index = -1; private: - GrCircleBlurFragmentProcessor(SkRect circleRect, - float textureRadius, + GrCircleBlurFragmentProcessor(std::unique_ptr<GrFragmentProcessor> inputFP, + SkRect circleRect, float solidRadius, - GrSurfaceProxyView blurProfileSampler) + float textureRadius, + std::unique_ptr<GrFragmentProcessor> blurProfile) : INHERITED(kGrCircleBlurFragmentProcessor_ClassID, - (OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag) + (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get()) + : kAll_OptimizationFlags) & + kCompatibleWithCoverageAsAlpha_OptimizationFlag) , circleRect(circleRect) - , textureRadius(textureRadius) , solidRadius(solidRadius) - , blurProfileSampler(std::move(blurProfileSampler)) { - this->setTextureSamplerCnt(1); + , textureRadius(textureRadius) { + if (inputFP) { + inputFP_index = this->registerChild(std::move(inputFP)); + } + SkASSERT(blurProfile); + blurProfile_index = this->registerExplicitlySampledChild(std::move(blurProfile)); } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; - const TextureSampler& onTextureSampler(int) const override; GR_DECLARE_FRAGMENT_PROCESSOR_TEST typedef GrFragmentProcessor INHERITED; }; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.cpp index 272d33234a5..f9df3c9fdcb 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.cpp @@ -33,20 +33,39 @@ public: circleVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kFloat4_GrSLType, "circle"); fragBuilder->codeAppendf( - "float2 prevCenter;\nfloat prevRadius = %f;\nhalf d;\n@if (%d == 2 || %d == 3) {\n " - " d = half((length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * %s.z);\n} else {\n " - " d = half((1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * %s.z);\n}\n@if " - "((%d == 1 || %d == 3) || %d == 4) {\n %s = %s * clamp(d, 0.0, 1.0);\n} else " - "{\n %s = d > 0.5 ? %s : half4(0.0);\n}\n", + R"SkSL(float2 prevCenter; +float prevRadius = %f; +half d; +@if (%d == 2 || %d == 3) { + d = half((length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * %s.z); +} else { + d = half((1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * %s.z); +})SkSL", prevRadius, (int)_outer.edgeType, (int)_outer.edgeType, args.fUniformHandler->getUniformCStr(circleVar), args.fUniformHandler->getUniformCStr(circleVar), args.fUniformHandler->getUniformCStr(circleVar), args.fUniformHandler->getUniformCStr(circleVar), args.fUniformHandler->getUniformCStr(circleVar), - args.fUniformHandler->getUniformCStr(circleVar), (int)_outer.edgeType, - (int)_outer.edgeType, (int)_outer.edgeType, args.fOutputColor, args.fInputColor, - args.fOutputColor, args.fInputColor); + args.fUniformHandler->getUniformCStr(circleVar)); + SkString _input2509(args.fInputColor); + SkString _sample2509; + if (_outer.inputFP_index >= 0) { + _sample2509 = this->invokeChild(_outer.inputFP_index, _input2509.c_str(), args); + } else { + _sample2509.swap(_input2509); + } + fragBuilder->codeAppendf( + R"SkSL( +half4 inputColor = %s; +@if (%d == 1 || %d == 3) { + %s = inputColor * clamp(d, 0.0, 1.0); +} else { + %s = d > 0.5 ? inputColor : half4(0.0); +} +)SkSL", + _sample2509.c_str(), (int)_outer.edgeType, (int)_outer.edgeType, args.fOutputColor, + args.fOutputColor); } private: @@ -101,7 +120,11 @@ GrCircleEffect::GrCircleEffect(const GrCircleEffect& src) : INHERITED(kGrCircleEffect_ClassID, src.optimizationFlags()) , edgeType(src.edgeType) , center(src.center) - , radius(src.radius) {} + , radius(src.radius) { + if (src.inputFP_index >= 0) { + inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); + } +} std::unique_ptr<GrFragmentProcessor> GrCircleEffect::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(*this)); } @@ -112,10 +135,12 @@ std::unique_ptr<GrFragmentProcessor> GrCircleEffect::TestCreate(GrProcessorTestD center.fX = testData->fRandom->nextRangeScalar(0.f, 1000.f); center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f); SkScalar radius = testData->fRandom->nextRangeF(1.f, 1000.f); - GrClipEdgeType et; + bool success; + std::unique_ptr<GrFragmentProcessor> fp; do { - et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt); - } while (GrClipEdgeType::kHairlineAA == et); - return GrCircleEffect::Make(et, center, radius); + GrClipEdgeType et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt); + std::tie(success, fp) = GrCircleEffect::Make(/*inputFP=*/nullptr, et, center, radius); + } while (!success); + return fp; } #endif diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.h index b20412c70ae..ded95ae941f 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.h @@ -10,37 +10,51 @@ **************************************************************************************************/ #ifndef GrCircleEffect_DEFINED #define GrCircleEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrCircleEffect : public GrFragmentProcessor { public: - static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, - SkPoint center, - float radius) { + static GrFPResult Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, + SkPoint center, + float radius) { // A radius below half causes the implicit insetting done by this processor to become // inverted. We could handle this case by making the processor code more complicated. if (radius < .5f && GrProcessorEdgeTypeIsInverseFill(edgeType)) { - return nullptr; + return GrFPFailure(std::move(inputFP)); } - return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(edgeType, center, radius)); + return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>( + new GrCircleEffect(std::move(inputFP), edgeType, center, radius))); } GrCircleEffect(const GrCircleEffect& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "CircleEffect"; } + int inputFP_index = -1; GrClipEdgeType edgeType; SkPoint center; float radius; private: - GrCircleEffect(GrClipEdgeType edgeType, SkPoint center, float radius) + GrCircleEffect(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, + SkPoint center, + float radius) : INHERITED(kGrCircleEffect_ClassID, - (OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag) + (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get()) + : kAll_OptimizationFlags) & + kCompatibleWithCoverageAsAlpha_OptimizationFlag) , edgeType(edgeType) , center(center) - , radius(radius) {} + , radius(radius) { + if (inputFP) { + inputFP_index = this->registerChild(std::move(inputFP)); + } + } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.cpp index 7d692b52de2..f218bf889db 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.cpp @@ -25,11 +25,24 @@ public: (void)_outer; auto clampToPremul = _outer.clampToPremul; (void)clampToPremul; + SkString _input464(args.fInputColor); + SkString _sample464; + if (_outer.inputFP_index >= 0) { + _sample464 = this->invokeChild(_outer.inputFP_index, _input464.c_str(), args); + } else { + _sample464.swap(_input464); + } fragBuilder->codeAppendf( - "@if (%s) {\n half alpha = clamp(%s.w, 0.0, 1.0);\n %s = half4(clamp(%s.xyz, " - "0.0, alpha), alpha);\n} else {\n %s = clamp(%s, 0.0, 1.0);\n}\n", - (_outer.clampToPremul ? "true" : "false"), args.fInputColor, args.fOutputColor, - args.fInputColor, args.fOutputColor, args.fInputColor); + R"SkSL(half4 inputColor = %s; +@if (%s) { + half alpha = clamp(inputColor.w, 0.0, 1.0); + %s = half4(clamp(inputColor.xyz, 0.0, alpha), alpha); +} else { + %s = clamp(inputColor, 0.0, 1.0); +} +)SkSL", + _sample464.c_str(), (_outer.clampToPremul ? "true" : "false"), args.fOutputColor, + args.fOutputColor); } private: @@ -51,13 +64,17 @@ bool GrClampFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const } GrClampFragmentProcessor::GrClampFragmentProcessor(const GrClampFragmentProcessor& src) : INHERITED(kGrClampFragmentProcessor_ClassID, src.optimizationFlags()) - , clampToPremul(src.clampToPremul) {} + , clampToPremul(src.clampToPremul) { + if (src.inputFP_index >= 0) { + inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); + } +} std::unique_ptr<GrFragmentProcessor> GrClampFragmentProcessor::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrClampFragmentProcessor(*this)); } GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrClampFragmentProcessor); #if GR_TEST_UTILS std::unique_ptr<GrFragmentProcessor> GrClampFragmentProcessor::TestCreate(GrProcessorTestData* d) { - return GrClampFragmentProcessor::Make(d->fRandom->nextBool()); + return GrClampFragmentProcessor::Make(/*inputFP=*/nullptr, d->fRandom->nextBool()); } #endif diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.h index 61dc3a03d60..795555a7d18 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.h @@ -10,33 +10,47 @@ **************************************************************************************************/ #ifndef GrClampFragmentProcessor_DEFINED #define GrClampFragmentProcessor_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrClampFragmentProcessor : public GrFragmentProcessor { public: - SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override { + SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override { + SkPMColor4f input = this->numChildProcessors() ? ConstantOutputForConstantInput( + this->childProcessor(0), inColor) + : inColor; float clampedAlpha = SkTPin(input.fA, 0.f, 1.f); float clampVal = clampToPremul ? clampedAlpha : 1.f; return {SkTPin(input.fR, 0.f, clampVal), SkTPin(input.fG, 0.f, clampVal), SkTPin(input.fB, 0.f, clampVal), clampedAlpha}; } - static std::unique_ptr<GrFragmentProcessor> Make(bool clampToPremul) { - return std::unique_ptr<GrFragmentProcessor>(new GrClampFragmentProcessor(clampToPremul)); + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP, + bool clampToPremul) { + return std::unique_ptr<GrFragmentProcessor>( + new GrClampFragmentProcessor(std::move(inputFP), clampToPremul)); } GrClampFragmentProcessor(const GrClampFragmentProcessor& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "ClampFragmentProcessor"; } + int inputFP_index = -1; bool clampToPremul; private: - GrClampFragmentProcessor(bool clampToPremul) + GrClampFragmentProcessor(std::unique_ptr<GrFragmentProcessor> inputFP, bool clampToPremul) : INHERITED(kGrClampFragmentProcessor_ClassID, - (OptimizationFlags)kConstantOutputForConstantInput_OptimizationFlag | - kPreservesOpaqueInput_OptimizationFlag) - , clampToPremul(clampToPremul) {} + (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get()) + : kAll_OptimizationFlags) & + (kConstantOutputForConstantInput_OptimizationFlag | + kPreservesOpaqueInput_OptimizationFlag)) + , clampToPremul(clampToPremul) { + if (inputFP) { + inputFP_index = this->registerChild(std::move(inputFP)); + } + } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp index 1f3091a88dd..ad8eca849ca 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp @@ -38,13 +38,35 @@ public: "m"); vVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf4_GrSLType, "v"); + SkString _input585(args.fInputColor); + SkString _sample585; + if (_outer.inputFP_index >= 0) { + _sample585 = this->invokeChild(_outer.inputFP_index, _input585.c_str(), args); + } else { + _sample585.swap(_input585); + } fragBuilder->codeAppendf( - "half4 inputColor = %s;\n@if (%s) {\n half nonZeroAlpha = max(inputColor.w, " - "9.9999997473787516e-05);\n inputColor = half4(inputColor.xyz / nonZeroAlpha, " - "inputColor.w);\n}\n%s = %s * inputColor + %s;\n@if (%s) {\n %s = clamp(%s, " - "0.0, 1.0);\n} else {\n %s.w = clamp(%s.w, 0.0, 1.0);\n}\n@if (%s) {\n " - "%s.xyz *= %s.w;\n}\n", - args.fInputColor, (_outer.unpremulInput ? "true" : "false"), args.fOutputColor, + R"SkSL(half4 inputColor = %s; +@if (%s) { + half4 inlineResult0; + half4 inlineArg1_0 = inputColor; + { + inlineResult0 = half4(inlineArg1_0.xyz / max(inlineArg1_0.w, 9.9999997473787516e-05), inlineArg1_0.w); + } + inputColor = inlineResult0; + +} +%s = %s * inputColor + %s; +@if (%s) { + %s = clamp(%s, 0.0, 1.0); +} else { + %s.w = clamp(%s.w, 0.0, 1.0); +} +@if (%s) { + %s.xyz *= %s.w; +} +)SkSL", + _sample585.c_str(), (_outer.unpremulInput ? "true" : "false"), args.fOutputColor, args.fUniformHandler->getUniformCStr(mVar), args.fUniformHandler->getUniformCStr(vVar), (_outer.clampRGBOutput ? "true" : "false"), args.fOutputColor, args.fOutputColor, @@ -100,7 +122,11 @@ GrColorMatrixFragmentProcessor::GrColorMatrixFragmentProcessor( , v(src.v) , unpremulInput(src.unpremulInput) , clampRGBOutput(src.clampRGBOutput) - , premulOutput(src.premulOutput) {} + , premulOutput(src.premulOutput) { + if (src.inputFP_index >= 0) { + inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); + } +} std::unique_ptr<GrFragmentProcessor> GrColorMatrixFragmentProcessor::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrColorMatrixFragmentProcessor(*this)); } @@ -115,6 +141,6 @@ std::unique_ptr<GrFragmentProcessor> GrColorMatrixFragmentProcessor::TestCreate( bool unpremul = d->fRandom->nextBool(); bool clampRGB = d->fRandom->nextBool(); bool premul = d->fRandom->nextBool(); - return Make(m, unpremul, clampRGB, premul); + return Make(/*inputFP=*/nullptr, m, unpremul, clampRGB, premul); } #endif diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h index e8fa784cabf..4160af95949 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h @@ -10,14 +10,19 @@ **************************************************************************************************/ #ifndef GrColorMatrixFragmentProcessor_DEFINED #define GrColorMatrixFragmentProcessor_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrColorMatrixFragmentProcessor : public GrFragmentProcessor { public: - SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override { + SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override { + SkPMColor4f input = this->numChildProcessors() ? ConstantOutputForConstantInput( + this->childProcessor(0), inColor) + : inColor; SkColor4f color; if (unpremulInput) { color = input.unpremul(); @@ -42,7 +47,8 @@ public: } } - static std::unique_ptr<GrFragmentProcessor> Make(const float matrix[20], + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP, + const float matrix[20], bool unpremulInput, bool clampRGBOutput, bool premulOutput) { @@ -51,11 +57,12 @@ public: matrix[17], matrix[18]); SkV4 v4 = {matrix[4], matrix[9], matrix[14], matrix[19]}; return std::unique_ptr<GrFragmentProcessor>(new GrColorMatrixFragmentProcessor( - m44, v4, unpremulInput, clampRGBOutput, premulOutput)); + std::move(inputFP), m44, v4, unpremulInput, clampRGBOutput, premulOutput)); } GrColorMatrixFragmentProcessor(const GrColorMatrixFragmentProcessor& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "ColorMatrixFragmentProcessor"; } + int inputFP_index = -1; SkM44 m; SkV4 v; bool unpremulInput; @@ -63,15 +70,25 @@ public: bool premulOutput; private: - GrColorMatrixFragmentProcessor( - SkM44 m, SkV4 v, bool unpremulInput, bool clampRGBOutput, bool premulOutput) + GrColorMatrixFragmentProcessor(std::unique_ptr<GrFragmentProcessor> inputFP, + SkM44 m, + SkV4 v, + bool unpremulInput, + bool clampRGBOutput, + bool premulOutput) : INHERITED(kGrColorMatrixFragmentProcessor_ClassID, - (OptimizationFlags)kConstantOutputForConstantInput_OptimizationFlag) + (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get()) + : kAll_OptimizationFlags) & + kConstantOutputForConstantInput_OptimizationFlag) , m(m) , v(v) , unpremulInput(unpremulInput) , clampRGBOutput(clampRGBOutput) - , premulOutput(premulOutput) {} + , premulOutput(premulOutput) { + if (inputFP) { + inputFP_index = this->registerChild(std::move(inputFP)); + } + } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.cpp index 78aabacb90d..3a4a323672d 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.cpp @@ -39,11 +39,12 @@ public: } else { _sample358 = "half4(1)"; } - fragBuilder->codeAppendf("%s = mix(%s ? %s : %s, %s ? %s : %s, half(%s));\n", - args.fOutputColor, _outer.child1_index >= 0 ? "true" : "false", - _sample290.c_str(), args.fInputColor, - _outer.child2_index >= 0 ? "true" : "false", _sample358.c_str(), - args.fInputColor, args.fUniformHandler->getUniformCStr(weightVar)); + fragBuilder->codeAppendf( + R"SkSL(%s = mix(%s ? %s : %s, %s ? %s : %s, half(%s)); +)SkSL", + args.fOutputColor, _outer.child1_index >= 0 ? "true" : "false", _sample290.c_str(), + args.fInputColor, _outer.child2_index >= 0 ? "true" : "false", _sample358.c_str(), + args.fInputColor, args.fUniformHandler->getUniformCStr(weightVar)); } private: @@ -66,23 +67,12 @@ bool GrComposeLerpEffect::onIsEqual(const GrFragmentProcessor& other) const { return true; } GrComposeLerpEffect::GrComposeLerpEffect(const GrComposeLerpEffect& src) - : INHERITED(kGrComposeLerpEffect_ClassID, src.optimizationFlags()) - , child1_index(src.child1_index) - , child2_index(src.child2_index) - , weight(src.weight) { - if (child1_index >= 0) { - auto clone = src.childProcessor(child1_index).clone(); - if (src.childProcessor(child1_index).isSampledWithExplicitCoords()) { - clone->setSampledWithExplicitCoords(); - } - this->registerChildProcessor(std::move(clone)); + : INHERITED(kGrComposeLerpEffect_ClassID, src.optimizationFlags()), weight(src.weight) { + if (src.child1_index >= 0) { + child1_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child1_index)); } - if (child2_index >= 0) { - auto clone = src.childProcessor(child2_index).clone(); - if (src.childProcessor(child2_index).isSampledWithExplicitCoords()) { - clone->setSampledWithExplicitCoords(); - } - this->registerChildProcessor(std::move(clone)); + if (src.child2_index >= 0) { + child2_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child2_index)); } } std::unique_ptr<GrFragmentProcessor> GrComposeLerpEffect::clone() const { diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.h index d1fb0ff42cb..1f9d225043f 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.h @@ -10,11 +10,13 @@ **************************************************************************************************/ #ifndef GrComposeLerpEffect_DEFINED #define GrComposeLerpEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrComposeLerpEffect : public GrFragmentProcessor { public: static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> child1, @@ -36,12 +38,10 @@ private: float weight) : INHERITED(kGrComposeLerpEffect_ClassID, kNone_OptimizationFlags), weight(weight) { if (child1) { - child1_index = this->numChildProcessors(); - this->registerChildProcessor(std::move(child1)); + child1_index = this->registerChild(std::move(child1)); } if (child2) { - child2_index = this->numChildProcessors(); - this->registerChildProcessor(std::move(child2)); + child2_index = this->registerChild(std::move(child2)); } } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.cpp index 9a3e9877d31..0ec66fd31d0 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.cpp @@ -28,10 +28,16 @@ public: fragBuilder->forceHighPrecision(); fragBuilder->codeAppendf( - "%s = floor(%s * 255.0 + 0.5) / 255.0;\n@switch (%d) {\n case 0:\n " - "%s.xyz = floor((%s.xyz * %s.w) * 255.0 + 0.5) / 255.0;\n break;\n case " - "1:\n %s.xyz = %s.w <= 0.0 ? half3(0.0) : floor((%s.xyz / %s.w) * 255.0 + " - "0.5) / 255.0;\n break;\n}\n", + R"SkSL(%s = floor(%s * 255.0 + 0.5) / 255.0; +@switch (%d) { + case 0: + %s.xyz = floor((%s.xyz * %s.w) * 255.0 + 0.5) / 255.0; + break; + case 1: + %s.xyz = %s.w <= 0.0 ? half3(0.0) : floor((%s.xyz / %s.w) * 255.0 + 0.5) / 255.0; + break; +} +)SkSL", args.fOutputColor, args.fInputColor, (int)_outer.pmConversion, args.fOutputColor, args.fOutputColor, args.fOutputColor, args.fOutputColor, args.fOutputColor, args.fOutputColor, args.fOutputColor); diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.h index f6172b9e35d..129c21dd17f 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.h @@ -10,18 +10,19 @@ **************************************************************************************************/ #ifndef GrConfigConversionEffect_DEFINED #define GrConfigConversionEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "include/gpu/GrContext.h" #include "src/gpu/GrBitmapTextureMaker.h" -#include "src/gpu/GrClip.h" #include "src/gpu/GrContextPriv.h" #include "src/gpu/GrImageInfo.h" #include "src/gpu/GrRenderTargetContext.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrConfigConversionEffect : public GrFragmentProcessor { public: static bool TestForPreservingPMConversions(GrContext* context) { @@ -93,8 +94,7 @@ public: paint1.addColorFragmentProcessor(pmToUPM->clone()); paint1.setPorterDuffXPFactory(SkBlendMode::kSrc); - readRTC->fillRectToRect(GrNoClip(), std::move(paint1), GrAA::kNo, SkMatrix::I(), kRect, - kRect); + readRTC->fillRectToRect(nullptr, std::move(paint1), GrAA::kNo, SkMatrix::I(), kRect, kRect); if (!readRTC->readPixels(ii, firstRead, 0, {0, 0})) { return false; } @@ -108,16 +108,14 @@ public: paint2.addColorFragmentProcessor(std::move(upmToPM)); paint2.setPorterDuffXPFactory(SkBlendMode::kSrc); - tempRTC->fillRectToRect(GrNoClip(), std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect, - kRect); + tempRTC->fillRectToRect(nullptr, std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect, kRect); paint3.addColorFragmentProcessor( GrTextureEffect::Make(tempRTC->readSurfaceView(), kPremul_SkAlphaType)); paint3.addColorFragmentProcessor(std::move(pmToUPM)); paint3.setPorterDuffXPFactory(SkBlendMode::kSrc); - readRTC->fillRectToRect(GrNoClip(), std::move(paint3), GrAA::kNo, SkMatrix::I(), kRect, - kRect); + readRTC->fillRectToRect(nullptr, std::move(paint3), GrAA::kNo, SkMatrix::I(), kRect, kRect); if (!readRTC->readPixels(ii, secondRead, 0, {0, 0})) { return false; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.cpp index 22079b65a21..50b4b749e23 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.cpp @@ -30,12 +30,49 @@ public: colorVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf4_GrSLType, "color"); fragBuilder->codeAppendf( - "@switch (%d) {\n case 0:\n %s = %s;\n break;\n case 1:\n " - " %s = %s * %s;\n break;\n case 2:\n %s = %s.w * %s;\n " - "break;\n}\n", - (int)_outer.mode, args.fOutputColor, args.fUniformHandler->getUniformCStr(colorVar), - args.fOutputColor, args.fInputColor, args.fUniformHandler->getUniformCStr(colorVar), - args.fOutputColor, args.fInputColor, + R"SkSL(@switch (%d) { + case 0: + { + %s = %s; + break; + } + case 1: + {)SkSL", + (int)_outer.mode, args.fOutputColor, + args.fUniformHandler->getUniformCStr(colorVar)); + SkString _input1009(args.fInputColor); + SkString _sample1009; + if (_outer.inputFP_index >= 0) { + _sample1009 = this->invokeChild(_outer.inputFP_index, _input1009.c_str(), args); + } else { + _sample1009.swap(_input1009); + } + fragBuilder->codeAppendf( + R"SkSL( + half4 inputColor = %s; + %s = inputColor * %s; + break; + } + case 2: + {)SkSL", + _sample1009.c_str(), args.fOutputColor, + args.fUniformHandler->getUniformCStr(colorVar)); + SkString _input1181(args.fInputColor); + SkString _sample1181; + if (_outer.inputFP_index >= 0) { + _sample1181 = this->invokeChild(_outer.inputFP_index, _input1181.c_str(), args); + } else { + _sample1181.swap(_input1181); + } + fragBuilder->codeAppendf( + R"SkSL( + half inputAlpha = %s.w; + %s = inputAlpha * %s; + break; + } +} +)SkSL", + _sample1181.c_str(), args.fOutputColor, args.fUniformHandler->getUniformCStr(colorVar)); } @@ -71,7 +108,11 @@ bool GrConstColorProcessor::onIsEqual(const GrFragmentProcessor& other) const { GrConstColorProcessor::GrConstColorProcessor(const GrConstColorProcessor& src) : INHERITED(kGrConstColorProcessor_ClassID, src.optimizationFlags()) , color(src.color) - , mode(src.mode) {} + , mode(src.mode) { + if (src.inputFP_index >= 0) { + inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); + } +} std::unique_ptr<GrFragmentProcessor> GrConstColorProcessor::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrConstColorProcessor(*this)); } @@ -98,6 +139,6 @@ std::unique_ptr<GrFragmentProcessor> GrConstColorProcessor::TestCreate(GrProcess break; } InputMode mode = static_cast<InputMode>(d->fRandom->nextULessThan(kInputModeCnt)); - return GrConstColorProcessor::Make(color, mode); + return GrConstColorProcessor::Make(/*inputFP=*/nullptr, color, mode); } #endif diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.h index 6d84f836cf2..e9b8b86c5cc 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.h @@ -10,53 +10,73 @@ **************************************************************************************************/ #ifndef GrConstColorProcessor_DEFINED #define GrConstColorProcessor_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrConstColorProcessor : public GrFragmentProcessor { public: enum class InputMode { kIgnore = 0, kLast = 2, kModulateA = 2, kModulateRGBA = 1 }; static const int kInputModeCnt = (int)InputMode::kLast + 1; - static OptimizationFlags OptFlags(const SkPMColor4f& color, InputMode mode) { - OptimizationFlags flags = kConstantOutputForConstantInput_OptimizationFlag; - if (mode != InputMode::kIgnore) { - flags |= kCompatibleWithCoverageAsAlpha_OptimizationFlag; - } - if (color.isOpaque()) { - flags |= kPreservesOpaqueInput_OptimizationFlag; - } - return flags; - } - - SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override { + SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override { switch (mode) { - case InputMode::kIgnore: + case InputMode::kIgnore: { return color; - case InputMode::kModulateA: + } + case InputMode::kModulateA: { + SkPMColor4f input = this->numChildProcessors() + ? ConstantOutputForConstantInput( + this->childProcessor(inputFP_index), inColor) + : inColor; return color * input.fA; - case InputMode::kModulateRGBA: + } + case InputMode::kModulateRGBA: { + SkPMColor4f input = this->numChildProcessors() + ? ConstantOutputForConstantInput( + this->childProcessor(inputFP_index), inColor) + : inColor; return color * input; + } } - SK_ABORT("Unexpected mode"); + SkUNREACHABLE; } - static std::unique_ptr<GrFragmentProcessor> Make(SkPMColor4f color, InputMode mode) { - return std::unique_ptr<GrFragmentProcessor>(new GrConstColorProcessor(color, mode)); + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP, + SkPMColor4f color, + InputMode mode) { + return std::unique_ptr<GrFragmentProcessor>( + new GrConstColorProcessor(std::move(inputFP), color, mode)); } GrConstColorProcessor(const GrConstColorProcessor& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "ConstColorProcessor"; } + int inputFP_index = -1; SkPMColor4f color; InputMode mode; private: - GrConstColorProcessor(SkPMColor4f color, InputMode mode) - : INHERITED(kGrConstColorProcessor_ClassID, (OptimizationFlags)OptFlags(color, mode)) + GrConstColorProcessor(std::unique_ptr<GrFragmentProcessor> inputFP, + SkPMColor4f color, + InputMode mode) + : INHERITED(kGrConstColorProcessor_ClassID, + (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get()) + : kAll_OptimizationFlags) & + (kConstantOutputForConstantInput_OptimizationFlag | + ((mode != InputMode::kIgnore) + ? kCompatibleWithCoverageAsAlpha_OptimizationFlag + : kNone_OptimizationFlags) | + ((color.isOpaque()) ? kPreservesOpaqueInput_OptimizationFlag + : kNone_OptimizationFlags))) , color(color) - , mode(mode) {} + , mode(mode) { + if (inputFP) { + inputFP_index = this->registerChild(std::move(inputFP)); + } + } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.cpp index be9e92c6ecf..4fec9b1ab0d 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.cpp @@ -23,17 +23,32 @@ public: GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; const GrDeviceSpaceEffect& _outer = args.fFp.cast<GrDeviceSpaceEffect>(); (void)_outer; - SkString _input204 = SkStringPrintf("%s", args.fInputColor); - SkString _sample204; - SkString _coords204("sk_FragCoord.xy"); - _sample204 = - this->invokeChild(_outer.fp_index, _input204.c_str(), args, _coords204.c_str()); - fragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, _sample204.c_str()); + auto matrix = _outer.matrix; + (void)matrix; + matrixVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, + kFloat3x3_GrSLType, "matrix"); + fragBuilder->codeAppendf( + R"SkSL(float3 p = %s * float3(sk_FragCoord.xy, 1);)SkSL", + args.fUniformHandler->getUniformCStr(matrixVar)); + SkString _input276(args.fInputColor); + SkString _sample276; + SkString _coords276("p.xy / p.z"); + _sample276 = + this->invokeChild(_outer.fp_index, _input276.c_str(), args, _coords276.c_str()); + fragBuilder->codeAppendf( + R"SkSL( +%s = %s; +)SkSL", + args.fOutputColor, _sample276.c_str()); } private: void onSetData(const GrGLSLProgramDataManager& pdman, - const GrFragmentProcessor& _proc) override {} + const GrFragmentProcessor& _proc) override { + const GrDeviceSpaceEffect& _outer = _proc.cast<GrDeviceSpaceEffect>(); + { pdman.setSkMatrix(matrixVar, (_outer.matrix)); } + } + UniformHandle matrixVar; }; GrGLSLFragmentProcessor* GrDeviceSpaceEffect::onCreateGLSLInstance() const { return new GrGLSLDeviceSpaceEffect(); @@ -43,17 +58,12 @@ void GrDeviceSpaceEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, bool GrDeviceSpaceEffect::onIsEqual(const GrFragmentProcessor& other) const { const GrDeviceSpaceEffect& that = other.cast<GrDeviceSpaceEffect>(); (void)that; + if (matrix != that.matrix) return false; return true; } GrDeviceSpaceEffect::GrDeviceSpaceEffect(const GrDeviceSpaceEffect& src) - : INHERITED(kGrDeviceSpaceEffect_ClassID, src.optimizationFlags()), fp_index(src.fp_index) { - { - auto clone = src.childProcessor(fp_index).clone(); - if (src.childProcessor(fp_index).isSampledWithExplicitCoords()) { - clone->setSampledWithExplicitCoords(); - } - this->registerChildProcessor(std::move(clone)); - } + : INHERITED(kGrDeviceSpaceEffect_ClassID, src.optimizationFlags()), matrix(src.matrix) { + { fp_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.fp_index)); } } std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceEffect::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrDeviceSpaceEffect(*this)); diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.h index e08d29d892d..c7e4f2439aa 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.h @@ -10,28 +10,30 @@ **************************************************************************************************/ #ifndef GrDeviceSpaceEffect_DEFINED #define GrDeviceSpaceEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrDeviceSpaceEffect : public GrFragmentProcessor { public: - static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp) { - return std::unique_ptr<GrFragmentProcessor>(new GrDeviceSpaceEffect(std::move(fp))); + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp, + const SkMatrix& matrix = SkMatrix::I()) { + return std::unique_ptr<GrFragmentProcessor>(new GrDeviceSpaceEffect(std::move(fp), matrix)); } GrDeviceSpaceEffect(const GrDeviceSpaceEffect& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "DeviceSpaceEffect"; } int fp_index = -1; + SkMatrix matrix; private: - GrDeviceSpaceEffect(std::unique_ptr<GrFragmentProcessor> fp) - : INHERITED(kGrDeviceSpaceEffect_ClassID, kNone_OptimizationFlags) { + GrDeviceSpaceEffect(std::unique_ptr<GrFragmentProcessor> fp, SkMatrix matrix) + : INHERITED(kGrDeviceSpaceEffect_ClassID, kNone_OptimizationFlags), matrix(matrix) { SkASSERT(fp); - fp_index = this->numChildProcessors(); - fp->setSampledWithExplicitCoords(); - this->registerChildProcessor(std::move(fp)); + fp_index = this->registerExplicitlySampledChild(std::move(fp)); } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.cpp index fa349032589..0a75b96dd8e 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.cpp @@ -38,26 +38,61 @@ public: kFloat2_GrSLType, "scale"); } fragBuilder->codeAppendf( - "float2 prevCenter;\nfloat2 prevRadii = float2(%f, %f);\nbool medPrecision = " - "%s;\nfloat2 d = sk_FragCoord.xy - %s.xy;\n@if (medPrecision) {\n d *= " - "%s.y;\n}\nfloat2 Z = d * %s.zw;\nfloat implicit = dot(Z, d) - 1.0;\nfloat " - "grad_dot = 4.0 * dot(Z, Z);\n@if (medPrecision) {\n grad_dot = max(grad_dot, " - "6.1036000261083245e-05);\n} else {\n grad_dot = max(grad_dot, " - "1.1754999560161448e-38);\n}\nfloat approx_dist = implicit * " - "inversesqrt(grad_dot);\n@if (medPrecision) {\n approx_dist *= %s.x;\n}\nhalf " - "alph", + R"SkSL(float2 prevCenter; +float2 prevRadii = float2(%f, %f); +bool medPrecision = %s; +float2 d = sk_FragCoord.xy - %s.xy; +@if (medPrecision) { + d *= %s.y; +} +float2 Z = d * %s.zw; +float implicit = dot(Z, d) - 1.0; +float grad_dot = 4.0 * dot(Z, Z); +@if (medPrecision) { + grad_dot = max(grad_dot, 6.1036000261083245e-05); +} else { + grad_dot = max(grad_dot, 1.1754999560161448e-38); +} +float approx_dist = implicit * inversesqrt(grad_dot); +@if (medPrecision) { + approx_dist *= %s.x; +} +half alpha; +@switch (%d) { + case 0: + alpha = approx_dist > 0.0 ? 0.0 : 1.0; + break; + case 1: + alpha = clamp(0.5 - half(approx_dist), 0.0, 1.0); + break; + case 2: + alpha = approx_dist > 0.0 ? 1.0 : 0.0; + break; + case 3: + alpha = clamp(0.5 + half(approx_dist), 0.0, 1.0); + break; + default: + discard; +})SkSL", prevRadii.fX, prevRadii.fY, (medPrecision ? "true" : "false"), args.fUniformHandler->getUniformCStr(ellipseVar), scaleVar.isValid() ? args.fUniformHandler->getUniformCStr(scaleVar) : "float2(0)", args.fUniformHandler->getUniformCStr(ellipseVar), - scaleVar.isValid() ? args.fUniformHandler->getUniformCStr(scaleVar) : "float2(0)"); + scaleVar.isValid() ? args.fUniformHandler->getUniformCStr(scaleVar) : "float2(0)", + (int)_outer.edgeType); + SkString _input4481(args.fInputColor); + SkString _sample4481; + if (_outer.inputFP_index >= 0) { + _sample4481 = this->invokeChild(_outer.inputFP_index, _input4481.c_str(), args); + } else { + _sample4481.swap(_input4481); + } fragBuilder->codeAppendf( - "a;\n@switch (%d) {\n case 0:\n alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n " - " break;\n case 1:\n alpha = clamp(0.5 - half(approx_dist), 0.0, " - "1.0);\n break;\n case 2:\n alpha = approx_dist > 0.0 ? 1.0 : " - "0.0;\n break;\n case 3:\n alpha = clamp(0.5 + half(approx_dist), " - "0.0, 1.0);\n break;\n default:\n discard;\n}\n%s = %s * alpha;\n", - (int)_outer.edgeType, args.fOutputColor, args.fInputColor); + R"SkSL( +half4 inputColor = %s; +%s = inputColor * alpha; +)SkSL", + _sample4481.c_str(), args.fOutputColor); } private: @@ -125,7 +160,11 @@ GrEllipseEffect::GrEllipseEffect(const GrEllipseEffect& src) : INHERITED(kGrEllipseEffect_ClassID, src.optimizationFlags()) , edgeType(src.edgeType) , center(src.center) - , radii(src.radii) {} + , radii(src.radii) { + if (src.inputFP_index >= 0) { + inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); + } +} std::unique_ptr<GrFragmentProcessor> GrEllipseEffect::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrEllipseEffect(*this)); } @@ -137,11 +176,14 @@ std::unique_ptr<GrFragmentProcessor> GrEllipseEffect::TestCreate(GrProcessorTest center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f); SkScalar rx = testData->fRandom->nextRangeF(0.f, 1000.f); SkScalar ry = testData->fRandom->nextRangeF(0.f, 1000.f); - GrClipEdgeType et; + bool success; + std::unique_ptr<GrFragmentProcessor> fp; do { - et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt); - } while (GrClipEdgeType::kHairlineAA == et); - return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry), - *testData->caps()->shaderCaps()); + GrClipEdgeType et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt); + std::tie(success, fp) = + GrEllipseEffect::Make(/*inputFP=*/nullptr, et, center, SkPoint::Make(rx, ry), + *testData->caps()->shaderCaps()); + } while (!success); + return fp; } #endif diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.h index fb746b36c88..6348d97b34d 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.h @@ -10,47 +10,61 @@ **************************************************************************************************/ #ifndef GrEllipseEffect_DEFINED #define GrEllipseEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrShaderCaps.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrEllipseEffect : public GrFragmentProcessor { public: - static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, - SkPoint center, - SkPoint radii, - const GrShaderCaps& caps) { + static GrFPResult Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, + SkPoint center, + SkPoint radii, + const GrShaderCaps& caps) { // Small radii produce bad results on devices without full float. if (!caps.floatIs32Bits() && (radii.fX < 0.5f || radii.fY < 0.5f)) { - return nullptr; + return GrFPFailure(std::move(inputFP)); } // Very narrow ellipses produce bad results on devices without full float if (!caps.floatIs32Bits() && (radii.fX > 255 * radii.fY || radii.fY > 255 * radii.fX)) { - return nullptr; + return GrFPFailure(std::move(inputFP)); } // Very large ellipses produce bad results on devices without full float if (!caps.floatIs32Bits() && (radii.fX > 16384 || radii.fY > 16384)) { - return nullptr; + return GrFPFailure(std::move(inputFP)); } - return std::unique_ptr<GrFragmentProcessor>(new GrEllipseEffect(edgeType, center, radii)); + return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>( + new GrEllipseEffect(std::move(inputFP), edgeType, center, radii))); } GrEllipseEffect(const GrEllipseEffect& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "EllipseEffect"; } + int inputFP_index = -1; GrClipEdgeType edgeType; SkPoint center; SkPoint radii; private: - GrEllipseEffect(GrClipEdgeType edgeType, SkPoint center, SkPoint radii) + GrEllipseEffect(std::unique_ptr<GrFragmentProcessor> inputFP, + GrClipEdgeType edgeType, + SkPoint center, + SkPoint radii) : INHERITED(kGrEllipseEffect_ClassID, - (OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag) + (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get()) + : kAll_OptimizationFlags) & + kCompatibleWithCoverageAsAlpha_OptimizationFlag) , edgeType(edgeType) , center(center) - , radii(radii) {} + , radii(radii) { + if (inputFP) { + inputFP_index = this->registerChild(std::move(inputFP)); + } + } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp index 11effd21a3e..91796e1f0d7 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp @@ -23,13 +23,24 @@ public: GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; const GrHSLToRGBFilterEffect& _outer = args.fFp.cast<GrHSLToRGBFilterEffect>(); (void)_outer; + SkString _input523(args.fInputColor); + SkString _sample523; + if (_outer.inputFP_index >= 0) { + _sample523 = this->invokeChild(_outer.inputFP_index, _input523.c_str(), args); + } else { + _sample523.swap(_input523); + } fragBuilder->codeAppendf( - "half3 hsl = %s.xyz;\nhalf C = (1.0 - abs(2.0 * hsl.z - 1.0)) * hsl.y;\nhalf3 p = " - "hsl.xxx + half3(0.0, 0.66666666666666663, 0.33333333333333331);\nhalf3 q = " - "clamp(abs(fract(p) * 6.0 - 3.0) - 1.0, 0.0, 1.0);\nhalf3 rgb = (q - 0.5) * C + " - "hsl.z;\n%s = clamp(half4(rgb, %s.w), 0.0, 1.0);\n%s.xyz *= %s.w;\n", - args.fInputColor, args.fOutputColor, args.fInputColor, args.fOutputColor, - args.fOutputColor); + R"SkSL(half4 inputColor = %s; +half3 hsl = inputColor.xyz; +half C = (1.0 - abs(2.0 * hsl.z - 1.0)) * hsl.y; +half3 p = hsl.xxx + half3(0.0, 0.66666666666666663, 0.33333333333333331); +half3 q = clamp(abs(fract(p) * 6.0 - 3.0) - 1.0, 0.0, 1.0); +half3 rgb = (q - 0.5) * C + hsl.z; +%s = clamp(half4(rgb, inputColor.w), 0.0, 1.0); +%s.xyz *= %s.w; +)SkSL", + _sample523.c_str(), args.fOutputColor, args.fOutputColor, args.fOutputColor); } private: @@ -47,7 +58,11 @@ bool GrHSLToRGBFilterEffect::onIsEqual(const GrFragmentProcessor& other) const { return true; } GrHSLToRGBFilterEffect::GrHSLToRGBFilterEffect(const GrHSLToRGBFilterEffect& src) - : INHERITED(kGrHSLToRGBFilterEffect_ClassID, src.optimizationFlags()) {} + : INHERITED(kGrHSLToRGBFilterEffect_ClassID, src.optimizationFlags()) { + if (src.inputFP_index >= 0) { + inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); + } +} std::unique_ptr<GrFragmentProcessor> GrHSLToRGBFilterEffect::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrHSLToRGBFilterEffect(*this)); } diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.h index a86c4af0464..25f10b87206 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.h @@ -10,17 +10,22 @@ **************************************************************************************************/ #ifndef GrHSLToRGBFilterEffect_DEFINED #define GrHSLToRGBFilterEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrHSLToRGBFilterEffect : public GrFragmentProcessor { public: #include "include/private/SkColorData.h" #include "include/private/SkNx.h" - SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& c) const override { + SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override { + SkPMColor4f c = this->numChildProcessors() + ? ConstantOutputForConstantInput(this->childProcessor(0), inColor) + : inColor; const auto H = c[0], S = c[1], L = c[2], C = (1 - std::abs(2 * L - 1)) * S; const auto p = H + Sk4f(0, 2 / 3.f, 1 / 3.f, 0), @@ -30,18 +35,25 @@ public: return SkColor4f{rgba[0], rgba[1], rgba[2], rgba[3]}.premul(); } - static std::unique_ptr<GrFragmentProcessor> Make() { - return std::unique_ptr<GrFragmentProcessor>(new GrHSLToRGBFilterEffect()); + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP) { + return std::unique_ptr<GrFragmentProcessor>(new GrHSLToRGBFilterEffect(std::move(inputFP))); } GrHSLToRGBFilterEffect(const GrHSLToRGBFilterEffect& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "HSLToRGBFilterEffect"; } + int inputFP_index = -1; private: - GrHSLToRGBFilterEffect() + GrHSLToRGBFilterEffect(std::unique_ptr<GrFragmentProcessor> inputFP) : INHERITED(kGrHSLToRGBFilterEffect_ClassID, - (OptimizationFlags)(kConstantOutputForConstantInput_OptimizationFlag | - kPreservesOpaqueInput_OptimizationFlag)) {} + (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get()) + : kAll_OptimizationFlags) & + (kConstantOutputForConstantInput_OptimizationFlag | + kPreservesOpaqueInput_OptimizationFlag)) { + if (inputFP) { + inputFP_index = this->registerChild(std::move(inputFP)); + } + } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp index c85bc65069b..ec9045b9324 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp @@ -23,10 +23,20 @@ public: GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; const GrLumaColorFilterEffect& _outer = args.fFp.cast<GrLumaColorFilterEffect>(); (void)_outer; + SkString _input953(args.fInputColor); + SkString _sample953; + if (_outer.inputFP_index >= 0) { + _sample953 = this->invokeChild(_outer.inputFP_index, _input953.c_str(), args); + } else { + _sample953.swap(_input953); + } fragBuilder->codeAppendf( - "\nhalf luma = clamp(dot(half3(0.2125999927520752, 0.71520000696182251, " - "0.072200000286102295), %s.xyz), 0.0, 1.0);\n%s = half4(0.0, 0.0, 0.0, luma);\n", - args.fInputColor, args.fOutputColor); + R"SkSL(half4 inputColor = %s; + +half luma = clamp(dot(half3(0.2125999927520752, 0.71520000696182251, 0.072200000286102295), inputColor.xyz), 0.0, 1.0); +%s = half4(0.0, 0.0, 0.0, luma); +)SkSL", + _sample953.c_str(), args.fOutputColor); } private: @@ -44,7 +54,11 @@ bool GrLumaColorFilterEffect::onIsEqual(const GrFragmentProcessor& other) const return true; } GrLumaColorFilterEffect::GrLumaColorFilterEffect(const GrLumaColorFilterEffect& src) - : INHERITED(kGrLumaColorFilterEffect_ClassID, src.optimizationFlags()) {} + : INHERITED(kGrLumaColorFilterEffect_ClassID, src.optimizationFlags()) { + if (src.inputFP_index >= 0) { + inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); + } +} std::unique_ptr<GrFragmentProcessor> GrLumaColorFilterEffect::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrLumaColorFilterEffect(*this)); } diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.h index 3ee5c06aede..274958efef9 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.h @@ -10,31 +10,45 @@ **************************************************************************************************/ #ifndef GrLumaColorFilterEffect_DEFINED #define GrLumaColorFilterEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrLumaColorFilterEffect : public GrFragmentProcessor { public: #include "include/private/SkColorData.h" - SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override { + SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override { + SkPMColor4f input = this->numChildProcessors() + ? ConstantOutputForConstantInput( + this->childProcessor(inputFP_index), inColor) + : inColor; float luma = SK_ITU_BT709_LUM_COEFF_R * input.fR + SK_ITU_BT709_LUM_COEFF_G * input.fG + SK_ITU_BT709_LUM_COEFF_B * input.fB; return {0, 0, 0, SkTPin(luma, 0.0f, 1.0f)}; } - static std::unique_ptr<GrFragmentProcessor> Make() { - return std::unique_ptr<GrFragmentProcessor>(new GrLumaColorFilterEffect()); + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP) { + return std::unique_ptr<GrFragmentProcessor>( + new GrLumaColorFilterEffect(std::move(inputFP))); } GrLumaColorFilterEffect(const GrLumaColorFilterEffect& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "LumaColorFilterEffect"; } + int inputFP_index = -1; private: - GrLumaColorFilterEffect() + GrLumaColorFilterEffect(std::unique_ptr<GrFragmentProcessor> inputFP) : INHERITED(kGrLumaColorFilterEffect_ClassID, - (OptimizationFlags)kConstantOutputForConstantInput_OptimizationFlag) {} + (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get()) + : kAll_OptimizationFlags) & + kConstantOutputForConstantInput_OptimizationFlag) { + if (inputFP) { + inputFP_index = this->registerChild(std::move(inputFP)); + } + } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.cpp index 0746fbf6c60..acc344d4a86 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.cpp @@ -35,44 +35,51 @@ public: (void)xInvInset; auto yInvInset = _outer.yInvInset; (void)yInvInset; - boundsUniformVar = args.fUniformHandler->addUniform( - &_outer, kFragment_GrShaderFlag, kFloat4_GrSLType, "boundsUniform"); - xInvZoomVar = args.fUniformHandler->addUniform( - &_outer, kFragment_GrShaderFlag, kFloat_GrSLType, "xInvZoom"); - yInvZoomVar = args.fUniformHandler->addUniform( - &_outer, kFragment_GrShaderFlag, kFloat_GrSLType, "yInvZoom"); - xInvInsetVar = args.fUniformHandler->addUniform( - &_outer, kFragment_GrShaderFlag, kFloat_GrSLType, "xInvInset"); - yInvInsetVar = args.fUniformHandler->addUniform( - &_outer, kFragment_GrShaderFlag, kFloat_GrSLType, "yInvInset"); - offsetVar = args.fUniformHandler->addUniform( - &_outer, kFragment_GrShaderFlag, kHalf2_GrSLType, "offset"); + boundsUniformVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, + kFloat4_GrSLType, "boundsUniform"); + xInvZoomVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, + kFloat_GrSLType, "xInvZoom"); + yInvZoomVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, + kFloat_GrSLType, "yInvZoom"); + xInvInsetVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, + kFloat_GrSLType, "xInvInset"); + yInvInsetVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, + kFloat_GrSLType, "yInvInset"); + offsetVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, + kHalf2_GrSLType, "offset"); SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D( args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix()); fragBuilder->codeAppendf( - "float2 coord = %s;\nfloat2 zoom_coord = float2(%s) + coord * float2(%s, " - "%s);\nfloat2 delta = (coord - %s.xy) * %s.zw;\ndelta = min(delta, " - "float2(half2(1.0, 1.0)) - delta);\ndelta *= float2(%s, %s);\nfloat weight = " - "0.0;\nif (delta.x < 2.0 && delta.y < 2.0) {\n delta = float2(half2(2.0, 2.0)) " - "- delta;\n float dist = length(delta);\n dist = max(2.0 - dist, 0.0);\n " - "weight = min(dist * dist, 1.0);\n} else {\n float2 delta_squared = delta * " - "delta;\n weight = min(min(delta_squared.x, delta_square", - sk_TransformedCoords2D_0.c_str(), - args.fUniformHandler->getUniformCStr(offsetVar), + R"SkSL(float2 coord = %s; +float2 zoom_coord = float2(%s) + coord * float2(%s, %s); +float2 delta = (coord - %s.xy) * %s.zw; +delta = min(delta, float2(half2(1.0, 1.0)) - delta); +delta *= float2(%s, %s); +float weight = 0.0; +if (delta.x < 2.0 && delta.y < 2.0) { + delta = float2(half2(2.0, 2.0)) - delta; + float dist = length(delta); + dist = max(2.0 - dist, 0.0); + weight = min(dist * dist, 1.0); +} else { + float2 delta_squared = delta * delta; + weight = min(min(delta_squared.x, delta_squared.y), 1.0); +})SkSL", + sk_TransformedCoords2D_0.c_str(), args.fUniformHandler->getUniformCStr(offsetVar), args.fUniformHandler->getUniformCStr(xInvZoomVar), args.fUniformHandler->getUniformCStr(yInvZoomVar), args.fUniformHandler->getUniformCStr(boundsUniformVar), args.fUniformHandler->getUniformCStr(boundsUniformVar), args.fUniformHandler->getUniformCStr(xInvInsetVar), args.fUniformHandler->getUniformCStr(yInvInsetVar)); + SkString _sample1112; + SkString _coords1112("mix(coord, zoom_coord, weight)"); + _sample1112 = this->invokeChild(_outer.src_index, args, _coords1112.c_str()); fragBuilder->codeAppendf( - "d.y), 1.0);\n}\n%s = sample(%s, mix(coord, zoom_coord, weight)).%s;\n", - args.fOutputColor, - fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]), - fragBuilder->getProgramBuilder() - ->samplerSwizzle(args.fTexSamplers[0]) - .asString() - .c_str()); + R"SkSL( +%s = %s; +)SkSL", + args.fOutputColor, _sample1112.c_str()); } private: @@ -85,9 +92,6 @@ private: pdman.set1f(xInvInsetVar, (_outer.xInvInset)); pdman.set1f(yInvInsetVar, (_outer.yInvInset)); } - const GrSurfaceProxyView& srcView = _outer.textureSampler(0).view(); - GrTexture& src = *srcView.proxy()->peekTexture(); - (void)src; auto bounds = _outer.bounds; (void)bounds; UniformHandle& boundsUniform = boundsUniformVar; @@ -105,32 +109,9 @@ private: UniformHandle& offset = offsetVar; (void)offset; - SkScalar invW = 1.0f / src.width(); - SkScalar invH = 1.0f / src.height(); - - { - SkScalar y = srcRect.y() * invH; - if (srcView.origin() != kTopLeft_GrSurfaceOrigin) { - y = 1.0f - (srcRect.height() / bounds.height()) - y; - } - - pdman.set2f(offset, srcRect.x() * invW, y); - } - - { - SkScalar y = bounds.y() * invH; - SkScalar hSign = 1.f; - if (srcView.origin() != kTopLeft_GrSurfaceOrigin) { - y = 1.0f - bounds.y() * invH; - hSign = -1.f; - } - - pdman.set4f(boundsUniform, - bounds.x() * invW, - y, - SkIntToScalar(src.width()) / bounds.width(), - hSign * SkIntToScalar(src.height()) / bounds.height()); - } + pdman.set2f(offset, srcRect.x(), srcRect.y()); + pdman.set4f(boundsUniform, bounds.x(), bounds.y(), 1.f / bounds.width(), + 1.f / bounds.height()); } UniformHandle boundsUniformVar; UniformHandle offsetVar; @@ -147,7 +128,6 @@ void GrMagnifierEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, bool GrMagnifierEffect::onIsEqual(const GrFragmentProcessor& other) const { const GrMagnifierEffect& that = other.cast<GrMagnifierEffect>(); (void)that; - if (src != that.src) return false; if (bounds != that.bounds) return false; if (srcRect != that.srcRect) return false; if (xInvZoom != that.xInvZoom) return false; @@ -158,27 +138,22 @@ bool GrMagnifierEffect::onIsEqual(const GrFragmentProcessor& other) const { } GrMagnifierEffect::GrMagnifierEffect(const GrMagnifierEffect& src) : INHERITED(kGrMagnifierEffect_ClassID, src.optimizationFlags()) - , srcCoordTransform(src.srcCoordTransform) - , src(src.src) + , fCoordTransform0(src.fCoordTransform0) , bounds(src.bounds) , srcRect(src.srcRect) , xInvZoom(src.xInvZoom) , yInvZoom(src.yInvZoom) , xInvInset(src.xInvInset) , yInvInset(src.yInvInset) { - this->setTextureSamplerCnt(1); - this->addCoordTransform(&srcCoordTransform); + { src_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.src_index)); } + this->addCoordTransform(&fCoordTransform0); } std::unique_ptr<GrFragmentProcessor> GrMagnifierEffect::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrMagnifierEffect(*this)); } -const GrFragmentProcessor::TextureSampler& GrMagnifierEffect::onTextureSampler(int index) const { - return IthTextureSampler(index, src); -} GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrMagnifierEffect); #if GR_TEST_UTILS std::unique_ptr<GrFragmentProcessor> GrMagnifierEffect::TestCreate(GrProcessorTestData* d) { - auto[view, ct, at] = d->randomView(); const int kMaxWidth = 200; const int kMaxHeight = 200; const SkScalar kMaxInset = 20.0f; @@ -189,7 +164,8 @@ std::unique_ptr<GrFragmentProcessor> GrMagnifierEffect::TestCreate(GrProcessorTe SkIRect bounds = SkIRect::MakeWH(SkIntToScalar(kMaxWidth), SkIntToScalar(kMaxHeight)); SkRect srcRect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); - auto effect = GrMagnifierEffect::Make(std::move(view), + auto src = GrProcessorUnitTest::MakeChildFP(d); + auto effect = GrMagnifierEffect::Make(std::move(src), bounds, srcRect, srcRect.width() / bounds.width(), diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.h index ab930d9cdb3..aff287f30a3 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.h @@ -10,14 +10,16 @@ **************************************************************************************************/ #ifndef GrMagnifierEffect_DEFINED #define GrMagnifierEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrMagnifierEffect : public GrFragmentProcessor { public: - static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView src, + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> src, SkIRect bounds, SkRect srcRect, float xInvZoom, @@ -30,8 +32,8 @@ public: GrMagnifierEffect(const GrMagnifierEffect& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "MagnifierEffect"; } - GrCoordTransform srcCoordTransform; - TextureSampler src; + GrCoordTransform fCoordTransform0; + int src_index = -1; SkIRect bounds; SkRect srcRect; float xInvZoom; @@ -40,7 +42,7 @@ public: float yInvInset; private: - GrMagnifierEffect(GrSurfaceProxyView src, + GrMagnifierEffect(std::unique_ptr<GrFragmentProcessor> src, SkIRect bounds, SkRect srcRect, float xInvZoom, @@ -48,21 +50,20 @@ private: float xInvInset, float yInvInset) : INHERITED(kGrMagnifierEffect_ClassID, kNone_OptimizationFlags) - , srcCoordTransform(SkMatrix::I(), src.proxy(), src.origin()) - , src(std::move(src)) + , fCoordTransform0(SkMatrix::I()) , bounds(bounds) , srcRect(srcRect) , xInvZoom(xInvZoom) , yInvZoom(yInvZoom) , xInvInset(xInvInset) , yInvInset(yInvInset) { - this->setTextureSamplerCnt(1); - this->addCoordTransform(&srcCoordTransform); + SkASSERT(src); + src_index = this->registerExplicitlySampledChild(std::move(src)); + this->addCoordTransform(&fCoordTransform0); } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; - const TextureSampler& onTextureSampler(int) const override; GR_DECLARE_FRAGMENT_PROCESSOR_TEST typedef GrFragmentProcessor INHERITED; }; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrMatrixEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrMatrixEffect.cpp deleted file mode 100644 index fa8b6910e2b..00000000000 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrMatrixEffect.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/************************************************************************************************** - *** This file was autogenerated from GrMatrixEffect.fp; do not modify. - **************************************************************************************************/ -#include "GrMatrixEffect.h" - -#include "src/gpu/GrTexture.h" -#include "src/gpu/glsl/GrGLSLFragmentProcessor.h" -#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" -#include "src/gpu/glsl/GrGLSLProgramBuilder.h" -#include "src/sksl/SkSLCPP.h" -#include "src/sksl/SkSLUtil.h" -class GrGLSLMatrixEffect : public GrGLSLFragmentProcessor { -public: - GrGLSLMatrixEffect() {} - void emitCode(EmitArgs& args) override { - GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - const GrMatrixEffect& _outer = args.fFp.cast<GrMatrixEffect>(); - (void)_outer; - auto matrix = _outer.matrix; - (void)matrix; - matrixVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, - kFloat3x3_GrSLType, "matrix"); - SkString _input716 = SkStringPrintf("%s", args.fInputColor); - SkString _sample716; - _sample716 = this->invokeChild(_outer.child_index, _input716.c_str(), args); - fragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, _sample716.c_str()); - } - -private: - void onSetData(const GrGLSLProgramDataManager& pdman, - const GrFragmentProcessor& _proc) override { - const GrMatrixEffect& _outer = _proc.cast<GrMatrixEffect>(); - { pdman.setSkMatrix(matrixVar, (_outer.matrix)); } - } - UniformHandle matrixVar; -}; -GrGLSLFragmentProcessor* GrMatrixEffect::onCreateGLSLInstance() const { - return new GrGLSLMatrixEffect(); -} -void GrMatrixEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, - GrProcessorKeyBuilder* b) const {} -bool GrMatrixEffect::onIsEqual(const GrFragmentProcessor& other) const { - const GrMatrixEffect& that = other.cast<GrMatrixEffect>(); - (void)that; - if (matrix != that.matrix) return false; - return true; -} -GrMatrixEffect::GrMatrixEffect(const GrMatrixEffect& src) - : INHERITED(kGrMatrixEffect_ClassID, src.optimizationFlags()) - , matrix(src.matrix) - , child_index(src.child_index) { - { - auto clone = src.childProcessor(child_index).clone(); - if (src.childProcessor(child_index).isSampledWithExplicitCoords()) { - clone->setSampledWithExplicitCoords(); - } - this->registerChildProcessor(std::move(clone)); - } -} -std::unique_ptr<GrFragmentProcessor> GrMatrixEffect::clone() const { - return std::unique_ptr<GrFragmentProcessor>(new GrMatrixEffect(*this)); -} diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.cpp index fea85f413a5..1dbf8ecabec 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.cpp @@ -27,21 +27,25 @@ public: (void)weight; weightVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf_GrSLType, "weight"); - SkString _input1278 = SkStringPrintf("%s", args.fInputColor); + SkString _input1278(args.fInputColor); SkString _sample1278; _sample1278 = this->invokeChild(_outer.fp0_index, _input1278.c_str(), args); - fragBuilder->codeAppendf("half4 in0 = %s;", _sample1278.c_str()); - SkString _input1335 = SkStringPrintf("%s", args.fInputColor); + fragBuilder->codeAppendf( + R"SkSL(half4 in0 = %s;)SkSL", _sample1278.c_str()); + SkString _input1335(args.fInputColor); SkString _sample1335; if (_outer.fp1_index >= 0) { _sample1335 = this->invokeChild(_outer.fp1_index, _input1335.c_str(), args); } else { - _sample1335 = "half4(1)"; + _sample1335.swap(_input1335); } - fragBuilder->codeAppendf("\nhalf4 in1 = %s ? %s : %s;\n%s = mix(in0, in1, %s);\n", - _outer.fp1_index >= 0 ? "true" : "false", _sample1335.c_str(), - args.fInputColor, args.fOutputColor, - args.fUniformHandler->getUniformCStr(weightVar)); + fragBuilder->codeAppendf( + R"SkSL( +half4 in1 = %s ? %s : %s; +%s = mix(in0, in1, %s); +)SkSL", + _outer.fp1_index >= 0 ? "true" : "false", _sample1335.c_str(), args.fInputColor, + args.fOutputColor, args.fUniformHandler->getUniformCStr(weightVar)); } private: @@ -64,23 +68,10 @@ bool GrMixerEffect::onIsEqual(const GrFragmentProcessor& other) const { return true; } GrMixerEffect::GrMixerEffect(const GrMixerEffect& src) - : INHERITED(kGrMixerEffect_ClassID, src.optimizationFlags()) - , fp0_index(src.fp0_index) - , fp1_index(src.fp1_index) - , weight(src.weight) { - { - auto clone = src.childProcessor(fp0_index).clone(); - if (src.childProcessor(fp0_index).isSampledWithExplicitCoords()) { - clone->setSampledWithExplicitCoords(); - } - this->registerChildProcessor(std::move(clone)); - } - if (fp1_index >= 0) { - auto clone = src.childProcessor(fp1_index).clone(); - if (src.childProcessor(fp1_index).isSampledWithExplicitCoords()) { - clone->setSampledWithExplicitCoords(); - } - this->registerChildProcessor(std::move(clone)); + : INHERITED(kGrMixerEffect_ClassID, src.optimizationFlags()), weight(src.weight) { + { fp0_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.fp0_index)); } + if (src.fp1_index >= 0) { + fp1_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.fp1_index)); } } std::unique_ptr<GrFragmentProcessor> GrMixerEffect::clone() const { diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.h index a9e3717f885..391fbf6bdb8 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.h @@ -10,11 +10,13 @@ **************************************************************************************************/ #ifndef GrMixerEffect_DEFINED #define GrMixerEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrMixerEffect : public GrFragmentProcessor { public: static OptimizationFlags OptFlags(const std::unique_ptr<GrFragmentProcessor>& fp0, @@ -54,11 +56,9 @@ private: : INHERITED(kGrMixerEffect_ClassID, (OptimizationFlags)OptFlags(fp0, fp1)) , weight(weight) { SkASSERT(fp0); - fp0_index = this->numChildProcessors(); - this->registerChildProcessor(std::move(fp0)); + fp0_index = this->registerChild(std::move(fp0)); if (fp1) { - fp1_index = this->numChildProcessors(); - this->registerChildProcessor(std::move(fp1)); + fp1_index = this->registerChild(std::move(fp1)); } } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp index 0e34b530003..deae796c1b1 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp @@ -35,8 +35,12 @@ public: kHalf4_GrSLType, "uniformColor"); } fragBuilder->codeAppendf( - "half4 constColor;\n@if (%s) {\n constColor = %s;\n} else {\n constColor = " - "half4(%f, %f, %f, %f);\n}", + R"SkSL(half4 constColor; +@if (%s) { + constColor = %s; +} else { + constColor = half4(%f, %f, %f, %f); +})SkSL", (_outer.useUniform ? "true" : "false"), uniformColorVar.isValid() ? args.fUniformHandler->getUniformCStr(uniformColorVar) : "half4(0)", @@ -45,7 +49,11 @@ public: SkString _input1992("constColor"); SkString _sample1992; _sample1992 = this->invokeChild(_outer.fp_index, _input1992.c_str(), args); - fragBuilder->codeAppendf("\n%s = %s;\n", args.fOutputColor, _sample1992.c_str()); + fragBuilder->codeAppendf( + R"SkSL( +%s = %s; +)SkSL", + args.fOutputColor, _sample1992.c_str()); } private: @@ -87,17 +95,10 @@ bool GrOverrideInputFragmentProcessor::onIsEqual(const GrFragmentProcessor& othe GrOverrideInputFragmentProcessor::GrOverrideInputFragmentProcessor( const GrOverrideInputFragmentProcessor& src) : INHERITED(kGrOverrideInputFragmentProcessor_ClassID, src.optimizationFlags()) - , fp_index(src.fp_index) , useUniform(src.useUniform) , uniformColor(src.uniformColor) , literalColor(src.literalColor) { - { - auto clone = src.childProcessor(fp_index).clone(); - if (src.childProcessor(fp_index).isSampledWithExplicitCoords()) { - clone->setSampledWithExplicitCoords(); - } - this->registerChildProcessor(std::move(clone)); - } + { fp_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.fp_index)); } } std::unique_ptr<GrFragmentProcessor> GrOverrideInputFragmentProcessor::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrOverrideInputFragmentProcessor(*this)); diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h index d69c16ebbbe..988b1caf0c4 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h @@ -10,11 +10,13 @@ **************************************************************************************************/ #ifndef GrOverrideInputFragmentProcessor_DEFINED #define GrOverrideInputFragmentProcessor_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrOverrideInputFragmentProcessor : public GrFragmentProcessor { public: static OptimizationFlags OptFlags(const std::unique_ptr<GrFragmentProcessor>& fp, @@ -59,8 +61,7 @@ private: , uniformColor(uniformColor) , literalColor(literalColor) { SkASSERT(fp); - fp_index = this->numChildProcessors(); - this->registerChildProcessor(std::move(fp)); + fp_index = this->registerChild(std::move(fp)); } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrPremulInputFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrPremulInputFragmentProcessor.cpp deleted file mode 100644 index f327850bdb9..00000000000 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrPremulInputFragmentProcessor.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 file was autogenerated from GrPremulInputFragmentProcessor.fp; do not modify. - **************************************************************************************************/ -#include "GrPremulInputFragmentProcessor.h" - -#include "src/gpu/GrTexture.h" -#include "src/gpu/glsl/GrGLSLFragmentProcessor.h" -#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" -#include "src/gpu/glsl/GrGLSLProgramBuilder.h" -#include "src/sksl/SkSLCPP.h" -#include "src/sksl/SkSLUtil.h" -class GrGLSLPremulInputFragmentProcessor : public GrGLSLFragmentProcessor { -public: - GrGLSLPremulInputFragmentProcessor() {} - void emitCode(EmitArgs& args) override { - GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; - const GrPremulInputFragmentProcessor& _outer = - args.fFp.cast<GrPremulInputFragmentProcessor>(); - (void)_outer; - fragBuilder->codeAppendf("%s = %s;\n%s.xyz *= %s.w;\n", args.fOutputColor, args.fInputColor, - args.fOutputColor, args.fInputColor); - } - -private: - void onSetData(const GrGLSLProgramDataManager& pdman, - const GrFragmentProcessor& _proc) override {} -}; -GrGLSLFragmentProcessor* GrPremulInputFragmentProcessor::onCreateGLSLInstance() const { - return new GrGLSLPremulInputFragmentProcessor(); -} -void GrPremulInputFragmentProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps, - GrProcessorKeyBuilder* b) const {} -bool GrPremulInputFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const { - const GrPremulInputFragmentProcessor& that = other.cast<GrPremulInputFragmentProcessor>(); - (void)that; - return true; -} -GrPremulInputFragmentProcessor::GrPremulInputFragmentProcessor( - const GrPremulInputFragmentProcessor& src) - : INHERITED(kGrPremulInputFragmentProcessor_ClassID, src.optimizationFlags()) {} -std::unique_ptr<GrFragmentProcessor> GrPremulInputFragmentProcessor::clone() const { - return std::unique_ptr<GrFragmentProcessor>(new GrPremulInputFragmentProcessor(*this)); -} diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrPremulInputFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrPremulInputFragmentProcessor.h deleted file mode 100644 index ae093ca6daf..00000000000 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrPremulInputFragmentProcessor.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 file was autogenerated from GrPremulInputFragmentProcessor.fp; do not modify. - **************************************************************************************************/ -#ifndef GrPremulInputFragmentProcessor_DEFINED -#define GrPremulInputFragmentProcessor_DEFINED -#include "include/core/SkTypes.h" -#include "include/core/SkM44.h" - -#include "src/gpu/GrCoordTransform.h" -#include "src/gpu/GrFragmentProcessor.h" -class GrPremulInputFragmentProcessor : public GrFragmentProcessor { -public: - SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override { - return SkColor4f{input.fR, input.fG, input.fB, input.fA}.premul(); - } - static std::unique_ptr<GrFragmentProcessor> Make() { - return std::unique_ptr<GrFragmentProcessor>(new GrPremulInputFragmentProcessor()); - } - GrPremulInputFragmentProcessor(const GrPremulInputFragmentProcessor& src); - std::unique_ptr<GrFragmentProcessor> clone() const override; - const char* name() const override { return "PremulInputFragmentProcessor"; } - -private: - GrPremulInputFragmentProcessor() - : INHERITED(kGrPremulInputFragmentProcessor_ClassID, - (OptimizationFlags)kPreservesOpaqueInput_OptimizationFlag | - kConstantOutputForConstantInput_OptimizationFlag) {} - GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; - void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; - bool onIsEqual(const GrFragmentProcessor&) const override; - GR_DECLARE_FRAGMENT_PROCESSOR_TEST - typedef GrFragmentProcessor INHERITED; -}; -#endif diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp index 6d93aa9ad2f..a2acd522195 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp @@ -23,15 +23,27 @@ public: GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; const GrRGBToHSLFilterEffect& _outer = args.fFp.cast<GrRGBToHSLFilterEffect>(); (void)_outer; + SkString _input1173(args.fInputColor); + SkString _sample1173; + if (_outer.inputFP_index >= 0) { + _sample1173 = this->invokeChild(_outer.inputFP_index, _input1173.c_str(), args); + } else { + _sample1173.swap(_input1173); + } fragBuilder->codeAppendf( - "half4 c = %s;\nhalf4 p = c.y < c.z ? half4(c.zy, -1.0, 0.66666666666666663) : " - "half4(c.yz, 0.0, -0.33333333333333331);\nhalf4 q = c.x < p.x ? half4(p.x, c.x, " - "p.yw) : half4(c.x, p.x, p.yz);\n\nhalf pmV = q.x;\nhalf pmC = pmV - min(q.y, " - "q.z);\nhalf pmL = pmV - pmC * 0.5;\nhalf H = abs(q.w + (q.y - q.z) / (pmC * 6.0 + " - "9.9999997473787516e-05));\nhalf S = pmC / ((c.w + 9.9999997473787516e-05) - " - "abs(pmL * 2.0 - c.w));\nhalf L = pmL / (c.w + 9.9999997473787516e-05);\n%s = " - "half4(H, S, L, c.w);\n", - args.fInputColor, args.fOutputColor); + R"SkSL(half4 c = %s; +half4 p = c.y < c.z ? half4(c.zy, -1.0, 0.66666666666666663) : half4(c.yz, 0.0, -0.33333333333333331); +half4 q = c.x < p.x ? half4(p.x, c.x, p.yw) : half4(c.x, p.x, p.yz); + +half pmV = q.x; +half pmC = pmV - min(q.y, q.z); +half pmL = pmV - pmC * 0.5; +half H = abs(q.w + (q.y - q.z) / (pmC * 6.0 + 9.9999997473787516e-05)); +half S = pmC / ((c.w + 9.9999997473787516e-05) - abs(pmL * 2.0 - c.w)); +half L = pmL / (c.w + 9.9999997473787516e-05); +%s = half4(H, S, L, c.w); +)SkSL", + _sample1173.c_str(), args.fOutputColor); } private: @@ -49,7 +61,11 @@ bool GrRGBToHSLFilterEffect::onIsEqual(const GrFragmentProcessor& other) const { return true; } GrRGBToHSLFilterEffect::GrRGBToHSLFilterEffect(const GrRGBToHSLFilterEffect& src) - : INHERITED(kGrRGBToHSLFilterEffect_ClassID, src.optimizationFlags()) {} + : INHERITED(kGrRGBToHSLFilterEffect_ClassID, src.optimizationFlags()) { + if (src.inputFP_index >= 0) { + inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); + } +} std::unique_ptr<GrFragmentProcessor> GrRGBToHSLFilterEffect::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrRGBToHSLFilterEffect(*this)); } diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.h index e8e0bba7561..4b5fdccd835 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.h @@ -10,16 +10,21 @@ **************************************************************************************************/ #ifndef GrRGBToHSLFilterEffect_DEFINED #define GrRGBToHSLFilterEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrRGBToHSLFilterEffect : public GrFragmentProcessor { public: #include "include/private/SkColorData.h" - SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& c) const override { + SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override { + SkPMColor4f c = this->numChildProcessors() + ? ConstantOutputForConstantInput(this->childProcessor(0), inColor) + : inColor; const auto p = (c.fG < c.fB) ? SkPMColor4f{c.fB, c.fG, -1, 2 / 3.f} : SkPMColor4f{c.fG, c.fB, 0, -1 / 3.f}, q = (c.fR < p[0]) ? SkPMColor4f{p[0], c.fR, p[1], p[3]} @@ -32,18 +37,25 @@ public: return {H, S, L, c.fA}; } - static std::unique_ptr<GrFragmentProcessor> Make() { - return std::unique_ptr<GrFragmentProcessor>(new GrRGBToHSLFilterEffect()); + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP) { + return std::unique_ptr<GrFragmentProcessor>(new GrRGBToHSLFilterEffect(std::move(inputFP))); } GrRGBToHSLFilterEffect(const GrRGBToHSLFilterEffect& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "RGBToHSLFilterEffect"; } + int inputFP_index = -1; private: - GrRGBToHSLFilterEffect() + GrRGBToHSLFilterEffect(std::unique_ptr<GrFragmentProcessor> inputFP) : INHERITED(kGrRGBToHSLFilterEffect_ClassID, - (OptimizationFlags)(kConstantOutputForConstantInput_OptimizationFlag | - kPreservesOpaqueInput_OptimizationFlag)) {} + (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get()) + : kAll_OptimizationFlags) & + (kConstantOutputForConstantInput_OptimizationFlag | + kPreservesOpaqueInput_OptimizationFlag)) { + if (inputFP) { + inputFP_index = this->registerChild(std::move(inputFP)); + } + } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.cpp index 74a49b102e0..968ab1e0ee6 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.cpp @@ -10,11 +10,13 @@ **************************************************************************************************/ #include "GrRRectBlurEffect.h" -std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::Make(GrRecordingContext* context, - float sigma, - float xformedSigma, - const SkRRect& srcRRect, - const SkRRect& devRRect) { +std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::Make( + std::unique_ptr<GrFragmentProcessor> inputFP, + GrRecordingContext* context, + float sigma, + float xformedSigma, + const SkRRect& srcRRect, + const SkRRect& devRRect) { SkASSERT(!SkRRectPriv::IsCircle(devRRect) && !devRRect.isRect()); // Should've been caught up-stream @@ -39,15 +41,15 @@ std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::Make(GrRecordingContext* return nullptr; } - GrSurfaceProxyView mask = - find_or_create_rrect_blur_mask(context, rrectToDraw, dimensions, xformedSigma); - if (!mask) { + std::unique_ptr<GrFragmentProcessor> maskFP = + find_or_create_rrect_blur_mask_fp(context, rrectToDraw, dimensions, xformedSigma); + if (!maskFP) { return nullptr; } return std::unique_ptr<GrFragmentProcessor>( - new GrRRectBlurEffect(xformedSigma, devRRect.getBounds(), - SkRRectPriv::GetSimpleRadii(devRRect).fX, std::move(mask))); + new GrRRectBlurEffect(std::move(inputFP), xformedSigma, devRRect.getBounds(), + SkRRectPriv::GetSimpleRadii(devRRect).fX, std::move(maskFP))); } #include "src/gpu/GrTexture.h" #include "src/gpu/glsl/GrGLSLFragmentProcessor.h" @@ -75,29 +77,42 @@ public: blurRadiusVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf_GrSLType, "blurRadius"); fragBuilder->codeAppendf( - "\nhalf2 translatedFragPos = half2(sk_FragCoord.xy - %s.xy);\nhalf threshold = %s " - "+ 2.0 * %s;\nhalf2 middle = half2((%s.zw - %s.xy) - float(2.0 * threshold));\nif " - "(translatedFragPos.x >= threshold && translatedFragPos.x < middle.x + threshold) " - "{\n translatedFragPos.x = threshold;\n} else if (translatedFragPos.x >= " - "middle.x + threshold) {\n translatedFragPos.x -= middle.x - 1.0;\n}\nif " - "(translatedFragPos.y > threshold && translatedFragPos.y < middle.y + threshold) " - "{\n translatedFragPos.y = threshold;", + R"SkSL(half2 translatedFragPos = half2(sk_FragCoord.xy - %s.xy); +half2 proxyCenter = half2((%s.zw - %s.xy) * 0.5); +half edgeSize = (2.0 * %s + %s) + 0.5; +translatedFragPos -= proxyCenter; +half2 fragDirection = sign(translatedFragPos); +translatedFragPos = abs(translatedFragPos); +translatedFragPos -= proxyCenter - edgeSize; +translatedFragPos = max(translatedFragPos, 0.0); +translatedFragPos *= fragDirection; +translatedFragPos += half2(edgeSize); +half2 proxyDims = half2(2.0 * edgeSize); +half2 texCoord = translatedFragPos / proxyDims;)SkSL", + args.fUniformHandler->getUniformCStr(proxyRectVar), args.fUniformHandler->getUniformCStr(proxyRectVar), - args.fUniformHandler->getUniformCStr(cornerRadiusVar), - args.fUniformHandler->getUniformCStr(blurRadiusVar), args.fUniformHandler->getUniformCStr(proxyRectVar), - args.fUniformHandler->getUniformCStr(proxyRectVar)); + args.fUniformHandler->getUniformCStr(blurRadiusVar), + args.fUniformHandler->getUniformCStr(cornerRadiusVar)); + SkString _input9604(args.fInputColor); + SkString _sample9604; + if (_outer.inputFP_index >= 0) { + _sample9604 = this->invokeChild(_outer.inputFP_index, _input9604.c_str(), args); + } else { + _sample9604.swap(_input9604); + } + fragBuilder->codeAppendf( + R"SkSL( +half4 inputColor = %s;)SkSL", + _sample9604.c_str()); + SkString _sample9664; + SkString _coords9664("float2(texCoord)"); + _sample9664 = this->invokeChild(_outer.ninePatchFP_index, args, _coords9664.c_str()); fragBuilder->codeAppendf( - "\n} else if (translatedFragPos.y >= middle.y + threshold) {\n " - "translatedFragPos.y -= middle.y - 1.0;\n}\nhalf2 proxyDims = half2(2.0 * " - "threshold + 1.0);\nhalf2 texCoord = translatedFragPos / proxyDims;\n%s = %s * " - "sample(%s, float2(texCoord)).%s;\n", - args.fOutputColor, args.fInputColor, - fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]), - fragBuilder->getProgramBuilder() - ->samplerSwizzle(args.fTexSamplers[0]) - .asString() - .c_str()); + R"SkSL( +%s = inputColor * %s; +)SkSL", + args.fOutputColor, _sample9664.c_str()); } private: @@ -111,9 +126,6 @@ private: (void)rect; UniformHandle& cornerRadius = cornerRadiusVar; (void)cornerRadius; - const GrSurfaceProxyView& ninePatchSamplerView = _outer.textureSampler(0).view(); - GrTexture& ninePatchSampler = *ninePatchSamplerView.proxy()->peekTexture(); - (void)ninePatchSampler; UniformHandle& proxyRect = proxyRectVar; (void)proxyRect; UniformHandle& blurRadius = blurRadiusVar; @@ -141,23 +153,24 @@ bool GrRRectBlurEffect::onIsEqual(const GrFragmentProcessor& other) const { if (sigma != that.sigma) return false; if (rect != that.rect) return false; if (cornerRadius != that.cornerRadius) return false; - if (ninePatchSampler != that.ninePatchSampler) return false; return true; } GrRRectBlurEffect::GrRRectBlurEffect(const GrRRectBlurEffect& src) : INHERITED(kGrRRectBlurEffect_ClassID, src.optimizationFlags()) , sigma(src.sigma) , rect(src.rect) - , cornerRadius(src.cornerRadius) - , ninePatchSampler(src.ninePatchSampler) { - this->setTextureSamplerCnt(1); + , cornerRadius(src.cornerRadius) { + if (src.inputFP_index >= 0) { + inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); + } + { + ninePatchFP_index = + this->cloneAndRegisterChildProcessor(src.childProcessor(src.ninePatchFP_index)); + } } std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrRRectBlurEffect(*this)); } -const GrFragmentProcessor::TextureSampler& GrRRectBlurEffect::onTextureSampler(int index) const { - return IthTextureSampler(index, ninePatchSampler); -} GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRRectBlurEffect); #if GR_TEST_UTILS std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::TestCreate(GrProcessorTestData* d) { @@ -167,6 +180,6 @@ std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::TestCreate(GrProcessorTe SkScalar sigma = d->fRandom->nextRangeF(1.f, 10.f); SkRRect rrect; rrect.setRectXY(SkRect::MakeWH(w, h), r, r); - return GrRRectBlurEffect::Make(d->context(), sigma, sigma, rrect, rrect); + return GrRRectBlurEffect::Make(/*inputFP=*/nullptr, d->context(), sigma, sigma, rrect, rrect); } #endif diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.h index 84eb69d48d3..32efd147c60 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.h @@ -10,8 +10,9 @@ **************************************************************************************************/ #ifndef GrRRectBlurEffect_DEFINED #define GrRRectBlurEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "include/gpu/GrContext.h" #include "include/private/GrRecordingContext.h" @@ -19,21 +20,23 @@ #include "src/core/SkGpuBlurUtils.h" #include "src/core/SkRRectPriv.h" #include "src/gpu/GrCaps.h" -#include "src/gpu/GrClip.h" #include "src/gpu/GrPaint.h" #include "src/gpu/GrProxyProvider.h" #include "src/gpu/GrRecordingContextPriv.h" #include "src/gpu/GrRenderTargetContext.h" #include "src/gpu/GrStyle.h" +#include "src/gpu/effects/GrTextureEffect.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrRRectBlurEffect : public GrFragmentProcessor { public: - static GrSurfaceProxyView find_or_create_rrect_blur_mask(GrRecordingContext* context, - const SkRRect& rrectToDraw, - const SkISize& dimensions, - float xformedSigma) { + static std::unique_ptr<GrFragmentProcessor> find_or_create_rrect_blur_mask_fp( + GrRecordingContext* context, + const SkRRect& rrectToDraw, + const SkISize& dimensions, + float xformedSigma) { static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); GrUniqueKey key; GrUniqueKey::Builder builder(&key, kDomain, 9, "RoundRect Blur Mask"); @@ -49,31 +52,37 @@ public: } builder.finish(); + // It seems like we could omit this matrix and modify the shader code to not normalize + // the coords used to sample the texture effect. However, the "proxyDims" value in the + // shader is not always the actual the proxy dimensions. This is because 'dimensions' here + // was computed using integer corner radii as determined in + // SkComputeBlurredRRectParams whereas the shader code uses the float radius to compute + // 'proxyDims'. Why it draws correctly with these unequal values is a mystery for the ages. + auto m = SkMatrix::Scale(dimensions.width(), dimensions.height()); static constexpr auto kMaskOrigin = kBottomLeft_GrSurfaceOrigin; GrProxyProvider* proxyProvider = context->priv().proxyProvider(); if (auto view = proxyProvider->findCachedProxyWithColorTypeFallback( key, kMaskOrigin, GrColorType::kAlpha_8, 1)) { - return view; + return GrTextureEffect::Make(std::move(view), kPremul_SkAlphaType, m); } auto rtc = GrRenderTargetContext::MakeWithFallback( context, GrColorType::kAlpha_8, nullptr, SkBackingFit::kExact, dimensions, 1, GrMipMapped::kNo, GrProtected::kNo, kMaskOrigin); if (!rtc) { - return {}; + return nullptr; } GrPaint paint; - rtc->clear(nullptr, SK_PMColor4fTRANSPARENT, - GrRenderTargetContext::CanClearFullscreen::kYes); - rtc->drawRRect(GrNoClip(), std::move(paint), GrAA::kYes, SkMatrix::I(), rrectToDraw, + rtc->clear(SK_PMColor4fTRANSPARENT); + rtc->drawRRect(nullptr, std::move(paint), GrAA::kYes, SkMatrix::I(), rrectToDraw, GrStyle::SimpleFill()); GrSurfaceProxyView srcView = rtc->readSurfaceView(); if (!srcView) { - return {}; + return nullptr; } SkASSERT(srcView.asTextureProxy()); auto rtc2 = SkGpuBlurUtils::GaussianBlur(context, @@ -88,21 +97,21 @@ public: SkTileMode::kClamp, SkBackingFit::kExact); if (!rtc2) { - return {}; + return nullptr; } GrSurfaceProxyView mask = rtc2->readSurfaceView(); if (!mask) { - return {}; + return nullptr; } SkASSERT(mask.asTextureProxy()); - SkASSERT(mask.origin() == kBottomLeft_GrSurfaceOrigin); + SkASSERT(mask.origin() == kMaskOrigin); proxyProvider->assignUniqueKeyToProxy(key, mask.asTextureProxy()); - - return mask; + return GrTextureEffect::Make(std::move(mask), kPremul_SkAlphaType, m); } - static std::unique_ptr<GrFragmentProcessor> Make(GrRecordingContext* context, + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrRecordingContext* context, float sigma, float xformedSigma, const SkRRect& srcRRect, @@ -110,28 +119,34 @@ public: GrRRectBlurEffect(const GrRRectBlurEffect& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "RRectBlurEffect"; } + int inputFP_index = -1; float sigma; SkRect rect; float cornerRadius; - TextureSampler ninePatchSampler; + int ninePatchFP_index = -1; private: - GrRRectBlurEffect(float sigma, + GrRRectBlurEffect(std::unique_ptr<GrFragmentProcessor> inputFP, + float sigma, SkRect rect, float cornerRadius, - GrSurfaceProxyView ninePatchSampler) + std::unique_ptr<GrFragmentProcessor> ninePatchFP) : INHERITED(kGrRRectBlurEffect_ClassID, - (OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag) + (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get()) + : kAll_OptimizationFlags) & + kCompatibleWithCoverageAsAlpha_OptimizationFlag) , sigma(sigma) , rect(rect) - , cornerRadius(cornerRadius) - , ninePatchSampler(std::move(ninePatchSampler)) { - this->setTextureSamplerCnt(1); + , cornerRadius(cornerRadius) { + if (inputFP) { + inputFP_index = this->registerChild(std::move(inputFP)); + } + SkASSERT(ninePatchFP); + ninePatchFP_index = this->registerExplicitlySampledChild(std::move(ninePatchFP)); } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; - const TextureSampler& onTextureSampler(int) const override; GR_DECLARE_FRAGMENT_PROCESSOR_TEST typedef GrFragmentProcessor INHERITED; }; diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.cpp index 11180695942..689c69bb725 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.cpp +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.cpp @@ -25,8 +25,6 @@ public: (void)_outer; auto rect = _outer.rect; (void)rect; - auto invSixSigma = _outer.invSixSigma; - (void)invSixSigma; auto isFast = _outer.isFast; (void)isFast; highp = ((abs(rect.left()) > 16000.0 || abs(rect.top()) > 16000.0) || @@ -40,103 +38,94 @@ public: rectHVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf4_GrSLType, "rectH"); } - invSixSigmaVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, - kHalf_GrSLType, "invSixSigma"); fragBuilder->codeAppendf( - "/* key */ bool highp = %s;\nhalf xCoverage, yCoverage;\n@if (%s) {\n half x, " - "y;\n @if (highp) {\n x = max(half(%s.x - sk_FragCoord.x), " - "half(sk_FragCoord.x - %s.z));\n y = max(half(%s.y - sk_FragCoord.y), " - "half(sk_FragCoord.y - %s.w));\n } else {\n x = max(half(float(%s.x) - " - "sk_FragCoord.x), half(sk_FragCoord.x - float(%s.z)));\n y = " - "max(half(float(%s.y) - sk_FragCoord.y), half(sk_FragCoord.y - float(%s.w)));\n " - "}\n xCoverage = sample(%s, float2(half2(x * %s, 0.5))).", + R"SkSL(/* key */ bool highp = %s; +half xCoverage, yCoverage; +@if (%s) { + half2 xy; + @if (highp) { + xy = max(half2(%s.xy - sk_FragCoord.xy), half2(sk_FragCoord.xy - %s.zw)); + } else { + xy = max(half2(float2(%s.xy) - sk_FragCoord.xy), half2(sk_FragCoord.xy - float2(%s.zw))); + })SkSL", (highp ? "true" : "false"), (_outer.isFast ? "true" : "false"), rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)", rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)", - rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)", - rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)", - rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)", - rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)", - rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)", rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)", - fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]), - args.fUniformHandler->getUniformCStr(invSixSigmaVar)); + rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)"); + SkString _sample7215; + SkString _coords7215("float2(half2(xy.x, 0.5))"); + _sample7215 = this->invokeChild(_outer.integral_index, args, _coords7215.c_str()); fragBuilder->codeAppendf( - "%s.w;\n yCoverage = sample(%s, float2(half2(y * %s, 0.5))).%s.w;\n %s = (%s " - "* xCoverage) * yCoverage;\n} else {\n half l, r, t, b;\n @if (highp) {\n " - " l = half(sk_FragCoord.x - %s.x);\n r = half(%s.z - sk_FragCoord.x);\n " - " t = half(sk_FragCoord.y - %s.y);\n b = half(%s.w - " - "sk_FragCoord.y);\n } else {\n l = half(sk_FragCoord.x - float(%s.x));\n " - " r = half(float(%s.z) - sk_FragCoord.x);\n t = half(sk_FragCoord.y - " - "float(%s.y));\n b = half(float(", - fragBuilder->getProgramBuilder() - ->samplerSwizzle(args.fTexSamplers[0]) - .asString() - .c_str(), - fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]), - args.fUniformHandler->getUniformCStr(invSixSigmaVar), - fragBuilder->getProgramBuilder() - ->samplerSwizzle(args.fTexSamplers[0]) - .asString() - .c_str(), - args.fOutputColor, args.fInputColor, - rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)", - rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)", + R"SkSL( + xCoverage = %s.w;)SkSL", + _sample7215.c_str()); + SkString _sample7273; + SkString _coords7273("float2(half2(xy.y, 0.5))"); + _sample7273 = this->invokeChild(_outer.integral_index, args, _coords7273.c_str()); + fragBuilder->codeAppendf( + R"SkSL( + yCoverage = %s.w; +} else { + half4 rect; + @if (highp) { + rect.xy = half2(%s.xy - sk_FragCoord.xy); + rect.zw = half2(sk_FragCoord.xy - %s.zw); + } else { + rect.xy = half2(float2(%s.xy) - sk_FragCoord.xy); + rect.zw = half2(sk_FragCoord.xy - float2(%s.zw)); + })SkSL", + _sample7273.c_str(), rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)", rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)", rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)", - rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)", rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)"); + SkString _sample8640; + SkString _coords8640("float2(half2(rect.x, 0.5))"); + _sample8640 = this->invokeChild(_outer.integral_index, args, _coords8640.c_str()); + SkString _sample8703; + SkString _coords8703("float2(half2(rect.z, 0.5))"); + _sample8703 = this->invokeChild(_outer.integral_index, args, _coords8703.c_str()); fragBuilder->codeAppendf( - "%s.w) - sk_FragCoord.y);\n }\n half il = 1.0 + l * %s;\n half ir = 1.0 + " - "r * %s;\n half it = 1.0 + t * %s;\n half ib = 1.0 + b * %s;\n xCoverage " - "= (1.0 - sample(%s, float2(half2(il, 0.5))).%s.w) - sample(%s, float2(half2(ir, " - "0.5))).%s.w;\n yCoverage = (1.0 - sample(%s, float2(half2(it, 0.5))).%s.w) - " - "sample(%s, float2(half2(ib, 0.5))).%s.w;\n}\n%s = (%s * xCoverage) * yCoverage;\n", - rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)", - args.fUniformHandler->getUniformCStr(invSixSigmaVar), - args.fUniformHandler->getUniformCStr(invSixSigmaVar), - args.fUniformHandler->getUniformCStr(invSixSigmaVar), - args.fUniformHandler->getUniformCStr(invSixSigmaVar), - fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]), - fragBuilder->getProgramBuilder() - ->samplerSwizzle(args.fTexSamplers[0]) - .asString() - .c_str(), - fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]), - fragBuilder->getProgramBuilder() - ->samplerSwizzle(args.fTexSamplers[0]) - .asString() - .c_str(), - fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]), - fragBuilder->getProgramBuilder() - ->samplerSwizzle(args.fTexSamplers[0]) - .asString() - .c_str(), - fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]), - fragBuilder->getProgramBuilder() - ->samplerSwizzle(args.fTexSamplers[0]) - .asString() - .c_str(), - args.fOutputColor, args.fInputColor); + R"SkSL( + xCoverage = (1.0 - %s.w) - %s.w;)SkSL", + _sample8640.c_str(), _sample8703.c_str()); + SkString _sample8767; + SkString _coords8767("float2(half2(rect.y, 0.5))"); + _sample8767 = this->invokeChild(_outer.integral_index, args, _coords8767.c_str()); + SkString _sample8830; + SkString _coords8830("float2(half2(rect.w, 0.5))"); + _sample8830 = this->invokeChild(_outer.integral_index, args, _coords8830.c_str()); + fragBuilder->codeAppendf( + R"SkSL( + yCoverage = (1.0 - %s.w) - %s.w; +})SkSL", + _sample8767.c_str(), _sample8830.c_str()); + SkString _input8899(args.fInputColor); + SkString _sample8899; + if (_outer.inputFP_index >= 0) { + _sample8899 = this->invokeChild(_outer.inputFP_index, _input8899.c_str(), args); + } else { + _sample8899.swap(_input8899); + } + fragBuilder->codeAppendf( + R"SkSL( +half4 inputColor = %s; +%s = (inputColor * xCoverage) * yCoverage; +)SkSL", + _sample8899.c_str(), args.fOutputColor); } private: void onSetData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& _proc) override { const GrRectBlurEffect& _outer = _proc.cast<GrRectBlurEffect>(); - { pdman.set1f(invSixSigmaVar, (_outer.invSixSigma)); } auto rect = _outer.rect; (void)rect; UniformHandle& rectF = rectFVar; (void)rectF; UniformHandle& rectH = rectHVar; (void)rectH; - const GrSurfaceProxyView& integralView = _outer.textureSampler(0).view(); - GrTexture& integral = *integralView.proxy()->peekTexture(); - (void)integral; - UniformHandle& invSixSigma = invSixSigmaVar; - (void)invSixSigma; auto isFast = _outer.isFast; (void)isFast; @@ -146,7 +135,6 @@ private: bool highp = false; UniformHandle rectFVar; UniformHandle rectHVar; - UniformHandle invSixSigmaVar; }; GrGLSLFragmentProcessor* GrRectBlurEffect::onCreateGLSLInstance() const { return new GrGLSLRectBlurEffect(); @@ -163,32 +151,31 @@ bool GrRectBlurEffect::onIsEqual(const GrFragmentProcessor& other) const { const GrRectBlurEffect& that = other.cast<GrRectBlurEffect>(); (void)that; if (rect != that.rect) return false; - if (integral != that.integral) return false; - if (invSixSigma != that.invSixSigma) return false; if (isFast != that.isFast) return false; return true; } GrRectBlurEffect::GrRectBlurEffect(const GrRectBlurEffect& src) : INHERITED(kGrRectBlurEffect_ClassID, src.optimizationFlags()) , rect(src.rect) - , integral(src.integral) - , invSixSigma(src.invSixSigma) , isFast(src.isFast) { - this->setTextureSamplerCnt(1); + if (src.inputFP_index >= 0) { + inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); + } + { + integral_index = + this->cloneAndRegisterChildProcessor(src.childProcessor(src.integral_index)); + } } std::unique_ptr<GrFragmentProcessor> GrRectBlurEffect::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect(*this)); } -const GrFragmentProcessor::TextureSampler& GrRectBlurEffect::onTextureSampler(int index) const { - return IthTextureSampler(index, integral); -} GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRectBlurEffect); #if GR_TEST_UTILS std::unique_ptr<GrFragmentProcessor> GrRectBlurEffect::TestCreate(GrProcessorTestData* data) { float sigma = data->fRandom->nextRangeF(3, 8); float width = data->fRandom->nextRangeF(200, 300); float height = data->fRandom->nextRangeF(200, 300); - return GrRectBlurEffect::Make(data->context(), *data->caps()->shaderCaps(), + return GrRectBlurEffect::Make(/*inputFP=*/nullptr, data->context(), *data->caps()->shaderCaps(), SkRect::MakeWH(width, height), sigma); } #endif diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.h index 37727a96d38..9b45f1e983e 100644 --- a/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.h +++ b/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.h @@ -10,8 +10,9 @@ **************************************************************************************************/ #ifndef GrRectBlurEffect_DEFINED #define GrRectBlurEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include <cmath> #include "include/core/SkRect.h" @@ -24,12 +25,15 @@ #include "src/gpu/GrProxyProvider.h" #include "src/gpu/GrRecordingContextPriv.h" #include "src/gpu/GrShaderCaps.h" +#include "src/gpu/effects/GrTextureEffect.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrRectBlurEffect : public GrFragmentProcessor { public: - static GrSurfaceProxyView CreateIntegralTexture(GrRecordingContext* context, float sixSigma) { + static std::unique_ptr<GrFragmentProcessor> MakeIntegralFP(GrRecordingContext* context, + float sixSigma) { // The texture we're producing represents the integral of a normal distribution over a // six-sigma range centered at zero. We want enough resolution so that the linear // interpolation done in texture lookup doesn't introduce noticeable artifacts. We @@ -44,11 +48,15 @@ public: builder[0] = width; builder.finish(); + SkMatrix m = SkMatrix::Scale(width / sixSigma, 1.f); + GrProxyProvider* proxyProvider = context->priv().proxyProvider(); if (sk_sp<GrTextureProxy> proxy = proxyProvider->findOrCreateProxyByUniqueKey(key)) { GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(proxy->backendFormat(), GrColorType::kAlpha_8); - return {std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle}; + GrSurfaceProxyView view{std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle}; + return GrTextureEffect::Make(std::move(view), kPremul_SkAlphaType, m, + GrSamplerState::Filter::kBilerp); } SkBitmap bitmap; @@ -73,10 +81,12 @@ public: } SkASSERT(view.origin() == kTopLeft_GrSurfaceOrigin); proxyProvider->assignUniqueKeyToProxy(key, view.asTextureProxy()); - return view; + return GrTextureEffect::Make(std::move(view), kPremul_SkAlphaType, m, + GrSamplerState::Filter::kBilerp); } - static std::unique_ptr<GrFragmentProcessor> Make(GrRecordingContext* context, + static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP, + GrRecordingContext* context, const GrShaderCaps& caps, const SkRect& rect, float sigma) { @@ -92,7 +102,7 @@ public: } const float sixSigma = 6 * sigma; - GrSurfaceProxyView integral = CreateIntegralTexture(context, sixSigma); + std::unique_ptr<GrFragmentProcessor> integral = MakeIntegralFP(context, sixSigma); if (!integral) { return nullptr; } @@ -110,39 +120,39 @@ public: // less than 6 sigma wide then things aren't so simple and we have to consider both the // left and right edge of the rectangle (and similar in y). bool isFast = insetRect.isSorted(); - // 1 / (6 * sigma) is the domain of the integral texture. We use the inverse to produce - // normalized texture coords from frag coord distances. - float invSixSigma = 1.f / sixSigma; return std::unique_ptr<GrFragmentProcessor>( - new GrRectBlurEffect(insetRect, std::move(integral), invSixSigma, isFast, + new GrRectBlurEffect(std::move(inputFP), insetRect, std::move(integral), isFast, GrSamplerState::Filter::kBilerp)); } GrRectBlurEffect(const GrRectBlurEffect& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "RectBlurEffect"; } + int inputFP_index = -1; SkRect rect; - TextureSampler integral; - float invSixSigma; + int integral_index = -1; bool isFast; private: - GrRectBlurEffect(SkRect rect, - GrSurfaceProxyView integral, - float invSixSigma, + GrRectBlurEffect(std::unique_ptr<GrFragmentProcessor> inputFP, + SkRect rect, + std::unique_ptr<GrFragmentProcessor> integral, bool isFast, GrSamplerState samplerParams) : INHERITED(kGrRectBlurEffect_ClassID, - (OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag) + (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get()) + : kAll_OptimizationFlags) & + kCompatibleWithCoverageAsAlpha_OptimizationFlag) , rect(rect) - , integral(std::move(integral), samplerParams) - , invSixSigma(invSixSigma) , isFast(isFast) { - this->setTextureSamplerCnt(1); + if (inputFP) { + inputFP_index = this->registerChild(std::move(inputFP)); + } + SkASSERT(integral); + integral_index = this->registerExplicitlySampledChild(std::move(integral)); } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; - const TextureSampler& onTextureSampler(int) const override; GR_DECLARE_FRAGMENT_PROCESSOR_TEST typedef GrFragmentProcessor INHERITED; }; diff --git a/chromium/third_party/skia/src/gpu/geometry/GrPathUtils.cpp b/chromium/third_party/skia/src/gpu/geometry/GrPathUtils.cpp index 625b9d6756f..55d1207c4ca 100644 --- a/chromium/third_party/skia/src/gpu/geometry/GrPathUtils.cpp +++ b/chromium/third_party/skia/src/gpu/geometry/GrPathUtils.cpp @@ -188,6 +188,7 @@ int GrPathUtils::worstCasePointCount(const SkPath& path, int* subpaths, SkScalar for (int i = 0; i < converter.countQuads(); ++i) { pointCount += quadraticPointCount(quadPts + 2*i, tol); } + [[fallthrough]]; } case SkPath::kQuad_Verb: pointCount += quadraticPointCount(pts, tol); @@ -806,7 +807,7 @@ SkCubicType GrPathUtils::getCubicKLM(const SkPoint src[4], SkMatrix* klm, double switch (type) { case SkCubicType::kCuspAtInfinity: SkASSERT(1 == t1 && 0 == s1); // Infinity. - // fallthru. + [[fallthrough]]; case SkCubicType::kLocalCusp: case SkCubicType::kSerpentine: calc_serp_kcoeffs(t0, s0, t1, s1, skipTerm, &klmCoeffs[0]); diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLBuffer.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLBuffer.cpp index fc11731b736..0ac421d116d 100644 --- a/chromium/third_party/skia/src/gpu/gl/GrGLBuffer.cpp +++ b/chromium/third_party/skia/src/gpu/gl/GrGLBuffer.cpp @@ -14,15 +14,17 @@ #define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X) #define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glGpu()->glInterface(), RET, X) -#if GR_GL_CHECK_ALLOC_WITH_GET_ERROR - #define CLEAR_ERROR_BEFORE_ALLOC(iface) GrGLClearErr(iface) - #define GL_ALLOC_CALL(iface, call) GR_GL_CALL_NOERRCHECK(iface, call) - #define CHECK_ALLOC_ERROR(iface) GR_GL_GET_ERROR(iface) -#else - #define CLEAR_ERROR_BEFORE_ALLOC(iface) - #define GL_ALLOC_CALL(iface, call) GR_GL_CALL(iface, call) - #define CHECK_ALLOC_ERROR(iface) GR_GL_NO_ERROR -#endif +#define GL_ALLOC_CALL(call) \ + [&] { \ + if (this->glGpu()->glCaps().skipErrorChecks()) { \ + GR_GL_CALL(this->glGpu()->glInterface(), call); \ + return static_cast<GrGLenum>(GR_GL_NO_ERROR); \ + } else { \ + this->glGpu()->clearErrorsAndCheckForOOM(); \ + GR_GL_CALL_NOERRCHECK(this->glGpu()->glInterface(), call); \ + return this->glGpu()->getErrorAndCheckForOOM(); \ + } \ + }() #ifdef SK_DEBUG #define VALIDATE() this->validate() @@ -109,13 +111,8 @@ GrGLBuffer::GrGLBuffer(GrGLGpu* gpu, size_t size, GrGpuBufferType intendedType, GL_CALL(GenBuffers(1, &fBufferID)); if (fBufferID) { GrGLenum target = gpu->bindBuffer(fIntendedType, this); - CLEAR_ERROR_BEFORE_ALLOC(gpu->glInterface()); - // make sure driver can allocate memory for this buffer - GL_ALLOC_CALL(gpu->glInterface(), BufferData(target, - (GrGLsizeiptr) size, - data, - fUsage)); - if (CHECK_ALLOC_ERROR(gpu->glInterface()) != GR_GL_NO_ERROR) { + GrGLenum error = GL_ALLOC_CALL(BufferData(target, (GrGLsizeiptr)size, data, fUsage)); + if (error != GR_GL_NO_ERROR) { GL_CALL(DeleteBuffers(1, &fBufferID)); fBufferID = 0; } else { @@ -182,7 +179,11 @@ void GrGLBuffer::onMap() { if (!readOnly) { // Let driver know it can discard the old data if (this->glCaps().useBufferDataNullHint() || fGLSizeInBytes != this->size()) { - GL_CALL(BufferData(target, this->size(), nullptr, fUsage)); + GrGLenum error = + GL_ALLOC_CALL(BufferData(target, this->size(), nullptr, fUsage)); + if (error != GR_GL_NO_ERROR) { + return; + } } } GL_CALL_RET(fMapPtr, MapBuffer(target, readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY)); @@ -192,7 +193,10 @@ void GrGLBuffer::onMap() { GrGLenum target = this->glGpu()->bindBuffer(fIntendedType, this); // Make sure the GL buffer size agrees with fDesc before mapping. if (fGLSizeInBytes != this->size()) { - GL_CALL(BufferData(target, this->size(), nullptr, fUsage)); + GrGLenum error = GL_ALLOC_CALL(BufferData(target, this->size(), nullptr, fUsage)); + if (error != GR_GL_NO_ERROR) { + return; + } } GrGLbitfield access; if (readOnly) { @@ -211,7 +215,10 @@ void GrGLBuffer::onMap() { GrGLenum target = this->glGpu()->bindBuffer(fIntendedType, this); // Make sure the GL buffer size agrees with fDesc before mapping. if (fGLSizeInBytes != this->size()) { - GL_CALL(BufferData(target, this->size(), nullptr, fUsage)); + GrGLenum error = GL_ALLOC_CALL(BufferData(target, this->size(), nullptr, fUsage)); + if (error != GR_GL_NO_ERROR) { + return; + } } GL_CALL_RET(fMapPtr, MapBufferSubData(target, 0, this->size(), readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY)); @@ -266,7 +273,11 @@ bool GrGLBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) { if (this->glCaps().useBufferDataNullHint()) { if (this->size() == srcSizeInBytes) { - GL_CALL(BufferData(target, (GrGLsizeiptr) srcSizeInBytes, src, fUsage)); + GrGLenum error = + GL_ALLOC_CALL(BufferData(target, (GrGLsizeiptr)srcSizeInBytes, src, fUsage)); + if (error != GR_GL_NO_ERROR) { + return false; + } } else { // Before we call glBufferSubData we give the driver a hint using // glBufferData with nullptr. This makes the old buffer contents @@ -275,7 +286,11 @@ bool GrGLBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) { // assign a different allocation for the new contents to avoid // flushing the gpu past draws consuming the old contents. // TODO I think we actually want to try calling bufferData here - GL_CALL(BufferData(target, this->size(), nullptr, fUsage)); + GrGLenum error = + GL_ALLOC_CALL(BufferData(target, (GrGLsizeiptr)this->size(), nullptr, fUsage)); + if (error != GR_GL_NO_ERROR) { + return false; + } GL_CALL(BufferSubData(target, 0, (GrGLsizeiptr) srcSizeInBytes, src)); } fGLSizeInBytes = this->size(); @@ -283,7 +298,11 @@ bool GrGLBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) { // Note that we're cheating on the size here. Currently no methods // allow a partial update that preserves contents of non-updated // portions of the buffer (map() does a glBufferData(..size, nullptr..)) - GL_CALL(BufferData(target, srcSizeInBytes, src, fUsage)); + GrGLenum error = + GL_ALLOC_CALL(BufferData(target, (GrGLsizeiptr)srcSizeInBytes, src, fUsage)); + if (error != GR_GL_NO_ERROR) { + return false; + } fGLSizeInBytes = srcSizeInBytes; } VALIDATE(); diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLCaps.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLCaps.cpp index 062a3e10d87..dd4e89b084e 100644 --- a/chromium/third_party/skia/src/gpu/gl/GrGLCaps.cpp +++ b/chromium/third_party/skia/src/gpu/gl/GrGLCaps.cpp @@ -11,6 +11,7 @@ #include "src/core/SkCompressedDataUtils.h" #include "src/core/SkTSearch.h" #include "src/core/SkTSort.h" +#include "src/gpu/GrBackendUtils.h" #include "src/gpu/GrProgramDesc.h" #include "src/gpu/GrRenderTargetProxyPriv.h" #include "src/gpu/GrShaderCaps.h" @@ -236,15 +237,8 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, fRectangleTextureSupport = true; } } else if (GR_IS_GR_GL_ES(standard)) { - if (ctxInfo.driver() == kChromium_GrGLDriver || - ctxInfo.driver() == kSwiftShader_GrGLDriver) { - fRectangleTextureSupport = ctxInfo.hasExtension("GL_ARB_texture_rectangle"); - } else { - // ANGLE will advertise the extension in ES2 contexts but actually using the texture in - // a shader requires ES3 shading language. - fRectangleTextureSupport = ctxInfo.hasExtension("GL_ANGLE_texture_rectangle") && - ctxInfo.glslGeneration() >= k330_GrGLSLGeneration; - } + fRectangleTextureSupport = ctxInfo.hasExtension("GL_ARB_texture_rectangle") || + ctxInfo.hasExtension("GL_ANGLE_texture_rectangle"); } // no WebGL support // GrCaps defaults fClampToBorderSupport to true, so disable when unsupported @@ -335,6 +329,10 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, } // No WebGL support fSkipErrorChecks = ctxInfo.driver() == kChromium_GrGLDriver; + if (GR_IS_GR_WEBGL(standard)) { + // Error checks are quite costly in webgl, especially in Chrome. + fSkipErrorChecks = true; + } /************************************************************************** * GrShaderCaps fields @@ -652,13 +650,12 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, // Only in WebGL 2.0 fSemaphoreSupport = fFenceSyncSupport = version >= GR_GL_VER(2, 0); fFenceType = FenceType::kSyncObject; - } else if (ctxInfo.hasExtension("GL_ARB_sync") || ctxInfo.hasExtension("GL_APPLE_sync")) { + } else if (GR_IS_GR_GL(standard) && + (version >= GR_GL_VER(3, 2) || ctxInfo.hasExtension("GL_ARB_sync"))) { fSemaphoreSupport = fFenceSyncSupport = true; fFenceType = FenceType::kSyncObject; - } else if (GR_IS_GR_GL(standard) && version >= GR_GL_VER(3, 2)) { - fSemaphoreSupport = fFenceSyncSupport = true; - fFenceType = FenceType::kSyncObject; - } else if (GR_IS_GR_GL_ES(standard) && version >= GR_GL_VER(3, 0)) { + } else if (GR_IS_GR_GL_ES(standard) && + (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_APPLE_sync"))) { fSemaphoreSupport = fFenceSyncSupport = true; fFenceType = FenceType::kSyncObject; } else if (ctxInfo.hasExtension("GL_NV_fence")) { @@ -843,6 +840,14 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli fFBFetchRequiresEnablePerSample = true; } shaderCaps->fUsesPrecisionModifiers = true; + } else if (GR_IS_GR_GL(standard)) { + if (ctxInfo.hasExtension("GL_EXT_shader_framebuffer_fetch")) { + shaderCaps->fFBFetchNeedsCustomOutput = (version >= GR_GL_VER(3, 0)); + shaderCaps->fFBFetchSupport = true; + shaderCaps->fFBFetchColorName = "gl_LastFragData[0]"; + shaderCaps->fFBFetchExtensionString = "GL_EXT_shader_framebuffer_fetch"; + fFBFetchRequiresEnablePerSample = false; + } } else if (GR_IS_GR_WEBGL(standard)) { shaderCaps->fUsesPrecisionModifiers = true; } @@ -882,17 +887,21 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli } } + bool hasTessellationSupport = false; if (GR_IS_GR_GL(standard)) { - shaderCaps->fTessellationSupport = - version >= GR_GL_VER(4,0) || - ctxInfo.hasExtension("GL_ARB_tessellation_shader"); - } else { - if (version >= GR_GL_VER(3,2)) { - shaderCaps->fTessellationSupport = true; - } else if (ctxInfo.hasExtension("GL_OES_tessellation_shader")) { - shaderCaps->fTessellationSupport = true; - shaderCaps->fTessellationExtensionString = "GL_OES_tessellation_shader"; - } + hasTessellationSupport = version >= GR_GL_VER(4,0) || + ctxInfo.hasExtension("GL_ARB_tessellation_shader"); + } else if (version >= GR_GL_VER(3,2)) { + hasTessellationSupport = true; + } else if (ctxInfo.hasExtension("GL_OES_tessellation_shader")) { + hasTessellationSupport = true; + shaderCaps->fTessellationExtensionString = "GL_OES_tessellation_shader"; + } + if (hasTessellationSupport) { + GR_GL_GetIntegerv(gli, GR_GL_MAX_TESS_GEN_LEVEL_OES, + &shaderCaps->fMaxTessellationSegments); + // Just in case a driver returns a negative number? + shaderCaps->fMaxTessellationSegments = std::max(0, shaderCaps->fMaxTessellationSegments); } shaderCaps->fVersionDeclString = get_glsl_version_decl_string(standard, @@ -1029,13 +1038,6 @@ void GrGLCaps::initFSAASupport(const GrContextOptions& contextOptions, fMSFBOType = kNone_MSFBOType; } } - - // We disable MSAA for all Intel GPUs. Before Gen9, performance was very bad. Even with Gen9, - // we've seen driver crashes in the wild. We don't have data on Gen11 yet. - // chromium:527565, chromium:983926 - if (kIntel_GrGLVendor == ctxInfo.vendor()) { - fMSFBOType = kNone_MSFBOType; - } } void GrGLCaps::initBlendEqationSupport(const GrGLContextInfo& ctxInfo) { @@ -3640,6 +3642,10 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo, // Tegra3 fract() seems to trigger undefined behavior for negative values, so we // must avoid this condition. shaderCaps->fCanUseFractForNegativeValues = false; + + // Seeing crashes on Tegra3 with inlined functions that have early returns. Looks like the + // do { ... break; } while (false); construct is causing a crash in the driver. + shaderCaps->fCanUseDoLoops = false; } // On Intel GPU there is an issue where it reads the second argument to atan "- %s.x" as an int @@ -3849,14 +3855,14 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo, if (ctxInfo.version() >= GR_GL_VER(4,2)) { fRequiresManualFBBarrierAfterTessellatedStencilDraw = true; } else { - shaderCaps->fTessellationSupport = false; + shaderCaps->fMaxTessellationSegments = 0; } } else { // glMemoryBarrier wasn't around until es version 3.1. if (ctxInfo.version() >= GR_GL_VER(3,1)) { fRequiresManualFBBarrierAfterTessellatedStencilDraw = true; } else { - shaderCaps->fTessellationSupport = false; + shaderCaps->fMaxTessellationSegments = 0; } } } @@ -3864,7 +3870,7 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo, if (kQualcomm_GrGLDriver == ctxInfo.driver()) { // Qualcomm fails to link programs with tessellation and does not give an error message. // http://skbug.com/9740 - shaderCaps->fTessellationSupport = false; + shaderCaps->fMaxTessellationSegments = 0; } #ifdef SK_BUILD_FOR_WIN @@ -3937,8 +3943,10 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo, #ifdef SK_BUILD_FOR_MAC // On a MacBookPro 11.5 running MacOS 10.13 with a Radeon M370X the TransferPixelsFrom test // fails when transferring out from a GL_RG8 texture using GL_RG/GL_UNSIGNED_BYTE. + // The same error also occurs in MacOS 10.15 with a Radeon Pro 5300M. formatWorkarounds->fDisallowDirectRG8ReadPixels = ctxInfo.renderer() == kAMDRadeonR9M3xx_GrGLRenderer || + ctxInfo.renderer() == kAMDRadeonPro5xxx_GrGLRenderer || ctxInfo.renderer() == kAMDRadeonProVegaxx_GrGLRenderer; #endif @@ -3987,6 +3995,24 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo, if (ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D9) { formatWorkarounds->fDisallowBGRA8ReadPixels = true; } + + // We disable MSAA for all Intel GPUs. Before Gen9, performance was very bad. Even with Gen9, + // we've seen driver crashes in the wild. We don't have data on Gen11 yet. + // (crbug.com/527565, crbug.com/983926) + if (kIntel_GrGLVendor == ctxInfo.vendor()) { + fMSFBOType = kNone_MSFBOType; + } + + // ANGLE doesn't support do-while loops + if (kANGLE_GrGLDriver == ctxInfo.driver()) { + shaderCaps->fCanUseDoLoops = false; + } + + // ANGLE's D3D9 backend + AMD GPUs are flaky with program binary caching (skbug.com/10395) + if (ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D9 && + ctxInfo.angleVendor() == GrGLANGLEVendor::kAMD) { + fProgramBinarySupport = false; + } } void GrGLCaps::onApplyOptionsOverrides(const GrContextOptions& options) { @@ -4066,6 +4092,7 @@ size_t offset_alignment_for_transfer_buffer(GrGLenum externalType) { case GR_GL_UNSIGNED_INT: return sizeof(GrGLuint); case GR_GL_INT: return sizeof(GrGLint); case GR_GL_HALF_FLOAT: return sizeof(GrGLhalf); + case GR_GL_HALF_FLOAT_OES: return sizeof(GrGLhalf); case GR_GL_FLOAT: return sizeof(GrGLfloat); case GR_GL_UNSIGNED_SHORT_5_6_5: return sizeof(GrGLushort); case GR_GL_UNSIGNED_SHORT_4_4_4_4: return sizeof(GrGLushort); @@ -4094,7 +4121,7 @@ GrCaps::SupportedRead GrGLCaps::onSupportedReadPixelsColorType( GrColorType srcColorType, const GrBackendFormat& srcBackendFormat, GrColorType dstColorType) const { - SkImage::CompressionType compression = this->compressionType(srcBackendFormat); + SkImage::CompressionType compression = GrBackendFormatToCompressionType(srcBackendFormat); if (compression != SkImage::CompressionType::kNone) { return { SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x : GrColorType::kRGBA_8888, @@ -4174,25 +4201,10 @@ bool GrGLCaps::isFormatSRGB(const GrBackendFormat& format) const { return format.asGLFormat() == GrGLFormat::kSRGB8_ALPHA8; } -SkImage::CompressionType GrGLCaps::compressionType(const GrBackendFormat& format) const { - auto fmt = format.asGLFormat(); - - switch (fmt) { - case GrGLFormat::kCOMPRESSED_ETC1_RGB8: // same compression layout as ETC2_RGB8_UNORM - case GrGLFormat::kCOMPRESSED_RGB8_ETC2: - return SkImage::CompressionType::kETC2_RGB8_UNORM; - case GrGLFormat::kCOMPRESSED_RGB8_BC1: - return SkImage::CompressionType::kBC1_RGB8_UNORM; - case GrGLFormat::kCOMPRESSED_RGBA8_BC1: - return SkImage::CompressionType::kBC1_RGBA8_UNORM; - default: - return SkImage::CompressionType::kNone; - } - - SkUNREACHABLE; -} - bool GrGLCaps::isFormatTexturable(const GrBackendFormat& format) const { + if (format.textureType() == GrTextureType::kRectangle && !this->rectangleTextureSupport()) { + return false; + } return this->isFormatTexturable(format.asGLFormat()); } @@ -4203,6 +4215,12 @@ bool GrGLCaps::isFormatTexturable(GrGLFormat format) const { bool GrGLCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format, int sampleCount) const { + if (format.textureType() == GrTextureType::kRectangle && !this->rectangleTextureSupport()) { + return false; + } + if (format.textureType() == GrTextureType::kExternal) { + return false; + } auto f = format.asGLFormat(); const FormatInfo& info = this->getFormatInfo(f); if (!SkToBool(info.colorTypeFlags(ct) & ColorTypeInfo::kRenderable_Flag)) { @@ -4213,6 +4231,12 @@ bool GrGLCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendForm } bool GrGLCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount) const { + if (format.textureType() == GrTextureType::kRectangle && !this->rectangleTextureSupport()) { + return false; + } + if (format.textureType() == GrTextureType::kExternal) { + return false; + } return this->isFormatRenderable(format.asGLFormat(), sampleCount); } @@ -4324,13 +4348,6 @@ void GrGLCaps::didQueryImplementationReadSupport(GrGLFormat format, bool GrGLCaps::onAreColorTypeAndFormatCompatible(GrColorType ct, const GrBackendFormat& format) const { GrGLFormat glFormat = format.asGLFormat(); - - SkImage::CompressionType compression = GrGLFormatToCompressionType(glFormat); - if (compression != SkImage::CompressionType::kNone) { - return ct == (SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x - : GrColorType::kRGBA_8888); - } - const auto& info = this->getFormatInfo(glFormat); for (int i = 0; i < info.fColorTypeInfoCount; ++i) { if (info.fColorTypeInfos[i].fColorType == ct) { @@ -4379,8 +4396,9 @@ GrBackendFormat GrGLCaps::getBackendFormatFromCompressionType( SkUNREACHABLE; } -GrSwizzle GrGLCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const { - const auto& info = this->getFormatInfo(format.asGLFormat()); +GrSwizzle GrGLCaps::onGetReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const { + GrGLFormat glFormat = format.asGLFormat(); + const auto& info = this->getFormatInfo(glFormat); for (int i = 0; i < info.fColorTypeInfoCount; ++i) { const auto& ctInfo = info.fColorTypeInfos[i]; if (ctInfo.fColorType == colorType) { @@ -4388,7 +4406,7 @@ GrSwizzle GrGLCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType co } } SkDEBUGFAILF("Illegal color type (%d) and format (%d) combination.", colorType, - format.asGLFormat()); + glFormat); return {}; } @@ -4481,7 +4499,15 @@ std::vector<GrCaps::TestFormatColorTypeCombination> GrGLCaps::getTestingCombinat combos.push_back({ GrColorType::kBGRA_8888, GrBackendFormat::MakeGL(GR_GL_BGRA8, GR_GL_TEXTURE_2D) }); } - + if (this->rectangleTextureSupport()) { + size_t count2D = combos.size(); + for (size_t i = 0; i < count2D; ++i) { + auto combo2D = combos[i]; + GrGLenum formatEnum = GrGLFormatToEnum(combo2D.fFormat.asGLFormat()); + combos.push_back({combo2D.fColorType, + GrBackendFormat::MakeGL(formatEnum, GR_GL_TEXTURE_RECTANGLE)}); + } + } return combos; } #endif diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLCaps.h b/chromium/third_party/skia/src/gpu/gl/GrGLCaps.h index 1371b26c28b..8ee8e9b84b5 100644 --- a/chromium/third_party/skia/src/gpu/gl/GrGLCaps.h +++ b/chromium/third_party/skia/src/gpu/gl/GrGLCaps.h @@ -114,7 +114,6 @@ public: const GrGLInterface* glInterface); bool isFormatSRGB(const GrBackendFormat&) const override; - SkImage::CompressionType compressionType(const GrBackendFormat&) const override; bool isFormatTexturable(const GrBackendFormat&) const override; bool isFormatTexturable(GrGLFormat) const; @@ -441,7 +440,6 @@ public: GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override; - GrSwizzle getReadSwizzle(const GrBackendFormat&, GrColorType) const override; GrSwizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override; uint64_t computeFormatKey(const GrBackendFormat&) const override; @@ -502,6 +500,8 @@ private: SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&, GrColorType) const override; + GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override; + GrGLStandard fStandard = kNone_GrGLStandard; SkTArray<StencilFormat, true> fStencilFormats; diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLDefines.h b/chromium/third_party/skia/src/gpu/gl/GrGLDefines.h index a2ac31561c5..8fde6be2ebb 100644 --- a/chromium/third_party/skia/src/gpu/gl/GrGLDefines.h +++ b/chromium/third_party/skia/src/gpu/gl/GrGLDefines.h @@ -1140,4 +1140,7 @@ /** GL_NV_fence_sync */ #define GR_GL_ALL_COMPLETED 0x84F2 +/* Tessellation */ +#define GR_GL_MAX_TESS_GEN_LEVEL_OES 0x8E7E + #endif diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLGpu.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLGpu.cpp index f1d744d3307..24d4318d6ad 100644 --- a/chromium/third_party/skia/src/gpu/gl/GrGLGpu.cpp +++ b/chromium/third_party/skia/src/gpu/gl/GrGLGpu.cpp @@ -19,10 +19,10 @@ #include "src/core/SkConvertPixels.h" #include "src/core/SkMipMap.h" #include "src/core/SkTraceEvent.h" +#include "src/gpu/GrBackendUtils.h" #include "src/gpu/GrContextPriv.h" #include "src/gpu/GrCpuBuffer.h" #include "src/gpu/GrDataUtils.h" -#include "src/gpu/GrFixedClip.h" #include "src/gpu/GrGpuResourcePriv.h" #include "src/gpu/GrPipeline.h" #include "src/gpu/GrProgramInfo.h" @@ -50,9 +50,9 @@ GR_GL_CALL(this->glInterface(), call); \ return static_cast<GrGLenum>(GR_GL_NO_ERROR); \ } else { \ - GrGLClearErr(this->glInterface()); \ + this->clearErrorsAndCheckForOOM(); \ GR_GL_CALL_NOERRCHECK(this->glInterface(), call); \ - return GR_GL_GET_ERROR(this->glInterface()); \ + return this->getErrorAndCheckForOOM(); \ } \ }() @@ -333,7 +333,11 @@ GrGLGpu::GrGLGpu(std::unique_ptr<GrGLContext> ctx, GrContext* context) , fStencilClearFBOID(0) , fFinishCallbacks(this) { SkASSERT(fGLContext); - GrGLClearErr(this->glInterface()); + // Clear errors so we don't get confused whether we caused an error. + this->clearErrorsAndCheckForOOM(); + // Toss out any pre-existing OOM that was hanging around before we got started. + this->checkAndResetOOMed(); + fCaps = sk_ref_sp(fGLContext->caps()); fHWTextureUnitBindings.reset(this->numTextureUnits()); @@ -837,9 +841,10 @@ bool GrGLGpu::onWritePixels(GrSurface* surface, int left, int top, int width, in this->bindTextureToScratchUnit(glTex->target(), glTex->textureID()); SkASSERT(!GrGLFormatIsCompressed(glTex->format())); - return this->uploadTexData(glTex->format(), surfaceColorType, glTex->width(), glTex->height(), - glTex->target(), left, top, width, height, srcColorType, texels, - mipLevelCount); + SkIRect dstRect = SkIRect::MakeXYWH(left, top, width, height); + return this->uploadColorTypeTexData(glTex->format(), surfaceColorType, glTex->dimensions(), + glTex->target(), dstRect, srcColorType, texels, + mipLevelCount); } bool GrGLGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int width, int height, @@ -931,33 +936,21 @@ void GrGLGpu::unbindCpuToGpuXferBuffer() { } } -bool GrGLGpu::uploadTexData(GrGLFormat textureFormat, GrColorType textureColorType, int texWidth, - int texHeight, GrGLenum target, int left, int top, int width, - int height, GrColorType srcColorType, const GrMipLevel texels[], - int mipLevelCount, GrMipMapsStatus* mipMapsStatus) { +bool GrGLGpu::uploadColorTypeTexData(GrGLFormat textureFormat, + GrColorType textureColorType, + SkISize texDims, + GrGLenum target, + SkIRect dstRect, + GrColorType srcColorType, + const GrMipLevel texels[], + int mipLevelCount) { // If we're uploading compressed data then we should be using uploadCompressedTexData SkASSERT(!GrGLFormatIsCompressed(textureFormat)); SkASSERT(this->glCaps().isFormatTexturable(textureFormat)); - SkDEBUGCODE( - SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height); - SkIRect bounds = SkIRect::MakeWH(texWidth, texHeight); - SkASSERT(bounds.contains(subRect)); - ) - SkASSERT(1 == mipLevelCount || - (0 == left && 0 == top && width == texWidth && height == texHeight)); - - this->unbindCpuToGpuXferBuffer(); - - const GrGLInterface* interface = this->glInterface(); - const GrGLCaps& caps = this->glCaps(); size_t bpp = GrColorTypeBytesPerPixel(srcColorType); - if (width == 0 || height == 0) { - return false; - } - // External format and type come from the upload data. GrGLenum externalFormat; GrGLenum externalType; @@ -966,52 +959,100 @@ bool GrGLGpu::uploadTexData(GrGLFormat textureFormat, GrColorType textureColorTy if (!externalFormat || !externalType) { return false; } + this->uploadTexData(texDims, target, dstRect, externalFormat, externalType, bpp, texels, + mipLevelCount); + return true; +} - /* - * Check whether to allocate a temporary buffer for flipping y or - * because our srcData has extra bytes past each row. If so, we need - * to trim those off here, since GL ES may not let us specify - * GL_UNPACK_ROW_LENGTH. - */ - bool restoreGLRowLength = false; +bool GrGLGpu::uploadColorToTex(GrGLFormat textureFormat, + SkISize texDims, + GrGLenum target, + SkColor4f color, + uint32_t levelMask) { + GrColorType colorType; + GrGLenum externalFormat, externalType; + this->glCaps().getTexSubImageDefaultFormatTypeAndColorType(textureFormat, &externalFormat, + &externalType, &colorType); + if (colorType == GrColorType::kUnknown) { + return false; + } - if (mipMapsStatus) { - *mipMapsStatus = (mipLevelCount > 1) ? - GrMipMapsStatus::kValid : GrMipMapsStatus::kNotAllocated; + std::unique_ptr<char[]> pixelStorage; + size_t bpp = 0; + int numLevels = SkMipMap::ComputeLevelCount(texDims) + 1; + SkSTArray<16, GrMipLevel> levels; + levels.resize(numLevels); + SkISize levelDims = texDims; + for (int i = 0; i < numLevels; ++i, levelDims = {std::max(levelDims.width() >> 1, 1), + std::max(levelDims.height() >> 1, 1)}) { + if (levelMask & (1 << i)) { + if (!pixelStorage) { + // Make one tight image at the first size and reuse it for smaller levels. + GrImageInfo ii(colorType, kUnpremul_SkAlphaType, nullptr, levelDims); + size_t rb = ii.minRowBytes(); + pixelStorage.reset(new char[rb * levelDims.height()]); + if (!GrClearImage(ii, pixelStorage.get(), ii.minRowBytes(), color)) { + return false; + } + bpp = ii.bpp(); + } + levels[i] = {pixelStorage.get(), levelDims.width()*bpp}; + } } + this->uploadTexData(texDims, target, SkIRect::MakeSize(texDims), externalFormat, externalType, + bpp, levels.begin(), levels.count()); + return true; +} - GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1)); +void GrGLGpu::uploadTexData(SkISize texDims, + GrGLenum target, + SkIRect dstRect, + GrGLenum externalFormat, + GrGLenum externalType, + size_t bpp, + const GrMipLevel texels[], + int mipLevelCount) { + SkASSERT(!texDims.isEmpty()); + SkASSERT(!dstRect.isEmpty()); + SkASSERT(SkIRect::MakeSize(texDims).contains(dstRect)); + SkASSERT(mipLevelCount > 0 && mipLevelCount <= SkMipMap::ComputeLevelCount(texDims) + 1); + SkASSERT(mipLevelCount == 1 || dstRect == SkIRect::MakeSize(texDims)); - for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) { - if (!texels[currentMipLevel].fPixels) { - if (mipMapsStatus) { - *mipMapsStatus = GrMipMapsStatus::kDirty; - } + const GrGLCaps& caps = this->glCaps(); + + bool restoreGLRowLength = false; + + this->unbindCpuToGpuXferBuffer(); + GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1)); + + SkISize dims = dstRect.size(); + for (int level = 0; level < mipLevelCount; ++level, dims = {std::max(dims.width() >> 1, 1), + std::max(dims.height() >> 1, 1)}) { + if (!texels[level].fPixels) { continue; } - int twoToTheMipLevel = 1 << currentMipLevel; - const int currentWidth = std::max(1, width / twoToTheMipLevel); - const int currentHeight = std::max(1, height / twoToTheMipLevel); - const size_t trimRowBytes = currentWidth * bpp; - const size_t rowBytes = texels[currentMipLevel].fRowBytes; + const size_t trimRowBytes = dims.width() * bpp; + const size_t rowBytes = texels[level].fRowBytes; if (caps.writePixelsRowBytesSupport() && (rowBytes != trimRowBytes || restoreGLRowLength)) { GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp); - GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength)); + GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength)); restoreGLRowLength = true; + } else { + SkASSERT(rowBytes == trimRowBytes); } - GL_CALL(TexSubImage2D(target, currentMipLevel, left, top, currentWidth, currentHeight, - externalFormat, externalType, texels[currentMipLevel].fPixels)); + GL_CALL(TexSubImage2D(target, level, dstRect.x(), dstRect.y(), dims.width(), dims.height(), + externalFormat, externalType, texels[level].fPixels)); } if (restoreGLRowLength) { SkASSERT(caps.writePixelsRowBytesSupport()); GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); } - return true; } -bool GrGLGpu::uploadCompressedTexData(GrGLFormat format, +bool GrGLGpu::uploadCompressedTexData(SkImage::CompressionType compressionType, + GrGLFormat format, SkISize dimensions, GrMipMapped mipMapped, GrGLenum target, @@ -1025,7 +1066,6 @@ bool GrGLGpu::uploadCompressedTexData(GrGLFormat format, return false; } - SkImage::CompressionType compressionType = GrGLFormatToCompressionType(format); SkASSERT(compressionType != SkImage::CompressionType::kNone); bool useTexStorage = caps.formatSupportsTexStorage(format); @@ -1250,14 +1290,27 @@ sk_sp<GrTexture> GrGLGpu::onCreateTexture(SkISize dimensions, GrGLTextureParameters::SamplerOverriddenState initialState; GrGLTexture::Desc texDesc; texDesc.fSize = dimensions; - texDesc.fTarget = GR_GL_TEXTURE_2D; + switch (format.textureType()) { + case GrTextureType::kExternal: + case GrTextureType::kNone: + return nullptr; + case GrTextureType::k2D: + texDesc.fTarget = GR_GL_TEXTURE_2D; + break; + case GrTextureType::kRectangle: + if (mipLevelCount > 1 || !this->glCaps().rectangleTextureSupport()) { + return nullptr; + } + texDesc.fTarget = GR_GL_TEXTURE_RECTANGLE; + break; + } texDesc.fFormat = format.asGLFormat(); texDesc.fOwnership = GrBackendObjectOwnership::kOwned; SkASSERT(texDesc.fFormat != GrGLFormat::kUnknown); SkASSERT(!GrGLFormatIsCompressed(texDesc.fFormat)); - texDesc.fID = this->createTexture2D(dimensions, texDesc.fFormat, renderable, &initialState, - mipLevelCount); + texDesc.fID = this->createTexture(dimensions, texDesc.fFormat, texDesc.fTarget, renderable, + &initialState, mipLevelCount); if (!texDesc.fID) { return return_null_texture(); @@ -1283,11 +1336,11 @@ sk_sp<GrTexture> GrGLGpu::onCreateTexture(SkISize dimensions, tex->parameters()->set(&initialState, GrGLTextureParameters::NonsamplerState(), fResetTimestampForTextureParameters); if (levelClearMask) { - GrGLenum externalFormat, externalType; - GrColorType colorType; - this->glCaps().getTexSubImageDefaultFormatTypeAndColorType(texDesc.fFormat, &externalFormat, - &externalType, &colorType); if (this->glCaps().clearTextureSupport()) { + GrGLenum externalFormat, externalType; + GrColorType colorType; + this->glCaps().getTexSubImageDefaultFormatTypeAndColorType( + texDesc.fFormat, &externalFormat, &externalType, &colorType); for (int i = 0; i < mipLevelCount; ++i) { if (levelClearMask & (1U << i)) { GL_CALL(ClearTexImage(tex->textureID(), i, externalFormat, externalType, @@ -1310,24 +1363,10 @@ sk_sp<GrTexture> GrGLGpu::onCreateTexture(SkISize dimensions, } fHWBoundRenderTargetUniqueID.makeInvalid(); } else { - std::unique_ptr<char[]> zeros; - GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1)); - for (int i = 0; i < mipLevelCount; ++i) { - if (levelClearMask & (1U << i)) { - int levelWidth = std::max(1, texDesc.fSize.width() >> i); - int levelHeight = std::max(1, texDesc.fSize.height() >> i); - // Levels only get smaller as we proceed. Once we create a zeros use it for all - // smaller levels that need clearing. - if (!zeros) { - size_t bpp = GrColorTypeBytesPerPixel(colorType); - size_t size = levelWidth * levelHeight * bpp; - zeros.reset(new char[size]()); - } - this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, tex->textureID()); - GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, i, 0, 0, levelWidth, levelHeight, - externalFormat, externalType, zeros.get())); - } - } + this->bindTextureToScratchUnit(texDesc.fTarget, tex->textureID()); + static constexpr SkColor4f kZeroColor = {0, 0, 0, 0}; + this->uploadColorToTex(texDesc.fFormat, texDesc.fSize, texDesc.fTarget, kZeroColor, + levelClearMask); } } return std::move(tex); @@ -1343,13 +1382,15 @@ sk_sp<GrTexture> GrGLGpu::onCreateCompressedTexture(SkISize dimensions, if (isProtected == GrProtected::kYes) { return nullptr; } + SkImage::CompressionType compression = GrBackendFormatToCompressionType(format); + GrGLTextureParameters::SamplerOverriddenState initialState; GrGLTexture::Desc desc; desc.fSize = dimensions; desc.fTarget = GR_GL_TEXTURE_2D; desc.fOwnership = GrBackendObjectOwnership::kOwned; desc.fFormat = format.asGLFormat(); - desc.fID = this->createCompressedTexture2D(desc.fSize, desc.fFormat, + desc.fID = this->createCompressedTexture2D(desc.fSize, compression, desc.fFormat, mipMapped, &initialState, data, dataSize); if (!desc.fID) { @@ -1386,16 +1427,16 @@ GrBackendTexture GrGLGpu::onCreateCompressedBackendTexture( return {}; } + SkImage::CompressionType compression = GrBackendFormatToCompressionType(format); + const char* rawData = nullptr; size_t rawDataSize = 0; SkAutoMalloc am; - SkASSERT(!data || data->type() != BackendTextureData::Type::kPixmaps); if (data && data->type() == BackendTextureData::Type::kCompressed) { rawData = (const char*) data->compressedData(); rawDataSize = data->compressedSize(); } else if (data && data->type() == BackendTextureData::Type::kColor) { - SkImage::CompressionType compression = GrGLFormatToCompressionType(glFormat); SkASSERT(compression != SkImage::CompressionType::kNone); rawDataSize = SkCompressedDataSize(compression, dimensions, nullptr, @@ -1413,7 +1454,7 @@ GrBackendTexture GrGLGpu::onCreateCompressedBackendTexture( info.fTarget = GR_GL_TEXTURE_2D; info.fFormat = GrGLFormatToEnum(glFormat); - info.fID = this->createCompressedTexture2D(dimensions, glFormat, + info.fID = this->createCompressedTexture2D(dimensions, compression, glFormat, mipMapped, &initialState, rawData, rawDataSize); if (!info.fID) { @@ -1466,8 +1507,8 @@ int GrGLGpu::getCompatibleStencilIndex(GrGLFormat format) { // Default to unsupported, set this if we find a stencil format that works. int firstWorkingStencilFormatIndex = -1; - GrGLuint colorID = - this->createTexture2D({kSize, kSize}, format, GrRenderable::kYes, nullptr, 1); + GrGLuint colorID = this->createTexture({kSize, kSize}, format, GR_GL_TEXTURE_2D, + GrRenderable::kYes, nullptr, 1); if (!colorID) { return -1; } @@ -1536,6 +1577,7 @@ int GrGLGpu::getCompatibleStencilIndex(GrGLFormat format) { GrGLuint GrGLGpu::createCompressedTexture2D( SkISize dimensions, + SkImage::CompressionType compression, GrGLFormat format, GrMipMapped mipMapped, GrGLTextureParameters::SamplerOverriddenState* initialState, @@ -1554,7 +1596,7 @@ GrGLuint GrGLGpu::createCompressedTexture2D( *initialState = set_initial_texture_params(this->glInterface(), GR_GL_TEXTURE_2D); if (data) { - if (!this->uploadCompressedTexData(format, dimensions, mipMapped, + if (!this->uploadCompressedTexData(compression, format, dimensions, mipMapped, GR_GL_TEXTURE_2D, data, dataSize)) { GL_CALL(DeleteTextures(1, &id)); return 0; @@ -1564,11 +1606,12 @@ GrGLuint GrGLGpu::createCompressedTexture2D( return id; } -GrGLuint GrGLGpu::createTexture2D(SkISize dimensions, - GrGLFormat format, - GrRenderable renderable, - GrGLTextureParameters::SamplerOverriddenState* initialState, - int mipLevelCount) { +GrGLuint GrGLGpu::createTexture(SkISize dimensions, + GrGLFormat format, + GrGLenum target, + GrRenderable renderable, + GrGLTextureParameters::SamplerOverriddenState* initialState, + int mipLevelCount) { SkASSERT(format != GrGLFormat::kUnknown); SkASSERT(!GrGLFormatIsCompressed(format)); @@ -1579,17 +1622,17 @@ GrGLuint GrGLGpu::createTexture2D(SkISize dimensions, return 0; } - this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, id); + this->bindTextureToScratchUnit(target, id); if (GrRenderable::kYes == renderable && this->glCaps().textureUsageSupport()) { // provides a hint about how this texture will be used - GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_USAGE, GR_GL_FRAMEBUFFER_ATTACHMENT)); + GL_CALL(TexParameteri(target, GR_GL_TEXTURE_USAGE, GR_GL_FRAMEBUFFER_ATTACHMENT)); } if (initialState) { - *initialState = set_initial_texture_params(this->glInterface(), GR_GL_TEXTURE_2D); + *initialState = set_initial_texture_params(this->glInterface(), target); } else { - set_initial_texture_params(this->glInterface(), GR_GL_TEXTURE_2D); + set_initial_texture_params(this->glInterface(), target); } GrGLenum internalFormat = this->glCaps().getTexImageOrStorageInternalFormat(format); @@ -1598,9 +1641,8 @@ GrGLuint GrGLGpu::createTexture2D(SkISize dimensions, if (internalFormat) { if (this->glCaps().formatSupportsTexStorage(format)) { auto levelCount = std::max(mipLevelCount, 1); - GrGLenum error = - GL_ALLOC_CALL(TexStorage2D(GR_GL_TEXTURE_2D, levelCount, internalFormat, - dimensions.width(), dimensions.height())); + GrGLenum error = GL_ALLOC_CALL(TexStorage2D(target, levelCount, internalFormat, + dimensions.width(), dimensions.height())); success = (error == GR_GL_NO_ERROR); } else { GrGLenum externalFormat, externalType; @@ -1611,9 +1653,9 @@ GrGLuint GrGLGpu::createTexture2D(SkISize dimensions, const int twoToTheMipLevel = 1 << level; const int currentWidth = std::max(1, dimensions.width() / twoToTheMipLevel); const int currentHeight = std::max(1, dimensions.height() / twoToTheMipLevel); - error = GL_ALLOC_CALL(TexImage2D(GR_GL_TEXTURE_2D, level, internalFormat, - currentWidth, currentHeight, 0, externalFormat, - externalType, nullptr)); + error = GL_ALLOC_CALL(TexImage2D(target, level, internalFormat, currentWidth, + currentHeight, 0, externalFormat, externalType, + nullptr)); } success = (error == GR_GL_NO_ERROR); } @@ -1748,8 +1790,7 @@ void GrGLGpu::disableWindowRectangles() { #endif } -bool GrGLGpu::flushGLState(GrRenderTarget* renderTarget, - const GrProgramInfo& programInfo) { +bool GrGLGpu::flushGLState(GrRenderTarget* renderTarget, const GrProgramInfo& programInfo) { this->handleDirtyContext(); sk_sp<GrGLProgram> program = fProgramCache->findOrCreateProgram(renderTarget, programInfo); @@ -1847,51 +1888,29 @@ GrGLenum GrGLGpu::bindBuffer(GrGpuBufferType type, const GrBuffer* buffer) { return bufferState->fGLTarget; } -void GrGLGpu::clear(const GrFixedClip& clip, const SkPMColor4f& color, +void GrGLGpu::clear(const GrScissorState& scissor, const SkPMColor4f& color, GrRenderTarget* target, GrSurfaceOrigin origin) { // parent class should never let us get here with no RT SkASSERT(target); SkASSERT(!this->caps()->performColorClearsAsDraws()); - SkASSERT(!clip.scissorEnabled() || !this->caps()->performPartialClearsAsDraws()); + SkASSERT(!scissor.enabled() || !this->caps()->performPartialClearsAsDraws()); this->handleDirtyContext(); GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target); - if (clip.scissorEnabled()) { - this->flushRenderTarget(glRT, origin, clip.scissorRect()); + if (scissor.enabled()) { + this->flushRenderTarget(glRT, origin, scissor.rect()); } else { this->flushRenderTarget(glRT); } - this->flushScissor(clip.scissorState(), glRT->width(), glRT->height(), origin); - this->flushWindowRectangles(clip.windowRectsState(), glRT, origin); + this->flushScissor(scissor, glRT->width(), glRT->height(), origin); + this->disableWindowRectangles(); this->flushColorWrite(true); this->flushClearColor(color); GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT)); } -void GrGLGpu::clearStencil(GrRenderTarget* target, int clearValue) { - SkASSERT(!this->caps()->performStencilClearsAsDraws()); - - if (!target) { - return; - } - - // This should only be called internally when we know we have a stencil buffer. - SkASSERT(target->renderTargetPriv().getStencilAttachment()); - - GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target); - this->flushRenderTargetNoColorWrites(glRT); - - this->flushScissorTest(GrScissorTest::kDisabled); - this->disableWindowRectangles(); - - GL_CALL(StencilMask(0xffffffff)); - GL_CALL(ClearStencil(clearValue)); - GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT)); - fHWStencilSettings.invalidate(); -} - static bool use_tiled_rendering(const GrGLCaps& glCaps, const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilLoadStore) { // Only use the tiled rendering extension if we can explicitly clear and discard the stencil. @@ -1989,11 +2008,11 @@ void GrGLGpu::endCommandBuffer(GrRenderTarget* rt, SkDEBUGCODE(fIsExecutingCommandBuffer_DebugOnly = false); } -void GrGLGpu::clearStencilClip(const GrFixedClip& clip, - bool insideStencilMask, +void GrGLGpu::clearStencilClip(const GrScissorState& scissor, bool insideStencilMask, GrRenderTarget* target, GrSurfaceOrigin origin) { SkASSERT(target); SkASSERT(!this->caps()->performStencilClearsAsDraws()); + SkASSERT(!scissor.enabled() || !this->caps()->performPartialClearsAsDraws()); this->handleDirtyContext(); GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment(); @@ -2024,8 +2043,8 @@ void GrGLGpu::clearStencilClip(const GrFixedClip& clip, GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target); this->flushRenderTargetNoColorWrites(glRT); - this->flushScissor(clip.scissorState(), glRT->width(), glRT->height(), origin); - this->flushWindowRectangles(clip.windowRectsState(), glRT, origin); + this->flushScissor(scissor, glRT->width(), glRT->height(), origin); + this->disableWindowRectangles(); GL_CALL(StencilMask((uint32_t) clipStencilMask)); GL_CALL(ClearStencil(value)); @@ -2136,7 +2155,8 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int } GrOpsRenderPass* GrGLGpu::getOpsRenderPass( - GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds, + GrRenderTarget* rt, GrStencilAttachment*, + GrSurfaceOrigin origin, const SkIRect& bounds, const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) { @@ -2258,11 +2278,11 @@ void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resol fHWBoundRenderTargetUniqueID.makeInvalid(); if (GrGLCaps::kES_Apple_MSFBOType == this->glCaps().msFBOType()) { // Apple's extension uses the scissor as the blit bounds. - GrScissorState scissorState; - scissorState.set(resolveRect); // Passing in kTopLeft_GrSurfaceOrigin will make sure no transformation of the rect // happens inside flushScissor since resolveRect is already in native device coordinates. - this->flushScissor(scissorState, rt->width(), rt->height(), kTopLeft_GrSurfaceOrigin); + GrScissorState scissor(rt->dimensions()); + SkAssertResult(scissor.set(resolveRect)); + this->flushScissor(scissor, rt->width(), rt->height(), kTopLeft_GrSurfaceOrigin); this->disableWindowRectangles(); GL_CALL(ResolveMultisampleFramebuffer()); } else { @@ -3547,16 +3567,29 @@ GrBackendTexture GrGLGpu::onCreateBackendTexture(SkISize dimensions, if (glFormat == GrGLFormat::kUnknown) { return {}; } - - info.fTarget = GR_GL_TEXTURE_2D; + switch (format.textureType()) { + case GrTextureType::kNone: + case GrTextureType::kExternal: + return {}; + case GrTextureType::k2D: + info.fTarget = GR_GL_TEXTURE_2D; + break; + case GrTextureType::kRectangle: + if (!this->glCaps().rectangleTextureSupport() || mipMapped == GrMipMapped::kYes) { + return {}; + } + info.fTarget = GR_GL_TEXTURE_RECTANGLE; + break; + } info.fFormat = GrGLFormatToEnum(glFormat); - info.fID = this->createTexture2D(dimensions, glFormat, renderable, &initialState, numMipLevels); + info.fID = this->createTexture(dimensions, glFormat, info.fTarget, renderable, &initialState, + numMipLevels); if (!info.fID) { return {}; } // Unbind this texture from the scratch texture unit. - this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, 0); + this->bindTextureToScratchUnit(info.fTarget, 0); auto parameters = sk_make_sp<GrGLTextureParameters>(); // The non-sampler params are still at their default values. @@ -3581,25 +3614,26 @@ bool GrGLGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture, GrGLFormat glFormat = GrGLFormatFromGLEnum(info.fFormat); - this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, info.fID); + this->bindTextureToScratchUnit(info.fTarget, info.fID); - // If we have mips make sure the base level is set to 0 and the max level set to numMipLevesl-1 + // If we have mips make sure the base level is set to 0 and the max level set to numMipLevels-1 // so that the uploads go to the right levels. - if (numMipLevels) { + if (numMipLevels && this->glCaps().mipMapLevelAndLodControlSupport()) { auto params = backendTexture.getGLTextureParams(); GrGLTextureParameters::NonsamplerState nonsamplerState = params->nonsamplerState(); if (params->nonsamplerState().fBaseMipMapLevel != 0) { - GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_BASE_LEVEL, 0)); + GL_CALL(TexParameteri(info.fTarget, GR_GL_TEXTURE_BASE_LEVEL, 0)); nonsamplerState.fBaseMipMapLevel = 0; } if (params->nonsamplerState().fMaxMipMapLevel != (numMipLevels - 1)) { - GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAX_LEVEL, numMipLevels - 1)); + GL_CALL(TexParameteri(info.fTarget, GR_GL_TEXTURE_MAX_LEVEL, numMipLevels - 1)); nonsamplerState.fBaseMipMapLevel = numMipLevels - 1; } params->set(nullptr, nonsamplerState, fResetTimestampForTextureParameters); } SkASSERT(data->type() != BackendTextureData::Type::kCompressed); + bool result = false; if (data->type() == BackendTextureData::Type::kPixmaps) { SkTDArray<GrMipLevel> texels; GrColorType colorType = SkColorTypeToGrColorType(data->pixmap(0).colorType()); @@ -3607,47 +3641,19 @@ bool GrGLGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture, for (int i = 0; i < numMipLevels; ++i) { texels[i] = {data->pixmap(i).addr(), data->pixmap(i).rowBytes()}; } - if (!this->uploadTexData(glFormat, colorType, backendTexture.width(), - backendTexture.height(), GR_GL_TEXTURE_2D, 0, 0, - backendTexture.width(), backendTexture.height(), - colorType, texels.begin(), texels.count())) { - GL_CALL(DeleteTextures(1, &info.fID)); - return false; - } - } else if (data && data->type() == BackendTextureData::Type::kColor) { - // TODO: Unify this with the clear texture code in onCreateTexture(). - GrColorType colorType; - GrGLenum externalFormat, externalType; - this->glCaps().getTexSubImageDefaultFormatTypeAndColorType(glFormat, &externalFormat, - &externalType, &colorType); - if (colorType == GrColorType::kUnknown) { - GL_CALL(DeleteTextures(1, &info.fID)); - return false; - } - - // Make one tight image at the base size and reuse it for smaller levels. - GrImageInfo ii(colorType, kUnpremul_SkAlphaType, nullptr, backendTexture.dimensions()); - auto rb = ii.minRowBytes(); - std::unique_ptr<char[]> pixelStorage(new char[rb * backendTexture.height()]); - if (!GrClearImage(ii, pixelStorage.get(), rb, data->color())) { - GL_CALL(DeleteTextures(1, &info.fID)); - return false; - } - - GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1)); - SkISize levelDimensions = backendTexture.dimensions(); - for (int i = 0; i < numMipLevels; ++i) { - GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, i, 0, 0, levelDimensions.width(), - levelDimensions.height(), externalFormat, externalType, - pixelStorage.get())); - levelDimensions = {std::max(1, levelDimensions.width() / 2), - std::max(1, levelDimensions.height() / 2)}; - } + SkIRect dstRect = SkIRect::MakeSize(backendTexture.dimensions()); + result = this->uploadColorTypeTexData(glFormat, colorType, backendTexture.dimensions(), + info.fTarget, dstRect, colorType, texels.begin(), + texels.count()); + } else if (data->type() == BackendTextureData::Type::kColor) { + uint32_t levelMask = (1 << numMipLevels) - 1; + result = this->uploadColorToTex(glFormat, backendTexture.dimensions(), info.fTarget, + data->color(), levelMask); } // Unbind this texture from the scratch texture unit. - this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, 0); - return true; + this->bindTextureToScratchUnit(info.fTarget, 0); + return result; } void GrGLGpu::deleteBackendTexture(const GrBackendTexture& tex) { @@ -3743,7 +3749,8 @@ GrBackendRenderTarget GrGLGpu::createTestingOnlyBackendRenderTarget(int w, int h this->bindFramebuffer(GR_GL_FRAMEBUFFER, info.fFBOID); if (useTexture) { GrGLTextureParameters::SamplerOverriddenState initialState; - colorID = this->createTexture2D({w, h}, format, GrRenderable::kYes, &initialState, 1); + colorID = this->createTexture({w, h}, format, GR_GL_TEXTURE_2D, GrRenderable::kYes, + &initialState, 1); if (!colorID) { deleteIDs(); return {}; @@ -3859,6 +3866,9 @@ bool GrGLGpu::onSubmitToGpu(bool syncCpu) { // See if any previously inserted finish procs are good to go. fFinishCallbacks.check(); } + if (!this->glCaps().skipErrorChecks()) { + this->clearErrorsAndCheckForOOM(); + } return true; } @@ -3938,6 +3948,7 @@ std::unique_ptr<GrSemaphore> GrGLGpu::wrapBackendSemaphore( } void GrGLGpu::insertSemaphore(GrSemaphore* semaphore) { + SkASSERT(semaphore); GrGLSemaphore* glSem = static_cast<GrGLSemaphore*>(semaphore); GrGLsync sync; @@ -3947,6 +3958,7 @@ void GrGLGpu::insertSemaphore(GrSemaphore* semaphore) { } void GrGLGpu::waitSemaphore(GrSemaphore* semaphore) { + SkASSERT(semaphore); GrGLSemaphore* glSem = static_cast<GrGLSemaphore*>(semaphore); GL_CALL(WaitSync(glSem->sync(), 0, GR_GL_TIMEOUT_IGNORED)); @@ -3956,6 +3968,23 @@ void GrGLGpu::checkFinishProcs() { fFinishCallbacks.check(); } +void GrGLGpu::clearErrorsAndCheckForOOM() { + while (this->getErrorAndCheckForOOM() != GR_GL_NO_ERROR) {} +} + +GrGLenum GrGLGpu::getErrorAndCheckForOOM() { +#if GR_GL_CHECK_ERROR + if (this->glInterface()->checkAndResetOOMed()) { + this->setOOMed(); + } +#endif + GrGLenum error = this->fGLContext->glInterface()->fFunctions.fGetError(); + if (error == GR_GL_OUT_OF_MEMORY) { + this->setOOMed(); + } + return error; +} + void GrGLGpu::deleteSync(GrGLsync sync) const { if (this->glCaps().fenceType() == GrGLCaps::FenceType::kNVFence) { GrGLuint nvFence = SkToUInt(reinterpret_cast<intptr_t>(sync)); diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLGpu.h b/chromium/third_party/skia/src/gpu/gl/GrGLGpu.h index a716cf8a03c..0a40333c531 100644 --- a/chromium/third_party/skia/src/gpu/gl/GrGLGpu.h +++ b/chromium/third_party/skia/src/gpu/gl/GrGLGpu.h @@ -104,18 +104,14 @@ public: // The GrGLOpsRenderPass does not buffer up draws before submitting them to the gpu. // Thus this is the implementation of the clear call for the corresponding passthrough function // on GrGLOpsRenderPass. - void clear(const GrFixedClip&, const SkPMColor4f&, GrRenderTarget*, GrSurfaceOrigin); + void clear(const GrScissorState&, const SkPMColor4f&, GrRenderTarget*, GrSurfaceOrigin); // The GrGLOpsRenderPass does not buffer up draws before submitting them to the gpu. // Thus this is the implementation of the clearStencil call for the corresponding passthrough // function on GrGLOpsrenderPass. - void clearStencilClip(const GrFixedClip&, bool insideStencilMask, + void clearStencilClip(const GrScissorState&, bool insideStencilMask, GrRenderTarget*, GrSurfaceOrigin); - // FIXME (michaelludwig): Can this go away and just use clearStencilClip() + marking the - // stencil buffer as not dirty? - void clearStencil(GrRenderTarget*, int clearValue); - void beginCommandBuffer(GrRenderTarget*, const SkIRect& bounds, GrSurfaceOrigin, const GrOpsRenderPass::LoadAndStoreInfo& colorLoadStore, const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilLoadStore); @@ -124,7 +120,8 @@ public: const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilLoadStore); GrOpsRenderPass* getOpsRenderPass( - GrRenderTarget*, GrSurfaceOrigin, const SkIRect&, + GrRenderTarget*, GrStencilAttachment*, + GrSurfaceOrigin, const SkIRect&, const GrOpsRenderPass::LoadAndStoreInfo&, const GrOpsRenderPass::StencilLoadAndStoreInfo&, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override; @@ -172,6 +169,11 @@ public: void checkFinishProcs() override; + // Calls glGetError() until no errors are reported. Also looks for OOMs. + void clearErrorsAndCheckForOOM(); + // Calls glGetError() once and returns the result. Also looks for an OOM. + GrGLenum getErrorAndCheckForOOM(); + std::unique_ptr<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override; void deleteSync(GrGLsync) const; @@ -181,6 +183,11 @@ public: void insertManualFramebufferBarrier() override; + void flushProgram(sk_sp<GrGLProgram>); + + // Version for programs that aren't GrGLProgram. + void flushProgram(GrGLuint); + private: GrGLGpu(std::unique_ptr<GrGLContext>, GrContext*); @@ -253,13 +260,15 @@ private: // returned. On failure, zero is returned. // The texture is populated with |texels|, if it is non-null. // The texture parameters are cached in |initialTexParams|. - GrGLuint createTexture2D(SkISize dimensions, - GrGLFormat, - GrRenderable, - GrGLTextureParameters::SamplerOverriddenState*, - int mipLevelCount); + GrGLuint createTexture(SkISize dimensions, + GrGLFormat, + GrGLenum target, + GrRenderable, + GrGLTextureParameters::SamplerOverriddenState*, + int mipLevelCount); GrGLuint createCompressedTexture2D(SkISize dimensions, + SkImage::CompressionType compression, GrGLFormat, GrMipMapped, GrGLTextureParameters::SamplerOverriddenState*, @@ -299,11 +308,6 @@ private: // binds texture unit in GL void setTextureUnit(int unitIdx); - void flushProgram(sk_sp<GrGLProgram>); - - // Version for programs that aren't GrGLProgram. - void flushProgram(GrGLuint); - void flushBlendAndColorWrite(const GrXferProcessor::BlendInfo& blendInfo, const GrSwizzle&); void addFinishedProc(GrGpuFinishedProc finishedProc, @@ -411,14 +415,45 @@ private: void flushFramebufferSRGB(bool enable); - bool uploadTexData(GrGLFormat textureFormat, GrColorType textureColorType, int texWidth, - int texHeight, GrGLenum target, int left, int top, int width, int height, - GrColorType srcColorType, const GrMipLevel texels[], int mipLevelCount, - GrMipMapsStatus* mipMapsStatus = nullptr); + // Uploads src data of a color type to the currently bound texture on the active texture unit. + // The caller specifies color type that the texture is being used with, which may be different + // than the src color type. This fails if the combination of texture format, texture color type, + // and src data color type are not valid. No conversion is performed on the data before passing + // it to GL. 'dstRect' must be the texture bounds if mipLevelCount is greater than 1. + bool uploadColorTypeTexData(GrGLFormat textureFormat, + GrColorType textureColorType, + SkISize texDims, + GrGLenum target, + SkIRect dstRect, + GrColorType srcColorType, + const GrMipLevel texels[], + int mipLevelCount); + + // Uploads a constant color to a texture using the "default" format and color type. Overwrites + // entire levels. Bit n in 'levelMask' indicates whether level n should be written. This + // function doesn't know if MIP levels have been allocated, thus levelMask should not have bits + // beyond the low bit set if the texture is not MIP mapped. + bool uploadColorToTex(GrGLFormat textureFormat, + SkISize texDims, + GrGLenum target, + SkColor4f color, + uint32_t levelMask); + + // Pushes data to the currently bound texture to the currently active unit. 'dstRect' must be + // the texture bounds if mipLevelCount is greater than 1. + void uploadTexData(SkISize dimensions, + GrGLenum target, + SkIRect dstRect, + GrGLenum externalFormat, + GrGLenum externalType, + size_t bpp, + const GrMipLevel texels[], + int mipLevelCount); // Helper for onCreateCompressedTexture. Compressed textures are read-only so we only use this // to populate a new texture. Returns false if we failed to create and upload the texture. - bool uploadCompressedTexData(GrGLFormat, + bool uploadCompressedTexData(SkImage::CompressionType compressionType, + GrGLFormat, SkISize dimensions, GrMipMapped, GrGLenum target, diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLInterfaceAutogen.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLInterfaceAutogen.cpp index c465fe618c0..c4f61ffe9f7 100644 --- a/chromium/third_party/skia/src/gpu/gl/GrGLInterfaceAutogen.cpp +++ b/chromium/third_party/skia/src/gpu/gl/GrGLInterfaceAutogen.cpp @@ -19,6 +19,54 @@ GrGLInterface::GrGLInterface() { fStandard = kNone_GrGLStandard; } +#if GR_GL_CHECK_ERROR +static const char* get_error_string(GrGLenum err) { + switch (err) { + case GR_GL_NO_ERROR: + return ""; + case GR_GL_INVALID_ENUM: + return "Invalid Enum"; + case GR_GL_INVALID_VALUE: + return "Invalid Value"; + case GR_GL_INVALID_OPERATION: + return "Invalid Operation"; + case GR_GL_OUT_OF_MEMORY: + return "Out of Memory"; + case GR_GL_CONTEXT_LOST: + return "Context Lost"; + } + return "Unknown"; +} + +GrGLenum GrGLInterface::checkError(const char* location, const char* call) const { + GrGLenum error = fFunctions.fGetError(); + if (error != GR_GL_NO_ERROR && !fSuppressErrorLogging) { + SkDebugf("---- glGetError 0x%x(%s)", error, get_error_string(error)); + if (location) { + SkDebugf(" at\n\t%s", location); + } + if (call) { + SkDebugf("\n\t\t%s", call); + } + SkDebugf("\n"); + if (error == GR_GL_OUT_OF_MEMORY) { + fOOMed = true; + } + } + return error; +} + +bool GrGLInterface::checkAndResetOOMed() const { + if (fOOMed) { + fOOMed = false; + return true; + } + return false; +} + +void GrGLInterface::suppressErrorLogging() { fSuppressErrorLogging = true; } +#endif + #define RETURN_FALSE_INTERFACE \ SkDEBUGF("%s:%d GrGLInterface::validate() failed.\n", __FILE__, __LINE__); \ return false diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.cpp index 865d8075fe8..0d2a801ed90 100644 --- a/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.cpp +++ b/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.cpp @@ -8,7 +8,6 @@ #include "src/gpu/gl/GrGLOpsRenderPass.h" #include "src/gpu/GrContextPriv.h" -#include "src/gpu/GrFixedClip.h" #include "src/gpu/GrProgramInfo.h" #include "src/gpu/GrRenderTargetPriv.h" @@ -259,12 +258,10 @@ void GrGLOpsRenderPass::onDrawIndexedIndirect(const GrBuffer* drawIndirectBuffer } } -void GrGLOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& color) { - fGpu->clear(clip, color, fRenderTarget, fOrigin); +void GrGLOpsRenderPass::onClear(const GrScissorState& scissor, const SkPMColor4f& color) { + fGpu->clear(scissor, color, fRenderTarget, fOrigin); } -void GrGLOpsRenderPass::onClearStencilClip(const GrFixedClip& clip, - bool insideStencilMask) { - fGpu->clearStencilClip(clip, insideStencilMask, fRenderTarget, fOrigin); +void GrGLOpsRenderPass::onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) { + fGpu->clearStencilClip(scissor, insideStencilMask, fRenderTarget, fOrigin); } - diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.h b/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.h index b16dda1a953..038e5586f35 100644 --- a/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.h +++ b/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.h @@ -69,8 +69,8 @@ private: void onDrawIndirect(const GrBuffer* drawIndirectBuffer, size_t offset, int drawCount) override; void onDrawIndexedIndirect(const GrBuffer* drawIndirectBuffer, size_t offset, int drawCount) override; - void onClear(const GrFixedClip& clip, const SkPMColor4f& color) override; - void onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) override; + void onClear(const GrScissorState& scissor, const SkPMColor4f& color) override; + void onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) override; GrGLGpu* fGpu; SkIRect fContentBounds; @@ -89,4 +89,3 @@ private: }; #endif - diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLProgram.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLProgram.cpp index e8f08847ce6..17938d42a99 100644 --- a/chromium/third_party/skia/src/gpu/gl/GrGLProgram.cpp +++ b/chromium/third_party/skia/src/gpu/gl/GrGLProgram.cpp @@ -26,6 +26,43 @@ /////////////////////////////////////////////////////////////////////////////////////////////////// +sk_sp<GrGLProgram> GrGLProgram::Make( + GrGLGpu* gpu, + const GrGLSLBuiltinUniformHandles& builtinUniforms, + GrGLuint programID, + const UniformInfoArray& uniforms, + const UniformInfoArray& textureSamplers, + const VaryingInfoArray& pathProcVaryings, + std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor, + std::unique_ptr<GrGLSLXferProcessor> xferProcessor, + std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fps, + int fragmentProcessorCnt, + std::unique_ptr<Attribute[]> attributes, + int vertexAttributeCnt, + int instanceAttributeCnt, + int vertexStride, + int instanceStride) { + sk_sp<GrGLProgram> program(new GrGLProgram(gpu, + builtinUniforms, + programID, + uniforms, + textureSamplers, + pathProcVaryings, + std::move(geometryProcessor), + std::move(xferProcessor), + std::move(fps), + fragmentProcessorCnt, + std::move(attributes), + vertexAttributeCnt, + instanceAttributeCnt, + vertexStride, + instanceStride)); + // Assign texture units to sampler uniforms one time up front. + gpu->flushProgram(program); + program->fProgramDataManager.setSamplerUniforms(textureSamplers, 0); + return program; +} + GrGLProgram::GrGLProgram( GrGLGpu* gpu, const GrGLSLBuiltinUniformHandles& builtinUniforms, @@ -35,7 +72,7 @@ GrGLProgram::GrGLProgram( const VaryingInfoArray& pathProcVaryings, std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor, std::unique_ptr<GrGLSLXferProcessor> xferProcessor, - std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors, + std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fps, int fragmentProcessorCnt, std::unique_ptr<Attribute[]> attributes, int vertexAttributeCnt, @@ -46,7 +83,7 @@ GrGLProgram::GrGLProgram( , fProgramID(programID) , fPrimitiveProcessor(std::move(geometryProcessor)) , fXferProcessor(std::move(xferProcessor)) - , fFragmentProcessors(std::move(fragmentProcessors)) + , fFragmentProcessors(std::move(fps)) , fFragmentProcessorCnt(fragmentProcessorCnt) , fAttributes(std::move(attributes)) , fVertexAttributeCnt(vertexAttributeCnt) @@ -56,9 +93,6 @@ GrGLProgram::GrGLProgram( , fGpu(gpu) , fProgramDataManager(gpu, programID, uniforms, pathProcVaryings) , fNumTextureSamplers(textureSamplers.count()) { - // Assign texture units to sampler uniforms one time up front. - GL_CALL(UseProgram(fProgramID)); - fProgramDataManager.setSamplerUniforms(textureSamplers, 0); } GrGLProgram::~GrGLProgram() { diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLProgram.h b/chromium/third_party/skia/src/gpu/gl/GrGLProgram.h index f784f2b0aa9..ce9e262f7bc 100644 --- a/chromium/third_party/skia/src/gpu/gl/GrGLProgram.h +++ b/chromium/third_party/skia/src/gpu/gl/GrGLProgram.h @@ -48,21 +48,21 @@ public: * The attribute array consists of vertexAttributeCnt + instanceAttributeCnt elements with * the vertex attributes preceding the instance attributes. */ - GrGLProgram(GrGLGpu*, - const GrGLSLBuiltinUniformHandles&, - GrGLuint programID, - const UniformInfoArray& uniforms, - const UniformInfoArray& textureSamplers, - const VaryingInfoArray&, // used for NVPR only currently - std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor, - std::unique_ptr<GrGLSLXferProcessor> xferProcessor, - std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors, - int fragmentProcessorCnt, - std::unique_ptr<Attribute[]>, - int vertexAttributeCnt, - int instanceAttributeCnt, - int vertexStride, - int instanceStride); + static sk_sp<GrGLProgram> Make(GrGLGpu*, + const GrGLSLBuiltinUniformHandles&, + GrGLuint programID, + const UniformInfoArray& uniforms, + const UniformInfoArray& textureSamplers, + const VaryingInfoArray&, // used for NVPR only currently + std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor, + std::unique_ptr<GrGLSLXferProcessor> xferProcessor, + std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fps, + int fragmentProcessorCnt, + std::unique_ptr<Attribute[]>, + int vertexAttributeCnt, + int instanceAttributeCnt, + int vertexStride, + int instanceStride); ~GrGLProgram(); @@ -141,6 +141,22 @@ public: } private: + GrGLProgram(GrGLGpu*, + const GrGLSLBuiltinUniformHandles&, + GrGLuint programID, + const UniformInfoArray& uniforms, + const UniformInfoArray& textureSamplers, + const VaryingInfoArray&, // used for NVPR only currently + std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor, + std::unique_ptr<GrGLSLXferProcessor> xferProcessor, + std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fps, + int fragmentProcessorCnt, + std::unique_ptr<Attribute[]>, + int vertexAttributeCnt, + int instanceAttributeCnt, + int vertexStride, + int instanceStride); + // Helper for setData() that sets the view matrix and loads the render target height uniform void setRenderTargetState(const GrRenderTarget*, GrSurfaceOrigin, const GrPrimitiveProcessor&); diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLUtil.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLUtil.cpp index 28bdbd6588e..fc4781d2814 100644 --- a/chromium/third_party/skia/src/gpu/gl/GrGLUtil.cpp +++ b/chromium/third_party/skia/src/gpu/gl/GrGLUtil.cpp @@ -12,46 +12,6 @@ #include "src/gpu/gl/GrGLUtil.h" #include <stdio.h> -void GrGLClearErr(const GrGLInterface* gl) { - while (GR_GL_NO_ERROR != gl->fFunctions.fGetError()) {} -} - -namespace { -const char *get_error_string(uint32_t err) { - switch (err) { - case GR_GL_NO_ERROR: - return ""; - case GR_GL_INVALID_ENUM: - return "Invalid Enum"; - case GR_GL_INVALID_VALUE: - return "Invalid Value"; - case GR_GL_INVALID_OPERATION: - return "Invalid Operation"; - case GR_GL_OUT_OF_MEMORY: - return "Out of Memory"; - case GR_GL_CONTEXT_LOST: - return "Context Lost"; - } - return "Unknown"; -} -} - -void GrGLCheckErr(const GrGLInterface* gl, - const char* location, - const char* call) { - uint32_t err = GR_GL_GET_ERROR(gl); - if (GR_GL_NO_ERROR != err) { - SkDebugf("---- glGetError 0x%x(%s)", err, get_error_string(err)); - if (location) { - SkDebugf(" at\n\t%s", location); - } - if (call) { - SkDebugf("\n\t\t%s", call); - } - SkDebugf("\n"); - } -} - /////////////////////////////////////////////////////////////////////////////// #if GR_GL_LOG_CALLS @@ -480,33 +440,38 @@ GrGLRenderer GrGLGetRendererFromStrings(const char* rendererString, static constexpr char kRadeonStr[] = "Radeon "; if (const char* amdString = strstr(rendererString, kRadeonStr)) { amdString += strlen(kRadeonStr); - char amdGeneration, amdTier, amdRevision; // Sometimes there is a (TM) and sometimes not. static constexpr char kTMStr[] = "(TM) "; if (!strncmp(amdString, kTMStr, strlen(kTMStr))) { amdString += strlen(kTMStr); } - n = sscanf(amdString, "R9 M%c%c%c", &amdGeneration, &amdTier, &amdRevision); - if (3 == n) { - if ('3' == amdGeneration) { - return kAMDRadeonR9M3xx_GrGLRenderer; - } else if ('4' == amdGeneration) { - return kAMDRadeonR9M4xx_GrGLRenderer; - } - } char amd0, amd1, amd2; + int amdModel; + n = sscanf(amdString, "R9 M3%c%c", &amd0, &amd1); + if (2 == n && isdigit(amd0) && isdigit(amd1)) { + return kAMDRadeonR9M3xx_GrGLRenderer; + } + + n = sscanf(amdString, "R9 M4%c%c", &amd0, &amd1); + if (2 == n && isdigit(amd0) && isdigit(amd1)) { + return kAMDRadeonR9M4xx_GrGLRenderer; + } + n = sscanf(amdString, "HD 7%c%c%c Series", &amd0, &amd1, &amd2); - if (3 == n) { + if (3 == n && isdigit(amd0) && isdigit(amd1) && isdigit(amd2)) { return kAMDRadeonHD7xxx_GrGLRenderer; } - int amdVegaModel=0; - n = sscanf(amdString, "Pro Vega %i", &amdVegaModel); + n = sscanf(amdString, "Pro 5%c%c%c", &amd0, &amd1, &amd2); + if (3 == n && isdigit(amd0) && isdigit(amd1) && isdigit(amd2)) { + return kAMDRadeonPro5xxx_GrGLRenderer; + } + + n = sscanf(amdString, "Pro Vega %i", &amdModel); if (1 == n) { return kAMDRadeonProVegaxx_GrGLRenderer; } - } if (strstr(rendererString, "llvmpipe")) { @@ -579,6 +544,8 @@ std::tuple<GrGLANGLEBackend, GrGLANGLEVendor, GrGLANGLERenderer> GrGLGetANGLEInf } } else if (strstr(rendererString, "NVIDIA")) { vendor = GrGLANGLEVendor::kNVIDIA; + } else if (strstr(rendererString, "Radeon")) { + vendor = GrGLANGLEVendor::kAMD; } if (strstr(rendererString, "Direct3D11")) { backend = GrGLANGLEBackend::kD3D11; @@ -678,37 +645,3 @@ bool GrGLFormatIsCompressed(GrGLFormat format) { SkUNREACHABLE; } -SkImage::CompressionType GrGLFormatToCompressionType(GrGLFormat format) { - switch (format) { - case GrGLFormat::kCOMPRESSED_ETC1_RGB8: - case GrGLFormat::kCOMPRESSED_RGB8_ETC2: - return SkImage::CompressionType::kETC2_RGB8_UNORM; - case GrGLFormat::kCOMPRESSED_RGB8_BC1: - return SkImage::CompressionType::kBC1_RGB8_UNORM; - case GrGLFormat::kCOMPRESSED_RGBA8_BC1: - return SkImage::CompressionType::kBC1_RGBA8_UNORM; - - case GrGLFormat::kRGBA8: - case GrGLFormat::kR8: - case GrGLFormat::kALPHA8: - case GrGLFormat::kLUMINANCE8: - case GrGLFormat::kBGRA8: - case GrGLFormat::kRGB565: - case GrGLFormat::kRGBA16F: - case GrGLFormat::kR16F: - case GrGLFormat::kLUMINANCE16F: - case GrGLFormat::kRGB8: - case GrGLFormat::kRG8: - case GrGLFormat::kRGB10_A2: - case GrGLFormat::kRGBA4: - case GrGLFormat::kSRGB8_ALPHA8: - case GrGLFormat::kR16: - case GrGLFormat::kRG16: - case GrGLFormat::kRGBA16: - case GrGLFormat::kRG16F: - case GrGLFormat::kUnknown: - return SkImage::CompressionType::kNone; - } - SkUNREACHABLE; -} - diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLUtil.h b/chromium/third_party/skia/src/gpu/gl/GrGLUtil.h index e168275a16d..08435d0a1ab 100644 --- a/chromium/third_party/skia/src/gpu/gl/GrGLUtil.h +++ b/chromium/third_party/skia/src/gpu/gl/GrGLUtil.h @@ -130,6 +130,7 @@ enum GrGLRenderer { kAMDRadeonHD7xxx_GrGLRenderer, // AMD Radeon HD 7000 Series kAMDRadeonR9M3xx_GrGLRenderer, // AMD Radeon R9 M300 Series kAMDRadeonR9M4xx_GrGLRenderer, // AMD Radeon R9 M400 Series + kAMDRadeonPro5xxx_GrGLRenderer, // AMD Radeon Pro 5000 Series kAMDRadeonProVegaxx_GrGLRenderer, // AMD Radeon Pro Vega kOther_GrGLRenderer @@ -157,7 +158,8 @@ enum class GrGLANGLEBackend { enum class GrGLANGLEVendor { kUnknown, kIntel, - kNVIDIA + kNVIDIA, + kAMD }; enum class GrGLANGLERenderer { @@ -255,23 +257,25 @@ void GrGLCheckErr(const GrGLInterface* gl, const char* location, const char* call); -void GrGLClearErr(const GrGLInterface* gl); - //////////////////////////////////////////////////////////////////////////////// /** * Macros for using GrGLInterface to make GL calls */ -// internal macro to conditionally call glGetError based on compile-time and -// run-time flags. +// Conditionally checks glGetError based on compile-time and run-time flags. #if GR_GL_CHECK_ERROR extern bool gCheckErrorGL; - #define GR_GL_CHECK_ERROR_IMPL(IFACE, X) \ - if (gCheckErrorGL) \ - GrGLCheckErr(IFACE, GR_FILE_AND_LINE_STR, #X) +#define GR_GL_CHECK_ERROR_IMPL(IFACE, X) \ + do { \ + if (gCheckErrorGL) { \ + IFACE->checkError(GR_FILE_AND_LINE_STR, #X); \ + } \ + } while (false) #else - #define GR_GL_CHECK_ERROR_IMPL(IFACE, X) +#define GR_GL_CHECK_ERROR_IMPL(IFACE, X) \ + do { \ + } while (false) #endif // internal macro to conditionally log the gl call using SkDebugf based on @@ -314,9 +318,6 @@ void GrGLClearErr(const GrGLInterface* gl); GR_GL_LOG_CALLS_IMPL(X); \ } while (false) -// call glGetError without doing a redundant error check or logging. -#define GR_GL_GET_ERROR(IFACE) (IFACE)->fFunctions.fGetError() - static constexpr GrGLFormat GrGLFormatFromGLEnum(GrGLenum glFormat) { switch (glFormat) { case GR_GL_RGBA8: return GrGLFormat::kRGBA8; @@ -415,9 +416,4 @@ GrGLenum GrToGLStencilFunc(GrStencilTest test); */ bool GrGLFormatIsCompressed(GrGLFormat); -/** - * This will return CompressionType::kNone if the format is uncompressed. - */ -SkImage::CompressionType GrGLFormatToCompressionType(GrGLFormat); - #endif diff --git a/chromium/third_party/skia/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/chromium/third_party/skia/src/gpu/gl/builders/GrGLProgramBuilder.cpp index 6c2ba755bcd..230298f00c7 100644 --- a/chromium/third_party/skia/src/gpu/gl/builders/GrGLProgramBuilder.cpp +++ b/chromium/third_party/skia/src/gpu/gl/builders/GrGLProgramBuilder.cpp @@ -10,9 +10,9 @@ #include "include/gpu/GrContext.h" #include "src/core/SkATrace.h" #include "src/core/SkAutoMalloc.h" -#include "src/core/SkReader32.h" +#include "src/core/SkReadBuffer.h" #include "src/core/SkTraceEvent.h" -#include "src/core/SkWriter32.h" +#include "src/core/SkWriteBuffer.h" #include "src/gpu/GrAutoLocaleSetter.h" #include "src/gpu/GrContextPriv.h" #include "src/gpu/GrCoordTransform.h" @@ -166,16 +166,19 @@ void GrGLProgramBuilder::storeShaderInCache(const SkSL::Program::Inputs& inputs, GrGLsizei length = 0; GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length)); if (length > 0) { - SkWriter32 writer; - writer.write32(kGLPB_Tag); + SkBinaryWriteBuffer writer; + writer.writeInt(GrPersistentCacheUtils::kCurrentVersion); + writer.writeUInt(kGLPB_Tag); - writer.writePad(&inputs, sizeof(inputs)); - writer.write32(length); + writer.writePad32(&inputs, sizeof(inputs)); - void* binary = writer.reservePad(length); + SkAutoSMalloc<2048> binary(length); GrGLenum binaryFormat; - GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary)); - writer.write32(binaryFormat); + GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary.get())); + + writer.writeUInt(binaryFormat); + writer.writeInt(length); + writer.writePad32(binary.get(), length); auto data = writer.snapshotAsData(); this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data); @@ -254,7 +257,7 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr usedProgramBinaries = true; } else if (cached) { ATRACE_ANDROID_FRAMEWORK_ALWAYS("cache_hit"); - SkReader32 reader(fCached->data(), fCached->size()); + SkReadBuffer reader(fCached->data(), fCached->size()); SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader); switch (shaderType) { @@ -265,15 +268,18 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr cached = false; break; } - reader.read(&inputs, sizeof(inputs)); - GrGLsizei length = reader.readInt(); + reader.readPad32(&inputs, sizeof(inputs)); + GrGLenum binaryFormat = reader.readUInt(); + GrGLsizei length = reader.readInt(); const void* binary = reader.skip(length); - GrGLenum binaryFormat = reader.readU32(); - GrGLClearErr(this->gpu()->glInterface()); + if (!reader.isValid()) { + break; + } + this->gpu()->clearErrorsAndCheckForOOM(); GR_GL_CALL_NOERRCHECK(this->gpu()->glInterface(), ProgramBinary(programID, binaryFormat, const_cast<void*>(binary), length)); - if (GR_GL_GET_ERROR(this->gpu()->glInterface()) == GR_GL_NO_ERROR) { + if (this->gpu()->getErrorAndCheckForOOM() == GR_GL_NO_ERROR) { if (checkLinked) { cached = this->checkLinkStatus(programID, errorHandler, nullptr, nullptr); } @@ -295,11 +301,20 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr case kSKSL_Tag: // SkSL cache hit, this should only happen in tools overriding the generated SkSL - GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, &inputs, 1); - for (int i = 0; i < kGrShaderTypeCount; ++i) { - sksl[i] = &cached_sksl[i]; + if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, &inputs, 1)) { + for (int i = 0; i < kGrShaderTypeCount; ++i) { + sksl[i] = &cached_sksl[i]; + } } break; + + default: + // We got something invalid, so pretend it wasn't there + reader.validate(false); + break; + } + if (!reader.isValid()) { + cached = false; } } if (!usedProgramBinaries) { @@ -376,7 +391,8 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr } SkString tessControlShader = primProc.getTessControlShaderGLSL( - versionAndExtensionDecls.c_str(), *this->shaderCaps()); + fGeometryProcessor.get(), versionAndExtensionDecls.c_str(), fUniformHandler, + *this->shaderCaps()); if (!this->compileAndAttachShaders(tessControlShader.c_str(), programID, GR_GL_TESS_CONTROL_SHADER, &shadersToDelete, errorHandler)) { @@ -385,7 +401,8 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr } SkString tessEvaluationShader = primProc.getTessEvaluationShaderGLSL( - versionAndExtensionDecls.c_str(), *this->shaderCaps()); + fGeometryProcessor.get(), versionAndExtensionDecls.c_str(), fUniformHandler, + *this->shaderCaps()); if (!this->compileAndAttachShaders(tessEvaluationShader.c_str(), programID, GR_GL_TESS_EVALUATION_SHADER, &shadersToDelete, errorHandler)) { @@ -534,27 +551,27 @@ void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID, boo } sk_sp<GrGLProgram> GrGLProgramBuilder::createProgram(GrGLuint programID) { - return sk_sp<GrGLProgram>(new GrGLProgram(fGpu, - fUniformHandles, - programID, - fUniformHandler.fUniforms, - fUniformHandler.fSamplers, - fVaryingHandler.fPathProcVaryingInfos, - std::move(fGeometryProcessor), - std::move(fXferProcessor), - std::move(fFragmentProcessors), - fFragmentProcessorCnt, - std::move(fAttributes), - fVertexAttributeCnt, - fInstanceAttributeCnt, - fVertexStride, - fInstanceStride)); + return GrGLProgram::Make(fGpu, + fUniformHandles, + programID, + fUniformHandler.fUniforms, + fUniformHandler.fSamplers, + fVaryingHandler.fPathProcVaryingInfos, + std::move(fGeometryProcessor), + std::move(fXferProcessor), + std::move(fFragmentProcessors), + fFragmentProcessorCnt, + std::move(fAttributes), + fVertexAttributeCnt, + fInstanceAttributeCnt, + fVertexStride, + fInstanceStride); } bool GrGLProgramBuilder::PrecompileProgram(GrGLPrecompiledProgram* precompiledProgram, GrGLGpu* gpu, const SkData& cachedData) { - SkReader32 reader(cachedData.data(), cachedData.size()); + SkReadBuffer reader(cachedData.data(), cachedData.size()); SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader); if (shaderType != kSKSL_Tag) { // TODO: Support GLSL, and maybe even program binaries, too? @@ -563,13 +580,6 @@ bool GrGLProgramBuilder::PrecompileProgram(GrGLPrecompiledProgram* precompiledPr const GrGLInterface* gl = gpu->glInterface(); auto errorHandler = gpu->getContext()->priv().getShaderErrorHandler(); - GrGLuint programID; - GR_GL_CALL_RET(gl, programID, CreateProgram()); - if (0 == programID) { - return false; - } - - SkTDArray<GrGLuint> shadersToDelete; SkSL::Program::Settings settings; const GrGLCaps& caps = gpu->glCaps(); @@ -580,7 +590,17 @@ bool GrGLProgramBuilder::PrecompileProgram(GrGLPrecompiledProgram* precompiledPr SkSL::String shaders[kGrShaderTypeCount]; SkSL::Program::Inputs inputs; - GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders, &inputs, 1, &meta); + if (!GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders, &inputs, 1, &meta)) { + return false; + } + + GrGLuint programID; + GR_GL_CALL_RET(gl, programID, CreateProgram()); + if (0 == programID) { + return false; + } + + SkTDArray<GrGLuint> shadersToDelete; auto compileShader = [&](SkSL::Program::Kind kind, const SkSL::String& sksl, GrGLenum type) { SkSL::String glsl; diff --git a/chromium/third_party/skia/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/chromium/third_party/skia/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp index ad629d0bf59..68ba303dc33 100644 --- a/chromium/third_party/skia/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp +++ b/chromium/third_party/skia/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp @@ -88,9 +88,16 @@ SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords, } switch (matrix.fKind) { case SkSL::SampleMatrix::Kind::kMixed: - case SkSL::SampleMatrix::Kind::kVariable: - result = SkStringPrintf("(_matrix * float3(%s, 1)).xy", result.c_str()); - break; + case SkSL::SampleMatrix::Kind::kVariable: { + SkString sampleCoords2D; + sampleCoords2D.printf("%s_sample", coords.c_str()); + this->codeAppendf("\tfloat3 %s_3d = _matrix * %s.xy1;\n", + sampleCoords2D.c_str(), result.c_str()); + this->codeAppendf("\tfloat2 %s = %s_3d.xy / %s_3d.z;\n", + sampleCoords2D.c_str(), sampleCoords2D.c_str(), + sampleCoords2D.c_str()); + result = sampleCoords2D; + break; } default: break; } @@ -181,11 +188,15 @@ SkString GrGLSLFPFragmentBuilder::writeProcessorFunction(GrGLSLFragmentProcessor const GrShaderVar& transform = args.fTransformedCoords[0].fTransform; switch (transform.getType()) { case kFloat4_GrSLType: + // This is a scale+translate, so there's no perspective division needed this->codeAppendf("_coords = _coords * %s.xz + %s.yw;\n", transform.c_str(), transform.c_str()); break; case kFloat3x3_GrSLType: - this->codeAppendf("_coords = (%s * float3(_coords, 1)).xy;\n", transform.c_str()); + this->codeAppend("{\n"); + this->codeAppendf("float3 _coords3 = (%s * _coords.xy1);\n", transform.c_str()); + this->codeAppend("_coords = _coords3.xy / _coords3.z;\n"); + this->codeAppend("}\n"); break; default: SkASSERT(transform.getType() == kVoid_GrSLType); @@ -195,8 +206,12 @@ SkString GrGLSLFPFragmentBuilder::writeProcessorFunction(GrGLSLFragmentProcessor SkASSERT(!hasVariableMatrix); this->codeAppend("{\n"); args.fUniformHandler->writeUniformMappings(args.fFp.sampleMatrix().fOwner, this); - this->codeAppendf("_coords = (%s * float3(_coords, 1)).xy;\n", + // FIXME This is not a variable matrix, we could key on the matrix type and skip + // perspective division; it may also be worth detecting if it was scale+translate and + // evaluating this similarly to the kFloat4 explicit coord case. + this->codeAppendf("float3 _coords3 = (%s * _coords.xy1);\n", args.fFp.sampleMatrix().fExpression.c_str()); + this->codeAppend("_coords = _coords3.xy / _coords3.z;\n"); this->codeAppend("}\n"); } } diff --git a/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.cpp b/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.cpp index 3ef36d4f48c..4d2ee7e532c 100644 --- a/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.cpp +++ b/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.cpp @@ -14,10 +14,19 @@ #include "src/gpu/glsl/GrGLSLVarying.h" #include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h" +#include <unordered_map> + void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) { GrGPArgs gpArgs; this->onEmitCode(args, &gpArgs); + // FIXME This must always be called at the moment, even when fLocalCoordVar is uninitialized + // and void because collectTransforms registers the uniforms for legacy coord transforms, which + // still need to be added even if the FPs are sampled explicitly. When they are gone, we only + // need to call this if the local coord isn't void (plus verify that FPs really don't need it). + this->collectTransforms(args.fVertBuilder, args.fVaryingHandler, args.fUniformHandler, + gpArgs.fLocalCoordVar, args.fFPCoordTransformHandler); + if (args.fGP.willUseTessellationShaders()) { // Tessellation shaders are temporarily responsible for integrating their own code strings // while we work out full support. @@ -42,11 +51,14 @@ void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) { vBuilder->codeAppendf("sk_Position = float4(%s", gpArgs.fPositionVar.c_str()); switch (gpArgs.fPositionVar.getType()) { case kFloat_GrSLType: - vBuilder->codeAppend(", 0"); // fallthru. + vBuilder->codeAppend(", 0"); + [[fallthrough]]; case kFloat2_GrSLType: - vBuilder->codeAppend(", 0"); // fallthru. + vBuilder->codeAppend(", 0"); + [[fallthrough]]; case kFloat3_GrSLType: - vBuilder->codeAppend(", 1"); // fallthru. + vBuilder->codeAppend(", 1"); + [[fallthrough]]; case kFloat4_GrSLType: vBuilder->codeAppend(");"); break; @@ -57,12 +69,11 @@ void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) { } } -void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb, - GrGLSLVaryingHandler* varyingHandler, - GrGLSLUniformHandler* uniformHandler, - const GrShaderVar& localCoordsVar, - const SkMatrix& localMatrix, - FPCoordTransformHandler* handler) { +void GrGLSLGeometryProcessor::collectTransforms(GrGLSLVertexBuilder* vb, + GrGLSLVaryingHandler* varyingHandler, + GrGLSLUniformHandler* uniformHandler, + const GrShaderVar& localCoordsVar, + FPCoordTransformHandler* handler) { // We only require localCoordsVar to be valid if there is a coord transform that needs // it. CTs on FPs called with explicit coords do not require a local coord. auto getLocalCoords = [&localCoordsVar, @@ -115,8 +126,7 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb, if (!fp.isSampledWithExplicitCoords()) { auto [localCoordsStr, localCoordLength] = getLocalCoords(); GrGLSLVarying v(kFloat2_GrSLType); - if (localMatrix.hasPerspective() || coordTransform.matrix().hasPerspective() || - localCoordLength == 3) { + if (coordTransform.matrix().hasPerspective() || localCoordLength == 3) { v = GrGLSLVarying(kFloat3_GrSLType); } SkString strVaryingName; @@ -142,41 +152,49 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb, void GrGLSLGeometryProcessor::emitTransformCode(GrGLSLVertexBuilder* vb, GrGLSLUniformHandler* uniformHandler) { + std::unordered_map<const GrFragmentProcessor*, const char*> localCoordsMap; for (const auto& tr : fTransformInfos) { switch (tr.fFP->sampleMatrix().fKind) { - case SkSL::SampleMatrix::Kind::kConstantOrUniform: + case SkSL::SampleMatrix::Kind::kConstantOrUniform: { + SkString localCoords; + localCoordsMap.insert({ tr.fFP, tr.fName }); + if (tr.fFP->sampleMatrix().fBase) { + SkASSERT(localCoordsMap[tr.fFP->sampleMatrix().fBase]); + localCoords = SkStringPrintf("float3(%s, 1)", + localCoordsMap[tr.fFP->sampleMatrix().fBase]); + } else { + localCoords = tr.fLocalCoords.c_str(); + } vb->codeAppend("{\n"); - uniformHandler->writeUniformMappings(tr.fFP->sampleMatrix().fOwner, vb); + if (tr.fFP->sampleMatrix().fOwner) { + uniformHandler->writeUniformMappings(tr.fFP->sampleMatrix().fOwner, vb); + } if (tr.fType == kFloat2_GrSLType) { vb->codeAppendf("%s = (%s * %s * %s).xy", tr.fName, tr.fFP->sampleMatrix().fExpression.c_str(), tr.fMatrix.c_str(), - tr.fLocalCoords.c_str()); + localCoords.c_str()); } else { SkASSERT(tr.fType == kFloat3_GrSLType); vb->codeAppendf("%s = %s * %s * %s", tr.fName, tr.fFP->sampleMatrix().fExpression.c_str(), tr.fMatrix.c_str(), - tr.fLocalCoords.c_str()); + localCoords.c_str()); } vb->codeAppend(";\n"); vb->codeAppend("}\n"); + break; + } default: break; } } } -void GrGLSLGeometryProcessor::setTransformDataHelper(const SkMatrix& localMatrix, - const GrGLSLProgramDataManager& pdman, +void GrGLSLGeometryProcessor::setTransformDataHelper(const GrGLSLProgramDataManager& pdman, const CoordTransformRange& transformRange) { int i = 0; for (auto [transform, fp] : transformRange) { if (fInstalledTransforms[i].fHandle.isValid()) { - SkMatrix m; - if (fp.isSampledWithExplicitCoords()) { - m = GetTransformMatrix(transform, SkMatrix::I()); - } else { - m = GetTransformMatrix(transform, localMatrix); - } + SkMatrix m = GetTransformMatrix(transform, SkMatrix::I()); if (!SkMatrixPriv::CheapEqual(fInstalledTransforms[i].fCurrentValue, m)) { if (fInstalledTransforms[i].fType == kFloat4_GrSLType) { float values[4] = {m.getScaleX(), m.getTranslateX(), @@ -196,11 +214,94 @@ void GrGLSLGeometryProcessor::setTransformDataHelper(const SkMatrix& localMatrix SkASSERT(i == fInstalledTransforms.count()); } +void GrGLSLGeometryProcessor::setTransform(const GrGLSLProgramDataManager& pdman, + const UniformHandle& uniform, + const SkMatrix& matrix, + SkMatrix* state) const { + if (!uniform.isValid() || (state && SkMatrixPriv::CheapEqual(*state, matrix))) { + // No update needed + return; + } + if (state) { + *state = matrix; + } + if (matrix.isScaleTranslate()) { + // ComputeMatrixKey and writeX() assume the uniform is a float4 (can't assert since nothing + // is exposed on a handle, but should be caught lower down). + float values[4] = {matrix.getScaleX(), matrix.getTranslateX(), + matrix.getScaleY(), matrix.getTranslateY()}; + pdman.set4fv(uniform, 1, values); + } else { + pdman.setSkMatrix(uniform, matrix); + } +} + +static void write_vertex_position(GrGLSLVertexBuilder* vertBuilder, + GrGLSLUniformHandler* uniformHandler, + const GrShaderVar& inPos, + const SkMatrix& matrix, + const char* matrixName, + GrShaderVar* outPos, + GrGLSLGeometryProcessor::UniformHandle* matrixUniform) { + SkASSERT(inPos.getType() == kFloat3_GrSLType || inPos.getType() == kFloat2_GrSLType); + SkString outName = vertBuilder->newTmpVarName(inPos.getName().c_str()); + + if (matrix.isIdentity()) { + // Direct assignment, we won't use a uniform for the matrix. + outPos->set(inPos.getType(), outName.c_str()); + vertBuilder->codeAppendf("float%d %s = %s;", GrSLTypeVecLength(inPos.getType()), + outName.c_str(), inPos.getName().c_str()); + } else { + SkASSERT(matrixUniform); + + bool useCompactTransform = matrix.isScaleTranslate(); + const char* mangledMatrixName; + *matrixUniform = uniformHandler->addUniform(nullptr, + kVertex_GrShaderFlag, + useCompactTransform ? kFloat4_GrSLType + : kFloat3x3_GrSLType, + matrixName, + &mangledMatrixName); + + if (inPos.getType() == kFloat3_GrSLType) { + // A float3 stays a float3 whether or not the matrix adds perspective + if (useCompactTransform) { + vertBuilder->codeAppendf("float3 %s = %s.xz1 * %s + %s.yw0;\n", + outName.c_str(), mangledMatrixName, + inPos.getName().c_str(), mangledMatrixName); + } else { + vertBuilder->codeAppendf("float3 %s = %s * %s;\n", outName.c_str(), + mangledMatrixName, inPos.getName().c_str()); + } + outPos->set(kFloat3_GrSLType, outName.c_str()); + } else if (matrix.hasPerspective()) { + // A float2 is promoted to a float3 if we add perspective via the matrix + SkASSERT(!useCompactTransform); + vertBuilder->codeAppendf("float3 %s = (%s * %s.xy1);", + outName.c_str(), mangledMatrixName, inPos.getName().c_str()); + outPos->set(kFloat3_GrSLType, outName.c_str()); + } else { + if (useCompactTransform) { + vertBuilder->codeAppendf("float2 %s = %s.xz * %s + %s.yw;\n", + outName.c_str(), mangledMatrixName, + inPos.getName().c_str(), mangledMatrixName); + } else { + vertBuilder->codeAppendf("float2 %s = (%s * %s.xy1).xy;\n", + outName.c_str(), mangledMatrixName, + inPos.getName().c_str()); + } + outPos->set(kFloat2_GrSLType, outName.c_str()); + } + } +} + void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder, GrGPArgs* gpArgs, const char* posName) { - gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos2"); - vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName); + // writeOutputPosition assumes the incoming pos name points to a float2 variable + GrShaderVar inPos(posName, kFloat2_GrSLType); + write_vertex_position(vertBuilder, nullptr, inPos, SkMatrix::I(), "viewMatrix", + &gpArgs->fPositionVar, nullptr); } void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder, @@ -209,24 +310,17 @@ void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuild const char* posName, const SkMatrix& mat, UniformHandle* viewMatrixUniform) { - if (mat.isIdentity()) { - gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos2"); - vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName); - } else { - const char* viewMatrixName; - *viewMatrixUniform = uniformHandler->addUniform(nullptr, - kVertex_GrShaderFlag, - kFloat3x3_GrSLType, - "uViewM", - &viewMatrixName); - if (!mat.hasPerspective()) { - gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos2"); - vertBuilder->codeAppendf("float2 %s = (%s * float3(%s, 1)).xy;", - gpArgs->fPositionVar.c_str(), viewMatrixName, posName); - } else { - gpArgs->fPositionVar.set(kFloat3_GrSLType, "pos3"); - vertBuilder->codeAppendf("float3 %s = %s * float3(%s, 1);", - gpArgs->fPositionVar.c_str(), viewMatrixName, posName); - } - } + GrShaderVar inPos(posName, kFloat2_GrSLType); + write_vertex_position(vertBuilder, uniformHandler, inPos, mat, "viewMatrix", + &gpArgs->fPositionVar, viewMatrixUniform); +} + +void GrGLSLGeometryProcessor::writeLocalCoord(GrGLSLVertexBuilder* vertBuilder, + GrGLSLUniformHandler* uniformHandler, + GrGPArgs* gpArgs, + GrShaderVar localVar, + const SkMatrix& localMatrix, + UniformHandle* localMatrixUniform) { + write_vertex_position(vertBuilder, uniformHandler, localVar, localMatrix, "localMatrix", + &gpArgs->fLocalCoordVar, localMatrixUniform); } diff --git a/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.h b/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.h index f23bd0e800d..10e21376750 100644 --- a/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.h +++ b/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.h @@ -22,41 +22,33 @@ public: /* Any general emit code goes in the base class emitCode. Subclasses override onEmitCode */ void emitCode(EmitArgs&) final; + // Generate the final code for assigning transformed coordinates to the varyings recorded in + // the call to collectTransforms(). This must happen after FP code emission so that it has + // access to any uniforms the FPs registered for const/uniform sample matrix invocations. + void emitTransformCode(GrGLSLVertexBuilder* vb, + GrGLSLUniformHandler* uniformHandler) override; + protected: // A helper which subclasses can use to upload coord transform matrices in setData(). - void setTransformDataHelper(const SkMatrix& localMatrix, - const GrGLSLProgramDataManager& pdman, + void setTransformDataHelper(const GrGLSLProgramDataManager& pdman, const CoordTransformRange&); - // Emit transformed local coords from the vertex shader as a uniform matrix and varying per - // coord-transform. localCoordsVar must be a 2- or 3-component vector. If it is 3 then it is - // assumed to be a 2D homogeneous coordinate. - void emitTransforms(GrGLSLVertexBuilder*, - GrGLSLVaryingHandler*, - GrGLSLUniformHandler*, - const GrShaderVar& localCoordsVar, - const SkMatrix& localMatrix, - FPCoordTransformHandler*); - - // Version of above that assumes identity for the local matrix. - void emitTransforms(GrGLSLVertexBuilder* vb, - GrGLSLVaryingHandler* varyingHandler, - GrGLSLUniformHandler* uniformHandler, - const GrShaderVar& localCoordsVar, - FPCoordTransformHandler* handler) { - this->emitTransforms(vb, varyingHandler, uniformHandler, localCoordsVar, SkMatrix::I(), - handler); - } - - // TODO: doc - void emitTransformCode(GrGLSLVertexBuilder* vb, - GrGLSLUniformHandler* uniformHandler) override; + // A helper for setting the matrix on a uniform handle initialized through + // writeOutputPosition or writeLocalCoord. Automatically handles elided uniforms, + // scale+translate matrices, and state tracking (if provided state pointer is non-null). + void setTransform(const GrGLSLProgramDataManager& pdman, const UniformHandle& uniform, + const SkMatrix& matrix, SkMatrix* state=nullptr) const; struct GrGPArgs { // Used to specify the output variable used by the GP to store its device position. It can // either be a float2 or a float3 (in order to handle perspective). The subclass sets this // in its onEmitCode(). GrShaderVar fPositionVar; + // Used to specify the variable storing the draw's local coordinates. It can be either a + // float2, float3, or void. It can only be void when no FP needs local coordinates. This + // variable can be an attribute or local variable, but should not itself be a varying. + // GrGLSLGeometryProcessor automatically determines if this must be passed to a FS. + GrShaderVar fLocalCoordVar; }; // Helpers for adding code to write the transformed vertex position. The first simple version @@ -73,19 +65,54 @@ protected: const SkMatrix& mat, UniformHandle* viewMatrixUniform); - static uint32_t ComputePosKey(const SkMatrix& mat) { + // Helper to transform an existing variable by a given local matrix (e.g. the inverse view + // matrix). It will declare the transformed local coord variable and will set + // GrGPArgs::fLocalCoordVar. + void writeLocalCoord(GrGLSLVertexBuilder*, GrGLSLUniformHandler*, GrGPArgs*, + GrShaderVar localVar, const SkMatrix& localMatrix, + UniformHandle* localMatrixUniform); + + // GPs that use writeOutputPosition and/or writeLocalCoord must incorporate the matrix type + // into their key, and should use this function or one of the other related helpers. + static uint32_t ComputeMatrixKey(const SkMatrix& mat) { if (mat.isIdentity()) { - return 0x0; + return 0b00; + } else if (mat.isScaleTranslate()) { + return 0b01; } else if (!mat.hasPerspective()) { - return 0x01; + return 0b10; } else { - return 0x02; + return 0b11; } } + static uint32_t ComputeMatrixKeys(const SkMatrix& viewMatrix, const SkMatrix& localMatrix) { + return (ComputeMatrixKey(viewMatrix) << kMatrixKeyBits) | ComputeMatrixKey(localMatrix); + } + static uint32_t AddMatrixKeys(uint32_t flags, const SkMatrix& viewMatrix, + const SkMatrix& localMatrix) { + // Shifting to make room for the matrix keys shouldn't lose bits + SkASSERT(((flags << (2 * kMatrixKeyBits)) >> (2 * kMatrixKeyBits)) == flags); + return (flags << (2 * kMatrixKeyBits)) | ComputeMatrixKeys(viewMatrix, localMatrix); + } + static constexpr int kMatrixKeyBits = 2; private: virtual void onEmitCode(EmitArgs&, GrGPArgs*) = 0; + // Iterates over the FPs in 'handler' to register additional varyings and uniforms to support + // VS-promoted local coord evaluation for the FPs. Subclasses must call this with + // 'localCoordsVar' set to an SkSL variable expression of type 'float2' or 'float3' representing + // the original local coordinates of the draw. + // + // This must happen before FP code emission so that the FPs can find the appropriate varying + // handles they use in place of explicit coord sampling; it is automatically called after + // onEmitCode() returns using the value stored in GpArgs::fLocalCoordVar. + void collectTransforms(GrGLSLVertexBuilder* vb, + GrGLSLVaryingHandler* varyingHandler, + GrGLSLUniformHandler* uniformHandler, + const GrShaderVar& localCoordsVar, + FPCoordTransformHandler* handler); + struct TransformUniform { UniformHandle fHandle; GrSLType fType = kVoid_GrSLType; diff --git a/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.cpp b/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.cpp index 95f97feb695..e5a9c1448ff 100644 --- a/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.cpp +++ b/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.cpp @@ -20,7 +20,8 @@ GrGLSLShaderBuilder::GrGLSLShaderBuilder(GrGLSLProgramBuilder* program) , fOutputs(GrGLSLProgramBuilder::kVarsPerBlock) , fFeaturesAddedMask(0) , fCodeIndex(kCode) - , fFinalized(false) { + , fFinalized(false) + , fTmpVariableCounter(0) { // We push back some dummy pointers which will later become our header for (int i = 0; i <= kCode; i++) { fShaderStrings.push_back(); @@ -198,9 +199,7 @@ void GrGLSLShaderBuilder::appendColorGamutXform(SkString* out, GrShaderVar("color", useFloat ? kFloat4_GrSLType : kHalf4_GrSLType)}; SkString body; if (colorXformHelper->applyUnpremul()) { - body.appendf("%s nonZeroAlpha = max(color.a, 0.0001);", useFloat ? "float" : "half"); - body.appendf("color = %s(color.rgb / nonZeroAlpha, nonZeroAlpha);", - useFloat ? "float4" : "half4"); + body.appendf("color = unpremul%s(color);", useFloat ? "_float" : ""); } if (colorXformHelper->applySrcTF()) { body.appendf("color.r = %s(half(color.r));", srcTFFuncName.c_str()); diff --git a/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.h b/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.h index b69abe89442..b766280d23a 100644 --- a/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.h +++ b/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.h @@ -84,6 +84,13 @@ public: void declareGlobal(const GrShaderVar&); + // Generates a unique variable name for holding the result of a temporary expression when it's + // not reasonable to just add a new block for scoping. Does not declare anything. + SkString newTmpVarName(const char* suffix) { + int tmpIdx = fTmpVariableCounter++; + return SkStringPrintf("_tmp_%d_%s", tmpIdx, suffix); + } + /** * Called by GrGLSLProcessors to add code to one of the shaders. */ @@ -238,6 +245,9 @@ protected: int fCodeIndex; bool fFinalized; + // Counter for generating unique scratch variable names in a shader. + int fTmpVariableCounter; + friend class GrCCCoverageProcessor; // to access code(). friend class GrGLSLProgramBuilder; friend class GrGLProgramBuilder; diff --git a/chromium/third_party/skia/src/gpu/gradients/GrGradientShader.cpp b/chromium/third_party/skia/src/gpu/gradients/GrGradientShader.cpp index 59624f2bb7f..8981955a38e 100644 --- a/chromium/third_party/skia/src/gpu/gradients/GrGradientShader.cpp +++ b/chromium/third_party/skia/src/gpu/gradients/GrGradientShader.cpp @@ -27,6 +27,7 @@ #include "src/gpu/GrColorInfo.h" #include "src/gpu/GrRecordingContextPriv.h" #include "src/gpu/SkGr.h" +#include "src/gpu/effects/GrTextureEffect.h" // Intervals smaller than this (that aren't hard stops) on low-precision-only devices force us to // use the textured gradient @@ -64,8 +65,11 @@ static std::unique_ptr<GrFragmentProcessor> make_textured_colorizer(const SkPMCo SkDebugf("Gradient won't draw. Could not create texture."); return nullptr; } - - return GrTextureGradientColorizer::Make(std::move(view)); + // TODO: When we start sampling colorizers with explicit coords rather than using sk_InColor + // the GrTextureEffect can simply be the colorizer. + auto m = SkMatrix::Scale(view.width(), 1.f); + auto te = GrTextureEffect::Make(std::move(view), alphaType, m, GrSamplerState::Filter::kBilerp); + return GrTextureGradientColorizer::Make(std::move(te)); } // Analyze the shader's color stops and positions and chooses an appropriate colorizer to represent diff --git a/chromium/third_party/skia/src/gpu/gradients/GrTextureGradientColorizer.fp b/chromium/third_party/skia/src/gpu/gradients/GrTextureGradientColorizer.fp index c2146459f3e..b8dba025808 100644 --- a/chromium/third_party/skia/src/gpu/gradients/GrTextureGradientColorizer.fp +++ b/chromium/third_party/skia/src/gpu/gradients/GrTextureGradientColorizer.fp @@ -6,13 +6,9 @@ */ // Should have height = 1px, horizontal axis represents t = 0 to 1 -in uniform sampler2D gradient; - -@samplerParams(gradient) { - GrSamplerState::Filter::kBilerp -} +in fragmentProcessor textureFP; void main() { half2 coord = half2(sk_InColor.x, 0.5); - sk_OutColor = sample(gradient, coord); + sk_OutColor = sample(textureFP, coord); } diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.cpp index 044165365d9..7e309c35b7e 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.cpp +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.cpp @@ -38,8 +38,14 @@ public: SkString _sample1099; _sample1099 = this->invokeChild(_outer.gradLayout_index, args); fragBuilder->codeAppendf( - "half4 t = %s;\nif (!%s && t.y < 0.0) {\n %s = half4(0.0);\n} else if (t.x < " - "0.0) {\n %s = %s;\n} else if (t.x > 1.0) {\n %s = %s;\n} else {", + R"SkSL(half4 t = %s; +if (!%s && t.y < 0.0) { + %s = half4(0.0); +} else if (t.x < 0.0) { + %s = %s; +} else if (t.x > 1.0) { + %s = %s; +} else {)SkSL", _sample1099.c_str(), (_outer.childProcessor(_outer.gradLayout_index).preservesOpaqueInput() ? "true" : "false"), @@ -49,10 +55,16 @@ public: SkString _input1767("t"); SkString _sample1767; _sample1767 = this->invokeChild(_outer.colorizer_index, _input1767.c_str(), args); - fragBuilder->codeAppendf("\n %s = %s;\n}\n@if (%s) {\n %s.xyz *= %s.w;\n}\n", - args.fOutputColor, _sample1767.c_str(), - (_outer.makePremul ? "true" : "false"), args.fOutputColor, - args.fOutputColor); + fragBuilder->codeAppendf( + R"SkSL( + %s = %s; +} +@if (%s) { + %s.xyz *= %s.w; +} +)SkSL", + args.fOutputColor, _sample1767.c_str(), (_outer.makePremul ? "true" : "false"), + args.fOutputColor, args.fOutputColor); } private: @@ -95,25 +107,17 @@ bool GrClampedGradientEffect::onIsEqual(const GrFragmentProcessor& other) const } GrClampedGradientEffect::GrClampedGradientEffect(const GrClampedGradientEffect& src) : INHERITED(kGrClampedGradientEffect_ClassID, src.optimizationFlags()) - , colorizer_index(src.colorizer_index) - , gradLayout_index(src.gradLayout_index) , leftBorderColor(src.leftBorderColor) , rightBorderColor(src.rightBorderColor) , makePremul(src.makePremul) , colorsAreOpaque(src.colorsAreOpaque) { { - auto clone = src.childProcessor(colorizer_index).clone(); - if (src.childProcessor(colorizer_index).isSampledWithExplicitCoords()) { - clone->setSampledWithExplicitCoords(); - } - this->registerChildProcessor(std::move(clone)); + colorizer_index = + this->cloneAndRegisterChildProcessor(src.childProcessor(src.colorizer_index)); } { - auto clone = src.childProcessor(gradLayout_index).clone(); - if (src.childProcessor(gradLayout_index).isSampledWithExplicitCoords()) { - clone->setSampledWithExplicitCoords(); - } - this->registerChildProcessor(std::move(clone)); + gradLayout_index = + this->cloneAndRegisterChildProcessor(src.childProcessor(src.gradLayout_index)); } } std::unique_ptr<GrFragmentProcessor> GrClampedGradientEffect::clone() const { diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.h index 4779cdbb61f..eee25ff2726 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.h +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.h @@ -10,11 +10,13 @@ **************************************************************************************************/ #ifndef GrClampedGradientEffect_DEFINED #define GrClampedGradientEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrClampedGradientEffect : public GrFragmentProcessor { public: static std::unique_ptr<GrFragmentProcessor> Make( @@ -55,11 +57,9 @@ private: , makePremul(makePremul) , colorsAreOpaque(colorsAreOpaque) { SkASSERT(colorizer); - colorizer_index = this->numChildProcessors(); - this->registerChildProcessor(std::move(colorizer)); + colorizer_index = this->registerChild(std::move(colorizer)); SkASSERT(gradLayout); - gradLayout_index = this->numChildProcessors(); - this->registerChildProcessor(std::move(gradLayout)); + gradLayout_index = this->registerChild(std::move(gradLayout)); } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.cpp index 88b50df48f0..323fec5e1bb 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.cpp +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.cpp @@ -45,9 +45,17 @@ public: thresholdVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf_GrSLType, "threshold"); fragBuilder->codeAppendf( - "half t = %s.x;\nfloat4 scale, bias;\nif (t < %s) {\n scale = %s;\n bias = " - "%s;\n} else {\n scale = %s;\n bias = %s;\n}\n%s = half4(float(t) * scale + " - "bias);\n", + R"SkSL(half t = %s.x; +float4 scale, bias; +if (t < %s) { + scale = %s; + bias = %s; +} else { + scale = %s; + bias = %s; +} +%s = half4(float(t) * scale + bias); +)SkSL", args.fInputColor, args.fUniformHandler->getUniformCStr(thresholdVar), args.fUniformHandler->getUniformCStr(scale01Var), args.fUniformHandler->getUniformCStr(bias01Var), diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.h index d8ebc1ef29b..58a97a3128a 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.h +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.h @@ -10,11 +10,13 @@ **************************************************************************************************/ #ifndef GrDualIntervalGradientColorizer_DEFINED #define GrDualIntervalGradientColorizer_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrDualIntervalGradientColorizer : public GrFragmentProcessor { public: static std::unique_ptr<GrFragmentProcessor> Make(const SkPMColor4f& c0, diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.cpp index 2d28b92df08..5bc1732a773 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.cpp +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.cpp @@ -28,7 +28,9 @@ public: SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D( args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix()); fragBuilder->codeAppendf( - "half t = half(%s.x) + 9.9999997473787516e-06;\n%s = half4(t, 1.0, 0.0, 0.0);\n", + R"SkSL(half t = half(%s.x) + 9.9999997473787516e-06; +%s = half4(t, 1.0, 0.0, 0.0); +)SkSL", sk_TransformedCoords2D_0.c_str(), args.fOutputColor); } diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.h index 6ecbeee850c..5c3323d2759 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.h +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.h @@ -10,14 +10,16 @@ **************************************************************************************************/ #ifndef GrLinearGradientLayout_DEFINED #define GrLinearGradientLayout_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/gradients/GrGradientShader.h" #include "src/shaders/gradients/SkLinearGradient.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrLinearGradientLayout : public GrFragmentProcessor { public: static std::unique_ptr<GrFragmentProcessor> Make(const SkLinearGradient& gradient, diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.cpp index ecf6e742233..c17f77a3c48 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.cpp +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.cpp @@ -27,8 +27,11 @@ public: (void)gradientMatrix; SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D( args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix()); - fragBuilder->codeAppendf("half t = half(length(%s));\n%s = half4(t, 1.0, 0.0, 0.0);\n", - sk_TransformedCoords2D_0.c_str(), args.fOutputColor); + fragBuilder->codeAppendf( + R"SkSL(half t = half(length(%s)); +%s = half4(t, 1.0, 0.0, 0.0); +)SkSL", + sk_TransformedCoords2D_0.c_str(), args.fOutputColor); } private: diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.h index 44be21202e4..897a97f02d2 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.h +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.h @@ -10,14 +10,16 @@ **************************************************************************************************/ #ifndef GrRadialGradientLayout_DEFINED #define GrRadialGradientLayout_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/gradients/GrGradientShader.h" #include "src/shaders/gradients/SkRadialGradient.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrRadialGradientLayout : public GrFragmentProcessor { public: static std::unique_ptr<GrFragmentProcessor> Make(const SkRadialGradient& gradient, diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.cpp index cc4c82289d0..4a524a11f96 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.cpp +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.cpp @@ -32,10 +32,12 @@ public: kHalf4_GrSLType, "start"); endVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf4_GrSLType, "end"); - fragBuilder->codeAppendf("half t = %s.x;\n%s = (1.0 - t) * %s + t * %s;\n", - args.fInputColor, args.fOutputColor, - args.fUniformHandler->getUniformCStr(startVar), - args.fUniformHandler->getUniformCStr(endVar)); + fragBuilder->codeAppendf( + R"SkSL(half t = %s.x; +%s = (1.0 - t) * %s + t * %s; +)SkSL", + args.fInputColor, args.fOutputColor, args.fUniformHandler->getUniformCStr(startVar), + args.fUniformHandler->getUniformCStr(endVar)); } private: diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.h index 2c808102c9d..a8cd30feea1 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.h +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.h @@ -10,11 +10,13 @@ **************************************************************************************************/ #ifndef GrSingleIntervalGradientColorizer_DEFINED #define GrSingleIntervalGradientColorizer_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrSingleIntervalGradientColorizer : public GrFragmentProcessor { public: static std::unique_ptr<GrFragmentProcessor> Make(SkPMColor4f start, SkPMColor4f end) { diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.cpp index cd4653a75ea..0776671193d 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.cpp +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.cpp @@ -36,10 +36,15 @@ public: SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D( args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix()); fragBuilder->codeAppendf( - "half angle;\nif (sk_Caps.atan2ImplementedAsAtanYOverX) {\n angle = half(2.0 * " - "atan(-%s.y, length(%s) - %s.x));\n} else {\n angle = half(atan(-%s.y, " - "-%s.x));\n}\nhalf t = ((angle * 0.15915493667125702 + 0.5) + %s) * %s;\n%s = " - "half4(t, 1.0, 0.0, 0.0);\n", + R"SkSL(half angle; +if (sk_Caps.atan2ImplementedAsAtanYOverX) { + angle = half(2.0 * atan(-%s.y, length(%s) - %s.x)); +} else { + angle = half(atan(-%s.y, -%s.x)); +} +half t = ((angle * 0.15915493667125702 + 0.5) + %s) * %s; +%s = half4(t, 1.0, 0.0, 0.0); +)SkSL", sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str(), args.fUniformHandler->getUniformCStr(biasVar), diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.h index ef7a2ea4918..b547ec1db98 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.h +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.h @@ -10,14 +10,16 @@ **************************************************************************************************/ #ifndef GrSweepGradientLayout_DEFINED #define GrSweepGradientLayout_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/gradients/GrGradientShader.h" #include "src/shaders/gradients/SkSweepGradient.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrSweepGradientLayout : public GrFragmentProcessor { public: static std::unique_ptr<GrFragmentProcessor> Make(const SkSweepGradient& gradient, diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.cpp index f2b079145de..c2f05339732 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.cpp +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.cpp @@ -24,13 +24,15 @@ public: const GrTextureGradientColorizer& _outer = args.fFp.cast<GrTextureGradientColorizer>(); (void)_outer; fragBuilder->codeAppendf( - "half2 coord = half2(%s.x, 0.5);\n%s = sample(%s, float2(coord)).%s;\n", - args.fInputColor, args.fOutputColor, - fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]), - fragBuilder->getProgramBuilder() - ->samplerSwizzle(args.fTexSamplers[0]) - .asString() - .c_str()); + R"SkSL(half2 coord = half2(%s.x, 0.5);)SkSL", args.fInputColor); + SkString _sample327; + SkString _coords327("float2(coord)"); + _sample327 = this->invokeChild(_outer.textureFP_index, args, _coords327.c_str()); + fragBuilder->codeAppendf( + R"SkSL( +%s = %s; +)SkSL", + args.fOutputColor, _sample327.c_str()); } private: @@ -45,18 +47,15 @@ void GrTextureGradientColorizer::onGetGLSLProcessorKey(const GrShaderCaps& caps, bool GrTextureGradientColorizer::onIsEqual(const GrFragmentProcessor& other) const { const GrTextureGradientColorizer& that = other.cast<GrTextureGradientColorizer>(); (void)that; - if (gradient != that.gradient) return false; return true; } GrTextureGradientColorizer::GrTextureGradientColorizer(const GrTextureGradientColorizer& src) - : INHERITED(kGrTextureGradientColorizer_ClassID, src.optimizationFlags()) - , gradient(src.gradient) { - this->setTextureSamplerCnt(1); + : INHERITED(kGrTextureGradientColorizer_ClassID, src.optimizationFlags()) { + { + textureFP_index = + this->cloneAndRegisterChildProcessor(src.childProcessor(src.textureFP_index)); + } } std::unique_ptr<GrFragmentProcessor> GrTextureGradientColorizer::clone() const { return std::unique_ptr<GrFragmentProcessor>(new GrTextureGradientColorizer(*this)); } -const GrFragmentProcessor::TextureSampler& GrTextureGradientColorizer::onTextureSampler( - int index) const { - return IthTextureSampler(index, gradient); -} diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.h index 0672b9fdf0d..b49637ac8f4 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.h +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.h @@ -10,32 +10,34 @@ **************************************************************************************************/ #ifndef GrTextureGradientColorizer_DEFINED #define GrTextureGradientColorizer_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrTextureGradientColorizer : public GrFragmentProcessor { public: - static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView gradient) { + static std::unique_ptr<GrFragmentProcessor> Make( + std::unique_ptr<GrFragmentProcessor> textureFP) { return std::unique_ptr<GrFragmentProcessor>( - new GrTextureGradientColorizer(std::move(gradient))); + new GrTextureGradientColorizer(std::move(textureFP))); } GrTextureGradientColorizer(const GrTextureGradientColorizer& src); std::unique_ptr<GrFragmentProcessor> clone() const override; const char* name() const override { return "TextureGradientColorizer"; } - TextureSampler gradient; + int textureFP_index = -1; private: - GrTextureGradientColorizer(GrSurfaceProxyView gradient) - : INHERITED(kGrTextureGradientColorizer_ClassID, kNone_OptimizationFlags) - , gradient(std::move(gradient), GrSamplerState::Filter::kBilerp) { - this->setTextureSamplerCnt(1); + GrTextureGradientColorizer(std::unique_ptr<GrFragmentProcessor> textureFP) + : INHERITED(kGrTextureGradientColorizer_ClassID, kNone_OptimizationFlags) { + SkASSERT(textureFP); + textureFP_index = this->registerExplicitlySampledChild(std::move(textureFP)); } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; bool onIsEqual(const GrFragmentProcessor&) const override; - const TextureSampler& onTextureSampler(int) const override; GR_DECLARE_FRAGMENT_PROCESSOR_TEST typedef GrFragmentProcessor INHERITED; }; diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.cpp index 248e7f9303d..3d9dc96d92c 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.cpp +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.cpp @@ -32,11 +32,20 @@ public: SkString _sample453; _sample453 = this->invokeChild(_outer.gradLayout_index, args); fragBuilder->codeAppendf( - "half4 t = %s;\nif (!%s && t.y < 0.0) {\n %s = half4(0.0);\n} else {\n @if " - "(%s) {\n half t_1 = t.x - 1.0;\n half tiled_t = (t_1 - 2.0 * " - "floor(t_1 * 0.5)) - 1.0;\n if (sk_Caps.mustDoOpBetweenFloorAndAbs) {\n " - " tiled_t = clamp(tiled_t, -1.0, 1.0);\n }\n t.x = " - "abs(tiled_t);\n } else {\n t.x = fract(t.x);\n }", + R"SkSL(half4 t = %s; +if (!%s && t.y < 0.0) { + %s = half4(0.0); +} else { + @if (%s) { + half t_1 = t.x - 1.0; + half tiled_t = (t_1 - 2.0 * floor(t_1 * 0.5)) - 1.0; + if (sk_Caps.mustDoOpBetweenFloorAndAbs) { + tiled_t = clamp(tiled_t, -1.0, 1.0); + } + t.x = abs(tiled_t); + } else { + t.x = fract(t.x); + })SkSL", _sample453.c_str(), (_outer.childProcessor(_outer.gradLayout_index).preservesOpaqueInput() ? "true" : "false"), @@ -44,10 +53,16 @@ public: SkString _input1464("t"); SkString _sample1464; _sample1464 = this->invokeChild(_outer.colorizer_index, _input1464.c_str(), args); - fragBuilder->codeAppendf("\n %s = %s;\n}\n@if (%s) {\n %s.xyz *= %s.w;\n}\n", - args.fOutputColor, _sample1464.c_str(), - (_outer.makePremul ? "true" : "false"), args.fOutputColor, - args.fOutputColor); + fragBuilder->codeAppendf( + R"SkSL( + %s = %s; +} +@if (%s) { + %s.xyz *= %s.w; +} +)SkSL", + args.fOutputColor, _sample1464.c_str(), (_outer.makePremul ? "true" : "false"), + args.fOutputColor, args.fOutputColor); } private: @@ -72,24 +87,16 @@ bool GrTiledGradientEffect::onIsEqual(const GrFragmentProcessor& other) const { } GrTiledGradientEffect::GrTiledGradientEffect(const GrTiledGradientEffect& src) : INHERITED(kGrTiledGradientEffect_ClassID, src.optimizationFlags()) - , colorizer_index(src.colorizer_index) - , gradLayout_index(src.gradLayout_index) , mirror(src.mirror) , makePremul(src.makePremul) , colorsAreOpaque(src.colorsAreOpaque) { { - auto clone = src.childProcessor(colorizer_index).clone(); - if (src.childProcessor(colorizer_index).isSampledWithExplicitCoords()) { - clone->setSampledWithExplicitCoords(); - } - this->registerChildProcessor(std::move(clone)); + colorizer_index = + this->cloneAndRegisterChildProcessor(src.childProcessor(src.colorizer_index)); } { - auto clone = src.childProcessor(gradLayout_index).clone(); - if (src.childProcessor(gradLayout_index).isSampledWithExplicitCoords()) { - clone->setSampledWithExplicitCoords(); - } - this->registerChildProcessor(std::move(clone)); + gradLayout_index = + this->cloneAndRegisterChildProcessor(src.childProcessor(src.gradLayout_index)); } } std::unique_ptr<GrFragmentProcessor> GrTiledGradientEffect::clone() const { diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.h index d22d1c61106..4fbf2d3b264 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.h +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.h @@ -10,11 +10,13 @@ **************************************************************************************************/ #ifndef GrTiledGradientEffect_DEFINED #define GrTiledGradientEffect_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrTiledGradientEffect : public GrFragmentProcessor { public: static std::unique_ptr<GrFragmentProcessor> Make( @@ -50,11 +52,9 @@ private: , makePremul(makePremul) , colorsAreOpaque(colorsAreOpaque) { SkASSERT(colorizer); - colorizer_index = this->numChildProcessors(); - this->registerChildProcessor(std::move(colorizer)); + colorizer_index = this->registerChild(std::move(colorizer)); SkASSERT(gradLayout); - gradLayout_index = this->numChildProcessors(); - this->registerChildProcessor(std::move(gradLayout)); + gradLayout_index = this->registerChild(std::move(gradLayout)); } GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.cpp index 2f80228e6a1..fa172c76c29 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.cpp +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.cpp @@ -45,48 +45,90 @@ public: SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D( args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix()); fragBuilder->codeAppendf( - "float2 p = %s;\nfloat t = -1.0;\nhalf v = 1.0;\n@switch (%d) {\n case 1:\n " - " {\n half r0_2 = %s.y;\n t = float(r0_2) - p.y * p.y;\n " - " if (t >= 0.0) {\n t = p.x + sqrt(t);\n } else " - "{\n v = -1.0;\n }\n }\n break;\n case " - "0:\n {\n half r0 = %s.x;\n @if (%s) {\n " - " t = length(p) - float(r0);\n } else {\n t = " - "-length(p) - float(r0);\n ", + R"SkSL(float2 p = %s; +float t = -1.0; +half v = 1.0; +@switch (%d) { + case 1: + { + half r0_2 = %s.y; + t = float(r0_2) - p.y * p.y; + if (t >= 0.0) { + t = p.x + sqrt(t); + } else { + v = -1.0; + } + } + break; + case 0: + { + half r0 = %s.x; + @if (%s) { + t = length(p) - float(r0); + } else { + t = -length(p) - float(r0); + } + } + break; + case 2: + { + half invR1 = %s.x; + half fx = %s.y; + float x_t = -1.0; + @if (%s) { + x_t = dot(p, p) / p.x; + } else if (%s) { + x_t = length(p) - p.x * float(invR1); + } else { + float temp = p.x * p.x - p.y * p.y; + if (temp >= 0.0) { + @if (%s || !%s) { + x_t = -sqrt(temp) - p.x * float(invR1); + } else { + x_t = sqrt(temp) - p.x * float(invR1); + } + } + } + @if (!%s) { + if (x_t <= 0.0) { + v = -1.0; + } + } + @if (%s) { + @if (%s) { + t = x_t; + } else { + t = x_t + float(fx); + } + } else { + @if (%s) { + t = -x_t; + } else { + t = -x_t + float(fx); + } + } + @if (%s) { + t = 1.0 - t; + } + } + break; +} +%s = half4(half(t), v, 0.0, 0.0); +)SkSL", sk_TransformedCoords2D_0.c_str(), (int)_outer.type, args.fUniformHandler->getUniformCStr(focalParamsVar), args.fUniformHandler->getUniformCStr(focalParamsVar), - (_outer.isRadiusIncreasing ? "true" : "false")); - fragBuilder->codeAppendf( - " }\n }\n break;\n case 2:\n {\n half invR1 " - "= %s.x;\n half fx = %s.y;\n float x_t = -1.0;\n " - "@if (%s) {\n x_t = dot(p, p) / p.x;\n } else if (%s) " - "{\n x_t = length(p) - p.x * float(invR1);\n } else {\n " - " float temp = p.x * p.x - p.y * p.y;\n if (temp >= " - "0.0) {\n @if (%s || !%s) {\n x_t = " - "-sqrt(temp) - p.x * float(invR1)", + (_outer.isRadiusIncreasing ? "true" : "false"), args.fUniformHandler->getUniformCStr(focalParamsVar), args.fUniformHandler->getUniformCStr(focalParamsVar), (_outer.isFocalOnCircle ? "true" : "false"), (_outer.isWellBehaved ? "true" : "false"), (_outer.isSwapped ? "true" : "false"), - (_outer.isRadiusIncreasing ? "true" : "false")); - fragBuilder->codeAppendf( - ";\n } else {\n x_t = sqrt(temp) - p.x * " - "float(invR1);\n }\n }\n }\n " - " @if (!%s) {\n if (x_t <= 0.0) {\n v = -1.0;\n " - " }\n }\n @if (%s) {\n @if (%s) " - "{\n t = x_t;\n } else {\n t " - "= x_t + float(fx);\n }\n } else {\n @if " - "(%s) {\n ", + (_outer.isRadiusIncreasing ? "true" : "false"), (_outer.isWellBehaved ? "true" : "false"), (_outer.isRadiusIncreasing ? "true" : "false"), (_outer.isNativelyFocal ? "true" : "false"), - (_outer.isNativelyFocal ? "true" : "false")); - fragBuilder->codeAppendf( - " t = -x_t;\n } else {\n t = -x_t + " - "float(fx);\n }\n }\n @if (%s) {\n " - " t = 1.0 - t;\n }\n }\n break;\n}\n%s = " - "half4(half(t), v, 0.0, 0.0);\n", - (_outer.isSwapped ? "true" : "false"), args.fOutputColor); + (_outer.isNativelyFocal ? "true" : "false"), (_outer.isSwapped ? "true" : "false"), + args.fOutputColor); } private: diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.h index 4a08aea9831..afd93db24f3 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.h +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.h @@ -10,14 +10,16 @@ **************************************************************************************************/ #ifndef GrTwoPointConicalGradientLayout_DEFINED #define GrTwoPointConicalGradientLayout_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/gradients/GrGradientShader.h" #include "src/shaders/gradients/SkTwoPointConicalGradient.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrTwoPointConicalGradientLayout : public GrFragmentProcessor { public: enum class Type { kFocal = 2, kRadial = 0, kStrip = 1 }; diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.cpp index 3f5c5aca95d..38368dbb505 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.cpp +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.cpp @@ -127,13 +127,47 @@ public: thresholds9_13Var = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf4_GrSLType, "thresholds9_13"); fragBuilder->codeAppendf( - "half t = %s.x;\nfloat4 scale, bias;\nif (%d <= 4 || t < %s.w) {\n if (%d <= 2 " - "|| t < %s.y) {\n if (%d <= 1 || t < %s.x) {\n scale = %s;\n " - " bias = %s;\n } else {\n scale = %s;\n bias = " - "%s;\n }\n } else {\n if (%d <= 3 || t < %s.z) {\n " - "scale = %s;\n bias = %s;\n } else {\n scale = %s;\n " - " bias = %s;\n }\n }\n} else {\n if (%d <= 6 || t < %s.y) " - "{\n if (%d <= 5 || t <", + R"SkSL(half t = %s.x; +float4 scale, bias; +if (%d <= 4 || t < %s.w) { + if (%d <= 2 || t < %s.y) { + if (%d <= 1 || t < %s.x) { + scale = %s; + bias = %s; + } else { + scale = %s; + bias = %s; + } + } else { + if (%d <= 3 || t < %s.z) { + scale = %s; + bias = %s; + } else { + scale = %s; + bias = %s; + } + } +} else { + if (%d <= 6 || t < %s.y) { + if (%d <= 5 || t < %s.x) { + scale = %s; + bias = %s; + } else { + scale = %s; + bias = %s; + } + } else { + if (%d <= 7 || t < %s.z) { + scale = %s; + bias = %s; + } else { + scale = %s; + bias = %s; + } + } +} +%s = half4(float(t) * scale + bias); +)SkSL", args.fInputColor, _outer.intervalCount, args.fUniformHandler->getUniformCStr(thresholds1_7Var), _outer.intervalCount, args.fUniformHandler->getUniformCStr(thresholds1_7Var), _outer.intervalCount, @@ -154,14 +188,7 @@ public: bias6_7Var.isValid() ? args.fUniformHandler->getUniformCStr(bias6_7Var) : "float4(0)", _outer.intervalCount, args.fUniformHandler->getUniformCStr(thresholds9_13Var), - _outer.intervalCount); - fragBuilder->codeAppendf( - " %s.x) {\n scale = %s;\n bias = %s;\n } else {\n " - " scale = %s;\n bias = %s;\n }\n } else {\n if " - "(%d <= 7 || t < %s.z) {\n scale = %s;\n bias = %s;\n " - "} else {\n scale = %s;\n bias = %s;\n }\n " - "}\n}\n%s = half4(float(t) * scale + bias);\n", - args.fUniformHandler->getUniformCStr(thresholds9_13Var), + _outer.intervalCount, args.fUniformHandler->getUniformCStr(thresholds9_13Var), scale8_9Var.isValid() ? args.fUniformHandler->getUniformCStr(scale8_9Var) : "float4(0)", bias8_9Var.isValid() ? args.fUniformHandler->getUniformCStr(bias8_9Var) diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.h index 9c9ecea611f..144cd8c0447 100644 --- a/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.h +++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.h @@ -10,11 +10,13 @@ **************************************************************************************************/ #ifndef GrUnrolledBinaryGradientColorizer_DEFINED #define GrUnrolledBinaryGradientColorizer_DEFINED -#include "include/core/SkTypes.h" + #include "include/core/SkM44.h" +#include "include/core/SkTypes.h" #include "src/gpu/GrCoordTransform.h" #include "src/gpu/GrFragmentProcessor.h" + class GrUnrolledBinaryGradientColorizer : public GrFragmentProcessor { public: static const int kMaxColorCount = 16; diff --git a/chromium/third_party/skia/src/gpu/mock/GrMockCaps.h b/chromium/third_party/skia/src/gpu/mock/GrMockCaps.h index 42a97144593..6548aa634ba 100644 --- a/chromium/third_party/skia/src/gpu/mock/GrMockCaps.h +++ b/chromium/third_party/skia/src/gpu/mock/GrMockCaps.h @@ -35,7 +35,7 @@ public: fShaderCaps->fShaderDerivativeSupport = options.fShaderDerivativeSupport; fShaderCaps->fDualSourceBlendingSupport = options.fDualSourceBlendingSupport; fShaderCaps->fSampleMaskSupport = true; - fShaderCaps->fTessellationSupport = options.fTessellationSupport; + fShaderCaps->fMaxTessellationSegments = options.fMaxTessellationSegments; this->finishInitialization(contextOptions); } @@ -50,10 +50,6 @@ public: return GrGetColorTypeDesc(ct).encoding() == GrColorTypeEncoding::kSRGBUnorm; } - SkImage::CompressionType compressionType(const GrBackendFormat& format) const override { - return format.asMockCompressionType(); - } - bool isFormatTexturable(const GrBackendFormat& format) const override { SkImage::CompressionType compression = format.asMockCompressionType(); if (compression != SkImage::CompressionType::kNone) { @@ -155,10 +151,6 @@ public: return {}; } - GrSwizzle getReadSwizzle(const GrBackendFormat& format, GrColorType ct) const override { - SkASSERT(this->areColorTypeAndFormatCompatible(ct, format)); - return GrSwizzle("rgba"); - } GrSwizzle getWriteSwizzle(const GrBackendFormat& format, GrColorType ct) const override { SkASSERT(this->areColorTypeAndFormatCompatible(ct, format)); return GrSwizzle("rgba"); @@ -205,6 +197,11 @@ private: return SupportedRead{srcColorType, 1}; } + GrSwizzle onGetReadSwizzle(const GrBackendFormat& format, GrColorType ct) const override { + SkASSERT(this->areColorTypeAndFormatCompatible(ct, format)); + return GrSwizzle("rgba"); + } + static const int kMaxSampleCnt = 16; GrMockOptions fOptions; diff --git a/chromium/third_party/skia/src/gpu/mock/GrMockGpu.cpp b/chromium/third_party/skia/src/gpu/mock/GrMockGpu.cpp index 3348c4bbdb7..ccd1157cf89 100644 --- a/chromium/third_party/skia/src/gpu/mock/GrMockGpu.cpp +++ b/chromium/third_party/skia/src/gpu/mock/GrMockGpu.cpp @@ -53,7 +53,8 @@ sk_sp<GrGpu> GrMockGpu::Make(const GrMockOptions* mockOptions, } GrOpsRenderPass* GrMockGpu::getOpsRenderPass( - GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds, + GrRenderTarget* rt, GrStencilAttachment*, + GrSurfaceOrigin origin, const SkIRect& bounds, const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, const GrOpsRenderPass::StencilLoadAndStoreInfo&, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) { diff --git a/chromium/third_party/skia/src/gpu/mock/GrMockGpu.h b/chromium/third_party/skia/src/gpu/mock/GrMockGpu.h index 05fdda7599a..29dda81d2b3 100644 --- a/chromium/third_party/skia/src/gpu/mock/GrMockGpu.h +++ b/chromium/third_party/skia/src/gpu/mock/GrMockGpu.h @@ -25,7 +25,10 @@ public: ~GrMockGpu() override {} GrOpsRenderPass* getOpsRenderPass( - GrRenderTarget*, GrSurfaceOrigin, const SkIRect&, + GrRenderTarget*, + GrStencilAttachment*, + GrSurfaceOrigin, + const SkIRect&, const GrOpsRenderPass::LoadAndStoreInfo&, const GrOpsRenderPass::StencilLoadAndStoreInfo&, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override; diff --git a/chromium/third_party/skia/src/gpu/mock/GrMockOpsRenderPass.h b/chromium/third_party/skia/src/gpu/mock/GrMockOpsRenderPass.h index 5a45a3e9713..703eac21333 100644 --- a/chromium/third_party/skia/src/gpu/mock/GrMockOpsRenderPass.h +++ b/chromium/third_party/skia/src/gpu/mock/GrMockOpsRenderPass.h @@ -45,8 +45,10 @@ private: void onDrawIndexedInstanced(int, int, int, int, int) override { this->dummyDraw(); } void onDrawIndirect(const GrBuffer*, size_t, int) override { this->dummyDraw(); } void onDrawIndexedIndirect(const GrBuffer*, size_t, int) override { this->dummyDraw(); } - void onClear(const GrFixedClip&, const SkPMColor4f&) override { this->markRenderTargetDirty(); } - void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) override {} + void onClear(const GrScissorState& scissor, const SkPMColor4f&) override { + this->markRenderTargetDirty(); + } + void onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) override {} void dummyDraw() { this->markRenderTargetDirty(); ++fNumDraws; diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.h b/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.h index 09ae534a9b6..0650c5a9b61 100644 --- a/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.h +++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.h @@ -27,7 +27,6 @@ public: MTLFeatureSet featureSet); bool isFormatSRGB(const GrBackendFormat&) const override; - SkImage::CompressionType compressionType(const GrBackendFormat&) const override; bool isFormatTexturable(const GrBackendFormat&) const override; bool isFormatTexturable(MTLPixelFormat) const; @@ -82,7 +81,6 @@ public: return fColorTypeToFormatTable[idx]; } - GrSwizzle getReadSwizzle(const GrBackendFormat&, GrColorType) const override; GrSwizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override; uint64_t computeFormatKey(const GrBackendFormat&) const override; @@ -113,6 +111,8 @@ private: SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&, GrColorType) const override; + GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override; + // ColorTypeInfo for a specific format struct ColorTypeInfo { GrColorType fColorType = GrColorType::kUnknown; diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.mm b/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.mm index 4b28bf7034b..2fb81021f4e 100644 --- a/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.mm +++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.mm @@ -10,6 +10,7 @@ #include "include/core/SkRect.h" #include "include/gpu/GrBackendSurface.h" #include "src/core/SkCompressedDataUtils.h" +#include "src/gpu/GrBackendUtils.h" #include "src/gpu/GrProcessor.h" #include "src/gpu/GrProgramDesc.h" #include "src/gpu/GrProgramInfo.h" @@ -318,24 +319,6 @@ bool GrMtlCaps::isFormatSRGB(const GrBackendFormat& format) const { return format_is_srgb(GrBackendFormatAsMTLPixelFormat(format)); } -SkImage::CompressionType GrMtlCaps::compressionType(const GrBackendFormat& format) const { - - switch (GrBackendFormatAsMTLPixelFormat(format)) { -#ifdef SK_BUILD_FOR_IOS - case MTLPixelFormatETC2_RGB8: - // ETC2 uses the same compression layout as ETC1 - return SkImage::CompressionType::kETC2_RGB8_UNORM; -#else - case MTLPixelFormatBC1_RGBA: - return SkImage::CompressionType::kBC1_RGBA8_UNORM; -#endif - default: - return SkImage::CompressionType::kNone; - } - - SkUNREACHABLE; -} - bool GrMtlCaps::isFormatTexturable(const GrBackendFormat& format) const { MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format); return this->isFormatTexturable(mtlFormat); @@ -900,12 +883,6 @@ bool GrMtlCaps::onAreColorTypeAndFormatCompatible(GrColorType ct, const GrBackendFormat& format) const { MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format); - SkImage::CompressionType compression = GrMtlFormatToCompressionType(mtlFormat); - if (compression != SkImage::CompressionType::kNone) { - return ct == (SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x - : GrColorType::kRGBA_8888); - } - const auto& info = this->getFormatInfo(mtlFormat); for (int i = 0; i < info.fColorTypeInfoCount; ++i) { if (info.fColorTypeInfos[i].fColorType == ct) { @@ -948,7 +925,7 @@ GrBackendFormat GrMtlCaps::getBackendFormatFromCompressionType( SK_ABORT("Invalid compression type"); } -GrSwizzle GrMtlCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const { +GrSwizzle GrMtlCaps::onGetReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const { MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format); SkASSERT(mtlFormat != MTLPixelFormatInvalid); const auto& info = this->getFormatInfo(mtlFormat); @@ -1008,9 +985,7 @@ GrCaps::SupportedWrite GrMtlCaps::supportedWritePixelsColorType( GrCaps::SupportedRead GrMtlCaps::onSupportedReadPixelsColorType( GrColorType srcColorType, const GrBackendFormat& srcBackendFormat, GrColorType dstColorType) const { - MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(srcBackendFormat); - - SkImage::CompressionType compression = GrMtlFormatToCompressionType(mtlFormat); + SkImage::CompressionType compression = GrBackendFormatToCompressionType(srcBackendFormat); if (compression != SkImage::CompressionType::kNone) { #ifdef SK_BUILD_FOR_IOS // Reading back to kRGB_888x doesn't work on Metal/iOS (skbug.com/9839) @@ -1024,6 +999,7 @@ GrCaps::SupportedRead GrMtlCaps::onSupportedReadPixelsColorType( // Metal requires the destination offset for copyFromTexture to be a multiple of the textures // pixels size. size_t offsetAlignment = GrColorTypeBytesPerPixel(srcColorType); + MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(srcBackendFormat); const auto& info = this->getFormatInfo(mtlFormat); for (int i = 0; i < info.fColorTypeInfoCount; ++i) { diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlCppUtil.h b/chromium/third_party/skia/src/gpu/mtl/GrMtlCppUtil.h index f431ec81076..bcbdbdd4b14 100644 --- a/chromium/third_party/skia/src/gpu/mtl/GrMtlCppUtil.h +++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlCppUtil.h @@ -8,14 +8,19 @@ #ifndef GrMtlCppUtil_DEFINED #define GrMtlCppUtil_DEFINED +#include "include/core/SkImage.h" #include "include/gpu/mtl/GrMtlTypes.h" +class GrBackendFormat; + // Utilities that can be used from cpp files (rather than .mm). GrMTLPixelFormat GrGetMTLPixelFormatFromMtlTextureInfo(const GrMtlTextureInfo&); uint32_t GrMtlFormatChannels(GrMTLPixelFormat); +SkImage::CompressionType GrMtlBackendFormatToCompressionType(const GrBackendFormat& format); + #if GR_TEST_UTILS const char* GrMtlFormatToStr(GrMTLPixelFormat mtlFormat); bool GrMtlFormatIsBGRA8(GrMTLPixelFormat mtlFormat); diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.h b/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.h index 191c0bacf37..16bd0fe8442 100644 --- a/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.h +++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.h @@ -68,6 +68,10 @@ public: void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override; void testingOnly_flushGpuAndSync() override; + + void resetShaderCacheForTesting() const override { + fResourceProvider.resetShaderCacheForTesting(); + } #endif void copySurfaceAsResolve(GrSurface* dst, GrSurface* src); @@ -79,7 +83,8 @@ public: const SkIPoint& dstPoint) override; GrOpsRenderPass* getOpsRenderPass( - GrRenderTarget*, GrSurfaceOrigin, const SkIRect& bounds, + GrRenderTarget*, GrStencilAttachment*, + GrSurfaceOrigin, const SkIRect& bounds, const GrOpsRenderPass::LoadAndStoreInfo&, const GrOpsRenderPass::StencilLoadAndStoreInfo&, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override; diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.mm b/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.mm index 420bb896679..dced04f7b58 100644 --- a/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.mm +++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.mm @@ -11,6 +11,7 @@ #include "src/core/SkCompressedDataUtils.h" #include "src/core/SkConvertPixels.h" #include "src/core/SkMipMap.h" +#include "src/gpu/GrBackendUtils.h" #include "src/gpu/GrDataUtils.h" #include "src/gpu/GrRenderTargetPriv.h" #include "src/gpu/GrTexturePriv.h" @@ -159,7 +160,8 @@ void GrMtlGpu::destroyResources() { } GrOpsRenderPass* GrMtlGpu::getOpsRenderPass( - GrRenderTarget* renderTarget, GrSurfaceOrigin origin, const SkIRect& bounds, + GrRenderTarget* renderTarget, GrStencilAttachment*, + GrSurfaceOrigin origin, const SkIRect& bounds, const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) { @@ -545,7 +547,7 @@ sk_sp<GrTexture> GrMtlGpu::onCreateCompressedTexture(SkISize dimensions, id<MTLTexture> mtlTexture = tex->mtlTexture(); SkASSERT(mtlTexture); - auto compressionType = GrMtlFormatToCompressionType(mtlTexture.pixelFormat); + auto compressionType = GrBackendFormatToCompressionType(format); SkASSERT(compressionType != SkImage::CompressionType::kNone); SkTArray<size_t> individualMipOffsets(numMipLevels); @@ -844,7 +846,8 @@ bool GrMtlGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture, int numMipLevels = mtlTexture.mipmapLevelCount; GrMipMapped mipMapped = numMipLevels > 1 ? GrMipMapped::kYes : GrMipMapped::kNo; - SkImage::CompressionType compression = GrMtlFormatToCompressionType(mtlFormat); + SkImage::CompressionType compression = GrBackendFormatToCompressionType( + backendTexture.getBackendFormat()); // Create a transfer buffer and fill with data. SkSTArray<16, size_t> individualMipOffsets; @@ -1349,6 +1352,7 @@ std::unique_ptr<GrSemaphore> GrMtlGpu::wrapBackendSemaphore( void GrMtlGpu::insertSemaphore(GrSemaphore* semaphore) { if (@available(macOS 10.14, iOS 12.0, *)) { + SkASSERT(semaphore); GrMtlSemaphore* mtlSem = static_cast<GrMtlSemaphore*>(semaphore); this->commandBuffer()->encodeSignalEvent(mtlSem->event(), mtlSem->value()); @@ -1357,6 +1361,7 @@ void GrMtlGpu::insertSemaphore(GrSemaphore* semaphore) { void GrMtlGpu::waitSemaphore(GrSemaphore* semaphore) { if (@available(macOS 10.14, iOS 12.0, *)) { + SkASSERT(semaphore); GrMtlSemaphore* mtlSem = static_cast<GrMtlSemaphore*>(semaphore); this->commandBuffer()->encodeWaitForEvent(mtlSem->event(), mtlSem->value()); diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.h b/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.h index 77229ce8487..c4cf385ef0d 100644 --- a/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.h +++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.h @@ -49,9 +49,9 @@ private: void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance, int baseVertex) override; - void onClear(const GrFixedClip& clip, const SkPMColor4f& color) override; + void onClear(const GrScissorState& scissor, const SkPMColor4f& color) override; - void onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) override; + void onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) override; void setupRenderPass(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo); @@ -80,4 +80,3 @@ private: }; #endif - diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.mm b/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.mm index 576a1349c3b..13ef3a3bce8 100644 --- a/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.mm +++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.mm @@ -8,7 +8,6 @@ #include "src/gpu/mtl/GrMtlOpsRenderPass.h" #include "src/gpu/GrColor.h" -#include "src/gpu/GrFixedClip.h" #include "src/gpu/GrRenderTargetPriv.h" #include "src/gpu/mtl/GrMtlCommandBuffer.h" #include "src/gpu/mtl/GrMtlPipelineState.h" @@ -123,7 +122,10 @@ bool GrMtlOpsRenderPass::onBindTextures(const GrPrimitiveProcessor& primProc, return true; } -void GrMtlOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& color) { +void GrMtlOpsRenderPass::onClear(const GrScissorState& scissor, const SkPMColor4f& color) { + // Partial clears are not supported + SkASSERT(!scissor.enabled()); + // Ideally we should never end up here since all clears should either be done as draws or // load ops in metal. However, if a client inserts a wait op we need to handle it. fRenderPassDesc.colorAttachments[0].clearColor = @@ -135,8 +137,9 @@ void GrMtlOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& col fGpu->commandBuffer()->getRenderCommandEncoder(fRenderPassDesc, nullptr, this); } -void GrMtlOpsRenderPass::onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) { - SkASSERT(!clip.hasWindowRectangles()); +void GrMtlOpsRenderPass::onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) { + // Partial clears are not supported + SkASSERT(!scissor.enabled()); GrStencilAttachment* sb = fRenderTarget->renderTargetPriv().getStencilAttachment(); // this should only be called internally when we know we have a diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.h b/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.h index cd1d1021523..eed06eb2c54 100644 --- a/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.h +++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.h @@ -21,7 +21,7 @@ class GrProgramInfo; class GrMtlCaps; class GrMtlGpu; class GrMtlPipelineState; -class SkReader32; +class SkReadBuffer; class GrMtlPipelineStateBuilder : public GrGLSLProgramBuilder { public: @@ -58,7 +58,7 @@ private: SkSL::Program::Inputs inputs); void storeShadersInCache(const SkSL::String shaders[], const SkSL::Program::Inputs inputs[], bool isSkSL); - void loadShadersFromCache(SkReader32* cached, __strong id<MTLLibrary> outLibraries[]); + bool loadShadersFromCache(SkReadBuffer* cached, __strong id<MTLLibrary> outLibraries[]); GrGLSLUniformHandler* uniformHandler() override { return &fUniformHandler; } const GrGLSLUniformHandler* uniformHandler() const override { return &fUniformHandler; } diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.mm b/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.mm index 3c2c91bb039..0bfd4ee7976 100644 --- a/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.mm +++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.mm @@ -8,7 +8,7 @@ #include "src/gpu/mtl/GrMtlPipelineStateBuilder.h" #include "include/gpu/GrContext.h" -#include "src/core/SkReader32.h" +#include "src/core/SkReadBuffer.h" #include "src/core/SkTraceEvent.h" #include "src/gpu/GrAutoLocaleSetter.h" #include "src/gpu/GrContextPriv.h" @@ -66,12 +66,14 @@ static constexpr SkFourByteTag kMSL_Tag = SkSetFourByteTag('M', 'S', 'L', ' '); static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L'); -void GrMtlPipelineStateBuilder::loadShadersFromCache(SkReader32* cached, +bool GrMtlPipelineStateBuilder::loadShadersFromCache(SkReadBuffer* cached, __strong id<MTLLibrary> outLibraries[]) { SkSL::String shaders[kGrShaderTypeCount]; SkSL::Program::Inputs inputs[kGrShaderTypeCount]; - GrPersistentCacheUtils::UnpackCachedShaders(cached, shaders, inputs, kGrShaderTypeCount); + if (!GrPersistentCacheUtils::UnpackCachedShaders(cached, shaders, inputs, kGrShaderTypeCount)) { + return false; + } outLibraries[kVertex_GrShaderType] = this->compileMtlShaderLibrary( shaders[kVertex_GrShaderType], @@ -80,11 +82,9 @@ void GrMtlPipelineStateBuilder::loadShadersFromCache(SkReader32* cached, shaders[kFragment_GrShaderType], inputs[kFragment_GrShaderType]); - // Geometry shaders are not supported - SkASSERT(shaders[kGeometry_GrShaderType].empty()); - - SkASSERT(outLibraries[kVertex_GrShaderType]); - SkASSERT(outLibraries[kFragment_GrShaderType]); + return outLibraries[kVertex_GrShaderType] && + outLibraries[kFragment_GrShaderType] && + shaders[kGeometry_GrShaderType].empty(); // Geometry shaders are not supported } void GrMtlPipelineStateBuilder::storeShadersInCache(const SkSL::String shaders[], @@ -399,7 +399,7 @@ GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(GrRenderTarget* renderTa SkASSERT(!this->fragColorIsInOut()); sk_sp<SkData> cached; - SkReader32 reader; + SkReadBuffer reader; SkFourByteTag shaderType = 0; auto persistentCache = fGpu->getContext()->priv().getPersistentCache(); if (persistentCache) { @@ -414,10 +414,10 @@ GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(GrRenderTarget* renderTa } } - SkSL::String shaders[kGrShaderTypeCount]; - if (kMSL_Tag == shaderType) { - this->loadShadersFromCache(&reader, shaderLibraries); + if (kMSL_Tag == shaderType && this->loadShadersFromCache(&reader, shaderLibraries)) { + // We successfully loaded and compiled MSL } else { + SkSL::String shaders[kGrShaderTypeCount]; SkSL::Program::Inputs inputs[kGrShaderTypeCount]; SkSL::String* sksl[kGrShaderTypeCount] = { @@ -427,10 +427,11 @@ GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(GrRenderTarget* renderTa }; SkSL::String cached_sksl[kGrShaderTypeCount]; if (kSKSL_Tag == shaderType) { - GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, inputs, - kGrShaderTypeCount); - for (int i = 0; i < kGrShaderTypeCount; ++i) { - sksl[i] = &cached_sksl[i]; + if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, inputs, + kGrShaderTypeCount)) { + for (int i = 0; i < kGrShaderTypeCount; ++i) { + sksl[i] = &cached_sksl[i]; + } } } diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlResourceProvider.h b/chromium/third_party/skia/src/gpu/mtl/GrMtlResourceProvider.h index 5d1f213b154..20e6eb29aa1 100644 --- a/chromium/third_party/skia/src/gpu/mtl/GrMtlResourceProvider.h +++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlResourceProvider.h @@ -41,6 +41,10 @@ public: // Destroy any cached resources. To be called before releasing the MtlDevice. void destroyResources(); +#if GR_TEST_UTILS + void resetShaderCacheForTesting() const { fPipelineStateCache->release(); } +#endif + private: #ifdef SK_DEBUG #define GR_PIPELINE_STATE_CACHE_STATS diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlUtil.mm b/chromium/third_party/skia/src/gpu/mtl/GrMtlUtil.mm index c890e4b8991..df519b3037a 100644 --- a/chromium/third_party/skia/src/gpu/mtl/GrMtlUtil.mm +++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlUtil.mm @@ -7,6 +7,7 @@ #include "src/gpu/mtl/GrMtlUtil.h" +#include "include/gpu/GrBackendSurface.h" #include "include/private/GrTypesPriv.h" #include "include/private/SkMutex.h" #include "src/gpu/GrSurface.h" @@ -269,6 +270,12 @@ uint32_t GrMtlFormatChannels(GrMTLPixelFormat mtlFormat) { } } +SkImage::CompressionType GrMtlBackendFormatToCompressionType(const GrBackendFormat& format) { + MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format); + return GrMtlFormatToCompressionType(mtlFormat); +} + + bool GrMtlFormatIsCompressed(MTLPixelFormat mtlFormat) { switch (mtlFormat) { #ifdef SK_BUILD_FOR_IOS diff --git a/chromium/third_party/skia/src/gpu/ops/GrAAConvexPathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrAAConvexPathRenderer.cpp index e427a4a7383..2dc3e1add28 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrAAConvexPathRenderer.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrAAConvexPathRenderer.cpp @@ -213,6 +213,7 @@ static void update_degenerate_test(DegenerateTestData* data, const SkPoint& pt) if (SkScalarAbs(data->fLineNormal.dot(pt) + data->fLineC) > kClose) { data->fStage = DegenerateTestData::kNonDegenerate; } + break; case DegenerateTestData::kNonDegenerate: break; default: @@ -576,14 +577,11 @@ public: // Setup position this->writeOutputPosition(vertBuilder, gpArgs, qe.fInPosition.name()); - - // emit transforms - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - qe.fInPosition.asShaderVar(), - qe.fLocalMatrix, - args.fFPCoordTransformHandler); + if (qe.fUsesLocalCoords) { + this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, + qe.fInPosition.asShaderVar(), qe.fLocalMatrix, + &fLocalMatrixUniform); + } fragBuilder->codeAppendf("half edgeAlpha;"); @@ -610,18 +608,24 @@ public: const GrShaderCaps&, GrProcessorKeyBuilder* b) { const QuadEdgeEffect& qee = gp.cast<QuadEdgeEffect>(); - b->add32(SkToBool(qee.fUsesLocalCoords && qee.fLocalMatrix.hasPerspective())); + uint32_t key = (uint32_t) qee.fUsesLocalCoords; + key |= ComputeMatrixKey(qee.fLocalMatrix) << 1; + b->add32(key); } void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp, const CoordTransformRange& transformRange) override { const QuadEdgeEffect& qe = gp.cast<QuadEdgeEffect>(); - this->setTransformDataHelper(qe.fLocalMatrix, pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); + this->setTransform(pdman, fLocalMatrixUniform, qe.fLocalMatrix, &fLocalMatrix); } private: typedef GrGLSLGeometryProcessor INHERITED; + + SkMatrix fLocalMatrix = SkMatrix::InvalidMatrix(); + UniformHandle fLocalMatrixUniform; }; void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override { @@ -915,7 +919,7 @@ bool GrAAConvexPathRenderer::onDrawPath(const DrawPathArgs& args) { std::unique_ptr<GrDrawOp> op = AAConvexPathOp::Make(args.fContext, std::move(args.fPaint), *args.fViewMatrix, path, args.fUserStencilSettings); - args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op)); + args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op)); return true; } diff --git a/chromium/third_party/skia/src/gpu/ops/GrAAHairLinePathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrAAHairLinePathRenderer.cpp index 537d0f1c62d..b87d2f6a8d6 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrAAHairLinePathRenderer.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrAAHairLinePathRenderer.cpp @@ -15,12 +15,12 @@ #include "src/gpu/GrAuditTrail.h" #include "src/gpu/GrBuffer.h" #include "src/gpu/GrCaps.h" -#include "src/gpu/GrClip.h" #include "src/gpu/GrDefaultGeoProcFactory.h" #include "src/gpu/GrDrawOpTest.h" #include "src/gpu/GrOpFlushState.h" #include "src/gpu/GrProcessor.h" #include "src/gpu/GrProgramInfo.h" +#include "src/gpu/GrRenderTargetContext.h" #include "src/gpu/GrResourceProvider.h" #include "src/gpu/GrStyle.h" #include "src/gpu/effects/GrBezierEffect.h" @@ -1011,7 +1011,6 @@ void AAHairlineOp::makeQuadProgramInfo(const GrCaps& caps, SkArenaAlloc* arena, GrGeometryProcessor* quadGP = GrQuadEffect::Make(arena, this->color(), *geometryProcessorViewM, - GrClipEdgeType::kHairlineAA, caps, *geometryProcessorLocalM, fHelper.usesLocalCoords(), @@ -1034,7 +1033,6 @@ void AAHairlineOp::makeConicProgramInfo(const GrCaps& caps, SkArenaAlloc* arena, GrGeometryProcessor* conicGP = GrConicEffect::Make(arena, this->color(), *geometryProcessorViewM, - GrClipEdgeType::kHairlineAA, caps, *geometryProcessorLocalM, fHelper.usesLocalCoords(), @@ -1117,7 +1115,7 @@ void AAHairlineOp::onPrePrepareDraws(GrRecordingContext* context, const GrCaps* caps = context->priv().caps(); // This is equivalent to a GrOpFlushState::detachAppliedClip - GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip(); + GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled(); // Conservatively predict which programs will be required fCharacterization = this->predictPrograms(caps); @@ -1272,14 +1270,13 @@ bool GrAAHairLinePathRenderer::onDrawPath(const DrawPathArgs& args) { "GrAAHairlinePathRenderer::onDrawPath"); SkASSERT(args.fRenderTargetContext->numSamples() <= 1); - SkIRect devClipBounds = args.fClip->getConservativeBounds(args.fRenderTargetContext->width(), - args.fRenderTargetContext->height()); SkPath path; args.fShape->asPath(&path); std::unique_ptr<GrDrawOp> op = AAHairlineOp::Make(args.fContext, std::move(args.fPaint), *args.fViewMatrix, path, - args.fShape->style(), devClipBounds, args.fUserStencilSettings); - args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op)); + args.fShape->style(), *args.fClipConservativeBounds, + args.fUserStencilSettings); + args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op)); return true; } diff --git a/chromium/third_party/skia/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp index d6d644986d1..9c67fd8c3a0 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp @@ -405,7 +405,7 @@ bool GrAALinearizingConvexPathRenderer::onDrawPath(const DrawPathArgs& args) { std::unique_ptr<GrDrawOp> op = AAFlatteningConvexPathOp::Make( args.fContext, std::move(args.fPaint), *args.fViewMatrix, path, strokeWidth, stroke.getStyle(), join, miterLimit, args.fUserStencilSettings); - args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op)); + args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op)); return true; } diff --git a/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.cpp index 80a34c66b1b..4e4e7f7e2e6 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.cpp @@ -16,6 +16,7 @@ #include "src/gpu/GrMemoryPool.h" #include "src/gpu/GrOpFlushState.h" #include "src/gpu/GrRecordingContextPriv.h" +#include "src/gpu/GrRenderTargetContext.h" #include "src/gpu/GrResourceProvider.h" #include "src/gpu/effects/GrBitmapTextGeoProc.h" #include "src/gpu/effects/GrDistanceFieldGeoProc.h" @@ -23,6 +24,10 @@ #include "src/gpu/text/GrAtlasManager.h" #include "src/gpu/text/GrDistanceFieldAdjustTable.h" +#if GR_TEST_UTILS +#include "src/gpu/GrDrawOpTest.h" +#endif + /////////////////////////////////////////////////////////////////////////////////////////////////// GrAtlasTextOp::GrAtlasTextOp(MaskType maskType, @@ -43,7 +48,7 @@ GrAtlasTextOp::GrAtlasTextOp(MaskType maskType, , fDFGPFlags{DFGPFlags} , fGeoDataAllocSize{kMinGeometryAllocated} , fProcessors{std::move(paint)} - , fNumGlyphs{SkTo<int>(subrun->fGlyphs.size())} { + , fNumGlyphs{subrun->glyphCount()} { GrAtlasTextOp::Geometry& geometry = fGeoData[0]; // Unref handled in ~GrAtlasTextOp(). @@ -62,6 +67,11 @@ GrAtlasTextOp::GrAtlasTextOp(MaskType maskType, this->setBounds(bounds, HasAABloat::kNo, IsHairline::kNo); } +void GrAtlasTextOp::Geometry::fillVertexData(void *dst, int offset, int count) const { + fSubRunPtr->fillVertexData(dst, offset, count, fColor.toBytes_RGBA(), + fDrawMatrix, fDrawOrigin, fClipRect); +} + std::unique_ptr<GrAtlasTextOp> GrAtlasTextOp::MakeBitmap(GrRecordingContext* context, GrPaint&& paint, GrTextBlob::SubRun* subrun, @@ -193,113 +203,6 @@ GrProcessorSet::Analysis GrAtlasTextOp::finalize( return analysis; } -static void clip_quads(const SkIRect& clipRect, char* currVertex, const char* blobVertices, - size_t vertexStride, int glyphCount) { - for (int i = 0; i < glyphCount; ++i) { - const SkPoint* blobPositionLT = reinterpret_cast<const SkPoint*>(blobVertices); - const SkPoint* blobPositionRB = - reinterpret_cast<const SkPoint*>(blobVertices + 3 * vertexStride); - - // positions for bitmap glyphs are pixel boundary aligned - SkIRect positionRect = SkIRect::MakeLTRB(SkScalarRoundToInt(blobPositionLT->fX), - SkScalarRoundToInt(blobPositionLT->fY), - SkScalarRoundToInt(blobPositionRB->fX), - SkScalarRoundToInt(blobPositionRB->fY)); - if (clipRect.contains(positionRect)) { - memcpy(currVertex, blobVertices, 4 * vertexStride); - currVertex += 4 * vertexStride; - } else { - // Pull out some more data that we'll need. - // In the LCD case the color will be garbage, but we'll overwrite it with the texcoords - // and it avoids a lot of conditionals. - auto color = *reinterpret_cast<const SkColor*>(blobVertices + sizeof(SkPoint)); - size_t coordOffset = vertexStride - 2*sizeof(uint16_t); - auto* blobCoordsLT = reinterpret_cast<const uint16_t*>(blobVertices + coordOffset); - auto* blobCoordsRB = reinterpret_cast<const uint16_t*>(blobVertices + 3 * vertexStride + - coordOffset); - // Pull out the texel coordinates and texture index bits - uint16_t coordsRectL = blobCoordsLT[0]; - uint16_t coordsRectT = blobCoordsLT[1]; - uint16_t coordsRectR = blobCoordsRB[0]; - uint16_t coordsRectB = blobCoordsRB[1]; - int index0, index1; - std::tie(coordsRectL, coordsRectT, index0) = - GrDrawOpAtlas::UnpackIndexFromTexCoords(coordsRectL, coordsRectT); - std::tie(coordsRectR, coordsRectB, index1) = - GrDrawOpAtlas::UnpackIndexFromTexCoords(coordsRectR, coordsRectB); - SkASSERT(index0 == index1); - - int positionRectWidth = positionRect.width(); - int positionRectHeight = positionRect.height(); - SkASSERT(positionRectWidth == (coordsRectR - coordsRectL)); - SkASSERT(positionRectHeight == (coordsRectB - coordsRectT)); - - // Clip position and texCoords to the clipRect - unsigned int delta; - delta = std::min(std::max(clipRect.fLeft - positionRect.fLeft, 0), positionRectWidth); - coordsRectL += delta; - positionRect.fLeft += delta; - - delta = std::min(std::max(clipRect.fTop - positionRect.fTop, 0), positionRectHeight); - coordsRectT += delta; - positionRect.fTop += delta; - - delta = std::min(std::max(positionRect.fRight - clipRect.fRight, 0), positionRectWidth); - coordsRectR -= delta; - positionRect.fRight -= delta; - - delta = std::min(std::max(positionRect.fBottom - clipRect.fBottom, 0), positionRectHeight); - coordsRectB -= delta; - positionRect.fBottom -= delta; - - // Repack texel coordinates and index - std::tie(coordsRectL, coordsRectT) = - GrDrawOpAtlas::PackIndexInTexCoords(coordsRectL, coordsRectT, index0); - std::tie(coordsRectR, coordsRectB) = - GrDrawOpAtlas::PackIndexInTexCoords(coordsRectR, coordsRectB, index1); - - // Set new positions and coords - SkPoint* currPosition = reinterpret_cast<SkPoint*>(currVertex); - currPosition->fX = positionRect.fLeft; - currPosition->fY = positionRect.fTop; - *(reinterpret_cast<SkColor*>(currVertex + sizeof(SkPoint))) = color; - uint16_t* currCoords = reinterpret_cast<uint16_t*>(currVertex + coordOffset); - currCoords[0] = coordsRectL; - currCoords[1] = coordsRectT; - currVertex += vertexStride; - - currPosition = reinterpret_cast<SkPoint*>(currVertex); - currPosition->fX = positionRect.fLeft; - currPosition->fY = positionRect.fBottom; - *(reinterpret_cast<SkColor*>(currVertex + sizeof(SkPoint))) = color; - currCoords = reinterpret_cast<uint16_t*>(currVertex + coordOffset); - currCoords[0] = coordsRectL; - currCoords[1] = coordsRectB; - currVertex += vertexStride; - - currPosition = reinterpret_cast<SkPoint*>(currVertex); - currPosition->fX = positionRect.fRight; - currPosition->fY = positionRect.fTop; - *(reinterpret_cast<SkColor*>(currVertex + sizeof(SkPoint))) = color; - currCoords = reinterpret_cast<uint16_t*>(currVertex + coordOffset); - currCoords[0] = coordsRectR; - currCoords[1] = coordsRectT; - currVertex += vertexStride; - - currPosition = reinterpret_cast<SkPoint*>(currVertex); - currPosition->fX = positionRect.fRight; - currPosition->fY = positionRect.fBottom; - *(reinterpret_cast<SkColor*>(currVertex + sizeof(SkPoint))) = color; - currCoords = reinterpret_cast<uint16_t*>(currVertex + coordOffset); - currCoords[0] = coordsRectR; - currCoords[1] = coordsRectB; - currVertex += vertexStride; - } - - blobVertices += 4 * vertexStride; - } -} - void GrAtlasTextOp::onPrepareDraws(Target* target) { auto resourceProvider = target->resourceProvider(); @@ -381,8 +284,6 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) { SkASSERT((int)subRun->vertexStride() == vertexStride); subRun->prepareGrGlyphs(target->strikeCache()); - subRun->updateVerticesColorIfNeeded(args.fColor.toBytes_RGBA()); - subRun->translateVerticesIfNeeded(args.fDrawMatrix, args.fDrawOrigin); // TODO4F: Preserve float colors GrTextBlob::VertexRegenerator regenerator(resourceProvider, subRun, @@ -390,7 +291,7 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) { // Where the subRun begins and ends relative to totalGlyphsRegened. int subRunBegin = totalGlyphsRegened; - int subRunEnd = subRunBegin + subRun->fGlyphs.count(); + int subRunEnd = subRunBegin + subRun->glyphCount(); // Draw all the glyphs in the subRun. while (totalGlyphsRegened < subRunEnd) { @@ -409,39 +310,10 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) { // Update all the vertices for glyphsRegenerate glyphs. if (glyphsRegenerated > 0) { int quadBufferIndex = totalGlyphsRegened - quadBufferBegin; - int subRunIndex = totalGlyphsRegened - subRunBegin; auto regeneratedQuadBuffer = SkTAddOffset<char>(vertices, subRun->quadOffset(quadBufferIndex)); - if (args.fClipRect.isEmpty()) { - memcpy(regeneratedQuadBuffer, - subRun->quadStart(subRunIndex), - glyphsRegenerated * quadSize); - } else { - SkASSERT(!vmPerspective); - clip_quads(args.fClipRect, - regeneratedQuadBuffer, - subRun->quadStart(subRunIndex), - vertexStride, - glyphsRegenerated); - } - if (fNeedsGlyphTransform && !args.fDrawMatrix.isIdentity()) { - // We always do the distance field view matrix transformation after copying - // rather than during blob vertex generation time in the blob as handling - // successive arbitrary transformations would be complicated and accumulate - // error. - if (args.fDrawMatrix.hasPerspective()) { - auto* pos = reinterpret_cast<SkPoint3*>(regeneratedQuadBuffer); - SkMatrixPriv::MapHomogeneousPointsWithStride( - args.fDrawMatrix, pos, - vertexStride, pos, - vertexStride, - glyphsRegenerated * kVerticesPerGlyph); - } else { - auto* pos = reinterpret_cast<SkPoint*>(regeneratedQuadBuffer); - SkMatrixPriv::MapPointsWithStride(args.fDrawMatrix, pos, vertexStride, - glyphsRegenerated * kVerticesPerGlyph); - } - } + int subRunIndex = totalGlyphsRegened - subRunBegin; + args.fillVertexData(regeneratedQuadBuffer, subRunIndex, glyphsRegenerated); } totalGlyphsRegened += glyphsRegenerated; @@ -619,7 +491,6 @@ GrOp::CombineResult GrAtlasTextOp::onCombineIfPossible(GrOp* t, GrRecordingConte static const int kDistanceAdjustLumShift = 5; // TODO trying to figure out why lcd is so whack -// (see comments in GrTextContext::ComputeCanonicalColor) GrGeometryProcessor* GrAtlasTextOp::setupDfProcessor(SkArenaAlloc* arena, const GrShaderCaps& caps, const GrSurfaceProxyView* views, @@ -672,3 +543,78 @@ GrGeometryProcessor* GrAtlasTextOp::setupDfProcessor(SkArenaAlloc* arena, } } +#if GR_TEST_UTILS +std::unique_ptr<GrDrawOp> GrAtlasTextOp::CreateOpTestingOnly(GrRenderTargetContext* rtc, + const SkPaint& skPaint, + const SkFont& font, + const SkMatrixProvider& mtxProvider, + const char* text, + int x, + int y) { + static SkSurfaceProps surfaceProps(SkSurfaceProps::kLegacyFontHost_InitType); + + size_t textLen = (int)strlen(text); + + const SkMatrix& drawMatrix(mtxProvider.localToDevice()); + + auto drawOrigin = SkPoint::Make(x, y); + SkGlyphRunBuilder builder; + builder.drawTextUTF8(skPaint, font, text, textLen, drawOrigin); + + auto glyphRunList = builder.useGlyphRunList(); + + const GrRecordingContextPriv& contextPriv = rtc->fContext->priv(); + GrSDFTOptions SDFOptions = rtc->fContext->priv().SDFTOptions(); + + if (glyphRunList.empty()) { + return nullptr; + } + sk_sp<GrTextBlob> blob = GrTextBlob::Make(glyphRunList, drawMatrix); + SkGlyphRunListPainter* painter = &rtc->fGlyphPainter; + painter->processGlyphRunList( + glyphRunList, drawMatrix, surfaceProps, + contextPriv.caps()->shaderCaps()->supportsDistanceFieldText(), + SDFOptions, blob.get()); + + return blob->firstSubRun()->makeOp(mtxProvider, + drawOrigin, + SkIRect::MakeEmpty(), + skPaint, + surfaceProps, + rtc->textTarget()); +} + +GR_DRAW_OP_TEST_DEFINE(GrAtlasTextOp) { + // Setup dummy SkPaint / GrPaint / GrRenderTargetContext + auto rtc = GrRenderTargetContext::Make( + context, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kApprox, {1024, 1024}); + + SkSimpleMatrixProvider matrixProvider(GrTest::TestMatrixInvertible(random)); + + SkPaint skPaint; + skPaint.setColor(random->nextU()); + + SkFont font; + if (random->nextBool()) { + font.setEdging(SkFont::Edging::kSubpixelAntiAlias); + } else { + font.setEdging(random->nextBool() ? SkFont::Edging::kAntiAlias : SkFont::Edging::kAlias); + } + font.setSubpixel(random->nextBool()); + + const char* text = "The quick brown fox jumps over the lazy dog."; + + // create some random x/y offsets, including negative offsets + static const int kMaxTrans = 1024; + int xPos = (random->nextU() % 2) * 2 - 1; + int yPos = (random->nextU() % 2) * 2 - 1; + int xInt = (random->nextU() % kMaxTrans) * xPos; + int yInt = (random->nextU() % kMaxTrans) * yPos; + + return GrAtlasTextOp::CreateOpTestingOnly( + rtc.get(), skPaint, font, matrixProvider, text, xInt, yInt); +} + +#endif + + diff --git a/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.h b/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.h index 451de49aec4..e4e9af9b20a 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.h +++ b/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.h @@ -12,7 +12,6 @@ #include "src/gpu/text/GrTextBlob.h" class GrRecordingContext; -class SkAtlasTextTarget; class GrAtlasTextOp final : public GrMeshDrawOp { public: @@ -34,6 +33,8 @@ public: SkPoint fDrawOrigin; GrTextBlob::SubRun* fSubRunPtr; SkPMColor4f fColor; + + void fillVertexData(void* dst, int offset, int count) const; }; static std::unique_ptr<GrAtlasTextOp> MakeBitmap(GrRecordingContext* context, @@ -81,8 +82,15 @@ public: MaskType maskType() const { return fMaskType; } - void finalizeForTextTarget(uint32_t color, const GrCaps&); - void executeForTextTarget(SkAtlasTextTarget*); +#if GR_TEST_UTILS + static std::unique_ptr<GrDrawOp> CreateOpTestingOnly(GrRenderTargetContext* rtc, + const SkPaint& skPaint, + const SkFont& font, + const SkMatrixProvider& mtxProvider, + const char* text, + int x, + int y); +#endif private: friend class GrOpMemoryPool; // for ctor diff --git a/chromium/third_party/skia/src/gpu/ops/GrClearOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrClearOp.cpp index 28529f47a0e..7f82206654c 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrClearOp.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrClearOp.cpp @@ -14,52 +14,74 @@ #include "src/gpu/GrProxyProvider.h" #include "src/gpu/GrRecordingContextPriv.h" -std::unique_ptr<GrClearOp> GrClearOp::Make(GrRecordingContext* context, - const GrFixedClip& clip, - const SkPMColor4f& color, - GrSurfaceProxy* dstProxy) { - const SkIRect rect = SkIRect::MakeSize(dstProxy->dimensions()); - if (clip.scissorEnabled() && !SkIRect::Intersects(clip.scissorRect(), rect)) { - return nullptr; - } +static bool contains_scissor(const GrScissorState& a, const GrScissorState& b) { + return !a.enabled() || (b.enabled() && a.rect().contains(b.rect())); +} +std::unique_ptr<GrClearOp> GrClearOp::MakeColor(GrRecordingContext* context, + const GrScissorState& scissor, + const SkPMColor4f& color) { GrOpMemoryPool* pool = context->priv().opMemoryPool(); - - return pool->allocate<GrClearOp>(clip, color, dstProxy); + return pool->allocate<GrClearOp>(Buffer::kColor, scissor, color, false); } -std::unique_ptr<GrClearOp> GrClearOp::Make(GrRecordingContext* context, - const SkIRect& rect, - const SkPMColor4f& color, - bool fullScreen) { - SkASSERT(fullScreen || !rect.isEmpty()); - +std::unique_ptr<GrClearOp> GrClearOp::MakeStencilClip(GrRecordingContext* context, + const GrScissorState& scissor, + bool insideMask) { GrOpMemoryPool* pool = context->priv().opMemoryPool(); - - return pool->allocate<GrClearOp>(rect, color, fullScreen); + return pool->allocate<GrClearOp>(Buffer::kStencilClip, scissor, SkPMColor4f(), insideMask); } -GrClearOp::GrClearOp(const GrFixedClip& clip, const SkPMColor4f& color, GrSurfaceProxy* proxy) +GrClearOp::GrClearOp(Buffer buffer, const GrScissorState& scissor, + const SkPMColor4f& color, bool insideMask) : INHERITED(ClassID()) - , fClip(clip) - , fColor(color) { - const SkIRect rtRect = SkIRect::MakeSize(proxy->dimensions()); - if (fClip.scissorEnabled()) { - // Don't let scissors extend outside the RT. This may improve op combining. - if (!fClip.intersect(rtRect)) { - SkASSERT(0); // should be caught upstream - fClip = GrFixedClip(SkIRect::MakeEmpty()); - } + , fScissor(scissor) + , fColor(color) + , fStencilInsideMask(insideMask) + , fBuffer(buffer) { + this->setBounds(SkRect::Make(scissor.rect()), HasAABloat::kNo, IsHairline::kNo); +} - if (proxy->isFunctionallyExact() && fClip.scissorRect() == rtRect) { - fClip.disableScissor(); +GrOp::CombineResult GrClearOp::onCombineIfPossible(GrOp* t, GrRecordingContext::Arenas*, + const GrCaps& caps) { + GrClearOp* other = t->cast<GrClearOp>(); + + if (other->fBuffer == fBuffer) { + // This could be much more complicated. Currently we look at cases where the new clear + // contains the old clear, or when the new clear is a subset of the old clear and they clear + // to the same value (color or stencil mask depending on target). + if (contains_scissor(other->fScissor, fScissor)) { + fScissor = other->fScissor; + fColor = other->fColor; + fStencilInsideMask = other->fStencilInsideMask; + return CombineResult::kMerged; + } else if (other->fColor == fColor && other->fStencilInsideMask == fStencilInsideMask && + contains_scissor(fScissor, other->fScissor)) { + return CombineResult::kMerged; + } + } else if (other->fScissor == fScissor) { + // When the scissors are the exact same but the buffers are different, we can combine and + // clear both stencil and clear together in onExecute(). + if (other->fBuffer & Buffer::kColor) { + SkASSERT((fBuffer & Buffer::kStencilClip) && !(fBuffer & Buffer::kColor)); + fColor = other->fColor; + } + if (other->fBuffer & Buffer::kStencilClip) { + SkASSERT(!(fBuffer & Buffer::kStencilClip) && (fBuffer & Buffer::kColor)); + fStencilInsideMask = other->fStencilInsideMask; } + fBuffer = Buffer::kBoth; } - this->setBounds(SkRect::Make(fClip.scissorEnabled() ? fClip.scissorRect() : rtRect), - HasAABloat::kNo, IsHairline::kNo); + return CombineResult::kCannotCombine; } void GrClearOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) { SkASSERT(state->opsRenderPass()); - state->opsRenderPass()->clear(fClip, fColor); + if (fBuffer & Buffer::kColor) { + state->opsRenderPass()->clear(fScissor, fColor); + } + + if (fBuffer & Buffer::kStencilClip) { + state->opsRenderPass()->clearStencilClip(fScissor, fStencilInsideMask); + } } diff --git a/chromium/third_party/skia/src/gpu/ops/GrClearOp.h b/chromium/third_party/skia/src/gpu/ops/GrClearOp.h index fbac02f9a74..5eaff4bb19c 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrClearOp.h +++ b/chromium/third_party/skia/src/gpu/ops/GrClearOp.h @@ -8,7 +8,8 @@ #ifndef GrClearOp_DEFINED #define GrClearOp_DEFINED -#include "src/gpu/GrFixedClip.h" +#include "include/gpu/GrTypes.h" +#include "src/gpu/GrScissorState.h" #include "src/gpu/ops/GrOp.h" class GrOpFlushState; @@ -18,15 +19,14 @@ class GrClearOp final : public GrOp { public: DEFINE_OP_CLASS_ID - static std::unique_ptr<GrClearOp> Make(GrRecordingContext* context, - const GrFixedClip& clip, - const SkPMColor4f& color, - GrSurfaceProxy* dstProxy); + // A fullscreen or scissored clear, depending on the clip and proxy dimensions + static std::unique_ptr<GrClearOp> MakeColor(GrRecordingContext* context, + const GrScissorState& scissor, + const SkPMColor4f& color); - static std::unique_ptr<GrClearOp> Make(GrRecordingContext* context, - const SkIRect& rect, - const SkPMColor4f& color, - bool fullScreen); + static std::unique_ptr<GrClearOp> MakeStencilClip(GrRecordingContext* context, + const GrScissorState& scissor, + bool insideMask); const char* name() const override { return "Clear"; } @@ -35,8 +35,8 @@ public: SkString string; string.append(INHERITED::dumpInfo()); string.appendf("Scissor [ "); - if (fClip.scissorEnabled()) { - const SkIRect& r = fClip.scissorRect(); + if (fScissor.enabled()) { + const SkIRect& r = fScissor.rect(); string.appendf("L: %d, T: %d, R: %d, B: %d", r.fLeft, r.fTop, r.fRight, r.fBottom); } else { string.append("disabled"); @@ -46,64 +46,37 @@ public: } #endif - const SkPMColor4f& color() const { return fColor; } - void setColor(const SkPMColor4f& color) { fColor = color; } - private: friend class GrOpMemoryPool; // for ctors - GrClearOp(const GrFixedClip& clip, const SkPMColor4f& color, GrSurfaceProxy* proxy); + enum class Buffer { + kColor = 0b01, + kStencilClip = 0b10, - GrClearOp(const SkIRect& rect, const SkPMColor4f& color, bool fullScreen) - : INHERITED(ClassID()) - , fClip(GrFixedClip(rect)) - , fColor(color) { + kBoth = 0b11, + }; + GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(Buffer); - if (fullScreen) { - fClip.disableScissor(); - } - this->setBounds(SkRect::Make(rect), HasAABloat::kNo, IsHairline::kNo); - } + GrClearOp(Buffer buffer, const GrScissorState& scissor, const SkPMColor4f& color, bool stencil); CombineResult onCombineIfPossible(GrOp* t, GrRecordingContext::Arenas*, - const GrCaps& caps) override { - // This could be much more complicated. Currently we look at cases where the new clear - // contains the old clear, or when the new clear is a subset of the old clear and is the - // same color. - GrClearOp* cb = t->cast<GrClearOp>(); - if (fClip.windowRectsState() != cb->fClip.windowRectsState()) { - return CombineResult::kCannotCombine; - } - if (cb->contains(this)) { - fClip = cb->fClip; - fColor = cb->fColor; - return CombineResult::kMerged; - } else if (cb->fColor == fColor && this->contains(cb)) { - return CombineResult::kMerged; - } - return CombineResult::kCannotCombine; - } - - bool contains(const GrClearOp* that) const { - // The constructor ensures that scissor gets disabled on any clip that fills the entire RT. - return !fClip.scissorEnabled() || - (that->fClip.scissorEnabled() && - fClip.scissorRect().contains(that->fClip.scissorRect())); - } + const GrCaps& caps) override; - void onPrePrepare(GrRecordingContext*, - const GrSurfaceProxyView* writeView, - GrAppliedClip*, + void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView* writeView, GrAppliedClip*, const GrXferProcessor::DstProxyView&) override {} void onPrepare(GrOpFlushState*) override {} void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override; - GrFixedClip fClip; - SkPMColor4f fColor; + GrScissorState fScissor; + SkPMColor4f fColor; + bool fStencilInsideMask; + Buffer fBuffer; typedef GrOp INHERITED; }; +GR_MAKE_BITFIELD_CLASS_OPS(GrClearOp::Buffer) + #endif diff --git a/chromium/third_party/skia/src/gpu/ops/GrClearStencilClipOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrClearStencilClipOp.cpp deleted file mode 100644 index 7ca4063b967..00000000000 --- a/chromium/third_party/skia/src/gpu/ops/GrClearStencilClipOp.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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 "src/gpu/ops/GrClearStencilClipOp.h" - -#include "include/private/GrRecordingContext.h" -#include "src/gpu/GrMemoryPool.h" -#include "src/gpu/GrOpFlushState.h" -#include "src/gpu/GrOpsRenderPass.h" -#include "src/gpu/GrRecordingContextPriv.h" - -std::unique_ptr<GrOp> GrClearStencilClipOp::Make(GrRecordingContext* context, - const GrFixedClip& clip, - bool insideStencilMask, - GrRenderTargetProxy* proxy) { - GrOpMemoryPool* pool = context->priv().opMemoryPool(); - - return pool->allocate<GrClearStencilClipOp>(clip, insideStencilMask, proxy); -} - -void GrClearStencilClipOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) { - SkASSERT(state->opsRenderPass()); - state->opsRenderPass()->clearStencilClip(fClip, fInsideStencilMask); -} diff --git a/chromium/third_party/skia/src/gpu/ops/GrClearStencilClipOp.h b/chromium/third_party/skia/src/gpu/ops/GrClearStencilClipOp.h deleted file mode 100644 index 68f825a7e40..00000000000 --- a/chromium/third_party/skia/src/gpu/ops/GrClearStencilClipOp.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrClearStencilClipOp_DEFINED -#define GrClearStencilClipOp_DEFINED - -#include "src/gpu/GrFixedClip.h" -#include "src/gpu/GrRenderTargetProxy.h" -#include "src/gpu/ops/GrOp.h" - -class GrOpFlushState; -class GrRecordingContext; - -class GrClearStencilClipOp final : public GrOp { -public: - DEFINE_OP_CLASS_ID - - static std::unique_ptr<GrOp> Make(GrRecordingContext* context, - const GrFixedClip& clip, - bool insideStencilMask, - GrRenderTargetProxy* proxy); - - const char* name() const override { return "ClearStencilClip"; } - -#ifdef SK_DEBUG - SkString dumpInfo() const override { - SkString string("Scissor ["); - if (fClip.scissorEnabled()) { - const SkIRect& r = fClip.scissorRect(); - string.appendf("L: %d, T: %d, R: %d, B: %d", r.fLeft, r.fTop, r.fRight, r.fBottom); - } else { - string.append("disabled"); - } - string.appendf("], insideMask: %s\n", fInsideStencilMask ? "true" : "false"); - string.append(INHERITED::dumpInfo()); - return string; - } -#endif - -private: - friend class GrOpMemoryPool; // for ctor - - GrClearStencilClipOp(const GrFixedClip& clip, bool insideStencilMask, - GrRenderTargetProxy* proxy) - : INHERITED(ClassID()) - , fClip(clip) - , fInsideStencilMask(insideStencilMask) { - const SkRect& bounds = - fClip.scissorEnabled() ? SkRect::Make(fClip.scissorRect()) : proxy->getBoundsRect(); - this->setBounds(bounds, HasAABloat::kNo, IsHairline::kNo); - } - - void onPrePrepare(GrRecordingContext*, - const GrSurfaceProxyView* writeView, - GrAppliedClip*, - const GrXferProcessor::DstProxyView&) override {} - - void onPrepare(GrOpFlushState*) override {} - - void onExecute(GrOpFlushState*, const SkRect& chainBounds) override; - - const GrFixedClip fClip; - const bool fInsideStencilMask; - - typedef GrOp INHERITED; -}; - -#endif diff --git a/chromium/third_party/skia/src/gpu/ops/GrDashLinePathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrDashLinePathRenderer.cpp index 96fc06cde17..e5cf9e4038b 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrDashLinePathRenderer.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrDashLinePathRenderer.cpp @@ -53,6 +53,6 @@ bool GrDashLinePathRenderer::onDrawPath(const DrawPathArgs& args) { if (!op) { return false; } - args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op)); + args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op)); return true; } diff --git a/chromium/third_party/skia/src/gpu/ops/GrDashOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrDashOp.cpp index 7e1b63fdc82..5ee04a42a2a 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrDashOp.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrDashOp.cpp @@ -167,9 +167,9 @@ static void setup_dashed_rect(const SkRect& rect, // 'dashRect' gets interpolated over the rendered 'rect'. For y we want the perpendicular signed // distance from the stroke center line in device space. 'perpScale' is the scale factor applied // to the y dimension of 'rect' isolated from 'matrix'. - SkScalar halfDevRectHeight = rect.height()*perpScale/2.f; + SkScalar halfDevRectHeight = rect.height() * perpScale / 2.f; SkRect dashRect = { offset - bloatX, -halfDevRectHeight, - offset + len + bloatX, halfDevRectHeight}; + offset + len + bloatX, halfDevRectHeight }; if (kRound_DashCap == cap) { SkScalar radius = SkScalarHalf(strokeWidth) - 0.5f; @@ -311,9 +311,8 @@ private: SkMatrix& combinedMatrix = fLines[0].fSrcRotInv; combinedMatrix.postConcat(geometry.fViewMatrix); - IsHairline zeroArea = geometry.fSrcStrokeWidth ? IsHairline::kNo - : IsHairline::kYes; - HasAABloat aaBloat = (aaMode == AAMode::kNone) ? HasAABloat ::kNo : HasAABloat::kYes; + IsHairline zeroArea = geometry.fSrcStrokeWidth ? IsHairline::kNo : IsHairline::kYes; + HasAABloat aaBloat = (aaMode == AAMode::kNone) ? HasAABloat::kNo : HasAABloat::kYes; this->setTransformedBounds(bounds, combinedMatrix, aaBloat, zeroArea); } @@ -418,18 +417,15 @@ private: bool hasCap = SkPaint::kButt_Cap != cap; - // We always want to at least stroke out half a pixel on each side in device space - // so 0.5f / perpScale gives us this min in src space - SkScalar halfSrcStroke = - std::max(args.fSrcStrokeWidth * 0.5f, 0.5f / args.fPerpendicularScale); - - SkScalar strokeAdj; - if (!hasCap) { - strokeAdj = 0.f; - } else { - strokeAdj = halfSrcStroke; + SkScalar halfSrcStroke = args.fSrcStrokeWidth * 0.5f; + if (halfSrcStroke == 0.0f || this->aaMode() != AAMode::kCoverageWithMSAA) { + // In the non-MSAA case, we always want to at least stroke out half a pixel on each + // side in device space. 0.5f / fPerpendicularScale gives us this min in src space. + // This is also necessary when the stroke width is zero, to allow hairlines to draw. + halfSrcStroke = std::max(halfSrcStroke, 0.5f / args.fPerpendicularScale); } + SkScalar strokeAdj = hasCap ? halfSrcStroke : 0.0f; SkScalar startAdj = 0; bool lineDone = false; @@ -536,14 +532,20 @@ private: } SkScalar startOffset = devIntervals[1] * 0.5f + devPhase; - // For EdgeAA, we bloat in X & Y for both square and round caps. - // For MSAA, we don't bloat at all for square caps, and bloat in Y only for round caps. - SkScalar devBloatX = this->aaMode() == AAMode::kCoverage ? 0.5f : 0.0f; - SkScalar devBloatY; - if (SkPaint::kRound_Cap == cap && this->aaMode() == AAMode::kCoverageWithMSAA) { - devBloatY = 0.5f; - } else { - devBloatY = devBloatX; + SkScalar devBloatX = 0.0f; + SkScalar devBloatY = 0.0f; + switch (this->aaMode()) { + case AAMode::kNone: + break; + case AAMode::kCoverage: + // For EdgeAA, we bloat in X & Y for both square and round caps. + devBloatX = 0.5f; + devBloatY = 0.5f; + break; + case AAMode::kCoverageWithMSAA: + // For MSAA, we only bloat in Y for round caps. + devBloatY = (cap == SkPaint::kRound_Cap) ? 0.5f : 0.0f; + break; } SkScalar bloatX = devBloatX / args.fParallelScale; @@ -782,7 +784,7 @@ std::unique_ptr<GrDrawOp> GrDashOp::MakeDashLineOp(GrRecordingContext* context, SkScalar strokeWidth = lineData.fSrcStrokeWidth * lineData.fPerpendicularScale; if (SkPaint::kSquare_Cap == cap && 0 != lineData.fSrcStrokeWidth) { - // add cap to on interveal and remove from off interval + // add cap to on interval and remove from off interval offInterval -= strokeWidth; } @@ -874,14 +876,19 @@ public: private: UniformHandle fParamUniform; UniformHandle fColorUniform; + UniformHandle fLocalMatrixUniform; + + SkMatrix fLocalMatrix; SkPMColor4f fColor; SkScalar fPrevRadius; SkScalar fPrevCenterX; SkScalar fPrevIntervalLength; + typedef GrGLSLGeometryProcessor INHERITED; }; GLDashingCircleEffect::GLDashingCircleEffect() { + fLocalMatrix = SkMatrix::InvalidMatrix(); fColor = SK_PMColor4fILLEGAL; fPrevRadius = SK_ScalarMin; fPrevCenterX = SK_ScalarMin; @@ -913,14 +920,10 @@ void GLDashingCircleEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { // Setup position this->writeOutputPosition(vertBuilder, gpArgs, dce.fInPosition.name()); - - // emit transforms - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - dce.fInPosition.asShaderVar(), - dce.localMatrix(), - args.fFPCoordTransformHandler); + if (dce.usesLocalCoords()) { + this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, dce.fInPosition.asShaderVar(), + dce.localMatrix(), &fLocalMatrixUniform); + } // transforms all points so that we can compare them to our test circle fragBuilder->codeAppendf("half xShifted = half(%s.x - floor(%s.x / %s.z) * %s.z);", @@ -949,7 +952,8 @@ void GLDashingCircleEffect::setData(const GrGLSLProgramDataManager& pdman, pdman.set4fv(fColorUniform, 1, dce.color().vec()); fColor = dce.color(); } - this->setTransformDataHelper(dce.localMatrix(), pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); + this->setTransform(pdman, fLocalMatrixUniform, dce.localMatrix(), &fLocalMatrix); } void GLDashingCircleEffect::GenKey(const GrGeometryProcessor& gp, @@ -957,8 +961,9 @@ void GLDashingCircleEffect::GenKey(const GrGeometryProcessor& gp, GrProcessorKeyBuilder* b) { const DashingCircleEffect& dce = gp.cast<DashingCircleEffect>(); uint32_t key = 0; - key |= dce.usesLocalCoords() && dce.localMatrix().hasPerspective() ? 0x1 : 0x0; + key |= dce.usesLocalCoords() ? 0x1 : 0x0; key |= static_cast<uint32_t>(dce.aaMode()) << 1; + key |= ComputeMatrixKey(dce.localMatrix()) << 3; b->add32(key); } @@ -1084,6 +1089,10 @@ public: private: SkPMColor4f fColor; UniformHandle fColorUniform; + + SkMatrix fLocalMatrix; + UniformHandle fLocalMatrixUniform; + typedef GrGLSLGeometryProcessor INHERITED; }; @@ -1116,14 +1125,10 @@ void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { // Setup position this->writeOutputPosition(vertBuilder, gpArgs, de.fInPosition.name()); - - // emit transforms - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - de.fInPosition.asShaderVar(), - de.localMatrix(), - args.fFPCoordTransformHandler); + if (de.usesLocalCoords()) { + this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, de.fInPosition.asShaderVar(), + de.localMatrix(), &fLocalMatrixUniform); + } // transforms all points so that we can compare them to our test rect fragBuilder->codeAppendf("half xShifted = half(%s.x - floor(%s.x / %s.z) * %s.z);", @@ -1176,7 +1181,8 @@ void GLDashingLineEffect::setData(const GrGLSLProgramDataManager& pdman, pdman.set4fv(fColorUniform, 1, de.color().vec()); fColor = de.color(); } - this->setTransformDataHelper(de.localMatrix(), pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); + this->setTransform(pdman, fLocalMatrixUniform, de.localMatrix(), &fLocalMatrix); } void GLDashingLineEffect::GenKey(const GrGeometryProcessor& gp, @@ -1184,8 +1190,9 @@ void GLDashingLineEffect::GenKey(const GrGeometryProcessor& gp, GrProcessorKeyBuilder* b) { const DashingLineEffect& de = gp.cast<DashingLineEffect>(); uint32_t key = 0; - key |= de.usesLocalCoords() && de.localMatrix().hasPerspective() ? 0x1 : 0x0; - key |= static_cast<int>(de.aaMode()) << 8; + key |= de.usesLocalCoords() ? 0x1 : 0x0; + key |= static_cast<int>(de.aaMode()) << 1; + key |= ComputeMatrixKey(de.localMatrix()) << 3; b->add32(key); } diff --git a/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.cpp index 7f4f634b33e..88175db9d20 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.cpp @@ -14,9 +14,9 @@ #include "src/core/SkTraceEvent.h" #include "src/gpu/GrAuditTrail.h" #include "src/gpu/GrCaps.h" +#include "src/gpu/GrClip.h" #include "src/gpu/GrDefaultGeoProcFactory.h" #include "src/gpu/GrDrawOpTest.h" -#include "src/gpu/GrFixedClip.h" #include "src/gpu/GrOpFlushState.h" #include "src/gpu/GrProgramInfo.h" #include "src/gpu/GrRenderTargetContextPriv.h" @@ -537,7 +537,7 @@ bool GrDefaultPathRenderer::internalDrawPath(GrRenderTargetContext* renderTarget GrPaint&& paint, GrAAType aaType, const GrUserStencilSettings& userStencilSettings, - const GrClip& clip, + const GrClip* clip, const SkMatrix& viewMatrix, const GrStyledShape& shape, bool stencilOnly) { @@ -583,7 +583,7 @@ bool GrDefaultPathRenderer::internalDrawPath(GrRenderTargetContext* renderTarget switch (path.getFillType()) { case SkPathFillType::kInverseEvenOdd: reverse = true; - // fallthrough + [[fallthrough]]; case SkPathFillType::kEvenOdd: passes[0] = &gEOStencilPass; if (stencilOnly) { @@ -602,7 +602,7 @@ bool GrDefaultPathRenderer::internalDrawPath(GrRenderTargetContext* renderTarget case SkPathFillType::kInverseWinding: reverse = true; - // fallthrough + [[fallthrough]]; case SkPathFillType::kWinding: passes[0] = &gWindStencilPass; passCount = 2; @@ -705,7 +705,7 @@ bool GrDefaultPathRenderer::onDrawPath(const DrawPathArgs& args) { return this->internalDrawPath( args.fRenderTargetContext, std::move(args.fPaint), aaType, *args.fUserStencilSettings, - *args.fClip, *args.fViewMatrix, *args.fShape, false); + args.fClip, *args.fViewMatrix, *args.fShape, false); } void GrDefaultPathRenderer::onStencilPath(const StencilPathArgs& args) { @@ -720,7 +720,7 @@ void GrDefaultPathRenderer::onStencilPath(const StencilPathArgs& args) { this->internalDrawPath( args.fRenderTargetContext, std::move(paint), aaType, GrUserStencilSettings::kUnused, - *args.fClip, *args.fViewMatrix, *args.fShape, true); + args.fClip, *args.fViewMatrix, *args.fShape, true); } /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.h b/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.h index e709964f690..7b0a32d1128 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.h +++ b/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.h @@ -35,7 +35,7 @@ private: GrPaint&&, GrAAType, const GrUserStencilSettings&, - const GrClip&, + const GrClip*, const SkMatrix& viewMatrix, const GrStyledShape&, bool stencilOnly); diff --git a/chromium/third_party/skia/src/gpu/ops/GrDrawVerticesOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrDrawVerticesOp.cpp index f9a42f35cfe..111cc7e7c09 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrDrawVerticesOp.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrDrawVerticesOp.cpp @@ -58,21 +58,29 @@ static GrSLType SkVerticesAttributeToGrSLType(const SkVertices::Attribute& a) { SkUNREACHABLE; } +static bool AttributeUsesViewMatrix(const SkVertices::Attribute& attr) { + return (attr.fMarkerID == 0) && (attr.fUsage == SkVertices::Attribute::Usage::kVector || + attr.fUsage == SkVertices::Attribute::Usage::kNormalVector || + attr.fUsage == SkVertices::Attribute::Usage::kPosition); +} + // Container for a collection of [uint32_t, Matrix] pairs. For a GrDrawVerticesOp whose custom // attributes reference some set of IDs, this stores the actual values of those matrices, // at the time the Op is created. class MarkedMatrices { public: - // For each ID required by 'info', fetch the value of that matrix from 'matrixProvider' + // For each ID required by 'info', fetch the value of that matrix from 'matrixProvider'. + // For vectors/normals/positions, we let ID 0 refer to the canvas CTM matrix. void gather(const SkVerticesPriv& info, const SkMatrixProvider& matrixProvider) { for (int i = 0; i < info.attributeCount(); ++i) { - if (uint32_t id = info.attributes()[i].fMarkerID) { + uint32_t id = info.attributes()[i].fMarkerID; + if (id != 0 || AttributeUsesViewMatrix(info.attributes()[i])) { if (std::none_of(fMatrices.begin(), fMatrices.end(), [id](const auto& m) { return m.first == id; })) { SkM44 matrix; - // SkCanvas should guarantee that this succeeds + // SkCanvas should guarantee that this succeeds. SkAssertResult(matrixProvider.getLocalToMarker(id, &matrix)); - fMatrices.push_back({id, matrix}); + fMatrices.emplace_back(id, matrix); } } } @@ -177,12 +185,7 @@ public: // emit transforms using either explicit local coords or positions const auto& coordsAttr = gp.localCoordsAttr().isInitialized() ? gp.localCoordsAttr() : gp.positionAttr(); - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - coordsAttr.asShaderVar(), - SkMatrix::I(), - args.fFPCoordTransformHandler); + gpArgs->fLocalCoordVar = coordsAttr.asShaderVar(); // Add varyings and globals for all custom attributes using Usage = SkVertices::Attribute::Usage; @@ -195,7 +198,7 @@ public: SkString varyingIn(attr.name()); UniformHandle matrixHandle; - if (customAttr.fMarkerID) { + if (customAttr.fMarkerID || AttributeUsesViewMatrix(customAttr)) { bool normal = customAttr.fUsage == Usage::kNormalVector; for (const MarkedUniform& matrixUni : fCustomMatrixUniforms) { if (matrixUni.fID == customAttr.fMarkerID && matrixUni.fNormal == normal) { @@ -214,10 +217,6 @@ public: } } - // TODO: For now, vectors/normals/positions with a 0 markerID get no transform. - // Those should use localToDevice instead. That means we need to change batching - // logic and then guarantee that we have the view matrix as a uniform here. - switch (customAttr.fUsage) { case Usage::kRaw: break; @@ -302,7 +301,7 @@ public: const VerticesGP& vgp = gp.cast<VerticesGP>(); uint32_t key = 0; key |= (vgp.fColorArrayType == ColorArrayType::kSkColor) ? 0x1 : 0; - key |= ComputePosKey(vgp.viewMatrix()) << 20; + key |= ComputeMatrixKey(vgp.viewMatrix()) << 20; b->add32(key); b->add32(GrColorSpaceXform::XformKey(vgp.fColorSpaceXform.get())); @@ -319,19 +318,14 @@ public: const CoordTransformRange& transformRange) override { const VerticesGP& vgp = gp.cast<VerticesGP>(); - if (!vgp.viewMatrix().isIdentity() && - !SkMatrixPriv::CheapEqual(fViewMatrix, vgp.viewMatrix())) { - fViewMatrix = vgp.viewMatrix(); - pdman.setSkMatrix(fViewMatrixUniform, fViewMatrix); - } + this->setTransform(pdman, fViewMatrixUniform, vgp.viewMatrix(), &fViewMatrix); + this->setTransformDataHelper(pdman, transformRange); if (!vgp.colorAttr().isInitialized() && vgp.color() != fColor) { pdman.set4fv(fColorUniform, 1, vgp.color().vec()); fColor = vgp.color(); } - this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange); - fColorSpaceHelper.setData(pdman, vgp.fColorSpaceXform.get()); for (const auto& matrixUni : fCustomMatrixUniforms) { diff --git a/chromium/third_party/skia/src/gpu/ops/GrFillRRectOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrFillRRectOp.cpp index 76122e576ce..630955fe042 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrFillRRectOp.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrFillRRectOp.cpp @@ -680,15 +680,13 @@ class FillRRectOp::Processor::CoverageImpl : public GrGLSLGeometryProcessor { v->codeAppend("float2 aa_outset = aa_bloat_direction.xy * aa_bloatradius;"); v->codeAppend("float2 vertexpos = corner + radius_outset * radii + aa_outset;"); - // Emit transforms. + // Write positions GrShaderVar localCoord("", kFloat2_GrSLType); if (proc.fFlags & ProcessorFlags::kHasLocalCoords) { v->codeAppend("float2 localcoord = (local_rect.xy * (1 - vertexpos) + " "local_rect.zw * (1 + vertexpos)) * .5;"); - localCoord.set(kFloat2_GrSLType, "localcoord"); + gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord"); } - this->emitTransforms(v, varyings, args.fUniformHandler, localCoord, - args.fFPCoordTransformHandler); // Transform to device space. SkASSERT(!(proc.fFlags & ProcessorFlags::kHasPerspective)); @@ -743,7 +741,7 @@ class FillRRectOp::Processor::CoverageImpl : public GrGLSLGeometryProcessor { void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&, const CoordTransformRange& transformRange) override { - this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); } }; @@ -781,15 +779,13 @@ class FillRRectOp::Processor::MSAAImpl : public GrGLSLGeometryProcessor { // [-1,-1,+1,+1] space. v->codeAppend("float2 vertexpos = corner + radius_outset * radii;"); - // Emit transforms. + // Write positions GrShaderVar localCoord("", kFloat2_GrSLType); if (hasLocalCoords) { v->codeAppend("float2 localcoord = (local_rect.xy * (1 - vertexpos) + " "local_rect.zw * (1 + vertexpos)) * .5;"); - localCoord.set(kFloat2_GrSLType, "localcoord"); + gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord"); } - this->emitTransforms(v, varyings, args.fUniformHandler, localCoord, - args.fFPCoordTransformHandler); // Transform to device space. if (!hasPerspective) { @@ -849,7 +845,7 @@ class FillRRectOp::Processor::MSAAImpl : public GrGLSLGeometryProcessor { void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&, const CoordTransformRange& transformRange) override { - this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); } }; diff --git a/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.cpp index 9e27f9dfe77..5d20400675b 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.cpp @@ -250,7 +250,7 @@ private: SkArenaAlloc* arena = context->priv().recordTimeAllocator(); // This is equivalent to a GrOpFlushState::detachAppliedClip - GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip(); + GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled(); this->createProgramInfo(context->priv().caps(), arena, writeView, std::move(appliedClip), dstProxyView); @@ -524,7 +524,7 @@ std::unique_ptr<GrDrawOp> GrFillRectOp::MakeOp(GrRecordingContext* context, } void GrFillRectOp::AddFillRectOps(GrRenderTargetContext* rtc, - const GrClip& clip, + const GrClip* clip, GrRecordingContext* context, GrPaint&& paint, GrAAType aaType, diff --git a/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.h b/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.h index 947ee7c8a3f..4a8f211ee05 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.h +++ b/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.h @@ -49,7 +49,7 @@ public: // Bulk API for drawing quads with a single op // TODO(michaelludwig) - remove if the bulk API is not useful for SkiaRenderer static void AddFillRectOps(GrRenderTargetContext*, - const GrClip& clip, + const GrClip* clip, GrRecordingContext*, GrPaint&&, GrAAType, diff --git a/chromium/third_party/skia/src/gpu/ops/GrLatticeOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrLatticeOp.cpp index 7efe3a322fa..fe9983fb51d 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrLatticeOp.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrLatticeOp.cpp @@ -49,7 +49,7 @@ public: void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc, const CoordTransformRange& transformRange) override { const auto& latticeGP = proc.cast<LatticeGP>(); - this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); fColorSpaceXformHelper.setData(pdman, latticeGP.fColorSpaceXform.get()); } @@ -62,11 +62,8 @@ public: args.fVaryingHandler->emitAttributes(latticeGP); this->writeOutputPosition(args.fVertBuilder, gpArgs, latticeGP.fInPosition.name()); - this->emitTransforms(args.fVertBuilder, - args.fVaryingHandler, - args.fUniformHandler, - latticeGP.fInTextureCoords.asShaderVar(), - args.fFPCoordTransformHandler); + gpArgs->fLocalCoordVar = latticeGP.fInTextureCoords.asShaderVar(); + args.fFragBuilder->codeAppend("float2 textureCoords;"); args.fVaryingHandler->addPassThroughAttribute(latticeGP.fInTextureCoords, "textureCoords"); diff --git a/chromium/third_party/skia/src/gpu/ops/GrMeshDrawOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrMeshDrawOp.cpp index f5a8c040477..809620b91b7 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrMeshDrawOp.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrMeshDrawOp.cpp @@ -33,7 +33,7 @@ void GrMeshDrawOp::onPrePrepareDraws(GrRecordingContext* context, SkArenaAlloc* arena = context->priv().recordTimeAllocator(); // This is equivalent to a GrOpFlushState::detachAppliedClip - GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip(); + GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled(); this->createProgramInfo(context->priv().caps(), arena, writeView, std::move(appliedClip), dstProxyView); diff --git a/chromium/third_party/skia/src/gpu/ops/GrOvalOpFactory.cpp b/chromium/third_party/skia/src/gpu/ops/GrOvalOpFactory.cpp index d85755781bf..f720f638607 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrOvalOpFactory.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrOvalOpFactory.cpp @@ -155,14 +155,9 @@ private: // Setup position this->writeOutputPosition(vertBuilder, gpArgs, cgp.fInPosition.name()); - - // emit transforms - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - cgp.fInPosition.asShaderVar(), - cgp.fLocalMatrix, - args.fFPCoordTransformHandler); + this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, + cgp.fInPosition.asShaderVar(), cgp.fLocalMatrix, + &fLocalMatrixUniform); fragBuilder->codeAppend("float d = length(circleEdge.xy);"); fragBuilder->codeAppend("half distanceToOuterEdge = half(circleEdge.z * (1.0 - d));"); @@ -210,24 +205,29 @@ private: const GrShaderCaps&, GrProcessorKeyBuilder* b) { const CircleGeometryProcessor& cgp = gp.cast<CircleGeometryProcessor>(); - uint16_t key; + uint32_t key; key = cgp.fStroke ? 0x01 : 0x0; - key |= cgp.fLocalMatrix.hasPerspective() ? 0x02 : 0x0; - key |= cgp.fInClipPlane.isInitialized() ? 0x04 : 0x0; - key |= cgp.fInIsectPlane.isInitialized() ? 0x08 : 0x0; - key |= cgp.fInUnionPlane.isInitialized() ? 0x10 : 0x0; - key |= cgp.fInRoundCapCenters.isInitialized() ? 0x20 : 0x0; + key |= cgp.fInClipPlane.isInitialized() ? 0x02 : 0x0; + key |= cgp.fInIsectPlane.isInitialized() ? 0x04 : 0x0; + key |= cgp.fInUnionPlane.isInitialized() ? 0x08 : 0x0; + key |= cgp.fInRoundCapCenters.isInitialized() ? 0x10 : 0x0; + key |= (ComputeMatrixKey(cgp.fLocalMatrix) << 16); b->add32(key); } void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc, const CoordTransformRange& transformRange) override { - this->setTransformDataHelper(primProc.cast<CircleGeometryProcessor>().fLocalMatrix, - pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); + this->setTransform(pdman, fLocalMatrixUniform, + primProc.cast<CircleGeometryProcessor>().fLocalMatrix, + &fLocalMatrix); } private: typedef GrGLSLGeometryProcessor INHERITED; + + SkMatrix fLocalMatrix = SkMatrix::InvalidMatrix(); + UniformHandle fLocalMatrixUniform; }; SkMatrix fLocalMatrix; @@ -389,14 +389,10 @@ private: // Setup position this->writeOutputPosition(vertBuilder, gpArgs, bcscgp.fInPosition.name()); + this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, + bcscgp.fInPosition.asShaderVar(), bcscgp.fLocalMatrix, + &fLocalMatrixUniform); - // emit transforms - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - bcscgp.fInPosition.asShaderVar(), - bcscgp.fLocalMatrix, - args.fFPCoordTransformHandler); GrShaderVar fnArgs[] = { GrShaderVar("angleToEdge", kFloat_GrSLType), GrShaderVar("diameter", kFloat_GrSLType), @@ -477,18 +473,22 @@ private: GrProcessorKeyBuilder* b) { const ButtCapDashedCircleGeometryProcessor& bcscgp = gp.cast<ButtCapDashedCircleGeometryProcessor>(); - b->add32(bcscgp.fLocalMatrix.hasPerspective()); + b->add32(ComputeMatrixKey(bcscgp.fLocalMatrix)); } void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc, const CoordTransformRange& transformRange) override { - this->setTransformDataHelper( - primProc.cast<ButtCapDashedCircleGeometryProcessor>().fLocalMatrix, pdman, - transformRange); + this->setTransformDataHelper(pdman, transformRange); + this->setTransform(pdman, fLocalMatrixUniform, + primProc.cast<ButtCapDashedCircleGeometryProcessor>().fLocalMatrix, + &fLocalMatrix); } private: typedef GrGLSLGeometryProcessor INHERITED; + + SkMatrix fLocalMatrix = SkMatrix::InvalidMatrix(); + UniformHandle fLocalMatrixUniform; }; SkMatrix fLocalMatrix; @@ -588,14 +588,10 @@ private: // Setup position this->writeOutputPosition(vertBuilder, gpArgs, egp.fInPosition.name()); + this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, + egp.fInPosition.asShaderVar(), egp.fLocalMatrix, + &fLocalMatrixUniform); - // emit transforms - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - egp.fInPosition.asShaderVar(), - egp.fLocalMatrix, - args.fFPCoordTransformHandler); // For stroked ellipses, we use the full ellipse equation (x^2/a^2 + y^2/b^2 = 1) // to compute both the edges because we need two separate test equations for // the single offset. @@ -666,19 +662,23 @@ private: const GrShaderCaps&, GrProcessorKeyBuilder* b) { const EllipseGeometryProcessor& egp = gp.cast<EllipseGeometryProcessor>(); - uint16_t key = egp.fStroke ? 0x1 : 0x0; - key |= egp.fLocalMatrix.hasPerspective() ? 0x2 : 0x0; + uint32_t key = egp.fStroke ? 0x1 : 0x0; + key |= ComputeMatrixKey(egp.fLocalMatrix) << 1; b->add32(key); } void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc, const CoordTransformRange& transformRange) override { const EllipseGeometryProcessor& egp = primProc.cast<EllipseGeometryProcessor>(); - this->setTransformDataHelper(egp.fLocalMatrix, pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); + this->setTransform(pdman, fLocalMatrixUniform, egp.fLocalMatrix, &fLocalMatrix); } private: typedef GrGLSLGeometryProcessor INHERITED; + + SkMatrix fLocalMatrix = SkMatrix::InvalidMatrix(); + UniformHandle fLocalMatrixUniform; }; Attribute fInPosition; @@ -791,13 +791,7 @@ private: diegp.fInPosition.name(), diegp.fViewMatrix, &fViewMatrixUniform); - - // emit transforms - this->emitTransforms(vertBuilder, - varyingHandler, - uniformHandler, - diegp.fInPosition.asShaderVar(), - args.fFPCoordTransformHandler); + gpArgs->fLocalCoordVar = diegp.fInPosition.asShaderVar(); // for outer curve fragBuilder->codeAppendf("float2 scaledOffset = %s.xy;", offsets0.fsIn()); @@ -862,8 +856,8 @@ private: const GrShaderCaps&, GrProcessorKeyBuilder* b) { const DIEllipseGeometryProcessor& diegp = gp.cast<DIEllipseGeometryProcessor>(); - uint16_t key = static_cast<uint16_t>(diegp.fStyle); - key |= ComputePosKey(diegp.fViewMatrix) << 10; + uint32_t key = static_cast<uint32_t>(diegp.fStyle); + key |= ComputeMatrixKey(diegp.fViewMatrix) << 10; b->add32(key); } @@ -871,17 +865,12 @@ private: const CoordTransformRange& transformRange) override { const DIEllipseGeometryProcessor& diegp = gp.cast<DIEllipseGeometryProcessor>(); - if (!diegp.fViewMatrix.isIdentity() && - !SkMatrixPriv::CheapEqual(fViewMatrix, diegp.fViewMatrix)) - { - fViewMatrix = diegp.fViewMatrix; - pdman.setSkMatrix(fViewMatrixUniform, fViewMatrix); - } - this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange); + this->setTransform(pdman, fViewMatrixUniform, diegp.fViewMatrix, &fViewMatrix); + this->setTransformDataHelper(pdman, transformRange); } private: - SkMatrix fViewMatrix; + SkMatrix fViewMatrix; UniformHandle fViewMatrixUniform; typedef GrGLSLGeometryProcessor INHERITED; diff --git a/chromium/third_party/skia/src/gpu/ops/GrQuadPerEdgeAA.cpp b/chromium/third_party/skia/src/gpu/ops/GrQuadPerEdgeAA.cpp index bc5de24d968..ca420dd839f 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrQuadPerEdgeAA.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrQuadPerEdgeAA.cpp @@ -571,7 +571,7 @@ public: void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc, const CoordTransformRange& transformRange) override { const auto& gp = proc.cast<QuadPerEdgeAAGeometryProcessor>(); - this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); fTextureColorSpaceXformHelper.setData(pdman, gp.fTextureColorSpaceXform.get()); } @@ -604,18 +604,10 @@ public: gpArgs->fPositionVar = gp.fPosition.asShaderVar(); } - // Handle local coordinates if they exist. This is required even when the op - // isn't providing local coords but there are FPs called with explicit coords. - // It installs the uniforms that transform their coordinates in the fragment - // shader. - // NOTE: If the only usage of local coordinates is for the inline texture fetch - // before FPs, then there are no registered FPCoordTransforms and this ends up - // emitting nothing, so there isn't a duplication of local coordinates - this->emitTransforms(args.fVertBuilder, - args.fVaryingHandler, - args.fUniformHandler, - gp.fLocalCoord.asShaderVar(), - args.fFPCoordTransformHandler); + // This attribute will be uninitialized if earlier FP analysis determined no + // local coordinates are needed (and this will not include the inline texture + // fetch this GP does before invoking FPs). + gpArgs->fLocalCoordVar = gp.fLocalCoord.asShaderVar(); // Solid color before any texturing gets modulated in if (gp.fColor.isInitialized()) { diff --git a/chromium/third_party/skia/src/gpu/ops/GrSmallPathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrSmallPathRenderer.cpp index 075376d7f18..0f3ab8ae4fb 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrSmallPathRenderer.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrSmallPathRenderer.cpp @@ -885,7 +885,7 @@ bool GrSmallPathRenderer::onDrawPath(const DrawPathArgs& args) { std::unique_ptr<GrDrawOp> op = SmallPathOp::Make( args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix, fAtlas.get(), &fShapeCache, &fShapeList, args.fGammaCorrect, args.fUserStencilSettings); - args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op)); + args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op)); return true; } diff --git a/chromium/third_party/skia/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp index 59a8bf75a7a..fcff78cf6f0 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp @@ -7,7 +7,6 @@ #include "include/private/GrRecordingContext.h" #include "src/gpu/GrCaps.h" -#include "src/gpu/GrFixedClip.h" #include "src/gpu/GrGpu.h" #include "src/gpu/GrPath.h" #include "src/gpu/GrRenderTargetContextPriv.h" @@ -101,7 +100,7 @@ void GrStencilAndCoverPathRenderer::onStencilPath(const StencilPathArgs& args) { "GrStencilAndCoverPathRenderer::onStencilPath"); sk_sp<GrPath> p(get_gr_path(fResourceProvider, *args.fShape)); args.fRenderTargetContext->priv().stencilPath( - *args.fClip, args.fDoStencilMSAA, *args.fViewMatrix, std::move(p)); + args.fClip, args.fDoStencilMSAA, *args.fViewMatrix, std::move(p)); } bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) { @@ -125,15 +124,16 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) { args.fRenderTargetContext->height()); // Inverse fill. // fake inverse with a stencil and cover - GrAppliedClip appliedClip; - if (!args.fClip->apply( + GrAppliedClip appliedClip(args.fRenderTargetContext->dimensions()); + if (args.fClip && !args.fClip->apply( args.fContext, args.fRenderTargetContext, doStencilMSAA, true, &appliedClip, &devBounds)) { return true; } - GrStencilClip stencilClip(appliedClip.stencilStackID()); + GrStencilClip stencilClip(args.fRenderTargetContext->dimensions(), + appliedClip.stencilStackID()); if (appliedClip.scissorState().enabled()) { - stencilClip.fixedClip().setScissor(appliedClip.scissorState().rect()); + SkAssertResult(stencilClip.fixedClip().setScissor(appliedClip.scissorState().rect())); } if (appliedClip.windowRectsState().enabled()) { stencilClip.fixedClip().setWindowRectangles(appliedClip.windowRectsState().windows(), @@ -142,7 +142,7 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) { // Just ignore the analytic FPs (if any) during the stencil pass. They will still clip the // final draw and it is meaningless to multiply by coverage when drawing to stencil. args.fRenderTargetContext->priv().stencilPath( - stencilClip, GrAA(doStencilMSAA), viewMatrix, std::move(path)); + &stencilClip, GrAA(doStencilMSAA), viewMatrix, std::move(path)); { static constexpr GrUserStencilSettings kInvertedCoverPass( @@ -179,14 +179,14 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) { doStencilMSAA = GrAA::kYes; } args.fRenderTargetContext->priv().stencilRect( - *args.fClip, &kInvertedCoverPass, std::move(args.fPaint), doStencilMSAA, + args.fClip, &kInvertedCoverPass, std::move(args.fPaint), doStencilMSAA, coverMatrix, coverBounds, &localMatrix); } } else { std::unique_ptr<GrDrawOp> op = GrDrawPathOp::Make( args.fContext, viewMatrix, std::move(args.fPaint), GrAA(doStencilMSAA), std::move(path)); - args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op)); + args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op)); } return true; diff --git a/chromium/third_party/skia/src/gpu/ops/GrTextureOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrTextureOp.cpp index 92904e97fad..ee712911f95 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrTextureOp.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrTextureOp.cpp @@ -95,7 +95,7 @@ static bool filter_has_effect(const GrQuad& srcQuad, const GrQuad& dstQuad) { // regular and rectangular textures, w/ or w/o origin correction. struct NormalizationParams { float fIW; // 1 / width of texture, or 1.0 for texture rectangles - float fIH; // 1 / height of texture, or 1.0 for tex rects, X -1 if bottom-left origin + float fInvH; // 1 / height of texture, or 1.0 for tex rects, X -1 if bottom-left origin float fYOffset; // 0 for top-left origin, height of [normalized] tex if bottom-left }; static NormalizationParams proxy_normalization_params(const GrSurfaceProxy* proxy, @@ -120,21 +120,13 @@ static NormalizationParams proxy_normalization_params(const GrSurfaceProxy* prox } } -static SkRect inset_subset_for_bilerp(const NormalizationParams& params, const SkRect& subsetRect) { - // Normalized pixel size is also equal to iw and ih, so the insets for bilerp are just - // in those units and can be applied safely after normalization. However, if the subset is - // smaller than a texel, it should clamp to the center of that axis. - float dw = subsetRect.width() < params.fIW ? subsetRect.width() : params.fIW; - float dh = subsetRect.height() < params.fIH ? subsetRect.height() : params.fIH; - return subsetRect.makeInset(0.5f * dw, 0.5f * dh); -} - // Normalize the subset. If 'subsetRect' is null, it is assumed no subset constraint is desired, // so a sufficiently large rect is returned even if the quad ends up batched with an op that uses -// subsets overall. -static SkRect normalize_subset(GrSamplerState::Filter filter, - const NormalizationParams& params, - const SkRect* subsetRect) { +// subsets overall. When there is a subset it will be inset based on the filter mode. Normalization +// and y-flipping are applied as indicated by NormalizationParams. +static SkRect normalize_and_inset_subset(GrSamplerState::Filter filter, + const NormalizationParams& params, + const SkRect* subsetRect) { static constexpr SkRect kLargeRect = {-100000, -100000, 1000000, 1000000}; if (!subsetRect) { // Either the quad has no subset constraint and is batched with a subset constrained op @@ -144,10 +136,20 @@ static SkRect normalize_subset(GrSamplerState::Filter filter, } auto ltrb = skvx::Vec<4, float>::Load(subsetRect); + auto flipHi = skvx::Vec<4, float>({1.f, 1.f, -1.f, -1.f}); + if (filter == GrSamplerState::Filter::kNearest) { + // Make sure our insetting puts us at pixel centers. + ltrb = skvx::floor(ltrb*flipHi)*flipHi; + } + // Inset with pin to the rect center. + ltrb += skvx::Vec<4, float>({.5f, .5f, -.5f, -.5f}); + auto mid = (skvx::shuffle<2, 3, 0, 1>(ltrb) + ltrb)*0.5f; + ltrb = skvx::min(ltrb*flipHi, mid*flipHi)*flipHi; + // Normalize and offset - ltrb = mad(ltrb, {params.fIW, params.fIH, params.fIW, params.fIH}, + ltrb = mad(ltrb, {params.fIW, params.fInvH, params.fIW, params.fInvH}, {0.f, params.fYOffset, 0.f, params.fYOffset}); - if (params.fIH < 0.f) { + if (params.fInvH < 0.f) { // Flip top and bottom to keep the rect sorted when loaded back to SkRect. ltrb = skvx::shuffle<0, 3, 2, 1>(ltrb); } @@ -163,7 +165,7 @@ static void normalize_src_quad(const NormalizationParams& params, // The src quad should not have any perspective SkASSERT(!srcQuad->hasPerspective()); skvx::Vec<4, float> xs = srcQuad->x4f() * params.fIW; - skvx::Vec<4, float> ys = mad(srcQuad->y4f(), params.fIH, params.fYOffset); + skvx::Vec<4, float> ys = mad(srcQuad->y4f(), params.fInvH, params.fYOffset); xs.store(srcQuad->xs()); ys.store(srcQuad->ys()); } @@ -183,6 +185,32 @@ static int proxy_run_count(const GrRenderTargetContext::TextureSetEntry set[], i return actualProxyRunCount; } +static bool safe_to_ignore_subset_rect(GrAAType aaType, GrSamplerState::Filter filter, + const DrawQuad& quad, const SkRect& subsetRect) { + // If both the device and local quad are both axis-aligned, and filtering is off, the local quad + // can push all the way up to the edges of the the subset rect and the sampler shouldn't + // overshoot. Unfortunately, antialiasing adds enough jitter that we can only rely on this in + // the non-antialiased case. + SkRect localBounds = quad.fLocal.bounds(); + if (aaType == GrAAType::kNone && + filter == GrSamplerState::Filter::kNearest && + quad.fDevice.quadType() == GrQuad::Type::kAxisAligned && + quad.fLocal.quadType() == GrQuad::Type::kAxisAligned && + subsetRect.contains(localBounds)) { + + return true; + } + + // If the subset rect is inset by at least 0.5 pixels into the local quad's bounds, the + // sampler shouldn't overshoot, even when antialiasing and filtering is taken into account. + if (subsetRect.makeInset(0.5f, 0.5f).contains(localBounds)) { + return true; + } + + // The subset rect cannot be ignored safely. + return false; +} + /** * Op that implements GrTextureOp::Make. It draws textured quads. Each quad can modulate against a * the texture by color. The blend with the destination is always src-over. The edges are non-AA. @@ -415,9 +443,7 @@ private: void allocatePrePreparedVertices(SkArenaAlloc* arena) { fPrePreparedVertices = arena->makeArrayDefault<char>(this->totalSizeInBytes()); } - }; - // If subsetRect is not null it will be used to apply a strict src rect-style constraint. TextureOp(GrSurfaceProxyView proxyView, sk_sp<GrColorSpaceXform> textureColorSpaceXform, @@ -444,19 +470,19 @@ private: !subsetRect->contains(proxyView.proxy()->backingStoreBoundsRect())); // We may have had a strict constraint with nearest filter solely due to possible AA bloat. - // If we don't have (or determined we don't need) coverage AA then we can skip using a - // subset. - if (subsetRect && filter == GrSamplerState::Filter::kNearest && - aaType != GrAAType::kCoverage) { - subsetRect = nullptr; - fMetadata.fSubset = static_cast<uint16_t>(Subset::kNo); + // Try to identify cases where the subsetting isn't actually necessary, and skip it. + if (subsetRect) { + if (safe_to_ignore_subset_rect(aaType, filter, *quad, *subsetRect)) { + subsetRect = nullptr; + fMetadata.fSubset = static_cast<uint16_t>(Subset::kNo); + } } // Normalize src coordinates and the subset (if set) NormalizationParams params = proxy_normalization_params(proxyView.proxy(), proxyView.origin()); normalize_src_quad(params, &quad->fLocal); - SkRect subset = normalize_subset(filter, params, subsetRect); + SkRect subset = normalize_and_inset_subset(filter, params, subsetRect); // Set bounds before clipping so we don't have to worry about unioning the bounds of // the two potential quads (GrQuad::bounds() is perspective-safe). @@ -542,11 +568,6 @@ private: netFilter = GrSamplerState::Filter::kBilerp; } - // Normalize the src quads and apply origin - NormalizationParams proxyParams = proxy_normalization_params( - curProxy, set[q].fProxyView.origin()); - normalize_src_quad(proxyParams, &quad.fLocal); - // Update overall bounds of the op as the union of all quads bounds.joinPossiblyEmptyRect(quad.fDevice.bounds()); @@ -554,6 +575,7 @@ private: GrAAType aaForQuad; GrQuadUtils::ResolveAAType(aaType, set[q].fAAFlags, quad.fDevice, &aaForQuad, &quad.fEdgeFlags); + // Resolve sets aaForQuad to aaType or None, there is never a change between aa methods SkASSERT(aaForQuad == GrAAType::kNone || aaForQuad == aaType); if (netAAType == GrAAType::kNone && aaForQuad != GrAAType::kNone) { @@ -563,27 +585,29 @@ private: // Calculate metadata for the entry const SkRect* subsetForQuad = nullptr; if (constraint == SkCanvas::kStrict_SrcRectConstraint) { - // Check (briefly) if the strict constraint is needed for this set entry - if (!set[q].fSrcRect.contains(curProxy->backingStoreBoundsRect()) && - (filter == GrSamplerState::Filter::kBilerp || - aaForQuad == GrAAType::kCoverage)) { - // Can't rely on hardware clamping and the draw will access outer texels - // for AA and/or bilerp. Unlike filter quality, this op still has per-quad - // control over AA so that can check aaForQuad, not netAAType. - netSubset = Subset::kYes; - subsetForQuad = &set[q].fSrcRect; + // Check (briefly) if the subset rect is actually needed for this set entry. + SkRect* subsetRect = &set[q].fSrcRect; + if (!subsetRect->contains(curProxy->backingStoreBoundsRect())) { + if (!safe_to_ignore_subset_rect(aaForQuad, filter, quad, *subsetRect)) { + netSubset = Subset::kYes; + subsetForQuad = subsetRect; + } } } + + // Normalize the src quads and apply origin + NormalizationParams proxyParams = proxy_normalization_params( + curProxy, set[q].fProxyView.origin()); + normalize_src_quad(proxyParams, &quad.fLocal); + // This subset may represent a no-op, otherwise it will have the origin and dimensions // of the texture applied to it. Insetting for bilinear filtering is deferred until // on[Pre]Prepare so that the overall filter can be lazily determined. - SkRect subset = normalize_subset(filter, proxyParams, subsetForQuad); + SkRect subset = normalize_and_inset_subset(filter, proxyParams, subsetForQuad); // Always append a quad (or 2 if perspective clipped), it just may refer back to a prior // ViewCountPair (this frequently happens when Chrome draws 9-patches). - float alpha = SkTPin(set[q].fAlpha, 0.f, 1.f); - fViewCountPairs[p].fQuadCnt += this->appendQuad( - &quad, {alpha, alpha, alpha, alpha}, subset); + fViewCountPairs[p].fQuadCnt += this->appendQuad(&quad, set[q].fColor, subset); } // The # of proxy switches should match what was provided (+1 because we incremented p // when a new proxy was encountered). @@ -689,21 +713,12 @@ private: const int quadCnt = op.fViewCountPairs[p].fQuadCnt; SkDEBUGCODE(int meshVertexCnt = quadCnt * desc->fVertexSpec.verticesPerQuad()); - // Can just use top-left for origin here since we only need the dimensions to - // determine the texel size for insetting. - NormalizationParams params = proxy_normalization_params( - op.fViewCountPairs[p].fProxy.get(), kTopLeft_GrSurfaceOrigin); - - bool inset = texOp->fMetadata.filter() != GrSamplerState::Filter::kNearest; - for (int i = 0; i < quadCnt && iter.next(); ++i) { SkASSERT(iter.isLocalValid()); const ColorSubsetAndAA& info = iter.metadata(); tessellator.append(iter.deviceQuad(), iter.localQuad(), info.fColor, - inset ? inset_subset_for_bilerp(params, info.fSubsetRect) - : info.fSubsetRect, - info.aaFlags()); + info.fSubsetRect, info.aaFlags()); } SkASSERT((totVerticesSeen + meshVertexCnt) * vertexSize @@ -1041,21 +1056,20 @@ std::unique_ptr<GrDrawOp> GrTextureOp::Make(GrRecordingContext* context, const auto& caps = *context->priv().caps(); SkRect localRect; if (quad->fLocal.asRect(&localRect)) { - fp = GrTextureEffect::MakeSubset(std::move(proxyView), alphaType, SkMatrix::I(), filter, - *subset, localRect, caps); + fp = GrTextureEffect::MakeSubset(std::move(proxyView), alphaType, SkMatrix::I(), + filter, *subset, localRect, caps); } else { - fp = GrTextureEffect::MakeSubset(std::move(proxyView), alphaType, SkMatrix::I(), filter, - *subset, caps); + fp = GrTextureEffect::MakeSubset(std::move(proxyView), alphaType, SkMatrix::I(), + filter, *subset, caps); } } else { fp = GrTextureEffect::Make(std::move(proxyView), alphaType, SkMatrix::I(), filter); } fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(textureXform)); - paint.addColorFragmentProcessor(std::move(fp)); if (saturate == GrTextureOp::Saturate::kYes) { - paint.addColorFragmentProcessor(GrClampFragmentProcessor::Make(false)); + fp = GrClampFragmentProcessor::Make(std::move(fp), /*clampToPremul=*/false); } - + paint.addColorFragmentProcessor(std::move(fp)); return GrFillRectOp::Make(context, std::move(paint), aaType, quad); } } @@ -1064,7 +1078,7 @@ std::unique_ptr<GrDrawOp> GrTextureOp::Make(GrRecordingContext* context, class GrTextureOp::BatchSizeLimiter { public: BatchSizeLimiter(GrRenderTargetContext* rtc, - const GrClip& clip, + const GrClip* clip, GrRecordingContext* context, int numEntries, GrSamplerState::Filter filter, @@ -1102,7 +1116,7 @@ public: private: GrRenderTargetContext* fRTC; - const GrClip& fClip; + const GrClip* fClip; GrRecordingContext* fContext; GrSamplerState::Filter fFilter; GrTextureOp::Saturate fSaturate; @@ -1116,7 +1130,7 @@ private: // Greedily clump quad draws together until the index buffer limit is exceeded. void GrTextureOp::AddTextureSetOps(GrRenderTargetContext* rtc, - const GrClip& clip, + const GrClip* clip, GrRecordingContext* context, GrRenderTargetContext::TextureSetEntry set[], int cnt, @@ -1141,7 +1155,6 @@ void GrTextureOp::AddTextureSetOps(GrRenderTargetContext* rtc, // automatically creates the appropriate GrFillRectOp to emulate GrTextureOp. SkMatrix ctm; for (int i = 0; i < cnt; ++i) { - float alpha = set[i].fAlpha; ctm = viewMatrix; if (set[i].fPreViewMatrix) { ctm.preConcat(*set[i].fPreViewMatrix); @@ -1164,7 +1177,7 @@ void GrTextureOp::AddTextureSetOps(GrRenderTargetContext* rtc, ? &set[i].fSrcRect : nullptr; auto op = Make(context, set[i].fProxyView, set[i].fSrcAlphaType, textureColorSpaceXform, - filter, {alpha, alpha, alpha, alpha}, saturate, blendMode, aaType, + filter, set[i].fColor, saturate, blendMode, aaType, &quad, subset); rtc->addDrawOp(clip, std::move(op)); } diff --git a/chromium/third_party/skia/src/gpu/ops/GrTextureOp.h b/chromium/third_party/skia/src/gpu/ops/GrTextureOp.h index 404535b68f4..2c1f48e16cd 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrTextureOp.h +++ b/chromium/third_party/skia/src/gpu/ops/GrTextureOp.h @@ -56,7 +56,7 @@ public: // supported, or if the blend mode is not src-over. 'cnt' is the size of the entry array. // 'proxyCnt' <= 'cnt' and represents the number of proxy switches within the array. static void AddTextureSetOps(GrRenderTargetContext*, - const GrClip& clip, + const GrClip* clip, GrRecordingContext*, GrRenderTargetContext::TextureSetEntry[], int cnt, diff --git a/chromium/third_party/skia/src/gpu/ops/GrTriangulatingPathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrTriangulatingPathRenderer.cpp index 67f829827ae..7e696c4ae2f 100644 --- a/chromium/third_party/skia/src/gpu/ops/GrTriangulatingPathRenderer.cpp +++ b/chromium/third_party/skia/src/gpu/ops/GrTriangulatingPathRenderer.cpp @@ -11,12 +11,12 @@ #include "src/core/SkGeometry.h" #include "src/gpu/GrAuditTrail.h" #include "src/gpu/GrCaps.h" -#include "src/gpu/GrClip.h" #include "src/gpu/GrDefaultGeoProcFactory.h" #include "src/gpu/GrDrawOpTest.h" #include "src/gpu/GrEagerVertexAllocator.h" #include "src/gpu/GrOpFlushState.h" #include "src/gpu/GrProgramInfo.h" +#include "src/gpu/GrRenderTargetContext.h" #include "src/gpu/GrResourceCache.h" #include "src/gpu/GrResourceProvider.h" #include "src/gpu/GrSimpleMesh.h" @@ -419,12 +419,11 @@ private: bool GrTriangulatingPathRenderer::onDrawPath(const DrawPathArgs& args) { GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(), "GrTriangulatingPathRenderer::onDrawPath"); - SkIRect clipBoundsI = args.fClip->getConservativeBounds(args.fRenderTargetContext->width(), - args.fRenderTargetContext->height()); + std::unique_ptr<GrDrawOp> op = TriangulatingPathOp::Make( - args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix, clipBoundsI, - args.fAAType, args.fUserStencilSettings); - args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op)); + args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix, + *args.fClipConservativeBounds, args.fAAType, args.fUserStencilSettings); + args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op)); return true; } diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.cpp b/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.cpp index 142e20cb5fb..cda13bea6f6 100644 --- a/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.cpp +++ b/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.cpp @@ -18,8 +18,8 @@ namespace { constexpr static GrGeometryProcessor::Attribute kInstanceAttribs[] = { - {"devibounds", kInt4_GrVertexAttribType, kInt4_GrSLType}, - {"dev_to_atlas_offset", kInt2_GrVertexAttribType, kInt2_GrSLType}, + {"dev_xywh", kInt4_GrVertexAttribType, kInt4_GrSLType}, + {"atlas_xy", kInt2_GrVertexAttribType, kInt2_GrSLType}, {"color", kFloat4_GrVertexAttribType, kHalf4_GrSLType}, {"viewmatrix_scaleskew", kFloat4_GrVertexAttribType, kFloat4_GrSLType}, {"viewmatrix_trans", kFloat2_GrVertexAttribType, kFloat2_GrSLType}}; @@ -73,22 +73,24 @@ class DrawAtlasPathShader::Impl : public GrGLSLGeometryProcessor { args.fVertBuilder->codeAppendf(R"( float2 T = float2(sk_VertexID & 1, sk_VertexID >> 1); - float2 devcoord = mix(float2(devibounds.xy), float2(devibounds.zw), T); - float2 atlascoord = devcoord + float2(dev_to_atlas_offset); + float2 devtopleft = float2(dev_xywh.xy); + float2 devcoord = abs(float2(dev_xywh.zw)) * T + devtopleft; + float2 atlascoord = devcoord - devtopleft; + if (dev_xywh.w < 0) { // Negative height indicates that the path is transposed. + atlascoord = atlascoord.yx; + } + atlascoord += atlas_xy; %s = atlascoord * %s;)", atlasCoord.vsOut(), atlasAdjust); gpArgs->fPositionVar.set(kFloat2_GrSLType, "devcoord"); - GrShaderVar localCoord = gpArgs->fPositionVar; if (shader.fUsesLocalCoords) { args.fVertBuilder->codeAppendf(R"( float2x2 M = float2x2(viewmatrix_scaleskew); float2 localcoord = inverse(M) * (devcoord - viewmatrix_trans);)"); - localCoord.set(kFloat2_GrSLType, "localcoord"); + gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord"); } - this->emitTransforms(args.fVertBuilder, args.fVaryingHandler, args.fUniformHandler, - localCoord, args.fFPCoordTransformHandler); args.fFragBuilder->codeAppendf("%s = ", args.fOutputCoverage); args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], atlasCoord.fsIn()); @@ -99,7 +101,7 @@ class DrawAtlasPathShader::Impl : public GrGLSLGeometryProcessor { const CoordTransformRange& transformRange) override { const SkISize& dimensions = primProc.cast<DrawAtlasPathShader>().fAtlasDimensions; pdman.set2f(fAtlasAdjustUniform, 1.f / dimensions.width(), 1.f / dimensions.height()); - this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); } GrGLSLUniformHandler::UniformHandle fAtlasAdjustUniform; diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.h b/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.h index b20583ba41c..43f8671167b 100644 --- a/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.h +++ b/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.h @@ -8,6 +8,7 @@ #ifndef GrDrawAtlasPathOp_DEFINED #define GrDrawAtlasPathOp_DEFINED +#include "src/core/SkIPoint16.h" #include "src/gpu/ops/GrDrawOp.h" class GrDrawAtlasPathOp : public GrDrawOp { @@ -15,12 +16,13 @@ public: DEFINE_OP_CLASS_ID GrDrawAtlasPathOp(int numRenderTargetSamples, sk_sp<GrTextureProxy> atlasProxy, - const SkIRect& devIBounds, const SkIVector& devToAtlasOffset, - const SkMatrix& viewMatrix, GrPaint&& paint) + const SkIRect& devIBounds, const SkIPoint16& locationInAtlas, + bool transposedInAtlas, const SkMatrix& viewMatrix, GrPaint&& paint) : GrDrawOp(ClassID()) , fEnableHWAA(numRenderTargetSamples > 1) , fAtlasProxy(std::move(atlasProxy)) - , fInstanceList(devIBounds, devToAtlasOffset, paint.getColor4f(), viewMatrix) + , fInstanceList(devIBounds, locationInAtlas, transposedInAtlas, paint.getColor4f(), + viewMatrix) , fProcessors(std::move(paint)) { this->setBounds(SkRect::Make(devIBounds), HasAABloat::kYes, IsHairline::kNo); } @@ -53,25 +55,27 @@ private: } return stride; } - Instance(const SkIRect& devIBounds, SkIVector devToAtlasOffset, const SkPMColor4f& color, - const SkMatrix& m) - : fDevIBounds(devIBounds) - , fDevToAtlasOffset(devToAtlasOffset) + Instance(const SkIRect& devIBounds, const SkIPoint16& locationInAtlas, + bool transposedInAtlas, const SkPMColor4f& color, const SkMatrix& m) + : fDevXYWH{devIBounds.left(), devIBounds.top(), devIBounds.width(), + // We use negative height to indicate that the path is transposed. + (transposedInAtlas) ? -devIBounds.height() : devIBounds.height()} + , fAtlasXY{locationInAtlas.x(), locationInAtlas.y()} , fColor(color) , fViewMatrixIfUsingLocalCoords{m.getScaleX(), m.getSkewY(), m.getSkewX(), m.getScaleY(), m.getTranslateX(), m.getTranslateY()} { } - SkIRect fDevIBounds; - SkIVector fDevToAtlasOffset; + std::array<int, 4> fDevXYWH; + std::array<int, 2> fAtlasXY; SkPMColor4f fColor; float fViewMatrixIfUsingLocalCoords[6]; }; struct InstanceList { - InstanceList(const SkIRect& devIBounds, SkIVector devToAtlasOffset, - const SkPMColor4f& color, const SkMatrix& viewMatrix) - : fInstance(devIBounds, devToAtlasOffset, color, viewMatrix) { + InstanceList(const SkIRect& devIBounds, const SkIPoint16& locationInAtlas, + bool transposedInAtlas, const SkPMColor4f& color, const SkMatrix& viewMatrix) + : fInstance(devIBounds, locationInAtlas, transposedInAtlas, color, viewMatrix) { } InstanceList* fNext = nullptr; Instance fInstance; diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrFillPathShader.cpp b/chromium/third_party/skia/src/gpu/tessellate/GrFillPathShader.cpp index f87ac4a03ce..93e6e598d5f 100644 --- a/chromium/third_party/skia/src/gpu/tessellate/GrFillPathShader.cpp +++ b/chromium/third_party/skia/src/gpu/tessellate/GrFillPathShader.cpp @@ -26,11 +26,8 @@ public: args.fVertBuilder->codeAppend("float2 localcoord, vertexpos;"); shader.emitVertexCode(this, args.fVertBuilder, viewMatrix, args.fUniformHandler); - this->emitTransforms(args.fVertBuilder, args.fVaryingHandler, args.fUniformHandler, - GrShaderVar("localcoord", kFloat2_GrSLType), - args.fFPCoordTransformHandler); - gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertexpos"); + gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord"); const char* color; fColorUniform = args.fUniformHandler->addUniform( @@ -53,7 +50,7 @@ public: pdman.set4f(fPathBoundsUniform, b.left(), b.top(), b.right(), b.bottom()); } - this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange); + this->setTransformDataHelper(pdman, transformRange); } GrGLSLUniformHandler::UniformHandle fViewMatrixUniform; diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h b/chromium/third_party/skia/src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h index 258e175fdbb..482f2e3bb37 100644 --- a/chromium/third_party/skia/src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h +++ b/chromium/third_party/skia/src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h @@ -40,10 +40,12 @@ // recursion, we manipulate an O(log N) stack to determine the correct middle-out triangulation. class GrMiddleOutPolygonTriangulator { public: - GrMiddleOutPolygonTriangulator(SkPoint* vertexData, int maxVertices) - : fTriangleData(reinterpret_cast<std::array<SkPoint, 3>*>(vertexData)) { + GrMiddleOutPolygonTriangulator(SkPoint* vertexData, int perTriangleVertexAdvance, + int maxPushVertexCalls) + : fVertexData(vertexData) + , fPerTriangleVertexAdvance(perTriangleVertexAdvance) { // Determine the deepest our stack can ever go. - int maxStackDepth = SkNextLog2(maxVertices) + 1; + int maxStackDepth = SkNextLog2(maxPushVertexCalls) + 1; if (maxStackDepth > kStackPreallocCount) { fVertexStack.reset(maxStackDepth); } @@ -75,17 +77,15 @@ public: // (This is a stack-based implementation of the recursive example method from the class // comment.) while (vertexIdxDelta == fTop->fVertexIdxDelta) { - *fTriangleData++ = {fTop[-1].fPoint, fTop->fPoint, pt}; + this->popTopTriangle(pt); vertexIdxDelta *= 2; - this->popTop(); } - this->pushTop(); - *fTop = {vertexIdxDelta, pt}; + this->pushVertex(vertexIdxDelta, pt); } int close() { - if (fTop == &fVertexStack[0]) { // The stack only contains one point (the starting point). - return fTotalClosedVertexCount; + if (fTop == fVertexStack) { // The stack only contains one point (the starting point). + return fTotalClosedTriangleCount; } // We will count vertices by walking the stack backwards. int finalVertexCount = 1; @@ -94,24 +94,23 @@ public: // vertexIdxDeltas match. const SkPoint& p0 = fVertexStack[0].fPoint; SkASSERT(fTop->fPoint != p0); // We should have detected and handled this case earlier. - while (fTop > &fVertexStack[1]) { - *fTriangleData++ = {fTop[-1].fPoint, fTop->fPoint, p0}; + while (fTop - 1 > fVertexStack) { finalVertexCount += fTop->fVertexIdxDelta; - this->popTop(); + this->popTopTriangle(p0); } + SkASSERT(fTop == fVertexStack + 1); finalVertexCount += fTop->fVertexIdxDelta; - this->popTop(); - SkASSERT(fTop == &fVertexStack[0]); SkASSERT(fVertexStack[0].fVertexIdxDelta == 0); + fTop = fVertexStack; int numTriangles = finalVertexCount - 2; SkASSERT(numTriangles >= 0); - fTotalClosedVertexCount += numTriangles * 3; - return fTotalClosedVertexCount; + fTotalClosedTriangleCount += numTriangles; + return fTotalClosedTriangleCount; } void closeAndMove(const SkPoint& startPt) { this->close(); - SkASSERT(fTop == &fVertexStack[0]); // The stack should only contain a starting point now. + SkASSERT(fTop == fVertexStack); // The stack should only contain a starting point now. fTop->fPoint = startPt; // Modify the starting point. SkASSERT(fTop->fVertexIdxDelta == 0); // Ensure we are in the initial stack state. } @@ -129,23 +128,30 @@ private: SkPoint fPoint; }; - void pushTop() { + void pushVertex(int vertexIdxDelta, const SkPoint& point) { ++fTop; // We should never push deeper than fStackAllocCount. - SkASSERT(fTop < &fVertexStack[fStackAllocCount]); + SkASSERT(fTop < fVertexStack + fStackAllocCount); + fTop->fVertexIdxDelta = vertexIdxDelta; + fTop->fPoint = point; } - void popTop() { - SkASSERT(fTop > &fVertexStack[0]); // We should never pop the starting point. + void popTopTriangle(const SkPoint& lastPt) { + SkASSERT(fTop > fVertexStack); // We should never pop the starting point. --fTop; + fVertexData[0] = fTop[0].fPoint; + fVertexData[1] = fTop[1].fPoint; + fVertexData[2] = lastPt; + fVertexData += fPerTriangleVertexAdvance; } constexpr static int kStackPreallocCount = 32; SkAutoSTMalloc<kStackPreallocCount, StackVertex> fVertexStack; SkDEBUGCODE(int fStackAllocCount;) StackVertex* fTop; - std::array<SkPoint, 3>* fTriangleData; - int fTotalClosedVertexCount = 0; + SkPoint* fVertexData; + int fPerTriangleVertexAdvance; + int fTotalClosedTriangleCount = 0; }; #endif diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrResolveLevelCounter.h b/chromium/third_party/skia/src/gpu/tessellate/GrResolveLevelCounter.h new file mode 100644 index 00000000000..66b0540fea5 --- /dev/null +++ b/chromium/third_party/skia/src/gpu/tessellate/GrResolveLevelCounter.h @@ -0,0 +1,73 @@ +/* + * Copyright 2020 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrResolveLevelCounter_DEFINED +#define GrResolveLevelCounter_DEFINED + +#include "src/core/SkPathPriv.h" +#include "src/gpu/tessellate/GrStencilPathShader.h" +#include "src/gpu/tessellate/GrWangsFormula.h" + +// This class helps bin cubics by log2 "resolveLevel" when we don't use hardware tessellation. It is +// composed of simple counters that track how many cubics we intend to draw at each resolveLevel, +// and how many resolveLevels there are that have at least one cubic. +class GrResolveLevelCounter { +public: + void reset() { + memset(fInstanceCounts, 0, sizeof(fInstanceCounts)); + SkDEBUGCODE(fHasCalledReset = true;) + } + + void reset(const SkPath& path, const SkMatrix& viewMatrix, float intolerance) { + this->reset(); + GrVectorXform xform(viewMatrix); + for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) { + switch (verb) { + case SkPathVerb::kQuad: + // Quadratics get converted to cubics before rendering. + this->countCubic(GrWangsFormula::quadratic_log2(intolerance, pts, xform)); + break; + case SkPathVerb::kCubic: + this->countCubic(GrWangsFormula::cubic_log2(intolerance, pts, xform)); + break; + default: + break; + } + } + } + + void countCubic(int resolveLevel) { + SkASSERT(fHasCalledReset); + SkASSERT(resolveLevel >= 0); + if (resolveLevel == 0) { + // Cubics with 2^0=1 segments are empty (zero area). We ignore them completely. + return; + } + resolveLevel = std::min(resolveLevel, GrMiddleOutCubicShader::kMaxResolveLevel); + if (!fInstanceCounts[resolveLevel]++) { + ++fTotalCubicIndirectDrawCount; + } + ++fTotalCubicInstanceCount; + } + + int operator[](int resolveLevel) const { + SkASSERT(fHasCalledReset); + SkASSERT(resolveLevel > 0); // Empty cubics with 2^0=1 segments do not need to be drawn. + SkASSERT(resolveLevel <= GrMiddleOutCubicShader::kMaxResolveLevel); + return fInstanceCounts[resolveLevel]; + } + int totalCubicInstanceCount() const { return fTotalCubicInstanceCount; } + int totalCubicIndirectDrawCount() const { return fTotalCubicIndirectDrawCount; } + +private: + SkDEBUGCODE(bool fHasCalledReset = false;) + int fInstanceCounts[GrMiddleOutCubicShader::kMaxResolveLevel + 1]; + int fTotalCubicInstanceCount = 0; + int fTotalCubicIndirectDrawCount = 0; +}; + +#endif diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.cpp b/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.cpp index 9b36c2ac582..c6e95ef9027 100644 --- a/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.cpp +++ b/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.cpp @@ -35,6 +35,7 @@ constexpr char kEvalCubicFn[] = R"( })"; class GrStencilPathShader::Impl : public GrGLSLGeometryProcessor { +protected: void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { const auto& shader = args.fGP.cast<GrStencilPathShader>(); args.fVaryingHandler->emitAttributes(shader); @@ -45,7 +46,7 @@ class GrStencilPathShader::Impl : public GrGLSLGeometryProcessor { fViewMatrixUniform = args.fUniformHandler->addUniform( nullptr, kVertex_GrShaderFlag, kFloat3x3_GrSLType, "view_matrix", &viewMatrix); args.fVertBuilder->codeAppendf( - "float2 vertexpos = (%s * float3(point, 1)).xy;", viewMatrix); + "float2 vertexpos = (%s * float3(inputPoint, 1)).xy;", viewMatrix); vertexPos.set(kFloat2_GrSLType, "vertexpos"); } @@ -75,8 +76,10 @@ GrGLSLPrimitiveProcessor* GrStencilPathShader::createGLSLInstance(const GrShader return new Impl; } -SkString GrStencilCubicShader::getTessControlShaderGLSL(const char* versionAndExtensionDecls, - const GrShaderCaps&) const { +SkString GrTessellateCubicShader::getTessControlShaderGLSL(const GrGLSLPrimitiveProcessor*, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, + const GrShaderCaps&) const { SkString code(versionAndExtensionDecls); code.append(kWangsFormulaCubicFn); code.append(R"( @@ -115,8 +118,9 @@ SkString GrStencilCubicShader::getTessControlShaderGLSL(const char* versionAndEx return code; } -SkString GrStencilCubicShader::getTessEvaluationShaderGLSL(const char* versionAndExtensionDecls, - const GrShaderCaps&) const { +SkString GrTessellateCubicShader::getTessEvaluationShaderGLSL( + const GrGLSLPrimitiveProcessor*, const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, const GrShaderCaps&) const { SkString code(versionAndExtensionDecls); code.append(kEvalCubicFn); code.append(R"( @@ -147,8 +151,10 @@ SkString GrStencilCubicShader::getTessEvaluationShaderGLSL(const char* versionAn return code; } -SkString GrStencilWedgeShader::getTessControlShaderGLSL(const char* versionAndExtensionDecls, - const GrShaderCaps&) const { +SkString GrTessellateWedgeShader::getTessControlShaderGLSL(const GrGLSLPrimitiveProcessor*, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, + const GrShaderCaps&) const { SkString code(versionAndExtensionDecls); code.append(kWangsFormulaCubicFn); code.append(R"( @@ -183,8 +189,9 @@ SkString GrStencilWedgeShader::getTessControlShaderGLSL(const char* versionAndEx return code; } -SkString GrStencilWedgeShader::getTessEvaluationShaderGLSL(const char* versionAndExtensionDecls, - const GrShaderCaps&) const { +SkString GrTessellateWedgeShader::getTessEvaluationShaderGLSL( + const GrGLSLPrimitiveProcessor*, const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, const GrShaderCaps&) const { SkString code(versionAndExtensionDecls); code.append(kEvalCubicFn); code.append(R"( @@ -218,3 +225,109 @@ SkString GrStencilWedgeShader::getTessEvaluationShaderGLSL(const char* versionAn return code; } + +GR_DECLARE_STATIC_UNIQUE_KEY(gMiddleOutIndexBufferKey); + +sk_sp<const GrGpuBuffer> GrMiddleOutCubicShader::FindOrMakeMiddleOutIndexBuffer( + GrResourceProvider* resourceProvider) { + GR_DEFINE_STATIC_UNIQUE_KEY(gMiddleOutIndexBufferKey); + if (auto buffer = resourceProvider->findByUniqueKey<GrGpuBuffer>(gMiddleOutIndexBufferKey)) { + return std::move(buffer); + } + + // One explicit triangle at index 0, and one middle-out cubic with kMaxResolveLevel line + // segments beginning at index 3. + constexpr static int kIndexCount = 3 + NumVerticesAtResolveLevel(kMaxResolveLevel); + auto buffer = resourceProvider->createBuffer( + kIndexCount * sizeof(uint16_t), GrGpuBufferType::kIndex, kStatic_GrAccessPattern); + if (!buffer) { + return nullptr; + } + + // We shouldn't bin and/or cache static buffers. + SkASSERT(buffer->size() == kIndexCount * sizeof(uint16_t)); + SkASSERT(!buffer->resourcePriv().getScratchKey().isValid()); + auto indexData = static_cast<uint16_t*>(buffer->map()); + SkAutoTMalloc<uint16_t> stagingBuffer; + if (!indexData) { + SkASSERT(!buffer->isMapped()); + indexData = stagingBuffer.reset(kIndexCount); + } + + // Indices 0,1,2 contain special values that emit points P0, P1, and P2 respectively. (When the + // vertex shader is fed an index value larger than (1 << kMaxResolveLevel), it emits + // P[index % 4].) + int i = 0; + indexData[i++] = (1 << kMaxResolveLevel) + 4; // % 4 == 0 + indexData[i++] = (1 << kMaxResolveLevel) + 5; // % 4 == 1 + indexData[i++] = (1 << kMaxResolveLevel) + 6; // % 4 == 2 + + // Starting at index 3, we triangulate a cubic with 2^kMaxResolveLevel line segments. Each + // index value corresponds to parametric value T=(index / 2^kMaxResolveLevel). Since the + // triangles are arranged in "middle-out" order, we will be able to conveniently control the + // resolveLevel by changing only the indexCount. + for (uint16_t advance = 1 << (kMaxResolveLevel - 1); advance; advance >>= 1) { + uint16_t T = 0; + do { + indexData[i++] = T; + indexData[i++] = (T += advance); + indexData[i++] = (T += advance); + } while (T != (1 << kMaxResolveLevel)); + } + SkASSERT(i == kIndexCount); + + if (buffer->isMapped()) { + buffer->unmap(); + } else { + buffer->updateData(stagingBuffer, kIndexCount * sizeof(uint16_t)); + } + buffer->resourcePriv().setUniqueKey(gMiddleOutIndexBufferKey); + return std::move(buffer); +} + +class GrMiddleOutCubicShader::Impl : public GrStencilPathShader::Impl { + void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { + const auto& shader = args.fGP.cast<GrMiddleOutCubicShader>(); + args.fVaryingHandler->emitAttributes(shader); + args.fVertBuilder->defineConstant("kMaxResolveLevel", kMaxResolveLevel); + args.fVertBuilder->codeAppend(R"( + float4x2 P = float4x2(inputPoints_0_1, inputPoints_2_3); + float2 point; + if (sk_VertexID > (1 << kMaxResolveLevel)) { + // This is a special index value that wants us to emit a specific point. + point = P[sk_VertexID & 3]; + } else {)"); + // Evaluate the cubic at T=(sk_VertexID / 2^kMaxResolveLevel). + if (args.fShaderCaps->fpManipulationSupport()) { + args.fVertBuilder->codeAppend(R"( + float T = ldexp(sk_VertexID, -kMaxResolveLevel);)"); + } else { + args.fVertBuilder->codeAppend(R"( + float T = sk_VertexID / float(1 << kMaxResolveLevel);)"); + } + args.fVertBuilder->codeAppend(R"( + float2 ab = mix(P[0], P[1], T); + float2 bc = mix(P[1], P[2], T); + float2 cd = mix(P[2], P[3], T); + float2 abc = mix(ab, bc, T); + float2 bcd = mix(bc, cd, T); + point = mix(abc, bcd, T); + })"); + + GrShaderVar vertexPos("point", kFloat2_GrSLType); + if (!shader.viewMatrix().isIdentity()) { + const char* viewMatrix; + fViewMatrixUniform = args.fUniformHandler->addUniform( + nullptr, kVertex_GrShaderFlag, kFloat3x3_GrSLType, "view_matrix", &viewMatrix); + args.fVertBuilder->codeAppendf(R"( + float2 transformedPoint = (%s * float3(point, 1)).xy;)", viewMatrix); + vertexPos.set(kFloat2_GrSLType, "transformedPoint"); + } + gpArgs->fPositionVar = vertexPos; + // No fragment shader. + } +}; + +GrGLSLPrimitiveProcessor* GrMiddleOutCubicShader::createGLSLInstance(const GrShaderCaps&) const { + return new Impl; +} diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.h b/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.h index 0aa0b5983b4..c098f76a8d5 100644 --- a/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.h +++ b/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.h @@ -9,6 +9,7 @@ #define GrStencilPathShader_DEFINED #include "src/gpu/tessellate/GrPathShader.h" +#include "src/gpu/tessellate/GrTessellationPathRenderer.h" // This is the base class for shaders that stencil path elements, namely, triangles, standalone // cubics, and wedges. @@ -17,16 +18,15 @@ public: GrStencilPathShader(ClassID classID, const SkMatrix& viewMatrix, GrPrimitiveType primitiveType, int tessellationPatchVertexCount = 0) : GrPathShader(classID, viewMatrix, primitiveType, tessellationPatchVertexCount) { - constexpr static Attribute kPointAttrib = { - "point", kFloat2_GrVertexAttribType, kFloat2_GrSLType}; - this->setVertexAttributes(&kPointAttrib, 1); } -private: - void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const final { +protected: + constexpr static Attribute kSinglePointAttrib{"inputPoint", kFloat2_GrVertexAttribType, + kFloat2_GrSLType}; + void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override { b->add32(this->viewMatrix().isIdentity()); } - GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final; + GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override; class Impl; }; @@ -35,23 +35,30 @@ private: class GrStencilTriangleShader : public GrStencilPathShader { public: GrStencilTriangleShader(const SkMatrix& viewMatrix) : GrStencilPathShader( - kTessellate_GrStencilTriangleShader_ClassID, viewMatrix, GrPrimitiveType::kTriangles) {} + kTessellate_GrStencilTriangleShader_ClassID, viewMatrix, GrPrimitiveType::kTriangles) { + this->setVertexAttributes(&kSinglePointAttrib, 1); + } const char* name() const override { return "tessellate_GrStencilTriangleShader"; } }; -// Uses GPU tessellation shaders to linearize, triangulate, and render standalone cubics. Here, a -// "cubic" is a standalone closed contour consisting of a single cubic bezier. +// Uses GPU tessellation shaders to linearize, triangulate, and render standalone closed cubics. // TODO: Eventually we want to use rational cubic wedges in order to support perspective and conics. -class GrStencilCubicShader : public GrStencilPathShader { +class GrTessellateCubicShader : public GrStencilPathShader { public: - GrStencilCubicShader(const SkMatrix& viewMatrix) : GrStencilPathShader( - kTessellate_GrStencilCubicShader_ClassID, viewMatrix, GrPrimitiveType::kPatches, 4) {} - const char* name() const override { return "tessellate_GrStencilCubicShader"; } + GrTessellateCubicShader(const SkMatrix& viewMatrix) : GrStencilPathShader( + kTessellate_GrTessellateCubicShader_ClassID, viewMatrix, GrPrimitiveType::kPatches, 4) { + this->setVertexAttributes(&kSinglePointAttrib, 1); + } + const char* name() const override { return "tessellate_GrTessellateCubicShader"; } private: - SkString getTessControlShaderGLSL(const char* versionAndExtensionDecls, + SkString getTessControlShaderGLSL(const GrGLSLPrimitiveProcessor*, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, const GrShaderCaps&) const override; - SkString getTessEvaluationShaderGLSL(const char* versionAndExtensionDecls, + SkString getTessEvaluationShaderGLSL(const GrGLSLPrimitiveProcessor*, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, const GrShaderCaps&) const override; }; @@ -59,17 +66,88 @@ private: // wedge is a 5-point patch consisting of 4 cubic control points, plus an anchor point fanning from // the center of the curve's resident contour. // TODO: Eventually we want to use rational cubic wedges in order to support perspective and conics. -class GrStencilWedgeShader : public GrStencilPathShader { +class GrTessellateWedgeShader : public GrStencilPathShader { public: - GrStencilWedgeShader(const SkMatrix& viewMatrix) : GrStencilPathShader( - kTessellate_GrStencilWedgeShader_ClassID, viewMatrix, GrPrimitiveType::kPatches, 5) {} - const char* name() const override { return "tessellate_GrStencilWedgeShader"; } + GrTessellateWedgeShader(const SkMatrix& viewMatrix) : GrStencilPathShader( + kTessellate_GrTessellateWedgeShader_ClassID, viewMatrix, GrPrimitiveType::kPatches, 5) { + this->setVertexAttributes(&kSinglePointAttrib, 1); + } + const char* name() const override { return "tessellate_GrTessellateWedgeShader"; } private: - SkString getTessControlShaderGLSL(const char* versionAndExtensionDecls, + SkString getTessControlShaderGLSL(const GrGLSLPrimitiveProcessor*, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, const GrShaderCaps&) const override; - SkString getTessEvaluationShaderGLSL(const char* versionAndExtensionDecls, + SkString getTessEvaluationShaderGLSL(const GrGLSLPrimitiveProcessor*, + const char* versionAndExtensionDecls, + const GrGLSLUniformHandler&, const GrShaderCaps&) const override; }; +// Uses indirect (instanced) draws to triangulate standalone closed cubics with a "middle-out" +// topology. The caller must compute each cubic's resolveLevel on the CPU (i.e., the log2 number of +// line segments it will be divided into; see GrWangsFormula::cubic_log2/quadratic_log2), and then +// sort the instance buffer by resolveLevel for efficient batching of indirect draws. +class GrMiddleOutCubicShader : public GrStencilPathShader { +public: + // Each resolveLevel linearizes the curve into 2^resolveLevel line segments. The finest + // supported resolveLevel is therefore 2^12=4096 line segments. + constexpr static int kMaxResolveLevel = GrTessellationPathRenderer::kMaxResolveLevel; + + // How many vertices do we need to draw in order to triangulate a cubic with 2^resolveLevel + // line segments? + constexpr static int NumVerticesAtResolveLevel(int resolveLevel) { + // resolveLevel=0 -> 0 line segments -> 0 triangles -> 0 vertices + // resolveLevel=1 -> 2 line segments -> 1 triangle -> 3 vertices + // resolveLevel=2 -> 4 line segments -> 3 triangles -> 9 vertices + // resolveLevel=3 -> 8 line segments -> 7 triangles -> 21 vertices + // ... + return ((1 << resolveLevel) - 1) * 3; + } + + // Configures an indirect draw to render cubic instances with 2^resolveLevel evenly-spaced (in + // the parametric sense) line segments. + static GrDrawIndexedIndirectCommand MakeDrawCubicsIndirectCmd(int resolveLevel, + uint32_t instanceCount, + uint32_t baseInstance) { + SkASSERT(resolveLevel > 0 && resolveLevel <= kMaxResolveLevel); + // Starting at baseIndex=3, the index buffer triangulates a cubic with 2^kMaxResolveLevel + // line segments. Each index value corresponds to a parametric T value on the curve. Since + // the triangles are arranged in "middle-out" order, we can conveniently control the + // resolveLevel by changing only the indexCount. + uint32_t indexCount = NumVerticesAtResolveLevel(resolveLevel); + return {indexCount, instanceCount, 3, 0, baseInstance}; + } + + // For performance reasons we can often express triangles as an indirect cubic draw and sneak + // them in alongside the other indirect draws. This method configures an indirect draw to emit + // the triangle [P0, P1, P2] from a 4-point instance. + static GrDrawIndexedIndirectCommand MakeDrawTrianglesIndirectCmd(uint32_t instanceCount, + uint32_t baseInstance) { + // Indices 0,1,2 have special index values that emit points P0, P1, and P2 respectively. + return {3, instanceCount, 0, 0, baseInstance}; + } + + // Returns the index buffer that should be bound when drawing with this shader. + // (Our vertex shader uses raw index values directly, so there is no vertex buffer.) + static sk_sp<const GrGpuBuffer> FindOrMakeMiddleOutIndexBuffer(GrResourceProvider*); + + GrMiddleOutCubicShader(const SkMatrix& viewMatrix) + : GrStencilPathShader(kTessellate_GrMiddleOutCubicShader_ClassID, viewMatrix, + GrPrimitiveType::kTriangles) { + constexpr static Attribute kInputPtsAttribs[] = { + {"inputPoints_0_1", kFloat4_GrVertexAttribType, kFloat4_GrSLType}, + {"inputPoints_2_3", kFloat4_GrVertexAttribType, kFloat4_GrSLType}}; + this->setInstanceAttributes(kInputPtsAttribs, 2); + } + + const char* name() const override { return "tessellate_GrMiddleOutCubicShader"; } + +private: + GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override; + + class Impl; +}; + #endif diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrStrokeGeometry.cpp b/chromium/third_party/skia/src/gpu/tessellate/GrStrokeGeometry.cpp new file mode 100644 index 00000000000..b097c73a2d5 --- /dev/null +++ b/chromium/third_party/skia/src/gpu/tessellate/GrStrokeGeometry.cpp @@ -0,0 +1,583 @@ +/* + * 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 "src/gpu/tessellate/GrStrokeGeometry.h" + +#include "include/core/SkStrokeRec.h" +#include "include/private/SkNx.h" +#include "src/core/SkGeometry.h" +#include "src/core/SkMathPriv.h" + +// This is the maximum distance in pixels that we can stray from the edge of a stroke when +// converting it to flat line segments. +static constexpr float kMaxErrorFromLinearization = 1/8.f; + +static inline float length(const Sk2f& n) { + Sk2f nn = n*n; + return SkScalarSqrt(nn[0] + nn[1]); +} + +static inline Sk2f normalize(const Sk2f& v) { + Sk2f vv = v*v; + vv += SkNx_shuffle<1,0>(vv); + return v * vv.rsqrt(); +} + +static inline void transpose(const Sk2f& a, const Sk2f& b, Sk2f* X, Sk2f* Y) { + float transpose[4]; + a.store(transpose); + b.store(transpose+2); + Sk2f::Load2(transpose, X, Y); +} + +static inline void normalize2(const Sk2f& v0, const Sk2f& v1, SkPoint out[2]) { + Sk2f X, Y; + transpose(v0, v1, &X, &Y); + Sk2f invlength = (X*X + Y*Y).rsqrt(); + Sk2f::Store2(out, Y * invlength, -X * invlength); +} + +static inline float calc_curvature_costheta(const Sk2f& leftTan, const Sk2f& rightTan) { + Sk2f X, Y; + transpose(leftTan, rightTan, &X, &Y); + Sk2f invlength = (X*X + Y*Y).rsqrt(); + Sk2f dotprod = leftTan * rightTan; + return (dotprod[0] + dotprod[1]) * invlength[0] * invlength[1]; +} + +static GrStrokeGeometry::Verb join_verb_from_join(SkPaint::Join join) { + using Verb = GrStrokeGeometry::Verb; + switch (join) { + case SkPaint::kBevel_Join: + return Verb::kBevelJoin; + case SkPaint::kMiter_Join: + return Verb::kMiterJoin; + case SkPaint::kRound_Join: + return Verb::kRoundJoin; + } + SK_ABORT("Invalid SkPaint::Join."); +} + +void GrStrokeGeometry::beginPath(const SkStrokeRec& stroke, float strokeDevWidth, + InstanceTallies* tallies) { + SkASSERT(!fInsideContour); + // Client should have already converted the stroke to device space (i.e. width=1 for hairline). + SkASSERT(strokeDevWidth > 0); + + fCurrStrokeRadius = strokeDevWidth/2; + fCurrStrokeJoinVerb = join_verb_from_join(stroke.getJoin()); + fCurrStrokeCapType = stroke.getCap(); + fCurrStrokeTallies = tallies; + + if (Verb::kMiterJoin == fCurrStrokeJoinVerb) { + // We implement miters by placing a triangle-shaped cap on top of a bevel join. Convert the + // "miter limit" to how tall that triangle cap can be. + float m = stroke.getMiter(); + fMiterMaxCapHeightOverWidth = .5f * SkScalarSqrt(m*m - 1); + } + + // Find the angle of curvature where the arc height above a simple line from point A to point B + // is equal to kMaxErrorFromLinearization. + float r = std::max(1 - kMaxErrorFromLinearization / fCurrStrokeRadius, 0.f); + fMaxCurvatureCosTheta = 2*r*r - 1; + + fCurrContourFirstPtIdx = -1; + fCurrContourFirstNormalIdx = -1; + + fVerbs.push_back(Verb::kBeginPath); +} + +void GrStrokeGeometry::moveTo(SkPoint pt) { + SkASSERT(!fInsideContour); + fCurrContourFirstPtIdx = fPoints.count(); + fCurrContourFirstNormalIdx = fNormals.count(); + fPoints.push_back(pt); + SkDEBUGCODE(fInsideContour = true); +} + +void GrStrokeGeometry::lineTo(SkPoint pt) { + SkASSERT(fInsideContour); + this->lineTo(fCurrStrokeJoinVerb, pt); +} + +void GrStrokeGeometry::lineTo(Verb leftJoinVerb, SkPoint pt) { + Sk2f tan = Sk2f::Load(&pt) - Sk2f::Load(&fPoints.back()); + if ((tan == 0).allTrue()) { + return; + } + + tan = normalize(tan); + SkVector n = SkVector::Make(tan[1], -tan[0]); + + this->recordLeftJoinIfNotEmpty(leftJoinVerb, n); + fNormals.push_back(n); + + this->recordStroke(Verb::kLinearStroke, 0); + fPoints.push_back(pt); +} + +void GrStrokeGeometry::quadraticTo(const SkPoint P[3]) { + SkASSERT(fInsideContour); + this->quadraticTo(fCurrStrokeJoinVerb, P, SkFindQuadMaxCurvature(P)); +} + +// Wang's formula for quadratics (1985) gives us the number of evenly spaced (in the parametric +// sense) line segments that are guaranteed to be within a distance of "kMaxErrorFromLinearization" +// from the actual curve. +static inline float wangs_formula_quadratic(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2) { + static constexpr float k = 2 / (8 * kMaxErrorFromLinearization); + float f = SkScalarSqrt(k * length(p2 - p1*2 + p0)); + return SkScalarCeilToInt(f); +} + +void GrStrokeGeometry::quadraticTo(Verb leftJoinVerb, const SkPoint P[3], float maxCurvatureT) { + Sk2f p0 = Sk2f::Load(P); + Sk2f p1 = Sk2f::Load(P+1); + Sk2f p2 = Sk2f::Load(P+2); + + Sk2f tan0 = p1 - p0; + Sk2f tan1 = p2 - p1; + + // Snap to a "lineTo" if the control point is so close to an endpoint that FP error will become + // an issue. + if ((tan0.abs() < SK_ScalarNearlyZero).allTrue() || // p0 ~= p1 + (tan1.abs() < SK_ScalarNearlyZero).allTrue()) { // p1 ~= p2 + this->lineTo(leftJoinVerb, P[2]); + return; + } + + SkPoint normals[2]; + normalize2(tan0, tan1, normals); + + // Decide how many flat line segments to chop the curve into. + int numSegments = wangs_formula_quadratic(p0, p1, p2); + numSegments = std::min(numSegments, 1 << kMaxNumLinearSegmentsLog2); + if (numSegments <= 1) { + this->rotateTo(leftJoinVerb, normals[0]); + this->lineTo(Verb::kInternalRoundJoin, P[2]); + this->rotateTo(Verb::kInternalRoundJoin, normals[1]); + return; + } + + // At + B gives a vector tangent to the quadratic. + Sk2f A = p0 - p1*2 + p2; + Sk2f B = p1 - p0; + + // Find a line segment that crosses max curvature. + float segmentLength = SkScalarInvert(numSegments); + float leftT = maxCurvatureT - segmentLength/2; + float rightT = maxCurvatureT + segmentLength/2; + Sk2f leftTan, rightTan; + if (leftT <= 0) { + leftT = 0; + leftTan = tan0; + rightT = segmentLength; + rightTan = A*rightT + B; + } else if (rightT >= 1) { + leftT = 1 - segmentLength; + leftTan = A*leftT + B; + rightT = 1; + rightTan = tan1; + } else { + leftTan = A*leftT + B; + rightTan = A*rightT + B; + } + + // Check if curvature is too strong for a triangle strip on the line segment that crosses max + // curvature. If it is, we will chop and convert the segment to a "lineTo" with round joins. + // + // FIXME: This is quite costly and the vast majority of curves only have moderate curvature. We + // would benefit significantly from a quick reject that detects curves that don't need special + // treatment for strong curvature. + bool isCurvatureTooStrong = calc_curvature_costheta(leftTan, rightTan) < fMaxCurvatureCosTheta; + if (isCurvatureTooStrong) { + SkPoint ptsBuffer[5]; + const SkPoint* currQuadratic = P; + + if (leftT > 0) { + SkChopQuadAt(currQuadratic, ptsBuffer, leftT); + this->quadraticTo(leftJoinVerb, ptsBuffer, /*maxCurvatureT=*/1); + if (rightT < 1) { + rightT = (rightT - leftT) / (1 - leftT); + } + currQuadratic = ptsBuffer + 2; + } else { + this->rotateTo(leftJoinVerb, normals[0]); + } + + if (rightT < 1) { + SkChopQuadAt(currQuadratic, ptsBuffer, rightT); + this->lineTo(Verb::kInternalRoundJoin, ptsBuffer[2]); + this->quadraticTo(Verb::kInternalRoundJoin, ptsBuffer + 2, /*maxCurvatureT=*/0); + } else { + this->lineTo(Verb::kInternalRoundJoin, currQuadratic[2]); + this->rotateTo(Verb::kInternalRoundJoin, normals[1]); + } + return; + } + + this->recordLeftJoinIfNotEmpty(leftJoinVerb, normals[0]); + fNormals.push_back_n(2, normals); + + this->recordStroke(Verb::kQuadraticStroke, SkNextLog2(numSegments)); + p1.store(&fPoints.push_back()); + p2.store(&fPoints.push_back()); +} + +void GrStrokeGeometry::cubicTo(const SkPoint P[4]) { + SkASSERT(fInsideContour); + float roots[3]; + int numRoots = SkFindCubicMaxCurvature(P, roots); + this->cubicTo(fCurrStrokeJoinVerb, P, + numRoots > 0 ? roots[numRoots/2] : 0, + numRoots > 1 ? roots[0] : kLeftMaxCurvatureNone, + numRoots > 2 ? roots[2] : kRightMaxCurvatureNone); +} + +// Wang's formula for cubics (1985) gives us the number of evenly spaced (in the parametric sense) +// line segments that are guaranteed to be within a distance of "kMaxErrorFromLinearization" +// from the actual curve. +static inline float wangs_formula_cubic(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2, + const Sk2f& p3) { + static constexpr float k = (3 * 2) / (8 * kMaxErrorFromLinearization); + float f = SkScalarSqrt(k * length(Sk2f::Max((p2 - p1*2 + p0).abs(), + (p3 - p2*2 + p1).abs()))); + return SkScalarCeilToInt(f); +} + +void GrStrokeGeometry::cubicTo(Verb leftJoinVerb, const SkPoint P[4], float maxCurvatureT, + float leftMaxCurvatureT, float rightMaxCurvatureT) { + Sk2f p0 = Sk2f::Load(P); + Sk2f p1 = Sk2f::Load(P+1); + Sk2f p2 = Sk2f::Load(P+2); + Sk2f p3 = Sk2f::Load(P+3); + + Sk2f tan0 = p1 - p0; + Sk2f tan1 = p3 - p2; + + // Snap control points to endpoints if they are so close that FP error will become an issue. + if ((tan0.abs() < SK_ScalarNearlyZero).allTrue()) { // p0 ~= p1 + p1 = p0; + tan0 = p2 - p0; + if ((tan0.abs() < SK_ScalarNearlyZero).allTrue()) { // p0 ~= p1 ~= p2 + this->lineTo(leftJoinVerb, P[3]); + return; + } + } + if ((tan1.abs() < SK_ScalarNearlyZero).allTrue()) { // p2 ~= p3 + p2 = p3; + tan1 = p3 - p1; + if ((tan1.abs() < SK_ScalarNearlyZero).allTrue() || // p1 ~= p2 ~= p3 + (p0 == p1).allTrue()) { // p0 ~= p1 AND p2 ~= p3 + this->lineTo(leftJoinVerb, P[3]); + return; + } + } + + SkPoint normals[2]; + normalize2(tan0, tan1, normals); + + // Decide how many flat line segments to chop the curve into. + int numSegments = wangs_formula_cubic(p0, p1, p2, p3); + numSegments = std::min(numSegments, 1 << kMaxNumLinearSegmentsLog2); + if (numSegments <= 1) { + this->rotateTo(leftJoinVerb, normals[0]); + this->lineTo(leftJoinVerb, P[3]); + this->rotateTo(Verb::kInternalRoundJoin, normals[1]); + return; + } + + // At^2 + Bt + C gives a vector tangent to the cubic. (More specifically, it's the derivative + // minus an irrelevant scale by 3, since all we care about is the direction.) + Sk2f A = p3 + (p1 - p2)*3 - p0; + Sk2f B = (p0 - p1*2 + p2)*2; + Sk2f C = p1 - p0; + + // Find a line segment that crosses max curvature. + float segmentLength = SkScalarInvert(numSegments); + float leftT = maxCurvatureT - segmentLength/2; + float rightT = maxCurvatureT + segmentLength/2; + Sk2f leftTan, rightTan; + if (leftT <= 0) { + leftT = 0; + leftTan = tan0; + rightT = segmentLength; + rightTan = A*rightT*rightT + B*rightT + C; + } else if (rightT >= 1) { + leftT = 1 - segmentLength; + leftTan = A*leftT*leftT + B*leftT + C; + rightT = 1; + rightTan = tan1; + } else { + leftTan = A*leftT*leftT + B*leftT + C; + rightTan = A*rightT*rightT + B*rightT + C; + } + + // Check if curvature is too strong for a triangle strip on the line segment that crosses max + // curvature. If it is, we will chop and convert the segment to a "lineTo" with round joins. + // + // FIXME: This is quite costly and the vast majority of curves only have moderate curvature. We + // would benefit significantly from a quick reject that detects curves that don't need special + // treatment for strong curvature. + bool isCurvatureTooStrong = calc_curvature_costheta(leftTan, rightTan) < fMaxCurvatureCosTheta; + if (isCurvatureTooStrong) { + SkPoint ptsBuffer[7]; + p0.store(ptsBuffer); + p1.store(ptsBuffer + 1); + p2.store(ptsBuffer + 2); + p3.store(ptsBuffer + 3); + const SkPoint* currCubic = ptsBuffer; + + if (leftT > 0) { + SkChopCubicAt(currCubic, ptsBuffer, leftT); + this->cubicTo(leftJoinVerb, ptsBuffer, /*maxCurvatureT=*/1, + (kLeftMaxCurvatureNone != leftMaxCurvatureT) + ? leftMaxCurvatureT/leftT : kLeftMaxCurvatureNone, + kRightMaxCurvatureNone); + if (rightT < 1) { + rightT = (rightT - leftT) / (1 - leftT); + } + if (rightMaxCurvatureT < 1 && kRightMaxCurvatureNone != rightMaxCurvatureT) { + rightMaxCurvatureT = (rightMaxCurvatureT - leftT) / (1 - leftT); + } + currCubic = ptsBuffer + 3; + } else { + this->rotateTo(leftJoinVerb, normals[0]); + } + + if (rightT < 1) { + SkChopCubicAt(currCubic, ptsBuffer, rightT); + this->lineTo(Verb::kInternalRoundJoin, ptsBuffer[3]); + currCubic = ptsBuffer + 3; + this->cubicTo(Verb::kInternalRoundJoin, currCubic, /*maxCurvatureT=*/0, + kLeftMaxCurvatureNone, kRightMaxCurvatureNone); + } else { + this->lineTo(Verb::kInternalRoundJoin, currCubic[3]); + this->rotateTo(Verb::kInternalRoundJoin, normals[1]); + } + return; + } + + // Recurse and check the other two points of max curvature, if any. + if (kRightMaxCurvatureNone != rightMaxCurvatureT) { + this->cubicTo(leftJoinVerb, P, rightMaxCurvatureT, leftMaxCurvatureT, + kRightMaxCurvatureNone); + return; + } + if (kLeftMaxCurvatureNone != leftMaxCurvatureT) { + SkASSERT(kRightMaxCurvatureNone == rightMaxCurvatureT); + this->cubicTo(leftJoinVerb, P, leftMaxCurvatureT, kLeftMaxCurvatureNone, + kRightMaxCurvatureNone); + return; + } + + this->recordLeftJoinIfNotEmpty(leftJoinVerb, normals[0]); + fNormals.push_back_n(2, normals); + + this->recordStroke(Verb::kCubicStroke, SkNextLog2(numSegments)); + p1.store(&fPoints.push_back()); + p2.store(&fPoints.push_back()); + p3.store(&fPoints.push_back()); +} + +void GrStrokeGeometry::recordStroke(Verb verb, int numSegmentsLog2) { + SkASSERT(Verb::kLinearStroke != verb || 0 == numSegmentsLog2); + SkASSERT(numSegmentsLog2 <= kMaxNumLinearSegmentsLog2); + fVerbs.push_back(verb); + if (Verb::kLinearStroke != verb) { + SkASSERT(numSegmentsLog2 > 0); + fParams.push_back().fNumLinearSegmentsLog2 = numSegmentsLog2; + } + ++fCurrStrokeTallies->fStrokes[numSegmentsLog2]; +} + +void GrStrokeGeometry::rotateTo(Verb leftJoinVerb, SkVector normal) { + this->recordLeftJoinIfNotEmpty(leftJoinVerb, normal); + fNormals.push_back(normal); +} + +void GrStrokeGeometry::recordLeftJoinIfNotEmpty(Verb joinVerb, SkVector nextNormal) { + if (fNormals.count() <= fCurrContourFirstNormalIdx) { + // The contour is empty. Nothing to join with. + SkASSERT(fNormals.count() == fCurrContourFirstNormalIdx); + return; + } + + if (Verb::kBevelJoin == joinVerb) { + this->recordBevelJoin(Verb::kBevelJoin); + return; + } + + Sk2f n0 = Sk2f::Load(&fNormals.back()); + Sk2f n1 = Sk2f::Load(&nextNormal); + Sk2f base = n1 - n0; + if ((base.abs() * fCurrStrokeRadius < kMaxErrorFromLinearization).allTrue()) { + // Treat any join as a bevel when the outside corners of the two adjoining strokes are + // close enough to each other. This is important because "miterCapHeightOverWidth" becomes + // unstable when n0 and n1 are nearly equal. + this->recordBevelJoin(joinVerb); + return; + } + + // We implement miters and round joins by placing a triangle-shaped cap on top of a bevel join. + // (For round joins this triangle cap comprises the conic control points.) Find how tall to make + // this triangle cap, relative to its width. + // + // NOTE: This value would be infinite at 180 degrees, but we clamp miterCapHeightOverWidth at + // near-infinity. 180-degree round joins still look perfectly acceptable like this (though + // technically not pure arcs). + Sk2f cross = base * SkNx_shuffle<1,0>(n0); + Sk2f dot = base * n0; + float miterCapHeight = SkScalarAbs(dot[0] + dot[1]); + float miterCapWidth = SkScalarAbs(cross[0] - cross[1]) * 2; + + if (Verb::kMiterJoin == joinVerb) { + if (miterCapHeight > fMiterMaxCapHeightOverWidth * miterCapWidth) { + // This join is tighter than the miter limit. Treat it as a bevel. + this->recordBevelJoin(Verb::kMiterJoin); + return; + } + this->recordMiterJoin(miterCapHeight / miterCapWidth); + return; + } + + SkASSERT(Verb::kRoundJoin == joinVerb || Verb::kInternalRoundJoin == joinVerb); + + // Conic arcs become unstable when they approach 180 degrees. When the conic control point + // begins shooting off to infinity (i.e., height/width > 32), split the conic into two. + static constexpr float kAlmost180Degrees = 32; + if (miterCapHeight > kAlmost180Degrees * miterCapWidth) { + Sk2f bisect = normalize(n0 - n1); + this->rotateTo(joinVerb, SkVector::Make(-bisect[1], bisect[0])); + this->recordLeftJoinIfNotEmpty(joinVerb, nextNormal); + return; + } + + float miterCapHeightOverWidth = miterCapHeight / miterCapWidth; + + // Find the heights of this round join's conic control point as well as the arc itself. + Sk2f X, Y; + transpose(base * base, n0 * n1, &X, &Y); + Sk2f r = Sk2f::Max(X + Y + Sk2f(0, 1), 0.f).sqrt(); + Sk2f heights = SkNx_fma(r, Sk2f(miterCapHeightOverWidth, -SK_ScalarRoot2Over2), Sk2f(0, 1)); + float controlPointHeight = SkScalarAbs(heights[0]); + float curveHeight = heights[1]; + if (curveHeight * fCurrStrokeRadius < kMaxErrorFromLinearization) { + // Treat round joins as bevels when their curvature is nearly flat. + this->recordBevelJoin(joinVerb); + return; + } + + float w = curveHeight / (controlPointHeight - curveHeight); + this->recordRoundJoin(joinVerb, miterCapHeightOverWidth, w); +} + +void GrStrokeGeometry::recordBevelJoin(Verb originalJoinVerb) { + if (!IsInternalJoinVerb(originalJoinVerb)) { + fVerbs.push_back(Verb::kBevelJoin); + ++fCurrStrokeTallies->fTriangles; + } else { + fVerbs.push_back(Verb::kInternalBevelJoin); + fCurrStrokeTallies->fTriangles += 2; + } +} + +void GrStrokeGeometry::recordMiterJoin(float miterCapHeightOverWidth) { + fVerbs.push_back(Verb::kMiterJoin); + fParams.push_back().fMiterCapHeightOverWidth = miterCapHeightOverWidth; + fCurrStrokeTallies->fTriangles += 2; +} + +void GrStrokeGeometry::recordRoundJoin(Verb joinVerb, float miterCapHeightOverWidth, + float conicWeight) { + fVerbs.push_back(joinVerb); + fParams.push_back().fConicWeight = conicWeight; + fParams.push_back().fMiterCapHeightOverWidth = miterCapHeightOverWidth; + if (Verb::kRoundJoin == joinVerb) { + ++fCurrStrokeTallies->fTriangles; + ++fCurrStrokeTallies->fConics; + } else { + SkASSERT(Verb::kInternalRoundJoin == joinVerb); + fCurrStrokeTallies->fTriangles += 2; + fCurrStrokeTallies->fConics += 2; + } +} + +void GrStrokeGeometry::closeContour() { + SkASSERT(fInsideContour); + SkASSERT(fPoints.count() > fCurrContourFirstPtIdx); + if (fPoints.back() != fPoints[fCurrContourFirstPtIdx]) { + // Draw a line back to the beginning. + this->lineTo(fCurrStrokeJoinVerb, fPoints[fCurrContourFirstPtIdx]); + } + if (fNormals.count() > fCurrContourFirstNormalIdx) { + // Join the first and last lines. + this->rotateTo(fCurrStrokeJoinVerb,fNormals[fCurrContourFirstNormalIdx]); + } else { + // This contour is empty. Add a bogus normal since the iterator always expects one. + SkASSERT(fNormals.count() == fCurrContourFirstNormalIdx); + fNormals.push_back({0, 0}); + } + fVerbs.push_back(Verb::kEndContour); + SkDEBUGCODE(fInsideContour = false); +} + +void GrStrokeGeometry::capContourAndExit() { + SkASSERT(fInsideContour); + if (fCurrContourFirstNormalIdx >= fNormals.count()) { + // This contour is empty. Add a normal in the direction that caps orient on empty geometry. + SkASSERT(fNormals.count() == fCurrContourFirstNormalIdx); + fNormals.push_back({1, 0}); + } + + this->recordCapsIfAny(); + fVerbs.push_back(Verb::kEndContour); + + SkDEBUGCODE(fInsideContour = false); +} + +void GrStrokeGeometry::recordCapsIfAny() { + SkASSERT(fInsideContour); + SkASSERT(fCurrContourFirstNormalIdx < fNormals.count()); + + if (SkPaint::kButt_Cap == fCurrStrokeCapType) { + return; + } + + Verb capVerb; + if (SkPaint::kSquare_Cap == fCurrStrokeCapType) { + if (fCurrStrokeRadius * SK_ScalarRoot2Over2 < kMaxErrorFromLinearization) { + return; + } + capVerb = Verb::kSquareCap; + fCurrStrokeTallies->fStrokes[0] += 2; + } else { + SkASSERT(SkPaint::kRound_Cap == fCurrStrokeCapType); + if (fCurrStrokeRadius < kMaxErrorFromLinearization) { + return; + } + capVerb = Verb::kRoundCap; + fCurrStrokeTallies->fTriangles += 2; + fCurrStrokeTallies->fConics += 4; + } + + fVerbs.push_back(capVerb); + fVerbs.push_back(Verb::kEndContour); + + fVerbs.push_back(capVerb); + + // Reserve the space first, since push_back() takes the point by reference and might + // invalidate the reference if the array grows. + fPoints.reserve(fPoints.count() + 1); + fPoints.push_back(fPoints[fCurrContourFirstPtIdx]); + + // Reserve the space first, since push_back() takes the normal by reference and might + // invalidate the reference if the array grows. (Although in this case we should be fine + // since there is a negate operator.) + fNormals.reserve(fNormals.count() + 1); + fNormals.push_back(-fNormals[fCurrContourFirstNormalIdx]); +} diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrStrokeGeometry.h b/chromium/third_party/skia/src/gpu/tessellate/GrStrokeGeometry.h new file mode 100644 index 00000000000..98a85fffac9 --- /dev/null +++ b/chromium/third_party/skia/src/gpu/tessellate/GrStrokeGeometry.h @@ -0,0 +1,177 @@ +/* + * 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 GrGrStrokeGeometry_DEFINED +#define GrGrStrokeGeometry_DEFINED + +#include "include/core/SkPaint.h" +#include "include/core/SkPoint.h" +#include "include/private/SkTArray.h" + +class SkStrokeRec; + +/** + * This class converts post-transform stroked paths into a set of independent strokes, joins, and + * caps that map directly to GPU instances. + */ +class GrStrokeGeometry { +public: + static constexpr int kMaxNumLinearSegmentsLog2 = 15; + + GrStrokeGeometry(int numSkPoints = 0, int numSkVerbs = 0) + : fVerbs(numSkVerbs * 5/2) // Reserve for a 2.5x expansion in verbs. (Joins get their + // own separate verb in our representation.) + , fParams(numSkVerbs * 3) // Somewhere around 1-2 params per verb. + , fPoints(numSkPoints * 5/4) // Reserve for a 1.25x expansion in points and normals. + , fNormals(numSkPoints * 5/4) {} + + // A string of verbs and their corresponding, params, points, and normals are a compact + // representation of what will eventually be independent instances in GPU buffers. + enum class Verb : uint8_t { + kBeginPath, // Instructs the iterator to advance its stroke width, atlas offset, etc. + + // Independent strokes of a single line or curve, with (antialiased) butt caps on the ends. + kLinearStroke, + kQuadraticStroke, + kCubicStroke, + + // Joins are a triangles that connect the outer corners of two adjoining strokes. Miters + // have an additional triangle cap on top of the bevel, and round joins have an arc on top. + kBevelJoin, + kMiterJoin, + kRoundJoin, + + // We use internal joins when we have to internally break up a stroke because its curvature + // is too strong for a triangle strip. They are coverage-counted, self-intersecting + // quadrilaterals that tie the four corners of two adjoining strokes together a like a + // shoelace. (Coverage is negative on the inside half.) We place an arc on both ends of an + // internal round join. + kInternalBevelJoin, + kInternalRoundJoin, + + kSquareCap, + kRoundCap, + + kEndContour // Instructs the iterator to advance its internal point and normal ptrs. + }; + static bool IsInternalJoinVerb(Verb verb); + + // Some verbs require additional parameters(s). + union Parameter { + // For cubic and quadratic strokes: How many flat line segments to chop the curve into? + int fNumLinearSegmentsLog2; + // For miter and round joins: How tall should the triangle cap be on top of the join? + // (This triangle is the conic control points for a round join.) + float fMiterCapHeightOverWidth; + float fConicWeight; // Round joins only. + }; + + const SkTArray<Verb, true>& verbs() const { SkASSERT(!fInsideContour); return fVerbs; } + const SkTArray<Parameter, true>& params() const { SkASSERT(!fInsideContour); return fParams; } + const SkTArray<SkPoint, true>& points() const { SkASSERT(!fInsideContour); return fPoints; } + const SkTArray<SkVector, true>& normals() const { SkASSERT(!fInsideContour); return fNormals; } + + // These track the numbers of instances required to draw all the recorded strokes. + struct InstanceTallies { + int fStrokes[kMaxNumLinearSegmentsLog2 + 1]; + int fTriangles; + int fConics; + + InstanceTallies operator+(const InstanceTallies&) const; + }; + + void beginPath(const SkStrokeRec&, float strokeDevWidth, InstanceTallies*); + void moveTo(SkPoint); + void lineTo(SkPoint); + void quadraticTo(const SkPoint[3]); + void cubicTo(const SkPoint[4]); + void closeContour(); // Connect back to the first point in the contour and exit. + void capContourAndExit(); // Add endcaps (if any) and exit the contour. + +private: + void lineTo(Verb leftJoinVerb, SkPoint); + void quadraticTo(Verb leftJoinVerb, const SkPoint[3], float maxCurvatureT); + + static constexpr float kLeftMaxCurvatureNone = 1; + static constexpr float kRightMaxCurvatureNone = 0; + void cubicTo(Verb leftJoinVerb, const SkPoint[4], float maxCurvatureT, float leftMaxCurvatureT, + float rightMaxCurvatureT); + + // Pushes a new normal to fNormals and records a join, without changing the current position. + void rotateTo(Verb leftJoinVerb, SkVector normal); + + // Records a stroke in fElememts. + void recordStroke(Verb, int numSegmentsLog2); + + // Records a join in fElememts with the previous stroke, if the cuurent contour is not empty. + void recordLeftJoinIfNotEmpty(Verb joinType, SkVector nextNormal); + void recordBevelJoin(Verb originalJoinVerb); + void recordMiterJoin(float miterCapHeightOverWidth); + void recordRoundJoin(Verb roundJoinVerb, float miterCapHeightOverWidth, float conicWeight); + + void recordCapsIfAny(); + + float fCurrStrokeRadius; + Verb fCurrStrokeJoinVerb; + SkPaint::Cap fCurrStrokeCapType; + InstanceTallies* fCurrStrokeTallies = nullptr; + + // We implement miters by placing a triangle-shaped cap on top of a bevel join. This field tells + // us what the miter limit is, restated in terms of how tall that triangle cap can be. + float fMiterMaxCapHeightOverWidth; + + // Any curvature on the original curve gets magnified on the outer edge of the stroke, + // proportional to how thick the stroke radius is. This field tells us the maximum curvature we + // can tolerate using the current stroke radius, before linearization artifacts begin to appear + // on the outer edge. + // + // (Curvature this strong is quite rare in practice, but when it does happen, we decompose the + // section with strong curvature into lineTo's with round joins in between.) + float fMaxCurvatureCosTheta; + + int fCurrContourFirstPtIdx; + int fCurrContourFirstNormalIdx; + + SkDEBUGCODE(bool fInsideContour = false); + + SkSTArray<128, Verb, true> fVerbs; + SkSTArray<128, Parameter, true> fParams; + SkSTArray<128, SkPoint, true> fPoints; + SkSTArray<128, SkVector, true> fNormals; +}; + +inline GrStrokeGeometry::InstanceTallies GrStrokeGeometry::InstanceTallies::operator+( + const InstanceTallies& t) const { + InstanceTallies ret; + for (int i = 0; i <= kMaxNumLinearSegmentsLog2; ++i) { + ret.fStrokes[i] = fStrokes[i] + t.fStrokes[i]; + } + ret.fTriangles = fTriangles + t.fTriangles; + ret.fConics = fConics + t.fConics; + return ret; +} + +inline bool GrStrokeGeometry::IsInternalJoinVerb(Verb verb) { + switch (verb) { + case Verb::kInternalBevelJoin: + case Verb::kInternalRoundJoin: + return true; + case Verb::kBeginPath: + case Verb::kLinearStroke: + case Verb::kQuadraticStroke: + case Verb::kCubicStroke: + case Verb::kBevelJoin: + case Verb::kMiterJoin: + case Verb::kRoundJoin: + case Verb::kSquareCap: + case Verb::kRoundCap: + case Verb::kEndContour: + return false; + } + SK_ABORT("Invalid GrStrokeGeometry::Verb."); +} +#endif diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.cpp b/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.cpp index 7e0950ac460..4d028b357c4 100644 --- a/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.cpp +++ b/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.cpp @@ -14,7 +14,16 @@ #include "src/gpu/tessellate/GrFillPathShader.h" #include "src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h" #include "src/gpu/tessellate/GrMidpointContourParser.h" +#include "src/gpu/tessellate/GrResolveLevelCounter.h" #include "src/gpu/tessellate/GrStencilPathShader.h" +#include "src/gpu/tessellate/GrTessellationPathRenderer.h" + +constexpr static float kLinearizationIntolerance = + GrTessellationPathRenderer::kLinearizationIntolerance; + +constexpr static int kMaxResolveLevel = GrTessellationPathRenderer::kMaxResolveLevel; + +using OpFlags = GrTessellationPathRenderer::OpFlags; GrTessellatePathOp::FixedFunctionFlags GrTessellatePathOp::fixedFunctionFlags() const { auto flags = FixedFunctionFlags::kUsesStencil; @@ -30,50 +39,68 @@ void GrTessellatePathOp::onPrePrepare(GrRecordingContext*, const GrXferProcessor::DstProxyView&) { } -void GrTessellatePathOp::onPrepare(GrOpFlushState* state) { +void GrTessellatePathOp::onPrepare(GrOpFlushState* flushState) { + int numVerbs = fPath.countVerbs(); + if (numVerbs <= 0) { + return; + } + // First check if the path is large and/or simple enough that we can actually triangulate the // inner polygon(s) on the CPU. This is our fastest approach. It allows us to stencil only the - // curves, and then fill the internal polygons directly to the final render target, thus filling - // in the majority of pixels in a single render pass. + // curves, and then fill the internal polygons directly to the final render target, thus drawing + // the majority of pixels in a single render pass. SkScalar scales[2]; SkAssertResult(fViewMatrix.getMinMaxScales(scales)); // Will fail if perspective. const SkRect& bounds = fPath.getBounds(); - int numVerbs = fPath.countVerbs(); - if (numVerbs <= 0) { - return; - } float gpuFragmentWork = bounds.height() * scales[0] * bounds.width() * scales[1]; float cpuTessellationWork = (float)numVerbs * SkNextLog2(numVerbs); // N log N. if (cpuTessellationWork * 500 + (256 * 256) < gpuFragmentWork) { // Don't try below 256x256. - int numCountedCurves; + int numCountedCubics; // This will fail if the inner triangles do not form a simple polygon (e.g., self // intersection, double winding). - if (this->prepareNonOverlappingInnerTriangles(state, &numCountedCurves)) { - // Prepare cubics on an instance boundary so we can use the buffer to fill local convex - // hulls as well. - this->prepareOuterCubics(state, numCountedCurves, - CubicDataAlignment::kInstanceBoundary); + if (this->prepareNonOverlappingInnerTriangles(flushState, &numCountedCubics)) { + if (!numCountedCubics) { + return; + } + // Always use indirect draws for cubics instead of tessellation here. Our goal in this + // mode is to maximize GPU performance, and the middle-out topology used by our indirect + // draws is easier on the rasterizer than a tessellated fan. There also seems to be a + // small amount of fixed tessellation overhead that this avoids. + GrResolveLevelCounter resolveLevelCounter; + resolveLevelCounter.reset(fPath, fViewMatrix, kLinearizationIntolerance); + this->prepareIndirectOuterCubics(flushState, resolveLevelCounter); return; } } - // Next see if we can split up inner polygon triangles and curves, and triangulate the inner - // polygon(s) more efficiently. This causes greater CPU overhead due to the extra shaders and - // draw calls, but the better triangulation can reduce the rasterizer load by a great deal on - // complex paths. + // When there are only a few verbs, it seems to always be fastest to make a single indirect draw + // that contains both the inner triangles and the outer cubics, instead of using hardware + // tessellation. Also take this path if tessellation is not supported. + bool drawTrianglesAsIndirectCubicDraw = (numVerbs < 50); + if (drawTrianglesAsIndirectCubicDraw || (fOpFlags & OpFlags::kDisableHWTessellation)) { + // Prepare outer cubics with indirect draws. + GrResolveLevelCounter resolveLevelCounter; + this->prepareMiddleOutTrianglesAndCubics(flushState, &resolveLevelCounter, + drawTrianglesAsIndirectCubicDraw); + return; + } + + // The caller should have sent Flags::kDisableHWTessellation if it was not supported. + SkASSERT(flushState->caps().shaderCaps()->tessellationSupport()); + + // Next see if we can split up the inner triangles and outer cubics into two draw calls. This + // allows for a more efficient inner triangle topology that can reduce the rasterizer load by a + // large margin on complex paths, but also causes greater CPU overhead due to the extra shader + // switches and draw calls. // NOTE: Raster-edge work is 1-dimensional, so we sum height and width instead of multiplying. float rasterEdgeWork = (bounds.height() + bounds.width()) * scales[1] * fPath.countVerbs(); - if (rasterEdgeWork > 1000 * 1000) { - int numCountedCurves; - this->prepareMiddleOutInnerTriangles(state, &numCountedCurves); - // We will fill the path with a bounding box instead local cubic convex hulls, so there is - // no need to prepare the cubics on an instance boundary. - this->prepareOuterCubics(state, numCountedCurves, CubicDataAlignment::kVertexBoundary); + if (rasterEdgeWork > 300 * 300) { + this->prepareMiddleOutTrianglesAndCubics(flushState); return; } // Fastest CPU approach: emit one cubic wedge per verb, fanning out from the center. - this->prepareCubicWedges(state); + this->prepareTessellatedCubicWedges(flushState); } bool GrTessellatePathOp::prepareNonOverlappingInnerTriangles(GrMeshDrawOp::Target* target, @@ -93,52 +120,88 @@ bool GrTessellatePathOp::prepareNonOverlappingInnerTriangles(GrMeshDrawOp::Targe // simple. return false; } - if (((Flags::kStencilOnly | Flags::kWireframe) & fFlags) || GrAAType::kCoverage == fAAType || + if (((OpFlags::kStencilOnly | OpFlags::kWireframe) & fOpFlags) || + GrAAType::kCoverage == fAAType || (target->appliedClip() && target->appliedClip()->hasStencilClip())) { // If we have certain flags, mixed samples, or a stencil clip then we unfortunately // can't fill the inner polygon directly. Indicate that these triangles need to be // stencilled. fDoStencilTriangleBuffer = true; } - if (!(Flags::kStencilOnly & fFlags)) { + if (!(OpFlags::kStencilOnly & fOpFlags)) { fDoFillTriangleBuffer = true; } return true; } -void GrTessellatePathOp::prepareMiddleOutInnerTriangles(GrMeshDrawOp::Target* target, - int* numCountedCurves) { +void GrTessellatePathOp::prepareMiddleOutTrianglesAndCubics( + GrMeshDrawOp::Target* target, GrResolveLevelCounter* resolveLevelCounter, + bool drawTrianglesAsIndirectCubicDraw) { SkASSERT(!fTriangleBuffer); SkASSERT(!fDoStencilTriangleBuffer); SkASSERT(!fDoFillTriangleBuffer); + SkASSERT(!fCubicBuffer); + SkASSERT(!fStencilCubicsShader); + SkASSERT(!fIndirectDrawBuffer); // No initial moveTo, plus an implicit close at the end; n-2 triangles fill an n-gon. - // Each triangle has 3 vertices. - int maxVertices = (fPath.countVerbs() - 1) * 3; - - GrEagerDynamicVertexAllocator vertexAlloc(target, &fTriangleBuffer, &fBaseTriangleVertex); - auto* vertexData = vertexAlloc.lock<SkPoint>(maxVertices); + int maxInnerTriangles = fPath.countVerbs() - 1; + int maxCubics = fPath.countVerbs(); + + SkPoint* vertexData; + int vertexAdvancePerTriangle; + if (drawTrianglesAsIndirectCubicDraw) { + // Allocate the triangles as 4-point instances at the beginning of the cubic buffer. + SkASSERT(resolveLevelCounter); + vertexAdvancePerTriangle = 4; + int baseTriangleInstance; + vertexData = static_cast<SkPoint*>(target->makeVertexSpace( + sizeof(SkPoint) * 4, maxInnerTriangles + maxCubics, &fCubicBuffer, + &baseTriangleInstance)); + fBaseCubicVertex = baseTriangleInstance * 4; + } else { + // Allocate the triangles as normal 3-point instances in the triangle buffer. + vertexAdvancePerTriangle = 3; + vertexData = static_cast<SkPoint*>(target->makeVertexSpace( + sizeof(SkPoint), maxInnerTriangles * 3, &fTriangleBuffer, &fBaseTriangleVertex)); + } if (!vertexData) { return; } - GrMiddleOutPolygonTriangulator middleOut(vertexData, maxVertices); - int localCurveCount = 0; + GrVectorXform xform(fViewMatrix); + GrMiddleOutPolygonTriangulator middleOut(vertexData, vertexAdvancePerTriangle, + fPath.countVerbs()); + if (resolveLevelCounter) { + resolveLevelCounter->reset(); + } + int numCountedCurves = 0; for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) { switch (verb) { case SkPathVerb::kMove: - middleOut.closeAndMove(*pts++); + middleOut.closeAndMove(pts[0]); break; case SkPathVerb::kLine: middleOut.pushVertex(pts[1]); break; case SkPathVerb::kQuad: middleOut.pushVertex(pts[2]); - ++localCurveCount; + if (resolveLevelCounter) { + // Quadratics get converted to cubics before rendering. + resolveLevelCounter->countCubic(GrWangsFormula::quadratic_log2( + kLinearizationIntolerance, pts, xform)); + break; + } + ++numCountedCurves; break; case SkPathVerb::kCubic: middleOut.pushVertex(pts[3]); - ++localCurveCount; + if (resolveLevelCounter) { + resolveLevelCounter->countCubic(GrWangsFormula::cubic_log2( + kLinearizationIntolerance, pts, xform)); + break; + } + ++numCountedCurves; break; case SkPathVerb::kClose: middleOut.close(); @@ -147,13 +210,31 @@ void GrTessellatePathOp::prepareMiddleOutInnerTriangles(GrMeshDrawOp::Target* ta SkUNREACHABLE; } } - fTriangleVertexCount = middleOut.close(); - *numCountedCurves = localCurveCount; - - vertexAlloc.unlock(fTriangleVertexCount); - - if (fTriangleVertexCount) { - fDoStencilTriangleBuffer = true; + int triangleCount = middleOut.close(); + SkASSERT(triangleCount <= maxInnerTriangles); + + if (drawTrianglesAsIndirectCubicDraw) { + SkASSERT(resolveLevelCounter); + int totalInstanceCount = triangleCount + resolveLevelCounter->totalCubicInstanceCount(); + SkASSERT(vertexAdvancePerTriangle == 4); + target->putBackVertices(maxInnerTriangles + maxCubics - totalInstanceCount, + sizeof(SkPoint) * 4); + if (totalInstanceCount) { + this->prepareIndirectOuterCubicsAndTriangles(target, *resolveLevelCounter, vertexData, + triangleCount); + } + } else { + SkASSERT(vertexAdvancePerTriangle == 3); + target->putBackVertices(maxInnerTriangles - triangleCount, sizeof(SkPoint) * 3); + fTriangleVertexCount = triangleCount * 3; + if (fTriangleVertexCount) { + fDoStencilTriangleBuffer = true; + } + if (resolveLevelCounter) { + this->prepareIndirectOuterCubics(target, *resolveLevelCounter); + } else { + this->prepareTessellatedOuterCubics(target, numCountedCurves); + } } } @@ -176,8 +257,141 @@ static void quad2cubic(const SkPoint pts[], SkPoint* out) { out[3] = pts[2]; } -void GrTessellatePathOp::prepareOuterCubics(GrMeshDrawOp::Target* target, int numCountedCurves, - CubicDataAlignment alignment) { +void GrTessellatePathOp::prepareIndirectOuterCubics( + GrMeshDrawOp::Target* target, const GrResolveLevelCounter& resolveLevelCounter) { + SkASSERT(resolveLevelCounter.totalCubicInstanceCount() >= 0); + if (resolveLevelCounter.totalCubicInstanceCount() == 0) { + return; + } + // Allocate a buffer to store the cubic data. + SkPoint* cubicData; + int baseInstance; + cubicData = static_cast<SkPoint*>(target->makeVertexSpace( + sizeof(SkPoint) * 4, resolveLevelCounter.totalCubicInstanceCount(), &fCubicBuffer, + &baseInstance)); + if (!cubicData) { + return; + } + fBaseCubicVertex = baseInstance * 4; + this->prepareIndirectOuterCubicsAndTriangles(target, resolveLevelCounter, cubicData, + /*numTrianglesAtBeginningOfData=*/0); +} + +void GrTessellatePathOp::prepareIndirectOuterCubicsAndTriangles( + GrMeshDrawOp::Target* target, const GrResolveLevelCounter& resolveLevelCounter, + SkPoint* cubicData, int numTrianglesAtBeginningOfData) { + SkASSERT(target->caps().drawInstancedSupport()); + SkASSERT(numTrianglesAtBeginningOfData + resolveLevelCounter.totalCubicInstanceCount() > 0); + SkASSERT(!fStencilCubicsShader); + SkASSERT(cubicData); + + fIndirectIndexBuffer = GrMiddleOutCubicShader::FindOrMakeMiddleOutIndexBuffer( + target->resourceProvider()); + if (!fIndirectIndexBuffer) { + return; + } + + // Here we treat fCubicBuffer as an instance buffer. It should have been prepared with the base + // vertex on an instance boundary in order to accommodate this. + SkASSERT(fBaseCubicVertex % 4 == 0); + int baseInstance = fBaseCubicVertex >> 2; + + // Start preparing the indirect draw buffer. + fIndirectDrawCount = resolveLevelCounter.totalCubicIndirectDrawCount(); + if (numTrianglesAtBeginningOfData) { + ++fIndirectDrawCount; // Add an indirect draw for the triangles at the beginning. + } + + // Allocate space for the GrDrawIndexedIndirectCommand structs. + GrDrawIndexedIndirectCommand* indirectData = target->makeDrawIndexedIndirectSpace( + fIndirectDrawCount, &fIndirectDrawBuffer, &fIndirectDrawOffset); + if (!indirectData) { + SkASSERT(!fIndirectDrawBuffer); + return; + } + + // Fill out the GrDrawIndexedIndirectCommand structs and determine the starting instance data + // location at each resolve level. + SkPoint* instanceLocations[kMaxResolveLevel + 1]; + int indirectIdx = 0; + int runningInstanceCount = 0; + if (numTrianglesAtBeginningOfData) { + // The caller has already packed "triangleInstanceCount" triangles into 4-point instances + // at the beginning of the instance buffer. Add a special-case indirect draw here that will + // emit the triangles [P0, P1, P2] from these 4-point instances. + indirectData[0] = GrMiddleOutCubicShader::MakeDrawTrianglesIndirectCmd( + numTrianglesAtBeginningOfData, baseInstance); + indirectIdx = 1; + runningInstanceCount = numTrianglesAtBeginningOfData; + } + for (int resolveLevel = 1; resolveLevel <= kMaxResolveLevel; ++resolveLevel) { + instanceLocations[resolveLevel] = cubicData + runningInstanceCount * 4; + if (int instanceCountAtCurrLevel = resolveLevelCounter[resolveLevel]) { + indirectData[indirectIdx++] = GrMiddleOutCubicShader::MakeDrawCubicsIndirectCmd( + resolveLevel, instanceCountAtCurrLevel, baseInstance + runningInstanceCount); + runningInstanceCount += instanceCountAtCurrLevel; + } + } + +#ifdef SK_DEBUG + SkASSERT(indirectIdx == fIndirectDrawCount); + SkASSERT(runningInstanceCount == numTrianglesAtBeginningOfData + + resolveLevelCounter.totalCubicInstanceCount()); + SkASSERT(fIndirectDrawCount > 0); + + SkPoint* endLocations[kMaxResolveLevel + 1]; + memcpy(endLocations, instanceLocations + 1, kMaxResolveLevel * sizeof(SkPoint*)); + int totalInstanceCount = numTrianglesAtBeginningOfData + + resolveLevelCounter.totalCubicInstanceCount(); + endLocations[kMaxResolveLevel] = cubicData + totalInstanceCount * 4; +#endif + + fCubicVertexCount = numTrianglesAtBeginningOfData * 4; + + if (resolveLevelCounter.totalCubicInstanceCount()) { + GrVectorXform xform(fViewMatrix); + for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) { + int level; + switch (verb) { + default: + continue; + case SkPathVerb::kQuad: + level = GrWangsFormula::quadratic_log2(kLinearizationIntolerance, pts, xform); + if (level == 0) { + continue; + } + level = std::min(level, kMaxResolveLevel); + quad2cubic(pts, instanceLocations[level]); + break; + case SkPathVerb::kCubic: + level = GrWangsFormula::cubic_log2(kLinearizationIntolerance, pts, xform); + if (level == 0) { + continue; + } + level = std::min(level, kMaxResolveLevel); + memcpy(instanceLocations[level], pts, sizeof(SkPoint) * 4); + break; + } + instanceLocations[level] += 4; + fCubicVertexCount += 4; + } + } + +#ifdef SK_DEBUG + for (int i = 1; i <= kMaxResolveLevel; ++i) { + SkASSERT(instanceLocations[i] == endLocations[i]); + } + SkASSERT(fCubicVertexCount == (numTrianglesAtBeginningOfData + + resolveLevelCounter.totalCubicInstanceCount()) * 4); +#endif + + fStencilCubicsShader = target->allocator()->make<GrMiddleOutCubicShader>(fViewMatrix); +} + +void GrTessellatePathOp::prepareTessellatedOuterCubics(GrMeshDrawOp::Target* target, + int numCountedCurves) { + SkASSERT(target->caps().shaderCaps()->tessellationSupport()); + SkASSERT(numCountedCurves >= 0); SkASSERT(!fCubicBuffer); SkASSERT(!fStencilCubicsShader); @@ -185,41 +399,35 @@ void GrTessellatePathOp::prepareOuterCubics(GrMeshDrawOp::Target* target, int nu return; } - bool instanceAligned = (alignment == CubicDataAlignment::kInstanceBoundary); - int instanceOrVertexStride = (instanceAligned) ? sizeof(SkPoint) * 4 : sizeof(SkPoint); - int instanceOrVertexCount = (instanceAligned) ? numCountedCurves : numCountedCurves * 4; - int baseInstanceOrVertex; - auto* vertexData = static_cast<SkPoint*>(target->makeVertexSpace( - instanceOrVertexStride, instanceOrVertexCount, &fCubicBuffer, &baseInstanceOrVertex)); + sizeof(SkPoint), numCountedCurves * 4, &fCubicBuffer, &fBaseCubicVertex)); if (!vertexData) { return; } - fBaseCubicVertex = (instanceAligned) ? baseInstanceOrVertex * 4 : baseInstanceOrVertex; fCubicVertexCount = 0; for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) { switch (verb) { + default: + continue; case SkPathVerb::kQuad: SkASSERT(fCubicVertexCount < numCountedCurves * 4); quad2cubic(pts, vertexData + fCubicVertexCount); - fCubicVertexCount += 4; break; case SkPathVerb::kCubic: SkASSERT(fCubicVertexCount < numCountedCurves * 4); memcpy(vertexData + fCubicVertexCount, pts, sizeof(SkPoint) * 4); - fCubicVertexCount += 4; - break; - default: break; } + fCubicVertexCount += 4; } SkASSERT(fCubicVertexCount == numCountedCurves * 4); - fStencilCubicsShader = target->allocator()->make<GrStencilCubicShader>(fViewMatrix); + fStencilCubicsShader = target->allocator()->make<GrTessellateCubicShader>(fViewMatrix); } -void GrTessellatePathOp::prepareCubicWedges(GrMeshDrawOp::Target* target) { +void GrTessellatePathOp::prepareTessellatedCubicWedges(GrMeshDrawOp::Target* target) { + SkASSERT(target->caps().shaderCaps()->tessellationSupport()); SkASSERT(!fCubicBuffer); SkASSERT(!fStencilCubicsShader); @@ -274,18 +482,18 @@ void GrTessellatePathOp::prepareCubicWedges(GrMeshDrawOp::Target* target) { vertexAlloc.unlock(fCubicVertexCount); if (fCubicVertexCount) { - fStencilCubicsShader = target->allocator()->make<GrStencilWedgeShader>(fViewMatrix); + fStencilCubicsShader = target->allocator()->make<GrTessellateWedgeShader>(fViewMatrix); } } -void GrTessellatePathOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) { - this->drawStencilPass(state); - if (!(Flags::kStencilOnly & fFlags)) { - this->drawCoverPass(state); +void GrTessellatePathOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) { + this->drawStencilPass(flushState); + if (!(OpFlags::kStencilOnly & fOpFlags)) { + this->drawCoverPass(flushState); } } -void GrTessellatePathOp::drawStencilPass(GrOpFlushState* state) { +void GrTessellatePathOp::drawStencilPass(GrOpFlushState* flushState) { // Increments clockwise triangles and decrements counterclockwise. Used for "winding" fill. constexpr static GrUserStencilSettings kIncrDecrStencil( GrUserStencilSettings::StaticInitSeparate< @@ -310,41 +518,48 @@ void GrTessellatePathOp::drawStencilPass(GrOpFlushState* state) { if (GrAAType::kNone != fAAType) { initArgs.fInputFlags |= GrPipeline::InputFlags::kHWAntialias; } - if (state->caps().wireframeSupport() && (Flags::kWireframe & fFlags)) { + if (flushState->caps().wireframeSupport() && (OpFlags::kWireframe & fOpFlags)) { initArgs.fInputFlags |= GrPipeline::InputFlags::kWireframe; } SkASSERT(SkPathFillType::kWinding == fPath.getFillType() || SkPathFillType::kEvenOdd == fPath.getFillType()); initArgs.fUserStencil = (SkPathFillType::kWinding == fPath.getFillType()) ? &kIncrDecrStencil : &kInvertStencil; - initArgs.fCaps = &state->caps(); + initArgs.fCaps = &flushState->caps(); GrPipeline pipeline(initArgs, GrDisableColorXPFactory::MakeXferProcessor(), - state->appliedHardClip()); + flushState->appliedHardClip()); if (fDoStencilTriangleBuffer) { SkASSERT(fTriangleBuffer); GrStencilTriangleShader stencilTriangleShader(fViewMatrix); - GrPathShader::ProgramInfo programInfo(state->writeView(), &pipeline, + GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline, &stencilTriangleShader); - state->bindPipelineAndScissorClip(programInfo, this->bounds()); - state->bindBuffers(nullptr, nullptr, fTriangleBuffer.get()); - state->draw(fTriangleVertexCount, fBaseTriangleVertex); + flushState->bindPipelineAndScissorClip(programInfo, this->bounds()); + flushState->bindBuffers(nullptr, nullptr, fTriangleBuffer.get()); + flushState->draw(fTriangleVertexCount, fBaseTriangleVertex); } if (fStencilCubicsShader) { - GrPathShader::ProgramInfo programInfo(state->writeView(), &pipeline, fStencilCubicsShader); - state->bindPipelineAndScissorClip(programInfo, this->bounds()); - state->bindBuffers(nullptr, nullptr, fCubicBuffer.get()); - state->draw(fCubicVertexCount, fBaseCubicVertex); - } - - // http://skbug.com/9739 - if (state->caps().requiresManualFBBarrierAfterTessellatedStencilDraw()) { - state->gpu()->insertManualFramebufferBarrier(); + SkASSERT(fCubicBuffer); + GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline, + fStencilCubicsShader); + flushState->bindPipelineAndScissorClip(programInfo, this->bounds()); + if (fIndirectDrawBuffer) { + SkASSERT(fIndirectIndexBuffer); + flushState->bindBuffers(fIndirectIndexBuffer.get(), fCubicBuffer.get(), nullptr); + flushState->drawIndexedIndirect(fIndirectDrawBuffer.get(), fIndirectDrawOffset, + fIndirectDrawCount); + } else { + flushState->bindBuffers(nullptr, nullptr, fCubicBuffer.get()); + flushState->draw(fCubicVertexCount, fBaseCubicVertex); + if (flushState->caps().requiresManualFBBarrierAfterTessellatedStencilDraw()) { + flushState->gpu()->insertManualFramebufferBarrier(); // http://skbug.com/9739 + } + } } } -void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state) { +void GrTessellatePathOp::drawCoverPass(GrOpFlushState* flushState) { // Allows non-zero stencil values to pass and write a color, and resets the stencil value back // to zero; discards immediately on stencil values of zero. // NOTE: It's ok to not check the clip here because the previous stencil pass only wrote to @@ -361,7 +576,7 @@ void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state) { GrPipeline::InitArgs initArgs; if (GrAAType::kNone != fAAType) { initArgs.fInputFlags |= GrPipeline::InputFlags::kHWAntialias; - if (1 == state->proxy()->numSamples()) { + if (1 == flushState->proxy()->numSamples()) { SkASSERT(GrAAType::kCoverage == fAAType); // We are mixed sampled. Use conservative raster to make the sample coverage mask 100% // at every fragment. This way we will still get a double hit on shared edges, but @@ -370,10 +585,10 @@ void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state) { initArgs.fInputFlags |= GrPipeline::InputFlags::kConservativeRaster; } } - initArgs.fCaps = &state->caps(); - initArgs.fDstProxyView = state->drawOpArgs().dstProxyView(); - initArgs.fWriteSwizzle = state->drawOpArgs().writeSwizzle(); - GrPipeline pipeline(initArgs, std::move(fProcessors), state->detachAppliedClip()); + initArgs.fCaps = &flushState->caps(); + initArgs.fDstProxyView = flushState->drawOpArgs().dstProxyView(); + initArgs.fWriteSwizzle = flushState->drawOpArgs().writeSwizzle(); + GrPipeline pipeline(initArgs, std::move(fProcessors), flushState->detachAppliedClip()); if (fDoFillTriangleBuffer) { SkASSERT(fTriangleBuffer); @@ -420,29 +635,32 @@ void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state) { } GrFillTriangleShader fillTriangleShader(fViewMatrix, fColor); - GrPathShader::ProgramInfo programInfo(state->writeView(), &pipeline, &fillTriangleShader); - state->bindPipelineAndScissorClip(programInfo, this->bounds()); - state->bindTextures(fillTriangleShader, nullptr, pipeline); - state->bindBuffers(nullptr, nullptr, fTriangleBuffer.get()); - state->draw(fTriangleVertexCount, fBaseTriangleVertex); + GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline, + &fillTriangleShader); + flushState->bindPipelineAndScissorClip(programInfo, this->bounds()); + flushState->bindTextures(fillTriangleShader, nullptr, pipeline); + flushState->bindBuffers(nullptr, nullptr, fTriangleBuffer.get()); + flushState->draw(fTriangleVertexCount, fBaseTriangleVertex); if (fStencilCubicsShader) { + SkASSERT(fCubicBuffer); + // At this point, every pixel is filled in except the ones touched by curves. Issue a // final cover pass over the curves by drawing their convex hulls. This will fill in any // remaining samples and reset the stencil buffer. pipeline.setUserStencil(&kTestAndResetStencil); GrFillCubicHullShader fillCubicHullShader(fViewMatrix, fColor); - GrPathShader::ProgramInfo programInfo(state->writeView(), &pipeline, + GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline, &fillCubicHullShader); - state->bindPipelineAndScissorClip(programInfo, this->bounds()); - state->bindTextures(fillCubicHullShader, nullptr, pipeline); + flushState->bindPipelineAndScissorClip(programInfo, this->bounds()); + flushState->bindTextures(fillCubicHullShader, nullptr, pipeline); // Here we treat fCubicBuffer as an instance buffer. It should have been prepared with // the base vertex on an instance boundary in order to accommodate this. SkASSERT((fCubicVertexCount % 4) == 0); SkASSERT((fBaseCubicVertex % 4) == 0); - state->bindBuffers(nullptr, fCubicBuffer.get(), nullptr); - state->drawInstanced(fCubicVertexCount >> 2, fBaseCubicVertex >> 2, 4, 0); + flushState->bindBuffers(nullptr, fCubicBuffer.get(), nullptr); + flushState->drawInstanced(fCubicVertexCount >> 2, fBaseCubicVertex >> 2, 4, 0); } return; } @@ -450,9 +668,10 @@ void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state) { // There are no triangles to fill. Just draw a bounding box. pipeline.setUserStencil(&kTestAndResetStencil); GrFillBoundingBoxShader fillBoundingBoxShader(fViewMatrix, fColor, fPath.getBounds()); - GrPathShader::ProgramInfo programInfo(state->writeView(), &pipeline, &fillBoundingBoxShader); - state->bindPipelineAndScissorClip(programInfo, this->bounds()); - state->bindTextures(fillBoundingBoxShader, nullptr, pipeline); - state->bindBuffers(nullptr, nullptr, nullptr); - state->draw(4, 0); + GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline, + &fillBoundingBoxShader); + flushState->bindPipelineAndScissorClip(programInfo, this->bounds()); + flushState->bindTextures(fillBoundingBoxShader, nullptr, pipeline); + flushState->bindBuffers(nullptr, nullptr, nullptr); + flushState->draw(4, 0); } diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.h b/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.h index 8ee6d21bd65..c53e194a7f1 100644 --- a/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.h +++ b/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.h @@ -9,28 +9,23 @@ #define GrTessellatePathOp_DEFINED #include "src/gpu/ops/GrMeshDrawOp.h" +#include "src/gpu/tessellate/GrTessellationPathRenderer.h" class GrAppliedHardClip; class GrStencilPathShader; +class GrResolveLevelCounter; -// Renders paths using a hybrid Red Book "stencil, then cover" method. Curves get linearized by -// GPU tessellation shaders. This Op doesn't apply analytic AA, so it requires a render target that -// supports either MSAA or mixed samples if AA is desired. +// Renders paths using a hybrid "Red Book" (stencil, then cover) method. Curves get linearized by +// either GPU tessellation shaders or indirect draws. This Op doesn't apply analytic AA, so it +// requires a render target that supports either MSAA or mixed samples if AA is desired. class GrTessellatePathOp : public GrDrawOp { -public: - enum class Flags { - kNone = 0, - kStencilOnly = (1 << 0), - kWireframe = (1 << 1) - }; - private: DEFINE_OP_CLASS_ID GrTessellatePathOp(const SkMatrix& viewMatrix, const SkPath& path, GrPaint&& paint, - GrAAType aaType, Flags flags = Flags::kNone) + GrAAType aaType, GrTessellationPathRenderer::OpFlags opFlags) : GrDrawOp(ClassID()) - , fFlags(flags) + , fOpFlags(opFlags) , fViewMatrix(viewMatrix) , fPath(path) , fAAType(aaType) @@ -66,25 +61,41 @@ private: // and this is not an option as it would introduce T-junctions with the outer cubics. bool prepareNonOverlappingInnerTriangles(GrMeshDrawOp::Target*, int* numCountedCurves); - // Produces a "Red Book" style triangulation of the SkPath's inner polygon(s). The inner - // polygons connect the endpoints of each verb. (i.e., they are the path that would result from - // collapsing all curves to single lines.) Stencilled together with the outer cubics, these - // define the complete path. + // Produces a "Red Book" style triangulation of the SkPath's inner polygon(s) using a + // "middle-out" topology (See GrMiddleOutPolygonTriangulator), and then prepares outer cubics in + // the cubic buffer. The inner triangles and outer cubics stencilled together define the + // complete path. // - // This method emits the inner triangles with a "middle-out" topology. Middle-out can reduce - // the load on the rasterizer by a great deal as compared to a linear triangle strip or fan. - // See GrMiddleOutPolygonTriangulator. - void prepareMiddleOutInnerTriangles(GrMeshDrawOp::Target*, int* numCountedCurves); - - enum class CubicDataAlignment : bool { - kVertexBoundary, - kInstanceBoundary - }; - - // Writes an array of "outer" cubics from each bezier in the SkPath, converting any quadratics - // to cubics. An outer cubic is an independent, 4-point closed contour consisting of a single - // cubic curve. Stencilled together with the inner triangles, these define the complete path. - void prepareOuterCubics(GrMeshDrawOp::Target*, int numCountedCurves, CubicDataAlignment); + // If a resolveLevel counter is provided, this method resets it and uses it to count and + // prepares the outer cubics as indirect draws. Otherwise they are prepared as hardware + // tessellation patches. + // + // If drawTrianglesAsIndirectCubicDraw is true, then the resolveLevel counter must be non-null, + // and we express the inner triangles as an indirect cubic draw and sneak them in alongside the + // other cubic draws. + void prepareMiddleOutTrianglesAndCubics(GrMeshDrawOp::Target*, GrResolveLevelCounter* = nullptr, + bool drawTrianglesAsIndirectCubicDraw = false); + + // Prepares a list of indirect draw commands and instance data for the path's "outer cubics", + // converting any quadratics to cubics. An outer cubic is an independent, 4-point closed contour + // consisting of a single cubic curve. Stencilled together with the inner triangles, these + // define the complete path. + void prepareIndirectOuterCubics(GrMeshDrawOp::Target*, const GrResolveLevelCounter&); + + // For performance reasons we can often express triangles as an indirect cubic draw and sneak + // them in alongside the other indirect draws. This prepareIndirectOuterCubics variant allows + // the caller to provide a mapped cubic buffer with triangles already written into 4-point + // instances at the beginning. If numTrianglesAtBeginningOfData is nonzero, we add an extra + // indirect draw that renders these triangles. + void prepareIndirectOuterCubicsAndTriangles(GrMeshDrawOp::Target*, const GrResolveLevelCounter&, + SkPoint* cubicData, + int numTrianglesAtBeginningOfData); + + // Writes an array of "outer cubic" tessellation patches from each bezier in the SkPath, + // converting any quadratics to cubics. An outer cubic is an independent, 4-point closed contour + // consisting of a single cubic curve. Stencilled together with the inner triangles, these + // define the complete path. + void prepareTessellatedOuterCubics(GrMeshDrawOp::Target*, int numCountedCurves); // Writes an array of cubic "wedges" from the SkPath, converting any lines or quadratics to // cubics. A wedge is an independent, 5-point closed contour consisting of 4 cubic control @@ -92,13 +103,13 @@ private: // stencilled, these wedges alone define the complete path. // // TODO: Eventually we want to use rational cubic wedges in order to support conics. - void prepareCubicWedges(GrMeshDrawOp::Target*); + void prepareTessellatedCubicWedges(GrMeshDrawOp::Target*); void onExecute(GrOpFlushState*, const SkRect& chainBounds) override; void drawStencilPass(GrOpFlushState*); void drawCoverPass(GrOpFlushState*); - const Flags fFlags; + const GrTessellationPathRenderer::OpFlags fOpFlags; const SkMatrix fViewMatrix; const SkPath fPath; const GrAAType fAAType; @@ -137,6 +148,14 @@ private: int fCubicVertexCount; GrStencilPathShader* fStencilCubicsShader = nullptr; + // If fIndirectDrawBuffer is non-null, then we issue an indexed-indirect draw instead of using + // hardware tessellation. This is oftentimes faster than tessellation, and other times it serves + // as a polyfill when tessellation just isn't supported. + sk_sp<const GrBuffer> fIndirectDrawBuffer; + size_t fIndirectDrawOffset; + int fIndirectDrawCount; + sk_sp<const GrBuffer> fIndirectIndexBuffer; + friend class GrOpMemoryPool; // For ctor. public: @@ -144,6 +163,4 @@ public: class TestingOnly_Benchmark; }; -GR_MAKE_BITFIELD_CLASS_OPS(GrTessellatePathOp::Flags); - #endif diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.cpp b/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.cpp index e632c23a6f9..482a1ef7849 100644 --- a/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.cpp +++ b/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.cpp @@ -7,6 +7,8 @@ #include "src/gpu/tessellate/GrTessellationPathRenderer.h" +#include "include/pathops/SkPathOps.h" +#include "src/core/SkIPoint16.h" #include "src/core/SkPathPriv.h" #include "src/gpu/GrClip.h" #include "src/gpu/GrMemoryPool.h" @@ -17,19 +19,87 @@ #include "src/gpu/ops/GrFillRectOp.h" #include "src/gpu/tessellate/GrDrawAtlasPathOp.h" #include "src/gpu/tessellate/GrTessellatePathOp.h" +#include "src/gpu/tessellate/GrWangsFormula.h" constexpr static SkISize kAtlasInitialSize{512, 512}; constexpr static int kMaxAtlasSize = 2048; -GrTessellationPathRenderer::GrTessellationPathRenderer(const GrCaps& caps) : fAtlas( - GrColorType::kAlpha_8, GrDynamicAtlas::InternalMultisample::kYes, kAtlasInitialSize, - std::min(kMaxAtlasSize, caps.maxPreferredRenderTargetSize()), caps) { +// The atlas is only used for small-area paths, which means at least one dimension of every path is +// guaranteed to be quite small. So if we transpose tall paths, then every path will have a small +// height, which lends very well to efficient pow2 atlas packing. +constexpr static auto kAtlasAlgorithm = GrDynamicAtlas::RectanizerAlgorithm::kPow2; + +// Ensure every path in the atlas falls in or below the 128px high rectanizer band. +constexpr static int kMaxAtlasPathHeight = 128; + +GrTessellationPathRenderer::GrTessellationPathRenderer(const GrCaps& caps) + : fAtlas(GrColorType::kAlpha_8, GrDynamicAtlas::InternalMultisample::kYes, + kAtlasInitialSize, std::min(kMaxAtlasSize, caps.maxPreferredRenderTargetSize()), + caps, kAtlasAlgorithm) { + this->initAtlasFlags(*caps.shaderCaps()); +} + +void GrTessellationPathRenderer::initAtlasFlags(const GrShaderCaps& shaderCaps) { + fStencilAtlasFlags = OpFlags::kStencilOnly | OpFlags::kDisableHWTessellation; + fMaxAtlasPathWidth = fAtlas.maxAtlasSize() / 2; + // The atlas usually does better with hardware tessellation. If hardware tessellation is + // supported, we choose a max atlas path width that is guaranteed to never require more + // tessellation segments than are supported by the hardware. + if (!shaderCaps.tessellationSupport()) { + return; + } + // Since we limit the area of paths in the atlas to kMaxAtlasPathHeight^2, taller paths can't + // get very wide anyway. Find the tallest path whose width is limited by + // GrWangsFormula::worst_case_cubic() rather than the max area constraint, and use that for our + // max atlas path width. + // + // Solve the following equation for w: + // + // GrWangsFormula::worst_case_cubic(kLinearizationIntolerance, w, kMaxAtlasPathHeight^2 / w) + // == maxTessellationSegments + // + float k = GrWangsFormula::cubic_k(kLinearizationIntolerance); + float h = kMaxAtlasPathHeight; + float s = shaderCaps.maxTessellationSegments(); + // Quadratic formula from Numerical Recipes in C: + // + // q = -1/2 [b + sign(b) sqrt(b*b - 4*a*c)] + // x1 = q/a + // x2 = c/q + // + // float a = 1; // 'a' is always 1 in our specific equation. + float b = -s*s*s*s / (4*k*k); // Always negative. + float c = h*h*h*h; // Always positive. + float det = b*b - 4*1*c; + if (det <= 0) { + // maxTessellationSegments is too small for any path whose area == kMaxAtlasPathHeight^2. + // (This is unexpected because the GL spec mandates a minimum of 64 segments.) + SkDebugf("WARNING: maxTessellationSegments seems too low. (%i)\n", + shaderCaps.maxTessellationSegments()); + return; + } + float q = -.5f * (b - std::sqrt(det)); // Always positive. + // The two roots represent the width^2 and height^2 of the tallest rectangle that is limited by + // GrWangsFormula::worst_case_cubic(). + float r0 = q; // Always positive. + float r1 = c/q; // Always positive. + float worstCaseWidth = std::sqrt(std::max(r0, r1)); +#ifdef SK_DEBUG + float worstCaseHeight = std::sqrt(std::min(r0, r1)); + // Verify the above equation worked as expected. It should have found a width and height whose + // area == kMaxAtlasPathHeight^2. + SkASSERT(SkScalarNearlyEqual(worstCaseHeight * worstCaseWidth, h*h, 1)); + // Verify GrWangsFormula::worst_case_cubic() still works as we expect. The worst case number of + // segments for this bounding box should be maxTessellationSegments. + SkASSERT(SkScalarNearlyEqual(GrWangsFormula::worst_case_cubic( + kLinearizationIntolerance, worstCaseWidth, worstCaseHeight), s, 1)); +#endif + fStencilAtlasFlags &= ~OpFlags::kDisableHWTessellation; + fMaxAtlasPathWidth = std::min(fMaxAtlasPathWidth, (int)worstCaseWidth); } GrPathRenderer::CanDrawPath GrTessellationPathRenderer::onCanDrawPath( const CanDrawPathArgs& args) const { - // This class should not have been added to the chain without tessellation support. - SkASSERT(args.fCaps->shaderCaps()->tessellationSupport()); if (!args.fShape->style().isSimpleFill() || args.fShape->inverseFilled() || args.fViewMatrix->hasPerspective()) { return CanDrawPath::kNo; @@ -51,63 +121,142 @@ GrPathRenderer::CanDrawPath GrTessellationPathRenderer::onCanDrawPath( bool GrTessellationPathRenderer::onDrawPath(const DrawPathArgs& args) { GrRenderTargetContext* renderTargetContext = args.fRenderTargetContext; GrOpMemoryPool* pool = args.fContext->priv().opMemoryPool(); + const GrShaderCaps& shaderCaps = *args.fContext->priv().caps()->shaderCaps(); + SkPath path; args.fShape->asPath(&path); + SkRect devBounds; + args.fViewMatrix->mapRect(&devBounds, path.getBounds()); + // See if the path is small and simple enough to atlas instead of drawing directly. // // NOTE: The atlas uses alpha8 coverage even for msaa render targets. We could theoretically // render the sample mask to an integer texture, but such a scheme would probably require // GL_EXT_post_depth_coverage, which appears to have low adoption. SkIRect devIBounds; - SkIVector devToAtlasOffset; - if (this->tryAddPathToAtlas(*args.fContext->priv().caps(), *args.fViewMatrix, path, - args.fAAType, &devIBounds, &devToAtlasOffset)) { + SkIPoint16 locationInAtlas; + bool transposedInAtlas; + if (this->tryAddPathToAtlas(*args.fContext->priv().caps(), *args.fViewMatrix, path, devBounds, + args.fAAType, &devIBounds, &locationInAtlas, &transposedInAtlas)) { +#ifdef SK_DEBUG + // If using hardware tessellation in the atlas, make sure the max number of segments is + // sufficient for this path. fMaxAtlasPathWidth should have been tuned for this to always be + // the case. + if (!(fStencilAtlasFlags & OpFlags::kDisableHWTessellation)) { + int worstCaseNumSegments = GrWangsFormula::worst_case_cubic(kLinearizationIntolerance, + devIBounds.width(), + devIBounds.height()); + SkASSERT(worstCaseNumSegments <= shaderCaps.maxTessellationSegments()); + } +#endif auto op = pool->allocate<GrDrawAtlasPathOp>( renderTargetContext->numSamples(), sk_ref_sp(fAtlas.textureProxy()), - devIBounds, devToAtlasOffset, *args.fViewMatrix, std::move(args.fPaint)); - renderTargetContext->addDrawOp(*args.fClip, std::move(op)); + devIBounds, locationInAtlas, transposedInAtlas, *args.fViewMatrix, + std::move(args.fPaint)); + renderTargetContext->addDrawOp(args.fClip, std::move(op)); return true; } - auto op = pool->allocate<GrTessellatePathOp>( - *args.fViewMatrix, path, std::move(args.fPaint), args.fAAType); - renderTargetContext->addDrawOp(*args.fClip, std::move(op)); + auto drawPathFlags = OpFlags::kNone; + + // Find the worst-case log2 number of line segments that a curve in this path might need to be + // divided into. + int worstCaseResolveLevel = GrWangsFormula::worst_case_cubic_log2(kLinearizationIntolerance, + devBounds.width(), + devBounds.height()); + if (worstCaseResolveLevel > kMaxResolveLevel) { + // The path is too large for our internal indirect draw shaders. Crop it to the viewport. + SkPath viewport; + viewport.addRect(SkRect::MakeIWH(renderTargetContext->width(), + renderTargetContext->height()).makeOutset(1, 1)); + // Perform the crop in device space so it's a simple rect-path intersection. + path.transform(*args.fViewMatrix); + if (!Op(viewport, path, kIntersect_SkPathOp, &path)) { + // The crop can fail if the PathOps encounter NaN or infinities. Return true + // because drawing nothing is acceptable behavior for FP overflow. + return true; + } + // Transform the path back to its own local space. + SkMatrix inverse; + if (!args.fViewMatrix->invert(&inverse)) { + return true; // Singular view matrix. Nothing would have drawn anyway. Return true. + } + path.transform(inverse); + path.setIsVolatile(true); + args.fViewMatrix->mapRect(&devBounds, path.getBounds()); + worstCaseResolveLevel = GrWangsFormula::worst_case_cubic_log2(kLinearizationIntolerance, + devBounds.width(), + devBounds.height()); + // kMaxResolveLevel should be large enough to tessellate paths the size of any screen we + // might encounter. + SkASSERT(worstCaseResolveLevel <= kMaxResolveLevel); + } + + if ((1 << worstCaseResolveLevel) > shaderCaps.maxTessellationSegments()) { + // The path is too large for hardware tessellation; a curve in this bounding box could + // potentially require more segments than are supported by the hardware. Fall back on + // indirect draws. + drawPathFlags |= OpFlags::kDisableHWTessellation; + } + + auto op = pool->allocate<GrTessellatePathOp>(*args.fViewMatrix, path, std::move(args.fPaint), + args.fAAType, drawPathFlags); + renderTargetContext->addDrawOp(args.fClip, std::move(op)); return true; } bool GrTessellationPathRenderer::tryAddPathToAtlas( - const GrCaps& caps, const SkMatrix& viewMatrix, const SkPath& path, GrAAType aaType, - SkIRect* devIBounds, SkIVector* devToAtlasOffset) { + const GrCaps& caps, const SkMatrix& viewMatrix, const SkPath& path, const SkRect& devBounds, + GrAAType aaType, SkIRect* devIBounds, SkIPoint16* locationInAtlas, + bool* transposedInAtlas) { if (!caps.multisampleDisableSupport() && GrAAType::kNone == aaType) { return false; } - // Atlas paths require their points to be transformed on CPU. Check if the path has too many - // points to justify this CPU transformation. - if (path.countPoints() > 150) { + // Atlas paths require their points to be transformed on the CPU and copied into an "uber path". + // Check if this path has too many points to justify this extra work. + if (path.countPoints() > 200) { return false; } - // Check if the path is too large for an atlas. - SkRect devBounds; - viewMatrix.mapRect(&devBounds, path.getBounds()); - if (devBounds.height() * devBounds.width() > 100 * 100 || - std::max(devBounds.height(), devBounds.width()) > kMaxAtlasSize / 2) { + // Transpose tall paths in the atlas. Since we limit ourselves to small-area paths, this + // guarantees that every atlas entry has a small height, which lends very well to efficient pow2 + // atlas packing. + devBounds.roundOut(devIBounds); + int maxDimenstion = devIBounds->width(); + int minDimension = devIBounds->height(); + *transposedInAtlas = minDimension > maxDimenstion; + if (*transposedInAtlas) { + std::swap(minDimension, maxDimenstion); + } + + // Check if the path is too large for an atlas. Since we use "minDimension" for height in the + // atlas, limiting to kMaxAtlasPathHeight^2 pixels guarantees height <= kMaxAtlasPathHeight. + if (maxDimenstion * minDimension > kMaxAtlasPathHeight * kMaxAtlasPathHeight || + maxDimenstion > fMaxAtlasPathWidth) { return false; } - devBounds.roundOut(devIBounds); - if (!fAtlas.addRect(*devIBounds, devToAtlasOffset)) { + if (!fAtlas.addRect(maxDimenstion, minDimension, locationInAtlas)) { return false; } SkMatrix atlasMatrix = viewMatrix; - atlasMatrix.postTranslate(devToAtlasOffset->x(), devToAtlasOffset->y()); + if (*transposedInAtlas) { + std::swap(atlasMatrix[0], atlasMatrix[3]); + std::swap(atlasMatrix[1], atlasMatrix[4]); + float tx=atlasMatrix.getTranslateX(), ty=atlasMatrix.getTranslateY(); + atlasMatrix.setTranslateX(ty - devIBounds->y() + locationInAtlas->x()); + atlasMatrix.setTranslateY(tx - devIBounds->x() + locationInAtlas->y()); + } else { + atlasMatrix.postTranslate(locationInAtlas->x() - devIBounds->x(), + locationInAtlas->y() - devIBounds->y()); + } // Concatenate this path onto our uber path that matches its fill and AA types. SkPath* uberPath = this->getAtlasUberPath(path.getFillType(), GrAAType::kNone != aaType); - uberPath->moveTo(devToAtlasOffset->x(), devToAtlasOffset->y()); // Implicit moveTo(0,0). + uberPath->moveTo(locationInAtlas->x(), locationInAtlas->y()); // Implicit moveTo(0,0). uberPath->addPath(path, atlasMatrix); return true; } @@ -119,8 +268,8 @@ void GrTessellationPathRenderer::onStencilPath(const StencilPathArgs& args) { GrAAType aaType = (GrAA::kYes == args.fDoStencilMSAA) ? GrAAType::kMSAA : GrAAType::kNone; auto op = args.fContext->priv().opMemoryPool()->allocate<GrTessellatePathOp>( - *args.fViewMatrix, path, GrPaint(), aaType, GrTessellatePathOp::Flags::kStencilOnly); - args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op)); + *args.fViewMatrix, path, GrPaint(), aaType, OpFlags::kStencilOnly); + args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op)); } void GrTessellationPathRenderer::preFlush(GrOnFlushResourceProvider* onFlushRP, @@ -168,9 +317,8 @@ void GrTessellationPathRenderer::renderAtlas(GrOnFlushResourceProvider* onFlushR uberPath->setFillType(fillType); GrAAType aaType = (antialias) ? GrAAType::kMSAA : GrAAType::kNone; auto op = onFlushRP->opMemoryPool()->allocate<GrTessellatePathOp>( - SkMatrix::I(), *uberPath, GrPaint(), aaType, - GrTessellatePathOp::Flags::kStencilOnly); - rtc->addDrawOp(GrNoClip(), std::move(op)); + SkMatrix::I(), *uberPath, GrPaint(), aaType, fStencilAtlasFlags); + rtc->addDrawOp(nullptr, std::move(op)); } } @@ -206,7 +354,7 @@ void GrTessellationPathRenderer::renderAtlas(GrOnFlushResourceProvider* onFlushR auto coverOp = GrFillRectOp::Make(rtc->surfPriv().getContext(), std::move(paint), GrAAType::kMSAA, &drawQuad, stencil, fillRectFlags); - rtc->addDrawOp(GrNoClip(), std::move(coverOp)); + rtc->addDrawOp(nullptr, std::move(coverOp)); if (rtc->asSurfaceProxy()->requiresManualMSAAResolve()) { onFlushRP->addTextureResolveTask(sk_ref_sp(rtc->asTextureProxy()), diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.h b/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.h index bf8ea29eb70..4035a0d7a2f 100644 --- a/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.h +++ b/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.h @@ -19,9 +19,32 @@ // target that supports either MSAA or mixed samples if AA is desired. class GrTessellationPathRenderer : public GrPathRenderer, public GrOnFlushCallbackObject { public: - const char* name() const final { return "Tess"; } + // Don't allow linearized segments to be off by more than 1/4th of a pixel from the true curve. + constexpr static float kLinearizationIntolerance = 4; + + // This is the maximum resolve level supported by our internal indirect draw shaders. (Indirect + // draws are an alternative to hardware tessellation, and we can use them when hardware support + // is lacking.) + // + // At a given resolveLevel, a curve gets linearized into 2^resolveLevel line segments. So the + // finest resolveLevel supported by our indirect draw shaders is 2^10 == 1024 line segments. + // + // 1024 line segments is enough resolution (with intolerance == 4) to guarantee we can render a + // 123575px x 123575px path. (See GrWangsFormula::worst_case_cubic.) + constexpr static int kMaxResolveLevel = 10; + + // We send these flags to the internal tessellation Ops to control how a path gets rendered. + enum class OpFlags { + kNone = 0, + // Used when tessellation is not supported, or when a path will require more resolution than + // the max number of segments supported by the hardware. + kDisableHWTessellation = (1 << 0), + kStencilOnly = (1 << 1), + kWireframe = (1 << 2) + }; GrTessellationPathRenderer(const GrCaps&); + const char* name() const final { return "GrTessellationPathRenderer"; } StencilSupport onGetStencilSupport(const GrStyledShape& shape) const override { // TODO: Single-pass (e.g., convex) paths can have full support. return kStencilOnly_StencilSupport; @@ -33,18 +56,24 @@ public: int numOpsTaskIDs) override; private: + void initAtlasFlags(const GrShaderCaps& shaderCaps); SkPath* getAtlasUberPath(SkPathFillType fillType, bool antialias) { int idx = (int)antialias << 1; idx |= (int)fillType & 1; return &fAtlasUberPaths[idx]; } // Allocates space in fAtlas if the path is small and simple enough, and if there is room. - bool tryAddPathToAtlas(const GrCaps&, const SkMatrix&, const SkPath&, GrAAType, - SkIRect* devIBounds, SkIVector* devToAtlasOffset); + bool tryAddPathToAtlas(const GrCaps&, const SkMatrix&, const SkPath&, const SkRect& devBounds, + GrAAType, SkIRect* devIBounds, SkIPoint16* locationInAtlas, + bool* transposedInAtlas); void renderAtlas(GrOnFlushResourceProvider*); GrDynamicAtlas fAtlas; + OpFlags fStencilAtlasFlags; + int fMaxAtlasPathWidth; SkPath fAtlasUberPaths[4]; // 2 fillTypes * 2 antialias modes. }; +GR_MAKE_BITFIELD_CLASS_OPS(GrTessellationPathRenderer::OpFlags); + #endif diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrWangsFormula.h b/chromium/third_party/skia/src/gpu/tessellate/GrWangsFormula.h index 1fa79c6793e..b9c3264e479 100644 --- a/chromium/third_party/skia/src/gpu/tessellate/GrWangsFormula.h +++ b/chromium/third_party/skia/src/gpu/tessellate/GrWangsFormula.h @@ -22,6 +22,11 @@ SK_ALWAYS_INLINE static float length(const Sk2f& n) { return std::sqrt(nn[0] + nn[1]); } +// Constant term for the quatratic formula. +constexpr float quadratic_k(float intolerance) { + return .25f * intolerance; +} + // Returns the minimum number of evenly spaced (in the parametric sense) line segments that the // quadratic must be chopped into in order to guarantee all lines stay within a distance of // "1/intolerance" pixels from the true curve. @@ -29,10 +34,15 @@ SK_ALWAYS_INLINE static float quadratic(float intolerance, const SkPoint pts[]) Sk2f p0 = Sk2f::Load(pts); Sk2f p1 = Sk2f::Load(pts + 1); Sk2f p2 = Sk2f::Load(pts + 2); - float k = intolerance * .25f; + float k = quadratic_k(intolerance); return SkScalarSqrt(k * length(p0 - p1*2 + p2)); } +// Constant term for the cubic formula. +constexpr float cubic_k(float intolerance) { + return .75f * intolerance; +} + // Returns the minimum number of evenly spaced (in the parametric sense) line segments that the // cubic must be chopped into in order to guarantee all lines stay within a distance of // "1/intolerance" pixels from the true curve. @@ -41,11 +51,19 @@ SK_ALWAYS_INLINE static float cubic(float intolerance, const SkPoint pts[]) { Sk2f p1 = Sk2f::Load(pts + 1); Sk2f p2 = Sk2f::Load(pts + 2); Sk2f p3 = Sk2f::Load(pts + 3); - float k = intolerance * .75f; + float k = cubic_k(intolerance); return SkScalarSqrt(k * length(Sk2f::Max((p0 - p1*2 + p2).abs(), (p1 - p2*2 + p3).abs()))); } +// Returns the maximum number of line segments a cubic with the given device-space bounding box size +// would ever need to be divided into. This is simply a special case of the cubic formula where we +// maximize its value by placing control points on specific corners of the bounding box. +SK_ALWAYS_INLINE static float worst_case_cubic(float intolerance, float devWidth, float devHeight) { + float k = cubic_k(intolerance); + return SkScalarSqrt(2*k * SkVector::Length(devWidth, devHeight)); +} + // Returns the log2 of the provided value, were that value to be rounded up to the next power of 2. // Returns 0 if value <= 0: // Never returns a negative number, even if value is NaN. @@ -63,6 +81,10 @@ SK_ALWAYS_INLINE static int nextlog2(float value) { return exp & ~(exp >> 31); // Return 0 for negative or denormalized floats, and exponents < 0. } +SK_ALWAYS_INLINE static int ceil_log2_sqrt_sqrt(float f) { + return (nextlog2(f) + 3) >> 2; // i.e., "ceil(log2(sqrt(sqrt(f)))) +} + // Returns the minimum log2 number of evenly spaced (in the parametric sense) line segments that the // transformed quadratic must be chopped into in order to guarantee all lines stay within a distance // of "1/intolerance" pixels from the true curve. @@ -74,9 +96,9 @@ SK_ALWAYS_INLINE static int quadratic_log2(float intolerance, const SkPoint pts[ Sk2f v = p0 + p1*-2 + p2; v = vectorXform(v); Sk2f vv = v*v; - float k = intolerance * .25f; + float k = quadratic_k(intolerance); float f = k*k * (vv[0] + vv[1]); - return (nextlog2(f) + 3) >> 2; // ceil(log2(sqrt(sqrt(f)))) + return ceil_log2_sqrt_sqrt(f); } // Returns the minimum log2 number of evenly spaced (in the parametric sense) line segments that the @@ -91,9 +113,17 @@ SK_ALWAYS_INLINE static int cubic_log2(float intolerance, const SkPoint pts[], v = vectorXform(v); Sk4f vv = v*v; vv = Sk4f::Max(vv, SkNx_shuffle<2,3,0,1>(vv)); - float k = intolerance * .75f; + float k = cubic_k(intolerance); float f = k*k * (vv[0] + vv[1]); - return (nextlog2(f) + 3) >> 2; // ceil(log2(sqrt(sqrt(f)))) + return ceil_log2_sqrt_sqrt(f); +} + +// Returns the maximum log2 number of line segments a cubic with the given device-space bounding box +// size would ever need to be divided into. +SK_ALWAYS_INLINE static int worst_case_cubic_log2(float intolerance, float devWidth, + float devHeight) { + float k = cubic_k(intolerance); + return ceil_log2_sqrt_sqrt(4*k*k * (devWidth * devWidth + devHeight * devHeight)); } } // namespace diff --git a/chromium/third_party/skia/src/gpu/text/GrAtlasManager.cpp b/chromium/third_party/skia/src/gpu/text/GrAtlasManager.cpp index efe4a472683..3120255a7c8 100644 --- a/chromium/third_party/skia/src/gpu/text/GrAtlasManager.cpp +++ b/chromium/third_party/skia/src/gpu/text/GrAtlasManager.cpp @@ -7,6 +7,8 @@ #include "src/gpu/text/GrAtlasManager.h" +#include "src/codec/SkMasks.h" +#include "src/core/SkAutoMalloc.h" #include "src/gpu/GrGlyph.h" #include "src/gpu/GrImageInfo.h" #include "src/gpu/text/GrStrikeCache.h" @@ -32,6 +34,155 @@ bool GrAtlasManager::hasGlyph(GrMaskFormat format, GrGlyph* glyph) { return this->getAtlas(format)->hasID(glyph->fAtlasLocator.plotLocator()); } +template <typename INT_TYPE> +static void expand_bits(INT_TYPE* dst, + const uint8_t* src, + int width, + int height, + int dstRowBytes, + int srcRowBytes) { + for (int i = 0; i < height; ++i) { + int rowWritesLeft = width; + const uint8_t* s = src; + INT_TYPE* d = dst; + while (rowWritesLeft > 0) { + unsigned mask = *s++; + for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) { + *d++ = (mask & (1 << i)) ? (INT_TYPE)(~0UL) : 0; + } + } + dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes); + src += srcRowBytes; + } +} + +static void get_packed_glyph_image( + const SkGlyph& glyph, int dstRB, GrMaskFormat expectedMaskFormat, void* dst) { + const int width = glyph.width(); + const int height = glyph.height(); + const void* src = glyph.image(); + SkASSERT(src != nullptr); + + GrMaskFormat grMaskFormat = GrGlyph::FormatFromSkGlyph(glyph.maskFormat()); + if (grMaskFormat == expectedMaskFormat) { + int srcRB = glyph.rowBytes(); + // Notice this comparison is with the glyphs raw mask format, and not its GrMaskFormat. + if (glyph.maskFormat() != SkMask::kBW_Format) { + if (srcRB != dstRB) { + const int bbp = GrMaskFormatBytesPerPixel(expectedMaskFormat); + for (int y = 0; y < height; y++) { + memcpy(dst, src, width * bbp); + src = (const char*) src + srcRB; + dst = (char*) dst + dstRB; + } + } else { + memcpy(dst, src, dstRB * height); + } + } else { + // Handle 8-bit format by expanding the mask to the expected format. + const uint8_t* bits = reinterpret_cast<const uint8_t*>(src); + switch (expectedMaskFormat) { + case kA8_GrMaskFormat: { + uint8_t* bytes = reinterpret_cast<uint8_t*>(dst); + expand_bits(bytes, bits, width, height, dstRB, srcRB); + break; + } + case kA565_GrMaskFormat: { + uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst); + expand_bits(rgb565, bits, width, height, dstRB, srcRB); + break; + } + default: + SK_ABORT("Invalid GrMaskFormat"); + } + } + } else if (grMaskFormat == kA565_GrMaskFormat && expectedMaskFormat == kARGB_GrMaskFormat) { + // Convert if the glyph uses a 565 mask format since it is using LCD text rendering + // but the expected format is 8888 (will happen on macOS with Metal since that + // combination does not support 565). + static constexpr SkMasks masks{ + {0b1111'1000'0000'0000, 11, 5}, // Red + {0b0000'0111'1110'0000, 5, 6}, // Green + {0b0000'0000'0001'1111, 0, 5}, // Blue + {0, 0, 0} // Alpha + }; + constexpr int a565Bpp = GrMaskFormatBytesPerPixel(kA565_GrMaskFormat); + constexpr int argbBpp = GrMaskFormatBytesPerPixel(kARGB_GrMaskFormat); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + uint16_t color565 = 0; + memcpy(&color565, src, a565Bpp); + uint32_t colorRGBA = GrColorPackRGBA(masks.getRed(color565), + masks.getGreen(color565), + masks.getBlue(color565), + 0xFF); + memcpy(dst, &colorRGBA, argbBpp); + src = (char*)src + a565Bpp; + dst = (char*)dst + argbBpp; + } + } + } else { + // crbug:510931 + // Retrieving the image from the cache can actually change the mask format. This case is + // very uncommon so for now we just draw a clear box for these glyphs. + const int bpp = GrMaskFormatBytesPerPixel(expectedMaskFormat); + for (int y = 0; y < height; y++) { + sk_bzero(dst, width * bpp); + dst = (char*)dst + dstRB; + } + } +} + +// returns true if glyph successfully added to texture atlas, false otherwise. If the glyph's +// mask format has changed, then addGlyphToAtlas will draw a clear box. This will almost never +// happen. +// TODO we can handle some of these cases if we really want to, but the long term solution is to +// get the actual glyph image itself when we get the glyph metrics. +GrDrawOpAtlas::ErrorCode GrAtlasManager::addGlyphToAtlas(const SkGlyph& skGlyph, + int padding, + GrGlyph* grGlyph, + GrResourceProvider* resourceProvider, + GrDeferredUploadTarget* uploadTarget) { + if (skGlyph.image() == nullptr) { + return GrDrawOpAtlas::ErrorCode::kError; + } + SkASSERT(grGlyph != nullptr); + + GrMaskFormat glyphFormat = GrGlyph::FormatFromSkGlyph(skGlyph.maskFormat()); + GrMaskFormat expectedMaskFormat = this->resolveMaskFormat(glyphFormat); + int bytesPerPixel = GrMaskFormatBytesPerPixel(expectedMaskFormat); + + if (padding > 0) { + SkASSERT(skGlyph.maskFormat() != SkMask::kSDF_Format); + } + + SkASSERT(padding == 0 || padding == 1); + // Add 1 pixel padding around grGlyph if needed. + const int width = skGlyph.width() + 2*padding; + const int height = skGlyph.height() + 2*padding; + int rowBytes = width * bytesPerPixel; + size_t size = height * rowBytes; + + // Temporary storage for normalizing grGlyph image. + SkAutoSMalloc<1024> storage(size); + void* dataPtr = storage.get(); + if (padding > 0) { + sk_bzero(dataPtr, size); + // Advance in one row and one column. + dataPtr = (char*)(dataPtr) + rowBytes + bytesPerPixel; + } + + get_packed_glyph_image(skGlyph, rowBytes, expectedMaskFormat, dataPtr); + + return this->addToAtlas(resourceProvider, + uploadTarget, + expectedMaskFormat, + width, + height, + storage.get(), + &grGlyph->fAtlasLocator); +} + // add to texture atlas that matches this format GrDrawOpAtlas::ErrorCode GrAtlasManager::addToAtlas(GrResourceProvider* resourceProvider, GrDeferredUploadTarget* target, diff --git a/chromium/third_party/skia/src/gpu/text/GrAtlasManager.h b/chromium/third_party/skia/src/gpu/text/GrAtlasManager.h index 036495fa53b..97fcb9a81a8 100644 --- a/chromium/third_party/skia/src/gpu/text/GrAtlasManager.h +++ b/chromium/third_party/skia/src/gpu/text/GrAtlasManager.h @@ -28,18 +28,6 @@ public: GrAtlasManager(GrProxyProvider*, size_t maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing); ~GrAtlasManager() override; - // Change an expected 565 mask format to 8888 if 565 is not supported (will happen when using - // Metal on macOS). The actual conversion of the data is handled in get_packed_glyph_image() in - // GrStrikeCache.cpp - GrMaskFormat resolveMaskFormat(GrMaskFormat format) const { - if (kA565_GrMaskFormat == format && - !fProxyProvider->caps()->getDefaultBackendFormat(GrColorType::kBGR_565, - GrRenderable::kNo).isValid()) { - format = kARGB_GrMaskFormat; - } - return format; - } - // if getViews returns nullptr, the client must not try to use other functions on the // GrStrikeCache which use the atlas. This function *must* be called first, before other // functions which use the atlas. Note that we can have proxies available but none active @@ -58,6 +46,12 @@ public: bool hasGlyph(GrMaskFormat, GrGlyph*); + GrDrawOpAtlas::ErrorCode addGlyphToAtlas(const SkGlyph& skGlyph, + int padding, + GrGlyph* grGlyph, + GrResourceProvider* resourceProvider, + GrDeferredUploadTarget* uploadTarget); + // To ensure the GrDrawOpAtlas does not evict the Glyph Mask from its texture backing store, // the client must pass in the current op token along with the GrGlyph. // A BulkUseTokenUpdater is used to manage bulk last use token updating in the Atlas. @@ -118,6 +112,17 @@ public: private: bool initAtlas(GrMaskFormat); + // Change an expected 565 mask format to 8888 if 565 is not supported (will happen when using + // Metal on macOS). The actual conversion of the data is handled in get_packed_glyph_image() in + // GrStrikeCache.cpp + GrMaskFormat resolveMaskFormat(GrMaskFormat format) const { + if (kA565_GrMaskFormat == format && + !fProxyProvider->caps()->getDefaultBackendFormat(GrColorType::kBGR_565, + GrRenderable::kNo).isValid()) { + format = kARGB_GrMaskFormat; + } + return format; + } // There is a 1:1 mapping between GrMaskFormats and atlas indices static int MaskFormatToAtlasIndex(GrMaskFormat format) { return static_cast<int>(format); } diff --git a/chromium/third_party/skia/src/gpu/text/GrSDFTOptions.cpp b/chromium/third_party/skia/src/gpu/text/GrSDFTOptions.cpp new file mode 100644 index 00000000000..e0ed2189e90 --- /dev/null +++ b/chromium/third_party/skia/src/gpu/text/GrSDFTOptions.cpp @@ -0,0 +1,167 @@ +/* + * Copyright 2020 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "src/gpu/text/GrSDFTOptions.h" + +#include "include/core/SkFont.h" +#include "include/core/SkMatrix.h" +#include "include/core/SkPaint.h" +#include "include/core/SkScalar.h" +#include "include/core/SkSurfaceProps.h" + +#include <tuple> + +// DF sizes and thresholds for usage of the small and medium sizes. For example, above +// kSmallDFFontLimit we will use the medium size. The large size is used up until the size at +// which we switch over to drawing as paths as controlled by Options. +static const int kSmallDFFontSize = 32; +static const int kSmallDFFontLimit = 32; +static const int kMediumDFFontSize = 72; +static const int kMediumDFFontLimit = 72; +static const int kLargeDFFontSize = 162; +#ifdef SK_BUILD_FOR_MAC +static const int kLargeDFFontLimit = 162; +static const int kExtraLargeDFFontSize = 256; +#endif + +GrSDFTOptions::GrSDFTOptions(SkScalar min, SkScalar max) + : fMinDistanceFieldFontSize{min} + , fMaxDistanceFieldFontSize{max} { + SkASSERT_RELEASE(min > 0 && max >= min); +} + +bool GrSDFTOptions::canDrawAsDistanceFields(const SkPaint& paint, const SkFont& font, + const SkMatrix& viewMatrix, + const SkSurfaceProps& props, + bool contextSupportsDistanceFieldText) const { + // mask filters modify alpha, which doesn't translate well to distance + if (paint.getMaskFilter() || !contextSupportsDistanceFieldText) { + return false; + } + + // TODO: add some stroking support + if (paint.getStyle() != SkPaint::kFill_Style) { + return false; + } + + if (viewMatrix.hasPerspective()) { + // Don't use SDF for perspective. Paths look better. + return false; + } else { + SkScalar maxScale = viewMatrix.getMaxScale(); + SkScalar scaledTextSize = maxScale * font.getSize(); + // Hinted text looks far better at small resolutions + // Scaling up beyond 2x yields undesirable artifacts + if (scaledTextSize < fMinDistanceFieldFontSize || + scaledTextSize > fMaxDistanceFieldFontSize) { + return false; + } + + bool useDFT = props.isUseDeviceIndependentFonts(); +#if SK_FORCE_DISTANCE_FIELD_TEXT + useDFT = true; +#endif + + if (!useDFT && scaledTextSize < kLargeDFFontSize) { + return false; + } + } + + return true; +} + +SkScalar scaled_text_size(const SkScalar textSize, const SkMatrix& viewMatrix) { + SkScalar scaledTextSize = textSize; + + if (viewMatrix.hasPerspective()) { + // for perspective, we simply force to the medium size + // TODO: compute a size based on approximate screen area + scaledTextSize = kMediumDFFontLimit; + } else { + SkScalar maxScale = viewMatrix.getMaxScale(); + // if we have non-unity scale, we need to choose our base text size + // based on the SkPaint's text size multiplied by the max scale factor + // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)? + if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) { + scaledTextSize *= maxScale; + } + } + + return scaledTextSize; +} + +SkFont GrSDFTOptions::getSDFFont(const SkFont& font, + const SkMatrix& viewMatrix, + SkScalar* textRatio) const { + SkScalar textSize = font.getSize(); + SkScalar scaledTextSize = scaled_text_size(textSize, viewMatrix); + + SkFont dfFont{font}; + + if (scaledTextSize <= kSmallDFFontLimit) { + *textRatio = textSize / kSmallDFFontSize; + dfFont.setSize(SkIntToScalar(kSmallDFFontSize)); + } else if (scaledTextSize <= kMediumDFFontLimit) { + *textRatio = textSize / kMediumDFFontSize; + dfFont.setSize(SkIntToScalar(kMediumDFFontSize)); +#ifdef SK_BUILD_FOR_MAC + } else if (scaledTextSize <= kLargeDFFontLimit) { + *textRatio = textSize / kLargeDFFontSize; + dfFont.setSize(SkIntToScalar(kLargeDFFontSize)); + } else { + *textRatio = textSize / kExtraLargeDFFontSize; + dfFont.setSize(SkIntToScalar(kExtraLargeDFFontSize)); + } +#else + } else { + *textRatio = textSize / kLargeDFFontSize; + dfFont.setSize(SkIntToScalar(kLargeDFFontSize)); + } +#endif + + dfFont.setEdging(SkFont::Edging::kAntiAlias); + dfFont.setForceAutoHinting(false); + dfFont.setHinting(SkFontHinting::kNormal); + + // The sub-pixel position will always happen when transforming to the screen. + dfFont.setSubpixel(false); + return dfFont; +} + +std::pair<SkScalar, SkScalar> GrSDFTOptions::computeSDFMinMaxScale( + SkScalar textSize, const SkMatrix& viewMatrix) const { + + SkScalar scaledTextSize = scaled_text_size(textSize, viewMatrix); + + // We have three sizes of distance field text, and within each size 'bucket' there is a floor + // and ceiling. A scale outside of this range would require regenerating the distance fields + SkScalar dfMaskScaleFloor; + SkScalar dfMaskScaleCeil; + if (scaledTextSize <= kSmallDFFontLimit) { + dfMaskScaleFloor = fMinDistanceFieldFontSize; + dfMaskScaleCeil = kSmallDFFontLimit; + } else if (scaledTextSize <= kMediumDFFontLimit) { + dfMaskScaleFloor = kSmallDFFontLimit; + dfMaskScaleCeil = kMediumDFFontLimit; + } else { + dfMaskScaleFloor = kMediumDFFontLimit; + dfMaskScaleCeil = fMaxDistanceFieldFontSize; + } + + // Because there can be multiple runs in the blob, we want the overall maxMinScale, and + // minMaxScale to make regeneration decisions. Specifically, we want the maximum minimum scale + // we can tolerate before we'd drop to a lower mip size, and the minimum maximum scale we can + // tolerate before we'd have to move to a large mip size. When we actually test these values + // we look at the delta in scale between the new viewmatrix and the old viewmatrix, and test + // against these values to decide if we can reuse or not(ie, will a given scale change our mip + // level) + SkASSERT(dfMaskScaleFloor <= scaledTextSize && scaledTextSize <= dfMaskScaleCeil); + + return std::make_pair(dfMaskScaleFloor / scaledTextSize, dfMaskScaleCeil / scaledTextSize); +} + + diff --git a/chromium/third_party/skia/src/gpu/text/GrSDFTOptions.h b/chromium/third_party/skia/src/gpu/text/GrSDFTOptions.h new file mode 100644 index 00000000000..33e7b6bd2db --- /dev/null +++ b/chromium/third_party/skia/src/gpu/text/GrSDFTOptions.h @@ -0,0 +1,38 @@ +/* + * Copyright 2020 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrSDFTOptions_DEFINED +#define GrSDFTOptions_DEFINED + +#include "include/core/SkFont.h" +#include "include/core/SkScalar.h" + +class SkMatrix; +class SkSurfaceProps; + +class GrSDFTOptions { +public: + GrSDFTOptions(SkScalar min, SkScalar max); + + bool canDrawAsDistanceFields(const SkPaint&, const SkFont&, const SkMatrix& viewMatrix, + const SkSurfaceProps& props, + bool contextSupportsDistanceFieldText) const; + SkFont getSDFFont(const SkFont& font, + const SkMatrix& viewMatrix, + SkScalar* textRatio) const; + std::pair<SkScalar, SkScalar> computeSDFMinMaxScale( + SkScalar textSize, const SkMatrix& viewMatrix) const; +private: + // Below this size (in device space) distance field text will not be used. + const SkScalar fMinDistanceFieldFontSize; + + // Above this size (in device space) distance field text will not be used and glyphs will + // be rendered from outline as individual paths. + const SkScalar fMaxDistanceFieldFontSize; +}; + +#endif // GrSDFTOptions_DEFINED diff --git a/chromium/third_party/skia/src/gpu/text/GrTextBlob.cpp b/chromium/third_party/skia/src/gpu/text/GrTextBlob.cpp index e73868beaa7..565d605f995 100644 --- a/chromium/third_party/skia/src/gpu/text/GrTextBlob.cpp +++ b/chromium/third_party/skia/src/gpu/text/GrTextBlob.cpp @@ -8,11 +8,10 @@ #include "include/core/SkColorFilter.h" #include "include/gpu/GrContext.h" #include "include/private/SkTemplates.h" -#include "src/codec/SkMasks.h" -#include "src/core/SkAutoMalloc.h" #include "src/core/SkMaskFilterBase.h" #include "src/core/SkMatrixProvider.h" #include "src/core/SkPaintPriv.h" +#include "src/core/SkStrikeSpec.h" #include "src/gpu/GrBlurUtils.h" #include "src/gpu/GrClip.h" #include "src/gpu/GrStyle.h" @@ -41,153 +40,229 @@ GrTextBlob::PathGlyph::PathGlyph(const SkPath& path, SkPoint origin) // -- GrTextBlob::SubRun --------------------------------------------------------------------------- GrTextBlob::SubRun::SubRun(SubRunType type, GrTextBlob* textBlob, const SkStrikeSpec& strikeSpec, - GrMaskFormat format, const SkSpan<PackedGlyphIDorGrGlyph>& glyphs, - const SkSpan<char>& vertexData) - : fType{type} - , fBlob{textBlob} + GrMaskFormat format, SkRect vertexBounds, + const SkSpan<VertexData>& vertexData) + : fBlob{textBlob} + , fType{type} , fMaskFormat{format} - , fGlyphs{glyphs} - , fVertexData{vertexData} , fStrikeSpec{strikeSpec} - , fCurrentColor{textBlob->fColor} - , fCurrentOrigin{textBlob->fInitialOrigin} - , fCurrentMatrix{textBlob->fInitialMatrix} { - SkASSERT(type != kTransformedPath); - textBlob->insertSubRun(this); + , fVertexBounds{vertexBounds} + , fVertexData{vertexData} { + SkASSERT(fType != kTransformedPath); } GrTextBlob::SubRun::SubRun(GrTextBlob* textBlob, const SkStrikeSpec& strikeSpec) - : fType{kTransformedPath} - , fBlob{textBlob} + : fBlob{textBlob} + , fType{kTransformedPath} , fMaskFormat{kA8_GrMaskFormat} - , fGlyphs{SkSpan<PackedGlyphIDorGrGlyph>{}} - , fVertexData{SkSpan<char>{}} , fStrikeSpec{strikeSpec} - , fCurrentColor{textBlob->fColor} - , fPaths{} { - textBlob->insertSubRun(this); -} - -static SkRect dest_rect(const SkGlyph& g, SkPoint origin) { - return SkRect::MakeXYWH( - SkIntToScalar(g.left()) + origin.x(), - SkIntToScalar(g.top()) + origin.y(), - SkIntToScalar(g.width()), - SkIntToScalar(g.height())); -} - -static bool is_SDF(const SkGlyph& skGlyph) { - return skGlyph.maskFormat() == SkMask::kSDF_Format; -} - -static SkRect dest_rect(const SkGlyph& g, SkPoint origin, SkScalar textScale) { - if (!is_SDF(g)) { - return SkRect::MakeXYWH( - SkIntToScalar(g.left()) * textScale + origin.x(), - SkIntToScalar(g.top()) * textScale + origin.y(), - SkIntToScalar(g.width()) * textScale, - SkIntToScalar(g.height()) * textScale); - } else { - return SkRect::MakeXYWH( - (SkIntToScalar(g.left()) + SK_DistanceFieldInset) * textScale + origin.x(), - (SkIntToScalar(g.top()) + SK_DistanceFieldInset) * textScale + origin.y(), - (SkIntToScalar(g.width()) - 2 * SK_DistanceFieldInset) * textScale, - (SkIntToScalar(g.height()) - 2 * SK_DistanceFieldInset) * textScale); - } -} - -void GrTextBlob::SubRun::appendGlyphs(const SkZip<SkGlyphVariant, SkPoint>& drawables) { - SkScalar strikeToSource = fStrikeSpec.strikeToSourceRatio(); - SkASSERT(!this->isPrepared()); - PackedGlyphIDorGrGlyph* packedIDCursor = fGlyphs.data(); - char* vertexCursor = fVertexData.data(); - size_t vertexStride = this->vertexStride(); - // We always write the third position component used by SDFs. If it is unused it gets - // overwritten. Similarly, we always write the color and the blob will later overwrite it - // with texture coords if it is unused. - size_t colorOffset = this->colorOffset(); - for (auto [variant, pos] : drawables) { - SkGlyph* skGlyph = variant; - // Only floor the device coordinates. - SkRect dstRect; - if (!this->needsTransform()) { - pos = {SkScalarFloorToScalar(pos.x()), SkScalarFloorToScalar(pos.y())}; - dstRect = dest_rect(*skGlyph, pos); - } else { - dstRect = dest_rect(*skGlyph, pos, strikeToSource); - } - - this->joinGlyphBounds(dstRect); - - // V0 - *reinterpret_cast<SkPoint3*>(vertexCursor) = {dstRect.fLeft, dstRect.fTop, 1.f}; - *reinterpret_cast<GrColor*>(vertexCursor + colorOffset) = fCurrentColor; - vertexCursor += vertexStride; - - // V1 - *reinterpret_cast<SkPoint3*>(vertexCursor) = {dstRect.fLeft, dstRect.fBottom, 1.f}; - *reinterpret_cast<GrColor*>(vertexCursor + colorOffset) = fCurrentColor; - vertexCursor += vertexStride; - - // V2 - *reinterpret_cast<SkPoint3*>(vertexCursor) = {dstRect.fRight, dstRect.fTop, 1.f}; - *reinterpret_cast<GrColor*>(vertexCursor + colorOffset) = fCurrentColor; - vertexCursor += vertexStride; - - // V3 - *reinterpret_cast<SkPoint3*>(vertexCursor) = {dstRect.fRight, dstRect.fBottom, 1.f}; - *reinterpret_cast<GrColor*>(vertexCursor + colorOffset) = fCurrentColor; - vertexCursor += vertexStride; - - packedIDCursor->fPackedGlyphID = skGlyph->getPackedID(); - packedIDCursor++; - } - - // Use the negative initial origin to make the fVertexBounds {0, 0} based. - SkPoint pt = fBlob->fInitialOrigin; - if (!this->needsTransform()) { - // If the box is in device space, then transform the source space origin to device space. - pt = fBlob->fInitialMatrix.mapXY(pt.x(), pt.y()); - } - fVertexBounds.offset(-pt); -} + , fVertexBounds{SkRect::MakeEmpty()} + , fVertexData{SkSpan<VertexData>{}} { } void GrTextBlob::SubRun::resetBulkUseToken() { fBulkUseToken.reset(); } GrDrawOpAtlas::BulkUseTokenUpdater* GrTextBlob::SubRun::bulkUseToken() { return &fBulkUseToken; } -GrTextStrike* GrTextBlob::SubRun::strike() const { return fStrike.get(); } GrMaskFormat GrTextBlob::SubRun::maskFormat() const { return fMaskFormat; } -size_t GrTextBlob::SubRun::vertexStride() const { - return GetVertexStride(this->maskFormat(), this->hasW()); -} -size_t GrTextBlob::SubRun::colorOffset() const { - return this->hasW() ? offsetof(SDFT3DVertex, color) : offsetof(Mask2DVertex, color); -} -size_t GrTextBlob::SubRun::texCoordOffset() const { - switch (fMaskFormat) { +size_t GrTextBlob::SubRun::vertexStride() const { + switch (this->maskFormat()) { case kA8_GrMaskFormat: - return this->hasW() ? offsetof(SDFT3DVertex, atlasPos) - : offsetof(Mask2DVertex, atlasPos); + return this->hasW() ? sizeof(Mask3DVertex) : sizeof(Mask2DVertex); case kARGB_GrMaskFormat: - return this->hasW() ? offsetof(ARGB3DVertex, atlasPos) - : offsetof(ARGB2DVertex, atlasPos); + return this->hasW() ? sizeof(ARGB3DVertex) : sizeof(ARGB2DVertex); default: SkASSERT(!this->hasW()); - return offsetof(Mask2DVertex, atlasPos); + return sizeof(Mask2DVertex); } -} - -char* GrTextBlob::SubRun::quadStart(size_t index) const { - return SkTAddOffset<char>(fVertexData.data(), this->quadOffset(index)); + SkUNREACHABLE; } size_t GrTextBlob::SubRun::quadOffset(size_t index) const { return index * kVerticesPerGlyph * this->vertexStride(); } -void GrTextBlob::SubRun::joinGlyphBounds(const SkRect& glyphBounds) { - fVertexBounds.joinNonEmptyArg(glyphBounds); +template <typename Rect> +static auto ltbr(const Rect& r) { + return std::make_tuple(r.left(), r.top(), r.right(), r.bottom()); +} + +void GrTextBlob::SubRun::fillVertexData( + void *vertexDst, int offset, int count, + GrColor color, const SkMatrix& drawMatrix, SkPoint drawOrigin, SkIRect clip) const { + + SkMatrix matrix = drawMatrix; + matrix.preTranslate(drawOrigin.x(), drawOrigin.y()); + + auto transformed2D = [&](auto dst, SkScalar dstPadding, SkScalar srcPadding) { + SkScalar strikeToSource = fStrikeSpec.strikeToSourceRatio(); + SkPoint inset = {dstPadding, dstPadding}; + for (auto[quad, vertexData] : SkMakeZip(dst, fVertexData.subspan(offset, count))) { + auto[glyph, pos, rect] = vertexData; + auto [l, t, r, b] = rect; + SkPoint sLT = (SkPoint::Make(l, t) + inset) * strikeToSource + pos, + sRB = (SkPoint::Make(r, b) - inset) * strikeToSource + pos; + SkPoint lt = matrix.mapXY(sLT.x(), sLT.y()), + lb = matrix.mapXY(sLT.x(), sRB.y()), + rt = matrix.mapXY(sRB.x(), sLT.y()), + rb = matrix.mapXY(sRB.x(), sRB.y()); + auto[al, at, ar, ab] = glyph.grGlyph->fAtlasLocator.getUVs(srcPadding); + quad[0] = {lt, color, {al, at}}; // L,T + quad[1] = {lb, color, {al, ab}}; // L,B + quad[2] = {rt, color, {ar, at}}; // R,T + quad[3] = {rb, color, {ar, ab}}; // R,B + } + }; + + auto transformed3D = [&](auto dst, SkScalar dstPadding, SkScalar srcPadding) { + SkScalar strikeToSource = fStrikeSpec.strikeToSourceRatio(); + SkPoint inset = {dstPadding, dstPadding}; + auto mapXYZ = [&](SkScalar x, SkScalar y) { + SkPoint pt{x, y}; + SkPoint3 result; + matrix.mapHomogeneousPoints(&result, &pt, 1); + return result; + }; + for (auto[quad, vertexData] : SkMakeZip(dst, fVertexData.subspan(offset, count))) { + auto[glyph, pos, rect] = vertexData; + auto [l, t, r, b] = rect; + SkPoint sLT = (SkPoint::Make(l, t) + inset) * strikeToSource + pos, + sRB = (SkPoint::Make(r, b) - inset) * strikeToSource + pos; + SkPoint3 lt = mapXYZ(sLT.x(), sLT.y()), + lb = mapXYZ(sLT.x(), sRB.y()), + rt = mapXYZ(sRB.x(), sLT.y()), + rb = mapXYZ(sRB.x(), sRB.y()); + auto[al, at, ar, ab] = glyph.grGlyph->fAtlasLocator.getUVs(srcPadding); + quad[0] = {lt, color, {al, at}}; // L,T + quad[1] = {lb, color, {al, ab}}; // L,B + quad[2] = {rt, color, {ar, at}}; // R,T + quad[3] = {rb, color, {ar, ab}}; // R,B + } + }; + + auto direct2D = [&](auto dst, SkIRect* clip) { + // Rectangles in device space + SkPoint originInDeviceSpace = matrix.mapXY(0, 0); + for (auto[quad, vertexData] : SkMakeZip(dst, fVertexData.subspan(offset, count))) { + auto[glyph, pos, rect] = vertexData; + auto[l, t, r, b] = rect; + auto[fx, fy] = pos + originInDeviceSpace; + auto[al, at, ar, ab] = glyph.grGlyph->fAtlasLocator.getUVs(0); + if (clip == nullptr) { + SkScalar dx = SkScalarRoundToScalar(fx), + dy = SkScalarRoundToScalar(fy); + auto[dl, dt, dr, db] = SkRect::MakeLTRB(l + dx, t + dy, r + dx, b + dy); + quad[0] = {{dl, dt}, color, {al, at}}; // L,T + quad[1] = {{dl, db}, color, {al, ab}}; // L,B + quad[2] = {{dr, dt}, color, {ar, at}}; // R,T + quad[3] = {{dr, db}, color, {ar, ab}}; // R,B + } else { + int dx = SkScalarRoundToInt(fx), + dy = SkScalarRoundToInt(fy); + SkIRect devIRect = SkIRect::MakeLTRB(l + dx, t + dy, r + dx, b + dy); + SkScalar dl, dt, dr, db; + uint16_t tl, tt, tr, tb; + if (!clip->containsNoEmptyCheck(devIRect)) { + if (SkIRect clipped; clipped.intersect(devIRect, *clip)) { + int lD = clipped.left() - devIRect.left(); + int tD = clipped.top() - devIRect.top(); + int rD = clipped.right() - devIRect.right(); + int bD = clipped.bottom() - devIRect.bottom(); + int indexLT, indexRB; + std::tie(dl, dt, dr, db) = ltbr(clipped); + std::tie(tl, tt, indexLT) = + GrDrawOpAtlas::UnpackIndexFromTexCoords(al, at); + std::tie(tr, tb, indexRB) = + GrDrawOpAtlas::UnpackIndexFromTexCoords(ar, ab); + std::tie(tl, tt) = + GrDrawOpAtlas::PackIndexInTexCoords(tl + lD, tt + tD, indexLT); + std::tie(tr, tb) = + GrDrawOpAtlas::PackIndexInTexCoords(tr + rD, tb + bD, indexRB); + } else { + // TODO: omit generating any vertex data for fully clipped glyphs ? + std::tie(dl, dt, dr, db) = std::make_tuple(0, 0, 0, 0); + std::tie(tl, tt, tr, tb) = std::make_tuple(0, 0, 0, 0); + } + + } else { + std::tie(dl, dt, dr, db) = ltbr(devIRect); + std::tie(tl, tt, tr, tb) = std::tie(al, at, ar, ab); + } + quad[0] = {{dl, dt}, color, {tl, tt}}; // L,T + quad[1] = {{dl, db}, color, {tl, tb}}; // L,B + quad[2] = {{dr, dt}, color, {tr, tt}}; // R,T + quad[3] = {{dr, db}, color, {tr, tb}}; // R,B + } + } + }; + + switch (fType) { + case kDirectMask: { + if (clip.isEmpty()) { + if (this->maskFormat() != kARGB_GrMaskFormat) { + using Quad = Mask2DVertex[4]; + SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph); + direct2D((Quad*) vertexDst, nullptr); + } else { + using Quad = ARGB2DVertex[4]; + SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph); + direct2D((Quad*) vertexDst, nullptr); + } + } else { + if (this->maskFormat() != kARGB_GrMaskFormat) { + using Quad = Mask2DVertex[4]; + SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph); + direct2D((Quad*) vertexDst, &clip); + } else { + using Quad = ARGB2DVertex[4]; + SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph); + direct2D((Quad*) vertexDst, &clip); + } + } + break; + } + case kTransformedMask: { + if (!this->hasW()) { + if (this->maskFormat() == GrMaskFormat::kARGB_GrMaskFormat) { + using Quad = ARGB2DVertex[4]; + SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph); + transformed2D((Quad*) vertexDst, 0, 1); + } else { + using Quad = Mask2DVertex[4]; + SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph); + transformed2D((Quad*) vertexDst, 0, 1); + } + } else { + if (this->maskFormat() == GrMaskFormat::kARGB_GrMaskFormat) { + using Quad = ARGB3DVertex[4]; + SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph); + transformed3D((Quad*) vertexDst, 0, 1); + } else { + using Quad = Mask3DVertex[4]; + SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph); + transformed3D((Quad*) vertexDst, 0, 1); + } + } + break; + } + case kTransformedSDFT: { + if (!this->hasW()) { + using Quad = Mask2DVertex[4]; + SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph); + transformed2D((Quad*) vertexDst, SK_DistanceFieldInset, SK_DistanceFieldInset); + } else { + using Quad = Mask3DVertex[4]; + SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph); + transformed3D((Quad*) vertexDst, SK_DistanceFieldInset, SK_DistanceFieldInset); + } + break; + } + case kTransformedPath: + SK_ABORT("Paths don't generate vertex data."); + } +} + +int GrTextBlob::SubRun::glyphCount() const { + return fVertexData.count(); } bool GrTextBlob::SubRun::drawAsDistanceFields() const { return fType == kTransformedSDFT; } @@ -204,8 +279,22 @@ bool GrTextBlob::SubRun::needsPadding() const { return fType == kTransformedPath || fType == kTransformedMask; } +int GrTextBlob::SubRun::atlasPadding() const { + return SkTo<int>(this->needsPadding()); +} + +auto GrTextBlob::SubRun::vertexData() const -> SkSpan<const VertexData> { + return fVertexData; +} + bool GrTextBlob::SubRun::hasW() const { - return fBlob->hasW(fType); + if (fType == kTransformedSDFT || fType == kTransformedMask || fType == kTransformedPath) { + return fBlob->hasPerspective(); + } + + // The viewMatrix is implicitly SkMatrix::I when drawing kDirectMask, because it is not + // used. + return false; } void GrTextBlob::SubRun::prepareGrGlyphs(GrStrikeCache* strikeCache) { @@ -215,114 +304,248 @@ void GrTextBlob::SubRun::prepareGrGlyphs(GrStrikeCache* strikeCache) { fStrike = fStrikeSpec.findOrCreateGrStrike(strikeCache); - for (auto& tmp : fGlyphs) { - tmp.fGrGlyph = fStrike->getGlyph(tmp.fPackedGlyphID); + for (auto& tmp : fVertexData) { + tmp.glyph.grGlyph = fStrike->getGlyph(tmp.glyph.packedGlyphID); } } -void GrTextBlob::SubRun::translateVerticesIfNeeded( - const SkMatrix& drawMatrix, SkPoint drawOrigin) { - SkVector translation; +SkRect GrTextBlob::SubRun::deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const { + SkRect outBounds = fVertexBounds; if (this->needsTransform()) { - // If transform is needed, then the vertices are in source space, calculate the source - // space translation. - translation = drawOrigin - fCurrentOrigin; + // if the glyph needs transformation offset the by the new origin, and map to device space. + outBounds.offset(drawOrigin); + outBounds = drawMatrix.mapRect(outBounds); } else { - // Calculate the translation in source space to a translation in device space. Calculate - // the translation by mapping (0, 0) through both the current matrix, and the draw - // matrix, and taking the difference. - SkMatrix currentMatrix{fCurrentMatrix}; - currentMatrix.preTranslate(fCurrentOrigin.x(), fCurrentOrigin.y()); - SkPoint currentDeviceOrigin{0, 0}; - currentMatrix.mapPoints(¤tDeviceOrigin, 1); - SkMatrix completeDrawMatrix{drawMatrix}; - completeDrawMatrix.preTranslate(drawOrigin.x(), drawOrigin.y()); - SkPoint drawDeviceOrigin{0, 0}; - completeDrawMatrix.mapPoints(&drawDeviceOrigin, 1); - translation = drawDeviceOrigin - currentDeviceOrigin; + SkPoint offset = drawMatrix.mapXY(drawOrigin.x(), drawOrigin.y()); + // The vertex bounds are already {0, 0} based, so just add the new origin offset. + outBounds.offset(offset); + + // Due to floating point numerical inaccuracies, we have to round out here + outBounds.roundOut(); } + return outBounds; +} - if (translation != SkPoint{0, 0}) { - size_t vertexStride = this->vertexStride(); - for (size_t quad = 0; quad < fGlyphs.size(); quad++) { - SkPoint* vertexCursor = reinterpret_cast<SkPoint*>(quadStart(quad)); - for (int i = 0; i < 4; ++i) { - *vertexCursor += translation; - vertexCursor = SkTAddOffset<SkPoint>(vertexCursor, vertexStride); - } - } - fCurrentMatrix = drawMatrix; - fCurrentOrigin = drawOrigin; +GrGlyph* GrTextBlob::SubRun::grGlyph(int i) const { + return fVertexData[i].glyph.grGlyph; +} + +void GrTextBlob::SubRun::setUseLCDText(bool useLCDText) { fUseLCDText = useLCDText; } +bool GrTextBlob::SubRun::hasUseLCDText() const { return fUseLCDText; } +void GrTextBlob::SubRun::setAntiAliased(bool antiAliased) { fAntiAliased = antiAliased; } +bool GrTextBlob::SubRun::isAntiAliased() const { return fAntiAliased; } +const SkStrikeSpec& GrTextBlob::SubRun::strikeSpec() const { return fStrikeSpec; } + +auto GrTextBlob::SubRun::MakePaths( + const SkZip<SkGlyphVariant, SkPoint>& drawables, + const SkFont& runFont, + const SkStrikeSpec& strikeSpec, + GrTextBlob* blob, + SkArenaAlloc* alloc) -> SubRun* { + SubRun* subRun = alloc->make<SubRun>(blob, strikeSpec); + subRun->setAntiAliased(runFont.hasSomeAntiAliasing()); + for (auto [variant, pos] : drawables) { + subRun->fPaths.emplace_back(*variant.path(), pos); } + return subRun; +}; + +auto GrTextBlob::SubRun::MakeSDFT( + const SkZip<SkGlyphVariant, SkPoint>& drawables, + const SkFont& runFont, + const SkStrikeSpec& strikeSpec, + GrTextBlob* blob, + SkArenaAlloc* alloc) -> SubRun* { + SubRun* subRun = SubRun::InitForAtlas( + kTransformedSDFT, drawables, strikeSpec, kA8_GrMaskFormat, blob, alloc); + subRun->setUseLCDText(runFont.getEdging() == SkFont::Edging::kSubpixelAntiAlias); + subRun->setAntiAliased(runFont.hasSomeAntiAliasing()); + return subRun; +} + +auto GrTextBlob::SubRun::MakeDirectMask( + const SkZip<SkGlyphVariant, SkPoint>& drawables, + const SkStrikeSpec& strikeSpec, + GrMaskFormat format, + GrTextBlob* blob, + SkArenaAlloc* alloc) -> SubRun* { + return SubRun::InitForAtlas(kDirectMask, drawables, strikeSpec, format, blob, alloc); } -void GrTextBlob::SubRun::updateVerticesColorIfNeeded(GrColor newColor) { - if (this->maskFormat() != kARGB_GrMaskFormat && fCurrentColor != newColor) { - size_t vertexStride = this->vertexStride(); - size_t colorOffset = this->colorOffset(); - for (size_t quad = 0; quad < fGlyphs.size(); quad++) { - GrColor* colorCursor = SkTAddOffset<GrColor>(quadStart(quad), colorOffset); - for (int i = 0; i < 4; ++i) { - *colorCursor = newColor; - colorCursor = SkTAddOffset<GrColor>(colorCursor, vertexStride); +auto GrTextBlob::SubRun::MakeTransformedMask( + const SkZip<SkGlyphVariant, SkPoint>& drawables, + const SkStrikeSpec& strikeSpec, + GrMaskFormat format, + GrTextBlob* blob, + SkArenaAlloc* alloc) -> SubRun* { + return SubRun::InitForAtlas(kTransformedMask, drawables, strikeSpec, format, blob, alloc); +} + +void GrTextBlob::SubRun::insertSubRunOpsIntoTarget(GrTextTarget* target, + const SkSurfaceProps& props, + const SkPaint& paint, + const GrClip* clip, + const SkMatrixProvider& deviceMatrix, + SkPoint drawOrigin) { + if (this->drawAsPaths()) { + SkPaint runPaint{paint}; + runPaint.setAntiAlias(this->isAntiAliased()); + // If there are shaders, blurs or styles, the path must be scaled into source + // space independently of the CTM. This allows the CTM to be correct for the + // different effects. + GrStyle style(runPaint); + + bool needsExactCTM = runPaint.getShader() + || style.applies() + || runPaint.getMaskFilter(); + + // Calculate the matrix that maps the path glyphs from their size in the strike to + // the graphics source space. + SkScalar scale = this->fStrikeSpec.strikeToSourceRatio(); + SkMatrix strikeToSource = SkMatrix::Scale(scale, scale); + strikeToSource.postTranslate(drawOrigin.x(), drawOrigin.y()); + if (!needsExactCTM) { + for (const auto& pathPos : this->fPaths) { + const SkPath& path = pathPos.fPath; + const SkPoint pos = pathPos.fOrigin; // Transform the glyph to source space. + SkMatrix pathMatrix = strikeToSource; + pathMatrix.postTranslate(pos.x(), pos.y()); + SkPreConcatMatrixProvider strikeToDevice(deviceMatrix, pathMatrix); + + GrStyledShape shape(path, paint); + target->drawShape(clip, runPaint, strikeToDevice, shape); + } + } else { + // Transform the path to device because the deviceMatrix must be unchanged to + // draw effect, filter or shader paths. + for (const auto& pathPos : this->fPaths) { + const SkPath& path = pathPos.fPath; + const SkPoint pos = pathPos.fOrigin; + // Transform the glyph to source space. + SkMatrix pathMatrix = strikeToSource; + pathMatrix.postTranslate(pos.x(), pos.y()); + + SkPath deviceOutline; + path.transform(pathMatrix, &deviceOutline); + deviceOutline.setIsVolatile(true); + GrStyledShape shape(deviceOutline, paint); + target->drawShape(clip, runPaint, deviceMatrix, shape); } } - this->fCurrentColor = newColor; + } else { + int glyphCount = this->glyphCount(); + if (0 == glyphCount) { + return; + } + + bool skipClip = false; + SkIRect clipRect = SkIRect::MakeEmpty(); + SkRect rtBounds = SkRect::MakeWH(target->width(), target->height()); + SkRRect clipRRect = SkRRect::MakeRect(rtBounds); + GrAA aa; + // We can clip geometrically if we're not using SDFs or transformed glyphs, + // and we have an axis-aligned rectangular non-AA clip + if (!this->drawAsDistanceFields() && + !this->needsTransform() && + (!clip || (clip->isRRect(&clipRRect, &aa) && + clipRRect.isRect() && GrAA::kNo == aa))) { + // We only need to do clipping work if the subrun isn't contained by the clip + SkRect subRunBounds = this->deviceRect(deviceMatrix.localToDevice(), drawOrigin); + if (!clipRRect.getBounds().contains(subRunBounds)) { + // If the subrun is completely outside, don't add an op for it + if (!clipRRect.getBounds().intersects(subRunBounds)) { + return; + } else { + clipRRect.getBounds().round(&clipRect); + } + } + skipClip = true; + } + + auto op = this->makeOp(deviceMatrix, drawOrigin, clipRect, paint, props, target); + if (op != nullptr) { + target->addDrawOp(skipClip ? nullptr : clip, std::move(op)); + } } } -void GrTextBlob::SubRun::updateTexCoords(int begin, int end) { - SkASSERT(this->isPrepared()); - - const size_t vertexStride = this->vertexStride(); - const size_t texCoordOffset = this->texCoordOffset(); - char* vertex = this->quadStart(begin); - uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset); - for (int i = begin; i < end; i++) { - GrGlyph* glyph = this->fGlyphs[i].fGrGlyph; - SkASSERT(glyph != nullptr); - - int pad = this->drawAsDistanceFields() ? SK_DistanceFieldInset - : (this->needsPadding() ? 1 : 0); - std::array<uint16_t, 4> uvs = glyph->fAtlasLocator.getUVs(pad); - - textureCoords[0] = uvs[0]; - textureCoords[1] = uvs[1]; - textureCoords = SkTAddOffset<uint16_t>(textureCoords, vertexStride); - textureCoords[0] = uvs[0]; - textureCoords[1] = uvs[3]; - textureCoords = SkTAddOffset<uint16_t>(textureCoords, vertexStride); - textureCoords[0] = uvs[2]; - textureCoords[1] = uvs[1]; - textureCoords = SkTAddOffset<uint16_t>(textureCoords, vertexStride); - textureCoords[0] = uvs[2]; - textureCoords[1] = uvs[3]; - textureCoords = SkTAddOffset<uint16_t>(textureCoords, vertexStride); +SkPMColor4f generate_filtered_color(const SkPaint& paint, const GrColorInfo& colorInfo) { + SkColor4f c = paint.getColor4f(); + if (auto* xform = colorInfo.colorSpaceXformFromSRGB()) { + c = xform->apply(c); + } + if (auto* cf = paint.getColorFilter()) { + c = cf->filterColor4f(c, colorInfo.colorSpace(), colorInfo.colorSpace()); } + return c.premul(); } -SkRect GrTextBlob::SubRun::deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const { - SkRect outBounds = fVertexBounds; - if (this->needsTransform()) { - // if the glyph needs transformation offset the by the new origin, and map to device space. - outBounds.offset(drawOrigin); - outBounds = drawMatrix.mapRect(outBounds); - } else { - SkPoint offset = drawMatrix.mapXY(drawOrigin.x(), drawOrigin.y()); - // The vertex bounds are already {0, 0} based, so just add the new origin offset. - outBounds.offset(offset); +std::unique_ptr<GrAtlasTextOp> GrTextBlob::SubRun::makeOp(const SkMatrixProvider& matrixProvider, + SkPoint drawOrigin, + const SkIRect& clipRect, + const SkPaint& paint, + const SkSurfaceProps& props, + GrTextTarget* target) { + GrPaint grPaint; + target->makeGrPaint(this->maskFormat(), paint, matrixProvider, &grPaint); + const GrColorInfo& colorInfo = target->colorInfo(); + // This is the color the op will use to draw. + SkPMColor4f drawingColor = generate_filtered_color(paint, colorInfo); - // Due to floating point numerical inaccuracies, we have to round out here - outBounds.roundOut(); + if (this->drawAsDistanceFields()) { + // TODO: Can we be even smarter based on the dest transfer function? + return GrAtlasTextOp::MakeDistanceField(target->getContext(), + std::move(grPaint), + this, + matrixProvider.localToDevice(), + drawOrigin, + clipRect, + drawingColor, + target->colorInfo().isLinearlyBlended(), + SkPaintPriv::ComputeLuminanceColor(paint), + props); + } else { + return GrAtlasTextOp::MakeBitmap(target->getContext(), + std::move(grPaint), + this, + matrixProvider.localToDevice(), + drawOrigin, + clipRect, + drawingColor); } - return outBounds; } -void GrTextBlob::SubRun::setUseLCDText(bool useLCDText) { fFlags.useLCDText = useLCDText; } -bool GrTextBlob::SubRun::hasUseLCDText() const { return fFlags.useLCDText; } -void GrTextBlob::SubRun::setAntiAliased(bool antiAliased) { fFlags.antiAliased = antiAliased; } -bool GrTextBlob::SubRun::isAntiAliased() const { return fFlags.antiAliased; } -const SkStrikeSpec& GrTextBlob::SubRun::strikeSpec() const { return fStrikeSpec; } +auto GrTextBlob::SubRun::InitForAtlas(SubRunType type, + const SkZip<SkGlyphVariant, SkPoint>& drawables, + const SkStrikeSpec& strikeSpec, + GrMaskFormat format, + GrTextBlob* blob, + SkArenaAlloc* alloc) -> SubRun* { + size_t vertexCount = drawables.size(); + using Data = VertexData; + SkRect bounds = SkRectPriv::MakeLargestInverted(); + auto initializer = [&, strikeToSource=strikeSpec.strikeToSourceRatio()](size_t i) { + auto [variant, pos] = drawables[i]; + SkGlyph* skGlyph = variant; + int16_t l = skGlyph->left(); + int16_t t = skGlyph->top(); + int16_t r = l + skGlyph->width(); + int16_t b = t + skGlyph->height(); + SkPoint lt = SkPoint::Make(l, t) * strikeToSource + pos, + rb = SkPoint::Make(r, b) * strikeToSource + pos; + + bounds.joinPossiblyEmptyRect(SkRect::MakeLTRB(lt.x(), lt.y(), rb.x(), rb.y())); + return Data{{skGlyph->getPackedID()}, pos, {l, t, r, b}}; + }; + + SkSpan<Data> vertexData{ + alloc->makeInitializedArray<Data>(vertexCount, initializer), vertexCount}; + + SubRun* subRun = alloc->make<SubRun>(type, blob, strikeSpec, format, bounds, vertexData); + + return subRun; +} + // -- GrTextBlob ----------------------------------------------------------------------------------- void GrTextBlob::operator delete(void* p) { ::operator delete(p); } @@ -331,33 +554,12 @@ void* GrTextBlob::operator new(size_t, void* p) { return p; } GrTextBlob::~GrTextBlob() = default; -sk_sp<GrTextBlob> GrTextBlob::Make(const SkGlyphRunList& glyphRunList, - const SkMatrix& drawMatrix, - GrColor color, - bool forceWForDistanceFields) { - - static_assert(sizeof(ARGB2DVertex) <= sizeof(Mask2DVertex)); - static_assert(alignof(ARGB2DVertex) <= alignof(Mask2DVertex)); - size_t quadSize = sizeof(Mask2DVertex) * kVerticesPerGlyph; - if (drawMatrix.hasPerspective() || forceWForDistanceFields) { - static_assert(sizeof(ARGB3DVertex) <= sizeof(SDFT3DVertex)); - static_assert(alignof(ARGB3DVertex) <= alignof(SDFT3DVertex)); - quadSize = sizeof(SDFT3DVertex) * kVerticesPerGlyph; - } - - // We can use the alignment of SDFT3DVertex as a proxy for all Vertex alignments. - static_assert(alignof(SDFT3DVertex) >= alignof(Mask2DVertex)); - // Assume there is no padding needed between glyph pointers and vertices. - static_assert(alignof(GrGlyph*) >= alignof(SDFT3DVertex)); - - // In the arena, the layout is GrGlyph*... | SDFT3DVertex... | SubRun, so there is no padding - // between GrGlyph* and SDFT3DVertex, but padding is needed between the Mask2DVertex array - // and the SubRun. - size_t vertexToSubRunPadding = alignof(SDFT3DVertex) - alignof(SubRun); - size_t arenaSize = - sizeof(GrGlyph*) * glyphRunList.totalGlyphCount() - + quadSize * glyphRunList.totalGlyphCount() - + glyphRunList.runCount() * (sizeof(SubRun) + vertexToSubRunPadding); +sk_sp<GrTextBlob> GrTextBlob::Make(const SkGlyphRunList& glyphRunList, const SkMatrix& drawMatrix) { + // The difference in alignment from the storage of VertexData to SubRun; + constexpr size_t alignDiff = alignof(SubRun) - alignof(SubRun::VertexData); + constexpr size_t vertexDataToSubRunPadding = alignDiff > 0 ? alignDiff : 0; + size_t arenaSize = sizeof(SubRun::VertexData) * glyphRunList.totalGlyphCount() + + glyphRunList.runCount() * (sizeof(SubRun) + vertexDataToSubRunPadding); size_t allocationSize = sizeof(GrTextBlob) + arenaSize; @@ -365,8 +567,7 @@ sk_sp<GrTextBlob> GrTextBlob::Make(const SkGlyphRunList& glyphRunList, SkColor initialLuminance = SkPaintPriv::ComputeLuminanceColor(glyphRunList.paint()); sk_sp<GrTextBlob> blob{new (allocation) GrTextBlob{ - arenaSize, drawMatrix, glyphRunList.origin(), - color, initialLuminance, forceWForDistanceFields}}; + arenaSize, drawMatrix, glyphRunList.origin(), initialLuminance}}; return blob; } @@ -400,42 +601,31 @@ void GrTextBlob::setMinAndMaxScale(SkScalar scaledMin, SkScalar scaledMax) { fMinMaxScale = std::min(scaledMax, fMinMaxScale); } -size_t GrTextBlob::GetVertexStride(GrMaskFormat maskFormat, bool hasWCoord) { - switch (maskFormat) { - case kA8_GrMaskFormat: - return hasWCoord ? sizeof(SDFT3DVertex) : sizeof(Mask2DVertex); - case kARGB_GrMaskFormat: - return hasWCoord ? sizeof(ARGB3DVertex) : sizeof(ARGB2DVertex); - default: - SkASSERT(!hasWCoord); - return sizeof(Mask2DVertex); - } -} - -bool GrTextBlob::mustRegenerate(const SkPaint& paint, bool anyRunHasSubpixelPosition, - const SkMaskFilterBase::BlurRec& blurRec, - const SkMatrix& drawMatrix, SkPoint drawOrigin) { +bool GrTextBlob::canReuse(const SkPaint& paint, + const SkMaskFilterBase::BlurRec& blurRec, + const SkMatrix& drawMatrix, + SkPoint drawOrigin) { // If we have LCD text then our canonical color will be set to transparent, in this case we have // to regenerate the blob on any color change // We use the grPaint to get any color filter effects if (fKey.fCanonicalColor == SK_ColorTRANSPARENT && fInitialLuminance != SkPaintPriv::ComputeLuminanceColor(paint)) { - return true; + return false; } if (fInitialMatrix.hasPerspective() != drawMatrix.hasPerspective()) { - return true; + return false; } /** This could be relaxed for blobs with only distance field glyphs. */ if (fInitialMatrix.hasPerspective() && !SkMatrixPriv::CheapEqual(fInitialMatrix, drawMatrix)) { - return true; + return false; } // We only cache one masked version if (fKey.fHasBlur && (fBlurRec.fSigma != blurRec.fSigma || fBlurRec.fStyle != blurRec.fStyle)) { - return true; + return false; } // Similarly, we only cache one version for each style @@ -443,15 +633,14 @@ bool GrTextBlob::mustRegenerate(const SkPaint& paint, bool anyRunHasSubpixelPosi (fStrokeInfo.fFrameWidth != paint.getStrokeWidth() || fStrokeInfo.fMiterLimit != paint.getStrokeMiter() || fStrokeInfo.fJoin != paint.getStrokeJoin())) { - return true; + return false; } // Mixed blobs must be regenerated. We could probably figure out a way to do integer scrolls // for mixed blobs if this becomes an issue. if (this->hasBitmap() && this->hasDistanceField()) { // Identical view matrices and we can reuse in all cases - return !(SkMatrixPriv::CheapEqual(fInitialMatrix, drawMatrix) && - drawOrigin == fInitialOrigin); + return SkMatrixPriv::CheapEqual(fInitialMatrix, drawMatrix) && drawOrigin == fInitialOrigin; } if (this->hasBitmap()) { @@ -459,7 +648,7 @@ bool GrTextBlob::mustRegenerate(const SkPaint& paint, bool anyRunHasSubpixelPosi fInitialMatrix.getScaleY() != drawMatrix.getScaleY() || fInitialMatrix.getSkewX() != drawMatrix.getSkewX() || fInitialMatrix.getSkewY() != drawMatrix.getSkewY()) { - return true; + return false; } // TODO(herb): this is not needed for full pixel glyph choice, but is needed to adjust @@ -481,7 +670,7 @@ bool GrTextBlob::mustRegenerate(const SkPaint& paint, bool anyRunHasSubpixelPosi SkPoint translation = drawDeviceOrigin - initialDeviceOrigin; if (!SkScalarIsInt(translation.x()) || !SkScalarIsInt(translation.y())) { - return true; + return false; } } else if (this->hasDistanceField()) { // A scale outside of [blob.fMaxMinScale, blob.fMinMaxScale] would result in a different @@ -490,170 +679,31 @@ bool GrTextBlob::mustRegenerate(const SkPaint& paint, bool anyRunHasSubpixelPosi SkScalar oldMaxScale = fInitialMatrix.getMaxScale(); SkScalar scaleAdjust = newMaxScale / oldMaxScale; if (scaleAdjust < fMaxMinScale || scaleAdjust > fMinMaxScale) { - return true; + return false; } } - // It is possible that a blob has neither distanceField nor bitmaptext. This is in the case - // when all of the runs inside the blob are drawn as paths. In this case, we always regenerate - // the blob anyways at flush time, so no need to regenerate explicitly - return false; + // If the blob is all paths, there is no reason to regenerate. + return true; } -void GrTextBlob::addOp(GrTextTarget* target, - const SkSurfaceProps& props, - const SkPaint& paint, - const SkPMColor4f& filteredColor, - const GrClip& clip, - const SkMatrixProvider& deviceMatrix, - SkPoint drawOrigin) { +void GrTextBlob::insertOpsIntoTarget(GrTextTarget* target, + const SkSurfaceProps& props, + const SkPaint& paint, + const GrClip* clip, + const SkMatrixProvider& deviceMatrix, + SkPoint drawOrigin) { for (SubRun* subRun = fFirstSubRun; subRun != nullptr; subRun = subRun->fNextSubRun) { - if (subRun->drawAsPaths()) { - SkPaint runPaint{paint}; - runPaint.setAntiAlias(subRun->isAntiAliased()); - // If there are shaders, blurs or styles, the path must be scaled into source - // space independently of the CTM. This allows the CTM to be correct for the - // different effects. - GrStyle style(runPaint); - - bool needsExactCTM = runPaint.getShader() - || style.applies() - || runPaint.getMaskFilter(); - - // Calculate the matrix that maps the path glyphs from their size in the strike to - // the graphics source space. - SkMatrix strikeToSource = SkMatrix::MakeScale( - subRun->fStrikeSpec.strikeToSourceRatio()); - strikeToSource.postTranslate(drawOrigin.x(), drawOrigin.y()); - if (!needsExactCTM) { - for (const auto& pathPos : subRun->fPaths) { - const SkPath& path = pathPos.fPath; - const SkPoint pos = pathPos.fOrigin; // Transform the glyph to source space. - SkMatrix pathMatrix = strikeToSource; - pathMatrix.postTranslate(pos.x(), pos.y()); - SkPreConcatMatrixProvider strikeToDevice(deviceMatrix, pathMatrix); - - GrStyledShape shape(path, paint); - target->drawShape(clip, runPaint, strikeToDevice, shape); - } - } else { - // Transform the path to device because the deviceMatrix must be unchanged to - // draw effect, filter or shader paths. - for (const auto& pathPos : subRun->fPaths) { - const SkPath& path = pathPos.fPath; - const SkPoint pos = pathPos.fOrigin; - // Transform the glyph to source space. - SkMatrix pathMatrix = strikeToSource; - pathMatrix.postTranslate(pos.x(), pos.y()); - - SkPath deviceOutline; - path.transform(pathMatrix, &deviceOutline); - deviceOutline.setIsVolatile(true); - GrStyledShape shape(deviceOutline, paint); - target->drawShape(clip, runPaint, deviceMatrix, shape); - } - } - } else { - int glyphCount = subRun->fGlyphs.count(); - if (0 == glyphCount) { - continue; - } - - bool skipClip = false; - SkIRect clipRect = SkIRect::MakeEmpty(); - SkRect rtBounds = SkRect::MakeWH(target->width(), target->height()); - SkRRect clipRRect; - GrAA aa; - // We can clip geometrically if we're not using SDFs or transformed glyphs, - // and we have an axis-aligned rectangular non-AA clip - if (!subRun->drawAsDistanceFields() && - !subRun->needsTransform() && - clip.isRRect(rtBounds, &clipRRect, &aa) && - clipRRect.isRect() && GrAA::kNo == aa) { - skipClip = true; - // We only need to do clipping work if the subrun isn't contained by the clip - SkRect subRunBounds = subRun->deviceRect(deviceMatrix.localToDevice(), drawOrigin); - if (!clipRRect.getBounds().contains(subRunBounds)) { - // If the subrun is completely outside, don't add an op for it - if (!clipRRect.getBounds().intersects(subRunBounds)) { - continue; - } else { - clipRRect.getBounds().round(&clipRect); - } - } - } - - auto op = this->makeOp(*subRun, deviceMatrix, drawOrigin, clipRect, - paint, filteredColor, props, target); - if (op) { - if (skipClip) { - target->addDrawOp(GrNoClip(), std::move(op)); - } - else { - target->addDrawOp(clip, std::move(op)); - } - } - } + subRun->insertSubRunOpsIntoTarget(target, props, paint, clip, deviceMatrix, drawOrigin); } } const GrTextBlob::Key& GrTextBlob::key() const { return fKey; } size_t GrTextBlob::size() const { return fSize; } -std::unique_ptr<GrDrawOp> GrTextBlob::test_makeOp(const SkMatrixProvider& matrixProvider, - SkPoint drawOrigin, - const SkPaint& paint, - const SkPMColor4f& filteredColor, - const SkSurfaceProps& props, - GrTextTarget* target) { - SubRun* info = fFirstSubRun; - SkIRect emptyRect = SkIRect::MakeEmpty(); - return this->makeOp(*info, matrixProvider, drawOrigin, emptyRect, paint, - filteredColor, props, target); -} - -bool GrTextBlob::hasW(GrTextBlob::SubRunType type) const { - if (type == kTransformedSDFT) { - return this->hasPerspective() || fForceWForDistanceFields; - } else if (type == kTransformedMask || type == kTransformedPath) { - return this->hasPerspective(); - } - - // The viewMatrix is implicitly SkMatrix::I when drawing kDirectMask, because it is not - // used. - return false; -} - -GrTextBlob::SubRun* GrTextBlob::makeSubRun(SubRunType type, - const SkZip<SkGlyphVariant, SkPoint>& drawables, - const SkStrikeSpec& strikeSpec, - GrMaskFormat format) { - SkSpan<SubRun::PackedGlyphIDorGrGlyph> glyphs{ - fAlloc.makeArrayDefault<SubRun::PackedGlyphIDorGrGlyph>(drawables.size()), drawables.size()}; - bool hasW = this->hasW(type); - - SkASSERT(!fInitialMatrix.hasPerspective() || hasW); - - size_t vertexDataSize = drawables.size() * GetVertexStride(format, hasW) * kVerticesPerGlyph; - SkSpan<char> vertexData{fAlloc.makeArrayDefault<char>(vertexDataSize), vertexDataSize}; - - SubRun* subRun = fAlloc.make<SubRun>(type, this, strikeSpec, format, glyphs, vertexData); - - subRun->appendGlyphs(drawables); - - return subRun; -} - -void GrTextBlob::addSingleMaskFormat( - SubRunType type, - const SkZip<SkGlyphVariant, SkPoint>& drawables, - const SkStrikeSpec& strikeSpec, - GrMaskFormat format) { - this->makeSubRun(type, drawables, strikeSpec, format); -} - +template<typename AddSingleMaskFormat> void GrTextBlob::addMultiMaskFormat( - SubRunType type, + AddSingleMaskFormat addSingle, const SkZip<SkGlyphVariant, SkPoint>& drawables, const SkStrikeSpec& strikeSpec) { this->setHasBitmap(); @@ -668,39 +718,24 @@ void GrTextBlob::addMultiMaskFormat( GrMaskFormat nextFormat = GrGlyph::FormatFromSkGlyph(glyph->maskFormat()); if (format != nextFormat) { auto sameFormat = drawables.subspan(startIndex, i - startIndex); - this->addSingleMaskFormat(type, sameFormat, strikeSpec, format); + SubRun* subRun = addSingle(sameFormat, strikeSpec, format, this, &fAlloc); + this->insertSubRun(subRun); format = nextFormat; startIndex = i; } } auto sameFormat = drawables.last(drawables.size() - startIndex); - this->addSingleMaskFormat(type, sameFormat, strikeSpec, format); -} - -void GrTextBlob::addSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables, - const SkStrikeSpec& strikeSpec, - const SkFont& runFont, - SkScalar minScale, - SkScalar maxScale) { - this->setHasDistanceField(); - this->setMinAndMaxScale(minScale, maxScale); - - SubRun* subRun = this->makeSubRun(kTransformedSDFT, drawables, strikeSpec, kA8_GrMaskFormat); - subRun->setUseLCDText(runFont.getEdging() == SkFont::Edging::kSubpixelAntiAlias); - subRun->setAntiAliased(runFont.hasSomeAntiAliasing()); + SubRun* subRun = addSingle(sameFormat, strikeSpec, format, this, &fAlloc); + this->insertSubRun(subRun); } GrTextBlob::GrTextBlob(size_t allocSize, const SkMatrix& drawMatrix, SkPoint origin, - GrColor color, - SkColor initialLuminance, - bool forceWForDistanceFields) + SkColor initialLuminance) : fSize{allocSize} , fInitialMatrix{drawMatrix} , fInitialOrigin{origin} - , fForceWForDistanceFields{forceWForDistanceFields} - , fColor{color} , fInitialLuminance{initialLuminance} , fAlloc{SkTAddOffset<char>(this, sizeof(GrTextBlob)), allocSize, allocSize/2} { } @@ -714,53 +749,18 @@ void GrTextBlob::insertSubRun(SubRun* subRun) { } } -std::unique_ptr<GrAtlasTextOp> GrTextBlob::makeOp(SubRun& info, - const SkMatrixProvider& matrixProvider, - SkPoint drawOrigin, - const SkIRect& clipRect, - const SkPaint& paint, - const SkPMColor4f& filteredColor, - const SkSurfaceProps& props, - GrTextTarget* target) { - GrPaint grPaint; - target->makeGrPaint(info.maskFormat(), paint, matrixProvider, &grPaint); - if (info.drawAsDistanceFields()) { - // TODO: Can we be even smarter based on the dest transfer function? - return GrAtlasTextOp::MakeDistanceField(target->getContext(), - std::move(grPaint), - &info, - matrixProvider.localToDevice(), - drawOrigin, - clipRect, - filteredColor, - target->colorInfo().isLinearlyBlended(), - SkPaintPriv::ComputeLuminanceColor(paint), - props); - } else { - return GrAtlasTextOp::MakeBitmap(target->getContext(), - std::move(grPaint), - &info, - matrixProvider.localToDevice(), - drawOrigin, - clipRect, - filteredColor); - } -} - void GrTextBlob::processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables, const SkStrikeSpec& strikeSpec) { - this->addMultiMaskFormat(kDirectMask, drawables, strikeSpec); + + this->addMultiMaskFormat(SubRun::MakeDirectMask, drawables, strikeSpec); } void GrTextBlob::processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables, const SkFont& runFont, const SkStrikeSpec& strikeSpec) { this->setHasBitmap(); - SubRun* subRun = fAlloc.make<SubRun>(this, strikeSpec); - subRun->setAntiAliased(runFont.hasSomeAntiAliasing()); - for (auto [variant, pos] : drawables) { - subRun->fPaths.emplace_back(*variant.path(), pos); - } + SubRun* subRun = SubRun::MakePaths(drawables, runFont, strikeSpec, this, &fAlloc); + this->insertSubRun(subRun); } void GrTextBlob::processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables, @@ -768,158 +768,18 @@ void GrTextBlob::processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawabl const SkFont& runFont, SkScalar minScale, SkScalar maxScale) { - this->addSDFT(drawables, strikeSpec, runFont, minScale, maxScale); + this->setHasDistanceField(); + this->setMinAndMaxScale(minScale, maxScale); + SubRun* subRun = SubRun::MakeSDFT(drawables, runFont, strikeSpec, this, &fAlloc); + this->insertSubRun(subRun); } void GrTextBlob::processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables, const SkStrikeSpec& strikeSpec) { - this->addMultiMaskFormat(kTransformedMask, drawables, strikeSpec); -} - -// -- Adding a mask to an atlas ---------------------------------------------------------------- - -// expands each bit in a bitmask to 0 or ~0 of type INT_TYPE. Used to expand a BW glyph mask to -// A8, RGB565, or RGBA8888. -template <typename INT_TYPE> -static void expand_bits(INT_TYPE* dst, - const uint8_t* src, - int width, - int height, - int dstRowBytes, - int srcRowBytes) { - for (int i = 0; i < height; ++i) { - int rowWritesLeft = width; - const uint8_t* s = src; - INT_TYPE* d = dst; - while (rowWritesLeft > 0) { - unsigned mask = *s++; - for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) { - *d++ = (mask & (1 << i)) ? (INT_TYPE)(~0UL) : 0; - } - } - dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes); - src += srcRowBytes; - } -} - -static void get_packed_glyph_image( - const SkGlyph& glyph, int dstRB, GrMaskFormat expectedMaskFormat, void* dst) { - const int width = glyph.width(); - const int height = glyph.height(); - const void* src = glyph.image(); - SkASSERT(src != nullptr); - - GrMaskFormat grMaskFormat = GrGlyph::FormatFromSkGlyph(glyph.maskFormat()); - if (grMaskFormat == expectedMaskFormat) { - int srcRB = glyph.rowBytes(); - // Notice this comparison is with the glyphs raw mask format, and not its GrMaskFormat. - if (glyph.maskFormat() != SkMask::kBW_Format) { - if (srcRB != dstRB) { - const int bbp = GrMaskFormatBytesPerPixel(expectedMaskFormat); - for (int y = 0; y < height; y++) { - memcpy(dst, src, width * bbp); - src = (const char*) src + srcRB; - dst = (char*) dst + dstRB; - } - } else { - memcpy(dst, src, dstRB * height); - } - } else { - // Handle 8-bit format by expanding the mask to the expected format. - const uint8_t* bits = reinterpret_cast<const uint8_t*>(src); - switch (expectedMaskFormat) { - case kA8_GrMaskFormat: { - uint8_t* bytes = reinterpret_cast<uint8_t*>(dst); - expand_bits(bytes, bits, width, height, dstRB, srcRB); - break; - } - case kA565_GrMaskFormat: { - uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst); - expand_bits(rgb565, bits, width, height, dstRB, srcRB); - break; - } - default: - SK_ABORT("Invalid GrMaskFormat"); - } - } - } else if (grMaskFormat == kA565_GrMaskFormat && expectedMaskFormat == kARGB_GrMaskFormat) { - // Convert if the glyph uses a 565 mask format since it is using LCD text rendering - // but the expected format is 8888 (will happen on macOS with Metal since that - // combination does not support 565). - static constexpr SkMasks masks{ - {0b1111'1000'0000'0000, 11, 5}, // Red - {0b0000'0111'1110'0000, 5, 6}, // Green - {0b0000'0000'0001'1111, 0, 5}, // Blue - {0, 0, 0} // Alpha - }; - const int a565Bpp = GrMaskFormatBytesPerPixel(kA565_GrMaskFormat); - const int argbBpp = GrMaskFormatBytesPerPixel(kARGB_GrMaskFormat); - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - uint16_t color565 = 0; - memcpy(&color565, src, a565Bpp); - uint32_t colorRGBA = GrColorPackRGBA(masks.getRed(color565), - masks.getGreen(color565), - masks.getBlue(color565), - 0xFF); - memcpy(dst, &colorRGBA, argbBpp); - src = (char*)src + a565Bpp; - dst = (char*)dst + argbBpp; - } - } - } else { - // crbug:510931 - // Retrieving the image from the cache can actually change the mask format. This case is - // very uncommon so for now we just draw a clear box for these glyphs. - const int bpp = GrMaskFormatBytesPerPixel(expectedMaskFormat); - for (int y = 0; y < height; y++) { - sk_bzero(dst, width * bpp); - dst = (char*)dst + dstRB; - } - } + this->addMultiMaskFormat(SubRun::MakeTransformedMask, drawables, strikeSpec); } -// returns true if glyph successfully added to texture atlas, false otherwise. If the glyph's -// mask format has changed, then add_glyph_to_atlas will draw a clear box. This will almost never -// happen. -// TODO we can handle some of these cases if we really want to, but the long term solution is to -// get the actual glyph image itself when we get the glyph metrics. -static GrDrawOpAtlas::ErrorCode add_glyph_to_atlas(const SkGlyph& skGlyph, - GrMaskFormat expectedMaskFormat, - bool needsPadding, - GrResourceProvider* resourceProvider, - GrDeferredUploadTarget* target, - GrAtlasManager* fullAtlasManager, - GrGlyph* grGlyph) { - SkASSERT(grGlyph != nullptr); - SkASSERT(skGlyph.image() != nullptr); - - expectedMaskFormat = fullAtlasManager->resolveMaskFormat(expectedMaskFormat); - int bytesPerPixel = GrMaskFormatBytesPerPixel(expectedMaskFormat); - - SkDEBUGCODE(bool isSDFGlyph = skGlyph.maskFormat() == SkMask::kSDF_Format;) - SkASSERT(!needsPadding || !isSDFGlyph); - - // Add 1 pixel padding around grGlyph if needed. - const int width = needsPadding ? skGlyph.width() + 2 : skGlyph.width(); - const int height = needsPadding ? skGlyph.height() + 2 : skGlyph.height(); - int rowBytes = width * bytesPerPixel; - size_t size = height * rowBytes; - - // Temporary storage for normalizing grGlyph image. - SkAutoSMalloc<1024> storage(size); - void* dataPtr = storage.get(); - if (needsPadding) { - sk_bzero(dataPtr, size); - // Advance in one row and one column. - dataPtr = (char*)(dataPtr) + rowBytes + bytesPerPixel; - } - - get_packed_glyph_image(skGlyph, rowBytes, expectedMaskFormat, dataPtr); - - return fullAtlasManager->addToAtlas(resourceProvider, target, expectedMaskFormat, width, height, - storage.get(), &grGlyph->fAtlasLocator); -} +auto GrTextBlob::firstSubRun() const -> SubRun* { return fFirstSubRun; } // -- GrTextBlob::VertexRegenerator ---------------------------------------------------------------- GrTextBlob::VertexRegenerator::VertexRegenerator(GrResourceProvider* resourceProvider, @@ -935,43 +795,32 @@ std::tuple<bool, int> GrTextBlob::VertexRegenerator::updateTextureCoordinates( const int begin, const int end) { SkASSERT(fSubRun->isPrepared()); - const SkStrikeSpec& strikeSpec = fSubRun->strikeSpec(); - if (!fMetricsAndImages.isValid() || - fMetricsAndImages->descriptor() != strikeSpec.descriptor()) { - fMetricsAndImages.init(strikeSpec); - } + SkBulkGlyphMetricsAndImages metricsAndImages{fSubRun->strikeSpec()}; // Update the atlas information in the GrStrike. - auto code = GrDrawOpAtlas::ErrorCode::kSucceeded; auto tokenTracker = fUploadTarget->tokenTracker(); - int i = begin; - for (; i < end; i++) { - GrGlyph* grGlyph = fSubRun->fGlyphs[i].fGrGlyph; - SkASSERT(grGlyph); + auto vertexData = fSubRun->vertexData().subspan(begin, end - begin); + int glyphsPlacedInAtlas = 0; + for (auto [glyph, pos, rect] : vertexData) { + GrGlyph* grGlyph = glyph.grGlyph; + SkASSERT(grGlyph != nullptr); if (!fFullAtlasManager->hasGlyph(fSubRun->maskFormat(), grGlyph)) { - const SkGlyph& skGlyph = *fMetricsAndImages->glyph(grGlyph->fPackedID); - if (skGlyph.image() == nullptr) { - return {false, 0}; - } - code = add_glyph_to_atlas(skGlyph, fSubRun->maskFormat(), - fSubRun->needsPadding(), fResourceProvider, - fUploadTarget, fFullAtlasManager, grGlyph); + const SkGlyph& skGlyph = *metricsAndImages.glyph(grGlyph->fPackedID); + auto code = fFullAtlasManager->addGlyphToAtlas( + skGlyph, fSubRun->atlasPadding(), grGlyph, fResourceProvider, fUploadTarget); if (code != GrDrawOpAtlas::ErrorCode::kSucceeded) { - break; + return {code != GrDrawOpAtlas::ErrorCode::kError, glyphsPlacedInAtlas}; } } fFullAtlasManager->addGlyphToBulkAndSetUseToken( fSubRun->bulkUseToken(), fSubRun->maskFormat(), grGlyph, tokenTracker->nextDrawToken()); + glyphsPlacedInAtlas++; } - int glyphsPlacedInAtlas = i - begin; - // Update the quads with the new atlas coordinates. - fSubRun->updateTexCoords(begin, begin + glyphsPlacedInAtlas); - - return {code != GrDrawOpAtlas::ErrorCode::kError, glyphsPlacedInAtlas}; + return {true, glyphsPlacedInAtlas}; } std::tuple<bool, int> GrTextBlob::VertexRegenerator::regenerate(int begin, int end) { @@ -984,15 +833,16 @@ std::tuple<bool, int> GrTextBlob::VertexRegenerator::regenerate(int begin, int e auto [success, glyphsPlacedInAtlas] = this->updateTextureCoordinates(begin, end); // Update atlas generation if there are no more glyphs to put in the atlas. - if (success && begin + glyphsPlacedInAtlas == fSubRun->fGlyphs.count()) { + if (success && begin + glyphsPlacedInAtlas == fSubRun->glyphCount()) { // Need to get the freshest value of the atlas' generation because // updateTextureCoordinates may have changed it. fSubRun->fAtlasGeneration = fFullAtlasManager->atlasGeneration(fSubRun->maskFormat()); } + return {success, glyphsPlacedInAtlas}; } else { // The atlas hasn't changed, so our texture coordinates are still valid. - if (end == fSubRun->fGlyphs.count()) { + if (end == fSubRun->glyphCount()) { // The atlas hasn't changed and the texture coordinates are all still valid. Update // all the plots used to the new use token. fFullAtlasManager->setUseTokenBulk(*fSubRun->bulkUseToken(), diff --git a/chromium/third_party/skia/src/gpu/text/GrTextBlob.h b/chromium/third_party/skia/src/gpu/text/GrTextBlob.h index 98f813a258c..ab04255c2da 100644 --- a/chromium/third_party/skia/src/gpu/text/GrTextBlob.h +++ b/chromium/third_party/skia/src/gpu/text/GrTextBlob.h @@ -27,7 +27,7 @@ class GrAtlasTextOp; class GrDeferredUploadTarget; class GrGlyph; class GrStrikeCache; -class GrTextContext; +class GrTextTarget; class SkMatrixProvider; class SkSurfaceProps; @@ -61,13 +61,6 @@ public: class SubRun; class VertexRegenerator; - enum SubRunType { - kDirectMask, - kTransformedMask, - kTransformedPath, - kTransformedSDFT - }; - struct Key { Key(); uint32_t fUniqueID; @@ -105,9 +98,7 @@ public: // Make an empty GrTextBlob, with all the invariants set to make the right decisions when // adding SubRuns. static sk_sp<GrTextBlob> Make(const SkGlyphRunList& glyphRunList, - const SkMatrix& drawMatrix, - GrColor color, - bool forceWForDistanceFields); + const SkMatrix& drawMatrix); // Key manipulation functions void setupKey(const GrTextBlob::Key& key, @@ -124,78 +115,30 @@ public: void setHasBitmap(); void setMinAndMaxScale(SkScalar scaledMin, SkScalar scaledMax); - static size_t GetVertexStride(GrMaskFormat maskFormat, bool hasWCoord); + bool canReuse(const SkPaint& paint, const SkMaskFilterBase::BlurRec& blurRec, + const SkMatrix& drawMatrix, SkPoint drawOrigin); - bool mustRegenerate(const SkPaint&, bool, const SkMaskFilterBase::BlurRec& blurRec, - const SkMatrix& drawMatrix, SkPoint drawOrigin); - - void addOp(GrTextTarget* target, - const SkSurfaceProps& props, - const SkPaint& paint, - const SkPMColor4f& filteredColor, - const GrClip& clip, - const SkMatrixProvider& deviceMatrix, - SkPoint drawOrigin); - - - // Normal text mask, SDFT, or color. - struct Mask2DVertex { - SkPoint devicePos; - GrColor color; - SkIPoint16 atlasPos; - }; - struct ARGB2DVertex { - SkPoint devicePos; - SkIPoint16 atlasPos; - }; - - // Perspective SDFT or SDFT forced to 3D or perspective color. - struct SDFT3DVertex { - SkPoint3 devicePos; - GrColor color; - SkIPoint16 atlasPos; - }; - struct ARGB3DVertex { - SkPoint3 devicePos; - SkIPoint16 atlasPos; - }; + void insertOpsIntoTarget(GrTextTarget* target, + const SkSurfaceProps& props, + const SkPaint& paint, + const GrClip* clip, + const SkMatrixProvider& deviceMatrix, + SkPoint drawOrigin); static const int kVerticesPerGlyph = 4; const Key& key() const; size_t size() const; - // Internal test methods - std::unique_ptr<GrDrawOp> test_makeOp(const SkMatrixProvider& matrixProvider, - SkPoint drawOrigin, - const SkPaint& paint, - const SkPMColor4f& filteredColor, - const SkSurfaceProps&, - GrTextTarget*); - - bool hasW(SubRunType type) const; - - SubRun* makeSubRun(SubRunType type, - const SkZip<SkGlyphVariant, SkPoint>& drawables, - const SkStrikeSpec& strikeSpec, - GrMaskFormat format); - - void addSingleMaskFormat( - SubRunType type, - const SkZip<SkGlyphVariant, SkPoint>& drawables, - const SkStrikeSpec& strikeSpec, - GrMaskFormat format); - + template<typename AddSingleMaskFormat> void addMultiMaskFormat( - SubRunType type, + AddSingleMaskFormat addSingle, const SkZip<SkGlyphVariant, SkPoint>& drawables, const SkStrikeSpec& strikeSpec); - void addSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables, - const SkStrikeSpec& strikeSpec, - const SkFont& runFont, - SkScalar minScale, - SkScalar maxScale); + SubRun* firstSubRun() const; + + bool forceWForDistanceFields() const; private: enum TextType { @@ -212,21 +155,10 @@ private: GrTextBlob(size_t allocSize, const SkMatrix& drawMatrix, SkPoint origin, - GrColor color, - SkColor initialLuminance, - bool forceWForDistanceFields); + SkColor initialLuminance); void insertSubRun(SubRun* subRun); - std::unique_ptr<GrAtlasTextOp> makeOp(SubRun& info, - const SkMatrixProvider& matrixProvider, - SkPoint drawOrigin, - const SkIRect& clipRect, - const SkPaint& paint, - const SkPMColor4f& filteredColor, - const SkSurfaceProps&, - GrTextTarget*); - // Methods to satisfy SkGlyphRunPainterInterface void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables, const SkStrikeSpec& strikeSpec) override; @@ -254,11 +186,6 @@ private: // blob. const SkPoint fInitialOrigin; - // From the distance field options to force distance fields to have a W coordinate. - const bool fForceWForDistanceFields; - - // The color of the text to draw for solid colors. - const GrColor fColor; const SkColor fInitialLuminance; SkMaskFilterBase::BlurRec fBlurRec; @@ -306,7 +233,6 @@ private: GrResourceProvider* fResourceProvider; GrDeferredUploadTarget* fUploadTarget; GrAtlasManager* fFullAtlasManager; - SkTLazy<SkBulkGlyphMetricsAndImages> fMetricsAndImages; SubRun* fSubRun; }; @@ -314,15 +240,24 @@ private: // Hold data to draw the different types of sub run. SubRuns are produced knowing all the // glyphs that are included in them. class GrTextBlob::SubRun { + enum SubRunType { + kDirectMask, + kTransformedMask, + kTransformedPath, + kTransformedSDFT + }; + public: - // Within a glyph-based subRun, the glyphs are initially recorded as SkPackedGlyphs. At - // flush time they are then converted to GrGlyph's (via the GrTextStrike). Once converted - // they are never converted back. - union PackedGlyphIDorGrGlyph { - PackedGlyphIDorGrGlyph() {} - - SkPackedGlyphID fPackedGlyphID; - GrGlyph* fGrGlyph; + struct VertexData { + union { + // Initially, filled with packed id, but changed to GrGlyph* in the onPrepare stage. + SkPackedGlyphID packedGlyphID; + GrGlyph* grGlyph; + } glyph; + const SkPoint pos; + // The rectangle of the glyphs in strike space. But, for kDirectMask this also implies a + // device space rect. + GrIRect16 rect; }; // SubRun for masks @@ -330,79 +265,144 @@ public: GrTextBlob* textBlob, const SkStrikeSpec& strikeSpec, GrMaskFormat format, - const SkSpan<PackedGlyphIDorGrGlyph>& glyphs, - const SkSpan<char>& vertexData); + SkRect vertexBounds, + const SkSpan<VertexData>& vertexData); // SubRun for paths SubRun(GrTextBlob* textBlob, const SkStrikeSpec& strikeSpec); - void appendGlyphs(const SkZip<SkGlyphVariant, SkPoint>& drawables); - // TODO when this object is more internal, drop the privacy void resetBulkUseToken(); GrDrawOpAtlas::BulkUseTokenUpdater* bulkUseToken(); - GrTextStrike* strike() const; GrMaskFormat maskFormat() const; size_t vertexStride() const; - size_t colorOffset() const; - size_t texCoordOffset() const; - char* quadStart(size_t index) const; size_t quadOffset(size_t index) const; + void fillVertexData( + void* vertexDst, int offset, int count, + GrColor color, const SkMatrix& drawMatrix, SkPoint drawOrigin, + SkIRect clip) const; - void joinGlyphBounds(const SkRect& glyphBounds); + int glyphCount() const; bool drawAsDistanceFields() const; - bool drawAsPaths() const; bool needsTransform() const; bool needsPadding() const; + int atlasPadding() const; + SkSpan<const VertexData> vertexData() const; + // Acquire a GrTextStrike and convert the SkPackedGlyphIDs to GrGlyphs for this run void prepareGrGlyphs(GrStrikeCache*); // has 'prepareGrGlyphs' been called (i.e., can the GrGlyphs be accessed) ? SkDEBUGCODE(bool isPrepared() const { return SkToBool(fStrike); }) - void translateVerticesIfNeeded(const SkMatrix& drawMatrix, SkPoint drawOrigin); - void updateVerticesColorIfNeeded(GrColor newColor); - void updateTexCoords(int begin, int end); - // The rectangle that surrounds all the glyph bounding boxes in device space. SkRect deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const; + GrGlyph* grGlyph(int i) const; + // df properties - void setUseLCDText(bool useLCDText); bool hasUseLCDText() const; - void setAntiAliased(bool antiAliased); bool isAntiAliased() const; const SkStrikeSpec& strikeSpec() const; + static SubRun* MakePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables, + const SkFont& runFont, + const SkStrikeSpec& strikeSpec, + GrTextBlob* blob, + SkArenaAlloc* alloc); + static SubRun* MakeSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables, + const SkFont& runFont, + const SkStrikeSpec& strikeSpec, + GrTextBlob* blob, + SkArenaAlloc* alloc); + static SubRun* MakeDirectMask(const SkZip<SkGlyphVariant, SkPoint>& drawables, + const SkStrikeSpec& strikeSpec, + GrMaskFormat format, + GrTextBlob* blob, + SkArenaAlloc* alloc); + static SubRun* MakeTransformedMask(const SkZip<SkGlyphVariant, SkPoint>& drawables, + const SkStrikeSpec& strikeSpec, + GrMaskFormat format, + GrTextBlob* blob, + SkArenaAlloc* alloc); + + void insertSubRunOpsIntoTarget(GrTextTarget* target, + const SkSurfaceProps& props, + const SkPaint& paint, + const GrClip* clip, + const SkMatrixProvider& deviceMatrix, + SkPoint drawOrigin); + + std::unique_ptr<GrAtlasTextOp> makeOp(const SkMatrixProvider& matrixProvider, + SkPoint drawOrigin, + const SkIRect& clipRect, + const SkPaint& paint, + const SkSurfaceProps&, + GrTextTarget*); + SubRun* fNextSubRun{nullptr}; + GrTextBlob* fBlob; + uint64_t fAtlasGeneration{GrDrawOpAtlas::kInvalidAtlasGeneration}; + +private: + struct AtlasPt { + uint16_t u; + uint16_t v; + }; + + // Normal text mask, SDFT, or color. + struct Mask2DVertex { + SkPoint devicePos; + GrColor color; + AtlasPt atlasPos; + }; + struct ARGB2DVertex { + ARGB2DVertex(SkPoint d, GrColor, AtlasPt a) : devicePos{d}, atlasPos{a} {} + SkPoint devicePos; + AtlasPt atlasPos; + }; + + // Perspective SDFT or SDFT forced to 3D or perspective color. + struct Mask3DVertex { + SkPoint3 devicePos; + GrColor color; + AtlasPt atlasPos; + }; + struct ARGB3DVertex { + ARGB3DVertex(SkPoint3 d, GrColor, AtlasPt a) : devicePos{d}, atlasPos{a} {} + SkPoint3 devicePos; + AtlasPt atlasPos; + }; + + static SubRun* InitForAtlas(SubRunType type, + const SkZip<SkGlyphVariant, SkPoint>& drawables, + const SkStrikeSpec& strikeSpec, + GrMaskFormat format, + GrTextBlob* blob, + SkArenaAlloc* alloc); + bool hasW() const; + void setUseLCDText(bool useLCDText); + void setAntiAliased(bool antiAliased); + bool drawAsPaths() const; + const SubRunType fType; - GrTextBlob* const fBlob; const GrMaskFormat fMaskFormat; - const SkSpan<PackedGlyphIDorGrGlyph> fGlyphs; - const SkSpan<char> fVertexData; + bool fUseLCDText{false}; + bool fAntiAliased{false}; + const SkStrikeSpec fStrikeSpec; sk_sp<GrTextStrike> fStrike; - struct { - bool useLCDText:1; - bool antiAliased:1; - } fFlags{false, false}; - GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken; - uint64_t fAtlasGeneration{GrDrawOpAtlas::kInvalidAtlasGeneration}; - GrColor fCurrentColor; - SkPoint fCurrentOrigin; - SkMatrix fCurrentMatrix; - std::vector<PathGlyph> fPaths; -private: + GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken; // The vertex bounds in device space if needsTransform() is false, otherwise the bounds in // source space. The bounds are the joined rectangles of all the glyphs. - SkRect fVertexBounds = SkRectPriv::MakeLargestInverted(); - bool hasW() const; - + const SkRect fVertexBounds; + const SkSpan<VertexData> fVertexData; + std::vector<PathGlyph> fPaths; }; // SubRun #endif // GrTextBlob_DEFINED diff --git a/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.cpp b/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.cpp index c3a6860231e..29c855e7056 100644 --- a/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.cpp +++ b/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.cpp @@ -9,15 +9,64 @@ DECLARE_SKMESSAGEBUS_MESSAGE(GrTextBlobCache::PurgeBlobMessage) +// This function is captured by the above macro using implementations from SkMessageBus.h static inline bool SkShouldPostMessageToBus( const GrTextBlobCache::PurgeBlobMessage& msg, uint32_t msgBusUniqueID) { return msg.fContextID == msgBusUniqueID; } +GrTextBlobCache::GrTextBlobCache(PurgeMore purgeMore, uint32_t messageBusID) + : fPurgeMore(purgeMore) + , fSizeBudget(kDefaultBudget) + , fMessageBusID(messageBusID) + , fPurgeBlobInbox(messageBusID) { } + GrTextBlobCache::~GrTextBlobCache() { this->freeAll(); } +sk_sp<GrTextBlob> +GrTextBlobCache::makeCachedBlob(const SkGlyphRunList& glyphRunList, const GrTextBlob::Key& key, + const SkMaskFilterBase::BlurRec& blurRec, + const SkMatrix& viewMatrix) { + sk_sp<GrTextBlob> cacheBlob(GrTextBlob::Make(glyphRunList, viewMatrix)); + cacheBlob->setupKey(key, blurRec, glyphRunList.paint()); + this->internalAdd(cacheBlob); + glyphRunList.temporaryShuntBlobNotifyAddedToCache(fMessageBusID); + return cacheBlob; +} + +sk_sp<GrTextBlob> GrTextBlobCache::find(const GrTextBlob::Key& key) const { + const auto* idEntry = fBlobIDCache.find(key.fUniqueID); + return idEntry ? idEntry->find(key) : nullptr; +} + +void GrTextBlobCache::remove(GrTextBlob* blob) { + this->internalRemove(blob); +} + +void GrTextBlobCache::internalRemove(GrTextBlob* blob) { + auto id = GrTextBlob::GetKey(*blob).fUniqueID; + auto* idEntry = fBlobIDCache.find(id); + SkASSERT(idEntry); + + fCurrentSize -= blob->size(); + fBlobList.remove(blob); + idEntry->removeBlob(blob); + if (idEntry->fBlobs.empty()) { + fBlobIDCache.remove(id); + } +} + +void GrTextBlobCache::makeMRU(GrTextBlob* blob) { + if (fBlobList.head() == blob) { + return; + } + + fBlobList.remove(blob); + fBlobList.addToHead(blob); +} + void GrTextBlobCache::freeAll() { fBlobIDCache.foreach([this](uint32_t, BlobIDCacheEntry* entry) { for (const auto& blob : entry->fBlobs) { @@ -33,12 +82,21 @@ void GrTextBlobCache::freeAll() { SkASSERT(fBlobList.isEmpty()); } +void GrTextBlobCache::setBudget(size_t budget) { + fSizeBudget = budget; + this->internalCheckPurge(); +} + void GrTextBlobCache::PostPurgeBlobMessage(uint32_t blobID, uint32_t cacheID) { SkASSERT(blobID != SK_InvalidGenID); SkMessageBus<PurgeBlobMessage>::Post(PurgeBlobMessage(blobID, cacheID)); } void GrTextBlobCache::purgeStaleBlobs() { + this->internalPurgeStaleBlobs(); +} + +void GrTextBlobCache::internalPurgeStaleBlobs() { SkTArray<PurgeBlobMessage> msgs; fPurgeBlobInbox.poll(&msgs); @@ -60,36 +118,93 @@ void GrTextBlobCache::purgeStaleBlobs() { } } -void GrTextBlobCache::checkPurge(GrTextBlob* blob) { +size_t GrTextBlobCache::usedBytes() const { + return fCurrentSize; +} + +void GrTextBlobCache::internalCheckPurge(GrTextBlob* blob) { // First, purge all stale blob IDs. - this->purgeStaleBlobs(); + this->internalPurgeStaleBlobs(); // If we are still over budget, then unref until we are below budget again if (fCurrentSize > fSizeBudget) { - BitmapBlobList::Iter iter; - iter.init(fBlobList, BitmapBlobList::Iter::kTail_IterStart); + TextBlobList::Iter iter; + iter.init(fBlobList, TextBlobList::Iter::kTail_IterStart); GrTextBlob* lruBlob = nullptr; while (fCurrentSize > fSizeBudget && (lruBlob = iter.get()) && lruBlob != blob) { // Backup the iterator before removing and unrefing the blob iter.prev(); - this->remove(lruBlob); + this->internalRemove(lruBlob); } // If we break out of the loop with lruBlob == blob, then we haven't purged enough // use the call back and try to free some more. If we are still overbudget after this, // then this single textblob is over our budget if (blob && lruBlob == blob) { - (*fCallback)(fData); + fPurgeMore(); } -#ifdef SPEW_BUDGET_MESSAGE + #ifdef SPEW_BUDGET_MESSAGE if (fCurrentSize > fSizeBudget) { SkDebugf("Single textblob is larger than our whole budget"); } -#endif + #endif } } +void GrTextBlobCache::internalAdd(sk_sp<GrTextBlob> blob) { + auto id = GrTextBlob::GetKey(*blob).fUniqueID; + auto* idEntry = fBlobIDCache.find(id); + if (!idEntry) { + idEntry = fBlobIDCache.set(id, BlobIDCacheEntry(id)); + } + + // Safe to retain a raw ptr temporarily here, because the cache will hold a ref. + GrTextBlob* rawBlobPtr = blob.get(); + fBlobList.addToHead(rawBlobPtr); + fCurrentSize += blob->size(); + idEntry->addBlob(std::move(blob)); + + this->internalCheckPurge(rawBlobPtr); +} + +GrTextBlobCache::BlobIDCacheEntry::BlobIDCacheEntry() : fID(SK_InvalidGenID) {} + +GrTextBlobCache::BlobIDCacheEntry::BlobIDCacheEntry(uint32_t id) : fID(id) {} + +uint32_t GrTextBlobCache::BlobIDCacheEntry::GetKey(const GrTextBlobCache::BlobIDCacheEntry& entry) { + return entry.fID; +} + +void GrTextBlobCache::BlobIDCacheEntry::addBlob(sk_sp<GrTextBlob> blob) { + SkASSERT(blob); + SkASSERT(GrTextBlob::GetKey(*blob).fUniqueID == fID); + SkASSERT(!this->find(GrTextBlob::GetKey(*blob))); + fBlobs.emplace_back(std::move(blob)); +} + +void GrTextBlobCache::BlobIDCacheEntry::removeBlob(GrTextBlob* blob) { + SkASSERT(blob); + SkASSERT(GrTextBlob::GetKey(*blob).fUniqueID == fID); + + auto index = this->findBlobIndex(GrTextBlob::GetKey(*blob)); + SkASSERT(index >= 0); + + fBlobs.removeShuffle(index); +} +sk_sp<GrTextBlob> GrTextBlobCache::BlobIDCacheEntry::find(const GrTextBlob::Key& key) const { + auto index = this->findBlobIndex(key); + return index < 0 ? nullptr : fBlobs[index]; +} + +int GrTextBlobCache::BlobIDCacheEntry::findBlobIndex(const GrTextBlob::Key& key) const { + for (int i = 0; i < fBlobs.count(); ++i) { + if (GrTextBlob::GetKey(*fBlobs[i]) == key) { + return i; + } + } + return -1; +} diff --git a/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.h b/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.h index 9af2f2c5a1e..6dc46908229 100644 --- a/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.h +++ b/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.h @@ -15,85 +15,30 @@ #include "src/core/SkTextBlobPriv.h" #include "src/gpu/text/GrTextBlob.h" +#include <functional> + class GrTextBlobCache { public: - /** - * The callback function used by the cache when it is still over budget after a purge. The - * passed in 'data' is the same 'data' handed to setOverbudgetCallback. - */ - typedef void (*PFOverBudgetCB)(void* data); - - GrTextBlobCache(PFOverBudgetCB cb, void* data, uint32_t uniqueID) - : fCallback(cb) - , fData(data) - , fSizeBudget(kDefaultBudget) - , fUniqueID(uniqueID) - , fPurgeBlobInbox(uniqueID) { - SkASSERT(cb && data); - } - ~GrTextBlobCache(); + // The callback function used by the cache when it is still over budget after a purge. + using PurgeMore = std::function<void()>; - sk_sp<GrTextBlob> makeBlob(const SkGlyphRunList& glyphRunList, - const SkMatrix& viewMatrix, - GrColor color, - bool forceW) { - return GrTextBlob::Make(glyphRunList, viewMatrix, color, forceW); - } + GrTextBlobCache(PurgeMore purgeMore, uint32_t messageBusID); + ~GrTextBlobCache(); sk_sp<GrTextBlob> makeCachedBlob(const SkGlyphRunList& glyphRunList, const GrTextBlob::Key& key, const SkMaskFilterBase::BlurRec& blurRec, - const SkMatrix& viewMatrix, - GrColor color, - bool forceW) { - sk_sp<GrTextBlob> cacheBlob(this->makeBlob(glyphRunList, viewMatrix, color, forceW)); - cacheBlob->setupKey(key, blurRec, glyphRunList.paint()); - this->add(cacheBlob); - glyphRunList.temporaryShuntBlobNotifyAddedToCache(fUniqueID); - return cacheBlob; - } - - sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) const { - const auto* idEntry = fBlobIDCache.find(key.fUniqueID); - return idEntry ? idEntry->find(key) : nullptr; - } - - void remove(GrTextBlob* blob) { - auto id = GrTextBlob::GetKey(*blob).fUniqueID; - auto* idEntry = fBlobIDCache.find(id); - SkASSERT(idEntry); - - fCurrentSize -= blob->size(); - fBlobList.remove(blob); - idEntry->removeBlob(blob); - if (idEntry->fBlobs.empty()) { - fBlobIDCache.remove(id); - } - } - - void makeMRU(GrTextBlob* blob) { - if (fBlobList.head() == blob) { - return; - } - - fBlobList.remove(blob); - fBlobList.addToHead(blob); - } + const SkMatrix& viewMatrix); - void freeAll(); + sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) const; - // TODO move to SkTextBlob - static void BlobGlyphCount(int* glyphCount, int* runCount, const SkTextBlob* blob) { - SkTextBlobRunIterator itCounter(blob); - for (; !itCounter.done(); itCounter.next(), (*runCount)++) { - *glyphCount += itCounter.glyphCount(); - } - } + void remove(GrTextBlob* blob); - void setBudget(size_t budget) { - fSizeBudget = budget; - this->checkPurge(); - } + void makeMRU(GrTextBlob* blob); + + void freeAll(); + + void setBudget(size_t budget); struct PurgeBlobMessage { PurgeBlobMessage(uint32_t blobID, uint32_t contextUniqueID) @@ -107,84 +52,48 @@ public: void purgeStaleBlobs(); - size_t usedBytes() const { return fCurrentSize; } + size_t usedBytes() const; private: - using BitmapBlobList = SkTInternalLList<GrTextBlob>; + using TextBlobList = SkTInternalLList<GrTextBlob>; struct BlobIDCacheEntry { - BlobIDCacheEntry() : fID(SK_InvalidGenID) {} - explicit BlobIDCacheEntry(uint32_t id) : fID(id) {} - - static uint32_t GetKey(const BlobIDCacheEntry& entry) { - return entry.fID; - } - - void addBlob(sk_sp<GrTextBlob> blob) { - SkASSERT(blob); - SkASSERT(GrTextBlob::GetKey(*blob).fUniqueID == fID); - SkASSERT(!this->find(GrTextBlob::GetKey(*blob))); - - fBlobs.emplace_back(std::move(blob)); - } - - void removeBlob(GrTextBlob* blob) { - SkASSERT(blob); - SkASSERT(GrTextBlob::GetKey(*blob).fUniqueID == fID); - - auto index = this->findBlobIndex(GrTextBlob::GetKey(*blob)); - SkASSERT(index >= 0); - - fBlobs.removeShuffle(index); - } - - sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) const { - auto index = this->findBlobIndex(key); - return index < 0 ? nullptr : fBlobs[index]; - } - - int findBlobIndex(const GrTextBlob::Key& key) const{ - for (int i = 0; i < fBlobs.count(); ++i) { - if (GrTextBlob::GetKey(*fBlobs[i]) == key) { - return i; - } - } - return -1; - } - - uint32_t fID; + BlobIDCacheEntry(); + explicit BlobIDCacheEntry(uint32_t id); + + static uint32_t GetKey(const BlobIDCacheEntry& entry); + + void addBlob(sk_sp<GrTextBlob> blob); + + void removeBlob(GrTextBlob* blob); + + sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) const; + + int findBlobIndex(const GrTextBlob::Key& key) const; + + uint32_t fID; // Current clients don't generate multiple GrAtlasTextBlobs per SkTextBlob, so an array w/ // linear search is acceptable. If usage changes, we should re-evaluate this structure. SkSTArray<1, sk_sp<GrTextBlob>> fBlobs; }; - void add(sk_sp<GrTextBlob> blob) { - auto id = GrTextBlob::GetKey(*blob).fUniqueID; - auto* idEntry = fBlobIDCache.find(id); - if (!idEntry) { - idEntry = fBlobIDCache.set(id, BlobIDCacheEntry(id)); - } - - // Safe to retain a raw ptr temporarily here, because the cache will hold a ref. - GrTextBlob* rawBlobPtr = blob.get(); - fBlobList.addToHead(rawBlobPtr); - fCurrentSize += blob->size(); - idEntry->addBlob(std::move(blob)); + void internalPurgeStaleBlobs(); - this->checkPurge(rawBlobPtr); - } + void internalAdd(sk_sp<GrTextBlob> blob); + void internalRemove(GrTextBlob* blob); - void checkPurge(GrTextBlob* blob = nullptr); + void internalCheckPurge(GrTextBlob* blob = nullptr); - static const int kMinGrowthSize = 1 << 16; static const int kDefaultBudget = 1 << 22; - BitmapBlobList fBlobList; + + TextBlobList fBlobList; SkTHashMap<uint32_t, BlobIDCacheEntry> fBlobIDCache; - PFOverBudgetCB fCallback; - void* fData; + PurgeMore fPurgeMore; size_t fSizeBudget; size_t fCurrentSize{0}; - uint32_t fUniqueID; // unique id to use for messaging + + // In practice 'messageBusID' is always the unique ID of the owning GrContext + uint32_t fMessageBusID; SkMessageBus<PurgeBlobMessage>::Inbox fPurgeBlobInbox; }; diff --git a/chromium/third_party/skia/src/gpu/text/GrTextContext.cpp b/chromium/third_party/skia/src/gpu/text/GrTextContext.cpp deleted file mode 100644 index 59a3d46179f..00000000000 --- a/chromium/third_party/skia/src/gpu/text/GrTextContext.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright 2015 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "src/gpu/text/GrTextContext.h" - -#include "include/core/SkGraphics.h" -#include "include/gpu/GrContext.h" -#include "include/private/SkTo.h" -#include "src/core/SkDistanceFieldGen.h" -#include "src/core/SkDraw.h" -#include "src/core/SkDrawProcs.h" -#include "src/core/SkGlyphRun.h" -#include "src/core/SkMaskFilterBase.h" -#include "src/core/SkPaintPriv.h" -#include "src/gpu/GrCaps.h" -#include "src/gpu/GrRecordingContextPriv.h" -#include "src/gpu/SkGr.h" -#include "src/gpu/ops/GrMeshDrawOp.h" -#include "src/gpu/text/GrSDFMaskFilter.h" -#include "src/gpu/text/GrTextBlobCache.h" - -// DF sizes and thresholds for usage of the small and medium sizes. For example, above -// kSmallDFFontLimit we will use the medium size. The large size is used up until the size at -// which we switch over to drawing as paths as controlled by Options. -static const int kSmallDFFontSize = 32; -static const int kSmallDFFontLimit = 32; -static const int kMediumDFFontSize = 72; -static const int kMediumDFFontLimit = 72; -static const int kLargeDFFontSize = 162; -#ifdef SK_BUILD_FOR_MAC -static const int kLargeDFFontLimit = 162; -static const int kExtraLargeDFFontSize = 256; -#endif - -static const int kDefaultMinDistanceFieldFontSize = 18; -#if defined(SK_BUILD_FOR_ANDROID) -static const int kDefaultMaxDistanceFieldFontSize = 384; -#elif defined(SK_BUILD_FOR_MAC) -static const int kDefaultMaxDistanceFieldFontSize = kExtraLargeDFFontSize; -#else -static const int kDefaultMaxDistanceFieldFontSize = 2 * kLargeDFFontSize; -#endif - -GrTextContext::GrTextContext(const Options& options) : fOptions(options) { - SanitizeOptions(&fOptions); -} - -std::unique_ptr<GrTextContext> GrTextContext::Make(const Options& options) { - return std::unique_ptr<GrTextContext>(new GrTextContext(options)); -} - -SkColor GrTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd) { - SkColor canonicalColor = SkPaintPriv::ComputeLuminanceColor(paint); - if (lcd) { - // This is the correct computation, but there are tons of cases where LCD can be overridden. - // For now we just regenerate if any run in a textblob has LCD. - // TODO figure out where all of these overrides are and see if we can incorporate that logic - // at a higher level *OR* use sRGB - SkASSERT(false); - //canonicalColor = SkMaskGamma::CanonicalColor(canonicalColor); - } else { - // A8, though can have mixed BMP text but it shouldn't matter because BMP text won't have - // gamma corrected masks anyways, nor color - U8CPU lum = SkComputeLuminance(SkColorGetR(canonicalColor), - SkColorGetG(canonicalColor), - SkColorGetB(canonicalColor)); - // reduce to our finite number of bits - canonicalColor = SkMaskGamma::CanonicalColor(SkColorSetRGB(lum, lum, lum)); - } - return canonicalColor; -} - -SkScalerContextFlags GrTextContext::ComputeScalerContextFlags(const GrColorInfo& colorInfo) { - // If we're doing linear blending, then we can disable the gamma hacks. - // Otherwise, leave them on. In either case, we still want the contrast boost: - // TODO: Can we be even smarter about mask gamma based on the dest transfer function? - if (colorInfo.isLinearlyBlended()) { - return SkScalerContextFlags::kBoostContrast; - } else { - return SkScalerContextFlags::kFakeGammaAndBoostContrast; - } -} - -void GrTextContext::SanitizeOptions(Options* options) { - if (options->fMaxDistanceFieldFontSize < 0.f) { - options->fMaxDistanceFieldFontSize = kDefaultMaxDistanceFieldFontSize; - } - if (options->fMinDistanceFieldFontSize < 0.f) { - options->fMinDistanceFieldFontSize = kDefaultMinDistanceFieldFontSize; - } -} - -bool GrTextContext::CanDrawAsDistanceFields(const SkPaint& paint, const SkFont& font, - const SkMatrix& viewMatrix, - const SkSurfaceProps& props, - bool contextSupportsDistanceFieldText, - const Options& options) { - // mask filters modify alpha, which doesn't translate well to distance - if (paint.getMaskFilter() || !contextSupportsDistanceFieldText) { - return false; - } - - // TODO: add some stroking support - if (paint.getStyle() != SkPaint::kFill_Style) { - return false; - } - - if (viewMatrix.hasPerspective()) { - if (!options.fDistanceFieldVerticesAlwaysHaveW) { - return false; - } - } else { - SkScalar maxScale = viewMatrix.getMaxScale(); - SkScalar scaledTextSize = maxScale * font.getSize(); - // Hinted text looks far better at small resolutions - // Scaling up beyond 2x yields undesireable artifacts - if (scaledTextSize < options.fMinDistanceFieldFontSize || - scaledTextSize > options.fMaxDistanceFieldFontSize) { - return false; - } - - bool useDFT = props.isUseDeviceIndependentFonts(); -#if SK_FORCE_DISTANCE_FIELD_TEXT - useDFT = true; -#endif - - if (!useDFT && scaledTextSize < kLargeDFFontSize) { - return false; - } - } - - return true; -} - -SkScalar scaled_text_size(const SkScalar textSize, const SkMatrix& viewMatrix) { - SkScalar scaledTextSize = textSize; - - if (viewMatrix.hasPerspective()) { - // for perspective, we simply force to the medium size - // TODO: compute a size based on approximate screen area - scaledTextSize = kMediumDFFontLimit; - } else { - SkScalar maxScale = viewMatrix.getMaxScale(); - // if we have non-unity scale, we need to choose our base text size - // based on the SkPaint's text size multiplied by the max scale factor - // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)? - if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) { - scaledTextSize *= maxScale; - } - } - - return scaledTextSize; -} - -SkFont GrTextContext::InitDistanceFieldFont(const SkFont& font, - const SkMatrix& viewMatrix, - const Options& options, - SkScalar* textRatio) { - SkScalar textSize = font.getSize(); - SkScalar scaledTextSize = scaled_text_size(textSize, viewMatrix); - - SkFont dfFont{font}; - - if (scaledTextSize <= kSmallDFFontLimit) { - *textRatio = textSize / kSmallDFFontSize; - dfFont.setSize(SkIntToScalar(kSmallDFFontSize)); - } else if (scaledTextSize <= kMediumDFFontLimit) { - *textRatio = textSize / kMediumDFFontSize; - dfFont.setSize(SkIntToScalar(kMediumDFFontSize)); -#ifdef SK_BUILD_FOR_MAC - } else if (scaledTextSize <= kLargeDFFontLimit) { - *textRatio = textSize / kLargeDFFontSize; - dfFont.setSize(SkIntToScalar(kLargeDFFontSize)); - } else { - *textRatio = textSize / kExtraLargeDFFontSize; - dfFont.setSize(SkIntToScalar(kExtraLargeDFFontSize)); - } -#else - } else { - *textRatio = textSize / kLargeDFFontSize; - dfFont.setSize(SkIntToScalar(kLargeDFFontSize)); - } -#endif - - dfFont.setEdging(SkFont::Edging::kAntiAlias); - dfFont.setForceAutoHinting(false); - dfFont.setHinting(SkFontHinting::kNormal); - - // The sub-pixel position will always happen when transforming to the screen. - dfFont.setSubpixel(false); - return dfFont; -} - -std::pair<SkScalar, SkScalar> GrTextContext::InitDistanceFieldMinMaxScale( - SkScalar textSize, - const SkMatrix& viewMatrix, - const GrTextContext::Options& options) { - - SkScalar scaledTextSize = scaled_text_size(textSize, viewMatrix); - - // We have three sizes of distance field text, and within each size 'bucket' there is a floor - // and ceiling. A scale outside of this range would require regenerating the distance fields - SkScalar dfMaskScaleFloor; - SkScalar dfMaskScaleCeil; - if (scaledTextSize <= kSmallDFFontLimit) { - dfMaskScaleFloor = options.fMinDistanceFieldFontSize; - dfMaskScaleCeil = kSmallDFFontLimit; - } else if (scaledTextSize <= kMediumDFFontLimit) { - dfMaskScaleFloor = kSmallDFFontLimit; - dfMaskScaleCeil = kMediumDFFontLimit; - } else { - dfMaskScaleFloor = kMediumDFFontLimit; - dfMaskScaleCeil = options.fMaxDistanceFieldFontSize; - } - - // Because there can be multiple runs in the blob, we want the overall maxMinScale, and - // minMaxScale to make regeneration decisions. Specifically, we want the maximum minimum scale - // we can tolerate before we'd drop to a lower mip size, and the minimum maximum scale we can - // tolerate before we'd have to move to a large mip size. When we actually test these values - // we look at the delta in scale between the new viewmatrix and the old viewmatrix, and test - // against these values to decide if we can reuse or not(ie, will a given scale change our mip - // level) - SkASSERT(dfMaskScaleFloor <= scaledTextSize && scaledTextSize <= dfMaskScaleCeil); - - return std::make_pair(dfMaskScaleFloor / scaledTextSize, dfMaskScaleCeil / scaledTextSize); -} - -SkPaint GrTextContext::InitDistanceFieldPaint(const SkPaint& paint) { - SkPaint dfPaint{paint}; - dfPaint.setMaskFilter(GrSDFMaskFilter::Make()); - return dfPaint; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -#if GR_TEST_UTILS - -#include "src/gpu/GrRenderTargetContext.h" - -GR_DRAW_OP_TEST_DEFINE(GrAtlasTextOp) { - static uint32_t gContextID = SK_InvalidGenID; - static std::unique_ptr<GrTextContext> gTextContext; - static SkSurfaceProps gSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType); - - if (context->priv().contextID() != gContextID) { - gContextID = context->priv().contextID(); - gTextContext = GrTextContext::Make(GrTextContext::Options()); - } - - // Setup dummy SkPaint / GrPaint / GrRenderTargetContext - auto rtc = GrRenderTargetContext::Make( - context, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kApprox, {1024, 1024}); - - SkSimpleMatrixProvider matrixProvider(GrTest::TestMatrixInvertible(random)); - - SkPaint skPaint; - skPaint.setColor(random->nextU()); - - SkFont font; - if (random->nextBool()) { - font.setEdging(SkFont::Edging::kSubpixelAntiAlias); - } else { - font.setEdging(random->nextBool() ? SkFont::Edging::kAntiAlias : SkFont::Edging::kAlias); - } - font.setSubpixel(random->nextBool()); - - const char* text = "The quick brown fox jumps over the lazy dog."; - - // create some random x/y offsets, including negative offsets - static const int kMaxTrans = 1024; - int xPos = (random->nextU() % 2) * 2 - 1; - int yPos = (random->nextU() % 2) * 2 - 1; - int xInt = (random->nextU() % kMaxTrans) * xPos; - int yInt = (random->nextU() % kMaxTrans) * yPos; - - return gTextContext->createOp_TestingOnly(context, gTextContext.get(), rtc.get(), skPaint, font, - matrixProvider, text, xInt, yInt); -} - -#endif diff --git a/chromium/third_party/skia/src/gpu/text/GrTextContext.h b/chromium/third_party/skia/src/gpu/text/GrTextContext.h deleted file mode 100644 index 4b902393e29..00000000000 --- a/chromium/third_party/skia/src/gpu/text/GrTextContext.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2015 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrTextContext_DEFINED -#define GrTextContext_DEFINED - -#include "src/core/SkGlyphRun.h" -#include "src/gpu/GrGeometryProcessor.h" -#include "src/gpu/text/GrTextTarget.h" - -#if GR_TEST_UTILS -#include "src/gpu/GrDrawOpTest.h" -#endif - -class GrDrawOp; -class GrRecordingContext; -class GrRenderTargetContext; -class GrTextBlobCache; -class SkGlyph; -class GrTextBlob; - -/* - * Renders text using some kind of an atlas, ie BitmapText or DistanceField text - */ -class GrTextContext { -public: - struct Options { - /** - * Below this size (in device space) distance field text will not be used. Negative means - * use a default value. - */ - SkScalar fMinDistanceFieldFontSize = -1.f; - /** - * Above this size (in device space) distance field text will not be used and glyphs will - * be rendered from outline as individual paths. Negative means use a default value. - */ - SkScalar fMaxDistanceFieldFontSize = -1.f; - /** Forces all distance field vertices to use 3 components, not just when in perspective. */ - bool fDistanceFieldVerticesAlwaysHaveW = false; - }; - - static std::unique_ptr<GrTextContext> Make(const Options& options); - - void drawGlyphRunList(GrRecordingContext*, - GrTextTarget*, - const GrClip&, - const SkMatrixProvider&, - const SkSurfaceProps&, - const SkGlyphRunList&) const; - -#if GR_TEST_UTILS - std::unique_ptr<GrDrawOp> createOp_TestingOnly(GrRecordingContext*, - GrTextContext*, - GrRenderTargetContext*, - const SkPaint&, - const SkFont&, - const SkMatrixProvider&, - const char* text, - int x, - int y); -#endif - - static void SanitizeOptions(Options* options); - static bool CanDrawAsDistanceFields(const SkPaint&, const SkFont&, const SkMatrix& viewMatrix, - const SkSurfaceProps& props, - bool contextSupportsDistanceFieldText, - const Options& options); - - static SkFont InitDistanceFieldFont(const SkFont& font, - const SkMatrix& viewMatrix, - const Options& options, - SkScalar* textRatio); - - static SkPaint InitDistanceFieldPaint(const SkPaint& paint); - - static std::pair<SkScalar, SkScalar> InitDistanceFieldMinMaxScale(SkScalar textSize, - const SkMatrix& viewMatrix, - const Options& options); - -private: - GrTextContext(const Options& options); - - // sets up the descriptor on the blob and returns a detached cache. Client must attach - static SkColor ComputeCanonicalColor(const SkPaint&, bool lcd); - // Determines if we need to use fake gamma (and contrast boost): - static SkScalerContextFlags ComputeScalerContextFlags(const GrColorInfo&); - - Options fOptions; - -#if GR_TEST_UTILS - static const SkScalerContextFlags kTextBlobOpScalerContextFlags = - SkScalerContextFlags::kFakeGammaAndBoostContrast; - GR_DRAW_OP_TEST_FRIEND(GrAtlasTextOp); -#endif -}; - -#endif // GrTextContext_DEFINED diff --git a/chromium/third_party/skia/src/gpu/text/GrTextTarget.h b/chromium/third_party/skia/src/gpu/text/GrTextTarget.h index 9f88eb72044..7a834ccc5f6 100644 --- a/chromium/third_party/skia/src/gpu/text/GrTextTarget.h +++ b/chromium/third_party/skia/src/gpu/text/GrTextTarget.h @@ -31,9 +31,9 @@ public: const GrColorInfo& colorInfo() const { return fColorInfo; } - virtual void addDrawOp(const GrClip&, std::unique_ptr<GrAtlasTextOp> op) = 0; + virtual void addDrawOp(const GrClip*, std::unique_ptr<GrAtlasTextOp> op) = 0; - virtual void drawShape(const GrClip&, + virtual void drawShape(const GrClip*, const SkPaint&, const SkMatrixProvider&, const GrStyledShape&) = 0; diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.cpp index a1339537d6c..03467a24af2 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.cpp @@ -98,8 +98,8 @@ GrVkAMDMemoryAllocator::~GrVkAMDMemoryAllocator() { fAllocator = VK_NULL_HANDLE; } -bool GrVkAMDMemoryAllocator::allocateMemoryForImage(VkImage image, AllocationPropertyFlags flags, - GrVkBackendMemory* backendMemory) { +VkResult GrVkAMDMemoryAllocator::allocateImageMemory(VkImage image, AllocationPropertyFlags flags, + GrVkBackendMemory* backendMemory) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); VmaAllocationCreateInfo info; info.flags = 0; @@ -124,16 +124,15 @@ bool GrVkAMDMemoryAllocator::allocateMemoryForImage(VkImage image, AllocationPro VmaAllocation allocation; VkResult result = vmaAllocateMemoryForImage(fAllocator, image, &info, &allocation, nullptr); - if (VK_SUCCESS != result) { - return false; + if (VK_SUCCESS == result) { + *backendMemory = (GrVkBackendMemory)allocation; } - *backendMemory = (GrVkBackendMemory)allocation; - return true; + return result; } -bool GrVkAMDMemoryAllocator::allocateMemoryForBuffer(VkBuffer buffer, BufferUsage usage, - AllocationPropertyFlags flags, - GrVkBackendMemory* backendMemory) { +VkResult GrVkAMDMemoryAllocator::allocateBufferMemory(VkBuffer buffer, BufferUsage usage, + AllocationPropertyFlags flags, + GrVkBackendMemory* backendMemory) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); VmaAllocationCreateInfo info; info.flags = 0; @@ -187,12 +186,11 @@ bool GrVkAMDMemoryAllocator::allocateMemoryForBuffer(VkBuffer buffer, BufferUsag result = vmaAllocateMemoryForBuffer(fAllocator, buffer, &info, &allocation, nullptr); } } - if (VK_SUCCESS != result) { - return false; + if (VK_SUCCESS == result) { + *backendMemory = (GrVkBackendMemory)allocation; } - *backendMemory = (GrVkBackendMemory)allocation; - return true; + return result; } void GrVkAMDMemoryAllocator::freeMemory(const GrVkBackendMemory& memoryHandle) { @@ -225,12 +223,10 @@ void GrVkAMDMemoryAllocator::getAllocInfo(const GrVkBackendMemory& memoryHandle, alloc->fBackendMemory = memoryHandle; } -void* GrVkAMDMemoryAllocator::mapMemory(const GrVkBackendMemory& memoryHandle) { +VkResult GrVkAMDMemoryAllocator::mapMemory(const GrVkBackendMemory& memoryHandle, void** data) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); const VmaAllocation allocation = (const VmaAllocation)memoryHandle; - void* mapPtr; - vmaMapMemory(fAllocator, allocation, &mapPtr); - return mapPtr; + return vmaMapMemory(fAllocator, allocation, data); } void GrVkAMDMemoryAllocator::unmapMemory(const GrVkBackendMemory& memoryHandle) { @@ -239,18 +235,18 @@ void GrVkAMDMemoryAllocator::unmapMemory(const GrVkBackendMemory& memoryHandle) vmaUnmapMemory(fAllocator, allocation); } -void GrVkAMDMemoryAllocator::flushMappedMemory(const GrVkBackendMemory& memoryHandle, - VkDeviceSize offset, VkDeviceSize size) { +VkResult GrVkAMDMemoryAllocator::flushMemory(const GrVkBackendMemory& memoryHandle, + VkDeviceSize offset, VkDeviceSize size) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); const VmaAllocation allocation = (const VmaAllocation)memoryHandle; - vmaFlushAllocation(fAllocator, allocation, offset, size); + return vmaFlushAllocation(fAllocator, allocation, offset, size); } -void GrVkAMDMemoryAllocator::invalidateMappedMemory(const GrVkBackendMemory& memoryHandle, - VkDeviceSize offset, VkDeviceSize size) { +VkResult GrVkAMDMemoryAllocator::invalidateMemory(const GrVkBackendMemory& memoryHandle, + VkDeviceSize offset, VkDeviceSize size) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); const VmaAllocation allocation = (const VmaAllocation)memoryHandle; - vmaFlushAllocation(fAllocator, allocation, offset, size); + return vmaFlushAllocation(fAllocator, allocation, offset, size); } uint64_t GrVkAMDMemoryAllocator::totalUsedMemory() const { diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.h b/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.h index 5957cd5944f..82a3e31c29c 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.h @@ -39,23 +39,22 @@ public: ~GrVkAMDMemoryAllocator() override; - bool allocateMemoryForImage(VkImage image, AllocationPropertyFlags flags, - GrVkBackendMemory*) override; + VkResult allocateImageMemory(VkImage image, AllocationPropertyFlags flags, + GrVkBackendMemory*) override; - bool allocateMemoryForBuffer(VkBuffer buffer, BufferUsage usage, - AllocationPropertyFlags flags, GrVkBackendMemory*) override; + VkResult allocateBufferMemory(VkBuffer buffer, BufferUsage usage, + AllocationPropertyFlags flags, GrVkBackendMemory*) override; void freeMemory(const GrVkBackendMemory&) override; void getAllocInfo(const GrVkBackendMemory&, GrVkAlloc*) const override; - void* mapMemory(const GrVkBackendMemory&) override; + VkResult mapMemory(const GrVkBackendMemory&, void** data) override; void unmapMemory(const GrVkBackendMemory&) override; - void flushMappedMemory(const GrVkBackendMemory&, VkDeviceSize offset, - VkDeviceSize size) override; - void invalidateMappedMemory(const GrVkBackendMemory&, VkDeviceSize offset, - VkDeviceSize size) override; + VkResult flushMemory(const GrVkBackendMemory&, VkDeviceSize offset, VkDeviceSize size) override; + VkResult invalidateMemory(const GrVkBackendMemory&, VkDeviceSize offset, + VkDeviceSize size) override; uint64_t totalUsedMemory() const override; uint64_t totalAllocatedMemory() const override; diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkCaps.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkCaps.cpp index eacce98fc74..5dc79fbd250 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkCaps.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkCaps.cpp @@ -9,6 +9,7 @@ #include "include/gpu/vk/GrVkBackendContext.h" #include "include/gpu/vk/GrVkExtensions.h" #include "src/core/SkCompressedDataUtils.h" +#include "src/gpu/GrBackendUtils.h" #include "src/gpu/GrProgramDesc.h" #include "src/gpu/GrRenderTarget.h" #include "src/gpu/GrRenderTargetProxy.h" @@ -516,14 +517,20 @@ void GrVkCaps::initGrCaps(const GrVkInterface* vkInterface, static const uint32_t kMaxVertexAttributes = 64; fMaxVertexAttributes = std::min(properties.limits.maxVertexInputAttributes, kMaxVertexAttributes); + // GrCaps::fSampleLocationsSupport refers to the ability to *query* the sample locations (not + // program them). For now we just set this to true if the device uses standard locations, and + // return the standard locations back when queried. if (properties.limits.standardSampleLocations) { fSampleLocationsSupport = true; } + // See skbug.com/10346 +#if 0 if (extensions.hasExtension(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME, 1)) { // We "disable" multisample by colocating all samples at pixel center. fMultisampleDisableSupport = true; } +#endif if (extensions.hasExtension(VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME, 1)) { fMixedSamplesSupport = true; @@ -1318,22 +1325,6 @@ bool GrVkCaps::isFormatSRGB(const GrBackendFormat& format) const { return format_is_srgb(vkFormat); } -SkImage::CompressionType GrVkCaps::compressionType(const GrBackendFormat& format) const { - VkFormat vkFormat; - if (!format.asVkFormat(&vkFormat)) { - return SkImage::CompressionType::kNone; - } - - switch (vkFormat) { - case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: return SkImage::CompressionType::kETC2_RGB8_UNORM; - case VK_FORMAT_BC1_RGB_UNORM_BLOCK: return SkImage::CompressionType::kBC1_RGB8_UNORM; - case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: return SkImage::CompressionType::kBC1_RGBA8_UNORM; - default: return SkImage::CompressionType::kNone; - } - - SkUNREACHABLE; -} - bool GrVkCaps::isFormatTexturable(const GrBackendFormat& format) const { VkFormat vkFormat; if (!format.asVkFormat(&vkFormat)) { @@ -1531,12 +1522,6 @@ bool GrVkCaps::onAreColorTypeAndFormatCompatible(GrColorType ct, return false; } - SkImage::CompressionType compression = GrVkFormatToCompressionType(vkFormat); - if (compression != SkImage::CompressionType::kNone) { - return ct == (SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x - : GrColorType::kRGBA_8888); - } - const auto& info = this->getFormatInfo(vkFormat); for (int i = 0; i < info.fColorTypeInfoCount; ++i) { if (info.fColorTypeInfos[i].fColorType == ct) { @@ -1579,7 +1564,7 @@ GrBackendFormat GrVkCaps::getBackendFormatFromCompressionType( SkUNREACHABLE; } -GrSwizzle GrVkCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const { +GrSwizzle GrVkCaps::onGetReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const { VkFormat vkFormat; SkAssertResult(format.asVkFormat(&vkFormat)); const auto* ycbcrInfo = format.getVkYcbcrConversionInfo(); @@ -1589,6 +1574,7 @@ GrSwizzle GrVkCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType co // onAreColorTypeAndFormatCompatible. return GrSwizzle{"rgba"}; } + const auto& info = this->getFormatInfo(vkFormat); for (int i = 0; i < info.fColorTypeInfoCount; ++i) { const auto& ctInfo = info.fColorTypeInfos[i]; @@ -1641,7 +1627,7 @@ GrCaps::SupportedRead GrVkCaps::onSupportedReadPixelsColorType( return {GrColorType::kUnknown, 0}; } - SkImage::CompressionType compression = GrVkFormatToCompressionType(vkFormat); + SkImage::CompressionType compression = GrBackendFormatToCompressionType(srcBackendFormat); if (compression != SkImage::CompressionType::kNone) { return { SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x : GrColorType::kRGBA_8888, 0 }; @@ -1716,9 +1702,12 @@ GrProgramDesc GrVkCaps::makeDesc(const GrRenderTarget* rt, const GrProgramInfo& b.add32(GrVkGpu::kShader_PersistentCacheKeyType); GrVkRenderTarget* vkRT = (GrVkRenderTarget*) rt; + + bool needsStencil = programInfo.numStencilSamples() || programInfo.isStencilEnabled(); // TODO: support failure in getSimpleRenderPass - SkASSERT(vkRT->getSimpleRenderPass()); - vkRT->getSimpleRenderPass()->genKey(&b); + const GrVkRenderPass* rp = vkRT->getSimpleRenderPass(needsStencil); + SkASSERT(rp); + rp->genKey(&b); GrStencilSettings stencil = programInfo.nonGLStencilSettings(); stencil.genKey(&b, true); diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkCaps.h b/chromium/third_party/skia/src/gpu/vk/GrVkCaps.h index f136817b2ff..57787c2db42 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkCaps.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkCaps.h @@ -33,7 +33,6 @@ public: const GrVkExtensions& extensions, GrProtected isProtected = GrProtected::kNo); bool isFormatSRGB(const GrBackendFormat&) const override; - SkImage::CompressionType compressionType(const GrBackendFormat&) const override; bool isFormatTexturable(const GrBackendFormat&) const override; bool isVkFormatTexturable(VkFormat) const; @@ -189,7 +188,6 @@ public: return fColorTypeToFormatTable[idx]; } - GrSwizzle getReadSwizzle(const GrBackendFormat&, GrColorType) const override; GrSwizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override; uint64_t computeFormatKey(const GrBackendFormat&) const override; @@ -243,6 +241,9 @@ private: SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&, GrColorType) const override; + GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override; + + // ColorTypeInfo for a specific format struct ColorTypeInfo { GrColorType fColorType = GrColorType::kUnknown; diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkCommandBuffer.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkCommandBuffer.cpp index e23459b496a..c1dfe13fc52 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkCommandBuffer.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkCommandBuffer.cpp @@ -308,6 +308,7 @@ void GrVkCommandBuffer::drawIndirect(const GrVkGpu* gpu, SkASSERT(fActiveRenderPass); SkASSERT(!indirectBuffer->isCpuBuffer()); this->addingWork(gpu); + this->addResource(indirectBuffer->resource()); GR_VK_CALL(gpu->vkInterface(), CmdDrawIndirect(fCmdBuffer, indirectBuffer->buffer(), offset, @@ -324,6 +325,7 @@ void GrVkCommandBuffer::drawIndexedIndirect(const GrVkGpu* gpu, SkASSERT(fActiveRenderPass); SkASSERT(!indirectBuffer->isCpuBuffer()); this->addingWork(gpu); + this->addResource(indirectBuffer->resource()); GR_VK_CALL(gpu->vkInterface(), CmdDrawIndexedIndirect(fCmdBuffer, indirectBuffer->buffer(), offset, @@ -472,7 +474,7 @@ bool GrVkPrimaryCommandBuffer::beginRenderPass(GrVkGpu* gpu, SkASSERT(!fActiveRenderPass); SkASSERT(renderPass->isCompatible(*target)); - const GrVkFramebuffer* framebuffer = target->getFramebuffer(); + const GrVkFramebuffer* framebuffer = target->getFramebuffer(renderPass->hasStencilAttachment()); if (!framebuffer) { return false; } @@ -499,7 +501,7 @@ bool GrVkPrimaryCommandBuffer::beginRenderPass(GrVkGpu* gpu, GR_VK_CALL(gpu->vkInterface(), CmdBeginRenderPass(fCmdBuffer, &beginInfo, contents)); fActiveRenderPass = renderPass; this->addResource(renderPass); - target->addResources(*this); + target->addResources(*this, renderPass->hasStencilAttachment()); return true; } diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkGpu.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkGpu.cpp index f2ab8104ac8..6bec1c977e9 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkGpu.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkGpu.cpp @@ -14,6 +14,7 @@ #include "src/core/SkCompressedDataUtils.h" #include "src/core/SkConvertPixels.h" #include "src/core/SkMipMap.h" +#include "src/gpu/GrBackendUtils.h" #include "src/gpu/GrContextPriv.h" #include "src/gpu/GrDataUtils.h" #include "src/gpu/GrGeometryProcessor.h" @@ -241,7 +242,6 @@ void GrVkGpu::destroyResources() { fMainCmdPool->getPrimaryCommandBuffer()->end(this); fMainCmdPool->close(); } - SkASSERT(!fTempCmdPool); // wait for all commands to finish VkResult res = VK_CALL(QueueWaitIdle(fQueue)); @@ -286,9 +286,11 @@ void GrVkGpu::destroyResources() { GrVkGpu::~GrVkGpu() { if (!fDisconnected) { this->destroyResources(); - fMemoryAllocator.reset(); } delete fCompiler; + // We don't delete the memory allocator until the very end of the GrVkGpu lifetime so that + // clients can continue to delete backend textures even after a context has been abandoned. + fMemoryAllocator.reset(); } @@ -296,12 +298,10 @@ void GrVkGpu::disconnect(DisconnectType type) { INHERITED::disconnect(type); if (!fDisconnected) { this->destroyResources(); - fMemoryAllocator.reset(); fSemaphoresToWaitOn.reset(); fSemaphoresToSignal.reset(); fMainCmdBuffer = nullptr; - SkASSERT(!fTempCmdBuffer); fDisconnected = true; } } @@ -309,7 +309,8 @@ void GrVkGpu::disconnect(DisconnectType type) { /////////////////////////////////////////////////////////////////////////////// GrOpsRenderPass* GrVkGpu::getOpsRenderPass( - GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds, + GrRenderTarget* rt, GrStencilAttachment* stencil, + GrSurfaceOrigin origin, const SkIRect& bounds, const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) { @@ -317,49 +318,18 @@ GrOpsRenderPass* GrVkGpu::getOpsRenderPass( fCachedOpsRenderPass.reset(new GrVkOpsRenderPass(this)); } - if (!fCachedOpsRenderPass->set(rt, origin, bounds, colorInfo, stencilInfo, sampledProxies)) { + if (!fCachedOpsRenderPass->set(rt, stencil, origin, bounds, + colorInfo, stencilInfo, sampledProxies)) { return nullptr; } return fCachedOpsRenderPass.get(); } -GrVkPrimaryCommandBuffer* GrVkGpu::getTempCommandBuffer() { - SkASSERT(!fTempCmdPool && !fTempCmdBuffer); - fTempCmdPool = fResourceProvider.findOrCreateCommandPool(); - if (!fTempCmdPool) { - return nullptr; - } - fTempCmdBuffer = fTempCmdPool->getPrimaryCommandBuffer(); - SkASSERT(fTempCmdBuffer); - fTempCmdBuffer->begin(this); - return fTempCmdBuffer; -} - -bool GrVkGpu::submitTempCommandBuffer(SyncQueue sync, sk_sp<GrRefCntedCallback> finishedCallback) { - SkASSERT(fTempCmdBuffer); - - fTempCmdBuffer->end(this); - fTempCmdPool->close(); - - SkASSERT(fMainCmdBuffer->validateNoSharedImageResources(fTempCmdBuffer)); - - fTempCmdBuffer->addFinishedProc(std::move(finishedCallback)); - - SkTArray<GrVkSemaphore::Resource*, false> fEmptySemaphores; - bool didSubmit = fTempCmdBuffer->submitToQueue(this, fQueue, fEmptySemaphores, - fEmptySemaphores); - if (didSubmit && sync == kForce_SyncQueue) { - fTempCmdBuffer->forceSync(this); - } - fTempCmdPool->unref(); - fTempCmdPool = nullptr; - fTempCmdBuffer = nullptr; - return didSubmit; -} - bool GrVkGpu::submitCommandBuffer(SyncQueue sync) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); - SkASSERT(this->currentCommandBuffer()); + if (!this->currentCommandBuffer()) { + return false; + } SkASSERT(!fCachedOpsRenderPass || !fCachedOpsRenderPass->isActive()); if (!this->currentCommandBuffer()->hasWork() && kForce_SyncQueue != sync && @@ -510,6 +480,9 @@ bool GrVkGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt GrColorType surfaceColorType, GrColorType bufferColorType, GrGpuBuffer* transferBuffer, size_t bufferOffset, size_t rowBytes) { + if (!this->currentCommandBuffer()) { + return false; + } if (surfaceColorType != bufferColorType) { return false; } @@ -574,6 +547,9 @@ bool GrVkGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt bool GrVkGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height, GrColorType surfaceColorType, GrColorType bufferColorType, GrGpuBuffer* transferBuffer, size_t offset) { + if (!this->currentCommandBuffer()) { + return false; + } SkASSERT(surface); SkASSERT(transferBuffer); if (fProtectedContext == GrProtected::kYes) { @@ -635,6 +611,10 @@ bool GrVkGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int wi void GrVkGpu::resolveImage(GrSurface* dst, GrVkRenderTarget* src, const SkIRect& srcRect, const SkIPoint& dstPoint) { + if (!this->currentCommandBuffer()) { + return; + } + SkASSERT(dst); SkASSERT(src && src->numSamples() > 1 && src->msaaImage()); @@ -741,10 +721,9 @@ bool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex, int left, int top, int width // 'individualMipOffsets' is filled in as a side-effect. static size_t fill_in_regions(GrVkCaps* vkCaps, SkTArray<VkBufferImageCopy>* regions, SkTArray<size_t>* individualMipOffsets, + SkImage::CompressionType compression, VkFormat vkFormat, SkISize dimensions, GrMipMapped mipMapped, VkDeviceSize bufferOffset) { - SkImage::CompressionType compression = GrVkFormatToCompressionType(vkFormat); - int numMipLevels = 1; if (mipMapped == GrMipMapped::kYes) { numMipLevels = SkMipMap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1; @@ -788,6 +767,10 @@ static size_t fill_in_regions(GrVkCaps* vkCaps, SkTArray<VkBufferImageCopy>* reg bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, int left, int top, int width, int height, GrColorType dataColorType, const GrMipLevel texels[], int mipLevelCount) { + if (!this->currentCommandBuffer()) { + return false; + } + SkASSERT(!tex->isLinearTiled()); // The assumption is either that we have no mipmaps, or that our rect is the entire texture SkASSERT(1 == mipLevelCount || @@ -972,9 +955,13 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, int left, int top, int widt // It's probably possible to roll this into uploadTexDataOptimal, // but for now it's easier to maintain as a separate entity. -bool GrVkGpu::uploadTexDataCompressed(GrVkTexture* uploadTexture, VkFormat vkFormat, +bool GrVkGpu::uploadTexDataCompressed(GrVkTexture* uploadTexture, + SkImage::CompressionType compression, VkFormat vkFormat, SkISize dimensions, GrMipMapped mipMapped, const void* data, size_t dataSize) { + if (!this->currentCommandBuffer()) { + return false; + } SkASSERT(data); SkASSERT(!uploadTexture->isLinearTiled()); // For now the assumption is that our rect is the entire texture. @@ -1009,9 +996,9 @@ bool GrVkGpu::uploadTexDataCompressed(GrVkTexture* uploadTexture, VkFormat vkFor SkTArray<VkBufferImageCopy> regions; SkTArray<size_t> individualMipOffsets; SkDEBUGCODE(size_t combinedBufferSize =) fill_in_regions(fVkCaps.get(), ®ions, - &individualMipOffsets, - vkFormat, dimensions, - mipMapped, bufferOffset); + &individualMipOffsets, compression, + vkFormat, dimensions, mipMapped, + bufferOffset); SkASSERT(dataSize == combinedBufferSize); // Change layout of our target so it can be copied to @@ -1090,6 +1077,9 @@ sk_sp<GrTexture> GrVkGpu::onCreateTexture(SkISize dimensions, } if (levelClearMask) { + if (!this->currentCommandBuffer()) { + return nullptr; + } SkSTArray<1, VkImageSubresourceRange> ranges; bool inRange = false; for (uint32_t i = 0; i < tex->mipLevels(); ++i) { @@ -1165,7 +1155,8 @@ sk_sp<GrTexture> GrVkGpu::onCreateCompressedTexture(SkISize dimensions, return nullptr; } - if (!this->uploadTexDataCompressed(tex.get(), pixelFormat, dimensions, mipMapped, + SkImage::CompressionType compression = GrBackendFormatToCompressionType(format); + if (!this->uploadTexDataCompressed(tex.get(), compression, pixelFormat, dimensions, mipMapped, data, dataSize)) { return nullptr; } @@ -1177,6 +1168,9 @@ sk_sp<GrTexture> GrVkGpu::onCreateCompressedTexture(SkISize dimensions, void GrVkGpu::copyBuffer(GrVkBuffer* srcBuffer, GrVkBuffer* dstBuffer, VkDeviceSize srcOffset, VkDeviceSize dstOffset, VkDeviceSize size) { + if (!this->currentCommandBuffer()) { + return; + } VkBufferCopy copyRegion; copyRegion.srcOffset = srcOffset; copyRegion.dstOffset = dstOffset; @@ -1186,6 +1180,9 @@ void GrVkGpu::copyBuffer(GrVkBuffer* srcBuffer, GrVkBuffer* dstBuffer, VkDeviceS bool GrVkGpu::updateBuffer(GrVkBuffer* buffer, const void* src, VkDeviceSize offset, VkDeviceSize size) { + if (!this->currentCommandBuffer()) { + return false; + } // Update the buffer this->currentCommandBuffer()->updateBuffer(this, buffer, offset, size, src); @@ -1196,7 +1193,8 @@ bool GrVkGpu::updateBuffer(GrVkBuffer* buffer, const void* src, static bool check_image_info(const GrVkCaps& caps, const GrVkImageInfo& info, - bool needsAllocation) { + bool needsAllocation, + uint32_t graphicsQueueIndex) { if (VK_NULL_HANDLE == info.fImage) { return false; } @@ -1209,6 +1207,18 @@ static bool check_image_info(const GrVkCaps& caps, return false; } + if (info.fCurrentQueueFamily != VK_QUEUE_FAMILY_IGNORED && + info.fCurrentQueueFamily != VK_QUEUE_FAMILY_EXTERNAL && + info.fCurrentQueueFamily != VK_QUEUE_FAMILY_FOREIGN_EXT) { + if (info.fSharingMode == VK_SHARING_MODE_EXCLUSIVE) { + if (info.fCurrentQueueFamily != graphicsQueueIndex) { + return false; + } + } else { + return false; + } + } + if (info.fYcbcrConversionInfo.isValid()) { if (!caps.supportsYcbcrConversion()) { return false; @@ -1254,7 +1264,8 @@ sk_sp<GrTexture> GrVkGpu::onWrapBackendTexture(const GrBackendTexture& backendTe return nullptr; } - if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership)) { + if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership, + this->queueIndex())) { return nullptr; } @@ -1266,10 +1277,10 @@ sk_sp<GrTexture> GrVkGpu::onWrapBackendTexture(const GrBackendTexture& backendTe return nullptr; } - sk_sp<GrVkImageLayout> layout = backendTex.getGrVkImageLayout(); - SkASSERT(layout); + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = backendTex.getMutableState(); + SkASSERT(mutableState); return GrVkTexture::MakeWrappedTexture(this, backendTex.dimensions(), ownership, cacheable, - ioType, imageInfo, std::move(layout)); + ioType, imageInfo, std::move(mutableState)); } sk_sp<GrTexture> GrVkGpu::onWrapCompressedBackendTexture(const GrBackendTexture& beTex, @@ -1280,7 +1291,8 @@ sk_sp<GrTexture> GrVkGpu::onWrapCompressedBackendTexture(const GrBackendTexture& return nullptr; } - if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership)) { + if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership, + this->queueIndex())) { return nullptr; } @@ -1292,10 +1304,10 @@ sk_sp<GrTexture> GrVkGpu::onWrapCompressedBackendTexture(const GrBackendTexture& return nullptr; } - sk_sp<GrVkImageLayout> layout = beTex.getGrVkImageLayout(); - SkASSERT(layout); + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = beTex.getMutableState(); + SkASSERT(mutableState); return GrVkTexture::MakeWrappedTexture(this, beTex.dimensions(), ownership, cacheable, - kRead_GrIOType, imageInfo, std::move(layout)); + kRead_GrIOType, imageInfo, std::move(mutableState)); } sk_sp<GrTexture> GrVkGpu::onWrapRenderableBackendTexture(const GrBackendTexture& backendTex, @@ -1307,7 +1319,8 @@ sk_sp<GrTexture> GrVkGpu::onWrapRenderableBackendTexture(const GrBackendTexture& return nullptr; } - if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership)) { + if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership, + this->queueIndex())) { return nullptr; } @@ -1324,12 +1337,13 @@ sk_sp<GrTexture> GrVkGpu::onWrapRenderableBackendTexture(const GrBackendTexture& sampleCnt = this->vkCaps().getRenderTargetSampleCount(sampleCnt, imageInfo.fFormat); - sk_sp<GrVkImageLayout> layout = backendTex.getGrVkImageLayout(); - SkASSERT(layout); + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = backendTex.getMutableState(); + SkASSERT(mutableState); return GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(this, backendTex.dimensions(), sampleCnt, ownership, cacheable, - imageInfo, std::move(layout)); + imageInfo, + std::move(mutableState)); } sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) { @@ -1346,7 +1360,7 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTa return nullptr; } - if (!check_image_info(this->vkCaps(), info, false)) { + if (!check_image_info(this->vkCaps(), info, false, this->queueIndex())) { return nullptr; } @@ -1358,10 +1372,11 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTa return nullptr; } - sk_sp<GrVkImageLayout> layout = backendRT.getGrVkImageLayout(); + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = backendRT.getMutableState(); + SkASSERT(mutableState); sk_sp<GrVkRenderTarget> tgt = GrVkRenderTarget::MakeWrappedRenderTarget( - this, backendRT.dimensions(), 1, info, std::move(layout)); + this, backendRT.dimensions(), 1, info, std::move(mutableState)); // We don't allow the client to supply a premade stencil buffer. We always create one if needed. SkASSERT(!backendRT.stencilBits()); @@ -1378,7 +1393,7 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendTextureAsRenderTarget(const GrBacken if (!tex.getVkImageInfo(&imageInfo)) { return nullptr; } - if (!check_image_info(this->vkCaps(), imageInfo, false)) { + if (!check_image_info(this->vkCaps(), imageInfo, false, this->queueIndex())) { return nullptr; } @@ -1395,11 +1410,11 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendTextureAsRenderTarget(const GrBacken return nullptr; } - sk_sp<GrVkImageLayout> layout = tex.getGrVkImageLayout(); - SkASSERT(layout); + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = tex.getMutableState(); + SkASSERT(mutableState); return GrVkRenderTarget::MakeWrappedRenderTarget(this, tex.dimensions(), sampleCnt, imageInfo, - std::move(layout)); + std::move(mutableState)); } sk_sp<GrRenderTarget> GrVkGpu::onWrapVulkanSecondaryCBAsRenderTarget( @@ -1422,6 +1437,9 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapVulkanSecondaryCBAsRenderTarget( } bool GrVkGpu::onRegenerateMipMapLevels(GrTexture* tex) { + if (!this->currentCommandBuffer()) { + return false; + } auto* vkTex = static_cast<GrVkTexture*>(tex); // don't do anything for linearly tiled textures (can't have mipmaps) if (vkTex->isLinearTiled()) { @@ -1628,17 +1646,17 @@ bool GrVkGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture, GrVkImageInfo info; SkAssertResult(backendTexture.getVkImageInfo(&info)); - sk_sp<GrVkImageLayout> layout = backendTexture.getGrVkImageLayout(); - SkASSERT(layout); + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = backendTexture.getMutableState(); + SkASSERT(mutableState); sk_sp<GrVkTexture> texture = GrVkTexture::MakeWrappedTexture(this, backendTexture.dimensions(), kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, - kRW_GrIOType, info, layout); + kRW_GrIOType, info, std::move(mutableState)); if (!texture) { return false; } - GrVkPrimaryCommandBuffer* cmdBuffer = this->getTempCommandBuffer(); + GrVkPrimaryCommandBuffer* cmdBuffer = this->currentCommandBuffer(); if (!cmdBuffer) { return false; } @@ -1668,10 +1686,14 @@ bool GrVkGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture, range.levelCount = info.fLevelCount; cmdBuffer->clearColorImage(this, texture.get(), &vkColor, 1, &range); } else { + SkImage::CompressionType compression = GrBackendFormatToCompressionType( + backendTexture.getBackendFormat()); + SkTArray<VkBufferImageCopy> regions; SkTArray<size_t> individualMipOffsets; size_t combinedBufferSize = fill_in_regions(fVkCaps.get(), ®ions, &individualMipOffsets, - info.fFormat, backendTexture.dimensions(), + compression, info.fFormat, + backendTexture.dimensions(), backendTexture.fMipMapped, 0); sk_sp<GrVkTransferBuffer> transferBuffer = @@ -1689,8 +1711,6 @@ bool GrVkGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture, data->compressedData(), data->compressedSize()); } else { SkASSERT(data->type() == BackendTextureData::Type::kColor); - SkImage::CompressionType compression = GrVkFormatToCompressionType(info.fFormat); - result = generate_compressed_data(this, (char*)transferBuffer->map(), compression, backendTexture.dimensions(), backendTexture.fMipMapped, data->color()); @@ -1707,7 +1727,10 @@ bool GrVkGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, false); - return this->submitTempCommandBuffer(kSkip_SyncQueue, std::move(finishedCallback)); + if (finishedCallback) { + this->addFinishedCallback(std::move(finishedCallback)); + } + return true; } GrBackendTexture GrVkGpu::onCreateBackendTexture(SkISize dimensions, @@ -1791,6 +1814,56 @@ GrBackendTexture GrVkGpu::onCreateCompressedBackendTexture( return beTex; } +void set_layout_and_queue_from_mutable_state(GrVkGpu* gpu, GrVkImage* image, + const GrVkSharedImageInfo& newInfo) { + // Even though internally we use this helper for getting src access flags and stages they + // can also be used for general dst flags since we don't know exactly what the client + // plans on using the image for. + VkImageLayout newLayout = newInfo.getImageLayout(); + VkPipelineStageFlags dstStage = GrVkImage::LayoutToPipelineSrcStageFlags(newLayout); + VkAccessFlags dstAccess = GrVkImage::LayoutToSrcAccessMask(newLayout); + image->setImageLayoutAndQueueIndex(gpu, newLayout, dstAccess, dstStage, false, + newInfo.getQueueFamilyIndex()); +} + +bool GrVkGpu::setBackendSurfaceState(GrVkImageInfo info, + sk_sp<GrBackendSurfaceMutableStateImpl> currentState, + SkISize dimensions, + const GrVkSharedImageInfo& newInfo) { + sk_sp<GrVkTexture> texture = GrVkTexture::MakeWrappedTexture( + this, dimensions, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType, info, + std::move(currentState)); + SkASSERT(texture); + if (!texture) { + return false; + } + set_layout_and_queue_from_mutable_state(this, texture.get(), newInfo); + return true; +} + +bool GrVkGpu::setBackendTextureState(const GrBackendTexture& backendTeture, + const GrBackendSurfaceMutableState& newState, + sk_sp<GrRefCntedCallback> finishedCallback) { + GrVkImageInfo info; + SkAssertResult(backendTeture.getVkImageInfo(&info)); + sk_sp<GrBackendSurfaceMutableStateImpl> currentState = backendTeture.getMutableState(); + SkASSERT(currentState); + SkASSERT(newState.fBackend == GrBackend::kVulkan); + return this->setBackendSurfaceState(info, std::move(currentState), backendTeture.dimensions(), + newState.fVkState); +} + +bool GrVkGpu::setBackendRenderTargetState(const GrBackendRenderTarget& backendRenderTarget, + const GrBackendSurfaceMutableState& newState, + sk_sp<GrRefCntedCallback> finishedCallback) { + GrVkImageInfo info; + SkAssertResult(backendRenderTarget.getVkImageInfo(&info)); + sk_sp<GrBackendSurfaceMutableStateImpl> currentState = backendRenderTarget.getMutableState(); + SkASSERT(currentState); + SkASSERT(newState.fBackend == GrBackend::kVulkan); + return this->setBackendSurfaceState(info, std::move(currentState), + backendRenderTarget.dimensions(), newState.fVkState); +} void GrVkGpu::querySampleLocations(GrRenderTarget* renderTarget, SkTArray<SkPoint>* sampleLocations) { @@ -1923,7 +1996,9 @@ void GrVkGpu::addBufferMemoryBarrier(const GrManagedResource* resource, VkPipelineStageFlags dstStageMask, bool byRegion, VkBufferMemoryBarrier* barrier) const { - SkASSERT(this->currentCommandBuffer()); + if (!this->currentCommandBuffer()) { + return; + } SkASSERT(resource); this->currentCommandBuffer()->pipelineBarrier(this, resource, @@ -1956,14 +2031,16 @@ void GrVkGpu::addImageMemoryBarrier(const GrManagedResource* resource, barrier); } -void GrVkGpu::prepareSurfacesForBackendAccessAndExternalIO( - GrSurfaceProxy* proxies[], int numProxies, SkSurface::BackendSurfaceAccess access, - const GrPrepareForExternalIORequests& externalRequests) { +void GrVkGpu::prepareSurfacesForBackendAccessAndStateUpdates( + GrSurfaceProxy* proxies[], + int numProxies, + SkSurface::BackendSurfaceAccess access, + const GrBackendSurfaceMutableState* newState) { SkASSERT(numProxies >= 0); SkASSERT(!numProxies || proxies); // Submit the current command buffer to the Queue. Whether we inserted semaphores or not does // not effect what we do here. - if (numProxies && access == SkSurface::BackendSurfaceAccess::kPresent) { + if (numProxies && (access == SkSurface::BackendSurfaceAccess::kPresent || newState)) { GrVkImage* image; for (int i = 0; i < numProxies; ++i) { SkASSERT(proxies[i]->isInstantiated()); @@ -1974,57 +2051,11 @@ void GrVkGpu::prepareSurfacesForBackendAccessAndExternalIO( SkASSERT(rt); image = static_cast<GrVkRenderTarget*>(rt); } - image->prepareForPresent(this); - } - } - - // Handle requests for preparing for external IO - for (int i = 0; i < externalRequests.fNumImages; ++i) { - SkImage* image = externalRequests.fImages[i]; - if (!image->isTextureBacked()) { - continue; - } - SkImage_GpuBase* gpuImage = static_cast<SkImage_GpuBase*>(as_IB(image)); - const GrSurfaceProxyView* view = gpuImage->view(this->getContext()); - SkASSERT(view && *view); - - if (!view->proxy()->isInstantiated()) { - auto resourceProvider = this->getContext()->priv().resourceProvider(); - if (!view->proxy()->instantiate(resourceProvider)) { - continue; - } - } - - GrTexture* tex = view->proxy()->peekTexture(); - if (!tex) { - continue; - } - GrVkTexture* vkTex = static_cast<GrVkTexture*>(tex); - vkTex->prepareForExternal(this); - } - for (int i = 0; i < externalRequests.fNumSurfaces; ++i) { - SkSurface* surface = externalRequests.fSurfaces[i]; - if (!surface->getCanvas()->getGrContext()) { - continue; - } - SkSurface_Gpu* gpuSurface = static_cast<SkSurface_Gpu*>(surface); - auto* rtc = gpuSurface->getDevice()->accessRenderTargetContext(); - sk_sp<GrRenderTargetProxy> proxy = rtc->asRenderTargetProxyRef(); - if (!proxy->isInstantiated()) { - auto resourceProvider = this->getContext()->priv().resourceProvider(); - if (!proxy->instantiate(resourceProvider)) { - continue; + if (newState) { + const GrVkSharedImageInfo& newInfo = newState->fVkState; + set_layout_and_queue_from_mutable_state(this, image, newInfo); } - } - - GrRenderTarget* rt = proxy->peekRenderTarget(); - SkASSERT(rt); - GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt); - if (externalRequests.fPrepareSurfaceForPresent && - externalRequests.fPrepareSurfaceForPresent[i]) { - vkRT->prepareForPresent(this); - } else { - vkRT->prepareForExternal(this); + image->prepareForPresent(this); } } } @@ -2032,7 +2063,14 @@ void GrVkGpu::prepareSurfacesForBackendAccessAndExternalIO( void GrVkGpu::addFinishedProc(GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) { SkASSERT(finishedProc); - fResourceProvider.addFinishedProcToActiveCommandBuffers(finishedProc, finishedContext); + sk_sp<GrRefCntedCallback> finishedCallback( + new GrRefCntedCallback(finishedProc, finishedContext)); + this->addFinishedCallback(std::move(finishedCallback)); +} + +void GrVkGpu::addFinishedCallback(sk_sp<GrRefCntedCallback> finishedCallback) { + SkASSERT(finishedCallback); + fResourceProvider.addFinishedProcToActiveCommandBuffers(std::move(finishedCallback)); } bool GrVkGpu::onSubmitToGpu(bool syncCpu) { @@ -2053,6 +2091,10 @@ static int get_surface_sample_cnt(GrSurface* surf) { void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst, GrSurface* src, GrVkImage* dstImage, GrVkImage* srcImage, const SkIRect& srcRect, const SkIPoint& dstPoint) { + if (!this->currentCommandBuffer()) { + return; + } + #ifdef SK_DEBUG int dstSampleCnt = get_surface_sample_cnt(dst); int srcSampleCnt = get_surface_sample_cnt(src); @@ -2108,6 +2150,10 @@ void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst, GrSurface* src, GrVkImage* void GrVkGpu::copySurfaceAsBlit(GrSurface* dst, GrSurface* src, GrVkImage* dstImage, GrVkImage* srcImage, const SkIRect& srcRect, const SkIPoint& dstPoint) { + if (!this->currentCommandBuffer()) { + return; + } + #ifdef SK_DEBUG int dstSampleCnt = get_surface_sample_cnt(dst); int srcSampleCnt = get_surface_sample_cnt(src); @@ -2255,6 +2301,10 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int return false; } + if (!this->currentCommandBuffer()) { + return false; + } + GrVkImage* image = nullptr; GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(surface->asRenderTarget()); if (rt) { @@ -2443,6 +2493,9 @@ bool GrVkGpu::beginRenderPass(const GrVkRenderPass* renderPass, const VkClearValue* colorClear, GrVkRenderTarget* target, GrSurfaceOrigin origin, const SkIRect& bounds, bool forSecondaryCB) { + if (!this->currentCommandBuffer()) { + return false; + } SkASSERT (!target->wrapsSecondaryCommandBuffer()); auto nativeBounds = GrNativeRect::MakeRelativeTo(origin, target->height(), bounds); @@ -2478,11 +2531,16 @@ bool GrVkGpu::beginRenderPass(const GrVkRenderPass* renderPass, void GrVkGpu::endRenderPass(GrRenderTarget* target, GrSurfaceOrigin origin, const SkIRect& bounds) { + // We had a command buffer when we started the render pass, we should have one now as well. + SkASSERT(this->currentCommandBuffer()); this->currentCommandBuffer()->endRenderPass(this); this->didWriteToSurface(target, origin, &bounds); } void GrVkGpu::submitSecondaryCommandBuffer(std::unique_ptr<GrVkSecondaryCommandBuffer> buffer) { + if (!this->currentCommandBuffer()) { + return; + } this->currentCommandBuffer()->executeCommands(this, std::move(buffer)); } @@ -2540,6 +2598,8 @@ std::unique_ptr<GrSemaphore> GrVkGpu::wrapBackendSemaphore( } void GrVkGpu::insertSemaphore(GrSemaphore* semaphore) { + SkASSERT(semaphore); + GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore); GrVkSemaphore::Resource* resource = vkSem->getResource(); @@ -2550,6 +2610,8 @@ void GrVkGpu::insertSemaphore(GrSemaphore* semaphore) { } void GrVkGpu::waitSemaphore(GrSemaphore* semaphore) { + SkASSERT(semaphore); + GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore); GrVkSemaphore::Resource* resource = vkSem->getResource(); diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkGpu.h b/chromium/third_party/skia/src/gpu/vk/GrVkGpu.h index be7a03c12d0..312792ba9d4 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkGpu.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkGpu.h @@ -56,9 +56,7 @@ public: VkDevice device() const { return fDevice; } VkQueue queue() const { return fQueue; } uint32_t queueIndex() const { return fQueueIndex; } - GrVkCommandPool* cmdPool() const { - return fTempCmdPool ? fTempCmdPool : fMainCmdPool; - } + GrVkCommandPool* cmdPool() const { return fMainCmdPool; } const VkPhysicalDeviceProperties& physicalDeviceProperties() const { return fPhysDevProps; } @@ -69,14 +67,20 @@ public: GrVkResourceProvider& resourceProvider() { return fResourceProvider; } - GrVkPrimaryCommandBuffer* currentCommandBuffer() const { - return fTempCmdBuffer ? fTempCmdBuffer : fMainCmdBuffer; - } + GrVkPrimaryCommandBuffer* currentCommandBuffer() const { return fMainCmdBuffer; } void querySampleLocations(GrRenderTarget*, SkTArray<SkPoint>*) override; void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {} + bool setBackendTextureState(const GrBackendTexture&, + const GrBackendSurfaceMutableState&, + sk_sp<GrRefCntedCallback> finishedCallback) override; + + bool setBackendRenderTargetState(const GrBackendRenderTarget&, + const GrBackendSurfaceMutableState&, + sk_sp<GrRefCntedCallback> finishedCallback) override; + void deleteBackendTexture(const GrBackendTexture&) override; bool compile(const GrProgramDesc&, const GrProgramInfo&) override; @@ -98,7 +102,8 @@ public: const GrRenderTarget*, int width, int height, int numStencilSamples) override; GrOpsRenderPass* getOpsRenderPass( - GrRenderTarget*, GrSurfaceOrigin, const SkIRect&, + GrRenderTarget*, GrStencilAttachment*, + GrSurfaceOrigin, const SkIRect&, const GrOpsRenderPass::LoadAndStoreInfo&, const GrOpsRenderPass::StencilLoadAndStoreInfo&, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override; @@ -166,6 +171,8 @@ public: const SkIRect& bounds, bool forSecondaryCB); void endRenderPass(GrRenderTarget* target, GrSurfaceOrigin origin, const SkIRect& bounds); + using GrGpu::setOOMed; + private: enum SyncQueue { kForce_SyncQueue, @@ -196,6 +203,11 @@ private: sk_sp<GrRefCntedCallback> finishedCallback, const BackendTextureData*) override; + bool setBackendSurfaceState(GrVkImageInfo info, + sk_sp<GrBackendSurfaceMutableStateImpl> currentState, + SkISize dimensions, + const GrVkSharedImageInfo& newInfo); + sk_sp<GrTexture> onCreateTexture(SkISize, const GrBackendFormat&, GrRenderable, @@ -255,9 +267,13 @@ private: void addFinishedProc(GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) override; - void prepareSurfacesForBackendAccessAndExternalIO( - GrSurfaceProxy* proxies[], int numProxies, SkSurface::BackendSurfaceAccess access, - const GrPrepareForExternalIORequests& externalRequests) override; + void addFinishedCallback(sk_sp<GrRefCntedCallback> finishedCallback); + + void prepareSurfacesForBackendAccessAndStateUpdates( + GrSurfaceProxy* proxies[], + int numProxies, + SkSurface::BackendSurfaceAccess access, + const GrBackendSurfaceMutableState* newState) override; bool onSubmitToGpu(bool syncCpu) override; @@ -284,8 +300,9 @@ private: GrColorType colorType, const void* data, size_t rowBytes); bool uploadTexDataOptimal(GrVkTexture* tex, int left, int top, int width, int height, GrColorType colorType, const GrMipLevel texels[], int mipLevelCount); - bool uploadTexDataCompressed(GrVkTexture* tex, VkFormat vkFormat, SkISize dimensions, - GrMipMapped mipMapped, const void* data, size_t dataSize); + bool uploadTexDataCompressed(GrVkTexture* tex, SkImage::CompressionType compression, + VkFormat vkFormat, SkISize dimensions, GrMipMapped mipMapped, + const void* data, size_t dataSize); void resolveImage(GrSurface* dst, GrVkRenderTarget* src, const SkIRect& srcRect, const SkIPoint& dstPoint); @@ -297,18 +314,6 @@ private: GrVkImageInfo*, GrProtected); - // Creates a new temporary primary command buffer that will be target of all subsequent commands - // until it is submitted via submitTempCommandBuffer. When the temp command buffer gets - // submitted the main command buffer will begin being the target of commands again. When using a - // a temp command buffer, the caller should not use any resources that may have been used by the - // unsubmitted main command buffer. The reason for this is we've already updated state, like - // image layout, for the resources on the main command buffer even though we haven't submitted - // it yet. Thus if the same resource gets used on the temp our tracking will get thosse state - // updates out of order. It is legal to use a resource on either the temp or main command buffer - // that was used on a previously submitted command buffer; - GrVkPrimaryCommandBuffer* getTempCommandBuffer(); - bool submitTempCommandBuffer(SyncQueue sync, sk_sp<GrRefCntedCallback> finishedCallback); - sk_sp<const GrVkInterface> fInterface; sk_sp<GrVkMemoryAllocator> fMemoryAllocator; sk_sp<GrVkCaps> fVkCaps; @@ -326,10 +331,6 @@ private: // just a raw pointer; object's lifespan is managed by fCmdPool GrVkPrimaryCommandBuffer* fMainCmdBuffer; - GrVkCommandPool* fTempCmdPool = nullptr; - // just a raw pointer; object's lifespan is managed by fCmdPool - GrVkPrimaryCommandBuffer* fTempCmdBuffer = nullptr; - SkSTArray<1, GrVkSemaphore::Resource*> fSemaphoresToWaitOn; SkSTArray<1, GrVkSemaphore::Resource*> fSemaphoresToSignal; diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkImage.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkImage.cpp index 5022f1c54d0..98b24db5b0d 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkImage.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkImage.cpp @@ -13,6 +13,43 @@ #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X) +GrVkImage::GrVkImage(const GrVkGpu* gpu, + const GrVkImageInfo& info, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, + GrBackendObjectOwnership ownership, + bool forSecondaryCB) + : fInfo(info) + , fInitialQueueFamily(info.fCurrentQueueFamily) + , fMutableState(std::move(mutableState)) + , fIsBorrowed(GrBackendObjectOwnership::kBorrowed == ownership) { + SkASSERT(fMutableState->getImageLayout() == fInfo.fImageLayout); + SkASSERT(fMutableState->getQueueFamilyIndex() == fInfo.fCurrentQueueFamily); +#ifdef SK_DEBUG + // We can't transfer from the non graphics queue to the graphics queue since we can't + // release the image from the original queue without having that queue. This limits us in terms + // of the types of queue indices we can handle. + if (info.fCurrentQueueFamily != VK_QUEUE_FAMILY_IGNORED && + info.fCurrentQueueFamily != VK_QUEUE_FAMILY_EXTERNAL && + info.fCurrentQueueFamily != VK_QUEUE_FAMILY_FOREIGN_EXT) { + if (info.fSharingMode == VK_SHARING_MODE_EXCLUSIVE) { + if (info.fCurrentQueueFamily != gpu->queueIndex()) { + SkASSERT(false); + } + } else { + SkASSERT(false); + } + } +#endif + if (forSecondaryCB) { + fResource = nullptr; + } else if (fIsBorrowed) { + fResource = new BorrowedResource(gpu, info.fImage, info.fAlloc, info.fImageTiling); + } else { + SkASSERT(VK_NULL_HANDLE != info.fAlloc.fMemory); + fResource = new Resource(gpu, info.fImage, info.fAlloc, info.fImageTiling); + } +} + VkPipelineStageFlags GrVkImage::LayoutToPipelineSrcStageFlags(const VkImageLayout layout) { if (VK_IMAGE_LAYOUT_GENERAL == layout) { return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; @@ -82,26 +119,58 @@ VkImageAspectFlags vk_format_to_aspect_flags(VkFormat format) { } } -void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout, - VkAccessFlags dstAccessMask, - VkPipelineStageFlags dstStageMask, - bool byRegion, bool releaseFamilyQueue) { +void GrVkImage::setImageLayoutAndQueueIndex(const GrVkGpu* gpu, + VkImageLayout newLayout, + VkAccessFlags dstAccessMask, + VkPipelineStageFlags dstStageMask, + bool byRegion, + uint32_t newQueueFamilyIndex) { SkASSERT(!gpu->isDeviceLost()); - SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED != newLayout && - VK_IMAGE_LAYOUT_PREINITIALIZED != newLayout); + SkASSERT(newLayout == this->currentLayout() || + (VK_IMAGE_LAYOUT_UNDEFINED != newLayout && + VK_IMAGE_LAYOUT_PREINITIALIZED != newLayout)); VkImageLayout currentLayout = this->currentLayout(); + uint32_t currentQueueIndex = this->currentQueueFamilyIndex(); + +#ifdef SK_DEBUG + if (fInfo.fSharingMode == VK_SHARING_MODE_CONCURRENT) { + if (newQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED) { + SkASSERT(currentQueueIndex == VK_QUEUE_FAMILY_IGNORED || + currentQueueIndex == VK_QUEUE_FAMILY_EXTERNAL || + currentQueueIndex == VK_QUEUE_FAMILY_FOREIGN_EXT); + } else { + SkASSERT(newQueueFamilyIndex == VK_QUEUE_FAMILY_EXTERNAL || + newQueueFamilyIndex == VK_QUEUE_FAMILY_FOREIGN_EXT); + SkASSERT(currentQueueIndex == VK_QUEUE_FAMILY_IGNORED); + } + } else { + SkASSERT(fInfo.fSharingMode == VK_SHARING_MODE_EXCLUSIVE); + if (newQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED || + currentQueueIndex == gpu->queueIndex()) { + SkASSERT(currentQueueIndex == VK_QUEUE_FAMILY_IGNORED || + currentQueueIndex == VK_QUEUE_FAMILY_EXTERNAL || + currentQueueIndex == VK_QUEUE_FAMILY_FOREIGN_EXT || + currentQueueIndex == gpu->queueIndex()); + } else if (newQueueFamilyIndex == VK_QUEUE_FAMILY_EXTERNAL || + newQueueFamilyIndex == VK_QUEUE_FAMILY_FOREIGN_EXT) { + SkASSERT(currentQueueIndex == VK_QUEUE_FAMILY_IGNORED || + currentQueueIndex == gpu->queueIndex()); + } + } +#endif - if (releaseFamilyQueue && fInfo.fCurrentQueueFamily == fInitialQueueFamily && - newLayout == currentLayout) { - // We never transfered the image to this queue and we are releasing it so don't do anything. - return; + if (fInfo.fSharingMode == VK_SHARING_MODE_EXCLUSIVE) { + if (newQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED) { + newQueueFamilyIndex = gpu->queueIndex(); + } + if (currentQueueIndex == VK_QUEUE_FAMILY_IGNORED) { + currentQueueIndex = gpu->queueIndex(); + } } // If the old and new layout are the same and the layout is a read only layout, there is no need // to put in a barrier unless we also need to switch queues. - if (newLayout == currentLayout && !releaseFamilyQueue && - (fInfo.fCurrentQueueFamily == VK_QUEUE_FAMILY_IGNORED || - fInfo.fCurrentQueueFamily == gpu->queueIndex()) && + if (newLayout == currentLayout && currentQueueIndex == newQueueFamilyIndex && (VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL == currentLayout || VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == currentLayout || VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == currentLayout)) { @@ -113,26 +182,6 @@ void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout, VkImageAspectFlags aspectFlags = vk_format_to_aspect_flags(fInfo.fFormat); - uint32_t srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - uint32_t dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - if (fInfo.fCurrentQueueFamily != VK_QUEUE_FAMILY_IGNORED && - gpu->queueIndex() != fInfo.fCurrentQueueFamily) { - // The image still is owned by its original queue family and we need to transfer it into - // ours. - SkASSERT(!releaseFamilyQueue); - SkASSERT(fInfo.fCurrentQueueFamily == fInitialQueueFamily); - - srcQueueFamilyIndex = fInfo.fCurrentQueueFamily; - dstQueueFamilyIndex = gpu->queueIndex(); - fInfo.fCurrentQueueFamily = gpu->queueIndex(); - } else if (releaseFamilyQueue) { - // We are releasing the image so we must transfer the image back to its original queue - // family. - srcQueueFamilyIndex = fInfo.fCurrentQueueFamily; - dstQueueFamilyIndex = fInitialQueueFamily; - fInfo.fCurrentQueueFamily = fInitialQueueFamily; - } - VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType nullptr, // pNext @@ -140,8 +189,8 @@ void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout, dstAccessMask, // dstAccessMask currentLayout, // oldLayout newLayout, // newLayout - srcQueueFamilyIndex, // srcQueueFamilyIndex - dstQueueFamilyIndex, // dstQueueFamilyIndex + currentQueueIndex, // srcQueueFamilyIndex + newQueueFamilyIndex, // dstQueueFamilyIndex fInfo.fImage, // image { aspectFlags, 0, fInfo.fLevelCount, 0, 1 } // subresourceRange }; @@ -150,6 +199,7 @@ void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout, &imageMemoryBarrier); this->updateImageLayout(newLayout); + this->setQueueFamilyIndex(newQueueFamilyIndex); } bool GrVkImage::InitImageInfo(GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo* info) { @@ -217,6 +267,7 @@ bool GrVkImage::InitImageInfo(GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImag info->fCurrentQueueFamily = VK_QUEUE_FAMILY_IGNORED; info->fProtected = (createflags & VK_IMAGE_CREATE_PROTECTED_BIT) ? GrProtected::kYes : GrProtected::kNo; + info->fSharingMode = VK_SHARING_MODE_EXCLUSIVE; return true; } @@ -239,24 +290,17 @@ void GrVkImage::prepareForPresent(GrVkGpu* gpu) { layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; } } - this->setImageLayout(gpu, layout, 0, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, false, true); + this->setImageLayoutAndQueueIndex(gpu, layout, 0, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, false, + fInitialQueueFamily); } void GrVkImage::prepareForExternal(GrVkGpu* gpu) { - this->setImageLayout(gpu, this->currentLayout(), 0, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, false, - true); + this->setImageLayoutAndQueueIndex(gpu, this->currentLayout(), 0, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, false, + fInitialQueueFamily); } -void GrVkImage::releaseImage(GrVkGpu* gpu) { - if (!gpu->isDeviceLost() && fInfo.fCurrentQueueFamily != fInitialQueueFamily) { - // The Vulkan spec is vague on what to put for the dstStageMask here. The spec for image - // memory barrier says the dstStageMask must not be zero. However, in the spec when it talks - // about family queue transfers it says the dstStageMask is ignored and should be set to - // zero. Assuming it really is ignored we set it to VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT here - // since it makes the Vulkan validation layers happy. - this->setImageLayout(gpu, this->currentLayout(), 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - false, true); - } +void GrVkImage::releaseImage() { if (fResource) { fResource->removeOwningTexture(); fResource->unref(); @@ -283,7 +327,7 @@ void GrVkImage::BorrowedResource::freeGPUData() const { #if GR_TEST_UTILS void GrVkImage::setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu) { - fInfo.fCurrentQueueFamily = gpu->queueIndex(); + fMutableState->setQueueFamilyIndex(gpu->queueIndex()); } #endif diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkImage.h b/chromium/third_party/skia/src/gpu/vk/GrVkImage.h index fbd15767569..dc4d0531563 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkImage.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkImage.h @@ -12,9 +12,10 @@ #include "include/gpu/GrBackendSurface.h" #include "include/gpu/vk/GrVkTypes.h" #include "include/private/GrTypesPriv.h" +#include "include/private/GrVkTypesPriv.h" +#include "src/gpu/GrBackendSurfaceMutableStateImpl.h" #include "src/gpu/GrManagedResource.h" #include "src/gpu/GrTexture.h" -#include "src/gpu/vk/GrVkImageLayout.h" class GrVkGpu; class GrVkTexture; @@ -24,22 +25,12 @@ private: class Resource; public: - GrVkImage(const GrVkGpu* gpu, const GrVkImageInfo& info, sk_sp<GrVkImageLayout> layout, - GrBackendObjectOwnership ownership, bool forSecondaryCB = false) - : fInfo(info) - , fInitialQueueFamily(info.fCurrentQueueFamily) - , fLayout(std::move(layout)) - , fIsBorrowed(GrBackendObjectOwnership::kBorrowed == ownership) { - SkASSERT(fLayout->getImageLayout() == fInfo.fImageLayout); - if (forSecondaryCB) { - fResource = nullptr; - } else if (fIsBorrowed) { - fResource = new BorrowedResource(gpu, info.fImage, info.fAlloc, info.fImageTiling); - } else { - SkASSERT(VK_NULL_HANDLE != info.fAlloc.fMemory); - fResource = new Resource(gpu, info.fImage, info.fAlloc, info.fImageTiling); - } - } + GrVkImage(const GrVkGpu* gpu, + const GrVkImageInfo& info, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, + GrBackendObjectOwnership ownership, + bool forSecondaryCB = false); + virtual ~GrVkImage(); VkImage image() const { @@ -82,18 +73,31 @@ public: } bool isBorrowed() const { return fIsBorrowed; } - sk_sp<GrVkImageLayout> grVkImageLayout() const { return fLayout; } + sk_sp<GrBackendSurfaceMutableStateImpl> getMutableState() const { return fMutableState; } - VkImageLayout currentLayout() const { - return fLayout->getImageLayout(); - } + VkImageLayout currentLayout() const { return fMutableState->getImageLayout(); } + + void setImageLayoutAndQueueIndex(const GrVkGpu* gpu, + VkImageLayout newLayout, + VkAccessFlags dstAccessMask, + VkPipelineStageFlags dstStageMask, + bool byRegion, + uint32_t newQueueFamilyIndex); void setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout, VkAccessFlags dstAccessMask, VkPipelineStageFlags dstStageMask, - bool byRegion, - bool releaseFamilyQueue = false); + bool byRegion) { + this->setImageLayoutAndQueueIndex(gpu, newLayout, dstAccessMask, dstStageMask, byRegion, + VK_QUEUE_FAMILY_IGNORED); + } + + uint32_t currentQueueFamilyIndex() const { return fMutableState->getQueueFamilyIndex(); } + + void setQueueFamilyIndex(uint32_t queueFamilyIndex) { + fMutableState->setQueueFamilyIndex(queueFamilyIndex); + } // Returns the image to its original queue family and changes the layout to present if the queue // family is not external or foreign. @@ -109,7 +113,7 @@ public: // Should only be called when we have a real fResource object, i.e. never when being used as // a RT in an external secondary command buffer. SkASSERT(fResource); - fLayout->setImageLayout(newLayout); + fMutableState->setImageLayout(newLayout); } struct ImageDesc { @@ -156,13 +160,13 @@ public: #endif protected: - void releaseImage(GrVkGpu* gpu); + void releaseImage(); bool hasResource() const { return fResource; } - GrVkImageInfo fInfo; - uint32_t fInitialQueueFamily; - sk_sp<GrVkImageLayout> fLayout; - bool fIsBorrowed; + GrVkImageInfo fInfo; + uint32_t fInitialQueueFamily; + sk_sp<GrBackendSurfaceMutableStateImpl> fMutableState; + bool fIsBorrowed; private: class Resource : public GrTextureResource { diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkMemory.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkMemory.cpp index ff07d3ba0a2..08cee6e3462 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkMemory.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkMemory.cpp @@ -31,6 +31,16 @@ static BufferUsage get_buffer_usage(GrVkBuffer::Type type, bool dynamic) { SK_ABORT("Invalid GrVkBuffer::Type"); } +static bool check_result(GrVkGpu* gpu, VkResult result) { + if (result != VK_SUCCESS) { + if (result == VK_ERROR_DEVICE_LOST) { + gpu->setDeviceLost(); + } + return false; + } + return true; +} + bool GrVkMemory::AllocAndBindBufferMemory(GrVkGpu* gpu, VkBuffer buffer, GrVkBuffer::Type type, @@ -57,7 +67,8 @@ bool GrVkMemory::AllocAndBindBufferMemory(GrVkGpu* gpu, propFlags = AllocationPropertyFlags::kNone; } - if (!allocator->allocateMemoryForBuffer(buffer, usage, propFlags, &memory)) { + VkResult result = allocator->allocateBufferMemory(buffer, usage, propFlags, &memory); + if (!check_result(gpu, result)) { return false; } allocator->getAllocInfo(memory, alloc); @@ -76,12 +87,9 @@ bool GrVkMemory::AllocAndBindBufferMemory(GrVkGpu* gpu, void GrVkMemory::FreeBufferMemory(const GrVkGpu* gpu, GrVkBuffer::Type type, const GrVkAlloc& alloc) { - if (alloc.fBackendMemory) { - GrVkMemoryAllocator* allocator = gpu->memoryAllocator(); - allocator->freeMemory(alloc.fBackendMemory); - } else { - GR_VK_CALL(gpu->vkInterface(), FreeMemory(gpu->device(), alloc.fMemory, nullptr)); - } + SkASSERT(alloc.fBackendMemory); + GrVkMemoryAllocator* allocator = gpu->memoryAllocator(); + allocator->freeMemory(alloc.fBackendMemory); } const VkDeviceSize kMaxSmallImageSize = 256 * 1024; @@ -109,9 +117,11 @@ bool GrVkMemory::AllocAndBindImageMemory(GrVkGpu* gpu, propFlags |= AllocationPropertyFlags::kProtected; } - if (!allocator->allocateMemoryForImage(image, propFlags, &memory)) { + VkResult result = allocator->allocateImageMemory(image, propFlags, &memory); + if (!check_result(gpu, result)) { return false; } + allocator->getAllocInfo(memory, alloc); // Bind buffer @@ -128,38 +138,27 @@ bool GrVkMemory::AllocAndBindImageMemory(GrVkGpu* gpu, void GrVkMemory::FreeImageMemory(const GrVkGpu* gpu, bool linearTiling, const GrVkAlloc& alloc) { - if (alloc.fBackendMemory) { - GrVkMemoryAllocator* allocator = gpu->memoryAllocator(); - allocator->freeMemory(alloc.fBackendMemory); - } else { - GR_VK_CALL(gpu->vkInterface(), FreeMemory(gpu->device(), alloc.fMemory, nullptr)); - } + SkASSERT(alloc.fBackendMemory); + GrVkMemoryAllocator* allocator = gpu->memoryAllocator(); + allocator->freeMemory(alloc.fBackendMemory); } void* GrVkMemory::MapAlloc(GrVkGpu* gpu, const GrVkAlloc& alloc) { SkASSERT(GrVkAlloc::kMappable_Flag & alloc.fFlags); - if (alloc.fBackendMemory) { - GrVkMemoryAllocator* allocator = gpu->memoryAllocator(); - return allocator->mapMemory(alloc.fBackendMemory); - } - + SkASSERT(alloc.fBackendMemory); + GrVkMemoryAllocator* allocator = gpu->memoryAllocator(); void* mapPtr; - VkResult err; - GR_VK_CALL_RESULT(gpu, err, MapMemory(gpu->device(), alloc.fMemory, alloc.fOffset, alloc.fSize, - 0, &mapPtr)); - if (err) { - mapPtr = nullptr; + VkResult result = allocator->mapMemory(alloc.fBackendMemory, &mapPtr); + if (!check_result(gpu, result)) { + return nullptr; } return mapPtr; } void GrVkMemory::UnmapAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc) { - if (alloc.fBackendMemory) { - GrVkMemoryAllocator* allocator = gpu->memoryAllocator(); - allocator->unmapMemory(alloc.fBackendMemory); - } else { - GR_VK_CALL(gpu->vkInterface(), UnmapMemory(gpu->device(), alloc.fMemory)); - } + SkASSERT(alloc.fBackendMemory); + GrVkMemoryAllocator* allocator = gpu->memoryAllocator(); + allocator->unmapMemory(alloc.fBackendMemory); } void GrVkMemory::GetNonCoherentMappedMemoryRange(const GrVkAlloc& alloc, VkDeviceSize offset, @@ -185,41 +184,27 @@ void GrVkMemory::GetNonCoherentMappedMemoryRange(const GrVkAlloc& alloc, VkDevic range->size = size; } -void GrVkMemory::FlushMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc, VkDeviceSize offset, +void GrVkMemory::FlushMappedAlloc(GrVkGpu* gpu, const GrVkAlloc& alloc, VkDeviceSize offset, VkDeviceSize size) { if (alloc.fFlags & GrVkAlloc::kNoncoherent_Flag) { SkASSERT(offset == 0); SkASSERT(size <= alloc.fSize); - if (alloc.fBackendMemory) { - GrVkMemoryAllocator* allocator = gpu->memoryAllocator(); - allocator->flushMappedMemory(alloc.fBackendMemory, offset, size); - } else { - VkDeviceSize alignment = gpu->physicalDeviceProperties().limits.nonCoherentAtomSize; - VkMappedMemoryRange mappedMemoryRange; - GrVkMemory::GetNonCoherentMappedMemoryRange(alloc, offset, size, alignment, - &mappedMemoryRange); - GR_VK_CALL(gpu->vkInterface(), FlushMappedMemoryRanges(gpu->device(), 1, - &mappedMemoryRange)); - } + SkASSERT(alloc.fBackendMemory); + GrVkMemoryAllocator* allocator = gpu->memoryAllocator(); + VkResult result = allocator->flushMemory(alloc.fBackendMemory, offset, size); + check_result(gpu, result); } } -void GrVkMemory::InvalidateMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc, +void GrVkMemory::InvalidateMappedAlloc(GrVkGpu* gpu, const GrVkAlloc& alloc, VkDeviceSize offset, VkDeviceSize size) { if (alloc.fFlags & GrVkAlloc::kNoncoherent_Flag) { SkASSERT(offset == 0); SkASSERT(size <= alloc.fSize); - if (alloc.fBackendMemory) { - GrVkMemoryAllocator* allocator = gpu->memoryAllocator(); - allocator->invalidateMappedMemory(alloc.fBackendMemory, offset, size); - } else { - VkDeviceSize alignment = gpu->physicalDeviceProperties().limits.nonCoherentAtomSize; - VkMappedMemoryRange mappedMemoryRange; - GrVkMemory::GetNonCoherentMappedMemoryRange(alloc, offset, size, alignment, - &mappedMemoryRange); - GR_VK_CALL(gpu->vkInterface(), InvalidateMappedMemoryRanges(gpu->device(), 1, - &mappedMemoryRange)); - } + SkASSERT(alloc.fBackendMemory); + GrVkMemoryAllocator* allocator = gpu->memoryAllocator(); + VkResult result = allocator->invalidateMemory(alloc.fBackendMemory, offset, size); + check_result(gpu, result); } } diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkMemory.h b/chromium/third_party/skia/src/gpu/vk/GrVkMemory.h index db2c0e66062..2cb91fd7b2b 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkMemory.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkMemory.h @@ -42,9 +42,9 @@ namespace GrVkMemory { // For the Flush and Invalidate calls, the offset should be relative to the GrVkAlloc. Thus this // will often be 0. The client does not need to make sure the offset and size are aligned to the // nonCoherentAtomSize, the internal calls will handle that. - void FlushMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc, VkDeviceSize offset, + void FlushMappedAlloc(GrVkGpu* gpu, const GrVkAlloc& alloc, VkDeviceSize offset, VkDeviceSize size); - void InvalidateMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc, VkDeviceSize offset, + void InvalidateMappedAlloc(GrVkGpu* gpu, const GrVkAlloc& alloc, VkDeviceSize offset, VkDeviceSize size); // Helper for aligning and setting VkMappedMemoryRange for flushing/invalidating noncoherent diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.cpp index 3327cf8c8ed..00f54b9008d 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.cpp @@ -11,7 +11,6 @@ #include "include/core/SkRect.h" #include "include/gpu/GrBackendDrawableInfo.h" #include "src/gpu/GrContextPriv.h" -#include "src/gpu/GrFixedClip.h" #include "src/gpu/GrOpFlushState.h" #include "src/gpu/GrPipeline.h" #include "src/gpu/GrRenderTargetPriv.h" @@ -61,7 +60,8 @@ GrVkOpsRenderPass::GrVkOpsRenderPass(GrVkGpu* gpu) : fGpu(gpu) {} bool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo, - const SkPMColor4f& clearColor) { + const SkPMColor4f& clearColor, + bool withStencil) { VkAttachmentLoadOp loadOp; VkAttachmentStoreOp storeOp; @@ -87,8 +87,11 @@ bool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, false); // If we are using a stencil attachment we also need to update its layout - if (GrStencilAttachment* stencil = fRenderTarget->renderTargetPriv().getStencilAttachment()) { - GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil; + if (withStencil) { + GrVkStencilAttachment* vkStencil = + (GrVkStencilAttachment*) fRenderTarget->renderTargetPriv().getStencilAttachment(); + SkASSERT(vkStencil); + // We need the write and read access bits since we may load and store the stencil. // The initial load happens in the VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT so we // wait there. @@ -101,7 +104,7 @@ bool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, } const GrVkResourceProvider::CompatibleRPHandle& rpHandle = - vkRT->compatibleRenderPassHandle(); + vkRT->compatibleRenderPassHandle(withStencil); if (rpHandle.isValid()) { fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle, vkColorOps, @@ -109,7 +112,9 @@ bool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, } else { fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(vkRT, vkColorOps, - vkStencilOps); + vkStencilOps, + nullptr, + withStencil); } if (!fCurrentRenderPass) { return false; @@ -128,7 +133,8 @@ bool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, fCurrentRenderPass = nullptr; return false; } - fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->getFramebuffer(), fCurrentRenderPass); + fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->getFramebuffer(withStencil), + fCurrentRenderPass); } if (!fGpu->beginRenderPass(fCurrentRenderPass, &vkClearColor, vkRT, fOrigin, fBounds, @@ -168,6 +174,9 @@ GrVkCommandBuffer* GrVkOpsRenderPass::currentCommandBuffer() { if (fCurrentSecondaryCommandBuffer) { return fCurrentSecondaryCommandBuffer.get(); } + // We checked this when we setup the GrVkOpsRenderPass and it should not have changed while we + // are still using this object. + SkASSERT(fGpu->currentCommandBuffer()); return fGpu->currentCommandBuffer(); } @@ -196,7 +205,8 @@ void GrVkOpsRenderPass::submit() { fGpu->endRenderPass(fRenderTarget, fOrigin, fBounds); } -bool GrVkOpsRenderPass::set(GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds, +bool GrVkOpsRenderPass::set(GrRenderTarget* rt, GrStencilAttachment* stencil, + GrSurfaceOrigin origin, const SkIRect& bounds, const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) { @@ -207,6 +217,13 @@ bool GrVkOpsRenderPass::set(GrRenderTarget* rt, GrSurfaceOrigin origin, const Sk fIsActive = true; #endif + // We check to make sure the GrVkGpu has a valid current command buffer instead of each time we + // access it. If the command buffer is valid here should be valid throughout the use of the + // render pass since nothing should trigger a submit while this render pass is active. + if (!fGpu->currentCommandBuffer()) { + return false; + } + this->INHERITED::set(rt, origin); for (int i = 0; i < sampledProxies.count(); ++i) { @@ -227,7 +244,7 @@ bool GrVkOpsRenderPass::set(GrRenderTarget* rt, GrSurfaceOrigin origin, const Sk return this->initWrapped(); } - return this->init(colorInfo, stencilInfo, colorInfo.fClearColor); + return this->init(colorInfo, stencilInfo, colorInfo.fClearColor, SkToBool(stencil)); } void GrVkOpsRenderPass::reset() { @@ -257,14 +274,12 @@ bool GrVkOpsRenderPass::wrapsSecondaryCommandBuffer() const { //////////////////////////////////////////////////////////////////////////////// -void GrVkOpsRenderPass::onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) { +void GrVkOpsRenderPass::onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) { if (!fCurrentRenderPass) { SkASSERT(fGpu->isDeviceLost()); return; } - SkASSERT(!clip.hasWindowRectangles()); - GrStencilAttachment* sb = fRenderTarget->renderTargetPriv().getStencilAttachment(); // this should only be called internally when we know we have a // stencil buffer. @@ -285,14 +300,13 @@ void GrVkOpsRenderPass::onClearStencilClip(const GrFixedClip& clip, bool insideS VkClearRect clearRect; // Flip rect if necessary SkIRect vkRect; - if (!clip.scissorEnabled()) { + if (!scissor.enabled()) { vkRect.setXYWH(0, 0, fRenderTarget->width(), fRenderTarget->height()); } else if (kBottomLeft_GrSurfaceOrigin != fOrigin) { - vkRect = clip.scissorRect(); + vkRect = scissor.rect(); } else { - const SkIRect& scissor = clip.scissorRect(); - vkRect.setLTRB(scissor.fLeft, fRenderTarget->height() - scissor.fBottom, - scissor.fRight, fRenderTarget->height() - scissor.fTop); + vkRect.setLTRB(scissor.rect().fLeft, fRenderTarget->height() - scissor.rect().fBottom, + scissor.rect().fRight, fRenderTarget->height() - scissor.rect().fTop); } clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop }; @@ -313,15 +327,12 @@ void GrVkOpsRenderPass::onClearStencilClip(const GrFixedClip& clip, bool insideS fCurrentCBIsEmpty = false; } -void GrVkOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& color) { +void GrVkOpsRenderPass::onClear(const GrScissorState& scissor, const SkPMColor4f& color) { if (!fCurrentRenderPass) { SkASSERT(fGpu->isDeviceLost()); return; } - // parent class should never let us get here with no RT - SkASSERT(!clip.hasWindowRectangles()); - VkClearColorValue vkColor = {{color.fR, color.fG, color.fB, color.fA}}; // If we end up in a situation where we are calling clear without a scissior then in general it @@ -330,20 +341,19 @@ void GrVkOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& colo // load op (e.g. if we needed to execute a wait op). Thus we also have the empty check here. // TODO: Make the waitOp a RenderTask instead so we can clear out the GrOpsTask for a clear. We // can then reenable this assert assuming we can't get messed up by a waitOp. - //SkASSERT(!fCurrentCBIsEmpty || clip.scissorEnabled()); + //SkASSERT(!fCurrentCBIsEmpty || scissor); // We always do a sub rect clear with clearAttachments since we are inside a render pass VkClearRect clearRect; // Flip rect if necessary SkIRect vkRect; - if (!clip.scissorEnabled()) { + if (!scissor.enabled()) { vkRect.setXYWH(0, 0, fRenderTarget->width(), fRenderTarget->height()); } else if (kBottomLeft_GrSurfaceOrigin != fOrigin) { - vkRect = clip.scissorRect(); + vkRect = scissor.rect(); } else { - const SkIRect& scissor = clip.scissorRect(); - vkRect.setLTRB(scissor.fLeft, fRenderTarget->height() - scissor.fBottom, - scissor.fRight, fRenderTarget->height() - scissor.fTop); + vkRect.setLTRB(scissor.rect().fLeft, fRenderTarget->height() - scissor.rect().fBottom, + scissor.rect().fRight, fRenderTarget->height() - scissor.rect().fTop); } clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop }; clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() }; @@ -374,8 +384,10 @@ void GrVkOpsRenderPass::addAdditionalRenderPass(bool mustUseSecondaryCommandBuff GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE); + bool withStencil = fCurrentRenderPass->hasStencilAttachment(); + const GrVkResourceProvider::CompatibleRPHandle& rpHandle = - vkRT->compatibleRenderPassHandle(); + vkRT->compatibleRenderPassHandle(withStencil); SkASSERT(fCurrentRenderPass); fCurrentRenderPass->unref(); if (rpHandle.isValid()) { @@ -385,7 +397,9 @@ void GrVkOpsRenderPass::addAdditionalRenderPass(bool mustUseSecondaryCommandBuff } else { fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(vkRT, vkColorOps, - vkStencilOps); + vkStencilOps, + nullptr, + withStencil); } if (!fCurrentRenderPass) { return; @@ -402,7 +416,8 @@ void GrVkOpsRenderPass::addAdditionalRenderPass(bool mustUseSecondaryCommandBuff fCurrentRenderPass = nullptr; return; } - fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->getFramebuffer(), fCurrentRenderPass); + fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->getFramebuffer(withStencil), + fCurrentRenderPass); } // We use the same fBounds as the whole GrVkOpsRenderPass since we have no way of tracking the @@ -669,4 +684,3 @@ void GrVkOpsRenderPass::onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHan drawable->draw(info); fGpu->addDrawable(std::move(drawable)); } - diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.h b/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.h index 195bb922c02..ef666ec334b 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.h @@ -32,7 +32,8 @@ public: void onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) override; - bool set(GrRenderTarget*, GrSurfaceOrigin, const SkIRect& bounds, + bool set(GrRenderTarget*, GrStencilAttachment*, + GrSurfaceOrigin, const SkIRect& bounds, const GrOpsRenderPass::LoadAndStoreInfo&, const GrOpsRenderPass::StencilLoadAndStoreInfo&, const SkTArray<GrSurfaceProxy*, true>& sampledProxies); @@ -47,7 +48,8 @@ public: private: bool init(const GrOpsRenderPass::LoadAndStoreInfo&, const GrOpsRenderPass::StencilLoadAndStoreInfo&, - const SkPMColor4f& clearColor); + const SkPMColor4f& clearColor, + bool withStencil); // Called instead of init when we are drawing to a render target that already wraps a secondary // command buffer. @@ -82,9 +84,9 @@ private: void onDrawIndexedIndirect(const GrBuffer* drawIndirectBuffer, size_t offset, int drawCount) override; - void onClear(const GrFixedClip&, const SkPMColor4f& color) override; + void onClear(const GrScissorState& scissor, const SkPMColor4f& color) override; - void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) override; + void onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) override; void addAdditionalRenderPass(bool mustUseSecondaryCommandBuffer); diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.cpp index 4347cf4034a..1e04c61a5b6 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.cpp @@ -19,8 +19,6 @@ #include "src/gpu/vk/GrVkRenderPass.h" #include "src/gpu/vk/GrVkRenderTarget.h" -typedef size_t shader_size; - GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState( GrVkGpu* gpu, GrRenderTarget* renderTarget, @@ -100,39 +98,49 @@ bool GrVkPipelineStateBuilder::installVkShaderModule(VkShaderStageFlagBits stage static constexpr SkFourByteTag kSPIRV_Tag = SkSetFourByteTag('S', 'P', 'R', 'V'); static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L'); -int GrVkPipelineStateBuilder::loadShadersFromCache(SkReader32* cached, +int GrVkPipelineStateBuilder::loadShadersFromCache(SkReadBuffer* cached, VkShaderModule outShaderModules[], VkPipelineShaderStageCreateInfo* outStageInfo) { SkSL::String shaders[kGrShaderTypeCount]; SkSL::Program::Inputs inputs[kGrShaderTypeCount]; - GrPersistentCacheUtils::UnpackCachedShaders(cached, shaders, inputs, kGrShaderTypeCount); + if (!GrPersistentCacheUtils::UnpackCachedShaders(cached, shaders, inputs, kGrShaderTypeCount)) { + return 0; + } - SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT, + bool success = this->installVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT, fVS, &outShaderModules[kVertex_GrShaderType], &outStageInfo[0], shaders[kVertex_GrShaderType], - inputs[kVertex_GrShaderType])); + inputs[kVertex_GrShaderType]); - SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT, - fFS, - &outShaderModules[kFragment_GrShaderType], - &outStageInfo[1], - shaders[kFragment_GrShaderType], - inputs[kFragment_GrShaderType])); + success = success && this->installVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT, + fFS, + &outShaderModules[kFragment_GrShaderType], + &outStageInfo[1], + shaders[kFragment_GrShaderType], + inputs[kFragment_GrShaderType]); if (!shaders[kGeometry_GrShaderType].empty()) { - SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT, - fGS, - &outShaderModules[kGeometry_GrShaderType], - &outStageInfo[2], - shaders[kGeometry_GrShaderType], - inputs[kGeometry_GrShaderType])); - return 3; - } else { - return 2; + success = success && this->installVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT, + fGS, + &outShaderModules[kGeometry_GrShaderType], + &outStageInfo[2], + shaders[kGeometry_GrShaderType], + inputs[kGeometry_GrShaderType]); + } + + if (!success) { + for (int i = 0; i < kGrShaderTypeCount; ++i) { + if (outShaderModules[i]) { + GR_VK_CALL(fGpu->vkInterface(), + DestroyShaderModule(fGpu->device(), outShaderModules[i], nullptr)); + } + } + return 0; } + return shaders[kGeometry_GrShaderType].empty() ? 2 : 3; } void GrVkPipelineStateBuilder::storeShadersInCache(const SkSL::String shaders[], @@ -211,7 +219,7 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrProgramDesc& desc, SkASSERT(!this->fragColorIsInOut()); sk_sp<SkData> cached; - SkReader32 reader; + SkReadBuffer reader; SkFourByteTag shaderType = 0; auto persistentCache = fGpu->getContext()->priv().getPersistentCache(); if (persistentCache) { @@ -231,7 +239,10 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrProgramDesc& desc, int numShaderStages = 0; if (kSPIRV_Tag == shaderType) { numShaderStages = this->loadShadersFromCache(&reader, shaderModules, shaderStageInfo); - } else { + } + + // Proceed from sources if we didn't get a SPIRV cache (or the cache was invalid) + if (!numShaderStages) { numShaderStages = 2; // We always have at least vertex and fragment stages. SkSL::String shaders[kGrShaderTypeCount]; SkSL::Program::Inputs inputs[kGrShaderTypeCount]; @@ -243,10 +254,11 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrProgramDesc& desc, }; SkSL::String cached_sksl[kGrShaderTypeCount]; if (kSKSL_Tag == shaderType) { - GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, inputs, - kGrShaderTypeCount); - for (int i = 0; i < kGrShaderTypeCount; ++i) { - sksl[i] = &cached_sksl[i]; + if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, inputs, + kGrShaderTypeCount)) { + for (int i = 0; i < kGrShaderTypeCount; ++i) { + sksl[i] = &cached_sksl[i]; + } } } diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.h b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.h index 1eb5290f6a0..d13f47bee3e 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.h @@ -19,7 +19,7 @@ class GrProgramDesc; class GrVkGpu; class GrVkRenderPass; -class SkReader32; +class SkReadBuffer; class GrVkPipelineStateBuilder : public GrGLSLProgramBuilder { public: @@ -48,7 +48,7 @@ private: GrVkPipelineState* finalize(const GrProgramDesc&, VkRenderPass compatibleRenderPass); // returns number of shader stages - int loadShadersFromCache(SkReader32* cached, VkShaderModule outShaderModules[], + int loadShadersFromCache(SkReadBuffer* cached, VkShaderModule outShaderModules[], VkPipelineShaderStageCreateInfo* outStageInfo); void storeShadersInCache(const SkSL::String shaders[], const SkSL::Program::Inputs inputs[], diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.cpp index bd0c8d460f6..8377437afe7 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.cpp @@ -12,11 +12,8 @@ GrVkPipelineStateDataManager::GrVkPipelineStateDataManager(const UniformInfoArray& uniforms, uint32_t uniformSize) - : fUniformSize(uniformSize) - , fUniformsDirty(false) { - fUniformData.reset(uniformSize); - fUniforms.push_back_n(uniforms.count()); - // We must add uniforms in same order is the UniformInfoArray so that UniformHandles already + : INHERITED(uniforms.count(), uniformSize) { + // We must add uniforms in same order as the UniformInfoArray so that UniformHandles already // owned by other objects will still match up here. int i = 0; for (const auto& uniformInfo : uniforms.items()) { @@ -33,306 +30,6 @@ GrVkPipelineStateDataManager::GrVkPipelineStateDataManager(const UniformInfoArra } } -void* GrVkPipelineStateDataManager::getBufferPtrAndMarkDirty(const Uniform& uni) const { - fUniformsDirty = true; - return static_cast<char*>(fUniformData.get())+uni.fOffset; -} - -void GrVkPipelineStateDataManager::set1i(UniformHandle u, int32_t i) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType); - SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); - void* buffer = this->getBufferPtrAndMarkDirty(uni); - memcpy(buffer, &i, sizeof(int32_t)); -} - -void GrVkPipelineStateDataManager::set1iv(UniformHandle u, - int arrayCount, - const int32_t v[]) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType); - SkASSERT(arrayCount > 0); - SkASSERT(arrayCount <= uni.fArrayCount || - (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); - - void* buffer = this->getBufferPtrAndMarkDirty(uni); - SkASSERT(sizeof(int32_t) == 4); - for (int i = 0; i < arrayCount; ++i) { - const int32_t* curVec = &v[i]; - memcpy(buffer, curVec, sizeof(int32_t)); - buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t); - } -} - -void GrVkPipelineStateDataManager::set1f(UniformHandle u, float v0) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kFloat_GrSLType || uni.fType == kHalf_GrSLType); - SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); - void* buffer = this->getBufferPtrAndMarkDirty(uni); - SkASSERT(sizeof(float) == 4); - memcpy(buffer, &v0, sizeof(float)); -} - -void GrVkPipelineStateDataManager::set1fv(UniformHandle u, - int arrayCount, - const float v[]) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kFloat_GrSLType || uni.fType == kHalf_GrSLType); - SkASSERT(arrayCount > 0); - SkASSERT(arrayCount <= uni.fArrayCount || - (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); - - void* buffer = this->getBufferPtrAndMarkDirty(uni); - SkASSERT(sizeof(float) == 4); - for (int i = 0; i < arrayCount; ++i) { - const float* curVec = &v[i]; - memcpy(buffer, curVec, sizeof(float)); - buffer = static_cast<char*>(buffer) + 4*sizeof(float); - } -} - -void GrVkPipelineStateDataManager::set2i(UniformHandle u, int32_t i0, int32_t i1) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kInt2_GrSLType || uni.fType == kShort2_GrSLType); - SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); - void* buffer = this->getBufferPtrAndMarkDirty(uni); - int32_t v[2] = { i0, i1 }; - memcpy(buffer, v, 2 * sizeof(int32_t)); -} - -void GrVkPipelineStateDataManager::set2iv(UniformHandle u, - int arrayCount, - const int32_t v[]) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kInt2_GrSLType || uni.fType == kShort2_GrSLType); - SkASSERT(arrayCount > 0); - SkASSERT(arrayCount <= uni.fArrayCount || - (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); - - void* buffer = this->getBufferPtrAndMarkDirty(uni); - SkASSERT(sizeof(int32_t) == 4); - for (int i = 0; i < arrayCount; ++i) { - const int32_t* curVec = &v[2 * i]; - memcpy(buffer, curVec, 2 * sizeof(int32_t)); - buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t); - } -} - -void GrVkPipelineStateDataManager::set2f(UniformHandle u, float v0, float v1) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType); - SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); - void* buffer = this->getBufferPtrAndMarkDirty(uni); - SkASSERT(sizeof(float) == 4); - float v[2] = { v0, v1 }; - memcpy(buffer, v, 2 * sizeof(float)); -} - -void GrVkPipelineStateDataManager::set2fv(UniformHandle u, - int arrayCount, - const float v[]) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType); - SkASSERT(arrayCount > 0); - SkASSERT(arrayCount <= uni.fArrayCount || - (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); - - void* buffer = this->getBufferPtrAndMarkDirty(uni); - SkASSERT(sizeof(float) == 4); - for (int i = 0; i < arrayCount; ++i) { - const float* curVec = &v[2 * i]; - memcpy(buffer, curVec, 2 * sizeof(float)); - buffer = static_cast<char*>(buffer) + 4*sizeof(float); - } -} - -void GrVkPipelineStateDataManager::set3i(UniformHandle u, - int32_t i0, - int32_t i1, - int32_t i2) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kInt3_GrSLType || uni.fType == kShort3_GrSLType); - SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); - void* buffer = this->getBufferPtrAndMarkDirty(uni); - int32_t v[3] = { i0, i1, i2 }; - memcpy(buffer, v, 3 * sizeof(int32_t)); -} - -void GrVkPipelineStateDataManager::set3iv(UniformHandle u, - int arrayCount, - const int32_t v[]) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kInt3_GrSLType || uni.fType == kShort3_GrSLType); - SkASSERT(arrayCount > 0); - SkASSERT(arrayCount <= uni.fArrayCount || - (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); - - void* buffer = this->getBufferPtrAndMarkDirty(uni); - SkASSERT(sizeof(int32_t) == 4); - for (int i = 0; i < arrayCount; ++i) { - const int32_t* curVec = &v[3 * i]; - memcpy(buffer, curVec, 3 * sizeof(int32_t)); - buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t); - } -} - -void GrVkPipelineStateDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_GrSLType); - SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); - void* buffer = this->getBufferPtrAndMarkDirty(uni); - SkASSERT(sizeof(float) == 4); - float v[3] = { v0, v1, v2 }; - memcpy(buffer, v, 3 * sizeof(float)); -} - -void GrVkPipelineStateDataManager::set3fv(UniformHandle u, - int arrayCount, - const float v[]) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_GrSLType); - SkASSERT(arrayCount > 0); - SkASSERT(arrayCount <= uni.fArrayCount || - (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); - - void* buffer = this->getBufferPtrAndMarkDirty(uni); - SkASSERT(sizeof(float) == 4); - for (int i = 0; i < arrayCount; ++i) { - const float* curVec = &v[3 * i]; - memcpy(buffer, curVec, 3 * sizeof(float)); - buffer = static_cast<char*>(buffer) + 4*sizeof(float); - } -} - -void GrVkPipelineStateDataManager::set4i(UniformHandle u, - int32_t i0, - int32_t i1, - int32_t i2, - int32_t i3) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kInt4_GrSLType || uni.fType == kShort4_GrSLType); - SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); - void* buffer = this->getBufferPtrAndMarkDirty(uni); - int32_t v[4] = { i0, i1, i2, i3 }; - memcpy(buffer, v, 4 * sizeof(int32_t)); -} - -void GrVkPipelineStateDataManager::set4iv(UniformHandle u, - int arrayCount, - const int32_t v[]) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kInt4_GrSLType || uni.fType == kShort4_GrSLType); - SkASSERT(arrayCount > 0); - SkASSERT(arrayCount <= uni.fArrayCount || - (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); - - void* buffer = this->getBufferPtrAndMarkDirty(uni); - SkASSERT(sizeof(int32_t) == 4); - for (int i = 0; i < arrayCount; ++i) { - const int32_t* curVec = &v[4 * i]; - memcpy(buffer, curVec, 4 * sizeof(int32_t)); - buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t); - } -} - -void GrVkPipelineStateDataManager::set4f(UniformHandle u, - float v0, - float v1, - float v2, - float v3) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_GrSLType); - SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); - void* buffer = this->getBufferPtrAndMarkDirty(uni); - SkASSERT(sizeof(float) == 4); - float v[4] = { v0, v1, v2, v3 }; - memcpy(buffer, v, 4 * sizeof(float)); -} - -void GrVkPipelineStateDataManager::set4fv(UniformHandle u, - int arrayCount, - const float v[]) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_GrSLType); - SkASSERT(arrayCount > 0); - SkASSERT(arrayCount <= uni.fArrayCount || - (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); - - void* buffer = this->getBufferPtrAndMarkDirty(uni); - SkASSERT(sizeof(float) == 4); - memcpy(buffer, v, arrayCount * 4 * sizeof(float)); -} - -void GrVkPipelineStateDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const { - this->setMatrices<2>(u, 1, matrix); -} - -void GrVkPipelineStateDataManager::setMatrix2fv(UniformHandle u, - int arrayCount, - const float m[]) const { - this->setMatrices<2>(u, arrayCount, m); -} - -void GrVkPipelineStateDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const { - this->setMatrices<3>(u, 1, matrix); -} - -void GrVkPipelineStateDataManager::setMatrix3fv(UniformHandle u, - int arrayCount, - const float m[]) const { - this->setMatrices<3>(u, arrayCount, m); -} - -void GrVkPipelineStateDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const { - this->setMatrices<4>(u, 1, matrix); -} - -void GrVkPipelineStateDataManager::setMatrix4fv(UniformHandle u, - int arrayCount, - const float m[]) const { - this->setMatrices<4>(u, arrayCount, m); -} - -template<int N> struct set_uniform_matrix; - -template<int N> inline void GrVkPipelineStateDataManager::setMatrices(UniformHandle u, - int arrayCount, - const float matrices[]) const { - const Uniform& uni = fUniforms[u.toIndex()]; - SkASSERT(uni.fType == kFloat2x2_GrSLType + (N - 2) || - uni.fType == kHalf2x2_GrSLType + (N - 2)); - SkASSERT(arrayCount > 0); - SkASSERT(arrayCount <= uni.fArrayCount || - (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); - - void* buffer = fUniformData.get(); - fUniformsDirty = true; - - set_uniform_matrix<N>::set(buffer, uni.fOffset, arrayCount, matrices); -} - -template<int N> struct set_uniform_matrix { - inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) { - static_assert(sizeof(float) == 4); - buffer = static_cast<char*>(buffer) + uniformOffset; - for (int i = 0; i < count; ++i) { - const float* matrix = &matrices[N * N * i]; - for (int j = 0; j < N; ++j) { - memcpy(buffer, &matrix[j * N], N * sizeof(float)); - buffer = static_cast<char*>(buffer) + 4 * sizeof(float); - } - } - } -}; - -template<> struct set_uniform_matrix<4> { - inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) { - static_assert(sizeof(float) == 4); - buffer = static_cast<char*>(buffer) + uniformOffset; - memcpy(buffer, matrices, count * 16 * sizeof(float)); - } -}; - bool GrVkPipelineStateDataManager::uploadUniformBuffers(GrVkGpu* gpu, GrVkUniformBuffer* buffer) const { bool updatedBuffer = false; diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.h b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.h index 91d50924b68..b090dd6f56c 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.h @@ -8,78 +8,28 @@ #ifndef GrVkPipelineStateDataManager_DEFINED #define GrVkPipelineStateDataManager_DEFINED -#include "src/gpu/glsl/GrGLSLProgramDataManager.h" +#include "src/gpu/GrUniformDataManager.h" #include "include/gpu/vk/GrVkTypes.h" -#include "src/core/SkAutoMalloc.h" #include "src/gpu/vk/GrVkUniformHandler.h" class GrVkGpu; class GrVkUniformBuffer; -class GrVkPipelineStateDataManager : public GrGLSLProgramDataManager { +class GrVkPipelineStateDataManager : public GrUniformDataManager { public: typedef GrVkUniformHandler::UniformInfoArray UniformInfoArray; GrVkPipelineStateDataManager(const UniformInfoArray&, uint32_t uniformSize); - void set1i(UniformHandle, int32_t) const override; - void set1iv(UniformHandle, int arrayCount, const int32_t v[]) const override; - void set1f(UniformHandle, float v0) const override; - void set1fv(UniformHandle, int arrayCount, const float v[]) const override; - void set2i(UniformHandle, int32_t, int32_t) const override; - void set2iv(UniformHandle, int arrayCount, const int32_t v[]) const override; - void set2f(UniformHandle, float, float) const override; - void set2fv(UniformHandle, int arrayCount, const float v[]) const override; - void set3i(UniformHandle, int32_t, int32_t, int32_t) const override; - void set3iv(UniformHandle, int arrayCount, const int32_t v[]) const override; - void set3f(UniformHandle, float, float, float) const override; - void set3fv(UniformHandle, int arrayCount, const float v[]) const override; - void set4i(UniformHandle, int32_t, int32_t, int32_t, int32_t) const override; - void set4iv(UniformHandle, int arrayCount, const int32_t v[]) const override; - void set4f(UniformHandle, float, float, float, float) const override; - void set4fv(UniformHandle, int arrayCount, const float v[]) const override; - // matrices are column-major, the first two upload a single matrix, the latter two upload - // arrayCount matrices into a uniform array. - void setMatrix2f(UniformHandle, const float matrix[]) const override; - void setMatrix3f(UniformHandle, const float matrix[]) const override; - void setMatrix4f(UniformHandle, const float matrix[]) const override; - void setMatrix2fv(UniformHandle, int arrayCount, const float matrices[]) const override; - void setMatrix3fv(UniformHandle, int arrayCount, const float matrices[]) const override; - void setMatrix4fv(UniformHandle, int arrayCount, const float matrices[]) const override; - - // for nvpr only - void setPathFragmentInputTransform(VaryingHandle u, int components, - const SkMatrix& matrix) const override { - SK_ABORT("Only supported in NVPR, which is not in vulkan"); - } - // Returns true if either the geometry or fragment buffers needed to generate a new underlying // VkBuffer object in order upload data. If true is returned, this is a signal to the caller // that they will need to update the descriptor set that is using these buffers. bool uploadUniformBuffers(GrVkGpu* gpu, GrVkUniformBuffer* buffer) const; private: - struct Uniform { - uint32_t fOffset; - SkDEBUGCODE( - GrSLType fType; - int fArrayCount; - ); - }; - - template<int N> inline void setMatrices(UniformHandle, int arrayCount, - const float matrices[]) const; - - void* getBufferPtrAndMarkDirty(const Uniform& uni) const; - - uint32_t fUniformSize; - - SkTArray<Uniform, true> fUniforms; - - mutable SkAutoMalloc fUniformData; - mutable bool fUniformsDirty; + typedef GrUniformDataManager INHERITED; }; #endif diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.cpp index 627eb2253e2..281983f8451 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.cpp @@ -234,7 +234,7 @@ bool GrVkRenderPass::isCompatible(const GrVkRenderTarget& target) const { AttachmentsDescriptor desc; AttachmentFlags flags; - target.getAttachmentsDescriptor(&desc, &flags); + target.getAttachmentsDescriptor(&desc, &flags, this->hasStencilAttachment()); return this->isCompatible(desc, flags); } diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.h b/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.h index 8b8c641b18b..5009e1ec3bb 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.h @@ -94,6 +94,7 @@ public: // index value. bool colorAttachmentIndex(uint32_t* index) const; bool stencilAttachmentIndex(uint32_t* index) const; + bool hasStencilAttachment() const { return fAttachmentFlags & kStencil_AttachmentFlag; } // Returns whether or not the structure of a RenderTarget matches that of the VkRenderPass in // this object. Specifically this compares that the number of attachments, format of diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.cpp index 3021298c700..c2afefc6a17 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.cpp @@ -26,21 +26,23 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu, SkISize dimensions, int sampleCnt, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageInfo& msaaInfo, - sk_sp<GrVkImageLayout> msaaLayout, + sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState, const GrVkImageView* colorAttachmentView, const GrVkImageView* resolveAttachmentView) : GrSurface(gpu, dimensions, info.fProtected) - , GrVkImage(gpu, info, std::move(layout), GrBackendObjectOwnership::kBorrowed) + , GrVkImage(gpu, info, std::move(mutableState), GrBackendObjectOwnership::kBorrowed) // for the moment we only support 1:1 color to stencil , GrRenderTarget(gpu, dimensions, sampleCnt, info.fProtected) , fColorAttachmentView(colorAttachmentView) - , fMSAAImage(new GrVkImage(gpu, msaaInfo, std::move(msaaLayout), + , fMSAAImage(new GrVkImage(gpu, msaaInfo, std::move(msaaMutableState), GrBackendObjectOwnership::kOwned)) , fResolveAttachmentView(resolveAttachmentView) , fCachedFramebuffer(nullptr) - , fCachedSimpleRenderPass(nullptr) { + , fCachedStencilFramebuffer(nullptr) + , fCachedSimpleRenderPass(nullptr) + , fCachedStencilRenderPass(nullptr) { SkASSERT(info.fProtected == msaaInfo.fProtected); SkASSERT(sampleCnt > 1); this->registerWithCacheWrapped(GrWrapCacheable::kNo); @@ -52,22 +54,24 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu, SkISize dimensions, int sampleCnt, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageInfo& msaaInfo, - sk_sp<GrVkImageLayout> msaaLayout, + sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState, const GrVkImageView* colorAttachmentView, const GrVkImageView* resolveAttachmentView, GrBackendObjectOwnership ownership) : GrSurface(gpu, dimensions, info.fProtected) - , GrVkImage(gpu, info, std::move(layout), ownership) + , GrVkImage(gpu, info, std::move(mutableState), ownership) // for the moment we only support 1:1 color to stencil , GrRenderTarget(gpu, dimensions, sampleCnt, info.fProtected) , fColorAttachmentView(colorAttachmentView) - , fMSAAImage(new GrVkImage(gpu, msaaInfo, std::move(msaaLayout), + , fMSAAImage(new GrVkImage(gpu, msaaInfo, std::move(msaaMutableState), GrBackendObjectOwnership::kOwned)) , fResolveAttachmentView(resolveAttachmentView) , fCachedFramebuffer(nullptr) - , fCachedSimpleRenderPass(nullptr) { + , fCachedStencilFramebuffer(nullptr) + , fCachedSimpleRenderPass(nullptr) + , fCachedStencilRenderPass(nullptr) { SkASSERT(info.fProtected == msaaInfo.fProtected); SkASSERT(sampleCnt > 1); } @@ -77,16 +81,18 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu, GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu, SkISize dimensions, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageView* colorAttachmentView) : GrSurface(gpu, dimensions, info.fProtected) - , GrVkImage(gpu, info, std::move(layout), GrBackendObjectOwnership::kBorrowed) + , GrVkImage(gpu, info, std::move(mutableState), GrBackendObjectOwnership::kBorrowed) , GrRenderTarget(gpu, dimensions, 1, info.fProtected) , fColorAttachmentView(colorAttachmentView) , fMSAAImage(nullptr) , fResolveAttachmentView(nullptr) , fCachedFramebuffer(nullptr) - , fCachedSimpleRenderPass(nullptr) { + , fCachedStencilFramebuffer(nullptr) + , fCachedSimpleRenderPass(nullptr) + , fCachedStencilRenderPass(nullptr) { this->registerWithCacheWrapped(GrWrapCacheable::kNo); } @@ -95,42 +101,44 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu, GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu, SkISize dimensions, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageView* colorAttachmentView, GrBackendObjectOwnership ownership) : GrSurface(gpu, dimensions, info.fProtected) - , GrVkImage(gpu, info, std::move(layout), ownership) + , GrVkImage(gpu, info, std::move(mutableState), ownership) , GrRenderTarget(gpu, dimensions, 1, info.fProtected) , fColorAttachmentView(colorAttachmentView) , fMSAAImage(nullptr) , fResolveAttachmentView(nullptr) , fCachedFramebuffer(nullptr) - , fCachedSimpleRenderPass(nullptr) {} + , fCachedStencilFramebuffer(nullptr) + , fCachedSimpleRenderPass(nullptr) + , fCachedStencilRenderPass(nullptr) {} GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu, SkISize dimensions, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkRenderPass* renderPass, VkCommandBuffer secondaryCommandBuffer) : GrSurface(gpu, dimensions, info.fProtected) - , GrVkImage(gpu, info, std::move(layout), GrBackendObjectOwnership::kBorrowed, true) + , GrVkImage(gpu, info, std::move(mutableState), GrBackendObjectOwnership::kBorrowed, true) , GrRenderTarget(gpu, dimensions, 1, info.fProtected) , fColorAttachmentView(nullptr) , fMSAAImage(nullptr) , fResolveAttachmentView(nullptr) , fCachedFramebuffer(nullptr) + , fCachedStencilFramebuffer(nullptr) , fCachedSimpleRenderPass(renderPass) + , fCachedStencilRenderPass(nullptr) , fSecondaryCommandBuffer(secondaryCommandBuffer) { SkASSERT(fSecondaryCommandBuffer != VK_NULL_HANDLE); this->registerWithCacheWrapped(GrWrapCacheable::kNo); } -sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(GrVkGpu* gpu, - SkISize dimensions, - int sampleCnt, - const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout) { +sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget( + GrVkGpu* gpu, SkISize dimensions, int sampleCnt, const GrVkImageInfo& info, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState) { SkASSERT(VK_NULL_HANDLE != info.fImage); SkASSERT(1 == info.fLevelCount); @@ -140,7 +148,7 @@ sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(GrVkGpu* gpu, // create msaa surface if necessary GrVkImageInfo msInfo; - sk_sp<GrVkImageLayout> msLayout; + sk_sp<GrBackendSurfaceMutableStateImpl> msMutableState; const GrVkImageView* resolveAttachmentView = nullptr; if (sampleCnt > 1) { GrVkImage::ImageDesc msImageDesc; @@ -172,7 +180,8 @@ sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(GrVkGpu* gpu, GrVkImage::DestroyImageInfo(gpu, &msInfo); return nullptr; } - msLayout.reset(new GrVkImageLayout(msInfo.fImageLayout)); + msMutableState.reset(new GrBackendSurfaceMutableStateImpl(msInfo.fImageLayout, + msInfo.fCurrentQueueFamily)); } else { // Set color attachment image colorImage = info.fImage; @@ -192,11 +201,12 @@ sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(GrVkGpu* gpu, GrVkRenderTarget* vkRT; if (sampleCnt > 1) { - vkRT = new GrVkRenderTarget(gpu, dimensions, sampleCnt, info, std::move(layout), msInfo, - std::move(msLayout), colorAttachmentView, + vkRT = new GrVkRenderTarget(gpu, dimensions, sampleCnt, info, std::move(mutableState), + msInfo, std::move(msMutableState), colorAttachmentView, resolveAttachmentView); } else { - vkRT = new GrVkRenderTarget(gpu, dimensions, info, std::move(layout), colorAttachmentView); + vkRT = new GrVkRenderTarget(gpu, dimensions, info, std::move(mutableState), + colorAttachmentView); } return sk_sp<GrVkRenderTarget>(vkRT); @@ -204,14 +214,6 @@ sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(GrVkGpu* gpu, sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeSecondaryCBRenderTarget( GrVkGpu* gpu, SkISize dimensions, const GrVkDrawableInfo& vkInfo) { - // We only set the few properties of the GrVkImageInfo that we know like layout and format. The - // others we keep at the default "null" values. - GrVkImageInfo info; - info.fImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - info.fFormat = vkInfo.fFormat; - - sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); - const GrVkRenderPass* rp = gpu->resourceProvider().findCompatibleExternalRenderPass(vkInfo.fCompatibleRenderPass, vkInfo.fColorAttachmentIndex); @@ -223,78 +225,108 @@ sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeSecondaryCBRenderTarget( return nullptr; } - GrVkRenderTarget* vkRT = new GrVkRenderTarget(gpu, dimensions, info, std::move(layout), rp, - vkInfo.fSecondaryCommandBuffer); + // We only set the few properties of the GrVkImageInfo that we know like layout and format. The + // others we keep at the default "null" values. + GrVkImageInfo info; + info.fImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + info.fFormat = vkInfo.fFormat; + + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState(new GrBackendSurfaceMutableStateImpl( + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_IGNORED)); + + GrVkRenderTarget* vkRT = new GrVkRenderTarget(gpu, dimensions, info, std::move(mutableState), + rp, vkInfo.fSecondaryCommandBuffer); return sk_sp<GrVkRenderTarget>(vkRT); } bool GrVkRenderTarget::completeStencilAttachment() { SkASSERT(!this->wrapsSecondaryCommandBuffer()); - // If we have a previous renderpass or framebuffer it will have been made without stencil, so - // we set it to null to trigger creating a new one the next time we need it. - if (fCachedSimpleRenderPass) { - fCachedSimpleRenderPass->unref(); - fCachedSimpleRenderPass = nullptr; - } - if (fCachedFramebuffer) { - fCachedFramebuffer->unref(); - fCachedFramebuffer = nullptr; - } - fCompatibleRPHandle = GrVkResourceProvider::CompatibleRPHandle(); return true; } -const GrVkRenderPass* GrVkRenderTarget::getSimpleRenderPass() { - if (fCachedSimpleRenderPass) { - return fCachedSimpleRenderPass; +const GrVkRenderPass* GrVkRenderTarget::getSimpleRenderPass(bool withStencil) { + if (withStencil) { + if (fCachedStencilRenderPass) { + return fCachedStencilRenderPass; + } + } else { + if (fCachedSimpleRenderPass) { + return fCachedSimpleRenderPass; + } } - return this->createSimpleRenderPass(); + + return this->createSimpleRenderPass(withStencil); } -const GrVkRenderPass* GrVkRenderTarget::createSimpleRenderPass() { +const GrVkRenderPass* GrVkRenderTarget::createSimpleRenderPass(bool withStencil) { SkASSERT(!this->wrapsSecondaryCommandBuffer()); - SkASSERT(!fCachedSimpleRenderPass); - fCachedSimpleRenderPass = - this->getVkGpu()->resourceProvider().findCompatibleRenderPass(*this, &fCompatibleRPHandle); - return fCachedSimpleRenderPass; + GrVkResourceProvider& rp = this->getVkGpu()->resourceProvider(); + if (withStencil) { + SkASSERT(!fCachedStencilRenderPass); + fCachedStencilRenderPass = rp.findCompatibleRenderPass(*this, &fCompatibleStencilRPHandle, + withStencil); + return fCachedStencilRenderPass; + } else { + SkASSERT(!fCachedSimpleRenderPass); + fCachedSimpleRenderPass = rp.findCompatibleRenderPass(*this, &fCompatibleRPHandle, + withStencil); + return fCachedSimpleRenderPass; + } } -const GrVkFramebuffer* GrVkRenderTarget::getFramebuffer() { - if (fCachedFramebuffer) { - return fCachedFramebuffer; +const GrVkFramebuffer* GrVkRenderTarget::getFramebuffer(bool withStencil) { + if (withStencil) { + if (fCachedStencilFramebuffer) { + return fCachedStencilFramebuffer; + } + } else { + if (fCachedFramebuffer) { + return fCachedFramebuffer; + } } - return this->createFramebuffer(); + return this->createFramebuffer(withStencil); } -const GrVkFramebuffer* GrVkRenderTarget::createFramebuffer() { +const GrVkFramebuffer* GrVkRenderTarget::createFramebuffer(bool withStencil) { SkASSERT(!this->wrapsSecondaryCommandBuffer()); - SkASSERT(!fCachedFramebuffer); - GrVkGpu* gpu = this->getVkGpu(); - // Stencil attachment view is stored in the base RT stencil attachment - const GrVkImageView* stencilView = this->stencilAttachmentView(); - const GrVkRenderPass* renderPass = this->getSimpleRenderPass(); + + const GrVkRenderPass* renderPass = this->getSimpleRenderPass(withStencil); if (!renderPass) { return nullptr; } - fCachedFramebuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(), renderPass, - fColorAttachmentView, stencilView); - return fCachedFramebuffer; + + // Stencil attachment view is stored in the base RT stencil attachment + const GrVkImageView* stencilView = withStencil ? this->stencilAttachmentView() : nullptr; + GrVkFramebuffer* frameBuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(), + renderPass, fColorAttachmentView, + stencilView); + + if (withStencil) { + SkASSERT(!fCachedStencilFramebuffer); + fCachedStencilFramebuffer = frameBuffer; + } else { + SkASSERT(!fCachedFramebuffer); + fCachedFramebuffer = frameBuffer; + } + + return frameBuffer; } -void GrVkRenderTarget::getAttachmentsDescriptor( - GrVkRenderPass::AttachmentsDescriptor* desc, - GrVkRenderPass::AttachmentFlags* attachmentFlags) const { +void GrVkRenderTarget::getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor* desc, + GrVkRenderPass::AttachmentFlags* attachmentFlags, + bool withStencil) const { SkASSERT(!this->wrapsSecondaryCommandBuffer()); desc->fColor.fFormat = this->imageFormat(); desc->fColor.fSamples = this->numSamples(); *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag; uint32_t attachmentCount = 1; - const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment(); - if (stencil) { + if (withStencil) { + const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment(); + SkASSERT(stencil); const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil); desc->fStencil.fFormat = vkStencil->imageFormat(); desc->fStencil.fSamples = vkStencil->numSamples(); @@ -317,11 +349,13 @@ GrVkRenderTarget::~GrVkRenderTarget() { SkASSERT(!fResolveAttachmentView); SkASSERT(!fColorAttachmentView); SkASSERT(!fCachedFramebuffer); + SkASSERT(!fCachedStencilFramebuffer); SkASSERT(!fCachedSimpleRenderPass); + SkASSERT(!fCachedStencilRenderPass); } -void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) { - commandBuffer.addResource(this->getFramebuffer()); +void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer, bool withStencil) { + commandBuffer.addResource(this->getFramebuffer(withStencil)); commandBuffer.addResource(this->colorAttachmentView()); commandBuffer.addResource(this->msaaImageResource() ? this->msaaImageResource() : this->resource()); @@ -332,10 +366,8 @@ void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) { } void GrVkRenderTarget::releaseInternalObjects() { - GrVkGpu* gpu = this->getVkGpu(); - if (fMSAAImage) { - fMSAAImage->releaseImage(gpu); + fMSAAImage->releaseImage(); fMSAAImage.reset(); } @@ -351,10 +383,18 @@ void GrVkRenderTarget::releaseInternalObjects() { fCachedFramebuffer->unref(); fCachedFramebuffer = nullptr; } + if (fCachedStencilFramebuffer) { + fCachedStencilFramebuffer->unref(); + fCachedStencilFramebuffer = nullptr; + } if (fCachedSimpleRenderPass) { fCachedSimpleRenderPass->unref(); fCachedSimpleRenderPass = nullptr; } + if (fCachedStencilRenderPass) { + fCachedStencilRenderPass->unref(); + fCachedStencilRenderPass = nullptr; + } for (int i = 0; i < fGrSecondaryCommandBuffers.count(); ++i) { SkASSERT(fGrSecondaryCommandBuffers[i]); fGrSecondaryCommandBuffers[i]->releaseResources(); @@ -364,20 +404,20 @@ void GrVkRenderTarget::releaseInternalObjects() { void GrVkRenderTarget::onRelease() { this->releaseInternalObjects(); - this->releaseImage(this->getVkGpu()); + this->releaseImage(); GrRenderTarget::onRelease(); } void GrVkRenderTarget::onAbandon() { this->releaseInternalObjects(); - this->releaseImage(this->getVkGpu()); + this->releaseImage(); GrRenderTarget::onAbandon(); } GrBackendRenderTarget GrVkRenderTarget::getBackendRenderTarget() const { SkASSERT(!this->wrapsSecondaryCommandBuffer()); return GrBackendRenderTarget(this->width(), this->height(), this->numSamples(), fInfo, - this->grVkImageLayout()); + this->getMutableState()); } const GrManagedResource* GrVkRenderTarget::stencilImageResource() const { diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.h b/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.h index daae1a04a7d..94ad40f353b 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.h @@ -34,7 +34,7 @@ class GrVkRenderTarget: public GrRenderTarget, public virtual GrVkImage { public: static sk_sp<GrVkRenderTarget> MakeWrappedRenderTarget(GrVkGpu*, SkISize, int sampleCnt, const GrVkImageInfo&, - sk_sp<GrVkImageLayout>); + sk_sp<GrBackendSurfaceMutableStateImpl>); static sk_sp<GrVkRenderTarget> MakeSecondaryCBRenderTarget(GrVkGpu*, SkISize, const GrVkDrawableInfo& vkInfo); @@ -43,7 +43,7 @@ public: GrBackendFormat backendFormat() const override { return this->getBackendFormat(); } - const GrVkFramebuffer* getFramebuffer(); + const GrVkFramebuffer* getFramebuffer(bool withStencil); const GrVkImageView* colorAttachmentView() const { return fColorAttachmentView; } const GrManagedResource* msaaImageResource() const { if (fMSAAImage) { @@ -56,15 +56,26 @@ public: const GrManagedResource* stencilImageResource() const; const GrVkImageView* stencilAttachmentView() const; - const GrVkRenderPass* getSimpleRenderPass(); - GrVkResourceProvider::CompatibleRPHandle compatibleRenderPassHandle() { + const GrVkRenderPass* getSimpleRenderPass(bool withStencil); + GrVkResourceProvider::CompatibleRPHandle compatibleRenderPassHandle(bool withStencil) { SkASSERT(!this->wrapsSecondaryCommandBuffer()); - if (!fCompatibleRPHandle.isValid()) { - SkASSERT(!fCachedSimpleRenderPass); - this->createSimpleRenderPass(); + + auto pRPHandle = withStencil ? &fCompatibleStencilRPHandle : &fCompatibleRPHandle; + if (!pRPHandle->isValid()) { + this->createSimpleRenderPass(withStencil); + } + +#ifdef SK_DEBUG + if (withStencil) { + SkASSERT(pRPHandle->isValid() == SkToBool(fCachedStencilRenderPass)); + SkASSERT(fCachedStencilRenderPass->hasStencilAttachment()); + } else { + SkASSERT(pRPHandle->isValid() == SkToBool(fCachedSimpleRenderPass)); + SkASSERT(!fCachedSimpleRenderPass->hasStencilAttachment()); } - SkASSERT(fCompatibleRPHandle.isValid() == SkToBool(fCachedSimpleRenderPass)); - return fCompatibleRPHandle; +#endif + + return *pRPHandle; } const GrVkRenderPass* externalRenderPass() const { SkASSERT(this->wrapsSecondaryCommandBuffer()); @@ -86,9 +97,10 @@ public: GrBackendRenderTarget getBackendRenderTarget() const override; void getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor* desc, - GrVkRenderPass::AttachmentFlags* flags) const; + GrVkRenderPass::AttachmentFlags* flags, + bool withStencil) const; - void addResources(GrVkCommandBuffer& commandBuffer); + void addResources(GrVkCommandBuffer& commandBuffer, bool withStencil); void addWrappedGrSecondaryCommandBuffer(std::unique_ptr<GrVkSecondaryCommandBuffer> cmdBuffer) { fGrSecondaryCommandBuffers.push_back(std::move(cmdBuffer)); @@ -99,9 +111,9 @@ protected: SkISize dimensions, int sampleCnt, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageInfo& msaaInfo, - sk_sp<GrVkImageLayout> msaaLayout, + sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState, const GrVkImageView* colorAttachmentView, const GrVkImageView* resolveAttachmentView, GrBackendObjectOwnership); @@ -109,7 +121,7 @@ protected: GrVkRenderTarget(GrVkGpu* gpu, SkISize dimensions, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageView* colorAttachmentView, GrBackendObjectOwnership); @@ -133,29 +145,29 @@ private: SkISize dimensions, int sampleCnt, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageInfo& msaaInfo, - sk_sp<GrVkImageLayout> msaaLayout, + sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState, const GrVkImageView* colorAttachmentView, const GrVkImageView* resolveAttachmentView); GrVkRenderTarget(GrVkGpu* gpu, SkISize dimensions, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageView* colorAttachmentView); GrVkRenderTarget(GrVkGpu* gpu, SkISize dimensions, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkRenderPass* renderPass, VkCommandBuffer secondaryCommandBuffer); GrVkGpu* getVkGpu() const; - const GrVkRenderPass* createSimpleRenderPass(); - const GrVkFramebuffer* createFramebuffer(); + const GrVkRenderPass* createSimpleRenderPass(bool withStencil); + const GrVkFramebuffer* createFramebuffer(bool withStencil); bool completeStencilAttachment() override; @@ -173,12 +185,18 @@ private: const GrVkImageView* fResolveAttachmentView; const GrVkFramebuffer* fCachedFramebuffer; + const GrVkFramebuffer* fCachedStencilFramebuffer; - // This is a cached pointer to a simple render pass. The render target should unref it - // once it is done with it. + // Cached pointers to a simple and stencil render passes. The render target should unref them + // once it is done with them. const GrVkRenderPass* fCachedSimpleRenderPass; - // This is a handle to be used to quickly get compatible GrVkRenderPasses for this render target + const GrVkRenderPass* fCachedStencilRenderPass; + + // This is a handle to be used to quickly get a GrVkRenderPass that is compatible with + // this render target if its stencil buffer is ignored. GrVkResourceProvider::CompatibleRPHandle fCompatibleRPHandle; + // Same as above but taking the render target's stencil buffer into account + GrVkResourceProvider::CompatibleRPHandle fCompatibleStencilRPHandle; // If this render target wraps an external VkCommandBuffer, then this handle will be that // VkCommandBuffer and not VK_NULL_HANDLE. In this case the render target will not be backed by diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.cpp index 017310a8419..e5c2785335b 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.cpp @@ -102,12 +102,13 @@ GrVkPipeline* GrVkResourceProvider::createPipeline(const GrProgramInfo& programI // RenderPasses as needed that are compatible with the framebuffer. const GrVkRenderPass* GrVkResourceProvider::findCompatibleRenderPass(const GrVkRenderTarget& target, - CompatibleRPHandle* compatibleHandle) { + CompatibleRPHandle* compatibleHandle, + bool withStencil) { // Get attachment information from render target. This includes which attachments the render // target has (color, stencil) and the attachments format and sample count. GrVkRenderPass::AttachmentFlags attachmentFlags; GrVkRenderPass::AttachmentsDescriptor attachmentsDesc; - target.getAttachmentsDescriptor(&attachmentsDesc, &attachmentFlags); + target.getAttachmentsDescriptor(&attachmentsDesc, &attachmentFlags, withStencil); return this->findCompatibleRenderPass(&attachmentsDesc, attachmentFlags, compatibleHandle); } @@ -164,11 +165,12 @@ const GrVkRenderPass* GrVkResourceProvider::findRenderPass( GrVkRenderTarget* target, const GrVkRenderPass::LoadStoreOps& colorOps, const GrVkRenderPass::LoadStoreOps& stencilOps, - CompatibleRPHandle* compatibleHandle) { + CompatibleRPHandle* compatibleHandle, + bool withStencil) { GrVkResourceProvider::CompatibleRPHandle tempRPHandle; GrVkResourceProvider::CompatibleRPHandle* pRPHandle = compatibleHandle ? compatibleHandle : &tempRPHandle; - *pRPHandle = target->compatibleRenderPassHandle(); + *pRPHandle = target->compatibleRenderPassHandle(withStencil); if (!pRPHandle->isValid()) { return nullptr; } @@ -363,12 +365,11 @@ void GrVkResourceProvider::checkCommandBuffers() { } void GrVkResourceProvider::addFinishedProcToActiveCommandBuffers( - GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) { - sk_sp<GrRefCntedCallback> procRef(new GrRefCntedCallback(finishedProc, finishedContext)); + sk_sp<GrRefCntedCallback> finishedCallback) { for (int i = 0; i < fActiveCommandPools.count(); ++i) { GrVkCommandPool* pool = fActiveCommandPools[i]; GrVkPrimaryCommandBuffer* buffer = pool->getPrimaryCommandBuffer(); - buffer->addFinishedProc(procRef); + buffer->addFinishedProc(finishedCallback); } } diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.h b/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.h index d4ef8632aef..a3d72cf8b98 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.h @@ -57,7 +57,8 @@ public: // non null it will be set to a handle that can be used in the furutre to quickly return a // compatible GrVkRenderPasses without the need inspecting a GrVkRenderTarget. const GrVkRenderPass* findCompatibleRenderPass(const GrVkRenderTarget& target, - CompatibleRPHandle* compatibleHandle = nullptr); + CompatibleRPHandle* compatibleHandle, + bool withStencil); const GrVkRenderPass* findCompatibleRenderPass(GrVkRenderPass::AttachmentsDescriptor*, GrVkRenderPass::AttachmentFlags, CompatibleRPHandle* compatibleHandle = nullptr); @@ -73,7 +74,8 @@ public: const GrVkRenderPass* findRenderPass(GrVkRenderTarget* target, const GrVkRenderPass::LoadStoreOps& colorOps, const GrVkRenderPass::LoadStoreOps& stencilOps, - CompatibleRPHandle* compatibleHandle = nullptr); + CompatibleRPHandle* compatibleHandle, + bool withStencil); // The CompatibleRPHandle must be a valid handle previously set by a call to findRenderPass or // findCompatibleRenderPass. @@ -89,8 +91,7 @@ public: // that the client cares about before they explicitly called flush and the GPU may reorder // command execution. So we make sure all previously submitted work finishes before we call the // finishedProc. - void addFinishedProcToActiveCommandBuffers(GrGpuFinishedProc finishedProc, - GrGpuFinishedContext finishedContext); + void addFinishedProcToActiveCommandBuffers(sk_sp<GrRefCntedCallback> finishedCallback); // Finds or creates a compatible GrVkDescriptorPool for the requested type and count. // The refcount is incremented and a pointer returned. diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.h b/chromium/third_party/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.h index 05c10b848ba..829129841ff 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.h @@ -23,7 +23,7 @@ public: struct Key { Key() : fVkFormat(VK_FORMAT_UNDEFINED), fExternalFormat(0), fConversionKey(0) {} - Key(VkFormat vkFormat, uint64_t externalFormat, uint8_t conversionKey) { + Key(VkFormat vkFormat, int64_t externalFormat, uint8_t conversionKey) { memset(this, 0, sizeof(Key)); fVkFormat = vkFormat; fExternalFormat = externalFormat; @@ -31,7 +31,7 @@ public: } VkFormat fVkFormat; - uint64_t fExternalFormat; + int64_t fExternalFormat; uint8_t fConversionKey; bool operator==(const Key& that) const { diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkSemaphore.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkSemaphore.cpp index ee68cdd68a3..23bf656bf86 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkSemaphore.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkSemaphore.cpp @@ -38,6 +38,7 @@ std::unique_ptr<GrVkSemaphore> GrVkSemaphore::MakeWrapped(GrVkGpu* gpu, WrapType wrapType, GrWrapOwnership ownership) { if (VK_NULL_HANDLE == semaphore) { + SkDEBUGFAIL("Trying to wrap an invalid VkSemaphore"); return nullptr; } bool prohibitSignal = WrapType::kWillWait == wrapType; diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.cpp index 3236ac2a0b8..63a90ddb647 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.cpp @@ -17,10 +17,10 @@ GrVkStencilAttachment::GrVkStencilAttachment(GrVkGpu* gpu, const Format& format, const GrVkImage::ImageDesc& desc, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageView* stencilView) : GrStencilAttachment(gpu, desc.fWidth, desc.fHeight, format.fStencilBits, desc.fSamples) - , GrVkImage(gpu, info, std::move(layout), GrBackendObjectOwnership::kOwned) + , GrVkImage(gpu, info, std::move(mutableState), GrBackendObjectOwnership::kOwned) , fStencilView(stencilView) { this->registerWithCache(SkBudgeted::kYes); stencilView->ref(); @@ -57,9 +57,11 @@ GrVkStencilAttachment* GrVkStencilAttachment::Create(GrVkGpu* gpu, return nullptr; } - sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(info.fImageLayout)); + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState(new GrBackendSurfaceMutableStateImpl( + info.fImageLayout, info.fCurrentQueueFamily)); GrVkStencilAttachment* stencil = new GrVkStencilAttachment(gpu, format, imageDesc, - info, std::move(layout), imageView); + info, std::move(mutableState), + imageView); imageView->unref(); return stencil; @@ -79,8 +81,7 @@ size_t GrVkStencilAttachment::onGpuMemorySize() const { } void GrVkStencilAttachment::onRelease() { - GrVkGpu* gpu = this->getVkGpu(); - this->releaseImage(gpu); + this->releaseImage(); fStencilView->unref(); fStencilView = nullptr; @@ -88,8 +89,7 @@ void GrVkStencilAttachment::onRelease() { } void GrVkStencilAttachment::onAbandon() { - GrVkGpu* gpu = this->getVkGpu(); - this->releaseImage(gpu); + this->releaseImage(); fStencilView->unref(); fStencilView = nullptr; diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.h b/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.h index 8accd289fa4..ad96fae5178 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.h @@ -41,7 +41,7 @@ private: const Format& format, const GrVkImage::ImageDesc&, const GrVkImageInfo&, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageView* stencilView); GrVkGpu* getVkGpu() const; diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkTexture.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkTexture.cpp index ce3f49a0dd1..c930a288a59 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkTexture.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkTexture.cpp @@ -23,11 +23,11 @@ GrVkTexture::GrVkTexture(GrVkGpu* gpu, SkBudgeted budgeted, SkISize dimensions, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageView* view, GrMipMapsStatus mipMapsStatus) : GrSurface(gpu, dimensions, info.fProtected) - , GrVkImage(gpu, info, std::move(layout), GrBackendObjectOwnership::kOwned) + , GrVkImage(gpu, info, std::move(mutableState), GrBackendObjectOwnership::kOwned) , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus) , fTextureView(view) , fDescSetCache(kMaxCachedDescSets) { @@ -41,11 +41,12 @@ GrVkTexture::GrVkTexture(GrVkGpu* gpu, } GrVkTexture::GrVkTexture(GrVkGpu* gpu, SkISize dimensions, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, const GrVkImageView* view, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, + const GrVkImageView* view, GrMipMapsStatus mipMapsStatus, GrBackendObjectOwnership ownership, GrWrapCacheable cacheable, GrIOType ioType, bool isExternal) : GrSurface(gpu, dimensions, info.fProtected) - , GrVkImage(gpu, info, std::move(layout), ownership) + , GrVkImage(gpu, info, std::move(mutableState), ownership) , INHERITED(gpu, dimensions, info.fProtected, isExternal ? GrTextureType::kExternal : GrTextureType::k2D, mipMapsStatus) , fTextureView(view) @@ -61,12 +62,12 @@ GrVkTexture::GrVkTexture(GrVkGpu* gpu, SkISize dimensions, const GrVkImageInfo& GrVkTexture::GrVkTexture(GrVkGpu* gpu, SkISize dimensions, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageView* view, GrMipMapsStatus mipMapsStatus, GrBackendObjectOwnership ownership) : GrSurface(gpu, dimensions, info.fProtected) - , GrVkImage(gpu, info, layout, ownership) + , GrVkImage(gpu, info, std::move(mutableState), ownership) , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus) , fTextureView(view) , fDescSetCache(kMaxCachedDescSets) { @@ -94,19 +95,16 @@ sk_sp<GrVkTexture> GrVkTexture::MakeNewTexture(GrVkGpu* gpu, SkBudgeted budgeted GrVkImage::DestroyImageInfo(gpu, &info); return nullptr; } - sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(info.fImageLayout)); - - return sk_sp<GrVkTexture>(new GrVkTexture(gpu, budgeted, dimensions, info, std::move(layout), - imageView, mipMapsStatus)); + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState( + new GrBackendSurfaceMutableStateImpl(info.fImageLayout, info.fCurrentQueueFamily)); + return sk_sp<GrVkTexture>(new GrVkTexture(gpu, budgeted, dimensions, info, + std::move(mutableState), imageView, mipMapsStatus)); } -sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu, - SkISize dimensions, - GrWrapOwnership wrapOwnership, - GrWrapCacheable cacheable, - GrIOType ioType, - const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout) { +sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture( + GrVkGpu* gpu, SkISize dimensions, GrWrapOwnership wrapOwnership, GrWrapCacheable cacheable, + GrIOType ioType, const GrVkImageInfo& info, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState) { // Adopted textures require both image and allocation because we're responsible for freeing SkASSERT(VK_NULL_HANDLE != info.fImage && (kBorrow_GrWrapOwnership == wrapOwnership || VK_NULL_HANDLE != info.fAlloc.fMemory)); @@ -125,9 +123,9 @@ sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu, ? GrBackendObjectOwnership::kBorrowed : GrBackendObjectOwnership::kOwned; bool isExternal = info.fYcbcrConversionInfo.isValid() && (info.fYcbcrConversionInfo.fExternalFormat != 0); - return sk_sp<GrVkTexture>(new GrVkTexture(gpu, dimensions, info, std::move(layout), imageView, - mipMapsStatus, ownership, cacheable, ioType, - isExternal)); + return sk_sp<GrVkTexture>(new GrVkTexture(gpu, dimensions, info, std::move(mutableState), + imageView, mipMapsStatus, ownership, cacheable, + ioType, isExternal)); } GrVkTexture::~GrVkTexture() { @@ -151,7 +149,7 @@ void GrVkTexture::onRelease() { fDescSetCache.reset(); - this->releaseImage(this->getVkGpu()); + this->releaseImage(); INHERITED::onRelease(); } @@ -185,12 +183,12 @@ void GrVkTexture::onAbandon() { fDescSetCache.reset(); - this->releaseImage(this->getVkGpu()); + this->releaseImage(); INHERITED::onAbandon(); } GrBackendTexture GrVkTexture::getBackendTexture() const { - return GrBackendTexture(this->width(), this->height(), fInfo, this->grVkImageLayout()); + return GrBackendTexture(this->width(), this->height(), fInfo, this->getMutableState()); } GrVkGpu* GrVkTexture::getVkGpu() const { diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkTexture.h b/chromium/third_party/skia/src/gpu/vk/GrVkTexture.h index 6a13f5af3a0..d719ef16973 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkTexture.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkTexture.h @@ -33,7 +33,7 @@ public: GrWrapCacheable, GrIOType, const GrVkImageInfo&, - sk_sp<GrVkImageLayout>); + sk_sp<GrBackendSurfaceMutableStateImpl>); ~GrVkTexture() override; @@ -61,7 +61,7 @@ protected: GrVkTexture(GrVkGpu*, SkISize dimensions, const GrVkImageInfo&, - sk_sp<GrVkImageLayout>, + sk_sp<GrBackendSurfaceMutableStateImpl>, const GrVkImageView*, GrMipMapsStatus, GrBackendObjectOwnership); @@ -78,9 +78,10 @@ protected: void willRemoveLastRef() override; private: - GrVkTexture(GrVkGpu*, SkBudgeted, SkISize, const GrVkImageInfo&, sk_sp<GrVkImageLayout> layout, - const GrVkImageView* imageView, GrMipMapsStatus); - GrVkTexture(GrVkGpu*, SkISize, const GrVkImageInfo&, sk_sp<GrVkImageLayout>, + GrVkTexture(GrVkGpu*, SkBudgeted, SkISize, const GrVkImageInfo&, + sk_sp<GrBackendSurfaceMutableStateImpl>, const GrVkImageView* imageView, + GrMipMapsStatus); + GrVkTexture(GrVkGpu*, SkISize, const GrVkImageInfo&, sk_sp<GrBackendSurfaceMutableStateImpl>, const GrVkImageView*, GrMipMapsStatus, GrBackendObjectOwnership, GrWrapCacheable, GrIOType, bool isExternal); diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.cpp index 0ce652a4ba0..39d87d33bc0 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.cpp @@ -18,82 +18,87 @@ #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X) -GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu, - SkBudgeted budgeted, - SkISize dimensions, - int sampleCnt, - const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, - const GrVkImageView* texView, - const GrVkImageInfo& msaaInfo, - sk_sp<GrVkImageLayout> msaaLayout, - const GrVkImageView* colorAttachmentView, - const GrVkImageView* resolveAttachmentView, - GrMipMapsStatus mipMapsStatus) +GrVkTextureRenderTarget::GrVkTextureRenderTarget( + GrVkGpu* gpu, + SkBudgeted budgeted, + SkISize dimensions, + int sampleCnt, + const GrVkImageInfo& info, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, + const GrVkImageView* texView, + const GrVkImageInfo& msaaInfo, + sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState, + const GrVkImageView* colorAttachmentView, + const GrVkImageView* resolveAttachmentView, + GrMipMapsStatus mipMapsStatus) : GrSurface(gpu, dimensions, info.fProtected) - , GrVkImage(gpu, info, layout, GrBackendObjectOwnership::kOwned) - , GrVkTexture(gpu, dimensions, info, layout, texView, mipMapsStatus, + , GrVkImage(gpu, info, mutableState, GrBackendObjectOwnership::kOwned) + , GrVkTexture(gpu, dimensions, info, mutableState, texView, mipMapsStatus, GrBackendObjectOwnership::kOwned) - , GrVkRenderTarget(gpu, dimensions, sampleCnt, info, layout, msaaInfo, - std::move(msaaLayout), colorAttachmentView, resolveAttachmentView, + , GrVkRenderTarget(gpu, dimensions, sampleCnt, info, std::move(mutableState), msaaInfo, + std::move(msaaMutableState), colorAttachmentView, resolveAttachmentView, GrBackendObjectOwnership::kOwned) { SkASSERT(info.fProtected == msaaInfo.fProtected); this->registerWithCache(budgeted); } -GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu, - SkBudgeted budgeted, - SkISize dimensions, - const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, - const GrVkImageView* texView, - const GrVkImageView* colorAttachmentView, - GrMipMapsStatus mipMapsStatus) +GrVkTextureRenderTarget::GrVkTextureRenderTarget( + GrVkGpu* gpu, + SkBudgeted budgeted, + SkISize dimensions, + const GrVkImageInfo& info, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, + const GrVkImageView* texView, + const GrVkImageView* colorAttachmentView, + GrMipMapsStatus mipMapsStatus) : GrSurface(gpu, dimensions, info.fProtected) - , GrVkImage(gpu, info, layout, GrBackendObjectOwnership::kOwned) - , GrVkTexture(gpu, dimensions, info, layout, texView, mipMapsStatus, + , GrVkImage(gpu, info, mutableState, GrBackendObjectOwnership::kOwned) + , GrVkTexture(gpu, dimensions, info, mutableState, texView, mipMapsStatus, GrBackendObjectOwnership::kOwned) - , GrVkRenderTarget(gpu, dimensions, info, layout, colorAttachmentView, + , GrVkRenderTarget(gpu, dimensions, info, std::move(mutableState), colorAttachmentView, GrBackendObjectOwnership::kOwned) { this->registerWithCache(budgeted); } -GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu, - SkISize dimensions, - int sampleCnt, - const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, - const GrVkImageView* texView, - const GrVkImageInfo& msaaInfo, - sk_sp<GrVkImageLayout> msaaLayout, - const GrVkImageView* colorAttachmentView, - const GrVkImageView* resolveAttachmentView, - GrMipMapsStatus mipMapsStatus, - GrBackendObjectOwnership ownership, - GrWrapCacheable cacheable) +GrVkTextureRenderTarget::GrVkTextureRenderTarget( + GrVkGpu* gpu, + SkISize dimensions, + int sampleCnt, + const GrVkImageInfo& info, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, + const GrVkImageView* texView, + const GrVkImageInfo& msaaInfo, + sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState, + const GrVkImageView* colorAttachmentView, + const GrVkImageView* resolveAttachmentView, + GrMipMapsStatus mipMapsStatus, + GrBackendObjectOwnership ownership, + GrWrapCacheable cacheable) : GrSurface(gpu, dimensions, info.fProtected) - , GrVkImage(gpu, info, layout, ownership) - , GrVkTexture(gpu, dimensions, info, layout, texView, mipMapsStatus, ownership) - , GrVkRenderTarget(gpu, dimensions, sampleCnt, info, layout, msaaInfo, - std::move(msaaLayout), colorAttachmentView, resolveAttachmentView, + , GrVkImage(gpu, info, mutableState, ownership) + , GrVkTexture(gpu, dimensions, info, mutableState, texView, mipMapsStatus, ownership) + , GrVkRenderTarget(gpu, dimensions, sampleCnt, info, std::move(mutableState), msaaInfo, + std::move(msaaMutableState), colorAttachmentView, resolveAttachmentView, ownership) { SkASSERT(info.fProtected == msaaInfo.fProtected); this->registerWithCacheWrapped(cacheable); } -GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu, - SkISize dimensions, - const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, - const GrVkImageView* texView, - const GrVkImageView* colorAttachmentView, - GrMipMapsStatus mipMapsStatus, - GrBackendObjectOwnership ownership, - GrWrapCacheable cacheable) +GrVkTextureRenderTarget::GrVkTextureRenderTarget( + GrVkGpu* gpu, + SkISize dimensions, + const GrVkImageInfo& info, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, + const GrVkImageView* texView, + const GrVkImageView* colorAttachmentView, + GrMipMapsStatus mipMapsStatus, + GrBackendObjectOwnership ownership, + GrWrapCacheable cacheable) : GrSurface(gpu, dimensions, info.fProtected) - , GrVkImage(gpu, info, layout, ownership) - , GrVkTexture(gpu, dimensions, info, layout, texView, mipMapsStatus, ownership) - , GrVkRenderTarget(gpu, dimensions, info, layout, colorAttachmentView, ownership) { + , GrVkImage(gpu, info, mutableState, ownership) + , GrVkTexture(gpu, dimensions, info, mutableState, texView, mipMapsStatus, ownership) + , GrVkRenderTarget(gpu, dimensions, info, std::move(mutableState), colorAttachmentView, + ownership) { this->registerWithCacheWrapped(cacheable); } @@ -103,7 +108,7 @@ struct Views { const GrVkImageView* colorAttachmentView = nullptr; const GrVkImageView* resolveAttachmentView = nullptr; GrVkImageInfo msInfo; - sk_sp<GrVkImageLayout> msLayout; + sk_sp<GrBackendSurfaceMutableStateImpl> msMutableState; }; } // anonymous namespace @@ -154,7 +159,8 @@ static Views create_views(GrVkGpu* gpu, SkISize dimensions, int sampleCnt, views.imageView->unref(); return {}; } - views.msLayout.reset(new GrVkImageLayout(views.msInfo.fImageLayout)); + views.msMutableState.reset(new GrBackendSurfaceMutableStateImpl( + views.msInfo.fImageLayout, views.msInfo.fCurrentQueueFamily)); } else { // Set color attachment image colorImage = info.fImage; @@ -187,7 +193,8 @@ sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeNewTextureRenderTarg if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) { return nullptr; } - sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(info.fImageLayout)); + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState( + new GrBackendSurfaceMutableStateImpl(info.fImageLayout, info.fCurrentQueueFamily)); Views views = create_views(gpu, dimensions, sampleCnt, info); if (!views.colorAttachmentView) { @@ -196,12 +203,12 @@ sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeNewTextureRenderTarg } if (sampleCnt > 1) { return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget( - gpu, budgeted, dimensions, sampleCnt, info, std::move(layout), views.imageView, - views.msInfo, std::move(views.msLayout), views.colorAttachmentView, - views.resolveAttachmentView, mipMapsStatus)); + gpu, budgeted, dimensions, sampleCnt, info, std::move(mutableState), + views.imageView, views.msInfo, std::move(views.msMutableState), + views.colorAttachmentView, views.resolveAttachmentView, mipMapsStatus)); } else { return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget( - gpu, budgeted, dimensions, info, std::move(layout), views.imageView, + gpu, budgeted, dimensions, info, std::move(mutableState), views.imageView, views.colorAttachmentView, mipMapsStatus)); } } @@ -213,7 +220,7 @@ sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeWrappedTextureRender GrWrapOwnership wrapOwnership, GrWrapCacheable cacheable, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout) { + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState) { // Adopted textures require both image and allocation because we're responsible for freeing SkASSERT(VK_NULL_HANDLE != info.fImage && (kBorrow_GrWrapOwnership == wrapOwnership || VK_NULL_HANDLE != info.fAlloc.fMemory)); @@ -229,12 +236,12 @@ sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeWrappedTextureRender } if (sampleCnt > 1) { return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget( - gpu, dimensions, sampleCnt, info, std::move(layout), views.imageView, views.msInfo, - std::move(views.msLayout), views.colorAttachmentView, views.resolveAttachmentView, - mipMapsStatus, ownership, cacheable)); + gpu, dimensions, sampleCnt, info, std::move(mutableState), views.imageView, + views.msInfo, std::move(views.msMutableState), views.colorAttachmentView, + views.resolveAttachmentView, mipMapsStatus, ownership, cacheable)); } else { return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget( - gpu, dimensions, info, std::move(layout), views.imageView, + gpu, dimensions, info, std::move(mutableState), views.imageView, views.colorAttachmentView, mipMapsStatus, ownership, cacheable)); } } diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.h b/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.h index e3191751819..adc352d48fa 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.h @@ -32,13 +32,14 @@ public: const GrVkImage::ImageDesc&, GrMipMapsStatus); - static sk_sp<GrVkTextureRenderTarget> MakeWrappedTextureRenderTarget(GrVkGpu*, - SkISize dimensions, - int sampleCnt, - GrWrapOwnership, - GrWrapCacheable, - const GrVkImageInfo&, - sk_sp<GrVkImageLayout>); + static sk_sp<GrVkTextureRenderTarget> MakeWrappedTextureRenderTarget( + GrVkGpu*, + SkISize dimensions, + int sampleCnt, + GrWrapOwnership, + GrWrapCacheable, + const GrVkImageInfo&, + sk_sp<GrBackendSurfaceMutableStateImpl>); GrBackendFormat backendFormat() const override { return this->getBackendFormat(); } @@ -62,10 +63,10 @@ private: SkISize dimensions, int sampleCnt, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageView* texView, const GrVkImageInfo& msaaInfo, - sk_sp<GrVkImageLayout> msaaLayout, + sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState, const GrVkImageView* colorAttachmentView, const GrVkImageView* resolveAttachmentView, GrMipMapsStatus); @@ -75,7 +76,7 @@ private: SkBudgeted budgeted, SkISize dimensions, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageView* texView, const GrVkImageView* colorAttachmentView, GrMipMapsStatus); @@ -85,10 +86,10 @@ private: SkISize dimensions, int sampleCnt, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageView* texView, const GrVkImageInfo& msaaInfo, - sk_sp<GrVkImageLayout> msaaLayout, + sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState, const GrVkImageView* colorAttachmentView, const GrVkImageView* resolveAttachmentView, GrMipMapsStatus, @@ -99,7 +100,7 @@ private: GrVkTextureRenderTarget(GrVkGpu* gpu, SkISize dimensions, const GrVkImageInfo& info, - sk_sp<GrVkImageLayout> layout, + sk_sp<GrBackendSurfaceMutableStateImpl> mutableState, const GrVkImageView* texView, const GrVkImageView* colorAttachmentView, GrMipMapsStatus, diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkTypesPriv.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkTypesPriv.cpp index 6f5d0b27f23..5360ab46b5d 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkTypesPriv.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkTypesPriv.cpp @@ -7,44 +7,32 @@ #include "include/private/GrVkTypesPriv.h" +#include "src/gpu/GrBackendSurfaceMutableStateImpl.h" #include "src/gpu/vk/GrVkImageLayout.h" -void GrVkBackendSurfaceInfo::cleanup() { - SkSafeUnref(fLayout); - fLayout = nullptr; -}; +void GrVkBackendSurfaceInfo::cleanup() {}; void GrVkBackendSurfaceInfo::assign(const GrVkBackendSurfaceInfo& that, bool isThisValid) { fImageInfo = that.fImageInfo; - GrVkImageLayout* oldLayout = fLayout; - fLayout = SkSafeRef(that.fLayout); - if (isThisValid) { - SkSafeUnref(oldLayout); - } } -void GrVkBackendSurfaceInfo::setImageLayout(VkImageLayout layout) { - SkASSERT(fLayout); - fLayout->setImageLayout(layout); -} - -sk_sp<GrVkImageLayout> GrVkBackendSurfaceInfo::getGrVkImageLayout() const { - SkASSERT(fLayout); - return sk_ref_sp(fLayout); -} - -GrVkImageInfo GrVkBackendSurfaceInfo::snapImageInfo() const { - return GrVkImageInfo(fImageInfo, fLayout->getImageLayout()); +GrVkImageInfo GrVkBackendSurfaceInfo::snapImageInfo( + const GrBackendSurfaceMutableStateImpl* mutableState) const { + SkASSERT(mutableState); + return GrVkImageInfo(fImageInfo, mutableState->getImageLayout(), + mutableState->getQueueFamilyIndex()); } #if GR_TEST_UTILS bool GrVkBackendSurfaceInfo::operator==(const GrVkBackendSurfaceInfo& that) const { GrVkImageInfo cpyInfoThis = fImageInfo; GrVkImageInfo cpyInfoThat = that.fImageInfo; - // We don't care about the fImageLayout here since we require they use the same - // GrVkImageLayout. + // We don't care about the fImageLayout or fCurrentQueueFamily here since we require they use + // the same mutableState. cpyInfoThis.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; cpyInfoThat.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - return cpyInfoThis == cpyInfoThat && fLayout == that.fLayout; + cpyInfoThis.fCurrentQueueFamily = VK_QUEUE_FAMILY_IGNORED; + cpyInfoThat.fCurrentQueueFamily = VK_QUEUE_FAMILY_IGNORED; + return cpyInfoThis == cpyInfoThat; } #endif diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkUtil.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkUtil.cpp index bd73858bd65..892d6055831 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkUtil.cpp +++ b/chromium/third_party/skia/src/gpu/vk/GrVkUtil.cpp @@ -151,12 +151,3 @@ bool GrVkFormatIsCompressed(VkFormat vkFormat) { SkUNREACHABLE; } -SkImage::CompressionType GrVkFormatToCompressionType(VkFormat vkFormat) { - switch (vkFormat) { - case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: return SkImage::CompressionType::kETC2_RGB8_UNORM; - case VK_FORMAT_BC1_RGB_UNORM_BLOCK: return SkImage::CompressionType::kBC1_RGB8_UNORM; - case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: return SkImage::CompressionType::kBC1_RGBA8_UNORM; - default: return SkImage::CompressionType::kNone; - } - SkUNREACHABLE; -} diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkUtil.h b/chromium/third_party/skia/src/gpu/vk/GrVkUtil.h index e66cd81fc9f..ba24ea4d2d6 100644 --- a/chromium/third_party/skia/src/gpu/vk/GrVkUtil.h +++ b/chromium/third_party/skia/src/gpu/vk/GrVkUtil.h @@ -21,25 +21,31 @@ class GrVkGpu; // makes a Vk call on the interface #define GR_VK_CALL(IFACE, X) (IFACE)->fFunctions.f##X -#define GR_VK_CALL_RESULT(GPU, RESULT, X) \ - do { \ - (RESULT) = GR_VK_CALL(GPU->vkInterface(), X); \ - SkASSERT(VK_SUCCESS == RESULT || VK_ERROR_DEVICE_LOST == RESULT); \ - if (RESULT != VK_SUCCESS && !GPU->isDeviceLost()) { \ - SkDebugf("Failed vulkan call. Error: %d\n", RESULT); \ - } \ - if (VK_ERROR_DEVICE_LOST == RESULT) { \ - GPU->setDeviceLost(); \ - } \ - } while(false) - -#define GR_VK_CALL_RESULT_NOCHECK(GPU, RESULT, X) \ - do { \ - (RESULT) = GR_VK_CALL(GPU->vkInterface(), X); \ - if (VK_ERROR_DEVICE_LOST == RESULT) { \ - GPU->setDeviceLost(); \ - } \ - } while(false) +#define GR_VK_CALL_RESULT(GPU, RESULT, X) \ + do { \ + (RESULT) = GR_VK_CALL(GPU->vkInterface(), X); \ + SkASSERT(VK_SUCCESS == RESULT || VK_ERROR_DEVICE_LOST == RESULT); \ + if (RESULT != VK_SUCCESS && !GPU->isDeviceLost()) { \ + SkDebugf("Failed vulkan call. Error: %d," #X "\n", RESULT); \ + } \ + if (RESULT == VK_ERROR_DEVICE_LOST) { \ + GPU->setDeviceLost(); \ + } else if (RESULT == VK_ERROR_OUT_OF_HOST_MEMORY || \ + RESULT == VK_ERROR_OUT_OF_DEVICE_MEMORY) { \ + GPU->setOOMed(); \ + } \ + } while (false) + +#define GR_VK_CALL_RESULT_NOCHECK(GPU, RESULT, X) \ + do { \ + (RESULT) = GR_VK_CALL(GPU->vkInterface(), X); \ + if (RESULT == VK_ERROR_DEVICE_LOST) { \ + GPU->setDeviceLost(); \ + } else if (RESULT == VK_ERROR_OUT_OF_HOST_MEMORY || \ + RESULT == VK_ERROR_OUT_OF_DEVICE_MEMORY) { \ + GPU->setOOMed(); \ + } \ + } while (false) // same as GR_VK_CALL but checks for success #define GR_VK_CALL_ERRCHECK(GPU, X) \ @@ -101,11 +107,6 @@ bool GrInstallVkShaderModule(GrVkGpu* gpu, */ bool GrVkFormatIsCompressed(VkFormat); -/** - * Maps a vk format into the CompressionType enum if applicable. - */ -SkImage::CompressionType GrVkFormatToCompressionType(VkFormat vkFormat); - #if GR_TEST_UTILS static constexpr const char* GrVkFormatToStr(VkFormat vkFormat) { switch (vkFormat) { |