| 1 | /** |
| 2 | * Copyright (c) 2006-2023 LOVE Development Team |
| 3 | * |
| 4 | * This software is provided 'as-is', without any express or implied |
| 5 | * warranty. In no event will the authors be held liable for any damages |
| 6 | * arising from the use of this software. |
| 7 | * |
| 8 | * Permission is granted to anyone to use this software for any purpose, |
| 9 | * including commercial applications, and to alter it and redistribute it |
| 10 | * freely, subject to the following restrictions: |
| 11 | * |
| 12 | * 1. The origin of this software must not be misrepresented; you must not |
| 13 | * claim that you wrote the original software. If you use this software |
| 14 | * in a product, an acknowledgment in the product documentation would be |
| 15 | * appreciated but is not required. |
| 16 | * 2. Altered source versions must be plainly marked as such, and must not be |
| 17 | * misrepresented as being the original software. |
| 18 | * 3. This notice may not be removed or altered from any source distribution. |
| 19 | **/ |
| 20 | |
| 21 | #ifndef LOVE_GRAPHICS_GRAPHICS_H |
| 22 | #define LOVE_GRAPHICS_GRAPHICS_H |
| 23 | |
| 24 | // LOVE |
| 25 | #include "common/config.h" |
| 26 | #include "common/Module.h" |
| 27 | #include "common/StringMap.h" |
| 28 | #include "common/Vector.h" |
| 29 | #include "common/Optional.h" |
| 30 | #include "common/int.h" |
| 31 | #include "common/Color.h" |
| 32 | #include "StreamBuffer.h" |
| 33 | #include "vertex.h" |
| 34 | #include "Texture.h" |
| 35 | #include "Canvas.h" |
| 36 | #include "Font.h" |
| 37 | #include "ShaderStage.h" |
| 38 | #include "Shader.h" |
| 39 | #include "Quad.h" |
| 40 | #include "Mesh.h" |
| 41 | #include "Image.h" |
| 42 | #include "Deprecations.h" |
| 43 | #include "depthstencil.h" |
| 44 | #include "math/Transform.h" |
| 45 | #include "font/Rasterizer.h" |
| 46 | #include "font/Font.h" |
| 47 | #include "video/VideoStream.h" |
| 48 | #include "data/HashFunction.h" |
| 49 | |
| 50 | // C++ |
| 51 | #include <string> |
| 52 | #include <vector> |
| 53 | |
| 54 | namespace love |
| 55 | { |
| 56 | |
| 57 | namespace graphics |
| 58 | { |
| 59 | |
| 60 | class SpriteBatch; |
| 61 | class ParticleSystem; |
| 62 | class Text; |
| 63 | class Video; |
| 64 | class Buffer; |
| 65 | |
| 66 | typedef Optional<Colorf> OptionalColorf; |
| 67 | |
| 68 | const int MAX_COLOR_RENDER_TARGETS = 8; |
| 69 | |
| 70 | /** |
| 71 | * Globally sets whether gamma correction is enabled. Ideally this should be set |
| 72 | * prior to using any Graphics module function. |
| 73 | **/ |
| 74 | void setGammaCorrect(bool gammacorrect); |
| 75 | |
| 76 | /** |
| 77 | * Gets whether global gamma correction is enabled. |
| 78 | **/ |
| 79 | bool isGammaCorrect(); |
| 80 | |
| 81 | /** |
| 82 | * Gamma-corrects a color (converts it from sRGB to linear RGB, if |
| 83 | * gamma correction is enabled.) |
| 84 | * The color's components are expected to be in the range of [0, 1]. |
| 85 | **/ |
| 86 | void gammaCorrectColor(Colorf &c); |
| 87 | |
| 88 | /** |
| 89 | * Un-gamma-corrects a color (converts it from linear RGB to sRGB, if |
| 90 | * gamma correction is enabled.) |
| 91 | * The color's components are expected to be in the range of [0, 1]. |
| 92 | **/ |
| 93 | void unGammaCorrectColor(Colorf &c); |
| 94 | |
| 95 | Colorf gammaCorrectColor(const Colorf &c); |
| 96 | Colorf unGammaCorrectColor(const Colorf &c); |
| 97 | |
| 98 | bool isDebugEnabled(); |
| 99 | |
| 100 | class Graphics : public Module |
| 101 | { |
| 102 | public: |
| 103 | |
| 104 | static love::Type type; |
| 105 | |
| 106 | enum DrawMode |
| 107 | { |
| 108 | DRAW_LINE, |
| 109 | DRAW_FILL, |
| 110 | DRAW_MAX_ENUM |
| 111 | }; |
| 112 | |
| 113 | enum ArcMode |
| 114 | { |
| 115 | ARC_OPEN, |
| 116 | ARC_CLOSED, |
| 117 | ARC_PIE, |
| 118 | ARC_MAX_ENUM |
| 119 | }; |
| 120 | |
| 121 | enum BlendMode |
| 122 | { |
| 123 | BLEND_ALPHA, |
| 124 | BLEND_ADD, |
| 125 | BLEND_SUBTRACT, |
| 126 | BLEND_MULTIPLY, |
| 127 | BLEND_LIGHTEN, |
| 128 | BLEND_DARKEN, |
| 129 | BLEND_SCREEN, |
| 130 | BLEND_REPLACE, |
| 131 | BLEND_NONE, |
| 132 | BLEND_MAX_ENUM |
| 133 | }; |
| 134 | |
| 135 | enum BlendAlpha |
| 136 | { |
| 137 | BLENDALPHA_MULTIPLY, |
| 138 | BLENDALPHA_PREMULTIPLIED, |
| 139 | BLENDALPHA_MAX_ENUM |
| 140 | }; |
| 141 | |
| 142 | enum LineStyle |
| 143 | { |
| 144 | LINE_ROUGH, |
| 145 | LINE_SMOOTH, |
| 146 | LINE_MAX_ENUM |
| 147 | }; |
| 148 | |
| 149 | enum LineJoin |
| 150 | { |
| 151 | LINE_JOIN_NONE, |
| 152 | LINE_JOIN_MITER, |
| 153 | LINE_JOIN_BEVEL, |
| 154 | LINE_JOIN_MAX_ENUM |
| 155 | }; |
| 156 | |
| 157 | enum Feature |
| 158 | { |
| 159 | FEATURE_MULTI_CANVAS_FORMATS, |
| 160 | FEATURE_CLAMP_ZERO, |
| 161 | FEATURE_LIGHTEN, |
| 162 | FEATURE_FULL_NPOT, |
| 163 | FEATURE_PIXEL_SHADER_HIGHP, |
| 164 | FEATURE_SHADER_DERIVATIVES, |
| 165 | FEATURE_GLSL3, |
| 166 | FEATURE_INSTANCING, |
| 167 | FEATURE_MAX_ENUM |
| 168 | }; |
| 169 | |
| 170 | enum Renderer |
| 171 | { |
| 172 | RENDERER_OPENGL = 0, |
| 173 | RENDERER_OPENGLES, |
| 174 | RENDERER_MAX_ENUM |
| 175 | }; |
| 176 | |
| 177 | enum SystemLimit |
| 178 | { |
| 179 | LIMIT_POINT_SIZE, |
| 180 | LIMIT_TEXTURE_SIZE, |
| 181 | LIMIT_VOLUME_TEXTURE_SIZE, |
| 182 | LIMIT_CUBE_TEXTURE_SIZE, |
| 183 | LIMIT_TEXTURE_LAYERS, |
| 184 | LIMIT_MULTI_CANVAS, |
| 185 | LIMIT_CANVAS_MSAA, |
| 186 | LIMIT_ANISOTROPY, |
| 187 | LIMIT_MAX_ENUM |
| 188 | }; |
| 189 | |
| 190 | enum StackType |
| 191 | { |
| 192 | STACK_ALL, |
| 193 | STACK_TRANSFORM, |
| 194 | STACK_MAX_ENUM |
| 195 | }; |
| 196 | |
| 197 | enum TemporaryRenderTargetFlags |
| 198 | { |
| 199 | TEMPORARY_RT_DEPTH = (1 << 0), |
| 200 | TEMPORARY_RT_STENCIL = (1 << 1), |
| 201 | }; |
| 202 | |
| 203 | struct Capabilities |
| 204 | { |
| 205 | double limits[LIMIT_MAX_ENUM]; |
| 206 | bool features[FEATURE_MAX_ENUM]; |
| 207 | bool textureTypes[TEXTURE_MAX_ENUM]; |
| 208 | }; |
| 209 | |
| 210 | struct RendererInfo |
| 211 | { |
| 212 | std::string name; |
| 213 | std::string version; |
| 214 | std::string vendor; |
| 215 | std::string device; |
| 216 | }; |
| 217 | |
| 218 | struct Stats |
| 219 | { |
| 220 | int drawCalls; |
| 221 | int drawCallsBatched; |
| 222 | int canvasSwitches; |
| 223 | int shaderSwitches; |
| 224 | int canvases; |
| 225 | int images; |
| 226 | int fonts; |
| 227 | int64 textureMemory; |
| 228 | }; |
| 229 | |
| 230 | struct ColorMask |
| 231 | { |
| 232 | bool r, g, b, a; |
| 233 | |
| 234 | ColorMask() |
| 235 | : r(true), g(true), b(true), a(true) |
| 236 | {} |
| 237 | |
| 238 | ColorMask(bool _r, bool _g, bool _b, bool _a) |
| 239 | : r(_r), g(_g), b(_b), a(_a) |
| 240 | {} |
| 241 | |
| 242 | bool operator == (const ColorMask &m) const |
| 243 | { |
| 244 | return r == m.r && g == m.g && b == m.b && a == m.a; |
| 245 | } |
| 246 | |
| 247 | bool operator != (const ColorMask &m) const |
| 248 | { |
| 249 | return !(operator == (m)); |
| 250 | } |
| 251 | }; |
| 252 | |
| 253 | struct DrawCommand |
| 254 | { |
| 255 | PrimitiveType primitiveType = PRIMITIVE_TRIANGLES; |
| 256 | |
| 257 | const vertex::Attributes *attributes; |
| 258 | const vertex::BufferBindings *buffers; |
| 259 | |
| 260 | int vertexStart = 0; |
| 261 | int vertexCount = 0; |
| 262 | int instanceCount = 1; |
| 263 | |
| 264 | Texture *texture = nullptr; |
| 265 | |
| 266 | // TODO: This should be moved out to a state transition API? |
| 267 | CullMode cullMode = CULL_NONE; |
| 268 | |
| 269 | DrawCommand(const vertex::Attributes *attribs, const vertex::BufferBindings *buffers) |
| 270 | : attributes(attribs) |
| 271 | , buffers(buffers) |
| 272 | {} |
| 273 | }; |
| 274 | |
| 275 | struct DrawIndexedCommand |
| 276 | { |
| 277 | PrimitiveType primitiveType = PRIMITIVE_TRIANGLES; |
| 278 | |
| 279 | const vertex::Attributes *attributes; |
| 280 | const vertex::BufferBindings *buffers; |
| 281 | |
| 282 | int indexCount = 0; |
| 283 | int instanceCount = 1; |
| 284 | |
| 285 | IndexDataType indexType = INDEX_UINT16; |
| 286 | Resource *indexBuffer; |
| 287 | size_t indexBufferOffset = 0; |
| 288 | |
| 289 | Texture *texture = nullptr; |
| 290 | |
| 291 | // TODO: This should be moved out to a state transition API? |
| 292 | CullMode cullMode = CULL_NONE; |
| 293 | |
| 294 | DrawIndexedCommand(const vertex::Attributes *attribs, const vertex::BufferBindings *buffers, Resource *indexbuffer) |
| 295 | : attributes(attribs) |
| 296 | , buffers(buffers) |
| 297 | , indexBuffer(indexbuffer) |
| 298 | {} |
| 299 | }; |
| 300 | |
| 301 | struct StreamDrawCommand |
| 302 | { |
| 303 | PrimitiveType primitiveMode = PRIMITIVE_TRIANGLES; |
| 304 | vertex::CommonFormat formats[2]; |
| 305 | vertex::TriangleIndexMode indexMode = vertex::TriangleIndexMode::NONE; |
| 306 | int vertexCount = 0; |
| 307 | Texture *texture = nullptr; |
| 308 | Shader::StandardShader standardShaderType = Shader::STANDARD_DEFAULT; |
| 309 | |
| 310 | StreamDrawCommand() |
| 311 | { |
| 312 | // VS2013 can't initialize arrays in the above manner... |
| 313 | formats[1] = formats[0] = vertex::CommonFormat::NONE; |
| 314 | } |
| 315 | }; |
| 316 | |
| 317 | struct StreamVertexData |
| 318 | { |
| 319 | void *stream[2]; |
| 320 | }; |
| 321 | |
| 322 | class TempTransform |
| 323 | { |
| 324 | public: |
| 325 | |
| 326 | TempTransform(Graphics *gfx) |
| 327 | : gfx(gfx) |
| 328 | { |
| 329 | gfx->pushTransform(); |
| 330 | } |
| 331 | |
| 332 | TempTransform(Graphics *gfx, const Matrix4 &t) |
| 333 | : gfx(gfx) |
| 334 | { |
| 335 | gfx->pushTransform(); |
| 336 | gfx->transformStack.back() *= t; |
| 337 | } |
| 338 | |
| 339 | ~TempTransform() |
| 340 | { |
| 341 | gfx->popTransform(); |
| 342 | } |
| 343 | |
| 344 | private: |
| 345 | Graphics *gfx; |
| 346 | }; |
| 347 | |
| 348 | struct ScreenshotInfo; |
| 349 | typedef void (*ScreenshotCallback)(const ScreenshotInfo *info, love::image::ImageData *i, void *ud); |
| 350 | |
| 351 | struct ScreenshotInfo |
| 352 | { |
| 353 | ScreenshotCallback callback = nullptr; |
| 354 | void *data = nullptr; |
| 355 | }; |
| 356 | |
| 357 | struct RenderTargetStrongRef; |
| 358 | |
| 359 | struct RenderTarget |
| 360 | { |
| 361 | Canvas *canvas; |
| 362 | int slice; |
| 363 | int mipmap; |
| 364 | |
| 365 | RenderTarget(Canvas *canvas, int slice = 0, int mipmap = 0) |
| 366 | : canvas(canvas) |
| 367 | , slice(slice) |
| 368 | , mipmap(mipmap) |
| 369 | {} |
| 370 | |
| 371 | RenderTarget() |
| 372 | : canvas(nullptr) |
| 373 | , slice(0) |
| 374 | , mipmap(0) |
| 375 | {} |
| 376 | |
| 377 | bool operator != (const RenderTarget &other) const |
| 378 | { |
| 379 | return canvas != other.canvas || slice != other.slice || mipmap != other.mipmap; |
| 380 | } |
| 381 | |
| 382 | bool operator != (const RenderTargetStrongRef &other) const |
| 383 | { |
| 384 | return canvas != other.canvas.get() || slice != other.slice || mipmap != other.mipmap; |
| 385 | } |
| 386 | }; |
| 387 | |
| 388 | struct RenderTargetStrongRef |
| 389 | { |
| 390 | StrongRef<Canvas> canvas; |
| 391 | int slice = 0; |
| 392 | int mipmap = 0; |
| 393 | |
| 394 | RenderTargetStrongRef(Canvas *canvas, int slice = 0, int mipmap = 0) |
| 395 | : canvas(canvas) |
| 396 | , slice(slice) |
| 397 | , mipmap(mipmap) |
| 398 | {} |
| 399 | |
| 400 | bool operator != (const RenderTargetStrongRef &other) const |
| 401 | { |
| 402 | return canvas.get() != other.canvas.get() || slice != other.slice || mipmap != other.mipmap; |
| 403 | } |
| 404 | |
| 405 | bool operator != (const RenderTarget &other) const |
| 406 | { |
| 407 | return canvas.get() != other.canvas || slice != other.slice || mipmap != other.mipmap; |
| 408 | } |
| 409 | }; |
| 410 | |
| 411 | struct RenderTargets |
| 412 | { |
| 413 | std::vector<RenderTarget> colors; |
| 414 | RenderTarget depthStencil; |
| 415 | uint32 temporaryRTFlags; |
| 416 | |
| 417 | RenderTargets() |
| 418 | : depthStencil(nullptr) |
| 419 | , temporaryRTFlags(0) |
| 420 | {} |
| 421 | |
| 422 | const RenderTarget &getFirstTarget() const |
| 423 | { |
| 424 | return colors.empty() ? depthStencil : colors[0]; |
| 425 | } |
| 426 | |
| 427 | bool operator == (const RenderTargets &other) const |
| 428 | { |
| 429 | size_t ncolors = colors.size(); |
| 430 | if (ncolors != other.colors.size()) |
| 431 | return false; |
| 432 | |
| 433 | for (size_t i = 0; i < ncolors; i++) |
| 434 | { |
| 435 | if (colors[i] != other.colors[i]) |
| 436 | return false; |
| 437 | } |
| 438 | |
| 439 | if (depthStencil != other.depthStencil || temporaryRTFlags != other.temporaryRTFlags) |
| 440 | return false; |
| 441 | |
| 442 | return true; |
| 443 | } |
| 444 | }; |
| 445 | |
| 446 | struct RenderTargetsStrongRef |
| 447 | { |
| 448 | std::vector<RenderTargetStrongRef> colors; |
| 449 | RenderTargetStrongRef depthStencil; |
| 450 | uint32 temporaryRTFlags; |
| 451 | |
| 452 | RenderTargetsStrongRef() |
| 453 | : depthStencil(nullptr) |
| 454 | , temporaryRTFlags(0) |
| 455 | {} |
| 456 | |
| 457 | const RenderTargetStrongRef &getFirstTarget() const |
| 458 | { |
| 459 | return colors.empty() ? depthStencil : colors[0]; |
| 460 | } |
| 461 | }; |
| 462 | |
| 463 | struct DefaultShaderCode |
| 464 | { |
| 465 | std::string source[ShaderStage::STAGE_MAX_ENUM]; |
| 466 | }; |
| 467 | |
| 468 | Graphics(); |
| 469 | virtual ~Graphics(); |
| 470 | |
| 471 | // Implements Module. |
| 472 | virtual ModuleType getModuleType() const { return M_GRAPHICS; } |
| 473 | |
| 474 | virtual Image *newImage(const Image::Slices &data, const Image::Settings &settings) = 0; |
| 475 | virtual Image *newImage(TextureType textype, PixelFormat format, int width, int height, int slices, const Image::Settings &settings) = 0; |
| 476 | |
| 477 | Quad *newQuad(Quad::Viewport v, double sw, double sh); |
| 478 | Font *newFont(love::font::Rasterizer *data, const Texture::Filter &filter = Texture::defaultFilter); |
| 479 | Font *newDefaultFont(int size, font::TrueTypeRasterizer::Hinting hinting, const Texture::Filter &filter = Texture::defaultFilter); |
| 480 | Video *newVideo(love::video::VideoStream *stream, float dpiscale); |
| 481 | |
| 482 | SpriteBatch *newSpriteBatch(Texture *texture, int size, vertex::Usage usage); |
| 483 | ParticleSystem *newParticleSystem(Texture *texture, int size); |
| 484 | |
| 485 | virtual Canvas *newCanvas(const Canvas::Settings &settings) = 0; |
| 486 | |
| 487 | ShaderStage *newShaderStage(ShaderStage::StageType stage, const std::string &source); |
| 488 | Shader *newShader(const std::string &vertex, const std::string &pixel); |
| 489 | |
| 490 | virtual Buffer *newBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags) = 0; |
| 491 | |
| 492 | Mesh *newMesh(const std::vector<Vertex> &vertices, PrimitiveType drawmode, vertex::Usage usage); |
| 493 | Mesh *newMesh(int vertexcount, PrimitiveType drawmode, vertex::Usage usage); |
| 494 | Mesh *newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, int vertexcount, PrimitiveType drawmode, vertex::Usage usage); |
| 495 | Mesh *newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, vertex::Usage usage); |
| 496 | |
| 497 | Text *newText(Font *font, const std::vector<Font::ColoredString> &text = {}); |
| 498 | |
| 499 | bool validateShader(bool gles, const std::string &vertex, const std::string &pixel, std::string &err); |
| 500 | |
| 501 | /** |
| 502 | * Resets the current color, background color, line style, and so forth. |
| 503 | **/ |
| 504 | void reset(); |
| 505 | |
| 506 | virtual void clear(OptionalColorf color, OptionalInt stencil, OptionalDouble depth) = 0; |
| 507 | virtual void clear(const std::vector<OptionalColorf> &colors, OptionalInt stencil, OptionalDouble depth) = 0; |
| 508 | |
| 509 | virtual void discard(const std::vector<bool> &colorbuffers, bool depthstencil) = 0; |
| 510 | |
| 511 | /** |
| 512 | * Flips buffers. (Rendered geometry is presented on screen). |
| 513 | **/ |
| 514 | virtual void present(void *screenshotCallbackData) = 0; |
| 515 | |
| 516 | /** |
| 517 | * Sets the current graphics display viewport dimensions. |
| 518 | **/ |
| 519 | virtual void setViewportSize(int width, int height, int pixelwidth, int pixelheight) = 0; |
| 520 | |
| 521 | /** |
| 522 | * Sets the current graphics display viewport and initializes the renderer. |
| 523 | * @param width The viewport width. |
| 524 | * @param height The viewport height. |
| 525 | **/ |
| 526 | virtual bool setMode(int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil) = 0; |
| 527 | |
| 528 | /** |
| 529 | * Un-sets the current graphics display mode (uninitializing objects if |
| 530 | * necessary.) |
| 531 | **/ |
| 532 | virtual void unSetMode() = 0; |
| 533 | |
| 534 | /** |
| 535 | * Sets whether the module is active (internal use only.) |
| 536 | **/ |
| 537 | virtual void setActive(bool active) = 0; |
| 538 | |
| 539 | /** |
| 540 | * Gets whether the module is active. Graphics module methods are only |
| 541 | * guaranteed to work when it is active. Calling them otherwise may cause |
| 542 | * the program to crash (or worse.) |
| 543 | * Normally the module will always be active as long as a window exists, it |
| 544 | * may be different on some platforms (especially mobile ones.) |
| 545 | **/ |
| 546 | bool isActive() const; |
| 547 | |
| 548 | /** |
| 549 | * True if a graphics viewport is set. |
| 550 | **/ |
| 551 | bool isCreated() const; |
| 552 | |
| 553 | int getWidth() const; |
| 554 | int getHeight() const; |
| 555 | int getPixelWidth() const; |
| 556 | int getPixelHeight() const; |
| 557 | |
| 558 | double getCurrentDPIScale() const; |
| 559 | double getScreenDPIScale() const; |
| 560 | |
| 561 | /** |
| 562 | * Sets the current constant color. |
| 563 | **/ |
| 564 | virtual void setColor(Colorf c) = 0; |
| 565 | |
| 566 | /** |
| 567 | * Gets current color. |
| 568 | **/ |
| 569 | Colorf getColor() const; |
| 570 | |
| 571 | /** |
| 572 | * Sets the background Color. |
| 573 | **/ |
| 574 | void setBackgroundColor(Colorf c); |
| 575 | |
| 576 | /** |
| 577 | * Gets the current background color. |
| 578 | **/ |
| 579 | Colorf getBackgroundColor() const; |
| 580 | |
| 581 | void setFont(Font *font); |
| 582 | Font *getFont(); |
| 583 | |
| 584 | void setShader(Shader *shader); |
| 585 | void setShader(); |
| 586 | |
| 587 | Shader *getShader() const; |
| 588 | |
| 589 | void setCanvas(RenderTarget rt, uint32 temporaryRTFlags); |
| 590 | void setCanvas(const RenderTargets &rts); |
| 591 | void setCanvas(const RenderTargetsStrongRef &rts); |
| 592 | void setCanvas(); |
| 593 | |
| 594 | RenderTargets getCanvas() const; |
| 595 | bool isCanvasActive() const; |
| 596 | bool isCanvasActive(Canvas *canvas) const; |
| 597 | bool isCanvasActive(Canvas *canvas, int slice) const; |
| 598 | |
| 599 | /** |
| 600 | * Scissor defines a box such that everything outside that box is discarded |
| 601 | * and not drawn. Scissoring is automatically enabled. |
| 602 | * @param rect The rectangle defining the scissor area. |
| 603 | **/ |
| 604 | virtual void setScissor(const Rect &rect) = 0; |
| 605 | void intersectScissor(const Rect &rect); |
| 606 | |
| 607 | /** |
| 608 | * Clears any scissor that has been created. |
| 609 | **/ |
| 610 | virtual void setScissor() = 0; |
| 611 | |
| 612 | /** |
| 613 | * Gets the current scissor box. |
| 614 | * @return Whether the scissor is enabled. |
| 615 | */ |
| 616 | bool getScissor(Rect &rect) const; |
| 617 | |
| 618 | /** |
| 619 | * Enables or disables drawing to the stencil buffer. When enabled, the |
| 620 | * color buffer is disabled. |
| 621 | **/ |
| 622 | virtual void drawToStencilBuffer(StencilAction action, int value) = 0; |
| 623 | virtual void stopDrawToStencilBuffer() = 0; |
| 624 | |
| 625 | /** |
| 626 | * Sets whether stencil testing is enabled. |
| 627 | **/ |
| 628 | virtual void setStencilTest(CompareMode compare, int value) = 0; |
| 629 | void setStencilTest(); |
| 630 | void getStencilTest(CompareMode &compare, int &value) const; |
| 631 | |
| 632 | virtual void setDepthMode(CompareMode compare, bool write) = 0; |
| 633 | void setDepthMode(); |
| 634 | void getDepthMode(CompareMode &compare, bool &write) const; |
| 635 | |
| 636 | void setMeshCullMode(CullMode cull); |
| 637 | CullMode getMeshCullMode() const; |
| 638 | |
| 639 | virtual void setFrontFaceWinding(vertex::Winding winding) = 0; |
| 640 | vertex::Winding getFrontFaceWinding() const; |
| 641 | |
| 642 | /** |
| 643 | * Sets the enabled color components when rendering. |
| 644 | **/ |
| 645 | virtual void setColorMask(ColorMask mask) = 0; |
| 646 | |
| 647 | /** |
| 648 | * Gets the current color mask. |
| 649 | **/ |
| 650 | ColorMask getColorMask() const; |
| 651 | |
| 652 | /** |
| 653 | * Sets the current blend mode. |
| 654 | **/ |
| 655 | virtual void setBlendMode(BlendMode mode, BlendAlpha alphamode) = 0; |
| 656 | |
| 657 | /** |
| 658 | * Gets the current blend mode. |
| 659 | **/ |
| 660 | BlendMode getBlendMode(BlendAlpha &alphamode) const; |
| 661 | |
| 662 | /** |
| 663 | * Sets the default filter for images, canvases, and fonts. |
| 664 | **/ |
| 665 | void setDefaultFilter(const Texture::Filter &f); |
| 666 | |
| 667 | /** |
| 668 | * Gets the default filter for images, canvases, and fonts. |
| 669 | **/ |
| 670 | const Texture::Filter &getDefaultFilter() const; |
| 671 | |
| 672 | /** |
| 673 | * Default Image mipmap filter mode and sharpness values. |
| 674 | **/ |
| 675 | void setDefaultMipmapFilter(Texture::FilterMode filter, float sharpness); |
| 676 | void getDefaultMipmapFilter(Texture::FilterMode *filter, float *sharpness) const; |
| 677 | |
| 678 | /** |
| 679 | * Sets the line width. |
| 680 | * @param width The new width of the line. |
| 681 | **/ |
| 682 | void setLineWidth(float width); |
| 683 | float getLineWidth() const; |
| 684 | |
| 685 | /** |
| 686 | * Sets the line style. |
| 687 | * @param style LINE_ROUGH or LINE_SMOOTH. |
| 688 | **/ |
| 689 | void setLineStyle(LineStyle style); |
| 690 | LineStyle getLineStyle() const; |
| 691 | |
| 692 | /** |
| 693 | * Sets the line join mode. |
| 694 | **/ |
| 695 | void setLineJoin(LineJoin style); |
| 696 | LineJoin getLineJoin() const; |
| 697 | |
| 698 | /** |
| 699 | * Sets the size of points. |
| 700 | **/ |
| 701 | virtual void setPointSize(float size) = 0; |
| 702 | |
| 703 | /** |
| 704 | * Gets the point size. |
| 705 | **/ |
| 706 | float getPointSize() const; |
| 707 | |
| 708 | /** |
| 709 | * Sets whether graphics will be drawn as wireframe lines instead of filled |
| 710 | * triangles (has no effect for drawn points.) |
| 711 | * This should only be used as a debugging tool. The wireframe lines do not |
| 712 | * behave the same as regular love.graphics lines. |
| 713 | **/ |
| 714 | virtual void setWireframe(bool enable) = 0; |
| 715 | |
| 716 | /** |
| 717 | * Gets whether wireframe drawing mode is enabled. |
| 718 | **/ |
| 719 | bool isWireframe() const; |
| 720 | |
| 721 | void captureScreenshot(const ScreenshotInfo &info); |
| 722 | |
| 723 | void draw(Drawable *drawable, const Matrix4 &m); |
| 724 | void draw(Texture *texture, Quad *quad, const Matrix4 &m); |
| 725 | void drawLayer(Texture *texture, int layer, const Matrix4 &m); |
| 726 | void drawLayer(Texture *texture, int layer, Quad *quad, const Matrix4 &m); |
| 727 | void drawInstanced(Mesh *mesh, const Matrix4 &m, int instancecount); |
| 728 | |
| 729 | /** |
| 730 | * Draws text at the specified coordinates |
| 731 | **/ |
| 732 | void print(const std::vector<Font::ColoredString> &str, const Matrix4 &m); |
| 733 | void print(const std::vector<Font::ColoredString> &str, Font *font, const Matrix4 &m); |
| 734 | |
| 735 | /** |
| 736 | * Draws formatted text on screen at the specified coordinates. |
| 737 | **/ |
| 738 | void printf(const std::vector<Font::ColoredString> &str, float wrap, Font::AlignMode align, const Matrix4 &m); |
| 739 | void printf(const std::vector<Font::ColoredString> &str, Font *font, float wrap, Font::AlignMode align, const Matrix4 &m); |
| 740 | |
| 741 | /** |
| 742 | * Draws a series of points at the specified positions. |
| 743 | **/ |
| 744 | void points(const Vector2 *positions, const Colorf *colors, size_t numpoints); |
| 745 | |
| 746 | /** |
| 747 | * Draws a series of lines connecting the given vertices. |
| 748 | * @param coords Vertex positions (v1, ..., vn). If v1 == vn the line will be drawn closed. |
| 749 | * @param count Number of vertices. |
| 750 | **/ |
| 751 | void polyline(const Vector2 *vertices, size_t count); |
| 752 | |
| 753 | /** |
| 754 | * Draws a rectangle. |
| 755 | * @param x Position along x-axis for top-left corner. |
| 756 | * @param y Position along y-axis for top-left corner. |
| 757 | * @param w The width of the rectangle. |
| 758 | * @param h The height of the rectangle. |
| 759 | **/ |
| 760 | void rectangle(DrawMode mode, float x, float y, float w, float h); |
| 761 | |
| 762 | /** |
| 763 | * Variant of rectangle that draws a rounded rectangle. |
| 764 | * @param mode The mode of drawing (line/filled). |
| 765 | * @param x X-coordinate of top-left corner |
| 766 | * @param y Y-coordinate of top-left corner |
| 767 | * @param w The width of the rectangle. |
| 768 | * @param h The height of the rectangle. |
| 769 | * @param rx The radius of the corners on the x axis |
| 770 | * @param ry The radius of the corners on the y axis |
| 771 | * @param points The number of points to use per corner |
| 772 | **/ |
| 773 | void rectangle(DrawMode mode, float x, float y, float w, float h, float rx, float ry, int points); |
| 774 | void rectangle(DrawMode mode, float x, float y, float w, float h, float rx, float ry); |
| 775 | |
| 776 | /** |
| 777 | * Draws a circle using the specified arguments. |
| 778 | * @param mode The mode of drawing (line/filled). |
| 779 | * @param x X-coordinate. |
| 780 | * @param y Y-coordinate. |
| 781 | * @param radius Radius of the circle. |
| 782 | * @param points Number of points to use to draw the circle. |
| 783 | **/ |
| 784 | void circle(DrawMode mode, float x, float y, float radius, int points); |
| 785 | void circle(DrawMode mode, float x, float y, float radius); |
| 786 | |
| 787 | /** |
| 788 | * Draws an ellipse using the specified arguments. |
| 789 | * @param mode The mode of drawing (line/filled). |
| 790 | * @param x X-coordinate of center |
| 791 | * @param y Y-coordinate of center |
| 792 | * @param a Radius in x-direction |
| 793 | * @param b Radius in y-direction |
| 794 | * @param points Number of points to use to draw the circle. |
| 795 | **/ |
| 796 | void ellipse(DrawMode mode, float x, float y, float a, float b, int points); |
| 797 | void ellipse(DrawMode mode, float x, float y, float a, float b); |
| 798 | |
| 799 | /** |
| 800 | * Draws an arc using the specified arguments. |
| 801 | * @param drawmode The mode of drawing (line/filled). |
| 802 | * @param arcmode The type of arc. |
| 803 | * @param x X-coordinate. |
| 804 | * @param y Y-coordinate. |
| 805 | * @param radius Radius of the arc. |
| 806 | * @param angle1 The angle at which the arc begins. |
| 807 | * @param angle2 The angle at which the arc terminates. |
| 808 | * @param points Number of points to use to draw the arc. |
| 809 | **/ |
| 810 | void arc(DrawMode drawmode, ArcMode arcmode, float x, float y, float radius, float angle1, float angle2, int points); |
| 811 | void arc(DrawMode drawmode, ArcMode arcmode, float x, float y, float radius, float angle1, float angle2); |
| 812 | |
| 813 | /** |
| 814 | * Draws a polygon with an arbitrary number of vertices. |
| 815 | * @param mode The type of drawing (line/filled). |
| 816 | * @param coords Vertex positions. |
| 817 | * @param count Vertex array size. |
| 818 | **/ |
| 819 | void polygon(DrawMode mode, const Vector2 *vertices, size_t count, bool skipLastFilledVertex = true); |
| 820 | |
| 821 | /** |
| 822 | * Gets the graphics capabilities (feature support, limit values, and |
| 823 | * supported texture types) of this system. |
| 824 | **/ |
| 825 | const Capabilities &getCapabilities() const; |
| 826 | |
| 827 | /** |
| 828 | * Gets whether the specified pixel format is supported by Canvases or |
| 829 | * Images. |
| 830 | **/ |
| 831 | virtual bool isCanvasFormatSupported(PixelFormat format) const = 0; |
| 832 | virtual bool isCanvasFormatSupported(PixelFormat format, bool readable) const = 0; |
| 833 | virtual bool isImageFormatSupported(PixelFormat format, bool sRGB = false) const = 0; |
| 834 | |
| 835 | /** |
| 836 | * Gets the renderer used by love.graphics. |
| 837 | **/ |
| 838 | virtual Renderer getRenderer() const = 0; |
| 839 | |
| 840 | /** |
| 841 | * Returns system-dependent renderer information. |
| 842 | * Returned strings can vary greatly between systems! Do not rely on it for |
| 843 | * anything! |
| 844 | **/ |
| 845 | virtual RendererInfo getRendererInfo() const = 0; |
| 846 | |
| 847 | /** |
| 848 | * Returns performance-related statistics. |
| 849 | **/ |
| 850 | Stats getStats() const; |
| 851 | |
| 852 | size_t getStackDepth() const; |
| 853 | void push(StackType type = STACK_TRANSFORM); |
| 854 | void pop(); |
| 855 | |
| 856 | const Matrix4 &getTransform() const; |
| 857 | const Matrix4 &getProjection() const; |
| 858 | |
| 859 | void rotate(float r); |
| 860 | void scale(float x, float y = 1.0f); |
| 861 | void translate(float x, float y); |
| 862 | void shear(float kx, float ky); |
| 863 | void origin(); |
| 864 | |
| 865 | void applyTransform(love::math::Transform *transform); |
| 866 | void replaceTransform(love::math::Transform *transform); |
| 867 | |
| 868 | Vector2 transformPoint(Vector2 point); |
| 869 | Vector2 inverseTransformPoint(Vector2 point); |
| 870 | |
| 871 | virtual void draw(const DrawCommand &cmd) = 0; |
| 872 | virtual void draw(const DrawIndexedCommand &cmd) = 0; |
| 873 | virtual void drawQuads(int start, int count, const vertex::Attributes &attributes, const vertex::BufferBindings &buffers, Texture *texture) = 0; |
| 874 | |
| 875 | void flushStreamDraws(); |
| 876 | StreamVertexData requestStreamDraw(const StreamDrawCommand &command); |
| 877 | |
| 878 | static void flushStreamDrawsGlobal(); |
| 879 | |
| 880 | virtual Shader::Language getShaderLanguageTarget() const = 0; |
| 881 | const DefaultShaderCode &getCurrentDefaultShaderCode() const; |
| 882 | |
| 883 | void cleanupCachedShaderStage(ShaderStage::StageType type, const std::string &cachekey); |
| 884 | |
| 885 | template <typename T> |
| 886 | T *getScratchBuffer(size_t count) |
| 887 | { |
| 888 | size_t bytes = sizeof(T) * count; |
| 889 | |
| 890 | if (scratchBuffer.size() < bytes) |
| 891 | scratchBuffer.resize(bytes); |
| 892 | |
| 893 | return (T *) scratchBuffer.data(); |
| 894 | } |
| 895 | |
| 896 | static bool getConstant(const char *in, DrawMode &out); |
| 897 | static bool getConstant(DrawMode in, const char *&out); |
| 898 | static std::vector<std::string> getConstants(DrawMode); |
| 899 | |
| 900 | static bool getConstant(const char *in, ArcMode &out); |
| 901 | static bool getConstant(ArcMode in, const char *&out); |
| 902 | static std::vector<std::string> getConstants(ArcMode); |
| 903 | |
| 904 | static bool getConstant(const char *in, BlendMode &out); |
| 905 | static bool getConstant(BlendMode in, const char *&out); |
| 906 | static std::vector<std::string> getConstants(BlendMode); |
| 907 | |
| 908 | static bool getConstant(const char *in, BlendAlpha &out); |
| 909 | static bool getConstant(BlendAlpha in, const char *&out); |
| 910 | static std::vector<std::string> getConstants(BlendAlpha); |
| 911 | |
| 912 | static bool getConstant(const char *in, LineStyle &out); |
| 913 | static bool getConstant(LineStyle in, const char *&out); |
| 914 | static std::vector<std::string> getConstants(LineStyle); |
| 915 | |
| 916 | static bool getConstant(const char *in, LineJoin &out); |
| 917 | static bool getConstant(LineJoin in, const char *&out); |
| 918 | static std::vector<std::string> getConstants(LineJoin); |
| 919 | |
| 920 | static bool getConstant(const char *in, Feature &out); |
| 921 | static bool getConstant(Feature in, const char *&out); |
| 922 | |
| 923 | static bool getConstant(const char *in, SystemLimit &out); |
| 924 | static bool getConstant(SystemLimit in, const char *&out); |
| 925 | |
| 926 | static bool getConstant(const char *in, StackType &out); |
| 927 | static bool getConstant(StackType in, const char *&out); |
| 928 | static std::vector<std::string> getConstants(StackType); |
| 929 | |
| 930 | // Default shader code (a shader is always required internally.) |
| 931 | static DefaultShaderCode defaultShaderCode[Shader::STANDARD_MAX_ENUM][Shader::LANGUAGE_MAX_ENUM][2]; |
| 932 | |
| 933 | protected: |
| 934 | |
| 935 | struct DisplayState |
| 936 | { |
| 937 | Colorf color = Colorf(1.0, 1.0, 1.0, 1.0); |
| 938 | Colorf backgroundColor = Colorf(0.0, 0.0, 0.0, 1.0); |
| 939 | |
| 940 | BlendMode blendMode = BLEND_ALPHA; |
| 941 | BlendAlpha blendAlphaMode = BLENDALPHA_MULTIPLY; |
| 942 | |
| 943 | float lineWidth = 1.0f; |
| 944 | LineStyle lineStyle = LINE_SMOOTH; |
| 945 | LineJoin lineJoin = LINE_JOIN_MITER; |
| 946 | |
| 947 | float pointSize = 1.0f; |
| 948 | |
| 949 | bool scissor = false; |
| 950 | Rect scissorRect = Rect(); |
| 951 | |
| 952 | CompareMode stencilCompare = COMPARE_ALWAYS; |
| 953 | int stencilTestValue = 0; |
| 954 | |
| 955 | CompareMode depthTest = COMPARE_ALWAYS; |
| 956 | bool depthWrite = false; |
| 957 | |
| 958 | CullMode meshCullMode = CULL_NONE; |
| 959 | vertex::Winding winding = vertex::WINDING_CCW; |
| 960 | |
| 961 | StrongRef<Font> font; |
| 962 | StrongRef<Shader> shader; |
| 963 | |
| 964 | RenderTargetsStrongRef renderTargets; |
| 965 | |
| 966 | ColorMask colorMask = ColorMask(true, true, true, true); |
| 967 | |
| 968 | bool wireframe = false; |
| 969 | |
| 970 | Texture::Filter defaultFilter = Texture::Filter(); |
| 971 | |
| 972 | Texture::FilterMode defaultMipmapFilter = Texture::FILTER_LINEAR; |
| 973 | float defaultMipmapSharpness = 0.0f; |
| 974 | }; |
| 975 | |
| 976 | struct StreamBufferState |
| 977 | { |
| 978 | StreamBuffer *vb[2]; |
| 979 | StreamBuffer *indexBuffer = nullptr; |
| 980 | |
| 981 | PrimitiveType primitiveMode = PRIMITIVE_TRIANGLES; |
| 982 | vertex::CommonFormat formats[2]; |
| 983 | StrongRef<Texture> texture; |
| 984 | Shader::StandardShader standardShaderType = Shader::STANDARD_DEFAULT; |
| 985 | int vertexCount = 0; |
| 986 | int indexCount = 0; |
| 987 | |
| 988 | StreamBuffer::MapInfo vbMap[2]; |
| 989 | StreamBuffer::MapInfo indexBufferMap = StreamBuffer::MapInfo(); |
| 990 | |
| 991 | StreamBufferState() |
| 992 | { |
| 993 | vb[0] = vb[1] = nullptr; |
| 994 | formats[0] = formats[1] = vertex::CommonFormat::NONE; |
| 995 | vbMap[0] = vbMap[1] = StreamBuffer::MapInfo(); |
| 996 | } |
| 997 | }; |
| 998 | |
| 999 | struct TemporaryCanvas |
| 1000 | { |
| 1001 | Canvas *canvas; |
| 1002 | int framesSinceUse; |
| 1003 | |
| 1004 | TemporaryCanvas(Canvas *c) |
| 1005 | : canvas(c) |
| 1006 | , framesSinceUse(0) |
| 1007 | {} |
| 1008 | }; |
| 1009 | |
| 1010 | virtual ShaderStage *newShaderStageInternal(ShaderStage::StageType stage, const std::string &cachekey, const std::string &source, bool gles) = 0; |
| 1011 | virtual Shader *newShaderInternal(ShaderStage *vertex, ShaderStage *pixel) = 0; |
| 1012 | virtual StreamBuffer *newStreamBuffer(BufferType type, size_t size) = 0; |
| 1013 | |
| 1014 | virtual void setCanvasInternal(const RenderTargets &rts, int w, int h, int pixelw, int pixelh, bool hasSRGBcanvas) = 0; |
| 1015 | |
| 1016 | virtual void initCapabilities() = 0; |
| 1017 | virtual void getAPIStats(int &shaderswitches) const = 0; |
| 1018 | |
| 1019 | void createQuadIndexBuffer(); |
| 1020 | |
| 1021 | Canvas *getTemporaryCanvas(PixelFormat format, int w, int h, int samples); |
| 1022 | |
| 1023 | void restoreState(const DisplayState &s); |
| 1024 | void restoreStateChecked(const DisplayState &s); |
| 1025 | |
| 1026 | void pushTransform(); |
| 1027 | void pushIdentityTransform(); |
| 1028 | void popTransform(); |
| 1029 | |
| 1030 | int width; |
| 1031 | int height; |
| 1032 | int pixelWidth; |
| 1033 | int pixelHeight; |
| 1034 | |
| 1035 | bool created; |
| 1036 | bool active; |
| 1037 | |
| 1038 | bool writingToStencil; |
| 1039 | |
| 1040 | StrongRef<love::graphics::Font> defaultFont; |
| 1041 | |
| 1042 | std::vector<ScreenshotInfo> pendingScreenshotCallbacks; |
| 1043 | |
| 1044 | StreamBufferState streamBufferState; |
| 1045 | |
| 1046 | std::vector<Matrix4> transformStack; |
| 1047 | Matrix4 projectionMatrix; |
| 1048 | |
| 1049 | std::vector<double> pixelScaleStack; |
| 1050 | |
| 1051 | std::vector<DisplayState> states; |
| 1052 | std::vector<StackType> stackTypeStack; |
| 1053 | |
| 1054 | std::vector<TemporaryCanvas> temporaryCanvases; |
| 1055 | |
| 1056 | int canvasSwitchCount; |
| 1057 | int drawCalls; |
| 1058 | int drawCallsBatched; |
| 1059 | |
| 1060 | Buffer *quadIndexBuffer; |
| 1061 | |
| 1062 | Capabilities capabilities; |
| 1063 | |
| 1064 | Deprecations deprecations; |
| 1065 | |
| 1066 | static const size_t MAX_USER_STACK_DEPTH = 128; |
| 1067 | static const int MAX_TEMPORARY_CANVAS_UNUSED_FRAMES = 16; |
| 1068 | |
| 1069 | private: |
| 1070 | |
| 1071 | void checkSetDefaultFont(); |
| 1072 | int calculateEllipsePoints(float rx, float ry) const; |
| 1073 | |
| 1074 | std::vector<uint8> scratchBuffer; |
| 1075 | |
| 1076 | std::unordered_map<std::string, ShaderStage *> cachedShaderStages[ShaderStage::STAGE_MAX_ENUM]; |
| 1077 | |
| 1078 | static StringMap<DrawMode, DRAW_MAX_ENUM>::Entry drawModeEntries[]; |
| 1079 | static StringMap<DrawMode, DRAW_MAX_ENUM> drawModes; |
| 1080 | |
| 1081 | static StringMap<ArcMode, ARC_MAX_ENUM>::Entry arcModeEntries[]; |
| 1082 | static StringMap<ArcMode, ARC_MAX_ENUM> arcModes; |
| 1083 | |
| 1084 | static StringMap<BlendMode, BLEND_MAX_ENUM>::Entry blendModeEntries[]; |
| 1085 | static StringMap<BlendMode, BLEND_MAX_ENUM> blendModes; |
| 1086 | |
| 1087 | static StringMap<BlendAlpha, BLENDALPHA_MAX_ENUM>::Entry blendAlphaEntries[]; |
| 1088 | static StringMap<BlendAlpha, BLENDALPHA_MAX_ENUM> blendAlphaModes; |
| 1089 | |
| 1090 | static StringMap<LineStyle, LINE_MAX_ENUM>::Entry lineStyleEntries[]; |
| 1091 | static StringMap<LineStyle, LINE_MAX_ENUM> lineStyles; |
| 1092 | |
| 1093 | static StringMap<LineJoin, LINE_JOIN_MAX_ENUM>::Entry lineJoinEntries[]; |
| 1094 | static StringMap<LineJoin, LINE_JOIN_MAX_ENUM> lineJoins; |
| 1095 | |
| 1096 | static StringMap<Feature, FEATURE_MAX_ENUM>::Entry featureEntries[]; |
| 1097 | static StringMap<Feature, FEATURE_MAX_ENUM> features; |
| 1098 | |
| 1099 | static StringMap<SystemLimit, LIMIT_MAX_ENUM>::Entry systemLimitEntries[]; |
| 1100 | static StringMap<SystemLimit, LIMIT_MAX_ENUM> systemLimits; |
| 1101 | |
| 1102 | static StringMap<StackType, STACK_MAX_ENUM>::Entry stackTypeEntries[]; |
| 1103 | static StringMap<StackType, STACK_MAX_ENUM> stackTypes; |
| 1104 | |
| 1105 | }; // Graphics |
| 1106 | |
| 1107 | } // graphics |
| 1108 | } // love |
| 1109 | |
| 1110 | #endif // LOVE_GRAPHICS_GRAPHICS_H |
| 1111 | |