/* * Copyright 2021 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/ganesh/GrYUVATextureProxies.h" #include "src/gpu/ganesh/GrTextureProxy.h" #ifdef SK_DEBUG static int num_channels(uint32_t channelFlags) { switch (channelFlags) { case kRed_SkColorChannelFlag : return 1; case kAlpha_SkColorChannelFlag : return 1; case kGray_SkColorChannelFlag : return 1; case kGrayAlpha_SkColorChannelFlags : return 2; case kRG_SkColorChannelFlags : return 2; case kRGB_SkColorChannelFlags : return 3; case kRGBA_SkColorChannelFlags : return 4; default: SkDEBUGFAILF("Unexpected channel combination 0x%08x", channelFlags); return 0; } } #endif GrYUVATextureProxies::GrYUVATextureProxies(const SkYUVAInfo& yuvaInfo, sk_sp proxies[SkYUVAInfo::kMaxPlanes], GrSurfaceOrigin textureOrigin) : fYUVAInfo(yuvaInfo), fTextureOrigin(textureOrigin) { int n = yuvaInfo.numPlanes(); if (n == 0) { *this = {}; SkASSERT(!this->isValid()); return; } uint32_t textureChannelMasks[SkYUVAInfo::kMaxPlanes]; for (int i = 0; i < n; ++i) { if (!proxies[i]) { *this = {}; SkASSERT(!this->isValid()); return; } textureChannelMasks[i] = proxies[i]->backendFormat().channelMask(); } fYUVALocations = yuvaInfo.toYUVALocations(textureChannelMasks); if (fYUVALocations[0].fPlane < 0) { *this = {}; SkASSERT(!this->isValid()); return; } fMipmapped = skgpu::Mipmapped::kYes; for (size_t i = 0; i < static_cast(n); ++i) { if (!proxies[i]) { *this = {}; SkASSERT(!this->isValid()); return; } SkASSERT(proxies[i]->asTextureProxy()); if (proxies[i]->asTextureProxy()->mipmapped() == skgpu::Mipmapped::kNo) { fMipmapped = skgpu::Mipmapped::kNo; } fProxies[i] = std::move(proxies[i]); } SkASSERT(this->isValid()); } GrYUVATextureProxies::GrYUVATextureProxies(const SkYUVAInfo& yuvaInfo, GrSurfaceProxyView views[SkYUVAInfo::kMaxPlanes], GrColorType colorTypes[SkYUVAInfo::kMaxPlanes]) : fYUVAInfo(yuvaInfo) { uint32_t pixmapChannelMasks[SkYUVAInfo::kMaxPlanes]; int n = yuvaInfo.numPlanes(); if (n == 0) { *this = {}; SkASSERT(!this->isValid()); return; } fMipmapped = skgpu::Mipmapped::kYes; for (int i = 0; i < n; ++i) { pixmapChannelMasks[i] = GrColorTypeChannelFlags(colorTypes[i]); SkASSERT(num_channels(pixmapChannelMasks[i]) <= num_channels(views[i].proxy()->backendFormat().channelMask())); if (!views[i] || views[i].origin() != views[0].origin()) { *this = {}; SkASSERT(!this->isValid()); return; } if (views[i].proxy()->asTextureProxy()->mipmapped() == skgpu::Mipmapped::kNo) { fMipmapped = skgpu::Mipmapped::kNo; } } // Initial locations refer to the CPU pixmap channels. fYUVALocations = yuvaInfo.toYUVALocations(pixmapChannelMasks); if (fYUVALocations[0].fPlane < 0) { *this = {}; SkASSERT(!this->isValid()); return; } // Run each location through the proxy view's swizzle to get the actual texture format channel. for (int i = 0; i < SkYUVAInfo::kYUVAChannelCount; ++i) { int plane = fYUVALocations[i].fPlane; if (plane >= 0) { int chanAsIdx = static_cast(fYUVALocations[i].fChannel); switch (views[plane].swizzle()[chanAsIdx]) { case 'r': fYUVALocations[i].fChannel = SkColorChannel::kR; break; case 'g': fYUVALocations[i].fChannel = SkColorChannel::kG; break; case 'b': fYUVALocations[i].fChannel = SkColorChannel::kB; break; case 'a': fYUVALocations[i].fChannel = SkColorChannel::kA; break; default: SkDEBUGFAILF("Unexpected swizzle value: %c", views[i].swizzle()[chanAsIdx]); *this = {}; SkASSERT(!this->isValid()); return; } } } for (int i = 0; i < n; ++i) { fProxies[i] = views[i].detachProxy(); } fTextureOrigin = views[0].origin(); SkASSERT(this->isValid()); }