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
| 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 |
| 6121 | static 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 | |
| 6165 | GSState::TextureMinMaxResult GSState::GetTextureMinMax(GIFRegTEX0 TEX0, GIFRegCLAMP CLAMP, bool linear, bool clamp_to_tsize) |
| 6166 | { |
no test coverage detected