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