Home | History | Annotate | Download | only in WSI
      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 "Device/Surface.hpp"
     18 #include "Reactor/Reactor.hpp"
     19 #include "System/Timer.hpp"
     20 #include "System/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 = VK_FORMAT_B8G8R8A8_UNORM;
     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, &parameters);
     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 VK_FORMAT_B8G8R8A8_UNORM:
    191 					{
    192 						Int x = x0;
    193 
    194 						switch(state.sourceFormat)
    195 						{
    196 						case VK_FORMAT_B8G8R8A8_UNORM:
    197 							For(, x < width - 3, x += 4)
    198 							{
    199 								*Pointer<Int4>(d, 1) = *Pointer<Int4>(s, sStride % 16 ? 1 : 16);
    200 
    201 								s += 4 * sBytes;
    202 								d += 4 * dBytes;
    203 							}
    204 							break;
    205 						case VK_FORMAT_R8G8B8A8_UNORM:
    206 							For(, x < width - 3, x += 4)
    207 							{
    208 								Int4 bgra = *Pointer<Int4>(s, sStride % 16 ? 1 : 16);
    209 
    210 								*Pointer<Int4>(d, 1) = ((bgra & Int4(0x00FF0000)) >> 16) |
    211 								                       ((bgra & Int4(0x000000FF)) << 16) |
    212 								                       (bgra & Int4(0xFF00FF00));
    213 
    214 								s += 4 * sBytes;
    215 								d += 4 * dBytes;
    216 							}
    217 							break;
    218 						case VK_FORMAT_R16G16B16A16_UNORM:
    219 							For(, x < width - 1, x += 2)
    220 							{
    221 								Short4 c0 = As<UShort4>(Swizzle(*Pointer<Short4>(s + 0), 0xC6)) >> 8;
    222 								Short4 c1 = As<UShort4>(Swizzle(*Pointer<Short4>(s + 8), 0xC6)) >> 8;
    223 
    224 								*Pointer<Int2>(d) = As<Int2>(PackUnsigned(c0, c1));
    225 
    226 								s += 2 * sBytes;
    227 								d += 2 * dBytes;
    228 							}
    229 							break;
    230 						case VK_FORMAT_R5G6B5_UNORM_PACK16:
    231 							For(, x < width - 3, x += 4)
    232 							{
    233 								Int4 rgb = Int4(*Pointer<Short4>(s));
    234 
    235 								*Pointer<Int4>(d) = (((rgb & Int4(0xF800)) << 8) | ((rgb & Int4(0xE01F)) << 3)) |
    236 								                    (((rgb & Int4(0x07E0)) << 5) | ((rgb & Int4(0x0600)) >> 1)) |
    237 								                    (((rgb & Int4(0x001C)) >> 2) | Int4(0xFF000000));
    238 
    239 								s += 4 * sBytes;
    240 								d += 4 * dBytes;
    241 							}
    242 							break;
    243 						default:
    244 							ASSERT(false);
    245 							break;
    246 						}
    247 
    248 						For(, x < width, x++)
    249 						{
    250 							switch(state.sourceFormat)
    251 							{
    252 							case VK_FORMAT_B8G8R8A8_UNORM:
    253 								*Pointer<Int>(d) = *Pointer<Int>(s);
    254 								break;
    255 							case VK_FORMAT_R8G8B8A8_UNORM:
    256 								{
    257 									Int rgba = *Pointer<Int>(s);
    258 
    259 									*Pointer<Int>(d) = ((rgba & Int(0x00FF0000)) >> 16) |
    260 									                   ((rgba & Int(0x000000FF)) << 16) |
    261 									                   (rgba & Int(0xFF00FF00));
    262 								}
    263 								break;
    264 							case VK_FORMAT_R16G16B16A16_UNORM:
    265 								{
    266 									Short4 c = As<UShort4>(Swizzle(*Pointer<Short4>(s), 0xC6)) >> 8;
    267 
    268 									*Pointer<Int>(d) = Int(As<Int2>(PackUnsigned(c, c)));
    269 								}
    270 								break;
    271 							case VK_FORMAT_R5G6B5_UNORM_PACK16:
    272 								{
    273 									Int rgb = Int(*Pointer<Short>(s));
    274 
    275 									*Pointer<Int>(d) = 0xFF000000 |
    276 									                   ((rgb & 0xF800) << 8) | ((rgb & 0xE01F) << 3) |
    277 								                       ((rgb & 0x07E0) << 5) | ((rgb & 0x0600) >> 1) |
    278 								                       ((rgb & 0x001C) >> 2);
    279 								}
    280 								break;
    281 							default:
    282 								ASSERT(false);
    283 								break;
    284 							}
    285 
    286 							s += sBytes;
    287 							d += dBytes;
    288 						}
    289 					}
    290 					break;
    291 				case VK_FORMAT_R8G8B8A8_UNORM:
    292 				case VK_FORMAT_R8G8B8A8_SRGB:
    293 					{
    294 						Int x = x0;
    295 
    296 						switch(state.sourceFormat)
    297 						{
    298 						case VK_FORMAT_R8G8B8A8_UNORM:
    299 							For(, x < width - 3, x += 4)
    300 							{
    301 								*Pointer<Int4>(d, 1) = *Pointer<Int4>(s, sStride % 16 ? 1 : 16);
    302 
    303 								s += 4 * sBytes;
    304 								d += 4 * dBytes;
    305 							}
    306 							break;
    307 						case VK_FORMAT_B8G8R8A8_UNORM:
    308 							For(, x < width - 3, x += 4)
    309 							{
    310 								Int4 bgra = *Pointer<Int4>(s, sStride % 16 ? 1 : 16);
    311 
    312 								*Pointer<Int4>(d, 1) = ((bgra & Int4(0x00FF0000)) >> 16) |
    313 								                       ((bgra & Int4(0x000000FF)) << 16) |
    314 								                       (bgra & Int4(0xFF00FF00));
    315 
    316 								s += 4 * sBytes;
    317 								d += 4 * dBytes;
    318 							}
    319 							break;
    320 						case VK_FORMAT_R16G16B16A16_UNORM:
    321 							For(, x < width - 1, x += 2)
    322 							{
    323 								Short4 c0 = *Pointer<UShort4>(s + 0) >> 8;
    324 								Short4 c1 = *Pointer<UShort4>(s + 8) >> 8;
    325 
    326 								*Pointer<Int2>(d) = As<Int2>(PackUnsigned(c0, c1));
    327 
    328 								s += 2 * sBytes;
    329 								d += 2 * dBytes;
    330 							}
    331 							break;
    332 						case VK_FORMAT_R5G6B5_UNORM_PACK16:
    333 							For(, x < width - 3, x += 4)
    334 							{
    335 								Int4 rgb = Int4(*Pointer<Short4>(s));
    336 
    337 								*Pointer<Int4>(d) = Int4(0xFF000000) |
    338                                                     (((rgb & Int4(0x001F)) << 19) | ((rgb & Int4(0x001C)) << 14)) |
    339 								                    (((rgb & Int4(0x07E0)) << 5) | ((rgb & Int4(0x0600)) >> 1)) |
    340 								                    (((rgb & Int4(0xF800)) >> 8) | ((rgb & Int4(0xE000)) >> 13));
    341 
    342 								s += 4 * sBytes;
    343 								d += 4 * dBytes;
    344 							}
    345 							break;
    346 						default:
    347 							ASSERT(false);
    348 							break;
    349 						}
    350 
    351 						For(, x < width, x++)
    352 						{
    353 							switch(state.sourceFormat)
    354 							{
    355 							case VK_FORMAT_R8G8B8A8_UNORM:
    356 								*Pointer<Int>(d) = *Pointer<Int>(s);
    357 								break;
    358 							case VK_FORMAT_B8G8R8A8_UNORM:
    359 								{
    360 									Int bgra = *Pointer<Int>(s);
    361 									*Pointer<Int>(d) = ((bgra & Int(0x00FF0000)) >> 16) |
    362 									                   ((bgra & Int(0x000000FF)) << 16) |
    363 									                   (bgra & Int(0xFF00FF00));
    364 								}
    365 								break;
    366 							case VK_FORMAT_R16G16B16A16_UNORM:
    367 								{
    368 									Short4 c = *Pointer<UShort4>(s) >> 8;
    369 
    370 									*Pointer<Int>(d) = Int(As<Int2>(PackUnsigned(c, c)));
    371 								}
    372 								break;
    373 							case VK_FORMAT_R5G6B5_UNORM_PACK16:
    374 								{
    375 									Int rgb = Int(*Pointer<Short>(s));
    376 
    377 									*Pointer<Int>(d) = 0xFF000000 |
    378 									                   ((rgb & 0x001F) << 19) | ((rgb & 0x001C) << 14) |
    379 								                       ((rgb & 0x07E0) << 5) | ((rgb & 0x0600) >> 1) |
    380 								                       ((rgb & 0xF800) >> 8) | ((rgb & 0xE000) >> 13);
    381 								}
    382 								break;
    383 							default:
    384 								ASSERT(false);
    385 								break;
    386 							}
    387 
    388 							s += sBytes;
    389 							d += dBytes;
    390 						}
    391 					}
    392 					break;
    393 				case VK_FORMAT_R5G6B5_UNORM_PACK16:
    394 					{
    395 						For(Int x = x0, x < width, x++)
    396 						{
    397 							switch(state.sourceFormat)
    398 							{
    399 							case VK_FORMAT_B8G8R8A8_UNORM:
    400 								{
    401 									Int c = *Pointer<Int>(s);
    402 
    403 									*Pointer<Short>(d) = Short((c & 0x00F80000) >> 8 |
    404 									                           (c & 0x0000FC00) >> 5 |
    405 									                           (c & 0x000000F8) >> 3);
    406 								}
    407 								break;
    408 							case VK_FORMAT_R8G8B8A8_UNORM:
    409 								{
    410 									Int c = *Pointer<Int>(s);
    411 
    412 									*Pointer<Short>(d) = Short((c & 0x00F80000) >> 19 |
    413 									                           (c & 0x0000FC00) >> 5 |
    414 									                           (c & 0x000000F8) << 8);
    415 								}
    416 								break;
    417 							case VK_FORMAT_R16G16B16A16_UNORM:
    418 								{
    419 									Short4 cc = *Pointer<UShort4>(s) >> 8;
    420 									Int c = Int(As<Int2>(PackUnsigned(cc, cc)));
    421 
    422 									*Pointer<Short>(d) = Short((c & 0x00F80000) >> 19 |
    423 									                           (c & 0x0000FC00) >> 5 |
    424 									                           (c & 0x000000F8) << 8);
    425 								}
    426 								break;
    427 							case VK_FORMAT_R5G6B5_UNORM_PACK16:
    428 								*Pointer<Short>(d) = *Pointer<Short>(s);
    429 								break;
    430 							default:
    431 								ASSERT(false);
    432 								break;
    433 							}
    434 
    435 							s += sBytes;
    436 							d += dBytes;
    437 						}
    438 					}
    439 					break;
    440 				default:
    441 					ASSERT(false);
    442 					break;
    443 				}
    444 			}
    445 
    446 			if(state.cursorWidth > 0 && state.cursorHeight > 0)
    447 			{
    448 				Int x0 = *Pointer<Int>(cursor + OFFSET(Cursor,x));
    449 				Int y0 = *Pointer<Int>(cursor + OFFSET(Cursor,y));
    450 
    451 				For(Int y1 = 0, y1 < state.cursorHeight, y1++)
    452 				{
    453 					Int y = y0 + y1;
    454 
    455 					If(y >= 0 && y < height)
    456 					{
    457 						Pointer<Byte> d = dst + y * dStride + x0 * dBytes;
    458 						Pointer<Byte> s = src + y * sStride + x0 * sBytes;
    459 						Pointer<Byte> c = *Pointer<Pointer<Byte>>(cursor + OFFSET(Cursor,image)) + y1 * state.cursorWidth * 4;
    460 
    461 						For(Int x1 = 0, x1 < state.cursorWidth, x1++)
    462 						{
    463 							Int x = x0 + x1;
    464 
    465 							If(x >= 0 && x < width)
    466 							{
    467 								blend(state, d, s, c);
    468 							}
    469 
    470 							c += 4;
    471 							s += sBytes;
    472 							d += dBytes;
    473 						}
    474 					}
    475 				}
    476 			}
    477 		}
    478 
    479 		return function("FrameBuffer");
    480 	}
    481 
    482 	void FrameBuffer::blend(const BlitState &state, const Pointer<Byte> &d, const Pointer<Byte> &s, const Pointer<Byte> &c)
    483 	{
    484 		Short4 c1;
    485 		Short4 c2;
    486 
    487 		c1 = Unpack(*Pointer<Byte4>(c));
    488 
    489 		switch(state.sourceFormat)
    490 		{
    491 		case VK_FORMAT_B8G8R8A8_UNORM:
    492 			c2 = Unpack(*Pointer<Byte4>(s));
    493 			break;
    494 		case VK_FORMAT_R8G8B8A8_UNORM:
    495 			c2 = Swizzle(Unpack(*Pointer<Byte4>(s)), 0xC6);
    496 			break;
    497 		case VK_FORMAT_R16G16B16A16_UNORM:
    498 			c2 = Swizzle(*Pointer<Short4>(s), 0xC6);
    499 			break;
    500 		case VK_FORMAT_R5G6B5_UNORM_PACK16:
    501 			{
    502 				Int rgb(*Pointer<Short>(s));
    503 				rgb = 0xFF000000 |
    504 				      ((rgb & 0xF800) << 8) | ((rgb & 0xE01F) << 3) |
    505 				      ((rgb & 0x07E0) << 5) | ((rgb & 0x0600) >> 1) |
    506 				      ((rgb & 0x001C) >> 2);
    507 				c2 = Unpack(As<Byte4>(rgb));
    508 			}
    509 			break;
    510 		default:
    511 			ASSERT(false);
    512 			break;
    513 		}
    514 
    515 		c1 = As<Short4>(As<UShort4>(c1) >> 9);
    516 		c2 = As<Short4>(As<UShort4>(c2) >> 9);
    517 
    518 		Short4 alpha = Swizzle(c1, 0xFF) & Short4(0xFFFFu, 0xFFFFu, 0xFFFFu, 0x0000);
    519 
    520 		c1 = (c1 - c2) * alpha;
    521 		c1 = c1 >> 7;
    522 		c1 = c1 + c2;
    523 		c1 = c1 + c1;
    524 
    525 		switch(state.destFormat)
    526 		{
    527 		case VK_FORMAT_B8G8R8A8_UNORM:
    528 			*Pointer<Byte4>(d) = Byte4(PackUnsigned(c1, c1));
    529 			break;
    530 		case VK_FORMAT_R8G8B8A8_UNORM:
    531 		case VK_FORMAT_R8G8B8A8_SRGB:
    532 			{
    533 				c1 = Swizzle(c1, 0xC6);
    534 
    535 				*Pointer<Byte4>(d) = Byte4(PackUnsigned(c1, c1));
    536 			}
    537 			break;
    538 		case VK_FORMAT_R5G6B5_UNORM_PACK16:
    539 			{
    540 				Int c = Int(As<Int2>(PackUnsigned(c1, c1)));
    541 
    542 				*Pointer<Short>(d) = Short((c & 0x00F80000) >> 8 |
    543 				                           (c & 0x0000FC00) >> 5 |
    544 				                           (c & 0x000000F8) >> 3);
    545 			}
    546 			break;
    547 		default:
    548 			ASSERT(false);
    549 			break;
    550 		}
    551 	}
    552 
    553 	void FrameBuffer::threadFunction(void *parameters)
    554 	{
    555 		FrameBuffer *frameBuffer = *static_cast<FrameBuffer**>(parameters);
    556 
    557 		while(!frameBuffer->terminate)
    558 		{
    559 			frameBuffer->blitEvent.wait();
    560 
    561 			if(!frameBuffer->terminate)
    562 			{
    563 				frameBuffer->copyLocked();
    564 
    565 				frameBuffer->syncEvent.signal();
    566 			}
    567 		}
    568 	}
    569 }
    570