summaryrefslogtreecommitdiff
path: root/src/include/main.h
blob: 375d8da2727ad9f5f8d0b06b7cb35ca00ac12f02 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
#include <glad.h>

#include <stdio.h>
#if WINDOWS
#include <windows.h>
#else
#include <sys/mman.h>
#include <unistd.h>
#endif

#if ARM
#include <arm_neon.h>
#include <arm_sve.h>
#else
#include <smmintrin.h>
#endif

#include "imgui.h"
#include "imgui_impl_sdl.h"
#include "imgui_impl_opengl3.h"
#include <SDL.h>
#if defined(IMGUI_IMPL_OPENGL_ES2)
#include <SDL_opengles2.h>
#else
#include <SDL_opengl.h>
#endif

#define STB_IMAGE_IMPLEMENTATION
#define STBI_FAILURE_USERMSG
#include "stb_image.h"

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"

// TODO(fox): Used for thumbnails. The renderer could be expanded to do this
// much more efficiently.
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "stb_image_resize.h"

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavutil/avutil.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
}



#include "defines.h"
#include "my_math.h"
#include "structs.h"
#if STABLE
#include "stable_diffusion.h"
#endif
#include "memory.h"
#include "nanovg.h"

enum instruction_mode {
    instruction_mode_scalar,
#if ARM
    instruction_mode_neon,
#else
    instruction_mode_sse,
    instruction_mode_avx
#endif
};

static char* BlendmodeNames[] = {
    "Normal",
    "Multiply",
    "Color Burn",
    "Linear Burn",
    "Add",
    "Screen",
    "Overlay",
    "Soft Light",
    "Hard Light",
    "Subtract",
    "Divide",
    "Difference"
};

enum blend_mode
{
    blend_normal,
    blend_multiply,
    blend_colorburn,
    blend_linearburn,
    blend_add,
    blend_screen,
    blend_overlay,
    blend_softlight,
    blend_hardlight,
    blend_subtract,
    blend_divide,
    blend_difference
};

#define STRING_SIZE (1024 - sizeof(uint8))  // TODO(fox): Paths above STRING_SIZE length aren't handled properly.
struct block_string {
    uint8 Occupied;
    char Char[STRING_SIZE];
};

struct bitmap_cache_status
{
    uint32 Block_End;
};

enum cache_entry_type
{
    cache_entry_type_assert,
    cache_entry_type_comp,
    cache_entry_type_source
};

struct cache_entry
{
    uint8 IsOccupied;
    uint8 IsCached;
    uint64 CycleTime;
    uint32 Block_StartIndex;
    enum cache_entry_type Type;
    uint32 TypeInfo;
    uint32 TypeInfo_Sub;
};

enum interpolation_type
{
    interpolation_type_linear,
    interpolation_type_bezier,
    interpolation_type_hold
};

struct bezier_point {
    uint8 Occupied;
    v2 Pos[3];
    interpolation_type Type;
    bool32 IsSelected;
    uint8 PointSelect[3];
    uint8 Color;
};

struct block_bezier {
    uint8 Occupied;
    bezier_point Point[MAX_KEYFRAMES_PER_BLOCK];
};

enum selection_type
{
    selection_type_none,
    selection_type_layer,
    selection_type_keyframe
};

struct clipboard_channel {
    void *Name;
    uint16 LayerOffset;
    uint16 KeyframeCount;
};

struct clipboard_contents {
    selection_type Type;
    clipboard_channel Channel[16];
    uint16 ChannelCount;
};

struct layer_bitmap_state {
    // Image and video
    bool32 ToUpdate = 1;

    // GL state
    // gl_effect_layer Test;
    // gl_effect_layer TestM;

    // Video state
    int32 CurrentFrame = -1;  // The last frame number rendered to the bitmap. -1 gurantees a load upon layer creation.
    void *AVInfo;             // Internal data containing current frame info
};

struct render_state
{
    struct layer_bitmap_state Bitmap[MAX_LAYERS];
    cache_entry Entry[2048];
};

struct render_queue_item
{
    bool32 Type;
    v2 Pos;
};

struct layer_transforms
{
    real32 x;
    real32 y;
    real32 ax;
    real32 ay;
    real32 rotation;
    real32 scale;
};

struct render_queue
{
    uint16 Playhead;
    uint16 CurrentIdx;
    render_queue_item Item[512];
};

enum focused_window
{
    focus_viewport,
    focus_properties,
    focus_timeline
};

struct sorted_property_array
{
    uint32 KeyframeCount;
    uint32 MinYIndex;
    uint32 MaxYIndex;
};

struct sorted_comp_array
{
    uint32 LayerCount;
    uint32 FakeLayerCount;
    uint32 CurrentSortIndex;        // Used intermediately in the sorting algorithm
    real32 DisplaySize;
};

struct sorted_layer_array
{
    uint16 Block_Layer_Index;
    bool32 IsFake;
    real32 SortedOffset;
    real32 DisplayOffset;
    uint16 Sorted_Effect_Index[MAX_EFFECTS];
    uint16 SortedPropertyStart;
    uint16 SortedKeyframeStart;
    real32 Interact_Offset[4];
};

struct sorted_file
{
    sorted_comp_array *CompArray;
    sorted_layer_array *LayerArray;
    sorted_property_array *PropertyStart;
    uint16 *PropertyArray;
    uint16 *SourceArray;        // sorted by 'recency,' wip for stablediffusion stuff
    uint16 TempSourceCount;
    uint64 Layer_SortSize;
    uint64 Property_SortSize;
    uint64 Source_SortSize;
};


struct shape_options {
    int Visibility;
    v4 FillCol =  {1, 1, 1, 1};
    v4 StrokeCol =  {0, 0, 0, 1};
    float StrokeWidth = 0;
    nvg_line_cap LineJoinType = NVG_SQUARE;
    nvg_line_cap LineCapType = NVG_MITER;
    real32 Roundness;
};

struct shape_layer {
    uint16 Block_Bezier_Index[MAX_KEYFRAME_BLOCKS];
    uint16 Block_Bezier_Count;
    uint16 Point_Count;
    bool32 IsClosed;
    bool32 Contiguous = 1; // No points have been deleted/added, so sorting isn't needed.
    // NOTE(fox): Point vals are normalized based on whatever these values are!
    // They get set once the shape becomes a shape layer!
    real32 Width;
    real32 Height;
};

enum timeline_mode
{
    timeline_mode_default,
    timeline_mode_graph
};

struct pen_state {
};

struct brush_state
{
    ImVec2 UIPos;               // Initial position when ctrl is held
    real32 Size = 256;          // Maxes at 1024 for now
    real32 Hardness = 0.55f;     // From 1 to 100
    real32 Spacing = 1.0f;
    bool32 EraseMode = 0;
    GLuint GLTexture;
    v2 PrevPos;
    void *PaintBuffer;
    void *TransientBitmap;
    uint32 LayerToPaint_Index = -1;
    rectangle CacheBounds = { 99999, 99999, -99999, -99999 };
};

enum interact_type
{
    interact_type_none,
    interact_type_timeline_scrub,
    interact_type_slider_scrub,
    interact_type_layer_move,
    interact_type_layer_timeadjust,
    interact_type_viewport_selection,
    interact_type_viewport_transform,
    interact_type_viewport_transform_gizmo,
    interact_type_viewport_duplicate,
    interact_type_viewport_slide,
    interact_type_keyframe_move,
    interact_type_keyframe_scale,
    interact_type_keyframe_rotate,
    interact_type_brush
};

char *ToolName[] {
    "Move",
    "Point move",
    "Crop",
    "Brush",
    "Slide",
    "Pen",
    "Rectangle"
};

enum tool {
    tool_default,
    tool_default_pointmove,
    tool_crop,
    tool_brush,
    tool_slide,
    tool_pen,
    tool_rectangle,
    tool_count
};

struct interact_transform
{
    v2 Min;
    v2 Max;
    real32 Radians;
    real32 RadianOffset;
    v2 Position;
    v2 OGCenter;
    v2 NewCenter;
    real32 Scale = 1.0f;
    ImVec2 OGPos;
    uint32 TransformMode;
};

struct interact_slide_layer
{
    uint16 Index;
    real32 Offset[4];
};

enum hotkey_input
{
    hotkey_none,
    hotkey_newlayer_source,
    hotkey_newlayer_paint,
    hotkey_newlayer_shape,
    hotkey_deletelayer,
    hotkey_duplicatelayer,
    hotkey_undo,
    hotkey_redo,
};

enum property_display_type
{
    property_display_type_standard,
    property_display_type_blendmode,
    property_display_type_color
};

struct header_property
{
    char *Name;
    real32 DefaultValue;
    property_display_type DisplayType;
    real32 MinVal;
    real32 MaxVal;
    bool32 AlwaysInteger;

};

struct gl_effect_layer {
    bool32 Initialized;
    GLuint Texture;
    GLuint FramebufferObject;
    uint32 Color_Renderbuffer;
    uint32 Stencil_Renderbuffer;
};

enum gl_shape_renderflags
{
    gl_renderflag_fill    = 1 << 0,
    gl_renderflag_stroke  = 1 << 1,
    gl_renderflag_convex  = 1 << 2,
    gl_renderflag_texture = 1 << 3,
    gl_renderflag_blend   = 1 << 4
};

struct gl_data
{
	int Type;
    void *StrokeData;
	uint32 StrokeCount;
	v4 StrokeCol;
	void *FillData;
	uint32 FillCount;
	v4 FillCol;
    layer_transforms T;
	real32 Width;
	real32 Height;
	void *BitmapData;
	blend_mode BlendMode;
	int RenderMode;

	v2 BlendMin;
	v2 BlendMax;
};

struct gl_viewport_data
{
	ImVec2 ViewportMin;
	ImVec2 ViewportMax;
	ImVec2 ViewportSize;
	int ViewportDisplay;
    int Width;
	int Height;
	int BytesPerPixel;
    ImVec2 UIPos;
    ImVec2 UIZoom;
    real32 UIScale;
    v4 BGColor;
    gl_data *LayerEntry[MAX_LAYERS];
    int LayerCount;
};

enum effect_display_type
{
    effect_display_type_standard,
    effect_display_type_levels,
    effect_display_type_curves
};

struct block_effect
{
    uint8 Occupied;
    char ID[8];
    bool32 IsToggled;
    uint32 Block_Property_Index[MAX_PROPERTIES_PER_EFFECT];
    real32 ExtraData[16];
};

struct header_effect
{
    char *Name;
    char *ID;       // Eight-letter string that's used in the actual file
	void (*func)(real32 *, int, int, int, void *, uint16);
    uint16 PropertyStartIndex;
    uint16 Property_Count;
    effect_display_type DisplayType;
    bool32 UseGL;
    uint32 GLShaderIndex;
};

enum imgui_popups
{
    popup_none,
    popup_saveas,
    popup_keybinds
};

enum option_sortflag
{
    sortflag_up        = 1 << 0,
    sortflag_furthest  = 1 << 1
};

struct project_state
{
    bool32 UpdateKeyframes = 0;
    bool32 UpdateFrame = 1;         // only refreshes frame; set UpdateKeyframes to update animation
    bool32 UpdateScreen = 1;        // refreshes entire UI; influenced by raw key/mouse input
    bool32 DebugDisableCache = 1;

    // TODO(fox): Group inconsequential state UI into one thing?
    bool32 DuplicateMode = sortflag_furthest | sortflag_up;
    bool32 ShapeMode = 0;
    bool32 ViewportEnabled = 0;
    bool32 SelectionMode = 1;

    uint16 PreviousSelection[MAX_LAYERS];
    uint16 PreviousSelectionCount = 0;

    // bad
    uint32 CachedFrameCount;
    int32 LastCachedFrame = -10000;

    bool32 MenuFocused = 0;

    uint64 HotFramePerf = 0;

    uint32 AVCount;

    render_state Render;
    render_queue Queue;

    int32 Frame_Current;
    tool Tool = tool_default;
    // GLuint ToolIconTex[(int)tool_count];
    pen_state Pen = {};
    brush_state Brush;

#if STABLE
    int32 CurlActive = 0;
    char JSONPayload[1024*1024*4];
    real32 SDPercentDone;
    real32 SDTimeEstimate;
    real64 SDTimer;
#endif

    header_effect Effect[128];
    header_property Property[512];
    uint16 Playhead_Effect;
    uint16 Playhead_Property;

    int32 PreviewLayer = -1;
    int32 PreviewSource = -1;

    hotkey_input HotkeyInput;

    void *Dump1;
    void *Dump2;

    char DummyName[512];
    char DummyName2[512];

    bool32 IsRunning = 1;
    bool32 IsPlaying;
    bool32 PlayAudio;
    int32 FramePlayingCount;
    bool32 FirstFrame = 1;
    int32 AudioLayerIndex = -1;

    void *ClipboardBuffer;
    uint64 ClipboardSize;

    int16 MostRecentlySelectedLayer = -1;

    // NOTE(fox): Try to use this only where you actually need it (the
    // ambiguous case of copying keyframes versus layers), since this state
    // transfer will get buggy if you expand it to everything.
    selection_type RecentSelectionType = selection_type_none;

    interact_transform Interact_Transform;
    interact_transform Interact_Transform_Prev;
    interact_type Interact_Active;
    int32 Interact_Modifier;
    bool32 Interact_OutOfDrag;       // TODO(fox): replace this
    real32 Interact_Offset[12];
    real32 Interact_Dup_Previous[2];
    void *Interact_Address;
    int Interact_Count;

    // whether duplicated layers get created above or below
    int DuplicateDirection = -1;

    ImGuiID RightDock;

    // NOTE(fox): We need to keep track of when the user changes the CurrentValue of a
    // channel that has keyframes on it (i.e. CurrentValue will now evaluate to
    // its previous value unless the user adds a new keyframe to the channel)
    // so we can purge the cache if the user changes to a different frame.
    int UncommitedKeyframe;

    int32 Initializing = 3;

    int32 MsgTime; // currently in "frames"
    char *Msg;

    imgui_popups ImGuiPopups;
    char Filename[512];

    ImGuiTextFilter filter;     // This filter API is pretty ballin'.
    bool32 RerouteEffects;      // Allows shift+space hotkey to gain focus on the effects panel.

    ImDrawListSplitter Test;
    ImDrawListSplitter Split_KeybindUI;

    int32  Warp_X = 0;
    int32  Warp_Y = 0;
    bool32 Warp_WantSetPos = false;
    ImVec2 Warp_PositionToSet;
    real32 Warp_PositionInitial;
    int32  Warp_Direction;

    uint32 InteractTransformMode;   // Whether a drag on the Shift+T UI is scale (1), rotation (2), or position (3).

    timeline_mode TimelineMode;

    bool32 BoxSelect;

    focused_window FocusedWindow;       // Convenience for adding window-specific hotkeys.
    bool32 SetFocus;
    v2 LastClickedPoint = V2(1, 1);

};

// UI info that's saved to the file and is not part of the history tree
struct ui
{
    ImVec2 CompZoom;                    // In screen pixels, not percentage.
    ImVec2 CompPos;

    int Mode = 1;

    // Under 1 is zoomed in!
    ImVec2 TimelinePercentZoomed;
    ImVec2 TimelinePercentOffset;

    ImVec2 GraphZoomSize;
    ImVec2 GraphMoveSize;

    v4 Color =  {1, 1, 1, 1};
    v4 AltColor = {0, 0, 0, 1};
    bool32 IsPrimary;
    v4 BGColor =  {0, 0, 0, 1};

#if STABLE
    sd_state SD;
    bool32 StableEnabled = 0;
#endif

    shape_layer Shape;
    shape_options ShapeOpt;

    ImU32 LayerColors[16] = {
        0xff8b1f1f,
        0xffc25909,
        0xff57c20a,
        0xff203d6a,
        0xffa48fb7,
        0xffd14061,
        0xff38b683,
        0xff3fdbe5,
        0xffc9c9c9,
        0xff978489,
        0xfffaf5ab,
        0xff101010,
        0xffa024ca,
        0xfffae920,
        0xff208dfa,
        0xfffa2051
    };
};


struct project_data
{
    uint8 Occupied;
    uint16 Layer_Count;
    uint16 Source_Count;
    uint16 Comp_Count;
    uint16 PrincipalCompIndex;
    ui UI;
};

struct block_composition
{
    uint8 Occupied;

    uint16 Name_String_Index;

    uint16 Width;
    uint16 Height;
    uint16 BytesPerPixel;
    uint16 FPS;

    uint32 Frame_Count;
     int32 Frame_Start;
     int32 Frame_End;
};

enum source_type {
    source_type_none,
    source_type_principal,
    source_type_principal_temp,
    source_type_file
};

struct block_source
{
    uint8 Occupied;

    bool32 IsSelected;

    uint16 Path_String_Index;
    uint16 Name_String_Index;

    // Only used for type_principal
    uint16 Bitmap_Index;

    uint16 Width;
    uint16 Height;
    uint16 BytesPerPixel;

    // LibAV specific
    real32 FPS;
    bool32 HasAudio;
    bool32 HasVideo;

    uint32 RelativeTimestamp;
    GLuint ThumbnailTex;

    source_type Type;
};

struct property_channel {
    uint8 Occupied;
    uint16 Block_Bezier_Index[MAX_KEYFRAME_BLOCKS];
    uint16 Block_Bezier_Count;
    // NOTE(fox): Don't use this in sorted circumstances; use the one in sorted_property_array instead!
    uint16 Keyframe_Count;  

    int32 Identifier;

    real32 CurrentValue;
    real32 MaxVal;
    real32 MinVal;
    bool32 AlwaysInteger;
    real32 ScrubVal;           // increment when dragging on sliders, etc.

    bool32 IsToggled;
};

char *DefaultChannel[] = { "X Position", "Y Position", "Anchor X", "Anchor Y",
                          "Rotation", "Scale", "Opacity", "Frame Number" };

struct block_layer {
    uint8 Occupied;

    bool32 IsPrecomp;
    bool32 IsShapeLayer;
    bool32 Precomp_Toggled;
    // NOTE(fox): References a precomp index if IsPrecomp is true, not a source index.
    uint16 Block_Source_Index;
    uint16 Block_String_Index;
    // References the precomp that the layer belongs to.
    uint16 Block_Composition_Index;

    uint16 Block_Effect_Index[MAX_EFFECTS];
    uint16 Block_Effect_Count;

    shape_layer Shape;
    shape_options ShapeOpt;

    blend_mode BlendMode;

    union
    {
        property_channel Property[8];
        struct
        {
            property_channel x;
            property_channel y;
            property_channel ax;
            property_channel ay;
            property_channel rotation;
            property_channel scale;
            property_channel opacity;
            property_channel time;
        };
    };

    bool32 IsVisible;
    bool32 IsLocked;
    // Valid values this can be:
    //  0x01 - standard select
    //  0x02 - precomp layer
    //  0x04 - transient box selection state when shift is held
    bool32 IsSelected;
    bool32 IsAdjustment;

    // NOTE(fox): I use these in some places without calling
    // Interact_Evaluate_Layer(), because I'm assuming it's impossible for
    // layer dragging to happen in those contexts. Check for this if weird bugs appear.
    int32 Frame_Start;
    int32 Frame_End;
    // This is what changes when the layer is dragged. It also marks the starting frame for video footage.
    int32 Frame_Offset;

    real32 Vertical_Offset;
    real32 Vertical_Height = 1;

    uint16 ColIndex;
};

struct render_byte_info {
    uint32 MaskPixel;
    uint32 ByteOffset;
    uint32 Bits;
    real32 Normalized;
};

struct transform_info {
    real32 XAxisPX;
    real32 XAxisPY;
    real32 YAxisPX;
    real32 YAxisPY;

    real32 LayerWidth;
    real32 LayerHeight;
    real32 LayerBytesPerPixel;
    real32 LayerPitch;
    render_byte_info LayerBits;

    real32 BufferWidth;
    real32 BufferHeight;
    real32 BufferBytesPerPixel;
    real32 BufferPitch;
    render_byte_info BufferBits;

    real32 LayerOpacity;
    real32 OriginX;
    real32 OriginY;
    blend_mode BlendMode;

    bool32 IsAdjustment;

    rectangle ClipRect;
    void *SourceBuffer;
};

struct direct_info {
    real32 BufferWidth;
    real32 BufferHeight;
    real32 BufferBytesPerPixel;
    real32 BufferPitch;
    render_byte_info BufferBits;

    real32 Opacity;

    blend_mode BlendMode;
    rectangle ClipRect;
    void *SourceBuffer;

    bool32 SwapActive;
    bool32 OnlyBlendAlpha;
};

struct brush_info {
    uint32 BrushLength;
    rectangle LayerBounds;
    uint32 LayerPitch;
    uint32 BrushPitch;
    int32 ExtraX;
    int32 ExtraY;
    render_byte_info LayerBits;
    render_byte_info BrushBits;
    int BytesPerPixel;
    int SourceWidth;
    int SourceBytesPerPixel;
    void *SourceBuffer;
    void *BrushBuffer;
    real32 R_Brush;
    real32 G_Brush;
    real32 B_Brush;
    real32 A_Brush;
    bool32 EraseMode;
    uint8 *BrushRow;
};

enum render_type {
    render_type_main,
    render_type_notransform,
    render_type_notransform_swap,
    render_type_brush
};

struct render_entry {
    void *RenderData;
    void *OutputBuffer;
    render_type RenderType;
    rectangle RenderRegion;
};


#include "ffmpeg_backend.h"
#include "layer.h"
#include "debug.h"
#include "all.h"

#include "imgui_internal_widgets.h"

#include "imgui_ops.h"