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