propane 2.7.2-java → 2.8.0.pre-java

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