Skip to content

Instantly share code, notes, and snippets.

@GetVladimir
Last active November 15, 2024 14:00
Show Gist options
  • Save GetVladimir/c89a26df1806001543bef4c8d90cc2f8 to your computer and use it in GitHub Desktop.
Save GetVladimir/c89a26df1806001543bef4c8d90cc2f8 to your computer and use it in GitHub Desktop.
Force RGB Color on M1 Mac

Force RGB Color on M1 Mac

How to Force RGB Color Output instead of YPbPr on your M1 Apple Silicon Mac for an External Monitor.

This step-by-step video tutorial will guide you through the procedure of forcing RGB color output on your M1 Mac.

Force RGB Color on M1 Mac

Here is the direct link to the video tutorial: https://www.youtube.com/watch?v=Z1EqH3fd0V4

The video also has Closed Captions (Subtitles) that you can enable, to make it easier to follow if needed.



Please note that you're doing any changes on your own risk.

Terminal commands used in the video

Here are each of the Terminal commands mentioned in the tutorial, so that you can just copy and paste them:

open /Library/Preferences

plutil -convert xml1

plutil -convert binary1

plutil -lint



The step-by-step procedure on how to force RGB Color Output on M1 and M2 based Macs with Terminal commands

  1. Open Terminal and use this command to make Finder select the displays plist file:
    open -R /Library/Preferences/com.apple.windowserver.displays.plist

  2. Drag and drop the com.apple.windowserver.displays.plist file to Desktop manually. Don't use the cp command, as it won't add your current user with writing privileges.

  3. Convert the file to XML:
    plutil -convert xml1 ~/Desktop/com.apple.windowserver.displays.plist

  4. Open the converted file with the default plain text editor (avoid using the built-in TextEdit app if possible, since it might modify the file and make it unreadable by the system)
    open -t ~/Desktop/com.apple.windowserver.displays.plist
    or
    open -a CotEditor.app ~/Desktop/com.apple.windowserver.displays.plist

  5. Copy and paste the missing LinkDesription Key under the current display (check the screenshot below for an example of how it should look like):

				<key>LinkDescription</key>
				<dict>
					<key>BitDepth</key>
					<integer>8</integer>
					<key>EOTF</key>
					<integer>0</integer>
					<key>PixelEncoding</key>
					<integer>0</integer>
					<key>Range</key>
					<integer>1</integer>
				</dict>
  1. Save the file and then convert it to binary again:
    plutil -convert binary1 ~/Desktop/com.apple.windowserver.displays.plist

  2. Check if the plist file is valid:
    plutil -lint ~/Desktop/com.apple.windowserver.displays.plist

  3. Open the /Library/Preferences/ folder again:
    open /Library/Preferences/

  4. Drag and drop the updated com.apple.windowserver.displays.plist file from Desktop to the Library folder manually. Don't use the cp command, as it won't add your current user with writing privileges.

  5. Right Click on the com.apple.windowserver.displays.plist file in the Library folder and click on Get Info

  6. Check the boxes for Stationery and Locked.

  7. Reboot the Mac.

That's it!



(Alternative) Terminal commands to force RGB Color Output on M1 and M2 based Macs and workaround for losing RGB color after waking up from sleep

  1. Open Terminal

  2. Paste the following commands to edit the User's displays plist file com.apple.windowserver.displays.[UUID].plist using the built-in PlistBuddy function in macOS:

/usr/libexec/PlistBuddy -c "add DisplaySets:Configs:DisplayConfig:DisplayConfig:DisplayConfig:LinkDescription:BitDepth integer" ~/Library/Preferences/ByHost/com.apple.windowserver.displays.*.plist
/usr/libexec/PlistBuddy -c "set DisplaySets:Configs:DisplayConfig:DisplayConfig:DisplayConfig:LinkDescription:BitDepth 8" ~/Library/Preferences/ByHost/com.apple.windowserver.displays.*.plist
/usr/libexec/PlistBuddy -c "add DisplaySets:Configs:DisplayConfig:DisplayConfig:DisplayConfig:LinkDescription:EOTF integer" ~/Library/Preferences/ByHost/com.apple.windowserver.displays.*.plist
/usr/libexec/PlistBuddy -c "add DisplaySets:Configs:DisplayConfig:DisplayConfig:DisplayConfig:LinkDescription:PixelEncoding integer" ~/Library/Preferences/ByHost/com.apple.windowserver.displays.*.plist
/usr/libexec/PlistBuddy -c "add DisplaySets:Configs:DisplayConfig:DisplayConfig:DisplayConfig:LinkDescription:Range integer" ~/Library/Preferences/ByHost/com.apple.windowserver.displays.*.plist
  1. Reboot your Mac

(Workaround) If your Mac loses RGB color after waking up from sleep mode, either Reboot your Mac (recommended) or use this Terminal command to stop the WindowServer and login again (not recommended):

sudo killall -HUP WindowServer



End result

The end result is having your M1 mac output RGB color to your external monitor instead of YPbPr, potentially making the colors more accurate and the text a bit more crisp, even on older 1080p monitors.

Hopefully this tutorial would be useful to someone.

Please feel free to ask in the comment section if you have any questions regarding this procedure.



Background

While doing a lot of testing on how the Dual-Cable workaround makes RGB to work on M1, I've discovered what changes it makes to macOS, and managed to create a more streamlined workaround without the need to use a second cable.

To make things easier, I've created a step-by-step video tutorial of the whole procedure that should force RGB color output on your M1 Mac connected to an external monitor, and works on an HDMI-to-HDMI cable connection.

Credits

Big thanks goes to the amazing community and all their help over the years to solve issues like this:
https://gist.github.com/ejdyksen/8302862
https://gist.github.com/adaugherity/7435890

Useful Sources

Apple Open Source Project Files for Displays and Graphics
https://opensource.apple.com/source/IOKitUser/IOKitUser-1445.60.1/graphics.subproj/IODisplayLib.c
https://opensource.apple.com/source/IOGraphics/IOGraphics-517.17/IOGraphicsFamily/IOFramebuffer.cpp.auto.html

How to Edit and Convert binary plist files
http://hints.macworld.com/article.php?story=20050803111126899
https://apple.stackexchange.com/questions/155393/how-to-beautify-binary-dict-files
https://discussions.apple.com/thread/1768480

How to Edit plist files using defaults and PlistBuddy
https://ss64.com/osx/defaults.html
https://github.com/mathiasbynens/dotfiles/blob/master/.macos

Apps based on this method

@sudowork has created an awesome script written in Phyton that automates the steps and checks for duplicate files.
You can find more info about it here: https://github.com/sudowork/fix_m1_rgb

@dangh has created an alernative script for fishshell.
You can find more info about it here: https://github.com/dangh/force-rgb.fish

@GetVladimir I've also created a Shortcut to Force RGB Color Output using the built-in Shortcuts app.
You can find how to create the Shortcut here: https://gist.github.com/GetVladimir/c89a26df1806001543bef4c8d90cc2f8?permalink_comment_id=4531552#gistcomment-4531552

@entropyconquers has created a script based on this method written in Phyton that automates the steps, makes a backup and checks for duplicate files.
You can find more info about it here: https://github.com/entropyconquers/Force-RGB-Color-on-M1-M2-Mac-Script

Additional notes

Multiple PixelEncoding and Range keys in the same plist file
Note that there might be multiple instances of the PixelEncoding and Range keys in the same file, one for each output of your monitor and for different AirPlay devices. You might need to update the integer on each one to get RGB color output on all displays.

Getting RGB color only before login
There might be multiple duplicate plist files with the same name in different locations.

Make sure that you only have the main modified file in:
/Library/Preferences

Then make a backup and remove duplicate displays plist files from these locations (if any):
~/Library/Preferences
or
/Users/username/Library/Preferences
and
/Users/username/Library/Preferences/ByHost


Please note that you'll need to have administrator privileges in order to modify the file in /Library/Preferences. Thanks goes to @keegandent and @StrategicalIT for pointing this out.

Updates regarding macOS Monterey

USB-C to DisplayPort
From what I've seen, it seems that macOS Monterey 12.0.1 finally outputs RGB color by default on some monitors when using USB-C to DisplayPort cable on M1 Apple Silicone Macs.

You might need to make a backup and delete these 2 files:
/Library/Preferences/com.apple.windowserver.displays.plist
and
/Users/yourname/Library/Preferences/ByHost/com.apple.windowserver.displays.[UDID].plist

Restart your Mac and it should properly output RGB color on the monitor on the next boot.

HDMI to HDMI
The situation with HDMI seems to got a bit more complicated. Now the whole section for the LinkDescription might be missing from the com.apple.windowserver.displays.plist on a clean install and doesn't seem to be recreated when rotating the screen either.

Luckily, the solution still works, but you might need to manually add this whole section in the displays plist file:

					<key>LinkDescription</key>
					<dict>
						<key>BitDepth</key>
						<integer>8</integer>
						<key>EOTF</key>
						<integer>0</integer>
						<key>PixelEncoding</key>
						<integer>0</integer>
						<key>Range</key>
						<integer>1</integer>
					</dict>



The section usually goes right under the CurrentInfo key, and it should look something like this:

pixelencoding

This should get your RGB color output working on M1 Mac mini, even when connected with HDMI to HDMI cable.

Multiple monitors when one them is using HDMI to HDMI
Additional thanks goes to @somogyi-ede who tested this with multiple monitors and confirmed that the LinkDescription key needs to be added under each monitor instance in order for all of them to receive RGB color output. Link to the comment

Updates regarding macOS 13 Ventura

USB-C to DisplayPort
The macOS 13 Ventura beta seems to outputs RGB color by default on some monitors when using USB-C to DisplayPort cable on M1 Apple Silicone Macs.

You might need to make a backup and delete these 2 files:
/Library/Preferences/com.apple.windowserver.displays.plist
and
/Users/yourname/Library/Preferences/ByHost/com.apple.windowserver.displays.[UDID].plist

Restart your Mac and it should properly output RGB color on the monitor on the next boot.

HDMI to HDMI
Similar as macOS Monterey, the situation with HDMI on macOS Venturs seems a bit more complicated. Usually the whole section for the LinkDescription might be missing from the com.apple.windowserver.displays.plist on a clean install and doesn't seem to be recreated when rotating the screen either.

Luckily, the solution still works, and you still need to manually add this whole section in the displays plist file:

					<key>LinkDescription</key>
					<dict>
						<key>BitDepth</key>
						<integer>8</integer>
						<key>EOTF</key>
						<integer>0</integer>
						<key>PixelEncoding</key>
						<integer>0</integer>
						<key>Range</key>
						<integer>1</integer>
					</dict>



The section usually goes right under the CurrentInfo key, and it should look something like this:

pixelencoding

This should get your RGB color output working on M1 Mac mini, even when connected with HDMI to HDMI cable.

(Optional) Lock the plist file and set it as stationary
After the macOS Ventura 13.3 update, the plist file seems to get overwritten on reboot.

After you make the edits in the file, you can try setting the file /Library/Preferences/com.apple.windowserver.displays.plist as Stationery pad and Locked, so that it doesn't get overwritten on every reboot

Stationery Pad Locked

To do this, right click on the plist file, click on Get Info and check the boxes next to Stationery pad and Locked

This requires further testing and might cause some issues, like not being able to remember new resolutions or display settings. Please note that you're making any changes at your own risk.

Updates regarding macOS 14 Sonoma Beta

USB-C to DisplayPort
The macOS 14 Sonoma seems to outputs RGB color by default when using USB-C to DisplayPort cable.

HDMI to HDMI
The macOS 14 Sonoma seems to outputs YCbCr color by default when using HDMI to HDMI cable.

  • Forcing RGB Color Output still seems to work with the original procedure of modifying the plist files

  • Modifying the display plist files still works with the alternative version

  • After the plist files are modified, putting the Mac to sleep and waking it, it seem to keep the RGB Color output (this seems to be fixed at least on a M1 Mac mini)

If you have any additional questions, please feel free to contact me.

@GetVladimir
Copy link
Author

@traderdude123 thanks for the info.

Yes, that might make sense, since the HDMI on the Mac might not have the bandwidth required for 10 bit RGB

@traderdude123
Copy link

@GetVladimir

But the hdmi-hdmi cable had bandwidth for 10b YCBCR444, isnt that enough bandwidth for 10b RGB?

@GetVladimir
Copy link
Author

@traderdude123 No, that's actually one of the differences between RGB and YCbCr.

RGB carries the full info for each channel (Red, Green and Blue) and requires more bandwidth, while YCbCr is usually compressed

@traderdude123
Copy link

@GetVladimir

So you are saying YCBCR444 is compressed?

@GetVladimir
Copy link
Author

@traderdude123 Yes, at least on macOS.

That's why the Pixel Encoding key in the plist is set to 1 when using YCbCr.

When using RGB, the Pixel Encoding is set to 0

@traderdude123
Copy link

@GetVladimir

Hmm, thats interesting. This is first time i heard that YCBCR444 is compressed.

I thought YCBCR422 or 420 was compressed and 444 was uncompressed. But in macOS even ycbcr444 is compressed.

But is this the case in windows also?

@GetVladimir
Copy link
Author

@traderdude123 Do you think perhaps macOS uses 4:2:2 instead of 4:4:4 YCbCr when the Pixel Encoding is set to 1?

How does it show on the On Screen Display menu of the TV/Monitor when you set it to 1?

@traderdude123
Copy link

@GetVladimir

Also , i was able to get 10b RGB on hdmi-hdmi with BetterDisplay when i had the trial.

So i m sure the hdmi cable can do 10b RGB.

@GetVladimir
Copy link
Author

GetVladimir commented Apr 14, 2023

@traderdude123 does your Mac have HDMI 2.1 or 2.0 port?

As far as I know, there isn't a way to realistically get 10-bit RGB 4K over HDMI 2.0 connection.

@traderdude123
Copy link

@GetVladimir

M2 Mac mini with hdmi 2.1

@GetVladimir
Copy link
Author

@traderdude123 Then the bandwidth limitations doesn't apply to you.

HDMI 2.1 theoretically has 48Gbps in bandwidth (compared to 18Gbps of HDMI 2.0), so it can handle 10-bit RGB at 4K.

I haven't tested this myself though, since my M1 Mac mini has HDMI 2.0.

@traderdude123
Copy link

@GetVladimir

ahh ic.

Ok , so let me know what i need to test to get 10b RGB over hdmi-hdmi.

I was playing around with both the cables yesterday and i somehow got 10b RGB 4k over hdmi-hdmi.

But now what i suspect is RGB colors are different from hdmi 2.1 port and usb-c port. Because even if we run at 8b RGB over hdmi, the auto black level should set it to high, but its setting it to low. which means there is a signal difference between hdmi 2.1 port and usb-c port

Also there is color differences coming for the same RGB signal coming from hdmi 2.1 port and usb-c.

Why couldn't apple just provide a simple switch for RGB and YCBCR, i will never know. when they clearly know they are selling mac mini and till today no way to configure external displays correctly like in windows.

@GetVladimir
Copy link
Author

@traderdude123 Maybe the USB-C adapter that you have does some kind of active conversion to HDMI, that might be the reason why it gets hot as well.

At the moment, I don't know of any other way to activate the 10 bit RGB color except with the plist files.

And you're right, all this would be so much easier if the setting to choose RGB color and range was added by Apple in the System Settings.

@traderdude123
Copy link

@GetVladimir

Can you test on your monitor or TV if RGB either 8b or 10b coming from hdmi and usb-c port are same or different?

Try testing some random images.

Let me know , because now this is another new issue i think we will face.

I just want to know if its just my particular TV or this issue is in general affecting all m1/m2 mac minis.

@GetVladimir
Copy link
Author

@traderdude123 Yes, of course. I have an USB-C to DisplayPort connection and also HDMI-to-HDMI connection.

I can confirm that both of these connections output the same when using RGB color output on my monitor.

On my TV, I can test only HDMI-to-HDMI, but I don't have any USB-C to HDMI adapters, and the TV only accepts HDMI.

My guess is the adapter might be causing the discrepancy.

At the moment, I can't test 10-bit on my Monitor, as neither the Monitor or the M1 Mac mini HDMI port supports it.

@traderdude123
Copy link

traderdude123 commented Apr 15, 2023

@GetVladimir

I got RGB 10b 4k over hdmi-hdmi.

This is another alternate way of getting there. Below are the steps. I almost feel bad for dev of BD.Below method is for users whos trial has expired for BD and do not want to pay for the license.

  1. Create a new user ( this is going to be temporary)
  2. Install BetterDisplay, you should now get 14-day trial.
  3. Extract EDID using BD.
  4. Install AW Editor to modify EDID.
  5. Edit the EDID using AW Editor and remove all references to YCBCR and make EDID version 4.
  6. Upload the EDID using BetterDisplay. Steps 3-6 can be skipped if you already have a modified EDID and ready to upload.
  7. Now you should get RGB 10b for all users on your system.
  8. Switch to Original user, it should now have RGB. Reboot and login to original user to verify you have RGB 10b.
  9. Delete the temporary created user.
  10. Done.

Note: Do not go into sleep , you might lose RGB.

Coming back to RGB vs YCBCR differences.

The macOS is sending RGB Full(high) by default to the TV. if the TV is set to Auto black level it will set black level to high.This confirms that macOS is sending RGB Full and not Limited. Which is correct and this can be verified on lagom test Black levels page. I will refer to RGB Full as RGB High and RGB Limited as RGB Low.

In the lagom Black level test ,if RGB Low is set on TV, you can see that 1-15 Blacks will be too dark to see and that is correct. if you are seeing greys or even visible dark , then your monitor needs calibration.if RGB full is set on TV, you can and should see all blacks from 1-15.

However , Limited RGB(low) can give deeper blacks and better contrast and some users may prefer this.One use case for this is Coding on OLED Monitors/TV. for e.g. i do coding on Xcode and RGB limited(low) is much better as everything is deep dark on OLEDs. Also images looks better due to better contrast.

But when consuming videos , Limited RGB will make dark scenes very dark and Full RGB or better yet YCBCR444 is the best. you can compare this by running a video on your browser and check all three options 1. RGB High 2.RGB Low 3. YCBCR444. You can then choose your preference.

Edit: In summary , the weird thing is with Full RGB as source(macOS) and TV set to RGB Low, we lose the black and white details as they get crushed, but what we lose in some black/white details , we gain in color vibrancy and deeper blacks which some may enjoy for certain use cases. This is more so suitable for an OLED display. Please test and let me know what you all prefer. Another benefit is the text clarity is somewhat improved on RGB Low compared to RGB high/Full.

@domscr2
Copy link

domscr2 commented Apr 17, 2023

@GetVladimir just wanted to say thanks again for your support and engagement. Been subscribed to the gist in the event of changes such as the ones we've been having for the past month, been expecting issues and finally had them. Updated my 2020 M1 MacBook Pro to 13.3.1 and implemented the new manual fix and it's worked. Hopefully no more issues for a couple more months

@Strate
Copy link

Strate commented Apr 17, 2023

I realized, that RGB set only after I restart my monitor (power off and then power on).

@GetVladimir
Copy link
Author

@domscr2 thank you so much! I appreciate that and I'm glad to hear that the new manual fix works

@andreilica
Copy link

andreilica commented Apr 21, 2023

Hello @GetVladimir ! I have tried all of the methods suggested here (edit /Library/Preferences/ file, also ran those commands using the plist tool) and also in the comments (including EDID editing using BetterDisplay) and I cannot get my monitor to receive RGB signal at all (only YCbCr). System: MacBook Air M1 13", Display: Dell U2722D, connected the display to the laptop through HDMI using the Anker 555 (8 in 1) hub which supports 4k@60Hz on the HDMI Port. Am I missing something? What should I try to do next?

@GetVladimir
Copy link
Author

@andreilica thank you for your comment and I'm sorry to hear that.

Please try it with a direct connection between the MacBook and the monitor, with USB-C to DisplayPort cable if possible.

If that works, it might mean that the HDMI on the hub is not capable of outputting RGB color

@Strate
Copy link

Strate commented Apr 21, 2023

@andreilica hello, i've ran into same issues. Restarting monitor with power button helped. I use WavLink thunderbolt docking station

@andreilica
Copy link

@GetVladimir I currently don't have that type of cable available. The HUB is outputting RGB color to this monitor when hooked up to a Windows PC with USB-C Thunderbolt, so I don't think it's a hub issue. @Strate I have tried that multiple times after running the plist commands or editing the /Library/Preferences/ file with no success.

@GetVladimir
Copy link
Author

GetVladimir commented Apr 21, 2023

@andreilica thank you for the info that it works on a Windows PC. That means there might be a chance yet to make it work.

Please try again one more time by deleting both plist files and removing any other changes that you've done.

Then only apply the steps here: https://gist.github.com/GetVladimir/c89a26df1806001543bef4c8d90cc2f8#alternative-terminal-commands-to-force-rgb-color-output-on-m1-and-m2-based-macs-and-workaround-for-losing-rgb-color-after-waking-up-from-sleep

There is one catch though. In macOS 13.3.1, the plist files seem to be ignored when waking up from sleep. It only works after reboot.

If the hub does something similar to the connection like waking up from sleep every time is connected, macOS will not recognize it properly and output YCbCr color, even if you did everything correctly.

A temporary workaround might be to reboot the Mac after connecting the hub.

A more permanent solution would be either to use a separate USB-C to DisplayPort cable only for the monitor, or a future macOS update to fix the issue.

@andreilica
Copy link

andreilica commented Apr 21, 2023

After deleting the files, the commands won't work anymore as it doesn't find any file inside ByHost:
image

If I make any changes to the display settings the file appears and the commands can run. But after I run them and I restart, still no change. My display still shows YCbCr :(.

@GetVladimir
Copy link
Author

@andreilica thank you for the update.

It seems that the M1 just doesn't play nice with this hub, at least on this version of macOS.

The other suggestion I can make is to try with the USB-C to DisplayPort cable if possible

@csergiu
Copy link

csergiu commented Apr 25, 2023

So currently on Ventura 13.3.1 there is no way to get the monitor to stay in RGB after resuming from sleep? 😞

My setup: MBP 14" M1 w/ Dell P3421W w/ USB-C <-> USB-C

@GetVladimir
Copy link
Author

GetVladimir commented Apr 25, 2023

@csergiu yes, you'll need to reboot to fix it or prevent it to go to sleep.

Although, from the details of your specific setup, you can try using an USB-C to DisplayPort instead of USB-C to USB-C cable. That might fix the issue

@zhxst
Copy link

zhxst commented May 6, 2023

My MacBook is M1 and my external display was fine on Monterey. Updated to Ventura 13.3.1(a) yesterday and the display was ruined. The black turned into purple and the white turned into some kind of yellow. After some dig I found here.
So here is the result, the solution partially worked, but only in the login screen. After logged in, the external screen go black for half second, and it's purple and yellow again.
I use a hub and HDMI cable. Does things goes worse with the (a) patch? I don't know.
I don't know if it is because my display doesn't support YPbPr or Ventura changed something.

Thank you for your kindness and this article. At least I can confirm it's a YPbPr issue, and there is still hope to solve it.


BetterDisplay to force RGB works. Thanks to @traderdude123
Finally the screen not purple and yellow any more!

  • The options to get and set EDID is in the bottom of the menu with the gear button. Find your monitor under the Display tab.
  • Retrieve EDID Data and Export EDID binary.
  • Do edit the EDID binary with AW EDID Editor. It's free.
  • In the Version & Revision page, change Revision to 4.
  • Then you can turn off any YCrCb option in Feature Support page.
  • Check CEA Extension sector and turn off any YCrCb option.
  • Save the file.
  • Upload EDID Binary and Apply EDID.
  • remember to uncheck the Restore factory EDID on quit.

Does anybody know what does BetterDisplay do when upload and apply the EDID? Maybe there is a way to make it automatic.

@GetVladimir
Copy link
Author

@zhxst thank you for your comment.

You can try the new alternative method to fix RGB color output after login: https://gist.github.com/GetVladimir/c89a26df1806001543bef4c8d90cc2f8#alternative-terminal-commands-to-force-rgb-color-output-on-m1-and-m2-based-macs-and-workaround-for-losing-rgb-color-after-waking-up-from-sleep

The issues usually started with the later Ventura updates, but the (a) doesn't seem to make any difference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment