Skip to content

Commit 964d263

Browse files
committed
[[ Bug 21396 ]] Fix crash on startup in iOS 12 beta
This patch fixes an issue where the view layer appears to be retaining the `CGDataProvider` from an image when it is drawn via `CGContextDrawImage`. As we were freeing the raster directly after the draw the `CALayer` could not access it from the `CGDataProvider` when rendering causing a crash. This patch therefore changes the behavior of `MCGRasterCreateCGDataProvider` where previously when calling it with the copy parameter `false` it would be left to the caller to free the buffer the data provider now takes ownership of it and it is freed via the data provider free callback. As a consequence of the change custom cursor creation on mac now copies the buffer for simplicity.
1 parent 720de35 commit 964d263

5 files changed

Lines changed: 20 additions & 10 deletions

File tree

docs/notes/bugfix-21396.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Fix crash on startup in iOS 12 beta

engine/src/cgimageutil.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ bool MCGRasterCreateCGDataProvider(const MCGRaster &p_raster, const MCGIntegerRe
114114
t_width = p_src_rect.size.width;
115115
t_height = p_src_rect.size.height;
116116

117-
const uint8_t *t_src_ptr = (uint8_t*)MCGRasterGetPixelPtr(p_raster, t_x, t_y);
117+
uint8_t *t_src_ptr = (uint8_t*)MCGRasterGetPixelPtr(p_raster, t_x, t_y);
118118

119119
uint32_t t_dst_stride;
120120

@@ -125,8 +125,10 @@ bool MCGRasterCreateCGDataProvider(const MCGRaster &p_raster, const MCGIntegerRe
125125
if (!p_copy)
126126
{
127127
t_dst_stride = p_raster.stride;
128-
t_data_provider = CGDataProviderCreateWithData(nil, t_src_ptr, t_height * p_raster.stride, nil);
128+
t_data_provider = CGDataProviderCreateWithData(nil, t_src_ptr, t_height * p_raster.stride, __CGDataProviderDeallocate);
129129
t_success = t_data_provider != nil;
130+
if (!t_success)
131+
MCMemoryDeallocate(t_src_ptr);
130132
}
131133
else
132134
{

engine/src/mac-cursor.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ void MCPlatformCreateCustomCursor(MCImageBitmap *p_image, MCPoint p_hotspot, MCP
137137
t_cursor -> is_standard = false;
138138

139139
CGImageRef t_cg_image;
140-
/* UNCHECKED */ MCImageBitmapToCGImage(p_image, false, false, t_cg_image);
140+
/* UNCHECKED */ MCImageBitmapToCGImage(p_image, true, false, t_cg_image);
141141

142142
// Convert the CGImage into an NSIMage
143143
NSImage *t_cursor_image;

engine/src/mac-surface.mm

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,6 @@ CGRect MCMacFlipCGRect(const CGRect &p_rect, uint32_t p_surface_height)
317317
// IM-2014-10-03: [[ Bug 13432 ]] Render with copy blend mode to replace destination alpha with the source alpha.
318318
MCMacRenderRasterToCG(m_cg_context, t_dst_rect, m_raster, MCGRectangleMake(0, 0, m_raster.width, m_raster.height), 1.0, kMCGBlendModeCopy);
319319

320-
free(m_raster . pixels);
321320
m_raster . pixels = nil;
322321
}
323322

engine/src/mbliphonegfx.mm

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ static void do_update(void *p_dirty)
102102
MCGRegionRef m_region;
103103
bool m_own_region;
104104

105-
virtual void FlushBits(MCGIntegerRectangle p_area, void *p_bits, uint32_t p_stride) = 0;
105+
virtual void FlushBits(MCGIntegerRectangle p_area, void *p_bits, uint32_t p_stride, bool &x_taken) = 0;
106106

107107
public:
108108
MCIPhoneStackSurface(MCGRegionRef p_region)
@@ -197,10 +197,16 @@ void UnlockPixels(MCGIntegerRectangle p_area, MCGRaster& p_raster, bool p_update
197197
if (p_raster . pixels == nil)
198198
return;
199199

200+
bool t_taken = false;
201+
200202
if (p_update)
201-
FlushBits(p_area, p_raster . pixels, p_raster . stride);
203+
FlushBits(p_area, p_raster . pixels, p_raster . stride, t_taken);
204+
205+
if (!t_taken)
206+
{
207+
free(p_raster.pixels);
208+
}
202209

203-
free(p_raster . pixels);
204210
}
205211

206212
bool Composite(MCGRectangle p_dst_rect, MCGImageRef p_src, MCGRectangle p_src_rect, MCGFloat p_alpha, MCGBlendMode p_blend)
@@ -337,7 +343,7 @@ void UnlockTarget(void)
337343

338344
protected:
339345
// MM-2014-07-31: [[ ThreadedRendering ]] Updated to pass in the area we wish to draw.
340-
void FlushBits(MCGIntegerRectangle p_area, void *p_bits, uint32_t p_stride)
346+
void FlushBits(MCGIntegerRectangle p_area, void *p_bits, uint32_t p_stride, bool &x_taken)
341347
{
342348
void *t_target;
343349
if (!LockTarget(kMCStackSurfaceTargetCoreGraphics, t_target))
@@ -368,6 +374,8 @@ void FlushBits(MCGIntegerRectangle p_area, void *p_bits, uint32_t p_stride)
368374

369375
if (MCGRasterToCGImage(t_raster, MCGIntegerRectangleMake(0, 0, p_area.size.width, p_area.size.height), t_colorspace, false, false, t_image))
370376
{
377+
x_taken = true;
378+
371379
CGContextDrawImage(t_context, CGRectMake((float)p_area.origin.x, (float)(m_height - (p_area.origin.y + p_area.size.height)), (float)p_area.size.width, (float)p_area.size.height), t_image);
372380
CGImageRelease(t_image);
373381
}
@@ -521,7 +529,7 @@ void UnlockTarget(void)
521529

522530
protected:
523531
// MM-2014-07-31: [[ ThreadedRendering ]] Updated to pass in the area we wish to draw.
524-
void FlushBits(MCGIntegerRectangle p_area, void *p_bits, uint32_t p_stride)
532+
void FlushBits(MCGIntegerRectangle p_area, void *p_bits, uint32_t p_stride, bool& x_taken)
525533
{
526534
GLuint t_texture;
527535
glGenTextures(1, &t_texture);
@@ -582,7 +590,7 @@ void FlushBits(MCGIntegerRectangle p_area, void *p_bits, uint32_t p_stride)
582590
}
583591

584592
glDeleteTextures(1, &t_texture);
585-
}
593+
}
586594
};
587595

588596
@implementation MCIPhoneOpenGLDisplayView

0 commit comments

Comments
 (0)