[PATCH 2/3] winemac: Implement WineMetalView class

Andrew Eikum aeikum at codeweavers.com
Fri Jul 13 09:27:44 CDT 2018


From: Ken Thomases <ken at codeweavers.com>

Signed-off-by: Ken Thomases <ken at codeweavers.com>
Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
---

Note that this and the next patch need config.h.in to be re-generated,
I don't recall if I'm supposed to do that or not.

 configure.ac                    |   7 ++
 dlls/winemac.drv/Makefile.in    |   2 +-
 dlls/winemac.drv/cocoa_window.m | 141 ++++++++++++++++++++++++++++++++
 dlls/winemac.drv/macdrv_cocoa.h |  10 +++
 4 files changed, 159 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 1db5a407fa..9ba9a28cc3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -762,6 +762,9 @@ case $host_os in
 
   darwin*|macosx*)
     AC_CHECK_HEADERS(libunwind.h)
+    AC_LANG_PUSH([Objective C])
+        AC_CHECK_HEADERS(Metal/Metal.h)
+    AC_LANG_POP([Objective C])
     LIBEXT="dylib"
     DLLFLAGS="$DLLFLAGS -fPIC"
     LDRPATH_INSTALL="-Wl,-rpath, at loader_path/\`\$(MAKEDEP) -R \${bindir} \${libdir}\`"
@@ -846,6 +849,10 @@ case $host_os in
     then
         AC_SUBST(CARBON_LIBS,"-framework Carbon")
     fi
+    if test "$ac_cv_header_Metal_Metal_h" = "yes"
+    then
+        AC_SUBST(METAL_LIBS,"-framework Metal -framework QuartzCore")
+    fi
 
     dnl Enable Mac driver on Mac OS X 10.6 or later
     if test "$ac_cv_header_ApplicationServices_ApplicationServices_h" = "yes"
diff --git a/dlls/winemac.drv/Makefile.in b/dlls/winemac.drv/Makefile.in
index c160895c7d..33f4e2ee00 100644
--- a/dlls/winemac.drv/Makefile.in
+++ b/dlls/winemac.drv/Makefile.in
@@ -1,7 +1,7 @@
 MODULE    = winemac.drv
 IMPORTS   = uuid user32 gdi32 advapi32
 DELAYIMPORTS = ole32 shell32 imm32
-EXTRALIBS = -framework AppKit -framework Carbon -framework Security -framework OpenGL -framework IOKit -framework CoreVideo
+EXTRALIBS = -framework AppKit -framework Carbon -framework Security -framework OpenGL -framework IOKit -framework CoreVideo $(METAL_LIBS)
 
 C_SRCS = \
 	clipboard.c \
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m
index 1e10c27ce8..4c59faf1f4 100644
--- a/dlls/winemac.drv/cocoa_window.m
+++ b/dlls/winemac.drv/cocoa_window.m
@@ -18,8 +18,14 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
+
 #import <Carbon/Carbon.h>
 #import <CoreVideo/CoreVideo.h>
+#ifdef HAVE_METAL_METAL_H
+#import <Metal/Metal.h>
+#import <QuartzCore/QuartzCore.h>
+#endif
 
 #import "cocoa_window.h"
 
@@ -303,6 +309,18 @@ @interface WineBaseView : NSView
 @end
 
 
+#ifdef HAVE_METAL_METAL_H
+ at interface WineMetalView : WineBaseView
+{
+    id<MTLDevice> _device;
+}
+
+    - (id) initWithFrame:(NSRect)frame device:(id<MTLDevice>)device;
+
+ at end
+#endif
+
+
 @interface WineContentView : WineBaseView <NSTextInputClient>
 {
     NSMutableArray* glContexts;
@@ -316,6 +334,10 @@ @interface WineContentView : WineBaseView <NSTextInputClient>
     NSRange markedTextSelection;
 
     int backingSize[2];
+
+#ifdef HAVE_METAL_METAL_H
+    WineMetalView *_metalView;
+#endif
 }
 
 @property (readonly, nonatomic) BOOL everHadGLContext;
@@ -327,6 +349,10 @@ - (void) updateGLContexts;
     - (void) wine_getBackingSize:(int*)outBackingSize;
     - (void) wine_setBackingSize:(const int*)newBackingSize;
 
+#ifdef HAVE_METAL_METAL_H
+    - (WineMetalView*) newMetalViewWithDevice:(id<MTLDevice>)device;
+#endif
+
 @end
 
 
@@ -628,6 +654,23 @@ - (void) wine_setBackingSize:(const int*)newBackingSize
         }
     }
 
+#ifdef HAVE_METAL_METAL_H
+    - (WineMetalView*) newMetalViewWithDevice:(id<MTLDevice>)device
+    {
+        if (_metalView) return _metalView;
+
+        WineMetalView* view = [[WineMetalView alloc] initWithFrame:[self bounds] device:device];
+        [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+        [self setAutoresizesSubviews:YES];
+        [self addSubview:view positioned:NSWindowBelow relativeTo:nil];
+        _metalView = view;
+
+        [(WineWindow*)self.window windowDidDrawContent];
+
+        return _metalView;
+    }
+#endif
+
     - (void) setRetinaMode:(int)mode
     {
         double scale = mode ? 0.5 : 2.0;
@@ -693,6 +736,10 @@ - (void) willRemoveSubview:(NSView*)subview
             if (!view->_cachedHasGLDescendantValid || view->_cachedHasGLDescendant)
                 [self invalidateHasGLDescendant];
         }
+#ifdef HAVE_METAL_METAL_H
+        if (subview == _metalView)
+            _metalView = nil;
+#endif
         [super willRemoveSubview:subview];
     }
 
@@ -833,6 +880,53 @@ - (NSInteger) windowLevel
 @end
 
 
+#ifdef HAVE_METAL_METAL_H
+ at implementation WineMetalView
+
+    - (id) initWithFrame:(NSRect)frame device:(id<MTLDevice>)device
+    {
+        self = [super initWithFrame:frame];
+        if (self)
+        {
+            _device = [device retain];
+            self.wantsLayer = YES;
+            self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawNever;
+        }
+        return self;
+    }
+
+    - (void) dealloc
+    {
+        [_device release];
+        [super dealloc];
+    }
+
+    - (void) setRetinaMode:(int)mode
+    {
+        self.layer.contentsScale = mode ? 2.0 : 1.0;
+        [super setRetinaMode:mode];
+    }
+
+    - (CALayer*) makeBackingLayer
+    {
+        CAMetalLayer *layer = [CAMetalLayer layer];
+        layer.device = _device;
+        layer.framebufferOnly = YES;
+        layer.magnificationFilter = kCAFilterNearest;
+        layer.backgroundColor = CGColorGetConstantColor(kCGColorBlack);
+        layer.contentsScale = retina_on ? 2.0 : 1.0;
+        return layer;
+    }
+
+    - (BOOL) isOpaque
+    {
+        return YES;
+    }
+
+ at end
+#endif
+
+
 @implementation WineWindow
 
     static WineWindow* causing_becomeKeyWindow;
@@ -3492,6 +3586,7 @@ macdrv_view macdrv_create_view(CGRect rect)
 
         view = [[WineContentView alloc] initWithFrame:NSRectFromCGRect(cgrect_mac_from_win(rect))];
         [view setAutoresizesSubviews:NO];
+        [view setAutoresizingMask:NSViewNotSizable];
         [view setHidden:YES];
         [nc addObserver:view
                selector:@selector(updateGLContexts)
@@ -3679,6 +3774,52 @@ void macdrv_remove_view_opengl_context(macdrv_view v, macdrv_opengl_context c)
     [pool release];
 }
 
+#ifdef HAVE_METAL_METAL_H
+macdrv_metal_device macdrv_create_metal_device(void)
+{
+    macdrv_metal_device ret;
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11
+    if (MTLCreateSystemDefaultDevice == NULL)
+        return NULL;
+#endif
+
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    ret = (macdrv_metal_device)MTLCreateSystemDefaultDevice();
+    [pool release];
+    return ret;
+}
+
+void macdrv_release_metal_device(macdrv_metal_device d)
+{
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    [(id<MTLDevice>)d release];
+    [pool release];
+}
+
+macdrv_metal_view macdrv_view_create_metal_view(macdrv_view v, macdrv_metal_device d)
+{
+    id<MTLDevice> device = (id<MTLDevice>)d;
+    WineContentView* view = (WineContentView*)v;
+    __block WineMetalView *metalView;
+
+    OnMainThread(^{
+        metalView = [view newMetalViewWithDevice:device];
+    });
+
+    return (macdrv_metal_view)metalView;
+}
+
+void macdrv_view_release_metal_view(macdrv_metal_view v)
+{
+    WineMetalView* view = (WineMetalView*)v;
+    OnMainThread(^{
+        [view removeFromSuperview];
+        [view release];
+    });
+}
+#endif
+
 int macdrv_get_view_backing_size(macdrv_view v, int backing_size[2])
 {
     WineContentView* view = (WineContentView*)v;
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index a22b4c2917..acab5dfd92 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -138,6 +138,10 @@
 typedef struct macdrv_opaque_event_queue* macdrv_event_queue;
 typedef struct macdrv_opaque_view* macdrv_view;
 typedef struct macdrv_opaque_opengl_context* macdrv_opengl_context;
+#ifdef HAVE_METAL_METAL_H
+typedef struct macdrv_opaque_metal_device* macdrv_metal_device;
+typedef struct macdrv_opaque_metal_view* macdrv_metal_view;
+#endif
 typedef struct macdrv_opaque_status_item* macdrv_status_item;
 struct macdrv_event;
 struct macdrv_query;
@@ -527,6 +531,12 @@ extern void macdrv_set_window_color_key(macdrv_window w, CGFloat keyRed, CGFloat
 extern void macdrv_set_view_hidden(macdrv_view v, int hidden) DECLSPEC_HIDDEN;
 extern void macdrv_add_view_opengl_context(macdrv_view v, macdrv_opengl_context c) DECLSPEC_HIDDEN;
 extern void macdrv_remove_view_opengl_context(macdrv_view v, macdrv_opengl_context c) DECLSPEC_HIDDEN;
+#ifdef HAVE_METAL_METAL_H
+extern macdrv_metal_device macdrv_create_metal_device(void) DECLSPEC_HIDDEN;
+extern void macdrv_release_metal_device(macdrv_metal_device d) DECLSPEC_HIDDEN;
+extern macdrv_metal_view macdrv_view_create_metal_view(macdrv_view v, macdrv_metal_device d) DECLSPEC_HIDDEN;
+extern void macdrv_view_release_metal_view(macdrv_metal_view v) DECLSPEC_HIDDEN;
+#endif
 extern int macdrv_get_view_backing_size(macdrv_view v, int backing_size[2]) DECLSPEC_HIDDEN;
 extern void macdrv_set_view_backing_size(macdrv_view v, const int backing_size[2]) DECLSPEC_HIDDEN;
 extern uint32_t macdrv_window_background_color(void) DECLSPEC_HIDDEN;
-- 
2.18.0





More information about the wine-devel mailing list