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