CSDN特别收录 --- DirectDraw中使用Lock()锁定出现的问题

原创 2007年10月01日 23:49:00

我的程序里有一个实时走波功能,我想加入一个用DirectX7来显示帧动画的模块。SetCooperativeLevel时设置了全屏和排它,然后调用Lock()锁定表面读取图片属性并将图片画到表面上去。
    运行时能看到动画,也能看到没加入新模块之前的走波,就是走波变的不够顺畅,走一下停一下的,感觉有点卡。本人认为是Lock()方法出的问题,请大家给个解决方法。
=========================================

查了资料说IDirectDrawSurface7::Lock  IDirectDrawSurface7::Unlock方法加解锁可以使用the IDirectDrawSurface7::GetDC方法来代替,不知道要怎么修改?我显示帧图片的主要程序如下:
D3DTextr_RestoreAllTextures( m_pd3dDevice );

// Lock the surface and put the stereo signature in it
LPDIRECTDRAWSURFACE7 pSurface = D3DTextr_GetSurface( TEXT(strPictureFile) );

    DDSURFACEDESC2 ddsd;
    ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize = sizeof(ddsd);
    pSurface->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_DONOTWAIT |DDLOCK_NOSYSLOCK | DDLOCK_WRITEONLY, NULL);

    LPNVSTEREOIMAGEHEADER pStereoImageHeader = (LPNVSTEREOIMAGEHEADER)(((unsigned char *) ddsd.lpSurface) + (ddsd.lPitch * (ddsd.dwHeight - 1)));
    pStereoImageHeader->dwSignature = NVSTEREO_IMAGE_SIGNATURE;

    pStereoImageHeader->dwBPP = ddsd.ddpfPixelFormat.dwRGBBitCount;
#if 0
    // If you want to stretch the source image to fit into the destination surface.
    // ATTN!!! This feature works in Nvidia drivers starting with Rel.40
    //pStereoImageHeader->dwFlags = SIH_SWAP_EYES | SIH_SCALE_TO_FIT;
#else
    pStereoImageHeader->dwFlags = SIH_SWAP_EYES;
#endif
    pStereoImageHeader->dwWidth = ddsd.dwWidth; //The surface has both eyes side by side. The actual displayed width is sdDesc.Width/2
    pStereoImageHeader->dwHeight = ddsd.dwHeight;

pSurface->Unlock(NULL);

// Set up the blit rectangles
RECT rDest = {0, 0, 0, 0};
RECT rSrc = {0, 0, ddsd.dwWidth, ddsd.dwHeight};

    // Adjust the destination rect according to the aspect ratio...
    int nXCenter = m_pDeviceInfo->ddsdFullscreenMode.dwWidth / 2;
    int nYCenter = m_pDeviceInfo->ddsdFullscreenMode.dwHeight / 2;
    int nBltWidth = ddsd.dwWidth / 2;
    float fImageAspect = ((float) nBltWidth) / ((float) ddsd.dwHeight);
    float fDisplayAspect = ((float) m_pDeviceInfo->ddsdFullscreenMode.dwWidth) / ((float) m_pDeviceInfo->ddsdFullscreenMode.dwHeight);
   
    if(fImageAspect > fDisplayAspect) {
        rDest.left = 0;
        rDest.right = m_pDeviceInfo->ddsdFullscreenMode.dwWidth;
       
        int nTmpHeight = (int) ((float) m_pDeviceInfo->ddsdFullscreenMode.dwWidth / fImageAspect);
        rDest.top = nYCenter - (nTmpHeight / 2);
        rDest.bottom = rDest.top + nTmpHeight;
    }
    else {
        rDest.top = 0;
        rDest.bottom = m_pDeviceInfo->ddsdFullscreenMode.dwHeight;
       
        int nTmpWidth = (int) ((float) m_pDeviceInfo->ddsdFullscreenMode.dwHeight * fImageAspect);
        rDest.left = nXCenter - (nTmpWidth / 2);
        rDest.right = rDest.left + nTmpWidth;
    }

// Fill in the blit fx structure
    DDBLTFX DDBltFx;
    memset (&DDBltFx, 0, sizeof (DDBLTFX));
    DDBltFx.dwSize = sizeof (DDBLTFX);
    DDBltFx.dwROP = SRCCOPY;
    DDBltFx.dwFillColor = 0;    // Black

// Clear and Blit to the back buffer and flip
LPDIRECTDRAWSURFACE7 pRenderTarget;
m_pd3dDevice->GetRenderTarget(&pRenderTarget);
pRenderTarget->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &DDBltFx); // Clear it
HRESULT hRes = pRenderTarget->Blt(&rDest, pSurface, &rSrc, DDBLT_ROP | DDBLT_WAIT, &DDBltFx);
pRenderTarget->Release();
m_pFramework->ShowFrame();

    return S_OK;
 ===============================================

再问一下IDirectDrawSurface7::Lock 方法锁内存的问题:

上网查资料时看过这样一句话:对创建平面的内存上锁,是保证你的程序和系统不能同时对此内存进行存取.这防止你写入"平面"内存时发生错误.

——用Lock 方法时我的主程序是不是也不能访问内存的?我实时走波的那个功能是不是就受这个的影响?
=================================================

怎么没人关注呢,回复有用者加分~~~                                    /////////////////////////汗了  !!-_-!!
=================================

怎么刷新的?
====================================================

来到m_pFramework->ShowFrame();这里就刷新了。
HRESULT CD3DFramework7::ShowFrame()
{
    if( NULL == m_pddsFrontBuffer )
        return D3DFWERR_NOTINITIALIZED;

    if( m_bIsFullscreen )
    {
        // We are in fullscreen mode, so perform a flip.
        if( m_bIsStereo )
            return m_pddsFrontBuffer->Flip( NULL, DDFLIP_WAIT | DDFLIP_STEREO );
        else
            return m_pddsFrontBuffer->Flip( NULL, DDFLIP_WAIT );
    }
    else
    {
        // We are in windowed mode, so perform a blit.
        return m_pddsFrontBuffer->Blt( &m_rcScreenRect, m_pddsBackBuffer,
                                       NULL, DDBLT_WAIT, NULL );
    }
}
==========================================

我是说你2楼的代码是在哪里被调用的?
================================================

是在InitDeviceObjects这个函数里被调用的,而这个函数在下面被调用

HRESULT CD3DApplication::Initialize3DEnvironment()
{
    HRESULT hr;
    DWORD   dwFrameworkFlags = 0L;
    dwFrameworkFlags |= ( !m_pDeviceInfo->bWindowed ? D3DFW_FULLSCREEN : 0L );
    dwFrameworkFlags |= (  m_pDeviceInfo->bStereo   ? D3DFW_STEREO     : 0L );
    dwFrameworkFlags |= (  m_bAppUseZBuffer         ? D3DFW_ZBUFFER    : 0L );

    // Initialize the D3D framework
    if( SUCCEEDED( hr = m_pFramework->Initialize( m_hWnd,
                     m_pDeviceInfo->pDriverGUID, m_pDeviceInfo->pDeviceGUID,
                     &m_pDeviceInfo->ddsdFullscreenMode, dwFrameworkFlags ) ) )
    {
        m_pDD        = m_pFramework->GetDirectDraw();
        m_pD3D       = m_pFramework->GetDirect3D();
        m_pd3dDevice = m_pFramework->GetD3DDevice();

        m_pddsRenderTarget     = m_pFramework->GetRenderSurface();
        m_pddsRenderTargetLeft = m_pFramework->GetRenderSurfaceLeft();

        m_ddsdRenderTarget.dwSize = sizeof(m_ddsdRenderTarget);
        m_pddsRenderTarget->GetSurfaceDesc( &m_ddsdRenderTarget );

        // Let the app run its startup code which creates the 3d scene.
        if( SUCCEEDED( hr = InitDeviceObjects() ) )——————————————调用处
            return S_OK;
        else
        {
            DeleteDeviceObjects();
            m_pFramework->DestroyObjects();
        }
    }

    // If we get here, the first initialization passed failed. If that was with a
    // hardware device, try again using a software rasterizer instead.
    if( m_pDeviceInfo->bHardware )
    {
        // Try again with a software rasterizer
        DisplayFrameworkError( hr, MSGWARN_SWITCHEDTOSOFTWARE );
        D3DEnum_SelectDefaultDevice( &m_pDeviceInfo, D3DENUM_SOFTWAREONLY );
        return Initialize3DEnvironment();
    }

    return hr;
}

===============================================

好惨,自己来顶
==============================================

怎么还没人来呀?能帮解决的再加一百分
============================================

代码太长了,估计没多少人愿意看。
DirectDraw的绘图效率挺高的,如果是系统卡的话,那就是你每次绘图的时候做的操作过多了,如果是画面卡的话,那就是你没有及时刷新屏幕。
问题应该不在Lock上,LZ方向错误。单从你的函数名InitDeviceObjects就似乎是说此函数只在初始化时运行一次,如果真是这样的话,画面又怎么可能及时刷新呢?
=====================================

不是画面卡,是在运行过程中,非主画面的东西感觉有点卡

Lock锁的是整个内存吗?
加100分了
========================================

不是整个内存,只是那个表面自己部分的内存,虽然没有尝试过开两个线程去同时访问这块内存,不过我猜想Lock他的实现可能是这样的:
1、初始时某个信号量为1。
2、Lock时先等待这个信号量,如果为1则减到0并返回这块内存的首地址,如果为0则一直等待。
3、Unlock时将此信号加1。
以上只是猜想,因为自己做多线程的内存互斥访问的时候,也经常使用类似伎俩,所以Lock的实现未必真是如我所说,不过它绝对不是锁整个内存。

===================================

不过如果你是把桌面或整个应用程序的主窗口的表面给锁了,那么他们自己的绘图肯定绘不上去了。
=========================================

我运行第一次InitDeviceObjects()的时候不再让它运行我的实时画波功能就正常,而只要我再一次调用画波就不正确了,而且断断续续的
===============================================

我也觉得是你理解错了,Lock一般是在刷新的时候用于填充画面的。
==================================================

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

==================================================

我顶你个肺啊!以我现在的水平还看不懂!不是语法不明白,就是不了解这个DirectX平台,学完MFC才能开始了解这个平台,不过学完MFC的时候应当要考本科了,计算机图形学留在大学研究啦~~~TMD

//程序注释还是E文的哈~~

//The commentary for the program  is  阴沟累死~~

 

Directdraw新手入门(二)

今天我们将分别使用调色板和RGB模式来熟悉DirectDraw的基本图形。它们有什么不同呢?如果你曾经在DOS下编程,你可能使用过调色板映射模式。调色板是个颜色查询表,为了绘制象素,你将一个单独的字节...
  • butcher986115
  • butcher986115
  • 2016年01月27日 18:02
  • 404

D3DLOCK的用法分析

Direct3D 程序设计中,
  • berookie
  • berookie
  • 2014年07月27日 11:16
  • 808

D3DLOCK详解

一个或者多个组合的锁定选项,用来描述资源锁定类型的表现。 D3DLOCK_DISCARD: 使用方式会强制为:D3DUSAGE_DYNAMIC。 应用程序将会丢弃锁定区域内的所有内存。对于顶点和...
  • Blues1021
  • Blues1021
  • 2014年11月23日 10:40
  • 2466

创建一个关联有"后备缓冲"的"主表面"(即复杂表面,Complex Surface)

离屏表面有两类:第一种叫做后备缓冲(Back  Buffer)。 后备缓冲是指一些用在动画链中的表面,它们具有和主表面相同的尺寸和色深。后备缓冲表面比较独特,因为当你创建主表面时 也创建也它们(通...
  • yaoxinchao
  • yaoxinchao
  • 2012年07月18日 10:26
  • 1948

CSDN特别收录 --- DirectDraw中使用Lock()锁定出现的问题

我的程序里有一个实时走波功能,我想加入一个用DirectX7来显示帧动画的模块。SetCooperativeLevel时设置了全屏和排它,然后调用Lock()锁定表面读取图片属性并将图片画到表面上去。...
  • benny5609
  • benny5609
  • 2007年10月01日 23:49
  • 2701

调用DirectDraw7接口对象

我们都知道DirectDraw有很多个不同的接口,拿Direct X 8.0来说它提供的DirectDraw接口有: l IDirectDraw l IDirectDraw2 l IDirect...
  • juan380649731
  • juan380649731
  • 2013年02月25日 15:34
  • 760

directdraw显示yuv视频,出现屏保时,yuv显示不出来,表面丢失

原因是: DDrawSurface 丢失, DDraw表面在很多情况下都会丢失(如:启动其他全屏独占程序,屏保,或锁屏时), 表面丢失其实就是表面所使用的内存或显存被DirectDraw系统释放, ...
  • smilestone322
  • smilestone322
  • 2012年02月24日 10:25
  • 2501

如何使用DirectDraw直接显示RGB、YUV视频数据(播放yuv)

1.在DirectDraw中创建YUV表面   与一般表面不同的是,创建YUV表面时需要指定象素格式,并指定YUV数据的FourCC码,关于FourCC码可以参考微软MSDN站点上的说明,下面是具体的...
  • mao0514
  • mao0514
  • 2013年11月09日 09:39
  • 2016

双缓冲技术 directdraw

双缓冲技术   在离屏缓冲绘制图像,然后将其拷贝到显示表面的处理过程被称作双缓冲技术。 实现:额外的一块同主DirectDraw表面具有同样尺寸的内存。并在这块内存上画每一帧动画之后...
  • woaicide
  • woaicide
  • 2016年11月04日 18:34
  • 172

关于 Direct Blt 0x887601AE (DDERR_SURFACEBUSY) 和函数指针

0x887601ae(0x887601ae, "DDERR_SURFACEBUSY", "Access to this surface is being refused because the s...
  • u013115296
  • u013115296
  • 2014年05月18日 22:16
  • 1048
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:CSDN特别收录 --- DirectDraw中使用Lock()锁定出现的问题
举报原因:
原因补充:

(最多只允许输入30个字)