propane 3.9.0-java → 3.10.0-java

Sign up to get free protection for your applications and to get access to all the features.
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
+ }