Home | History | Annotate | Download | only in src
      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