::uint8_t ReadU8();
::uint16_t ReadU16();
::int16_t ReadS16();
+ const ::std::vector<uint8_t> ReadBuffer();
const ::std::string ReadString();
private:
void RangeCheck(const char *Method, size_t bytes) throw(::std::out_of_range);
return ~rv_u + 1;
}
+const ::std::vector<uint8_t> CDeserialiser::ReadBuffer()
+{
+ RangeCheck("CDeserialiser::ReadBuffer(len)", 2);
+ size_t size = ReadU16();
+
+ ::std::vector<uint8_t> 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);
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
*/
#include <CSurface.hpp>
#include <cassert>
+#include <stdexcept>
+#include <cstring>
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()
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];
}
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;
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;
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;
void HandleSelect(const fd_set& rfds)
{
- for( auto channel : glChannels )
+ for( const auto channel : glChannels )
{
+ assert(channel);
channel->HandleSelect(rfds);
}
}
void SendNotify_Dims(CClient& client, unsigned int NewW, unsigned int NewH)
{
- assert(!"TODO: CClient::SendNotify_Dims");
+ _SysDebug("TODO: CClient::SendNotify_Dims");
}
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<uint8_t> 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)
{
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<uint32_t*>(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);
}
}