Point the layer compositor's GL context at the window's back buffer

Second half of the NVIDIA black screen (#3). With the visual fix the
compositor gets a window surface and drawables recycle, but the window
stays black: after CARenderer draws, the back buffer reads back black and
even a glClear to blue changes nothing. GL_DRAW_BUFFER and GL_READ_BUFFER
are GL_NONE.

CALayerContext -setSubwindow: creates the context and then notifies the
layer tree; CAMetalLayer -_setContext: makes the context current (to
create its textures) before any window surface is attached. Per
EGL_KHR_surfaceless_context, a context first made current without a
default framebuffer starts with DRAW_BUFFER = NONE, and attaching a
window later doesn't change it. NVIDIA follows that; Mesa resets it on
bind, which is why AMD works.

After CGLContextMakeCurrentAndAttachToWindow in -renderLayer:, set the
draw and read buffers to GL_BACK.
This commit is contained in:
Polar committed 2026-10-17 00:14:31 +00:00
1 parent 0d78eaf0ff
commit f230dd8b9e
1 file changed
+10 -5
+10 -5
View File
@@ -8723,7 +8723,7 @@ index 5dcac115..5de4f03f 100644
+
@end
diff --git a/QuartzCore/CALayerContext.m b/QuartzCore/CALayerContext.m
index 5dce8c56..dee2b80c 100644
index 5dce8c56..d76cdae4 100644
--- a/QuartzCore/CALayerContext.m
+++ b/QuartzCore/CALayerContext.m
@@ -1,47 +1,58 @@
@@ -8879,7 +8879,7 @@ index 5dce8c56..dee2b80c 100644
}
- (void) assignTextureIdsToLayerTree: (CALayer *) layer {
@@ -93,7 +148,22 @@
@@ -93,8 +148,27 @@
[self assignTextureIdsToLayerTree: child];
}
@@ -8900,9 +8900,14 @@ index 5dce8c56..dee2b80c 100644
- (void) renderLayer: (CALayer *) layer {
+ CFTimeInterval renderLayerStart = CACurrentMediaTime();
CGLContextMakeCurrentAndAttachToWindow(_glContext, _cglWindow);
+ // CAMetalLayer first makes this context current without a surface, which leaves GL_DRAW_BUFFER
+ // at GL_NONE on NVIDIA even once the window is attached (Mesa resets it).
+ glDrawBuffer(GL_BACK);
+ glReadBuffer(GL_BACK);
glEnable(GL_DEPTH_TEST);
@@ -118,27 +188,63 @@
glShadeModel(GL_SMOOTH);
@@ -118,27 +192,63 @@
[_deleteTextureIds removeAllObjects];
@@ -8971,7 +8976,7 @@ index 5dce8c56..dee2b80c 100644
}
- (void) startTimerIfNeeded {
@@ -147,7 +253,7 @@
@@ -147,7 +257,7 @@
target: self
selector: @selector(timer:)
userInfo: nil
@@ -8980,7 +8985,7 @@ index 5dce8c56..dee2b80c 100644
}
- (void) deleteTextureId: (NSNumber *) textureId {
@@ -155,7 +261,10 @@
@@ -155,7 +265,10 @@
}
- (void) flush {