1/* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "src/gpu/GrCaps.h" 9 10#include "include/gpu/GrBackendSurface.h" 11#include "include/gpu/GrContextOptions.h" 12#include "include/private/GrTypesPriv.h" 13#include "src/gpu/GrBackendUtils.h" 14#include "src/gpu/GrRenderTargetProxy.h" 15#include "src/gpu/GrSurface.h" 16#include "src/gpu/GrSurfaceProxy.h" 17#include "src/gpu/GrWindowRectangles.h" 18 19GrCaps::GrCaps(const GrContextOptions& options) { 20 fMipmapSupport = false; 21 fNPOTTextureTileSupport = false; 22 fReuseScratchTextures = true; 23 fReuseScratchBuffers = true; 24 fGpuTracingSupport = false; 25 fOversizedStencilSupport = false; 26 fTextureBarrierSupport = false; 27 fSampleLocationsSupport = false; 28 fDrawInstancedSupport = false; 29 fNativeDrawIndirectSupport = false; 30 fUseClientSideIndirectBuffers = false; 31 fConservativeRasterSupport = false; 32 fWireframeSupport = false; 33 fMSAAResolvesAutomatically = false; 34 fUsePrimitiveRestart = false; 35 fPreferClientSideDynamicBuffers = false; 36 fPreferFullscreenClears = false; 37 fTwoSidedStencilRefsAndMasksMustMatch = false; 38 fMustClearUploadedBufferData = false; 39 fShouldInitializeTextures = false; 40 fSupportsAHardwareBufferImages = false; 41 fFenceSyncSupport = false; 42 fSemaphoreSupport = false; 43 fCrossContextTextureSupport = false; 44 fHalfFloatVertexAttributeSupport = false; 45 fDynamicStateArrayGeometryProcessorTextureSupport = false; 46 fPerformPartialClearsAsDraws = false; 47 fPerformColorClearsAsDraws = false; 48 fAvoidLargeIndexBufferDraws = false; 49 fPerformStencilClearsAsDraws = false; 50 fTransferFromBufferToTextureSupport = false; 51 fTransferFromSurfaceToBufferSupport = false; 52 fWritePixelsRowBytesSupport = false; 53 fTransferPixelsToRowBytesSupport = false; 54 fReadPixelsRowBytesSupport = false; 55 fShouldCollapseSrcOverToSrcWhenAble = false; 56 fMustSyncGpuDuringAbandon = true; 57 fDriverDisableMSAAClipAtlas = false; 58 fDisableTessellationPathRenderer = false; 59 60 fBlendEquationSupport = kBasic_BlendEquationSupport; 61 fAdvBlendEqDisableFlags = 0; 62 63 fMapBufferFlags = kNone_MapFlags; 64 65 fMaxVertexAttributes = 0; 66 fMaxRenderTargetSize = 1; 67 fMaxPreferredRenderTargetSize = 1; 68 fMaxTextureSize = 1; 69 fMaxWindowRectangles = 0; 70 fInternalMultisampleCount = 0; 71 72 fSuppressPrints = options.fSuppressPrints; 73#if GR_TEST_UTILS 74 fWireframeMode = options.fWireframeMode; 75#else 76 fWireframeMode = false; 77#endif 78 fBufferMapThreshold = options.fBufferMapThreshold; 79 fAvoidStencilBuffers = false; 80 fAvoidWritePixelsFastPath = false; 81 fRequiresManualFBBarrierAfterTessellatedStencilDraw = false; 82 fNativeDrawIndexedIndirectIsBroken = false; 83 fAvoidReorderingRenderTasks = false; 84 fAvoidDithering = false; 85 86 fPreferVRAMUseOverFlushes = true; 87 88 // Default to true, allow older versions of OpenGL to disable explicitly 89 fClampToBorderSupport = true; 90 91 fDriverBugWorkarounds = options.fDriverBugWorkarounds; 92} 93 94void GrCaps::finishInitialization(const GrContextOptions& options) { 95 if (!fNativeDrawIndirectSupport) { 96 // We will implement indirect draws with a polyfill, so the commands need to reside in CPU 97 // memory. 98 fUseClientSideIndirectBuffers = true; 99 } 100 101 this->applyOptionsOverrides(options); 102 103 // Our render targets are always created with textures as the color attachment, hence this min: 104 fMaxRenderTargetSize = std::min(fMaxRenderTargetSize, fMaxTextureSize); 105 fMaxPreferredRenderTargetSize = std::min(fMaxPreferredRenderTargetSize, fMaxRenderTargetSize); 106} 107 108void GrCaps::applyOptionsOverrides(const GrContextOptions& options) { 109 fShaderCaps->applyOptionsOverrides(options); 110 this->onApplyOptionsOverrides(options); 111 if (options.fDisableDriverCorrectnessWorkarounds) { 112 SkASSERT(!fDriverDisableMSAAClipAtlas); 113 SkASSERT(!fDisableTessellationPathRenderer); 114 SkASSERT(!fAvoidStencilBuffers); 115 SkASSERT(!fAvoidWritePixelsFastPath); 116 SkASSERT(!fRequiresManualFBBarrierAfterTessellatedStencilDraw); 117 SkASSERT(!fNativeDrawIndexedIndirectIsBroken); 118 SkASSERT(!fAdvBlendEqDisableFlags); 119 SkASSERT(!fPerformColorClearsAsDraws); 120 SkASSERT(!fPerformStencilClearsAsDraws); 121 // Don't check the partial-clear workaround, since that is a backend limitation, not a 122 // driver workaround (it just so happens the fallbacks are the same). 123 } 124 if (GrContextOptions::Enable::kNo == options.fUseDrawInsteadOfClear) { 125 fPerformColorClearsAsDraws = false; 126 fPerformStencilClearsAsDraws = false; 127 } else if (GrContextOptions::Enable::kYes == options.fUseDrawInsteadOfClear) { 128 fPerformColorClearsAsDraws = true; 129 fPerformStencilClearsAsDraws = true; 130 } 131 132 fMaxTextureSize = std::min(fMaxTextureSize, options.fMaxTextureSizeOverride); 133#if GR_TEST_UTILS 134 if (options.fSuppressAdvancedBlendEquations) { 135 fBlendEquationSupport = kBasic_BlendEquationSupport; 136 } 137 if (options.fClearAllTextures) { 138 fShouldInitializeTextures = true; 139 } 140 if (options.fDisallowWriteAndTransferPixelRowBytes) { 141 fWritePixelsRowBytesSupport = false; 142 fTransferPixelsToRowBytesSupport = false; 143 } 144 if (options.fAlwaysPreferHardwareTessellation) { 145 fMinPathVerbsForHwTessellation = fMinStrokeVerbsForHwTessellation = 0; 146 } 147#endif 148 if (options.fSuppressMipmapSupport) { 149 fMipmapSupport = false; 150 } 151 152 if (fMaxWindowRectangles > GrWindowRectangles::kMaxWindows) { 153 SkDebugf("WARNING: capping window rectangles at %i. HW advertises support for %i.\n", 154 GrWindowRectangles::kMaxWindows, fMaxWindowRectangles); 155 fMaxWindowRectangles = GrWindowRectangles::kMaxWindows; 156 } 157 158 fInternalMultisampleCount = options.fInternalMultisampleCount; 159 160 fAvoidStencilBuffers = options.fAvoidStencilBuffers; 161 162 fDriverBugWorkarounds.applyOverrides(options.fDriverBugWorkarounds); 163} 164 165 166#ifdef SK_ENABLE_DUMP_GPU 167#include "src/gpu/GrTestUtils.h" 168#include "src/utils/SkJSONWriter.h" 169 170static SkString map_flags_to_string(uint32_t flags) { 171 SkString str; 172 if (GrCaps::kNone_MapFlags == flags) { 173 str = "none"; 174 } else { 175 SkASSERT(GrCaps::kCanMap_MapFlag & flags); 176 SkDEBUGCODE(flags &= ~GrCaps::kCanMap_MapFlag); 177 str = "can_map"; 178 179 if (GrCaps::kSubset_MapFlag & flags) { 180 str.append(" partial"); 181 } else { 182 str.append(" full"); 183 } 184 SkDEBUGCODE(flags &= ~GrCaps::kSubset_MapFlag); 185 if (GrCaps::kAsyncRead_MapFlag & flags) { 186 str.append(" async_read"); 187 } else { 188 str.append(" sync_read"); 189 } 190 SkDEBUGCODE(flags &= ~GrCaps::kAsyncRead_MapFlag); 191 } 192 SkASSERT(0 == flags); // Make sure we handled all the flags. 193 return str; 194} 195 196void GrCaps::dumpJSON(SkJSONWriter* writer) const { 197 writer->beginObject(); 198 199 writer->appendBool("MIP Map Support", fMipmapSupport); 200 writer->appendBool("NPOT Texture Tile Support", fNPOTTextureTileSupport); 201 writer->appendBool("Reuse Scratch Textures", fReuseScratchTextures); 202 writer->appendBool("Reuse Scratch Buffers", fReuseScratchBuffers); 203 writer->appendBool("Gpu Tracing Support", fGpuTracingSupport); 204 writer->appendBool("Oversized Stencil Support", fOversizedStencilSupport); 205 writer->appendBool("Texture Barrier Support", fTextureBarrierSupport); 206 writer->appendBool("Sample Locations Support", fSampleLocationsSupport); 207 writer->appendBool("Draw Instanced Support", fDrawInstancedSupport); 208 writer->appendBool("Native Draw Indirect Support", fNativeDrawIndirectSupport); 209 writer->appendBool("Use client side indirect buffers", fUseClientSideIndirectBuffers); 210 writer->appendBool("Conservative Raster Support", fConservativeRasterSupport); 211 writer->appendBool("Wireframe Support", fWireframeSupport); 212 writer->appendBool("MSAA Resolves Automatically", fMSAAResolvesAutomatically); 213 writer->appendBool("Use primitive restart", fUsePrimitiveRestart); 214 writer->appendBool("Prefer client-side dynamic buffers", fPreferClientSideDynamicBuffers); 215 writer->appendBool("Prefer fullscreen clears (and stencil discard)", fPreferFullscreenClears); 216 writer->appendBool("Two-sided Stencil Refs And Masks Must Match", 217 fTwoSidedStencilRefsAndMasksMustMatch); 218 writer->appendBool("Must clear buffer memory", fMustClearUploadedBufferData); 219 writer->appendBool("Should initialize textures", fShouldInitializeTextures); 220 writer->appendBool("Supports importing AHardwareBuffers", fSupportsAHardwareBufferImages); 221 writer->appendBool("Fence sync support", fFenceSyncSupport); 222 writer->appendBool("Semaphore support", fSemaphoreSupport); 223 writer->appendBool("Cross context texture support", fCrossContextTextureSupport); 224 writer->appendBool("Half float vertex attribute support", fHalfFloatVertexAttributeSupport); 225 writer->appendBool("Specify GeometryProcessor textures as a dynamic state array", 226 fDynamicStateArrayGeometryProcessorTextureSupport); 227 writer->appendBool("Use draws for partial clears", fPerformPartialClearsAsDraws); 228 writer->appendBool("Use draws for color clears", fPerformColorClearsAsDraws); 229 writer->appendBool("Avoid Large IndexBuffer Draws", fAvoidLargeIndexBufferDraws); 230 writer->appendBool("Use draws for stencil clip clears", fPerformStencilClearsAsDraws); 231 writer->appendBool("Supports transfers from buffers to textures", 232 fTransferFromBufferToTextureSupport); 233 writer->appendBool("Supports transfers from textures to buffers", 234 fTransferFromSurfaceToBufferSupport); 235 writer->appendBool("Write pixels row bytes support", fWritePixelsRowBytesSupport); 236 writer->appendBool("Transfer pixels to row bytes support", fTransferPixelsToRowBytesSupport); 237 writer->appendBool("Read pixels row bytes support", fReadPixelsRowBytesSupport); 238 writer->appendBool("Disable msaa clip mask atlas on current driver [workaround]", 239 fDriverDisableMSAAClipAtlas); 240 writer->appendBool("Disable TessellationPathRenderer current driver [workaround]", 241 fDisableTessellationPathRenderer); 242 writer->appendBool("Clamp-to-border", fClampToBorderSupport); 243 244 writer->appendBool("Prefer VRAM Use over flushes [workaround]", fPreferVRAMUseOverFlushes); 245 writer->appendBool("Avoid stencil buffers [workaround]", fAvoidStencilBuffers); 246 writer->appendBool("Avoid writePixels fast path [workaround]", fAvoidWritePixelsFastPath); 247 writer->appendBool("Requires manual FB barrier after tessellated stencilDraw [workaround]", 248 fRequiresManualFBBarrierAfterTessellatedStencilDraw); 249 writer->appendBool("Native draw indexed indirect is broken [workaround]", 250 fNativeDrawIndexedIndirectIsBroken); 251 writer->appendBool("Avoid DAG reordering [workaround]", fAvoidReorderingRenderTasks); 252 writer->appendBool("Avoid Dithering [workaround]", fAvoidDithering); 253 254 if (this->advancedBlendEquationSupport()) { 255 writer->appendHexU32("Advanced Blend Equation Disable Flags", fAdvBlendEqDisableFlags); 256 } 257 258 writer->appendS32("Max Vertex Attributes", fMaxVertexAttributes); 259 writer->appendS32("Max Texture Size", fMaxTextureSize); 260 writer->appendS32("Max Render Target Size", fMaxRenderTargetSize); 261 writer->appendS32("Max Preferred Render Target Size", fMaxPreferredRenderTargetSize); 262 writer->appendS32("Max Window Rectangles", fMaxWindowRectangles); 263 writer->appendS32("Sample Count for Internal MSAA", fInternalMultisampleCount); 264 writer->appendS32("Min Path Verbs for HW Tessellation", fMinPathVerbsForHwTessellation); 265 writer->appendS32("Min Stroke Verbs for HW Tessellation", fMinStrokeVerbsForHwTessellation); 266 267 static const char* kBlendEquationSupportNames[] = { 268 "Basic", 269 "Advanced", 270 "Advanced Coherent", 271 }; 272 static_assert(0 == kBasic_BlendEquationSupport); 273 static_assert(1 == kAdvanced_BlendEquationSupport); 274 static_assert(2 == kAdvancedCoherent_BlendEquationSupport); 275 static_assert(SK_ARRAY_COUNT(kBlendEquationSupportNames) == kLast_BlendEquationSupport + 1); 276 277 writer->appendString("Blend Equation Support", 278 kBlendEquationSupportNames[fBlendEquationSupport]); 279 writer->appendString("Map Buffer Support", map_flags_to_string(fMapBufferFlags).c_str()); 280 281 this->onDumpJSON(writer); 282 283 writer->appendName("shaderCaps"); 284 this->shaderCaps()->dumpJSON(writer); 285 286 writer->endObject(); 287} 288#else 289void GrCaps::dumpJSON(SkJSONWriter* writer) const { } 290#endif 291 292bool GrCaps::surfaceSupportsWritePixels(const GrSurface* surface) const { 293 return surface->readOnly() ? false : this->onSurfaceSupportsWritePixels(surface); 294} 295 296bool GrCaps::canCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src, 297 const SkIRect& srcRect, const SkIPoint& dstPoint) const { 298 if (dst->readOnly()) { 299 return false; 300 } 301 302 if (dst->backendFormat() != src->backendFormat()) { 303 return false; 304 } 305 return this->onCanCopySurface(dst, src, srcRect, dstPoint); 306} 307 308bool GrCaps::validateSurfaceParams(const SkISize& dimensions, const GrBackendFormat& format, 309 GrRenderable renderable, int renderTargetSampleCnt, 310 GrMipmapped mipped, GrTextureType textureType) const { 311 if (textureType != GrTextureType::kNone) { 312 if (!this->isFormatTexturable(format, textureType)) { 313 return false; 314 } 315 } 316 317 if (GrMipmapped::kYes == mipped && !this->mipmapSupport()) { 318 return false; 319 } 320 321 if (dimensions.width() < 1 || dimensions.height() < 1) { 322 return false; 323 } 324 325 if (renderable == GrRenderable::kYes) { 326 if (!this->isFormatRenderable(format, renderTargetSampleCnt)) { 327 return false; 328 } 329 int maxRTSize = this->maxRenderTargetSize(); 330 if (dimensions.width() > maxRTSize || dimensions.height() > maxRTSize) { 331 return false; 332 } 333 } else { 334 // We currently do not support multisampled textures 335 if (renderTargetSampleCnt != 1) { 336 return false; 337 } 338 int maxSize = this->maxTextureSize(); 339 if (dimensions.width() > maxSize || dimensions.height() > maxSize) { 340 return false; 341 } 342 } 343 344 return true; 345} 346 347GrCaps::SupportedRead GrCaps::supportedReadPixelsColorType(GrColorType srcColorType, 348 const GrBackendFormat& srcFormat, 349 GrColorType dstColorType) const { 350 SupportedRead read = this->onSupportedReadPixelsColorType(srcColorType, srcFormat, 351 dstColorType); 352 353 // There are known problems with 24 vs 32 bit BPP with this color type. Just fail for now if 354 // using a transfer buffer. 355 if (GrColorType::kRGB_888x == read.fColorType) { 356 read.fOffsetAlignmentForTransferBuffer = 0; 357 } 358 // It's very convenient to access 1 byte-per-channel 32 bit color types as uint32_t on the CPU. 359 // Make those aligned reads out of the buffer even if the underlying API doesn't require it. 360 auto channelFlags = GrColorTypeChannelFlags(read.fColorType); 361 if ((channelFlags == kRGBA_SkColorChannelFlags || channelFlags == kRGB_SkColorChannelFlags || 362 channelFlags == kAlpha_SkColorChannelFlag || channelFlags == kGray_SkColorChannelFlag) && 363 GrColorTypeBytesPerPixel(read.fColorType) == 4) { 364 switch (read.fOffsetAlignmentForTransferBuffer & 0b11) { 365 // offset alignment already a multiple of 4 366 case 0: 367 break; 368 // offset alignment is a multiple of 2 but not 4. 369 case 2: 370 read.fOffsetAlignmentForTransferBuffer *= 2; 371 break; 372 // offset alignment is not a multiple of 2. 373 default: 374 read.fOffsetAlignmentForTransferBuffer *= 4; 375 break; 376 } 377 } 378 return read; 379} 380 381GrBackendFormat GrCaps::getDefaultBackendFormat(GrColorType colorType, 382 GrRenderable renderable) const { 383 // Unknown color types are always an invalid format, so early out before calling virtual. 384 if (colorType == GrColorType::kUnknown) { 385 return {}; 386 } 387 388 auto format = this->onGetDefaultBackendFormat(colorType); 389 if (!this->isFormatTexturable(format, GrTextureType::k2D)) { 390 return {}; 391 } 392 if (!this->areColorTypeAndFormatCompatible(colorType, format)) { 393 return {}; 394 } 395 // Currently we require that it be possible to write pixels into the "default" format. Perhaps, 396 // that could be a separate requirement from the caller. It seems less necessary if 397 // renderability was requested. 398 if (this->supportedWritePixelsColorType(colorType, format, colorType).fColorType == 399 GrColorType::kUnknown) { 400 return {}; 401 } 402 if (renderable == GrRenderable::kYes && 403 !this->isFormatAsColorTypeRenderable(colorType, format)) { 404 return {}; 405 } 406 return format; 407} 408 409bool GrCaps::areColorTypeAndFormatCompatible(GrColorType grCT, 410 const GrBackendFormat& format) const { 411 if (GrColorType::kUnknown == grCT) { 412 return false; 413 } 414 415 SkImage::CompressionType compression = GrBackendFormatToCompressionType(format); 416 if (compression != SkImage::CompressionType::kNone) { 417 return grCT == (SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x 418 : GrColorType::kRGBA_8888); 419 } 420 421 return this->onAreColorTypeAndFormatCompatible(grCT, format); 422} 423 424GrSwizzle GrCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const { 425 SkImage::CompressionType compression = GrBackendFormatToCompressionType(format); 426 if (compression != SkImage::CompressionType::kNone) { 427 if (colorType == GrColorType::kRGB_888x || colorType == GrColorType::kRGBA_8888) { 428 return GrSwizzle::RGBA(); 429 } 430 SkDEBUGFAILF("Illegal color type (%d) and compressed format (%d) combination.", 431 (int)colorType, (int)compression); 432 return {}; 433 } 434 435 return this->onGetReadSwizzle(format, colorType); 436} 437 438bool GrCaps::isFormatCompressed(const GrBackendFormat& format) const { 439 return GrBackendFormatToCompressionType(format) != SkImage::CompressionType::kNone; 440} 441 442GrDstSampleFlags GrCaps::getDstSampleFlagsForProxy(const GrRenderTargetProxy* rt, 443 bool drawUsesMSAA) const { 444 SkASSERT(rt); 445 if (this->textureBarrierSupport() && (!drawUsesMSAA || this->msaaResolvesAutomatically())) { 446 return this->onGetDstSampleFlagsForProxy(rt); 447 } 448 return GrDstSampleFlags::kNone; 449} 450 451bool GrCaps::supportsDynamicMSAA(const GrRenderTargetProxy* rtProxy) const { 452 return rtProxy->numSamples() == 1 && 453 this->internalMultisampleCount(rtProxy->backendFormat()) > 1 && 454 this->onSupportsDynamicMSAA(rtProxy); 455} 456 457static inline GrColorType color_type_fallback(GrColorType ct) { 458 switch (ct) { 459 // kRGBA_8888 is our default fallback for many color types that may not have renderable 460 // backend formats. 461 case GrColorType::kAlpha_8: 462 case GrColorType::kBGR_565: 463 case GrColorType::kABGR_4444: 464 case GrColorType::kBGRA_8888: 465 case GrColorType::kRGBA_1010102: 466 case GrColorType::kBGRA_1010102: 467 case GrColorType::kRGBA_F16: 468 case GrColorType::kRGBA_F16_Clamped: 469 return GrColorType::kRGBA_8888; 470 case GrColorType::kAlpha_F16: 471 return GrColorType::kRGBA_F16; 472 case GrColorType::kGray_8: 473 return GrColorType::kRGB_888x; 474 default: 475 return GrColorType::kUnknown; 476 } 477} 478 479std::tuple<GrColorType, GrBackendFormat> GrCaps::getFallbackColorTypeAndFormat( 480 GrColorType ct, 481 int sampleCnt) const { 482 do { 483 auto format = this->getDefaultBackendFormat(ct, GrRenderable::kYes); 484 // We continue to the fallback color type if there no default renderable format or we 485 // requested msaa and the format doesn't support msaa. 486 if (format.isValid() && this->isFormatRenderable(format, sampleCnt)) { 487 return {ct, format}; 488 } 489 ct = color_type_fallback(ct); 490 } while (ct != GrColorType::kUnknown); 491 return {GrColorType::kUnknown, {}}; 492} 493