R *X(taint)(R *p, int s) { if (((unsigned)s * sizeof(R)) % ALIGNMENT) p = (R *) (PTRINT(p) | TAINT_BIT); if (((unsigned)s * sizeof(R)) % ALIGNMENTA) p = (R *) (PTRINT(p) | TAINT_BITA); return p; }
/** * Writes the data for a single mip-level into a destination buffer. * @param FaceIndex The index of the face of the mip-level to read. * @param MipIndex The index of the mip-level to read. * @param Dest The address of the destination buffer to receive the mip-level's data. * @param DestPitch Number of bytes per row */ void GetData( int32 FaceIndex, int32 MipIndex, void* Dest, uint32 DestPitch ) { check( MipData[FaceIndex][MipIndex] ); // for platforms that returned 0 pitch from Lock, we need to just use the bulk data directly, never do // runtime block size checking, conversion, or the like if (DestPitch == 0) { FMemory::Memcpy(Dest, MipData[FaceIndex][MipIndex], Owner->PlatformData->Mips[MipIndex].BulkData.GetBulkDataSize() / 6); } else { EPixelFormat PixelFormat = Owner->GetPixelFormat(); uint32 NumRows = 0; uint32 SrcPitch = 0; uint32 BlockSizeX = GPixelFormats[PixelFormat].BlockSizeX; // Block width in pixels uint32 BlockSizeY = GPixelFormats[PixelFormat].BlockSizeY; // Block height in pixels uint32 BlockBytes = GPixelFormats[PixelFormat].BlockBytes; FIntPoint MipExtent = CalcMipMapExtent(Owner->GetSizeX(), Owner->GetSizeY(), PixelFormat, MipIndex); uint32 NumColumns = (MipExtent.X + BlockSizeX - 1) / BlockSizeX; // Num-of columns in the source data (in blocks) NumRows = (MipExtent.Y + BlockSizeY - 1) / BlockSizeY; // Num-of rows in the source data (in blocks) SrcPitch = NumColumns * BlockBytes; // Num-of bytes per row in the source data SIZE_T MipSizeInBytes = CalcTextureMipMapSize(MipExtent.X, MipExtent.Y, PixelFormat, 0); if (SrcPitch == DestPitch) { // Copy data, not taking into account stride! FMemory::Memcpy(Dest, MipData[FaceIndex][MipIndex], MipSizeInBytes); } else { // Copy data, taking the stride into account! uint8 *Src = (uint8*) MipData[FaceIndex][MipIndex]; uint8 *Dst = (uint8*) Dest; for ( uint32 Row=0; Row < NumRows; ++Row ) { FMemory::Memcpy( Dst, Src, SrcPitch ); Src += SrcPitch; Dst += DestPitch; } check( (PTRINT(Src) - PTRINT(MipData[FaceIndex][MipIndex])) == PTRINT(MipSizeInBytes) ); } } FMemory::Free( MipData[FaceIndex][MipIndex] ); MipData[FaceIndex][MipIndex] = NULL; }
/** * Opens a file. (Thread-safe) * If opened for write, it will create any necessary directory structure. * * @param Filename Full path to the file * @param Flags A combination of EFileOpenFlags, specifying read/write access. * @return File handle **/ FFileHandle FFileManagerWindows::InternalFileOpen( const TCHAR* Filename, DWORD Flags ) { DWORD AccessFlags = (Flags & IO_READ) ? GENERIC_READ : 0; DWORD CreateFlags = 0; if ( Flags & IO_WRITE ) { MakeDirectory(*FFilename(Filename).GetPath(), TRUE); AccessFlags |= GENERIC_WRITE; CreateFlags = (Flags & IO_APPEND) ? OPEN_ALWAYS : CREATE_NEW; } else { CreateFlags = OPEN_EXISTING; } HANDLE WinHandle = CreateFile( Filename, AccessFlags, FILE_SHARE_READ, NULL, CreateFlags, FILE_ATTRIBUTE_NORMAL, NULL ); if ( WinHandle == INVALID_HANDLE_VALUE ) { WinHandle = (HANDLE) INDEX_NONE; } else if ( Flags & IO_APPEND ) { SetFilePointer( WinHandle, 0, NULL, FILE_END ); } FFileHandle Handle( PTRINT(WinHandle), 0 ); return Handle; }
/** * Tries to reallocate texture memory in-place (without relocating), * by adjusting the base address of the allocation but keeping the end address the same. * * @param OldBaseAddress Pointer to the original allocation * @param NewBaseAddress New desired baseaddress for the allocation (adjusting the size so the end stays the same) * @returns TRUE if it succeeded **/ UBOOL FBestFitAllocator::Reallocate( void* OldBaseAddress, void* NewBaseAddress ) { SCOPE_SECONDS_COUNTER(TimeSpentInAllocator); // Look up pointer in TMap. FMemoryChunk* MatchingChunk = PointerToChunkMap.FindRef( PTRINT(OldBaseAddress) ); check( MatchingChunk && PTRINT(OldBaseAddress) == PTRINT(MatchingChunk->Base) ); INT MemoryAdjustment = Abs<INT>(PTRINT(NewBaseAddress) - PTRINT(OldBaseAddress)); // Are we growing the allocation? if ( PTRINT(NewBaseAddress) < PTRINT(OldBaseAddress) ) { // Is there enough free memory immediately before this chunk? FMemoryChunk* PrevChunk = MatchingChunk->PreviousChunk; if ( PrevChunk && PrevChunk->bIsAvailable && PrevChunk->Size >= MemoryAdjustment ) { PointerToChunkMap.Remove( PTRINT(OldBaseAddress) ); // Shrink the previous and grow the current chunk. PrevChunk->Size -= MemoryAdjustment; MatchingChunk->Base -= MemoryAdjustment; MatchingChunk->Size += MemoryAdjustment; check(PTRINT(NewBaseAddress) == PTRINT(MatchingChunk->Base)); PointerToChunkMap.Set( PTRINT(NewBaseAddress), MatchingChunk ); if ( PrevChunk->Size == 0 ) { delete PrevChunk; } // Update usage stats in a thread safe way. appInterlockedAdd( &AllocatedMemorySize, +MemoryAdjustment ); appInterlockedAdd( &AvailableMemorySize, -MemoryAdjustment ); return TRUE; } } else { // We're shrinking the allocation. check( MemoryAdjustment <= MatchingChunk->Size ); FMemoryChunk* PrevChunk = MatchingChunk->PreviousChunk; if ( PrevChunk ) { // Shrink the current chunk. MatchingChunk->Base += MemoryAdjustment; MatchingChunk->Size -= MemoryAdjustment; // Grow the previous chunk. INT OriginalPrevSize = PrevChunk->Size; PrevChunk->Size += MemoryAdjustment; // If the previous chunk was "in use", split it and insert a 2nd free chunk. if ( !PrevChunk->bIsAvailable ) { Split( PrevChunk, OriginalPrevSize ); } } else { // This was the first chunk, split it. Split( MatchingChunk, MemoryAdjustment ); // We're going to use the new chunk. Mark it as "used memory". MatchingChunk = MatchingChunk->NextChunk; MatchingChunk->UnlinkFree(); // Make the original chunk "free memory". FreeChunk( MatchingChunk->PreviousChunk ); } check(PTRINT(NewBaseAddress) == PTRINT(MatchingChunk->Base)); PointerToChunkMap.Remove( PTRINT(OldBaseAddress) ); PointerToChunkMap.Set( PTRINT(NewBaseAddress), MatchingChunk ); // Update usage stats in a thread safe way. appInterlockedAdd( &AllocatedMemorySize, -MemoryAdjustment ); appInterlockedAdd( &AvailableMemorySize, +MemoryAdjustment ); return TRUE; } return FALSE; }
/* join the taint of two pointers that are supposed to be the same modulo the taint */ R *X(join_taint)(R *p1, R *p2) { A(UNTAINT(p1) == UNTAINT(p2)); return (R *)(PTRINT(p1) | PTRINT(p2)); }