我的程式裡有一個實時走波功能,我想加入一個用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 陰溝累死~~