-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
Expand file tree
/
Copy pathScreenUtils.java
More file actions
156 lines (139 loc) · 7.33 KB
/
ScreenUtils.java
File metadata and controls
156 lines (139 loc) · 7.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.utils;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Blending;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.MathUtils;
/** Class with static helper methods related to currently bound OpenGL frame buffer, including access to the current OpenGL
* FrameBuffer. These methods can be used to get the entire screen content or a portion thereof.
*
* @author espitz */
public final class ScreenUtils {
/** Clears the color buffers with the specified Color.
* @param color Color to clear the color buffers with. */
public static void clear (Color color) {
clear(color.r, color.g, color.b, color.a, false);
}
/** Clears the color buffers with the specified color. */
public static void clear (float r, float g, float b, float a) {
clear(r, g, b, a, false);
}
/** Clears the color buffers and optionally the depth buffer.
* @param color Color to clear the color buffers with.
* @param clearDepth Clears the depth buffer if true. */
public static void clear (Color color, boolean clearDepth) {
clear(color.r, color.g, color.b, color.a, clearDepth);
}
/** Clears the color buffers and optionally the depth buffer.
* @param clearDepth Clears the depth buffer if true. */
public static void clear (float r, float g, float b, float a, boolean clearDepth) {
clear(r, g, b, a, clearDepth, false);
}
/** Clears the color buffers, optionally the depth buffer and whether to apply antialiasing (requires to set number of samples
* in the launcher class).
*
* @param clearDepth Clears the depth buffer if true.
* @param applyAntialiasing applies multi-sampling for antialiasing if true. */
public static void clear (float r, float g, float b, float a, boolean clearDepth, boolean applyAntialiasing) {
Gdx.gl.glClearColor(r, g, b, a);
int mask = GL20.GL_COLOR_BUFFER_BIT;
if (clearDepth) mask = mask | GL20.GL_DEPTH_BUFFER_BIT;
if (applyAntialiasing && Gdx.graphics.getBufferFormat().coverageSampling) mask = mask | GL20.GL_COVERAGE_BUFFER_BIT_NV;
Gdx.gl.glClear(mask);
}
/** Returns the current framebuffer contents as a {@link TextureRegion} with a width and height equal to the current screen
* size. The base {@link Texture} always has {@link MathUtils#nextPowerOfTwo} dimensions and RGBA8888 {@link Format}. It can be
* accessed via {@link TextureRegion#getTexture}. The texture is not managed and has to be reloaded manually on a context loss.
* The returned TextureRegion is flipped along the Y axis by default. */
public static TextureRegion getFrameBufferTexture () {
final int w = Gdx.graphics.getBackBufferWidth();
final int h = Gdx.graphics.getBackBufferHeight();
return getFrameBufferTexture(0, 0, w, h);
}
/** Returns a portion of the current framebuffer contents specified by x, y, width and height as a {@link TextureRegion} with
* the same dimensions. The base {@link Texture} always has {@link MathUtils#nextPowerOfTwo} dimensions and RGBA8888
* {@link Format}. It can be accessed via {@link TextureRegion#getTexture}. This texture is not managed and has to be reloaded
* manually on a context loss. If the width and height specified are larger than the framebuffer dimensions, the Texture will
* be padded accordingly. Pixels that fall outside of the current screen will have RGBA values of 0.
*
* @param x the x position of the framebuffer contents to capture
* @param y the y position of the framebuffer contents to capture
* @param w the width of the framebuffer contents to capture
* @param h the height of the framebuffer contents to capture */
public static TextureRegion getFrameBufferTexture (int x, int y, int w, int h) {
final int potW = MathUtils.nextPowerOfTwo(w);
final int potH = MathUtils.nextPowerOfTwo(h);
final Pixmap pixmap = Pixmap.createFromFrameBuffer(x, y, w, h);
final Pixmap potPixmap = new Pixmap(potW, potH, Format.RGBA8888);
potPixmap.setBlending(Blending.None);
potPixmap.drawPixmap(pixmap, 0, 0);
Texture texture = new Texture(potPixmap);
TextureRegion textureRegion = new TextureRegion(texture, 0, h, w, -h);
potPixmap.dispose();
pixmap.dispose();
return textureRegion;
}
/** @deprecated use {@link Pixmap#createFromFrameBuffer(int, int, int, int)} instead. */
@Deprecated
public static Pixmap getFrameBufferPixmap (int x, int y, int w, int h) {
return Pixmap.createFromFrameBuffer(x, y, w, h);
}
/** Returns the current framebuffer contents as a byte[] array with a length equal to screen width * height * 4. The byte[]
* will always contain RGBA8888 data. Because of differences in screen and image origins the framebuffer contents should be
* flipped along the Y axis if you intend save them to disk as a bitmap. Flipping is not a cheap operation, so use this
* functionality wisely.
*
* @param flipY whether to flip pixels along Y axis */
public static byte[] getFrameBufferPixels (boolean flipY) {
final int w = Gdx.graphics.getBackBufferWidth();
final int h = Gdx.graphics.getBackBufferHeight();
return getFrameBufferPixels(0, 0, w, h, flipY);
}
/** Returns a portion of the current framebuffer contents specified by x, y, width and height, as a byte[] array with a length
* equal to the specified width * height * 4. The byte[] will always contain RGBA8888 data. If the width and height specified
* are larger than the framebuffer dimensions, the Texture will be padded accordingly. Pixels that fall outside of the current
* screen will have RGBA values of 0. Because of differences in screen and image origins the framebuffer contents should be
* flipped along the Y axis if you intend save them to disk as a bitmap. Flipping is not a cheap operation, so use this
* functionality wisely.
*
* @param flipY whether to flip pixels along Y axis */
public static byte[] getFrameBufferPixels (int x, int y, int w, int h, boolean flipY) {
Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1);
final ByteBuffer pixels = BufferUtils.newByteBuffer(w * h * 4);
Gdx.gl.glReadPixels(x, y, w, h, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, pixels);
final int numBytes = w * h * 4;
byte[] lines = new byte[numBytes];
if (flipY) {
final int numBytesPerLine = w * 4;
for (int i = 0; i < h; i++) {
((Buffer)pixels).position((h - i - 1) * numBytesPerLine);
pixels.get(lines, i * numBytesPerLine, numBytesPerLine);
}
} else {
((Buffer)pixels).clear();
pixels.get(lines);
}
return lines;
}
}