propane 3.4.2-java → 3.5.0-java

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