summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/video/rdpblend.cpp
blob: 7e20b68aa6443674e30999619ce8ce60c348d329 (plain) (tree)
1
2
3
4
5
6
7
8
9

                               





                                                                               
                 

                                                                            



                                                                               



                         
                              
 
















                                                                   
 



                                                          

                                                                                                     

                 
 
 
                                                                  
 

                                         
 
                                                                  









                                           

 
                                                                                         
 



                                           
                                                                                                            




                            
 
                                                                                      
 
                                                       



                                     
 
                       
                                                                                                 

                       
                                                                                           



                                     

 
                                                                                                                                                                                   
 

                                                                                                                



                                              
                                                                      



                    
                                                                                                                                                                                 
 

                                                                                                                



                                              

                                                                    
                         

                             
                                                                                                                                
 


                    
                                                                                                                                                                                 
 
                                                                                                                
 



                                              
                                                                      



                    
                                                                                                                                                                               
 
                                                                                                                
 



                                              

                                                                    
                         

                             
                                                                                                                                



                    
                                                                                                                                                                                 
 

                                                                                                                





                                              
                                                                                           



                    
                                                                                                                                                                               
 

                                                                                                                
 




                                              

                                                                                 
 
                       

                           
                                                                                                                          



                    
                                                                                                                                                                               
 
                                                                                                                





                                              
                                                                                           



                    
                                                                                                                                                                             
 
                                                                                                                
 




                                              

                                                                                 
 
                       

                           
                                                                                                                          


                    
 
                                                                                                                                                                                             
 

                                                                                                                





                                              
                                                                                                   
                                                                               
                                                                               
 
                                                                      
 

                    
 
                                                                                                                                                                                           
 

                                                                                                                
 




                                              
                                                                                                            
                                                                               
                                                                               
 
                                                                    
                         

                             
                                                                                                                                
 
                    
 
 
                                                                                                                                                                                           
 
                                                                                                                





                                              
                                                                                                   
                                                                               
                                                                               
 
                                                                      


                    
 
                                                                                                                                                                                         
 
                                                                                                                
 




                                              
                                                                                                   
                                                                               
                                                                               
 
                                                                    
                         

                             
                                                                                                                                
 

                    
 
                                                                                                                                                                                           
 

                                                                                                                





                                              
                                                                                                   
                                                                               
                                                                               
 
                                                                                           

                    

 
                                                                                                                                                                                         
 

                                                                                                       





                                              
                                                                                                   

                                                                               
 

                                                                                 
 
                       

                           
                                                                                                                          
 

                    
 
                                                                                                                                                                                         
 
                                                                                                       
 



                                              
 
                                                                                                   
                                                                               
                                                                               
 
                                                                                           
 
                    

 
                                                                                                                                                                                       
 
                                                                                                       
 



                                              
 
                                                                                                   
                                                                               
                                                                               
 

                                                                                 
 
                       

                           
                                                                                                                          

                    

 
                                                                                                                                                                       
 
                                                                     
         
                                                                        


            
                                                                                                               
                                                                 
         

 
                                                                                                                                      
 





                                                                                                         
 

                                                                       
 


                                                                            
 
                        
                                         
                            
                                                       
 
                               
                                              
         
                                                                         

                               


                                                                


                    
                                                      


                 

                      
 
 
                                                                     
 




                         
 
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************


    SGI/Nintendo Reality Display Processor Blend Unit (BL)
    -------------------

    by Ryan Holtz
    based on initial C code by Ville Linde
    contains additional improvements from angrylion, Ziggy, Gonetz and Orkin


******************************************************************************/

#include "emu.h"
#include "includes/n64.h"
#include "video/n64.h"

n64_blender_t::n64_blender_t()
{
	blend1[0] = &n64_blender_t::cycle1_noblend_noacvg_nodither;
	blend1[1] = &n64_blender_t::cycle1_noblend_noacvg_dither;
	blend1[2] = &n64_blender_t::cycle1_noblend_acvg_nodither;
	blend1[3] = &n64_blender_t::cycle1_noblend_acvg_dither;
	blend1[4] = &n64_blender_t::cycle1_blend_noacvg_nodither;
	blend1[5] = &n64_blender_t::cycle1_blend_noacvg_dither;
	blend1[6] = &n64_blender_t::cycle1_blend_acvg_nodither;
	blend1[7] = &n64_blender_t::cycle1_blend_acvg_dither;

	blend2[0] = &n64_blender_t::cycle2_noblend_noacvg_nodither;
	blend2[1] = &n64_blender_t::cycle2_noblend_noacvg_dither;
	blend2[2] = &n64_blender_t::cycle2_noblend_acvg_nodither;
	blend2[3] = &n64_blender_t::cycle2_noblend_acvg_dither;
	blend2[4] = &n64_blender_t::cycle2_blend_noacvg_nodither;
	blend2[5] = &n64_blender_t::cycle2_blend_noacvg_dither;
	blend2[6] = &n64_blender_t::cycle2_blend_acvg_nodither;
	blend2[7] = &n64_blender_t::cycle2_blend_acvg_dither;

	for (int value = 0; value < 256; value++)
	{
		for (int dither = 0; dither < 8; dither++)
		{
			m_color_dither[(value << 3) | dither] = (uint8_t)dither_color(value, dither);
			m_alpha_dither[(value << 3) | dither] = (uint8_t)dither_alpha(value, dither);
		}
	}
}

int32_t n64_blender_t::dither_alpha(int32_t alpha, int32_t dither)
{
	return min(alpha + dither, 0xff);
}

int32_t n64_blender_t::dither_color(int32_t color, int32_t dither)
{
	if ((color & 7) > dither)
	{
		color = (color & 0xf8) + 8;
		if (color > 247)
		{
			color = 255;
		}
	}
	return color;
}

bool n64_blender_t::test_for_reject(rdp_span_aux* userdata, const rdp_poly_state& object)
{
	if (alpha_reject(userdata, object))
	{
		return true;
	}
	if (object.m_other_modes.antialias_en ? !userdata->m_current_pix_cvg : !userdata->m_current_cvg_bit)
	{
		return true;
	}
	return false;
}

bool n64_blender_t::alpha_reject(rdp_span_aux* userdata, const rdp_poly_state& object)
{
	switch (object.m_other_modes.alpha_dither_mode)
	{
		case 0:
		case 1:
			return false;

		case 2:
			return userdata->m_pixel_color.get_a() < userdata->m_blend_color.get_a();

		case 3:
			return userdata->m_pixel_color.get_a() < (machine().rand() & 0xff);

		default:
			return false;
	}
}

bool n64_blender_t::cycle1_noblend_noacvg_nodither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_pixel_color.set_a(m_alpha_dither[((uint8_t)userdata->m_pixel_color.get_a() << 3) | adseed]);
	userdata->m_shade_color.set_a(m_alpha_dither[((uint8_t)userdata->m_shade_color.get_a() << 3) | adseed]);
	if (test_for_reject(userdata, object))
	{
		return false;
	}
	blended_pixel.set(*userdata->m_color_inputs.blender1a_rgb[0]);

	return true;
}

bool n64_blender_t::cycle1_noblend_noacvg_dither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_pixel_color.set_a(m_alpha_dither[((uint8_t)userdata->m_pixel_color.get_a() << 3) | adseed]);
	userdata->m_shade_color.set_a(m_alpha_dither[((uint8_t)userdata->m_shade_color.get_a() << 3) | adseed]);
	if (test_for_reject(userdata, object))
	{
		return false;
	}

	rgbaint_t index(*userdata->m_color_inputs.blender1a_rgb[0]);
	index.shl_imm(3);
	index.or_imm(dith);
	index.and_imm(0x7ff);
	blended_pixel.set(0, m_color_dither[index.get_r32()], m_color_dither[index.get_g32()], m_color_dither[index.get_b32()]);

	return true;
}

bool n64_blender_t::cycle1_noblend_acvg_nodither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_shade_color.set_a(m_alpha_dither[((uint8_t)userdata->m_shade_color.get_a() << 3) | adseed]);

	if (test_for_reject(userdata, object))
	{
		return false;
	}
	blended_pixel.set(*userdata->m_color_inputs.blender1a_rgb[0]);

	return true;
}

bool n64_blender_t::cycle1_noblend_acvg_dither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_shade_color.set_a(m_alpha_dither[((uint8_t)userdata->m_shade_color.get_a() << 3) | adseed]);

	if (test_for_reject(userdata, object))
	{
		return false;
	}

	rgbaint_t index(*userdata->m_color_inputs.blender1a_rgb[0]);
	index.shl_imm(3);
	index.or_imm(dith);
	index.and_imm(0x7ff);
	blended_pixel.set(0, m_color_dither[index.get_r32()], m_color_dither[index.get_g32()], m_color_dither[index.get_b32()]);

	return true;
}

bool n64_blender_t::cycle1_blend_noacvg_nodither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_pixel_color.set_a(m_alpha_dither[((uint8_t)userdata->m_pixel_color.get_a() << 3) | adseed]);
	userdata->m_shade_color.set_a(m_alpha_dither[((uint8_t)userdata->m_shade_color.get_a() << 3) | adseed]);

	if (test_for_reject(userdata, object))
	{
		return false;
	}

	blend_with_partial_reject(blended_pixel, 0, partialreject, sel0, userdata, object);

	return true;
}

bool n64_blender_t::cycle1_blend_noacvg_dither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_pixel_color.set_a(m_alpha_dither[((uint8_t)userdata->m_pixel_color.get_a() << 3) | adseed]);
	userdata->m_shade_color.set_a(m_alpha_dither[((uint8_t)userdata->m_shade_color.get_a() << 3) | adseed]);

	if (test_for_reject(userdata, object))
	{
		return false;
	}

	color_t rgb;
	blend_with_partial_reject(rgb, 0, partialreject, sel0, userdata, object);

	rgb.shl_imm(3);
	rgb.or_imm(dith);
	rgb.and_imm(0x7ff);
	blended_pixel.set(0, m_color_dither[rgb.get_r32()], m_color_dither[rgb.get_g32()], m_color_dither[rgb.get_b32()]);

	return true;
}

bool n64_blender_t::cycle1_blend_acvg_nodither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_shade_color.set_a(m_alpha_dither[((uint8_t)userdata->m_shade_color.get_a() << 3) | adseed]);

	if (test_for_reject(userdata, object))
	{
		return false;
	}

	blend_with_partial_reject(blended_pixel, 0, partialreject, sel0, userdata, object);

	return true;
}

bool n64_blender_t::cycle1_blend_acvg_dither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_shade_color.set_a(m_alpha_dither[((uint8_t)userdata->m_shade_color.get_a() << 3) | adseed]);

	if (test_for_reject(userdata, object))
	{
		return false;
	}

	color_t rgb;
	blend_with_partial_reject(rgb, 0, partialreject, sel0, userdata, object);

	rgb.shl_imm(3);
	rgb.or_imm(dith);
	rgb.and_imm(0x7ff);
	blended_pixel.set(0, m_color_dither[rgb.get_r32()], m_color_dither[rgb.get_g32()], m_color_dither[rgb.get_b32()]);

	return true;
}

bool n64_blender_t::cycle2_noblend_noacvg_nodither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, int sel1, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_pixel_color.set_a(m_alpha_dither[((uint8_t)userdata->m_pixel_color.get_a() << 3) | adseed]);
	userdata->m_shade_color.set_a(m_alpha_dither[((uint8_t)userdata->m_shade_color.get_a() << 3) | adseed]);

	if (test_for_reject(userdata, object))
	{
		return false;
	}

	userdata->m_inv_pixel_color.set_a(0xff - userdata->m_color_inputs.blender1b_a[0]->get_a());
	blend_pipe(0, sel0, userdata->m_blended_pixel_color, userdata, object);
	userdata->m_blended_pixel_color.set_a(userdata->m_pixel_color.get_a());

	blended_pixel.set(*userdata->m_color_inputs.blender1a_rgb[1]);

	return true;
}

bool n64_blender_t::cycle2_noblend_noacvg_dither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, int sel1, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_pixel_color.set_a(m_alpha_dither[((uint8_t)userdata->m_pixel_color.get_a() << 3) | adseed]);
	userdata->m_shade_color.set_a(m_alpha_dither[((uint8_t)userdata->m_shade_color.get_a() << 3) | adseed]);

	if (test_for_reject(userdata, object))
	{
		return false;
	}

	userdata->m_inv_pixel_color.set_a(0xff - (uint8_t)userdata->m_color_inputs.blender1b_a[0]->get_a());
	blend_pipe(0, sel0, userdata->m_blended_pixel_color, userdata, object);
	userdata->m_blended_pixel_color.set_a(userdata->m_pixel_color.get_a());

	rgbaint_t index(*userdata->m_color_inputs.blender1a_rgb[1]);
	index.shl_imm(3);
	index.or_imm(dith);
	index.and_imm(0x7ff);
	blended_pixel.set(0, m_color_dither[index.get_r32()], m_color_dither[index.get_g32()], m_color_dither[index.get_b32()]);

	return true;
}

bool n64_blender_t::cycle2_noblend_acvg_nodither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, int sel1, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_shade_color.set_a(m_alpha_dither[((uint8_t)userdata->m_shade_color.get_a() << 3) | adseed]);

	if (test_for_reject(userdata, object))
	{
		return false;
	}

	userdata->m_inv_pixel_color.set_a(0xff - userdata->m_color_inputs.blender1b_a[0]->get_a());
	blend_pipe(0, sel0, userdata->m_blended_pixel_color, userdata, object);
	userdata->m_blended_pixel_color.set_a(userdata->m_pixel_color.get_a());

	blended_pixel.set(*userdata->m_color_inputs.blender1a_rgb[1]);

	return true;
}

bool n64_blender_t::cycle2_noblend_acvg_dither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, int sel1, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_shade_color.set_a(m_alpha_dither[((uint8_t)userdata->m_shade_color.get_a() << 3) | adseed]);

	if (test_for_reject(userdata, object))
	{
		return false;
	}

	userdata->m_inv_pixel_color.set_a(0xff - userdata->m_color_inputs.blender1b_a[0]->get_a());
	blend_pipe(0, sel0, userdata->m_blended_pixel_color, userdata, object);
	userdata->m_blended_pixel_color.set_a(userdata->m_pixel_color.get_a());

	rgbaint_t index(*userdata->m_color_inputs.blender1a_rgb[1]);
	index.shl_imm(3);
	index.or_imm(dith);
	index.and_imm(0x7ff);
	blended_pixel.set(0, m_color_dither[index.get_r32()], m_color_dither[index.get_g32()], m_color_dither[index.get_b32()]);

	return true;
}

bool n64_blender_t::cycle2_blend_noacvg_nodither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, int sel1, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_pixel_color.set_a(m_alpha_dither[((uint8_t)userdata->m_pixel_color.get_a() << 3) | adseed]);
	userdata->m_shade_color.set_a(m_alpha_dither[((uint8_t)userdata->m_shade_color.get_a() << 3) | adseed]);

	if (test_for_reject(userdata, object))
	{
		return false;
	}

	userdata->m_inv_pixel_color.set_a(0xff - userdata->m_color_inputs.blender1b_a[0]->get_a());
	blend_pipe(0, sel0, userdata->m_blended_pixel_color, userdata, object);
	userdata->m_blended_pixel_color.set_a(userdata->m_pixel_color.get_a());

	blend_with_partial_reject(blended_pixel, 1, partialreject, sel1, userdata, object);

	return true;
}

bool n64_blender_t::cycle2_blend_noacvg_dither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, int sel1, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_pixel_color.set_a(m_alpha_dither[(userdata->m_pixel_color.get_a() << 3) | adseed]);
	userdata->m_shade_color.set_a(m_alpha_dither[(userdata->m_shade_color.get_a() << 3) | adseed]);

	if (test_for_reject(userdata, object))
	{
		return false;
	}

	userdata->m_inv_pixel_color.set_a(0xff - userdata->m_color_inputs.blender1b_a[0]->get_a());
	blend_pipe(0, sel0, userdata->m_blended_pixel_color, userdata, object);
	userdata->m_blended_pixel_color.set_a(userdata->m_pixel_color.get_a());

	color_t rgb;
	blend_with_partial_reject(rgb, 1, partialreject, sel1, userdata, object);

	rgb.shl_imm(3);
	rgb.or_imm(dith);
	rgb.and_imm(0x7ff);
	blended_pixel.set(0, m_color_dither[rgb.get_r32()], m_color_dither[rgb.get_g32()], m_color_dither[rgb.get_b32()]);

	return true;
}

bool n64_blender_t::cycle2_blend_acvg_nodither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, int sel1, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_shade_color.set_a(m_alpha_dither[(userdata->m_shade_color.get_a() << 3) | adseed]);

	if (test_for_reject(userdata, object))
	{
		return false;
	}

	userdata->m_inv_pixel_color.set_a(0xff - userdata->m_color_inputs.blender1b_a[0]->get_a());
	blend_pipe(0, sel0, userdata->m_blended_pixel_color, userdata, object);
	userdata->m_blended_pixel_color.set_a(userdata->m_pixel_color.get_a());

	blend_with_partial_reject(blended_pixel, 1, partialreject, sel1, userdata, object);

	return true;
}

bool n64_blender_t::cycle2_blend_acvg_dither(color_t& blended_pixel, int dith, int adseed, int partialreject, int sel0, int sel1, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	userdata->m_shade_color.set_a(m_alpha_dither[(userdata->m_shade_color.get_a() << 3) | adseed]);

	if (test_for_reject(userdata, object))
	{
		return false;
	}

	userdata->m_inv_pixel_color.set_a(0xff - userdata->m_color_inputs.blender1b_a[0]->get_a());
	blend_pipe(0, sel0, userdata->m_blended_pixel_color, userdata, object);
	userdata->m_blended_pixel_color.set_a(userdata->m_pixel_color.get_a());

	color_t rgb;
	blend_with_partial_reject(rgb, 1, partialreject, sel1, userdata, object);

	rgb.shl_imm(3);
	rgb.or_imm(dith);
	rgb.and_imm(0x7ff);
	blended_pixel.set(0, m_color_dither[rgb.get_r32()], m_color_dither[rgb.get_g32()], m_color_dither[rgb.get_b32()]);

	return true;
}

void n64_blender_t::blend_with_partial_reject(color_t& out, int32_t cycle, int32_t partialreject, int32_t select, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	if (partialreject && userdata->m_pixel_color.get_a() >= 0xff)
	{
		out.set(*userdata->m_color_inputs.blender1a_rgb[cycle]);
	}
	else
	{
		userdata->m_inv_pixel_color.set_a(0xff - userdata->m_color_inputs.blender1b_a[cycle]->get_a());
		blend_pipe(cycle, select, out, userdata, object);
	}
}

void n64_blender_t::blend_pipe(const int cycle, const int special, color_t& out, rdp_span_aux* userdata, const rdp_poly_state& object)
{
	const int32_t mask = 0xff &~ (0x73 * special);
	const int32_t shift_a = 3 + userdata->m_shift_a * special;
	const int32_t shift_b = 3 + userdata->m_shift_b * special;
	const int32_t blend1a = (userdata->m_color_inputs.blender1b_a[cycle]->get_a() >> shift_a) & mask;
	const int32_t blend2a = (userdata->m_color_inputs.blender2b_a[cycle]->get_a() >> shift_b) & mask;
	const int32_t special_shift = special << 1;

	rgbaint_t temp(*userdata->m_color_inputs.blender1a_rgb[cycle]);
	temp.mul_imm(blend1a);

	rgbaint_t secondary(*userdata->m_color_inputs.blender2a_rgb[cycle]);
	rgbaint_t other(*userdata->m_color_inputs.blender2a_rgb[cycle]);
	other.mul_imm(blend2a);

	temp.add(other);
	secondary.shl_imm(special_shift);
	temp.add(secondary);
	temp.shr_imm(object.m_other_modes.blend_shift);

	int32_t factor_sum = 0;
	if (!object.m_other_modes.force_blend)
	{
		factor_sum = ((blend1a >> 2) + (blend2a >> 2) + 1) & 0xf;
		if (factor_sum)
		{
			temp.set_r(temp.get_r32() / factor_sum);
			temp.set_g(temp.get_g32() / factor_sum);
			temp.set_b(temp.get_b32() / factor_sum);
		}
		else
		{
			temp.set(0, 0xff, 0xff, 0xff);
		}
	}

	temp.min(255);
	out.set(temp);
}

inline int32_t n64_blender_t::min(const int32_t x, const int32_t min)
{
	if (x < min)
	{
		return x;
	}
	return min;
}