b0fa8b70bba7432fe0a0690ac0c2750ea6728569
[framework/graphics/cairo.git] / TC / perf / main.c
1 /*
2  * Cairo Performance Test Framework
3  * (c) 2012 Samsung Electronics, Inc.
4  * All rights reserved.
5  *
6  * Measures rendering performance for image, gl backends
7  *
8  * This software is a confidential and proprietary information of Samsung
9  * Electronics, Inc. ("Confidential Information"). You shall not disclose such
10  * Confidential Information and shall use it only in accordance with the terms
11  * of the license agreement you entered into with Samsung Electronics.
12  *
13  * Author: Dongyeon Kim <dy5.kim@samsung.com>
14  */
15
16 #include <Ecore_X.h>
17 #include <Elementary.h>
18 #include <EGL/egl.h>
19 #include <EGL/eglext.h>
20 #include <cairo.h>
21 #include <cairo-gl.h>
22
23 #define SURFACE_TYPE_IMAGE  0
24 #define SURFACE_TYPE_GL     1
25 #define TOTAL_TIME      100
26
27 int WIDTH, HEIGHT;
28
29 //Ecore Evas variables
30 Ecore_X_Window window;
31 Evas_Object *img;
32
33 //EGL variables
34 EGLDisplay egl_display;
35 EGLSurface egl_surface;
36 EGLContext egl_context;
37
38 //Cairo variables
39 cairo_device_t *cairo_device;
40 cairo_surface_t *cairo_surface;
41 cairo_t *cr;
42
43 Eina_Bool renderMain(void *data)
44 {
45     static int counter = 0;
46     static float totalTime = 0;
47     static float totalPaint = 0;
48     static float totalUpdate = 0;
49     struct timeval paintStart, paintStop, updateStop;
50
51     cairo_save(cr);
52     gettimeofday(&paintStart, NULL);
53     /* ########## PAINT : START ########## */
54     render(cr);
55     /* ########## PAINT : END ########## */
56     gettimeofday(&paintStop, NULL);
57     /* ########## UPDATE : START ########## */
58     if(cairo_surface_get_type(cairo_get_target(cr)) == CAIRO_SURFACE_TYPE_GL) {
59         cairo_gl_surface_swapbuffers(cairo_get_target(cr));
60     } else {
61         unsigned char *imageData = cairo_image_surface_get_data(cairo_get_target(cr));
62         evas_object_image_data_set(img, imageData);
63         evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
64         ecore_x_sync();
65     }
66     /* ########## UPDATE : END ########## */
67     gettimeofday(&updateStop, NULL);
68     cairo_restore(cr);
69
70     totalTime += updateStop.tv_usec - paintStart.tv_usec;
71     totalTime += (updateStop.tv_sec - paintStart.tv_sec)*1000000;
72     totalPaint += (paintStop.tv_usec - paintStart.tv_usec);
73     totalPaint += (paintStop.tv_sec - paintStart.tv_sec)*1000000;
74     totalUpdate += (updateStop.tv_usec - paintStop.tv_usec);
75     totalUpdate += (updateStop.tv_sec - paintStop.tv_sec)*1000000;
76     counter++;
77
78     if(counter == TOTAL_TIME)
79     {
80         float fps =  TOTAL_TIME / totalTime * 1000000.0f;
81         printf("fps = %0.2f\n", fps);
82         printf("average paint time = %0.1f usec, update time = %0.1f usec\n", totalPaint/TOTAL_TIME, totalUpdate/TOTAL_TIME);
83
84         elm_exit();
85         return 0;
86     }
87 }
88
89 void initELMWindow(int surface_type)
90 {
91     Evas_Object *win = elm_win_add(NULL, "cairotest", ELM_WIN_BASIC);
92     elm_win_autodel_set(win, EINA_TRUE);
93     ecore_x_screen_size_get(ecore_x_default_screen_get(), &WIDTH, &HEIGHT);
94     evas_object_resize(win, WIDTH, HEIGHT);
95     evas_object_show(win);
96
97     if (surface_type == SURFACE_TYPE_IMAGE) {
98         Evas_Object *img_win = elm_image_add(win);
99         img = evas_object_image_filled_add(evas_object_evas_get(img_win));
100         elm_win_resize_object_add(win, img);
101         evas_object_image_content_hint_set(img, EVAS_IMAGE_CONTENT_HINT_DYNAMIC);
102         evas_object_image_size_set(img, WIDTH, HEIGHT);
103         evas_object_image_colorspace_set(img, EVAS_COLORSPACE_ARGB8888);
104         evas_object_image_alpha_set(img, 0);
105         evas_object_show(img_win);
106         evas_object_show(img);
107     } else if(surface_type == SURFACE_TYPE_GL) {
108         window = ecore_x_window_new(0, 0, 0, WIDTH, HEIGHT);
109         ecore_x_icccm_title_set(window, "window");
110         ecore_x_netwm_name_set(window, "window");
111         ecore_x_input_multi_select(window);
112         ecore_x_icccm_transient_for_set(window, elm_win_xwindow_get(win));
113         ecore_x_window_show(window);
114     }
115 }
116
117 void initEGL(int surface_type)
118 {
119     if(surface_type != SURFACE_TYPE_GL)
120         return;
121
122     setenv("ELM_ENGINE", "gl", 1);
123
124     egl_display = eglGetDisplay((EGLNativeDisplayType) ecore_x_display_get());
125     if(egl_display == EGL_NO_DISPLAY)
126     {
127         printf("cannot get egl display\n");
128         exit(1);
129     }
130
131     EGLint major, minor;
132     if(!eglInitialize(egl_display, &major, &minor))
133     {
134         printf("cannot initialize egl\n");
135         exit(-1);
136     }
137
138     if(!eglBindAPI(EGL_OPENGL_ES_API))
139     {
140         printf("cannot bind egl to gles2 API\n");
141         exit(-1);
142     }
143
144     EGLConfig egl_config;
145     EGLint num;
146
147     EGLint attr[] =
148     {
149         EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
150         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
151         EGL_STENCIL_SIZE, 0,
152         EGL_SAMPLES, 4,
153         EGL_RED_SIZE, 8,
154         EGL_GREEN_SIZE, 8,
155         EGL_BLUE_SIZE, 8,
156         EGL_ALPHA_SIZE, 8,
157         EGL_NONE
158     };
159
160
161     if(!eglChooseConfig(egl_display, attr, &egl_config, 1, &num))
162     {
163         printf("cannot choose config\n");
164         exit(-1);
165     }
166
167     if(num != 1)
168     {
169         printf("did not get exactly one config = %d\n", num);
170         exit(-1);
171     }
172
173     egl_surface = eglCreateWindowSurface(egl_display,
174         egl_config, (NativeWindowType) window, NULL);
175     if(egl_surface == EGL_NO_SURFACE)
176     {
177         printf("cannot create surface\n");
178         exit(-1);
179     }
180
181     EGLint e = eglGetError();
182     //printf("egl error = %x\n", e);
183
184     EGLint ctxattr[] =
185     {
186         EGL_CONTEXT_CLIENT_VERSION, 2,
187         EGL_NONE
188     };
189
190     egl_context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, ctxattr);
191     if(egl_context == EGL_NO_CONTEXT)
192     {
193         EGLint e = eglGetError();
194         printf("cannot create context, error = %x\n", e);
195         exit(-1);
196     }
197
198     EGLint value;
199     EGLBoolean result = eglQueryContext(egl_display, egl_context, EGL_CONTEXT_CLIENT_VERSION, &value);
200     //printf("Context version = %x, result = %d\n", value, result);
201
202     eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
203 }
204
205 void destroyEGL(int surface_type)
206 {
207     if(surface_type != SURFACE_TYPE_GL)
208         return;
209
210     eglDestroyContext(egl_display, egl_context);
211     eglDestroySurface(egl_display, egl_surface);
212     eglTerminate(egl_display);
213 }
214
215 void initCairo(int surface_type)
216 {
217     if(surface_type == SURFACE_TYPE_IMAGE) {
218         printf("== CREATE IMAGE SURFACE ==\n");
219         cairo_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, WIDTH, HEIGHT);
220     } else if(surface_type == SURFACE_TYPE_GL) {
221         printf("== CREATE GL SURFACE ==\n");
222         setenv("CAIRO_GL_COMPOSITOR", "msaa", 1);
223         cairo_device = cairo_egl_device_create(egl_display, egl_context);
224         cairo_gl_device_set_thread_aware(cairo_device, 0);
225         cairo_surface = cairo_gl_surface_create_for_egl(cairo_device, egl_surface, WIDTH, HEIGHT);
226     }
227     cr = cairo_create(cairo_surface);
228 }
229
230 void destroyCairo(int surface_type)
231 {
232     cairo_surface_destroy(cairo_surface);
233     cairo_destroy(cr);
234
235     if(surface_type == SURFACE_TYPE_GL) {
236         cairo_device_destroy(cairo_device);
237     }
238 }
239
240 int main(int argc, char **argv)
241 {
242     int surface_type = SURFACE_TYPE_GL;
243
244     if(argc == 2)
245         surface_type = atoi(argv[1]);
246
247     elm_init(argc, argv);
248
249     initELMWindow(surface_type);
250     initEGL(surface_type);
251     initCairo(surface_type);
252
253     preRender(cr);
254     Ecore_Animator *animator = ecore_animator_add(renderMain, (void *)cr);
255     elm_run();
256     postRender(cr);
257
258     destroyCairo(surface_type);
259     destroyEGL(surface_type);
260     elm_shutdown();
261
262     return 0;
263 }
264