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, &parameters);
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 		delete blitRoutine;
71 	}
72 
setCursorImage(sw::Surface * cursorImage)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 
setCursorOrigin(int x0,int y0)90 	void FrameBuffer::setCursorOrigin(int x0, int y0)
91 	{
92 		cursor.hotspotX = x0;
93 		cursor.hotspotY = y0;
94 	}
95 
setCursorPosition(int x,int y)96 	void FrameBuffer::setCursorPosition(int x, int y)
97 	{
98 		cursor.positionX = x;
99 		cursor.positionY = y;
100 	}
101 
copy(sw::Surface * source)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 
copyLocked()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 
copyRoutine(const BlitState & state)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 
blend(const BlitState & state,const Pointer<Byte> & d,const Pointer<Byte> & s,const Pointer<Byte> & c)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 
threadFunction(void * parameters)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