diff options
-rw-r--r-- | bezier.cpp | 47 | ||||
-rw-r--r-- | bitmap_calls.cpp | 45 | ||||
-rwxr-xr-x | build.sh | 20 | ||||
-rw-r--r-- | createcalls.cpp | 211 | ||||
-rw-r--r-- | debug.h | 32 | ||||
-rw-r--r-- | effects.cpp | 231 | ||||
-rw-r--r-- | effects.h | 76 | ||||
-rw-r--r-- | effects_software.cpp | 174 | ||||
-rw-r--r-- | ffmpeg_backend.cpp | 55 | ||||
-rw-r--r-- | functions.h | 20 | ||||
-rw-r--r-- | gl_calls.cpp | 111 | ||||
-rw-r--r-- | gl_calls.h | 24 | ||||
-rw-r--r-- | main.cpp | 116 | ||||
-rw-r--r-- | main.h | 91 | ||||
-rw-r--r-- | my_imgui_widgets.cpp | 9 | ||||
-rw-r--r-- | prenderer.cpp | 1 | ||||
-rw-r--r-- | structs.h | 5 |
17 files changed, 647 insertions, 621 deletions
@@ -209,3 +209,50 @@ Mask_AddPointToCurve(mask *Mask, uint16 Index, real32 ratio) PointToAdd->TangentRight = -(NewPos - NewHandleRight); Mask->NumberOfPoints++; } + +static void +Mask_RasterizePoints(mask *Mask) +{ + Mask->NumberOfVerts = 0; + for (int i = 0; i < Mask->NumberOfPoints; i++) { + mask_point Point0 = Mask->Point[i]; + mask_point Point1 = Mask->Point[i+1]; + if (i+1 == Mask->NumberOfPoints) + Point1 = Mask->Point[0]; + + if (Point0.HandleBezier && Point1.HandleBezier) { + Bezier_CubicCalcPoints(Point0.Pos, Point0.Pos + Point0.TangentRight, Point1.Pos + Point1.TangentLeft, Point1.Pos, + Mask->TriangulatedPointCache, &Mask->NumberOfVerts); + } else if (Point0.HandleBezier) { + Bezier_CubicCalcPoints(Point0.Pos, Point0.Pos + Point0.TangentRight, Point1.Pos, Point1.Pos, + Mask->TriangulatedPointCache, &Mask->NumberOfVerts); + } else if (Point1.HandleBezier) { + Bezier_CubicCalcPoints(Point0.Pos, Point0.Pos, Point1.Pos + Point1.TangentLeft, Point1.Pos, + Mask->TriangulatedPointCache, &Mask->NumberOfVerts); + } else { + real32 *Data = (real32 *)Mask->TriangulatedPointCache + Mask->NumberOfVerts*3; + *(Data++) = Point0.Pos.x; + *(Data++) = Point0.Pos.y; + *(Data++) = 0; + // NOTE(fox): CubicCalcPoints sometimes misses generating the start + // point of the next path in the above two cases, so I'm making + // straight lines always add both points as a hotfix. This leads + // to cases of duplicate verts, but it doesn't seem like it harms + // the rendering in any way. + *(Data++) = Point1.Pos.x; + *(Data++) = Point1.Pos.y; + *(Data++) = 0; + Mask->NumberOfVerts += 2; + } + } +} + +void Mask_TriangulateAndRasterize(memory *Memory, project_layer *Layer, mask *Mask) +{ + if (!Mask->TriangulatedPointCache) { + Mask->TriangulatedPointCache = AllocateMemory(Memory, 50*1024, P_VectorPoints); + } + Mask_RasterizePoints(Mask); + + GL_RasterizeShape(Layer, Mask); +} diff --git a/bitmap_calls.cpp b/bitmap_calls.cpp index a67cd0b..f37f493 100644 --- a/bitmap_calls.cpp +++ b/bitmap_calls.cpp @@ -238,6 +238,51 @@ Bitmap_CopyToPointer(void *Input, void *Output, uint16 BytesPerPixel, uint64 Tot } } +static void +Bitmap_StencilAlpha(void *Input, void *Output, uint16 BytesPerPixel, uint64 TotalBytes) +{ + uint8 *Row = (uint8 *)Input; + uint8 *Row2 = (uint8 *)Output; + + uint64 bytes = 0; + uint16 ByteOffset = Bitmap_CalcByteOffset(BytesPerPixel); + uint64 RemainderBytes = TotalBytes % ByteOffset; + + __m256i AlphaBytes = _mm256_set1_epi32(0x00FFFFFF); + __m256 Zeroi = _mm256_set1_epi32(0); + + while (bytes <= TotalBytes - RemainderBytes) { + uint8 *Pixel = (uint8 *)Row + bytes; + uint8 *Pixel2 = (uint8 *)Row2 + bytes; +#if ARM + if (InstructionMode == instruction_mode_neon) { + uint32x2x4_t OutputPixel = vld4_u32((uint32 *)Pixel); + vst4_u32((uint32 *)Pixel2, OutputPixel); +#else + if (InstructionMode == instruction_mode_avx) { + __m256i InputPixel = _mm256_loadu_si256((__m256i *)Pixel); + __m256i OutputPixel = _mm256_loadu_si256((__m256i *)Pixel2); + if (_mm256_movemask_epi8(OutputPixel)) { + OutputPixel = _mm256_blendv_epi8(OutputPixel, InputPixel, AlphaBytes); + _mm256_storeu_si256((__m256i *)Pixel2, OutputPixel); + } + } else if (InstructionMode == instruction_mode_sse) { + __m128i OutputPixel = _mm_loadu_si128((__m128i *)Pixel); + _mm_storeu_si128((__m128i *)Pixel2, OutputPixel); +#endif + } else { + *(uint32 *)Pixel2 = *(uint32 *)Pixel; + } + bytes += ByteOffset; + } + while (bytes <= TotalBytes) { + uint8 *Pixel = (uint8 *)Row + bytes; + uint8 *Pixel2 = (uint8 *)Row2 + bytes; + *(uint32 *)Pixel2 = *(uint32 *)Pixel; + bytes += BytesPerPixel; + } +} + // This would be an easy SIMD if only AVX had a scatter call... // NOTE(fox): Only works with unpacked bitmaps for now. static void @@ -1,11 +1,12 @@ #!/bin/bash -DEBUG=1 # Compile with debug symbols. -IMGUI=0 # Compile ImGui libs. Our custom ImGui functions still compile on zero. +OPTIMIZATION="-O2" # Enable optimization. +DEBUG=1 # Compile with debug UI. +IMGUI=1 # Compile ImGui libs. Our custom ImGui functions still compile on zero. THREADED=1 # Compile with threading. Useful to disable when stepping through the renderer. WINDOWS=0 # Compile for Windows with Mingw. ARM=0 # Compile on ARM machines. -PACKEDRGB=0 # Use 4x4 chunks for the software rasterizer. +PACKEDRGB=0 # Use 4x4 chunks for the software rasterizer. Isn't actually faster at the moment. PERF=0 # Print cycle stats. FFMPEG_LIBS=" @@ -42,9 +43,6 @@ WARNING_FLAGS=" if [[ "$DEBUG" == 1 ]]; then WARNING_FLAGS="$WARNING_FLAGS -DDEBUG=1" -DEBUG="-g" -else -DEBUG="-O2" fi if [[ "$THREADED" == 1 ]]; then WARNING_FLAGS="$WARNING_FLAGS -DTHREADED=1" @@ -71,11 +69,11 @@ fi if [[ "$OSTYPE" =~ ^darwin ]]; then IMGUI_FLAGS=" - -std=c++11 -Iimgui -Iimgui/backends $DEBUG -Wall -Wformat `sdl2-config --cflags` -I/usr/local/include -I/opt/local/include -c + -std=c++11 -Iimgui -Iimgui/backends $OPTIMIZATION -Wall -Wformat `sdl2-config --cflags` -I/usr/local/include -I/opt/local/include -c " else IMGUI_FLAGS=" - -Iimgui -Iimgui/backends $DEBUG -Wall -Wformat `sdl2-config --cflags` -c + -Iimgui -Iimgui/backends $OPTIMIZATION -Wall -Wformat `sdl2-config --cflags` -c " fi @@ -104,15 +102,15 @@ if [[ "$IMGUI" == 1 ]]; then fi if [[ "$WINDOWS" == 1 ]]; then -clang++ $DEBUG $WARNING_FLAGS -target x86_64-pc-windows-gnu -march=x86-64-v3 -I .. -Iimgui -Iimgui/backends \ +clang++ $OPTIMIZATION $WARNING_FLAGS -target x86_64-pc-windows-gnu -march=x86-64-v3 -I .. -Iimgui -Iimgui/backends \ main.cpp imgui/imgui*.cpp imgui/backends/imgui_impl_sdl.cpp imgui/backends/imgui_impl_opengl3.cpp \ -I/usr/x86_64-w64-mingw32/include/SDL2 -I/usr/x86_64-w64-mingw32/include/GL \ -lmingw32 -lopengl32 -lSDL2main -lSDL2 -llibavcodec -llibswscale -llibavformat -llibavutil \ -o bin/real2d else clang lib/glad.c $GLAD_FLAGS -I/usr/local/include -I/opt/local/include -c \ - $WARNING_FLAGS $DEBUG $ADDITIONAL_FLAGS -o bin/glad.o -clang main.cpp $WARNING_FLAGS $DEBUG $ADDITIONAL_FLAGS -o bin/real2d bin/*.o \ + $WARNING_FLAGS $OPTIMIZATION $ADDITIONAL_FLAGS -o bin/glad.o +clang main.cpp $WARNING_FLAGS $OPTIMIZATION $ADDITIONAL_FLAGS -o bin/real2d bin/*.o \ $GLAD_FLAGS \ -std=c++11 -lstdc++ -Iimgui -Iimgui/backends \ $SDL_ARGS \ diff --git a/createcalls.cpp b/createcalls.cpp index 1d4e2e5..f8c166e 100644 --- a/createcalls.cpp +++ b/createcalls.cpp @@ -83,6 +83,8 @@ project_layer * Layer_Init(project_data *File, memory *Memory) File->Layer[Index] = (project_layer *)AllocateMemory(Memory, sizeof(project_layer), F_Layers); project_layer *Layer = File->Layer[Index]; + *Layer = {}; + Layer->BitmapInfo.CurrentFrame = -1; History_Entry_SetPointer(Memory, &Layer->BitmapInfo.AVInfo); @@ -110,10 +112,13 @@ Cache_CheckBitmap(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, return 0; memory_table *Table = &Memory->Slot[B_LoadedBitmaps]; int32 FrameToSeek = TimelineFrame - BitmapInfo->FrameOffset; - // Stills have a frame index of zero. - if (FrameToSeek < 0 || Source->SourceType == source_type_image) { + if (FrameToSeek < 0) { FrameToSeek = 0; - }; + } + // Stills have a frame index of one. + if (Source->SourceType == source_type_image) { + FrameToSeek = 0; + } for (int i = 0; i < Table->NumberOfPointers; i++) { cached_bitmap *Bitmap = &Memory->Bitmap[i]; if (Bitmap->Frame == FrameToSeek && Bitmap->SourceOwner == Source) { @@ -138,145 +143,6 @@ STB_LoadStill(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory) } static void -Mask_RasterizePoints(mask *Mask) -{ - Mask->NumberOfVerts = 0; - for (int i = 0; i < Mask->NumberOfPoints; i++) { - mask_point Point0 = Mask->Point[i]; - mask_point Point1 = Mask->Point[i+1]; - if (i+1 == Mask->NumberOfPoints) - Point1 = Mask->Point[0]; - - if (Point0.HandleBezier && Point1.HandleBezier) { - Bezier_CubicCalcPoints(Point0.Pos, Point0.Pos + Point0.TangentRight, Point1.Pos + Point1.TangentLeft, Point1.Pos, - Mask->TriangulatedPointCache, &Mask->NumberOfVerts); - } else if (Point0.HandleBezier) { - Bezier_CubicCalcPoints(Point0.Pos, Point0.Pos + Point0.TangentRight, Point1.Pos, Point1.Pos, - Mask->TriangulatedPointCache, &Mask->NumberOfVerts); - } else if (Point1.HandleBezier) { - Bezier_CubicCalcPoints(Point0.Pos, Point0.Pos, Point1.Pos + Point1.TangentLeft, Point1.Pos, - Mask->TriangulatedPointCache, &Mask->NumberOfVerts); - } else { - real32 *Data = (real32 *)Mask->TriangulatedPointCache + Mask->NumberOfVerts*3; - *(Data++) = Point0.Pos.x; - *(Data++) = Point0.Pos.y; - *(Data++) = 0; - // NOTE(fox): CubicCalcPoints sometimes misses generating the start - // point of the next path in the above two cases, so I'm making - // straight lines always add both points as a hotfix. This leads - // to cases of duplicate verts, but it doesn't seem like it harms - // the rendering in any way. - *(Data++) = Point1.Pos.x; - *(Data++) = Point1.Pos.y; - *(Data++) = 0; - Mask->NumberOfVerts += 2; - } - } -} - -static void -Mask_TriangulateAndRasterize(memory *Memory, project_layer *Layer, mask *Mask) -{ - if (!Mask->TriangulatedPointCache) { - Mask->TriangulatedPointCache = AllocateMemory(Memory, 50*1024, P_VectorPoints); - } - Mask_RasterizePoints(Mask); - - gl_vertex_shader VertData; - gl_effect_layer Test = Layer->BitmapInfo.TestM; - gl_effect_layer Test2 = Layer->BitmapInfo.Test; - - uint32 Width = Layer->Source->Info.Width; - uint32 Height = Layer->Source->Info.Height; - - uint8 *Data = (uint8 *)Layer->BitmapInfo.BitmapBuffer; - - glBindFramebuffer(GL_FRAMEBUFFER, Test.FramebufferObject); - - glEnable(GL_STENCIL_TEST); - // glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - glStencilFunc(GL_ALWAYS, 0, 0xFF); // always write - glStencilMask(0xff); // allow writing; ANDs any writes to the stencil buffer with this - - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - - glUseProgram(DefaultShaderProgram); - - int VertexMode = glGetUniformLocation(DefaultShaderProgram, "VertexMode"); - int FragmentMode = glGetUniformLocation(DefaultShaderProgram, "FragmentMode"); - glUniform1i(VertexMode, 1); - glUniform1i(FragmentMode, 0); - - // secondary VBO - glGenVertexArrays(1, &VertData.VertexArrayObject); - glBindVertexArray(VertData.VertexArrayObject); - glBindBuffer(GL_ARRAY_BUFFER, VertData.VertexBufferObject); - glBufferData(GL_ARRAY_BUFFER, Mask->NumberOfVerts*3*sizeof(real32), Mask->TriangulatedPointCache, GL_STREAM_DRAW); - - // position attribute - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); - glEnableVertexAttribArray(0); - - int Scale = glGetUniformLocation(DefaultShaderProgram, "CompDimensions"); - glUniform3f(Scale, Width, Height, 0); - - - glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP); - glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP); - - glDisable(GL_CULL_FACE); - - glDrawArrays(GL_TRIANGLE_FAN, 0, Mask->NumberOfVerts); - - // glEnable(GL_CULL_FACE); - - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - glBindVertexArray(0); - - // glBindRenderbuffer(GL_RENDERBUFFER, Test.Color_Renderbuffer); - - VertexMode = glGetUniformLocation(DefaultShaderProgram, "VertexMode"); - FragmentMode = glGetUniformLocation(DefaultShaderProgram, "FragmentMode"); - glUniform1i(VertexMode, 0); - glUniform1i(FragmentMode, 1); - - - // // Switch to main buffer - glBindBuffer(GL_ARRAY_BUFFER, DefaultVerts.VertexBufferObject); - glBufferData(GL_ARRAY_BUFFER, sizeof(DefaultVertices), DefaultVertices, GL_STATIC_DRAW); - // position attribute - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); - glEnableVertexAttribArray(0); - // texture coordinate (note the last parameter's offset) - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); - glEnableVertexAttribArray(1); - - glStencilFunc(GL_NOTEQUAL, 0, 0xFF); - glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); - glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_INT, 0); - - glDisable(GL_STENCIL_TEST); - glStencilMask(0xFF); - glStencilFunc(GL_ALWAYS, 0, 0xFF); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, Test.FramebufferObject); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, Test2.FramebufferObject); - glBlitFramebuffer(0, 0, Width, Height, 0, 0, Width, Height, - GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_FRAMEBUFFER, Test2.FramebufferObject); - - glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, &Data[0]); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - -} - -static void Layer_InitSource(project_layer *Layer, source *Source, memory *Memory) { uint16 Width = Source->Info.Width; @@ -320,7 +186,7 @@ Layer_UpdateBitmap(project_data *File, project_layer *Layer, memory *Memory, int cached_bitmap *Bitmap = Cache_CheckBitmap(Source, BitmapInfo, Memory, CurrentFrame); if (!Bitmap) { if (Source->SourceType == source_type_image) { - Bitmap = AV_LoadVideoFrame(Source, BitmapInfo, Memory, 1); + Bitmap = STB_LoadStill(Source, BitmapInfo, Memory); } else { Bitmap = AV_LoadVideoFrame(Source, BitmapInfo, Memory, CurrentFrame); } @@ -338,8 +204,8 @@ Layer_UpdateBitmap(project_data *File, project_layer *Layer, memory *Memory, int Bitmap_CopyToPointer(Memory->Scratch, DestBuffer, BytesPerPixel, PackedSize); } else { Bitmap_CopyToPointer(Bitmap->Data, DestBuffer, BytesPerPixel, UnpackedSize); - TestGL_InitTexture(&BitmapInfo->Test, DestBuffer, Width, Height); - TestGL_MaskTexture(&BitmapInfo->TestM, DestBuffer, Width, Height); + // GL_InitTexture(&BitmapInfo->Test, DestBuffer, Width, Height); + // GL_MaskTexture(&BitmapInfo->TestM, DestBuffer, Width, Height); if (Layer->NumberOfMasks) { for (int i = 0; i < Layer->NumberOfMasks; i++) { @@ -359,8 +225,8 @@ Layer_UpdateBitmap(project_data *File, project_layer *Layer, memory *Memory, int } #else Bitmap_CopyToPointer(Bitmap->Data, DestBuffer, BytesPerPixel, UnpackedSize); - TestGL_UpdateTexture(&BitmapInfo->Test, DestBuffer, Width, Height, 0); - TestGL_UpdateTexture(&BitmapInfo->TestM, DestBuffer, Width, Height, 1); + GL_UpdateTexture(&BitmapInfo->Test, DestBuffer, Width, Height, 0); + GL_UpdateTexture(&BitmapInfo->TestM, DestBuffer, Width, Height, 1); if (Layer->NumberOfMasks) { for (int i = 0; i < Layer->NumberOfMasks; i++) { @@ -368,6 +234,13 @@ Layer_UpdateBitmap(project_data *File, project_layer *Layer, memory *Memory, int if (Mask->IsClosed) Mask_TriangulateAndRasterize(Memory, Layer, Mask); } + Bitmap_StencilAlpha(Bitmap->Data, DestBuffer, BytesPerPixel, UnpackedSize); + } + + for (int i = 0; i < Layer->NumberOfEffects; i++) + { + if (Layer->Effect[i]->IsActive) + Layer->Effect[i]->func(Source, BitmapInfo, Memory, Layer->Effect[i]->Property); } #endif } @@ -406,11 +279,18 @@ LoadTestFootage(project_data *File, project_state *State, memory *Memory) { void *SourceString = String_GenerateFromChar(Memory, "../asset/24.mp4"); Source_Generate(File, Memory, SourceString); + SourceString = String_GenerateFromChar(Memory, "../asset/a.jpg"); + Source_Generate(File, Memory, SourceString); + SourceString = String_GenerateFromChar(Memory, "../asset/b.jpg"); + Source_Generate(File, Memory, SourceString); + SourceString = String_GenerateFromChar(Memory, "../asset/c.jpg"); + Source_Generate(File, Memory, SourceString); + SourceString = String_GenerateFromChar(Memory, "../asset/p.mp4"); + Source_Generate(File, Memory, SourceString); - source *Source = &File->Source[0]; - Layer_CreateFromSource(File, State, Memory, Source); - SelectLayer(File->Layer[0], State, 0); - property_channel *Property = &File->Layer[0]->x; + // Layer_CreateFromSource(File, State, Memory, &File->Source[0]); + // SelectLayer(File->Layer[0], State, 0); + // property_channel *Property = &File->Layer[0]->x; // for (int i = 0; i < 16; i++) // Keyframe_Insert(Property, Memory, i*2, i*2*100); // Keyframe_Insert(Property, Memory, 1, 100); @@ -420,10 +300,11 @@ LoadTestFootage(project_data *File, project_state *State, memory *Memory) // History_Undo(Memory); // History_Redo(Memory); - Property->IsToggled = true; + // Property->IsToggled = true; // AddEffect(File->Layer[0], Memory, 3); + /* mask *Mask = &File->Layer[0]->Mask[0]; File->Layer[0]->NumberOfMasks = 1; Mask->Point[0].Pos = V2(200, 200); @@ -452,6 +333,7 @@ LoadTestFootage(project_data *File, project_state *State, memory *Memory) Mask->NumberOfPoints = 5; Mask->IsClosed = true; + */ // if (!Source_Generate(File, Memory, "../asset/test.png")) // PostMsg(State, "File open fail..."); @@ -498,26 +380,28 @@ LoadTestFootage(project_data *File, project_state *State, memory *Memory) } static void -CreateDemoScene(project_data *File, memory *Memory) +CreateDemoScene(project_data *File, project_state *State, 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; + Layer_CreateFromSource(File, State, Memory, &File->Source[1]); + project_layer *Layer1 = File->Layer[0]; + Layer1->x.CurrentValue.f = 1920/2; + Layer1->y.CurrentValue.f = 1080/2; Layer1->StartFrame = 0; Layer1->EndFrame = File->EndFrame; - project_layer *Layer2 = CreateSolidLayer(File, Memory, 499, 503, V4(0.0, 1.0, 0.4, 1.0)); - Layer2->x.CurrentValue.f = 1280/2; - Layer2->y.CurrentValue.f = 720/2; + Layer_CreateFromSource(File, State, Memory, &File->Source[2]); + project_layer *Layer2 = File->Layer[1]; + Layer2->x.CurrentValue.f = 1920/2; + Layer2->y.CurrentValue.f = 1080/2; Layer2->StartFrame = 0; Layer2->EndFrame = File->EndFrame; Keyframe_Insert(&Layer2->rotation, Memory, 2, 0); Keyframe_Insert(&Layer2->rotation, Memory, 50, 360); Layer2->rotation.IsToggled = true; Layer2->scale.IsToggled = true; - project_layer *Layer3 = CreateSolidLayer(File, Memory, 157, 163, V4(1.0, 0.3, 0.2, 1.0)); - Layer3->x.CurrentValue.f = 1280/4; - Layer3->y.CurrentValue.f = 720/4; + Layer_CreateFromSource(File, State, Memory, &File->Source[3]); + project_layer *Layer3 = File->Layer[2]; + Layer3->x.CurrentValue.f = 1920/4; + Layer3->y.CurrentValue.f = 1080/4; Layer3->opacity.CurrentValue.f = 0.5f; Layer3->StartFrame = 0; Layer3->EndFrame = File->EndFrame; @@ -526,7 +410,6 @@ CreateDemoScene(project_data *File, memory *Memory) Keyframe_Insert(&Layer3->x, Memory, 60, Layer3->x.CurrentValue.f+(1280/3)); Layer3->x.IsToggled = true; Layer3->y.IsToggled = true; -#endif } #if 0 @@ -15,10 +15,6 @@ union debugval { int32 i; }; -enum PerfID { - perf_renderframe -}; - // things that get cleared every frame with the UI struct debug_temp { @@ -41,15 +37,6 @@ struct project_debug static project_debug Debug; - -#if DEBUG -#define Debug_CycleCountStart(ID) Debug.CycleCount[ID] = __rdtsc(); -#define Debug_CycleCountEnd(ID) Debug.EndCycleCount[ID] += __rdtsc() - Debug.CycleCount[ID]; Debug.ExecutionAmount[ID]++; -#else -#define Debug_CycleCountStart(ID) -#define Debug_CycleCountEnd(ID) -#endif - static void DebugWatchVar(char *Name, void *Address, valtype Type) { uint32 i = Debug.Temp.WatchedProperties; @@ -64,6 +51,17 @@ DebugWatchVar(char *Name, void *Address, valtype Type) { Debug.Temp.WatchedProperties++; } +static void +DebugPrintMemoryUsage(memory Memory) +{ + for (int i = 0; i < 8; i++) { + memory_table Table = Memory.Slot[i]; + printf("%s: %li bytes, %li kb\n", Table.Name, Table.CurrentPosition, Table.CurrentPosition / 1024); + } +} + + + #else #define Assert(Expression) @@ -82,12 +80,13 @@ struct project_debug { }; -#define DEBUG_CycleCountStart(ID) -#define DEBUG_CycleCountEnd(ID) - static void DebugWatchVar(char *Name, void *Address, valtype Type) { } + +static void +DebugPrintMemoryUsage(memory Memory) { +} #endif #ifdef PERF @@ -99,7 +98,6 @@ struct perf_stats uint64 PixelCountChecked; }; -static perf_stats Perf; static uint64 Test; #endif diff --git a/effects.cpp b/effects.cpp index 61b7729..9de8008 100644 --- a/effects.cpp +++ b/effects.cpp @@ -1,190 +1,16 @@ -static void -DrawColor(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]) -{ -#if 0 - v4 FloatColor = Property[0].CurrentValue.col; - blend_mode BlendMode = Property[1].CurrentValue.blendmode; - - __m256 ZeroReal = _mm256_set1_ps(0); - __m256 ZeroPointFive = _mm256_set1_ps(0.5); - __m256 One = _mm256_set1_ps(1); - __m256 Two = _mm256_set1_ps(2); - - __m256 Fraction255 = _mm256_set1_ps(1/255.0f); - __m256 Real255 = _mm256_set1_ps(255); - - __m256i FF = _mm256_set1_epi32(0xFF); - - __m256 Alpha = _mm256_set1_ps(FloatColor.a); - __m256 AlphaInv = _mm256_set1_ps(1.0f - FloatColor.a); - - __m256 R_Col = _mm256_set1_ps(FloatColor.E[0]); - __m256 R_Colx2 = _mm256_mul_ps(R_Col, Two); - __m256 R_ColInv = _mm256_set1_ps(1.0f - FloatColor.E[0]); - - __m256 G_Col = _mm256_set1_ps(FloatColor.E[1]); - __m256 G_Colx2 = _mm256_mul_ps(G_Col, Two); - __m256 G_ColInv = _mm256_set1_ps(1.0f - FloatColor.E[1]); - - __m256 B_Col = _mm256_set1_ps(FloatColor.E[2]); - __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 < Source->Info.Height; Y += 2) - { - for (int16 X = 0; X < Source->Info.Width; X += 4) - { - uint32 XLookup = (X >> 2)*16 + (X % 4); - uint32 YLookup = (Y >> 2)*(Source->Info.Width*4) + (Y % 4)*4; - uint32 PixelToSeek = XLookup + YLookup; - uint8 *Pixel = (uint8 *)BitmapInfo->BitmapBuffer + PixelToSeek*Source->Info.BytesPerPixel; - __m256i DestPixel = _mm256_loadu_si256((const __m256i *)Pixel); - - // normalized values - __m256 R_Dest = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256( DestPixel, FF)), Fraction255); - __m256 G_Dest = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srli_epi32(DestPixel, 8), FF)), Fraction255); - __m256 B_Dest = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srli_epi32(DestPixel, 16), FF)), Fraction255); - __m256i A_Out = _mm256_and_si256(_mm256_srli_epi32(DestPixel, 24), FF); - - __m256 R_Blend = _mm256_setzero_ps(); - __m256 G_Blend = _mm256_setzero_ps(); - __m256 B_Blend = _mm256_setzero_ps(); - switch (BlendMode) - { - case blend_normal: - { - } break; - case blend_multiply: - { - R_Blend = _mm256_mul_ps(R_Dest, R_Col); - G_Blend = _mm256_mul_ps(G_Dest, G_Col); - B_Blend = _mm256_mul_ps(B_Dest, B_Col); - } break; - case blend_colorburn: - { - R_Blend = _mm256_sub_ps(One, _mm256_div_ps(_mm256_sub_ps(One, R_Dest), R_Col)); - G_Blend = _mm256_sub_ps(One, _mm256_div_ps(_mm256_sub_ps(One, G_Dest), G_Col)); - B_Blend = _mm256_sub_ps(One, _mm256_div_ps(_mm256_sub_ps(One, B_Dest), B_Col)); - } break; - case blend_linearburn: - { - R_Blend = _mm256_sub_ps(_mm256_add_ps(R_Dest, R_Col), One); - G_Blend = _mm256_sub_ps(_mm256_add_ps(G_Dest, G_Col), One); - B_Blend = _mm256_sub_ps(_mm256_add_ps(B_Dest, B_Col), One); - } break; - case blend_add: - { - R_Blend = _mm256_add_ps(R_Dest, R_Col); - G_Blend = _mm256_add_ps(G_Dest, G_Col); - B_Blend = _mm256_add_ps(B_Dest, B_Col); - } break; - case blend_screen: - { - R_Blend = _mm256_sub_ps(One, _mm256_mul_ps(_mm256_sub_ps(One, R_Dest), R_ColInv)); - G_Blend = _mm256_sub_ps(One, _mm256_mul_ps(_mm256_sub_ps(One, G_Dest), G_ColInv)); - B_Blend = _mm256_sub_ps(One, _mm256_mul_ps(_mm256_sub_ps(One, B_Dest), B_ColInv)); - } break; - case blend_overlay: - { - __m256 R_Mask = _mm256_cmp_ps(R_Dest, ZeroPointFive, 1); - __m256 G_Mask = _mm256_cmp_ps(G_Dest, ZeroPointFive, 1); - __m256 B_Mask = _mm256_cmp_ps(B_Dest, ZeroPointFive, 1); - __m256 R_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(R_Dest, R_Col)); - __m256 G_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(G_Dest, G_Col)); - __m256 B_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(B_Dest, B_Col)); - __m256 R_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, R_Dest), R_ColInv))); - __m256 G_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, G_Dest), G_ColInv))); - __m256 B_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, B_Dest), B_ColInv))); - R_Blend = _mm256_blendv_ps(R_Upper, R_Lower, R_Mask); - G_Blend = _mm256_blendv_ps(G_Upper, G_Lower, G_Mask); - B_Blend = _mm256_blendv_ps(B_Upper, B_Lower, B_Mask); - } break; - case blend_softlight: - { - // using Pegtop's equation - R_Blend = _mm256_add_ps(_mm256_mul_ps(_mm256_sub_ps(One, R_Colx2), _mm256_mul_ps(R_Dest, R_Dest)), _mm256_mul_ps(R_Colx2, R_Dest)); - G_Blend = _mm256_add_ps(_mm256_mul_ps(_mm256_sub_ps(One, G_Colx2), _mm256_mul_ps(G_Dest, G_Dest)), _mm256_mul_ps(G_Colx2, G_Dest)); - B_Blend = _mm256_add_ps(_mm256_mul_ps(_mm256_sub_ps(One, B_Colx2), _mm256_mul_ps(B_Dest, B_Dest)), _mm256_mul_ps(B_Colx2, B_Dest)); - } break; - case blend_hardlight: - { - __m256 R_Mask = _mm256_cmp_ps(R_Dest, ZeroPointFive, 13); - __m256 G_Mask = _mm256_cmp_ps(G_Dest, ZeroPointFive, 13); - __m256 B_Mask = _mm256_cmp_ps(B_Dest, ZeroPointFive, 13); - __m256 R_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(R_Dest, R_Col)); - __m256 G_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(G_Dest, G_Col)); - __m256 B_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(B_Dest, B_Col)); - __m256 R_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, R_Dest), R_ColInv))); - __m256 G_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, G_Dest), G_ColInv))); - __m256 B_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, B_Dest), B_ColInv))); - R_Blend = _mm256_blendv_ps(R_Upper, R_Lower, R_Mask); - G_Blend = _mm256_blendv_ps(G_Upper, G_Lower, G_Mask); - B_Blend = _mm256_blendv_ps(B_Upper, B_Lower, B_Mask); - } break; - case blend_subtract: - { - R_Blend = _mm256_sub_ps(R_Dest, R_Col); - G_Blend = _mm256_sub_ps(G_Dest, G_Col); - B_Blend = _mm256_sub_ps(B_Dest, B_Col); - } break; - case blend_divide: - { - R_Blend = _mm256_div_ps(R_Dest, R_Col); - G_Blend = _mm256_div_ps(G_Dest, G_Col); - B_Blend = _mm256_div_ps(B_Dest, B_Col); - } break; - case blend_difference: - { - __m256 R_Lower = _mm256_sub_ps(R_Col, R_Dest); - __m256 G_Lower = _mm256_sub_ps(G_Col, G_Dest); - __m256 B_Lower = _mm256_sub_ps(B_Col, B_Dest); - __m256 R_Upper = _mm256_sub_ps(R_Dest, R_Col); - __m256 G_Upper = _mm256_sub_ps(G_Dest, G_Col); - __m256 B_Upper = _mm256_sub_ps(B_Dest, B_Col); - __m256 R_Mask = _mm256_cmp_ps(R_Lower, ZeroReal, 14); - __m256 G_Mask = _mm256_cmp_ps(G_Lower, ZeroReal, 14); - __m256 B_Mask = _mm256_cmp_ps(B_Lower, ZeroReal, 14); - R_Blend = _mm256_blendv_ps(R_Upper, R_Lower, R_Mask); - G_Blend = _mm256_blendv_ps(G_Upper, G_Lower, G_Mask); - B_Blend = _mm256_blendv_ps(B_Upper, B_Lower, B_Mask); - } break; - } - - R_Blend = _mm256_add_ps(_mm256_mul_ps(R_Dest, AlphaInv), - _mm256_mul_ps(R_Blend, Alpha)); - G_Blend = _mm256_add_ps(_mm256_mul_ps(G_Dest, AlphaInv), - _mm256_mul_ps(G_Blend, Alpha)); - B_Blend = _mm256_add_ps(_mm256_mul_ps(B_Dest, AlphaInv), - _mm256_mul_ps(B_Blend, Alpha)); - - R_Blend = _mm256_max_ps(_mm256_min_ps(One, R_Blend), ZeroReal); - G_Blend = _mm256_max_ps(_mm256_min_ps(One, G_Blend), ZeroReal); - B_Blend = _mm256_max_ps(_mm256_min_ps(One, B_Blend), ZeroReal); - - __m256i R_Out = _mm256_cvttps_epi32(_mm256_mul_ps(R_Blend, Real255)); - __m256i G_Out = _mm256_cvttps_epi32(_mm256_mul_ps(G_Blend, Real255)); - __m256i B_Out = _mm256_cvttps_epi32(_mm256_mul_ps(B_Blend, Real255)); - - __m256i OutputPixel = _mm256_or_si256( - _mm256_or_si256(R_Out, _mm256_slli_epi32(G_Out, 8)), - _mm256_or_si256(_mm256_slli_epi32(B_Out, 16), _mm256_slli_epi32(A_Out, 24))); - - _mm256_storeu_si256((__m256i *)Pixel, OutputPixel); - } - } -#endif -} +#include "effects.h" +#include "effects_software.cpp" static void -DrawGradient(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]) +Effect_DrawColor(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]) { - v4 StartColor = Property[0].CurrentValue.col; - v4 EndColor = Property[1].CurrentValue.col; + Effect_DrawColor_Software(Source, BitmapInfo, Memory, Property); } static void -Levels(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]) +Effect_Levels(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]) { +#if 0 real32 All_Start = Property[0].CurrentValue.f; real32 All_Mid = Property[1].CurrentValue.f; real32 All_End = Property[2].CurrentValue.f; @@ -225,11 +51,13 @@ Levels(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_c uint8 *Data = (uint8 *)BitmapInfo->BitmapBuffer; glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, &Data[0]); glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif } static void -GaussianBlur(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]) +Effect_GaussianBlur(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]) { +#if 0 real32 Radius = Property[0].CurrentValue.f; gl_effect_layer *Test = &BitmapInfo->Test; @@ -251,7 +79,7 @@ GaussianBlur(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, prop uint8 *Data = (uint8 *)BitmapInfo->BitmapBuffer; glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, &Data[0]); - TestGL_UpdateTexture(&BitmapInfo->Test, Data, Width, Height, 0); + GL_UpdateTexture(&BitmapInfo->Test, Data, Width, Height, 0); // glBindRenderbuffer(GL_RENDERBUFFER, Test->RBO); /* glUseProgram(TGL.ShaderProgram); @@ -263,46 +91,9 @@ GaussianBlur(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, prop glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, &Data[0]); glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif } -#if WINDOWS -static effect_header EffectList[3]; -#else -static effect_header EffectList[] { - { - "Solid Color", - &DrawColor, 2, standard, { - {"Color", {.col = V4(0.0f, 0.0f, 0.0f, 0.0f)}, type_color, NORMALIZED_COL_MIN, NORMALIZED_COL_MAX}, - {"Blend mode", {.blendmode = blend_normal}, type_blendmode}, - } - }, - { - "Linear Gradient", - &DrawGradient, 3, standard, { - {"Start Color", {.col = V4(0.0f, 1.0f, 0.0f, 0.0f)}, type_color, NORMALIZED_COL_MIN, NORMALIZED_COL_MAX}, - {"End Color", {.col = V4(1.0f, 0.0f, 0.0f, 1.0f)}, type_color, NORMALIZED_COL_MIN, NORMALIZED_COL_MAX}, - {"Opacity", {1.0f}, type_real, NORMALIZED_REAL_MIN, NORMALIZED_REAL_MAX} - } - }, - { - "Levels", - &Levels, 6, levels, { - {"Start point", {0.0f}, type_real}, - {"Mid point", {1.0f}, type_real}, - {"End point", {1.0f}, type_real}, - {"Start Col", {.col = V4(0.0f)}, type_color}, - {"Mid Col", {.col = V4(1.0f)}, type_color}, - {"End Col", {.col = V4(1.0f)}, type_color}, - } - }, - { - "Gaussian Blur", - &GaussianBlur, 1, standard, { - {"Radius", {0.0f}, type_real, 0.0f, 500.0f}, - } - } -}; -#endif #if 0 { "Solid Color", diff --git a/effects.h b/effects.h new file mode 100644 index 0000000..58787c2 --- /dev/null +++ b/effects.h @@ -0,0 +1,76 @@ +enum effect_display_type +{ + standard, + levels +}; + +struct effect_supported_renderers +{ + bool32 renderer_effect_gpu; +#if ARM + bool32 renderer_effect_neon; +#else + bool32 renderer_effect_avx; + bool32 renderer_effect_sse; +#endif + bool32 renderer_effect_scalar; +}; + +struct effect_header +{ + char *Name; + void (*func)(source *, layer_bitmap_info *, memory *, property_channel []); + uint16 NumberOfProperties; + effect_display_type DisplayType; + // effect_supported_renderers SupportedRenderers; + property_header PropertyHeader[MAX_PROPERTIES_PER_EFFECT]; +}; + +struct effect { + char *Name; + void (*func)(source *, layer_bitmap_info *, memory *, property_channel []); + uint16 NumberOfProperties; + effect_display_type DisplayType; + + struct gl_effect { + uint32 ShaderProgram; + }; + + gl_effect GL_Effect; + property_channel Property[MAX_PROPERTIES_PER_EFFECT]; + bool32 UIIsCollapsed = 0; + bool32 IsActive = 1; +}; + + +#if WINDOWS +static effect_header EffectList[3]; +#else +static effect_header EffectList[] { + { + "Solid Color", + &Effect_DrawColor, 2, standard, { + {"Color", {.col = V4(0.0f, 0.0f, 0.0f, 1.0f)}, type_color, NORMALIZED_COL_MIN, NORMALIZED_COL_MAX}, + {"Blend mode", {.blendmode = blend_normal}, type_blendmode}, + } + }, + { + "Levels", + &Effect_Levels, 6, levels, { + {"Start point", {0.0f}, type_real}, + {"Mid point", {1.0f}, type_real}, + {"End point", {1.0f}, type_real}, + {"Start Col", {.col = V4(0.0f)}, type_color}, + {"Mid Col", {.col = V4(1.0f)}, type_color}, + {"End Col", {.col = V4(1.0f)}, type_color}, + } + }, + { + "Gaussian Blur", + &Effect_GaussianBlur, 1, standard, { + {"Radius", {0.0f}, type_real, 0.0f, 500.0f}, + } + } +}; +#endif + diff --git a/effects_software.cpp b/effects_software.cpp new file mode 100644 index 0000000..5b9e4d9 --- /dev/null +++ b/effects_software.cpp @@ -0,0 +1,174 @@ +static void +Effect_DrawColor_Software(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]) +{ + v4 FloatColor = Property[0].CurrentValue.col; + blend_mode BlendMode = Property[1].CurrentValue.blendmode; + + __m256 ZeroReal = _mm256_set1_ps(0); + __m256 ZeroPointFive = _mm256_set1_ps(0.5); + __m256 One = _mm256_set1_ps(1); + __m256 Two = _mm256_set1_ps(2); + + __m256 Fraction255 = _mm256_set1_ps(1/255.0f); + __m256 Real255 = _mm256_set1_ps(255); + + __m256i FF = _mm256_set1_epi32(0xFF); + + __m256 Alpha = _mm256_set1_ps(FloatColor.a); + __m256 AlphaInv = _mm256_set1_ps(1.0f - FloatColor.a); + + __m256 R_Col = _mm256_set1_ps(FloatColor.E[0]); + __m256 R_Colx2 = _mm256_mul_ps(R_Col, Two); + __m256 R_ColInv = _mm256_set1_ps(1.0f - FloatColor.E[0]); + + __m256 G_Col = _mm256_set1_ps(FloatColor.E[1]); + __m256 G_Colx2 = _mm256_mul_ps(G_Col, Two); + __m256 G_ColInv = _mm256_set1_ps(1.0f - FloatColor.E[1]); + + __m256 B_Col = _mm256_set1_ps(FloatColor.E[2]); + __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 < Source->Info.Height; Y += 2) + { + for (int16 X = 0; X < Source->Info.Width; X += 4) + { + uint32 XLookup = (X >> 2)*16 + (X % 4); + uint32 YLookup = (Y >> 2)*(Source->Info.Width*4) + (Y % 4)*4; + uint32 PixelToSeek = XLookup + YLookup; + uint8 *Pixel = (uint8 *)BitmapInfo->BitmapBuffer + PixelToSeek*Source->Info.BytesPerPixel; + __m256i DestPixel = _mm256_loadu_si256((const __m256i *)Pixel); + + // normalized values + __m256 R_Dest = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256( DestPixel, FF)), Fraction255); + __m256 G_Dest = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srli_epi32(DestPixel, 8), FF)), Fraction255); + __m256 B_Dest = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srli_epi32(DestPixel, 16), FF)), Fraction255); + __m256i A_Out = _mm256_and_si256(_mm256_srli_epi32(DestPixel, 24), FF); + + __m256 R_Blend = R_Col; + __m256 G_Blend = G_Col; + __m256 B_Blend = B_Col; + switch (BlendMode) + { + case blend_normal: + { + } break; + case blend_multiply: + { + R_Blend = _mm256_mul_ps(R_Dest, R_Col); + G_Blend = _mm256_mul_ps(G_Dest, G_Col); + B_Blend = _mm256_mul_ps(B_Dest, B_Col); + } break; + case blend_colorburn: + { + R_Blend = _mm256_sub_ps(One, _mm256_div_ps(_mm256_sub_ps(One, R_Dest), R_Col)); + G_Blend = _mm256_sub_ps(One, _mm256_div_ps(_mm256_sub_ps(One, G_Dest), G_Col)); + B_Blend = _mm256_sub_ps(One, _mm256_div_ps(_mm256_sub_ps(One, B_Dest), B_Col)); + } break; + case blend_linearburn: + { + R_Blend = _mm256_sub_ps(_mm256_add_ps(R_Dest, R_Col), One); + G_Blend = _mm256_sub_ps(_mm256_add_ps(G_Dest, G_Col), One); + B_Blend = _mm256_sub_ps(_mm256_add_ps(B_Dest, B_Col), One); + } break; + case blend_add: + { + R_Blend = _mm256_add_ps(R_Dest, R_Col); + G_Blend = _mm256_add_ps(G_Dest, G_Col); + B_Blend = _mm256_add_ps(B_Dest, B_Col); + } break; + case blend_screen: + { + R_Blend = _mm256_sub_ps(One, _mm256_mul_ps(_mm256_sub_ps(One, R_Dest), R_ColInv)); + G_Blend = _mm256_sub_ps(One, _mm256_mul_ps(_mm256_sub_ps(One, G_Dest), G_ColInv)); + B_Blend = _mm256_sub_ps(One, _mm256_mul_ps(_mm256_sub_ps(One, B_Dest), B_ColInv)); + } break; + case blend_overlay: + { + __m256 R_Mask = _mm256_cmp_ps(R_Dest, ZeroPointFive, 1); + __m256 G_Mask = _mm256_cmp_ps(G_Dest, ZeroPointFive, 1); + __m256 B_Mask = _mm256_cmp_ps(B_Dest, ZeroPointFive, 1); + __m256 R_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(R_Dest, R_Col)); + __m256 G_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(G_Dest, G_Col)); + __m256 B_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(B_Dest, B_Col)); + __m256 R_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, R_Dest), R_ColInv))); + __m256 G_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, G_Dest), G_ColInv))); + __m256 B_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, B_Dest), B_ColInv))); + R_Blend = _mm256_blendv_ps(R_Upper, R_Lower, R_Mask); + G_Blend = _mm256_blendv_ps(G_Upper, G_Lower, G_Mask); + B_Blend = _mm256_blendv_ps(B_Upper, B_Lower, B_Mask); + } break; + case blend_softlight: + { + // using Pegtop's equation + R_Blend = _mm256_add_ps(_mm256_mul_ps(_mm256_sub_ps(One, R_Colx2), _mm256_mul_ps(R_Dest, R_Dest)), _mm256_mul_ps(R_Colx2, R_Dest)); + G_Blend = _mm256_add_ps(_mm256_mul_ps(_mm256_sub_ps(One, G_Colx2), _mm256_mul_ps(G_Dest, G_Dest)), _mm256_mul_ps(G_Colx2, G_Dest)); + B_Blend = _mm256_add_ps(_mm256_mul_ps(_mm256_sub_ps(One, B_Colx2), _mm256_mul_ps(B_Dest, B_Dest)), _mm256_mul_ps(B_Colx2, B_Dest)); + } break; + case blend_hardlight: + { + __m256 R_Mask = _mm256_cmp_ps(R_Dest, ZeroPointFive, 13); + __m256 G_Mask = _mm256_cmp_ps(G_Dest, ZeroPointFive, 13); + __m256 B_Mask = _mm256_cmp_ps(B_Dest, ZeroPointFive, 13); + __m256 R_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(R_Dest, R_Col)); + __m256 G_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(G_Dest, G_Col)); + __m256 B_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(B_Dest, B_Col)); + __m256 R_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, R_Dest), R_ColInv))); + __m256 G_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, G_Dest), G_ColInv))); + __m256 B_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, B_Dest), B_ColInv))); + R_Blend = _mm256_blendv_ps(R_Upper, R_Lower, R_Mask); + G_Blend = _mm256_blendv_ps(G_Upper, G_Lower, G_Mask); + B_Blend = _mm256_blendv_ps(B_Upper, B_Lower, B_Mask); + } break; + case blend_subtract: + { + R_Blend = _mm256_sub_ps(R_Dest, R_Col); + G_Blend = _mm256_sub_ps(G_Dest, G_Col); + B_Blend = _mm256_sub_ps(B_Dest, B_Col); + } break; + case blend_divide: + { + R_Blend = _mm256_div_ps(R_Dest, R_Col); + G_Blend = _mm256_div_ps(G_Dest, G_Col); + B_Blend = _mm256_div_ps(B_Dest, B_Col); + } break; + case blend_difference: + { + __m256 R_Lower = _mm256_sub_ps(R_Col, R_Dest); + __m256 G_Lower = _mm256_sub_ps(G_Col, G_Dest); + __m256 B_Lower = _mm256_sub_ps(B_Col, B_Dest); + __m256 R_Upper = _mm256_sub_ps(R_Dest, R_Col); + __m256 G_Upper = _mm256_sub_ps(G_Dest, G_Col); + __m256 B_Upper = _mm256_sub_ps(B_Dest, B_Col); + __m256 R_Mask = _mm256_cmp_ps(R_Lower, ZeroReal, 14); + __m256 G_Mask = _mm256_cmp_ps(G_Lower, ZeroReal, 14); + __m256 B_Mask = _mm256_cmp_ps(B_Lower, ZeroReal, 14); + R_Blend = _mm256_blendv_ps(R_Upper, R_Lower, R_Mask); + G_Blend = _mm256_blendv_ps(G_Upper, G_Lower, G_Mask); + B_Blend = _mm256_blendv_ps(B_Upper, B_Lower, B_Mask); + } break; + } + + R_Blend = _mm256_add_ps(_mm256_mul_ps(R_Dest, AlphaInv), + _mm256_mul_ps(R_Blend, Alpha)); + G_Blend = _mm256_add_ps(_mm256_mul_ps(G_Dest, AlphaInv), + _mm256_mul_ps(G_Blend, Alpha)); + B_Blend = _mm256_add_ps(_mm256_mul_ps(B_Dest, AlphaInv), + _mm256_mul_ps(B_Blend, Alpha)); + + R_Blend = _mm256_max_ps(_mm256_min_ps(One, R_Blend), ZeroReal); + G_Blend = _mm256_max_ps(_mm256_min_ps(One, G_Blend), ZeroReal); + B_Blend = _mm256_max_ps(_mm256_min_ps(One, B_Blend), ZeroReal); + + __m256i R_Out = _mm256_cvttps_epi32(_mm256_mul_ps(R_Blend, Real255)); + __m256i G_Out = _mm256_cvttps_epi32(_mm256_mul_ps(G_Blend, Real255)); + __m256i B_Out = _mm256_cvttps_epi32(_mm256_mul_ps(B_Blend, Real255)); + + __m256i OutputPixel = _mm256_or_si256( + _mm256_or_si256(R_Out, _mm256_slli_epi32(G_Out, 8)), + _mm256_or_si256(_mm256_slli_epi32(B_Out, 16), _mm256_slli_epi32(A_Out, 24))); + + _mm256_storeu_si256((__m256i *)Pixel, OutputPixel); + } + } +} diff --git a/ffmpeg_backend.cpp b/ffmpeg_backend.cpp index 03d3214..6e16e76 100644 --- a/ffmpeg_backend.cpp +++ b/ffmpeg_backend.cpp @@ -45,6 +45,9 @@ bool32 AV_TryFrame(av_info *AV, int32 *err) while (*err >= 0) { *err = avcodec_receive_frame(AV->VideoCodecContext, AV->VideoFrame); if (*err == AVERROR_EOF) { + av_seek_frame(AV->FileFormatContext, -1, 0, AVSEEK_FLAG_BACKWARD); + *err = 0; + break; } else if (*err == AVERROR(EAGAIN)) { *err = 0; break; @@ -209,6 +212,11 @@ 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. + if (AV->VideoStream->duration == 1) { + Source->Info.AvgPTSPerFrame = 1; + return; + } + // TODO(fox): Handle footage under five seconds. int16 TestAmount = 5; @@ -234,6 +242,53 @@ void AV_GetPTSAverage(source *Source, av_info *AV, int32 *err) av_seek_frame(AV->FileFormatContext, -1, 0, AVSEEK_FLAG_BACKWARD); } +cached_bitmap * AV_LoadStill(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory) +{ + av_info *AV = (av_info *)BitmapInfo->AVInfo; + int32 *CurrentlyRenderedFrame = &BitmapInfo->CurrentFrame; + + int32 err = 0; + + *CurrentlyRenderedFrame = 0; + + av_seek_frame(AV->FileFormatContext, -1, 0, AVSEEK_FLAG_FRAME); + + while (err >= 0) { + if (AV_TryFrame(AV, &err)) + { + uint16 Width = Source->Info.Width; + uint16 Height = Source->Info.Height; + uint16 BytesPerPixel = Source->Info.BytesPerPixel; + int32 Pitch = Width*BytesPerPixel; + + cached_bitmap *Bitmap = Memory_RollingBitmap(Memory, Source, 0); + 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. + 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(!AV->RGBContext) { + printf("Libav error: SwsContext creation failed."); + } + + sws_scale(AV->RGBContext, AV->VideoFrame->data, AV->VideoFrame->linesize, 0, AV->VideoFrame->height, + dst_data, out_linesize); + + av_frame_unref(AV->VideoFrame); + + Assert(BitmapInfo->BitmapBuffer); + return Bitmap; + } + av_frame_unref(AV->VideoFrame); + } + return 0; +} cached_bitmap * AV_LoadVideoFrame(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, int32 TimelineFrame) { diff --git a/functions.h b/functions.h index 3d4184d..9b63832 100644 --- a/functions.h +++ b/functions.h @@ -6,11 +6,11 @@ static project_layer * Layer_Init(project_data *File, memory *Memory); // Initia static void Bitmap_CalcPackedDimensions(uint16 Width, uint16 Height, uint16 *WidthP, uint16 *HeightP); // Returns the dimensions a packed bitmap should be in memory. +static void Bitmap_ConvertPacking(void *Buffer, void *DestBuffer, uint16 Width, uint16 Height, uint16 BytesPerPixel, uint16 Which); +static void Bitmap_CalcHistogram(void *Data, void *Input, uint16 BytesPerPixel, uint64 TotalBytes); 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 uint64 Bitmap_CalcUnpackedBytes(uint16 Width, uint16 Height, uint16 BytesPerPixel); -static void Bitmap_ConvertPacking(void *Buffer, void *DestBuffer, uint16 Width, uint16 Height, uint16 BytesPerPixel, uint16 Which); -static void Bitmap_CalcHistogram(void *Data, void *Input, uint16 BytesPerPixel, uint64 TotalBytes); static bool32 Source_Generate(project_data *File, memory *Memory, void *Path); // Fills out source info if the source is a supported file. @@ -22,16 +22,18 @@ static cached_bitmap * AV_LoadVideoFrame(source *Source, memory *Memory, int32 T static cached_bitmap * Cache_CheckBitmap(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, int32 TimelineFrame); -static void TestGL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height, bool32 Multisample); -static gl_effect TestGL_MaskInitVerts(mask Mask); -static void TestGL_InitVerts(); -static gl_vertex_shader TestGL_MaskUploadVerts(project_layer *Layer, mask *Mask); +// OpenGL + +static void GL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height, bool32 Multisample); +static void GL_RasterizeShape(project_layer *Layer, mask *Mask); static v2 Line_RatioToPoint(v2 a, v2 b, float ratio); static v2 ImGui_ScreenPointToCompUV(ImVec2 ViewportMin, ImVec2 CompPos, ImVec2 CompZoom, ImVec2 MousePos); void Bezier_CubicCalcPoints(v2 p1, v2 p2, v2 p3, v2 p4, void *Data, uint32 *Increment); +static void Mask_TriangulateAndRasterize(memory *Memory, project_layer *Layer, mask *Mask); + static void History_Undo(memory *Memory); static void History_Redo(memory *Memory); @@ -57,3 +59,9 @@ static void Fallback_RenderLayer(transform_info TransformInfo, comp_buffer *Buff static void PushRect(rectangle RenderRegion); static bool32 CheckQueue(render_queue RenderInfo, uint16 Index); +// Effects + +static void Effect_DrawColor(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]); +static void Effect_Levels(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]); +static void Effect_GaussianBlur(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]); + diff --git a/gl_calls.cpp b/gl_calls.cpp index fcb7fd9..8a7b905 100644 --- a/gl_calls.cpp +++ b/gl_calls.cpp @@ -1,3 +1,6 @@ +#include "gl_calls.h" + + const char *DefaultVertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "layout (location = 1) in vec2 aTexCoord;\n" @@ -75,7 +78,7 @@ const char *fragmentShaderSource = "#version 330 core\n" #endif -static void TestGL_InitDefaultShader() { +static void GL_InitDefaultShader() { DefaultVertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(DefaultVertexShader, 1, &DefaultVertexShaderSource, NULL); @@ -121,7 +124,7 @@ static void TestGL_InitDefaultShader() { glDeleteShader(DefaultFragmentShader); } -static void TestGL_InitDefaultVerts() { +static void GL_InitDefaultVerts() { unsigned int GLIndices[] = { 0, 1, 3, @@ -139,7 +142,7 @@ static void TestGL_InitDefaultVerts() { // Our vertices need to be stored in this buffer. glBindBuffer(GL_ARRAY_BUFFER, DefaultVerts.VertexBufferObject); - glBufferData(GL_ARRAY_BUFFER, sizeof(DefaultVertices), DefaultVertices, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(GL_DefaultVertices), GL_DefaultVertices, GL_STATIC_DRAW); // position attribute glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); @@ -150,7 +153,7 @@ static void TestGL_InitDefaultVerts() { } void -TestGL_InitTexture(gl_effect_layer *Test) +GL_InitTexture(gl_effect_layer *Test) { glGenFramebuffers(1, &Test->FramebufferObject); glGenTextures(1, &Test->Texture); @@ -160,12 +163,12 @@ TestGL_InitTexture(gl_effect_layer *Test) } void -TestGL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height, bool32 Multisample) +GL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height, bool32 Multisample) { glViewport(0, 0, Width, Height); if (!Test->Initialized) { - TestGL_InitTexture(Test); + GL_InitTexture(Test); } GLenum Target = GL_TEXTURE_2D; @@ -213,3 +216,99 @@ TestGL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Hei glBindFramebuffer(GL_FRAMEBUFFER, 0); } + +static void +GL_RasterizeShape(project_layer *Layer, mask *Mask) +{ + gl_effect_layer Test = Layer->BitmapInfo.TestM; + gl_effect_layer Test2 = Layer->BitmapInfo.Test; + gl_vertex_shader VertData; + + uint32 Width = Layer->Source->Info.Width; + uint32 Height = Layer->Source->Info.Height; + + uint8 *Data = (uint8 *)Layer->BitmapInfo.BitmapBuffer; + glBindFramebuffer(GL_FRAMEBUFFER, Test.FramebufferObject); + + glEnable(GL_STENCIL_TEST); + // glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + glStencilFunc(GL_ALWAYS, 0, 0xFF); // always write + glStencilMask(0xff); // allow writing; ANDs any writes to the stencil buffer with this + + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + glUseProgram(DefaultShaderProgram); + + int VertexMode = glGetUniformLocation(DefaultShaderProgram, "VertexMode"); + int FragmentMode = glGetUniformLocation(DefaultShaderProgram, "FragmentMode"); + glUniform1i(VertexMode, 1); + glUniform1i(FragmentMode, 0); + + // secondary VBO + glGenVertexArrays(1, &VertData.VertexArrayObject); + glGenBuffers(1, &VertData.VertexBufferObject); + glBindVertexArray(VertData.VertexArrayObject); + glBindBuffer(GL_ARRAY_BUFFER, VertData.VertexBufferObject); + glBufferData(GL_ARRAY_BUFFER, Mask->NumberOfVerts*3*sizeof(real32), Mask->TriangulatedPointCache, GL_STREAM_DRAW); + + // position attribute + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); + glEnableVertexAttribArray(0); + + int Scale = glGetUniformLocation(DefaultShaderProgram, "CompDimensions"); + glUniform3f(Scale, Width, Height, 0); + + + glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP); + glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP); + + glDisable(GL_CULL_FACE); + + glDrawArrays(GL_TRIANGLE_FAN, 0, Mask->NumberOfVerts); + + // glEnable(GL_CULL_FACE); + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + glBindVertexArray(0); + + // glBindRenderbuffer(GL_RENDERBUFFER, Test.Color_Renderbuffer); + + VertexMode = glGetUniformLocation(DefaultShaderProgram, "VertexMode"); + FragmentMode = glGetUniformLocation(DefaultShaderProgram, "FragmentMode"); + glUniform1i(VertexMode, 0); + glUniform1i(FragmentMode, 1); + + + // // Switch to main buffer + glBindBuffer(GL_ARRAY_BUFFER, DefaultVerts.VertexBufferObject); + glBufferData(GL_ARRAY_BUFFER, sizeof(GL_DefaultVertices), GL_DefaultVertices, GL_STATIC_DRAW); + // position attribute + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); + glEnableVertexAttribArray(0); + // texture coordinate (note the last parameter's offset) + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); + glEnableVertexAttribArray(1); + + glStencilFunc(GL_NOTEQUAL, 0, 0xFF); + glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); + glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_INT, 0); + + glDisable(GL_STENCIL_TEST); + glStencilMask(0xFF); + glStencilFunc(GL_ALWAYS, 0, 0xFF); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, Test.FramebufferObject); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, Test2.FramebufferObject); + glBlitFramebuffer(0, 0, Width, Height, 0, 0, Width, Height, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_FRAMEBUFFER, Test2.FramebufferObject); + + glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, &Data[0]); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} @@ -1,2 +1,24 @@ -extern void InitGLShaders(); +struct default_gl_vertex_object { + uint32 VertexArrayObject; + uint32 VertexBufferObject; + uint32 ElementBufferObject; +}; + +struct gl_vertex_shader { + uint32 VertexArrayObject; + uint32 VertexBufferObject; +}; + +static default_gl_vertex_object DefaultVerts; +static gl_vertex_shader GL_DefaultVertexObjects; +static uint32 DefaultVertexShader; +static uint32 DefaultShaderProgram; +static uint32 MaskShaderProgram; + +float GL_DefaultVertices[] = { + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, +}; @@ -34,6 +34,7 @@ #include "defines.h" #include "my_math.h" +#include "structs.h" #include "main.h" #include "debug.h" #include "functions.h" @@ -73,7 +74,7 @@ SDL_sem *Semaphore; static void MainFunction(main_sdl *Main, memory *Memory, project_state *State, project_data *File, - cache_pool *Cache, comp_buffer *CompBuffer) + comp_buffer *CompBuffer) { Bitmap_Clear(CompBuffer->PackedBuffer, CompBuffer->Width, CompBuffer->Height, CompBuffer->BytesPerPixel); Bitmap_Clear(CompBuffer->UnpackedBuffer, CompBuffer->Width, CompBuffer->Height, CompBuffer->BytesPerPixel); @@ -99,106 +100,6 @@ MainFunction(main_sdl *Main, memory *Memory, QueueCurrentFrame(File, CompBuffer, State); } -#if 0 -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) -{ - ClearBuffer(CompBuffer); - - if (Cache->Frame[File->CurrentFrame].Cached) { - FetchCache(&Cache->Frame[File->CurrentFrame], CompBuffer); - } else { - for (int i = 0; i < File->NumberOfLayers; i++) { - if (File->Layer[i]->Raster.OriginalBuffer) { - for (int p = 0; p < File->Layer[i]->NumberOfEffects; p++) { - for (int o = 0; o < File->Layer[i]->Effect[p].NumberOfProperties; o++) { - CalculateKeyframesLinearly(File->CurrentFrame, &File->Layer[i]->Effect[p].Property[o]); - } - } - for (int r = 0; r < AmountOf(File->Layer[i]->Property); r++) { - CalculateKeyframesLinearly(File->CurrentFrame, &File->Layer[i]->Property[r]); - } - if (File->Layer[i]->Raster.ToUpdate) { - UpdateEffects(File->Layer[i], Memory); - File->Layer[i]->Raster.ToUpdate = true; - } - } - } - - if (State->DebugDisableCache) { - RenderCurrentFrame(File, CompBuffer, State); - } else { - if (Cache->Interact == Clear) { - Cache->Intermediate[0].Cached = 0; - Cache->Intermediate[1].Cached = 0; - Cache->Intermediate[2].Cached = 0; - Cache->Interact = Inactive; - } - if (Cache->Interact == Active) { - if (!Cache->Intermediate[0].Address) { - Cache->Intermediate[0].Address = (uint64 *)Memory->Address + Memory->CurrentPosition; - Memory->CurrentPosition += File->Width * File->Height * 4; - Cache->Intermediate[1].Address = (uint64 *)Memory->Address + Memory->CurrentPosition; - Memory->CurrentPosition += File->Width * File->Height * 4; - Cache->Intermediate[2].Address = (uint64 *)Memory->Address + Memory->CurrentPosition; - Memory->CurrentPosition += File->Width * File->Height * 4; - } - pixel_buffer TempBuffer = *CompBuffer; - if (!Cache->Intermediate[0].Cached) { - TempBuffer.OriginalBuffer = Cache->Intermediate[0].Address; - ClearBuffer(&TempBuffer); - for (int i = 0; i < Cache->InteractIndex; i++) { - // RenderLayer(File->LayerPTR[i], &TempBuffer, State); - // RenderCurrentFrame(File->LayerPTR[Cache->InteractIndex], &TempBuffer, State); - } - Cache->Intermediate[0].Cached = 1; - } - TempBuffer.OriginalBuffer = Cache->Intermediate[1].Address; - ClearBuffer(&TempBuffer); - // RenderLayer(File->LayerPTR[Cache->InteractIndex], &TempBuffer, State); - // RenderCurrentFrame(File->LayerPTR[Cache->InteractIndex], &TempBuffer, State); - if (!Cache->Intermediate[2].Cached) { - TempBuffer.OriginalBuffer = Cache->Intermediate[2].Address; - ClearBuffer(&TempBuffer); - for (int i = Cache->InteractIndex + 1; i < File->NumberOfLayers; i++) { - // RenderLayer(File->LayerPTR[i], &TempBuffer, State); - // RenderCurrentFrame(File->LayerPTR[Cache->InteractIndex], &TempBuffer, State); - } - Cache->Intermediate[2].Cached = 1; - } - InteractToComp(CompBuffer, Cache); - } else { - for (int i = 0; i < File->NumberOfLayers; i++) { - } - } - if (!Cache->Interact) { - if (!Cache->Frame[File->CurrentFrame].Address) { - Cache->Frame[File->CurrentFrame].Address = (uint64 *)Memory->Address + Memory->CurrentPosition; - Memory->CurrentPosition += File->Width * File->Height * 4; - } - CacheFrame(&Cache->Frame[File->CurrentFrame], CompBuffer); - Cache->Frame[File->CurrentFrame].Cached = true; - } else { - Cache->Frame[File->CurrentFrame].Cached = false; - } - } - } -} -#endif - - -static void -DebugPrintMemoryUsage(memory Memory) -{ - for (int i = 0; i < 8; i++) { - memory_table Table = Memory.Slot[i]; - printf("%s: %li bytes, %li kb\n", Table.Name, Table.CurrentPosition, Table.CurrentPosition / 1024); - } -} - - int main(int argc, char *argv[]) { global_memory GlobalMemory = {}; @@ -249,8 +150,8 @@ int main(int argc, char *argv[]) { #endif project_data File = {}; - File.Width = 1280; - File.Height = 720; + File.Width = 1920; + File.Height = 1080; File.NumberOfFrames = 65; File.FPS = 30; File.CurrentFrame = 1; @@ -279,9 +180,6 @@ int main(int argc, char *argv[]) { 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; - ui UI = {}; // shm_unlink("/testl"); @@ -385,8 +283,8 @@ int main(int argc, char *argv[]) { return -1; } - TestGL_InitDefaultShader(); - TestGL_InitDefaultVerts(); + GL_InitDefaultShader(); + GL_InitDefaultVerts(); SDL_GL_MakeCurrent(window, gl_context); @@ -487,7 +385,7 @@ int main(int argc, char *argv[]) { // UI never lags. if (State.UpdateFrame && !IsRendering) { - MainFunction(0, &Memory, &State, &File, &Cache, &CompBuffer); + MainFunction(0, &Memory, &State, &File, &CompBuffer); State.UpdateFrame = 0; } @@ -8,24 +8,6 @@ enum instruction_mode { #endif }; -struct cache { - void *Address; - bool32 Cached; -}; - -enum whattocallthis { - Inactive, - Active, - Clear -}; - -struct cache_pool { - cache Frame[2048]; - cache Intermediate[3]; - whattocallthis Interact; - int16 InteractIndex; -}; - enum memory_table_list { // F = file attributes @@ -111,12 +93,6 @@ struct memory { struct property_channel; struct project_layer; -enum display_type -{ - standard, - levels -}; - enum keyframe_type { linear, @@ -166,45 +142,6 @@ enum blend_mode }; -struct gl_effect { - uint32 ShaderProgram; -}; - -struct gl_vertex_shader { - uint32 VertexArrayObject; - uint32 VertexBufferObject; -}; - -struct default_gl_vertex_object { - uint32 VertexArrayObject; - uint32 VertexBufferObject; - uint32 ElementBufferObject; -}; - -static default_gl_vertex_object DefaultVerts; -static uint32 DefaultVertexShader; -static uint32 DefaultShaderProgram; -static uint32 MaskShaderProgram; - -float DefaultVertices[] = { - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -}; - - -struct gl_effect_layer { - bool32 Initialized; - GLuint Texture; - GLuint FramebufferObject; - uint32 Color_Renderbuffer; - uint32 Stencil_Renderbuffer; -}; - -static gl_vertex_shader GL_Vertices; - - union val { real32 f; v4 col; @@ -285,12 +222,20 @@ struct source { // Bitmaps from files are loaded into these temporary cache blocks. +struct gl_effect_layer { + bool32 Initialized; + GLuint Texture; + GLuint FramebufferObject; + uint32 Color_Renderbuffer; + uint32 Stencil_Renderbuffer; +}; struct layer_bitmap_info { // Image and video void *BitmapBuffer; // Each layer has a persistent bitmap that the source data gets packed into. int32 FrameOffset; // The "true" position of the layer, separate from StartFrame. Starts at zero and only gets incremented when the layer is moved. bool32 ToUpdate = 1; + gl_effect_layer Test; gl_effect_layer TestM; @@ -314,26 +259,6 @@ 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; - gl_effect GL_Effect; - property_channel Property[MAX_PROPERTIES_PER_EFFECT]; - bool32 UIIsCollapsed = 0; - bool32 IsActive = 1; -}; - struct transform_info { real32 XAxisPX; real32 XAxisPY; diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp index ea2e314..ac0739e 100644 --- a/my_imgui_widgets.cpp +++ b/my_imgui_widgets.cpp @@ -111,7 +111,6 @@ static void ImGui_DebugUndoTree(project_data *File, memory *Memory) { ImGui::SetNextWindowSize(ImVec2(200, 800)); - ImGui::SetNextWindowPos(ImVec2(2498, 10)); ImGui::Begin("undotree"); for (int i = 0; i < Memory->Action.NumberOfEntries; i++) { action_entry Entry = Memory->Action.Entry[i]; @@ -802,7 +801,7 @@ ImGui_File(project_data *File, project_state *State, memory *Memory, ui *UI, ImG ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); if (State->DemoButton) { if (ImGui::Button("Generate demo scene")) { - // CreateDemoScene(File, Memory); + CreateDemoScene(File, State, Memory); State->UpdateKeyframes = true; State->UpdateFrame = true; State->DemoButton = false; @@ -885,6 +884,7 @@ ImGui_EffectsPanel(project_data *File, project_state *State, memory *Memory, ui if (State->filter.PassFilter(EffectList[i].Name)) { if (EffectSel == p && State->MostRecentlySelectedLayer != -1) { AddEffect(File->Layer[State->MostRecentlySelectedLayer], Memory, i); + State->UpdateFrame = true; } p++; } @@ -902,6 +902,7 @@ ImGui_EffectsPanel(project_data *File, project_state *State, memory *Memory, ui if (ImGui::IsItemClicked()) { if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && State->MostRecentlySelectedLayer != -1) { AddEffect(File->Layer[State->MostRecentlySelectedLayer], Memory, i); + State->UpdateFrame = true; } } p++; @@ -999,9 +1000,9 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, UI->DraggingKeyframeThreshold += io.MouseDelta.x; if (abs(UI->DraggingKeyframeThreshold) >= UI->TimelineZoom) { int16 Increment = UI->DraggingKeyframeThreshold/UI->TimelineZoom; - if (File->CurrentFrame <= 0 && Increment < File->StartFrame) + if (File->CurrentFrame + Increment <= 0) File->CurrentFrame = 0; - else if (File->CurrentFrame >= File->EndFrame && Increment > File->EndFrame) { + else if (File->CurrentFrame + Increment >= File->EndFrame) { File->CurrentFrame = File->EndFrame; } else { File->CurrentFrame += Increment; diff --git a/prenderer.cpp b/prenderer.cpp index ccacbe8..1fa3e71 100644 --- a/prenderer.cpp +++ b/prenderer.cpp @@ -151,6 +151,7 @@ QueueCurrentFrame(project_data *File, comp_buffer *CompBuffer, project_state *St { IsRendering = true; render_queue RenderInfo = {File, State, CompBuffer}; + #if PERF Test = __rdtsc(); #endif diff --git a/structs.h b/structs.h new file mode 100644 index 0000000..fbb97ed --- /dev/null +++ b/structs.h @@ -0,0 +1,5 @@ +struct effect; + +struct action_entry; +struct action_entries; + |