Make RGB_888x pixel operations work.

Also remove vulkan-specific conversions in GrVkGpu and rely
on higher level SurfaceContext to convert correctly.

Bug: skia:8862
Change-Id: Ib8b0541c8c5831148b7129c4bbed3f925660116e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/392378
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2021-04-05 09:34:56 -04:00 committed by Skia Commit-Bot
parent 8960100112
commit 8ce24b1d11
8 changed files with 106 additions and 190 deletions

View File

@ -510,10 +510,6 @@ static inline void append_clamp_gamut(SkRasterPipeline* pipeline) {
bool GrConvertPixels(const GrPixmap& dst, const GrCPixmap& src, bool flipY) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
if (src.colorType() == GrColorType::kRGB_888) {
// We don't expect to have to convert from this format.
return false;
}
if (src.dimensions().isEmpty() || dst.dimensions().isEmpty()) {
return false;
}
@ -538,12 +534,27 @@ bool GrConvertPixels(const GrPixmap& dst, const GrCPixmap& src, bool flipY) {
auto* dRow = reinterpret_cast<char*>(dst.addr());
for (int y = 0; y < dst.height(); ++y, tRow += temp.rowBytes(), dRow += dst.rowBytes()) {
for (int x = 0; x < dst.width(); ++x) {
auto t = reinterpret_cast<const uint32_t*>(tRow + x * sizeof(uint32_t));
auto d = reinterpret_cast<uint32_t*>(dRow + x * 3);
auto t = tRow + x*sizeof(uint32_t);
auto d = dRow + x*3;
memcpy(d, t, 3);
}
}
return true;
} else if (src.colorType() == GrColorType::kRGB_888) {
// SkRasterPipeline doesn't handle reading from RGB_888. So convert it to RGB_888x and then
// do a recursive call if there is any remaining conversion.
GrPixmap temp = GrPixmap::Allocate(src.info().makeColorType(GrColorType::kRGB_888x));
auto* sRow = reinterpret_cast<const char*>(src.addr());
auto* tRow = reinterpret_cast<char*>(temp.addr());
for (int y = 0; y < src.height(); ++y, sRow += src.rowBytes(), tRow += temp.rowBytes()) {
for (int x = 0; x < src.width(); ++x) {
auto s = sRow + x*3;
auto t = tRow + x*sizeof(uint32_t);
memcpy(t, s, 3);
t[3] = static_cast<char>(0xFF);
}
}
return GrConvertPixels(dst, temp, flipY);
}
size_t srcBpp = src.info().bpp();

View File

@ -615,13 +615,13 @@ bool GrSurfaceContext::internalWritePixels(GrDirectContext* dContext,
pt.fY = flip ? dstSurface->height() - pt.fY - src[0].height() : pt.fY;
if (!dContext->priv().drawingManager()->newWritePixelsTask(
sk_ref_sp(dstProxy),
SkIRect::MakePtSize(pt, src[0].dimensions()),
this->colorInfo().colorType(),
allowedColorType,
srcLevels.begin(),
numLevels,
prepForSampling)) {
sk_ref_sp(dstProxy),
SkIRect::MakePtSize(pt, src[0].dimensions()),
allowedColorType,
this->colorInfo().colorType(),
srcLevels.begin(),
numLevels,
prepForSampling)) {
return false;
}
if (numLevels > 1) {

View File

@ -2388,17 +2388,11 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
ctInfo.fExternalIOFormats = std::make_unique<ColorTypeInfo::ExternalIOFormats[]>(
ctInfo.fExternalIOFormatCount);
int ioIdx = 0;
// Format: RGB8, Surface: kRGB_888x, Data: kRGB_888x
// Format: RGB8, Surface: kRGB_888x, Data: kRGB_888
{
auto& ioFormat = ctInfo.fExternalIOFormats[ioIdx++];
ioFormat.fColorType = GrColorType::kRGB_888x;
ioFormat.fColorType = GrColorType::kRGB_888;
ioFormat.fExternalType = GR_GL_UNSIGNED_BYTE;
// This is technically the wrong format to use for this color type since the color
// type is 4 bytes but the format is 3. However, we don't currently upload data of
// this type so the format is only used when creating an empty texture. If we want
// to support uploading data we should add in RGB_888 GrColorType. Additionally, on
// the FormatInfo we should have a default format to use when we want to create an
// empty texture.
ioFormat.fExternalTexImageFormat = GR_GL_RGB;
ioFormat.fExternalReadFormat = 0;
}

View File

@ -868,6 +868,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kRGBA_8888;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
}
// Format: VK_FORMAT_R8G8B8A8_UNORM, Surface: kRGB_888x
@ -875,6 +876,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kRGB_888x;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
ctInfo.fReadSwizzle = GrSwizzle::RGB1();
}
@ -895,6 +897,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kAlpha_8;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
ctInfo.fReadSwizzle = GrSwizzle("000r");
ctInfo.fWriteSwizzle = GrSwizzle("a000");
@ -904,6 +907,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kGray_8;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
ctInfo.fReadSwizzle = GrSwizzle("rrr1");
}
@ -923,6 +927,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kBGRA_8888;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
}
}
@ -941,6 +946,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kBGR_565;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
}
}
@ -959,6 +965,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kRGBA_F16;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
}
// Format: VK_FORMAT_R16G16B16A16_SFLOAT, Surface: GrColorType::kRGBA_F16_Clamped
@ -966,6 +973,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kRGBA_F16_Clamped;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
}
}
@ -984,6 +992,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kAlpha_F16;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
ctInfo.fReadSwizzle = GrSwizzle("000r");
ctInfo.fWriteSwizzle = GrSwizzle("a000");
@ -1004,6 +1013,8 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kRGB_888x;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
// The Vulkan format is 3 bpp so we must convert to/from that when transferring.
ctInfo.fTransferColorType = GrColorType::kRGB_888;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
}
}
@ -1022,6 +1033,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kRG_88;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
}
}
@ -1040,6 +1052,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kRGBA_1010102;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
}
}
@ -1058,6 +1071,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kBGRA_1010102;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
}
}
@ -1076,6 +1090,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kABGR_4444;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
ctInfo.fReadSwizzle = GrSwizzle::BGRA();
ctInfo.fWriteSwizzle = GrSwizzle::BGRA();
@ -1097,6 +1112,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kABGR_4444;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
}
}
@ -1115,6 +1131,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kRGBA_8888_SRGB;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
}
}
@ -1133,6 +1150,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kAlpha_16;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
ctInfo.fReadSwizzle = GrSwizzle("000r");
ctInfo.fWriteSwizzle = GrSwizzle("a000");
@ -1153,6 +1171,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kRG_1616;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
}
}
@ -1171,6 +1190,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kRGBA_16161616;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
}
}
@ -1189,6 +1209,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kRG_F16;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
}
}
@ -1209,6 +1230,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kRGB_888x;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kWrappedOnly_Flag;
}
}
@ -1229,6 +1251,7 @@ void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice
constexpr GrColorType ct = GrColorType::kRGB_888x;
auto& ctInfo = info.fColorTypeInfos[ctIdx++];
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kWrappedOnly_Flag;
}
}
@ -1529,7 +1552,7 @@ GrCaps::SupportedWrite GrVkCaps::supportedWritePixelsColorType(GrColorType surfa
for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
const auto& ctInfo = info.fColorTypeInfos[i];
if (ctInfo.fColorType == surfaceColorType) {
return {surfaceColorType, offsetAlignment};
return {ctInfo.fTransferColorType, offsetAlignment};
}
}
return {GrColorType::kUnknown, 0};
@ -1560,6 +1583,16 @@ GrCaps::SurfaceReadPixelsSupport GrVkCaps::surfaceSupportsReadPixels(
return SurfaceReadPixelsSupport::kUnsupported;
}
GrColorType GrVkCaps::transferColorType(VkFormat vkFormat, GrColorType surfaceColorType) const {
const auto& info = this->getFormatInfo(vkFormat);
for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
if (info.fColorTypeInfos[i].fColorType == surfaceColorType) {
return info.fColorTypeInfos[i].fTransferColorType;
}
}
return GrColorType::kUnknown;
}
bool GrVkCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
if (auto rt = surface->asRenderTarget()) {
return rt->numSamples() <= 1 && SkToBool(surface->asTexture());
@ -1720,7 +1753,7 @@ GrCaps::SupportedRead GrVkCaps::onSupportedReadPixelsColorType(
for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
const auto& ctInfo = info.fColorTypeInfos[i];
if (ctInfo.fColorType == srcColorType) {
return {srcColorType, offsetAlignment};
return {ctInfo.fTransferColorType, offsetAlignment};
}
}
return {GrColorType::kUnknown, 0};

View File

@ -75,6 +75,10 @@ public:
return SkToBool(FormatInfo::kBlitSrc_Flag & flags);
}
// Gets the GrColorType that should be used to transfer data in/out of a transfer buffer to
// write/read data when using a VkFormat with a specified color type.
GrColorType transferColorType(VkFormat, GrColorType surfaceColorType) const;
// On some GPUs (Windows Nvidia and Imagination) calls to QueueWaitIdle return before actually
// signalling the fences on the command buffers even though they have completed. This causes
// issues when then deleting the command buffers. Therefore we additionally will call
@ -294,6 +298,7 @@ private:
// ColorTypeInfo for a specific format
struct ColorTypeInfo {
GrColorType fColorType = GrColorType::kUnknown;
GrColorType fTransferColorType = GrColorType::kUnknown;
enum {
kUploadData_Flag = 0x1,
// Does Ganesh itself support rendering to this colorType & format pair. Renderability

View File

@ -483,9 +483,6 @@ bool GrVkGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt
if (!this->currentCommandBuffer()) {
return false;
}
if (surfaceColorType != bufferColorType) {
return false;
}
size_t bpp = GrColorTypeBytesPerPixel(bufferColorType);
if (GrBackendFormatBytesPerPixel(texture->backendFormat()) != bpp) {
@ -501,14 +498,20 @@ bool GrVkGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt
return false;
}
GrVkAttachment* vkTex = tex->textureAttachment();
VkFormat format = vkTex->imageFormat();
// Can't transfer compressed data
SkASSERT(!GrVkFormatIsCompressed(vkTex->imageFormat()));
SkASSERT(!GrVkFormatIsCompressed(format));
if (!transferBuffer) {
return false;
}
if (bufferColorType != this->vkCaps().transferColorType(format, surfaceColorType)) {
return false;
}
SkASSERT(GrVkFormatBytesPerBlock(format) == GrColorTypeBytesPerPixel(bufferColorType));
SkDEBUGCODE(
SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
SkIRect bounds = SkIRect::MakeWH(texture->width(), texture->height());
@ -558,9 +561,6 @@ bool GrVkGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int wi
if (fProtectedContext == GrProtected::kYes) {
return false;
}
if (surfaceColorType != bufferColorType) {
return false;
}
GrVkImage* srcImage;
if (GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(surface->asRenderTarget())) {
@ -579,10 +579,11 @@ bool GrVkGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int wi
srcImage = static_cast<GrVkTexture*>(surface->asTexture())->textureAttachment();
}
if (GrVkFormatBytesPerBlock(srcImage->imageFormat()) !=
GrColorTypeBytesPerPixel(surfaceColorType)) {
VkFormat format = srcImage->imageFormat();
if (bufferColorType != this->vkCaps().transferColorType(format, surfaceColorType)) {
return false;
}
SkASSERT(GrVkFormatBytesPerBlock(format) == GrColorTypeBytesPerPixel(bufferColorType));
// Set up copy region
VkBufferImageCopy region;
@ -808,22 +809,6 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkAttachment* texAttachment, int left, int
}
SkASSERT(this->vkCaps().surfaceSupportsWritePixels(texAttachment));
SkASSERT(this->vkCaps().areColorTypeAndFormatCompatible(
dataColorType, texAttachment->backendFormat()));
// For RGB_888x src data we are uploading it first to an RGBA texture and then copying it to the
// dst RGB texture. Thus we do not upload mip levels for that.
if (dataColorType == GrColorType::kRGB_888x &&
texAttachment->imageFormat() == VK_FORMAT_R8G8B8_UNORM) {
// First check that we'll be able to do the copy to the to the R8G8B8 image in the end via a
// blit or draw.
if (!this->vkCaps().formatCanBeDstofBlit(VK_FORMAT_R8G8B8_UNORM,
texAttachment->isLinearTiled()) &&
!this->vkCaps().isFormatRenderable(VK_FORMAT_R8G8B8_UNORM, 1)) {
return false;
}
mipLevelCount = 1;
}
SkASSERT(this->vkCaps().isVkFormatTexturable(texAttachment->imageFormat()));
size_t bpp = GrColorTypeBytesPerPixel(dataColorType);
@ -834,39 +819,19 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkAttachment* texAttachment, int left, int
SkAutoTArray<GrMipLevel> texelsShallowCopy(mipLevelCount);
std::copy_n(texels, mipLevelCount, texelsShallowCopy.get());
SkTArray<size_t> individualMipOffsets(mipLevelCount);
individualMipOffsets.push_back(0);
size_t combinedBufferSize = width * bpp * height;
int currentWidth = width;
int currentHeight = height;
if (!texelsShallowCopy[0].fPixels) {
combinedBufferSize = 0;
}
// The alignment must be at least 4 bytes and a multiple of the bytes per pixel of the image
// config. This works with the assumption that the bytes in pixel config is always a power of 2.
SkASSERT((bpp & (bpp - 1)) == 0);
const size_t alignmentMask = 0x3 | (bpp - 1);
for (int currentMipLevel = 1; currentMipLevel < mipLevelCount; currentMipLevel++) {
currentWidth = std::max(1, currentWidth/2);
currentHeight = std::max(1, currentHeight/2);
if (texelsShallowCopy[currentMipLevel].fPixels) {
const size_t trimmedSize = currentWidth * bpp * currentHeight;
const size_t alignmentDiff = combinedBufferSize & alignmentMask;
if (alignmentDiff != 0) {
combinedBufferSize += alignmentMask - alignmentDiff + 1;
}
individualMipOffsets.push_back(combinedBufferSize);
combinedBufferSize += trimmedSize;
} else {
individualMipOffsets.push_back(0);
}
}
if (0 == combinedBufferSize) {
// We don't actually have any data to upload so just return success
return true;
SkTArray<size_t> individualMipOffsets;
size_t combinedBufferSize;
if (mipLevelCount > 1) {
combinedBufferSize = GrComputeTightCombinedBufferSize(bpp,
{width, height},
&individualMipOffsets,
mipLevelCount);
} else {
SkASSERT(texelsShallowCopy[0].fPixels && texelsShallowCopy[0].fRowBytes);
combinedBufferSize = width*height*bpp;
individualMipOffsets.push_back(0);
}
SkASSERT(combinedBufferSize);
// Get a staging buffer slice to hold our mip data.
// Vulkan requires offsets in the buffer to be aligned to multiple of the texel size and 4
@ -879,37 +844,13 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkAttachment* texAttachment, int left, int
int uploadLeft = left;
int uploadTop = top;
GrVkAttachment* uploadTexture = texAttachment;
// For uploading RGB_888x data to an R8G8B8_UNORM texture we must first upload the data to an
// R8G8B8A8_UNORM image and then copy it.
sk_sp<GrVkAttachment> copyTexAttachment;
if (dataColorType == GrColorType::kRGB_888x &&
texAttachment->imageFormat() == VK_FORMAT_R8G8B8_UNORM) {
bool dstHasYcbcr = texAttachment->ycbcrConversionInfo().isValid();
if (!this->vkCaps().canCopyAsBlit(texAttachment->imageFormat(), 1, false, dstHasYcbcr,
VK_FORMAT_R8G8B8A8_UNORM, 1, false, false)) {
return false;
}
copyTexAttachment = GrVkAttachment::MakeTexture(this, {width, height},
VK_FORMAT_R8G8B8A8_UNORM, /*mipLevels=*/1,
GrRenderable::kNo, /*numSamples=*/1,
SkBudgeted::kYes, GrProtected::kNo);
if (!copyTexAttachment) {
return false;
}
uploadTexture = copyTexAttachment.get();
uploadLeft = 0;
uploadTop = 0;
}
char* buffer = (char*) slice.fOffsetMapPtr;
SkTArray<VkBufferImageCopy> regions(mipLevelCount);
currentWidth = width;
currentHeight = height;
int layerHeight = uploadTexture->height();
int currentWidth = width;
int currentHeight = height;
int layerHeight = texAttachment->height();
for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
if (texelsShallowCopy[currentMipLevel].fPixels) {
SkASSERT(1 == mipLevelCount || currentHeight == layerHeight);
@ -926,17 +867,19 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkAttachment* texAttachment, int left, int
region.bufferOffset = slice.fOffset + individualMipOffsets[currentMipLevel];
region.bufferRowLength = currentWidth;
region.bufferImageHeight = currentHeight;
region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1 };
region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1};
region.imageOffset = {uploadLeft, uploadTop, 0};
region.imageExtent = { (uint32_t)currentWidth, (uint32_t)currentHeight, 1 };
region.imageExtent = {(uint32_t)currentWidth, (uint32_t)currentHeight, 1};
}
currentWidth = std::max(1, currentWidth/2);
currentWidth = std::max(1, currentWidth/2);
currentHeight = std::max(1, currentHeight/2);
layerHeight = currentHeight;
}
// Change layout of our target so it can be copied to
uploadTexture->setImageLayout(this,
texAttachment->setImageLayout(this,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
@ -950,20 +893,10 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkAttachment* texAttachment, int left, int
GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(slice.fBuffer);
this->currentCommandBuffer()->copyBufferToImage(this,
vkBuffer->vkBuffer(),
uploadTexture,
texAttachment,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
regions.count(),
regions.begin());
// If we copied the data into a temporary image first, copy that image into our main texture
// now.
if (copyTexAttachment) {
SkASSERT(dataColorType == GrColorType::kRGB_888x);
SkAssertResult(this->copySurface(texAttachment, copyTexAttachment.get(),
SkIRect::MakeWH(width, height),
SkIPoint::Make(left, top)));
}
return true;
}
@ -2387,10 +2320,6 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int
return false;
}
if (surfaceColorType != dstColorType) {
return false;
}
if (!this->currentCommandBuffer()) {
return false;
}
@ -2413,55 +2342,9 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int
return false;
}
// Skia's RGB_888x color type, which we map to the vulkan R8G8B8_UNORM, expects the data to be
// 32 bits, but the Vulkan format is only 24. So we first copy the surface into an R8G8B8A8
// image and then do the read pixels from that.
sk_sp<GrVkAttachment> copySurface;
if (dstColorType == GrColorType::kRGB_888x && image->imageFormat() == VK_FORMAT_R8G8B8_UNORM) {
int srcSampleCount = 0;
if (rt) {
srcSampleCount = rt->numSamples();
}
bool srcHasYcbcr = image->ycbcrConversionInfo().isValid();
if (!this->vkCaps().canCopyAsBlit(VK_FORMAT_R8G8B8A8_UNORM, 1, false, false,
image->imageFormat(), srcSampleCount,
image->isLinearTiled(), srcHasYcbcr)) {
return false;
}
// Make a new surface that is RGBA to copy the RGB surface into.
VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
GrVkImage::ImageDesc imageDesc;
imageDesc.fImageType = VK_IMAGE_TYPE_2D;
imageDesc.fFormat = VK_FORMAT_R8G8B8A8_UNORM;
imageDesc.fWidth = width;
imageDesc.fHeight = height;
imageDesc.fLevels = 1;
imageDesc.fSamples = 1;
imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
imageDesc.fUsageFlags = usageFlags;
imageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
copySurface =
GrVkAttachment::MakeTexture(this, {width, height}, VK_FORMAT_R8G8B8A8_UNORM,
/*mipLevels=*/1, GrRenderable::kYes, /*numSamples=*/1,
SkBudgeted::kYes, GrProtected::kNo);
if (!copySurface) {
return false;
}
SkIRect srcRect = SkIRect::MakeXYWH(left, top, width, height);
SkAssertResult(this->copySurface(copySurface.get(), surface, srcRect, SkIPoint::Make(0,0)));
top = 0;
left = 0;
dstColorType = GrColorType::kRGBA_8888;
image = copySurface.get();
if (dstColorType == GrColorType::kUnknown ||
dstColorType != this->vkCaps().transferColorType(image->imageFormat(), surfaceColorType)) {
return false;
}
// Change layout of our target so it can be used as copy

View File

@ -501,10 +501,6 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceContextReadPixels, reporter, ctxInfo)
for (GrSurfaceOrigin origin : {kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin}) {
auto factory = std::function<GpuSrcFactory<Surface>>(
[direct, origin, renderable](const SkPixmap& src) {
// skbug.com/8862
if (src.colorType() == kRGB_888x_SkColorType) {
return Surface();
}
auto surfContext = GrSurfaceContext::Make(
direct, src.info(), SkBackingFit::kExact, origin, renderable);
if (surfContext) {
@ -623,10 +619,6 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceAsyncReadPixels, reporter, ctxInfo) {
gpu_read_pixels_test_driver(reporter, rules, factory, reader, label);
auto backendRTFactory = std::function<GpuSrcFactory<Surface>>(
[context = ctxInfo.directContext(), origin](const SkPixmap& src) {
// skbug.com/8862
if (src.colorType() == kRGB_888x_SkColorType) {
return Surface();
}
// Dawn backend implementation of backend render targets doesn't support
// reading.
if (context->backend() == GrBackendApi::kDawn) {
@ -1099,10 +1091,6 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceContextWritePixels, reporter, ctxInfo)
for (GrSurfaceOrigin origin : {kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin}) {
auto factory = std::function<GpuDstFactory<Surface>>(
[direct, origin, renderable](const SkImageInfo& info) {
// skbug.com/8862
if (info.colorType() == kRGB_888x_SkColorType) {
return Surface();
}
return GrSurfaceContext::Make(direct,
info,
SkBackingFit::kExact,

View File

@ -315,7 +315,9 @@ void basic_transfer_from_test(skiatest::Reporter* reporter, const sk_gpu_test::C
size_t bufferSize = fullBufferRowBytes * kTexDims.fHeight;
// Arbitrary starting offset for the partial read.
size_t partialReadOffset = GrAlignTo(11, offsetAlignment);
static constexpr size_t kStartingOffset = 11;
size_t partialReadOffset = kStartingOffset +
(offsetAlignment - kStartingOffset%offsetAlignment)%offsetAlignment;
bufferSize = std::max(bufferSize, partialReadOffset + partialBufferRowBytes * kPartialHeight);
sk_sp<GrGpuBuffer> buffer(resourceProvider->createBuffer(
@ -421,7 +423,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TransferPixelsToTextureTest, reporter, ctxInf
GrColorType::kABGR_4444,
GrColorType::kRGBA_8888,
GrColorType::kRGBA_8888_SRGB,
// GrColorType::kRGB_888x, Broken in GL until we have kRGB_888
GrColorType::kRGB_888x,
GrColorType::kRG_88,
GrColorType::kBGRA_8888,
GrColorType::kRGBA_1010102,
@ -454,7 +456,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TransferPixelsFromTextureTest, reporter, ctxI
GrColorType::kABGR_4444,
GrColorType::kRGBA_8888,
GrColorType::kRGBA_8888_SRGB,
// GrColorType::kRGB_888x, Broken in GL until we have kRGB_888
GrColorType::kRGB_888x,
GrColorType::kRG_88,
GrColorType::kBGRA_8888,
GrColorType::kRGBA_1010102,