VirtualBox

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

Last change on this file since 2962 was 2962, checked in by vboxsync, 18 years ago

Don't use putenv if possible as setenv is more correct. The reason is that putenv expects a parameter which gets part of the environment. If the passed string is changed, the environment changes as well. Passing an automatic variable to putenv is a bug. Though it isn't wrong to pass a constant since a constant string goes never away. But gcc-4.2 warns about it.

  • 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 InnoTek Systemberatung 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.

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