加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

winapi – 为什么我的Win32 gdi游戏在Windows 7上速度非常慢?

发布时间:2020-12-14 05:39:13 所属栏目:Windows 来源:网络整理
导读:[本条目底部的重要新信息如下] 我相信使用GDI是一个非常标准的游戏循环.它工作得相当好(复杂游戏大约25 fps, Vista和XP上的简单游戏40 fps.当我在Windows 7上运行它时(CPU速度更快,内存更多), 它慢慢减速,游戏无法使用(我随处可见 从0 fps到4 fps).我在下面
[本条目底部的重要新信息如下]

我相信使用GDI是一个非常标准的游戏循环.它工作得相当好(复杂游戏大约25 fps,
Vista和XP上的简单游戏40 fps.当我在Windows 7上运行它时(CPU速度更快,内存更多),
它慢慢减速,游戏无法使用(我随处可见
从0 fps到4 fps).我在下面列出了我认为代码的相关部分.正如我所说,我相信这一点
是使用GDI的最简单的(基于内存位图的)游戏循环.你可以在下面看到我为加速事情所做的两次尝试
起来.首先,我担心如果比WM_PAINT消息更频繁地调用InvalidateRect()
发送,系统正在把这作为一个线索,我的程序是坏/慢,并扣留我的时间片.所以我补充道
paintIsPending标志,以确保每个油漆不会多次失效.这没有改善.第二,我
在下面的OPTIONAL SECTION中添加了代码,认为如果我自己触发WM_PAINT消息而不是
等待它发送的东西会更好.再一次,没有改善.

对我来说,像这样的简单GDI游戏循环会在Windows 7上消失似乎很疯狂.我知道存在一些差异
在Windows 7如何处理2D图形加速,但这个代码似乎是如此基本,很难相信它会
没有功能.此外,我知道我可以切换到DirectX,我可能会这样做,但目前有相当数量的投资
在下面的DrawGameStuff(图形)调用代表的代码库中,如果可能的话我宁愿不重写它.

谢谢你的帮助.

#define CLIENT_WIDTH 320
#define CLIENT_HEIGHT 480

Graphics *graphics;
HDC memoryDC;
HBITMAP memoryBitmap;
bool paintIsPending = false;

void InitializeEngine( HDC screenDC )
{
    memoryDC = CreateCompatibleDC( screenDC );
    memoryBitmap = CreateCompatibleBitmap( screenDC,CLIENT_WIDTH,CLIENT_HEIGHT );
    SelectObject( memoryDC,memoryBitmap );
    graphics = new Graphics( memoryDC );

    ...
}

BOOL InitInstance( HINSTANCE hInstance,int nCmdShow )
{
    ...
    InitializeEngine( GetWindowDC( hWnd ) );
    ...
    myTimer = SetTimer( hWnd,timerID,1000 / 60,NULL );
    ...
}

void DrawScreen( HDC hdc )
{
    graphics->Clear( Color( 255,200,255 ) );

    DrawGameStuff( graphics );

    BitBlt( hdc,CLIENT_HEIGHT,memoryDC,SRCCOPY );
}

LRESULT CALLBACK WndProc( HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam )
{
    ...
    case WM_TIMER:
        if ( !paintIsPending )
        {
            paintIsPending = true;
            InvalidateRect( hWnd,NULL,false );
            /////// START OPTIONAL SECTION
            UpdateWindow( hWnd );
            ValidateRect( hWnd,NULL );
            /////// END OPTIONAL SECTION
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint( hWnd,&ps );
        DrawScreen( hdc );
        EndPaint( hWnd,&ps );
        paintIsPending = false;
        break;
    ...
}

啊哈!根据Chris Becke的线索,我现在有更多非常相关的信息.我确信这是BitBlt()很慢而不是图形 – > Clear(),但是当我注释掉图形时,我看到了> Clear()我在Windows 7上突然得到40 FPS.所以然后我将graphics-> Clear()更改为

// graphics->Clear( Color( 255,255 ) );
SolidBrush brush( Color( 255,255 ) );
graphics->FillRectangle( &brush,CLIENT_HEIGHT );

并且它看起来仍然以40 FPS运行.我不知道为什么FillRectangle()调用比Clear()调用更快.

然后我开始添加我的游戏绘图代码,我立即找到另一个杀死它的调用:绘制游戏内容我使用精灵将精灵绘制到memoryDC中

graphics->DrawImage( myImageThatCameFromAPngFile,destx,desty,srcx,srcy,width,height,UnitPixel );

那些电话也很慢.作为实验,我从PNG文件预先绘制到与screenDC兼容的第二个memoryDC中.然后,为了绘制我的精灵,我从这个辅助memoryDC绘制到我的主memoryDC中.所以我没有上面的DrawImage调用,而是:

BitBlt( memoryDC,secondaryMemoryDC,SRCCOPY );

并且,当我这样做时,整个游戏在Windows 7上以40 FPS运行.

然而,这不是一个真正的解决方案,因为在预渲染到二级存储器DC时,我丢失了PNG文件中的透明度信息,所以我的精灵现在都是不透明和丑陋的.

所以我的问题似乎是memoryDC(创建与screenDC兼容)和PNG源文件之间不兼容.我不明白为什么这种不兼容性存在(或者至少,为什么它会减慢这么多东西)只在Windows 7上.有没有办法保存PNG文件从一开始就与屏幕兼容?或者在一开始就在内部重新渲染它以获得与屏幕兼容的新PNG文件?嗯….

好的,所以我能够通过将其渲染到32bpp HBITMAP来正确渲染我的PNG文件,如下所示:

HDC hdc = CreateCompatibleDC( GetWindowDC( hWnd ) );
    Bitmap *bitmap = new Bitmap( image->GetWidth(),image->GetHeight(),PixelFormat32bppARGB );
    HBITMAP hbitmap;
    bitmap->GetHBITMAP( Color( 0,0 ),&hbitmap );
    SelectObject( hdc,hbitmap );

    Graphics *g = new Graphics( hdc );
    g->DrawImage( pngImage,pngImage->GetWidth(),pngImage->GetHeight(),UnitPixel );

然后使用AlphaBlend()渲染它:

_BLENDFUNCTION bf;
    bf.BlendOp = AC_SRC_OVER;
    bf.BlendFlags = 0;
    bf.SourceConstantAlpha = 255;
    bf.AlphaFormat = AC_SRC_ALPHA;
    AlphaBlend( memoryDC,hdc,bf );

所以现在我的游戏在Windows 7上运行得很快.

但是我仍然不明白为什么我必须为Windows 7完成所有这些操作.为什么使用DrawImage()的PNG图像的默认绘图在Windows 7上如此之慢?

解决方法

我不知道这是否是您当前代码速度慢的原因,但更有效的双缓冲解决方案是仅在WM_PAINT处理程序中执行BitBlt,并在WM_TIMER处理程序中调用DrawGameStuff.这样你在绘画过程中唯一要做的就是将后台缓冲区复制到屏幕上,实际的绘图逻辑可以在不同的时间发生.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读