12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496 |
- // Copyright 2009 Dolphin Emulator Project
- // SPDX-License-Identifier: GPL-2.0-or-later
- #include "VideoBackends/Software/TextureEncoder.h"
- #include "Common/Align.h"
- #include "Common/Assert.h"
- #include "Common/CommonFuncs.h"
- #include "Common/CommonTypes.h"
- #include "Common/MsgHandler.h"
- #include "Common/Swap.h"
- #include "VideoBackends/Software/EfbInterface.h"
- #include "VideoBackends/Software/SWTexture.h"
- #include "VideoCommon/BPMemory.h"
- #include "VideoCommon/LookUpTables.h"
- #include "VideoCommon/TextureCacheBase.h"
- #include "VideoCommon/TextureDecoder.h"
- namespace TextureEncoder
- {
- static inline void RGBA_to_RGBA8(const u8* src, u8* r, u8* g, u8* b, u8* a)
- {
- u32 srcColor = *(u32*)src;
- *a = Convert6To8(srcColor & 0x3f);
- *b = Convert6To8((srcColor >> 6) & 0x3f);
- *g = Convert6To8((srcColor >> 12) & 0x3f);
- *r = Convert6To8((srcColor >> 18) & 0x3f);
- }
- static inline void RGBA_to_RGB8(const u8* src, u8* r, u8* g, u8* b)
- {
- u32 srcColor = *(u32*)src;
- *b = Convert6To8((srcColor >> 6) & 0x3f);
- *g = Convert6To8((srcColor >> 12) & 0x3f);
- *r = Convert6To8((srcColor >> 18) & 0x3f);
- }
- static inline u8 RGB8_to_I(u8 r, u8 g, u8 b)
- {
- // values multiplied by 256 to keep math integer
- u16 val = 4096 + 66 * r + 129 * g + 25 * b;
- return val >> 8;
- }
- // box filter sampling averages 4 samples with the source texel being the top left of the box
- // components are scaled to the range 0-255 after all samples are taken
- static inline void BoxfilterRGBA_to_RGBA8(const u8* src, u8* r, u8* g, u8* b, u8* a)
- {
- u16 r16 = 0, g16 = 0, b16 = 0, a16 = 0;
- for (int y = 0; y < 2; y++)
- {
- for (int x = 0; x < 2; x++)
- {
- u32 srcColor = *(u32*)src;
- a16 += srcColor & 0x3f;
- b16 += (srcColor >> 6) & 0x3f;
- g16 += (srcColor >> 12) & 0x3f;
- r16 += (srcColor >> 18) & 0x3f;
- src += 3; // move to next pixel
- }
- src += (640 - 2) * 3; // move to next line
- }
- *r = r16 + (r16 >> 6);
- *g = g16 + (g16 >> 6);
- *b = b16 + (b16 >> 6);
- *a = a16 + (a16 >> 6);
- }
- static inline void BoxfilterRGBA_to_RGB8(const u8* src, u8* r, u8* g, u8* b)
- {
- u16 r16 = 0, g16 = 0, b16 = 0;
- for (int y = 0; y < 2; y++)
- {
- for (int x = 0; x < 2; x++)
- {
- u32 srcColor = *(u32*)src;
- b16 += (srcColor >> 6) & 0x3f;
- g16 += (srcColor >> 12) & 0x3f;
- r16 += (srcColor >> 18) & 0x3f;
- src += 3; // move to next pixel
- }
- src += (640 - 2) * 3; // move to next line
- }
- *r = r16 + (r16 >> 6);
- *g = g16 + (g16 >> 6);
- *b = b16 + (b16 >> 6);
- }
- static inline void BoxfilterRGBA_to_x8(const u8* src, u8* x8, int shift)
- {
- u16 x16 = 0;
- for (int y = 0; y < 2; y++)
- {
- for (int x = 0; x < 2; x++)
- {
- u32 srcColor = *(u32*)src;
- x16 += (srcColor >> shift) & 0x3f;
- src += 3; // move to next pixel
- }
- src += (640 - 2) * 3; // move to next line
- }
- *x8 = x16 + (x16 >> 6);
- }
- static inline void BoxfilterRGBA_to_xx8(const u8* src, u8* x1, u8* x2, int shift1, int shift2)
- {
- u16 x16_1 = 0;
- u16 x16_2 = 0;
- for (int y = 0; y < 2; y++)
- {
- for (int x = 0; x < 2; x++)
- {
- u32 srcColor = *(u32*)src;
- x16_1 += (srcColor >> shift1) & 0x3f;
- x16_2 += (srcColor >> shift2) & 0x3f;
- src += 3; // move to next pixel
- }
- src += (640 - 2) * 3; // move to next line
- }
- *x1 = x16_1 + (x16_1 >> 6);
- *x2 = x16_2 + (x16_2 >> 6);
- }
- static inline void BoxfilterRGB_to_RGB8(const u8* src, u8* r, u8* g, u8* b)
- {
- u16 r16 = 0, g16 = 0, b16 = 0;
- for (int y = 0; y < 2; y++)
- {
- for (int x = 0; x < 2; x++)
- {
- b16 += src[0];
- g16 += src[1];
- r16 += src[2];
- src += 3; // move to next pixel
- }
- src += (640 - 2) * 3; // move to next line
- }
- *r = r16 >> 2;
- *g = g16 >> 2;
- *b = b16 >> 2;
- }
- static inline void BoxfilterRGB_to_x8(const u8* src, u8* x8, int comp)
- {
- u16 x16 = 0;
- for (int y = 0; y < 2; y++)
- {
- for (int x = 0; x < 2; x++)
- {
- x16 += src[comp];
- src += 3; // move to next pixel
- }
- src += (640 - 2) * 3; // move to next line
- }
- *x8 = x16 >> 2;
- }
- static inline void BoxfilterRGB_to_xx8(const u8* src, u8* x1, u8* x2, int comp1, int comp2)
- {
- u16 x16_1 = 0;
- u16 x16_2 = 0;
- for (int y = 0; y < 2; y++)
- {
- for (int x = 0; x < 2; x++)
- {
- x16_1 += src[comp1];
- x16_2 += src[comp2];
- src += 3; // move to next pixel
- }
- src += (640 - 2) * 3; // move to next line
- }
- *x1 = x16_1 >> 2;
- *x2 = x16_2 >> 2;
- }
- static void SetBlockDimensions(int blkWidthLog2, int blkHeightLog2, u16* sBlkCount, u16* tBlkCount,
- u16* sBlkSize, u16* tBlkSize)
- {
- // if half_scale is 1 then the size is cut in half
- u32 width = bpmem.copyTexSrcWH.x >> bpmem.triggerEFBCopy.half_scale;
- u32 height = bpmem.copyTexSrcWH.y >> bpmem.triggerEFBCopy.half_scale;
- *sBlkCount = (width >> blkWidthLog2) + 1;
- *tBlkCount = (height >> blkHeightLog2) + 1;
- *sBlkSize = 1 << blkWidthLog2;
- *tBlkSize = 1 << blkHeightLog2;
- }
- static void SetSpans(int sBlkSize, int tBlkSize, s32* tSpan, s32* sBlkSpan, s32* tBlkSpan,
- s32* writeStride)
- {
- // width is 1 less than the number of pixels of width
- u32 width = bpmem.copyTexSrcWH.x >> bpmem.triggerEFBCopy.half_scale;
- u32 alignedWidth = Common::AlignUp(width + 1, sBlkSize);
- u32 readStride = 3 << bpmem.triggerEFBCopy.half_scale;
- *tSpan = (640 - sBlkSize) *
- readStride; // bytes to advance src pointer after each row of texels in a block
- *sBlkSpan =
- ((-640 * tBlkSize) + sBlkSize) * readStride; // bytes to advance src pointer after each block
- *tBlkSpan = ((640 * tBlkSize) - alignedWidth) *
- readStride; // bytes to advance src pointer after each row of blocks
- *writeStride = bpmem.copyDestStride << 5;
- }
- #define ENCODE_LOOP_BLOCKS \
- for (int tBlk = 0; tBlk < tBlkCount; tBlk++) \
- { \
- dst = dstBlockStart; \
- for (int sBlk = 0; sBlk < sBlkCount; sBlk++) \
- { \
- for (int t = 0; t < tBlkSize; t++) \
- { \
- for (int s = 0; s < sBlkSize; s++) \
- {
- #define ENCODE_LOOP_SPANS \
- } \
- src += tSpan; \
- } \
- src += sBlkSpan; \
- } \
- src += tBlkSpan; \
- dstBlockStart += writeStride; \
- }
- #define ENCODE_LOOP_SPANS2 \
- } \
- src += tSpan; \
- } \
- src += sBlkSpan; \
- dst += 32; \
- } \
- src += tBlkSpan; \
- dstBlockStart += writeStride; \
- }
- static void EncodeRGBA6(u8* dst, const u8* src, EFBCopyFormat format, bool yuv)
- {
- u16 sBlkCount, tBlkCount, sBlkSize, tBlkSize;
- s32 tSpan, sBlkSpan, tBlkSpan, writeStride;
- u8 r, g, b, a;
- u32 readStride = 3;
- u8* dstBlockStart = dst;
- switch (format)
- {
- case EFBCopyFormat::R4:
- SetBlockDimensions(3, 3, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- sBlkSize /= 2;
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- RGBA_to_RGB8(src, &r, &g, &b);
- src += readStride;
- *dst = RGB8_to_I(r, g, b) & 0xf0;
- RGBA_to_RGB8(src, &r, &g, &b);
- src += readStride;
- *dst |= RGB8_to_I(r, g, b) >> 4;
- dst++;
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- u32 srcColor = *(u32*)src;
- src += readStride;
- *dst = (srcColor >> 16) & 0xf0;
- srcColor = *(u32*)src;
- src += readStride;
- *dst |= (srcColor >> 20) & 0x0f;
- dst++;
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::R8_0x1:
- case EFBCopyFormat::R8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- RGBA_to_RGB8(src, &r, &g, &b);
- src += readStride;
- *dst++ = RGB8_to_I(r, g, b);
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- u32 srcColor = *(u32*)src;
- *dst++ = Convert6To8((srcColor >> 18) & 0x3f);
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::RA4:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- RGBA_to_RGBA8(src, &r, &g, &b, &a);
- src += readStride;
- *dst++ = (a & 0xf0) | (RGB8_to_I(r, g, b) >> 4);
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- u32 srcColor = *(u32*)src;
- src += readStride;
- *dst++ = ((srcColor << 2) & 0xf0) | ((srcColor >> 20) & 0x0f);
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::RA8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- RGBA_to_RGBA8(src, &r, &g, &b, &a);
- src += readStride;
- *dst++ = a;
- *dst++ = RGB8_to_I(r, g, b);
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- u32 srcColor = *(u32*)src;
- src += readStride;
- *dst++ = Convert6To8(srcColor & 0x3f);
- *dst++ = Convert6To8((srcColor >> 18) & 0x3f);
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::RGB565:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- u32 srcColor = *(u32*)src;
- src += readStride;
- u16 val =
- ((srcColor >> 8) & 0xf800) | ((srcColor >> 7) & 0x07e0) | ((srcColor >> 7) & 0x001f);
- *(u16*)dst = Common::swap16(val);
- dst += 2;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::RGB5A3:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- u32 srcColor = *(u32*)src;
- src += readStride;
- u16 alpha = (srcColor << 9) & 0x7000;
- u16 val;
- if (alpha == 0x7000) // 555
- val = 0x8000 | ((srcColor >> 9) & 0x7c00) | ((srcColor >> 8) & 0x03e0) |
- ((srcColor >> 7) & 0x001f);
- else // 4443
- val = alpha | ((srcColor >> 12) & 0x0f00) | ((srcColor >> 10) & 0x00f0) |
- ((srcColor >> 8) & 0x000f);
- *(u16*)dst = Common::swap16(val);
- dst += 2;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::RGBA8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- RGBA_to_RGBA8(src, &dst[1], &dst[32], &dst[33], &dst[0]);
- src += readStride;
- dst += 2;
- }
- ENCODE_LOOP_SPANS2
- break;
- case EFBCopyFormat::A8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- u32 srcColor = *(u32*)src;
- *dst++ = Convert6To8(srcColor & 0x3f);
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::G8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- u32 srcColor = *(u32*)src;
- *dst++ = Convert6To8((srcColor >> 12) & 0x3f);
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::B8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- u32 srcColor = *(u32*)src;
- *dst++ = Convert6To8((srcColor >> 6) & 0x3f);
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::RG8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- u32 srcColor = *(u32*)src;
- src += readStride;
- *dst++ = Convert6To8((srcColor >> 12) & 0x3f);
- *dst++ = Convert6To8((srcColor >> 18) & 0x3f);
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::GB8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- u32 srcColor = *(u32*)src;
- src += readStride;
- *dst++ = Convert6To8((srcColor >> 6) & 0x3f);
- *dst++ = Convert6To8((srcColor >> 12) & 0x3f);
- }
- ENCODE_LOOP_SPANS
- break;
- default:
- PanicAlertFmt("Unknown texture copy format: {}\n", format);
- break;
- }
- }
- static void EncodeRGBA6halfscale(u8* dst, const u8* src, EFBCopyFormat format, bool yuv)
- {
- u16 sBlkCount, tBlkCount, sBlkSize, tBlkSize;
- s32 tSpan, sBlkSpan, tBlkSpan, writeStride;
- u8 r, g, b, a;
- u32 readStride = 6;
- u8* dstBlockStart = dst;
- switch (format)
- {
- case EFBCopyFormat::R4:
- SetBlockDimensions(3, 3, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- sBlkSize /= 2;
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_RGB8(src, &r, &g, &b);
- src += readStride;
- *dst = RGB8_to_I(r, g, b) & 0xf0;
- BoxfilterRGBA_to_RGB8(src, &r, &g, &b);
- src += readStride;
- *dst |= RGB8_to_I(r, g, b) >> 4;
- dst++;
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_x8(src, &r, 18);
- src += readStride;
- *dst = r & 0xf0;
- BoxfilterRGBA_to_x8(src, &r, 18);
- src += readStride;
- *dst |= r >> 4;
- dst++;
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::R8_0x1:
- case EFBCopyFormat::R8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_RGB8(src, &r, &g, &b);
- src += readStride;
- *dst++ = RGB8_to_I(r, g, b);
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_x8(src, &r, 18);
- *dst++ = r;
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::RA4:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_RGBA8(src, &r, &g, &b, &a);
- src += readStride;
- *dst++ = (a & 0xf0) | (RGB8_to_I(r, g, b) >> 4);
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_xx8(src, &r, &a, 18, 0);
- src += readStride;
- *dst++ = (a & 0xf0) | (r >> 4);
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::RA8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_RGBA8(src, &r, &g, &b, &a);
- src += readStride;
- *dst++ = a;
- *dst++ = RGB8_to_I(r, g, b);
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_xx8(src, &r, &a, 18, 0);
- src += readStride;
- *dst++ = a;
- *dst++ = r;
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::RGB565:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_RGB8(src, &r, &g, &b);
- src += readStride;
- u16 val = ((r << 8) & 0xf800) | ((g << 3) & 0x07e0) | ((b >> 3) & 0x001f);
- *(u16*)dst = Common::swap16(val);
- dst += 2;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::RGB5A3:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_RGBA8(src, &r, &g, &b, &a);
- src += readStride;
- u16 val;
- if (a >= 224) // 5551
- val = 0x8000 | ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f);
- else // 4443
- val = ((a << 7) & 0x7000) | ((r << 4) & 0x0f00) | (g & 0x00f0) | ((b >> 4) & 0x000f);
- *(u16*)dst = Common::swap16(val);
- dst += 2;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::RGBA8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_RGBA8(src, &dst[1], &dst[32], &dst[33], &dst[0]);
- src += readStride;
- dst += 2;
- }
- ENCODE_LOOP_SPANS2
- break;
- case EFBCopyFormat::A8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_x8(src, &a, 0);
- *dst++ = a;
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::G8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_x8(src, &g, 12);
- *dst++ = g;
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::B8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_x8(src, &b, 6);
- *dst++ = b;
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::RG8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_xx8(src, &r, &g, 18, 12);
- src += readStride;
- *dst++ = g;
- *dst++ = r;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::GB8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGBA_to_xx8(src, &g, &b, 12, 6);
- src += readStride;
- *dst++ = b;
- *dst++ = g;
- }
- ENCODE_LOOP_SPANS
- break;
- default:
- PanicAlertFmt("Unknown texture copy format: {}\n", format);
- break;
- }
- }
- static void EncodeRGB8(u8* dst, const u8* src, EFBCopyFormat format, bool yuv)
- {
- u16 sBlkCount, tBlkCount, sBlkSize, tBlkSize;
- s32 tSpan, sBlkSpan, tBlkSpan, writeStride;
- u32 readStride = 3;
- u8* dstBlockStart = dst;
- switch (format)
- {
- case EFBCopyFormat::R4:
- SetBlockDimensions(3, 3, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- sBlkSize /= 2;
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- *dst = RGB8_to_I(src[2], src[1], src[0]) & 0xf0;
- src += readStride;
- *dst |= RGB8_to_I(src[2], src[1], src[0]) >> 4;
- src += readStride;
- dst++;
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- *dst = src[2] & 0xf0;
- src += readStride;
- *dst |= src[2] >> 4;
- src += readStride;
- dst++;
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::R8_0x1:
- case EFBCopyFormat::R8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- *dst++ = RGB8_to_I(src[2], src[1], src[0]);
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- *dst++ = src[2];
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::RA4:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- *dst++ = 0xf0 | (RGB8_to_I(src[2], src[1], src[0]) >> 4);
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- *dst++ = 0xf0 | (src[2] >> 4);
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::RA8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- *dst++ = 0xff;
- *dst++ = RGB8_to_I(src[2], src[1], src[0]);
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- *dst++ = 0xff;
- *dst++ = src[2];
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::RGB565:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- u16 val = ((src[2] << 8) & 0xf800) | ((src[1] << 3) & 0x07e0) | ((src[0] >> 3) & 0x001f);
- *(u16*)dst = Common::swap16(val);
- src += readStride;
- dst += 2;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::RGB5A3:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- u16 val =
- 0x8000 | ((src[2] << 7) & 0x7c00) | ((src[1] << 2) & 0x03e0) | ((src[0] >> 3) & 0x001f);
- *(u16*)dst = Common::swap16(val);
- src += readStride;
- dst += 2;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::RGBA8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- dst[0] = 0xff;
- dst[1] = src[2];
- dst[32] = src[1];
- dst[33] = src[0];
- src += readStride;
- dst += 2;
- }
- ENCODE_LOOP_SPANS2
- break;
- case EFBCopyFormat::A8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS { *dst++ = 0xff; }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::G8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- *dst++ = src[1];
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::B8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- *dst++ = src[0];
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::RG8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- // FIXME: is this backwards?
- *dst++ = src[1];
- *dst++ = src[2];
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::GB8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- *dst++ = src[0];
- *dst++ = src[1];
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- default:
- PanicAlertFmt("Unknown texture copy format: {}\n", format);
- break;
- }
- }
- static void EncodeRGB8halfscale(u8* dst, const u8* src, EFBCopyFormat format, bool yuv)
- {
- u16 sBlkCount, tBlkCount, sBlkSize, tBlkSize;
- s32 tSpan, sBlkSpan, tBlkSpan, writeStride;
- u8 r, g, b;
- u32 readStride = 6;
- u8* dstBlockStart = dst;
- switch (format)
- {
- case EFBCopyFormat::R4:
- SetBlockDimensions(3, 3, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- sBlkSize /= 2;
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_RGB8(src, &r, &g, &b);
- *dst = RGB8_to_I(r, g, b) & 0xf0;
- src += readStride;
- BoxfilterRGB_to_RGB8(src, &r, &g, &b);
- *dst |= RGB8_to_I(r, g, b) >> 4;
- src += readStride;
- dst++;
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_x8(src, &r, 2);
- *dst = r & 0xf0;
- src += readStride;
- BoxfilterRGB_to_x8(src, &r, 2);
- *dst |= r >> 4;
- src += readStride;
- dst++;
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::R8_0x1:
- case EFBCopyFormat::R8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_RGB8(src, &r, &g, &b);
- *dst++ = RGB8_to_I(r, g, b);
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_x8(src, &r, 2);
- *dst++ = r;
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::RA4:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_RGB8(src, &r, &g, &b);
- *dst++ = 0xf0 | (RGB8_to_I(r, g, b) >> 4);
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_x8(src, &r, 2);
- *dst++ = 0xf0 | (r >> 4);
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::RA8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- if (yuv)
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_RGB8(src, &r, &g, &b);
- *dst++ = 0xff;
- *dst++ = RGB8_to_I(r, g, b);
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- }
- else
- {
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_x8(src, &r, 2);
- *dst++ = 0xff;
- *dst++ = r;
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- }
- break;
- case EFBCopyFormat::RGB565:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_RGB8(src, &r, &g, &b);
- u16 val = ((r << 8) & 0xf800) | ((g << 3) & 0x07e0) | ((b >> 3) & 0x001f);
- *(u16*)dst = Common::swap16(val);
- src += readStride;
- dst += 2;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::RGB5A3:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_RGB8(src, &r, &g, &b);
- u16 val = 0x8000 | ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f);
- *(u16*)dst = Common::swap16(val);
- src += readStride;
- dst += 2;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::RGBA8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_RGB8(src, &r, &g, &b);
- dst[0] = 0xff;
- dst[1] = r;
- dst[32] = g;
- dst[33] = b;
- src += readStride;
- dst += 2;
- }
- ENCODE_LOOP_SPANS2
- break;
- case EFBCopyFormat::A8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS { *dst++ = 0xff; }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::G8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_x8(src, &g, 1);
- *dst++ = g;
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::B8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_x8(src, &b, 0);
- *dst++ = b;
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::RG8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_xx8(src, &r, &g, 2, 1);
- *dst++ = g;
- *dst++ = r;
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::GB8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_xx8(src, &g, &b, 1, 0);
- *dst++ = b;
- *dst++ = g;
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- default:
- PanicAlertFmt("Unknown texture copy format: {}\n", format);
- break;
- }
- }
- static void EncodeZ24(u8* dst, const u8* src, EFBCopyFormat format)
- {
- u16 sBlkCount, tBlkCount, sBlkSize, tBlkSize;
- s32 tSpan, sBlkSpan, tBlkSpan, writeStride;
- u32 readStride = 3;
- u8* dstBlockStart = dst;
- switch (format)
- {
- case EFBCopyFormat::R8_0x1:
- case EFBCopyFormat::R8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- *dst++ = src[2];
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- // FIXME: handle RA8?
- case EFBCopyFormat::RGBA8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- dst[0] = 0xff;
- dst[1] = src[2];
- dst[32] = src[1];
- dst[33] = src[0];
- src += readStride;
- dst += 2;
- }
- ENCODE_LOOP_SPANS2
- break;
- case EFBCopyFormat::R4:
- SetBlockDimensions(3, 3, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- sBlkSize /= 2;
- ENCODE_LOOP_BLOCKS
- {
- *dst = src[2] & 0xf0;
- src += readStride;
- *dst |= src[2] >> 4;
- src += readStride;
- dst++;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::G8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- *dst++ = src[1];
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::B8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- *dst++ = src[0];
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::RG8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- // FIXME: should these be reversed?
- *dst++ = src[1];
- *dst++ = src[2];
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::GB8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- *dst++ = src[0];
- *dst++ = src[1];
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- default:
- PanicAlertFmt("Unknown texture copy format: {}\n", format);
- break;
- }
- }
- static void EncodeZ24halfscale(u8* dst, const u8* src, EFBCopyFormat format)
- {
- u16 sBlkCount, tBlkCount, sBlkSize, tBlkSize;
- s32 tSpan, sBlkSpan, tBlkSpan, writeStride;
- u32 readStride = 6;
- u8 r, g, b;
- u8* dstBlockStart = dst;
- switch (format)
- {
- case EFBCopyFormat::R8_0x1:
- case EFBCopyFormat::R8:
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_x8(src, &b, 2);
- *dst++ = b;
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- // FIXME: handle RA8?
- case EFBCopyFormat::RGBA8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_RGB8(src, &dst[33], &dst[32], &dst[1]);
- dst[0] = 255;
- src += readStride;
- dst += 2;
- }
- ENCODE_LOOP_SPANS2
- break;
- case EFBCopyFormat::R4: // Z4
- SetBlockDimensions(3, 3, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- sBlkSize /= 2;
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_x8(src, &b, 2);
- *dst = b & 0xf0;
- src += readStride;
- BoxfilterRGB_to_x8(src, &b, 2);
- *dst |= b >> 4;
- src += readStride;
- dst++;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::G8: // Z8M
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_x8(src, &g, 1);
- *dst++ = g;
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::B8: // Z8L
- SetBlockDimensions(3, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_x8(src, &r, 0);
- *dst++ = r;
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::RG8: // RG8
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_xx8(src, &r, &g, 0, 1);
- *dst++ = g;
- *dst++ = r;
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- case EFBCopyFormat::GB8:
- SetBlockDimensions(2, 2, &sBlkCount, &tBlkCount, &sBlkSize, &tBlkSize);
- SetSpans(sBlkSize, tBlkSize, &tSpan, &sBlkSpan, &tBlkSpan, &writeStride);
- ENCODE_LOOP_BLOCKS
- {
- BoxfilterRGB_to_xx8(src, &g, &b, 1, 2);
- // FIXME: is this backwards?
- *dst++ = b;
- *dst++ = g;
- src += readStride;
- }
- ENCODE_LOOP_SPANS
- break;
- default:
- PanicAlertFmt("Unknown texture copy format: {}\n", format);
- break;
- }
- }
- namespace
- {
- void EncodeEfbCopy(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
- u32 num_blocks_y, u32 memory_stride, const MathUtil::Rectangle<int>& src_rect,
- bool scale_by_half)
- {
- const u8* src = EfbInterface::GetPixelPointer(src_rect.left, src_rect.top, params.depth);
- if (scale_by_half)
- {
- switch (params.efb_format)
- {
- case PixelFormat::RGBA6_Z24:
- EncodeRGBA6halfscale(dst, src, params.copy_format, params.yuv);
- break;
- case PixelFormat::RGB8_Z24:
- EncodeRGB8halfscale(dst, src, params.copy_format, params.yuv);
- break;
- case PixelFormat::RGB565_Z16:
- EncodeRGB8halfscale(dst, src, params.copy_format, params.yuv);
- break;
- case PixelFormat::Z24:
- EncodeZ24halfscale(dst, src, params.copy_format);
- break;
- default:
- break;
- }
- }
- else
- {
- switch (params.efb_format)
- {
- case PixelFormat::RGBA6_Z24:
- EncodeRGBA6(dst, src, params.copy_format, params.yuv);
- break;
- case PixelFormat::RGB8_Z24:
- EncodeRGB8(dst, src, params.copy_format, params.yuv);
- break;
- case PixelFormat::RGB565_Z16:
- EncodeRGB8(dst, src, params.copy_format, params.yuv);
- break;
- case PixelFormat::Z24:
- EncodeZ24(dst, src, params.copy_format);
- break;
- default:
- break;
- }
- }
- }
- } // namespace
- void Encode(AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width,
- u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
- const MathUtil::Rectangle<int>& src_rect, bool scale_by_half, float y_scale,
- float gamma)
- {
- // HACK: Override the memory stride for this staging texture with new copy stride.
- // This is required because the texture encoder assumes that we're writing directly to memory,
- // and each row is tightly packed with no padding, whereas our encoding abstract texture has
- // a width of 2560. When we copy the texture back later on, it'll use the tightly packed stride.
- ASSERT(memory_stride <= (dst->GetConfig().width * dst->GetTexelSize()));
- static_cast<SW::SWStagingTexture*>(dst)->SetMapStride(memory_stride);
- if (params.copy_format == EFBCopyFormat::XFB)
- {
- EfbInterface::EncodeXFB(reinterpret_cast<u8*>(dst->GetMappedPointer()), native_width, src_rect,
- y_scale, gamma);
- }
- else
- {
- EncodeEfbCopy(reinterpret_cast<u8*>(dst->GetMappedPointer()), params, native_width,
- bytes_per_row, num_blocks_y, memory_stride, src_rect, scale_by_half);
- }
- }
- } // namespace TextureEncoder
|