diff --git a/Makefile b/Makefile
index 4e029d07..a8f8308c 100644
--- a/Makefile
+++ b/Makefile
@@ -6,6 +6,11 @@ ifneq ($(BUILD_LIBC),0)
endif
ALLMODULES:=$(ALLMODULES) libc
+ifneq ($(BUILD_DISPD),0)
+ MODULES:=$(MODULES) dispd
+endif
+ALLMODULES:=$(ALLMODULES) dispd
+
ifneq ($(BUILD_GAMES),0)
MODULES:=$(MODULES) games
endif
diff --git a/dispd/.gitignore b/dispd/.gitignore
new file mode 100644
index 00000000..20586633
--- /dev/null
+++ b/dispd/.gitignore
@@ -0,0 +1,3 @@
+*.a
+*.o
+server/dispd
diff --git a/dispd/Makefile b/dispd/Makefile
new file mode 100644
index 00000000..87fdb8b5
--- /dev/null
+++ b/dispd/Makefile
@@ -0,0 +1,78 @@
+include ../compiler.mak
+include ../version.mak
+include ../dirs.mak
+
+ifndef OPTLEVEL
+ OPTLEVEL:=-O2
+endif
+
+ifndef CXXFLAGS
+ CXXFLAGS:=$(OPTLEVEL)
+endif
+
+CXXFLAGS:=$(CXXFLAGS) -Wall -Wextra -fno-exceptions -fno-rtti
+CPPFLAGS:=$(CPPFLAGS) -I include
+
+CLIENT_OBJS:=\
+client/library.o \
+client/session.o \
+client/window.o \
+
+SERVER_OBJS:=\
+server/dispd.o \
+
+BINS:=server/dispd client/libdispd.a
+
+all: $(BINS)
+
+.PHONY: all headers client server clean install install-include-dirs \
+ install-headers install-client-dirs install-client install-server-dirs \
+ install-server
+
+headers:
+
+client: client/libdispd.a
+
+client/libdispd.a: $(CLIENT_OBJS)
+ $(HOSTAR) rcs $@ $(CLIENT_OBJS)
+
+server: server/dispd
+
+server/dispd: $(SERVER_OBJS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(SERVER_OBJS) -o $@
+
+clean:
+ rm -f $(CLIENT_OBJS) $(SERVER_OBJS)
+ rm -f $(BINS)
+ rm -f *.o client/*.o server/*.o
+
+%.o: %.cpp
+ $(HOSTCXX) -c $< -o $@ $(CPPFLAGS) $(CXXFLAGS)
+
+# Installation into sysroot
+install: install-headers install-client install-server
+
+install-include-dirs: headers
+ mkdir -p $(INSTALLINCLUDEDIR)
+ for D in $$(find include/ -type d | sed 's/include\/*//'); do \
+ mkdir -p $(INSTALLINCLUDEDIR)/$$D || exit $?; \
+ done
+
+install-headers: install-include-dirs headers
+ for SRC in $$(find include/ -type f); do \
+ DEST=`echo $$SRC | sed 's/include\///'`; \
+ cp -P $$SRC $(INSTALLINCLUDEDIR)/$$DEST || exit $?; \
+ done
+
+install-client-dirs:
+ mkdir -p $(INSTALLLIBDIR)
+ mkdir -p $(INSTALLLIBDIR)/$(HOST)
+
+install-client: install-client-dirs
+ cp -P client/libdispd.a $(INSTALLLIBDIR)/$(HOST)
+
+install-server-dirs:
+ mkdir -p $(INSTALLBINDIR)/$(HOST)
+
+install-server: install-server-dirs
+ install server/dispd $(INSTALLBINDIR)/$(HOST)
diff --git a/dispd/client/framebuffer.h b/dispd/client/framebuffer.h
new file mode 100644
index 00000000..005e0de3
--- /dev/null
+++ b/dispd/client/framebuffer.h
@@ -0,0 +1,49 @@
+/*******************************************************************************
+
+ Copyright(C) Jonas 'Sortie' Termansen 2012.
+
+ This file is part of dispd.
+
+ dispd is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ dispd is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with dispd. If not, see .
+
+ framebuffer.h
+ Keeps track of framebuffers.
+
+*******************************************************************************/
+
+#ifndef INCLUDE_DISPD_FRAMEBUFFER_H
+#define INCLUDE_DISPD_FRAMEBUFFER_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct dispd_framebuffer
+{
+ struct dispd_window* window;
+ uint8_t* data;
+ size_t datasize;
+ size_t pitch;
+ int bpp;
+ int width;
+ int height;
+ bool is_vga;
+ bool is_rgba;
+};
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif
+
+#endif
diff --git a/dispd/client/library.cpp b/dispd/client/library.cpp
new file mode 100644
index 00000000..74eaf75e
--- /dev/null
+++ b/dispd/client/library.cpp
@@ -0,0 +1,37 @@
+/*******************************************************************************
+
+ Copyright(C) Jonas 'Sortie' Termansen 2012.
+
+ This file is part of dispd.
+
+ dispd is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ dispd is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with dispd. If not, see .
+
+ library.cpp
+ Main entry point of the Sortix Display Daemon.
+
+*******************************************************************************/
+
+#include
+#include
+
+#include
+
+#include "session.h"
+
+extern "C" bool dispd_initialize(int* argc, char*** argv)
+{
+ if ( !dispd__session_initialize(argc, argv) )
+ return false;
+ return true;
+}
diff --git a/dispd/client/session.cpp b/dispd/client/session.cpp
new file mode 100644
index 00000000..723f4eca
--- /dev/null
+++ b/dispd/client/session.cpp
@@ -0,0 +1,125 @@
+/*******************************************************************************
+
+ Copyright(C) Jonas 'Sortie' Termansen 2012.
+
+ This file is part of dispd.
+
+ dispd is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ dispd is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with dispd. If not, see .
+
+ session.cpp
+ Handles session management.
+
+*******************************************************************************/
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "session.h"
+
+const uint64_t ONE_AND_ONLY_DEVICE = 0;
+const uint64_t ONE_AND_ONLY_CONNECTOR = 0;
+
+struct dispd_session* global_session = NULL;
+
+bool dispd__session_initialize(int* /*argc*/, char*** /*argv*/)
+{
+ size_t size = sizeof(struct dispd_session);
+ global_session = (struct dispd_session*) malloc(size);
+ if ( !global_session )
+ return false;
+ memset(global_session, 0, sizeof(*global_session));
+ global_session->device = ONE_AND_ONLY_DEVICE;
+ global_session->connector = ONE_AND_ONLY_CONNECTOR;
+ return true;
+}
+
+struct dispd_session* dispd_attach_default_session()
+{
+ global_session->refcount++;
+ return global_session;
+}
+
+bool dispd_detach_session(struct dispd_session* session)
+{
+ session->refcount--;
+ return true;
+}
+
+bool dispd_session_setup_game_vga(struct dispd_session* session)
+{
+ if ( session->is_vga )
+ return true;
+ if ( session->is_rgba )
+ return false;
+ if ( session->current_window )
+ return false;
+ struct dispmsg_get_crtc_mode msg;
+ msg.msgid = DISPMSG_GET_CRTC_MODE;
+ msg.device = session->device;
+ msg.connector = session->connector;
+ if ( dispmsg_issue(&msg, sizeof(msg)) != 0 )
+ return false;
+ return session->is_vga = (msg.mode.control & 1)== 0;
+}
+
+bool dispd_session_setup_game_rgba(struct dispd_session* session)
+{
+ if ( session->is_vga )
+ return false;
+ if ( session->is_rgba )
+ return true;
+ if ( session->current_window )
+ return false;
+ struct dispmsg_get_crtc_mode msg;
+ msg.msgid = DISPMSG_GET_CRTC_MODE;
+ msg.device = session->device;
+ msg.connector = session->connector;
+ if ( dispmsg_issue(&msg, sizeof(msg)) != 0 )
+ return false;
+ if ( !(msg.mode.control & 1) || msg.mode.fb_format != 32 )
+ {
+ pid_t childpid = fork();
+ if ( childpid < 0 )
+ return false;
+ if ( childpid )
+ {
+ int status;
+ waitpid(childpid, &status, 0);
+ return session->is_rgba = (WIFEXITED(status) && !WEXITSTATUS(status));
+ }
+ const char* chvideomode = "chvideomode";
+#if 1
+ // TODO chvideomode currently launches --bpp 32 as a program...
+ execlp(chvideomode, chvideomode, NULL);
+#else
+ execlp(chvideomode, chvideomode,
+ "--bpp", "32",
+ "--show-graphics", "true",
+ "--show-text", "false",
+ NULL);
+#endif
+ perror(chvideomode);
+ exit(127);
+ }
+ return session->is_rgba = true;
+}
diff --git a/dispd/client/session.h b/dispd/client/session.h
new file mode 100644
index 00000000..cf2150a9
--- /dev/null
+++ b/dispd/client/session.h
@@ -0,0 +1,48 @@
+/*******************************************************************************
+
+ Copyright(C) Jonas 'Sortie' Termansen 2012.
+
+ This file is part of dispd.
+
+ dispd is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ dispd is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with dispd. If not, see .
+
+ session.h
+ Handles session management.
+
+*******************************************************************************/
+
+#ifndef INCLUDE_DISPD_SESSION_H
+#define INCLUDE_DISPD_SESSION_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct dispd_session
+{
+ size_t refcount;
+ uint64_t device;
+ uint64_t connector;
+ struct dispd_window* current_window;
+ bool is_vga;
+ bool is_rgba;
+};
+
+bool dispd__session_initialize(int* argc, char*** argv);
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif
+
+#endif
diff --git a/dispd/client/window.cpp b/dispd/client/window.cpp
new file mode 100644
index 00000000..96b740db
--- /dev/null
+++ b/dispd/client/window.cpp
@@ -0,0 +1,190 @@
+/*******************************************************************************
+
+ Copyright(C) Jonas 'Sortie' Termansen 2012.
+
+ This file is part of dispd.
+
+ dispd is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ dispd is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with dispd. If not, see .
+
+ window.cpp
+ Handles windows.
+
+*******************************************************************************/
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "framebuffer.h"
+#include "session.h"
+#include "window.h"
+
+extern "C"
+struct dispd_window* dispd_create_window_game_vga(struct dispd_session* session)
+{
+ if ( session->current_window )
+ return NULL;
+ if ( !session->is_vga )
+ return NULL;
+ size_t size = sizeof(struct dispd_window);
+ struct dispd_window* window = (struct dispd_window*) malloc(size);
+ if ( !window )
+ return NULL;
+ memset(window, 0, sizeof(*window));
+ window->session = session;
+ window->is_vga = true;
+ return session->current_window = window;
+}
+
+extern "C"
+struct dispd_window* dispd_create_window_game_rgba(struct dispd_session* session)
+{
+ if ( session->current_window )
+ return NULL;
+ if ( !session->is_rgba )
+ return NULL;
+ size_t size = sizeof(struct dispd_window);
+ struct dispd_window* window = (struct dispd_window*) malloc(size);
+ if ( !window )
+ return NULL;
+ memset(window, 0, sizeof(*window));
+ window->session = session;
+ window->is_rgba = true;
+ return session->current_window = window;
+}
+
+extern "C" bool dispd_destroy_window(struct dispd_window* window)
+{
+ free(window);
+ return true;
+}
+
+static
+struct dispd_framebuffer* disp_begin_render_vga(struct dispd_window* window)
+{
+ size_t size = sizeof(struct dispd_framebuffer);
+ struct dispd_framebuffer* fb = (struct dispd_framebuffer*) malloc(size);
+ if ( !fb )
+ return NULL;
+ memset(fb, 0, sizeof(*fb));
+ fb->is_vga = true;
+ fb->window = window;
+ fb->width = 80;
+ fb->height = 25;
+ fb->bpp = 16;
+ fb->pitch = fb->width * fb->bpp / 8;
+ fb->datasize = fb->pitch * fb->height;
+ fb->data = (uint8_t*) malloc(fb->datasize);
+ if ( !fb->data ) { free(fb); return NULL; }
+ return fb;
+}
+
+static
+struct dispd_framebuffer* disp_begin_render_rgba(struct dispd_window* window)
+{
+ struct dispmsg_get_crtc_mode msg;
+ msg.msgid = DISPMSG_GET_CRTC_MODE;
+ msg.device = window->session->device;
+ msg.connector = window->session->connector;
+ if ( dispmsg_issue(&msg, sizeof(msg)) != 0 )
+ return NULL;
+ size_t size = sizeof(struct dispd_framebuffer);
+ struct dispd_framebuffer* fb = (struct dispd_framebuffer*) malloc(size);
+ if ( !fb )
+ return NULL;
+ memset(fb, 0, sizeof(*fb));
+ fb->window = window;
+ fb->is_rgba = true;
+ fb->width = msg.mode.view_xres;
+ fb->height = msg.mode.view_yres;
+ fb->bpp = 32;
+ fb->pitch = fb->width * fb->bpp / 8;
+ fb->datasize = fb->pitch * fb->height;
+ fb->data = (uint8_t*) malloc(fb->datasize);
+ if ( !fb->data ) { free(fb); return NULL; }
+ return fb;
+}
+
+
+struct dispd_framebuffer* dispd_begin_render(struct dispd_window* window)
+{
+ if ( window->is_vga )
+ return disp_begin_render_vga(window);
+ if ( window->is_rgba )
+ return disp_begin_render_rgba(window);
+ return NULL;
+}
+
+bool dispd_finish_render(struct dispd_framebuffer* fb)
+{
+ struct dispd_window* window = fb->window;
+ bool ret = false;
+ if ( window->is_vga )
+ {
+ int fd = open("/dev/vga", O_WRONLY);
+ if ( 0 <= fd )
+ {
+ if ( writeall(fd, fb->data, fb->datasize) == fb->datasize )
+ ret = true;
+ close(fd);
+ }
+ }
+ else if ( window->is_rgba )
+ {
+ struct dispmsg_write_memory msg;
+ msg.msgid = DISPMSG_WRITE_MEMORY;
+ msg.device = window->session->device;
+ msg.offset = 0;
+ msg.size = fb->datasize;
+ msg.src = fb->data;
+ if ( dispmsg_issue(&msg, sizeof(msg)) == 0 )
+ ret = true;
+ }
+ free(fb->data);
+ free(fb);
+ return ret;
+}
+
+uint8_t* dispd_get_framebuffer_data(struct dispd_framebuffer* fb)
+{
+ return fb->data;
+}
+
+size_t dispd_get_framebuffer_pitch(struct dispd_framebuffer* fb)
+{
+ return fb->pitch;
+}
+
+int dispd_get_framebuffer_format(struct dispd_framebuffer* fb)
+{
+ return fb->is_vga ? 0 : fb->bpp;
+}
+
+int dispd_get_framebuffer_height(struct dispd_framebuffer* fb)
+{
+ return fb->height;
+}
+
+int dispd_get_framebuffer_width(struct dispd_framebuffer* fb)
+{
+ return fb->width;
+}
diff --git a/dispd/client/window.h b/dispd/client/window.h
new file mode 100644
index 00000000..daa24704
--- /dev/null
+++ b/dispd/client/window.h
@@ -0,0 +1,43 @@
+/*******************************************************************************
+
+ Copyright(C) Jonas 'Sortie' Termansen 2012.
+
+ This file is part of dispd.
+
+ dispd is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ dispd is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with dispd. If not, see .
+
+ window.h
+ Handles windows.
+
+*******************************************************************************/
+
+#ifndef INCLUDE_DISPD_WINDOW_H
+#define INCLUDE_DISPD_WINDOW_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct dispd_window
+{
+ struct dispd_session* session;
+ bool is_vga;
+ bool is_rgba;
+};
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif
+
+#endif
diff --git a/dispd/include/dispd.h b/dispd/include/dispd.h
new file mode 100644
index 00000000..2f1fd51b
--- /dev/null
+++ b/dispd/include/dispd.h
@@ -0,0 +1,65 @@
+/*******************************************************************************
+
+ Copyright(C) Jonas 'Sortie' Termansen 2012.
+
+ This file is part of dispd.
+
+ dispd is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ dispd is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with dispd. If not, see .
+
+ dispd.h
+ Interface to the Sortix Display Daemon.
+
+*******************************************************************************/
+
+#ifndef INCLUDE_DISPD_H
+#define INCLUDE_DISPD_H
+
+#if !defined(__cplusplus)
+#include
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct dispd_session;
+struct dispd_window;
+struct dispd_framebuffer;
+
+bool dispd_initialize(int* argc, char*** argv);
+
+struct dispd_session* dispd_attach_default_session();
+bool dispd_detach_session(struct dispd_session* session);
+
+bool dispd_session_setup_game_vga(struct dispd_session* session);
+bool dispd_session_setup_game_rgba(struct dispd_session* session);
+
+struct dispd_window* dispd_create_window_game_vga(struct dispd_session* session);
+struct dispd_window* dispd_create_window_game_rgba(struct dispd_session* session);
+bool dispd_destroy_window(struct dispd_window* window);
+
+struct dispd_framebuffer* dispd_begin_render(struct dispd_window* window);
+bool dispd_finish_render(struct dispd_framebuffer* framebuffer);
+
+uint8_t* dispd_get_framebuffer_data(struct dispd_framebuffer* framebuffer);
+size_t dispd_get_framebuffer_pitch(struct dispd_framebuffer* framebuffer);
+int dispd_get_framebuffer_format(struct dispd_framebuffer* framebuffer);
+int dispd_get_framebuffer_height(struct dispd_framebuffer* framebuffer);
+int dispd_get_framebuffer_width(struct dispd_framebuffer* framebuffer);
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif
+
+#endif
diff --git a/dispd/server/dispd.cpp b/dispd/server/dispd.cpp
new file mode 100644
index 00000000..4bcf08ed
--- /dev/null
+++ b/dispd/server/dispd.cpp
@@ -0,0 +1,32 @@
+/*******************************************************************************
+
+ Copyright(C) Jonas 'Sortie' Termansen 2012.
+
+ This file is part of dispd.
+
+ dispd is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ dispd is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with dispd. If not, see .
+
+ dispd.cpp
+ Main entry point of the Sortix Display Daemon.
+
+*******************************************************************************/
+
+#include
+#include
+
+int main(int /*argc*/, char* /*argv*/[])
+{
+ fprintf(stderr, "dispd is not implemented as a server yet.\n");
+ exit(1);
+}