MCPcopy Create free account
hub / github.com/PCSX2/pcsx2 / UsesRegionRepeat

Function UsesRegionRepeat

pcsx2/GS/GSState.cpp:6121–6163  ·  view source on GitHub ↗

Checks if region repeat is used (applying it does something to at least one of the values in min...max) Also calculates the real min and max values seen after applying the region repeat to all values in min...max

Source from the content-addressed store, hash-verified

6119/// Checks if region repeat is used (applying it does something to at least one of the values in min...max)
6120/// Also calculates the real min and max values seen after applying the region repeat to all values in min...max
6121static bool UsesRegionRepeat(int fix, int msk, int min, int max, int* min_out, int* max_out)
6122{
6123 if ((min < 0) != (max < 0))
6124 {
6125 // Algorithm doesn't work properly if bits overflow when incrementing (happens on the -1 → 0 crossing)
6126 // Conveniently, crossing zero guarantees you use the full range
6127 *min_out = fix;
6128 *max_out = (fix | msk) + 1;
6129 return true;
6130 }
6131
6132 const int cleared_bits = ~msk & ~fix; // Bits that are always cleared by applying msk and fix
6133 const int set_bits = fix; // Bits that are always set by applying msk and fix
6134 unsigned long msb;
6135 int variable_bits = min ^ max;
6136 if (_BitScanReverse(&msb, variable_bits))
6137 variable_bits |= (1 << msb) - 1; // Fill in all lower bits
6138
6139 const int always_set = min & ~variable_bits; // Bits that are set in every value in min...max
6140 const int sometimes_set = min | variable_bits; // Bits that are set in at least one value in min...max
6141
6142 const bool sets_bits = (set_bits | always_set) != always_set; // At least one bit in min...max is set by applying msk and fix
6143 const bool clears_bits = (cleared_bits & sometimes_set) != 0; // At least one bit in min...max is cleared by applying msk and fix
6144
6145 const int overwritten_variable_bits = (cleared_bits | set_bits) & variable_bits;
6146 // A variable bit that's `0` in `min` will at some point switch to a `1` (because it's variable)
6147 // When it does, all bits below it will switch to a `0` (that's how incrementing works)
6148 // If the 0 to 1 switch is reflected in the final output (not masked and not replaced by a fixed value),
6149 // the final value would be larger than the previous. Otherwise, the final value will be less.
6150 // The true minimum value is `min` with all bits below the most significant replaced variable `0` bit cleared
6151 const int min_overwritten_variable_zeros = ~min & overwritten_variable_bits;
6152 if (_BitScanReverse(&msb, min_overwritten_variable_zeros))
6153 min &= (~0u << msb);
6154 // Similar thing for max, but the first masked `1` bit
6155 const int max_overwritten_variable_ones = max & overwritten_variable_bits;
6156 if (_BitScanReverse(&msb, max_overwritten_variable_ones))
6157 max |= (1 << msb) - 1;
6158
6159 *min_out = (msk & min) | fix;
6160 *max_out = ((msk & max) | fix) + 1;
6161
6162 return sets_bits || clears_bits;
6163}
6164
6165GSState::TextureMinMaxResult GSState::GetTextureMinMax(GIFRegTEX0 TEX0, GIFRegCLAMP CLAMP, bool linear, bool clamp_to_tsize)
6166{

Callers 1

GetTextureMinMaxMethod · 0.85

Calls 1

_BitScanReverseFunction · 0.85

Tested by

no test coverage detected