• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
GetCarveoutTotalSize(unsigned int * total)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  */
GetCarveoutFreeSize(unsigned int * free)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  */
CreateTexture(int width,int height,int number)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  */
LoadIdentity(GLfloat * result)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  */
Scale(GLfloat * result,GLfloat sx,GLfloat sy,GLfloat sz)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  */
Translate(GLfloat * result,GLfloat tx,GLfloat ty,GLfloat tz)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  */
ShowTextures(GLuint * tex,int count,int width,int height)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  */
RunPhase(int phase,int phase_width,int phase_height,int texture_count,int texture_size,GLuint * tex)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  */
RunTest(int carveout_percent)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  */
PrintShaderInfoLog(GLuint shader)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 
LoadShader(const char * shader_src,GLenum type)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 
InitGraphicsState()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 
CleanupX()557 void CleanupX()
558 {
559         XDestroyWindow(x_display, win);
560         XCloseDisplay(x_display);
561 }
562 
CleanupEgl()563 void CleanupEgl()
564 {
565         eglDestroyContext(egl_display, egl_context);
566         eglDestroySurface(egl_display, egl_surface);
567         eglTerminate(egl_display);
568 }
569 
XInitialize(int x,int y,int width,int height)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 
EglInitialize()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 
PrintUsage()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 
main(int argc,char * argv[])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