1 /* 2 * Copyright (c) 2002-2011 LWJGL Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'LWJGL' nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package org.lwjgl.opengles; 33 34 import org.lwjgl.BufferUtils; 35 import org.lwjgl.LWJGLException; 36 import org.lwjgl.LWJGLUtil; 37 import org.lwjgl.opengl.PixelFormatLWJGL; 38 39 import java.nio.IntBuffer; 40 import java.util.HashMap; 41 import java.util.HashSet; 42 import java.util.Map; 43 import java.util.Set; 44 45 import static org.lwjgl.opengles.EGL.*; 46 import static org.lwjgl.opengles.NVCoverageSample.*; 47 import static org.lwjgl.opengles.NVDepthNonlinear.*; 48 import static org.lwjgl.opengles.PixelFormat.Attrib.*; 49 50 /** 51 * This class describes the configuration settings for an EGL surface. Instances 52 * of this class are used as arguments to Display.create(). The attributes specified 53 * in this class will be used to get EGLConfigs from an EGLDisplay. PixelFormat 54 * is not the best name for this class, but it matches the corresponding class 55 * in the official desktop LWJGL. 56 * <p/> 57 * Instances of this class are immutable. An example of the expected way to set 58 * the PixelFormat property values is the following: 59 * <code>PixelFormat pf = new PixelFormat().withDepth(24).withSamples(4);</code> 60 * <p/> 61 * Attributes that correspond to EGL extensions will be silently ignored if those 62 * extensions are not supported by the EGLDisplay. 63 */ 64 public final class PixelFormat implements PixelFormatLWJGL { 65 66 public static enum Attrib { 67 // CORE ATTRIBUTES 68 69 RED_SIZE(EGL_RED_SIZE, 0), 70 GREEN_SIZE(EGL_GREEN_SIZE, 0), 71 BLUE_SIZE(EGL_BLUE_SIZE, 0), 72 ALPHA_SIZE(EGL_ALPHA_SIZE, 0), 73 74 LUMINANCE_SIZE(EGL_LUMINANCE_SIZE, 0), 75 76 DEPTH_SIZE(EGL_DEPTH_SIZE, 0), 77 STENCIL_SIZE(EGL_STENCIL_SIZE, 0), 78 79 MIN_SWAP_INTERVAL(EGL_MIN_SWAP_INTERVAL, EGL_DONT_CARE), 80 MAX_SWAP_INTERVAL(EGL_MAX_SWAP_INTERVAL, EGL_DONT_CARE), 81 82 SAMPLES(EGL_SAMPLES, 0), 83 SAMPLE_BUFFERS(EGL_SAMPLE_BUFFERS, 0), 84 85 TRANSPARENT_TYPE(EGL_TRANSPARENT_TYPE, EGL_NONE), 86 TRANSPARENT_RED_VALUE(EGL_TRANSPARENT_RED_VALUE, EGL_DONT_CARE), 87 TRANSPARENT_GREEN_VALUE(EGL_TRANSPARENT_GREEN_VALUE, EGL_DONT_CARE), 88 TRANSPARENT_BLUE_VALUE(EGL_TRANSPARENT_BLUE_VALUE, EGL_DONT_CARE), 89 90 // SURFACE ATTRIBUTES 91 92 MULTISAMPLE_RESOLVE(EGL_MULTISAMPLE_RESOLVE, EGL_MULTISAMPLE_RESOLVE_DEFAULT, true), 93 SWAP_BEHAVIOR(EGL_SWAP_BEHAVIOR, EGL_DONT_CARE, true), 94 95 // EXTENSION ATTRIBUTES 96 97 COVERAGE_SAMPLES_NV(EGL_COVERAGE_SAMPLES_NV, 0), 98 COVERAGE_BUFFERS_NV(EGL_COVERAGE_BUFFERS_NV, 0), 99 100 DEPTH_ENCODING_NONLINEAR_NV(EGL_DEPTH_ENCODING_NONLINEAR_NV, EGL_DONT_CARE); 101 102 private final int eglAttrib; 103 private final int defaultValue; 104 105 private final boolean surfaceAttrib; 106 Attrib(final int eglAttrib, final int defaultValue)107 Attrib(final int eglAttrib, final int defaultValue) { 108 this(eglAttrib, defaultValue, false); 109 } 110 Attrib(final int eglAttrib, final int defaultValue, final boolean surfaceAttrib)111 Attrib(final int eglAttrib, final int defaultValue, final boolean surfaceAttrib) { 112 this.eglAttrib = eglAttrib; 113 this.defaultValue = defaultValue; 114 115 this.surfaceAttrib = surfaceAttrib; 116 } 117 118 /** 119 * Returns the EGL token that corresponds to this attribute. 120 * 121 * @return the EGL attribute token 122 */ getEGLAttrib()123 public int getEGLAttrib() { 124 return eglAttrib; 125 } 126 127 /** 128 * Returns the default value of this attribute. Attributes 129 * with default values will be ignored when choosing the EGLConfig. 130 * 131 * @return the default value 132 */ getDefaultValue()133 public int getDefaultValue() { 134 return defaultValue; 135 } 136 isSurfaceAttrib()137 public boolean isSurfaceAttrib() { 138 return surfaceAttrib; 139 } 140 141 } 142 143 private final Map<Attrib, Integer> config = new HashMap<Attrib, Integer>(16); 144 145 /** 146 * Creates a new PixelFormat with rgbSize = 8, alphaSize = 8 and depthSize = 16. 147 * 148 * @see #PixelFormat(int, int, int, int, int, int) 149 */ PixelFormat()150 public PixelFormat() { 151 this(8, 16, 0); 152 } 153 154 /** 155 * Creates a new PixelFormat with rgbSize = 8 and the specified 156 * alphaSize, depthSize and stencilSize. 157 * 158 * @param alphaSize the EGL_ALPHA_SIZE value 159 * @param depthSize the EGL_DEPTH_SIZE value 160 * @param stencilSize the EGL_STENCIL_SIZE value 161 * 162 * @see #PixelFormat(int, int, int, int, int, int) 163 */ PixelFormat(int alphaSize, int depthSize, int stencilSize)164 public PixelFormat(int alphaSize, int depthSize, int stencilSize) { 165 this(alphaSize, depthSize, stencilSize, 0); 166 } 167 168 /** 169 * Creates a new PixelFormat with rgbSize = 8 and the specified 170 * alphaSize, depthSize, stencilSize and samples. 171 * 172 * @param alphaSize the EGL_ALPHA_SIZE value 173 * @param depthSize the EGL_DEPTH_SIZE value 174 * @param stencilSize the EGL_STENCIL_SIZE value 175 * @param samples the EGL_SAMPLE_SIZE value 176 * 177 * @see #PixelFormat(int, int, int, int, int, int) 178 */ PixelFormat(int alphaSize, int depthSize, int stencilSize, int samples)179 public PixelFormat(int alphaSize, int depthSize, int stencilSize, int samples) { 180 this(8, alphaSize, 0, depthSize, stencilSize, samples); 181 } 182 183 /** 184 * Creates a new PixelFormat with the specified RGB sizes, EGL_ALPHA_SIZE, 185 * EGL_LUMINANCE_SIZE, EGL_DEPTH_SIZE, EGL_STENCIL_SIZE, EGL_SAMPLES. 186 * All values must be greater than or equal to 0. rgbSize and luminanceSize 187 * cannot both be greater than 0. depthSize greater than 24 and stencilSize 188 * greater than 8 are not recommended. 189 * The corresponding EGL_SAMPLE_BUFFERS value will become 0 if samples is 0, 190 * or 1 if samples is greater than 0. 191 * 192 * @param rgbSize the RGB sizes 193 * @param alphaSize the EGL_ALPHA_SIZE value 194 * @param luminanceSize the EGL_LUMINANCE_SIZE value 195 * @param depthSize the EGL_DEPTH_SIZE value 196 * @param stencilSize the EGL_STENCIL_SIZE value 197 * @param samples the EGL_SAMPLE_SIZE value 198 */ PixelFormat(int rgbSize, int alphaSize, int luminanceSize, int depthSize, int stencilSize, int samples)199 public PixelFormat(int rgbSize, int alphaSize, int luminanceSize, int depthSize, int stencilSize, int samples) { 200 if ( rgbSize < 0 ) 201 throw new IllegalArgumentException("Invalid RGB size specified: " + rgbSize); 202 203 if ( alphaSize < 0 ) 204 throw new IllegalArgumentException("Invalid EGL_ALPHA_SIZE specified: " + alphaSize); 205 206 if ( luminanceSize < 0 || (0 < luminanceSize && 0 < rgbSize) ) 207 throw new IllegalArgumentException("Invalid EGL_LUMINANCE_SIZE specified: " + luminanceSize); 208 209 if ( depthSize < 0 ) 210 throw new IllegalArgumentException("Invalid EGL_DEPTH_SIZE specified: " + depthSize); 211 212 if ( stencilSize < 0 ) 213 throw new IllegalArgumentException("Invalid EGL_STENCIL_SIZE specified: " + stencilSize); 214 215 if ( samples < 0 ) 216 throw new IllegalArgumentException("Invalid EGL_SAMPLES specified: " + samples); 217 218 if ( 0 < rgbSize ) { 219 setAttrib(RED_SIZE, rgbSize); 220 setAttrib(GREEN_SIZE, rgbSize); 221 setAttrib(BLUE_SIZE, rgbSize); 222 } 223 setAttrib(ALPHA_SIZE, alphaSize); 224 225 setAttrib(LUMINANCE_SIZE, luminanceSize); 226 227 setAttrib(DEPTH_SIZE, depthSize); 228 setAttrib(STENCIL_SIZE, stencilSize); 229 230 setAttrib(SAMPLES, samples); 231 setAttrib(SAMPLE_BUFFERS, samples == 0 ? 0 : 1); 232 } 233 234 /** 235 * Creates a new PixelFormat that is a copy of the specified PixelFormat. 236 * 237 * @param pf the source PixelFormat 238 */ PixelFormat(final PixelFormat pf)239 private PixelFormat(final PixelFormat pf) { 240 config.clear(); 241 config.putAll(pf.config); 242 } 243 244 /** 245 * Sets the value of an attribute to the current configuration. 246 * If the value matches the default attribute value, the 247 * attribute will be removed from the configuration. 248 * 249 * @param attrib the attribute 250 * @param value the new value 251 */ setAttrib(final Attrib attrib, final int value)252 private void setAttrib(final Attrib attrib, final int value) { 253 if ( attrib.defaultValue == value ) 254 config.remove(attrib); 255 else 256 config.put(attrib, value); 257 } 258 259 /** 260 * Returns an IntBuffer that can be used to get/choose EGLConfigs. 261 * The contents of the IntBuffer will be the sum of the source 262 * LWJGL attributes and the user-defined attributes from this 263 * PixelFormat's configuration. 264 * <p/> 265 * The source LWJGL attributes should not contain the EGL_SURFACE_TYPE 266 * attirube, or any attributes that are handled by PixelFormat. 267 * <p/> 268 * Attributes that correspond to EGL extensions will be checked 269 * against the extensions supported in the specified EGLDisplay. 270 * Attributes that correspond to unsupported extensions will not 271 * be included in the final EGLConfig query. 272 * 273 * @param display the EGL display from which the EGLConfig is going to be retrieved 274 * @param lwjglAttribs the LWJGL attributes 275 * 276 * @return the IntBuffer 277 */ getAttribBuffer(final EGLDisplay display, int surfaceType, final int[] lwjglAttribs)278 public IntBuffer getAttribBuffer(final EGLDisplay display, int surfaceType, final int[] lwjglAttribs) { 279 // Create a copy of the configuration attributes 280 Set<Attrib> keys = new HashSet<Attrib>(config.keySet()); 281 282 // Handle surface type bits 283 if ( keys.contains(MULTISAMPLE_RESOLVE) ) { 284 if ( display.getMajorVersion() == 1 && display.getMinorVersion() < 4 ) 285 keys.remove(MULTISAMPLE_RESOLVE); 286 else if ( getAttrib(MULTISAMPLE_RESOLVE) == EGL_MULTISAMPLE_RESOLVE_BOX ) 287 surfaceType |= EGL_MULTISAMPLE_RESOLVE_BOX_BIT; 288 } 289 290 if ( keys.contains(SWAP_BEHAVIOR) ) { 291 if ( display.getMajorVersion() == 1 && display.getMinorVersion() < 4 ) 292 keys.remove(SWAP_BEHAVIOR); 293 else if ( getAttrib(SWAP_BEHAVIOR) == EGL_BUFFER_PRESERVED ) 294 surfaceType |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT; 295 } 296 297 // Check NV_coverage_sample 298 if ( keys.contains(COVERAGE_BUFFERS_NV) && !display.isExtensionSupported("EGL_NV_coverage_sample") ) { 299 keys.remove(COVERAGE_BUFFERS_NV); 300 keys.remove(COVERAGE_SAMPLES_NV); 301 } 302 303 // Check NV_depth_nonlinear 304 if ( keys.contains(DEPTH_ENCODING_NONLINEAR_NV) && !display.isExtensionSupported("EGL_NV_depth_nonlinear") ) 305 keys.remove(DEPTH_ENCODING_NONLINEAR_NV); 306 307 // Create IntBuffer and insert the attributes 308 final IntBuffer attribs = BufferUtils.createIntBuffer( 309 2 // SURFACE_TYPE 310 + lwjglAttribs.length // Source LWJGL attributes 311 + (keys.size() * 2) // PixelFormat attributes 312 + 1 // Termination 313 ); 314 315 attribs.put(EGL_SURFACE_TYPE).put(surfaceType); 316 attribs.put(lwjglAttribs); 317 318 for ( Attrib key : keys ) { 319 if ( !key.isSurfaceAttrib() ) 320 attribs.put(key.eglAttrib).put(config.get(key)); 321 } 322 323 // Finish the attribute list 324 attribs.put(EGL_NONE); 325 attribs.flip(); 326 327 return attribs; 328 } 329 330 /** 331 * Returns true if the requested attribute matches the attribute in the specified EGL config. 332 * 333 * @param attrib the requested attribute 334 * @param config the EGL config 335 * 336 * @return true if the two attributes match 337 * 338 * @throws org.lwjgl.LWJGLException if an EGL error occurs 339 */ matches(final Attrib attrib, final EGLConfig config)340 private boolean matches(final Attrib attrib, final EGLConfig config) throws LWJGLException { 341 return getAttrib(attrib) == config.getAttribute(attrib.getEGLAttrib()); 342 } 343 344 /** 345 * Returns true if the requested attribute matches the attribute in the specified EGL config. 346 * If the requested attribute is equal to 1, then it will match with any EGL config attribute 347 * that is greater than 0. 348 * 349 * @param attrib the requested attribute 350 * @param config the EGL config 351 * 352 * @return true if the two attributes match 353 * 354 * @throws org.lwjgl.LWJGLException if an EGL error occurs 355 */ matchesNonZero(final Attrib attrib, final EGLConfig config)356 private boolean matchesNonZero(final Attrib attrib, final EGLConfig config) throws LWJGLException { 357 final int reqValue = getAttrib(attrib); 358 final int cfgValue = config.getAttribute(attrib.getEGLAttrib()); 359 360 return reqValue == cfgValue || (reqValue == 1 && cfgValue > 0); 361 } 362 363 /** 364 * Returns the EGL config from the specified array that best matches this PixelFormat. 365 * 366 * @param configs the EGL configs 367 * 368 * @return the best match 369 */ getBestMatch(final EGLConfig[] configs)370 public EGLConfig getBestMatch(final EGLConfig[] configs) throws LWJGLException { 371 if ( configs == null || configs.length == 0 ) 372 throw new IllegalArgumentException("No EGLConfigs specified."); 373 374 if ( configs.length == 1 ) 375 return configs[0]; 376 377 /*System.out.println("\nASKED FOR:"); 378 for ( Attrib attrib : config.keySet() ) { 379 System.out.println("EGL_" + attrib.name() + ": " + getAttrib(attrib)); 380 } 381 382 for ( EGLConfig config : configs ) { 383 if ( config == null ) 384 continue; 385 386 System.out.println("\n----"); 387 System.out.println(config); 388 }*/ 389 390 for ( EGLConfig config : configs ) { 391 if ( config == null ) 392 continue; 393 394 if ( !(matches(ALPHA_SIZE, config) && matchesNonZero(DEPTH_SIZE, config) && matchesNonZero(STENCIL_SIZE, config)) ) 395 continue; 396 397 final int luminance = getAttrib(LUMINANCE_SIZE); 398 if ( 0 < luminance && !matches(LUMINANCE_SIZE, config) ) 399 continue; 400 401 if ( luminance == 0 && !(matches(RED_SIZE, config) && matches(GREEN_SIZE, config) && matches(BLUE_SIZE, config)) ) 402 continue; 403 404 if ( !(matches(SAMPLE_BUFFERS, config) && matches(SAMPLES, config)) ) 405 continue; 406 407 // TODO: Add more? NV's Tegra SDK checks a hardcoded 5 value for COVERAGE_SAMPLES_NV (nv_main.c, line: 1823) 408 409 return config; 410 } 411 412 // No match found, use the one recommended by the EGL implementation. 413 LWJGLUtil.log("Could not find an exact EGLConfig match for the PixelFormat requested, using first returned."); 414 return configs[0]; 415 } 416 417 /** 418 * Applies this PixelFormat's surface attributes to the specified EGL surface. 419 * 420 * @param surface the EGL surface 421 */ setSurfaceAttribs(final EGLSurface surface)422 public void setSurfaceAttribs(final EGLSurface surface) throws LWJGLException { 423 setSurfaceAttrib(surface, SWAP_BEHAVIOR); 424 setSurfaceAttrib(surface, MULTISAMPLE_RESOLVE); 425 } 426 setSurfaceAttrib(final EGLSurface surface, final Attrib attrib)427 private void setSurfaceAttrib(final EGLSurface surface, final Attrib attrib) throws LWJGLException { 428 final int value = getAttrib(attrib); 429 if ( value != attrib.getDefaultValue() ) 430 surface.setAttribute(attrib.getEGLAttrib(), value); 431 } 432 433 /** 434 * Returns the value of the specified attribute. 435 * 436 * @param attrib the attribute to retrieve 437 * 438 * @return the attribute's value 439 */ getAttrib(final Attrib attrib)440 public int getAttrib(final Attrib attrib) { 441 final Integer value = config.get(attrib); 442 if ( value == null ) 443 return attrib.defaultValue; 444 445 return value; 446 } 447 448 /* ----------------------------------------- 449 CORE ATTRIBUTES 450 ----------------------------------------- */ 451 452 /** 453 * Returns a new PixelFormat with the specified RGB sizes. 454 * 455 * @param rgb the new EGL_RED_SIZE, EGL_GREEN_SIZE and EGL_BLUE_SIZE 456 * 457 * @return the new PixelFormat 458 * 459 * @see #withRGBSize(int, int, int) 460 */ withRGBSize(final int rgb)461 public PixelFormat withRGBSize(final int rgb) { 462 return withRGBSize(rgb, rgb, rgb); 463 } 464 465 /** 466 * Returns a new PixelFormat with the specified EGL_RED_SIZE, EGL_GREEN_SIZE and EGL_BLUE_SIZE. 467 * All 3 values must be greater than or equal to 0. If any of the 3 values is greater than 0, 468 * the luminanceSize will be set to 0. 469 * 470 * @param r the new EGL_RED_SIZE 471 * @param g the new EGL_GREEN_SIZE 472 * @param b the new EGL_BLUE_SIZE 473 * 474 * @return the new PixelFormat 475 */ withRGBSize(final int r, final int g, final int b)476 public PixelFormat withRGBSize(final int r, final int g, final int b) { 477 if ( r < 0 || g < 0 || b < 0 ) 478 throw new IllegalArgumentException("Invalid RGB sizes specified: " + r + ", " + g + ", " + b); 479 480 final PixelFormat pf = new PixelFormat(this); 481 pf.setAttrib(RED_SIZE, r); 482 pf.setAttrib(GREEN_SIZE, g); 483 pf.setAttrib(BLUE_SIZE, b); 484 if ( 0 < r || 0 < g || 0 < b ) 485 pf.setAttrib(LUMINANCE_SIZE, 0); 486 return pf; 487 } 488 489 /** 490 * Returns a new PixelFormat with the specified EGL_ALPHA_SIZE. 491 * The alphaSize value must be greater than or equal to 0. 492 * 493 * @param alphaSize the new EGL_ALPHA_SIZE 494 * 495 * @return the new PixelFormat 496 */ withAlphaSize(final int alphaSize)497 public PixelFormat withAlphaSize(final int alphaSize) { 498 if ( alphaSize < 0 ) 499 throw new IllegalArgumentException("Invalid EGL_ALPHA_SIZE specified: " + alphaSize); 500 501 final PixelFormat pf = new PixelFormat(this); 502 pf.setAttrib(ALPHA_SIZE, alphaSize); 503 return pf; 504 } 505 506 /** 507 * Returns a new PixelFormat with the specified EGL_LUMINANCE_SIZE. 508 * The luminanceSize value must be greater than or equal to 0. If 509 * luminanceSize is greater than 0, the RGB sizes will be set to 0. 510 * 511 * @param luminanceSize the new EGL_LUMINANCE_SIZE 512 * 513 * @return the new PixelFormat 514 */ withLuminanceSize(final int luminanceSize)515 public PixelFormat withLuminanceSize(final int luminanceSize) { 516 if ( luminanceSize < 0 ) 517 throw new IllegalArgumentException("Invalid EGL_LUMINANCE_SIZE specified: " + luminanceSize); 518 519 final PixelFormat pf = new PixelFormat(this); 520 pf.setAttrib(LUMINANCE_SIZE, luminanceSize); 521 if ( 0 < luminanceSize ) { 522 pf.setAttrib(RED_SIZE, 0); 523 pf.setAttrib(GREEN_SIZE, 0); 524 pf.setAttrib(BLUE_SIZE, 0); 525 } 526 return pf; 527 } 528 529 /** 530 * Returns a new PixelFormat with the specified EGL_DEPTH_SIZE. 531 * The depthSize value must be greater than or equal to 0. 532 * Values greater than 24 are not recommended. 533 * 534 * @param depthSize the new EGL_DEPTH_SIZE 535 * 536 * @return the new PixelFormat 537 */ withDepthSize(final int depthSize)538 public PixelFormat withDepthSize(final int depthSize) { 539 if ( depthSize < 0 ) 540 throw new IllegalArgumentException("Invalid EGL_DEPTH_SIZE specified: " + depthSize); 541 542 final PixelFormat pf = new PixelFormat(this); 543 pf.setAttrib(DEPTH_SIZE, depthSize); 544 return pf; 545 } 546 547 /** 548 * Returns a new PixelFormat with the specified EGL_STENCIL_SIZE. 549 * The stencilSize value must be greater than or equal to 0. 550 * Values greater than 8 are not recommended. 551 * 552 * @param stencilSize the new EGL_STENCIL_SIZE 553 * 554 * @return the new PixelFormat 555 */ withStencilSize(final int stencilSize)556 public PixelFormat withStencilSize(final int stencilSize) { 557 if ( stencilSize < 0 ) 558 throw new IllegalArgumentException("Invalid EGL_STENCIL_SIZE specified: " + stencilSize); 559 560 final PixelFormat pf = new PixelFormat(this); 561 pf.setAttrib(STENCIL_SIZE, stencilSize); 562 return pf; 563 } 564 565 /** 566 * Returns a new PixelFormat with the specified EGL_MIN_SWAP_INTERVAL. 567 * The minSwapInterval value must be between 0 and this PixelFormat's EGL_MAX_SWAP_INTERVAL. 568 * 569 * @param minSwapInterval the new EGL_MIN_SWAP_INTERVAL value 570 * 571 * @return the new PixelFormat 572 */ withMinSwapInterval(final int minSwapInterval)573 public PixelFormat withMinSwapInterval(final int minSwapInterval) { 574 final int maxSwapInterval = getAttrib(MAX_SWAP_INTERVAL); 575 if ( minSwapInterval != EGL_DONT_CARE && (minSwapInterval < 0 || (maxSwapInterval != EGL_DONT_CARE && maxSwapInterval < minSwapInterval)) ) 576 throw new IllegalArgumentException("Invalid EGL_MIN_SWAP_INTERVAL specified: " + minSwapInterval); 577 578 final PixelFormat pf = new PixelFormat(this); 579 pf.setAttrib(MIN_SWAP_INTERVAL, minSwapInterval); 580 return pf; 581 } 582 583 /** 584 * Returns a new PixelFormat with the specified EGL_MAX_SWAP_INTERVAL. 585 * The maxSwapInterval value must be greater than or equal to this PixelFormat's EGL_MIN_SWAP_INTERVAL. 586 * 587 * @param maxSwapInterval the new EGL_MAX_SWAP_INTERVAL value 588 * 589 * @return the new PixelFormat 590 */ withMaxSwapInterval(final int maxSwapInterval)591 public PixelFormat withMaxSwapInterval(final int maxSwapInterval) { 592 if ( maxSwapInterval < getAttrib(MIN_SWAP_INTERVAL) ) 593 throw new IllegalArgumentException("Invalid EGL_MAX_SWAP_INTERVAL specified: " + maxSwapInterval); 594 595 final PixelFormat pf = new PixelFormat(this); 596 pf.setAttrib(MAX_SWAP_INTERVAL, maxSwapInterval); 597 return pf; 598 } 599 600 /** 601 * Returns a new PixelFormat with the specified number of EGL_SAMPLES. 602 * The samples value must be either 0 or greater than or equal to 2. The related 603 * EGL_SAMPLE_BUFFERS value will become 0 if samples is 0, or 1 if samples 604 * is greater than or equal to 2. 605 * 606 * @param samples the new EGL_SAMPLES value 607 * 608 * @return the new PixelFormat 609 */ withSamples(final int samples)610 public PixelFormat withSamples(final int samples) { 611 if ( samples != 0 && samples < 2 ) 612 throw new IllegalArgumentException("Invalid number of EGL_SAMPLES specified: " + samples); 613 614 final PixelFormat pf = new PixelFormat(this); 615 pf.setAttrib(SAMPLES, samples); 616 pf.setAttrib(SAMPLE_BUFFERS, samples == 0 ? 0 : 1); 617 return pf; 618 } 619 maxValue(final int bits)620 private static int maxValue(final int bits) { 621 return (2 << bits) - 1; 622 } 623 624 /** 625 * Returns a new PixelFormat with the specified EGL_TRANSPARENT_TYPE and 626 * the specified transparent RGB values. The transparentType must be 627 * either EGL_NONE or EGL_TRANSPARENT_RGB. When it is EGL_NONE, the RGB 628 * values are set to zero and ignored. When it is EGL_TRANSPARENT_RGB, 629 * the RGB values must be between 0 and 2^rgbSize - 1. 630 * 631 * @param transparentType the new EGL_TRANSPARENT_TYPE value 632 * @param r the new EGL_TRANSPARENT_RED_VALUE 633 * @param g the new EGL_TRANSPARENT_GREEN_VALUE 634 * @param b the new EGL_TRANSPARENT_BLUE_VALUE 635 * 636 * @return the new PixelFormat 637 */ withTransparentType(final int transparentType, int r, int g, int b)638 public PixelFormat withTransparentType(final int transparentType, int r, int g, int b) { 639 if ( transparentType == EGL_TRANSPARENT_RGB ) { 640 final int redSize = getAttrib(RED_SIZE); 641 final int greenSize = getAttrib(GREEN_SIZE); 642 final int blueSize = getAttrib(BLUE_SIZE); 643 if ( r < 0 || (0 < redSize && maxValue(redSize) < r) ) 644 throw new IllegalArgumentException("Invalid EGL_TRANSPARENT_RED_VALUE specified: " + r); 645 646 if ( r < 0 || (0 < greenSize && maxValue(greenSize) < g) ) 647 throw new IllegalArgumentException("Invalid EGL_TRANSPARENT_GREEN_VALUE specified: " + g); 648 649 if ( r < 0 || (0 < blueSize && maxValue(blueSize) < b) ) 650 throw new IllegalArgumentException("Invalid EGL_TRANSPARENT_BLUE_VALUE specified: " + b); 651 } else if ( transparentType != EGL_NONE ) 652 throw new IllegalArgumentException("Invalid EGL_TRANSPARENT_TYPE specified: " + transparentType); 653 else 654 r = g = b = EGL_DONT_CARE; 655 656 final PixelFormat pf = new PixelFormat(this); 657 658 pf.setAttrib(TRANSPARENT_TYPE, transparentType); 659 660 pf.setAttrib(TRANSPARENT_RED_VALUE, r); 661 pf.setAttrib(TRANSPARENT_GREEN_VALUE, g); 662 pf.setAttrib(TRANSPARENT_BLUE_VALUE, b); 663 664 return pf; 665 } 666 667 /* ----------------------------------------- 668 SURFACE ATTRIBUTES 669 ----------------------------------------- */ 670 671 /** 672 * Returns a new PixelFormat with the specified EGL_MULTISAMPLE_RESOLVE value. 673 * Valid values for multisampleResolve are EGL_MULTISAMPLE_RESOLVE_DEFAULT 674 * and EGL_MULTISAMPLE_RESOLVE_BOX. 675 * <p/> 676 * An IllegalStateException will be thrown if EGL_SAMPLES has not been previously defined 677 * to be greater than or equal to 2. 678 * 679 * @param multisampleResolve the new EGL_MULTISAMPLE_RESOLVE value 680 * 681 * @return the new PixelFormat 682 */ withMultisampleResolve(final int multisampleResolve)683 public PixelFormat withMultisampleResolve(final int multisampleResolve) { 684 if ( multisampleResolve != EGL_MULTISAMPLE_RESOLVE_DEFAULT && multisampleResolve != EGL_MULTISAMPLE_RESOLVE_BOX ) 685 throw new IllegalArgumentException("Invalid EGL_MULTISAMPLE_RESOLVE value specified: " + multisampleResolve); 686 687 if ( getAttrib(SAMPLE_BUFFERS) == 0 ) 688 throw new IllegalStateException("An EGL_MULTISAMPLE_RESOLVE value cannot be specified unless EGL_SAMPLE_BUFFERS is 1."); 689 690 final PixelFormat pf = new PixelFormat(this); 691 pf.setAttrib(MULTISAMPLE_RESOLVE, multisampleResolve); 692 return pf; 693 } 694 695 /** 696 * Returns a new PixelFormat with the specified EGL_SWAP_BEHAVIOR value. 697 * Valid values for swapBehavior are EGL_DONT_CARE, EGL_BUFFER_PRESERVED 698 * and EGL_BUFFER_DESTROYED. 699 * 700 * @param swapBehavior the new EGL_SWAP_BEHAVIOR value 701 * 702 * @return the new PixelFormat 703 */ withSwapBehavior(final int swapBehavior)704 public PixelFormat withSwapBehavior(final int swapBehavior) { 705 switch ( swapBehavior ) { 706 case EGL_DONT_CARE: 707 case EGL_BUFFER_PRESERVED: 708 case EGL_BUFFER_DESTROYED: 709 break; 710 default: 711 throw new IllegalArgumentException("Invalid EGL_SWAP_BEHAVIOR value specified: " + swapBehavior); 712 } 713 714 final PixelFormat pf = new PixelFormat(this); 715 pf.setAttrib(SWAP_BEHAVIOR, swapBehavior); 716 return pf; 717 } 718 719 /* ----------------------------------------- 720 EXTENSION ATTRIBUTES 721 ----------------------------------------- */ 722 723 /** 724 * Returns a new PixelFormat with the specified number of EGL_COVERAGE_SAMPLES_NV. 725 * The samples value must be greater than or equal to 0. The related 726 * EGL_COVERAGE_BUFFERS_NV value will become 0 if samples is 0, or 1 if samples 727 * is greater than 0. 728 * 729 * @param samples the new EGL_SAMPLES value 730 * 731 * @return the new PixelFormat 732 */ withCoverageSamplesNV(final int samples)733 public PixelFormat withCoverageSamplesNV(final int samples) { 734 if ( samples < 0 ) 735 throw new IllegalArgumentException("Invalid number of EGL_COVERAGE_SAMPLES_NV specified: " + samples); 736 737 final PixelFormat pf = new PixelFormat(this); 738 pf.setAttrib(COVERAGE_SAMPLES_NV, samples); 739 pf.setAttrib(COVERAGE_BUFFERS_NV, samples == 0 ? 0 : 1); 740 return pf; 741 } 742 743 /** 744 * Returns a new PixelFormat with the specified EGL_DEPTH_ENCODING_NONLINEAR_NV. 745 * Valid values for depthEncoding are EGL_DONT_CARE, EGL_DEPTH_ENCODING_NONE_NV 746 * and EGL_DEPTH_ENCODING_NONLINEAR_NV. 747 * 748 * @param depthEncoding the new EGL_DEPTH_ENCODING_NONLINEAR_NV value 749 * 750 * @return the new PixelFormat 751 */ withDepthEncodingNonlinearNV(final int depthEncoding)752 public PixelFormat withDepthEncodingNonlinearNV(final int depthEncoding) { 753 switch ( depthEncoding ) { 754 case EGL_DONT_CARE: 755 case EGL_DEPTH_ENCODING_NONE_NV: 756 case EGL_DEPTH_ENCODING_NONLINEAR_NV: 757 break; 758 default: 759 throw new IllegalArgumentException("Invalid EGL_DEPTH_ENCODING_NONLINEAR_NV value specified: " + depthEncoding); 760 } 761 762 final PixelFormat pf = new PixelFormat(this); 763 pf.setAttrib(DEPTH_ENCODING_NONLINEAR_NV, depthEncoding); 764 return pf; 765 } 766 767 }