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, &parameters);
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