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 46 App::App() 47 : BApplication("application/x-vnd.stippi.ClippingTest") 48 { 49 srand(real_time_clock_usecs()); 50 } 51 52 // ReadyToRun 53 void 54 App::ReadyToRun() 55 { 56 Window* win = new Window("clipping"); 57 win->Show(); 58 59 // win->Test(); 60 } 61 62 // constructor 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 81 Window::~Window() 82 { 83 fInterface.Shutdown(); 84 fDesktop->Lock(); 85 fDesktop->Quit(); 86 } 87 88 // QuitRequested 89 bool 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 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 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 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 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 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 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 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 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 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 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 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 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 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