VirtualBox

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

Last change on this file since 47678 was 44528, checked in by vboxsync, 12 years ago

header (C) fixes

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