Merge branch 'master' of git://localhost/acess2
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / renderers / framebuffer.c
1 /*
2  * Acess2 Window Manager v3
3  * - By John Hodge (thePowersGang)
4  *
5  * renderer_passthru.c
6  * - Passthrough window render (framebuffer essentially)
7  */
8 #include <common.h>
9 #include <wm_renderer.h>
10 #include <string.h>
11 #include <framebuffer_messages.h>
12 #include <wm_messages.h>
13
14 // === TYPES ===
15 typedef struct
16 {
17         short   W, H;
18         void    *Data;
19 } tFBBuffer;
20 typedef struct
21 {
22         tFBBuffer       BackBuffer;
23          int    MaxBufferCount;
24         tFBBuffer       *Buffers[];
25 } tFBWin;
26
27 // === PROTOTYPES ===
28 tWindow *Renderer_Framebuffer_Create(int Flags);
29 void    Renderer_Framebuffer_Redraw(tWindow *Window);
30  int    _Handle_Commit(tWindow *Target, size_t Len, const void *Data);
31  int    _Handle_CreateBuf(tWindow *Target, size_t Len, const void *Data);
32  int    Renderer_Framebuffer_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
33
34 // === GLOBALS ===
35 tWMRenderer     gRenderer_Framebuffer = {
36         .Name = "FrameBuffer",
37         .CreateWindow = Renderer_Framebuffer_Create,
38         .Redraw = Renderer_Framebuffer_Redraw,
39         .HandleMessage = Renderer_Framebuffer_HandleMessage,
40         .nIPCHandlers = N_IPC_FB,
41         .IPCHandlers = {
42                 [IPC_FB_COMMIT] = _Handle_Commit,
43                 [IPC_FB_NEWBUF] = _Handle_CreateBuf,
44         }
45 };
46
47 // === CODE ===
48 int Renderer_Framebuffer_Init(void)
49 {
50         WM_RegisterRenderer(&gRenderer_Framebuffer);
51         return 0;
52 }
53
54 tWindow *Renderer_Framebuffer_Create(int Flags)
55 {
56         tWindow *ret;
57         tFBWin  *info;
58         const int       max_buffers = 10;       // TODO: Have this be configurable
59         
60         ret = WM_CreateWindowStruct( sizeof(*info) + max_buffers*sizeof(tFBBuffer*) );
61         info = ret->RendererInfo;
62         
63         info->BackBuffer.W = 0;
64         info->BackBuffer.H = 0;
65         info->BackBuffer.Data = NULL;
66         info->MaxBufferCount = max_buffers;
67         memset( info->Buffers, 0, sizeof(tFBBuffer*) * max_buffers );
68         
69         return ret;
70 }
71
72 void Renderer_Framebuffer_Redraw(tWindow *Window)
73 {
74         
75 }
76
77 // --- ---
78 tFBBuffer *_GetBuffer(tWindow *Win, uint16_t ID)
79 {
80         tFBWin  *info = Win->RendererInfo;
81         if( ID == 0xFFFF )
82                 return &info->BackBuffer;
83         else if( ID >= info->MaxBufferCount )
84                 return NULL;
85         else
86                 return info->Buffers[ ID ];
87 }
88
89 void _Blit(
90         tFBBuffer *Dest, uint16_t DX, uint16_t DY,
91         const tFBBuffer *Src, uint16_t SX, uint16_t SY,
92         uint16_t W, uint16_t H
93         )
94 {
95         uint32_t        *dest_data = Dest->Data;
96         const uint32_t  *src_data = Src->Data;
97         // First, some sanity
98         if( DX > Dest->W )      return ;
99         if( DY > Dest->H )      return ;
100         if( SX > Src->W )       return ;
101         if( SY > Src->H )       return ;
102         
103         if( DX + W > Dest->W )  W = Dest->W - DX;
104         if( SX + W > Src->W )   W = Src->W - SX;
105         if( DY + H > Dest->H )  H = Dest->H - DY;
106         if( SY + H > Src->H )   H = Src->H - SY;
107         
108         dest_data += (DY * Dest->W) + DX;
109         src_data  += (SY * Src->W ) + SX;
110         for( int i = 0; i < H; i ++ )
111         {
112                 memcpy( dest_data, src_data, W * 4 );
113                 dest_data += Dest->W;
114                 src_data += Src->W;
115         }
116 }
117
118 void _Fill(tFBBuffer *Buf, uint16_t X, uint16_t Y, uint16_t W, uint16_t H, uint32_t Colour)
119 {
120         uint32_t        *data = Buf->Data;
121         
122         if( X > Buf->W )        return ;
123         if( Y > Buf->H )        return ;
124         if( X + W > Buf->W )    W = Buf->W - X;
125         if( Y + H > Buf->H )    H = Buf->H - Y;
126         
127         data += (Y * Buf->W) + X;
128         for( int i = 0; i < H; i ++ )
129         {
130                 for( int j = 0; j < W; j ++ )
131                         *data++ = Colour;
132                 data += Buf->W - W;
133         }
134 }
135
136 // --- ---
137 int _Handle_Commit(tWindow *Target, size_t Len, const void *Data)
138 {
139         // Do a window invalidate
140         return 0;
141 }
142
143 int _Handle_CreateBuf(tWindow *Target, size_t Len, const void *Data)
144 {
145         const tFBIPC_NewBuf     *msg = Data;
146         tFBBuffer       *buf;
147         tFBWin  *info = Target->RendererInfo;
148         
149         if( Len < sizeof(*msg) )        return -1;
150         
151         if( msg->Buffer == -1 || msg->Buffer >= info->MaxBufferCount ) {
152                 // Can't reallocate -1
153                 return 1;
154         }
155         
156         if( info->Buffers[msg->Buffer] ) {
157                 free(info->Buffers[msg->Buffer]);
158                 info->Buffers[msg->Buffer] = NULL;
159         }
160         
161         buf = malloc(sizeof(tFBBuffer) + msg->W * msg->H * 4);
162         buf->W = msg->W;
163         buf->H = msg->H;
164         buf->Data = buf + 1;
165         
166         info->Buffers[msg->Buffer] = buf;
167         
168         return 0;
169 }
170
171 int _Handle_Upload(tWindow *Target, size_t Len, const void *Data)
172 {
173         const tFBIPC_Transfer   *msg = Data;
174         tFBBuffer       *dest, src;
175         
176         if( Len < sizeof(*msg) )        return -1;
177         if( Len < sizeof(*msg) + msg->W * msg->H * 4 )  return -1;
178         
179         dest = _GetBuffer(Target, msg->Buffer);
180
181         src.W = msg->W; 
182         src.H = msg->H; 
183         src.Data = (void*)msg->ImageData;
184
185         _Blit( dest, msg->X, msg->Y,  &src, 0, 0,  msg->W, msg->H );
186         return 0;
187 }
188
189 int _Handle_Download(tWindow *Target, size_t Len, const void *Data)
190 {
191         const tFBIPC_Transfer   *msg = Data;
192         tFBBuffer       dest, *src;
193         
194         if( Len < sizeof(*msg) )        return -1;
195         
196         src = _GetBuffer(Target, msg->Buffer);
197
198         tFBIPC_Transfer *ret;
199          int    retlen = sizeof(*ret) + msg->W*msg->H*4;
200         ret = malloc( retlen );
201
202         dest.W = ret->W = msg->W;
203         dest.H = ret->H = msg->H;
204         dest.Data = ret->ImageData;
205         
206         _Blit( &dest, 0, 0,  src, msg->X, msg->Y,  msg->W, msg->H );
207
208         WM_SendIPCReply(Target, IPC_FB_DOWNLOAD, retlen, ret);
209
210         free(ret);
211
212         return 0;
213 }
214
215 int _Handle_LocalBlit(tWindow *Target, size_t Len, const void *Data)
216 {
217         const tFBIPC_Blit       *msg = Data;
218         tFBBuffer       *dest, *src;
219         
220         if( Len < sizeof(*msg) )        return -1;
221         
222         src = _GetBuffer(Target, msg->Source);
223         dest = _GetBuffer(Target, msg->Dest);
224
225         _Blit( dest, msg->DstX, msg->DstY,  src, msg->SrcX, msg->SrcY,  msg->W, msg->H );
226         return 0;
227 }
228
229 int _Handle_FillRect(tWindow *Target, size_t Len, const void *Data)
230 {
231         const tFBIPC_Fill       *msg = Data;
232         tFBBuffer       *dest;
233         
234         if( Len < sizeof(*msg) )        return -1;
235         
236         dest = _GetBuffer(Target, msg->Buffer);
237         
238         _Fill( dest, msg->X, msg->Y, msg->W, msg->H, msg->Colour );
239         return 0;
240 }
241
242 int Renderer_Framebuffer_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
243 {
244         switch(Msg)
245         {
246         case WNDMSG_RESIZE:
247                 // Resize the framebuffer
248                 return 1;       // Pass on
249         
250         // Messages that get passed on
251         case WNDMSG_MOUSEBTN:
252                 return 1;
253         }
254         return 1;
255 }
256
257

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