// Verifies that directory exists. // Returns success if the directory exists and is readable (failure may mean // it's busy or permissions denied on win32) //----------------------------------------------------------------------------- CPUTResult CPUTFileSystem::DoesDirectoryExist(const cString &path) { #ifdef CPUT_OS_ANDROID // On Android, all files are in the APK and are compressed. // We do not have access to the standard file system, so // all files need streaming from memory through the android asset manager AAssetManager* assetManager = CPUTWindowAndroid::GetAppState()->activity->assetManager; AAssetDir* AssetDir = AAssetManager_openDir(assetManager, path.c_str()); if (AssetDir) return CPUT_SUCCESS; #else struct stat fileAttributes; int result = stat(path.c_str(), &fileAttributes); if (result == -1) { DEBUG_ERROR(strerror(errno)); result = CPUT_ERROR; } if (S_ISDIR(fileAttributes.st_mode)) { return CPUT_SUCCESS; } #endif return CPUT_ERROR; }
// Read the entire contents of a file and return a pointer/size to it //----------------------------------------------------------------------------- CPUTResult CPUTFileSystem::ReadFileContents(const cString &fileName, UINT *pSizeInBytes, void **ppData, bool bAddTerminator, bool bLoadAsBinary) { FILE *pFile = NULL; errno_t err; if (bLoadAsBinary) { #if defined (UNICODE) || defined(_UNICODE) err = _wfopen_s(&pFile, fileName.c_str(), _L("rb")); #else err = fopen_s(&pFile, fileName.c_str(), "rb"); #endif } else { #if defined (UNICODE) || defined(_UNICODE) err = _wfopen_s(&pFile, fileName.c_str(), _L("r")); #else err = fopen_s(&pFile, fileName.c_str(), "r"); #endif } if(0 == err) { // get file size fseek(pFile, 0, SEEK_END); *pSizeInBytes = ftell(pFile); fseek (pFile, 0, SEEK_SET); // allocate buffer *ppData = (void*) new char[*pSizeInBytes]; ASSERT( *ppData, _L("Out of memory") ); // read it all in UINT numBytesRead = (UINT) fread(*ppData, sizeof(char), *pSizeInBytes, pFile); if (bAddTerminator) { ((char *)(*ppData))[numBytesRead++] = '\0'; (*pSizeInBytes)++; } //fixme - this isn't doing what it appears to be doing. counts off for Windows... //ASSERT( numBytesRead == *pSizeInBytes, _L("File read byte count mismatch.") ); UNREFERENCED_PARAMETER(numBytesRead); // close and return fclose(pFile); return CPUT_SUCCESS; } // some kind of file error, translate the error code and return it return TranslateFileError(err); }
//----------------------------------------------------------------------------- CPUTResult CPUTTextureDX11::CreateNativeTexture( ID3D11Device *pD3dDevice, const cString &fileName, ID3D11ShaderResourceView **ppShaderResourceView, ID3D11Resource **ppTexture, bool ForceLoadAsSRGB) { HRESULT hr; hr = DirectX::CreateDDSTextureFromFileEx( pD3dDevice, fileName.c_str(), 0,//maxsize D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, ForceLoadAsSRGB, ppTexture, ppShaderResourceView); if( FAILED( hr ) ) { ASSERT( false, _L("Failed to load texture: ") + fileName ) return CPUT_TEXTURE_LOAD_ERROR; } CPUTSetDebugName( *ppTexture, fileName ); CPUTSetDebugName( *ppShaderResourceView, fileName ); return CPUT_SUCCESS; }
CPUTFileSystem::CPUTandroidifstream::CPUTandroidifstream(const cString &fileName, std::ios_base::openmode mode) : iCPUTifstream(fileName, mode) { mpAsset = NULL; mpAssetDir = NULL; mbEOF = true; // Extract the file and dir int length = fileName.length(); int index = fileName.find_last_of("\\/"); cString file = fileName.substr(index + 1, (length - 1 - index)); cString dir = fileName.substr(0, index); // On Android, all files are in the APK and are compressed. // We do not have access to the standard file system, so // all files need streaming from memory through the android asset manager AAssetManager* assetManager = CPUTWindowAndroid::GetAppState()->activity->assetManager; mpAssetDir = AAssetManager_openDir(assetManager, dir.c_str()); if (!mpAssetDir) DEBUG_PRINT("Failed to load asset Dir"); const char* assetFileName = NULL; while ((assetFileName = AAssetDir_getNextFileName(mpAssetDir)) != NULL) { if (strcmp(file.c_str(), assetFileName) == 0) { // For some reason we need to pass in the fully pathed filename here, rather than the relative filename // that we have just been given. This feels like a bug in Android! mpAsset = AAssetManager_open(assetManager, fileName.c_str()/*assetFileName*/, AASSET_MODE_STREAMING); if (mpAsset) mbEOF = false; return; } } }
// Use DX11 compile from file method to do all the heavy lifting //----------------------------------------------------------------------------- CPUTResult CPUTAssetLibraryDX11::CompileShaderFromMemory( const char *pShaderSource, const cString &shaderMain, const cString &shaderProfile, ID3DBlob **ppBlob ) { CPUTResult result = CPUT_SUCCESS; char pShaderMainAsChar[128]; char pShaderProfileAsChar[128]; ASSERT( shaderMain.length() < 128, _L("Shader main name '") + shaderMain + _L("' longer than 128 chars.") ); ASSERT( shaderProfile.length() < 128, _L("Shader profile name '") + shaderProfile + _L("' longer than 128 chars.") ); size_t count; wcstombs_s( &count, pShaderMainAsChar, shaderMain.c_str(), 128 ); wcstombs_s( &count, pShaderProfileAsChar, shaderProfile.c_str(), 128 ); // use DirectX to compile the shader file ID3DBlob *pErrorBlob = NULL; D3D10_SHADER_MACRO pShaderMacros[2] = { "_CPUT", "1", NULL, NULL }; // TODO: Support passed-in, and defined in .mtl file. Perhaps under [Shader Defines], etc char *pShaderMainAsChars = ws2s(shaderMain.c_str()); HRESULT hr = D3DX11CompileFromMemory( pShaderSource, // shader as a string strlen( pShaderSource ), // pShaderMainAsChars, // Use entrypoint as file name pShaderMacros, // macro define's NULL, // includes pShaderMainAsChar, // main function name pShaderProfileAsChar, // shader profile/feature level 0, // flags 1 0, // flags 2 NULL, // threaded load? (no for right now) ppBlob, // blob data with compiled code &pErrorBlob, // any compile errors stored here NULL ); ASSERT( SUCCEEDED(hr), _L("Error compiling shader '") + shaderMain + _L("'.\n") + (pErrorBlob ? s2ws((char*)pErrorBlob->GetBufferPointer()) : _L("no error message") ) ); if(pErrorBlob) { pErrorBlob->Release(); } delete pShaderMainAsChars; return result; }
CPUTKey MapKey(cString strKey) { for(int i = 0; i < KEY_NUM_KEYS; i++) { if( 0 == strKey.compare(CPUTKeyMap[i].name)) return CPUTKeyMap[i].value; } DEBUG_PRINT(_L("Unknown Key: %s"), strKey.c_str()); return KEY_NUM_KEYS; }
// Open a file and return file pointer to it //----------------------------------------------------------------------------- CPUTResult CPUTFileSystem::OpenFile(const cString &fileName, FILE **ppFilePointer) { #ifdef CPUT_OS_ANDROID DEBUG_PRINT("OpenFile stubbed"); #else *ppFilePointer = fopen(fileName.c_str(), "r"); if (*ppFilePointer == NULL) { return CPUT_ERROR; } #endif return CPUT_SUCCESS; }
void CPUTGUIElement::SetText(cString string) { DEBUG_PRINT(_L("GUIElement SetText: %s"), string.c_str()); mText = string; if(mpFont && mpTextMaterial) { DEBUG_PRINT(_L("\t have font and material")); if(!mpTextMesh) { #ifdef CPUT_FOR_DX11 mpTextMesh = new CPUTMeshDX11(); #else mpTextMesh = new CPUTMeshOGL(); #endif } unsigned int numCharacters = (unsigned int) string.size(); unsigned int numVertices = numCharacters * 6; CPUTGUIVertex* pVB = new CPUTGUIVertex[numVertices]; CPUTBufferElementInfo pGUIVertex[3] = { { "POSITION", 0, 0, CPUT_F32, 3, 3*sizeof(float), 0 }, { "TEXCOORD", 0, 1, CPUT_F32, 2, 2*sizeof(float), 3*sizeof(float)}, { "COLOR", 0, 2, CPUT_F32, 4, 4*sizeof(float), 5*sizeof(float)}, }; mpFont->LayoutText(NULL, &mTextWidth, &mTextHeight, mText, 0, 0); mTextX = (mWidth-mTextWidth)/2; mTextY = (mHeight-mTextHeight)/2; mpFont->LayoutText(pVB, &mTextWidth, &mTextHeight, mText, 0, 0); mpTextMesh->CreateNativeResources(NULL, 1, 3, pGUIVertex, numVertices, pVB, NULL, 0, NULL); #ifdef CPUT_FOR_DX11 mpTextMesh->SetMeshTopology(CPUT_TOPOLOGY_INDEXED_TRIANGLE_LIST); D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; UINT numElements = ARRAYSIZE( layout ); ID3DBlob* pBlob = ((CPUTMaterialEffectDX11*)mpTextMaterial->GetMaterialEffects()[0])->GetVertexShader()->GetBlob(); CPUT_DX11::GetDevice()->CreateInputLayout( layout, numElements, pBlob->GetBufferPointer(), pBlob->GetBufferSize(), &mpVertexLayout ); CPUTSetDebugName( mpVertexLayout, "CPUT GUI InputLayout object"); #else #endif SAFE_DELETE_ARRAY(pVB); } }
int GetEventValue(StringMap eventMap[], cString event) { int i = 0; while(eventMap[i].value > 0) { if(event.compare(eventMap[i].key) == 0) { DEBUG_PRINT(_L("Found Event: %s\n"), event.c_str()); return eventMap[i].value; } i++; } return -1; }
//----------------------------------------------------------------------------- void CPUTSetDebugName( void *pResource, cString name ) { #ifdef _DEBUG char pCharString[CPUT_MAX_STRING_LENGTH]; const wchar_t *pWideString = name.c_str(); UINT ii; UINT length = min( (UINT)name.length(), (CPUT_MAX_STRING_LENGTH-1)); for(ii=0; ii<length; ii++) { pCharString[ii] = (char)pWideString[ii]; } pCharString[ii] = 0; // Force NULL termination ((ID3D11DeviceChild*)pResource)->SetPrivateData( WKPDID_D3DDebugObjectName, (UINT)name.length(), pCharString ); #endif // _DEBUG }
// Verifies that file exists at specified path // // #### this should probably just return a bool //----------------------------------------------------------------------------- CPUTResult CPUTFileSystem::DoesFileExist(const cString &pathAndFilename) { #ifdef CPUT_OS_ANDROID DEBUG_PRINT("DoesFileExist stubbed"); #else struct stat fileAttributes; int result = stat(pathAndFilename.c_str(), &fileAttributes); if (result == -1) { DEBUG_ERROR(strerror(errno)); result = CPUT_ERROR; } if (S_ISREG(fileAttributes.st_mode)) { return CPUT_SUCCESS; } #endif return CPUT_ERROR; }
// Takes a relative/full path+fileName and returns the absolute path with drive // letter, absolute path, fileName and extension of this file. // Truncates total path/file length to CPUT_MAX_PATH //----------------------------------------------------------------------------- CPUTResult CPUTFileSystem::ResolveAbsolutePathAndFilename(const cString &fileName, cString *pResolvedPathAndFilename) { CPUTResult result = CPUT_SUCCESS; #ifdef CPUT_OS_ANDROID pResolvedPathAndFilename->assign(fileName); #else char *fullPath = NULL; fullPath = realpath(fileName.c_str(), NULL); if (fullPath == NULL) { DEBUG_ERROR(fileName); DEBUG_ERROR(strerror(errno)); result = CPUT_ERROR; return result; } pResolvedPathAndFilename->assign(fullPath); free(fullPath); // realpath() mallocs the memory required to hold the path name, so we need to free it #endif return result; }
// Pop up a message box with specified title/text //----------------------------------------------------------------------------- void CPUT_DX11::CPUTMessageBox(const cString DialogBoxTitle, const cString DialogMessage) { CPUTOSServices::GetOSServices()->OpenMessageBox(DialogBoxTitle.c_str(), DialogMessage.c_str()); }
//----------------------------------------------------------------------------- CPUTResult CPUTModel::LoadModelPayload(const cString &File) { CPUTResult result = CPUT_SUCCESS; std::ifstream file(File.c_str(), std::ios::in | std::ios::binary); ASSERT( !file.fail(), _L("CPUTModelDX11::LoadModelPayload() - Could not find binary model file: ") + File ); // set up for mesh creation loop UINT meshIndex = 0; while(file.good() && !file.eof()) { // TODO: rearrange while() to avoid if(eof). Should perform only one branch per loop iteration, not two CPUTRawMeshData vertexFormatDesc; vertexFormatDesc.Read(file); if(file.eof()) { // TODO: Wtf? Why would we get here? We check eof at the top of loop. If it isn't eof there, why is it eof here? break; } ASSERT( meshIndex < mMeshCount, _L("Actual mesh count doesn't match stated mesh count")); // create the mesh. CPUTMesh *pMesh = mpMesh[meshIndex]; // always a triangle list (at this point) pMesh->SetMeshTopology(CPUT_TOPOLOGY_INDEXED_TRIANGLE_LIST); // get number of data blocks in the vertex element (pos,norm,uv,etc) // YUCK! TODO: Use fixed-size array of elements CPUTBufferInfo *pVertexElementInfo = new CPUTBufferInfo[vertexFormatDesc.mFormatDescriptorCount]; // pMesh->SetBounds(vertexFormatDesc.mBboxCenter, vertexFormatDesc.mBboxHalf); // running count of each type of element int positionStreamCount=0; int normalStreamCount=0; int texCoordStreamCount=0; int tangentStreamCount=0; int binormalStreamCount=0; int colorStreamCount=0; int RunningOffset = 0; for(UINT ii=0; ii<vertexFormatDesc.mFormatDescriptorCount; ii++) { // lookup the CPUT data type equivalent pVertexElementInfo[ii].mElementType = CPUT_FILE_ELEMENT_TYPE_TO_CPUT_TYPE_CONVERT[vertexFormatDesc.mpElements[ii].mVertexElementType]; ASSERT((pVertexElementInfo[ii].mElementType !=CPUT_UNKNOWN ) , _L(".MDL file load error. This model file has an unknown data type in it's model data.")); // calculate the number of elements in this stream block (i.e. F32F32F32 = 3xF32) pVertexElementInfo[ii].mElementComponentCount = vertexFormatDesc.mpElements[ii].mElementSizeInBytes/CPUT_DATA_FORMAT_SIZE[pVertexElementInfo[ii].mElementType]; // store the size of each element type in bytes (i.e. 3xF32, each element = F32 = 4 bytes) pVertexElementInfo[ii].mElementSizeInBytes = vertexFormatDesc.mpElements[ii].mElementSizeInBytes; // store the number of elements (i.e. 3xF32, 3 elements) pVertexElementInfo[ii].mElementCount = vertexFormatDesc.mVertexCount; // calculate the offset from the first element of the stream - assumes all blocks appear in the vertex stream as the order that appears here pVertexElementInfo[ii].mOffset = RunningOffset; RunningOffset = RunningOffset + pVertexElementInfo[ii].mElementSizeInBytes; // extract the name of stream pVertexElementInfo[ii].mpSemanticName = CPUT_VERTEX_ELEMENT_SEMANTIC_AS_STRING[ii]; switch(vertexFormatDesc.mpElements[ii].mVertexElementSemantic) { case CPUT_VERTEX_ELEMENT_POSITON: pVertexElementInfo[ii].mpSemanticName = "POSITION"; pVertexElementInfo[ii].mSemanticIndex = positionStreamCount++; break; case CPUT_VERTEX_ELEMENT_NORMAL: pVertexElementInfo[ii].mpSemanticName = "NORMAL"; pVertexElementInfo[ii].mSemanticIndex = normalStreamCount++; break; case CPUT_VERTEX_ELEMENT_TEXTURECOORD: pVertexElementInfo[ii].mpSemanticName = "TEXCOORD"; pVertexElementInfo[ii].mSemanticIndex = texCoordStreamCount++; break; case CPUT_VERTEX_ELEMENT_TANGENT: pVertexElementInfo[ii].mpSemanticName = "TANGENT"; pVertexElementInfo[ii].mSemanticIndex = tangentStreamCount++; break; case CPUT_VERTEX_ELEMENT_BINORMAL: pVertexElementInfo[ii].mpSemanticName = "BINORMAL"; pVertexElementInfo[ii].mSemanticIndex = binormalStreamCount++; break; case CPUT_VERTEX_ELEMENT_VERTEXCOLOR: pVertexElementInfo[ii].mpSemanticName = "COLOR"; pVertexElementInfo[ii].mSemanticIndex = colorStreamCount++; break; default: cString errorString = _L("Invalid vertex semantic in: '")+File+_L("'\n"); TRACE(errorString.c_str()); ASSERT(0, errorString); } } // Index buffer CPUTBufferInfo indexDataInfo; indexDataInfo.mElementType = (vertexFormatDesc.mIndexType == tUINT32) ? CPUT_U32 : CPUT_U16; indexDataInfo.mElementComponentCount = 1; indexDataInfo.mElementSizeInBytes = (vertexFormatDesc.mIndexType == tUINT32) ? sizeof(UINT32) : sizeof(UINT16); indexDataInfo.mElementCount = vertexFormatDesc.mIndexCount; indexDataInfo.mOffset = 0; indexDataInfo.mSemanticIndex = 0; indexDataInfo.mpSemanticName = NULL; if( pVertexElementInfo->mElementCount && indexDataInfo.mElementCount ) { result = pMesh->CreateNativeResources( this, meshIndex, vertexFormatDesc.mFormatDescriptorCount, pVertexElementInfo, (void*)vertexFormatDesc.mpVertices, &indexDataInfo, &vertexFormatDesc.mpIndices[0] ); if(CPUTFAILED(result)) { return result; } // CC added result = pMesh->ExtractVerticesandIndices(); if(CPUTFAILED(result)) { return result; } // CC added ends } delete [] pVertexElementInfo; pVertexElementInfo = NULL; ++meshIndex; } ASSERT( file.eof(), _L("") ); // close file file.close(); return result; }
// load a file and return it's contents //----------------------------------------------------------------------------- CPUTResult CPUTAssetLibraryOGLES::LoadShaderFileString(const cString Filename, void** ppData) { if(NULL == ppData) { ASSERT( ppData, _L("Invalid data pointer for storing shader string")); return CPUT_ERROR_INVALID_PARAMETER; } FILE* pFile = NULL; #if defined (UNICODE) || defined(_UNICODE) errno_t err = _wfopen_s(&pFile, Filename.c_str(), _L("r")); #else errno_t err = fopen_s(&pFile, Filename.c_str(), _L("r")); #endif ASSERT( (0 == err), _L("Error loading shader file: ")+Filename); if(0 != err) { // error opening file // char message[250]; // sprintf_s(message, 250, "Could not find file: %s\n", filename); // MessageBox("Error: Load file", message, CPUT_MB_ERROR); return CPUT_ERROR_FILE_NOT_FOUND; } // file open - read contents // get file size err = fseek( pFile, 0, SEEK_END ); ASSERT( (0 == err), _L("Error reading contents of shader file: ")+Filename); if(0!=err) { // char message[250]; // sprintf_s(message, 250, "Error getting file size: %s\n", filename); // MessageBox("Error: Load file", message, CPUT_MB_ERROR); fclose(pFile); return CPUT_ERROR_FILE_READ_ERROR; } long endPos = ftell( pFile ); fseek( pFile, 0, SEEK_SET ); ASSERT( (0 == err), _L("Error getting size of shader file: ")+Filename); if(0!=err) { // char message[250]; // sprintf_s(message, 250, "Error getting file size: %s\n", filename); // MessageBox("Error: Load file", message, CPUT_MB_ERROR); fclose(pFile); return CPUT_ERROR_FILE_READ_ERROR; } // allocate buffer char* pContents = new char[endPos+1]; // read the contents! size_t actuallyRead = fread(pContents, sizeof(char), endPos, pFile); pContents[actuallyRead] = '\0'; // always null terminate on your own - not guaranteed by fread() // close file err = fclose(pFile); ASSERT( (0 == err), _L("Error closing shader file: ")+Filename); if(pFile) { if(0 != err) { // file did not close properly! // char message[250]; // sprintf_s(message, 250, "File did not close properly: %s\n", filename); // MessageBox("Error: Load file", message, CPUT_MB_ERROR); delete [] pContents; return CPUT_ERROR_FILE_CLOSE_ERROR; } } // set the return buffer *ppData = pContents; return CPUT_SUCCESS; }
// Read the entire contents of a file and return a pointer/size to it //----------------------------------------------------------------------------- CPUTResult CPUTFileSystem::ReadFileContents(const cString &fileName, UINT *pSizeInBytes, void **ppData, bool bAddTerminator, bool bLoadAsBinary) { #ifdef CPUT_OS_ANDROID // Extract the file and dir int length = fileName.length(); int index = fileName.find_last_of("\\/"); cString file = fileName.substr(index + 1, (length - 1 - index)); cString dir = fileName.substr(0, index); DEBUG_PRINT("ReadFileContents(%s) : dir [%s], file [%s]", fileName.c_str(), dir.c_str(), file.c_str()); // On Android, all files are in the APK and are compressed. // We do not have access to the standard file system, so // all files need streaming from memory through the android asset manager AAssetManager* assetManager = CPUTWindowAndroid::GetAppState()->activity->assetManager; AAssetDir* assetDir = AAssetManager_openDir(assetManager, dir.c_str()); if (!assetDir) DEBUG_PRINT("Failed to load asset Dir"); const char* assetFileName = NULL; while ((assetFileName = AAssetDir_getNextFileName(assetDir)) != NULL) { if (strcmp(file.c_str(), assetFileName) == 0) { // For some reason we need to pass in the fully pathed filename here, rather than the relative filename // that we have just been given. This feels like a bug in Android! AAsset* asset = AAssetManager_open(assetManager, fileName.c_str()/*assetFileName*/, AASSET_MODE_STREAMING); if (!asset) { DEBUG_PRINT("Asset failed to load for file %s", fileName.c_str()); return CPUT_ERROR; } *pSizeInBytes = AAsset_getLength(asset); // allocate buffer if (bAddTerminator) *ppData = (void*) new char[*pSizeInBytes + 1]; else *ppData = (void*) new char[*pSizeInBytes]; if (!*ppData) { DEBUG_PRINT("Out of memory loading %s", fileName.c_str()); return CPUT_ERROR; } // read it all in int numBytesRead = AAsset_read(asset, *ppData, *pSizeInBytes); if (bAddTerminator) { ((char *)(*ppData))[numBytesRead++] = '\0'; *pSizeInBytes++; } ASSERT( numBytesRead == *pSizeInBytes, _L("File read byte count mismatch.") ); AAsset_close(asset); AAssetDir_close(assetDir); return CPUT_SUCCESS; } } AAssetDir_close(assetDir); #else FILE *pFile = NULL; if (bLoadAsBinary) { #if defined (UNICODE) || defined(_UNICODE) _wfopen_s(&pFile, fileName.c_str(), _L("r")); #else pFile = fopen(fileName.c_str(), "r"); #endif } else { #if defined (UNICODE) || defined(_UNICODE) _wfopen_s(&pFile, fileName.c_str(), _L("r")); #else pFile = fopen(fileName.c_str(), "r"); #endif } if(pFile) { // get file size fseek(pFile, 0, SEEK_END); *pSizeInBytes = ftell(pFile); fseek (pFile, 0, SEEK_SET); // allocate buffer *ppData = (void*) new char[*pSizeInBytes]; ASSERT( *ppData, _L("Out of memory") ); // read it all in UINT numBytesRead = (UINT) fread(*ppData, sizeof(char), *pSizeInBytes, pFile); if (bAddTerminator) { ((char *)(*ppData))[numBytesRead++] = '\0'; *pSizeInBytes++; } ASSERT( numBytesRead == *pSizeInBytes, _L("File read byte count mismatch.") ); // close and return fclose(pFile); return CPUT_SUCCESS; } #endif // some kind of file error, translate the error code and return it return CPUT_ERROR; // return TranslateFileError(err); }
// Pop up a message box with specified title/text //----------------------------------------------------------------------------- void CPUT_OGL::CPUTMessageBox(const cString DialogBoxTitle, const cString DialogMessage) { CPUTOSServices::OpenMessageBox(DialogBoxTitle.c_str(), DialogMessage.c_str()); }
CPUTResult CPUTTextureDX11::CreateNativeTexture( ID3D11Device *pD3dDevice, const cString &fileName, ID3D11ShaderResourceView **ppShaderResourceView, ID3D11Resource **ppTexture, bool ForceLoadAsSRGB ){ CPUTResult result; HRESULT hr; // Set up loading structure // // Indicate all texture parameters should come from the file D3DX11_IMAGE_LOAD_INFO LoadInfo; ZeroMemory(&LoadInfo, sizeof(D3DX11_IMAGE_LOAD_INFO)); LoadInfo.Width = D3DX11_FROM_FILE; LoadInfo.Height = D3DX11_FROM_FILE; LoadInfo.Depth = D3DX11_FROM_FILE; LoadInfo.FirstMipLevel = D3DX11_FROM_FILE; LoadInfo.MipLevels = D3DX11_FROM_FILE; // LoadInfo.Usage = D3D11_USAGE_IMMUTABLE; // TODO: maintain a "mappable" flag? Set immutable if not mappable? LoadInfo.Usage = D3D11_USAGE_DEFAULT; LoadInfo.BindFlags = D3D11_BIND_SHADER_RESOURCE; LoadInfo.CpuAccessFlags = 0; LoadInfo.MiscFlags = 0; LoadInfo.MipFilter = D3DX11_FROM_FILE; LoadInfo.pSrcInfo = NULL; LoadInfo.Format = (DXGI_FORMAT) D3DX11_FROM_FILE; LoadInfo.Filter = D3DX11_FILTER_NONE; // if we're 'forcing' load of sRGB data, we need to verify image is sRGB // or determine image format that best matches the non-sRGB source format in hopes that the conversion will be faster // and data preserved if(true == ForceLoadAsSRGB) { // get the source image info D3DX11_IMAGE_INFO SrcInfo; hr = D3DX11GetImageInfoFromFile(fileName.c_str(), NULL, &SrcInfo, NULL); ASSERT( SUCCEEDED(hr), _L(" - Error loading texture '")+fileName+_L("'.") ); // find a closest equivalent sRGB format result = GetSRGBEquivalent(SrcInfo.Format, LoadInfo.Format); ASSERT( CPUTSUCCESS(result), _L("Error loading texture '")+fileName+_L("'. It is specified this texture must load as sRGB, but the source image is in a format that cannot be converted to sRGB.\n") ); // set filtering mode to interpret 'in'-coming data as sRGB, and storing it 'out' on an sRGB surface // // As it stands, we don't have any tools that support sRGB output in DXT compressed textures. // If we later support a format that does provide sRGB, then the filter 'in' flag will need to be removed LoadInfo.Filter = D3DX11_FILTER_NONE | D3DX11_FILTER_SRGB_IN | D3DX11_FILTER_SRGB_OUT; #if 0 // DWM: TODO: We want to catch the cases where the loader needs to do work. // This happens if the texture's pixel format isn't supported by DXGI. // TODO: how to determine? // if a runtime conversion must happen report a performance warning error. // Note: choosing not to assert here, as this will be a common issue. if( SrcInfo.Format != LoadInfo.Format) { cString dxgiName = GetDXGIFormatString(SrcInfo.Format); cString errorString = _T(__FUNCTION__); errorString += _L("- PERFORMANCE WARNING: '") + fileName +_L("' has an image format ")+dxgiName +_L(" but must be run-time converted to ")+GetDXGIFormatString(LoadInfo.Format) +_L(" based on requested sRGB target buffer.\n"); TRACE( errorString.c_str() ); } #endif } //hr = D3DX11CreateTextureFromFile( pD3dDevice, fileName.c_str(), &LoadInfo, NULL, ppTexture, NULL ); hr = MyCreateTextureFromFile( pD3dDevice, fileName.c_str(), &LoadInfo, NULL, ppTexture, NULL ); ASSERT( SUCCEEDED(hr), _L("Failed to load texture: ") + fileName ); CPUTSetDebugName( *ppTexture, fileName ); hr = pD3dDevice->CreateShaderResourceView( *ppTexture, NULL, ppShaderResourceView ); ASSERT( SUCCEEDED(hr), _L("Failed to create texture shader resource view.") ); CPUTSetDebugName( *ppShaderResourceView, fileName ); return CPUT_SUCCESS; }
//---------------------------------------------------------------- CPUTResult CPUTConfigFile::LoadFile(const cString &szFilename) { int nBytes = 0; char *pFileContents = NULL; #if 1 CPUTResult result = CPUTFileSystem::ReadFileContents(szFilename, (UINT *)&nBytes, (void **)&pFileContents, true); if(CPUTFAILED(result)) { DEBUG_PRINT(_L("Failed to read file %s"), szFilename.c_str()); return result; } #else // Load the file FILE *pFile = NULL; CPUTResult result = CPUTFileSystem::OpenFile(szFilename, &pFile); if(CPUTFAILED(result)) { return result; } // locale_t locale = newlocale(LC_ALL_MASK, setlocale(LC_ALL, NULL), NULL); /* Determine file size */ fseek(pFile, 0, SEEK_END); nBytes = ftell(pFile); // for text files, this is an overestimate fseek(pFile, 0, SEEK_SET); /* Read the whole thing */ pFileContents = new char[nBytes + 1]; nBytes = (int)fread(pFileContents, 1, nBytes, pFile); fclose(pFile); pFileContents[nBytes] = 0; // add 0-terminator #endif CPUTConfigBlock *pCurrBlock = NULL; int nCurrBlock = 0; /* Count the number of blocks */ const char *pCur = pFileContents; const char *pStart, *pEnd; while(ReadLine(&pStart, &pEnd, &pCur)) { const char *pOpen = FindFirst(pStart, pEnd, '['); const char *pClose = FindLast(pOpen + 1, pEnd, ']'); if (pOpen < pClose) { // This line is a valid block header mnBlockCount++; } } // For files that don't have any blocks, just add the entire file to one block if(mnBlockCount == 0) { mnBlockCount = 1; } pCur = pFileContents; mpBlocks = new CPUTConfigBlock[mnBlockCount]; pCurrBlock = mpBlocks; /* Find the first block first */ while(ReadLine(&pStart, &pEnd, &pCur)) { const char *pOpen = FindFirst(pStart, pEnd, '['); const char *pClose = FindLast(pOpen + 1, pEnd, ']'); if (pOpen < pClose) { // This line is a valid block header pCurrBlock = mpBlocks + nCurrBlock++; // AssignStr(pCurrBlock->mszName, pOpen + 1, pClose, locale); pCurrBlock->mszName.assign(pOpen + 1, pClose); std::transform(pCurrBlock->mszName.begin(), pCurrBlock->mszName.end(), pCurrBlock->mszName.begin(), tolow); } else if (pStart < pEnd) { // It's a value if (pCurrBlock == NULL) { continue; } const char *pEquals = FindFirst(pStart, pEnd, '='); if (pEquals == pEnd) { // No value, just a key, save it anyway // Optimistically, we assume it's new cString &name = pCurrBlock->mpValues[pCurrBlock->mnValueCount].szName; //AssignStr(name, pStart, pEnd, locale); name.assign(pStart, pEnd); bool dup = false; for(int ii=0;ii<pCurrBlock->mnValueCount;++ii) { if(!pCurrBlock->mpValues[ii].szName.compare(name)) { dup = true; break; } } if(!dup) { pCurrBlock->mnValueCount++; } } else { const char *pNameStart = pStart; const char *pNameEnd = pEquals; const char *pValStart = pEquals + 1; const char *pValEnd = pEnd; RemoveWhitespace(pNameStart, pNameEnd); RemoveWhitespace(pValStart, pValEnd); // Optimistically assume the name is new cString &name = pCurrBlock->mpValues[pCurrBlock->mnValueCount].szName; // AssignStr(name, pNameStart, pNameEnd, locale); name.assign(pNameStart, pNameEnd); std::transform(name.begin(), name.end(), name.begin(), tolow); bool dup = false; for(int ii=0;ii<pCurrBlock->mnValueCount;++ii) { if(!pCurrBlock->mpValues[ii].szName.compare(name)) { dup = true; break; } } if(!dup) { // AssignStr(pCurrBlock->mpValues[pCurrBlock->mnValueCount].szValue, pValStart, pValEnd, locale); pCurrBlock->mpValues[pCurrBlock->mnValueCount].szValue.assign(pValStart, pValEnd); pCurrBlock->mnValueCount++; } } } } delete[] pFileContents; return CPUT_SUCCESS; }