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