1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "FrameBuffer.hpp" 16 17 #include "Timer.hpp" 18 #include "CPUID.hpp" 19 #include "Renderer/Surface.hpp" 20 #include "Reactor/Reactor.hpp" 21 #include "Common/Debug.hpp" 22 23 #include <stdio.h> 24 #include <string.h> 25 #include <time.h> 26 27 #ifdef __ANDROID__ 28 #include <cutils/properties.h> 29 #endif 30 31 #define ASYNCHRONOUS_BLIT 0 // FIXME: Currently leads to rare race conditions 32 33 namespace sw 34 { 35 extern bool forceWindowed; 36 37 void *FrameBuffer::cursor; 38 int FrameBuffer::cursorWidth = 0; 39 int FrameBuffer::cursorHeight = 0; 40 int FrameBuffer::cursorHotspotX; 41 int FrameBuffer::cursorHotspotY; 42 int FrameBuffer::cursorPositionX; 43 int FrameBuffer::cursorPositionY; 44 int FrameBuffer::cursorX; 45 int FrameBuffer::cursorY; 46 bool FrameBuffer::topLeftOrigin = false; 47 FrameBuffer(int width,int height,bool fullscreen,bool topLeftOrigin)48 FrameBuffer::FrameBuffer(int width, int height, bool fullscreen, bool topLeftOrigin) 49 { 50 this->topLeftOrigin = topLeftOrigin; 51 52 locked = nullptr; 53 54 this->width = width; 55 this->height = height; 56 destFormat = FORMAT_X8R8G8B8; 57 sourceFormat = FORMAT_X8R8G8B8; 58 stride = 0; 59 60 if(forceWindowed) 61 { 62 fullscreen = false; 63 } 64 65 windowed = !fullscreen; 66 67 blitFunction = nullptr; 68 blitRoutine = nullptr; 69 70 blitState.width = 0; 71 blitState.height = 0; 72 blitState.destFormat = FORMAT_X8R8G8B8; 73 blitState.sourceFormat = FORMAT_X8R8G8B8; 74 blitState.cursorWidth = 0; 75 blitState.cursorHeight = 0; 76 77 if(ASYNCHRONOUS_BLIT) 78 { 79 terminate = false; 80 FrameBuffer *parameters = this; 81 blitThread = new Thread(threadFunction, ¶meters); 82 } 83 } 84 ~FrameBuffer()85 FrameBuffer::~FrameBuffer() 86 { 87 if(ASYNCHRONOUS_BLIT) 88 { 89 terminate = true; 90 blitEvent.signal(); 91 blitThread->join(); 92 delete blitThread; 93 } 94 95 delete blitRoutine; 96 } 97 getWidth() const98 int FrameBuffer::getWidth() const 99 { 100 return width; 101 } 102 getHeight() const103 int FrameBuffer::getHeight() const 104 { 105 return height; 106 } 107 getStride() const108 int FrameBuffer::getStride() const 109 { 110 return stride; 111 } 112 setCursorImage(sw::Surface * cursorImage)113 void FrameBuffer::setCursorImage(sw::Surface *cursorImage) 114 { 115 if(cursorImage) 116 { 117 cursor = cursorImage->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC); 118 cursorImage->unlockExternal(); 119 120 cursorWidth = cursorImage->getWidth(); 121 cursorHeight = cursorImage->getHeight(); 122 } 123 else 124 { 125 cursorWidth = 0; 126 cursorHeight = 0; 127 } 128 } 129 setCursorOrigin(int x0,int y0)130 void FrameBuffer::setCursorOrigin(int x0, int y0) 131 { 132 cursorHotspotX = x0; 133 cursorHotspotY = y0; 134 } 135 setCursorPosition(int x,int y)136 void FrameBuffer::setCursorPosition(int x, int y) 137 { 138 cursorPositionX = x; 139 cursorPositionY = y; 140 } 141 copy(void * source,Format format,size_t stride)142 void FrameBuffer::copy(void *source, Format format, size_t stride) 143 { 144 if(!source) 145 { 146 return; 147 } 148 149 if(!lock()) 150 { 151 return; 152 } 153 154 sourceFormat = format; 155 156 if(topLeftOrigin) 157 { 158 target = source; 159 } 160 else 161 { 162 target = (byte*)source + (height - 1) * stride; 163 } 164 165 cursorX = cursorPositionX - cursorHotspotX; 166 cursorY = cursorPositionY - cursorHotspotY; 167 168 if(ASYNCHRONOUS_BLIT) 169 { 170 blitEvent.signal(); 171 syncEvent.wait(); 172 } 173 else 174 { 175 copyLocked(); 176 } 177 178 unlock(); 179 180 profiler.nextFrame(); // Assumes every copy() is a full frame 181 } 182 copyLocked()183 void FrameBuffer::copyLocked() 184 { 185 BlitState update = {}; 186 update.width = width; 187 update.height = height; 188 update.destFormat = destFormat; 189 update.sourceFormat = sourceFormat; 190 update.stride = stride; 191 update.cursorWidth = cursorWidth; 192 update.cursorHeight = cursorHeight; 193 194 if(memcmp(&blitState, &update, sizeof(BlitState)) != 0) 195 { 196 blitState = update; 197 delete blitRoutine; 198 199 blitRoutine = copyRoutine(blitState); 200 blitFunction = (void(*)(void*, void*))blitRoutine->getEntry(); 201 } 202 203 blitFunction(locked, target); 204 } 205 copyRoutine(const BlitState & state)206 Routine *FrameBuffer::copyRoutine(const BlitState &state) 207 { 208 const int width = state.width; 209 const int height = state.height; 210 const int width2 = (state.width + 1) & ~1; 211 const int dBytes = Surface::bytes(state.destFormat); 212 const int dStride = state.stride; 213 const int sBytes = Surface::bytes(state.sourceFormat); 214 const int sStride = topLeftOrigin ? (sBytes * width2) : -(sBytes * width2); 215 216 Function<Void(Pointer<Byte>, Pointer<Byte>)> function; 217 { 218 Pointer<Byte> dst(function.Arg<0>()); 219 Pointer<Byte> src(function.Arg<1>()); 220 221 For(Int y = 0, y < height, y++) 222 { 223 Pointer<Byte> d = dst + y * dStride; 224 Pointer<Byte> s = src + y * sStride; 225 226 Int x0 = 0; 227 228 switch(state.destFormat) 229 { 230 case FORMAT_X8R8G8B8: 231 case FORMAT_A8R8G8B8: 232 { 233 Int x = x0; 234 235 switch(state.sourceFormat) 236 { 237 case FORMAT_X8R8G8B8: 238 case FORMAT_A8R8G8B8: 239 For(, x < width - 3, x += 4) 240 { 241 *Pointer<Int4>(d, 1) = *Pointer<Int4>(s, sStride % 16 ? 1 : 16); 242 243 s += 4 * sBytes; 244 d += 4 * dBytes; 245 } 246 break; 247 case FORMAT_X8B8G8R8: 248 case FORMAT_A8B8G8R8: 249 For(, x < width - 3, x += 4) 250 { 251 Int4 bgra = *Pointer<Int4>(s, sStride % 16 ? 1 : 16); 252 253 *Pointer<Int4>(d, 1) = ((bgra & Int4(0x00FF0000)) >> 16) | 254 ((bgra & Int4(0x000000FF)) << 16) | 255 (bgra & Int4(0xFF00FF00)); 256 257 s += 4 * sBytes; 258 d += 4 * dBytes; 259 } 260 break; 261 case FORMAT_A16B16G16R16: 262 For(, x < width - 1, x += 2) 263 { 264 UShort4 c0 = As<UShort4>(Swizzle(*Pointer<Short4>(s + 0), 0xC6)) >> 8; 265 UShort4 c1 = As<UShort4>(Swizzle(*Pointer<Short4>(s + 8), 0xC6)) >> 8; 266 267 *Pointer<Int2>(d) = As<Int2>(Pack(c0, c1)); 268 269 s += 2 * sBytes; 270 d += 2 * dBytes; 271 } 272 break; 273 case FORMAT_R5G6B5: 274 For(, x < width, x++) 275 { 276 Int rgb = Int(*Pointer<Short>(s)); 277 278 *Pointer<Int>(d) = 0xFF000000 | 279 ((rgb & 0xF800) << 8) | ((rgb & 0xE01F) << 3) | 280 ((rgb & 0x07E0) << 5) | ((rgb & 0x0600) >> 1) | 281 ((rgb & 0x001C) >> 2); 282 283 s += sBytes; 284 d += dBytes; 285 } 286 break; 287 default: 288 ASSERT(false); 289 break; 290 } 291 292 For(, x < width, x++) 293 { 294 switch(state.sourceFormat) 295 { 296 case FORMAT_X8R8G8B8: 297 case FORMAT_A8R8G8B8: 298 *Pointer<Int>(d) = *Pointer<Int>(s); 299 break; 300 case FORMAT_X8B8G8R8: 301 case FORMAT_A8B8G8R8: 302 { 303 Int rgba = *Pointer<Int>(s); 304 305 *Pointer<Int>(d) = ((rgba & Int(0x00FF0000)) >> 16) | 306 ((rgba & Int(0x000000FF)) << 16) | 307 (rgba & Int(0xFF00FF00)); 308 } 309 break; 310 case FORMAT_A16B16G16R16: 311 { 312 UShort4 c = As<UShort4>(Swizzle(*Pointer<Short4>(s), 0xC6)) >> 8; 313 314 *Pointer<Int>(d) = Int(As<Int2>(Pack(c, c))); 315 } 316 break; 317 case FORMAT_R5G6B5: 318 { 319 Int rgb = Int(*Pointer<Short>(s)); 320 321 *Pointer<Int>(d) = 0xFF000000 | 322 ((rgb & 0xF800) << 8) | ((rgb & 0xE01F) << 3) | 323 ((rgb & 0x07E0) << 5) | ((rgb & 0x0600) >> 1) | 324 ((rgb & 0x001C) >> 2); 325 } 326 break; 327 default: 328 ASSERT(false); 329 break; 330 } 331 332 s += sBytes; 333 d += dBytes; 334 } 335 } 336 break; 337 case FORMAT_X8B8G8R8: 338 case FORMAT_A8B8G8R8: 339 case FORMAT_SRGB8_X8: 340 case FORMAT_SRGB8_A8: 341 { 342 Int x = x0; 343 344 switch(state.sourceFormat) 345 { 346 case FORMAT_X8B8G8R8: 347 case FORMAT_A8B8G8R8: 348 For(, x < width - 3, x += 4) 349 { 350 *Pointer<Int4>(d, 1) = *Pointer<Int4>(s, sStride % 16 ? 1 : 16); 351 352 s += 4 * sBytes; 353 d += 4 * dBytes; 354 } 355 break; 356 case FORMAT_X8R8G8B8: 357 case FORMAT_A8R8G8B8: 358 For(, x < width - 3, x += 4) 359 { 360 Int4 bgra = *Pointer<Int4>(s, sStride % 16 ? 1 : 16); 361 362 *Pointer<Int4>(d, 1) = ((bgra & Int4(0x00FF0000)) >> 16) | 363 ((bgra & Int4(0x000000FF)) << 16) | 364 (bgra & Int4(0xFF00FF00)); 365 366 s += 4 * sBytes; 367 d += 4 * dBytes; 368 } 369 break; 370 case FORMAT_A16B16G16R16: 371 For(, x < width - 1, x += 2) 372 { 373 UShort4 c0 = *Pointer<UShort4>(s + 0) >> 8; 374 UShort4 c1 = *Pointer<UShort4>(s + 8) >> 8; 375 376 *Pointer<Int2>(d) = As<Int2>(Pack(c0, c1)); 377 378 s += 2 * sBytes; 379 d += 2 * dBytes; 380 } 381 break; 382 case FORMAT_R5G6B5: 383 For(, x < width, x++) 384 { 385 Int rgb = Int(*Pointer<Short>(s)); 386 387 *Pointer<Int>(d) = 0xFF000000 | 388 ((rgb & 0x001F) << 19) | ((rgb & 0x001C) << 14) | 389 ((rgb & 0x07E0) << 5) | ((rgb & 0x0600) >> 1) | 390 ((rgb & 0xF800) >> 8) | ((rgb & 0xE000) >> 13); 391 392 s += sBytes; 393 d += dBytes; 394 } 395 break; 396 default: 397 ASSERT(false); 398 break; 399 } 400 401 For(, x < width, x++) 402 { 403 switch(state.sourceFormat) 404 { 405 case FORMAT_X8B8G8R8: 406 case FORMAT_A8B8G8R8: 407 *Pointer<Int>(d) = *Pointer<Int>(s); 408 break; 409 case FORMAT_X8R8G8B8: 410 case FORMAT_A8R8G8B8: 411 { 412 Int bgra = *Pointer<Int>(s); 413 *Pointer<Int>(d) = ((bgra & Int(0x00FF0000)) >> 16) | 414 ((bgra & Int(0x000000FF)) << 16) | 415 (bgra & Int(0xFF00FF00)); 416 } 417 break; 418 case FORMAT_A16B16G16R16: 419 { 420 UShort4 c = *Pointer<UShort4>(s) >> 8; 421 422 *Pointer<Int>(d) = Int(As<Int2>(Pack(c, c))); 423 } 424 break; 425 case FORMAT_R5G6B5: 426 { 427 Int rgb = Int(*Pointer<Short>(s)); 428 429 *Pointer<Int>(d) = 0xFF000000 | 430 ((rgb & 0x001F) << 19) | ((rgb & 0x001C) << 14) | 431 ((rgb & 0x07E0) << 5) | ((rgb & 0x0600) >> 1) | 432 ((rgb & 0xF800) >> 8) | ((rgb & 0xE000) >> 13); 433 } 434 break; 435 default: 436 ASSERT(false); 437 break; 438 } 439 440 s += sBytes; 441 d += dBytes; 442 } 443 } 444 break; 445 case FORMAT_R8G8B8: 446 { 447 For(Int x = x0, x < width, x++) 448 { 449 switch(state.sourceFormat) 450 { 451 case FORMAT_X8R8G8B8: 452 case FORMAT_A8R8G8B8: 453 *Pointer<Byte>(d + 0) = *Pointer<Byte>(s + 0); 454 *Pointer<Byte>(d + 1) = *Pointer<Byte>(s + 1); 455 *Pointer<Byte>(d + 2) = *Pointer<Byte>(s + 2); 456 break; 457 case FORMAT_X8B8G8R8: 458 case FORMAT_A8B8G8R8: 459 *Pointer<Byte>(d + 0) = *Pointer<Byte>(s + 2); 460 *Pointer<Byte>(d + 1) = *Pointer<Byte>(s + 1); 461 *Pointer<Byte>(d + 2) = *Pointer<Byte>(s + 0); 462 break; 463 case FORMAT_A16B16G16R16: 464 *Pointer<Byte>(d + 0) = *Pointer<Byte>(s + 5); 465 *Pointer<Byte>(d + 1) = *Pointer<Byte>(s + 3); 466 *Pointer<Byte>(d + 2) = *Pointer<Byte>(s + 1); 467 break; 468 case FORMAT_R5G6B5: 469 { 470 Int rgb = Int(*Pointer<Short>(s)); 471 472 *Pointer<Byte>(d + 0) = Byte(((rgb & 0x001F) << 3) | ((rgb & 0x001C) >> 2)); 473 *Pointer<Byte>(d + 1) = Byte(((rgb & 0x07E0) << 5) | ((rgb & 0x0600) >> 1)); 474 *Pointer<Byte>(d + 2) = Byte(((rgb & 0xF800) << 8) | ((rgb & 0xE000) << 3)); 475 } 476 break; 477 default: 478 ASSERT(false); 479 break; 480 } 481 482 s += sBytes; 483 d += dBytes; 484 } 485 } 486 break; 487 case FORMAT_R5G6B5: 488 { 489 For(Int x = x0, x < width, x++) 490 { 491 switch(state.sourceFormat) 492 { 493 case FORMAT_X8R8G8B8: 494 case FORMAT_A8R8G8B8: 495 { 496 Int c = *Pointer<Int>(s); 497 498 *Pointer<Short>(d) = Short((c & 0x00F80000) >> 8 | 499 (c & 0x0000FC00) >> 5 | 500 (c & 0x000000F8) >> 3); 501 } 502 break; 503 case FORMAT_X8B8G8R8: 504 case FORMAT_A8B8G8R8: 505 { 506 Int c = *Pointer<Int>(s); 507 508 *Pointer<Short>(d) = Short((c & 0x00F80000) >> 19 | 509 (c & 0x0000FC00) >> 5 | 510 (c & 0x000000F8) << 8); 511 } 512 break; 513 case FORMAT_A16B16G16R16: 514 { 515 UShort4 cc = *Pointer<UShort4>(s) >> 8; 516 Int c = Int(As<Int2>(Pack(cc, cc))); 517 518 *Pointer<Short>(d) = Short((c & 0x00F80000) >> 19 | 519 (c & 0x0000FC00) >> 5 | 520 (c & 0x000000F8) << 8); 521 } 522 break; 523 case FORMAT_R5G6B5: 524 *Pointer<Short>(d) = *Pointer<Short>(s); 525 break; 526 default: 527 ASSERT(false); 528 break; 529 } 530 531 s += sBytes; 532 d += dBytes; 533 } 534 } 535 break; 536 default: 537 ASSERT(false); 538 break; 539 } 540 } 541 542 Int x0 = *Pointer<Int>(&cursorX); 543 Int y0 = *Pointer<Int>(&cursorY); 544 545 For(Int y1 = 0, y1 < cursorHeight, y1++) 546 { 547 Int y = y0 + y1; 548 549 If(y >= 0 && y < height) 550 { 551 Pointer<Byte> d = dst + y * dStride + x0 * dBytes; 552 Pointer<Byte> s = src + y * sStride + x0 * sBytes; 553 Pointer<Byte> c = *Pointer<Pointer<Byte> >(&cursor) + y1 * cursorWidth * 4; 554 555 For(Int x1 = 0, x1 < cursorWidth, x1++) 556 { 557 Int x = x0 + x1; 558 559 If(x >= 0 && x < width) 560 { 561 blend(state, d, s, c); 562 } 563 564 c += 4; 565 s += sBytes; 566 d += dBytes; 567 } 568 } 569 } 570 } 571 572 return function(L"FrameBuffer"); 573 } 574 blend(const BlitState & state,const Pointer<Byte> & d,const Pointer<Byte> & s,const Pointer<Byte> & c)575 void FrameBuffer::blend(const BlitState &state, const Pointer<Byte> &d, const Pointer<Byte> &s, const Pointer<Byte> &c) 576 { 577 Short4 c1; 578 Short4 c2; 579 580 c1 = UnpackLow(As<Byte8>(c1), *Pointer<Byte8>(c)); 581 582 switch(state.sourceFormat) 583 { 584 case FORMAT_X8R8G8B8: 585 case FORMAT_A8R8G8B8: 586 c2 = UnpackLow(As<Byte8>(c2), *Pointer<Byte8>(s)); 587 break; 588 case FORMAT_X8B8G8R8: 589 case FORMAT_A8B8G8R8: 590 c2 = Swizzle(UnpackLow(As<Byte8>(c2), *Pointer<Byte8>(s)), 0xC6); 591 break; 592 case FORMAT_A16B16G16R16: 593 c2 = Swizzle(*Pointer<Short4>(s), 0xC6); 594 break; 595 case FORMAT_R5G6B5: 596 { 597 Int rgb(*Pointer<Short>(s)); 598 rgb = 0xFF000000 | 599 ((rgb & 0xF800) << 8) | ((rgb & 0xE01F) << 3) | 600 ((rgb & 0x07E0) << 5) | ((rgb & 0x0600) >> 1) | 601 ((rgb & 0x001C) >> 2); 602 c2 = Unpack(As<Byte4>(rgb)); 603 } 604 break; 605 default: 606 ASSERT(false); 607 break; 608 } 609 610 c1 = As<Short4>(As<UShort4>(c1) >> 9); 611 c2 = As<Short4>(As<UShort4>(c2) >> 9); 612 613 Short4 alpha = Swizzle(c1, 0xFF) & Short4(0xFFFFu, 0xFFFFu, 0xFFFFu, 0x0000); 614 615 c1 = (c1 - c2) * alpha; 616 c1 = c1 >> 7; 617 c1 = c1 + c2; 618 c1 = c1 + c1; 619 620 switch(state.destFormat) 621 { 622 case FORMAT_X8R8G8B8: 623 case FORMAT_A8R8G8B8: 624 *Pointer<UInt>(d) = UInt(As<Long>(Pack(As<UShort4>(c1), As<UShort4>(c1)))); 625 break; 626 case FORMAT_X8B8G8R8: 627 case FORMAT_A8B8G8R8: 628 case FORMAT_SRGB8_X8: 629 case FORMAT_SRGB8_A8: 630 { 631 c1 = Swizzle(c1, 0xC6); 632 633 *Pointer<UInt>(d) = UInt(As<Long>(Pack(As<UShort4>(c1), As<UShort4>(c1)))); 634 } 635 break; 636 case FORMAT_R8G8B8: 637 { 638 Int c = Int(As<Int2>(Pack(As<UShort4>(c1), As<UShort4>(c1)))); 639 640 *Pointer<Byte>(d + 0) = Byte(c >> 0); 641 *Pointer<Byte>(d + 1) = Byte(c >> 8); 642 *Pointer<Byte>(d + 2) = Byte(c >> 16); 643 } 644 break; 645 case FORMAT_R5G6B5: 646 { 647 Int c = Int(As<Int2>(Pack(As<UShort4>(c1), As<UShort4>(c1)))); 648 649 *Pointer<Short>(d) = Short((c & 0x00F80000) >> 8 | 650 (c & 0x0000FC00) >> 5 | 651 (c & 0x000000F8) >> 3); 652 } 653 break; 654 default: 655 ASSERT(false); 656 break; 657 } 658 } 659 threadFunction(void * parameters)660 void FrameBuffer::threadFunction(void *parameters) 661 { 662 FrameBuffer *frameBuffer = *static_cast<FrameBuffer**>(parameters); 663 664 while(!frameBuffer->terminate) 665 { 666 frameBuffer->blitEvent.wait(); 667 668 if(!frameBuffer->terminate) 669 { 670 frameBuffer->copyLocked(); 671 672 frameBuffer->syncEvent.signal(); 673 } 674 } 675 } 676 } 677