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