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)
::uint8_t ReadU8();
::uint16_t ReadU16();
::int16_t ReadS16();
+ ::uint32_t ReadU32();
+ ::uint64_t ReadU64();
const ::std::vector<uint8_t> ReadBuffer();
const ::std::string ReadString();
private:
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) {
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<uint8_t> CDeserialiser::ReadBuffer()
{
RangeCheck("CDeserialiser::ReadBuffer(len)", 2);
}
}
+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<const uint8_t*>(val);
const ::std::vector<uint8_t>& 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());
}
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) );
#include <cassert>
#include <stdexcept>
#include <cstring>
+#include <system_error>
+#include <cerrno>
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 )
{
{
}
-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<uint32_t*>( _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 )
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
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
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);
CRect m_rect;
uint32_t* m_data;
+private:
+ int m_fd;
};
}; // namespace AxWin
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)
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) {
[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
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)},
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()
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");
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
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 );
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);
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);
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