Vuo 2.4.4
Loading...
Searching...
No Matches
VuoImageRenderer.cc
Go to the documentation of this file.
1
10#include "VuoImageRenderer.h"
11
12
13#include <IOSurface/IOSurface.h>
14
15#include <OpenGL/CGLMacro.h>
17#define glGenVertexArrays glGenVertexArraysAPPLE
18#define glBindVertexArray glBindVertexArrayAPPLE
19#define glDeleteVertexArrays glDeleteVertexArraysAPPLE
21
22extern "C"
23{
24#ifdef VUO_COMPILER
26 "title" : "VuoImageRenderer",
27 "dependencies" : [
28 "VuoImage",
29 "VuoImageColorDepth",
30 "VuoShader",
31 "VuoGlContext",
32 "VuoGlPool",
33 "OpenGL.framework"
34 ]
35 });
36#endif
37}
38
43{
44 GLuint outputFramebuffer;
45
46 GLuint vertexArray;
47 GLuint quadDataBuffer;
48};
53
57static const GLfloat quadData[] = {
58 // Positions
59 -1, -1, 0, 1,
60 1, -1, 0, 1,
61 -1, 1, 0, 1,
62 1, 1, 0, 1,
63
64 // Texture Coordinates
65 0, 0, 0, 0,
66 1, 0, 0, 0,
67 0, 1, 0, 0,
68 1, 1, 0, 0
69};
73static const GLfloat unityMatrix[16] = {
74 1,0,0,0,
75 0,1,0,0,
76 0,0,1,0,
77 0,0,0,1
78};
79
83static bool VuoImageRenderer_initialized = false;
84
88static void VuoImageRenderer_init(void)
89{
90 static dispatch_once_t once = 0;
91 dispatch_once(&once, ^{
93
94 VuoGlContext_perform(^(CGLContextObj cgl_ctx){
97 {
98 VuoImageRendererGlobal.quadDataBuffer = VuoGlPool_use(cgl_ctx, VuoGlPool_ArrayBuffer, sizeof(quadData));
100 glBindBuffer(GL_ARRAY_BUFFER, VuoImageRendererGlobal.quadDataBuffer);
101 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(quadData), quadData);
102 }
104
105 glFlushRenderAPPLE();
106
107 glGenFramebuffers(1, &VuoImageRendererGlobal.outputFramebuffer);
108 });
109 });
110}
111
115extern "C" VuoImage VuoImageRenderer_draw(void *ir, VuoShader shader, unsigned int pixelsWide, unsigned int pixelsHigh, VuoImageColorDepth imageColorDepth)
116{
117 return VuoImageRenderer_render(shader, pixelsWide, pixelsHigh, imageColorDepth);
118}
119
123extern "C" void *VuoImageRenderer_make(void *)
124{
125 return NULL;
126}
127
133VuoImage VuoImageRenderer_render(VuoShader shader, unsigned int pixelsWide, unsigned int pixelsHigh, VuoImageColorDepth imageColorDepth)
134{
135 if (pixelsWide < 1 || pixelsHigh < 1)
136 return NULL;
137
138 GLuint internalFormat;
139 GLuint outputTexture = VuoImageRenderer_draw_internal(shader, pixelsWide, pixelsHigh, imageColorDepth, false, false, 0, &internalFormat);
140 if (!outputTexture)
141 return NULL;
142
143 VuoImage outputImage = VuoImage_make(outputTexture, internalFormat, pixelsWide, pixelsHigh);
144
145 VuoImage firstInputImage = VuoShader_getFirstImage(shader);
146 if (firstInputImage)
147 outputImage->scaleFactor = firstInputImage->scaleFactor;
148
149 return outputImage;
150}
151
157unsigned long int VuoImageRenderer_draw_internal(VuoShader shader, unsigned int pixelsWide, unsigned int pixelsHigh, VuoImageColorDepth imageColorDepth, bool outputToIOSurface, bool outputToGlTextureRectangle, unsigned int outputToSpecificTexture, GLuint *outputInternalFormat)
158{
160
161 __block GLuint outputTexture = 0;
162 __block IOSurfaceID surfID = 0;
163 VuoGlContext_perform(^(CGLContextObj cgl_ctx){
164 glViewport(0, 0, pixelsWide, pixelsHigh);
165
166 // Create a new GL Texture Object.
167 bool shaderOpaque = VuoShader_isOpaque(shader);
168 GLenum textureFormat = shaderOpaque ? GL_BGR : GL_BGRA;
169 GLuint textureTarget = (outputToIOSurface || outputToGlTextureRectangle) ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D;
170 GLuint textureTargetInternalFormat = VuoImageColorDepth_getGlInternalFormat(textureFormat, imageColorDepth);
171 if (outputInternalFormat)
172 *outputInternalFormat = textureTargetInternalFormat;
173
174 VuoIoSurface ioSurface = NULL;
175 if (outputToIOSurface)
177 ioSurface = VuoIoSurfacePool_use(cgl_ctx, pixelsWide, pixelsHigh, &outputTexture);
178 else if (outputToSpecificTexture)
179 outputTexture = outputToSpecificTexture;
180 else
181 outputTexture = VuoGlTexturePool_use(cgl_ctx, VuoGlTexturePool_Allocate, outputToGlTextureRectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D, textureTargetInternalFormat, pixelsWide, pixelsHigh, textureFormat, NULL);
182
183 if (!outputTexture)
184 return;
185
186 glBindFramebuffer(GL_FRAMEBUFFER, VuoImageRendererGlobal.outputFramebuffer);
187// VLog("glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, %s, %d, 0);", VuoGl_stringForConstant(textureTarget), outputTexture);
188 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureTarget, outputTexture, 0);
189
190 if (!shaderOpaque)
191 {
192 glClearColor(0,0,0,0);
193 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
194 }
195
196 // Execute the shader.
197 {
198 GLint positionAttribute;
199 GLint textureCoordinateAttribute;
200 bool ret = VuoShader_getAttributeLocations(shader, VuoMesh_IndividualTriangles, cgl_ctx, &positionAttribute, NULL, &textureCoordinateAttribute, NULL);
201 if (!ret)
202 {
203 VDebugLog("Error: Failed to get attribute locations.");
204 glBindFramebuffer(GL_FRAMEBUFFER, 0);
205 if (outputToIOSurface)
206 VuoIoSurfacePool_disuse(ioSurface, false); // It was never used, so no need to quarantine it.
207 else if (outputToSpecificTexture)
208 {}
209 else
210 {
211 VuoGlTexture_retain(outputTexture, NULL, NULL);
212 VuoGlTexture_release(VuoGlTexturePool_Allocate, outputToGlTextureRectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D, textureTargetInternalFormat, pixelsWide, pixelsHigh, outputTexture);
213 }
214 outputTexture = 0;
215 surfID = 0;
216 return;
217 }
218
219 VuoGlProgram program;
220 if (!VuoShader_activate(shader, VuoMesh_IndividualTriangles, cgl_ctx, &program))
221 {
222 VUserLog("Shader activation failed.");
223 outputTexture = 0;
224 surfID = 0;
225 return;
226 }
227
228 {
230
231 GLint projectionMatrixUniform = VuoGlProgram_getUniformLocation(program, "projectionMatrix");
232 glUniformMatrix4fv(projectionMatrixUniform, 1, GL_FALSE, unityMatrix);
233
234 GLint cameraMatrixInverseUniform = VuoGlProgram_getUniformLocation(program, "cameraMatrixInverse");
235 glUniformMatrix4fv(cameraMatrixInverseUniform, 1, GL_FALSE, unityMatrix);
236
237 GLint useFisheyeProjectionUniform = VuoGlProgram_getUniformLocation(program, "useFisheyeProjection");
238 glUniform1i(useFisheyeProjectionUniform, false);
239
240 GLint modelviewMatrixUniform = VuoGlProgram_getUniformLocation(program, "modelviewMatrix");
241 glUniformMatrix4fv(modelviewMatrixUniform, 1, GL_FALSE, unityMatrix);
242
243 GLint aspectRatioUniform = VuoGlProgram_getUniformLocation(program, "aspectRatio");
244 if (aspectRatioUniform != -1)
245 glUniform1f(aspectRatioUniform, (float)pixelsWide/(float)pixelsHigh);
246
247 GLint viewportSizeUniform = VuoGlProgram_getUniformLocation(program, "viewportSize");
248 if (viewportSizeUniform != -1)
249 glUniform2f(viewportSizeUniform, (float)pixelsWide, (float)pixelsHigh);
250
251 glBindBuffer(GL_ARRAY_BUFFER, VuoImageRendererGlobal.quadDataBuffer);
252
253 glEnableVertexAttribArray(positionAttribute);
254 glVertexAttribPointer(positionAttribute, 4 /* XYZW */, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*4, (void*)0);
255
256 if (textureCoordinateAttribute != -1)
257 {
258 glEnableVertexAttribArray(textureCoordinateAttribute);
259 glVertexAttribPointer(textureCoordinateAttribute, 4 /* XYZW */, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*4, (void*)(sizeof(GLfloat)*16));
260 }
261
262#ifdef VUO_PROFILE
263 GLuint timeElapsedQuery;
264 glGenQueries(1, &timeElapsedQuery);
265 glBeginQuery(GL_TIME_ELAPSED_EXT, timeElapsedQuery);
266#endif
267
268 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
269
270#ifdef VUO_PROFILE
271 double seconds;
272 glEndQuery(GL_TIME_ELAPSED_EXT);
273 GLuint nanoseconds;
274 glGetQueryObjectuiv(timeElapsedQuery, GL_QUERY_RESULT, &nanoseconds);
275 seconds = ((double)nanoseconds) / NSEC_PER_SEC;
276 glDeleteQueries(1, &timeElapsedQuery);
277
278 double objectPercent = seconds / (1./60.) * 100.;
279 VLog("%6.2f %% of 60 Hz frame %s", objectPercent, shader->name);
280#endif
281
282 if (textureCoordinateAttribute != -1)
283 glDisableVertexAttribArray(textureCoordinateAttribute);
284
285 glDisableVertexAttribArray(positionAttribute);
286
287 glBindBuffer(GL_ARRAY_BUFFER, 0);
289 }
291 }
292
293 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureTarget, 0, 0);
294 glBindFramebuffer(GL_FRAMEBUFFER, 0);
295
296 if (outputToIOSurface)
297 {
298 surfID = VuoIoSurfacePool_getId(ioSurface);
299 VuoIoSurfacePool_disuse(ioSurface, true); // We may be sending it to another process, so we need to quarantine it.
300 }
301
302 glFlushRenderAPPLE();
303 });
304
305 if (outputToIOSurface)
306 return surfID;
307 else
308 return outputTexture;
309}
310
316extern "C" void VuoImageRenderer_fini(void)
317{
319 return;
320
321 static dispatch_once_t once = 0;
322 dispatch_once(&once, ^{
323 VuoGlContext_perform(^(CGLContextObj cgl_ctx){
324 glBindBuffer(GL_ARRAY_BUFFER, 0);
325
326 VuoGlPool_release(VuoGlPool_ArrayBuffer, sizeof(quadData), VuoImageRendererGlobal.quadDataBuffer);
327
329 glDeleteFramebuffers(1, &VuoImageRendererGlobal.outputFramebuffer);
330 });
331 });
332}