diff options
-rw-r--r-- | src/gpu/vk/GrVkGpu.cpp | 83 |
1 files changed, 48 insertions, 35 deletions
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index 33b53b1bcd..71782777a5 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -283,9 +283,10 @@ bool GrVkGpu::onWritePixels(GrSurface* surface, success = this->uploadTexDataLinear(vkTex, left, top, width, height, config, texels.begin()->fPixels, texels.begin()->fRowBytes); } else { - int mipLevels = texels.count(); - if (vkTex->texturePriv().maxMipMapLevel() != mipLevels) { - if (!vkTex->reallocForMipmap(this, mipLevels)) { + int newMipLevels = texels.count(); + int currentMipLevels = vkTex->texturePriv().maxMipMapLevel(); + if ((currentMipLevels || newMipLevels != 1) && newMipLevels != currentMipLevels) { + if (!vkTex->reallocForMipmap(this, newMipLevels)) { return false; } } @@ -389,36 +390,45 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, size_t bpp = GrBytesPerPixel(dataConfig); // texels is const. - // But we may need to adjust the fPixels ptr based on the copyRect. - // In this case we need to make a non-const shallow copy of texels. - const SkTArray<GrMipLevel>* texelsPtr = &texels; - SkTArray<GrMipLevel> texelsCopy; - if (0 != left || 0 != top || width != tex->width() || height != tex->height()) { - texelsCopy = texels; + // But we may need to adjust the fPixels ptr based on the copyRect, or fRowBytes. + // Because of this we need to make a non-const shallow copy of texels. + SkTArray<GrMipLevel> texelsShallowCopy(texels); - SkASSERT(1 == texels.count()); - SkASSERT(texelsCopy[0].fPixels); - - if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top, - &width, &height, &texelsCopy[0].fPixels, - &texelsCopy[0].fRowBytes)) { - return false; - } - - texelsPtr = &texelsCopy; + for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >= 0; + currentMipLevel--) { + SkASSERT(texelsShallowCopy[currentMipLevel].fPixels); } // Determine whether we need to flip when we copy into the buffer - bool flipY = (kBottomLeft_GrSurfaceOrigin == desc.fOrigin && !texelsPtr->empty()); + bool flipY = (kBottomLeft_GrSurfaceOrigin == desc.fOrigin && !texelsShallowCopy.empty()); + // adjust any params (left, top, currentWidth, currentHeight // find the combined size of all the mip levels and the relative offset of // each into the collective buffer - size_t combinedBufferSize = 0; - SkTArray<size_t> individualMipOffsets(texelsPtr->count()); - for (int currentMipLevel = 0; currentMipLevel < texelsPtr->count(); currentMipLevel++) { - int twoToTheMipLevel = 1 << currentMipLevel; - int currentWidth = SkTMax(1, width / twoToTheMipLevel); - int currentHeight = SkTMax(1, height / twoToTheMipLevel); + // Do the first level separately because we may need to adjust width and height + // (for the non-mipped case). + if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top, + &width, + &height, + &texelsShallowCopy[0].fPixels, + &texelsShallowCopy[0].fRowBytes)) { + return false; + } + SkTArray<size_t> individualMipOffsets(texelsShallowCopy.count()); + individualMipOffsets.push_back(0); + size_t combinedBufferSize = width * bpp * height; + int currentWidth = width; + int currentHeight = height; + for (int currentMipLevel = 1; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) { + currentWidth = SkTMax(1, currentWidth/2); + currentHeight = SkTMax(1, currentHeight/2); + if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top, + ¤tWidth, + ¤tHeight, + &texelsShallowCopy[currentMipLevel].fPixels, + &texelsShallowCopy[currentMipLevel].fRowBytes)) { + return false; + } const size_t trimmedSize = currentWidth * bpp * currentHeight; individualMipOffsets.push_back(combinedBufferSize); combinedBufferSize += trimmedSize; @@ -429,18 +439,17 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, GrVkTransferBuffer::Create(this, combinedBufferSize, GrVkBuffer::kCopyRead_Type); char* buffer = (char*) transferBuffer->map(); - SkTArray<VkBufferImageCopy> regions(texelsPtr->count()); + SkTArray<VkBufferImageCopy> regions(texelsShallowCopy.count()); - for (int currentMipLevel = 0; currentMipLevel < texelsPtr->count(); currentMipLevel++) { - int twoToTheMipLevel = 1 << currentMipLevel; - int currentWidth = SkTMax(1, width / twoToTheMipLevel); - int currentHeight = SkTMax(1, height / twoToTheMipLevel); + currentWidth = width; + currentHeight = height; + for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) { const size_t trimRowBytes = currentWidth * bpp; - const size_t rowBytes = (*texelsPtr)[currentMipLevel].fRowBytes; + const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes; // copy data into the buffer, skipping the trailing bytes char* dst = buffer + individualMipOffsets[currentMipLevel]; - const char* src = (const char*)(*texelsPtr)[currentMipLevel].fPixels; + const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels; if (flipY) { src += (currentHeight - 1) * rowBytes; for (int y = 0; y < currentHeight; y++) { @@ -460,8 +469,11 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, region.bufferRowLength = currentWidth; region.bufferImageHeight = currentHeight; region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1 }; - region.imageOffset = { left, top, 0 }; + region.imageOffset = { left, flipY ? tex->height() - top - currentHeight : top, 0 }; region.imageExtent = { (uint32_t)currentWidth, (uint32_t)currentHeight, 1 }; + + currentWidth = SkTMax(1, currentWidth/2); + currentHeight = SkTMax(1, currentHeight/2); } transferBuffer->unmap(); @@ -553,12 +565,13 @@ GrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budget // This ImageDesc refers to the texture that will be read by the client. Thus even if msaa is // requested, this ImageDesc describes the resolved texture. Therefore we always have samples set // to 1. + int mipLevels = texels.empty() ? 1 : texels.count(); GrVkImage::ImageDesc imageDesc; imageDesc.fImageType = VK_IMAGE_TYPE_2D; imageDesc.fFormat = pixelFormat; imageDesc.fWidth = desc.fWidth; imageDesc.fHeight = desc.fHeight; - imageDesc.fLevels = linearTiling ? 1 : texels.count(); + imageDesc.fLevels = linearTiling ? 1 : mipLevels; imageDesc.fSamples = 1; imageDesc.fImageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL; imageDesc.fUsageFlags = usageFlags; |