JOGL v2.6.0-rc-20250712
JOGL, High-Performance Graphics Binding for Java™ (public API).
RenderState.java
Go to the documentation of this file.
1/**
2 * Copyright 2011-2024 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28package com.jogamp.graph.curve.opengl;
29
30import java.nio.FloatBuffer;
31
32import com.jogamp.opengl.GL;
33import com.jogamp.opengl.GL2ES2;
34import com.jogamp.opengl.GLException;
35import com.jogamp.opengl.GLUniformData;
36
37import jogamp.common.os.PlatformPropsImpl;
38import jogamp.graph.curve.opengl.shader.UniformNames;
39
40import com.jogamp.graph.curve.Region;
41import com.jogamp.math.Vec4f;
42import com.jogamp.math.geom.Frustum;
43import com.jogamp.math.util.PMVMatrix4f;
44import com.jogamp.opengl.util.GLArrayDataWrapper;
45import com.jogamp.opengl.util.glsl.ShaderProgram;
46
47/**
48 * The RenderState is owned by {@link RegionRenderer}.
49 *
50 * It holds rendering state data like {@link PMVMatrix4f}, viewport,
51 * but also the current {@link #getColorStatic(float[]) static color}.
52 */
53public class RenderState {
54 private static final String thisKey = "jogamp.graph.curve.RenderState" ;
55
56 /**
57 * Bitfield hint, {@link #hintBitsSet(int) if set}
58 * stating <i>enabled</i> {@link GL#GL_BLEND}, otherwise <i>disabled</i>.
59 * <p>
60 * Shall be set via {@link #setHintBits(int)} and cleared via {@link #clearHintBits(int)}.
61 * </p>
62 * <p>
63 * If set, {@link GLRegion#draw(GL2ES2, RegionRenderer) GLRegion's draw-method}
64 * will set the proper {@link GL#glBlendFuncSeparate(int, int, int, int) blend-function}
65 * and the clear-color to <i>transparent-black</i> in case of {@link Region#isTwoPass(int) multipass} FBO rendering.
66 * </p>
67 * <p>
68 * Shall be set by custom code, e.g. via {@link RegionRenderer}'s
69 * enable and disable {@link RegionRenderer.GLCallback} as done in
70 * {@link RegionRenderer#defaultBlendEnable} and {@link RegionRenderer#defaultBlendDisable}.
71 * </p>
72 */
73 public static final int BITHINT_BLENDING_ENABLED = 1 << 0 ;
74
75 /**
76 * Bitfield hint, {@link #hintBitsSet(int) if set}
77 * stating globally <i>enabled</i> {@link GL#GL_DEPTH_TEST}, otherwise <i>disabled</i>.
78 * <p>
79 * Shall be set via {@link #setHintBits(int)} and cleared via {@link #clearHintBits(int)}.
80 * </p>
81 * <p>
82 * {@link GLRegion#draw(GL2ES2, RegionRenderer) GLRegion's draw-method}
83 * may toggle depth test, and reset it's state according to this hint.
84 * </p>
85 * <p>
86 * Shall be set by custom code, e.g. after {@link RenderState} or {@link RegionRenderer} construction.
87 * </p>
88 */
89 public static final int BITHINT_GLOBAL_DEPTH_TEST_ENABLED = 1 << 1 ;
90
91 public static final int DEBUG_LINESTRIP = 1 << 0 ;
92
93 public static final RenderState getRenderState(final GL2ES2 gl) {
94 return (RenderState) gl.getContext().getAttachedObject(thisKey);
95 }
96
97 private final int id;
98 private final PMVMatrix4f pmvMatrix;
99 private final float[] weight;
100 private final FloatBuffer weightBuffer;
101 private final float[] colorStatic;
102 private final FloatBuffer colorStaticBuffer;
103 /** Pass2 AA-quality rendering {@value} for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT}. */
104 private int aaQuality;
105 /** Default pass2 AA sample count {@value} for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT}. */
106 private int sampleCount;
107 /** Optional clipping {@link Frustum}, which shall be pre-multiplied with the Mv-matrix. Null if unused. */
108 private final Frustum clipFrustum;
109 private boolean useClipFrustum;
110 private int hintBits;
111 private int debugBits;
112 private ShaderProgram sp;
113
114 private static synchronized int getNextID() {
115 return nextID++;
116 }
117 private static int nextID = 1;
118
119 /**
120 * Representation of {@link RenderState} data per {@link ShaderProgram}
121 * as {@link GLUniformData}.
122 * <p>
123 * FIXME: Utilize 'ARB_Uniform_Buffer_Object' where available!
124 * </p>
125 */
126 public static class ProgramLocal {
130 private int rsId = -1;
131
132 public ProgramLocal() {
133 gcu_PMVMatrix01 = GLUniformData.creatEmptyMatrix(UniformNames.gcu_PMVMatrix01, 4, 4);
134 gcu_Weight = GLUniformData.creatEmptyVector(UniformNames.gcu_Weight, 1);
135 gcu_ColorStatic = GLUniformData.creatEmptyVector(UniformNames.gcu_ColorStatic, 4);
136 }
137
138 public final int getRenderStateId() { return rsId; }
139
140 /**
141 * <p>
142 * Since {@link RenderState} data is being used in multiple
143 * {@link ShaderProgram}s the data must always be written.
144 * </p>
145 * @param gl
146 * @param updateLocation
147 * @param renderModes
148 * @param setPMVMat01 TODO
149 * @param throwOnError TODO
150 * @return true if no error occurred, i.e. all locations found, otherwise false.
151 */
152 public final boolean update(final GL2ES2 gl, final RenderState rs, final boolean updateLocation, final int renderModes,
153 final boolean setPMVMat01, final boolean pass1, final boolean throwOnError) {
154 if( rs.id() != rsId ) {
155 // Assignment of Renderstate buffers to uniforms (no copy, direct reference)
156 gcu_PMVMatrix01.setData(rs.pmvMatrix.getSyncPMv());
157 gcu_Weight.setData(rs.weightBuffer);
158 gcu_ColorStatic.setData(rs.colorStaticBuffer);
159 rsId = rs.id();
160 }
161 boolean res = true;
162 if( null != rs.sp && rs.sp.inUse() ) {
163 if( setPMVMat01 ) {
164 final boolean r0 = rs.updateUniformDataLoc(gl, updateLocation, true, gcu_PMVMatrix01, throwOnError);
165 res = res && r0;
166 }
167 if( pass1 ) {
168 if( Region.hasVariableWeight( renderModes ) ) {
169 final boolean r0 = rs.updateUniformDataLoc(gl, updateLocation, true, gcu_Weight, throwOnError);
170 res = res && r0;
171 }
172 {
173 final boolean r0 = rs.updateUniformDataLoc(gl, updateLocation, true, gcu_ColorStatic, throwOnError);
174 res = res && r0;
175 }
176 }
177 }
178 return res;
179 }
180
181 public StringBuilder toString(StringBuilder sb, final boolean alsoUnlocated) {
182 if(null==sb) {
183 sb = new StringBuilder();
184 }
185 sb.append("ProgramLocal[rsID ").append(rsId).append(PlatformPropsImpl.NEWLINE);
186 // pmvMatrix.toString(sb, "%.2f");
187 sb.append(gcu_PMVMatrix01).append(", ").append(PlatformPropsImpl.NEWLINE);
188 sb.append(gcu_ColorStatic).append(", ");
189 sb.append(gcu_Weight).append("]");
190 return sb;
191 }
192
193 @Override
194 public String toString() {
195 return toString(null, false).toString();
196 }
197 }
198
199 /**
200 * Create a RenderState, a composition of RegionRenderer
201 * @param sharedPMVMatrix optional shared PMVMatrix4f, if null using a local instance
202 */
203 /* pp */ RenderState(final PMVMatrix4f sharedPMVMatrix) {
204 this.id = getNextID();
205 this.pmvMatrix = null != sharedPMVMatrix ? sharedPMVMatrix : new PMVMatrix4f();
206 this.weight = new float[1];
207 this.weightBuffer = FloatBuffer.wrap(weight);
208 this.colorStatic = new float[] { 1, 1, 1, 1 };
209 this.colorStaticBuffer = FloatBuffer.wrap(colorStatic);
210 this.aaQuality = Region.DEFAULT_AA_QUALITY;
211 this.sampleCount = Region.DEFAULT_AA_SAMPLE_COUNT;
212 this.clipFrustum = new Frustum();
213 this.useClipFrustum = false;
214
215 this.hintBits = 0;
216 this.debugBits = 0;
217 this.sp = null;
218 }
219
220 public final int id() { return id; }
221
222 /** Return the current {@link ShaderProgram} */
223 public final ShaderProgram getShaderProgram() { return sp; }
224
225 /** Return whether the current {@link ShaderProgram} is {@link ShaderProgram#inUse() in use}. */
226 public final boolean isShaderProgramInUse() { return null != sp ? sp.inUse() : false; }
227
228 /**
229 * Sets the current {@link ShaderProgram} and enables it.
230 *
231 * If the given {@link ShaderProgram} is not {@link #getShaderProgram() the current}, method returns true, otherwise false.
232 *
233 * @param gl
234 * @param spNext the next current {@link ShaderProgram} to be set and enabled
235 * @return true if a new shader program is being used and hence external uniform-data and -location,
236 * as well as the attribute-location must be updated, otherwise false.
237 */
238 public final boolean setShaderProgram(final GL2ES2 gl, final ShaderProgram spNext) {
239 if( spNext.equals(this.sp) ) {
240 spNext.useProgram(gl, true);
241 return false;
242 }
243 if( null != this.sp ) {
244 this.sp.notifyNotInUse();
245 }
246 this.sp = spNext;
247 spNext.useProgram(gl, true);
248 return true;
249 }
250
251 /** Borrow the current {@link PMVMatrix4f}. */
252 public final PMVMatrix4f getMatrix() { return pmvMatrix; }
253
254 public static boolean isWeightValid(final float v) {
255 return 0.0f <= v && v <= 1.9f ;
256 }
257 public final float getWeight() { return weight[0]; }
258 public final void setWeight(final float v) {
259 if( !isWeightValid(v) ) {
260 throw new IllegalArgumentException("Weight out of range");
261 }
262 weight[0] = v;
263 }
264
265 public final Vec4f getColorStatic(final Vec4f rgbaColor) {
266 return rgbaColor.set(colorStatic);
267 }
268 public final void setColorStatic(final Vec4f rgbaColor){
269 colorStatic[0] = rgbaColor.x();
270 colorStatic[1] = rgbaColor.y();
271 colorStatic[2] = rgbaColor.z();
272 colorStatic[3] = rgbaColor.w();
273 }
274 public final void setColorStatic(final float r, final float g, final float b, final float a){
275 colorStatic[0] = r;
276 colorStatic[1] = g;
277 colorStatic[2] = b;
278 colorStatic[3] = a;
279 }
280
281 /** Sets pass2 AA-quality rendering value clipped to the range [{@link Region#MIN_AA_QUALITY}..{@link Region#MAX_AA_QUALITY}] for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT}. */
282 public final int setAAQuality(final int v) { final int q=Region.clipAAQuality(v); this.aaQuality=q; return q;}
283 /** Returns pass2 AA-quality rendering value for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT}. */
284 public final int getAAQuality() { return this.aaQuality; }
285
286 /** Sets pass2 AA sample count clipped to the range [{@link Region#MIN_AA_SAMPLE_COUNT}..{@link Region#MAX_AA_SAMPLE_COUNT}] for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link #VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT}. */
287 public final int setSampleCount(final int v) { final int s=Region.clipAASampleCount(v); this.sampleCount=s; return s;}
288 /** Returns pass2 AA sample count for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link #VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT}. */
289 public final int getSampleCount() { return this.sampleCount; }
290
291 /** Set the optional clipping {@link Frustum}, which shall be pre-multiplied with the Mv-matrix or null to disable. */
292 public final void setClipFrustum(final Frustum clipFrustum) {
293 if( null != clipFrustum ) {
294 this.clipFrustum.set(clipFrustum);
295 this.useClipFrustum=true;
296 } else {
297 this.useClipFrustum=false;
298 }
299 }
300 /** Returns the optional Mv-premultiplied clipping {@link Frustum} or null if unused. */
301 public final Frustum getClipFrustum() { return useClipFrustum ? this.clipFrustum : null; }
302
303 public final int getHintBits() { return this.hintBits; }
304 public final boolean hintBitsSet(final int mask) {
305 return mask == ( hintBits & mask );
306 }
307 public final void setHintBits(final int mask) {
308 hintBits |= mask;
309 }
310 public final void clearHintBits(final int mask) {
311 hintBits &= ~mask;
312 }
313
314 public final int getDebugBits() { return this.debugBits; }
315 public final boolean debugBitsSet(final int mask) {
316 return mask == ( debugBits & mask );
317 }
318 public final void setDebugBits(final int mask) {
319 debugBits |= mask;
320 }
321 public final void clearDebugBits(final int mask) {
322 debugBits &= ~mask;
323 }
324
325 /**
326 *
327 * @param gl
328 * @param updateLocation
329 * @param data
330 * @param throwOnError TODO
331 * @return true if no error occured, i.e. all locations found, otherwise false.
332 */
333 public final boolean updateUniformLoc(final GL2ES2 gl, final boolean updateLocation, final GLUniformData data, final boolean throwOnError) {
334 if( updateLocation || 0 > data.getLocation() ) {
335 final boolean ok = 0 <= data.setLocation(gl, sp.program());
336 if( throwOnError && !ok ) {
337 sp.dumpSource(System.err);
338 throw new GLException("Could not locate "+data.getName()+" in "+sp+", "+data);
339 }
340 return ok;
341 } else {
342 return true;
343 }
344 }
345
346 /**
347 *
348 * @param gl
349 * @param updateLocation
350 * @param updateData TODO
351 * @param data
352 * @param throwOnError TODO
353 * @return true if no error occured, i.e. all locations found, otherwise false.
354 */
355 public final boolean updateUniformDataLoc(final GL2ES2 gl, boolean updateLocation, boolean updateData, final GLUniformData data, final boolean throwOnError) {
356 updateLocation = updateLocation || 0 > data.getLocation();
357 if( updateLocation ) {
358 updateData = 0 <= data.setLocation(gl, sp.program());
359 if( throwOnError && !updateData ) {
360 sp.dumpSource(System.err);
361 throw new GLException("Could not locate "+data.getName()+" in "+sp+", "+data);
362 }
363 }
364 if( updateData ){
365 gl.glUniform(data);
366 return true;
367 } else {
368 return !updateLocation;
369 }
370 }
371
372 /**
373 * @param gl
374 * @param data
375 * @param throwOnError TODO
376 * @return true if no error occured, i.e. all locations found, otherwise false.
377 */
378 public final boolean updateAttributeLoc(final GL2ES2 gl, final boolean updateLocation, final GLArrayDataWrapper data, final boolean throwOnError) {
379 if( updateLocation || 0 > data.getLocation() ) {
380 final boolean ok = 0 <= data.setLocation(gl, sp.program());
381 if( throwOnError && !ok ) {
382 sp.dumpSource(System.err);
383 throw new GLException("Could not locate "+data.getName()+" in "+sp+", "+data);
384 }
385 return ok;
386 } else {
387 return true;
388 }
389 }
390
391 /**
392 * Only nullifies {@link ShaderProgram} reference owned by {@link RegionRenderer}.
393 */
394 /* pp */ void destroy() {
395 sp = null; // owned by RegionRenderer
396 }
397
398 public final RenderState attachTo(final GL2ES2 gl) {
399 return (RenderState) gl.getContext().attachObject(thisKey, this);
400 }
401
402 public final boolean detachFrom(final GL2ES2 gl) {
403 final RenderState _rs = (RenderState) gl.getContext().getAttachedObject(thisKey);
404 if(_rs == this) {
405 gl.getContext().detachObject(thisKey);
406 return true;
407 }
408 return false;
409 }
410
411 @Override
412 public String toString() {
413 return "RenderState["+sp+"]";
414 }
415}
Abstract Outline shape representation define the method an OutlineShape(s) is bound and rendered.
Definition: Region.java:62
static final int clipAAQuality(final int v)
Returns clipped AA quality value to [Region#MIN_AA_QUALITY..Region#MAX_AA_QUALITY].
Definition: Region.java:170
static final int DEFAULT_AA_QUALITY
Default pass2 AA-quality rendering {@value} for Graph Region AA render-modes: VBAA_RENDERING_BIT.
Definition: Region.java:168
static boolean hasVariableWeight(final int renderModes)
Returns true if render mode capable of variable weights, i.e.
Definition: Region.java:222
static final int clipAASampleCount(final int v)
Returns clipped AA sample-count to [Region#MIN_AA_SAMPLE_COUNT..Region#MAX_AA_SAMPLE_COUNT].
Definition: Region.java:179
static final int DEFAULT_AA_SAMPLE_COUNT
Default pass2 AA sample count {@value} for Graph Region AA render-modes: VBAA_RENDERING_BIT or Region...
Definition: Region.java:177
Representation of RenderState data per ShaderProgram as GLUniformData.
StringBuilder toString(StringBuilder sb, final boolean alsoUnlocated)
final boolean update(final GL2ES2 gl, final RenderState rs, final boolean updateLocation, final int renderModes, final boolean setPMVMat01, final boolean pass1, final boolean throwOnError)
The RenderState is owned by RegionRenderer.
final boolean isShaderProgramInUse()
Return whether the current ShaderProgram is in use.
final Frustum getClipFrustum()
Returns the optional Mv-premultiplied clipping Frustum or null if unused.
final boolean hintBitsSet(final int mask)
final Vec4f getColorStatic(final Vec4f rgbaColor)
final RenderState attachTo(final GL2ES2 gl)
final boolean updateAttributeLoc(final GL2ES2 gl, final boolean updateLocation, final GLArrayDataWrapper data, final boolean throwOnError)
static final int BITHINT_BLENDING_ENABLED
Bitfield hint, if set stating enabled GL#GL_BLEND, otherwise disabled.
final boolean updateUniformLoc(final GL2ES2 gl, final boolean updateLocation, final GLUniformData data, final boolean throwOnError)
final void setColorStatic(final Vec4f rgbaColor)
static final int BITHINT_GLOBAL_DEPTH_TEST_ENABLED
Bitfield hint, if set stating globally enabled GL#GL_DEPTH_TEST, otherwise disabled.
final void setColorStatic(final float r, final float g, final float b, final float a)
final int getSampleCount()
Returns pass2 AA sample count for Graph Region AA render-modes: VBAA_RENDERING_BIT or Region#MSAA_REN...
final void clearDebugBits(final int mask)
static final RenderState getRenderState(final GL2ES2 gl)
final boolean detachFrom(final GL2ES2 gl)
final PMVMatrix4f getMatrix()
Borrow the current PMVMatrix4f.
final void clearHintBits(final int mask)
final boolean debugBitsSet(final int mask)
static boolean isWeightValid(final float v)
final int setSampleCount(final int v)
Sets pass2 AA sample count clipped to the range [Region#MIN_AA_SAMPLE_COUNT..Region#MAX_AA_SAMPLE_COU...
final boolean updateUniformDataLoc(final GL2ES2 gl, boolean updateLocation, boolean updateData, final GLUniformData data, final boolean throwOnError)
final void setHintBits(final int mask)
final boolean setShaderProgram(final GL2ES2 gl, final ShaderProgram spNext)
Sets the current ShaderProgram and enables it.
final int getAAQuality()
Returns pass2 AA-quality rendering value for Graph Region AA render-modes: Region#VBAA_RENDERING_BIT.
final void setClipFrustum(final Frustum clipFrustum)
Set the optional clipping Frustum, which shall be pre-multiplied with the Mv-matrix or null to disabl...
final ShaderProgram getShaderProgram()
Return the current ShaderProgram.
final void setDebugBits(final int mask)
final int setAAQuality(final int v)
Sets pass2 AA-quality rendering value clipped to the range [Region#MIN_AA_QUALITY....
4D Vector based upon four float components.
Definition: Vec4f.java:37
Vec4f set(final Vec4f o)
this = o, returns this.
Definition: Vec4f.java:67
Providing frustum planes derived by different inputs (P*MV, ..) used to classify objects.
Definition: Frustum.java:81
Frustum set(final Frustum o)
Definition: Frustum.java:141
PMVMatrix4f implements the basic computer graphics Matrix4f pack using projection (P),...
final SyncMatrices4f getSyncPMv()
Returns SyncMatrices4f of 2 matrices within one FloatBuffer: P and Mv.
final Object getAttachedObject(final String name)
Returns the attached user object for the given name to this GLContext.
Definition: GLContext.java:611
final Object detachObject(final String name)
Definition: GLContext.java:623
final Object attachObject(final String name, final Object obj)
Sets the attached user object for the given name to this GLContext.
Definition: GLContext.java:619
A generic exception for OpenGL errors used throughout the binding as a substitute for RuntimeExceptio...
GLSL uniform data wrapper encapsulating data to be uploaded to the GPU as a uniform.
static GLUniformData creatEmptyVector(final String name, final int components)
static GLUniformData creatEmptyMatrix(final String name, final int rows, final int columns)
String getName()
Return the uniform name as used in the shader.
int setLocation(final int location)
Sets the given location of the shader uniform.
GLUniformData setData(final int data)
final int setLocation(final int v)
Sets the given location of the shader attribute.
final String getName()
The name of the reflecting shader array attribute.
final int getLocation()
Returns the shader attribute location for this name, -1 if not yet determined.
int program()
Returns the shader program name, which is non zero if valid.
synchronized void useProgram(final GL2ES2 gl, boolean on)
void dumpSource(final PrintStream out)
void glUniform(GLUniformData data)
GLContext getContext()
Returns the GLContext associated which this GL object.