JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
TileRendererBase.java
Go to the documentation of this file.
1/**
2 * Copyright 2013 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 *
28 * ---------------------
29 *
30 * Based on Brian Paul's tile rendering library, found
31 * at <a href = "http://www.mesa3d.org/brianp/TR.html">http://www.mesa3d.org/brianp/TR.html</a>.
32 *
33 * Copyright (C) 1997-2005 Brian Paul.
34 * Licensed under BSD-compatible terms with permission of the author.
35 * See LICENSE.txt for license information.
36 */
37package com.jogamp.opengl.util;
38
39import com.jogamp.nativewindow.util.Dimension;
40import com.jogamp.nativewindow.util.DimensionImmutable;
41import com.jogamp.opengl.GL;
42import com.jogamp.opengl.GL2ES3;
43import com.jogamp.opengl.GLAutoDrawable;
44import com.jogamp.opengl.GLCapabilitiesImmutable;
45import com.jogamp.opengl.GLDrawable;
46import com.jogamp.opengl.GLEventListener;
47import com.jogamp.opengl.GLException;
48import jogamp.opengl.Debug;
49
50/**
51 * A fairly direct port of Brian Paul's tile rendering library, found
52 * at <a href = "http://www.mesa3d.org/brianp/TR.html">
53 * http://www.mesa3d.org/brianp/TR.html </a> . I've java-fied it, but
54 * the functionality is the same.
55 * <p>
56 * Original code Copyright (C) 1997-2005 Brian Paul. Licensed under
57 * BSD-compatible terms with permission of the author. See LICENSE.txt
58 * for license information.
59 * </p>
60 * <p>
61 * Enhanced for {@link GL} and {@link GL2ES3}, abstracted to suit {@link TileRenderer} and {@link RandomTileRenderer}.
62 * </p>
63 * <a name="pmvmatrix"><h5>PMV Matrix Considerations</h5></a>
64 * <p>
65 * The PMV matrix needs to be reshaped in user code
66 * after calling {@link #beginTile(GL)}, See {@link #beginTile(GL)}.
67 * </p>
68 * <p>
69 * If {@link #attachAutoDrawable(GLAutoDrawable) attaching to} an {@link GLAutoDrawable},
70 * the {@link TileRendererListener#reshapeTile(TileRendererBase, int, int, int, int, int, int)} method
71 * is being called after {@link #beginTile(GL)} for each rendered tile.
72 * It's implementation shall reshape the PMV matrix according to {@link #beginTile(GL)}.
73 * </p>
74 * <a name="glprequirement"><h5>GL Profile Requirement</h5></a>
75 * <p>
76 * Note that {@link #setImageBuffer(GLPixelBuffer) image buffer} can only be used
77 * in conjunction w/ a {@link GL} instance &ge; {@link GL2ES3} passed to {@link #beginTile(GL)} and {@link #endTile(GL)}.<br>
78 * This is due to setting up the {@link GL2ES3#GL_PACK_ROW_LENGTH pack row length}
79 * for an {@link #setImageSize(int, int) image width} != tile-width, which usually is the case.<br>
80 * Hence a {@link GLException} is thrown in both methods,
81 * if using an {@link #setImageBuffer(GLPixelBuffer) image buffer}
82 * and passing a {@link GL} instance &lt; {@link GL2ES3}.
83 * </p>
84 * <p>
85 * Further more, reading back of MSAA buffers is only supported since {@link GL2ES3}
86 * since it requires to set the {@link GL2ES3#glReadBuffer(int) read-buffer}.
87 * </p>
88 *
89 * @author ryanm, sgothel
90 */
91public abstract class TileRendererBase {
92 /**
93 * The width of the final image. See {@link #getParam(int)}.
94 */
95 public static final int TR_IMAGE_WIDTH = 1;
96 /**
97 * The height of the final image. See {@link #getParam(int)}.
98 */
99 public static final int TR_IMAGE_HEIGHT = 2;
100 /**
101 * The x-pos of the current tile. See {@link #getParam(int)}.
102 */
103 public static final int TR_CURRENT_TILE_X_POS = 3;
104 /**
105 * The y-pos of the current tile. See {@link #getParam(int)}.
106 */
107 public static final int TR_CURRENT_TILE_Y_POS = 4;
108 /**
109 * The width of the current tile. See {@link #getParam(int)}.
110 */
111 public static final int TR_CURRENT_TILE_WIDTH = 5;
112 /**
113 * The height of the current tile. See {@link #getParam(int)}.
114 */
115 public static final int TR_CURRENT_TILE_HEIGHT = 6;
116
117 /* pp */ static final boolean DEBUG = Debug.debug("TileRenderer");
118
119 /**
120 * Listener for tile renderer events, intended to extend {@link GLEventListener} implementations,
121 * enabling tile rendering via {@link TileRendererBase#attachAutoDrawable(GLAutoDrawable)}.
122 */
123 public static interface TileRendererListener {
124 /**
125 * The owning {@link GLAutoDrawable} is {@link TileRendererBase#attachAutoDrawable(GLAutoDrawable) attached}
126 * to the given {@link TileRendererBase} instance.
127 * <p>
128 * The {@link GLContext} of the {@link TileRendererBase}'s {@link TileRendererBase#getAttachedDrawable() attached} {@link GLAutoDrawable}
129 * <i>is not</i> current.
130 * </p>
131 * @param tr the associated {@link TileRendererBase}
132 * @see TileRendererBase#getAttachedDrawable()
133 */
135
136 /**
137 * The owning {@link GLAutoDrawable} is {@link TileRendererBase#detachAutoDrawable() detached}
138 * from the given {@link TileRendererBase} instance.
139 * <p>
140 * The {@link GLContext} of the {@link TileRendererBase}'s {@link TileRendererBase#getAttachedDrawable() attached} {@link GLAutoDrawable}
141 * <i>is not</i> current.
142 * </p>
143 * @param tr the disassociated {@link TileRendererBase}
144 * @see TileRendererBase#getAttachedDrawable()
145 */
147
148 /**
149 * Called by the {@link TileRendererBase} during tile-rendering via an
150 * {@link TileRendererBase#getAttachedDrawable() attached} {@link GLAutoDrawable}'s
151 * {@link GLAutoDrawable#display()} call for each tile before {@link #display(GLAutoDrawable)}.
152 * <p>
153 * The <a href="TileRendererBase#pmvmatrix">PMV Matrix</a> shall be reshaped
154 * according to the given
155 * <ul>
156 * <li>current tile-position</li>
157 * <li>current tile-size</li>
158 * <li>final image-size</li>
159 * </ul>
160 * The GL viewport is already set to origin 0/0 and the current tile-size.<br>
161 * See details in {@link TileRendererBase#beginTile(GL)}.<br>
162 * </p>
163 * <p>
164 * The {@link GLContext} of the {@link TileRendererBase}'s {@link TileRendererBase#getAttachedDrawable() attached} {@link GLAutoDrawable}
165 * <i>is</i> current.
166 * </p>
167 * @param tr the issuing {@link TileRendererBase}
168 * @param tileX the {@link TileRendererBase#TR_CURRENT_TILE_X_POS current tile's x-pos}
169 * @param tileY the {@link TileRendererBase#TR_CURRENT_TILE_Y_POS current tile's y-pos}
170 * @param tileWidth the {@link TileRendererBase#TR_CURRENT_TILE_WIDTH current tile's width}
171 * @param tileHeight the {@link TileRendererBase#TR_CURRENT_TILE_HEIGHT current tile's height}
172 * @param imageWidth the {@link TileRendererBase#TR_IMAGE_WIDTH final image width}
173 * @param imageHeight the {@link TileRendererBase#TR_IMAGE_HEIGHT final image height}
174 * @see TileRendererBase#getAttachedDrawable()
175 */
177 int tileX, int tileY, int tileWidth, int tileHeight,
178 int imageWidth, int imageHeight);
179
180 /**
181 * Called by the {@link TileRendererBase} during tile-rendering
182 * after {@link TileRendererBase#beginTile(GL)} and before {@link #reshapeTile(TileRendererBase, int, int, int, int, int, int) reshapeTile(..)}.
183 * <p>
184 * If {@link TileRendererBase} is of type {@link TileRenderer},
185 * method is called for the first tile of all tiles.<br>
186 * Otherwise, i.e. {@link RandomTileRenderer}, method is called for each particular tile.
187 * </p>
188 * <p>
189 * The {@link GLContext} of the {@link TileRenderer}'s {@link TileRenderer#getAttachedDrawable() attached} {@link GLAutoDrawable}
190 * <i>is</i> current.
191 * </p>
192 * @param tr the issuing {@link TileRendererBase}
193 */
195
196 /**
197 * Called by the {@link TileRenderer} during tile-rendering
198 * after {@link TileRendererBase#endTile(GL)} and {@link GLAutoDrawable#swapBuffers()}.
199 * <p>
200 * If {@link TileRendererBase} is of type {@link TileRenderer},
201 * method is called for the last tile of all tiles.<br>
202 * Otherwise, i.e. {@link RandomTileRenderer}, method is called for each particular tile.
203 * </p>
204 * <p>
205 * The {@link GLContext} of the {@link TileRenderer}'s {@link TileRenderer#getAttachedDrawable() attached} {@link GLAutoDrawable}
206 * <i>is</i> current.
207 * </p>
208 * @param tr the issuing {@link TileRendererBase}
209 */
211 }
212
213 protected final Dimension imageSize = new Dimension(0, 0);
217 protected boolean beginCalled = false;
218 protected int currentTileXPos;
219 protected int currentTileYPos;
220 protected int currentTileWidth;
221 protected int currentTileHeight;
223 protected boolean gladRequiresPreSwap;
224 protected boolean gladAutoSwapBufferMode = true;
226 protected boolean[] listenersInit;
229
230 private final String hashStr(final Object o) {
231 final int h = null != o ? o.hashCode() : 0;
232 return "0x"+Integer.toHexString(h);
233 }
234 protected StringBuilder tileDetails(final StringBuilder sb) {
235 return sb.append("cur "+currentTileXPos+"/"+currentTileYPos+" "+currentTileWidth+"x"+currentTileHeight+", buffer "+hashStr(tileBuffer));
236 }
237 public StringBuilder toString(final StringBuilder sb) {
238 final int gladListenerCount = null != listeners ? listeners.length : 0;
239 sb.append("tile[");
240 tileDetails(sb);
241 sb.append("], image[size "+imageSize+", buffer "+hashStr(imageBuffer)+"], glad["+
242 gladListenerCount+" listener, pre "+(null!=glEventListenerPre)+", post "+(null!=glEventListenerPost)+", preSwap "+gladRequiresPreSwap+"]");
243 sb.append(", isSetup "+isSetup());
244 return sb;
245 }
246 @Override
247 public String toString() {
248 final StringBuilder sb = new StringBuilder();
249 return getClass().getSimpleName()+
250 "["+toString(sb).toString()+"]";
251 }
252
253 protected TileRendererBase() {
254 }
255
256 /**
257 * Gets the parameters of this TileRenderer object
258 *
259 * @param pname The parameter name that is to be retrieved
260 * @return the value of the parameter
261 * @throws IllegalArgumentException if <code>pname</code> is not handled
262 */
263 public abstract int getParam(int pname) throws IllegalArgumentException;
264
265 /**
266 * Specify a buffer the tiles to be copied to. This is not
267 * necessary for the creation of the final image, but useful if you
268 * want to inspect each tile in turn.
269 *
270 * @param buffer The buffer itself. Must be large enough to contain a random tile
271 */
272 public final void setTileBuffer(final GLPixelBuffer buffer) {
273 tileBuffer = buffer;
274 if( DEBUG ) {
275 System.err.println("TileRenderer: tile-buffer "+tileBuffer);
276 }
277 }
278
279 /** @see #setTileBuffer(GLPixelBuffer) */
280 public final GLPixelBuffer getTileBuffer() { return tileBuffer; }
281
282 /**
283 * Sets the desired size of the final image
284 *
285 * @param width The width of the final image
286 * @param height The height of the final image
287 */
288 public void setImageSize(final int width, final int height) {
289 imageSize.set(width, height);
290 }
291
292 /** @see #setImageSize(int, int) */
293 public final DimensionImmutable getImageSize() { return imageSize; }
294
295 /**
296 * Sets the buffer in which to store the final image
297 *
298 * @param buffer the buffer itself, must be large enough to hold the final image
299 */
300 public final void setImageBuffer(final GLPixelBuffer buffer) {
301 imageBuffer = buffer;
302 if( DEBUG ) {
303 System.err.println("TileRenderer: image-buffer "+imageBuffer);
304 }
305 }
306
307 /** @see #setImageBuffer(GLPixelBuffer) */
308 public final GLPixelBuffer getImageBuffer() { return imageBuffer; }
309
310 /* pp */ final void validateGL(final GL gl) throws GLException {
311 if( imageBuffer != null && !gl.isGL2ES3()) {
312 throw new GLException("Using image-buffer w/ inssufficient GL context: "+gl.getContext().getGLVersion()+", "+gl.getGLProfile());
313 }
314 }
315
316 /**
317 * Returns true if this instance is setup properly, i.e. {@link #setImageSize(int, int)} ..,
318 * and ready for {@link #beginTile(GL)}.
319 * Otherwise returns false.
320 */
321 public abstract boolean isSetup();
322
323 /**
324 * Returns true if <i>end of tiling</i> has been reached, otherwise false.
325 * <p>
326 * <i>end of tiling</i> criteria is implementation specific and may never be reached.
327 * </p>
328 * <p>
329 * User needs to {@link #reset()} tiling after reaching <i>end of tiling</i>
330 * before calling {@link #beginTile(GL)} again.
331 * </p>
332 */
333 public abstract boolean eot();
334
335 /**
336 * Method resets implementation's internal state to <i>start of tiling</i>
337 * as required for {@link #beginTile(GL)} if {@link #eot() end of tiling} has been reached.
338 * <p>
339 * Implementation is a <i>nop</i> where {@link #eot() end of tiling} is never reached.
340 * </p>
341 */
342 public abstract void reset();
343
344 /**
345 * Begins rendering a tile.
346 * <p>
347 * This method modifies the viewport, see below.
348 * User shall reset the viewport when finishing all tile rendering,
349 * i.e. after very last call of {@link #endTile(GL)}!
350 * </p>
351 * <p>
352 * The <a href="TileRendererBase.html#pmvmatrix">PMV Matrix</a>
353 * must be reshaped after this call using:
354 * <ul>
355 * <li>Current Viewport
356 * <ul>
357 * <li>x 0</li>
358 * <li>y 0</li>
359 * <li>{@link #TR_CURRENT_TILE_WIDTH current tile's width}</li>
360 * <li>{@link #TR_CURRENT_TILE_HEIGHT current tile's height}</li>
361 * </ul></li>
362 * <li>{@link #TR_CURRENT_TILE_X_POS current tile's x-pos}</li>
363 * <li>{@link #TR_CURRENT_TILE_Y_POS current tile's y-pos}</li>
364 * <li>{@link #TR_IMAGE_WIDTH final image width}</li>
365 * <li>{@link #TR_IMAGE_HEIGHT final image height}</li>
366 * </ul>
367 * </p>
368 * <p>
369 * Use shall render the scene afterwards, concluded with a call to
370 * this renderer {@link #endTile(GL)}.
371 * </p>
372 * <p>
373 * User has to comply with the <a href="TileRendererBase.html#glprequirement">GL profile requirement</a>.
374 * </p>
375 * <p>
376 * If {@link #eot() end of tiling} has been reached,
377 * user needs to {@link #reset()} tiling before calling this method.
378 * </p>
379 *
380 * @param gl The gl context
381 * @throws IllegalStateException if {@link #setImageSize(int, int) image-size} is undefined,
382 * an {@link #isSetup() implementation related setup} has not be performed
383 * or {@ link #eot()} has been reached. See implementing classes.
384 * @throws GLException if {@link #setImageBuffer(GLPixelBuffer) image buffer} is used but <code>gl</code> instance is &lt; {@link GL2ES3}
385 * @see #isSetup()
386 * @see #eot()
387 * @see #reset()
388 */
389 public abstract void beginTile(GL gl) throws IllegalStateException, GLException;
390
391 /**
392 * Must be called after rendering the scene,
393 * see {@link #beginTile(GL)}.
394 * <p>
395 * Please consider {@link #reqPreSwapBuffers(GLCapabilitiesImmutable)} to determine
396 * whether you need to perform {@link GLDrawable#swapBuffers() swap-buffers} before or after
397 * calling this method!
398 * </p>
399 * <p>
400 * User has to comply with the <a href="TileRendererBase.html#glprequirement">GL profile requirement</a>.
401 * </p>
402 *
403 * @param gl the gl context
404 * @throws IllegalStateException if beginTile(gl) has not been called
405 * @throws GLException if {@link #setImageBuffer(GLPixelBuffer) image buffer} is used but <code>gl</code> instance is &lt; {@link GL2ES3}
406 */
407 public abstract void endTile( GL gl ) throws IllegalStateException, GLException;
408
409 /**
410 * Determines whether the chosen {@link GLCapabilitiesImmutable}
411 * requires a <i>pre-{@link GLDrawable#swapBuffers() swap-buffers}</i>
412 * before accessing the results, i.e. before {@link #endTile(GL)}.
413 * <p>
414 * See {@link GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable)}.
415 * </p>
416 */
417 public final boolean reqPreSwapBuffers(final GLCapabilitiesImmutable chosenCaps) {
418 return GLDrawableUtil.swapBuffersBeforeRead(chosenCaps);
419 }
420
421 /**
422 * Attaches the given {@link GLAutoDrawable} to this tile renderer.
423 * <p>
424 * The {@link GLAutoDrawable}'s original {@link GLEventListener} are moved to this tile renderer.
425 * </p>
426 * <p>
427 * {@link GLEventListeners} not implementing {@link TileRendererListener} are ignored while tile rendering.
428 * </p>
429 * <p>
430 * The {@link GLAutoDrawable}'s {@link GLAutoDrawable#getAutoSwapBufferMode() auto-swap mode} is cached
431 * and set to <code>false</code>, since {@link GLAutoDrawable#swapBuffers() swapBuffers()} maybe issued before {@link #endTile(GL)},
432 * see {@link #reqPreSwapBuffers(GLCapabilitiesImmutable)}.
433 * </p>
434 * <p>
435 * This tile renderer's internal {@link GLEventListener} is then added to the attached {@link GLAutoDrawable}
436 * to handle the tile rendering, replacing the original {@link GLEventListener}.<br>
437 * It's {@link GLEventListener#display(GLAutoDrawable) display} implementations issues:
438 * <ul>
439 * <li>Optional {@link #setGLEventListener(GLEventListener, GLEventListener) pre-glel}.{@link GLEventListener#display(GLAutoDrawable) display(..)}</li>
440 * <li>{@link #beginTile(GL)}</li>
441 * <li>for all original {@link TileRendererListener}:
442 * <ul>
443 * <li>{@link TileRendererListener#reshapeTile(TileRendererBase, int, int, int, int, int, int) reshapeTile(tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight)}</li>
444 * <li>{@link GLEventListener#display(GLAutoDrawable) display(autoDrawable)}</li>
445 * </ul></li>
446 * <li>if ( {@link #reqPreSwapBuffers(GLCapabilitiesImmutable) pre-swap} ) { {@link GLAutoDrawable#swapBuffers() swapBuffers()} }</li>
447 * <li>{@link #endTile(GL)}</li>
448 * <li>if ( !{@link #reqPreSwapBuffers(GLCapabilitiesImmutable) pre-swap} ) { {@link GLAutoDrawable#swapBuffers() swapBuffers()} }</li>
449 * <li>Optional {@link #setGLEventListener(GLEventListener, GLEventListener) post-glel}.{@link GLEventListener#display(GLAutoDrawable) display(..)}</li>
450 * </ul>
451 * </p>
452 * <p>
453 * Consider using {@link #setGLEventListener(GLEventListener, GLEventListener)} to add pre- and post
454 * hooks to be performed on this renderer {@link GLEventListener}.<br>
455 * The pre-hook is able to allocate memory and setup parameters, since it's called before {@link #beginTile(GL)}.<br>
456 * The post-hook is able to use the rendering result and can even shutdown tile-rendering,
457 * since it's called after {@link #endTile(GL)}.
458 * </p>
459 * <p>
460 * Call {@link #detachAutoDrawable()} to remove the attached {@link GLAutoDrawable} from this tile renderer
461 * and to restore it's original {@link GLEventListener}.
462 * </p>
463 * @param glad the {@link GLAutoDrawable} to attach.
464 * @throws IllegalStateException if an {@link GLAutoDrawable} is already attached
465 * @see #getAttachedDrawable()
466 * @see #detachAutoDrawable()
467 */
468 public final void attachAutoDrawable(final GLAutoDrawable glad) throws IllegalStateException {
469 if( null != this.glad ) {
470 throw new IllegalStateException("GLAutoDrawable already attached");
471 }
472 this.glad = glad;
473
474 final int aSz = glad.getGLEventListenerCount();
475 listeners = new GLEventListener[aSz];
476 listenersInit = new boolean[aSz];
477 for(int i=0; i<aSz; i++) {
481 final boolean trn;
482 if( listeners[i] instanceof TileRendererListener ) {
483 trn = true;
484 ((TileRendererListener)listeners[i]).addTileRendererNotify(this);
485 } else {
486 trn = false;
487 }
488 if( DEBUG ) {
489 System.err.println("TileRenderer.attach["+i+"]: isInit "+listenersInit[i]+", isTRN "+trn+", "+listeners[i].getClass().getName());
490 }
491 }
492 glad.addGLEventListener(tiledGLEL);
496 if( DEBUG ) {
497 System.err.println("TileRenderer: attached: "+glad);
498 System.err.println("TileRenderer: preSwap "+gladRequiresPreSwap+", "+glad.getChosenGLCapabilities()+", cached "+listeners.length+" listener");
499 }
500 }
501
502 /**
503 * Returns a previously {@link #attachAutoDrawable(GLAutoDrawable) attached} {@link GLAutoDrawable},
504 * <code>null</code> if none is attached.
505 * <p>
506 * If called from {@link TileRendererListener#addTileRendererNotify(TileRendererBase)}
507 * or {@link TileRendererListener#removeTileRendererNotify(TileRendererBase)}, method returns the
508 * just attached or soon to be detached {@link GLAutoDrawable}.
509 * </p>
510 * @see #attachAutoDrawable(GLAutoDrawable)
511 * @see #detachAutoDrawable()
512 */
514 return glad;
515 }
516
517 /**
518 * Detaches the given {@link GLAutoDrawable} from this tile renderer.
519 * @see #attachAutoDrawable(GLAutoDrawable)
520 * @see #getAttachedDrawable()
521 */
522 public final void detachAutoDrawable() {
523 if( null != glad ) {
524 glad.removeGLEventListener(tiledGLEL);
525 final int aSz = listenersInit.length;
526 for(int i=0; i<aSz; i++) {
527 final GLEventListener l = listeners[i];
528 if( l instanceof TileRendererListener ) {
529 ((TileRendererListener)l).removeTileRendererNotify(this);
530 }
533 }
535 if( DEBUG ) {
536 System.err.println("TileRenderer: detached: "+glad);
537 System.err.println("TileRenderer: "+glad.getChosenGLCapabilities());
538 }
539
540 listeners = null;
541 listenersInit = null;
542 glad = null;
543 }
544 }
545
546 /**
547 * Set {@link GLEventListener} for pre- and post operations when used w/
548 * {@link #attachAutoDrawable(GLAutoDrawable)}
549 * for each {@link GLEventListener} callback.
550 * @param preTile the pre operations
551 * @param postTile the post operations
552 */
553 public final void setGLEventListener(final GLEventListener preTile, final GLEventListener postTile) {
554 glEventListenerPre = preTile;
555 glEventListenerPost = postTile;
556 }
557
558 /**
559 * Rendering one tile, by simply calling {@link GLAutoDrawable#display()}.
560 *
561 * @throws IllegalStateException if no {@link GLAutoDrawable} is {@link #attachAutoDrawable(GLAutoDrawable) attached}
562 * or imageSize is not set
563 */
564 public final void display() throws IllegalStateException {
565 if( null == glad ) {
566 throw new IllegalStateException("No GLAutoDrawable attached");
567 }
568 glad.display();
569 }
570
571 private final GLEventListener tiledGLEL = new GLEventListener() {
572 final TileRenderer tileRenderer = TileRendererBase.this instanceof TileRenderer ? (TileRenderer) TileRendererBase.this : null;
573
574 @Override
575 public void init(final GLAutoDrawable drawable) {
576 if( null != glEventListenerPre ) {
577 glEventListenerPre.init(drawable);
578 }
579 final int aSz = listenersInit.length;
580 for(int i=0; i<aSz; i++) {
581 final GLEventListener l = listeners[i];
582 if( !listenersInit[i] && l instanceof TileRendererListener ) {
583 l.init(drawable);
584 listenersInit[i] = true;
585 }
586 }
587 if( null != glEventListenerPost ) {
588 glEventListenerPost.init(drawable);
589 }
590 }
591 @Override
592 public void dispose(final GLAutoDrawable drawable) {
593 if( null != glEventListenerPre ) {
594 glEventListenerPre.dispose(drawable);
595 }
596 final int aSz = listenersInit.length;
597 for(int i=0; i<aSz; i++) { // dispose all GLEventListener, last chance!
598 listeners[i].dispose(drawable);
599 }
600 if( null != glEventListenerPost ) {
602 }
603 }
604 @Override
605 public void display(final GLAutoDrawable drawable) {
606 if( null != glEventListenerPre ) {
608 glEventListenerPre.display(drawable);
609 }
610 if( !isSetup() ) {
611 if( DEBUG ) {
612 System.err.println("TileRenderer.glel.display: !setup: "+TileRendererBase.this);
613 }
614 return;
615 }
616 if( eot() ) {
617 if( DEBUG ) {
618 System.err.println("TileRenderer.glel.display: EOT: "+TileRendererBase.this);
619 }
620 return;
621 }
622 final GL gl = drawable.getGL();
623
624 beginTile(gl);
625
626 final int aSz = listenersInit.length;
627 for(int i=0; i<aSz; i++) {
628 final GLEventListener l = listeners[i];
629 if( l instanceof TileRendererListener ) {
630 final TileRendererListener tl = (TileRendererListener)l;
631 if( null == tileRenderer || 0 == tileRenderer.getCurrentTile() ) {
632 tl.startTileRendering(TileRendererBase.this);
633 }
634 tl.reshapeTile(TileRendererBase.this,
637 l.display(drawable);
638 }
639 }
640
641 if( gladRequiresPreSwap ) {
643 endTile(gl);
644 } else {
645 endTile(gl);
647 }
648 if( null == tileRenderer || tileRenderer.eot() ) {
649 for(int i=0; i<aSz; i++) {
650 final GLEventListener l = listeners[i];
651 if( l instanceof TileRendererListener ) {
652 ((TileRendererListener)l).endTileRendering(TileRendererBase.this);
653 }
654 }
655 }
656 if( null != glEventListenerPost ) {
659 }
660 }
661 @Override
662 public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
663 };
664}
final void set(final int width, final int height)
Definition: Dimension.java:71
A generic exception for OpenGL errors used throughout the binding as a substitute for RuntimeExceptio...
Providing utility functions dealing w/ GLDrawables, GLAutoDrawable and their GLEventListener.
static final boolean swapBuffersBeforeRead(final GLCapabilitiesImmutable chosenCaps)
Determines whether the chosen GLCapabilitiesImmutable requires a swap-buffers before reading pixels.
OpenGL pixel data buffer, allowing user to provide buffers via their GLPixelBufferProvider implementa...
Utility to safely set and restore the PACK and UNPACK pixel storage mode, regardless of the GLProfile...
A fairly direct port of Brian Paul's tile rendering library, found at http://www.mesa3d....
final void setGLEventListener(final GLEventListener preTile, final GLEventListener postTile)
Set GLEventListener for pre- and post operations when used w/ attachAutoDrawable(GLAutoDrawable) for ...
final void setTileBuffer(final GLPixelBuffer buffer)
Specify a buffer the tiles to be copied to.
final GLAutoDrawable getAttachedDrawable()
Returns a previously attached GLAutoDrawable, null if none is attached.
abstract boolean eot()
Returns true if end of tiling has been reached, otherwise false.
abstract int getParam(int pname)
Gets the parameters of this TileRenderer object.
final void setImageBuffer(final GLPixelBuffer buffer)
Sets the buffer in which to store the final image.
static final int TR_CURRENT_TILE_WIDTH
The width of the current tile.
StringBuilder tileDetails(final StringBuilder sb)
final boolean reqPreSwapBuffers(final GLCapabilitiesImmutable chosenCaps)
Determines whether the chosen GLCapabilitiesImmutable requires a pre-swap-buffers before accessing th...
static final int TR_IMAGE_WIDTH
The width of the final image.
abstract void endTile(GL gl)
Must be called after rendering the scene, see beginTile(GL).
abstract void reset()
Method resets implementation's internal state to start of tiling as required for beginTile(GL) if end...
final void detachAutoDrawable()
Detaches the given GLAutoDrawable from this tile renderer.
StringBuilder toString(final StringBuilder sb)
abstract void beginTile(GL gl)
Begins rendering a tile.
static final int TR_CURRENT_TILE_HEIGHT
The height of the current tile.
static final int TR_CURRENT_TILE_X_POS
The x-pos of the current tile.
final void display()
Rendering one tile, by simply calling GLAutoDrawable#display().
final void attachAutoDrawable(final GLAutoDrawable glad)
Attaches the given GLAutoDrawable to this tile renderer.
abstract boolean isSetup()
Returns true if this instance is setup properly, i.e.
void setImageSize(final int width, final int height)
Sets the desired size of the final image.
static final int TR_CURRENT_TILE_Y_POS
The y-pos of the current tile.
static final int TR_IMAGE_HEIGHT
The height of the final image.
A fairly direct port of Brian Paul's tile rendering library, found at http://www.mesa3d....
final boolean eot()
Returns true if end of tiling has been reached, otherwise false.end of tiling criteria is implementat...
Immutable Dimension Interface, consisting of it's read only components:
A higher-level abstraction than GLDrawable which supplies an event based mechanism (GLEventListener) ...
GLEventListener getGLEventListener(int index)
Returns the GLEventListener at the given index of this drawable queue.
void setGLEventListenerInitState(GLEventListener listener, boolean initialized)
Sets the given listener's initialized state.
boolean getAutoSwapBufferMode()
Indicates whether automatic buffer swapping is enabled for this drawable.
void addGLEventListener(GLEventListener listener)
Adds the given listener to the end of this drawable queue.
int getGLEventListenerCount()
Returns the number of GLEventListener of this drawable queue.
GLEventListener removeGLEventListener(GLEventListener listener)
Removes the given listener from this drawable queue.
boolean getGLEventListenerInitState(GLEventListener listener)
Retrieves whether the given listener is initialized or not.
void setAutoSwapBufferMode(boolean enable)
Enables or disables automatic buffer swapping for this drawable.
Specifies an immutable set of OpenGL capabilities.
GLCapabilitiesImmutable getChosenGLCapabilities()
Fetches the GLCapabilitiesImmutable corresponding to the chosen OpenGL capabilities (pixel format / v...
void swapBuffers()
Swaps the front and back buffers of this drawable.
Declares events which client code can use to manage OpenGL rendering into a GLAutoDrawable.
void dispose(GLAutoDrawable drawable)
Notifies the listener to perform the release of all OpenGL resources per GLContext,...
void display(GLAutoDrawable drawable)
Called by the drawable to initiate OpenGL rendering by the client.
void init(GLAutoDrawable drawable)
Called by the drawable immediately after the OpenGL context is initialized.
void reshape(GLAutoDrawable drawable, int x, int y, int width, int height)
Called by the drawable during the first repaint after the component has been resized.
Listener for tile renderer events, intended to extend GLEventListener implementations,...
void reshapeTile(TileRendererBase tr, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight)
Called by the TileRendererBase during tile-rendering via an attached GLAutoDrawable's GLAutoDrawable#...
void removeTileRendererNotify(TileRendererBase tr)
The owning GLAutoDrawable is detached from the given TileRendererBase instance.
void addTileRendererNotify(TileRendererBase tr)
The owning GLAutoDrawable is attached to the given TileRendererBase instance.
void endTileRendering(TileRendererBase tr)
Called by the TileRenderer during tile-rendering after TileRendererBase#endTile(GL) and GLAutoDrawabl...
void startTileRendering(TileRendererBase tr)
Called by the TileRendererBase during tile-rendering after TileRendererBase#beginTile(GL) and before ...