| 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 "include/gpu/GrBackendSurface.h" | 
|---|
| 9 | #include "include/gpu/GrContextOptions.h" | 
|---|
| 10 | #include "include/private/GrTypesPriv.h" | 
|---|
| 11 | #include "src/gpu/GrBackendUtils.h" | 
|---|
| 12 | #include "src/gpu/GrCaps.h" | 
|---|
| 13 | #include "src/gpu/GrSurface.h" | 
|---|
| 14 | #include "src/gpu/GrSurfaceProxy.h" | 
|---|
| 15 | #include "src/gpu/GrWindowRectangles.h" | 
|---|
| 16 | #include "src/utils/SkJSONWriter.h" | 
|---|
| 17 |  | 
|---|
| 18 | GrCaps::GrCaps(const GrContextOptions& options) { | 
|---|
| 19 | fMipmapSupport = false; | 
|---|
| 20 | fNPOTTextureTileSupport = false; | 
|---|
| 21 | fReuseScratchTextures = true; | 
|---|
| 22 | fReuseScratchBuffers = true; | 
|---|
| 23 | fGpuTracingSupport = false; | 
|---|
| 24 | fOversizedStencilSupport = false; | 
|---|
| 25 | fTextureBarrierSupport = false; | 
|---|
| 26 | fSampleLocationsSupport = false; | 
|---|
| 27 | fMultisampleDisableSupport = false; | 
|---|
| 28 | fDrawInstancedSupport = false; | 
|---|
| 29 | fNativeDrawIndirectSupport = false; | 
|---|
| 30 | fUseClientSideIndirectBuffers = false; | 
|---|
| 31 | fMixedSamplesSupport = false; | 
|---|
| 32 | fConservativeRasterSupport = false; | 
|---|
| 33 | fWireframeSupport = false; | 
|---|
| 34 | fMSAAResolvesAutomatically = false; | 
|---|
| 35 | fUsePrimitiveRestart = false; | 
|---|
| 36 | fPreferClientSideDynamicBuffers = false; | 
|---|
| 37 | fPreferFullscreenClears = false; | 
|---|
| 38 | fTwoSidedStencilRefsAndMasksMustMatch = false; | 
|---|
| 39 | fMustClearUploadedBufferData = false; | 
|---|
| 40 | fShouldInitializeTextures = false; | 
|---|
| 41 | fSupportsAHardwareBufferImages = false; | 
|---|
| 42 | fFenceSyncSupport = false; | 
|---|
| 43 | fSemaphoreSupport = false; | 
|---|
| 44 | fCrossContextTextureSupport = false; | 
|---|
| 45 | fHalfFloatVertexAttributeSupport = false; | 
|---|
| 46 | fDynamicStateArrayGeometryProcessorTextureSupport = false; | 
|---|
| 47 | fPerformPartialClearsAsDraws = false; | 
|---|
| 48 | fPerformColorClearsAsDraws = false; | 
|---|
| 49 | fAvoidLargeIndexBufferDraws = false; | 
|---|
| 50 | fPerformStencilClearsAsDraws = false; | 
|---|
| 51 | fAllowCoverageCounting = false; | 
|---|
| 52 | fTransferFromBufferToTextureSupport = false; | 
|---|
| 53 | fTransferFromSurfaceToBufferSupport = false; | 
|---|
| 54 | fWritePixelsRowBytesSupport = false; | 
|---|
| 55 | fReadPixelsRowBytesSupport = false; | 
|---|
| 56 | fShouldCollapseSrcOverToSrcWhenAble = false; | 
|---|
| 57 | fDriverDisableCCPR = false; | 
|---|
| 58 | fDriverDisableMSAACCPR = 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 |  | 
|---|
| 84 | fPreferVRAMUseOverFlushes = true; | 
|---|
| 85 |  | 
|---|
| 86 | fPreferTrianglesOverSampleMask = false; | 
|---|
| 87 |  | 
|---|
| 88 | // Default to true, allow older versions of OpenGL to disable explicitly | 
|---|
| 89 | fClampToBorderSupport = true; | 
|---|
| 90 |  | 
|---|
| 91 | fDriverBugWorkarounds = options.fDriverBugWorkarounds; | 
|---|
| 92 | } | 
|---|
| 93 |  | 
|---|
| 94 | void GrCaps::finishInitialization(const GrContextOptions& options) { | 
|---|
| 95 | if (fMixedSamplesSupport) { | 
|---|
| 96 | // We need multisample disable and dual source blending in order to support mixed samples. | 
|---|
| 97 | fMixedSamplesSupport = this->multisampleDisableSupport() && | 
|---|
| 98 | this->shaderCaps()->dualSourceBlendingSupport(); | 
|---|
| 99 | } | 
|---|
| 100 |  | 
|---|
| 101 | if (!fNativeDrawIndirectSupport) { | 
|---|
| 102 | // We will implement indirect draws with a polyfill, so the commands need to reside in CPU | 
|---|
| 103 | // memory. | 
|---|
| 104 | fUseClientSideIndirectBuffers = true; | 
|---|
| 105 | } | 
|---|
| 106 |  | 
|---|
| 107 | // Overrides happen last. | 
|---|
| 108 | this->applyOptionsOverrides(options); | 
|---|
| 109 | } | 
|---|
| 110 |  | 
|---|
| 111 | void GrCaps::applyOptionsOverrides(const GrContextOptions& options) { | 
|---|
| 112 | fShaderCaps->applyOptionsOverrides(options); | 
|---|
| 113 | this->onApplyOptionsOverrides(options); | 
|---|
| 114 | if (options.fDisableDriverCorrectnessWorkarounds) { | 
|---|
| 115 | SkASSERT(!fDriverDisableCCPR); | 
|---|
| 116 | SkASSERT(!fDriverDisableMSAACCPR); | 
|---|
| 117 | SkASSERT(!fAvoidStencilBuffers); | 
|---|
| 118 | SkASSERT(!fAvoidWritePixelsFastPath); | 
|---|
| 119 | SkASSERT(!fRequiresManualFBBarrierAfterTessellatedStencilDraw); | 
|---|
| 120 | SkASSERT(!fNativeDrawIndexedIndirectIsBroken); | 
|---|
| 121 | SkASSERT(!fAdvBlendEqDisableFlags); | 
|---|
| 122 | SkASSERT(!fPerformColorClearsAsDraws); | 
|---|
| 123 | SkASSERT(!fPerformStencilClearsAsDraws); | 
|---|
| 124 | // Don't check the partial-clear workaround, since that is a backend limitation, not a | 
|---|
| 125 | // driver workaround (it just so happens the fallbacks are the same). | 
|---|
| 126 | } | 
|---|
| 127 | if (GrContextOptions::Enable::kNo == options.fUseDrawInsteadOfClear) { | 
|---|
| 128 | fPerformColorClearsAsDraws = false; | 
|---|
| 129 | fPerformStencilClearsAsDraws = false; | 
|---|
| 130 | } else if (GrContextOptions::Enable::kYes == options.fUseDrawInsteadOfClear) { | 
|---|
| 131 | fPerformColorClearsAsDraws = true; | 
|---|
| 132 | fPerformStencilClearsAsDraws = true; | 
|---|
| 133 | } | 
|---|
| 134 |  | 
|---|
| 135 | fAllowCoverageCounting = !options.fDisableCoverageCountingPaths; | 
|---|
| 136 |  | 
|---|
| 137 | fMaxTextureSize = std::min(fMaxTextureSize, options.fMaxTextureSizeOverride); | 
|---|
| 138 | fMaxTileSize = fMaxTextureSize; | 
|---|
| 139 | #if GR_TEST_UTILS | 
|---|
| 140 | // If the max tile override is zero, it means we should use the max texture size. | 
|---|
| 141 | if (options.fMaxTileSizeOverride && options.fMaxTileSizeOverride < fMaxTextureSize) { | 
|---|
| 142 | fMaxTileSize = options.fMaxTileSizeOverride; | 
|---|
| 143 | } | 
|---|
| 144 | if (options.fSuppressDualSourceBlending) { | 
|---|
| 145 | // GrShaderCaps::applyOptionsOverrides already handled the rest; here we just need to make | 
|---|
| 146 | // sure mixed samples gets disabled if dual source blending is suppressed. | 
|---|
| 147 | fMixedSamplesSupport = false; | 
|---|
| 148 | } | 
|---|
| 149 | if (options.fClearAllTextures) { | 
|---|
| 150 | fShouldInitializeTextures = true; | 
|---|
| 151 | } | 
|---|
| 152 | #endif | 
|---|
| 153 |  | 
|---|
| 154 | if (fMaxWindowRectangles > GrWindowRectangles::kMaxWindows) { | 
|---|
| 155 | SkDebugf( "WARNING: capping window rectangles at %i. HW advertises support for %i.\n", | 
|---|
| 156 | GrWindowRectangles::kMaxWindows, fMaxWindowRectangles); | 
|---|
| 157 | fMaxWindowRectangles = GrWindowRectangles::kMaxWindows; | 
|---|
| 158 | } | 
|---|
| 159 |  | 
|---|
| 160 | fInternalMultisampleCount = options.fInternalMultisampleCount; | 
|---|
| 161 |  | 
|---|
| 162 | fAvoidStencilBuffers = options.fAvoidStencilBuffers; | 
|---|
| 163 |  | 
|---|
| 164 | fDriverBugWorkarounds.applyOverrides(options.fDriverBugWorkarounds); | 
|---|
| 165 | } | 
|---|
| 166 |  | 
|---|
| 167 |  | 
|---|
| 168 | #ifdef SK_ENABLE_DUMP_GPU | 
|---|
| 169 | #include "src/gpu/GrTestUtils.h" | 
|---|
| 170 |  | 
|---|
| 171 | static SkString map_flags_to_string(uint32_t flags) { | 
|---|
| 172 | SkString str; | 
|---|
| 173 | if (GrCaps::kNone_MapFlags == flags) { | 
|---|
| 174 | str = "none"; | 
|---|
| 175 | } else { | 
|---|
| 176 | SkASSERT(GrCaps::kCanMap_MapFlag & flags); | 
|---|
| 177 | SkDEBUGCODE(flags &= ~GrCaps::kCanMap_MapFlag); | 
|---|
| 178 | str = "can_map"; | 
|---|
| 179 |  | 
|---|
| 180 | if (GrCaps::kSubset_MapFlag & flags) { | 
|---|
| 181 | str.append( " partial"); | 
|---|
| 182 | } else { | 
|---|
| 183 | str.append( " full"); | 
|---|
| 184 | } | 
|---|
| 185 | SkDEBUGCODE(flags &= ~GrCaps::kSubset_MapFlag); | 
|---|
| 186 | if (GrCaps::kAsyncRead_MapFlag & flags) { | 
|---|
| 187 | str.append( " async_read"); | 
|---|
| 188 | } else { | 
|---|
| 189 | str.append( " sync_read"); | 
|---|
| 190 | } | 
|---|
| 191 | SkDEBUGCODE(flags &= ~GrCaps::kAsyncRead_MapFlag); | 
|---|
| 192 | } | 
|---|
| 193 | SkASSERT(0 == flags); // Make sure we handled all the flags. | 
|---|
| 194 | return str; | 
|---|
| 195 | } | 
|---|
| 196 |  | 
|---|
| 197 | void GrCaps::dumpJSON(SkJSONWriter* writer) const { | 
|---|
| 198 | writer->beginObject(); | 
|---|
| 199 |  | 
|---|
| 200 | writer->appendBool( "MIP Map Support", fMipmapSupport); | 
|---|
| 201 | writer->appendBool( "NPOT Texture Tile Support", fNPOTTextureTileSupport); | 
|---|
| 202 | writer->appendBool( "Reuse Scratch Textures", fReuseScratchTextures); | 
|---|
| 203 | writer->appendBool( "Reuse Scratch Buffers", fReuseScratchBuffers); | 
|---|
| 204 | writer->appendBool( "Gpu Tracing Support", fGpuTracingSupport); | 
|---|
| 205 | writer->appendBool( "Oversized Stencil Support", fOversizedStencilSupport); | 
|---|
| 206 | writer->appendBool( "Texture Barrier Support", fTextureBarrierSupport); | 
|---|
| 207 | writer->appendBool( "Sample Locations Support", fSampleLocationsSupport); | 
|---|
| 208 | writer->appendBool( "Multisample disable support", fMultisampleDisableSupport); | 
|---|
| 209 | writer->appendBool( "Draw Instanced Support", fDrawInstancedSupport); | 
|---|
| 210 | writer->appendBool( "Native Draw Indirect Support", fNativeDrawIndirectSupport); | 
|---|
| 211 | writer->appendBool( "Use client side indirect buffers", fUseClientSideIndirectBuffers); | 
|---|
| 212 | writer->appendBool( "Mixed Samples Support", fMixedSamplesSupport); | 
|---|
| 213 | writer->appendBool( "Conservative Raster Support", fConservativeRasterSupport); | 
|---|
| 214 | writer->appendBool( "Wireframe Support", fWireframeSupport); | 
|---|
| 215 | writer->appendBool( "MSAA Resolves Automatically", fMSAAResolvesAutomatically); | 
|---|
| 216 | writer->appendBool( "Use primitive restart", fUsePrimitiveRestart); | 
|---|
| 217 | writer->appendBool( "Prefer client-side dynamic buffers", fPreferClientSideDynamicBuffers); | 
|---|
| 218 | writer->appendBool( "Prefer fullscreen clears (and stencil discard)", fPreferFullscreenClears); | 
|---|
| 219 | writer->appendBool( "Two-sided Stencil Refs And Masks Must Match", | 
|---|
| 220 | fTwoSidedStencilRefsAndMasksMustMatch); | 
|---|
| 221 | writer->appendBool( "Must clear buffer memory", fMustClearUploadedBufferData); | 
|---|
| 222 | writer->appendBool( "Should initialize textures", fShouldInitializeTextures); | 
|---|
| 223 | writer->appendBool( "Supports importing AHardwareBuffers", fSupportsAHardwareBufferImages); | 
|---|
| 224 | writer->appendBool( "Fence sync support", fFenceSyncSupport); | 
|---|
| 225 | writer->appendBool( "Semaphore support", fSemaphoreSupport); | 
|---|
| 226 | writer->appendBool( "Cross context texture support", fCrossContextTextureSupport); | 
|---|
| 227 | writer->appendBool( "Half float vertex attribute support", fHalfFloatVertexAttributeSupport); | 
|---|
| 228 | writer->appendBool( "Specify GeometryProcessor textures as a dynamic state array", | 
|---|
| 229 | fDynamicStateArrayGeometryProcessorTextureSupport); | 
|---|
| 230 | writer->appendBool( "Use draws for partial clears", fPerformPartialClearsAsDraws); | 
|---|
| 231 | writer->appendBool( "Use draws for color clears", fPerformColorClearsAsDraws); | 
|---|
| 232 | writer->appendBool( "Avoid Large IndexBuffer Draws", fAvoidLargeIndexBufferDraws); | 
|---|
| 233 | writer->appendBool( "Use draws for stencil clip clears", fPerformStencilClearsAsDraws); | 
|---|
| 234 | writer->appendBool( "Allow coverage counting shortcuts", fAllowCoverageCounting); | 
|---|
| 235 | writer->appendBool( "Supports transfers from buffers to textures", | 
|---|
| 236 | fTransferFromBufferToTextureSupport); | 
|---|
| 237 | writer->appendBool( "Supports transfers from textures to buffers", | 
|---|
| 238 | fTransferFromSurfaceToBufferSupport); | 
|---|
| 239 | writer->appendBool( "Write pixels row bytes support", fWritePixelsRowBytesSupport); | 
|---|
| 240 | writer->appendBool( "Read pixels row bytes support", fReadPixelsRowBytesSupport); | 
|---|
| 241 | writer->appendBool( "Disable CCPR on current driver [workaround]", fDriverDisableCCPR); | 
|---|
| 242 | writer->appendBool( "Disable MSAA version of CCPR on current driver [workaround]", | 
|---|
| 243 | fDriverDisableMSAACCPR); | 
|---|
| 244 | writer->appendBool( "Clamp-to-border", fClampToBorderSupport); | 
|---|
| 245 |  | 
|---|
| 246 | writer->appendBool( "Prefer VRAM Use over flushes [workaround]", fPreferVRAMUseOverFlushes); | 
|---|
| 247 | writer->appendBool( "Prefer more triangles over sample mask [MSAA only]", | 
|---|
| 248 | fPreferTrianglesOverSampleMask); | 
|---|
| 249 | writer->appendBool( "Avoid stencil buffers [workaround]", fAvoidStencilBuffers); | 
|---|
| 250 | writer->appendBool( "Avoid writePixels fast path [workaround]", fAvoidWritePixelsFastPath); | 
|---|
| 251 | writer->appendBool( "Requires manual FB barrier after tessellated stencilDraw [workaround]", | 
|---|
| 252 | fRequiresManualFBBarrierAfterTessellatedStencilDraw); | 
|---|
| 253 | writer->appendBool( "Native draw indexed indirect is broken [workaround]", | 
|---|
| 254 | fNativeDrawIndexedIndirectIsBroken); | 
|---|
| 255 |  | 
|---|
| 256 | if (this->advancedBlendEquationSupport()) { | 
|---|
| 257 | writer->appendHexU32( "Advanced Blend Equation Disable Flags", fAdvBlendEqDisableFlags); | 
|---|
| 258 | } | 
|---|
| 259 |  | 
|---|
| 260 | writer->appendS32( "Max Vertex Attributes", fMaxVertexAttributes); | 
|---|
| 261 | writer->appendS32( "Max Texture Size", fMaxTextureSize); | 
|---|
| 262 | writer->appendS32( "Max Render Target Size", fMaxRenderTargetSize); | 
|---|
| 263 | writer->appendS32( "Max Preferred Render Target Size", fMaxPreferredRenderTargetSize); | 
|---|
| 264 | writer->appendS32( "Max Window Rectangles", fMaxWindowRectangles); | 
|---|
| 265 | writer->appendS32( "Preferred Sample Count for Internal MSAA and Mixed Samples", | 
|---|
| 266 | fInternalMultisampleCount); | 
|---|
| 267 |  | 
|---|
| 268 | static const char* kBlendEquationSupportNames[] = { | 
|---|
| 269 | "Basic", | 
|---|
| 270 | "Advanced", | 
|---|
| 271 | "Advanced Coherent", | 
|---|
| 272 | }; | 
|---|
| 273 | static_assert(0 == kBasic_BlendEquationSupport); | 
|---|
| 274 | static_assert(1 == kAdvanced_BlendEquationSupport); | 
|---|
| 275 | static_assert(2 == kAdvancedCoherent_BlendEquationSupport); | 
|---|
| 276 | static_assert(SK_ARRAY_COUNT(kBlendEquationSupportNames) == kLast_BlendEquationSupport + 1); | 
|---|
| 277 |  | 
|---|
| 278 | writer->appendString( "Blend Equation Support", | 
|---|
| 279 | kBlendEquationSupportNames[fBlendEquationSupport]); | 
|---|
| 280 | writer->appendString( "Map Buffer Support", map_flags_to_string(fMapBufferFlags).c_str()); | 
|---|
| 281 |  | 
|---|
| 282 | this->onDumpJSON(writer); | 
|---|
| 283 |  | 
|---|
| 284 | writer->appendName( "shaderCaps"); | 
|---|
| 285 | this->shaderCaps()->dumpJSON(writer); | 
|---|
| 286 |  | 
|---|
| 287 | writer->endObject(); | 
|---|
| 288 | } | 
|---|
| 289 | #else | 
|---|
| 290 | void GrCaps::dumpJSON(SkJSONWriter* writer) const { } | 
|---|
| 291 | #endif | 
|---|
| 292 |  | 
|---|
| 293 | bool GrCaps::surfaceSupportsWritePixels(const GrSurface* surface) const { | 
|---|
| 294 | return surface->readOnly() ? false : this->onSurfaceSupportsWritePixels(surface); | 
|---|
| 295 | } | 
|---|
| 296 |  | 
|---|
| 297 | bool GrCaps::canCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src, | 
|---|
| 298 | const SkIRect& srcRect, const SkIPoint& dstPoint) const { | 
|---|
| 299 | if (dst->readOnly()) { | 
|---|
| 300 | return false; | 
|---|
| 301 | } | 
|---|
| 302 |  | 
|---|
| 303 | if (dst->backendFormat() != src->backendFormat()) { | 
|---|
| 304 | return false; | 
|---|
| 305 | } | 
|---|
| 306 | return this->onCanCopySurface(dst, src, srcRect, dstPoint); | 
|---|
| 307 | } | 
|---|
| 308 |  | 
|---|
| 309 | bool GrCaps::validateSurfaceParams(const SkISize& dimensions, const GrBackendFormat& format, | 
|---|
| 310 | GrRenderable renderable, int renderTargetSampleCnt, | 
|---|
| 311 | GrMipmapped mipped) const { | 
|---|
| 312 | if (!this->isFormatTexturable(format)) { | 
|---|
| 313 | return false; | 
|---|
| 314 | } | 
|---|
| 315 |  | 
|---|
| 316 | if (GrMipmapped::kYes == mipped && !this->mipmapSupport()) { | 
|---|
| 317 | return false; | 
|---|
| 318 | } | 
|---|
| 319 |  | 
|---|
| 320 | if (dimensions.width() < 1 || dimensions.height() < 1) { | 
|---|
| 321 | return false; | 
|---|
| 322 | } | 
|---|
| 323 |  | 
|---|
| 324 | if (renderable == GrRenderable::kYes) { | 
|---|
| 325 | if (!this->isFormatRenderable(format, renderTargetSampleCnt)) { | 
|---|
| 326 | return false; | 
|---|
| 327 | } | 
|---|
| 328 | int maxRTSize = this->maxRenderTargetSize(); | 
|---|
| 329 | if (dimensions.width() > maxRTSize || dimensions.height() > maxRTSize) { | 
|---|
| 330 | return false; | 
|---|
| 331 | } | 
|---|
| 332 | } else { | 
|---|
| 333 | // We currently do not support multisampled textures | 
|---|
| 334 | if (renderTargetSampleCnt != 1) { | 
|---|
| 335 | return false; | 
|---|
| 336 | } | 
|---|
| 337 | int maxSize = this->maxTextureSize(); | 
|---|
| 338 | if (dimensions.width() > maxSize || dimensions.height() > maxSize) { | 
|---|
| 339 | return false; | 
|---|
| 340 | } | 
|---|
| 341 | } | 
|---|
| 342 |  | 
|---|
| 343 | return true; | 
|---|
| 344 | } | 
|---|
| 345 |  | 
|---|
| 346 | GrCaps::SupportedRead GrCaps::supportedReadPixelsColorType(GrColorType srcColorType, | 
|---|
| 347 | const GrBackendFormat& srcFormat, | 
|---|
| 348 | GrColorType dstColorType) const { | 
|---|
| 349 | SupportedRead read = this->onSupportedReadPixelsColorType(srcColorType, srcFormat, | 
|---|
| 350 | dstColorType); | 
|---|
| 351 |  | 
|---|
| 352 | // There are known problems with 24 vs 32 bit BPP with this color type. Just fail for now if | 
|---|
| 353 | // using a transfer buffer. | 
|---|
| 354 | if (GrColorType::kRGB_888x == read.fColorType) { | 
|---|
| 355 | read.fOffsetAlignmentForTransferBuffer = 0; | 
|---|
| 356 | } | 
|---|
| 357 | // It's very convenient to access 1 byte-per-channel 32 bit color types as uint32_t on the CPU. | 
|---|
| 358 | // Make those aligned reads out of the buffer even if the underlying API doesn't require it. | 
|---|
| 359 | auto channelFlags = GrColorTypeChannelFlags(read.fColorType); | 
|---|
| 360 | if ((channelFlags == kRGBA_SkColorChannelFlags || channelFlags == kRGB_SkColorChannelFlags || | 
|---|
| 361 | channelFlags == kAlpha_SkColorChannelFlag || channelFlags == kGray_SkColorChannelFlag) && | 
|---|
| 362 | GrColorTypeBytesPerPixel(read.fColorType) == 4) { | 
|---|
| 363 | switch (read.fOffsetAlignmentForTransferBuffer & 0b11) { | 
|---|
| 364 | // offset alignment already a multiple of 4 | 
|---|
| 365 | case 0: | 
|---|
| 366 | break; | 
|---|
| 367 | // offset alignment is a multiple of 2 but not 4. | 
|---|
| 368 | case 2: | 
|---|
| 369 | read.fOffsetAlignmentForTransferBuffer *= 2; | 
|---|
| 370 | break; | 
|---|
| 371 | // offset alignment is not a multiple of 2. | 
|---|
| 372 | default: | 
|---|
| 373 | read.fOffsetAlignmentForTransferBuffer *= 4; | 
|---|
| 374 | break; | 
|---|
| 375 | } | 
|---|
| 376 | } | 
|---|
| 377 | return read; | 
|---|
| 378 | } | 
|---|
| 379 |  | 
|---|
| 380 | GrBackendFormat GrCaps::getDefaultBackendFormat(GrColorType colorType, | 
|---|
| 381 | GrRenderable renderable) const { | 
|---|
| 382 | auto format = this->onGetDefaultBackendFormat(colorType); | 
|---|
| 383 | if (!this->isFormatTexturable(format)) { | 
|---|
| 384 | return {}; | 
|---|
| 385 | } | 
|---|
| 386 | if (!this->areColorTypeAndFormatCompatible(colorType, format)) { | 
|---|
| 387 | return {}; | 
|---|
| 388 | } | 
|---|
| 389 | // Currently we require that it be possible to write pixels into the "default" format. Perhaps, | 
|---|
| 390 | // that could be a separate requirement from the caller. It seems less necessary if | 
|---|
| 391 | // renderability was requested. | 
|---|
| 392 | if (this->supportedWritePixelsColorType(colorType, format, colorType).fColorType == | 
|---|
| 393 | GrColorType::kUnknown) { | 
|---|
| 394 | return {}; | 
|---|
| 395 | } | 
|---|
| 396 | if (renderable == GrRenderable::kYes && | 
|---|
| 397 | !this->isFormatAsColorTypeRenderable(colorType, format)) { | 
|---|
| 398 | return {}; | 
|---|
| 399 | } | 
|---|
| 400 | return format; | 
|---|
| 401 | } | 
|---|
| 402 |  | 
|---|
| 403 | bool GrCaps::areColorTypeAndFormatCompatible(GrColorType grCT, | 
|---|
| 404 | const GrBackendFormat& format) const { | 
|---|
| 405 | if (GrColorType::kUnknown == grCT) { | 
|---|
| 406 | return false; | 
|---|
| 407 | } | 
|---|
| 408 |  | 
|---|
| 409 | SkImage::CompressionType compression = GrBackendFormatToCompressionType(format); | 
|---|
| 410 | if (compression != SkImage::CompressionType::kNone) { | 
|---|
| 411 | return grCT == (SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x | 
|---|
| 412 | : GrColorType::kRGBA_8888); | 
|---|
| 413 | } | 
|---|
| 414 |  | 
|---|
| 415 | return this->onAreColorTypeAndFormatCompatible(grCT, format); | 
|---|
| 416 | } | 
|---|
| 417 |  | 
|---|
| 418 | GrSwizzle GrCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const { | 
|---|
| 419 | SkImage::CompressionType compression = GrBackendFormatToCompressionType(format); | 
|---|
| 420 | if (compression != SkImage::CompressionType::kNone) { | 
|---|
| 421 | if (colorType == GrColorType::kRGB_888x || colorType == GrColorType::kRGBA_8888) { | 
|---|
| 422 | return GrSwizzle::RGBA(); | 
|---|
| 423 | } | 
|---|
| 424 | SkDEBUGFAILF( "Illegal color type (%d) and compressed format (%d) combination.", colorType, | 
|---|
| 425 | compression); | 
|---|
| 426 | return {}; | 
|---|
| 427 | } | 
|---|
| 428 |  | 
|---|
| 429 | return this->onGetReadSwizzle(format, colorType); | 
|---|
| 430 | } | 
|---|
| 431 |  | 
|---|
| 432 | bool GrCaps::isFormatCompressed(const GrBackendFormat& format) const { | 
|---|
| 433 | return GrBackendFormatToCompressionType(format) != SkImage::CompressionType::kNone; | 
|---|
| 434 | } | 
|---|
| 435 |  | 
|---|
| 436 |  | 
|---|