blob: cc4bfc6b7dddab79ba950d13379eb55258cda994 [file] [log] [blame]
/*
* 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());
}