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:
parent
8960100112
commit
8ce24b1d11
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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};
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user