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
54namespace love
55{
56
57namespace graphics
58{
59
60class SpriteBatch;
61class ParticleSystem;
62class Text;
63class Video;
64class Buffer;
65
66typedef Optional<Colorf> OptionalColorf;
67
68const 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 **/
74void setGammaCorrect(bool gammacorrect);
75
76/**
77 * Gets whether global gamma correction is enabled.
78 **/
79bool 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 **/
86void 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 **/
93void unGammaCorrectColor(Colorf &c);
94
95Colorf gammaCorrectColor(const Colorf &c);
96Colorf unGammaCorrectColor(const Colorf &c);
97
98bool isDebugEnabled();
99
100class Graphics : public Module
101{
102public:
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
933protected:
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
1069private:
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