1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501 |
- // 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/CommonTypes.h"
- #include "Common/MsgHandler.h"
- #include "Common/Swap.h"
- #include "VideoBackends/Software/SWEfbInterface.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
|