50 |
51 |
52 |
53 |
58 |
63 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/src/org/lwjgl/util/stream/RenderStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002-2012 LWJGL Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * * Neither the name of 'LWJGL' nor the names of
17 | * its contributors may be used to endorse or promote products derived
18 | * from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 | package org.lwjgl.util.stream;
33 |
34 | /** @author Spasi */
35 | public interface RenderStream {
36 |
37 | StreamHandler getHandler();
38 |
39 | void bind();
40 |
41 | void swapBuffers();
42 |
43 | void destroy();
44 |
45 | }
--------------------------------------------------------------------------------
/src/org/lwjgl/util/stream/RenderStreamINTEL.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002-2012 LWJGL Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * * Neither the name of 'LWJGL' nor the names of
17 | * its contributors may be used to endorse or promote products derived
18 | * from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 | package org.lwjgl.util.stream;
33 |
34 | import org.lwjgl.BufferUtils;
35 | import org.lwjgl.opengl.ContextCapabilities;
36 | import org.lwjgl.opengl.GLContext;
37 | import org.lwjgl.util.stream.StreamUtil.RenderStreamFactory;
38 |
39 | import java.nio.ByteBuffer;
40 | import java.nio.IntBuffer;
41 |
42 | import static org.lwjgl.opengl.GL11.*;
43 | import static org.lwjgl.opengl.GL12.*;
44 | import static org.lwjgl.opengl.GL30.*;
45 | import static org.lwjgl.opengl.INTELMapTexture.*;
46 |
47 | /**
48 | * Optimized StreamPBOReader for Intel IGPs:
49 | *
50 | * - We render to a standard FBO.
51 | * - We asynchronously blit to another FBO with INTEL_map_texture attachments (linear layout).
52 | * - We synchronously map the linear textures.
53 | *
54 | */
55 | final class RenderStreamINTEL extends StreamBuffered implements RenderStream {
56 |
57 | public static final RenderStreamFactory FACTORY = new RenderStreamFactory("INTEL_map_texture") {
58 | public boolean isSupported(final ContextCapabilities caps) {
59 | // TODO: We currently require BlitFramebuffer. Relax and implement manually?
60 | return caps.GL_INTEL_map_texture && (caps.OpenGL30 || caps.GL_ARB_framebuffer_object || caps.GL_EXT_framebuffer_blit);
61 | }
62 |
63 | public RenderStream create(final StreamHandler handler, final int samples, final int transfersToBuffer) {
64 | return new RenderStreamINTEL(handler, samples, transfersToBuffer);
65 | }
66 | };
67 |
68 | private final IntBuffer strideBuffer;
69 | private final IntBuffer layoutBuffer;
70 |
71 | private final StreamUtil.FBOUtil fboUtil;
72 | private final int renderFBO;
73 |
74 | private int rgbaBuffer;
75 | private int depthBuffer;
76 |
77 | private final int resolveFBO;
78 | private final int[] resolveBuffers;
79 |
80 | private int samples;
81 |
82 | private int synchronousFrames;
83 |
84 | RenderStreamINTEL(final StreamHandler handler, final int samples, final int transfersToBuffer) {
85 | super(handler, transfersToBuffer);
86 |
87 | final ContextCapabilities caps = GLContext.getCapabilities();
88 |
89 | this.strideBuffer = BufferUtils.createIntBuffer(1);
90 | this.layoutBuffer = BufferUtils.createIntBuffer(1);
91 |
92 | fboUtil = StreamUtil.getFBOUtil(caps);
93 | renderFBO = fboUtil.genFramebuffers();
94 |
95 | resolveFBO = fboUtil.genFramebuffers();
96 | resolveBuffers = new int[transfersToBuffer];
97 |
98 | this.samples = StreamUtil.checkSamples(samples, caps);
99 | }
100 |
101 | public StreamHandler getHandler() {
102 | return handler;
103 | }
104 |
105 | private void resize(final int width, final int height) {
106 | if ( width < 0 || height < 0 )
107 | throw new IllegalArgumentException("Invalid dimensions: " + width + " x " + height);
108 |
109 | destroyObjects();
110 |
111 | this.width = width;
112 | this.height = height;
113 |
114 | this.stride = StreamUtil.getStride(width);
115 |
116 | if ( width == 0 || height == 0 )
117 | return;
118 |
119 | bufferIndex = synchronousFrames = transfersToBuffer - 1;
120 |
121 | // Setup render FBO
122 |
123 | fboUtil.bindFramebuffer(GL_DRAW_FRAMEBUFFER, renderFBO);
124 |
125 | rgbaBuffer = StreamUtil.createRenderBuffer(fboUtil, width, height, samples, GL_RGBA8);
126 | fboUtil.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rgbaBuffer);
127 |
128 | depthBuffer = StreamUtil.createRenderBuffer(fboUtil, width, height, samples, GL_DEPTH24_STENCIL8);
129 | fboUtil.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
130 |
131 | glViewport(0, 0, width, height);
132 |
133 | fboUtil.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
134 |
135 | for ( int i = 0; i < resolveBuffers.length; i++ )
136 | resolveBuffers[i] = genLayoutLinearTexture(width, height);
137 |
138 | glBindTexture(GL_TEXTURE_2D, 0);
139 | }
140 |
141 | private static int genLayoutLinearTexture(final int width, final int height) {
142 | final int texID = glGenTextures();
143 |
144 | glBindTexture(GL_TEXTURE_2D, texID);
145 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
146 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
147 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MEMORY_LAYOUT_INTEL, GL_LAYOUT_LINEAR_CPU_CACHED_INTEL);
148 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, (ByteBuffer)null);
149 |
150 | return texID;
151 | }
152 |
153 | public void bind() {
154 | if ( this.width != handler.getWidth() || this.height != handler.getHeight() )
155 | resize(handler.getWidth(), handler.getHeight());
156 |
157 | fboUtil.bindFramebuffer(GL_DRAW_FRAMEBUFFER, renderFBO);
158 | }
159 |
160 | private void prepareFramebuffer(final int trgTEX) {
161 | // Back-pressure. Make sure we never buffer more than frames ahead.
162 | if ( processingState.get(trgTEX) )
163 | waitForProcessingToComplete(trgTEX);
164 |
165 | fboUtil.bindFramebuffer(GL_READ_FRAMEBUFFER, renderFBO);
166 | fboUtil.bindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
167 |
168 | // Blit current texture
169 | fboUtil.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveBuffers[trgTEX], 0);
170 | fboUtil.blitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
171 |
172 | fboUtil.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
173 | fboUtil.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
174 | }
175 |
176 | public void swapBuffers() {
177 | if ( width == 0 || height == 0 )
178 | return;
179 |
180 | final int trgTEX = (int)(bufferIndex % transfersToBuffer);
181 | final int srcTEX = (int)((bufferIndex - 1) % transfersToBuffer);
182 |
183 | prepareFramebuffer(trgTEX);
184 |
185 | // This will be non-zero for the first (transfersToBuffer - 1) frames
186 | // after start-up or a resize.
187 | if ( 0 < synchronousFrames ) {
188 | // The srcTEX is currently empty. Wait for trgPBO's ReadPixels to complete and copy the current frame to srcTEX.
189 | // We do this to avoid sending an empty buffer for processing, which would cause a visible flicker on resize.
190 | copyFrames(trgTEX, srcTEX);
191 | synchronousFrames--;
192 | }
193 |
194 | // Time to process the srcTEX
195 |
196 | pinBuffer(srcTEX);
197 |
198 | // Send the buffer for processing
199 |
200 | processingState.set(srcTEX, true);
201 | semaphores[srcTEX].acquireUninterruptibly();
202 |
203 | handler.process(
204 | width, height,
205 | pinnedBuffers[srcTEX],
206 | stride,
207 | semaphores[srcTEX]
208 | );
209 |
210 | bufferIndex++;
211 | }
212 |
213 | private void copyFrames(final int src, final int trg) {
214 | pinnedBuffers[src] = glMapTexture2DINTEL(resolveBuffers[src], 0, height * stride, GL_MAP_READ_BIT, strideBuffer, layoutBuffer, pinnedBuffers[src]);
215 | pinnedBuffers[trg] = glMapTexture2DINTEL(resolveBuffers[trg], 0, height * stride, GL_MAP_WRITE_BIT, strideBuffer, layoutBuffer, pinnedBuffers[trg]);
216 |
217 | pinnedBuffers[trg].put(pinnedBuffers[src]);
218 |
219 | pinnedBuffers[src].flip();
220 | pinnedBuffers[trg].flip();
221 |
222 | glUnmapTexture2DINTEL(resolveBuffers[trg], 0);
223 | glUnmapTexture2DINTEL(resolveBuffers[src], 0);
224 | }
225 |
226 | private void pinBuffer(final int index) {
227 | final int texID = resolveBuffers[index];
228 |
229 | pinnedBuffers[index] = glMapTexture2DINTEL(texID, 0, height * stride, GL_MAP_READ_BIT, strideBuffer, layoutBuffer, pinnedBuffers[index]);
230 | // TODO: Row alignment is currently hardcoded to 16 pixels
231 | // We wouldn't need to do that if we could create a ByteBuffer
232 | // from an arbitrary address + length. Consider for LWJGL 3.0?
233 | checkStride(index, texID);
234 | }
235 |
236 | private void checkStride(final int index, final int texID) {
237 | if ( strideBuffer.get(0) != stride ) {
238 | System.err.println("Wrong stride: " + stride + ". Should be: " + strideBuffer.get(0));
239 | glUnmapTexture2DINTEL(texID, 0);
240 | stride = strideBuffer.get(0);
241 | pinnedBuffers[index] = glMapTexture2DINTEL(texID, 0, height * stride, GL_MAP_READ_BIT, strideBuffer, layoutBuffer, pinnedBuffers[index]);
242 | }
243 | }
244 |
245 | protected void postProcess(int index) {
246 | glUnmapTexture2DINTEL(resolveBuffers[index], 0);
247 | }
248 |
249 | private void destroyObjects() {
250 | for ( int i = 0; i < semaphores.length; i++ ) {
251 | if ( processingState.get(i) )
252 | waitForProcessingToComplete(i);
253 | }
254 |
255 | if ( rgbaBuffer != 0 ) fboUtil.deleteRenderbuffers(rgbaBuffer);
256 | if ( depthBuffer != 0 ) fboUtil.deleteRenderbuffers(depthBuffer);
257 |
258 | for ( int i = 0; i < resolveBuffers.length; i++ ) {
259 | glDeleteTextures(resolveBuffers[i]);
260 | resolveBuffers[i] = 0;
261 | }
262 | }
263 |
264 | public void destroy() {
265 | destroyObjects();
266 |
267 | if ( resolveFBO != 0 )
268 | fboUtil.deleteFramebuffers(resolveFBO);
269 | fboUtil.deleteFramebuffers(renderFBO);
270 | }
271 |
272 | }
--------------------------------------------------------------------------------
/src/org/lwjgl/util/stream/RenderStreamPBO.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002-2012 LWJGL Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * * Neither the name of 'LWJGL' nor the names of
17 | * its contributors may be used to endorse or promote products derived
18 | * from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 | package org.lwjgl.util.stream;
33 |
34 | import org.lwjgl.opengl.ContextCapabilities;
35 | import org.lwjgl.opengl.GLContext;
36 |
37 | import static org.lwjgl.opengl.GL11.*;
38 | import static org.lwjgl.opengl.GL12.*;
39 | import static org.lwjgl.opengl.GL15.*;
40 | import static org.lwjgl.opengl.GL21.*;
41 | import static org.lwjgl.opengl.GL30.*;
42 |
43 | /** Implements streaming PBO updates from a framebuffer object. */
44 | abstract class RenderStreamPBO extends StreamBufferedPBO implements RenderStream {
45 |
46 | public static enum ReadbackType {
47 | /** RenderBuffers on FBO, ReadPixels to readback. */
48 | READ_PIXELS,
49 | /** Textures on FBO, GetTexImage to readback. */
50 | GET_TEX_IMAGE
51 | }
52 |
53 | private final ReadbackType readbackType;
54 |
55 | protected final StreamUtil.FBOUtil fboUtil;
56 | private final int renderFBO;
57 |
58 | private int samples;
59 |
60 | private int rgbaBuffer;
61 | private int depthBuffer;
62 |
63 | private int msaaResolveFBO;
64 | private int msaaResolveBuffer;
65 |
66 | protected int synchronousFrames;
67 |
68 | protected RenderStreamPBO(final StreamHandler handler, final int samples, final int transfersToBuffer, final ReadbackType readbackType) {
69 | super(handler, transfersToBuffer);
70 |
71 | this.readbackType = readbackType;
72 |
73 | final ContextCapabilities caps = GLContext.getCapabilities();
74 |
75 | fboUtil = StreamUtil.getFBOUtil(caps);
76 | renderFBO = fboUtil.genFramebuffers();
77 |
78 | this.samples = StreamUtil.checkSamples(samples, caps);
79 | }
80 |
81 | public StreamHandler getHandler() {
82 | return handler;
83 | }
84 |
85 | private void resize(final int width, final int height) {
86 | if ( width < 0 || height < 0 )
87 | throw new IllegalArgumentException("Invalid dimensions: " + width + " x " + height);
88 |
89 | destroyObjects();
90 |
91 | this.width = width;
92 | this.height = height;
93 |
94 | this.stride = StreamUtil.getStride(width);
95 |
96 | if ( width == 0 || height == 0 )
97 | return;
98 |
99 | bufferIndex = synchronousFrames = transfersToBuffer - 1;
100 |
101 | // Setup render FBO
102 |
103 | fboUtil.bindFramebuffer(GL_DRAW_FRAMEBUFFER, renderFBO);
104 |
105 | if ( samples <= 1 && readbackType == ReadbackType.GET_TEX_IMAGE )
106 | fboUtil.framebufferTexture2D(
107 | GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
108 | rgbaBuffer = StreamUtil.createRenderTexture(width, height), 0
109 | );
110 | else
111 | fboUtil.framebufferRenderbuffer(
112 | GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
113 | rgbaBuffer = StreamUtil.createRenderBuffer(fboUtil, width, height, samples, GL_RGBA8)
114 | );
115 |
116 | fboUtil.framebufferRenderbuffer(
117 | GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
118 | depthBuffer = StreamUtil.createRenderBuffer(fboUtil, width, height, samples, GL_DEPTH24_STENCIL8)
119 | );
120 |
121 | glViewport(0, 0, width, height);
122 |
123 | fboUtil.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
124 |
125 | if ( 1 < samples ) {
126 | // Setup MSAA resolve FBO
127 |
128 | if ( msaaResolveFBO == 0 ) msaaResolveFBO = fboUtil.genFramebuffers();
129 |
130 | fboUtil.bindFramebuffer(GL_READ_FRAMEBUFFER, msaaResolveFBO);
131 |
132 | if ( readbackType == ReadbackType.READ_PIXELS )
133 | fboUtil.framebufferRenderbuffer(
134 | GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
135 | msaaResolveBuffer = StreamUtil.createRenderBuffer(fboUtil, width, height, GL_RGBA8)
136 | );
137 | else
138 | fboUtil.framebufferTexture2D(
139 | GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
140 | msaaResolveBuffer = StreamUtil.createRenderTexture(width, height), 0
141 | );
142 |
143 | fboUtil.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
144 | } else if ( msaaResolveFBO != 0 ) {
145 | if ( readbackType == ReadbackType.READ_PIXELS )
146 | fboUtil.deleteRenderbuffers(msaaResolveBuffer);
147 | else
148 | glDeleteTextures(msaaResolveBuffer);
149 | msaaResolveBuffer = 0;
150 |
151 | fboUtil.deleteFramebuffers(msaaResolveFBO);
152 | msaaResolveFBO = 0;
153 | }
154 |
155 | // Setup read-back buffers
156 |
157 | resizeBuffers(height, stride);
158 | }
159 |
160 | protected void resizeBuffers(final int height, final int stride) {
161 | super.resizeBuffers(height, stride, GL_PIXEL_PACK_BUFFER, GL_STREAM_READ);
162 | }
163 |
164 | public void bind() {
165 | if ( this.width != handler.getWidth() || this.height != handler.getHeight() )
166 | resize(handler.getWidth(), handler.getHeight());
167 |
168 | fboUtil.bindFramebuffer(GL_DRAW_FRAMEBUFFER, renderFBO);
169 | }
170 |
171 | protected void prepareFramebuffer() {
172 | if ( msaaResolveFBO == 0 )
173 | fboUtil.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
174 | else {
175 | // Resolve MSAA
176 | fboUtil.bindFramebuffer(GL_READ_FRAMEBUFFER, renderFBO);
177 | fboUtil.bindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaResolveFBO);
178 | fboUtil.blitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
179 | fboUtil.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
180 | fboUtil.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
181 | }
182 | }
183 |
184 | public void swapBuffers() {
185 | if ( width == 0 || height == 0 )
186 | return;
187 |
188 | prepareFramebuffer();
189 |
190 | final int trgPBO = (int)(bufferIndex % transfersToBuffer);
191 | final int srcPBO = (int)((bufferIndex - 1) % transfersToBuffer);
192 |
193 | glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[trgPBO]);
194 |
195 | // Back-pressure. Make sure we never buffer more than frames ahead.
196 | if ( processingState.get(trgPBO) )
197 | waitForProcessingToComplete(trgPBO);
198 |
199 | readBack(trgPBO);
200 |
201 | // This will be non-zero for the first (transfersToBuffer - 1) frames
202 | // after start-up or a resize.
203 | if ( 0 < synchronousFrames ) {
204 | // The srcPBO is currently empty. Wait for trgPBO's ReadPixels to complete and copy the current frame to srcPBO.
205 | // We do this to avoid sending an empty buffer for processing, which would cause a visible flicker on resize.
206 | copyFrames(trgPBO, srcPBO);
207 | synchronousFrames--;
208 | }
209 |
210 | // Time to process the srcPBO
211 |
212 | pinBuffer(srcPBO);
213 |
214 | // Send the buffer for processing
215 |
216 | processingState.set(srcPBO, true);
217 | semaphores[srcPBO].acquireUninterruptibly();
218 |
219 | handler.process(
220 | width, height,
221 | pinnedBuffers[srcPBO],
222 | stride,
223 | semaphores[srcPBO]
224 | );
225 |
226 | bufferIndex++;
227 | }
228 |
229 | protected void readBack(final int index) {
230 | // Stride in pixels
231 | glPixelStorei(GL_PACK_ROW_LENGTH, stride >> 2);
232 |
233 | // Asynchronously transfer current frame
234 | if ( readbackType == ReadbackType.READ_PIXELS ) {
235 | fboUtil.bindFramebuffer(GL_READ_FRAMEBUFFER, msaaResolveFBO == 0 ? renderFBO : msaaResolveFBO);
236 | glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
237 | fboUtil.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
238 | } else {
239 | glBindTexture(GL_TEXTURE_2D, msaaResolveFBO == 0 ? rgbaBuffer : msaaResolveBuffer);
240 | glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
241 | glBindTexture(GL_TEXTURE_2D, 0);
242 | }
243 |
244 | // Restore PACK_ROW_LENGTH
245 | glPixelStorei(GL_PACK_ROW_LENGTH, 0);
246 | }
247 |
248 | protected abstract void copyFrames(final int src, final int trg);
249 |
250 | protected abstract void pinBuffer(final int index);
251 |
252 | protected void destroyObjects() {
253 | for ( int i = 0; i < semaphores.length; i++ ) {
254 | if ( processingState.get(i) ) {
255 | glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[i]);
256 | waitForProcessingToComplete(i);
257 | }
258 | }
259 |
260 | glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
261 |
262 | for ( int i = 0; i < pbos.length; i++ ) {
263 | if ( pbos[i] != 0 )
264 | glDeleteBuffers(pbos[i]);
265 | }
266 |
267 | if ( msaaResolveBuffer != 0 ) {
268 | if ( readbackType == ReadbackType.READ_PIXELS )
269 | fboUtil.deleteRenderbuffers(msaaResolveBuffer);
270 | else
271 | glDeleteTextures(msaaResolveBuffer);
272 | }
273 | if ( depthBuffer != 0 ) fboUtil.deleteRenderbuffers(depthBuffer);
274 | if ( rgbaBuffer != 0 ) {
275 | if ( samples <= 1 && readbackType == ReadbackType.GET_TEX_IMAGE )
276 | glDeleteTextures(rgbaBuffer);
277 | else
278 | fboUtil.deleteRenderbuffers(rgbaBuffer);
279 | }
280 | }
281 |
282 | public void destroy() {
283 | destroyObjects();
284 |
285 | if ( msaaResolveFBO != 0 )
286 | fboUtil.deleteFramebuffers(msaaResolveFBO);
287 | fboUtil.deleteFramebuffers(renderFBO);
288 | }
289 |
290 | }
--------------------------------------------------------------------------------
/src/org/lwjgl/util/stream/RenderStreamPBOAMD.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002-2012 LWJGL Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * * Neither the name of 'LWJGL' nor the names of
17 | * its contributors may be used to endorse or promote products derived
18 | * from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 | package org.lwjgl.util.stream;
33 |
34 | import org.lwjgl.BufferUtils;
35 | import org.lwjgl.MemoryUtil;
36 | import org.lwjgl.opengl.ContextCapabilities;
37 | import org.lwjgl.opengl.GLSync;
38 | import org.lwjgl.util.stream.StreamUtil.PageSizeProvider;
39 | import org.lwjgl.util.stream.StreamUtil.RenderStreamFactory;
40 |
41 | import java.nio.ByteBuffer;
42 | import java.nio.ByteOrder;
43 |
44 | import static org.lwjgl.opengl.AMDPinnedMemory.*;
45 | import static org.lwjgl.opengl.GL15.*;
46 | import static org.lwjgl.opengl.GL32.*;
47 |
48 | /** Optimized StreamPBOReader for AMD GPUs: Asynchronous ReadPixels to AMD_pinned_memory buffers. */
49 | final class RenderStreamPBOAMD extends RenderStreamPBO {
50 |
51 | public static final RenderStreamFactory FACTORY = new RenderStreamFactory("AMD_pinned_memory") {
52 | public boolean isSupported(final ContextCapabilities caps) {
53 | return TextureStreamPBODefault.FACTORY.isSupported(caps) && caps.GL_AMD_pinned_memory && (caps.OpenGL32 || caps.GL_ARB_sync);
54 | }
55 |
56 | public RenderStream create(final StreamHandler handler, final int samples, final int transfersToBuffer) {
57 | return new RenderStreamPBOAMD(handler, samples, transfersToBuffer);
58 | }
59 | };
60 |
61 | private final GLSync[] fences;
62 |
63 | RenderStreamPBOAMD(final StreamHandler handler, final int samples, final int transfersToBuffer) {
64 | super(handler, samples, transfersToBuffer, ReadbackType.READ_PIXELS);
65 |
66 | fences = new GLSync[this.transfersToBuffer];
67 | }
68 |
69 | protected void resizeBuffers(final int height, final int stride) {
70 | final int renderBytes = height * stride;
71 |
72 | for ( int i = 0; i < pbos.length; i++ ) {
73 | pbos[i] = glGenBuffers();
74 |
75 | glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, pbos[i]);
76 |
77 | // Pre-allocate page-aligned pinned buffers
78 | final int PAGE_SIZE = PageSizeProvider.PAGE_SIZE;
79 |
80 | final ByteBuffer buffer = BufferUtils.createByteBuffer(renderBytes + PAGE_SIZE);
81 | final int pageOffset = (int)(MemoryUtil.getAddress(buffer) % PAGE_SIZE);
82 | buffer.position(PAGE_SIZE - pageOffset); // Aligns to page
83 | buffer.limit(buffer.capacity() - pageOffset); // Caps remaining() to renderBytes
84 |
85 | pinnedBuffers[i] = buffer.slice().order(ByteOrder.nativeOrder());
86 | glBufferData(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, pinnedBuffers[i], GL_STREAM_READ);
87 | }
88 |
89 | glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0);
90 | }
91 |
92 | protected void readBack(final int index) {
93 | super.readBack(index);
94 |
95 | // Insert a fence after ReadPixels
96 | fences[index] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
97 | }
98 |
99 | protected void pinBuffer(final int index) {
100 | if ( fences[index] != null ) // Wait for ReadPixels on the PBO to complete
101 | StreamUtil.waitOnFence(fences, index);
102 | }
103 |
104 | protected void copyFrames(final int src, final int trg) {
105 | StreamUtil.waitOnFence(fences, src);
106 |
107 | final ByteBuffer srcBuffer = pinnedBuffers[src];
108 | final ByteBuffer trgBuffer = pinnedBuffers[trg];
109 |
110 | trgBuffer.put(srcBuffer);
111 |
112 | trgBuffer.flip();
113 | srcBuffer.flip();
114 | }
115 |
116 | protected void postProcess(final int index) {
117 | }
118 |
119 | protected void destroyObjects() {
120 | for ( int i = 0; i < fences.length; i++ ) {
121 | if ( fences[i] != null )
122 | StreamUtil.waitOnFence(fences, i);
123 | }
124 |
125 | super.destroyObjects();
126 | }
127 |
128 | }
--------------------------------------------------------------------------------
/src/org/lwjgl/util/stream/RenderStreamPBOCopy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002-2012 LWJGL Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * * Neither the name of 'LWJGL' nor the names of
17 | * its contributors may be used to endorse or promote products derived
18 | * from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 | package org.lwjgl.util.stream;
33 |
34 | import org.lwjgl.opengl.ContextCapabilities;
35 | import org.lwjgl.util.stream.StreamUtil.RenderStreamFactory;
36 |
37 | import static org.lwjgl.opengl.GL15.*;
38 | import static org.lwjgl.opengl.GL21.*;
39 | import static org.lwjgl.opengl.GL31.*;
40 |
41 | /** Default StreamPBOReader implementation: Asynchronous ReadPixels to PBOs */
42 | final class RenderStreamPBOCopy extends RenderStreamPBO {
43 |
44 | public static final RenderStreamFactory FACTORY = new RenderStreamFactory("ARB_copy_buffer") {
45 | public boolean isSupported(final ContextCapabilities caps) {
46 | return RenderStreamPBODefault.FACTORY.isSupported(caps)
47 | && caps.GL_ARB_copy_buffer
48 | && caps.GL_NV_gpu_program5 // Nvidia only
49 | && (caps.OpenGL40 || caps.GL_ARB_tessellation_shader) // Fermi+
50 | ;
51 | }
52 |
53 | public RenderStream create(final StreamHandler handler, final int samples, final int transfersToBuffer) {
54 | return new RenderStreamPBOCopy(handler, samples, transfersToBuffer, ReadbackType.GET_TEX_IMAGE);
55 | }
56 | };
57 |
58 | private int devicePBO;
59 |
60 | RenderStreamPBOCopy(final StreamHandler handler, final int samples, final int transfersToBuffer, final ReadbackType readbackType) {
61 | super(handler, samples, transfersToBuffer, readbackType);
62 | }
63 |
64 | protected void resizeBuffers(final int height, final int stride) {
65 | super.resizeBuffers(height, stride);
66 |
67 | devicePBO = glGenBuffers();
68 |
69 | glBindBuffer(GL_PIXEL_PACK_BUFFER, devicePBO);
70 | glBufferData(GL_PIXEL_PACK_BUFFER, height * stride, GL_STREAM_COPY); // Should allocate device memory
71 | glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
72 | }
73 |
74 | protected void readBack(final int index) {
75 | glBindBuffer(GL_PIXEL_PACK_BUFFER, devicePBO);
76 |
77 | super.readBack(index);
78 |
79 | glBindBuffer(GL_COPY_WRITE_BUFFER, pbos[index]);
80 |
81 | glCopyBufferSubData(GL_PIXEL_PACK_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, height * stride);
82 |
83 | glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
84 | glBindBuffer(GL_COPY_READ_BUFFER, 0);
85 | }
86 |
87 | protected void pinBuffer(final int index) {
88 | glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[index]);
89 |
90 | // We don't need to manually synchronized here, MapBuffer will block until ReadPixels above has finished.
91 | // The buffer will be unmapped in waitForProcessingToComplete
92 | pinnedBuffers[index] = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY, height * stride, pinnedBuffers[index]);
93 |
94 | glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
95 | }
96 |
97 | protected void copyFrames(final int src, final int trg) {
98 | glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[src]);
99 | glBindBuffer(GL_COPY_WRITE_BUFFER, pbos[trg]);
100 |
101 | glCopyBufferSubData(GL_PIXEL_PACK_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, height * stride);
102 |
103 | glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
104 | glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
105 | }
106 |
107 | protected void postProcess(final int index) {
108 | glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
109 | }
110 |
111 | protected void destroyObjects() {
112 | glDeleteBuffers(devicePBO);
113 | super.destroyObjects();
114 | }
115 | }
--------------------------------------------------------------------------------
/src/org/lwjgl/util/stream/RenderStreamPBODefault.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002-2012 LWJGL Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * * Neither the name of 'LWJGL' nor the names of
17 | * its contributors may be used to endorse or promote products derived
18 | * from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 | package org.lwjgl.util.stream;
33 |
34 | import org.lwjgl.opengl.ContextCapabilities;
35 | import org.lwjgl.opengl.GLContext;
36 | import org.lwjgl.util.stream.StreamUtil.RenderStreamFactory;
37 |
38 | import static org.lwjgl.opengl.GL15.*;
39 | import static org.lwjgl.opengl.GL21.*;
40 | import static org.lwjgl.opengl.GL31.*;
41 |
42 | /** Default StreamPBOReader implementation: Asynchronous ReadPixels to PBOs */
43 | final class RenderStreamPBODefault extends RenderStreamPBO {
44 |
45 | public static final RenderStreamFactory FACTORY = new RenderStreamFactory("Asynchronous PBO") {
46 | public boolean isSupported(final ContextCapabilities caps) {
47 | return caps.OpenGL21 || caps.GL_ARB_pixel_buffer_object || caps.GL_EXT_pixel_buffer_object;
48 | }
49 |
50 | public RenderStream create(final StreamHandler handler, final int samples, final int transfersToBuffer) {
51 | final ContextCapabilities caps = GLContext.getCapabilities();
52 |
53 | return new RenderStreamPBODefault(
54 | handler, samples, transfersToBuffer,
55 | // Detect NVIDIA and use GetTexImage instead of ReadPixels
56 | StreamUtil.isNVIDIA(caps) ? ReadbackType.GET_TEX_IMAGE : ReadbackType.READ_PIXELS
57 | );
58 | }
59 | };
60 |
61 | private final boolean USE_COPY_BUFFER_SUB_DATA;
62 |
63 | RenderStreamPBODefault(final StreamHandler handler, final int samples, final int transfersToBuffer, final ReadbackType readbackType) {
64 | super(handler, samples, transfersToBuffer, readbackType);
65 |
66 | final ContextCapabilities caps = GLContext.getCapabilities();
67 |
68 | USE_COPY_BUFFER_SUB_DATA = (caps.OpenGL31 || caps.GL_ARB_copy_buffer) &&
69 | // Disable on ATI/AMD GPUs: ARB_copy_buffer is unoptimized on current
70 | // drivers and kills performance. TODO: Fix?
71 | !StreamUtil.isAMD(caps);
72 | }
73 |
74 | protected void pinBuffer(final int index) {
75 | glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[index]);
76 |
77 | // We don't need to manually synchronized here, MapBuffer will block until ReadPixels above has finished.
78 | // The buffer will be unmapped in waitForProcessingToComplete
79 | pinnedBuffers[index] = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY, height * stride, pinnedBuffers[index]);
80 |
81 | glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
82 | }
83 |
84 | protected void copyFrames(final int src, final int trg) {
85 | if ( USE_COPY_BUFFER_SUB_DATA ) {
86 | glBindBuffer(GL_COPY_WRITE_BUFFER, pbos[trg]);
87 | glCopyBufferSubData(GL_PIXEL_PACK_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, height * stride);
88 | glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
89 | } else {
90 | pinnedBuffers[src] = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY, height * stride, pinnedBuffers[src]);
91 |
92 | glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[trg]);
93 | glBufferSubData(GL_PIXEL_PACK_BUFFER, 0, pinnedBuffers[src]);
94 |
95 | glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[src]);
96 | glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
97 | }
98 | }
99 |
100 | protected void postProcess(final int index) {
101 | glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
102 | }
103 |
104 | }
--------------------------------------------------------------------------------
/src/org/lwjgl/util/stream/StreamBuffered.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002-2012 LWJGL Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * * Neither the name of 'LWJGL' nor the names of
17 | * its contributors may be used to endorse or promote products derived
18 | * from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 | package org.lwjgl.util.stream;
33 |
34 | import java.nio.ByteBuffer;
35 | import java.util.BitSet;
36 | import java.util.concurrent.Semaphore;
37 |
38 | /** Base functionality for buffered transfers. */
39 | abstract class StreamBuffered {
40 |
41 | protected final StreamHandler handler;
42 |
43 | // Low: Less memory usage, less concurrency, less transfers behind
44 | // High: More memory usages, more concurrency, more transfers behind
45 | protected final int transfersToBuffer; // 3 provides optimal concurrency in most cases
46 |
47 | protected final ByteBuffer[] pinnedBuffers;
48 | protected final Semaphore[] semaphores; // Required for synchronization with the processing thread
49 |
50 | /**
51 | * A flag per pinned buffer that indicates if it's currently being
52 | * processed by the handler.
53 | */
54 | protected final BitSet processingState;
55 |
56 | protected int width;
57 | protected int height;
58 | protected int stride;
59 |
60 | protected long bufferIndex;
61 |
62 | protected StreamBuffered(final StreamHandler handler, final int transfersToBuffer) {
63 | this.handler = handler;
64 | this.transfersToBuffer = transfersToBuffer;
65 |
66 | pinnedBuffers = new ByteBuffer[transfersToBuffer];
67 | semaphores = new Semaphore[transfersToBuffer];
68 | for ( int i = 0; i < semaphores.length; i++ )
69 | semaphores[i] = new Semaphore(1, false);
70 |
71 | processingState = new BitSet(transfersToBuffer);
72 | }
73 |
74 | protected void waitForProcessingToComplete(final int index) {
75 | final Semaphore s = semaphores[index];
76 | // Early-out: start-up or handler has finished processing
77 | if ( s.availablePermits() == 0 ) {
78 | // This will block until handler has finished processing
79 | s.acquireUninterruptibly();
80 | // Give the permit back
81 | s.release();
82 | }
83 |
84 | postProcess(index);
85 | processingState.set(index, false);
86 | }
87 |
88 | protected abstract void postProcess(int index);
89 |
90 | }
--------------------------------------------------------------------------------
/src/org/lwjgl/util/stream/StreamBufferedPBO.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002-2012 LWJGL Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * * Neither the name of 'LWJGL' nor the names of
17 | * its contributors may be used to endorse or promote products derived
18 | * from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 | package org.lwjgl.util.stream;
33 |
34 | import static org.lwjgl.opengl.GL15.*;
35 |
36 | /** Base functionality for streaming PBO transfers. */
37 | abstract class StreamBufferedPBO extends StreamBuffered {
38 |
39 | protected final int[] pbos;
40 |
41 | protected StreamBufferedPBO(final StreamHandler handler, final int transfersToBuffer) {
42 | super(handler, transfersToBuffer);
43 |
44 | pbos = new int[transfersToBuffer];
45 | }
46 |
47 | protected void resizeBuffers(final int height, final int stride, final int pboTarget, final int pboUsage) {
48 | final int renderBytes = height * stride;
49 |
50 | for ( int i = 0; i < pbos.length; i++ ) {
51 | pbos[i] = glGenBuffers();
52 |
53 | glBindBuffer(pboTarget, pbos[i]);
54 | glBufferData(pboTarget, renderBytes, pboUsage);
55 |
56 | pinnedBuffers[i] = null;
57 | }
58 |
59 | glBindBuffer(pboTarget, 0);
60 | }
61 |
62 | }
--------------------------------------------------------------------------------
/src/org/lwjgl/util/stream/StreamHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002-2012 LWJGL Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * * Neither the name of 'LWJGL' nor the names of
17 | * its contributors may be used to endorse or promote products derived
18 | * from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 | package org.lwjgl.util.stream;
33 |
34 | import java.nio.ByteBuffer;
35 | import java.util.concurrent.Semaphore;
36 |
37 | /** @author Spasi */
38 | public interface StreamHandler {
39 |
40 | int getWidth();
41 |
42 | int getHeight();
43 |
44 | void process(final int width, final int height, ByteBuffer data, final int stride, Semaphore signal);
45 |
46 | }
--------------------------------------------------------------------------------
/src/org/lwjgl/util/stream/StreamUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002-2012 LWJGL Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * * Neither the name of 'LWJGL' nor the names of
17 | * its contributors may be used to endorse or promote products derived
18 | * from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 | package org.lwjgl.util.stream;
33 |
34 | import org.lwjgl.opengl.ContextCapabilities;
35 | import org.lwjgl.opengl.GLContext;
36 | import org.lwjgl.opengl.GLSync;
37 |
38 | import java.lang.reflect.Field;
39 | import java.lang.reflect.Modifier;
40 | import java.nio.ByteBuffer;
41 | import java.util.ArrayList;
42 | import java.util.List;
43 |
44 | import sun.misc.Unsafe;
45 |
46 | import static org.lwjgl.opengl.EXTFramebufferBlit.*;
47 | import static org.lwjgl.opengl.EXTFramebufferMultisample.*;
48 | import static org.lwjgl.opengl.EXTFramebufferObject.*;
49 | import static org.lwjgl.opengl.GL11.*;
50 | import static org.lwjgl.opengl.GL12.*;
51 | import static org.lwjgl.opengl.GL30.*;
52 | import static org.lwjgl.opengl.GL32.*;
53 |
54 | /** @author Spasi */
55 | public final class StreamUtil {
56 |
57 | private static final int TEX_ROW_ALIGNMENT = 16 * 4; // 16 pixels
58 |
59 | private StreamUtil() {
60 | }
61 |
62 | static int createRenderTexture(final int width, final int height) {
63 | return createRenderTexture(width, height, GL_NEAREST);
64 | }
65 |
66 | static int createRenderTexture(final int width, final int height, final int filter) {
67 | final int texID = glGenTextures();
68 |
69 | glBindTexture(GL_TEXTURE_2D, texID);
70 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
71 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
72 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, (ByteBuffer)null);
73 | glBindTexture(GL_TEXTURE_2D, 0);
74 |
75 | return texID;
76 | }
77 |
78 | static int createRenderBuffer(final FBOUtil fboUtil, final int width, final int height, final int internalformat) {
79 | return createRenderBuffer(fboUtil, width, height, 1, internalformat);
80 | }
81 |
82 | static int createRenderBuffer(final FBOUtil fboUtil, final int width, final int height, final int samples, final int internalformat) {
83 | final int bufferID = fboUtil.genRenderbuffers();
84 |
85 | fboUtil.bindRenderbuffer(GL_RENDERBUFFER, bufferID);
86 | if ( samples <= 1 )
87 | fboUtil.renderbufferStorage(GL_RENDERBUFFER, internalformat, width, height);
88 | else
89 | fboUtil.renderbufferStorageMultisample(GL_RENDERBUFFER, samples, internalformat, width, height);
90 | fboUtil.bindRenderbuffer(GL_RENDERBUFFER, 0);
91 |
92 | return bufferID;
93 | }
94 |
95 | static void waitOnFence(final GLSync[] fences, final int index) {
96 | glWaitSync(fences[index], 0, GL_TIMEOUT_IGNORED);
97 | glDeleteSync(fences[index]);
98 | fences[index] = null;
99 | }
100 |
101 | static boolean isAMD(final ContextCapabilities caps) {
102 | return caps.GL_ATI_fragment_shader || caps.GL_ATI_texture_compression_3dc || caps.GL_AMD_debug_output;
103 | }
104 |
105 | static boolean isNVIDIA(final ContextCapabilities caps) {
106 | return caps.GL_NV_vertex_program || caps.GL_NV_register_combiners || caps.GL_NV_gpu_program4;
107 | }
108 |
109 | static int getStride(final int width) {
110 | // Force a packed format on AMD. Their drivers show unstable
111 | // performance if we mess with (UN)PACK_ROW_LENGTH.
112 | return isAMD(GLContext.getCapabilities()) ?
113 | width * 4 :
114 | getStride(width, TEX_ROW_ALIGNMENT);
115 | }
116 |
117 | /**
118 | * Aligns the row stride. This is beneficial for all the memcpy's we're doing (and also required for INTEL_map_texture).
119 | *
120 | * @param width the row width in pixels
121 | * @param aligment the row aligment in bytes. Must be a power-of-two value.
122 | *
123 | * @return the aligned row stride
124 | */
125 | static int getStride(final int width, final int aligment) {
126 | int stride = width * 4;
127 |
128 | if ( (stride & (aligment - 1)) != 0 )
129 | stride += aligment - (stride & (aligment - 1));
130 |
131 | return stride;
132 | }
133 |
134 | private static void checkCapabilities(final ContextCapabilities caps) {
135 | if ( !caps.OpenGL15 )
136 | throw new UnsupportedOperationException("Support for OpenGL 1.5 or higher is required.");
137 |
138 | if ( !(caps.OpenGL20 || caps.GL_ARB_texture_non_power_of_two) )
139 | throw new UnsupportedOperationException("Support for npot textures is required.");
140 |
141 | if ( !(caps.OpenGL30 || caps.GL_ARB_framebuffer_object || caps.GL_EXT_framebuffer_object) )
142 | throw new UnsupportedOperationException("Framebuffer object support is required.");
143 | }
144 |
145 | public static RenderStreamFactory getRenderStreamImplementation() {
146 | final List list = getRenderStreamImplementations();
147 |
148 | if ( list.isEmpty() )
149 | throw new UnsupportedOperationException("A supported TextureStream implementation could not be found.");
150 |
151 | return list.get(0);
152 | }
153 |
154 | public static List getRenderStreamImplementations() {
155 | final ContextCapabilities caps = GLContext.getCapabilities();
156 |
157 | checkCapabilities(caps);
158 |
159 | final List list = new ArrayList();
160 |
161 | addIfSupported(caps, list, RenderStreamPBOAMD.FACTORY);
162 | addIfSupported(caps, list, RenderStreamPBOCopy.FACTORY);
163 | addIfSupported(caps, list, RenderStreamINTEL.FACTORY);
164 | addIfSupported(caps, list, RenderStreamPBODefault.FACTORY);
165 |
166 | return list;
167 | }
168 |
169 | public static TextureStreamFactory getTextureStreamImplementation() {
170 | final List list = getTextureStreamImplementations();
171 |
172 | if ( list.isEmpty() )
173 | throw new UnsupportedOperationException("A supported TextureStream implementation could not be found.");
174 |
175 | return list.get(0);
176 | }
177 |
178 | public static List getTextureStreamImplementations() {
179 | final ContextCapabilities caps = GLContext.getCapabilities();
180 |
181 | checkCapabilities(caps);
182 |
183 | final List list = new ArrayList();
184 |
185 | addIfSupported(caps, list, TextureStreamINTEL.FACTORY);
186 | addIfSupported(caps, list, TextureStreamPBORange.FACTORY);
187 | addIfSupported(caps, list, TextureStreamPBODefault.FACTORY);
188 |
189 | return list;
190 | }
191 |
192 | private static > void addIfSupported(final ContextCapabilities caps, final List list, final T factory) {
193 | if ( factory.isSupported(caps) )
194 | list.add(factory);
195 | }
196 |
197 | public abstract static class StreamFactory {
198 |
199 | private final String description;
200 |
201 | protected StreamFactory(final String description) {
202 | this.description = description;
203 | }
204 |
205 | public String getDescription() {
206 | return description;
207 | }
208 |
209 | public abstract boolean isSupported(ContextCapabilities caps);
210 |
211 | public String toString() {
212 | return description;
213 | }
214 |
215 | }
216 |
217 | public abstract static class RenderStreamFactory extends StreamFactory {
218 |
219 | protected RenderStreamFactory(final String description) {
220 | super(description);
221 | }
222 |
223 | public abstract RenderStream create(StreamHandler handler, int samples, int transfersToBuffer);
224 |
225 | }
226 |
227 | public abstract static class TextureStreamFactory extends StreamFactory {
228 |
229 | protected TextureStreamFactory(final String description) {
230 | super(description);
231 | }
232 |
233 | public abstract TextureStream create(StreamHandler handler, int transfersToBuffer);
234 |
235 | }
236 |
237 | static int checkSamples(final int samples, final ContextCapabilities caps) {
238 | if ( samples <= 1 )
239 | return samples;
240 |
241 | if ( !(caps.OpenGL30 || (caps.GL_EXT_framebuffer_multisample && caps.GL_EXT_framebuffer_blit)) )
242 | throw new UnsupportedOperationException("Multisampled rendering on framebuffer objects is not supported.");
243 |
244 | return Math.min(samples, glGetInteger(GL_MAX_SAMPLES));
245 | }
246 |
247 | static final class PageSizeProvider {
248 |
249 | static final int PAGE_SIZE;
250 |
251 | static {
252 | int pageSize = 4096; // Assume 4kb if Unsafe is not available
253 |
254 | try {
255 | pageSize = getUnsafeInstance().pageSize();
256 | } catch (Exception e) {
257 | // ignore
258 | }
259 |
260 | PAGE_SIZE = pageSize;
261 | }
262 |
263 | private static Unsafe getUnsafeInstance() {
264 | final Field[] fields = Unsafe.class.getDeclaredFields();
265 |
266 | /*
267 | Different runtimes use different names for the Unsafe singleton,
268 | so we cannot use .getDeclaredField and we scan instead. For example:
269 |
270 | Oracle: theUnsafe
271 | PERC : m_unsafe_instance
272 | Android: THE_ONE
273 | */
274 | for ( Field field : fields ) {
275 | if ( !field.getType().equals(Unsafe.class) )
276 | continue;
277 |
278 | final int modifiers = field.getModifiers();
279 | if ( !(Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) )
280 | continue;
281 |
282 | field.setAccessible(true);
283 | try {
284 | return (Unsafe)field.get(null);
285 | } catch (IllegalAccessException e) {
286 | // ignore
287 | }
288 | break;
289 | }
290 |
291 | throw new UnsupportedOperationException();
292 | }
293 | }
294 |
295 | interface FBOUtil {
296 |
297 | int genFramebuffers();
298 |
299 | void bindFramebuffer(int target, int framebuffer);
300 |
301 | void framebufferTexture2D(int target, int attachment, int textarget, int texture, int level);
302 |
303 | void framebufferRenderbuffer(int target, int attachment, int renderbuffertarget, int renderbuffer);
304 |
305 | void deleteFramebuffers(int framebuffer);
306 |
307 | int genRenderbuffers();
308 |
309 | void bindRenderbuffer(int target, int renderbuffer);
310 |
311 | void renderbufferStorage(int target, int internalformat, int width, int height);
312 |
313 | void renderbufferStorageMultisample(int target, int samples, int internalformat, int width, int height);
314 |
315 | void blitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter);
316 |
317 | void deleteRenderbuffers(int renderbuffer);
318 |
319 | }
320 |
321 | static FBOUtil getFBOUtil(final ContextCapabilities caps) {
322 | if ( caps.OpenGL30 || caps.GL_ARB_framebuffer_object )
323 | return new FBOUtil() {
324 | public int genFramebuffers() {
325 | return glGenFramebuffers();
326 | }
327 |
328 | public void bindFramebuffer(int target, int framebuffer) {
329 | glBindFramebuffer(target, framebuffer);
330 | }
331 |
332 | public void framebufferTexture2D(int target, int attachment, int textarget, int texture, int level) {
333 | glFramebufferTexture2D(target, attachment, textarget, texture, level);
334 | }
335 |
336 | public void framebufferRenderbuffer(int target, int attachment, int renderbuffertarget, int renderbuffer) {
337 | glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
338 | }
339 |
340 | public void deleteFramebuffers(int framebuffer) {
341 | glDeleteFramebuffers(framebuffer);
342 | }
343 |
344 | public int genRenderbuffers() {
345 | return glGenRenderbuffers();
346 | }
347 |
348 | public void bindRenderbuffer(int target, int renderbuffer) {
349 | glBindRenderbuffer(target, renderbuffer);
350 | }
351 |
352 | public void renderbufferStorage(int target, int internalformat, int width, int height) {
353 | glRenderbufferStorage(target, internalformat, width, height);
354 | }
355 |
356 | public void renderbufferStorageMultisample(int target, int samples, int internalformat, int width, int height) {
357 | glRenderbufferStorageMultisample(target, samples, internalformat, width, height);
358 | }
359 |
360 | public void blitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) {
361 | glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
362 | }
363 |
364 | public void deleteRenderbuffers(int renderbuffer) {
365 | glDeleteRenderbuffers(renderbuffer);
366 | }
367 | };
368 | else if ( caps.GL_EXT_framebuffer_object )
369 | return new FBOUtil() {
370 | public int genFramebuffers() {
371 | return glGenFramebuffersEXT();
372 | }
373 |
374 | public void bindFramebuffer(int target, int framebuffer) {
375 | glBindFramebufferEXT(target, framebuffer);
376 | }
377 |
378 | public void framebufferTexture2D(int target, int attachment, int textarget, int texture, int level) {
379 | glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
380 | }
381 |
382 | public void framebufferRenderbuffer(int target, int attachment, int renderbuffertarget, int renderbuffer) {
383 | glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, renderbuffer);
384 | }
385 |
386 | public void deleteFramebuffers(int framebuffer) {
387 | glDeleteFramebuffersEXT(framebuffer);
388 | }
389 |
390 | public int genRenderbuffers() {
391 | return glGenRenderbuffersEXT();
392 | }
393 |
394 | public void bindRenderbuffer(int target, int renderbuffer) {
395 | glBindRenderbufferEXT(target, renderbuffer);
396 | }
397 |
398 | public void renderbufferStorage(int target, int internalformat, int width, int height) {
399 | glRenderbufferStorageEXT(target, internalformat, width, height);
400 | }
401 |
402 | public void renderbufferStorageMultisample(int target, int samples, int internalformat, int width, int height) {
403 | glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height);
404 | }
405 |
406 | public void blitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) {
407 | glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
408 | }
409 |
410 | public void deleteRenderbuffers(int renderbuffer) {
411 | glDeleteRenderbuffersEXT(renderbuffer);
412 | }
413 | };
414 | else
415 | throw new UnsupportedOperationException("Framebuffer object is not available.");
416 | }
417 |
418 | }
--------------------------------------------------------------------------------
/src/org/lwjgl/util/stream/TextureStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002-2012 LWJGL Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * * Neither the name of 'LWJGL' nor the names of
17 | * its contributors may be used to endorse or promote products derived
18 | * from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 | package org.lwjgl.util.stream;
33 |
34 | /** @author Spasi */
35 | public interface TextureStream {
36 |
37 | StreamHandler getHandler();
38 |
39 | int getWidth();
40 |
41 | int getHeight();
42 |
43 | void snapshot();
44 |
45 | void tick();
46 |
47 | void bind();
48 |
49 | void destroy();
50 |
51 | }
--------------------------------------------------------------------------------
/src/org/lwjgl/util/stream/TextureStreamINTEL.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002-2012 LWJGL Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * * Neither the name of 'LWJGL' nor the names of
17 | * its contributors may be used to endorse or promote products derived
18 | * from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 | package org.lwjgl.util.stream;
33 |
34 | import org.lwjgl.BufferUtils;
35 | import org.lwjgl.opengl.ContextCapabilities;
36 | import org.lwjgl.opengl.GLContext;
37 | import org.lwjgl.util.stream.StreamUtil.TextureStreamFactory;
38 |
39 | import java.nio.ByteBuffer;
40 | import java.nio.IntBuffer;
41 |
42 | import static org.lwjgl.opengl.GL11.*;
43 | import static org.lwjgl.opengl.GL12.*;
44 | import static org.lwjgl.opengl.GL30.*;
45 | import static org.lwjgl.opengl.INTELMapTexture.*;
46 |
47 | /**
48 | * Optimized StreamPBOReader for Intel IGPs:
49 | *
50 | * - We render to a standard FBO.
51 | * - We asynchronously blit to another FBO with INTEL_map_texture attachments (linear layout).
52 | * - We synchronously map the linear textures.
53 | *
54 | */
55 | final class TextureStreamINTEL extends StreamBuffered implements TextureStream {
56 |
57 | public static final TextureStreamFactory FACTORY = new TextureStreamFactory("INTEL_map_texture") {
58 | public boolean isSupported(final ContextCapabilities caps) {
59 | // TODO: We currently require BlitFramebuffer. Relax and implement manually?
60 | return caps.GL_INTEL_map_texture && (caps.OpenGL30 || caps.GL_ARB_framebuffer_object || caps.GL_EXT_framebuffer_blit);
61 | }
62 |
63 | public TextureStream create(final StreamHandler handler, final int transfersToBuffer) {
64 | return new TextureStreamINTEL(handler, transfersToBuffer);
65 | }
66 | };
67 |
68 | private final IntBuffer strideBuffer;
69 | private final IntBuffer layoutBuffer;
70 |
71 | private final StreamUtil.FBOUtil fboUtil;
72 |
73 | private final int texFBO;
74 | private final int bufferFBO;
75 |
76 | private int texID;
77 | private int[] buffers;
78 |
79 | private long currentIndex;
80 |
81 | private boolean resetTexture;
82 |
83 | TextureStreamINTEL(final StreamHandler handler, final int transfersToBuffer) {
84 | super(handler, transfersToBuffer);
85 |
86 | this.strideBuffer = BufferUtils.createIntBuffer(1);
87 | this.layoutBuffer = BufferUtils.createIntBuffer(1);
88 |
89 | fboUtil = StreamUtil.getFBOUtil(GLContext.getCapabilities());
90 |
91 | texFBO = fboUtil.genFramebuffers();
92 | bufferFBO = fboUtil.genFramebuffers();
93 |
94 | buffers = new int[transfersToBuffer];
95 | }
96 |
97 | public StreamHandler getHandler() {
98 | return handler;
99 | }
100 |
101 | public int getWidth() {
102 | return width;
103 | }
104 |
105 | public int getHeight() {
106 | return height;
107 | }
108 |
109 | private void resize(final int width, final int height) {
110 | if ( width < 0 || height < 0 )
111 | throw new IllegalArgumentException("Invalid dimensions: " + width + " x " + height);
112 |
113 | destroyObjects();
114 |
115 | this.width = width;
116 | this.height = height;
117 |
118 | this.stride = StreamUtil.getStride(width);
119 |
120 | if ( width == 0 || height == 0 )
121 | return;
122 |
123 | bufferIndex = 0;
124 | currentIndex = 0;
125 |
126 | resetTexture = true;
127 |
128 | texID = StreamUtil.createRenderTexture(width, height, GL_LINEAR);
129 |
130 | fboUtil.bindFramebuffer(GL_DRAW_FRAMEBUFFER, texFBO);
131 | fboUtil.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texID, 0);
132 | fboUtil.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
133 |
134 | for ( int i = 0; i < buffers.length; i++ )
135 | buffers[i] = genLayoutLinearTexture(width, height);
136 |
137 | glBindTexture(GL_TEXTURE_2D, 0);
138 | }
139 |
140 | private static int genLayoutLinearTexture(final int width, final int height) {
141 | final int texID = glGenTextures();
142 |
143 | glBindTexture(GL_TEXTURE_2D, texID);
144 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
145 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
146 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MEMORY_LAYOUT_INTEL, GL_LAYOUT_LINEAR_CPU_CACHED_INTEL);
147 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, (ByteBuffer)null);
148 |
149 | return texID;
150 | }
151 |
152 | public void snapshot() {
153 | if ( width != handler.getWidth() || height != handler.getHeight() )
154 | resize(handler.getWidth(), handler.getHeight());
155 |
156 | if ( width == 0 || height == 0 )
157 | return;
158 |
159 | final int trgPBO = (int)(bufferIndex % transfersToBuffer);
160 |
161 | // Back-pressure. Make sure we never buffer more than frames ahead.
162 |
163 | if ( processingState.get(trgPBO) )
164 | syncCopy(trgPBO);
165 |
166 | pinnedBuffers[trgPBO] = glMapTexture2DINTEL(buffers[trgPBO], 0, height * stride, GL_MAP_WRITE_BIT, strideBuffer, layoutBuffer, pinnedBuffers[trgPBO]);
167 |
168 | // Send the buffer for processing
169 |
170 | processingState.set(trgPBO, true);
171 | semaphores[trgPBO].acquireUninterruptibly();
172 |
173 | handler.process(
174 | width, height,
175 | pinnedBuffers[trgPBO],
176 | stride,
177 | semaphores[trgPBO]
178 | );
179 |
180 | bufferIndex++;
181 |
182 | if ( resetTexture ) {
183 | syncCopy(trgPBO);
184 | resetTexture = true;
185 | }
186 | }
187 |
188 | public void tick() {
189 | final int srcPBO = (int)(currentIndex % transfersToBuffer);
190 | if ( !processingState.get(srcPBO) )
191 | return;
192 |
193 | // Try again next frame
194 | if ( !semaphores[srcPBO].tryAcquire() )
195 | return;
196 |
197 | semaphores[srcPBO].release(); // Give it back
198 |
199 | postProcess(srcPBO);
200 | processingState.set(srcPBO, false);
201 |
202 | copyTexture(srcPBO);
203 | }
204 |
205 | private void syncCopy(final int index) {
206 | waitForProcessingToComplete(index);
207 | copyTexture(index);
208 | }
209 |
210 | private void copyTexture(final int index) {
211 | fboUtil.bindFramebuffer(GL_READ_FRAMEBUFFER, bufferFBO);
212 | fboUtil.bindFramebuffer(GL_DRAW_FRAMEBUFFER, texFBO);
213 |
214 | fboUtil.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, buffers[index], 0);
215 | fboUtil.blitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
216 | fboUtil.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
217 |
218 | fboUtil.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
219 | fboUtil.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
220 |
221 | currentIndex++;
222 | }
223 |
224 | protected void postProcess(final int index) {
225 | glUnmapTexture2DINTEL(buffers[index], 0);
226 | }
227 |
228 | public void bind() {
229 | glBindTexture(GL_TEXTURE_2D, texID);
230 | }
231 |
232 | private void destroyObjects() {
233 | for ( int i = 0; i < semaphores.length; i++ ) {
234 | if ( processingState.get(i) )
235 | waitForProcessingToComplete(i);
236 | }
237 |
238 | for ( int i = 0; i < buffers.length; i++ ) {
239 | glDeleteTextures(buffers[i]);
240 | buffers[i] = 0;
241 | }
242 |
243 | glDeleteTextures(texID);
244 | }
245 |
246 | public void destroy() {
247 | destroyObjects();
248 |
249 | fboUtil.deleteFramebuffers(bufferFBO);
250 | fboUtil.deleteFramebuffers(texFBO);
251 | }
252 |
253 | }
--------------------------------------------------------------------------------
/src/org/lwjgl/util/stream/TextureStreamPBO.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002-2012 LWJGL Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * * Neither the name of 'LWJGL' nor the names of
17 | * its contributors may be used to endorse or promote products derived
18 | * from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 | package org.lwjgl.util.stream;
33 |
34 | import static org.lwjgl.opengl.GL11.*;
35 | import static org.lwjgl.opengl.GL12.*;
36 | import static org.lwjgl.opengl.GL15.*;
37 | import static org.lwjgl.opengl.GL21.*;
38 |
39 | /** Implements streaming PBO updates to an OpenGL texture. */
40 | abstract class TextureStreamPBO extends StreamBufferedPBO implements TextureStream {
41 |
42 | private final int texID;
43 |
44 | private long currentIndex;
45 |
46 | private boolean resetTexture;
47 |
48 | protected TextureStreamPBO(final StreamHandler handler, final int transfersToBuffer) {
49 | super(handler, transfersToBuffer);
50 |
51 | texID = glGenTextures();
52 | glBindTexture(GL_TEXTURE_2D, texID);
53 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
54 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
55 | glBindTexture(GL_TEXTURE_2D, 0);
56 | }
57 |
58 | public StreamHandler getHandler() {
59 | return handler;
60 | }
61 |
62 | public int getWidth() {
63 | return width;
64 | }
65 |
66 | public int getHeight() {
67 | return height;
68 | }
69 |
70 | private void resize(final int width, final int height) {
71 | if ( width < 0 || height < 0 )
72 | throw new IllegalArgumentException("Invalid dimensions: " + width + " x " + height);
73 |
74 | destroyObjects();
75 |
76 | this.width = width;
77 | this.height = height;
78 |
79 | this.stride = StreamUtil.getStride(width);
80 |
81 | if ( width == 0 || height == 0 )
82 | return;
83 |
84 | bufferIndex = 0;
85 | currentIndex = 0;
86 |
87 | resetTexture = true;
88 |
89 | // Setup upload buffers
90 |
91 | resizeBuffers(height, stride);
92 | }
93 |
94 | protected void resizeBuffers(final int height, final int stride) {
95 | super.resizeBuffers(height, stride, GL_PIXEL_UNPACK_BUFFER, GL_STREAM_DRAW);
96 | }
97 |
98 | public void snapshot() {
99 | if ( width != handler.getWidth() || height != handler.getHeight() )
100 | resize(handler.getWidth(), handler.getHeight());
101 |
102 | if ( width == 0 || height == 0 )
103 | return;
104 |
105 | final int trgPBO = (int)(bufferIndex % transfersToBuffer);
106 |
107 | // Back-pressure. Make sure we never buffer more than frames ahead.
108 |
109 | if ( processingState.get(trgPBO) )
110 | syncUpload(trgPBO);
111 |
112 | pinBuffer(trgPBO);
113 |
114 | // Send the buffer for processing
115 |
116 | processingState.set(trgPBO, true);
117 | semaphores[trgPBO].acquireUninterruptibly();
118 |
119 | handler.process(
120 | width, height,
121 | pinnedBuffers[trgPBO],
122 | stride,
123 | semaphores[trgPBO]
124 | );
125 |
126 | bufferIndex++;
127 |
128 | if ( resetTexture ) // Synchronize to show the first frame immediately
129 | syncUpload(trgPBO);
130 | }
131 |
132 | protected abstract void pinBuffer(final int index);
133 |
134 | public void tick() {
135 | final int srcPBO = (int)(currentIndex % transfersToBuffer);
136 | if ( !processingState.get(srcPBO) )
137 | return;
138 |
139 | syncUpload(srcPBO);
140 | }
141 |
142 | private void syncUpload(final int index) {
143 | glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos[index]);
144 | waitForProcessingToComplete(index);
145 |
146 | upload(index);
147 |
148 | glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
149 | }
150 |
151 | private void upload(final int srcPBO) {
152 | // Asynchronously upload current update
153 |
154 | glBindTexture(GL_TEXTURE_2D, texID);
155 | glPixelStorei(GL_UNPACK_ROW_LENGTH, stride >> 2);
156 | if ( resetTexture ) {
157 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
158 | resetTexture = false;
159 | } else
160 | glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
161 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
162 | glBindTexture(GL_TEXTURE_2D, 0);
163 |
164 | postUpload(srcPBO);
165 |
166 | currentIndex++;
167 | }
168 |
169 | protected abstract void postUpload(int index);
170 |
171 | public void bind() {
172 | glBindTexture(GL_TEXTURE_2D, texID);
173 | }
174 |
175 | protected void destroyObjects() {
176 | for ( int i = 0; i < semaphores.length; i++ ) {
177 | if ( processingState.get(i) ) {
178 | glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos[i]);
179 | waitForProcessingToComplete(i);
180 | }
181 | }
182 |
183 | glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
184 |
185 | for ( int i = 0; i < pbos.length; i++ ) {
186 | if ( pbos[i] != 0 )
187 | glDeleteBuffers(pbos[i]);
188 | }
189 | }
190 |
191 | public void destroy() {
192 | destroyObjects();
193 | }
194 |
195 | }
--------------------------------------------------------------------------------
/src/org/lwjgl/util/stream/TextureStreamPBODefault.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002-2012 LWJGL Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * * Neither the name of 'LWJGL' nor the names of
17 | * its contributors may be used to endorse or promote products derived
18 | * from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 | package org.lwjgl.util.stream;
33 |
34 | import org.lwjgl.opengl.ContextCapabilities;
35 | import org.lwjgl.util.stream.StreamUtil.TextureStreamFactory;
36 |
37 | import static org.lwjgl.opengl.GL15.*;
38 | import static org.lwjgl.opengl.GL21.*;
39 |
40 | /** Implements streaming PBO updates to an OpenGL texture. */
41 | public class TextureStreamPBODefault extends TextureStreamPBO {
42 |
43 | public static final TextureStreamFactory FACTORY = new TextureStreamFactory("Asynchronous PBO") {
44 | public boolean isSupported(final ContextCapabilities caps) {
45 | return caps.OpenGL21 || caps.GL_ARB_pixel_buffer_object || caps.GL_EXT_pixel_buffer_object;
46 | }
47 |
48 | public TextureStream create(final StreamHandler handler, final int transfersToBuffer) {
49 | return new TextureStreamPBODefault(handler, transfersToBuffer);
50 | }
51 | };
52 |
53 | public TextureStreamPBODefault(final StreamHandler handler, final int transfersToBuffer) {
54 | super(handler, transfersToBuffer);
55 | }
56 |
57 | protected void postProcess(final int index) {
58 | glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
59 | }
60 |
61 | protected void postUpload(final int index) {
62 | }
63 |
64 | public void pinBuffer(final int index) {
65 | glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos[index]);
66 | glBufferData(GL_PIXEL_UNPACK_BUFFER, height * stride, GL_STREAM_DRAW); // Orphan previous buffer
67 | pinnedBuffers[index] = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY, height * stride, pinnedBuffers[index]);
68 | glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
69 | }
70 |
71 | public void destroy() {
72 | destroyObjects();
73 | }
74 |
75 | }
--------------------------------------------------------------------------------
/src/org/lwjgl/util/stream/TextureStreamPBORange.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2002-2012 LWJGL Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * * Neither the name of 'LWJGL' nor the names of
17 | * its contributors may be used to endorse or promote products derived
18 | * from this software without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 | package org.lwjgl.util.stream;
33 |
34 | import org.lwjgl.opengl.ContextCapabilities;
35 | import org.lwjgl.opengl.GLSync;
36 | import org.lwjgl.util.stream.StreamUtil.TextureStreamFactory;
37 |
38 | import static org.lwjgl.opengl.GL15.*;
39 | import static org.lwjgl.opengl.GL21.*;
40 | import static org.lwjgl.opengl.GL30.*;
41 | import static org.lwjgl.opengl.GL32.*;
42 |
43 | /** Implements streaming PBO updates to an OpenGL texture. */
44 | public class TextureStreamPBORange extends TextureStreamPBO {
45 |
46 | public static final TextureStreamFactory FACTORY = new TextureStreamFactory("ARB_map_buffer_range") {
47 | public boolean isSupported(final ContextCapabilities caps) {
48 | return TextureStreamPBODefault.FACTORY.isSupported(caps) && (caps.OpenGL30 || caps.GL_ARB_map_buffer_range);
49 | }
50 |
51 | public TextureStream create(final StreamHandler handler, final int transfersToBuffer) {
52 | return new TextureStreamPBORange(handler, transfersToBuffer);
53 | }
54 | };
55 |
56 | private final GLSync[] fences;
57 |
58 | public TextureStreamPBORange(final StreamHandler handler, final int transfersToBuffer) {
59 | super(handler, transfersToBuffer);
60 |
61 | fences = new GLSync[this.transfersToBuffer];
62 | }
63 |
64 | protected void postUpload(final int index) {
65 | fences[index] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
66 | }
67 |
68 | protected void postProcess(final int index) {
69 | glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
70 | }
71 |
72 | public void pinBuffer(final int index) {
73 | if ( fences[index] != null ) // Wait for TexSubImage to complete
74 | StreamUtil.waitOnFence(fences, index);
75 |
76 | glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos[index]);
77 | glBufferData(GL_PIXEL_UNPACK_BUFFER, height * stride, GL_STREAM_DRAW); // Orphan previous buffer
78 | pinnedBuffers[index] = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, height * stride, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT, pinnedBuffers[index]);
79 | glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
80 | }
81 |
82 | public void destroy() {
83 | destroyObjects();
84 | }
85 |
86 | }
--------------------------------------------------------------------------------