Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epoxy
GitHub Repository: epoxy/proj11
Path: blob/master/SLICK_HOME/src/org/newdawn/slick/opengl/InternalTextureLoader.java
1461 views
1
package org.newdawn.slick.opengl;
2
3
import java.io.BufferedInputStream;
4
import java.io.File;
5
import java.io.FileInputStream;
6
import java.io.IOException;
7
import java.io.InputStream;
8
import java.lang.ref.SoftReference;
9
import java.nio.ByteBuffer;
10
import java.nio.ByteOrder;
11
import java.nio.IntBuffer;
12
import java.util.HashMap;
13
14
import org.lwjgl.BufferUtils;
15
import org.lwjgl.opengl.GL11;
16
import org.newdawn.slick.util.ResourceLoader;
17
18
/**
19
* A texture loaded based on many old versions that will load image data from a file
20
* and produce OpenGL textures.
21
*
22
* @see ImageData
23
*
24
* @author kevin
25
*/
26
public class InternalTextureLoader {
27
/** The standard texture loaded used everywhere */
28
private static final InternalTextureLoader loader = new InternalTextureLoader();
29
30
/**
31
* Get the single instance of this texture loader
32
*
33
* @return The single instance of the texture loader
34
*/
35
public static InternalTextureLoader get() {
36
return loader;
37
}
38
39
/** The table of textures that have been loaded in this loader */
40
private HashMap texturesLinear = new HashMap();
41
/** The table of textures that have been loaded in this loader */
42
private HashMap texturesNearest = new HashMap();
43
/** The destination pixel format */
44
private int dstPixelFormat = GL11.GL_RGBA8;
45
/** True if we're using deferred loading */
46
private boolean deferred;
47
48
/**
49
* Create a new texture loader based on the game panel
50
*/
51
private InternalTextureLoader() {
52
}
53
54
/**
55
* True if we should only record the request to load in the intention
56
* of loading the texture later
57
*
58
* @param deferred True if the we should load a token
59
*/
60
public void setDeferredLoading(boolean deferred) {
61
this.deferred = deferred;
62
}
63
64
/**
65
* Check if we're using deferred loading
66
*
67
* @return True if we're loading deferred textures
68
*/
69
public boolean isDeferredLoading() {
70
return deferred;
71
}
72
73
/**
74
* Remove a particular named image from the cache
75
*
76
* @param name The name of the image to be cleared
77
*/
78
public void clear(String name) {
79
texturesLinear.remove(name);
80
texturesNearest.remove(name);
81
}
82
83
/**
84
* Clear out the cached textures
85
*/
86
public void clear() {
87
texturesLinear.clear();
88
texturesNearest.clear();
89
}
90
91
/**
92
* Tell the loader to produce 16 bit textures
93
*/
94
public void set16BitMode() {
95
dstPixelFormat = GL11.GL_RGBA16;
96
}
97
98
/**
99
* Create a new texture ID
100
*
101
* @return A new texture ID
102
*/
103
public static int createTextureID()
104
{
105
IntBuffer tmp = createIntBuffer(1);
106
GL11.glGenTextures(tmp);
107
return tmp.get(0);
108
}
109
110
/**
111
* Get a texture from a specific file
112
*
113
* @param source The file to load the texture from
114
* @param flipped True if we should flip the texture on the y axis while loading
115
* @param filter The filter to use
116
* @return The texture loaded
117
* @throws IOException Indicates a failure to load the image
118
*/
119
public Texture getTexture(File source, boolean flipped,int filter) throws IOException {
120
String resourceName = source.getAbsolutePath();
121
InputStream in = new FileInputStream(source);
122
123
return getTexture(in, resourceName, flipped, filter, null);
124
}
125
126
/**
127
* Get a texture from a specific file
128
*
129
* @param source The file to load the texture from
130
* @param flipped True if we should flip the texture on the y axis while loading
131
* @param filter The filter to use
132
* @param transparent The colour to interpret as transparent or null if none
133
* @return The texture loaded
134
* @throws IOException Indicates a failure to load the image
135
*/
136
public Texture getTexture(File source, boolean flipped,int filter, int[] transparent) throws IOException {
137
String resourceName = source.getAbsolutePath();
138
InputStream in = new FileInputStream(source);
139
140
return getTexture(in, resourceName, flipped, filter, transparent);
141
}
142
143
/**
144
* Get a texture from a resource location
145
*
146
* @param resourceName The location to load the texture from
147
* @param flipped True if we should flip the texture on the y axis while loading
148
* @param filter The filter to use when scaling the texture
149
* @return The texture loaded
150
* @throws IOException Indicates a failure to load the image
151
*/
152
public Texture getTexture(String resourceName, boolean flipped, int filter) throws IOException {
153
InputStream in = ResourceLoader.getResourceAsStream(resourceName);
154
155
return getTexture(in, resourceName, flipped, filter, null);
156
}
157
158
/**
159
* Get a texture from a resource location
160
*
161
* @param resourceName The location to load the texture from
162
* @param flipped True if we should flip the texture on the y axis while loading
163
* @param filter The filter to use when scaling the texture
164
* @param transparent The colour to interpret as transparent or null if none
165
* @return The texture loaded
166
* @throws IOException Indicates a failure to load the image
167
*/
168
public Texture getTexture(String resourceName, boolean flipped, int filter, int[] transparent) throws IOException {
169
InputStream in = ResourceLoader.getResourceAsStream(resourceName);
170
171
return getTexture(in, resourceName, flipped, filter, transparent);
172
}
173
/**
174
* Get a texture from a image file
175
*
176
* @param in The stream from which we can load the image
177
* @param resourceName The name to give this image in the internal cache
178
* @param flipped True if we should flip the image on the y-axis while loading
179
* @param filter The filter to use when scaling the texture
180
* @return The texture loaded
181
* @throws IOException Indicates a failure to load the image
182
*/
183
public Texture getTexture(InputStream in, String resourceName, boolean flipped, int filter) throws IOException {
184
return getTexture(in, resourceName, flipped, filter, null);
185
}
186
187
/**
188
* Get a texture from a image file
189
*
190
* @param in The stream from which we can load the image
191
* @param resourceName The name to give this image in the internal cache
192
* @param flipped True if we should flip the image on the y-axis while loading
193
* @param filter The filter to use when scaling the texture
194
* @param transparent The colour to interpret as transparent or null if none
195
* @return The texture loaded
196
* @throws IOException Indicates a failure to load the image
197
*/
198
public TextureImpl getTexture(InputStream in, String resourceName, boolean flipped, int filter, int[] transparent) throws IOException {
199
if (deferred) {
200
return new DeferredTexture(in, resourceName, flipped, filter, transparent);
201
}
202
203
HashMap hash = texturesLinear;
204
if (filter == GL11.GL_NEAREST) {
205
hash = texturesNearest;
206
}
207
208
String resName = resourceName;
209
if (transparent != null) {
210
resName += ":"+transparent[0]+":"+transparent[1]+":"+transparent[2];
211
}
212
resName += ":"+flipped;
213
214
SoftReference ref = (SoftReference) hash.get(resName);
215
if (ref != null) {
216
TextureImpl tex = (TextureImpl) ref.get();
217
if (tex != null) {
218
return tex;
219
} else {
220
hash.remove(resName);
221
}
222
}
223
224
// horrible test until I can find something more suitable
225
try {
226
GL11.glGetError();
227
} catch (NullPointerException e) {
228
throw new RuntimeException("Image based resources must be loaded as part of init() or the game loop. They cannot be loaded before initialisation.");
229
}
230
231
TextureImpl tex = getTexture(in, resourceName,
232
GL11.GL_TEXTURE_2D,
233
filter,
234
filter, flipped, transparent);
235
236
tex.setCacheName(resName);
237
hash.put(resName, new SoftReference(tex));
238
239
return tex;
240
}
241
242
/**
243
* Get a texture from a image file
244
*
245
* @param in The stream from which we can load the image
246
* @param resourceName The name to give this image in the internal cache
247
* @param flipped True if we should flip the image on the y-axis while loading
248
* @param target The texture target we're loading this texture into
249
* @param minFilter The scaling down filter
250
* @param magFilter The scaling up filter
251
* @param transparent The colour to interpret as transparent or null if none
252
* @return The texture loaded
253
* @throws IOException Indicates a failure to load the image
254
*/
255
private TextureImpl getTexture(InputStream in,
256
String resourceName,
257
int target,
258
int magFilter,
259
int minFilter, boolean flipped, int[] transparent) throws IOException
260
{
261
// create the texture ID for this texture
262
int textureID = createTextureID();
263
TextureImpl texture = new TextureImpl(resourceName, target, textureID);
264
265
// bind this texture
266
GL11.glBindTexture(target, textureID);
267
268
ByteBuffer textureBuffer;
269
int width;
270
int height;
271
int texWidth;
272
int texHeight;
273
274
boolean hasAlpha;
275
276
LoadableImageData imageData = ImageDataFactory.getImageDataFor(resourceName);
277
textureBuffer = imageData.loadImage(new BufferedInputStream(in), flipped, transparent);
278
279
width = imageData.getWidth();
280
height = imageData.getHeight();
281
hasAlpha = imageData.getDepth() == 32;
282
283
texture.setTextureWidth(imageData.getTexWidth());
284
texture.setTextureHeight(imageData.getTexHeight());
285
286
texWidth = texture.getTextureWidth();
287
texHeight = texture.getTextureHeight();
288
289
IntBuffer temp = BufferUtils.createIntBuffer(16);
290
GL11.glGetInteger(GL11.GL_MAX_TEXTURE_SIZE, temp);
291
int max = temp.get(0);
292
if ((texWidth > max) || (texHeight > max)) {
293
throw new IOException("Attempt to allocate a texture to big for the current hardware");
294
}
295
296
int srcPixelFormat = hasAlpha ? GL11.GL_RGBA : GL11.GL_RGB;
297
int componentCount = hasAlpha ? 4 : 3;
298
299
texture.setWidth(width);
300
texture.setHeight(height);
301
texture.setAlpha(hasAlpha);
302
303
GL11.glTexParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, minFilter);
304
GL11.glTexParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, magFilter);
305
306
// produce a texture from the byte buffer
307
GL11.glTexImage2D(target,
308
0,
309
dstPixelFormat,
310
get2Fold(width),
311
get2Fold(height),
312
0,
313
srcPixelFormat,
314
GL11.GL_UNSIGNED_BYTE,
315
textureBuffer);
316
317
return texture;
318
}
319
320
/**
321
* Create an empty texture
322
*
323
* @param width The width of the new texture
324
* @param height The height of the new texture
325
* @return The created empty texture
326
* @throws IOException Indicates a failure to create the texture on the graphics hardware
327
*/
328
public Texture createTexture(final int width, final int height) throws IOException {
329
return createTexture(width, height, GL11.GL_NEAREST);
330
}
331
332
/**
333
* Create an empty texture
334
*
335
* @param width The width of the new texture
336
* @param height The height of the new texture
337
* @return The created empty texture
338
* @throws IOException Indicates a failure to create the texture on the graphics hardware
339
*/
340
public Texture createTexture(final int width, final int height, final int filter) throws IOException {
341
ImageData ds = new EmptyImageData(width, height);
342
343
return getTexture(ds, filter);
344
}
345
346
/**
347
* Get a texture from a image file
348
*
349
* @param dataSource The image data to generate the texture from
350
* @param filter The filter to use when scaling the texture
351
* @return The texture created
352
* @throws IOException Indicates the texture is too big for the hardware
353
*/
354
public Texture getTexture(ImageData dataSource, int filter) throws IOException
355
{
356
int target = GL11.GL_TEXTURE_2D;
357
358
// create the texture ID for this texture
359
int textureID = createTextureID();
360
TextureImpl texture = new TextureImpl("generated:"+dataSource, target ,textureID);
361
362
int minFilter = filter;
363
int magFilter = filter;
364
boolean flipped = false;
365
366
// bind this texture
367
GL11.glBindTexture(target, textureID);
368
369
ByteBuffer textureBuffer;
370
int width;
371
int height;
372
int texWidth;
373
int texHeight;
374
375
boolean hasAlpha;
376
textureBuffer = dataSource.getImageBufferData();
377
378
width = dataSource.getWidth();
379
height = dataSource.getHeight();
380
hasAlpha = dataSource.getDepth() == 32;
381
382
texture.setTextureWidth(dataSource.getTexWidth());
383
texture.setTextureHeight(dataSource.getTexHeight());
384
385
texWidth = texture.getTextureWidth();
386
texHeight = texture.getTextureHeight();
387
388
int srcPixelFormat = hasAlpha ? GL11.GL_RGBA : GL11.GL_RGB;
389
int componentCount = hasAlpha ? 4 : 3;
390
391
texture.setWidth(width);
392
texture.setHeight(height);
393
texture.setAlpha(hasAlpha);
394
395
IntBuffer temp = BufferUtils.createIntBuffer(16);
396
GL11.glGetInteger(GL11.GL_MAX_TEXTURE_SIZE, temp);
397
int max = temp.get(0);
398
if ((texWidth > max) || (texHeight > max)) {
399
throw new IOException("Attempt to allocate a texture to big for the current hardware");
400
}
401
402
GL11.glTexParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, minFilter);
403
GL11.glTexParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, magFilter);
404
405
// produce a texture from the byte buffer
406
GL11.glTexImage2D(target,
407
0,
408
dstPixelFormat,
409
get2Fold(width),
410
get2Fold(height),
411
0,
412
srcPixelFormat,
413
GL11.GL_UNSIGNED_BYTE,
414
textureBuffer);
415
416
return texture;
417
}
418
419
/**
420
* Get the closest greater power of 2 to the fold number
421
*
422
* @param fold The target number
423
* @return The power of 2
424
*/
425
public static int get2Fold(int fold) {
426
int ret = 2;
427
while (ret < fold) {
428
ret *= 2;
429
}
430
return ret;
431
}
432
433
/**
434
* Creates an integer buffer to hold specified ints
435
* - strictly a utility method
436
*
437
* @param size how many int to contain
438
* @return created IntBuffer
439
*/
440
public static IntBuffer createIntBuffer(int size) {
441
ByteBuffer temp = ByteBuffer.allocateDirect(4 * size);
442
temp.order(ByteOrder.nativeOrder());
443
444
return temp.asIntBuffer();
445
}
446
}
447
448