1/* 2* Copyright 2011 The Android Open Source Project 3* 4* Licensed under the Apache License, Version 2.0 (the "License"); 5* you may not use this file except in compliance with the License. 6* You may obtain a copy of the License at 7* 8* http://www.apache.org/licenses/LICENSE-2.0 9* 10* Unless required by applicable law or agreed to in writing, software 11* distributed under the License is distributed on an "AS IS" BASIS, 12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13* See the License for the specific language governing permissions and 14* limitations under the License. 15*/ 16 17#include <stdio.h> 18#include <string.h> 19#include <stdlib.h> 20#include <unistd.h> 21 22//#define GL_API 23//#define GL_APIENTRY 24 25#undef ANDROID 26#include <EGL/egl.h> 27#include <GLES2/gl2.h> 28 29#ifdef __APPLE__ 30extern "C" void * createGLView(void *nsWindowPtr, int x, int y, int width, int height); 31#endif 32 33#undef HAVE_MALLOC_H 34#include <SDL.h> 35#include <SDL_syswm.h> 36 37 38#define WINDOW_WIDTH 500 39#define WINDOW_HEIGHT 500 40 41#define TEX_WIDTH 256 42#define TEX_HEIGHT 256 43 44 45#define F_to_X(d) ((d) > 32767.65535 ? 32767 * 65536 + 65535 : \ 46 (d) < -32768.65535 ? -32768 * 65536 + 65535 : \ 47 ((GLfixed) ((d) * 65536))) 48#define X_to_F(x) ((float)(x))/65536.0f 49 50//#define __FIXED__ 51 52const char *def_vShaderStr = 53 "attribute vec4 vPosition; \n" 54 "void main() \n" 55 "{ \n" 56 " gl_Position = vPosition; \n" 57 "} \n"; 58 59const char *def_fShaderStr = 60 "precision mediump float; \n" 61 "void main() \n" 62 "{ \n" 63#ifndef __FIXED__ 64 " gl_FragColor = vec4(0.2, 0.5, 0.1, 1.0); \n" 65#else 66 " gl_FragColor = vec4(0.4, 0.3, 0.7, 1.0); \n" 67#endif 68 "} \n"; 69 70static EGLint const attribute_list[] = { 71 EGL_RED_SIZE, 1, 72 EGL_GREEN_SIZE, 1, 73 EGL_BLUE_SIZE, 1, 74 EGL_NONE 75}; 76 77unsigned char *genTexture(int width, int height, int comp) 78{ 79 unsigned char *img = new unsigned char[width * height * comp]; 80 unsigned char *ptr = img; 81 for (int i = 0; i < height; i++) { 82 for (int j = 0; j < width; j++) { 83 unsigned char col = ((i / 8 + j / 8) % 2) * 255 ; 84 for (int c = 0; c < comp; c++) { 85 *ptr = col; ptr++; 86 } 87 } 88 } 89 return img; 90} 91 92unsigned char *genRedTexture(int width, int height, int comp) 93{ 94 unsigned char *img = new unsigned char[width * height * comp]; 95 memset(img,0,width*height*comp); 96 unsigned char *ptr = img; 97 for (int i = 0; i < height; i++) { 98 for (int j = 0; j < width; j++) { 99 unsigned char col = ((i / 8 + j / 8) % 2) * 255 ; 100 *ptr = col; 101 ptr+=comp; 102 } 103 } 104 return img; 105} 106 107 108void printUsage(const char *progname) 109{ 110 fprintf(stderr, "usage: %s [options]\n", progname); 111 fprintf(stderr, "\t-vs <filename> - vertex shader to use\n"); 112 fprintf(stderr, "\t-fs <filename> - fragment shader to use\n"); 113} 114 115 116 117GLuint LoadShader(GLenum type,const char *shaderSrc) 118{ 119 GLuint shader; 120 GLint compiled; 121 // Create the shader object 122 shader = glCreateShader(type); 123 if(shader == 0) 124 return 0; 125 // Load the shader source 126 glShaderSource(shader, 1, &shaderSrc, NULL); 127 // Compile the shader 128 glCompileShader(shader); 129 // Check the compile status 130 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 131 if(!compiled) 132 { 133 GLint infoLen = 0; 134 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); 135 if(infoLen > 1) 136 { 137 char* infoLog = (char*)malloc(sizeof(char) * infoLen); 138 glGetShaderInfoLog(shader, infoLen, NULL, infoLog); 139 printf("Error compiling shader:\n%s\n", infoLog); 140 free(infoLog); 141 } 142 glDeleteShader(shader); 143 return 0; 144 } 145 return shader; 146} 147 148const char *readShader(const char *fileName) 149{ 150 FILE *fp = fopen(fileName, "rb"); 151 if (!fp) return NULL; 152 153 int bSize = 1024; 154 int nBufs = 1; 155 char *buf = (char *)malloc(bSize); 156 int n; 157 int len = 0; 158 n = fread(&buf[0], 1, bSize, fp); 159 while( n == bSize ) { 160 len += n; 161 nBufs++; 162 buf = (char *)realloc(buf, bSize * nBufs); 163 n = fread(&buf[len], 1, bSize, fp); 164 } 165 len += n; 166 167 buf[len] = '\0'; 168 return (const char *)buf; 169} 170 171void dumpUniforms(GLuint program) 172{ 173 GLint numU; 174 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numU); 175 printf("==== Program %d has %d active uniforms ===\n", program, numU); 176 char name[512]; 177 GLsizei len; 178 GLint size; 179 GLenum type; 180 for (int i=0; i<numU; i++) { 181 glGetActiveUniform(program, i, 182 512, &len, &size, &type, name); 183 printf("\t%s : type=0x%x size=%d\n", name, type, size); 184 } 185} 186 187/// 188// Initialize the shader and program object 189// 190int Init(const char *vShaderStr, const char *fShaderStr) 191{ 192 GLuint vertexShader; 193 GLuint fragmentShader; 194 GLuint programObject; 195 GLint linked; 196 // Load the vertex/fragment shaders 197 vertexShader = LoadShader(GL_VERTEX_SHADER, vShaderStr); 198 fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fShaderStr); 199 // Create the program object 200 programObject = glCreateProgram(); 201 if(programObject == 0) 202 return -1; 203 glAttachShader(programObject, vertexShader); 204 glAttachShader(programObject, fragmentShader); 205 // Bind vPosition to attribute 0 206 glBindAttribLocation(programObject, 0, "vPosition"); 207 // Link the program 208 glLinkProgram(programObject); 209 // Check the link status 210 glGetProgramiv(programObject, GL_LINK_STATUS, &linked); 211 if(!linked) 212 { 213 GLint infoLen = 0; 214 glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen); 215 if(infoLen > 1) 216 { 217 char* infoLog = (char*)malloc(sizeof(char) * infoLen); 218 glGetProgramInfoLog(programObject, infoLen, NULL, infoLog); 219 printf("Error linking program:\n%s\n", infoLog); 220 free(infoLog); 221 } 222 glDeleteProgram(programObject); 223 return -1; 224 } 225 226 // dump active uniforms 227 dumpUniforms(programObject); 228 229 // Store the program object 230#ifndef __FIXED__ 231 glClearColor(0.0f, 0.0f, 1.0f, 1.0f); 232#else 233 glClearColor(1.0f, 0.0f, 0.0f, 1.0f); 234#endif 235 return programObject; 236} 237 238 239/// 240// Draw a triangle using the shader pair created in Init() 241// 242void Draw(EGLDisplay display,EGLSurface surface,int width,int height,GLuint program) 243{ 244#ifndef __FIXED__ 245 GLfloat vVertices[] = {0.0f, 0.5f, 0.0f, 246 -0.5f, -0.5f, 0.0f, 247 0.5f, -0.5f, 0.0f}; 248#else 249 250 GLfixed vVertices[] = {F_to_X(0.0f), F_to_X(0.5f),F_to_X(0.0f), 251 F_to_X(-0.5f),F_to_X(-0.5f), F_to_X(0.0f), 252 F_to_X(0.5f),F_to_X(-0.5f),F_to_X(0.0f)}; 253#endif 254 255 // Set the viewport 256 glViewport(0, 0,width,height); 257 // Clear the color buffer 258 glClear(GL_COLOR_BUFFER_BIT); 259 // Use the program object 260 glUseProgram(program); 261 // Load the vertex data 262#ifndef __FIXED__ 263 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices); 264#else 265 glVertexAttribPointer(0, 3, GL_FIXED, GL_FALSE, 0, vVertices); 266#endif 267 glEnableVertexAttribArray(0); 268 glDrawArrays(GL_TRIANGLES, 0, 3); 269 eglSwapBuffers(display,surface); 270} 271 272#ifdef _WIN32 273char **parseCmdLine(char *cmdLine, int *argc) 274{ 275 int argvSize = 10; 276 char **argv = (char **)malloc(argvSize * sizeof(char *)); 277 *argc = 0; 278 int i=0; 279 bool prevIsSpace = true; 280 int argStart = 0; 281 282 argv[(*argc)++] = strdup("playdump"); 283 284 while(cmdLine[i] != '\0') { 285 bool isSpace = (cmdLine[i] == ' ' || cmdLine[i] == '\t'); 286 if ( !isSpace && prevIsSpace ) { 287 argStart = i; 288 } 289 else if (isSpace && !prevIsSpace) { 290 cmdLine[i] = '\0'; 291 if (*argc >= argvSize) { 292 argvSize *= 2; 293 argv = (char **)realloc(argv, argvSize * sizeof(char *)); 294 } 295 argv[(*argc)++] = &cmdLine[argStart]; 296 argStart = i+1; 297 } 298 299 prevIsSpace = isSpace; 300 i++; 301 } 302 303 if (i > argStart) { 304 argv[(*argc)++] = &cmdLine[argStart]; 305 } 306 return argv; 307} 308#endif 309 310#ifdef _WIN32 311int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) 312#else 313int main(int argc, char **argv) 314#endif 315{ 316#ifdef _WIN32 317 int argc; 318 char **argv = parseCmdLine(lpCmdLine, &argc); 319#endif 320 const char *vShader = def_vShaderStr; 321 const char *fShader = def_fShaderStr; 322 323 for (int i=1; i<argc; i++) { 324 if (!strcmp(argv[i],"-vs")) { 325 if (++i >= argc) { 326 printUsage(argv[0]); 327 return -1; 328 } 329 vShader = readShader(argv[i]); 330 if (!vShader) { 331 vShader = def_vShaderStr; 332 printf("Failed to load vshader %s, using defualt\n", argv[i]); 333 } 334 else { 335 printf("Using vshader %s\n", argv[i]); 336 } 337 } 338 else if (!strcmp(argv[i],"-fs")) { 339 if (++i >= argc) { 340 printUsage(argv[0]); 341 return -1; 342 } 343 fShader = readShader(argv[i]); 344 if (!fShader) { 345 fShader = def_fShaderStr; 346 printf("Failed to load fshader %s, using defualt\n", argv[i]); 347 } 348 else { 349 printf("Using fshader %s\n", argv[i]); 350 } 351 } 352 else { 353 printUsage(argv[0]); 354 return -1; 355 } 356 } 357 358 #ifdef _WIN32 359 HWND windowId = NULL; 360 #elif __linux__ 361 Window windowId = 0; 362 #elif __APPLE__ 363 void* windowId = NULL; 364 #endif 365 366 // // Inialize SDL window 367 // 368 if (SDL_Init(SDL_INIT_NOPARACHUTE | SDL_INIT_VIDEO)) { 369 fprintf(stderr,"SDL init failed: %s\n", SDL_GetError()); 370 return -1; 371 } 372 373 SDL_Surface *surface = SDL_SetVideoMode(WINDOW_WIDTH,WINDOW_HEIGHT, 32, SDL_HWSURFACE); 374 if (surface == NULL) { 375 fprintf(stderr,"Failed to set video mode: %s\n", SDL_GetError()); 376 return -1; 377 } 378 379 SDL_SysWMinfo wminfo; 380 memset(&wminfo, 0, sizeof(wminfo)); 381 SDL_GetWMInfo(&wminfo); 382 #ifdef _WIN32 383 windowId = wminfo.window; 384 #elif __linux__ 385 windowId = wminfo.info.x11.window; 386 #elif __APPLE__ 387 windowId = createGLView(wminfo.nsWindowPtr,0,0,WINDOW_WIDTH,WINDOW_HEIGHT); 388 #endif 389 390 int major,minor,num_config; 391 int attrib_list[] ={ 392 EGL_CONTEXT_CLIENT_VERSION, 2, 393 EGL_NONE 394 }; 395 EGLConfig configs[150]; 396 EGLSurface egl_surface; 397 EGLContext ctx; 398 EGLDisplay d = eglGetDisplay(EGL_DEFAULT_DISPLAY); 399 eglInitialize(d,&major,&minor); 400 printf("DISPLAY == %p major =%d minor = %d\n",d,major,minor); 401 eglChooseConfig(d, attribute_list, configs, 150, &num_config); 402 printf("config returned %d\n",num_config); 403 egl_surface = eglCreateWindowSurface(d,configs[0],windowId,NULL); 404 ctx = eglCreateContext(d,configs[0],EGL_NO_CONTEXT,attrib_list); 405 printf("SURFACE == %p CONTEXT == %p\n",egl_surface,ctx); 406 if(eglMakeCurrent(d,egl_surface,egl_surface,ctx)!= EGL_TRUE){ 407 printf("make current failed\n"); 408 return false; 409 } 410 printf("after make current\n"); 411 412 GLenum err = glGetError(); 413 if(err != GL_NO_ERROR) { 414 printf("error before drawing ->>> %d \n",err); 415 } else { 416 printf("no error before drawing\n"); 417 } 418 419 int program = Init(vShader, fShader); 420 if(program < 0){ 421 printf("failed init shaders\n"); 422 return false; 423 } 424 425 Draw(d,egl_surface,WINDOW_WIDTH,WINDOW_HEIGHT,program); 426 427 err = glGetError(); 428 if(err != GL_NO_ERROR) 429 printf("error ->>> %d \n",err); 430 eglDestroySurface(d,egl_surface); 431 eglDestroyContext(d,ctx); 432 433// Just wait until the window is closed 434 SDL_Event ev; 435 while( SDL_WaitEvent(&ev) ) { 436 if (ev.type == SDL_QUIT) { 437 break; 438 } 439 } 440 return 0; 441} 442 443 444