From f3bdde1ff0ec3cf20c1371a50eb37a0907fe00c5 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 22 Jun 2014 23:17:42 +0800 Subject: [PATCH] Usermode/AxWin4 - Working in shared memory usage --- .../axwin4_src/Common/include/ipc_proto.hpp | 1 + .../Common/include/serialisation.hpp | 4 ++ .../axwin4_src/Common/serialisation.cpp | 28 +++++++++++++ .../Server/CIPCChannel_AcessIPCPipe.cpp | 4 +- .../axwin4_src/Server/CSurface.cpp | 40 +++++++++++++++---- .../axwin4_src/Server/compositor.cpp | 2 +- .../axwin4_src/Server/include/CSurface.hpp | 4 ++ .../Applications/axwin4_src/Server/ipc.cpp | 19 ++++++++- .../Applications/axwin4_src/Server/video.cpp | 8 +--- Usermode/Applications/axwin4_src/UI/main.c | 7 +++- .../libaxwin4.so_src/include/common.hpp | 3 ++ .../libaxwin4.so_src/ipc_acessipcpipe.cpp | 2 +- .../libaxwin4.so_src/window_drawing.cpp | 1 + Usermode/Libraries/libaxwin4.so_src/wm.cpp | 31 +++++++++++--- 14 files changed, 128 insertions(+), 26 deletions(-) diff --git a/Usermode/Applications/axwin4_src/Common/include/ipc_proto.hpp b/Usermode/Applications/axwin4_src/Common/include/ipc_proto.hpp index 7018a620..e47ed14d 100644 --- a/Usermode/Applications/axwin4_src/Common/include/ipc_proto.hpp +++ b/Usermode/Applications/axwin4_src/Common/include/ipc_proto.hpp @@ -26,6 +26,7 @@ enum IPCMSG_GETWINBUF, // get a handle to the window's buffer // - Window drawing commands + IPCMSG_DAMAGERECT, // (u16 win, u16 x, u16 y, u16 w, u16 h) - Force reblit of area //IPCMSG_DRAWGROUP, // (u16 win, u16 group_id) - (hint) Switch to this group //IPCMSG_CLEAR, // (u16 win) - (hint) Clear current drawing group IPCMSG_PUSHDATA, // (u16 win, u16 x, u16 y, u16 w, u16 h, void data) diff --git a/Usermode/Applications/axwin4_src/Common/include/serialisation.hpp b/Usermode/Applications/axwin4_src/Common/include/serialisation.hpp index 5ccef67e..54293c1b 100644 --- a/Usermode/Applications/axwin4_src/Common/include/serialisation.hpp +++ b/Usermode/Applications/axwin4_src/Common/include/serialisation.hpp @@ -37,6 +37,8 @@ public: ::uint8_t ReadU8(); ::uint16_t ReadU16(); ::int16_t ReadS16(); + ::uint32_t ReadU32(); + ::uint64_t ReadU64(); const ::std::vector ReadBuffer(); const ::std::string ReadString(); private: @@ -51,6 +53,8 @@ public: void WriteU8(::uint8_t val); void WriteU16(::uint16_t val); void WriteS16(::int16_t val); + void WriteU32(::uint32_t val); + void WriteU64(::uint64_t val); void WriteBuffer(size_t n, const void* val); void WriteString(const char* val, size_t n); void WriteString(const char* val) { diff --git a/Usermode/Applications/axwin4_src/Common/serialisation.cpp b/Usermode/Applications/axwin4_src/Common/serialisation.cpp index f23d5cd8..016b0004 100644 --- a/Usermode/Applications/axwin4_src/Common/serialisation.cpp +++ b/Usermode/Applications/axwin4_src/Common/serialisation.cpp @@ -58,6 +58,20 @@ bool CDeserialiser::IsConsumed() const return ~rv_u + 1; } +::uint32_t CDeserialiser::ReadU32() +{ + uint32_t rv = ReadU16(); + rv |= (uint32_t)ReadU16() << 16; + return rv; +} + +::uint64_t CDeserialiser::ReadU64() +{ + uint64_t rv = ReadU32(); + rv |= (uint64_t)ReadU32() << 32; + return rv; +} + const ::std::vector CDeserialiser::ReadBuffer() { RangeCheck("CDeserialiser::ReadBuffer(len)", 2); @@ -116,6 +130,20 @@ void CSerialiser::WriteS16(::int16_t Value) } } +void CSerialiser::WriteU32(::uint32_t Value) +{ + m_data.push_back(Value & 0xFF); + m_data.push_back(Value >> 8); + m_data.push_back(Value >> 16); + m_data.push_back(Value >> 24); +} + +void CSerialiser::WriteU64(::uint64_t Value) +{ + WriteU32(Value); + WriteU32(Value>>32); +} + void CSerialiser::WriteBuffer(size_t n, const void* val) { const uint8_t* val8 = static_cast(val); diff --git a/Usermode/Applications/axwin4_src/Server/CIPCChannel_AcessIPCPipe.cpp b/Usermode/Applications/axwin4_src/Server/CIPCChannel_AcessIPCPipe.cpp index df94958c..867c4917 100644 --- a/Usermode/Applications/axwin4_src/Server/CIPCChannel_AcessIPCPipe.cpp +++ b/Usermode/Applications/axwin4_src/Server/CIPCChannel_AcessIPCPipe.cpp @@ -98,7 +98,7 @@ void CClient_AcessIPCPipe::SendMessage(CSerialiser& message) const ::std::vector& data = message.Compact(); _SysDebug("CClient_AcessIPCPipe::SendMessage - %i bytes to %i", data.size(), m_fd); - _SysDebugHex("CClient_AcessIPCPipe::SendMessage", data.data(), data.size()); + //_SysDebugHex("CClient_AcessIPCPipe::SendMessage", data.data(), data.size()); _SysWrite(m_fd, data.data(), data.size()); } @@ -109,7 +109,7 @@ void CClient_AcessIPCPipe::HandleReceive() if( len == (size_t)-1 ) throw ::std::system_error(errno, ::std::system_category()); //_SysDebug("CClient_AcessIPCPipe::HandleReceive - Rx %i/%i bytes", len, rxbuf.capacity()); - //_SysDebugHex("CClient_AcessIPCPipe::HandleReceive", m_rxbuf.data(), len); + //_SysDebugHex("CClient_AcessIPCPipe::HandleReceive", rxbuf.data(), len); rxbuf.resize(len); CDeserialiser msg( ::std::move(rxbuf) ); diff --git a/Usermode/Applications/axwin4_src/Server/CSurface.cpp b/Usermode/Applications/axwin4_src/Server/CSurface.cpp index 6d4b0907..07d8bfb6 100644 --- a/Usermode/Applications/axwin4_src/Server/CSurface.cpp +++ b/Usermode/Applications/axwin4_src/Server/CSurface.cpp @@ -9,11 +9,15 @@ #include #include #include +#include +#include namespace AxWin { CSurface::CSurface(int x, int y, unsigned int w, unsigned int h): - m_rect(x,y, w,h) + m_rect(x,y, w,h), + m_fd(-1), + m_data(0) { if( w > 0 && h > 0 ) { @@ -25,18 +29,39 @@ CSurface::~CSurface() { } -void CSurface::Resize(unsigned int W, unsigned int H) +uint64_t CSurface::GetSHMHandle() { - // Easy realloc - // TODO: Should I maintain window contents sanely? NOPE! + // 1. Free local buffer delete m_data; - m_data = new uint32_t[W * H]; + // 2. Allocate a copy in SHM + m_fd = _SysOpen("/Devices/shm/anon", OPENFLAG_WRITE|OPENFLAG_READ); + if(m_fd==-1) throw ::std::system_error(errno, ::std::system_category()); + size_t size = m_rect.m_w*m_rect.m_h*4; + _SysTruncate(m_fd, size); + // 3. mmap shm copy + m_data = static_cast( _SysMMap(nullptr, size, MMAP_PROT_WRITE, 0, m_fd, 0) ); + if(!m_data) throw ::std::system_error(errno, ::std::system_category()); + return _SysMarshalFD(m_fd); +} + +void CSurface::Resize(unsigned int W, unsigned int H) +{ + if( m_fd == -1 ) + { + // Easy realloc + // TODO: Should I maintain window contents sanely? NOPE! + delete m_data; + m_data = new uint32_t[W * H]; + } + else + { + //_SysIOCtl(m_fd, SHM_IOCTL_SETSIZE, W*H*4); + } m_rect.Resize(W, H); } void CSurface::DrawScanline(unsigned int row, unsigned int x_ofs, unsigned int w, const void* data) { - //_SysDebug("DrawScanline(%i,%i,%i,%p)", row, x_ofs, w, data); if( row >= m_rect.m_h ) throw ::std::out_of_range("CSurface::DrawScanline row"); if( x_ofs >= m_rect.m_w ) @@ -45,7 +70,8 @@ void CSurface::DrawScanline(unsigned int row, unsigned int x_ofs, unsigned int w if( w > m_rect.m_w ) throw ::std::out_of_range("CSurface::DrawScanline width"); - ::memcpy( &m_data[row*m_rect.m_w + x_ofs], data, w*4 ); + size_t ofs = row*m_rect.m_w + x_ofs; + ::memcpy( &m_data[ofs], data, w*4 ); } const uint32_t* CSurface::GetScanline(unsigned int row, unsigned int x_ofs) const diff --git a/Usermode/Applications/axwin4_src/Server/compositor.cpp b/Usermode/Applications/axwin4_src/Server/compositor.cpp index a5d1ff2d..699b6a24 100644 --- a/Usermode/Applications/axwin4_src/Server/compositor.cpp +++ b/Usermode/Applications/axwin4_src/Server/compositor.cpp @@ -97,7 +97,7 @@ void CCompositor::BlitFromSurface(const CSurface& dest, const CRect& src_rect) for( unsigned int i = 0; i < src_rect.m_h; i ++ ) { m_video.BlitLine( - dest.GetScanline(src_rect.m_y, src_rect.m_y), + dest.GetScanline(src_rect.m_y, src_rect.m_x), dest.m_rect.m_y + src_rect.m_y + i, dest.m_rect.m_x + src_rect.m_x, src_rect.m_w diff --git a/Usermode/Applications/axwin4_src/Server/include/CSurface.hpp b/Usermode/Applications/axwin4_src/Server/include/CSurface.hpp index 488d4d6c..6de73055 100644 --- a/Usermode/Applications/axwin4_src/Server/include/CSurface.hpp +++ b/Usermode/Applications/axwin4_src/Server/include/CSurface.hpp @@ -13,6 +13,8 @@ class CSurface public: CSurface(int x, int y, unsigned int w, unsigned int h); ~CSurface(); + + uint64_t GetSHMHandle(); void Resize(unsigned int new_w, unsigned int new_h); @@ -21,6 +23,8 @@ public: CRect m_rect; uint32_t* m_data; +private: + int m_fd; }; }; // namespace AxWin diff --git a/Usermode/Applications/axwin4_src/Server/ipc.cpp b/Usermode/Applications/axwin4_src/Server/ipc.cpp index 732ddfd1..fcd0eb91 100644 --- a/Usermode/Applications/axwin4_src/Server/ipc.cpp +++ b/Usermode/Applications/axwin4_src/Server/ipc.cpp @@ -224,7 +224,21 @@ void HandleMessage_SendIPC(CClient& client, CDeserialiser& message) void HandleMessage_GetWindowBuffer(CClient& client, CDeserialiser& message) { - assert(!"TODO HandleMessage_GetWindowBuffer"); + uint16_t win_id = message.ReadU16(); + _SysDebug("_SetWindowAttr: (%i)", win_id); + + CWindow* win = client.GetWindow(win_id); + if(!win) { + throw IPC::CClientFailure("_PushData: Bad window"); + } + + uint64_t handle = win->m_surface.GetSHMHandle(); + + CSerialiser reply; + reply.WriteU8(IPCMSG_REPLY); + reply.WriteU16(win_id); + reply.WriteU64(handle); + client.SendMessage(reply); } void HandleMessage_PushData(CClient& client, CDeserialiser& message) @@ -234,7 +248,7 @@ void HandleMessage_PushData(CClient& client, CDeserialiser& message) uint16_t y = message.ReadU16(); uint16_t w = message.ReadU16(); uint16_t h = message.ReadU16(); - _SysDebug("_PushData: (%i, (%i,%i) %ix%i)", win_id, x, y, w, h); + //_SysDebug("_PushData: (%i, (%i,%i) %ix%i)", win_id, x, y, w, h); CWindow* win = client.GetWindow(win_id); if(!win) { @@ -280,6 +294,7 @@ MessageHandler_op_t *message_handlers[] = { [IPCMSG_GETWINATTR] = &HandleMessage_GetWindowAttr, [IPCMSG_SENDIPC] = &HandleMessage_SendIPC, // Use the GUI server for low-bandwith IPC [IPCMSG_GETWINBUF] = &HandleMessage_GetWindowBuffer, + [IPCMSG_DAMAGERECT] = nullptr, [IPCMSG_PUSHDATA] = &HandleMessage_PushData, // to a window's buffer [IPCMSG_BLIT] = &HandleMessage_Blit, // Copy data from one part of the window to another [IPCMSG_DRAWCTL] = &HandleMessage_DrawCtl, // Draw a control diff --git a/Usermode/Applications/axwin4_src/Server/video.cpp b/Usermode/Applications/axwin4_src/Server/video.cpp index 8d5f5dd2..50686c61 100644 --- a/Usermode/Applications/axwin4_src/Server/video.cpp +++ b/Usermode/Applications/axwin4_src/Server/video.cpp @@ -57,7 +57,8 @@ void CVideo::GetDims(unsigned int& w, unsigned int& h) void CVideo::BlitLine(const uint32_t* src, unsigned int dst_y, unsigned int dst_x, unsigned int width) { //_SysDebug("CVideo::BlitLine (%p, %i, %i, %i)", src, dst_y, dst_x, width); - size_t cmdlen = sizeof(struct ptycmd_senddata)/4 + width; + //_SysDebugHex("CVideo::BlitLine", src, width*4); + size_t cmdlen = (sizeof(struct ptycmd_senddata) + width*4)/4; //_SysDebug(" - Offset = %i, cmdlen = %i", (dst_y * m_width + dst_x) * 4, cmdlen); struct ptycmd_senddata cmd = { {PTY2D_CMD_SEND, uint8_t(cmdlen & 0xFF), uint16_t(cmdlen>>8)}, @@ -66,11 +67,6 @@ void CVideo::BlitLine(const uint32_t* src, unsigned int dst_y, unsigned int dst_ SetBufFormat(PTYBUFFMT_2DCMD); _SysWrite(m_fd, &cmd, sizeof(cmd)); _SysWrite(m_fd, src, width*4); - - //SetBufFormat(PTYBUFFMT_FB); - //_SysWriteAt(m_fd, (dst_y * m_width + dst_x) * 4, width * 4, src); - //_SysSeek(m_fd, (dst_y * m_width + dst_x) * 4, SEEK_SET); - //_SysWrite(m_fd, src, width * 4); } void CVideo::Flush() diff --git a/Usermode/Applications/axwin4_src/UI/main.c b/Usermode/Applications/axwin4_src/UI/main.c index 3baf0279..54eae0ff 100644 --- a/Usermode/Applications/axwin4_src/UI/main.c +++ b/Usermode/Applications/axwin4_src/UI/main.c @@ -23,12 +23,15 @@ int main(int argc, const char *argv[]) AxWin4_SetWindowFlags(bgwin, AXWIN4_WNDFLAG_NODECORATE|AXWIN4_WNDFLAG_KEEPBELOW); AxWin4_ShowWindow(bgwin, true); + + uint32_t *buf = AxWin4_GetWindowBuffer(bgwin); + _SysDebug("buf = %p", buf); // Load image uint32_t *image = malloc(w*h*4); for(size_t i = 0; i < w*h; i ++ ) - image[i] = rand(); + image[i] = i*(0x1000000/w*h); - AxWin4_DrawBitmap(bgwin, 0, 0, w, h, (void*)image); + //AxWin4_DrawBitmap(bgwin, 0, 0, w, h, (void*)image); _SysDebug("Beginning queue"); diff --git a/Usermode/Libraries/libaxwin4.so_src/include/common.hpp b/Usermode/Libraries/libaxwin4.so_src/include/common.hpp index f0ec6d77..e3aa8074 100644 --- a/Usermode/Libraries/libaxwin4.so_src/include/common.hpp +++ b/Usermode/Libraries/libaxwin4.so_src/include/common.hpp @@ -14,12 +14,15 @@ namespace AxWin { extern void SendMessage(CSerialiser& message); extern void RecvMessage(CDeserialiser& message); +extern CDeserialiser GetSyncReply(CSerialiser& request, unsigned int Message); }; struct sAxWin4_Window { unsigned int m_id; + int m_fd; + void *m_buffer; }; #endif diff --git a/Usermode/Libraries/libaxwin4.so_src/ipc_acessipcpipe.cpp b/Usermode/Libraries/libaxwin4.so_src/ipc_acessipcpipe.cpp index 4b4bc71a..87cc6c93 100644 --- a/Usermode/Libraries/libaxwin4.so_src/ipc_acessipcpipe.cpp +++ b/Usermode/Libraries/libaxwin4.so_src/ipc_acessipcpipe.cpp @@ -40,7 +40,7 @@ bool CIPCChannel_AcessIPCPipe::HandleSelect(const fd_set& fds) throw ::std::system_error(errno, ::std::system_category()); rxbuf.resize(len); _SysDebug("CClient_AcessIPCPipe::HandleReceive - Rx %i/%i bytes", len, rxbuf.capacity()); - _SysDebugHex("CClient_AcessIPCPipe::HandleReceive", rxbuf.data(), len); + //_SysDebugHex("CClient_AcessIPCPipe::HandleReceive", rxbuf.data(), len); CDeserialiser msg(rxbuf); ::AxWin::RecvMessage( msg ); diff --git a/Usermode/Libraries/libaxwin4.so_src/window_drawing.cpp b/Usermode/Libraries/libaxwin4.so_src/window_drawing.cpp index e074ee40..6947d294 100644 --- a/Usermode/Libraries/libaxwin4.so_src/window_drawing.cpp +++ b/Usermode/Libraries/libaxwin4.so_src/window_drawing.cpp @@ -15,6 +15,7 @@ namespace AxWin { void _push_data(tAxWin4_Window *Window, int X, int Y, unsigned int W, unsigned int H, const void *Data) { CSerialiser message; + //_SysDebug("_push_data - (%i,%i), %ix%i %p", X, Y, W, H, Data); message.WriteU8(IPCMSG_PUSHDATA); message.WriteU16(Window->m_id); message.WriteU16(X); diff --git a/Usermode/Libraries/libaxwin4.so_src/wm.cpp b/Usermode/Libraries/libaxwin4.so_src/wm.cpp index f023ea81..fdfa32c2 100644 --- a/Usermode/Libraries/libaxwin4.so_src/wm.cpp +++ b/Usermode/Libraries/libaxwin4.so_src/wm.cpp @@ -35,6 +35,8 @@ extern "C" tAxWin4_Window *AxWin4_CreateWindow(const char *Name) tAxWin4_Window *ret = new tAxWin4_Window(); gWindowList[id] = ret; ret->m_id = id; + ret->m_fd = -1; + ret->m_buffer = nullptr; // Request creation of window CSerialiser message; message.WriteU8(IPCMSG_CREATEWIN); @@ -97,11 +99,30 @@ extern "C" void AxWin4_SetTitle(tAxWin4_Window *Window, const char *Title) extern "C" void *AxWin4_GetWindowBuffer(tAxWin4_Window *Window) { - //if( !Window->m_buffer ) - //{ - // // TODO: Support non-blocking operations - //} - return NULL; + if( Window->m_fd == -1 ) + { + CSerialiser req; + req.WriteU8(IPCMSG_GETWINBUF); + req.WriteU16(Window->m_id); + + CDeserialiser response = GetSyncReply(req, IPCMSG_GETWINBUF); + if( response.ReadU16() != Window->m_id ) { + + } + + uint64_t handle = response.ReadU64(); + Window->m_fd = _SysUnMarshalFD(handle); + + _SysDebug("AxWin4_GetWindowBuffer: %llx = %i", handle, Window->m_fd); + } + + if( !Window->m_buffer ) + { + size_t size = 640*480*4; + Window->m_buffer = _SysMMap(NULL, size, MMAP_PROT_WRITE, MMAP_MAP_SHARED, Window->m_fd, 0); + } + + return Window->m_buffer; } }; // namespace AxWin -- 2.20.1