OSDN Git Service

#32713 初コミット。SVNrev567時点での、ファイルはbranch/140707(ReBuild XGVersion)から移行したもの。
[dtxmaniaxg-verk/dtxmaniaxg-verk-git.git] / SlimDXc_Jun2010(VC++2008) / source / Utilities.cpp
1 #include "stdafx.h"
2 /*
3 * Copyright (c) 2007-2010 SlimDX Group
4
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24 #include "DataStream.h"
25 #include "Utilities.h"
26 #include "multimedia/WaveStream.h"
27
28 #include "SlimDXException.h"
29
30 using namespace System;
31 using namespace System::Collections::Generic;
32 using namespace System::IO;
33 using namespace System::Reflection;
34 using namespace System::Globalization;
35 using namespace SlimDX::Multimedia;
36
37 namespace SlimDX
38 {
39         Utilities::Utilities()
40         {
41         }
42
43         generic<typename T> where T : value class
44         array<T>^ Utilities::ReadRange( ID3DXBuffer *buffer, int count )
45         {
46                 if( count < 0 )
47                         throw gcnew ArgumentOutOfRangeException( "count" );
48
49                 if (buffer == NULL)
50                         return nullptr;
51                         
52                 size_t elementSize = sizeof(T);
53                 array<T>^ result = gcnew array<T>( count );
54
55                 pin_ptr<T> pinnedBuffer = &result[0];
56                 memcpy( pinnedBuffer, buffer->GetBufferPointer(), count * elementSize );
57
58                 buffer->Release();
59
60                 return result;
61         }
62         
63         //TODO: This needs review upon interface refactor.
64         GUID Utilities::GetNativeGuidForType( Type^ type )
65         {
66                 if( type == nullptr )
67                         throw gcnew ArgumentNullException( "type" );
68                 
69                 // This will only work for ComObjects.
70                 if( !type->IsSubclassOf( ComObject::typeid ) )
71                         return GUID_NULL;
72                 
73                 // This should never fail (i.e., should never return null) since we now know the type is a ComObject subclass.
74                 //TODO: Old comobjects have this private, new ones public. blah blah. this needs to be moved to an attribute anyway
75                 //      or it won't work with interfaces.
76                 PropertyInfo^ nativeInterfaceProperty = type->GetProperty( "NativeInterface", BindingFlags::NonPublic | BindingFlags::Static );
77                 if( nativeInterfaceProperty == nullptr ) 
78                         nativeInterfaceProperty = type->GetProperty( "NativeInterface" );
79
80                 Guid nativeInterface = static_cast<Guid>( nativeInterfaceProperty->GetValue( nullptr, nullptr ) );
81                 
82                 return ConvertManagedGuid( nativeInterface );
83         }
84         
85         Guid Utilities::ConvertNativeGuid( const GUID &guid )
86         {
87                 if( guid == GUID_NULL )
88                         return Guid::Empty;
89
90                 Guid result(
91                         guid.Data1,
92                         guid.Data2,
93                         guid.Data3,
94                         guid.Data4[0],
95                         guid.Data4[1],
96                         guid.Data4[2], 
97                         guid.Data4[3],
98                         guid.Data4[4],
99                         guid.Data4[5],
100                         guid.Data4[6],
101                         guid.Data4[7]
102                 );
103
104                 return result;
105         }
106
107         GUID Utilities::ConvertManagedGuid( Guid guid )
108         {
109                 if( guid == Guid::Empty )
110                         return GUID_NULL;
111
112                 GUID result;
113                 array<Byte>^ bytes = guid.ToByteArray();
114                 pin_ptr<unsigned char> pinned_bytes = &bytes[0];
115                 memcpy( &result, pinned_bytes, sizeof(GUID) );
116
117                 return result;
118         }
119         
120         int Utilities::SizeOfFormatElement( DXGI_FORMAT format )
121         {
122                 switch( format )
123                 {
124                         case DXGI_FORMAT_R32G32B32A32_TYPELESS:
125                         case DXGI_FORMAT_R32G32B32A32_FLOAT:
126                         case DXGI_FORMAT_R32G32B32A32_UINT:
127                         case DXGI_FORMAT_R32G32B32A32_SINT:
128                                 return 128;
129                                 
130                         case DXGI_FORMAT_R32G32B32_TYPELESS:
131                         case DXGI_FORMAT_R32G32B32_FLOAT:
132                         case DXGI_FORMAT_R32G32B32_UINT:
133                         case DXGI_FORMAT_R32G32B32_SINT:
134                                 return 96;
135                                 
136                         case DXGI_FORMAT_R16G16B16A16_TYPELESS:
137                         case DXGI_FORMAT_R16G16B16A16_FLOAT:
138                         case DXGI_FORMAT_R16G16B16A16_UNORM:
139                         case DXGI_FORMAT_R16G16B16A16_UINT:
140                         case DXGI_FORMAT_R16G16B16A16_SNORM:
141                         case DXGI_FORMAT_R16G16B16A16_SINT:
142                         case DXGI_FORMAT_R32G32_TYPELESS:
143                         case DXGI_FORMAT_R32G32_FLOAT:
144                         case DXGI_FORMAT_R32G32_UINT:
145                         case DXGI_FORMAT_R32G32_SINT:
146                         case DXGI_FORMAT_R32G8X24_TYPELESS:
147                         case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
148                         case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
149                         case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
150                                 return 64;
151                         
152                         case DXGI_FORMAT_R10G10B10A2_TYPELESS:
153                         case DXGI_FORMAT_R10G10B10A2_UNORM:
154                         case DXGI_FORMAT_R10G10B10A2_UINT:
155                         case DXGI_FORMAT_R11G11B10_FLOAT:
156                         case DXGI_FORMAT_R8G8B8A8_TYPELESS:
157                         case DXGI_FORMAT_R8G8B8A8_UNORM:
158                         case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
159                         case DXGI_FORMAT_R8G8B8A8_UINT:
160                         case DXGI_FORMAT_R8G8B8A8_SNORM:
161                         case DXGI_FORMAT_R8G8B8A8_SINT:
162                         case DXGI_FORMAT_R16G16_TYPELESS:
163                         case DXGI_FORMAT_R16G16_FLOAT:
164                         case DXGI_FORMAT_R16G16_UNORM:
165                         case DXGI_FORMAT_R16G16_UINT:
166                         case DXGI_FORMAT_R16G16_SNORM:
167                         case DXGI_FORMAT_R16G16_SINT:
168                         case DXGI_FORMAT_R32_TYPELESS:
169                         case DXGI_FORMAT_D32_FLOAT:
170                         case DXGI_FORMAT_R32_FLOAT:
171                         case DXGI_FORMAT_R32_UINT:
172                         case DXGI_FORMAT_R32_SINT:
173                         case DXGI_FORMAT_R24G8_TYPELESS:
174                         case DXGI_FORMAT_D24_UNORM_S8_UINT:
175                         case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
176                         case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
177                         case DXGI_FORMAT_B8G8R8A8_UNORM:
178                         case DXGI_FORMAT_B8G8R8X8_UNORM:
179                                 return 32;
180                                 
181                         case DXGI_FORMAT_R8G8_TYPELESS:
182                         case DXGI_FORMAT_R8G8_UNORM:
183                         case DXGI_FORMAT_R8G8_UINT:
184                         case DXGI_FORMAT_R8G8_SNORM:
185                         case DXGI_FORMAT_R8G8_SINT:
186                         case DXGI_FORMAT_R16_TYPELESS:
187                         case DXGI_FORMAT_R16_FLOAT:
188                         case DXGI_FORMAT_D16_UNORM:
189                         case DXGI_FORMAT_R16_UNORM:
190                         case DXGI_FORMAT_R16_UINT:
191                         case DXGI_FORMAT_R16_SNORM:
192                         case DXGI_FORMAT_R16_SINT:
193                         case DXGI_FORMAT_B5G6R5_UNORM:
194                         case DXGI_FORMAT_B5G5R5A1_UNORM:
195                                 return 16;
196                                 
197                         case DXGI_FORMAT_R8_TYPELESS:
198                         case DXGI_FORMAT_R8_UNORM:
199                         case DXGI_FORMAT_R8_UINT:
200                         case DXGI_FORMAT_R8_SNORM:
201                         case DXGI_FORMAT_R8_SINT:
202                         case DXGI_FORMAT_A8_UNORM:
203                                 return 8;
204                         
205                         // Compressed format; http://msdn2.microsoft.com/en-us/library/bb694531(VS.85).aspx
206                         case DXGI_FORMAT_BC2_TYPELESS:
207                         case DXGI_FORMAT_BC2_UNORM:
208                         case DXGI_FORMAT_BC2_UNORM_SRGB:
209                         case DXGI_FORMAT_BC3_TYPELESS:
210                         case DXGI_FORMAT_BC3_UNORM:
211                         case DXGI_FORMAT_BC3_UNORM_SRGB:
212                         case DXGI_FORMAT_BC5_TYPELESS:
213                         case DXGI_FORMAT_BC5_UNORM:
214                         case DXGI_FORMAT_BC5_SNORM:
215                                 return 128;
216                                 
217                         // Compressed format; http://msdn2.microsoft.com/en-us/library/bb694531(VS.85).aspx
218                         case DXGI_FORMAT_R1_UNORM:
219                         case DXGI_FORMAT_BC1_TYPELESS:
220                         case DXGI_FORMAT_BC1_UNORM:
221                         case DXGI_FORMAT_BC1_UNORM_SRGB:
222                         case DXGI_FORMAT_BC4_TYPELESS:
223                         case DXGI_FORMAT_BC4_UNORM:
224                         case DXGI_FORMAT_BC4_SNORM:
225                                 return 64;
226                         
227                         // Compressed format; http://msdn2.microsoft.com/en-us/library/bb694531(VS.85).aspx
228                         case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
229                                 return 32;
230                         
231                         // These are compressed, but bit-size information is unclear.
232                         case DXGI_FORMAT_R8G8_B8G8_UNORM:
233                         case DXGI_FORMAT_G8R8_G8B8_UNORM:
234                                 return 32;
235
236                         case DXGI_FORMAT_UNKNOWN:
237                         default:
238                                 throw gcnew InvalidOperationException( "Cannot determine format element size; invalid format specified." );
239                 }
240         }
241         
242         Drawing::Rectangle Utilities::ConvertRect(RECT rect)
243         {
244                 return Drawing::Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
245         }
246
247         void Utilities::ConvertRect(System::Drawing::Rectangle& source, RECT& dest)
248         {
249                 dest.top = source.Top;
250                 dest.bottom = source.Bottom;
251                 dest.left = source.Left;
252                 dest.right = source.Right;
253         }
254
255         array<Byte>^ Utilities::ReadStream( Stream^ stream, DataStream^* dataStream )
256         {
257                 int length = 0;
258
259                 return ReadStream( stream, length, dataStream );
260         }
261
262         array<Byte>^ Utilities::ReadStream( Stream^ stream, int% readLength, DataStream^* dataStream )
263         {
264                 if( stream == nullptr )
265                         throw gcnew ArgumentNullException( "stream" );
266                 if( !stream->CanRead )
267                         throw gcnew NotSupportedException();
268
269                 if( readLength > stream->Length - stream->Position )
270                         throw gcnew ArgumentOutOfRangeException( "readLength" );
271                 if( readLength == 0 )
272                         readLength = static_cast<int>( stream->Length - stream->Position );
273                 if( readLength < 0 )
274                         throw gcnew ArgumentOutOfRangeException( "readLength" );
275                 if( readLength == 0 )
276                         return gcnew array<Byte>( 0 );
277
278                 //if we're reading a DataStream, don't return anything and send back the casted DataStream
279                 DataStream^ ds = dynamic_cast<DataStream^>( stream );
280                 if( ds != nullptr && dataStream != NULL )
281                 {
282                         *dataStream = ds;
283                         return nullptr;
284                 }
285
286                 //It turns out this can fail because MemoryStream keeps an exposable parameter, and defaults it to
287                 //false, so that most of the time, MemoryStream->GetBuffer() can't be used. We might use reflection
288                 //to pull the internal array directly. Until then, MemoryStream can literally GO FUCK ITS OWN INTERFACE.
289                 /*//if we're reading an entire memory stream from beginning to end, just return the internal buffer
290                 MemoryStream^ ms = dynamic_cast<MemoryStream^>( stream );
291                 if( ms != nullptr && stream->Position == 0 && readLength == stream->Length )
292                 {
293                         return ms->GetBuffer();
294                 }*/
295
296                 WaveStream^ ws = dynamic_cast<WaveStream^>( stream );
297                 if( ws != nullptr && dataStream != NULL && ws->InternalMemory != nullptr )
298                 {
299                         *dataStream = ws->InternalMemory;
300                         return nullptr;
301                 }
302
303                 array<Byte>^ buffer = gcnew array<Byte>( readLength ); 
304                 int bytesRead = 0;
305                 while( bytesRead < readLength )
306                         bytesRead += stream->Read( buffer, bytesRead, readLength - bytesRead );
307
308                 return buffer;
309         }
310         
311         void Utilities::CheckArrayBounds( Array^ data, int offset, int% count )
312         {
313                 if( data == nullptr )
314                         throw gcnew ArgumentNullException( "data" );
315
316                 CheckBounds( 0, data->Length, offset, count );
317         }
318         
319         void Utilities::CheckBounds( int lowerBound, int size, int offset, int% count )
320         {
321                 if( offset < lowerBound )
322                         throw gcnew ArgumentOutOfRangeException( "offset" );
323                 if( count < 0 )
324                         throw gcnew ArgumentOutOfRangeException( "count" );
325                 if( offset + count > size )
326                         throw gcnew ArgumentException( "The sum of offset and count is greater than the buffer length." );
327                         
328                 if( count == 0 )
329                         count = size - offset;
330         }
331         
332         generic<typename T>
333         bool Utilities::CheckElementEquality( array<T>^ left, array<T>^ right )
334         {
335                 if( left->Length != right->Length )
336                         return false;
337                 
338                 for( int index = 0; index < left->Length; ++index )
339                 {
340                         if( !left[index]->Equals( right[index] ) ) 
341                         {
342                                 return false;
343                         }
344                 }
345                 
346                 return true;
347         }
348         
349         generic<typename T>
350         bool Utilities::CheckElementEquality( IList<T>^ left, IList<T>^ right )
351         {
352                 if( left->Count != right->Count )
353                         return false;
354                 
355                 for( int index = 0; index < left->Count; ++index )
356                 {
357                         if( !left[index]->Equals( right[index] ) ) 
358                         {
359                                 return false;
360                         }
361                 }
362                 
363                 return true;
364         }
365         
366         String^ Utilities::BufferToString( ID3DXBuffer *buffer )
367         {
368                 if( buffer != NULL )
369                 {
370                         String^ string = gcnew String( reinterpret_cast<const char*>( buffer->GetBufferPointer() ) );
371                         buffer->Release();
372                         return string;
373                 }
374                 else
375                 {
376                         return String::Empty;
377                 }
378         }
379
380         String^ Utilities::BlobToString( ID3D10Blob *blob )
381         {
382                 if( blob != NULL )
383                 {
384                         String^ string = gcnew String( reinterpret_cast<const char*>( blob->GetBufferPointer() ) );
385                         blob->Release();
386                         return string; 
387                 }
388                 else
389                         return String::Empty;
390         }
391
392         void Utilities::FreeNativeString( LPCSTR string )
393         {
394                 if( string == NULL )
395                         return;
396
397                 System::Runtime::InteropServices::Marshal::FreeHGlobal( IntPtr( const_cast<void*>( reinterpret_cast<const void*>( string ) ) ) );
398         }
399
400         void Utilities::FreeNativeString( LPSTR string )
401         {
402                 if( string == NULL )
403                         return;
404
405                 System::Runtime::InteropServices::Marshal::FreeHGlobal( IntPtr( reinterpret_cast<void*>( string ) ) );
406         }
407
408         LPSTR Utilities::AllocateNativeString( String^ value )
409         {
410                 if( value == nullptr || String::IsNullOrEmpty( value ) )
411                         return NULL;
412                 else
413                         return reinterpret_cast<LPSTR>( System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi( value ).ToPointer() );
414         }
415
416         generic<typename T>
417         T Utilities::FromIntToT( int value )
418         {
419                 if( T::typeid->IsEnum )
420                         return safe_cast<T>( static_cast<int>( value ) );
421                 else if( T::typeid == float::typeid )
422                         return safe_cast<T>( *reinterpret_cast<float*>( &value ) );
423                 else
424                         return safe_cast<T>( Convert::ChangeType( static_cast<int>( value ), T::typeid, CultureInfo::InvariantCulture ) );
425         }
426 }