#include #include #if WINDOWS #include #else #include #include #endif #if ARM #include #include #else #include #endif #include "imgui/imgui.h" #include "imgui/backends/imgui_impl_sdl.h" #include "imgui/backends/imgui_impl_opengl3.h" #if WINDOWS #include #else #include #endif #if defined(IMGUI_IMPL_OPENGL_ES2) #include #else #include #endif #define STB_IMAGE_IMPLEMENTATION #define STBI_FAILURE_USERMSG #include "lib/stb_image.h" #include "defines.h" #include "my_math.h" #include "structs.h" #include "main.h" #include "debug.h" #include "functions.h" // #include "sharebuffer.h" SDL_atomic_t CurrentEntry; SDL_atomic_t QueuedEntries; SDL_atomic_t CompletedEntries; static bool32 IsRendering = false; static instruction_mode InstructionMode = instruction_mode_scalar; static uint32 RandomGlobalIncrement = 0; static bool32 test = 1; render_entry Entries[256]; SDL_Thread *thread[8]; SDL_sem *Semaphore; #include "memory.cpp" #include "effects.cpp" #include "keyframes.cpp" #include "layer.cpp" #include "strings.cpp" #include "bezier.cpp" #if THREADED #include "threading.cpp" #endif #include "prenderer.cpp" #include "ffmpeg_backend.cpp" #include "bitmap_calls.cpp" #include "createcalls.cpp" #include "my_imgui_widgets.cpp" #include "gl_calls.cpp" #include "undo.cpp" static void MainFunction(main_sdl *Main, memory *Memory, project_state *State, project_data *File, comp_buffer *CompBuffer) { Bitmap_Clear(CompBuffer->PackedBuffer, CompBuffer->Width, CompBuffer->Height, CompBuffer->BytesPerPixel); Bitmap_Clear(CompBuffer->UnpackedBuffer, CompBuffer->Width, CompBuffer->Height, CompBuffer->BytesPerPixel); for (int i = 0; i < File->NumberOfLayers; i++) { project_layer *Layer = File->Layer[i]; if (Layer->StartFrame <= File->CurrentFrame && Layer->EndFrame >= File->CurrentFrame) { if (State->UpdateKeyframes) { for (int p = 0; p < Layer->NumberOfEffects; p++) { for (int o = 0; o < Layer->Effect[p]->NumberOfProperties; o++) { CalculateKeyframesLinearly(File->CurrentFrame, &Layer->Effect[p]->Property[o]); } } for (int r = 0; r < AmountOf(Layer->Property); r++) { CalculateKeyframesLinearly(File->CurrentFrame, &Layer->Property[r]); } } Layer_UpdateBitmap(File, Layer, Memory, File->CurrentFrame); } } State->UpdateKeyframes = false; QueueCurrentFrame(File, CompBuffer, State); } int main(int argc, char *argv[]) { global_memory GlobalMemory = {}; GlobalMemory.Size = ((uint64)4 * 1024 * 1024 * 1024); GlobalMemory.CurrentPosition = 0; #if WINDOWS GlobalMemory.Address = VirtualAlloc(0, GlobalMemory.Size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); #else GlobalMemory.Address = mmap(0, GlobalMemory.Size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); #endif memory Memory = {}; InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, P_AVInfo, "Image/video headers"); InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, P_VectorPoints, "Vector Points"); InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, P_UndoBuffer, "Undo buffer"); InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, P_MiscCache, "Misc cache"); 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)200 * 1024 * 1024, B_LayerBitmaps, "Layer buffer"); InitMemoryTable(&GlobalMemory, &Memory, (uint64)200 * 1024 * 1024, B_LoadedBitmaps, "Loaded bitmap buffer"); Memory.Scratch = AllocateMemory(&Memory, (uint64)64*1024*1024, B_LayerBitmaps); project_state State = {}; #if ARM InstructionMode = instruction_mode_neon; #else if (SDL_HasSSE2()) { InstructionMode = instruction_mode_sse; } if (SDL_HasAVX2()) { InstructionMode = instruction_mode_avx; } #endif project_data File = {}; File.Width = 1920; File.Height = 1080; File.NumberOfFrames = 65; File.FPS = 30; File.CurrentFrame = 1; File.StartFrame = 0; File.EndFrame = 65; LoadTestFootage(&File, &State, &Memory); #if DEBUG // GDB and LLDB say this plain struct that's literally under 30 bytes is // incomplete in the layers unless I do this... layer_bitmap_info BitmapInfo; BitmapInfo.ToUpdate = 0; BitmapInfo.FrameOffset = 2; av_info BS = {}; BS.PreviousPTS = 0; effect as = {}; #endif uint16 BytesPerPixel = 4; comp_buffer CompBuffer = {}; CompBuffer.Width = File.Width; CompBuffer.Height = File.Height; CompBuffer.BytesPerPixel = BytesPerPixel; CompBuffer.PackedBuffer = Layer_AllocateBitmap(&Memory, CompBuffer.Width, CompBuffer.Height, CompBuffer.BytesPerPixel); CompBuffer.UnpackedBuffer = Layer_AllocateBitmap(&Memory, CompBuffer.Width, CompBuffer.Height, CompBuffer.BytesPerPixel); ui UI = {}; // shm_unlink("/testl"); // int fd = shm_open("/testl", O_CREAT | O_EXCL | O_RDWR, // S_IRUSR | S_IWUSR); // if (fd == -1) // errExit("shm_open"); // if (ftruncate(fd, SHAREDMEMORY_SIZE) == -1) // Assert(0); // void *asda = mmap(NULL, SHAREDMEMORY_SIZE, // PROT_READ | PROT_WRITE, // MAP_SHARED, fd, 0); // SharedMemoryInfo *shmp = (SharedMemoryInfo *)asda; // if (shmp == MAP_FAILED) // Assert(0); // if (sem_init(&shmp->sem1, 1, 0) == -1) // Assert(0); // if (sem_init(&shmp->sem2, 1, 0) == -1) // Assert(0); SDL_Init(SDL_INIT_VIDEO); Semaphore = SDL_CreateSemaphore(0); render_queue RenderInfo = {}; RenderInfo.File = &File; RenderInfo.State = &State; RenderInfo.CompBuffer = &CompBuffer; #if THREADED thread_info ThreadInfo[7]; for (int i = 0; i < 7; i++) { char str[256]; ThreadInfo[i].Index = i; ThreadInfo[i].RenderInfo = &RenderInfo; thread[i] = SDL_CreateThread(TestThread, str, &ThreadInfo[i]); } #endif sdl_input Input; sdl_input OldInput; // Decide GL+GLSL versions #if defined(IMGUI_IMPL_OPENGL_ES2) // GL ES 2.0 + GLSL 100 const char* glsl_version = "#version 100"; SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #elif defined(__APPLE__) // GL 3.2 Core + GLSL 150 const char* glsl_version = "#version 150"; SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); #else // GL 3.0 + GLSL 130 const char* glsl_version = "#version 130"; SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #endif SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); #if DEBUG #if ARM uint32 ScreenSize[2] = {(uint32)(2560/1.2), (uint32)(1600/1.2)}; #else real32 ScreenSize[2] = {3840/1.2, 2160/1.2}; #endif #else real32 ScreenSize[2]; SDL_DisplayMode current; int windowtest = SDL_GetCurrentDisplayMode(0, ¤t); if (windowtest == 0) { ScreenSize[0] = current.w; ScreenSize[1] = current.h; } else { ScreenSize[0] = 1920; ScreenSize[1] = 1080; } #endif SDL_Window* window = SDL_CreateWindow("Event Tester", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, ScreenSize[0], ScreenSize[1], window_flags); SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GL_MakeCurrent(window, gl_context); SDL_GL_SetSwapInterval(1); // Enable vsync if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { printf("Failed to initialize GLAD"); return -1; } GL_InitDefaultShader(); GL_InitDefaultVerts(); SDL_GL_MakeCurrent(window, gl_context); SDL_Event Event; IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_DockingEnable; (void)io; // NOTE(fox): Instead of constructing the position of the windows on // startup with Docking API calls (which is experimental and incomplete) // I'm loading the window positions from this convenient tool. ImGui by // default saves window position to an external .ini file, which can be // loaded from disk or memory. io.IniFilename = NULL; ImGui::LoadIniSettingsFromMemory(ImGuiPrefs); ImGui::StyleColorsDark(); ImGui_ImplSDL2_InitForOpenGL(window, gl_context); ImGui_ImplOpenGL3_Init(glsl_version); GLuint textureID; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // This is required on WebGL for non power-of-two textures glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Same #if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); #endif glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, CompBuffer.Width, CompBuffer.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, CompBuffer.PackedBuffer); ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); while (State.IsRunning) { SDL_Event event; while (SDL_PollEvent(&event)) { ImGui_ImplSDL2_ProcessEvent(&event); if (event.type == SDL_DROPFILE) { printf("%s", event.drop.file); // AddSource(File, Memory, event.drop.file); } if (event.type == SDL_QUIT) State.IsRunning = false; if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)) State.IsRunning = false; } ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplSDL2_NewFrame(); ImGui::NewFrame(); if (!io.WantCaptureKeyboard) ImGui_ProcessInputs(&File, &State, &CompBuffer, &Memory, &UI, io); ImGui::DockSpaceOverViewport(); ImGui_Viewport(File, &State, &UI, &Memory, CompBuffer, io, textureID); ImGui_File(&File, &State, &Memory, &UI, io); ImGui_EffectsPanel(&File, &State, &Memory, &UI, io); ImGui_PropertiesPanel(&File, &State, &UI, &Memory); ImGui_Timeline(&File, &State, &Memory, &UI, io); #if DEBUG ImGui_DebugUndoTree(&File, &Memory); if (Debug.ToggleWindow) { // ImGui::ShowDemoWindow(); ImGui_DebugMemoryViewer(&File, &Memory); } #endif if (UI.TemporaryUpdateOverride) { UI.TemporaryUpdateOverride = 0; State.UpdateFrame = 1; } if (UI.Initializing) UI.Initializing--; // if (File.CurrentFrame != shmp->shared_framenumber) { // File.CurrentFrame = shmp->shared_framenumber; // } // Right now IsRendering does nothing. I have it here if we want to // completely detatch the rendering updater onto its own thread so the // UI never lags. if (State.UpdateFrame && !IsRendering) { MainFunction(0, &Memory, &State, &File, &CompBuffer); State.UpdateFrame = 0; } #if THREADED uint32 C = SDL_AtomicGet(&CompletedEntries); if (IsRendering) { while (C != 16) { C = SDL_AtomicGet(&CompletedEntries); CheckQueue(RenderInfo, 8); } C = SDL_AtomicGet(&CompletedEntries); if (C == 16) { FinishRenderAndUpload(&State, &CompBuffer, textureID); } } #else if (IsRendering) { FinishRenderAndUpload(&State, &CompBuffer, textureID); } #endif ImGui::Render(); glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w); glClear(GL_COLOR_BUFFER_BIT); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); SDL_GL_SwapWindow(window); } for (int i = 0; i < 7; i++) { SDL_DetachThread(thread[i]); } // shm_unlink("/testl"); ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplSDL2_Shutdown(); ImGui::DestroyContext(); SDL_Quit(); return 0; }