1
2#include <Application.h>
3#include <DirectWindow.h>
4#include <View.h>
5
6#include <stdio.h>
7#include <stdlib.h>
8
9#include "AccelerantHWInterface.h"
10#include "Desktop.h"
11#include "DirectWindowBuffer.h"
12#include "DrawingEngine.h"
13#include "DrawView.h"
14#include "ViewLayer.h"
15#include "WindowLayer.h"
16
17class App : public BApplication {
18 public:
19						App();
20
21	virtual void		ReadyToRun();
22};
23
24class Window : public BDirectWindow {
25 public:
26								Window(const char* title);
27	virtual						~Window();
28
29	virtual	bool				QuitRequested();
30
31	virtual void				DirectConnected(direct_buffer_info* info);
32
33			void				AddWindow(BRect frame, const char* name);
34			void				Test();
35 private:
36		DrawView*				fView;
37		Desktop*				fDesktop;
38		bool					fQuit;
39		DirectWindowBuffer		fBuffer;
40		AccelerantHWInterface	fInterface;
41		DrawingEngine			fEngine;
42
43};
44
45// constructor
46App::App()
47	: BApplication("application/x-vnd.stippi.ClippingTest")
48{
49	srand(real_time_clock_usecs());
50}
51
52// ReadyToRun
53void
54App::ReadyToRun()
55{
56	Window* win = new Window("clipping");
57	win->Show();
58
59//	win->Test();
60}
61
62// constructor
63Window::Window(const char* title)
64	: BDirectWindow(BRect(50, 50, 800, 650), title,
65					B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_ASYNCHRONOUS_CONTROLS),
66	  fQuit(false),
67	  fBuffer(),
68	  fInterface(),
69	  fEngine(&fInterface, &fBuffer)
70{
71	fInterface.Initialize();
72	fView = new DrawView(Bounds());
73	AddChild(fView);
74	fView->MakeFocus(true);
75
76	fDesktop = new Desktop(fView, &fEngine);
77	fDesktop->Run();
78}
79
80// destructor
81Window::~Window()
82{
83	fInterface.Shutdown();
84	fDesktop->Lock();
85	fDesktop->Quit();
86}
87
88// QuitRequested
89bool
90Window::QuitRequested()
91{
92/*	if (!fQuit) {
93		fDesktop->PostMessage(MSG_QUIT);
94		fQuit = true;
95		return false;
96	}*/
97be_app->PostMessage(B_QUIT_REQUESTED);
98	return true;
99}
100
101// #pragma mark -
102
103void
104fill_line_8(uint8* buffer, int32 pixels, uint8 r, uint8 g, uint8 b)
105{
106	for (int32 i = 0; i < pixels; i++) {
107		*buffer++ = b;
108		*buffer++ = g;
109		*buffer++ = r;
110		*buffer++ = 255;
111	}
112}
113
114void
115fill_line_32(uint8* buffer, int32 pixels, uint8 r, uint8 g, uint8 b)
116{
117	uint32 pixel;
118	uint32* handle = (uint32*)buffer;
119	for (int32 i = 0; i < pixels; i++) {
120		pixel = 0xff000000 | (r << 16) | (g << 8) | (b);
121		*handle++ = pixel;
122	}
123}
124
125void
126fill_line_64(uint8* buffer, int32 pixels, uint8 r, uint8 g, uint8 b)
127{
128	uint64 pixel;
129	uint64* handle = (uint64*)buffer;
130	pixels /= 2;
131	for (int32 i = 0; i < pixels; i++) {
132		pixel = 0xff000000 | (r << 16) | (g << 8) | (b);
133		pixel = pixel << 32;
134		pixel |= 0xff000000 | (r << 16) | (g << 8) | (b);
135		*handle++ = pixel;
136	}
137}
138
139void
140test1(uint8* buffer, uint32 bpr)
141{
142	uint8* handle = buffer;
143
144/*	bigtime_t start8 = system_time();
145	for (int32 x = 0; x < 1000; x++) {
146		handle = buffer;
147		for (int32 i = 0; i < 64; i++) {
148			fill_line_8(handle, 512, 255, 0, 255);
149			handle += bpr;
150		}
151	}
152
153	bigtime_t start32 = system_time();
154	for (int32 x = 0; x < 1000; x++) {
155		handle = buffer;
156		for (int32 i = 0; i < 64; i++) {
157			fill_line_32(handle, 512, 255, 0, 255);
158			handle += bpr;
159		}
160	}
161
162	bigtime_t start64 = system_time();
163	for (int32 x = 0; x < 1000; x++) {*/
164		handle = buffer;
165		for (int32 i = 0; i < 640; i++) {
166			fill_line_64(handle, 512, 0, 255, 255);
167			handle += bpr;
168		}
169/*	}
170
171
172	bigtime_t finish = system_time();
173	printf("8:  %lld\n", start32 - start8);
174	printf("32: %lld\n", start64 - start32);
175	printf("64: %lld\n", finish - start64);*/
176}
177
178// #pragma mark -
179
180void
181blend_line_8(uint8* buffer, int32 pixels, uint8 r, uint8 g, uint8 b, uint8 a)
182{
183	for (int32 i = 0; i < pixels; i++) {
184		buffer[0] = ((b - buffer[0]) * a + (buffer[0] << 8)) >> 8;
185		buffer[1] = ((g - buffer[1]) * a + (buffer[1] << 8)) >> 8;
186		buffer[2] = ((r - buffer[2]) * a + (buffer[2] << 8)) >> 8;;
187		buffer[3] = a;
188		buffer += 4;
189	}
190}
191
192union pixel {
193	uint32	data32;
194	uint8	data8[4];
195};
196
197void
198blend_line_32(uint8* buffer, int32 pixels, uint8 r, uint8 g, uint8 b, uint8 a)
199{
200	pixel p;
201	pixels /= 2;
202	for (int32 i = 0; i < pixels; i++) {
203		p.data32 = *(uint32*)buffer;
204
205		p.data8[0] = ((b - p.data8[0]) * a + (p.data8[0] << 8)) >> 8;
206		p.data8[1] = ((g - p.data8[1]) * a + (p.data8[1] << 8)) >> 8;
207		p.data8[2] = ((r - p.data8[2]) * a + (p.data8[2] << 8)) >> 8;
208		p.data8[3] = 255;
209		*((uint32*)buffer) = p.data32;
210		buffer += 4;
211
212		p.data32 = *(uint32*)buffer;
213
214		p.data8[0] = ((b - p.data8[0]) * a + (p.data8[0] << 8)) >> 8;
215		p.data8[1] = ((g - p.data8[1]) * a + (p.data8[1] << 8)) >> 8;
216		p.data8[2] = ((r - p.data8[2]) * a + (p.data8[2] << 8)) >> 8;
217		p.data8[3] = 255;
218		*((uint32*)buffer) = p.data32;
219		buffer += 4;
220	}
221}
222
223union pixel2 {
224	uint64	data64;
225	uint8	data8[8];
226};
227
228// gfxcpy32
229// * numBytes is expected to be a multiple of 4
230inline
231void
232gfxcpy32(uint8* dst, uint8* src, int32 numBytes)
233{
234	uint64* d64 = (uint64*)dst;
235	uint64* s64 = (uint64*)src;
236	int32 numBytesStart = numBytes;
237	while (numBytes >= 32) {
238		*d64++ = *s64++;
239		*d64++ = *s64++;
240		*d64++ = *s64++;
241		*d64++ = *s64++;
242		numBytes -= 32;
243	}
244	if (numBytes >= 16) {
245		*d64++ = *s64++;
246		*d64++ = *s64++;
247		numBytes -= 16;
248	}
249	if (numBytes >= 8) {
250		*d64++ = *s64++;
251		numBytes -= 8;
252	}
253	if (numBytes == 4) {
254		uint32* d32 = (uint32*)(dst + numBytesStart - numBytes);
255		uint32* s32 = (uint32*)(src + numBytesStart - numBytes);
256		*d32 = *s32;
257	}
258}
259
260void
261blend_line_64(uint8* buffer, int32 pixels, uint8 r, uint8 g, uint8 b, uint8 a)
262{
263	pixel2 p;
264	pixels /= 2;
265
266	r = (r * a) >> 8;
267	g = (g * a) >> 8;
268	b = (b * a) >> 8;
269	a = 255 - a;
270
271	uint8 tempBuffer[pixels * 8];
272
273	uint8* t = tempBuffer;
274	uint8* s = buffer;
275
276	for (int32 i = 0; i < pixels; i++) {
277		p.data64 = *(uint64*)s;
278
279		t[0] = ((p.data8[0] * a) >> 8) + b;
280		t[1] = ((p.data8[1] * a) >> 8) + g;
281		t[2] = ((p.data8[2] * a) >> 8) + r;
282
283		t[4] = ((p.data8[4] * a) >> 8) + b;
284		t[5] = ((p.data8[5] * a) >> 8) + g;
285		t[6] = ((p.data8[6] * a) >> 8) + r;
286
287		t += 8;
288		s += 8;
289	}
290
291	gfxcpy32(buffer, tempBuffer, pixels * 8);
292}
293void
294test2(uint8* buffer, uint32 bpr)
295{
296	uint8* handle = buffer;
297
298/*	bigtime_t start8 = system_time();
299//	for (int32 x = 0; x < 10; x++) {
300		handle = buffer;
301		for (int32 i = 0; i < 64; i++) {
302			blend_line_8(handle, 512, 255, 0, 0, 20);
303			handle += bpr;
304		}
305//	}
306
307	bigtime_t start32 = system_time();
308//	for (int32 x = 0; x < 10; x++) {
309		handle = buffer;
310		for (int32 i = 0; i < 64; i++) {
311			blend_line_32(handle, 512, 255, 0, 0, 20);
312			handle += bpr;
313		}
314//	}*/
315
316	bigtime_t start64 = system_time();
317//	for (int32 x = 0; x < 10; x++) {
318		handle = buffer;
319		for (int32 i = 0; i < 640; i++) {
320			blend_line_64(handle, 512, 255, 0, 0, 200);
321			handle += bpr;
322		}
323//	}
324
325	bigtime_t finish = system_time();
326//	printf("8:  %lld\n", start32 - start8);
327//	printf("32: %lld\n", start64 - start32);
328	printf("blend 64: %lld\n", finish - start64);
329}
330
331// #pragma mark -
332
333// DirectConnected
334void
335Window::DirectConnected(direct_buffer_info* info)
336{
337	// TODO: for some reason, this deadlocks
338	// on B_DIRECT_STOP... be aware
339//	fDesktop->LockClipping();
340
341//	fEngine.Lock();
342
343	switch(info->buffer_state & B_DIRECT_MODE_MASK) {
344		case B_DIRECT_START:
345		case B_DIRECT_MODIFY:
346			fBuffer.SetTo(info);
347			fDesktop->SetOffset(info->window_bounds.left, info->window_bounds.top);
348			test2((uint8*)info->bits, info->bytes_per_row);
349			break;
350		case B_DIRECT_STOP:
351			fBuffer.SetTo(NULL);
352			break;
353	}
354
355//	fDesktop->SetMasterClipping(&fBuffer.WindowClipping());
356
357//	fEngine.Unlock();
358
359//	fDesktop->UnlockClipping();
360}
361
362// AddWindow
363void
364Window::AddWindow(BRect frame, const char* name)
365{
366	WindowLayer* window = new WindowLayer(frame, name,
367										  fDesktop->GetDrawingEngine(),
368										  fDesktop);
369
370	// add a coupld children
371	frame.OffsetTo(B_ORIGIN);
372	frame.InsetBy(5.0, 5.0);
373	if (frame.IsValid()) {
374		ViewLayer* layer1 = new ViewLayer(frame, "View 1",
375										  B_FOLLOW_ALL,
376										  B_FULL_UPDATE_ON_RESIZE,
377										  (rgb_color){ 180, 180, 180, 255 });
378
379		frame.OffsetTo(B_ORIGIN);
380		frame.InsetBy(15.0, 15.0);
381		if (frame.IsValid()) {
382
383			BRect f = frame;
384			f.bottom = f.top + f.Height() / 3 - 3;
385			f.right = f.left + f.Width() / 3 - 3;
386
387			// top row of views
388			ViewLayer* layer;
389			layer = new ViewLayer(f, "View", B_FOLLOW_LEFT | B_FOLLOW_TOP,
390								  B_FULL_UPDATE_ON_RESIZE, (rgb_color){ 120, 120, 120, 255 });
391			layer1->AddChild(layer);
392
393			f.OffsetBy(f.Width() + 6, 0);
394
395			layer = new ViewLayer(f, "View", B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
396								  B_FULL_UPDATE_ON_RESIZE, (rgb_color){ 120, 120, 120, 255 });
397			layer1->AddChild(layer);
398
399			f.OffsetBy(f.Width() + 6, 0);
400
401			layer = new ViewLayer(f, "View", B_FOLLOW_RIGHT | B_FOLLOW_TOP,
402								  B_FULL_UPDATE_ON_RESIZE, (rgb_color){ 120, 120, 120, 255 });
403			layer1->AddChild(layer);
404
405			// middle row of views
406			f = frame;
407			f.bottom = f.top + f.Height() / 3 - 3;
408			f.right = f.left + f.Width() / 3 - 3;
409			f.OffsetBy(0, f.Height() + 6);
410
411			layer = new ViewLayer(f, "View", B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM,
412								  B_FULL_UPDATE_ON_RESIZE, (rgb_color){ 120, 120, 120, 255 });
413			layer1->AddChild(layer);
414
415			f.OffsetBy(f.Width() + 6, 0);
416
417			layer = new ViewLayer(f, "View", B_FOLLOW_ALL,
418								  B_FULL_UPDATE_ON_RESIZE, (rgb_color){ 120, 120, 120, 255 });
419			layer1->AddChild(layer);
420
421			f.OffsetBy(f.Width() + 6, 0);
422
423			layer = new ViewLayer(f, "View", B_FOLLOW_RIGHT | B_FOLLOW_TOP_BOTTOM,
424								  B_FULL_UPDATE_ON_RESIZE, (rgb_color){ 120, 120, 120, 255 });
425			layer1->AddChild(layer);
426
427			// bottom row of views
428			f = frame;
429			f.bottom = f.top + f.Height() / 3 - 3;
430			f.right = f.left + f.Width() / 3 - 3;
431			f.OffsetBy(0, 2 * f.Height() + 12);
432
433			layer = new ViewLayer(f, "View", B_FOLLOW_LEFT | B_FOLLOW_BOTTOM,
434								  B_FULL_UPDATE_ON_RESIZE, (rgb_color){ 120, 120, 120, 255 });
435			layer1->AddChild(layer);
436
437			f.OffsetBy(f.Width() + 6, 0);
438
439//			layer = new ViewLayer(f, "View", B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM,
440			layer = new ViewLayer(f, "View", B_FOLLOW_LEFT | B_FOLLOW_BOTTOM,
441								  B_FULL_UPDATE_ON_RESIZE, (rgb_color){ 120, 120, 120, 255 });
442			layer1->AddChild(layer);
443
444			f.OffsetBy(f.Width() + 6, 0);
445
446//			layer = new ViewLayer(f, "View", B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM,
447			layer = new ViewLayer(f, "View", B_FOLLOW_LEFT | B_FOLLOW_BOTTOM,
448								  B_FULL_UPDATE_ON_RESIZE, (rgb_color){ 120, 120, 120, 255 });
449			layer1->AddChild(layer);
450		}
451
452		window->AddChild(layer1);
453	}
454
455	window->Run();
456
457	BMessage message(MSG_ADD_WINDOW);
458	message.AddPointer("window", (void*)window);
459	fDesktop->PostMessage(&message);
460}
461
462// Test
463void
464Window::Test()
465{
466	BRect frame(20, 20, 330, 230);
467//	AddWindow(frame, "Window 1");
468//	AddWindow(frame, "Window 2");
469	for (int32 i = 0; i < 20; i++) {
470		BString name("Window ");
471		frame.OffsetBy(20, 15);
472		name << i + 1;
473		AddWindow(frame, name.String());
474	}
475
476/*	frame.Set(10, 80, 320, 290);
477	for (int32 i = 20; i < 40; i++) {
478		BString name("Window ");
479		frame.OffsetBy(20, 15);
480		name << i + 1;
481		AddWindow(frame, name.String());
482	}
483
484	frame.Set(20, 140, 330, 230);
485	for (int32 i = 40; i < 60; i++) {
486		BString name("Window ");
487		frame.OffsetBy(20, 15);
488		name << i + 1;
489		AddWindow(frame, name.String());
490	}
491
492	frame.Set(20, 200, 330, 230);
493	for (int32 i = 60; i < 80; i++) {
494		BString name("Window ");
495		frame.OffsetBy(20, 15);
496		name << i + 1;
497		AddWindow(frame, name.String());
498	}
499
500	frame.Set(20, 260, 330, 230);
501// 99 windows are ok, the 100th looper does not run anymore,
502// I guess I'm hitting a BeOS limit (max loopers per app?)
503	for (int32 i = 80; i < 99; i++) {
504		BString name("Window ");
505		frame.OffsetBy(20, 15);
506		name << i + 1;
507		AddWindow(frame, name.String());
508	}*/
509}
510
511// main
512int
513main(int argc, const char* argv[])
514{
515	srand((long int)system_time());
516
517	App app;
518	app.Run();
519	return 0;
520}
521