/// <summary> /// Function to enumerate raw input devices. /// </summary> /// <returns>An array of raw input device structures.</returns> public unsafe static RAWINPUTDEVICELIST[] EnumerateInputDevices() { int deviceCount = 0; int structSize = DirectAccess.SizeOf <RAWINPUTDEVICELIST>(); if (GetRawInputDeviceList(IntPtr.Zero, ref deviceCount, structSize) < 0) { throw new Win32Exception(); } if (deviceCount == 0) { return(new RAWINPUTDEVICELIST[0]); } RAWINPUTDEVICELIST *deviceListPtr = stackalloc RAWINPUTDEVICELIST[deviceCount]; if (GetRawInputDeviceList((IntPtr)deviceListPtr, ref deviceCount, structSize) < 0) { throw new Win32Exception(); } var result = new RAWINPUTDEVICELIST[deviceCount]; fixed(RAWINPUTDEVICELIST *resultPtr = &result[0]) { DirectAccess.MemoryCopy(resultPtr, deviceListPtr, structSize * deviceCount); } return(result); }
/// <summary> /// Function to retrieve device information. /// </summary> /// <param name="deviceHandle">Device handle.</param> /// <returns>The device information structure.</returns> public static unsafe RID_DEVICE_INFO GetDeviceInfo(IntPtr deviceHandle) { int dataSize = DirectAccess.SizeOf <RID_DEVICE_INFO>(); byte *data = stackalloc byte[dataSize]; if (GetRawInputDeviceInfo(deviceHandle, RawInputCommand.DeviceInfo, (IntPtr)data, ref dataSize) < 0) { throw new Win32Exception(); } RID_DEVICE_INFO result; DirectAccess.MemoryCopy(&result, data, dataSize); return(result); }
private readonly int _headerSize = DirectAccess.SizeOf <RAWINPUTHEADER>(); // Size of the input data in bytes. #endregion #region IMessageFilter Members /// <summary> /// Filters out a message before it is dispatched. /// </summary> /// <param name="m">The message to be dispatched. You cannot modify this message.</param> /// <returns> /// true to filter the message and stop it from being dispatched; false to allow the message to continue to the next filter or control. /// </returns> public unsafe bool PreFilterMessage(ref Message m) { int dataSize = 0; // Get data size. int result = Win32API.GetRawInputData(m.LParam, RawInputCommand.Input, IntPtr.Zero, ref dataSize, _headerSize); if (result == -1) { throw new GorgonException(GorgonResult.CannotRead, Resources.GORINP_RAW_CANNOT_READ_DATA); } // Get actual data. var rawInputPtr = stackalloc byte[dataSize]; result = Win32API.GetRawInputData(m.LParam, RawInputCommand.Input, (IntPtr)rawInputPtr, ref dataSize, _headerSize); if ((result == -1) || (result != dataSize)) { throw new GorgonException(GorgonResult.CannotRead, Resources.GORINP_RAW_CANNOT_READ_DATA); } var rawInput = *((RAWINPUT *)rawInputPtr); switch (rawInput.Header.Type) { case RawInputType.Mouse: if (RawInputPointingDeviceData != null) { RawInputPointingDeviceData(this, new RawInputPointingDeviceEventArgs(rawInput.Header.Device, ref rawInput.Union.Mouse)); } break; case RawInputType.Keyboard: if (RawInputKeyboardData != null) { RawInputKeyboardData(this, new RawInputKeyboardEventArgs(rawInput.Header.Device, ref rawInput.Union.Keyboard)); } break; default: if (RawInputHIDData != null) { var HIDData = new byte[rawInput.Union.HID.Size * rawInput.Union.HID.Count]; var hidDataPtr = rawInputPtr + _headerSize + 8; fixed(byte *buffer = &HIDData[0]) { DirectAccess.MemoryCopy(buffer, hidDataPtr, HIDData.Length); } RawInputHIDData(this, new RawInputHIDEventArgs(rawInput.Header.Device, ref rawInput.Union.HID, HIDData)); } break; } return(false); }
/// <summary> /// Function to copy (or update in-place) a line with opaque alpha substituion (if required). /// </summary> /// <param name="src">The pointer to the source data.</param> /// <param name="srcPitch">The pitch of the source data.</param> /// <param name="dest">The pointer to the destination data.</param> /// <param name="destPitch">The pitch of the destination data.</param> /// <param name="format">Format of the destination buffer.</param> /// <param name="bitFlags">Image bit conversion control flags.</param> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="format"/> parameter is Unknown.</exception> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="src"/> or the <paramref name="dest"/> parameter is NULL.</exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="srcPitch"/> or the <paramref name="destPitch"/> parameter is less than 0.</exception> /// <remarks>Use this method to copy a single scanline of an image and (optionally) set an opaque constant alpha value.</remarks> protected unsafe void CopyScanline(void *src, int srcPitch, void *dest, int destPitch, BufferFormat format, ImageBitFlags bitFlags) { if (src == null) { throw new ArgumentNullException("src"); } if (dest == null) { throw new ArgumentNullException("dest"); } if (format == BufferFormat.Unknown) { throw new ArgumentException(string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, BufferFormat.Unknown), "format"); } int size = (src == dest) ? destPitch : (srcPitch.Min(destPitch)); if ((bitFlags & ImageBitFlags.OpaqueAlpha) == ImageBitFlags.OpaqueAlpha) { // Do a straight copy. switch (format) { case BufferFormat.R32G32B32A32: case BufferFormat.R32G32B32A32_Float: case BufferFormat.R32G32B32A32_UInt: case BufferFormat.R32G32B32A32_Int: { uint alpha = (format == BufferFormat.R32G32B32_Float) ? 0x3F800000 : ((format == BufferFormat.R32G32B32_Int) ? 0x7FFFFFFF : 0xFFFFFFFF); var srcPtr = (uint *)src; var destPtr = (uint *)dest; for (int i = 0; i < size; i += 16) { // If not in-place copy, then copy from the source. if (src != dest) { *destPtr = *srcPtr; srcPtr += 4; } *destPtr += 3; *(destPtr++) = alpha; } } return; case BufferFormat.R16G16B16A16: case BufferFormat.R16G16B16A16_Float: case BufferFormat.R16G16B16A16_UIntNormal: case BufferFormat.R16G16B16A16_UInt: case BufferFormat.R16G16B16A16_IntNormal: case BufferFormat.R16G16B16A16_Int: { ushort alpha = 0xFFFF; switch (format) { case BufferFormat.R16G16B16A16_Float: alpha = 0x3C00; break; case BufferFormat.R16G16B16A16_Int: case BufferFormat.R16G16B16A16_IntNormal: alpha = 0x7FFF; break; } var srcPtr = (ushort *)src; var destPtr = (ushort *)dest; for (int i = 0; i < size; i += 8) { // If not in-place copy, then copy from the source. if (src != dest) { *destPtr = *srcPtr; srcPtr += 4; } *destPtr += 3; *(destPtr++) = alpha; } } return; case BufferFormat.R10G10B10A2: case BufferFormat.R10G10B10A2_UIntNormal: case BufferFormat.R10G10B10A2_UInt: case BufferFormat.R10G10B10_XR_BIAS_A2_UIntNormal: { var srcPtr = (uint *)src; var destPtr = (uint *)dest; for (int i = 0; i < size; i += 4) { // If not in-place copy, then copy from the source. if (src != dest) { *destPtr = (*srcPtr) & 0x3FFFFFFF; srcPtr++; } *destPtr |= 0xC0000000; destPtr++; } } return; case BufferFormat.R8G8B8A8: case BufferFormat.R8G8B8A8_UIntNormal: case BufferFormat.R8G8B8A8_UIntNormal_sRGB: case BufferFormat.R8G8B8A8_UInt: case BufferFormat.R8G8B8A8_IntNormal: case BufferFormat.R8G8B8A8_Int: case BufferFormat.B8G8R8A8_UIntNormal: case BufferFormat.B8G8R8A8: case BufferFormat.B8G8R8A8_UIntNormal_sRGB: { uint alpha = ((format == BufferFormat.R8G8B8A8_Int) || (format == BufferFormat.R8G8B8A8_IntNormal)) ? 0x7F000000 : 0xFF000000; var srcPtr = (uint *)src; var destPtr = (uint *)dest; for (int i = 0; i < size; i += 4) { // If not in-place copy, then copy from the source. if (src != dest) { *destPtr = (*srcPtr) & 0xFFFFFF; srcPtr++; } *destPtr |= alpha; destPtr++; } } return; case BufferFormat.B5G5R5A1_UIntNormal: { var srcPtr = (ushort *)src; var destPtr = (ushort *)dest; for (int i = 0; i < size; i += 2) { // If not in-place copy, then copy from the source. if (src != dest) { *(destPtr++) = (ushort)((*srcPtr++) | 0x8000); } else { *(destPtr++) |= 0x8000; } } } return; case BufferFormat.A8_UIntNormal: DirectAccess.FillMemory(dest, 0xFF, size); return; } } // Copy if not doing an in-place update. if (dest != src) { DirectAccess.MemoryCopy(dest, src, size); } }
/// <summary> /// Function to copy (or update in-place) with bits swizzled to match another format. /// </summary> /// <param name="src">The pointer to the source data.</param> /// <param name="srcPitch">The pitch of the source data.</param> /// <param name="dest">The pointer to the destination data.</param> /// <param name="destPitch">The pitch of the destination data.</param> /// <param name="format">Format of the destination buffer.</param> /// <param name="bitFlags">Image bit conversion control flags.</param> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="format"/> parameter is Unknown.</exception> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="src"/> or the <paramref name="dest"/> parameter is NULL.</exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="srcPitch"/> or the <paramref name="destPitch"/> parameter is less than 0.</exception> /// <remarks>Use this method to copy a single scanline and swizzle the bits of an image and (optionally) set an opaque constant alpha value.</remarks> protected unsafe void SwizzleScanline(void *src, int srcPitch, void *dest, int destPitch, BufferFormat format, ImageBitFlags bitFlags) { int size = srcPitch.Min(destPitch); uint r, g, b, a, pixel; if (src == null) { throw new ArgumentNullException("src"); } if (dest == null) { throw new ArgumentNullException("dest"); } if (format == BufferFormat.Unknown) { throw new ArgumentException(string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, BufferFormat.Unknown), "format"); } var srcPtr = (uint *)src; var destPtr = (uint *)dest; switch (format) { case BufferFormat.R10G10B10A2: case BufferFormat.R10G10B10A2_UInt: case BufferFormat.R10G10B10A2_UIntNormal: case BufferFormat.R10G10B10_XR_BIAS_A2_UIntNormal: for (int i = 0; i < size; i += 4) { if (src != dest) { pixel = *(srcPtr++); } else { pixel = *(destPtr); } r = ((pixel & 0x3FF00000) >> 20); g = (pixel & 0x000FFC00); b = ((pixel & 0x000003FF) << 20); a = ((bitFlags & ImageBitFlags.OpaqueAlpha) == ImageBitFlags.OpaqueAlpha) ? 0xC0000000 : pixel & 0xC0000000; *destPtr = r | g | b | a; destPtr++; } return; case BufferFormat.R8G8B8A8: case BufferFormat.R8G8B8A8_UIntNormal: case BufferFormat.R8G8B8A8_UIntNormal_sRGB: case BufferFormat.B8G8R8A8_UIntNormal: case BufferFormat.B8G8R8X8_UIntNormal: case BufferFormat.B8G8R8A8: case BufferFormat.B8G8R8A8_UIntNormal_sRGB: case BufferFormat.B8G8R8X8: case BufferFormat.B8G8R8X8_UIntNormal_sRGB: for (int i = 0; i < size; i += 4) { if (src != dest) { pixel = *(srcPtr++); } else { pixel = *(destPtr); } r = ((pixel & 0xFF0000) >> 16); g = (pixel & 0x00FF00); b = ((pixel & 0x0000FF) << 16); a = ((bitFlags & ImageBitFlags.OpaqueAlpha) == ImageBitFlags.OpaqueAlpha) ? 0xFF000000 : pixel & 0xFF000000; *destPtr = r | g | b | a; destPtr++; } return; } if (src != dest) { DirectAccess.MemoryCopy(dest, src, size); } }
/// <summary> /// Function to copy the memory contents from this pointer to another. /// </summary> /// <param name="destination">Destination buffer.</param> /// <param name="source">Source buffer.</param> /// <param name="size">Size of the data to copy, in bytes.</param> /// <remarks>Since a pointer doesn't have a size associated with it, care must be taken to not overstep the bounds of the data pointed at by the pointer.</remarks> /// <exception cref="System.ArgumentNullException">Thrown when the destination pointer is NULL (Nothing in VB.Net).</exception> public static void CopyTo(this IntPtr source, IntPtr destination, int size) { DirectAccess.MemoryCopy(destination, source, size); }
/// <summary> /// Function to copy the image buffer data from this buffer into another. /// </summary> /// <param name="buffer">The buffer to copy into.</param> /// <param name="sourceRegion">[Optional] The region in the source to copy.</param> /// <param name="destX">[Optional] Horizontal offset in the destination buffer.</param> /// <param name="destY">[Optional] Vertical offset in the destination buffer.</param> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="buffer" /> parameter is NULL (Nothing in VB.Net).</exception> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="buffer" /> is not the same format as this buffer.</exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the source region does not fit within the bounds of this buffer.</exception> /// <remarks> /// This method will copy the contents of this buffer into another buffer and will provide clipping to handle cases where the buffer or <paramref name="sourceRegion" /> is mismatched with the /// destination size. /// <para>Users may define an area on this buffer to copy by specifying the <paramref name="sourceRegion" /> parameter. If NULL (Nothing in VB.Net) is passed to this parameter, then the /// entire buffer will be copied to the destination.</para><para>An offset into the destination buffer may also be specified to relocate the data copied from this buffer into the destination. Clipping will be applied if the offset pushes the /// source data outside of the boundaries of the destination buffer.</para><para>The destination buffer must be the same format as the source buffer. If it is not, then an exception will be thrown.</para> /// <para>The <paramref name="buffer"/> parameter must not be the same as the this buffer. An exception will be thrown if an attempt to copy this buffer into itself is made.</para> /// <para>If the source region does not fit within the bounds of this buffer, then an exception will be thrown.</para> /// </remarks> public unsafe void CopyTo(GorgonImageBuffer buffer, Rectangle?sourceRegion = null, int destX = 0, int destY = 0) { var sourceBufferDims = new Rectangle(0, 0, Width, Height); Rectangle srcRegion = sourceRegion != null ? sourceRegion.Value : sourceBufferDims; if ((buffer == null) || (buffer.Data == null) || (buffer.Data.Length == 0)) { throw new ArgumentNullException("buffer"); } if ((buffer == this) || (buffer.Data.UnsafePointer == Data.UnsafePointer)) { throw new ArgumentException(Resources.GORGFX_IMAGE_BUFFER_CANT_BE_SAME, "buffer"); } if (buffer.Format != Format) { throw new ArgumentException(Resources.GORGFX_IMAGE_MUST_BE_SAME_FORMAT, "buffer"); } if (!sourceBufferDims.Contains(srcRegion)) { throw new ArgumentOutOfRangeException("sourceRegion"); } // If we try to place this image outside of the target buffer, then do nothing. if ((destX >= buffer.Width) || (destY >= buffer.Height)) { return; } // Adjust in case we're trying to move off the target. if (destX < 0) { srcRegion.X -= destX; srcRegion.Width += destX; destX = 0; } if (destY < 0) { srcRegion.Y -= destY; srcRegion.Height += destY; destY = 0; } // Ensure that the regions actually fit within their respective buffers. srcRegion = Rectangle.FromLTRB(srcRegion.X.Max(0), srcRegion.Y.Max(0), srcRegion.Right.Min(Width), srcRegion.Bottom.Min(Height)); Rectangle dstRegion = Rectangle.FromLTRB(destX, destY, (destX + buffer.Width).Min(buffer.Width), (destY + buffer.Height).Min(buffer.Height)); // If the source/dest region is empty, then we have nothing to copy. if ((srcRegion.IsEmpty) || (dstRegion.IsEmpty) || (dstRegion.Right < 0) || (dstRegion.Bottom < 0)) { return; } // If the buffers are identical in dimensions and have no offset, then just do a straight copy. if (srcRegion == dstRegion) { DirectAccess.MemoryCopy(buffer.Data.UnsafePointer, Data.UnsafePointer, (int)Data.Length); return; } // Find out how many bytes each pixel occupies. int dataSize = PitchInformation.RowPitch / Width; int srcLineSize = dataSize * srcRegion.Width; // Number of source bytes/scanline. var srcData = ((byte *)Data.UnsafePointer) + (srcRegion.Y * PitchInformation.RowPitch) + (srcRegion.X * dataSize); int dstLineSize = dataSize * dstRegion.Width; // Number of dest bytes/scanline. var dstData = ((byte *)buffer.Data.UnsafePointer) + (dstRegion.Y * buffer.PitchInformation.RowPitch) + (dstRegion.X * dataSize); // Get the smallest line size. int minLineSize = dstLineSize.Min(srcLineSize); int minHeight = dstRegion.Height.Min(srcRegion.Height); // Finally, copy our data. for (int i = 0; i < minHeight; ++i) { DirectAccess.MemoryCopy(dstData, srcData, minLineSize); srcData += PitchInformation.RowPitch; dstData += buffer.PitchInformation.RowPitch; } }