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