From 4696a38ba9ea5798e67ccd475c8b77f318db133d Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 8 Jun 2014 18:39:52 +0800 Subject: [PATCH] Usermode/AxWin4 - PushData implemented --- .../Common/include/serialisation.hpp | 1 + .../axwin4_src/Common/serialisation.cpp | 11 ++++++ .../Applications/axwin4_src/Server/CRect.cpp | 8 +++++ .../axwin4_src/Server/CSurface.cpp | 34 ++++++++++++++++-- .../axwin4_src/Server/include/CRect.hpp | 1 + .../axwin4_src/Server/include/CSurface.hpp | 1 + .../Applications/axwin4_src/Server/ipc.cpp | 32 ++++++++++++++--- .../libaxwin4.so_src/window_drawing.cpp | 35 +++++++++---------- 8 files changed, 98 insertions(+), 25 deletions(-) diff --git a/Usermode/Applications/axwin4_src/Common/include/serialisation.hpp b/Usermode/Applications/axwin4_src/Common/include/serialisation.hpp index 7212018e..c1478096 100644 --- a/Usermode/Applications/axwin4_src/Common/include/serialisation.hpp +++ b/Usermode/Applications/axwin4_src/Common/include/serialisation.hpp @@ -32,6 +32,7 @@ public: ::uint8_t ReadU8(); ::uint16_t ReadU16(); ::int16_t ReadS16(); + const ::std::vector ReadBuffer(); const ::std::string ReadString(); private: void RangeCheck(const char *Method, size_t bytes) throw(::std::out_of_range); diff --git a/Usermode/Applications/axwin4_src/Common/serialisation.cpp b/Usermode/Applications/axwin4_src/Common/serialisation.cpp index 7bb77bf5..9f536b5d 100644 --- a/Usermode/Applications/axwin4_src/Common/serialisation.cpp +++ b/Usermode/Applications/axwin4_src/Common/serialisation.cpp @@ -49,6 +49,17 @@ bool CDeserialiser::IsConsumed() const return ~rv_u + 1; } +const ::std::vector CDeserialiser::ReadBuffer() +{ + RangeCheck("CDeserialiser::ReadBuffer(len)", 2); + size_t size = ReadU16(); + + ::std::vector ret( size ); + for( size_t i = 0; i < size; i ++ ) + ret[i] = m_data[m_offset++]; + return ret; +} + const ::std::string CDeserialiser::ReadString() { RangeCheck("CDeserialiser::ReadString(len)", 1); diff --git a/Usermode/Applications/axwin4_src/Server/CRect.cpp b/Usermode/Applications/axwin4_src/Server/CRect.cpp index 34013b1c..6f504d85 100644 --- a/Usermode/Applications/axwin4_src/Server/CRect.cpp +++ b/Usermode/Applications/axwin4_src/Server/CRect.cpp @@ -26,6 +26,14 @@ void CRect::Move(int NewX, int NewY) m_y2 = m_y + m_h; } +void CRect::Resize(int NewW, int NewH) +{ + m_w = NewW; + m_h = NewH; + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; +} + bool CRect::HasIntersection(const CRect& other) const { // If other's origin is past our far corner diff --git a/Usermode/Applications/axwin4_src/Server/CSurface.cpp b/Usermode/Applications/axwin4_src/Server/CSurface.cpp index d52298cd..429657a3 100644 --- a/Usermode/Applications/axwin4_src/Server/CSurface.cpp +++ b/Usermode/Applications/axwin4_src/Server/CSurface.cpp @@ -7,12 +7,18 @@ */ #include #include +#include +#include namespace AxWin { CSurface::CSurface(int x, int y, unsigned int w, unsigned int h): m_rect(x,y, w,h) { + if( w > 0 && h > 0 ) + { + m_data = new uint32_t[w * h]; + } } CSurface::~CSurface() @@ -21,12 +27,36 @@ CSurface::~CSurface() void CSurface::Resize(unsigned int W, unsigned int H) { - assert(!"TODO: CSurface::Resize"); + // Easy realloc + // TODO: Should I maintain window contents sanely? NOPE! + delete m_data; + m_data = new uint32_t[W * H]; + 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 ) + throw ::std::out_of_range("CSurface::DrawScanline x_ofs"); + + if( w > m_rect.m_w ) + throw ::std::out_of_range("CSurface::DrawScanline width"); + + _SysDebug(" memcpy(%p, %p, %i)", &m_data[row*m_rect.m_w + x_ofs], data, w*4 ); + ::memcpy( &m_data[row*m_rect.m_w + x_ofs], data, w*4 ); } const uint32_t* CSurface::GetScanline(unsigned int row, unsigned int x_ofs) const { - return 0; + if( row >= m_rect.m_h ) + throw ::std::out_of_range("CSurface::GetScanline row"); + if( x_ofs >= m_rect.m_w ) + throw ::std::out_of_range("CSurface::GetScanline x_ofs"); + + return &m_data[row * m_rect.m_w + x_ofs]; } diff --git a/Usermode/Applications/axwin4_src/Server/include/CRect.hpp b/Usermode/Applications/axwin4_src/Server/include/CRect.hpp index e8f9dc82..708186ac 100644 --- a/Usermode/Applications/axwin4_src/Server/include/CRect.hpp +++ b/Usermode/Applications/axwin4_src/Server/include/CRect.hpp @@ -15,6 +15,7 @@ public: CRect(int X, int Y, unsigned int W, unsigned int H); void Move(int NewX, int NewY); + void Resize(int NewW, int NewH); bool HasIntersection(const CRect& other) const; CRect Intersection(const CRect& other) const; diff --git a/Usermode/Applications/axwin4_src/Server/include/CSurface.hpp b/Usermode/Applications/axwin4_src/Server/include/CSurface.hpp index c0c6c8b9..488d4d6c 100644 --- a/Usermode/Applications/axwin4_src/Server/include/CSurface.hpp +++ b/Usermode/Applications/axwin4_src/Server/include/CSurface.hpp @@ -16,6 +16,7 @@ public: void Resize(unsigned int new_w, unsigned int new_h); + void DrawScanline(unsigned int row, unsigned int x_ofs, unsigned int w, const void* data); const uint32_t* GetScanline(unsigned int row, unsigned int x_ofs) const; CRect m_rect; diff --git a/Usermode/Applications/axwin4_src/Server/ipc.cpp b/Usermode/Applications/axwin4_src/Server/ipc.cpp index 4e5ba76b..70605fc0 100644 --- a/Usermode/Applications/axwin4_src/Server/ipc.cpp +++ b/Usermode/Applications/axwin4_src/Server/ipc.cpp @@ -39,9 +39,10 @@ void Initialise(const CConfigIPC& config, CCompositor& compositor) int FillSelect(fd_set& rfds) { int ret = 0; - for( auto channel : glChannels ) + for( const auto channel : glChannels ) { _SysDebug("IPC::FillSelect - channel=%p", channel); + assert(channel); ret = ::std::max(ret, channel->FillSelect(rfds)); } return ret; @@ -49,8 +50,9 @@ int FillSelect(fd_set& rfds) void HandleSelect(const fd_set& rfds) { - for( auto channel : glChannels ) + for( const auto channel : glChannels ) { + assert(channel); channel->HandleSelect(rfds); } } @@ -70,7 +72,7 @@ void DeregisterClient(CClient& client) void SendNotify_Dims(CClient& client, unsigned int NewW, unsigned int NewH) { - assert(!"TODO: CClient::SendNotify_Dims"); + _SysDebug("TODO: CClient::SendNotify_Dims"); } @@ -216,7 +218,29 @@ void HandleMessage_GetWindowBuffer(CClient& client, CDeserialiser& message) void HandleMessage_PushData(CClient& client, CDeserialiser& message) { - assert(!"TODO HandleMessage_PushData"); + uint16_t win_id = message.ReadU16(); + uint16_t x = message.ReadU16(); + 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); + + CWindow* win = client.GetWindow(win_id); + if(!win) { + throw IPC::CClientFailure("_PushData: Bad window"); + } + + for( unsigned int row = 0; row < h; row ++ ) + { + const ::std::vector scanline_data = message.ReadBuffer(); + _SysDebug("_PushData: Scanline %i: %i bytes", row, scanline_data.size()); + if( scanline_data.size() != w * 4 ) { + _SysDebug("ERROR _PushData: Scanline buffer size mismatch (%i,%i)", + scanline_data.size(), w*4); + continue ; + } + win->m_surface.DrawScanline(y+row, x, w, scanline_data.data()); + } } void HandleMessage_Blit(CClient& client, CDeserialiser& message) { diff --git a/Usermode/Libraries/libaxwin4.so_src/window_drawing.cpp b/Usermode/Libraries/libaxwin4.so_src/window_drawing.cpp index 6f2f898b..e074ee40 100644 --- a/Usermode/Libraries/libaxwin4.so_src/window_drawing.cpp +++ b/Usermode/Libraries/libaxwin4.so_src/window_drawing.cpp @@ -12,38 +12,35 @@ namespace AxWin { +void _push_data(tAxWin4_Window *Window, int X, int Y, unsigned int W, unsigned int H, const void *Data) +{ + CSerialiser message; + message.WriteU8(IPCMSG_PUSHDATA); + message.WriteU16(Window->m_id); + message.WriteU16(X); + message.WriteU16(Y); + message.WriteU16(W); + message.WriteU16(H); + message.WriteBuffer(H*W*4, Data); + ::AxWin::SendMessage(message); +} + extern "C" void AxWin4_DrawBitmap(tAxWin4_Window *Window, int X, int Y, unsigned int W, unsigned int H, void *Data) { // TODO: Split message up into blocks such that it can be dispatched if( W > 128 ) { const uint32_t* data32 = static_cast(Data); - const unsigned int rows_per_message = 2048 / W; + const unsigned int rows_per_message = 1; // 2048 / W; for( unsigned int row = 0; row < H; row += rows_per_message ) { - CSerialiser message; - message.WriteU8(IPCMSG_PUSHDATA); - message.WriteU16(Window->m_id); - message.WriteU16(X); - message.WriteU16(Y+row); - message.WriteU16(W); - message.WriteU16( ::std::min(rows_per_message,H-row) ); - message.WriteBuffer(W*4, data32); - ::AxWin::SendMessage(message); + _push_data(Window, X, Y+row, W, ::std::min(rows_per_message,H-row), data32); data32 += W*rows_per_message; } } else { - CSerialiser message; - message.WriteU8(IPCMSG_PUSHDATA); - message.WriteU16(Window->m_id); - message.WriteU16(X); - message.WriteU16(Y); - message.WriteU16(W); - message.WriteU16(H); - message.WriteBuffer(W*H*4, Data); - ::AxWin::SendMessage(message); + _push_data(Window, X, Y, W, H, Data); } } -- 2.20.1