@@ -89,7 +89,22 @@ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
8989#import " CCSpriteFrame.h"
9090
9191#if __CC_METAL_SUPPORTED_AND_ENABLED
92+
9293#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+
93108#endif
94109
95110
@@ -213,43 +228,30 @@ + (id) textureWithFile:(NSString*)file
213228- (id ) initWithData : (const void *)data pixelFormat : (CCTexturePixelFormat)pixelFormat pixelsWide : (NSUInteger )width pixelsHigh : (NSUInteger )height contentSizeInPixels : (CGSize)sizeInPixels contentScale : (CGFloat)contentScale
214229{
215230 if ((self = [super init ])) {
216- CCRenderDispatch (NO , ^{
217231#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
251253#endif
252- {
254+ CCRenderDispatch ( NO , ^ {
253255 CCGL_DEBUG_PUSH_GROUP_MARKER (" CCTexture: Init" );
254256
255257 // 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
296298 }
297299
298300 CCGL_DEBUG_POP_GROUP_MARKER ();
299- }
300301 });
301302
302303 _sizeInPixels = sizeInPixels;
@@ -393,9 +394,40 @@ -(CCSpriteFrame*) createSpriteFrame
393394
394395- (void ) setAntialiased : (BOOL )antialiased
395396{
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+ }
399431}
400432
401433@end
@@ -682,32 +714,77 @@ +(void) PVRImagesHavePremultipliedAlpha:(BOOL)haveAlphaPremultiplied
682714#pragma mark -
683715#pragma mark CCTexture2D - GLFilter
684716
685- #warning Not implemented for Metal.
686-
687717//
688718// Use to apply MIN/MAG filter
689719//
690720@implementation CCTexture (GLFilter)
691721
692722-(void ) generateMipmap
693723{
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 ;
704780}
705781
706782-(void ) setTexParameters : (ccTexParams*) texParams
707783{
708784 CCRenderDispatch (NO , ^{
709785 CCGL_DEBUG_PUSH_GROUP_MARKER (" CCTexture: Set Texture Parameters" );
710786
787+ NSAssert ([CCConfiguration sharedConfiguration ].graphicsAPI == CCGraphicsAPIGL, @" Not implemented for Metal." );
711788 NSAssert ( (_width == CCNextPOT(_width) && _height == CCNextPOT(_height)) ||
712789 (texParams->wrapS == GL_CLAMP_TO_EDGE && texParams->wrapT == GL_CLAMP_TO_EDGE),
713790 @"GL_CLAMP_TO_EDGE should be used in NPOT dimensions");
@@ -723,47 +800,6 @@ -(void) setTexParameters: (ccTexParams*) texParams
723800 });
724801}
725802
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- }
767803@end
768804
769805
0 commit comments