Project

General

Profile

Download (23.6 KB) Statistics
| Branch: | Revision:

library / src / main / java / org / distorted / library / main / DistortedNode.java @ f953bee0

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted is free software: you can redistribute it and/or modify                             //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Distorted is distributed in the hope that it will be useful,                                  //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.library.main;
21

    
22
import android.opengl.GLES31;
23

    
24
import org.distorted.library.mesh.MeshBase;
25

    
26
import java.util.ArrayList;
27
import java.util.Collections;
28

    
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30
/**
31
 * Class which represents a Node in a Tree of (InputSurface,Mesh,Effects) triplets.
32
 * <p>
33
 * Having organized such sets into a Tree, we can then render any Node to any OutputSurface.
34
 * That recursively renders the set held in the Node and all its children.
35
 * <p>
36
 * The class takes special care to only render identical sub-trees once. Each Node holds a reference
37
 * to sub-class 'NodeData'. Two identical sub-trees attached at different points of the main tree
38
 * will point to the same NodeData; only the first of this is rendered (mData.numRender!).
39
 */
40
public class DistortedNode implements InternalChildrenList.Parent
41
  {
42
  private MeshBase mMesh;
43
  private DistortedEffects mEffects;
44
  private InternalSurface mSurface;
45
  private InternalRenderState mState;
46
  private InternalNodeData mData;
47
  private InternalChildrenList mChildren;
48
  private InternalChildrenList.Parent mParent;
49

    
50
  private int mFboW, mFboH, mFboDepthStencil;
51
  private boolean mRenderWayOIT;
52

    
53
///////////////////////////////////////////////////////////////////////////////////////////////////
54

    
55
  public void markForDeletion()
56
    {
57
    if( mData.removeData() )
58
      {
59
      mData.mFBO.markForDeletion();
60
      mData.mFBO = null;
61
      }
62
    }
63

    
64
///////////////////////////////////////////////////////////////////////////////////////////////////
65
// [3] --> the postprocessing queue. See EffectType.
66

    
67
  long getBucket()
68
    {
69
    return mEffects.getQueues()[3].getID();
70
    }
71

    
72
///////////////////////////////////////////////////////////////////////////////////////////////////
73

    
74
  private ArrayList<Long> generateIDList()
75
    {
76
    ArrayList<Long> ret = new ArrayList<>();
77
    int numChildren = mChildren.getNumChildren();
78

    
79
    if( numChildren==0 )
80
      {
81
      // add a negative number so this leaf never gets confused with a internal node
82
      // with a single child that happens to have ID identical to some leaf's Effects ID.
83
      ret.add(-mEffects.getID());
84
      }
85
    else
86
      {
87
      DistortedNode node;
88
   
89
      for(int i=0; i<numChildren; i++)
90
        {
91
        node = mChildren.getChild(i);
92
        ret.add(node.mData.ID);
93
        }
94

    
95
      // A bit questionable decision here - we are sorting the children IDs, which means
96
      // that order in which we draw the children is going to be undefined (well, this is not
97
      // strictly speaking true - when rendering, if no postprocessing and isomorphism are
98
      // involved, we *DO* render the children in order they were added; if however there
99
      // are two internal nodes with the same list of identical children, just added in a
100
      // different order each time, then we consider them isomorphic, i.e. identical and only
101
      // render the first one. If then two children of such 'pseudo-isomorphic' nodes are at
102
      // exactly the same Z-height this might result in some unexpected sights).
103
      //
104
      // Reason: with the children being sorted by postprocessing buckets, the order is
105
      // undefined anyway (although only when postprocessing is applied).
106
      //
107
      // See the consequences in the 'Olympic' app - remove a few leaves and add them back in
108
      // different order. You will see the number of renders go back to the original 15.
109
      Collections.sort(ret);
110
      }
111

    
112
    ret.add( 0, mSurface.getID() );
113

    
114
    return ret;
115
    }
116

    
117
///////////////////////////////////////////////////////////////////////////////////////////////////
118
/**
119
 * This is not really part of the public API. Has to be public only because it is a part of the
120
 * InternalChildrenList.Parent interface.
121
 *
122
 * @y.exclude
123
 */
124
  public void adjustIsomorphism()
125
    {
126
    InternalNodeData newData = InternalNodeData.returnData(generateIDList());
127
    boolean deleteOldFBO = mData.removeData();
128
    boolean createNewFBO = (mChildren.getNumChildren()>0 && newData.mFBO==null);
129

    
130
    if( deleteOldFBO && createNewFBO )
131
      {
132
      newData.mFBO = mData.mFBO;
133
      }
134
    else if( deleteOldFBO )
135
      {
136
      mData.mFBO.markForDeletion();
137
      mData.mFBO = null;
138
      }
139
    else if( createNewFBO )
140
      {
141
      newData.mFBO = allocateNewFBO();
142
      }
143

    
144
    mData = newData;
145

    
146
    if( mParent!=null ) mParent.adjustIsomorphism();
147
    }
148

    
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150
// return the total number of render calls issued
151

    
152
  int drawNoBlend(long currTime, InternalOutputSurface surface)
153
    {
154
    InternalSurface input = getSurface();
155

    
156
    if( input.setAsInput() )
157
      {
158
      mState.apply();
159
      GLES31.glDisable(GLES31.GL_BLEND);
160
      DistortedLibrary.drawPriv(mEffects.getQueues(), mSurface.getWidth()/2.0f, mSurface.getHeight()/2.0f, mMesh, surface, currTime);
161
      GLES31.glEnable(GLES31.GL_BLEND);
162
      return 1;
163
      }
164

    
165
    return 0;
166
    }
167

    
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169
// Use the Order Independent Transparency method to draw a non-postprocessed child.
170

    
171
  int drawOIT(long currTime, InternalOutputSurface surface)
172
    {
173
    InternalSurface input = getSurface();
174

    
175
    if( input.setAsInput() )
176
      {
177
      mState.apply();
178
      DistortedLibrary.drawPrivOIT(mEffects.getQueues(), mSurface.getWidth()/2.0f, mSurface.getHeight()/2.0f, mMesh, surface, currTime);
179
      return 1;
180
      }
181

    
182
    return 0;
183
    }
184

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186
// return the total number of render calls issued
187

    
188
  int draw(long currTime, InternalOutputSurface surface)
189
    {
190
    InternalSurface input = getSurface();
191

    
192
    if( input.setAsInput() )
193
      {
194
      mState.apply();
195
      DistortedLibrary.drawPriv(mEffects.getQueues(), mSurface.getWidth()/2.0f, mSurface.getHeight()/2.0f, mMesh, surface, currTime);
196
      return 1;
197
      }
198

    
199
    return 0;
200
    }
201

    
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203
// return the total number of render calls issued
204

    
205
  int renderRecursive(long currTime)
206
    {
207
    int numRenders = 0;
208
    int numChildren = mChildren.getNumChildren();
209

    
210
    if( numChildren>0 && mData.notRenderedYetAtThisTime(currTime) )
211
      {
212
      DistortedNode node;
213
      long oldBucket=0, newBucket;
214

    
215
      for (int i=0; i<numChildren; i++)
216
        {
217
        node = mChildren.getChild(i);
218
        newBucket = node.getBucket();
219
        numRenders += node.renderRecursive(currTime);
220
        if( newBucket<oldBucket ) mChildren.rearrangeByBuckets(i,newBucket);
221
        else oldBucket=newBucket;
222
        }
223

    
224
      if( mData.mFBO==null ) mData.mFBO = allocateNewFBO();
225
      mData.mFBO.setAsOutput(currTime);
226

    
227
      if( mSurface.setAsInput() )
228
        {
229
        numRenders++;
230
        DistortedLibrary.blitPriv(mData.mFBO);
231
        }
232

    
233
      numRenders += mData.mFBO.renderChildren(currTime,numChildren,mChildren,0, mRenderWayOIT);
234
      }
235

    
236
    return numRenders;
237
    }
238

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240

    
241
  private DistortedFramebuffer allocateNewFBO()
242
    {
243
    int width  = mFboW <= 0 ? mSurface.getWidth()  : mFboW;
244
    int height = mFboH <= 0 ? mSurface.getHeight() : mFboH;
245
    return new DistortedFramebuffer(1,mFboDepthStencil, InternalSurface.TYPE_TREE, width, height);
246
    }
247

    
248
///////////////////////////////////////////////////////////////////////////////////////////////////
249

    
250
  void setParent(InternalChildrenList.Parent parent)
251
    {
252
    mParent = parent;
253
    }
254

    
255
///////////////////////////////////////////////////////////////////////////////////////////////////
256
// PUBLIC API
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258
/**
259
 * Constructs new Node.
260
 *     
261
 * @param surface InputSurface to put into the new Node.
262
 * @param effects DistortedEffects to put into the new Node.
263
 * @param mesh MeshBase to put into the new Node.
264
 */
265
  public DistortedNode(InternalSurface surface, DistortedEffects effects, MeshBase mesh)
266
    {
267
    mSurface       = surface;
268
    mEffects       = effects;
269
    mMesh          = mesh;
270
    mState         = new InternalRenderState();
271
    mChildren      = new InternalChildrenList(this);
272
    mParent        = null;
273
    mRenderWayOIT  = false;
274

    
275
    mFboW            = 0;  // i.e. take this from
276
    mFboH            = 0;  // mSurface's dimensions
277
    mFboDepthStencil = DistortedFramebuffer.DEPTH_NO_STENCIL;
278

    
279
    mData = InternalNodeData.returnData(generateIDList());
280
    }
281

    
282
///////////////////////////////////////////////////////////////////////////////////////////////////  
283
/**
284
 * Copy-constructs new Node from another Node.
285
 *     
286
 * @param node The DistortedNode to copy data from.
287
 * @param flags bit field composed of a subset of the following:
288
 *        {@link DistortedLibrary#CLONE_SURFACE},  {@link DistortedLibrary#CLONE_MATRIX}, {@link DistortedLibrary#CLONE_VERTEX},
289
 *        {@link DistortedLibrary#CLONE_FRAGMENT} and {@link DistortedLibrary#CLONE_CHILDREN}.
290
 *        For example flags = CLONE_SURFACE | CLONE_CHILDREN.
291
 */
292
  public DistortedNode(DistortedNode node, int flags)
293
    {
294
    mEffects      = new DistortedEffects(node.mEffects,flags);
295
    mMesh         = node.mMesh;
296
    mState        = new InternalRenderState();
297
    mParent       = null;
298
    mRenderWayOIT = false;
299

    
300
    mFboW            = node.mFboW;
301
    mFboH            = node.mFboH;
302
    mFboDepthStencil = node.mFboDepthStencil;
303

    
304
    if( (flags & DistortedLibrary.CLONE_SURFACE) != 0 )
305
      {
306
      mSurface = node.mSurface;
307
      }
308
    else
309
      {
310
      int w = node.mSurface.getWidth();
311
      int h = node.mSurface.getHeight();
312

    
313
      if( node.mSurface instanceof DistortedTexture )
314
        {
315
        mSurface = new DistortedTexture(w,h, InternalSurface.TYPE_TREE);
316
        }
317
      else if( node.mSurface instanceof DistortedFramebuffer )
318
        {
319
        int depthStencil = DistortedFramebuffer.NO_DEPTH_NO_STENCIL;
320

    
321
        if( ((DistortedFramebuffer) node.mSurface).hasDepth() )
322
          {
323
          boolean hasStencil = ((DistortedFramebuffer) node.mSurface).hasStencil();
324
          depthStencil = (hasStencil ? DistortedFramebuffer.BOTH_DEPTH_STENCIL:DistortedFramebuffer.DEPTH_NO_STENCIL);
325
          }
326

    
327
        mSurface = new DistortedFramebuffer(1,depthStencil, InternalSurface.TYPE_TREE,w,h);
328
        }
329
      }
330

    
331
    if( (flags & DistortedLibrary.CLONE_CHILDREN) != 0 )
332
      {
333
      mChildren = node.mChildren;
334
      }
335
    else
336
      {
337
      mChildren = new InternalChildrenList(this);
338
      }
339

    
340
    mData = InternalNodeData.returnData(generateIDList());
341
    }
342

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344
  /**
345
   * When rendering this Node, should we use the Order Independent Transparency render more?
346
   * <p>
347
   * There are two modes of rendering: the fast 'normal' way, which however renders transparent
348
   * fragments in different ways depending on which fragments get rendered first, or the slower
349
   * 'oit' way, which renders transparent fragments correctly regardless of their order.
350
   *
351
   * @param oit True if we want to render more slowly, but in a way which accounts for transparency.
352
   */
353
  public void setOrderIndependentTransparency(boolean oit)
354
    {
355
    mRenderWayOIT = oit;
356
    }
357

    
358
///////////////////////////////////////////////////////////////////////////////////////////////////
359
  /**
360
   * When rendering this Node, should we use the Order Independent Transparency render more?
361
   * <p>
362
   * There are two modes of rendering: the fast 'normal' way, which however renders transparent
363
   * fragments in different ways depending on which fragments get rendered first, or the slower
364
   * 'oit' way, which renders transparent fragments correctly regardless of their order.
365
   *
366
   * @param oit True if we want to render more slowly, but in a way which accounts for transparency.
367
   * @param initialSize Initial number of transparent fragments we expect, in screenfulls.
368
   *                    I.e '1.0' means 'the scene we are going to render contains dialog_about 1 screen
369
   *                    worth of transparent fragments'. Valid values: 0.0 &lt; initialSize &lt; 10.0
370
   *                    Even if you get this wrong, the library will detect that there are more
371
   *                    transparent fragments than it has space for and readjust its internal buffers,
372
   *                    but only after a few frames during which one will probably see missing objects.
373
   */
374
  public void setOrderIndependentTransparency(boolean oit, float initialSize)
375
    {
376
    mRenderWayOIT = oit;
377

    
378
    if( initialSize>0.0f && initialSize<10.0f )
379
      DistortedLibrary.setSSBOSize(initialSize);
380
    }
381

    
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383
/**
384
 * Adds a new child to the last position in the list of our Node's children.
385
 * <p>
386
 * We cannot do this mid-render - actual attachment will be done just before the next render, by the
387
 * InternalMaster (by calling doWork())
388
 *
389
 * @param node The new Node to add.
390
 */
391
  public void attach(DistortedNode node)
392
    {
393
    mChildren.attach(node);
394
    }
395

    
396
///////////////////////////////////////////////////////////////////////////////////////////////////
397
/**
398
 * Adds a new child to the last position in the list of our Node's children.
399
 * <p>
400
 * We cannot do this mid-render - actual attachment will be done just before the next render, by the
401
 * InternalMaster (by calling doWork())
402
 *
403
 * @param surface InputSurface to initialize our child Node with.
404
 * @param effects DistortedEffects to initialize our child Node with.
405
 * @param mesh MeshBase to initialize our child Node with.
406
 * @return the newly constructed child Node, or null if we couldn't allocate resources.
407
 */
408
  public DistortedNode attach(InternalSurface surface, DistortedEffects effects, MeshBase mesh)
409
    {
410
    return mChildren.attach(surface,effects,mesh);
411
    }
412

    
413
///////////////////////////////////////////////////////////////////////////////////////////////////
414
/**
415
 * Removes the first occurrence of a specified child from the list of children of our Node.
416
 * <p>
417
 * We cannot do this mid-render - actual detachment will be done just before the next render, by the
418
 * InternalMaster (by calling doWork())
419
 *
420
 * @param node The Node to remove.
421
 */
422
  public void detach(DistortedNode node)
423
    {
424
    mChildren.detach(node);
425
    }
426

    
427
///////////////////////////////////////////////////////////////////////////////////////////////////
428
/**
429
 * Removes the first occurrence of a specified child from the list of children of our Node.
430
 * <p>
431
 * A bit questionable method as there can be many different Nodes attached as children, some
432
 * of them having the same Effects but - for instance - different Mesh. Use with care.
433
 * <p>
434
 * We cannot do this mid-render - actual detachment will be done just before the next render, by the
435
 * InternalMaster (by calling doWork())
436
 *
437
 * @param effects DistortedEffects to remove.
438
 */
439
  public void detach(DistortedEffects effects)
440
    {
441
    mChildren.detach(effects);
442
    }
443

    
444
///////////////////////////////////////////////////////////////////////////////////////////////////
445
/**
446
 * Removes all children Nodes.
447
 * <p>
448
 * We cannot do this mid-render - actual detachment will be done just before the next render, by the
449
 * InternalMaster (by calling doWork())
450
 */
451
  public void detachAll()
452
    {
453
    mChildren.detachAll();
454
    }
455

    
456
///////////////////////////////////////////////////////////////////////////////////////////////////
457
/**
458
 * Returns the DistortedEffects object that's in the Node.
459
 * 
460
 * @return The DistortedEffects contained in the Node.
461
 */
462
  public DistortedEffects getEffects()
463
    {
464
    return mEffects;
465
    }
466

    
467
///////////////////////////////////////////////////////////////////////////////////////////////////
468
  /**
469
   * Returns the surface this object gets rendered to.
470
   *
471
   * @return The InternalSurface contained in the Node (if a leaf), or the FBO (if an internal Node)
472
   */
473
  public InternalSurface getSurface()
474
    {
475
    return mChildren.getNumChildren()==0 ? mSurface : mData.mFBO;
476
    }
477

    
478
///////////////////////////////////////////////////////////////////////////////////////////////////
479
/**
480
 * Returns the Mesh object that's in the Node.
481
 *
482
 * @return Mesh contained in the Node.
483
 */
484
  public MeshBase getMesh()
485
    {
486
    return mMesh;
487
    }
488

    
489
///////////////////////////////////////////////////////////////////////////////////////////////////
490
/**
491
 * Resizes the DistortedFramebuffer object that we render this Node to.
492
 */
493
  public void resize(int width, int height)
494
    {
495
    mFboW = width;
496
    mFboH = height;
497

    
498
    if ( mData.mFBO !=null )
499
      {
500
      // TODO: potentially allocate a new NodeData if we have to
501
      mData.mFBO.resize(width,height);
502
      }
503
    }
504

    
505
///////////////////////////////////////////////////////////////////////////////////////////////////
506
/**
507
 * Enables/disables DEPTH and STENCIL buffers in the Framebuffer object that we render this Node to.
508
 */
509
  public void enableDepthStencil(int depthStencil)
510
    {
511
    mFboDepthStencil = depthStencil;
512

    
513
    if ( mData.mFBO !=null )
514
      {
515
      // TODO: potentially allocate a new NodeData if we have to
516
      mData.mFBO.enableDepthStencil(depthStencil);
517
      }
518
    }
519

    
520
///////////////////////////////////////////////////////////////////////////////////////////////////
521
// APIs that control how to set the OpenGL state just before rendering this Node.
522
///////////////////////////////////////////////////////////////////////////////////////////////////
523
/**
524
 * When rendering this Node, use ColorMask (r,g,b,a).
525
 *
526
 * @param r Write to the RED color channel when rendering this Node?
527
 * @param g Write to the GREEN color channel when rendering this Node?
528
 * @param b Write to the BLUE color channel when rendering this Node?
529
 * @param a Write to the ALPHA channel when rendering this Node?
530
 */
531
  @SuppressWarnings("unused")
532
  public void glColorMask(boolean r, boolean g, boolean b, boolean a)
533
    {
534
    mState.glColorMask(r,g,b,a);
535
    }
536

    
537
///////////////////////////////////////////////////////////////////////////////////////////////////
538
/**
539
 * When rendering this Node, switch on writing to Depth buffer?
540
 *
541
 * @param mask Write to the Depth buffer when rendering this Node?
542
 */
543
  @SuppressWarnings("unused")
544
  public void glDepthMask(boolean mask)
545
    {
546
    mState.glDepthMask(mask);
547
    }
548

    
549
///////////////////////////////////////////////////////////////////////////////////////////////////
550
/**
551
 * When rendering this Node, which bits of the Stencil buffer to write to?
552
 *
553
 * @param mask Marks the bits of the Stencil buffer we will write to when rendering this Node.
554
 */
555
  @SuppressWarnings("unused")
556
  public void glStencilMask(int mask)
557
    {
558
    mState.glStencilMask(mask);
559
    }
560

    
561
///////////////////////////////////////////////////////////////////////////////////////////////////
562
/**
563
 * When rendering this Node, which Tests to enable?
564
 *
565
 * @param test Valid values: GL_DEPTH_TEST, GL_STENCIL_TEST, GL_BLEND
566
 */
567
  @SuppressWarnings("unused")
568
  public void glEnable(int test)
569
    {
570
    mState.glEnable(test);
571
    }
572

    
573
///////////////////////////////////////////////////////////////////////////////////////////////////
574
/**
575
 * When rendering this Node, which Tests to enable?
576
 *
577
 * @param test Valid values: GL_DEPTH_TEST, GL_STENCIL_TEST, GL_BLEND
578
 */
579
  @SuppressWarnings("unused")
580
  public void glDisable(int test)
581
    {
582
    mState.glDisable(test);
583
    }
584

    
585
///////////////////////////////////////////////////////////////////////////////////////////////////
586
/**
587
 * When rendering this Node, use the following StencilFunc.
588
 *
589
 * @param func Valid values: GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL
590
 * @param ref  Reference valut to compare our stencil with.
591
 * @param mask Mask used when comparing.
592
 */
593
  @SuppressWarnings("unused")
594
  public void glStencilFunc(int func, int ref, int mask)
595
    {
596
    mState.glStencilFunc(func,ref,mask);
597
    }
598

    
599
///////////////////////////////////////////////////////////////////////////////////////////////////
600
/**
601
 * When rendering this Node, use the following StencilOp.
602
 * <p>
603
 * Valid values of all 3 parameters: GL_KEEP, GL_ZERO, GL_REPLACE, GL_INCR, GL_DECR, GL_INVERT, GL_INCR_WRAP, GL_DECR_WRAP
604
 *
605
 * @param sfail  What to do when Stencil Test fails.
606
 * @param dpfail What to do when Depth Test fails.
607
 * @param dppass What to do when Depth Test passes.
608
 */
609
  @SuppressWarnings("unused")
610
  public void glStencilOp(int sfail, int dpfail, int dppass)
611
    {
612
    mState.glStencilOp(sfail,dpfail,dppass);
613
    }
614

    
615
///////////////////////////////////////////////////////////////////////////////////////////////////
616
/**
617
 * When rendering this Node, use the following DepthFunc.
618
 *
619
 * @param func Valid values: GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL
620
 */
621
  @SuppressWarnings("unused")
622
  public void glDepthFunc(int func)
623
    {
624
    mState.glDepthFunc(func);
625
    }
626

    
627
///////////////////////////////////////////////////////////////////////////////////////////////////
628
/**
629
 * When rendering this Node, use the following Blending mode.
630
 * <p>
631
 * Valid values: GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
632
 *               GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
633
 *               GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_SRC_ALPHA_SATURATE
634
 *
635
 * @param src Source Blend function
636
 * @param dst Destination Blend function
637
 */
638
  @SuppressWarnings("unused")
639
  public void glBlendFunc(int src, int dst)
640
    {
641
    mState.glBlendFunc(src,dst);
642
    }
643

    
644
///////////////////////////////////////////////////////////////////////////////////////////////////
645
/**
646
 * Before rendering this Node, clear the following buffers.
647
 * <p>
648
 * Valid values: 0, or bitwise OR of one or more values from the set GL_COLOR_BUFFER_BIT,
649
 *               GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT.
650
 * Default: 0
651
 *
652
 * @param mask bitwise OR of BUFFER_BITs to clear.
653
 */
654
  @SuppressWarnings("unused")
655
  public void glClear(int mask)
656
    {
657
    mState.glClear(mask);
658
    }
659
  }
(4-4/14)