From 8875d0226f0d38a1e5ef946e56cd15810627f5ac Mon Sep 17 00:00:00 2001 From: Fox Caminiti Date: Wed, 3 Aug 2022 16:57:07 -0400 Subject: caching introduced --- createcalls.cpp | 90 ++++++++++++++--- defines.h | 3 +- effects.cpp | 33 ++----- ffmpeg_backend.cpp | 169 +++++++++++++++++--------------- ffmpeg_backend.h | 25 ++--- functions.h | 6 +- main.cpp | 23 +++-- main.h | 76 +++++++-------- memory.cpp | 19 +++- my_imgui_internal_widgets.cpp | 222 ++++++------------------------------------ my_imgui_widgets.cpp | 136 +++++++++++++++++++++----- prenderer.cpp | 2 +- 12 files changed, 407 insertions(+), 397 deletions(-) diff --git a/createcalls.cpp b/createcalls.cpp index 42ab9b1..892be0a 100644 --- a/createcalls.cpp +++ b/createcalls.cpp @@ -55,7 +55,6 @@ Source_Generate(project_data *File, memory *Memory, char *Path) if (!Found && AV_IsFileSupported(Path)) { Source->SourceType = source_type_video; - AV_CodecInfo_Init(Path, Source, Memory); Found = true; } @@ -178,27 +177,96 @@ project_layer * Layer_Init(project_data *File, memory *Memory) return File->Layer[a]; } +static cached_bitmap * +Cache_CheckBitmap(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, int32 TimelineFrame) +{ + memory_table *Table = &Memory->Slot[B_LoadedBitmaps]; + int32 FrameToSeek = TimelineFrame - BitmapInfo->FrameOffset; + if (FrameToSeek < 0) { FrameToSeek = 0; }; + for (int i = 0; i < Table->NumberOfPointers; i++) { + cached_bitmap *Bitmap = &Memory->Bitmap[i]; + if (Bitmap->Frame == FrameToSeek && Bitmap->SourceOwner == Source) { + return Bitmap; + } + } + return 0; +} + static void -Layer_UpdateBitmap(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, int32 CurrentFrame) { - AV_LoadVideoFrame(Source, BitmapInfo, Memory, CurrentFrame); - // UpdateEffects(Layer, Memory); +Layer_UpdateBitmap(project_layer *Layer, memory *Memory, int32 CurrentFrame) { + source *Source = Layer->Source; + layer_bitmap_info *BitmapInfo = &Layer->BitmapInfo; + cached_bitmap *Bitmap = Cache_CheckBitmap(Source, BitmapInfo, Memory, CurrentFrame); + if (Bitmap) { + uint16 Width = Source->Info.Width; + uint16 Height = Source->Info.Height; + uint16 BytesPerPixel = Source->Info.BytesPerPixel; + void *DestBuffer = BitmapInfo->BitmapBuffer; + Bitmap_ConvertPacking(Bitmap->Data, DestBuffer, Width, Height, BytesPerPixel, 0); + } else { + AV_LoadVideoFrame(Source, BitmapInfo, Memory, CurrentFrame); + } + for (int i = 0; i < Layer->NumberOfEffects; i++) + { + if (Layer->Effect[i]->IsActive) + Layer->Effect[i]->func(Source, BitmapInfo, Memory, Layer->Effect[i]->Property); + } } static void -LoadTestFootage(project_data *File, project_state *State, memory *Memory) +Layer_InitSource(project_layer *Layer, source *Source, memory *Memory) { - 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); + Layer->BitmapInfo.BitmapBuffer = Layer_AllocateBitmap(Memory, Width, Height, BytesPerPixel); +} +static void +Layer_PositionCenter(project_layer *Layer, uint16 Width, uint16 Height) { + Layer->x.CurrentValue.f = Width/2; + Layer->y.CurrentValue.f = Height/2; +} + +static void +Layer_CreateFromSource(project_data *File, project_state *State, memory *Memory, source *Source) +{ + project_layer *Layer = Layer_Init(File, Memory); + AV_Init(Source, &Layer->BitmapInfo, Memory); + Layer_InitSource(Layer, Source, Memory); + Layer_PositionCenter(Layer, File->Width, File->Height); + State->UpdateFrame = true; +} + +static void +LoadTestFootage(project_data *File, project_state *State, memory *Memory) +{ + if (!Source_Generate(File, Memory, "../asset/24.mp4")) + PostMsg(State, "File open fail..."); + source *Source = &File->Source[0]; + Layer_CreateFromSource(File, State, Memory, Source); SelectLayer(File->Layer[0], State, 0); + AddEffect(File->Layer[0], Memory, 2); + property_channel *Property = &File->Layer[0]->x; + ManualKeyframeInsertF(Property, Memory, 1, 500); + ManualKeyframeInsertF(Property, Memory, 30, 800); + ManualKeyframeInsertF(Property, Memory, 15, 400); + ManualKeyframeInsertF(Property, Memory, 20, 100); + Property->IsToggled = true; + Property->IsGraphToggled = true; + Property->GraphLength = 150; + Property->GraphYOffset = (Property->GraphWindowHeight - Property->GraphLength)/2; + + // Layer_CreateFromSource(File, State, Memory, Source); + + if (!Source_Generate(File, Memory, "../asset/p.mp4")) + PostMsg(State, "File open fail..."); + source *Source2 = &File->Source[1]; + project_layer *Layer2 = Layer_Init(File, Memory); + AV_Init(Source2, &Layer2->BitmapInfo, Memory); + Layer_InitSource(Layer2, Source2, Memory); + // 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)); diff --git a/defines.h b/defines.h index ccca81c..d4a8788 100644 --- a/defines.h +++ b/defines.h @@ -32,9 +32,10 @@ typedef double real64; #define MAX_EFFECTS 32 #define MAX_SOURCES 1024 #define MAX_PROPERTIES_PER_EFFECT 16 +// max keyframes on a single channel is 2048 #define MAX_KEYFRAME_BLOCKS 64 #define MAX_KEYFRAMES_PER_BLOCK 32 -#define STRING_SIZE 256 +#define STRING_SIZE 1024 #define MAX_SELECTED_PROPERTIES 16 diff --git a/effects.cpp b/effects.cpp index d427778..6d27df1 100644 --- a/effects.cpp +++ b/effects.cpp @@ -1,5 +1,5 @@ static void -DrawColor(pixel_buffer *Buffer, memory *Memory, property_channel Property[]) +DrawColor(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]) { v4 FloatColor = Property[0].CurrentValue.col; blend_mode BlendMode = Property[1].CurrentValue.blendmode; @@ -32,14 +32,14 @@ DrawColor(pixel_buffer *Buffer, memory *Memory, property_channel Property[]) __m256 B_Colx2 = _mm256_mul_ps(B_Col, Two); __m256 B_ColInv = _mm256_set1_ps(1.0f - FloatColor.E[2]); - for (int16 Y = 0; Y < Buffer->Height; Y += 2) + for (int16 Y = 0; Y < Source->Info.Height; Y += 2) { - for (int16 X = 0; X < Buffer->Width; X += 4) + for (int16 X = 0; X < Source->Info.Width; X += 4) { uint32 XLookup = (X >> 2)*16 + (X % 4); - uint32 YLookup = (Y >> 2)*(Buffer->Width*4) + (Y % 4)*4; + uint32 YLookup = (Y >> 2)*(Source->Info.Width*4) + (Y % 4)*4; uint32 PixelToSeek = XLookup + YLookup; - uint8 *Pixel = (uint8 *)Buffer->EffectBuffer + PixelToSeek*Buffer->BytesPerPixel; + uint8 *Pixel = (uint8 *)BitmapInfo->BitmapBuffer + PixelToSeek*Source->Info.BytesPerPixel; __m256i DestPixel = _mm256_loadu_si256((const __m256i *)Pixel); // normalized values @@ -178,14 +178,14 @@ DrawColor(pixel_buffer *Buffer, memory *Memory, property_channel Property[]) } static void -DrawGradient(pixel_buffer *Buffer, memory *Memory, property_channel Property[]) +DrawGradient(source *Source, layer_bitmap_info *BitmapInfo, 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[]) +Levels(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]) { } @@ -303,25 +303,6 @@ AddEffect(project_layer *Layer, memory *Memory, uint16 EffectListIndex) Layer->NumberOfEffects++; } -static void -CopyToBuffer(pixel_buffer *, uint16 asda = 0); - -static void -UpdateEffects(project_layer *Layer, memory *Memory) -{ - 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); - } - CopyToBuffer(&Source->Raster); - for (int i = 0; i < Layer->NumberOfEffects; i++) - { - if (Layer->Effect[i]->IsActive) - Layer->Effect[i]->func(&Source->Raster, Memory, Layer->Effect[i]->Property); - } -} - #if 0 static void diff --git a/ffmpeg_backend.cpp b/ffmpeg_backend.cpp index e97b4da..dfc1241 100644 --- a/ffmpeg_backend.cpp +++ b/ffmpeg_backend.cpp @@ -19,20 +19,20 @@ av_always_inline std::string av_err2string(int errnum) { #include "ffmpeg_backend.h" -bool32 AV_TryFrame(av_codec_info *AV, av_packet_info *AVLayer, int32 *err) +bool32 AV_TryFrame(av_info *AV, int32 *err) { - *err = av_read_frame(AV->FileFormatContext, AVLayer->VideoPacket); - if (*err >= 0 && AVLayer->VideoPacket->stream_index != AV->VideoStream->index) { - av_packet_unref(AVLayer->VideoPacket); + *err = av_read_frame(AV->FileFormatContext, AV->VideoPacket); + if (*err >= 0 && AV->VideoPacket->stream_index != AV->VideoStream->index) { + av_packet_unref(AV->VideoPacket); return 0; } if (*err < 0) - *err = avcodec_send_packet(AV->VideoCodecContext, AVLayer->VideoPacket); + *err = avcodec_send_packet(AV->VideoCodecContext, AV->VideoPacket); else { - *err = avcodec_send_packet(AV->VideoCodecContext, AVLayer->VideoPacket); + *err = avcodec_send_packet(AV->VideoCodecContext, AV->VideoPacket); } - av_packet_unref(AVLayer->VideoPacket); + av_packet_unref(AV->VideoPacket); if (*err < 0) { @@ -41,7 +41,7 @@ bool32 AV_TryFrame(av_codec_info *AV, av_packet_info *AVLayer, int32 *err) } while (*err >= 0) { - *err = avcodec_receive_frame(AV->VideoCodecContext, AVLayer->VideoFrame); + *err = avcodec_receive_frame(AV->VideoCodecContext, AV->VideoFrame); if (*err == AVERROR_EOF) { } else if (*err == AVERROR(EAGAIN)) { *err = 0; @@ -54,6 +54,8 @@ bool32 AV_TryFrame(av_codec_info *AV, av_packet_info *AVLayer, int32 *err) return 0; } +// TODO(fox): Could be combined into AV_Init once we have dealloc functions for +// the AVInfo allocation. bool32 AV_IsFileSupported(char *filename) { int32 err = 0; @@ -84,10 +86,10 @@ bool32 AV_IsFileSupported(char *filename) return 1; } -void AV_CodecInfo_Init(char *filename, source *Source, memory *Memory) +void AV_Init(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory) { - Source->Info.AVCodecInfo = AllocateMemory(Memory, sizeof(av_codec_info), P_AVInfo); - av_codec_info *AV = (av_codec_info *)Source->Info.AVCodecInfo; + BitmapInfo->AVInfo = AllocateMemory(Memory, sizeof(av_info), P_AVInfo); + av_info *AV = (av_info *)BitmapInfo->AVInfo; *AV = {}; int32 err = 0; @@ -96,17 +98,20 @@ void AV_CodecInfo_Init(char *filename, source *Source, memory *Memory) // while((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE) // printf("%s\n", av_hwdevice_get_type_name(type)); - AV->FileFormatContext = avformat_alloc_context(); - err = avformat_open_input(&AV->FileFormatContext, filename, NULL, NULL);; + // The two calls below theoretically shouldn't fail since we already tested them in IsFileSupported. + AV->FileFormatContext = avformat_alloc_context(); + err = avformat_open_input(&AV->FileFormatContext, Source->Path, NULL, NULL);; if (err < 0) { fprintf(stderr, "Libav error: (%s)\n", av_err2str(err)); + Assert(0); } err = avformat_find_stream_info(AV->FileFormatContext, NULL); if (err < 0) { fprintf(stderr, "Libav error: (%s)\n", av_err2str(err)); + Assert(0); } for (int i = 0; i < AV->FileFormatContext->nb_streams; i++) @@ -154,12 +159,20 @@ void AV_CodecInfo_Init(char *filename, source *Source, memory *Memory) if (err < 0) { fprintf(stderr, "Libav error: (%s)\n", av_err2str(err)); } - avcodec_open2(AV->VideoCodecContext, AV->VideoCodec, NULL); if (err < 0) { 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; @@ -167,7 +180,7 @@ void AV_CodecInfo_Init(char *filename, source *Source, memory *Memory) -void AV_GetPTSAverage(av_codec_info *AV, av_packet_info *AVLayer, int32 *err) +void AV_GetPTSAverage(source *Source, av_info *AV, int32 *err) { // TODO(fox): This PTS average isn't exact and causes an occasional // frame skip. See libav remarks in forum for more details. @@ -180,62 +193,34 @@ void AV_GetPTSAverage(av_codec_info *AV, av_packet_info *AVLayer, int32 *err) int16 i = 0; real32 AvgPTSPerSecond = 0; for (;;) { - if (AV_TryFrame(AV, AVLayer, err)) { + if (AV_TryFrame(AV, err)) { if (i >= FPS * TestAmount) { - AvgPTSPerSecond = (real32)AVLayer->VideoFrame->pts / TestAmount; - printf("frame: %i, pts: %li\n", i, AVLayer->VideoFrame->pts); + AvgPTSPerSecond = (real32)AV->VideoFrame->pts / TestAmount; + printf("frame: %i, pts: %li\n", i, AV->VideoFrame->pts); break; } i++; - av_frame_unref(AVLayer->VideoFrame); + av_frame_unref(AV->VideoFrame); } } - AV->AvgPTSPerFrame = (real32)AvgPTSPerSecond / (int32)(FPS + 0.5f); - printf("Avg PTS per sec: %.06f, Avg PTS per frame: %.06f\n", AvgPTSPerSecond, AV->AvgPTSPerFrame); + Source->Info.AvgPTSPerFrame = (real32)AvgPTSPerSecond / (int32)(FPS + 0.5f); + printf("Avg PTS per sec: %.06f, Avg PTS per frame: %.06f\n", AvgPTSPerSecond, Source->Info.AvgPTSPerFrame); av_seek_frame(AV->FileFormatContext, -1, 0, AVSEEK_FLAG_BACKWARD); } - -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); -static void -ClearBuffer(pixel_buffer *Raster, void *); - bool32 AV_LoadVideoFrame(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, int32 TimelineFrame) { - av_codec_info *AV = (av_codec_info *)Source->Info.AVCodecInfo; - av_packet_info *AVLayer = (av_packet_info *)BitmapInfo->AVPacketInfo; - + av_info *AV = (av_info *)BitmapInfo->AVInfo; int32 *CurrentlyRenderedFrame = &BitmapInfo->CurrentFrame; int32 err = 0; - if (!AV->AvgPTSPerFrame) { - AV_GetPTSAverage(AV, AVLayer, &err); + if (!Source->Info.AvgPTSPerFrame) { + AV_GetPTSAverage(Source, AV, &err); } - Assert(AV->AvgPTSPerFrame); + Assert(Source->Info.AvgPTSPerFrame); int p = 0; int i = 0; @@ -258,28 +243,28 @@ bool32 AV_LoadVideoFrame(source *Source, layer_bitmap_info *BitmapInfo, memory * *CurrentlyRenderedFrame = FrameToSeek; - int64 SeekPTS = (int64)(AV->AvgPTSPerFrame*FrameToSeek + 0.5f); + int64 SeekPTS = (int64)(Source->Info.AvgPTSPerFrame*FrameToSeek + 0.5f); while (err >= 0) { - if (AV_TryFrame(AV, AVLayer, &err)) { + if (AV_TryFrame(AV, &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 && AVLayer->VideoFrame->pts != AV->VideoStream->start_time) { - av_frame_unref(AVLayer->VideoFrame); - printf("NON-START: avg: %li, real pts: %li", SeekPTS, AVLayer->VideoFrame->pts); + 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); continue; } - int64 Difference = AVLayer->VideoFrame->pts - SeekPTS; - if (abs(Difference) < AV->AvgPTSPerFrame) + int64 Difference = AV->VideoFrame->pts - SeekPTS; + if (abs(Difference) < Source->Info.AvgPTSPerFrame) { - if (AVLayer->PreviousPTS == -1) { - AVLayer->PreviousPTS = AVLayer->VideoFrame->pts; - printf("avg: %li, real pts: %li, difference: %li\n", SeekPTS, AVLayer->VideoFrame->pts, Difference); + if (AV->PreviousPTS == -1) { + AV->PreviousPTS = AV->VideoFrame->pts; + printf("avg: %li, real pts: %li, difference: %li\n", SeekPTS, AV->VideoFrame->pts, Difference); } else { - 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; + 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->PreviousPTS); + AV->PreviousPTS = AV->VideoFrame->pts; } uint16 Width = Source->Info.Width; @@ -287,31 +272,63 @@ bool32 AV_LoadVideoFrame(source *Source, layer_bitmap_info *BitmapInfo, memory * uint16 BytesPerPixel = Source->Info.BytesPerPixel; int32 Pitch = Width*BytesPerPixel; - void *Buffer = AllocateMemory(Memory, Bitmap_CalcTotalBytes(Width, Height, BytesPerPixel), B_LoadedBitmaps); + // probably should rename this + memory_table *Table = &Memory->Slot[B_LoadedBitmaps]; + uint64 Size = Bitmap_CalcTotalBytes(Width, Height, BytesPerPixel); + if (Table->CurrentPosition + Size > Table->Size) { + Table->CurrentPosition = 0; + Table->PointerIndex = 0; + } + cached_bitmap *Bitmap = &Memory->Bitmap[Table->PointerIndex]; + if (Table->PointerIndex < Table->NumberOfPointers) { + bool32 Avail = false; + void *DataStart = Memory->Bitmap[Table->PointerIndex].Data; + while(!Avail) { + void *Data2 = Memory->Bitmap[Table->PointerIndex+1].Data; + uint64 BytesBetween = (uint8 *)Data2 - (uint8 *)DataStart; + if (BytesBetween < Size) { + Memory->Bitmap[Table->PointerIndex+1].SourceOwner = NULL; + Table->PointerIndex++; + } else { + Avail = true; + } + Table->NumberOfPointers--; + } + } + Table->NumberOfPointers++; + Bitmap->Data = AllocateMemory(Memory, Size, B_LoadedBitmaps); + if (!Bitmap->Data) { + Assert(0); + } + Bitmap->SourceOwner = Source; + Bitmap->Frame = FrameToSeek; + Bitmap->Index = Table->PointerIndex; + Table->PointerIndex++; + void *Buffer = Bitmap->Data; 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. - 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, + 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, NULL, NULL, NULL); - if(!AVLayer->RGBContext) { + if(!AV->RGBContext) { printf("Libav error: SwsContext creation failed."); } - sws_scale(AVLayer->RGBContext, AVLayer->VideoFrame->data, AVLayer->VideoFrame->linesize, 0, AVLayer->VideoFrame->height, + sws_scale(AV->RGBContext, AV->VideoFrame->data, AV->VideoFrame->linesize, 0, AV->VideoFrame->height, dst_data, out_linesize); - av_frame_unref(AVLayer->VideoFrame); + av_frame_unref(AV->VideoFrame); - if (!BitmapInfo->BitmapBuffer) { - BitmapInfo->BitmapBuffer = AllocateMemory(Memory, Bitmap_CalcTotalBytes(Width, Height, BytesPerPixel), B_LayerBitmaps); - } + Assert(BitmapInfo->BitmapBuffer); void *DestBuffer = BitmapInfo->BitmapBuffer; Bitmap_ConvertPacking(Buffer, DestBuffer, Width, Height, BytesPerPixel, 0); + // void *Buffer2 = AllocateMemory(Memory, Bitmap_CalcTotalBytes(Width, Height, BytesPerPixel), B_LoadedBitmaps); + // uint64 test = &Buffer2 - &Buffer; // CopyToBuffer(Buffer, 1); // Bitmap_Clear(Buffer, Source->Info.Width, Source->Info.Height, Source->Info.BytesPerPixel); @@ -320,9 +337,9 @@ bool32 AV_LoadVideoFrame(source *Source, layer_bitmap_info *BitmapInfo, memory * 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, AVLayer->VideoFrame->pts, Difference); + printf("FRAME SKIP: avg: %li, real pts: %li, difference: %li\n", SeekPTS, AV->VideoFrame->pts, Difference); } - av_frame_unref(AVLayer->VideoFrame); + av_frame_unref(AV->VideoFrame); } } /* diff --git a/ffmpeg_backend.h b/ffmpeg_backend.h index d6a6a66..de73ff4 100644 --- a/ffmpeg_backend.h +++ b/ffmpeg_backend.h @@ -1,22 +1,23 @@ -struct av_codec_info { - real32 AvgPTSPerFrame; +// NOTE(fox): Even though each layer has its own completely isolated AV +// instance, it appears two layers with the same file still share something. +// When the layers aren't at the same position in time, the playhead of one +// layer gets misaligned every few frames and causes a manual seek back to the +// position. Different files don't exhibit this behavior. - AVFormatContext *FileFormatContext; - AVCodecParameters *VideoCodecParameters; +struct av_info { + uint64 PreviousPTS = -1; // PTS value of the previous frame, used to check timings. + + AVCodecParameters *VideoCodecParameters; // Used to supply info about the decoder. const AVCodec* VideoCodec; - const AVCodecHWConfig* VideoHWConfig; + // const AVCodecHWConfig* VideoHWConfig; // Haven't done enough research to know if HW decoding is already done by default or if we need these. // AVPixelFormat HWPixFormat; + AVStream *VideoStream; // Which stream, or channel, the video is in. Holds FPS info and is used to verify that the decoded packet belongs to this stream. + AVFormatContext *FileFormatContext; // Umbrella for everything else, seems to contain the playhead state 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. +static bool32 AV_TryFrame(av_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 index af4f109..64c8dc9 100644 --- a/functions.h +++ b/functions.h @@ -1,7 +1,7 @@ // Buffer management -static void * Layer_AllocateBuffer(memory *Memory, uint16 Width, uint16 Height, uint16 BytesPerPixel); // +static void * Layer_AllocateBitmap(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. @@ -10,9 +10,11 @@ static uint16 Bitmap_CalcByteOffset(uint16 BytesPerPixel); // Returns the amount 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); +static bool32 Source_Generate(project_data *File, memory *Memory, char *Path); // Fills out source info if the source is a supported file. + // 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 void AV_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/main.cpp b/main.cpp index c6e129b..dc16f30 100644 --- a/main.cpp +++ b/main.cpp @@ -55,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" @@ -88,8 +88,7 @@ MainFunction(main_sdl *Main, memory *Memory, CalculateKeyframesLinearly(File->CurrentFrame, &Layer->Property[r]); } } - - Layer_UpdateBitmap(Layer->Source, &Layer->BitmapInfo, Memory, File->CurrentFrame); + Layer_UpdateBitmap(Layer, Memory, File->CurrentFrame); } State->UpdateKeyframes = false; QueueCurrentFrame(File, CompBuffer, State); @@ -215,17 +214,18 @@ int main(int argc, char *argv[]) { memory Memory = {}; - 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_AVInfo, "Image/video headers"); + InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, P_SourceBitmapTable, "Source bitmap tables"); - InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_ProjectSettings, "Project settings"); - InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Layers, "Layers"); + InitMemoryTable(&GlobalMemory, &Memory, 15 * 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)16 * 1024 * 1024, B_LayerBitmaps, "Layer buffer"); - InitMemoryTable(&GlobalMemory, &Memory, (uint64)1 * 1024 * 1024 * 1024, B_LoadedBitmaps, "Loaded bitmap buffer"); + + InitMemoryTable(&GlobalMemory, &Memory, (uint64)200 * 1024 * 1024, B_LayerBitmaps, "Layer buffer"); + InitMemoryTable(&GlobalMemory, &Memory, (uint64)200 * 1024 * 1024, B_LoadedBitmaps, "Loaded bitmap buffer"); project_state State = {}; @@ -251,8 +251,9 @@ int main(int argc, char *argv[]) { layer_bitmap_info BitmapInfo; BitmapInfo.ToUpdate = 0; BitmapInfo.FrameOffset = 2; - av_packet_info BS = {}; + av_info BS = {}; BS.PreviousPTS = 0; + effect as = {}; #endif LoadTestFootage(&File, &State, &Memory); @@ -432,8 +433,10 @@ int main(int argc, char *argv[]) { ImGui_Timeline(&File, &State, &Memory, &UI, io); #if DEBUG - if (Debug.ToggleWindow) + if (Debug.ToggleWindow) { ImGui::ShowDemoWindow(); + ImGui_DebugMemoryViewer(&File, &Memory); + } #endif if (UI.TemporaryUpdateOverride) { diff --git a/main.h b/main.h index 691d915..0067c26 100644 --- a/main.h +++ b/main.h @@ -28,16 +28,14 @@ enum memory_table_list { // P = persistent data, but not file-based // B = cached data, often cleared - F_ProjectSettings, - // The majority bloat from these two are the properties. + P_AVInfo, + P_SourceBitmapTable, + F_Layers, F_Effects, F_Keyframes, F_Strings, - P_UIState, - P_AVInfo, - B_LayerBitmaps, B_LoadedBitmaps, }; @@ -47,6 +45,8 @@ struct memory_table { void *Address; uint64 CurrentPosition; uint64 Size; + uint32 NumberOfPointers; + uint32 PointerIndex; }; struct global_memory { @@ -55,12 +55,18 @@ struct global_memory { uint64 Size; }; -struct cached_bitmap_block; +struct source; + +struct cached_bitmap { + source *SourceOwner; // Which source it belongs to. Currently used to dereference the bitmap. + void *Data; // Unpacked data loaded from the source file. + uint32 Frame; // What frame it is. + uint32 Index; // Index in memory. +}; struct memory { memory_table Slot[16]; - cached_bitmap_block *CacheBlock[256]; - uint16 NumberOfCachedBlocks; + cached_bitmap Bitmap[4096]; }; struct property_channel; @@ -144,7 +150,7 @@ struct keyframe_block { struct property_channel { char *Name; keyframe_block *KeyframeBlock[MAX_KEYFRAME_BLOCKS]; - uint16 SortedIndex[MAX_KEYFRAMES_PER_BLOCK * MAX_KEYFRAME_BLOCKS]; + uint16 SortedIndex[MAX_KEYFRAME_BLOCKS * MAX_KEYFRAMES_PER_BLOCK]; uint16 NumberOfKeyframeBlocks; uint16 NumberOfSelectedKeyframes; uint16 NumberOfTotalKeyframes; @@ -175,27 +181,6 @@ struct property_header val MaxVal; }; -struct pixel_buffer {}; - -struct effect_header -{ - char *Name; - void (*func)(pixel_buffer *, memory *, property_channel []); - uint16 NumberOfProperties; - display_type DisplayType; - property_header PropertyHeader[MAX_PROPERTIES_PER_EFFECT]; -}; - -struct effect { - char *Name; - void (*func)(pixel_buffer *, memory *, property_channel []); - uint16 NumberOfProperties; - display_type DisplayType; - property_channel Property[MAX_PROPERTIES_PER_EFFECT]; - bool32 UIIsCollapsed = 0; - bool32 IsActive = 1; -}; - // Information about a particular file. @@ -216,7 +201,7 @@ struct source_info { // Video only real32 FPS; - void* AVCodecInfo; // Internal data for the video decoder library. + real32 AvgPTSPerFrame; // set by Libav }; struct source { @@ -227,12 +212,6 @@ struct source { // 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 @@ -242,7 +221,7 @@ struct layer_bitmap_info { // 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 + void *AVInfo; // Internal data containing current frame info }; struct comp_buffer { @@ -253,6 +232,26 @@ struct comp_buffer { void *UnpackedBuffer; }; +struct effect_header +{ + char *Name; + void (*func)(source *, layer_bitmap_info *, memory *, property_channel []); + uint16 NumberOfProperties; + display_type DisplayType; + property_header PropertyHeader[MAX_PROPERTIES_PER_EFFECT]; +}; + +struct effect { + char *Name; + void (*func)(source *, layer_bitmap_info *, memory *, property_channel []); + uint16 NumberOfProperties; + display_type DisplayType; + property_channel Property[MAX_PROPERTIES_PER_EFFECT]; + bool32 UIIsCollapsed = 0; + bool32 IsActive = 1; +}; + + struct transform_info { real32 XAxisPX; @@ -366,7 +365,6 @@ enum transforms_hotkey_interact { struct main_sdl { - // pixel_buffer Buffer; SDL_Texture *Texture; SDL_Event Event; SDL_Window *Window; diff --git a/memory.cpp b/memory.cpp index 6aebdc3..fcd7627 100644 --- a/memory.cpp +++ b/memory.cpp @@ -2,7 +2,7 @@ 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; - Table->Address = (uint64 *)GlobalMemory->Address + GlobalMemory->CurrentPosition; + Table->Address = (uint64 *)((uint8 *)GlobalMemory->Address + GlobalMemory->CurrentPosition); Table->Size = Size; GlobalMemory->CurrentPosition += Size; } @@ -11,8 +11,21 @@ static void* AllocateMemory(memory *Memory, uint64 Size, memory_table_list TableName) { void *Address; memory_table *Table = &Memory->Slot[TableName]; - Assert(Table->CurrentPosition + Size < Table->Size); - Address = (uint64 *)Table->Address + Table->CurrentPosition; + if (Table->CurrentPosition + Size > Table->Size) { + return NULL; + } + Address = (uint64 *)((uint8 *)Table->Address + Table->CurrentPosition); Table->CurrentPosition += Size; return Address; } + +// Returns 0-1 range wherever Pointer is in relation to StartingPointer to Size*Amount. +static real32 +Memory_NormalizedPosition(void *StartingPointer, uint32 Amount, uint32 Size, void *Pointer) +{ + real32 Result = 0; + uint64 TotalSize = Amount*Size; + uint64 PointerLocationSize = (uint8 *)Pointer - (uint8 *)StartingPointer; + Result = (real32)PointerLocationSize / (real32)TotalSize; + return Result; +} diff --git a/my_imgui_internal_widgets.cpp b/my_imgui_internal_widgets.cpp index 5ff01ee..d8934d8 100644 --- a/my_imgui_internal_widgets.cpp +++ b/my_imgui_internal_widgets.cpp @@ -7,57 +7,14 @@ #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 +// of the slider to be draggable by two other buttons. p_mid 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) +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 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; @@ -69,154 +26,53 @@ bool ImGui::SliderLevels(const char* label, void* p_data, void* s_left, void* s_ ImGuiDataType data_type = ImGuiDataType_Float; const char *format = "%f"; + ImGuiSliderFlags flags = ImGuiSliderFlags_NoInput; ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; + + // I'm not well-versed in exactly what ImGui's id system does, but I'm + // pretty sure it's one clickable object equals one ImGui ID. const ImGuiID id = window->GetID(label); - const ImGuiID id_mid = window->GetID("asdasbdsgd"); - const ImGuiID id_L = window->GetID("ppasd"); + PushID(label); + PushID(1); + const ImGuiID id_L = window->GetID(""); + PopID(); + PopID(); const ImGuiID id_R = window->GetID("adsafb"); + const ImGuiID id_mid = window->GetID("asdasbdsgd"); 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); + 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; // 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); + 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 (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); + 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 (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)); + 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_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; + 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); const bool hovered = ItemHoverable(frame_bb, id); @@ -226,10 +82,10 @@ bool ImGui::SliderLevels(const char* label, void* p_mid, void* p_left, void* p_r if (make_active) { - if (g.IO.MousePos.x < test_L_bb.Max.x) { + if (g.IO.MousePos.x < grab_bb.Max.x) { SetActiveID(id_L, window); SetFocusID(id_L, window); - } else if (g.IO.MousePos.x > test_R_bb.Min.x) { + } else if (g.IO.MousePos.x > grab_bb2.Min.x) { SetActiveID(id_R, window); SetFocusID(id_R, window); } else { @@ -246,33 +102,16 @@ bool ImGui::SliderLevels(const char* label, void* p_mid, void* p_left, void* p_r 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) @@ -291,4 +130,3 @@ bool ImGui::SliderLevels(const char* label, void* p_mid, void* p_left, void* p_r IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); return value_changed; } -#endif diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp index 1ee82e9..f93866a 100644 --- a/my_imgui_widgets.cpp +++ b/my_imgui_widgets.cpp @@ -70,6 +70,87 @@ ImGui_KeyframeDragging(project_data *File, project_state *State, ui *UI, propert } } +static void +ImGui_DebugMemoryViewer(project_data *File, memory *Memory) +{ + ImGui::SetNextWindowSize(ImVec2(800, 200)); + ImGui::Begin("memoryviewer"); + ImVec2 ViewportMin = ImGui::GetCursorScreenPos(); + ImVec2 ViewportScale = ImGui::GetContentRegionAvail(); + ImVec2 ViewportMax = ImVec2(ViewportMin.x + ViewportScale.x, ViewportMin.y + ViewportScale.y); + + memory_table *Table = &Memory->Slot[B_LoadedBitmaps]; + + real32 TotalMB = Table->Size/1024/1024; + real32 LineAmount = 50; + real32 IncrementMB = TotalMB / LineAmount; + real32 ScreenIncrement = ViewportScale.x / LineAmount; + + real32 CubeHeight = ImGui::GetFontSize(); + real32 TotalHeight = CubeHeight*4; + + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->AddRectFilled(ViewportMin, ViewportMax, IM_COL32(50, 50, 50, 255)); + + for (float x = 0; x < LineAmount; x++) { + uint32 LineColor = IM_COL32(200, 200, 200, 40); + ImVec2 Min = ImVec2(ViewportMin.x + ScreenIncrement * x, ViewportMin.y); + ImVec2 Max = ImVec2(Min.x + 2, ViewportMax.y); + draw_list->AddLine(Min, Max, LineColor); + } + + for (uint32 i = 0; i < Table->NumberOfPointers; i++) { + if (Memory->Bitmap[i].SourceOwner) { + void *DataStart = Memory->Bitmap[i].Data; + void *NextDataStart; + int pp = 1; + for (;;) { + if (Memory->Bitmap[i+pp].SourceOwner) { + NextDataStart = Memory->Bitmap[i+pp].Data; + break; + } + pp++; + } + uint64 BytesBetween = (uint8 *)NextDataStart - (uint8 *)DataStart; + source *Source = Memory->Bitmap[i].SourceOwner; + real32 Pos = Memory_NormalizedPosition(&File->Source[0], File->NumberOfSources, sizeof(source), Source); + + ImVec4 col = ImColor::HSV(Pos, 0.3, 0.6, 1.0f); + uint64 BitmapSize = Bitmap_CalcTotalBytes(Source->Info.Width, Source->Info.Height, Source->Info.BytesPerPixel); + if (BitmapSize > BytesBetween) { + col = ImColor::HSV(Pos, 1.0, 1.0, 1.0f); + } + + uint64 DataStart2 = (uint8 *)DataStart - (uint8 *)Table->Address; + real32 StartReal = ((real32)DataStart2/1024/1024); + ImVec2 Min = ImVec2(ViewportMin.x + (StartReal/IncrementMB * ScreenIncrement), ViewportMin.y + (ViewportScale.y / 2) - (TotalHeight / 2) + TotalHeight*Pos); + real32 SizeReal = ((real32)BitmapSize/1024/1024); + ImVec2 Size = ImVec2(SizeReal/IncrementMB * ScreenIncrement, CubeHeight); + ImGui::SetCursorScreenPos(Min); + ImGui::PushID(i); + ImGui::PushStyleColor(ImGuiCol_Button, col); + char buf2[256]; + sprintf(buf2, "%i##mempos", Memory->Bitmap[i].Frame); + ImGui::Button(buf2, Size); + ImGui::PopStyleColor(); + if (ImGui::IsItemHovered()) { + char buf[1024]; + sprintf(buf, "Source owner: %s\nSize: %.02f MB\n Frame number: %i", Memory->Bitmap[i].SourceOwner->Path, SizeReal, Memory->Bitmap[i].Frame); + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::TextUnformatted(buf); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + ImGui::PopID(); + ImVec2 Max = ImVec2(ViewportMax.x, Min.y + CubeHeight); + // draw_list->AddRectFilled(Min, Max, IM_COL32(200, 200, 200, 255)); + } + } + + ImGui::End(); +} + static void ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *Memory) { @@ -130,20 +211,10 @@ ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory * 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); + real32 *Min = &Effect->Property[0].CurrentValue.f; + real32 *Mid = &Effect->Property[1].CurrentValue.f; + real32 *Max = &Effect->Property[2].CurrentValue.f; + ImGui::SliderLevels("f", Mid, Min, Max); } } } else { @@ -297,10 +368,7 @@ ImGui_File(project_data *File, project_state *State, memory *Memory, ui *UI, ImG { ImGui::Begin("Files"); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); - // if (ImGui::Button("Add source")) { - // } if (State->DemoButton) { - ImGui::SameLine(); if (ImGui::Button("Generate demo scene")) { // CreateDemoScene(File, Memory); State->UpdateKeyframes = true; @@ -317,12 +385,23 @@ ImGui_File(project_data *File, project_state *State, memory *Memory, ui *UI, ImG State->GridButton = false; } } - static char Input[1024]; - ImGui::InputText("##sourceinput", Input, STRING_SIZE); - ImGui::SameLine(); - if (ImGui::Button("Create Layer")) { - // AddSource(File, State, Memory, Input); + ImGui::Text("Sources:"); + for (int i = 0; i < File->NumberOfSources; i++) { + ImGui::Text(File->Source[i].Path); + ImGui::OpenPopupOnItemClick("sourcecontext", ImGuiPopupFlags_MouseButtonRight); + if (ImGui::BeginPopup("sourcecontext")) { + if (ImGui::MenuItem("Create layer from source")) { + Layer_CreateFromSource(File, State, Memory, &File->Source[i]); + } + ImGui::EndPopup(); + } } + // 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++) { if (Debug.DebugPropertyType[i] == d_float) { @@ -340,7 +419,6 @@ ImGui_File(project_data *File, project_state *State, memory *Memory, ui *UI, ImG 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(); @@ -390,7 +468,6 @@ ImGui_EffectsPanel(project_data *File, project_state *State, memory *Memory, ui } } ImGui::End(); -#endif } @@ -467,9 +544,12 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImGui::BeginChild("Topbar", TopbarSize, true, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar); + ImGui::Text + /* ImGui::Button("V", TopbarButtonSize); ImGui::SameLine(); ImGui::Button("V", TopbarButtonSize); ImGui::SameLine(); ImGui::Button("V", TopbarButtonSize); ImGui::SameLine(); + */ ImGui::SetCursorScreenPos(PlayheadPos); ImGui::Button("P", ButtonSize); @@ -688,6 +768,14 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, } ImGui_SlidingLayer(Layer, &UI->DraggingKeyframeThreshold, io.MouseDelta.x, UI->TimelineZoom, 2); + for (int a = Layer->StartFrame; a < Layer->EndFrame; a++) { + cached_bitmap *Bitmap = Cache_CheckBitmap(Layer->Source, &Layer->BitmapInfo, Memory, a); + if (Bitmap) { + ImVec2 MinPos = ImVec2(TimelineStartingPos.x + UI->TimelineZoom * a, ImGui::GetCursorScreenPos().y); + draw_list->AddRect(MinPos, ImVec2(MinPos.x + UI->TimelineZoom, MinPos.y + 2.0f), ImColor(0, 255, 0, 255)); + } + } + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, ItemSpacing.y * UI->KeyframeSpacing)); ImGui::SetCursorPosY(ImGui::GetCursorPos().y + (ItemSpacing.y * UI->KeyframeSpacing / 2)); diff --git a/prenderer.cpp b/prenderer.cpp index 7ce738a..24b271c 100644 --- a/prenderer.cpp +++ b/prenderer.cpp @@ -3,7 +3,7 @@ static void PushRect(rectangle RenderRegion); static void -RenderLayerNeon(project_layer *Layer, pixel_buffer *Buffer, rectangle RenderRegion); +RenderLayerNeon(project_layer *Layer, comp_buffer *Buffer, rectangle RenderRegion); static void AVX2_RenderLayer(transform_info TransformInfo, comp_buffer *Buffer, rectangle RenderRegion); static void -- cgit v1.2.3