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")。
阅读(1496) | 评论(0) | 转发(0) |