/
MTLPTexture+CGImage.m
81 lines (56 loc) · 2.04 KB
/
MTLPTexture+CGImage.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#import "MTLPTexture+CGImage.h"
@implementation NSObject (MTLPTextureCGImage)
- (BOOL)replaceMetalTextureWithCGImage:(CGImageRef)image mipmapLevel:(NSUInteger)mipmapLevel slice:(NSUInteger)slice
{
id<MTLTexture> texture = (id<MTLTexture>)self;
if(![texture conformsToProtocol:@protocol(MTLTexture)])
{
return NO;
}
if(image == NULL)
{
return NO;
}
const size_t width = CGImageGetWidth(image);
const size_t height = CGImageGetHeight(image);
const size_t components = CGImageGetBitsPerPixel(image) / CGImageGetBitsPerComponent(image);
size_t bytesPerRow = 0;
size_t bytesPerImage = 0;
MTLPixelFormat pixelFormat = MTLPixelFormatInvalid;
CGContextRef context = NULL;
switch(components) {
case 1 :
{
pixelFormat = MTLPixelFormatR8Unorm;
bytesPerRow = width;
bytesPerImage = width * height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
context = CGBitmapContextCreate(NULL, width, height, 8, width, colorSpace, (CGBitmapInfo)kCGImageAlphaNone);
CGColorSpaceRelease(colorSpace);
break;
}
case 4 :
{
pixelFormat = MTLPixelFormatRGBA8Unorm;
bytesPerRow = width * 4;
bytesPerImage = width * height * 4;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
context = CGBitmapContextCreate(NULL, width, height, 8, width * 4, colorSpace, (CGBitmapInfo)kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
break;
}
default :
NSLog(@"Unable to assign texture");
return NO;
}
CGRect rect = CGRectMake(0, 0, width, height);
CGContextClearRect(context, rect);
CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, height));
CGContextDrawImage(context, rect, image);
void * const data = CGBitmapContextGetData(context);
MTLRegion region = MTLRegionMake2D(0, 0, (NSUInteger)width, (NSUInteger)height);
[texture replaceRegion:region mipmapLevel:mipmapLevel slice:slice withBytes:data bytesPerRow:bytesPerRow bytesPerImage:bytesPerImage];
CGContextRelease(context), context = NULL;
return YES;
}
@end