1 /* 2 * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 3 * Use of this source code is governed by a BSD-style license that can be 4 * found in the LICENSE file. 5 */ 6 7 #include <GLES2/gl2.h> 8 #include <GLES2/gl2ext.h> 9 #include <EGL/egl.h> 10 #include <EGL/eglext.h> 11 #include <X11/Xlib.h> 12 #include <X11/Xatom.h> 13 #include <X11/Xutil.h> 14 15 #include <stdlib.h> 16 #include <unistd.h> 17 #include <getopt.h> 18 #include <stdio.h> 19 #include <math.h> 20 #include <sys/time.h> 21 #include <string.h> 22 #include <stdbool.h> 23 #include <assert.h> 24 25 #define ALLOC_COUNT_MAX 256 26 #define ALLOC_SIZE_MAX 8000000 27 #define REALLOCS_COUNT 10000 28 #define PINNING_PERCENTAGE 0 29 #define DEFAULT_LOOP_COUNT 100 30 #define DEFAULT_CARVEOUT_AMT 80 31 #define SYS_ROOT "/sys/devices/platform/tegra-nvmap/misc/nvmap" 32 #define WINDOW_WIDTH 1024 33 #define WINDOW_HEIGHT 768 34 35 /* GART is 32mb, but is limited to 24mb per process */ 36 #define GART_FILL_SIZE 24 37 38 static int verbose = 0; 39 static const char space[] = "************************************************"; 40 static GLuint vsObj, fsObj, programObj; 41 static Display *x_display; 42 static Window win; 43 static EGLDisplay egl_display; 44 static EGLContext egl_context; 45 static EGLSurface egl_surface; 46 47 const char vertex_src [] = 48 " \ 49 uniform mat4 transformMatrix; \ 50 attribute vec4 position; \ 51 attribute vec4 tcoord; \ 52 varying vec2 st; \ 53 \ 54 void main() \ 55 { \ 56 gl_Position = transformMatrix * position; \ 57 st = tcoord.st; \ 58 } \ 59 "; 60 61 const char fragment_src [] = 62 " \ 63 precision highp float; \ 64 uniform sampler2D tex; \ 65 varying vec2 st; \ 66 \ 67 void main() \ 68 { \ 69 gl_FragColor = texture2D(tex, st); \ 70 } \ 71 "; 72 73 static const GLfloat sVertData[] = { 74 -1, -1, 0, 1, 75 1, -1, 0, 1, 76 -1, 1, 0, 1, 77 1, 1, 0, 1 78 }; 79 80 /* 81 * This function gets the available amount of carveout from sysfs. 82 */ 83 int GetCarveoutTotalSize(unsigned int *total) 84 { 85 FILE* f; 86 char buffer[256]; 87 88 sprintf(buffer, "%s/heap-generic-0/total_size", SYS_ROOT); 89 90 f = fopen(buffer, "r"); 91 if(!f) { 92 printf("Failed to open %s", buffer); 93 return -1; 94 } 95 96 fscanf(f, "%d", total); 97 fclose(f); 98 99 return 0; 100 } 101 102 /* 103 * This function gets the free amount of carveout from sysfs. 104 */ 105 int GetCarveoutFreeSize(unsigned int *free) 106 { 107 FILE* f; 108 char buffer[256]; 109 110 sprintf(buffer, "%s/heap-generic-0/free_size", SYS_ROOT); 111 112 /* 113 * Make sure all previous rendering calls have completed so we 114 * can query free carveout size 115 */ 116 glFinish(); 117 118 f = fopen(buffer, "r"); 119 if(!f) { 120 printf("Failed to open %s", buffer); 121 return -1; 122 } 123 124 fscanf(f, "%d", free); 125 fclose(f); 126 127 return 0; 128 } 129 130 /* 131 * This function creates an RGBA texture with a given width and height. 132 * Return value: handle to texture 133 */ 134 static GLuint CreateTexture(int width, int height, int number) 135 { 136 char *data = NULL; 137 int x, y, bytesPerPixel; 138 GLuint tex; 139 140 assert(number == (number & 0xF)); 141 142 /* There are 4 bytes per pixel for GL_RGBA & GL_UNSIGNED_BYTE */ 143 bytesPerPixel = 4; 144 145 data = (char *)malloc((size_t)(width*height*bytesPerPixel)); 146 if (!data) 147 return -1; 148 149 for (x = 0; x < width; x++) { 150 for (y = 0 ; y < height; y++) { 151 int idx = (y*width + x)*bytesPerPixel; 152 data[idx] = (number * 0xF) & 0xFF; 153 data[idx+1] = (number * 0xF) & 0xFF; 154 data[idx+2] = 0xFF; 155 data[idx+3] = 0xFF; 156 } 157 } 158 159 /* create texture */ 160 glGenTextures(1, &tex); 161 if (glGetError() != GL_NO_ERROR) 162 goto fail; 163 164 glActiveTexture(GL_TEXTURE0); 165 if (glGetError() != GL_NO_ERROR) 166 goto fail; 167 168 glBindTexture(GL_TEXTURE_2D, tex); 169 if (glGetError() != GL_NO_ERROR) 170 goto fail; 171 172 glTexImage2D( 173 /* target */ GL_TEXTURE_2D, 174 /* level */ 0, 175 /* internalformat */ (GLint)GL_RGBA, 176 /* width */ width, 177 /* height */ height, 178 /* border */ 0, 179 /* format */ GL_RGBA, 180 /* type */ GL_UNSIGNED_BYTE, 181 /* pixels */ data); 182 183 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 184 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 185 186 goto done; 187 188 fail: 189 tex = -1; 190 done: 191 free(data); 192 193 return tex; 194 } 195 196 /* 197 * Fill in the result array with an identity matrix. 198 */ 199 static void LoadIdentity(GLfloat *result) 200 { 201 memset(result, 0x0, 16*4); 202 result[0] = 1; 203 result[5] = 1; 204 result[10] = 1; 205 result[15] = 1; 206 } 207 208 /* 209 * Fill in the result array with a scaling matrix. 210 */ 211 static void Scale(GLfloat *result, GLfloat sx, GLfloat sy, GLfloat sz) 212 { 213 result[0] *= sx; 214 result[1] *= sx; 215 result[2] *= sx; 216 result[3] *= sx; 217 218 result[4] *= sy; 219 result[5] *= sy; 220 result[6] *= sy; 221 result[7] *= sy; 222 223 result[8] *= sz; 224 result[9] *= sz; 225 result[10] *= sz; 226 result[11] *= sz; 227 } 228 229 /* 230 * Fill in the result array with a transformation matrix. 231 */ 232 static void Translate(GLfloat *result, GLfloat tx, GLfloat ty, GLfloat tz) 233 { 234 result[12] += (result[0] * tx + result[4] * ty + result[8] * tz); 235 result[13] += (result[1] * tx + result[5] * ty + result[9] * tz); 236 result[14] += (result[2] * tx + result[6] * ty + result[10] * tz); 237 result[15] += (result[3] * tx + result[7] * ty + result[11] * tz); 238 } 239 240 /* 241 * This function takes a given texture array and displays the textures in it. 242 * All textures need to be the same size, width x height. 243 */ 244 int ShowTextures(GLuint *tex, int count, int width, int height) 245 { 246 GLint texSampler; 247 GLint transformMatrixUniform; 248 GLfloat vertSTData[8]; 249 int i; 250 GLfloat transformMatrix[16]; 251 int cols = (int)sqrtf(count); 252 struct timeval tv; 253 int rnd; 254 255 gettimeofday(&tv, NULL); 256 rnd = tv.tv_sec * 1000; 257 258 /* Texture coords */ 259 vertSTData[0] = 0; 260 vertSTData[1] = 0; 261 vertSTData[2] = width; 262 vertSTData[3] = 0; 263 vertSTData[4] = 0; 264 vertSTData[5] = height; 265 vertSTData[6] = width; 266 vertSTData[7] = height; 267 268 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, vertSTData); 269 texSampler = glGetUniformLocation(programObj, "tex"); 270 transformMatrixUniform = glGetUniformLocation(programObj, 271 "transformMatrix"); 272 glUniform1i(texSampler, 0); 273 274 /* Draw texture rectangles */ 275 LoadIdentity(transformMatrix); 276 Scale(transformMatrix, 4.0f/cols, 4.0f/cols, 4.0f/cols); 277 Translate(transformMatrix, -cols - 1.0f, cols - 1.0f, 0.0f); 278 for (i = 0; i < count; i++) { 279 rnd = rnd * 69069 + 69069; 280 if(((rnd / 1217) & 255) > 128) { 281 Translate(transformMatrix, 2.0f, 0.0f, 0.0f); 282 glUniformMatrix4fv(transformMatrixUniform, 1, GL_FALSE, 283 transformMatrix); 284 glBindTexture(GL_TEXTURE_2D, tex[i]); 285 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 286 if (((i+1) % cols) == 0) { 287 Translate(transformMatrix, -2.0f*cols, -2.0f, 288 0.0f); 289 } 290 } 291 } 292 293 /* Issue flush to ensure all gl commands are sent to processing */ 294 glFlush(); 295 296 return 0; 297 } 298 299 /* 300 * This function runs a single phase of the test. 301 * Return value: 0 on success 302 */ 303 int RunPhase(int phase, int phase_width, int phase_height, int texture_count, 304 int texture_size, GLuint *tex) 305 { 306 unsigned int phase_size = texture_count * texture_size; 307 unsigned int freeBefore, freeAfter; 308 GLenum errCode = GL_NO_ERROR; 309 int brokeAt = 0; 310 unsigned int displacement; 311 int i; 312 313 printf("%.*s\n", 48, space); 314 printf("Phase %d: Allocating small %d (%dMB) [%dMB] textures\n", 315 phase, texture_count, texture_size, 316 texture_count * texture_size); 317 printf("%.*s\n", 48, space); 318 319 /* Create texture */ 320 printf("allocating textures.. (%d,%d)\n", phase_width, phase_height); 321 GetCarveoutFreeSize(&freeBefore); 322 for (i = 0; i < texture_count; i++) { 323 tex[i] = CreateTexture(phase_width - 1, phase_height - 1, 324 (i % 16)); 325 326 if (tex[i] < 0) { 327 printf("Failed to create texture.\n"); 328 brokeAt = i; 329 goto done; 330 } 331 332 errCode = glGetError(); 333 if (errCode != GL_NO_ERROR) { 334 printf("GL Error Occured : %d\n", errCode); 335 brokeAt = i; 336 goto done; 337 } 338 } 339 340 GetCarveoutFreeSize(&freeAfter); 341 /* Calculate difference in MB */ 342 displacement = (freeBefore - freeAfter) / (1024 * 1024); 343 344 if (displacement < phase_size) { 345 fprintf(stderr, "FAIL to alloc required mem from carveout.\n"); 346 fprintf(stderr, "Allocated %dMB instead of desired %dMB\n", 347 displacement, phase_size); 348 brokeAt = texture_count - 1; 349 goto done; 350 } 351 352 if (verbose) { 353 unsigned int free; 354 GetCarveoutFreeSize(&free); 355 printf("CarveOut free after phase %d allocation: %d\n", 356 phase, free); 357 } 358 359 done: 360 return brokeAt; /* brokeAt is 0 unless and error happened */ 361 } 362 363 /* 364 * This function runs the actual test, drawing the texture rects. 365 * Return value: 0 on success 366 */ 367 int RunTest(int carveout_percent) 368 { 369 GLuint phase1_tex[ALLOC_COUNT_MAX]; 370 GLuint phase2_tex[ALLOC_COUNT_MAX / 4]; 371 GLuint phase3_tex[ALLOC_COUNT_MAX / 8]; 372 int i; 373 unsigned int allocCount = 0; 374 unsigned int carveoutTotal; 375 unsigned int carveoutFree; 376 int allocatedMemoryLimit; 377 GLenum errCode = GL_NO_ERROR; 378 int phase = 0; 379 int brokeAt = 0; 380 381 if(GetCarveoutTotalSize(&carveoutTotal) || 382 GetCarveoutFreeSize(&carveoutFree)) { 383 printf("Failed to read carveout stats\n"); 384 return -1; 385 } 386 387 printf("CarveOut total before cleanup: %d [%dMB]\n", carveoutTotal, 388 carveoutTotal / (1024*1024)); 389 printf("CarveOut free before cleanup: %d [%dMB]\n", carveoutFree, 390 carveoutFree / (1024*1024)); 391 392 /* Memory is in units of bytes */ 393 394 allocatedMemoryLimit = (int)((carveoutFree / 100) * carveout_percent); 395 allocCount = allocatedMemoryLimit / 1048576; /* 1 mb */ 396 allocCount = (allocCount / 4) * 4; /* always a multiple of 4. */ 397 398 phase = 1; 399 errCode = RunPhase(phase, 512, 512, allocCount, 1, phase1_tex); 400 if (errCode) { 401 brokeAt = errCode; 402 goto cleanup_phase1; 403 } 404 405 printf("freeing first 3 of every 4 textures from phase 1 [%dMB]\n", 406 (allocCount * 3 / 4) * 1); 407 for (i = 0; i < allocCount; i++) { 408 if ((i + 1) % 4 == 0) continue; 409 glDeleteTextures(1, &phase1_tex[i]); 410 } 411 412 /* 413 * Make sure all previous rendering calls have completed so we 414 * can query free carveout size 415 */ 416 glFinish(); 417 418 if (verbose) { 419 unsigned int free; 420 GetCarveoutFreeSize(&free); 421 printf("CarveOut free after phase 1 freeing: %d\n", free); 422 } 423 424 /* 425 * prepare for phase 2 426 * we free'd up 3/4 of the phase 1 handles, and then these will be 427 * 4x as large, so the number will further shrink so 3/16 428 */ 429 allocCount = (allocCount * 3) / 16; 430 phase = 2; 431 errCode = RunPhase(phase, 1024, 1024, allocCount, 4, phase2_tex); 432 if (errCode) { 433 brokeAt = errCode; 434 goto cleanup_phase2; 435 } 436 437 printf("freeing every other texture from phase 2 [%dMB]\n", 438 (allocCount / 2) * 4 ); 439 for (i = 0; i < allocCount; i++) { 440 if (i % 2 != 0) continue; 441 glDeleteTextures(1, &phase2_tex[i]); 442 } 443 444 /* 445 * Make sure all previous rendering calls have completed so we 446 * can query free carveout size 447 */ 448 glFinish(); 449 450 if (verbose) { 451 unsigned int free; 452 GetCarveoutFreeSize(&free); 453 printf("CarveOut free after phase 2 freeing: %d\n", free); 454 } 455 456 /* 457 * prepare for phase 3 458 * we free'd up 1/2 of the phase 2 handles, and then these will be 459 * 2x as large, so the number will further shrink so 1/4 460 */ 461 allocCount = (allocCount / 4); 462 phase = 3; 463 errCode = RunPhase(phase, 2048, 1024, allocCount, 8, phase3_tex); 464 if (errCode) { 465 brokeAt = errCode; 466 goto cleanup_phase3; 467 } 468 469 printf("%.*s\n", 48, space); 470 printf("Test Complete \n"); 471 printf("%.*s\n", 48, space); 472 473 cleanup_phase3: 474 printf("freeing last textures from phase 3\n"); 475 for (i = 0; i < (brokeAt ? brokeAt : allocCount); i++) 476 glDeleteTextures(1, &phase3_tex[i]); 477 478 cleanup_phase2: 479 printf("freeing last textures from phase 2\n"); 480 if (phase == 2 && errCode != GL_NO_ERROR) 481 for (i = 0; i < (brokeAt ? brokeAt : allocCount); i++) 482 glDeleteTextures(1, &phase2_tex[i]); 483 else 484 for (i = 0; i < allocCount; i += 2) 485 glDeleteTextures(1, &phase2_tex[i]); 486 487 cleanup_phase1: 488 printf("freeing last textures from phase 1\n"); 489 if (phase == 1 && errCode != GL_NO_ERROR) 490 for (i = 0; i < (brokeAt ? brokeAt : allocCount); i++) 491 glDeleteTextures(1, &phase1_tex[i]); 492 else 493 for (i = 3; i < allocCount; i += 4) 494 glDeleteTextures(1, &phase1_tex[i]); 495 496 return (errCode == GL_NO_ERROR ? 0 : -1); 497 } 498 499 /* 500 * This function prints the info log for a given shader (from handle). 501 */ 502 void PrintShaderInfoLog(GLuint shader) 503 { 504 GLint length; 505 506 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); 507 508 if (length) { 509 char buffer[length]; 510 glGetShaderInfoLog(shader, length, NULL, buffer); 511 printf("shader info: %s\n", buffer); 512 } 513 } 514 515 GLuint LoadShader(const char *shader_src, GLenum type) 516 { 517 GLuint shader = glCreateShader(type); 518 GLint success; 519 520 glShaderSource(shader, 1, &shader_src, NULL); 521 glCompileShader(shader); 522 glGetShaderiv(shader, GL_COMPILE_STATUS, &success); 523 if (success != GL_TRUE) { 524 fprintf(stderr, "FAILED to compile shader. %d\n", success); 525 return success; 526 } 527 528 if (verbose) 529 PrintShaderInfoLog(shader); 530 531 return shader; 532 } 533 534 static void InitGraphicsState() 535 { 536 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, sVertData); 537 glEnableVertexAttribArray(0); 538 glEnableVertexAttribArray(1); 539 540 vsObj = LoadShader(vertex_src, GL_VERTEX_SHADER); 541 fsObj = LoadShader(fragment_src, GL_FRAGMENT_SHADER); 542 543 programObj = glCreateProgram(); 544 glAttachShader(programObj, vsObj); 545 glAttachShader(programObj, fsObj); 546 glBindAttribLocation(programObj, 0, "position"); 547 glBindAttribLocation(programObj, 1, "tcoord"); 548 glLinkProgram(programObj); 549 glUseProgram(programObj); 550 551 /* so that odd-sized RGB textures will work nicely */ 552 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 553 554 glDisable(GL_DEPTH_TEST); 555 } 556 557 void CleanupX() 558 { 559 XDestroyWindow(x_display, win); 560 XCloseDisplay(x_display); 561 } 562 563 void CleanupEgl() 564 { 565 eglDestroyContext(egl_display, egl_context); 566 eglDestroySurface(egl_display, egl_surface); 567 eglTerminate(egl_display); 568 } 569 570 int XInitialize(int x, int y, int width, int height) 571 { 572 Window root; 573 XSetWindowAttributes swa; 574 XSetWindowAttributes xattr; 575 Atom atom; 576 XWMHints hints; 577 int xres; 578 579 x_display = XOpenDisplay(NULL); 580 if (x_display == NULL) { 581 printf("Cannot connect to X server. Exiting...\n"); 582 return -1; 583 } 584 585 root = DefaultRootWindow(x_display); 586 swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask; 587 588 if (verbose) 589 printf("Creating window at (%d,%d) with w=%d, h=%d\n", 590 x, y, width, height); 591 592 win = XCreateWindow( 593 /* connection to x server */ x_display, 594 /* parent window */ root, 595 /* x coord, top left corner */ x, 596 /* y coord, top left corner */ y, 597 /* width of window */ width, 598 /* height of window */ height, 599 /* border width */ 0, 600 /* depth of window */ CopyFromParent, 601 /* window's class */ InputOutput, 602 /* visual type */ CopyFromParent, 603 /* valid attribute mask */ CWEventMask, 604 /* attributes */ &swa); 605 if (win == BadAlloc || 606 win == BadColor || 607 win == BadCursor || 608 win == BadMatch || 609 win == BadPixmap || 610 win == BadValue || 611 win == BadWindow) { 612 fprintf(stderr, "FAILED to create X window\n"); 613 return -1; 614 } 615 616 xattr.override_redirect = false; 617 xres = XChangeWindowAttributes(x_display, win, CWOverrideRedirect, 618 &xattr); 619 if (xres == BadAccess || 620 xres == BadColor || 621 xres == BadCursor || 622 xres == BadMatch || 623 xres == BadPixmap || 624 xres == BadValue || 625 xres == BadWindow) { 626 fprintf(stderr, "FAIL changing X win attribs: %d\n", xres); 627 goto fail; 628 } 629 630 atom = XInternAtom(x_display, "_NET_WM_STATE_FULLSCREEN", true); 631 632 hints.input = true; 633 hints.flags = InputHint; 634 xres = XSetWMHints(x_display, win, &hints); 635 if (xres == BadAlloc || xres == BadWindow) { 636 fprintf(stderr, "FAIL setting X WM hints: %d\n", xres); 637 goto fail; 638 } 639 640 xres = XMapWindow(x_display, win); 641 if (xres == BadAlloc || xres == BadWindow ) { 642 fprintf(stderr, "FAIL mapping X window: %d\n", xres); 643 goto fail; 644 } 645 646 xres = XStoreName(x_display, win, "GLES2 Texture Test"); 647 if (xres == BadAlloc || xres == BadWindow) { 648 fprintf(stderr, "FAIL storing X window name: %d\n", xres); 649 goto fail; 650 } 651 652 return 0; 653 654 fail: 655 CleanupX(); 656 657 return -1; 658 } 659 660 661 int EglInitialize() 662 { 663 EGLConfig config; 664 EGLint numConfig; 665 666 EGLint attr[] = { 667 EGL_BUFFER_SIZE, 16, 668 EGL_RENDERABLE_TYPE, 669 EGL_OPENGL_ES2_BIT, 670 EGL_NONE 671 }; 672 673 EGLint ctxattr[] = { 674 EGL_CONTEXT_CLIENT_VERSION, 2, 675 EGL_NONE 676 }; 677 678 egl_display = eglGetDisplay((EGLNativeDisplayType)x_display); 679 if (egl_display == EGL_NO_DISPLAY) { 680 fprintf(stderr, "EGL failed to obtain display. Exiting...\n"); 681 return -1; 682 } 683 684 if ( !eglInitialize(egl_display, NULL, NULL)) { 685 fprintf(stderr, "EGL failed to initialize. Exiting...\n"); 686 return -1; 687 } 688 689 if ( !eglChooseConfig(egl_display, attr, &config, 1, &numConfig)) { 690 fprintf(stderr, "EGL failed to choose config. Exiting...\n"); 691 return -1; 692 } 693 694 if (numConfig != 1) { 695 fprintf(stderr, "EGL failed got %d > 1 Exiting...\n", 696 numConfig); 697 return -1; 698 } 699 700 egl_surface = eglCreateWindowSurface(egl_display, config, win, NULL); 701 if (egl_surface == EGL_NO_SURFACE) { 702 fprintf(stderr, "EGL failed create window surface. Exiting\n"); 703 return -1; 704 } 705 706 egl_context = eglCreateContext(egl_display, config, EGL_NO_CONTEXT, 707 ctxattr); 708 if (egl_context == EGL_NO_CONTEXT) { 709 fprintf(stderr, "EGL failed to create context. Exiting...\n"); 710 return -1; 711 } 712 713 if ( !eglMakeCurrent(egl_display, egl_surface, egl_surface, 714 egl_context)) { 715 fprintf(stderr, "EGL failed make context current. Exiting\n"); 716 return -1; 717 } 718 719 return 0; 720 } 721 722 void PrintUsage() 723 { 724 printf("--------------------------------------------\n"); 725 printf("nvmap_carveout_compactor [options]\n"); 726 printf(" -h | --help - Show this help screen\n"); 727 printf(" -v | --verbose - Enables verbose prints\n"); 728 printf(" -l | --loop_count - # of times to loop [def: %d]\n", 729 DEFAULT_LOOP_COUNT); 730 printf(" -c | --carveout_percent - %% of free carveout [def : %d].\n", 731 DEFAULT_CARVEOUT_AMT); 732 } 733 734 int main(int argc, char *argv[]) 735 { 736 GLuint fill_tex[GART_FILL_SIZE]; 737 int failure = 0; 738 int failIndex = 0; 739 int i; 740 int loop_count = 1; 741 int option_index = 0; 742 GLenum errCode; 743 int x = 0, y = 0, width = WINDOW_WIDTH, height = WINDOW_HEIGHT; 744 int carveout_percent = 80; /* 80 percent of free carveout */ 745 746 static struct option long_options[] = { 747 {"help", no_argument, 0, 'h'}, 748 {"verbose", no_argument, 0, 'v'}, 749 {"loop_count", required_argument, 0, 'l'}, 750 {"carveout_percent", required_argument, 0, 'c'}, 751 {NULL, 0, NULL, 0} 752 }; 753 754 if (!getenv("DISPLAY")) { 755 fprintf(stderr, "FAIL: DISPLAY env variable not set.\n"); 756 failure = -1; 757 goto done; 758 } 759 760 while ((i = getopt_long(argc, argv, "hvl:c:", long_options, 761 &option_index)) != -1) 762 switch (i) { 763 case 'h': 764 PrintUsage(); 765 return 0; 766 case 'v': 767 verbose = 1; 768 break; 769 case 'l': 770 loop_count = atoi(optarg); 771 break; 772 case 'c': 773 carveout_percent = atoi(optarg); 774 break; 775 case '?': 776 printf("unknown option `\\x%x`.\n", optopt); 777 return 1; 778 default: 779 goto done; 780 } 781 782 failure = XInitialize(x, y, width, height); 783 if (failure) 784 goto done; 785 786 failure = EglInitialize(); 787 if (failure) 788 goto clean_x; 789 790 InitGraphicsState(); 791 792 glViewport(0, 0, width, height); 793 glClear(GL_COLOR_BUFFER_BIT); 794 795 printf("Test started pid = %d.\n", getpid()); 796 if (verbose) { 797 printf("Looping for %d iterations.\n", loop_count); 798 printf("Going to try to use %d%% of carveout during test.\n", 799 carveout_percent); 800 } 801 802 /* first need to allocate 24mb of textures to fill GART */ 803 printf("allocating textures to fill GART.. (%d,%d)\n", 804 512, 512); 805 806 /* Each process gets 24mb of GART */ 807 for (i = 0; i < GART_FILL_SIZE; i++) { 808 fill_tex[i] = CreateTexture(511, 511, (i % 16)); 809 810 errCode = glGetError(); 811 if (fill_tex[i] >= 0 && errCode == GL_NO_ERROR) 812 continue; 813 814 /* Some error occured when creating textures */ 815 printf("Failed to create texture.\n"); 816 if (errCode != GL_NO_ERROR) 817 printf("GL Error Occured : %d\n", errCode); 818 819 failIndex = i; 820 failure = -1; 821 goto done; 822 } 823 824 ShowTextures(fill_tex, GART_FILL_SIZE, 512, 512); 825 826 /* predefined resolutions to account for size */ 827 828 for(i = 0; i < loop_count; i++) { 829 failure |= RunTest(carveout_percent); 830 eglSwapBuffers(egl_display, egl_surface); 831 } 832 833 if (!failure) { 834 errCode = glGetError(); 835 if (errCode == GL_NO_ERROR) 836 failure = false; 837 else { 838 fprintf(stderr, "FAIL: GL Error Occured : %d\n", 839 errCode); 840 failure = 1; 841 } 842 } 843 844 CleanupEgl(); 845 clean_x: 846 CleanupX(); 847 done: 848 849 for (i = 0; i < (failIndex ? failIndex : GART_FILL_SIZE); i++) 850 glDeleteTextures(1, &fill_tex[i]); 851 852 if (!failure) 853 printf("Test completed [SUCCESS]: pid = %d\n", getpid()); 854 else 855 fprintf(stderr, "Test completed [FAIL]: pid = %d\n", getpid()); 856 857 return failure ? -1 : 0; 858 } 859 860