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

[复制链接]

该用户从未签到

2380

主题

2433

帖子

9139

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
9139
QQ
跳转到指定楼层
楼主
发表于 2017-12-19 09:46:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

想要查看内容赶紧注册登陆吧!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
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")。                     
分享到:  QQ好友和群QQ好友和群
收藏收藏
回复

使用道具 举报

快速回复高级模式
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表