diff options
Diffstat (limited to 'video/pixlib')
| -rw-r--r-- | video/pixlib/PixLib.vcxproj | 151 | ||||
| -rw-r--r-- | video/pixlib/PixLib.vcxproj.Filters | 22 | ||||
| -rw-r--r-- | video/pixlib/ReadMe.md | 7 | ||||
| -rw-r--r-- | video/pixlib/pixel.cpp | 695 | ||||
| -rw-r--r-- | video/pixlib/pixel.hpp | 365 | ||||
| -rw-r--r-- | video/pixlib/pixlib.cpp | 8 | ||||
| -rw-r--r-- | video/pixlib/pixlib.sln | 28 |
7 files changed, 1276 insertions, 0 deletions
diff --git a/video/pixlib/PixLib.vcxproj b/video/pixlib/PixLib.vcxproj new file mode 100644 index 00000000..422787ba --- /dev/null +++ b/video/pixlib/PixLib.vcxproj @@ -0,0 +1,151 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{4E06B3AB-DFAD-4F48-8936-FFF04466B8EA}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{81B1500C-93FF-426B-9F4E-AE70C8AC0E32}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>PixLib</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>PixLib</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>PixLib</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>PixLib</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="pixlib.cpp" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/video/pixlib/PixLib.vcxproj.Filters b/video/pixlib/PixLib.vcxproj.Filters new file mode 100644 index 00000000..48f6096a --- /dev/null +++ b/video/pixlib/PixLib.vcxproj.Filters @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{A8B745DE-6F64-4D24-9987-A54ECE81A482}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{826CC0FB-F174-4CEB-B426-B314EF20FC3D}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{AABC8FBD-8833-4320-AD01-F66555EFE527}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="pixlib.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/video/pixlib/ReadMe.md b/video/pixlib/ReadMe.md new file mode 100644 index 00000000..b7667909 --- /dev/null +++ b/video/pixlib/ReadMe.md @@ -0,0 +1,7 @@ +PixLib sample +============= + +The PixLib sample demonstrates how to implement the **CPixel** class for use by a display driver. + +For more information, see the WDK documentation topic, [CPixel Support Methods for Lightweight MIP Maps](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540585). + diff --git a/video/pixlib/pixel.cpp b/video/pixlib/pixel.cpp new file mode 100644 index 00000000..a1599e63 --- /dev/null +++ b/video/pixlib/pixel.cpp @@ -0,0 +1,695 @@ +/*==========================================================================; + * + * Copyright (C) 1999-2002 Microsoft Corporation. All Rights Reserved. + * + * File: pixel.cpp + * Content: Utility class for working with pixel formats + * + * + ***************************************************************************/ + +#include "strsafe.h" +#include "pixel.hpp" + +#ifndef DXPIXELVER +#define DXPIXELVER 100 +#endif + +IHVFormatInfo *CPixel::m_pFormatList = 0; + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::Cleanup" +void CPixel::Cleanup() +{ + while(m_pFormatList != 0) + { + IHVFormatInfo *t = m_pFormatList->m_pNext; + delete m_pFormatList; + m_pFormatList = t; + } +} + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::BytesPerPixel" + +UINT CPixel::BytesPerPixel(D3DFORMAT Format) +{ + switch (DWORD(Format)) + { + case D3DFMT_DXT1: + // Size is negative to indicate DXT; and indicates + // the size of the block + return (UINT)(-8); + case D3DFMT_DXT2: + case D3DFMT_DXT3: + case D3DFMT_DXT4: + case D3DFMT_DXT5: + // Size is negative to indicate DXT; and indicates + // the size of the block + return (UINT)(-16); + + +#if (DXPIXELVER > 8) + case D3DFMT_A32B32G32R32F: + return 16; + + case D3DFMT_A16B16G16R16: + case D3DFMT_Q16W16V16U16: + case D3DFMT_A16B16G16R16F: + case D3DFMT_G32R32F: + case D3DFMT_MULTI2_ARGB8: + return 8; +#endif + + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + case D3DFMT_D32: + case D3DFMT_D24S8: + case D3DFMT_S8D24: + case D3DFMT_X8L8V8U8: + case D3DFMT_X4S4D24: + case D3DFMT_D24X4S4: + case D3DFMT_Q8W8V8U8: + case D3DFMT_V16U16: + case D3DFMT_A2W10V10U10: + case D3DFMT_A2B10G10R10: + case D3DFMT_A8B8G8R8: + case D3DFMT_X8B8G8R8: + case D3DFMT_G16R16: + case D3DFMT_D24X8: + case D3DFMT_X8D24: + case D3DFMT_W11V11U10: +#if (DXPIXELVER > 8) + case D3DFMT_A2R10G10B10: + case D3DFMT_G16R16F: + case D3DFMT_R32F: + case D3DFMT_D32F_LOCKABLE: + case D3DFMT_D24FS8: + case D3DFMT_D32_LOCKABLE: +#endif + return 4; + + case D3DFMT_R8G8B8: + return 3; + + case D3DFMT_R5G6B5: + case D3DFMT_X1R5G5B5: + case D3DFMT_A1R5G5B5: + case D3DFMT_A4R4G4B4: + case D3DFMT_A8L8: + case D3DFMT_V8U8: + case D3DFMT_L6V5U5: + case D3DFMT_D16: + case D3DFMT_D16_LOCKABLE: + case D3DFMT_D15S1: + case D3DFMT_S1D15: + case D3DFMT_A8P8: + case D3DFMT_A8R3G3B2: + case D3DFMT_UYVY: + case D3DFMT_YUY2: + case D3DFMT_X4R4G4B4: +#if (DXPIXELVER > 8) + case D3DFMT_CxV8U8: + case D3DFMT_L16: + case D3DFMT_R16F: + case D3DFMT_R8G8_B8G8: + case D3DFMT_G8R8_G8B8: +#endif + return 2; + + case D3DFMT_P8: + case D3DFMT_L8: + case D3DFMT_R3G3B2: + case D3DFMT_A4L4: + case D3DFMT_A8: +#if (DXPIXELVER > 8) + case D3DFMT_A1: + case D3DFMT_S8_LOCKABLE: +#endif + return 1; + + default: + return 0; + }; +}; // BytesPerPixel + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::ComputePixelStride" + +UINT CPixel::ComputePixelStride(D3DFORMAT Format) +{ + UINT BPP = BytesPerPixel(Format); + if (BPP == 0) + { + for(IHVFormatInfo *p = m_pFormatList; p != 0; p = p->m_pNext) + { + if (p->m_Format == Format) + { + return p->m_BPP >> 3; + } + } + } + return BPP; +}; // ComputePixelStride + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::ComputeSurfaceStride" + +// Figure out a stride for a particular surface based on format and width +inline UINT CPixel::ComputeSurfaceStride(UINT cpWidth, UINT cbPixel) +{ + UINT uStride = 0; + ComputeSurfaceStrideChecked(cpWidth, cbPixel, &uStride); + return uStride; +}; // ComputeSurfaceStride + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::ComputeSurfaceStrideChecked" + +// Figure out a stride for a particular surface based on format and width +inline BOOL CPixel::ComputeSurfaceStrideChecked(UINT cpWidth, UINT cbPixel, UINT *pStride) +{ + // Figure out basic (linear) stride; + UINT64 u64Stride = (UINT64)cpWidth * (UINT64)cbPixel; + + // Round up to multiple of 4 (for NT; but makes sense to maximize + // cache hits and reduce unaligned accesses) + // + // NOTE: Also necessary for UYVY and YUY2 formats that this round + // up by at least a multiple of 4. + u64Stride = (u64Stride + 3) & ~3; //safe since cbPixel cannot be 4G + + if (u64Stride <= MAXALLOCSIZE) + { + *pStride = (UINT)u64Stride; + return TRUE; + } + return FALSE; +}; // ComputeSurfaceStride + + + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::ComputeSurfaceSize" + +UINT CPixel::ComputeSurfaceSize(UINT cpWidth, + UINT cpHeight, + UINT cbPixel) +{ + UINT uSize; + ComputeSurfaceSizeChecked(cpWidth, cpHeight, cbPixel, &uSize); + return uSize; +} // ComputeSurfaceSize + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::ComputeSurfaceSizeChecked" + +BOOL CPixel::ComputeSurfaceSizeChecked(UINT cpWidth, + UINT cpHeight, + UINT cbPixel, + UINT *pSize) + +{ + UINT uStride; + UINT64 uSize64; + if (ComputeSurfaceStrideChecked(cpWidth, cbPixel, &uStride)) + { + uSize64 = (UINT64)cpHeight * (UINT64)uStride; + if (uSize64 <= MAXALLOCSIZE) + { + *pSize = (UINT)uSize64; + return TRUE; + } + } + + *pSize = 0U; + return FALSE; +} // ComputeSurfaceSize + + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::ComputeMipMapSize" + +UINT CPixel::ComputeMipMapSize(UINT cpWidth, + UINT cpHeight, + UINT cLevels, + D3DFORMAT Format) +{ + UINT uSize = 0; // initialize to zero to keep prefix happy win7: 185027 + ComputeMipMapSizeChecked(cpWidth, cpHeight, cLevels, Format, &uSize); + return uSize; +} // ComputeMipMapSize + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::ComputeMipMapSizeChecked" + +BOOL CPixel::ComputeMipMapSizeChecked(UINT cpWidth, + UINT cpHeight, + UINT cLevels, + D3DFORMAT Format, + UINT *pSize) +{ + UINT cbPixel = ComputePixelStride(Format); + + // Adjust pixel->block if necessary + BOOL isDXT = IsDXT(cbPixel); + if (isDXT) + cbPixel *= (UINT)-1; + + UINT64 cbSize = 0; + if (cpWidth > MAXALLOCSIZE-3 || cpHeight > MAXALLOCSIZE-3) + return FALSE; + + for (UINT i = 0; i < cLevels; i++) + { + UINT cbMipSize; + // Figure out the size for + // each level of the mip-map + if (isDXT) + { + if (!ComputeSurfaceSizeChecked((cpWidth+3)/4, (cpHeight+3)/4, cbPixel, &cbMipSize)) + return FALSE; + } + else + { + if (!ComputeSurfaceSizeChecked(cpWidth, cpHeight, cbPixel, &cbMipSize)) + return FALSE; + } + cbSize += cbMipSize; + // Shrink width and height by half; clamp to 1 pixel + if (cpWidth > 1) + cpWidth >>= 1; + if (cpHeight > 1) + cpHeight >>= 1; + } + if (cbSize <= MAXALLOCSIZE) + { + *pSize = (UINT)cbSize; + return TRUE; + } + return FALSE; + +} // ComputeMipMapSize + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::ComputeMipVolumeSize" + +UINT CPixel::ComputeMipVolumeSize(UINT cpWidth, + UINT cpHeight, + UINT cpDepth, + UINT cLevels, + D3DFORMAT Format) +{ + UINT uSize = 0; // To keep prefix happy win7: 185029 + ComputeMipVolumeSizeChecked(cpWidth, cpHeight, cpDepth, cLevels, Format, &uSize); + return uSize; +} // ComputeMipVolumeSize + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::ComputeMipVolumeSizeChecked" + +BOOL CPixel::ComputeMipVolumeSizeChecked(UINT cpWidth, + UINT cpHeight, + UINT cpDepth, + UINT cLevels, + D3DFORMAT Format, + UINT *pSize) +{ + UINT cbPixel = ComputePixelStride(Format); + + // Adjust pixel->block if necessary + BOOL isDXT = IsDXT(cbPixel); + + if (isDXT) + cbPixel *= (UINT)-1; + + UINT64 cbSize = 0; + + if (cpWidth > MAXALLOCSIZE-3 || cpHeight > MAXALLOCSIZE-3 || cpDepth > MAXALLOCSIZE-3) + return FALSE; + + for (UINT i = 0; i < cLevels; i++) + { + // Figure out the size for + // each level of the mip-volume + UINT Depth = cpDepth; + UINT64 cbLevelSize; + UINT cbSliceSize; + if (isDXT) + { + if (!ComputeSurfaceSizeChecked((cpWidth+3)/4, (cpHeight+3)/4, cbPixel, &cbSliceSize)) + return FALSE; + } + else + { + if (!ComputeSurfaceSizeChecked(cpWidth, cpHeight, cbPixel, &cbSliceSize)) + return FALSE; + } + cbLevelSize = (UINT64)Depth * (UINT64)cbSliceSize; + if (cbLevelSize > MAXALLOCSIZE) + return FALSE; + cbSize += cbLevelSize; + + // Shrink width and height by half; clamp to 1 pixel + if (cpWidth > 1) + cpWidth >>= 1; + if (cpHeight > 1) + cpHeight >>= 1; + if (cpDepth > 1) + cpDepth >>= 1; + } + + if (cbSize <= MAXALLOCSIZE) + { + *pSize = (UINT)cbSize; + return TRUE; + } + return FALSE; + +} // ComputeMipVolumeSize + +// Given a surface desc, a level, and pointer to +// bits (pBits in the LockedRectData) and a sub-rect, +// this will fill in the pLockedRectData structure +void CPixel::ComputeMipMapOffset(const D3DSURFACE_DESC *pDescTopLevel, + UINT iLevel, + BYTE *pBits, + CONST RECT *pRect, + D3DLOCKED_RECT *pLockedRectData) +{ + DXGASSERT(pBits != NULL); + DXGASSERT(pLockedRectData != NULL); + DXGASSERT(iLevel < 32); + DXGASSERT(pDescTopLevel != NULL); + DXGASSERT(0 != ComputePixelStride(pDescTopLevel->Format)); + DXGASSERT(pDescTopLevel->Width > 0); + DXGASSERT(pDescTopLevel->Height > 0); + + // CONSIDER: This is slow; and we can do a much better + // job for the non-compressed/wacky cases. + UINT cbOffset = 0; + UINT cbPixel = ComputePixelStride(pDescTopLevel->Format); + UINT cpWidth = pDescTopLevel->Width; + UINT cpHeight = pDescTopLevel->Height; + + // Adjust pixel->block if necessary + BOOL isDXT = IsDXT(cbPixel); + if (isDXT) + cbPixel *= (UINT)-1; + BOOL OneBitPerPixelFormat = FALSE; +#if (DXPIXELVER > 8) + OneBitPerPixelFormat = pDescTopLevel->Format == D3DFMT_A1; + if (OneBitPerPixelFormat) + { + cbPixel = 1; + } +#endif + for (UINT i = 0; i < iLevel; i++) + { + if (isDXT) + cbOffset += ComputeSurfaceSize((cpWidth+3)/4, (cpHeight+3)/4, cbPixel); + else + if (OneBitPerPixelFormat) + cbOffset += ComputeSurfaceSize((cpWidth + 7) >> 3, cpHeight, cbPixel); + else + cbOffset += ComputeSurfaceSize(cpWidth, cpHeight, cbPixel); + + // Shrink width and height by half; clamp to 1 pixel + if (cpWidth > 1) + cpWidth >>= 1; + if (cpHeight > 1) + cpHeight >>= 1; + } + if (isDXT) + cpWidth = (cpWidth+3)/4; + else + if (OneBitPerPixelFormat) + cpWidth = (cpWidth+7)/8; + + + // For DXTs, the pitch is the number of bytes + // for a single row of blocks; which is the same + // thing as the normal routine + pLockedRectData->Pitch = ComputeSurfaceStride(cpWidth, + cbPixel); + DXGASSERT(pLockedRectData->Pitch != 0); + + // Don't adjust for Rect for DXT formats + if (pRect) + { + if (isDXT) + { + DXGASSERT((pRect->top & 3) == 0); + DXGASSERT((pRect->left & 3) == 0); + cbOffset += (pRect->top / 4) * pLockedRectData->Pitch + + (pRect->left / 4) * cbPixel; + } + else + if (OneBitPerPixelFormat) + { + // Assume that left is always 8 pixels aligned + cbOffset += pRect->top * pLockedRectData->Pitch + + (pRect->left >> 3); + } + else + { + cbOffset += pRect->top * pLockedRectData->Pitch + + pRect->left * cbPixel; + } + } + + pLockedRectData->pBits = pBits + cbOffset; + +} // ComputeMipMapOffset + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::ComputeMipVolumeOffset" + +// MipVolume version of ComputeMipMapOffset +void CPixel::ComputeMipVolumeOffset(const D3DVOLUME_DESC *pDescTopLevel, + UINT iLevel, + BYTE *pBits, + CONST D3DBOX *pBox, + D3DLOCKED_BOX *pLockedBoxData) +{ + DXGASSERT(pBits != NULL); + DXGASSERT(pLockedBoxData != NULL); + DXGASSERT(iLevel < 32); + DXGASSERT(pDescTopLevel != NULL); + DXGASSERT(0 != ComputePixelStride(pDescTopLevel->Format)); + DXGASSERT(pDescTopLevel->Width > 0); + DXGASSERT(pDescTopLevel->Height > 0); + DXGASSERT(pDescTopLevel->Depth > 0); + + UINT cbOffset = 0; + UINT cbPixel = ComputePixelStride(pDescTopLevel->Format); + UINT cpWidth = pDescTopLevel->Width; + UINT cpHeight = pDescTopLevel->Height; + UINT cpDepth = pDescTopLevel->Depth; + + // Adjust pixel->block if necessary + BOOL isDXT = IsDXT(cbPixel); + + if (isDXT) + cbPixel *= (UINT)-1; + + for (UINT i = 0; i < iLevel; i++) + { + UINT Depth = cpDepth; + if (isDXT) + cbOffset += Depth * ComputeSurfaceSize((cpWidth+3)/4, (cpHeight+3)/4, cbPixel); + else + cbOffset += Depth * ComputeSurfaceSize(cpWidth, cpHeight, cbPixel); + + // Shrink width and height by half; clamp to 1 pixel + if (cpWidth > 1) + cpWidth >>= 1; + if (cpHeight > 1) + cpHeight >>= 1; + if (cpDepth > 1) + cpDepth >>= 1; + } + + if (isDXT) + { + cpWidth = (cpWidth+3)/4; + cpHeight = (cpHeight+3)/4; + } + + // For DXTs, the row pitch is the number of bytes + // for a single row of blocks; which is the same + // thing as the normal routine + pLockedBoxData->RowPitch = ComputeSurfaceStride(cpWidth, + cbPixel); + DXGASSERT(pLockedBoxData->RowPitch != 0); + + // For DXVs the slice pitch is the number of bytes + // for a single plane of blocks; which is the same thing + // as the normal routine + pLockedBoxData->SlicePitch = ComputeSurfaceSize(cpWidth, + cpHeight, + cbPixel); + DXGASSERT(pLockedBoxData->SlicePitch != 0); + + // Adjust for Box + if (pBox) + { + UINT iStride = pLockedBoxData->RowPitch; + UINT iSlice = pLockedBoxData->SlicePitch; + if (isDXT) + { + cbOffset += (pBox->Front) * iSlice; + + DXGASSERT((pBox->Top & 3) == 0); + DXGASSERT((pBox->Left & 3) == 0); + cbOffset += (pBox->Top / 4) * iStride + + (pBox->Left / 4) * cbPixel; + } + else + { + cbOffset += pBox->Front * iSlice + + pBox->Top * iStride + + pBox->Left * cbPixel; + } + } + + pLockedBoxData->pBits = pBits + cbOffset; + +} // ComputeMipVolumeOffset + + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::Register" + +HRESULT CPixel::Register(D3DFORMAT Format, DWORD BPP) +{ + DXGASSERT(BPP != 0); + + // Do not register duplicates + IHVFormatInfo *p; + for(p = m_pFormatList; p != 0; p = p->m_pNext) + { + if (p->m_Format == Format) + { + return S_OK; + } + } + + // Not found, add to registry. + // This allocation will be leaked, but since + // we don't expect to have a large number of + // IHV formats, the leak is not a big deal. + // Also, the leak will be immediately recovered + // upon process exit. + IHVFormatInfo *p2 = new IHVFormatInfo; + if (p2 == 0) + { + return E_OUTOFMEMORY; + } + p2->m_Format = Format; + p2->m_BPP = BPP; + p2->m_pNext = m_pFormatList; + m_pFormatList = p2; + + return S_OK; +} + + +extern "C" UINT CPixel__ComputeSurfaceSize(UINT cpWidth, + UINT cpHeight, + D3DFORMAT Format) +{ + return CPixel::ComputeSurfaceSize(cpWidth, cpHeight, Format); +} + +extern "C" UINT CPixel__ComputeVolumeSize(UINT cpWidth, + UINT cpHeight, + UINT cpDepth, + D3DFORMAT Format) +{ + return CPixel::ComputeVolumeSize(cpWidth, cpHeight, cpDepth, Format); +} + +extern "C" UINT CPixel__ComputeMipMapSize(UINT cpWidth, + UINT cpHeight, + UINT cLevels, + D3DFORMAT Format) +{ + return CPixel::ComputeMipMapSize(cpWidth, cpHeight, cLevels, Format); +} + +extern "C" UINT CPixel__ComputeMipVolumeSize(UINT cpWidth, + UINT cpHeight, + UINT cpDepth, + UINT cLevels, + D3DFORMAT Format) +{ + return CPixel::ComputeMipVolumeSize(cpWidth, cpHeight, cpDepth, cLevels, Format); +} + +extern "C" void CPixel__ComputeMipMapOffset(const D3DSURFACE_DESC *pDescTopLevel, + UINT iLevel, + BYTE *pBits, + CONST RECT *pRect, + D3DLOCKED_RECT *pLockedRectData) +{ + CPixel::ComputeMipMapOffset(pDescTopLevel, iLevel, pBits, pRect, pLockedRectData); +} + +extern "C" void CPixel__ComputeMipVolumeOffset(const D3DVOLUME_DESC *pDescTopLevel, + UINT iLevel, + BYTE *pBits, + CONST D3DBOX *pBox, + D3DLOCKED_BOX *pLockedBoxData) +{ + CPixel::ComputeMipVolumeOffset(pDescTopLevel, iLevel, pBits, pBox, pLockedBoxData); +} + +extern "C" void CPixel__ComputeSurfaceOffset(const D3DSURFACE_DESC *pDesc, + BYTE *pBits, + CONST RECT *pRect, + D3DLOCKED_RECT *pLockedRectData) +{ + CPixel::ComputeSurfaceOffset(pDesc, pBits, pRect, pLockedRectData); +} + +extern "C" UINT CPixel__ComputePixelStride(D3DFORMAT Format) +{ + return CPixel::ComputePixelStride(Format); +} + +extern "C" void CPixel__AdjustForDXT(UINT *pcpWidth, + UINT *pcpHeight, + UINT *pcbPixel) +{ + CPixel::AdjustForDXT(pcpWidth, pcpHeight, pcbPixel); +} + +extern "C" BOOL CPixel__IsDXT(D3DFORMAT Format) +{ + return CPixel::IsDXT(Format); +} + +extern "C" UINT CPixel__BytesPerPixel(D3DFORMAT Format) +{ + return CPixel::BytesPerPixel(Format); +} + +extern "C" HRESULT CPixel__Register(D3DFORMAT Format, DWORD BPP) +{ + return CPixel::Register(Format, BPP); +} + +extern "C" void CPixel__Cleanup() +{ + CPixel::Cleanup(); +} + +extern "C" UINT CPixel__ComputeSurfaceStride(UINT cpWidth, UINT cbPixel) +{ + return CPixel::ComputeSurfaceStride(cpWidth, cbPixel); +} + + +// End of file : pixel.cpp + diff --git a/video/pixlib/pixel.hpp b/video/pixlib/pixel.hpp new file mode 100644 index 00000000..a23a79f6 --- /dev/null +++ b/video/pixlib/pixel.hpp @@ -0,0 +1,365 @@ +/*==========================================================================; + * + * Copyright (C) 1999-2002 Microsoft Corporation. All Rights Reserved. + * + * File: pixel.hpp + * Content: Utility class for working with pixel formats + * + * + ***************************************************************************/ + +#ifdef __cplusplus + +#ifndef __PIXEL_HPP_CPP__ +#define __PIXEL_HPP_CPP__ + +#ifndef DXPIXELVER +#define DXPIXELVER 100 +#endif + +#ifndef DXGASSERT +#define DXGASSERT( x ) _Analysis_assume_( x ); +#endif + +struct IHVFormatInfo +{ + D3DFORMAT m_Format; + DWORD m_BPP; + IHVFormatInfo *m_pNext; +}; + +//2GB max allocation size +#define MAXALLOCSIZE 0x80000000 + +// This is a utility class that implements useful helpers for +// allocating and accessing various pixel formats. All methods +// are static and hence should be accessed as follows: +// e.g. CPixel::LockOffset(...) +// + +class CPixel +{ +public: + // Allocate helpers + + // Determine the amount of memory that is needed to + // allocate various things.. + static UINT ComputeSurfaceSize(UINT cpWidth, + UINT cpHeight, + D3DFORMAT Format); + + static UINT ComputeVolumeSize(UINT cpWidth, + UINT cpHeight, + UINT cpDepth, + D3DFORMAT Format); + + + static UINT ComputeMipMapSize(UINT cpWidth, + UINT cpHeight, + UINT cLevels, + D3DFORMAT Format); + + static UINT ComputeMipVolumeSize(UINT cpWidth, + UINT cpHeight, + UINT cpDepth, + UINT cLevels, + D3DFORMAT Format); + + static BOOL ComputeSurfaceSizeChecked(UINT cpWidth, + UINT cpHeight, + D3DFORMAT Format, + UINT *pSize); + + static BOOL ComputeVolumeSizeChecked(UINT cpWidth, + UINT cpHeight, + UINT cpDepth, + D3DFORMAT Format, + UINT *pSize); + + + static BOOL ComputeMipMapSizeChecked(UINT cpWidth, + UINT cpHeight, + UINT cLevels, + D3DFORMAT Format, + UINT *pSize); + + static BOOL ComputeMipVolumeSizeChecked(UINT cpWidth, + UINT cpHeight, + UINT cpDepth, + UINT cLevels, + D3DFORMAT Format, + UINT *pSize); + + + // Lock helpers + + // Given a surface desc, a level, and pointer to + // bits (pBits in the LockedRectData) and a sub-rect, + // this will fill in the pLockedRectData structure + static void ComputeMipMapOffset(const D3DSURFACE_DESC *pDescTopLevel, + UINT iLevel, + BYTE *pBits, + CONST RECT *pRect, + D3DLOCKED_RECT *pLockedRectData); + + // MipVolume version of ComputeMipMapOffset + static void ComputeMipVolumeOffset(const D3DVOLUME_DESC *pDescTopLevel, + UINT iLevel, + BYTE *pBits, + CONST D3DBOX *pBox, + D3DLOCKED_BOX *pLockedBoxData); + + // Surface version of ComputeMipMapOffset + static void ComputeSurfaceOffset(const D3DSURFACE_DESC *pDesc, + BYTE *pBits, + CONST RECT *pRect, + D3DLOCKED_RECT *pLockedRectData); + + // Pixel Stride will return negative for DXT formats + // Call AdjustForDXT to work with things at the block level + static UINT ComputePixelStride(D3DFORMAT Format); + + // This will adjust cbPixel + // to pixels per block; and width and height will + // be adjusted to pixels. Assumes the IsDXT(cbPixel). + static void AdjustForDXT(UINT *pcpWidth, + UINT *pcpHeight, + UINT *pcbPixel); + + // returns TRUE if cbPixel is "negative" i.e. DXT/V group + static BOOL IsDXT(UINT cbPixel); + + // returns TRUE if format is one of the DXT/V group + static BOOL IsDXT(D3DFORMAT Format); + + static UINT BytesPerPixel(D3DFORMAT Format); + + // Register format for later lookup + static HRESULT Register(D3DFORMAT Format, DWORD BPP); + + // Cleanup registry + static void Cleanup(); + + static UINT ComputeSurfaceStride(UINT cpWidth, UINT cbPixel); + + static BOOL ComputeSurfaceStrideChecked(UINT cpWidth, UINT cbPixel, UINT *pStride); + + +private: + // Internal functions + + static UINT ComputeSurfaceSize(UINT cpWidth, + UINT cpHeight, + UINT cbPixel); + + static BOOL ComputeSurfaceSizeChecked(UINT cpWidth, + UINT cpHeight, + UINT cbPixel, + UINT *pSize); + + + static IHVFormatInfo *m_pFormatList; + +}; // CPixel + + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::ComputeSurfaceOffset" + +inline void CPixel::ComputeSurfaceOffset(const D3DSURFACE_DESC *pDesc, + BYTE *pBits, + CONST RECT *pRect, + D3DLOCKED_RECT *pLockedRectData) +{ + ComputeMipMapOffset(pDesc, 0, pBits, pRect, pLockedRectData); +} // ComputeSurfaceOffset + + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::ComputeSurfaceSize" + +inline UINT CPixel::ComputeSurfaceSize(UINT cpWidth, + UINT cpHeight, + D3DFORMAT Format) +{ + UINT uSize = 0; // initialize to zero to keep prefix happy win7: 185026 + ComputeSurfaceSizeChecked(cpWidth, cpHeight, Format, &uSize); + return uSize; +} // ComputeSurfaceSize + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::ComputeSurfaceSizeChecked" + +inline BOOL CPixel::ComputeSurfaceSizeChecked(UINT cpWidth, + UINT cpHeight, + D3DFORMAT Format, + UINT *uSize) +{ + UINT cbPixel = ComputePixelStride(Format); + + // Adjust pixel->block if necessary + BOOL isDXT = IsDXT(cbPixel); + if (isDXT) + { + AdjustForDXT(&cpWidth, &cpHeight, &cbPixel); + } +#if (DXPIXELVER > 8) + else + if (Format == D3DFMT_A1) + { + cpWidth = (cpWidth + 7) >> 3; + cbPixel = 1; + } +#endif + + return ComputeSurfaceSizeChecked(cpWidth, + cpHeight, + cbPixel, + uSize); +} // ComputeSurfaceSize + + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::AdjustForDXT" +inline void CPixel::AdjustForDXT(UINT *pcpWidth, + UINT *pcpHeight, + UINT *pcbPixel) +{ + DXGASSERT(pcbPixel); + DXGASSERT(pcpWidth); + DXGASSERT(pcpHeight); + DXGASSERT(IsDXT(*pcbPixel)); + + // Adjust width and height for DXT formats to be in blocks + // instead of pixels. Blocks are 4x4 pixels. + *pcpWidth = (*pcpWidth + 3) / 4; + *pcpHeight = (*pcpHeight + 3) / 4; + + // Negate the pcbPixel to determine bytes per block + *pcbPixel *= (UINT)-1; + + // We only know of two DXT formats right now... + DXGASSERT(*pcbPixel == 8 || *pcbPixel == 16); + +} // CPixel::AdjustForDXT + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::ComputeVolumeSize" + +inline UINT CPixel::ComputeVolumeSize(UINT cpWidth, + UINT cpHeight, + UINT cpDepth, + D3DFORMAT Format) +{ + UINT cbPixel = ComputePixelStride(Format); + + if (IsDXT(cbPixel)) + { + AdjustForDXT(&cpWidth, &cpHeight, &cbPixel); + } + + return cpDepth * ComputeSurfaceSize(cpWidth, cpHeight, cbPixel); +} // ComputeVolumeSize + + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::IsDXT(cbPixel)" + +// returns TRUE if cbPixel is "negative" +inline BOOL CPixel::IsDXT(UINT cbPixel) +{ + if (((INT)cbPixel) < 0) + return TRUE; + else + return FALSE; +} // IsDXT + +#undef DPF_MODNAME +#define DPF_MODNAME "CPixel::IsDXT(format)" + +// returns TRUE if this is a linear format +// i.e. DXT or DXV +inline BOOL CPixel::IsDXT(D3DFORMAT Format) +{ + // CONSIDER: This is a duplication of Requires4x4 function + switch (Format) + { + // normal DXTs + case D3DFMT_DXT1: + case D3DFMT_DXT2: + case D3DFMT_DXT3: + case D3DFMT_DXT4: + case D3DFMT_DXT5: + return TRUE; + } + + return FALSE; +} // IsDXT + + +#endif // __PIXEL_HPP_CPP__ + +#else + +#ifndef __PIXEL_HPP_C__ +#define __PIXEL_HPP_C__ + +UINT CPixel__ComputeSurfaceSize(UINT cpWidth, + UINT cpHeight, + D3DFORMAT Format); + +UINT CPixel__ComputeVolumeSize(UINT cpWidth, + UINT cpHeight, + UINT cpDepth, + D3DFORMAT Format); + +UINT CPixel__ComputeMipMapSize(UINT cpWidth, + UINT cpHeight, + UINT cLevels, + D3DFORMAT Format); + +UINT CPixel__ComputeMipVolumeSize(UINT cpWidth, + UINT cpHeight, + UINT cpDepth, + UINT cLevels, + D3DFORMAT Format); + +void CPixel__ComputeMipMapOffset(const D3DSURFACE_DESC *pDescTopLevel, + UINT iLevel, + BYTE *pBits, + CONST RECT *pRect, + D3DLOCKED_RECT *pLockedRectData); + +void CPixel__ComputeMipVolumeOffset(const D3DVOLUME_DESC *pDescTopLevel, + UINT iLevel, + BYTE *pBits, + CONST D3DBOX *pBox, + D3DLOCKED_BOX *pLockedBoxData); + +void CPixel__ComputeSurfaceOffset(const D3DSURFACE_DESC *pDesc, + BYTE *pBits, + CONST RECT *pRect, + D3DLOCKED_RECT *pLockedRectData); + +UINT CPixel__ComputePixelStride(D3DFORMAT Format); + +void CPixel__AdjustForDXT(UINT *pcpWidth, + UINT *pcpHeight, + UINT *pcbPixel); + +BOOL CPixel__IsDXT(D3DFORMAT Format); + +UINT CPixel__BytesPerPixel(D3DFORMAT Format); + +HRESULT CPixel__Register(D3DFORMAT Format, DWORD BPP); + +void CPixel__Cleanup(); + +UINT CPixel__ComputeSurfaceStride(UINT cpWidth, UINT cbPixel); + + +#endif // __PIXEL_HPP_C__ + +#endif + + diff --git a/video/pixlib/pixlib.cpp b/video/pixlib/pixlib.cpp new file mode 100644 index 00000000..df761641 --- /dev/null +++ b/video/pixlib/pixlib.cpp @@ -0,0 +1,8 @@ + +#include "d3d9.h" +#include "ddraw.h" +#include "dx95type.h" +#include "d3dnthal.h" + +#include "pixel.cpp" + diff --git a/video/pixlib/pixlib.sln b/video/pixlib/pixlib.sln new file mode 100644 index 00000000..4be1ce6b --- /dev/null +++ b/video/pixlib/pixlib.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0 +MinimumVisualStudioVersion = 12.0 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PixLib", "PixLib.vcxproj", "{4E06B3AB-DFAD-4F48-8936-FFF04466B8EA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4E06B3AB-DFAD-4F48-8936-FFF04466B8EA}.Debug|Win32.ActiveCfg = Debug|Win32 + {4E06B3AB-DFAD-4F48-8936-FFF04466B8EA}.Debug|Win32.Build.0 = Debug|Win32 + {4E06B3AB-DFAD-4F48-8936-FFF04466B8EA}.Release|Win32.ActiveCfg = Release|Win32 + {4E06B3AB-DFAD-4F48-8936-FFF04466B8EA}.Release|Win32.Build.0 = Release|Win32 + {4E06B3AB-DFAD-4F48-8936-FFF04466B8EA}.Debug|x64.ActiveCfg = Debug|x64 + {4E06B3AB-DFAD-4F48-8936-FFF04466B8EA}.Debug|x64.Build.0 = Debug|x64 + {4E06B3AB-DFAD-4F48-8936-FFF04466B8EA}.Release|x64.ActiveCfg = Release|x64 + {4E06B3AB-DFAD-4F48-8936-FFF04466B8EA}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal |
