/** * Copyright 1993-2013 NVIDIA Corporation. All rights reserved. * * Please refer to the NVIDIA end user license agreement (EULA) associated * with this source code for terms and conditions that govern your use of * this software. Any use, reproduction, disclosure, or distribution of * this software and related documentation outside the terms of the EULA * is strictly prohibited. * */ //////////////////////////////////////////////////////////////////////////////// // // Utility funcs to wrap up savings a surface or the back buffer as a PPM file // In addition, wraps up a threshold comparision of two PPMs. // // These functions are designed to be used to implement an automated QA testing for SDK samples. // // Author: Bryan Dudash // Email: sdkfeedback@nvidia.com // // Copyright (c) NVIDIA Corporation. All rights reserved. //////////////////////////////////////////////////////////////////////////////// #include #include // originally copied from checkrender_gl.cpp and slightly modified bool CheckRenderD3D9::PPMvsPPM(const char *src_file, const char *ref_file, const char *exec_path, const float epsilon, const float threshold) { char *ref_file_path = sdkFindFilePath(ref_file, exec_path); if (ref_file_path == NULL) { printf("CheckRenderD3D9::PPMvsPPM unable to find <%s> in <%s> Aborting comparison!\n", ref_file, exec_path); printf(">>> Check info.xml and [project//data] folder <%s> <<<\n", ref_file); printf("Aborting comparison!\n"); printf(" FAILURE!\n"); return false; } return (sdkComparePPM(src_file, ref_file_path, epsilon, threshold, true) == true); }; HRESULT CheckRenderD3D9::BackbufferToPPM(IDirect3DDevice9 *pDevice, const char *zFileName) { IDirect3DSurface9 *pSurface = NULL; if (FAILED(pDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO, &pSurface))) { printf("Unable to get the back buffer. Aborting...\n"); return E_FAIL; } //D3DXSaveSurfaceToFile("C:\\bing.dds",D3DXIFF_DDS,pSurface,NULL,NULL); HRESULT hr = S_OK; hr = SurfaceToPPM(pDevice,pSurface,zFileName); pSurface->Release(); return hr; } HRESULT CheckRenderD3D9::SurfaceToPPM(IDirect3DDevice9 *pDevice, IDirect3DSurface9 *pSurface, const char *zFileName) { D3DSURFACE_DESC pDesc; pSurface->GetDesc(&pDesc); // $$ For now only support common 8bit formats. TODO: support for more complex formats via conversion? if (!(pDesc.Format == D3DFMT_A8R8G8B8 || pDesc.Format == D3DFMT_X8R8G8B8)) { return E_INVALIDARG; } IDirect3DTexture9 *pTargetTex = NULL; if (FAILED(pDevice->CreateTexture(pDesc.Width,pDesc.Height,1,D3DUSAGE_DYNAMIC,pDesc.Format,D3DPOOL_SYSTEMMEM,&pTargetTex,NULL))) { printf("Unable to create texture for surface transfer! Aborting...\n"); return E_FAIL; } IDirect3DSurface9 *pTargetSurface = NULL; if (FAILED(pTargetTex->GetSurfaceLevel(0,&pTargetSurface))) { printf("Unable to get surface for surface transfer! Aborting...\n"); return E_FAIL; } // This is required because we cannot lock a D3DPOOL_DEAULT surface directly. So, we copy to our sysmem surface. if (FAILED(pDevice->GetRenderTargetData(pSurface,pTargetSurface))) { printf("Unable to GetRenderTargetData() for surface transfer! Aborting...\n"); return E_FAIL; } D3DLOCKED_RECT lockedRect; HRESULT hr = pTargetSurface->LockRect(&lockedRect,NULL,0); // Need to convert from dx pitch to pitch=width // // $ PPM is BGR and not RGB it seems. Saved image looks "funny" in viewer(red and blue swapped), but since ref will be dumped using same method, this is ok. // however, if we want the saved image to be properly colored, then we can swizzle the color bytes here. unsigned char *pPPMData = new unsigned char[pDesc.Width*pDesc.Height*4]; for (unsigned int iHeight = 0; iHeightB, [7:0] <-> [23:16], swizzle color = ((color&0xFF)<<16) | (color&0xFF00) | ((color&0xFF0000)>>16) | (color&0xFF000000); memcpy(&(pPPMData[(iHeight*pDesc.Width + iWidth)*4]),(unsigned char *)&color,4); } #else memcpy(&(pPPMData[iHeight*pDesc.Width*4]),(unsigned char *)(lockedRect.pBits)+iHeight*lockedRect.Pitch,pDesc.Width*4); #endif } pTargetSurface->UnlockRect(); // Prepends the PPM header info and bumps byte data afterwards sdkSavePPM4ub(zFileName, pPPMData, pDesc.Width, pDesc.Height); delete [] pPPMData; pTargetSurface->Release(); pTargetTex->Release(); return S_OK; }