@@ -89,7 +89,22 @@ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
89
89
#import " CCSpriteFrame.h"
90
90
91
91
#if __CC_METAL_SUPPORTED_AND_ENABLED
92
+
92
93
#import " CCMetalSupport_Private.h"
94
+
95
+ static const MTLPixelFormat MetalPixelFormats[] = {
96
+ MTLPixelFormatRGBA8Unorm ,
97
+ MTLPixelFormatInvalid , // CCTexturePixelFormat_RGB888,
98
+ MTLPixelFormatInvalid , // CCTexturePixelFormat_RGB565,
99
+ MTLPixelFormatA8Unorm , // CCTexturePixelFormat_A8,
100
+ MTLPixelFormatRG8Unorm , // CCTexturePixelFormat_I8,
101
+ MTLPixelFormatInvalid , // CCTexturePixelFormat_AI88,
102
+ MTLPixelFormatABGR4Unorm, // CCTexturePixelFormat_RGBA4444,
103
+ MTLPixelFormatInvalid , // CCTexturePixelFormat_RGB5A1,
104
+ MTLPixelFormatPVRTC_RGBA_4BPP, // CCTexturePixelFormat_PVRTC4,
105
+ MTLPixelFormatPVRTC_RGBA_2BPP, // CCTexturePixelFormat_PVRTC2,
106
+ };
107
+
93
108
#endif
94
109
95
110
@@ -213,43 +228,30 @@ + (id) textureWithFile:(NSString*)file
213
228
- (id ) initWithData : (const void *)data pixelFormat : (CCTexturePixelFormat)pixelFormat pixelsWide : (NSUInteger )width pixelsHigh : (NSUInteger )height contentSizeInPixels : (CGSize)sizeInPixels contentScale : (CGFloat)contentScale
214
229
{
215
230
if ((self = [super init ])) {
216
- CCRenderDispatch (NO , ^{
217
231
#if __CC_METAL_SUPPORTED_AND_ENABLED
218
- if ([CCConfiguration sharedConfiguration ].graphicsAPI == CCGraphicsAPIMetal){
219
- id <MTLDevice > device = [CCMetalContext currentContext ].device ;
220
-
221
- MTLSamplerDescriptor *samplerDesc = [MTLSamplerDescriptor new ];
222
- samplerDesc.minFilter = MTLSamplerMinMagFilterLinear ;
223
- samplerDesc.magFilter = MTLSamplerMinMagFilterLinear ;
224
- samplerDesc.mipFilter = MTLSamplerMipFilterNotMipmapped ;
225
- samplerDesc.sAddressMode = MTLSamplerAddressModeClampToEdge ;
226
- samplerDesc.tAddressMode = MTLSamplerAddressModeClampToEdge ;
227
-
228
- _metalSampler = [device newSamplerStateWithDescriptor: samplerDesc];
229
-
230
- static const MTLPixelFormat metalFormats[] = {
231
- MTLPixelFormatRGBA8Unorm ,
232
- MTLPixelFormatInvalid , // CCTexturePixelFormat_RGB888,
233
- MTLPixelFormatInvalid , // CCTexturePixelFormat_RGB565,
234
- MTLPixelFormatA8Unorm , // CCTexturePixelFormat_A8,
235
- MTLPixelFormatRG8Unorm , // CCTexturePixelFormat_I8,
236
- MTLPixelFormatInvalid , // CCTexturePixelFormat_AI88,
237
- MTLPixelFormatABGR4Unorm, // CCTexturePixelFormat_RGBA4444,
238
- MTLPixelFormatInvalid , // CCTexturePixelFormat_RGB5A1,
239
- MTLPixelFormatPVRTC_RGBA_4BPP, // CCTexturePixelFormat_PVRTC4,
240
- MTLPixelFormatPVRTC_RGBA_2BPP, // CCTexturePixelFormat_PVRTC2,
241
- };
242
- MTLPixelFormat metalFormat = metalFormats[pixelFormat];
243
- NSAssert (metalFormat != MTLPixelFormatInvalid , @" This texture format is not supported by Apple's Metal API." );
244
-
245
- MTLTextureDescriptor *textureDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: metalFormat width: width height: height mipmapped: NO ];
246
- _metalTexture = [device newTextureWithDescriptor: textureDesc];
247
-
248
- NSUInteger bytesPerRow = width*[CCTexture bitsPerPixelForFormat: pixelFormat]/8 ;
249
- [_metalTexture replaceRegion: MTLRegionMake2D (0 , 0 , width, height) mipmapLevel: 0 withBytes: data bytesPerRow: bytesPerRow];
250
- } else
232
+ if ([CCConfiguration sharedConfiguration ].graphicsAPI == CCGraphicsAPIMetal){
233
+ id <MTLDevice > device = [CCMetalContext currentContext ].device ;
234
+
235
+ MTLSamplerDescriptor *samplerDesc = [MTLSamplerDescriptor new ];
236
+ samplerDesc.minFilter = MTLSamplerMinMagFilterLinear ;
237
+ samplerDesc.magFilter = MTLSamplerMinMagFilterLinear ;
238
+ samplerDesc.mipFilter = MTLSamplerMipFilterNotMipmapped ;
239
+ samplerDesc.sAddressMode = MTLSamplerAddressModeClampToEdge ;
240
+ samplerDesc.tAddressMode = MTLSamplerAddressModeClampToEdge ;
241
+
242
+ _metalSampler = [device newSamplerStateWithDescriptor: samplerDesc];
243
+
244
+ MTLPixelFormat metalFormat = MetalPixelFormats[pixelFormat];
245
+ NSAssert (metalFormat != MTLPixelFormatInvalid , @" This texture format is not supported by Apple's Metal API." );
246
+
247
+ MTLTextureDescriptor *textureDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: metalFormat width: width height: height mipmapped: NO ];
248
+ _metalTexture = [device newTextureWithDescriptor: textureDesc];
249
+
250
+ NSUInteger bytesPerRow = width*[CCTexture bitsPerPixelForFormat: pixelFormat]/8 ;
251
+ [_metalTexture replaceRegion: MTLRegionMake2D (0 , 0 , width, height) mipmapLevel: 0 withBytes: data bytesPerRow: bytesPerRow];
252
+ } else
251
253
#endif
252
- {
254
+ CCRenderDispatch ( NO , ^ {
253
255
CCGL_DEBUG_PUSH_GROUP_MARKER (" CCTexture: Init" );
254
256
255
257
// XXX: 32 bits or POT textures uses UNPACK of 4 (is this correct ??? )
@@ -296,7 +298,6 @@ - (id) initWithData:(const void*)data pixelFormat:(CCTexturePixelFormat)pixelFor
296
298
}
297
299
298
300
CCGL_DEBUG_POP_GROUP_MARKER ();
299
- }
300
301
});
301
302
302
303
_sizeInPixels = sizeInPixels;
@@ -393,9 +394,40 @@ -(CCSpriteFrame*) createSpriteFrame
393
394
394
395
- (void ) setAntialiased : (BOOL )antialiased
395
396
{
396
- _antialiased = antialiased;
397
- if (antialiased) [self setAntiAliasTexParameters ];
398
- else [self setAliasTexParameters ];
397
+ if (_antialiased != antialiased){
398
+ CCRenderDispatch (NO , ^{
399
+ #if __CC_METAL_SUPPORTED_AND_ENABLED
400
+ if ([CCConfiguration sharedConfiguration ].graphicsAPI == CCGraphicsAPIMetal){
401
+ CCMetalContext *context = [CCMetalContext currentContext ];
402
+
403
+ MTLSamplerDescriptor *samplerDesc = [MTLSamplerDescriptor new ];
404
+ samplerDesc.minFilter = samplerDesc.magFilter = (antialiased ? MTLSamplerMinMagFilterLinear : MTLSamplerMinMagFilterNearest );
405
+ samplerDesc.mipFilter = (_hasMipmaps ? MTLSamplerMipFilterNearest : MTLSamplerMipFilterNotMipmapped );
406
+ samplerDesc.sAddressMode = MTLSamplerAddressModeClampToEdge ;
407
+ samplerDesc.tAddressMode = MTLSamplerAddressModeClampToEdge ;
408
+
409
+ _metalSampler = [context.device newSamplerStateWithDescriptor: samplerDesc];
410
+ } else
411
+ #endif
412
+ {
413
+ CCGL_DEBUG_PUSH_GROUP_MARKER (" CCTexture: Set Alias Texture Parameters" );
414
+
415
+ glBindTexture (GL_TEXTURE_2D, _name);
416
+
417
+ if (_hasMipmaps){
418
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, antialiased ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_NEAREST);
419
+ } else {
420
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, antialiased ? GL_LINEAR : GL_NEAREST);
421
+ }
422
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, antialiased ? GL_LINEAR : GL_NEAREST);
423
+
424
+ CCGL_DEBUG_POP_GROUP_MARKER ();
425
+ CC_CHECK_GL_ERROR_DEBUG ();
426
+ }
427
+ });
428
+
429
+ _antialiased = antialiased;
430
+ }
399
431
}
400
432
401
433
@end
@@ -682,32 +714,77 @@ +(void) PVRImagesHavePremultipliedAlpha:(BOOL)haveAlphaPremultiplied
682
714
#pragma mark -
683
715
#pragma mark CCTexture2D - GLFilter
684
716
685
- #warning Not implemented for Metal.
686
-
687
717
//
688
718
// Use to apply MIN/MAG filter
689
719
//
690
720
@implementation CCTexture (GLFilter)
691
721
692
722
-(void ) generateMipmap
693
723
{
694
- CCRenderDispatch (NO , ^{
695
- CCGL_DEBUG_PUSH_GROUP_MARKER (" CCTexture: Generate Mipmap" );
696
-
697
- NSAssert ( _width == CCNextPOT(_width) && _height == CCNextPOT(_height), @"Mimpap texture only works in POT textures");
698
- glBindTexture (GL_TEXTURE_2D, _name);
699
- glGenerateMipmap (GL_TEXTURE_2D);
700
- _hasMipmaps = YES ;
701
-
702
- CCGL_DEBUG_POP_GROUP_MARKER ();
703
- });
724
+ if (!_hasMipmaps){
725
+ CCRenderDispatch (NO , ^{
726
+ #if __CC_METAL_SUPPORTED_AND_ENABLED
727
+ if ([CCConfiguration sharedConfiguration ].graphicsAPI == CCGraphicsAPIMetal){
728
+ CCMetalContext *context = [CCMetalContext currentContext ];
729
+
730
+ // Create a new blank texture.
731
+ MTLPixelFormat metalFormat = MetalPixelFormats[_format];
732
+ MTLTextureDescriptor *textureDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: metalFormat width: _width height: _height mipmapped: YES ];
733
+ id <MTLTexture > newTexture = [context.device newTextureWithDescriptor: textureDesc];
734
+
735
+ // Set up a command buffer for the blit operations.
736
+ id <MTLCommandBuffer > blitCommands = [context.commandQueue commandBuffer ];
737
+ id <MTLBlitCommandEncoder > blitter = [blitCommands blitCommandEncoder ];
738
+
739
+ // Copy in level 0.
740
+ MTLOrigin origin = MTLOriginMake (0 , 0 , 0 );
741
+ MTLSize size = MTLSizeMake (_width, _height, 1 );
742
+ [blitter
743
+ copyFromTexture: _metalTexture sourceSlice: 0 sourceLevel: 0 sourceOrigin: origin sourceSize: size
744
+ toTexture: newTexture destinationSlice: 0 destinationLevel: 0 destinationOrigin: origin
745
+ ];
746
+
747
+ // Generate mipmaps and commit.
748
+ [blitter generateMipmapsForTexture: newTexture];
749
+ [blitter endEncoding ];
750
+ [blitCommands commit ];
751
+
752
+ // Update sampler and texture.
753
+ MTLSamplerDescriptor *samplerDesc = [MTLSamplerDescriptor new ];
754
+ samplerDesc.minFilter = samplerDesc.magFilter = (_antialiased ? MTLSamplerMinMagFilterLinear : MTLSamplerMinMagFilterNearest );
755
+ samplerDesc.mipFilter = MTLSamplerMipFilterNearest ; // TODO trillinear?
756
+ samplerDesc.sAddressMode = MTLSamplerAddressModeClampToEdge ;
757
+ samplerDesc.tAddressMode = MTLSamplerAddressModeClampToEdge ;
758
+
759
+ _metalSampler = [context.device newSamplerStateWithDescriptor: samplerDesc];
760
+ NSLog (@" Generate mipmaps. Replacing %p with %p ." , _metalTexture, newTexture);
761
+ _metalTexture = newTexture;
762
+ } else
763
+ #endif
764
+ {
765
+ CCGL_DEBUG_PUSH_GROUP_MARKER (" CCTexture: Generate Mipmap" );
766
+
767
+ NSAssert ( _width == CCNextPOT(_width) && _height == CCNextPOT(_height), @"Mimpap texture only works in POT textures");
768
+ glBindTexture (GL_TEXTURE_2D, _name);
769
+ glGenerateMipmap (GL_TEXTURE_2D);
770
+
771
+ // Update the minification filter.
772
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _antialiased ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_NEAREST);
773
+
774
+ CCGL_DEBUG_POP_GROUP_MARKER ();
775
+ }
776
+ });
777
+ }
778
+
779
+ _hasMipmaps = YES ;
704
780
}
705
781
706
782
-(void ) setTexParameters : (ccTexParams*) texParams
707
783
{
708
784
CCRenderDispatch (NO , ^{
709
785
CCGL_DEBUG_PUSH_GROUP_MARKER (" CCTexture: Set Texture Parameters" );
710
786
787
+ NSAssert ([CCConfiguration sharedConfiguration ].graphicsAPI == CCGraphicsAPIGL, @" Not implemented for Metal." );
711
788
NSAssert ( (_width == CCNextPOT(_width) && _height == CCNextPOT(_height)) ||
712
789
(texParams->wrapS == GL_CLAMP_TO_EDGE && texParams->wrapT == GL_CLAMP_TO_EDGE),
713
790
@"GL_CLAMP_TO_EDGE should be used in NPOT dimensions");
@@ -723,47 +800,6 @@ -(void) setTexParameters: (ccTexParams*) texParams
723
800
});
724
801
}
725
802
726
- -(void ) setAliasTexParameters
727
- {
728
- CCRenderDispatch (NO , ^{
729
- CCGL_DEBUG_PUSH_GROUP_MARKER (" CCTexture: Set Alias Texture Parameters" );
730
-
731
- glBindTexture (GL_TEXTURE_2D, _name );
732
-
733
- if ( ! _hasMipmaps ){
734
- glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
735
- } else {
736
- glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST );
737
- }
738
-
739
- glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
740
- CCGL_DEBUG_POP_GROUP_MARKER ();
741
- CC_CHECK_GL_ERROR_DEBUG ();
742
- });
743
-
744
- _antialiased = NO ;
745
- }
746
-
747
- -(void ) setAntiAliasTexParameters
748
- {
749
- CCRenderDispatch (NO , ^{
750
- CCGL_DEBUG_PUSH_GROUP_MARKER (" CCTexture: Set Anti-alias Texture Parameters" );
751
-
752
- glBindTexture (GL_TEXTURE_2D, _name );
753
-
754
- if ( ! _hasMipmaps )
755
- glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
756
- else
757
- glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
758
-
759
- glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
760
-
761
- CCGL_DEBUG_POP_GROUP_MARKER ();
762
- CC_CHECK_GL_ERROR_DEBUG ();
763
- });
764
-
765
- _antialiased = YES ;
766
- }
767
803
@end
768
804
769
805
0 commit comments