X11: Fix launcher appearing completely corrupted when visual depth is not 24/32 bit depth

This commit is contained in:
UnknownShadow200 2022-01-15 00:41:14 +11:00
parent 2502f3fe41
commit 3ef9938aa9
2 changed files with 82 additions and 9 deletions

View File

@ -968,16 +968,86 @@ static void ShowDialogCore(const char* title, const char* msg) {
static GC fb_gc;
static XImage* fb_image;
static struct Bitmap fb_bmp;
static void* fb_data;
static int fb_fast;
static int fb_rShift, fb_gShift, fb_bShift;
static int fb_rOffset, fb_gOffset, fb_bOffset;
static int CountSetBits(cc_uint32 i) {
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
i = (i + (i >> 4)) & 0x0F0F0F0F;
return (i * 0x01010101) >> 24;
}
/* Calculates adjustments from 24 bit depth to depth of window visual */
static void CalcRGBAdjustments(void) {
int rBits = CountSetBits(win_visual.red_mask);
int gBits = CountSetBits(win_visual.green_mask);
int bBits = CountSetBits(win_visual.blue_mask);
/* e.g. for 8 bits to 6 bits, need to drop 2 lowest bits */
fb_bShift = 8 - rBits;
fb_gShift = 8 - gBits;
fb_rShift = 8 - bBits;
fb_bOffset = 0;
fb_gOffset = bBits;
fb_rOffset = bBits + gBits;
}
void Window_AllocFramebuffer(struct Bitmap* bmp) {
if (!fb_gc) fb_gc = XCreateGC(win_display, win_handle, 0, NULL);
bmp->scan0 = (BitmapCol*)Mem_Alloc(bmp->width * bmp->height, 4, "window pixels");
fb_image = XCreateImage(win_display, win_visual.visual,
win_visual.depth, ZPixmap, 0, (char*)bmp->scan0,
/* X11 requires that the image to draw has same depth as window */
/* Easy for 24/32 bit case, but much trickier with other depths */
/* (have to do a manual and slow second blit for other depths) */
fb_fast = win_visual.depth == 24 || win_visual.depth == 32;
fb_data = fb_fast ? bmp->scan0 : Mem_Alloc(bmp->width * bmp->height, 4, "window blit");
CalcRGBAdjustments();
fb_bmp = *bmp;
fb_image = XCreateImage(win_display, win_visual.visual,
win_visual.depth, ZPixmap, 0, fb_data,
bmp->width, bmp->height, 32, 0);
}
static void BlitFramebuffer(int x1, int y1, int width, int height) {
unsigned long pixel;
BitmapCol src;
int x, y;
for (y = y1; y < y1 + height; y++) {
BitmapCol* row = Bitmap_GetRow(&fb_bmp, y);
for (x = x1; x < x1 + width; x++) {
src = row[x];
/* e.g. for 24 to 16 bit depth (R5 G5 B5): */
/* B is shifted right 3 bits, then shifted left 0 bits */
/* G is shifted right 2 bits, then shifted left 5 bits */
/* R is shifted right 3 bits, then shifted left 6+5 bits */
/* Visually explained
/* rrrrrrrr:gggggggg:bbbbbbbb */
/* ||||| |||||| :|||||
/* rrrrr gggggg :bbbbb */
/* \\\\\ \\\\\\ |||||
/* rrrrrggg:gggbbbbb*/
pixel =
((BitmapCol_R(src) >> fb_rShift) << fb_rOffset) |
((BitmapCol_G(src) >> fb_gShift) << fb_gOffset) |
((BitmapCol_B(src) >> fb_bShift) << fb_bOffset);
XPutPixel(fb_image, x, y, pixel);
}
}
}
void Window_DrawFramebuffer(Rect2D r) {
/* Convert 32 bit depth to window depth when required */
if (!fb_fast) BlitFramebuffer(r.X, r.Y, r.Width, r.Height);
XPutImage(win_display, win_handle, fb_gc, fb_image,
r.X, r.Y, r.X, r.Y, r.Width, r.Height);
}
@ -985,6 +1055,7 @@ void Window_DrawFramebuffer(Rect2D r) {
void Window_FreeFramebuffer(struct Bitmap* bmp) {
XFree(fb_image);
Mem_Free(bmp->scan0);
if (bmp->scan0 != fb_data) Mem_Free(fb_data);
}
void Window_OpenKeyboard(const struct OpenKeyboardArgs* args) { }

View File

@ -79,17 +79,19 @@ static void InitGraphicsMode(struct GraphicsMode* m) {
m->A = 0;
switch (bpp) {
case 32:
m->R = 8; m->G = 8; m->B = 8; m->A = 8; break;
m->R = 8; m->G = 8; m->B = 8; m->A = 8; break;
case 30:
m->R = 10; m->G = 10; m->B = 10; m->A = 2; break;
case 24:
m->R = 8; m->G = 8; m->B = 8; break;
m->R = 8; m->G = 8; m->B = 8; break;
case 16:
m->R = 5; m->G = 6; m->B = 5; break;
m->R = 5; m->G = 6; m->B = 5; break;
case 15:
m->R = 5; m->G = 5; m->B = 5; break;
m->R = 5; m->G = 5; m->B = 5; break;
case 8:
m->R = 3; m->G = 3; m->B = 2; break;
m->R = 3; m->G = 3; m->B = 2; break;
case 4:
m->R = 2; m->G = 2; m->B = 1; break;
m->R = 2; m->G = 2; m->B = 1; break;
default:
/* mode->R = 0; mode->G = 0; mode->B = 0; */
Logger_Abort2(bpp, "Unsupported bits per pixel"); break;