public int chooseCapabilities( Capabilities desired, Capabilities[] available, int windowSystemRecommendedChoice) { GLCapabilities _desired = (GLCapabilities) desired; GLCapabilities[] _available = (GLCapabilities[]) available; if (DEBUG) { System.err.println("Desired: " + _desired); for (int i = 0; i < _available.length; i++) { System.err.println("Available " + i + ": " + _available[i]); } System.err.println("Window system's recommended choice: " + windowSystemRecommendedChoice); } if (windowSystemRecommendedChoice >= 0 && windowSystemRecommendedChoice < _available.length && _available[windowSystemRecommendedChoice] != null) { if (DEBUG) { System.err.println( "Choosing window system's recommended choice of " + windowSystemRecommendedChoice); System.err.println(_available[windowSystemRecommendedChoice]); } return windowSystemRecommendedChoice; } // Create score array int[] scores = new int[_available.length]; int NO_SCORE = -9999999; int DOUBLE_BUFFER_MISMATCH_PENALTY = 1000; int STENCIL_MISMATCH_PENALTY = 500; // Pseudo attempt to keep equal rank penalties scale-equivalent // (e.g., stencil mismatch is 3 * accum because there are 3 accum // components) int COLOR_MISMATCH_PENALTY_SCALE = 36; int DEPTH_MISMATCH_PENALTY_SCALE = 6; int ACCUM_MISMATCH_PENALTY_SCALE = 1; int STENCIL_MISMATCH_PENALTY_SCALE = 3; for (int i = 0; i < scores.length; i++) { scores[i] = NO_SCORE; } // Compute score for each for (int i = 0; i < scores.length; i++) { GLCapabilities cur = _available[i]; if (cur == null) { continue; } if (_desired.isOnscreen() != cur.isOnscreen()) { continue; } if (_desired.getStereo() != cur.getStereo()) { continue; } int score = 0; // Compute difference in color depth // (Note that this decides the direction of all other penalties) score += (COLOR_MISMATCH_PENALTY_SCALE * ((cur.getRedBits() + cur.getGreenBits() + cur.getBlueBits() + cur.getAlphaBits()) - (_desired.getRedBits() + _desired.getGreenBits() + _desired.getBlueBits() + _desired.getAlphaBits()))); // Compute difference in depth buffer depth score += (DEPTH_MISMATCH_PENALTY_SCALE * sign(score) * Math.abs(cur.getDepthBits() - _desired.getDepthBits())); // Compute difference in accumulation buffer depth score += (ACCUM_MISMATCH_PENALTY_SCALE * sign(score) * Math.abs( (cur.getAccumRedBits() + cur.getAccumGreenBits() + cur.getAccumBlueBits() + cur.getAccumAlphaBits()) - (_desired.getAccumRedBits() + _desired.getAccumGreenBits() + _desired.getAccumBlueBits() + _desired.getAccumAlphaBits()))); // Compute difference in stencil bits score += STENCIL_MISMATCH_PENALTY_SCALE * sign(score) * (cur.getStencilBits() - _desired.getStencilBits()); if (cur.getDoubleBuffered() != _desired.getDoubleBuffered()) { score += sign(score) * DOUBLE_BUFFER_MISMATCH_PENALTY; } if ((_desired.getStencilBits() > 0) && (cur.getStencilBits() == 0)) { score += sign(score) * STENCIL_MISMATCH_PENALTY; } scores[i] = score; } // Now prefer hardware-accelerated visuals by pushing scores of // non-hardware-accelerated visuals out boolean gotHW = false; int maxAbsoluteHWScore = 0; for (int i = 0; i < scores.length; i++) { int score = scores[i]; if (score == NO_SCORE) { continue; } GLCapabilities cur = _available[i]; if (cur.getHardwareAccelerated()) { int absScore = Math.abs(score); if (!gotHW || (absScore > maxAbsoluteHWScore)) { gotHW = true; maxAbsoluteHWScore = absScore; } } } if (gotHW) { for (int i = 0; i < scores.length; i++) { int score = scores[i]; if (score == NO_SCORE) { continue; } GLCapabilities cur = _available[i]; if (!cur.getHardwareAccelerated()) { if (score <= 0) { score -= maxAbsoluteHWScore; } else if (score > 0) { score += maxAbsoluteHWScore; } scores[i] = score; } } } if (DEBUG) { System.err.print("Scores: ["); for (int i = 0; i < _available.length; i++) { if (i > 0) { System.err.print(","); } System.err.print(" " + scores[i]); } System.err.println(" ]"); } // Ready to select. Choose score closest to 0. int scoreClosestToZero = NO_SCORE; int chosenIndex = -1; for (int i = 0; i < scores.length; i++) { int score = scores[i]; if (score == NO_SCORE) { continue; } // Don't substitute a positive score for a smaller negative score if ((scoreClosestToZero == NO_SCORE) || (Math.abs(score) < Math.abs(scoreClosestToZero) && ((sign(scoreClosestToZero) < 0) || (sign(score) > 0)))) { scoreClosestToZero = score; chosenIndex = i; } } if (chosenIndex < 0) { throw new NativeWindowException("Unable to select one of the provided GLCapabilities"); } if (DEBUG) { System.err.println("Chosen index: " + chosenIndex); System.err.println("Chosen capabilities:"); System.err.println(_available[chosenIndex]); } return chosenIndex; }