| /* |
| * 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<GrSurfaceProxy> 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<size_t>(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<int>(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()); |
| } |