Warn­ing! Your devicePixelRatio is not 1 (or your brows­er doesn't CSS me­dia queries, in which case you can prob­a­bly ig­nore this warn­ing)! Since HTML is as brain­dead as it can get, cre­at­ing sites out­side of di­ver­si­ty hires cor­po­rate art sphere is damn near im­pos­si­ble, so this site is not re­al­ly op­ti­mized for HiDPI screens. Some im­ages might ap­pear blur­ry.

Upscaling things on X11

Cre­at­ed: 1665454425 (2022-10-11T02:13:45Z), 1544 words, ~6 min­utes

Tags: , ,

Sit­u­a­tion: you have some old game that on­ly runs at 320x240 or some­thing like that, and it looks very bad on your full-HD mon­i­tor. Or you were re­tard­ed enough to buy a meme 4k/8k mon­i­tor, and you can't run your game with ac­cept­able speed on your toast­er. Since I on­ly have a full-HD mon­i­tor, I will fo­cus on the first use­case, but there might be some use­ful here for the sec­ond use­case too.

Emulators#

If you're run­ning the game in some kind of em­u­la­tor, and the em­u­la­tor has an op­tion to up­scale the graph­ics, use it. Re­al­ly. Yes, this means sep­a­rate set­up for each em­u­la­tor, but it's still much less pain than any­thing else in this guide.

If you're not so lucky, ei­ther be­cause you're run­ning some na­tive Lin­ux game or you're run­ning some old Win­dows game in wine, con­tin­ue read­ing.

Glide games#

This is part­ly the em­u­la­tors cat­e­go­ry, but if you're us­ing a nglide or dgvoodoo 2 (un­der wine), you can force a res­o­lu­tion in their set­tings pan­el, and the game will be up­scaled to that res­o­lu­tion au­to­mat­i­cal­ly. As a bonus, this will cause 3D geom­e­try to be ren­dered at high­er res­o­lu­tion, which usu­al­ly means much bet­ter re­sults than just up­scal­ing the fi­nal im­age in 3D games.

xrandr#

The first op­tion is us­ing xrandr and it's scale op­tion. First run xrandr -q to get a list of out­puts, then you can run some­thing like this:

xrandr --output DVI-D-0 --scale 0.5x0.5 --filter nearest

Re­place DVI-D-0 with the ac­tu­al name of your out­put. This will halve your "vir­tu­al" res­o­lu­tion's width and height while the de­vice will stay at the old res­o­lu­tion, so your mon­i­tor will get a x2 scale. You can use --scale 0.25x0.25 to get a x4 scale, etc.

Pros: no ex­tra tools need­ed, works with every card (at least I test­ed with Nvidia, AMD, In­tel), and min­i­mal over­head.

Cons: oh, well. First, you'll have to get your game in­to win­dowed mode, be­cause if the game it­self tries to change res­o­lu­tion, all hell will break loose. Sec­ond, it fucks up your mon­i­tor res­o­lu­tion un­til you re­store it with --scale 1x1, an­noy­ing if you want to check some­thing quick­ly in an­oth­er app. But the re­al clus­ter­fuck is if you have mul­ti­ple mon­i­tors. First, us­ing things like --right-of and friends will break, be­cause xrandr will use the non-scaled res­o­lu­tion when po­si­tion­ing, which means that if, for ex­am­ple, you have a 1920x1200 mon­i­tor but scaled to 960x600, and you use --right-of to put a 1920x1200 (not scaled) mon­i­tor to the right, xrandr will place it at +1920+0, and you will have a 960 pix­el wide dead area be­tween your two mon­i­tors. You have to use --pos 960x0 to place your mon­i­tor to a more sane place, but of course that will break when you switch back to your orig­i­nal res­o­lu­tion. What's worse, if you do this, from the right mon­i­tor you can on­ly move your cur­sor to the left in the up­per half of the screen, be­cause at the low­er half, there's "noth­ing" (vir­tu­al­ly) to the left (that mon­i­tor is on­ly 600 pix­els height). In­ter­est­ing­ly if you leave a 1 pix­el dead area (i.e. use --pos 961x0), you can move your mouse in­to these in­vis­i­ble ar­eas, which I found much less an­noy­ing than ran­dom­ly hit­ting a wall with my mouse. Just don't be sur­prised if your cur­sor dis­ap­pears. Al­so, an­oth­er an­noy­ance, on your scaled mon­i­tor, your mouse speed will be faster (it has a con­stant speed per pix­el, but since on one of your mon­i­tor a pix­el is much big­ger, it will ap­pear to move faster).

So yes, it works, if you have noth­ing bet­ter, but it's an­noy­ing.

gamescope#

TL;DR A hyped garbage.

Gamescope calls it­self "the mi­cro-com­pos­i­tor for­mer­ly known as steam­comp­m­gr"—we al­ready have mar­ket­ing bull­shit and no re­al in­fo. Any­way what this does is cre­ate a way­land com­pos­i­tor with an Xway­land, then it will scale the app run­ning in­side the way­land to the size of the win­dow.

Pros: it au­to­mat­i­cal­ly re­sizes the game to the size of the win­dow you have, ef­fects are lo­cal to the win­dow (you don't have to fuck up your screen res­o­lu­tion). Your game runs in an iso­lat­ed X, so it won't fuck up your re­al X's res­o­lu­tion, cap­ture your mouse when you don't want it, etc.

Cons: for a long time it was AMD/In­tel on­ly (al­leged­ly, nvidia dri­vers 515.43.04+ are sup­port­ed, but these dri­vers do not sup­port my nvidia card, so I could nev­er try). If you get through that, the sec­ond thing you will no­tice that it's full of nig­ger de­pen­den­cies, like way­land, seatd... for­tu­nate­ly you can run it with­out sys­temd, but it's still a clus­ter­fuck. It has non-re­bind­able (well, un­less you ed­it the source) short­cuts that will con­flict with all the short­cuts your win­dow man­ag­er has. But the worst, this shit on­ly sup­ports a sin­gle win­dow. Yes, if your app opens more than one win­dow, it will just dis­play one in full screen. No Alt-Tab or any­thing. And since this is not nor­mal X, but some Xway­land pseu­do X abom­i­na­tion, you can't even start a win­dow man­ag­er in­side. If you have a Win­dows game, you can work around this by en­abling "em­u­late a vir­tu­al desk­top" in winecfg to get a Win­dows 3.1 lev­el win­dow man­ag­er, but oth­er­wise you're fucked. Ba­si­cal­ly use­less if you want to run a game with a text hook­er, for ex­am­ple. With 30 years of evo­lu­tion we man­aged to get back to the DOS times, where you could on­ly run one pro­gram at a time (TSR is not re­al mul­ti­task­ing), ex­cept with ridicu­lous­ly in­creased HW re­quire­ments.


This is what you prob­a­bly get as "work­ing" op­tions, if you search the net. Some peo­ple sug­gest­ed run­ning an Xvnc and con­nect­ing to it with a VNC client that sup­ports scal­ing, I haven't tried that, but I've tried xpra. For "of­fice" work, it might work, but for any games, there's just too much lag and too low FPS to be us­able, even when run­ning lo­cal­host.

Patching Xephyr#

There's Xe­phyr, which is an X serv­er that can be run in­side an X win­dow. Un­for­tu­nate­ly, it doesn't sup­port scal­ing out of the box. I think you could try run­ning Xe­phyr in­side gamescope, to get rid of the prob­lems, but when I tried to use this, I did not have a HW where I could try this out (well, maybe my shit­ty note­book, but I didn't want to play on it), so that was out of ques­tion.

Then I had an idea. How hard would it be to ed­it the source of Xe­phyr to up­scale the im­age? The an­swer: a few hours of mess­ing around with the code, with ze­ro pri­or knowl­edge about how Xorg in­ter­nals work. I orig­i­nal­ly pub­lished it as a patch file on some ob­scure im­age­boards, but now here is it in a "prop­er" git re­po: mir­ror a, mir­ror b. It's very rough, but it gets the job done.

Pros: it's a prop­er X serv­er, not that soy­lent X-like crap that comes with gamescope. You can run what­ev­er win­dow man­ag­er you want. Like gamescope, it's an iso­lat­ed X serv­er, so the game won't fuck up your nor­mal X serv­er.

Cons: this is a hack I once threw to­geth­er in a few hours and nev­er touched af­ter­wards. It re­ceived ze­ro op­ti­miza­tions. You have to re­com­pile it if you want a dif­fer­ent scale ra­tio. No HW ac­cel­er­a­tion. You will have GLX and OpenGL in­side Xe­phyr, but it will be a soft­ware im­ple­men­ta­tion (llvmpipe), it won't use your GPU. This is a Xe­phyr lim­i­ta­tion, that's un­for­tu­nate­ly not triv­ial to solve. Al­so, no clip­board syn­chro­niza­tion with your nor­mal X's clip­board, which can be a prob­lem if you want to use texthook­ers. But for­tu­nate­ly this is X, grab xclip­sync, and it just werks.

So yes, use it at your own risk. I've used this with Did­nap­per and 黄昏の境界, with­out prob­lems, but these two games don't even use HW ac­cel­er­a­tion as far as I can tell.

Future ideas#

Take we­st­on (or any oth­er way­land com­pos­i­tor that can run in an X win­dow and sup­ports Xway­land), and mod­i­fy it to up­scale the out­put. It's still over­com­pli­cat­ing things with way­land, but at least you would have a ba­sic win­dow man­ag­er, so it will work even if you would have more than one win­dow. Such fea­tures in 2022!

Run the whole shit in a VM. With things like vir­tio-gpu you might get de­cent per­for­mance, if you run a Lin­ux guest. But if you vir­tu­al­ize, and you have a Win­dows game, you're prob­a­bly bet­ter with run­ning a Win­dows in the VM. I've tried look­ing glass, but it had hor­ri­ble per­for­mance (but this is more like­ly the prob­lem of the mon­keys at AMD not be­ing able to write a fuck­ing func­tion­ing dri­ver, even obs-stu­dio shits it­self in­side the VM, while it works per­fect­ly on Lin­ux us­ing the open source dri­ver).

And while we're at VMs and GPU passthrough, I could start a sec­ond X serv­er on the sec­ond card when need­ed, then write a mi­ni VNC that dis­plays the con­tents of the sec­ond X serv­er on the first one (a very sim­ple PoC could be made with x0vncserver and a VNC client, but that would be high­ly in­ef­fi­cient). Like look­ing glass above, but be­tween two X servers, with­out a VM.

Maybe, one day, if I'll have too much free time.