2025-07-31 20:50:00 +02:00

177 lines
4.9 KiB
C#

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 IntPtr GetData0()
{
if (locked == IntPtr.Zero)
throw new InvalidOperationException("Texture not locked");
return locked;
}
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);
}
}
}