MF_API void MFSound_Unlock(MFSound *pSound) { MFDebug_Assert(pSound->flags & MFPF_Locked, MFStr("Dynamic sound '%s' is not locked.", pSound->name)); if(pSound->pInternal->p3DBuffer) { // copy new data into 3d buffer... VOID *pBuffer, *pB2; DWORD bufferLen, l2; pSound->pInternal->p3DBuffer->Lock((DWORD)pSound->lockOffset, (DWORD)pSound->lockBytes, &pBuffer, &bufferLen, &pB2, &l2, pSound->lockBytes == 0 ? DSBLOCK_ENTIREBUFFER : 0); MFCopyMemory(pBuffer, pSound->pLock1, pSound->lockSize1); if(pB2) MFCopyMemory(pB2, pSound->pLock2, pSound->lockSize2); pSound->pInternal->p3DBuffer->Unlock(pBuffer, bufferLen, pB2, l2); } // and unlock the main buffer pSound->pInternal->pBuffer->Unlock(pSound->pLock1, (DWORD)pSound->lockSize1, pSound->pLock2, (DWORD)pSound->lockSize2); pSound->pLock1 = NULL; pSound->lockSize1 = 0; pSound->pLock2 = NULL; pSound->lockSize2 = 0; pSound->flags = pSound->flags & ~MFPF_Locked; }
MF_API void MFVertex_CopyVertexData(MFVertexBuffer *pVertexBuffer, MFVertexElementType targetElement, int targetElementIndex, const void *pSourceData, MFVertexDataFormat sourceDataFormat, int sourceDataStride, int numVertices) { const MFVertexDeclaration *pDecl = pVertexBuffer->pVertexDeclatation; int element = MFVertex_FindVertexElement(pDecl, targetElement, targetElementIndex); if(!pVertexBuffer->bLocked || element == -1) return; MFDebug_Assert(numVertices <= pVertexBuffer->numVerts, "Too manu vertices for vertex buffer!"); MFVertexDataFormat format = pDecl->pElements[element].format; int stride = pDecl->pElementData[element].stride; int offset = pDecl->pElementData[element].offset; void *pElementData = (char*)pVertexBuffer->pLocked + offset; if(format == sourceDataFormat && stride == sourceDataStride) { // The stream has only a single element, we can memcopy MFCopyMemory(pElementData, pSourceData, numVertices * sourceDataStride); } else if(format == sourceDataFormat) { // interleaved stream copy char *pSource = (char*)pSourceData; char *pTarget = (char*)pElementData; int dataSize = gVertexDataStride[sourceDataFormat]; for(int a=0; a<numVertices; ++a) { MFCopyMemory(pTarget, pSource, dataSize); pSource += sourceDataStride; pTarget += stride; } } else { // transcode formats.... char *pSource = (char*)pSourceData; char *pTarget = (char*)pElementData; if(sourceDataFormat == MFVDF_Float4) { // this is a really common case (filling a vertex buffer with generated vertex data, or blanket setting to zero/one) for(int a=0; a<numVertices; ++a) { MFVertex_PackVertexData(*(MFVector*)pSource, pTarget, format); pSource += sourceDataStride; pTarget += stride; } } else { for(int a=0; a<numVertices; ++a) { MFVector v = MFVertex_UnpackVertexData(pSource, sourceDataFormat); MFVertex_PackVertexData(v, pTarget, format); pSource += sourceDataStride; pTarget += stride; } } } }
void MFModel_CreateMeshChunk(MFMeshChunk *pMeshChunk) { MFCALLSTACK; MFMeshChunk_Generic *pMC = (MFMeshChunk_Generic*)pMeshChunk; pMC->pMaterial = MFMaterial_Create((char*)pMC->pMaterial); HRESULT hr; MFDebug_Assert(sizeof(MeshChunkD3DRuntimeData) <= sizeof(pMC->runtimeData), "MeshChunkD3DRuntimeData is larger than runtimeData!"); MeshChunkD3DRuntimeData &runtimeData = (MeshChunkD3DRuntimeData&)pMC->runtimeData; // create D3D interfaces hr = MFModelD3D9_CreateVertexDeclaration(pMC->pVertexFormat, &runtimeData.vertexDecl); MFDebug_Assert(SUCCEEDED(hr), "Failed to create vertex declaration.."); hr = pd3dDevice->CreateVertexBuffer(pMC->pVertexFormat->pStreams[0].streamStride*pMC->numVertices, 0, 0, D3DPOOL_MANAGED, &runtimeData.vertexBuffer, NULL); MFDebug_Assert(SUCCEEDED(hr), "Failed to create vertex buffer.."); if(pMC->pVertexFormat->numVertexStreams > 1) { hr = pd3dDevice->CreateVertexBuffer(pMC->pVertexFormat->pStreams[1].streamStride*pMC->numVertices, 0, 0, D3DPOOL_MANAGED, &runtimeData.animBuffer, NULL); MFDebug_Assert(SUCCEEDED(hr), "Failed to create animation buffer.."); } hr = pd3dDevice->CreateIndexBuffer(sizeof(uint16)*pMC->numIndices, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &runtimeData.indexBuffer, NULL); MFDebug_Assert(SUCCEEDED(hr), "Failed to create index buffer.."); void *pData; // fill vertex buffer hr = runtimeData.vertexBuffer->Lock(0, 0, &pData, 0); MFDebug_Assert(SUCCEEDED(hr), "Failed to lock vertex buffer.."); MFCopyMemory(pData, pMC->ppVertexStreams[0], pMC->pVertexFormat->pStreams[0].streamStride*pMC->numVertices); runtimeData.vertexBuffer->Unlock(); // fill animation buffer if(pMC->pVertexFormat->numVertexStreams > 1) { hr = runtimeData.animBuffer->Lock(0, 0, &pData, 0); MFDebug_Assert(SUCCEEDED(hr), "Failed to lock animation buffer.."); MFCopyMemory(pData, pMC->ppVertexStreams[1], pMC->pVertexFormat->pStreams[1].streamStride*pMC->numVertices); runtimeData.animBuffer->Unlock(); } // fill index buffer hr = runtimeData.indexBuffer->Lock(0, 0, &pData, 0); MFDebug_Assert(SUCCEEDED(hr), "Failed to lock index buffer.."); MFCopyMemory(pData, pMC->pIndexData, sizeof(uint16)*pMC->numIndices); runtimeData.indexBuffer->Unlock(); }
MF_API void MFIntSound_CreateRuntimeData(MFIntSound *pSound, void **ppOutput, size_t *pSize, MFPlatform platform) { *ppOutput = NULL; MFAudioStream *pStream = (MFAudioStream*)pSound->pInternal; // decode audio into buffer size_t sampleSize = (pSound->soundTemplate.bitsPerSample * pSound->soundTemplate.numChannels) >> 3; size_t bytesAllocated = 44100 * sampleSize; size_t bytes = 0; char *pAudioData = (char*)MFHeap_Alloc(bytesAllocated); size_t read; do { // read samples from stream read = MFSound_ReadStreamSamples(pStream, pAudioData + bytes, bytesAllocated - bytes); bytes += read; // if we fill the buffer, increase it's size if(bytes == bytesAllocated) { bytesAllocated *= 4; pAudioData = (char*)MFHeap_Realloc(pAudioData, bytesAllocated); } } while(read); // calculate the number of samples from the bytes read int numSamples = (int)(bytes / sampleSize); // construct MFSoundTemplate size_t templateBytes = sizeof(MFSoundTemplate) + sizeof(char*)*pSound->soundTemplate.numStreams + sampleSize*numSamples; MFSoundTemplate *pTemplate = (MFSoundTemplate*)MFHeap_Alloc(templateBytes); MFCopyMemory(pTemplate, &pSound->soundTemplate, sizeof(MFSoundTemplate)); pTemplate->numSamples = numSamples; pTemplate->ppStreams = (char**)&pTemplate[1]; pTemplate->ppStreams[0] = (char*)&pTemplate->ppStreams[1]; // copy sample data MFCopyMemory(pTemplate->ppStreams[0], pAudioData, sampleSize * numSamples); // free decode buffer MFHeap_Free(pAudioData); // fix down pointers for(int a=0; a<pTemplate->numStreams; a++) MFFixUp(pTemplate->ppStreams[a], pTemplate, false); MFFixUp(pTemplate->ppStreams, pTemplate, false); // return template data *ppOutput = pTemplate; if(pSize) *pSize = templateBytes; }
MF_API void *MFHeap_AllocInternal(size_t bytes, MFHeap *pHeap) { MFCALLSTACK; MFHeap *pAllocHeap = pOverrideHeap ? pOverrideHeap : (pHeap ? pHeap : pActiveHeap); size_t extra; size_t allocBytes = GetAllocSize(bytes, extra); MFThread_LockMutex(gAllocMutex); char *pMemory = (char*)pAllocHeap->pCallbacks->pMalloc(allocBytes, pAllocHeap->pHeapData); if(pMemory) { #if defined(_USE_TRACKING_HASH_TABLE) #if defined(USE_PRE_MUNGWALL) int alignment = (int)(MFALIGN(pMemory + MFHeap_MungwallBytes, heapAlignment) - (uintp)pMemory); #else int alignment = (int)(MFALIGN(pMemory, heapAlignment) - (uintp)pMemory); #endif #else int alignment = (int)(MFALIGN(pMemory + sizeof(MFAllocHeader), heapAlignment) - (uintp)pMemory); #endif pMemory += alignment; #if defined(_USE_TRACKING_HASH_TABLE) MFAllocHeader *pHeader = AddAlloc(pMemory, bytes, NULL); #else MFAllocHeader *pHeader = GetAllocHeader(pMemory); #endif pHeader->alignment = alignment; pHeader->pHeap = pAllocHeap; pHeader->size = bytes; pHeader->pFile = gpMFHeap_TrackerFile; pHeader->line = gMFHeap_TrackerLine; #if defined(USE_PRE_MUNGWALL) MFCopyMemory(pMemory - MFHeap_MungwallBytes, gLlawgnum, MFHeap_MungwallBytes); #endif #if !defined(_RETAIL) MFCopyMemory(pMemory + bytes, gMungwall, MFHeap_MungwallBytes); pAllocHeap->totalAllocated += allocBytes; pAllocHeap->totalWaste += extra; ++pAllocHeap->allocCount; // MFDebug_Log(2, MFStr("Alloc: %p(%p), %d bytes - %s:(%d)", pMemory, pMemory - pHeader->alignment, bytes, gpMFHeap_TrackerFile, gMFHeap_TrackerLine)); #endif } MFThread_ReleaseMutex(gAllocMutex); return (void*)pMemory; }
// interface functions void MFTexture_CreatePlatformSpecific(MFTexture *pTexture, bool generateMipChain) { MFCALLSTACK; HRESULT hr; MFTextureTemplateData *pTemplate = pTexture->pTemplateData; // create texture D3DFORMAT platformFormat = (D3DFORMAT)MFTexture_GetPlatformFormatID(pTemplate->imageFormat, MFDD_D3D9); hr = D3DXCreateTexture(pd3dDevice, pTemplate->pSurfaces[0].width, pTemplate->pSurfaces[0].height, generateMipChain ? 0 : 1, 0, platformFormat, D3DPOOL_MANAGED, (IDirect3DTexture9**)&pTexture->pInternalData); MFDebug_Assert(hr != D3DERR_NOTAVAILABLE, MFStr("LoadTexture failed: D3DERR_NOTAVAILABLE, 0x%08X", hr)); MFDebug_Assert(hr != D3DERR_OUTOFVIDEOMEMORY, MFStr("LoadTexture failed: D3DERR_OUTOFVIDEOMEMORY, 0x%08X", hr)); MFDebug_Assert(hr != D3DERR_INVALIDCALL, MFStr("LoadTexture failed: D3DERR_INVALIDCALL, 0x%08X", hr)); MFDebug_Assert(hr != D3DXERR_INVALIDDATA, MFStr("LoadTexture failed: D3DXERR_INVALIDDATA, 0x%08X", hr)); MFDebug_Assert(hr == D3D_OK, MFStr("Failed to create texture '%s'.", pTexture->name)); IDirect3DTexture9 *pTex = (IDirect3DTexture9*)pTexture->pInternalData; // copy image data D3DLOCKED_RECT rect; pTex->LockRect(0, &rect, NULL, 0); MFCopyMemory(rect.pBits, pTemplate->pSurfaces[0].pImageData, pTemplate->pSurfaces[0].bufferLength); pTex->UnlockRect(0); // filter mip levels if(generateMipChain) D3DXFilterTexture(pTex, NULL, 0, D3DX_DEFAULT); }
MF_API int MFFileSystem_MountFujiPath(const char *pMountpoint, const char *pFujiPath, int priority, uint32 flags) { const char *pColon = MFString_Chr(pFujiPath, ':'); if(!pColon) return -1; // not a fuji path. needs a volume name! MFMount *pMount = MFFileSystem_FindVolume(MFStrN(pFujiPath, pColon-pFujiPath)); if(!pMount) return -2; // volume not mounted // get the path // ++pColon; // const char *pNewPath = MFStr("%s%s", pColon, MFString_EndsWith(pColon, "/") ? "" : "/"); MFMount *pNew = (MFMount*)MFHeap_Alloc(sizeof(MFMount) + MFString_Length(pMountpoint) + 1); MFCopyMemory(pNew, pMount, sizeof(MFMount)); pNew->volumeInfo.pVolumeName = (const char*)&pNew[1]; MFString_Copy((char*)pNew->volumeInfo.pVolumeName, pMountpoint); pNew->volumeInfo.priority = priority; pNew->volumeInfo.flags = (pNew->volumeInfo.flags & ~MFMF_DontCacheTOC) | flags; return MFFileSystem_AddVolume(pNew); }
int GetMADSamples(MFAudioStream *pStream, void *pBuffer, uint32 bytes) { MFMADDecoder *pDecoder = (MFMADDecoder*)pStream->pStreamData; int written = 0; if(pDecoder->overflowBytes) { // grab from the overflow until we run out... uint32 numBytes = MFMin(pDecoder->overflowBytes - pDecoder->overflowOffset, bytes); MFCopyMemory(pBuffer, pDecoder->overflow + pDecoder->overflowOffset, numBytes); pDecoder->overflowOffset += numBytes; if(pDecoder->overflowOffset == pDecoder->overflowBytes) pDecoder->overflowBytes = 0; // increment timer mad_timer_t t = { 0, MAD_TIMER_RESOLUTION / pDecoder->firstHeader.samplerate }; mad_timer_multiply(&t, numBytes >> 2); mad_timer_add(&pDecoder->timer, t); if(bytes == numBytes) return numBytes; bytes -= numBytes; (char*&)pBuffer += numBytes; written = (int)numBytes; }
void FlipImage(SourceImage *pImage) { for(int a=0; a<pImage->mipLevels; a++) { int halfHeight = pImage->pLevels[a].height / 2; int stride = pImage->pLevels[a].width * sizeof(Pixel); int height = pImage->pLevels[a].height; char *pBuffer = (char*)malloc(stride); char *pData = (char*)pImage->pLevels[a].pData; for(int b=0; b<halfHeight; b++) { // swap lines MFCopyMemory(pBuffer, &pData[b*stride], stride); MFCopyMemory(&pData[b*stride], &pData[(height-b-1)*stride], stride); MFCopyMemory(&pData[(height-b-1)*stride], pBuffer, stride); } } }
MF_API void MFHeap_Free(void *pMem) { MFCALLSTACK; if(!pMem) { MFDebug_Warn(3, "Attemptd to Free 'NULL' pointer."); return; } MFThread_LockMutex(gAllocMutex); MFAllocHeader *pHeader = GetAllocHeader(pMem); MFDebug_Assert(MFHeap_ValidateMemory(pMem), MFStr("Memory corruption detected!!\n%s(" MFFMT_SIZE_T ")", pHeader->pFile, pHeader->line)); MFHeap *pHeap = pHeader->pHeap; #if !defined(_RETAIL) size_t extra; size_t allocBytes = GetAllocSize(pHeader->size, extra); pHeap->totalAllocated -= allocBytes; pHeap->totalWaste -= extra; --pHeap->allocCount; // MFDebug_Log(2, MFStr("Free: %p, %d bytes - %s:(%d)", pMem, pHeader->size, pHeader->pFile, (int)pHeader->line)); #endif MFCopyMemory((char*)pMem + pHeader->size, "freefreefreefree", MFHeap_MungwallBytes); #if defined(USE_PRE_MUNGWALL) MFCopyMemory((char*)pMem - MFHeap_MungwallBytes, "eerfeerfeerfeerf", MFHeap_MungwallBytes); #endif MFMemSet(pMem, 0xFE, pHeader->size); pHeap->pCallbacks->pFree((char*)pMem - pHeader->alignment, pHeap->pHeapData); #if defined(_USE_TRACKING_HASH_TABLE) FreeAlloc(pMem); #endif MFThread_ReleaseMutex(gAllocMutex); }
bool MFVertex_CreateVertexBufferPlatformSpecific(MFVertexBuffer *pVertexBuffer, void *pVertexBufferMemory) { DWORD usage; D3DPOOL pool; DWORD lockFlags = 0; switch(pVertexBuffer->bufferType) { case MFVBType_Static: pool = D3DPOOL_MANAGED; usage = 0; break; case MFVBType_Dynamic: pool = D3DPOOL_DEFAULT; usage = D3DUSAGE_WRITEONLY; usage = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY; lockFlags = D3DLOCK_DISCARD; break; case MFVBType_Scratch: // Maybe it's better to use UP draw calls for scratch buffers? pool = D3DPOOL_DEFAULT; usage = D3DUSAGE_WRITEONLY; // usage = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY; // DYNAMIC is supposedly only for frequent locking... we don't intend to lock more than once break; default: MFDebug_Assert(false, "Invalid vertex buffer type!"); return false; } int stride = pVertexBuffer->pVertexDeclatation->pElementData[0].stride; IDirect3DVertexBuffer9 *pVertBuffer; HRESULT hr = pd3dDevice->CreateVertexBuffer(stride*pVertexBuffer->numVerts, usage, 0, pool, &pVertBuffer, NULL); MFDebug_Assert(SUCCEEDED(hr), "Failed to create vertex buffer"); if(FAILED(hr)) return false; if(pVertexBuffer->pName) MFRenderer_D3D9_SetDebugName(pVertBuffer, pVertexBuffer->pName); pVertexBuffer->pPlatformData = pVertBuffer; if(pVertexBufferMemory) { void *pData; pVertBuffer->Lock(0, 0, &pData, lockFlags); MFCopyMemory(pData, pVertexBufferMemory, stride*pVertexBuffer->numVerts); pVertBuffer->Unlock(); } return true; }
void MFObjectPoolGroup::Init(const MFObjectPoolGroupConfig *_pPools, int _numPools) { pConfig = (MFObjectPoolGroupConfig*)MFHeap_Alloc(sizeof(MFObjectPoolGroupConfig)*_numPools + sizeof(MFObjectPool)*_numPools); pPools = (MFObjectPool*)&pConfig[_numPools]; numPools = _numPools; MFCopyMemory(pConfig, _pPools, sizeof(MFObjectPoolGroupConfig)*_numPools); mutex = MFThread_CreateMutex("MFObjectPoolGroup alloc mutex"); for(int a=0; a<_numPools; ++a) { pPools[a].Init(pConfig[a].objectSize, pConfig[a].numObjects, pConfig[a].growObjects); } }
MF_API size_t MFSound_SetBufferData(MFSound *pSound, const void *pData, size_t size) { // lock the buffers and copy in the data void *pBuffer; size_t len; MFSound_Lock(pSound, 0, 0, &pBuffer, &len); MFDebug_Assert(len == size, "Incorrect number of bytes in source buffer."); MFCopyMemory(pBuffer, pData, len); MFSound_Unlock(pSound); return len; }
void MFMidi_UpdateInternal() { // copy notes into lastNotes size_t numInputDevices = MFDevice_GetNumDevices(MFDT_MidiInput); for (int i = 0; i < numInputDevices; ++i) { MFDevice *pDevice = MFDevice_GetDeviceByIndex(MFDT_MidiInput, i); if (pDevice->state == MFDevState_Active) { MFMidiPC_MidiInputDevice *pMidi = (MFMidiPC_MidiInputDevice*)pDevice->pInternal; for (int j = 0; j < 16; ++j) MFCopyMemory(pMidi->channels[j].lastNotes, pMidi->channels[j].notes, sizeof(pMidi->channels[j].lastNotes)); } } }
// interface functions void MFTexture_CreatePlatformSpecific(MFTexture *pTexture, bool generateMipChain) { MFTextureTemplateData *pTemplate = pTexture->pTemplateData; // create texture D3DFORMAT platformFormat = (D3DFORMAT)MFTexture_GetPlatformFormatID(pTemplate->imageFormat, MFDD_XBOX); #if defined(XB_XGTEXTURES) pTexture->pTexture = &pTexture->texture; XGSetTextureHeader(pTemplate->pSurfaces[0].width, pTemplate->pSurfaces[0].height, 1, 0, platformFormat, 0, pTexture->pTexture, 0, 0); pTexture->pTexture->Register(pTemplate->pSurfaces[0].pImageData); if(pTemplate->imageFormat >= TexFmt_XB_A8R8G8B8s && pTemplate->imageFormat <= TexFmt_XB_R4G4B4A4s) { XGSwizzleRect(pTemplate->pSurfaces[0].pImageData, 0, NULL, pTemplate->pSurfaces[0].pImageData, pTemplate->pSurfaces[0].width, pTemplate->pSurfaces[0].height, NULL, pTemplate->pSurfaces[0].bitsPerPixel/8); } #else HRESULT hr; hr = D3DXCreateTexture(pd3dDevice, pTemplate->pSurfaces[0].width, pTemplate->pSurfaces[0].height, generateMipChain ? 0 : 1, 0, platformFormat, 0, &pTexture->pTexture); MFDebug_Assert(hr != D3DERR_NOTAVAILABLE, MFStr("LoadTexture failed: D3DERR_NOTAVAILABLE, 0x%08X", hr)); MFDebug_Assert(hr != D3DERR_OUTOFVIDEOMEMORY, MFStr("LoadTexture failed: D3DERR_OUTOFVIDEOMEMORY, 0x%08X", hr)); MFDebug_Assert(hr != D3DERR_INVALIDCALL, MFStr("LoadTexture failed: D3DERR_INVALIDCALL, 0x%08X", hr)); MFDebug_Assert(hr != D3DXERR_INVALIDDATA, MFStr("LoadTexture failed: D3DXERR_INVALIDDATA, 0x%08X", hr)); MFDebug_Assert(hr == D3D_OK, MFStr("Failed to create texture '%s'.", pTexture->name)); // copy image data D3DLOCKED_RECT rect; pTexture->pTexture->LockRect(0, &rect, NULL, 0); if(pTemplate->imageFormat >= TexFmt_XB_A8R8G8B8s && pTemplate->imageFormat <= TexFmt_XB_R4G4B4A4s) { XGSwizzleRect(pTemplate->pSurfaces[0].pImageData, 0, NULL, rect.pBits, pTemplate->pSurfaces[0].width, pTemplate->pSurfaces[0].height, NULL, pTemplate->pSurfaces[0].bitsPerPixel/8); } else { MFCopyMemory(rect.pBits, pTemplate->pSurfaces[0].pImageData, pTemplate->pSurfaces[0].bufferLength); } pTexture->pTexture->UnlockRect(0); // filter mip levels if(generateMipChain) D3DXFilterTexture(pTexture->pTexture, NULL, 0, D3DX_DEFAULT); #endif }
MF_API void MFMaterial_RegisterMaterialType(const char *pName, const MFMaterialCallbacks *pCallbacks) { MFCALLSTACK; MFMaterialType *pMatType; pMatType = (MFMaterialType*)MFHeap_Alloc(sizeof(MFMaterialType) + MFString_Length(pName) + 1); pMatType->pTypeName = (char*)&pMatType[1]; MFString_Copy(pMatType->pTypeName, pName); MFDebug_Assert(pCallbacks->pBegin, "Material must supply Begin() callback."); MFCopyMemory(&pMatType->materialCallbacks, pCallbacks, sizeof(MFMaterialCallbacks)); gMaterialRegistry.Create(pMatType); pCallbacks->pRegisterMaterial(NULL); }
MFFileSystemHandle MFFileSystem_RegisterFileSystem(const char *pFilesystemName, MFFileSystemCallbacks *pCallbacks) { MFDebug_Log(5, MFStr("Call: MFFileSystem_RegisterFileSystem(\"%s\")", pFilesystemName)); GET_MODULE_DATA(MFFileSystemState); for(uint32 a=0; a<gDefaults.filesys.maxFileSystems; a++) { if(pModuleData->ppFileSystemList[a] == NULL) { MFDebug_Assert(pCallbacks->Open, "No Open function supplied."); MFDebug_Assert(pCallbacks->Close, "No Close function supplied."); MFDebug_Assert(pCallbacks->Read, "No Read function supplied."); MFDebug_Assert(pCallbacks->Write, "No Write function supplied."); MFDebug_Assert(pCallbacks->Seek, "No Seek function supplied."); MFFileSystem *pFS = pModuleData->gFileSystems.Create(); MFZeroMemory(pFS, sizeof(MFFileSystem)); MFString_Copy(pFS->name, pFilesystemName); MFCopyMemory(&pFS->callbacks, pCallbacks, sizeof(MFFileSystemCallbacks)); pModuleData->ppFileSystemList[a] = pFS; #if defined(USE_JOB_THREAD) pFS->ppJobQueue = (MFJob**)MFHeap_Alloc(sizeof(MFJob*)*MAX_JOBS); pFS->jobs.Init(MFStr("%s Job List", pFilesystemName), MAX_JOBS+2); pFS->readJob = 0; pFS->writeJob = 0; pFS->numJobs = MAX_JOBS; pFS->semaphore = MFThread_CreateSemaphore("Filesystem Semaphore", MAX_JOBS, 0); pFS->thread = MFThread_CreateThread(MFStr("%s Thread", pFilesystemName), MKFileJobThread, pFS, MFPriority_AboveNormal); #endif if(pFS->callbacks.RegisterFS) pFS->callbacks.RegisterFS(); return a; } } MFDebug_Assert(false, MFStr("Exceeded maximum of %d Filesystems. Modify 'gDefaults.filesys.maxFileSystems'.", gDefaults.filesys.maxFileSystems)); return -1; }
MFSocket MFSockets_Accept(MFSocket socket, MFSocketAddress *pConnectingSocketAddress) { char address[sizeof(sockaddr_in)*10]; int size = sizeof(sockaddr_in)*10; MFSocket result = (MFSocket)accept((SOCKET)socket, (sockaddr*)&address, &size); if(pConnectingSocketAddress) { MFSocketAddress *pAddress = MFSocketsPC_GetSocketAddress((sockaddr*)&address); if(pConnectingSocketAddress->cbSize >= pAddress->cbSize) { MFCopyMemory(pConnectingSocketAddress, pAddress, pAddress->cbSize); } } return result; }
int MFSockets_RecvFrom(MFSocket socket, char *pBuffer, int bufferSize, uint32 flags, MFSocketAddress *pSenderAddress) { char address[sizeof(sockaddr_in)*10]; int size = sizeof(sockaddr_in)*10; int result = recvfrom((SOCKET)socket, pBuffer, bufferSize, flags, (sockaddr*)&address, &size); if(pSenderAddress) { MFSocketAddress *pAddress = MFSocketsPC_GetSocketAddress((sockaddr*)&address); if(pSenderAddress->cbSize >= pAddress->cbSize) { MFCopyMemory(pSenderAddress, pAddress, pAddress->cbSize); } } return result; }
MF_API size_t MFMidi_GetEvents(MFDevice *pDevice, MFMidiEvent *pEvents, size_t maxEvents, bool bPeek) { MFMidiPC_MidiInputDevice *pMidi = (MFMidiPC_MidiInputDevice*)pDevice->pInternal; if (pMidi->numEvents == 0) return 0; if (!pEvents) return pMidi->numEvents - pMidi->numEventsRead; uint32 toRead = MFMin((uint32)maxEvents, pMidi->numEvents - pMidi->numEventsRead); MFCopyMemory(pEvents, pMidi->pEvents + pMidi->numEventsRead, sizeof(MFMidiEvent)*toRead); if (!bPeek) { pMidi->numEventsRead += toRead; if (pMidi->numEventsRead == pMidi->numEvents) pMidi->numEvents = pMidi->numEventsRead = 0; } return toRead; }
bool MFVertex_CreateIndexBufferPlatformSpecific(MFIndexBuffer *pIndexBuffer, uint16 *pIndexBufferMemory) { IDirect3DIndexBuffer9 *pIB; HRESULT hr = pd3dDevice->CreateIndexBuffer(sizeof(uint16)*pIndexBuffer->numIndices, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &pIB, NULL); MFDebug_Assert(SUCCEEDED(hr), "Failed to create index buffer"); if(FAILED(hr)) return false; if(pIndexBuffer->pName) MFRenderer_D3D9_SetDebugName(pIB, pIndexBuffer->pName); pIndexBuffer->pPlatformData = pIB; if(pIndexBufferMemory) { void *pData; pIB->Lock(0, 0, &pData, 0); MFCopyMemory(pData, pIndexBufferMemory, sizeof(uint16)*pIndexBuffer->numIndices); pIB->Unlock(); } return true; }
MF_API size_t MFInput_GetEvents(int device, int deviceID, MFInputEvent *pEvents, size_t maxEvents, bool bPeek) { MFThread_LockMutex(gInputMutex); uint32 toRead = 0; if(gNumEvents[device][deviceID] != 0) { toRead = MFMin((uint32)maxEvents, gNumEvents[device][deviceID] - gNumEventsRead[device][deviceID]); MFCopyMemory(pEvents, gInputEvents[device][deviceID] + gNumEventsRead[device][deviceID], sizeof(MFInputEvent)*toRead); if(!bPeek) { gNumEventsRead[device][deviceID] += toRead; if(gNumEventsRead[device][deviceID] == gNumEvents[device][deviceID]) gNumEvents[device][deviceID] = gNumEventsRead[device][deviceID] = 0; } } MFThread_ReleaseMutex(gInputMutex); return toRead; }
MF_API void *MFHeap_ReallocInternal(void *pMem, size_t bytes) { MFCALLSTACK; if(pMem) { MFAllocHeader *pHeader = &((MFAllocHeader*)pMem)[-1]; MFDebug_Assert(MFHeap_ValidateMemory(pMem), MFStr("Memory corruption detected!!\n%s(%d)", pHeader->pFile, pHeader->line)); void *pNew = MFHeap_AllocInternal(bytes, pHeader->pHeap); MFDebug_Assert(pNew, "Failed to allocate memory!"); if(!pNew) return NULL; MFCopyMemory(pNew, pMem, MFMin(bytes, (size_t)pHeader->size)); MFHeap_Free(pMem); return pNew; } else { return MFHeap_AllocInternal(bytes, NULL); } }
void *MFPoolHeapCollection::Realloc(void *pItem, size_t size) { if(!pItem) return Alloc(size); for(int i = 0; i < numHeaps; ++i) { MFPoolHeap *pHeap = pHeaps[i]; if(pHeap->IsFromThisHeap(pItem)) { size_t heapSize = pHeap->Size(); if(size <= heapSize) return pItem; void *pNewItem = Alloc(size); MFCopyMemory(pNewItem, pItem, heapSize); Delete(pItem); return pNewItem; } } return MFHeap_Realloc(pItem, size); }
void MFInput_Update() { int a, b; // platform specific update MFInput_UpdatePlatformSpecific(); // update state for each device for(a=0; a<IDD_Max; a++) { for(b=0; b<MFInput_MaxInputID; b++) { gDeviceStatus[a][b] = MFInput_GetDeviceStatusInternal(a, b); } } // count number of gamepads int maxGamepad = -1; for(a=0; a<MFInput_MaxInputID; a++) { if(MFInput_IsAvailable(IDD_Gamepad, a)) maxGamepad = a; } gNumGamepads = maxGamepad+1; // update number of keyboards int maxKB = -1; for(a=0; a<MFInput_MaxInputID; a++) { if(MFInput_IsAvailable(IDD_Keyboard, a)) maxKB = a; } gNumKeyboards = maxKB+1; // update number of pointers int maxMouse = -1; for(a=0; a<MFInput_MaxInputID; a++) { if(MFInput_IsAvailable(IDD_Mouse, a)) maxMouse = a; } gNumPointers = maxMouse+1; // update number of accelerometers int maxAccelerometer = -1; for(a=0; a<MFInput_MaxInputID; a++) { if(MFInput_IsAvailable(IDD_Accelerometer, a)) maxAccelerometer = a; } gNumAccelerometers = maxAccelerometer+1; // update number of touch panels int maxTouchPanel = -1; for(a=0; a<MFInput_MaxInputID; a++) { if(MFInput_IsAvailable(IDD_TouchPanel, a)) maxTouchPanel = a; } gNumTouchPanels = maxTouchPanel+1; // copy current states into last states MFCopyMemory(gPrevGamepadStates, gGamepadStates, sizeof(gPrevGamepadStates)); MFCopyMemory(gPrevKeyStates, gKeyStates, sizeof(gPrevKeyStates)); MFCopyMemory(gPrevMouseStates, gMouseStates, sizeof(gPrevMouseStates)); MFCopyMemory(gPrevAccelerometerStates, gAccelerometerStates, sizeof(gPrevAccelerometerStates)); MFCopyMemory(gPrevTouchPanelStates, gTouchPanelStates, sizeof(gPrevTouchPanelStates)); // update keyboard state for(a=0; a<gNumKeyboards; a++) { if(MFInput_IsAvailable(IDD_Keyboard, a)) MFInput_GetKeyStateInternal(a, &gKeyStates[a]); } // update gamepad state for(a=0; a<gNumGamepads; a++) { if(MFInput_IsAvailable(IDD_Gamepad, a)) { // update gamepad state #if !defined(_RETAIL) if(gDeviceStatus[IDD_Gamepad][0] == IDS_Unavailable) MFInputInternal_GetGamepadStateFromKeyMap(&gGamepadStates[a], &gKeyStates[0]); else #endif MFInput_GetGamepadStateInternal(a, &gGamepadStates[a]); // apply analog deadzone to axiis uint32 deviceFlags = MFInput_GetDeviceFlags(IDD_Gamepad, a); if(!(deviceFlags & MFGF_DontUseSphericalDeadzone)) { MFInputInternal_ApplySphericalDeadZone(&gGamepadStates[a].values[Axis_LX], &gGamepadStates[a].values[Axis_LY]); MFInputInternal_ApplySphericalDeadZone(&gGamepadStates[a].values[Axis_RX], &gGamepadStates[a].values[Axis_RY]); } } } // update mouse state for(a=0; a<gNumPointers; a++) { if(MFInput_IsAvailable(IDD_Mouse, a)) MFInput_GetMouseStateInternal(a, &gMouseStates[a]); } // update accelerometer state for(a=0; a<gNumAccelerometers; a++) { if(MFInput_IsAvailable(IDD_Accelerometer, a)) MFInput_GetAccelerometerStateInternal(a, &gAccelerometerStates[a]); } // update touch panel state for(a=0; a<gNumTouchPanels; a++) { if(MFInput_IsAvailable(IDD_TouchPanel, a)) MFInput_GetTouchPanelStateInternal(a, &gTouchPanelStates[a]); } // add network devices if(MFNetwork_IsRemoteInputServerRunning()) { gNetGamepadStart = gNumGamepads; gNetKeyboardStart = gNumKeyboards; gNetPointerStart = gNumPointers; MFNetwork_LockInputMutex(); // add additional gamepads for(a=0; a<MFNetwork_MaxRemoteDevices(); a++) { MFInputDeviceStatus status = (MFInputDeviceStatus)MFNetwork_GetRemoteDeviceStatus(a); if(status > IDS_Unavailable) { gDeviceStatus[IDD_Gamepad][gNetGamepadStart + a] = status; MFNetwork_GetRemoteGamepadState(a, &gGamepadStates[gNetGamepadStart + a]); gNumGamepads = gNetGamepadStart + a + 1; } } MFNetwork_ReleaseInputMutex(); } }
MF_API MFVertexDeclaration *MFVertex_CreateVertexDeclaration(const MFVertexElement *pElementArray, int elementCount) { // assign the auto format components before calculating the hash MFVertexElement elements[16]; MFCopyMemory(elements, pElementArray, sizeof(MFVertexElement)*elementCount); for(int e=0; e<elementCount; ++e) { if(pElementArray[e].format == MFVDF_Auto) elements[e].format = MFVertex_ChoooseVertexDataTypePlatformSpecific(pElementArray[e].type, pElementArray[e].componentCount); } uint32 hash = MFUtil_HashBuffer(elements, sizeof(MFVertexElement)*elementCount); MFVertexDeclaration *pDecl = (MFVertexDeclaration*)MFResource_Find(hash); if(!pDecl) { pDecl = (MFVertexDeclaration*)MFHeap_AllocAndZero(sizeof(MFVertexDeclaration) + (sizeof(MFVertexElement) + sizeof(MFVertexElementData))*elementCount); pDecl->numElements = elementCount; pDecl->pElements = (MFVertexElement*)&pDecl[1]; pDecl->pElementData = (MFVertexElementData*)&pDecl->pElements[elementCount]; MFCopyMemory(pDecl->pElements, elements, sizeof(MFVertexElement)*elementCount); int streamOffsets[16]; MFZeroMemory(streamOffsets, sizeof(streamOffsets)); // set the element data and calculate the strides for(int e=0; e<elementCount; ++e) { pDecl->pElementData[e].offset = streamOffsets[elements[e].stream]; pDecl->pElementData[e].stride = 0; streamOffsets[elements[e].stream] += gVertexDataStride[elements[e].format]; pDecl->streamsUsed |= MFBIT(elements[e].stream); } // set the strides for each component for(int e=0; e<elementCount; ++e) pDecl->pElementData[e].stride = streamOffsets[elements[e].stream]; if(!MFVertex_CreateVertexDeclarationPlatformSpecific(pDecl)) { MFHeap_Free(pDecl); return NULL; } MFResource_AddResource(pDecl, MFRT_VertexDecl, hash); if(pDecl->streamsUsed != 1) { // create the stream declarations... MFVertexElement streamElements[64]; for(int s=0; s<16; ++s) { if(!(pDecl->streamsUsed & (1 << s))) continue; int numStreamElements = 0; for(int e=0; e<elementCount; ++e) { if(elements[e].stream == s) { streamElements[numStreamElements] = elements[e]; streamElements[numStreamElements].stream = 0; ++numStreamElements; } } if(numStreamElements) pDecl->pStreamDecl[s] = MFVertex_CreateVertexDeclaration(streamElements, numStreamElements); } } } return pDecl; }
MF_API void MFHeap_Free(void *pMem) { MFCALLSTACK; if(!pMem) { MFDebug_Warn(3, "Attemptd to Free 'NULL' pointer."); return; } MFAllocHeader *pHeader = &((MFAllocHeader*)pMem)[-1]; MFDebug_Assert(MFHeap_ValidateMemory(pMem), MFStr("Memory corruption detected!!\n%s(%d)", pHeader->pFile, pHeader->line)); MFThread_LockMutex(gAllocMutex); MFHeap *pHeap = pHeader->pHeap; if(pHeap->heapType != MFHT_Debug) { #if defined(_USE_TRACKING_HASH_TABLE) int hash = MFUtil_HashPointer(pMem) % MFHeap_AllocTableLength; MFHeap_AllocItem *pT = gpAllocTable[hash]; if(pT) { if(pT->pMemory == pMem) { gpAllocTable[hash] = pT->pNext; gAllocHeaderPool.Free(pT); } else { while(pT->pNext && pT->pNext->pMemory != pMem) pT = pT->pNext; if(pT->pNext) { MFHeap_AllocItem *pTN = pT->pNext; pT->pNext = pTN->pNext; gAllocHeaderPool.Free(pTN); } } } #endif #if defined(_USE_ALLOC_TRACKER) if(gPoolInitialised) { int numAllocs = gAllocList.GetNumAllocated(); for(int a=0; a<numAllocs; ++a) { void **ppAlloc = (void**)gAllocList.GetItem(a); if(*ppAlloc == pMem) { gAllocList.Free(ppAlloc); break; } } } #endif } #if !defined(_RETAIL) int pad = 0; while(pad < (int)sizeof(MFAllocHeader)) pad += heapAlignment; size_t extra = pad + sizeof(MFAllocHeader) + MFHeap_MungwallBytes; pHeap->totalAllocated -= pHeader->size + extra; pHeap->totalWaste -= extra; --pHeap->allocCount; // MFDebug_Log(2, MFStr("Free: %08X, %d bytes - %s:(%d)", pMem, pHeader->size, pHeader->pFile, (int)pHeader->line)); #endif MFHeap *pAllocHeap = pHeader->pHeap; MFCopyMemory((char*)pMem + pHeader->size, "freefreefreefree", MFHeap_MungwallBytes); MFCopyMemory((char*)pMem - 8, "freefreefreefree", MFHeap_MungwallBytes); MFMemSet(pMem, 0xFE, pHeader->size); pAllocHeap->pCallbacks->pFree((char*)pMem - pHeader->alignment, pAllocHeap->pHeapData); MFThread_ReleaseMutex(gAllocMutex); }
int main(int argc, char *argv[]) { MFPlatform platform = FP_Unknown; MFWaveFormat targetFormat = MFWF_PCM_s16; char fileName[256] = ""; char outFile[256] = ""; int a; // process command line for(a=1; a<argc; a++) { if(argv[a][0] == '-' || argv[a][0] == '/') { for(int b=0; b<FP_Max; b++) { if(!MFString_CaseCmp(&argv[a][1], MFSystem_GetPlatformString(b))) { platform = (MFPlatform)b; break; } } if(!MFString_CaseCmp(&argv[a][1], "v") || !MFString_CaseCmp(&argv[a][1], "version")) { // print version return 0; } } else { if(!fileName[0]) MFString_Copy(fileName, argv[a]); else if(!outFile[0]) MFString_Copy(outFile, argv[a]); } } if(platform == FP_Unknown) { LOGERROR("No platform specified...\n"); return 1; } if(!fileName[0]) { LOGERROR("No file specified...\n"); return 1; } if(!outFile[0]) { // generate output filename MFString_Copy(outFile, fileName); for(int i=MFString_Length(outFile); --i; ) { if(outFile[i] == '.') { outFile[i] = 0; break; } } MFString_Cat(outFile, ".snd"); } // load image char *pBuffer; FILE *pFile = fopen(fileName, "rb"); if(!pFile) { LOGERROR("Couldnt open source file '%s' for reading.", fileName); return 1; } fseek(pFile, 0, SEEK_END); int bytes = ftell(pFile) + 1; fseek(pFile, 0, SEEK_SET); pBuffer = (char*)malloc(bytes); fread(pBuffer, bytes, 1, pFile); fclose(pFile); FILE *pOutFile = fopen(outFile, "wb"); if(!pOutFile) { LOGERROR("Couldnt open output file '%s' for writing.", outFile); return 2; } // parse the sound file... WAVHeader *pHeader = (WAVHeader*)pBuffer; if(pHeader->RIFF != MFMAKEFOURCC('R', 'I', 'F', 'F') || pHeader->WAVE != MFMAKEFOURCC('W', 'A', 'V', 'E')) { LOGERROR("Source file '%s' is not a wave file.", fileName); return 1; } WAVChunk *pChunk = (WAVChunk*)&pHeader[1]; WAVFormatChunk *pFormat = NULL; WAVDataChunk *pData = NULL; while((char*)pChunk - pBuffer < bytes && bytes - ((char*)pChunk - pBuffer) >= sizeof(WAVChunk)) { if(pChunk->id == MFMAKEFOURCC('f', 'm', 't', ' ')) { pFormat = (WAVFormatChunk*)pChunk; } else if(pChunk->id == MFMAKEFOURCC('d', 'a', 't', 'a')) { pData = (WAVDataChunk*)pChunk; } pChunk = (WAVChunk*)((char*)pChunk + sizeof(WAVChunk) + ((pChunk->size+1) & ~1)); } if(!pFormat || !pData) { LOGERROR("WAVE file '%s' has no format or data chunks.", fileName); return 2; } // we only output 1 stream for now.. int numStreams = 1; int numSamples = ((pData->size*8) / ((pFormat->wBitsPerSample + 7) & ~7)) / pFormat->nChannels; int fileSize = sizeof(MFSoundTemplate) + sizeof(char*)*numStreams + bytesPerSample[targetFormat]*pFormat->nChannels*numSamples*numStreams; char *pSndFile = (char*)MFHeap_Alloc(fileSize); MFSoundTemplate *pTemplate = (MFSoundTemplate*)pSndFile; pTemplate->ppStreams = (char **)&pTemplate[1]; char *pWaveData = (char*)&pTemplate->ppStreams[numStreams]; for(int a=0; a<numStreams; a++) { pTemplate->ppStreams[a] = pWaveData; pWaveData += bytesPerSample[targetFormat]*pFormat->nChannels*numSamples; } pTemplate->magic = MFMAKEFOURCC('S', 'N', 'D', '1'); pTemplate->flags = 0; pTemplate->format = targetFormat; pTemplate->numSamples = numSamples; pTemplate->numStreams = numStreams; pTemplate->numChannels = pFormat->nChannels; pTemplate->bitsPerSample = bytesPerSample[targetFormat]*8; pTemplate->sampleRate = pFormat->nSamplesPerSec; // write wave data into file if(pTemplate->bitsPerSample == pFormat->wBitsPerSample) { for(int a=0; a<pTemplate->numStreams; a++) MFCopyMemory(pTemplate->ppStreams[a], pData->data, bytesPerSample[targetFormat]*pTemplate->numChannels*pTemplate->numSamples); } else { // do a format conversion LOGERROR("Format conversion not written."); return 3; } // fix up template for(int a=0; a<numStreams; a++) MFFixUp(pTemplate->ppStreams[a], pTemplate, false); MFFixUp(pTemplate->ppStreams, pTemplate, false); // write to disk fwrite(pSndFile, fileSize, 1, pOutFile); fclose(pOutFile); printf("> %s\n", outFile); return 0; }
MF_API void *MFHeap_AllocInternal(size_t bytes, MFHeap *pHeap) { MFCALLSTACK; MFHeap *pAllocHeap = pOverrideHeap ? pOverrideHeap : (pHeap ? pHeap : pActiveHeap); int pad = 0; while(pad < (int)sizeof(MFAllocHeader)) pad += heapAlignment; size_t allocExtra = pad + sizeof(MFAllocHeader) + MFHeap_MungwallBytes; size_t allocBytes = bytes + allocExtra; MFThread_LockMutex(gAllocMutex); char *pMemory = (char*)pAllocHeap->pCallbacks->pMalloc(allocBytes, pAllocHeap->pHeapData); MFDebug_Assert(pMemory, "Failed to allocate memory!"); if(pMemory) { int alignment = (int)(MFALIGN(pMemory + sizeof(MFAllocHeader), heapAlignment) - (uintp)pMemory); pMemory += alignment; MFAllocHeader *pHeader = &((MFAllocHeader*)pMemory)[-1]; pHeader->alignment = (uint16)alignment; pHeader->pHeap = pAllocHeap; pHeader->size = (uint32)bytes; pHeader->pFile = gpMFHeap_TrackerFile; pHeader->line = (uint16)gMFHeap_TrackerLine; #if defined(USE_PRE_MUNGWALL) MFCopyMemory(pHeader->llawgnum, gLlawgnum, MFHeap_MungwallBytes); #endif if(pAllocHeap->heapType != MFHT_Debug) { #if defined(_USE_TRACKING_HASH_TABLE) MFHeap_AllocItem *pAlloc = (MFHeap_AllocItem*)gAllocHeaderPool.Alloc(); pAlloc->header.alignment = (uint16)alignment; pAlloc->header.pHeap = pAllocHeap; pAlloc->header.size = (uint32)bytes; pAlloc->header.pFile = gpMFHeap_TrackerFile; pAlloc->header.line = (uint16)gMFHeap_TrackerLine; pAlloc->pMemory = pMemory; int hash = MFUtil_HashPointer(pMemory) % MFHeap_AllocTableLength; pAlloc->pNext = gpAllocTable[hash]; gpAllocTable[hash] = pAlloc; #endif #if defined(_USE_ALLOC_TRACKER) if(gPoolInitialised) *(void**)gAllocList.Alloc() = pMemory; #endif } #if !defined(_RETAIL) MFCopyMemory(pMemory + bytes, gMungwall, MFHeap_MungwallBytes); pAllocHeap->totalAllocated += allocBytes; pAllocHeap->totalWaste += allocExtra; ++pAllocHeap->allocCount; // MFDebug_Log(2, MFStr("Alloc: %08X(%08X), %d bytes - %s:(%d)", pMemory, pMemory - pHeader->alignment, bytes, gpMFHeap_TrackerFile, gMFHeap_TrackerLine)); #endif } MFThread_ReleaseMutex(gAllocMutex); return (void*)pMemory; }
MF_API bool MFTexture_Update(MFTexture *pTexture, int element, int mipLevel, const void *pData, size_t lineStride, size_t sliceStride) { int numFaces = pTexture->type == MFTexType_Cubemap ? 6 : 1; MFDebug_Assert(element < numFaces, "Array textures not supported in D3D9!"); int s = mipLevel*pTexture->numElements + (element > -1 ? element : 0); MFTextureSurface &surface = pTexture->pSurfaces[s]; DWORD lockFlags = (pTexture->createFlags & MFTCF_TypeMask) == MFTCF_Scratch ? D3DLOCK_DISCARD : 0; size_t lineBytes = (surface.bitsPerPixel * surface.width) / 8; if(lineStride == 0) lineStride = lineBytes; if(sliceStride == 0) sliceStride = lineStride * surface.width; switch(pTexture->type) { case MFTexType_1D: { IDirect3DTexture9 *pTex = (IDirect3DTexture9*)pTexture->pInternalData; #if defined(MF_DEBUG) D3DSURFACE_DESC desc; pTex->GetLevelDesc(mipLevel, &desc); MFDebug_Assert((int)desc.Width == surface.width && (int)desc.Height == surface.height, "D3D9 mip dimensions don't match the texture template data..."); #endif D3DLOCKED_RECT rect; pTex->LockRect(mipLevel, &rect, NULL, lockFlags); MFCopyMemory(rect.pBits, pData, lineBytes); pTex->UnlockRect(mipLevel); break; } case MFTexType_2D: { IDirect3DTexture9 *pTex = (IDirect3DTexture9*)pTexture->pInternalData; #if defined(MF_DEBUG) D3DSURFACE_DESC desc; pTex->GetLevelDesc(mipLevel, &desc); MFDebug_Assert((int)desc.Width == surface.width && (int)desc.Height == surface.height, "D3D9 mip dimensions don't match the texture template data..."); #endif D3DLOCKED_RECT rect; pTex->LockRect(mipLevel, &rect, NULL, lockFlags); const char *pSrc = (const char*)pData; char *pDest = (char*)rect.pBits; for(int i=0; i<surface.height; ++i) { MFCopyMemory(pDest, pSrc, lineBytes); pDest += rect.Pitch; pSrc += lineStride; } pTex->UnlockRect(mipLevel); break; } case MFTexType_3D: { IDirect3DVolumeTexture9 *pTex = (IDirect3DVolumeTexture9*)pTexture->pInternalData; #if defined(MF_DEBUG) D3DVOLUME_DESC desc; pTex->GetLevelDesc(mipLevel, &desc); MFDebug_Assert((int)desc.Width == surface.width && (int)desc.Height == surface.height && (int)desc.Depth == surface.depth, "D3D9 mip dimensions don't match the texture template data..."); #endif D3DLOCKED_BOX box; pTex->LockBox(mipLevel, &box, NULL, lockFlags); MFCopyMemory(box.pBits, pData, surface.bufferLength); const char *pSrcSlice = (const char*)pData; char *pDestSlice = (char*)box.pBits; for(int d=0; d<surface.depth; ++d) { const char *pSrcLine = pSrcSlice; char *pDestLine = pDestSlice; for(int i=0; i<surface.height; ++i) { MFCopyMemory(pDestLine, pSrcLine, lineBytes); pDestLine += box.RowPitch; pSrcLine += lineStride; } pSrcSlice += sliceStride; pDestSlice += box.SlicePitch; } pTex->UnlockBox(mipLevel); break; } case MFTexType_Cubemap: { MFDebug_Assert(element != -1, "TODO: must handle setting all surfaces at once..."); IDirect3DCubeTexture9 *pTex = (IDirect3DCubeTexture9*)pTexture->pInternalData; #if defined(MF_DEBUG) D3DSURFACE_DESC desc; pTex->GetLevelDesc(mipLevel, &desc); MFDebug_Assert((int)desc.Width == surface.width && (int)desc.Height == surface.height, "D3D9 mip dimensions don't match the texture template data..."); #endif D3DLOCKED_RECT rect; pTex->LockRect(gD3DCubeFaces[element], mipLevel, &rect, NULL, lockFlags); const char *pSrc = (const char*)pData; char *pDest = (char*)rect.pBits; for(int i=0; i<surface.height; ++i) { MFCopyMemory(pDest, pSrc, lineBytes); pDest += rect.Pitch; pSrc += lineStride; } pTex->UnlockRect(gD3DCubeFaces[element], mipLevel); break; } } return true; }