Merge branch 'master' of git://github.com/thepowersgang/acess2
[tpg/acess2.git] / Usermode / Applications / axwin4_src / Server / CSurface.cpp
1 /*
2  * Acess2 GUI v4
3  * - By John Hodge (thePowersGang)
4  *
5  * CWindow.cpp
6  * - Window
7  */
8 #include <CSurface.hpp>
9 #include <cassert>
10 #include <stdexcept>
11 #include <cstring>
12 #include <system_error>
13 #include <cerrno>
14 #include <CColour.hpp>
15
16 namespace AxWin {
17
18 CSurface::CSurface(int x, int y, unsigned int w, unsigned int h):
19         m_rect(x,y, w,h),
20         m_fd(-1),
21         m_data(0)
22 {
23         if( w > 0 && h > 0 )
24         {
25                 m_data = new uint32_t[w * h];
26         }
27 }
28
29 CSurface::~CSurface()
30 {
31         if( m_fd == -1 ) {
32                 delete[] m_data;
33         }
34         else {
35                 size_t  size = m_rect.m_w*m_rect.m_h*4;
36                 _SysMUnMap(m_data, size);
37         }
38 }
39
40 uint64_t CSurface::GetSHMHandle()
41 {
42         size_t  size = m_rect.m_w*m_rect.m_h*4;
43         if( m_fd == -1 )
44         {
45                 // 2. Allocate a copy in SHM
46                 m_fd = _SysOpen("/Devices/shm/anon", OPENFLAG_WRITE|OPENFLAG_READ);
47                 if(m_fd == -1) {
48                         _SysDebug("GetSHMHandle: Unable to open anon SHM");
49                         return -1;
50                 }
51                 // 1. Free local buffer
52                 delete m_data;
53                 _SysTruncate(m_fd, size);
54         }
55         else
56         {
57                 _SysMUnMap(m_data, size);
58         }
59         // 3. mmap shm copy
60         m_data = static_cast<uint32_t*>( _SysMMap(nullptr, size, MMAP_PROT_WRITE, 0, m_fd, 0) );
61         if(!m_data)     throw ::std::system_error(errno, ::std::system_category());
62         
63         return _SysMarshalFD(m_fd);
64 }
65
66 void CSurface::Resize(unsigned int W, unsigned int H)
67 {
68         if( m_fd == -1 )
69         {
70                 // Easy realloc
71                 // TODO: Should I maintain window contents sanely? NOPE!
72                 delete m_data;
73                 m_data = new uint32_t[W * H];
74         }
75         else
76         {
77                 //_SysIOCtl(m_fd, SHM_IOCTL_SETSIZE, W*H*4);
78         }
79         m_rect.Resize(W, H);
80 }
81
82 void CSurface::DrawScanline(unsigned int row, unsigned int x_ofs, unsigned int w, const void* data)
83 {
84         if( row >= m_rect.m_h )
85                 throw ::std::out_of_range("CSurface::DrawScanline row");
86         if( x_ofs >= m_rect.m_w )
87                 throw ::std::out_of_range("CSurface::DrawScanline x_ofs");
88
89         if( w > m_rect.m_w )
90                 throw ::std::out_of_range("CSurface::DrawScanline width");
91         
92         size_t  ofs = row*m_rect.m_w + x_ofs;
93         ::memcpy( &m_data[ofs], data, w*4 );
94 }
95
96 void CSurface::BlendScanline(unsigned int row, unsigned int x_ofs, unsigned int w, const void* data)
97 {
98         if( row >= m_rect.m_h )
99                 throw ::std::out_of_range("CSurface::DrawScanline row");
100         if( x_ofs >= m_rect.m_w )
101                 throw ::std::out_of_range("CSurface::DrawScanline x_ofs");
102
103         if( w > m_rect.m_w )
104                 throw ::std::out_of_range("CSurface::DrawScanline width");
105         
106         const uint32_t* in_data = (const uint32_t*)data;
107         size_t  ofs = row*m_rect.m_w + x_ofs;
108         for( unsigned int x = 0; x < w; x ++ )
109         {
110                 CColour out = CColour::from_argb(m_data[ofs+x]).blend( CColour::from_argb(in_data[x]) );
111                 m_data[ofs+x] = out.to_argb();
112         }
113 }
114
115 void CSurface::FillScanline(unsigned int row, unsigned int x_ofs, unsigned int w, uint32_t colour)
116 {
117         if( row >= m_rect.m_h )
118                 throw ::std::out_of_range("CSurface::FillScanline row");
119         if( x_ofs >= m_rect.m_w )
120                 throw ::std::out_of_range("CSurface::FillScanline x_ofs");
121
122         if( w > m_rect.m_w )
123                 throw ::std::out_of_range("CSurface::FillScanline width");
124         
125         size_t  ofs = row*m_rect.m_w + x_ofs;
126         while( w -- )
127                 m_data[ofs++] = colour;
128 }
129
130 const uint32_t* CSurface::GetScanline(unsigned int row, unsigned int x_ofs) const
131 {
132         if( row >= m_rect.m_h )
133                 throw ::std::out_of_range("CSurface::GetScanline row");
134         if( x_ofs >= m_rect.m_w )
135                 throw ::std::out_of_range("CSurface::GetScanline x_ofs");
136
137         return &m_data[row * m_rect.m_w + x_ofs];
138 }
139
140
141 };      // namespace AxWin
142
143

UCC git Repository :: git.ucc.asn.au