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 | |