Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

devdraw: rewrite the cocoa screen #194

Closed
wants to merge 1 commit into from
Closed

Conversation

jxy
Copy link
Contributor

@jxy jxy commented Oct 22, 2018

Add a new macOS cocoa screen, cocoa-screen-metal.m.
Rewrite the macOS cocoa drawing code to use the builtin runloop,
and use Metal to push pixels with CAMetalLayer.

Remove all of the deprecated code, and simplify some of the logic.
Modify mkwsysrules.sh such that the new code is used only when
the system version is equal or higher than 10.14.

Allow touch events to simulate mouse clicks:
three finger tap for the middle mouse button;
four finger tap for the 2-1 chord.

Support macOS input sources including the basic dead keys and the
advanced CJK input methods.

Increase the communication buffers in cocoa-srv.c to allow more
input, especially for long sentences prepared by the macOS input
souces.

@jxy
Copy link
Contributor Author

jxy commented Oct 22, 2018

This should fix #185.

I think the code is much more readable in this way, but this is a subjective matter.

I also reworked the cursor change code, which I borrowed some from 9front's drawterm. The big arrow finally works.

I haven't yet put in the code for a proper icon. I plan to copy from the existing code in cocoa-screen.m for the icon. Done.

Since I dropped most of the code, please let me know if there is any feature that is missing in this code.

If you are using a previous version of the macOS, by default you will compile and link the previous code, cocoa-screen.m. If you want to try the new code, cocoa-screen-mojave.m, do mk COCOATYPE=mojave in the directory, src/cmd/devdraw, and run DEVDRAW=./o.devdraw font=/mnt/font/GoMono/14a/font 9term. Doesn't really work.

@jacobvosmaer
Copy link
Contributor

Neat!. Dumping some observations:

  • Ctrl-e, ctrl-a, ctrl-u are not working in Acme at 5b88da4
  • App icon is terminal instead of glenda
  • Cmd-q not working

I'll test some more to see what else I find.

src/cmd/devdraw/mkwsysrules.sh Outdated Show resolved Hide resolved
src/cmd/devdraw/cocoa-screen-mojave.m Outdated Show resolved Hide resolved
@jxy
Copy link
Contributor Author

jxy commented Oct 23, 2018

  • Ctrl-e, ctrl-a, ctrl-u are not working in Acme at 5b88da4
  • App icon is terminal instead of glenda
  • Cmd-q not working

These should be fixed.

@jacobvosmaer
Copy link
Contributor

FWIW, I can't compile this on macOS 10.13:

9c -DOSX_VERSION=101306 -fobjc-arc -o cocoa-screen-mojave-objc.o cocoa-screen-mojave.m
cocoa-screen-mojave.m:412:19: error: no visible @interface for 'NSWindow' declares the selector 'convertPointToBacking:'
cocoa-screen-mojave.m:568:11: error: no visible @interface for 'NSWindow' declares the selector 'convertPointFromBacking:'
cocoa-screen-mojave.m:572:11: error: no visible @interface for 'NSWindow' declares the selector 'convertPointToScreen:'
mk: 9c -DOSX_VERSION=101306 -fobjc-arc ...  : exit status=exit(1)

Not that it matters because this explicitly targets 10.14 and up.

@jxy
Copy link
Contributor Author

jxy commented Oct 24, 2018

Now it should be usable.

The new revision uses CALayer of the view, and no longer uses drawRect. sample(1) shows that three parts dominate, read time (maybe from pipe), CGContext draw time (the offscreen part within the _flushmemscreen), and the CALayer draw time (push to screen). I guess the last two should be improvable.

@jacobvosmaer
Copy link
Contributor

I have been benchmarking what happens when you run pump a lot of text into an Acme window. The use case is accidentally opening / catting a large file.

In this benchmark, the latest version here is slower than #191. This is my silly benchmark: https://gist.github.com/jacobvosmaer/2b70d04833219b9bb3c9ae11608ae7e6

I wonder if CALayer is working against us because it always does a full screen redraw, while devdraw clients may often just invalidate small portions of the screen.

@jxy how are you benchmarking performance?

@jxy
Copy link
Contributor Author

jxy commented Oct 24, 2018

I'm using sample(1) while doing the cat thing.

When I get around, I'm going to change this to drawInContext later, and eliminate the additional offscreen drawing.

@jacobvosmaer
Copy link
Contributor

Cool. I started with find / and cat but then I came up with my 'blurt' script to make sure disk IO is not distorting my measurement.

I have no complaints about the current performance but I thought it was worth mentioning the difference. Considering that macOS 10.14 is still broken on plan9port master, you could consider leaving performance for a later PR.

I think it's super awesome that you did a clean rewrite. I think it's a better idea than what I did in #191; this lets us sunset the old Cocoa.

@jacobvosmaer
Copy link
Contributor

I found another bug. When I start Acme on a low-DPI external monitor, and then disconnect the monitor, the text rendering does not update to hi-DPI (Retina). I end up with tiny letters until I restart Acme.

@jxy
Copy link
Contributor Author

jxy commented Oct 26, 2018

Yes. There is one more event to process. At the mean time, you can try Cmd-r.

@jacobvosmaer
Copy link
Contributor

I found something else. When I do a three finger tap, I used to get a middle click. E.g. by three-finger-tapping 'Put' in a dirty Acme window I would save the window.

In this branch that is not currently working. Nothing happens when I do the three finger tap.

@jacobvosmaer
Copy link
Contributor

Another bug: entering Latin non-ASCII characters with Alt-key combinations no longer works. In my local environment I can type Alt-e e and get é. This used to work in Acme but with the devdraw from this branch it doesn't anymore.

@jxy
Copy link
Contributor Author

jxy commented Nov 1, 2018

Thanks @jacobvosmaer. These should be easy to fix.

I'm a little confused about the thread safety now. Apparently resizeimg can be called by the main thread from the NSWindow event. This is clearly not safe as all changes of the Memimage is done via the servep9p thread.

On the other hand, it seems that the Tresize event is never received.

Can somebody shed some light about the resize event in devdraw?

@jxy
Copy link
Contributor Author

jxy commented Nov 2, 2018

I've updated the commit using MetalKit. @jacobvosmaer I'll look into the missing features later.

@jxy jxy force-pushed the cocoa-mojave branch 2 times, most recently from b3a00d5 to 7c9e176 Compare November 8, 2018 03:00
@jxy
Copy link
Contributor Author

jxy commented Nov 8, 2018

I added most of the existing features, except for the drag and drop. Does anybody actually use the drag and drop?

Please test the external low DPI monitor support.

It now allows touch events to simulate mouse clicks: two finger tap for the right mouse button; three finger tap for the middle mouse button; four finger tap for the 2-1 chord. It also includes the control click #119 simulating left button (mainly for 2-1 chord).

It also supports macOS input sources including the basic dead keys and the advanced CJK input methods (I only tested the Chinese and Japanese ones). There is a different implementation in #121. This uses artificial keystrokes to show IME's input buffer in any application. You can test and see the behavior by pressing option-e in the default U.S. keyboard, which would show [´], and then pressing e turns [´] into é.

@jxy
Copy link
Contributor Author

jxy commented Nov 8, 2018

Changed to CAMetalLayer. This fixes the graphical glitches appearing in the MTKView based renderer. Things are much smoother and responsive now.

@jacobvosmaer
Copy link
Contributor

Oddly, I'm having trouble compiling at dcfb631.

devdraw jacobvosmaer$ 9 mk clean; 9 mk
rm -f *.[o] [o].out o.macargv o.mklatinkbd latin1.h y.tab.[ch]
9c -DOSX_VERSION=101401 mklatinkbd.c
9c -DOSX_VERSION=101401 -fobjc-arc -o cocoa-screen-metal-objc.o cocoa-screen-metal.m
cocoa-screen-metal.m:506:19: error: no visible @interface for 'NSWindow' declares the selector 'convertPointToBacking:'
cocoa-screen-metal.m:960:12: error: no visible @interface for 'NSWindow' declares the selector 'convertPointFromBacking:'
cocoa-screen-metal.m:964:12: error: no visible @interface for 'NSWindow' declares the selector 'convertPointToScreen:'
mk: 9c -DOSX_VERSION=101401 -fobjc-arc ...  : exit status=exit(1)

@jxy
Copy link
Contributor Author

jxy commented Nov 8, 2018

@jacobvosmaer you updated to 10.14.1? You need Xcode, and set CC9='xcrun --sdk macosx clang'.

Apple seems to botched their system header files.

@jacobvosmaer
Copy link
Contributor

Yes, 10.14.1. That CC9 override works, thanks. Will try your latest version now!

@jacobvosmaer
Copy link
Contributor

When I do a two-finger tap (i.e. button 3) to search for a word in an Acme window, I get two searches in a row sometimes. It seems to register two events instead of one.

@jxy
Copy link
Contributor Author

jxy commented Nov 14, 2018

  1. If I open acme and right click on a file in a directory window, the mouse cursor is supposed to end up in the "button", the square box in the upper left corner of the new window. On my Mac the cursor is ending up much too low and a little to the right of where it should be.

When you move the window, the cursor is supposed to end up in the "button". When you open a new window by right click a file/dir or via plumber, the cursor is supposed to end up at the beginning of the window, or position :#0. Is this what you are seeing? I believe it is the expected behavior.

  1. Cmd-F to toggle full screen seems to have been dropped.

OK. I added it back, see fcc76fb.

  1. If I enter full screen using the green circle in the top bar, I get a black screen. Clicking in an acme window makes the screen redraw properly.

This is a serious problem. Unfortunately I cannot reproduce it. I only have my 2017 13-inch MacBook pro and I have not seen such an issue. Do you always get black screen? Can you change the line #define LOG if(0)NSLog to #define LOG if(1)NSLog and let me know the output when it happens?

  1. Once I'm in full screen mode it seems to be impossible to leave. The old answer was Cmd-F (which should come back). Executing Exit in acme is an option.

I got used to two finger pinch to toggle full screen. Cmd-F is back for people who like it.

@rsc
Copy link
Contributor

rsc commented Nov 14, 2018

I got used to two finger pinch to toggle full screen. Cmd-F is back for people who like it.

Thank you. When I'm at my desk I use an external keyboard and don't have any trackpad to pinch.

@rsc
Copy link
Contributor

rsc commented Nov 14, 2018

When you move the window, the cursor is supposed to end up in the "button". When you open a new window by right click a file/dir or via plumber, the cursor is supposed to end up at the beginning of the window, or position :#0. Is this what you are seeing? I believe it is the expected behavior.

You are correct - I was wrong about the button vs the #0 position. What I'm seeing then is that the cursor is way too far down vertically but probably aligned correctly horizontally.

screen shot 2018-11-14 at 12 28 28 am

@rsc
Copy link
Contributor

rsc commented Nov 14, 2018

For the black full-screen, I see it on both my main laptop screen and my external monitor. Here's a log. Various things happening before I typed Cmd-F:

2018-11-14 00:34:54.791 devdraw[70150:759490] callsetNeedsDisplayInRect(0, 0, 2240, 1356)
2018-11-14 00:34:54.791 devdraw[70150:759490] setNeedsDisplayInRect(0, 0, 1120, 678)
2018-11-14 00:34:54.791 devdraw[70150:759490] update last input rect (0, 0, 1120, 678)
2018-11-14 00:34:54.791 devdraw[70150:759490] callsetNeedsDisplayInRect(0, 0, 2240, 1356)
2018-11-14 00:34:54.791 devdraw[70150:759490] setNeedsDisplayInRect(0, 0, 1120, 678)
2018-11-14 00:34:54.791 devdraw[70150:759490] update last input rect (0, 0, 1120, 678)
2018-11-14 00:34:54.791 devdraw[70150:759490] callsetNeedsDisplayInRect(1344, 66, 896, 1290)
2018-11-14 00:34:54.791 devdraw[70150:759490] setNeedsDisplayInRect(672, 33, 448, 645)
2018-11-14 00:34:54.791 devdraw[70150:759490] update last input rect (0, 0, 1120, 678)
2018-11-14 00:34:54.804 devdraw[70150:759490] display
2018-11-14 00:34:54.804 devdraw[70150:759490] display query drawable
2018-11-14 00:34:54.804 devdraw[70150:759490] display got drawable
2018-11-14 00:34:54.805 devdraw[70150:759490] display commit
2018-11-14 00:34:54.809 devdraw[70150:759504] command buffer finishes present drawable
2018-11-14 00:34:56.189 devdraw[70150:759490] initimg 2240 1356
2018-11-14 00:34:56.190 devdraw[70150:759490] initimg return
2018-11-14 00:34:56.203 devdraw[70150:759496] _flushmemscreen(0,0,2240,1356)
2018-11-14 00:34:56.216 devdraw[70150:759490] callsetNeedsDisplayInRect(0, 0, 2240, 1356)
2018-11-14 00:34:56.216 devdraw[70150:759490] setNeedsDisplayInRect(0, 0, 1120, 678)
2018-11-14 00:34:56.216 devdraw[70150:759490] update last input rect (0, 0, 1120, 678)
2018-11-14 00:34:56.216 devdraw[70150:759490] display
2018-11-14 00:34:56.216 devdraw[70150:759490] display query drawable
2018-11-14 00:34:56.217 devdraw[70150:759490] display got drawable
2018-11-14 00:34:56.217 devdraw[70150:759490] display commit
2018-11-14 00:34:56.221 devdraw[70150:759491] command buffer finishes present drawable

I waited until 00:35:00 and typed Cmd-F:

2018-11-14 00:35:00.512 devdraw[70150:759490] flagsChanged
2018-11-14 00:35:00.578 devdraw[70150:759490] initimg 5120 2880
2018-11-14 00:35:00.579 devdraw[70150:759490] initimg return
2018-11-14 00:35:00.620 devdraw[70150:759496] _flushmemscreen(0,0,5120,2880)
2018-11-14 00:35:00.628 devdraw[70150:759490] flagsChanged
2018-11-14 00:35:00.674 devdraw[70150:759490] callsetNeedsDisplayInRect(0, 0, 5120, 2880)
2018-11-14 00:35:00.674 devdraw[70150:759490] setNeedsDisplayInRect(0, 0, 2560, 1440)
2018-11-14 00:35:00.674 devdraw[70150:759490] update last input rect (0, 0, 2560, 1440)
2018-11-14 00:35:00.674 devdraw[70150:759490] display
2018-11-14 00:35:00.674 devdraw[70150:759490] display query drawable
2018-11-14 00:35:00.674 devdraw[70150:759490] display got drawable
2018-11-14 00:35:00.674 devdraw[70150:759490] display commit
2018-11-14 00:35:00.690 devdraw[70150:759607] command buffer finishes present drawable

The black screen appeared. I clicked, knowing the cursor was in the white part (not in an acme window):

2018-11-14 00:35:11.153 devdraw[70150:759490] resetLastInputRect

Nothing happened.

Then I moved the cursor into a real acme window and clicked again:

2018-11-14 00:35:14.920 devdraw[70150:759496] _flushmemscreen(3093,97,6,30)
2018-11-14 00:35:14.920 devdraw[70150:759496] _flushmemscreen(3093,517,6,30)
2018-11-14 00:35:14.920 devdraw[70150:759490] callsetNeedsDisplayInRect(3093, 97, 6, 30)
2018-11-14 00:35:14.920 devdraw[70150:759490] setNeedsDisplayInRect(1546.5, 48.5, 3, 15)
2018-11-14 00:35:14.920 devdraw[70150:759490] update last input rect (1546.5, 1376.5, 3, 15)
2018-11-14 00:35:14.920 devdraw[70150:759490] callsetNeedsDisplayInRect(3093, 517, 6, 30)
2018-11-14 00:35:14.920 devdraw[70150:759490] setNeedsDisplayInRect(1546.5, 258.5, 3, 15)
2018-11-14 00:35:14.920 devdraw[70150:759490] update last input rect (1546.5, 1166.5, 3, 225)
2018-11-14 00:35:14.920 devdraw[70150:759490] display
2018-11-14 00:35:14.920 devdraw[70150:759490] display query drawable
2018-11-14 00:35:14.921 devdraw[70150:759490] display got drawable
2018-11-14 00:35:14.921 devdraw[70150:759490] display commit
2018-11-14 00:35:14.936 devdraw[70150:759508] command buffer finishes present drawable
2018-11-14 00:35:15.001 devdraw[70150:759496] _flushmemscreen(3068,66,23,31)
2018-11-14 00:35:15.001 devdraw[70150:759490] callsetNeedsDisplayInRect(3068, 66, 23, 31)
2018-11-14 00:35:15.001 devdraw[70150:759490] setNeedsDisplayInRect(1534, 33, 11.5, 15.5)
2018-11-14 00:35:15.001 devdraw[70150:759490] update last input rect (1534, 1166.5, 15.5, 240.5)
2018-11-14 00:35:15.001 devdraw[70150:759490] display
2018-11-14 00:35:15.001 devdraw[70150:759490] display query drawable
2018-11-14 00:35:15.003 devdraw[70150:759490] display got drawable
2018-11-14 00:35:15.003 devdraw[70150:759490] display commit
2018-11-14 00:35:15.019 devdraw[70150:759609] command buffer finishes present drawable

At this point the screen was no longer black.

@rsc
Copy link
Contributor

rsc commented Nov 14, 2018

This fixes the cursor problem, which only occurs on an external monitor:

diff --git a/src/cmd/devdraw/cocoa-screen-metal.m b/src/cmd/devdraw/cocoa-screen-metal.m
index 54a32ad9..d0123e98 100644
--- a/src/cmd/devdraw/cocoa-screen-metal.m
+++ b/src/cmd/devdraw/cocoa-screen-metal.m
@@ -967,7 +967,7 @@ - (void)display
                q = [myContent convertPoint:q toView:nil];
                LOG(@"(%g, %g) <- toWindow", q.x, q.y);
                q = [win convertPointToScreen:q];
-               h = [[NSScreen mainScreen] frame].size.height;
+               h = [[[NSScreen screens] objectAtIndex:0] frame].size.height;
                q.y = h - q.y;
                LOG(@"(%g, %g) <- setmouse", q.x, q.y);
                CGWarpMouseCursorPosition(NSPointToCGPoint(q));

I just put the line from cocoa-screen.m back in. :-)
I don't know what it means.

@rsc
Copy link
Contributor

rsc commented Nov 14, 2018

At this point I think the black screen on full-screen mode is the only problem. It happens on the main laptop as well as the external monitor. I have:

m8:devdraw rsc$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14
BuildVersion:	18A391

I will try updating to 10.14.1.

@mkhl
Copy link
Contributor

mkhl commented Nov 14, 2018

I just put the line from cocoa-screen.m back in. :-)
I don't know what it means.

From the documentation:

The screen at index 0 in the returned array corresponds to the primary screen of the user’s system. This is the screen that contains the menu bar and whose origin is at the point (0, 0). In the case of mirroring, the first screen is the largest drawable display; if all screens are the same size, it is the screen with the highest pixel depth. This primary screen may not be the same as the one returned by the main method, which returns the screen with the active window.

Naively, I would have thought that the “screen with the active window” sounds like what we would want, but maybe we’re not working in its coordinate system.

@rsc
Copy link
Contributor

rsc commented Nov 14, 2018

10.14.1 did not fix the black screen on full-size.

In addition to the black screen, can we go back to the system arrow cursor instead of the big Plan 9 arrow? The Plan 9 arrow does not look right on retina screens (the white outline has weird glitches).

@jacobvosmaer
Copy link
Contributor

I tried to debug the low-DPI monitor issue, where the scaling factor is wrong after disconnecting my monitor. This time I got a crash...

Thread 2 Crashed:
0   com.apple.driver.AppleIntelHD5000GraphicsMTLDriver	0x00007fff421470fe CpuSwizzleBlt + 9876
1   com.apple.driver.AppleIntelHD5000GraphicsMTLDriver	0x00007fff4214492e -[MTLIGAccelTexture replaceRegion:mipmapLevel:slice:withBytes:bytesPerRow:bytesPerImage:] + 1457
2   com.apple.driver.AppleIntelHD5000GraphicsMTLDriver	0x00007fff421796cc -[MTLIGAccelTexture replaceRegion:mipmapLevel:withBytes:bytesPerRow:] + 67
3   devdraw                       	0x00000001068758b9 _flushmemscreen + 233 (cocoa-screen-metal.m:945)
4   devdraw                       	0x000000010686f0f4 _drawmsgwrite + 3300 (devdraw.c:301)

acme-crash-20181114.txt

@jacobvosmaer
Copy link
Contributor

I can't reproduce the black screen problem on my machines sadly.

Unrelated: I still need to override CC9 to get fcc76fb to compile. I haven't tried a full INSTALL run, I'm using 9 mk in the devdraw directory. Assuming the compile failure happens with INSTALL too (should I try that out?) we should fix that CC9 problem before we merge.

@rsc
Copy link
Contributor

rsc commented Nov 14, 2018

@jacobvosmaer I installed Xcode from the App Store on a fresh Mojave system last night and I've been running ./INSTALL and mk install with no CC9 override. I'm not sure what's wrong on your system but maybe updating Xcode would fix it?

@rsc
Copy link
Contributor

rsc commented Nov 14, 2018

I will take another look at all this tonight and merge this PR. It's working well enough and any bugs are limited to Mojave (and the alternative is nothing working at all).

I'd still like to go back to the system cursor instead of the big cursor. If someone can figure out why the white lines in the cursor are not white (the screen pixels below them display inverted instead!) I'd be happy to try the big cursor again at that point.

@jxy
Copy link
Contributor Author

jxy commented Nov 14, 2018

  1. Setting cursor on a second screen
    I understand the problem. I'll push a fix tonight.

  2. Fullscreen black
    @rsc, can you search for the word MTLStoreActionDontCare, and change it to MTLStoreActionStore and see if it helps? If not, try changing the line above to use MTLLoadActionLoad in addition? Perhaps it relates to how metal deals with discrete graphics card differently from an integrated one?

  3. Low res second monitor
    It seems to me that the current version works fine. It triggers a resize when moved from my laptop screen to an external screen with the correct scaling, and it does it correctly when I unplug the screen. @jacobvosmaer, can you also change the line #define LOG if(0)NSLog to #define LOG if(1)NSLog and let me know the output when it crashes. Can you tell me how I can reproduce the crash? My naive guess would be some race condition between resizeimg called from main thread, while servep9p is doing the drawing. Perhaps we just need a lock somewhere.

  4. 16x16 Cursor at hidpi
    I guess the automatic scaling of the cursor is not good enough. You can see the defects in the box cursor, too, when you move acme windows. I will see if I can put in some code to do a simple up scaling tonight.

  5. default clang
    Perhaps both mine and @jacobvosmaer's Xcode install or the Xcode command line tools has some problem. I have to put a line CC9='xcrun --sdk macosx clang' in the file LOCAL.config.

@rsc
Copy link
Contributor

rsc commented Nov 15, 2018

Thanks for the fixes. I'll wait for your next patch set to do the full push.

  • Re: fullscreen black. The MTLStoreAction changes didn't help.

  • Re: cursor glitches. Yes, I first noticed the problem with the box cursor in the old devdraw implementation. I toyed with detecting the box and changing to the system hand cursor because the glitching was so annoying, but I never actually pushed that change back. It would be great to figure out how to make white be white.

  • Re: default clang. Try:

    clang --version
    xcrun --sdk macosx clang --version
    xcode-select -p
    

    It seems to me that you should be able to run xcode-select -s with the InstalledDir printed by the xcrun clang version output. I thought about changing the default compiler in 9c to the xcrun sequence, but it seems like maybe it would be better to respect people's xcode-select settings.

@rsc
Copy link
Contributor

rsc commented Nov 15, 2018

FWIW, I agree that the locking is suspect here. I applied this patch locally, to make programs build with ThreadSanitizer:

diff --git a/bin/9c b/bin/9c
index 3ffb716c..5ce40c56 100755
--- a/bin/9c
+++ b/bin/9c
@@ -73,6 +73,7 @@ useclang()
 		-Wno-unneeded-internal-declaration \
 		-fsigned-char \
 		-fno-caret-diagnostics \
+		-fsanitize=thread \
 	"
 	cflags="$ngflags -g"
 }
diff --git a/bin/9l b/bin/9l
index 6195815f..fb77ed27 100755
--- a/bin/9l
+++ b/bin/9l
@@ -46,7 +46,7 @@ case "$tag" in
 	esac
 	;;
 *Darwin*x86_64*)
-	ld="${CC9:-gcc} -m64"
+	ld="${CC9:-clang} -m64 -fsanitize=thread"
 	;;
 *Darwin*)
 	ld="${CC9:-gcc} -m32"

After rebuilding all the libraries and devdraw, I got consistent reports about races between the graphics thread and the serving thread. I applied this diff and they went away:

diff --git a/src/cmd/devdraw/cocoa-screen-metal.m b/src/cmd/devdraw/cocoa-screen-metal.m
index 54a32ad9..49f9a0cf 100644
--- a/src/cmd/devdraw/cocoa-screen-metal.m
+++ b/src/cmd/devdraw/cocoa-screen-metal.m
@@ -887,7 +889,7 @@ - (void)display
 		waitUntilDone:YES];
 	kicklabel(label);
 	setcursor(nil);
-	atomic_init(&mouseresized, 0);
+	mouseresized = 0;
 	return initimg();
 }
 
@@ -967,7 +969,7 @@ - (void)display
 		q = [myContent convertPoint:q toView:nil];
 		LOG(@"(%g, %g) <- toWindow", q.x, q.y);
 		q = [win convertPointToScreen:q];
-		h = [[NSScreen mainScreen] frame].size.height;
+		h = [[[NSScreen screens] objectAtIndex:0] frame].size.height;
 		q.y = h - q.y;
 		LOG(@"(%g, %g) <- setmouse", q.x, q.y);
 		CGWarpMouseCursorPosition(NSPointToCGPoint(q));
@@ -1059,9 +1061,10 @@ - (void)display
 void
 resizeimg(void)
 {
+	zlock();
 	_drawreplacescreenimage(initimg());
-
-	atomic_store(&mouseresized, 1);
+	mouseresized = 1;
+	zunlock();
 	[myContent sendmouse:0];
 }
 
diff --git a/src/cmd/devdraw/cocoa-screen.h b/src/cmd/devdraw/cocoa-screen.h
index c99845b5..7b41c34b 100644
--- a/src/cmd/devdraw/cocoa-screen.h
+++ b/src/cmd/devdraw/cocoa-screen.h
@@ -20,10 +20,5 @@ void resizeimg(void);
 
 Rectangle mouserect;
 
-#if OSX_VERSION < 101400
 int mouseresized;
-#else
-#include<stdatomic.h>
-atomic_int mouseresized;
 void resizewindow(Rectangle);
-#endif
diff --git a/src/cmd/devdraw/cocoa-srv.c b/src/cmd/devdraw/cocoa-srv.c
index 7575fca8..226ed05d 100644
--- a/src/cmd/devdraw/cocoa-srv.c
+++ b/src/cmd/devdraw/cocoa-srv.c
@@ -191,6 +191,7 @@ runmsg(Wsysmsg *m)
 		break;
 
 	case Trddraw:
+		zlock();
 		n = m->count;
 		if(n > sizeof buf)
 			n = sizeof buf;
@@ -202,13 +203,16 @@ runmsg(Wsysmsg *m)
 			m->data = buf;
 			replymsg(m);
 		}
+		zunlock();
 		break;
 
 	case Twrdraw:
+		zlock();
 		if(_drawmsgwrite(m->data, m->count) < 0)
 			replyerror(m);
 		else
 			replymsg(m);
+		zunlock();
 		break;
 	
 	case Ttop:
@@ -217,10 +221,12 @@ runmsg(Wsysmsg *m)
 		break;
 	
 	case Tresize:
+		zlock();
 #if OSX_VERSION >= 101400
 		resizewindow(m->rect);
 #endif
 		replymsg(m);
+		zunlock();
 		break;
 	}
 }
@@ -294,12 +300,8 @@ matchmouse(void)
 		if(mousetags.ri == nelem(mousetags.t))
 			mousetags.ri = 0;
 		m.mouse = mouse.m[mouse.ri];
-#if OSX_VERSION < 101400
 		m.resized = mouseresized;
 		mouseresized = 0;
-#else
-		m.resized = atomic_exchange(&mouseresized, 0);
-#endif
 		/*
 		if(m.resized)
 			fprint(2, "sending resize\n");

Please apply those changes to your copy. Thanks.

@rsc
Copy link
Contributor

rsc commented Nov 15, 2018

  • Re: fullscreen black. Even with my locking fixes above, I still get the black fullscreen. However, I've found that no action is needed on the part of devdraw to make the black go away: Ctrl-UpArrow to get the exploded-desktop view or Ctrl-LeftArrow to flip back to the main desktop both cause the black screen to get repainted correctly for a split second before doing their thing. So it seems everything has made it to some macOS buffer but there is some kind of 'flush image to screen' operation missing.

  • Re: resizewindow not being called. Most programs don't resize their own windows. Here's a test that should:

    png -t $PLAN9/dist/glendacircle.png | img
    

    The window that pops up should be resized down to match the displayed image.
    With logging turned on I can see the resizewindow print.

Add a new macOS cocoa screen, cocoa-screen-metal.m.
Rewrite the macOS cocoa drawing code to use the builtin runloop,
and use Metal to push pixels with CAMetalLayer.

Remove all of the deprecated code, and simplify some of the logic.
Modify mkwsysrules.sh such that the new code is used only when
the system version is equal or higher than 10.14.

Allow touch events to simulate mouse clicks:
three finger tap for the middle mouse button;
four finger tap for the 2-1 chord.

Support Tresize.

Scale 16x16 Cursor up to 32x32 with an EPX algorithm.

Support macOS input sources including the basic dead keys and the
advanced CJK input methods.

Increase the communication buffers in cocoa-srv.c to allow more
input, especially for long sentences prepared by the macOS input
souces.
@jxy
Copy link
Contributor Author

jxy commented Nov 15, 2018

Please check the new patch 7bded71

Completed the resizewindow implementation. Included the locks @rsc suggested. Implemented a cursor up scaling algorithm, EPX, from wikipedia.

For the fullscreen black issue, @rsc, can you try changing NSViewLayerContentsRedrawOnSetNeedsDisplay to either one of NSViewLayerContentsRedrawDuringViewResize, NSViewLayerContentsRedrawBeforeViewResize or NSViewLayerContentsRedrawCrossfade?

@jxy
Copy link
Contributor Author

jxy commented Nov 15, 2018

Regarding the default clang, I have the same versions and xcode-select prints the correct path. The only thing I can see that's different when invoking clang directly or xcrun with sdk parameter is that the framework directory is different.

% xcrun --sdk macosx clang -v -DOSX_VERSION=101401 -fobjc-arc -o cocoa-screen-metal-objc.o cocoa-screen-metal.m -I$PLAN9/include -c                    
Apple LLVM version 10.0.0 (clang-1000.11.45.5)
Target: x86_64-apple-darwin18.2.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.14.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name cocoa-screen-metal.m -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fno-strict-return -masm-verbose -munwind-tables -target-cpu penryn -dwarf-column-info -debugger-tuning=lldb -target-linker-version 409.12 -v -coverage-notes-file /Users/jin/src/plan9port/src/cmd/devdraw/cocoa-screen-metal-objc.gcno -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/10.0.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -D OSX_VERSION=101401 -I /Users/jin/src/p9p/include -fdebug-compilation-dir /Users/jin/src/plan9port/src/cmd/devdraw -ferror-limit 19 -fmessage-length 123 -stack-protector 1 -fblocks -fencode-extended-block-signature -fobjc-runtime=macosx-10.14.0 -fobjc-arc -fobjc-exceptions -fexceptions -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -o cocoa-screen-metal-objc.o -x objective-c cocoa-screen-metal.m
clang -cc1 version 10.0.0 (clang-1000.11.45.5) default target x86_64-apple-darwin18.2.0
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/local/include"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/Library/Frameworks"
#include "..." search starts here:
#include <...> search starts here:
 /Users/jin/src/p9p/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/10.0.0/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks (framework directory)
End of search list.
% clang -v -DOSX_VERSION=101401 -fobjc-arc -o cocoa-screen-metal-objc.o cocoa-screen-metal.m -I$PLAN9/include -c       
Apple LLVM version 10.0.0 (clang-1000.11.45.5)
Target: x86_64-apple-darwin18.2.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.14.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name cocoa-screen-metal.m -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fno-strict-return -masm-verbose -munwind-tables -target-cpu penryn -dwarf-column-info -debugger-tuning=lldb -target-linker-version 409.12 -v -coverage-notes-file /Users/jin/src/plan9port/src/cmd/devdraw/cocoa-screen-metal-objc.gcno -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/10.0.0 -D OSX_VERSION=101401 -I /Users/jin/src/p9p/include -fdebug-compilation-dir /Users/jin/src/plan9port/src/cmd/devdraw -ferror-limit 19 -fmessage-length 123 -stack-protector 1 -fblocks -fencode-extended-block-signature -fobjc-runtime=macosx-10.14.0 -fobjc-arc -fobjc-exceptions -fexceptions -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -o cocoa-screen-metal-objc.o -x objective-c cocoa-screen-metal.m
clang -cc1 version 10.0.0 (clang-1000.11.45.5) default target x86_64-apple-darwin18.2.0
ignoring nonexistent directory "/usr/local/include"
#include "..." search starts here:
#include <...> search starts here:
 /Users/jin/src/p9p/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/10.0.0/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)
End of search list.

I wonder if /System/Library/Frameworks is somehow gone bad, because /System/Library/Frameworks/AppKit.framework/ is quite different from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/AppKit.framework/

% diff -r /System/Library/Frameworks/AppKit.framework/Headers/NSWindow.h /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSWindow.h|p
4c4
<     Copyright (c) 1994-2017, Apple Inc.
---
>     Copyright (c) 1994-2018, Apple Inc.
21a22
> #import <AppKit/NSMenu.h>
43c44
<     NSWindowStyleMaskTexturedBackground = 1 << 8,
---
>     NSWindowStyleMaskTexturedBackground NS_ENUM_DEPRECATED_MAC(10_2, API_TO_BE_DEPRECATED, "Textured window style should no longer be used") = 1 << 8,
82,88d82
< typedef NS_ENUM(NSUInteger, NSWindowBackingLocation) {
<     NSWindowBackingLocationDefault = 0,		// System determines if window backing store is in VRAM or main memory
<     NSWindowBackingLocationVideoMemory = 1,		// Window backing store is in VRAM
<     NSWindowBackingLocationMainMemory = 2		// Window backing store is in main memory
< } NS_ENUM_AVAILABLE_MAC(10_5);
< 
< 
144d137
< static const NSWindowLevel NSDockWindowLevel NS_DEPRECATED_MAC(10_0, 10_13) = kCGDockWindowLevel;
163d155
<     NSWindowFullScreenButton NS_ENUM_DEPRECATED_MAC(10_7, 10_12, "The standard window button for NSWindowFullScreenButton is always nil; use NSWindowZoomButton instead"),
[MORE OMITTED]

@rsc
Copy link
Contributor

rsc commented Nov 15, 2018

I wonder if the CC9 issue is somehow the same root cause as golang/go#26073. It's like recent Xcodes have a bug where they are just out of sync with themselves.

@rsc
Copy link
Contributor

rsc commented Nov 16, 2018

I merged the latest commit. Thanks for all the work on this!

Re fullscreen black, changing NSViewLayerContentsRedrawOnSetNeedsDisplay did not help. The others all drew garbage during the resize and then went to black when it was done. I left it alone. For now it's OK to just click for redraw after the full-screen switch.

The pixel-art scaling algorithm was interesting, but it drove me nuts how the point of the arrow got rounded. I prefer the sharpness of plain upscaling-by-doubling to the mushiness of the pixel-art output. I changed the upscaling to use doubling instead. But I also added support to libdraw to allow applications to supply their own 32x32 cursors, and I added a hand-edited 32x32 bigarrow that looks nice.

I also changed INSTALL to write a CC9 setting to $PLAN9/config saying xcrun --sdk macosx clang.

@rsc rsc closed this Nov 16, 2018
@jxy
Copy link
Contributor Author

jxy commented Nov 16, 2018

Good. For what it's worth, I reinstalled the system from option-command-r and directly calling clang works now. I guess Apple probably served a buggy Xcode command-line tools at the beginning of the 10.14.1 release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants