Reduce screen corruption when resizing

This commit clears framebuffers when they are created, copies the contents of
the previous framebuffer to the new framebuffer when resizing and moves all the
resizing code into the blit method. All of these help to reduce screen
corruption, although a small amount still remains if you resize quickly.
master
Graham 5 years ago
parent 5f22187451
commit 74516baaa6
  1. 108
      gl-natives/src/main/c/jaggl.c

@ -226,42 +226,72 @@ static void *jaggl_proc_addr(const char *name) {
[super dealloc]; [super dealloc];
} }
- (void)genFramebuffer { - (void)blit {
framebuffer_width = (GLint) self.bounds.size.width; [lock lock];
framebuffer_height = (GLint) self.bounds.size.height;
glGenFramebuffersEXT(1, &framebuffer); /* get current size */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer); NSSize size = self.bounds.size;
GLint width = (GLint) size.width;
GLint height = (GLint) size.height;
glGenRenderbuffersEXT(1, &renderbuffer_color); /* check if we need to resize the framebuffer/off-screen window */
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer_color); bool resized = width != framebuffer_width || height != framebuffer_height;
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, framebuffer_width, framebuffer_height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, renderbuffer_color);
glGenRenderbuffersEXT(1, &renderbuffer_depth); if (!framebuffer || resized) {
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer_depth); /* create new framebuffer */
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, framebuffer_width, framebuffer_height); GLuint new_framebuffer, new_renderbuffer_color, new_renderbuffer_depth;
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderbuffer_depth);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glGenFramebuffersEXT(1, &new_framebuffer);
} glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, new_framebuffer);
- (void)deleteFramebuffer { glGenRenderbuffersEXT(1, &new_renderbuffer_color);
glDeleteRenderbuffersEXT(1, &renderbuffer_depth); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, new_renderbuffer_color);
glDeleteRenderbuffersEXT(1, &renderbuffer_color); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, width, height);
glDeleteFramebuffersEXT(1, &framebuffer); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, new_renderbuffer_color);
}
- (void)blit { glGenRenderbuffersEXT(1, &new_renderbuffer_depth);
[lock lock]; glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, new_renderbuffer_depth);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, new_renderbuffer_depth);
if (!framebuffer) { /* clear the framebuffer */
return; glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* copy the old framebuffer to the new framebuffer */
if (framebuffer) {
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, new_framebuffer);
glBlitFramebufferEXT(0, 0, framebuffer_width, framebuffer_height, 0, 0, framebuffer_width, framebuffer_height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
/* delete the old framebuffer */
if (framebuffer) {
glDeleteRenderbuffersEXT(1, &renderbuffer_depth);
glDeleteRenderbuffersEXT(1, &renderbuffer_color);
glDeleteFramebuffersEXT(1, &framebuffer);
}
/* update framebuffer_* vars */
framebuffer = new_framebuffer;
renderbuffer_color = new_renderbuffer_color;
renderbuffer_depth = new_renderbuffer_depth;
framebuffer_width = width;
framebuffer_height = height;
} }
/* bind the existing framebuffer */
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer);
/* clear the framebuffer */
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* copy current off-screen contents to the framebuffer */
glBlitFramebufferEXT(0, 0, framebuffer_width, framebuffer_height, 0, 0, framebuffer_width, framebuffer_height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); glBlitFramebufferEXT(0, 0, framebuffer_width, framebuffer_height, 0, 0, framebuffer_width, framebuffer_height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
@ -270,6 +300,12 @@ static void *jaggl_proc_addr(const char *name) {
dispatch_sync(dispatch_get_main_queue(), ^{ dispatch_sync(dispatch_get_main_queue(), ^{
[self setNeedsDisplay]; [self setNeedsDisplay];
if (resized) {
jaggl_view.frame = NSMakeRect(0, 0, width, height);
[jaggl_window setFrame:[jaggl_window frameRectForContentRect:jaggl_view.frame] display:YES];
[jaggl_context_appkit update];
}
}); });
} }
@ -286,25 +322,17 @@ static void *jaggl_proc_addr(const char *name) {
displayTime:(const CVTimeStamp *)displayTime { displayTime:(const CVTimeStamp *)displayTime {
CGLSetCurrentContext(context); CGLSetCurrentContext(context);
GLint width = (GLint) self.bounds.size.width;
GLint height = (GLint) self.bounds.size.height;
[lock lock]; [lock lock];
/* TODO(gpe): improve resize support (fix corruption, do we need to resize the NSView/NSWindow?) */ glClearColor(0, 0, 0, 1);
if (width != framebuffer_width || height != framebuffer_height) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[self deleteFramebuffer];
[self genFramebuffer];
jaggl_view.frame = NSMakeRect(0, 0, width, height); if (framebuffer) {
[jaggl_window setFrame:[jaggl_window frameRectForContentRect:jaggl_view.frame] display:YES]; glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer);
[jaggl_context_appkit update]; glBlitFramebufferEXT(0, 0, framebuffer_width, framebuffer_height, 0, 0, framebuffer_width, framebuffer_height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
} }
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer);
glBlitFramebufferEXT(0, 0, framebuffer_width, framebuffer_height, 0, 0, framebuffer_width, framebuffer_height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
[lock unlock]; [lock unlock];
[super drawInCGLContext:context pixelFormat:pixelFormat forLayerTime:layerTime displayTime:displayTime]; [super drawInCGLContext:context pixelFormat:pixelFormat forLayerTime:layerTime displayTime:displayTime];
@ -319,10 +347,6 @@ static void *jaggl_proc_addr(const char *name) {
} }
- (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pix { - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pix {
CGLSetCurrentContext(jaggl_onscreen_context);
[lock lock];
[self genFramebuffer];
[lock unlock];
return jaggl_onscreen_context; return jaggl_onscreen_context;
} }

Loading…
Cancel
Save