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