77
88#include " src/gpu/mtl/GrMtlGpu.h"
99
10+ #include " include/private/GrTypesPriv.h"
1011#include " src/core/SkCompressedDataUtils.h"
1112#include " src/core/SkConvertPixels.h"
1213#include " src/core/SkMipMap.h"
@@ -594,7 +595,7 @@ static bool check_max_blit_width(int widthInPixels) {
594595
595596 // TODO: can this all be done in one go?
596597 [blitCmdEncoder copyFromBuffer: transferBuffer
597- sourceOffset: individualMipOffsets[currentMipLevel]
598+ sourceOffset: bufferOffset + individualMipOffsets[currentMipLevel]
598599 sourceBytesPerRow: levelRowBytes
599600 sourceBytesPerImage: levelSize
600601 sourceSize: MTLSizeMake (levelDimensions.width (),
@@ -644,7 +645,8 @@ static inline void init_surface_desc(GrSurfaceDesc* surfaceDesc, id<MTLTexture>
644645sk_sp<GrTexture> GrMtlGpu::onWrapBackendTexture (const GrBackendTexture& backendTex,
645646 GrColorType grColorType,
646647 GrWrapOwnership,
647- GrWrapCacheable cacheable, GrIOType ioType) {
648+ GrWrapCacheable cacheable,
649+ GrIOType ioType) {
648650 id <MTLTexture > mtlTexture = get_texture_from_backend (backendTex);
649651 if (!mtlTexture) {
650652 return nullptr ;
@@ -657,9 +659,17 @@ static inline void init_surface_desc(GrSurfaceDesc* surfaceDesc, id<MTLTexture>
657659}
658660
659661sk_sp<GrTexture> GrMtlGpu::onWrapCompressedBackendTexture (const GrBackendTexture& backendTex,
660- GrWrapOwnership ownership ,
662+ GrWrapOwnership,
661663 GrWrapCacheable cacheable) {
662- return nullptr ;
664+ id <MTLTexture > mtlTexture = get_texture_from_backend (backendTex);
665+ if (!mtlTexture) {
666+ return nullptr ;
667+ }
668+
669+ GrSurfaceDesc surfDesc;
670+ init_surface_desc (&surfDesc, mtlTexture, GrRenderable::kNo );
671+
672+ return GrMtlTexture::MakeWrappedTexture (this , surfDesc, mtlTexture, cacheable, kRead_GrIOType );
663673}
664674
665675sk_sp<GrTexture> GrMtlGpu::onWrapRenderableBackendTexture (const GrBackendTexture& backendTex,
@@ -788,7 +798,7 @@ void copy_src_data(char* dst, size_t bytesPerPixel, const SkTArray<size_t>& indi
788798 }
789799}
790800
791- bool GrMtlGpu::createMtlTextureForBackendSurface (MTLPixelFormat format ,
801+ bool GrMtlGpu::createMtlTextureForBackendSurface (MTLPixelFormat mtlFormat ,
792802 SkISize dimensions,
793803 GrTexturable texturable,
794804 GrRenderable renderable,
@@ -800,15 +810,10 @@ void copy_src_data(char* dst, size_t bytesPerPixel, const SkTArray<size_t>& indi
800810 SkASSERT (!data && mipMapped == GrMipMapped::kNo );
801811 }
802812
803- #ifdef SK_BUILD_FOR_IOS
804- // Compressed formats go through onCreateCompressedBackendTexture
805- SkASSERT (!GrMtlFormatIsCompressed (format));
806- #endif
807-
808- if (texturable == GrTexturable::kYes && !fMtlCaps ->isFormatTexturable (format)) {
813+ if (texturable == GrTexturable::kYes && !fMtlCaps ->isFormatTexturable (mtlFormat)) {
809814 return false ;
810815 }
811- if (renderable == GrRenderable::kYes && !fMtlCaps ->isFormatRenderable (format , 1 )) {
816+ if (renderable == GrRenderable::kYes && !fMtlCaps ->isFormatRenderable (mtlFormat , 1 )) {
812817 return false ;
813818 }
814819
@@ -817,7 +822,7 @@ void copy_src_data(char* dst, size_t bytesPerPixel, const SkTArray<size_t>& indi
817822 }
818823
819824 MTLTextureDescriptor * desc =
820- [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: format
825+ [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: mtlFormat
821826 width: dimensions.width ()
822827 height: dimensions.height ()
823828 mipmapped: mipMapped == GrMipMapped: :kYes ];
@@ -835,8 +840,6 @@ void copy_src_data(char* dst, size_t bytesPerPixel, const SkTArray<size_t>& indi
835840 }
836841
837842 // Create the transfer buffer
838- size_t bytesPerPixel = fMtlCaps ->bytesPerPixel (format);
839-
840843 NSUInteger options = 0 ; // TODO: consider other options here
841844 if (@available (macOS 10.11 , iOS 9.0 , *)) {
842845#ifdef SK_BUILD_FOR_MAC
@@ -851,69 +854,121 @@ void copy_src_data(char* dst, size_t bytesPerPixel, const SkTArray<size_t>& indi
851854 numMipLevels = SkMipMap::ComputeLevelCount (dimensions.width (), dimensions.height ()) + 1 ;
852855 }
853856
857+ SkImage::CompressionType compression = GrMtlFormatToCompressionType (mtlFormat);
858+
854859 // Create a transfer buffer and fill with data.
855860 SkSTArray<16 , size_t > individualMipOffsets;
856861 id <MTLBuffer > transferBuffer;
857862 size_t transferBufferSize;
858863
859- SkASSERT (data->type () != BackendTextureData::Type::kCompressed );
860- if (data->type () == BackendTextureData::Type::kPixmaps ) {
861- transferBufferSize = GrComputeTightCombinedBufferSize (bytesPerPixel, dimensions,
862- &individualMipOffsets, numMipLevels);
864+ if (data->type () == BackendTextureData::Type::kCompressed ||
865+ data->type () == BackendTextureData::Type::kPixmaps ) {
866+
867+ if (compression == SkImage::CompressionType::kNone ) {
868+ size_t bytesPerPixel = fMtlCaps ->bytesPerPixel (mtlFormat);
869+
870+ transferBufferSize = GrComputeTightCombinedBufferSize (bytesPerPixel, dimensions,
871+ &individualMipOffsets,
872+ numMipLevels);
873+
874+ } else {
875+ transferBufferSize = SkCompressedDataSize (compression, dimensions,
876+ &individualMipOffsets,
877+ mipMapped == GrMipMapped::kYes );
878+ }
879+ SkASSERT (individualMipOffsets.count () == numMipLevels);
880+
863881 transferBuffer = [fDevice newBufferWithLength: transferBufferSize
864882 options: options];
865883 if (nil == transferBuffer) {
866884 return false ;
867885 }
868886 char * buffer = (char *)transferBuffer.contents ;
869- copy_src_data (buffer, bytesPerPixel, individualMipOffsets, data->pixmaps (), numMipLevels,
870- transferBufferSize);
887+
888+ if (data->type () == BackendTextureData::Type::kPixmaps ) {
889+ size_t bytesPerPixel = fMtlCaps ->bytesPerPixel (mtlFormat);
890+
891+ copy_src_data (buffer, bytesPerPixel, individualMipOffsets, data->pixmaps (),
892+ numMipLevels, transferBufferSize);
893+ } else {
894+ SkASSERT (data->type () == BackendTextureData::Type::kCompressed );
895+
896+ memcpy (buffer, data->compressedData (), data->compressedSize ());
897+ }
871898 } else {
872899 SkASSERT (data->type () == BackendTextureData::Type::kColor );
873- auto colorType = mtl_format_to_backend_tex_clear_colortype (format);
874- if (colorType == GrColorType::kUnknown ) {
875- return false ;
876- }
877- GrImageInfo ii (colorType, kUnpremul_SkAlphaType , nullptr , dimensions);
878- auto rb = ii.minRowBytes ();
879- transferBufferSize = rb*dimensions.height ();
880- transferBuffer = [fDevice newBufferWithLength: transferBufferSize
881- options: options];
882- if (nil == transferBuffer) {
883- return false ;
884- }
885- if (!GrClearImage (ii, transferBuffer.contents , rb, data->color ())) {
886- return false ;
900+
901+ if (compression == SkImage::CompressionType::kNone ) {
902+ auto colorType = mtl_format_to_backend_tex_clear_colortype (mtlFormat);
903+ if (colorType == GrColorType::kUnknown ) {
904+ return false ;
905+ }
906+ GrImageInfo ii (colorType, kUnpremul_SkAlphaType , nullptr , dimensions);
907+ auto rb = ii.minRowBytes ();
908+ transferBufferSize = rb*dimensions.height ();
909+ transferBuffer = [fDevice newBufferWithLength: transferBufferSize
910+ options: options];
911+ if (nil == transferBuffer) {
912+ return false ;
913+ }
914+ if (!GrClearImage (ii, transferBuffer.contents , rb, data->color ())) {
915+ return false ;
916+ }
917+ // Reuse the same buffer for all levels. Should be ok since we made the row bytes tight.
918+ individualMipOffsets.push_back_n (numMipLevels, (size_t )0 );
919+ } else {
920+ transferBufferSize = SkCompressedDataSize (compression, dimensions,
921+ &individualMipOffsets,
922+ mipMapped == GrMipMapped::kYes );
923+ SkASSERT (individualMipOffsets.count () == numMipLevels);
924+
925+ transferBuffer = [fDevice newBufferWithLength: transferBufferSize
926+ options: options];
927+ if (nil == transferBuffer) {
928+ return false ;
929+ }
930+
931+ char * buffer = (char *)transferBuffer.contents ;
932+ GrFillInCompressedData (compression, dimensions, mipMapped, buffer, data->color ());
887933 }
888- // Reuse the same buffer for all levels. Should be ok since we made the row bytes tight.
889- individualMipOffsets.push_back_n (numMipLevels, (size_t )0 );
890934 }
891935
892936 // Transfer buffer contents to texture
893- int currentWidth = dimensions.width ();
894- int currentHeight = dimensions.height ();
895937 MTLOrigin origin = MTLOriginMake (0 , 0 , 0 );
896938
897939 id <MTLCommandBuffer > cmdBuffer = [fQueue commandBuffer ];
898940 id <MTLBlitCommandEncoder > blitCmdEncoder = [cmdBuffer blitCommandEncoder ];
899941
942+ SkISize levelDimensions (dimensions);
900943 for (int currentMipLevel = 0 ; currentMipLevel < numMipLevels; currentMipLevel++) {
901- size_t trimRowBytes = currentWidth * bytesPerPixel;
902- size_t levelSize = trimRowBytes*currentHeight;
944+ size_t levelRowBytes;
945+ size_t levelSize;
946+
947+ if (compression == SkImage::CompressionType::kNone ) {
948+ size_t bytesPerPixel = fMtlCaps ->bytesPerPixel (mtlFormat);
949+
950+ levelRowBytes = levelDimensions.width () * bytesPerPixel;
951+ levelSize = levelRowBytes * levelDimensions.height ();
952+ } else {
953+ levelRowBytes = GrCompressedRowBytes (compression, levelDimensions.width ());
954+ levelSize = SkCompressedDataSize (compression, levelDimensions, nullptr ,
955+ false );
956+ }
903957
904958 // TODO: can this all be done in one go?
905959 [blitCmdEncoder copyFromBuffer: transferBuffer
906960 sourceOffset: individualMipOffsets[currentMipLevel]
907- sourceBytesPerRow: trimRowBytes
961+ sourceBytesPerRow: levelRowBytes
908962 sourceBytesPerImage: levelSize
909- sourceSize: MTLSizeMake (currentWidth, currentHeight, 1 )
963+ sourceSize: MTLSizeMake (levelDimensions.width (),
964+ levelDimensions.height (), 1 )
910965 toTexture: testTexture
911966 destinationSlice: 0
912967 destinationLevel: currentMipLevel
913968 destinationOrigin: origin];
914969
915- currentWidth = SkTMax (1 , currentWidth/ 2 );
916- currentHeight = SkTMax (1 , currentHeight/ 2 ) ;
970+ levelDimensions = { SkTMax (1 , levelDimensions. width () / 2 ),
971+ SkTMax (1 , levelDimensions. height () / 2 ) } ;
917972 }
918973#ifdef SK_BUILD_FOR_MAC
919974 [transferBuffer didModifyRange: NSMakeRange (0 , transferBufferSize)];
@@ -925,7 +980,6 @@ void copy_src_data(char* dst, size_t bytesPerPixel, const SkTArray<size_t>& indi
925980 transferBuffer = nil ;
926981
927982 info->fTexture .reset (GrRetainPtrFromId (testTexture));
928-
929983 return true ;
930984}
931985
@@ -935,8 +989,8 @@ void copy_src_data(char* dst, size_t bytesPerPixel, const SkTArray<size_t>& indi
935989 GrMipMapped mipMapped,
936990 GrProtected isProtected,
937991 const BackendTextureData* data) {
938- // GrGpu::createBackendTexture should've ensured these conditions
939992 const MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat (format);
993+
940994 GrMtlTextureInfo info;
941995 if (!this ->createMtlTextureForBackendSurface (mtlFormat, dimensions, GrTexturable::kYes ,
942996 renderable, mipMapped, &info, data)) {
@@ -948,11 +1002,20 @@ void copy_src_data(char* dst, size_t bytesPerPixel, const SkTArray<size_t>& indi
9481002}
9491003
9501004GrBackendTexture GrMtlGpu::onCreateCompressedBackendTexture (SkISize dimensions,
951- const GrBackendFormat&,
952- GrMipMapped,
953- GrProtected,
954- const BackendTextureData*) {
955- return {};
1005+ const GrBackendFormat& format,
1006+ GrMipMapped mipMapped,
1007+ GrProtected isProtected,
1008+ const BackendTextureData* data) {
1009+ const MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat (format);
1010+
1011+ GrMtlTextureInfo info;
1012+ if (!this ->createMtlTextureForBackendSurface (mtlFormat, dimensions, GrTexturable::kYes ,
1013+ GrRenderable::kNo , mipMapped, &info, data)) {
1014+ return {};
1015+ }
1016+
1017+ GrBackendTexture backendTex (dimensions.width (), dimensions.height (), mipMapped, info);
1018+ return backendTex;
9561019}
9571020
9581021void GrMtlGpu::deleteBackendTexture (const GrBackendTexture& tex) {
0 commit comments