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
17 class App : public BApplication {
18 public:
19 App();
20
21 virtual void ReadyToRun();
22 };
23
24 class 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
App()46 App::App()
47 : BApplication("application/x-vnd.stippi.ClippingTest")
48 {
49 srand(real_time_clock_usecs());
50 }
51
52 // ReadyToRun
53 void
ReadyToRun()54 App::ReadyToRun()
55 {
56 Window* win = new Window("clipping");
57 win->Show();
58
59 // win->Test();
60 }
61
62 // constructor
Window(const char * title)63 Window::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
~Window()81 Window::~Window()
82 {
83 fInterface.Shutdown();
84 fDesktop->Lock();
85 fDesktop->Quit();
86 }
87
88 // QuitRequested
89 bool
QuitRequested()90 Window::QuitRequested()
91 {
92 /* if (!fQuit) {
93 fDesktop->PostMessage(MSG_QUIT);
94 fQuit = true;
95 return false;
96 }*/
97 be_app->PostMessage(B_QUIT_REQUESTED);
98 return true;
99 }
100
101 // #pragma mark -
102
103 void
fill_line_8(uint8 * buffer,int32 pixels,uint8 r,uint8 g,uint8 b)104 fill_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
114 void
fill_line_32(uint8 * buffer,int32 pixels,uint8 r,uint8 g,uint8 b)115 fill_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
125 void
fill_line_64(uint8 * buffer,int32 pixels,uint8 r,uint8 g,uint8 b)126 fill_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
139 void
test1(uint8 * buffer,uint32 bpr)140 test1(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
180 void
blend_line_8(uint8 * buffer,int32 pixels,uint8 r,uint8 g,uint8 b,uint8 a)181 blend_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
192 union pixel {
193 uint32 data32;
194 uint8 data8[4];
195 };
196
197 void
blend_line_32(uint8 * buffer,int32 pixels,uint8 r,uint8 g,uint8 b,uint8 a)198 blend_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
223 union pixel2 {
224 uint64 data64;
225 uint8 data8[8];
226 };
227
228 // gfxcpy32
229 // * numBytes is expected to be a multiple of 4
230 inline
231 void
gfxcpy32(uint8 * dst,uint8 * src,int32 numBytes)232 gfxcpy32(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
260 void
blend_line_64(uint8 * buffer,int32 pixels,uint8 r,uint8 g,uint8 b,uint8 a)261 blend_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 }
293 void
test2(uint8 * buffer,uint32 bpr)294 test2(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
334 void
DirectConnected(direct_buffer_info * info)335 Window::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
363 void
AddWindow(BRect frame,const char * name)364 Window::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
463 void
Test()464 Window::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
512 int
main(int argc,const char * argv[])513 main(int argc, const char* argv[])
514 {
515 srand((long int)system_time());
516
517 App app;
518 app.Run();
519 return 0;
520 }
521