// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 using System; using System.Drawing; using OpenTK; #if ANDROID using Android.Graphics; #else using System.Drawing.Imaging; #endif namespace ClassicalSharp.GraphicsAPI { /// Abstracts a 3D graphics rendering API. public abstract partial class IGraphicsApi { /// Maximum supported length of a dimension (width and height) of a 2D texture. public abstract int MaxTextureDimensions { get; } /// Sets whether texturing is applied when rasterizing primitives. public abstract bool Texturing { set; } internal float MinZNear = 0.1f; readonly FastBitmap bmpBuffer = new FastBitmap(); /// Returns whether this graphics api had a valid context. public bool LostContext; /// Event raised when a context is destroyed after having been previously lost. public event Action ContextLost; /// Event raised when a context is recreated after having been previously lost. public event Action ContextRecreated; /// Whether mipmapping of terrain textures is used. public bool Mipmaps; /// Whether the backend supports setting the number of custom mipmaps levels. public bool CustomMipmapsLevels; /// Delegate that is invoked when the current context is lost, /// and is repeatedly invoked until the context can be retrieved. public ScheduledTaskCallback LostContextFunction; /// Creates a new native texture with the specified dimensions and using the /// image data encapsulated by the Bitmap instance. /// Note that should make every effort you can to ensure that the dimensions of the bitmap /// are powers of two, because otherwise they will not display properly on certain graphics cards.
/// This method returns -1 if the input image is not a 32bpp format.
public int CreateTexture(Bitmap bmp, bool managedPool, bool mipmaps) { if (!Platform.Is32Bpp(bmp)) { throw new ArgumentOutOfRangeException("Bitmap must be 32bpp"); } bmpBuffer.SetData(bmp, true, true); return CreateTexture(bmpBuffer, managedPool, mipmaps); } /// Creates a new native texture with the specified dimensions and FastBitmap instance /// that encapsulates the pointer to the 32bpp image data. /// Note that should make every effort you can to ensure that the dimensions are powers of two, /// because otherwise they will not display properly on certain graphics cards. public int CreateTexture(FastBitmap bmp, bool managedPool, bool mipmaps) { if (!Utils.IsPowerOf2(bmp.Width) || !Utils.IsPowerOf2(bmp.Height)) { throw new ArgumentOutOfRangeException("Bitmap must have power of two dimensions"); } if (LostContext) throw new InvalidOperationException("Cannot create texture when context lost"); if (!bmp.IsLocked) bmp.LockBits(); int texId = CreateTexture(bmp.Width, bmp.Height, bmp.Scan0, managedPool, mipmaps); bmp.UnlockBits(); return texId; } /// Creates a new native texture with the specified dimensions and pointer to the 32bpp image data. /// Note that should make every effort you can to ensure that the dimensions are powers of two, /// because otherwise they will not display properly on certain graphics cards. protected abstract int CreateTexture(int width, int height, IntPtr scan0, bool managedPool, bool mipmaps); /// Updates the sub-rectangle (x, y) -> (x + part.Width, y + part.Height) /// of the native texture associated with the given ID, with the pixels encapsulated in the 'part' instance. public abstract void UpdateTexturePart(int texId, int x, int y, FastBitmap part, bool mipmaps); /// Binds the given texture id so that it can be used for rasterization. public abstract void BindTexture(int texId); /// Frees all native resources held for the given texture id. public abstract void DeleteTexture(ref int texId); /// Frees all native resources held for the given texture id. public void DeleteTexture(ref Texture texture) { DeleteTexture(ref texture.ID); } /// Enables mipmapping for subsequent texture drawing. public abstract void EnableMipmaps(); /// Disbles mipmapping for subsequent texture drawing. public abstract void DisableMipmaps(); /// Gets or sets whether fog is currently enabled. public abstract bool Fog { get; set; } /// Sets the fog colour that is blended with final primitive colours. public abstract void SetFogColour(FastColour col); /// Sets the density of exp and exp^2 fog public abstract void SetFogDensity(float value); /// Sets the start radius of fog for linear fog. public abstract void SetFogStart(float value); /// Sets the end radius of fog for for linear fog. public abstract void SetFogEnd(float value); /// Sets the current fog mode. (linear, exp, or exp^2) public abstract void SetFogMode(Fog fogMode); /// Whether back facing primitives should be culled by the 3D graphics api. public abstract bool FaceCulling { set; } /// Whether alpha testing is currently enabled. public abstract bool AlphaTest { set; } /// Sets the alpha test compare function that is used when alpha testing is enabled. public abstract void AlphaTestFunc(CompareFunc func, float refValue); /// Whether alpha blending is currently enabled. public abstract bool AlphaBlending { set; } /// Sets the alpha blend function that is used when alpha blending is enabled. public abstract void AlphaBlendFunc(BlendFunc srcFunc, BlendFunc dstFunc); /// Clears the underlying back and/or front buffer. public abstract void Clear(); /// Sets the colour the screen is cleared to when Clear() is called. public abstract void ClearColour(FastColour col); /// Whether depth testing is currently enabled. public abstract bool DepthTest { set; } /// Sets the depth test compare function that is used when depth testing is enabled. public abstract void DepthTestFunc(CompareFunc func); /// Whether writing to the colour buffer is enabled. public abstract bool ColourWrite { set; } /// Whether writing to the depth buffer is enabled. public abstract bool DepthWrite { set; } /// Whether blending between the alpha components of the texture and colour are performed. public abstract bool AlphaArgBlend { set; } /// Creates a vertex buffer that can have its data dynamically updated. public abstract int CreateDynamicVb(VertexFormat format, int maxVertices); /// Creates a static vertex buffer that has its data set at creation, /// but the vertex buffer's data cannot be updated after creation. public abstract int CreateVb(IntPtr vertices, VertexFormat format, int count); /// Creates a static index buffer that has its data set at creation, /// but the index buffer's data cannot be updated after creation. public abstract int CreateIb(IntPtr indices, int indicesCount); /// Sets the currently active vertex buffer to the given id. public abstract void BindVb(int vb); /// Sets the currently active index buffer to the given id. public abstract void BindIb(int ib); /// Frees all native resources held for the vertex buffer associated with the given id. public abstract void DeleteVb(ref int vb); /// Frees all native resources held for the index buffer associated with the given id. public abstract void DeleteIb(ref int ib); /// Informs the graphics API that the format of the vertex data used in subsequent /// draw calls will be in the given format. public abstract void SetBatchFormat(VertexFormat format); /// Binds and updates the data of the current dynamic vertex buffer's data.
/// This method also replaces the dynamic vertex buffer's data first with the given vertices before drawing.
public abstract void SetDynamicVbData(int vb, IntPtr vertices, int vCount); /// Draws the specified subset of the vertices in the current vertex buffer as lines. public abstract void DrawVb_Lines(int verticesCount); /// Draws the specified subset of the vertices in the current vertex buffer as triangles. public abstract void DrawVb_IndexedTris(int verticesCount, int startVertex); /// Draws the specified subset of the vertices in the current vertex buffer as triangles. public abstract void DrawVb_IndexedTris(int verticesCount); /// Optimised version of DrawIndexedVb for VertexFormat.Pos3fTex2fCol4b internal abstract void DrawIndexedVb_TrisT2fC4b(int verticesCount, int startVertex); protected static int[] strideSizes = { 16, 24 }; /// Sets the matrix type that load/push/pop operations should be applied to. public abstract void SetMatrixMode(MatrixType mode); /// Sets the current matrix to the given matrix. public abstract void LoadMatrix(ref Matrix4 matrix); /// Sets the current matrix to the identity matrix. public abstract void LoadIdentityMatrix(); /// Multplies the current matrix by the given matrix, then /// sets the current matrix to the result of the multiplication. public abstract void MultiplyMatrix(ref Matrix4 matrix); /// Gets the top matrix the current matrix stack and pushes it to the stack. public abstract void PushMatrix(); /// Removes the top matrix from the current matrix stack, then /// sets the current matrix to the new top matrix of the stack. public abstract void PopMatrix(); /// Outputs a .png screenshot of the backbuffer to the specified file. public abstract void TakeScreenshot(string output, int width, int height); /// Adds a warning to chat if this graphics API has problems with the current user's GPU. public virtual bool WarnIfNecessary(Chat chat) { return false; } /// Informs the graphic api to update its state in preparation for a new frame. public abstract void BeginFrame(Game game); /// Informs the graphic api to update its state in preparation for the end of a frame, /// and to prepare that frame for display on the monitor. public abstract void EndFrame(Game game); /// Sets whether the graphics api should tie frame rendering to the refresh rate of the monitor. public abstract void SetVSync(Game game, bool value); /// Raised when the dimensions of the game's window have changed. public abstract void OnWindowResize(Game game); internal abstract void MakeApiInfo(); public string[] ApiInfo; protected virtual void LoadOrthoMatrix(float width, float height) { Matrix4 matrix; Matrix4.CreateOrthographicOffCenter(0, width, height, 0, -10000, 10000, out matrix); LoadMatrix(ref matrix); } /// Sets the appropriate alpha testing/blending states necessary to render the given block. public void SetupAlphaState(byte draw) { if (draw == DrawType.Translucent) AlphaBlending = true; if (draw == DrawType.Transparent) AlphaTest = true; if (draw == DrawType.TransparentThick) AlphaTest = true; if (draw == DrawType.Sprite) AlphaTest = true; } public void RestoreAlphaState(byte draw) { if (draw == DrawType.Translucent) AlphaBlending = false; if (draw == DrawType.Transparent) AlphaTest = false; if (draw == DrawType.TransparentThick) AlphaTest = false; if (draw == DrawType.Sprite) AlphaTest = false; } } }