2 Copyright 2017, The AROS Development Team. All rights reserved.
7 #include <aros/debug.h>
9 #include <proto/exec.h>
10 #include <proto/dos.h>
11 #include <proto/processor.h>
12 #include <proto/kernel.h>
14 #include <proto/dos.h>
15 #include <proto/graphics.h>
16 #include <proto/cybergraphics.h>
17 #include <proto/intuition.h>
18 #include <proto/timer.h>
20 #include <exec/tasks.h>
21 #include <exec/ports.h>
22 #include <exec/lists.h>
23 #include <exec/rawfmt.h>
24 #include <resources/processor.h>
25 #include <cybergraphx/cybergraphics.h>
29 CONST_STRPTR version
= "$VER: SMP-Smallpt 1.0 (03.03.2017) ©2017 The AROS Development Team";
33 struct Window
* createMainWindow(int req_width
, int req_height
)
35 struct Screen
*pubScreen
;
36 struct Window
*displayWin
= NULL
;
39 pubScreen
= LockPubScreen(0);
43 width
= ((pubScreen
->Width
* 4) / 5) & ~0x1f;
44 height
= (width
* 3 / 4) & ~0x1f;
46 if (req_width
&& req_width
< width
)
47 width
= req_width
& ~0x1f;
48 if (req_height
&& req_height
< height
)
49 height
= req_height
& ~0x1f;
51 if (height
>= (pubScreen
->Height
* 4) / 5)
53 height
= ((pubScreen
->Height
* 4) / 5) & ~0x1f;
54 width
= (height
* 4 / 3) & ~0x1f;
63 if ((displayWin
= OpenWindowTags(0,
64 WA_PubScreen
, (IPTR
)pubScreen
,
66 WA_Top
, (pubScreen
) ? pubScreen
->BarHeight
: 10,
68 WA_InnerHeight
, height
,
69 WA_Title
, (IPTR
) "SMP-Smallpt renderer",
70 WA_SimpleRefresh
, TRUE
,
75 WA_SizeBBottom
, FALSE
,
77 WA_IDCMP
, IDCMP_CLOSEWINDOW
| IDCMP_REFRESHWINDOW
,
81 UnlockPubScreen(0, pubScreen
);
87 #define ARG_TEMPLATE "MAXCPU/N,MAXITER/N,WIDTH/N,HEIGHT/N,RAYDEPTH/N,EXPLICIT/S"
92 #define ARG_RAYDEPTH 4
93 #define ARG_EXPLICIT 5
98 IPTR args
[6] = { 0, 0, 0, 0, 0, 0 };
102 int req_width
= 0, req_height
= 0;
104 int explicit_mode
= 0;
105 struct MsgPort
*timerPort
= CreateMsgPort();
106 struct timerequest
*tr
= CreateIORequest(timerPort
, sizeof(struct timerequest
));
107 struct TimerBase
*TimerBase
= NULL
;
108 struct timeval start_time
;
111 struct Window
*displayWin
;
112 struct BitMap
*outputBMap
= NULL
;
115 struct TagItem tags
[] =
117 {GCIT_NumberOfProcessors
, (IPTR
)&coreCount
},
120 ProcessorBase
= OpenResource(PROCESSORNAME
);
124 KernelBase
= OpenResource("kernel.resource");
130 FreeSignal(timerPort
->mp_SigBit
);
131 timerPort
->mp_SigBit
= -1;
132 timerPort
->mp_Flags
= PA_IGNORE
;
137 if (!OpenDevice("timer.device", UNIT_VBLANK
, (struct IORequest
*)tr
, 0))
139 TimerBase
= (struct TimerBase
*)tr
->tr_node
.io_Device
;
145 D(bug("[SMP-Smallpt] %s: detected %d CPU cores\n", __func__
, coreCount
);)
147 rda
= ReadArgs(ARG_TEMPLATE
, args
, NULL
);
150 LONG
*ptr
= (LONG
*)args
[ARG_MAXCPU
];
154 ptr
= (LONG
*)args
[ARG_RAYDEPTH
];
156 maximal_ray_depth
= *ptr
;
157 if (maximal_ray_depth
< 2)
158 maximal_ray_depth
= 2;
161 ptr
= (LONG
*)args
[ARG_MAXITER
];
167 else if (max_iter
> 10000)
171 ptr
= (LONG
*)args
[ARG_WIDTH
];
175 if (req_width
&& req_width
< 160)
178 if (req_height
&& req_height
< 128)
181 ptr
= (LONG
*)args
[ARG_HEIGHT
];
185 if (max_cpus
> 0 && coreCount
> max_cpus
)
186 coreCount
= max_cpus
;
191 explicit_mode
= args
[ARG_EXPLICIT
];
194 // NewRawDoFmt("Hello %s", RAWFMTFUNC_STRING, buffer, "world!");
196 displayWin
= createMainWindow(req_width
, req_height
);
200 struct RastPort
*outBMRastPort
;
202 int windowClosing
= FALSE
;
203 struct MsgPort
*mainPort
= CreateMsgPort();
204 struct MsgPort
*rendererPort
= NULL
;
206 struct Task
*renderer
;
208 struct MyMessage cmd
;
209 BOOL busyPointer
= FALSE
;
214 width
= (displayWin
->Width
- displayWin
->BorderLeft
- displayWin
->BorderRight
);
215 height
= (displayWin
->Height
- displayWin
->BorderTop
- displayWin
->BorderBottom
);
217 D(bug("[SMP-Smallpt] %s: Created window with inner size of %dx%d\n", __func__
, width
, height
);)
218 D(bug("[SMP-Smallpt] %s: Tiles amount %dx%d\n", __func__
, width
/ 32, height
/ 32);)
220 outputBMap
= AllocBitMap(
223 GetBitMapAttr(displayWin
->WScreen
->RastPort
.BitMap
, BMA_DEPTH
),
224 BMF_DISPLAYABLE
, displayWin
->WScreen
->RastPort
.BitMap
);
226 outBMRastPort
= CreateRastPort();
227 outBMRastPort
->BitMap
= outputBMap
;
229 workBuffer
= AllocMem(width
* height
* sizeof(ULONG
), MEMF_ANY
|MEMF_CLEAR
);
231 WritePixelArray(workBuffer
,
232 0, 0, width
* sizeof(ULONG
),
238 BltBitMapRastPort (outputBMap
, 0, 0,
239 displayWin
->RPort
, displayWin
->BorderLeft
, displayWin
->BorderTop
,
240 width
, height
, 0xC0);
242 D(bug("[SMP-Smallpt] %s: Creating renderer task\n", __func__
);)
244 renderer
= NewCreateTask(TASKTAG_NAME
, "SMP-Smallpt Master",
245 TASKTAG_AFFINITY
, TASKAFFINITY_ANY
,
247 TASKTAG_PC
, Renderer
,
248 TASKTAG_ARG1
, SysBase
,
249 TASKTAG_ARG2
, mainPort
,
250 //TASKTAG_STACKSIZE, 10000000,
251 //TASKTAG_USERDATA , &workMaster,
255 D(bug("[SMP-Smallpt] %s: waiting for welcome message form renderer\n", __func__
);)
257 msg
= GetMsg(mainPort
);
258 rendererPort
= msg
->mn_ReplyPort
;
261 cmd
.mm_Type
= MSG_STARTUP
;
262 cmd
.mm_Message
.mn_Length
= sizeof(cmd
);
263 cmd
.mm_Message
.mn_ReplyPort
= mainPort
;
264 cmd
.mm_Body
.Startup
.ChunkyBM
= workBuffer
;
265 cmd
.mm_Body
.Startup
.Width
= width
;
266 cmd
.mm_Body
.Startup
.Height
= height
;
267 cmd
.mm_Body
.Startup
.coreCount
= coreCount
;
268 cmd
.mm_Body
.Startup
.numberOfSamples
= max_iter
;
269 cmd
.mm_Body
.Startup
.explicitMode
= explicit_mode
;
271 D(bug("[SMP-Smallpt] %s: renderer alive. sending startup message\n", __func__
);)
273 PutMsg(rendererPort
, &cmd
.mm_Message
);
277 D(bug("[SMP-Smallpt] %s: enter main loop\n", __func__
);)
279 GetSysTime(&start_time
);
281 while ((!windowClosing
) && ((signals
= Wait(SIGBREAKF_CTRL_D
| (1 << displayWin
->UserPort
->mp_SigBit
) | (1 << mainPort
->mp_SigBit
))) != 0))
283 // CTRL_D is redraw signal
284 if (signals
& SIGBREAKF_CTRL_D
)
286 WritePixelArray(workBuffer
,
287 0, 0, width
* sizeof(ULONG
),
293 BltBitMapRastPort (outputBMap
, 0, 0,
294 displayWin
->RPort
, displayWin
->BorderLeft
, displayWin
->BorderTop
,
295 width
, height
, 0xC0);
297 if (signals
& (1 << displayWin
->UserPort
->mp_SigBit
))
299 struct IntuiMessage
*msg
;
300 while ((msg
= (struct IntuiMessage
*)GetMsg(displayWin
->UserPort
)))
304 case IDCMP_CLOSEWINDOW
:
305 D(bug("[SMP-Smallpt] %s: window closing pressed\n", __func__
);)
307 windowClosing
= TRUE
;
310 case IDCMP_REFRESHWINDOW
:
311 D(bug("[SMP-Smallpt] %s: Displaying output BitMap (REFRESHWINDOW)\n", __func__
);)
312 BeginRefresh(msg
->IDCMPWindow
);
313 BltBitMapRastPort (outputBMap
, 0, 0,
314 msg
->IDCMPWindow
->RPort
, msg
->IDCMPWindow
->BorderLeft
, msg
->IDCMPWindow
->BorderTop
,
315 width
, height
, 0xC0);
316 EndRefresh(msg
->IDCMPWindow
, TRUE
);
319 ReplyMsg((struct Message
*)msg
);
322 if (signals
& (1 << mainPort
->mp_SigBit
))
324 struct MyMessage
*msg
;
326 while ((msg
= (struct MyMessage
*)GetMsg(mainPort
)))
328 if (msg
->mm_Message
.mn_Length
== sizeof(struct MyMessage
))
330 switch (msg
->mm_Type
)
333 WritePixelArray(workBuffer
,
334 msg
->mm_Body
.RedrawTile
.TileX
* TILE_SIZE
,
335 msg
->mm_Body
.RedrawTile
.TileY
* TILE_SIZE
, width
* sizeof(ULONG
),
337 msg
->mm_Body
.RedrawTile
.TileX
* TILE_SIZE
,
338 msg
->mm_Body
.RedrawTile
.TileY
* TILE_SIZE
,
339 TILE_SIZE
, TILE_SIZE
, RECTFMT_ARGB
);
341 BltBitMapRastPort (outputBMap
,
342 msg
->mm_Body
.RedrawTile
.TileX
* TILE_SIZE
,
343 msg
->mm_Body
.RedrawTile
.TileY
* TILE_SIZE
,
345 displayWin
->BorderLeft
+ msg
->mm_Body
.RedrawTile
.TileX
* TILE_SIZE
, displayWin
->BorderTop
+ msg
->mm_Body
.RedrawTile
.TileY
* TILE_SIZE
,
346 TILE_SIZE
, TILE_SIZE
, 0xC0);
350 tasksWork
= msg
->mm_Body
.Stats
.tasksWork
;
351 tasksIn
= msg
->mm_Body
.Stats
.tasksIn
;
352 tasksOut
= msg
->mm_Body
.Stats
.tasksOut
;
355 SubTime(&now
, &start_time
);
356 NewRawDoFmt("SMP-Smallpt renderer (%d in work, %d waiting, %d done): %d:%02d:%02d", RAWFMTFUNC_STRING
,
357 tmpbuf
, tasksWork
, tasksIn
, tasksOut
,
359 (now
.tv_secs
/ 60) % 60,
361 SetWindowTitles(displayWin
, tmpbuf
, NULL
);
362 if ((busyPointer
) && (msg
->mm_Body
.Stats
.tasksWork
== 0))
364 SetWindowPointer(displayWin
, WA_BusyPointer
, FALSE
, TAG_DONE
);
367 else if ((!busyPointer
) && (msg
->mm_Body
.Stats
.tasksWork
> 0))
369 SetWindowPointer(displayWin
, WA_BusyPointer
, TRUE
, TAG_DONE
);
375 D(bug("[SMP-Smallpt] %s: unhandled message (%d) arrived\n", __func__
, msg
->mm_Type
);)
377 ReplyMsg(&msg
->mm_Message
);
383 D(bug("[SMP-Smallpt] %s: Send DIE msg to renderer\n", __func__
);)
385 struct MyMessage quitmsg
;
386 quitmsg
.mm_Message
.mn_ReplyPort
= mainPort
;
387 quitmsg
.mm_Message
.mn_Length
= sizeof(quitmsg
);
388 quitmsg
.mm_Type
= MSG_DIE
;
390 PutMsg(rendererPort
, &quitmsg
.mm_Message
);
394 struct MyMessage
*msg
;
395 while ((msg
= (struct MyMessage
*)GetMsg(mainPort
)))
396 if (msg
->mm_Type
== MSG_DIE
)
400 DeleteMsgPort(mainPort
);
402 CloseWindow(displayWin
);
403 FreeRastPort(outBMRastPort
);
404 FreeBitMap(outputBMap
);
405 FreeMem(workBuffer
, width
* height
* sizeof(ULONG
));
407 D(bug("[SMP-Smallpt] %s: goodbye\n", __func__
);)
409 for (int ty
= 0; ty
< height
/32; ty
++)
411 for (int tx
= 0; tx
< width
/32; tx
++)
413 D(bug("[SMP-Smallpt] %s: Rendering tile %d,%d\n", __func__
, tx
, ty
));
415 render_tile(width
, height
, 1024, tx
, ty
, workBuffer
);
417 D(bug("[SMP-Smallpt] %s: Redrawing\n", __func__
));
419 WritePixelArray(workBuffer
,
420 tx
*32, ty
*32, width
* sizeof(ULONG
),
426 BltBitMapRastPort (outputBMap
, tx
*32, ty
*32,
427 displayWin
->RPort
, displayWin
->BorderLeft
+ tx
*32, displayWin
->BorderTop
+ ty
*32,