diff options
| author | Jasper St. Pierre <jstpierre@mecheye.net> | 2013-12-07 15:14:29 -0500 |
|---|---|---|
| committer | Jasper St. Pierre <jstpierre@mecheye.net> | 2013-12-31 14:03:19 -0500 |
| commit | 34692ab826abc8f8faa61bdb2280b742424528f1 (patch) | |
| tree | b0eedc645badbea316ff59c125eaf808b28777ec /Source/Core/VideoBackends/Software/EfbInterface.cpp | |
| parent | 43e618682e8093602fc83dfa902ee7ae3fd3a4f6 (diff) | |
Remove unnecessary Src/ folders
Diffstat (limited to 'Source/Core/VideoBackends/Software/EfbInterface.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/Software/EfbInterface.cpp | 549 |
1 files changed, 549 insertions, 0 deletions
diff --git a/Source/Core/VideoBackends/Software/EfbInterface.cpp b/Source/Core/VideoBackends/Software/EfbInterface.cpp new file mode 100644 index 0000000000..f13f6a47b1 --- /dev/null +++ b/Source/Core/VideoBackends/Software/EfbInterface.cpp @@ -0,0 +1,549 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "Common.h" + +#include "EfbInterface.h" +#include "BPMemLoader.h" +#include "LookUpTables.h" +#include "SWPixelEngine.h" + + +u8 efb[EFB_WIDTH*EFB_HEIGHT*6]; + + +namespace EfbInterface +{ + + u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; + + inline u32 GetColorOffset(u16 x, u16 y) + { + return (x + y * EFB_WIDTH) * 3; + } + + inline u32 GetDepthOffset(u16 x, u16 y) + { + return (x + y * EFB_WIDTH) * 3 + DEPTH_BUFFER_START; + } + + void DoState(PointerWrap &p) + { + p.DoArray(efb, EFB_WIDTH*EFB_HEIGHT*6); + p.DoArray(efbColorTexture, EFB_WIDTH*EFB_HEIGHT*4); + } + + void SetPixelAlphaOnly(u32 offset, u8 a) + { + switch (bpmem.zcontrol.pixel_format) + { + case PIXELFMT_RGB8_Z24: + case PIXELFMT_Z24: + case PIXELFMT_RGB565_Z16: + // do nothing + break; + case PIXELFMT_RGBA6_Z24: + { + u32 a32 = a; + u32 *dst = (u32*)&efb[offset]; + u32 val = *dst & 0xffffffc0; + val |= (a32 >> 2) & 0x0000003f; + *dst = val; + } + break; + default: + ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format); + } + } + + void SetPixelColorOnly(u32 offset, u8 *rgb) + { + switch (bpmem.zcontrol.pixel_format) + { + case PIXELFMT_RGB8_Z24: + case PIXELFMT_Z24: + { + u32 src = *(u32*)rgb; + u32 *dst = (u32*)&efb[offset]; + u32 val = *dst & 0xff000000; + val |= src >> 8; + *dst = val; + } + break; + case PIXELFMT_RGBA6_Z24: + { + u32 src = *(u32*)rgb; + u32 *dst = (u32*)&efb[offset]; + u32 val = *dst & 0xff00003f; + val |= (src >> 4) & 0x00000fc0; // blue + val |= (src >> 6) & 0x0003f000; // green + val |= (src >> 8) & 0x00fc0000; // red + *dst = val; + } + break; + case PIXELFMT_RGB565_Z16: + { + INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet"); + u32 src = *(u32*)rgb; + u32 *dst = (u32*)&efb[offset]; + u32 val = *dst & 0xff000000; + val |= src >> 8; + *dst = val; + } + break; + default: + ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format); + } + } + + void SetPixelAlphaColor(u32 offset, u8 *color) + { + switch (bpmem.zcontrol.pixel_format) + { + case PIXELFMT_RGB8_Z24: + case PIXELFMT_Z24: + { + u32 src = *(u32*)color; + u32 *dst = (u32*)&efb[offset]; + u32 val = *dst & 0xff000000; + val |= src >> 8; + *dst = val; + } + break; + case PIXELFMT_RGBA6_Z24: + { + u32 src = *(u32*)color; + u32 *dst = (u32*)&efb[offset]; + u32 val = *dst & 0xff000000; + val |= (src >> 2) & 0x0000003f; // alpha + val |= (src >> 4) & 0x00000fc0; // blue + val |= (src >> 6) & 0x0003f000; // green + val |= (src >> 8) & 0x00fc0000; // red + *dst = val; + } + break; + case PIXELFMT_RGB565_Z16: + { + INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet"); + u32 src = *(u32*)color; + u32 *dst = (u32*)&efb[offset]; + u32 val = *dst & 0xff000000; + val |= src >> 8; + *dst = val; + } + break; + default: + ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format); + } + } + + void GetPixelColor(u32 offset, u8 *color) + { + switch (bpmem.zcontrol.pixel_format) + { + case PIXELFMT_RGB8_Z24: + case PIXELFMT_Z24: + { + u32 src = *(u32*)&efb[offset]; + u32 *dst = (u32*)color; + u32 val = 0xff | ((src & 0x00ffffff) << 8); + *dst = val; + } + break; + case PIXELFMT_RGBA6_Z24: + { + u32 src = *(u32*)&efb[offset]; + color[ALP_C] = Convert6To8(src & 0x3f); + color[BLU_C] = Convert6To8((src >> 6) & 0x3f); + color[GRN_C] = Convert6To8((src >> 12) & 0x3f); + color[RED_C] = Convert6To8((src >> 18) & 0x3f); + } + break; + case PIXELFMT_RGB565_Z16: + { + INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet"); + u32 src = *(u32*)&efb[offset]; + u32 *dst = (u32*)color; + u32 val = 0xff | ((src & 0x00ffffff) << 8); + *dst = val; + } + break; + default: + ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format); + } + } + + void SetPixelDepth(u32 offset, u32 depth) + { + switch (bpmem.zcontrol.pixel_format) + { + case PIXELFMT_RGB8_Z24: + case PIXELFMT_RGBA6_Z24: + case PIXELFMT_Z24: + { + u32 *dst = (u32*)&efb[offset]; + u32 val = *dst & 0xff000000; + val |= depth & 0x00ffffff; + *dst = val; + } + break; + case PIXELFMT_RGB565_Z16: + { + INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet"); + u32 *dst = (u32*)&efb[offset]; + u32 val = *dst & 0xff000000; + val |= depth & 0x00ffffff; + *dst = val; + } + break; + default: + ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format); + } + } + + u32 GetPixelDepth(u32 offset) + { + u32 depth = 0; + + switch (bpmem.zcontrol.pixel_format) + { + case PIXELFMT_RGB8_Z24: + case PIXELFMT_RGBA6_Z24: + case PIXELFMT_Z24: + { + depth = (*(u32*)&efb[offset]) & 0x00ffffff; + } + break; + case PIXELFMT_RGB565_Z16: + { + INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet"); + depth = (*(u32*)&efb[offset]) & 0x00ffffff; + } + break; + default: + ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format); + } + + return depth; + } + + u32 GetSourceFactor(u8 *srcClr, u8 *dstClr, int mode) + { + switch (mode) { + case 0: // zero + return 0; + case 1: // one + return 0xffffffff; + case 2: // dstclr + return *(u32*)dstClr; + case 3: // invdstclr + return 0xffffffff - *(u32*)dstClr; + case 4: // srcalpha + { + u8 alpha = srcClr[ALP_C]; + u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha; + return factor; + } + case 5: // invsrcalpha + { + u8 alpha = 0xff - srcClr[ALP_C]; + u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha; + return factor; + } + case 6: // dstalpha + { + u8 alpha = dstClr[ALP_C]; + u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha; + return factor; + } + case 7: // invdstalpha + { + u8 alpha = 0xff - dstClr[ALP_C]; + u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha; + return factor; + } + } + + return 0; + } + + u32 GetDestinationFactor(u8 *srcClr, u8 *dstClr, int mode) + { + switch (mode) { + case 0: // zero + return 0; + case 1: // one + return 0xffffffff; + case 2: // srcclr + return *(u32*)srcClr; + case 3: // invsrcclr + return 0xffffffff - *(u32*)srcClr; + case 4: // srcalpha + { + u8 alpha = srcClr[ALP_C]; + u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha; + return factor; + } + case 5: // invsrcalpha + { + u8 alpha = 0xff - srcClr[ALP_C]; + u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha; + return factor; + } + case 6: // dstalpha + { + u8 alpha = dstClr[ALP_C] & 0xff; + u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha; + return factor; + } + case 7: // invdstalpha + { + u8 alpha = 0xff - dstClr[ALP_C]; + u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha; + return factor; + } + } + + return 0; + } + + void BlendColor(u8 *srcClr, u8 *dstClr) + { + u32 srcFactor = GetSourceFactor(srcClr, dstClr, bpmem.blendmode.srcfactor); + u32 dstFactor = GetDestinationFactor(srcClr, dstClr, bpmem.blendmode.dstfactor); + + for (int i = 0; i < 4; i++) + { + // add MSB of factors to make their range 0 -> 256 + u32 sf = (srcFactor & 0xff); + sf += sf >> 7; + + u32 df = (dstFactor & 0xff); + df += df >> 7; + + u32 color = (srcClr[i] * sf + dstClr[i] * df) >> 8; + dstClr[i] = (color>255)?255:color; + + dstFactor >>= 8; + srcFactor >>= 8; + } + } + + void LogicBlend(u32 srcClr, u32 &dstClr, int op) + { + switch (op) + { + case 0: // clear + dstClr = 0; + break; + case 1: // and + dstClr = srcClr & dstClr; + break; + case 2: // revand + dstClr = srcClr & (~dstClr); + break; + case 3: // copy + dstClr = srcClr; + break; + case 4: // invand + dstClr = (~srcClr) & dstClr; + break; + case 5: // noop + // Do nothing + break; + case 6: // xor + dstClr = srcClr ^ dstClr; + break; + case 7: // or + dstClr = srcClr | dstClr; + break; + case 8: // nor + dstClr = ~(srcClr | dstClr); + break; + case 9: // equiv + dstClr = ~(srcClr ^ dstClr); + break; + case 10: // inv + dstClr = ~dstClr; + break; + case 11: // revor + dstClr = srcClr | (~dstClr); + break; + case 12: // invcopy + dstClr = ~srcClr; + break; + case 13: // invor + dstClr = (~srcClr) | dstClr; + break; + case 14: // nand + dstClr = ~(srcClr & dstClr); + break; + case 15: // set + dstClr = 0xffffffff; + break; + } + } + + void SubtractBlend(u8 *srcClr, u8 *dstClr) + { + for (int i = 0; i < 4; i++) + { + int c = (int)dstClr[i] - (int)srcClr[i]; + dstClr[i] = (c < 0)?0:c; + } + } + + void BlendTev(u16 x, u16 y, u8 *color) + { + u32 dstClr; + u32 offset = GetColorOffset(x, y); + + u8 *dstClrPtr = (u8*)&dstClr; + + GetPixelColor(offset, dstClrPtr); + + if (bpmem.blendmode.blendenable) + { + if (bpmem.blendmode.subtract) + SubtractBlend(color, dstClrPtr); + else + BlendColor(color, dstClrPtr); + } + else if (bpmem.blendmode.logicopenable) + { + LogicBlend(*((u32*)color), dstClr, bpmem.blendmode.logicmode); + } + else + { + dstClrPtr = color; + } + + if (bpmem.dstalpha.enable) + dstClrPtr[ALP_C] = bpmem.dstalpha.alpha; + + if (bpmem.blendmode.colorupdate) + { + if (bpmem.blendmode.alphaupdate) + SetPixelAlphaColor(offset, dstClrPtr); + else + SetPixelColorOnly(offset, dstClrPtr); + } + else if (bpmem.blendmode.alphaupdate) + { + SetPixelAlphaOnly(offset, dstClrPtr[ALP_C]); + } + + // branchless bounding box update + SWPixelEngine::pereg.boxLeft = SWPixelEngine::pereg.boxLeft>x?x:SWPixelEngine::pereg.boxLeft; + SWPixelEngine::pereg.boxRight = SWPixelEngine::pereg.boxRight<x?x:SWPixelEngine::pereg.boxRight; + SWPixelEngine::pereg.boxTop = SWPixelEngine::pereg.boxTop>y?y:SWPixelEngine::pereg.boxTop; + SWPixelEngine::pereg.boxBottom = SWPixelEngine::pereg.boxBottom<y?y:SWPixelEngine::pereg.boxBottom; + } + + void SetColor(u16 x, u16 y, u8 *color) + { + u32 offset = GetColorOffset(x, y); + if (bpmem.blendmode.colorupdate) + { + if (bpmem.blendmode.alphaupdate) + SetPixelAlphaColor(offset, color); + else + SetPixelColorOnly(offset, color); + } + else if (bpmem.blendmode.alphaupdate) + { + SetPixelAlphaOnly(offset, color[ALP_C]); + } + } + + void SetDepth(u16 x, u16 y, u32 depth) + { + if (bpmem.zmode.updateenable) + SetPixelDepth(GetDepthOffset(x, y), depth); + } + + void GetColor(u16 x, u16 y, u8 *color) + { + u32 offset = GetColorOffset(x, y); + GetPixelColor(offset, color); + } + + u32 GetDepth(u16 x, u16 y) + { + u32 offset = GetDepthOffset(x, y); + return GetPixelDepth(offset); + } + + u8 *GetPixelPointer(u16 x, u16 y, bool depth) + { + if (depth) + return &efb[GetDepthOffset(x, y)]; + return &efb[GetColorOffset(x, y)]; + } + + void UpdateColorTexture() + { + u32 color; + u8* colorPtr = (u8*)&color; + u32* texturePtr = (u32*)efbColorTexture; + u32 textureAddress = 0; + u32 efbOffset = 0; + + for (u16 y = 0; y < EFB_HEIGHT; y++) + { + for (u16 x = 0; x < EFB_WIDTH; x++) + { + GetPixelColor(efbOffset, colorPtr); + efbOffset += 3; + texturePtr[textureAddress++] = Common::swap32(color); // ABGR->RGBA + } + } + } + + bool ZCompare(u16 x, u16 y, u32 z) + { + u32 offset = GetDepthOffset(x, y); + u32 depth = GetPixelDepth(offset); + + bool pass; + + switch (bpmem.zmode.func) + { + case COMPARE_NEVER: + pass = false; + break; + case COMPARE_LESS: + pass = z < depth; + break; + case COMPARE_EQUAL: + pass = z == depth; + break; + case COMPARE_LEQUAL: + pass = z <= depth; + break; + case COMPARE_GREATER: + pass = z > depth; + break; + case COMPARE_NEQUAL: + pass = z != depth; + break; + case COMPARE_GEQUAL: + pass = z >= depth; + break; + case COMPARE_ALWAYS: + pass = true; + break; + default: + pass = false; + ERROR_LOG(VIDEO, "Bad Z compare mode %i", bpmem.zmode.func); + } + + if (pass && bpmem.zmode.updateenable) + { + SetPixelDepth(offset, z); + } + + return pass; + } +} |
