blob: 8e94d02512a50b52c423c8845a76e9e22d5cfcac [file] [log] [blame]
/*
* Copyright 2023 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/graphite/YUVABackendTextures.h"
#include "include/gpu/graphite/Recorder.h"
#include "src/core/SkYUVAInfoLocation.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/RecorderPriv.h"
namespace skgpu::graphite {
namespace {
int num_channels(uint32_t ChannelMasks) {
switch (ChannelMasks) {
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;
}
SkUNREACHABLE;
}
}
YUVABackendTextureInfo::YUVABackendTextureInfo(const Recorder* recorder,
const SkYUVAInfo& yuvaInfo,
SkSpan<const TextureInfo> textureInfo,
Mipmapped mipmapped)
: fYUVAInfo(yuvaInfo)
, fMipmapped(mipmapped) {
int numPlanes = yuvaInfo.numPlanes();
if (!yuvaInfo.isValid() ||
numPlanes == 0 ||
(size_t)numPlanes > textureInfo.size()) {
*this = {};
SkASSERT(!this->isValid());
return;
}
for (int i = 0; i < numPlanes; ++i) {
int numRequiredChannels = yuvaInfo.numChannelsInPlane(i);
SkASSERT(numRequiredChannels > 0);
fPlaneChannelMasks[i] = recorder->priv().caps()->channelMask(textureInfo[i]);
if (!textureInfo[i].isValid() ||
textureInfo[i].backend() != textureInfo[0].backend() ||
num_channels(fPlaneChannelMasks[i]) < numRequiredChannels) {
*this = {};
SkASSERT(!this->isValid());
return;
}
fPlaneTextureInfos[i] = textureInfo[i];
}
SkASSERT(this->isValid());
}
bool YUVABackendTextureInfo::operator==(const YUVABackendTextureInfo& that) const {
if (fYUVAInfo != that.fYUVAInfo || fMipmapped != that.fMipmapped) {
return false;
}
return fPlaneTextureInfos == that.fPlaneTextureInfos;
}
SkYUVAInfo::YUVALocations YUVABackendTextureInfo::toYUVALocations() const {
auto result = fYUVAInfo.toYUVALocations(fPlaneChannelMasks.data());
SkDEBUGCODE(int numPlanes;)
SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(result, &numPlanes));
SkASSERT(numPlanes == this->numPlanes());
return result;
}
//////////////////////////////////////////////////////////////////////////////
YUVABackendTextures::YUVABackendTextures(const Recorder* recorder,
const SkYUVAInfo& yuvaInfo,
SkSpan<const BackendTexture> textures)
: fYUVAInfo(yuvaInfo) {
if (!yuvaInfo.isValid()) {
SkASSERT(!this->isValid());
return;
}
SkISize planeDimensions[kMaxPlanes];
int numPlanes = yuvaInfo.planeDimensions(planeDimensions);
if (numPlanes == 0 || (size_t)numPlanes > textures.size()) {
fYUVAInfo = {};
SkASSERT(!this->isValid());
return;
}
for (int i = 0; i < numPlanes; ++i) {
int numRequiredChannels = yuvaInfo.numChannelsInPlane(i);
SkASSERT(numRequiredChannels > 0);
fPlaneChannelMasks[i] = recorder->priv().caps()->channelMask(textures[i].info());
if (!textures[i].isValid() ||
textures[i].dimensions() != planeDimensions[i] ||
textures[i].backend() != textures[0].backend() ||
num_channels(fPlaneChannelMasks[i]) < numRequiredChannels) {
SkASSERT(!this->isValid());
return;
}
fPlaneTextures[i] = textures[i];
}
SkASSERT(this->isValid());
}
SkYUVAInfo::YUVALocations YUVABackendTextures::toYUVALocations() const {
auto result = fYUVAInfo.toYUVALocations(fPlaneChannelMasks.data());
SkDEBUGCODE(int numPlanes;)
SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(result, &numPlanes));
SkASSERT(numPlanes == this->numPlanes());
return result;
}
} // End of namespace skgpu::graphite