VirtualBox

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

Last change on this file since 7392 was 5999, checked in by vboxsync, 17 years ago

The Giant CDDL Dual-License Header Change.

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