summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFox Caminiti <fox@foxcam.net>2022-08-01 20:03:12 -0400
committerFox Caminiti <fox@foxcam.net>2022-08-01 20:04:43 -0400
commitb26f27d9e3fd44ec5775accdc3666a339684be4c (patch)
treee5c7b8b48f5597904190529f90d71a8526ca9800
parent7d3dcee5b370c05065eb409ad5c21d0bc64790b1 (diff)
large changes to bitmap structure
-rw-r--r--.gitignore1
-rw-r--r--bitmap_calls.cpp107
-rwxr-xr-xbuild.sh33
-rw-r--r--caching.cpp14
-rw-r--r--createcalls.cpp466
-rw-r--r--debug.h8
-rw-r--r--defines.h40
-rw-r--r--effects.cpp45
-rw-r--r--ffmpeg_backend.cpp (renamed from video.cpp)179
-rw-r--r--ffmpeg_backend.h22
-rw-r--r--functions.h18
-rw-r--r--keyframes.cpp40
-rw-r--r--layer.cpp30
-rw-r--r--main.cpp158
-rw-r--r--main.h134
-rw-r--r--memory.cpp4
-rw-r--r--my_imgui_internal_widgets.cpp294
-rw-r--r--my_imgui_internal_widgets.h11
-rw-r--r--my_imgui_widgets.cpp160
-rw-r--r--paint.cpp4
-rw-r--r--prenderer.cpp118
-rw-r--r--strings.cpp9
-rw-r--r--threading.cpp8
-rw-r--r--ui.cpp2
24 files changed, 1177 insertions, 728 deletions
diff --git a/.gitignore b/.gitignore
index 36f971e..5ef7aca 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
bin/*
+compile_commands.json
diff --git a/bitmap_calls.cpp b/bitmap_calls.cpp
index 132aec5..09d1cb1 100644
--- a/bitmap_calls.cpp
+++ b/bitmap_calls.cpp
@@ -6,28 +6,29 @@
// 0 - store in 4x4 chunks
// 1 - unpack to 1xwidth
-internal void
-Convert4x4Chunk(pixel_buffer *Buffer, uint8 Which)
+void Bitmap_ConvertPacking(void *Buffer, void *DestBuffer, uint16 Width, uint16 Height, uint16 BytesPerPixel, uint16 Which)
{
- uint8 *Src = (uint8 *)Buffer->OriginalBuffer;
- uint8 *Temp = (uint8 *)Buffer->EffectBuffer;
- uint32 RemainderPixels = Buffer->Width % 4;
- for (uint32 Y = 0; Y < Buffer->Height; Y++) {
+ uint8 *Src = (uint8 *)Buffer;
+ uint8 *Temp = (uint8 *)DestBuffer;
+ uint32 RemainderPixels = Width % 4;
+ for (uint32 Y = 0; Y < Height; Y++) {
uint32 X = 0;
- while (X < Buffer->Width - RemainderPixels) {
+ while (X < Width - RemainderPixels) {
+ uint16 WidthP, HeightP;
+ Bitmap_CalcPackedDimensions(Width, Height, &WidthP, &HeightP);
uint32 XLookup = (X >> 2)*16 + (X % 4);
- uint32 YLookup = (Y >> 2)*(Buffer->FullWidth*4) + (Y % 4)*4;
+ uint32 YLookup = (Y >> 2)*(WidthP*4) + (Y % 4)*4;
uint32 PixelToSeek = XLookup + YLookup;
uint8 *DPixel, *Pixel;
if (Which == 0) {
- DPixel = Temp + PixelToSeek*Buffer->BytesPerPixel;
- Pixel = Src + Y*Buffer->Width*4 + X*Buffer->BytesPerPixel;
+ DPixel = Temp + PixelToSeek*BytesPerPixel;
+ Pixel = Src + Y*Width*4 + X*BytesPerPixel;
} else {
- Pixel = Src + PixelToSeek*Buffer->BytesPerPixel;
- DPixel = Temp + Y*Buffer->Width*4 + X*Buffer->BytesPerPixel;
+ Pixel = Src + PixelToSeek*BytesPerPixel;
+ DPixel = Temp + Y*Width*4 + X*BytesPerPixel;
}
- if (InstructionMode == sse_enabled || InstructionMode == avx_enabled) {
+ if (InstructionMode == instruction_mode_sse || InstructionMode == instruction_mode_avx) {
__m128i Row = _mm_loadu_si128((__m128i *)Pixel);
_mm_storeu_si128((__m128i *)DPixel, Row);
X+=4;
@@ -36,17 +37,19 @@ Convert4x4Chunk(pixel_buffer *Buffer, uint8 Which)
X++;
}
}
- while (X < Buffer->Width) {
+ while (X < Width) {
+ uint16 WidthP, HeightP;
+ Bitmap_CalcPackedDimensions(Width, Height, &WidthP, &HeightP);
uint32 XLookup = (X >> 2)*16 + (X % 4);
- uint32 YLookup = (Y >> 2)*(Buffer->FullWidth*4) + (Y % 4)*4;
+ uint32 YLookup = (Y >> 2)*(WidthP*4) + (Y % 4)*4;
uint32 PixelToSeek = XLookup + YLookup;
uint8 *DPixel, *Pixel;
if (Which == 0) {
- DPixel = Temp + PixelToSeek*Buffer->BytesPerPixel;
- Pixel = Src + Y*Buffer->Width*4 + X*Buffer->BytesPerPixel;
+ DPixel = Temp + PixelToSeek*BytesPerPixel;
+ Pixel = Src + Y*Width*4 + X*BytesPerPixel;
} else {
- Pixel = Src + PixelToSeek*Buffer->BytesPerPixel;
- DPixel = Temp + Y*Buffer->Width*4 + X*Buffer->BytesPerPixel;
+ Pixel = Src + PixelToSeek*BytesPerPixel;
+ DPixel = Temp + Y*Width*4 + X*BytesPerPixel;
}
*(uint32 *)DPixel = *(uint32 *)Pixel;
@@ -56,27 +59,23 @@ Convert4x4Chunk(pixel_buffer *Buffer, uint8 Which)
}
// TODO(fox): Replace this in the future.
-internal void *
+#if 0
+static void *
MoveImportToBitmap(memory *Memory, pixel_buffer *Raster, void *Input)
{
uint8 *Row = ((uint8 *)Input);
- void *Output = AllocateMemory(Memory, Raster->FullWidth * Raster->FullHeight * Raster->BytesPerPixel, B_Scratch);
+ // void *Output = AllocateMemory(Memory, Bitmap_CalcTotalBytes(Raster->Width, Raster->Height, Raster->BytesPerPixel), B_Layers);
uint8 *Row2 = ((uint8 *)Output);
uint64 bytes = 0;
- uint16 ByteOffset = Raster->BytesPerPixel;
- if (InstructionMode == avx_enabled)
- ByteOffset = 8*Raster->BytesPerPixel;
- else if (InstructionMode == avx_enabled)
- ByteOffset = 4*Raster->BytesPerPixel;
-
- uint64 TotalBytes = Raster->Height*Raster->Width*Raster->BytesPerPixel;
+ uint16 ByteOffset = Bitmap_CalculateByteOffset(BytesPerPixel);
+ uint64 TotalBytes = Bitmap_CalculateTotalBytes(Width, Height, BytesPerPixel);
uint64 RemainderBytes = TotalBytes % ByteOffset;
while (bytes <= TotalBytes - RemainderBytes) {
uint8 *Pixel = (uint8 *)Row + bytes;
uint8 *Pixel2 = (uint8 *)Row2 + bytes;
- if (InstructionMode == sse_enabled || InstructionMode == avx_enabled) {
+ if (InstructionMode == instruction_mode_sse || InstructionMode == instruction_mode_avx) {
__m128i OutputPixel = _mm_loadu_si128((__m128i *)Pixel);
_mm_storeu_si128((__m128i *)Pixel2, OutputPixel);
bytes += 4*Raster->BytesPerPixel;
@@ -93,28 +92,24 @@ MoveImportToBitmap(memory *Memory, pixel_buffer *Raster, void *Input)
}
return Output;
}
+#endif
-internal void
-ClearBuffer(pixel_buffer *Raster, void *Buffer)
+static void
+Bitmap_Clear(void *Buffer, uint16 Width, uint16 Height, uint16 BytesPerPixel)
{
uint8 *Row = (uint8 *)Buffer;
__m256i Zero8 = _mm256_setzero_si256();
__m128i Zero = _mm_setzero_si128();
-
uint64 bytes = 0;
- uint16 ByteOffset = Raster->BytesPerPixel;
- if (InstructionMode == avx_enabled)
- ByteOffset = 8*Raster->BytesPerPixel;
- else if (InstructionMode == avx_enabled)
- ByteOffset = 4*Raster->BytesPerPixel;
- uint64 TotalBytes = Raster->FullHeight*Raster->FullWidth*Raster->BytesPerPixel;
+ uint16 ByteOffset = Bitmap_CalcByteOffset(BytesPerPixel);
+ uint64 TotalBytes = Bitmap_CalcTotalBytes(Width, Height, BytesPerPixel);
while (bytes < TotalBytes) {
uint8 *Pixel = Row + bytes;
- if (InstructionMode == avx_enabled) {
+ if (InstructionMode == instruction_mode_avx) {
_mm256_storeu_si256((__m256i *)Pixel, Zero8);
- } else if (InstructionMode == sse_enabled) {
+ } else if (InstructionMode == instruction_mode_sse) {
_mm_storeu_si128((__m128i *)Pixel, Zero);
} else {
*(uint32 *)Pixel = 0x00000000;
@@ -122,10 +117,10 @@ ClearBuffer(pixel_buffer *Raster, void *Buffer)
bytes += ByteOffset;
}
}
-
+#if 0
// 0 - original -> effect
// 1 - effect -> original
-internal void
+static void
CopyToBuffer(pixel_buffer *Raster, uint16 Which)
{
uint8 *Row, *Row2;
@@ -138,19 +133,14 @@ CopyToBuffer(pixel_buffer *Raster, uint16 Which)
}
uint64 bytes = 0;
- uint16 ByteOffset = Raster->BytesPerPixel;
- if (InstructionMode == avx_enabled)
- ByteOffset = 8*Raster->BytesPerPixel;
- else if (InstructionMode == avx_enabled)
- ByteOffset = 4*Raster->BytesPerPixel;
-
- uint64 TotalBytes = Raster->FullHeight*Raster->FullWidth*Raster->BytesPerPixel;
+ uint16 ByteOffset = Bitmap_CalculateByteOffset(BytesPerPixel);
+ uint64 TotalBytes = Bitmap_CalculateTotalBytes(Width, Height, BytesPerPixel);
uint64 RemainderBytes = TotalBytes % ByteOffset;
while (bytes <= TotalBytes - RemainderBytes) {
uint8 *Pixel = (uint8 *)Row + bytes;
uint8 *Pixel2 = (uint8 *)Row2 + bytes;
- if (InstructionMode == sse_enabled || InstructionMode == avx_enabled) {
+ if (InstructionMode == instruction_mode_sse || InstructionMode == instruction_mode_avx) {
__m128i OutputPixel = _mm_loadu_si128((__m128i *)Pixel);
_mm_storeu_si128((__m128i *)Pixel2, OutputPixel);
bytes += 4*Raster->BytesPerPixel;
@@ -167,7 +157,7 @@ CopyToBuffer(pixel_buffer *Raster, uint16 Which)
}
}
-internal void
+static void
BitmapPackRGB(pixel_buffer *Buffer) {
Assert(Buffer->Pitch);
Convert4x4Chunk(Buffer, 0);
@@ -175,7 +165,7 @@ BitmapPackRGB(pixel_buffer *Buffer) {
ClearBuffer(Buffer, Buffer->EffectBuffer);
}
-internal void
+static void
OutputToViewport(pixel_buffer *CompBuffer, project_state *State, GLuint textureID) {
Convert4x4Chunk(CompBuffer, 1);
EndRenderState(State);
@@ -184,7 +174,7 @@ OutputToViewport(pixel_buffer *CompBuffer, project_state *State, GLuint textureI
CompBuffer->EffectBuffer);
}
-internal void
+static void
DebugFillSolid(pixel_buffer *Raster, v4 Color)
{
uint32 ColS = ColToUint32(Color);
@@ -194,18 +184,18 @@ DebugFillSolid(pixel_buffer *Raster, v4 Color)
uint64 bytes = 0;
uint16 ByteOffset = Raster->BytesPerPixel;
- if (InstructionMode == avx_enabled)
+ if (InstructionMode == instruction_mode_avx)
ByteOffset = 8*Raster->BytesPerPixel;
- else if (InstructionMode == avx_enabled)
+ else if (InstructionMode == instruction_mode_sse)
ByteOffset = 4*Raster->BytesPerPixel;
uint64 TotalBytes = Raster->FullHeight*Raster->FullWidth*Raster->BytesPerPixel;
while (bytes < TotalBytes) {
uint8 *Pixel = Row + bytes;
- if (InstructionMode == avx_enabled) {
+ if (InstructionMode == instruction_mode_avx) {
_mm256_storeu_si256((__m256i *)Pixel, Col8);
- } else if (InstructionMode == sse_enabled) {
+ } else if (InstructionMode == instruction_mode_sse) {
_mm_storeu_si128((__m128i *)Pixel, Col);
} else {
*(uint32 *)Pixel = ColS;
@@ -214,7 +204,7 @@ DebugFillSolid(pixel_buffer *Raster, v4 Color)
}
}
-internal void
+static void
DebugBitmap(pixel_buffer *Raster)
{
uint8 asda = 0x0;
@@ -233,3 +223,4 @@ DebugBitmap(pixel_buffer *Raster)
}
}
}
+#endif
diff --git a/build.sh b/build.sh
index 35ac264..433bfc6 100755
--- a/build.sh
+++ b/build.sh
@@ -26,12 +26,17 @@ FFMPEG_LIBS="
libavutil
"
+# IMGUI_FILES="
+# imgui/imgui
+# imgui/imgui_demo
+# imgui/imgui_draw
+# imgui/imgui_tables
+# imgui/imgui_widgets
+# my_imgui_internal_widgets
+# "
+
IMGUI_FILES="
- imgui
- imgui_demo
- imgui_draw
- imgui_tables
- imgui_widgets
+ my_imgui_internal_widgets
"
IMGUI_FILES_IMPL="
@@ -51,12 +56,12 @@ fi
imgui() {
for i in $IMGUI_FILES
do
- clang $IMGUI_FLAGS -o bin/$i.o imgui/$i.cpp
- done
- for i in $IMGUI_FILES_IMPL
- do
- clang $IMGUI_FLAGS -o bin/$i.o imgui/backends/$i.cpp
+ clang $IMGUI_FLAGS -o bin/$i.o $i.cpp
done
+# for i in $IMGUI_FILES_IMPL
+# do
+# clang $IMGUI_FLAGS -o bin/$i.o imgui/backends/$i.cpp
+# done
}
if [[ "$OSTYPE" =~ ^darwin ]]; then
@@ -65,7 +70,9 @@ else
SDL_ARGS="`sdl2-config --cflags` -lGL -ldl `sdl2-config --libs`"
fi
-# imgui
+imgui
+
+ # -lm $(pkg-config --cflags --libs $FFMPEG_LIBS) -MJresult.json
if [[ "$WINDOWS" == 1 ]]; then
clang++ -g $WARNING_FLAGS -target x86_64-pc-windows-gnu -march=x86-64-v3 -I .. -Iimgui -Iimgui/backends \
@@ -74,9 +81,9 @@ clang++ -g $WARNING_FLAGS -target x86_64-pc-windows-gnu -march=x86-64-v3 -I .. -
-lmingw32 -lopengl32 -lSDL2main -lSDL2 -llibavcodec -llibswscale -llibavformat -llibavutil \
-o bin/real2d
else
-clang main.cpp $WARNING_FLAGS -g -O0 -march=native -o bin/real2d bin/*.o \
+clang main.cpp $WARNING_FLAGS -g -march=native -o bin/real2d bin/*.o \
-std=c++11 -lstdc++ -Iimgui -Iimgui/backends \
$SDL_ARGS \
-I . \
- -lm $(pkg-config --cflags --libs $FFMPEG_LIBS)
+ -lm -I /usr/local/include ~/.local/src/ffmpeg/bin/*.so
fi
diff --git a/caching.cpp b/caching.cpp
index d84377a..c35189e 100644
--- a/caching.cpp
+++ b/caching.cpp
@@ -1,5 +1,6 @@
-internal void
+#if 0
+static void
CacheFrame(cache *Cache, pixel_buffer *CompBuffer)
{
@@ -33,7 +34,7 @@ CacheFrame(cache *Cache, pixel_buffer *CompBuffer)
}
}
-internal void
+static void
FetchCache(cache *Cache, pixel_buffer *CompBuffer)
{
@@ -67,7 +68,7 @@ FetchCache(cache *Cache, pixel_buffer *CompBuffer)
}
}
-internal void
+static void
InteractToComp(pixel_buffer *CompBuffer, cache_pool *Cache)
{
int MinX = 0;
@@ -114,15 +115,14 @@ InteractToComp(pixel_buffer *CompBuffer, cache_pool *Cache)
}
}
-internal void
+static void
UncacheFrames(int16 Min, int16 Max, cache_pool *Cache)
{
for (int16 i = Min; i < Max; i++)
Cache->Frame[i].Cached = false;
};
-#if 0
-internal void
+static void
CacheKeyframeAtIndex(uint16 i, struct property_channel *Property, cache_pool *Cache)
{
Assert(Property->NumberOfKeyframes > 0);
@@ -140,7 +140,7 @@ CacheKeyframeAtIndex(uint16 i, struct property_channel *Property, cache_pool *Ca
}
}
-internal void
+static void
SortAndCacheKeyframeAtFrame(uint16 f, struct property_channel *Property, cache_pool *Cache)
{
Assert(Property->NumberOfKeyframes > 0);
diff --git a/createcalls.cpp b/createcalls.cpp
index 7088694..42ab9b1 100644
--- a/createcalls.cpp
+++ b/createcalls.cpp
@@ -1,4 +1,4 @@
-internal void
+static void
IncrementFrame(project_data *File, int16 Amount) {
if ((File->CurrentFrame <= 0 && Amount < File->StartFrame) || (File->CurrentFrame >= File->EndFrame)) {
File->CurrentFrame = 0;
@@ -7,46 +7,70 @@ IncrementFrame(project_data *File, int16 Amount) {
}
}
-internal void
-CalculateFull(pixel_buffer *Buffer) {
- uint16 ExtraWidth = 4 - (Buffer->Width % 4);
+static void
+Bitmap_CalcPackedDimensions(uint16 Width, uint16 Height, uint16 *WidthP, uint16 *HeightP) {
+ uint16 ExtraWidth = 4 - (Width % 4);
if (ExtraWidth == 4)
ExtraWidth = 0;
- uint16 ExtraHeight = 4 - (Buffer->Height % 4);
+ uint16 ExtraHeight = 4 - (Height % 4);
if (ExtraHeight == 4)
ExtraHeight = 0;
- Buffer->FullWidth = Buffer->Width + ExtraWidth;
- Buffer->FullHeight = Buffer->Height + ExtraHeight;
+ *WidthP = Width + ExtraWidth;
+ *HeightP = Height + ExtraHeight;
}
-internal pixel_buffer
-CreateBuffer(int Width, int Height, memory *Memory)
-{
- pixel_buffer Buffer = {};
- Buffer.BytesPerPixel = 4;
- Buffer.Width = Width;
- Buffer.Height = Height;
- CalculateFull(&Buffer);
- Buffer.Pitch = Buffer.FullWidth*Buffer.BytesPerPixel;
- Buffer.OriginalBuffer = AllocateMemory(Memory, Buffer.FullWidth * Buffer.FullHeight * Buffer.BytesPerPixel, B_Scratch);
- Buffer.EffectBuffer = AllocateMemory(Memory, Buffer.FullWidth * Buffer.FullHeight * Buffer.BytesPerPixel, B_Scratch);
- Buffer.ToUpdate = true;
- return Buffer;
+static uint16
+Bitmap_CalcByteOffset(uint16 BytesPerPixel) {
+ uint16 ByteOffset = BytesPerPixel;
+ if (InstructionMode == instruction_mode_avx)
+ ByteOffset = 8*BytesPerPixel;
+ if (InstructionMode == instruction_mode_sse)
+ ByteOffset = 4*BytesPerPixel;
+ return ByteOffset;
}
-internal void
-AddSource(project_data *File, memory *Memory, char *Path)
+static uint64
+Bitmap_CalcTotalBytes(uint16 Width, uint16 Height, uint16 BytesPerPixel) {
+ uint16 WidthP, HeightP;
+ Bitmap_CalcPackedDimensions(Width, Height, &WidthP, &HeightP);
+ uint64 TotalBytes = (uint64)WidthP*HeightP*BytesPerPixel;
+ return TotalBytes;
+}
+
+static bool32
+Source_Generate(project_data *File, memory *Memory, char *Path)
{
- int16 a = File->NumberOfSources++;
- Assert(a < MAX_SOURCES);
- if (Path == NULL) {
- File->Source[a] = (char *)AllocateMemory(Memory, STRING_SIZE, F_Strings);
- } else {
- File->Source[a] = Path;
+ Assert(File->NumberOfSources < MAX_SOURCES);
+ source *Source = &File->Source[File->NumberOfSources];
+
+ bool32 Found = 0;
+
+ int w, h;
+ if (stbi_info(Path, &w, &h, NULL)) {
+ Source->Info.Width = w;
+ Source->Info.Height = h;
+ Source->SourceType = source_type_image;
+ Found = true;
+ }
+
+ if (!Found && AV_IsFileSupported(Path)) {
+ Source->SourceType = source_type_video;
+ AV_CodecInfo_Init(Path, Source, Memory);
+ Found = true;
+ }
+
+ if (Found) {
+ Source->Info.BytesPerPixel = 4;
+ Source->Path = Path;
+ File->NumberOfSources++;
+ return 1;
}
+
+ return 0;
}
-internal pixel_buffer
+ /*
+static pixel_buffer
LoadImage(memory *Memory, char *filename)
{
pixel_buffer Buffer = {};
@@ -69,110 +93,9 @@ LoadImage(memory *Memory, char *filename)
return Buffer;
}
-internal pixel_buffer
-CreateSolidBitmap(memory *Memory, uint16 Height, uint16 Width, v4 Color) {
- pixel_buffer Buffer = {};
- Buffer.BytesPerPixel = 4;
- Buffer.Height = Height;
- Buffer.Width = Width;
- CalculateFull(&Buffer);
- Buffer.Pitch = Buffer.FullWidth*Buffer.BytesPerPixel;
- Buffer.OriginalBuffer = AllocateMemory(Memory, Buffer.FullHeight * Buffer.FullWidth * Buffer.BytesPerPixel, B_Scratch);
- Buffer.EffectBuffer = AllocateMemory(Memory, Buffer.FullHeight * Buffer.FullWidth * Buffer.BytesPerPixel, B_Scratch);
- DebugFillSolid(&Buffer, Color);
- BitmapPackRGB(&Buffer);
- Buffer.ToUpdate = true;
- return Buffer;
-}
-
-internal pixel_buffer
-CreateDebugBitmap(memory *Memory, uint16 Height, uint16 Width) {
- pixel_buffer Buffer = {};
- Buffer.BytesPerPixel = 4;
- Buffer.Height = Height;
- Buffer.Width = Width;
- CalculateFull(&Buffer);
- Buffer.Pitch = Buffer.FullWidth*Buffer.BytesPerPixel;
- Buffer.OriginalBuffer = AllocateMemory(Memory, Buffer.FullHeight * Buffer.FullWidth * Buffer.BytesPerPixel, B_Scratch);
- Buffer.EffectBuffer = AllocateMemory(Memory, Buffer.FullHeight * Buffer.FullWidth * Buffer.BytesPerPixel, B_Scratch);
- DebugBitmap(&Buffer);
- BitmapPackRGB(&Buffer);
- Buffer.ToUpdate = true;
- return Buffer;
-}
-
-
-internal void
-DrawHistogram(project_layer *Layer, pixel_buffer *UIBuffer, void *Scratch, memory *Memory, sdl_input Input, project_state *State,
- rectangle Box)
-{
- uint16 Padding = 20; //UI->LayerPadding / 5;
- uint16 Margin = 100;
-
- uint16 *Levels = (uint16 *)Scratch;
-
- uint16 *Mean = (Levels + 256*7);
-
- uint32 Color = 0;
- uint32 AltColor = ColToUint32(V4(0.1,0.1,0.1,1.0));
-
- // this is a bad idea
- real32 *Zoom = (real32 *)(Levels + 256*6);
- if (*Zoom < 0.0f)
- *Zoom = 0.0f;
- uint16 *SelectedChannel = (uint16 *)(Levels + 256*6 + 3);
-
- if (*SelectedChannel == 0) {
- Color = ColToUint32(V4(0.6,0.6,0.6,1.0));
- } else if (*SelectedChannel == 1) {
- Levels += 256;
- Color = ColToUint32(V4(0.6,0.0,0.0,1.0));
- } else if (*SelectedChannel == 2) {
- Levels += 256*2;
- Color = ColToUint32(V4(0.0,0.6,0.0,1.0));
- } else if (*SelectedChannel == 3) {
- Levels += 256*3;
- Color = ColToUint32(V4(0.0,0.0,0.6,1.0));
- } else if (*SelectedChannel == 4) {
- Levels += 256*4;
- Color = ColToUint32(V4(0.9,0.9,0.9,1.0));
- }
-
-
- /*
- if (TestRectangle(Box, Input.Mouse) &&
- Input.MouseButton[0].IsDown)
- {
- State->ArbitrarySlide = 1;
- State->Sliding.RandomPointer = Zoom;
- }
*/
- uint8 *Row = ((uint8 *)UIBuffer->OriginalBuffer +
- UIBuffer->BytesPerPixel +
- UIBuffer->Pitch);
- for (int Y = 0;
- Y > Box.Min.y;
- Y--)
- {
- uint32 *Pixel = (uint32 *)Row + Box.Min.x;
- for(int X = Box.Min.x;
- X < Box.Max.x;
- ++X)
- {
- real32 Span = (Box.Max.x - Box.Min.x) / 256.0f;
- int16 XLocal = (X - Box.Min.x) / Span;
- int16 YLocal = -(Y - Box.Max.y);
- if (*(Levels + XLocal) > (YLocal * RoundReal32ToInt32(*Zoom)) && XLocal < 256)
- *Pixel++ = Color;
- else
- *Pixel++ = AltColor;
- }
- Row -= UIBuffer->Pitch;
- }
-}
-
-internal property_channel
+static property_channel
InitFloatProperty(char *Name, real32 Val, real32 ScrubVal, real32 MinVal = PROPERTY_REAL_MIN, real32 MaxVal = PROPERTY_REAL_MAX) {
property_channel Property = {};
Property.Name = Name;
@@ -185,66 +108,55 @@ InitFloatProperty(char *Name, real32 Val, real32 ScrubVal, real32 MinVal = PROPE
return Property;
}
-internal bool32
-IsSupportedFile(source_type *Type, char *filename) {
- bool32 Result = 0;
- if (stbi_info(filename, NULL, NULL, NULL)) {
- *Type = source_image;
- Result = 1;
- } else if (TestAV(filename)) {
- *Type = source_video;
- Result = 1;
- }
- return Result;
-}
-internal void
-CreateRenderInfo(project_layer *Layer, memory *Memory, project_data File, source_type Type, char *filename)
+static void
+CreateKeyframeBlock(property_channel *Property, memory *Memory)
{
- if (Type == source_image) {
- Layer->RenderInfo = AllocateMemory(Memory, sizeof(image_source), P_SourceData);
- image_source *Source = (image_source *)Layer->RenderInfo;
- Source->Raster = LoadImage(Memory, filename);
- Layer->SourceType = source_image;
-
- Layer->x.CurrentValue.f = 1280/2;
- Layer->y.CurrentValue.f = 720/2;
- Layer->StartFrame = 0;
- Layer->EndFrame = File.EndFrame;
- }
- else if (Type == source_video) {
- Layer->RenderInfo = AllocateMemory(Memory, sizeof(video_source), P_SourceData);
- video_source *Source = (video_source *)Layer->RenderInfo;
- InitAV(filename, &Source->AV);
-
- Layer->SourceType = source_video;
- Source->VideoCurrentFrame = -1;
+ int16 a = Property->NumberOfKeyframeBlocks++;
+ Assert(a < MAX_KEYFRAME_BLOCKS);
- int32 Width = Source->AV.VideoCodecContext->width;
- int32 Height = Source->AV.VideoCodecContext->height;
- Source->Raster = CreateBuffer(Width, Height, Memory);
+ Property->KeyframeBlock[a] = (keyframe_block *)AllocateMemory(Memory, sizeof(keyframe_block), F_Keyframes);
+}
- Layer->x.CurrentValue.f = 1280/2;
- Layer->y.CurrentValue.f = 720/2;
- Layer->StartFrame = 0;
- Layer->EndFrame = File.EndFrame;
- } else {
- Assert(0);
- }
+static void
+PostMsg(project_state *State, char *msg)
+{
+ State->MsgTime = 120;
+ State->Msg = msg;
}
+/*
+static project_layer *
+CreateSolidLayer(project_data *File, memory *Memory, uint16 Width, uint16 Height, v4 Col)
+{
+ project_layer *Layer = CreateLayer(File, Memory);
+ Layer->RenderInfo = AllocateMemory(Memory, sizeof(source_image), P_SourceData);
+ source_image *Source = (source_image *)Layer->RenderInfo;
+ Source->Raster = CreateSolidBitmap(Memory, Width, Height, Col);
+ Layer->SourceType = source_type_image;
+ return Layer;
+}
-internal void
-CreateKeyframeBlock(property_channel *Property, memory *Memory)
+static project_layer *
+CreateDebugLayer(project_data *File, memory *Memory, uint16 Width, uint16 Height, int i)
{
- int16 a = Property->NumberOfKeyframeBlocks++;
- Assert(a < MAX_KEYFRAME_BLOCKS);
+ project_layer *Layer = CreateLayer(File, Memory);
+ Layer->RenderInfo = AllocateMemory(Memory, sizeof(source_image), P_SourceData);
+ source_image *Source = (source_image *)Layer->RenderInfo;
+ Source->Raster = CreateDebugBitmap(Memory, Width, Height);
+ Layer->SourceType = source_type_image;
+ return Layer;
+}
+*/
- Property->KeyframeBlock[a] = (keyframe_block *)AllocateMemory(Memory, sizeof(keyframe_block), F_Keyframes);
+void * Layer_AllocateBitmap(memory *Memory, uint16 Width, uint16 Height, uint16 BytesPerPixel)
+{
+ uint64 TotalBytes = Bitmap_CalcTotalBytes(Width, Height, BytesPerPixel);
+ void *Address = AllocateMemory(Memory, TotalBytes, B_LayerBitmaps);
+ return Address;
}
-internal project_layer *
-CreateLayer(project_data *File, memory *Memory)
+project_layer * Layer_Init(project_data *File, memory *Memory)
{
int16 a = File->NumberOfLayers++;
Assert(a < MAX_LAYERS);
@@ -266,54 +178,28 @@ CreateLayer(project_data *File, memory *Memory)
return File->Layer[a];
}
-internal void
-PostMsg(project_state *State, char *msg)
-{
- State->MsgTime = 120;
- State->Msg = msg;
-}
-
-internal void
-CreateLayerFromSource(project_data *File, project_state *State, memory *Memory, char *filename)
-{
- source_type Type = source_none;
- if (IsSupportedFile(&Type, filename)) {
- project_layer *Layer = CreateLayer(File, Memory);
- CreateRenderInfo(Layer, Memory, *File, Type, filename);
- State->UpdateFrame = true;
- State->DemoButton = true;
- } else {
- PostMsg(State, "File open fail...");
- }
-}
-
-
-internal project_layer *
-CreateSolidLayer(project_data *File, memory *Memory, uint16 Width, uint16 Height, v4 Col)
-{
- project_layer *Layer = CreateLayer(File, Memory);
- Layer->RenderInfo = AllocateMemory(Memory, sizeof(image_source), P_SourceData);
- image_source *Source = (image_source *)Layer->RenderInfo;
- Source->Raster = CreateSolidBitmap(Memory, Width, Height, Col);
- Layer->SourceType = source_image;
- return Layer;
+static void
+Layer_UpdateBitmap(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, int32 CurrentFrame) {
+ AV_LoadVideoFrame(Source, BitmapInfo, Memory, CurrentFrame);
+ // UpdateEffects(Layer, Memory);
}
-internal project_layer *
-CreateDebugLayer(project_data *File, memory *Memory, uint16 Width, uint16 Height, int i)
-{
- project_layer *Layer = CreateLayer(File, Memory);
- Layer->RenderInfo = AllocateMemory(Memory, sizeof(image_source), P_SourceData);
- image_source *Source = (image_source *)Layer->RenderInfo;
- Source->Raster = CreateDebugBitmap(Memory, Width, Height);
- Layer->SourceType = source_image;
- return Layer;
-}
-
-internal void
+static void
LoadTestFootage(project_data *File, project_state *State, memory *Memory)
{
- CreateLayerFromSource(File, State, Memory, "../asset/24.mp4");
+ if (!Source_Generate(File, Memory, "../asset/24.mp4"))
+ PostMsg(State, "File open fail...");
+ source *Source = &File->Source[0];
+ project_layer *Layer = Layer_Init(File, Memory);
+ Layer->Source = Source;
+ AV_PacketInfo_Init(&Layer->BitmapInfo, Memory);
+ uint16 Height = Source->Info.Height;
+ uint16 Width = Source->Info.Width;
+ uint16 BytesPerPixel = Source->Info.BytesPerPixel;
+ Layer_AllocateBitmap(Memory, Width, Height, BytesPerPixel);
+
+ SelectLayer(File->Layer[0], State, 0);
+ // AddEffect(File->Layer[0], Memory, 2);
// project_layer *Layer1 = CreateDebugLayer(&File, &Memory, 9, 14);
// project_layer *Layer1 = CreateSolidLayer(&File, &Memory, 9, 13, V4(1.0, 1.0, 1.0, 1.0));
// Layer1->x.CurrentValue.f = 7;
@@ -322,9 +208,10 @@ LoadTestFootage(project_data *File, project_state *State, memory *Memory)
// Layer1->EndFrame = File.EndFrame;
}
-internal void
+static void
CreateDemoScene(project_data *File, memory *Memory)
{
+#if 0
project_layer *Layer1 = CreateSolidLayer(File, Memory, 720, 1280, V4(0.0, 0.0, 0.0, 1.0));
Layer1->x.CurrentValue.f = 1280/2;
Layer1->y.CurrentValue.f = 720/2;
@@ -350,9 +237,11 @@ CreateDemoScene(project_data *File, memory *Memory)
ManualKeyframeInsertF(&Layer3->x, Memory, 60, Layer3->x.CurrentValue.f+(1280/3));
Layer3->x.IsToggled = true;
Layer3->y.IsToggled = true;
+#endif
}
-internal void
+#if 0
+static void
CreateGrid(project_data *File, memory *Memory) {
uint16 Amount = 8;
real32 XInc = File->Width / Amount;
@@ -370,3 +259,128 @@ CreateGrid(project_data *File, memory *Memory) {
}
}
}
+#endif
+#if 0
+static void
+DrawHistogram(project_layer *Layer, pixel_buffer *UIBuffer, void *Scratch, memory *Memory, sdl_input Input, project_state *State,
+ rectangle Box)
+{
+ uint16 Padding = 20; //UI->LayerPadding / 5;
+ uint16 Margin = 100;
+
+ uint16 *Levels = (uint16 *)Scratch;
+
+ uint16 *Mean = (Levels + 256*7);
+
+ uint32 Color = 0;
+ uint32 AltColor = ColToUint32(V4(0.1,0.1,0.1,1.0));
+
+ // this is a bad idea
+ real32 *Zoom = (real32 *)(Levels + 256*6);
+ if (*Zoom < 0.0f)
+ *Zoom = 0.0f;
+ uint16 *SelectedChannel = (uint16 *)(Levels + 256*6 + 3);
+
+ if (*SelectedChannel == 0) {
+ Color = ColToUint32(V4(0.6,0.6,0.6,1.0));
+ } else if (*SelectedChannel == 1) {
+ Levels += 256;
+ Color = ColToUint32(V4(0.6,0.0,0.0,1.0));
+ } else if (*SelectedChannel == 2) {
+ Levels += 256*2;
+ Color = ColToUint32(V4(0.0,0.6,0.0,1.0));
+ } else if (*SelectedChannel == 3) {
+ Levels += 256*3;
+ Color = ColToUint32(V4(0.0,0.0,0.6,1.0));
+ } else if (*SelectedChannel == 4) {
+ Levels += 256*4;
+ Color = ColToUint32(V4(0.9,0.9,0.9,1.0));
+ }
+
+
+ /*
+ if (TestRectangle(Box, Input.Mouse) &&
+ Input.MouseButton[0].IsDown)
+ {
+ State->ArbitrarySlide = 1;
+ State->Sliding.RandomPointer = Zoom;
+ }
+ */
+
+ uint8 *Row = ((uint8 *)UIBuffer->OriginalBuffer +
+ UIBuffer->BytesPerPixel +
+ UIBuffer->Pitch);
+ for (int Y = 0;
+ Y > Box.Min.y;
+ Y--)
+ {
+ uint32 *Pixel = (uint32 *)Row + Box.Min.x;
+ for(int X = Box.Min.x;
+ X < Box.Max.x;
+ ++X)
+ {
+ real32 Span = (Box.Max.x - Box.Min.x) / 256.0f;
+ int16 XLocal = (X - Box.Min.x) / Span;
+ int16 YLocal = -(Y - Box.Max.y);
+ if (*(Levels + XLocal) > (YLocal * RoundReal32ToInt32(*Zoom)) && XLocal < 256)
+ *Pixel++ = Color;
+ else
+ *Pixel++ = AltColor;
+ }
+ Row -= UIBuffer->Pitch;
+ }
+}
+
+static pixel_buffer
+CreateSolidBitmap(memory *Memory, uint16 Height, uint16 Width, v4 Color) {
+ pixel_buffer Buffer = {};
+ Buffer.BytesPerPixel = 4;
+ Buffer.Height = Height;
+ Buffer.Width = Width;
+ CalculateFull(&Buffer);
+ Buffer.Pitch = Buffer.FullWidth*Buffer.BytesPerPixel;
+ Buffer.OriginalBuffer = AllocateMemory(Memory, Buffer.FullHeight * Buffer.FullWidth * Buffer.BytesPerPixel, B_Scratch);
+ Buffer.EffectBuffer = AllocateMemory(Memory, Buffer.FullHeight * Buffer.FullWidth * Buffer.BytesPerPixel, B_Scratch);
+ DebugFillSolid(&Buffer, Color);
+ BitmapPackRGB(&Buffer);
+ Buffer.ToUpdate = true;
+ return Buffer;
+}
+
+static pixel_buffer
+CreateDebugBitmap(memory *Memory, uint16 Height, uint16 Width) {
+ pixel_buffer Buffer = {};
+ Buffer.BytesPerPixel = 4;
+ Buffer.Height = Height;
+ Buffer.Width = Width;
+ CalculateFull(&Buffer);
+ Buffer.Pitch = Buffer.FullWidth*Buffer.BytesPerPixel;
+ Buffer.OriginalBuffer = AllocateMemory(Memory, Buffer.FullHeight * Buffer.FullWidth * Buffer.BytesPerPixel, B_Scratch);
+ Buffer.EffectBuffer = AllocateMemory(Memory, Buffer.FullHeight * Buffer.FullWidth * Buffer.BytesPerPixel, B_Scratch);
+ DebugBitmap(&Buffer);
+ BitmapPackRGB(&Buffer);
+ Buffer.ToUpdate = true;
+ return Buffer;
+}
+
+/*
+{
+ Layer->RenderInfo = AllocateMemory(Memory, sizeof(source_image), P_SourceData);
+ Layer->RenderInfo = AllocateMemory(Memory, sizeof(source_video), P_SourceData);
+ source_image *Source = (source_image *)Layer->RenderInfo;
+ Source->Raster = LoadImage(Memory, filename);
+ Layer->EndFrame = File.EndFrame;
+ Layer->x.CurrentValue.f = 1280/2;
+ Layer->y.CurrentValue.f = 720/2;
+ Layer->StartFrame = 0;
+
+
+ Layer->x.CurrentValue.f = 1280/2;
+ Layer->y.CurrentValue.f = 720/2;
+ Layer->StartFrame = 0;
+ Layer->EndFrame = File.EndFrame;
+}
+*/
+
+
+#endif
diff --git a/debug.h b/debug.h
index 4a6891e..45fa718 100644
--- a/debug.h
+++ b/debug.h
@@ -1,6 +1,6 @@
#if DEBUG
-global_variable int32 *debugnull = NULL;
+static int32 *debugnull = NULL;
#define Assert(Expression) if(!(Expression)) {*debugnull = 21;}
enum valtype {
@@ -32,7 +32,7 @@ struct project_debug
bool32 ToggleRenders;
};
-global_variable project_debug Debug;
+static project_debug Debug;
#if ARM
#define DEBUG_CycleCountStart(ID)
@@ -42,7 +42,7 @@ global_variable project_debug Debug;
#define DEBUG_CycleCountEnd(ID) Debug.EndCycleCount[ID] += __rdtsc() - Debug.CycleCount[ID]; Debug.ExecutionAmount[ID]++;
#endif
-internal void
+static void
DebugWatchVar(char *Name, void *Address, valtype Type) {
uint32 i = Debug.WatchedProperties;
Debug.String[i] = Name;
@@ -73,7 +73,7 @@ struct project_debug
#define DEBUG_CycleCountStart(ID)
#define DEBUG_CycleCountEnd(ID)
-internal void
+static void
DebugWatchVar(char *Name, void *Address, valtype Type) {
}
#endif
diff --git a/defines.h b/defines.h
new file mode 100644
index 0000000..ccca81c
--- /dev/null
+++ b/defines.h
@@ -0,0 +1,40 @@
+#define SwitchBool(Bool) if((Bool)) {(Bool) = 0;} else {(Bool) = 1;}
+#define AmountOf(Array) sizeof((Array)) / sizeof((Array)[1])
+
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+
+typedef int64_t int64;
+typedef int32 bool32;
+
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
+
+typedef float real32;
+typedef double real64;
+
+#define NORMALIZED_COL_MIN { .col = V4(0.0f, 0.0f, 0.0f, 0.0f) }
+#define NORMALIZED_COL_MAX { .col = V4(1.0f, 1.0f, 1.0f, 1.0f) }
+#define NORMALIZED_REAL_MIN { 0.0f }
+#define NORMALIZED_REAL_MAX { 1.0f }
+
+
+// All of these MIN/MAX values are arbitrarily chosen; they can probably be
+// increased if the user requires it.
+
+#define PROPERTY_REAL_MAX 1000000
+#define PROPERTY_REAL_MIN -1000000
+
+#define MAX_LAYERS 2048
+#define MAX_EFFECTS 32
+#define MAX_SOURCES 1024
+#define MAX_PROPERTIES_PER_EFFECT 16
+#define MAX_KEYFRAME_BLOCKS 64
+#define MAX_KEYFRAMES_PER_BLOCK 32
+#define STRING_SIZE 256
+
+#define MAX_SELECTED_PROPERTIES 16
+
diff --git a/effects.cpp b/effects.cpp
index 6c3c946..d427778 100644
--- a/effects.cpp
+++ b/effects.cpp
@@ -1,4 +1,4 @@
-internal void
+static void
DrawColor(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
{
v4 FloatColor = Property[0].CurrentValue.col;
@@ -177,17 +177,22 @@ DrawColor(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
}
}
-internal void
+static void
DrawGradient(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
{
v4 StartColor = Property[0].CurrentValue.col;
v4 EndColor = Property[1].CurrentValue.col;
}
+static void
+Levels(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
+{
+}
+
#if WINDOWS
-global_variable effect_header EffectList[3];
+static effect_header EffectList[3];
#else
-global_variable effect_header EffectList[] {
+static effect_header EffectList[] {
{
"Solid Color",
&DrawColor, 2, standard, {
@@ -205,7 +210,7 @@ global_variable effect_header EffectList[] {
},
{
"Levels",
- &DrawColor, 6, levels, {
+ &Levels, 6, levels, {
{"Start point", {0.0f}, type_real},
{"Mid point", {1.0f}, type_real},
{"End point", {1.0f}, type_real},
@@ -275,9 +280,11 @@ global_variable effect_header EffectList[] {
}
#endif
-internal void
+static void
AddEffect(project_layer *Layer, memory *Memory, uint16 EffectListIndex)
{
+ if (Layer == NULL)
+ return;
Layer->Effect[Layer->NumberOfEffects] = (effect *)AllocateMemory(Memory, sizeof(effect), F_Effects);
effect *Effect = Layer->Effect[Layer->NumberOfEffects];
effect_header EffectHeader = EffectList[EffectListIndex];
@@ -296,13 +303,13 @@ AddEffect(project_layer *Layer, memory *Memory, uint16 EffectListIndex)
Layer->NumberOfEffects++;
}
-internal void
+static void
CopyToBuffer(pixel_buffer *, uint16 asda = 0);
-internal void
+static void
UpdateEffects(project_layer *Layer, memory *Memory)
{
- image_source *Source = (image_source *)Layer->RenderInfo;
+ source_image *Source = (source_image *)Layer->RenderInfo;
if (!Source->Raster.EffectBuffer) {
Source->Raster.EffectBuffer = AllocateMemory(Memory, Source->Raster.Width * Source->Raster.Height * Source->Raster.BytesPerPixel,
B_Scratch);
@@ -317,7 +324,7 @@ UpdateEffects(project_layer *Layer, memory *Memory)
#if 0
-internal void
+static void
DrawColor(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
{
v4 FloatColor = Property[0].CurrentValue.col;
@@ -344,7 +351,7 @@ DrawColor(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
}
}
-internal void
+static void
Invert(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
{
uint8 *Row = ((uint8 *)Buffer->EffectBuffer);
@@ -368,7 +375,7 @@ Invert(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
}
}
-internal void
+static void
DrawGradient(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
{
v4 StartColor = Property[0].CurrentValue.col;
@@ -399,7 +406,7 @@ DrawGradient(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
}
}
-internal void
+static void
DrawGrid(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
{
v4 StartColor = Property[0].CurrentValue.col;
@@ -427,7 +434,7 @@ DrawGrid(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
}
}
-internal real32
+static real32
KernLoop(pixel_buffer *Buffer, int16 Xp, int16 Yp, real32 Value[8])
{
real32 P[9];
@@ -457,7 +464,7 @@ KernLoop(pixel_buffer *Buffer, int16 Xp, int16 Yp, real32 Value[8])
return Sum;
}
-internal void
+static void
SpacialFilter(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
{
real32 P[9];
@@ -515,7 +522,7 @@ SpacialFilter(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
}
-internal void
+static void
Gaussian(pixel_buffer *Buffer, void *FloatStorage, real32 Radius)
{
if (Radius < 1.0f)
@@ -581,7 +588,7 @@ Gaussian(pixel_buffer *Buffer, void *FloatStorage, real32 Radius)
}
}
-internal void
+static void
Canny(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
{
real32 SH[9] = { -1, 0, 1,
@@ -711,7 +718,7 @@ Canny(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
}
}
-internal void
+static void
Levels(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
{
real32 Min = Property[0].CurrentValue.f;
@@ -777,7 +784,7 @@ Levels(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
}
-internal void
+static void
GaussianBlur(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
{
real32 Radius = Property[0].CurrentValue.f;
diff --git a/video.cpp b/ffmpeg_backend.cpp
index bb3e17e..e97b4da 100644
--- a/video.cpp
+++ b/ffmpeg_backend.cpp
@@ -1,5 +1,12 @@
-// workaround to make libav error printing work
+extern "C" {
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+#include <libavformat/avio.h>
+#include <libavutil/avutil.h>
+#include <libswscale/swscale.h>
+}
+// workaround to make libav error printing work
#ifdef av_err2str
#undef av_err2str
#include <string>
@@ -10,21 +17,22 @@ av_always_inline std::string av_err2string(int errnum) {
#define av_err2str(err) av_err2string(err).c_str()
#endif // av_err2str
-internal bool32
-AV_TryFrame(av_info *AV, int32 *err)
+#include "ffmpeg_backend.h"
+
+bool32 AV_TryFrame(av_codec_info *AV, av_packet_info *AVLayer, int32 *err)
{
- *err = av_read_frame(AV->FileFormatContext, AV->VideoPacket);
- if (*err >= 0 && AV->VideoPacket->stream_index != AV->StreamIndex) {
- av_packet_unref(AV->VideoPacket);
+ *err = av_read_frame(AV->FileFormatContext, AVLayer->VideoPacket);
+ if (*err >= 0 && AVLayer->VideoPacket->stream_index != AV->VideoStream->index) {
+ av_packet_unref(AVLayer->VideoPacket);
return 0;
}
if (*err < 0)
- *err = avcodec_send_packet(AV->VideoCodecContext, AV->VideoPacket);
+ *err = avcodec_send_packet(AV->VideoCodecContext, AVLayer->VideoPacket);
else {
- *err = avcodec_send_packet(AV->VideoCodecContext, AV->VideoPacket);
+ *err = avcodec_send_packet(AV->VideoCodecContext, AVLayer->VideoPacket);
}
- av_packet_unref(AV->VideoPacket);
+ av_packet_unref(AVLayer->VideoPacket);
if (*err < 0)
{
@@ -33,7 +41,7 @@ AV_TryFrame(av_info *AV, int32 *err)
}
while (*err >= 0) {
- *err = avcodec_receive_frame(AV->VideoCodecContext, AV->VideoFrame);
+ *err = avcodec_receive_frame(AV->VideoCodecContext, AVLayer->VideoFrame);
if (*err == AVERROR_EOF) {
} else if (*err == AVERROR(EAGAIN)) {
*err = 0;
@@ -46,8 +54,7 @@ AV_TryFrame(av_info *AV, int32 *err)
return 0;
}
-internal bool32
-TestAV(char *filename)
+bool32 AV_IsFileSupported(char *filename)
{
int32 err = 0;
@@ -77,9 +84,12 @@ TestAV(char *filename)
return 1;
}
-internal void
-InitAV(char *filename, av_info *AV)
+void AV_CodecInfo_Init(char *filename, source *Source, memory *Memory)
{
+ Source->Info.AVCodecInfo = AllocateMemory(Memory, sizeof(av_codec_info), P_AVInfo);
+ av_codec_info *AV = (av_codec_info *)Source->Info.AVCodecInfo;
+ *AV = {};
+
int32 err = 0;
// enum AVHWDeviceType type;
@@ -106,7 +116,6 @@ InitAV(char *filename, av_info *AV)
if (LocalCodecParameters->codec_type == AVMEDIA_TYPE_VIDEO) {
AV->VideoCodecParameters = LocalCodecParameters;
AV->VideoStream = AV->FileFormatContext->streams[i];
- AV->StreamIndex = i;
break;
}
}
@@ -151,63 +160,87 @@ InitAV(char *filename, av_info *AV)
fprintf(stderr, "Libav error: (%s)\n", av_err2str(err));
}
- AV->VideoPacket = av_packet_alloc();
- if (err < 0) {
- fprintf(stderr, "Libav error: (%s)\n", av_err2str(err));
- }
- AV->VideoFrame = av_frame_alloc();
- if (err < 0) {
- fprintf(stderr, "Libav error: (%s)\n", av_err2str(err));
- }
+ Source->Info.FPS = (real32)AV->VideoStream->r_frame_rate.num / AV->VideoStream->r_frame_rate.den;
+ Source->Info.Width = AV->VideoCodecContext->width;
+ Source->Info.Height = AV->VideoCodecContext->height;
+};
- AV->FPS = (real32)AV->VideoStream->r_frame_rate.num / AV->VideoStream->r_frame_rate.den;
- AV->IntFPS = (int32)(AV->FPS + 0.5f);
- AV->LastPTS = -1;
+void AV_GetPTSAverage(av_codec_info *AV, av_packet_info *AVLayer, int32 *err)
+{
// TODO(fox): This PTS average isn't exact and causes an occasional
// frame skip. See libav remarks in forum for more details.
// TODO(fox): Handle footage under five seconds.
int16 TestAmount = 5;
+ real32 FPS = (real32)AV->VideoStream->r_frame_rate.num / AV->VideoStream->r_frame_rate.den;
+
int16 i = 0;
+ real32 AvgPTSPerSecond = 0;
for (;;) {
- if (AV_TryFrame(AV, &err)) {
- if (i >= AV->FPS * TestAmount) {
- AV->AvgPTSPerSecond = (real32)AV->VideoFrame->pts / TestAmount;
- printf("frame: %i, pts: %li\n", i, AV->VideoFrame->pts);
+ if (AV_TryFrame(AV, AVLayer, err)) {
+ if (i >= FPS * TestAmount) {
+ AvgPTSPerSecond = (real32)AVLayer->VideoFrame->pts / TestAmount;
+ printf("frame: %i, pts: %li\n", i, AVLayer->VideoFrame->pts);
break;
}
i++;
- av_frame_unref(AV->VideoFrame);
+ av_frame_unref(AVLayer->VideoFrame);
}
}
- AV->AvgPTSPerFrame = (real32)AV->AvgPTSPerSecond / AV->IntFPS;
- printf("Avg PTS per sec: %.06f, Avg PTS per frame: %.06f\n", AV->AvgPTSPerSecond, AV->AvgPTSPerFrame);
+ AV->AvgPTSPerFrame = (real32)AvgPTSPerSecond / (int32)(FPS + 0.5f);
+ printf("Avg PTS per sec: %.06f, Avg PTS per frame: %.06f\n", AvgPTSPerSecond, AV->AvgPTSPerFrame);
av_seek_frame(AV->FileFormatContext, -1, 0, AVSEEK_FLAG_BACKWARD);
-};
+}
-internal void
+
+void AV_PacketInfo_Init(layer_bitmap_info *BitmapInfo, memory *Memory)
+{
+ BitmapInfo->AVPacketInfo = AllocateMemory(Memory, sizeof(av_packet_info), P_AVInfo);
+ av_packet_info *AV = (av_packet_info *)BitmapInfo->AVPacketInfo;
+ *AV = {};
+ printf("%li", AV->PreviousPTS);
+
+ int32 err = 0;
+
+ AV->VideoPacket = av_packet_alloc();
+ if (err < 0) {
+ fprintf(stderr, "Libav error: (%s)\n", av_err2str(err));
+ }
+ AV->VideoFrame = av_frame_alloc();
+ if (err < 0) {
+ fprintf(stderr, "Libav error: (%s)\n", av_err2str(err));
+ }
+}
+
+
+static void
Convert4x4Chunk(pixel_buffer *Raster, uint8);
-internal void
+static void
ClearBuffer(pixel_buffer *Raster, void *);
-internal int16
-LoadVideoFrame(video_source *Source, memory *Memory, int32 TimelineFrame)
+bool32 AV_LoadVideoFrame(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, int32 TimelineFrame)
{
- av_info *AV = &Source->AV;
- pixel_buffer *Buffer = &Source->Raster;
- int32 *CurrentlyRenderedFrame = &Source->VideoCurrentFrame;
+ av_codec_info *AV = (av_codec_info *)Source->Info.AVCodecInfo;
+ av_packet_info *AVLayer = (av_packet_info *)BitmapInfo->AVPacketInfo;
+
+ int32 *CurrentlyRenderedFrame = &BitmapInfo->CurrentFrame;
int32 err = 0;
+ if (!AV->AvgPTSPerFrame) {
+ AV_GetPTSAverage(AV, AVLayer, &err);
+ }
+ Assert(AV->AvgPTSPerFrame);
+
int p = 0;
int i = 0;
- int32 FrameToSeek = TimelineFrame - Source->VideoFrameOffset;
+ int32 FrameToSeek = TimelineFrame - BitmapInfo->FrameOffset;
if (*CurrentlyRenderedFrame == FrameToSeek || FrameToSeek < 0)
return 0;
@@ -216,7 +249,7 @@ LoadVideoFrame(video_source *Source, memory *Memory, int32 TimelineFrame)
// This function only seeks to the nearest "keyframe."
if (*CurrentlyRenderedFrame != FrameToSeek - 1) {
- int64 SeekSeconds = (int64)(FrameToSeek / AV->IntFPS * AV_TIME_BASE);
+ int64 SeekSeconds = (int64)(FrameToSeek / (int32)(Source->Info.FPS + 0.5f) * AV_TIME_BASE);
av_seek_frame(AV->FileFormatContext, -1, SeekSeconds, AVSEEK_FLAG_BACKWARD);
printf("Seek activated\n");
} else if (*CurrentlyRenderedFrame < 0) {
@@ -228,58 +261,68 @@ LoadVideoFrame(video_source *Source, memory *Memory, int32 TimelineFrame)
int64 SeekPTS = (int64)(AV->AvgPTSPerFrame*FrameToSeek + 0.5f);
while (err >= 0) {
- if (AV_TryFrame(AV, &err)) {
+ if (AV_TryFrame(AV, AVLayer, &err)) {
// The first frame that gets loaded isn't always the actual
// first frame, so we need to check until it's correct.
- if (FrameToSeek == 0 && AV->VideoFrame->pts != AV->VideoStream->start_time) {
- av_frame_unref(AV->VideoFrame);
- printf("NON-START: avg: %li, real pts: %li", SeekPTS, AV->VideoFrame->pts);
+ if (FrameToSeek == 0 && AVLayer->VideoFrame->pts != AV->VideoStream->start_time) {
+ av_frame_unref(AVLayer->VideoFrame);
+ printf("NON-START: avg: %li, real pts: %li", SeekPTS, AVLayer->VideoFrame->pts);
continue;
}
- int64 Difference = AV->VideoFrame->pts - SeekPTS;
+ int64 Difference = AVLayer->VideoFrame->pts - SeekPTS;
if (abs(Difference) < AV->AvgPTSPerFrame)
{
- if (AV->LastPTS == -1) {
- AV->LastPTS = AV->VideoFrame->pts;
- printf("avg: %li, real pts: %li, difference: %li\n", SeekPTS, AV->VideoFrame->pts, Difference);
+ if (AVLayer->PreviousPTS == -1) {
+ AVLayer->PreviousPTS = AVLayer->VideoFrame->pts;
+ printf("avg: %li, real pts: %li, difference: %li\n", SeekPTS, AVLayer->VideoFrame->pts, Difference);
} else {
- printf("avg: %li, real pts: %li, difference: %li difference from last pts: %li\n", SeekPTS, AV->VideoFrame->pts, AV->VideoFrame->pts - SeekPTS, AV->VideoFrame->pts - AV->LastPTS);
- AV->LastPTS = AV->VideoFrame->pts;
+ printf("avg: %li, real pts: %li, difference: %li difference from last pts: %li\n", SeekPTS, AVLayer->VideoFrame->pts, AVLayer->VideoFrame->pts - SeekPTS, AVLayer->VideoFrame->pts - AVLayer->PreviousPTS);
+ AVLayer->PreviousPTS = AVLayer->VideoFrame->pts;
}
- uint32 PixelCount = AV->VideoFrame->width*AV->VideoFrame->height;
- int out_linesize[4] = { Buffer->Pitch, Buffer->Pitch, Buffer->Pitch, Buffer->Pitch };
- uint8 *dst_data[4] = { (uint8 *)Buffer->OriginalBuffer, (uint8 *)Buffer->OriginalBuffer + PixelCount,
- (uint8 *)Buffer->OriginalBuffer + PixelCount*2, (uint8 *)Buffer->OriginalBuffer + PixelCount*3 };
+ uint16 Width = Source->Info.Width;
+ uint16 Height = Source->Info.Height;
+ uint16 BytesPerPixel = Source->Info.BytesPerPixel;
+ int32 Pitch = Width*BytesPerPixel;
+
+ void *Buffer = AllocateMemory(Memory, Bitmap_CalcTotalBytes(Width, Height, BytesPerPixel), B_LoadedBitmaps);
+
+ int out_linesize[4] = { Pitch, Pitch, Pitch, Pitch };
+ uint8 *dst_data[4] = { (uint8 *)Buffer, (uint8 *)Buffer + Width*Height*BytesPerPixel,
+ (uint8 *)Buffer + Width*Height*BytesPerPixel*2, (uint8 *)Buffer + Width*Height*BytesPerPixel*3 };
// NOTE(fox): This function will be replaced in the future.
- AV->RGBContext = sws_getContext(AV->VideoFrame->width, AV->VideoFrame->height, (AVPixelFormat)AV->VideoFrame->format,
- AV->VideoFrame->width, AV->VideoFrame->height, AV_PIX_FMT_RGBA, SWS_BILINEAR,
+ AVLayer->RGBContext = sws_getContext(AVLayer->VideoFrame->width, AVLayer->VideoFrame->height, (AVPixelFormat)AVLayer->VideoFrame->format,
+ AVLayer->VideoFrame->width, AVLayer->VideoFrame->height, AV_PIX_FMT_RGBA, SWS_BILINEAR,
NULL, NULL, NULL);
- if(!AV->RGBContext) {
+ if(!AVLayer->RGBContext) {
printf("Libav error: SwsContext creation failed.");
}
- sws_scale(AV->RGBContext, AV->VideoFrame->data, AV->VideoFrame->linesize, 0, AV->VideoFrame->height,
+ sws_scale(AVLayer->RGBContext, AVLayer->VideoFrame->data, AVLayer->VideoFrame->linesize, 0, AVLayer->VideoFrame->height,
dst_data, out_linesize);
- av_frame_unref(AV->VideoFrame);
+ av_frame_unref(AVLayer->VideoFrame);
- Convert4x4Chunk(Buffer, 0);
- CopyToBuffer(Buffer, 1);
- ClearBuffer(Buffer, Buffer->EffectBuffer);
+ if (!BitmapInfo->BitmapBuffer) {
+ BitmapInfo->BitmapBuffer = AllocateMemory(Memory, Bitmap_CalcTotalBytes(Width, Height, BytesPerPixel), B_LayerBitmaps);
+ }
+ void *DestBuffer = BitmapInfo->BitmapBuffer;
+ Bitmap_ConvertPacking(Buffer, DestBuffer, Width, Height, BytesPerPixel, 0);
+ // CopyToBuffer(Buffer, 1);
+ // Bitmap_Clear(Buffer, Source->Info.Width, Source->Info.Height, Source->Info.BytesPerPixel);
- return 0;
+ return 1;
}
else
{
// If this gets printed when not seeking, a frame has been skipped!
- printf("FRAME SKIP: avg: %li, real pts: %li, difference: %li\n", SeekPTS, AV->VideoFrame->pts, Difference);
+ printf("FRAME SKIP: avg: %li, real pts: %li, difference: %li\n", SeekPTS, AVLayer->VideoFrame->pts, Difference);
}
- av_frame_unref(AV->VideoFrame);
+ av_frame_unref(AVLayer->VideoFrame);
}
}
/*
diff --git a/ffmpeg_backend.h b/ffmpeg_backend.h
new file mode 100644
index 0000000..d6a6a66
--- /dev/null
+++ b/ffmpeg_backend.h
@@ -0,0 +1,22 @@
+struct av_codec_info {
+ real32 AvgPTSPerFrame;
+
+ AVFormatContext *FileFormatContext;
+ AVCodecParameters *VideoCodecParameters;
+ const AVCodec* VideoCodec;
+ const AVCodecHWConfig* VideoHWConfig;
+ // AVPixelFormat HWPixFormat;
+ AVCodecContext *VideoCodecContext;
+ AVStream *VideoStream;
+};
+
+struct av_packet_info {
+ uint64 PreviousPTS = -1; // PTS value of the previous frame, used to check timings.
+
+ AVPacket *VideoPacket;
+ AVFrame *VideoFrame;
+ SwsContext *RGBContext;
+};
+
+static bool32 AV_TryFrame(av_codec_info *AV, av_packet_info *AVPacket, int32 *err); // Internal attempt to decode a frame. Typically run in a while loop until it returns true.
+
diff --git a/functions.h b/functions.h
new file mode 100644
index 0000000..af4f109
--- /dev/null
+++ b/functions.h
@@ -0,0 +1,18 @@
+
+// Buffer management
+
+static void * Layer_AllocateBuffer(memory *Memory, uint16 Width, uint16 Height, uint16 BytesPerPixel); //
+static project_layer * Layer_Init(project_data *File, memory *Memory); // Initializes a layer's name and properties. Add a source manually.
+
+
+static void Bitmap_CalcPackedDimensions(uint16 Width, uint16 Height, uint16 *WidthP, uint16 *HeightP); // Returns the dimensions a packed bitmap should be in memory.
+static uint16 Bitmap_CalcByteOffset(uint16 BytesPerPixel); // Returns the amount of bytes a loop goes through depending on the InstructionMode.
+static uint64 Bitmap_CalcTotalBytes(uint16 Width, uint16 Height, uint16 BytesPerPixel); // Returns the total amount of bytes a bitmap takes up.
+static void Bitmap_ConvertPacking(void *Buffer, void *DestBuffer, uint16 Width, uint16 Height, uint16 BytesPerPixel, uint16 Which);
+
+// Libav (ffmpeg) backend for decoding video
+
+static bool32 AV_IsFileSupported(char *filename); // Tests whether a decoder is available for a given file.
+static void AV_CodecInfo_Init(char *filename, source *Source, memory *Memory); // Initializes all internal structs and calculates average PTS.
+static bool32 AV_LoadVideoFrame(source *Source, memory *Memory, int32 TimelineFrame); // Loads video frame at TimelineFrame.
+
diff --git a/keyframes.cpp b/keyframes.cpp
index 42234d8..d2813a9 100644
--- a/keyframes.cpp
+++ b/keyframes.cpp
@@ -1,11 +1,11 @@
-internal keyframe*
+static keyframe*
KeyframeLookupMemory(property_channel *Property, int16 i) {
int16 b = i / MAX_KEYFRAMES_PER_BLOCK;
int16 k = i - b*MAX_KEYFRAMES_PER_BLOCK;
return &Property->KeyframeBlock[b]->Keyframe[k];
}
-internal keyframe*
+static keyframe*
KeyframeLookupIndex(property_channel *Property, int16 a) {
int16 i = Property->SortedIndex[a];
int16 b = i / MAX_KEYFRAMES_PER_BLOCK;
@@ -13,7 +13,7 @@ KeyframeLookupIndex(property_channel *Property, int16 a) {
return &Property->KeyframeBlock[b]->Keyframe[k];
}
-internal keyframe*
+static keyframe*
PushKeyframe(property_channel *Property) {
int16 i = Property->NumberOfTotalKeyframes;
int16 b = i / MAX_KEYFRAMES_PER_BLOCK;
@@ -22,7 +22,7 @@ PushKeyframe(property_channel *Property) {
}
// (extremely bad)
-internal temp_keyframe_list
+static temp_keyframe_list
GetSelectedKeyframes(project_data *File)
{
temp_keyframe_list KeyframeList;
@@ -42,7 +42,7 @@ GetSelectedKeyframes(project_data *File)
return KeyframeList;
}
-internal int32
+static int32
KeyframeMemoryToIndex(property_channel *Property, int32 a)
{
int32 Result = -1;
@@ -56,7 +56,7 @@ KeyframeMemoryToIndex(property_channel *Property, int32 a)
return Result;
}
-internal void
+static void
SelectKeyframe(project_data *File, project_layer *Layer, property_channel *Property, keyframe *Keyframe)
{
Layer->IsSelected = true;
@@ -65,7 +65,7 @@ SelectKeyframe(project_data *File, project_layer *Layer, property_channel *Prope
Keyframe->IsSelected = true;
}
-internal void
+static void
DeselectKeyframe(project_data *File, project_layer *Layer, property_channel *Property, keyframe *Keyframe)
{
Layer->IsSelected = true;
@@ -74,7 +74,7 @@ DeselectKeyframe(project_data *File, project_layer *Layer, property_channel *Pro
Keyframe->IsSelected = true;
}
-internal void
+static void
CheckKeyframeSort(property_channel *Property, int32 Increment, int32 b)
{
int32 i = KeyframeMemoryToIndex(Property, b);
@@ -101,7 +101,7 @@ CheckKeyframeSort(property_channel *Property, int32 Increment, int32 b)
}
}
-internal void
+static void
ShiftKeyframeIndex(property_channel *Property, int16 Increment, int16 StopAt) {
if (Increment > 0) {
int16 i = Property->NumberOfTotalKeyframes - 1;
@@ -118,7 +118,7 @@ ShiftKeyframeIndex(property_channel *Property, int16 Increment, int16 StopAt) {
}
}
-internal void
+static void
DeleteKeyframeFromMemory(property_channel *Property, int16 Increment, int16 StopAt) {
if (Increment > 0) {
int16 i = Property->NumberOfTotalKeyframes - 1;
@@ -141,7 +141,7 @@ DeleteKeyframeFromMemory(property_channel *Property, int16 Increment, int16 Stop
}
}
-internal void
+static void
ResortPropertyChannel(property_channel *Property) {
for (int16 i = 0; i < Property->NumberOfTotalKeyframes; i++)
{
@@ -165,7 +165,7 @@ ResortPropertyChannel(property_channel *Property) {
}
}
-internal void
+static void
DeleteSelectedKeyframes(project_data *File, memory *Memory)
{
for (int i = 0; i < File->NumberOfLayers; i++) {
@@ -192,7 +192,7 @@ DeleteSelectedKeyframes(project_data *File, memory *Memory)
}
}
-internal void
+static void
CalculatePropertyMinMax(property_channel *Property) {
Property->LocalMaxVal = Property->MinVal;
Property->LocalMinVal = Property->MaxVal;
@@ -208,7 +208,7 @@ CalculatePropertyMinMax(property_channel *Property) {
}
-internal void
+static void
IncrementKeyframes(property_channel *Property, int16 Increment)
{
for (int i = 0; i < Property->NumberOfTotalKeyframes; i++) {
@@ -217,7 +217,7 @@ IncrementKeyframes(property_channel *Property, int16 Increment)
}
}
-internal void
+static void
IncrementKeyframesInLayer(project_layer *Layer, int16 Increment)
{
for (int a = 0; a < AmountOf(Layer->Property); a++)
@@ -227,11 +227,11 @@ IncrementKeyframesInLayer(project_layer *Layer, int16 Increment)
IncrementKeyframes(&Layer->Effect[e]->Property[a], Increment);
}
-internal void
+static void
CreateKeyframeBlock(property_channel *, memory *);
// dir 0 left, 1 right
-internal void
+static void
ClampKeyframeHandles(property_channel *Property, int16 b, int16 dir) {
if (dir == 0) {
if (b > 0) {
@@ -262,7 +262,7 @@ ClampKeyframeHandles(property_channel *Property, int16 b, int16 dir) {
}
}
-internal void
+static void
ClampSurroundingKeyframeHandles(property_channel *Property, int16 b) {
ClampKeyframeHandles(Property, b, 0);
ClampKeyframeHandles(Property, b, 1);
@@ -278,7 +278,7 @@ ClampSurroundingKeyframeHandles(property_channel *Property, int16 b) {
-internal void
+static void
ManualKeyframeInsertF(property_channel *Property, memory *Memory, int32 CurrentFrame, real32 Val)
{
if (!(Property->NumberOfTotalKeyframes % MAX_KEYFRAMES_PER_BLOCK)) {
@@ -326,7 +326,7 @@ ManualKeyframeInsertF(property_channel *Property, memory *Memory, int32 CurrentF
}
-internal void
+static void
CalculateKeyframesLinearly(uint16 CurrentFrame, struct property_channel *Property)
{
diff --git a/layer.cpp b/layer.cpp
index b8355ed..d6c225b 100644
--- a/layer.cpp
+++ b/layer.cpp
@@ -1,4 +1,4 @@
-internal temp_layer_list
+static temp_layer_list
FindSelectedLayerIndex(project_data *File, int16 NumberOfSelectedLayers)
{
temp_layer_list List = {};
@@ -18,16 +18,16 @@ FindSelectedLayerIndex(project_data *File, int16 NumberOfSelectedLayers)
return List;
}
-internal transform_info
-CalculateTransforms(project_layer *Layer, pixel_buffer *Buffer);
+static transform_info
+CalculateTransforms(project_layer *Layer, comp_buffer *CompBuffer);
-internal bool32
-TestPointInLayer(project_layer *Layer, pixel_buffer *Buffer, v2 UV)
+static bool32
+TestPointInLayer(project_layer *Layer, comp_buffer *CompBuffer, v2 UV)
{
bool32 Result = false;
- real32 X = UV.x*Buffer->Width;
- real32 Y = UV.y*Buffer->Height;
- transform_info T = CalculateTransforms(Layer, Buffer);
+ real32 X = UV.x*CompBuffer->Width;
+ real32 Y = UV.y*CompBuffer->Height;
+ transform_info T = CalculateTransforms(Layer, CompBuffer);
real32 StartVectorX = X - T.OriginX;
real32 StartVectorY = Y - T.OriginY;
real32 LayerU = (StartVectorX * T.XAxisPX) + (StartVectorY * T.XAxisPY);
@@ -38,10 +38,10 @@ TestPointInLayer(project_layer *Layer, pixel_buffer *Buffer, v2 UV)
return Result;
}
-internal void
+static void
CalculateAnchorOffset(project_layer *, real32, uint16);
-internal void
+static void
InteractProperty(int16 a, project_data *File, project_state *State, bool32 Ended, real32 Value, memory *Memory)
{
temp_layer_list List = FindSelectedLayerIndex(File, State->NumberOfSelectedLayers);
@@ -67,7 +67,7 @@ InteractProperty(int16 a, project_data *File, project_state *State, bool32 Ended
// Cache->Frame[File->CurrentFrame].Cached = false;
}
-internal void
+static void
TransformsInteract(project_data *File, project_state *State, ui *UI, transforms_hotkey_interact Mode)
{
if (UI->FocusedWindow == focus_timeline) {
@@ -92,7 +92,7 @@ TransformsInteract(project_data *File, project_state *State, ui *UI, transforms_
}
}
-internal void
+static void
SelectLayer(project_layer *Layer, project_state *State, int32 i)
{
Layer->IsSelected = true;
@@ -100,7 +100,7 @@ SelectLayer(project_layer *Layer, project_state *State, int32 i)
State->MostRecentlySelectedLayer = i;
}
-internal void
+static void
DeselectAllLayers(project_data *File, project_state *State)
{
temp_layer_list List = FindSelectedLayerIndex(File, State->NumberOfSelectedLayers);
@@ -117,7 +117,7 @@ DeselectAllLayers(project_data *File, project_state *State)
// keeping an Index value in the layer and just sorting every time the order
// changes probably won't be much of a performance cost.
-internal void
+static void
MoveLayersByIncrement(project_data *File, project_state *State, int16 Increment)
{
bool32 AllowMove = true;
@@ -170,7 +170,7 @@ MoveLayersByIncrement(project_data *File, project_state *State, int16 Increment)
/*
-internal bool32
+static bool32
TestSelectedLayer(project_state *State, uint16 *a, uint16 Index)
{
bool32 Result = 0;
diff --git a/main.cpp b/main.cpp
index a575ef4..c6e129b 100644
--- a/main.cpp
+++ b/main.cpp
@@ -29,14 +29,6 @@
#define STBI_FAILURE_USERMSG
#include "lib/stb_image.h"
-extern "C" {
-#include <libavcodec/avcodec.h>
-#include <libavformat/avformat.h>
-#include <libavformat/avio.h>
-#include <libavutil/avutil.h>
-#include <libswscale/swscale.h>
-}
-
#if 0
#include <iacaMarks.h>
#else
@@ -44,60 +36,18 @@ extern "C" {
#define IACA_END
#endif
-#define internal static
-#define local_persist static
-#define global_variable static
-
-#define SwitchBool(Bool) if((Bool)) {(Bool) = 0;} else {(Bool) = 1;}
-#define AmountOf(Array) sizeof((Array)) / sizeof((Array)[1])
-
-typedef int8_t int8;
-typedef int16_t int16;
-typedef int32_t int32;
-
-typedef int64_t int64;
-typedef int32 bool32;
-
-typedef uint8_t uint8;
-typedef uint16_t uint16;
-typedef uint32_t uint32;
-typedef uint64_t uint64;
-
-typedef float real32;
-typedef double real64;
-
-#define NORMALIZED_COL_MIN { .col = V4(0.0f, 0.0f, 0.0f, 0.0f) }
-#define NORMALIZED_COL_MAX { .col = V4(1.0f, 1.0f, 1.0f, 1.0f) }
-#define NORMALIZED_REAL_MIN { 0.0f }
-#define NORMALIZED_REAL_MAX { 1.0f }
-
-
-// All of these MIN/MAX values are arbitrarily chosen; they can probably be
-// increased if the user requires it.
-
-#define PROPERTY_REAL_MAX 1000000
-#define PROPERTY_REAL_MIN -1000000
-
-#define MAX_LAYERS 2048
-#define MAX_EFFECTS 32
-#define MAX_SOURCES 1024
-#define MAX_PROPERTIES_PER_EFFECT 16
-#define MAX_KEYFRAME_BLOCKS 64
-#define MAX_KEYFRAMES_PER_BLOCK 32
-#define STRING_SIZE 256
-
-#define MAX_SELECTED_PROPERTIES 16
-
+#include "defines.h"
#include "my_math.h"
#include "main.h"
#include "debug.h"
+#include "functions.h"
+// #include "sharebuffer.h"
SDL_atomic_t CurrentEntry;
SDL_atomic_t QueuedEntries;
SDL_atomic_t CompletedEntries;
-global_variable bool32 IsRendering = false;
-global_variable instruction_mode InstructionMode = scalar_only;
-
+static bool32 IsRendering = false;
+static instruction_mode InstructionMode = instruction_mode_scalar;
render_entry Entries[256];
@@ -105,7 +55,7 @@ SDL_Thread *thread[8];
SDL_sem *Semaphore;
#include "memory.cpp"
-#include "effects.cpp"
+// #include "effects.cpp"
#include "keyframes.cpp"
#include "layer.cpp"
#include "strings.cpp"
@@ -114,59 +64,39 @@ SDL_sem *Semaphore;
#else
#endif
#include "prenderer.cpp"
-#include "video.cpp"
+#include "ffmpeg_backend.cpp"
#include "bitmap_calls.cpp"
#include "createcalls.cpp"
#include "my_imgui_widgets.cpp"
-// #include "sharebuffer.h"
-
-internal void
+static void
MainFunction(main_sdl *Main, memory *Memory,
project_state *State, project_data *File,
- cache_pool *Cache, pixel_buffer *CompBuffer)
+ cache_pool *Cache, comp_buffer *CompBuffer)
{
- ClearBuffer(CompBuffer, CompBuffer->OriginalBuffer);
- ClearBuffer(CompBuffer, CompBuffer->EffectBuffer);
+ Bitmap_Clear(CompBuffer->PackedBuffer, CompBuffer->Width, CompBuffer->Height, CompBuffer->BytesPerPixel);
+ Bitmap_Clear(CompBuffer->UnpackedBuffer, CompBuffer->Width, CompBuffer->Height, CompBuffer->BytesPerPixel);
for (int i = 0; i < File->NumberOfLayers; i++) {
project_layer *Layer = File->Layer[i];
- if (Layer->RenderInfo) {
- // Keyframe updating
- if (State->UpdateKeyframes) {
- for (int p = 0; p < Layer->NumberOfEffects; p++) {
- for (int o = 0; o < Layer->Effect[p]->NumberOfProperties; o++) {
- CalculateKeyframesLinearly(File->CurrentFrame, &Layer->Effect[p]->Property[o]);
- }
- }
- for (int r = 0; r < AmountOf(Layer->Property); r++) {
- CalculateKeyframesLinearly(File->CurrentFrame, &Layer->Property[r]);
- }
- }
-
- // Video updating
- if (Layer->SourceType == source_video) { // && Layer->VideoCurrentFrame != File->CurrentFrame - Layer->VideoFrameOffset) {
- video_source *Source = (video_source *)Layer->RenderInfo;
- LoadVideoFrame(Source, Memory, File->CurrentFrame); // TODO(fox): Make above check work!
- UpdateEffects(Layer, Memory);
- Source->Raster.ToUpdate = true;
+ if (State->UpdateKeyframes) {
+ for (int p = 0; p < Layer->NumberOfEffects; p++) {
+ for (int o = 0; o < Layer->Effect[p]->NumberOfProperties; o++) {
+ CalculateKeyframesLinearly(File->CurrentFrame, &Layer->Effect[p]->Property[o]);
+ }
}
-
- // Effect updating
- if (Layer->SourceType == source_image) {
- image_source *Source = (image_source *)Layer->RenderInfo;
- if (Source->Raster.ToUpdate) {
- UpdateEffects(Layer, Memory);
- Source->Raster.ToUpdate = false;
- }
+ for (int r = 0; r < AmountOf(Layer->Property); r++) {
+ CalculateKeyframesLinearly(File->CurrentFrame, &Layer->Property[r]);
}
}
+
+ Layer_UpdateBitmap(Layer->Source, &Layer->BitmapInfo, Memory, File->CurrentFrame);
}
State->UpdateKeyframes = false;
QueueCurrentFrame(File, CompBuffer, State);
}
#if 0
-internal void
+static void
MainFunction(main_sdl *Main, project_debug *D, memory *Memory, sdl_input *Input, sdl_input *OldInput,
project_state *State, brush_tool *Brush, project_data *File,
cache_pool *Cache, pixel_buffer *CompBuffer)
@@ -255,7 +185,7 @@ MainFunction(main_sdl *Main, project_debug *D, memory *Memory, sdl_input *Input,
#endif
-internal void
+static void
DebugPrintMemoryUsage(memory Memory)
{
for (int i = 0; i < 8; i++) {
@@ -269,7 +199,7 @@ int main(int argc, char *argv[]) {
global_memory GlobalMemory = {};
- GlobalMemory.Size = ((uint64)2 * 1024 * 1024 * 1024);
+ GlobalMemory.Size = ((uint64)4 * 1024 * 1024 * 1024);
GlobalMemory.CurrentPosition = 0;
#if WINDOWS
@@ -287,42 +217,53 @@ int main(int argc, char *argv[]) {
InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, P_UIState, "UI state");
// TODO(fox): Make clean-up functions when these get deleted!
- InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, P_SourceData, "Image/video headers");
+ InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, P_AVInfo, "Image/video headers");
InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_ProjectSettings, "Project settings");
InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Layers, "Layers");
InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Effects, "Effects");
InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Keyframes, "Keyframe blocks");
InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Strings, "Strings");
- InitMemoryTable(&GlobalMemory, &Memory, (uint64)2 * 1024 * 1024 * 1024, B_Scratch, "Scratch buffer");
+ InitMemoryTable(&GlobalMemory, &Memory, (uint64)16 * 1024 * 1024, B_LayerBitmaps, "Layer buffer");
+ InitMemoryTable(&GlobalMemory, &Memory, (uint64)1 * 1024 * 1024 * 1024, B_LoadedBitmaps, "Loaded bitmap buffer");
project_state State = {};
if (SDL_HasSSE2()) {
- InstructionMode = sse_enabled;
+ InstructionMode = instruction_mode_sse;
}
if (SDL_HasAVX2()) {
- InstructionMode = avx_enabled;
+ InstructionMode = instruction_mode_avx;
}
project_data File = {};
File.Width = 1280;
File.Height = 720;
- // File.Width = 1923;
- // File.Height = 1083;
File.NumberOfFrames = 65;
File.FPS = 30;
File.CurrentFrame = 1;
File.StartFrame = 0;
File.EndFrame = 65;
- // CreateLayerFromSource(&File, &State, &Memory, "../asset/b.jpg");
- // char String[1024];
- // uint16 Size = 1024;
- // getcwd(String, Size);
- // printf("dir: %s", String);
+#if DEBUG
+ // GDB and LLDB say this plain struct that's literally under 30 bytes is
+ // incomplete in the layers unless I do this...
+ layer_bitmap_info BitmapInfo;
+ BitmapInfo.ToUpdate = 0;
+ BitmapInfo.FrameOffset = 2;
+ av_packet_info BS = {};
+ BS.PreviousPTS = 0;
+#endif
+
+ LoadTestFootage(&File, &State, &Memory);
- pixel_buffer CompBuffer = CreateBuffer(File.Width, File.Height, &Memory);
+ uint16 BytesPerPixel = 4;
+ comp_buffer CompBuffer = {};
+ CompBuffer.Width = File.Width;
+ CompBuffer.Height = File.Height;
+ CompBuffer.BytesPerPixel = BytesPerPixel;
+ CompBuffer.PackedBuffer = Layer_AllocateBitmap(&Memory, CompBuffer.Width, CompBuffer.Height, CompBuffer.BytesPerPixel);
+ CompBuffer.UnpackedBuffer = Layer_AllocateBitmap(&Memory, CompBuffer.Width, CompBuffer.Height, CompBuffer.BytesPerPixel);
cache_pool Cache = {};
Cache.Interact = Inactive;
@@ -451,7 +392,7 @@ int main(int argc, char *argv[]) {
#if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, CompBuffer.Width, CompBuffer.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, CompBuffer.OriginalBuffer);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, CompBuffer.Width, CompBuffer.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, CompBuffer.PackedBuffer);
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
@@ -525,11 +466,12 @@ int main(int argc, char *argv[]) {
}
C = SDL_AtomicGet(&CompletedEntries);
if (C == 16) {
- Convert4x4Chunk(&CompBuffer, 1);
+ Bitmap_ConvertPacking(CompBuffer.PackedBuffer, CompBuffer.UnpackedBuffer,
+ CompBuffer.Width, CompBuffer.Height, CompBuffer.BytesPerPixel, 1);
EndRenderState(&State);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, CompBuffer.Width, CompBuffer.Height, GL_RGBA, GL_UNSIGNED_BYTE,
- CompBuffer.EffectBuffer);
+ CompBuffer.UnpackedBuffer);
// shmp->shared_framenumber = File.CurrentFrame;
// if (sem_post(&shmp->sem2) == -1)
diff --git a/main.h b/main.h
index 612e24f..691d915 100644
--- a/main.h
+++ b/main.h
@@ -1,50 +1,7 @@
-enum source_type {
- source_none,
- source_video,
- source_image
-};
-
enum instruction_mode {
- scalar_only,
- sse_enabled,
- avx_enabled
-};
-
-struct pixel_buffer {
- void *OriginalBuffer;
- void *EffectBuffer;
- void *Scratch;
- uint16 Width;
- uint16 Height;
- // IMPORTANT(fox): Since we're storing 4x4 chunks, I'm opting to pad out each
- // dimension with an extra 1-3 pixels to make our lookup functions simpler.
- // This has the cost of extra RAM, but it's a miniscule amount (0.2% extra
- // data for a worst-case 1080p 16bpc frame, or 140 kb).
- uint16 FullWidth;
- uint16 FullHeight;
- uint16 Pitch;
- uint16 BytesPerPixel;
- bool32 ToUpdate; // Set whenever effects or video frames need to be updated.
-};
-
-struct av_info {
- AVFormatContext *FileFormatContext;
- AVCodecParameters *VideoCodecParameters;
- const AVCodec* VideoCodec;
- const AVCodecHWConfig* VideoHWConfig;
- AVPixelFormat HWPixFormat;
- AVCodecContext *VideoCodecContext;
- AVPacket *VideoPacket;
- AVFrame *VideoFrame;
- AVStream *VideoStream;
- SwsContext *RGBContext;
-
- uint16 StreamIndex;
- real32 FPS;
- int32 IntFPS;
- real32 AvgPTSPerSecond;
- real32 AvgPTSPerFrame;
- uint64 LastPTS;
+ instruction_mode_scalar,
+ instruction_mode_sse,
+ instruction_mode_avx
};
struct cache {
@@ -79,9 +36,10 @@ enum memory_table_list {
F_Strings,
P_UIState,
- P_SourceData,
+ P_AVInfo,
- B_Scratch,
+ B_LayerBitmaps,
+ B_LoadedBitmaps,
};
struct memory_table {
@@ -97,8 +55,12 @@ struct global_memory {
uint64 Size;
};
+struct cached_bitmap_block;
+
struct memory {
memory_table Slot[16];
+ cached_bitmap_block *CacheBlock[256];
+ uint16 NumberOfCachedBlocks;
};
struct property_channel;
@@ -127,7 +89,7 @@ enum var_type
};
-global_variable char* BlendmodeNames[] = {
+static char* BlendmodeNames[] = {
"Normal",
"Multiply",
"Color Burn",
@@ -213,6 +175,8 @@ struct property_header
val MaxVal;
};
+struct pixel_buffer {};
+
struct effect_header
{
char *Name;
@@ -233,20 +197,63 @@ struct effect {
};
-// Note how pixel_buffer is first in both so we can cast to image_source if we
-// don't care about the AV info.
+// Information about a particular file.
-struct video_source {
- struct pixel_buffer Raster;
- av_info AV;
- int32 VideoFrameOffset; // the "true" position of video layers, separate from StartFrame
- int32 VideoCurrentFrame;
+enum source_type {
+ source_type_none,
+ source_type_video,
+ source_type_image
};
-struct image_source {
- struct pixel_buffer Raster;
+// Probably best to consider source_info a part of the file data so we don't
+// have to re-check each source on every project load. (except for AVInfo)
+
+struct source_info {
+ // Image and video
+ uint16 Width;
+ uint16 Height;
+ uint16 BytesPerPixel;
+
+ // Video only
+ real32 FPS;
+ void* AVCodecInfo; // Internal data for the video decoder library.
};
+struct source {
+ char *Path;
+ source_type SourceType;
+ source_info Info;
+};
+
+// Bitmaps from files are loaded into these temporary cache blocks.
+
+struct cached_bitmap_block {
+ source *SourceOwner; // Which source the data belongs to.
+ void *Data; // Unpacked data loaded from the source file.
+ uint32 StartFrame;
+ uint32 NumberOfCachedFrames;
+};
+
+struct layer_bitmap_info {
+ // Image and video
+ void *BitmapBuffer; // Each layer has a persistent bitmap that the source data gets packed into.
+ bool32 ToUpdate = 1;
+
+ // Video only
+ int32 FrameOffset; // the "true" position of video layers, separate from StartFrame
+ int32 CurrentFrame = -1; // The last frame number rendered to the bitmap.
+ void *AVPacketInfo; // Internal data containing current frame info
+};
+
+struct comp_buffer {
+ uint16 Width;
+ uint16 Height;
+ uint16 BytesPerPixel;
+ void *PackedBuffer;
+ void *UnpackedBuffer;
+};
+
+
struct transform_info {
real32 XAxisPX;
real32 XAxisPY;
@@ -288,8 +295,8 @@ struct project_layer {
bool32 IsSelected;
- void *RenderInfo;
- source_type SourceType;
+ source *Source;
+ layer_bitmap_info BitmapInfo;
effect *Effect[MAX_EFFECTS];
uint16 NumberOfEffects;
@@ -303,6 +310,7 @@ struct project_layer {
transform_info TransformInfo;
};
+
// NOTE(fox): I have no idea how people normally do selection; currently I'm
// treating it more "immediate." Instead of updating a selection state as
// things are selected, I'm just calling functions that go through all the
@@ -336,7 +344,7 @@ struct project_data
uint16 NumberOfSelectedLayers;
uint16 NumberOfLayers;
- char *Source[MAX_SOURCES];
+ source Source[MAX_SOURCES];
uint16 NumberOfSources;
};
@@ -358,7 +366,7 @@ enum transforms_hotkey_interact {
struct main_sdl
{
- pixel_buffer Buffer;
+ // pixel_buffer Buffer;
SDL_Texture *Texture;
SDL_Event Event;
SDL_Window *Window;
@@ -510,7 +518,7 @@ struct render_queue
{
project_data *File;
project_state *State;
- pixel_buffer *CompBuffer;
+ comp_buffer *CompBuffer;
};
struct thread_info
diff --git a/memory.cpp b/memory.cpp
index 73d1fb4..6aebdc3 100644
--- a/memory.cpp
+++ b/memory.cpp
@@ -1,4 +1,4 @@
-internal void
+static void
InitMemoryTable(global_memory *GlobalMemory, memory *Memory, uint64 Size, memory_table_list TableName, char *Name) {
memory_table *Table = &Memory->Slot[TableName];
Table->Name = Name;
@@ -7,7 +7,7 @@ InitMemoryTable(global_memory *GlobalMemory, memory *Memory, uint64 Size, memory
GlobalMemory->CurrentPosition += Size;
}
-internal void*
+static void*
AllocateMemory(memory *Memory, uint64 Size, memory_table_list TableName) {
void *Address;
memory_table *Table = &Memory->Slot[TableName];
diff --git a/my_imgui_internal_widgets.cpp b/my_imgui_internal_widgets.cpp
new file mode 100644
index 0000000..5ff01ee
--- /dev/null
+++ b/my_imgui_internal_widgets.cpp
@@ -0,0 +1,294 @@
+#include "my_imgui_internal_widgets.h"
+
+#include "imgui.h"
+#ifndef IMGUI_DEFINE_MATH_OPERATORS
+#define IMGUI_DEFINE_MATH_OPERATORS
+#endif
+#include "imgui_internal.h"
+
+// A modded version of ScalarSlider allowing for the minimum and maximum parts
+// of the slider to be draggable by two other buttons. p_data is from range -1
+// to 1, and s_min and max are from 0-1.
+#if 0
+// bool ImGui::SliderLevels(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format, ImGuiSliderFlags flags)
+bool ImGui::SliderLevels(const char* label, void* p_data, const void* s_min, const void* s_max)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ const float MidMin = -1;
+ const float MidMax = 1;
+ const void* mid_min = &SliderMin;
+ const void* mid_max = &SliderMax;
+ ImGuiDataType data_type = ImGuiDataType_Float;
+ const char *format = "%f";
+
+ ImVec2 picker_pos = window->DC.CursorPos;
+
+ ImGuiContext& g = *GImGui;
+ bool value_changed = false;
+ BeginGroup();
+ PushID(label);
+ value_changed |= SliderScalar("", data_type, p_data, mid_min, mid_max, format, ImGuiSliderFlags_Logarithmic);
+ SetCursorScreenPos(ImVec2(picker_pos.x + 20.0f, picker_pos.y));
+ // PushItemWidth();
+ value_changed |= SliderScalar("", data_type, p_data, p_min, p_max, format, ImGuiSliderFlags_Logarithmic);
+ // PushMultiItemsWidths(components, CalcItemWidth());
+ // size_t type_size = GDataTypeInfo[data_type].Size;
+ // for (int i = 0; i < components; i++)
+ // {
+ // PushID(i);
+ // if (i > 0)
+ // SameLine(0, g.Style.ItemInnerSpacing.x);
+ // value_changed |= SliderScalar("", data_type, v, v_min, v_max, format, flags);
+ // PopID();
+ // PopItemWidth();
+ // v = (void*)((char*)v + type_size);
+ // }
+ PopID();
+
+ EndGroup();
+ return value_changed;
+}
+bool ImGui::SliderLevels(const char* label, void* p_data, void* s_left, void* s_right)
+{
+ ImGuiSliderFlags flags = ImGuiSliderFlags_NoInput;
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ const float SliderMin = -1;
+ const float SliderMax = 1;
+ const float OtherMin = 0;
+ const float OtherMax = 1;
+ const void* p_min = &SliderMin;
+ const void* p_max = &SliderMax;
+ const void* o_min = &OtherMin;
+ const void* o_max = &OtherMax;
+ ImGuiDataType data_type = ImGuiDataType_Float;
+ const char *format = "%f";
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+ const ImGuiID id_mid = window->GetID("asdasbdsgd");
+ const ImGuiID id_L = window->GetID("ppasd");
+ const ImGuiID id_R = window->GetID("adsafb");
+ const float w = CalcItemWidth();
+
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
+ const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
+
+ // const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
+ // ItemSize(total_bb, style.FramePadding.y);
+ // if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemFlags_Inputable : 0))
+ // return false;
+
+ const bool hovered = ItemHoverable(frame_bb, id_L);
+
+ // NOTE(fox): Making bogus calls here to get these positions so we can only activate the one we want - replace with the lower-level call.
+ // const ImGuiID id_bogus = window->GetID("ppp");
+ // ImRect test_left;
+ // SliderBehavior(frame_bb, id_bogus, data_type, s_left, o_min, o_max, format, ImGuiSliderFlags_NoInput, &test_left);
+ // ImRect test_right;
+ // SliderBehavior(frame_bb, id_bogus, data_type, s_right, o_min, o_max, format, ImGuiSliderFlags_NoInput, &test_right);
+
+ const bool input_requested_by_tabbing = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
+ const bool clicked = (hovered && g.IO.MouseClicked[0]);
+ const bool make_active = (input_requested_by_tabbing || clicked || g.NavActivateId == id_L || g.NavActivateInputId == id_L);
+ if (make_active)
+ {
+ SetActiveID(id_L, window);
+ SetFocusID(id_L, window);
+ FocusWindow(window);
+ g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
+ }
+ /*
+ else if (make_active && g.IO.MousePos.x > test_right.Min.x) {
+ SetActiveID(id_R, window);
+ SetFocusID(id_R, window);
+ FocusWindow(window);
+ g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
+ } else if (make_active) {
+ SetActiveID(id_mid, window);
+ SetFocusID(id_mid, window);
+ FocusWindow(window);
+ g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
+ }
+ */
+
+ // Draw frame
+ const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
+ RenderNavHighlight(frame_bb, id);
+ RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
+
+
+ // Slider behavior
+ ImRect L_grab_bb;
+ const bool value_changed = SliderBehavior(frame_bb, id_L, data_type, s_left, o_min, o_max, format, ImGuiSliderFlags_NoInput, &L_grab_bb);
+ if (value_changed)
+ MarkItemEdited(id_L);
+
+ // Render grab
+ if (L_grab_bb.Max.x > L_grab_bb.Min.x)
+ window->DrawList->AddRectFilled(L_grab_bb.Min, L_grab_bb.Max, GetColorU32(g.ActiveId == id_L ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
+
+#if 0
+ // Slider behavior
+ ImRect R_grab_bb;
+ const bool value_changed2 = SliderBehavior(frame_bb, id_R, data_type, s_right, o_min, o_max, format, ImGuiSliderFlags_NoInput, &R_grab_bb);
+ if (value_changed2)
+ MarkItemEdited(id_R);
+
+ // Render grab
+ if (R_grab_bb.Max.x > R_grab_bb.Min.x)
+ window->DrawList->AddRectFilled(R_grab_bb.Min, R_grab_bb.Max, GetColorU32(g.ActiveId == id_R ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
+
+ const ImRect range_bb(ImVec2(L_grab_bb.Min.x, frame_bb.Min.y), ImVec2(R_grab_bb.Min.x, frame_bb.Max.y));
+
+ // Slider behavior
+ ImRect grab_bb_mid;
+ const bool value_changed_mid = SliderBehavior(range_bb, id_mid, data_type, p_data, p_min, p_max, format, flags | ImGuiSliderFlags_Logarithmic, &grab_bb_mid);
+ // if (value_changed2)
+ // MarkItemEdited(id_bogus);
+
+ ImVec2 asda = ImVec2(0, 5);
+ // // Render grab
+ if (grab_bb_mid.Max.x > grab_bb_mid.Min.x)
+ window->DrawList->AddRectFilled(grab_bb_mid.Min + asda, grab_bb_mid.Max + asda, GetColorU32(g.ActiveId == id_bogus ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
+#endif
+ // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
+ char value_buf[64];
+ const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
+ if (g.LogEnabled)
+ LogSetNextTextDecoration("{", "}");
+ RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
+
+ if (label_size.x > 0.0f)
+ RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
+
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
+ return value_changed;
+}
+#else
+bool ImGui::SliderLevels(const char* label, void* p_mid, void* p_left, void* p_right)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ const float SliderMin = -1;
+ const float SliderMax = 1;
+ const float OtherMin = 0;
+ const float OtherMax = 1;
+ const void* p_min = &SliderMin;
+ const void* p_max = &SliderMax;
+ const void* o_min = &OtherMin;
+ const void* o_max = &OtherMax;
+ ImGuiDataType data_type = ImGuiDataType_Float;
+ const char *format = "%f";
+
+ ImGuiSliderFlags flags = ImGuiSliderFlags_NoInput;
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+ const ImGuiID idnull = window->GetID("asdas");
+ const ImGuiID id_mid = window->GetID("asdasbdsgd");
+ const ImGuiID id_L = window->GetID("ppasd");
+ const ImGuiID id_R = window->GetID("adsafb");
+ const float w = CalcItemWidth();
+
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
+ const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
+
+ ImRect test_L_bb;
+ SliderBehavior(frame_bb, idnull, data_type, p_left, o_min, o_max, format, flags, &test_L_bb);
+ ImRect test_R_bb;
+ SliderBehavior(frame_bb, idnull, data_type, p_right, o_min, o_max, format, flags, &test_R_bb);
+
+ ItemSize(total_bb, style.FramePadding.y);
+
+ if (!ItemAdd(total_bb, id_L, &frame_bb, 0))
+ return false;
+ if (!ItemAdd(total_bb, id_R, &frame_bb, 0))
+ return false;
+ if (!ItemAdd(total_bb, id_mid, &frame_bb, 0))
+ return false;
+
+ const bool hovered = ItemHoverable(frame_bb, id);
+
+ const bool input_requested_by_tabbing = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
+ const bool clicked = (hovered && g.IO.MouseClicked[0]);
+ const bool make_active = (input_requested_by_tabbing || clicked || g.NavActivateId == id || g.NavActivateInputId == id);
+
+ if (make_active)
+ {
+ if (g.IO.MousePos.x < test_L_bb.Max.x) {
+ SetActiveID(id_L, window);
+ SetFocusID(id_L, window);
+ } else if (g.IO.MousePos.x > test_R_bb.Min.x) {
+ SetActiveID(id_R, window);
+ SetFocusID(id_R, window);
+ } else {
+ SetActiveID(id_mid, window);
+ SetFocusID(id_mid, window);
+ }
+ FocusWindow(window);
+ g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
+ }
+
+
+ // Draw frame
+ const ImU32 frame_col = GetColorU32(g.ActiveId == id_L ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
+ RenderNavHighlight(frame_bb, id_L);
+ RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
+
+ // Slider behavior
+ ImRect grab_bb;
+ const bool value_changed = SliderBehavior(frame_bb, id_L, data_type, p_left, o_min, o_max, format, flags, &grab_bb);
+ if (value_changed)
+ MarkItemEdited(id_L);
+
+ // Render grab
+ if (grab_bb.Max.x > grab_bb.Min.x)
+ window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id_L ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
+
+ // Slider behavior
+ ImRect grab_bb2;
+ const bool value_changed2 = SliderBehavior(frame_bb, id_R, data_type, p_right, o_min, o_max, format, flags, &grab_bb2);
+ if (value_changed2)
+ MarkItemEdited(id_R);
+
+ // Render grab
+ if (grab_bb2.Max.x > grab_bb2.Min.x)
+ window->DrawList->AddRectFilled(grab_bb2.Min, grab_bb2.Max, GetColorU32(g.ActiveId == id_R ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
+
+ const ImRect mid_bb(ImVec2(grab_bb.Max.x, frame_bb.Min.y), ImVec2(grab_bb2.Min.x, frame_bb.Max.y));
+
+ // Slider behavior
+ ImRect grab_bb3;
+ const bool value_changed3 = SliderBehavior(mid_bb, id_mid, data_type, p_mid, p_min, p_max, format, flags, &grab_bb3);
+ if (value_changed3)
+ MarkItemEdited(id_mid);
+
+ // Render grab
+ if (grab_bb3.Max.x > grab_bb3.Min.x)
+ window->DrawList->AddRectFilled(grab_bb3.Min, grab_bb3.Max, GetColorU32(g.ActiveId == id_mid ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
+
+ // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
+ char value_buf[64];
+ const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_left, format);
+ if (g.LogEnabled)
+ LogSetNextTextDecoration("{", "}");
+ RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
+
+ if (label_size.x > 0.0f)
+ RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
+
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
+ return value_changed;
+}
+#endif
diff --git a/my_imgui_internal_widgets.h b/my_imgui_internal_widgets.h
new file mode 100644
index 0000000..ec106b1
--- /dev/null
+++ b/my_imgui_internal_widgets.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <climits>
+
+#include <imgui.h>
+
+// NOTE(fox): Appending to the standard ImGui namespace so I don't have to convert all the functions to ImGui::Function()
+namespace ImGui {
+ IMGUI_API bool SliderLevels(const char* label, void* p_data, void* p_min, void* p_max);
+}
+
diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp
index f94e47c..1ee82e9 100644
--- a/my_imgui_widgets.cpp
+++ b/my_imgui_widgets.cpp
@@ -1,8 +1,9 @@
#include "imgui/imgui.h"
+#include "my_imgui_internal_widgets.h"
#include "imgui_ops.h"
// 0 for timeline keyframe, 1 for graph keyframe, 2 for left graph handle, 3 for right graph handle
-internal void
+static void
ImGui_KeyframeDragging(project_data *File, project_state *State, ui *UI, property_channel *Property, int32 b, ImGuiIO io, int16 Type)
{
keyframe *Keyframe = KeyframeLookupMemory(Property, b);
@@ -69,7 +70,7 @@ ImGui_KeyframeDragging(project_data *File, project_state *State, ui *UI, propert
}
}
-internal void
+static void
ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *Memory)
{
if (State->MostRecentlySelectedLayer > -1) {
@@ -97,35 +98,52 @@ ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *
effect *Effect = Layer->Effect[h];
ImGui::Button("V"); ImGui::SameLine();
ImGui::Text(Effect->Name);
- for (int i = 0; i < Effect->NumberOfProperties; i++) {
- property_channel *Property = &Effect->Property[i];
- ImGui::PushID(Property);
- if (Property->VarType == type_real)
- ImGui::DragScalar(Property->Name, ImGuiDataType_Float, &Property->CurrentValue.f, 0.005f, &Property->MaxVal.f, &Property->MaxVal.f, "%f");
- if (Property->VarType == type_color)
- if (ImGui::ColorEdit4("color 1", &Property->CurrentValue.f, ImGuiColorEditFlags_Float))
- State->UpdateFrame = true;
- if (Property->VarType == type_blendmode)
- {
- uint32 *item_current_idx = (uint32 *)&Property->CurrentValue.blendmode; // Here we store our selection data as an index.
- if (ImGui::BeginListBox("Blend mode"))
+ if (Effect->DisplayType == standard) {
+ for (int i = 0; i < Effect->NumberOfProperties; i++) {
+ property_channel *Property = &Effect->Property[i];
+ ImGui::PushID(Property);
+ if (Property->VarType == type_real)
+ ImGui::DragScalar(Property->Name, ImGuiDataType_Float, &Property->CurrentValue.f, 0.005f, &Property->MaxVal.f, &Property->MaxVal.f, "%f");
+ if (Property->VarType == type_color)
+ if (ImGui::ColorEdit4("color 1", &Property->CurrentValue.f, ImGuiColorEditFlags_Float))
+ State->UpdateFrame = true;
+ if (Property->VarType == type_blendmode)
{
- for (int n = 0; n < IM_ARRAYSIZE(BlendmodeNames); n++)
+ uint32 *item_current_idx = (uint32 *)&Property->CurrentValue.blendmode; // Here we store our selection data as an index.
+ if (ImGui::BeginListBox("Blend mode"))
{
- const bool is_selected = (*item_current_idx == n);
- if (ImGui::Selectable(BlendmodeNames[n], is_selected)) {
- *item_current_idx = n;
- State->UpdateFrame = true;
+ for (int n = 0; n < IM_ARRAYSIZE(BlendmodeNames); n++)
+ {
+ const bool is_selected = (*item_current_idx == n);
+ if (ImGui::Selectable(BlendmodeNames[n], is_selected)) {
+ *item_current_idx = n;
+ State->UpdateFrame = true;
+ }
+
+ // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
+ if (is_selected)
+ ImGui::SetItemDefaultFocus();
}
-
- // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
- if (is_selected)
- ImGui::SetItemDefaultFocus();
+ ImGui::EndListBox();
}
- ImGui::EndListBox();
}
+ ImGui::PopID();
}
- ImGui::PopID();
+ } else if (Effect->DisplayType == levels) {
+ ImGui::Button("asda");
+ // bool ImGui::SliderScalarasda(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
+ // static int8 p = 0;
+ // static int8 m = 10;
+ // static int8 c = 2;
+ // ImGui::SliderScalarasda("slider s8 full", ImGuiDataType_S8, &c, &p, &m, "%d", ImGuiSliderFlags_None);
+ static real32 p = 0;
+ static real32 m = 1;
+ static real32 c = 2;
+ ImGui::SliderScalar("f2", ImGuiDataType_Float, &c, &p, &m, "%f", ImGuiSliderFlags_Logarithmic);
+ static real32 Max = 0.8;
+ static real32 Min = 0.25;
+ static real32 Mid = 0; // NOTE(fox): "Neutral" is zero, negative one is full black, one is full white.
+ ImGui::SliderLevels("f", &Mid, &Min, &Max);
}
}
} else {
@@ -138,11 +156,11 @@ ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *
ImGui::End();
}
-internal v2
-CalculateAnchorPointUV(project_layer *Layer, pixel_buffer *Buffer);
+static v2
+CalculateAnchorPointUV(project_layer *Layer, comp_buffer *Buffer);
-internal void
-ImGui_Viewport(project_data File, project_state *State, ui *UI, pixel_buffer CompBuffer,
+static void
+ImGui_Viewport(project_data File, project_state *State, ui *UI, comp_buffer CompBuffer,
ImGuiIO io, GLuint textureID)
{
ImGui::Begin("Viewport");
@@ -202,9 +220,9 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, pixel_buffer Com
// }
ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonMiddle);
if (ImGui::BeginPopup("context")) {
- if (ImGui::MenuItem("Scalar", NULL, false, InstructionMode != scalar_only)) { InstructionMode = scalar_only; State->UpdateFrame = true; }
- if (ImGui::MenuItem("SSE", NULL, false, InstructionMode != sse_enabled)) { InstructionMode = sse_enabled; State->UpdateFrame = true; }
- if (ImGui::MenuItem("AVX2", NULL, false, InstructionMode != avx_enabled)) { InstructionMode = avx_enabled; State->UpdateFrame = true; }
+ if (ImGui::MenuItem("Scalar", NULL, false, InstructionMode != instruction_mode_scalar)) { InstructionMode = instruction_mode_scalar; State->UpdateFrame = true; }
+ if (ImGui::MenuItem("SSE", NULL, false, InstructionMode != instruction_mode_sse)) { InstructionMode = instruction_mode_sse; State->UpdateFrame = true; }
+ if (ImGui::MenuItem("AVX2", NULL, false, InstructionMode != instruction_mode_avx)) { InstructionMode = instruction_mode_avx; State->UpdateFrame = true; }
ImGui::EndPopup();
}
if (IsActive && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1.0f) && ImGui::IsKeyDown(ImGuiKey_Z))
@@ -241,7 +259,7 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, pixel_buffer Com
}
// 1 for left, 2 for right, 3 for both
-internal bool32
+static bool32
ImGui_SlidingLayer(project_layer *Layer, real32 *DraggingThreshold, real32 Delta, int16 TimelineZoom, int16 Side)
{
bool32 Result = 0;
@@ -262,9 +280,8 @@ ImGui_SlidingLayer(project_layer *Layer, real32 *DraggingThreshold, real32 Delta
Layer->EndFrame += Increment;
if (Side == 3) {
IncrementKeyframesInLayer(Layer, Increment);
- if (Layer->SourceType == source_video) {
- video_source *Source = (video_source *)Layer->RenderInfo;
- Source->VideoFrameOffset += Increment;
+ if (Layer->Source->SourceType == source_type_video) {
+ Layer->BitmapInfo.FrameOffset += Increment;
}
}
}
@@ -275,21 +292,17 @@ ImGui_SlidingLayer(project_layer *Layer, real32 *DraggingThreshold, real32 Delta
return Result;
}
-internal void
-AddSource(project_data *File, memory *Memory, char * = NULL);
-
-internal void
+static void
ImGui_File(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io)
{
ImGui::Begin("Files");
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
- if (ImGui::Button("Add source")) {
- AddSource(File, Memory);
- }
+ // if (ImGui::Button("Add source")) {
+ // }
if (State->DemoButton) {
ImGui::SameLine();
if (ImGui::Button("Generate demo scene")) {
- CreateDemoScene(File, Memory);
+ // CreateDemoScene(File, Memory);
State->UpdateKeyframes = true;
State->UpdateFrame = true;
State->DemoButton = false;
@@ -298,20 +311,17 @@ ImGui_File(project_data *File, project_state *State, memory *Memory, ui *UI, ImG
if (State->GridButton) {
ImGui::SameLine();
if (ImGui::Button("Generate square grid")) {
- CreateGrid(File, Memory);
+ // CreateGrid(File, Memory);
State->UpdateKeyframes = true;
State->UpdateFrame = true;
State->GridButton = false;
}
}
- for (int16 i = 0; i < File->NumberOfSources; i++) {
- ImGui::PushID(i);
- ImGui::InputText("##source", File->Source[i], STRING_SIZE);
- ImGui::SameLine();
- if (ImGui::Button("Create Layer")) {
- CreateLayerFromSource(File, State, Memory, File->Source[i]);
- }
- ImGui::PopID();
+ static char Input[1024];
+ ImGui::InputText("##sourceinput", Input, STRING_SIZE);
+ ImGui::SameLine();
+ if (ImGui::Button("Create Layer")) {
+ // AddSource(File, State, Memory, Input);
}
#if DEBUG
for (int i = 0; i < Debug.WatchedProperties; i++) {
@@ -327,9 +337,10 @@ ImGui_File(project_data *File, project_state *State, memory *Memory, ui *UI, ImG
ImGui::End();
}
-internal void
+static void
ImGui_EffectsPanel(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io)
{
+#if 0
ImGui::Begin("Effects list", NULL);
if (State->RerouteEffects) {
ImGui::SetKeyboardFocusHere();
@@ -349,23 +360,41 @@ ImGui_EffectsPanel(project_data *File, project_state *State, memory *Memory, ui
State->filter.Build();
EffectSel = -1;
}
+ // Enter conveniently deactivates the InputText field
+ if (ImGui::IsItemDeactivated() && ImGui::IsKeyPressed(ImGuiKey_Enter)) {
+ int32 p = 0;
+ for (int32 i = 0; i < AmountOf(EffectList); i++) {
+ if (State->filter.PassFilter(EffectList[i].Name)) {
+ if (EffectSel == p && State->MostRecentlySelectedLayer != -1) {
+ AddEffect(File->Layer[State->MostRecentlySelectedLayer], Memory, i);
+ }
+ p++;
+ }
+ }
+ EffectSel = -1;
+ }
+ int32 p = 0;
for (int32 i = 0; i < AmountOf(EffectList); i++) {
if (State->filter.PassFilter(EffectList[i].Name)) {
- if (EffectSel == i) {
- bool t = true;
- ImGui::Selectable(EffectList[i].Name, &t);
- } else {
- bool s = false;
- ImGui::Selectable(EffectList[i].Name, &s);
+ bool t = false;
+ if (EffectSel == p) {
+ t = true;
}
- // ImGui::Text(EffectList[i].Name);
+ ImGui::Selectable(EffectList[i].Name, &t);
+ if (ImGui::IsItemClicked()) {
+ if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && State->MostRecentlySelectedLayer != -1) {
+ AddEffect(File->Layer[State->MostRecentlySelectedLayer], Memory, i);
+ }
+ }
+ p++;
}
}
ImGui::End();
+#endif
}
-internal void
+static void
ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io)
{
ImVec2 FramePadding = ImGui::GetStyle().FramePadding;
@@ -991,6 +1020,7 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
UI->BoxStart = {0, 0};
UI->BoxEnd = {0, 0};
UI->BoxSelectActive = false;
+ if (!io.KeyShift) DeselectAllLayers(File, State);
}
ImGui::EndChild();
@@ -1018,8 +1048,8 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
}
-internal void
-ImGui_ProcessInputs(project_data *File, project_state *State, pixel_buffer *CompBuffer, memory *Memory, ui *UI, ImGuiIO io)
+static void
+ImGui_ProcessInputs(project_data *File, project_state *State, comp_buffer *CompBuffer, memory *Memory, ui *UI, ImGuiIO io)
{
if (io.KeysData[ImGuiKey_Q].Down)
State->IsRunning = false;
@@ -1132,7 +1162,7 @@ ImGui_ProcessInputs(project_data *File, project_state *State, pixel_buffer *Comp
}
}
-global_variable char ImGuiPrefs[] = "[Window][DockSpaceViewport_11111111]"
+static char ImGuiPrefs[] = "[Window][DockSpaceViewport_11111111]"
"\nPos=0,0"
"\nSize=3200,1800"
"\nCollapsed=0"
diff --git a/paint.cpp b/paint.cpp
index f760d8e..f3170e5 100644
--- a/paint.cpp
+++ b/paint.cpp
@@ -1,5 +1,5 @@
-internal void
+static void
SlidingBrush(pixel_buffer *Buffer, v2i Pos, brush_tool Brush)
{
v2i Min = {0,0};
@@ -35,7 +35,7 @@ SlidingBrush(pixel_buffer *Buffer, v2i Pos, brush_tool Brush)
}
/*
-internal void
+static void
Paint(sdl_input Input, project_layer *Layer, brush_tool Brush)
{
int16 X = Input.Mouse.x - UI.CompX; // convert to comp space
diff --git a/prenderer.cpp b/prenderer.cpp
index 5df28f4..7ce738a 100644
--- a/prenderer.cpp
+++ b/prenderer.cpp
@@ -1,26 +1,26 @@
-internal void
+static void
PushRect(rectangle RenderRegion);
-internal void
+static void
RenderLayerNeon(project_layer *Layer, pixel_buffer *Buffer, rectangle RenderRegion);
-internal void
-AVX2_RenderLayer(transform_info TransformInfo, pixel_buffer *Buffer, rectangle RenderRegion);
-internal void
-SSE2_RenderLayer(transform_info TransformInfo, pixel_buffer *Buffer, rectangle RenderRegion);
-internal void
-Fallback_RenderLayer(transform_info TransformInfo, pixel_buffer *Buffer, rectangle RenderRegion);
-
-internal bool32
+static void
+AVX2_RenderLayer(transform_info TransformInfo, comp_buffer *Buffer, rectangle RenderRegion);
+static void
+SSE2_RenderLayer(transform_info TransformInfo, comp_buffer *Buffer, rectangle RenderRegion);
+static void
+Fallback_RenderLayer(transform_info TransformInfo, comp_buffer *Buffer, rectangle RenderRegion);
+
+static bool32
CheckQueue(render_queue RenderInfo, uint16 Index);
// for the anchor point moving UI
-internal void
+static void
CalculateAnchorOffset(project_layer *Layer, real32 Value, uint16 Dir)
{
v2 Result = {};
transform_info TransformInfo;
- image_source *Source = (image_source *)Layer->RenderInfo;
+ source *Source = Layer->Source;
real32 Rad = (Layer->rotation.CurrentValue.f * (PI / 180));
real32 s = Layer->scale.CurrentValue.f;
@@ -28,28 +28,28 @@ CalculateAnchorOffset(project_layer *Layer, real32 Value, uint16 Dir)
if (Dir == 0) {
v2 XAxis = V2(cos(Rad), sin(Rad)) * (Value / s);
Layer->x.CurrentValue.f += Value;
- Layer->ax.CurrentValue.f += XAxis.x/Source->Raster.Width;
- Layer->ay.CurrentValue.f -= XAxis.y/Source->Raster.Height;
+ Layer->ax.CurrentValue.f += XAxis.x/Source->Info.Width;
+ Layer->ay.CurrentValue.f -= XAxis.y/Source->Info.Height;
} else {
v2 YAxis = V2(sin(Rad), -cos(Rad)) * (Value / -s);
Layer->y.CurrentValue.f += Value;
- Layer->ax.CurrentValue.f -= YAxis.x/Source->Raster.Width;
- Layer->ay.CurrentValue.f += YAxis.y/Source->Raster.Height;
+ Layer->ax.CurrentValue.f -= YAxis.x/Source->Info.Width;
+ Layer->ay.CurrentValue.f += YAxis.y/Source->Info.Height;
}
}
-internal transform_info
-CalculateTransforms(project_layer *Layer, pixel_buffer *Buffer)
+static transform_info
+CalculateTransforms(project_layer *Layer, comp_buffer *CompBuffer)
{
transform_info TransformInfo;
- image_source *Source = (image_source *)Layer->RenderInfo;
+ source *Source = Layer->Source;
real32 Rad = (Layer->rotation.CurrentValue.f * (PI / 180));
real32 s = Layer->scale.CurrentValue.f;
// v2 Scale = {Source->Raster.Width * s, Source->Raster.Height * s};
- v2 XAxis = (Source->Raster.Width * s)*V2(cos(Rad), sin(Rad));
- v2 YAxis = (Source->Raster.Height * -s)*V2(sin(Rad), -cos(Rad));
+ v2 XAxis = (Source->Info.Width * s)*V2(cos(Rad), sin(Rad));
+ v2 YAxis = (Source->Info.Height * -s)*V2(sin(Rad), -cos(Rad));
real32 AnchorX = Layer->ax.CurrentValue.f;
real32 AnchorY = Layer->ay.CurrentValue.f;
@@ -62,8 +62,8 @@ CalculateTransforms(project_layer *Layer, pixel_buffer *Buffer)
int32 MaxX = 0;
int32 MaxY = 0;
- int32 MinX = Buffer->Width;
- int32 MinY = Buffer->Height;
+ int32 MinX = CompBuffer->Width;
+ int32 MinY = CompBuffer->Height;
v2 Points[4] = {Origin, Origin + XAxis, Origin + YAxis, Origin + XAxis + YAxis};
for (int i = 0; i < 4; i++) {
@@ -77,24 +77,30 @@ CalculateTransforms(project_layer *Layer, pixel_buffer *Buffer)
TransformInfo.XAxisPY = XLengthSq*XAxis.y;
TransformInfo.YAxisPX = YLengthSq*YAxis.x;
TransformInfo.YAxisPY = YLengthSq*YAxis.y;
- TransformInfo.LayerWidth = (real32)Source->Raster.Width;
- TransformInfo.LayerHeight = (real32)Source->Raster.Height;
- TransformInfo.FullLayerWidth = Source->Raster.FullWidth;
- TransformInfo.FullLayerHeight = Source->Raster.FullHeight;
+
+ uint16 Width = Source->Info.Width;
+ uint16 Height = Source->Info.Height;
+ uint16 WidthP, HeightP;
+ Bitmap_CalcPackedDimensions(Width, Height, &WidthP, &HeightP);
+
+ TransformInfo.LayerWidth = Width;
+ TransformInfo.LayerHeight = Height;
+ TransformInfo.FullLayerWidth = WidthP;
+ TransformInfo.FullLayerHeight = HeightP;
TransformInfo.LayerOpacity = Layer->opacity.CurrentValue.f;
TransformInfo.BlendMode =Layer->BlendMode;
TransformInfo.OriginX = Origin.x;
TransformInfo.OriginY = Origin.y;
- TransformInfo.BufferPitch = Buffer->Pitch;
- TransformInfo.LayerPitch = Source->Raster.Pitch;
+ TransformInfo.BufferPitch = CompBuffer->Width*CompBuffer->BytesPerPixel;
+ TransformInfo.LayerPitch = Source->Info.Width*Source->Info.BytesPerPixel;
TransformInfo.ClipRect = {MinX - (MinX & 3), MinY, MaxX + 1, MaxY + 1};
- TransformInfo.SourceBuffer = Source->Raster.EffectBuffer;
+ TransformInfo.SourceBuffer = Layer->BitmapInfo.BitmapBuffer;
return TransformInfo;
}
-internal void
+static void
EndRenderState(project_state *State)
{
IsRendering = false;
@@ -113,21 +119,21 @@ EndRenderState(project_state *State)
}
-internal void
+static void
RenderLayers(render_queue *RenderInfo, rectangle RenderRegion) {
for (int16 i = 0; i < RenderInfo->State->NumberOfLayersToRender; i++) {
int16 Idx = RenderInfo->State->LayersToRender[i];
- if (InstructionMode == avx_enabled)
+ if (InstructionMode == instruction_mode_avx)
AVX2_RenderLayer(RenderInfo->File->Layer[Idx]->TransformInfo, RenderInfo->CompBuffer, RenderRegion);
- else if (InstructionMode == sse_enabled)
+ else if (InstructionMode == instruction_mode_sse)
SSE2_RenderLayer(RenderInfo->File->Layer[Idx]->TransformInfo, RenderInfo->CompBuffer, RenderRegion);
else
Fallback_RenderLayer(RenderInfo->File->Layer[Idx]->TransformInfo, RenderInfo->CompBuffer, RenderRegion);
}
}
-internal void
-QueueCurrentFrame(project_data *File, pixel_buffer *CompBuffer, project_state *State)
+static void
+QueueCurrentFrame(project_data *File, comp_buffer *CompBuffer, project_state *State)
{
IsRendering = true;
render_queue RenderInfo = {File, State, CompBuffer};
@@ -181,7 +187,7 @@ QueueCurrentFrame(project_data *File, pixel_buffer *CompBuffer, project_state *S
#if ARM
-internal void
+static void
RenderLayerNeon(project_layer *Layer, pixel_buffer *Buffer, rectangle RenderRegion)
{
float32x4_t XAxisPX = vdupq_n_f32(XAxisP.x);
@@ -362,8 +368,8 @@ RenderLayerNeon(project_layer *Layer, pixel_buffer *Buffer, rectangle RenderRegi
}
#else
-internal void
-AVX2_RenderLayer(transform_info T, pixel_buffer *Buffer, rectangle RenderRegion)
+static void
+AVX2_RenderLayer(transform_info T, comp_buffer *Buffer, rectangle RenderRegion)
{
rectangle LayerBounds = ClipRectangle( T.ClipRect,
RenderRegion );
@@ -439,10 +445,14 @@ AVX2_RenderLayer(transform_info T, pixel_buffer *Buffer, rectangle RenderRegion)
__m256 StartVectorX = _mm256_sub_ps(PixelX, OriginX);
+ // TODO(fox): Not unwraping this function may lose a few cycles!
+ uint16 WidthP, HeightP;
+ Bitmap_CalcPackedDimensions(Buffer->Width, Buffer->Height, &WidthP, &HeightP);
+
uint32 XLookup = (X >> 2)*16 + (X % 4);
- uint32 YLookup = (Y >> 2)*(Buffer->FullWidth*4) + (Y % 4)*4;
+ uint32 YLookup = (Y >> 2)*(WidthP*4) + (Y % 4)*4;
uint32 PixelToSeek = XLookup + YLookup;
- uint8 *Pixel = (uint8 *)Buffer->OriginalBuffer + PixelToSeek*Buffer->BytesPerPixel;
+ uint8 *Pixel = (uint8 *)Buffer->PackedBuffer + PixelToSeek*Buffer->BytesPerPixel;
__m256 U = _mm256_add_ps(_mm256_mul_ps(StartVectorX, XAxisPX), _mm256_mul_ps(StartVectorY, XAxisPY));
__m256 V = _mm256_add_ps(_mm256_mul_ps(StartVectorX, YAxisPX), _mm256_mul_ps(StartVectorY, YAxisPY));
@@ -690,8 +700,8 @@ AVX2_RenderLayer(transform_info T, pixel_buffer *Buffer, rectangle RenderRegion)
}
}
-internal void
-SSE2_RenderLayer(transform_info T, pixel_buffer *Buffer, rectangle RenderRegion)
+static void
+SSE2_RenderLayer(transform_info T, comp_buffer *Buffer, rectangle RenderRegion)
{
rectangle LayerBounds = ClipRectangle( T.ClipRect,
RenderRegion );
@@ -752,10 +762,15 @@ SSE2_RenderLayer(transform_info T, pixel_buffer *Buffer, rectangle RenderRegion)
__m128 StartVectorX = _mm_sub_ps(PixelX, OriginX);
+
+ // TODO(fox): Not unwraping this function may lose a few cycles!
+ uint16 WidthP, HeightP;
+ Bitmap_CalcPackedDimensions(Buffer->Width, Buffer->Height, &WidthP, &HeightP);
+
uint32 XLookup = (X >> 2)*16 + (X % 4);
- uint32 YLookup = (Y >> 2)*(Buffer->FullWidth*4) + (Y % 4)*4;
+ uint32 YLookup = (Y >> 2)*(WidthP*4) + (Y % 4)*4;
uint32 PixelToSeek = XLookup + YLookup;
- uint8 *Pixel = (uint8 *)Buffer->OriginalBuffer + PixelToSeek*Buffer->BytesPerPixel;
+ uint8 *Pixel = (uint8 *)Buffer->PackedBuffer + PixelToSeek*Buffer->BytesPerPixel;
__m128 U = _mm_add_ps(_mm_mul_ps(StartVectorX, XAxisPX), _mm_mul_ps(StartVectorY, XAxisPY));
__m128 V = _mm_add_ps(_mm_mul_ps(StartVectorX, YAxisPX), _mm_mul_ps(StartVectorY, YAxisPY));
@@ -1040,15 +1055,18 @@ SSE2_RenderLayer(transform_info T, pixel_buffer *Buffer, rectangle RenderRegion)
#endif
-internal void
-Fallback_RenderLayer(transform_info T, pixel_buffer *Buffer, rectangle RenderRegion)
+static void
+Fallback_RenderLayer(transform_info T, comp_buffer *Buffer, rectangle RenderRegion)
{
rectangle LayerBounds = ClipRectangle( T.ClipRect, RenderRegion);
Assert(LayerBounds.Max.x <= Buffer->Width);
Assert(LayerBounds.Max.y <= Buffer->Height);
- uint8 *Row = ((uint8 *)Buffer->OriginalBuffer + Buffer->Pitch*(int16)(LayerBounds.Min.y) );
+ uint16 WidthP, HeightP;
+ Bitmap_CalcPackedDimensions(Buffer->Width, Buffer->Height, &WidthP, &HeightP);
+
+ uint8 *Row = ((uint8 *)Buffer->PackedBuffer + WidthP*Buffer->BytesPerPixel*(int16)(LayerBounds.Min.y) );
uint32 Channel = (T.LayerWidth * T.LayerHeight);
real32 Normalized255 = 1 / 255.0f;
@@ -1123,9 +1141,9 @@ Fallback_RenderLayer(transform_info T, pixel_buffer *Buffer, rectangle RenderReg
uint32 PixelD = *(uint32 *)((uint8 *)T.SourceBuffer + PixelToSeek*Buffer->BytesPerPixel);
#endif
XLookup = (X >> 2)*16 + (X % 4);
- YLookup = (Y >> 2)*(Buffer->FullWidth*4) + (Y % 4)*4;
+ YLookup = (Y >> 2)*(WidthP*4) + (Y % 4)*4;
PixelToSeek = XLookup + YLookup;
- uint32 *Pixel = (uint32 *)((uint8 *)Buffer->OriginalBuffer + PixelToSeek*Buffer->BytesPerPixel);
+ uint32 *Pixel = (uint32 *)((uint8 *)Buffer->PackedBuffer + PixelToSeek*Buffer->BytesPerPixel);
real32 TexRA = (real32)(PixelA & 0xFF) * Normalized255;
real32 TexRB = (real32)(PixelB & 0xFF) * Normalized255;
diff --git a/strings.cpp b/strings.cpp
index 814a52f..c1b9c9f 100644
--- a/strings.cpp
+++ b/strings.cpp
@@ -1,7 +1,10 @@
-global_variable bool32 Hacko = false;
-global_variable int32 EffectSel = -1;
+static bool32 Hacko = false;
+static int32 EffectSel = -1;
-internal int
+// I'm using the filter's grep functionality to sort the effects for us
+// (probably severely suboptimal), so I'm just using this callback function to
+// signal back to our code that tab has been pressed in the text edit.
+static int
EffectConsoleCallback(ImGuiInputTextCallbackData* data)
{
if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion)
diff --git a/threading.cpp b/threading.cpp
index 1b89136..c1cfe5c 100644
--- a/threading.cpp
+++ b/threading.cpp
@@ -1,4 +1,4 @@
-internal void
+static void
PushRect(rectangle RenderRegion)
{
uint32 Q = SDL_AtomicGet(&QueuedEntries);
@@ -8,10 +8,10 @@ PushRect(rectangle RenderRegion)
SDL_SemPost(Semaphore);
}
-internal void
+static void
RenderLayers(render_queue *RenderInfo, rectangle RenderRegion);
-internal bool32
+static bool32
CheckQueue(render_queue RenderInfo, uint16 Index)
{
bool32 Result = 0;
@@ -31,7 +31,7 @@ CheckQueue(render_queue RenderInfo, uint16 Index)
return Result;
}
-internal int
+static int
TestThread(void *ptr)
{
thread_info *ThreadInfo = (thread_info *)ptr;
diff --git a/ui.cpp b/ui.cpp
index b7b10da..04b9002 100644
--- a/ui.cpp
+++ b/ui.cpp
@@ -1,4 +1,4 @@
-internal void
+static void
InteractProperty(int16 Index, project_data *File, project_state *State, bool32 Ended, real32 Value, memory *Memory, cache_pool *Cache)
{
for (int r = 0; r < State->NumberOfSelectedLayers; r++) {