macOS Fix potential memory leaks in the Metal renderer caught by clang's static analyzer.
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 82 83 84 85 86
diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m
index bdf7ed1..bf42468 100644
--- a/src/render/metal/SDL_render_metal.m
+++ b/src/render/metal/SDL_render_metal.m
@@ -173,6 +173,7 @@ typedef struct METAL_ShaderPipelines
[_mtltexture release];
[_mtltexture_uv release];
[_mtlsampler release];
+ [_lockedbuffer release];
[super dealloc];
}
#endif
@@ -831,6 +832,7 @@ METAL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
METAL_TextureData *texturedata = (__bridge METAL_TextureData *)texture->driverdata;
int buffersize = 0;
+ id<MTLBuffer> lockedbuffer = nil;
if (rect->w <= 0 || rect->h <= 0) {
return SDL_SetError("Invalid rectangle dimensions for LockTexture.");
@@ -844,13 +846,19 @@ METAL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
buffersize = (*pitch) * rect->h;
}
- texturedata.lockedrect = *rect;
- texturedata.lockedbuffer = [data.mtldevice newBufferWithLength:buffersize options:MTLResourceStorageModeShared];
- if (texturedata.lockedbuffer == nil) {
+ lockedbuffer = [data.mtldevice newBufferWithLength:buffersize options:MTLResourceStorageModeShared];
+ if (lockedbuffer == nil) {
return SDL_OutOfMemory();
}
- *pixels = [texturedata.lockedbuffer contents];
+ texturedata.lockedrect = *rect;
+ texturedata.lockedbuffer = lockedbuffer;
+ *pixels = [lockedbuffer contents];
+
+ /* METAL_TextureData.lockedbuffer retains. */
+#if !__has_feature(objc_arc)
+ [lockedbuffer release];
+#endif
return 0;
}}
@@ -934,11 +942,7 @@ METAL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
[data.mtlcmdbuffer commit];
data.mtlcmdbuffer = nil;
-#if !__has_feature(objc_arc)
- [texturedata.lockedbuffer release];
-#endif
-
- texturedata.lockedbuffer = nil;
+ texturedata.lockedbuffer = nil; /* Retained property, so it calls release. */
texturedata.hasdata = YES;
}}
@@ -1299,6 +1303,8 @@ METAL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
{ @autoreleasepool {
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
METAL_DrawStateCache statecache;
+ SDL_zero(statecache);
+
id<MTLBuffer> mtlbufvertex = nil;
statecache.pipeline = nil;
@@ -1586,6 +1592,9 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
view = SDL_Metal_CreateView(window);
if (view == NULL) {
+#if !__has_feature(objc_arc)
+ [mtldevice release];
+#endif
SDL_free(renderer);
return NULL;
}
@@ -1594,6 +1603,9 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
data = [[METAL_RenderData alloc] init];
if (data == nil) {
+#if !__has_feature(objc_arc)
+ [mtldevice release];
+#endif
SDL_Metal_DestroyView(view);
SDL_free(renderer);
return NULL;