lwjgl/src/java/org/lwjgl/opengles/PixelFormat.java

767 lines
26 KiB
Java

/*
* Copyright (c) 2002-2011 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'LWJGL' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.lwjgl.opengles;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil;
import org.lwjgl.opengl.PixelFormatLWJGL;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static org.lwjgl.opengles.EGL.*;
import static org.lwjgl.opengles.NVCoverageSample.*;
import static org.lwjgl.opengles.NVDepthNonlinear.*;
import static org.lwjgl.opengles.PixelFormat.Attrib.*;
/**
* This class describes the configuration settings for an EGL surface. Instances
* of this class are used as arguments to Display.create(). The attributes specified
* in this class will be used to get EGLConfigs from an EGLDisplay. PixelFormat
* is not the best name for this class, but it matches the corresponding class
* in the official desktop LWJGL.
* <p/>
* Instances of this class are immutable. An example of the expected way to set
* the PixelFormat property values is the following:
* <code>PixelFormat pf = new PixelFormat().withDepth(24).withSamples(4);</code>
* <p/>
* Attributes that correspond to EGL extensions will be silently ignored if those
* extensions are not supported by the EGLDisplay.
*/
public final class PixelFormat implements PixelFormatLWJGL {
public static enum Attrib {
// CORE ATTRIBUTES
RED_SIZE(EGL_RED_SIZE, 0),
GREEN_SIZE(EGL_GREEN_SIZE, 0),
BLUE_SIZE(EGL_BLUE_SIZE, 0),
ALPHA_SIZE(EGL_ALPHA_SIZE, 0),
LUMINANCE_SIZE(EGL_LUMINANCE_SIZE, 0),
DEPTH_SIZE(EGL_DEPTH_SIZE, 0),
STENCIL_SIZE(EGL_STENCIL_SIZE, 0),
MIN_SWAP_INTERVAL(EGL_MIN_SWAP_INTERVAL, EGL_DONT_CARE),
MAX_SWAP_INTERVAL(EGL_MAX_SWAP_INTERVAL, EGL_DONT_CARE),
SAMPLES(EGL_SAMPLES, 0),
SAMPLE_BUFFERS(EGL_SAMPLE_BUFFERS, 0),
TRANSPARENT_TYPE(EGL_TRANSPARENT_TYPE, EGL_NONE),
TRANSPARENT_RED_VALUE(EGL_TRANSPARENT_RED_VALUE, EGL_DONT_CARE),
TRANSPARENT_GREEN_VALUE(EGL_TRANSPARENT_GREEN_VALUE, EGL_DONT_CARE),
TRANSPARENT_BLUE_VALUE(EGL_TRANSPARENT_BLUE_VALUE, EGL_DONT_CARE),
// SURFACE ATTRIBUTES
MULTISAMPLE_RESOLVE(EGL_MULTISAMPLE_RESOLVE, EGL_MULTISAMPLE_RESOLVE_DEFAULT, true),
SWAP_BEHAVIOR(EGL_SWAP_BEHAVIOR, EGL_DONT_CARE, true),
// EXTENSION ATTRIBUTES
COVERAGE_SAMPLES_NV(EGL_COVERAGE_SAMPLES_NV, 0),
COVERAGE_BUFFERS_NV(EGL_COVERAGE_BUFFERS_NV, 0),
DEPTH_ENCODING_NONLINEAR_NV(EGL_DEPTH_ENCODING_NONLINEAR_NV, EGL_DONT_CARE);
private final int eglAttrib;
private final int defaultValue;
private final boolean surfaceAttrib;
Attrib(final int eglAttrib, final int defaultValue) {
this(eglAttrib, defaultValue, false);
}
Attrib(final int eglAttrib, final int defaultValue, final boolean surfaceAttrib) {
this.eglAttrib = eglAttrib;
this.defaultValue = defaultValue;
this.surfaceAttrib = surfaceAttrib;
}
/**
* Returns the EGL token that corresponds to this attribute.
*
* @return the EGL attribute token
*/
public int getEGLAttrib() {
return eglAttrib;
}
/**
* Returns the default value of this attribute. Attributes
* with default values will be ignored when choosing the EGLConfig.
*
* @return the default value
*/
public int getDefaultValue() {
return defaultValue;
}
public boolean isSurfaceAttrib() {
return surfaceAttrib;
}
}
private final Map<Attrib, Integer> config = new HashMap<Attrib, Integer>(16);
/**
* Creates a new PixelFormat with rgbSize = 8, alphaSize = 8 and depthSize = 16.
*
* @see #PixelFormat(int, int, int, int, int, int)
*/
public PixelFormat() {
this(8, 16, 0);
}
/**
* Creates a new PixelFormat with rgbSize = 8 and the specified
* alphaSize, depthSize and stencilSize.
*
* @param alphaSize the EGL_ALPHA_SIZE value
* @param depthSize the EGL_DEPTH_SIZE value
* @param stencilSize the EGL_STENCIL_SIZE value
*
* @see #PixelFormat(int, int, int, int, int, int)
*/
public PixelFormat(int alphaSize, int depthSize, int stencilSize) {
this(alphaSize, depthSize, stencilSize, 0);
}
/**
* Creates a new PixelFormat with rgbSize = 8 and the specified
* alphaSize, depthSize, stencilSize and samples.
*
* @param alphaSize the EGL_ALPHA_SIZE value
* @param depthSize the EGL_DEPTH_SIZE value
* @param stencilSize the EGL_STENCIL_SIZE value
* @param samples the EGL_SAMPLE_SIZE value
*
* @see #PixelFormat(int, int, int, int, int, int)
*/
public PixelFormat(int alphaSize, int depthSize, int stencilSize, int samples) {
this(8, alphaSize, 0, depthSize, stencilSize, samples);
}
/**
* Creates a new PixelFormat with the specified RGB sizes, EGL_ALPHA_SIZE,
* EGL_LUMINANCE_SIZE, EGL_DEPTH_SIZE, EGL_STENCIL_SIZE, EGL_SAMPLES.
* All values must be greater than or equal to 0. rgbSize and luminanceSize
* cannot both be greater than 0. depthSize greater than 24 and stencilSize
* greater than 8 are not recommended.
* The corresponding EGL_SAMPLE_BUFFERS value will become 0 if samples is 0,
* or 1 if samples is greater than 0.
*
* @param rgbSize the RGB sizes
* @param alphaSize the EGL_ALPHA_SIZE value
* @param luminanceSize the EGL_LUMINANCE_SIZE value
* @param depthSize the EGL_DEPTH_SIZE value
* @param stencilSize the EGL_STENCIL_SIZE value
* @param samples the EGL_SAMPLE_SIZE value
*/
public PixelFormat(int rgbSize, int alphaSize, int luminanceSize, int depthSize, int stencilSize, int samples) {
if ( rgbSize < 0 )
throw new IllegalArgumentException("Invalid RGB size specified: " + rgbSize);
if ( alphaSize < 0 )
throw new IllegalArgumentException("Invalid EGL_ALPHA_SIZE specified: " + alphaSize);
if ( luminanceSize < 0 || (0 < luminanceSize && 0 < rgbSize) )
throw new IllegalArgumentException("Invalid EGL_LUMINANCE_SIZE specified: " + luminanceSize);
if ( depthSize < 0 )
throw new IllegalArgumentException("Invalid EGL_DEPTH_SIZE specified: " + depthSize);
if ( stencilSize < 0 )
throw new IllegalArgumentException("Invalid EGL_STENCIL_SIZE specified: " + stencilSize);
if ( samples < 0 )
throw new IllegalArgumentException("Invalid EGL_SAMPLES specified: " + samples);
if ( 0 < rgbSize ) {
setAttrib(RED_SIZE, rgbSize);
setAttrib(GREEN_SIZE, rgbSize);
setAttrib(BLUE_SIZE, rgbSize);
}
setAttrib(ALPHA_SIZE, alphaSize);
setAttrib(LUMINANCE_SIZE, luminanceSize);
setAttrib(DEPTH_SIZE, depthSize);
setAttrib(STENCIL_SIZE, stencilSize);
setAttrib(SAMPLES, samples);
setAttrib(SAMPLE_BUFFERS, samples == 0 ? 0 : 1);
}
/**
* Creates a new PixelFormat that is a copy of the specified PixelFormat.
*
* @param pf the source PixelFormat
*/
private PixelFormat(final PixelFormat pf) {
config.clear();
config.putAll(pf.config);
}
/**
* Sets the value of an attribute to the current configuration.
* If the value matches the default attribute value, the
* attribute will be removed from the configuration.
*
* @param attrib the attribute
* @param value the new value
*/
private void setAttrib(final Attrib attrib, final int value) {
if ( attrib.defaultValue == value )
config.remove(attrib);
else
config.put(attrib, value);
}
/**
* Returns an IntBuffer that can be used to get/choose EGLConfigs.
* The contents of the IntBuffer will be the sum of the source
* LWJGL attributes and the user-defined attributes from this
* PixelFormat's configuration.
* <p/>
* The source LWJGL attributes should not contain the EGL_SURFACE_TYPE
* attirube, or any attributes that are handled by PixelFormat.
* <p/>
* Attributes that correspond to EGL extensions will be checked
* against the extensions supported in the specified EGLDisplay.
* Attributes that correspond to unsupported extensions will not
* be included in the final EGLConfig query.
*
* @param display the EGL display from which the EGLConfig is going to be retrieved
* @param lwjglAttribs the LWJGL attributes
*
* @return the IntBuffer
*/
public IntBuffer getAttribBuffer(final EGLDisplay display, int surfaceType, final int[] lwjglAttribs) {
// Create a copy of the configuration attributes
Set<Attrib> keys = new HashSet<Attrib>(config.keySet());
// Handle surface type bits
if ( keys.contains(MULTISAMPLE_RESOLVE) ) {
if ( display.getMajorVersion() == 1 && display.getMinorVersion() < 4 )
keys.remove(MULTISAMPLE_RESOLVE);
else if ( getAttrib(MULTISAMPLE_RESOLVE) == EGL_MULTISAMPLE_RESOLVE_BOX )
surfaceType |= EGL_MULTISAMPLE_RESOLVE_BOX_BIT;
}
if ( keys.contains(SWAP_BEHAVIOR) ) {
if ( display.getMajorVersion() == 1 && display.getMinorVersion() < 4 )
keys.remove(SWAP_BEHAVIOR);
else if ( getAttrib(SWAP_BEHAVIOR) == EGL_BUFFER_PRESERVED )
surfaceType |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
}
// Check NV_coverage_sample
if ( keys.contains(COVERAGE_BUFFERS_NV) && !display.isExtensionSupported("EGL_NV_coverage_sample") ) {
keys.remove(COVERAGE_BUFFERS_NV);
keys.remove(COVERAGE_SAMPLES_NV);
}
// Check NV_depth_nonlinear
if ( keys.contains(DEPTH_ENCODING_NONLINEAR_NV) && !display.isExtensionSupported("EGL_NV_depth_nonlinear") )
keys.remove(DEPTH_ENCODING_NONLINEAR_NV);
// Create IntBuffer and insert the attributes
final IntBuffer attribs = BufferUtils.createIntBuffer(
2 // SURFACE_TYPE
+ lwjglAttribs.length // Source LWJGL attributes
+ (keys.size() * 2) // PixelFormat attributes
+ 1 // Termination
);
attribs.put(EGL_SURFACE_TYPE).put(surfaceType);
attribs.put(lwjglAttribs);
for ( Attrib key : keys ) {
if ( !key.isSurfaceAttrib() )
attribs.put(key.eglAttrib).put(config.get(key));
}
// Finish the attribute list
attribs.put(EGL_NONE);
attribs.flip();
return attribs;
}
/**
* Returns true if the requested attribute matches the attribute in the specified EGL config.
*
* @param attrib the requested attribute
* @param config the EGL config
*
* @return true if the two attributes match
*
* @throws org.lwjgl.LWJGLException if an EGL error occurs
*/
private boolean matches(final Attrib attrib, final EGLConfig config) throws LWJGLException {
return getAttrib(attrib) == config.getAttribute(attrib.getEGLAttrib());
}
/**
* Returns true if the requested attribute matches the attribute in the specified EGL config.
* If the requested attribute is equal to 1, then it will match with any EGL config attribute
* that is greater than 0.
*
* @param attrib the requested attribute
* @param config the EGL config
*
* @return true if the two attributes match
*
* @throws org.lwjgl.LWJGLException if an EGL error occurs
*/
private boolean matchesNonZero(final Attrib attrib, final EGLConfig config) throws LWJGLException {
final int reqValue = getAttrib(attrib);
final int cfgValue = config.getAttribute(attrib.getEGLAttrib());
return reqValue == cfgValue || (reqValue == 1 && cfgValue > 0);
}
/**
* Returns the EGL config from the specified array that best matches this PixelFormat.
*
* @param configs the EGL configs
*
* @return the best match
*/
public EGLConfig getBestMatch(final EGLConfig[] configs) throws LWJGLException {
if ( configs == null || configs.length == 0 )
throw new IllegalArgumentException("No EGLConfigs specified.");
if ( configs.length == 1 )
return configs[0];
/*System.out.println("\nASKED FOR:");
for ( Attrib attrib : config.keySet() ) {
System.out.println("EGL_" + attrib.name() + ": " + getAttrib(attrib));
}
for ( EGLConfig config : configs ) {
if ( config == null )
continue;
System.out.println("\n----");
System.out.println(config);
}*/
for ( EGLConfig config : configs ) {
if ( config == null )
continue;
if ( !(matches(ALPHA_SIZE, config) && matchesNonZero(DEPTH_SIZE, config) && matchesNonZero(STENCIL_SIZE, config)) )
continue;
final int luminance = getAttrib(LUMINANCE_SIZE);
if ( 0 < luminance && !matches(LUMINANCE_SIZE, config) )
continue;
if ( luminance == 0 && !(matches(RED_SIZE, config) && matches(GREEN_SIZE, config) && matches(BLUE_SIZE, config)) )
continue;
if ( !(matches(SAMPLE_BUFFERS, config) && matches(SAMPLES, config)) )
continue;
// TODO: Add more? NV's Tegra SDK checks a hardcoded 5 value for COVERAGE_SAMPLES_NV (nv_main.c, line: 1823)
return config;
}
// No match found, use the one recommended by the EGL implementation.
LWJGLUtil.log("Could not find an exact EGLConfig match for the PixelFormat requested, using first returned.");
return configs[0];
}
/**
* Applies this PixelFormat's surface attributes to the specified EGL surface.
*
* @param surface the EGL surface
*/
public void setSurfaceAttribs(final EGLSurface surface) throws LWJGLException {
setSurfaceAttrib(surface, SWAP_BEHAVIOR);
setSurfaceAttrib(surface, MULTISAMPLE_RESOLVE);
}
private void setSurfaceAttrib(final EGLSurface surface, final Attrib attrib) throws LWJGLException {
final int value = getAttrib(attrib);
if ( value != attrib.getDefaultValue() )
surface.setAttribute(attrib.getEGLAttrib(), value);
}
/**
* Returns the value of the specified attribute.
*
* @param attrib the attribute to retrieve
*
* @return the attribute's value
*/
public int getAttrib(final Attrib attrib) {
final Integer value = config.get(attrib);
if ( value == null )
return attrib.defaultValue;
return value;
}
/* -----------------------------------------
CORE ATTRIBUTES
----------------------------------------- */
/**
* Returns a new PixelFormat with the specified RGB sizes.
*
* @param rgb the new EGL_RED_SIZE, EGL_GREEN_SIZE and EGL_BLUE_SIZE
*
* @return the new PixelFormat
*
* @see #withRGBSize(int, int, int)
*/
public PixelFormat withRGBSize(final int rgb) {
return withRGBSize(rgb, rgb, rgb);
}
/**
* Returns a new PixelFormat with the specified EGL_RED_SIZE, EGL_GREEN_SIZE and EGL_BLUE_SIZE.
* All 3 values must be greater than or equal to 0. If any of the 3 values is greater than 0,
* the luminanceSize will be set to 0.
*
* @param r the new EGL_RED_SIZE
* @param g the new EGL_GREEN_SIZE
* @param b the new EGL_BLUE_SIZE
*
* @return the new PixelFormat
*/
public PixelFormat withRGBSize(final int r, final int g, final int b) {
if ( r < 0 || g < 0 || b < 0 )
throw new IllegalArgumentException("Invalid RGB sizes specified: " + r + ", " + g + ", " + b);
final PixelFormat pf = new PixelFormat(this);
pf.setAttrib(RED_SIZE, r);
pf.setAttrib(GREEN_SIZE, g);
pf.setAttrib(BLUE_SIZE, b);
if ( 0 < r || 0 < g || 0 < b )
pf.setAttrib(LUMINANCE_SIZE, 0);
return pf;
}
/**
* Returns a new PixelFormat with the specified EGL_ALPHA_SIZE.
* The alphaSize value must be greater than or equal to 0.
*
* @param alphaSize the new EGL_ALPHA_SIZE
*
* @return the new PixelFormat
*/
public PixelFormat withAlphaSize(final int alphaSize) {
if ( alphaSize < 0 )
throw new IllegalArgumentException("Invalid EGL_ALPHA_SIZE specified: " + alphaSize);
final PixelFormat pf = new PixelFormat(this);
pf.setAttrib(ALPHA_SIZE, alphaSize);
return pf;
}
/**
* Returns a new PixelFormat with the specified EGL_LUMINANCE_SIZE.
* The luminanceSize value must be greater than or equal to 0. If
* luminanceSize is greater than 0, the RGB sizes will be set to 0.
*
* @param luminanceSize the new EGL_LUMINANCE_SIZE
*
* @return the new PixelFormat
*/
public PixelFormat withLuminanceSize(final int luminanceSize) {
if ( luminanceSize < 0 )
throw new IllegalArgumentException("Invalid EGL_LUMINANCE_SIZE specified: " + luminanceSize);
final PixelFormat pf = new PixelFormat(this);
pf.setAttrib(LUMINANCE_SIZE, luminanceSize);
if ( 0 < luminanceSize ) {
pf.setAttrib(RED_SIZE, 0);
pf.setAttrib(GREEN_SIZE, 0);
pf.setAttrib(BLUE_SIZE, 0);
}
return pf;
}
/**
* Returns a new PixelFormat with the specified EGL_DEPTH_SIZE.
* The depthSize value must be greater than or equal to 0.
* Values greater than 24 are not recommended.
*
* @param depthSize the new EGL_DEPTH_SIZE
*
* @return the new PixelFormat
*/
public PixelFormat withDepthSize(final int depthSize) {
if ( depthSize < 0 )
throw new IllegalArgumentException("Invalid EGL_DEPTH_SIZE specified: " + depthSize);
final PixelFormat pf = new PixelFormat(this);
pf.setAttrib(DEPTH_SIZE, depthSize);
return pf;
}
/**
* Returns a new PixelFormat with the specified EGL_STENCIL_SIZE.
* The stencilSize value must be greater than or equal to 0.
* Values greater than 8 are not recommended.
*
* @param stencilSize the new EGL_STENCIL_SIZE
*
* @return the new PixelFormat
*/
public PixelFormat withStencilSize(final int stencilSize) {
if ( stencilSize < 0 )
throw new IllegalArgumentException("Invalid EGL_STENCIL_SIZE specified: " + stencilSize);
final PixelFormat pf = new PixelFormat(this);
pf.setAttrib(STENCIL_SIZE, stencilSize);
return pf;
}
/**
* Returns a new PixelFormat with the specified EGL_MIN_SWAP_INTERVAL.
* The minSwapInterval value must be between 0 and this PixelFormat's EGL_MAX_SWAP_INTERVAL.
*
* @param minSwapInterval the new EGL_MIN_SWAP_INTERVAL value
*
* @return the new PixelFormat
*/
public PixelFormat withMinSwapInterval(final int minSwapInterval) {
final int maxSwapInterval = getAttrib(MAX_SWAP_INTERVAL);
if ( minSwapInterval != EGL_DONT_CARE && (minSwapInterval < 0 || (maxSwapInterval != EGL_DONT_CARE && maxSwapInterval < minSwapInterval)) )
throw new IllegalArgumentException("Invalid EGL_MIN_SWAP_INTERVAL specified: " + minSwapInterval);
final PixelFormat pf = new PixelFormat(this);
pf.setAttrib(MIN_SWAP_INTERVAL, minSwapInterval);
return pf;
}
/**
* Returns a new PixelFormat with the specified EGL_MAX_SWAP_INTERVAL.
* The maxSwapInterval value must be greater than or equal to this PixelFormat's EGL_MIN_SWAP_INTERVAL.
*
* @param maxSwapInterval the new EGL_MAX_SWAP_INTERVAL value
*
* @return the new PixelFormat
*/
public PixelFormat withMaxSwapInterval(final int maxSwapInterval) {
if ( maxSwapInterval < getAttrib(MIN_SWAP_INTERVAL) )
throw new IllegalArgumentException("Invalid EGL_MAX_SWAP_INTERVAL specified: " + maxSwapInterval);
final PixelFormat pf = new PixelFormat(this);
pf.setAttrib(MAX_SWAP_INTERVAL, maxSwapInterval);
return pf;
}
/**
* Returns a new PixelFormat with the specified number of EGL_SAMPLES.
* The samples value must be either 0 or greater than or equal to 2. The related
* EGL_SAMPLE_BUFFERS value will become 0 if samples is 0, or 1 if samples
* is greater than or equal to 2.
*
* @param samples the new EGL_SAMPLES value
*
* @return the new PixelFormat
*/
public PixelFormat withSamples(final int samples) {
if ( samples != 0 && samples < 2 )
throw new IllegalArgumentException("Invalid number of EGL_SAMPLES specified: " + samples);
final PixelFormat pf = new PixelFormat(this);
pf.setAttrib(SAMPLES, samples);
pf.setAttrib(SAMPLE_BUFFERS, samples == 0 ? 0 : 1);
return pf;
}
private static int maxValue(final int bits) {
return (2 << bits) - 1;
}
/**
* Returns a new PixelFormat with the specified EGL_TRANSPARENT_TYPE and
* the specified transparent RGB values. The transparentType must be
* either EGL_NONE or EGL_TRANSPARENT_RGB. When it is EGL_NONE, the RGB
* values are set to zero and ignored. When it is EGL_TRANSPARENT_RGB,
* the RGB values must be between 0 and 2^rgbSize - 1.
*
* @param transparentType the new EGL_TRANSPARENT_TYPE value
* @param r the new EGL_TRANSPARENT_RED_VALUE
* @param g the new EGL_TRANSPARENT_GREEN_VALUE
* @param b the new EGL_TRANSPARENT_BLUE_VALUE
*
* @return the new PixelFormat
*/
public PixelFormat withTransparentType(final int transparentType, int r, int g, int b) {
if ( transparentType == EGL_TRANSPARENT_RGB ) {
final int redSize = getAttrib(RED_SIZE);
final int greenSize = getAttrib(GREEN_SIZE);
final int blueSize = getAttrib(BLUE_SIZE);
if ( r < 0 || (0 < redSize && maxValue(redSize) < r) )
throw new IllegalArgumentException("Invalid EGL_TRANSPARENT_RED_VALUE specified: " + r);
if ( r < 0 || (0 < greenSize && maxValue(greenSize) < g) )
throw new IllegalArgumentException("Invalid EGL_TRANSPARENT_GREEN_VALUE specified: " + g);
if ( r < 0 || (0 < blueSize && maxValue(blueSize) < b) )
throw new IllegalArgumentException("Invalid EGL_TRANSPARENT_BLUE_VALUE specified: " + b);
} else if ( transparentType != EGL_NONE )
throw new IllegalArgumentException("Invalid EGL_TRANSPARENT_TYPE specified: " + transparentType);
else
r = g = b = EGL_DONT_CARE;
final PixelFormat pf = new PixelFormat(this);
pf.setAttrib(TRANSPARENT_TYPE, transparentType);
pf.setAttrib(TRANSPARENT_RED_VALUE, r);
pf.setAttrib(TRANSPARENT_GREEN_VALUE, g);
pf.setAttrib(TRANSPARENT_BLUE_VALUE, b);
return pf;
}
/* -----------------------------------------
SURFACE ATTRIBUTES
----------------------------------------- */
/**
* Returns a new PixelFormat with the specified EGL_MULTISAMPLE_RESOLVE value.
* Valid values for multisampleResolve are EGL_MULTISAMPLE_RESOLVE_DEFAULT
* and EGL_MULTISAMPLE_RESOLVE_BOX.
* <p/>
* An IllegalStateException will be thrown if EGL_SAMPLES has not been previously defined
* to be greater than or equal to 2.
*
* @param multisampleResolve the new EGL_MULTISAMPLE_RESOLVE value
*
* @return the new PixelFormat
*/
public PixelFormat withMultisampleResolve(final int multisampleResolve) {
if ( multisampleResolve != EGL_MULTISAMPLE_RESOLVE_DEFAULT && multisampleResolve != EGL_MULTISAMPLE_RESOLVE_BOX )
throw new IllegalArgumentException("Invalid EGL_MULTISAMPLE_RESOLVE value specified: " + multisampleResolve);
if ( getAttrib(SAMPLE_BUFFERS) == 0 )
throw new IllegalStateException("An EGL_MULTISAMPLE_RESOLVE value cannot be specified unless EGL_SAMPLE_BUFFERS is 1.");
final PixelFormat pf = new PixelFormat(this);
pf.setAttrib(MULTISAMPLE_RESOLVE, multisampleResolve);
return pf;
}
/**
* Returns a new PixelFormat with the specified EGL_SWAP_BEHAVIOR value.
* Valid values for swapBehavior are EGL_DONT_CARE, EGL_BUFFER_PRESERVED
* and EGL_BUFFER_DESTROYED.
*
* @param swapBehavior the new EGL_SWAP_BEHAVIOR value
*
* @return the new PixelFormat
*/
public PixelFormat withSwapBehavior(final int swapBehavior) {
switch ( swapBehavior ) {
case EGL_DONT_CARE:
case EGL_BUFFER_PRESERVED:
case EGL_BUFFER_DESTROYED:
break;
default:
throw new IllegalArgumentException("Invalid EGL_SWAP_BEHAVIOR value specified: " + swapBehavior);
}
final PixelFormat pf = new PixelFormat(this);
pf.setAttrib(SWAP_BEHAVIOR, swapBehavior);
return pf;
}
/* -----------------------------------------
EXTENSION ATTRIBUTES
----------------------------------------- */
/**
* Returns a new PixelFormat with the specified number of EGL_COVERAGE_SAMPLES_NV.
* The samples value must be greater than or equal to 0. The related
* EGL_COVERAGE_BUFFERS_NV value will become 0 if samples is 0, or 1 if samples
* is greater than 0.
*
* @param samples the new EGL_SAMPLES value
*
* @return the new PixelFormat
*/
public PixelFormat withCoverageSamplesNV(final int samples) {
if ( samples < 0 )
throw new IllegalArgumentException("Invalid number of EGL_COVERAGE_SAMPLES_NV specified: " + samples);
final PixelFormat pf = new PixelFormat(this);
pf.setAttrib(COVERAGE_SAMPLES_NV, samples);
pf.setAttrib(COVERAGE_BUFFERS_NV, samples == 0 ? 0 : 1);
return pf;
}
/**
* Returns a new PixelFormat with the specified EGL_DEPTH_ENCODING_NONLINEAR_NV.
* Valid values for depthEncoding are EGL_DONT_CARE, EGL_DEPTH_ENCODING_NONE_NV
* and EGL_DEPTH_ENCODING_NONLINEAR_NV.
*
* @param depthEncoding the new EGL_DEPTH_ENCODING_NONLINEAR_NV value
*
* @return the new PixelFormat
*/
public PixelFormat withDepthEncodingNonlinearNV(final int depthEncoding) {
switch ( depthEncoding ) {
case EGL_DONT_CARE:
case EGL_DEPTH_ENCODING_NONE_NV:
case EGL_DEPTH_ENCODING_NONLINEAR_NV:
break;
default:
throw new IllegalArgumentException("Invalid EGL_DEPTH_ENCODING_NONLINEAR_NV value specified: " + depthEncoding);
}
final PixelFormat pf = new PixelFormat(this);
pf.setAttrib(DEPTH_ENCODING_NONLINEAR_NV, depthEncoding);
return pf;
}
}