1 #pragma once 2 3 #include <mbgl/gl/features.hpp> 4 #include <mbgl/gl/object.hpp> 5 #include <mbgl/gl/state.hpp> 6 #include <mbgl/gl/value.hpp> 7 #include <mbgl/gl/texture.hpp> 8 #include <mbgl/gl/renderbuffer.hpp> 9 #include <mbgl/gl/framebuffer.hpp> 10 #include <mbgl/gl/vertex_buffer.hpp> 11 #include <mbgl/gl/index_buffer.hpp> 12 #include <mbgl/gl/vertex_array.hpp> 13 #include <mbgl/gl/types.hpp> 14 #include <mbgl/gl/draw_mode.hpp> 15 #include <mbgl/gl/depth_mode.hpp> 16 #include <mbgl/gl/stencil_mode.hpp> 17 #include <mbgl/gl/color_mode.hpp> 18 #include <mbgl/util/noncopyable.hpp> 19 20 21 #include <functional> 22 #include <memory> 23 #include <vector> 24 #include <array> 25 #include <string> 26 27 namespace mbgl { 28 namespace gl { 29 30 constexpr size_t TextureMax = 64; 31 using ProcAddress = void (*)(); 32 33 namespace extension { 34 class VertexArray; 35 class Debugging; 36 class ProgramBinary; 37 } // namespace extension 38 39 class Context { 40 public: 41 Context(); 42 ~Context(); 43 Context(const Context&) = delete; 44 Context& operator=(const Context& other) = delete; 45 46 void initializeExtensions(const std::function<gl::ProcAddress(const char*)>&); 47 48 void enableDebugging(); 49 50 UniqueShader createShader(ShaderType type, const std::string& source); 51 UniqueProgram createProgram(ShaderID vertexShader, ShaderID fragmentShader); 52 UniqueProgram createProgram(BinaryProgramFormat binaryFormat, const std::string& binaryProgram); 53 void verifyProgramLinkage(ProgramID); 54 void linkProgram(ProgramID); 55 UniqueTexture createTexture(); 56 VertexArray createVertexArray(); 57 58 #if MBGL_HAS_BINARY_PROGRAMS 59 bool supportsProgramBinaries() const; 60 #else supportsProgramBinaries() const61 constexpr bool supportsProgramBinaries() const { return false; } 62 #endif 63 optional<std::pair<BinaryProgramFormat, std::string>> getBinaryProgram(ProgramID) const; 64 65 template <class Vertex, class DrawMode> createVertexBuffer(VertexVector<Vertex,DrawMode> && v,const BufferUsage usage=BufferUsage::StaticDraw)66 VertexBuffer<Vertex, DrawMode> createVertexBuffer(VertexVector<Vertex, DrawMode>&& v, const BufferUsage usage = BufferUsage::StaticDraw) { 67 return VertexBuffer<Vertex, DrawMode> { 68 v.vertexSize(), 69 createVertexBuffer(v.data(), v.byteSize(), usage) 70 }; 71 } 72 73 template <class Vertex, class DrawMode> updateVertexBuffer(VertexBuffer<Vertex,DrawMode> & buffer,VertexVector<Vertex,DrawMode> && v)74 void updateVertexBuffer(VertexBuffer<Vertex, DrawMode>& buffer, VertexVector<Vertex, DrawMode>&& v) { 75 assert(v.vertexSize() == buffer.vertexCount); 76 updateVertexBuffer(buffer.buffer, v.data(), v.byteSize()); 77 } 78 79 template <class DrawMode> createIndexBuffer(IndexVector<DrawMode> && v,const BufferUsage usage=BufferUsage::StaticDraw)80 IndexBuffer<DrawMode> createIndexBuffer(IndexVector<DrawMode>&& v, const BufferUsage usage = BufferUsage::StaticDraw) { 81 return IndexBuffer<DrawMode> { 82 v.indexSize(), 83 createIndexBuffer(v.data(), v.byteSize(), usage) 84 }; 85 } 86 87 template <class DrawMode> updateIndexBuffer(IndexBuffer<DrawMode> & buffer,IndexVector<DrawMode> && v)88 void updateIndexBuffer(IndexBuffer<DrawMode>& buffer, IndexVector<DrawMode>&& v) { 89 assert(v.indexSize() == buffer.indexCount); 90 updateIndexBuffer(buffer.buffer, v.data(), v.byteSize()); 91 } 92 93 template <RenderbufferType type> createRenderbuffer(const Size size)94 Renderbuffer<type> createRenderbuffer(const Size size) { 95 static_assert(type == RenderbufferType::RGBA || 96 type == RenderbufferType::DepthStencil || 97 type == RenderbufferType::DepthComponent, 98 "invalid renderbuffer type"); 99 return { size, createRenderbuffer(type, size) }; 100 } 101 102 Framebuffer createFramebuffer(const Renderbuffer<RenderbufferType::RGBA>&, 103 const Renderbuffer<RenderbufferType::DepthStencil>&); 104 Framebuffer createFramebuffer(const Renderbuffer<RenderbufferType::RGBA>&); 105 Framebuffer createFramebuffer(const Texture&, 106 const Renderbuffer<RenderbufferType::DepthStencil>&); 107 Framebuffer createFramebuffer(const Texture&); 108 Framebuffer createFramebuffer(const Texture&, 109 const Renderbuffer<RenderbufferType::DepthComponent>&); 110 111 template <typename Image, 112 TextureFormat format = Image::channels == 4 ? TextureFormat::RGBA 113 : TextureFormat::Alpha> readFramebuffer(const Size size,bool flip=true)114 Image readFramebuffer(const Size size, bool flip = true) { 115 static_assert(Image::channels == (format == TextureFormat::RGBA ? 4 : 1), 116 "image format mismatch"); 117 return { size, readFramebuffer(size, format, flip) }; 118 } 119 120 #if not MBGL_USE_GLES2 121 template <typename Image> drawPixels(const Image & image)122 void drawPixels(const Image& image) { 123 auto format = image.channels == 4 ? TextureFormat::RGBA : TextureFormat::Alpha; 124 drawPixels(image.size, image.data.get(), format); 125 } 126 #endif // MBGL_USE_GLES2 127 128 // Create a texture from an image with data. 129 template <typename Image> createTexture(const Image & image,TextureUnit unit=0,TextureType type=TextureType::UnsignedByte)130 Texture createTexture(const Image& image, 131 TextureUnit unit = 0, 132 TextureType type = TextureType::UnsignedByte) { 133 auto format = image.channels == 4 ? TextureFormat::RGBA : TextureFormat::Alpha; 134 return { image.size, createTexture(image.size, image.data.get(), format, unit, type) }; 135 } 136 137 template <typename Image> updateTexture(Texture & obj,const Image & image,TextureUnit unit=0,TextureType type=TextureType::UnsignedByte)138 void updateTexture(Texture& obj, 139 const Image& image, 140 TextureUnit unit = 0, 141 TextureType type = TextureType::UnsignedByte) { 142 auto format = image.channels == 4 ? TextureFormat::RGBA : TextureFormat::Alpha; 143 updateTexture(obj.texture.get(), image.size, image.data.get(), format, unit, type); 144 obj.size = image.size; 145 } 146 147 // Creates an empty texture with the specified dimensions. createTexture(const Size size,TextureFormat format=TextureFormat::RGBA,TextureUnit unit=0,TextureType type=TextureType::UnsignedByte)148 Texture createTexture(const Size size, 149 TextureFormat format = TextureFormat::RGBA, 150 TextureUnit unit = 0, 151 TextureType type = TextureType::UnsignedByte) { 152 return { size, createTexture(size, nullptr, format, unit, type) }; 153 } 154 155 void bindTexture(Texture&, 156 TextureUnit = 0, 157 TextureFilter = TextureFilter::Nearest, 158 TextureMipMap = TextureMipMap::No, 159 TextureWrap wrapX = TextureWrap::Clamp, 160 TextureWrap wrapY = TextureWrap::Clamp); 161 162 void clear(optional<mbgl::Color> color, 163 optional<float> depth, 164 optional<int32_t> stencil); 165 166 void setDrawMode(const Points&); 167 void setDrawMode(const Lines&); 168 void setDrawMode(const LineStrip&); 169 void setDrawMode(const Triangles&); 170 void setDrawMode(const TriangleStrip&); 171 172 void setDepthMode(const DepthMode&); 173 void setStencilMode(const StencilMode&); 174 void setColorMode(const ColorMode&); 175 176 void draw(PrimitiveType, 177 std::size_t indexOffset, 178 std::size_t indexLength); 179 180 // Actually remove the objects we marked as abandoned with the above methods. 181 // Only call this while the OpenGL context is exclusive to this thread. 182 void performCleanup(); 183 184 // Drain pools and remove abandoned objects, in preparation for destroying the store. 185 // Only call this while the OpenGL context is exclusive to this thread. 186 void reset(); 187 empty() const188 bool empty() const { 189 return pooledTextures.empty() 190 && abandonedPrograms.empty() 191 && abandonedShaders.empty() 192 && abandonedBuffers.empty() 193 && abandonedTextures.empty() 194 && abandonedVertexArrays.empty() 195 && abandonedFramebuffers.empty(); 196 } 197 198 void setDirtyState(); 199 getDebuggingExtension() const200 extension::Debugging* getDebuggingExtension() const { 201 return debugging.get(); 202 } 203 getVertexArrayExtension() const204 extension::VertexArray* getVertexArrayExtension() const { 205 return vertexArray.get(); 206 } 207 setCleanupOnDestruction(bool cleanup)208 void setCleanupOnDestruction(bool cleanup) { 209 cleanupOnDestruction = cleanup; 210 } 211 212 private: 213 bool cleanupOnDestruction = true; 214 215 std::unique_ptr<extension::Debugging> debugging; 216 std::unique_ptr<extension::VertexArray> vertexArray; 217 #if MBGL_HAS_BINARY_PROGRAMS 218 std::unique_ptr<extension::ProgramBinary> programBinary; 219 #endif 220 221 public: 222 State<value::ActiveTextureUnit> activeTextureUnit; 223 State<value::BindFramebuffer> bindFramebuffer; 224 State<value::Viewport> viewport; 225 State<value::ScissorTest> scissorTest; 226 std::array<State<value::BindTexture>, 2> texture; 227 State<value::Program> program; 228 State<value::BindVertexBuffer> vertexBuffer; 229 230 State<value::BindVertexArray, const Context&> bindVertexArray { *this }; 231 VertexArrayState globalVertexArrayState { UniqueVertexArray(0, { this }) }; 232 233 State<value::PixelStorePack> pixelStorePack; 234 State<value::PixelStoreUnpack> pixelStoreUnpack; 235 236 #if not MBGL_USE_GLES2 237 State<value::PixelZoom> pixelZoom; 238 State<value::RasterPos> rasterPos; 239 State<value::PixelTransferDepth> pixelTransferDepth; 240 State<value::PixelTransferStencil> pixelTransferStencil; 241 #endif // MBGL_USE_GLES2 242 243 bool supportsHalfFloatTextures = false; 244 const uint32_t maximumVertexBindingCount; 245 static constexpr const uint32_t minimumRequiredVertexBindingCount = 8; 246 247 private: 248 State<value::StencilFunc> stencilFunc; 249 State<value::StencilMask> stencilMask; 250 State<value::StencilTest> stencilTest; 251 State<value::StencilOp> stencilOp; 252 State<value::DepthRange> depthRange; 253 State<value::DepthMask> depthMask; 254 State<value::DepthTest> depthTest; 255 State<value::DepthFunc> depthFunc; 256 State<value::Blend> blend; 257 State<value::BlendEquation> blendEquation; 258 State<value::BlendFunc> blendFunc; 259 State<value::BlendColor> blendColor; 260 State<value::ColorMask> colorMask; 261 State<value::ClearDepth> clearDepth; 262 State<value::ClearColor> clearColor; 263 State<value::ClearStencil> clearStencil; 264 State<value::LineWidth> lineWidth; 265 State<value::BindRenderbuffer> bindRenderbuffer; 266 #if not MBGL_USE_GLES2 267 State<value::PointSize> pointSize; 268 #endif // MBGL_USE_GLES2 269 270 UniqueBuffer createVertexBuffer(const void* data, std::size_t size, const BufferUsage usage); 271 void updateVertexBuffer(UniqueBuffer& buffer, const void* data, std::size_t size); 272 UniqueBuffer createIndexBuffer(const void* data, std::size_t size, const BufferUsage usage); 273 void updateIndexBuffer(UniqueBuffer& buffer, const void* data, std::size_t size); 274 UniqueTexture createTexture(Size size, const void* data, TextureFormat, TextureUnit, TextureType); 275 void updateTexture(TextureID, Size size, const void* data, TextureFormat, TextureUnit, TextureType); 276 UniqueFramebuffer createFramebuffer(); 277 UniqueRenderbuffer createRenderbuffer(RenderbufferType, Size size); 278 std::unique_ptr<uint8_t[]> readFramebuffer(Size, TextureFormat, bool flip); 279 #if not MBGL_USE_GLES2 280 void drawPixels(Size size, const void* data, TextureFormat); 281 #endif // MBGL_USE_GLES2 282 283 bool supportsVertexArrays() const; 284 285 friend detail::ProgramDeleter; 286 friend detail::ShaderDeleter; 287 friend detail::BufferDeleter; 288 friend detail::TextureDeleter; 289 friend detail::VertexArrayDeleter; 290 friend detail::FramebufferDeleter; 291 friend detail::RenderbufferDeleter; 292 293 std::vector<TextureID> pooledTextures; 294 295 std::vector<ProgramID> abandonedPrograms; 296 std::vector<ShaderID> abandonedShaders; 297 std::vector<BufferID> abandonedBuffers; 298 std::vector<TextureID> abandonedTextures; 299 std::vector<VertexArrayID> abandonedVertexArrays; 300 std::vector<FramebufferID> abandonedFramebuffers; 301 std::vector<RenderbufferID> abandonedRenderbuffers; 302 303 public: 304 // For testing and Windows because Qt + ANGLE 305 // crashes with VAO enabled. 306 #if defined(_WINDOWS) 307 bool disableVAOExtension = true; 308 #else 309 bool disableVAOExtension = false; 310 #endif 311 }; 312 313 } // namespace gl 314 } // namespace mbgl 315