mirror of
				https://github.com/dolphin-emu/dolphin.git
				synced 2025-10-25 17:39:09 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			128 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2016 Dolphin Emulator Project
 | |
| // Licensed under GPLv2+
 | |
| // Refer to the license.txt file included.
 | |
| 
 | |
| #include "VideoCommon/RenderState.h"
 | |
| 
 | |
| // If the framebuffer format has no alpha channel, it is assumed to
 | |
| // ONE on blending. As the backends may emulate this framebuffer
 | |
| // configuration with an alpha channel, we just drop all references
 | |
| // to the destination alpha channel.
 | |
| static BlendMode::BlendFactor RemoveDstAlphaUsage(BlendMode::BlendFactor factor)
 | |
| {
 | |
|   switch (factor)
 | |
|   {
 | |
|   case BlendMode::DSTALPHA:
 | |
|     return BlendMode::ONE;
 | |
|   case BlendMode::INVDSTALPHA:
 | |
|     return BlendMode::ZERO;
 | |
|   default:
 | |
|     return factor;
 | |
|   }
 | |
| }
 | |
| 
 | |
| // We separate the blending parameter for rgb and alpha. For blending
 | |
| // the alpha component, CLR and ALPHA are indentical. So just always
 | |
| // use ALPHA as this makes it easier for the backends to use the second
 | |
| // alpha value of dual source blending.
 | |
| static BlendMode::BlendFactor RemoveSrcColorUsage(BlendMode::BlendFactor factor)
 | |
| {
 | |
|   switch (factor)
 | |
|   {
 | |
|   case BlendMode::SRCCLR:
 | |
|     return BlendMode::SRCALPHA;
 | |
|   case BlendMode::INVSRCCLR:
 | |
|     return BlendMode::INVSRCALPHA;
 | |
|   default:
 | |
|     return factor;
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Same as RemoveSrcColorUsage, but because of the overlapping enum,
 | |
| // this must be written as another function.
 | |
| static BlendMode::BlendFactor RemoveDstColorUsage(BlendMode::BlendFactor factor)
 | |
| {
 | |
|   switch (factor)
 | |
|   {
 | |
|   case BlendMode::DSTCLR:
 | |
|     return BlendMode::DSTALPHA;
 | |
|   case BlendMode::INVDSTCLR:
 | |
|     return BlendMode::INVDSTALPHA;
 | |
|   default:
 | |
|     return factor;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void BlendingState::Generate(const BPMemory& bp)
 | |
| {
 | |
|   // Start with everything disabled.
 | |
|   hex = 0;
 | |
| 
 | |
|   bool target_has_alpha = bp.zcontrol.pixel_format == PEControl::RGBA6_Z24;
 | |
|   bool alpha_test_may_success = bp.alpha_test.TestResult() != AlphaTest::FAIL;
 | |
| 
 | |
|   dither = bp.blendmode.dither;
 | |
|   colorupdate = bp.blendmode.colorupdate && alpha_test_may_success;
 | |
|   alphaupdate = bp.blendmode.alphaupdate && target_has_alpha && alpha_test_may_success;
 | |
|   dstalpha = bp.dstalpha.enable && alphaupdate;
 | |
| 
 | |
|   // The subtract bit has the highest priority
 | |
|   if (bp.blendmode.subtract)
 | |
|   {
 | |
|     blendenable = true;
 | |
|     subtractAlpha = subtract = true;
 | |
|     srcfactoralpha = srcfactor = BlendMode::ONE;
 | |
|     dstfactoralpha = dstfactor = BlendMode::ONE;
 | |
| 
 | |
|     if (dstalpha)
 | |
|     {
 | |
|       subtractAlpha = false;
 | |
|       srcfactoralpha = BlendMode::ONE;
 | |
|       dstfactoralpha = BlendMode::ZERO;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // The blendenable bit has the middle priority
 | |
|   else if (bp.blendmode.blendenable)
 | |
|   {
 | |
|     blendenable = true;
 | |
|     srcfactor = bp.blendmode.srcfactor;
 | |
|     dstfactor = bp.blendmode.dstfactor;
 | |
|     if (!target_has_alpha)
 | |
|     {
 | |
|       // uses ONE instead of DSTALPHA
 | |
|       srcfactor = RemoveDstAlphaUsage(srcfactor);
 | |
|       dstfactor = RemoveDstAlphaUsage(dstfactor);
 | |
|     }
 | |
|     // replaces SRCCLR with SRCALPHA
 | |
|     srcfactoralpha = RemoveSrcColorUsage(srcfactor);
 | |
|     dstfactoralpha = RemoveDstColorUsage(dstfactor);
 | |
| 
 | |
|     if (dstalpha)
 | |
|     {
 | |
|       srcfactoralpha = BlendMode::ONE;
 | |
|       dstfactoralpha = BlendMode::ZERO;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // The logicop bit has the lowest priority
 | |
|   else if (bp.blendmode.logicopenable)
 | |
|   {
 | |
|     if (bp.blendmode.logicmode == BlendMode::NOOP)
 | |
|     {
 | |
|       // Fast path for Kirby's Return to Dreamland, they use it with dstAlpha.
 | |
|       colorupdate = false;
 | |
|       alphaupdate = alphaupdate && dstalpha;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       logicopenable = true;
 | |
|       logicmode = bp.blendmode.logicmode;
 | |
| 
 | |
|       if (dstalpha)
 | |
|       {
 | |
|         // TODO: Not supported by backends.
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 |