作者:龍飛
2.1:需要修改的地方。
這里,我們真正的開始使用SDL的硬件渲染。首先,我們需要設置驅動的環境(以windows為例,我們設置為directx,Linux的設置請參考官方網站,我們這里預留為dga)。另外,如果要啟動硬件加速,必須使用全屏模式(SDL_FULLSCREEN),所以,在前面的軟件渲染中,我們也使用全屏以作對比。第三,硬件渲染需要打開雙緩沖(SDL_DOUBLEBUF),至于為什么我們在最后討論,我們還是先看看完整的代碼。
2.2:硬件渲染演示程序完整的源代碼。
#define __windows__ // Linux using #define __linux__
#include <iostream>
#include "SDL/SDL.h"
SDL_Surface* pScreen = 0;
SDL_Surface* pBack = 0;
SDL_Surface* pFront = 0;
void pressESCtoQuitPlus();
void loopRender();
int main(int argc, char* argv[])
{
#ifdef __windows__
SDL_putenv("SDL_VIDEODRIVER=directx");
#endif
#ifdef __linux__
putenv("SDL_VIDEODRIVER=dga");
#endif
try {
if ( SDL_Init(SDL_INIT_VIDEO) != 0 )
throw SDL_GetError();
}
catch ( const char* s ) {
std::cerr << "SDL_Init() failed!\n" << s << std::endl;
return -1;
}
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
const Uint32 SCREEN_FLAGS = SDL_FULLSCREEN | SDL_DOUBLEBUF | SDL_HWSURFACE;
pScreen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SCREEN_FLAGS);
try {
if ( pScreen == 0 )
throw SDL_GetError();
}
catch ( const char* s ) {
std::cerr << "SDL_SetVideoMode() failed!\n" << s << std::endl;
SDL_Quit();
return -1;
}
pBack = SDL_LoadBMP("back.bmp");
try {
if ( pBack == 0 )
throw SDL_GetError();
}
catch ( const char* s ) {
std::cerr << "SDL_LoadBMP() failed!\n" << s << std::endl;
SDL_Quit();
return -1;
}
pFront = SDL_LoadBMP("front.bmp");
try {
if ( pFront == 0 )
throw SDL_GetError();
}
catch ( const char* s ) {
std::cerr << "SDL_LoadBMP() failed!\n" << s << std::endl;
SDL_Quit();
return -1;
}
try {
pressESCtoQuitPlus();
}
catch ( const char* s ) {
std::cerr << "pressESCtoQuitPlus() failed!\n" << s << std::endl;
SDL_Quit();
return -1;
}
SDL_Quit();
return 0;
}
void pressESCtoQuitPlus()
{
bool gameOver = false;
while( gameOver == false ){
SDL_Event gameEvent;
while ( SDL_PollEvent(&gameEvent) != 0 ){
if ( gameEvent.type == SDL_QUIT ){
gameOver = true;
}
if ( gameEvent.type == SDL_KEYUP ){
if ( gameEvent.key.keysym.sym == SDLK_ESCAPE ){
gameOver = true;
}
}
}
loopRender();
}
return;
}
void loopRender()
{
SDL_Rect* pSrcRect = 0;
SDL_Rect* pDstRect = 0;
if ( SDL_BlitSurface(pBack, pSrcRect, pScreen, pDstRect) != 0 )
throw SDL_GetError();
if ( SDL_BlitSurface(pFront, pSrcRect, pScreen, pDstRect) != 0 )
throw SDL_GetError();
if ( SDL_Flip(pScreen) != 0 )
throw SDL_GetError();
return;
}
2.3:問題。
你可能發現除了鼠標指針不顯示之外,沒有其它問題——這其實不是好現象,因為應該和可能出現的問題,都被我們事先避免了,但是這樣讓我們離事情的本質越來越遠。你可以嘗試著關掉SDL_DOUBLEBUF位標看看是什么效果;或者,在前面渲染單幀的程序中使用硬件渲染同時打開雙緩沖看看出現什么問題——這些正是我們下一節將要討論的。
如果你迫不及待的想知道原因,并且英語也過關的話,對于硬件渲染可能會引發的問題,我給你推薦一篇SDL官方也推薦的論文:
http://www.linuxdevcenter.com/pub/a/linux/2003/08/07/sdl_anim.html 但是很不幸的是,我在試驗的過程中發現這篇文章有很多問題,當然,也許是我錯了。因為我僅僅把SDL作為了一個黑盒子來研究,但是我得到的試驗結果,卻是不可能錯的。
2.4:補充。
目前用Debian試驗的時候,發現NVidia的顯卡驅動屏蔽掉了dga的。也就是說實際上用不了,或者會設置起來很麻煩。實際上,SDL通過x11來實現圖像,我目前的認識應該是這樣的:SDL->x11->NV驅動->顯卡。所以,實際上我們雖然沒有通過SDL接觸到顯卡,但實際上還是通過種種渠道調用了顯卡,我們應該充分相信NV的工程師比我們牛得多。NV官方解釋如下:
http://us.download.nvidia.com/XFree86/Linux-x86/169.04/README/chapter-07.html#id2546686
Why do applications that use DGA graphics fail?
|
|
The NVIDIA driver does not support the graphics component of the
XFree86-DGA (Direct Graphics Access) extension. Applications can
use the XDGASelectInput() function to acquire relative pointer
motion, but graphics-related functions such as XDGASetMode() and
XDGAOpenFramebuffer() will fail.
The graphics component of XFree86-DGA is not supported because
it requires a CPU mapping of framebuffer memory. As graphics cards
ship with increasing quantities of video memory, the NVIDIA X
driver has had to switch to a more dynamic memory mapping scheme
that is incompatible with DGA. Furthermore, DGA does not cooperate
with other graphics rendering libraries such as Xlib and OpenGL
because it accesses GPU resources directly.
NVIDIA recommends that applications use OpenGL or Xlib, rather
than DGA, for graphics rendering. Using rendering libraries other
than DGA will yield better performance and improve interoperability
with other X applications.
|
posted on 2008-02-15 16:23
lf426 閱讀(9506)
評論(6) 編輯 收藏 引用 所屬分類:
SDL入門教程