VirtualBox

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

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

Biggest check-in ever. New source code headers for all (C) innotek files.

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