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;
}
#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作爲了一個黑盒子來研究,但是我得到的試驗結果,卻是不可能錯的。