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