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); +}