Commit 47708c26 authored by Ken Thomases's avatar Ken Thomases Committed by Alexandre Julliard

winemac: Add a new registry setting, OpenGLSurfaceMode, to control how GL…

winemac: Add a new registry setting, OpenGLSurfaceMode, to control how GL surfaces relate to the window. The default behavior is that GL surfaces are on top of all non-GL content in the window. This maximizes the performance for the common case of games, but clipping by parents, siblings, and child windows isn't respected. Setting OpenGLSurfaceMode to "behind" pushes the GL surface to be behind the Mac window. The window has transparent holes punched through it so that the GL surface shows through. USER32 and the wineserver take care of making sure the holes are only where the GL windows would be unclipped and unoccluded. Because the OS X window server has to composite the GL surface with the window, this limits the framerate. Since the Mac driver has no server-side rendering path, GDI rendering to a window which has a GL surface doesn't work. As a partial workaround, mostly for cases where a GL surface is created but never used, setting OpenGLSurfaceMode to "transparent" allows the GDI rendering to show through the transparent parts of the GL surface. The GDI rendering is drawn to the top-level window's surface as normal. (The behavior of user32 to exclude the portion covered by a GL window from GDI rendering is disabled.) The GL surface is in front of the window but potentially wholly or partially transparent. It is composited with the window behind it. The GL surface is initially cleared to be completely transparent. So, if no GL rendering is done, the window will appear as though the GL surface didn't exist.
parent 7e7b4de4
...@@ -109,7 +109,7 @@ ...@@ -109,7 +109,7 @@
glDrawBuffer(GL_FRONT_AND_BACK); glDrawBuffer(GL_FRONT_AND_BACK);
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glClearColor(0, 0, 0, 1); glClearColor(0, 0, 0, gl_surface_mode == GL_SURFACE_IN_FRONT_TRANSPARENT ? 0 : 1);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
......
...@@ -198,6 +198,7 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif ...@@ -198,6 +198,7 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
@property (readonly, copy, nonatomic) NSArray* childWineWindows; @property (readonly, copy, nonatomic) NSArray* childWineWindows;
- (void) updateColorSpace; - (void) updateColorSpace;
- (void) updateForGLSubviews;
- (BOOL) becameEligibleParentOrChild; - (BOOL) becameEligibleParentOrChild;
- (void) becameIneligibleChild; - (void) becameIneligibleChild;
...@@ -334,14 +335,14 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif ...@@ -334,14 +335,14 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
} }
[(WineWindow*)[self window] updateColorSpace]; [(WineWindow*)[self window] updateForGLSubviews];
} }
- (void) removeGLContext:(WineOpenGLContext*)context - (void) removeGLContext:(WineOpenGLContext*)context
{ {
[glContexts removeObjectIdenticalTo:context]; [glContexts removeObjectIdenticalTo:context];
[pendingGlContexts removeObjectIdenticalTo:context]; [pendingGlContexts removeObjectIdenticalTo:context];
[(WineWindow*)[self window] updateColorSpace]; [(WineWindow*)[self window] updateForGLSubviews];
} }
- (void) updateGLContexts - (void) updateGLContexts
...@@ -1402,7 +1403,8 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif ...@@ -1402,7 +1403,8 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
- (BOOL) needsTransparency - (BOOL) needsTransparency
{ {
return self.shape || self.colorKeyed || self.usePerPixelAlpha; return self.shape || self.colorKeyed || self.usePerPixelAlpha ||
(gl_surface_mode == GL_SURFACE_BEHIND && [[self.contentView valueForKeyPath:@"subviews.@max.hasGLContext"] boolValue]);
} }
- (void) checkTransparency - (void) checkTransparency
...@@ -1775,6 +1777,13 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif ...@@ -1775,6 +1777,13 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
[self setColorSpace:[NSColorSpace genericRGBColorSpace]]; [self setColorSpace:[NSColorSpace genericRGBColorSpace]];
} }
- (void) updateForGLSubviews
{
[self updateColorSpace];
if (gl_surface_mode == GL_SURFACE_BEHIND)
[self checkTransparency];
}
/* /*
* ---------- NSResponder method overrides ---------- * ---------- NSResponder method overrides ----------
...@@ -2683,7 +2692,7 @@ macdrv_view macdrv_create_view(macdrv_window w, CGRect rect) ...@@ -2683,7 +2692,7 @@ macdrv_view macdrv_create_view(macdrv_window w, CGRect rect)
name:NSApplicationDidChangeScreenParametersNotification name:NSApplicationDidChangeScreenParametersNotification
object:NSApp]; object:NSApp];
[[window contentView] addSubview:view]; [[window contentView] addSubview:view];
[window updateColorSpace]; [window updateForGLSubviews];
}); });
[pool release]; [pool release];
...@@ -2712,7 +2721,7 @@ void macdrv_dispose_view(macdrv_view v) ...@@ -2712,7 +2721,7 @@ void macdrv_dispose_view(macdrv_view v)
object:NSApp]; object:NSApp];
[view removeFromSuperview]; [view removeFromSuperview];
[view release]; [view release];
[window updateColorSpace]; [window updateForGLSubviews];
}); });
[pool release]; [pool release];
...@@ -2737,15 +2746,15 @@ void macdrv_set_view_window_and_frame(macdrv_view v, macdrv_window w, CGRect rec ...@@ -2737,15 +2746,15 @@ void macdrv_set_view_window_and_frame(macdrv_view v, macdrv_window w, CGRect rec
BOOL changedWindow = (window && window != [view window]); BOOL changedWindow = (window && window != [view window]);
NSRect newFrame = NSRectFromCGRect(rect); NSRect newFrame = NSRectFromCGRect(rect);
NSRect oldFrame = [view frame]; NSRect oldFrame = [view frame];
BOOL needUpdateWindowColorSpace = FALSE; BOOL needUpdateWindowForGLSubviews = FALSE;
if (changedWindow) if (changedWindow)
{ {
WineWindow* oldWindow = (WineWindow*)[view window]; WineWindow* oldWindow = (WineWindow*)[view window];
[view removeFromSuperview]; [view removeFromSuperview];
[oldWindow updateColorSpace]; [oldWindow updateForGLSubviews];
[[window contentView] addSubview:view]; [[window contentView] addSubview:view];
needUpdateWindowColorSpace = TRUE; needUpdateWindowForGLSubviews = TRUE;
} }
if (!NSEqualRects(oldFrame, newFrame)) if (!NSEqualRects(oldFrame, newFrame))
...@@ -2759,11 +2768,11 @@ void macdrv_set_view_window_and_frame(macdrv_view v, macdrv_window w, CGRect rec ...@@ -2759,11 +2768,11 @@ void macdrv_set_view_window_and_frame(macdrv_view v, macdrv_window w, CGRect rec
else else
[view setFrame:newFrame]; [view setFrame:newFrame];
[view setNeedsDisplay:YES]; [view setNeedsDisplay:YES];
needUpdateWindowColorSpace = TRUE; needUpdateWindowForGLSubviews = TRUE;
} }
if (needUpdateWindowColorSpace) if (needUpdateWindowForGLSubviews)
[(WineWindow*)[view window] updateColorSpace]; [(WineWindow*)[view window] updateForGLSubviews];
}); });
[pool release]; [pool release];
......
...@@ -118,6 +118,12 @@ enum { ...@@ -118,6 +118,12 @@ enum {
}; };
enum { enum {
GL_SURFACE_IN_FRONT_OPAQUE,
GL_SURFACE_IN_FRONT_TRANSPARENT,
GL_SURFACE_BEHIND,
};
enum {
MACDRV_HOTKEY_SUCCESS, MACDRV_HOTKEY_SUCCESS,
MACDRV_HOTKEY_ALREADY_REGISTERED, MACDRV_HOTKEY_ALREADY_REGISTERED,
MACDRV_HOTKEY_FAILURE, MACDRV_HOTKEY_FAILURE,
...@@ -149,6 +155,7 @@ extern int right_option_is_alt DECLSPEC_HIDDEN; ...@@ -149,6 +155,7 @@ extern int right_option_is_alt DECLSPEC_HIDDEN;
extern int allow_immovable_windows DECLSPEC_HIDDEN; extern int allow_immovable_windows DECLSPEC_HIDDEN;
extern int cursor_clipping_locks_windows DECLSPEC_HIDDEN; extern int cursor_clipping_locks_windows DECLSPEC_HIDDEN;
extern int use_precise_scrolling DECLSPEC_HIDDEN; extern int use_precise_scrolling DECLSPEC_HIDDEN;
extern int gl_surface_mode DECLSPEC_HIDDEN;
extern int macdrv_start_cocoa_app(unsigned long long tickcount) DECLSPEC_HIDDEN; extern int macdrv_start_cocoa_app(unsigned long long tickcount) DECLSPEC_HIDDEN;
extern void macdrv_window_rejected_focus(const struct macdrv_event *event) DECLSPEC_HIDDEN; extern void macdrv_window_rejected_focus(const struct macdrv_event *event) DECLSPEC_HIDDEN;
......
...@@ -57,6 +57,7 @@ BOOL disable_window_decorations = FALSE; ...@@ -57,6 +57,7 @@ BOOL disable_window_decorations = FALSE;
int allow_immovable_windows = TRUE; int allow_immovable_windows = TRUE;
int cursor_clipping_locks_windows = TRUE; int cursor_clipping_locks_windows = TRUE;
int use_precise_scrolling = TRUE; int use_precise_scrolling = TRUE;
int gl_surface_mode = GL_SURFACE_IN_FRONT_OPAQUE;
HMODULE macdrv_module = 0; HMODULE macdrv_module = 0;
...@@ -183,6 +184,16 @@ static void setup_options(void) ...@@ -183,6 +184,16 @@ static void setup_options(void)
if (!get_config_key(hkey, appkey, "UsePreciseScrolling", buffer, sizeof(buffer))) if (!get_config_key(hkey, appkey, "UsePreciseScrolling", buffer, sizeof(buffer)))
use_precise_scrolling = IS_OPTION_TRUE(buffer[0]); use_precise_scrolling = IS_OPTION_TRUE(buffer[0]);
if (!get_config_key(hkey, appkey, "OpenGLSurfaceMode", buffer, sizeof(buffer)))
{
if (!strcmp(buffer, "transparent"))
gl_surface_mode = GL_SURFACE_IN_FRONT_TRANSPARENT;
else if (!strcmp(buffer, "behind"))
gl_surface_mode = GL_SURFACE_BEHIND;
else
gl_surface_mode = GL_SURFACE_IN_FRONT_OPAQUE;
}
if (appkey) RegCloseKey(appkey); if (appkey) RegCloseKey(appkey);
if (hkey) RegCloseKey(hkey); if (hkey) RegCloseKey(hkey);
} }
......
...@@ -1480,6 +1480,21 @@ static BOOL create_context(struct wgl_context *context, CGLContextObj share, uns ...@@ -1480,6 +1480,21 @@ static BOOL create_context(struct wgl_context *context, CGLContextObj share, uns
return FALSE; return FALSE;
} }
if (gl_surface_mode == GL_SURFACE_IN_FRONT_TRANSPARENT)
{
GLint opacity = 0;
err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOpacity, &opacity);
if (err != kCGLNoError)
WARN("CGLSetParameter(kCGLCPSurfaceOpacity) failed with error %d %s; leaving opaque\n", err, CGLErrorString(err));
}
else if (gl_surface_mode == GL_SURFACE_BEHIND)
{
GLint order = -1;
err = CGLSetParameter(context->cglcontext, kCGLCPSurfaceOrder, &order);
if (err != kCGLNoError)
WARN("CGLSetParameter(kCGLCPSurfaceOrder) failed with error %d %s; leaving in front\n", err, CGLErrorString(err));
}
context->context = macdrv_create_opengl_context(context->cglcontext); context->context = macdrv_create_opengl_context(context->cglcontext);
CGLReleaseContext(context->cglcontext); CGLReleaseContext(context->cglcontext);
if (!context->context) if (!context->context)
...@@ -1638,7 +1653,7 @@ static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset) ...@@ -1638,7 +1653,7 @@ static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset)
done: done:
release_win_data(data); release_win_data(data);
if (ret) __wine_set_pixel_format(hwnd, fmt); if (ret && gl_surface_mode == GL_SURFACE_BEHIND) __wine_set_pixel_format(hwnd, fmt);
return ret; return ret;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment