1 /*
2  * Copyright (c) 2002-2008 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.opengl;
33 
34 /**
35  * This class describes pixel format properties for an OpenGL context. Instances
36  * of this class is used as arguments to Display.create(), Pbuffer.create() and
37  * AWTGLCanvas, to indicate minimum required properties.
38  * <p/>
39  * Instants of this class are immutable. An example of the expected way to set
40  * the PixelFormat property values is the following:
41  * <code>PixelFormat pf = new PixelFormat().withDepthBits(24).withSamples(4).withSRGB(true);</code>
42  * <p/>
43  * WARNING: Some pixel formats are known to cause troubles on certain buggy drivers.
44  * Example: Under Windows, specifying samples != 0 will enable the ARB
45  * pixel format selection path, which could trigger a crash.
46  *
47  * @author elias_naur@sourceforge.net
48  * @version $Revision$
49  */
50 public final class PixelFormat implements PixelFormatLWJGL {
51 
52 	/**
53 	 * The number of bits per pixel, exluding alpha.
54 	 * This parameter is ignored in Display.create().
55 	 */
56 	private int bpp;
57 	/** The number of alpha bits. */
58 	private int alpha;
59 	/** The number of depth buffer bits */
60 	private int depth;
61 	/** The number of stencil bits */
62 	private int stencil;
63 	/**
64 	 * The number of samples to use in anti-aliasing.
65 	 * 0 means that anti-aliasing is disabled.
66 	 */
67 	private int samples;
68 	/**
69 	 * The number of COLOR_SAMPLES_NV to use for Coverage Sample Anti-aliasing (CSAA).
70 	 * When this number is greater than 0, the {@code samples} property will be treated
71 	 * as if it were the COVERAGE_SAMPLES_NV property.
72 	 * <p/>
73 	 * This property is currently a no-op for the MacOS implementation.
74 	 */
75 	private int colorSamples;
76 	/** The number of auxiliary buffers */
77 	private int num_aux_buffers;
78 	/** The number of bits per pixel in the accumulation buffer */
79 	private int accum_bpp;
80 	/** The number of alpha bits in the accumulation buffer */
81 	private int accum_alpha;
82 	/** Whether this format requires a stereo buffer */
83 	private boolean stereo;
84 	/** Whether this format specifies a floating point format */
85 	private boolean floating_point;
86 	/**
87 	 * Whether this format specifies a packed floating point format (32 bit unsigned - R11F_G11F_B10F)
88 	 * This property is currently a no-op for the MacOS implementation.
89 	 */
90 	private boolean floating_point_packed;
91 	/**
92 	 * Whether this format specifies an sRGB format
93 	 * This property is currently a no-op for the MacOS implementation.
94 	 */
95 	private boolean sRGB;
96 
97 	/**
98 	 * Default pixel format is minimum 8 bits depth, and no alpha
99 	 * nor stencil requirements.
100 	 */
PixelFormat()101 	public PixelFormat() {
102 		this(0, 8, 0);
103 	}
104 
PixelFormat(int alpha, int depth, int stencil)105 	public PixelFormat(int alpha, int depth, int stencil) {
106 		this(alpha, depth, stencil, 0);
107 	}
108 
PixelFormat(int alpha, int depth, int stencil, int samples)109 	public PixelFormat(int alpha, int depth, int stencil, int samples) {
110 		this(0, alpha, depth, stencil, samples);
111 	}
112 
PixelFormat(int bpp, int alpha, int depth, int stencil, int samples)113 	public PixelFormat(int bpp, int alpha, int depth, int stencil, int samples) {
114 		this(bpp, alpha, depth, stencil, samples, 0, 0, 0, false);
115 	}
116 
PixelFormat(int bpp, int alpha, int depth, int stencil, int samples, int num_aux_buffers, int accum_bpp, int accum_alpha, boolean stereo)117 	public PixelFormat(int bpp, int alpha, int depth, int stencil, int samples, int num_aux_buffers, int accum_bpp, int accum_alpha, boolean stereo) {
118 		this(bpp, alpha, depth, stencil, samples, num_aux_buffers, accum_bpp, accum_alpha, stereo, false);
119 	}
120 
PixelFormat(int bpp, int alpha, int depth, int stencil, int samples, int num_aux_buffers, int accum_bpp, int accum_alpha, boolean stereo, boolean floating_point)121 	public PixelFormat(int bpp, int alpha, int depth, int stencil, int samples, int num_aux_buffers, int accum_bpp, int accum_alpha, boolean stereo, boolean floating_point) {
122 		this.bpp = bpp;
123 		this.alpha = alpha;
124 		this.depth = depth;
125 		this.stencil = stencil;
126 
127 		this.samples = samples;
128 
129 		this.num_aux_buffers = num_aux_buffers;
130 
131 		this.accum_bpp = accum_bpp;
132 		this.accum_alpha = accum_alpha;
133 
134 		this.stereo = stereo;
135 
136 		this.floating_point = floating_point;
137 		this.floating_point_packed = false;
138 		this.sRGB = false;
139 	}
140 
PixelFormat(final PixelFormat pf)141 	private PixelFormat(final PixelFormat pf) {
142 		this.bpp = pf.bpp;
143 		this.alpha = pf.alpha;
144 		this.depth = pf.depth;
145 		this.stencil = pf.stencil;
146 
147 		this.samples = pf.samples;
148 		this.colorSamples = pf.colorSamples;
149 
150 		this.num_aux_buffers = pf.num_aux_buffers;
151 
152 		this.accum_bpp = pf.accum_bpp;
153 		this.accum_alpha = pf.accum_alpha;
154 
155 		this.stereo = pf.stereo;
156 
157 		this.floating_point = pf.floating_point;
158 		this.floating_point_packed = pf.floating_point_packed;
159 		this.sRGB = pf.sRGB;
160 	}
161 
getBitsPerPixel()162 	public int getBitsPerPixel() {
163 		return bpp;
164 	}
165 
166 	/**
167 	 * Returns a new PixelFormat object with the same properties as this PixelFormat and the new bits per pixel value.
168 	 *
169 	 * @param bpp the new bits per pixel value.
170 	 *
171 	 * @return the new PixelFormat
172 	 */
withBitsPerPixel(final int bpp)173 	public PixelFormat withBitsPerPixel(final int bpp) {
174 		if ( bpp < 0 )
175 			throw new IllegalArgumentException("Invalid number of bits per pixel specified: " + bpp);
176 
177 		final PixelFormat pf = new PixelFormat(this);
178 		pf.bpp = bpp;
179 		return pf;
180 	}
181 
getAlphaBits()182 	public int getAlphaBits() {
183 		return alpha;
184 	}
185 
186 	/**
187 	 * Returns a new PixelFormat object with the same properties as this PixelFormat and the new alpha bits value.
188 	 *
189 	 * @param alpha the new alpha bits value.
190 	 *
191 	 * @return the new PixelFormat
192 	 */
withAlphaBits(final int alpha)193 	public PixelFormat withAlphaBits(final int alpha) {
194 		if ( alpha < 0 )
195 			throw new IllegalArgumentException("Invalid number of alpha bits specified: " + alpha);
196 
197 		final PixelFormat pf = new PixelFormat(this);
198 		pf.alpha = alpha;
199 		return pf;
200 	}
201 
getDepthBits()202 	public int getDepthBits() {
203 		return depth;
204 	}
205 
206 	/**
207 	 * Returns a new PixelFormat object with the same properties as this PixelFormat and the new depth bits value.
208 	 *
209 	 * @param depth the new depth bits value.
210 	 *
211 	 * @return the new PixelFormat
212 	 */
withDepthBits(final int depth)213 	public PixelFormat withDepthBits(final int depth) {
214 		if ( depth < 0 )
215 			throw new IllegalArgumentException("Invalid number of depth bits specified: " + depth);
216 
217 		final PixelFormat pf = new PixelFormat(this);
218 		pf.depth = depth;
219 		return pf;
220 	}
221 
getStencilBits()222 	public int getStencilBits() {
223 		return stencil;
224 	}
225 
226 	/**
227 	 * Returns a new PixelFormat object with the same properties as this PixelFormat and the new stencil bits value.
228 	 *
229 	 * @param stencil the new stencil bits value.
230 	 *
231 	 * @return the new PixelFormat
232 	 */
withStencilBits(final int stencil)233 	public PixelFormat withStencilBits(final int stencil) {
234 		if ( stencil < 0 )
235 			throw new IllegalArgumentException("Invalid number of stencil bits specified: " + stencil);
236 
237 		final PixelFormat pf = new PixelFormat(this);
238 		pf.stencil = stencil;
239 		return pf;
240 	}
241 
getSamples()242 	public int getSamples() {
243 		return samples;
244 	}
245 
246 	/**
247 	 * Returns a new PixelFormat object with the same properties as this PixelFormat and the new samples value.
248 	 *
249 	 * @param samples the new samples value.
250 	 *
251 	 * @return the new PixelFormat
252 	 */
withSamples(final int samples)253 	public PixelFormat withSamples(final int samples) {
254 		if ( samples < 0 )
255 			throw new IllegalArgumentException("Invalid number of samples specified: " + samples);
256 
257 		final PixelFormat pf = new PixelFormat(this);
258 		pf.samples = samples;
259 		return pf;
260 	}
261 
262 	/**
263 	 * Returns a new PixelFormat object with the same properties as this PixelFormat and the new color samples values.
264 	 * A value greater than 0 is valid only if the {@code samples} property is also greater than 0. Additionally, the
265 	 * color samples value needs to be lower than or equal to the {@code samples} property.
266 	 *
267 	 * @param colorSamples    the new color samples value.
268 	 *
269 	 * @return the new PixelFormat
270 	 */
withCoverageSamples(final int colorSamples)271 	public PixelFormat withCoverageSamples(final int colorSamples) {
272 		return withCoverageSamples(colorSamples, samples);
273 	}
274 
275 	/**
276 	 * Returns a new PixelFormat object with the same properties as this PixelFormat and the new color samples
277 	 * and coverage samples values.
278 	 *
279 	 * @param colorSamples    the new color samples value. This value must be lower than or equal to the coverage samples value.
280 	 * @param coverageSamples the new coverage samples value.
281 	 *
282 	 * @return the new PixelFormat
283 	 */
withCoverageSamples(final int colorSamples, final int coverageSamples)284 	public PixelFormat withCoverageSamples(final int colorSamples, final int coverageSamples) {
285 		if ( coverageSamples < 0 || colorSamples < 0 || (coverageSamples == 0 && 0 < colorSamples) || coverageSamples < colorSamples  )
286 			throw new IllegalArgumentException("Invalid number of coverage samples specified: " + coverageSamples + " - " + colorSamples);
287 
288 		final PixelFormat pf = new PixelFormat(this);
289 		pf.samples = coverageSamples;
290 		pf.colorSamples = colorSamples;
291 		return pf;
292 	}
293 
getAuxBuffers()294 	public int getAuxBuffers() {
295 		return num_aux_buffers;
296 	}
297 
298 	/**
299 	 * Returns a new PixelFormat object with the same properties as this PixelFormat and the new auxiliary buffers value.
300 	 *
301 	 * @param num_aux_buffers the new auxiliary buffers value.
302 	 *
303 	 * @return the new PixelFormat
304 	 */
withAuxBuffers(final int num_aux_buffers)305 	public PixelFormat withAuxBuffers(final int num_aux_buffers) {
306 		if ( num_aux_buffers < 0 )
307 			throw new IllegalArgumentException("Invalid number of auxiliary buffers specified: " + num_aux_buffers);
308 
309 		final PixelFormat pf = new PixelFormat(this);
310 		pf.num_aux_buffers = num_aux_buffers;
311 		return pf;
312 	}
313 
getAccumulationBitsPerPixel()314 	public int getAccumulationBitsPerPixel() {
315 		return accum_bpp;
316 	}
317 
318 	/**
319 	 * Returns a new PixelFormat object with the same properties as this PixelFormat and the new bits per pixel in the accumulation buffer value.
320 	 *
321 	 * @param accum_bpp the new bits per pixel in the accumulation buffer value.
322 	 *
323 	 * @return the new PixelFormat
324 	 */
withAccumulationBitsPerPixel(final int accum_bpp)325 	public PixelFormat withAccumulationBitsPerPixel(final int accum_bpp) {
326 		if ( accum_bpp < 0 )
327 			throw new IllegalArgumentException("Invalid number of bits per pixel in the accumulation buffer specified: " + accum_bpp);
328 
329 		final PixelFormat pf = new PixelFormat(this);
330 		pf.accum_bpp = accum_bpp;
331 		return pf;
332 	}
333 
getAccumulationAlpha()334 	public int getAccumulationAlpha() {
335 		return accum_alpha;
336 	}
337 
338 	/**
339 	 * Returns a new PixelFormat object with the same properties as this PixelFormat and the new alpha bits in the accumulation buffer value.
340 	 *
341 	 * @param accum_alpha the new alpha bits in the accumulation buffer value.
342 	 *
343 	 * @return the new PixelFormat
344 	 */
withAccumulationAlpha(final int accum_alpha)345 	public PixelFormat withAccumulationAlpha(final int accum_alpha) {
346 		if ( accum_alpha < 0 )
347 			throw new IllegalArgumentException("Invalid number of alpha bits in the accumulation buffer specified: " + accum_alpha);
348 
349 		final PixelFormat pf = new PixelFormat(this);
350 		pf.accum_alpha = accum_alpha;
351 		return pf;
352 	}
353 
isStereo()354 	public boolean isStereo() {
355 		return stereo;
356 	}
357 
358 	/**
359 	 * Returns a new PixelFormat object with the same properties as this PixelFormat and the new stereo value.
360 	 *
361 	 * @param stereo the new stereo value.
362 	 *
363 	 * @return the new PixelFormat
364 	 */
withStereo(final boolean stereo)365 	public PixelFormat withStereo(final boolean stereo) {
366 		final PixelFormat pf = new PixelFormat(this);
367 		pf.stereo = stereo;
368 		return pf;
369 	}
370 
isFloatingPoint()371 	public boolean isFloatingPoint() {
372 		return floating_point;
373 	}
374 
375 	/**
376 	 * Returns a new PixelFormat object with the same properties as this PixelFormat and the new floating point value.
377 	 * If floating_point is true, floating_point_packed will be reset to false.
378 	 *
379 	 * @param floating_point the new floating point value.
380 	 *
381 	 * @return the new PixelFormat
382 	 */
withFloatingPoint(final boolean floating_point)383 	public PixelFormat withFloatingPoint(final boolean floating_point) {
384 		final PixelFormat pf = new PixelFormat(this);
385 		pf.floating_point = floating_point;
386 		if ( floating_point )
387 			pf.floating_point_packed = false;
388 		return pf;
389 	}
390 
391 	/**
392 	 * Returns a new PixelFormat object with the same properties as this PixelFormat and the new packed floating point value.
393 	 * If floating_point_packed is true, floating_point will be reset to false.
394 	 *
395 	 * @param floating_point_packed the new packed floating point value.
396 	 *
397 	 * @return the new PixelFormat
398 	 */
withFloatingPointPacked(final boolean floating_point_packed)399 	public PixelFormat withFloatingPointPacked(final boolean floating_point_packed) {
400 		final PixelFormat pf = new PixelFormat(this);
401 		pf.floating_point_packed = floating_point_packed;
402 		if ( floating_point_packed )
403 			pf.floating_point = false;
404 		return pf;
405 	}
406 
isSRGB()407 	public boolean isSRGB() {
408 		return sRGB;
409 	}
410 
411 	/**
412 	 * Returns a new PixelFormat object with the same properties as this PixelFormat and the new sRGB value.
413 	 *
414 	 * @param sRGB the new floating point value.
415 	 *
416 	 * @return the new PixelFormat
417 	 */
withSRGB(final boolean sRGB)418 	public PixelFormat withSRGB(final boolean sRGB) {
419 		final PixelFormat pf = new PixelFormat(this);
420 		pf.sRGB = sRGB;
421 		return pf;
422 	}
423 
424 }