1 // SwiftShader Software Renderer
3 // Copyright(c) 2005-2013 TransGaming Inc.
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,
6 // transcribed, stored in a retrieval system, translated into any human or computer
7 // language by any means, or disclosed to third parties without the explicit written
8 // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9 // or implied, including but not limited to any patent rights, are granted to you.
12 #include "Blitter.hpp"
14 #include "Common/Debug.hpp"
15 #include "Reactor/Reactor.hpp"
23 blitCache = new RoutineCache<BlitState>(1024);
31 void Blitter::clear(void* pixel, sw::Format format, Surface *dest, const SliceRect &dRect, unsigned int rgbaMask)
33 sw::Surface color(1, 1, 1, format, pixel, sw::Surface::bytes(format), sw::Surface::bytes(format));
34 Blitter::Options clearOptions = static_cast<sw::Blitter::Options>((rgbaMask & 0xF) | CLEAR_OPERATION);
35 blit(&color, dRect, dest, dRect, clearOptions);
38 void Blitter::blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter)
40 Blitter::Options options = filter ? static_cast<Blitter::Options>(WRITE_RGBA | FILTER_LINEAR) : WRITE_RGBA;
41 blit(source, sRect, dest, dRect, options);
44 void Blitter::blit(Surface *source, const SliceRect &sourceRect, Surface *dest, const SliceRect &destRect, const Blitter::Options& options)
46 if(blitReactor(source, sourceRect, dest, destRect, options))
51 SliceRect sRect = sourceRect;
52 SliceRect dRect = destRect;
54 bool flipX = destRect.x0 > destRect.x1;
55 bool flipY = destRect.y0 > destRect.y1;
59 swap(dRect.x0, dRect.x1);
60 swap(sRect.x0, sRect.x1);
64 swap(dRect.y0, dRect.y1);
65 swap(sRect.y0, sRect.y1);
68 source->lockInternal(sRect.x0, sRect.y0, sRect.slice, sw::LOCK_READONLY, sw::PUBLIC);
69 dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, sw::LOCK_WRITEONLY, sw::PUBLIC);
71 float w = static_cast<float>(sRect.x1 - sRect.x0) / static_cast<float>(dRect.x1 - dRect.x0);
72 float h = static_cast<float>(sRect.y1 - sRect.y0) / static_cast<float>(dRect.y1 - dRect.y0);
74 const float xStart = (float)sRect.x0 + 0.5f * w;
75 float y = (float)sRect.y0 + 0.5f * h;
77 for(int j = dRect.y0; j < dRect.y1; j++)
81 for(int i = dRect.x0; i < dRect.x1; i++)
83 // FIXME: Support RGBA mask
84 dest->copyInternal(source, i, j, x, y, (options & FILTER_LINEAR) == FILTER_LINEAR);
92 source->unlockInternal();
93 dest->unlockInternal();
96 void Blitter::blit3D(Surface *source, Surface *dest)
98 source->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
99 dest->lockInternal(0, 0, 0, sw::LOCK_WRITEONLY, sw::PUBLIC);
101 float w = static_cast<float>(source->getWidth()) / static_cast<float>(dest->getWidth());
102 float h = static_cast<float>(source->getHeight()) / static_cast<float>(dest->getHeight());
103 float d = static_cast<float>(source->getDepth()) / static_cast<float>(dest->getDepth());
106 for(int k = 0; k < dest->getDepth(); ++k)
109 for(int j = 0; j < dest->getHeight(); ++j)
112 for(int i = 0; i < dest->getWidth(); ++i)
114 dest->copyInternal(source, i, j, k, x, y, z, true);
122 source->unlockInternal();
123 dest->unlockInternal();
126 bool Blitter::read(Float4 &c, Pointer<Byte> element, Format format)
128 c = Float4(0.0f, 0.0f, 0.0f, 1.0f);
133 c.xyz = Float(Int(*Pointer<Byte>(element)));
137 c.w = Float(Int(*Pointer<Byte>(element)));
141 c.x = Float(Int(*Pointer<SByte>(element)));
145 c.x = Float(Int(*Pointer<Byte>(element)));
147 case FORMAT_R8I_SNORM:
149 c.x = Float(Int(*Pointer<SByte>(element)));
153 c.x = Float(Int(*Pointer<Byte>(element)));
157 c.x = Float(Int(*Pointer<Short>(element)));
161 c.x = Float(Int(*Pointer<UShort>(element)));
165 c.x = Float(Int(*Pointer<Int>(element)));
169 c.x = Float(Int(*Pointer<UInt>(element)));
171 case FORMAT_A8R8G8B8:
172 c = Float4(*Pointer<Byte4>(element)).zyxw;
174 case FORMAT_A8B8G8R8I:
175 c = Float4(*Pointer<SByte4>(element));
177 case FORMAT_A8B8G8R8UI:
178 c = Float4(*Pointer<Byte4>(element));
180 case FORMAT_A8B8G8R8I_SNORM:
181 c = Float4(*Pointer<SByte4>(element));
183 case FORMAT_A8B8G8R8:
184 c = Float4(*Pointer<Byte4>(element));
186 case FORMAT_X8R8G8B8:
187 c = Float4(*Pointer<Byte4>(element)).zyxw;
190 case FORMAT_X8B8G8R8I:
191 c = Float4(*Pointer<SByte4>(element));
194 case FORMAT_X8B8G8R8UI:
195 c = Float4(*Pointer<Byte4>(element));
198 case FORMAT_X8B8G8R8I_SNORM:
199 c = Float4(*Pointer<SByte4>(element));
202 case FORMAT_X8B8G8R8:
203 c = Float4(*Pointer<Byte4>(element));
206 case FORMAT_A16B16G16R16I:
207 c = Float4(*Pointer<Short4>(element));
209 case FORMAT_A16B16G16R16:
210 case FORMAT_A16B16G16R16UI:
211 c = Float4(*Pointer<UShort4>(element));
213 case FORMAT_X16B16G16R16I:
214 c = Float4(*Pointer<Short4>(element));
217 case FORMAT_X16B16G16R16UI:
218 c = Float4(*Pointer<UShort4>(element));
221 case FORMAT_A32B32G32R32I:
222 c = Float4(*Pointer<Int4>(element));
224 case FORMAT_A32B32G32R32UI:
225 c = Float4(*Pointer<UInt4>(element));
227 case FORMAT_X32B32G32R32I:
228 c = Float4(*Pointer<Int4>(element));
229 c.w = float(0x7FFFFFFF);
231 case FORMAT_X32B32G32R32UI:
232 c = Float4(*Pointer<UInt4>(element));
233 c.w = float(0xFFFFFFFF);
236 c.x = Float(Int(*Pointer<SByte>(element + 0)));
237 c.y = Float(Int(*Pointer<SByte>(element + 1)));
240 c.x = Float(Int(*Pointer<Byte>(element + 0)));
241 c.y = Float(Int(*Pointer<Byte>(element + 1)));
243 case FORMAT_G8R8I_SNORM:
244 c.x = Float(Int(*Pointer<SByte>(element + 0)));
245 c.y = Float(Int(*Pointer<SByte>(element + 1)));
248 c.x = Float(Int(*Pointer<Byte>(element + 0)));
249 c.y = Float(Int(*Pointer<Byte>(element + 1)));
252 c.x = Float(Int(*Pointer<Short>(element + 0)));
253 c.y = Float(Int(*Pointer<Short>(element + 2)));
256 case FORMAT_G16R16UI:
257 c.x = Float(Int(*Pointer<UShort>(element + 0)));
258 c.y = Float(Int(*Pointer<UShort>(element + 2)));
261 c.x = Float(Int(*Pointer<Int>(element + 0)));
262 c.y = Float(Int(*Pointer<Int>(element + 4)));
264 case FORMAT_G32R32UI:
265 c.x = Float(Int(*Pointer<UInt>(element + 0)));
266 c.y = Float(Int(*Pointer<UInt>(element + 4)));
268 case FORMAT_A32B32G32R32F:
269 c = *Pointer<Float4>(element);
272 c.x = *Pointer<Float>(element + 0);
273 c.y = *Pointer<Float>(element + 4);
276 c.x = *Pointer<Float>(element);
279 c.x = Float(Int((*Pointer<UShort>(element) & UShort(0xF800)) >> UShort(11)));
280 c.y = Float(Int((*Pointer<UShort>(element) & UShort(0x07E0)) >> UShort(5)));
281 c.z = Float(Int(*Pointer<UShort>(element) & UShort(0x001F)));
290 bool Blitter::write(Float4 &c, Pointer<Byte> element, Format format, const Blitter::Options& options)
292 bool writeR = (options & WRITE_RED) == WRITE_RED;
293 bool writeG = (options & WRITE_GREEN) == WRITE_GREEN;
294 bool writeB = (options & WRITE_BLUE) == WRITE_BLUE;
295 bool writeA = (options & WRITE_ALPHA) == WRITE_ALPHA;
296 bool writeRGBA = writeR && writeG && writeB && writeA;
301 *Pointer<Byte>(element) = Byte(RoundInt(Float(c.x)));
304 if(writeA) { *Pointer<Byte>(element) = Byte(RoundInt(Float(c.w))); }
306 case FORMAT_A8R8G8B8:
309 UShort4 c0 = As<UShort4>(RoundShort4(c.zyxw));
310 Byte8 c1 = Pack(c0, c0);
311 *Pointer<UInt>(element) = UInt(As<Long>(c1));
315 if(writeB) { *Pointer<Byte>(element + 0) = Byte(RoundInt(Float(c.z))); }
316 if(writeG) { *Pointer<Byte>(element + 1) = Byte(RoundInt(Float(c.y))); }
317 if(writeR) { *Pointer<Byte>(element + 2) = Byte(RoundInt(Float(c.x))); }
318 if(writeA) { *Pointer<Byte>(element + 3) = Byte(RoundInt(Float(c.w))); }
321 case FORMAT_A8B8G8R8:
324 UShort4 c0 = As<UShort4>(RoundShort4(c));
325 Byte8 c1 = Pack(c0, c0);
326 *Pointer<UInt>(element) = UInt(As<Long>(c1));
330 if(writeR) { *Pointer<Byte>(element + 0) = Byte(RoundInt(Float(c.x))); }
331 if(writeG) { *Pointer<Byte>(element + 1) = Byte(RoundInt(Float(c.y))); }
332 if(writeB) { *Pointer<Byte>(element + 2) = Byte(RoundInt(Float(c.z))); }
333 if(writeA) { *Pointer<Byte>(element + 3) = Byte(RoundInt(Float(c.w))); }
336 case FORMAT_X8R8G8B8:
339 UShort4 c0 = As<UShort4>(RoundShort4(c.zyxw));
340 Byte8 c1 = Pack(c0, c0);
341 *Pointer<UInt>(element) = UInt(As<Long>(c1)) | 0xFF000000;
345 if(writeB) { *Pointer<Byte>(element + 0) = Byte(RoundInt(Float(c.z))); }
346 if(writeG) { *Pointer<Byte>(element + 1) = Byte(RoundInt(Float(c.y))); }
347 if(writeR) { *Pointer<Byte>(element + 2) = Byte(RoundInt(Float(c.x))); }
348 if(writeA) { *Pointer<Byte>(element + 3) = Byte(0xFF); }
351 case FORMAT_X8B8G8R8:
354 UShort4 c0 = As<UShort4>(RoundShort4(c));
355 Byte8 c1 = Pack(c0, c0);
356 *Pointer<UInt>(element) = UInt(As<Long>(c1)) | 0xFF000000;
360 if(writeR) { *Pointer<Byte>(element + 0) = Byte(RoundInt(Float(c.x))); }
361 if(writeG) { *Pointer<Byte>(element + 1) = Byte(RoundInt(Float(c.y))); }
362 if(writeB) { *Pointer<Byte>(element + 2) = Byte(RoundInt(Float(c.z))); }
363 if(writeA) { *Pointer<Byte>(element + 3) = Byte(0xFF); }
366 case FORMAT_A32B32G32R32F:
369 *Pointer<Float4>(element) = c;
373 if(writeR) { *Pointer<Float>(element) = c.x; }
374 if(writeG) { *Pointer<Float>(element + 4) = c.y; }
375 if(writeB) { *Pointer<Float>(element + 8) = c.z; }
376 if(writeA) { *Pointer<Float>(element + 12) = c.w; }
382 *Pointer<Float2>(element) = Float2(c);
386 if(writeR) { *Pointer<Float>(element) = c.x; }
387 if(writeG) { *Pointer<Float>(element + 4) = c.y; }
391 if(writeR) { *Pointer<Float>(element) = c.x; }
393 case FORMAT_A8B8G8R8I:
394 case FORMAT_A8B8G8R8I_SNORM:
395 if(writeA) { *Pointer<SByte>(element + 3) = SByte(RoundInt(Float(c.w))); }
396 case FORMAT_X8B8G8R8I:
397 case FORMAT_X8B8G8R8I_SNORM:
398 if(writeA && (format == FORMAT_X8B8G8R8I || format == FORMAT_X8B8G8R8I_SNORM))
400 *Pointer<SByte>(element + 3) = SByte(0x7F);
402 if(writeB) { *Pointer<SByte>(element + 2) = SByte(RoundInt(Float(c.z))); }
404 case FORMAT_G8R8I_SNORM:
405 if(writeG) { *Pointer<SByte>(element + 1) = SByte(RoundInt(Float(c.y))); }
407 case FORMAT_R8I_SNORM:
408 if(writeR) { *Pointer<SByte>(element) = SByte(RoundInt(Float(c.x))); }
410 case FORMAT_A8B8G8R8UI:
411 if(writeA) { *Pointer<Byte>(element + 3) = Byte(RoundInt(Float(c.w))); }
412 case FORMAT_X8B8G8R8UI:
413 if(writeA && (format == FORMAT_X8B8G8R8UI))
415 *Pointer<Byte>(element + 3) = Byte(0xFF);
417 if(writeB) { *Pointer<Byte>(element + 2) = Byte(RoundInt(Float(c.z))); }
420 if(writeG) { *Pointer<Byte>(element + 1) = Byte(RoundInt(Float(c.y))); }
423 if(writeR) { *Pointer<Byte>(element) = Byte(RoundInt(Float(c.x))); }
425 case FORMAT_A16B16G16R16I:
428 *Pointer<Short4>(element) = Short4(RoundInt(c));
432 if(writeR) { *Pointer<Short>(element) = Short(RoundInt(Float(c.x))); }
433 if(writeG) { *Pointer<Short>(element + 2) = Short(RoundInt(Float(c.y))); }
434 if(writeB) { *Pointer<Short>(element + 4) = Short(RoundInt(Float(c.z))); }
435 if(writeA) { *Pointer<Short>(element + 6) = Short(RoundInt(Float(c.w))); }
438 case FORMAT_X16B16G16R16I:
441 *Pointer<Short4>(element) = Short4(RoundInt(c));
445 if(writeR) { *Pointer<Short>(element) = Short(RoundInt(Float(c.x))); }
446 if(writeG) { *Pointer<Short>(element + 2) = Short(RoundInt(Float(c.y))); }
447 if(writeB) { *Pointer<Short>(element + 4) = Short(RoundInt(Float(c.z))); }
449 if(writeA) { *Pointer<Short>(element + 6) = Short(0x7F); }
454 *Pointer<UInt>(element) = UInt(As<Long>(Short4(RoundInt(c))));
458 if(writeR) { *Pointer<Short>(element) = Short(RoundInt(Float(c.x))); }
459 if(writeG) { *Pointer<Short>(element + 2) = Short(RoundInt(Float(c.y))); }
463 if(writeR) { *Pointer<Short>(element) = Short(RoundInt(Float(c.x))); }
465 case FORMAT_A16B16G16R16UI:
466 case FORMAT_A16B16G16R16:
469 *Pointer<UShort4>(element) = UShort4(RoundInt(c));
473 if(writeR) { *Pointer<UShort>(element) = UShort(RoundInt(Float(c.x))); }
474 if(writeG) { *Pointer<UShort>(element + 2) = UShort(RoundInt(Float(c.y))); }
475 if(writeB) { *Pointer<UShort>(element + 4) = UShort(RoundInt(Float(c.z))); }
476 if(writeA) { *Pointer<UShort>(element + 6) = UShort(RoundInt(Float(c.w))); }
479 case FORMAT_X16B16G16R16UI:
482 *Pointer<UShort4>(element) = UShort4(RoundInt(c));
486 if(writeR) { *Pointer<UShort>(element) = UShort(RoundInt(Float(c.x))); }
487 if(writeG) { *Pointer<UShort>(element + 2) = UShort(RoundInt(Float(c.y))); }
488 if(writeB) { *Pointer<UShort>(element + 4) = UShort(RoundInt(Float(c.z))); }
490 if(writeA) { *Pointer<UShort>(element + 6) = UShort(0xFF); }
492 case FORMAT_G16R16UI:
496 *Pointer<UInt>(element) = UInt(As<Long>(UShort4(RoundInt(c))));
500 if(writeR) { *Pointer<UShort>(element) = UShort(RoundInt(Float(c.x))); }
501 if(writeG) { *Pointer<UShort>(element + 2) = UShort(RoundInt(Float(c.y))); }
505 if(writeR) { *Pointer<UShort>(element) = UShort(RoundInt(Float(c.x))); }
507 case FORMAT_A32B32G32R32I:
510 *Pointer<Int4>(element) = RoundInt(c);
514 if(writeR) { *Pointer<Int>(element) = RoundInt(Float(c.x)); }
515 if(writeG) { *Pointer<Int>(element + 4) = RoundInt(Float(c.y)); }
516 if(writeB) { *Pointer<Int>(element + 8) = RoundInt(Float(c.z)); }
517 if(writeA) { *Pointer<Int>(element + 12) = RoundInt(Float(c.w)); }
520 case FORMAT_X32B32G32R32I:
523 *Pointer<Int4>(element) = RoundInt(c);
527 if(writeR) { *Pointer<Int>(element) = RoundInt(Float(c.x)); }
528 if(writeG) { *Pointer<Int>(element + 4) = RoundInt(Float(c.y)); }
529 if(writeB) { *Pointer<Int>(element + 8) = RoundInt(Float(c.z)); }
531 if(writeA) { *Pointer<Int>(element + 12) = Int(0x7FFFFFFF); }
534 if(writeG) { *Pointer<Int>(element + 4) = RoundInt(Float(c.y)); }
536 if(writeR) { *Pointer<Int>(element) = RoundInt(Float(c.x)); }
538 case FORMAT_A32B32G32R32UI:
541 *Pointer<UInt4>(element) = UInt4(RoundInt(c));
545 if(writeR) { *Pointer<UInt>(element) = As<UInt>(RoundInt(Float(c.x))); }
546 if(writeG) { *Pointer<UInt>(element + 4) = As<UInt>(RoundInt(Float(c.y))); }
547 if(writeB) { *Pointer<UInt>(element + 8) = As<UInt>(RoundInt(Float(c.z))); }
548 if(writeA) { *Pointer<UInt>(element + 12) = As<UInt>(RoundInt(Float(c.w))); }
551 case FORMAT_X32B32G32R32UI:
554 *Pointer<UInt4>(element) = UInt4(RoundInt(c));
558 if(writeR) { *Pointer<UInt>(element) = As<UInt>(RoundInt(Float(c.x))); }
559 if(writeG) { *Pointer<UInt>(element + 4) = As<UInt>(RoundInt(Float(c.y))); }
560 if(writeB) { *Pointer<UInt>(element + 8) = As<UInt>(RoundInt(Float(c.z))); }
562 if(writeA) { *Pointer<UInt4>(element + 12) = UInt4(0xFFFFFFFF); }
564 case FORMAT_G32R32UI:
565 if(writeG) { *Pointer<UInt>(element + 4) = As<UInt>(RoundInt(Float(c.y))); }
567 if(writeR) { *Pointer<UInt>(element) = As<UInt>(RoundInt(Float(c.x))); }
570 if(writeR && writeG && writeB)
572 *Pointer<UShort>(element) = UShort(RoundInt(Float(c.z)) |
573 (RoundInt(Float(c.y)) << Int(5)) |
574 (RoundInt(Float(c.x)) << Int(11)));
578 unsigned short mask = (writeB ? 0x001F : 0x0000) | (writeG ? 0x07E0 : 0x0000) | (writeR ? 0xF800 : 0x0000);
579 unsigned short unmask = ~mask;
580 *Pointer<UShort>(element) = (*Pointer<UShort>(element) & UShort(unmask)) |
581 (UShort(RoundInt(Float(c.z)) |
582 (RoundInt(Float(c.y)) << Int(5)) |
583 (RoundInt(Float(c.x)) << Int(11))) & UShort(mask));
592 bool Blitter::read(Int4 &c, Pointer<Byte> element, Format format)
594 c = Int4(0, 0, 0, 0xFFFFFFFF);
598 case FORMAT_A8B8G8R8I:
599 Insert(c, Int(*Pointer<SByte>(element + 3)), 3);
600 case FORMAT_X8B8G8R8I:
601 Insert(c, Int(*Pointer<SByte>(element + 2)), 2);
603 Insert(c, Int(*Pointer<SByte>(element + 1)), 1);
605 Insert(c, Int(*Pointer<SByte>(element)), 0);
606 if(format != FORMAT_A8B8G8R8I)
608 Insert(c, Int(0x7F), 3); // Set alpha
611 case FORMAT_A8B8G8R8UI:
612 Insert(c, Int(*Pointer<Byte>(element + 3)), 3);
613 case FORMAT_X8B8G8R8UI:
614 Insert(c, Int(*Pointer<Byte>(element + 2)), 2);
616 Insert(c, Int(*Pointer<Byte>(element + 1)), 1);
618 Insert(c, Int(*Pointer<Byte>(element)), 0);
619 if(format != FORMAT_A8B8G8R8UI)
621 Insert(c, Int(0xFF), 3); // Set alpha
624 case FORMAT_A16B16G16R16I:
625 Insert(c, Int(*Pointer<Short>(element + 3)), 3);
626 case FORMAT_X16B16G16R16I:
627 Insert(c, Int(*Pointer<Short>(element + 2)), 2);
629 Insert(c, Int(*Pointer<Short>(element + 1)), 1);
631 Insert(c, Int(*Pointer<Short>(element)), 0);
632 if(format != FORMAT_A16B16G16R16I)
634 Insert(c, Int(0x7FFF), 3); // Set alpha
637 case FORMAT_A16B16G16R16UI:
638 Insert(c, Int(*Pointer<UShort>(element + 3)), 3);
639 case FORMAT_X16B16G16R16UI:
640 Insert(c, Int(*Pointer<UShort>(element + 2)), 2);
641 case FORMAT_G16R16UI:
642 Insert(c, Int(*Pointer<UShort>(element + 1)), 1);
644 Insert(c, Int(*Pointer<UShort>(element)), 0);
645 if(format != FORMAT_A16B16G16R16UI)
647 Insert(c, Int(0xFFFF), 3); // Set alpha
650 case FORMAT_A32B32G32R32I:
651 Insert(c, Int(*Pointer<Int>(element + 3)), 3);
652 case FORMAT_X32B32G32R32I:
653 Insert(c, Int(*Pointer<Int>(element + 2)), 2);
655 Insert(c, Int(*Pointer<Int>(element + 1)), 1);
657 Insert(c, Int(*Pointer<Int>(element)), 0);
658 if(format != FORMAT_A32B32G32R32I)
660 Insert(c, Int(0x7FFFFFFF), 3); // Set alpha
663 case FORMAT_A32B32G32R32UI:
664 Insert(c, Int(*Pointer<UInt>(element + 3)), 3);
665 case FORMAT_X32B32G32R32UI:
666 Insert(c, Int(*Pointer<UInt>(element + 2)), 2);
667 case FORMAT_G32R32UI:
668 Insert(c, Int(*Pointer<UInt>(element + 1)), 1);
670 Insert(c, Int(*Pointer<UInt>(element)), 0);
671 if(format != FORMAT_A32B32G32R32UI)
673 Insert(c, Int(UInt(0xFFFFFFFFU)), 3); // Set alpha
683 bool Blitter::write(Int4 &c, Pointer<Byte> element, Format format, const Blitter::Options& options)
685 bool writeR = (options & WRITE_RED) == WRITE_RED;
686 bool writeG = (options & WRITE_GREEN) == WRITE_GREEN;
687 bool writeB = (options & WRITE_BLUE) == WRITE_BLUE;
688 bool writeA = (options & WRITE_ALPHA) == WRITE_ALPHA;
689 bool writeRGBA = writeR && writeG && writeB && writeA;
693 case FORMAT_A8B8G8R8I:
694 if(writeA) { *Pointer<SByte>(element + 3) = SByte(Extract(c, 3)); }
695 case FORMAT_X8B8G8R8I:
696 if(writeA && (format != FORMAT_A8B8G8R8I))
698 *Pointer<SByte>(element + 3) = SByte(0x7F);
700 if(writeB) { *Pointer<SByte>(element + 2) = SByte(Extract(c, 2)); }
702 if(writeG) { *Pointer<SByte>(element + 1) = SByte(Extract(c, 1)); }
704 if(writeR) { *Pointer<SByte>(element) = SByte(Extract(c, 0)); }
706 case FORMAT_A8B8G8R8UI:
707 if(writeA) { *Pointer<Byte>(element + 3) = Byte(Extract(c, 3)); }
708 case FORMAT_X8B8G8R8UI:
709 if(writeA && (format != FORMAT_A8B8G8R8UI))
711 *Pointer<Byte>(element + 3) = Byte(0xFF);
713 if(writeB) { *Pointer<Byte>(element + 2) = Byte(Extract(c, 2)); }
715 if(writeG) { *Pointer<Byte>(element + 1) = Byte(Extract(c, 1)); }
717 if(writeR) { *Pointer<Byte>(element) = Byte(Extract(c, 0)); }
719 case FORMAT_A16B16G16R16I:
720 if(writeA) { *Pointer<Short>(element + 6) = Short(Extract(c, 3)); }
721 case FORMAT_X16B16G16R16I:
722 if(writeA && (format != FORMAT_A16B16G16R16I))
724 *Pointer<Short>(element + 6) = Short(0x7FFF);
726 if(writeB) { *Pointer<Short>(element + 4) = Short(Extract(c, 2)); }
728 if(writeG) { *Pointer<Short>(element + 2) = Short(Extract(c, 1)); }
730 if(writeR) { *Pointer<Short>(element) = Short(Extract(c, 0)); }
732 case FORMAT_A16B16G16R16UI:
733 if(writeA) { *Pointer<UShort>(element + 6) = UShort(Extract(c, 3)); }
734 case FORMAT_X16B16G16R16UI:
735 if(writeA && (format != FORMAT_A16B16G16R16UI))
737 *Pointer<UShort>(element + 6) = UShort(0xFFFF);
739 if(writeB) { *Pointer<UShort>(element + 4) = UShort(Extract(c, 2)); }
740 case FORMAT_G16R16UI:
741 if(writeG) { *Pointer<UShort>(element + 2) = UShort(Extract(c, 1)); }
743 if(writeR) { *Pointer<UShort>(element) = UShort(Extract(c, 0)); }
745 case FORMAT_A32B32G32R32I:
748 *Pointer<Int4>(element) = c;
752 if(writeR) { *Pointer<Int>(element) = Extract(c, 0); }
753 if(writeG) { *Pointer<Int>(element + 4) = Extract(c, 1); }
754 if(writeB) { *Pointer<Int>(element + 8) = Extract(c, 2); }
755 if(writeA) { *Pointer<Int>(element + 12) = Extract(c, 3); }
758 case FORMAT_X32B32G32R32I:
761 *Pointer<Int4>(element) = c;
765 if(writeR) { *Pointer<Int>(element) = Extract(c, 0); }
766 if(writeG) { *Pointer<Int>(element + 4) = Extract(c, 1); }
767 if(writeB) { *Pointer<Int>(element + 8) = Extract(c, 2); }
769 if(writeA) { *Pointer<Int>(element + 12) = Int(0x7FFFFFFF); }
772 if(writeR) { *Pointer<Int>(element) = Extract(c, 0); }
773 if(writeG) { *Pointer<Int>(element + 4) = Extract(c, 1); }
776 if(writeR) { *Pointer<Int>(element) = Extract(c, 0); }
778 case FORMAT_A32B32G32R32UI:
781 *Pointer<UInt4>(element) = As<UInt4>(c);
785 if(writeR) { *Pointer<UInt>(element) = As<UInt>(Extract(c, 0)); }
786 if(writeG) { *Pointer<UInt>(element + 4) = As<UInt>(Extract(c, 1)); }
787 if(writeB) { *Pointer<UInt>(element + 8) = As<UInt>(Extract(c, 2)); }
788 if(writeA) { *Pointer<UInt>(element + 12) = As<UInt>(Extract(c, 3)); }
791 case FORMAT_X32B32G32R32UI:
794 *Pointer<UInt4>(element) = As<UInt4>(c);
798 if(writeR) { *Pointer<UInt>(element) = As<UInt>(Extract(c, 0)); }
799 if(writeG) { *Pointer<UInt>(element + 4) = As<UInt>(Extract(c, 1)); }
800 if(writeB) { *Pointer<UInt>(element + 8) = As<UInt>(Extract(c, 2)); }
802 if(writeA) { *Pointer<UInt>(element + 3) = UInt(0xFFFFFFFF); }
804 case FORMAT_G32R32UI:
805 if(writeR) { *Pointer<UInt>(element) = As<UInt>(Extract(c, 0)); }
806 if(writeG) { *Pointer<UInt>(element + 4) = As<UInt>(Extract(c, 1)); }
809 if(writeR) { *Pointer<UInt>(element) = As<UInt>(Extract(c, 0)); }
818 bool Blitter::GetScale(float4& scale, Format format)
824 case FORMAT_A8R8G8B8:
825 case FORMAT_X8R8G8B8:
828 case FORMAT_X8B8G8R8:
829 case FORMAT_A8B8G8R8:
830 scale = vector(0xFF, 0xFF, 0xFF, 0xFF);
832 case FORMAT_R8I_SNORM:
833 case FORMAT_G8R8I_SNORM:
834 case FORMAT_X8B8G8R8I_SNORM:
835 case FORMAT_A8B8G8R8I_SNORM:
836 scale = vector(0x7F, 0x7F, 0x7F, 0x7F);
842 case FORMAT_X8B8G8R8I:
843 case FORMAT_X8B8G8R8UI:
844 case FORMAT_A8B8G8R8I:
845 case FORMAT_A8B8G8R8UI:
850 case FORMAT_G16R16UI:
851 case FORMAT_X16B16G16R16I:
852 case FORMAT_X16B16G16R16UI:
853 case FORMAT_A16B16G16R16:
854 case FORMAT_A16B16G16R16I:
855 case FORMAT_A16B16G16R16UI:
859 case FORMAT_G32R32UI:
860 case FORMAT_X32B32G32R32I:
861 case FORMAT_X32B32G32R32UI:
862 case FORMAT_A32B32G32R32I:
863 case FORMAT_A32B32G32R32UI:
864 case FORMAT_A32B32G32R32F:
867 scale = vector(1.0f, 1.0f, 1.0f, 1.0f);
870 scale = vector(0x1F, 0x3F, 0x1F, 1.0f);
879 bool Blitter::ApplyScaleAndClamp(Float4& value, const BlitState& state)
881 float4 scale, unscale;
882 if(Surface::isNonNormalizedInteger(state.sourceFormat) &&
883 !Surface::isNonNormalizedInteger(state.destFormat) &&
884 (state.options & CLEAR_OPERATION))
886 // If we're clearing a buffer from an int or uint color into a normalized color,
887 // then the whole range of the int or uint color must be scaled between 0 and 1.
888 switch(state.sourceFormat)
890 case FORMAT_A32B32G32R32I:
891 unscale = vector(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF);
893 case FORMAT_A32B32G32R32UI:
894 unscale = vector(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
900 else if(!GetScale(unscale, state.sourceFormat))
905 if(!GetScale(scale, state.destFormat))
912 value *= Float4(scale.x / unscale.x, scale.y / unscale.y, scale.z / unscale.z, scale.w / unscale.w);
915 if(Surface::isFloatFormat(state.sourceFormat) && !Surface::isFloatFormat(state.destFormat))
917 value = Min(value, Float4(scale.x, scale.y, scale.z, scale.w));
919 value = Max(value, Float4(Surface::isUnsignedComponent(state.destFormat, 0) ? 0.0f : -scale.x,
920 Surface::isUnsignedComponent(state.destFormat, 1) ? 0.0f : -scale.y,
921 Surface::isUnsignedComponent(state.destFormat, 2) ? 0.0f : -scale.z,
922 Surface::isUnsignedComponent(state.destFormat, 3) ? 0.0f : -scale.w));
928 Routine *Blitter::generate(BlitState &state)
930 Function<Void, Pointer<Byte> > function;
932 Pointer<Byte> blit(function.arg(0));
934 Pointer<Byte> source = *Pointer<Pointer<Byte> >(blit + OFFSET(BlitData,source));
935 Pointer<Byte> dest = *Pointer<Pointer<Byte> >(blit + OFFSET(BlitData,dest));
936 Int sPitchB = *Pointer<Int>(blit + OFFSET(BlitData,sPitchB));
937 Int dPitchB = *Pointer<Int>(blit + OFFSET(BlitData,dPitchB));
939 Float x0 = *Pointer<Float>(blit + OFFSET(BlitData,x0));
940 Float y0 = *Pointer<Float>(blit + OFFSET(BlitData,y0));
941 Float w = *Pointer<Float>(blit + OFFSET(BlitData,w));
942 Float h = *Pointer<Float>(blit + OFFSET(BlitData,h));
944 Int x0d = *Pointer<Int>(blit + OFFSET(BlitData,x0d));
945 Int x1d = *Pointer<Int>(blit + OFFSET(BlitData,x1d));
946 Int y0d = *Pointer<Int>(blit + OFFSET(BlitData,y0d));
947 Int y1d = *Pointer<Int>(blit + OFFSET(BlitData,y1d));
949 Int sWidth = *Pointer<Int>(blit + OFFSET(BlitData,sWidth));
950 Int sHeight = *Pointer<Int>(blit + OFFSET(BlitData,sHeight));
952 bool intSrc = Surface::isNonNormalizedInteger(state.sourceFormat);
953 bool intDst = Surface::isNonNormalizedInteger(state.destFormat);
954 bool intBoth = intSrc && intDst;
956 bool hasConstantColorI = false;
958 bool hasConstantColorF = false;
959 Float4 constantColorF;
960 if(state.options & CLEAR_OPERATION)
962 if(intBoth) // Integer types
964 if(!read(constantColorI, source, state.sourceFormat))
968 hasConstantColorI = true;
972 if(!read(constantColorF, source, state.sourceFormat))
976 hasConstantColorF = true;
978 if(!ApplyScaleAndClamp(constantColorF, state))
987 For(Int j = y0d, j < y1d, j++)
990 Pointer<Byte> destLine = dest + j * dPitchB;
992 For(Int i = x0d, i < x1d, i++)
994 Pointer<Byte> d = destLine + i * Surface::bytes(state.destFormat);
995 if(hasConstantColorI)
997 if(!write(constantColorI, d, state.destFormat, state.options))
1002 else if(hasConstantColorF)
1004 if(!write(constantColorF, d, state.destFormat, state.options))
1009 else if(intBoth) // Integer types do not support filtering
1011 Int4 color; // When both formats are true integer types, we don't go to float to avoid losing precision
1012 Pointer<Byte> s = source + Int(y) * sPitchB + Int(x) * Surface::bytes(state.sourceFormat);
1013 if(!read(color, s, state.sourceFormat))
1018 if(!write(color, d, state.destFormat, state.options))
1027 if(!(state.options & FILTER_LINEAR) || intSrc)
1032 Pointer<Byte> s = source + Y * sPitchB + X * Surface::bytes(state.sourceFormat);
1034 if(!read(color, s, state.sourceFormat))
1039 else // Bilinear filtering
1041 Float x0 = x - 0.5f;
1042 Float y0 = y - 0.5f;
1044 Int X0 = Max(Int(x0), 0);
1045 Int Y0 = Max(Int(y0), 0);
1047 Int X1 = IfThenElse(X0 + 1 >= sWidth, X0, X0 + 1);
1048 Int Y1 = IfThenElse(Y0 + 1 >= sHeight, Y0, Y0 + 1);
1050 Pointer<Byte> s00 = source + Y0 * sPitchB + X0 * Surface::bytes(state.sourceFormat);
1051 Pointer<Byte> s01 = source + Y0 * sPitchB + X1 * Surface::bytes(state.sourceFormat);
1052 Pointer<Byte> s10 = source + Y1 * sPitchB + X0 * Surface::bytes(state.sourceFormat);
1053 Pointer<Byte> s11 = source + Y1 * sPitchB + X1 * Surface::bytes(state.sourceFormat);
1055 Float4 c00; if(!read(c00, s00, state.sourceFormat)) return nullptr;
1056 Float4 c01; if(!read(c01, s01, state.sourceFormat)) return nullptr;
1057 Float4 c10; if(!read(c10, s10, state.sourceFormat)) return nullptr;
1058 Float4 c11; if(!read(c11, s11, state.sourceFormat)) return nullptr;
1060 Float4 fx = Float4(x0 - Float(X0));
1061 Float4 fy = Float4(y0 - Float(Y0));
1063 color = c00 * (Float4(1.0f) - fx) * (Float4(1.0f) - fy) +
1064 c01 * fx * (Float4(1.0f) - fy) +
1065 c10 * (Float4(1.0f) - fx) * fy +
1069 if(!ApplyScaleAndClamp(color, state) || !write(color, d, state.destFormat, state.options))
1075 if(!hasConstantColorI && !hasConstantColorF) { x += w; }
1078 if(!hasConstantColorI && !hasConstantColorF) { y += h; }
1082 return function(L"BlitRoutine");
1085 bool Blitter::blitReactor(Surface *source, const SliceRect &sourceRect, Surface *dest, const SliceRect &destRect, const Blitter::Options& options)
1087 ASSERT(!(options & CLEAR_OPERATION) || ((source->getWidth() == 1) && (source->getHeight() == 1) && (source->getDepth() == 1)));
1089 Rect dRect = destRect;
1090 Rect sRect = sourceRect;
1091 if(destRect.x0 > destRect.x1)
1093 swap(dRect.x0, dRect.x1);
1094 swap(sRect.x0, sRect.x1);
1096 if(destRect.y0 > destRect.y1)
1098 swap(dRect.y0, dRect.y1);
1099 swap(sRect.y0, sRect.y1);
1104 bool useSourceInternal = !source->isExternalDirty();
1105 bool useDestInternal = !dest->isExternalDirty();
1107 state.sourceFormat = source->getFormat(useSourceInternal);
1108 state.destFormat = dest->getFormat(useDestInternal);
1109 state.options = options;
1111 criticalSection.lock();
1112 Routine *blitRoutine = blitCache->query(state);
1116 blitRoutine = generate(state);
1120 criticalSection.unlock();
1124 blitCache->add(state, blitRoutine);
1127 criticalSection.unlock();
1129 void (*blitFunction)(const BlitData *data) = (void(*)(const BlitData*))blitRoutine->getEntry();
1133 bool isRGBA = ((options & WRITE_RGBA) == WRITE_RGBA);
1134 bool isEntireDest = dest->isEntire(destRect);
1136 data.source = source->lock(0, 0, sourceRect.slice, sw::LOCK_READONLY, sw::PUBLIC, useSourceInternal);
1137 data.dest = dest->lock(0, 0, destRect.slice, isRGBA ? (isEntireDest ? sw::LOCK_DISCARD : sw::LOCK_WRITEONLY) : sw::LOCK_READWRITE, sw::PUBLIC, useDestInternal);
1138 data.sPitchB = source->getPitchB(useSourceInternal);
1139 data.dPitchB = dest->getPitchB(useDestInternal);
1141 data.w = 1.0f / (dRect.x1 - dRect.x0) * (sRect.x1 - sRect.x0);
1142 data.h = 1.0f / (dRect.y1 - dRect.y0) * (sRect.y1 - sRect.y0);
1143 data.x0 = (float)sRect.x0 + 0.5f * data.w;
1144 data.y0 = (float)sRect.y0 + 0.5f * data.h;
1146 data.x0d = dRect.x0;
1147 data.x1d = dRect.x1;
1148 data.y0d = dRect.y0;
1149 data.y1d = dRect.y1;
1151 data.sWidth = source->getWidth();
1152 data.sHeight = source->getHeight();
1154 blitFunction(&data);
1156 source->unlock(useSourceInternal);
1157 dest->unlock(useDestInternal);