1/* 2 * Copyright 2020 Google LLC 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/GrYUVABackendTextures.h" 9 10#include "src/core/SkYUVAInfoLocation.h" 11 12static int num_channels(const GrBackendFormat& format) { 13 switch (format.channelMask()) { 14 case kRed_SkColorChannelFlag : return 1; 15 case kAlpha_SkColorChannelFlag : return 1; 16 case kGray_SkColorChannelFlag : return 1; 17 case kGrayAlpha_SkColorChannelFlags : return 2; 18 case kRG_SkColorChannelFlags : return 2; 19 case kRGB_SkColorChannelFlags : return 3; 20 case kRGBA_SkColorChannelFlags : return 4; 21 default : return 0; 22 } 23} 24 25GrYUVABackendTextureInfo::GrYUVABackendTextureInfo(const SkYUVAInfo& yuvaInfo, 26 const GrBackendFormat formats[kMaxPlanes], 27 GrMipmapped mipmapped, 28 GrSurfaceOrigin origin) 29 : fYUVAInfo(yuvaInfo), fMipmapped(mipmapped), fTextureOrigin(origin) { 30 if (!yuvaInfo.isValid()) { 31 *this = {}; 32 SkASSERT(!this->isValid()); 33 return; 34 } 35 int n = yuvaInfo.numPlanes(); 36 for (size_t i = 0; i < static_cast<size_t>(n); ++i) { 37 if (!formats[i].isValid() || formats[i].backend() != formats[0].backend()) { 38 *this = {}; 39 SkASSERT(!this->isValid()); 40 return; 41 } 42 int numRequiredChannels = yuvaInfo.numChannelsInPlane(i); 43 SkASSERT(numRequiredChannels > 0); 44 int numActualChannels = num_channels(formats[i]); 45 if (numActualChannels < numRequiredChannels) { 46 *this = {}; 47 SkASSERT(!this->isValid()); 48 } 49 fPlaneFormats[i] = formats[i]; 50 } 51 SkASSERT(this->isValid()); 52} 53 54bool GrYUVABackendTextureInfo::operator==(const GrYUVABackendTextureInfo& that) const { 55 if (fYUVAInfo != that.fYUVAInfo || 56 fMipmapped != that.fMipmapped || 57 fTextureOrigin != that.fTextureOrigin) { 58 return false; 59 } 60 int n = fYUVAInfo.numPlanes(); 61 return std::equal(fPlaneFormats, fPlaneFormats + n, that.fPlaneFormats); 62} 63 64SkYUVAInfo::YUVALocations GrYUVABackendTextureInfo::toYUVALocations() const { 65 uint32_t channelFlags[] = {fPlaneFormats[0].channelMask(), 66 fPlaneFormats[1].channelMask(), 67 fPlaneFormats[2].channelMask(), 68 fPlaneFormats[3].channelMask()}; 69 auto result = fYUVAInfo.toYUVALocations(channelFlags); 70 SkDEBUGCODE(int numPlanes;) 71 SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(result, &numPlanes)); 72 SkASSERT(numPlanes == this->numPlanes()); 73 return result; 74} 75 76////////////////////////////////////////////////////////////////////////////// 77 78GrYUVABackendTextures::GrYUVABackendTextures( 79 const SkYUVAInfo& yuvaInfo, 80 const GrBackendTexture textures[SkYUVAInfo::kMaxPlanes], 81 GrSurfaceOrigin textureOrigin) 82 : fYUVAInfo(yuvaInfo), fTextureOrigin(textureOrigin) { 83 if (!fYUVAInfo.isValid()) { 84 return; 85 } 86 SkISize planeDimensions[SkYUVAInfo::kMaxPlanes]; 87 int numPlanes = yuvaInfo.planeDimensions(planeDimensions); 88 for (int i = 0; i < numPlanes; ++i) { 89 int numRequiredChannels = fYUVAInfo.numChannelsInPlane(i); 90 if (!textures[i].isValid() || 91 textures[i].dimensions() != planeDimensions[i] || 92 textures[i].backend() != textures[0].backend() || 93 num_channels(textures[i].getBackendFormat()) < numRequiredChannels) { 94 *this = {}; 95 return; 96 } 97 fTextures[i] = textures[i]; 98 } 99} 100 101SkYUVAInfo::YUVALocations GrYUVABackendTextures::toYUVALocations() const { 102 uint32_t channelFlags[] = {fTextures[0].getBackendFormat().channelMask(), 103 fTextures[1].getBackendFormat().channelMask(), 104 fTextures[2].getBackendFormat().channelMask(), 105 fTextures[3].getBackendFormat().channelMask()}; 106 auto result = fYUVAInfo.toYUVALocations(channelFlags); 107 SkDEBUGCODE(int numPlanes;) 108 SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(result, &numPlanes)); 109 SkASSERT(numPlanes == this->numPlanes()); 110 return result; 111} 112