propane 3.1.0.pre-java → 3.2.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.mvn/wrapper/maven-wrapper.properties +1 -0
  3. data/CHANGELOG.md +1 -5
  4. data/README.md +23 -12
  5. data/Rakefile +23 -12
  6. data/lib/propane/helpers/version_error.rb +6 -0
  7. data/lib/propane/runner.rb +12 -0
  8. data/lib/propane/version.rb +1 -1
  9. data/library/slider/slider.rb +1 -1
  10. data/mvnw +234 -0
  11. data/mvnw.cmd +145 -0
  12. data/pom.xml +28 -27
  13. data/propane.gemspec +2 -2
  14. data/src/main/java/japplemenubar/JAppleMenuBar.java +41 -47
  15. data/src/main/java/monkstone/ColorUtil.java +1 -1
  16. data/src/main/java/monkstone/MathToolModule.java +12 -11
  17. data/src/main/java/monkstone/PropaneLibrary.java +9 -10
  18. data/src/main/java/monkstone/core/LibraryProxy.java +124 -113
  19. data/src/main/java/monkstone/fastmath/Deglut.java +86 -89
  20. data/src/main/java/monkstone/filechooser/Chooser.java +7 -13
  21. data/src/main/java/monkstone/noise/SimplexNoise.java +0 -1
  22. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +4 -4
  23. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
  24. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +9 -9
  25. data/src/main/java/monkstone/slider/SimpleSlider.java +0 -9
  26. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +11 -13
  27. data/src/main/java/monkstone/slider/Slider.java +1 -1
  28. data/src/main/java/monkstone/slider/SliderBar.java +1 -1
  29. data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
  30. data/src/main/java/monkstone/slider/WheelHandler.java +8 -9
  31. data/src/main/java/monkstone/vecmath/AppRender.java +2 -2
  32. data/src/main/java/monkstone/vecmath/ShapeRender.java +2 -2
  33. data/src/main/java/monkstone/vecmath/package-info.java +2 -2
  34. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +2 -2
  35. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -1
  36. data/src/main/java/monkstone/videoevent/VideoInterface.java +11 -5
  37. data/src/main/java/monkstone/videoevent/package-info.java +2 -2
  38. data/src/main/java/processing/awt/PGraphicsJava2D.java +1742 -2243
  39. data/src/main/java/processing/awt/PShapeJava2D.java +268 -270
  40. data/src/main/java/processing/awt/PSurfaceAWT.java +821 -920
  41. data/src/main/java/processing/core/DesktopHandler.java +94 -0
  42. data/src/main/java/processing/core/PApplet.java +14170 -14082
  43. data/src/main/java/processing/core/PConstants.java +447 -473
  44. data/src/main/java/processing/core/PFont.java +867 -873
  45. data/src/main/java/processing/core/PGraphics.java +7193 -7428
  46. data/src/main/java/processing/core/PImage.java +3051 -3117
  47. data/src/main/java/processing/core/PMatrix.java +159 -172
  48. data/src/main/java/processing/core/PMatrix2D.java +403 -444
  49. data/src/main/java/processing/core/PMatrix3D.java +735 -749
  50. data/src/main/java/processing/core/PShape.java +2651 -2793
  51. data/src/main/java/processing/core/PShapeOBJ.java +415 -422
  52. data/src/main/java/processing/core/PShapeSVG.java +1466 -1475
  53. data/src/main/java/processing/core/PStyle.java +37 -40
  54. data/src/main/java/processing/core/PSurface.java +98 -103
  55. data/src/main/java/processing/core/PSurfaceNone.java +208 -236
  56. data/src/main/java/processing/core/PVector.java +961 -990
  57. data/src/main/java/processing/data/DoubleDict.java +709 -753
  58. data/src/main/java/processing/data/DoubleList.java +695 -748
  59. data/src/main/java/processing/data/FloatDict.java +702 -746
  60. data/src/main/java/processing/data/FloatList.java +697 -751
  61. data/src/main/java/processing/data/IntDict.java +673 -718
  62. data/src/main/java/processing/data/IntList.java +633 -699
  63. data/src/main/java/processing/data/JSONArray.java +873 -931
  64. data/src/main/java/processing/data/JSONObject.java +1165 -1262
  65. data/src/main/java/processing/data/JSONTokener.java +341 -351
  66. data/src/main/java/processing/data/LongDict.java +662 -707
  67. data/src/main/java/processing/data/LongList.java +634 -700
  68. data/src/main/java/processing/data/Sort.java +41 -37
  69. data/src/main/java/processing/data/StringDict.java +486 -522
  70. data/src/main/java/processing/data/StringList.java +580 -624
  71. data/src/main/java/processing/data/Table.java +3508 -3686
  72. data/src/main/java/processing/data/TableRow.java +183 -182
  73. data/src/main/java/processing/data/XML.java +883 -957
  74. data/src/main/java/processing/event/Event.java +66 -87
  75. data/src/main/java/processing/event/KeyEvent.java +41 -48
  76. data/src/main/java/processing/event/MouseEvent.java +93 -103
  77. data/src/main/java/processing/event/TouchEvent.java +6 -10
  78. data/src/main/java/processing/javafx/PGraphicsFX2D.java +5 -69
  79. data/src/main/java/processing/javafx/PSurfaceFX.java +2 -7
  80. data/src/main/java/processing/opengl/FontTexture.java +270 -290
  81. data/src/main/java/processing/opengl/FrameBuffer.java +363 -375
  82. data/src/main/java/processing/opengl/LinePath.java +500 -543
  83. data/src/main/java/processing/opengl/LineStroker.java +582 -593
  84. data/src/main/java/processing/opengl/PGL.java +2881 -2904
  85. data/src/main/java/processing/opengl/PGraphics2D.java +315 -408
  86. data/src/main/java/processing/opengl/PGraphics3D.java +72 -107
  87. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +12043 -12230
  88. data/src/main/java/processing/opengl/PJOGL.java +1681 -1745
  89. data/src/main/java/processing/opengl/PShader.java +1257 -1260
  90. data/src/main/java/processing/opengl/PShapeOpenGL.java +4599 -4662
  91. data/src/main/java/processing/opengl/PSurfaceJOGL.java +1030 -1047
  92. data/src/main/java/processing/opengl/Texture.java +1397 -1462
  93. data/src/main/java/processing/opengl/VertexBuffer.java +55 -57
  94. data/src/main/resources/icon/icon-1024.png +0 -0
  95. data/src/main/resources/icon/icon-128.png +0 -0
  96. data/src/main/resources/icon/icon-16.png +0 -0
  97. data/src/main/resources/icon/icon-256.png +0 -0
  98. data/src/main/resources/icon/icon-32.png +0 -0
  99. data/src/main/resources/icon/icon-48.png +0 -0
  100. data/src/main/resources/icon/icon-512.png +0 -0
  101. data/src/main/resources/icon/icon-64.png +0 -0
  102. data/vendors/Rakefile +1 -1
  103. metadata +12 -8
  104. data/src/main/java/processing/core/ThinkDifferent.java +0 -70
@@ -1,5 +1,3 @@
1
- /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
-
3
1
  /*
4
2
  Part of the Processing project - http://processing.org
5
3
 
@@ -20,8 +18,7 @@
20
18
  Public License along with this library; if not, write to the
21
19
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
22
20
  Boston, MA 02111-1307 USA
23
- */
24
-
21
+ */
25
22
  package processing.opengl;
26
23
 
27
24
  import processing.core.PApplet;
@@ -37,1634 +34,1572 @@ import java.util.LinkedList;
37
34
  import java.util.NoSuchElementException;
38
35
 
39
36
  /**
40
- * This class wraps an OpenGL texture.
41
- * By Andres Colubri
37
+ * This class wraps an OpenGL texture. By Andres Colubri
42
38
  *
43
39
  */
44
40
  public class Texture implements PConstants {
45
- /**
46
- * Texture with normalized UV.
47
- */
48
- protected static final int TEX2D = 0;
49
- /**
50
- * Texture with un-normalized UV.
51
- */
52
- protected static final int TEXRECT = 1;
53
-
54
- /** Point sampling: both magnification and minification filtering are set
55
- * to nearest */
56
- protected static final int POINT = 2;
57
- /** Linear sampling: magnification filtering is nearest, minification set
58
- * to linear */
59
- protected static final int LINEAR = 3;
60
- /** Bilinear sampling: both magnification filtering is set to linear and
61
- * minification either to linear-mipmap-nearest (linear interpolation is used
62
- * within a mipmap, but not between different mipmaps). */
63
- protected static final int BILINEAR = 4;
64
- /** Trilinear sampling: magnification filtering set to linear, minification to
65
- * linear-mipmap-linear, which offers the best mipmap quality since linear
66
- * interpolation to compute the value in each of two maps and then
67
- * interpolates linearly between these two values. */
68
- protected static final int TRILINEAR = 5;
69
-
70
-
71
- // This constant controls how many times pixelBuffer and rgbaPixels can be
72
- // accessed before they are not released anymore. The idea is that if they
73
- // have been used only a few times, it doesn't make sense to keep them around.
74
- protected static final int MAX_UPDATES = 10;
75
-
76
- // The minimum amount of free JVM's memory (in MB) before pixelBuffer and
77
- // rgbaPixels are released every time after they are used.
78
- protected static final int MIN_MEMORY = 5;
79
-
80
- public int width, height;
81
-
82
- public int glName;
83
- public int glTarget;
84
- public int glFormat;
85
- public int glMinFilter;
86
- public int glMagFilter;
87
- public int glWrapS;
88
- public int glWrapT;
89
- public int glWidth;
90
- public int glHeight;
91
- private GLResourceTexture glres;
92
-
93
- protected PGraphicsOpenGL pg;
94
- protected PGL pgl; // The interface between Processing and OpenGL.
95
- protected int context; // The context that created this texture.
96
- protected boolean colorBuffer; // true if it is the color attachment of
97
- // FrameBuffer object.
98
-
99
- protected boolean usingMipmaps;
100
- protected boolean usingRepeat;
101
- protected float maxTexcoordU;
102
- protected float maxTexcoordV;
103
- protected boolean bound;
104
-
105
- protected boolean invertedX;
106
- protected boolean invertedY;
107
-
108
- protected int[] rgbaPixels = null;
109
- protected IntBuffer pixelBuffer = null;
110
-
111
- protected int[] edgePixels = null;
112
- protected IntBuffer edgeBuffer = null;
113
-
114
- protected FrameBuffer tempFbo = null;
115
- protected int pixBufUpdateCount = 0;
116
- protected int rgbaPixUpdateCount = 0;
117
-
118
- /** Modified portion of the texture */
119
- protected boolean modified;
120
- protected int mx1, my1, mx2, my2;
121
-
122
- protected Object bufferSource;
123
- protected LinkedList<BufferData> bufferCache = null;
124
- protected LinkedList<BufferData> usedBuffers = null;
125
- protected Method disposeBufferMethod;
126
- public static final int MAX_BUFFER_CACHE_SIZE = 3;
127
-
128
- ////////////////////////////////////////////////////////////
129
-
130
- // Constructors.
131
-
132
-
133
- public Texture(PGraphicsOpenGL pg) {
134
- this.pg = pg;
135
- pgl = pg.pgl;
136
- context = pgl.createEmptyContext();
137
-
138
- colorBuffer = false;
139
-
140
- glName = 0;
141
- }
142
-
143
-
144
- /**
145
- * Creates an instance of PTexture with size width x height. The texture is
146
- * initialized (empty) to that size.
147
- * @param width int
148
- * @param height int
149
- */
150
- public Texture(PGraphicsOpenGL pg, int width, int height) {
151
- this(pg, width, height, new Parameters());
152
- }
153
-
154
-
155
- /**
156
- * Creates an instance of PTexture with size width x height and with the
157
- * specified parameters. The texture is initialized (empty) to that size.
158
- * @param width int
159
- * @param height int
160
- * @param params Parameters
161
- */
162
- public Texture(PGraphicsOpenGL pg, int width, int height, Object params) {
163
- this.pg = pg;
164
- pgl = pg.pgl;
165
- context = pgl.createEmptyContext();
166
-
167
- colorBuffer = false;
168
-
169
- glName = 0;
170
-
171
- init(width, height, (Parameters)params);
172
- }
173
-
174
-
175
- ////////////////////////////////////////////////////////////
176
-
177
- // Init, resize methods
178
-
179
-
180
- /**
181
- * Sets the size of the image and texture to width x height. If the texture is
182
- * already initialized, it first destroys the current OpenGL texture object
183
- * and then creates a new one with the specified size.
184
- * @param width int
185
- * @param height int
186
- */
187
- public void init(int width, int height) {
188
- Parameters params;
189
- if (0 < glName) {
190
- // Re-initializing a pre-existing texture.
191
- // We use the current parameters as default:
192
- params = getParameters();
193
- } else {
194
- // Just built-in default parameters otherwise:
195
- params = new Parameters();
196
- }
197
- init(width, height, params);
198
- }
199
41
 
42
+ /**
43
+ * Texture with normalized UV.
44
+ */
45
+ protected static final int TEX2D = 0;
46
+ /**
47
+ * Texture with un-normalized UV.
48
+ */
49
+ protected static final int TEXRECT = 1;
200
50
 
201
- /**
202
- * Sets the size of the image and texture to width x height, and the
203
- * parameters of the texture to params. If the texture is already initialized,
204
- * it first destroys the current OpenGL texture object and then creates a new
205
- * one with the specified size.
206
- * @param width int
207
- * @param height int
208
- * @param params GLTextureParameters
209
- */
210
- public void init(int width, int height, Parameters params) {
211
- setParameters(params);
212
- setSize(width, height);
213
- allocate();
214
- }
51
+ /**
52
+ * Point sampling: both magnification and minification filtering are set to
53
+ * nearest
54
+ */
55
+ protected static final int POINT = 2;
56
+ /**
57
+ * Linear sampling: magnification filtering is nearest, minification set to
58
+ * linear
59
+ */
60
+ protected static final int LINEAR = 3;
61
+ /**
62
+ * Bilinear sampling: both magnification filtering is set to linear and
63
+ * minification either to linear-mipmap-nearest (linear interpolation is
64
+ * used within a mipmap, but not between different mipmaps).
65
+ */
66
+ protected static final int BILINEAR = 4;
67
+ /**
68
+ * Trilinear sampling: magnification filtering set to linear, minification
69
+ * to linear-mipmap-linear, which offers the best mipmap quality since
70
+ * linear interpolation to compute the value in each of two maps and then
71
+ * interpolates linearly between these two values.
72
+ */
73
+ protected static final int TRILINEAR = 5;
74
+
75
+ // This constant controls how many times pixelBuffer and rgbaPixels can be
76
+ // accessed before they are not released anymore. The idea is that if they
77
+ // have been used only a few times, it doesn't make sense to keep them around.
78
+ protected static final int MAX_UPDATES = 10;
79
+
80
+ // The minimum amount of free JVM's memory (in MB) before pixelBuffer and
81
+ // rgbaPixels are released every time after they are used.
82
+ protected static final int MIN_MEMORY = 5;
83
+
84
+ public int width, height;
85
+
86
+ public int glName;
87
+ public int glTarget;
88
+ public int glFormat;
89
+ public int glMinFilter;
90
+ public int glMagFilter;
91
+ public int glWrapS;
92
+ public int glWrapT;
93
+ public int glWidth;
94
+ public int glHeight;
95
+ private GLResourceTexture glres;
96
+
97
+ protected PGraphicsOpenGL pg;
98
+ protected PGL pgl; // The interface between Processing and OpenGL.
99
+ protected int context; // The context that created this texture.
100
+ protected boolean colorBuffer; // true if it is the color attachment of
101
+ // FrameBuffer object.
102
+
103
+ protected boolean usingMipmaps;
104
+ protected boolean usingRepeat;
105
+ protected float maxTexcoordU;
106
+ protected float maxTexcoordV;
107
+ protected boolean bound;
108
+
109
+ protected boolean invertedX;
110
+ protected boolean invertedY;
111
+
112
+ protected int[] rgbaPixels = null;
113
+ protected IntBuffer pixelBuffer = null;
114
+
115
+ protected int[] edgePixels = null;
116
+ protected IntBuffer edgeBuffer = null;
117
+
118
+ protected FrameBuffer tempFbo = null;
119
+ protected int pixBufUpdateCount = 0;
120
+ protected int rgbaPixUpdateCount = 0;
215
121
 
122
+ /**
123
+ * Modified portion of the texture
124
+ */
125
+ protected boolean modified;
126
+ protected int mx1, my1, mx2, my2;
216
127
 
217
- /**
218
- * Initializes the texture using GL parameters
219
- */
220
- public void init(int width, int height,
221
- int glName, int glTarget, int glFormat,
222
- int glWidth, int glHeight,
223
- int glMinFilter, int glMagFilter,
224
- int glWrapS, int glWrapT) {
225
- this.width = width;
226
- this.height = height;
128
+ protected Object bufferSource;
129
+ protected LinkedList<BufferData> bufferCache = null;
130
+ protected LinkedList<BufferData> usedBuffers = null;
131
+ protected Method disposeBufferMethod;
132
+ public static final int MAX_BUFFER_CACHE_SIZE = 3;
227
133
 
228
- this.glName = glName;
229
- this.glTarget = glTarget;
230
- this.glFormat = glFormat;
231
- this.glWidth = glWidth;
232
- this.glHeight = glHeight;
233
- this.glMinFilter = glMinFilter;
234
- this.glMagFilter = glMagFilter;
235
- this.glWrapS = glWrapS;
236
- this.glWrapT = glWrapT;
134
+ ////////////////////////////////////////////////////////////
135
+ // Constructors.
136
+ public Texture(PGraphicsOpenGL pg) {
137
+ this.pg = pg;
138
+ pgl = pg.pgl;
139
+ context = pgl.createEmptyContext();
237
140
 
238
- maxTexcoordU = (float)width / glWidth;
239
- maxTexcoordV = (float)height / glHeight;
141
+ colorBuffer = false;
240
142
 
241
- usingMipmaps = glMinFilter == PGL.LINEAR_MIPMAP_NEAREST ||
242
- glMinFilter == PGL.LINEAR_MIPMAP_LINEAR;
143
+ glName = 0;
144
+ }
243
145
 
244
- usingRepeat = glWrapS == PGL.REPEAT || glWrapT == PGL.REPEAT;
245
- }
146
+ /**
147
+ * Creates an instance of PTexture with size width x height. The texture is
148
+ * initialized (empty) to that size.
149
+ *
150
+ * @param width int
151
+ * @param height int
152
+ */
153
+ public Texture(PGraphicsOpenGL pg, int width, int height) {
154
+ this(pg, width, height, new Parameters());
155
+ }
246
156
 
157
+ /**
158
+ * Creates an instance of PTexture with size width x height and with the
159
+ * specified parameters. The texture is initialized (empty) to that size.
160
+ *
161
+ * @param width int
162
+ * @param height int
163
+ * @param params Parameters
164
+ */
165
+ public Texture(PGraphicsOpenGL pg, int width, int height, Object params) {
166
+ this.pg = pg;
167
+ pgl = pg.pgl;
168
+ context = pgl.createEmptyContext();
247
169
 
248
- public void resize(int wide, int high) {
249
- // Disposing current resources.
250
- dispose();
170
+ colorBuffer = false;
251
171
 
252
- // Creating new texture with the appropriate size.
253
- Texture tex = new Texture(pg, wide, high, getParameters());
172
+ glName = 0;
254
173
 
255
- // Copying the contents of this texture into tex.
256
- tex.set(this);
174
+ init(width, height, (Parameters) params);
175
+ }
257
176
 
258
- // Now, overwriting "this" with tex.
259
- copyObject(tex);
177
+ ////////////////////////////////////////////////////////////
178
+ // Init, resize methods
179
+ /**
180
+ * Sets the size of the image and texture to width x height. If the texture
181
+ * is already initialized, it first destroys the current OpenGL texture
182
+ * object and then creates a new one with the specified size.
183
+ *
184
+ * @param width int
185
+ * @param height int
186
+ */
187
+ public void init(int width, int height) {
188
+ Parameters params;
189
+ if (0 < glName) {
190
+ // Re-initializing a pre-existing texture.
191
+ // We use the current parameters as default:
192
+ params = getParameters();
193
+ } else {
194
+ // Just built-in default parameters otherwise:
195
+ params = new Parameters();
196
+ }
197
+ init(width, height, params);
198
+ }
260
199
 
261
- // Nullifying some utility objects so they are recreated with the
262
- // appropriate size when needed.
263
- tempFbo = null;
264
- }
200
+ /**
201
+ * Sets the size of the image and texture to width x height, and the
202
+ * parameters of the texture to params. If the texture is already
203
+ * initialized, it first destroys the current OpenGL texture object and then
204
+ * creates a new one with the specified size.
205
+ *
206
+ * @param width int
207
+ * @param height int
208
+ * @param params GLTextureParameters
209
+ */
210
+ public void init(int width, int height, Parameters params) {
211
+ setParameters(params);
212
+ setSize(width, height);
213
+ allocate();
214
+ }
265
215
 
216
+ /**
217
+ * Initializes the texture using GL parameters
218
+ */
219
+ public void init(int width, int height,
220
+ int glName, int glTarget, int glFormat,
221
+ int glWidth, int glHeight,
222
+ int glMinFilter, int glMagFilter,
223
+ int glWrapS, int glWrapT) {
224
+ this.width = width;
225
+ this.height = height;
266
226
 
267
- /**
268
- * Returns true if the texture has been initialized.
269
- * @return boolean
270
- */
271
- public boolean available() {
272
- return 0 < glName;
273
- }
227
+ this.glName = glName;
228
+ this.glTarget = glTarget;
229
+ this.glFormat = glFormat;
230
+ this.glWidth = glWidth;
231
+ this.glHeight = glHeight;
232
+ this.glMinFilter = glMinFilter;
233
+ this.glMagFilter = glMagFilter;
234
+ this.glWrapS = glWrapS;
235
+ this.glWrapT = glWrapT;
274
236
 
237
+ maxTexcoordU = (float) width / glWidth;
238
+ maxTexcoordV = (float) height / glHeight;
275
239
 
276
- ////////////////////////////////////////////////////////////
240
+ usingMipmaps = glMinFilter == PGL.LINEAR_MIPMAP_NEAREST
241
+ || glMinFilter == PGL.LINEAR_MIPMAP_LINEAR;
277
242
 
278
- // Set methods
243
+ usingRepeat = glWrapS == PGL.REPEAT || glWrapT == PGL.REPEAT;
244
+ }
279
245
 
246
+ public void resize(int wide, int high) {
247
+ // Disposing current resources.
248
+ dispose();
280
249
 
281
- public void set(Texture tex) {
282
- copyTexture(tex, 0, 0, tex.width, tex.height, true);
283
- }
250
+ // Creating new texture with the appropriate size.
251
+ Texture tex = new Texture(pg, wide, high, getParameters());
284
252
 
253
+ // Copying the contents of this texture into tex.
254
+ tex.set(this);
285
255
 
286
- public void set(Texture tex, int x, int y, int w, int h) {
287
- copyTexture(tex, x, y, w, h, true);
288
- }
256
+ // Now, overwriting "this" with tex.
257
+ copyObject(tex);
289
258
 
259
+ // Nullifying some utility objects so they are recreated with the
260
+ // appropriate size when needed.
261
+ tempFbo = null;
262
+ }
290
263
 
291
- public void set(int texTarget, int texName, int texWidth, int texHeight,
292
- int w, int h) {
293
- copyTexture(texTarget, texName, texWidth, texHeight, 0, 0, w, h, true);
294
- }
264
+ /**
265
+ * Returns true if the texture has been initialized.
266
+ *
267
+ * @return boolean
268
+ */
269
+ public boolean available() {
270
+ return 0 < glName;
271
+ }
295
272
 
273
+ ////////////////////////////////////////////////////////////
274
+ // Set methods
275
+ public void set(Texture tex) {
276
+ copyTexture(tex, 0, 0, tex.width, tex.height, true);
277
+ }
296
278
 
297
- public void set(int texTarget, int texName, int texWidth, int texHeight,
298
- int target, int tex, int x, int y, int w, int h) {
299
- copyTexture(texTarget, texName, texWidth, texHeight, x, y, w, h, true);
300
- }
279
+ public void set(Texture tex, int x, int y, int w, int h) {
280
+ copyTexture(tex, x, y, w, h, true);
281
+ }
301
282
 
283
+ public void set(int texTarget, int texName, int texWidth, int texHeight,
284
+ int w, int h) {
285
+ copyTexture(texTarget, texName, texWidth, texHeight, 0, 0, w, h, true);
286
+ }
302
287
 
303
- public void set(int[] pixels) {
304
- set(pixels, 0, 0, width, height, ARGB);
305
- }
288
+ public void set(int texTarget, int texName, int texWidth, int texHeight,
289
+ int target, int tex, int x, int y, int w, int h) {
290
+ copyTexture(texTarget, texName, texWidth, texHeight, x, y, w, h, true);
291
+ }
306
292
 
293
+ public void set(int[] pixels) {
294
+ set(pixels, 0, 0, width, height, ARGB);
295
+ }
307
296
 
308
- public void set(int[] pixels, int format) {
309
- set(pixels, 0, 0, width, height, format);
310
- }
297
+ public void set(int[] pixels, int format) {
298
+ set(pixels, 0, 0, width, height, format);
299
+ }
311
300
 
301
+ public void set(int[] pixels, int x, int y, int w, int h) {
302
+ set(pixels, x, y, w, h, ARGB);
303
+ }
312
304
 
313
- public void set(int[] pixels, int x, int y, int w, int h) {
314
- set(pixels, x, y, w, h, ARGB);
315
- }
305
+ public void set(int[] pixels, int x, int y, int w, int h, int format) {
306
+ if (pixels == null) {
307
+ PGraphics.showWarning("The pixels array is null.");
308
+ return;
309
+ }
310
+ if (pixels.length < w * h) {
311
+ PGraphics.showWarning("The pixel array has a length of "
312
+ + pixels.length + ", but it should be at least "
313
+ + w * h);
314
+ return;
315
+ }
316
316
 
317
+ if (pixels.length == 0 || w == 0 || h == 0) {
318
+ return;
319
+ }
317
320
 
318
- public void set(int[] pixels, int x, int y, int w, int h, int format) {
319
- if (pixels == null) {
320
- PGraphics.showWarning("The pixels array is null.");
321
- return;
322
- }
323
- if (pixels.length < w * h) {
324
- PGraphics.showWarning("The pixel array has a length of " +
325
- pixels.length + ", but it should be at least " +
326
- w * h);
327
- return;
328
- }
321
+ boolean enabledTex = false;
322
+ if (!pgl.texturingIsEnabled(glTarget)) {
323
+ pgl.enableTexturing(glTarget);
324
+ enabledTex = true;
325
+ }
326
+ pgl.bindTexture(glTarget, glName);
329
327
 
330
- if (pixels.length == 0 || w == 0 || h == 0) {
331
- return;
332
- }
328
+ loadPixels(w * h);
329
+ convertToRGBA(pixels, format, w, h);
330
+ if (invertedX) {
331
+ flipArrayOnX(rgbaPixels, 1);
332
+ }
333
+ if (invertedY) {
334
+ flipArrayOnY(rgbaPixels, 1);
335
+ }
336
+ updatePixelBuffer(rgbaPixels);
337
+ pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE,
338
+ pixelBuffer);
339
+ fillEdges(x, y, w, h);
340
+
341
+ if (usingMipmaps) {
342
+ if (PGraphicsOpenGL.autoMipmapGenSupported) {
343
+ pgl.generateMipmap(glTarget);
344
+ } else {
345
+ manualMipmap();
346
+ }
347
+ }
333
348
 
334
- boolean enabledTex = false;
335
- if (!pgl.texturingIsEnabled(glTarget)) {
336
- pgl.enableTexturing(glTarget);
337
- enabledTex = true;
338
- }
339
- pgl.bindTexture(glTarget, glName);
349
+ pgl.bindTexture(glTarget, 0);
350
+ if (enabledTex) {
351
+ pgl.disableTexturing(glTarget);
352
+ }
340
353
 
341
- loadPixels(w * h);
342
- convertToRGBA(pixels, format, w, h);
343
- if (invertedX) flipArrayOnX(rgbaPixels, 1);
344
- if (invertedY) flipArrayOnY(rgbaPixels, 1);
345
- updatePixelBuffer(rgbaPixels);
346
- pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE,
347
- pixelBuffer);
348
- fillEdges(x, y, w, h);
354
+ releasePixelBuffer();
355
+ releaseRGBAPixels();
349
356
 
350
- if (usingMipmaps) {
351
- if (PGraphicsOpenGL.autoMipmapGenSupported) {
352
- pgl.generateMipmap(glTarget);
353
- } else {
354
- manualMipmap();
355
- }
357
+ updateTexels(x, y, w, h);
356
358
  }
357
359
 
358
- pgl.bindTexture(glTarget, 0);
359
- if (enabledTex) {
360
- pgl.disableTexturing(glTarget);
360
+ ////////////////////////////////////////////////////////////
361
+ // Native set methods
362
+ public void setNative(int[] pixels) {
363
+ setNative(pixels, 0, 0, width, height);
361
364
  }
362
365
 
363
- releasePixelBuffer();
364
- releaseRGBAPixels();
365
-
366
- updateTexels(x, y, w, h);
367
- }
366
+ public void setNative(int[] pixels, int x, int y, int w, int h) {
367
+ updatePixelBuffer(pixels);
368
+ setNative(pixelBuffer, x, y, w, h);
369
+ releasePixelBuffer();
370
+ }
368
371
 
372
+ public void setNative(IntBuffer pixBuf, int x, int y, int w, int h) {
373
+ if (pixBuf == null) {
374
+ pixBuf = null;
375
+ PGraphics.showWarning("The pixel buffer is null.");
376
+ return;
377
+ }
378
+ if (pixBuf.capacity() < w * h) {
379
+ PGraphics.showWarning("The pixel bufer has a length of "
380
+ + pixBuf.capacity() + ", but it should be at least "
381
+ + w * h);
382
+ return;
383
+ }
369
384
 
370
- ////////////////////////////////////////////////////////////
385
+ if (pixBuf.capacity() == 0) {
386
+ // Nothing to do (means that w == h == 0) but not an erroneous situation
387
+ return;
388
+ }
371
389
 
372
- // Native set methods
390
+ boolean enabledTex = false;
391
+ if (!pgl.texturingIsEnabled(glTarget)) {
392
+ pgl.enableTexturing(glTarget);
393
+ enabledTex = true;
394
+ }
395
+ pgl.bindTexture(glTarget, glName);
396
+
397
+ pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE,
398
+ pixBuf);
399
+ fillEdges(x, y, w, h);
400
+
401
+ if (usingMipmaps) {
402
+ if (PGraphicsOpenGL.autoMipmapGenSupported) {
403
+ pgl.generateMipmap(glTarget);
404
+ } else {
405
+ manualMipmap();
406
+ }
407
+ }
408
+ pgl.bindTexture(glTarget, 0);
409
+ if (enabledTex) {
410
+ pgl.disableTexturing(glTarget);
411
+ }
373
412
 
413
+ updateTexels(x, y, w, h);
414
+ }
374
415
 
375
- public void setNative(int[] pixels) {
376
- setNative(pixels, 0, 0, width, height);
377
- }
416
+ ////////////////////////////////////////////////////////////
417
+ // Get methods
418
+ /**
419
+ * Copy texture to pixels. Involves video memory to main memory transfer
420
+ * (slow).
421
+ */
422
+ public void get(int[] pixels) {
423
+ if (pixels == null) {
424
+ throw new RuntimeException("Trying to copy texture to null pixels array");
425
+ }
426
+ if (pixels.length != width * height) {
427
+ throw new RuntimeException("Trying to copy texture to pixels array of "
428
+ + "wrong size");
429
+ }
378
430
 
431
+ if (tempFbo == null) {
432
+ tempFbo = new FrameBuffer(pg, glWidth, glHeight);
433
+ }
379
434
 
380
- public void setNative(int[] pixels, int x, int y, int w, int h) {
381
- updatePixelBuffer(pixels);
382
- setNative(pixelBuffer, x, y, w, h);
383
- releasePixelBuffer();
384
- }
435
+ // Attaching the texture to the color buffer of a FBO, binding the FBO and
436
+ // reading the pixels from the current draw buffer (which is the color
437
+ // buffer of the FBO).
438
+ tempFbo.setColorBuffer(this);
439
+ pg.pushFramebuffer();
440
+ pg.setFramebuffer(tempFbo);
441
+ tempFbo.readPixels();
442
+ pg.popFramebuffer();
385
443
 
444
+ tempFbo.getPixels(pixels);
445
+ convertToARGB(pixels);
386
446
 
387
- public void setNative(IntBuffer pixBuf, int x, int y, int w, int h) {
388
- if (pixBuf == null) {
389
- pixBuf = null;
390
- PGraphics.showWarning("The pixel buffer is null.");
391
- return;
392
- }
393
- if (pixBuf.capacity() < w * h) {
394
- PGraphics.showWarning("The pixel bufer has a length of " +
395
- pixBuf.capacity() + ", but it should be at least " +
396
- w * h);
397
- return;
447
+ if (invertedX) {
448
+ flipArrayOnX(pixels, 1);
449
+ }
450
+ if (invertedY) {
451
+ flipArrayOnY(pixels, 1);
452
+ }
398
453
  }
399
454
 
400
- if (pixBuf.capacity() == 0) {
401
- // Nothing to do (means that w == h == 0) but not an erroneous situation
402
- return;
455
+ ////////////////////////////////////////////////////////////
456
+ // Put methods (the source texture is not resized to cover the entire
457
+ // destination).
458
+ public void put(Texture tex) {
459
+ copyTexture(tex, 0, 0, tex.width, tex.height, false);
403
460
  }
404
461
 
405
- boolean enabledTex = false;
406
- if (!pgl.texturingIsEnabled(glTarget)) {
407
- pgl.enableTexturing(glTarget);
408
- enabledTex = true;
462
+ public void put(Texture tex, int x, int y, int w, int h) {
463
+ copyTexture(tex, x, y, w, h, false);
409
464
  }
410
- pgl.bindTexture(glTarget, glName);
411
465
 
412
- pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE,
413
- pixBuf);
414
- fillEdges(x, y, w, h);
415
-
416
- if (usingMipmaps) {
417
- if (PGraphicsOpenGL.autoMipmapGenSupported) {
418
- pgl.generateMipmap(glTarget);
419
- } else {
420
- manualMipmap();
421
- }
422
- }
423
- pgl.bindTexture(glTarget, 0);
424
- if (enabledTex) {
425
- pgl.disableTexturing(glTarget);
466
+ public void put(int texTarget, int texName, int texWidth, int texHeight,
467
+ int w, int h) {
468
+ copyTexture(texTarget, texName, texWidth, texHeight, 0, 0, w, h, false);
426
469
  }
427
470
 
428
- updateTexels(x, y, w, h);
429
- }
471
+ public void put(int texTarget, int texName, int texWidth, int texHeight,
472
+ int target, int tex, int x, int y, int w, int h) {
473
+ copyTexture(texTarget, texName, texWidth, texHeight, x, y, w, h, false);
474
+ }
430
475
 
476
+ ////////////////////////////////////////////////////////////
477
+ // Get OpenGL parameters
478
+ /**
479
+ * Returns true or false whether or not the texture is using mipmaps.
480
+ *
481
+ * @return boolean
482
+ */
483
+ public boolean usingMipmaps() {
484
+ return usingMipmaps;
485
+ }
486
+
487
+ public void usingMipmaps(boolean mipmaps, int sampling) {
488
+ int glMagFilter0 = glMagFilter;
489
+ int glMinFilter0 = glMinFilter;
490
+ if (mipmaps) {
491
+ if (sampling == POINT) {
492
+ glMagFilter = PGL.NEAREST;
493
+ glMinFilter = PGL.NEAREST;
494
+ usingMipmaps = false;
495
+ } else if (sampling == LINEAR) {
496
+ glMagFilter = PGL.NEAREST;
497
+ glMinFilter
498
+ = PGL.MIPMAPS_ENABLED ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR;
499
+ usingMipmaps = true;
500
+ } else if (sampling == BILINEAR) {
501
+ glMagFilter = PGL.LINEAR;
502
+ glMinFilter
503
+ = PGL.MIPMAPS_ENABLED ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR;
504
+ usingMipmaps = true;
505
+ } else if (sampling == TRILINEAR) {
506
+ glMagFilter = PGL.LINEAR;
507
+ glMinFilter
508
+ = PGL.MIPMAPS_ENABLED ? PGL.LINEAR_MIPMAP_LINEAR : PGL.LINEAR;
509
+ usingMipmaps = true;
510
+ } else {
511
+ throw new RuntimeException("Unknown texture filtering mode");
512
+ }
513
+ } else {
514
+ usingMipmaps = false;
515
+ if (sampling == POINT) {
516
+ glMagFilter = PGL.NEAREST;
517
+ glMinFilter = PGL.NEAREST;
518
+ } else if (sampling == LINEAR) {
519
+ glMagFilter = PGL.NEAREST;
520
+ glMinFilter = PGL.LINEAR;
521
+ } else if (sampling == BILINEAR || sampling == TRILINEAR) {
522
+ glMagFilter = PGL.LINEAR;
523
+ glMinFilter = PGL.LINEAR;
524
+ } else {
525
+ throw new RuntimeException("Unknown texture filtering mode");
526
+ }
527
+ }
431
528
 
432
- ////////////////////////////////////////////////////////////
529
+ if (glMagFilter0 != glMagFilter || glMinFilter0 != glMinFilter) {
530
+ bind();
531
+ pgl.texParameteri(glTarget, PGL.TEXTURE_MIN_FILTER, glMinFilter);
532
+ pgl.texParameteri(glTarget, PGL.TEXTURE_MAG_FILTER, glMagFilter);
533
+ if (usingMipmaps) {
534
+ if (PGraphicsOpenGL.autoMipmapGenSupported) {
535
+ pgl.generateMipmap(glTarget);
536
+ } else {
537
+ manualMipmap();
538
+ }
539
+ }
540
+ unbind();
541
+ }
542
+ }
433
543
 
434
- // Get methods
544
+ /**
545
+ * Returns true or false whether or not the texture is using repeat wrap
546
+ * mode along either U or V directions.
547
+ *
548
+ * @return boolean
549
+ */
550
+ public boolean usingRepeat() {
551
+ return usingRepeat;
552
+ }
435
553
 
554
+ public void usingRepeat(boolean repeat) {
555
+ if (repeat) {
556
+ glWrapS = PGL.REPEAT;
557
+ glWrapT = PGL.REPEAT;
558
+ usingRepeat = true;
559
+ } else {
560
+ glWrapS = PGL.CLAMP_TO_EDGE;
561
+ glWrapT = PGL.CLAMP_TO_EDGE;
562
+ usingRepeat = false;
563
+ }
436
564
 
437
- /**
438
- * Copy texture to pixels. Involves video memory to main memory transfer (slow).
439
- */
440
- public void get(int[] pixels) {
441
- if (pixels == null) {
442
- throw new RuntimeException("Trying to copy texture to null pixels array");
443
- }
444
- if (pixels.length != width * height) {
445
- throw new RuntimeException("Trying to copy texture to pixels array of " +
446
- "wrong size");
565
+ bind();
566
+ pgl.texParameteri(glTarget, PGL.TEXTURE_WRAP_S, glWrapS);
567
+ pgl.texParameteri(glTarget, PGL.TEXTURE_WRAP_T, glWrapT);
568
+ unbind();
447
569
  }
448
570
 
449
- if (tempFbo == null) {
450
- tempFbo = new FrameBuffer(pg, glWidth, glHeight);
571
+ /**
572
+ * Returns the maximum possible value for the texture coordinate U
573
+ * (horizontal).
574
+ *
575
+ * @return float
576
+ */
577
+ public float maxTexcoordU() {
578
+ return maxTexcoordU;
451
579
  }
452
580
 
453
- // Attaching the texture to the color buffer of a FBO, binding the FBO and
454
- // reading the pixels from the current draw buffer (which is the color
455
- // buffer of the FBO).
456
- tempFbo.setColorBuffer(this);
457
- pg.pushFramebuffer();
458
- pg.setFramebuffer(tempFbo);
459
- tempFbo.readPixels();
460
- pg.popFramebuffer();
461
-
462
- tempFbo.getPixels(pixels);
463
- convertToARGB(pixels);
464
-
465
- if (invertedX) flipArrayOnX(pixels, 1);
466
- if (invertedY) flipArrayOnY(pixels, 1);
467
- }
581
+ /**
582
+ * Returns the maximum possible value for the texture coordinate V
583
+ * (vertical).
584
+ *
585
+ * @return float
586
+ */
587
+ public float maxTexcoordV() {
588
+ return maxTexcoordV;
589
+ }
468
590
 
591
+ /**
592
+ * Returns true if the texture is inverted along the horizontal direction.
593
+ *
594
+ * @return boolean;
595
+ */
596
+ public boolean invertedX() {
597
+ return invertedX;
598
+ }
469
599
 
470
- ////////////////////////////////////////////////////////////
600
+ /**
601
+ * Sets the texture as inverted or not along the horizontal direction.
602
+ *
603
+ * @param v boolean;
604
+ */
605
+ public void invertedX(boolean v) {
606
+ invertedX = v;
607
+ }
471
608
 
472
- // Put methods (the source texture is not resized to cover the entire
473
- // destination).
609
+ /**
610
+ * Returns true if the texture is inverted along the vertical direction.
611
+ *
612
+ * @return boolean;
613
+ */
614
+ public boolean invertedY() {
615
+ return invertedY;
616
+ }
474
617
 
618
+ /**
619
+ * Sets the texture as inverted or not along the vertical direction.
620
+ *
621
+ * @param v boolean;
622
+ */
623
+ public void invertedY(boolean v) {
624
+ invertedY = v;
625
+ }
626
+
627
+ public int currentSampling() {
628
+ if (glMagFilter == PGL.NEAREST && glMinFilter == PGL.NEAREST) {
629
+ return POINT;
630
+ } else if (glMagFilter == PGL.NEAREST
631
+ && glMinFilter == (PGL.MIPMAPS_ENABLED ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR)) {
632
+ return LINEAR;
633
+ } else if (glMagFilter == PGL.LINEAR
634
+ && glMinFilter == (PGL.MIPMAPS_ENABLED ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR)) {
635
+ return BILINEAR;
636
+ } else if (glMagFilter == PGL.LINEAR
637
+ && glMinFilter == PGL.LINEAR_MIPMAP_LINEAR) {
638
+ return TRILINEAR;
639
+ } else {
640
+ return -1;
641
+ }
642
+ }
475
643
 
476
- public void put(Texture tex) {
477
- copyTexture(tex, 0, 0, tex.width, tex.height, false);
478
- }
644
+ ////////////////////////////////////////////////////////////
645
+ // Bind/unbind
646
+ public void bind() {
647
+ // Binding a texture automatically enables texturing for the
648
+ // texture target from that moment onwards. Unbinding the texture
649
+ // won't disable texturing.
650
+ if (!pgl.texturingIsEnabled(glTarget)) {
651
+ pgl.enableTexturing(glTarget);
652
+ }
653
+ pgl.bindTexture(glTarget, glName);
654
+ bound = true;
655
+ }
656
+
657
+ public void unbind() {
658
+ if (pgl.textureIsBound(glTarget, glName)) {
659
+ // We don't want to unbind another texture
660
+ // that might be bound instead of this one.
661
+ if (!pgl.texturingIsEnabled(glTarget)) {
662
+ pgl.enableTexturing(glTarget);
663
+ pgl.bindTexture(glTarget, 0);
664
+ pgl.disableTexturing(glTarget);
665
+ } else {
666
+ pgl.bindTexture(glTarget, 0);
667
+ }
668
+ }
669
+ bound = false;
670
+ }
479
671
 
672
+ public boolean bound() {
673
+ // A true result might not necessarily mean that texturing is enabled
674
+ // (a texture can be bound to the target, but texturing is disabled).
675
+ return bound;
676
+ }
480
677
 
481
- public void put(Texture tex, int x, int y, int w, int h) {
482
- copyTexture(tex, x, y, w, h, false);
483
- }
678
+ //////////////////////////////////////////////////////////////
679
+ // Modified flag
680
+ public boolean isModified() {
681
+ return modified;
682
+ }
484
683
 
684
+ public void setModified() {
685
+ modified = true;
686
+ }
485
687
 
486
- public void put(int texTarget, int texName, int texWidth, int texHeight,
487
- int w, int h) {
488
- copyTexture(texTarget, texName, texWidth, texHeight, 0, 0, w, h, false);
489
- }
688
+ public void setModified(boolean m) {
689
+ modified = m;
690
+ }
490
691
 
692
+ public int getModifiedX1() {
693
+ return mx1;
694
+ }
491
695
 
492
- public void put(int texTarget, int texName, int texWidth, int texHeight,
493
- int target, int tex, int x, int y, int w, int h) {
494
- copyTexture(texTarget, texName, texWidth, texHeight, x, y, w, h, false);
495
- }
696
+ public int getModifiedX2() {
697
+ return mx2;
698
+ }
496
699
 
700
+ public int getModifiedY1() {
701
+ return my1;
702
+ }
497
703
 
498
- ////////////////////////////////////////////////////////////
704
+ public int getModifiedY2() {
705
+ return my2;
706
+ }
499
707
 
500
- // Get OpenGL parameters
708
+ public void updateTexels() {
709
+ updateTexelsImpl(0, 0, width, height);
710
+ }
501
711
 
712
+ public void updateTexels(int x, int y, int w, int h) {
713
+ updateTexelsImpl(x, y, w, h);
714
+ }
502
715
 
503
- /**
504
- * Returns true or false whether or not the texture is using mipmaps.
505
- * @return boolean
506
- */
507
- public boolean usingMipmaps() {
508
- return usingMipmaps;
509
- }
716
+ protected void updateTexelsImpl(int x, int y, int w, int h) {
717
+ int x2 = x + w;
718
+ int y2 = y + h;
510
719
 
720
+ if (!modified) {
721
+ mx1 = PApplet.max(0, x);
722
+ mx2 = PApplet.min(width - 1, x2);
723
+ my1 = PApplet.max(0, y);
724
+ my2 = PApplet.min(height - 1, y2);
725
+ modified = true;
511
726
 
512
- public void usingMipmaps(boolean mipmaps, int sampling) {
513
- int glMagFilter0 = glMagFilter;
514
- int glMinFilter0 = glMinFilter;
515
- if (mipmaps) {
516
- if (sampling == POINT) {
517
- glMagFilter = PGL.NEAREST;
518
- glMinFilter = PGL.NEAREST;
519
- usingMipmaps = false;
520
- } else if (sampling == LINEAR) {
521
- glMagFilter = PGL.NEAREST;
522
- glMinFilter =
523
- PGL.MIPMAPS_ENABLED ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR;
524
- usingMipmaps = true;
525
- } else if (sampling == BILINEAR) {
526
- glMagFilter = PGL.LINEAR;
527
- glMinFilter =
528
- PGL.MIPMAPS_ENABLED ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR;
529
- usingMipmaps = true;
530
- } else if (sampling == TRILINEAR) {
531
- glMagFilter = PGL.LINEAR;
532
- glMinFilter =
533
- PGL.MIPMAPS_ENABLED ? PGL.LINEAR_MIPMAP_LINEAR : PGL.LINEAR;
534
- usingMipmaps = true;
535
- } else {
536
- throw new RuntimeException("Unknown texture filtering mode");
537
- }
538
- } else {
539
- usingMipmaps = false;
540
- if (sampling == POINT) {
541
- glMagFilter = PGL.NEAREST;
542
- glMinFilter = PGL.NEAREST;
543
- } else if (sampling == LINEAR) {
544
- glMagFilter = PGL.NEAREST;
545
- glMinFilter = PGL.LINEAR;
546
- } else if (sampling == BILINEAR || sampling == TRILINEAR) {
547
- glMagFilter = PGL.LINEAR;
548
- glMinFilter = PGL.LINEAR;
549
- } else {
550
- throw new RuntimeException("Unknown texture filtering mode");
551
- }
552
- }
553
-
554
- if (glMagFilter0 != glMagFilter || glMinFilter0 != glMinFilter) {
555
- bind();
556
- pgl.texParameteri(glTarget, PGL.TEXTURE_MIN_FILTER, glMinFilter);
557
- pgl.texParameteri(glTarget, PGL.TEXTURE_MAG_FILTER, glMagFilter);
558
- if (usingMipmaps) {
559
- if (PGraphicsOpenGL.autoMipmapGenSupported) {
560
- pgl.generateMipmap(glTarget);
561
727
  } else {
562
- manualMipmap();
563
- }
564
- }
565
- unbind();
566
- }
567
- }
568
-
569
-
570
- /**
571
- * Returns true or false whether or not the texture is using repeat wrap mode
572
- * along either U or V directions.
573
- * @return boolean
574
- */
575
- public boolean usingRepeat() {
576
- return usingRepeat;
577
- }
578
-
579
-
580
- public void usingRepeat(boolean repeat) {
581
- if (repeat) {
582
- glWrapS = PGL.REPEAT;
583
- glWrapT = PGL.REPEAT;
584
- usingRepeat = true;
585
- } else {
586
- glWrapS = PGL.CLAMP_TO_EDGE;
587
- glWrapT = PGL.CLAMP_TO_EDGE;
588
- usingRepeat = false;
589
- }
590
-
591
- bind();
592
- pgl.texParameteri(glTarget, PGL.TEXTURE_WRAP_S, glWrapS);
593
- pgl.texParameteri(glTarget, PGL.TEXTURE_WRAP_T, glWrapT);
594
- unbind();
595
- }
596
-
597
-
598
- /**
599
- * Returns the maximum possible value for the texture coordinate U
600
- * (horizontal).
601
- * @return float
602
- */
603
- public float maxTexcoordU() {
604
- return maxTexcoordU;
605
- }
606
-
607
-
608
- /**
609
- * Returns the maximum possible value for the texture coordinate V (vertical).
610
- * @return float
611
- */
612
- public float maxTexcoordV() {
613
- return maxTexcoordV;
614
- }
615
-
616
-
617
- /**
618
- * Returns true if the texture is inverted along the horizontal direction.
619
- * @return boolean;
620
- */
621
- public boolean invertedX() {
622
- return invertedX;
623
- }
624
-
625
-
626
- /**
627
- * Sets the texture as inverted or not along the horizontal direction.
628
- * @param v boolean;
629
- */
630
- public void invertedX(boolean v) {
631
- invertedX = v;
632
- }
633
-
634
-
635
- /**
636
- * Returns true if the texture is inverted along the vertical direction.
637
- * @return boolean;
638
- */
639
- public boolean invertedY() {
640
- return invertedY;
641
- }
642
-
643
-
644
- /**
645
- * Sets the texture as inverted or not along the vertical direction.
646
- * @param v boolean;
647
- */
648
- public void invertedY(boolean v) {
649
- invertedY = v;
650
- }
651
-
652
-
653
- public int currentSampling() {
654
- if (glMagFilter == PGL.NEAREST && glMinFilter == PGL.NEAREST) {
655
- return POINT;
656
- } else if (glMagFilter == PGL.NEAREST &&
657
- glMinFilter == (PGL.MIPMAPS_ENABLED ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR)) {
658
- return LINEAR;
659
- } else if (glMagFilter == PGL.LINEAR &&
660
- glMinFilter == (PGL.MIPMAPS_ENABLED ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR)) {
661
- return BILINEAR;
662
- } else if (glMagFilter == PGL.LINEAR &&
663
- glMinFilter == PGL.LINEAR_MIPMAP_LINEAR) {
664
- return TRILINEAR;
665
- } else {
666
- return -1;
667
- }
668
- }
669
-
670
- ////////////////////////////////////////////////////////////
671
-
672
- // Bind/unbind
673
-
674
-
675
- public void bind() {
676
- // Binding a texture automatically enables texturing for the
677
- // texture target from that moment onwards. Unbinding the texture
678
- // won't disable texturing.
679
- if (!pgl.texturingIsEnabled(glTarget)) {
680
- pgl.enableTexturing(glTarget);
681
- }
682
- pgl.bindTexture(glTarget, glName);
683
- bound = true;
684
- }
685
-
686
-
687
- public void unbind() {
688
- if (pgl.textureIsBound(glTarget, glName)) {
689
- // We don't want to unbind another texture
690
- // that might be bound instead of this one.
691
- if (!pgl.texturingIsEnabled(glTarget)) {
692
- pgl.enableTexturing(glTarget);
693
- pgl.bindTexture(glTarget, 0);
694
- pgl.disableTexturing(glTarget);
695
- } else {
696
- pgl.bindTexture(glTarget, 0);
697
- }
728
+ if (x < mx1) {
729
+ mx1 = PApplet.max(0, x);
730
+ }
731
+ if (x > mx2) {
732
+ mx2 = PApplet.min(width - 1, x);
733
+ }
734
+ if (y < my1) {
735
+ my1 = PApplet.max(0, y);
736
+ }
737
+ if (y > my2) {
738
+ my2 = y;
739
+ }
740
+
741
+ if (x2 < mx1) {
742
+ mx1 = PApplet.max(0, x2);
743
+ }
744
+ if (x2 > mx2) {
745
+ mx2 = PApplet.min(width - 1, x2);
746
+ }
747
+ if (y2 < my1) {
748
+ my1 = PApplet.max(0, y2);
749
+ }
750
+ if (y2 > my2) {
751
+ my2 = PApplet.min(height - 1, y2);
752
+ }
753
+ }
698
754
  }
699
- bound = false;
700
- }
701
755
 
756
+ protected void loadPixels(int len) {
757
+ if (rgbaPixels == null || rgbaPixels.length < len) {
758
+ rgbaPixels = new int[len];
759
+ }
760
+ }
702
761
 
703
- public boolean bound() {
704
- // A true result might not necessarily mean that texturing is enabled
705
- // (a texture can be bound to the target, but texturing is disabled).
706
- return bound;
707
- }
762
+ protected void updatePixelBuffer(int[] pixels) {
763
+ pixelBuffer = PGL.updateIntBuffer(pixelBuffer, pixels, true);
764
+ pixBufUpdateCount++;
765
+ }
708
766
 
767
+ protected void manualMipmap() {
768
+ // TODO: finish manual mipmap generation,
769
+ // https://github.com/processing/processing/issues/3335
770
+ }
709
771
 
710
- //////////////////////////////////////////////////////////////
772
+ ////////////////////////////////////////////////////////////
773
+ // Buffer sink interface.
774
+ public void setBufferSource(Object source) {
775
+ bufferSource = source;
776
+ getSourceMethods();
777
+ }
711
778
 
712
- // Modified flag
779
+ public void copyBufferFromSource(Object natRef, ByteBuffer byteBuf,
780
+ int w, int h) {
781
+ if (bufferCache == null) {
782
+ bufferCache = new LinkedList<BufferData>();
783
+ }
713
784
 
785
+ if (bufferCache.size() + 1 <= MAX_BUFFER_CACHE_SIZE) {
786
+ bufferCache.add(new BufferData(natRef, byteBuf.asIntBuffer(), w, h));
787
+ } else {
788
+ // The buffer cache reached the maximum size, so we just dispose
789
+ // the new buffer by adding it to the list of used buffers.
790
+ try {
791
+ usedBuffers.add(new BufferData(natRef, byteBuf.asIntBuffer(), w, h));
792
+ } catch (Exception e) {
793
+ e.printStackTrace();
794
+ }
795
+ }
796
+ }
714
797
 
715
- public boolean isModified() {
716
- return modified;
717
- }
798
+ public void disposeSourceBuffer() {
799
+ if (usedBuffers == null) {
800
+ return;
801
+ }
718
802
 
803
+ while (0 < usedBuffers.size()) {
804
+ BufferData data = null;
805
+ try {
806
+ data = usedBuffers.remove(0);
807
+ } catch (NoSuchElementException ex) {
808
+ PGraphics.showWarning("Cannot remove used buffer");
809
+ }
810
+ if (data != null) {
811
+ data.dispose();
812
+ }
813
+ }
814
+ }
719
815
 
720
- public void setModified() {
721
- modified = true;
722
- }
816
+ public void getBufferPixels(int[] pixels) {
817
+ // We get the buffer either from the used buffers or the cache, giving
818
+ // priority to the used buffers. Why? Because the used buffer was already
819
+ // transferred to the texture, so the pixels should be in sync with the
820
+ // texture.
821
+ BufferData data = null;
822
+ if (usedBuffers != null && 0 < usedBuffers.size()) {
823
+ data = usedBuffers.getLast();
824
+ } else if (bufferCache != null && 0 < bufferCache.size()) {
825
+ data = bufferCache.getLast();
826
+ }
827
+ if (data != null) {
828
+ if ((data.w != width) || (data.h != height)) {
829
+ init(data.w, data.h);
830
+ }
831
+
832
+ data.rgbBuf.rewind();
833
+ data.rgbBuf.get(pixels);
834
+ convertToARGB(pixels);
835
+
836
+ // In order to avoid a cached buffer to overwrite the texture when the
837
+ // renderer draws the texture, and hence put the pixels put of sync, we
838
+ // simply empty the cache.
839
+ if (usedBuffers == null) {
840
+ usedBuffers = new LinkedList<BufferData>();
841
+ }
842
+ while (0 < bufferCache.size()) {
843
+ data = bufferCache.remove(0);
844
+ usedBuffers.add(data);
845
+ }
846
+ }
847
+ }
723
848
 
849
+ public boolean hasBufferSource() {
850
+ return bufferSource != null;
851
+ }
724
852
 
725
- public void setModified(boolean m) {
726
- modified = m;
727
- }
853
+ public boolean hasBuffers() {
854
+ return bufferSource != null && bufferCache != null
855
+ && 0 < bufferCache.size();
856
+ }
728
857
 
858
+ protected boolean bufferUpdate() {
859
+ BufferData data = null;
860
+ try {
861
+ data = bufferCache.remove(0);
862
+ } catch (NoSuchElementException ex) {
863
+ PGraphics.showWarning("Don't have pixel data to copy to texture");
864
+ }
729
865
 
730
- public int getModifiedX1() {
731
- return mx1;
732
- }
866
+ if (data != null) {
867
+ if ((data.w != width) || (data.h != height)) {
868
+ init(data.w, data.h);
869
+ }
870
+ data.rgbBuf.rewind();
871
+ setNative(data.rgbBuf, 0, 0, width, height);
872
+
873
+ // Putting the buffer in the used buffers list to dispose at the end of
874
+ // draw.
875
+ if (usedBuffers == null) {
876
+ usedBuffers = new LinkedList<BufferData>();
877
+ }
878
+ usedBuffers.add(data);
879
+
880
+ return true;
881
+ } else {
882
+ return false;
883
+ }
884
+ }
733
885
 
886
+ protected void getSourceMethods() {
887
+ try {
888
+ disposeBufferMethod = bufferSource.getClass().
889
+ getMethod("disposeBuffer", new Class[]{Object.class});
890
+ } catch (Exception e) {
891
+ throw new RuntimeException("Provided source object doesn't have a "
892
+ + "disposeBuffer method.");
893
+ }
894
+ }
734
895
 
735
- public int getModifiedX2() {
736
- return mx2;
737
- }
896
+ ////////////////////////////////////////////////////////////
897
+ // Utilities
898
+ /**
899
+ * Flips intArray along the X axis.
900
+ *
901
+ * @param intArray int[]
902
+ * @param mult int
903
+ */
904
+ protected void flipArrayOnX(int[] intArray, int mult) {
905
+ int index = 0;
906
+ int xindex = mult * (width - 1);
907
+ for (int x = 0; x < width / 2; x++) {
908
+ for (int y = 0; y < height; y++) {
909
+ int i = index + mult * y * width;
910
+ int j = xindex + mult * y * width;
911
+
912
+ for (int c = 0; c < mult; c++) {
913
+ int temp = intArray[i];
914
+ intArray[i] = intArray[j];
915
+ intArray[j] = temp;
916
+
917
+ i++;
918
+ j++;
919
+ }
920
+
921
+ }
922
+ index += mult;
923
+ xindex -= mult;
924
+ }
925
+ }
738
926
 
927
+ /**
928
+ * Flips intArray along the Y axis.
929
+ *
930
+ * @param intArray int[]
931
+ * @param mult int
932
+ */
933
+ protected void flipArrayOnY(int[] intArray, int mult) {
934
+ int index = 0;
935
+ int yindex = mult * (height - 1) * width;
936
+ for (int y = 0; y < height / 2; y++) {
937
+ for (int x = 0; x < mult * width; x++) {
938
+ int temp = intArray[index];
939
+ intArray[index] = intArray[yindex];
940
+ intArray[yindex] = temp;
941
+
942
+ index++;
943
+ yindex++;
944
+ }
945
+ yindex -= mult * width * 2;
946
+ }
947
+ }
739
948
 
740
- public int getModifiedY1() {
741
- return my1;
742
- }
949
+ /**
950
+ * Reorders a pixel array in the given format into the order required by
951
+ * OpenGL (RGBA) and stores it into rgbaPixels. The width and height
952
+ * parameters are used in the YUV420 to RBGBA conversion.
953
+ *
954
+ * @param pixels int[]
955
+ * @param format int
956
+ * @param w int
957
+ * @param h int
958
+ */
959
+ protected void convertToRGBA(int[] pixels, int format, int w, int h) {
960
+ if (PGL.BIG_ENDIAN) {
961
+ switch (format) {
962
+ case ALPHA:
963
+ // Converting from xxxA into RGBA. RGB is set to white
964
+ // (0xFFFFFF, i.e.: (255, 255, 255))
965
+ for (int i = 0; i < pixels.length; i++) {
966
+ rgbaPixels[i] = 0xFFFFFF00 | pixels[i];
967
+ }
968
+ break;
969
+ case RGB:
970
+ // Converting xRGB into RGBA. A is set to 0xFF (255, full opacity).
971
+ for (int i = 0; i < pixels.length; i++) {
972
+ int pixel = pixels[i];
973
+ rgbaPixels[i] = (pixel << 8) | 0xFF;
974
+ }
975
+ break;
976
+ case ARGB:
977
+ // Converting ARGB into RGBA. Shifting RGB to 8 bits to the left,
978
+ // and bringing A to the first byte.
979
+ for (int i = 0; i < pixels.length; i++) {
980
+ int pixel = pixels[i];
981
+ rgbaPixels[i] = (pixel << 8) | ((pixel >> 24) & 0xFF);
982
+ }
983
+ break;
984
+ }
985
+ } else {
986
+ // LITTLE_ENDIAN
987
+ // ARGB native, and RGBA opengl means ABGR on windows
988
+ // for the most part just need to swap two components here
989
+ // the sun.cpu.endian here might be "false", oddly enough..
990
+ // (that's why just using an "else", rather than check for "little")
991
+ switch (format) {
992
+ case ALPHA:
993
+ // Converting xxxA into ARGB, with RGB set to white.
994
+ for (int i = 0; i < pixels.length; i++) {
995
+ rgbaPixels[i] = (pixels[i] << 24) | 0x00FFFFFF;
996
+ }
997
+ break;
998
+ case RGB:
999
+ // We need to convert xRGB into ABGR,
1000
+ // so R and B must be swapped, and the x just made 0xFF.
1001
+ for (int i = 0; i < pixels.length; i++) {
1002
+ int pixel = pixels[i];
1003
+ rgbaPixels[i] = 0xFF000000
1004
+ | ((pixel & 0xFF) << 16) | ((pixel & 0xFF0000) >> 16)
1005
+ | (pixel & 0x0000FF00);
1006
+ }
1007
+ break;
1008
+ case ARGB:
1009
+ // We need to convert ARGB into ABGR,
1010
+ // so R and B must be swapped, A and G just brought back in.
1011
+ for (int i = 0; i < pixels.length; i++) {
1012
+ int pixel = pixels[i];
1013
+ rgbaPixels[i] = ((pixel & 0xFF) << 16) | ((pixel & 0xFF0000) >> 16)
1014
+ | (pixel & 0xFF00FF00);
1015
+ }
1016
+ break;
1017
+ }
1018
+ }
1019
+ rgbaPixUpdateCount++;
1020
+ }
743
1021
 
1022
+ /**
1023
+ * Reorders an OpenGL pixel array (RGBA) into ARGB. The array must be of
1024
+ * size width * height.
1025
+ *
1026
+ * @param pixels int[]
1027
+ */
1028
+ protected void convertToARGB(int[] pixels) {
1029
+ int t = 0;
1030
+ int p = 0;
1031
+ if (PGL.BIG_ENDIAN) {
1032
+ // RGBA to ARGB conversion: shifting RGB 8 bits to the right,
1033
+ // and placing A 24 bits to the left.
1034
+ for (int y = 0; y < height; y++) {
1035
+ for (int x = 0; x < width; x++) {
1036
+ int pixel = pixels[p++];
1037
+ pixels[t++] = (pixel >>> 8) | ((pixel << 24) & 0xFF000000);
1038
+ }
1039
+ }
1040
+ } else {
1041
+ // We have to convert ABGR into ARGB, so R and B must be swapped,
1042
+ // A and G just brought back in.
1043
+ for (int y = 0; y < height; y++) {
1044
+ for (int x = 0; x < width; x++) {
1045
+ int pixel = pixels[p++];
1046
+ pixels[t++] = ((pixel & 0xFF) << 16) | ((pixel & 0xFF0000) >> 16)
1047
+ | (pixel & 0xFF00FF00);
1048
+ }
1049
+ }
1050
+ }
1051
+ }
744
1052
 
745
- public int getModifiedY2() {
746
- return my2;
747
- }
1053
+ ///////////////////////////////////////////////////////////
1054
+ // Allocate/release texture.
1055
+ protected void setSize(int w, int h) {
1056
+ width = w;
1057
+ height = h;
748
1058
 
1059
+ if (PGraphicsOpenGL.npotTexSupported) {
1060
+ glWidth = w;
1061
+ glHeight = h;
1062
+ } else {
1063
+ glWidth = PGL.nextPowerOfTwo(w);
1064
+ glHeight = PGL.nextPowerOfTwo(h);
1065
+ }
749
1066
 
750
- public void updateTexels() {
751
- updateTexelsImpl(0, 0, width, height);
752
- }
1067
+ if (glWidth > PGraphicsOpenGL.maxTextureSize
1068
+ || glHeight > PGraphicsOpenGL.maxTextureSize) {
1069
+ glWidth = glHeight = 0;
1070
+ throw new RuntimeException("Image width and height cannot be"
1071
+ + " larger than "
1072
+ + PGraphicsOpenGL.maxTextureSize
1073
+ + " with this graphics card.");
1074
+ }
753
1075
 
1076
+ // If non-power-of-two textures are not supported, and the specified width
1077
+ // or height is non-power-of-two, then glWidth (glHeight) will be greater
1078
+ // than w (h) because it is chosen to be the next power of two, and this
1079
+ // quotient will give the appropriate maximum texture coordinate value given
1080
+ // this situation.
1081
+ maxTexcoordU = (float) width / glWidth;
1082
+ maxTexcoordV = (float) height / glHeight;
1083
+ }
754
1084
 
755
- public void updateTexels(int x, int y, int w, int h) {
756
- updateTexelsImpl(x, y, w, h);
757
- }
1085
+ /**
1086
+ * Allocates the opengl texture object.
1087
+ */
1088
+ protected void allocate() {
1089
+ dispose(); // Just in the case this object is being re-allocated.
758
1090
 
1091
+ boolean enabledTex = false;
1092
+ if (!pgl.texturingIsEnabled(glTarget)) {
1093
+ pgl.enableTexturing(glTarget);
1094
+ enabledTex = true;
1095
+ }
759
1096
 
760
- protected void updateTexelsImpl(int x, int y, int w, int h) {
761
- int x2 = x + w;
762
- int y2 = y + h;
1097
+ context = pgl.getCurrentContext();
1098
+ glres = new GLResourceTexture(this);
1099
+
1100
+ pgl.bindTexture(glTarget, glName);
1101
+ pgl.texParameteri(glTarget, PGL.TEXTURE_MIN_FILTER, glMinFilter);
1102
+ pgl.texParameteri(glTarget, PGL.TEXTURE_MAG_FILTER, glMagFilter);
1103
+ pgl.texParameteri(glTarget, PGL.TEXTURE_WRAP_S, glWrapS);
1104
+ pgl.texParameteri(glTarget, PGL.TEXTURE_WRAP_T, glWrapT);
1105
+ if (PGraphicsOpenGL.anisoSamplingSupported) {
1106
+ pgl.texParameterf(glTarget, PGL.TEXTURE_MAX_ANISOTROPY,
1107
+ PGraphicsOpenGL.maxAnisoAmount);
1108
+ }
763
1109
 
764
- if (!modified) {
765
- mx1 = PApplet.max(0, x);
766
- mx2 = PApplet.min(width - 1, x2);
767
- my1 = PApplet.max(0, y);
768
- my2 = PApplet.min(height - 1, y2);
769
- modified = true;
1110
+ // First, we use glTexImage2D to set the full size of the texture (glW/glH
1111
+ // might be diff from w/h in the case that the GPU doesn't support NPOT
1112
+ // textures)
1113
+ pgl.texImage2D(glTarget, 0, glFormat, glWidth, glHeight, 0,
1114
+ PGL.RGBA, PGL.UNSIGNED_BYTE, null);
770
1115
 
771
- } else {
772
- if (x < mx1) mx1 = PApplet.max(0, x);
773
- if (x > mx2) mx2 = PApplet.min(width - 1, x);
774
- if (y < my1) my1 = PApplet.max(0, y);
775
- if (y > my2) my2 = y;
1116
+ // Makes sure that the texture buffer in video memory doesn't contain
1117
+ // any garbage.
1118
+ pgl.initTexture(glTarget, PGL.RGBA, width, height);
776
1119
 
777
- if (x2 < mx1) mx1 = PApplet.max(0, x2);
778
- if (x2 > mx2) mx2 = PApplet.min(width - 1, x2);
779
- if (y2 < my1) my1 = PApplet.max(0, y2);
780
- if (y2 > my2) my2 = PApplet.min(height - 1, y2);
1120
+ pgl.bindTexture(glTarget, 0);
1121
+ if (enabledTex) {
1122
+ pgl.disableTexturing(glTarget);
1123
+ }
1124
+ bound = false;
781
1125
  }
782
- }
783
1126
 
784
-
785
- protected void loadPixels(int len) {
786
- if (rgbaPixels == null || rgbaPixels.length < len) {
787
- rgbaPixels = new int[len];
1127
+ /**
1128
+ * Marks the texture object for deletion.
1129
+ */
1130
+ protected void dispose() {
1131
+ if (glres != null) {
1132
+ glres.dispose();
1133
+ glres = null;
1134
+ glName = 0;
1135
+ }
788
1136
  }
789
- }
790
1137
 
1138
+ protected boolean contextIsOutdated() {
1139
+ boolean outdated = !pgl.contextIsCurrent(context);
1140
+ if (outdated) {
1141
+ dispose();
1142
+ }
1143
+ return outdated;
1144
+ }
791
1145
 
792
- protected void updatePixelBuffer(int[] pixels) {
793
- pixelBuffer = PGL.updateIntBuffer(pixelBuffer, pixels, true);
794
- pixBufUpdateCount++;
795
- }
1146
+ public void colorBuffer(boolean value) {
1147
+ colorBuffer = value;
1148
+ }
796
1149
 
1150
+ public boolean colorBuffer() {
1151
+ return colorBuffer;
1152
+ }
797
1153
 
798
- protected void manualMipmap() {
799
- // TODO: finish manual mipmap generation,
800
- // https://github.com/processing/processing/issues/3335
801
- }
1154
+ ///////////////////////////////////////////////////////////
1155
+ // Utilities.
1156
+ // Copies source texture tex into this.
1157
+ protected void copyTexture(Texture tex, int x, int y, int w, int h,
1158
+ boolean scale) {
1159
+ if (tex == null) {
1160
+ throw new RuntimeException("Source texture is null");
1161
+ }
802
1162
 
1163
+ if (tempFbo == null) {
1164
+ tempFbo = new FrameBuffer(pg, glWidth, glHeight);
1165
+ }
803
1166
 
804
- ////////////////////////////////////////////////////////////
1167
+ // This texture is the color (destination) buffer of the FBO.
1168
+ tempFbo.setColorBuffer(this);
1169
+ tempFbo.disableDepthTest();
1170
+
1171
+ // FBO copy:
1172
+ pg.pushFramebuffer();
1173
+ pg.setFramebuffer(tempFbo);
1174
+ // Replaces anything that this texture might contain in the area being
1175
+ // replaced by the new one.
1176
+ pg.pushStyle();
1177
+ pg.blendMode(REPLACE);
1178
+ if (scale) {
1179
+ // Rendering tex into "this", and scaling the source rectangle
1180
+ // to cover the entire destination region.
1181
+ pgl.drawTexture(tex.glTarget, tex.glName, tex.glWidth, tex.glHeight,
1182
+ 0, 0, tempFbo.width, tempFbo.height, 1,
1183
+ x, y, x + w, y + h, 0, 0, width, height);
805
1184
 
806
- // Buffer sink interface.
1185
+ } else {
1186
+ // Rendering tex into "this" but without scaling so the contents
1187
+ // of the source texture fall in the corresponding texels of the
1188
+ // destination.
1189
+ pgl.drawTexture(tex.glTarget, tex.glName, tex.glWidth, tex.glHeight,
1190
+ 0, 0, tempFbo.width, tempFbo.height, 1,
1191
+ x, y, x + w, y + h, x, y, x + w, y + h);
1192
+ }
1193
+ pgl.flush(); // Needed to make sure that the change in this texture is
1194
+ // available immediately.
1195
+ pg.popStyle();
1196
+ pg.popFramebuffer();
1197
+ updateTexels(x, y, w, h);
1198
+ }
1199
+
1200
+ // Copies source texture tex into this.
1201
+ protected void copyTexture(int texTarget, int texName,
1202
+ int texWidth, int texHeight,
1203
+ int x, int y, int w, int h, boolean scale) {
1204
+ if (tempFbo == null) {
1205
+ tempFbo = new FrameBuffer(pg, glWidth, glHeight);
1206
+ }
807
1207
 
1208
+ // This texture is the color (destination) buffer of the FBO.
1209
+ tempFbo.setColorBuffer(this);
1210
+ tempFbo.disableDepthTest();
1211
+
1212
+ // FBO copy:
1213
+ pg.pushFramebuffer();
1214
+ pg.setFramebuffer(tempFbo);
1215
+ // Replaces anything that this texture might contain in the area being
1216
+ // replaced by the new one.
1217
+ pg.pushStyle();
1218
+ pg.blendMode(REPLACE);
1219
+ if (scale) {
1220
+ // Rendering tex into "this", and scaling the source rectangle
1221
+ // to cover the entire destination region.
1222
+ pgl.drawTexture(texTarget, texName, texWidth, texHeight,
1223
+ 0, 0, tempFbo.width, tempFbo.height,
1224
+ x, y, w, h, 0, 0, width, height);
808
1225
 
809
- public void setBufferSource(Object source) {
810
- bufferSource = source;
811
- getSourceMethods();
812
- }
1226
+ } else {
1227
+ // Rendering tex into "this" but without scaling so the contents
1228
+ // of the source texture fall in the corresponding texels of the
1229
+ // destination.
1230
+ pgl.drawTexture(texTarget, texName, texWidth, texHeight,
1231
+ 0, 0, tempFbo.width, tempFbo.height,
1232
+ x, y, w, h, x, y, w, h);
1233
+ }
1234
+ pgl.flush(); // Needed to make sure that the change in this texture is
1235
+ // available immediately.
1236
+ pg.popStyle();
1237
+ pg.popFramebuffer();
1238
+ updateTexels(x, y, w, h);
1239
+ }
813
1240
 
1241
+ protected void copyObject(Texture src) {
1242
+ // The OpenGL texture of this object is replaced with the one from the
1243
+ // source object, so we delete the former to avoid resource wasting.
1244
+ dispose();
814
1245
 
815
- public void copyBufferFromSource(Object natRef, ByteBuffer byteBuf,
816
- int w, int h) {
817
- if (bufferCache == null) {
818
- bufferCache = new LinkedList<BufferData>();
819
- }
1246
+ width = src.width;
1247
+ height = src.height;
820
1248
 
821
- if (bufferCache.size() + 1 <= MAX_BUFFER_CACHE_SIZE) {
822
- bufferCache.add(new BufferData(natRef, byteBuf.asIntBuffer(), w, h));
823
- } else {
824
- // The buffer cache reached the maximum size, so we just dispose
825
- // the new buffer by adding it to the list of used buffers.
826
- try {
827
- usedBuffers.add(new BufferData(natRef, byteBuf.asIntBuffer(), w, h));
828
- } catch (Exception e) {
829
- e.printStackTrace();
830
- }
831
- }
832
- }
1249
+ glName = src.glName;
1250
+ glTarget = src.glTarget;
1251
+ glFormat = src.glFormat;
1252
+ glMinFilter = src.glMinFilter;
1253
+ glMagFilter = src.glMagFilter;
833
1254
 
1255
+ glWidth = src.glWidth;
1256
+ glHeight = src.glHeight;
834
1257
 
835
- public void disposeSourceBuffer() {
836
- if (usedBuffers == null) return;
1258
+ usingMipmaps = src.usingMipmaps;
1259
+ usingRepeat = src.usingRepeat;
1260
+ maxTexcoordU = src.maxTexcoordU;
1261
+ maxTexcoordV = src.maxTexcoordV;
837
1262
 
838
- while (0 < usedBuffers.size()) {
839
- BufferData data = null;
840
- try {
841
- data = usedBuffers.remove(0);
842
- } catch (NoSuchElementException ex) {
843
- PGraphics.showWarning("Cannot remove used buffer");
844
- }
845
- if (data != null) {
846
- data.dispose();
847
- }
1263
+ invertedX = src.invertedX;
1264
+ invertedY = src.invertedY;
848
1265
  }
849
- }
850
1266
 
851
- public void getBufferPixels(int[] pixels) {
852
- // We get the buffer either from the used buffers or the cache, giving
853
- // priority to the used buffers. Why? Because the used buffer was already
854
- // transferred to the texture, so the pixels should be in sync with the
855
- // texture.
856
- BufferData data = null;
857
- if (usedBuffers != null && 0 < usedBuffers.size()) {
858
- data = usedBuffers.getLast();
859
- } else if (bufferCache != null && 0 < bufferCache.size()) {
860
- data = bufferCache.getLast();
1267
+ // Releases the memory used by pixelBuffer either if the buffer hasn't been
1268
+ // used many times yet, or if the JVM is running low in free memory.
1269
+ protected void releasePixelBuffer() {
1270
+ double freeMB = Runtime.getRuntime().freeMemory() / 1E6;
1271
+ if (pixBufUpdateCount < MAX_UPDATES || freeMB < MIN_MEMORY) {
1272
+ pixelBuffer = null;
1273
+ }
861
1274
  }
862
- if (data != null) {
863
- if ((data.w != width) || (data.h != height)) {
864
- init(data.w, data.h);
865
- }
866
-
867
- data.rgbBuf.rewind();
868
- data.rgbBuf.get(pixels);
869
- convertToARGB(pixels);
870
1275
 
871
- // In order to avoid a cached buffer to overwrite the texture when the
872
- // renderer draws the texture, and hence put the pixels put of sync, we
873
- // simply empty the cache.
874
- if (usedBuffers == null) {
875
- usedBuffers = new LinkedList<BufferData>();
876
- }
877
- while (0 < bufferCache.size()) {
878
- data = bufferCache.remove(0);
879
- usedBuffers.add(data);
880
- }
1276
+ // Releases the memory used by rgbaPixels either if the array hasn't been
1277
+ // used many times yet, or if the JVM is running low in free memory.
1278
+ protected void releaseRGBAPixels() {
1279
+ double freeMB = Runtime.getRuntime().freeMemory() / 1E6;
1280
+ if (rgbaPixUpdateCount < MAX_UPDATES || freeMB < MIN_MEMORY) {
1281
+ rgbaPixels = null;
1282
+ }
881
1283
  }
882
- }
883
-
884
1284
 
885
- public boolean hasBufferSource() {
886
- return bufferSource != null;
887
- }
1285
+ ///////////////////////////////////////////////////////////
1286
+ // Parameter handling
1287
+ public Parameters getParameters() {
1288
+ Parameters res = new Parameters();
888
1289
 
1290
+ if (glTarget == PGL.TEXTURE_2D) {
1291
+ res.target = TEX2D;
1292
+ }
889
1293
 
890
- public boolean hasBuffers() {
891
- return bufferSource != null && bufferCache != null &&
892
- 0 < bufferCache.size();
893
- }
894
-
895
-
896
- protected boolean bufferUpdate() {
897
- BufferData data = null;
898
- try {
899
- data = bufferCache.remove(0);
900
- } catch (NoSuchElementException ex) {
901
- PGraphics.showWarning("Don't have pixel data to copy to texture");
902
- }
903
-
904
- if (data != null) {
905
- if ((data.w != width) || (data.h != height)) {
906
- init(data.w, data.h);
907
- }
908
- data.rgbBuf.rewind();
909
- setNative(data.rgbBuf, 0, 0, width, height);
910
-
911
- // Putting the buffer in the used buffers list to dispose at the end of
912
- // draw.
913
- if (usedBuffers == null) {
914
- usedBuffers = new LinkedList<BufferData>();
915
- }
916
- usedBuffers.add(data);
917
-
918
- return true;
919
- } else {
920
- return false;
921
- }
922
- }
923
-
924
-
925
- protected void getSourceMethods() {
926
- try {
927
- disposeBufferMethod = bufferSource.getClass().
928
- getMethod("disposeBuffer", new Class[] { Object.class });
929
- } catch (Exception e) {
930
- throw new RuntimeException("Provided source object doesn't have a " +
931
- "disposeBuffer method.");
932
- }
933
- }
934
-
935
-
936
- ////////////////////////////////////////////////////////////
937
-
938
- // Utilities
939
-
940
-
941
- /**
942
- * Flips intArray along the X axis.
943
- * @param intArray int[]
944
- * @param mult int
945
- */
946
- protected void flipArrayOnX(int[] intArray, int mult) {
947
- int index = 0;
948
- int xindex = mult * (width - 1);
949
- for (int x = 0; x < width / 2; x++) {
950
- for (int y = 0; y < height; y++) {
951
- int i = index + mult * y * width;
952
- int j = xindex + mult * y * width;
953
-
954
- for (int c = 0; c < mult; c++) {
955
- int temp = intArray[i];
956
- intArray[i] = intArray[j];
957
- intArray[j] = temp;
958
-
959
- i++;
960
- j++;
961
- }
962
-
963
- }
964
- index += mult;
965
- xindex -= mult;
966
- }
967
- }
968
-
969
-
970
- /**
971
- * Flips intArray along the Y axis.
972
- * @param intArray int[]
973
- * @param mult int
974
- */
975
- protected void flipArrayOnY(int[] intArray, int mult) {
976
- int index = 0;
977
- int yindex = mult * (height - 1) * width;
978
- for (int y = 0; y < height / 2; y++) {
979
- for (int x = 0; x < mult * width; x++) {
980
- int temp = intArray[index];
981
- intArray[index] = intArray[yindex];
982
- intArray[yindex] = temp;
983
-
984
- index++;
985
- yindex++;
986
- }
987
- yindex -= mult * width * 2;
988
- }
989
- }
990
-
991
-
992
- /**
993
- * Reorders a pixel array in the given format into the order required by
994
- * OpenGL (RGBA) and stores it into rgbaPixels. The width and height
995
- * parameters are used in the YUV420 to RBGBA conversion.
996
- * @param pixels int[]
997
- * @param format int
998
- * @param w int
999
- * @param h int
1000
- */
1001
- protected void convertToRGBA(int[] pixels, int format, int w, int h) {
1002
- if (PGL.BIG_ENDIAN) {
1003
- switch (format) {
1004
- case ALPHA:
1005
- // Converting from xxxA into RGBA. RGB is set to white
1006
- // (0xFFFFFF, i.e.: (255, 255, 255))
1007
- for (int i = 0; i< pixels.length; i++) {
1008
- rgbaPixels[i] = 0xFFFFFF00 | pixels[i];
1009
- }
1010
- break;
1011
- case RGB:
1012
- // Converting xRGB into RGBA. A is set to 0xFF (255, full opacity).
1013
- for (int i = 0; i< pixels.length; i++) {
1014
- int pixel = pixels[i];
1015
- rgbaPixels[i] = (pixel << 8) | 0xFF;
1016
- }
1017
- break;
1018
- case ARGB:
1019
- // Converting ARGB into RGBA. Shifting RGB to 8 bits to the left,
1020
- // and bringing A to the first byte.
1021
- for (int i = 0; i< pixels.length; i++) {
1022
- int pixel = pixels[i];
1023
- rgbaPixels[i] = (pixel << 8) | ((pixel >> 24) & 0xFF);
1024
- }
1025
- break;
1026
- }
1027
- } else {
1028
- // LITTLE_ENDIAN
1029
- // ARGB native, and RGBA opengl means ABGR on windows
1030
- // for the most part just need to swap two components here
1031
- // the sun.cpu.endian here might be "false", oddly enough..
1032
- // (that's why just using an "else", rather than check for "little")
1033
- switch (format) {
1034
- case ALPHA:
1035
- // Converting xxxA into ARGB, with RGB set to white.
1036
- for (int i = 0; i< pixels.length; i++) {
1037
- rgbaPixels[i] = (pixels[i] << 24) | 0x00FFFFFF;
1038
- }
1039
- break;
1040
- case RGB:
1041
- // We need to convert xRGB into ABGR,
1042
- // so R and B must be swapped, and the x just made 0xFF.
1043
- for (int i = 0; i< pixels.length; i++) {
1044
- int pixel = pixels[i];
1045
- rgbaPixels[i] = 0xFF000000 |
1046
- ((pixel & 0xFF) << 16) | ((pixel & 0xFF0000) >> 16) |
1047
- (pixel & 0x0000FF00);
1048
- }
1049
- break;
1050
- case ARGB:
1051
- // We need to convert ARGB into ABGR,
1052
- // so R and B must be swapped, A and G just brought back in.
1053
- for (int i = 0; i < pixels.length; i++) {
1054
- int pixel = pixels[i];
1055
- rgbaPixels[i] = ((pixel & 0xFF) << 16) | ((pixel & 0xFF0000) >> 16) |
1056
- (pixel & 0xFF00FF00);
1057
- }
1058
- break;
1059
- }
1060
- }
1061
- rgbaPixUpdateCount++;
1062
- }
1063
-
1064
-
1065
- /**
1066
- * Reorders an OpenGL pixel array (RGBA) into ARGB. The array must be
1067
- * of size width * height.
1068
- * @param pixels int[]
1069
- */
1070
- protected void convertToARGB(int[] pixels) {
1071
- int t = 0;
1072
- int p = 0;
1073
- if (PGL.BIG_ENDIAN) {
1074
- // RGBA to ARGB conversion: shifting RGB 8 bits to the right,
1075
- // and placing A 24 bits to the left.
1076
- for (int y = 0; y < height; y++) {
1077
- for (int x = 0; x < width; x++) {
1078
- int pixel = pixels[p++];
1079
- pixels[t++] = (pixel >>> 8) | ((pixel << 24) & 0xFF000000);
1080
- }
1081
- }
1082
- } else {
1083
- // We have to convert ABGR into ARGB, so R and B must be swapped,
1084
- // A and G just brought back in.
1085
- for (int y = 0; y < height; y++) {
1086
- for (int x = 0; x < width; x++) {
1087
- int pixel = pixels[p++];
1088
- pixels[t++] = ((pixel & 0xFF) << 16) | ((pixel & 0xFF0000) >> 16) |
1089
- (pixel & 0xFF00FF00);
1090
- }
1091
- }
1092
- }
1093
- }
1094
-
1095
-
1096
- ///////////////////////////////////////////////////////////
1097
-
1098
- // Allocate/release texture.
1099
-
1100
-
1101
- protected void setSize(int w, int h) {
1102
- width = w;
1103
- height = h;
1104
-
1105
- if (PGraphicsOpenGL.npotTexSupported) {
1106
- glWidth = w;
1107
- glHeight = h;
1108
- } else {
1109
- glWidth = PGL.nextPowerOfTwo(w);
1110
- glHeight = PGL.nextPowerOfTwo(h);
1111
- }
1112
-
1113
- if (glWidth > PGraphicsOpenGL.maxTextureSize ||
1114
- glHeight > PGraphicsOpenGL.maxTextureSize) {
1115
- glWidth = glHeight = 0;
1116
- throw new RuntimeException("Image width and height cannot be" +
1117
- " larger than " +
1118
- PGraphicsOpenGL.maxTextureSize +
1119
- " with this graphics card.");
1120
- }
1121
-
1122
- // If non-power-of-two textures are not supported, and the specified width
1123
- // or height is non-power-of-two, then glWidth (glHeight) will be greater
1124
- // than w (h) because it is chosen to be the next power of two, and this
1125
- // quotient will give the appropriate maximum texture coordinate value given
1126
- // this situation.
1127
- maxTexcoordU = (float)width / glWidth;
1128
- maxTexcoordV = (float)height / glHeight;
1129
- }
1130
-
1294
+ if (glFormat == PGL.RGB) {
1295
+ res.format = RGB;
1296
+ } else if (glFormat == PGL.RGBA) {
1297
+ res.format = ARGB;
1298
+ } else if (glFormat == PGL.ALPHA) {
1299
+ res.format = ALPHA;
1300
+ }
1131
1301
 
1132
- /**
1133
- * Allocates the opengl texture object.
1134
- */
1135
- protected void allocate() {
1136
- dispose(); // Just in the case this object is being re-allocated.
1302
+ if (glMagFilter == PGL.NEAREST && glMinFilter == PGL.NEAREST) {
1303
+ res.sampling = POINT;
1304
+ res.mipmaps = false;
1305
+ } else if (glMagFilter == PGL.NEAREST && glMinFilter == PGL.LINEAR) {
1306
+ res.sampling = LINEAR;
1307
+ res.mipmaps = false;
1308
+ } else if (glMagFilter == PGL.NEAREST
1309
+ && glMinFilter == PGL.LINEAR_MIPMAP_NEAREST) {
1310
+ res.sampling = LINEAR;
1311
+ res.mipmaps = true;
1312
+ } else if (glMagFilter == PGL.LINEAR && glMinFilter == PGL.LINEAR) {
1313
+ res.sampling = BILINEAR;
1314
+ res.mipmaps = false;
1315
+ } else if (glMagFilter == PGL.LINEAR
1316
+ && glMinFilter == PGL.LINEAR_MIPMAP_NEAREST) {
1317
+ res.sampling = BILINEAR;
1318
+ res.mipmaps = true;
1319
+ } else if (glMagFilter == PGL.LINEAR
1320
+ && glMinFilter == PGL.LINEAR_MIPMAP_LINEAR) {
1321
+ res.sampling = TRILINEAR;
1322
+ res.mipmaps = true;
1323
+ }
1137
1324
 
1138
- boolean enabledTex = false;
1139
- if (!pgl.texturingIsEnabled(glTarget)) {
1140
- pgl.enableTexturing(glTarget);
1141
- enabledTex = true;
1142
- }
1325
+ if (glWrapS == PGL.CLAMP_TO_EDGE) {
1326
+ res.wrapU = CLAMP;
1327
+ } else if (glWrapS == PGL.REPEAT) {
1328
+ res.wrapU = REPEAT;
1329
+ }
1143
1330
 
1144
- context = pgl.getCurrentContext();
1145
- glres = new GLResourceTexture(this);
1331
+ if (glWrapT == PGL.CLAMP_TO_EDGE) {
1332
+ res.wrapV = CLAMP;
1333
+ } else if (glWrapT == PGL.REPEAT) {
1334
+ res.wrapV = REPEAT;
1335
+ }
1146
1336
 
1147
- pgl.bindTexture(glTarget, glName);
1148
- pgl.texParameteri(glTarget, PGL.TEXTURE_MIN_FILTER, glMinFilter);
1149
- pgl.texParameteri(glTarget, PGL.TEXTURE_MAG_FILTER, glMagFilter);
1150
- pgl.texParameteri(glTarget, PGL.TEXTURE_WRAP_S, glWrapS);
1151
- pgl.texParameteri(glTarget, PGL.TEXTURE_WRAP_T, glWrapT);
1152
- if (PGraphicsOpenGL.anisoSamplingSupported) {
1153
- pgl.texParameterf(glTarget, PGL.TEXTURE_MAX_ANISOTROPY,
1154
- PGraphicsOpenGL.maxAnisoAmount);
1337
+ return res;
1155
1338
  }
1156
1339
 
1157
- // First, we use glTexImage2D to set the full size of the texture (glW/glH
1158
- // might be diff from w/h in the case that the GPU doesn't support NPOT
1159
- // textures)
1160
- pgl.texImage2D(glTarget, 0, glFormat, glWidth, glHeight, 0,
1161
- PGL.RGBA, PGL.UNSIGNED_BYTE, null);
1340
+ /**
1341
+ * Sets texture target and internal format according to the target and type
1342
+ * specified.
1343
+ *
1344
+ * @param target int
1345
+ * @param params GLTextureParameters
1346
+ */
1347
+ protected void setParameters(Parameters params) {
1348
+ if (params.target == TEX2D) {
1349
+ glTarget = PGL.TEXTURE_2D;
1350
+ } else {
1351
+ throw new RuntimeException("Unknown texture target");
1352
+ }
1162
1353
 
1163
- // Makes sure that the texture buffer in video memory doesn't contain
1164
- // any garbage.
1165
- pgl.initTexture(glTarget, PGL.RGBA, width, height);
1354
+ if (params.format == RGB) {
1355
+ glFormat = PGL.RGB;
1356
+ } else if (params.format == ARGB) {
1357
+ glFormat = PGL.RGBA;
1358
+ } else if (params.format == ALPHA) {
1359
+ glFormat = PGL.ALPHA;
1360
+ } else {
1361
+ throw new RuntimeException("Unknown texture format");
1362
+ }
1166
1363
 
1167
- pgl.bindTexture(glTarget, 0);
1168
- if (enabledTex) {
1169
- pgl.disableTexturing(glTarget);
1170
- }
1171
- bound = false;
1172
- }
1364
+ boolean mipmaps = params.mipmaps && PGL.MIPMAPS_ENABLED;
1365
+ if (mipmaps && !PGraphicsOpenGL.autoMipmapGenSupported) {
1366
+ PGraphics.showWarning("Mipmaps were requested but automatic mipmap "
1367
+ + "generation is not supported and manual "
1368
+ + "generation still not implemented, so mipmaps "
1369
+ + "will be disabled.");
1370
+ mipmaps = false;
1371
+ }
1173
1372
 
1373
+ if (params.sampling == POINT) {
1374
+ glMagFilter = PGL.NEAREST;
1375
+ glMinFilter = PGL.NEAREST;
1376
+ } else if (params.sampling == LINEAR) {
1377
+ glMagFilter = PGL.NEAREST;
1378
+ glMinFilter = mipmaps ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR;
1379
+ } else if (params.sampling == BILINEAR) {
1380
+ glMagFilter = PGL.LINEAR;
1381
+ glMinFilter = mipmaps ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR;
1382
+ } else if (params.sampling == TRILINEAR) {
1383
+ glMagFilter = PGL.LINEAR;
1384
+ glMinFilter = mipmaps ? PGL.LINEAR_MIPMAP_LINEAR : PGL.LINEAR;
1385
+ } else {
1386
+ throw new RuntimeException("Unknown texture filtering mode");
1387
+ }
1174
1388
 
1175
- /**
1176
- * Marks the texture object for deletion.
1177
- */
1178
- protected void dispose() {
1179
- if (glres != null) {
1180
- glres.dispose();
1181
- glres = null;
1182
- glName = 0;
1183
- }
1184
- }
1389
+ if (params.wrapU == CLAMP) {
1390
+ glWrapS = PGL.CLAMP_TO_EDGE;
1391
+ } else if (params.wrapU == REPEAT) {
1392
+ glWrapS = PGL.REPEAT;
1393
+ } else {
1394
+ throw new RuntimeException("Unknown wrapping mode");
1395
+ }
1185
1396
 
1397
+ if (params.wrapV == CLAMP) {
1398
+ glWrapT = PGL.CLAMP_TO_EDGE;
1399
+ } else if (params.wrapV == REPEAT) {
1400
+ glWrapT = PGL.REPEAT;
1401
+ } else {
1402
+ throw new RuntimeException("Unknown wrapping mode");
1403
+ }
1186
1404
 
1187
- protected boolean contextIsOutdated() {
1188
- boolean outdated = !pgl.contextIsCurrent(context);
1189
- if (outdated) {
1190
- dispose();
1405
+ usingMipmaps = glMinFilter == PGL.LINEAR_MIPMAP_NEAREST
1406
+ || glMinFilter == PGL.LINEAR_MIPMAP_LINEAR;
1407
+
1408
+ usingRepeat = glWrapS == PGL.REPEAT || glWrapT == PGL.REPEAT;
1409
+
1410
+ invertedX = false;
1411
+ invertedY = false;
1412
+ }
1413
+
1414
+ protected void fillEdges(int x, int y, int w, int h) {
1415
+ if ((width < glWidth || height < glHeight) && (x + w == width || y + h == height)) {
1416
+ if (x + w == width) {
1417
+ int ew = glWidth - width;
1418
+ edgePixels = new int[h * ew];
1419
+ for (int i = 0; i < h; i++) {
1420
+ int c = rgbaPixels[i * w + (w - 1)];
1421
+ Arrays.fill(edgePixels, i * ew, (i + 1) * ew, c);
1422
+ }
1423
+ edgeBuffer = PGL.updateIntBuffer(edgeBuffer, edgePixels, true);
1424
+ pgl.texSubImage2D(glTarget, 0, width, y, ew, h, PGL.RGBA,
1425
+ PGL.UNSIGNED_BYTE, edgeBuffer);
1426
+ }
1427
+
1428
+ if (y + h == height) {
1429
+ int eh = glHeight - height;
1430
+ edgePixels = new int[eh * w];
1431
+ for (int i = 0; i < eh; i++) {
1432
+ System.arraycopy(rgbaPixels, (h - 1) * w, edgePixels, i * w, w);
1433
+ }
1434
+ edgeBuffer = PGL.updateIntBuffer(edgeBuffer, edgePixels, true);
1435
+ pgl.texSubImage2D(glTarget, 0, x, height, w, eh, PGL.RGBA,
1436
+ PGL.UNSIGNED_BYTE, edgeBuffer);
1437
+ }
1438
+
1439
+ if (x + w == width && y + h == height) {
1440
+ int ew = glWidth - width;
1441
+ int eh = glHeight - height;
1442
+ int c = rgbaPixels[w * h - 1];
1443
+ edgePixels = new int[eh * ew];
1444
+ Arrays.fill(edgePixels, 0, eh * ew, c);
1445
+ edgeBuffer = PGL.updateIntBuffer(edgeBuffer, edgePixels, true);
1446
+ pgl.texSubImage2D(glTarget, 0, width, height, ew, eh, PGL.RGBA,
1447
+ PGL.UNSIGNED_BYTE, edgeBuffer);
1448
+ }
1449
+ }
1191
1450
  }
1192
- return outdated;
1193
- }
1194
1451
 
1452
+ ///////////////////////////////////////////////////////////////////////////
1453
+ // Parameters object
1454
+ /**
1455
+ * This class stores the parameters for a texture: target, internal format,
1456
+ * minimization filter and magnification filter.
1457
+ */
1458
+ static public class Parameters {
1459
+
1460
+ /**
1461
+ * Texture target.
1462
+ */
1463
+ public int target;
1464
+
1465
+ /**
1466
+ * Texture internal format.
1467
+ */
1468
+ public int format;
1469
+
1470
+ /**
1471
+ * Texture filtering (POINT, LINEAR, BILINEAR or TRILINEAR).
1472
+ */
1473
+ public int sampling;
1474
+
1475
+ /**
1476
+ * Use mipmaps or not.
1477
+ */
1478
+ public boolean mipmaps;
1479
+
1480
+ /**
1481
+ * Wrapping mode along U.
1482
+ */
1483
+ public int wrapU;
1484
+
1485
+ /**
1486
+ * Wrapping mode along V.
1487
+ */
1488
+ public int wrapV;
1489
+
1490
+ /**
1491
+ * Sets all the parameters to default values.
1492
+ */
1493
+ public Parameters() {
1494
+ this.target = TEX2D;
1495
+ this.format = ARGB;
1496
+ this.sampling = BILINEAR;
1497
+ this.mipmaps = true;
1498
+ this.wrapU = CLAMP;
1499
+ this.wrapV = CLAMP;
1500
+ }
1195
1501
 
1196
- public void colorBuffer(boolean value) {
1197
- colorBuffer = value;
1198
- }
1199
-
1200
-
1201
- public boolean colorBuffer() {
1202
- return colorBuffer;
1203
- }
1204
-
1205
-
1206
- ///////////////////////////////////////////////////////////
1207
-
1208
- // Utilities.
1209
-
1210
-
1211
- // Copies source texture tex into this.
1212
- protected void copyTexture(Texture tex, int x, int y, int w, int h,
1213
- boolean scale) {
1214
- if (tex == null) {
1215
- throw new RuntimeException("Source texture is null");
1216
- }
1217
-
1218
- if (tempFbo == null) {
1219
- tempFbo = new FrameBuffer(pg, glWidth, glHeight);
1220
- }
1221
-
1222
- // This texture is the color (destination) buffer of the FBO.
1223
- tempFbo.setColorBuffer(this);
1224
- tempFbo.disableDepthTest();
1225
-
1226
- // FBO copy:
1227
- pg.pushFramebuffer();
1228
- pg.setFramebuffer(tempFbo);
1229
- // Replaces anything that this texture might contain in the area being
1230
- // replaced by the new one.
1231
- pg.pushStyle();
1232
- pg.blendMode(REPLACE);
1233
- if (scale) {
1234
- // Rendering tex into "this", and scaling the source rectangle
1235
- // to cover the entire destination region.
1236
- pgl.drawTexture(tex.glTarget, tex.glName, tex.glWidth, tex.glHeight,
1237
- 0, 0, tempFbo.width, tempFbo.height, 1,
1238
- x, y, x + w, y + h, 0, 0, width, height);
1239
-
1240
- } else {
1241
- // Rendering tex into "this" but without scaling so the contents
1242
- // of the source texture fall in the corresponding texels of the
1243
- // destination.
1244
- pgl.drawTexture(tex.glTarget, tex.glName, tex.glWidth, tex.glHeight,
1245
- 0, 0, tempFbo.width, tempFbo.height, 1,
1246
- x, y, x + w, y + h, x, y, x + w, y + h);
1247
- }
1248
- pgl.flush(); // Needed to make sure that the change in this texture is
1249
- // available immediately.
1250
- pg.popStyle();
1251
- pg.popFramebuffer();
1252
- updateTexels(x, y, w, h);
1253
- }
1254
-
1502
+ public Parameters(int format) {
1503
+ this.target = TEX2D;
1504
+ this.format = format;
1505
+ this.sampling = BILINEAR;
1506
+ this.mipmaps = true;
1507
+ this.wrapU = CLAMP;
1508
+ this.wrapV = CLAMP;
1509
+ }
1255
1510
 
1256
- // Copies source texture tex into this.
1257
- protected void copyTexture(int texTarget, int texName,
1258
- int texWidth, int texHeight,
1259
- int x, int y, int w, int h, boolean scale) {
1260
- if (tempFbo == null) {
1261
- tempFbo = new FrameBuffer(pg, glWidth, glHeight);
1262
- }
1511
+ public Parameters(int format, int sampling) {
1512
+ this.target = TEX2D;
1513
+ this.format = format;
1514
+ this.sampling = sampling;
1515
+ this.mipmaps = true;
1516
+ this.wrapU = CLAMP;
1517
+ this.wrapV = CLAMP;
1518
+ }
1263
1519
 
1264
- // This texture is the color (destination) buffer of the FBO.
1265
- tempFbo.setColorBuffer(this);
1266
- tempFbo.disableDepthTest();
1520
+ public Parameters(int format, int sampling, boolean mipmaps) {
1521
+ this.target = TEX2D;
1522
+ this.format = format;
1523
+ this.mipmaps = mipmaps;
1524
+ if (sampling == TRILINEAR && !mipmaps) {
1525
+ this.sampling = BILINEAR;
1526
+ } else {
1527
+ this.sampling = sampling;
1528
+ }
1529
+ this.wrapU = CLAMP;
1530
+ this.wrapV = CLAMP;
1531
+ }
1267
1532
 
1268
- // FBO copy:
1269
- pg.pushFramebuffer();
1270
- pg.setFramebuffer(tempFbo);
1271
- // Replaces anything that this texture might contain in the area being
1272
- // replaced by the new one.
1273
- pg.pushStyle();
1274
- pg.blendMode(REPLACE);
1275
- if (scale) {
1276
- // Rendering tex into "this", and scaling the source rectangle
1277
- // to cover the entire destination region.
1278
- pgl.drawTexture(texTarget, texName, texWidth, texHeight,
1279
- 0, 0, tempFbo.width, tempFbo.height,
1280
- x, y, w, h, 0, 0, width, height);
1533
+ public Parameters(int format, int sampling, boolean mipmaps, int wrap) {
1534
+ this.target = TEX2D;
1535
+ this.format = format;
1536
+ this.mipmaps = mipmaps;
1537
+ if (sampling == TRILINEAR && !mipmaps) {
1538
+ this.sampling = BILINEAR;
1539
+ } else {
1540
+ this.sampling = sampling;
1541
+ }
1542
+ this.wrapU = wrap;
1543
+ this.wrapV = wrap;
1544
+ }
1281
1545
 
1282
- } else {
1283
- // Rendering tex into "this" but without scaling so the contents
1284
- // of the source texture fall in the corresponding texels of the
1285
- // destination.
1286
- pgl.drawTexture(texTarget, texName, texWidth, texHeight,
1287
- 0, 0, tempFbo.width, tempFbo.height,
1288
- x, y, w, h, x, y, w, h);
1289
- }
1290
- pgl.flush(); // Needed to make sure that the change in this texture is
1291
- // available immediately.
1292
- pg.popStyle();
1293
- pg.popFramebuffer();
1294
- updateTexels(x, y, w, h);
1295
- }
1296
-
1297
-
1298
- protected void copyObject(Texture src) {
1299
- // The OpenGL texture of this object is replaced with the one from the
1300
- // source object, so we delete the former to avoid resource wasting.
1301
- dispose();
1302
-
1303
- width = src.width;
1304
- height = src.height;
1305
-
1306
- glName = src.glName;
1307
- glTarget = src.glTarget;
1308
- glFormat = src.glFormat;
1309
- glMinFilter = src.glMinFilter;
1310
- glMagFilter = src.glMagFilter;
1311
-
1312
- glWidth= src.glWidth;
1313
- glHeight = src.glHeight;
1314
-
1315
- usingMipmaps = src.usingMipmaps;
1316
- usingRepeat = src.usingRepeat;
1317
- maxTexcoordU = src.maxTexcoordU;
1318
- maxTexcoordV = src.maxTexcoordV;
1319
-
1320
- invertedX = src.invertedX;
1321
- invertedY = src.invertedY;
1322
- }
1323
-
1324
-
1325
- // Releases the memory used by pixelBuffer either if the buffer hasn't been
1326
- // used many times yet, or if the JVM is running low in free memory.
1327
- protected void releasePixelBuffer() {
1328
- double freeMB = Runtime.getRuntime().freeMemory() / 1E6;
1329
- if (pixBufUpdateCount < MAX_UPDATES || freeMB < MIN_MEMORY) {
1330
- pixelBuffer = null;
1331
- }
1332
- }
1333
-
1334
-
1335
- // Releases the memory used by rgbaPixels either if the array hasn't been
1336
- // used many times yet, or if the JVM is running low in free memory.
1337
- protected void releaseRGBAPixels() {
1338
- double freeMB = Runtime.getRuntime().freeMemory() / 1E6;
1339
- if (rgbaPixUpdateCount < MAX_UPDATES || freeMB < MIN_MEMORY) {
1340
- rgbaPixels = null;
1341
- }
1342
- }
1343
-
1344
-
1345
- ///////////////////////////////////////////////////////////
1346
-
1347
- // Parameter handling
1348
-
1349
-
1350
- public Parameters getParameters() {
1351
- Parameters res = new Parameters();
1352
-
1353
- if (glTarget == PGL.TEXTURE_2D) {
1354
- res.target = TEX2D;
1355
- }
1356
-
1357
- if (glFormat == PGL.RGB) {
1358
- res.format = RGB;
1359
- } else if (glFormat == PGL.RGBA) {
1360
- res.format = ARGB;
1361
- } else if (glFormat == PGL.ALPHA) {
1362
- res.format = ALPHA;
1363
- }
1364
-
1365
- if (glMagFilter == PGL.NEAREST && glMinFilter == PGL.NEAREST) {
1366
- res.sampling = POINT;
1367
- res.mipmaps = false;
1368
- } else if (glMagFilter == PGL.NEAREST && glMinFilter == PGL.LINEAR) {
1369
- res.sampling = LINEAR;
1370
- res.mipmaps = false;
1371
- } else if (glMagFilter == PGL.NEAREST &&
1372
- glMinFilter == PGL.LINEAR_MIPMAP_NEAREST) {
1373
- res.sampling = LINEAR;
1374
- res.mipmaps = true;
1375
- } else if (glMagFilter == PGL.LINEAR && glMinFilter == PGL.LINEAR) {
1376
- res.sampling = BILINEAR;
1377
- res.mipmaps = false;
1378
- } else if (glMagFilter == PGL.LINEAR &&
1379
- glMinFilter == PGL.LINEAR_MIPMAP_NEAREST) {
1380
- res.sampling = BILINEAR;
1381
- res.mipmaps = true;
1382
- } else if (glMagFilter == PGL.LINEAR &&
1383
- glMinFilter == PGL.LINEAR_MIPMAP_LINEAR) {
1384
- res.sampling = TRILINEAR;
1385
- res.mipmaps = true;
1386
- }
1387
-
1388
- if (glWrapS == PGL.CLAMP_TO_EDGE) {
1389
- res.wrapU = CLAMP;
1390
- } else if (glWrapS == PGL.REPEAT) {
1391
- res.wrapU = REPEAT;
1392
- }
1393
-
1394
- if (glWrapT == PGL.CLAMP_TO_EDGE) {
1395
- res.wrapV = CLAMP;
1396
- } else if (glWrapT == PGL.REPEAT) {
1397
- res.wrapV = REPEAT;
1398
- }
1399
-
1400
- return res;
1401
- }
1402
-
1403
-
1404
- /**
1405
- * Sets texture target and internal format according to the target and
1406
- * type specified.
1407
- * @param target int
1408
- * @param params GLTextureParameters
1409
- */
1410
- protected void setParameters(Parameters params) {
1411
- if (params.target == TEX2D) {
1412
- glTarget = PGL.TEXTURE_2D;
1413
- } else {
1414
- throw new RuntimeException("Unknown texture target");
1415
- }
1416
-
1417
- if (params.format == RGB) {
1418
- glFormat = PGL.RGB;
1419
- } else if (params.format == ARGB) {
1420
- glFormat = PGL.RGBA;
1421
- } else if (params.format == ALPHA) {
1422
- glFormat = PGL.ALPHA;
1423
- } else {
1424
- throw new RuntimeException("Unknown texture format");
1425
- }
1426
-
1427
- boolean mipmaps = params.mipmaps && PGL.MIPMAPS_ENABLED;
1428
- if (mipmaps && !PGraphicsOpenGL.autoMipmapGenSupported) {
1429
- PGraphics.showWarning("Mipmaps were requested but automatic mipmap " +
1430
- "generation is not supported and manual " +
1431
- "generation still not implemented, so mipmaps " +
1432
- "will be disabled.");
1433
- mipmaps = false;
1434
- }
1435
-
1436
- if (params.sampling == POINT) {
1437
- glMagFilter = PGL.NEAREST;
1438
- glMinFilter = PGL.NEAREST;
1439
- } else if (params.sampling == LINEAR) {
1440
- glMagFilter = PGL.NEAREST;
1441
- glMinFilter = mipmaps ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR;
1442
- } else if (params.sampling == BILINEAR) {
1443
- glMagFilter = PGL.LINEAR;
1444
- glMinFilter = mipmaps ? PGL.LINEAR_MIPMAP_NEAREST : PGL.LINEAR;
1445
- } else if (params.sampling == TRILINEAR) {
1446
- glMagFilter = PGL.LINEAR;
1447
- glMinFilter = mipmaps ? PGL.LINEAR_MIPMAP_LINEAR : PGL.LINEAR;
1448
- } else {
1449
- throw new RuntimeException("Unknown texture filtering mode");
1450
- }
1451
-
1452
- if (params.wrapU == CLAMP) {
1453
- glWrapS = PGL.CLAMP_TO_EDGE;
1454
- } else if (params.wrapU == REPEAT) {
1455
- glWrapS = PGL.REPEAT;
1456
- } else {
1457
- throw new RuntimeException("Unknown wrapping mode");
1458
- }
1459
-
1460
- if (params.wrapV == CLAMP) {
1461
- glWrapT = PGL.CLAMP_TO_EDGE;
1462
- } else if (params.wrapV == REPEAT) {
1463
- glWrapT = PGL.REPEAT;
1464
- } else {
1465
- throw new RuntimeException("Unknown wrapping mode");
1466
- }
1467
-
1468
- usingMipmaps = glMinFilter == PGL.LINEAR_MIPMAP_NEAREST ||
1469
- glMinFilter == PGL.LINEAR_MIPMAP_LINEAR;
1470
-
1471
- usingRepeat = glWrapS == PGL.REPEAT || glWrapT == PGL.REPEAT;
1472
-
1473
- invertedX = false;
1474
- invertedY = false;
1475
- }
1476
-
1477
-
1478
- protected void fillEdges(int x, int y, int w, int h) {
1479
- if ((width < glWidth || height < glHeight) && (x + w == width || y + h == height)) {
1480
- if (x + w == width) {
1481
- int ew = glWidth - width;
1482
- edgePixels = new int[h * ew];
1483
- for (int i = 0; i < h; i++) {
1484
- int c = rgbaPixels[i * w + (w - 1)];
1485
- Arrays.fill(edgePixels, i * ew, (i + 1) * ew, c);
1486
- }
1487
- edgeBuffer = PGL.updateIntBuffer(edgeBuffer, edgePixels, true);
1488
- pgl.texSubImage2D(glTarget, 0, width, y, ew, h, PGL.RGBA,
1489
- PGL.UNSIGNED_BYTE, edgeBuffer);
1490
- }
1491
-
1492
- if (y + h == height) {
1493
- int eh = glHeight - height;
1494
- edgePixels = new int[eh * w];
1495
- for (int i = 0; i < eh; i++) {
1496
- System.arraycopy(rgbaPixels, (h - 1) * w, edgePixels, i * w, w);
1497
- }
1498
- edgeBuffer = PGL.updateIntBuffer(edgeBuffer, edgePixels, true);
1499
- pgl.texSubImage2D(glTarget, 0, x, height, w, eh, PGL.RGBA,
1500
- PGL.UNSIGNED_BYTE, edgeBuffer);
1501
- }
1502
-
1503
- if (x + w == width && y + h == height) {
1504
- int ew = glWidth - width;
1505
- int eh = glHeight - height;
1506
- int c = rgbaPixels[w * h - 1];
1507
- edgePixels = new int[eh * ew];
1508
- Arrays.fill(edgePixels, 0, eh * ew, c);
1509
- edgeBuffer = PGL.updateIntBuffer(edgeBuffer, edgePixels, true);
1510
- pgl.texSubImage2D(glTarget, 0, width, height, ew, eh, PGL.RGBA,
1511
- PGL.UNSIGNED_BYTE, edgeBuffer);
1512
- }
1513
- }
1514
- }
1515
-
1516
- ///////////////////////////////////////////////////////////////////////////
1517
-
1518
- // Parameters object
1519
-
1520
-
1521
- /**
1522
- * This class stores the parameters for a texture: target, internal format,
1523
- * minimization filter and magnification filter.
1524
- */
1525
- static public class Parameters {
1526
- /**
1527
- * Texture target.
1528
- */
1529
- public int target;
1546
+ public Parameters(Parameters src) {
1547
+ set(src);
1548
+ }
1530
1549
 
1531
- /**
1532
- * Texture internal format.
1533
- */
1534
- public int format;
1550
+ public void set(int format) {
1551
+ this.format = format;
1552
+ }
1535
1553
 
1536
- /**
1537
- * Texture filtering (POINT, LINEAR, BILINEAR or TRILINEAR).
1538
- */
1539
- public int sampling;
1554
+ public void set(int format, int sampling) {
1555
+ this.format = format;
1556
+ this.sampling = sampling;
1557
+ }
1540
1558
 
1541
- /**
1542
- * Use mipmaps or not.
1543
- */
1544
- public boolean mipmaps;
1559
+ public void set(int format, int sampling, boolean mipmaps) {
1560
+ this.format = format;
1561
+ this.sampling = sampling;
1562
+ this.mipmaps = mipmaps;
1563
+ }
1545
1564
 
1546
- /**
1547
- * Wrapping mode along U.
1548
- */
1549
- public int wrapU;
1565
+ public void set(Parameters src) {
1566
+ this.target = src.target;
1567
+ this.format = src.format;
1568
+ this.sampling = src.sampling;
1569
+ this.mipmaps = src.mipmaps;
1570
+ this.wrapU = src.wrapU;
1571
+ this.wrapV = src.wrapV;
1572
+ }
1573
+ }
1550
1574
 
1551
1575
  /**
1552
- * Wrapping mode along V.
1576
+ * This class stores a buffer copied from the buffer source.
1577
+ *
1553
1578
  */
1554
- public int wrapV;
1579
+ protected class BufferData {
1580
+
1581
+ int w, h;
1582
+ // Native buffer object.
1583
+ Object natBuf;
1584
+ // Buffer viewed as int.
1585
+ IntBuffer rgbBuf;
1586
+
1587
+ BufferData(Object nat, IntBuffer rgb, int w, int h) {
1588
+ natBuf = nat;
1589
+ rgbBuf = rgb;
1590
+ this.w = w;
1591
+ this.h = h;
1592
+ }
1555
1593
 
1556
- /**
1557
- * Sets all the parameters to default values.
1558
- */
1559
- public Parameters() {
1560
- this.target = TEX2D;
1561
- this.format = ARGB;
1562
- this.sampling = BILINEAR;
1563
- this.mipmaps = true;
1564
- this.wrapU = CLAMP;
1565
- this.wrapV = CLAMP;
1566
- }
1567
-
1568
- public Parameters(int format) {
1569
- this.target = TEX2D;
1570
- this.format = format;
1571
- this.sampling = BILINEAR;
1572
- this.mipmaps = true;
1573
- this.wrapU = CLAMP;
1574
- this.wrapV = CLAMP;
1575
- }
1576
-
1577
- public Parameters(int format, int sampling) {
1578
- this.target = TEX2D;
1579
- this.format = format;
1580
- this.sampling = sampling;
1581
- this.mipmaps = true;
1582
- this.wrapU = CLAMP;
1583
- this.wrapV = CLAMP;
1584
- }
1585
-
1586
- public Parameters(int format, int sampling, boolean mipmaps) {
1587
- this.target = TEX2D;
1588
- this.format = format;
1589
- this.mipmaps = mipmaps;
1590
- if (sampling == TRILINEAR && !mipmaps) {
1591
- this.sampling = BILINEAR;
1592
- } else {
1593
- this.sampling = sampling;
1594
- }
1595
- this.wrapU = CLAMP;
1596
- this.wrapV = CLAMP;
1597
- }
1598
-
1599
- public Parameters(int format, int sampling, boolean mipmaps, int wrap) {
1600
- this.target = TEX2D;
1601
- this.format = format;
1602
- this.mipmaps = mipmaps;
1603
- if (sampling == TRILINEAR && !mipmaps) {
1604
- this.sampling = BILINEAR;
1605
- } else {
1606
- this.sampling = sampling;
1607
- }
1608
- this.wrapU = wrap;
1609
- this.wrapV = wrap;
1610
- }
1611
-
1612
- public Parameters(Parameters src) {
1613
- set(src);
1614
- }
1615
-
1616
- public void set(int format) {
1617
- this.format = format;
1618
- }
1619
-
1620
- public void set(int format, int sampling) {
1621
- this.format = format;
1622
- this.sampling = sampling;
1623
- }
1624
-
1625
- public void set(int format, int sampling, boolean mipmaps) {
1626
- this.format = format;
1627
- this.sampling = sampling;
1628
- this.mipmaps = mipmaps;
1629
- }
1630
-
1631
- public void set(Parameters src) {
1632
- this.target = src.target;
1633
- this.format = src.format;
1634
- this.sampling = src.sampling;
1635
- this.mipmaps = src.mipmaps;
1636
- this.wrapU = src.wrapU;
1637
- this.wrapV = src.wrapV;
1638
- }
1639
- }
1640
-
1641
- /**
1642
- * This class stores a buffer copied from the buffer source.
1643
- *
1644
- */
1645
- protected class BufferData {
1646
- int w, h;
1647
- // Native buffer object.
1648
- Object natBuf;
1649
- // Buffer viewed as int.
1650
- IntBuffer rgbBuf;
1651
-
1652
- BufferData(Object nat, IntBuffer rgb, int w, int h) {
1653
- natBuf = nat;
1654
- rgbBuf = rgb;
1655
- this.w = w;
1656
- this.h = h;
1657
- }
1658
-
1659
- void dispose() {
1660
- try {
1661
- // Disposing the native buffer.
1662
- disposeBufferMethod.invoke(bufferSource, new Object[] { natBuf });
1663
- natBuf = null;
1664
- rgbBuf = null;
1665
- } catch (Exception e) {
1666
- e.printStackTrace();
1667
- }
1668
- }
1669
- }
1670
- }
1594
+ void dispose() {
1595
+ try {
1596
+ // Disposing the native buffer.
1597
+ disposeBufferMethod.invoke(bufferSource, new Object[]{natBuf});
1598
+ natBuf = null;
1599
+ rgbBuf = null;
1600
+ } catch (Exception e) {
1601
+ e.printStackTrace();
1602
+ }
1603
+ }
1604
+ }
1605
+ }