1 // This is core/vgui/tests/test_drawpix_speed.cxx
2 #include <iostream>
3 #ifdef _MSC_VER
4 # include "vcl_msvc_warnings.h"
5 #endif
6
7 #include "vpl/vpl.h"
8
9 #include "vul/vul_timer.h"
10
11 #include "vgui/vgui_gl.h"
12 #include "vgui/vgui_glx.h"
13 #include "vgui/vgui_utils.h"
14
15 #include <X11/Xlib.h>
16 #include <X11/Xutil.h>
17
18
19 #if VGUI_MESA
20 # include <GL/xmesa.h>
21 #endif
22
23 static int attribs[] = { GLX_RGBA, GLX_RED_SIZE, 5, GLX_GREEN_SIZE, 6, GLX_BLUE_SIZE, 5, GLX_DOUBLEBUFFER, None };
24
25 unsigned char global_data[512 * 512 * 4];
26
27 #if 0 // unused static function
28 static Bool WaitForNotify(Display *d, XEvent *e, char *arg)
29 {
30 return e->type == MapNotify && e->xmap.window == (Window)arg;
31 }
32 #endif // 0
33
34 double
fps_gl(GLenum pack_type,GLenum pix_type)35 fps_gl(GLenum pack_type, GLenum pix_type)
36 {
37 int draws = 0;
38 int elapsed;
39 vul_timer timer;
40 timer.mark();
41 do
42 {
43 glDrawPixels(512, 512, pack_type, pix_type, global_data);
44 ++draws;
45 elapsed = timer.real();
46 } while (elapsed < 3000);
47 return draws * 1000.0 / elapsed;
48 }
49
50
51 #ifdef HAS_HERMES
52 # include <Hermes/Hermes.h>
53 double
fps_hermes(float src_scale,float dest_scale,HermesFormat * src_format,XImage * backbuffer)54 fps_hermes(float src_scale, float dest_scale, HermesFormat * src_format, XImage * backbuffer)
55 {
56 HermesFormat * dest_format = Hermes_FormatNew(
57 backbuffer->bits_per_pixel, backbuffer->red_mask, backbuffer->green_mask, backbuffer->blue_mask, 0, 0);
58 HermesHandle converter = Hermes_ConverterInstance(HERMES_CONVERT_NORMAL);
59 Hermes_ConverterRequest(converter, src_format, dest_format);
60 int draws = 0;
61 int elapsed;
62 vul_timer timer;
63 int bytes_per_pixel = src_format->bits / 8;
64 int succeed;
65 do
66 {
67 succeed = Hermes_ConverterCopy(converter,
68 global_data,
69 0,
70 0,
71 (int)(src_scale * 512),
72 (int)(src_scale * 512),
73 512 * bytes_per_pixel,
74 backbuffer->data,
75 0,
76 0,
77 (int)(dest_scale * 512),
78 (int)(dest_scale * 512),
79 backbuffer->bytes_per_line);
80 if (!succeed)
81 return 0;
82 elapsed = timer.real();
83 ++draws;
84 } while (elapsed < 3000);
85 Hermes_ConverterReturn(converter);
86 Hermes_FormatFree(dest_format);
87 Hermes_FormatFree(src_format);
88 return draws * 1000.0 / elapsed;
89 }
90
91 double
fps_hermes_grey(float src_scale,float dest_scale,XImage * backbuffer)92 fps_hermes_grey(float src_scale, float dest_scale, XImage * backbuffer)
93 {
94 // special paletted case for 8-bit mode
95 HermesHandle palette = Hermes_PaletteInstance();
96 HermesFormat * dest_format = Hermes_FormatNew(
97 backbuffer->bits_per_pixel, backbuffer->red_mask, backbuffer->green_mask, backbuffer->blue_mask, 0, 0);
98 HermesFormat * src_format = Hermes_FormatNew(8, 0, 0, 0, 0, 1);
99 HermesHandle converter = Hermes_ConverterInstance(HERMES_CONVERT_NORMAL);
100 Hermes_ConverterRequest(converter, src_format, dest_format);
101 Hermes_ConverterPalette(converter, palette, palette); // last param is a dummy
102 int draws = 0;
103 int elapsed;
104 vul_timer timer;
105 int succeed;
106 do
107 {
108 succeed = Hermes_ConverterCopy(converter,
109 global_data,
110 0,
111 0,
112 (int)(src_scale * 512),
113 (int)(src_scale * 512),
114 512 * 1,
115 backbuffer->data,
116 0,
117 0,
118 (int)(dest_scale * 512),
119 (int)(dest_scale * 512),
120 backbuffer->bytes_per_line);
121 if (!succeed)
122 return 0;
123 elapsed = timer.real();
124 ++draws;
125 } while (elapsed < 3000);
126 Hermes_ConverterReturn(converter);
127 Hermes_PaletteReturn(palette);
128 Hermes_FormatFree(src_format);
129 Hermes_FormatFree(dest_format);
130 return draws * 1000.0 / elapsed;
131 }
132
133 #endif // HAS_HERMES
134
135 void
pattern_grey(unsigned char * data)136 pattern_grey(unsigned char * data)
137 {
138 for (int y = 0; y < 512; ++y)
139 {
140 for (int x = 0; x < 256; ++x)
141 {
142 data[y * 512 + 2 * x] = data[y * 512 + 2 * x + 1] = static_cast<unsigned char>(x);
143 }
144 }
145 }
146
147 void
pattern_RGB16(unsigned char * data,bool little_endian)148 pattern_RGB16(unsigned char * data, bool little_endian)
149 {
150 unsigned short r, g, b;
151 unsigned short * my_data = (unsigned short *)data;
152 if (little_endian)
153 {
154 r = 0x001f;
155 g = 0x07e0;
156 b = 0xf800;
157 }
158 else
159 {
160 r = 0xf800;
161 g = 0x07e0;
162 b = 0x001f;
163 }
164 for (int y = 0; y < 512; ++y)
165 {
166 for (int x = 0; x < 170; ++x)
167 {
168 my_data[y * 512 + x] = r;
169 my_data[y * 512 + 170 + x] = g;
170 my_data[y * 512 + 340 + x] = b;
171 }
172 }
173 }
174
175 void
pattern_RGB24(unsigned char * data,bool)176 pattern_RGB24(unsigned char * data, bool /*little_endian*/)
177 {
178 for (int n = 0; n < 512 * 512 * 3; ++n)
179 data[n] = 0;
180
181 for (int y = 0; y < 512; ++y)
182 {
183 for (int x = 0; x < 170; ++x)
184 {
185 data[y * 512 * 3 + 3 * x] = 255;
186 data[y * 512 * 3 + 170 * 3 + 3 * x + 1] = 255;
187 data[y * 512 * 3 + 340 * 3 + 3 * x + 2] = 255;
188 }
189 }
190 }
191
192 void
pattern_RGB32(unsigned char * data,bool little_endian)193 pattern_RGB32(unsigned char * data, bool little_endian)
194 {
195 unsigned long r, g, b;
196 unsigned long * my_data = (unsigned long *)data;
197 if (little_endian)
198 {
199 r = 0x000000ff;
200 g = 0x0000ff00;
201 b = 0x00ff0000;
202 }
203 else
204 {
205 r = 0xff000000;
206 g = 0x00ff0000;
207 b = 0x0000ff00;
208 }
209 for (int y = 0; y < 512; ++y)
210 {
211 for (int x = 0; x < 170; ++x)
212 {
213 my_data[y * 512 + x] = r;
214 my_data[y * 512 + 170 + x] = g;
215 my_data[y * 512 + 340 + x] = b;
216 }
217 }
218 }
219
220
221 // Try to do the #ifdef .. #endif madness once and for all here :
222 static struct
223 {
224 GLenum format;
225 GLenum type;
226 char const * nfixed;
227 char const * pretty;
228 }
229
230 ft_tab[] = { { GL_LUMINANCE, GL_UNSIGNED_BYTE, "LUM ", "8bit greyscale" },
231 { GL_RGB, GL_UNSIGNED_BYTE, "RGB ", "24bit 888 RGB" },
232 { GL_RGBA, GL_UNSIGNED_BYTE, "RGBA ", "32bit 8888 RGBA" },
233 #if defined(GL_VERSION_1_2)
234 { GLenum(GL_RGB), GLenum(GL_UNSIGNED_SHORT_5_6_5), "RGB565", "16bit 565 RGB" },
235 { GLenum(GL_BGR), GLenum(GL_UNSIGNED_BYTE), "BGR ", "24bit 888 BGR" },
236 { GLenum(GL_BGRA), GLenum(GL_UNSIGNED_BYTE), "BGRA ", "32bit 8888 BGRA" },
237 #endif
238 #if defined(GL_ABGR_EXT) || defined(GL_EXT_abgr)
239 { GLenum(GL_ABGR_EXT), GLenum(GL_UNSIGNED_BYTE), "ABGR ", "32bit ABGR" },
240 #endif
241 { GL_NONE, GL_NONE, 0, 0 } };
242
243 static const int ft_size = sizeof(ft_tab) / sizeof(ft_tab[0]) - 1;
244
245
246 int
main()247 main()
248 {
249 // GLX window code straight out of http://www.eecs.tulane.edu/www/graphics/doc/OpenGL-Man-Pages/glXIntro.html
250 std::cerr << "Opening double-buffered, RGBA GLX context...\n\n";
251 Display * display = XOpenDisplay(0);
252 XVisualInfo * visualinfo = glXChooseVisual(display, DefaultScreen(display), attribs);
253 GLXContext context = glXCreateContext(display, visualinfo, 0, GL_TRUE);
254
255 Colormap cmap = XCreateColormap(display, RootWindow(display, visualinfo->screen), visualinfo->visual, AllocNone);
256
257 // create a window
258 XSetWindowAttributes swa;
259 swa.colormap = cmap;
260 swa.border_pixel = 0;
261 swa.event_mask = StructureNotifyMask;
262 Window window = XCreateWindow(display,
263 RootWindow(display, visualinfo->screen),
264 0,
265 0,
266 512,
267 512,
268 0,
269 visualinfo->depth,
270 InputOutput,
271 visualinfo->visual,
272 CWBorderPixel | CWColormap | CWEventMask,
273 &swa);
274
275 glXMakeCurrent(display, window, context);
276
277 bool little_endian = (ImageByteOrder(display) == LSBFirst);
278 std::cerr << "GL_VERSION : " << (const char *)glGetString(GL_VERSION) << '\n'
279 << "GL_RENDERER : " << (const char *)glGetString(GL_RENDERER) << "\n\n"
280 << "X Display -\n"
281 << " byte-order : " << (little_endian ? "little" : "big") << "-endian\n\n"
282 << "XVisualInfo -\n"
283 << " depth : " << visualinfo->depth << std::endl
284 << " red-mask : " << std::hex << visualinfo->red_mask << '\n'
285 << " green-mask : " << std::hex << visualinfo->green_mask << '\n'
286 << " blue-mask : " << std::hex << visualinfo->blue_mask << "\n\n"
287 << "GL Gets -\n";
288 GLint data_int;
289 glGetIntegerv(GL_RED_BITS, &data_int);
290 std::cerr << " red-bits : " << data_int << std::endl;
291 glGetIntegerv(GL_GREEN_BITS, &data_int);
292 std::cerr << " green-bits : " << data_int << std::endl;
293 glGetIntegerv(GL_BLUE_BITS, &data_int);
294 std::cerr << " blue-bits : " << data_int << std::endl;
295 glGetIntegerv(GL_ALPHA_BITS, &data_int);
296 std::cerr << " alpha-bits : " << data_int << std::endl;
297
298 #if VGUI_MESA
299 {
300 std::cerr << std::endl;
301 XMesaBuffer mesabuf = XMesaGetCurrentBuffer();
302 Pixmap p;
303 XImage * backbuffer;
304 XMesaGetBackBuffer(mesabuf, &p, &backbuffer);
305
306 bool little_endian = (backbuffer->byte_order == LSBFirst);
307 std::cerr << "Mesa backbuffer XImage -\n"
308 << " depth : " << backbuffer->depth << std::endl
309 << " bits-per-pixel : " << backbuffer->bits_per_pixel << std::endl
310 << " byte_order : " << (little_endian ? "little" : "big") << "-endian\n"
311 << " bytes-per-line : " << backbuffer->bytes_per_line << std::endl
312 << " red-mask : " << std::hex << backbuffer->red_mask << '\n'
313 << " green-mask : " << std::hex << backbuffer->green_mask << '\n'
314 << " blue-mask : " << std::hex << backbuffer->blue_mask << '\n';
315 }
316 #endif
317
318 vgui_utils::set_glViewport(0, 0, 512, 512);
319 glMatrixMode(GL_PROJECTION);
320 glLoadIdentity();
321 glOrtho(0.0, 512, 0.0, 512, -1.0, 1.0);
322 glMatrixMode(GL_MODELVIEW);
323 glLoadIdentity();
324
325 glRasterPos2i(0, 0);
326
327 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
328 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
329 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // gl_direct_DrawPixels needs this set to 1 !!
330 glPixelStorei(GL_UNPACK_ROW_LENGTH, 512);
331
332 glDisable(GL_ALPHA_TEST);
333 glDisable(GL_BLEND);
334 glDisable(GL_DEPTH_TEST);
335
336 vgui_utils::set_glPixelZoom(1.0, 1.0);
337 glDrawBuffer(GL_BACK_LEFT);
338
339 #if 0 // commented out
340 // Render from all formats to check endian settings
341 XMapWindow(display, window);
342 XEvent event;
343 XIfEvent(display, &event, WaitForNotify, (char*)window);
344 std::cerr << "Rendering from 8-bit grey-level...\n";
345 pattern_grey(global_data);
346 glDrawPixels(512,512,GL_LUMINANCE,GL_UNSIGNED_BYTE,global_data);
347 glXSwapBuffers(display, window);
348 vpl_sleep(1);
349 # if defined(GL_VERSION_1_2)
350 std::cerr << "Rendering from 16-bit 565 RGB...\n";
351 pattern_RGB16(global_data, little_endian);
352 glDrawPixels(512,512,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,global_data);
353 glXSwapBuffers(display, window);
354 vpl_sleep(1);
355 # endif
356 std::cerr << "Rendering from 24-bit 888 RGB...\n";
357 pattern_RGB24(global_data, little_endian);
358 glDrawPixels(512,512,GL_RGB,GL_UNSIGNED_BYTE,global_data);
359 glXSwapBuffers(display, window);
360 vpl_sleep(1);
361 std::cerr << "Rendering from 32-bit 8888 RGBA...\n";
362 pattern_RGB32(global_data, little_endian);
363 glDrawPixels(512,512,GL_RGBA,GL_UNSIGNED_BYTE,global_data);
364 glXSwapBuffers(display, window);
365 vpl_sleep(1);
366 #endif // end commented out
367
368 {
369 std::cerr << "\nglClear - ";
370 int draws = 0;
371 int elapsed;
372 vul_timer timer;
373 do
374 {
375 glClear(GL_COLOR_BUFFER_BIT);
376 elapsed = timer.real();
377 ++draws;
378 } while (elapsed < 5000);
379 std::cerr << 512 * 512 * draws / (elapsed / 1000.0) << " pixels per second\n";
380 }
381 {
382 std::cerr << "\nglDrawPixels -\n";
383 double fps;
384 std::cerr << "source -";
385 for (int i = 0; i < ft_size; ++i)
386 std::cerr << " " << ft_tab[i].nfixed;
387 std::cerr << std::endl
388 << "source - LUM RGB565 RGB BGR RGBA BGRA ABGR\n"
389 << "zoom 1.00x ";
390 for (int i = 0; i < ft_size; ++i)
391 {
392 fps = fps_gl(ft_tab[i].format, ft_tab[i].type);
393 std::cerr << 512 * 512 * fps << " ";
394 }
395 std::cerr << "\nzoom 1.90x ";
396 vgui_utils::set_glPixelZoom(1.9f, 1.9f);
397 for (int i = 0; i < ft_size; ++i)
398 {
399 fps = fps_gl(ft_tab[i].format, ft_tab[i].type);
400 std::cerr << 512 * 512 * fps << " ";
401 }
402 std::cerr << "\nzoom 0.51x ";
403 vgui_utils::set_glPixelZoom(0.51f, 0.51f);
404 for (int i = 0; i < ft_size; ++i)
405 {
406 fps = fps_gl(ft_tab[i].format, ft_tab[i].type);
407 std::cerr << 0.51 * 0.51 * 512 * 512 * fps << " ";
408 }
409 std::cerr << std::endl;
410 }
411
412 #if defined(HAS_HERMES) && VGUI_MESA
413 {
414 XMesaBuffer mesabuf = XMesaGetCurrentBuffer();
415 Pixmap p;
416 XImage * backbuffer;
417 XMesaGetBackBuffer(mesabuf, &p, &backbuffer);
418
419 Hermes_Init();
420 HermesFormat * dest_format = Hermes_FormatNew(
421 backbuffer->bits_per_pixel, backbuffer->red_mask, backbuffer->green_mask, backbuffer->blue_mask, 0, 0);
422 {
423 std::cerr << "\nHermesClear - ";
424 HermesHandle clearer = Hermes_ClearerInstance();
425 Hermes_ClearerRequest(clearer, dest_format);
426 int draws = 0;
427 int elapsed;
428 vul_timer timer;
429 do
430 {
431 Hermes_ClearerClear(clearer, backbuffer->data, 0, 0, 512, 512, backbuffer->bytes_per_line, 0, 0, 0, 0);
432 elapsed = timer.real();
433 ++draws;
434 } while (elapsed < 3000);
435 std::cerr << (512 * 512 * draws) / (elapsed / 1000.0) << " pixels per second\n";
436 Hermes_ClearerReturn(clearer);
437 }
438 {
439 std::cerr << "\nHermesConverter -\n";
440 HermesFormat * src_format;
441 double fps;
442 std::cerr << "source - LUM OxRGB565 OxRGB OxBGR Ox_RGB 0x_BGR\n";
443
444 std::cerr << "zoom 1.00x ";
445 fps = fps_hermes_grey(1.0, 1.0, backbuffer);
446 std::cerr << 12 * 512 * fps << " ";
447
448 src_format = Hermes_FormatNew(16, 0xf800, 0x07e0, 0x001f, 0, 0);
449 fps = fps_hermes(1.0, 1.0, src_format, backbuffer);
450 std::cerr << 12 * 512 * fps << " ";
451 src_format = Hermes_FormatNew(24, 0xff0000, 0xff00, 0xff, 0, 0);
452 fps = fps_hermes(1.0, 1.0, src_format, backbuffer);
453 std::cerr << 12 * 512 * fps << " ";
454 src_format = Hermes_FormatNew(24, 0xff, 0xff00, 0xff0000, 0, 0);
455 fps = fps_hermes(1.0, 1.0, src_format, backbuffer);
456 std::cerr << 12 * 512 * fps << " ";
457 src_format = Hermes_FormatNew(32, 0xff0000, 0xff00, 0xff, 0, 0);
458 fps = fps_hermes(1.0, 1.0, src_format, backbuffer);
459 std::cerr << 12 * 512 * fps << " ";
460 src_format = Hermes_FormatNew(32, 0xff, 0xff00, 0xff0000, 0, 0);
461 fps = fps_hermes(1.0, 1.0, src_format, backbuffer);
462 std::cerr << 12 * 512 * fps << '\n';
463
464 std::cerr << "zoom 1.90x ";
465 fps = fps_hermes_grey(0.526, 1.0, backbuffer);
466 std::cerr << 12 * 512 * fps << " ";
467
468 src_format = Hermes_FormatNew(16, 0xf800, 0x07e0, 0x001f, 0, 0);
469 fps = fps_hermes(0.526, 1.0, src_format, backbuffer);
470 std::cerr << 12 * 512 * fps << " ";
471 src_format = Hermes_FormatNew(24, 0xff0000, 0xff00, 0xff, 0, 0);
472 fps = fps_hermes(0.526, 1.0, src_format, backbuffer);
473 std::cerr << 12 * 512 * fps << " ";
474 src_format = Hermes_FormatNew(24, 0xff, 0xff00, 0xff0000, 0, 0);
475 fps = fps_hermes(0.526, 1.0, src_format, backbuffer);
476 std::cerr << 12 * 512 * fps << " ";
477 src_format = Hermes_FormatNew(32, 0xff0000, 0xff00, 0xff, 0, 0);
478 fps = fps_hermes(0.526, 1.0, src_format, backbuffer);
479 std::cerr << 12 * 512 * fps << " ";
480 src_format = Hermes_FormatNew(32, 0xff, 0xff00, 0xff0000, 0, 0);
481 fps = fps_hermes(0.526, 1.0, src_format, backbuffer);
482 std::cerr << 12 * 512 * fps << '\n';
483
484 std::cerr << "zoom 0.51x ";
485 fps = fps_hermes_grey(1.0, 0.51, backbuffer);
486 std::cerr << .51 * 0.51 * 512 * 512 * fps << " ";
487
488 src_format = Hermes_FormatNew(16, 0xf800, 0x07e0, 0x001f, 0, 0);
489 fps = fps_hermes(1.0, 0.51, src_format, backbuffer);
490 std::cerr << .51 * 0.51 * 512 * 512 * fps << " ";
491 src_format = Hermes_FormatNew(24, 0xff0000, 0xff00, 0xff, 0, 0);
492 fps = fps_hermes(1.0, 0.51, src_format, backbuffer);
493 std::cerr << .51 * 0.51 * 512 * 512 * fps << " ";
494 src_format = Hermes_FormatNew(24, 0xff, 0xff00, 0xff0000, 0, 0);
495 fps = fps_hermes(1.0, 0.51, src_format, backbuffer);
496 std::cerr << .51 * 0.51 * 512 * 512 * fps << " ";
497 src_format = Hermes_FormatNew(32, 0xff0000, 0xff00, 0xff, 0, 0);
498 fps = fps_hermes(1.0, 0.51, src_format, backbuffer);
499 std::cerr << .51 * 0.51 * 512 * 512 * fps << " ";
500 src_format = Hermes_FormatNew(32, 0xff, 0xff00, 0xff0000, 0, 0);
501 fps = fps_hermes(1.0, 0.51, src_format, backbuffer);
502 std::cerr << .51 * 0.51 * 512 * 512 * fps << '\n';
503 }
504 Hermes_Done();
505 }
506 #endif
507 vpl_sleep(5);
508 return 0;
509 }
510