Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions Ports/iOSPort/nativeSources/CodenameOne_GLViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -2540,7 +2540,7 @@ -(void)updateCanvas:(BOOL)animated {
// the display width/height each time to match the view, without performing other resizing
// details, so it is possible that the size change event still needs to be sent
// even if the display width already matches the value we're given here.
[[self eaglView] updateFrameBufferSize:(int)size.width h:(int)size.height];
[[self eaglView] updateFrameBufferSize:(int)(size.width * scaleValue) h:(int)(size.height * scaleValue)];
displayWidth = (int)size.width * scaleValue;
displayHeight = (int)size.height * scaleValue;
screenSizeChanged(displayWidth, displayHeight);
Expand Down Expand Up @@ -3282,9 +3282,14 @@ -(void) viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coor
}

// simply create a property of 'BOOL' type
[[self eaglView] updateFrameBufferSize:(int)size.width h:(int)size.height];
// Pass physical pixels: viewWillTransitionToSize: fires before UIKit
// updates the view's bounds, so on the Metal backend the EAGLView's
// bounds read would still return the previous orientation. The
// METALView resize logic trusts these parameters; the EAGLView
// implementation is a no-op (#4954).
[[self eaglView] updateFrameBufferSize:(int)(size.width * scaleValue) h:(int)(size.height * scaleValue)];
[[self eaglView] deleteFramebuffer];

displayWidth = (int)size.width * scaleValue;
displayHeight = (int)size.height * scaleValue;

Expand Down Expand Up @@ -3325,7 +3330,7 @@ -(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOr
return;
}

[[self eaglView] updateFrameBufferSize:(int)self.view.bounds.size.width h:(int)self.view.bounds.size.height];
[[self eaglView] updateFrameBufferSize:(int)(self.view.bounds.size.width * scaleValue) h:(int)(self.view.bounds.size.height * scaleValue)];
[[self eaglView] deleteFramebuffer];

displayWidth = (int)self.view.bounds.size.width * scaleValue;
Expand Down
32 changes: 22 additions & 10 deletions Ports/iOSPort/nativeSources/METALView.m
Original file line number Diff line number Diff line change
Expand Up @@ -228,16 +228,28 @@ - (void)deleteFramebuffer


-(void)updateFrameBufferSize:(int)w h:(int)h {
// Ignore the passed w/h -- CodenameOne_GLViewController.m calls this with
// logical points (self.view.bounds.size), but the Metal drawable and
// projection must be in physical pixels. The GL path tolerates the
// logical-point argument because EAGLView.updateFrameBufferSize: is a
// no-op (dimensions get read back from the renderbuffer after the layer
// is bound). For Metal we always compute from our own layer bounds.
CGSize sz = self.bounds.size;
CGFloat s = self.contentScaleFactor;
int pw = (int)(sz.width * s);
int ph = (int)(sz.height * s);
// Trust caller-supplied physical-pixel dimensions; fall back to bounds
// only if the caller passes 0. Reading self.bounds alone is unsafe
// during rotation: viewWillTransitionToSize: in CodenameOne_GLView-
// Controller fires BEFORE UIKit updates the view's bounds, so a
// bounds-derived size matches the cached (old) framebuffer dimensions
// and the early-return below would leave screenTexture, the projection
// matrix and stencil texture at the previous orientation. CAMetalLayer's
// drawableSize is auto-resized by UIKit on rotation, so the next
// drawFrame would blit the old-sized screenTexture into the new-sized
// drawable -- portrait content lands in a corner of the landscape
// drawable and the remaining pixels read back uninitialised, surfacing
// as the smeared/pink frames reported in #4954. The callers in this
// file (initWithCoder, layoutSubviews) and the GLViewController callers
// all pass physical pixels.
int pw = w;
int ph = h;
if (pw <= 0 || ph <= 0) {
CGSize sz = self.bounds.size;
CGFloat s = self.contentScaleFactor;
pw = (int)(sz.width * s);
ph = (int)(sz.height * s);
}
if (pw <= 0 || ph <= 0) return;
if (pw == framebufferWidth && ph == framebufferHeight) {
return;
Expand Down
Loading