VirtualBox

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

Last change on this file since 61042 was 58035, checked in by vboxsync, 9 years ago

warning

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.3 KB
Line 
1/* $Id: VBoxSDLTest.cpp 58035 2015-10-06 07:47:47Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: VBoxSDL (simple frontend based on SDL):
5 * VBoxSDL testcases
6 */
7
8/*
9 * Copyright (C) 2006-2013 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20#if defined(RT_OS_WINDOWS) ///@todo someone please explain why we don't follow the book!
21# define _SDL_main_h
22#endif
23#include <SDL.h>
24
25#include <iprt/assert.h>
26#include <iprt/env.h>
27#include <iprt/initterm.h>
28#include <iprt/stream.h>
29#include <iprt/string.h>
30#include <iprt/time.h>
31
32#include <stdlib.h>
33#include <signal.h>
34
35#ifdef VBOX_OPENGL
36#include "SDL_opengl.h"
37#endif
38
39#ifdef RT_OS_WINDOWS
40#define ESC_NORM
41#define ESC_BOLD
42#else
43#define ESC_NORM "\033[m"
44#define ESC_BOLD "\033[1m"
45#endif
46
47static SDL_Surface *gSurfVRAM; /* SDL virtual framebuffer surface */
48static void *gPtrVRAM; /* allocated virtual framebuffer */
49static SDL_Surface *gScreen; /* SDL screen surface */
50static unsigned long guGuestXRes; /* virtual framebuffer width */
51static unsigned long guGuestYRes; /* virtual framebuffer height */
52static unsigned long guGuestBpp; /* virtual framebuffer bits per pixel */
53static unsigned long guMaxScreenWidth; /* max screen width SDL allows */
54static unsigned long guMaxScreenHeight; /* max screen height SDL allows */
55static int gfResizable = 1; /* SDL window is resizable */
56static int gfFullscreen = 0; /* use fullscreen mode */
57#ifdef VBOX_OPENGL
58static unsigned long guTextureWidth; /* width of OpenGL texture */
59static unsigned long guTextureHeight; /* height of OpenGL texture */
60static unsigned int gTexture;
61static int gfOpenGL; /* use OpenGL as backend */
62#endif
63static unsigned int guLoop = 1000; /* Number of frame redrawings for each test */
64
65static void bench(unsigned long w, unsigned long h, unsigned long bpp);
66static void benchExecute(void);
67static int checkSDL(const char *fn, int rc);
68static void checkEvents(void);
69
70int
71main(int argc, char **argv)
72{
73 int rc;
74 RTR3InitExe(argc, &argv, 0);
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 RT_OS_WINDOWS
95 /* Default to DirectX if nothing else set. "windib" would be possible. */
96 if (!RTEnvExist("SDL_VIDEODRIVER"))
97 {
98 _putenv("SDL_VIDEODRIVER=directx");
99 }
100#endif
101
102#ifdef RT_OS_WINDOWS
103 _putenv("SDL_VIDEO_WINDOW_POS=0,0");
104#else
105 RTEnvSet("SDL_VIDEO_WINDOW_POS", "0,0");
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", RTEnvGet("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#else
266 NOREF(Rsize); NOREF(Gsize); NOREF(Bsize);
267#endif
268
269 RTPrintf("Testing " ESC_BOLD "%ldx%ld@%ld" ESC_NORM "\n", guGuestXRes, guGuestYRes, guGuestBpp);
270
271 gScreen = SDL_SetVideoMode(newWidth, newHeight, 0, sdlFlags);
272 if (!gScreen)
273 {
274 RTPrintf("SDL_SetVideoMode failed (%s)\n", SDL_GetError());
275 return;
276 }
277
278 /* first free the current surface */
279 if (gSurfVRAM)
280 {
281 SDL_FreeSurface(gSurfVRAM);
282 gSurfVRAM = NULL;
283 }
284 if (gPtrVRAM)
285 {
286 free(gPtrVRAM);
287 gPtrVRAM = NULL;
288 }
289
290 if (gScreen->format->BitsPerPixel != guGuestBpp)
291 {
292 /* Create a source surface from guest VRAM. */
293 int bytes_per_pixel = (guGuestBpp + 7) / 8;
294 gPtrVRAM = malloc(guGuestXRes * guGuestYRes * bytes_per_pixel);
295 gSurfVRAM = SDL_CreateRGBSurfaceFrom(gPtrVRAM, guGuestXRes, guGuestYRes, guGuestBpp,
296 bytes_per_pixel * guGuestXRes,
297 Rmask, Gmask, Bmask, Amask);
298 }
299 else
300 {
301 /* Create a software surface for which SDL allocates the RAM */
302 gSurfVRAM = SDL_CreateRGBSurface(SDL_SWSURFACE, guGuestXRes, guGuestYRes, guGuestBpp,
303 Rmask, Gmask, Bmask, Amask);
304 }
305
306 if (!gSurfVRAM)
307 {
308 RTPrintf("Failed to allocate surface %ldx%ld@%ld\n",
309 guGuestXRes, guGuestYRes, guGuestBpp);
310 return;
311 }
312
313 RTPrintf(" gScreen=%dx%d@%d (surface: %s)\n",
314 gScreen->w, gScreen->h, gScreen->format->BitsPerPixel,
315 (gScreen->flags & SDL_HWSURFACE) == 0 ? "software" : "hardware");
316
317 SDL_Rect rect = { 0, 0, (Uint16)guGuestXRes, (Uint16)guGuestYRes };
318 checkSDL("SDL_FillRect",
319 SDL_FillRect(gSurfVRAM, &rect,
320 SDL_MapRGB(gSurfVRAM->format, 0x5F, 0x6F, 0x1F)));
321
322#ifdef VBOX_OPENGL
323 if (gfOpenGL)
324 {
325 int r, g, b, d, o;
326 SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &r);
327 SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &g);
328 SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &b);
329 SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &d);
330 SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &o);
331 RTPrintf(" OpenGL ctxt red=%d, green=%d, blue=%d, depth=%d, dbl=%d", r, g, b, d, o);
332
333 glEnable(GL_TEXTURE_2D);
334 glDisable(GL_BLEND);
335 glDisable(GL_DEPTH_TEST);
336 glDepthMask(GL_FALSE);
337 glGenTextures(1, &gTexture);
338 glBindTexture(GL_TEXTURE_2D, gTexture);
339 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
340 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
341 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
342 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
343
344 for (guTextureWidth = 32; guTextureWidth < newWidth; guTextureWidth <<= 1)
345 ;
346 for (guTextureHeight = 32; guTextureHeight < newHeight; guTextureHeight <<= 1)
347 ;
348 RTPrintf(", tex %ldx%ld\n", guTextureWidth, guTextureHeight);
349
350 switch (guGuestBpp)
351 {
352 case 16: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, guTextureWidth, guTextureHeight, 0,
353 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
354 break;
355 case 24: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, guTextureWidth, guTextureHeight, 0,
356 GL_BGR, GL_UNSIGNED_BYTE, 0);
357 break;
358 case 32: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, guTextureWidth, guTextureHeight, 0,
359 GL_BGRA, GL_UNSIGNED_BYTE, 0);
360 break;
361 default: RTPrintf("guGuestBpp=%d?\n", guGuestBpp);
362 return;
363 }
364
365 glViewport(0, 0, newWidth, newHeight);
366 glMatrixMode(GL_PROJECTION);
367 glLoadIdentity();
368 glOrtho(0.0, newWidth, newHeight, 0.0, -1.0, 1.0);
369 }
370#endif
371
372 checkEvents();
373 benchExecute();
374
375#ifdef VBOX_OPENGL
376 if (gfOpenGL)
377 {
378 glDeleteTextures(1, &gTexture);
379 }
380#endif
381}
382
383static void benchExecute()
384{
385 SDL_Rect rect = { 0, 0, (Uint16)guGuestXRes, (Uint16)guGuestYRes };
386 RTTIMESPEC t1, t2;
387
388 RTTimeNow(&t1);
389 for (unsigned i=0; i<guLoop; i++)
390 {
391#ifdef VBOX_OPENGL
392 if (!gfOpenGL)
393 {
394#endif
395 /* SDL backend */
396 checkSDL("SDL_BlitSurface", SDL_BlitSurface(gSurfVRAM, &rect, gScreen, &rect));
397 if ((gScreen->flags & SDL_HWSURFACE) == 0)
398 SDL_UpdateRect(gScreen, rect.x, rect.y, rect.w, rect.h);
399#ifdef VBOX_OPENGL
400 }
401 else
402 {
403 /* OpenGL backend */
404 glBindTexture(GL_TEXTURE_2D, gTexture);
405 glPixelStorei(GL_UNPACK_SKIP_PIXELS, rect.x);
406 glPixelStorei(GL_UNPACK_SKIP_ROWS, rect.y);
407 glPixelStorei(GL_UNPACK_ROW_LENGTH, gSurfVRAM->pitch / gSurfVRAM->format->BytesPerPixel);
408 switch (gSurfVRAM->format->BitsPerPixel)
409 {
410 case 16: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rect.w, rect.h,
411 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, gSurfVRAM->pixels);
412 break;
413 case 24: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rect.w, rect.h,
414 GL_BGR, GL_UNSIGNED_BYTE, gSurfVRAM->pixels);
415 break;
416 case 32: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rect.w, rect.h,
417 GL_BGRA, GL_UNSIGNED_BYTE, gSurfVRAM->pixels);
418 break;
419 default: RTPrintf("BitsPerPixel=%d?\n", gSurfVRAM->format->BitsPerPixel);
420 return;
421 }
422 GLfloat tx = (GLfloat)((float)rect.w) / guTextureWidth;
423 GLfloat ty = (GLfloat)((float)rect.h) / guTextureHeight;
424 glBegin(GL_QUADS);
425 glColor4f(1.0, 1.0, 1.0, 1.0);
426 glTexCoord2f(0.0, 0.0); glVertex2i(rect.x, rect.y );
427 glTexCoord2f(0.0, ty); glVertex2i(rect.x, rect.y + rect.h);
428 glTexCoord2f(tx, ty); glVertex2i(rect.x + rect.w, rect.y + rect.h);
429 glTexCoord2f(tx, 0.0); glVertex2i(rect.x + rect.w, rect.y );
430 glEnd();
431 glFlush();
432 }
433#endif
434 }
435 RTTimeNow(&t2);
436 int64_t ms = RTTimeSpecGetMilli(&t2) - RTTimeSpecGetMilli(&t1);
437 printf(" %.1fms/frame\n", (double)ms / guLoop);
438}
439
440static int checkSDL(const char *fn, int rc)
441{
442 if (rc == -1)
443 RTPrintf("" ESC_BOLD "%s() failed:" ESC_NORM " '%s'\n", fn, SDL_GetError());
444
445 return rc;
446}
447
448static void checkEvents(void)
449{
450 SDL_Event event;
451 while (SDL_PollEvent(&event))
452 {
453 switch (event.type)
454 {
455 case SDL_KEYDOWN:
456 RTPrintf("\nKey pressed, exiting ...\n");
457 exit(-1);
458 break;
459 }
460 }
461}
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