/* Copyright 2016-2023 melonDS team This file is part of melonDS. melonDS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. melonDS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with melonDS. If not, see http://www.gnu.org/licenses/. */ #pragma once #ifdef OGLRENDERER_ENABLED #include "GPU3D.h" #include "GPU_OpenGL.h" #include "OpenGLSupport.h" namespace melonDS { class GPU; class GLRenderer : public Renderer3D { public: ~GLRenderer() override; void Reset(GPU& gpu) override; void SetRenderSettings(bool betterpolygons, int scale) noexcept; void SetBetterPolygons(bool betterpolygons) noexcept; void SetScaleFactor(int scale) noexcept; [[nodiscard]] bool GetBetterPolygons() const noexcept { return BetterPolygons; } [[nodiscard]] int GetScaleFactor() const noexcept { return ScaleFactor; } void VCount144(GPU& gpu) override {}; void RenderFrame(GPU& gpu) override; void Stop(const GPU& gpu) override; u32* GetLine(int line) override; void SetupAccelFrame(); void PrepareCaptureFrame() override; void Blit(const GPU& gpu) override; [[nodiscard]] const GLCompositor& GetCompositor() const noexcept { return CurGLCompositor; } GLCompositor& GetCompositor() noexcept { return CurGLCompositor; } static std::unique_ptr New() noexcept; private: // Used by New() GLRenderer(GLCompositor&& compositor) noexcept; // GL version requirements // * texelFetch: 3.0 (GLSL 1.30) (3.2/1.50 for MS) // * UBO: 3.1 struct RendererPolygon { Polygon* PolyData; u32 NumIndices; u32 IndicesOffset; GLuint PrimType; u32 NumEdgeIndices; u32 EdgeIndicesOffset; u32 RenderKey; }; GLCompositor CurGLCompositor; RendererPolygon PolygonList[2048] {}; bool BuildRenderShader(u32 flags, const char* vs, const char* fs); void UseRenderShader(u32 flags); void SetupPolygon(RendererPolygon* rp, Polygon* polygon) const; u32* SetupVertex(const Polygon* poly, int vid, const Vertex* vtx, u32 vtxattr, u32* vptr) const; void BuildPolygons(RendererPolygon* polygons, int npolys); int RenderSinglePolygon(int i) const; int RenderPolygonBatch(int i) const; int RenderPolygonEdgeBatch(int i) const; void RenderSceneChunk(const GPU3D& gpu3d, int y, int h); enum { RenderFlag_WBuffer = 0x01, RenderFlag_Trans = 0x02, RenderFlag_ShadowMask = 0x04, RenderFlag_Edge = 0x08, }; GLuint ClearShaderPlain[3] {}; GLuint RenderShader[16][3] {}; GLuint CurShaderID = -1; GLuint FinalPassEdgeShader[3] {}; GLuint FinalPassFogShader[3] {}; // std140 compliant structure struct { float uScreenSize[2]; // vec2 0 / 2 u32 uDispCnt; // int 2 / 1 u32 __pad0; float uToonColors[32][4]; // vec4[32] 4 / 128 float uEdgeColors[8][4]; // vec4[8] 132 / 32 float uFogColor[4]; // vec4 164 / 4 float uFogDensity[34][4]; // float[34] 168 / 136 u32 uFogOffset; // int 304 / 1 u32 uFogShift; // int 305 / 1 u32 _pad1[2]; // int 306 / 2 } ShaderConfig {}; GLuint ShaderConfigUBO {}; int NumFinalPolys {}, NumOpaqueFinalPolys {}; GLuint ClearVertexBufferID = 0, ClearVertexArrayID {}; GLint ClearUniformLoc[4] {}; // vertex buffer // * XYZW: 4x16bit // * RGBA: 4x8bit // * ST: 2x16bit // * polygon data: 3x32bit (polygon/texture attributes) // // polygon attributes: // * bit4-7, 11, 14-15, 24-29: POLYGON_ATTR // * bit16-20: Z shift // * bit8: front-facing (?) // * bit9: W-buffering (?) GLuint VertexBufferID {}; u32 VertexBuffer[10240 * 7] {}; u32 NumVertices {}; GLuint VertexArrayID {}; GLuint IndexBufferID {}; u16 IndexBuffer[2048 * 40] {}; u32 NumIndices {}, NumEdgeIndices {}; const u32 EdgeIndicesOffset = 2048 * 30; GLuint TexMemID {}; GLuint TexPalMemID {}; int ScaleFactor {}; bool BetterPolygons {}; int ScreenW {}, ScreenH {}; GLuint FramebufferTex[8] {}; int FrontBuffer {}; GLuint FramebufferID[4] {}, PixelbufferID {}; u32 Framebuffer[256*192] {}; }; } #endif