diff options
-rw-r--r-- | Kernel/GUITypes.h | 7 | ||||
-rw-r--r-- | Kernel/Process.h | 2 | ||||
-rw-r--r-- | Kernel/ProcessGUI.cpp | 38 | ||||
-rw-r--r-- | Kernel/Syscall.cpp | 4 | ||||
-rw-r--r-- | Kernel/Syscall.h | 3 | ||||
-rw-r--r-- | LibC/Makefile | 5 | ||||
-rw-r--r-- | LibC/stdlib.cpp | 14 | ||||
-rw-r--r-- | LibC/stdlib.h | 4 | ||||
-rw-r--r-- | Userland/guitest.cpp | 33 | ||||
-rw-r--r-- | Widgets/Color.cpp | 10 | ||||
-rw-r--r-- | Widgets/GraphicsBitmap.cpp | 46 | ||||
-rw-r--r-- | Widgets/GraphicsBitmap.h | 17 | ||||
-rw-r--r-- | Widgets/Window.cpp | 2 |
13 files changed, 139 insertions, 46 deletions
diff --git a/Kernel/GUITypes.h b/Kernel/GUITypes.h index a5ff63a30f..490f2499f8 100644 --- a/Kernel/GUITypes.h +++ b/Kernel/GUITypes.h @@ -33,6 +33,13 @@ struct GUI_CreateWindowParameters { char title[128]; }; +struct GUI_WindowBackingStoreInfo { + GUI_Size size; + size_t bpp; + size_t pitch; + RGBA32* pixels; +}; + enum class GUI_MouseButton : unsigned char { NoButton = 0, Left = 1, diff --git a/Kernel/Process.h b/Kernel/Process.h index 5739cc0045..cff3df1d76 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -192,6 +192,8 @@ public: int gui$create_window(const GUI_CreateWindowParameters*); int gui$destroy_window(int window_id); + int gui$get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo*); + int gui$invalidate_window(int window_id); DisplayInfo get_display_info(); diff --git a/Kernel/ProcessGUI.cpp b/Kernel/ProcessGUI.cpp index c0049488bc..06ac5d64fd 100644 --- a/Kernel/ProcessGUI.cpp +++ b/Kernel/ProcessGUI.cpp @@ -25,8 +25,11 @@ void Process::initialize_gui_statics() int Process::make_window_id() { int new_id = m_next_window_id++; - while (!new_id || m_windows.contains(new_id)) + while (!new_id || m_windows.contains(new_id)) { new_id = m_next_window_id++; + if (new_id < 0) + new_id = 1; + } return new_id; } @@ -74,11 +77,40 @@ int Process::gui$destroy_window(int window_id) dbgprintf("%s<%u> gui$destroy_window (window_id=%d)\n", name().characters(), pid(), window_id); if (window_id < 0) return -EINVAL; - if (window_id >= static_cast<int>(m_windows.size())) - return -EBADWINDOW; auto it = m_windows.find(window_id); if (it == m_windows.end()) return -EBADWINDOW; m_windows.remove(window_id); return 0; } + +int Process::gui$get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo* info) +{ + dbgprintf("%s<%u> gui$get_window_backing_store (window_id=%d, info=%p)\n", name().characters(), pid(), window_id, info); + if (!validate_write_typed(info)) + return -EFAULT; + if (window_id < 0) + return -EINVAL; + auto it = m_windows.find(window_id); + if (it == m_windows.end()) + return -EBADWINDOW; + auto& window = *(*it).value; + info->bpp = sizeof(RGBA32); + info->pitch = window.backing()->pitch(); + info->size = window.backing()->size(); + info->pixels = reinterpret_cast<RGBA32*>(window.backing()->client_region()->linearAddress.asPtr()); + return 0; +} + +int Process::gui$invalidate_window(int window_id) +{ + dbgprintf("%s<%u> gui$invalidate_window (window_id=%d)\n", name().characters(), pid(), window_id); + if (window_id < 0) + return -EINVAL; + auto it = m_windows.find(window_id); + if (it == m_windows.end()) + return -EBADWINDOW; + auto& window = *(*it).value; + WindowManager::the().invalidate(window); + return 0; +} diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index a8b53db20d..df00742e51 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -191,6 +191,10 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2, return current->gui$create_window((const GUI_CreateWindowParameters*)arg1); case Syscall::SC_gui_destroy_window: return current->gui$destroy_window((int)arg1); + case Syscall::SC_gui_get_window_backing_store: + return current->gui$get_window_backing_store((int)arg1, (GUI_WindowBackingStoreInfo*)arg2); + case Syscall::SC_gui_invalidate_window: + return current->gui$invalidate_window((int)arg1); default: kprintf("<%u> int0x80: Unknown function %u requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3); break; diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index c6eab70007..9085724a92 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -68,6 +68,9 @@ __ENUMERATE_SYSCALL(sync) \ __ENUMERATE_SYSCALL(gui_create_window) \ __ENUMERATE_SYSCALL(gui_destroy_window) \ + __ENUMERATE_SYSCALL(gui_get_window_backing_store) \ + __ENUMERATE_SYSCALL(gui_invalidate_window) \ + namespace Syscall { diff --git a/LibC/Makefile b/LibC/Makefile index 55e182162f..122b314e2a 100644 --- a/LibC/Makefile +++ b/LibC/Makefile @@ -5,6 +5,9 @@ AK_OBJS = \ ../AK/FileSystemPath.o \ ../AK/kmalloc.o +WIDGETS_OBJS = \ + ../Widgets/Color.o + LIBC_OBJS = \ stdio.o \ unistd.o \ @@ -35,7 +38,7 @@ LIBC_OBJS = \ utime.o \ entry.o -OBJS = $(AK_OBJS) $(LIBC_OBJS) +OBJS = $(AK_OBJS) $(WIDGETS_OBJS) $(LIBC_OBJS) LIBRARY = LibC.a ARCH_FLAGS = diff --git a/LibC/stdlib.cpp b/LibC/stdlib.cpp index 1cb16f5a2f..deceb9f4e6 100644 --- a/LibC/stdlib.cpp +++ b/LibC/stdlib.cpp @@ -215,4 +215,18 @@ long atol(const char* str) return atoi(str); } + +static unsigned long s_next_rand = 1; + +int rand() +{ + s_next_rand = s_next_rand * 1103515245 + 12345; + return((unsigned)(s_next_rand/((RAND_MAX + 1) * 2)) % (RAND_MAX + 1)); +} + +void srand(unsigned seed) +{ + s_next_rand = seed; +} + } diff --git a/LibC/stdlib.h b/LibC/stdlib.h index c88d0ff597..29e5e4e66b 100644 --- a/LibC/stdlib.h +++ b/LibC/stdlib.h @@ -19,5 +19,9 @@ void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void *, co void exit(int status) __NORETURN; void abort() __NORETURN; +#define RAND_MAX 32767 +int rand(); +void srand(unsigned seed); + __END_DECLS diff --git a/Userland/guitest.cpp b/Userland/guitest.cpp index 48af3a9d24..c8341b6db8 100644 --- a/Userland/guitest.cpp +++ b/Userland/guitest.cpp @@ -7,6 +7,13 @@ #include <assert.h> #include <Kernel/GUITypes.h> #include <Kernel/Syscall.h> +#include <AK/StdLibExtras.h> + +int gui_invalidate_window(int window_id) +{ + int rc = syscall(SC_gui_invalidate_window, window_id); + __RETURN_WITH_ERRNO(rc, rc, -1); +} int main(int argc, char** argv) { @@ -26,6 +33,23 @@ int main(int argc, char** argv) return 1; } + GUI_WindowBackingStoreInfo backing; + int rc = syscall(SC_gui_get_window_backing_store, window_id, &backing); + if (rc < 0) { + perror("gui_get_window_backing_store"); + return 1; + } + + sys_printf("(Client) window backing %ux%u @ %p\n", backing.size.width, backing.size.height, backing.pixels); + + fast_dword_fill(backing.pixels, 0x00ff00, backing.size.width * backing.size.height); + + rc = gui_invalidate_window(window_id); + if (rc < 0) { + perror("gui_invalidate_window"); + return 1; + } + for (;;) { GUI_Event event; ssize_t nread = read(fd, &event, sizeof(event)); @@ -41,6 +65,15 @@ int main(int argc, char** argv) case GUI_Event::Type::MouseMove: sys_printf("WID=%x MouseMove %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break; } + if (event.type == GUI_Event::Type::MouseDown) { + byte r = rand() % 255; + byte g = rand() % 255; + byte b = rand() % 255; + Color color(r, g, b); + fast_dword_fill(backing.pixels, color.value(), backing.size.width * backing.size.height); + gui_invalidate_window(window_id); + } + } return 0; } diff --git a/Widgets/Color.cpp b/Widgets/Color.cpp index 9b81270108..7db2bd9dae 100644 --- a/Widgets/Color.cpp +++ b/Widgets/Color.cpp @@ -1,13 +1,9 @@ #include "Color.h" -#include "FrameBuffer.h" +#include <AK/Assertions.h> Color::Color(byte r, byte g, byte b) { -#ifdef USE_SDL - m_value = SDL_MapRGB(FrameBuffer::the().surface()->format, r, g, b); -#else m_value = (r << 16) | (g << 8) | b; -#endif } Color::Color(NamedColor named) @@ -32,9 +28,5 @@ Color::Color(NamedColor named) default: ASSERT_NOT_REACHED(); break; } -#ifdef USE_SDL - m_value = SDL_MapRGB(FrameBuffer::the().surface()->format, rgb.r, rgb.g, rgb.g); -#else m_value = (rgb.r << 16) | (rgb.g << 8) | rgb.b; -#endif } diff --git a/Widgets/GraphicsBitmap.cpp b/Widgets/GraphicsBitmap.cpp index 1a0a78feda..98fdb85b23 100644 --- a/Widgets/GraphicsBitmap.cpp +++ b/Widgets/GraphicsBitmap.cpp @@ -1,15 +1,12 @@ #include "GraphicsBitmap.h" #include "EventLoop.h" #include <AK/kmalloc.h> - -#ifdef SERENITY #include "Process.h" #include "MemoryManager.h" -#endif -RetainPtr<GraphicsBitmap> GraphicsBitmap::create(const Size& size) +RetainPtr<GraphicsBitmap> GraphicsBitmap::create(Process& process, const Size& size) { - return adopt(*new GraphicsBitmap(size)); + return adopt(*new GraphicsBitmap(process, size)); } RetainPtr<GraphicsBitmap> GraphicsBitmap::create_wrapper(const Size& size, RGBA32* data) @@ -17,39 +14,40 @@ RetainPtr<GraphicsBitmap> GraphicsBitmap::create_wrapper(const Size& size, RGBA3 return adopt(*new GraphicsBitmap(size, data)); } -GraphicsBitmap::GraphicsBitmap(const Size& size) +GraphicsBitmap::GraphicsBitmap(Process& process, const Size& size) : m_size(size) , m_pitch(size.width() * sizeof(RGBA32)) + , m_client_process(&process) { -#ifdef SERENITY - // FIXME: Oh god this is so horrible. - Process* server_process = EventLoop::main().running() ? &EventLoop::main().server_process() : current; - m_region = server_process->allocate_region(LinearAddress(), size.width() * size.height() * sizeof(RGBA32), "GraphicsBitmap", true, true, true); - m_data = (RGBA32*)m_region->linearAddress.asPtr(); - m_owned = false; -#else - m_data = static_cast<RGBA32*>(kmalloc(size.width() * size.height() * sizeof(RGBA32))); - memset(m_data, 0, size.width() * size.height() * sizeof(RGBA32)); - m_owned = true; -#endif + size_t size_in_bytes = size.width() * size.height() * sizeof(RGBA32); + auto vmo = VMObject::create_anonymous(size_in_bytes); + m_client_region = process.allocate_region_with_vmo(LinearAddress(), size_in_bytes, vmo.copyRef(), 0, "GraphicsBitmap (shared)", true, true); + m_client_region->commit(process); + + { + auto& server = EventLoop::main().server_process(); + ProcessInspectionHandle composer_handle(server); + m_server_region = server.allocate_region_with_vmo(LinearAddress(), size_in_bytes, move(vmo), 0, "GraphicsBitmap (shared)", true, true); + + process.dumpRegions(); + server.dumpRegions(); + } + m_data = (RGBA32*)m_server_region->linearAddress.asPtr(); } GraphicsBitmap::GraphicsBitmap(const Size& size, RGBA32* data) : m_size(size) , m_data(data) , m_pitch(size.width() * sizeof(RGBA32)) - , m_owned(false) { } GraphicsBitmap::~GraphicsBitmap() { -#ifdef SERENITY - if (m_region) - current->deallocate_region(*m_region); -#endif - if (m_owned) - kfree(m_data); + if (m_client_region) + m_client_process->deallocate_region(*m_client_region); + if (m_server_region) + EventLoop::main().server_process().deallocate_region(*m_server_region); m_data = nullptr; } diff --git a/Widgets/GraphicsBitmap.h b/Widgets/GraphicsBitmap.h index 92e8a485e4..f0f78175c3 100644 --- a/Widgets/GraphicsBitmap.h +++ b/Widgets/GraphicsBitmap.h @@ -4,12 +4,11 @@ #include "Size.h" #include <AK/Retainable.h> #include <AK/RetainPtr.h> - -class Region; +#include "Process.h" class GraphicsBitmap : public Retainable<GraphicsBitmap> { public: - static RetainPtr<GraphicsBitmap> create(const Size&); + static RetainPtr<GraphicsBitmap> create(Process&, const Size&); static RetainPtr<GraphicsBitmap> create_wrapper(const Size&, RGBA32*); ~GraphicsBitmap(); @@ -21,15 +20,17 @@ public: int height() const { return m_size.height(); } size_t pitch() const { return m_pitch; } + Region* client_region() { return m_client_region; } + Region* server_region() { return m_server_region; } + private: - explicit GraphicsBitmap(const Size&); + GraphicsBitmap(Process&, const Size&); GraphicsBitmap(const Size&, RGBA32*); Size m_size; RGBA32* m_data { nullptr }; size_t m_pitch { 0 }; -#ifdef SERENITY - Region* m_region { nullptr }; -#endif - bool m_owned { false }; + Process* m_client_process { nullptr }; + Region* m_client_region { nullptr }; + Region* m_server_region { nullptr }; }; diff --git a/Widgets/Window.cpp b/Widgets/Window.cpp index bc46a61958..f984e7bd45 100644 --- a/Widgets/Window.cpp +++ b/Widgets/Window.cpp @@ -33,7 +33,7 @@ void Window::setRect(const Rect& rect) auto oldRect = m_rect; m_rect = rect; dbgprintf("Window::setRect %d,%d %dx%d\n", m_rect.x(), m_rect.y(), m_rect.width(), m_rect.height()); - m_backing = GraphicsBitmap::create(m_rect.size()); + m_backing = GraphicsBitmap::create(m_process, m_rect.size()); WindowManager::the().notifyRectChanged(*this, oldRect, m_rect); } |