From 1752e124244102ee45e3e8b9c96802a4fbdc6ce7 Mon Sep 17 00:00:00 2001 From: James Jones Date: Fri, 28 Mar 2014 16:02:22 -0700 Subject: EGLStream sample code with clean git history Exported from NVIDIA-internal repository --- Makefile | 13 ++ create_window.h | 34 +++++ create_window_x11.c | 82 +++++++++++++ eglstream.c | 348 ++++++++++++++++++++++++++++++++++++++++++++++++++++ shared.c | 151 +++++++++++++++++++++++ shared.h | 66 ++++++++++ 6 files changed, 694 insertions(+) create mode 100644 Makefile create mode 100644 create_window.h create mode 100644 create_window_x11.c create mode 100644 eglstream.c create mode 100644 shared.c create mode 100644 shared.h 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 +#include +#include + +#include +#include + +#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 + +// 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 +#include +#include +#include +#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 -- cgit v1.2.3