summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kernel/GUITypes.h7
-rw-r--r--Kernel/Process.h2
-rw-r--r--Kernel/ProcessGUI.cpp38
-rw-r--r--Kernel/Syscall.cpp4
-rw-r--r--Kernel/Syscall.h3
-rw-r--r--LibC/Makefile5
-rw-r--r--LibC/stdlib.cpp14
-rw-r--r--LibC/stdlib.h4
-rw-r--r--Userland/guitest.cpp33
-rw-r--r--Widgets/Color.cpp10
-rw-r--r--Widgets/GraphicsBitmap.cpp46
-rw-r--r--Widgets/GraphicsBitmap.h17
-rw-r--r--Widgets/Window.cpp2
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);
}