using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using SDL2; namespace testdrid.SdlWrapper { internal class Texture : IDisposable { private Texture() {} internal IntPtr Pointer { get; set; } public static Texture FromSurface(Renderer renderer, Surface surface) { Texture result = new Texture(); result.Pointer = SDL.SDL_CreateTextureFromSurface(renderer.Pointer, surface.IntPointer); if (result.Pointer == IntPtr.Zero) { throw SdlException.GenerateException(); } return result; } public static Texture Create(Renderer renderer, SDL.SDL_TextureAccess access, int w, int h) { Texture result = new Texture(); result.Pointer = SDL.SDL_CreateTexture(renderer.Pointer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)access, w, h); if (result.Pointer == IntPtr.Zero) { throw SdlException.GenerateException(); } return result; } internal static Texture FromIntPointer(IntPtr intPtr) { Texture result = new Texture(); result.Pointer = intPtr; return result; } public void Dispose() { SDL.SDL_DestroyTexture(Pointer); Pointer = IntPtr.Zero; } private bool queryCached; private uint queryFormat; private int queryAccess, queryW, queryH; private void Query() { if (!queryCached) { SDL.SDL_QueryTexture(Pointer, out queryFormat, out queryAccess, out queryW, out queryH); queryCached = true; } } public int GetWidth() { Query(); return queryW; } public int GetHeight() { Query(); return queryH; } private IntPtr locked; private int lockedPitch; public void Lock() { if (locked != IntPtr.Zero) throw new InvalidOperationException("Texture already locked"); int sdlLockTexture = SDL.SDL_LockTexture(Pointer, IntPtr.Zero, out locked, out lockedPitch); if (sdlLockTexture != 0) { throw SdlException.GenerateException(); } } public void Fill(byte a, byte r, byte g, byte b) { SDL.SDL_Rect rekt = new SDL.SDL_Rect(); rekt.h = GetHeight(); rekt.w = GetWidth(); rekt.x = 0; rekt.y = 0; uint color = (uint)(a << 24); color += (uint)(r << 16); color += (uint)(g << 8); color += b; int sdlFillRect = SDL.SDL_FillRect(Pointer, ref rekt, color); if (sdlFillRect != 0) { throw SdlException.GenerateException(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetPixel(int x, int y, byte a, byte r, byte g, byte b) { if (y < 0) return; if (x < 0) return; if (x >= GetWidth()) return; if (y >= GetHeight()) return; if (locked == IntPtr.Zero) throw new InvalidOperationException("Texture not locked"); int bytesPerPixel = lockedPitch / GetWidth(); int offset = lockedPitch * y; offset += (x * bytesPerPixel); Marshal.WriteByte(locked, offset + 0, b); Marshal.WriteByte(locked, offset + 1, g); Marshal.WriteByte(locked, offset + 2, r); Marshal.WriteByte(locked, offset + 3, a); } public void Unlock() { if (locked == IntPtr.Zero) throw new InvalidOperationException("Texture not locked"); SDL.SDL_UnlockTexture(Pointer); locked = IntPtr.Zero; lockedPitch = 0; } public void SetDrawBlendMode(SDL.SDL_BlendMode mode) { int i = SDL.SDL_SetTextureBlendMode(Pointer, mode); if (i != 0) throw SdlException.GenerateException(); } public Surface LockAsSurface() { if (locked != IntPtr.Zero) throw new InvalidOperationException("Texture already locked"); IntPtr surfacePtr; if (SDL.SDL_LockTextureToSurface(Pointer, IntPtr.Zero, out surfacePtr) != 0) throw SdlException.GenerateException(); locked = surfacePtr; return new Surface(surfacePtr); } } }