summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile13
-rw-r--r--create_window.h34
-rw-r--r--create_window_x11.c82
-rw-r--r--eglstream.c348
-rw-r--r--shared.c151
-rw-r--r--shared.h66
6 files changed, 694 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..3279459
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
+C_FILES = create_window_x11.c eglstream.c shared.c
+H_FILES = create_window.h shared.h
+TARGET_BIN = eglstream
+
+.PHONY: all clean
+
+all: $(TARGET_BIN)
+
+$(TARGET_BIN): $(C_FILES) $(H_FILES)
+ gcc -I/usr/include/Khronos -o $@ $^ -lEGL -lX11 -lGLESv2 -lm
+
+clean:
+ rm -rf $(TARGET_BIN) *.o
diff --git a/create_window.h b/create_window.h
new file mode 100644
index 0000000..4c1ec50
--- /dev/null
+++ b/create_window.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "EGL/egl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EGLNativeWindowType CreateWindow(int width, int height, const char *name);
+void DestroyWindow(EGLNativeWindowType win);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/create_window_x11.c b/create_window_x11.c
new file mode 100644
index 0000000..5d30aad
--- /dev/null
+++ b/create_window_x11.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include "create_window.h"
+
+#define FATAL_ERROR(msg) \
+ do { \
+ printf("Fatal Error: %s\n",msg); \
+ printf("failed at %s:%d\n", __FILE__,__LINE__); \
+ exit(1); \
+ } while (0)
+
+static Display *dpy = NULL;
+static Window win = 0;
+
+EGLNativeWindowType CreateWindow(int width, int height, const char *name)
+{
+ XEvent evt;
+ int scr;
+
+ if (dpy != NULL || win != 0) {
+ FATAL_ERROR("only one window supported");
+ }
+
+ dpy = XOpenDisplay(NULL);
+ if (dpy == NULL) {
+ FATAL_ERROR("XOpenDisplay");
+ }
+
+ scr = DefaultScreen(dpy);
+ win = XCreateSimpleWindow(dpy, RootWindow(dpy, scr),
+ 0, 0, width, height, 1,
+ BlackPixel(dpy, scr), WhitePixel(dpy, scr));
+ if (!win) {
+ FATAL_ERROR("XCreateSimpleWindow");
+ }
+
+ XChangeProperty(dpy, win, XA_WM_NAME, XA_STRING,
+ 8, PropModeReplace, name, name ? strlen(name) : 0);
+
+ XSelectInput(dpy, win, KeyPressMask | ExposureMask);
+
+ XMapWindow(dpy, win);
+ XSync(dpy, False);
+
+ return win;
+}
+
+void DestroyWindow(EGLNativeWindowType w)
+{
+ if ((Window)w != win) {
+ FATAL_ERROR(__FUNCTION__);
+ }
+
+ XDestroyWindow(dpy, win);
+}
diff --git a/eglstream.c b/eglstream.c
new file mode 100644
index 0000000..71d2c5d
--- /dev/null
+++ b/eglstream.c
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "shared.h"
+#include "create_window.h"
+
+#define NUM_FRAMES 100
+#define WINDOW_WIDTH 600
+#define WINDOW_HEIGHT 600
+#define STREAM_WIDTH 128
+#define STREAM_HEIGHT 128
+
+// Shared.
+static EGLDisplay dpy;
+static EGLStreamKHR stream;
+static int frame = 0;
+
+// Consumer.
+static EGLNativeWindowType consumerWin;
+static EGLContext consumerCtx;
+static EGLSurface consumerSurf;
+static GLuint consumerRotationMatrixUniform;
+
+// Producer.
+static EGLContext producerCtx;
+static EGLSurface producerSurf;
+static GLuint producerScaleUniform;
+
+static void DoTest(void)
+{
+ while (frame++ < NUM_FRAMES) {
+
+ // Producer rendering.
+ {
+ float scale = (float)((frame % 50) + 50) / 100.0f;
+
+ if (!eglMakeCurrent(dpy, producerSurf, producerSurf, producerCtx))
+ FATAL_ERROR("Could not make producer context current");
+
+ glClear(GL_COLOR_BUFFER_BIT);
+ glUniform1f(producerScaleUniform, scale);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ glFinish();
+
+ if (!eglSwapBuffers(dpy, producerSurf))
+ FATAL_ERROR("SwapBuffers failed");
+ }
+
+ // Consumer rendering.
+ {
+ static const GLushort cubeIndices[] = {
+ 0, 1, 2, 3, 7, 1, 5, 4, 7, 6, 2, 4, 0, 1
+ };
+
+ if (!eglMakeCurrent(dpy, consumerSurf, consumerSurf, consumerCtx))
+ FATAL_ERROR("Could not make consumer context current");
+
+ if (!eglStreamConsumerAcquireKHR(dpy, stream))
+ FATAL_ERROR("Failed to acquire frame");
+
+ GLfloat rotMat[16];
+ CreateRotationMatrix(rotMat, (float)frame, 0.0f, 1.0f, 0.0f);
+ glUniformMatrix4fv(consumerRotationMatrixUniform, 1, GL_FALSE, rotMat);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glDrawElements(GL_TRIANGLE_STRIP, 14, GL_UNSIGNED_SHORT, cubeIndices);
+ glFinish();
+
+ if (!eglSwapBuffers(dpy, consumerSurf))
+ FATAL_ERROR("Failed in eglSwapBuffers");
+ }
+ }
+}
+
+static void InitializeEgl(void)
+{
+ InitEGLExtFuncs();
+
+ dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (dpy == EGL_NO_DISPLAY)
+ FATAL_ERROR("Could not get EGL display");
+ if (!eglInitialize(dpy, 0, 0))
+ FATAL_ERROR("Could not initialize EGL display");
+}
+
+static void InitializeStream(void)
+{
+ static EGLint streamAttrs[] = {
+ EGL_NONE, EGL_NONE,
+ EGL_NONE
+ };
+ stream = eglCreateStreamKHR(dpy, streamAttrs);
+ if (stream == EGL_NO_STREAM_KHR)
+ FATAL_ERROR("Error creating stream");
+}
+
+static void InitializeConsumer(void)
+{
+ static const char vertexShaderSource[] =
+ "attribute vec4 aPosition;\n"
+ "attribute vec2 aTexCoord;\n"
+ "varying vec2 vTexCoord;\n"
+ "uniform mat4 uProjectionMat;\n"
+ "uniform mat4 uRotationMat;\n"
+ "void main() {\n"
+ " vec4 pos = uRotationMat * aPosition;\n"
+ " pos.z -= 5.0;\n"
+ " gl_Position = uProjectionMat * pos;\n"
+ " vTexCoord = aTexCoord;\n"
+ "}\n";
+
+ static const char fragmentShaderSource[] =
+ "#extension GL_OES_EGL_image_external : enable\n"
+ "precision lowp float;\n"
+ "uniform samplerExternalOES uTex;\n"
+ "varying vec2 vTexCoord;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(uTex, vec2(vTexCoord.x, 1.0-vTexCoord.y));\n"
+ " if (vTexCoord.x < 0.01 || vTexCoord.x > 0.99 || vTexCoord.y < 0.01 || vTexCoord.y > 0.99) {\n"
+ " gl_FragColor = vec4(0.0, 0.5, 0.0, 1.0);\n"
+ " }\n"
+ "}\n";
+
+ static const GLfloat cubeVertices[] = {
+ -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
+ -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0,
+ };
+
+ static const GLfloat cubeTexCoords[] = {
+ 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,
+ 0.0, 1.0, 1.0, 1.0,
+ };
+
+ static EGLint configAttrs[] = {
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_DEPTH_SIZE, 16,
+ EGL_NONE
+ };
+
+ static EGLint contextAttrs[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ // Create window.
+ consumerWin = CreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "EGL Streams");
+
+ // Find config.
+ EGLint ncfg = 0;
+ EGLConfig cfg;
+ if (!eglChooseConfig(dpy, configAttrs, &cfg, 1, &ncfg))
+ FATAL_ERROR("Could not find EGL config");
+ if (ncfg == 0)
+ FATAL_ERROR("No EGL config found");
+
+ // Create context.
+ consumerCtx = eglCreateContext(dpy, cfg, EGL_NO_CONTEXT, contextAttrs);
+ if (consumerCtx == EGL_NO_CONTEXT)
+ FATAL_ERROR("Could not create EGL context");
+
+ // Create window surface.
+ consumerSurf = eglCreateWindowSurface(dpy, cfg, consumerWin, 0);
+ if (consumerSurf == EGL_NO_SURFACE)
+ FATAL_ERROR("Could not create EGLSurface for window");
+
+ // Make current.
+ if (!eglMakeCurrent(dpy, consumerSurf, consumerSurf, consumerCtx))
+ FATAL_ERROR("Could not make context current");
+
+ // Set clear color/viewport.
+ glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
+ glViewport(10, 10, WINDOW_WIDTH - 20, WINDOW_HEIGHT - 20);
+ glEnable(GL_DEPTH_TEST);
+
+ // Set vertex state and create program.
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, cubeVertices);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, cubeTexCoords);
+ glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ LoadShader(vs, vertexShaderSource, sizeof(vertexShaderSource));
+ LoadShader(fs, fragmentShaderSource, sizeof(fragmentShaderSource));
+ GLuint program = glCreateProgram();
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glBindAttribLocation(program, 0, "aPosition");
+ glBindAttribLocation(program, 1, "aTexCoord");
+ glLinkProgram(program);
+ glUseProgram(program);
+
+ // Set the uniforms.
+ GLfloat projMat[16];
+ CreatePerspectiveMatrix(projMat, 45.0f, (float)WINDOW_WIDTH/(float)WINDOW_HEIGHT, 1.0f, 1000.0f);
+ glUniformMatrix4fv(glGetUniformLocation(program, "uProjectionMat"), 1, GL_FALSE, projMat);
+ glUniform1i(glGetUniformLocation(program, "uTex"), 0);
+ consumerRotationMatrixUniform = glGetUniformLocation(program, "uRotationMat");
+
+ // Connect a new external texture as a consumer to the stream.
+ GLuint tex;
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex);
+ if (!eglStreamConsumerGLTextureExternalKHR(dpy, stream))
+ FATAL_ERROR("Failed to connect consumer");
+
+ if (glGetError() != GL_NO_ERROR)
+ FATAL_ERROR("GL Error while initializing consumer");
+}
+
+static void InitializeProducer(void)
+{
+ static const char vertexShaderSource[] =
+ "attribute vec2 aPosition;\n"
+ "uniform float uScale;\n"
+ "void main() {\n"
+ " gl_Position = vec4(aPosition * uScale, 0.0, 1.0);\n"
+ "}\n";
+
+ static const char fragmentShaderSource[] =
+ "precision lowp float;\n"
+ "void main() {\n"
+ " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
+ "}\n";
+
+ static const GLfloat triVertices[] = {
+ -0.5, -0.5,
+ 0.5, -0.5,
+ 0.0, 0.5};
+
+ static EGLint configAttrs[] = {
+ EGL_SURFACE_TYPE, EGL_STREAM_BIT_KHR,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_NONE
+ };
+
+ static EGLint contextAttrs[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ static EGLint surfaceAttrs[] = {
+ EGL_WIDTH, STREAM_WIDTH,
+ EGL_HEIGHT, STREAM_HEIGHT,
+ EGL_NONE
+ };
+
+ // Find producer config.
+ EGLint ncfg = 0;
+ EGLConfig cfg;
+ if (!eglChooseConfig(dpy, configAttrs, &cfg, 1, &ncfg))
+ FATAL_ERROR("Could not find EGL config for producer");
+ if (ncfg == 0)
+ FATAL_ERROR("No EGL config found for producer");
+
+ // Create producer context.
+ producerCtx = eglCreateContext(dpy, cfg, EGL_NO_CONTEXT, contextAttrs);
+ if (producerCtx == EGL_NO_CONTEXT)
+ FATAL_ERROR("Could not create producer EGL context");
+
+ // Create producer surface.
+ producerSurf = eglCreateStreamProducerSurfaceKHR(dpy, cfg, stream, surfaceAttrs);
+ if (producerSurf == EGL_NO_STREAM_KHR)
+ FATAL_ERROR("Could not create producer surface");
+
+ // Make producer context current.
+ if (!eglMakeCurrent(dpy, producerSurf, producerSurf, producerCtx))
+ FATAL_ERROR("Could not make producer context current");
+
+ // Set the clear color/viewport.
+ glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+ glViewport(0, 0, STREAM_WIDTH, STREAM_HEIGHT);
+
+ // Set vertex state and create program.
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, triVertices);
+ glEnableVertexAttribArray(0);
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ LoadShader(vs, vertexShaderSource, sizeof(vertexShaderSource));
+ LoadShader(fs, fragmentShaderSource, sizeof(fragmentShaderSource));
+ GLuint program = glCreateProgram();
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glBindAttribLocation(program, 0, "aPosition");
+ glLinkProgram(program);
+ glUseProgram(program);
+ producerScaleUniform = glGetUniformLocation(program, "uScale");
+
+ if (glGetError() != GL_NO_ERROR)
+ FATAL_ERROR("GL Error while initializing consumer");
+}
+
+static void TerminateEgl(void)
+{
+ eglTerminate(dpy);
+}
+
+static void TerminateStream(void)
+{
+ eglDestroyStreamKHR(dpy, stream);
+}
+
+static void TerminateConsumer(void)
+{
+ eglDestroyContext(dpy, consumerCtx);
+ eglDestroySurface(dpy, consumerSurf);
+ DestroyWindow(consumerWin);
+}
+
+static void TerminateProducer(void)
+{
+ eglDestroyContext(dpy, producerCtx);
+ eglDestroySurface(dpy, producerSurf);
+}
+
+int main(int argc, char *argv[])
+{
+ InitializeEgl();
+ InitializeStream();
+ InitializeConsumer();
+ InitializeProducer();
+ DoTest();
+ TerminateProducer();
+ TerminateConsumer();
+ TerminateStream();
+ TerminateEgl();
+ return 0;
+}
+
diff --git a/shared.c b/shared.c
new file mode 100644
index 0000000..f938281
--- /dev/null
+++ b/shared.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "shared.h"
+
+#include <math.h>
+
+// EGL_KHR_stream functions
+PFNEGLCREATESTREAMKHRPROC eglCreateStreamKHR;
+PFNEGLDESTROYSTREAMKHRPROC eglDestroyStreamKHR;
+PFNEGLSTREAMATTRIBKHRPROC eglStreamAttribKHR;
+PFNEGLQUERYSTREAMKHRPROC eglQueryStreamKHR;
+
+// EGL_KHR_stream_consumer_gltexture functions
+PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC eglStreamConsumerGLTextureExternalKHR;
+PFNEGLSTREAMCONSUMERACQUIREKHRPROC eglStreamConsumerAcquireKHR;
+PFNEGLSTREAMCONSUMERRELEASEKHRPROC eglStreamConsumerReleaseKHR;
+
+// EGL_KHR_stream_producer_eglsurface functions
+PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC eglCreateStreamProducerSurfaceKHR;
+
+void InitEGLExtFuncs(void)
+{
+ #define GET_FUNC(name, type) \
+ do { \
+ name = (type)eglGetProcAddress(#name); \
+ if (!name) { \
+ FATAL_ERROR("Failed to find extension function " #name); \
+ } \
+ } while(0)
+ GET_FUNC(eglCreateStreamKHR, PFNEGLCREATESTREAMKHRPROC);
+ GET_FUNC(eglDestroyStreamKHR, PFNEGLDESTROYSTREAMKHRPROC);
+ GET_FUNC(eglStreamAttribKHR, PFNEGLSTREAMATTRIBKHRPROC);
+ GET_FUNC(eglQueryStreamKHR, PFNEGLQUERYSTREAMKHRPROC);
+ GET_FUNC(eglCreateStreamProducerSurfaceKHR, PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC);
+ GET_FUNC(eglStreamConsumerGLTextureExternalKHR, PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC);
+ GET_FUNC(eglStreamConsumerAcquireKHR, PFNEGLSTREAMCONSUMERACQUIREKHRPROC);
+ GET_FUNC(eglStreamConsumerReleaseKHR, PFNEGLSTREAMCONSUMERRELEASEKHRPROC);
+ #undef GET_FUNC
+}
+
+void LoadShader(unsigned int sObj, const char *src, int srcLen)
+{
+ const char * source[1];
+ int length[1];
+ int compileStatus;
+
+ source[0] = src;
+ length[0] = srcLen;
+ glShaderSource(sObj, (sizeof(length) / sizeof(length[0])), source, length);
+ glCompileShader(sObj);
+ glGetShaderiv(sObj, GL_COMPILE_STATUS, &compileStatus);
+
+ if (compileStatus != 1) {
+ int infoLogLength, out;
+ char *infoLog;
+
+ glGetShaderiv(sObj, GL_INFO_LOG_LENGTH, &infoLogLength);
+ infoLog = malloc(infoLogLength+1);
+ memset(infoLog, 0, infoLogLength+1);
+ glGetShaderInfoLog(sObj, infoLogLength, &out, infoLog);
+ DEBUG_PRINT(("Shader compilation failed:\n"));
+ DEBUG_PRINT(("%s\n", infoLog));
+ free(infoLog);
+
+ FATAL_ERROR("Failed to load shader");
+ }
+}
+
+void CreateRotationMatrix(float mat[16], float angle, float x, float y, float z)
+{
+ /* Calculate the rotation matrix */
+ float norm, cosA, sinA, sqX, sqY, sqZ, xY, xZ, yZ;
+ cosA = cos(angle * M_PI / 180.0f);
+ sinA = sin(angle * M_PI / 180.0f);
+ sqX = x*x;
+ sqY = y*y;
+ sqZ = z*z;
+ xY = x * y;
+ xZ = x * z;
+ yZ = y * z;
+
+ mat[0] = sqX + (cosA * (1.0f - sqX));
+ mat[1] = xY - (cosA * xY) + (sinA * z);
+ mat[2] = xZ - (cosA * xZ) - (sinA * y);
+ mat[3] = 0.0f;
+ mat[4] = xY - (cosA * xY) - (sinA *z);
+ mat[5] = sqY + (cosA * (1.0f - sqY));
+ mat[6] = yZ - (cosA * yZ) + (sinA * x);
+ mat[7] = 0.0f;
+ mat[8] = xZ - (cosA * xZ) + (sinA * y);
+ mat[9] = yZ - (cosA * yZ) - (sinA * x);
+ mat[10] = sqZ + (cosA * (1.0f - sqZ));
+ mat[11] = 0.0f;
+ mat[12] = 0.0f;
+ mat[13] = 0.0f;
+ mat[14] = 0.0f;
+ mat[15] = 1.0f;
+}
+
+void CreatePerspectiveMatrix(float mat[16],
+ double fovy,
+ double aspect,
+ double zNear,
+ double zFar)
+{
+ const double f = 1.0 / tan(fovy / 2.0);
+
+ /* Column 0 */
+ mat[0] = (float)(f / aspect);
+ mat[1] = 0.0f;
+ mat[2] = 0.0f;
+ mat[3] = 0.0f;
+
+ /* Column 1 */
+ mat[4] = 0.0f;
+ mat[5] = (float)f;
+ mat[6] = 0.0f;
+ mat[7] = 0.0f;
+
+ /* Column 2 */
+ mat[8] = 0.0f;
+ mat[9] = 0.0f;
+ mat[10] = (-zFar - zNear) / (zFar - zNear);
+ mat[11] = -1.0f;
+
+ /* Column 3 */
+ mat[12] = 0.0f;
+ mat[13] = 0.0f;
+ mat[14] = (2.0f * zFar * zNear) / (zNear - zFar);
+ mat[15] = 0.0f;
+}
diff --git a/shared.h b/shared.h
new file mode 100644
index 0000000..22a3776
--- /dev/null
+++ b/shared.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __SHARED_H__
+#define __SHARED_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include "EGL/egl.h"
+#include "EGL/eglext.h"
+#include "GLES2/gl2.h"
+#include "GLES2/gl2ext.h"
+
+// EGL_KHR_stream functions
+extern PFNEGLCREATESTREAMKHRPROC eglCreateStreamKHR;
+extern PFNEGLDESTROYSTREAMKHRPROC eglDestroyStreamKHR;
+extern PFNEGLSTREAMATTRIBKHRPROC eglStreamAttribKHR;
+extern PFNEGLQUERYSTREAMKHRPROC eglQueryStreamKHR;
+
+// EGL_KHR_stream_consumer_gltexture functions
+extern PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC eglStreamConsumerGLTextureExternalKHR;
+extern PFNEGLSTREAMCONSUMERACQUIREKHRPROC eglStreamConsumerAcquireKHR;
+extern PFNEGLSTREAMCONSUMERRELEASEKHRPROC eglStreamConsumerReleaseKHR;
+
+// EGL_KHR_stream_producer_eglsurface functions
+extern PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC eglCreateStreamProducerSurfaceKHR;
+
+#define DEBUG_PRINT(x) printf x
+#define FATAL_ERROR(msg) \
+ do { \
+ int errsv = errno; \
+ printf("Fatal Error: " msg "\n"); \
+ if (errsv) printf("failed with error %s\n", strerror(errsv)); \
+ printf("failed at %s:%d\n", __FILE__,__LINE__); \
+ exit(1); \
+ } while (0)
+
+void InitEGLExtFuncs(void);
+void LoadShader(unsigned int sObj, const char *src, int srcLen);
+void CreateRotationMatrix(float mat[16], float angle, float x, float y, float z);
+extern void CreateFrustumMatrix(float *matrix, float left, float right, float bottom, float top,
+ float znear, float zfar);
+extern void CreatePerspectiveMatrix(float mat[16], double fovy, double aspect,
+ double zNear, double zFar);
+#endif