Ian Burgmyer
7 years ago
12 changed files with 479 additions and 35 deletions
@ -0,0 +1,16 @@
|
||||
namespace DotSDL.Graphics { |
||||
/// <summary> |
||||
/// Represents a point in 2D space. |
||||
/// </summary> |
||||
public class Point { |
||||
/// <summary> |
||||
/// The X coordinate of the point. |
||||
/// </summary> |
||||
public int X { get; set; } |
||||
|
||||
/// <summary> |
||||
/// The Y coordinate of the point. |
||||
/// </summary> |
||||
public int Y { get; set; } |
||||
} |
||||
} |
@ -0,0 +1,84 @@
|
||||
using System; |
||||
using DotSDL.Sdl; |
||||
|
||||
namespace DotSDL.Graphics { |
||||
/// <summary> |
||||
/// Represents an SDL window. TODO: Support other pixel formats. |
||||
/// </summary> |
||||
public class SdlWindow { |
||||
private readonly IntPtr _window; |
||||
private readonly IntPtr _renderer; |
||||
private readonly IntPtr _texture; |
||||
|
||||
private bool _running; |
||||
|
||||
/// <summary>Indicates that the window manager should position the window.</summary> |
||||
public const int WindowPosUndefined = 0x1FFF0000; |
||||
public static int WindowPosUndefinedDisplay(uint x) { |
||||
return (int)(WindowPosUndefined | x); |
||||
} |
||||
|
||||
/// <summary>Indicates that the window should be in the center of the screen.</summary> |
||||
public const int WindowPosCentered = 0x2FFF0000; |
||||
internal static int WindowPosCenteredDisplay(uint x) { |
||||
return (int)(WindowPosCentered | x); |
||||
} |
||||
|
||||
public SdlWindow(string name, Point position, int width, int height) { |
||||
_window = Video.CreateWindow(name, position.X, position.Y, width, height, Video.WindowFlags.Hidden); |
||||
_renderer = Render.CreateRenderer(_window, -1, Render.RendererFlags.Accelerated); |
||||
_texture = Render.CreateTexture(_renderer, Pixels.PixelFormatArgb8888, Render.TextureAccess.Streaming, width, height); |
||||
} |
||||
|
||||
private void BaseDraw() { |
||||
Render.LockTexture(_texture, IntPtr.Zero, out var pixels, out var pitch); |
||||
Console.WriteLine(pitch.ToString()); |
||||
OnDraw(); // Call the overridden Draw function. |
||||
Render.UnlockTexture(_texture); |
||||
|
||||
Render.RenderCopy(_renderer, _texture, IntPtr.Zero, IntPtr.Zero); |
||||
Render.RenderPresent(_renderer); |
||||
} |
||||
|
||||
private void BaseLoad() { |
||||
OnLoad(); // Call the overridden Load function. |
||||
} |
||||
|
||||
private void BaseUpdate() { |
||||
OnUpdate(); // Call the overridden Update function. |
||||
} |
||||
|
||||
private void Loop() { |
||||
_running = true; |
||||
|
||||
while(_running) { |
||||
BaseDraw(); |
||||
BaseUpdate(); |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Fired every time the window is drawn to. |
||||
/// </summary> |
||||
public virtual void OnDraw() {} |
||||
|
||||
/// <summary> |
||||
/// Fired before the window is shown. |
||||
/// </summary> |
||||
public virtual void OnLoad() {} |
||||
|
||||
/// <summary> |
||||
/// Fired every time the application logic update runs. |
||||
/// </summary> |
||||
public virtual void OnUpdate() {} |
||||
|
||||
/// <summary> |
||||
/// Displays the window and begins executing code that's associated with it. |
||||
/// </summary> |
||||
public void Start() { |
||||
BaseLoad(); |
||||
Video.ShowWindow(_window); |
||||
Loop(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,99 @@
|
||||
using System.Diagnostics.CodeAnalysis; |
||||
|
||||
namespace DotSDL.Sdl |
||||
{ |
||||
/// <summary> |
||||
/// Contains the necessary constants and function imports from SDL_pixels.h. |
||||
/// </summary> |
||||
internal static class Pixels { |
||||
internal enum PixelTypes { |
||||
Unknown, |
||||
Index1, |
||||
Index4, |
||||
Index8, |
||||
Packed8, |
||||
Packed16, |
||||
Packed32, |
||||
ArrayU8, |
||||
ArrayU16, |
||||
ArrayU32, |
||||
ArrayF16, |
||||
ArrayF32 |
||||
} |
||||
|
||||
internal enum ComponentOrder { |
||||
None = 0x00, |
||||
|
||||
// Bitmap pixel order. |
||||
Bitmap4321 = 0x01, |
||||
Bitmap1234 = 0x02, |
||||
|
||||
// Packed component order. |
||||
PackedXrgb = 0x01, |
||||
PackedRgbx = 0x02, |
||||
PackedArgb = 0x03, |
||||
PackedRgba = 0x04, |
||||
PackedXbgr = 0x05, |
||||
PackedBgrx = 0x06, |
||||
PackedAbgr = 0x07, |
||||
PackedBgra = 0x08, |
||||
|
||||
// Array component order. |
||||
ArrayRgb = 0x01, |
||||
ArrayRgba = 0x02, |
||||
ArrayArgb = 0x03, |
||||
ArrayBgr = 0x04, |
||||
ArrayBgra = 0x05, |
||||
ArrayAbgr = 0x06 |
||||
} |
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")] |
||||
internal enum PackedComponentLayout { |
||||
LayoutNone, |
||||
Layout332, |
||||
Layout4444, |
||||
Layout1555, |
||||
Layout5551, |
||||
Layout565, |
||||
Layout8888, |
||||
Layout2101010, |
||||
Layout1010102 |
||||
} |
||||
|
||||
internal static uint DefinePixelFormat(PixelTypes type, ComponentOrder order, PackedComponentLayout layout, byte bits, byte bytes) { |
||||
return (uint)((1 << 28) | ((int)type << 24) | ((int)order << 20) | ((int)layout << 16) | (bits << 8) | bytes); |
||||
} |
||||
|
||||
// Pixel formats cannot be easily expressed in an enum, so we'll make them consts instead. |
||||
internal static readonly uint PixelFormatIndex1Lsb = DefinePixelFormat(PixelTypes.Index1, ComponentOrder.Bitmap4321, PackedComponentLayout.LayoutNone, 1, 0); |
||||
internal static readonly uint PixelFormatIndex1Msb = DefinePixelFormat(PixelTypes.Index1, ComponentOrder.Bitmap1234, PackedComponentLayout.LayoutNone, 1, 0); |
||||
internal static readonly uint PixelFormatIndex4Lsb = DefinePixelFormat(PixelTypes.Index4, ComponentOrder.Bitmap4321, PackedComponentLayout.LayoutNone, 4, 0); |
||||
internal static readonly uint PixelFormatIndex4Msb = DefinePixelFormat(PixelTypes.Index4, ComponentOrder.Bitmap1234, PackedComponentLayout.LayoutNone, 4, 0); |
||||
internal static readonly uint PixelFormatIndex8 = DefinePixelFormat(PixelTypes.Index8, ComponentOrder.None, PackedComponentLayout.LayoutNone, 8, 1); |
||||
internal static readonly uint PixelFormatRgb332 = DefinePixelFormat(PixelTypes.Packed8, ComponentOrder.PackedXrgb, PackedComponentLayout.Layout332, 8, 1); |
||||
internal static readonly uint PixelFormatRgb444 = DefinePixelFormat(PixelTypes.Packed16, ComponentOrder.PackedXrgb, PackedComponentLayout.Layout4444, 12, 2); |
||||
internal static readonly uint PixelFormatRgb555 = DefinePixelFormat(PixelTypes.Packed16, ComponentOrder.PackedXrgb, PackedComponentLayout.Layout1555, 15, 2); |
||||
internal static readonly uint PixelFormatBgr555 = DefinePixelFormat(PixelTypes.Packed16, ComponentOrder.PackedXbgr, PackedComponentLayout.Layout1555, 15, 2); |
||||
internal static readonly uint PixelFormatArgb4444 = DefinePixelFormat(PixelTypes.Packed16, ComponentOrder.PackedArgb, PackedComponentLayout.Layout4444, 16, 2); |
||||
internal static readonly uint PixelFormatRgba4444 = DefinePixelFormat(PixelTypes.Packed16, ComponentOrder.PackedRgba, PackedComponentLayout.Layout4444, 16, 2); |
||||
internal static readonly uint PixelFormatAbgr4444 = DefinePixelFormat(PixelTypes.Packed16, ComponentOrder.PackedAbgr, PackedComponentLayout.Layout4444, 16, 2); |
||||
internal static readonly uint PixelFormatBgra4444 = DefinePixelFormat(PixelTypes.Packed16, ComponentOrder.PackedBgra, PackedComponentLayout.Layout4444, 16, 2); |
||||
internal static readonly uint PixelFormatArgb1555 = DefinePixelFormat(PixelTypes.Packed16, ComponentOrder.PackedArgb, PackedComponentLayout.Layout1555, 16, 2); |
||||
internal static readonly uint PixelFormatRgba5551 = DefinePixelFormat(PixelTypes.Packed16, ComponentOrder.PackedRgba, PackedComponentLayout.Layout5551, 16, 2); |
||||
internal static readonly uint PixelFormatAbgr1555 = DefinePixelFormat(PixelTypes.Packed16, ComponentOrder.PackedAbgr, PackedComponentLayout.Layout1555, 16, 2); |
||||
internal static readonly uint PixelFormatBgra5551 = DefinePixelFormat(PixelTypes.Packed16, ComponentOrder.PackedBgra, PackedComponentLayout.Layout5551, 16, 2); |
||||
internal static readonly uint PixelFormatRgb565 = DefinePixelFormat(PixelTypes.Packed16, ComponentOrder.PackedXrgb, PackedComponentLayout.Layout565, 16, 2); |
||||
internal static readonly uint PixelFormatBgr565 = DefinePixelFormat(PixelTypes.Packed16, ComponentOrder.PackedXbgr, PackedComponentLayout.Layout565, 16, 2); |
||||
internal static readonly uint PixelFormatRgb24 = DefinePixelFormat(PixelTypes.ArrayU8, ComponentOrder.ArrayRgb, PackedComponentLayout.LayoutNone, 24, 3); |
||||
internal static readonly uint PixelFormatBgr24 = DefinePixelFormat(PixelTypes.ArrayU8, ComponentOrder.ArrayBgr, PackedComponentLayout.LayoutNone, 24, 3); |
||||
internal static readonly uint PixelFormatRgb888 = DefinePixelFormat(PixelTypes.Packed32, ComponentOrder.PackedXrgb, PackedComponentLayout.Layout8888, 24, 4); |
||||
internal static readonly uint PixelFormatRgbx8888 = DefinePixelFormat(PixelTypes.Packed32, ComponentOrder.PackedRgbx, PackedComponentLayout.Layout8888, 24, 4); |
||||
internal static readonly uint PixelFormatBgr888 = DefinePixelFormat(PixelTypes.Packed32, ComponentOrder.PackedXbgr, PackedComponentLayout.Layout8888, 24, 4); |
||||
internal static readonly uint PixelFormatBgrx8888 = DefinePixelFormat(PixelTypes.Packed32, ComponentOrder.PackedBgrx, PackedComponentLayout.Layout8888, 24, 4); |
||||
internal static readonly uint PixelFormatArgb8888 = DefinePixelFormat(PixelTypes.Packed32, ComponentOrder.PackedArgb, PackedComponentLayout.Layout8888, 32, 4); |
||||
internal static readonly uint PixelFormatRgba8888 = DefinePixelFormat(PixelTypes.Packed32, ComponentOrder.PackedRgba, PackedComponentLayout.Layout8888, 32, 4); |
||||
internal static readonly uint PixelFormatAbgr8888 = DefinePixelFormat(PixelTypes.Packed32, ComponentOrder.PackedAbgr, PackedComponentLayout.Layout8888, 32, 4); |
||||
internal static readonly uint PixelFormatBgra8888 = DefinePixelFormat(PixelTypes.Packed32, ComponentOrder.PackedBgra, PackedComponentLayout.Layout8888, 32, 4); |
||||
internal static readonly uint PixelFormatArgb2101010 = DefinePixelFormat(PixelTypes.Packed32, ComponentOrder.ArrayArgb, PackedComponentLayout.Layout2101010, 32, 4); |
||||
} |
||||
} |
@ -0,0 +1,25 @@
|
||||
using System.Runtime.InteropServices; |
||||
|
||||
namespace DotSDL.Sdl { |
||||
/// <summary> |
||||
/// Contains the necessary constants and function imports from SDL_rect.h. |
||||
/// </summary> |
||||
internal class Rect { |
||||
/// <summary> |
||||
/// The structure that defines a point. |
||||
/// </summary> |
||||
[StructLayout(LayoutKind.Sequential)] |
||||
internal struct SdlPoint { |
||||
public int X, Y; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// A rectangle, with the origin at the upper left. |
||||
/// </summary> |
||||
[StructLayout(LayoutKind.Sequential)] |
||||
internal struct SdlRect { |
||||
public int X, Y; |
||||
public int W, H; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,116 @@
|
||||
using System; |
||||
using System.Runtime.InteropServices; |
||||
|
||||
namespace DotSDL.Sdl { |
||||
/// <summary> |
||||
/// Contains the necessary constants and function imports from SDL_render.h. |
||||
/// </summary> |
||||
internal static class Render { |
||||
/// <summary> |
||||
/// Flags used when creating a rendering context. |
||||
/// </summary> |
||||
[Flags] |
||||
internal enum RendererFlags : uint { |
||||
/// <summary>The renderer is a software fallback.</summary> |
||||
Software = 0x00000001, |
||||
|
||||
/// <summary>The renderer uses hardware acceleration.</summary> |
||||
Accelerated = 0x00000002, |
||||
|
||||
/// <summary>Present is synchronized with the refresh rate.</summary> |
||||
PresentVsync = 0x00000004, |
||||
|
||||
/// <summary>The renderer supports rendering to a texture.</summary> |
||||
TargetTexture = 0x00000008 |
||||
} |
||||
|
||||
/// <summary> |
||||
/// The access pattern allowed for a texture. |
||||
/// </summary> |
||||
internal enum TextureAccess : int { |
||||
/// <summary>Changes rarely, not lockable.</summary> |
||||
Static, |
||||
|
||||
/// <summary>Changes frequently, lockable.</summary> |
||||
Streaming, |
||||
|
||||
/// <summary>Texture can be used as a render target.</summary> |
||||
Target |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Create a 2D rendering context for a window. |
||||
/// </summary> |
||||
/// <param name="window">The window whwere rendering is displayed.</param> |
||||
/// <param name="index">The index of the rendering driver to initialize, or -1 |
||||
/// to initialize the first one supporting the requested flags.</param> |
||||
/// <param name="flags">The requested flags for the renderer.</param> |
||||
/// <returns>A valid rendering context or NULL if there was an error.</returns> |
||||
[DllImport(Meta.DllName, EntryPoint = "SDL_CreateRenderer", CallingConvention = CallingConvention.Cdecl)] |
||||
internal static extern IntPtr CreateRenderer(IntPtr window, int index, RendererFlags flags); |
||||
|
||||
/// <summary> |
||||
/// Create a texture for a rendering context. |
||||
/// </summary> |
||||
/// <param name="renderer">The renderer.</param> |
||||
/// <param name="format">The format of the texture.</param> |
||||
/// <param name="access">The access pattern for the new texture.</param> |
||||
/// <param name="w">The width of the texture in pixels.</param> |
||||
/// <param name="h">The height of the texture in pixels.</param> |
||||
/// <returns>The created texture is returned, or NULL if no rendering context was |
||||
/// active, the foramt was unsupported, or the width or height were out of range.</returns> |
||||
[DllImport(Meta.DllName, EntryPoint = "SDL_CreateTexture", CallingConvention = CallingConvention.Cdecl)] |
||||
internal static extern IntPtr CreateTexture(IntPtr renderer, uint format, TextureAccess access, int w, int h); |
||||
|
||||
/// <summary> |
||||
/// Lock a portion of the texture for write-only pixel access. |
||||
/// </summary> |
||||
/// <param name="texture">The texture to lock for access, which was created with <see cref="TextureAccess.Streaming"/>.</param> |
||||
/// <param name="rect">The rectangle to lock for access. If the rect is NULL, the entire texture will be locked.</param> |
||||
/// <param name="pixels">This is filled in with an <see cref="IntPtr"/> to the locked pixels, appropriately offset |
||||
/// by the locked area.</param> |
||||
/// <param name="pitch">This is filled in with the pitch of the locked pixels.</param> |
||||
/// <returns>0 on success, or -1 if the texture is not valid or was not created with <see cref="TextureAccess.Streaming"/>.</returns> |
||||
[DllImport(Meta.DllName, EntryPoint = "SDL_LockTexture", CallingConvention = CallingConvention.Cdecl)] |
||||
internal static extern int LockTexture(IntPtr texture, Rect.SdlRect rect, out IntPtr pixels, out int pitch); |
||||
[DllImport(Meta.DllName, EntryPoint = "SDL_LockTexture", CallingConvention = CallingConvention.Cdecl)] |
||||
internal static extern int LockTexture(IntPtr texture, IntPtr rect, out IntPtr pixels, out int pitch); |
||||
|
||||
/// <summary> |
||||
/// Clear the current rendering target with the drawing color. |
||||
/// |
||||
/// This function clears the entire rendering target, ignoring the viewport and the clip rectangle. |
||||
/// </summary> |
||||
/// <param name="renderer">The renderer to clear.</param> |
||||
/// <returns>0 on success, -1 on error.</returns> |
||||
[DllImport(Meta.DllName, EntryPoint = "SDL_RenderClear", CallingConvention = CallingConvention.Cdecl)] |
||||
internal static extern int RenderClear(IntPtr renderer); |
||||
|
||||
/// <summary> |
||||
/// Copy a portion of the texture to the current rendering target. |
||||
/// </summary> |
||||
/// <param name="renderer">The renderer which should copy parts of a texture.</param> |
||||
/// <param name="texture">The source texture.</param> |
||||
/// <param name="srcRect">The source rectangle, or NULL for the entire texture.</param> |
||||
/// <param name="dstRect">The destination rectangle, or NULL For the entire rendering target.</param> |
||||
/// <returns>0 on success, or -1 on error.</returns> |
||||
[DllImport(Meta.DllName, EntryPoint = "SDL_RenderCopy", CallingConvention = CallingConvention.Cdecl)] |
||||
internal static extern int RenderCopy(IntPtr renderer, IntPtr texture, Rect.SdlRect srcRect, Rect.SdlRect dstRect); |
||||
[DllImport(Meta.DllName, EntryPoint = "SDL_RenderCopy", CallingConvention = CallingConvention.Cdecl)] |
||||
internal static extern int RenderCopy(IntPtr renderer, IntPtr texture, IntPtr srcRect, IntPtr dstRect); |
||||
|
||||
/// <summary> |
||||
/// Update the screen with the rendering performed. |
||||
/// </summary> |
||||
/// <param name="renderer">The renderer to update.</param> |
||||
[DllImport(Meta.DllName, EntryPoint = "SDL_RenderPresent", CallingConvention = CallingConvention.Cdecl)] |
||||
internal static extern void RenderPresent(IntPtr renderer); |
||||
|
||||
/// <summary> |
||||
/// Unlock a texture, uploading the changes to video memory, if needed. |
||||
/// </summary> |
||||
/// <param name="texture">The texture to unlock.</param> |
||||
[DllImport(Meta.DllName, EntryPoint = "SDL_UnlockTexture", CallingConvention = CallingConvention.Cdecl)] |
||||
internal static extern void UnlockTexture(IntPtr texture); |
||||
} |
||||
} |
@ -0,0 +1,37 @@
|
||||
using DotSDL.Sdl; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace DotSDL { |
||||
/// <summary> |
||||
/// This singleton maintains the SDL initialization state. |
||||
/// </summary> |
||||
internal sealed class SdlInit { |
||||
private static readonly Lazy<SdlInit> Singleton = new Lazy<SdlInit>(() => new SdlInit()); |
||||
internal static SdlInit Instance => Singleton.Value; |
||||
|
||||
private readonly Stack<Init.SubsystemFlags> _subsystems = new Stack<Init.SubsystemFlags>(); |
||||
|
||||
private SdlInit() { |
||||
Init.Initialize(Init.SubsystemFlags.None); |
||||
} |
||||
|
||||
~SdlInit() { |
||||
// Pop flags and shut down each subsystem in order. |
||||
while(_subsystems.Count > 0) |
||||
Init.QuitSubSystem(_subsystems.Pop()); |
||||
|
||||
Init.Quit(); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Initializes an SDL subsystem. |
||||
/// </summary> |
||||
/// <param name="subsystemFlags">The subsystem(s) to initialize.</param> |
||||
/// <returns><c>true</c> if initialization was successful, otherwise <c>false</c>.</returns> |
||||
internal bool InitSubsystem(Init.SubsystemFlags subsystemFlags) { |
||||
_subsystems.Push(subsystemFlags); |
||||
return Init.Initialize(subsystemFlags) == 0; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,8 @@
|
||||
namespace DotSDL.Sample.BasicPixels { |
||||
internal class BasicPixels { |
||||
private static void Main(string[] args) { |
||||
var window = new Window(512, 512); |
||||
window.Start(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,11 @@
|
||||
using DotSDL.Graphics; |
||||
|
||||
namespace DotSDL.Sample.BasicPixels { |
||||
internal class Window : SdlWindow { |
||||
public Window(int width, int height) : base("Basic Pixels", new Point { X = WindowPosUndefined, Y = WindowPosUndefined }, width, height) {} |
||||
|
||||
public override void OnDraw() { |
||||
|
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue