MMXSwarm Sample: Demonstrates CImage and Visual C++ MMX Support
The sample demonstrates the implementation of CImage support into an application for basic loading and saving of data in many image formats. In addition, the sample demonstrates direct manipulation of a DIB surface, as well as using higher-level compiler support for MMX and SSE2 integer instructions to optimize bitmap manipulation without writing assembler code.
In the project, the Surface.* files contain the C++ base class for the DIB surface manipulation:
- The MMXSurface*.* files contain derived classes with MMX optimizations. MMXWrapper.h contains a simple class that encapsulates the compiler's __m64 data type and operations into a C++ friendly class for 16-bit saturated MMX operations.
- The SSE2Surface*.* files contain derived classes with SSE2 optimizations. SSE2Wrapper.h contains a simple class that encapsulates the compiler's __m128i data type and operations into a C++ friendly class for 16-bit saturated SSE2 integer operations.
These wrapper classes are not generally useful "as is", containing only enough functionality for the sample. The sample does not use the document/view archictecture. The
CChildView class is derived from CWnd and bound to the frame window.
Building and Running the Sample
To build and run the MMXSwarm sample
- Open the solution MMXSwarm.sln.
- On the Build menu, click Build.
- On the Debug menu, click Start Without Debugging.
In both Debug and Release mode, assembly listings of the MMXSurface*.cpp and SSE2Surface*.cpp files are generated in the output directory. Examine these files to see the code generated by the MMX and SSE2 portions of the project.
Build the sample in Release mode to see the speed improvements gained from using the intrinsic MMX and SSE2 integer support. In addition, debug information is generated for the release build to ease stepping through the MMX and SSE2 generated code.
For best results, run the sample in 32-bit color mode.
The sample draws a simple swarm on the screen and uses a custom fade routine to blur the image over time. The File menu has the options for saving the current image or loading an existing image. The View menu has options to disable/enable the blurring and the swarm. The View menu also contains a 'Pause Blit' command that will disable the BitBlt to the screen that enables better frame rate distinctions in the blur implementations. In addition, several keystrokes are asynchronously checked for other DIB manipulation (SHIFT, SPACE, UP ARROW, and DELETE). Finally, the CImage menu lets you select the bit depth of the DIB being manipulated. Typically, it is best if it matches the desktop bit depth. Each bit depth has an option for blurring with a generic C++ routine, or one optimized with the MMX or SSE2 integer intrinsics. The status bar contains a frame-per-second measurement to illustrate the performance differences.
This sample demonstrates the following keywords:
CImage::GetExporterFilterString, CImage::Load, CImage::SaveAdvanced, CImage::Create, CImage::GetPitch, CImage::GetDC, CImage::ReleaseDC, CImage::Destroy, CImage::BitBlt, CImage::GetBits, CImage::GetHeight, CImage::GetPixelAddress, GetAsyncKeyState, CDC::GetDeviceCaps, ON_UPDATE_COMMAND_UI_RANGE, CWnd::OnSizing, __m64, __m128i, CWinApp::OnIdle, _m_from_int, _mm_setzero_si64, _mm_adds_pu16, _mm_subs_pu16, _mm_srli_pi16, _mm_slli_pi16, _mm_and_si64, _mm_or_si64, _mm_andnot_si64, _m_to_int, _mm_packs_pu16, _mm_unpacklo_pi8, _mm_unpackhi_pi8, _mm_loadl_epi64, _mm_setzero_si128, _mm_set1_epi64, _mm_adds_epu16, _mm_subs_epu16, _mm_srli_epi16, _mm_slli_epi16, _mm_and_si128, _mm_or_si128, _mm_andnot_si128, _mm_packus_epi16, _mm_store_si128, _mm_load_si128, _mm_packus_epi16, _mm_unpacklo_epi8, _mm_unpackhi_epi8