/* * Copyright 2020 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "include/gpu/GrYUVABackendTextures.h" #include "src/core/SkYUVAInfoLocation.h" static int num_channels(const GrBackendFormat& format) { switch (format.channelMask()) { 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 : return 0; } } GrYUVABackendTextureInfo::GrYUVABackendTextureInfo(const SkYUVAInfo& yuvaInfo, const GrBackendFormat formats[kMaxPlanes], GrMipmapped mipmapped, GrSurfaceOrigin origin) : fYUVAInfo(yuvaInfo), fMipmapped(mipmapped), fTextureOrigin(origin) { if (!yuvaInfo.isValid()) { *this = {}; SkASSERT(!this->isValid()); return; } int n = yuvaInfo.numPlanes(); for (size_t i = 0; i < static_cast(n); ++i) { if (!formats[i].isValid() || formats[i].backend() != formats[0].backend()) { *this = {}; SkASSERT(!this->isValid()); return; } int numRequiredChannels = yuvaInfo.numChannelsInPlane(i); SkASSERT(numRequiredChannels > 0); int numActualChannels = num_channels(formats[i]); if (numActualChannels < numRequiredChannels) { *this = {}; SkASSERT(!this->isValid()); } fPlaneFormats[i] = formats[i]; } SkASSERT(this->isValid()); } bool GrYUVABackendTextureInfo::operator==(const GrYUVABackendTextureInfo& that) const { if (fYUVAInfo != that.fYUVAInfo || fMipmapped != that.fMipmapped || fTextureOrigin != that.fTextureOrigin) { return false; } int n = fYUVAInfo.numPlanes(); return std::equal(fPlaneFormats, fPlaneFormats + n, that.fPlaneFormats); } SkYUVAInfo::YUVALocations GrYUVABackendTextureInfo::toYUVALocations() const { uint32_t channelFlags[] = {fPlaneFormats[0].channelMask(), fPlaneFormats[1].channelMask(), fPlaneFormats[2].channelMask(), fPlaneFormats[3].channelMask()}; auto result = fYUVAInfo.toYUVALocations(channelFlags); SkDEBUGCODE(int numPlanes;) SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(result, &numPlanes)); SkASSERT(numPlanes == this->numPlanes()); return result; } ////////////////////////////////////////////////////////////////////////////// GrYUVABackendTextures::GrYUVABackendTextures( const SkYUVAInfo& yuvaInfo, const GrBackendTexture textures[SkYUVAInfo::kMaxPlanes], GrSurfaceOrigin textureOrigin) : fYUVAInfo(yuvaInfo), fTextureOrigin(textureOrigin) { if (!fYUVAInfo.isValid()) { return; } SkISize planeDimensions[SkYUVAInfo::kMaxPlanes]; int numPlanes = yuvaInfo.planeDimensions(planeDimensions); for (int i = 0; i < numPlanes; ++i) { int numRequiredChannels = fYUVAInfo.numChannelsInPlane(i); if (!textures[i].isValid() || textures[i].dimensions() != planeDimensions[i] || textures[i].backend() != textures[0].backend() || num_channels(textures[i].getBackendFormat()) < numRequiredChannels) { *this = {}; return; } fTextures[i] = textures[i]; } } SkYUVAInfo::YUVALocations GrYUVABackendTextures::toYUVALocations() const { uint32_t channelFlags[] = {fTextures[0].getBackendFormat().channelMask(), fTextures[1].getBackendFormat().channelMask(), fTextures[2].getBackendFormat().channelMask(), fTextures[3].getBackendFormat().channelMask()}; auto result = fYUVAInfo.toYUVALocations(channelFlags); SkDEBUGCODE(int numPlanes;) SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(result, &numPlanes)); SkASSERT(numPlanes == this->numPlanes()); return result; }