kernel/interface: 30-bit RGB pixel format support

On Apple ARM platforms, iBoot sets up a 30-bit framebuffer

Change-Id: I6c03937303a3363fde511c8b8b7f8fd66a6a6965
Reviewed-on: https://review.haiku-os.org/c/haiku/+/11128
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Sam Roberts
2026-06-17 18:01:51 +00:00
committed by waddlesplash
parent a309dd6890
commit c216360337
13 changed files with 99 additions and 23 deletions
+3
View File
@@ -175,6 +175,7 @@ typedef enum {
B_RGB48 = 0x0011, // RGB RGB 16:16:16 B_RGB48 = 0x0011, // RGB RGB 16:16:16
B_RGB32 = 0x0008, // BGR- -RGB 8:8:8:8 B_RGB32 = 0x0008, // BGR- -RGB 8:8:8:8
B_RGBA32 = 0x2008, // BGRA ARGB 8:8:8:8 B_RGBA32 = 0x2008, // BGRA ARGB 8:8:8:8
B_RGB30 = 0x0009, // BGR- -RGB 2:10:10:10
B_RGB24 = 0x0003, // BGR RGB 8:8:8 B_RGB24 = 0x0003, // BGR RGB 8:8:8
B_RGB16 = 0x0005, // BGR RGB 5:6:5 B_RGB16 = 0x0005, // BGR RGB 5:6:5
B_RGB15 = 0x0010, // BGR- -RGB 1:5:5:5 B_RGB15 = 0x0010, // BGR- -RGB 1:5:5:5
@@ -188,6 +189,7 @@ typedef enum {
B_RGB48_BIG = 0x1011, // RGB RGB 16:16:16 B_RGB48_BIG = 0x1011, // RGB RGB 16:16:16
B_RGB32_BIG = 0x1008, // -RGB BGR- 8:8:8:8 B_RGB32_BIG = 0x1008, // -RGB BGR- 8:8:8:8
B_RGBA32_BIG = 0x3008, // ARGB BGRA 8:8:8:8 B_RGBA32_BIG = 0x3008, // ARGB BGRA 8:8:8:8
B_RGB30_BIG = 0x1009, // -RGB BGR- 10:10:10:2
B_RGB24_BIG = 0x1003, // RGB BGR 8:8:8 B_RGB24_BIG = 0x1003, // RGB BGR 8:8:8
B_RGB16_BIG = 0x1005, // RGB BGR 5:6:5 B_RGB16_BIG = 0x1005, // RGB BGR 5:6:5
B_RGB15_BIG = 0x1010, // -RGB BGR- 5:5:5:1 B_RGB15_BIG = 0x1010, // -RGB BGR- 5:5:5:1
@@ -198,6 +200,7 @@ typedef enum {
B_RGB48_LITTLE = B_RGB48, B_RGB48_LITTLE = B_RGB48,
B_RGB32_LITTLE = B_RGB32, B_RGB32_LITTLE = B_RGB32,
B_RGBA32_LITTLE = B_RGBA32, B_RGBA32_LITTLE = B_RGBA32,
B_RGB30_LITTLE = B_RGB30,
B_RGB24_LITTLE = B_RGB24, B_RGB24_LITTLE = B_RGB24,
B_RGB16_LITTLE = B_RGB16, B_RGB16_LITTLE = B_RGB16,
B_RGB15_LITTLE = B_RGB15, B_RGB15_LITTLE = B_RGB15,
@@ -128,6 +128,32 @@ blit24(const BlitParameters& params)
} }
static void
blit30(const BlitParameters& params)
{
const uint8* data = params.from;
data += (params.fromWidth * params.fromTop + params.fromLeft) * 3;
uint32* start = (uint32*)(params.to
+ params.toBytesPerRow * params.toTop
+ 4 * params.toLeft);
for (int32 y = params.fromTop; y < params.fromBottom; y++) {
const uint8* src = data;
uint32* dst = start;
for (int32 x = params.fromLeft; x < params.fromRight; x++) {
dst[0] = (((src[2] * 1023) / 255) << 20)
| (((src[1] * 1023) / 255) << 10)
| ((src[0] * 1023) / 255);
dst++;
src += 3;
}
data += params.fromWidth * 3;
start = (uint32*)((addr_t)start + params.toBytesPerRow);
}
}
static void static void
blit32(const BlitParameters& params) blit32(const BlitParameters& params)
{ {
@@ -168,6 +194,9 @@ blit(const BlitParameters& params, int32 depth)
case 24: case 24:
blit24(params); blit24(params);
return; return;
case 30:
blit30(params);
return;
case 32: case 32:
blit32(params); blit32(params);
return; return;
@@ -39,6 +39,8 @@ get_color_space_for_depth(uint32 depth)
return B_RGB16; return B_RGB16;
case 24: case 24:
return B_RGB24; return B_RGB24;
case 30:
return B_RGB30;
case 32: case 32:
return B_RGB32; return B_RGB32;
} }
+1
View File
@@ -71,6 +71,7 @@ get_raw_bytes_per_row(color_space colorSpace, int32 width)
case B_CMY32: case B_CMYA32: case B_CMYK32: case B_CMY32: case B_CMYA32: case B_CMYK32:
bpr = 4 * width; bpr = 4 * width;
break; break;
case B_RGB30: case B_RGB30_BIG:
case B_RGB24: case B_RGB24_BIG: case B_RGB24: case B_RGB24_BIG:
case B_UVL24: case B_LAB24: case B_HSI24: case B_UVL24: case B_LAB24: case B_HSI24:
case B_HSV24: case B_HLS24: case B_CMY24: case B_HSV24: case B_HLS24: case B_CMY24:
@@ -73,6 +73,7 @@ get_pixel_size_for(color_space space, size_t *pixelChunk, size_t *rowAlignment,
case B_HSV32: case B_HSVA32: case B_HSV32: case B_HSVA32:
case B_HLS32: case B_HLSA32: case B_HLS32: case B_HLSA32:
case B_CMY32: case B_CMYA32: case B_CMYK32: case B_CMY32: case B_CMYA32: case B_CMYK32:
case B_RGB30: case B_RGB30_BIG:
bytesPerPixel = 4; bytesPerPixel = 4;
pixPerChunk = 1; pixPerChunk = 1;
break; break;
@@ -162,6 +163,7 @@ bitmaps_support_space(color_space space, uint32 *supportFlags)
case B_RGB48: case B_RGB48_BIG: case B_RGB48: case B_RGB48_BIG:
case B_RGB32: case B_RGBA32: case B_RGB24: case B_RGB32: case B_RGBA32: case B_RGB24:
case B_RGB32_BIG: case B_RGBA32_BIG: case B_RGB24_BIG: case B_RGB32_BIG: case B_RGBA32_BIG: case B_RGB24_BIG:
case B_RGB30: case B_RGB30_BIG:
case B_RGB16: case B_RGB15: case B_RGBA15: case B_RGB16: case B_RGB15: case B_RGBA15:
case B_RGB16_BIG: case B_RGB15_BIG: case B_RGBA15_BIG: case B_RGB16_BIG: case B_RGB15_BIG: case B_RGBA15_BIG:
case B_CMAP8: case B_GRAY8: case B_GRAY1: case B_CMAP8: case B_GRAY8: case B_GRAY1:
+1
View File
@@ -95,6 +95,7 @@ get_raw_bytes_per_row(color_space colorSpace, int32 width)
break; break;
case B_RGB32: case B_RGBA32: case B_RGB32: case B_RGBA32:
case B_RGB32_BIG: case B_RGBA32_BIG: case B_RGB32_BIG: case B_RGBA32_BIG:
case B_RGB30: case B_RGB30_BIG:
case B_UVL32: case B_UVLA32: case B_UVL32: case B_UVLA32:
case B_LAB32: case B_LABA32: case B_LAB32: case B_LABA32:
case B_HSI32: case B_HSIA32: case B_HSI32: case B_HSIA32:
+1
View File
@@ -232,6 +232,7 @@ bitmaps_support_space(color_space space, uint32 *supportFlags)
// supported, but cannot draw // supported, but cannot draw
case B_RGBA64: case B_RGBA64_BIG: case B_RGBA64: case B_RGBA64_BIG:
case B_RGB48: case B_RGB48_BIG: case B_RGB48: case B_RGB48_BIG:
case B_RGB30: case B_RGB30_BIG:
case B_YCbCr422: case B_YCbCr411: case B_YCbCr444: case B_YCbCr420: case B_YCbCr422: case B_YCbCr411: case B_YCbCr444: case B_YCbCr420:
case B_YUV422: case B_YUV411: case B_YUV444: case B_YUV420: case B_YUV422: case B_YUV411: case B_YUV444: case B_YUV420:
case B_UVL24: case B_UVL32: case B_UVLA32: case B_UVL24: case B_UVL32: case B_UVLA32:
+2 -1
View File
@@ -130,7 +130,8 @@ int32
screen_mode::BitsPerPixel() const screen_mode::BitsPerPixel() const
{ {
switch (space) { switch (space) {
case B_RGB32: return 32; case B_RGB30: return 30;
case B_RGB32: return 24;
case B_RGB24: return 24; case B_RGB24: return 24;
case B_RGB16: return 16; case B_RGB16: return 16;
case B_RGB15: return 15; case B_RGB15: return 15;
+6 -7
View File
@@ -76,14 +76,14 @@ const char* kBackgroundsSignature = "application/x-vnd.Haiku-Backgrounds";
// list of officially supported colour spaces // list of officially supported colour spaces
static const struct { static const struct {
color_space space; color_space space;
int32 bits_per_pixel;
const char* label; const char* label;
} kColorSpaces[] = { } kColorSpaces[] = {
{ B_CMAP8, 8, B_TRANSLATE("8 bits/pixel, 256 colors") }, { B_CMAP8, B_TRANSLATE("8 bits/pixel, 256 colors") },
{ B_RGB15, 15, B_TRANSLATE("15 bits/pixel, 32768 colors") }, { B_RGB15, B_TRANSLATE("15 bits/pixel, 32768 colors") },
{ B_RGB16, 16, B_TRANSLATE("16 bits/pixel, 65536 colors") }, { B_RGB16, B_TRANSLATE("16 bits/pixel, 65536 colors") },
{ B_RGB24, 24, B_TRANSLATE("24 bits/pixel, 16 Million colors") }, { B_RGB24, B_TRANSLATE("24 bits/pixel, 16 million colors") },
{ B_RGB32, 32, B_TRANSLATE("32 bits/pixel, 16 Million colors") } { B_RGB32, B_TRANSLATE("24 bits/pixel, 16 million colors") },
{ B_RGB30, B_TRANSLATE("30 bits/pixel, 1 billion colors") }
}; };
static const int32 kColorSpaceCount = B_COUNT_OF(kColorSpaces); static const int32 kColorSpaceCount = B_COUNT_OF(kColorSpaces);
@@ -396,7 +396,6 @@ ScreenWindow::ScreenWindow(ScreenSettings* settings)
continue; continue;
BMessage* message = new BMessage(POP_COLORS_MSG); BMessage* message = new BMessage(POP_COLORS_MSG);
message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel);
message->AddInt32("space", kColorSpaces[i].space); message->AddInt32("space", kColorSpaces[i].space);
BMenuItem* item = new BMenuItem(kColorSpaces[i].label, message); BMenuItem* item = new BMenuItem(kColorSpaces[i].label, message);
+21
View File
@@ -650,6 +650,27 @@ HWInterface::_CopyToFront(uint8* src, uint32 srcBPR, int32 x, int32 y,
break; break;
} }
case B_RGB30:
{
dst += y * dstBPR + x * 4;
for (; y <= bottom; y++) {
uint32* srcHandle = (uint32*)dst;
uint32* dstHandle = (uint32*)src;
for (int32 left = x; left <= right; left++, srcHandle++, dstHandle++) {
uint32 r = (*dstHandle) & 0xff;
uint32 g = (*dstHandle >> 8) & 0xff;
uint32 b = (*dstHandle >> 16) & 0xff;
*srcHandle = ((r * 1023) / 255)
| (((g * 1023) / 255) << 10)
| (((b * 1023) / 255) << 20);
}
src += srcBPR;
dst += dstBPR;
}
break;
}
case B_RGB24: case B_RGB24:
{ {
// offset to left top pixel in dest buffer // offset to left top pixel in dest buffer
+16 -12
View File
@@ -177,9 +177,10 @@ platform_init_video(void)
TRACE(("looking for best graphics mode...\n")); TRACE(("looking for best graphics mode...\n"));
size_t depth = 0, bytes_per_row = 0;
efi_graphics_output_mode_information *info = NULL;
for (size_t mode = 0; mode < sGraphicsOutput->Mode->MaxMode; ++mode) { for (size_t mode = 0; mode < sGraphicsOutput->Mode->MaxMode; ++mode) {
efi_graphics_output_mode_information *info; size_t size;
size_t size, depth;
sGraphicsOutput->QueryMode(sGraphicsOutput, mode, &size, &info); sGraphicsOutput->QueryMode(sGraphicsOutput, mode, &size, &info);
size_t area = info->HorizontalResolution * info->VerticalResolution; size_t area = info->HorizontalResolution * info->VerticalResolution;
TRACE((" mode: %lu\n", mode)); TRACE((" mode: %lu\n", mode));
@@ -191,6 +192,12 @@ platform_init_video(void)
} else if (info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) { } else if (info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
// seen this in the wild, but acts like RGB, go figure... // seen this in the wild, but acts like RGB, go figure...
depth = 32; depth = 32;
} else if (info->PixelFormat == PixelBitMask
&& info->PixelInformation.RedMask == 0x3FF00000
&& info->PixelInformation.GreenMask == 0x000FFC00
&& info->PixelInformation.BlueMask == 0x000003FF
&& info->PixelInformation.ReservedMask == 0xC0000000) {
depth = 30;
} else if (info->PixelFormat == PixelBitMask } else if (info->PixelFormat == PixelBitMask
&& info->PixelInformation.RedMask == 0xFF0000 && info->PixelInformation.RedMask == 0xFF0000
&& info->PixelInformation.GreenMask == 0x00FF00 && info->PixelInformation.GreenMask == 0x00FF00
@@ -210,13 +217,15 @@ platform_init_video(void)
} }
TRACE((" depth: %lu\n", depth)); TRACE((" depth: %lu\n", depth));
bytes_per_row = info->PixelsPerScanLine * ((depth + 7) / 8);
video_mode *videoMode = (video_mode*)malloc(sizeof(struct video_mode)); video_mode *videoMode = (video_mode*)malloc(sizeof(struct video_mode));
if (videoMode != NULL) { if (videoMode != NULL) {
videoMode->mode = mode; videoMode->mode = mode;
videoMode->width = info->HorizontalResolution; videoMode->width = info->HorizontalResolution;
videoMode->height = info->VerticalResolution; videoMode->height = info->VerticalResolution;
videoMode->bits_per_pixel = depth; videoMode->bits_per_pixel = depth;
videoMode->bytes_per_row = info->PixelsPerScanLine * depth / 8; videoMode->bytes_per_row = bytes_per_row;
add_video_mode(videoMode); add_video_mode(videoMode);
} }
@@ -237,6 +246,10 @@ platform_init_video(void)
} }
gKernelArgs.frame_buffer.enabled = true; gKernelArgs.frame_buffer.enabled = true;
gKernelArgs.frame_buffer.depth = depth;
gKernelArgs.frame_buffer.width = info->HorizontalResolution;
gKernelArgs.frame_buffer.height = info->VerticalResolution;
gKernelArgs.frame_buffer.bytes_per_row = bytes_per_row;
sModeChosen = false; sModeChosen = false;
sSettingsLoaded = false; sSettingsLoaded = false;
@@ -268,15 +281,6 @@ platform_switch_to_logo(void)
sGraphicsOutput->Mode->FrameBufferBase; sGraphicsOutput->Mode->FrameBufferBase;
gKernelArgs.frame_buffer.physical_buffer.size = gKernelArgs.frame_buffer.physical_buffer.size =
sGraphicsOutput->Mode->FrameBufferSize; sGraphicsOutput->Mode->FrameBufferSize;
gKernelArgs.frame_buffer.width =
sGraphicsOutput->Mode->Info->HorizontalResolution;
gKernelArgs.frame_buffer.height =
sGraphicsOutput->Mode->Info->VerticalResolution;
gKernelArgs.frame_buffer.depth =
sGraphicsOutput->Mode->Info->PixelFormat == PixelBitMask ? 24 : 32;
gKernelArgs.frame_buffer.bytes_per_row =
sGraphicsOutput->Mode->Info->PixelsPerScanLine
* gKernelArgs.frame_buffer.depth / 8;
video_display_splash(gKernelArgs.frame_buffer.physical_buffer.start); video_display_splash(gKernelArgs.frame_buffer.physical_buffer.start);
} }
@@ -78,8 +78,7 @@ static uint16 sPalette16[] = {
// bbbbbggggggrrrrr (5-6-5) // bbbbbggggggrrrrr (5-6-5)
0xffff, 0x3333, 0x4cc0, 0x04d3, 0xc800, 0x722f, 0xdd40, 0x0000, 0xffff, 0x3333, 0x4cc0, 0x04d3, 0xc800, 0x722f, 0xdd40, 0x0000,
}; };
static uint32 sPalette32[] = { static uint32 sPalette24[] = {
// is also used by 24 bit modes
0xffffff, // white 0xffffff, // white
0x336698, // blue 0x336698, // blue
0x4e9a00, // green 0x4e9a00, // green
@@ -89,6 +88,16 @@ static uint32 sPalette32[] = {
0xdaa800, // yellow 0xdaa800, // yellow
0x000000, // black 0x000000, // black
}; };
static uint32 sPalette30[] = {
0x3fcff3fc, // white
0x0cc66260, // blue
0x1389a000, // green
0x01898268, // cyan
0x33000000, // red
0x1cc441ec, // magenta
0x368a8000, // yellow
0x00000000, // black
};
static struct console_info sConsole; static struct console_info sConsole;
@@ -122,8 +131,10 @@ get_palette_entry(uint8 index)
return (uint8*)&sPalette15[index]; return (uint8*)&sPalette15[index];
case 16: case 16:
return (uint8*)&sPalette16[index]; return (uint8*)&sPalette16[index];
case 30:
return (uint8*)&sPalette30[index];
default: default:
return (uint8*)&sPalette32[index]; return (uint8*)&sPalette24[index];
} }
} }
@@ -49,6 +49,7 @@ get_bytes_per_row(color_space colorSpace, int32 width)
case B_HSV32: case B_HSVA32: case B_HSV32: case B_HSVA32:
case B_HLS32: case B_HLSA32: case B_HLS32: case B_HLSA32:
case B_CMY32: case B_CMYA32: case B_CMYK32: case B_CMY32: case B_CMYA32: case B_CMYK32:
case B_RGB30: case B_RGB30_BIG:
bpr = 4 * width; bpr = 4 * width;
break; break;
case B_RGB24: case B_RGB24_BIG: case B_RGB24: case B_RGB24_BIG: