mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 16:18:12 +00:00
WindowServer: Support windows with alpha channels. And per-WSWindow opacity.
This patch also adds a Format concept to GraphicsBitmap. For now there are only two formats: RGB32 and RGBA32. Windows with alpha channel have their backing stores created in the RGBA32 format. Use this to make Terminal windows semi-transparent for that comfy rice look. There is one problem here, in that window compositing overdraw incurs multiple passes of blending of the same pixels. This leads to a mismatch in opacity which is obviously not good. I will work on this in a later patch. The alpha blending is currently straight C++. It should be relatively easy to optimize this using SSE instructions. For now I'm just happy with the cute effect. :^)
This commit is contained in:
parent
d4973842c9
commit
9b71307d49
25 changed files with 244 additions and 71 deletions
|
@ -144,8 +144,8 @@ WSWindowManager::WSWindowManager()
|
|||
(void)m_flush_count;
|
||||
#endif
|
||||
auto size = m_screen_rect.size();
|
||||
m_front_bitmap = GraphicsBitmap::create_wrapper(size, m_screen.scanline(0));
|
||||
m_back_bitmap = GraphicsBitmap::create_wrapper(size, m_screen.scanline(size.height()));
|
||||
m_front_bitmap = GraphicsBitmap::create_wrapper(GraphicsBitmap::Format::RGB32, size, m_screen.scanline(0));
|
||||
m_back_bitmap = GraphicsBitmap::create_wrapper(GraphicsBitmap::Format::RGB32, size, m_screen.scanline(size.height()));
|
||||
|
||||
m_front_painter = make<Painter>(*m_front_bitmap);
|
||||
m_back_painter = make<Painter>(*m_back_bitmap);
|
||||
|
@ -170,17 +170,17 @@ WSWindowManager::WSWindowManager()
|
|||
m_cursor_bitmap_outer = CharacterBitmap::create_from_ascii(cursor_bitmap_outer_ascii, 12, 17);
|
||||
|
||||
m_wallpaper_path = "/res/wallpapers/cool.rgb";
|
||||
m_wallpaper = GraphicsBitmap::load_from_file(m_wallpaper_path, { 1024, 768 });
|
||||
m_wallpaper = GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, m_wallpaper_path, { 1024, 768 });
|
||||
|
||||
#ifdef KERNEL
|
||||
ProcFS::the().add_sys_bool("wm_flash_flush", m_flash_flush);
|
||||
ProcFS::the().add_sys_string("wm_wallpaper", m_wallpaper_path, [this] {
|
||||
m_wallpaper = GraphicsBitmap::load_from_file(m_wallpaper_path, m_screen_rect.size());
|
||||
m_wallpaper = GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, m_wallpaper_path, m_screen_rect.size());
|
||||
invalidate(m_screen_rect);
|
||||
});
|
||||
#endif
|
||||
|
||||
m_menu_selection_color = Color(0x84351a);
|
||||
m_menu_selection_color = Color::from_rgb(0x84351a);
|
||||
|
||||
{
|
||||
byte system_menu_name[] = { 0xf8, 0 };
|
||||
|
@ -242,8 +242,8 @@ void WSWindowManager::set_resolution(int width, int height)
|
|||
return;
|
||||
m_screen.set_resolution(width, height);
|
||||
m_screen_rect = m_screen.rect();
|
||||
m_front_bitmap = GraphicsBitmap::create_wrapper({ width, height }, m_screen.scanline(0));
|
||||
m_back_bitmap = GraphicsBitmap::create_wrapper({ width, height }, m_screen.scanline(height));
|
||||
m_front_bitmap = GraphicsBitmap::create_wrapper(GraphicsBitmap::Format::RGB32, { width, height }, m_screen.scanline(0));
|
||||
m_back_bitmap = GraphicsBitmap::create_wrapper(GraphicsBitmap::Format::RGB32, { width, height }, m_screen.scanline(height));
|
||||
m_front_painter = make<Painter>(*m_front_bitmap);
|
||||
m_back_painter = make<Painter>(*m_back_bitmap);
|
||||
m_buffers_are_flipped = false;
|
||||
|
@ -620,10 +620,17 @@ void WSWindowManager::compose()
|
|||
dbgprintf("[WM] compose #%u (%u rects)\n", ++m_compose_count, dirty_rects.size());
|
||||
#endif
|
||||
|
||||
auto any_window_contains_rect = [this] (const Rect& r) {
|
||||
auto any_opaque_window_contains_rect = [this] (const Rect& r) {
|
||||
for (auto* window = m_windows_in_order.head(); window; window = window->next()) {
|
||||
if (!window->is_visible())
|
||||
continue;
|
||||
if (window->opacity() < 1.0f)
|
||||
continue;
|
||||
if (window->has_alpha_channel()) {
|
||||
// FIXME: Just because the window has an alpha channel doesn't mean it's not opaque.
|
||||
// Maybe there's some way we could know this?
|
||||
continue;
|
||||
}
|
||||
if (outer_window_rect(window->rect()).contains(r))
|
||||
return true;
|
||||
}
|
||||
|
@ -640,9 +647,8 @@ void WSWindowManager::compose()
|
|||
};
|
||||
|
||||
for (auto& dirty_rect : dirty_rects) {
|
||||
if (any_window_contains_rect(dirty_rect)) {
|
||||
if (any_opaque_window_contains_rect(dirty_rect))
|
||||
continue;
|
||||
}
|
||||
if (!m_wallpaper)
|
||||
m_back_painter->fill_rect(dirty_rect, m_background_color);
|
||||
else
|
||||
|
@ -665,7 +671,10 @@ void WSWindowManager::compose()
|
|||
dirty_rect_in_window_coordinates.set_y(dirty_rect_in_window_coordinates.y() - window.y());
|
||||
auto dst = window.position();
|
||||
dst.move_by(dirty_rect_in_window_coordinates.location());
|
||||
m_back_painter->blit(dst, *backing, dirty_rect_in_window_coordinates);
|
||||
if (window.opacity() == 1.0f)
|
||||
m_back_painter->blit(dst, *backing, dirty_rect_in_window_coordinates);
|
||||
else
|
||||
m_back_painter->blit_with_opacity(dst, *backing, dirty_rect_in_window_coordinates, window.opacity());
|
||||
m_back_painter->clear_clip_rect();
|
||||
}
|
||||
m_back_painter->clear_clip_rect();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue