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