Directx 11 Blue Screen of Death when Running my Program - c++

I'm trying to use the following code:
HRESULT hResult;
HDC hDC;
IDXGISurface1 *pSurface = NULL;
hResult = m_flashTexture->QueryInterface(__uuidof(IDXGISurface1), (void**)&pSurface);
hResult = pSurface->GetDC(TRUE, &hDC);
assert(SUCCEEDED(hResult));
m_flashPlayer->DrawFrame(hDC);
Where drawFrame is...
void CFlashDXPlayer::DrawFrame(HDC dc)
{
if (m_dirtyFlag)
{
IViewObject* pViewObject = NULL;
m_flashInterface->QueryInterface(IID_IViewObject, (LPVOID*) &pViewObject);
if (pViewObject != NULL)
{
// Combine regions
HRGN unionRgn, first, second = NULL;
unionRgn = CreateRectRgnIndirect(&m_dirtyRects[0]);
if (m_dirtyRects.size() >= 2)
second = CreateRectRgn(0, 0, 1, 1);
for (std::vector<RECT>::iterator it = m_dirtyRects.begin() + 1; it != m_dirtyRects.end(); ++it)
{
// Fill combined region
first = unionRgn;
SetRectRgn(second, it->left, it->top, it->right, it->bottom);
unionRgn = CreateRectRgn(0, 0, 1, 1);
CombineRgn(unionRgn, first, second, RGN_OR);
DeleteObject(first);
}
if (second)
DeleteObject(second);
RECT clipRgnRect; GetRgnBox(unionRgn, &clipRgnRect);
RECTL clipRect = { 0, 0, m_width, m_height };
// Fill background
if (m_transpMode != TMODE_FULL_ALPHA)
{
// Set clip region
SelectClipRgn(dc, unionRgn);
COLORREF fillColor = GetBackgroundColor();
HBRUSH fillColorBrush = CreateSolidBrush(fillColor);
FillRgn(dc, unionRgn, fillColorBrush);
DeleteObject(fillColorBrush);
// Draw to main buffer
HRESULT hr = pViewObject->Draw(DVASPECT_TRANSPARENT, 1, NULL, NULL, NULL, dc, &clipRect, &clipRect, NULL, 0);
assert(SUCCEEDED(hr));
}
else
{
if (m_alphaBlackDC == NULL)
{
// Create memory buffers
BITMAPINFOHEADER bih = {0};
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biBitCount = 32;
bih.biCompression = BI_RGB;
bih.biPlanes = 1;
bih.biWidth = LONG(m_width);
bih.biHeight = -LONG(m_height);
m_alphaBlackDC = CreateCompatibleDC(dc);
m_alphaBlackBitmap = CreateDIBSection(m_alphaBlackDC, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&m_alphaBlackBuffer, 0, 0);
SelectObject(m_alphaBlackDC, m_alphaBlackBitmap);
m_alphaWhiteDC = CreateCompatibleDC(dc);
m_alphaWhiteBitmap = CreateDIBSection(m_alphaWhiteDC, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&m_alphaWhiteBuffer, 0, 0);
SelectObject(m_alphaWhiteDC, m_alphaWhiteBitmap);
}
HRESULT hr;
HBRUSH fillColorBrush;
// Render frame twice - against white and against black background to calculate alpha
SelectClipRgn(m_alphaBlackDC, unionRgn);
COLORREF blackColor = 0x00000000;
fillColorBrush = CreateSolidBrush(blackColor);
FillRgn(m_alphaBlackDC, unionRgn, fillColorBrush);
DeleteObject(fillColorBrush);
hr = pViewObject->Draw(DVASPECT_TRANSPARENT, 1, NULL, NULL, NULL, m_alphaBlackDC, &clipRect, &clipRect, NULL, 0);
assert(SUCCEEDED(hr));
// White background
SelectClipRgn(m_alphaWhiteDC, unionRgn);
COLORREF whiteColor = 0x00FFFFFF;
fillColorBrush = CreateSolidBrush(whiteColor);
FillRgn(m_alphaWhiteDC, unionRgn, fillColorBrush);
DeleteObject(fillColorBrush);
hr = pViewObject->Draw(DVASPECT_TRANSPARENT, 1, NULL, NULL, NULL, m_alphaWhiteDC, &clipRect, &clipRect, NULL, 0);
assert(SUCCEEDED(hr));
// Combine alpha
for (LONG y = clipRgnRect.top; y < clipRgnRect.bottom; ++y)
{
int offset = y * m_width * 4 + clipRgnRect.left * 4;
for (LONG x = clipRgnRect.left; x < clipRgnRect.right; ++x)
{
BYTE blackRed = m_alphaBlackBuffer[offset];
BYTE whiteRed = m_alphaWhiteBuffer[offset];
m_alphaBlackBuffer[offset + 3] = 255 - (whiteRed - blackRed);
offset += 4;
}
}
// Blit result to target DC
BitBlt(dc, clipRgnRect.left, clipRgnRect.top,
clipRgnRect.right - clipRgnRect.left,
clipRgnRect.bottom - clipRgnRect.top,
m_alphaBlackDC, clipRgnRect.left, clipRgnRect.top, SRCCOPY);
}
DeleteObject(unionRgn);
pViewObject->Release();
}
m_dirtyFlag = false;
m_dirtyRects.clear();
m_dirtyUnionRect.left = m_dirtyUnionRect.top = LONG_MAX;
m_dirtyUnionRect.right = m_dirtyUnionRect.bottom = -LONG_MAX;
}
}
I also should mention that I set up m_flashTexture using the following:
D3D11_TEXTURE2D_DESC textureDesc;
ZeroMemory(&textureDesc, sizeof(textureDesc));
textureDesc.Width = width;
textureDesc.Height = height;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
textureDesc.SampleDesc.Count = 1;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
textureDesc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
HRESULT hr = device->CreateTexture2D(&textureDesc, NULL, &m_flashTexture);
Whenever I run this code (there is more to it but it is burried in a bunch of other classes, let me know if you think something else would be useful..) I get a blue screen of death that is caused somewhere in the flashPlayer->drawFrame() function. I have no idea what is causing the blue screen.
Any ideas or does any one see something that stands out that looks like it would cause a blue screen?
Thanks.
More Information
Here is the results from the crash dump
ADDITIONAL_DEBUG_TEXT:
Use '!findthebuild' command to search for the target build information.
If the build information is available, run '!findthebuild -s ; .reload' to set symbol path and load symbols.
FAULTING_MODULE: fffff80002c01000 nt
DEBUG_FLR_IMAGE_TIMESTAMP: 4d41a3e1
READ_ADDRESS: unable to get nt!MmSpecialPoolStart
unable to get nt!MmSpecialPoolEnd
unable to get nt!MmPoolCodeStart
unable to get nt!MmPoolCodeEnd
fffff8814061c6a0
FAULTING_IP:
igdpmd64+15a878
fffff880`0697c878 8b0408 mov eax,dword ptr [rax+rcx]
MM_INTERNAL_CODE: 5
CUSTOMER_CRASH_COUNT: 1
DEFAULT_BUCKET_ID: VISTA_DRIVER_FAULT
BUGCHECK_STR: 0x50
CURRENT_IRQL: 0
LAST_CONTROL_TRANSFER: from fffff80002c283bf to fffff80002c7dc40
STACK_TEXT:
fffff880`0a7e5878 fffff800`02c283bf : 00000000`00000050 fffff881`4061c6a0 00000000`00000000 fffff880`0a7e59e0 : nt+0x7cc40
fffff880`0a7e5880 00000000`00000050 : fffff881`4061c6a0 00000000`00000000 fffff880`0a7e59e0 00000000`00000005 : nt+0x273bf
fffff880`0a7e5888 fffff881`4061c6a0 : 00000000`00000000 fffff880`0a7e59e0 00000000`00000005 00000000`00000000 : 0x50
fffff880`0a7e5890 00000000`00000000 : fffff880`0a7e59e0 00000000`00000005 00000000`00000000 00000000`00000000 : 0xfffff881`4061c6a0
STACK_COMMAND: .bugcheck ; kb
FOLLOWUP_IP:
igdpmd64+15a878
fffff880`0697c878 8b0408 mov eax,dword ptr [rax+rcx]
SYMBOL_NAME: igdpmd64+15a878
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: igdpmd64
IMAGE_NAME: igdpmd64.sys
BUCKET_ID: WRONG_SYMBOLS
Followup: MachineOwner
Does anyone know what this means?

Any time you write a user space application and it causes a BSoD, then there is certainly a bug in some kernel level code (either the windows kernel itself, or some driver, in this case, it looks like igdpmd64.sys). Simply put, the OS should never, under any circumstances, crash due to something a user space application did. So I would look into whether or not there is an upgrade for this driver or not.
However, it is also probable that you have a bug in your code which is using DirectX incorrectly and is triggering this driver bug.
Certainly, I would try to create an absolutely minimal, complete program which triggers the crash. At the very least so you can submit it to the driver writers.

Related

How to display image using CreateDIBSection

I want to display a images on window, am giving image data as in buffer &CaptureBuffer to CreateDIBSection, CreateDIBForVideo method is calling from thread on main().
dont know where im going wrong it is showing black window.
void CreateDIBForVideo()
{
// ScreenCaptureProcessorGDI is a class it have initialization for capture window screen
screenObject = new ScreenCaptureProcessorGDI();
screenObject->init();
HDC DisplayDC = CreateDC((LPCWSTR)"DISPLAY", NULL, NULL, NULL);
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biSize= sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = screenObject->lOutputDuplDesc.ModeDesc.Width;
bmpInfo.bmiHeader.biHeight= screenObject->lOutputDuplDesc.ModeDesc.Height;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 32;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biSizeImage = (4 * screenObject->lOutputDuplDesc.ModeDesc.Width * screenObject->lOutputDuplDesc.ModeDesc.Height);
bmpInfo.bmiHeader.biXPelsPerMeter = 0;
bmpInfo.bmiHeader.biYPelsPerMeter = 0;
bmpInfo.bmiHeader.biClrUsed = 0;
bmpInfo.bmiHeader.biClrImportant = 0;
CaptureBuffer = NULL;
HDC pXorDC = CreateCompatibleDC(DisplayDC);
HBITMAP hXorDib = CreateDIBSection(DisplayDC, &bmpInfo, DIB_RGB_COLORS, (void**)&CaptureBuffer, NULL, 0);
hXorTemp = (HBITMAP)SelectObject(pXorDC, hXorDib);
// startGrab this thread capture a windows screen after init()
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&startGrab, NULL, 0, NULL);
}
void startGrab()
{
for (int index = 0; index < 100; index++)
{
// grabImage will capture window screen and send image as a buffer to `CaptureBuffer`
screenObject->grabImage();
PaintViewerWindow();
UpdateWindow(global_hWnd);
::Sleep(2000);
}
}
void PaintViewerWindow()
{
HDC paintDC;
PAINTSTRUCT ps;
paintDC = BeginPaint(global_hWnd, &ps);
SetStretchBltMode(paintDC, HALFTONE);
BitBlt(paintDC, 0, 0, 1366, 768, pXorDC, 0, 0, SRCCOPY);
EndPaint(global_hWnd, &ps);
}
I find a solution for the above problem
It because of UCHAR *CaptureBuffer am directly passing CaptureBuffer to the CreateDIBSection now i changed to copying UCHAR *CaptureBuffer to char *DisplayBuffer its working fine now.
UCHAR *CaptureBuffer = NULL;
char *DisplayBuffer = NULL;
long CaptureSize = NULL;
void saveImage(unsigned int frame_num, BITMAPINFO &lBmpInfo, std::unique_ptr<BYTE> pBuf, UCHAR* &CaptureBuffer, long &CaptureSize)
{
BITMAPFILEHEADER bmpFileHeader;
bmpFileHeader.bfReserved1 = 0;
bmpFileHeader.bfReserved2 = 0;
bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + lBmpInfo.bmiHeader.biSizeImage;
bmpFileHeader.bfType = 'MB';
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
CaptureSize = lBmpInfo.bmiHeader.biSizeImage;
CaptureBuffer = (UCHAR*)malloc(CaptureSize);
memcpy(CaptureBuffer, pBuf.get(), lBmpInfo.bmiHeader.biSizeImage);
//Here am copying CaptureBuffer(uchar) to DisplayBuffer(char)
memcpy(DisplayBuffer, CaptureBuffer, CaptureSize);
lresult = 0;
}
void CreateDIBForVideo()
{
// ScreenCaptureProcessorGDI is a class it have initialization for capture window screen
screenObject = new ScreenCaptureProcessorGDI();
screenObject->init();
HDC DisplayDC = CreateDC((LPCWSTR)"DISPLAY", NULL, NULL, NULL);
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biSize= sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = screenObject->lOutputDuplDesc.ModeDesc.Width;
bmpInfo.bmiHeader.biHeight= screenObject->lOutputDuplDesc.ModeDesc.Height;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 32;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biSizeImage = (4 * screenObject->lOutputDuplDesc.ModeDesc.Width * screenObject->lOutputDuplDesc.ModeDesc.Height);
bmpInfo.bmiHeader.biXPelsPerMeter = 0;
bmpInfo.bmiHeader.biYPelsPerMeter = 0;
bmpInfo.bmiHeader.biClrUsed = 0;
bmpInfo.bmiHeader.biClrImportant = 0;
CaptureBuffer = NULL;
HDC pXorDC = CreateCompatibleDC(DisplayDC);
HBITMAP hXorDib = CreateDIBSection(DisplayDC, &bmpInfo, DIB_RGB_COLORS, (void**)&DisplayBuffer, NULL, 0);
hXorTemp = (HBITMAP)SelectObject(pXorDC, hXorDib);
// startGrab this thread capture a windows screen after init()
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&startGrab, NULL, 0, NULL);
}

Getting HBITMAP from layered window - incorrect data

I created a layered window (with WS_EX_LAYERED), size of about 400X300 px.
When drawing the window (using UpdateLayeredWindow) everything works great.
The problem is that I'm unable to get the HBITMAP of the window after drawing it.
When trying to get the HBITMAP through the window's HDC, I get an empty (black) bitmap, the size of my entire desktop (1920X1080 px insted of 400X300 px).
Does anybody know if it is even possible to get the HDC\HBITMAP of a layered window?
Code samples
Here's the code of how I draw the layered window (again, works great):
void MyLayeredWindow::DrawLayered() const
{
RECT rcWindow;
GetWindowRect(rcWindow);
int nWidth = abs(rcWindow.right - rcWindow.left);
int nHeight = abs(rcWindow.bottom - rcWindow.top);
// Create 32Bit bitmap to apply transparency
// (have to set negative height because if not the (0,0) point would be the bottom left instead of top left)
VOID *ppvBits = NULL;
BITMAPINFO BitmapInfo = {0};
BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BitmapInfo.bmiHeader.biWidth = nWidth;
BitmapInfo.bmiHeader.biHeight = -nHeight;
BitmapInfo.bmiHeader.biPlanes = 1;
BitmapInfo.bmiHeader.biBitCount = 32;
BitmapInfo.bmiHeader.biCompression = BI_RGB;
// Copy view buffer to a temp DC and bitmap
HDC hDcTemp = ::CreateCompatibleDC(NULL);
assert(hDcTemp);
HBITMAP hBitmapTemp = ::CreateDIBSection(hDcTemp, &BitmapInfo, DIB_RGB_COLORS, &ppvBits, NULL, 0);
assert(hBitmapTemp && hBitmapTemp!=(HBITMAP)ERROR_INVALID_PARAMETER)
::SelectObject(hDcTemp, hBitmapTemp);
// Darwing the window's conent here
// ....
// ....
// Call UpdateLayeredWindow
BLENDFUNCTION blend = {0};
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 190;
blend.AlphaFormat = AC_SRC_ALPHA;
SIZE sizeWnd = {0};
sizeWnd.cx = nWidth;
sizeWnd.cy = nHeight;
POINT ptPos = {0};
ptPos.x = rcWindow.left;
ptPos.y = rcWindow.top;
POINT ptSrc = {0,0};
::UpdateLayeredWindow(m_hWnd, NULL, &ptPos, &sizeWnd, hDcTemp, &ptSrc, 0, &blend, ULW_ALPHA);
if(hDcTemp)
::DeleteDC(hDcTemp);
if(hBitmapTemp)
::DeleteObject(hBitmapTemp);
}
Here's the code of how I capture the window's bitmap and save it to a file:
(NOTICE: It works of "normal" windows, such as the Calculator)
bool MyLayeredWindow::SaveBitmapFile(__in const HWND& hWnd, __in const wstring& sFileName)
{
HDC hDC = ::GetDC(hWnd);
// get bitmap of DC
HBITMAP hBmp = (HBITMAP)::GetCurrentObject( hDC, OBJ_BITMAP );
// get info of bitmap
BITMAPINFO stBmpInfo;
stBmpInfo.bmiHeader.biSize = sizeof( stBmpInfo.bmiHeader );
stBmpInfo.bmiHeader.biBitCount = 0;
GetDIBits( hDC, hBmp, 0, 0, NULL, &stBmpInfo, DIB_RGB_COLORS );
// init info size
ULONG iBmpInfoSize;
switch( stBmpInfo.bmiHeader.biBitCount )
{
case 24:
iBmpInfoSize = sizeof(BITMAPINFOHEADER);
break;
case 16:
case 32:
iBmpInfoSize = sizeof(BITMAPINFOHEADER)+sizeof(DWORD)*3;
break;
default:
iBmpInfoSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * ( 1 << stBmpInfo.bmiHeader.biBitCount );
break;
}
// copy header
PBITMAPINFO pstBmpInfo = NULL;
if( iBmpInfoSize != sizeof(BITMAPINFOHEADER) )
{
pstBmpInfo = (PBITMAPINFO)GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, iBmpInfoSize );
PBYTE pbtBmpInfoDest = (PBYTE)pstBmpInfo;
PBYTE pbtBmpInfoSrc = (PBYTE)&stBmpInfo;
ULONG iSizeTmp = sizeof( BITMAPINFOHEADER );
while( iSizeTmp-- )
*( ( pbtBmpInfoDest )++ ) = *( ( pbtBmpInfoSrc )++ );
}
// create file
HANDLE hFile = CreateFile( sFileName.c_str(), GENERIC_WRITE, 0 , NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL );
// init bmp file header
BITMAPFILEHEADER stBmpFileHder = {0};
stBmpFileHder.bfType = 0x4D42; // 'BM'
stBmpFileHder.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + iBmpInfoSize + pstBmpInfo->bmiHeader.biSizeImage;
stBmpFileHder.bfReserved1 = 0;
stBmpFileHder.bfReserved2 = 0;
stBmpFileHder.bfOffBits = sizeof(BITMAPFILEHEADER) + iBmpInfoSize;
// write header to file
DWORD dRet;
WriteFile( hFile, (LPCVOID)&stBmpFileHder, sizeof(BITMAPFILEHEADER), &dRet, NULL );
// allocate size for rest of bmp (body)
PBYTE pBits = (PBYTE)GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, stBmpInfo.bmiHeader.biSizeImage );
// get bmp bits
HBITMAP hBmpOld;
HBITMAP hTmpBmp = CreateCompatibleBitmap( hDC, pstBmpInfo->bmiHeader.biWidth, pstBmpInfo->bmiHeader.biHeight );
hBmpOld = (HBITMAP)SelectObject( hDC, hTmpBmp );
GetDIBits( hDC, hBmp, 0, pstBmpInfo->bmiHeader.biHeight, (LPSTR)pBits, pstBmpInfo, DIB_RGB_COLORS );
// write bmp info
WriteFile( hFile, (LPCVOID)pstBmpInfo, iBmpInfoSize, &dRet, NULL );
// write bmp bits
WriteFile( hFile, (LPCVOID)pBits, pstBmpInfo->bmiHeader.biSizeImage, &dRet, NULL );
// release handles and free memory
SelectObject( hDC, hBmpOld );
DeleteObject( hTmpBmp );
CloseHandle( hFile );
GlobalFree( pstBmpInfo );
GlobalFree( pBits );
ReleaseDC( hWnd, hDC );
return true;
}
Thanks!
Since I didn't get any better answer, I simply called a "Draw" function that paints my layered window, onto a temporary HDC.
Meaning I don't copy existing bitmap, but create an identical one, using the same drawing function.
I'd still love to get a better answer for this question.

Directx 11 Bitblt Alternative

I have the following function which I am trying to integrate into my directx 11 application. When I am using directx9 everything works fine but when converting to directx 11 I am getting a blue screen of death error at the Bitblt line (I must be doing something wrong with the HDC's?). I was wondering what the best way to convert this code to directx 11 compatible surfaces instead of HDC's would be.
Here is the function:
void CFlashDXPlayer::DrawFrame(HDC dc)
{
if (m_dirtyFlag)
{
IViewObject* pViewObject = NULL;
m_flashInterface->QueryInterface(IID_IViewObject, (LPVOID*) &pViewObject);
if (pViewObject != NULL)
{
// Combine regions
HRGN unionRgn, first, second = NULL;
unionRgn = CreateRectRgnIndirect(&m_dirtyRects[0]);
if (m_dirtyRects.size() >= 2)
second = CreateRectRgn(0, 0, 1, 1);
for (std::vector<RECT>::iterator it = m_dirtyRects.begin() + 1; it != m_dirtyRects.end(); ++it)
{
// Fill combined region
first = unionRgn;
SetRectRgn(second, it->left, it->top, it->right, it->bottom);
unionRgn = CreateRectRgn(0, 0, 1, 1);
CombineRgn(unionRgn, first, second, RGN_OR);
DeleteObject(first);
}
if (second)
DeleteObject(second);
RECT clipRgnRect; GetRgnBox(unionRgn, &clipRgnRect);
RECTL clipRect = { 0, 0, m_width, m_height };
// Fill background
if (m_transpMode != TMODE_FULL_ALPHA)
{
// Set clip region
SelectClipRgn(dc, unionRgn);
COLORREF fillColor = GetBackgroundColor();
HBRUSH fillColorBrush = CreateSolidBrush(fillColor);
FillRgn(dc, unionRgn, fillColorBrush);
DeleteObject(fillColorBrush);
// Draw to main buffer
HRESULT hr = pViewObject->Draw(DVASPECT_TRANSPARENT, 1, NULL, NULL, NULL, dc, &clipRect, &clipRect, NULL, 0);
assert(SUCCEEDED(hr));
}
else
{
if (m_alphaBlackDC == NULL)
{
// Create memory buffers
BITMAPINFOHEADER bih = {0};
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biBitCount = 32;
bih.biCompression = BI_RGB;
bih.biPlanes = 1;
bih.biWidth = LONG(m_width);
bih.biHeight = -LONG(m_height);
m_alphaBlackDC = CreateCompatibleDC(dc);
m_alphaBlackBitmap = CreateDIBSection(m_alphaBlackDC, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&m_alphaBlackBuffer, 0, 0);
SelectObject(m_alphaBlackDC, m_alphaBlackBitmap);
m_alphaWhiteDC = CreateCompatibleDC(dc);
m_alphaWhiteBitmap = CreateDIBSection(m_alphaWhiteDC, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&m_alphaWhiteBuffer, 0, 0);
SelectObject(m_alphaWhiteDC, m_alphaWhiteBitmap);
}
HRESULT hr;
HBRUSH fillColorBrush;
// Render frame twice - against white and against black background to calculate alpha
SelectClipRgn(m_alphaBlackDC, unionRgn);
COLORREF blackColor = 0x00000000;
fillColorBrush = CreateSolidBrush(blackColor);
FillRgn(m_alphaBlackDC, unionRgn, fillColorBrush);
DeleteObject(fillColorBrush);
hr = pViewObject->Draw(DVASPECT_TRANSPARENT, 1, NULL, NULL, NULL, m_alphaBlackDC, &clipRect, &clipRect, NULL, 0);
assert(SUCCEEDED(hr));
// White background
SelectClipRgn(m_alphaWhiteDC, unionRgn);
COLORREF whiteColor = 0x00FFFFFF;
fillColorBrush = CreateSolidBrush(whiteColor);
FillRgn(m_alphaWhiteDC, unionRgn, fillColorBrush);
DeleteObject(fillColorBrush);
hr = pViewObject->Draw(DVASPECT_TRANSPARENT, 1, NULL, NULL, NULL, m_alphaWhiteDC, &clipRect, &clipRect, NULL, 0);
assert(SUCCEEDED(hr));
// Combine alpha
for (LONG y = clipRgnRect.top; y < clipRgnRect.bottom; ++y)
{
int offset = y * m_width * 4 + clipRgnRect.left * 4;
for (LONG x = clipRgnRect.left; x < clipRgnRect.right; ++x)
{
BYTE blackRed = m_alphaBlackBuffer[offset];
BYTE whiteRed = m_alphaWhiteBuffer[offset];
m_alphaBlackBuffer[offset + 3] = 255 - (whiteRed - blackRed);
offset += 4;
}
}
// Blit result to target DC
BitBlt(dc, clipRgnRect.left, clipRgnRect.top,
clipRgnRect.right - clipRgnRect.left,
clipRgnRect.bottom - clipRgnRect.top,
m_alphaBlackDC, clipRgnRect.left, clipRgnRect.top, SRCCOPY);
}
DeleteObject(unionRgn);
pViewObject->Release();
}
m_dirtyFlag = false;
m_dirtyRects.clear();
m_dirtyUnionRect.left = m_dirtyUnionRect.top = LONG_MAX;
m_dirtyUnionRect.right = m_dirtyUnionRect.bottom = -LONG_MAX;
}
}
The HDC I am passing to this function is created in the following manner:
D3D11_TEXTURE2D_DESC textureDesc;
ZeroMemory(&textureDesc, sizeof(textureDesc));
textureDesc.Width = width;
textureDesc.Height = height;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
textureDesc.SampleDesc.Count = 1;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
textureDesc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
HRESULT hr = device->CreateTexture2D(&textureDesc, NULL, &m_flashTexture);
HRESULT hResult;
HDC hDC;
IDXGISurface1 *pSurface = NULL;
hResult = m_flashTexture->QueryInterface(__uuidof(IDXGISurface1), (void**)&pSurface);
hResult = pSurface->GetDC(TRUE, &hDC);
assert(SUCCEEDED(hResult));
m_flashPlayer->DrawFrame(hDC);
Any ideas of what I am doing wrong? I can't seem to figure out what is going on and why this is casuing a blue screen when if I use Directx 9 obejcts it doesn't. Is there a better way to do this?
(Also I've tried updating my drivers and they are all up to date).
Thank you for the help.
Turns out that this was indeed a driver issue. It works without a problem when I run with my graphics card set to the radeon in my latop, but when I have it on switchable for some reason it still crashes even though it should be selecting my radeon. I need to have the graphics mode fixed. Weird, but atleast its not my program I guess.
Can't really tell from code inspection. I haven't noticed anything blatantly wrong. There certainly should not be a any BSOD - that part is a driver bug. What hardware/driver are you running on?
A common reason for driver crashes though is illegally writing to some memory area, often if you're blitting to outside of your DC memory. I'd double check to verify that your regions are not out of bounds and that m_alphaBlackDC is the same size as dc.
I would also highly, highly recommend testing on another non-related GPU (that doesn't share the same hardware architecture).

why CreateDIBSection() fails with certian BITMAPINFO?

I am trying to use CreateDIBSection.
Problem:
In Windows XP, I tried to call CreateDIBSection, it returns NULL and GetLastError = 0
When I try to change the screen resolution, for example to 2048 x 1536, it returns correct value.
I have tested this function has some relationship with nMemSize (not necessarily small number).
Question:
Is there any guarantee way to ensure CreateDIBSection returns correct value?
nScreenWidth = 1024;
nScreenHeight= 768;
= nScreenWidth*nScreenHeight*3*7
HDC hdc = ::GetDC(hWnd);
m_hBmpMapFile = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, nMemSize, NULL);
BITMAPINFO bmpInfo = {0};
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = nScreenWidth;
bmpInfo.bmiHeader.biHeight = nScreenHeight;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 24;
bmpInfo.bmiHeader.biCompression = 0;
bmpInfo.bmiHeader.biSizeImage = nMemSize;
bmpInfo.bmiHeader.biXPelsPerMeter = 0;
bmpInfo.bmiHeader.biYPelsPerMeter = 0;
bmpInfo.bmiHeader.biClrUsed = 0;
bmpInfo.bmiHeader.biClrImportant = 0;
bmpInfo.bmiColors[0].rgbBlue = 204;
bmpInfo.bmiColors[0].rgbGreen = 204;
bmpInfo.bmiColors[0].rgbRed = 204;
bmpInfo.bmiColors[0].rgbReserved = 0;
PVOID pvBits;
m_hBmpAllWstDskWallpaper = ::CreateDIBSection(hdc, &bmpInfo, DIB_RGB_COLORS, &pvBits, m_hBmpMapFile, 0);
I suspect the problem might be contained in the section of code that you did not include (in the elipses ...). So I recommend:
Check your Device Context is valid
ZeroMemory
Add the structure size
And bitmap dimensions
Move the GetLastError calls to ensure that the Device Context is valid (perhaps an earlier API call fails)
The code below seems to work after I added the recommendations above, I hope it helps:
HDC hdc = ::GetDC(hWnd);
int nScreenWidth = 1024;
int nScreenHeight= 768;
int nMemSize = nScreenWidth*nScreenHeight*3*7;
HANDLE m_hBmpMapFile = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, nMemSize, NULL);
BITMAPINFO bmpInfo;
//clear the memory
ZeroMemory(&bmpInfo.bmiHeader, sizeof(BITMAPINFOHEADER));
//struct size
bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
//dimensions
bmpInfo.bmiHeader.biWidth = nScreenWidth;
bmpInfo.bmiHeader.biHeight = nScreenHeight;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 32;
bmpInfo.bmiHeader.biSizeImage=nMemSize;
void *pvBits = NULL;
HANDLE m_hBmpAllWstDskWallpaper = ::CreateDIBSection(hdc, &bmpInfo, DIB_RGB_COLORS, &pvBits, m_hBmpMapFile, 0);
int nError = ::GetLastError();

StretchBlt and filtering alpha channels

I am scaling an image down with StretchBlt().
http://img684.imageshack.us/img684/2152/stretchblt.png
As you can see, it currently looks like I have to choose between quality filtering and transparency. Is there any way to get both? This is the only image operation I need to perform, so I'd prefer to avoid extra libraries.
My code:
HDC srcDC = CreateCompatibleDC(NULL);
SelectObject(srcDC, *phbmp);
HDC destDC = CreateCompatibleDC(srcDC);
HBITMAP NewBMP = CreateCompatibleBitmap(srcDC,NewWidth,NewHeight);
SelectObject(destDC,NewBMP);
SetStretchBltMode(destDC,HALFTONE);
SetBrushOrgEx(destDC,0,0,NULL);
if (StretchBlt(destDC,0,0,NewWidth,NewHeight,srcDC,0,0,width,height,SRCCOPY) == TRUE)
{
DeleteObject(*phbmp);
*phbmp = NewBMP;
hr = S_OK;
}
else
DeleteObject(NewBMP);
DeleteDC(srcDC);
DeleteDC(destDC);
Gave up entirely on GDI in the end. Turns out that the proper way of doing this is, of course, with IWICImagingFactory. Final code:
IWICImagingFactory *pImgFac;
hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pImgFac));
IWICBitmap* NewBmp;
hr = pImgFac->CreateBitmapFromHBITMAP(*phbmp,0,WICBitmapUseAlpha,&NewBmp);
BITMAPINFO bmi = {};
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = NewWidth;
bmi.bmiHeader.biHeight = -NewHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
BYTE *pBits;
HBITMAP hbmp = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0);
hr = hbmp ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr))
{
IWICBitmapScaler* pIScaler;
hr = pImgFac->CreateBitmapScaler(&pIScaler);
hr = pIScaler->Initialize(NewBmp,NewWidth,NewHeight,WICBitmapInterpolationModeFant);
WICRect rect = {0, 0, NewWidth, NewHeight};
hr = pIScaler->CopyPixels(&rect, NewWidth * 4, NewWidth * NewHeight * 4, pBits);
if (SUCCEEDED(hr))
*phbmp = hbmp;
else
DeleteObject(hbmp);
pIScaler->Release();
}
NewBmp->Release();
pImgFac->Release();