/* Includes */ #include #include #include #include #include #include #include #include "main.h" static GLint vertices_loc, txtSampler, txtCoord_loc, colors_loc; GLubyte *buf; GLuint projMat_loc; int j; void computeMatrix(GLfloat *mat4, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) { GLfloat inv_width = 1.0f / (r - l); GLfloat inv_height = 1.0f / (t - b); GLfloat inv_depth = 1.0f / (f - n); memset(mat4, 0, sizeof(GLfloat) * 16); /* 0 4 8 12 1 5 9 13 2 6 10 14 3 7 11 15 */ mat4[0] = 2.0f * inv_width; mat4[5] = 2.0f * inv_height; mat4[10] = 2.0f * inv_depth; mat4[12] = -(r + l) * inv_width; mat4[13] = -(t + b) * inv_height; mat4[14] = -(f + n) * inv_depth; mat4[15] = 1.0f; } static long int random_value = 1; static char colorBufferFormatName[40]; int main(int cArgs, char **aArgs) { /* EGL variables */ EGLDisplay sEGLDisplay; EGLContext sEGLContext; EGLSurface sEGLSurface; /* EGL_RENDERABLE_TYPE must be set to EGL_OPENGL_ES2_BIT. Otherwise, no * configurations will be returned. */ EGLint aEGLAttributes[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 16, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; EGLConfig aEGLConfigs[1]; EGLint cEGLConfigs; /* The default version is 1. 2 must be passed else eglCreateContext will * fail. */ EGLint aEGLContextAttributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; /* Platform-specific variables */ XSetWindowAttributes win_attrs; int attrs[64], idx = 0, num_config = 0; unsigned int uiHeight = 64; unsigned int uiWidth = 64; Window win; Display* display; int major, minor; Colormap colormap; XVisualInfo *pVisual; XEvent e; /* GL specific variables */ GLint iLocPosition; GLint iLocColour; GLint iLocMVP; GLuint uiProgram; GLuint uiFragShader; GLuint uiVertShader; /* Misc variables */ int bDone = 0; int iXangle = 0 * 3; int iYangle = 0 * 2; int iZangle = 0 * 1; float aRotate[16]; float aModelView[16], aPerspective[16], aMVP[16]; GLenum colorBufferFormat, targetFormats[5]; GLsizei numTargetFormats; GLfloat ref[4], exp[4], buf[4]; GLsizei textureBits[4]; GLfloat eps[4]; GLfloat matProjection[16]; long i, ii, max; GLfloat texCoords0[2] = { 0.0f, 0.0f }; GLfloat texCoords1[2] = { 1.0f, 1.0f}; GLfloat vertex[2]; GLfloat texCol[4]; GLubyte *tmpBuf; GLfloat col[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; /* Open X display */ display = XOpenDisplay(NULL); if (NULL == display) { /* Environment variable DISPLAY not set */ printf("Failed to open display.\n"); } /* Initialize EGL */ sEGLDisplay = EGL_CHECK(eglGetDisplay(display)); EGL_CHECK(eglInitialize(sEGLDisplay, NULL, NULL)); EGL_CHECK(eglChooseConfig( sEGLDisplay, aEGLAttributes, aEGLConfigs, 1, &cEGLConfigs)); if (cEGLConfigs == 0) { printf("No EGL configurations were returned.\n"); } /* Create X window */ win = CreateXWindow( "OpenGL ES 2.0 Example on a Linux Desktop", uiWidth, uiHeight, display, sEGLDisplay, aEGLConfigs[0], &colormap, &pVisual); if (!win) { /* Failed to create X window */ printf("Failed to create X window.\n"); } sEGLSurface = EGL_CHECK(eglCreateWindowSurface( sEGLDisplay, aEGLConfigs[0], win, NULL)); if (EGL_NO_SURFACE == sEGLSurface) { printf("Failed to create EGL surface.\n"); } sEGLContext = EGL_CHECK(eglCreateContext( sEGLDisplay, aEGLConfigs[0], EGL_NO_CONTEXT, aEGLContextAttributes)); if (EGL_NO_CONTEXT == sEGLContext) { printf("Failed to create EGL context.\n"); } EGL_CHECK(eglMakeCurrent( sEGLDisplay, sEGLSurface, sEGLSurface, sEGLContext)); computeMatrix(matProjection, 0.0f, (GLfloat)uiWidth, 0.0f, (GLfloat)uiHeight, 1.0f, -1.0f); glDisable(GL_DITHER); /* Initialize shaders */ processShader(&uiVertShader, VERT_FILE, GL_VERTEX_SHADER); processShader(&uiFragShader, FRAG_FILE, GL_FRAGMENT_SHADER); /* Create uiProgram (ready to attach shaders) */ uiProgram = GL_CHECK(glCreateProgram()); /* Attach shaders and link uiProgram */ GL_CHECK(glAttachShader(uiProgram, uiVertShader)); GL_CHECK(glAttachShader(uiProgram, uiFragShader)); GL_CHECK(glLinkProgram(uiProgram)); GL_CHECK(glUseProgram(uiProgram)); projMat_loc = glGetUniformLocation(uiProgram, "mvpMatrix_uni"); glUniformMatrix4fv(projMat_loc, 1, 0, matProjection); vertices_loc = glGetAttribLocation(uiProgram, "vertex_att"); colors_loc = glGetAttribLocation(uiProgram, "color_att"); txtCoord_loc = glGetAttribLocation(uiProgram, "multiTexCoord_att"); txtSampler = glGetUniformLocation(uiProgram, "texture0"); glEnableVertexAttribArray(vertices_loc); glEnableVertexAttribArray(colors_loc); glEnableVertexAttribArray(txtCoord_loc); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); texCol[0] = 0.56; texCol[1] = 0.56; texCol[2] = 0.56; texCol[3] = 0.56; glClear(GL_COLOR_BUFFER_BIT); glVertexAttribPointer(txtCoord_loc, 2, GL_FLOAT, GL_FALSE, 0, texCoords1); vertex[0] = 4.5; vertex[1] = 4.5; glVertexAttribPointer(vertices_loc, 2, GL_FLOAT, GL_FALSE, 0, &vertex[0]); glVertexAttribPointer(colors_loc, 4, GL_FLOAT, GL_FALSE, 0, texCol); glDrawArrays(GL_POINTS, 0, 1); glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 1, 1, 0); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLfloat)GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLfloat)GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (GLfloat)GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (GLfloat)GL_CLAMP_TO_EDGE); glActiveTexture(GL_TEXTURE0); glUniform1i(txtSampler, 0); glVertexAttribPointer(txtCoord_loc, 2, GL_FLOAT, GL_FALSE, 0, texCoords0); vertex[0] = 12.5; vertex[1] = 12.5; col[0] = col[1] = col[2] = col[3] = 1; glVertexAttribPointer(vertices_loc, 2, GL_FLOAT, GL_FALSE, 0, &vertex[0]); glVertexAttribPointer(colors_loc, 4, GL_FLOAT, GL_FALSE, 0, col); glDrawArrays(GL_POINTS, 0, 1); tmpBuf = (GLubyte *)malloc(4*sizeof(GLubyte)); glReadPixels(12, 12, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, tmpBuf); return 0; } /* Simulates desktop's glRotatef. The matrix is returned in * column-major order. */ void rotateMatrix( double angle, double x, double y, double z, float *R) { double radians, c, s, c1, u[3], length; int i, j; radians = (angle * M_PI)/180.0; c = cos(radians); s = sin(radians); c1 = 1.0 - cos(radians); length = sqrt(x * x + y * y + z * z); u[0] = x/length; u[1] = y/length; u[2] = z/length; for (i = 0; i < 16; i++) { R[i] = 0.0; } R[15] = 1.0; for (i = 0; i < 3; i++) { R[i * 4 + (i + 1) % 3] = u[(i + 2) % 3] * s; R[i * 4 + (i + 2) % 3] = -u[(i + 1) % 3] * s; } for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { R[i * 4 + j] += c1 * u[i] * u[j] + (i == j ? c : 0.0); } } } /* Simulates gluPerspectiveMatrix */ void perspectiveMatrix( double fovy, double aspect, double znear, double zfar, float *P) { int i; double f; f = 1.0/tan(fovy * 0.5); for (i = 0; i < 16; i++) { P[i] = 0.0; } P[0] = f/aspect; P[5] = f; P[10] = (znear + zfar)/(znear - zfar); P[11] = -1.0; P[14] = (2.0 * znear * zfar)/(znear - zfar); P[15] = 0.0; } /* Multiplies A by B and writes out to C. All matrices are 4x4 and column * major. In-place multiplication is supported. */ void multiplyMatrix(float *A, float *B, float *C) { int i, j, k; float aTmp[16]; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { aTmp[j * 4 + i] = 0.0; for (k = 0; k < 4; k++) { aTmp[j * 4 + i] += A[k * 4 + i] * B[j * 4 + k]; } } } for (i = 0; i < 16; i++) { C[i] = aTmp[i]; } } /* Creates a shader, loads in source, compiles, dumps debug as necessary. * pShader: Pointer to return created shader ID. * sFilename: Passed-in filename from which to load shader source. * iShaderType: Passed to GL e.g. GL_VERTEX_SHADER. */ void processShader(GLuint *pShader, char *sFilename, GLint iShaderType) { GLint iStatus; const char *aStrings[1] = { NULL }; /* Create shader and load into GL */ *pShader = GL_CHECK(glCreateShader(iShaderType)); aStrings[0] = loadShader(sFilename); GL_CHECK(glShaderSource(*pShader, 1, aStrings, NULL)); /* Clean up shader source */ free((void *)(aStrings[0])); aStrings[0] = NULL; /* Try compiling the shader */ GL_CHECK(glCompileShader(*pShader)); GL_CHECK(glGetShaderiv(*pShader, GL_COMPILE_STATUS, &iStatus)); /* Dump debug info (source and log) if compilation failed */ if(iStatus != GL_TRUE) { GLint iLen; char *sDebugSource = NULL; char *sErrorLog = NULL; /* Get shader source */ GL_CHECK(glGetShaderiv(*pShader, GL_SHADER_SOURCE_LENGTH, &iLen)); sDebugSource = malloc(iLen); GL_CHECK(glGetShaderSource(*pShader, iLen, NULL, sDebugSource)); printf("Debug source START:\n%s\nDebug source END\n\n", sDebugSource); free(sDebugSource); /* Now get the info log */ GL_CHECK(glGetShaderiv(*pShader, GL_INFO_LOG_LENGTH, &iLen)); sErrorLog = malloc(iLen); GL_CHECK(glGetShaderInfoLog(*pShader, iLen, NULL, sErrorLog)); printf("Log START:\n%s\nLog END\n\n", sErrorLog); free(sErrorLog); printf("Compilation FAILED!\n\n"); exit(1); } } /* Loads the shader source into memory. * sFilename: String holding filename to load */ char* loadShader(char *sFilename) { char *pResult = NULL; FILE *pFile = NULL; long iLen = 0; pFile = fopen(sFilename, "r"); if(pFile == NULL) { fprintf(stderr, "Error: Cannot read file '%s'\n", sFilename); exit(1); } fseek(pFile, 0, SEEK_END); /* Seek end of file */ iLen = ftell(pFile); fseek(pFile, 0, SEEK_SET); /* Seek start of file again */ pResult = calloc(iLen+1, sizeof(char)); fread(pResult, sizeof(char), iLen, pFile); pResult[iLen] = '\0'; fclose(pFile); return pResult; } /* Waits for map notification */ Bool WaitForMap(Display *d, XEvent *e, char *win_ptr) { if (e->type == MapNotify && e->xmap.window == (*((Window*)win_ptr))) { return True; } return False; } /* Creates an X window */ Window CreateXWindow( const char *title, int width, int height, Display* display, EGLDisplay sEGLDisplay, EGLConfig FBConfig, Colormap *pColormap, XVisualInfo **ppVisual) { XSetWindowAttributes wa; XSizeHints sh; XEvent e; unsigned long mask; long screen; XVisualInfo *visual, template; Colormap colormap; int vID, n; Window window; screen = DefaultScreen(display); eglGetConfigAttrib(sEGLDisplay, FBConfig, EGL_NATIVE_VISUAL_ID, &vID); template.visualid = vID; visual = XGetVisualInfo(display, VisualIDMask, &template, &n); colormap = XCreateColormap( display, RootWindow(display, screen), visual->visual, AllocNone); wa.colormap = colormap; wa.background_pixel = 0xFFFFFFFF; wa.border_pixel = 0; wa.event_mask = StructureNotifyMask | ExposureMask; mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap; window = XCreateWindow( display, RootWindow(display, screen), 0, 0, width, height, 0, visual->depth, InputOutput, visual->visual, mask, &wa); sh.flags = USPosition; sh.x = 10; sh.y = 10; XSetStandardProperties(display, window, title, title, None, 0, 0, &sh); XMapWindow(display, window); XIfEvent(display, &e, WaitForMap, (char*)&window); XSetWMColormapWindows(display, window, &window, 1); XFlush(display); *pColormap = colormap; *ppVisual = visual; return window; }