VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxSDL/VBoxSDLTest.cpp@ 3481

Last change on this file since 3481 was 2981, checked in by vboxsync, 17 years ago

InnoTek -> innotek: all the headers and comments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.3 KB
Line 
1/** @file
2 *
3 * VBox frontends: VBoxSDL (simple frontend based on SDL):
4 * VBoxSDL testcases
5 */
6
7/*
8 * Copyright (C) 2006-2007 innotek GmbH
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
21 */
22
23#if defined(__WIN__) ///@todo someone please explain why we don't follow the book!
24# define _SDL_main_h
25#endif
26#include <SDL.h>
27
28#include <iprt/assert.h>
29#include <iprt/stream.h>
30#include <iprt/string.h>
31#include <iprt/time.h>
32
33#include <stdlib.h>
34#include <signal.h>
35
36#ifdef VBOX_OPENGL
37#include "SDL_opengl.h"
38#endif
39
40#ifdef __WIN__
41#define ESC_NORM
42#define ESC_BOLD
43#else
44#define ESC_NORM "\033[m"
45#define ESC_BOLD "\033[1m"
46#endif
47
48static SDL_Surface *gSurfVRAM; /* SDL virtual framebuffer surface */
49static void *gPtrVRAM; /* allocated virtual framebuffer */
50static SDL_Surface *gScreen; /* SDL screen surface */
51static unsigned long guGuestXRes; /* virtual framebuffer width */
52static unsigned long guGuestYRes; /* virtual framebuffer height */
53static unsigned long guGuestBpp; /* virtual framebuffer bits per pixel */
54static unsigned long guMaxScreenWidth; /* max screen width SDL allows */
55static unsigned long guMaxScreenHeight; /* max screen height SDL allows */
56static int gfResizable = 1; /* SDL window is resizable */
57static int gfFullscreen = 0; /* use fullscreen mode */
58#ifdef VBOX_OPENGL
59static unsigned long guTextureWidth; /* width of OpenGL texture */
60static unsigned long guTextureHeight; /* height of OpenGL texture */
61static unsigned int gTexture;
62static int gfOpenGL; /* use OpenGL as backend */
63#endif
64static unsigned int guLoop = 1000; /* Number of frame redrawings for each test */
65
66static void bench(unsigned long w, unsigned long h, unsigned long bpp);
67static void benchExecute(void);
68static int checkSDL(const char *fn, int rc);
69static void checkEvents(void);
70
71int
72main(int argc, char **argv)
73{
74 int rc;
75
76 for (int i = 1; i < argc; i++)
77 {
78#ifdef VBOX_OPENGL
79 if (strcmp(argv[i], "-gl") == 0)
80 {
81 gfOpenGL = 1;
82 continue;
83 }
84#endif
85 if (strcmp(argv[i], "-loop") == 0 && ++i < argc)
86 {
87 guLoop = atoi(argv[i]);
88 continue;
89 }
90 RTPrintf("Unrecognized option '%s'\n", argv[i]);
91 return -1;
92 }
93
94#ifdef __WIN__
95 /* Default to DirectX if nothing else set. "windib" would be possible. */
96 if (!getenv("SDL_VIDEODRIVER"))
97 {
98 _putenv("SDL_VIDEODRIVER=directx");
99 }
100#endif
101
102#ifdef __WIN__
103 _putenv("SDL_VIDEO_WINDOW_POS=0,0");
104#else
105 setenv("SDL_VIDEO_WINDOW_POS", "0,0", 1);
106#endif
107
108 rc = SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE);
109 if (rc != 0)
110 {
111 RTPrintf("Error: SDL_InitSubSystem failed with message '%s'\n", SDL_GetError());
112 return -1;
113 }
114
115 /* output what SDL is capable of */
116 const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
117
118 if (!videoInfo)
119 {
120 RTPrintf("No SDL video info available!\n");
121 return -1;
122 }
123
124 RTPrintf("SDL capabilities:\n");
125 RTPrintf(" Hardware surface support: %s\n", videoInfo->hw_available ? "yes" : "no");
126 RTPrintf(" Window manager available: %s\n", videoInfo->wm_available ? "yes" : "no");
127 RTPrintf(" Screen to screen blits accelerated: %s\n", videoInfo->blit_hw ? "yes" : "no");
128 RTPrintf(" Screen to screen colorkey blits accelerated: %s\n", videoInfo->blit_hw_CC ? "yes" : "no");
129 RTPrintf(" Screen to screen alpha blits accelerated: %s\n", videoInfo->blit_hw_A ? "yes" : "no");
130 RTPrintf(" Memory to screen blits accelerated: %s\n", videoInfo->blit_sw ? "yes" : "no");
131 RTPrintf(" Memory to screen colorkey blits accelerated: %s\n", videoInfo->blit_sw_CC ? "yes" : "no");
132 RTPrintf(" Memory to screen alpha blits accelerated: %s\n", videoInfo->blit_sw_A ? "yes" : "no");
133 RTPrintf(" Color fills accelerated: %s\n", videoInfo->blit_fill ? "yes" : "no");
134 RTPrintf(" Video memory in kilobytes: %d\n", videoInfo->video_mem);
135 RTPrintf(" Optimal bpp mode: %d\n", videoInfo->vfmt->BitsPerPixel);
136 char buf[256];
137 RTPrintf("Video driver SDL_VIDEODRIVER / active: %s/%s\n", getenv("SDL_VIDEODRIVER"),
138 SDL_VideoDriverName(buf, sizeof(buf)));
139
140 RTPrintf("\n"
141 "Starting tests. Any key pressed inside the SDL window will abort this\n"
142 "program at the end of the current test. Iterations = %u\n", guLoop);
143
144#ifdef VBOX_OPENGL
145 RTPrintf("\n========== "ESC_BOLD"OpenGL is %s"ESC_NORM" ==========\n",
146 gfOpenGL ? "ON" : "OFF");
147#endif
148 bench( 640, 480, 16); bench( 640, 480, 24); bench( 640, 480, 32);
149 bench(1024, 768, 16); bench(1024, 768, 24); bench(1024, 768, 32);
150 bench(1280, 1024, 16); bench(1280, 1024, 24); bench(1280, 1024, 32);
151
152 RTPrintf("\nSuccess!\n");
153 return 0;
154}
155
156/**
157 * Method that does the actual resize of the guest framebuffer and
158 * then changes the SDL framebuffer setup.
159 */
160static void bench(unsigned long w, unsigned long h, unsigned long bpp)
161{
162 Uint32 Rmask, Gmask, Bmask, Amask = 0;
163 Uint32 Rsize, Gsize, Bsize;
164 Uint32 newWidth, newHeight;
165
166 guGuestXRes = w;
167 guGuestYRes = h;
168 guGuestBpp = bpp;
169
170 RTPrintf("\n");
171
172 /* a different format we support directly? */
173 switch (guGuestBpp)
174 {
175 case 16:
176 {
177 Rmask = 0xF800;
178 Gmask = 0x07E0;
179 Bmask = 0x001F;
180 Amask = 0x0000;
181 Rsize = 5;
182 Gsize = 6;
183 Bsize = 5;
184 break;
185 }
186
187 case 24:
188 {
189 Rmask = 0x00FF0000;
190 Gmask = 0x0000FF00;
191 Bmask = 0x000000FF;
192 Amask = 0x00000000;
193 Rsize = 8;
194 Gsize = 8;
195 Bsize = 8;
196 break;
197 }
198
199 default:
200 Rmask = 0x00FF0000;
201 Gmask = 0x0000FF00;
202 Bmask = 0x000000FF;
203 Amask = 0x00000000;
204 Rsize = 8;
205 Gsize = 8;
206 Bsize = 8;
207 break;
208 }
209
210 int sdlFlags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
211#ifdef VBOX_OPENGL
212 if (gfOpenGL)
213 sdlFlags |= SDL_OPENGL;
214#endif
215 if (gfResizable)
216 sdlFlags |= SDL_RESIZABLE;
217 if (gfFullscreen)
218 sdlFlags |= SDL_FULLSCREEN;
219
220 /*
221 * Now we have to check whether there are video mode restrictions
222 */
223 SDL_Rect **modes;
224 /* Get available fullscreen/hardware modes */
225 modes = SDL_ListModes(NULL, sdlFlags);
226 if (modes == NULL)
227 {
228 RTPrintf("Error: SDL_ListModes failed with message '%s'\n", SDL_GetError());
229 return;
230 }
231
232 /* -1 means that any mode is possible (usually non fullscreen) */
233 if (modes != (SDL_Rect **)-1)
234 {
235 /*
236 * according to the SDL documentation, the API guarantees that
237 * the modes are sorted from larger to smaller, so we just
238 * take the first entry as the maximum.
239 */
240 guMaxScreenWidth = modes[0]->w;
241 guMaxScreenHeight = modes[0]->h;
242 }
243 else
244 {
245 /* no restriction */
246 guMaxScreenWidth = ~0;
247 guMaxScreenHeight = ~0;
248 }
249
250 newWidth = RT_MIN(guMaxScreenWidth, guGuestXRes);
251 newHeight = RT_MIN(guMaxScreenHeight, guGuestYRes);
252
253 /*
254 * Now set the screen resolution and get the surface pointer
255 * @todo BPP is not supported!
256 */
257#ifdef VBOX_OPENGL
258 if (gfOpenGL)
259 {
260 checkSDL("SDL_GL_SetAttribute", SDL_GL_SetAttribute(SDL_GL_RED_SIZE, Rsize));
261 checkSDL("SDL_GL_SetAttribute", SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, Gsize));
262 checkSDL("SDL_GL_SetAttribute", SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, Bsize));
263 checkSDL("SDL_GL_SetAttribute", SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0));
264 }
265#endif
266
267 RTPrintf("Testing "ESC_BOLD"%ldx%ld@%ld"ESC_NORM"\n", guGuestXRes, guGuestYRes, guGuestBpp);
268
269 gScreen = SDL_SetVideoMode(newWidth, newHeight, 0, sdlFlags);
270 if (!gScreen)
271 {
272 RTPrintf("SDL_SetVideoMode failed (%s)\n", SDL_GetError());
273 return;
274 }
275
276 /* first free the current surface */
277 if (gSurfVRAM)
278 {
279 SDL_FreeSurface(gSurfVRAM);
280 gSurfVRAM = NULL;
281 }
282 if (gPtrVRAM)
283 {
284 free(gPtrVRAM);
285 gPtrVRAM = NULL;
286 }
287
288 if (gScreen->format->BitsPerPixel != guGuestBpp)
289 {
290 /* Create a source surface from guest VRAM. */
291 int bytes_per_pixel = (guGuestBpp + 7) / 8;
292 gPtrVRAM = malloc(guGuestXRes * guGuestYRes * bytes_per_pixel);
293 gSurfVRAM = SDL_CreateRGBSurfaceFrom(gPtrVRAM, guGuestXRes, guGuestYRes, guGuestBpp,
294 bytes_per_pixel * guGuestXRes,
295 Rmask, Gmask, Bmask, Amask);
296 }
297 else
298 {
299 /* Create a software surface for which SDL allocates the RAM */
300 gSurfVRAM = SDL_CreateRGBSurface(SDL_SWSURFACE, guGuestXRes, guGuestYRes, guGuestBpp,
301 Rmask, Gmask, Bmask, Amask);
302 }
303
304 if (!gSurfVRAM)
305 {
306 RTPrintf("Failed to allocate surface %ldx%ld@%ld\n",
307 guGuestXRes, guGuestYRes, guGuestBpp);
308 return;
309 }
310
311 RTPrintf(" gScreen=%dx%d@%d (surface: %s)\n",
312 gScreen->w, gScreen->h, gScreen->format->BitsPerPixel,
313 (gScreen->flags & SDL_HWSURFACE) == 0 ? "software" : "hardware");
314
315 SDL_Rect rect = { 0, 0, (Uint16)guGuestXRes, (Uint16)guGuestYRes };
316 checkSDL("SDL_FillRect",
317 SDL_FillRect(gSurfVRAM, &rect,
318 SDL_MapRGB(gSurfVRAM->format, 0x5F, 0x6F, 0x1F)));
319
320#ifdef VBOX_OPENGL
321 if (gfOpenGL)
322 {
323 int r, g, b, d, o;
324 SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &r);
325 SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &g);
326 SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &b);
327 SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &d);
328 SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &o);
329 RTPrintf(" OpenGL ctxt red=%d, green=%d, blue=%d, depth=%d, dbl=%d", r, g, b, d, o);
330
331 glEnable(GL_TEXTURE_2D);
332 glDisable(GL_BLEND);
333 glDisable(GL_DEPTH_TEST);
334 glDepthMask(GL_FALSE);
335 glGenTextures(1, &gTexture);
336 glBindTexture(GL_TEXTURE_2D, gTexture);
337 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
338 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
339 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
340 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
341
342 for (guTextureWidth = 32; guTextureWidth < newWidth; guTextureWidth <<= 1);
343 for (guTextureHeight = 32; guTextureHeight < newHeight; guTextureHeight <<= 1);
344 RTPrintf(", tex %ldx%ld\n", guTextureWidth, guTextureHeight);
345
346 switch (guGuestBpp)
347 {
348 case 16: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, guTextureWidth, guTextureHeight, 0,
349 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
350 break;
351 case 24: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, guTextureWidth, guTextureHeight, 0,
352 GL_BGR, GL_UNSIGNED_BYTE, 0);
353 break;
354 case 32: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, guTextureWidth, guTextureHeight, 0,
355 GL_BGRA, GL_UNSIGNED_BYTE, 0);
356 break;
357 default: RTPrintf("guGuestBpp=%d?\n", guGuestBpp);
358 return;
359 }
360
361 glViewport(0, 0, newWidth, newHeight);
362 glMatrixMode(GL_PROJECTION);
363 glLoadIdentity();
364 glOrtho(0.0, newWidth, newHeight, 0.0, -1.0, 1.0);
365 }
366#endif
367
368 checkEvents();
369 benchExecute();
370
371#ifdef VBOX_OPENGL
372 if (gfOpenGL)
373 {
374 glDeleteTextures(1, &gTexture);
375 }
376#endif
377}
378
379static void benchExecute()
380{
381 SDL_Rect rect = { 0, 0, (Uint16)guGuestXRes, (Uint16)guGuestYRes };
382 RTTIMESPEC t1, t2;
383
384 RTTimeNow(&t1);
385 for (unsigned i=0; i<guLoop; i++)
386 {
387#ifdef VBOX_OPENGL
388 if (!gfOpenGL)
389 {
390#endif
391 /* SDL backend */
392 checkSDL("SDL_BlitSurface", SDL_BlitSurface(gSurfVRAM, &rect, gScreen, &rect));
393 if ((gScreen->flags & SDL_HWSURFACE) == 0)
394 SDL_UpdateRect(gScreen, rect.x, rect.y, rect.w, rect.h);
395#ifdef VBOX_OPENGL
396 }
397 else
398 {
399 /* OpenGL backend */
400 glBindTexture(GL_TEXTURE_2D, gTexture);
401 glPixelStorei(GL_UNPACK_SKIP_PIXELS, rect.x);
402 glPixelStorei(GL_UNPACK_SKIP_ROWS, rect.y);
403 glPixelStorei(GL_UNPACK_ROW_LENGTH, gSurfVRAM->pitch / gSurfVRAM->format->BytesPerPixel);
404 switch (gSurfVRAM->format->BitsPerPixel)
405 {
406 case 16: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rect.w, rect.h,
407 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, gSurfVRAM->pixels);
408 break;
409 case 24: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rect.w, rect.h,
410 GL_BGR, GL_UNSIGNED_BYTE, gSurfVRAM->pixels);
411 break;
412 case 32: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rect.w, rect.h,
413 GL_BGRA, GL_UNSIGNED_BYTE, gSurfVRAM->pixels);
414 break;
415 default: RTPrintf("BitsPerPixel=%d?\n", gSurfVRAM->format->BitsPerPixel);
416 return;
417 }
418 GLfloat tx = (GLfloat)((float)rect.w) / guTextureWidth;
419 GLfloat ty = (GLfloat)((float)rect.h) / guTextureHeight;
420 glBegin(GL_QUADS);
421 glColor4f(1.0, 1.0, 1.0, 1.0);
422 glTexCoord2f(0.0, 0.0); glVertex2i(rect.x, rect.y );
423 glTexCoord2f(0.0, ty); glVertex2i(rect.x, rect.y + rect.h);
424 glTexCoord2f(tx, ty); glVertex2i(rect.x + rect.w, rect.y + rect.h);
425 glTexCoord2f(tx, 0.0); glVertex2i(rect.x + rect.w, rect.y );
426 glEnd();
427 glFlush();
428 }
429#endif
430 }
431 RTTimeNow(&t2);
432 int64_t ms = RTTimeSpecGetMilli(&t2) - RTTimeSpecGetMilli(&t1);
433 printf(" %.1fms/frame\n", (double)ms / guLoop);
434}
435
436static int checkSDL(const char *fn, int rc)
437{
438 if (rc == -1)
439 RTPrintf(""ESC_BOLD"%s() failed:"ESC_NORM" '%s'\n", fn, SDL_GetError());
440
441 return rc;
442}
443
444static void checkEvents(void)
445{
446 SDL_Event event;
447 while (SDL_PollEvent(&event))
448 {
449 switch (event.type)
450 {
451 case SDL_KEYDOWN:
452 RTPrintf("\nKey pressed, exiting ...\n");
453 exit(-1);
454 break;
455 }
456 }
457}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette