SDL入门教程(三):3、视频属性信息(VideoInfo)

作者:龙飞

3.1:获取视频属性信息。

const  SDL_VideoInfo  * SDL_GetVideoInfo( void );
        我们在前一小节中,为了尽快实现一个SDL的运行窗口,跳过了很多细节,也留下了很多问题。其中一个很重要的问题就是:我们到底有没有使用到显卡的硬件加速?因为硬件的差异性,直接使用硬件接口的时候,会出现很多新的问题。这些问题在第(四)章中,我将以自己的操作系统和显卡硬件配置,通过试验得到结论,而在这之前,我们还必须弄清楚其他几个问题。
        SDL_GetVideoInfo()将返回当前SDL运行窗口的视频属性信息,其数据组织在一个名为SDL_VidioInfo的结构中。该函数就是返回这个只读结构的指针。
typedef  struct {
  Uint32 hw_available:
1 ;
  Uint32 wm_available:
1 ;
  Uint32 blit_hw:
1 ;
  Uint32 blit_hw_CC:
1 ;
  Uint32 blit_hw_A:
1 ;
  Uint32 blit_sw:
1 ;
  Uint32 blit_sw_CC:
1 ;
  Uint32 blit_sw_A:
1 ;
  Uint32 blit_fill:
1 ;
  Uint32 video_mem;
  SDL_PixelFormat 
* vfmt;
  
int  current_w;
  
int  current_h;
} SDL_VideoInfo;
        初看这个结构似乎有点让人头大,其实分析起来很简单,成员名称也很友好,容易让人记忆。hw_availabale表示创建硬件surface的可行性(1表示可以,0表示不可以,后同);wm_available表示是否存在可用的窗口管理器;3-9行表示了一系列硬件到硬件,软件到硬件加速的可行性;video_men表示显存大小;vfmt是当前显示驱动(video device)的像素格式(pixel format);current_w和current_h是当前窗口的宽和高。
        我们在使用在系统内存中建立SDL运行窗口的方式来察看这些成员数据。
    SDL_Init(SDL_INIT_VIDEO);
    atexit(SDL_Quit);

    SDL_Surface
*  pScreen  =  SDL_SetVideoMode( 640 480 32 , SDL_SWSURFACE);
    SDL_Flip(pScreen);

    
const  SDL_VideoInfo *  myInfo  =  SDL_GetVideoInfo();
    cout 
<<   " Is it possible to create hardware surfaces?  "   <<  myInfo -> hw_available  <<  endl;
    cout 
<<   " Is there a window manager available?  "   <<  myInfo -> wm_available  <<  endl;
    cout 
<<   " Are hardware to hardware blits accelerated?  "   <<  myInfo -> blit_hw  <<  endl;
    cout 
<<   " Are hardware to hardware colorkey blits accelerated?  "   <<  myInfo -> blit_hw_CC  <<  endl;
    cout 
<<   " Are hardware to hardware alpha blits accelerated?  "   <<  myInfo -> blit_hw_A  <<  endl;
    cout 
<<   " Are software to hardware blits accelerated?  "   <<  myInfo -> blit_sw  <<  endl;
    cout 
<<   " Are software to hardware colorkey blits accelerated?  "   <<  myInfo -> blit_sw_CC  <<  endl;
    cout 
<<   " Are software to hardware alpha blits accelerated?  "   <<  myInfo -> blit_sw_A  <<  endl;
    cout 
<<   " Are color fills accelerated?  "   <<  myInfo -> blit_fill  <<  endl;
    cout 
<<   " Total amount of video memory in Kilobytes?  "   <<  myInfo -> video_mem  <<  endl;
    cout 
<<   " Width of the current video mode?  "   <<  myInfo -> current_w  <<  endl;
    cout 
<<   " Height of the current video mode?  "   <<  myInfo -> current_h  <<  endl;

        结果似乎是可以预料的,创建硬件surface和硬件加速都是不可行的。接下来,我们将flag 从使用系统内存的SDL_SWSURFACE换成使用显存的SDL_HWSURFACE。

3.2:我的显卡不支持硬件加速??!!

        好吧,也许是我运气不好。问题来了!
        我的软件环境是windows server 2003,硬件环境是GeForce 4 Ti 4200 AGP 8x。当我第一次看到SDL反馈给我的信息:创建硬件surface不可行!硬件加速不可性!显存大小为0!!——我快喘不过气来。
        我的第一反应是SDL不支持我的显卡——后面一想,不对啊,SDL到今天(2008年2月)还在更新,我显卡可算是古董了——一定是什么地方搞错了,或者还有我没有了解到的问题。
        伴随而来的另外一个问题是:我是不是真正把surface建立到显存中了——尽快我要求SDL这么做。这里,我要第三次提到函数SDL_SetVideoMode()了。我们之前介绍过,这个函数的返回值是一个SDL_Surface结构的指针。而SDL_Surface结构中有一个数据成员flags储存了这个surface的位标信息,其中就包括是否建立到了显存里面(否则就在系统内存中)。

typedef  struct  SDL_Surface {
  Uint32 flags;                           
/*  Read-only  */
  SDL_PixelFormat 
* format;                 /*  Read-only  */
  
int  w, h;                                /*  Read-only  */
  Uint16 pitch;                           
/*  Read-only  */
  
void   * pixels;                            /*  Read-write  */
  SDL_Rect clip_rect;                     
/*  Read-only  */
  
int  refcount;                            /*  Read-mostly  */

  
/*  This structure also contains private fields not shown here  */

} SDL_Surface;
        这里我们继续忽略其他不熟悉的数据成员,直接将flags的信息读出来。
    cout  <<   " pScreen->flags =  " ;
    showHex(pScreen
-> flags);
    cout 
<<  boolalpha;
    cout 
<<   " SDL_SWSURFACE?  "   <<   ! ( bool ((pScreen -> flags)  &  SDL_HWSURFACE))  <<  endl;
    cout 
<<   " SDL_HWSURFACE?  "   <<   bool ((pScreen -> flags)  &  SDL_HWSURFACE)  <<  endl;
    cout 
<<   " SDL_DOUBLEBUF?  "   <<   bool ((pScreen -> flags)  &  SDL_DOUBLEBUF)  <<  endl;
    cout 
<<  noboolalpha;

        请注两点:函数showHex()显示16进格式,在前面章节有原形和定义;SDL_SWSURFACE是0,是伪位标,因为它与SDL_HWSURFACE只能二取一的,所以他的实际状态可以用如上方式表示。另外,SDL_DOUBLEBUF是在开启硬件画surface和加速时候很重要的位标,在后面会有介绍。
        结果是——很不幸,surface没有建立在显存中。

3.3:SDL的环境设置。

        寻找问题和试验的过程很曲折。我在这里直接说结论,在下一节中,再进行具体的试验。SDL有个环境设置的概念。这是因为SDL是跨平台的,在不同的操作系统和不同的GUI之上,SDL试图建立起一个与以上因素无关的封装。但是因为硬件(主要指显卡)的具体多样性,SDL在不同的OS和不同的GUI之上,使用不同的“驱动”,以windows为例,SDL在windows上的驱动有GDI(windib)和DirectX(directx)两种(Linux下则更多,请参考官方资料),我们可以通过一个函数知道当前SDL使用的驱动版本。

char   * SDL_VideoDriverName( char   * namebuf,  int  maxlen);
        如果返回空指针,则表示SDL_Init()没有装载或出现异常。我们可使用下面这样的语句查看当前SDL使用的驱动版本名字。
     char  driverName[ 20 ];
    SDL_VideoDriverName(driverName, 
20 );
    cout 
<<   " SDL_VideoDriverName =  "   <<  driverName  <<  endl;
        结果是:windib。为什么SDL官方资料显示,默认值是directx呢?(这不是反问,这是我的疑问,请知道答案的同学跟我联系,谢谢)——结论是,windib无法打开硬件加速,要使用硬件加速,必须使用directx。官方资料上用了很简短的描述来说明进行SDL的环境设置。在后面的章节中,我们将使用:
putenv( " SDL_VIDEODRIVER=directx " );
注意:这个函数必须用在SDL_Init();之前才有实际效果。来设置为directx环境。(VC下为了解除编译警告,也可使用SDL_putenv()来代替putenv(),效果都一样。)之后除了用SDL_VideoDriverName()获取显示驱动信息,还可以使用:(同样,VC下可使用SDL_getent()替换)
const   char *  myvalue  =  getenv( " name " ) ;
来获取相关的环境信息(包括显示驱动信息。"name"换为"SDL_VIDEODRIVER")。  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值