支持HW团队,就支付宝领取下面的红包吧! (打开支付宝就能领取!er1OEj73Uj), (打开支付宝收索“516503473”), 你领取消费,HW有奖励。红包使用无条件限制,有条件请注意是不是有病毒。

Login or Sign up | Validate
| Search

博主:初学MPEG

初学MPEG 本博客-采用Python的web框架Django与Mysql数据库,致力于对Python、Django的了解 与研究
Django技术QQ群:XXXXXXX
Python技术QQ群:XXXXXXX

Category

Keywords

本站最新博文

友情链接  

[转]SDL动画的硬件渲染(Hardware Render)(2)

类别:游戏 状态:游客可见,可回,会员可关联(良好) 阅读:4373 评论:0 时间:May 11, 2013, 4:28 p.m.
关键字:Hardware Render SDL

来源:http://www.cppblog.com/lf426/archive/2008/02/15/42773.html 作者:龙飞

1:需要修改的地方。

这里,我们真正的开始使用SDL的硬件渲染。首先,我们需要设置驱动的环境(以windows为例,我们设置为directx,Linux的设置请参考官方网站,我们这里预留为dga)。另外,如果要启动硬件加速,必须使用全屏模式(SDL_FULLSCREEN),所以,在前面的软件渲染中,我们也使用全屏以作对比。第三,硬件渲染需要打开双缓冲(SDL_DOUBLEBUF),至于为什么我们在最后讨论,我们还是先看看完整的代码。

2:硬件渲染演示程序完整的源代码。


#ifdef WIN32
#ifdef _DEBUG
#pragma comment (lib, "SDLd")
#pragma comment (lib, "SDLmaind")
#else
#pragma comment (lib, "SDL")
#pragma comment (lib, "SDLmain")
#endif
#endif /* WIN32 */


#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;
}

3:问题。

你可能发现除了鼠标指针不显示之外,没有其它问题——这其实不是好现象,因为应该和可能出现的问题,都被我们事先避免了,但是这样让我们离事情的本质越来越远。你可以尝试着关掉SDL_DOUBLEBUF位标看看是什么效果;或者,在前面渲染单帧的程序中使用硬件渲染同时打开双缓冲看看出现什么问题——这些正是我们下一节将要讨论的。
如果你迫不及待的想知道原因,并且英语也过关的话,对于硬件渲染可能会引发的问题,我给你推荐一篇SDL官方也推荐的论文:
http://www.linuxdevcenter.com/pub/a/linux/2003/08/07/sdl_anim.html
但是很不幸的是,我在试验的过程中发现这篇文章有很多问题,当然,也许是我错了。因为我仅仅把SDL作为了一个黑盒子来研究,但是我得到的试验结果,却是不可能错的。

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.
 

操作:

Please Login (or Sign Up) to leave a comment